From 9b0884286f16259decd9d9879dc7fb4a0b49b283 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 24 Aug 2017 17:25:37 -0500 Subject: [PATCH 0001/1056] Update deps to pull in additional logging changes. This update adds additional callsite logging options via btclog and fixes an error with the rotator package that caused it to stop running when creating any log messages larger than 4096 bytes. While here, switch to the new Write method of the Rotator object as this is more efficient than using the Reader interface with a pipe. Changes from @jrick. --- glide.lock | 6 +++--- log.go | 13 ++----------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/glide.lock b/glide.lock index a74b30ac1f..f4480be1c1 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ hash: 976decfaf173d97d2e4572399490637aa12e217312a7d8b28813780a738e1151 -updated: 2017-08-15T20:07:19.2012575-05:00 +updated: 2017-08-24T17:28:45.8117156-05:00 imports: - name: github.com/btcsuite/btclog - version: 96c2a91a67da03552a5e6554fe3ccbfbc7f860be + version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a - name: github.com/btcsuite/btcutil version: 501929d3d046174c3d39f0ea54ece471aa17238c subpackages: @@ -47,7 +47,7 @@ imports: - name: github.com/jessevdk/go-flags version: 1679536dcc895411a9f5848d9a0250be7856448c - name: github.com/jrick/logrotate - version: 4ed05ed86ef17d10ff99cce77481e0fcf6f2c7b0 + version: a93b200c26cbae3bb09dd0dc2c7c7fe1468a034a subpackages: - rotator - name: golang.org/x/crypto diff --git a/log.go b/log.go index 437bfecae6..c9782d2ce7 100644 --- a/log.go +++ b/log.go @@ -7,7 +7,6 @@ package main import ( "fmt" - "io" "os" "path/filepath" @@ -31,7 +30,7 @@ type logWriter struct{} func (logWriter) Write(p []byte) (n int, err error) { os.Stdout.Write(p) - logRotatorPipe.Write(p) + logRotator.Write(p) return len(p), nil } @@ -53,10 +52,6 @@ var ( // application shutdown. logRotator *rotator.Rotator - // logRotatorPipe is the write-end pipe for writing to the log rotator. It - // is written to by the Write method of the logWriter type. - logRotatorPipe *io.PipeWriter - adxrLog = backendLog.Logger("ADXR") amgrLog = backendLog.Logger("AMGR") cmgrLog = backendLog.Logger("CMGR") @@ -117,17 +112,13 @@ func initLogRotator(logFile string) { fmt.Fprintf(os.Stderr, "failed to create log directory: %v\n", err) os.Exit(1) } - pr, pw := io.Pipe() - r, err := rotator.New(pr, logFile, 10*1024, false, 3) + r, err := rotator.New(logFile, 10*1024, false, 3) if err != nil { fmt.Fprintf(os.Stderr, "failed to create file rotator: %v\n", err) os.Exit(1) } - go r.Run() - logRotator = r - logRotatorPipe = pw } // setLogLevel sets the logging level for provided subsystem. Invalid From 3135a40371f846f0f6b7ac8572eaefaa1f4ac121 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 24 Aug 2017 12:59:21 -0700 Subject: [PATCH 0002/1056] MOVEONLY: Move blockmanager and blocklogger to netsync directory. --- blocklogger.go => netsync/blocklogger.go | 0 blockmanager.go => netsync/manager.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename blocklogger.go => netsync/blocklogger.go (100%) rename blockmanager.go => netsync/manager.go (100%) diff --git a/blocklogger.go b/netsync/blocklogger.go similarity index 100% rename from blocklogger.go rename to netsync/blocklogger.go diff --git a/blockmanager.go b/netsync/manager.go similarity index 100% rename from blockmanager.go rename to netsync/manager.go From 1cf7e233e5b5ff9fe185e4ea9549051908a8e3db Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 24 Aug 2017 13:33:51 -0700 Subject: [PATCH 0003/1056] netsync: Initialize netsync package. Create doc.go, interface.go, and README for new package. --- netsync/README.md | 25 +++++++++++ netsync/blocklogger.go | 6 ++- netsync/doc.go | 13 ++++++ netsync/interface.go | 94 ++++++++++++++++++++++++++++++++++++++++++ netsync/manager.go | 26 +----------- 5 files changed, 138 insertions(+), 26 deletions(-) create mode 100644 netsync/README.md create mode 100644 netsync/doc.go create mode 100644 netsync/interface.go diff --git a/netsync/README.md b/netsync/README.md new file mode 100644 index 0000000000..4734d331e4 --- /dev/null +++ b/netsync/README.md @@ -0,0 +1,25 @@ +netsync +======= + +[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/netsync) + +## Overview + +This package implements a concurrency safe block syncing protocol. The provided +implementation of SyncManager communicates with connected peers to perform an +initial block download, keep the chain in sync, and announce new blocks +connected to the chain. Currently the sync manager selects a single sync peer +that it downloads all blocks from until it is up to date with the longest chain +the sync peer is aware of. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/netsync +``` + +## License + +Package netsync is licensed under the [copyfree](http://copyfree.org) ISC License. diff --git a/netsync/blocklogger.go b/netsync/blocklogger.go index 1901a708bc..18480e782a 100644 --- a/netsync/blocklogger.go +++ b/netsync/blocklogger.go @@ -1,4 +1,8 @@ -package main +// Copyright (c) 2015-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package netsync import ( "sync" diff --git a/netsync/doc.go b/netsync/doc.go new file mode 100644 index 0000000000..8fd29aad5a --- /dev/null +++ b/netsync/doc.go @@ -0,0 +1,13 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +The netsync package implements a concurrency safe block syncing protocol. The +provided implementation of SyncManager communicates with connected peers to +perform an initial block download, keep the chain and mempool in sync, and +announce new blocks connected to the chain. Currently the block manager selects +a single sync peer that it downloads all blocks from until it is up to date with +the longest chain the sync peer is aware of. +*/ +package netsync diff --git a/netsync/interface.go b/netsync/interface.go new file mode 100644 index 0000000000..69cd2421cb --- /dev/null +++ b/netsync/interface.go @@ -0,0 +1,94 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package netsync + +import ( + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mempool" + "github.com/btcsuite/btcd/peer" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" +) + +// PeerNotifier exposes methods to notify peers of status changes to +// transactions, blocks, etc. Currently server (in the main package) implements +// this interface. +type PeerNotifier interface { + AnnounceNewTransactions(newTxs []*mempool.TxDesc) + + UpdatePeerHeights(latestBlkHash *chainhash.Hash, latestHeight int32, updateSource *peer.Peer) + + RelayInventory(invVect *wire.InvVect, data interface{}) + + TransactionConfirmed(tx *btcutil.Tx) +} + +// Config is a configuration struct used to initialize a new SyncManager. +type Config struct { + PeerNotifier PeerNotifier + Chain *blockchain.BlockChain + TxMemPool *mempool.TxPool + ChainParams *chaincfg.Params + + DisableCheckpoints bool + MaxPeers int +} + +// SyncManager is the interface used to communicate block related messages with +// peers. The SyncManager is started as by executing Start() in a goroutine. +// Once started, it selects peers to sync from and starts the initial block +// download. Once the chain is in sync, the SyncManager handles incoming block +// and header notifications and relays announcements of new blocks to peers. +type SyncManager interface { + // NewPeer informs the SyncManager of a newly active peer. + NewPeer(p *peer.Peer) + + // QueueTx adds the passed transaction message and peer to the block + // handling queue. + QueueTx(tx *btcutil.Tx, p *peer.Peer, done chan struct{}) + + // QueueBlock adds the passed block message and peer to the block handling + // queue. + QueueBlock(block *btcutil.Block, p *peer.Peer, done chan struct{}) + + // QueueInv adds the passed inv message and peer to the block handling + // queue. + QueueInv(inv *wire.MsgInv, p *peer.Peer) + + // QueueHeaders adds the passed headers message and peer to the block + // handling queue. + QueueHeaders(headers *wire.MsgHeaders, p *peer.Peer) + + // DonePeer informs the SyncManager that a peer has disconnected. + DonePeer(p *peer.Peer) + + // Start begins the core block handler which processes block and inv + // messages. + Start() + + // Stop gracefully shuts down the SyncManager by stopping all asynchronous + // handlers and waiting for them to finish. + Stop() error + + // SyncPeerID returns the ID of the current sync peer, or 0 if there is + // none. + SyncPeerID() int32 + + // ProcessBlock makes use of ProcessBlock on an internal instance of a block + // chain. + ProcessBlock(block *btcutil.Block, flags blockchain.BehaviorFlags) (bool, error) + + // IsCurrent returns whether or not the SyncManager believes it is synced + // with the connected peers. + IsCurrent() bool + + // Pause pauses the SyncManager until the returned channel is closed. + // + // Note that while paused, all peer and block processing is halted. The + // message sender should avoid pausing the SyncManager for long durations. + Pause() chan<- struct{} +} diff --git a/netsync/manager.go b/netsync/manager.go index 93344ad8ab..09a37c3c3f 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -2,7 +2,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package main +package netsync import ( "container/list" @@ -134,30 +134,6 @@ type headerNode struct { hash *chainhash.Hash } -// PeerNotifier exposes methods to notify peers of status changes to -// transactions, blocks, etc. Currently server implements this interface. -type PeerNotifier interface { - AnnounceNewTransactions(newTxs []*mempool.TxDesc) - - UpdatePeerHeights(latestBlkHash *chainhash.Hash, latestHeight int32, updateSource *peerpkg.Peer) - - RelayInventory(invVect *wire.InvVect, data interface{}) - - TransactionConfirmed(tx *btcutil.Tx) -} - -// blockManangerConfig is a configuration struct used to initialize a new -// blockManager. -type blockManagerConfig struct { - PeerNotifier PeerNotifier - Chain *blockchain.BlockChain - TxMemPool *mempool.TxPool - ChainParams *chaincfg.Params - - DisableCheckpoints bool - MaxPeers int -} - // peerSyncState stores additional information that the blockManager tracks // about a peer. type peerSyncState struct { From f2fc24d0fc7bf76eebac50b855e820f760b31d43 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 24 Aug 2017 14:09:28 -0700 Subject: [PATCH 0004/1056] netsync: Use package-local logger. --- log.go | 6 ++- netsync/log.go | 25 ++++++++++++ netsync/manager.go | 98 +++++++++++++++++++++++----------------------- 3 files changed, 78 insertions(+), 51 deletions(-) create mode 100644 netsync/log.go diff --git a/log.go b/log.go index c9782d2ce7..ae413a18cf 100644 --- a/log.go +++ b/log.go @@ -18,6 +18,7 @@ import ( "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/mining/cpuminer" + "github.com/btcsuite/btcd/netsync" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btclog" @@ -56,7 +57,6 @@ var ( amgrLog = backendLog.Logger("AMGR") cmgrLog = backendLog.Logger("CMGR") bcdbLog = backendLog.Logger("BCDB") - bmgrLog = backendLog.Logger("BMGR") btcdLog = backendLog.Logger("BTCD") chanLog = backendLog.Logger("CHAN") discLog = backendLog.Logger("DISC") @@ -66,6 +66,7 @@ var ( rpcsLog = backendLog.Logger("RPCS") scrpLog = backendLog.Logger("SCRP") srvrLog = backendLog.Logger("SRVR") + syncLog = backendLog.Logger("SYNC") txmpLog = backendLog.Logger("TXMP") ) @@ -80,6 +81,7 @@ func init() { cpuminer.UseLogger(minrLog) peer.UseLogger(peerLog) txscript.UseLogger(scrpLog) + netsync.UseLogger(syncLog) mempool.UseLogger(txmpLog) } @@ -89,7 +91,6 @@ var subsystemLoggers = map[string]btclog.Logger{ "AMGR": amgrLog, "CMGR": cmgrLog, "BCDB": bcdbLog, - "BMGR": bmgrLog, "BTCD": btcdLog, "CHAN": chanLog, "DISC": discLog, @@ -99,6 +100,7 @@ var subsystemLoggers = map[string]btclog.Logger{ "RPCS": rpcsLog, "SCRP": scrpLog, "SRVR": srvrLog, + "SYNC": syncLog, "TXMP": txmpLog, } diff --git a/netsync/log.go b/netsync/log.go new file mode 100644 index 0000000000..cf12b2c70d --- /dev/null +++ b/netsync/log.go @@ -0,0 +1,25 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package netsync + +import "github.com/btcsuite/btclog" + +// log is a logger that is initialized with no output filters. This +// means the package will not perform any logging by default until the caller +// requests it. +var log btclog.Logger + +// DisableLog disables all library log output. Logging output is disabled +// by default until either UseLogger or SetLogWriter are called. +func DisableLog() { + log = btclog.Disabled +} + +// UseLogger uses a specified Logger to output package logging info. +// This should be used in preference to SetLogWriter if the caller is also +// using btclog. +func UseLogger(logger btclog.Logger) { + log = logger +} diff --git a/netsync/manager.go b/netsync/manager.go index 09a37c3c3f..cb46ffabac 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -230,7 +230,7 @@ func (b *blockManager) startSync() { // that we fully validate all blockchain data. segwitActive, err := b.chain.IsDeploymentActive(chaincfg.DeploymentSegwit) if err != nil { - bmgrLog.Errorf("Unable to query for segwit soft-fork state: %v", err) + log.Errorf("Unable to query for segwit soft-fork state: %v", err) return } @@ -242,7 +242,7 @@ func (b *blockManager) startSync() { } if segwitActive && !peer.IsWitnessEnabled() { - bmgrLog.Debugf("peer %v not witness enabled, skipping", peer) + log.Debugf("peer %v not witness enabled, skipping", peer) continue } @@ -271,12 +271,12 @@ func (b *blockManager) startSync() { locator, err := b.chain.LatestBlockLocator() if err != nil { - bmgrLog.Errorf("Failed to get block locator for the "+ + log.Errorf("Failed to get block locator for the "+ "latest block: %v", err) return } - bmgrLog.Infof("Syncing to block height %d from peer %v", + log.Infof("Syncing to block height %d from peer %v", bestPeer.LastBlock(), bestPeer.Addr()) // When the current height is less than a known checkpoint we @@ -302,7 +302,7 @@ func (b *blockManager) startSync() { bestPeer.PushGetHeadersMsg(locator, b.nextCheckpoint.Hash) b.headersFirstMode = true - bmgrLog.Infof("Downloading headers for blocks %d to "+ + log.Infof("Downloading headers for blocks %d to "+ "%d from peer %s", best.Height+1, b.nextCheckpoint.Height, bestPeer.Addr()) } else { @@ -310,7 +310,7 @@ func (b *blockManager) startSync() { } b.syncPeer = bestPeer } else { - bmgrLog.Warnf("No sync peer candidates available") + log.Warnf("No sync peer candidates available") } } @@ -337,7 +337,7 @@ func (b *blockManager) isSyncCandidate(peer *peerpkg.Peer) bool { // activated, then the peer must also be upgraded. segwitActive, err := b.chain.IsDeploymentActive(chaincfg.DeploymentSegwit) if err != nil { - bmgrLog.Errorf("Unable to query for segwit "+ + log.Errorf("Unable to query for segwit "+ "soft-fork state: %v", err) } nodeServices := peer.Services() @@ -360,7 +360,7 @@ func (b *blockManager) handleNewPeerMsg(peer *peerpkg.Peer) { return } - bmgrLog.Infof("New valid peer %s (%s)", peer, peer.UserAgent()) + log.Infof("New valid peer %s (%s)", peer, peer.UserAgent()) // Initialize the peer state isSyncCandidate := b.isSyncCandidate(peer) @@ -383,14 +383,14 @@ func (b *blockManager) handleNewPeerMsg(peer *peerpkg.Peer) { func (b *blockManager) handleDonePeerMsg(peer *peerpkg.Peer) { state, exists := b.peerStates[peer] if !exists { - bmgrLog.Warnf("Received done peer message for unknown peer %s", peer) + log.Warnf("Received done peer message for unknown peer %s", peer) return } // Remove the peer from the list of candidate peers. delete(b.peerStates, peer) - bmgrLog.Infof("Lost peer %s", peer) + log.Infof("Lost peer %s", peer) // Remove requested transactions from the global map so that they will // be fetched from elsewhere next time we get an inv. @@ -424,7 +424,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { peer := tmsg.peer state, exists := b.peerStates[peer] if !exists { - bmgrLog.Warnf("Received tx message from unknown peer %s", peer) + log.Warnf("Received tx message from unknown peer %s", peer) return } @@ -442,7 +442,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // send a reject message here because if the transaction was already // rejected, the transaction was unsolicited. if _, exists = b.rejectedTxns[*txHash]; exists { - bmgrLog.Debugf("Ignoring unsolicited previously rejected "+ + log.Debugf("Ignoring unsolicited previously rejected "+ "transaction %v from %s", txHash, peer) return } @@ -470,10 +470,10 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // so log it as such. Otherwise, something really did go wrong, // so log it as an actual error. if _, ok := err.(mempool.RuleError); ok { - bmgrLog.Debugf("Rejected transaction %v from %s: %v", + log.Debugf("Rejected transaction %v from %s: %v", txHash, peer, err) } else { - bmgrLog.Errorf("Failed to process transaction %v: %v", + log.Errorf("Failed to process transaction %v: %v", txHash, err) } @@ -513,7 +513,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { peer := bmsg.peer state, exists := b.peerStates[peer] if !exists { - bmgrLog.Warnf("Received block message from unknown peer %s", peer) + log.Warnf("Received block message from unknown peer %s", peer) return } @@ -526,7 +526,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // mode in this case so the chain code is actually fed the // duplicate blocks. if b.chainParams != &chaincfg.RegressionNetParams { - bmgrLog.Warnf("Got unrequested block %v from %s -- "+ + log.Warnf("Got unrequested block %v from %s -- "+ "disconnecting", blockHash, peer.Addr()) peer.Disconnect() return @@ -572,10 +572,10 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // it as such. Otherwise, something really did go wrong, so log // it as an actual error. if _, ok := err.(blockchain.RuleError); ok { - bmgrLog.Infof("Rejected block %v from %s: %v", blockHash, + log.Infof("Rejected block %v from %s: %v", blockHash, peer, err) } else { - bmgrLog.Errorf("Failed to process block %v: %v", + log.Errorf("Failed to process block %v: %v", blockHash, err) } if dbErr, ok := err.(database.Error); ok && dbErr.ErrorCode == @@ -614,10 +614,10 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { coinbaseTx := bmsg.block.Transactions()[0] cbHeight, err := blockchain.ExtractCoinbaseHeight(coinbaseTx) if err != nil { - bmgrLog.Warnf("Unable to extract height from "+ + log.Warnf("Unable to extract height from "+ "coinbase tx: %v", err) } else { - bmgrLog.Debugf("Extracted height of %v from "+ + log.Debugf("Extracted height of %v from "+ "orphan block", cbHeight) heightUpdate = cbHeight blkHashUpdate = blockHash @@ -627,7 +627,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { orphanRoot := b.chain.GetOrphanRoot(blockHash) locator, err := b.chain.LatestBlockLocator() if err != nil { - bmgrLog.Warnf("Failed to get block locator for the "+ + log.Warnf("Failed to get block locator for the "+ "latest block: %v", err) } else { peer.PushGetBlocksMsg(locator, orphanRoot) @@ -686,11 +686,11 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { locator := blockchain.BlockLocator([]*chainhash.Hash{prevHash}) err := peer.PushGetHeadersMsg(locator, b.nextCheckpoint.Hash) if err != nil { - bmgrLog.Warnf("Failed to send getheaders message to "+ + log.Warnf("Failed to send getheaders message to "+ "peer %s: %v", peer.Addr(), err) return } - bmgrLog.Infof("Downloading headers for blocks %d to %d from "+ + log.Infof("Downloading headers for blocks %d to %d from "+ "peer %s", prevHeight+1, b.nextCheckpoint.Height, b.syncPeer.Addr()) return @@ -701,11 +701,11 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // from the block after this one up to the end of the chain (zero hash). b.headersFirstMode = false b.headerList.Init() - bmgrLog.Infof("Reached the final checkpoint -- switching to normal mode") + log.Infof("Reached the final checkpoint -- switching to normal mode") locator := blockchain.BlockLocator([]*chainhash.Hash{blockHash}) err = peer.PushGetBlocksMsg(locator, &zeroHash) if err != nil { - bmgrLog.Warnf("Failed to send getblocks message to peer %s: %v", + log.Warnf("Failed to send getblocks message to peer %s: %v", peer.Addr(), err) return } @@ -716,7 +716,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { func (b *blockManager) fetchHeaderBlocks() { // Nothing to do if there is no start header. if b.startHeader == nil { - bmgrLog.Warnf("fetchHeaderBlocks called with no start header") + log.Warnf("fetchHeaderBlocks called with no start header") return } @@ -728,14 +728,14 @@ func (b *blockManager) fetchHeaderBlocks() { for e := b.startHeader; e != nil; e = e.Next() { node, ok := e.Value.(*headerNode) if !ok { - bmgrLog.Warn("Header list node type is not a headerNode") + log.Warn("Header list node type is not a headerNode") continue } iv := wire.NewInvVect(wire.InvTypeBlock, node.hash) haveInv, err := b.haveInventory(iv) if err != nil { - bmgrLog.Warnf("Unexpected failure when checking for "+ + log.Warnf("Unexpected failure when checking for "+ "existing inventory during header block "+ "fetch: %v", err) } @@ -771,7 +771,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { peer := hmsg.peer _, exists := b.peerStates[peer] if !exists { - bmgrLog.Warnf("Received headers message from unknown peer %s", peer) + log.Warnf("Received headers message from unknown peer %s", peer) return } @@ -779,7 +779,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { msg := hmsg.headers numHeaders := len(msg.Headers) if !b.headersFirstMode { - bmgrLog.Warnf("Got %d unrequested headers from %s -- "+ + log.Warnf("Got %d unrequested headers from %s -- "+ "disconnecting", numHeaders, peer.Addr()) peer.Disconnect() return @@ -801,7 +801,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // Ensure there is a previous header to compare against. prevNodeEl := b.headerList.Back() if prevNodeEl == nil { - bmgrLog.Warnf("Header list does not contain a previous" + + log.Warnf("Header list does not contain a previous" + "element as expected -- disconnecting peer") peer.Disconnect() return @@ -818,7 +818,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { b.startHeader = e } } else { - bmgrLog.Warnf("Received block header that does not "+ + log.Warnf("Received block header that does not "+ "properly connect to the chain from peer %s "+ "-- disconnecting", peer.Addr()) peer.Disconnect() @@ -829,11 +829,11 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { if node.height == b.nextCheckpoint.Height { if node.hash.IsEqual(b.nextCheckpoint.Hash) { receivedCheckpoint = true - bmgrLog.Infof("Verified downloaded block "+ + log.Infof("Verified downloaded block "+ "header against checkpoint at height "+ "%d/hash %s", node.height, node.hash) } else { - bmgrLog.Warnf("Block header at height %d/hash "+ + log.Warnf("Block header at height %d/hash "+ "%s from peer %s does NOT match "+ "expected checkpoint hash of %s -- "+ "disconnecting", node.height, @@ -854,7 +854,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // the next header links properly, it must be removed before // fetching the blocks. b.headerList.Remove(b.headerList.Front()) - bmgrLog.Infof("Received %v block headers: Fetching blocks", + log.Infof("Received %v block headers: Fetching blocks", b.headerList.Len()) b.progressLogger.SetLastLogTime(time.Now()) b.fetchHeaderBlocks() @@ -867,7 +867,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { locator := blockchain.BlockLocator([]*chainhash.Hash{finalHash}) err := peer.PushGetHeadersMsg(locator, b.nextCheckpoint.Hash) if err != nil { - bmgrLog.Warnf("Failed to send getheaders message to "+ + log.Warnf("Failed to send getheaders message to "+ "peer %s: %v", peer.Addr(), err) return } @@ -916,7 +916,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { peer := imsg.peer state, exists := b.peerStates[peer] if !exists { - bmgrLog.Warnf("Received inv message from unknown peer %s", peer) + log.Warnf("Received inv message from unknown peer %s", peer) return } @@ -982,7 +982,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { // Request the inventory if we don't already have it. haveInv, err := b.haveInventory(iv) if err != nil { - bmgrLog.Warnf("Unexpected failure when checking for "+ + log.Warnf("Unexpected failure when checking for "+ "existing inventory during inv message "+ "processing: %v", err) continue @@ -1027,7 +1027,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { orphanRoot := b.chain.GetOrphanRoot(&iv.Hash) locator, err := b.chain.LatestBlockLocator() if err != nil { - bmgrLog.Errorf("PEER: Failed to get block "+ + log.Errorf("PEER: Failed to get block "+ "locator for the latest block: "+ "%v", err) continue @@ -1190,7 +1190,7 @@ out: <-msg.unpause default: - bmgrLog.Warnf("Invalid message type in block "+ + log.Warnf("Invalid message type in block "+ "handler: %T", msg) } @@ -1200,7 +1200,7 @@ out: } b.wg.Done() - bmgrLog.Trace("Block handler done") + log.Trace("Block handler done") } // handleBlockchainNotification handles notifications from blockchain. It does @@ -1219,7 +1219,7 @@ func (b *blockManager) handleBlockchainNotification(notification *blockchain.Not block, ok := notification.Data.(*btcutil.Block) if !ok { - bmgrLog.Warnf("Chain accepted notification is not a block.") + log.Warnf("Chain accepted notification is not a block.") break } @@ -1231,7 +1231,7 @@ func (b *blockManager) handleBlockchainNotification(notification *blockchain.Not case blockchain.NTBlockConnected: block, ok := notification.Data.(*btcutil.Block) if !ok { - bmgrLog.Warnf("Chain connected notification is not a block.") + log.Warnf("Chain connected notification is not a block.") break } @@ -1255,7 +1255,7 @@ func (b *blockManager) handleBlockchainNotification(notification *blockchain.Not case blockchain.NTBlockDisconnected: block, ok := notification.Data.(*btcutil.Block) if !ok { - bmgrLog.Warnf("Chain disconnected notification is not a block.") + log.Warnf("Chain disconnected notification is not a block.") break } @@ -1349,7 +1349,7 @@ func (b *blockManager) Start() { return } - bmgrLog.Trace("Starting block manager") + log.Trace("Starting block manager") b.wg.Add(1) go b.blockHandler() } @@ -1358,12 +1358,12 @@ func (b *blockManager) Start() { // handlers and waiting for them to finish. func (b *blockManager) Stop() error { if atomic.AddInt32(&b.shutdown, 1) != 1 { - bmgrLog.Warnf("Block manager is already in the process of " + + log.Warnf("Block manager is already in the process of " + "shutting down") return nil } - bmgrLog.Infof("Block manager shutting down") + log.Infof("Block manager shutting down") close(b.quit) b.wg.Wait() return nil @@ -1416,7 +1416,7 @@ func newBlockManager(config *blockManagerConfig) (*blockManager, error) { requestedTxns: make(map[chainhash.Hash]struct{}), requestedBlocks: make(map[chainhash.Hash]struct{}), peerStates: make(map[*peerpkg.Peer]*peerSyncState), - progressLogger: newBlockProgressLogger("Processed", bmgrLog), + progressLogger: newBlockProgressLogger("Processed", log), msgChan: make(chan interface{}, config.MaxPeers*3), headerList: list.New(), quit: make(chan struct{}), @@ -1430,7 +1430,7 @@ func newBlockManager(config *blockManagerConfig) (*blockManager, error) { bm.resetHeaderState(&best.Hash, best.Height) } } else { - bmgrLog.Info("Checkpoints are disabled") + log.Info("Checkpoints are disabled") } bm.chain.Subscribe(bm.handleBlockchainNotification) From 46fd4ec358f7e16fb78d9b37fd70bd833a033a05 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 24 Aug 2017 14:46:59 -0700 Subject: [PATCH 0005/1056] netsync: Change name of blockManager to syncManager. --- btcd.go | 7 + netsync/README.md | 12 +- netsync/doc.go | 12 +- netsync/interface.go | 55 ------ netsync/manager.go | 447 +++++++++++++++++++++---------------------- rpcadapters.go | 13 +- server.go | 58 +++--- 7 files changed, 279 insertions(+), 325 deletions(-) diff --git a/btcd.go b/btcd.go index 7839b62939..8d4b880249 100644 --- a/btcd.go +++ b/btcd.go @@ -20,6 +20,13 @@ import ( "github.com/btcsuite/btcd/limits" ) +const ( + // blockDbNamePrefix is the prefix for the block database name. The + // database type is appended to this value to form the full block + // database name. + blockDbNamePrefix = "blocks" +) + var ( cfg *config ) diff --git a/netsync/README.md b/netsync/README.md index 4734d331e4..d5e141151d 100644 --- a/netsync/README.md +++ b/netsync/README.md @@ -7,12 +7,12 @@ netsync ## Overview -This package implements a concurrency safe block syncing protocol. The provided -implementation of SyncManager communicates with connected peers to perform an -initial block download, keep the chain in sync, and announce new blocks -connected to the chain. Currently the sync manager selects a single sync peer -that it downloads all blocks from until it is up to date with the longest chain -the sync peer is aware of. +This package implements a concurrency safe block syncing protocol. The +SyncManager communicates with connected peers to perform an initial block +download, keep the chain and unconfirmed transaction pool in sync, and announce +new blocks connected to the chain. Currently the sync manager selects a single +sync peer that it downloads all blocks from until it is up to date with the +longest chain the sync peer is aware of. ## Installation and Updating diff --git a/netsync/doc.go b/netsync/doc.go index 8fd29aad5a..7f45286d7b 100644 --- a/netsync/doc.go +++ b/netsync/doc.go @@ -3,11 +3,11 @@ // license that can be found in the LICENSE file. /* -The netsync package implements a concurrency safe block syncing protocol. The -provided implementation of SyncManager communicates with connected peers to -perform an initial block download, keep the chain and mempool in sync, and -announce new blocks connected to the chain. Currently the block manager selects -a single sync peer that it downloads all blocks from until it is up to date with -the longest chain the sync peer is aware of. +Package netsync implements a concurrency safe block syncing protocol. The +SyncManager communicates with connected peers to perform an initial block +download, keep the chain and unconfirmed transaction pool in sync, and announce +new blocks connected to the chain. Currently the sync manager selects a single +sync peer that it downloads all blocks from until it is up to date with the +longest chain the sync peer is aware of. */ package netsync diff --git a/netsync/interface.go b/netsync/interface.go index 69cd2421cb..61a230ac4c 100644 --- a/netsync/interface.go +++ b/netsync/interface.go @@ -37,58 +37,3 @@ type Config struct { DisableCheckpoints bool MaxPeers int } - -// SyncManager is the interface used to communicate block related messages with -// peers. The SyncManager is started as by executing Start() in a goroutine. -// Once started, it selects peers to sync from and starts the initial block -// download. Once the chain is in sync, the SyncManager handles incoming block -// and header notifications and relays announcements of new blocks to peers. -type SyncManager interface { - // NewPeer informs the SyncManager of a newly active peer. - NewPeer(p *peer.Peer) - - // QueueTx adds the passed transaction message and peer to the block - // handling queue. - QueueTx(tx *btcutil.Tx, p *peer.Peer, done chan struct{}) - - // QueueBlock adds the passed block message and peer to the block handling - // queue. - QueueBlock(block *btcutil.Block, p *peer.Peer, done chan struct{}) - - // QueueInv adds the passed inv message and peer to the block handling - // queue. - QueueInv(inv *wire.MsgInv, p *peer.Peer) - - // QueueHeaders adds the passed headers message and peer to the block - // handling queue. - QueueHeaders(headers *wire.MsgHeaders, p *peer.Peer) - - // DonePeer informs the SyncManager that a peer has disconnected. - DonePeer(p *peer.Peer) - - // Start begins the core block handler which processes block and inv - // messages. - Start() - - // Stop gracefully shuts down the SyncManager by stopping all asynchronous - // handlers and waiting for them to finish. - Stop() error - - // SyncPeerID returns the ID of the current sync peer, or 0 if there is - // none. - SyncPeerID() int32 - - // ProcessBlock makes use of ProcessBlock on an internal instance of a block - // chain. - ProcessBlock(block *btcutil.Block, flags blockchain.BehaviorFlags) (bool, error) - - // IsCurrent returns whether or not the SyncManager believes it is synced - // with the connected peers. - IsCurrent() bool - - // Pause pauses the SyncManager until the returned channel is closed. - // - // Note that while paused, all peer and block processing is halted. The - // message sender should avoid pausing the SyncManager for long durations. - Pause() chan<- struct{} -} diff --git a/netsync/manager.go b/netsync/manager.go index cb46ffabac..7f1d3605bd 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -27,11 +27,6 @@ const ( // more. minInFlightBlocks = 10 - // blockDbNamePrefix is the prefix for the block database name. The - // database type is appended to this value to form the full block - // database name. - blockDbNamePrefix = "blocks" - // maxRejectedTxns is the maximum number of rejected transactions // hashes to store in memory. maxRejectedTxns = 1000 @@ -113,14 +108,14 @@ type processBlockMsg struct { } // isCurrentMsg is a message type to be sent across the message channel for -// requesting whether or not the block manager believes it is synced with -// the currently connected peers. +// requesting whether or not the sync manager believes it is synced with the +// currently connected peers. type isCurrentMsg struct { reply chan bool } // pauseMsg is a message type to be sent across the message channel for -// pausing the block manager. This effectively provides the caller with +// pausing the sync manager. This effectively provides the caller with // exclusive access over the manager until a receive is performed on the // unpause channel. type pauseMsg struct { @@ -134,7 +129,7 @@ type headerNode struct { hash *chainhash.Hash } -// peerSyncState stores additional information that the blockManager tracks +// peerSyncState stores additional information that the SyncManager tracks // about a peer. type peerSyncState struct { syncCandidate bool @@ -143,9 +138,12 @@ type peerSyncState struct { requestedBlocks map[chainhash.Hash]struct{} } -// blockManager provides a concurrency safe block manager for handling all -// incoming blocks. -type blockManager struct { +// SyncManager is used to communicate block related messages with peers. The +// SyncManager is started as by executing Start() in a goroutine. Once started, +// it selects peers to sync from and starts the initial block download. Once the +// chain is in sync, the SyncManager handles incoming block and header +// notifications and relays announcements of new blocks to peers. +type SyncManager struct { peerNotifier PeerNotifier started int32 shutdown int32 @@ -173,17 +171,17 @@ type blockManager struct { // resetHeaderState sets the headers-first mode state to values appropriate for // syncing from a new peer. -func (b *blockManager) resetHeaderState(newestHash *chainhash.Hash, newestHeight int32) { - b.headersFirstMode = false - b.headerList.Init() - b.startHeader = nil +func (sm *SyncManager) resetHeaderState(newestHash *chainhash.Hash, newestHeight int32) { + sm.headersFirstMode = false + sm.headerList.Init() + sm.startHeader = nil // When there is a next checkpoint, add an entry for the latest known // block into the header pool. This allows the next downloaded header // to prove it links to the chain properly. - if b.nextCheckpoint != nil { + if sm.nextCheckpoint != nil { node := headerNode{height: newestHeight, hash: newestHash} - b.headerList.PushBack(&node) + sm.headerList.PushBack(&node) } } @@ -191,8 +189,8 @@ func (b *blockManager) resetHeaderState(newestHash *chainhash.Hash, newestHeight // It returns nil when there is not one either because the height is already // later than the final checkpoint or some other reason such as disabled // checkpoints. -func (b *blockManager) findNextHeaderCheckpoint(height int32) *chaincfg.Checkpoint { - checkpoints := b.chain.Checkpoints() +func (sm *SyncManager) findNextHeaderCheckpoint(height int32) *chaincfg.Checkpoint { + checkpoints := sm.chain.Checkpoints() if len(checkpoints) == 0 { return nil } @@ -219,24 +217,24 @@ func (b *blockManager) findNextHeaderCheckpoint(height int32) *chaincfg.Checkpoi // download/sync the blockchain from. When syncing is already running, it // simply returns. It also examines the candidates for any which are no longer // candidates and removes them as needed. -func (b *blockManager) startSync() { +func (sm *SyncManager) startSync() { // Return now if we're already syncing. - if b.syncPeer != nil { + if sm.syncPeer != nil { return } // Once the segwit soft-fork package has activated, we only // want to sync from peers which are witness enabled to ensure // that we fully validate all blockchain data. - segwitActive, err := b.chain.IsDeploymentActive(chaincfg.DeploymentSegwit) + segwitActive, err := sm.chain.IsDeploymentActive(chaincfg.DeploymentSegwit) if err != nil { log.Errorf("Unable to query for segwit soft-fork state: %v", err) return } - best := b.chain.BestSnapshot() + best := sm.chain.BestSnapshot() var bestPeer *peerpkg.Peer - for peer, state := range b.peerStates { + for peer, state := range sm.peerStates { if !state.syncCandidate { continue } @@ -267,9 +265,9 @@ func (b *blockManager) startSync() { // Clear the requestedBlocks if the sync peer changes, otherwise // we may ignore blocks we need that the last sync peer failed // to send. - b.requestedBlocks = make(map[chainhash.Hash]struct{}) + sm.requestedBlocks = make(map[chainhash.Hash]struct{}) - locator, err := b.chain.LatestBlockLocator() + locator, err := sm.chain.LatestBlockLocator() if err != nil { log.Errorf("Failed to get block locator for the "+ "latest block: %v", err) @@ -296,19 +294,19 @@ func (b *blockManager) startSync() { // and fully validate them. Finally, regression test mode does // not support the headers-first approach so do normal block // downloads when in regression test mode. - if b.nextCheckpoint != nil && - best.Height < b.nextCheckpoint.Height && - b.chainParams != &chaincfg.RegressionNetParams { + if sm.nextCheckpoint != nil && + best.Height < sm.nextCheckpoint.Height && + sm.chainParams != &chaincfg.RegressionNetParams { - bestPeer.PushGetHeadersMsg(locator, b.nextCheckpoint.Hash) - b.headersFirstMode = true + bestPeer.PushGetHeadersMsg(locator, sm.nextCheckpoint.Hash) + sm.headersFirstMode = true log.Infof("Downloading headers for blocks %d to "+ "%d from peer %s", best.Height+1, - b.nextCheckpoint.Height, bestPeer.Addr()) + sm.nextCheckpoint.Height, bestPeer.Addr()) } else { bestPeer.PushGetBlocksMsg(locator, &zeroHash) } - b.syncPeer = bestPeer + sm.syncPeer = bestPeer } else { log.Warnf("No sync peer candidates available") } @@ -316,11 +314,11 @@ func (b *blockManager) startSync() { // isSyncCandidate returns whether or not the peer is a candidate to consider // syncing from. -func (b *blockManager) isSyncCandidate(peer *peerpkg.Peer) bool { +func (sm *SyncManager) isSyncCandidate(peer *peerpkg.Peer) bool { // Typically a peer is not a candidate for sync if it's not a full node, // however regression test is special in that the regression tool is // not a full node and still needs to be considered a sync candidate. - if b.chainParams == &chaincfg.RegressionNetParams { + if sm.chainParams == &chaincfg.RegressionNetParams { // The peer is not a candidate if it's not coming from localhost // or the hostname can't be determined for some reason. host, _, err := net.SplitHostPort(peer.Addr()) @@ -335,7 +333,7 @@ func (b *blockManager) isSyncCandidate(peer *peerpkg.Peer) bool { // The peer is not a candidate for sync if it's not a full // node. Additionally, if the segwit soft-fork package has // activated, then the peer must also be upgraded. - segwitActive, err := b.chain.IsDeploymentActive(chaincfg.DeploymentSegwit) + segwitActive, err := sm.chain.IsDeploymentActive(chaincfg.DeploymentSegwit) if err != nil { log.Errorf("Unable to query for segwit "+ "soft-fork state: %v", err) @@ -354,25 +352,25 @@ func (b *blockManager) isSyncCandidate(peer *peerpkg.Peer) bool { // handleNewPeerMsg deals with new peers that have signalled they may // be considered as a sync peer (they have already successfully negotiated). It // also starts syncing if needed. It is invoked from the syncHandler goroutine. -func (b *blockManager) handleNewPeerMsg(peer *peerpkg.Peer) { +func (sm *SyncManager) handleNewPeerMsg(peer *peerpkg.Peer) { // Ignore if in the process of shutting down. - if atomic.LoadInt32(&b.shutdown) != 0 { + if atomic.LoadInt32(&sm.shutdown) != 0 { return } log.Infof("New valid peer %s (%s)", peer, peer.UserAgent()) // Initialize the peer state - isSyncCandidate := b.isSyncCandidate(peer) - b.peerStates[peer] = &peerSyncState{ + isSyncCandidate := sm.isSyncCandidate(peer) + sm.peerStates[peer] = &peerSyncState{ syncCandidate: isSyncCandidate, requestedTxns: make(map[chainhash.Hash]struct{}), requestedBlocks: make(map[chainhash.Hash]struct{}), } // Start syncing by choosing the best candidate if needed. - if isSyncCandidate && b.syncPeer == nil { - b.startSync() + if isSyncCandidate && sm.syncPeer == nil { + sm.startSync() } } @@ -380,22 +378,22 @@ func (b *blockManager) handleNewPeerMsg(peer *peerpkg.Peer) { // removes the peer as a candidate for syncing and in the case where it was // the current sync peer, attempts to select a new best peer to sync from. It // is invoked from the syncHandler goroutine. -func (b *blockManager) handleDonePeerMsg(peer *peerpkg.Peer) { - state, exists := b.peerStates[peer] +func (sm *SyncManager) handleDonePeerMsg(peer *peerpkg.Peer) { + state, exists := sm.peerStates[peer] if !exists { log.Warnf("Received done peer message for unknown peer %s", peer) return } // Remove the peer from the list of candidate peers. - delete(b.peerStates, peer) + delete(sm.peerStates, peer) log.Infof("Lost peer %s", peer) // Remove requested transactions from the global map so that they will // be fetched from elsewhere next time we get an inv. for txHash := range state.requestedTxns { - delete(b.requestedTxns, txHash) + delete(sm.requestedTxns, txHash) } // Remove requested blocks from the global map so that they will be @@ -403,26 +401,26 @@ func (b *blockManager) handleDonePeerMsg(peer *peerpkg.Peer) { // TODO: we could possibly here check which peers have these blocks // and request them now to speed things up a little. for blockHash := range state.requestedBlocks { - delete(b.requestedBlocks, blockHash) + delete(sm.requestedBlocks, blockHash) } // Attempt to find a new peer to sync from if the quitting peer is the // sync peer. Also, reset the headers-first state if in headers-first // mode so - if b.syncPeer == peer { - b.syncPeer = nil - if b.headersFirstMode { - best := b.chain.BestSnapshot() - b.resetHeaderState(&best.Hash, best.Height) + if sm.syncPeer == peer { + sm.syncPeer = nil + if sm.headersFirstMode { + best := sm.chain.BestSnapshot() + sm.resetHeaderState(&best.Hash, best.Height) } - b.startSync() + sm.startSync() } } // handleTxMsg handles transaction messages from all peers. -func (b *blockManager) handleTxMsg(tmsg *txMsg) { +func (sm *SyncManager) handleTxMsg(tmsg *txMsg) { peer := tmsg.peer - state, exists := b.peerStates[peer] + state, exists := sm.peerStates[peer] if !exists { log.Warnf("Received tx message from unknown peer %s", peer) return @@ -441,7 +439,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // Ignore transactions that we have already rejected. Do not // send a reject message here because if the transaction was already // rejected, the transaction was unsolicited. - if _, exists = b.rejectedTxns[*txHash]; exists { + if _, exists = sm.rejectedTxns[*txHash]; exists { log.Debugf("Ignoring unsolicited previously rejected "+ "transaction %v from %s", txHash, peer) return @@ -449,7 +447,7 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // Process the transaction to include validation, insertion in the // memory pool, orphan handling, etc. - acceptedTxs, err := b.txMemPool.ProcessTransaction(tmsg.tx, + acceptedTxs, err := sm.txMemPool.ProcessTransaction(tmsg.tx, true, true, mempool.Tag(peer.ID())) // Remove transaction from request maps. Either the mempool/chain @@ -457,13 +455,13 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { // instances of trying to fetch it, or we failed to insert and thus // we'll retry next time we get an inv. delete(state.requestedTxns, *txHash) - delete(b.requestedTxns, *txHash) + delete(sm.requestedTxns, *txHash) if err != nil { // Do not request this transaction again until a new block // has been processed. - b.rejectedTxns[*txHash] = struct{}{} - b.limitMap(b.rejectedTxns, maxRejectedTxns) + sm.rejectedTxns[*txHash] = struct{}{} + sm.limitMap(sm.rejectedTxns, maxRejectedTxns) // When the error is a rule error, it means the transaction was // simply rejected as opposed to something actually going wrong, @@ -484,34 +482,34 @@ func (b *blockManager) handleTxMsg(tmsg *txMsg) { return } - b.peerNotifier.AnnounceNewTransactions(acceptedTxs) + sm.peerNotifier.AnnounceNewTransactions(acceptedTxs) } // current returns true if we believe we are synced with our peers, false if we // still have blocks to check -func (b *blockManager) current() bool { - if !b.chain.IsCurrent() { +func (sm *SyncManager) current() bool { + if !sm.chain.IsCurrent() { return false } // if blockChain thinks we are current and we have no syncPeer it // is probably right. - if b.syncPeer == nil { + if sm.syncPeer == nil { return true } // No matter what chain thinks, if we are below the block we are syncing // to we are not current. - if b.chain.BestSnapshot().Height < b.syncPeer.LastBlock() { + if sm.chain.BestSnapshot().Height < sm.syncPeer.LastBlock() { return false } return true } // handleBlockMsg handles block messages from all peers. -func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { +func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) { peer := bmsg.peer - state, exists := b.peerStates[peer] + state, exists := sm.peerStates[peer] if !exists { log.Warnf("Received block message from unknown peer %s", peer) return @@ -525,7 +523,7 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // the peer or ignore the block when we're in regression test // mode in this case so the chain code is actually fed the // duplicate blocks. - if b.chainParams != &chaincfg.RegressionNetParams { + if sm.chainParams != &chaincfg.RegressionNetParams { log.Warnf("Got unrequested block %v from %s -- "+ "disconnecting", blockHash, peer.Addr()) peer.Disconnect() @@ -542,16 +540,16 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // properly. isCheckpointBlock := false behaviorFlags := blockchain.BFNone - if b.headersFirstMode { - firstNodeEl := b.headerList.Front() + if sm.headersFirstMode { + firstNodeEl := sm.headerList.Front() if firstNodeEl != nil { firstNode := firstNodeEl.Value.(*headerNode) if blockHash.IsEqual(firstNode.hash) { behaviorFlags |= blockchain.BFFastAdd - if firstNode.hash.IsEqual(b.nextCheckpoint.Hash) { + if firstNode.hash.IsEqual(sm.nextCheckpoint.Hash) { isCheckpointBlock = true } else { - b.headerList.Remove(firstNodeEl) + sm.headerList.Remove(firstNodeEl) } } } @@ -561,11 +559,11 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // so we shouldn't have any more instances of trying to fetch it, or we // will fail the insert and thus we'll retry next time we get an inv. delete(state.requestedBlocks, *blockHash) - delete(b.requestedBlocks, *blockHash) + delete(sm.requestedBlocks, *blockHash) // Process the block to include validation, best chain selection, orphan // handling, etc. - _, isOrphan, err := b.chain.ProcessBlock(bmsg.block, behaviorFlags) + _, isOrphan, err := sm.chain.ProcessBlock(bmsg.block, behaviorFlags) if err != nil { // When the error is a rule error, it means the block was simply // rejected as opposed to something actually going wrong, so log @@ -624,8 +622,8 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { } } - orphanRoot := b.chain.GetOrphanRoot(blockHash) - locator, err := b.chain.LatestBlockLocator() + orphanRoot := sm.chain.GetOrphanRoot(blockHash) + locator, err := sm.chain.LatestBlockLocator() if err != nil { log.Warnf("Failed to get block locator for the "+ "latest block: %v", err) @@ -635,16 +633,16 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { } else { // When the block is not an orphan, log information about it and // update the chain state. - b.progressLogger.LogBlockHeight(bmsg.block) + sm.progressLogger.LogBlockHeight(bmsg.block) // Update this peer's latest block height, for future // potential sync node candidacy. - best := b.chain.BestSnapshot() + best := sm.chain.BestSnapshot() heightUpdate = best.Height blkHashUpdate = &best.Hash // Clear the rejected transactions. - b.rejectedTxns = make(map[chainhash.Hash]struct{}) + sm.rejectedTxns = make(map[chainhash.Hash]struct{}) } // Update the block height for this peer. But only send a message to @@ -653,14 +651,14 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // if we're syncing the chain from scratch. if blkHashUpdate != nil && heightUpdate != 0 { peer.UpdateLastBlockHeight(heightUpdate) - if isOrphan || b.current() { - go b.peerNotifier.UpdatePeerHeights(blkHashUpdate, heightUpdate, + if isOrphan || sm.current() { + go sm.peerNotifier.UpdatePeerHeights(blkHashUpdate, heightUpdate, peer) } } // Nothing more to do if we aren't in headers-first mode. - if !b.headersFirstMode { + if !sm.headersFirstMode { return } @@ -668,9 +666,9 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // request more blocks using the header list when the request queue is // getting short. if !isCheckpointBlock { - if b.startHeader != nil && + if sm.startHeader != nil && len(state.requestedBlocks) < minInFlightBlocks { - b.fetchHeaderBlocks() + sm.fetchHeaderBlocks() } return } @@ -679,28 +677,28 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // there is a next checkpoint, get the next round of headers by asking // for headers starting from the block after this one up to the next // checkpoint. - prevHeight := b.nextCheckpoint.Height - prevHash := b.nextCheckpoint.Hash - b.nextCheckpoint = b.findNextHeaderCheckpoint(prevHeight) - if b.nextCheckpoint != nil { + prevHeight := sm.nextCheckpoint.Height + prevHash := sm.nextCheckpoint.Hash + sm.nextCheckpoint = sm.findNextHeaderCheckpoint(prevHeight) + if sm.nextCheckpoint != nil { locator := blockchain.BlockLocator([]*chainhash.Hash{prevHash}) - err := peer.PushGetHeadersMsg(locator, b.nextCheckpoint.Hash) + err := peer.PushGetHeadersMsg(locator, sm.nextCheckpoint.Hash) if err != nil { log.Warnf("Failed to send getheaders message to "+ "peer %s: %v", peer.Addr(), err) return } log.Infof("Downloading headers for blocks %d to %d from "+ - "peer %s", prevHeight+1, b.nextCheckpoint.Height, - b.syncPeer.Addr()) + "peer %s", prevHeight+1, sm.nextCheckpoint.Height, + sm.syncPeer.Addr()) return } // This is headers-first mode, the block is a checkpoint, and there are // no more checkpoints, so switch to normal mode by requesting blocks // from the block after this one up to the end of the chain (zero hash). - b.headersFirstMode = false - b.headerList.Init() + sm.headersFirstMode = false + sm.headerList.Init() log.Infof("Reached the final checkpoint -- switching to normal mode") locator := blockchain.BlockLocator([]*chainhash.Hash{blockHash}) err = peer.PushGetBlocksMsg(locator, &zeroHash) @@ -713,9 +711,9 @@ func (b *blockManager) handleBlockMsg(bmsg *blockMsg) { // fetchHeaderBlocks creates and sends a request to the syncPeer for the next // list of blocks to be downloaded based on the current list of headers. -func (b *blockManager) fetchHeaderBlocks() { +func (sm *SyncManager) fetchHeaderBlocks() { // Nothing to do if there is no start header. - if b.startHeader == nil { + if sm.startHeader == nil { log.Warnf("fetchHeaderBlocks called with no start header") return } @@ -723,9 +721,9 @@ func (b *blockManager) fetchHeaderBlocks() { // Build up a getdata request for the list of blocks the headers // describe. The size hint will be limited to wire.MaxInvPerMsg by // the function, so no need to double check it here. - gdmsg := wire.NewMsgGetDataSizeHint(uint(b.headerList.Len())) + gdmsg := wire.NewMsgGetDataSizeHint(uint(sm.headerList.Len())) numRequested := 0 - for e := b.startHeader; e != nil; e = e.Next() { + for e := sm.startHeader; e != nil; e = e.Next() { node, ok := e.Value.(*headerNode) if !ok { log.Warn("Header list node type is not a headerNode") @@ -733,43 +731,43 @@ func (b *blockManager) fetchHeaderBlocks() { } iv := wire.NewInvVect(wire.InvTypeBlock, node.hash) - haveInv, err := b.haveInventory(iv) + haveInv, err := sm.haveInventory(iv) if err != nil { log.Warnf("Unexpected failure when checking for "+ "existing inventory during header block "+ "fetch: %v", err) } if !haveInv { - syncPeerState := b.peerStates[b.syncPeer] + syncPeerState := sm.peerStates[sm.syncPeer] - b.requestedBlocks[*node.hash] = struct{}{} + sm.requestedBlocks[*node.hash] = struct{}{} syncPeerState.requestedBlocks[*node.hash] = struct{}{} // If we're fetching from a witness enabled peer // post-fork, then ensure that we receive all the // witness data in the blocks. - if b.syncPeer.IsWitnessEnabled() { + if sm.syncPeer.IsWitnessEnabled() { iv.Type = wire.InvTypeWitnessBlock } gdmsg.AddInvVect(iv) numRequested++ } - b.startHeader = e.Next() + sm.startHeader = e.Next() if numRequested >= wire.MaxInvPerMsg { break } } if len(gdmsg.InvList) > 0 { - b.syncPeer.QueueMessage(gdmsg, nil) + sm.syncPeer.QueueMessage(gdmsg, nil) } } // handleHeadersMsg handles block header messages from all peers. Headers are // requested when performing a headers-first sync. -func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { +func (sm *SyncManager) handleHeadersMsg(hmsg *headersMsg) { peer := hmsg.peer - _, exists := b.peerStates[peer] + _, exists := sm.peerStates[peer] if !exists { log.Warnf("Received headers message from unknown peer %s", peer) return @@ -778,7 +776,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // The remote peer is misbehaving if we didn't request headers. msg := hmsg.headers numHeaders := len(msg.Headers) - if !b.headersFirstMode { + if !sm.headersFirstMode { log.Warnf("Got %d unrequested headers from %s -- "+ "disconnecting", numHeaders, peer.Addr()) peer.Disconnect() @@ -799,7 +797,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { finalHash = &blockHash // Ensure there is a previous header to compare against. - prevNodeEl := b.headerList.Back() + prevNodeEl := sm.headerList.Back() if prevNodeEl == nil { log.Warnf("Header list does not contain a previous" + "element as expected -- disconnecting peer") @@ -813,9 +811,9 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { prevNode := prevNodeEl.Value.(*headerNode) if prevNode.hash.IsEqual(&blockHeader.PrevBlock) { node.height = prevNode.height + 1 - e := b.headerList.PushBack(&node) - if b.startHeader == nil { - b.startHeader = e + e := sm.headerList.PushBack(&node) + if sm.startHeader == nil { + sm.startHeader = e } } else { log.Warnf("Received block header that does not "+ @@ -826,8 +824,8 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { } // Verify the header at the next checkpoint height matches. - if node.height == b.nextCheckpoint.Height { - if node.hash.IsEqual(b.nextCheckpoint.Hash) { + if node.height == sm.nextCheckpoint.Height { + if node.hash.IsEqual(sm.nextCheckpoint.Hash) { receivedCheckpoint = true log.Infof("Verified downloaded block "+ "header against checkpoint at height "+ @@ -838,7 +836,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { "expected checkpoint hash of %s -- "+ "disconnecting", node.height, node.hash, peer.Addr(), - b.nextCheckpoint.Hash) + sm.nextCheckpoint.Hash) peer.Disconnect() return } @@ -853,11 +851,11 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // that is already in the database and is only used to ensure // the next header links properly, it must be removed before // fetching the blocks. - b.headerList.Remove(b.headerList.Front()) + sm.headerList.Remove(sm.headerList.Front()) log.Infof("Received %v block headers: Fetching blocks", - b.headerList.Len()) - b.progressLogger.SetLastLogTime(time.Now()) - b.fetchHeaderBlocks() + sm.headerList.Len()) + sm.progressLogger.SetLastLogTime(time.Now()) + sm.fetchHeaderBlocks() return } @@ -865,7 +863,7 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // headers starting from the latest known header and ending with the // next checkpoint. locator := blockchain.BlockLocator([]*chainhash.Hash{finalHash}) - err := peer.PushGetHeadersMsg(locator, b.nextCheckpoint.Hash) + err := peer.PushGetHeadersMsg(locator, sm.nextCheckpoint.Hash) if err != nil { log.Warnf("Failed to send getheaders message to "+ "peer %s: %v", peer.Addr(), err) @@ -878,27 +876,27 @@ func (b *blockManager) handleHeadersMsg(hmsg *headersMsg) { // inventory can be when it is in different states such as blocks that are part // of the main chain, on a side chain, in the orphan pool, and transactions that // are in the memory pool (either the main pool or orphan pool). -func (b *blockManager) haveInventory(invVect *wire.InvVect) (bool, error) { +func (sm *SyncManager) haveInventory(invVect *wire.InvVect) (bool, error) { switch invVect.Type { case wire.InvTypeWitnessBlock: fallthrough case wire.InvTypeBlock: // Ask chain if the block is known to it in any form (main // chain, side chain, or orphan). - return b.chain.HaveBlock(&invVect.Hash) + return sm.chain.HaveBlock(&invVect.Hash) case wire.InvTypeWitnessTx: fallthrough case wire.InvTypeTx: // Ask the transaction memory pool if the transaction is known // to it in any form (main pool or orphan). - if b.txMemPool.HaveTransaction(&invVect.Hash) { + if sm.txMemPool.HaveTransaction(&invVect.Hash) { return true, nil } // Check if the transaction exists from the point of view of the // end of the main chain. - entry, err := b.chain.FetchUtxoEntry(&invVect.Hash) + entry, err := sm.chain.FetchUtxoEntry(&invVect.Hash) if err != nil { return false, err } @@ -912,9 +910,9 @@ func (b *blockManager) haveInventory(invVect *wire.InvVect) (bool, error) { // handleInvMsg handles inv messages from all peers. // We examine the inventory advertised by the remote peer and act accordingly. -func (b *blockManager) handleInvMsg(imsg *invMsg) { +func (sm *SyncManager) handleInvMsg(imsg *invMsg) { peer := imsg.peer - state, exists := b.peerStates[peer] + state, exists := sm.peerStates[peer] if !exists { log.Warnf("Received inv message from unknown peer %s", peer) return @@ -936,20 +934,20 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { // announced block for this peer. We'll use this information later to // update the heights of peers based on blocks we've accepted that they // previously announced. - if lastBlock != -1 && (peer != b.syncPeer || b.current()) { + if lastBlock != -1 && (peer != sm.syncPeer || sm.current()) { peer.UpdateLastAnnouncedBlock(&invVects[lastBlock].Hash) } // Ignore invs from peers that aren't the sync if we are not current. // Helps prevent fetching a mass of orphans. - if peer != b.syncPeer && !b.current() { + if peer != sm.syncPeer && !sm.current() { return } // If our chain is current and a peer announces a block we already // know of, then update their current block height. - if lastBlock != -1 && b.current() { - blkHeight, err := b.chain.BlockHeightByHash(&invVects[lastBlock].Hash) + if lastBlock != -1 && sm.current() { + blkHeight, err := sm.chain.BlockHeightByHash(&invVects[lastBlock].Hash) if err == nil { peer.UpdateLastBlockHeight(blkHeight) } @@ -975,12 +973,12 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { peer.AddKnownInventory(iv) // Ignore inventory when we're in headers-first mode. - if b.headersFirstMode { + if sm.headersFirstMode { continue } // Request the inventory if we don't already have it. - haveInv, err := b.haveInventory(iv) + haveInv, err := sm.haveInventory(iv) if err != nil { log.Warnf("Unexpected failure when checking for "+ "existing inventory during inv message "+ @@ -991,7 +989,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { if iv.Type == wire.InvTypeTx { // Skip the transaction if it has already been // rejected. - if _, exists := b.rejectedTxns[iv.Hash]; exists { + if _, exists := sm.rejectedTxns[iv.Hash]; exists { continue } } @@ -1020,12 +1018,12 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { // resending the orphan block as an available block // to signal there are more missing blocks that need to // be requested. - if b.chain.IsKnownOrphan(&iv.Hash) { + if sm.chain.IsKnownOrphan(&iv.Hash) { // Request blocks starting at the latest known // up to the root of the orphan that just came // in. - orphanRoot := b.chain.GetOrphanRoot(&iv.Hash) - locator, err := b.chain.LatestBlockLocator() + orphanRoot := sm.chain.GetOrphanRoot(&iv.Hash) + locator, err := sm.chain.LatestBlockLocator() if err != nil { log.Errorf("PEER: Failed to get block "+ "locator for the latest block: "+ @@ -1044,7 +1042,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { // Request blocks after this one up to the // final one the remote peer knows about (zero // stop hash). - locator := b.chain.BlockLocatorFromHash(&iv.Hash) + locator := sm.chain.BlockLocatorFromHash(&iv.Hash) peer.PushGetBlocksMsg(locator, &zeroHash) } } @@ -1066,9 +1064,9 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { case wire.InvTypeBlock: // Request the block if there is not already a pending // request. - if _, exists := b.requestedBlocks[iv.Hash]; !exists { - b.requestedBlocks[iv.Hash] = struct{}{} - b.limitMap(b.requestedBlocks, maxRequestedBlocks) + if _, exists := sm.requestedBlocks[iv.Hash]; !exists { + sm.requestedBlocks[iv.Hash] = struct{}{} + sm.limitMap(sm.requestedBlocks, maxRequestedBlocks) state.requestedBlocks[iv.Hash] = struct{}{} if peer.IsWitnessEnabled() { @@ -1084,9 +1082,9 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { case wire.InvTypeTx: // Request the transaction if there is not already a // pending request. - if _, exists := b.requestedTxns[iv.Hash]; !exists { - b.requestedTxns[iv.Hash] = struct{}{} - b.limitMap(b.requestedTxns, maxRequestedTxns) + if _, exists := sm.requestedTxns[iv.Hash]; !exists { + sm.requestedTxns[iv.Hash] = struct{}{} + sm.limitMap(sm.requestedTxns, maxRequestedTxns) state.requestedTxns[iv.Hash] = struct{}{} // If the peer is capable, request the txn @@ -1113,7 +1111,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) { // limitMap is a helper function for maps that require a maximum limit by // evicting a random transaction if adding a new value would cause it to // overflow the maximum allowed. -func (b *blockManager) limitMap(m map[chainhash.Hash]struct{}, limit int) { +func (sm *SyncManager) limitMap(m map[chainhash.Hash]struct{}, limit int) { if len(m)+1 > limit { // Remove a random entry from the map. For most compilers, Go's // range statement iterates starting at a random item although @@ -1128,47 +1126,47 @@ func (b *blockManager) limitMap(m map[chainhash.Hash]struct{}, limit int) { } } -// blockHandler is the main handler for the block manager. It must be run -// as a goroutine. It processes block and inv messages in a separate goroutine +// blockHandler is the main handler for the sync manager. It must be run as a +// goroutine. It processes block and inv messages in a separate goroutine // from the peer handlers so the block (MsgBlock) messages are handled by a // single thread without needing to lock memory data structures. This is -// important because the block manager controls which blocks are needed and how +// important because the sync manager controls which blocks are needed and how // the fetching should proceed. -func (b *blockManager) blockHandler() { +func (sm *SyncManager) blockHandler() { out: for { select { - case m := <-b.msgChan: + case m := <-sm.msgChan: switch msg := m.(type) { case *newPeerMsg: - b.handleNewPeerMsg(msg.peer) + sm.handleNewPeerMsg(msg.peer) case *txMsg: - b.handleTxMsg(msg) + sm.handleTxMsg(msg) msg.reply <- struct{}{} case *blockMsg: - b.handleBlockMsg(msg) + sm.handleBlockMsg(msg) msg.reply <- struct{}{} case *invMsg: - b.handleInvMsg(msg) + sm.handleInvMsg(msg) case *headersMsg: - b.handleHeadersMsg(msg) + sm.handleHeadersMsg(msg) case *donePeerMsg: - b.handleDonePeerMsg(msg.peer) + sm.handleDonePeerMsg(msg.peer) case getSyncPeerMsg: var peerID int32 - if b.syncPeer != nil { - peerID = b.syncPeer.ID() + if sm.syncPeer != nil { + peerID = sm.syncPeer.ID() } msg.reply <- peerID case processBlockMsg: - _, isOrphan, err := b.chain.ProcessBlock( + _, isOrphan, err := sm.chain.ProcessBlock( msg.block, msg.flags) if err != nil { msg.reply <- processBlockResponse{ @@ -1183,7 +1181,7 @@ out: } case isCurrentMsg: - msg.reply <- b.current() + msg.reply <- sm.current() case pauseMsg: // Wait until the sender unpauses the manager. @@ -1194,26 +1192,26 @@ out: "handler: %T", msg) } - case <-b.quit: + case <-sm.quit: break out } } - b.wg.Done() + sm.wg.Done() log.Trace("Block handler done") } // handleBlockchainNotification handles notifications from blockchain. It does // things such as request orphan block parents and relay accepted blocks to // connected peers. -func (b *blockManager) handleBlockchainNotification(notification *blockchain.Notification) { +func (sm *SyncManager) handleBlockchainNotification(notification *blockchain.Notification) { switch notification.Type { // A block has been accepted into the block chain. Relay it to other // peers. case blockchain.NTBlockAccepted: // Don't relay if we are not current. Other peers that are // current should already know about it. - if !b.current() { + if !sm.current() { return } @@ -1225,7 +1223,7 @@ func (b *blockManager) handleBlockchainNotification(notification *blockchain.Not // Generate the inventory vector and relay it. iv := wire.NewInvVect(wire.InvTypeBlock, block.Hash()) - b.peerNotifier.RelayInventory(iv, block.MsgBlock().Header) + sm.peerNotifier.RelayInventory(iv, block.MsgBlock().Header) // A block has been connected to the main block chain. case blockchain.NTBlockConnected: @@ -1243,12 +1241,12 @@ func (b *blockManager) handleBlockchainNotification(notification *blockchain.Not // transaction are NOT removed recursively because they are still // valid. for _, tx := range block.Transactions()[1:] { - b.txMemPool.RemoveTransaction(tx, false) - b.txMemPool.RemoveDoubleSpends(tx) - b.txMemPool.RemoveOrphan(tx) - b.peerNotifier.TransactionConfirmed(tx) - acceptedTxs := b.txMemPool.ProcessOrphans(tx) - b.peerNotifier.AnnounceNewTransactions(acceptedTxs) + sm.txMemPool.RemoveTransaction(tx, false) + sm.txMemPool.RemoveDoubleSpends(tx) + sm.txMemPool.RemoveOrphan(tx) + sm.peerNotifier.TransactionConfirmed(tx) + acceptedTxs := sm.txMemPool.ProcessOrphans(tx) + sm.peerNotifier.AnnounceNewTransactions(acceptedTxs) } // A block has been disconnected from the main block chain. @@ -1262,152 +1260,151 @@ func (b *blockManager) handleBlockchainNotification(notification *blockchain.Not // Reinsert all of the transactions (except the coinbase) into // the transaction pool. for _, tx := range block.Transactions()[1:] { - _, _, err := b.txMemPool.MaybeAcceptTransaction(tx, + _, _, err := sm.txMemPool.MaybeAcceptTransaction(tx, false, false) if err != nil { // Remove the transaction and all transactions // that depend on it if it wasn't accepted into // the transaction pool. - b.txMemPool.RemoveTransaction(tx, true) + sm.txMemPool.RemoveTransaction(tx, true) } } } } -// NewPeer informs the block manager of a newly active peer. -func (b *blockManager) NewPeer(peer *peerpkg.Peer) { +// NewPeer informs the sync manager of a newly active peer. +func (sm *SyncManager) NewPeer(peer *peerpkg.Peer) { // Ignore if we are shutting down. - if atomic.LoadInt32(&b.shutdown) != 0 { + if atomic.LoadInt32(&sm.shutdown) != 0 { return } - b.msgChan <- &newPeerMsg{peer: peer} + sm.msgChan <- &newPeerMsg{peer: peer} } // QueueTx adds the passed transaction message and peer to the block handling // queue. Responds to the done channel argument after the tx message is // processed. -func (b *blockManager) QueueTx(tx *btcutil.Tx, peer *peerpkg.Peer, done chan struct{}) { +func (sm *SyncManager) QueueTx(tx *btcutil.Tx, peer *peerpkg.Peer, done chan struct{}) { // Don't accept more transactions if we're shutting down. - if atomic.LoadInt32(&b.shutdown) != 0 { + if atomic.LoadInt32(&sm.shutdown) != 0 { done <- struct{}{} return } - b.msgChan <- &txMsg{tx: tx, peer: peer, reply: done} + sm.msgChan <- &txMsg{tx: tx, peer: peer, reply: done} } // QueueBlock adds the passed block message and peer to the block handling // queue. Responds to the done channel argument after the block message is // processed. -func (b *blockManager) QueueBlock(block *btcutil.Block, peer *peerpkg.Peer, done chan struct{}) { +func (sm *SyncManager) QueueBlock(block *btcutil.Block, peer *peerpkg.Peer, done chan struct{}) { // Don't accept more blocks if we're shutting down. - if atomic.LoadInt32(&b.shutdown) != 0 { + if atomic.LoadInt32(&sm.shutdown) != 0 { done <- struct{}{} return } - b.msgChan <- &blockMsg{block: block, peer: peer, reply: done} + sm.msgChan <- &blockMsg{block: block, peer: peer, reply: done} } // QueueInv adds the passed inv message and peer to the block handling queue. -func (b *blockManager) QueueInv(inv *wire.MsgInv, peer *peerpkg.Peer) { +func (sm *SyncManager) QueueInv(inv *wire.MsgInv, peer *peerpkg.Peer) { // No channel handling here because peers do not need to block on inv // messages. - if atomic.LoadInt32(&b.shutdown) != 0 { + if atomic.LoadInt32(&sm.shutdown) != 0 { return } - b.msgChan <- &invMsg{inv: inv, peer: peer} + sm.msgChan <- &invMsg{inv: inv, peer: peer} } // QueueHeaders adds the passed headers message and peer to the block handling // queue. -func (b *blockManager) QueueHeaders(headers *wire.MsgHeaders, peer *peerpkg.Peer) { +func (sm *SyncManager) QueueHeaders(headers *wire.MsgHeaders, peer *peerpkg.Peer) { // No channel handling here because peers do not need to block on // headers messages. - if atomic.LoadInt32(&b.shutdown) != 0 { + if atomic.LoadInt32(&sm.shutdown) != 0 { return } - b.msgChan <- &headersMsg{headers: headers, peer: peer} + sm.msgChan <- &headersMsg{headers: headers, peer: peer} } // DonePeer informs the blockmanager that a peer has disconnected. -func (b *blockManager) DonePeer(peer *peerpkg.Peer) { +func (sm *SyncManager) DonePeer(peer *peerpkg.Peer) { // Ignore if we are shutting down. - if atomic.LoadInt32(&b.shutdown) != 0 { + if atomic.LoadInt32(&sm.shutdown) != 0 { return } - b.msgChan <- &donePeerMsg{peer: peer} + sm.msgChan <- &donePeerMsg{peer: peer} } // Start begins the core block handler which processes block and inv messages. -func (b *blockManager) Start() { +func (sm *SyncManager) Start() { // Already started? - if atomic.AddInt32(&b.started, 1) != 1 { + if atomic.AddInt32(&sm.started, 1) != 1 { return } - log.Trace("Starting block manager") - b.wg.Add(1) - go b.blockHandler() + log.Trace("Starting sync manager") + sm.wg.Add(1) + go sm.blockHandler() } -// Stop gracefully shuts down the block manager by stopping all asynchronous +// Stop gracefully shuts down the sync manager by stopping all asynchronous // handlers and waiting for them to finish. -func (b *blockManager) Stop() error { - if atomic.AddInt32(&b.shutdown, 1) != 1 { - log.Warnf("Block manager is already in the process of " + +func (sm *SyncManager) Stop() error { + if atomic.AddInt32(&sm.shutdown, 1) != 1 { + log.Warnf("Sync manager is already in the process of " + "shutting down") return nil } - log.Infof("Block manager shutting down") - close(b.quit) - b.wg.Wait() + log.Infof("Sync manager shutting down") + close(sm.quit) + sm.wg.Wait() return nil } // SyncPeerID returns the ID of the current sync peer, or 0 if there is none. -func (b *blockManager) SyncPeerID() int32 { +func (sm *SyncManager) SyncPeerID() int32 { reply := make(chan int32) - b.msgChan <- getSyncPeerMsg{reply: reply} + sm.msgChan <- getSyncPeerMsg{reply: reply} return <-reply } // ProcessBlock makes use of ProcessBlock on an internal instance of a block -// chain. It is funneled through the block manager since btcchain is not safe -// for concurrent access. -func (b *blockManager) ProcessBlock(block *btcutil.Block, flags blockchain.BehaviorFlags) (bool, error) { +// chain. +func (sm *SyncManager) ProcessBlock(block *btcutil.Block, flags blockchain.BehaviorFlags) (bool, error) { reply := make(chan processBlockResponse, 1) - b.msgChan <- processBlockMsg{block: block, flags: flags, reply: reply} + sm.msgChan <- processBlockMsg{block: block, flags: flags, reply: reply} response := <-reply return response.isOrphan, response.err } -// IsCurrent returns whether or not the block manager believes it is synced with +// IsCurrent returns whether or not the sync manager believes it is synced with // the connected peers. -func (b *blockManager) IsCurrent() bool { +func (sm *SyncManager) IsCurrent() bool { reply := make(chan bool) - b.msgChan <- isCurrentMsg{reply: reply} + sm.msgChan <- isCurrentMsg{reply: reply} return <-reply } -// Pause pauses the block manager until the returned channel is closed. +// Pause pauses the sync manager until the returned channel is closed. // // Note that while paused, all peer and block processing is halted. The -// message sender should avoid pausing the block manager for long durations. -func (b *blockManager) Pause() chan<- struct{} { +// message sender should avoid pausing the sync manager for long durations. +func (sm *SyncManager) Pause() chan<- struct{} { c := make(chan struct{}) - b.msgChan <- pauseMsg{c} + sm.msgChan <- pauseMsg{c} return c } -// newBlockManager returns a new bitcoin block manager. -// Use Start to begin processing asynchronous block and inv updates. -func newBlockManager(config *blockManagerConfig) (*blockManager, error) { - bm := blockManager{ +// New constructs a new SyncManager. Use Start to begin processing asynchronous +// block, tx, and inv updates. +func New(config *Config) (*SyncManager, error) { + sm := SyncManager{ peerNotifier: config.PeerNotifier, chain: config.Chain, txMemPool: config.TxMemPool, @@ -1422,18 +1419,18 @@ func newBlockManager(config *blockManagerConfig) (*blockManager, error) { quit: make(chan struct{}), } - best := bm.chain.BestSnapshot() + best := sm.chain.BestSnapshot() if !config.DisableCheckpoints { // Initialize the next checkpoint based on the current height. - bm.nextCheckpoint = bm.findNextHeaderCheckpoint(best.Height) - if bm.nextCheckpoint != nil { - bm.resetHeaderState(&best.Hash, best.Height) + sm.nextCheckpoint = sm.findNextHeaderCheckpoint(best.Height) + if sm.nextCheckpoint != nil { + sm.resetHeaderState(&best.Hash, best.Height) } } else { log.Info("Checkpoints are disabled") } - bm.chain.Subscribe(bm.handleBlockchainNotification) + sm.chain.Subscribe(sm.handleBlockchainNotification) - return &bm, nil + return &sm, nil } diff --git a/rpcadapters.go b/rpcadapters.go index 771985e453..7d2c3a14d0 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mempool" + "github.com/btcsuite/btcd/netsync" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" @@ -225,8 +226,8 @@ func (cm *rpcConnManager) RelayTransactions(txns []*mempool.TxDesc) { // rpcSyncMgr provides a block manager for use with the RPC server and // implements the rpcserverSyncManager interface. type rpcSyncMgr struct { - server *server - blockMgr *blockManager + server *server + syncMgr *netsync.SyncManager } // Ensure rpcSyncMgr implements the rpcserverSyncManager interface. @@ -238,7 +239,7 @@ var _ rpcserverSyncManager = (*rpcSyncMgr)(nil) // This function is safe for concurrent access and is part of the // rpcserverSyncManager interface implementation. func (b *rpcSyncMgr) IsCurrent() bool { - return b.blockMgr.IsCurrent() + return b.syncMgr.IsCurrent() } // SubmitBlock submits the provided block to the network after processing it @@ -247,7 +248,7 @@ func (b *rpcSyncMgr) IsCurrent() bool { // This function is safe for concurrent access and is part of the // rpcserverSyncManager interface implementation. func (b *rpcSyncMgr) SubmitBlock(block *btcutil.Block, flags blockchain.BehaviorFlags) (bool, error) { - return b.blockMgr.ProcessBlock(block, flags) + return b.syncMgr.ProcessBlock(block, flags) } // Pause pauses the sync manager until the returned channel is closed. @@ -255,7 +256,7 @@ func (b *rpcSyncMgr) SubmitBlock(block *btcutil.Block, flags blockchain.Behavior // This function is safe for concurrent access and is part of the // rpcserverSyncManager interface implementation. func (b *rpcSyncMgr) Pause() chan<- struct{} { - return b.blockMgr.Pause() + return b.syncMgr.Pause() } // SyncPeerID returns the peer that is currently the peer being used to sync @@ -264,7 +265,7 @@ func (b *rpcSyncMgr) Pause() chan<- struct{} { // This function is safe for concurrent access and is part of the // rpcserverSyncManager interface implementation. func (b *rpcSyncMgr) SyncPeerID() int32 { - return b.blockMgr.SyncPeerID() + return b.syncMgr.SyncPeerID() } // LocateBlocks returns the hashes of the blocks after the first known block in diff --git a/server.go b/server.go index 626c8ee0a3..f29e6d2f1c 100644 --- a/server.go +++ b/server.go @@ -32,6 +32,7 @@ import ( "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/mining/cpuminer" + "github.com/btcsuite/btcd/netsync" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -67,6 +68,9 @@ var ( userAgentVersion = fmt.Sprintf("%d.%d.%d", appMajor, appMinor, appPatch) ) +// zeroHash is the zero value hash (all zeros). It is defined as a convenience. +var zeroHash chainhash.Hash + // onionAddr implements the net.Addr interface and represents a tor address. type onionAddr struct { addr string @@ -177,7 +181,7 @@ type server struct { sigCache *txscript.SigCache hashCache *txscript.HashCache rpcServer *rpcServer - blockManager *blockManager + syncManager *netsync.SyncManager chain *blockchain.BlockChain txMemPool *mempool.TxPool cpuMiner *cpuminer.CPUMiner @@ -245,7 +249,7 @@ func newServerPeer(s *server, isPersistent bool) *serverPeer { // newestBlock returns the current best block hash and height using the format // required by the configuration for the peer package. func (sp *serverPeer) newestBlock() (*chainhash.Hash, int32, error) { - best := sp.server.blockManager.chain.BestSnapshot() + best := sp.server.chain.BestSnapshot() return &best.Hash, best.Height, nil } @@ -343,8 +347,8 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { // the local clock to keep the network time in sync. sp.server.timeSource.AddTimeSample(sp.Addr(), msg.Timestamp) - // Signal the block manager this peer is a new sync candidate. - sp.server.blockManager.NewPeer(sp.Peer) + // Signal the sync manager this peer is a new sync candidate. + sp.server.syncManager.NewPeer(sp.Peer) // Choose whether or not to relay transactions before a filter command // is received. @@ -363,7 +367,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { // After soft-fork activation, only make outbound // connection to peers if they flag that they're segwit // enabled. - chain := sp.server.blockManager.chain + chain := sp.server.chain segwitActive, err := chain.IsDeploymentActive(chaincfg.DeploymentSegwit) if err != nil { peerLog.Errorf("Unable to query for segwit "+ @@ -475,12 +479,12 @@ func (sp *serverPeer) OnTx(_ *peer.Peer, msg *wire.MsgTx) { iv := wire.NewInvVect(wire.InvTypeTx, tx.Hash()) sp.AddKnownInventory(iv) - // Queue the transaction up to be handled by the block manager and + // Queue the transaction up to be handled by the sync manager and // intentionally block further receives until the transaction is fully // processed and known good or bad. This helps prevent a malicious peer // from queuing up a bunch of bad transactions before disconnecting (or // being disconnected) and wasting memory. - sp.server.blockManager.QueueTx(tx, sp.Peer, sp.txProcessed) + sp.server.syncManager.QueueTx(tx, sp.Peer, sp.txProcessed) <-sp.txProcessed } @@ -506,7 +510,7 @@ func (sp *serverPeer) OnBlock(_ *peer.Peer, msg *wire.MsgBlock, buf []byte) { // reference implementation processes blocks in the same // thread and therefore blocks further messages until // the bitcoin block has been fully processed. - sp.server.blockManager.QueueBlock(block, sp.Peer, sp.blockProcessed) + sp.server.syncManager.QueueBlock(block, sp.Peer, sp.blockProcessed) <-sp.blockProcessed } @@ -517,7 +521,7 @@ func (sp *serverPeer) OnBlock(_ *peer.Peer, msg *wire.MsgBlock, buf []byte) { func (sp *serverPeer) OnInv(_ *peer.Peer, msg *wire.MsgInv) { if !cfg.BlocksOnly { if len(msg.InvList) > 0 { - sp.server.blockManager.QueueInv(msg, sp.Peer) + sp.server.syncManager.QueueInv(msg, sp.Peer) } return } @@ -543,14 +547,14 @@ func (sp *serverPeer) OnInv(_ *peer.Peer, msg *wire.MsgInv) { } if len(newInv.InvList) > 0 { - sp.server.blockManager.QueueInv(newInv, sp.Peer) + sp.server.syncManager.QueueInv(newInv, sp.Peer) } } // OnHeaders is invoked when a peer receives a headers bitcoin -// message. The message is passed down to the block manager. +// message. The message is passed down to the sync manager. func (sp *serverPeer) OnHeaders(_ *peer.Peer, msg *wire.MsgHeaders) { - sp.server.blockManager.QueueHeaders(msg, sp.Peer) + sp.server.syncManager.QueueHeaders(msg, sp.Peer) } // handleGetData is invoked when a peer receives a getdata bitcoin message and @@ -646,7 +650,7 @@ func (sp *serverPeer) OnGetBlocks(_ *peer.Peer, msg *wire.MsgGetBlocks) { // over with the genesis block if unknown block locators are provided. // // This mirrors the behavior in the reference implementation. - chain := sp.server.blockManager.chain + chain := sp.server.chain hashList := chain.LocateBlocks(msg.BlockLocatorHashes, &msg.HashStop, wire.MaxBlocksPerMsg) @@ -676,7 +680,7 @@ func (sp *serverPeer) OnGetBlocks(_ *peer.Peer, msg *wire.MsgGetBlocks) { // message. func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { // Ignore getheaders requests if not in sync. - if !sp.server.blockManager.IsCurrent() { + if !sp.server.syncManager.IsCurrent() { return } @@ -690,7 +694,7 @@ func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { // over with the genesis block if unknown block locators are provided. // // This mirrors the behavior in the reference implementation. - chain := sp.server.blockManager.chain + chain := sp.server.chain headers := chain.LocateHeaders(msg.BlockLocatorHashes, &msg.HashStop) if len(headers) == 0 { // Nothing to send. @@ -1075,7 +1079,7 @@ func (s *server) pushBlockMsg(sp *serverPeer, hash *chainhash.Hash, doneChan cha // to trigger it to issue another getblocks message for the next // batch of inventory. if sendInv { - best := sp.server.blockManager.chain.BestSnapshot() + best := sp.server.chain.BestSnapshot() invMsg := wire.NewMsgInvSizeHint(1) iv := wire.NewInvVect(wire.InvTypeBlock, &best.Hash) invMsg.AddInvVect(iv) @@ -1101,7 +1105,7 @@ func (s *server) pushMerkleBlockMsg(sp *serverPeer, hash *chainhash.Hash, } // Fetch the raw block bytes from the database. - blk, err := sp.server.blockManager.chain.BlockByHash(hash) + blk, err := sp.server.chain.BlockByHash(hash) if err != nil { peerLog.Tracef("Unable to fetch requested block hash %v: %v", hash, err) @@ -1616,9 +1620,9 @@ func (s *server) peerDoneHandler(sp *serverPeer) { sp.WaitForDisconnect() s.donePeers <- sp - // Only tell block manager we are gone if we ever told it we existed. + // Only tell sync manager we are gone if we ever told it we existed. if sp.VersionKnown() { - s.blockManager.DonePeer(sp.Peer) + s.syncManager.DonePeer(sp.Peer) // Evict any remaining orphans that were sent by the peer. numEvicted := s.txMemPool.RemoveOrphansByTag(mempool.Tag(sp.ID())) @@ -1635,13 +1639,13 @@ func (s *server) peerDoneHandler(sp *serverPeer) { // peers to and from the server, banning peers, and broadcasting messages to // peers. It must be run in a goroutine. func (s *server) peerHandler() { - // Start the address manager and block manager, both of which are needed + // Start the address manager and sync manager, both of which are needed // by peers. This is done here since their lifecycle is closely tied // to this handler and rather than adding more channels to sychronize // things, it's easier and slightly faster to simply start and stop them // in this handler. s.addrManager.Start() - s.blockManager.Start() + s.syncManager.Start() srvrLog.Tracef("Starting peer handler") @@ -1709,7 +1713,7 @@ out: } s.connManager.Stop() - s.blockManager.Stop() + s.syncManager.Stop() s.addrManager.Stop() // Drain channels before exiting so nothing is left waiting around @@ -2366,7 +2370,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param } s.txMemPool = mempool.New(&txC) - s.blockManager, err = newBlockManager(&blockManagerConfig{ + s.syncManager, err = netsync.New(&netsync.Config{ PeerNotifier: &s, Chain: s.chain, TxMemPool: s.txMemPool, @@ -2398,9 +2402,9 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param ChainParams: chainParams, BlockTemplateGenerator: blockTemplateGenerator, MiningAddrs: cfg.miningAddrs, - ProcessBlock: s.blockManager.ProcessBlock, + ProcessBlock: s.syncManager.ProcessBlock, ConnectedCount: s.ConnectedCount, - IsCurrent: s.blockManager.IsCurrent, + IsCurrent: s.syncManager.IsCurrent, }) // Only setup a function to return new addresses to connect to when @@ -2500,9 +2504,9 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param Listeners: rpcListeners, StartupTime: s.startupTime, ConnMgr: &rpcConnManager{&s}, - SyncMgr: &rpcSyncMgr{&s, s.blockManager}, + SyncMgr: &rpcSyncMgr{&s, s.syncManager}, TimeSource: s.timeSource, - Chain: s.blockManager.chain, + Chain: s.chain, ChainParams: chainParams, DB: db, TxMemPool: s.txMemPool, From feee952cd39bfa83da76d2a1e2baafd5bb09fde2 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 25 Aug 2017 13:51:43 -0500 Subject: [PATCH 0006/1056] readme: Remove mailing lists and include GPG key. This updates the README to remove the mailing lists which no longer exist and to link the GPG public key used to sign the release tags directly from the repository instead of the no longer active website. --- README.md | 11 +---- release/GIT-GPG-KEY-conformal.txt | 74 +++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 release/GIT-GPG-KEY-conformal.txt diff --git a/README.md b/README.md index 1ddd278723..68feed06e0 100644 --- a/README.md +++ b/README.md @@ -112,13 +112,6 @@ $ ./btcd - channel #btcd - [webchat](https://webchat.freenode.net/?channels=btcd) -## Mailing lists - -- btcd: discussion of btcd and its packages. -- btcd-commits: readonly mail-out of source code changes. - -To subscribe to a given list, send email to list+subscribe@opensource.conformal.com - ## Issue Tracker The [integrated github issue tracker](https://github.com/btcsuite/btcd/issues) @@ -134,8 +127,8 @@ All official release tags are signed by Conformal so users can ensure the code has not been tampered with and is coming from the btcsuite developers. To verify the signature perform the following: -- Download the public key from the Conformal website at - https://opensource.conformal.com/GIT-GPG-KEY-conformal.txt +- Download the Conformal public key: + https://raw.githubusercontent.com/btcsuite/btcd/master/release/GIT-GPG-KEY-conformal.txt - Import the public key into your GPG keyring: ```bash diff --git a/release/GIT-GPG-KEY-conformal.txt b/release/GIT-GPG-KEY-conformal.txt new file mode 100644 index 0000000000..a6d1a2562d --- /dev/null +++ b/release/GIT-GPG-KEY-conformal.txt @@ -0,0 +1,74 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +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 +=iic8 +-----END PGP PUBLIC KEY BLOCK----- From a1d1ea70dd212a440beb9caa4b766a58d1ed0254 Mon Sep 17 00:00:00 2001 From: Andy Weidenbaum Date: Sat, 26 Aug 2017 10:56:46 -0700 Subject: [PATCH 0007/1056] rm extra word segwit, s/segwit segwit/segwit --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index f29e6d2f1c..c676c8889d 100644 --- a/server.go +++ b/server.go @@ -377,7 +377,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { if segwitActive && !sp.IsWitnessEnabled() { peerLog.Infof("Disconnecting non-segwit "+ - "peer %v, isn't segwit segwit enabled and "+ + "peer %v, isn't segwit enabled and "+ "we need more segwit enabled peers", sp) sp.Disconnect() return From 3cb87afa2fc078efc2b12d16458cce15daab311c Mon Sep 17 00:00:00 2001 From: Alok Menghrajani Date: Mon, 28 Aug 2017 01:50:00 -0700 Subject: [PATCH 0008/1056] rpcclient: fix links in README.md --- rpcclient/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpcclient/README.md b/rpcclient/README.md index b6077d2a82..4d644110f5 100644 --- a/rpcclient/README.md +++ b/rpcclient/README.md @@ -19,15 +19,15 @@ implement and the API is not stable yet. ## Documentation * [API Reference](http://godoc.org/github.com/btcsuite/btcd/rpcclient) -* [btcd Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcdwebsockets) +* [btcd Websockets Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/btcdwebsockets) Connects to a btcd RPC server using TLS-secured websockets, registers for block connected and block disconnected notifications, and gets the current block count -* [btcwallet Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcwalletwebsockets) +* [btcwallet Websockets Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/btcwalletwebsockets) Connects to a btcwallet RPC server using TLS-secured websockets, registers for notifications about changes to account balances, and gets a list of unspent transaction outputs (utxos) the wallet can sign -* [Bitcoin Core HTTP POST Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/bitcoincorehttp) +* [Bitcoin Core HTTP POST Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/bitcoincorehttp) Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled and gets the current block count From 9bd7bcfff667b63680a968da1083f0f952766be4 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 25 Aug 2017 13:45:54 -0500 Subject: [PATCH 0009/1056] travis: Update to go 1.8 and 1.9. Also, make the gosimple linter happy while here. --- .travis.yml | 4 ++-- README.md | 2 +- server.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 465787cdba..d0244683da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: go go: - - 1.6.x - - 1.7.x + - 1.8.x + - 1.9.x sudo: false install: - GLIDE_TAG=v0.12.3 diff --git a/README.md b/README.md index 68feed06e0..0e8152a2f5 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ which are both under active development. ## Requirements -[Go](http://golang.org) 1.6 or newer. +[Go](http://golang.org) 1.8 or newer. ## Installation diff --git a/server.go b/server.go index c676c8889d..70d85b2b12 100644 --- a/server.go +++ b/server.go @@ -1202,7 +1202,7 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool { if banEnd, ok := state.banned[host]; ok { if time.Now().Before(banEnd) { srvrLog.Debugf("Peer %s is banned for another %v - disconnecting", - host, banEnd.Sub(time.Now())) + host, time.Until(banEnd)) sp.Disconnect() return false } From 0b50802d52cdb7e5560ea6ff3a453b7378e3d5f7 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Tue, 29 Aug 2017 20:40:19 -0500 Subject: [PATCH 0010/1056] btcjson/rpcserver: Encode witness stack as slice. The modifies the encoding of witness stacks in JSON responses to use a slice of strings instead of a single space-separated string for compatibility with Core. --- btcjson/chainsvrresults.go | 14 +++++++------- rpcserver.go | 39 +++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 9af1d3994f..33d54d385d 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -317,7 +317,7 @@ type Vin struct { Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` Sequence uint32 `json:"sequence"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` } // IsCoinBase returns a bool to show if a Vin is a Coinbase one or not. @@ -335,9 +335,9 @@ func (v *Vin) HasWitness() bool { func (v *Vin) MarshalJSON() ([]byte, error) { if v.IsCoinBase() { coinbaseStruct := struct { - Coinbase string `json:"coinbase"` - Sequence uint32 `json:"sequence"` - Witness string `json:"witness,omitempty"` + Coinbase string `json:"coinbase"` + Sequence uint32 `json:"sequence"` + Witness []string `json:"witness,omitempty"` }{ Coinbase: v.Coinbase, Sequence: v.Sequence, @@ -351,7 +351,7 @@ func (v *Vin) MarshalJSON() ([]byte, error) { Txid string `json:"txid"` Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` Sequence uint32 `json:"sequence"` }{ Txid: v.Txid, @@ -389,7 +389,7 @@ type VinPrevOut struct { Txid string `json:"txid"` Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` PrevOut *PrevOut `json:"prevOut"` Sequence uint32 `json:"sequence"` } @@ -423,7 +423,7 @@ func (v *VinPrevOut) MarshalJSON() ([]byte, error) { Txid string `json:"txid"` Vout uint32 `json:"vout"` ScriptSig *ScriptSig `json:"scriptSig"` - Witness string `json:"txinwitness"` + Witness []string `json:"txinwitness"` PrevOut *PrevOut `json:"prevOut,omitempty"` Sequence uint32 `json:"sequence"` }{ diff --git a/rpcserver.go b/rpcserver.go index 602e793b9b..db4dece8ae 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -629,6 +629,23 @@ func handleDebugLevel(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return "Done.", nil } +// witnessToHex formats the passed witness stack as a slice of hex-encoded +// strings to be used in a JSON response. +func witnessToHex(witness wire.TxWitness) []string { + // Ensure nil is returned when there are no entries versus an empty + // slice so it can properly be omitted as necessary. + if len(witness) == 0 { + return nil + } + + result := make([]string, 0, len(witness)) + for _, wit := range witness { + result = append(result, hex.EncodeToString(wit)) + } + + return result +} + // createVinList returns a slice of JSON objects for the inputs of the passed // transaction. func createVinList(mtx *wire.MsgTx) []btcjson.Vin { @@ -638,7 +655,7 @@ func createVinList(mtx *wire.MsgTx) []btcjson.Vin { txIn := mtx.TxIn[0] vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript) vinList[0].Sequence = txIn.Sequence - vinList[0].Witness = witnessToSring(txIn.Witness) + vinList[0].Witness = witnessToHex(txIn.Witness) return vinList } @@ -658,29 +675,13 @@ func createVinList(mtx *wire.MsgTx) []btcjson.Vin { } if mtx.HasWitness() { - vinEntry.Witness = witnessToSring(txIn.Witness) + vinEntry.Witness = witnessToHex(txIn.Witness) } } return vinList } -// witnessToSring formats the passed witness stack as a string to be used -// within a JSON response. The witness is encoded as a single string with -// spaces separating each witness element. -func witnessToSring(witness wire.TxWitness) string { - var b bytes.Buffer - for i, wit := range witness { - if i > 0 { - b.WriteString(" ") - } - - b.WriteString(hex.EncodeToString(wit)) - } - - return b.String() -} - // createVoutList returns a slice of JSON objects for the outputs of the passed // transaction. func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap map[string]struct{}) []btcjson.Vout { @@ -2852,7 +2853,7 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P } if len(txIn.Witness) != 0 { - vinEntry.Witness = witnessToSring(txIn.Witness) + vinEntry.Witness = witnessToHex(txIn.Witness) } // Add the entry to the list now if it already passed the filter From 0a9fb535489c295cd59bdfeade4faa746f75831c Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Wed, 30 Aug 2017 11:27:02 -0700 Subject: [PATCH 0011/1056] blockchain: Add node to block index in maybeAcceptBlock. This has the same effect but makes it clearer that all blocks written to the database end up in the block index. --- blockchain/accept.go | 9 +++++++++ blockchain/blockindex.go | 11 +++++++++++ blockchain/chain.go | 18 ------------------ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 3d32f8c030..73169ebb26 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -67,6 +67,15 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) newNode.height = blockHeight newNode.workSum.Add(prevNode.workSum, newNode.workSum) } + b.index.AddNode(newNode) + + // Disconnect it from the parent node when the function returns when + // running in dry run mode. + if dryRun { + defer func() { + b.index.RemoveNode(newNode) + }() + } // Connect the passed block to the chain while respecting proper chain // selection according to the chain with the most proof of work. This diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index d65619eb7a..64d66ffa64 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -224,3 +224,14 @@ func (bi *blockIndex) AddNode(node *blockNode) { bi.index[node.hash] = node bi.Unlock() } + +// RemoveNode removes the provided node to the block index. There is no check +// whether another node in the index depends on this one, so it is up to caller +// to avoid that situation. +// +// This function is safe for concurrent access. +func (bi *blockIndex) RemoveNode(node *blockNode) { + bi.Lock() + delete(bi.index, node.hash) + bi.Unlock() +} diff --git a/blockchain/chain.go b/blockchain/chain.go index d1ee628b81..04160a09fb 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -648,7 +648,6 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *U view.commit() // This node is now the end of the best chain. - b.index.AddNode(node) b.bestChain.SetTip(node) // Update the state for the best block. Notice how this replaces the @@ -1044,23 +1043,6 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla block.Hash()) } - // We're extending (or creating) a side chain which may or may not - // become the main chain, but in either case the entry is needed in the - // index for future processing. - b.index.Lock() - b.index.index[node.hash] = node - b.index.Unlock() - - // Disconnect it from the parent node when the function returns when - // running in dry run mode. - if dryRun { - defer func() { - b.index.Lock() - delete(b.index.index, node.hash) - b.index.Unlock() - }() - } - // We're extending (or creating) a side chain, but the cumulative // work for this new side chain is not enough to make it the new chain. if node.workSum.Cmp(b.bestChain.Tip().workSum) <= 0 { From 02a06a2cd8a408bfdd7fc6a6282066ed7d898c65 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 30 Aug 2017 14:31:35 -0500 Subject: [PATCH 0012/1056] blockchain: Update some comments to match reality. --- blockchain/accept.go | 7 +++---- blockchain/blockindex.go | 2 +- blockchain/chain.go | 5 ++--- blockchain/scriptval.go | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 73169ebb26..5bc517b43a 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -16,8 +16,8 @@ import ( // ProcessBlock before calling this function with it. // // The flags modify the behavior of this function as follows: -// - BFDryRun: The memory chain index will not be pruned and no accept -// notification will be sent since the block is not being accepted. +// - BFDryRun: The block index will not be updated and no accept notification +// will be sent since the block is not being accepted. // // The flags are also passed to checkBlockContext and connectBestChain. See // their documentation for how the flags modify their behavior. @@ -69,8 +69,7 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) } b.index.AddNode(newNode) - // Disconnect it from the parent node when the function returns when - // running in dry run mode. + // Undo changes to the block index when running in dry run mode. if dryRun { defer func() { b.index.RemoveNode(newNode) diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 64d66ffa64..63d021d8db 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -225,7 +225,7 @@ func (bi *blockIndex) AddNode(node *blockNode) { bi.Unlock() } -// RemoveNode removes the provided node to the block index. There is no check +// RemoveNode removes the provided node from the block index. There is no check // whether another node in the index depends on this one, so it is up to caller // to avoid that situation. // diff --git a/blockchain/chain.go b/blockchain/chain.go index 04160a09fb..25fcf46af4 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -984,9 +984,8 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List, flags // The flags modify the behavior of this function as follows: // - BFFastAdd: Avoids several expensive transaction validation operations. // This is useful when using checkpoints. -// - BFDryRun: Prevents the block from being connected and avoids modifying the -// state of the memory chain index. Also, any log messages related to -// modifying the state are avoided. +// - BFDryRun: Prevents the block from actually being connected and avoids any +// log messages related to modifying the state. // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) { diff --git a/blockchain/scriptval.go b/blockchain/scriptval.go index 38e50bcf10..f7c7601122 100644 --- a/blockchain/scriptval.go +++ b/blockchain/scriptval.go @@ -37,7 +37,7 @@ type txValidator struct { } // sendResult sends the result of a script pair validation on the internal -// result channel while respecting the quit channel. The allows orderly +// result channel while respecting the quit channel. This allows orderly // shutdown when the validation process is aborted early due to a validation // error in one of the other goroutines. func (v *txValidator) sendResult(result error) { @@ -135,7 +135,7 @@ func (v *txValidator) Validate(items []*txValidateItem) error { } // Limit the number of goroutines to do script validation based on the - // number of processor cores. This help ensure the system stays + // number of processor cores. This helps ensure the system stays // reasonably responsive under heavy load. maxGoRoutines := runtime.NumCPU() * 3 if maxGoRoutines <= 0 { From 42b969a827f789d36939a8daf167ee0745adc0ee Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 30 Aug 2017 14:36:56 -0500 Subject: [PATCH 0013/1056] blockchain: Remove unused min memory nodes field. This removes the minMemoryNodes field from the BlockChain struct since it is no longer used anywhere. --- blockchain/chain.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 25fcf46af4..f773549bf4 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -105,17 +105,9 @@ type BlockChain struct { // parameters. They are also set when the instance is created and // can't be changed afterwards, so there is no need to protect them with // a separate mutex. - // - // minMemoryNodes is the minimum number of consecutive nodes needed - // in memory in order to perform all necessary validation. It is used - // to determine when it's safe to prune nodes from memory without - // causing constant dynamic reloading. This is typically the same value - // as blocksPerRetarget, but it is separated here for tweakability and - // testability. minRetargetTimespan int64 // target timespan / adjustment factor maxRetargetTimespan int64 // target timespan * adjustment factor blocksPerRetarget int32 // target timespan / target time per block - minMemoryNodes int32 // chainLock protects concurrent access to the vast majority of the // fields in this struct below this point. From a2085c68f8965a0bad9274a1e7b74c06dbc43d71 Mon Sep 17 00:00:00 2001 From: David Hill Date: Thu, 31 Aug 2017 09:59:43 -0400 Subject: [PATCH 0014/1056] config: Add --whitelist support. --- config.go | 34 ++++++++++++++++++++++++++++++++++ doc.go | 6 ++++-- sample-btcd.conf | 7 +++++++ server.go | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/config.go b/config.go index b7a8219bae..1192be4f50 100644 --- a/config.go +++ b/config.go @@ -103,6 +103,7 @@ type config struct { DisableBanning bool `long:"nobanning" description:"Disable banning of misbehaving peers"` BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` + Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"` RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"` RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"` RPCLimitUser string `long:"rpclimituser" description:"Username for limited RPC connections"` @@ -163,6 +164,7 @@ type config struct { addCheckpoints []chaincfg.Checkpoint miningAddrs []btcutil.Address minRelayTxFee btcutil.Amount + whitelists []*net.IPNet } // serviceOptions defines the configuration options for the daemon as a service on @@ -630,6 +632,38 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } + // Validate any given whitelisted IP addresses and networks. + if len(cfg.Whitelists) > 0 { + var ip net.IP + cfg.whitelists = make([]*net.IPNet, 0, len(cfg.Whitelists)) + + for _, addr := range cfg.Whitelists { + _, ipnet, err := net.ParseCIDR(addr) + if err != nil { + ip = net.ParseIP(addr) + if ip == nil { + str := "%s: The whitelist value of '%s' is invalid" + err = fmt.Errorf(str, funcName, addr) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + var bits int + if ip.To4() == nil { + // IPv6 + bits = 128 + } else { + bits = 32 + } + ipnet = &net.IPNet{ + IP: ip, + Mask: net.CIDRMask(bits, bits), + } + } + cfg.whitelists = append(cfg.whitelists, ipnet) + } + } + // --addPeer and --connect do not mix. if len(cfg.AddPeers) > 0 && len(cfg.ConnectPeers) > 0 { str := "%s: the --addpeer and --connect options can not be " + diff --git a/doc.go b/doc.go index 90da387a72..631568ffdd 100644 --- a/doc.go +++ b/doc.go @@ -35,10 +35,12 @@ Application Options: (default all interfaces port: 8333, testnet: 18333) --maxpeers= Max number of inbound and outbound peers (125) --nobanning Disable banning of misbehaving peers - --banthreshold= Maximum allowed ban score before disconnecting and - banning misbehaving peers. --banduration= How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second (24h0m0s) + --banthreshold= Maximum allowed ban score before disconnecting and + banning misbehaving peers. + --whitelist= Add an IP network or IP that will not be banned. + (eg. 192.168.1.0/24 or ::1) -u, --rpcuser= Username for RPC connections -P, --rpcpass= Password for RPC connections --rpclimituser= Username for limited RPC connections diff --git a/sample-btcd.conf b/sample-btcd.conf index 3ac9aab4c1..ead8d06a76 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -114,6 +114,13 @@ ; banduration=24h ; banduration=11h30m15s +; Add whitelisted IP networks and IPs. Connected peers whose IP matches a +; whitelist will not have their ban score increased. +; whitelist=127.0.0.1 +; whitelist=::1 +; whitelist=192.168.0.0/24 +; whitelist=fd00::/16 + ; Disable DNS seeding for peers. By default, when btcd starts, it will use ; DNS to query for available peers to connect with. ; nodnsseed=1 diff --git a/server.go b/server.go index 70d85b2b12..a865e247b2 100644 --- a/server.go +++ b/server.go @@ -223,6 +223,7 @@ type serverPeer struct { relayMtx sync.Mutex disableRelayTx bool sentAddrs bool + isWhitelisted bool filter *bloom.Filter knownAddresses map[string]struct{} banScore connmgr.DynamicBanScore @@ -315,6 +316,11 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { if cfg.DisableBanning { return } + if sp.isWhitelisted { + peerLog.Debugf("Misbehaving whitelisted peer %s: %s", sp, reason) + return + } + warnThreshold := cfg.BanThreshold >> 1 if transient == 0 && persistent == 0 { // The score is not being increased, but a warning message is still @@ -1590,6 +1596,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { // for disconnection. func (s *server) inboundPeerConnected(conn net.Conn) { sp := newServerPeer(s, false) + sp.isWhitelisted = isWhitelisted(conn.RemoteAddr()) sp.Peer = peer.NewInboundPeer(newPeerConfig(sp)) sp.AssociateConnection(conn) go s.peerDoneHandler(sp) @@ -1609,6 +1616,7 @@ func (s *server) outboundPeerConnected(c *connmgr.ConnReq, conn net.Conn) { } sp.Peer = p sp.connReq = c + sp.isWhitelisted = isWhitelisted(conn.RemoteAddr()) sp.AssociateConnection(conn) go s.peerDoneHandler(sp) s.addrManager.Attempt(sp.NA()) @@ -2599,6 +2607,32 @@ func dynamicTickDuration(remaining time.Duration) time.Duration { return time.Hour } +// isWhitelisted returns whether the IP address is included in the whitelisted +// networks and IPs. +func isWhitelisted(addr net.Addr) bool { + if len(cfg.whitelists) == 0 { + return false + } + + host, _, err := net.SplitHostPort(addr.String()) + if err != nil { + srvrLog.Warnf("Unable to SplitHostPort on '%s': %v", addr, err) + return false + } + ip := net.ParseIP(host) + if ip == nil { + srvrLog.Warnf("Unable to parse IP '%s'", addr) + return false + } + + for _, ipnet := range cfg.whitelists { + if ipnet.Contains(ip) { + return true + } + } + return false +} + // checkpointSorter implements sort.Interface to allow a slice of checkpoints to // be sorted. type checkpointSorter []chaincfg.Checkpoint From 30d4caeac63f368f5164569d96cb0dd754f44222 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 29 Aug 2017 14:36:26 -0700 Subject: [PATCH 0015/1056] server: Simplify logic to bind listeners. The helper function parseListeners has been changed to return a slice of net.Addrs with Network() returning tcp4 or tcp6 instead of returning two slices of IPv4 and IPv6 addresses to simplify calling code. Also improves how local addresses are added to the address manager when listening on wildcard addresses. Also splits some newServer logic into new method initListeners. --- server.go | 311 +++++++++++++++++++++++++++++------------------------- 1 file changed, 165 insertions(+), 146 deletions(-) diff --git a/server.go b/server.go index a865e247b2..c2092c4433 100644 --- a/server.go +++ b/server.go @@ -93,6 +93,28 @@ func (oa *onionAddr) Network() string { // Ensure onionAddr implements the net.Addr interface. var _ net.Addr = (*onionAddr)(nil) +// onionAddr implements the net.Addr interface with two struct fields +type simpleAddr struct { + net, addr string +} + +// String returns the address. +// +// This is part of the net.Addr interface. +func (a simpleAddr) String() string { + return a.addr +} + +// Network returns the network. +// +// This is part of the net.Addr interface. +func (a simpleAddr) Network() string { + return a.net +} + +// Ensure simpleAddr implements the net.Addr interface. +var _ net.Addr = simpleAddr{} + // broadcastMsg provides the ability to house a bitcoin message to be broadcast // to all connected peers except specified excluded peers. type broadcastMsg struct { @@ -1981,28 +2003,23 @@ func (s *server) ScheduleShutdown(duration time.Duration) { }() } -// parseListeners splits the list of listen addresses passed in addrs into -// IPv4 and IPv6 slices and returns them. This allows easy creation of the -// listeners on the correct interface "tcp4" and "tcp6". It also properly -// detects addresses which apply to "all interfaces" and adds the address to -// both slices. -func parseListeners(addrs []string) ([]string, []string, bool, error) { - ipv4ListenAddrs := make([]string, 0, len(addrs)*2) - ipv6ListenAddrs := make([]string, 0, len(addrs)*2) - haveWildcard := false - +// parseListeners determines whether each listen address is IPv4 and IPv6 and +// returns a slice of appropriate net.Addrs to listen on with TCP. It also +// properly detects addresses which apply to "all interfaces" and adds the +// address as both IPv4 and IPv6. +func parseListeners(addrs []string) ([]net.Addr, error) { + netAddrs := make([]net.Addr, 0, len(addrs)*2) for _, addr := range addrs { host, _, err := net.SplitHostPort(addr) if err != nil { // Shouldn't happen due to already being normalized. - return nil, nil, false, err + return nil, err } // Empty host or host of * on plan9 is both IPv4 and IPv6. if host == "" || (host == "*" && runtime.GOOS == "plan9") { - ipv4ListenAddrs = append(ipv4ListenAddrs, addr) - ipv6ListenAddrs = append(ipv6ListenAddrs, addr) - haveWildcard = true + netAddrs = append(netAddrs, simpleAddr{net: "tcp4", addr: addr}) + netAddrs = append(netAddrs, simpleAddr{net: "tcp6", addr: addr}) continue } @@ -2016,19 +2033,18 @@ func parseListeners(addrs []string) ([]string, []string, bool, error) { // Parse the IP. ip := net.ParseIP(host) if ip == nil { - return nil, nil, false, fmt.Errorf("'%s' is not a "+ - "valid IP address", host) + return nil, fmt.Errorf("'%s' is not a valid IP address", host) } // To4 returns nil when the IP is not an IPv4 address, so use // this determine the address type. if ip.To4() == nil { - ipv6ListenAddrs = append(ipv6ListenAddrs, addr) + netAddrs = append(netAddrs, simpleAddr{net: "tcp6", addr: addr}) } else { - ipv4ListenAddrs = append(ipv4ListenAddrs, addr) + netAddrs = append(netAddrs, simpleAddr{net: "tcp4", addr: addr}) } } - return ipv4ListenAddrs, ipv6ListenAddrs, haveWildcard, nil + return netAddrs, nil } func (s *server) upnpUpdateThread() { @@ -2116,24 +2132,14 @@ func setupRPCListeners() ([]net.Listener, error) { } } - // TODO: This code is similar to the peer listener code. It should be - // factored into something shared. - ipv4Addrs, ipv6Addrs, _, err := parseListeners(cfg.RPCListeners) + netAddrs, err := parseListeners(cfg.RPCListeners) if err != nil { return nil, err } - listeners := make([]net.Listener, 0, len(ipv4Addrs)+len(ipv4Addrs)) - for _, addr := range ipv4Addrs { - listener, err := listenFunc("tcp4", addr) - if err != nil { - rpcsLog.Warnf("Can't listen on %s: %v", addr, err) - continue - } - listeners = append(listeners, listener) - } - for _, addr := range ipv6Addrs { - listener, err := listenFunc("tcp6", addr) + listeners := make([]net.Listener, 0, len(netAddrs)) + for _, addr := range netAddrs { + listener, err := listenFunc(addr.Network(), addr.String()) if err != nil { rpcsLog.Warnf("Can't listen on %s: %v", addr, err) continue @@ -2158,122 +2164,11 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param var listeners []net.Listener var nat NAT if !cfg.DisableListen { - ipv4Addrs, ipv6Addrs, wildcard, err := - parseListeners(listenAddrs) + var err error + listeners, nat, err = initListeners(amgr, listenAddrs, services) if err != nil { return nil, err } - listeners = make([]net.Listener, 0, len(ipv4Addrs)+len(ipv6Addrs)) - discover := true - if len(cfg.ExternalIPs) != 0 { - discover = false - // if this fails we have real issues. - port, _ := strconv.ParseUint( - activeNetParams.DefaultPort, 10, 16) - - for _, sip := range cfg.ExternalIPs { - eport := uint16(port) - host, portstr, err := net.SplitHostPort(sip) - if err != nil { - // no port, use default. - host = sip - } else { - port, err := strconv.ParseUint( - portstr, 10, 16) - if err != nil { - srvrLog.Warnf("Can not parse "+ - "port from %s for "+ - "externalip: %v", sip, - err) - continue - } - eport = uint16(port) - } - na, err := amgr.HostToNetAddress(host, eport, - services) - if err != nil { - srvrLog.Warnf("Not adding %s as "+ - "externalip: %v", sip, err) - continue - } - - err = amgr.AddLocalAddress(na, addrmgr.ManualPrio) - if err != nil { - amgrLog.Warnf("Skipping specified external IP: %v", err) - } - } - } else if cfg.Upnp { - nat, err = Discover() - if err != nil { - srvrLog.Warnf("Can't discover upnp: %v", err) - } - // nil nat here is fine, just means no upnp on network. - } - - // TODO: nonstandard port... - if wildcard { - port, err := - strconv.ParseUint(activeNetParams.DefaultPort, - 10, 16) - if err != nil { - // I can't think of a cleaner way to do this... - goto nowc - } - addrs, err := net.InterfaceAddrs() - for _, a := range addrs { - ip, _, err := net.ParseCIDR(a.String()) - if err != nil { - continue - } - na := wire.NewNetAddressIPPort(ip, - uint16(port), services) - if discover { - err = amgr.AddLocalAddress(na, addrmgr.InterfacePrio) - if err != nil { - amgrLog.Debugf("Skipping local address: %v", err) - } - } - } - } - nowc: - - for _, addr := range ipv4Addrs { - listener, err := net.Listen("tcp4", addr) - if err != nil { - srvrLog.Warnf("Can't listen on %s: %v", addr, - err) - continue - } - listeners = append(listeners, listener) - - if discover { - if na, err := amgr.DeserializeNetAddress(addr); err == nil { - err = amgr.AddLocalAddress(na, addrmgr.BoundPrio) - if err != nil { - amgrLog.Warnf("Skipping bound address: %v", err) - } - } - } - } - - for _, addr := range ipv6Addrs { - listener, err := net.Listen("tcp6", addr) - if err != nil { - srvrLog.Warnf("Can't listen on %s: %v", addr, - err) - continue - } - listeners = append(listeners, listener) - if discover { - if na, err := amgr.DeserializeNetAddress(addr); err == nil { - err = amgr.AddLocalAddress(na, addrmgr.BoundPrio) - if err != nil { - amgrLog.Debugf("Skipping bound address: %v", err) - } - } - } - } - if len(listeners) == 0 { return nil, errors.New("no valid listen address") } @@ -2537,6 +2432,84 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param return &s, nil } +// initListeners initializes the configured net listeners and adds any bound +// addresses to the address manager. Returns the listeners and a NAT interface, +// which is non-nil if UPnP is in use. +func initListeners(amgr *addrmgr.AddrManager, listenAddrs []string, services wire.ServiceFlag) ([]net.Listener, NAT, error) { + // Listen for TCP connections at the configured addresses + netAddrs, err := parseListeners(listenAddrs) + if err != nil { + return nil, nil, err + } + + listeners := make([]net.Listener, 0, len(netAddrs)) + for _, addr := range netAddrs { + listener, err := net.Listen(addr.Network(), addr.String()) + if err != nil { + srvrLog.Warnf("Can't listen on %s: %v", addr, err) + continue + } + listeners = append(listeners, listener) + } + + var nat NAT + if len(cfg.ExternalIPs) != 0 { + defaultPort, err := strconv.ParseUint(activeNetParams.DefaultPort, 10, 16) + if err != nil { + srvrLog.Errorf("Can not parse default port %s for active chain: %v", + activeNetParams.DefaultPort, err) + return nil, nil, err + } + + for _, sip := range cfg.ExternalIPs { + eport := uint16(defaultPort) + host, portstr, err := net.SplitHostPort(sip) + if err != nil { + // no port, use default. + host = sip + } else { + port, err := strconv.ParseUint(portstr, 10, 16) + if err != nil { + srvrLog.Warnf("Can not parse port from %s for "+ + "externalip: %v", sip, err) + continue + } + eport = uint16(port) + } + na, err := amgr.HostToNetAddress(host, eport, services) + if err != nil { + srvrLog.Warnf("Not adding %s as externalip: %v", sip, err) + continue + } + + err = amgr.AddLocalAddress(na, addrmgr.ManualPrio) + if err != nil { + amgrLog.Warnf("Skipping specified external IP: %v", err) + } + } + } else { + if cfg.Upnp { + var err error + nat, err = Discover() + if err != nil { + srvrLog.Warnf("Can't discover upnp: %v", err) + } + // nil nat here is fine, just means no upnp on network. + } + + // Add bound addresses to address manager to be advertised to peers. + for _, listener := range listeners { + addr := listener.Addr().String() + err := addLocalAddress(amgr, addr, services) + if err != nil { + amgrLog.Warnf("Skipping bound address %s: %v", addr, err) + } + } + } + + return listeners, nat, nil +} + // addrStringToNetAddr takes an address in the form of 'host:port' and returns // a net.Addr which maps to the original address with any host names resolved // to IP addresses. It also handles tor addresses properly by returning a @@ -2585,6 +2558,52 @@ func addrStringToNetAddr(addr string) (net.Addr, error) { }, nil } +// addLocalAddress adds an address that this node is listening on to the +// address manager so that it may be relayed to peers. +func addLocalAddress(addrMgr *addrmgr.AddrManager, addr string, services wire.ServiceFlag) error { + host, portStr, err := net.SplitHostPort(addr) + if err != nil { + return err + } + port, err := strconv.ParseUint(portStr, 10, 16) + if err != nil { + return err + } + + if ip := net.ParseIP(host); ip != nil && ip.IsUnspecified() { + // If bound to unspecified address, advertise all local interfaces + addrs, err := net.InterfaceAddrs() + if err != nil { + return err + } + + for _, addr := range addrs { + ifaceIP, _, err := net.ParseCIDR(addr.String()) + if err != nil { + continue + } + + // If bound to 0.0.0.0, do not add IPv6 interfaces and if bound to + // ::, do not add IPv4 interfaces. + if (ip.To4() == nil) != (ifaceIP.To4() == nil) { + continue + } + + netAddr := wire.NewNetAddressIPPort(ifaceIP, uint16(port), services) + addrMgr.AddLocalAddress(netAddr, addrmgr.BoundPrio) + } + } else { + netAddr, err := addrMgr.HostToNetAddress(host, uint16(port), services) + if err != nil { + return err + } + + addrMgr.AddLocalAddress(netAddr, addrmgr.BoundPrio) + } + + return nil +} + // dynamicTickDuration is a convenience function used to dynamically choose a // tick duration based on remaining time. It is primarily used during // server shutdown to make shutdown warnings more frequent as the shutdown time From 8c883d1fcad75ca146ab6657b0640208cb1555f4 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sun, 3 Sep 2017 19:50:38 -0500 Subject: [PATCH 0016/1056] blockchain/indexers: Allow interrupts. This propagates the interrupt channel through to blockchain and the indexers so that it is possible to interrupt long-running operations such as catching up indexes. --- blockchain/chain.go | 17 +++++++++-- blockchain/indexers/addrindex.go | 4 +-- blockchain/indexers/common.go | 18 ++++++++++++ blockchain/indexers/manager.go | 48 ++++++++++++++++++++++++++------ blockchain/indexers/txindex.go | 7 +++-- btcd.go | 15 +++++----- server.go | 3 +- 7 files changed, 87 insertions(+), 25 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index f773549bf4..47289a5269 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1421,8 +1421,11 @@ func (b *BlockChain) LocateHeaders(locator BlockLocator, hashStop *chainhash.Has // purpose of supporting optional indexes. type IndexManager interface { // Init is invoked during chain initialize in order to allow the index - // manager to initialize itself and any indexes it is managing. - Init(*BlockChain) error + // manager to initialize itself and any indexes it is managing. The + // channel parameter specifies a channel the caller can close to signal + // that the process should be interrupted. It can be nil if that + // behavior is not desired. + Init(*BlockChain, <-chan struct{}) error // ConnectBlock is invoked when a new block has been connected to the // main chain. @@ -1441,6 +1444,13 @@ type Config struct { // This field is required. DB database.DB + // Interrupt specifies a channel the caller can close to signal that + // long running operations, such as catching up indexes or performing + // database migrations, should be interrupted. + // + // This field can be nil if the caller does not desire the behavior. + Interrupt <-chan struct{} + // ChainParams identifies which chain parameters the chain is associated // with. // @@ -1555,7 +1565,8 @@ func New(config *Config) (*BlockChain, error) { // Initialize and catch up all of the currently active optional indexes // as needed. if config.IndexManager != nil { - if err := config.IndexManager.Init(&b); err != nil { + err := config.IndexManager.Init(&b, config.Interrupt) + if err != nil { return nil, err } } diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 6400b120ce..d512c32f40 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -958,6 +958,6 @@ func NewAddrIndex(db database.DB, chainParams *chaincfg.Params) *AddrIndex { // DropAddrIndex drops the address index from the provided database if it // exists. -func DropAddrIndex(db database.DB) error { - return dropIndex(db, addrIndexKey, addrIndexName) +func DropAddrIndex(db database.DB, interrupt <-chan struct{}) error { + return dropIndex(db, addrIndexKey, addrIndexName, interrupt) } diff --git a/blockchain/indexers/common.go b/blockchain/indexers/common.go index be4f07afd2..9b0320dcf9 100644 --- a/blockchain/indexers/common.go +++ b/blockchain/indexers/common.go @@ -9,6 +9,7 @@ package indexers import ( "encoding/binary" + "errors" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/database" @@ -19,6 +20,10 @@ var ( // byteOrder is the preferred byte order used for serializing numeric // fields for storage in the database. byteOrder = binary.LittleEndian + + // errInterruptRequested indicates that an operation was cancelled due + // to a user-requested interrupt. + errInterruptRequested = errors.New("interrupt requested") ) // NeedsInputser provides a generic interface for an indexer to specify the it @@ -88,3 +93,16 @@ type internalBucket interface { Put(key []byte, value []byte) error Delete(key []byte) error } + +// interruptRequested returns true when the provided channel has been closed. +// This simplifies early shutdown slightly since the caller can just use an if +// statement instead of a select. +func interruptRequested(interrupted <-chan struct{}) bool { + select { + case <-interrupted: + return true + default: + } + + return false +} diff --git a/blockchain/indexers/manager.go b/blockchain/indexers/manager.go index 7de6f5f54a..cc996dd875 100644 --- a/blockchain/indexers/manager.go +++ b/blockchain/indexers/manager.go @@ -146,7 +146,7 @@ func indexDropKey(idxKey []byte) []byte { // of being dropped and finishes dropping them when the are. This is necessary // because dropping and index has to be done in several atomic steps rather than // one big atomic step due to the massive number of entries. -func (m *Manager) maybeFinishDrops() error { +func (m *Manager) maybeFinishDrops(interrupt <-chan struct{}) error { indexNeedsDrop := make([]bool, len(m.enabledIndexes)) err := m.db.View(func(dbTx database.Tx) error { // None of the indexes needs to be dropped if the index tips @@ -156,7 +156,7 @@ func (m *Manager) maybeFinishDrops() error { return nil } - // Make the indexer as requiring a drop if one is already in + // Mark the indexer as requiring a drop if one is already in // progress. for i, indexer := range m.enabledIndexes { dropKey := indexDropKey(indexer.Key()) @@ -171,6 +171,10 @@ func (m *Manager) maybeFinishDrops() error { return err } + if interruptRequested(interrupt) { + return errInterruptRequested + } + // Finish dropping any of the enabled indexes that are already in the // middle of being dropped. for i, indexer := range m.enabledIndexes { @@ -179,7 +183,7 @@ func (m *Manager) maybeFinishDrops() error { } log.Infof("Resuming %s drop", indexer.Name()) - err := dropIndex(m.db, indexer.Key(), indexer.Name()) + err := dropIndex(m.db, indexer.Key(), indexer.Name(), interrupt) if err != nil { return err } @@ -225,14 +229,18 @@ func (m *Manager) maybeCreateIndexes(dbTx database.Tx) error { // catch up due to the I/O contention. // // This is part of the blockchain.IndexManager interface. -func (m *Manager) Init(chain *blockchain.BlockChain) error { +func (m *Manager) Init(chain *blockchain.BlockChain, interrupt <-chan struct{}) error { // Nothing to do when no indexes are enabled. if len(m.enabledIndexes) == 0 { return nil } + if interruptRequested(interrupt) { + return errInterruptRequested + } + // Finish and drops that were previously interrupted. - if err := m.maybeFinishDrops(); err != nil { + if err := m.maybeFinishDrops(interrupt); err != nil { return err } @@ -308,7 +316,8 @@ func (m *Manager) Init(chain *blockchain.BlockChain) error { var view *blockchain.UtxoViewpoint if indexNeedsInputs(indexer) { var err error - view, err = makeUtxoView(dbTx, block) + view, err = makeUtxoView(dbTx, block, + interrupt) if err != nil { return err } @@ -331,6 +340,10 @@ func (m *Manager) Init(chain *blockchain.BlockChain) error { if err != nil { return err } + + if interruptRequested(interrupt) { + return errInterruptRequested + } } if initialHeight != height { @@ -389,6 +402,10 @@ func (m *Manager) Init(chain *blockchain.BlockChain) error { return err } + if interruptRequested(interrupt) { + return errInterruptRequested + } + // Connect the block for all indexes that need it. var view *blockchain.UtxoViewpoint for i, indexer := range m.enabledIndexes { @@ -405,7 +422,8 @@ func (m *Manager) Init(chain *blockchain.BlockChain) error { // index. if view == nil && indexNeedsInputs(indexer) { var err error - view, err = makeUtxoView(dbTx, block) + view, err = makeUtxoView(dbTx, block, + interrupt) if err != nil { return err } @@ -421,6 +439,10 @@ func (m *Manager) Init(chain *blockchain.BlockChain) error { // Log indexing progress. progressLogger.LogBlockHeight(block) + + if interruptRequested(interrupt) { + return errInterruptRequested + } } log.Infof("Indexes caught up to height %d", bestHeight) @@ -470,7 +492,7 @@ func dbFetchTx(dbTx database.Tx, hash *chainhash.Hash) (*wire.MsgTx, error) { // transactions in the block. This is sometimes needed when catching indexes up // because many of the txouts could actually already be spent however the // associated scripts are still required to index them. -func makeUtxoView(dbTx database.Tx, block *btcutil.Block) (*blockchain.UtxoViewpoint, error) { +func makeUtxoView(dbTx database.Tx, block *btcutil.Block, interrupt <-chan struct{}) (*blockchain.UtxoViewpoint, error) { view := blockchain.NewUtxoViewpoint() for txIdx, tx := range block.Transactions() { // Coinbases do not reference any inputs. Since the block is @@ -492,6 +514,10 @@ func makeUtxoView(dbTx database.Tx, block *btcutil.Block) (*blockchain.UtxoViewp view.AddTxOuts(btcutil.NewTx(originTx), 0) } + + if interruptRequested(interrupt) { + return nil, errInterruptRequested + } } return view, nil @@ -548,7 +574,7 @@ func NewManager(db database.DB, enabledIndexes []Indexer) *Manager { // keep memory usage to reasonable levels. It also marks the drop in progress // so the drop can be resumed if it is stopped before it is done before the // index can be used again. -func dropIndex(db database.DB, idxKey []byte, idxName string) error { +func dropIndex(db database.DB, idxKey []byte, idxName string, interrupt <-chan struct{}) error { // Nothing to do if the index doesn't already exist. var needsDelete bool err := db.View(func(dbTx database.Tx) error { @@ -610,6 +636,10 @@ func dropIndex(db database.DB, idxKey []byte, idxName string) error { log.Infof("Deleted %d keys (%d total) from %s", numDeleted, totalDeleted, idxName) } + + if interruptRequested(interrupt) { + return errInterruptRequested + } } // Call extra index specific deinitialization for the transaction index. diff --git a/blockchain/indexers/txindex.go b/blockchain/indexers/txindex.go index 6d36ac60dd..9b1826ccb5 100644 --- a/blockchain/indexers/txindex.go +++ b/blockchain/indexers/txindex.go @@ -469,10 +469,11 @@ func dropBlockIDIndex(db database.DB) error { // DropTxIndex drops the transaction index from the provided database if it // exists. Since the address index relies on it, the address index will also be // dropped when it exists. -func DropTxIndex(db database.DB) error { - if err := dropIndex(db, addrIndexKey, addrIndexName); err != nil { +func DropTxIndex(db database.DB, interrupt <-chan struct{}) error { + err := dropIndex(db, addrIndexKey, addrIndexName, interrupt) + if err != nil { return err } - return dropIndex(db, txIndexKey, txIndexName) + return dropIndex(db, txIndexKey, txIndexName, interrupt) } diff --git a/btcd.go b/btcd.go index 8d4b880249..2395974bb0 100644 --- a/btcd.go +++ b/btcd.go @@ -57,7 +57,7 @@ func btcdMain(serverChan chan<- *server) error { // Get a channel that will be closed when a shutdown signal has been // triggered either from an OS signal such as SIGINT (Ctrl+C) or from // another subsystem such as the RPC server. - interruptedChan := interruptListener() + interrupt := interruptListener() defer btcdLog.Info("Shutdown complete") // Show version at startup. @@ -94,7 +94,7 @@ func btcdMain(serverChan chan<- *server) error { } // Return now if an interrupt signal was triggered. - if interruptRequested(interruptedChan) { + if interruptRequested(interrupt) { return nil } @@ -111,7 +111,7 @@ func btcdMain(serverChan chan<- *server) error { }() // Return now if an interrupt signal was triggered. - if interruptRequested(interruptedChan) { + if interruptRequested(interrupt) { return nil } @@ -120,7 +120,7 @@ func btcdMain(serverChan chan<- *server) error { // NOTE: The order is important here because dropping the tx index also // drops the address index since it relies on it. if cfg.DropAddrIndex { - if err := indexers.DropAddrIndex(db); err != nil { + if err := indexers.DropAddrIndex(db, interrupt); err != nil { btcdLog.Errorf("%v", err) return err } @@ -128,7 +128,7 @@ func btcdMain(serverChan chan<- *server) error { return nil } if cfg.DropTxIndex { - if err := indexers.DropTxIndex(db); err != nil { + if err := indexers.DropTxIndex(db, interrupt); err != nil { btcdLog.Errorf("%v", err) return err } @@ -137,7 +137,8 @@ func btcdMain(serverChan chan<- *server) error { } // Create server and start it. - server, err := newServer(cfg.Listeners, db, activeNetParams.Params) + server, err := newServer(cfg.Listeners, db, activeNetParams.Params, + interrupt) if err != nil { // TODO: this logging could do with some beautifying. btcdLog.Errorf("Unable to start server on %v: %v", @@ -158,7 +159,7 @@ func btcdMain(serverChan chan<- *server) error { // Wait until the interrupt signal is received from an OS signal or // shutdown is requested through one of the subsystems such as the RPC // server. - <-interruptedChan + <-interrupt return nil } diff --git a/server.go b/server.go index c2092c4433..5b3c8385e8 100644 --- a/server.go +++ b/server.go @@ -2153,7 +2153,7 @@ func setupRPCListeners() ([]net.Listener, error) { // newServer returns a new btcd server configured to listen on addr for the // bitcoin network type specified by chainParams. Use start to begin accepting // connections from peers. -func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Params) (*server, error) { +func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Params, interrupt <-chan struct{}) (*server, error) { services := defaultServices if cfg.NoPeerBloomFilters { services &^= wire.SFNodeBloom @@ -2237,6 +2237,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param var err error s.chain, err = blockchain.New(&blockchain.Config{ DB: s.db, + Interrupt: interrupt, ChainParams: s.chainParams, Checkpoints: checkpoints, TimeSource: s.timeSource, From 63d1550d426726ec8dfa1997e8191ac36327c0d0 Mon Sep 17 00:00:00 2001 From: Alex Bosworth Date: Fri, 8 Sep 2017 10:56:38 -0700 Subject: [PATCH 0017/1056] txscript: Trivial typo fixes. --- txscript/hashcache_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/txscript/hashcache_test.go b/txscript/hashcache_test.go index 406bbe5084..389918e2f2 100644 --- a/txscript/hashcache_test.go +++ b/txscript/hashcache_test.go @@ -62,7 +62,7 @@ func TestHashCacheAddContainsHashes(t *testing.T) { var err error - // First, well generate 10 random transactions for use within our + // First, we'll generate 10 random transactions for use within our // tests. const numTxns = 10 txns := make([]*wire.MsgTx, numTxns) @@ -104,8 +104,8 @@ func TestHashCacheAddContainsHashes(t *testing.T) { } } -// TestHashCacheAddGet tests that the sighahes for a particular transaction -// care properly retrieved by the GetSigHashes function. +// TestHashCacheAddGet tests that the sighashes for a particular transaction +// are properly retrieved by the GetSigHashes function. func TestHashCacheAddGet(t *testing.T) { t.Parallel() @@ -170,8 +170,8 @@ func TestHashCachePurge(t *testing.T) { cache.PurgeSigHashes(&txid) } - // At this point, non of the transaction inserted into the hash cache - // should be found within the ache. + // At this point, none of the transactions inserted into the hash cache + // should be found within the cache. for _, tx := range txns { txid := tx.TxHash() if ok := cache.ContainsHashes(&txid); ok { From 91e5ba1a80082d436cc35965d74e0a41be7f2d99 Mon Sep 17 00:00:00 2001 From: Craig Sturdy Date: Mon, 11 Sep 2017 05:10:46 +0100 Subject: [PATCH 0018/1056] btcjson: Implement addwitnessaddress functionality. --- btcjson/walletsvrcmds.go | 14 ++++++++++++++ btcjson/walletsvrcmds_test.go | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index f340714bd5..6697555172 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -27,6 +27,19 @@ func NewAddMultisigAddressCmd(nRequired int, keys []string, account *string) *Ad } } +// AddWitnessAddressCmd defines the addwitnessaddress JSON-RPC command. +type AddWitnessAddressCmd struct { + Address string +} + +// NewAddWitnessAddressCmd returns a new instance which can be used to issue a +// addwitnessaddress JSON-RPC command. +func NewAddWitnessAddressCmd(address string) *AddWitnessAddressCmd { + return &AddWitnessAddressCmd{ + Address: address, + } +} + // CreateMultisigCmd defines the createmultisig JSON-RPC command. type CreateMultisigCmd struct { NRequired int @@ -645,6 +658,7 @@ func init() { flags := UFWalletOnly MustRegisterCmd("addmultisigaddress", (*AddMultisigAddressCmd)(nil), flags) + MustRegisterCmd("addwitnessaddress", (*AddWitnessAddressCmd)(nil), flags) MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags) MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags) MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index d4755cc173..efc08cc945 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -61,6 +61,19 @@ func TestWalletSvrCmds(t *testing.T) { Account: btcjson.String("test"), }, }, + { + name: "addwitnessaddress", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("addwitnessaddress", "1address") + }, + staticCmd: func() interface{} { + return btcjson.NewAddWitnessAddressCmd("1address") + }, + marshalled: `{"jsonrpc":"1.0","method":"addwitnessaddress","params":["1address"],"id":1}`, + unmarshalled: &btcjson.AddWitnessAddressCmd{ + Address: "1address", + }, + }, { name: "createmultisig", newCmd: func() (interface{}, error) { From 4803a8291c92a1d2d41041b942a9a9e37deab065 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Wed, 20 Sep 2017 13:44:35 -0400 Subject: [PATCH 0019/1056] txscript: Add API to parse atomic swap contracts. --- txscript/standard.go | 67 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/txscript/standard.go b/txscript/standard.go index 4c31506a8f..d632a0a8db 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -623,3 +623,70 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return scriptClass, addrs, requiredSigs, nil } + +// AtomicSwapDataPushes houses the data pushes found in atomic swap contracts. +type AtomicSwapDataPushes struct { + RecipientHash160 [20]byte + RefundHash160 [20]byte + SecretHash [20]byte + LockTime int64 +} + +// ExtractAtomicSwapDataPushes returns the data pushes from an atomic swap +// contract. If the script is not an atomic swap contract, +// ExtractAtomicSwapDataPushes returns (nil, nil). Non-nil errors are returned +// for unparsable scripts. +// +// NOTE: Atomic swaps are not considered standard script types by the dcrd +// mempool policy and should be used with P2SH. The atomic swap format is also +// expected to change to use a more secure hash function in the future. +// +// This function is only defined in the txscript package due to API limitations +// which prevent callers using txscript to parse nonstandard scripts. +func ExtractAtomicSwapDataPushes(pkScript []byte) (*AtomicSwapDataPushes, error) { + pops, err := parseScript(pkScript) + if err != nil { + return nil, err + } + + if len(pops) != 17 { + return nil, nil + } + isAtomicSwap := pops[0].opcode.value == OP_IF && + pops[1].opcode.value == OP_RIPEMD160 && + pops[2].opcode.value == OP_DATA_20 && + pops[3].opcode.value == OP_EQUALVERIFY && + pops[4].opcode.value == OP_DUP && + pops[5].opcode.value == OP_HASH160 && + pops[6].opcode.value == OP_DATA_20 && + pops[7].opcode.value == OP_ELSE && + canonicalPush(pops[8]) && + pops[9].opcode.value == OP_CHECKLOCKTIMEVERIFY && + pops[10].opcode.value == OP_DROP && + pops[11].opcode.value == OP_DUP && + pops[12].opcode.value == OP_HASH160 && + pops[13].opcode.value == OP_DATA_20 && + pops[14].opcode.value == OP_ENDIF && + pops[15].opcode.value == OP_EQUALVERIFY && + pops[16].opcode.value == OP_CHECKSIG + if !isAtomicSwap { + return nil, nil + } + + pushes := new(AtomicSwapDataPushes) + copy(pushes.SecretHash[:], pops[2].data) + copy(pushes.RecipientHash160[:], pops[6].data) + copy(pushes.RefundHash160[:], pops[13].data) + if pops[8].data != nil { + locktime, err := makeScriptNum(pops[8].data, true, 5) + if err != nil { + return nil, nil + } + pushes.LockTime = int64(locktime) + } else if op := pops[8].opcode; isSmallInt(op) { + pushes.LockTime = int64(asSmallInt(op)) + } else { + return nil, nil + } + return pushes, nil +} From 04444c1d0e4e0c1d979d4f8a5d7cf75366fc6609 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 14 Sep 2017 19:09:32 -0700 Subject: [PATCH 0020/1056] blockchain: Use CheckConnectBlockTemplate for RPC block proposals. This renames CheckConnectBlock to CheckConnectBlockTemplate and modifies it to be easily consumable by the getblocktemplate RPC handler. Performs full block validation now instead of partial validation. --- blockchain/error.go | 6 +++ blockchain/error_test.go | 1 + blockchain/validate.go | 61 +++++++++++++++++++--------- blockchain/validate_test.go | 81 +++++++++++++++++++++++++++++++++---- mining/mining.go | 2 +- rpcserver.go | 9 ++--- 6 files changed, 125 insertions(+), 35 deletions(-) diff --git a/blockchain/error.go b/blockchain/error.go index eb30d8aea8..0f3f2b5919 100644 --- a/blockchain/error.go +++ b/blockchain/error.go @@ -212,6 +212,11 @@ const ( // included in the block's coinbase transaction doesn't match the // manually computed witness commitment. ErrWitnessCommitmentMismatch + + // ErrPrevBlockNotBest indicates that the block's previous block is not the + // current chain tip. This is not a block validation rule, but is required + // for block proposals submitted via getblocktemplate RPC. + ErrPrevBlockNotBest ) // Map of ErrorCode values back to their constant names for pretty printing. @@ -257,6 +262,7 @@ var errorCodeStrings = map[ErrorCode]string{ ErrUnexpectedWitness: "ErrUnexpectedWitness", ErrInvalidWitnessCommitment: "ErrInvalidWitnessCommitment", ErrWitnessCommitmentMismatch: "ErrWitnessCommitmentMismatch", + ErrPrevBlockNotBest: "ErrPrevBlockNotBest", } // String returns the ErrorCode as a human-readable name. diff --git a/blockchain/error_test.go b/blockchain/error_test.go index cf740de9e3..dda8ad2660 100644 --- a/blockchain/error_test.go +++ b/blockchain/error_test.go @@ -52,6 +52,7 @@ func TestErrorCodeStringer(t *testing.T) { {ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"}, {ErrScriptMalformed, "ErrScriptMalformed"}, {ErrScriptValidation, "ErrScriptValidation"}, + {ErrPrevBlockNotBest, "ErrPrevBlockNotBest"}, {0xffff, "Unknown ErrorCode (65535)"}, } diff --git a/blockchain/validate.go b/blockchain/validate.go index 3eef85cca9..66aafb7082 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -981,14 +981,18 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo // represent the state of the chain as if the block were actually connected and // consequently the best hash for the view is also updated to passed block. // -// The CheckConnectBlock function makes use of this function to perform the -// bulk of its work. The only difference is this function accepts a node which -// may or may not require reorganization to connect it to the main chain whereas -// CheckConnectBlock creates a new node which specifically connects to the end -// of the current main chain and then calls this function with that node. +// An example of some of the checks performed are ensuring connecting the block +// would not cause any duplicate transaction hashes for old transactions that +// aren't already fully spent, double spends, exceeding the maximum allowed +// signature operations per block, invalid values in relation to the expected +// block subsidy, or fail transaction script validation. // -// See the comments for CheckConnectBlock for some examples of the type of -// checks performed by this function. +// The CheckConnectBlockTemplate function makes use of this function to perform +// the bulk of its work. The only difference is this function accepts a node +// which may or may not require reorganization to connect it to the main chain +// whereas CheckConnectBlockTemplate creates a new node which specifically +// connects to the end of the current main chain and then calls this function +// with that node. // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint, stxos *[]spentTxOut) error { @@ -1243,27 +1247,44 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi return nil } -// CheckConnectBlock performs several checks to confirm connecting the passed -// block to the main chain does not violate any rules. An example of some of -// the checks performed are ensuring connecting the block would not cause any -// duplicate transaction hashes for old transactions that aren't already fully -// spent, double spends, exceeding the maximum allowed signature operations -// per block, invalid values in relation to the expected block subsidy, or fail -// transaction script validation. +// CheckConnectBlockTemplate fully validates that connecting the passed block to +// the main chain does not violate any rules, aside from the proof of work +// requirement. The block must connect to the current tip of the main chain. // // This function is safe for concurrent access. -func (b *BlockChain) CheckConnectBlock(block *btcutil.Block) error { +func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error { b.chainLock.Lock() defer b.chainLock.Unlock() - prevNode := b.bestChain.Tip() - newNode := newBlockNode(&block.MsgBlock().Header, prevNode.height+1) - newNode.parent = prevNode - newNode.workSum.Add(prevNode.workSum, newNode.workSum) + // Skip the proof of work check as this is just a block template. + flags := BFNoPoWCheck + + // This only checks whether the block can be connected to the tip of the + // current chain. + tip := b.bestChain.Tip() + header := block.MsgBlock().Header + if tip.hash != header.PrevBlock { + str := fmt.Sprintf("previous block must be the current chain tip %v, "+ + "instead got %v", tip.hash, header.PrevBlock) + return ruleError(ErrPrevBlockNotBest, str) + } + + err := checkBlockSanity(block, b.chainParams.PowLimit, b.timeSource, flags) + if err != nil { + return err + } + + err = b.checkBlockContext(block, tip, flags) + if err != nil { + return err + } // Leave the spent txouts entry nil in the state since the information // is not needed and thus extra work can be avoided. view := NewUtxoViewpoint() - view.SetBestHash(&prevNode.hash) + view.SetBestHash(&tip.hash) + newNode := newBlockNode(&header, tip.height+1) + newNode.parent = tip + newNode.workSum = newNode.workSum.Add(tip.workSum, newNode.workSum) return b.checkConnectBlock(newNode, block, view, nil) } diff --git a/blockchain/validate_test.go b/blockchain/validate_test.go index ede4151437..2201604302 100644 --- a/blockchain/validate_test.go +++ b/blockchain/validate_test.go @@ -63,11 +63,11 @@ func TestSequenceLocksActive(t *testing.T) { } } -// TestCheckConnectBlock tests the CheckConnectBlock function to ensure it -// fails. -func TestCheckConnectBlock(t *testing.T) { +// TestCheckConnectBlock tests the CheckConnectBlockTemplate function to ensure +// it fails. +func TestCheckConnectBlockTemplate(t *testing.T) { // Create a new database and chain instance to run tests against. - chain, teardownFunc, err := chainSetup("checkconnectblock", + chain, teardownFunc, err := chainSetup("checkconnectblocktemplate", &chaincfg.MainNetParams) if err != nil { t.Errorf("Failed to setup chain instance: %v", err) @@ -75,11 +75,76 @@ func TestCheckConnectBlock(t *testing.T) { } defer teardownFunc() - // The genesis block should fail to connect since it's already inserted. - genesisBlock := chaincfg.MainNetParams.GenesisBlock - err = chain.CheckConnectBlock(btcutil.NewBlock(genesisBlock)) + // Since we're not dealing with the real block chain, set the coinbase + // maturity to 1. + chain.TstSetCoinbaseMaturity(1) + + // Load up blocks such that there is a side chain. + // (genesis block) -> 1 -> 2 -> 3 -> 4 + // \-> 3a + testFiles := []string{ + "blk_0_to_4.dat.bz2", + "blk_3A.dat.bz2", + } + + var blocks []*btcutil.Block + for _, file := range testFiles { + blockTmp, err := loadBlocks(file) + if err != nil { + t.Fatalf("Error loading file: %v\n", err) + } + blocks = append(blocks, blockTmp...) + } + + for i := 1; i <= 3; i++ { + isMainChain, _, err := chain.ProcessBlock(blocks[i], BFNone) + if err != nil { + t.Fatalf("CheckConnectBlockTemplate: Received unexpected error "+ + "processing block %d: %v", i, err) + } + if !isMainChain { + t.Fatalf("CheckConnectBlockTemplate: Expected block %d to connect "+ + "to main chain", i) + } + } + + // The block 3 should fail to connect since it's already inserted. + err = chain.CheckConnectBlockTemplate(blocks[3]) + if err == nil { + t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + + "on block 3") + } + + // Block 4 should connect successfully to tip of chain. + err = chain.CheckConnectBlockTemplate(blocks[4]) + if err != nil { + t.Fatalf("CheckConnectBlockTemplate: Received unexpected error on "+ + "block 4: %v", err) + } + + // The block 3a should fail to connect since does not build on chain tip. + err = chain.CheckConnectBlockTemplate(blocks[5]) + if err == nil { + t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + + "on block 3a") + } + + // Block 4 should connect even if proof of work is invalid. + invalidPowBlock := *blocks[4].MsgBlock() + invalidPowBlock.Header.Nonce++ + err = chain.CheckConnectBlockTemplate(btcutil.NewBlock(&invalidPowBlock)) + if err != nil { + t.Fatalf("CheckConnectBlockTemplate: Received unexpected error on "+ + "block 4 with bad nonce: %v", err) + } + + // Invalid block building on chain tip should fail to connect. + invalidBlock := *blocks[4].MsgBlock() + invalidBlock.Header.Bits-- + err = chain.CheckConnectBlockTemplate(btcutil.NewBlock(&invalidBlock)) if err == nil { - t.Errorf("CheckConnectBlock: Did not received expected error") + t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + + "on block 4 with invalid difficulty bits") } } diff --git a/mining/mining.go b/mining/mining.go index 37158940e0..09aa391f33 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -879,7 +879,7 @@ mempoolLoop: // chain with no issues. block := btcutil.NewBlock(&msgBlock) block.SetHeight(nextBlockHeight) - if err := g.chain.CheckConnectBlock(block); err != nil { + if err := g.chain.CheckConnectBlockTemplate(block); err != nil { return nil, err } diff --git a/rpcserver.go b/rpcserver.go index db4dece8ae..1033b20f63 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2040,6 +2040,8 @@ func chainErrToGBTErrString(err error) string { return "bad-script-malformed" case blockchain.ErrScriptValidation: return "bad-script-validate" + case blockchain.ErrPrevBlockNotBest: + return "inconclusive-not-best-prvblk" } return "rejected: " + err.Error() @@ -2088,9 +2090,7 @@ func handleGetBlockTemplateProposal(s *rpcServer, request *btcjson.TemplateReque return "bad-prevblk", nil } - flags := blockchain.BFDryRun | blockchain.BFNoPoWCheck - isOrphan, err := s.cfg.SyncMgr.SubmitBlock(block, flags) - if err != nil { + if err := s.cfg.Chain.CheckConnectBlockTemplate(block); err != nil { if _, ok := err.(blockchain.RuleError); !ok { errStr := fmt.Sprintf("Failed to process block proposal: %v", err) rpcsLog.Error(errStr) @@ -2103,9 +2103,6 @@ func handleGetBlockTemplateProposal(s *rpcServer, request *btcjson.TemplateReque rpcsLog.Infof("Rejected block proposal: %v", err) return chainErrToGBTErrString(err), nil } - if isOrphan { - return "orphan", nil - } return nil, nil } From 64d60f2ef245fc7a5ea6de22c8368fa699f26f8c Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 14 Sep 2017 20:35:11 -0700 Subject: [PATCH 0021/1056] blockchain: Remove BFDryRun behaviour flag. This was only used to test block proposals, which has been changed to instead use CheckConnectBlockTemplate. The flag complicated the implementation of some chain processing routines and would be difficult to implement with headers-first syncing. --- blockchain/accept.go | 21 +++------------------ blockchain/chain.go | 32 +++----------------------------- blockchain/process.go | 32 ++++++++++---------------------- blockchain/validate.go | 4 ++-- blockchain/validate_test.go | 8 ++++---- 5 files changed, 22 insertions(+), 75 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 5bc517b43a..a11fc94d69 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -15,17 +15,11 @@ import ( // before adding it. The block is expected to have already gone through // ProcessBlock before calling this function with it. // -// The flags modify the behavior of this function as follows: -// - BFDryRun: The block index will not be updated and no accept notification -// will be sent since the block is not being accepted. -// // The flags are also passed to checkBlockContext and connectBestChain. See // their documentation for how the flags modify their behavior. // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) (bool, error) { - dryRun := flags&BFDryRun == BFDryRun - // The height of this block is one more than the referenced previous // block. blockHeight := int32(0) @@ -69,13 +63,6 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) } b.index.AddNode(newNode) - // Undo changes to the block index when running in dry run mode. - if dryRun { - defer func() { - b.index.RemoveNode(newNode) - }() - } - // Connect the passed block to the chain while respecting proper chain // selection according to the chain with the most proof of work. This // also handles validation of the transaction scripts. @@ -87,11 +74,9 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) // Notify the caller that the new block was accepted into the block // chain. The caller would typically want to react by relaying the // inventory to other peers. - if !dryRun { - b.chainLock.Unlock() - b.sendNotification(NTBlockAccepted, block) - b.chainLock.Lock() - } + b.chainLock.Unlock() + b.sendNotification(NTBlockAccepted, block) + b.chainLock.Lock() return isMainChain, nil } diff --git a/blockchain/chain.go b/blockchain/chain.go index 47289a5269..e14056583c 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -785,12 +785,8 @@ func countSpentOutputs(block *btcutil.Block) int { // the chain) and nodes the are being attached must be in forwards order // (think pushing them onto the end of the chain). // -// The flags modify the behavior of this function as follows: -// - BFDryRun: Only the checks which ensure the reorganize can be completed -// successfully are performed. The chain is not reorganized. -// // This function MUST be called with the chain state lock held (for writes). -func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List, flags BehaviorFlags) error { +func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error { // All of the blocks to detach and related spend journal entries needed // to unspend transaction outputs in the blocks being disconnected must // be loaded from the database during the reorg check phase below and @@ -883,12 +879,6 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List, flags } } - // Skip disconnecting and connecting the blocks when running with the - // dry run flag set. - if flags&BFDryRun == BFDryRun { - return nil - } - // Reset the view for the actual connection code below. This is // required because the view was previously modified when checking if // the reorg would be successful and the connection code requires the @@ -976,13 +966,10 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List, flags // The flags modify the behavior of this function as follows: // - BFFastAdd: Avoids several expensive transaction validation operations. // This is useful when using checkpoints. -// - BFDryRun: Prevents the block from actually being connected and avoids any -// log messages related to modifying the state. // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) { fastAdd := flags&BFFastAdd == BFFastAdd - dryRun := flags&BFDryRun == BFDryRun // We are extending the main (best) chain with a new block. This is the // most common case. @@ -1001,11 +988,6 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla } } - // Don't connect the block if performing a dry run. - if dryRun { - return true, nil - } - // In the fast add case the code to check the block connection // was skipped, so the utxo view needs to load the referenced // utxos, spend them, and add the new utxos being created by @@ -1037,11 +1019,6 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // We're extending (or creating) a side chain, but the cumulative // work for this new side chain is not enough to make it the new chain. if node.workSum.Cmp(b.bestChain.Tip().workSum) <= 0 { - // Skip Logging info when the dry run flag is set. - if dryRun { - return false, nil - } - // Log information about how the block is forking the chain. fork := b.bestChain.FindFork(node) if fork.hash.IsEqual(parentHash) { @@ -1067,11 +1044,8 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla detachNodes, attachNodes := b.getReorganizeNodes(node) // Reorganize the chain. - if !dryRun { - log.Infof("REORGANIZE: Block %v is causing a reorganize.", - node.hash) - } - err := b.reorganizeChain(detachNodes, attachNodes, flags) + log.Infof("REORGANIZE: Block %v is causing a reorganize.", node.hash) + err := b.reorganizeChain(detachNodes, attachNodes) if err != nil { return false, err } diff --git a/blockchain/process.go b/blockchain/process.go index fa438a8e60..6d2161bb95 100644 --- a/blockchain/process.go +++ b/blockchain/process.go @@ -29,11 +29,6 @@ const ( // not be performed. BFNoPoWCheck - // BFDryRun may be set to indicate the block should not modify the chain - // or memory chain index. This is useful to test that a block is valid - // without modifying the current state. - BFDryRun - // BFNone is a convenience value to specifically indicate no flags. BFNone BehaviorFlags = 0 ) @@ -149,7 +144,6 @@ func (b *BlockChain) ProcessBlock(block *btcutil.Block, flags BehaviorFlags) (bo defer b.chainLock.Unlock() fastAdd := flags&BFFastAdd == BFFastAdd - dryRun := flags&BFDryRun == BFDryRun blockHash := block.Hash() log.Tracef("Processing block %v", blockHash) @@ -223,11 +217,8 @@ func (b *BlockChain) ProcessBlock(block *btcutil.Block, flags BehaviorFlags) (bo return false, false, err } if !prevHashExists { - if !dryRun { - log.Infof("Adding orphan block %v with parent %v", - blockHash, prevHash) - b.addOrphanBlock(block) - } + log.Infof("Adding orphan block %v with parent %v", blockHash, prevHash) + b.addOrphanBlock(block) return false, true, nil } @@ -239,18 +230,15 @@ func (b *BlockChain) ProcessBlock(block *btcutil.Block, flags BehaviorFlags) (bo return false, false, err } - // Don't process any orphans or log when the dry run flag is set. - if !dryRun { - // Accept any orphan blocks that depend on this block (they are - // no longer orphans) and repeat for those accepted blocks until - // there are no more. - err := b.processOrphans(blockHash, flags) - if err != nil { - return false, false, err - } - - log.Debugf("Accepted block %v", blockHash) + // Accept any orphan blocks that depend on this block (they are + // no longer orphans) and repeat for those accepted blocks until + // there are no more. + err = b.processOrphans(blockHash, flags) + if err != nil { + return false, false, err } + log.Debugf("Accepted block %v", blockHash) + return isMainChain, false, nil } diff --git a/blockchain/validate.go b/blockchain/validate.go index 66aafb7082..ba20d7b374 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -1248,8 +1248,8 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi } // CheckConnectBlockTemplate fully validates that connecting the passed block to -// the main chain does not violate any rules, aside from the proof of work -// requirement. The block must connect to the current tip of the main chain. +// the main chain does not violate any consensus rules, aside from the proof of +// work requirement. The block must connect to the current tip of the main chain. // // This function is safe for concurrent access. func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error { diff --git a/blockchain/validate_test.go b/blockchain/validate_test.go index 2201604302..9bf2ff42e8 100644 --- a/blockchain/validate_test.go +++ b/blockchain/validate_test.go @@ -63,8 +63,8 @@ func TestSequenceLocksActive(t *testing.T) { } } -// TestCheckConnectBlock tests the CheckConnectBlockTemplate function to ensure -// it fails. +// TestCheckConnectBlockTemplate tests the CheckConnectBlockTemplate function to +// ensure it fails. func TestCheckConnectBlockTemplate(t *testing.T) { // Create a new database and chain instance to run tests against. chain, teardownFunc, err := chainSetup("checkconnectblocktemplate", @@ -108,7 +108,7 @@ func TestCheckConnectBlockTemplate(t *testing.T) { } } - // The block 3 should fail to connect since it's already inserted. + // Block 3 should fail to connect since it's already inserted. err = chain.CheckConnectBlockTemplate(blocks[3]) if err == nil { t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + @@ -122,7 +122,7 @@ func TestCheckConnectBlockTemplate(t *testing.T) { "block 4: %v", err) } - // The block 3a should fail to connect since does not build on chain tip. + // Block 3a should fail to connect since does not build on chain tip. err = chain.CheckConnectBlockTemplate(blocks[5]) if err == nil { t.Fatal("CheckConnectBlockTemplate: Did not received expected error " + From 79445fbd97024a259f0dbd2b3d02a10073d9d146 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Thu, 21 Sep 2017 00:00:49 +0200 Subject: [PATCH 0022/1056] btcec: Prevent static initialization of S256 This is achieved by introducing a new variable `halfOrder` on the KoblitzCurve struct that is half the order. --- btcec/btcec.go | 8 +++++--- btcec/signature.go | 13 +++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/btcec/btcec.go b/btcec/btcec.go index fe8ff9011c..5e7ce875fd 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -36,8 +36,9 @@ var ( // interface from crypto/elliptic. type KoblitzCurve struct { *elliptic.CurveParams - q *big.Int - H int // cofactor of the curve. + q *big.Int + H int // cofactor of the curve. + halfOrder *big.Int // half the order N // byteSize is simply the bit size / 8 and is provided for convenience // since it is calculated repeatedly. @@ -912,9 +913,10 @@ func initS256() { secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") secp256k1.BitSize = 256 - secp256k1.H = 1 secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P, big.NewInt(1)), big.NewInt(4)) + secp256k1.H = 1 + secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1) // Provided for convenience since this gets computed repeatedly. secp256k1.byteSize = secp256k1.BitSize / 8 diff --git a/btcec/signature.go b/btcec/signature.go index 21826f22be..4392ab41a2 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -29,10 +29,6 @@ type Signature struct { } var ( - // Curve order and halforder, used to tame ECDSA malleability (see BIP-0062) - order = new(big.Int).Set(S256().N) - halforder = new(big.Int).Rsh(order, 1) - // Used in RFC6979 implementation when testing the nonce for correctness one = big.NewInt(1) @@ -51,8 +47,8 @@ var ( func (sig *Signature) Serialize() []byte { // low 'S' malleability breaker sigS := sig.S - if sigS.Cmp(halforder) == 1 { - sigS = new(big.Int).Sub(order, sigS) + if sigS.Cmp(S256().halfOrder) == 1 { + sigS = new(big.Int).Sub(S256().N, sigS) } // Ensure the encoded bytes for the r and s values are canonical and // thus suitable for DER encoding. @@ -420,7 +416,8 @@ func RecoverCompact(curve *KoblitzCurve, signature, func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { privkey := privateKey.ToECDSA() - N := order + N := S256().N + halfOrder := S256().halfOrder k := nonceRFC6979(privkey.D, hash) inv := new(big.Int).ModInverse(k, N) r, _ := privkey.Curve.ScalarBaseMult(k.Bytes()) @@ -438,7 +435,7 @@ func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { s.Mul(s, inv) s.Mod(s, N) - if s.Cmp(halforder) == 1 { + if s.Cmp(halfOrder) == 1 { s.Sub(N, s) } if s.Sign() == 0 { From fb43a179cb37713cb19f93c9b62d436385edbc87 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Thu, 21 Sep 2017 23:07:44 +0200 Subject: [PATCH 0023/1056] btcec: Add case to signature serialization test It adds the case where the S value of the signature is bigger than the half of the order of the curve. --- btcec/signature_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/btcec/signature_test.go b/btcec/signature_test.go index 2ec05d3be6..a8b3e1e98c 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -417,6 +417,24 @@ func TestSignatureSerialize(t *testing.T) { 0x2e, 0xdd, 0xc2, 0x1c, 0x14, 0x15, 0xac, }, }, + { + "valid 4 - s is bigger than half order", + &Signature{ + R: fromHex("a196ed0e7ebcbe7b63fe1d8eecbdbde03a67ceba4fc8f6482bdcb9606a911404"), + S: fromHex("971729c7fa944b465b35250c6570a2f31acbb14b13d1565fab7330dcb2b3dfb1"), + }, + []byte{ + 0x30, 0x45, 0x02, 0x21, 0x00, 0xa1, 0x96, 0xed, + 0x0e, 0x7e, 0xbc, 0xbe, 0x7b, 0x63, 0xfe, 0x1d, + 0x8e, 0xec, 0xbd, 0xbd, 0xe0, 0x3a, 0x67, 0xce, + 0xba, 0x4f, 0xc8, 0xf6, 0x48, 0x2b, 0xdc, 0xb9, + 0x60, 0x6a, 0x91, 0x14, 0x04, 0x02, 0x20, 0x68, + 0xe8, 0xd6, 0x38, 0x05, 0x6b, 0xb4, 0xb9, 0xa4, + 0xca, 0xda, 0xf3, 0x9a, 0x8f, 0x5d, 0x0b, 0x9f, + 0xe3, 0x2b, 0x9b, 0x9b, 0x77, 0x49, 0xdc, 0x14, + 0x5f, 0x2d, 0xb0, 0x1d, 0x82, 0x61, 0x90, + }, + }, { "zero signature", &Signature{ From 11d7cae82bd51ebcd11d20d72c881868ce87f2c9 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Fri, 29 Sep 2017 14:36:37 -0700 Subject: [PATCH 0024/1056] rpctest: Compile current version of btcd and run that. Previously, rpctest would start a btcd node using the btcd executable in the environment PATH. This caused difficult-to-find issues where the code would be tested against an older version of btcd, or another fork entirely. Now it compiles btcd the first time it is needed and uses that fresh version when launching nodes. --- integration/rpctest/btcd.go | 73 ++++++++++++++++++++++++++++++ integration/rpctest/node.go | 14 ++++-- integration/rpctest/rpc_harness.go | 14 +++++- 3 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 integration/rpctest/btcd.go diff --git a/integration/rpctest/btcd.go b/integration/rpctest/btcd.go new file mode 100644 index 0000000000..3c87519737 --- /dev/null +++ b/integration/rpctest/btcd.go @@ -0,0 +1,73 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package rpctest + +import ( + "fmt" + "go/build" + "os/exec" + "path/filepath" + "runtime" + "sync" +) + +var ( + // compileMtx guards access to the executable path so that the project is + // only compiled once. + compileMtx sync.Mutex + + // executablePath is the path to the compiled executable. This is the empty + // string until btcd is compiled. This should not be accessed directly; + // instead use the function btcdExecutablePath(). + executablePath string +) + +// btcdExecutablePath returns a path to the btcd executable to be used by +// rpctests. To ensure the code tests against the most up-to-date version of +// btcd, this method compiles btcd the first time it is called. After that, the +// generated binary is used for subsequent test harnesses. The executable file +// is not cleaned up, but since it lives at a static path in a temp directory, +// it is not a big deal. +func btcdExecutablePath() (string, error) { + compileMtx.Lock() + defer compileMtx.Unlock() + + // If btcd has already been compiled, just use that. + if len(executablePath) != 0 { + return executablePath, nil + } + + testDir, err := baseDir() + if err != nil { + return "", err + } + + // Determine import path of this package. Not necessarily btcsuite/btcd if + // this is a forked repo. + _, rpctestDir, _, ok := runtime.Caller(1) + if !ok { + return "", fmt.Errorf("Cannot get path to btcd source code") + } + btcdPkgPath := filepath.Join(rpctestDir, "..", "..", "..") + btcdPkg, err := build.ImportDir(btcdPkgPath, build.FindOnly) + if err != nil { + return "", fmt.Errorf("Failed to build btcd: %v", err) + } + + // Build btcd and output an executable in a static temp path. + outputPath := filepath.Join(testDir, "btcd") + if runtime.GOOS == "windows" { + outputPath += ".exe" + } + cmd := exec.Command("go", "build", "-o", outputPath, btcdPkg.ImportPath) + err = cmd.Run() + if err != nil { + return "", fmt.Errorf("Failed to build btcd: %v", err) + } + + // Save executable path so future calls do not recompile. + executablePath = outputPath + return executablePath, nil +} diff --git a/integration/rpctest/node.go b/integration/rpctest/node.go index f56a088aad..4d224130a8 100644 --- a/integration/rpctest/node.go +++ b/integration/rpctest/node.go @@ -42,6 +42,11 @@ type nodeConfig struct { // newConfig returns a newConfig with all default values. func newConfig(prefix, certFile, keyFile string, extra []string) (*nodeConfig, error) { + btcdPath, err := btcdExecutablePath() + if err != nil { + return nil, err + } + a := &nodeConfig{ listen: "127.0.0.1:18555", rpcListen: "127.0.0.1:18556", @@ -49,11 +54,10 @@ func newConfig(prefix, certFile, keyFile string, extra []string) (*nodeConfig, e rpcPass: "pass", extra: extra, prefix: prefix, - - exe: "btcd", - endpoint: "ws", - certFile: certFile, - keyFile: keyFile, + exe: btcdPath, + endpoint: "ws", + certFile: certFile, + keyFile: keyFile, } if err := a.setDefaults(); err != nil { return nil, err diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 145c293885..653a378298 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -119,8 +119,13 @@ func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers, "of the supported chain networks") } + testDir, err := baseDir() + if err != nil { + return nil, err + } + harnessID := strconv.Itoa(numTestInstances) - nodeTestData, err := ioutil.TempDir("", "rpctest-"+harnessID) + nodeTestData, err := ioutil.TempDir(testDir, "harness-"+harnessID) if err != nil { return nil, err } @@ -453,3 +458,10 @@ func generateListeningAddresses() (string, string) { rpc := net.JoinHostPort(localhost, portString(minRPCPort, maxRPCPort)) return p2p, rpc } + +// baseDir is the directory path of the temp directory for all rpctest files. +func baseDir() (string, error) { + dirPath := filepath.Join(os.TempDir(), "btcd", "rpctest") + err := os.MkdirAll(dirPath, 0755) + return dirPath, err +} From e1ef2f899b61dfbf703c7ff33f4e9feea8dea75c Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 5 Sep 2017 20:42:54 -0700 Subject: [PATCH 0025/1056] blockchain: Track block validation status in block index. Each node in the block index records some flags about its validation state. This is just stored in memory for now, but can save effort if attempting to reconnect a block that failed validation or was disconnected. --- blockchain/accept.go | 17 +++++++--- blockchain/blockindex.go | 40 +++++++++++++++++++++++ blockchain/chain.go | 69 ++++++++++++++++++++++++++++++++++++++-- blockchain/chainio.go | 2 ++ blockchain/error.go | 14 +++++--- blockchain/error_test.go | 7 +++- blockchain/validate.go | 21 ++++-------- rpcserver.go | 16 ++++++++-- 8 files changed, 156 insertions(+), 30 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index a11fc94d69..897c4ddbff 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -5,6 +5,8 @@ package blockchain import ( + "fmt" + "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" ) @@ -22,11 +24,17 @@ import ( func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) (bool, error) { // The height of this block is one more than the referenced previous // block. - blockHeight := int32(0) - prevNode := b.index.LookupNode(&block.MsgBlock().Header.PrevBlock) - if prevNode != nil { - blockHeight = prevNode.height + 1 + prevHash := &block.MsgBlock().Header.PrevBlock + prevNode := b.index.LookupNode(prevHash) + if prevNode == nil { + str := fmt.Sprintf("previous block %s is unknown", prevHash) + return false, ruleError(ErrPreviousBlockUnknown, str) + } else if prevNode.KnownInvalid() { + str := fmt.Sprintf("previous block %s is known to be invalid", prevHash) + return false, ruleError(ErrInvalidAncestorBlock, str) } + + blockHeight := prevNode.height + 1 block.SetHeight(blockHeight) // The block must pass all of the validation rules which depend on the @@ -56,6 +64,7 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) // block chain (could be either a side chain or the main chain). blockHeader := &block.MsgBlock().Header newNode := newBlockNode(blockHeader, blockHeight) + newNode.status |= statusDataStored if prevNode != nil { newNode.parent = prevNode newNode.height = blockHeight diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 63d021d8db..8fa1fb99ec 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -16,6 +16,29 @@ import ( "github.com/btcsuite/btcd/wire" ) +// blockStatus is a bit field representing the validation state of the block. +type blockStatus byte + +const ( + // statusDataStored indicates that the block's payload is stored on disk. + statusDataStored blockStatus = 1 << iota + + // statusValid indicates that the block has been fully validated. + statusValid + + // statusValidateFailed indicates that the block has failed validation. + statusValidateFailed + + // statusInvalidAncestor indicates that one of the block's ancestors has + // has failed validation, thus the block is also invalid. + statusInvalidAncestor + + // statusNone indicates that the block has no validation state flags set. + // + // NOTE: This must be defined last in order to avoid influencing iota. + statusNone blockStatus = 0 +) + // blockNode represents a block within the block chain and is primarily used to // aid in selecting the best chain to be the main chain. The main chain is // stored into the block database. @@ -49,6 +72,9 @@ type blockNode struct { nonce uint32 timestamp int64 merkleRoot chainhash.Hash + + // status is a bitfield representing the validation state of the block + status blockStatus } // initBlockNode initializes a block node from the given header and height. The @@ -167,6 +193,20 @@ func (node *blockNode) CalcPastMedianTime() time.Time { return time.Unix(medianTimestamp, 0) } +// KnownValid returns whether the block is known to be valid. This will return +// false for a valid block that has not been fully validated yet. +func (node *blockNode) KnownValid() bool { + return node.status&statusValid != 0 +} + +// KnownInvalid returns whether the block is known to be invalid. This may be +// because the block itself failed validation or any of its ancestors is +// invalid. This will return false for invalid blocks that have not been proven +// invalid yet. +func (node *blockNode) KnownInvalid() bool { + return node.status&(statusValidateFailed|statusInvalidAncestor) != 0 +} + // blockIndex provides facilities for keeping track of an in-memory index of the // block chain. Although the name block chain suggests a single chain of // blocks, it is actually a tree-shaped structure where any node can have diff --git a/blockchain/chain.go b/blockchain/chain.go index e14056583c..83bfe883f0 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -497,10 +497,14 @@ func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 { // // This function MUST be called with the chain state lock held (for reads). func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List) { - // Nothing to detach or attach if there is no node. attachNodes := list.New() detachNodes := list.New() - if node == nil { + + // Do not reorganize to a known invalid chain. Ancestors deeper than the + // direct parent are checked below but this is a quick check before doing + // more unnecessary work. + if node.parent.KnownInvalid() { + node.status |= statusInvalidAncestor return detachNodes, attachNodes } @@ -509,10 +513,27 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List // so they are attached in the appropriate order when iterating the list // later. forkNode := b.bestChain.FindFork(node) + invalidChain := false for n := node; n != nil && n != forkNode; n = n.parent { + if n.KnownInvalid() { + invalidChain = true + break + } attachNodes.PushFront(n) } + // If any of the node's ancestors are invalid, unwind attachNodes, marking + // each one as invalid for future reference. + if invalidChain { + var next *list.Element + for e := attachNodes.Front(); e != nil; e = next { + next = e.Next() + n := attachNodes.Remove(e).(*blockNode) + n.status |= statusInvalidAncestor + } + return detachNodes, attachNodes + } + // Start from the end of the main chain and work backwards until the // common ancestor adding each block to the list of nodes to detach from // the main chain. @@ -854,8 +875,17 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // at least a couple of ways accomplish that rollback, but both involve // tweaking the chain and/or database. This approach catches these // issues before ever modifying the chain. + var validationError error for e := attachNodes.Front(); e != nil; e = e.Next() { n := e.Value.(*blockNode) + + // If any previous nodes in attachNodes failed validation, + // mark this one as having an invalid ancestor. + if validationError != nil { + n.status |= statusInvalidAncestor + continue + } + var block *btcutil.Block err := b.db.View(func(dbTx database.Tx) error { var err error @@ -869,14 +899,42 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Store the loaded block for later. attachBlocks = append(attachBlocks, block) + // Skip checks if node has already been fully validated. Although + // checkConnectBlock gets skipped, we still need to update the UTXO + // view. + if n.KnownValid() { + err = view.fetchInputUtxos(b.db, block) + if err != nil { + return err + } + err = view.connectTransactions(block, nil) + if err != nil { + return err + } + continue + } + // Notice the spent txout details are not requested here and // thus will not be generated. This is done because the state // is not being immediately written to the database, so it is // not needed. err = b.checkConnectBlock(n, block, view, nil) if err != nil { + // If the block failed validation mark it as invalid, then + // continue to loop through remaining nodes, marking them as + // having an invalid ancestor. + if _, ok := err.(RuleError); ok { + n.status |= statusValidateFailed + validationError = err + continue + } return err } + n.status |= statusValid + } + + if validationError != nil { + return validationError } // Reset the view for the actual connection code below. This is @@ -975,6 +1033,9 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // most common case. parentHash := &block.MsgBlock().Header.PrevBlock if parentHash.IsEqual(&b.bestChain.Tip().hash) { + // Skip checks if node has already been fully validated. + fastAdd = fastAdd || node.KnownValid() + // Perform several checks to verify the block can be connected // to the main chain without violating any rules and without // actually connecting the block. @@ -984,8 +1045,12 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla if !fastAdd { err := b.checkConnectBlock(node, block, view, &stxos) if err != nil { + if _, ok := err.(RuleError); ok { + node.status |= statusValidateFailed + } return false, err } + node.status |= statusValid } // In the fast add case the code to check the block connection diff --git a/blockchain/chainio.go b/blockchain/chainio.go index e4c95666c0..70277edf35 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1060,6 +1060,7 @@ func (b *BlockChain) createChainState() error { genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock) header := &genesisBlock.MsgBlock().Header node := newBlockNode(header, 0) + node.status |= statusDataStored | statusValid b.bestChain.SetTip(node) // Add the new node to the index which is used for faster lookups. @@ -1164,6 +1165,7 @@ func (b *BlockChain) initChainState() error { // and add it to the block index. node := &blockNodes[height] initBlockNode(node, header, height) + node.status |= statusDataStored | statusValid if tip != nil { node.parent = tip node.workSum = node.workSum.Add(tip.workSum, diff --git a/blockchain/error.go b/blockchain/error.go index 0f3f2b5919..1e7c879ba0 100644 --- a/blockchain/error.go +++ b/blockchain/error.go @@ -99,10 +99,6 @@ const ( // transaction. ErrNoTransactions - // ErrTooManyTransactions indicates the block has more transactions than - // are allowed. - ErrTooManyTransactions - // ErrNoTxInputs indicates a transaction does not have any inputs. A // valid transaction must have at least one input. ErrNoTxInputs @@ -213,6 +209,13 @@ const ( // manually computed witness commitment. ErrWitnessCommitmentMismatch + // ErrPreviousBlockUnknown indicates that the previous block is not known. + ErrPreviousBlockUnknown + + // ErrInvalidAncestorBlock indicates that an ancestor of this block has + // already failed validation. + ErrInvalidAncestorBlock + // ErrPrevBlockNotBest indicates that the block's previous block is not the // current chain tip. This is not a block validation rule, but is required // for block proposals submitted via getblocktemplate RPC. @@ -236,7 +239,6 @@ var errorCodeStrings = map[ErrorCode]string{ ErrForkTooOld: "ErrForkTooOld", ErrCheckpointTimeTooOld: "ErrCheckpointTimeTooOld", ErrNoTransactions: "ErrNoTransactions", - ErrTooManyTransactions: "ErrTooManyTransactions", ErrNoTxInputs: "ErrNoTxInputs", ErrNoTxOutputs: "ErrNoTxOutputs", ErrTxTooBig: "ErrTxTooBig", @@ -262,6 +264,8 @@ var errorCodeStrings = map[ErrorCode]string{ ErrUnexpectedWitness: "ErrUnexpectedWitness", ErrInvalidWitnessCommitment: "ErrInvalidWitnessCommitment", ErrWitnessCommitmentMismatch: "ErrWitnessCommitmentMismatch", + ErrPreviousBlockUnknown: "ErrPreviousBlockUnknown", + ErrInvalidAncestorBlock: "ErrInvalidAncestorBlock", ErrPrevBlockNotBest: "ErrPrevBlockNotBest", } diff --git a/blockchain/error_test.go b/blockchain/error_test.go index dda8ad2660..c0e56ab897 100644 --- a/blockchain/error_test.go +++ b/blockchain/error_test.go @@ -16,6 +16,7 @@ func TestErrorCodeStringer(t *testing.T) { }{ {ErrDuplicateBlock, "ErrDuplicateBlock"}, {ErrBlockTooBig, "ErrBlockTooBig"}, + {ErrBlockWeightTooHigh, "ErrBlockWeightTooHigh"}, {ErrBlockVersionTooOld, "ErrBlockVersionTooOld"}, {ErrInvalidTime, "ErrInvalidTime"}, {ErrTimeTooOld, "ErrTimeTooOld"}, @@ -28,7 +29,6 @@ func TestErrorCodeStringer(t *testing.T) { {ErrForkTooOld, "ErrForkTooOld"}, {ErrCheckpointTimeTooOld, "ErrCheckpointTimeTooOld"}, {ErrNoTransactions, "ErrNoTransactions"}, - {ErrTooManyTransactions, "ErrTooManyTransactions"}, {ErrNoTxInputs, "ErrNoTxInputs"}, {ErrNoTxOutputs, "ErrNoTxOutputs"}, {ErrTxTooBig, "ErrTxTooBig"}, @@ -52,6 +52,11 @@ func TestErrorCodeStringer(t *testing.T) { {ErrBadCoinbaseHeight, "ErrBadCoinbaseHeight"}, {ErrScriptMalformed, "ErrScriptMalformed"}, {ErrScriptValidation, "ErrScriptValidation"}, + {ErrUnexpectedWitness, "ErrUnexpectedWitness"}, + {ErrInvalidWitnessCommitment, "ErrInvalidWitnessCommitment"}, + {ErrWitnessCommitmentMismatch, "ErrWitnessCommitmentMismatch"}, + {ErrPreviousBlockUnknown, "ErrPreviousBlockUnknown"}, + {ErrInvalidAncestorBlock, "ErrInvalidAncestorBlock"}, {ErrPrevBlockNotBest, "ErrPrevBlockNotBest"}, {0xffff, "Unknown ErrorCode (65535)"}, } diff --git a/blockchain/validate.go b/blockchain/validate.go index ba20d7b374..1e96604966 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -482,11 +482,12 @@ func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource Median "any transactions") } - // A block must not have more transactions than the max block payload. - if numTx > wire.MaxBlockPayload { + // A block must not have more transactions than the max block payload or + // else it is certainly over the weight limit. + if numTx > MaxBlockBaseSize { str := fmt.Sprintf("block contains too many transactions - "+ - "got %d, max %d", numTx, wire.MaxBlockPayload) - return ruleError(ErrTooManyTransactions, str) + "got %d, max %d", numTx, MaxBlockBaseSize) + return ruleError(ErrBlockTooBig, str) } // A block must not exceed the maximum allowed block payload when @@ -644,11 +645,6 @@ func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int32) error { // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode *blockNode, flags BehaviorFlags) error { - // The genesis block is valid by definition. - if prevNode == nil { - return nil - } - fastAdd := flags&BFFastAdd == BFFastAdd if !fastAdd { // Ensure the difficulty specified in the block header matches @@ -731,11 +727,6 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode, flags BehaviorFlags) error { - // The genesis block is valid by definition. - if prevNode == nil { - return nil - } - // Perform all block header related validation checks. header := &block.MsgBlock().Header err := b.checkBlockHeaderContext(header, prevNode, flags) @@ -822,7 +813,7 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode str := fmt.Sprintf("block's weight metric is "+ "too high - got %v, max %v", blockWeight, MaxBlockWeight) - return ruleError(ErrBlockVersionTooOld, str) + return ruleError(ErrBlockWeightTooHigh, str) } } } diff --git a/rpcserver.go b/rpcserver.go index 1033b20f63..0ba2c4bc53 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1969,7 +1969,9 @@ func chainErrToGBTErrString(err error) string { case blockchain.ErrDuplicateBlock: return "duplicate" case blockchain.ErrBlockTooBig: - return "bad-block-size" + return "bad-blk-length" + case blockchain.ErrBlockWeightTooHigh: + return "bad-blk-weight" case blockchain.ErrBlockVersionTooOld: return "bad-version" case blockchain.ErrInvalidTime: @@ -1994,8 +1996,6 @@ func chainErrToGBTErrString(err error) string { return "checkpoint-time-too-old" case blockchain.ErrNoTransactions: return "bad-txns-none" - case blockchain.ErrTooManyTransactions: - return "bad-txns-toomany" case blockchain.ErrNoTxInputs: return "bad-txns-noinputs" case blockchain.ErrNoTxOutputs: @@ -2040,6 +2040,16 @@ func chainErrToGBTErrString(err error) string { return "bad-script-malformed" case blockchain.ErrScriptValidation: return "bad-script-validate" + case blockchain.ErrUnexpectedWitness: + return "unexpected-witness" + case blockchain.ErrInvalidWitnessCommitment: + return "bad-witness-nonce-size" + case blockchain.ErrWitnessCommitmentMismatch: + return "bad-witness-merkle-match" + case blockchain.ErrPreviousBlockUnknown: + return "prev-blk-not-found" + case blockchain.ErrInvalidAncestorBlock: + return "bad-prevblk" case blockchain.ErrPrevBlockNotBest: return "inconclusive-not-best-prvblk" } From c7588cbf7690cd9f047a28efa2dcd8f2435a4e5e Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Fri, 13 Oct 2017 14:36:40 -0700 Subject: [PATCH 0026/1056] blockchain: NodeStatus & Set/UnsetStatusFlags methods on blockIndex. These method allows safe concurrent access to reading and modifying block node statuses. When block statuses get persisted in a later change, the setter methods can be used to mark block nodes as dirty. --- blockchain/accept.go | 4 +-- blockchain/blockindex.go | 70 ++++++++++++++++++++++++++++------------ blockchain/chain.go | 22 ++++++------- blockchain/chainio.go | 4 +-- 4 files changed, 65 insertions(+), 35 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 897c4ddbff..963a4fd061 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -29,7 +29,7 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) if prevNode == nil { str := fmt.Sprintf("previous block %s is unknown", prevHash) return false, ruleError(ErrPreviousBlockUnknown, str) - } else if prevNode.KnownInvalid() { + } else if b.index.NodeStatus(prevNode).KnownInvalid() { str := fmt.Sprintf("previous block %s is known to be invalid", prevHash) return false, ruleError(ErrInvalidAncestorBlock, str) } @@ -64,7 +64,7 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) // block chain (could be either a side chain or the main chain). blockHeader := &block.MsgBlock().Header newNode := newBlockNode(blockHeader, blockHeight) - newNode.status |= statusDataStored + newNode.status = statusDataStored if prevNode != nil { newNode.parent = prevNode newNode.height = blockHeight diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 8fa1fb99ec..642b658e60 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -39,6 +39,27 @@ const ( statusNone blockStatus = 0 ) +// HaveData returns whether the full block data is stored in the database. This +// will return false for a block node where only the header is downloaded or +// kept. +func (status blockStatus) HaveData() bool { + return status&statusDataStored != 0 +} + +// KnownValid returns whether the block is known to be valid. This will return +// false for a valid block that has not been fully validated yet. +func (status blockStatus) KnownValid() bool { + return status&statusValid != 0 +} + +// KnownInvalid returns whether the block is known to be invalid. This may be +// because the block itself failed validation or any of its ancestors is +// invalid. This will return false for invalid blocks that have not been proven +// invalid yet. +func (status blockStatus) KnownInvalid() bool { + return status&(statusValidateFailed|statusInvalidAncestor) != 0 +} + // blockNode represents a block within the block chain and is primarily used to // aid in selecting the best chain to be the main chain. The main chain is // stored into the block database. @@ -73,7 +94,10 @@ type blockNode struct { timestamp int64 merkleRoot chainhash.Hash - // status is a bitfield representing the validation state of the block + // status is a bitfield representing the validation state of the block. The + // status field, unlike the other fields, may be written to and so should + // only be accessed using the concurrent-safe NodeStatus method on + // blockIndex once the node has been added to the global index. status blockStatus } @@ -193,20 +217,6 @@ func (node *blockNode) CalcPastMedianTime() time.Time { return time.Unix(medianTimestamp, 0) } -// KnownValid returns whether the block is known to be valid. This will return -// false for a valid block that has not been fully validated yet. -func (node *blockNode) KnownValid() bool { - return node.status&statusValid != 0 -} - -// KnownInvalid returns whether the block is known to be invalid. This may be -// because the block itself failed validation or any of its ancestors is -// invalid. This will return false for invalid blocks that have not been proven -// invalid yet. -func (node *blockNode) KnownInvalid() bool { - return node.status&(statusValidateFailed|statusInvalidAncestor) != 0 -} - // blockIndex provides facilities for keeping track of an in-memory index of the // block chain. Although the name block chain suggests a single chain of // blocks, it is actually a tree-shaped structure where any node can have @@ -265,13 +275,33 @@ func (bi *blockIndex) AddNode(node *blockNode) { bi.Unlock() } -// RemoveNode removes the provided node from the block index. There is no check -// whether another node in the index depends on this one, so it is up to caller -// to avoid that situation. +// NodeStatus provides concurrent-safe access to the status field of a node. +// +// This function is safe for concurrent access. +func (bi *blockIndex) NodeStatus(node *blockNode) blockStatus { + bi.RLock() + status := node.status + bi.RUnlock() + return status +} + +// SetStatusFlags flips the provided status flags on the block node to on, +// regardless of whether they were on or off previously. This does not unset any +// flags currently on. +// +// This function is safe for concurrent access. +func (bi *blockIndex) SetStatusFlags(node *blockNode, flags blockStatus) { + bi.Lock() + node.status |= flags + bi.Unlock() +} + +// UnsetStatusFlags flips the provided status flags on the block node to off, +// regardless of whether they were on or off previously. // // This function is safe for concurrent access. -func (bi *blockIndex) RemoveNode(node *blockNode) { +func (bi *blockIndex) UnsetStatusFlags(node *blockNode, flags blockStatus) { bi.Lock() - delete(bi.index, node.hash) + node.status &^= flags bi.Unlock() } diff --git a/blockchain/chain.go b/blockchain/chain.go index 83bfe883f0..bd24b1e1ac 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -503,8 +503,8 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List // Do not reorganize to a known invalid chain. Ancestors deeper than the // direct parent are checked below but this is a quick check before doing // more unnecessary work. - if node.parent.KnownInvalid() { - node.status |= statusInvalidAncestor + if b.index.NodeStatus(node.parent).KnownInvalid() { + b.index.SetStatusFlags(node, statusInvalidAncestor) return detachNodes, attachNodes } @@ -515,7 +515,7 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List forkNode := b.bestChain.FindFork(node) invalidChain := false for n := node; n != nil && n != forkNode; n = n.parent { - if n.KnownInvalid() { + if b.index.NodeStatus(n).KnownInvalid() { invalidChain = true break } @@ -529,7 +529,7 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List for e := attachNodes.Front(); e != nil; e = next { next = e.Next() n := attachNodes.Remove(e).(*blockNode) - n.status |= statusInvalidAncestor + b.index.SetStatusFlags(n, statusInvalidAncestor) } return detachNodes, attachNodes } @@ -882,7 +882,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // If any previous nodes in attachNodes failed validation, // mark this one as having an invalid ancestor. if validationError != nil { - n.status |= statusInvalidAncestor + b.index.SetStatusFlags(n, statusInvalidAncestor) continue } @@ -902,7 +902,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Skip checks if node has already been fully validated. Although // checkConnectBlock gets skipped, we still need to update the UTXO // view. - if n.KnownValid() { + if b.index.NodeStatus(n).KnownValid() { err = view.fetchInputUtxos(b.db, block) if err != nil { return err @@ -924,13 +924,13 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // continue to loop through remaining nodes, marking them as // having an invalid ancestor. if _, ok := err.(RuleError); ok { - n.status |= statusValidateFailed + b.index.SetStatusFlags(n, statusValidateFailed) validationError = err continue } return err } - n.status |= statusValid + b.index.SetStatusFlags(n, statusValid) } if validationError != nil { @@ -1034,7 +1034,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla parentHash := &block.MsgBlock().Header.PrevBlock if parentHash.IsEqual(&b.bestChain.Tip().hash) { // Skip checks if node has already been fully validated. - fastAdd = fastAdd || node.KnownValid() + fastAdd = fastAdd || b.index.NodeStatus(node).KnownValid() // Perform several checks to verify the block can be connected // to the main chain without violating any rules and without @@ -1046,11 +1046,11 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla err := b.checkConnectBlock(node, block, view, &stxos) if err != nil { if _, ok := err.(RuleError); ok { - node.status |= statusValidateFailed + b.index.SetStatusFlags(node, statusValidateFailed) } return false, err } - node.status |= statusValid + b.index.SetStatusFlags(node, statusValid) } // In the fast add case the code to check the block connection diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 70277edf35..6c629c6055 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1060,7 +1060,7 @@ func (b *BlockChain) createChainState() error { genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock) header := &genesisBlock.MsgBlock().Header node := newBlockNode(header, 0) - node.status |= statusDataStored | statusValid + node.status = statusDataStored | statusValid b.bestChain.SetTip(node) // Add the new node to the index which is used for faster lookups. @@ -1165,7 +1165,7 @@ func (b *BlockChain) initChainState() error { // and add it to the block index. node := &blockNodes[height] initBlockNode(node, header, height) - node.status |= statusDataStored | statusValid + node.status = statusDataStored | statusValid if tip != nil { node.parent = tip node.workSum = node.workSum.Add(tip.workSum, From 8cea3866d0f7fb12d567a20744942c0d078c7d15 Mon Sep 17 00:00:00 2001 From: Janus Troelsen Date: Thu, 26 Oct 2017 14:26:30 +0200 Subject: [PATCH 0027/1056] Update script_test.go Typo fix --- txscript/script_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/script_test.go b/txscript/script_test.go index 501716f654..6a725e275c 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -3975,7 +3975,7 @@ func TestRemoveOpcodes(t *testing.T) { after: "CAT", }, { - name: "invalid length (insruction)", + name: "invalid length (instruction)", before: "PUSHDATA1", remove: OP_CODESEPARATOR, err: scriptError(ErrMalformedPush, ""), From 2e60448ffcc6bf78332d1fe590260095f554dd78 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 28 Nov 2017 10:02:46 -0500 Subject: [PATCH 0028/1056] txscript: Require SHA256 secret hashes for atomic swaps --- txscript/standard.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index d632a0a8db..2ba5c8d962 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -628,7 +628,7 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script type AtomicSwapDataPushes struct { RecipientHash160 [20]byte RefundHash160 [20]byte - SecretHash [20]byte + SecretHash [32]byte LockTime int64 } @@ -653,8 +653,8 @@ func ExtractAtomicSwapDataPushes(pkScript []byte) (*AtomicSwapDataPushes, error) return nil, nil } isAtomicSwap := pops[0].opcode.value == OP_IF && - pops[1].opcode.value == OP_RIPEMD160 && - pops[2].opcode.value == OP_DATA_20 && + pops[1].opcode.value == OP_SHA256 && + pops[2].opcode.value == OP_DATA_32 && pops[3].opcode.value == OP_EQUALVERIFY && pops[4].opcode.value == OP_DUP && pops[5].opcode.value == OP_HASH160 && From b6afec5e51fe44272c6eb8b9fa5ea688e2448658 Mon Sep 17 00:00:00 2001 From: Shuai Qi Date: Fri, 26 Jan 2018 12:37:50 +0800 Subject: [PATCH 0029/1056] txscript: Fix comment typo. --- txscript/engine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/engine.go b/txscript/engine.go index 3fd7d5d950..b5aef52a01 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -821,7 +821,7 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags } // The clean stack flag (ScriptVerifyCleanStack) is not allowed without - // either the the pay-to-script-hash (P2SH) evaluation (ScriptBip16) + // either the pay-to-script-hash (P2SH) evaluation (ScriptBip16) // flag or the Segregated Witness (ScriptVerifyWitness) flag. // // Recall that evaluating a P2SH script without the flag set results in From be04ac2370b497b94fbaaf5f7e5afceb6f77b344 Mon Sep 17 00:00:00 2001 From: Kamil Slowikowski Date: Thu, 25 Jan 2018 23:39:33 -0500 Subject: [PATCH 0030/1056] rpcserver: Fix typo in generate handler. "mine a block" instead of "main a block". --- rpcserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index 0ba2c4bc53..2408e5a3ec 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -868,7 +868,7 @@ func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i Code: btcjson.ErrRPCDifficulty, Message: fmt.Sprintf("No support for `generate` on "+ "the current network, %s, as it's unlikely to "+ - "be possible to main a block with the CPU.", + "be possible to mine a block with the CPU.", s.cfg.ChainParams.Net), } } From f22a07b6cfae805f8d7e13007a7628ab1117a411 Mon Sep 17 00:00:00 2001 From: Mitchell Paull Date: Thu, 25 Jan 2018 23:40:42 -0500 Subject: [PATCH 0031/1056] blockchain: Fix typos in README.md. --- blockchain/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockchain/README.md b/blockchain/README.md index 275c2b4f02..de5611bcae 100644 --- a/blockchain/README.md +++ b/blockchain/README.md @@ -63,7 +63,7 @@ is by no means exhaustive: * [ProcessBlock Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-BlockChain-ProcessBlock) Demonstrates how to create a new chain instance and use ProcessBlock to - attempt to attempt add a block to the chain. This example intentionally + attempt to add a block to the chain. This example intentionally attempts to insert a duplicate genesis block to illustrate how an invalid block is handled. @@ -73,7 +73,7 @@ is by no means exhaustive: typical hex notation. * [BigToCompact Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-BigToCompact) - Demonstrates how to convert how to convert a target difficulty into the + Demonstrates how to convert a target difficulty into the compact "bits" in a block header which represent that target difficulty. ## GPG Verification Key From 78d12c33f0ce6112457f18e148cdd4119b140941 Mon Sep 17 00:00:00 2001 From: Leonardo Lazzaro Date: Fri, 26 Jan 2018 01:43:53 -0300 Subject: [PATCH 0032/1056] database: Update rpcclient link in README.md. --- database/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/README.md b/database/README.md index ea99722365..c51c9cc66b 100644 --- a/database/README.md +++ b/database/README.md @@ -13,7 +13,7 @@ one entity can have the database open at a time (for most database backends), and that entity will be btcd. When a client wants programmatic access to the data provided by btcd, they'll -likely want to use the [btcrpcclient](https://github.com/btcsuite/btcrpcclient) +likely want to use the [rpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) package which makes use of the [JSON-RPC API](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md). However, this package could be extremely useful for any applications requiring From 16dbb2602a6097c370fac43761dcff9963f3c70a Mon Sep 17 00:00:00 2001 From: Marko Bencun Date: Sat, 18 Nov 2017 22:43:45 +0100 Subject: [PATCH 0033/1056] txscript: export calcSignatureHash This is a useful function for users of this library, and deserves to be public. --- txscript/script.go | 11 +++++++++++ txscript/sign.go | 5 ++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 1c3939b0ba..4977e961ab 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -582,6 +582,17 @@ func shallowCopyTx(tx *wire.MsgTx) wire.MsgTx { return txCopy } +// CalcSignatureHash will, given a script and hash type for the current script +// engine instance, calculate the signature hash to be used for signing and +// verification. +func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) { + parsedScript, err := parseScript(script) + if err != nil { + return nil, fmt.Errorf("cannot parse output script: %v", err) + } + return calcSignatureHash(parsedScript, hashType, tx, idx), nil +} + // calcSignatureHash will, given a script and hash type for the current script // engine instance, calculate the signature hash to be used for signing and // verification. diff --git a/txscript/sign.go b/txscript/sign.go index 09ba8d1f57..42af9686cb 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -74,11 +74,10 @@ func WitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64 func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { - parsedScript, err := parseScript(subScript) + hash, err := CalcSignatureHash(subScript, hashType, tx, idx) if err != nil { - return nil, fmt.Errorf("cannot parse output script: %v", err) + return nil, err } - hash := calcSignatureHash(parsedScript, hashType, tx, idx) signature, err := key.Sign(hash) if err != nil { return nil, fmt.Errorf("cannot sign tx input: %s", err) From 11fcd83963ab0ecd1b84b429b1efc1d2cdc6d5c5 Mon Sep 17 00:00:00 2001 From: Nicola 'tekNico' Larosa Date: Sun, 29 Oct 2017 20:56:03 +0100 Subject: [PATCH 0034/1056] btcd/multi: fix a number of typos in comments. --- CHANGES | 4 ++-- README.md | 2 +- blockchain/chainview_test.go | 2 +- blockchain/fullblocktests/README.md | 2 +- blockchain/fullblocktests/doc.go | 2 +- blockchain/indexers/addrindex.go | 4 ++-- blockchain/indexers/txindex.go | 2 +- blockchain/mediantime_test.go | 2 +- blockchain/thresholdstate.go | 2 +- blockchain/validate.go | 2 +- blockchain/weight.go | 2 +- btcd.go | 6 +++--- btcec/signature.go | 2 +- btcjson/cmdinfo_test.go | 2 +- btcjson/cmdparse.go | 2 +- btcjson/register_test.go | 2 +- btcjson/walletsvrwsntfns.go | 2 +- chaincfg/params.go | 4 ++-- integration/csv_fork_test.go | 4 ++-- mempool/README.md | 2 +- mempool/doc.go | 2 +- mempool/mempool_test.go | 2 +- mining/mining.go | 4 ++-- rpcclient/extensions.go | 2 +- rpcclient/infrastructure.go | 2 +- rpcclient/notify.go | 2 +- rpcclient/wallet.go | 4 ++-- rpcserverhelp.go | 6 +++--- sample-btcd.conf | 2 +- server.go | 2 +- txscript/script.go | 4 ++-- txscript/standard_test.go | 6 +++--- wire/common.go | 4 ++-- wire/msggetdata_test.go | 2 +- wire/msginv_test.go | 2 +- wire/msgmerkleblock_test.go | 2 +- wire/msgnotfound_test.go | 2 +- wire/msgtx.go | 2 +- 38 files changed, 52 insertions(+), 52 deletions(-) diff --git a/CHANGES b/CHANGES index 99b2fc13ff..6f7013e922 100644 --- a/CHANGES +++ b/CHANGES @@ -570,8 +570,8 @@ Changes in 0.8.0-beta (Sun May 25 2014) - btcctl utility changes: - Add createencryptedwallet command - Add getblockchaininfo command - - Add importwallet commmand - - Add addmultisigaddress commmand + - Add importwallet command + - Add addmultisigaddress command - Add setgenerate command - Accept --testnet and --wallet flags which automatically select the appropriate port and TLS certificates needed to communicate diff --git a/README.md b/README.md index 0e8152a2f5..72e73a5560 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ $ go install . ./cmd/... ## Getting Started -btcd has several configuration options avilable to tweak how it runs, but all +btcd has several configuration options available to tweak how it runs, but all of the basic operations described in the intro section work with zero configuration. diff --git a/blockchain/chainview_test.go b/blockchain/chainview_test.go index 964da607bb..760d31ab1e 100644 --- a/blockchain/chainview_test.go +++ b/blockchain/chainview_test.go @@ -74,7 +74,7 @@ func zipLocators(locators ...BlockLocator) BlockLocator { } // TestChainView ensures all of the exported functionality of chain views works -// as intended with the expection of some special cases which are handled in +// as intended with the exception of some special cases which are handled in // other tests. func TestChainView(t *testing.T) { // Construct a synthetic block index consisting of the following diff --git a/blockchain/fullblocktests/README.md b/blockchain/fullblocktests/README.md index 1caca0273e..41f4b934e9 100644 --- a/blockchain/fullblocktests/README.md +++ b/blockchain/fullblocktests/README.md @@ -15,7 +15,7 @@ independent versions over the peer-to-peer network. This package has intentionally been designed so it can be used as a standalone package for any projects needing to test their implementation against a full set -of blocks that excerise the consensus validation rules. +of blocks that exercise the consensus validation rules. ## Installation and Updating diff --git a/blockchain/fullblocktests/doc.go b/blockchain/fullblocktests/doc.go index 83b9c115ef..bfedc43d92 100644 --- a/blockchain/fullblocktests/doc.go +++ b/blockchain/fullblocktests/doc.go @@ -15,6 +15,6 @@ independent versions over the peer-to-peer network. This package has intentionally been designed so it can be used as a standalone package for any projects needing to test their implementation against a full set -of blocks that excerise the consensus validation rules. +of blocks that exercise the consensus validation rules. */ package fullblocktests diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index d512c32f40..c9fee91c5e 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -651,7 +651,7 @@ func (idx *AddrIndex) Create(dbTx database.Tx) error { } // writeIndexData represents the address index data to be written for one block. -// It consistens of the address mapped to an ordered list of the transactions +// It consists of the address mapped to an ordered list of the transactions // that involve the address in block. It is ordered so the transactions can be // stored in the order they appear in the block. type writeIndexData map[[addrKeySize]byte][]int @@ -690,7 +690,7 @@ func (idx *AddrIndex) indexPkScript(data writeIndexData, pkScript []byte, txIdx } // indexBlock extract all of the standard addresses from all of the transactions -// in the passed block and maps each of them to the assocaited transaction using +// in the passed block and maps each of them to the associated transaction using // the passed map. func (idx *AddrIndex) indexBlock(data writeIndexData, block *btcutil.Block, view *blockchain.UtxoViewpoint) { for txIdx, tx := range block.Transactions() { diff --git a/blockchain/indexers/txindex.go b/blockchain/indexers/txindex.go index 9b1826ccb5..51fad698aa 100644 --- a/blockchain/indexers/txindex.go +++ b/blockchain/indexers/txindex.go @@ -40,7 +40,7 @@ var ( // ----------------------------------------------------------------------------- // The transaction index consists of an entry for every transaction in the main -// chain. In order to significanly optimize the space requirements a separate +// chain. In order to significantly optimize the space requirements a separate // index which provides an internal mapping between each block that has been // indexed and a unique ID for use within the hash to location mappings. The ID // is simply a sequentially incremented uint32. This is useful because it is diff --git a/blockchain/mediantime_test.go b/blockchain/mediantime_test.go index f5d74a75c5..948d03105b 100644 --- a/blockchain/mediantime_test.go +++ b/blockchain/mediantime_test.go @@ -45,7 +45,7 @@ func TestMedianTime(t *testing.T) { // be ignored. {in: []int64{-4201, 4202, -4203, 4204, -4205}, wantOffset: 0}, - // Excerise the condition where the median offset is greater + // Exercise the condition where the median offset is greater // than the max allowed adjustment, but there is at least one // sample that is close enough to the current time to avoid // triggering a warning about an invalid local clock. diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index b9f39294d0..35a762552a 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -85,7 +85,7 @@ type thresholdConditionChecker interface { // Condition returns whether or not the rule change activation condition // has been met. This typically involves checking whether or not the - // bit assocaited with the condition is set, but can be more complex as + // bit associated with the condition is set, but can be more complex as // needed. Condition(*blockNode) (bool, error) } diff --git a/blockchain/validate.go b/blockchain/validate.go index 1e96604966..27f04f6e0d 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -791,7 +791,7 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode } // If segwit is active, then we'll need to fully validate the - // new witness commitment for adherance to the rules. + // new witness commitment for adherence to the rules. if segwitState == ThresholdActive { // Validate the witness commitment (if any) within the // block. This involves asserting that if the coinbase diff --git a/blockchain/weight.go b/blockchain/weight.go index 286a9197d0..80de012f50 100644 --- a/blockchain/weight.go +++ b/blockchain/weight.go @@ -27,7 +27,7 @@ const ( // MaxBlockSigOpsCost is the maximum number of signature operations // allowed for a block. It is calculated via a weighted algorithm which - // weights segragated witness sig ops lower than regular sig ops. + // weights segregated witness sig ops lower than regular sig ops. MaxBlockSigOpsCost = 80000 // WitnessScaleFactor determines the level of "discount" witness data diff --git a/btcd.go b/btcd.go index 2395974bb0..b656e1b3e3 100644 --- a/btcd.go +++ b/btcd.go @@ -202,10 +202,10 @@ func blockDbPath(dbType string) string { return dbPath } -// warnMultipeDBs shows a warning if multiple block database types are detected. +// warnMultipleDBs shows a warning if multiple block database types are detected. // This is not a situation most users want. It is handy for development however // to support multiple side-by-side databases. -func warnMultipeDBs() { +func warnMultipleDBs() { // This is intentionally not using the known db types which depend // on the database types compiled into the binary since we want to // detect legacy db types as well. @@ -253,7 +253,7 @@ func loadBlockDB() (database.DB, error) { return db, nil } - warnMultipeDBs() + warnMultipleDBs() // The database name is based on the database type. dbPath := blockDbPath(cfg.DbType) diff --git a/btcec/signature.go b/btcec/signature.go index 4392ab41a2..6026c4241f 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -269,7 +269,7 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int { return ret } -// recoverKeyFromSignature recoves a public key from the signature "sig" on the +// recoverKeyFromSignature recovers a public key from the signature "sig" on the // given message hash "msg". Based on the algorithm found in section 5.1.5 of // SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details // in the inner loop in Step 1. The counter provided is actually the j parameter diff --git a/btcjson/cmdinfo_test.go b/btcjson/cmdinfo_test.go index b3336e646f..044040279a 100644 --- a/btcjson/cmdinfo_test.go +++ b/btcjson/cmdinfo_test.go @@ -183,7 +183,7 @@ func TestMethodUsageText(t *testing.T) { continue } - // Get the usage again to excerise caching. + // Get the usage again to exercise caching. usage, err = btcjson.MethodUsageText(test.method) if err != nil { t.Errorf("Test #%d (%s) unexpected error: %v", i, diff --git a/btcjson/cmdparse.go b/btcjson/cmdparse.go index abe52e3662..48c6278a61 100644 --- a/btcjson/cmdparse.go +++ b/btcjson/cmdparse.go @@ -183,7 +183,7 @@ func typesMaybeCompatible(dest reflect.Type, src reflect.Type) bool { return true } - // When both types are numeric, they are potentially compatibile. + // When both types are numeric, they are potentially compatible. srcKind := src.Kind() destKind := dest.Kind() if isNumeric(destKind) && isNumeric(srcKind) { diff --git a/btcjson/register_test.go b/btcjson/register_test.go index 4cac9c7a86..3832678aaf 100644 --- a/btcjson/register_test.go +++ b/btcjson/register_test.go @@ -247,7 +247,7 @@ func TestMustRegisterCmdPanic(t *testing.T) { func TestRegisteredCmdMethods(t *testing.T) { t.Parallel() - // Ensure the registerd methods are returned. + // Ensure the registered methods are returned. methods := btcjson.RegisteredCmdMethods() if len(methods) == 0 { t.Fatal("RegisteredCmdMethods: no methods") diff --git a/btcjson/walletsvrwsntfns.go b/btcjson/walletsvrwsntfns.go index 26dc15089b..8df8ebe685 100644 --- a/btcjson/walletsvrwsntfns.go +++ b/btcjson/walletsvrwsntfns.go @@ -21,7 +21,7 @@ const ( WalletLockStateNtfnMethod = "walletlockstate" // NewTxNtfnMethod is the method used to notify that a wallet server has - // added a new transaction to the transaciton store. + // added a new transaction to the transaction store. NewTxNtfnMethod = "newtx" ) diff --git a/chaincfg/params.go b/chaincfg/params.go index 60c99ac3ee..38b8a37aac 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -87,12 +87,12 @@ const ( DeploymentTestDummy = iota // DeploymentCSV defines the rule change deployment ID for the CSV - // soft-fork package. The CSV package includes the depolyment of BIPS + // soft-fork package. The CSV package includes the deployment of BIPS // 68, 112, and 113. DeploymentCSV // DeploymentSegwit defines the rule change deployment ID for the - // Segragated Witness (segwit) soft-fork package. The segwit package + // Segregated Witness (segwit) soft-fork package. The segwit package // includes the deployment of BIPS 141, 142, 144, 145, 147 and 173. DeploymentSegwit diff --git a/integration/csv_fork_test.go b/integration/csv_fork_test.go index d7da7be7d6..3dd471b187 100644 --- a/integration/csv_fork_test.go +++ b/integration/csv_fork_test.go @@ -88,7 +88,7 @@ func makeTestOutput(r *rpctest.Harness, t *testing.T, return key, utxo, selfAddrScript, nil } -// TestBIP0113Activation tests for proper adherance of the BIP 113 rule +// TestBIP0113Activation tests for proper adherence of the BIP 113 rule // constraint which requires all transaction finality tests to use the MTP of // the last 11 blocks, rather than the timestamp of the block which includes // them. @@ -188,7 +188,7 @@ func TestBIP0113Activation(t *testing.T) { // At this point, the block height should be 103: we mined 101 blocks // to create a single mature output, then an additional block to create // a new output, and then mined a single block above to include our - // transation. + // transaction. assertChainHeight(r, t, 103) // Next, mine enough blocks to ensure that the soft-fork becomes diff --git a/mempool/README.md b/mempool/README.md index 7ad0a68c8d..d9b8d73b5c 100644 --- a/mempool/README.md +++ b/mempool/README.md @@ -18,7 +18,7 @@ further filtered based upon a configurable policy. One of the policy configuration options controls whether or not "standard" transactions are accepted. In essence, a "standard" transaction is one that -satisfies a fairly strict set of requirements that are largley intended to help +satisfies a fairly strict set of requirements that are largely intended to help provide fair use of the system to all users. It is important to note that what is considered a "standard" transaction changes over time. For some insight, at the time of this writing, an example of _some_ of the criteria that are required diff --git a/mempool/doc.go b/mempool/doc.go index 9bd9f41f7c..3adad018ba 100644 --- a/mempool/doc.go +++ b/mempool/doc.go @@ -16,7 +16,7 @@ further filtered based upon a configurable policy. One of the policy configuration options controls whether or not "standard" transactions are accepted. In essence, a "standard" transaction is one that -satisfies a fairly strict set of requirements that are largley intended to help +satisfies a fairly strict set of requirements that are largely intended to help provide fair use of the system to all users. It is important to note that what is considered a "standard" transaction changes over time. For some insight, at the time of this writing, an example of SOME of the criteria that are required diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index c557d61f6e..6354126637 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -23,7 +23,7 @@ import ( // fakeChain is used by the pool harness to provide generated test utxos and // a current faked chain height to the pool callbacks. This, in turn, allows -// transations to be appear as though they are spending completely valid utxos. +// transactions to appear as though they are spending completely valid utxos. type fakeChain struct { sync.RWMutex utxos *blockchain.UtxoViewpoint diff --git a/mining/mining.go b/mining/mining.go index 09aa391f33..944b049bc3 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -219,7 +219,7 @@ type BlockTemplate struct { WitnessCommitment []byte } -// mergeUtxoView adds all of the entries in view to viewA. The result is that +// mergeUtxoView adds all of the entries in viewB to viewA. The result is that // viewA will contain all of its original entries plus all of the entries // in viewB. It will replace any entries in viewB which also exist in viewA // if the entry in viewA is fully spent. @@ -828,7 +828,7 @@ mempoolLoop: // witness preimage generated above. With the commitment // generated, the witness script for the output is: OP_RETURN // OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading - // prefix is refered to as the "witness magic bytes". + // prefix is referred to as the "witness magic bytes". witnessCommitment = chainhash.DoubleHashB(witnessPreimage[:]) witnessScript := append(blockchain.WitnessMagicBytes, witnessCommitment...) diff --git a/rpcclient/extensions.go b/rpcclient/extensions.go index 916ddb5fdf..d16cd5252e 100644 --- a/rpcclient/extensions.go +++ b/rpcclient/extensions.go @@ -422,7 +422,7 @@ func (c *Client) Session() (*btcjson.SessionResult, error) { return c.SessionAsync().Receive() } -// FutureVersionResult is a future promise to delivere the result of a version +// FutureVersionResult is a future promise to deliver the result of a version // RPC invocation (or an applicable error). // // NOTE: This is a btcsuite extension ported from diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 24f0ae9961..fe195cd70b 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -1106,7 +1106,7 @@ type ConnConfig struct { // flag can be set to true to use basic HTTP POST requests instead. HTTPPostMode bool - // EnableBCInfoHacks is an option provided to enable compatiblity hacks + // EnableBCInfoHacks is an option provided to enable compatibility hacks // when connecting to blockchain.info RPC server EnableBCInfoHacks bool } diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 9a0a3568f3..2454a94696 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -28,7 +28,7 @@ var ( "to use this feature") ) -// notificationState is used to track the current state of successfuly +// notificationState is used to track the current state of successfully // registered notification so the state can be automatically re-established on // reconnect. type notificationState struct { diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index caea70b84f..889a28d50d 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -148,7 +148,7 @@ type FutureListUnspentResult chan *response // Receive waits for the response promised by the future and returns all // unspent wallet transaction outputs returned by the RPC call. If the -// future wac returnd by a call to ListUnspentMinAsync, ListUnspentMinMaxAsync, +// future wac returned by a call to ListUnspentMinAsync, ListUnspentMinMaxAsync, // or ListUnspentMinMaxAddressesAsync, the range may be limited by the // parameters of the RPC invocation. func (r FutureListUnspentResult) Receive() ([]btcjson.ListUnspentResult, error) { @@ -1397,7 +1397,7 @@ func (r FutureGetBalanceResult) Receive() (btcutil.Amount, error) { // FutureGetBalanceParseResult is same as FutureGetBalanceResult except // that the result is expected to be a string which is then parsed into // a float64 value -// This is required for compatiblity with servers like blockchain.info +// This is required for compatibility with servers like blockchain.info type FutureGetBalanceParseResult chan *response // Receive waits for the response promised by the future and returns the diff --git a/rpcserverhelp.go b/rpcserverhelp.go index c615d03928..1705ebc85d 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -196,7 +196,7 @@ var helpDescsEnUS = map[string]string{ "txrawresult-confirmations": "Number of confirmations of the block", "txrawresult-time": "Transaction time in seconds since 1 Jan 1970 GMT", "txrawresult-blocktime": "Block time in seconds since the 1 Jan 1970 GMT", - "txrawresult-size": "The size of the transation in bytes", + "txrawresult-size": "The size of the transaction in bytes", "txrawresult-vsize": "The virtual size of the transaction in bytes", "txrawresult-hash": "The wtxid of the transaction", @@ -221,7 +221,7 @@ var helpDescsEnUS = map[string]string{ "getblockverboseresult-size": "The size of the block", "getblockverboseresult-height": "The height of the block in the block chain", "getblockverboseresult-version": "The block version", - "getblockverboseresult-versionHex": "The block version in hexidecimal", + "getblockverboseresult-versionHex": "The block version in hexadecimal", "getblockverboseresult-merkleroot": "Root hash of the merkle tree", "getblockverboseresult-tx": "The transaction hashes (only when verbosetx=false)", "getblockverboseresult-rawtx": "The transactions as JSON objects (only when verbosetx=true)", @@ -256,7 +256,7 @@ var helpDescsEnUS = map[string]string{ "getblockheaderverboseresult-confirmations": "The number of confirmations", "getblockheaderverboseresult-height": "The height of the block in the block chain", "getblockheaderverboseresult-version": "The block version", - "getblockheaderverboseresult-versionHex": "The block version in hexidecimal", + "getblockheaderverboseresult-versionHex": "The block version in hexadecimal", "getblockheaderverboseresult-merkleroot": "Root hash of the merkle tree", "getblockheaderverboseresult-time": "The block time in seconds since 1 Jan 1970 GMT", "getblockheaderverboseresult-nonce": "The block nonce", diff --git a/sample-btcd.conf b/sample-btcd.conf index ead8d06a76..a06dde669a 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -302,7 +302,7 @@ ; Enable built-in CPU mining. ; ; NOTE: This is typically only useful for testing purposes such as testnet or -; simnet since the difficutly on mainnet is far too high for CPU mining to be +; simnet since the difficulty on mainnet is far too high for CPU mining to be ; worth your while. ; generate=false diff --git a/server.go b/server.go index 5b3c8385e8..3d381fb216 100644 --- a/server.go +++ b/server.go @@ -2101,7 +2101,7 @@ out: s.wg.Done() } -// setupRPCListeners returns a slice of listners that are configured for use +// setupRPCListeners returns a slice of listeners that are configured for use // with the RPC server depending on the configuration settings for listen // addresses and TLS. func setupRPCListeners() ([]net.Listener, error) { diff --git a/txscript/script.go b/txscript/script.go index 4977e961ab..aac3d4aaaa 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -129,9 +129,9 @@ func IsWitnessProgram(script []byte) bool { // isWitnessProgram returns true if the passed script is a witness program, and // false otherwise. A witness program MUST adhere to the following constraints: -// there must be excatly two pops (program version and the program itself), the +// there must be exactly two pops (program version and the program itself), the // first opcode MUST be a small integer (0-16), the push data MUST be -// cannonical, and finally the size of the push data must be between 2 and 40 +// canonical, and finally the size of the push data must be between 2 and 40 // bytes. func isWitnessProgram(pops []parsedOpcode) bool { return len(pops) == 2 && diff --git a/txscript/standard_test.go b/txscript/standard_test.go index 02826ab54f..e24d5f615b 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -568,13 +568,13 @@ func TestCalcScriptInfo(t *testing.T) { // unsupported address types are handled properly. type bogusAddress struct{} -// EncodeAddress simply returns an empty string. It exists to satsify the +// EncodeAddress simply returns an empty string. It exists to satisfy the // btcutil.Address interface. func (b *bogusAddress) EncodeAddress() string { return "" } -// ScriptAddress simply returns an empty byte slice. It exists to satsify the +// ScriptAddress simply returns an empty byte slice. It exists to satisfy the // btcutil.Address interface. func (b *bogusAddress) ScriptAddress() []byte { return nil @@ -585,7 +585,7 @@ func (b *bogusAddress) IsForNet(chainParams *chaincfg.Params) bool { return true // why not? } -// String simply returns an empty string. It exists to satsify the +// String simply returns an empty string. It exists to satisfy the // btcutil.Address interface. func (b *bogusAddress) String() string { return "" diff --git a/wire/common.go b/wire/common.go index 85c9df83c7..42c1797b32 100644 --- a/wire/common.go +++ b/wire/common.go @@ -630,8 +630,8 @@ func WriteVarString(w io.Writer, pver uint32, str string) error { // ReadVarBytes reads a variable length byte array. A byte array is encoded // as a varInt containing the length of the array followed by the bytes // themselves. An error is returned if the length is greater than the -// passed maxAllowed parameter which helps protect against memory exhuastion -// attacks and forced panics thorugh malformed messages. The fieldName +// passed maxAllowed parameter which helps protect against memory exhaustion +// attacks and forced panics through malformed messages. The fieldName // parameter is only used for the error message so it provides more context in // the error. func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, diff --git a/wire/msggetdata_test.go b/wire/msggetdata_test.go index ea11262eeb..a2dd465184 100644 --- a/wire/msggetdata_test.go +++ b/wire/msggetdata_test.go @@ -78,7 +78,7 @@ func TestGetDataWire(t *testing.T) { t.Errorf("NewHashFromStr: %v", err) } - // Transation 1 of Block 203707 hash. + // Transaction 1 of Block 203707 hash. hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0" txHash, err := chainhash.NewHashFromStr(hashStr) if err != nil { diff --git a/wire/msginv_test.go b/wire/msginv_test.go index ea01fc1169..b7c7c6aec3 100644 --- a/wire/msginv_test.go +++ b/wire/msginv_test.go @@ -78,7 +78,7 @@ func TestInvWire(t *testing.T) { t.Errorf("NewHashFromStr: %v", err) } - // Transation 1 of Block 203707 hash. + // Transaction 1 of Block 203707 hash. hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0" txHash, err := chainhash.NewHashFromStr(hashStr) if err != nil { diff --git a/wire/msgmerkleblock_test.go b/wire/msgmerkleblock_test.go index 430c1fbb16..9837f8a973 100644 --- a/wire/msgmerkleblock_test.go +++ b/wire/msgmerkleblock_test.go @@ -405,7 +405,7 @@ var merkleBlockOne = MsgMerkleBlock{ } // merkleBlockOneBytes is the serialized bytes for a merkle block created from -// block one of the block chain where the first transation matches. +// block one of the block chain where the first transaction matches. var merkleBlockOneBytes = []byte{ 0x01, 0x00, 0x00, 0x00, // Version 1 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, diff --git a/wire/msgnotfound_test.go b/wire/msgnotfound_test.go index 07da74e8e3..69b9d07aea 100644 --- a/wire/msgnotfound_test.go +++ b/wire/msgnotfound_test.go @@ -69,7 +69,7 @@ func TestNotFoundWire(t *testing.T) { t.Errorf("NewHashFromStr: %v", err) } - // Transation 1 of Block 203707 hash. + // Transaction 1 of Block 203707 hash. hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0" txHash, err := chainhash.NewHashFromStr(hashStr) if err != nil { diff --git a/wire/msgtx.go b/wire/msgtx.go index af8abf610f..a5327cb3c6 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -923,7 +923,7 @@ func writeOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error // script. It is encoded as a varInt containing the length of the array // followed by the bytes themselves. An error is returned if the length is // greater than the passed maxAllowed parameter which helps protect against -// memory exhuastion attacks and forced panics thorugh malformed messages. The +// memory exhaustion attacks and forced panics through malformed messages. The // fieldName parameter is only used for the error message so it provides more // context in the error. func readScript(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { From e4a6228752df5f9109b8c428e9970da069e4a3f2 Mon Sep 17 00:00:00 2001 From: nakagawa Date: Fri, 26 Jan 2018 15:20:33 +0900 Subject: [PATCH 0035/1056] rpcclient: Add decodescript support. --- rpcclient/rawtransactions.go | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 3bd6e5d30e..e886f2250d 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -624,3 +624,41 @@ func (c *Client) SearchRawTransactionsVerbose(address btcutil.Address, skip, return c.SearchRawTransactionsVerboseAsync(address, skip, count, includePrevOut, reverse, &filterAddrs).Receive() } + +// FutureDecodeScriptResult is a future promise to deliver the result +// of a DecodeScriptAsync RPC invocation (or an applicable error). +type FutureDecodeScriptResult chan *response + +// Receive waits for the response promised by the future and returns information +// about a script given its serialized bytes. +func (r FutureDecodeScriptResult) Receive() (*btcjson.DecodeScriptResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a decodescript result object. + var decodeScriptResult btcjson.DecodeScriptResult + err = json.Unmarshal(res, &decodeScriptResult) + if err != nil { + return nil, err + } + + return &decodeScriptResult, nil +} + +// DecodeScriptAsync returns an instance of a type that can be used to +// get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See DecodeScript for the blocking version and more details. +func (c *Client) DecodeScriptAsync(serializedScript []byte) FutureDecodeScriptResult { + scriptHex := hex.EncodeToString(serializedScript) + cmd := btcjson.NewDecodeScriptCmd(scriptHex) + return c.sendCmd(cmd) +} + +// DecodeScript returns information about a script given its serialized bytes. +func (c *Client) DecodeScript(serializedScript []byte) (*btcjson.DecodeScriptResult, error) { + return c.DecodeScriptAsync(serializedScript).Receive() +} From fe786c93b6f4e0c96d6b19157b72963a9b50293d Mon Sep 17 00:00:00 2001 From: Jeremiah Goyette Date: Tue, 12 Sep 2017 00:07:53 -0500 Subject: [PATCH 0036/1056] rpcclient: implement addwitnessaddress --- rpcclient/wallet.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 889a28d50d..10c12f1f70 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -943,6 +943,44 @@ func (c *Client) GetRawChangeAddress(account string) (btcutil.Address, error) { return c.GetRawChangeAddressAsync(account).Receive() } +// FutureAddWitnessAddressResult is a future promise to deliver the result of +// a AddWitnessAddressAsync RPC invocation (or an applicable error). +type FutureAddWitnessAddressResult chan *response + +// Receive waits for the response promised by the future and returns the new +// address. +func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a string. + var addr string + err = json.Unmarshal(res, &addr) + if err != nil { + return nil, err + } + + return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams) +} + +// AddWitnessAddressAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See AddWitnessAddress for the blocking version and more details. +func (c *Client) AddWitnessAddressAsync(address string) FutureAddWitnessAddressResult { + cmd := btcjson.NewAddWitnessAddressCmd(address) + return c.sendCmd(cmd) +} + +// AddWitnessAddress adds a witness address for a script and returns the new +// address (P2SH of the witness script). +func (c *Client) AddWitnessAddress(address string) (btcutil.Address, error) { + return c.AddWitnessAddressAsync(address).Receive() +} + // FutureGetAccountAddressResult is a future promise to deliver the result of a // GetAccountAddressAsync RPC invocation (or an applicable error). type FutureGetAccountAddressResult chan *response From 358aed20b7ce1df988c833c492c6811dc07d0145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20F=C3=A9lizard?= Date: Sun, 28 Jan 2018 16:25:55 +0000 Subject: [PATCH 0037/1056] sampleconfig: Remove duplicate setting. `addrindex` was present twice. --- sample-btcd.conf | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/sample-btcd.conf b/sample-btcd.conf index a06dde669a..382b01143a 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -262,16 +262,6 @@ ; rejectnonstd=1 -; ------------------------------------------------------------------------------ -; Optional Transaction Indexes -; ------------------------------------------------------------------------------ - -; Build and maintain a full address-based transaction index. -; addrindex=1 -; Delete the entire address index on start up, then exit. -; dropaddrindex=0 - - ; ------------------------------------------------------------------------------ ; Optional Indexes ; ------------------------------------------------------------------------------ @@ -284,6 +274,9 @@ ; searchrawtransactions RPC available. ; addrindex=1 +; Delete the entire address index on start up, then exit. +; dropaddrindex=0 + ; ------------------------------------------------------------------------------ ; Signature Verification Cache From 175fd940bb8ca119e1c8e5cc88ebca680ed80366 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 5 Sep 2017 16:43:50 -0700 Subject: [PATCH 0038/1056] blockchain: Store block headers in bucket managed by chainio. The bucket contains block headers keyed by the block height encoded as big-endian concatenated with the block hash. This allows block headers to be fetched from the DB in height order with a cursor. --- blockchain/accept.go | 2 +- blockchain/chain.go | 14 -------- blockchain/chainio.go | 79 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 18 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 963a4fd061..1d68b5608b 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -54,7 +54,7 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) // such as making blocks that never become part of the main chain or // blocks that fail to connect available for further analysis. err = b.db.Update(func(dbTx database.Tx) error { - return dbMaybeStoreBlock(dbTx, block) + return dbStoreBlock(dbTx, block) }) if err != nil { return false, err diff --git a/blockchain/chain.go b/blockchain/chain.go index bd24b1e1ac..df90d5fd89 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -544,20 +544,6 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List return detachNodes, attachNodes } -// dbMaybeStoreBlock stores the provided block in the database if it's not -// already there. -func dbMaybeStoreBlock(dbTx database.Tx, block *btcutil.Block) error { - hasBlock, err := dbTx.HasBlock(block.Hash()) - if err != nil { - return err - } - if hasBlock { - return nil - } - - return dbTx.StoreBlock(block) -} - // connectBlock handles connecting the passed node/block to the end of the main // (best) chain. // diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 6c629c6055..25d35f04ea 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -18,7 +18,18 @@ import ( "github.com/btcsuite/btcutil" ) +const ( + // blockHdrSize is the size of a block header. This is simply the + // constant from wire and is only provided here for convenience since + // wire.MaxBlockHeaderPayload is quite long. + blockHdrSize = wire.MaxBlockHeaderPayload +) + var ( + // blockIndexBucketName is the name of the db bucket used to house to the + // block headers and contextual information. + blockIndexBucketName = []byte("blockheaderidx") + // hashIndexBucketName is the name of the db bucket used to house to the // block hash -> block height index. hashIndexBucketName = []byte("hashidx") @@ -1058,6 +1069,7 @@ func dbPutBestState(dbTx database.Tx, snapshot *BestState, workSum *big.Int) err func (b *BlockChain) createChainState() error { // Create a new node from the genesis block and set it as the best node. genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock) + genesisBlock.SetHeight(0) header := &genesisBlock.MsgBlock().Header node := newBlockNode(header, 0) node.status = statusDataStored | statusValid @@ -1077,10 +1089,17 @@ func (b *BlockChain) createChainState() error { // Create the initial the database chain state including creating the // necessary index buckets and inserting the genesis block. err := b.db.Update(func(dbTx database.Tx) error { + meta := dbTx.Metadata() + + // Create the bucket that houses the block index data. + _, err := meta.CreateBucket(blockIndexBucketName) + if err != nil { + return err + } + // Create the bucket that houses the chain block hash to height // index. - meta := dbTx.Metadata() - _, err := meta.CreateBucket(hashIndexBucketName) + _, err = meta.CreateBucket(hashIndexBucketName) if err != nil { return err } @@ -1120,7 +1139,7 @@ func (b *BlockChain) createChainState() error { } // Store the genesis block into the database. - return dbTx.StoreBlock(genesisBlock) + return dbStoreBlock(dbTx, genesisBlock) }) return err } @@ -1273,6 +1292,60 @@ func dbFetchBlockByNode(dbTx database.Tx, node *blockNode) (*btcutil.Block, erro return block, nil } +// dbStoreBlock stores the provided block in the database. The block header is +// written to the block index bucket and full block data is written to ffldb. +func dbStoreBlockHeader(dbTx database.Tx, blockHeader *wire.BlockHeader, height uint32) error { + // Serialize block data to be stored. This is just the serialized header. + w := bytes.NewBuffer(make([]byte, 0, blockHdrSize)) + err := blockHeader.Serialize(w) + if err != nil { + return err + } + value := w.Bytes() + + // Write block header data to block index bucket. + blockHash := blockHeader.BlockHash() + blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName) + key := blockIndexKey(&blockHash, height) + return blockIndexBucket.Put(key, value) +} + +// dbStoreBlock stores the provided block in the database. The block header is +// written to the block index bucket and full block data is written to ffldb. +func dbStoreBlock(dbTx database.Tx, block *btcutil.Block) error { + if block.Height() == btcutil.BlockHeightUnknown { + return fmt.Errorf("cannot store block %s with unknown height", + block.Hash()) + } + + // First store block header in the block index bucket. + err := dbStoreBlockHeader(dbTx, &block.MsgBlock().Header, + uint32(block.Height())) + if err != nil { + return err + } + + // Then store block data in ffldb if we haven't already. + hasBlock, err := dbTx.HasBlock(block.Hash()) + if err != nil { + return err + } + if hasBlock { + return nil + } + return dbTx.StoreBlock(block) +} + +// blockIndexKey generates the binary key for an entry in the block index +// bucket. The key is composed of the block height encoded as a big-endian +// 32-bit unsigned int followed by the 32 byte block hash. +func blockIndexKey(blockHash *chainhash.Hash, blockHeight uint32) []byte { + indexKey := make([]byte, chainhash.HashSize+4) + binary.BigEndian.PutUint32(indexKey[0:4], blockHeight) + copy(indexKey[4:chainhash.HashSize+4], blockHash[:]) + return indexKey +} + // BlockByHeight returns the block at the given height in the main chain. // // This function is safe for concurrent access. From 6315cea70c6ceda543addef3d82ed8d67c8cba9c Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 5 Sep 2017 16:58:49 -0700 Subject: [PATCH 0039/1056] blockchain: Load all block headers into block index on init. Currently only the blocks in the active chain are loaded into the block index on initialization. This instead iterates over the entire block index bucket in LevelDB and loads all nodes. --- blockchain/chainio.go | 75 +++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 24 deletions(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 25d35f04ea..66b552de3e 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1171,41 +1171,68 @@ func (b *BlockChain) initChainState() error { // for them versus a whole bunch of little ones to reduce // pressure on the GC. log.Infof("Loading block index. This might take a while...") - bestHeight := int32(state.height) - blockNodes := make([]blockNode, bestHeight+1) - var tip *blockNode - for height := int32(0); height <= bestHeight; height++ { - header, err := dbFetchHeaderByHeight(dbTx, height) + + blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName) + + // Determine how many blocks will be loaded into the index so we can + // allocate the right amount. + var blockCount int32 + cursor := blockIndexBucket.Cursor() + for ok := cursor.First(); ok; ok = cursor.Next() { + blockCount++ + } + blockNodes := make([]blockNode, blockCount) + + var i int32 + var lastNode *blockNode + cursor = blockIndexBucket.Cursor() + for ok := cursor.First(); ok; ok = cursor.Next() { + var header wire.BlockHeader + headerBytes := cursor.Value() + err := header.Deserialize(bytes.NewReader(headerBytes)) if err != nil { return err } // Initialize the block node for the block, connect it, // and add it to the block index. - node := &blockNodes[height] - initBlockNode(node, header, height) + node := &blockNodes[i] + initBlockNode(node, &header, 0) node.status = statusDataStored | statusValid - if tip != nil { - node.parent = tip - node.workSum = node.workSum.Add(tip.workSum, - node.workSum) + if lastNode == nil { + if node.hash != *b.chainParams.GenesisHash { + return AssertError(fmt.Sprintf("initChainState: Expected "+ + "first entry in block index to be genesis block, "+ + "found %s", header.BlockHash())) + } + } else { + // Since we iterate block headers in order of height, if the + // blocks are mostly linear there is a very good chance the + // previous header processed is the parent. + parent := lastNode + if header.PrevBlock != parent.hash { + parent = b.index.LookupNode(&header.PrevBlock) + } + if parent == nil { + return AssertError(fmt.Sprintf("initChainState: Could "+ + "not find parent for block %s", header.BlockHash())) + } + + node.parent = parent + node.height = parent.height + 1 + node.workSum = node.workSum.Add(parent.workSum, node.workSum) } - b.index.AddNode(node) - // This node is now the end of the best chain. - tip = node + b.index.AddNode(node) + lastNode = node + i++ } - // Ensure the resulting best chain matches the stored best state - // hash and set the best chain view accordingly. - if tip == nil || tip.hash != state.hash { - var tipHash chainhash.Hash - if tip != nil { - tipHash = tip.hash - } - return AssertError(fmt.Sprintf("initChainState: block "+ - "index chain tip %s does not match stored "+ - "best state %s", tipHash, state.hash)) + // Set the best chain view to the stored best state. + tip := b.index.LookupNode(&state.hash) + if tip == nil { + return AssertError(fmt.Sprintf("initChainState: cannot find "+ + "chain tip %s in block index", state.hash)) } b.bestChain.SetTip(tip) From 74fb6e56da4d09cef109e3cd499df5bb45f82151 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 5 Sep 2017 18:24:52 -0700 Subject: [PATCH 0040/1056] blockchain: Database migration to populate block index bucket. This creates a migration function that populates the block index bucket using data from the ffldb block index bucket if it does not exist. --- blockchain/blockindex.go | 2 +- blockchain/chainio.go | 45 ++++++++----- blockchain/upgrade.go | 139 +++++++++++++++++++++++++++++++++++++++ blockchain/validate.go | 6 +- 4 files changed, 170 insertions(+), 22 deletions(-) create mode 100644 blockchain/upgrade.go diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 642b658e60..e9be63b30e 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -136,7 +136,7 @@ func newBlockNode(blockHeader *wire.BlockHeader, height int32) *blockNode { // This function is safe for concurrent access. func (node *blockNode) Header() wire.BlockHeader { // No lock is needed because all accessed fields are immutable. - prevHash := zeroHash + prevHash := &zeroHash if node.parent != nil { prevHash = &node.parent.hash } diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 66b552de3e..51216f56e5 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1148,17 +1148,39 @@ func (b *BlockChain) createChainState() error { // database. When the db does not yet contain any chain state, both it and the // chain state are initialized to the genesis block. func (b *BlockChain) initChainState() error { - // Attempt to load the chain state from the database. - var isStateInitialized bool + // Determine the state of the chain database. We may need to initialize + // everything from scratch or upgrade certain buckets. + var initialized bool + var hasBlockIndex bool err := b.db.View(func(dbTx database.Tx) error { + initialized = dbTx.Metadata().Get(chainStateKeyName) != nil + hasBlockIndex = dbTx.Metadata().Bucket(blockIndexBucketName) != nil + return nil + }) + if err != nil { + return err + } + + if !initialized { + // At this point the database has not already been initialized, so + // initialize both it and the chain state to the genesis block. + return b.createChainState() + } + + if !hasBlockIndex { + err := migrateBlockIndex(b.db) + if err != nil { + return nil + } + } + + // Attempt to load the chain state from the database. + return b.db.View(func(dbTx database.Tx) error { // Fetch the stored chain state from the database metadata. // When it doesn't exist, it means the database hasn't been // initialized for use with chain yet, so break out now to allow // that to happen under a writable database transaction. serializedData := dbTx.Metadata().Get(chainStateKeyName) - if serializedData == nil { - return nil - } log.Tracef("Serialized chain state: %x", serializedData) state, err := deserializeBestChainState(serializedData) if err != nil { @@ -1253,22 +1275,9 @@ func (b *BlockChain) initChainState() error { numTxns := uint64(len(block.Transactions)) b.stateSnapshot = newBestState(tip, blockSize, blockWeight, numTxns, state.totalTxns, tip.CalcPastMedianTime()) - isStateInitialized = true return nil }) - if err != nil { - return err - } - - // There is nothing more to do if the chain state was initialized. - if isStateInitialized { - return nil - } - - // At this point the database has not already been initialized, so - // initialize both it and the chain state to the genesis block. - return b.createChainState() } // dbFetchHeaderByHash uses an existing database transaction to retrieve the diff --git a/blockchain/upgrade.go b/blockchain/upgrade.go new file mode 100644 index 0000000000..60e8a897ba --- /dev/null +++ b/blockchain/upgrade.go @@ -0,0 +1,139 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "bytes" + "container/list" + "fmt" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcd/wire" +) + +const ( + // blockHdrOffset defines the offsets into a v1 block index row for the + // block header. + // + // The serialized block index row format is: + // + blockHdrOffset = 12 +) + +// migrateBlockIndex migrates all block entries from the v1 block index bucket +// to the v2 bucket. The v1 bucket stores all block entries keyed by block hash, +// whereas the v2 bucket stores the exact same values, but keyed instead by +// block height + hash. +func migrateBlockIndex(db database.DB) error { + // Hardcoded bucket names so updates to the global values do not affect + // old upgrades. + v1BucketName := []byte("ffldb-blockidx") + v2BucketName := []byte("blockheaderidx") + + err := db.Update(func(dbTx database.Tx) error { + v1BlockIdxBucket := dbTx.Metadata().Bucket(v1BucketName) + if v1BlockIdxBucket == nil { + return fmt.Errorf("Bucket %s does not exist", v1BucketName) + } + + log.Info("Re-indexing block information in the database. This might take a while...") + + v2BlockIdxBucket, err := + dbTx.Metadata().CreateBucketIfNotExists(v2BucketName) + if err != nil { + return err + } + + // Scan the old block index bucket and construct a mapping of each block + // to all child blocks. + childBlocksMap, err := readBlockTree(v1BlockIdxBucket) + if err != nil { + return err + } + + // Use the block graph to calculate the height of each block. + blockHeights := determineBlockHeights(childBlocksMap) + + // Now that we have heights for all blocks, scan the old block index + // bucket and insert all rows into the new one. + return v1BlockIdxBucket.ForEach(func(hashBytes, blockRow []byte) error { + endOffset := blockHdrOffset + blockHdrSize + headerBytes := blockRow[blockHdrOffset:endOffset:endOffset] + + var hash chainhash.Hash + copy(hash[:], hashBytes[0:chainhash.HashSize]) + + height, exists := blockHeights[hash] + if !exists { + return fmt.Errorf("Unable to calculate chain height for "+ + "stored block %s", hash) + } + + key := blockIndexKey(&hash, height) + return v2BlockIdxBucket.Put(key, headerBytes) + }) + }) + if err != nil { + return err + } + + log.Infof("Block database migration complete") + return nil +} + +// readBlockTree reads the old block index bucket and constructs a mapping of +// each block to all child blocks. This mapping represents the full tree of +// blocks. +func readBlockTree(v1BlockIdxBucket database.Bucket) (map[chainhash.Hash][]*chainhash.Hash, error) { + childBlocksMap := make(map[chainhash.Hash][]*chainhash.Hash) + err := v1BlockIdxBucket.ForEach(func(_, blockRow []byte) error { + var header wire.BlockHeader + endOffset := blockHdrOffset + blockHdrSize + headerBytes := blockRow[blockHdrOffset:endOffset:endOffset] + err := header.Deserialize(bytes.NewReader(headerBytes)) + if err != nil { + return err + } + + blockHash := header.BlockHash() + childBlocksMap[header.PrevBlock] = + append(childBlocksMap[header.PrevBlock], &blockHash) + return nil + }) + return childBlocksMap, err +} + +// determineBlockHeights takes a map of block hashes to a slice of child hashes +// and uses it to compute the height for each block. The function assigns a +// height of 0 to the genesis hash and explores the tree of blocks +// breadth-first, assigning a height to every block with a path back to the +// genesis block. +func determineBlockHeights(childBlocksMap map[chainhash.Hash][]*chainhash.Hash) map[chainhash.Hash]uint32 { + blockHeights := make(map[chainhash.Hash]uint32) + queue := list.New() + + // The genesis block is included in childBlocksMap as a child of the zero + // hash because that is the value of the PrevBlock field in the genesis + // header. + for _, genesisHash := range childBlocksMap[zeroHash] { + blockHeights[*genesisHash] = 0 + queue.PushBack(genesisHash) + } + + for e := queue.Front(); e != nil; e = queue.Front() { + queue.Remove(e) + hash := e.Value.(*chainhash.Hash) + height := blockHeights[*hash] + + // For each block with this one as a parent, assign it a height and + // push to queue for future processing. + for _, childHash := range childBlocksMap[*hash] { + blockHeights[*childHash] = height + 1 + queue.PushBack(childHash) + } + } + return blockHeights +} diff --git a/blockchain/validate.go b/blockchain/validate.go index 27f04f6e0d..1beda89e58 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -47,7 +47,7 @@ var ( // zeroHash is the zero value for a chainhash.Hash and is defined as // a package level variable to avoid the need to create a new instance // every time a check is needed. - zeroHash = &chainhash.Hash{} + zeroHash chainhash.Hash // block91842Hash is one of the two nodes which violate the rules // set forth in BIP0030. It is defined as a package level variable to @@ -63,7 +63,7 @@ var ( // isNullOutpoint determines whether or not a previous transaction output point // is set. func isNullOutpoint(outpoint *wire.OutPoint) bool { - if outpoint.Index == math.MaxUint32 && outpoint.Hash.IsEqual(zeroHash) { + if outpoint.Index == math.MaxUint32 && outpoint.Hash == zeroHash { return true } return false @@ -95,7 +95,7 @@ func IsCoinBaseTx(msgTx *wire.MsgTx) bool { // The previous output of a coin base must have a max value index and // a zero hash. prevOut := &msgTx.TxIn[0].PreviousOutPoint - if prevOut.Index != math.MaxUint32 || !prevOut.Hash.IsEqual(zeroHash) { + if prevOut.Index != math.MaxUint32 || prevOut.Hash != zeroHash { return false } From ad00e7ff82020979ba23252085b2a2f09608f335 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 5 Sep 2017 19:08:09 -0700 Subject: [PATCH 0041/1056] database: Stop writing block header data to LevelDB. Now that all headers are stored in the in-memory index, the database bucket managed by blockchain, and in the flat files, it makes sense to drop the redundant data from the block index bucket in ffldb. To avoid modifying the database interface, this reimplements FetchBlockHeader(s) to use header data stored in flat files. This can be trivially implemented by delegating to FetchBlockRegion. --- database/ffldb/db.go | 80 ++++++-------------------------------------- 1 file changed, 11 insertions(+), 69 deletions(-) diff --git a/database/ffldb/db.go b/database/ffldb/db.go index 599f2427fa..fd1ff895c3 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -1255,27 +1255,11 @@ func (tx *transaction) fetchBlockRow(hash *chainhash.Hash) ([]byte, error) { // // This function is part of the database.Tx interface implementation. func (tx *transaction) FetchBlockHeader(hash *chainhash.Hash) ([]byte, error) { - // Ensure transaction state is valid. - if err := tx.checkClosed(); err != nil { - return nil, err - } - - // When the block is pending to be written on commit return the bytes - // from there. - if idx, exists := tx.pendingBlocks[*hash]; exists { - blockBytes := tx.pendingBlockData[idx].bytes - return blockBytes[0:blockHdrSize:blockHdrSize], nil - } - - // Fetch the block index row and slice off the header. Notice the use - // of the cap on the subslice to prevent the caller from accidentally - // appending into the db data. - blockRow, err := tx.fetchBlockRow(hash) - if err != nil { - return nil, err - } - endOffset := blockLocSize + blockHdrSize - return blockRow[blockLocSize:endOffset:endOffset], nil + return tx.FetchBlockRegion(&database.BlockRegion{ + Hash: hash, + Offset: 0, + Len: blockHdrSize, + }) } // FetchBlockHeaders returns the raw serialized bytes for the block headers @@ -1294,41 +1278,13 @@ func (tx *transaction) FetchBlockHeader(hash *chainhash.Hash) ([]byte, error) { // // This function is part of the database.Tx interface implementation. func (tx *transaction) FetchBlockHeaders(hashes []chainhash.Hash) ([][]byte, error) { - // Ensure transaction state is valid. - if err := tx.checkClosed(); err != nil { - return nil, err - } - - // NOTE: This could check for the existence of all blocks before loading - // any of the headers which would be faster in the failure case, however - // callers will not typically be calling this function with invalid - // values, so optimize for the common case. - - // Load the headers. - headers := make([][]byte, len(hashes)) + regions := make([]database.BlockRegion, len(hashes)) for i := range hashes { - hash := &hashes[i] - - // When the block is pending to be written on commit return the - // bytes from there. - if idx, exists := tx.pendingBlocks[*hash]; exists { - blkBytes := tx.pendingBlockData[idx].bytes - headers[i] = blkBytes[0:blockHdrSize:blockHdrSize] - continue - } - - // Fetch the block index row and slice off the header. Notice - // the use of the cap on the subslice to prevent the caller - // from accidentally appending into the db data. - blockRow, err := tx.fetchBlockRow(hash) - if err != nil { - return nil, err - } - endOffset := blockLocSize + blockHdrSize - headers[i] = blockRow[blockLocSize:endOffset:endOffset] + regions[i].Hash = &hashes[i] + regions[i].Offset = 0 + regions[i].Len = blockHdrSize } - - return headers, nil + return tx.FetchBlockRegions(regions) } // FetchBlock returns the raw serialized bytes for the block identified by the @@ -1656,19 +1612,6 @@ func (tx *transaction) close() { } } -// serializeBlockRow serializes a block row into a format suitable for storage -// into the block index. -func serializeBlockRow(blockLoc blockLocation, blockHdr []byte) []byte { - // The serialized block index row format is: - // - // [0:blockLocSize] Block location - // [blockLocSize:blockLocSize+blockHdrSize] Block header - serializedRow := make([]byte, blockLocSize+blockHdrSize) - copy(serializedRow, serializeBlockLoc(blockLoc)) - copy(serializedRow[blockHdrOffset:], blockHdr) - return serializedRow -} - // writePendingAndCommit writes pending block data to the flat block files, // updates the metadata with their locations as well as the new current write // location, and commits the metadata to the memory database cache. It also @@ -1706,8 +1649,7 @@ func (tx *transaction) writePendingAndCommit() error { // includes the location information needed to locate the block // on the filesystem as well as the block header since they are // so commonly needed. - blockHdr := blockData.bytes[0:blockHdrSize] - blockRow := serializeBlockRow(location, blockHdr) + blockRow := serializeBlockLoc(location) err = tx.blockIdxBucket.Put(blockData.hash[:], blockRow) if err != nil { rollback() From a4d22d8384806ca60e537108ed1672d330e1bda2 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Tue, 5 Sep 2017 19:22:16 -0700 Subject: [PATCH 0042/1056] blockchain: Delete block headers from old block index bucket. As part of the migration to the new block index bucket, also delete the redundant data from the old bucket. --- blockchain/chainio.go | 2 +- blockchain/upgrade.go | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 51216f56e5..85c910abb5 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1192,7 +1192,7 @@ func (b *BlockChain) initChainState() error { // number of nodes are already known, perform a single alloc // for them versus a whole bunch of little ones to reduce // pressure on the GC. - log.Infof("Loading block index. This might take a while...") + log.Infof("Loading block index...") blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName) diff --git a/blockchain/upgrade.go b/blockchain/upgrade.go index 60e8a897ba..f980d0152c 100644 --- a/blockchain/upgrade.go +++ b/blockchain/upgrade.go @@ -72,8 +72,16 @@ func migrateBlockIndex(db database.DB) error { "stored block %s", hash) } + // Write header to v2 bucket key := blockIndexKey(&hash, height) - return v2BlockIdxBucket.Put(key, headerBytes) + err := v2BlockIdxBucket.Put(key, headerBytes) + if err != nil { + return err + } + + // Delete header from v1 bucket + truncatedRow := blockRow[0:blockHdrOffset:blockHdrOffset] + return v1BlockIdxBucket.Put(hashBytes, truncatedRow) }) }) if err != nil { From 31444f589086ba7979b1a023ed412e44a2c70635 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 14 Sep 2017 19:32:36 -0700 Subject: [PATCH 0043/1056] blockchain: Add parent to blockNode constructor. --- blockchain/accept.go | 7 +------ blockchain/blockindex.go | 26 +++++++++++++------------- blockchain/chainio.go | 35 ++++++++++++++++++----------------- blockchain/chainview_test.go | 9 ++------- blockchain/common_test.go | 7 ++----- blockchain/validate.go | 4 +--- 6 files changed, 37 insertions(+), 51 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 1d68b5608b..2e877bd6c7 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -63,13 +63,8 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) // Create a new block node for the block and add it to the in-memory // block chain (could be either a side chain or the main chain). blockHeader := &block.MsgBlock().Header - newNode := newBlockNode(blockHeader, blockHeight) + newNode := newBlockNode(blockHeader, prevNode) newNode.status = statusDataStored - if prevNode != nil { - newNode.parent = prevNode - newNode.height = blockHeight - newNode.workSum.Add(prevNode.workSum, newNode.workSum) - } b.index.AddNode(newNode) // Connect the passed block to the chain while respecting proper chain diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index e9be63b30e..f3a060f170 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -101,33 +101,33 @@ type blockNode struct { status blockStatus } -// initBlockNode initializes a block node from the given header and height. The -// node is completely disconnected from the chain and the workSum value is just -// the work for the passed block. The work sum must be updated accordingly when -// the node is inserted into a chain. -// +// initBlockNode initializes a block node from the given header and parent node, +// calculating the height and workSum from the respective fields on the parent. // This function is NOT safe for concurrent access. It must only be called when // initially creating a node. -func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, height int32) { +func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parent *blockNode) { *node = blockNode{ hash: blockHeader.BlockHash(), workSum: CalcWork(blockHeader.Bits), - height: height, version: blockHeader.Version, bits: blockHeader.Bits, nonce: blockHeader.Nonce, timestamp: blockHeader.Timestamp.Unix(), merkleRoot: blockHeader.MerkleRoot, } + if parent != nil { + node.parent = parent + node.height = parent.height + 1 + node.workSum = node.workSum.Add(parent.workSum, node.workSum) + } } -// newBlockNode returns a new block node for the given block header. It is -// completely disconnected from the chain and the workSum value is just the work -// for the passed block. The work sum must be updated accordingly when the node -// is inserted into a chain. -func newBlockNode(blockHeader *wire.BlockHeader, height int32) *blockNode { +// newBlockNode returns a new block node for the given block header and parent +// node, calculating the height and workSum from the respective fields on the +// parent. This function is NOT safe for concurrent access. +func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode { var node blockNode - initBlockNode(&node, blockHeader, height) + initBlockNode(&node, blockHeader, parent) return &node } diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 85c910abb5..d7ff6ba197 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1071,7 +1071,7 @@ func (b *BlockChain) createChainState() error { genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock) genesisBlock.SetHeight(0) header := &genesisBlock.MsgBlock().Header - node := newBlockNode(header, 0) + node := newBlockNode(header, nil) node.status = statusDataStored | statusValid b.bestChain.SetTip(node) @@ -1216,36 +1216,37 @@ func (b *BlockChain) initChainState() error { return err } - // Initialize the block node for the block, connect it, - // and add it to the block index. - node := &blockNodes[i] - initBlockNode(node, &header, 0) - node.status = statusDataStored | statusValid + // Determine the parent block node. Since we iterate block headers + // in order of height, if the blocks are mostly linear there is a + // very good chance the previous header processed is the parent. + var parent *blockNode if lastNode == nil { - if node.hash != *b.chainParams.GenesisHash { + blockHash := header.BlockHash() + if !blockHash.IsEqual(b.chainParams.GenesisHash) { return AssertError(fmt.Sprintf("initChainState: Expected "+ "first entry in block index to be genesis block, "+ - "found %s", header.BlockHash())) + "found %s", blockHash)) } - } else { + } else if header.PrevBlock == lastNode.hash { // Since we iterate block headers in order of height, if the // blocks are mostly linear there is a very good chance the // previous header processed is the parent. - parent := lastNode - if header.PrevBlock != parent.hash { - parent = b.index.LookupNode(&header.PrevBlock) - } + parent = lastNode + } else { + parent = b.index.LookupNode(&header.PrevBlock) if parent == nil { return AssertError(fmt.Sprintf("initChainState: Could "+ "not find parent for block %s", header.BlockHash())) } - - node.parent = parent - node.height = parent.height + 1 - node.workSum = node.workSum.Add(parent.workSum, node.workSum) } + // Initialize the block node for the block, connect it, + // and add it to the block index. + node := &blockNodes[i] + initBlockNode(node, &header, parent) + node.status = statusDataStored | statusValid b.index.AddNode(node) + lastNode = node i++ } diff --git a/blockchain/chainview_test.go b/blockchain/chainview_test.go index 760d31ab1e..c59004fdaf 100644 --- a/blockchain/chainview_test.go +++ b/blockchain/chainview_test.go @@ -27,16 +27,11 @@ func chainedNodes(parent *blockNode, numNodes int) []*blockNode { // This is invalid, but all that is needed is enough to get the // synthetic tests to work. header := wire.BlockHeader{Nonce: testNoncePrng.Uint32()} - height := int32(0) if tip != nil { header.PrevBlock = tip.hash - height = tip.height + 1 } - node := newBlockNode(&header, height) - node.parent = tip - tip = node - - nodes[i] = node + nodes[i] = newBlockNode(&header, tip) + tip = nodes[i] } return nodes } diff --git a/blockchain/common_test.go b/blockchain/common_test.go index 38191c25ab..d6eff63dfb 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -261,7 +261,7 @@ func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) { func newFakeChain(params *chaincfg.Params) *BlockChain { // Create a genesis block node and block index index populated with it // for use when creating the fake chain below. - node := newBlockNode(¶ms.GenesisBlock.Header, 0) + node := newBlockNode(¶ms.GenesisBlock.Header, nil) index := newBlockIndex(nil, params) index.AddNode(node) @@ -291,8 +291,5 @@ func newFakeNode(parent *blockNode, blockVersion int32, bits uint32, timestamp t Bits: bits, Timestamp: timestamp, } - node := newBlockNode(header, parent.height+1) - node.parent = parent - node.workSum.Add(parent.workSum, node.workSum) - return node + return newBlockNode(header, parent) } diff --git a/blockchain/validate.go b/blockchain/validate.go index 1beda89e58..f78d3ae63a 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -1274,8 +1274,6 @@ func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error { // is not needed and thus extra work can be avoided. view := NewUtxoViewpoint() view.SetBestHash(&tip.hash) - newNode := newBlockNode(&header, tip.height+1) - newNode.parent = tip - newNode.workSum = newNode.workSum.Add(tip.workSum, newNode.workSum) + newNode := newBlockNode(&header, tip) return b.checkConnectBlock(newNode, block, view, nil) } From 52cddc19cd2c0a859e6689ab035d85729508cc11 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 14 Sep 2017 14:41:21 -0700 Subject: [PATCH 0044/1056] blockchain: Persist block status changes to disk. The block index now tracks the set of dirty block nodes with status changes that haven't been persisted and flushes the changes to the DB at the appropriate times. --- blockchain/accept.go | 10 ++++-- blockchain/blockindex.go | 47 ++++++++++++++++++++++++-- blockchain/chain.go | 50 +++++++++++++++++++++++----- blockchain/chainio.go | 71 ++++++++++++++++++++++------------------ 4 files changed, 133 insertions(+), 45 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 2e877bd6c7..f85d6558e8 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -60,12 +60,18 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) return false, err } - // Create a new block node for the block and add it to the in-memory - // block chain (could be either a side chain or the main chain). + // Create a new block node for the block and add it to the node index. Even + // if the block ultimately gets connected to the main chain, it starts out + // on a side chain. blockHeader := &block.MsgBlock().Header newNode := newBlockNode(blockHeader, prevNode) newNode.status = statusDataStored + b.index.AddNode(newNode) + err = b.index.flushToDB() + if err != nil { + return false, err + } // Connect the passed block to the chain while respecting proper chain // selection according to the chain with the most proof of work. This diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index f3a060f170..2ff2fa27c4 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -231,6 +231,7 @@ type blockIndex struct { sync.RWMutex index map[chainhash.Hash]*blockNode + dirty map[*blockNode]struct{} } // newBlockIndex returns a new empty instance of a block index. The index will @@ -241,6 +242,7 @@ func newBlockIndex(db database.DB, chainParams *chaincfg.Params) *blockIndex { db: db, chainParams: chainParams, index: make(map[chainhash.Hash]*blockNode), + dirty: make(map[*blockNode]struct{}), } } @@ -265,16 +267,25 @@ func (bi *blockIndex) LookupNode(hash *chainhash.Hash) *blockNode { return node } -// AddNode adds the provided node to the block index. Duplicate entries are not -// checked so it is up to caller to avoid adding them. +// AddNode adds the provided node to the block index and marks it as dirty. +// Duplicate entries are not checked so it is up to caller to avoid adding them. // // This function is safe for concurrent access. func (bi *blockIndex) AddNode(node *blockNode) { bi.Lock() - bi.index[node.hash] = node + bi.addNode(node) + bi.dirty[node] = struct{}{} bi.Unlock() } +// addNode adds the provided node to the block index, but does not mark it as +// dirty. This can be used while initializing the block index. +// +// This function is NOT safe for concurrent access. +func (bi *blockIndex) addNode(node *blockNode) { + bi.index[node.hash] = node +} + // NodeStatus provides concurrent-safe access to the status field of a node. // // This function is safe for concurrent access. @@ -293,6 +304,7 @@ func (bi *blockIndex) NodeStatus(node *blockNode) blockStatus { func (bi *blockIndex) SetStatusFlags(node *blockNode, flags blockStatus) { bi.Lock() node.status |= flags + bi.dirty[node] = struct{}{} bi.Unlock() } @@ -303,5 +315,34 @@ func (bi *blockIndex) SetStatusFlags(node *blockNode, flags blockStatus) { func (bi *blockIndex) UnsetStatusFlags(node *blockNode, flags blockStatus) { bi.Lock() node.status &^= flags + bi.dirty[node] = struct{}{} + bi.Unlock() +} + +// flushToDB writes all dirty block nodes to the database. If all writes +// succeed, this clears the dirty set. +func (bi *blockIndex) flushToDB() error { + bi.Lock() + if len(bi.dirty) == 0 { + bi.Unlock() + return nil + } + + err := bi.db.Update(func(dbTx database.Tx) error { + for node := range bi.dirty { + err := dbStoreBlockNode(dbTx, node) + if err != nil { + return err + } + } + return nil + }) + + // If write was successful, clear the dirty set. + if err == nil { + bi.dirty = make(map[*blockNode]struct{}) + } + bi.Unlock() + return err } diff --git a/blockchain/chain.go b/blockchain/chain.go index df90d5fd89..d00557e7ad 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -495,6 +495,8 @@ func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 { // passed node is the new end of the main chain. The lists will be empty if the // passed node is not on a side chain. // +// This function may modify node statuses in the block index without flushing. +// // This function MUST be called with the chain state lock held (for reads). func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List) { attachNodes := list.New() @@ -585,6 +587,12 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *U } } + // Write any block status changes to DB before updating best state. + err := b.index.flushToDB() + if err != nil { + return err + } + // Generate a new best state snapshot that will be used to update the // database and later memory if all database updates are successful. b.stateLock.RLock() @@ -597,7 +605,7 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *U curTotalTxns+numTxns, node.CalcPastMedianTime()) // Atomically insert info into the database. - err := b.db.Update(func(dbTx database.Tx) error { + err = b.db.Update(func(dbTx database.Tx) error { // Update best block state. err := dbPutBestState(dbTx, state, node.workSum) if err != nil { @@ -691,6 +699,12 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view return err } + // Write any block status changes to DB before updating best state. + err = b.index.flushToDB() + if err != nil { + return err + } + // Generate a new best state snapshot that will be used to update the // database and later memory if all database updates are successful. b.stateLock.RLock() @@ -792,6 +806,8 @@ func countSpentOutputs(block *btcutil.Block) int { // the chain) and nodes the are being attached must be in forwards order // (think pushing them onto the end of the chain). // +// This function may modify node statuses in the block index without flushing. +// // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error { // All of the blocks to detach and related spend journal entries needed @@ -1030,13 +1046,26 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla stxos := make([]spentTxOut, 0, countSpentOutputs(block)) if !fastAdd { err := b.checkConnectBlock(node, block, view, &stxos) + if err == nil { + b.index.SetStatusFlags(node, statusValid) + } else if _, ok := err.(RuleError); ok { + b.index.SetStatusFlags(node, statusValidateFailed) + } else { + return false, err + } + + // Intentionally ignore errors writing updated node status to DB. If + // it fails to write, it's not the end of the world. If the block is + // valid, we flush in connectBlock and if the block is invalid, the + // worst that can happen is we revalidate the block after a restart. + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", + writeErr) + } + if err != nil { - if _, ok := err.(RuleError); ok { - b.index.SetStatusFlags(node, statusValidateFailed) - } return false, err } - b.index.SetStatusFlags(node, statusValid) } // In the fast add case the code to check the block connection @@ -1097,11 +1126,16 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // Reorganize the chain. log.Infof("REORGANIZE: Block %v is causing a reorganize.", node.hash) err := b.reorganizeChain(detachNodes, attachNodes) - if err != nil { - return false, err + + // Either getReorganizeNodes or reorganizeChain could have made unsaved + // changes to the block index, so flush regardless of whether there was an + // error. The index would only be dirty if the block failed to connect, so + // we can ignore any errors writing. + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", writeErr) } - return true, nil + return err == nil, err } // isCurrent returns whether or not the chain believes it is current. Several diff --git a/blockchain/chainio.go b/blockchain/chainio.go index d7ff6ba197..4455849453 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1076,7 +1076,7 @@ func (b *BlockChain) createChainState() error { b.bestChain.SetTip(node) // Add the new node to the index which is used for faster lookups. - b.index.AddNode(node) + b.index.addNode(node) // Initialize the state related to the best block. Since it is the // genesis block, use its timestamp for the median time. @@ -1150,8 +1150,7 @@ func (b *BlockChain) createChainState() error { func (b *BlockChain) initChainState() error { // Determine the state of the chain database. We may need to initialize // everything from scratch or upgrade certain buckets. - var initialized bool - var hasBlockIndex bool + var initialized, hasBlockIndex bool err := b.db.View(func(dbTx database.Tx) error { initialized = dbTx.Metadata().Get(chainStateKeyName) != nil hasBlockIndex = dbTx.Metadata().Bucket(blockIndexBucketName) != nil @@ -1209,9 +1208,7 @@ func (b *BlockChain) initChainState() error { var lastNode *blockNode cursor = blockIndexBucket.Cursor() for ok := cursor.First(); ok; ok = cursor.Next() { - var header wire.BlockHeader - headerBytes := cursor.Value() - err := header.Deserialize(bytes.NewReader(headerBytes)) + header, status, err := deserializeBlockRow(cursor.Value()) if err != nil { return err } @@ -1243,9 +1240,9 @@ func (b *BlockChain) initChainState() error { // Initialize the block node for the block, connect it, // and add it to the block index. node := &blockNodes[i] - initBlockNode(node, &header, parent) - node.status = statusDataStored | statusValid - b.index.AddNode(node) + initBlockNode(node, header, parent) + node.status = status + b.index.addNode(node) lastNode = node i++ @@ -1281,6 +1278,25 @@ func (b *BlockChain) initChainState() error { }) } +// deserializeBlockRow parses a value in the block index bucket into a block +// header and block status bitfield. +func deserializeBlockRow(blockRow []byte) (*wire.BlockHeader, blockStatus, error) { + buffer := bytes.NewReader(blockRow) + + var header wire.BlockHeader + err := header.Deserialize(buffer) + if err != nil { + return nil, statusNone, err + } + + statusByte, err := buffer.ReadByte() + if err != nil { + return nil, statusNone, err + } + + return &header, blockStatus(statusByte), nil +} + // dbFetchHeaderByHash uses an existing database transaction to retrieve the // block header for the provided hash. func dbFetchHeaderByHash(dbTx database.Tx, hash *chainhash.Hash) (*wire.BlockHeader, error) { @@ -1329,40 +1345,31 @@ func dbFetchBlockByNode(dbTx database.Tx, node *blockNode) (*btcutil.Block, erro return block, nil } -// dbStoreBlock stores the provided block in the database. The block header is -// written to the block index bucket and full block data is written to ffldb. -func dbStoreBlockHeader(dbTx database.Tx, blockHeader *wire.BlockHeader, height uint32) error { - // Serialize block data to be stored. This is just the serialized header. - w := bytes.NewBuffer(make([]byte, 0, blockHdrSize)) - err := blockHeader.Serialize(w) +// dbStoreBlockNode stores the block header and validation status to the block +// index bucket. This overwrites the current entry if there exists one. +func dbStoreBlockNode(dbTx database.Tx, node *blockNode) error { + // Serialize block data to be stored. + w := bytes.NewBuffer(make([]byte, 0, blockHdrSize+1)) + header := node.Header() + err := header.Serialize(w) + if err != nil { + return err + } + err = w.WriteByte(byte(node.status)) if err != nil { return err } value := w.Bytes() // Write block header data to block index bucket. - blockHash := blockHeader.BlockHash() blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName) - key := blockIndexKey(&blockHash, height) + key := blockIndexKey(&node.hash, uint32(node.height)) return blockIndexBucket.Put(key, value) } -// dbStoreBlock stores the provided block in the database. The block header is -// written to the block index bucket and full block data is written to ffldb. +// dbStoreBlock stores the provided block in the database if it is not already +// there. The full block data is written to ffldb. func dbStoreBlock(dbTx database.Tx, block *btcutil.Block) error { - if block.Height() == btcutil.BlockHeightUnknown { - return fmt.Errorf("cannot store block %s with unknown height", - block.Hash()) - } - - // First store block header in the block index bucket. - err := dbStoreBlockHeader(dbTx, &block.MsgBlock().Header, - uint32(block.Height())) - if err != nil { - return err - } - - // Then store block data in ffldb if we haven't already. hasBlock, err := dbTx.HasBlock(block.Hash()) if err != nil { return err From 9aa9e79ebf7f11f1f70533c100e5c835a6af8c0f Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 9 Oct 2017 11:38:49 -0700 Subject: [PATCH 0045/1056] blockchain: Enhance migration to v2 block index bucket. This updates the block index migration to also store entries with valid status bytes. --- blockchain/upgrade.go | 111 ++++++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 26 deletions(-) diff --git a/blockchain/upgrade.go b/blockchain/upgrade.go index f980d0152c..5970913929 100644 --- a/blockchain/upgrade.go +++ b/blockchain/upgrade.go @@ -23,6 +23,16 @@ const ( blockHdrOffset = 12 ) +// blockChainContext represents a particular block's placement in the block +// chain. This is used by the block index migration to track block metadata that +// will be written to disk. +type blockChainContext struct { + parent *chainhash.Hash + children []*chainhash.Hash + height int32 + mainChain bool +} + // migrateBlockIndex migrates all block entries from the v1 block index bucket // to the v2 bucket. The v1 bucket stores all block entries keyed by block hash, // whereas the v2 bucket stores the exact same values, but keyed instead by @@ -47,15 +57,29 @@ func migrateBlockIndex(db database.DB) error { return err } + // Get tip of the main chain. + serializedData := dbTx.Metadata().Get(chainStateKeyName) + state, err := deserializeBestChainState(serializedData) + if err != nil { + return err + } + tip := &state.hash + // Scan the old block index bucket and construct a mapping of each block - // to all child blocks. - childBlocksMap, err := readBlockTree(v1BlockIdxBucket) + // to parent block and all child blocks. + blocksMap, err := readBlockTree(v1BlockIdxBucket) if err != nil { return err } // Use the block graph to calculate the height of each block. - blockHeights := determineBlockHeights(childBlocksMap) + err = determineBlockHeights(blocksMap) + if err != nil { + return err + } + + // Find blocks on the main chain with the block graph and current tip. + determineMainChainBlocks(blocksMap, tip) // Now that we have heights for all blocks, scan the old block index // bucket and insert all rows into the new one. @@ -65,16 +89,26 @@ func migrateBlockIndex(db database.DB) error { var hash chainhash.Hash copy(hash[:], hashBytes[0:chainhash.HashSize]) + chainContext := blocksMap[hash] - height, exists := blockHeights[hash] - if !exists { + if chainContext.height == -1 { return fmt.Errorf("Unable to calculate chain height for "+ "stored block %s", hash) } + // Mark blocks as valid if they are part of the main chain. + status := statusDataStored + if chainContext.mainChain { + status |= statusValid + } + // Write header to v2 bucket - key := blockIndexKey(&hash, height) - err := v2BlockIdxBucket.Put(key, headerBytes) + value := make([]byte, blockHdrSize+1) + copy(value[0:blockHdrSize], headerBytes) + value[blockHdrSize] = byte(status) + + key := blockIndexKey(&hash, uint32(chainContext.height)) + err := v2BlockIdxBucket.Put(key, value) if err != nil { return err } @@ -93,10 +127,11 @@ func migrateBlockIndex(db database.DB) error { } // readBlockTree reads the old block index bucket and constructs a mapping of -// each block to all child blocks. This mapping represents the full tree of -// blocks. -func readBlockTree(v1BlockIdxBucket database.Bucket) (map[chainhash.Hash][]*chainhash.Hash, error) { - childBlocksMap := make(map[chainhash.Hash][]*chainhash.Hash) +// each block to its parent block and all child blocks. This mapping represents +// the full tree of blocks. This function does not populate the height or +// mainChain fields of the returned blockChainContext values. +func readBlockTree(v1BlockIdxBucket database.Bucket) (map[chainhash.Hash]*blockChainContext, error) { + blocksMap := make(map[chainhash.Hash]*blockChainContext) err := v1BlockIdxBucket.ForEach(func(_, blockRow []byte) error { var header wire.BlockHeader endOffset := blockHdrOffset + blockHdrSize @@ -107,41 +142,65 @@ func readBlockTree(v1BlockIdxBucket database.Bucket) (map[chainhash.Hash][]*chai } blockHash := header.BlockHash() - childBlocksMap[header.PrevBlock] = - append(childBlocksMap[header.PrevBlock], &blockHash) + prevHash := header.PrevBlock + + if blocksMap[blockHash] == nil { + blocksMap[blockHash] = &blockChainContext{height: -1} + } + if blocksMap[prevHash] == nil { + blocksMap[prevHash] = &blockChainContext{height: -1} + } + + blocksMap[blockHash].parent = &prevHash + blocksMap[prevHash].children = + append(blocksMap[prevHash].children, &blockHash) return nil }) - return childBlocksMap, err + return blocksMap, err } // determineBlockHeights takes a map of block hashes to a slice of child hashes // and uses it to compute the height for each block. The function assigns a // height of 0 to the genesis hash and explores the tree of blocks // breadth-first, assigning a height to every block with a path back to the -// genesis block. -func determineBlockHeights(childBlocksMap map[chainhash.Hash][]*chainhash.Hash) map[chainhash.Hash]uint32 { - blockHeights := make(map[chainhash.Hash]uint32) +// genesis block. This function modifies the height field on the blocksMap +// entries. +func determineBlockHeights(blocksMap map[chainhash.Hash]*blockChainContext) error { queue := list.New() - // The genesis block is included in childBlocksMap as a child of the zero - // hash because that is the value of the PrevBlock field in the genesis - // header. - for _, genesisHash := range childBlocksMap[zeroHash] { - blockHeights[*genesisHash] = 0 + // The genesis block is included in blocksMap as a child of the zero hash + // because that is the value of the PrevBlock field in the genesis header. + preGenesisContext, exists := blocksMap[zeroHash] + if !exists || len(preGenesisContext.children) == 0 { + return fmt.Errorf("Unable to find genesis block") + } + + for _, genesisHash := range preGenesisContext.children { + blocksMap[*genesisHash].height = 0 queue.PushBack(genesisHash) } for e := queue.Front(); e != nil; e = queue.Front() { queue.Remove(e) hash := e.Value.(*chainhash.Hash) - height := blockHeights[*hash] + height := blocksMap[*hash].height // For each block with this one as a parent, assign it a height and // push to queue for future processing. - for _, childHash := range childBlocksMap[*hash] { - blockHeights[*childHash] = height + 1 + for _, childHash := range blocksMap[*hash].children { + blocksMap[*childHash].height = height + 1 queue.PushBack(childHash) } } - return blockHeights + + return nil +} + +// determineMainChainBlocks traverses the block graph down from the tip to +// determine which block hashes that are part of the main chain. This function +// modifies the mainChain field on the blocksMap entries. +func determineMainChainBlocks(blocksMap map[chainhash.Hash]*blockChainContext, tip *chainhash.Hash) { + for nextHash := tip; *nextHash != zeroHash; nextHash = blocksMap[*nextHash].parent { + blocksMap[*nextHash].mainChain = true + } } From 50de9da05b50eb15658bb350f6ea24368a111ab7 Mon Sep 17 00:00:00 2001 From: Alex Manuskin Date: Wed, 31 Jan 2018 10:40:46 +0200 Subject: [PATCH 0046/1056] blockchain: Fix typo in example_test.go. --- blockchain/example_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockchain/example_test.go b/blockchain/example_test.go index c7163e0e08..691d0927f2 100644 --- a/blockchain/example_test.go +++ b/blockchain/example_test.go @@ -18,7 +18,7 @@ import ( ) // This example demonstrates how to create a new chain instance and use -// ProcessBlock to attempt to attempt add a block to the chain. As the package +// ProcessBlock to attempt to add a block to the chain. As the package // overview documentation describes, this includes all of the Bitcoin consensus // rules. This example intentionally attempts to insert a duplicate genesis // block to illustrate how an invalid block is handled. From 0ef0d8c59b58ccfc8ac814dd6dac3990d4a16be2 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Fri, 9 Feb 2018 08:34:30 -0800 Subject: [PATCH 0047/1056] blockchain: Initialize database with genesis block. This fixes a bug introduced by #1066. --- blockchain/chainio.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 4455849453..3b0e258418 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1125,6 +1125,12 @@ func (b *BlockChain) createChainState() error { return err } + // Save the genesis block to the block index database. + err = dbStoreBlockNode(dbTx, node) + if err != nil { + return err + } + // Add the genesis block hash to height and height to hash // mappings to the index. err = dbPutBlockIndex(dbTx, &node.hash, node.height) From 99a26bf7e0998e938001eee57b0301fdf1de082d Mon Sep 17 00:00:00 2001 From: benma Date: Mon, 5 Feb 2018 10:30:51 +0100 Subject: [PATCH 0048/1056] wire: typo in BlockHeader PrevBlock comment --- wire/blockheader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/blockheader.go b/wire/blockheader.go index 892cf3ca69..9c9c2237e6 100644 --- a/wire/blockheader.go +++ b/wire/blockheader.go @@ -23,7 +23,7 @@ type BlockHeader struct { // Version of the block. This is not the same as the protocol version. Version int32 - // Hash of the previous block in the block chain. + // Hash of the previous block header in the block chain. PrevBlock chainhash.Hash // Merkle tree reference to hash of all transactions for the block. From 9866016012e7992f394888a4e65ec4315dfa8d49 Mon Sep 17 00:00:00 2001 From: Kai Date: Sun, 4 Feb 2018 22:55:31 +0800 Subject: [PATCH 0049/1056] Fix sub packages links --- docs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index ee208dd029..c00d295e7a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -268,9 +268,9 @@ information. * The btcsuite Bitcoin-related Go Packages: - * [btcrpcclient](https://github.com/btcsuite/btcrpcclient) - Implements a + * [btcrpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) - Implements a robust and easy to use Websocket-enabled Bitcoin JSON-RPC client - * [btcjson](https://github.com/btcsuite/btcjson) - Provides an extensive API + * [btcjson](https://github.com/btcsuite/btcd/tree/master/btcjson) - Provides an extensive API for the underlying JSON-RPC command and return values * [wire](https://github.com/btcsuite/btcd/tree/master/wire) - Implements the Bitcoin wire protocol From 1cd648d7842a04376ce45765c0d5e4415be41b9b Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Fri, 16 Feb 2018 16:18:43 -0500 Subject: [PATCH 0050/1056] Require atomic swap contracts to specify the secret size. This allows redeeming parties to audit the secret size and ensure it will be usable once revealed. --- txscript/standard.go | 61 +++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 2ba5c8d962..a7e929d101 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -629,6 +629,7 @@ type AtomicSwapDataPushes struct { RecipientHash160 [20]byte RefundHash160 [20]byte SecretHash [32]byte + SecretSize int64 LockTime int64 } @@ -643,47 +644,61 @@ type AtomicSwapDataPushes struct { // // This function is only defined in the txscript package due to API limitations // which prevent callers using txscript to parse nonstandard scripts. -func ExtractAtomicSwapDataPushes(pkScript []byte) (*AtomicSwapDataPushes, error) { +func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDataPushes, error) { pops, err := parseScript(pkScript) if err != nil { return nil, err } - if len(pops) != 17 { + if len(pops) != 20 { return nil, nil } isAtomicSwap := pops[0].opcode.value == OP_IF && - pops[1].opcode.value == OP_SHA256 && - pops[2].opcode.value == OP_DATA_32 && + pops[1].opcode.value == OP_SIZE && + canonicalPush(pops[2]) && pops[3].opcode.value == OP_EQUALVERIFY && - pops[4].opcode.value == OP_DUP && - pops[5].opcode.value == OP_HASH160 && - pops[6].opcode.value == OP_DATA_20 && - pops[7].opcode.value == OP_ELSE && - canonicalPush(pops[8]) && - pops[9].opcode.value == OP_CHECKLOCKTIMEVERIFY && - pops[10].opcode.value == OP_DROP && - pops[11].opcode.value == OP_DUP && - pops[12].opcode.value == OP_HASH160 && - pops[13].opcode.value == OP_DATA_20 && - pops[14].opcode.value == OP_ENDIF && - pops[15].opcode.value == OP_EQUALVERIFY && - pops[16].opcode.value == OP_CHECKSIG + pops[4].opcode.value == OP_SHA256 && + pops[5].opcode.value == OP_DATA_32 && + pops[6].opcode.value == OP_EQUALVERIFY && + pops[7].opcode.value == OP_DUP && + pops[8].opcode.value == OP_HASH160 && + pops[9].opcode.value == OP_DATA_20 && + pops[10].opcode.value == OP_ELSE && + canonicalPush(pops[11]) && + pops[12].opcode.value == OP_CHECKLOCKTIMEVERIFY && + pops[13].opcode.value == OP_DROP && + pops[14].opcode.value == OP_DUP && + pops[15].opcode.value == OP_HASH160 && + pops[16].opcode.value == OP_DATA_20 && + pops[17].opcode.value == OP_ENDIF && + pops[18].opcode.value == OP_EQUALVERIFY && + pops[19].opcode.value == OP_CHECKSIG if !isAtomicSwap { return nil, nil } pushes := new(AtomicSwapDataPushes) - copy(pushes.SecretHash[:], pops[2].data) - copy(pushes.RecipientHash160[:], pops[6].data) - copy(pushes.RefundHash160[:], pops[13].data) - if pops[8].data != nil { - locktime, err := makeScriptNum(pops[8].data, true, 5) + copy(pushes.SecretHash[:], pops[5].data) + copy(pushes.RecipientHash160[:], pops[9].data) + copy(pushes.RefundHash160[:], pops[16].data) + if pops[2].data != nil { + locktime, err := makeScriptNum(pops[2].data, true, 5) + if err != nil { + return nil, nil + } + pushes.SecretSize = int64(locktime) + } else if op := pops[2].opcode; isSmallInt(op) { + pushes.SecretSize = int64(asSmallInt(op)) + } else { + return nil, nil + } + if pops[11].data != nil { + locktime, err := makeScriptNum(pops[11].data, true, 5) if err != nil { return nil, nil } pushes.LockTime = int64(locktime) - } else if op := pops[8].opcode; isSmallInt(op) { + } else if op := pops[11].opcode; isSmallInt(op) { pushes.LockTime = int64(asSmallInt(op)) } else { return nil, nil From 2be2f12b358dc57d70b8f501b00be450192efbc3 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 19 Feb 2018 18:36:29 -0600 Subject: [PATCH 0051/1056] rpcclient: Update for go1.10 breaking changes. Go 1.10 made some changes such that json.Unmarshal can no longer unmarshal into exported fields that are themselves embedded via an uninitialized unexported pointer. Since rpcclient previously relied on this behavior, this updates the client to create the pointers before unmarshalling into the struct. --- rpcclient/infrastructure.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index fe195cd70b..27f7f21f1b 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -310,6 +310,8 @@ func (c *Client) handleMessage(msg []byte) { // Attempt to unmarshal the message as either a notification or // response. var in inMessage + in.rawResponse = new(rawResponse) + in.rawNotification = new(rawNotification) err := json.Unmarshal(msg, &in) if err != nil { log.Warnf("Remote server sent invalid message: %v", err) From ea82dfdee12c53efb64c5855139c032e8f05c8e6 Mon Sep 17 00:00:00 2001 From: Grace Noah Date: Tue, 20 Feb 2018 08:36:14 +0000 Subject: [PATCH 0052/1056] fix NewImportAddressCmd rescan wrong parameters fix #1126 --- btcjson/btcwalletextcmds.go | 4 +++- btcjson/btcwalletextcmds_test.go | 13 +++++++------ rpcclient/wallet.go | 10 +++++----- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/btcjson/btcwalletextcmds.go b/btcjson/btcwalletextcmds.go index 9cbc273a6d..3982a13551 100644 --- a/btcjson/btcwalletextcmds.go +++ b/btcjson/btcwalletextcmds.go @@ -36,14 +36,16 @@ func NewDumpWalletCmd(filename string) *DumpWalletCmd { // ImportAddressCmd defines the importaddress JSON-RPC command. type ImportAddressCmd struct { Address string + Account string Rescan *bool `jsonrpcdefault:"true"` } // NewImportAddressCmd returns a new instance which can be used to issue an // importaddress JSON-RPC command. -func NewImportAddressCmd(address string, rescan *bool) *ImportAddressCmd { +func NewImportAddressCmd(address string, account string, rescan *bool) *ImportAddressCmd { return &ImportAddressCmd{ Address: address, + Account: account, Rescan: rescan, } } diff --git a/btcjson/btcwalletextcmds_test.go b/btcjson/btcwalletextcmds_test.go index e478a08897..58de1c81d0 100644 --- a/btcjson/btcwalletextcmds_test.go +++ b/btcjson/btcwalletextcmds_test.go @@ -58,12 +58,12 @@ func TestBtcWalletExtCmds(t *testing.T) { { name: "importaddress", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("importaddress", "1Address") + return btcjson.NewCmd("importaddress", "1Address", "") }, staticCmd: func() interface{} { - return btcjson.NewImportAddressCmd("1Address", nil) + return btcjson.NewImportAddressCmd("1Address", "", nil) }, - marshalled: `{"jsonrpc":"1.0","method":"importaddress","params":["1Address"],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"importaddress","params":["1Address",""],"id":1}`, unmarshalled: &btcjson.ImportAddressCmd{ Address: "1Address", Rescan: btcjson.Bool(true), @@ -72,14 +72,15 @@ func TestBtcWalletExtCmds(t *testing.T) { { name: "importaddress optional", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("importaddress", "1Address", false) + return btcjson.NewCmd("importaddress", "1Address", "acct", false) }, staticCmd: func() interface{} { - return btcjson.NewImportAddressCmd("1Address", btcjson.Bool(false)) + return btcjson.NewImportAddressCmd("1Address", "acct", btcjson.Bool(false)) }, - marshalled: `{"jsonrpc":"1.0","method":"importaddress","params":["1Address",false],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"importaddress","params":["1Address","acct",false],"id":1}`, unmarshalled: &btcjson.ImportAddressCmd{ Address: "1Address", + Account: "acct", Rescan: btcjson.Bool(false), }, }, diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 10c12f1f70..27546f5de0 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2078,7 +2078,7 @@ func (r FutureImportAddressResult) Receive() error { // // See ImportAddress for the blocking version and more details. func (c *Client) ImportAddressAsync(address string) FutureImportAddressResult { - cmd := btcjson.NewImportAddressCmd(address, nil) + cmd := btcjson.NewImportAddressCmd(address, "", nil) return c.sendCmd(cmd) } @@ -2092,15 +2092,15 @@ func (c *Client) ImportAddress(address string) error { // returned instance. // // See ImportAddress for the blocking version and more details. -func (c *Client) ImportAddressRescanAsync(address string, rescan bool) FutureImportAddressResult { - cmd := btcjson.NewImportAddressCmd(address, &rescan) +func (c *Client) ImportAddressRescanAsync(address string, account string, rescan bool) FutureImportAddressResult { + cmd := btcjson.NewImportAddressCmd(address, account, &rescan) return c.sendCmd(cmd) } // ImportAddressRescan imports the passed public address. When rescan is true, // the block history is scanned for transactions addressed to provided address. -func (c *Client) ImportAddressRescan(address string, rescan bool) error { - return c.ImportAddressRescanAsync(address, rescan).Receive() +func (c *Client) ImportAddressRescan(address string, account string, rescan bool) error { + return c.ImportAddressRescanAsync(address, account, rescan).Receive() } // FutureImportPrivKeyResult is a future promise to deliver the result of an From a942799999d1088caeecf64205427c56444035f3 Mon Sep 17 00:00:00 2001 From: Jasper Date: Mon, 16 Apr 2018 06:38:35 +0200 Subject: [PATCH 0053/1056] Update README.md Use internet archive for old conformal blog entry link. --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index c00d295e7a..cb6517b186 100644 --- a/docs/README.md +++ b/docs/README.md @@ -47,7 +47,7 @@ transactions based on miner requirements ("standard" transactions). One key difference between btcd and Bitcoin Core is that btcd does *NOT* include wallet functionality and this was a very intentional design decision. See the -blog entry [here](https://blog.conformal.com/btcd-not-your-moms-bitcoin-daemon) +blog entry [here](https://web.archive.org/web/20171125143919/https://blog.conformal.com/btcd-not-your-moms-bitcoin-daemon) for more details. This means you can't actually make or receive payments directly with btcd. That functionality is provided by the [btcwallet](https://github.com/btcsuite/btcwallet) and From 675abc5df3c5531bc741b56a765e35623459da6d Mon Sep 17 00:00:00 2001 From: Vadym Popov Date: Tue, 20 Mar 2018 19:58:38 +0200 Subject: [PATCH 0054/1056] chaincfg: change hrp prefix for regtest network --- chaincfg/params.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chaincfg/params.go b/chaincfg/params.go index 38b8a37aac..9da7102b4a 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -379,7 +379,7 @@ var RegressionNetParams = Params{ // Human-readable part for Bech32 encoded segwit addresses, as defined in // BIP 173. - Bech32HRPSegwit: "tb", // always tb for test net + Bech32HRPSegwit: "bcrt", // always bcrt for reg test net // Address encoding magics PubKeyHashAddrID: 0x6f, // starts with m or n From 0734b553631c3e59d438c6acc1a8d00b22d385fd Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Sat, 21 Apr 2018 20:48:51 +0200 Subject: [PATCH 0055/1056] server: Fix bug disconnecting peer on filteradd --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index 3d381fb216..82faf9f516 100644 --- a/server.go +++ b/server.go @@ -799,7 +799,7 @@ func (sp *serverPeer) OnFilterAdd(_ *peer.Peer, msg *wire.MsgFilterAdd) { return } - if sp.filter.IsLoaded() { + if !sp.filter.IsLoaded() { peerLog.Debugf("%s sent a filteradd request with no filter "+ "loaded -- disconnecting", sp) sp.Disconnect() From 7580169cb66796062cc3e2468c49081264384496 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 19:22:15 -0700 Subject: [PATCH 0056/1056] build: update build to use go 1.9.5 and 1.10.1 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d0244683da..8727889c56 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: go go: - - 1.8.x - - 1.9.x + - "1.9.5" + - "1.10.1" sudo: false install: - GLIDE_TAG=v0.12.3 From 253b37c17f6570ea1f1070a2cbb8009b0d56744f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 19:28:09 -0700 Subject: [PATCH 0057/1056] btcec: format btcec_test.go with gofmt -s --- btcec/btcec_test.go | 252 ++++++++++++++++++++++---------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/btcec/btcec_test.go b/btcec/btcec_test.go index 6f14027116..c275514de7 100644 --- a/btcec/btcec_test.go +++ b/btcec/btcec_test.go @@ -898,132 +898,132 @@ var testVectors = []struct { r, s string ok bool }{ -/* - * All of these tests are disabled since they are for P224, not sec256k1. - * they are left here as an example of test vectors for when some *real* - * vectors may be found. - * - oga@conformal.com - { - "09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd", - "9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40", - "03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed", - "81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1", - "96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5", - false, - }, - { - "96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37", - "851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8", - "205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2", - "4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0", - "e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12", - false, - }, - { - "86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e", - "ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc", - "c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984", - "de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9", - "745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd", - true, - }, - { - "4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d", - "cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8", - "a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a", - "67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836", - "1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020", - false, - }, - { - "bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e", - "6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855", - "27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84", - "e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f", - "1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9", - false, - }, - { - "7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43", - "9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1", - "8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066", - "6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54", - "8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57", - false, - }, - { - "cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601", - "a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4", - "e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5", - "387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1", - "4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4", - false, - }, - { - "26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866", - "9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d", - "15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c", - "929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0", - "59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872", - true, - }, - { - "1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e", - "d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b", - "631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f", - "65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129", - "bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a", - false, - }, - { - "919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b", - "269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574", - "baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57", - "cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008", - "40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40", - false, - }, - { - "6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f", - "6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd", - "26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b", - "9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad", - "8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97", - true, - }, - { - "bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566", - "14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40", - "b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803", - "4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145", - "452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8", - false, - }, - { - "0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770", - "d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac", - "76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb", - "bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca", - "9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e", - false, - }, - { - "5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92", - "7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6", - "44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9", - "084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8", - "079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3", - false, - }, - { - "1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845", - "31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493", - "a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4", - "bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c", - "ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0", - false, - }, -*/ + /* + * All of these tests are disabled since they are for P224, not sec256k1. + * they are left here as an example of test vectors for when some *real* + * vectors may be found. + * - oga@conformal.com + { + "09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd", + "9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40", + "03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed", + "81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1", + "96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5", + false, + }, + { + "96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37", + "851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8", + "205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2", + "4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0", + "e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12", + false, + }, + { + "86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e", + "ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc", + "c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984", + "de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9", + "745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd", + true, + }, + { + "4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d", + "cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8", + "a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a", + "67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836", + "1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020", + false, + }, + { + "bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e", + "6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855", + "27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84", + "e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f", + "1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9", + false, + }, + { + "7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43", + "9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1", + "8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066", + "6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54", + "8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57", + false, + }, + { + "cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601", + "a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4", + "e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5", + "387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1", + "4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4", + false, + }, + { + "26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866", + "9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d", + "15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c", + "929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0", + "59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872", + true, + }, + { + "1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e", + "d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b", + "631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f", + "65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129", + "bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a", + false, + }, + { + "919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b", + "269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574", + "baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57", + "cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008", + "40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40", + false, + }, + { + "6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f", + "6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd", + "26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b", + "9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad", + "8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97", + true, + }, + { + "bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566", + "14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40", + "b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803", + "4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145", + "452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8", + false, + }, + { + "0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770", + "d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac", + "76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb", + "bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca", + "9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e", + false, + }, + { + "5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92", + "7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6", + "44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9", + "084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8", + "079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3", + false, + }, + { + "1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845", + "31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493", + "a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4", + "bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c", + "ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0", + false, + }, + */ } func TestVectors(t *testing.T) { From 04f0b5338a5d55d0b80314de28155c263b699a33 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 20:01:58 -0700 Subject: [PATCH 0058/1056] build: switch to stable version of gometalinter --- .travis.yml | 4 ++-- goclean.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8727889c56..0d4fb385e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,8 @@ install: - export PATH=$PATH:$PWD/linux-amd64/ - glide install - go install . ./cmd/... - - go get -v github.com/alecthomas/gometalinter - - gometalinter --install + - go get -u gopkg.in/alecthomas/gometalinter.v2 + - gometalinter.v2 --install script: - export PATH=$PATH:$HOME/gopath/bin - ./goclean.sh diff --git a/goclean.sh b/goclean.sh index bcbd52400d..548baf8bdb 100755 --- a/goclean.sh +++ b/goclean.sh @@ -21,14 +21,14 @@ fi # Make sure gometalinter is installed and $GOPATH/bin is in your path. # $ go get -v github.com/alecthomas/gometalinter" # $ gometalinter --install" -if [ ! -x "$(type -p gometalinter)" ]; then +if [ ! -x "$(type -p gometalinter.v2)" ]; then exit 1 fi linter_targets=$(glide novendor) # Automatic checks -test -z "$(gometalinter -j 4 --disable-all \ +test -z "$(gometalinter.v2 -j 4 --disable-all \ --enable=gofmt \ --enable=golint \ --enable=vet \ From 2842f933bb32cf3e9e8901dae4b12d19db4e098c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 20:06:16 -0700 Subject: [PATCH 0059/1056] server: fix linter error --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index 3d381fb216..4faa21167b 100644 --- a/server.go +++ b/server.go @@ -902,7 +902,7 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) { // A message that has no addresses is invalid. if len(msg.AddrList) == 0 { peerLog.Errorf("Command [%s] from %s does not contain any addresses", - msg.Command(), sp) + msg.Command(), sp.Peer) sp.Disconnect() return } From 4b968f7e181e617a4e00dbf7282d4a35c572d315 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 20:17:46 -0700 Subject: [PATCH 0060/1056] btcec: remove obsolete test --- btcec/btcec_test.go | 162 -------------------------------------------- 1 file changed, 162 deletions(-) diff --git a/btcec/btcec_test.go b/btcec/btcec_test.go index c275514de7..42a69037bc 100644 --- a/btcec/btcec_test.go +++ b/btcec/btcec_test.go @@ -8,8 +8,6 @@ package btcec import ( "crypto/rand" - "crypto/sha1" - "encoding/hex" "fmt" "math/big" "testing" @@ -889,163 +887,3 @@ func TestNAFRand(t *testing.T) { } } } - -// These test vectors were taken from -// http://csrc.nist.gov/groups/STM/cavp/documents/dss/ecdsatestvectors.zip -var testVectors = []struct { - msg string - Qx, Qy string - r, s string - ok bool -}{ - /* - * All of these tests are disabled since they are for P224, not sec256k1. - * they are left here as an example of test vectors for when some *real* - * vectors may be found. - * - oga@conformal.com - { - "09626b45493672e48f3d1226a3aff3201960e577d33a7f72c7eb055302db8fe8ed61685dd036b554942a5737cd1512cdf811ee0c00e6dd2f08c69f08643be396e85dafda664801e772cdb7396868ac47b172245b41986aa2648cb77fbbfa562581be06651355a0c4b090f9d17d8f0ab6cced4e0c9d386cf465a516630f0231bd", - "9504b5b82d97a264d8b3735e0568decabc4b6ca275bc53cbadfc1c40", - "03426f80e477603b10dee670939623e3da91a94267fc4e51726009ed", - "81d3ac609f9575d742028dd496450a58a60eea2dcf8b9842994916e1", - "96a8c5f382c992e8f30ccce9af120b067ec1d74678fa8445232f75a5", - false, - }, - { - "96b2b6536f6df29be8567a72528aceeaccbaa66c66c534f3868ca9778b02faadb182e4ed34662e73b9d52ecbe9dc8e875fc05033c493108b380689ebf47e5b062e6a0cdb3dd34ce5fe347d92768d72f7b9b377c20aea927043b509c078ed2467d7113405d2ddd458811e6faf41c403a2a239240180f1430a6f4330df5d77de37", - "851e3100368a22478a0029353045ae40d1d8202ef4d6533cfdddafd8", - "205302ac69457dd345e86465afa72ee8c74ca97e2b0b999aec1f10c2", - "4450c2d38b697e990721aa2dbb56578d32b4f5aeb3b9072baa955ee0", - "e26d4b589166f7b4ba4b1c8fce823fa47aad22f8c9c396b8c6526e12", - false, - }, - { - "86778dbb4a068a01047a8d245d632f636c11d2ad350740b36fad90428b454ad0f120cb558d12ea5c8a23db595d87543d06d1ef489263d01ee529871eb68737efdb8ff85bc7787b61514bed85b7e01d6be209e0a4eb0db5c8df58a5c5bf706d76cb2bdf7800208639e05b89517155d11688236e6a47ed37d8e5a2b1e0adea338e", - "ad5bda09d319a717c1721acd6688d17020b31b47eef1edea57ceeffc", - "c8ce98e181770a7c9418c73c63d01494b8b80a41098c5ea50692c984", - "de5558c257ab4134e52c19d8db3b224a1899cbd08cc508ce8721d5e9", - "745db7af5a477e5046705c0a5eff1f52cb94a79d481f0c5a5e108ecd", - true, - }, - { - "4bc6ef1958556686dab1e39c3700054a304cbd8f5928603dcd97fafd1f29e69394679b638f71c9344ce6a535d104803d22119f57b5f9477e253817a52afa9bfbc9811d6cc8c8be6b6566c6ef48b439bbb532abe30627548c598867f3861ba0b154dc1c3deca06eb28df8efd28258554b5179883a36fbb1eecf4f93ee19d41e3d", - "cc5eea2edf964018bdc0504a3793e4d2145142caa09a72ac5fb8d3e8", - "a48d78ae5d08aa725342773975a00d4219cf7a8029bb8cf3c17c374a", - "67b861344b4e416d4094472faf4272f6d54a497177fbc5f9ef292836", - "1d54f3fcdad795bf3b23408ecbac3e1321d1d66f2e4e3d05f41f7020", - false, - }, - { - "bb658732acbf3147729959eb7318a2058308b2739ec58907dd5b11cfa3ecf69a1752b7b7d806fe00ec402d18f96039f0b78dbb90a59c4414fb33f1f4e02e4089de4122cd93df5263a95be4d7084e2126493892816e6a5b4ed123cb705bf930c8f67af0fb4514d5769232a9b008a803af225160ce63f675bd4872c4c97b146e5e", - "6234c936e27bf141fc7534bfc0a7eedc657f91308203f1dcbd642855", - "27983d87ca785ef4892c3591ef4a944b1deb125dd58bd351034a6f84", - "e94e05b42d01d0b965ffdd6c3a97a36a771e8ea71003de76c4ecb13f", - "1dc6464ffeefbd7872a081a5926e9fc3e66d123f1784340ba17737e9", - false, - }, - { - "7c00be9123bfa2c4290be1d8bc2942c7f897d9a5b7917e3aabd97ef1aab890f148400a89abd554d19bec9d8ed911ce57b22fbcf6d30ca2115f13ce0a3f569a23bad39ee645f624c49c60dcfc11e7d2be24de9c905596d8f23624d63dc46591d1f740e46f982bfae453f107e80db23545782be23ce43708245896fc54e1ee5c43", - "9f3f037282aaf14d4772edffff331bbdda845c3f65780498cde334f1", - "8308ee5a16e3bcb721b6bc30000a0419bc1aaedd761be7f658334066", - "6381d7804a8808e3c17901e4d283b89449096a8fba993388fa11dc54", - "8e858f6b5b253686a86b757bad23658cda53115ac565abca4e3d9f57", - false, - }, - { - "cffc122a44840dc705bb37130069921be313d8bde0b66201aebc48add028ca131914ef2e705d6bedd19dc6cf9459bbb0f27cdfe3c50483808ffcdaffbeaa5f062e097180f07a40ef4ab6ed03fe07ed6bcfb8afeb42c97eafa2e8a8df469de07317c5e1494c41547478eff4d8c7d9f0f484ad90fedf6e1c35ee68fa73f1691601", - "a03b88a10d930002c7b17ca6af2fd3e88fa000edf787dc594f8d4fd4", - "e0cf7acd6ddc758e64847fe4df9915ebda2f67cdd5ec979aa57421f5", - "387b84dcf37dc343c7d2c5beb82f0bf8bd894b395a7b894565d296c1", - "4adc12ce7d20a89ce3925e10491c731b15ddb3f339610857a21b53b4", - false, - }, - { - "26e0e0cafd85b43d16255908ccfd1f061c680df75aba3081246b337495783052ba06c60f4a486c1591a4048bae11b4d7fec4f161d80bdc9a7b79d23e44433ed625eab280521a37f23dd3e1bdc5c6a6cfaa026f3c45cf703e76dab57add93fe844dd4cda67dc3bddd01f9152579e49df60969b10f09ce9372fdd806b0c7301866", - "9a8983c42f2b5a87c37a00458b5970320d247f0c8a88536440173f7d", - "15e489ec6355351361900299088cfe8359f04fe0cab78dde952be80c", - "929a21baa173d438ec9f28d6a585a2f9abcfc0a4300898668e476dc0", - "59a853f046da8318de77ff43f26fe95a92ee296fa3f7e56ce086c872", - true, - }, - { - "1078eac124f48ae4f807e946971d0de3db3748dd349b14cca5c942560fb25401b2252744f18ad5e455d2d97ed5ae745f55ff509c6c8e64606afe17809affa855c4c4cdcaf6b69ab4846aa5624ed0687541aee6f2224d929685736c6a23906d974d3c257abce1a3fb8db5951b89ecb0cda92b5207d93f6618fd0f893c32cf6a6e", - "d6e55820bb62c2be97650302d59d667a411956138306bd566e5c3c2b", - "631ab0d64eaf28a71b9cbd27a7a88682a2167cee6251c44e3810894f", - "65af72bc7721eb71c2298a0eb4eed3cec96a737cc49125706308b129", - "bd5a987c78e2d51598dbd9c34a9035b0069c580edefdacee17ad892a", - false, - }, - { - "919deb1fdd831c23481dfdb2475dcbe325b04c34f82561ced3d2df0b3d749b36e255c4928973769d46de8b95f162b53cd666cad9ae145e7fcfba97919f703d864efc11eac5f260a5d920d780c52899e5d76f8fe66936ff82130761231f536e6a3d59792f784902c469aa897aabf9a0678f93446610d56d5e0981e4c8a563556b", - "269b455b1024eb92d860a420f143ac1286b8cce43031562ae7664574", - "baeb6ca274a77c44a0247e5eb12ca72bdd9a698b3f3ae69c9f1aaa57", - "cb4ec2160f04613eb0dfe4608486091a25eb12aa4dec1afe91cfb008", - "40b01d8cd06589481574f958b98ca08ade9d2a8fe31024375c01bb40", - false, - }, - { - "6e012361250dacf6166d2dd1aa7be544c3206a9d43464b3fcd90f3f8cf48d08ec099b59ba6fe7d9bdcfaf244120aed1695d8be32d1b1cd6f143982ab945d635fb48a7c76831c0460851a3d62b7209c30cd9c2abdbe3d2a5282a9fcde1a6f418dd23c409bc351896b9b34d7d3a1a63bbaf3d677e612d4a80fa14829386a64b33f", - "6d2d695efc6b43b13c14111f2109608f1020e3e03b5e21cfdbc82fcd", - "26a4859296b7e360b69cf40be7bd97ceaffa3d07743c8489fc47ca1b", - "9a8cb5f2fdc288b7183c5b32d8e546fc2ed1ca4285eeae00c8b572ad", - "8c623f357b5d0057b10cdb1a1593dab57cda7bdec9cf868157a79b97", - true, - }, - { - "bf6bd7356a52b234fe24d25557200971fc803836f6fec3cade9642b13a8e7af10ab48b749de76aada9d8927f9b12f75a2c383ca7358e2566c4bb4f156fce1fd4e87ef8c8d2b6b1bdd351460feb22cdca0437ac10ca5e0abbbce9834483af20e4835386f8b1c96daaa41554ceee56730aac04f23a5c765812efa746051f396566", - "14250131b2599939cf2d6bc491be80ddfe7ad9de644387ee67de2d40", - "b5dc473b5d014cd504022043c475d3f93c319a8bdcb7262d9e741803", - "4f21642f2201278a95339a80f75cc91f8321fcb3c9462562f6cbf145", - "452a5f816ea1f75dee4fd514fa91a0d6a43622981966c59a1b371ff8", - false, - }, - { - "0eb7f4032f90f0bd3cf9473d6d9525d264d14c031a10acd31a053443ed5fe919d5ac35e0be77813071b4062f0b5fdf58ad5f637b76b0b305aec18f82441b6e607b44cdf6e0e3c7c57f24e6fd565e39430af4a6b1d979821ed0175fa03e3125506847654d7e1ae904ce1190ae38dc5919e257bdac2db142a6e7cd4da6c2e83770", - "d1f342b7790a1667370a1840255ac5bbbdc66f0bc00ae977d99260ac", - "76416cabae2de9a1000b4646338b774baabfa3db4673790771220cdb", - "bc85e3fc143d19a7271b2f9e1c04b86146073f3fab4dda1c3b1f35ca", - "9a5c70ede3c48d5f43307a0c2a4871934424a3303b815df4bb0f128e", - false, - }, - { - "5cc25348a05d85e56d4b03cec450128727bc537c66ec3a9fb613c151033b5e86878632249cba83adcefc6c1e35dcd31702929c3b57871cda5c18d1cf8f9650a25b917efaed56032e43b6fc398509f0d2997306d8f26675f3a8683b79ce17128e006aa0903b39eeb2f1001be65de0520115e6f919de902b32c38d691a69c58c92", - "7e49a7abf16a792e4c7bbc4d251820a2abd22d9f2fc252a7bf59c9a6", - "44236a8fb4791c228c26637c28ae59503a2f450d4cfb0dc42aa843b9", - "084461b4050285a1a85b2113be76a17878d849e6bc489f4d84f15cd8", - "079b5bddcc4d45de8dbdfd39f69817c7e5afa454a894d03ee1eaaac3", - false, - }, - { - "1951533ce33afb58935e39e363d8497a8dd0442018fd96dff167b3b23d7206a3ee182a3194765df4768a3284e23b8696c199b4686e670d60c9d782f08794a4bccc05cffffbd1a12acd9eb1cfa01f7ebe124da66ecff4599ea7720c3be4bb7285daa1a86ebf53b042bd23208d468c1b3aa87381f8e1ad63e2b4c2ba5efcf05845", - "31945d12ebaf4d81f02be2b1768ed80784bf35cf5e2ff53438c11493", - "a62bebffac987e3b9d3ec451eb64c462cdf7b4aa0b1bbb131ceaa0a4", - "bc3c32b19e42b710bca5c6aaa128564da3ddb2726b25f33603d2af3c", - "ed1a719cc0c507edc5239d76fe50e2306c145ad252bd481da04180c0", - false, - }, - */ -} - -func TestVectors(t *testing.T) { - sha := sha1.New() - - for i, test := range testVectors { - pub := PublicKey{ - Curve: S256(), - X: fromHex(test.Qx), - Y: fromHex(test.Qy), - } - msg, _ := hex.DecodeString(test.msg) - sha.Reset() - sha.Write(msg) - hashed := sha.Sum(nil) - sig := Signature{R: fromHex(test.r), S: fromHex(test.s)} - if verified := sig.Verify(hashed, &pub); verified != test.ok { - t.Errorf("%d: bad result %v instead of %v", i, verified, - test.ok) - } - if testing.Short() { - break - } - } -} From 1432d294a5b055c297457c25434efbf13384cc46 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 19:16:50 -0700 Subject: [PATCH 0061/1056] build: update glide to point to latest btcutil In this commit, we update the glide.lock file to be pinned against the latest btcutil commit hash. btcutil has recently been updated to pull in all changes from roasbeef's fork. Notably, it now includes the code necessary for creating GCS filters (BIP 158). --- glide.lock | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index f4480be1c1..b1d2e4a341 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,13 @@ hash: 976decfaf173d97d2e4572399490637aa12e217312a7d8b28813780a738e1151 -updated: 2017-08-24T17:28:45.8117156-05:00 +updated: 2018-05-15T19:16:29.311905983-07:00 imports: - name: github.com/btcsuite/btclog version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a - name: github.com/btcsuite/btcutil - version: 501929d3d046174c3d39f0ea54ece471aa17238c + version: b9afb0b9868a757e8fcc3c3adf5b129979f9b3e6 subpackages: - base58 + - bech32 - bloom - hdkeychain - name: github.com/btcsuite/go-socks @@ -41,7 +42,7 @@ imports: - svc - winapi - name: github.com/davecgh/go-spew - version: 346938d642f2ec3594ed81d874461961cd0faa76 + version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 subpackages: - spew - name: github.com/jessevdk/go-flags @@ -51,7 +52,7 @@ imports: subpackages: - rotator - name: golang.org/x/crypto - version: 122d919ec1efcfb58483215da23f815853e24b81 + version: 1a580b3eff7814fc9b40602fd35256c63b50f491 subpackages: - ripemd160 testImports: [] From d82e76cec9711a5544c16e69de76fee25973cc08 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 13 Dec 2016 09:34:25 +0000 Subject: [PATCH 0062/1056] Introduce a service flag for CBFs. Add a service flag for CBFs in the wire protocol. --- wire/protocol.go | 7 +++++++ wire/protocol_test.go | 2 ++ 2 files changed, 9 insertions(+) diff --git a/wire/protocol.go b/wire/protocol.go index 30fdb01eaa..9ea704fb20 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -10,6 +10,7 @@ import ( "strings" ) +// XXX pedro: we will probably need to bump this. const ( // ProtocolVersion is the latest protocol version this package supports. ProtocolVersion uint32 = 70013 @@ -70,6 +71,10 @@ const ( // SFNodeWitness is a flag used to indicate a peer supports blocks // and transactions including witness data (BIP0144). SFNodeWitness + + // SFNNodeCBF is a flag used to indicate a peer supports committed + // bloom filters (CBFs). + SFNodeCBF ) // Map of service flags back to their constant names for pretty printing. @@ -78,6 +83,7 @@ var sfStrings = map[ServiceFlag]string{ SFNodeGetUTXO: "SFNodeGetUTXO", SFNodeBloom: "SFNodeBloom", SFNodeWitness: "SFNodeWitness", + SFNodeCBF: "SFNodeCBF", } // orderedSFStrings is an ordered list of service flags from highest to @@ -87,6 +93,7 @@ var orderedSFStrings = []ServiceFlag{ SFNodeGetUTXO, SFNodeBloom, SFNodeWitness, + SFNodeCBF, } // String returns the ServiceFlag in human-readable form. diff --git a/wire/protocol_test.go b/wire/protocol_test.go index db9991f40e..dd3ea11f02 100644 --- a/wire/protocol_test.go +++ b/wire/protocol_test.go @@ -18,6 +18,8 @@ func TestServiceFlagStringer(t *testing.T) { {SFNodeBloom, "SFNodeBloom"}, {SFNodeWitness, "SFNodeWitness"}, {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|0xfffffff0"}, + {SFNodeCBF, "SFNodeCBF"}, + {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeCBF|0xfffffff0"}, } t.Logf("Running %d tests", len(tests)) From 333af136efc468731df137d405464a356e26b06d Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 13 Dec 2016 10:03:15 +0000 Subject: [PATCH 0063/1056] Create a knob to switch CBFs off. While having them on by default. We may want to revisit this and make no CBFs the default. --- config.go | 1 + doc.go | 1 + sample-btcd.conf | 3 +++ server.go | 6 +++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/config.go b/config.go index 1192be4f50..505b3fbb28 100644 --- a/config.go +++ b/config.go @@ -150,6 +150,7 @@ type config struct { BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"` UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."` NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"` + NoCBFilters bool `long:"nocbfilters" description:"Disable committed bloom filtering (CBF) support"` SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"` BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."` TxIndex bool `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` diff --git a/doc.go b/doc.go index 631568ffdd..9bb0f2e6c7 100644 --- a/doc.go +++ b/doc.go @@ -112,6 +112,7 @@ Application Options: --blockprioritysize= Size in bytes for high-priority/low-fee transactions when creating a block (50000) --nopeerbloomfilters Disable bloom filtering support. + --nocbfilters Disable committed bloom filtering (CBF) support. --sigcachemaxsize= The maximum number of entries in the signature verification cache. --blocksonly Do not accept transactions from remote peers. diff --git a/sample-btcd.conf b/sample-btcd.conf index 382b01143a..729d18ec75 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -167,6 +167,9 @@ ; Must not include characters '/', ':', '(' and ')'. ; uacomment= +; Disable committed peer bloom filtering (CBF). +; nocbfilters=1 + ; ------------------------------------------------------------------------------ ; RPC server options - The following options control the built-in RPC server ; which is used to control and query information from a running btcd process. diff --git a/server.go b/server.go index 4faa21167b..80fd0f42d7 100644 --- a/server.go +++ b/server.go @@ -43,7 +43,8 @@ import ( const ( // defaultServices describes the default services that are supported by // the server. - defaultServices = wire.SFNodeNetwork | wire.SFNodeBloom | wire.SFNodeWitness + defaultServices = wire.SFNodeNetwork | wire.SFNodeBloom | + wire.SFNodeWitness | wire.SFNodeCF // defaultRequiredServices describes the default services that are // required to be supported by outbound peers. @@ -2158,6 +2159,9 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param if cfg.NoPeerBloomFilters { services &^= wire.SFNodeBloom } + if cfg.NoCBFilters { + services &^= wire.SFNodeCBF + } amgr := addrmgr.New(cfg.DataDir, btcdLookup) From e9298934b97e5c49158150ce6ceebfdf52ccec53 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 13 Dec 2016 11:40:30 +0000 Subject: [PATCH 0064/1056] Add a stub GetCBFilter message. Actual semantic and payload format yet to be defined. --- peer/peer.go | 12 +++++++++++ peer/peer_test.go | 7 ++++++ server.go | 12 +++++++++++ wire/message.go | 4 ++++ wire/msggetcbfilter.go | 49 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+) create mode 100644 wire/msggetcbfilter.go diff --git a/peer/peer.go b/peer/peer.go index 4075c4353b..832331a00c 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -144,6 +144,10 @@ type MessageListeners struct { // message. OnGetHeaders func(p *Peer, msg *wire.MsgGetHeaders) + // OnGetCBFilter is invoked when a peer receives a getcbfilter bitcoin + // message. + OnGetCBFilter func(p *Peer, msg *wire.MsgGetCBFilter) + // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1280,6 +1284,9 @@ func (p *Peer) maybeAddDeadline(pendingResponses map[string]time.Time, msgCmd st // headers. deadline = time.Now().Add(stallResponseTimeout * 3) pendingResponses[wire.CmdHeaders] = deadline + + // XXX pedro: we may need to handle OnCBFilter here depending on the + // protocol behaviour defined. } } @@ -1579,6 +1586,11 @@ out: p.cfg.Listeners.OnGetHeaders(p, msg) } + case *wire.MsgGetCBFilter: + if p.cfg.Listeners.OnGetCBFilter != nil { + p.cfg.Listeners.OnGetCBFilter(p, msg) + } + case *wire.MsgFeeFilter: if p.cfg.Listeners.OnFeeFilter != nil { p.cfg.Listeners.OnFeeFilter(p, msg) diff --git a/peer/peer_test.go b/peer/peer_test.go index 590c95dc79..bbd4008df1 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -399,6 +399,9 @@ func TestPeerListeners(t *testing.T) { OnGetHeaders: func(p *peer.Peer, msg *wire.MsgGetHeaders) { ok <- msg }, + OnGetCBFilter: func(p *peer.Peer, msg *wire.MsgGetCBFilter) { + ok <- msg + }, OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { ok <- msg }, @@ -522,6 +525,10 @@ func TestPeerListeners(t *testing.T) { "OnGetHeaders", wire.NewMsgGetHeaders(), }, + { + "OnGetCBFilter", + wire.NewMsgGetCBFilter(&chainhash.Hash{}), + }, { "OnFeeFilter", wire.NewMsgFeeFilter(15000), diff --git a/server.go b/server.go index 80fd0f42d7..c180700daf 100644 --- a/server.go +++ b/server.go @@ -738,6 +738,17 @@ func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { sp.QueueMessage(&wire.MsgHeaders{Headers: blockHeaders}, nil) } +// OnGetCBFilter is invoked when a peer receives a getcbfilter bitcoin message. +func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) { + // Ignore getcbfilter requests if not in sync. + if !sp.server.blockManager.IsCurrent() { + return + } + + // XXX pedro: work in progress + peerLog.Warnf("received OnGetCBFilter") +} + // enforceNodeBloomFlag disconnects the peer if the server is not configured to // allow bloom filters. Additionally, if the peer has negotiated to a protocol // version that is high enough to observe the bloom filter service support bit, @@ -1585,6 +1596,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnGetData: sp.OnGetData, OnGetBlocks: sp.OnGetBlocks, OnGetHeaders: sp.OnGetHeaders, + OnGetCBFilter: sp.OnGetCBFilter, OnFeeFilter: sp.OnFeeFilter, OnFilterAdd: sp.OnFilterAdd, OnFilterClear: sp.OnFilterClear, diff --git a/wire/message.go b/wire/message.go index 80e9fe3ccc..b49f7d3b8f 100644 --- a/wire/message.go +++ b/wire/message.go @@ -51,6 +51,7 @@ const ( CmdReject = "reject" CmdSendHeaders = "sendheaders" CmdFeeFilter = "feefilter" + CmdGetCBFilter = "getcbfilter" ) // MessageEncoding represents the wire message encoding format to be used. @@ -156,6 +157,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdFeeFilter: msg = &MsgFeeFilter{} + case CmdGetCBFilter: + msg = &MsgGetCBFilter{} + default: return nil, fmt.Errorf("unhandled command [%s]", command) } diff --git a/wire/msggetcbfilter.go b/wire/msggetcbfilter.go new file mode 100644 index 0000000000..ba6a135400 --- /dev/null +++ b/wire/msggetcbfilter.go @@ -0,0 +1,49 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +type MsgGetCBFilter struct { + ProtocolVersion uint32 + BlockHash chainhash.Hash +} + +func (msg *MsgGetCBFilter) BtcDecode(r io.Reader, pver uint32) error { + return readElement(r, &msg.BlockHash) +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCBFilter) BtcEncode(w io.Writer, pver uint32) error { + return writeElement(w, &msg.BlockHash) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCBFilter) Command() string { + return CmdGetCBFilter +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCBFilter) MaxPayloadLength(pver uint32) uint32 { + // Protocol version 4 bytes + block hash. + return 4 + chainhash.HashSize +} + +// NewMsgGetCBFilter returns a new bitcoin getblocks message that conforms to +// the Message interface using the passed parameters and defaults for the +// remaining fields. +func NewMsgGetCBFilter(blockHash *chainhash.Hash) *MsgGetCBFilter { + return &MsgGetCBFilter{ + ProtocolVersion: ProtocolVersion, + BlockHash: *blockHash, + } +} From dc25da8296f93f93c5c9b5c4786fa252eab9c7b4 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Mon, 9 Jan 2017 12:00:18 +0000 Subject: [PATCH 0065/1056] Generate a filter for a given block --- server.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/server.go b/server.go index c180700daf..3c3df7c148 100644 --- a/server.go +++ b/server.go @@ -38,6 +38,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/bloom" + "github.com/btcsuite/btcutil/gcs" ) const ( @@ -745,8 +746,45 @@ func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) { return } + chain := sp.server.blockManager.chain + block, err := chain.BlockByHash(&msg.BlockHash) + if err != nil { + peerLog.Warnf("failed to get block %v: %v", msg.BlockHash, err) + return + } + + txSlice := block.Transactions() // XXX can this fail? + txHashes := make([][]byte, len(txSlice)) + + for i := 0; i < len(txSlice); i++ { + txHash, err := block.TxHash(i) + if err != nil { + peerLog.Warnf("failed to get hash of tx %v of block %v", + i, msg.BlockHash) + return + } + txHashes = append(txHashes, txHash.CloneBytes()) + peerLog.Warnf("got hash %v", txHash) + } + + var key [gcs.KeySize]byte + P := uint8(20) // collision probability + + for i := 0; i < gcs.KeySize; i += 4 { + binary.BigEndian.PutUint32(key[i:], + randomUint32Number(math.MaxUint32)) + } + + filter, err := gcs.BuildGCSFilter(P, key, txHashes) + if err != nil { + peerLog.Warnf("failed to generate filter for block %v", + msg.BlockHash) + return + } + // XXX pedro: work in progress - peerLog.Warnf("received OnGetCBFilter") + peerLog.Warnf("received OnGetCBFilter: %v", block) + peerLog.Warnf("received OnGetCBFilter: %v", filter) } // enforceNodeBloomFlag disconnects the peer if the server is not configured to @@ -975,6 +1013,24 @@ func randomUint16Number(max uint16) uint16 { } } +// randomUint32Number returns a random uint32 in a specified input range. Note +// that the range is in zeroth ordering; if you pass it 1800, you will get +// values from 0 to 1800. +func randomUint32Number(max uint32) uint32 { + // In order to avoid modulo bias and ensure every possible outcome in + // [0, max) has equal probability, the random number must be sampled + // from a random source that has a range limited to a multiple of the + // modulus. + var randomNumber uint32 + var limitRange = (math.MaxUint32 / max) * max + for { + binary.Read(rand.Reader, binary.LittleEndian, &randomNumber) + if randomNumber < limitRange { + return (randomNumber % max) + } + } +} + // AddRebroadcastInventory adds 'iv' to the list of inventories to be // rebroadcasted at random intervals until they show up in a block. func (s *server) AddRebroadcastInventory(iv *wire.InvVect, data interface{}) { From c8627cbee476dcb0c933b7ae24a1eca571de76ab Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 10 Jan 2017 12:53:21 +0000 Subject: [PATCH 0066/1056] Use a harcoded key to generate filters Pointed out by alex@. Using a dummy key for now. --- server.go | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/server.go b/server.go index 3c3df7c148..55594b5a1f 100644 --- a/server.go +++ b/server.go @@ -771,8 +771,7 @@ func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) { P := uint8(20) // collision probability for i := 0; i < gcs.KeySize; i += 4 { - binary.BigEndian.PutUint32(key[i:], - randomUint32Number(math.MaxUint32)) + binary.BigEndian.PutUint32(key[i:], uint32(0xcafebabe)) } filter, err := gcs.BuildGCSFilter(P, key, txHashes) @@ -1013,24 +1012,6 @@ func randomUint16Number(max uint16) uint16 { } } -// randomUint32Number returns a random uint32 in a specified input range. Note -// that the range is in zeroth ordering; if you pass it 1800, you will get -// values from 0 to 1800. -func randomUint32Number(max uint32) uint32 { - // In order to avoid modulo bias and ensure every possible outcome in - // [0, max) has equal probability, the random number must be sampled - // from a random source that has a range limited to a multiple of the - // modulus. - var randomNumber uint32 - var limitRange = (math.MaxUint32 / max) * max - for { - binary.Read(rand.Reader, binary.LittleEndian, &randomNumber) - if randomNumber < limitRange { - return (randomNumber % max) - } - } -} - // AddRebroadcastInventory adds 'iv' to the list of inventories to be // rebroadcasted at random intervals until they show up in a block. func (s *server) AddRebroadcastInventory(iv *wire.InvVect, data interface{}) { From 95cbe2a91196f4f1da5424b0d208d2683c882d03 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 10 Jan 2017 14:38:15 +0000 Subject: [PATCH 0067/1056] Add the skeleton of a CBF indexer --- blockchain/indexers/cbfindex.go | 111 ++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 blockchain/indexers/cbfindex.go diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go new file mode 100644 index 0000000000..9933ffcaca --- /dev/null +++ b/blockchain/indexers/cbfindex.go @@ -0,0 +1,111 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package indexers + +import ( + "errors" + + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcutil" +) + +const ( + // cbfIndexName is the human-readable name for the index. + cbfIndexName = "committed bloom filter index" +) + +var ( + // cbfIndexKey is the name of the db bucket used to house the + // block hash -> CBF index. + cbfIndexKey = []byte("cbfbyhashidx") + + // errNoCBFEntry is an error that indicates a requested entry does + // not exist in the CBF index. + errCBFEntry = errors.New("no entry in the block ID index") +) + +// The serialized format for keys and values in the block hash to CBF bucket is: +// = +// +// Field Type Size +// hash chainhash.Hash 32 bytes +// CBF []byte variable +// ----- +// Total: > 32 bytes + +// CBFIndex implements a CBF by hash index. +type CBFIndex struct { + db database.DB +} + +// Ensure the CBFIndex type implements the Indexer interface. +var _ Indexer = (*CBFIndex)(nil) + +// Init initializes the hash-based CBF index. +// +// This is part of the Indexer interface. +func (idx *CBFIndex) Init() error { + return nil +} + +// Key returns the database key to use for the index as a byte slice. +// +// This is part of the Indexer interface. +func (idx *CBFIndex) Key() []byte { + return cbfIndexKey +} + +// Name returns the human-readable name of the index. +// +// This is part of the Indexer interface. +func (idx *CBFIndex) Name() string { + return cbfIndexName +} + +// Create is invoked when the indexer manager determines the index needs +// to be created for the first time. It creates the buckets for the hash-based +// CBF index. +// +// This is part of the Indexer interface. +func (idx *CBFIndex) Create(dbTx database.Tx) error { + meta := dbTx.Metadata() + _, err := meta.CreateBucket(cbfIndexKey) + return err +} + +// ConnectBlock is invoked by the index manager when a new block has been +// connected to the main chain. This indexer adds a hash-to-CBF mapping for +// every passed block. +// +// This is part of the Indexer interface. +func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { + return nil +} + +// DisconnectBlock is invoked by the index manager when a block has been +// disconnected from the main chain. This indexer removes the hash-to-CBF +// mapping for every passed block. +// +// This is part of the Indexer interface. +func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { + return nil +} + +// NewCBFIndex returns a new instance of an indexer that is used to create a +// mapping of the hashes of all blocks in the blockchain to their respective +// committed bloom filters. +// +// It implements the Indexer interface which plugs into the IndexManager that in +// turn is used by the blockchain package. This allows the index to be +// seamlessly maintained along with the chain. +func NewCBFIndex(db database.DB) *CBFIndex { + return &CBFIndex{db: db} +} + +// DropCBFIndex drops the CBF index from the provided database if exists. +func DropCBFIndex(db database.DB) error { + return dropIndex(db, cbfIndexKey, cbfIndexName) +} From b2990e7999d1cadd21b5add136f80a29c31b39e7 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 11 Jan 2017 16:09:08 +0000 Subject: [PATCH 0068/1056] Move filter generating code to CBF indexer --- blockchain/indexers/cbfindex.go | 25 ++++++++++++++++++++ server.go | 41 ++------------------------------- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 9933ffcaca..81f2789f63 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -5,11 +5,13 @@ package indexers import ( + "encoding/binary" "errors" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/gcs" ) const ( @@ -82,6 +84,29 @@ func (idx *CBFIndex) Create(dbTx database.Tx) error { // // This is part of the Indexer interface. func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { + txSlice := block.Transactions() // XXX can this fail? + txHashes := make([][]byte, len(txSlice)) + + for i := 0; i < len(txSlice); i++ { + txHash, err := block.TxHash(i) + if err != nil { + return err + } + txHashes = append(txHashes, txHash.CloneBytes()) + } + + var key [gcs.KeySize]byte + P := uint8(20) // collision probability + + for i := 0; i < gcs.KeySize; i += 4 { + binary.BigEndian.PutUint32(key[i:], uint32(0xcafebabe)) + } + + _, err := gcs.BuildGCSFilter(P, key, txHashes) + if err != nil { + return err + } + return nil } diff --git a/server.go b/server.go index 55594b5a1f..487dcd8fd6 100644 --- a/server.go +++ b/server.go @@ -38,7 +38,6 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/bloom" - "github.com/btcsuite/btcutil/gcs" ) const ( @@ -746,44 +745,8 @@ func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) { return } - chain := sp.server.blockManager.chain - block, err := chain.BlockByHash(&msg.BlockHash) - if err != nil { - peerLog.Warnf("failed to get block %v: %v", msg.BlockHash, err) - return - } - - txSlice := block.Transactions() // XXX can this fail? - txHashes := make([][]byte, len(txSlice)) - - for i := 0; i < len(txSlice); i++ { - txHash, err := block.TxHash(i) - if err != nil { - peerLog.Warnf("failed to get hash of tx %v of block %v", - i, msg.BlockHash) - return - } - txHashes = append(txHashes, txHash.CloneBytes()) - peerLog.Warnf("got hash %v", txHash) - } - - var key [gcs.KeySize]byte - P := uint8(20) // collision probability - - for i := 0; i < gcs.KeySize; i += 4 { - binary.BigEndian.PutUint32(key[i:], uint32(0xcafebabe)) - } - - filter, err := gcs.BuildGCSFilter(P, key, txHashes) - if err != nil { - peerLog.Warnf("failed to generate filter for block %v", - msg.BlockHash) - return - } - - // XXX pedro: work in progress - peerLog.Warnf("received OnGetCBFilter: %v", block) - peerLog.Warnf("received OnGetCBFilter: %v", filter) + // XXX work in progress + peerLog.Warnf("received OnGetCBFilter: not yet") } // enforceNodeBloomFlag disconnects the peer if the server is not configured to From 620ad5b6fb75de03bec00aab9dac7ab251e37c8c Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 11 Jan 2017 16:29:32 +0000 Subject: [PATCH 0069/1056] Store filter in a db block index --- blockchain/indexers/cbfindex.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 81f2789f63..f892de872a 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -102,7 +102,14 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view * binary.BigEndian.PutUint32(key[i:], uint32(0xcafebabe)) } - _, err := gcs.BuildGCSFilter(P, key, txHashes) + filter, err := gcs.BuildGCSFilter(P, key, txHashes) + if err != nil { + return err + } + + meta := dbTx.Metadata() + hashIndex := meta.Bucket(cbfIndexKey) + err = hashIndex.Put(block.Hash().CloneBytes(), filter.Bytes()) if err != nil { return err } From 05d2fdeb11609c788144bbb6e5eaf58c503ac806 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 12 Jan 2017 10:31:19 +0000 Subject: [PATCH 0070/1056] Rename a variable in CBF's ConnectBlock() --- blockchain/indexers/cbfindex.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index f892de872a..001d114898 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -108,8 +108,8 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view * } meta := dbTx.Metadata() - hashIndex := meta.Bucket(cbfIndexKey) - err = hashIndex.Put(block.Hash().CloneBytes(), filter.Bytes()) + index := meta.Bucket(cbfIndexKey) + err = index.Put(block.Hash().CloneBytes(), filter.Bytes()) if err != nil { return err } From cf74c8c3ca7213f716035f1b532d3cecd5e6e316 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 12 Jan 2017 10:55:31 +0000 Subject: [PATCH 0071/1056] Abstract filter generation to a separate function --- blockchain/indexers/cbfindex.go | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 001d114898..32d6bd7642 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -78,19 +78,14 @@ func (idx *CBFIndex) Create(dbTx database.Tx) error { return err } -// ConnectBlock is invoked by the index manager when a new block has been -// connected to the main chain. This indexer adds a hash-to-CBF mapping for -// every passed block. -// -// This is part of the Indexer interface. -func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func generateFilterForBlock(block *btcutil.Block) ([]byte, error) { txSlice := block.Transactions() // XXX can this fail? txHashes := make([][]byte, len(txSlice)) for i := 0; i < len(txSlice); i++ { txHash, err := block.TxHash(i) if err != nil { - return err + return nil, err } txHashes = append(txHashes, txHash.CloneBytes()) } @@ -103,13 +98,28 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view * } filter, err := gcs.BuildGCSFilter(P, key, txHashes) + if err != nil { + return nil, err + } + + return filter.Bytes(), nil +} + +// ConnectBlock is invoked by the index manager when a new block has been +// connected to the main chain. This indexer adds a hash-to-CBF mapping for +// every passed block. +// +// This is part of the Indexer interface. +func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, + view *blockchain.UtxoViewpoint) error { + filterBytes, err := generateFilterForBlock(block) if err != nil { return err } meta := dbTx.Metadata() index := meta.Bucket(cbfIndexKey) - err = index.Put(block.Hash().CloneBytes(), filter.Bytes()) + err = index.Put(block.Hash().CloneBytes(), filterBytes) if err != nil { return err } From 9809f4ffdd0e1b4542a43224ebc4fec2837279ef Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 12 Jan 2017 11:03:42 +0000 Subject: [PATCH 0072/1056] Instrument basic logging --- blockchain/indexers/cbfindex.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 32d6bd7642..41bb45132c 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -7,11 +7,14 @@ package indexers import ( "encoding/binary" "errors" + "fmt" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs" + + "os" ) const ( @@ -102,6 +105,8 @@ func generateFilterForBlock(block *btcutil.Block) ([]byte, error) { return nil, err } + fmt.Fprintf(os.Stderr, "Generated CBF for block %v", block.Hash()) + return filter.Bytes(), nil } @@ -124,6 +129,8 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return err } + fmt.Fprintf(os.Stderr, "Stored CBF for block %v", block.Hash()) + return nil } From 3b0038093a65c9b584580fc11306a16c3bdeca1b Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 12 Jan 2017 11:20:16 +0000 Subject: [PATCH 0073/1056] Hook CBF indexer to server code --- server.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server.go b/server.go index 487dcd8fd6..6d8736b050 100644 --- a/server.go +++ b/server.go @@ -229,6 +229,7 @@ type server struct { // do not need to be protected for concurrent access. txIndex *indexers.TxIndex addrIndex *indexers.AddrIndex + cbfIndex *indexers.CBFIndex } // serverPeer extends the peer to maintain state shared by the server and @@ -2236,6 +2237,11 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param s.addrIndex = indexers.NewAddrIndex(db, chainParams) indexes = append(indexes, s.addrIndex) } + if !cfg.NoCBFilters { + indxLog.Info("CBF index is enabled") + s.cbfIndex = indexers.NewCBFIndex(db) + indexes = append(indexes, s.cbfIndex) + } // Create an index manager if any of the optional indexes are enabled. var indexManager blockchain.IndexManager From 76926f89048d4bfffb74fcfab6e94752b2d7b34a Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 12 Jan 2017 13:25:45 +0000 Subject: [PATCH 0074/1056] Roll in a dbFetchCBFIndexEntry() --- blockchain/indexers/cbfindex.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 41bb45132c..967ca76261 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -10,6 +10,7 @@ import ( "fmt" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs" @@ -32,6 +33,18 @@ var ( errCBFEntry = errors.New("no entry in the block ID index") ) +func dbFetchCBFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, + error) { + // Load the record from the database and return now if it doesn't exist. + index := dbTx.Metadata().Bucket(cbfIndexKey) + serializedFilter := index.Get(blockHash.CloneBytes()) + if len(serializedFilter) == 0 { + return nil, nil + } + + return serializedFilter, nil +} + // The serialized format for keys and values in the block hash to CBF bucket is: // = // From 43bf8db793e5a97d69badab6e458d5659c80351a Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 12 Jan 2017 15:28:27 +0000 Subject: [PATCH 0075/1056] Look up filters from p2p GetCBF message --- blockchain/indexers/cbfindex.go | 11 +++++++++++ server.go | 10 ++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 967ca76261..178c887157 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -156,6 +156,17 @@ func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, vie return nil } +func (idx *CBFIndex) GetFilterByBlockHash(hash *chainhash.Hash) ([]byte, + error) { + var filterBytes []byte + err := idx.db.View(func(dbTx database.Tx) error { + var err error + filterBytes, err = dbFetchCBFIndexEntry(dbTx, hash) + return err + }) + return filterBytes, err +} + // NewCBFIndex returns a new instance of an indexer that is used to create a // mapping of the hashes of all blocks in the blockchain to their respective // committed bloom filters. diff --git a/server.go b/server.go index 6d8736b050..850ada5271 100644 --- a/server.go +++ b/server.go @@ -746,8 +746,14 @@ func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) { return } - // XXX work in progress - peerLog.Warnf("received OnGetCBFilter: not yet") + filterBytes, err := sp.server.cbfIndex.GetFilterByBlockHash(&msg.BlockHash) + + if len(filterBytes) > 0 { + peerLog.Infof("Obtained CB filter for %v", msg.BlockHash) + } else { + peerLog.Infof("Could not obtain CB filter for %v: %v", + msg.BlockHash, err) + } } // enforceNodeBloomFlag disconnects the peer if the server is not configured to From 76378e716777849ad2de2cb9e0a73f1a298869dd Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Fri, 13 Jan 2017 12:07:25 +0000 Subject: [PATCH 0076/1056] Add a GetCBFilter RPC command --- btcjson/chainsvrcmds.go | 13 +++++++++++++ btcjson/chainsvrcmds_test.go | 13 +++++++++++++ rpcserver.go | 7 +++++++ rpcserverhelp.go | 6 ++++++ 4 files changed, 39 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 83c417ebbb..b90b927975 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -278,6 +278,18 @@ func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd { Request: request, } } +// GetCBFilterCmd defines the getcbfilter JSON-RPC command. +type GetCBFilterCmd struct { + Hash string +} + +// NewGetCBFilterCmd returns a new instance which can be used to issue a +// getcbfilter JSON-RPC command. +func NewGetCBFilterCmd(hash string) *GetCBFilterCmd { + return &GetCBFilterCmd{ + Hash: hash, + } +} // GetChainTipsCmd defines the getchaintips JSON-RPC command. type GetChainTipsCmd struct{} @@ -756,6 +768,7 @@ func init() { MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags) MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags) MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags) + MustRegisterCmd("getcbfilter", (*GetCBFilterCmd)(nil), flags) MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags) MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags) MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index d623012b1e..79060be693 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -317,6 +317,19 @@ func TestChainSvrCmds(t *testing.T) { }, }, }, + { + name: "getcbfilter", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getcbfilter", "123") + }, + staticCmd: func() interface{} { + return btcjson.NewGetCBFilterCmd("123") + }, + marshalled: `{"jsonrpc":"1.0","method":"getcbfilter","params":["123"],"id":1}`, + unmarshalled: &btcjson.GetCBFilterCmd{ + Hash: "123", + }, + }, { name: "getchaintips", newCmd: func() (interface{}, error) { diff --git a/rpcserver.go b/rpcserver.go index 2408e5a3ec..312a6596b5 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -142,6 +142,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "getblockhash": handleGetBlockHash, "getblockheader": handleGetBlockHeader, "getblocktemplate": handleGetBlockTemplate, + "getcbfilter": handleGetCBFilter, "getconnectioncount": handleGetConnectionCount, "getcurrentnet": handleGetCurrentNet, "getdifficulty": handleGetDifficulty, @@ -258,6 +259,7 @@ var rpcLimited = map[string]struct{}{ "getblockcount": {}, "getblockhash": {}, "getblockheader": {}, + "getcbfilter": {}, "getcurrentnet": {}, "getdifficulty": {}, "getheaders": {}, @@ -2144,6 +2146,11 @@ func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan stru } } +// handleGetCBFilter implements the getcbfilter command. +func handleGetCBFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + return nil, nil +} + // handleGetConnectionCount implements the getconnectioncount command. func handleGetConnectionCount(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { return s.cfg.ConnMgr.ConnectedCount(), nil diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 1705ebc85d..240df9bcef 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -323,6 +323,11 @@ var helpDescsEnUS = map[string]string{ "getblocktemplate--condition2": "mode=proposal, accepted", "getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted", + // GetCBFilterCmd help. + "getcbfilter--synopsis": "Returns a block's committed bloom filter given its hash.", + "getcbfilter-hash": "The hash of the block", + "getcbfilter--result0": "The block's committed bloom filter", + // GetConnectionCountCmd help. "getconnectioncount--synopsis": "Returns the number of active connections to other peers.", "getconnectioncount--result0": "The number of connections", @@ -668,6 +673,7 @@ var rpcResultTypes = map[string][]interface{}{ "getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)}, "getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil}, "getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)}, + "getcbfilter": {(*[]byte)(nil)}, "getconnectioncount": {(*int32)(nil)}, "getcurrentnet": {(*uint32)(nil)}, "getdifficulty": {(*float64)(nil)}, From f6dff40733b78e1180b19d80e583801c03f3ec9c Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Sat, 14 Jan 2017 10:26:13 +0000 Subject: [PATCH 0077/1056] Instrument GetCBFilter RPC --- rpcserver.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index 312a6596b5..a73351dd36 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2148,6 +2148,23 @@ func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan stru // handleGetCBFilter implements the getcbfilter command. func handleGetCBFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.GetCBFilterCmd) + hash, err := chainhash.NewHashFromStr(c.Hash) + if err != nil { + return nil, rpcDecodeHexError(c.Hash) + } + + filterBytes, err := s.server.cbfIndex.GetFilterByBlockHash(hash) + if len(filterBytes) > 0 { + rpcsLog.Debugf("Found CB filter for %v", hash) + } else { + rpcsLog.Debugf("Could not find CB filter for %v: %v", hash, err) + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCBlockNotFound, + Message: "Block not found", + } + } + return nil, nil } From cd7857b883d0c5b15a75a167835e96eafb4d433e Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Sat, 14 Jan 2017 10:38:28 +0000 Subject: [PATCH 0078/1056] GetCBFilter RPC returns a string, not a []byte --- rpcserverhelp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 240df9bcef..0e2eba978e 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -673,7 +673,7 @@ var rpcResultTypes = map[string][]interface{}{ "getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)}, "getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil}, "getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)}, - "getcbfilter": {(*[]byte)(nil)}, + "getcbfilter": {(*string)(nil)}, "getconnectioncount": {(*int32)(nil)}, "getcurrentnet": {(*uint32)(nil)}, "getdifficulty": {(*float64)(nil)}, From 618306116b9b1c9d8706635be99e062924ce891f Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Sat, 14 Jan 2017 10:38:46 +0000 Subject: [PATCH 0079/1056] Return filter in handleGetCBFilter() --- rpcserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index a73351dd36..75dede9c09 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2165,7 +2165,7 @@ func handleGetCBFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) } } - return nil, nil + return hex.EncodeToString(filterBytes), nil } // handleGetConnectionCount implements the getconnectioncount command. From 8b8c7bcf05b38d6e43448bc4b3e0cff84cbaa7df Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Mon, 16 Jan 2017 11:50:29 +0000 Subject: [PATCH 0080/1056] Implement DisconnectBlock() for the CBF Indexer --- blockchain/indexers/cbfindex.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 178c887157..e09505c845 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -152,8 +152,15 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, // mapping for every passed block. // // This is part of the Indexer interface. -func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - return nil +func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, + view *blockchain.UtxoViewpoint) error { + index := dbTx.Metadata().Bucket(cbfIndexKey) + filterBytes := index.Get(block.Hash().CloneBytes()) + if len(filterBytes) == 0 { + return fmt.Errorf("can't remove non-existent filter %s from " + + "the cbfilter index", block.Hash()) + } + return index.Delete(block.Hash().CloneBytes()) } func (idx *CBFIndex) GetFilterByBlockHash(hash *chainhash.Hash) ([]byte, From 9f02951b0e0d26f8980c5763f55a9d32f335ae01 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 18 Jan 2017 07:48:56 +0000 Subject: [PATCH 0081/1056] CloneBytes() -> [:], pointed out by davec@ --- blockchain/indexers/cbfindex.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index e09505c845..6684e64c84 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -37,7 +37,7 @@ func dbFetchCBFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, error) { // Load the record from the database and return now if it doesn't exist. index := dbTx.Metadata().Bucket(cbfIndexKey) - serializedFilter := index.Get(blockHash.CloneBytes()) + serializedFilter := index.Get(blockHash[:]) if len(serializedFilter) == 0 { return nil, nil } @@ -103,7 +103,7 @@ func generateFilterForBlock(block *btcutil.Block) ([]byte, error) { if err != nil { return nil, err } - txHashes = append(txHashes, txHash.CloneBytes()) + txHashes = append(txHashes, txHash[:]) } var key [gcs.KeySize]byte @@ -137,7 +137,7 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, meta := dbTx.Metadata() index := meta.Bucket(cbfIndexKey) - err = index.Put(block.Hash().CloneBytes(), filterBytes) + err = index.Put(block.Hash()[:], filterBytes) if err != nil { return err } @@ -155,12 +155,12 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { index := dbTx.Metadata().Bucket(cbfIndexKey) - filterBytes := index.Get(block.Hash().CloneBytes()) + filterBytes := index.Get(block.Hash()[:]) if len(filterBytes) == 0 { return fmt.Errorf("can't remove non-existent filter %s from " + "the cbfilter index", block.Hash()) } - return index.Delete(block.Hash().CloneBytes()) + return index.Delete(block.Hash()[:]) } func (idx *CBFIndex) GetFilterByBlockHash(hash *chainhash.Hash) ([]byte, From a77b1e00d5c4396d4cba8e549f9230dd558adfa9 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 18 Jan 2017 07:50:18 +0000 Subject: [PATCH 0082/1056] FilterByBlockHash(), pointed out by davec@ --- blockchain/indexers/cbfindex.go | 3 +-- rpcserver.go | 2 +- server.go | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index 6684e64c84..d10c997fcd 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -163,8 +163,7 @@ func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, return index.Delete(block.Hash()[:]) } -func (idx *CBFIndex) GetFilterByBlockHash(hash *chainhash.Hash) ([]byte, - error) { +func (idx *CBFIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) { var filterBytes []byte err := idx.db.View(func(dbTx database.Tx) error { var err error diff --git a/rpcserver.go b/rpcserver.go index 75dede9c09..bd45ec8001 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2154,7 +2154,7 @@ func handleGetCBFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return nil, rpcDecodeHexError(c.Hash) } - filterBytes, err := s.server.cbfIndex.GetFilterByBlockHash(hash) + filterBytes, err := s.server.cbfIndex.FilterByBlockHash(hash) if len(filterBytes) > 0 { rpcsLog.Debugf("Found CB filter for %v", hash) } else { diff --git a/server.go b/server.go index 850ada5271..bd66e4c122 100644 --- a/server.go +++ b/server.go @@ -746,7 +746,7 @@ func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) { return } - filterBytes, err := sp.server.cbfIndex.GetFilterByBlockHash(&msg.BlockHash) + filterBytes, err := sp.server.cbfIndex.FilterByBlockHash(&msg.BlockHash) if len(filterBytes) > 0 { peerLog.Infof("Obtained CB filter for %v", msg.BlockHash) From 6e5f650be9abcf278213387afb35b0a87251706f Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 18 Jan 2017 08:09:05 +0000 Subject: [PATCH 0083/1056] CBFilter -> CFilter, discussed with davec@ --- blockchain/indexers/cbfindex.go | 86 ++++++++++---------- btcjson/chainsvrcmds.go | 14 ++-- btcjson/chainsvrcmds_test.go | 10 +-- config.go | 2 +- doc.go | 2 +- peer/peer.go | 12 +-- peer/peer_test.go | 6 +- rpcserver.go | 17 ++-- rpcserverhelp.go | 10 +-- sample-btcd.conf | 4 +- server.go | 26 +++--- wire/message.go | 6 +- wire/{msggetcbfilter.go => msggetcfilter.go} | 18 ++-- wire/protocol.go | 10 +-- wire/protocol_test.go | 4 +- 15 files changed, 114 insertions(+), 113 deletions(-) rename wire/{msggetcbfilter.go => msggetcfilter.go} (68%) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cbfindex.go index d10c997fcd..80563cba5d 100644 --- a/blockchain/indexers/cbfindex.go +++ b/blockchain/indexers/cbfindex.go @@ -19,24 +19,24 @@ import ( ) const ( - // cbfIndexName is the human-readable name for the index. - cbfIndexName = "committed bloom filter index" + // cfIndexName is the human-readable name for the index. + cfIndexName = "committed bloom filter index" ) var ( - // cbfIndexKey is the name of the db bucket used to house the - // block hash -> CBF index. - cbfIndexKey = []byte("cbfbyhashidx") + // cfIndexKey is the name of the db bucket used to house the + // block hash -> CF index. + cfIndexKey = []byte("cfbyhashidx") - // errNoCBFEntry is an error that indicates a requested entry does - // not exist in the CBF index. - errCBFEntry = errors.New("no entry in the block ID index") + // errNoCFEntry is an error that indicates a requested entry does + // not exist in the CF index. + errCFEntry = errors.New("no entry in the block ID index") ) -func dbFetchCBFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, +func dbFetchCFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, error) { // Load the record from the database and return now if it doesn't exist. - index := dbTx.Metadata().Bucket(cbfIndexKey) + index := dbTx.Metadata().Bucket(cfIndexKey) serializedFilter := index.Get(blockHash[:]) if len(serializedFilter) == 0 { return nil, nil @@ -45,52 +45,52 @@ func dbFetchCBFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, return serializedFilter, nil } -// The serialized format for keys and values in the block hash to CBF bucket is: -// = +// The serialized format for keys and values in the block hash to CF bucket is: +// = // // Field Type Size // hash chainhash.Hash 32 bytes -// CBF []byte variable +// CF []byte variable // ----- // Total: > 32 bytes -// CBFIndex implements a CBF by hash index. -type CBFIndex struct { +// CFIndex implements a CF by hash index. +type CFIndex struct { db database.DB } -// Ensure the CBFIndex type implements the Indexer interface. -var _ Indexer = (*CBFIndex)(nil) +// Ensure the CFIndex type implements the Indexer interface. +var _ Indexer = (*CFIndex)(nil) -// Init initializes the hash-based CBF index. +// Init initializes the hash-based CF index. // // This is part of the Indexer interface. -func (idx *CBFIndex) Init() error { +func (idx *CFIndex) Init() error { return nil } // Key returns the database key to use for the index as a byte slice. // // This is part of the Indexer interface. -func (idx *CBFIndex) Key() []byte { - return cbfIndexKey +func (idx *CFIndex) Key() []byte { + return cfIndexKey } // Name returns the human-readable name of the index. // // This is part of the Indexer interface. -func (idx *CBFIndex) Name() string { - return cbfIndexName +func (idx *CFIndex) Name() string { + return cfIndexName } // Create is invoked when the indexer manager determines the index needs // to be created for the first time. It creates the buckets for the hash-based -// CBF index. +// CF index. // // This is part of the Indexer interface. -func (idx *CBFIndex) Create(dbTx database.Tx) error { +func (idx *CFIndex) Create(dbTx database.Tx) error { meta := dbTx.Metadata() - _, err := meta.CreateBucket(cbfIndexKey) + _, err := meta.CreateBucket(cfIndexKey) return err } @@ -118,17 +118,17 @@ func generateFilterForBlock(block *btcutil.Block) ([]byte, error) { return nil, err } - fmt.Fprintf(os.Stderr, "Generated CBF for block %v", block.Hash()) + fmt.Fprintf(os.Stderr, "Generated CF for block %v", block.Hash()) return filter.Bytes(), nil } // ConnectBlock is invoked by the index manager when a new block has been -// connected to the main chain. This indexer adds a hash-to-CBF mapping for +// connected to the main chain. This indexer adds a hash-to-CF mapping for // every passed block. // // This is part of the Indexer interface. -func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, +func (idx *CFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { filterBytes, err := generateFilterForBlock(block) if err != nil { @@ -136,55 +136,55 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, } meta := dbTx.Metadata() - index := meta.Bucket(cbfIndexKey) + index := meta.Bucket(cfIndexKey) err = index.Put(block.Hash()[:], filterBytes) if err != nil { return err } - fmt.Fprintf(os.Stderr, "Stored CBF for block %v", block.Hash()) + fmt.Fprintf(os.Stderr, "Stored CF for block %v", block.Hash()) return nil } // DisconnectBlock is invoked by the index manager when a block has been -// disconnected from the main chain. This indexer removes the hash-to-CBF +// disconnected from the main chain. This indexer removes the hash-to-CF // mapping for every passed block. // // This is part of the Indexer interface. -func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, +func (idx *CFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - index := dbTx.Metadata().Bucket(cbfIndexKey) + index := dbTx.Metadata().Bucket(cfIndexKey) filterBytes := index.Get(block.Hash()[:]) if len(filterBytes) == 0 { return fmt.Errorf("can't remove non-existent filter %s from " + - "the cbfilter index", block.Hash()) + "the cfilter index", block.Hash()) } return index.Delete(block.Hash()[:]) } -func (idx *CBFIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) { +func (idx *CFIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) { var filterBytes []byte err := idx.db.View(func(dbTx database.Tx) error { var err error - filterBytes, err = dbFetchCBFIndexEntry(dbTx, hash) + filterBytes, err = dbFetchCFIndexEntry(dbTx, hash) return err }) return filterBytes, err } -// NewCBFIndex returns a new instance of an indexer that is used to create a +// NewCFIndex returns a new instance of an indexer that is used to create a // mapping of the hashes of all blocks in the blockchain to their respective // committed bloom filters. // // It implements the Indexer interface which plugs into the IndexManager that in // turn is used by the blockchain package. This allows the index to be // seamlessly maintained along with the chain. -func NewCBFIndex(db database.DB) *CBFIndex { - return &CBFIndex{db: db} +func NewCFIndex(db database.DB) *CFIndex { + return &CFIndex{db: db} } -// DropCBFIndex drops the CBF index from the provided database if exists. -func DropCBFIndex(db database.DB) error { - return dropIndex(db, cbfIndexKey, cbfIndexName) +// DropCFIndex drops the CF index from the provided database if exists. +func DropCFIndex(db database.DB) error { + return dropIndex(db, cfIndexKey, cfIndexName) } diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index b90b927975..904627626f 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -278,15 +278,15 @@ func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd { Request: request, } } -// GetCBFilterCmd defines the getcbfilter JSON-RPC command. -type GetCBFilterCmd struct { +// GetCFilterCmd defines the getcfilter JSON-RPC command. +type GetCFilterCmd struct { Hash string } -// NewGetCBFilterCmd returns a new instance which can be used to issue a -// getcbfilter JSON-RPC command. -func NewGetCBFilterCmd(hash string) *GetCBFilterCmd { - return &GetCBFilterCmd{ +// NewGetCFilterCmd returns a new instance which can be used to issue a +// getcfilter JSON-RPC command. +func NewGetCFilterCmd(hash string) *GetCFilterCmd { + return &GetCFilterCmd{ Hash: hash, } } @@ -768,7 +768,7 @@ func init() { MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags) MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags) MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags) - MustRegisterCmd("getcbfilter", (*GetCBFilterCmd)(nil), flags) + MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags) MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags) MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags) MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 79060be693..0501bee558 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -318,15 +318,15 @@ func TestChainSvrCmds(t *testing.T) { }, }, { - name: "getcbfilter", + name: "getcfilter", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getcbfilter", "123") + return btcjson.NewCmd("getcfilter", "123") }, staticCmd: func() interface{} { - return btcjson.NewGetCBFilterCmd("123") + return btcjson.NewGetCFilterCmd("123") }, - marshalled: `{"jsonrpc":"1.0","method":"getcbfilter","params":["123"],"id":1}`, - unmarshalled: &btcjson.GetCBFilterCmd{ + marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123"],"id":1}`, + unmarshalled: &btcjson.GetCFilterCmd{ Hash: "123", }, }, diff --git a/config.go b/config.go index 505b3fbb28..c8aa1b0c8c 100644 --- a/config.go +++ b/config.go @@ -150,7 +150,7 @@ type config struct { BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"` UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."` NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"` - NoCBFilters bool `long:"nocbfilters" description:"Disable committed bloom filtering (CBF) support"` + NoCFilters bool `long:"nocfilters" description:"Disable committed filtering (CF) support"` SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"` BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."` TxIndex bool `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` diff --git a/doc.go b/doc.go index 9bb0f2e6c7..ace26b0f99 100644 --- a/doc.go +++ b/doc.go @@ -112,7 +112,7 @@ Application Options: --blockprioritysize= Size in bytes for high-priority/low-fee transactions when creating a block (50000) --nopeerbloomfilters Disable bloom filtering support. - --nocbfilters Disable committed bloom filtering (CBF) support. + --nocfilters Disable committed filtering (CF) support. --sigcachemaxsize= The maximum number of entries in the signature verification cache. --blocksonly Do not accept transactions from remote peers. diff --git a/peer/peer.go b/peer/peer.go index 832331a00c..ea0e3aa260 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -144,9 +144,9 @@ type MessageListeners struct { // message. OnGetHeaders func(p *Peer, msg *wire.MsgGetHeaders) - // OnGetCBFilter is invoked when a peer receives a getcbfilter bitcoin + // OnGetCFilter is invoked when a peer receives a getcfilter bitcoin // message. - OnGetCBFilter func(p *Peer, msg *wire.MsgGetCBFilter) + OnGetCFilter func(p *Peer, msg *wire.MsgGetCFilter) // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1285,7 +1285,7 @@ func (p *Peer) maybeAddDeadline(pendingResponses map[string]time.Time, msgCmd st deadline = time.Now().Add(stallResponseTimeout * 3) pendingResponses[wire.CmdHeaders] = deadline - // XXX pedro: we may need to handle OnCBFilter here depending on the + // XXX pedro: we may need to handle OnCFilter here depending on the // protocol behaviour defined. } } @@ -1586,9 +1586,9 @@ out: p.cfg.Listeners.OnGetHeaders(p, msg) } - case *wire.MsgGetCBFilter: - if p.cfg.Listeners.OnGetCBFilter != nil { - p.cfg.Listeners.OnGetCBFilter(p, msg) + case *wire.MsgGetCFilter: + if p.cfg.Listeners.OnGetCFilter != nil { + p.cfg.Listeners.OnGetCFilter(p, msg) } case *wire.MsgFeeFilter: diff --git a/peer/peer_test.go b/peer/peer_test.go index bbd4008df1..bfe2987bbd 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -399,7 +399,7 @@ func TestPeerListeners(t *testing.T) { OnGetHeaders: func(p *peer.Peer, msg *wire.MsgGetHeaders) { ok <- msg }, - OnGetCBFilter: func(p *peer.Peer, msg *wire.MsgGetCBFilter) { + OnGetCFilter: func(p *peer.Peer, msg *wire.MsgGetCFilter) { ok <- msg }, OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { @@ -526,8 +526,8 @@ func TestPeerListeners(t *testing.T) { wire.NewMsgGetHeaders(), }, { - "OnGetCBFilter", - wire.NewMsgGetCBFilter(&chainhash.Hash{}), + "OnGetCFilter", + wire.NewMsgGetCFilter(&chainhash.Hash{}), }, { "OnFeeFilter", diff --git a/rpcserver.go b/rpcserver.go index bd45ec8001..72f0f6a4ac 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -142,7 +142,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "getblockhash": handleGetBlockHash, "getblockheader": handleGetBlockHeader, "getblocktemplate": handleGetBlockTemplate, - "getcbfilter": handleGetCBFilter, + "getcfilter": handleGetCFilter, "getconnectioncount": handleGetConnectionCount, "getcurrentnet": handleGetCurrentNet, "getdifficulty": handleGetDifficulty, @@ -259,7 +259,7 @@ var rpcLimited = map[string]struct{}{ "getblockcount": {}, "getblockhash": {}, "getblockheader": {}, - "getcbfilter": {}, + "getcfilter": {}, "getcurrentnet": {}, "getdifficulty": {}, "getheaders": {}, @@ -2146,19 +2146,20 @@ func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan stru } } -// handleGetCBFilter implements the getcbfilter command. -func handleGetCBFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { - c := cmd.(*btcjson.GetCBFilterCmd) +// handleGetCFilter implements the getcfilter command. +func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.GetCFilterCmd) hash, err := chainhash.NewHashFromStr(c.Hash) if err != nil { return nil, rpcDecodeHexError(c.Hash) } - filterBytes, err := s.server.cbfIndex.FilterByBlockHash(hash) + filterBytes, err := s.server.cfIndex.FilterByBlockHash(hash) if len(filterBytes) > 0 { - rpcsLog.Debugf("Found CB filter for %v", hash) + rpcsLog.Debugf("Found committed filter for %v", hash) } else { - rpcsLog.Debugf("Could not find CB filter for %v: %v", hash, err) + rpcsLog.Debugf("Could not find committed filter for %v: %v", + hash, err) return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCBlockNotFound, Message: "Block not found", diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 0e2eba978e..19a3d724ed 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -323,10 +323,10 @@ var helpDescsEnUS = map[string]string{ "getblocktemplate--condition2": "mode=proposal, accepted", "getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted", - // GetCBFilterCmd help. - "getcbfilter--synopsis": "Returns a block's committed bloom filter given its hash.", - "getcbfilter-hash": "The hash of the block", - "getcbfilter--result0": "The block's committed bloom filter", + // GetCFilterCmd help. + "getcfilter--synopsis": "Returns a block's committed filter given its hash.", + "getcfilter-hash": "The hash of the block", + "getcfilter--result0": "The block's committed filter", // GetConnectionCountCmd help. "getconnectioncount--synopsis": "Returns the number of active connections to other peers.", @@ -673,7 +673,7 @@ var rpcResultTypes = map[string][]interface{}{ "getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)}, "getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil}, "getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)}, - "getcbfilter": {(*string)(nil)}, + "getcfilter": {(*string)(nil)}, "getconnectioncount": {(*int32)(nil)}, "getcurrentnet": {(*uint32)(nil)}, "getdifficulty": {(*float64)(nil)}, diff --git a/sample-btcd.conf b/sample-btcd.conf index 729d18ec75..4508e387a0 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -167,8 +167,8 @@ ; Must not include characters '/', ':', '(' and ')'. ; uacomment= -; Disable committed peer bloom filtering (CBF). -; nocbfilters=1 +; Disable committed peer filtering (CF). +; nocfilters=1 ; ------------------------------------------------------------------------------ ; RPC server options - The following options control the built-in RPC server diff --git a/server.go b/server.go index bd66e4c122..7ece52ebb4 100644 --- a/server.go +++ b/server.go @@ -229,7 +229,7 @@ type server struct { // do not need to be protected for concurrent access. txIndex *indexers.TxIndex addrIndex *indexers.AddrIndex - cbfIndex *indexers.CBFIndex + cfIndex *indexers.CFIndex } // serverPeer extends the peer to maintain state shared by the server and @@ -739,20 +739,20 @@ func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { sp.QueueMessage(&wire.MsgHeaders{Headers: blockHeaders}, nil) } -// OnGetCBFilter is invoked when a peer receives a getcbfilter bitcoin message. -func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) { - // Ignore getcbfilter requests if not in sync. +// OnGetCFilter is invoked when a peer receives a getcfilter bitcoin message. +func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { + // Ignore getcfilter requests if not in sync. if !sp.server.blockManager.IsCurrent() { return } - filterBytes, err := sp.server.cbfIndex.FilterByBlockHash(&msg.BlockHash) + filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash) if len(filterBytes) > 0 { peerLog.Infof("Obtained CB filter for %v", msg.BlockHash) } else { peerLog.Infof("Could not obtain CB filter for %v: %v", - msg.BlockHash, err) + msg.BlockHash, err) } } @@ -1603,7 +1603,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnGetData: sp.OnGetData, OnGetBlocks: sp.OnGetBlocks, OnGetHeaders: sp.OnGetHeaders, - OnGetCBFilter: sp.OnGetCBFilter, + OnGetCFilter: sp.OnGetCFilter, OnFeeFilter: sp.OnFeeFilter, OnFilterAdd: sp.OnFilterAdd, OnFilterClear: sp.OnFilterClear, @@ -2178,8 +2178,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param if cfg.NoPeerBloomFilters { services &^= wire.SFNodeBloom } - if cfg.NoCBFilters { - services &^= wire.SFNodeCBF + if cfg.NoCFilters { + services &^= wire.SFNodeCF } amgr := addrmgr.New(cfg.DataDir, btcdLookup) @@ -2243,10 +2243,10 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param s.addrIndex = indexers.NewAddrIndex(db, chainParams) indexes = append(indexes, s.addrIndex) } - if !cfg.NoCBFilters { - indxLog.Info("CBF index is enabled") - s.cbfIndex = indexers.NewCBFIndex(db) - indexes = append(indexes, s.cbfIndex) + if !cfg.NoCFilters { + indxLog.Info("CF index is enabled") + s.cfIndex = indexers.NewCFIndex(db) + indexes = append(indexes, s.cfIndex) } // Create an index manager if any of the optional indexes are enabled. diff --git a/wire/message.go b/wire/message.go index b49f7d3b8f..96388b603c 100644 --- a/wire/message.go +++ b/wire/message.go @@ -51,7 +51,7 @@ const ( CmdReject = "reject" CmdSendHeaders = "sendheaders" CmdFeeFilter = "feefilter" - CmdGetCBFilter = "getcbfilter" + CmdGetCFilter = "getcfilter" ) // MessageEncoding represents the wire message encoding format to be used. @@ -157,8 +157,8 @@ func makeEmptyMessage(command string) (Message, error) { case CmdFeeFilter: msg = &MsgFeeFilter{} - case CmdGetCBFilter: - msg = &MsgGetCBFilter{} + case CmdGetCFilter: + msg = &MsgGetCFilter{} default: return nil, fmt.Errorf("unhandled command [%s]", command) diff --git a/wire/msggetcbfilter.go b/wire/msggetcfilter.go similarity index 68% rename from wire/msggetcbfilter.go rename to wire/msggetcfilter.go index ba6a135400..160fc5f1d8 100644 --- a/wire/msggetcbfilter.go +++ b/wire/msggetcfilter.go @@ -10,39 +10,39 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" ) -type MsgGetCBFilter struct { +type MsgGetCFilter struct { ProtocolVersion uint32 BlockHash chainhash.Hash } -func (msg *MsgGetCBFilter) BtcDecode(r io.Reader, pver uint32) error { +func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error { return readElement(r, &msg.BlockHash) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. -func (msg *MsgGetCBFilter) BtcEncode(w io.Writer, pver uint32) error { +func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32) error { return writeElement(w, &msg.BlockHash) } // Command returns the protocol command string for the message. This is part // of the Message interface implementation. -func (msg *MsgGetCBFilter) Command() string { - return CmdGetCBFilter +func (msg *MsgGetCFilter) Command() string { + return CmdGetCFilter } // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. -func (msg *MsgGetCBFilter) MaxPayloadLength(pver uint32) uint32 { +func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { // Protocol version 4 bytes + block hash. return 4 + chainhash.HashSize } -// NewMsgGetCBFilter returns a new bitcoin getblocks message that conforms to +// NewMsgGetCFilter returns a new bitcoin getblocks message that conforms to // the Message interface using the passed parameters and defaults for the // remaining fields. -func NewMsgGetCBFilter(blockHash *chainhash.Hash) *MsgGetCBFilter { - return &MsgGetCBFilter{ +func NewMsgGetCFilter(blockHash *chainhash.Hash) *MsgGetCFilter { + return &MsgGetCFilter{ ProtocolVersion: ProtocolVersion, BlockHash: *blockHash, } diff --git a/wire/protocol.go b/wire/protocol.go index 9ea704fb20..c767a5faae 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -72,9 +72,9 @@ const ( // and transactions including witness data (BIP0144). SFNodeWitness - // SFNNodeCBF is a flag used to indicate a peer supports committed - // bloom filters (CBFs). - SFNodeCBF + // SFNodeCF is a flag used to indicate a peer supports committed + // filters (CFs). + SFNodeCF ) // Map of service flags back to their constant names for pretty printing. @@ -83,7 +83,7 @@ var sfStrings = map[ServiceFlag]string{ SFNodeGetUTXO: "SFNodeGetUTXO", SFNodeBloom: "SFNodeBloom", SFNodeWitness: "SFNodeWitness", - SFNodeCBF: "SFNodeCBF", + SFNodeCF: "SFNodeCF", } // orderedSFStrings is an ordered list of service flags from highest to @@ -93,7 +93,7 @@ var orderedSFStrings = []ServiceFlag{ SFNodeGetUTXO, SFNodeBloom, SFNodeWitness, - SFNodeCBF, + SFNodeCF, } // String returns the ServiceFlag in human-readable form. diff --git a/wire/protocol_test.go b/wire/protocol_test.go index dd3ea11f02..9a968f5758 100644 --- a/wire/protocol_test.go +++ b/wire/protocol_test.go @@ -18,8 +18,8 @@ func TestServiceFlagStringer(t *testing.T) { {SFNodeBloom, "SFNodeBloom"}, {SFNodeWitness, "SFNodeWitness"}, {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|0xfffffff0"}, - {SFNodeCBF, "SFNodeCBF"}, - {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeCBF|0xfffffff0"}, + {SFNodeCF, "SFNodeCF"}, + {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeCF|0xfffffff0"}, } t.Logf("Running %d tests", len(tests)) From 92c8ec4094304d99df3481700ede7cde7a2901fc Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 18 Jan 2017 08:55:52 +0000 Subject: [PATCH 0084/1056] cbfindex.go -> cfindex.go --- blockchain/indexers/{cbfindex.go => cfindex.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename blockchain/indexers/{cbfindex.go => cfindex.go} (100%) diff --git a/blockchain/indexers/cbfindex.go b/blockchain/indexers/cfindex.go similarity index 100% rename from blockchain/indexers/cbfindex.go rename to blockchain/indexers/cfindex.go From 6d6677b7976267bbf2860a3e4c1328f56d3a0a10 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 18 Jan 2017 09:12:37 +0000 Subject: [PATCH 0085/1056] zap errCFEntry --- blockchain/indexers/cfindex.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 80563cba5d..0de88cc798 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -6,7 +6,6 @@ package indexers import ( "encoding/binary" - "errors" "fmt" "github.com/btcsuite/btcd/blockchain" @@ -27,10 +26,6 @@ var ( // cfIndexKey is the name of the db bucket used to house the // block hash -> CF index. cfIndexKey = []byte("cfbyhashidx") - - // errNoCFEntry is an error that indicates a requested entry does - // not exist in the CF index. - errCFEntry = errors.New("no entry in the block ID index") ) func dbFetchCFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, From 472141f88d6ad2c880a84fc9b06a81c035460fae Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 19 Jan 2017 10:49:40 +0000 Subject: [PATCH 0086/1056] Switch to new GCS builder interface --- blockchain/indexers/cfindex.go | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 0de88cc798..202a9fb56c 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -5,14 +5,13 @@ package indexers import ( - "encoding/binary" "fmt" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/gcs" + "github.com/btcsuite/btcutil/gcs/builder" "os" ) @@ -90,32 +89,21 @@ func (idx *CFIndex) Create(dbTx database.Tx) error { } func generateFilterForBlock(block *btcutil.Block) ([]byte, error) { - txSlice := block.Transactions() // XXX can this fail? - txHashes := make([][]byte, len(txSlice)) - - for i := 0; i < len(txSlice); i++ { - txHash, err := block.TxHash(i) - if err != nil { - return nil, err - } - txHashes = append(txHashes, txHash[:]) + b := builder.WithKeyHash(block.Hash()) + _, err := b.Key() + if err != nil { + return nil, err } - - var key [gcs.KeySize]byte - P := uint8(20) // collision probability - - for i := 0; i < gcs.KeySize; i += 4 { - binary.BigEndian.PutUint32(key[i:], uint32(0xcafebabe)) + for _, tx := range block.Transactions() { + for _, txIn := range tx.MsgTx().TxIn { + b.AddOutPoint(txIn.PreviousOutPoint) + } } - - filter, err := gcs.BuildGCSFilter(P, key, txHashes) + f, err := b.Build() if err != nil { return nil, err } - - fmt.Fprintf(os.Stderr, "Generated CF for block %v", block.Hash()) - - return filter.Bytes(), nil + return f.Bytes(), nil } // ConnectBlock is invoked by the index manager when a new block has been From 57995fd11110b7959aaf7481afe0e6a25785a53e Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 19 Jan 2017 13:20:41 +0000 Subject: [PATCH 0087/1056] Start preparing the ground for layer {0,1} filters --- blockchain/indexers/cfindex.go | 37 ++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 202a9fb56c..482c24e1f9 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -18,19 +18,22 @@ import ( const ( // cfIndexName is the human-readable name for the index. - cfIndexName = "committed bloom filter index" + cfIndexName = "committed filter index" ) var ( - // cfIndexKey is the name of the db bucket used to house the - // block hash -> CF index. - cfIndexKey = []byte("cfbyhashidx") + // cfBasicIndexKey is the name of the db bucket used to house the + // block hash -> Basic CF index (CF #0). + cfBasicIndexKey = []byte("cf0byhashidx") + // cfExtendedIndexKey is the name of the db bucket used to house the + // block hash -> Extended CF index (CF #1). + cfExtendedIndexKey = []byte("cf1byhashidx") ) func dbFetchCFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, error) { // Load the record from the database and return now if it doesn't exist. - index := dbTx.Metadata().Bucket(cfIndexKey) + index := dbTx.Metadata().Bucket(cfBasicIndexKey) serializedFilter := index.Get(blockHash[:]) if len(serializedFilter) == 0 { return nil, nil @@ -64,10 +67,8 @@ func (idx *CFIndex) Init() error { } // Key returns the database key to use for the index as a byte slice. -// -// This is part of the Indexer interface. func (idx *CFIndex) Key() []byte { - return cfIndexKey + return cfBasicIndexKey } // Name returns the human-readable name of the index. @@ -77,14 +78,16 @@ func (idx *CFIndex) Name() string { return cfIndexName } -// Create is invoked when the indexer manager determines the index needs -// to be created for the first time. It creates the buckets for the hash-based -// CF index. -// -// This is part of the Indexer interface. +// Create is invoked when the indexer manager determines the index needs to be +// created for the first time. It creates buckets for the two hash-based CF +// indexes (simple, extended). func (idx *CFIndex) Create(dbTx database.Tx) error { meta := dbTx.Metadata() - _, err := meta.CreateBucket(cfIndexKey) + _, err := meta.CreateBucket(cfBasicIndexKey) + if err != nil { + return err + } + _, err = meta.CreateBucket(cfExtendedIndexKey) return err } @@ -119,7 +122,7 @@ func (idx *CFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, } meta := dbTx.Metadata() - index := meta.Bucket(cfIndexKey) + index := meta.Bucket(cfBasicIndexKey) err = index.Put(block.Hash()[:], filterBytes) if err != nil { return err @@ -137,7 +140,7 @@ func (idx *CFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, // This is part of the Indexer interface. func (idx *CFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - index := dbTx.Metadata().Bucket(cfIndexKey) + index := dbTx.Metadata().Bucket(cfBasicIndexKey) filterBytes := index.Get(block.Hash()[:]) if len(filterBytes) == 0 { return fmt.Errorf("can't remove non-existent filter %s from " + @@ -169,5 +172,5 @@ func NewCFIndex(db database.DB) *CFIndex { // DropCFIndex drops the CF index from the provided database if exists. func DropCFIndex(db database.DB) error { - return dropIndex(db, cfIndexKey, cfIndexName) + return dropIndex(db, cfBasicIndexKey, cfIndexName) } From 396d28955c3be3df73fc6df78dea2d8c71a16ba9 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 19 Jan 2017 14:55:39 +0000 Subject: [PATCH 0088/1056] better separation between filters; comments --- blockchain/indexers/cfindex.go | 157 ++++++++++++++++----------------- server.go | 6 +- 2 files changed, 80 insertions(+), 83 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 482c24e1f9..04737679cd 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -5,15 +5,11 @@ package indexers import ( - "fmt" - "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs/builder" - - "os" ) const ( @@ -21,67 +17,86 @@ const ( cfIndexName = "committed filter index" ) +// Committed filters come in two flavours: basic and extended. They are +// generated and dropped in pairs, and both are indexed by a block's hash. +// Besides holding different content, they also live in different buckets. var ( // cfBasicIndexKey is the name of the db bucket used to house the - // block hash -> Basic CF index (CF #0). + // block hash -> Basic cf index (cf#0). cfBasicIndexKey = []byte("cf0byhashidx") // cfExtendedIndexKey is the name of the db bucket used to house the - // block hash -> Extended CF index (CF #1). + // block hash -> Extended cf index (cf#1). cfExtendedIndexKey = []byte("cf1byhashidx") ) -func dbFetchCFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte, - error) { - // Load the record from the database and return now if it doesn't exist. - index := dbTx.Metadata().Bucket(cfBasicIndexKey) - serializedFilter := index.Get(blockHash[:]) - if len(serializedFilter) == 0 { - return nil, nil - } +// dbFetchBasicEntry() retrieves a block's basic filter. An entry's absence is +// not considered an error. The filter is returned serialized. +func dbFetchBasicEntry(dbTx database.Tx, h *chainhash.Hash) ([]byte, error) { + idx := dbTx.Metadata().Bucket(cfBasicIndexKey) + return idx.Get(h[:]), nil +} - return serializedFilter, nil +// dbFetchExtendedEntry() retrieves a block's extended filter. An entry's +// absence is not considered an error. The filter is returned serialized. +func dbFetchExtendedEntry(dbTx database.Tx, h *chainhash.Hash) ([]byte, error) { + idx := dbTx.Metadata().Bucket(cfExtendedIndexKey) + return idx.Get(h[:]), nil } -// The serialized format for keys and values in the block hash to CF bucket is: -// = -// -// Field Type Size -// hash chainhash.Hash 32 bytes -// CF []byte variable -// ----- -// Total: > 32 bytes - -// CFIndex implements a CF by hash index. -type CFIndex struct { +// dbStoreBasicEntry() stores a block's basic filter. +func dbStoreBasicEntry(dbTx database.Tx, h *chainhash.Hash, f []byte) error { + idx := dbTx.Metadata().Bucket(cfBasicIndexKey) + return idx.Put(h[:], f) +} + +// dbStoreBasicEntry() stores a block's extended filter. +func dbStoreExtendedEntry(dbTx database.Tx, h *chainhash.Hash, f []byte) error { + idx := dbTx.Metadata().Bucket(cfExtendedIndexKey) + return idx.Put(h[:], f) +} + +// dbDeleteBasicEntry() deletes a block's basic filter. +func dbDeleteBasicEntry(dbTx database.Tx, h *chainhash.Hash) error { + idx := dbTx.Metadata().Bucket(cfBasicIndexKey) + return idx.Delete(h[:]) +} + +// dbDeleteExtendedEntry() deletes a block's extended filter. +func dbDeleteExtendedEntry(dbTx database.Tx, h *chainhash.Hash) error { + idx := dbTx.Metadata().Bucket(cfExtendedIndexKey) + return idx.Delete(h[:]) +} + +// CfIndex implements a committed filter (cf) by hash index. +type CfIndex struct { db database.DB } -// Ensure the CFIndex type implements the Indexer interface. -var _ Indexer = (*CFIndex)(nil) +// Ensure the CfIndex type implements the Indexer interface. +var _ Indexer = (*CfIndex)(nil) -// Init initializes the hash-based CF index. -// -// This is part of the Indexer interface. -func (idx *CFIndex) Init() error { - return nil +// Init initializes the hash-based cf index. This is part of the Indexer +// interface. +func (idx *CfIndex) Init() error { + return nil // Nothing to do. } -// Key returns the database key to use for the index as a byte slice. -func (idx *CFIndex) Key() []byte { +// Key returns the database key to use for the index as a byte slice. This is +// part of the Indexer interface. +func (idx *CfIndex) Key() []byte { return cfBasicIndexKey } -// Name returns the human-readable name of the index. -// -// This is part of the Indexer interface. -func (idx *CFIndex) Name() string { +// Name returns the human-readable name of the index. This is part of the +// Indexer interface. +func (idx *CfIndex) Name() string { return cfIndexName } // Create is invoked when the indexer manager determines the index needs to be -// created for the first time. It creates buckets for the two hash-based CF +// created for the first time. It creates buckets for the two hash-based cf // indexes (simple, extended). -func (idx *CFIndex) Create(dbTx database.Tx) error { +func (idx *CfIndex) Create(dbTx database.Tx) error { meta := dbTx.Metadata() _, err := meta.CreateBucket(cfBasicIndexKey) if err != nil { @@ -91,7 +106,9 @@ func (idx *CFIndex) Create(dbTx database.Tx) error { return err } -func generateFilterForBlock(block *btcutil.Block) ([]byte, error) { +// makeBasicFilter() builds a block's basic filter, which consists of all +// outpoints referenced by transactions within the block. +func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { b := builder.WithKeyHash(block.Hash()) _, err := b.Key() if err != nil { @@ -110,67 +127,47 @@ func generateFilterForBlock(block *btcutil.Block) ([]byte, error) { } // ConnectBlock is invoked by the index manager when a new block has been -// connected to the main chain. This indexer adds a hash-to-CF mapping for -// every passed block. -// -// This is part of the Indexer interface. -func (idx *CFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, +// connected to the main chain. This indexer adds a hash-to-cf mapping for +// every passed block. This is part of the Indexer interface. +func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - filterBytes, err := generateFilterForBlock(block) - if err != nil { - return err - } - - meta := dbTx.Metadata() - index := meta.Bucket(cfBasicIndexKey) - err = index.Put(block.Hash()[:], filterBytes) + f, err := makeBasicFilterForBlock(block) if err != nil { return err } - - fmt.Fprintf(os.Stderr, "Stored CF for block %v", block.Hash()) - - return nil + return dbStoreBasicEntry(dbTx, block.Hash(), f) } // DisconnectBlock is invoked by the index manager when a block has been -// disconnected from the main chain. This indexer removes the hash-to-CF -// mapping for every passed block. -// -// This is part of the Indexer interface. -func (idx *CFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, +// disconnected from the main chain. This indexer removes the hash-to-cf +// mapping for every passed block. This is part of the Indexer interface. +func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - index := dbTx.Metadata().Bucket(cfBasicIndexKey) - filterBytes := index.Get(block.Hash()[:]) - if len(filterBytes) == 0 { - return fmt.Errorf("can't remove non-existent filter %s from " + - "the cfilter index", block.Hash()) - } - return index.Delete(block.Hash()[:]) + return dbDeleteBasicEntry(dbTx, block.Hash()) } -func (idx *CFIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) { +func (idx *CfIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) { var filterBytes []byte err := idx.db.View(func(dbTx database.Tx) error { var err error - filterBytes, err = dbFetchCFIndexEntry(dbTx, hash) + filterBytes, err = dbFetchBasicEntry(dbTx, hash) return err }) return filterBytes, err } -// NewCFIndex returns a new instance of an indexer that is used to create a +// NewCfIndex returns a new instance of an indexer that is used to create a // mapping of the hashes of all blocks in the blockchain to their respective -// committed bloom filters. +// committed filters. // // It implements the Indexer interface which plugs into the IndexManager that in -// turn is used by the blockchain package. This allows the index to be +// turn is used by the blockchain package. This allows the index to be // seamlessly maintained along with the chain. -func NewCFIndex(db database.DB) *CFIndex { - return &CFIndex{db: db} +func NewCfIndex(db database.DB) *CfIndex { + return &CfIndex{db: db} } -// DropCFIndex drops the CF index from the provided database if exists. -func DropCFIndex(db database.DB) error { +// DropCfIndex drops the CF index from the provided database if exists. +func DropCfIndex(db database.DB) error { return dropIndex(db, cfBasicIndexKey, cfIndexName) } diff --git a/server.go b/server.go index 7ece52ebb4..bcfcf75267 100644 --- a/server.go +++ b/server.go @@ -229,7 +229,7 @@ type server struct { // do not need to be protected for concurrent access. txIndex *indexers.TxIndex addrIndex *indexers.AddrIndex - cfIndex *indexers.CFIndex + cfIndex *indexers.CfIndex } // serverPeer extends the peer to maintain state shared by the server and @@ -2244,8 +2244,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param indexes = append(indexes, s.addrIndex) } if !cfg.NoCFilters { - indxLog.Info("CF index is enabled") - s.cfIndex = indexers.NewCFIndex(db) + indxLog.Info("cf index is enabled") + s.cfIndex = indexers.NewCfIndex(db) indexes = append(indexes, s.cfIndex) } From f16da156c9b8fcc55a9e59cff106f7f859bc09dd Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 19 Jan 2017 16:09:36 +0000 Subject: [PATCH 0089/1056] Include data pushes from pkscripts --- blockchain/indexers/cfindex.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 04737679cd..378fcd5c7f 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -118,6 +118,9 @@ func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { for _, txIn := range tx.MsgTx().TxIn { b.AddOutPoint(txIn.PreviousOutPoint) } + for _, txOut := range tx.MsgTx().TxOut { + b.AddScript(txOut.PkScript) + } } f, err := b.Build() if err != nil { From f703e186528aca917c04a26699424a5e26f48aae Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Fri, 20 Jan 2017 13:21:49 +0000 Subject: [PATCH 0090/1056] Populate filter #1 (extended) --- blockchain/indexers/cfindex.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 378fcd5c7f..01523e7fc9 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -107,7 +107,8 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { } // makeBasicFilter() builds a block's basic filter, which consists of all -// outpoints referenced by transactions within the block. +// outpoints and pkscript data pushes referenced by transactions within the +// block. func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { b := builder.WithKeyHash(block.Hash()) _, err := b.Key() @@ -129,6 +130,27 @@ func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { return f.Bytes(), nil } +// makeExtendedFilter() builds a block's extended filter, which consists of +// all tx hashes and sigscript data pushes contained in the block. +func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { + b := builder.WithKeyHash(block.Hash()) + _, err := b.Key() + if err != nil { + return nil, err + } + for _, tx := range block.Transactions() { + b.AddHash(tx.Hash()) + for _, txIn := range tx.MsgTx().TxIn { + b.AddScript(txIn.SignatureScript) + } + } + f, err := b.Build() + if err != nil { + return nil, err + } + return f.Bytes(), nil +} + // ConnectBlock is invoked by the index manager when a new block has been // connected to the main chain. This indexer adds a hash-to-cf mapping for // every passed block. This is part of the Indexer interface. From 71c421db666cab30001138eb6e1217f433262783 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Fri, 20 Jan 2017 15:01:19 +0000 Subject: [PATCH 0091/1056] Differentiate between basic/extended filters in p2p/RPC --- blockchain/indexers/cfindex.go | 8 ++++++-- btcjson/chainsvrcmds.go | 8 +++++--- btcjson/chainsvrcmds_test.go | 6 +++--- peer/peer.go | 3 --- rpcserver.go | 2 +- server.go | 3 ++- wire/msggetcfilter.go | 22 ++++++++++++++++------ 7 files changed, 33 insertions(+), 19 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 01523e7fc9..5152db3040 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -171,11 +171,15 @@ func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, return dbDeleteBasicEntry(dbTx, block.Hash()) } -func (idx *CfIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) { +func (idx *CfIndex) FilterByBlockHash(hash *chainhash.Hash, extended bool) ([]byte, error) { var filterBytes []byte err := idx.db.View(func(dbTx database.Tx) error { var err error - filterBytes, err = dbFetchBasicEntry(dbTx, hash) + if extended { + filterBytes, err = dbFetchExtendedEntry(dbTx, hash) + } else { + filterBytes, err = dbFetchBasicEntry(dbTx, hash) + } return err }) return filterBytes, err diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 904627626f..9461ff8b86 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -280,14 +280,16 @@ func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd { } // GetCFilterCmd defines the getcfilter JSON-RPC command. type GetCFilterCmd struct { - Hash string + Hash string + Extended bool } // NewGetCFilterCmd returns a new instance which can be used to issue a // getcfilter JSON-RPC command. -func NewGetCFilterCmd(hash string) *GetCFilterCmd { +func NewGetCFilterCmd(hash string, extended bool) *GetCFilterCmd { return &GetCFilterCmd{ - Hash: hash, + Hash: hash, + Extended: extended, } } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 0501bee558..a5b43b2dbe 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -320,12 +320,12 @@ func TestChainSvrCmds(t *testing.T) { { name: "getcfilter", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getcfilter", "123") + return btcjson.NewCmd("getcfilter", "123", false) }, staticCmd: func() interface{} { - return btcjson.NewGetCFilterCmd("123") + return btcjson.NewGetCFilterCmd("123", false) }, - marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123"],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",false],"id":1}`, unmarshalled: &btcjson.GetCFilterCmd{ Hash: "123", }, diff --git a/peer/peer.go b/peer/peer.go index ea0e3aa260..feefed6c8d 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1284,9 +1284,6 @@ func (p *Peer) maybeAddDeadline(pendingResponses map[string]time.Time, msgCmd st // headers. deadline = time.Now().Add(stallResponseTimeout * 3) pendingResponses[wire.CmdHeaders] = deadline - - // XXX pedro: we may need to handle OnCFilter here depending on the - // protocol behaviour defined. } } diff --git a/rpcserver.go b/rpcserver.go index 72f0f6a4ac..6654cd6163 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2154,7 +2154,7 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return nil, rpcDecodeHexError(c.Hash) } - filterBytes, err := s.server.cfIndex.FilterByBlockHash(hash) + filterBytes, err := s.server.cfIndex.FilterByBlockHash(hash, c.Extended) if len(filterBytes) > 0 { rpcsLog.Debugf("Found committed filter for %v", hash) } else { diff --git a/server.go b/server.go index bcfcf75267..56eae15f72 100644 --- a/server.go +++ b/server.go @@ -746,7 +746,8 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { return } - filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash) + filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash, + msg.Extended) if len(filterBytes) > 0 { peerLog.Infof("Obtained CB filter for %v", msg.BlockHash) diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index 160fc5f1d8..5e3e861429 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -13,16 +13,25 @@ import ( type MsgGetCFilter struct { ProtocolVersion uint32 BlockHash chainhash.Hash + Extended bool } func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error { - return readElement(r, &msg.BlockHash) + err := readElement(r, &msg.BlockHash) + if err != nil { + return err + } + return readElement(r, &msg.Extended) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32) error { - return writeElement(w, &msg.BlockHash) + err := writeElement(w, &msg.BlockHash) + if err != nil { + return err + } + return writeElement(w, &msg.Extended) } // Command returns the protocol command string for the message. This is part @@ -34,16 +43,17 @@ func (msg *MsgGetCFilter) Command() string { // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { - // Protocol version 4 bytes + block hash. - return 4 + chainhash.HashSize + // Protocol version 4 bytes + block hash + Extended flag. + return 4 + chainhash.HashSize + 1 } // NewMsgGetCFilter returns a new bitcoin getblocks message that conforms to // the Message interface using the passed parameters and defaults for the // remaining fields. -func NewMsgGetCFilter(blockHash *chainhash.Hash) *MsgGetCFilter { +func NewMsgGetCFilter(blockHash *chainhash.Hash, extended bool) *MsgGetCFilter { return &MsgGetCFilter{ - ProtocolVersion: ProtocolVersion, + ProtocolVersion: ProtocolVersion, BlockHash: *blockHash, + Extended: extended, } } From cdb3d44fa8af81683d0d45de06712f99df59ef74 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Fri, 20 Jan 2017 15:55:09 +0000 Subject: [PATCH 0092/1056] p2p needs a new message to return committed filters --- server.go | 3 +++ wire/message.go | 4 +++ wire/msgcfilter.go | 61 +++++++++++++++++++++++++++++++++++++++++++ wire/msggetcfilter.go | 2 +- 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 wire/msgcfilter.go diff --git a/server.go b/server.go index 56eae15f72..1e47eca41b 100644 --- a/server.go +++ b/server.go @@ -755,6 +755,9 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { peerLog.Infof("Could not obtain CB filter for %v: %v", msg.BlockHash, err) } + + filterMsg := wire.NewMsgCFilter(filterBytes) + sp.QueueMessage(filterMsg, nil) } // enforceNodeBloomFlag disconnects the peer if the server is not configured to diff --git a/wire/message.go b/wire/message.go index 96388b603c..168d881d36 100644 --- a/wire/message.go +++ b/wire/message.go @@ -52,6 +52,7 @@ const ( CmdSendHeaders = "sendheaders" CmdFeeFilter = "feefilter" CmdGetCFilter = "getcfilter" + CmdCFilter = "cfilter" ) // MessageEncoding represents the wire message encoding format to be used. @@ -160,6 +161,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFilter: msg = &MsgGetCFilter{} + case CmdCFilter: + msg = &MsgCFilter{} + default: return nil, fmt.Errorf("unhandled command [%s]", command) } diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go new file mode 100644 index 0000000000..ad12cc909a --- /dev/null +++ b/wire/msgcfilter.go @@ -0,0 +1,61 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "fmt" + "io" +) + +const ( + // MaxCFilterDataSize is the maximum byte size of a committed filter. + MaxCFilterDataSize = 65536 +) +type MsgCFilter struct { + Data []byte +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32) error { + var err error + msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize, + "cfilter data") + return err +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32) error { + size := len(msg.Data) + if size > MaxCFilterDataSize { + str := fmt.Sprintf("cfilter size too large for message "+ + "[size %v, max %v]", size, MaxCFilterDataSize) + return messageError("MsgCFilter.BtcEncode", str) + } + + return WriteVarBytes(w, pver, msg.Data) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgCFilter) Command() string { + return CmdCFilter +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 { + return uint32(VarIntSerializeSize(MaxCFilterDataSize)) + + MaxCFilterDataSize +} + +// NewMsgFilterAdd returns a new bitcoin filteradd message that conforms to the +// Message interface. See MsgCFilter for details. +func NewMsgCFilter(data []byte) *MsgCFilter { + return &MsgCFilter{ + Data: data, + } +} diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index 5e3e861429..b8aa18e770 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. From 0a841fefcf7d977694cbcdd017838ee5949916f6 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 31 Jan 2017 09:53:00 +0000 Subject: [PATCH 0093/1056] Generate and store extended filters in ConnectBlock() --- blockchain/indexers/cfindex.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 5152db3040..d8e50ed97e 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -160,7 +160,15 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, if err != nil { return err } - return dbStoreBasicEntry(dbTx, block.Hash(), f) + err = dbStoreBasicEntry(dbTx, block.Hash(), f) + if err != nil { + return err + } + f, err = makeExtendedFilterForBlock(block) + if err != nil { + return err + } + return dbStoreExtendedEntry(dbTx, block.Hash(), f) } // DisconnectBlock is invoked by the index manager when a block has been From ddfaed7f6fee84dd45b10c70bd78a4669f6621f5 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 31 Jan 2017 09:56:07 +0000 Subject: [PATCH 0094/1056] Delete extended filters in DisconnectBlock() --- blockchain/indexers/cfindex.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index d8e50ed97e..f39573dd0b 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -176,7 +176,11 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, // mapping for every passed block. This is part of the Indexer interface. func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - return dbDeleteBasicEntry(dbTx, block.Hash()) + err := dbDeleteBasicEntry(dbTx, block.Hash()) + if err != nil { + return err + } + return dbDeleteExtendedEntry(dbTx, block.Hash()) } func (idx *CfIndex) FilterByBlockHash(hash *chainhash.Hash, extended bool) ([]byte, error) { From 76738591081c5cbde0b95a3d6bbc5d061133b63d Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Tue, 31 Jan 2017 10:01:21 +0000 Subject: [PATCH 0095/1056] Create db buckets for committed filter hashes --- blockchain/indexers/cfindex.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index f39573dd0b..b4344581e6 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -22,11 +22,17 @@ const ( // Besides holding different content, they also live in different buckets. var ( // cfBasicIndexKey is the name of the db bucket used to house the - // block hash -> Basic cf index (cf#0). + // block hash -> basic cf index (cf#0). cfBasicIndexKey = []byte("cf0byhashidx") + // cfBasicHeaderKey is the name of the db bucket used to house the + // block hash -> basic cf header index (cf#0). + cfBasicHeaderKey = []byte("cf0headerbyhashidx") // cfExtendedIndexKey is the name of the db bucket used to house the - // block hash -> Extended cf index (cf#1). + // block hash -> extended cf index (cf#1). cfExtendedIndexKey = []byte("cf1byhashidx") + // cfExtendedHeaderKey is the name of the db bucket used to house the + // block hash -> extended cf header index (cf#1). + cfExtendedHeaderKey = []byte("cf1headerbyhashidx") ) // dbFetchBasicEntry() retrieves a block's basic filter. An entry's absence is @@ -102,7 +108,15 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { if err != nil { return err } + _, err = meta.CreateBucket(cfBasicHeaderKey) + if err != nil { + return err + } _, err = meta.CreateBucket(cfExtendedIndexKey) + if err != nil { + return err + } + _, err = meta.CreateBucket(cfExtendedHeaderKey) return err } From b53c42f5dc55360f22fa3dab1005bed3c28336b9 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 1 Feb 2017 09:50:36 +0000 Subject: [PATCH 0096/1056] Define dbFetch{Basic,Extended}Header() --- blockchain/indexers/cfindex.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index b4344581e6..b3ab58899a 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -49,6 +49,20 @@ func dbFetchExtendedEntry(dbTx database.Tx, h *chainhash.Hash) ([]byte, error) { return idx.Get(h[:]), nil } +// dbFetchBasicHeader() retrieves a block's basic filter header. A filter's +// absence is not considered an error. +func dbFetchBasicHeader(dbTx database.Tx, h *chainhash.Hash) ([]byte, error) { + idx := dbTx.Metadata().Bucket(cfBasicHeaderKey) + return idx.Get(h[:]), nil +} + +// dbFetchExtendedHeader() retrieves a block's extended filter header. +// A filter's absence is not considered an error. +func dbFetchExtendedHeader(dbTx database.Tx, h*chainhash.Hash) ([]byte, error) { + idx := dbTx.Metadata().Bucket(cfExtendedHeaderKey) + return idx.Get(h[:]), nil +} + // dbStoreBasicEntry() stores a block's basic filter. func dbStoreBasicEntry(dbTx database.Tx, h *chainhash.Hash, f []byte) error { idx := dbTx.Metadata().Bucket(cfBasicIndexKey) From e620538343212d922930a72c02514214234ed495 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 1 Feb 2017 12:12:30 +0000 Subject: [PATCH 0097/1056] Generate and store filter headers --- blockchain/indexers/cfindex.go | 131 +++++++++++++++++++++------------ 1 file changed, 82 insertions(+), 49 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index b3ab58899a..99a40a8bd2 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -5,11 +5,13 @@ package indexers import ( + "errors" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs/builder" + "github.com/btcsuite/fastsha256" ) const ( @@ -35,55 +37,48 @@ var ( cfExtendedHeaderKey = []byte("cf1headerbyhashidx") ) -// dbFetchBasicEntry() retrieves a block's basic filter. An entry's absence is -// not considered an error. The filter is returned serialized. -func dbFetchBasicEntry(dbTx database.Tx, h *chainhash.Hash) ([]byte, error) { - idx := dbTx.Metadata().Bucket(cfBasicIndexKey) - return idx.Get(h[:]), nil -} - -// dbFetchExtendedEntry() retrieves a block's extended filter. An entry's -// absence is not considered an error. The filter is returned serialized. -func dbFetchExtendedEntry(dbTx database.Tx, h *chainhash.Hash) ([]byte, error) { - idx := dbTx.Metadata().Bucket(cfExtendedIndexKey) - return idx.Get(h[:]), nil -} - -// dbFetchBasicHeader() retrieves a block's basic filter header. A filter's +// dbFetchFilter() retrieves a block's basic or extended filter. A filter's // absence is not considered an error. -func dbFetchBasicHeader(dbTx database.Tx, h *chainhash.Hash) ([]byte, error) { - idx := dbTx.Metadata().Bucket(cfBasicHeaderKey) +func dbFetchFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { + idx := dbTx.Metadata().Bucket(key) return idx.Get(h[:]), nil } -// dbFetchExtendedHeader() retrieves a block's extended filter header. +// dbFetchFilterHeader() retrieves a block's basic or extended filter header. // A filter's absence is not considered an error. -func dbFetchExtendedHeader(dbTx database.Tx, h*chainhash.Hash) ([]byte, error) { - idx := dbTx.Metadata().Bucket(cfExtendedHeaderKey) - return idx.Get(h[:]), nil +func dbFetchFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { + idx := dbTx.Metadata().Bucket(key) + fh := idx.Get(h[:]) + if len(fh) != fastsha256.Size { + return nil, errors.New("invalid filter header length") + } + return fh, nil } -// dbStoreBasicEntry() stores a block's basic filter. -func dbStoreBasicEntry(dbTx database.Tx, h *chainhash.Hash, f []byte) error { - idx := dbTx.Metadata().Bucket(cfBasicIndexKey) +// dbStoreFilter() stores a block's basic or extended filter. +func dbStoreFilter(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error { + idx := dbTx.Metadata().Bucket(key) return idx.Put(h[:], f) } -// dbStoreBasicEntry() stores a block's extended filter. -func dbStoreExtendedEntry(dbTx database.Tx, h *chainhash.Hash, f []byte) error { - idx := dbTx.Metadata().Bucket(cfExtendedIndexKey) - return idx.Put(h[:], f) +// dbStoreFilterHeader() stores a block's basic or extended filter header. +func dbStoreFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash, fh []byte) error { + if len(fh) != fastsha256.Size { + return errors.New("invalid filter header length") + } + idx := dbTx.Metadata().Bucket(key) + return idx.Put(h[:], fh) } -// dbDeleteBasicEntry() deletes a block's basic filter. -func dbDeleteBasicEntry(dbTx database.Tx, h *chainhash.Hash) error { - idx := dbTx.Metadata().Bucket(cfBasicIndexKey) +// dbDeleteFilter() deletes a filter's basic or extended filter. +func dbDeleteFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) error { + idx := dbTx.Metadata().Bucket(key) return idx.Delete(h[:]) } -// dbDeleteExtendedEntry() deletes a block's extended filter. -func dbDeleteExtendedEntry(dbTx database.Tx, h *chainhash.Hash) error { - idx := dbTx.Metadata().Bucket(cfExtendedIndexKey) +// dbDeleteFilterHeader() deletes a filter's basic or extended filter header. +func dbDeleteFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) error { + idx := dbTx.Metadata().Bucket(key) return idx.Delete(h[:]) } @@ -113,8 +108,8 @@ func (idx *CfIndex) Name() string { return cfIndexName } -// Create is invoked when the indexer manager determines the index needs to be -// created for the first time. It creates buckets for the two hash-based cf +// Create() is invoked when the indexer manager determines the index needs to +// be created for the first time. It creates buckets for the two hash-based cf // indexes (simple, extended). func (idx *CfIndex) Create(dbTx database.Tx) error { meta := dbTx.Metadata() @@ -134,8 +129,8 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { return err } -// makeBasicFilter() builds a block's basic filter, which consists of all -// outpoints and pkscript data pushes referenced by transactions within the +// makeBasicFilterForBlock() builds a block's basic filter, which consists of +// all outpoints and pkscript data pushes referenced by transactions within the // block. func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { b := builder.WithKeyHash(block.Hash()) @@ -158,8 +153,8 @@ func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { return f.Bytes(), nil } -// makeExtendedFilter() builds a block's extended filter, which consists of -// all tx hashes and sigscript data pushes contained in the block. +// makeExtendedFilterForBlock() builds a block's extended filter, which consists +// of all tx hashes and sigscript data pushes contained in the block. func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { b := builder.WithKeyHash(block.Hash()) _, err := b.Key() @@ -179,7 +174,45 @@ func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { return f.Bytes(), nil } -// ConnectBlock is invoked by the index manager when a new block has been +// makeHeaderForFilter() implements the chaining logic between filters, where +// a filter's header is defined as sha256(sha256(filter) + previousFilterHeader). +func makeHeaderForFilter(f, pfh []byte) []byte { + fhash := fastsha256.Sum256(f) + chain := make([]byte, 0, 2*fastsha256.Size) + chain = append(chain, fhash[:]...) + chain = append(chain, pfh...) + fh := fastsha256.Sum256(chain) + return fh[:] +} + +// storeFilter() stores a given filter, and performs the steps needed to +// generate the filter's header. +func storeFilter(dbTx database.Tx, block *btcutil.Block, f []byte, extended bool) error { + // Figure out which buckets to use. + fkey := cfBasicIndexKey + hkey := cfBasicHeaderKey + if extended { + fkey = cfExtendedIndexKey + hkey = cfExtendedHeaderKey + } + // Start by storing the filter. + h := block.Hash() + err := dbStoreFilter(dbTx, fkey, h, f) + if err != nil { + return err + } + // Then fetch the previous block's filter header. + ph := &block.MsgBlock().Header.PrevBlock + pfh, err := dbFetchFilterHeader(dbTx, hkey, ph) + if err != nil { + return err + } + // Construct the new block's filter header, and store it. + fh := makeHeaderForFilter(f, pfh) + return dbStoreFilterHeader(dbTx, cfBasicHeaderKey, h, fh) +} + +// ConnectBlock() is invoked by the index manager when a new block has been // connected to the main chain. This indexer adds a hash-to-cf mapping for // every passed block. This is part of the Indexer interface. func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, @@ -188,7 +221,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, if err != nil { return err } - err = dbStoreBasicEntry(dbTx, block.Hash(), f) + err = storeFilter(dbTx, block, f, false) if err != nil { return err } @@ -196,30 +229,30 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, if err != nil { return err } - return dbStoreExtendedEntry(dbTx, block.Hash(), f) + return storeFilter(dbTx, block, f, true) } -// DisconnectBlock is invoked by the index manager when a block has been +// DisconnectBlock() is invoked by the index manager when a block has been // disconnected from the main chain. This indexer removes the hash-to-cf // mapping for every passed block. This is part of the Indexer interface. func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - err := dbDeleteBasicEntry(dbTx, block.Hash()) + err := dbDeleteFilter(dbTx, cfBasicIndexKey, block.Hash()) if err != nil { return err } - return dbDeleteExtendedEntry(dbTx, block.Hash()) + return dbDeleteFilter(dbTx, cfExtendedIndexKey, block.Hash()) } func (idx *CfIndex) FilterByBlockHash(hash *chainhash.Hash, extended bool) ([]byte, error) { var filterBytes []byte err := idx.db.View(func(dbTx database.Tx) error { var err error + key := cfBasicIndexKey if extended { - filterBytes, err = dbFetchExtendedEntry(dbTx, hash) - } else { - filterBytes, err = dbFetchBasicEntry(dbTx, hash) + key = cfExtendedIndexKey } + filterBytes, err = dbFetchFilter(dbTx, key, hash) return err }) return filterBytes, err From a5bf8941d5d055d8f87c0a0515730702739172e3 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 1 Feb 2017 13:43:09 +0000 Subject: [PATCH 0098/1056] Define FilterHeaderByBlockHash() --- blockchain/indexers/cfindex.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 99a40a8bd2..260d154256 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -244,18 +244,36 @@ func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, return dbDeleteFilter(dbTx, cfExtendedIndexKey, block.Hash()) } -func (idx *CfIndex) FilterByBlockHash(hash *chainhash.Hash, extended bool) ([]byte, error) { - var filterBytes []byte +// FilterByBlockHash() returns the serialized contents of a block's basic or +// extended committed filter. +func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { + var f []byte err := idx.db.View(func(dbTx database.Tx) error { var err error key := cfBasicIndexKey if extended { key = cfExtendedIndexKey } - filterBytes, err = dbFetchFilter(dbTx, key, hash) + f, err = dbFetchFilter(dbTx, key, h) return err }) - return filterBytes, err + return f, err +} + +// FilterHeaderByBlockHash() returns the serialized contents of a block's basic +// or extended committed filter header. +func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { + var fh []byte + err := idx.db.View(func(dbTx database.Tx) error { + var err error + key := cfBasicHeaderKey + if extended { + key = cfExtendedHeaderKey + } + fh, err = dbFetchFilterHeader(dbTx, key, h) + return err + }) + return fh, err } // NewCfIndex returns a new instance of an indexer that is used to create a From 763842329b975d07ab02b7c7e9f3e3c94c7450ec Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Wed, 1 Feb 2017 13:57:45 +0000 Subject: [PATCH 0099/1056] Implement a GetCFilterHeader RPC command --- btcjson/chainsvrcmds.go | 16 ++++++++++++++++ btcjson/chainsvrcmds_test.go | 13 +++++++++++++ rpcserver.go | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 9461ff8b86..f399397597 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -293,6 +293,21 @@ func NewGetCFilterCmd(hash string, extended bool) *GetCFilterCmd { } } +// GetCFilterHeaderCmd defines the getcfilterheader JSON-RPC command. +type GetCFilterHeaderCmd struct { + Hash string + Extended bool +} + +// NewGetCFilterHeaderCmd returns a new instance which can be used to issue a +// getcfilterheader JSON-RPC command. +func NewGetCFilterHeaderCmd(hash string, extended bool) *GetCFilterHeaderCmd { + return &GetCFilterHeaderCmd{ + Hash: hash, + Extended: extended, + } +} + // GetChainTipsCmd defines the getchaintips JSON-RPC command. type GetChainTipsCmd struct{} @@ -771,6 +786,7 @@ func init() { MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags) MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags) MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags) + MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags) MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags) MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags) MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index a5b43b2dbe..1b2c33e707 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -330,6 +330,19 @@ func TestChainSvrCmds(t *testing.T) { Hash: "123", }, }, + { + name: "getcfilterheader", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getcfilterheader", "123", false) + }, + staticCmd: func() interface{} { + return btcjson.NewGetCFilterHeaderCmd("123", false) + }, + marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",false],"id":1}`, + unmarshalled: &btcjson.GetCFilterHeaderCmd{ + Hash: "123", + }, + }, { name: "getchaintips", newCmd: func() (interface{}, error) { diff --git a/rpcserver.go b/rpcserver.go index 6654cd6163..a7ebf3a919 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -143,6 +143,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "getblockheader": handleGetBlockHeader, "getblocktemplate": handleGetBlockTemplate, "getcfilter": handleGetCFilter, + "getcfilterheader": handleGetCFilterHeader, "getconnectioncount": handleGetConnectionCount, "getcurrentnet": handleGetCurrentNet, "getdifficulty": handleGetDifficulty, @@ -260,6 +261,7 @@ var rpcLimited = map[string]struct{}{ "getblockhash": {}, "getblockheader": {}, "getcfilter": {}, + "getcfilterheader": {}, "getcurrentnet": {}, "getdifficulty": {}, "getheaders": {}, @@ -2169,6 +2171,29 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return hex.EncodeToString(filterBytes), nil } +// handleGetCFilterHeader implements the getcfilterheader command. +func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.GetCFilterHeaderCmd) + hash, err := chainhash.NewHashFromStr(c.Hash) + if err != nil { + return nil, rpcDecodeHexError(c.Hash) + } + + headerBytes, err := s.server.cfIndex.FilterHeaderByBlockHash(hash, c.Extended) + if len(headerBytes) > 0 { + rpcsLog.Debugf("Found header of committed filter for %v", hash) + } else { + rpcsLog.Debugf("Could not find header of committed filter for %v: %v", + hash, err) + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCBlockNotFound, + Message: "Block not found", + } + } + + return hex.EncodeToString(headerBytes), nil +} + // handleGetConnectionCount implements the getconnectioncount command. func handleGetConnectionCount(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { return s.cfg.ConnMgr.ConnectedCount(), nil From 6102e129c5a0a15fa64cf5b636679f34e0f6e3f9 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 1 Feb 2017 19:51:23 -0700 Subject: [PATCH 0100/1056] Fixed a couple of bugs and added --dropcfindex option --- blockchain/indexers/cfindex.go | 79 ++++++++++++++++++++++++---------- btcd.go | 8 ++++ config.go | 1 + server.go | 4 +- 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 260d154256..104aaec3be 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -6,7 +6,9 @@ package indexers import ( "errors" + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" @@ -37,14 +39,14 @@ var ( cfExtendedHeaderKey = []byte("cf1headerbyhashidx") ) -// dbFetchFilter() retrieves a block's basic or extended filter. A filter's +// dbFetchFilter retrieves a block's basic or extended filter. A filter's // absence is not considered an error. func dbFetchFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { idx := dbTx.Metadata().Bucket(key) return idx.Get(h[:]), nil } -// dbFetchFilterHeader() retrieves a block's basic or extended filter header. +// dbFetchFilterHeader retrieves a block's basic or extended filter header. // A filter's absence is not considered an error. func dbFetchFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { idx := dbTx.Metadata().Bucket(key) @@ -55,13 +57,13 @@ func dbFetchFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byt return fh, nil } -// dbStoreFilter() stores a block's basic or extended filter. +// dbStoreFilter stores a block's basic or extended filter. func dbStoreFilter(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error { idx := dbTx.Metadata().Bucket(key) return idx.Put(h[:], f) } -// dbStoreFilterHeader() stores a block's basic or extended filter header. +// dbStoreFilterHeader stores a block's basic or extended filter header. func dbStoreFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash, fh []byte) error { if len(fh) != fastsha256.Size { return errors.New("invalid filter header length") @@ -70,13 +72,13 @@ func dbStoreFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash, fh []b return idx.Put(h[:], fh) } -// dbDeleteFilter() deletes a filter's basic or extended filter. +// dbDeleteFilter deletes a filter's basic or extended filter. func dbDeleteFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) error { idx := dbTx.Metadata().Bucket(key) return idx.Delete(h[:]) } -// dbDeleteFilterHeader() deletes a filter's basic or extended filter header. +// dbDeleteFilterHeader deletes a filter's basic or extended filter header. func dbDeleteFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) error { idx := dbTx.Metadata().Bucket(key) return idx.Delete(h[:]) @@ -84,7 +86,8 @@ func dbDeleteFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) error // CfIndex implements a committed filter (cf) by hash index. type CfIndex struct { - db database.DB + db database.DB + chainParams *chaincfg.Params } // Ensure the CfIndex type implements the Indexer interface. @@ -108,7 +111,7 @@ func (idx *CfIndex) Name() string { return cfIndexName } -// Create() is invoked when the indexer manager determines the index needs to +// Create is invoked when the indexer manager determines the index needs to // be created for the first time. It creates buckets for the two hash-based cf // indexes (simple, extended). func (idx *CfIndex) Create(dbTx database.Tx) error { @@ -126,10 +129,29 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { return err } _, err = meta.CreateBucket(cfExtendedHeaderKey) + if err != nil { + return err + } + firstHeader := make([]byte, chainhash.HashSize) + err = dbStoreFilterHeader( + dbTx, + cfBasicHeaderKey, + &idx.chainParams.GenesisBlock.Header.PrevBlock, + firstHeader, + ) + if err != nil { + return err + } + err = dbStoreFilterHeader( + dbTx, + cfExtendedHeaderKey, + &idx.chainParams.GenesisBlock.Header.PrevBlock, + firstHeader, + ) return err } -// makeBasicFilterForBlock() builds a block's basic filter, which consists of +// makeBasicFilterForBlock builds a block's basic filter, which consists of // all outpoints and pkscript data pushes referenced by transactions within the // block. func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { @@ -153,7 +175,7 @@ func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { return f.Bytes(), nil } -// makeExtendedFilterForBlock() builds a block's extended filter, which consists +// makeExtendedFilterForBlock builds a block's extended filter, which consists // of all tx hashes and sigscript data pushes contained in the block. func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { b := builder.WithKeyHash(block.Hash()) @@ -174,7 +196,7 @@ func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { return f.Bytes(), nil } -// makeHeaderForFilter() implements the chaining logic between filters, where +// makeHeaderForFilter implements the chaining logic between filters, where // a filter's header is defined as sha256(sha256(filter) + previousFilterHeader). func makeHeaderForFilter(f, pfh []byte) []byte { fhash := fastsha256.Sum256(f) @@ -185,7 +207,7 @@ func makeHeaderForFilter(f, pfh []byte) []byte { return fh[:] } -// storeFilter() stores a given filter, and performs the steps needed to +// storeFilter stores a given filter, and performs the steps needed to // generate the filter's header. func storeFilter(dbTx database.Tx, block *btcutil.Block, f []byte, extended bool) error { // Figure out which buckets to use. @@ -209,14 +231,14 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f []byte, extended bool } // Construct the new block's filter header, and store it. fh := makeHeaderForFilter(f, pfh) - return dbStoreFilterHeader(dbTx, cfBasicHeaderKey, h, fh) + return dbStoreFilterHeader(dbTx, hkey, h, fh) } -// ConnectBlock() is invoked by the index manager when a new block has been +// ConnectBlock is invoked by the index manager when a new block has been // connected to the main chain. This indexer adds a hash-to-cf mapping for // every passed block. This is part of the Indexer interface. func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, - view *blockchain.UtxoViewpoint) error { + view *blockchain.UtxoViewpoint) error { f, err := makeBasicFilterForBlock(block) if err != nil { return err @@ -232,11 +254,11 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return storeFilter(dbTx, block, f, true) } -// DisconnectBlock() is invoked by the index manager when a block has been +// DisconnectBlock is invoked by the index manager when a block has been // disconnected from the main chain. This indexer removes the hash-to-cf // mapping for every passed block. This is part of the Indexer interface. func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, - view *blockchain.UtxoViewpoint) error { + view *blockchain.UtxoViewpoint) error { err := dbDeleteFilter(dbTx, cfBasicIndexKey, block.Hash()) if err != nil { return err @@ -244,7 +266,7 @@ func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, return dbDeleteFilter(dbTx, cfExtendedIndexKey, block.Hash()) } -// FilterByBlockHash() returns the serialized contents of a block's basic or +// FilterByBlockHash returns the serialized contents of a block's basic or // extended committed filter. func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { var f []byte @@ -260,7 +282,7 @@ func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte, return f, err } -// FilterHeaderByBlockHash() returns the serialized contents of a block's basic +// FilterHeaderByBlockHash returns the serialized contents of a block's basic // or extended committed filter header. func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { var fh []byte @@ -283,11 +305,24 @@ func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, extended bool) ([ // It implements the Indexer interface which plugs into the IndexManager that in // turn is used by the blockchain package. This allows the index to be // seamlessly maintained along with the chain. -func NewCfIndex(db database.DB) *CfIndex { - return &CfIndex{db: db} +func NewCfIndex(db database.DB, chainParams *chaincfg.Params) *CfIndex { + return &CfIndex{db: db, chainParams: chainParams} } // DropCfIndex drops the CF index from the provided database if exists. func DropCfIndex(db database.DB) error { - return dropIndex(db, cfBasicIndexKey, cfIndexName) + err := dropIndex(db, cfBasicIndexKey, cfIndexName) + if err != nil { + return err + } + err = dropIndex(db, cfBasicHeaderKey, cfIndexName) + if err != nil { + return err + } + err = dropIndex(db, cfExtendedIndexKey, cfIndexName) + if err != nil { + return err + } + err = dropIndex(db, cfExtendedHeaderKey, cfIndexName) + return err } diff --git a/btcd.go b/btcd.go index b656e1b3e3..fdcebed3e9 100644 --- a/btcd.go +++ b/btcd.go @@ -135,6 +135,14 @@ func btcdMain(serverChan chan<- *server) error { return nil } + if cfg.DropCfIndex { + if err := indexers.DropCfIndex(db); err != nil { + btcdLog.Errorf("%v", err) + return err + } + + return nil + } // Create server and start it. server, err := newServer(cfg.Listeners, db, activeNetParams.Params, diff --git a/config.go b/config.go index c8aa1b0c8c..772c5ef8dc 100644 --- a/config.go +++ b/config.go @@ -151,6 +151,7 @@ type config struct { UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."` NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"` NoCFilters bool `long:"nocfilters" description:"Disable committed filtering (CF) support"` + DropCfIndex bool `long:"dropcfindex" description:"Deletes the index used for committed filtering (CF) support from the database on start up and then exits."` SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"` BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."` TxIndex bool `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` diff --git a/server.go b/server.go index 1e47eca41b..3ca3882a9b 100644 --- a/server.go +++ b/server.go @@ -747,7 +747,7 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { } filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash, - msg.Extended) + msg.Extended) if len(filterBytes) > 0 { peerLog.Infof("Obtained CB filter for %v", msg.BlockHash) @@ -2249,7 +2249,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param } if !cfg.NoCFilters { indxLog.Info("cf index is enabled") - s.cfIndex = indexers.NewCfIndex(db) + s.cfIndex = indexers.NewCfIndex(db, chainParams) indexes = append(indexes, s.cfIndex) } From b8c3be740f72389285b6f489228e8f61f7ada177 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 2 Feb 2017 10:42:44 +0000 Subject: [PATCH 0101/1056] Add CFilterHeader p2p counterparts --- peer/peer.go | 9 +++++ peer/peer_test.go | 7 ++++ server.go | 65 +++++++++++++++++++++++++------------ wire/message.go | 58 +++++++++++++++++++-------------- wire/msgcfilterheader.go | 63 +++++++++++++++++++++++++++++++++++ wire/msggetcfilter.go | 2 +- wire/msggetcfilterheader.go | 59 +++++++++++++++++++++++++++++++++ 7 files changed, 216 insertions(+), 47 deletions(-) create mode 100644 wire/msgcfilterheader.go create mode 100644 wire/msggetcfilterheader.go diff --git a/peer/peer.go b/peer/peer.go index feefed6c8d..488f3bcc74 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -148,6 +148,10 @@ type MessageListeners struct { // message. OnGetCFilter func(p *Peer, msg *wire.MsgGetCFilter) + // OnGetCFilterHeader is invoked when a peer receives a + // getcfilterheader bitcoin message. + OnGetCFilterHeader func(p *Peer, msg *wire.MsgGetCFilterHeader) + // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1588,6 +1592,11 @@ out: p.cfg.Listeners.OnGetCFilter(p, msg) } + case *wire.MsgGetCFilterHeader: + if p.cfg.Listeners.OnGetCFilterHeader != nil { + p.cfg.Listeners.OnGetCFilterHeader(p, msg) + } + case *wire.MsgFeeFilter: if p.cfg.Listeners.OnFeeFilter != nil { p.cfg.Listeners.OnFeeFilter(p, msg) diff --git a/peer/peer_test.go b/peer/peer_test.go index bfe2987bbd..c913f79e75 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -402,6 +402,9 @@ func TestPeerListeners(t *testing.T) { OnGetCFilter: func(p *peer.Peer, msg *wire.MsgGetCFilter) { ok <- msg }, + OnGetCFilterHeader: func(p *peer.Peer, msg *wire.MsgGetCFilterHeader) { + ok <- msg + }, OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { ok <- msg }, @@ -529,6 +532,10 @@ func TestPeerListeners(t *testing.T) { "OnGetCFilter", wire.NewMsgGetCFilter(&chainhash.Hash{}), }, + { + "OnGetCFilterHeader", + wire.NewMsgGetCFilterHeader(&chainhash.Hash{}), + }, { "OnFeeFilter", wire.NewMsgFeeFilter(15000), diff --git a/server.go b/server.go index 3ca3882a9b..91b614cb97 100644 --- a/server.go +++ b/server.go @@ -750,16 +750,38 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { msg.Extended) if len(filterBytes) > 0 { - peerLog.Infof("Obtained CB filter for %v", msg.BlockHash) + peerLog.Infof("Obtained CF for %v", msg.BlockHash) } else { - peerLog.Infof("Could not obtain CB filter for %v: %v", - msg.BlockHash, err) + peerLog.Infof("Could not obtain CF for %v: %v", msg.BlockHash, + err) } filterMsg := wire.NewMsgCFilter(filterBytes) sp.QueueMessage(filterMsg, nil) } +// OnGetCFilterHeader is invoked when a peer receives a getcfilterheader bitcoin +// message. +func (sp *serverPeer) OnGetCFilterHeader(_ *peer.Peer, msg *wire.MsgGetCFilterHeader) { + // Ignore getcfilterheader requests if not in sync. + if !sp.server.blockManager.IsCurrent() { + return + } + + headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( + &msg.BlockHash, msg.Extended) + + if len(headerBytes) > 0 { + peerLog.Infof("Obtained CF header for %v", msg.BlockHash) + } else { + peerLog.Infof("Could not obtain CF header for %v: %v", + msg.BlockHash, err) + } + + headerMsg := wire.NewMsgCFilterHeader(headerBytes) + sp.QueueMessage(headerMsg, nil) +} + // enforceNodeBloomFlag disconnects the peer if the server is not configured to // allow bloom filters. Additionally, if the peer has negotiated to a protocol // version that is high enough to observe the bloom filter service support bit, @@ -1598,24 +1620,25 @@ func disconnectPeer(peerList map[int32]*serverPeer, compareFunc func(*serverPeer func newPeerConfig(sp *serverPeer) *peer.Config { return &peer.Config{ Listeners: peer.MessageListeners{ - OnVersion: sp.OnVersion, - OnMemPool: sp.OnMemPool, - OnTx: sp.OnTx, - OnBlock: sp.OnBlock, - OnInv: sp.OnInv, - OnHeaders: sp.OnHeaders, - OnGetData: sp.OnGetData, - OnGetBlocks: sp.OnGetBlocks, - OnGetHeaders: sp.OnGetHeaders, - OnGetCFilter: sp.OnGetCFilter, - OnFeeFilter: sp.OnFeeFilter, - OnFilterAdd: sp.OnFilterAdd, - OnFilterClear: sp.OnFilterClear, - OnFilterLoad: sp.OnFilterLoad, - OnGetAddr: sp.OnGetAddr, - OnAddr: sp.OnAddr, - OnRead: sp.OnRead, - OnWrite: sp.OnWrite, + OnVersion: sp.OnVersion, + OnMemPool: sp.OnMemPool, + OnTx: sp.OnTx, + OnBlock: sp.OnBlock, + OnInv: sp.OnInv, + OnHeaders: sp.OnHeaders, + OnGetData: sp.OnGetData, + OnGetBlocks: sp.OnGetBlocks, + OnGetHeaders: sp.OnGetHeaders, + OnGetCFilter: sp.OnGetCFilter, + OnGetCFilterHeader: sp.OnGetCFilterHeader, + OnFeeFilter: sp.OnFeeFilter, + OnFilterAdd: sp.OnFilterAdd, + OnFilterClear: sp.OnFilterClear, + OnFilterLoad: sp.OnFilterLoad, + OnGetAddr: sp.OnGetAddr, + OnAddr: sp.OnAddr, + OnRead: sp.OnRead, + OnWrite: sp.OnWrite, // Note: The reference client currently bans peers that send alerts // not signed with its key. We could verify against their key, but diff --git a/wire/message.go b/wire/message.go index 168d881d36..ade36386d5 100644 --- a/wire/message.go +++ b/wire/message.go @@ -28,31 +28,33 @@ const MaxMessagePayload = (1024 * 1024 * 32) // 32MB // Commands used in bitcoin message headers which describe the type of message. const ( - CmdVersion = "version" - CmdVerAck = "verack" - CmdGetAddr = "getaddr" - CmdAddr = "addr" - CmdGetBlocks = "getblocks" - CmdInv = "inv" - CmdGetData = "getdata" - CmdNotFound = "notfound" - CmdBlock = "block" - CmdTx = "tx" - CmdGetHeaders = "getheaders" - CmdHeaders = "headers" - CmdPing = "ping" - CmdPong = "pong" - CmdAlert = "alert" - CmdMemPool = "mempool" - CmdFilterAdd = "filteradd" - CmdFilterClear = "filterclear" - CmdFilterLoad = "filterload" - CmdMerkleBlock = "merkleblock" - CmdReject = "reject" - CmdSendHeaders = "sendheaders" - CmdFeeFilter = "feefilter" - CmdGetCFilter = "getcfilter" - CmdCFilter = "cfilter" + CmdVersion = "version" + CmdVerAck = "verack" + CmdGetAddr = "getaddr" + CmdAddr = "addr" + CmdGetBlocks = "getblocks" + CmdInv = "inv" + CmdGetData = "getdata" + CmdNotFound = "notfound" + CmdBlock = "block" + CmdTx = "tx" + CmdGetHeaders = "getheaders" + CmdHeaders = "headers" + CmdPing = "ping" + CmdPong = "pong" + CmdAlert = "alert" + CmdMemPool = "mempool" + CmdFilterAdd = "filteradd" + CmdFilterClear = "filterclear" + CmdFilterLoad = "filterload" + CmdMerkleBlock = "merkleblock" + CmdReject = "reject" + CmdSendHeaders = "sendheaders" + CmdFeeFilter = "feefilter" + CmdGetCFilter = "getcfilter" + CmdGetCFilterHeader = "getcfilterheader" + CmdCFilter = "cfilter" + CmdCFilterHeader = "cfilterheader" ) // MessageEncoding represents the wire message encoding format to be used. @@ -161,9 +163,15 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFilter: msg = &MsgGetCFilter{} + case CmdGetCFilterHeader: + msg = &MsgGetCFilterHeader{} + case CmdCFilter: msg = &MsgCFilter{} + case CmdCFilterHeader: + msg = &MsgCFilterHeader{} + default: return nil, fmt.Errorf("unhandled command [%s]", command) } diff --git a/wire/msgcfilterheader.go b/wire/msgcfilterheader.go new file mode 100644 index 0000000000..ce8d102a5f --- /dev/null +++ b/wire/msgcfilterheader.go @@ -0,0 +1,63 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "fmt" + "github.com/btcsuite/fastsha256" + "io" +) + +const ( + // MaxCFilterHeaderDataSize is the maximum byte size of a committed + // filter header. + MaxCFilterHeaderDataSize = fastsha256.Size +) +type MsgCFilterHeader struct { + Data []byte +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgCFilterHeader) BtcDecode(r io.Reader, pver uint32) error { + var err error + msg.Data, err = ReadVarBytes(r, pver, MaxCFilterHeaderDataSize, + "cf header data") + return err +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgCFilterHeader) BtcEncode(w io.Writer, pver uint32) error { + size := len(msg.Data) + if size > MaxCFilterHeaderDataSize { + str := fmt.Sprintf("cf header size too large for message " + + "[size %v, max %v]", size, MaxCFilterHeaderDataSize) + return messageError("MsgCFilterHeader.BtcEncode", str) + } + + return WriteVarBytes(w, pver, msg.Data) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgCFilterHeader) Command() string { + return CmdCFilterHeader +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgCFilterHeader) MaxPayloadLength(pver uint32) uint32 { + return uint32(VarIntSerializeSize(MaxCFilterHeaderDataSize)) + + MaxCFilterHeaderDataSize +} + +// NewMsgFilterAdd returns a new bitcoin cfilterheader message that conforms to +// the Message interface. See MsgCFilterHeader for details. +func NewMsgCFilterHeader(data []byte) *MsgCFilterHeader { + return &MsgCFilterHeader{ + Data: data, + } +} diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index b8aa18e770..2b775103c0 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -47,7 +47,7 @@ func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { return 4 + chainhash.HashSize + 1 } -// NewMsgGetCFilter returns a new bitcoin getblocks message that conforms to +// NewMsgGetCFilter returns a new bitcoin getcfilter message that conforms to // the Message interface using the passed parameters and defaults for the // remaining fields. func NewMsgGetCFilter(blockHash *chainhash.Hash, extended bool) *MsgGetCFilter { diff --git a/wire/msggetcfilterheader.go b/wire/msggetcfilterheader.go new file mode 100644 index 0000000000..d23e1d18af --- /dev/null +++ b/wire/msggetcfilterheader.go @@ -0,0 +1,59 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +type MsgGetCFilterHeader struct { + ProtocolVersion uint32 + BlockHash chainhash.Hash + Extended bool +} + +func (msg *MsgGetCFilterHeader) BtcDecode(r io.Reader, pver uint32) error { + err := readElement(r, &msg.BlockHash) + if err != nil { + return err + } + return readElement(r, &msg.Extended) +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFilterHeader) BtcEncode(w io.Writer, pver uint32) error { + err := writeElement(w, &msg.BlockHash) + if err != nil { + return err + } + return writeElement(w, &msg.Extended) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCFilterHeader) Command() string { + return CmdGetCFilterHeader +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCFilterHeader) MaxPayloadLength(pver uint32) uint32 { + // Protocol version 4 bytes + block hash + Extended flag. + return 4 + chainhash.HashSize + 1 +} + +// NewMsgGetCFilterHeader returns a new bitcoin getcfilterheader message that +// conforms to the Message interface using the passed parameters and defaults +// for the remaining fields. +func NewMsgGetCFilterHeader(blockHash *chainhash.Hash, extended bool) *MsgGetCFilterHeader { + return &MsgGetCFilterHeader{ + ProtocolVersion: ProtocolVersion, + BlockHash: *blockHash, + Extended: extended, + } +} From 9780ef5997b3294723ef31fc8b456adf81147da8 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 2 Feb 2017 10:44:22 -0700 Subject: [PATCH 0102/1056] Skip TxIn on coinbase transaction when indexing --- blockchain/indexers/cfindex.go | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 104aaec3be..d9beb6371f 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -160,9 +160,12 @@ func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { if err != nil { return nil, err } - for _, tx := range block.Transactions() { - for _, txIn := range tx.MsgTx().TxIn { - b.AddOutPoint(txIn.PreviousOutPoint) + for i, tx := range block.Transactions() { + // Skip the inputs for the coinbase transaction + if i != 0 { + for _, txIn := range tx.MsgTx().TxIn { + b.AddOutPoint(txIn.PreviousOutPoint) + } } for _, txOut := range tx.MsgTx().TxOut { b.AddScript(txOut.PkScript) @@ -183,10 +186,13 @@ func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { if err != nil { return nil, err } - for _, tx := range block.Transactions() { + for i, tx := range block.Transactions() { b.AddHash(tx.Hash()) - for _, txIn := range tx.MsgTx().TxIn { - b.AddScript(txIn.SignatureScript) + // Skip the inputs for the coinbase transaction + if i != 0 { + for _, txIn := range tx.MsgTx().TxIn { + b.AddScript(txIn.SignatureScript) + } } } f, err := b.Build() From b5de49aa736dec8b0c87fcd2641dc5b928bda828 Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 9 Feb 2017 13:54:30 +0000 Subject: [PATCH 0103/1056] define MsgCFilter.Deserialize(), required by btcrpcclient --- wire/msgcfilter.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index ad12cc909a..bd600036d9 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -39,6 +39,22 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32) error { return WriteVarBytes(w, pver, msg.Data) } +// Deserialize decodes a filter from r into the receiver using a format that is +// suitable for long-term storage such as a database. This function differs +// from BtcDecode in that BtcDecode decodes from the bitcoin wire protocol as +// it was sent across the network. The wire encoding can technically differ +// depending on the protocol version and doesn't even really need to match the +// format of a stored filter at all. As of the time this comment was written, +// the encoded filter is the same in both instances, but there is a distinct +// difference and separating the two allows the API to be flexible enough to +// deal with changes. +func (msg *MsgCFilter) Deserialize(r io.Reader) error { + // At the current time, there is no difference between the wire encoding + // and the stable long-term storage format. As a result, make use of + // BtcDecode. + return msg.BtcDecode(r, 0) +} + // Command returns the protocol command string for the message. This is part // of the Message interface implementation. func (msg *MsgCFilter) Command() string { From 0c08ba2786f25080637a4aba98af773ccff913ba Mon Sep 17 00:00:00 2001 From: pedro martelletto Date: Thu, 9 Feb 2017 13:57:36 +0000 Subject: [PATCH 0104/1056] define MsgCFilterHeader.Deserialize(), required by btcrpcclient --- wire/msgcfilterheader.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/wire/msgcfilterheader.go b/wire/msgcfilterheader.go index ce8d102a5f..ca4908e930 100644 --- a/wire/msgcfilterheader.go +++ b/wire/msgcfilterheader.go @@ -41,6 +41,22 @@ func (msg *MsgCFilterHeader) BtcEncode(w io.Writer, pver uint32) error { return WriteVarBytes(w, pver, msg.Data) } +// Deserialize decodes a filter header from r into the receiver using a format +// that is suitable for long-term storage such as a database. This function +// differs from BtcDecode in that BtcDecode decodes from the bitcoin wire +// protocol as it was sent across the network. The wire encoding can +// technically differ depending on the protocol version and doesn't even really +// need to match the format of a stored filter header at all. As of the time +// this comment was written, the encoded filter header is the same in both +// instances, but there is a distinct difference and separating the two allows +// the API to be flexible enough to deal with changes. +func (msg *MsgCFilterHeader) Deserialize(r io.Reader) error { + // At the current time, there is no difference between the wire encoding + // and the stable long-term storage format. As a result, make use of + // BtcDecode. + return msg.BtcDecode(r, 0) +} + // Command returns the protocol command string for the message. This is part // of the Message interface implementation. func (msg *MsgCFilterHeader) Command() string { From ba7b5f330851d48fe29fa273ba0520d43ef00415 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 21 Feb 2017 19:28:17 -0700 Subject: [PATCH 0105/1056] Use NBytes() instead of Bytes() in CFIndex --- blockchain/indexers/cfindex.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index d9beb6371f..bf533a3ab5 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -175,7 +175,7 @@ func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { if err != nil { return nil, err } - return f.Bytes(), nil + return f.NBytes(), nil } // makeExtendedFilterForBlock builds a block's extended filter, which consists @@ -199,7 +199,7 @@ func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { if err != nil { return nil, err } - return f.Bytes(), nil + return f.NBytes(), nil } // makeHeaderForFilter implements the chaining logic between filters, where From 8ad7aa5d5d6f3b9d8067fa0ba7834f45e90a72be Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 22 Feb 2017 19:30:53 -0700 Subject: [PATCH 0106/1056] Rename CFilterHeader to CFHeader on P2P side; fix some bugs/tests --- peer/peer.go | 29 +++++++-- peer/peer_test.go | 22 +++++-- server.go | 45 +++++++------- wire/message.go | 62 ++++++++++---------- wire/message_test.go | 8 +++ wire/{msgcfilterheader.go => msgcfheader.go} | 44 +++++++------- wire/msggetcfheader.go | 57 ++++++++++++++++++ wire/msggetcfilter.go | 16 +++-- wire/msggetcfilterheader.go | 59 ------------------- 9 files changed, 189 insertions(+), 153 deletions(-) rename wire/{msgcfilterheader.go => msgcfheader.go} (62%) create mode 100644 wire/msggetcfheader.go delete mode 100644 wire/msggetcfilterheader.go diff --git a/peer/peer.go b/peer/peer.go index 488f3bcc74..858e2fc6cf 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -123,6 +123,13 @@ type MessageListeners struct { // OnBlock is invoked when a peer receives a block bitcoin message. OnBlock func(p *Peer, msg *wire.MsgBlock, buf []byte) + // OnCFilter is invoked when a peer receives a cfilter bitcoin message. + OnCFilter func(p *Peer, msg *wire.MsgCFilter) + + // OnCFHeader is invoked when a peer receives a cfheader bitcoin + // message. + OnCFHeader func(p *Peer, msg *wire.MsgCFHeader) + // OnInv is invoked when a peer receives an inv bitcoin message. OnInv func(p *Peer, msg *wire.MsgInv) @@ -148,9 +155,9 @@ type MessageListeners struct { // message. OnGetCFilter func(p *Peer, msg *wire.MsgGetCFilter) - // OnGetCFilterHeader is invoked when a peer receives a - // getcfilterheader bitcoin message. - OnGetCFilterHeader func(p *Peer, msg *wire.MsgGetCFilterHeader) + // OnGetCFHeader is invoked when a peer receives a getcfheader + // bitcoin message. + OnGetCFHeader func(p *Peer, msg *wire.MsgGetCFHeader) // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1592,9 +1599,19 @@ out: p.cfg.Listeners.OnGetCFilter(p, msg) } - case *wire.MsgGetCFilterHeader: - if p.cfg.Listeners.OnGetCFilterHeader != nil { - p.cfg.Listeners.OnGetCFilterHeader(p, msg) + case *wire.MsgGetCFHeader: + if p.cfg.Listeners.OnGetCFHeader != nil { + p.cfg.Listeners.OnGetCFHeader(p, msg) + } + + case *wire.MsgCFilter: + if p.cfg.Listeners.OnCFilter != nil { + p.cfg.Listeners.OnCFilter(p, msg) + } + + case *wire.MsgCFHeader: + if p.cfg.Listeners.OnCFHeader != nil { + p.cfg.Listeners.OnCFHeader(p, msg) } case *wire.MsgFeeFilter: diff --git a/peer/peer_test.go b/peer/peer_test.go index c913f79e75..04e7b7bdf8 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -402,7 +402,13 @@ func TestPeerListeners(t *testing.T) { OnGetCFilter: func(p *peer.Peer, msg *wire.MsgGetCFilter) { ok <- msg }, - OnGetCFilterHeader: func(p *peer.Peer, msg *wire.MsgGetCFilterHeader) { + OnGetCFHeader: func(p *peer.Peer, msg *wire.MsgGetCFHeader) { + ok <- msg + }, + OnCFilter: func(p *peer.Peer, msg *wire.MsgCFilter) { + ok <- msg + }, + OnCFHeader: func(p *peer.Peer, msg *wire.MsgCFHeader) { ok <- msg }, OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { @@ -530,11 +536,19 @@ func TestPeerListeners(t *testing.T) { }, { "OnGetCFilter", - wire.NewMsgGetCFilter(&chainhash.Hash{}), + wire.NewMsgGetCFilter(&chainhash.Hash{}, false), + }, + { + "OnGetCFHeader", + wire.NewMsgGetCFHeader(&chainhash.Hash{}, false), + }, + { + "OnCFilter", + wire.NewMsgCFilter([]byte("payload")), }, { - "OnGetCFilterHeader", - wire.NewMsgGetCFilterHeader(&chainhash.Hash{}), + "OnCFHeader", + wire.NewMsgCFHeader([]byte("payload")), }, { "OnFeeFilter", diff --git a/server.go b/server.go index 91b614cb97..c1880a9bcb 100644 --- a/server.go +++ b/server.go @@ -760,9 +760,8 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { sp.QueueMessage(filterMsg, nil) } -// OnGetCFilterHeader is invoked when a peer receives a getcfilterheader bitcoin -// message. -func (sp *serverPeer) OnGetCFilterHeader(_ *peer.Peer, msg *wire.MsgGetCFilterHeader) { +// OnGetCFHeader is invoked when a peer receives a getcfheader bitcoin message. +func (sp *serverPeer) OnGetCFHeader(_ *peer.Peer, msg *wire.MsgGetCFHeader) { // Ignore getcfilterheader requests if not in sync. if !sp.server.blockManager.IsCurrent() { return @@ -778,7 +777,7 @@ func (sp *serverPeer) OnGetCFilterHeader(_ *peer.Peer, msg *wire.MsgGetCFilterHe msg.BlockHash, err) } - headerMsg := wire.NewMsgCFilterHeader(headerBytes) + headerMsg := wire.NewMsgCFHeader(headerBytes) sp.QueueMessage(headerMsg, nil) } @@ -1620,25 +1619,25 @@ func disconnectPeer(peerList map[int32]*serverPeer, compareFunc func(*serverPeer func newPeerConfig(sp *serverPeer) *peer.Config { return &peer.Config{ Listeners: peer.MessageListeners{ - OnVersion: sp.OnVersion, - OnMemPool: sp.OnMemPool, - OnTx: sp.OnTx, - OnBlock: sp.OnBlock, - OnInv: sp.OnInv, - OnHeaders: sp.OnHeaders, - OnGetData: sp.OnGetData, - OnGetBlocks: sp.OnGetBlocks, - OnGetHeaders: sp.OnGetHeaders, - OnGetCFilter: sp.OnGetCFilter, - OnGetCFilterHeader: sp.OnGetCFilterHeader, - OnFeeFilter: sp.OnFeeFilter, - OnFilterAdd: sp.OnFilterAdd, - OnFilterClear: sp.OnFilterClear, - OnFilterLoad: sp.OnFilterLoad, - OnGetAddr: sp.OnGetAddr, - OnAddr: sp.OnAddr, - OnRead: sp.OnRead, - OnWrite: sp.OnWrite, + OnVersion: sp.OnVersion, + OnMemPool: sp.OnMemPool, + OnTx: sp.OnTx, + OnBlock: sp.OnBlock, + OnInv: sp.OnInv, + OnHeaders: sp.OnHeaders, + OnGetData: sp.OnGetData, + OnGetBlocks: sp.OnGetBlocks, + OnGetHeaders: sp.OnGetHeaders, + OnGetCFilter: sp.OnGetCFilter, + OnGetCFHeader: sp.OnGetCFHeader, + OnFeeFilter: sp.OnFeeFilter, + OnFilterAdd: sp.OnFilterAdd, + OnFilterClear: sp.OnFilterClear, + OnFilterLoad: sp.OnFilterLoad, + OnGetAddr: sp.OnGetAddr, + OnAddr: sp.OnAddr, + OnRead: sp.OnRead, + OnWrite: sp.OnWrite, // Note: The reference client currently bans peers that send alerts // not signed with its key. We could verify against their key, but diff --git a/wire/message.go b/wire/message.go index ade36386d5..377b967337 100644 --- a/wire/message.go +++ b/wire/message.go @@ -28,33 +28,33 @@ const MaxMessagePayload = (1024 * 1024 * 32) // 32MB // Commands used in bitcoin message headers which describe the type of message. const ( - CmdVersion = "version" - CmdVerAck = "verack" - CmdGetAddr = "getaddr" - CmdAddr = "addr" - CmdGetBlocks = "getblocks" - CmdInv = "inv" - CmdGetData = "getdata" - CmdNotFound = "notfound" - CmdBlock = "block" - CmdTx = "tx" - CmdGetHeaders = "getheaders" - CmdHeaders = "headers" - CmdPing = "ping" - CmdPong = "pong" - CmdAlert = "alert" - CmdMemPool = "mempool" - CmdFilterAdd = "filteradd" - CmdFilterClear = "filterclear" - CmdFilterLoad = "filterload" - CmdMerkleBlock = "merkleblock" - CmdReject = "reject" - CmdSendHeaders = "sendheaders" - CmdFeeFilter = "feefilter" - CmdGetCFilter = "getcfilter" - CmdGetCFilterHeader = "getcfilterheader" - CmdCFilter = "cfilter" - CmdCFilterHeader = "cfilterheader" + CmdVersion = "version" + CmdVerAck = "verack" + CmdGetAddr = "getaddr" + CmdAddr = "addr" + CmdGetBlocks = "getblocks" + CmdInv = "inv" + CmdGetData = "getdata" + CmdNotFound = "notfound" + CmdBlock = "block" + CmdTx = "tx" + CmdGetHeaders = "getheaders" + CmdHeaders = "headers" + CmdPing = "ping" + CmdPong = "pong" + CmdAlert = "alert" + CmdMemPool = "mempool" + CmdFilterAdd = "filteradd" + CmdFilterClear = "filterclear" + CmdFilterLoad = "filterload" + CmdMerkleBlock = "merkleblock" + CmdReject = "reject" + CmdSendHeaders = "sendheaders" + CmdFeeFilter = "feefilter" + CmdGetCFilter = "getcfilter" + CmdGetCFHeader = "getcfheader" + CmdCFilter = "cfilter" + CmdCFHeader = "cfheader" ) // MessageEncoding represents the wire message encoding format to be used. @@ -163,14 +163,14 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFilter: msg = &MsgGetCFilter{} - case CmdGetCFilterHeader: - msg = &MsgGetCFilterHeader{} + case CmdGetCFHeader: + msg = &MsgGetCFHeader{} case CmdCFilter: msg = &MsgCFilter{} - case CmdCFilterHeader: - msg = &MsgCFilterHeader{} + case CmdCFHeader: + msg = &MsgCFHeader{} default: return nil, fmt.Errorf("unhandled command [%s]", command) diff --git a/wire/message_test.go b/wire/message_test.go index 83005f4d1b..1aad5ef719 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -69,6 +69,10 @@ func TestMessage(t *testing.T) { bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0) msgMerkleBlock := NewMsgMerkleBlock(bh) msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") + msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, false) + msgGetCFHeader := NewMsgGetCFHeader(&chainhash.Hash{}, false) + msgCFilter := NewMsgCFilter([]byte("payload")) + msgCFHeader := NewMsgCFHeader([]byte("payload")) tests := []struct { in Message // Value to encode @@ -98,6 +102,10 @@ func TestMessage(t *testing.T) { {msgFilterLoad, msgFilterLoad, pver, MainNet, 35}, {msgMerkleBlock, msgMerkleBlock, pver, MainNet, 110}, {msgReject, msgReject, pver, MainNet, 79}, + {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, + {msgGetCFHeader, msgGetCFHeader, pver, MainNet, 57}, + {msgCFilter, msgCFilter, pver, MainNet, 32}, + {msgCFHeader, msgCFHeader, pver, MainNet, 32}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcfilterheader.go b/wire/msgcfheader.go similarity index 62% rename from wire/msgcfilterheader.go rename to wire/msgcfheader.go index ca4908e930..f6945544ef 100644 --- a/wire/msgcfilterheader.go +++ b/wire/msgcfheader.go @@ -6,36 +6,38 @@ package wire import ( "fmt" - "github.com/btcsuite/fastsha256" "io" + + "github.com/btcsuite/fastsha256" ) const ( - // MaxCFilterHeaderDataSize is the maximum byte size of a committed + // MaxCFHeaderDataSize is the maximum byte size of a committed // filter header. - MaxCFilterHeaderDataSize = fastsha256.Size + MaxCFHeaderDataSize = fastsha256.Size ) -type MsgCFilterHeader struct { + +type MsgCFHeader struct { Data []byte } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. -func (msg *MsgCFilterHeader) BtcDecode(r io.Reader, pver uint32) error { +func (msg *MsgCFHeader) BtcDecode(r io.Reader, pver uint32) error { var err error - msg.Data, err = ReadVarBytes(r, pver, MaxCFilterHeaderDataSize, + msg.Data, err = ReadVarBytes(r, pver, MaxCFHeaderDataSize, "cf header data") return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. -func (msg *MsgCFilterHeader) BtcEncode(w io.Writer, pver uint32) error { +func (msg *MsgCFHeader) BtcEncode(w io.Writer, pver uint32) error { size := len(msg.Data) - if size > MaxCFilterHeaderDataSize { - str := fmt.Sprintf("cf header size too large for message " + - "[size %v, max %v]", size, MaxCFilterHeaderDataSize) - return messageError("MsgCFilterHeader.BtcEncode", str) + if size > MaxCFHeaderDataSize { + str := fmt.Sprintf("cf header size too large for message "+ + "[size %v, max %v]", size, MaxCFHeaderDataSize) + return messageError("MsgCFHeader.BtcEncode", str) } return WriteVarBytes(w, pver, msg.Data) @@ -50,7 +52,7 @@ func (msg *MsgCFilterHeader) BtcEncode(w io.Writer, pver uint32) error { // this comment was written, the encoded filter header is the same in both // instances, but there is a distinct difference and separating the two allows // the API to be flexible enough to deal with changes. -func (msg *MsgCFilterHeader) Deserialize(r io.Reader) error { +func (msg *MsgCFHeader) Deserialize(r io.Reader) error { // At the current time, there is no difference between the wire encoding // and the stable long-term storage format. As a result, make use of // BtcDecode. @@ -59,21 +61,21 @@ func (msg *MsgCFilterHeader) Deserialize(r io.Reader) error { // Command returns the protocol command string for the message. This is part // of the Message interface implementation. -func (msg *MsgCFilterHeader) Command() string { - return CmdCFilterHeader +func (msg *MsgCFHeader) Command() string { + return CmdCFHeader } // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. -func (msg *MsgCFilterHeader) MaxPayloadLength(pver uint32) uint32 { - return uint32(VarIntSerializeSize(MaxCFilterHeaderDataSize)) + - MaxCFilterHeaderDataSize +func (msg *MsgCFHeader) MaxPayloadLength(pver uint32) uint32 { + return uint32(VarIntSerializeSize(MaxCFHeaderDataSize)) + + MaxCFHeaderDataSize } -// NewMsgFilterAdd returns a new bitcoin cfilterheader message that conforms to -// the Message interface. See MsgCFilterHeader for details. -func NewMsgCFilterHeader(data []byte) *MsgCFilterHeader { - return &MsgCFilterHeader{ +// NewMsgCFHeader returns a new bitcoin cfheader message that conforms to +// the Message interface. See MsgCFHeader for details. +func NewMsgCFHeader(data []byte) *MsgCFHeader { + return &MsgCFHeader{ Data: data, } } diff --git a/wire/msggetcfheader.go b/wire/msggetcfheader.go new file mode 100644 index 0000000000..0295ca8d27 --- /dev/null +++ b/wire/msggetcfheader.go @@ -0,0 +1,57 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +type MsgGetCFHeader struct { + BlockHash chainhash.Hash + Extended bool +} + +func (msg *MsgGetCFHeader) BtcDecode(r io.Reader, pver uint32) error { + err := readElement(r, &msg.BlockHash) + if err != nil { + return err + } + return readElement(r, &msg.Extended) +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFHeader) BtcEncode(w io.Writer, pver uint32) error { + err := writeElement(w, &msg.BlockHash) + if err != nil { + return err + } + return writeElement(w, msg.Extended) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCFHeader) Command() string { + return CmdGetCFHeader +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCFHeader) MaxPayloadLength(pver uint32) uint32 { + // Block hash + Extended flag. + return chainhash.HashSize + 1 +} + +// NewMsgGetCFHeader returns a new bitcoin getcfheader message that conforms to +// the Message interface using the passed parameters and defaults for the +// remaining fields. +func NewMsgGetCFHeader(blockHash *chainhash.Hash, extended bool) *MsgGetCFHeader { + return &MsgGetCFHeader{ + BlockHash: *blockHash, + Extended: extended, + } +} diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index 2b775103c0..f3ae5c9117 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -11,9 +11,8 @@ import ( ) type MsgGetCFilter struct { - ProtocolVersion uint32 - BlockHash chainhash.Hash - Extended bool + BlockHash chainhash.Hash + Extended bool } func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error { @@ -31,7 +30,7 @@ func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32) error { if err != nil { return err } - return writeElement(w, &msg.Extended) + return writeElement(w, msg.Extended) } // Command returns the protocol command string for the message. This is part @@ -43,8 +42,8 @@ func (msg *MsgGetCFilter) Command() string { // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { - // Protocol version 4 bytes + block hash + Extended flag. - return 4 + chainhash.HashSize + 1 + // Block hash + Extended flag. + return chainhash.HashSize + 1 } // NewMsgGetCFilter returns a new bitcoin getcfilter message that conforms to @@ -52,8 +51,7 @@ func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { // remaining fields. func NewMsgGetCFilter(blockHash *chainhash.Hash, extended bool) *MsgGetCFilter { return &MsgGetCFilter{ - ProtocolVersion: ProtocolVersion, - BlockHash: *blockHash, - Extended: extended, + BlockHash: *blockHash, + Extended: extended, } } diff --git a/wire/msggetcfilterheader.go b/wire/msggetcfilterheader.go deleted file mode 100644 index d23e1d18af..0000000000 --- a/wire/msggetcfilterheader.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) 2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package wire - -import ( - "io" - - "github.com/btcsuite/btcd/chaincfg/chainhash" -) - -type MsgGetCFilterHeader struct { - ProtocolVersion uint32 - BlockHash chainhash.Hash - Extended bool -} - -func (msg *MsgGetCFilterHeader) BtcDecode(r io.Reader, pver uint32) error { - err := readElement(r, &msg.BlockHash) - if err != nil { - return err - } - return readElement(r, &msg.Extended) -} - -// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. -// This is part of the Message interface implementation. -func (msg *MsgGetCFilterHeader) BtcEncode(w io.Writer, pver uint32) error { - err := writeElement(w, &msg.BlockHash) - if err != nil { - return err - } - return writeElement(w, &msg.Extended) -} - -// Command returns the protocol command string for the message. This is part -// of the Message interface implementation. -func (msg *MsgGetCFilterHeader) Command() string { - return CmdGetCFilterHeader -} - -// MaxPayloadLength returns the maximum length the payload can be for the -// receiver. This is part of the Message interface implementation. -func (msg *MsgGetCFilterHeader) MaxPayloadLength(pver uint32) uint32 { - // Protocol version 4 bytes + block hash + Extended flag. - return 4 + chainhash.HashSize + 1 -} - -// NewMsgGetCFilterHeader returns a new bitcoin getcfilterheader message that -// conforms to the Message interface using the passed parameters and defaults -// for the remaining fields. -func NewMsgGetCFilterHeader(blockHash *chainhash.Hash, extended bool) *MsgGetCFilterHeader { - return &MsgGetCFilterHeader{ - ProtocolVersion: ProtocolVersion, - BlockHash: *blockHash, - Extended: extended, - } -} From 860100019fc800cc3e73503170836b136a2bdedb Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 2 Mar 2017 03:20:54 -0700 Subject: [PATCH 0107/1056] blockchain: fix --dropcfindex --- blockchain/indexers/cfindex.go | 44 +++++++-------- blockchain/indexers/manager.go | 99 +++++++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 50 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index bf533a3ab5..3072445df9 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -25,6 +25,9 @@ const ( // generated and dropped in pairs, and both are indexed by a block's hash. // Besides holding different content, they also live in different buckets. var ( + // cfIndexParentBucketKey is the name of the parent bucket used to house + // the index. The rest of the buckets live below this bucket. + cfIndexParentBucketKey = []byte("cfindexparentbucket") // cfBasicIndexKey is the name of the db bucket used to house the // block hash -> basic cf index (cf#0). cfBasicIndexKey = []byte("cf0byhashidx") @@ -42,14 +45,14 @@ var ( // dbFetchFilter retrieves a block's basic or extended filter. A filter's // absence is not considered an error. func dbFetchFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { - idx := dbTx.Metadata().Bucket(key) + idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Get(h[:]), nil } // dbFetchFilterHeader retrieves a block's basic or extended filter header. // A filter's absence is not considered an error. func dbFetchFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { - idx := dbTx.Metadata().Bucket(key) + idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) fh := idx.Get(h[:]) if len(fh) != fastsha256.Size { return nil, errors.New("invalid filter header length") @@ -59,7 +62,7 @@ func dbFetchFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byt // dbStoreFilter stores a block's basic or extended filter. func dbStoreFilter(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error { - idx := dbTx.Metadata().Bucket(key) + idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Put(h[:], f) } @@ -68,19 +71,19 @@ func dbStoreFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash, fh []b if len(fh) != fastsha256.Size { return errors.New("invalid filter header length") } - idx := dbTx.Metadata().Bucket(key) + idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Put(h[:], fh) } // dbDeleteFilter deletes a filter's basic or extended filter. func dbDeleteFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) error { - idx := dbTx.Metadata().Bucket(key) + idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Delete(h[:]) } // dbDeleteFilterHeader deletes a filter's basic or extended filter header. func dbDeleteFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) error { - idx := dbTx.Metadata().Bucket(key) + idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Delete(h[:]) } @@ -102,7 +105,7 @@ func (idx *CfIndex) Init() error { // Key returns the database key to use for the index as a byte slice. This is // part of the Indexer interface. func (idx *CfIndex) Key() []byte { - return cfBasicIndexKey + return cfIndexParentBucketKey } // Name returns the human-readable name of the index. This is part of the @@ -116,19 +119,23 @@ func (idx *CfIndex) Name() string { // indexes (simple, extended). func (idx *CfIndex) Create(dbTx database.Tx) error { meta := dbTx.Metadata() - _, err := meta.CreateBucket(cfBasicIndexKey) + cfIndexParentBucket, err := meta.CreateBucket(cfIndexParentBucketKey) if err != nil { return err } - _, err = meta.CreateBucket(cfBasicHeaderKey) + _, err = cfIndexParentBucket.CreateBucket(cfBasicIndexKey) if err != nil { return err } - _, err = meta.CreateBucket(cfExtendedIndexKey) + _, err = cfIndexParentBucket.CreateBucket(cfBasicHeaderKey) if err != nil { return err } - _, err = meta.CreateBucket(cfExtendedHeaderKey) + _, err = cfIndexParentBucket.CreateBucket(cfExtendedIndexKey) + if err != nil { + return err + } + _, err = cfIndexParentBucket.CreateBucket(cfExtendedHeaderKey) if err != nil { return err } @@ -317,18 +324,5 @@ func NewCfIndex(db database.DB, chainParams *chaincfg.Params) *CfIndex { // DropCfIndex drops the CF index from the provided database if exists. func DropCfIndex(db database.DB) error { - err := dropIndex(db, cfBasicIndexKey, cfIndexName) - if err != nil { - return err - } - err = dropIndex(db, cfBasicHeaderKey, cfIndexName) - if err != nil { - return err - } - err = dropIndex(db, cfExtendedIndexKey, cfIndexName) - if err != nil { - return err - } - err = dropIndex(db, cfExtendedHeaderKey, cfIndexName) - return err + return dropIndex(db, cfIndexParentBucketKey, cfIndexName) } diff --git a/blockchain/indexers/manager.go b/blockchain/indexers/manager.go index cc996dd875..a7d2af203c 100644 --- a/blockchain/indexers/manager.go +++ b/blockchain/indexers/manager.go @@ -609,37 +609,90 @@ func dropIndex(db database.DB, idxKey []byte, idxName string, interrupt <-chan s // the bucket in a single database transaction would result in massive // memory usage and likely crash many systems due to ulimits. In order // to avoid this, use a cursor to delete a maximum number of entries out - // of the bucket at a time. + // of the bucket at a time. Recurse buckets depth-first to delete any + // sub-buckets. const maxDeletions = 2000000 var totalDeleted uint64 - for numDeleted := maxDeletions; numDeleted == maxDeletions; { - numDeleted = 0 - err := db.Update(func(dbTx database.Tx) error { - bucket := dbTx.Metadata().Bucket(idxKey) - cursor := bucket.Cursor() - for ok := cursor.First(); ok; ok = cursor.Next() && - numDeleted < maxDeletions { - - if err := cursor.Delete(); err != nil { - return err + + // Recurse through all buckets in the index, cataloging each for + // later deletion. + var subBuckets [][][]byte + var subBucketClosure func(database.Tx, []byte, [][]byte) error + subBucketClosure = func(dbTx database.Tx, + subBucket []byte, tlBucket [][]byte) error { + // Get full bucket name and append to subBuckets for later + // deletion. + var bucketName [][]byte + if (tlBucket == nil) || (len(tlBucket) == 0) { + bucketName = append(bucketName, subBucket) + } else { + bucketName = append(tlBucket, subBucket) + } + subBuckets = append(subBuckets, bucketName) + // Recurse sub-buckets to append to subBuckets slice. + bucket := dbTx.Metadata() + for _, subBucketName := range bucketName { + bucket = bucket.Bucket(subBucketName) + } + return bucket.ForEachBucket(func(k []byte) error { + return subBucketClosure(dbTx, k, bucketName) + }) + } + + // Call subBucketClosure with top-level bucket. + err = db.View(func(dbTx database.Tx) error { + return subBucketClosure(dbTx, idxKey, nil) + }) + if err != nil { + return nil + } + + // Iterate through each sub-bucket in reverse, deepest-first, deleting + // all keys inside them and then dropping the buckets themselves. + for i := range subBuckets { + bucketName := subBuckets[len(subBuckets)-1-i] + // Delete maxDeletions key/value pairs at a time. + for numDeleted := maxDeletions; numDeleted == maxDeletions; { + numDeleted = 0 + err := db.Update(func(dbTx database.Tx) error { + subBucket := dbTx.Metadata() + for _, subBucketName := range bucketName { + subBucket = subBucket.Bucket(subBucketName) + } + cursor := subBucket.Cursor() + for ok := cursor.First(); ok; ok = cursor.Next() && + numDeleted < maxDeletions { + + if err := cursor.Delete(); err != nil { + return err + } + numDeleted++ } - numDeleted++ + return nil + }) + if err != nil { + return err } - return nil - }) - if err != nil { - return err - } - if numDeleted > 0 { - totalDeleted += uint64(numDeleted) - log.Infof("Deleted %d keys (%d total) from %s", - numDeleted, totalDeleted, idxName) + if numDeleted > 0 { + totalDeleted += uint64(numDeleted) + log.Infof("Deleted %d keys (%d total) from %s", + numDeleted, totalDeleted, idxName) + } } if interruptRequested(interrupt) { return errInterruptRequested } + + // Drop the bucket itself. + err = db.Update(func(dbTx database.Tx) error { + bucket := dbTx.Metadata() + for j := 0; j < len(bucketName)-1; j++ { + bucket = bucket.Bucket(bucketName[j]) + } + return bucket.DeleteBucket(bucketName[len(bucketName)-1]) + }) } // Call extra index specific deinitialization for the transaction index. @@ -658,10 +711,6 @@ func dropIndex(db database.DB, idxKey []byte, idxName string, interrupt <-chan s return err } - if err := meta.DeleteBucket(idxKey); err != nil { - return err - } - return indexesBucket.Delete(indexDropKey(idxKey)) }) if err != nil { From 29b5ece1962fe2019dbbb95c72ae741bdb58a93d Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 8 Mar 2017 16:14:39 -0800 Subject: [PATCH 0108/1056] Changed getcfheaders/cfheaders messages to get multiple headers. --- peer/peer.go | 20 +++--- peer/peer_test.go | 12 ++-- server.go | 144 +++++++++++++++++++++++++++++++--------- wire/message.go | 62 ++++++++--------- wire/message_test.go | 8 +-- wire/msgcfheader.go | 81 ---------------------- wire/msgcfheaders.go | 139 ++++++++++++++++++++++++++++++++++++++ wire/msggetcfheader.go | 57 ---------------- wire/msggetcfheaders.go | 135 +++++++++++++++++++++++++++++++++++++ 9 files changed, 439 insertions(+), 219 deletions(-) delete mode 100644 wire/msgcfheader.go create mode 100644 wire/msgcfheaders.go delete mode 100644 wire/msggetcfheader.go create mode 100644 wire/msggetcfheaders.go diff --git a/peer/peer.go b/peer/peer.go index 858e2fc6cf..0a3765d7d0 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -126,9 +126,9 @@ type MessageListeners struct { // OnCFilter is invoked when a peer receives a cfilter bitcoin message. OnCFilter func(p *Peer, msg *wire.MsgCFilter) - // OnCFHeader is invoked when a peer receives a cfheader bitcoin + // OnCFHeaders is invoked when a peer receives a cfheader bitcoin // message. - OnCFHeader func(p *Peer, msg *wire.MsgCFHeader) + OnCFHeaders func(p *Peer, msg *wire.MsgCFHeaders) // OnInv is invoked when a peer receives an inv bitcoin message. OnInv func(p *Peer, msg *wire.MsgInv) @@ -155,9 +155,9 @@ type MessageListeners struct { // message. OnGetCFilter func(p *Peer, msg *wire.MsgGetCFilter) - // OnGetCFHeader is invoked when a peer receives a getcfheader + // OnGetCFHeaders is invoked when a peer receives a getcfheader // bitcoin message. - OnGetCFHeader func(p *Peer, msg *wire.MsgGetCFHeader) + OnGetCFHeaders func(p *Peer, msg *wire.MsgGetCFHeaders) // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1599,9 +1599,9 @@ out: p.cfg.Listeners.OnGetCFilter(p, msg) } - case *wire.MsgGetCFHeader: - if p.cfg.Listeners.OnGetCFHeader != nil { - p.cfg.Listeners.OnGetCFHeader(p, msg) + case *wire.MsgGetCFHeaders: + if p.cfg.Listeners.OnGetCFHeaders != nil { + p.cfg.Listeners.OnGetCFHeaders(p, msg) } case *wire.MsgCFilter: @@ -1609,9 +1609,9 @@ out: p.cfg.Listeners.OnCFilter(p, msg) } - case *wire.MsgCFHeader: - if p.cfg.Listeners.OnCFHeader != nil { - p.cfg.Listeners.OnCFHeader(p, msg) + case *wire.MsgCFHeaders: + if p.cfg.Listeners.OnCFHeaders != nil { + p.cfg.Listeners.OnCFHeaders(p, msg) } case *wire.MsgFeeFilter: diff --git a/peer/peer_test.go b/peer/peer_test.go index 04e7b7bdf8..8f80dfb7af 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -402,13 +402,13 @@ func TestPeerListeners(t *testing.T) { OnGetCFilter: func(p *peer.Peer, msg *wire.MsgGetCFilter) { ok <- msg }, - OnGetCFHeader: func(p *peer.Peer, msg *wire.MsgGetCFHeader) { + OnGetCFHeaders: func(p *peer.Peer, msg *wire.MsgGetCFHeaders) { ok <- msg }, OnCFilter: func(p *peer.Peer, msg *wire.MsgCFilter) { ok <- msg }, - OnCFHeader: func(p *peer.Peer, msg *wire.MsgCFHeader) { + OnCFHeaders: func(p *peer.Peer, msg *wire.MsgCFHeaders) { ok <- msg }, OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { @@ -539,16 +539,16 @@ func TestPeerListeners(t *testing.T) { wire.NewMsgGetCFilter(&chainhash.Hash{}, false), }, { - "OnGetCFHeader", - wire.NewMsgGetCFHeader(&chainhash.Hash{}, false), + "OnGetCFHeaders", + wire.NewMsgGetCFHeaders(), }, { "OnCFilter", wire.NewMsgCFilter([]byte("payload")), }, { - "OnCFHeader", - wire.NewMsgCFHeader([]byte("payload")), + "OnCFHeaders", + wire.NewMsgCFHeaders(), }, { "OnFeeFilter", diff --git a/server.go b/server.go index c1880a9bcb..ee6c213aa3 100644 --- a/server.go +++ b/server.go @@ -760,25 +760,109 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { sp.QueueMessage(filterMsg, nil) } -// OnGetCFHeader is invoked when a peer receives a getcfheader bitcoin message. -func (sp *serverPeer) OnGetCFHeader(_ *peer.Peer, msg *wire.MsgGetCFHeader) { +// OnGetCFHeaders is invoked when a peer receives a getcfheader bitcoin message. +func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { // Ignore getcfilterheader requests if not in sync. if !sp.server.blockManager.IsCurrent() { return } - headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( - &msg.BlockHash, msg.Extended) + // Attempt to look up the height of the provided stop hash. + chain := sp.server.blockManager.chain + endIdx := int32(math.MaxInt32) + height, err := chain.BlockHeightByHash(&msg.HashStop) + if err == nil { + endIdx = height + 1 + } - if len(headerBytes) > 0 { - peerLog.Infof("Obtained CF header for %v", msg.BlockHash) - } else { - peerLog.Infof("Could not obtain CF header for %v: %v", - msg.BlockHash, err) + // There are no block locators so a specific header is being requested + // as identified by the stop hash. + if len(msg.BlockLocatorHashes) == 0 { + // No blocks with the stop hash were found so there is nothing + // to do. Just return. This behavior mirrors the reference + // implementation. + if endIdx == math.MaxInt32 { + return + } + + // Fetch the raw committed filter header bytes from the + // database. + headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( + &msg.HashStop, msg.Extended) + if (err != nil) || (len(headerBytes) == 0) { + peerLog.Warnf("Could not obtain CF header for %v: %v", + msg.HashStop, err) + return + } + + // Deserialize the hash. + var header chainhash.Hash + err = header.SetBytes(headerBytes) + if err != nil { + peerLog.Warnf("Committed filter header deserialize "+ + "failed: %v", err) + return + } + + headersMsg := wire.NewMsgCFHeaders() + headersMsg.AddCFHeader(&header) + sp.QueueMessage(headersMsg, nil) + return + } + + // Find the most recent known block based on the block locator. + // Use the block after the genesis block if no other blocks in the + // provided locator are known. This does mean the client will start + // over with the genesis block if unknown block locators are provided. + // This mirrors the behavior in the reference implementation. + startIdx := int32(1) + for _, hash := range msg.BlockLocatorHashes { + height, err := chain.BlockHeightByHash(hash) + if err == nil { + // Start with the next hash since we know this one. + startIdx = height + 1 + break + } + } + + // Don't attempt to fetch more than we can put into a single message. + if endIdx-startIdx > wire.MaxBlockHeadersPerMsg { + endIdx = startIdx + wire.MaxBlockHeadersPerMsg + } + + // Fetch the inventory from the block database. + hashList, err := chain.HeightRange(startIdx, endIdx) + if err != nil { + peerLog.Warnf("Header lookup failed: %v", err) + return + } + + // Generate cfheaders message and send it. + headersMsg := wire.NewMsgCFHeaders() + var header chainhash.Hash + for i := range hashList { + // Fetch the raw committed filter header bytes from the + // database. + headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( + &hashList[i], msg.Extended) + if (err != nil) || (len(headerBytes) == 0) { + peerLog.Warnf("Could not obtain CF header for %v: %v", + hashList[i], err) + return + } + + // Deserialize the hash. + err = header.SetBytes(headerBytes) + if err != nil { + peerLog.Warnf("Committed filter header deserialize "+ + "failed: %v", err) + return + } + + headersMsg.AddCFHeader(&header) } - headerMsg := wire.NewMsgCFHeader(headerBytes) - sp.QueueMessage(headerMsg, nil) + sp.QueueMessage(headersMsg, nil) } // enforceNodeBloomFlag disconnects the peer if the server is not configured to @@ -1619,25 +1703,25 @@ func disconnectPeer(peerList map[int32]*serverPeer, compareFunc func(*serverPeer func newPeerConfig(sp *serverPeer) *peer.Config { return &peer.Config{ Listeners: peer.MessageListeners{ - OnVersion: sp.OnVersion, - OnMemPool: sp.OnMemPool, - OnTx: sp.OnTx, - OnBlock: sp.OnBlock, - OnInv: sp.OnInv, - OnHeaders: sp.OnHeaders, - OnGetData: sp.OnGetData, - OnGetBlocks: sp.OnGetBlocks, - OnGetHeaders: sp.OnGetHeaders, - OnGetCFilter: sp.OnGetCFilter, - OnGetCFHeader: sp.OnGetCFHeader, - OnFeeFilter: sp.OnFeeFilter, - OnFilterAdd: sp.OnFilterAdd, - OnFilterClear: sp.OnFilterClear, - OnFilterLoad: sp.OnFilterLoad, - OnGetAddr: sp.OnGetAddr, - OnAddr: sp.OnAddr, - OnRead: sp.OnRead, - OnWrite: sp.OnWrite, + OnVersion: sp.OnVersion, + OnMemPool: sp.OnMemPool, + OnTx: sp.OnTx, + OnBlock: sp.OnBlock, + OnInv: sp.OnInv, + OnHeaders: sp.OnHeaders, + OnGetData: sp.OnGetData, + OnGetBlocks: sp.OnGetBlocks, + OnGetHeaders: sp.OnGetHeaders, + OnGetCFilter: sp.OnGetCFilter, + OnGetCFHeaders: sp.OnGetCFHeaders, + OnFeeFilter: sp.OnFeeFilter, + OnFilterAdd: sp.OnFilterAdd, + OnFilterClear: sp.OnFilterClear, + OnFilterLoad: sp.OnFilterLoad, + OnGetAddr: sp.OnGetAddr, + OnAddr: sp.OnAddr, + OnRead: sp.OnRead, + OnWrite: sp.OnWrite, // Note: The reference client currently bans peers that send alerts // not signed with its key. We could verify against their key, but diff --git a/wire/message.go b/wire/message.go index 377b967337..9a34a2fa54 100644 --- a/wire/message.go +++ b/wire/message.go @@ -28,33 +28,33 @@ const MaxMessagePayload = (1024 * 1024 * 32) // 32MB // Commands used in bitcoin message headers which describe the type of message. const ( - CmdVersion = "version" - CmdVerAck = "verack" - CmdGetAddr = "getaddr" - CmdAddr = "addr" - CmdGetBlocks = "getblocks" - CmdInv = "inv" - CmdGetData = "getdata" - CmdNotFound = "notfound" - CmdBlock = "block" - CmdTx = "tx" - CmdGetHeaders = "getheaders" - CmdHeaders = "headers" - CmdPing = "ping" - CmdPong = "pong" - CmdAlert = "alert" - CmdMemPool = "mempool" - CmdFilterAdd = "filteradd" - CmdFilterClear = "filterclear" - CmdFilterLoad = "filterload" - CmdMerkleBlock = "merkleblock" - CmdReject = "reject" - CmdSendHeaders = "sendheaders" - CmdFeeFilter = "feefilter" - CmdGetCFilter = "getcfilter" - CmdGetCFHeader = "getcfheader" - CmdCFilter = "cfilter" - CmdCFHeader = "cfheader" + CmdVersion = "version" + CmdVerAck = "verack" + CmdGetAddr = "getaddr" + CmdAddr = "addr" + CmdGetBlocks = "getblocks" + CmdInv = "inv" + CmdGetData = "getdata" + CmdNotFound = "notfound" + CmdBlock = "block" + CmdTx = "tx" + CmdGetHeaders = "getheaders" + CmdHeaders = "headers" + CmdPing = "ping" + CmdPong = "pong" + CmdAlert = "alert" + CmdMemPool = "mempool" + CmdFilterAdd = "filteradd" + CmdFilterClear = "filterclear" + CmdFilterLoad = "filterload" + CmdMerkleBlock = "merkleblock" + CmdReject = "reject" + CmdSendHeaders = "sendheaders" + CmdFeeFilter = "feefilter" + CmdGetCFilter = "getcfilter" + CmdGetCFHeaders = "getcfheaders" + CmdCFilter = "cfilter" + CmdCFHeaders = "cfheaders" ) // MessageEncoding represents the wire message encoding format to be used. @@ -163,14 +163,14 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFilter: msg = &MsgGetCFilter{} - case CmdGetCFHeader: - msg = &MsgGetCFHeader{} + case CmdGetCFHeaders: + msg = &MsgGetCFHeaders{} case CmdCFilter: msg = &MsgCFilter{} - case CmdCFHeader: - msg = &MsgCFHeader{} + case CmdCFHeaders: + msg = &MsgCFHeaders{} default: return nil, fmt.Errorf("unhandled command [%s]", command) diff --git a/wire/message_test.go b/wire/message_test.go index 1aad5ef719..2b5e41ef4b 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -70,9 +70,9 @@ func TestMessage(t *testing.T) { msgMerkleBlock := NewMsgMerkleBlock(bh) msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, false) - msgGetCFHeader := NewMsgGetCFHeader(&chainhash.Hash{}, false) + msgGetCFHeaders := NewMsgGetCFHeaders() msgCFilter := NewMsgCFilter([]byte("payload")) - msgCFHeader := NewMsgCFHeader([]byte("payload")) + msgCFHeaders := NewMsgCFHeaders() tests := []struct { in Message // Value to encode @@ -103,9 +103,9 @@ func TestMessage(t *testing.T) { {msgMerkleBlock, msgMerkleBlock, pver, MainNet, 110}, {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, - {msgGetCFHeader, msgGetCFHeader, pver, MainNet, 57}, + {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 62}, {msgCFilter, msgCFilter, pver, MainNet, 32}, - {msgCFHeader, msgCFHeader, pver, MainNet, 32}, + {msgCFHeaders, msgCFHeaders, pver, MainNet, 25}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcfheader.go b/wire/msgcfheader.go deleted file mode 100644 index f6945544ef..0000000000 --- a/wire/msgcfheader.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package wire - -import ( - "fmt" - "io" - - "github.com/btcsuite/fastsha256" -) - -const ( - // MaxCFHeaderDataSize is the maximum byte size of a committed - // filter header. - MaxCFHeaderDataSize = fastsha256.Size -) - -type MsgCFHeader struct { - Data []byte -} - -// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. -// This is part of the Message interface implementation. -func (msg *MsgCFHeader) BtcDecode(r io.Reader, pver uint32) error { - var err error - msg.Data, err = ReadVarBytes(r, pver, MaxCFHeaderDataSize, - "cf header data") - return err -} - -// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. -// This is part of the Message interface implementation. -func (msg *MsgCFHeader) BtcEncode(w io.Writer, pver uint32) error { - size := len(msg.Data) - if size > MaxCFHeaderDataSize { - str := fmt.Sprintf("cf header size too large for message "+ - "[size %v, max %v]", size, MaxCFHeaderDataSize) - return messageError("MsgCFHeader.BtcEncode", str) - } - - return WriteVarBytes(w, pver, msg.Data) -} - -// Deserialize decodes a filter header from r into the receiver using a format -// that is suitable for long-term storage such as a database. This function -// differs from BtcDecode in that BtcDecode decodes from the bitcoin wire -// protocol as it was sent across the network. The wire encoding can -// technically differ depending on the protocol version and doesn't even really -// need to match the format of a stored filter header at all. As of the time -// this comment was written, the encoded filter header is the same in both -// instances, but there is a distinct difference and separating the two allows -// the API to be flexible enough to deal with changes. -func (msg *MsgCFHeader) Deserialize(r io.Reader) error { - // At the current time, there is no difference between the wire encoding - // and the stable long-term storage format. As a result, make use of - // BtcDecode. - return msg.BtcDecode(r, 0) -} - -// Command returns the protocol command string for the message. This is part -// of the Message interface implementation. -func (msg *MsgCFHeader) Command() string { - return CmdCFHeader -} - -// MaxPayloadLength returns the maximum length the payload can be for the -// receiver. This is part of the Message interface implementation. -func (msg *MsgCFHeader) MaxPayloadLength(pver uint32) uint32 { - return uint32(VarIntSerializeSize(MaxCFHeaderDataSize)) + - MaxCFHeaderDataSize -} - -// NewMsgCFHeader returns a new bitcoin cfheader message that conforms to -// the Message interface. See MsgCFHeader for details. -func NewMsgCFHeader(data []byte) *MsgCFHeader { - return &MsgCFHeader{ - Data: data, - } -} diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go new file mode 100644 index 0000000000..b66d695fd6 --- /dev/null +++ b/wire/msgcfheaders.go @@ -0,0 +1,139 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "fmt" + "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +const ( + // MaxCFHeaderPayload is the maximum byte size of a committed + // filter header. + MaxCFHeaderPayload = chainhash.HashSize + + // MaxCFHeadersPerMsg is the maximum number of committed filter headers + // that can be in a single bitcoin cfheaders message. + MaxCFHeadersPerMsg = 2000 +) + +// MsgCFHeaders implements the Message interface and represents a bitcoin +// cfheaders message. It is used to deliver committed filter header information +// in response to a getcfheaders message (MsgGetCFHeaders). The maximum number +// of committed filter headers per message is currently 2000. See +// MsgGetCFHeaders for details on requesting the headers. +type MsgCFHeaders struct { + HeaderHashes []*chainhash.Hash +} + +// AddCFHeader adds a new committed filter header to the message. +func (msg *MsgCFHeaders) AddCFHeader(headerHash *chainhash.Hash) error { + if len(msg.HeaderHashes)+1 > MaxCFHeadersPerMsg { + str := fmt.Sprintf("too many block headers in message [max %v]", + MaxBlockHeadersPerMsg) + return messageError("MsgCFHeaders.AddCFHeader", str) + } + + msg.HeaderHashes = append(msg.HeaderHashes, headerHash) + return nil +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { + count, err := ReadVarInt(r, pver) + if err != nil { + return err + } + + // Limit to max committed filter headers per message. + if count > MaxCFHeadersPerMsg { + str := fmt.Sprintf("too many committed filter headers for "+ + "message [count %v, max %v]", count, + MaxBlockHeadersPerMsg) + return messageError("MsgCFHeaders.BtcDecode", str) + } + + // Create a contiguous slice of headers to deserialize into in order to + // reduce the number of allocations. + headers := make([]chainhash.Hash, count) + msg.HeaderHashes = make([]*chainhash.Hash, 0, count) + for i := uint64(0); i < count; i++ { + cfh := &headers[i] + err := readElement(r, &cfh) + if err != nil { + return err + } + msg.AddCFHeader(cfh) + } + + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32) error { + // Limit to max committed headers per message. + count := len(msg.HeaderHashes) + if count > MaxCFHeadersPerMsg { + str := fmt.Sprintf("too many committed filter headers for "+ + "message [count %v, max %v]", count, + MaxBlockHeadersPerMsg) + return messageError("MsgCFHeaders.BtcEncode", str) + } + + err := WriteVarInt(w, pver, uint64(count)) + if err != nil { + return err + } + + for _, cfh := range msg.HeaderHashes { + err := writeElement(w, cfh) + if err != nil { + return err + } + } + + return nil +} + +// Deserialize decodes a filter header from r into the receiver using a format +// that is suitable for long-term storage such as a database. This function +// differs from BtcDecode in that BtcDecode decodes from the bitcoin wire +// protocol as it was sent across the network. The wire encoding can +// technically differ depending on the protocol version and doesn't even really +// need to match the format of a stored filter header at all. As of the time +// this comment was written, the encoded filter header is the same in both +// instances, but there is a distinct difference and separating the two allows +// the API to be flexible enough to deal with changes. +func (msg *MsgCFHeaders) Deserialize(r io.Reader) error { + // At the current time, there is no difference between the wire encoding + // and the stable long-term storage format. As a result, make use of + // BtcDecode. + return msg.BtcDecode(r, 0) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgCFHeaders) Command() string { + return CmdCFHeaders +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgCFHeaders) MaxPayloadLength(pver uint32) uint32 { + // Num headers (varInt) + (header size * max allowed headers). + return MaxVarIntPayload + (MaxCFHeaderPayload * MaxBlockHeadersPerMsg) +} + +// NewMsgCFHeaders returns a new bitcoin cfheaders message that conforms to +// the Message interface. See MsgCFHeaders for details. +func NewMsgCFHeaders() *MsgCFHeaders { + return &MsgCFHeaders{ + HeaderHashes: make([]*chainhash.Hash, 0, MaxCFHeadersPerMsg), + } +} diff --git a/wire/msggetcfheader.go b/wire/msggetcfheader.go deleted file mode 100644 index 0295ca8d27..0000000000 --- a/wire/msggetcfheader.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package wire - -import ( - "io" - - "github.com/btcsuite/btcd/chaincfg/chainhash" -) - -type MsgGetCFHeader struct { - BlockHash chainhash.Hash - Extended bool -} - -func (msg *MsgGetCFHeader) BtcDecode(r io.Reader, pver uint32) error { - err := readElement(r, &msg.BlockHash) - if err != nil { - return err - } - return readElement(r, &msg.Extended) -} - -// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. -// This is part of the Message interface implementation. -func (msg *MsgGetCFHeader) BtcEncode(w io.Writer, pver uint32) error { - err := writeElement(w, &msg.BlockHash) - if err != nil { - return err - } - return writeElement(w, msg.Extended) -} - -// Command returns the protocol command string for the message. This is part -// of the Message interface implementation. -func (msg *MsgGetCFHeader) Command() string { - return CmdGetCFHeader -} - -// MaxPayloadLength returns the maximum length the payload can be for the -// receiver. This is part of the Message interface implementation. -func (msg *MsgGetCFHeader) MaxPayloadLength(pver uint32) uint32 { - // Block hash + Extended flag. - return chainhash.HashSize + 1 -} - -// NewMsgGetCFHeader returns a new bitcoin getcfheader message that conforms to -// the Message interface using the passed parameters and defaults for the -// remaining fields. -func NewMsgGetCFHeader(blockHash *chainhash.Hash, extended bool) *MsgGetCFHeader { - return &MsgGetCFHeader{ - BlockHash: *blockHash, - Extended: extended, - } -} diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go new file mode 100644 index 0000000000..e66331c100 --- /dev/null +++ b/wire/msggetcfheaders.go @@ -0,0 +1,135 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "fmt" + "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +// MsgGetCFHeaders is a message similar to MsgGetHeaders, but for committed +// filter headers. It allows to set the Extended field to get headers in the +// chain of basic (false) or extended (true) headers. +type MsgGetCFHeaders struct { + ProtocolVersion uint32 + BlockLocatorHashes []*chainhash.Hash + HashStop chainhash.Hash + Extended bool +} + +// AddBlockLocatorHash adds a new block locator hash to the message. +func (msg *MsgGetCFHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { + if len(msg.BlockLocatorHashes)+1 > MaxBlockLocatorsPerMsg { + str := fmt.Sprintf("too many block locator hashes for message [max %v]", + MaxBlockLocatorsPerMsg) + return messageError("MsgGetCFHeaders.AddBlockLocatorHash", str) + } + + msg.BlockLocatorHashes = append(msg.BlockLocatorHashes, hash) + return nil +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32) error { + err := readElement(r, &msg.ProtocolVersion) + if err != nil { + return err + } + + // Read num block locator hashes and limit to max. + count, err := ReadVarInt(r, pver) + if err != nil { + return err + } + if count > MaxBlockLocatorsPerMsg { + str := fmt.Sprintf("too many block locator hashes for message "+ + "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) + return messageError("MsgGetHeaders.BtcDecode", str) + } + + // Create a contiguous slice of hashes to deserialize into in order to + // reduce the number of allocations. + locatorHashes := make([]chainhash.Hash, count) + msg.BlockLocatorHashes = make([]*chainhash.Hash, 0, count) + for i := uint64(0); i < count; i++ { + hash := &locatorHashes[i] + err := readElement(r, hash) + if err != nil { + return err + } + msg.AddBlockLocatorHash(hash) + } + + err = readElement(r, &msg.HashStop) + if err != nil { + return err + } + + return readElement(r, &msg.Extended) +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32) error { + // Limit to max block locator hashes per message. + count := len(msg.BlockLocatorHashes) + if count > MaxBlockLocatorsPerMsg { + str := fmt.Sprintf("too many block locator hashes for message "+ + "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) + return messageError("MsgGetHeaders.BtcEncode", str) + } + + err := writeElement(w, msg.ProtocolVersion) + if err != nil { + return err + } + + err = WriteVarInt(w, pver, uint64(count)) + if err != nil { + return err + } + + for _, hash := range msg.BlockLocatorHashes { + err := writeElement(w, hash) + if err != nil { + return err + } + } + + err = writeElement(w, &msg.HashStop) + if err != nil { + return err + } + + return writeElement(w, msg.Extended) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCFHeaders) Command() string { + return CmdGetCFHeaders +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCFHeaders) MaxPayloadLength(pver uint32) uint32 { + // Version 4 bytes + num block locator hashes (varInt) + max allowed + // block locators + hash stop + Extended flag 1 byte. + return 4 + MaxVarIntPayload + (MaxBlockLocatorsPerMsg * + chainhash.HashSize) + chainhash.HashSize + 1 +} + +// NewMsgGetCFHeaders returns a new bitcoin getcfheader message that conforms to +// the Message interface using the passed parameters and defaults for the +// remaining fields. +func NewMsgGetCFHeaders() *MsgGetCFHeaders { + return &MsgGetCFHeaders{ + BlockLocatorHashes: make([]*chainhash.Hash, 0, + MaxBlockLocatorsPerMsg), + } +} From 71ccc9550263d11d24d0a6b37bc997801592f15a Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 8 Mar 2017 17:11:00 -0800 Subject: [PATCH 0109/1056] wire: Fix MsgCFHeaders.Decode() --- wire/msgcfheaders.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index b66d695fd6..411bf8f1a9 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -60,15 +60,14 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // Create a contiguous slice of headers to deserialize into in order to // reduce the number of allocations. - headers := make([]chainhash.Hash, count) + var cfh chainhash.Hash msg.HeaderHashes = make([]*chainhash.Hash, 0, count) for i := uint64(0); i < count; i++ { - cfh := &headers[i] err := readElement(r, &cfh) if err != nil { return err } - msg.AddCFHeader(cfh) + msg.AddCFHeader(&cfh) } return nil From ba4a2f77a5b747720ac6a633a880556a0f1cb97e Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 8 Mar 2017 17:32:52 -0800 Subject: [PATCH 0110/1056] wire/server: allocate hash once per loop to prevent overwriting --- server.go | 2 +- wire/msgcfheaders.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index ee6c213aa3..a237b31bcb 100644 --- a/server.go +++ b/server.go @@ -839,7 +839,6 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { // Generate cfheaders message and send it. headersMsg := wire.NewMsgCFHeaders() - var header chainhash.Hash for i := range hashList { // Fetch the raw committed filter header bytes from the // database. @@ -852,6 +851,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { } // Deserialize the hash. + var header chainhash.Hash err = header.SetBytes(headerBytes) if err != nil { peerLog.Warnf("Committed filter header deserialize "+ diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 411bf8f1a9..3b9266b10c 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -60,9 +60,9 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // Create a contiguous slice of headers to deserialize into in order to // reduce the number of allocations. - var cfh chainhash.Hash msg.HeaderHashes = make([]*chainhash.Hash, 0, count) for i := uint64(0); i < count; i++ { + var cfh chainhash.Hash err := readElement(r, &cfh) if err != nil { return err From 936caad9c2e97a0bea0058528b91e1e2a9d23c05 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 3 Apr 2017 19:05:39 -0600 Subject: [PATCH 0111/1056] Add last blockhash to cfheaders and blockhash to cfilter messages --- peer/peer_test.go | 2 +- server.go | 4 +++- wire/message_test.go | 6 +++--- wire/msgcfheaders.go | 20 +++++++++++++++++--- wire/msgcfilter.go | 25 ++++++++++++++++++------- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/peer/peer_test.go b/peer/peer_test.go index 8f80dfb7af..cddf7aa38e 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -544,7 +544,7 @@ func TestPeerListeners(t *testing.T) { }, { "OnCFilter", - wire.NewMsgCFilter([]byte("payload")), + wire.NewMsgCFilter(&chainhash.Hash{}, []byte("payload")), }, { "OnCFHeaders", diff --git a/server.go b/server.go index a237b31bcb..1827f2c844 100644 --- a/server.go +++ b/server.go @@ -756,7 +756,7 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { err) } - filterMsg := wire.NewMsgCFilter(filterBytes) + filterMsg := wire.NewMsgCFilter(&msg.BlockHash, filterBytes) sp.QueueMessage(filterMsg, nil) } @@ -806,6 +806,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { headersMsg := wire.NewMsgCFHeaders() headersMsg.AddCFHeader(&header) + headersMsg.StopHash = msg.HashStop sp.QueueMessage(headersMsg, nil) return } @@ -862,6 +863,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { headersMsg.AddCFHeader(&header) } + headersMsg.StopHash = hashList[len(hashList)-1] sp.QueueMessage(headersMsg, nil) } diff --git a/wire/message_test.go b/wire/message_test.go index 2b5e41ef4b..3a65770467 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -71,7 +71,7 @@ func TestMessage(t *testing.T) { msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, false) msgGetCFHeaders := NewMsgGetCFHeaders() - msgCFilter := NewMsgCFilter([]byte("payload")) + msgCFilter := NewMsgCFilter(&chainhash.Hash{}, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() tests := []struct { @@ -104,8 +104,8 @@ func TestMessage(t *testing.T) { {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 62}, - {msgCFilter, msgCFilter, pver, MainNet, 32}, - {msgCFHeaders, msgCFHeaders, pver, MainNet, 25}, + {msgCFilter, msgCFilter, pver, MainNet, 64}, + {msgCFHeaders, msgCFHeaders, pver, MainNet, 57}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 3b9266b10c..615fb3f5d6 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -27,6 +27,7 @@ const ( // of committed filter headers per message is currently 2000. See // MsgGetCFHeaders for details on requesting the headers. type MsgCFHeaders struct { + StopHash chainhash.Hash HeaderHashes []*chainhash.Hash } @@ -45,6 +46,12 @@ func (msg *MsgCFHeaders) AddCFHeader(headerHash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { + // Read stop hash + err := readElement(r, &msg.StopHash) + if err != nil { + return err + } + count, err := ReadVarInt(r, pver) if err != nil { return err @@ -76,6 +83,12 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32) error { + // Write stop hash + err := writeElement(w, msg.StopHash) + if err != nil { + return err + } + // Limit to max committed headers per message. count := len(msg.HeaderHashes) if count > MaxCFHeadersPerMsg { @@ -85,7 +98,7 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32) error { return messageError("MsgCFHeaders.BtcEncode", str) } - err := WriteVarInt(w, pver, uint64(count)) + err = WriteVarInt(w, pver, uint64(count)) if err != nil { return err } @@ -125,8 +138,9 @@ func (msg *MsgCFHeaders) Command() string { // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. func (msg *MsgCFHeaders) MaxPayloadLength(pver uint32) uint32 { - // Num headers (varInt) + (header size * max allowed headers). - return MaxVarIntPayload + (MaxCFHeaderPayload * MaxBlockHeadersPerMsg) + // Hash size + num headers (varInt) + (header size * max headers). + return chainhash.HashSize + MaxVarIntPayload + + (MaxCFHeaderPayload * MaxCFHeadersPerMsg) } // NewMsgCFHeaders returns a new bitcoin cfheaders message that conforms to diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index bd600036d9..a1d1b0fb70 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -7,22 +7,27 @@ package wire import ( "fmt" "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" ) const ( // MaxCFilterDataSize is the maximum byte size of a committed filter. - MaxCFilterDataSize = 65536 + MaxCFilterDataSize = 262144 ) + type MsgCFilter struct { - Data []byte + BlockHash chainhash.Hash + Data []byte } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32) error { var err error + err = readElement(r, &msg.BlockHash) msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize, - "cfilter data") + "cfilter data") return err } @@ -36,6 +41,11 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32) error { return messageError("MsgCFilter.BtcEncode", str) } + err := writeElement(w, msg.BlockHash) + if err != nil { + return err + } + return WriteVarBytes(w, pver, msg.Data) } @@ -65,13 +75,14 @@ func (msg *MsgCFilter) Command() string { // receiver. This is part of the Message interface implementation. func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 { return uint32(VarIntSerializeSize(MaxCFilterDataSize)) + - MaxCFilterDataSize + MaxCFilterDataSize } -// NewMsgFilterAdd returns a new bitcoin filteradd message that conforms to the +// NewMsgCFilter returns a new bitcoin cfilter message that conforms to the // Message interface. See MsgCFilter for details. -func NewMsgCFilter(data []byte) *MsgCFilter { +func NewMsgCFilter(blockHash *chainhash.Hash, data []byte) *MsgCFilter { return &MsgCFilter{ - Data: data, + BlockHash: *blockHash, + Data: data, } } From dabb8000fb190d3f384b844dcdc6abccdc5750d5 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 4 Apr 2017 14:50:27 -0600 Subject: [PATCH 0112/1056] Add Extended flag to cfilter and cfheaders messages --- peer/peer_test.go | 3 ++- server.go | 5 ++++- wire/message_test.go | 6 +++--- wire/msgcfheaders.go | 16 +++++++++++++++- wire/msgcfilter.go | 22 ++++++++++++++++++++-- 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/peer/peer_test.go b/peer/peer_test.go index cddf7aa38e..acab18bb88 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -544,7 +544,8 @@ func TestPeerListeners(t *testing.T) { }, { "OnCFilter", - wire.NewMsgCFilter(&chainhash.Hash{}, []byte("payload")), + wire.NewMsgCFilter(&chainhash.Hash{}, true, + []byte("payload")), }, { "OnCFHeaders", diff --git a/server.go b/server.go index 1827f2c844..ca3e6dd2f1 100644 --- a/server.go +++ b/server.go @@ -756,7 +756,8 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { err) } - filterMsg := wire.NewMsgCFilter(&msg.BlockHash, filterBytes) + filterMsg := wire.NewMsgCFilter(&msg.BlockHash, msg.Extended, + filterBytes) sp.QueueMessage(filterMsg, nil) } @@ -807,6 +808,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { headersMsg := wire.NewMsgCFHeaders() headersMsg.AddCFHeader(&header) headersMsg.StopHash = msg.HashStop + headersMsg.Extended = msg.Extended sp.QueueMessage(headersMsg, nil) return } @@ -863,6 +865,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { headersMsg.AddCFHeader(&header) } + headersMsg.Extended = msg.Extended headersMsg.StopHash = hashList[len(hashList)-1] sp.QueueMessage(headersMsg, nil) } diff --git a/wire/message_test.go b/wire/message_test.go index 3a65770467..88533f4d69 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -71,7 +71,7 @@ func TestMessage(t *testing.T) { msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, false) msgGetCFHeaders := NewMsgGetCFHeaders() - msgCFilter := NewMsgCFilter(&chainhash.Hash{}, []byte("payload")) + msgCFilter := NewMsgCFilter(&chainhash.Hash{}, true, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() tests := []struct { @@ -104,8 +104,8 @@ func TestMessage(t *testing.T) { {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 62}, - {msgCFilter, msgCFilter, pver, MainNet, 64}, - {msgCFHeaders, msgCFHeaders, pver, MainNet, 57}, + {msgCFilter, msgCFilter, pver, MainNet, 65}, + {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 615fb3f5d6..aa26f01470 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -28,6 +28,7 @@ const ( // MsgGetCFHeaders for details on requesting the headers. type MsgCFHeaders struct { StopHash chainhash.Hash + Extended bool HeaderHashes []*chainhash.Hash } @@ -52,6 +53,13 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { return err } + // Read extended flag + err = readElement(r, &msg.Extended) + if err != nil { + return err + } + + // Read number of filter headers count, err := ReadVarInt(r, pver) if err != nil { return err @@ -89,6 +97,12 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32) error { return err } + // Write extended flag + err = writeElement(w, msg.Extended) + if err != nil { + return err + } + // Limit to max committed headers per message. count := len(msg.HeaderHashes) if count > MaxCFHeadersPerMsg { @@ -139,7 +153,7 @@ func (msg *MsgCFHeaders) Command() string { // receiver. This is part of the Message interface implementation. func (msg *MsgCFHeaders) MaxPayloadLength(pver uint32) uint32 { // Hash size + num headers (varInt) + (header size * max headers). - return chainhash.HashSize + MaxVarIntPayload + + return chainhash.HashSize + 1 + MaxVarIntPayload + (MaxCFHeaderPayload * MaxCFHeadersPerMsg) } diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index a1d1b0fb70..ed5c1fa1dc 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -18,6 +18,7 @@ const ( type MsgCFilter struct { BlockHash chainhash.Hash + Extended bool Data []byte } @@ -25,7 +26,17 @@ type MsgCFilter struct { // This is part of the Message interface implementation. func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32) error { var err error + // Read the hash of the filter's block err = readElement(r, &msg.BlockHash) + if err != nil { + return err + } + // Read extended flag + err = readElement(r, &msg.Extended) + if err != nil { + return err + } + // Read filter data msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize, "cfilter data") return err @@ -46,6 +57,11 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32) error { return err } + err = writeElement(w, msg.Extended) + if err != nil { + return err + } + return WriteVarBytes(w, pver, msg.Data) } @@ -75,14 +91,16 @@ func (msg *MsgCFilter) Command() string { // receiver. This is part of the Message interface implementation. func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 { return uint32(VarIntSerializeSize(MaxCFilterDataSize)) + - MaxCFilterDataSize + MaxCFilterDataSize + chainhash.HashSize + 1 } // NewMsgCFilter returns a new bitcoin cfilter message that conforms to the // Message interface. See MsgCFilter for details. -func NewMsgCFilter(blockHash *chainhash.Hash, data []byte) *MsgCFilter { +func NewMsgCFilter(blockHash *chainhash.Hash, extended bool, + data []byte) *MsgCFilter { return &MsgCFilter{ BlockHash: *blockHash, + Extended: extended, Data: data, } } From 92f1de6dd96ee0020097cdee42a08e7c6e2f5860 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 4 Apr 2017 16:43:06 -0600 Subject: [PATCH 0113/1056] Fix case where 0 headers are retrieved. --- server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server.go b/server.go index ca3e6dd2f1..fa871d61f1 100644 --- a/server.go +++ b/server.go @@ -839,6 +839,9 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { peerLog.Warnf("Header lookup failed: %v", err) return } + if len(hashList) == 0 { + return + } // Generate cfheaders message and send it. headersMsg := wire.NewMsgCFHeaders() From f11e87c957c3951bcedce868d3c8d11b03ac9055 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 13 Apr 2017 20:15:14 -0600 Subject: [PATCH 0114/1056] rpcserver: Fix getcfilterheader RPC method's hex encoding for hash. --- rpcserver.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index a7ebf3a919..bbc580619c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2161,7 +2161,7 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) rpcsLog.Debugf("Found committed filter for %v", hash) } else { rpcsLog.Debugf("Could not find committed filter for %v: %v", - hash, err) + hash, err) return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCBlockNotFound, Message: "Block not found", @@ -2184,14 +2184,15 @@ func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan stru rpcsLog.Debugf("Found header of committed filter for %v", hash) } else { rpcsLog.Debugf("Could not find header of committed filter for %v: %v", - hash, err) + hash, err) return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCBlockNotFound, Message: "Block not found", } } - return hex.EncodeToString(headerBytes), nil + hash.SetBytes(headerBytes) + return hash.String(), nil } // handleGetConnectionCount implements the getconnectioncount command. From 1c5f25bbf213369afa33e1a08ac735de94514441 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 26 Apr 2017 18:55:24 -0600 Subject: [PATCH 0115/1056] blockchain/cfindex: Factor out filter/header calc. --- blockchain/indexers/cfindex.go | 80 +++++----------------------------- 1 file changed, 12 insertions(+), 68 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 3072445df9..22c12956c9 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcutil/gcs" "github.com/btcsuite/btcutil/gcs/builder" "github.com/btcsuite/fastsha256" ) @@ -158,71 +159,10 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { return err } -// makeBasicFilterForBlock builds a block's basic filter, which consists of -// all outpoints and pkscript data pushes referenced by transactions within the -// block. -func makeBasicFilterForBlock(block *btcutil.Block) ([]byte, error) { - b := builder.WithKeyHash(block.Hash()) - _, err := b.Key() - if err != nil { - return nil, err - } - for i, tx := range block.Transactions() { - // Skip the inputs for the coinbase transaction - if i != 0 { - for _, txIn := range tx.MsgTx().TxIn { - b.AddOutPoint(txIn.PreviousOutPoint) - } - } - for _, txOut := range tx.MsgTx().TxOut { - b.AddScript(txOut.PkScript) - } - } - f, err := b.Build() - if err != nil { - return nil, err - } - return f.NBytes(), nil -} - -// makeExtendedFilterForBlock builds a block's extended filter, which consists -// of all tx hashes and sigscript data pushes contained in the block. -func makeExtendedFilterForBlock(block *btcutil.Block) ([]byte, error) { - b := builder.WithKeyHash(block.Hash()) - _, err := b.Key() - if err != nil { - return nil, err - } - for i, tx := range block.Transactions() { - b.AddHash(tx.Hash()) - // Skip the inputs for the coinbase transaction - if i != 0 { - for _, txIn := range tx.MsgTx().TxIn { - b.AddScript(txIn.SignatureScript) - } - } - } - f, err := b.Build() - if err != nil { - return nil, err - } - return f.NBytes(), nil -} - -// makeHeaderForFilter implements the chaining logic between filters, where -// a filter's header is defined as sha256(sha256(filter) + previousFilterHeader). -func makeHeaderForFilter(f, pfh []byte) []byte { - fhash := fastsha256.Sum256(f) - chain := make([]byte, 0, 2*fastsha256.Size) - chain = append(chain, fhash[:]...) - chain = append(chain, pfh...) - fh := fastsha256.Sum256(chain) - return fh[:] -} - // storeFilter stores a given filter, and performs the steps needed to // generate the filter's header. -func storeFilter(dbTx database.Tx, block *btcutil.Block, f []byte, extended bool) error { +func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, + extended bool) error { // Figure out which buckets to use. fkey := cfBasicIndexKey hkey := cfBasicHeaderKey @@ -232,7 +172,7 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f []byte, extended bool } // Start by storing the filter. h := block.Hash() - err := dbStoreFilter(dbTx, fkey, h, f) + err := dbStoreFilter(dbTx, fkey, h, f.NBytes()) if err != nil { return err } @@ -243,8 +183,12 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f []byte, extended bool return err } // Construct the new block's filter header, and store it. - fh := makeHeaderForFilter(f, pfh) - return dbStoreFilterHeader(dbTx, hkey, h, fh) + prevHeader, err := chainhash.NewHash(pfh) + if err != nil { + return err + } + fh := builder.MakeHeaderForFilter(f, *prevHeader) + return dbStoreFilterHeader(dbTx, hkey, h, fh[:]) } // ConnectBlock is invoked by the index manager when a new block has been @@ -252,7 +196,7 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f []byte, extended bool // every passed block. This is part of the Indexer interface. func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - f, err := makeBasicFilterForBlock(block) + f, err := builder.BuildBasicFilter(block.MsgBlock()) if err != nil { return err } @@ -260,7 +204,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, if err != nil { return err } - f, err = makeExtendedFilterForBlock(block) + f, err = builder.BuildExtFilter(block.MsgBlock()) if err != nil { return err } From e0943a84bd5adae7f7c5d0a4184c9503a89d89ce Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 27 Apr 2017 19:44:43 -0700 Subject: [PATCH 0116/1056] blockchain/indexers: add a bit more line spacing to cfindex.go --- blockchain/indexers/cfindex.go | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 22c12956c9..40597f962a 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -29,15 +29,19 @@ var ( // cfIndexParentBucketKey is the name of the parent bucket used to house // the index. The rest of the buckets live below this bucket. cfIndexParentBucketKey = []byte("cfindexparentbucket") + // cfBasicIndexKey is the name of the db bucket used to house the // block hash -> basic cf index (cf#0). cfBasicIndexKey = []byte("cf0byhashidx") + // cfBasicHeaderKey is the name of the db bucket used to house the // block hash -> basic cf header index (cf#0). cfBasicHeaderKey = []byte("cf0headerbyhashidx") + // cfExtendedIndexKey is the name of the db bucket used to house the // block hash -> extended cf index (cf#1). cfExtendedIndexKey = []byte("cf1byhashidx") + // cfExtendedHeaderKey is the name of the db bucket used to house the // block hash -> extended cf header index (cf#1). cfExtendedHeaderKey = []byte("cf1headerbyhashidx") @@ -54,10 +58,12 @@ func dbFetchFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, err // A filter's absence is not considered an error. func dbFetchFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) + fh := idx.Get(h[:]) if len(fh) != fastsha256.Size { return nil, errors.New("invalid filter header length") } + return fh, nil } @@ -120,6 +126,7 @@ func (idx *CfIndex) Name() string { // indexes (simple, extended). func (idx *CfIndex) Create(dbTx database.Tx) error { meta := dbTx.Metadata() + cfIndexParentBucket, err := meta.CreateBucket(cfIndexParentBucketKey) if err != nil { return err @@ -140,6 +147,7 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { if err != nil { return err } + firstHeader := make([]byte, chainhash.HashSize) err = dbStoreFilterHeader( dbTx, @@ -150,19 +158,20 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { if err != nil { return err } - err = dbStoreFilterHeader( + + return dbStoreFilterHeader( dbTx, cfExtendedHeaderKey, &idx.chainParams.GenesisBlock.Header.PrevBlock, firstHeader, ) - return err } // storeFilter stores a given filter, and performs the steps needed to // generate the filter's header. func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, extended bool) error { + // Figure out which buckets to use. fkey := cfBasicIndexKey hkey := cfBasicHeaderKey @@ -170,18 +179,21 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, fkey = cfExtendedIndexKey hkey = cfExtendedHeaderKey } + // Start by storing the filter. h := block.Hash() err := dbStoreFilter(dbTx, fkey, h, f.NBytes()) if err != nil { return err } + // Then fetch the previous block's filter header. ph := &block.MsgBlock().Header.PrevBlock pfh, err := dbFetchFilterHeader(dbTx, hkey, ph) if err != nil { return err } + // Construct the new block's filter header, and store it. prevHeader, err := chainhash.NewHash(pfh) if err != nil { @@ -196,18 +208,21 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, // every passed block. This is part of the Indexer interface. func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { + f, err := builder.BuildBasicFilter(block.MsgBlock()) if err != nil { return err } - err = storeFilter(dbTx, block, f, false) - if err != nil { + + if err := storeFilter(dbTx, block, f, false); err != nil { return err } + f, err = builder.BuildExtFilter(block.MsgBlock()) if err != nil { return err } + return storeFilter(dbTx, block, f, true) } @@ -216,10 +231,12 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, // mapping for every passed block. This is part of the Indexer interface. func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { + err := dbDeleteFilter(dbTx, cfBasicIndexKey, block.Hash()) if err != nil { return err } + return dbDeleteFilter(dbTx, cfExtendedIndexKey, block.Hash()) } @@ -233,6 +250,7 @@ func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte, if extended { key = cfExtendedIndexKey } + f, err = dbFetchFilter(dbTx, key, h) return err }) @@ -249,6 +267,7 @@ func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, extended bool) ([ if extended { key = cfExtendedHeaderKey } + fh, err = dbFetchFilterHeader(dbTx, key, h) return err }) @@ -259,8 +278,8 @@ func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, extended bool) ([ // mapping of the hashes of all blocks in the blockchain to their respective // committed filters. // -// It implements the Indexer interface which plugs into the IndexManager that in -// turn is used by the blockchain package. This allows the index to be +// It implements the Indexer interface which plugs into the IndexManager that +// in turn is used by the blockchain package. This allows the index to be // seamlessly maintained along with the chain. func NewCfIndex(db database.DB, chainParams *chaincfg.Params) *CfIndex { return &CfIndex{db: db, chainParams: chainParams} From 9b9ef42f8a1b8ef2a6003545e0669dfe26e3d9ec Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 27 Apr 2017 21:48:53 -0700 Subject: [PATCH 0117/1056] blockchain/indexers: proper handling of empty filters --- blockchain/indexers/cfindex.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 40597f962a..d89013a0fd 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -182,7 +182,11 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, // Start by storing the filter. h := block.Hash() - err := dbStoreFilter(dbTx, fkey, h, f.NBytes()) + var basicFilterBytes []byte + if f != nil { + basicFilterBytes = f.NBytes() + } + err := dbStoreFilter(dbTx, fkey, h, basicFilterBytes) if err != nil { return err } @@ -210,7 +214,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { f, err := builder.BuildBasicFilter(block.MsgBlock()) - if err != nil { + if err != nil && err != gcs.ErrNoData { return err } From ec228f9ff946828373234feef81d2492b6125c23 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 8 May 2017 13:38:57 -0600 Subject: [PATCH 0118/1056] rpctest: Add GenerateAndSubmitBlockWithCustomCoinbaseOutputs --- integration/rpctest/blockgen.go | 23 +++++--- integration/rpctest/rpc_harness.go | 23 +++++++- integration/rpctest/rpc_harness_test.go | 76 +++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 9 deletions(-) diff --git a/integration/rpctest/blockgen.go b/integration/rpctest/blockgen.go index bf092f61d5..6c7218f776 100644 --- a/integration/rpctest/blockgen.go +++ b/integration/rpctest/blockgen.go @@ -88,7 +88,8 @@ func standardCoinbaseScript(nextBlockHeight int32, extraNonce uint64) ([]byte, e // createCoinbaseTx returns a coinbase transaction paying an appropriate // subsidy based on the passed block height to the provided address. func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32, - addr btcutil.Address, net *chaincfg.Params) (*btcutil.Tx, error) { + addr btcutil.Address, mineTo []wire.TxOut, + net *chaincfg.Params) (*btcutil.Tx, error) { // Create the script to pay to the provided payment address. pkScript, err := txscript.PayToAddrScript(addr) @@ -105,10 +106,16 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32, SignatureScript: coinbaseScript, Sequence: wire.MaxTxInSequenceNum, }) - tx.AddTxOut(&wire.TxOut{ - Value: blockchain.CalcBlockSubsidy(nextBlockHeight, net), - PkScript: pkScript, - }) + if len(mineTo) == 0 { + tx.AddTxOut(&wire.TxOut{ + Value: blockchain.CalcBlockSubsidy(nextBlockHeight, net), + PkScript: pkScript, + }) + } else { + for i := range mineTo { + tx.AddTxOut(&mineTo[i]) + } + } return btcutil.NewTx(tx), nil } @@ -118,8 +125,8 @@ func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int32, // second is used. Passing nil for the previous block results in a block that // builds off of the genesis block for the specified chain. func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx, - blockVersion int32, blockTime time.Time, - miningAddr btcutil.Address, net *chaincfg.Params) (*btcutil.Block, error) { + blockVersion int32, blockTime time.Time, miningAddr btcutil.Address, + mineTo []wire.TxOut, net *chaincfg.Params) (*btcutil.Block, error) { var ( prevHash *chainhash.Hash @@ -156,7 +163,7 @@ func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx, return nil, err } coinbaseTx, err := createCoinbaseTx(coinbaseScript, blockHeight, - miningAddr, net) + miningAddr, mineTo, net) if err != nil { return nil, err } diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 653a378298..ea8868ce83 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -406,6 +406,27 @@ func (h *Harness) P2PAddress() string { // This function is safe for concurrent access. func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32, blockTime time.Time) (*btcutil.Block, error) { + return h.GenerateAndSubmitBlockWithCustomCoinbaseOutputs(txns, + blockVersion, blockTime, []wire.TxOut{}) +} + +// GenerateAndSubmitBlockWithCustomCoinbaseOutputs creates a block whose +// contents include the passed coinbase outputs and transactions and submits +// it to the running simnet node. For generating blocks with only a coinbase tx, +// callers can simply pass nil instead of transactions to be mined. +// Additionally, a custom block version can be set by the caller. A blockVersion +// of -1 indicates that the current default block version should be used. An +// uninitialized time.Time should be used for the blockTime parameter if one +// doesn't wish to set a custom time. The mineTo list of outputs will be added +// to the coinbase; this is not checked for correctness until the block is +// submitted; thus, it is the caller's responsibility to ensure that the outputs +// are correct. If the list is empty, the coinbase reward goes to the wallet +// managed by the Harness. +// +// This function is safe for concurrent access. +func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs( + txns []*btcutil.Tx, blockVersion int32, blockTime time.Time, + mineTo []wire.TxOut) (*btcutil.Block, error) { h.Lock() defer h.Unlock() @@ -427,7 +448,7 @@ func (h *Harness) GenerateAndSubmitBlock(txns []*btcutil.Tx, blockVersion int32, // Create a new block including the specified transactions newBlock, err := CreateBlock(prevBlock, txns, blockVersion, - blockTime, h.wallet.coinbaseAddr, h.ActiveNet) + blockTime, h.wallet.coinbaseAddr, mineTo, h.ActiveNet) if err != nil { return nil, err } diff --git a/integration/rpctest/rpc_harness_test.go b/integration/rpctest/rpc_harness_test.go index c3fc18b409..20797d3834 100644 --- a/integration/rpctest/rpc_harness_test.go +++ b/integration/rpctest/rpc_harness_test.go @@ -391,6 +391,81 @@ func testGenerateAndSubmitBlock(r *Harness, t *testing.T) { } } +func testGenerateAndSubmitBlockWithCustomCoinbaseOutputs(r *Harness, + t *testing.T) { + // Generate a few test spend transactions. + addr, err := r.NewAddress() + if err != nil { + t.Fatalf("unable to generate new address: %v", err) + } + pkScript, err := txscript.PayToAddrScript(addr) + if err != nil { + t.Fatalf("unable to create script: %v", err) + } + output := wire.NewTxOut(btcutil.SatoshiPerBitcoin, pkScript) + + const numTxns = 5 + txns := make([]*btcutil.Tx, 0, numTxns) + for i := 0; i < numTxns; i++ { + tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + if err != nil { + t.Fatalf("unable to create tx: %v", err) + } + + txns = append(txns, btcutil.NewTx(tx)) + } + + // Now generate a block with the default block version, a zero'd out + // time, and a burn output. + block, err := r.GenerateAndSubmitBlockWithCustomCoinbaseOutputs(txns, + -1, time.Time{}, []wire.TxOut{{ + Value: 0, + PkScript: []byte{}, + }}) + if err != nil { + t.Fatalf("unable to generate block: %v", err) + } + + // Ensure that all created transactions were included, and that the + // block version was properly set to the default. + numBlocksTxns := len(block.Transactions()) + if numBlocksTxns != numTxns+1 { + t.Fatalf("block did not include all transactions: "+ + "expected %v, got %v", numTxns+1, numBlocksTxns) + } + blockVersion := block.MsgBlock().Header.Version + if blockVersion != BlockVersion { + t.Fatalf("block version is not default: expected %v, got %v", + BlockVersion, blockVersion) + } + + // Next generate a block with a "non-standard" block version along with + // time stamp a minute after the previous block's timestamp. + timestamp := block.MsgBlock().Header.Timestamp.Add(time.Minute) + targetBlockVersion := int32(1337) + block, err = r.GenerateAndSubmitBlockWithCustomCoinbaseOutputs(nil, + targetBlockVersion, timestamp, []wire.TxOut{{ + Value: 0, + PkScript: []byte{}, + }}) + if err != nil { + t.Fatalf("unable to generate block: %v", err) + } + + // Finally ensure that the desired block version and timestamp were set + // properly. + header := block.MsgBlock().Header + blockVersion = header.Version + if blockVersion != targetBlockVersion { + t.Fatalf("block version mismatch: expected %v, got %v", + targetBlockVersion, blockVersion) + } + if !timestamp.Equal(header.Timestamp) { + t.Fatalf("header time stamp mismatch: expected %v, got %v", + timestamp, header.Timestamp) + } +} + func testMemWalletReorg(r *Harness, t *testing.T) { // Create a fresh harness, we'll be using the main harness to force a // re-org on this local harness. @@ -478,6 +553,7 @@ var harnessTestCases = []HarnessTestCase{ testJoinBlocks, testJoinMempools, // Depends on results of testJoinBlocks testGenerateAndSubmitBlock, + testGenerateAndSubmitBlockWithCustomCoinbaseOutputs, testMemWalletReorg, testMemWalletLockedOutputs, } From 7647f884a95689af7e6df0b46d5b0f302126e95c Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 11 May 2017 21:34:05 -0600 Subject: [PATCH 0119/1056] rpcserver: Return 0-length headers via RPC as they're now valid. --- rpcserver.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index bbc580619c..7c0ee34443 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2157,9 +2157,7 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) } filterBytes, err := s.server.cfIndex.FilterByBlockHash(hash, c.Extended) - if len(filterBytes) > 0 { - rpcsLog.Debugf("Found committed filter for %v", hash) - } else { + if err != nil { rpcsLog.Debugf("Could not find committed filter for %v: %v", hash, err) return nil, &btcjson.RPCError{ @@ -2168,6 +2166,7 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) } } + rpcsLog.Debugf("Found committed filter for %v", hash) return hex.EncodeToString(filterBytes), nil } From 4a6dc670675cb1cc1770ab0e5636285f0c57ff03 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 4 Jan 2017 16:28:38 -0800 Subject: [PATCH 0120/1056] txscript: add exported sighash calc func --- txscript/script.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/txscript/script.go b/txscript/script.go index aac3d4aaaa..29f1e4d906 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -424,6 +424,19 @@ func calcHashOutputs(tx *wire.MsgTx) chainhash.Hash { return chainhash.DoubleHashH(b.Bytes()) } +// CalcWitnessSigHash exports calcWitnessSignatureHash so that signatures +// can be verified. +func CalcWitnessSigHash(subScript []byte, sigHashes *TxSigHashes, + hashType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { + parsedScript, err := parseScript(subScript) + if err != nil { + return nil, fmt.Errorf("cannot parse output script: %v", err) + } + sighash := calcWitnessSignatureHash( + parsedScript, sigHashes, hashType, tx, idx, amt) + return sighash, nil +} + // calcWitnessSignatureHash computes the sighash digest of a transaction's // segwit input using the new, optimized digest calculation algorithm defined // in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. From ac4bd31ba075d0f09b74f81b11e83a3be6439eff Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 5 Jun 2017 14:45:49 -0700 Subject: [PATCH 0121/1056] peer: disable peer stalling for get blocks messages --- peer/peer.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index 0a3765d7d0..74b4b52734 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1278,10 +1278,6 @@ func (p *Peer) maybeAddDeadline(pendingResponses map[string]time.Time, msgCmd st // Expects an inv message. pendingResponses[wire.CmdInv] = deadline - case wire.CmdGetBlocks: - // Expects an inv message. - pendingResponses[wire.CmdInv] = deadline - case wire.CmdGetData: // Expects a block, merkleblock, tx, or notfound message. pendingResponses[wire.CmdBlock] = deadline From 6589cffb195c73c9e842b9eeee20dbc2c2086ac7 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 13 Jun 2017 09:27:18 -0600 Subject: [PATCH 0122/1056] server: change logging in OnGetCFilter to be less verbose --- server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index fa871d61f1..efbb978442 100644 --- a/server.go +++ b/server.go @@ -750,9 +750,9 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { msg.Extended) if len(filterBytes) > 0 { - peerLog.Infof("Obtained CF for %v", msg.BlockHash) + peerLog.Tracef("Obtained CF for %v", msg.BlockHash) } else { - peerLog.Infof("Could not obtain CF for %v: %v", msg.BlockHash, + peerLog.Warnf("Could not obtain CF for %v: %v", msg.BlockHash, err) } From a741b4366b10655f3a8556c15c9a821df1bd8de7 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Wed, 24 May 2017 17:24:06 -0400 Subject: [PATCH 0123/1056] all: Remove seelog logger. The btclog package has been changed to defining its own logging interface (rather than seelog's) and provides a default implementation for callers to use. There are two primary advantages to the new logger implementation. First, all log messages are created before the call returns. Compared to seelog, this prevents data races when mutable variables are logged. Second, the new logger does not implement any kind of artifical rate limiting (what seelog refers to as "adaptive logging"). Log messages are outputted as soon as possible and the application will appear to perform much better when watching standard output. Because log rotation is not a feature of the btclog logging implementation, it is handled by the main package by importing a file rotation package that provides an io.Reader interface for creating output to a rotating file output. The rotator has been configured with the same defaults that btcd previously used in the seelog config (10MB file limits with maximum of 3 rolls) but now compresses newly created roll files. Due to the high compressibility of log text, the compressed files typically reduce to around 15-30% of the original 10MB file. --- glide.lock | 58 ------------------------------------------------------ 1 file changed, 58 deletions(-) delete mode 100644 glide.lock diff --git a/glide.lock b/glide.lock deleted file mode 100644 index b1d2e4a341..0000000000 --- a/glide.lock +++ /dev/null @@ -1,58 +0,0 @@ -hash: 976decfaf173d97d2e4572399490637aa12e217312a7d8b28813780a738e1151 -updated: 2018-05-15T19:16:29.311905983-07:00 -imports: -- name: github.com/btcsuite/btclog - version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a -- name: github.com/btcsuite/btcutil - version: b9afb0b9868a757e8fcc3c3adf5b129979f9b3e6 - subpackages: - - base58 - - bech32 - - bloom - - hdkeychain -- name: github.com/btcsuite/go-socks - version: 4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f - subpackages: - - socks -- name: github.com/btcsuite/goleveldb - version: 7834afc9e8cd15233b6c3d97e12674a31ca24602 - subpackages: - - leveldb - - leveldb/cache - - leveldb/comparer - - leveldb/errors - - leveldb/filter - - leveldb/iterator - - leveldb/journal - - leveldb/memdb - - leveldb/opt - - leveldb/storage - - leveldb/table - - leveldb/util -- name: github.com/btcsuite/snappy-go - version: 0bdef8d067237991ddaa1bb6072a740bc40601ba -- name: github.com/btcsuite/websocket - version: 31079b6807923eb23992c421b114992b95131b55 -- name: github.com/btcsuite/winsvc - version: f8fb11f83f7e860e3769a08e6811d1b399a43722 - subpackages: - - eventlog - - mgr - - registry - - svc - - winapi -- name: github.com/davecgh/go-spew - version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 - subpackages: - - spew -- name: github.com/jessevdk/go-flags - version: 1679536dcc895411a9f5848d9a0250be7856448c -- name: github.com/jrick/logrotate - version: a93b200c26cbae3bb09dd0dc2c7c7fe1468a034a - subpackages: - - rotator -- name: golang.org/x/crypto - version: 1a580b3eff7814fc9b40602fd35256c63b50f491 - subpackages: - - ripemd160 -testImports: [] From 9a30e95d83b9e522ac2fcabe22941a0096350d55 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 4 Jul 2017 14:08:08 -0700 Subject: [PATCH 0124/1056] peer: don't inv trickle new blocks --- peer/peer.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/peer/peer.go b/peer/peer.go index 74b4b52734..9a06774baa 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1723,7 +1723,19 @@ out: case iv := <-p.outputInvChan: // No handshake? They'll find out soon enough. if p.VersionKnown() { - invSendQueue.PushBack(iv) + // If this is a new block, then we'll blast it + // out immediately, sipping the inv trickle + // queue. + if iv.Type == wire.InvTypeBlock || + iv.Type == wire.InvTypeWitnessBlock { + + invMsg := wire.NewMsgInvSizeHint(1) + invMsg.AddInvVect(iv) + waiting = queuePacket(outMsg{msg: invMsg}, + pendingMsgs, waiting) + } else { + invSendQueue.PushBack(iv) + } } case <-trickleTicker.C: From 3d1caa2f834cc1adc03e7ef69ef6725a7a33e9b8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 24 Aug 2017 16:29:38 -0700 Subject: [PATCH 0125/1056] multi: update to point to roasbeef forks --- CHANGES | 26 +++++----- blockchain/chainview_test.go | 2 +- blockchain/notifications_test.go | 2 +- chaincfg/chainhash/README.md | 1 + database/ffldb/README.md | 1 + docs/README.md | 48 +++++++++---------- docs/code_contribution_guidelines.md | 6 +-- docs/json_rpc_api.md | 14 +++--- integration/rpctest/README.md | 6 +-- mining/cpuminer/README.md | 1 + rpcadapters.go | 14 +++--- rpcclient/README.md | 14 +++--- rpcclient/doc.go | 2 +- rpcclient/examples/bitcoincorehttp/README.md | 4 +- rpcclient/examples/bitcoincorehttp/main.go | 2 +- rpcclient/examples/btcdwebsockets/README.md | 4 +- rpcclient/examples/btcdwebsockets/main.go | 6 +-- .../examples/btcwalletwebsockets/README.md | 4 +- .../examples/btcwalletwebsockets/main.go | 4 +- rpcclient/extensions.go | 8 ++-- rpcclient/infrastructure.go | 2 +- rpcclient/mining.go | 6 +-- rpcclient/net.go | 2 +- rpcclient/notify.go | 8 ++-- rpcclient/rawrequest.go | 2 +- rpcclient/rawtransactions.go | 8 ++-- rpcclient/wallet.go | 10 ++-- txscript/hashcache_test.go | 2 +- txscript/script.go | 13 ----- txscript/script_test.go | 2 +- 30 files changed, 107 insertions(+), 117 deletions(-) diff --git a/CHANGES b/CHANGES index 6f7013e922..b7aabf852d 100644 --- a/CHANGES +++ b/CHANGES @@ -264,7 +264,7 @@ Changes in 0.10.0 (Sun Mar 01 2015) for version 3 blocks which are compatible with BIP0066 - Allow getblocktemplate to serve blocks when the current time is less than the minimum allowed time for a generated block template - (https://github.com/btcsuite/btcd/issues/209) + (https://github.com/roasbeef/btcd/issues/209) - Crypto changes: - Optimize scalar multiplication by the base point by using a pre-computed table which results in approximately a 35% speedup @@ -279,29 +279,29 @@ Changes in 0.10.0 (Sun Mar 01 2015) - Add a new parameter --addrindex which will enable the creation of an address index which can be queried to determine all transactions which involve a given address - (https://github.com/btcsuite/btcd/issues/190) + (https://github.com/roasbeef/btcd/issues/190) - Add a new logging subsystem for address index related operations - Support new searchrawtransactions RPC - (https://github.com/btcsuite/btcd/issues/185) + (https://github.com/roasbeef/btcd/issues/185) - RPC changes: - Require TLS version 1.2 as the minimum version for all TLS connections - Provide support for disabling TLS when only listening on localhost - (https://github.com/btcsuite/btcd/pull/192) + (https://github.com/roasbeef/btcd/pull/192) - Modify help output for all commands to provide much more consistent and detailed information - Correct case in getrawtransaction which would refuse to serve certain transactions with invalid scripts - (https://github.com/btcsuite/btcd/issues/210) + (https://github.com/roasbeef/btcd/issues/210) - Correct error handling in the getrawtransaction RPC which could lead to a crash in rare cases - (https://github.com/btcsuite/btcd/issues/196) + (https://github.com/roasbeef/btcd/issues/196) - Update getinfo RPC to include the appropriate 'timeoffset' calculated from the median network time - Modify listreceivedbyaddress result type to include txids field so it is compatible - Add 'iswatchonly' field to validateaddress result - Add 'startingpriority' and 'currentpriority' fields to getrawmempool - (https://github.com/btcsuite/btcd/issues/178) + (https://github.com/roasbeef/btcd/issues/178) - Don't omit the 'confirmations' field from getrawtransaction when it is zero - Websocket changes: @@ -317,7 +317,7 @@ Changes in 0.10.0 (Sun Mar 01 2015) dumping all of the commands - Make the usage syntax much more consistent and correct a few cases of misnamed fields - (https://github.com/btcsuite/btcd/issues/305) + (https://github.com/roasbeef/btcd/issues/305) - Improve usage errors to show the specific parameter number, reason, and error code - Only show the usage for specific command is shown when a valid command @@ -336,7 +336,7 @@ Changes in 0.10.0 (Sun Mar 01 2015) - Remove utility in favor of the RPC getblock method - Notable developer-related package changes: - Many of the core packages have been relocated into the btcd repository - (https://github.com/btcsuite/btcd/issues/214) + (https://github.com/roasbeef/btcd/issues/214) - A new version of the btcjson package that has been completely redesigned from the ground up based based upon how the project has evolved and lessons learned while using it since it was first written @@ -353,21 +353,21 @@ Changes in 0.10.0 (Sun Mar 01 2015) and using that data to calculate an offset against the local time - Misc changes: - Fix a slow memory leak due to tickers not being stopped - (https://github.com/btcsuite/btcd/issues/189) + (https://github.com/roasbeef/btcd/issues/189) - Fix an issue where a mix of orphans and SPV clients could trigger a condition where peers would no longer be served - (https://github.com/btcsuite/btcd/issues/231) + (https://github.com/roasbeef/btcd/issues/231) - The RPC username and password can now contain symbols which previously conflicted with special symbols used in URLs - Improve handling of obtaining random nonces to prevent cases where it could error when not enough entropy was available - Improve handling of home directory creation errors such as in the case - of unmounted symlinks (https://github.com/btcsuite/btcd/issues/193) + of unmounted symlinks (https://github.com/roasbeef/btcd/issues/193) - Improve the error reporting for rejected transactions to include the inputs which are missing and/or being double spent - Update sample config file with new options and correct a comment regarding the fact the RPC server only listens on localhost by default - (https://github.com/btcsuite/btcd/issues/218) + (https://github.com/roasbeef/btcd/issues/218) - Update the continuous integration builds to run several tools which help keep code quality high - Significant amount of internal code cleanup and improvements diff --git a/blockchain/chainview_test.go b/blockchain/chainview_test.go index c59004fdaf..bf49751d08 100644 --- a/blockchain/chainview_test.go +++ b/blockchain/chainview_test.go @@ -10,7 +10,7 @@ import ( "reflect" "testing" - "github.com/btcsuite/btcd/wire" + "github.com/roasbeef/btcd/wire" ) // testNoncePrng provides a deterministic prng for the nonce in generated fake diff --git a/blockchain/notifications_test.go b/blockchain/notifications_test.go index fde58735df..11c60f8bff 100644 --- a/blockchain/notifications_test.go +++ b/blockchain/notifications_test.go @@ -7,7 +7,7 @@ package blockchain import ( "testing" - "github.com/btcsuite/btcd/chaincfg" + "github.com/roasbeef/btcd/chaincfg" ) // TestNotifications ensures that notification callbacks are fired on events. diff --git a/chaincfg/chainhash/README.md b/chaincfg/chainhash/README.md index 41eeef700c..fc49d9cd93 100644 --- a/chaincfg/chainhash/README.md +++ b/chaincfg/chainhash/README.md @@ -4,6 +4,7 @@ chainhash [![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/chaincfg/chainhash) +======= chainhash provides a generic hash type and associated functions that allows the specific hash algorithm to be abstracted. diff --git a/database/ffldb/README.md b/database/ffldb/README.md index 5609aa5e99..ebaa5a7e01 100644 --- a/database/ffldb/README.md +++ b/database/ffldb/README.md @@ -4,6 +4,7 @@ ffldb [![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![GoDoc](https://godoc.org/github.com/btcsuite/btcd/database/ffldb?status.png)](http://godoc.org/github.com/btcsuite/btcd/database/ffldb) +======= Package ffldb implements a driver for the database package that uses leveldb for the backing metadata and flat files for block storage. diff --git a/docs/README.md b/docs/README.md index c00d295e7a..09350d1842 100644 --- a/docs/README.md +++ b/docs/README.md @@ -69,7 +69,7 @@ details on how to install on the supported operating systems. **2.1.1 Windows Installation**
-* Install the MSI available at: https://github.com/btcsuite/btcd/releases +* Install the MSI available at: https://github.com/roasbeef/btcd/releases * Launch btcd from the Start Menu
@@ -96,8 +96,8 @@ recommended that `GOPATH` is set to a directory in your home directory such as ```bash $ go get -u github.com/Masterminds/glide -$ git clone https://github.com/btcsuite/btcd $GOPATH/src/github.com/btcsuite/btcd -$ cd $GOPATH/src/github.com/btcsuite/btcd +$ git clone https://github.com/roasbeef/btcd $GOPATH/src/github.com/roasbeef/btcd +$ cd $GOPATH/src/github.com/roasbeef/btcd $ glide install $ go install . ./cmd/... ``` @@ -111,7 +111,7 @@ $ go install . ./cmd/... - Run the following commands to update btcd, all dependencies, and install it: ```bash -$ cd $GOPATH/src/github.com/btcsuite/btcd +$ cd $GOPATH/src/github.com/roasbeef/btcd $ git pull && glide install $ go install . ./cmd/... ``` @@ -129,7 +129,7 @@ $ go install . ./cmd/... **2.2 Configuration** -btcd has a number of [configuration](http://godoc.org/github.com/btcsuite/btcd) +btcd has a number of [configuration](http://godoc.org/github.com/roasbeef/btcd) options, which can be viewed by running: `$ btcd --help`. @@ -213,16 +213,16 @@ configuration necessary, however, there is an optional method to use a **3.1.1 bootstrap.dat** -* [Using bootstrap.dat](https://github.com/btcsuite/btcd/tree/master/docs/using_bootstrap_dat.md) +* [Using bootstrap.dat](https://github.com/roasbeef/btcd/tree/master/docs/using_bootstrap_dat.md) **3.1.2 Network Configuration** -* [What Ports Are Used by Default?](https://github.com/btcsuite/btcd/tree/master/docs/default_ports.md) -* [How To Listen on Specific Interfaces](https://github.com/btcsuite/btcd/tree/master/docs/configure_peer_server_listen_interfaces.md) -* [How To Configure RPC Server to Listen on Specific Interfaces](https://github.com/btcsuite/btcd/tree/master/docs/configure_rpc_server_listen_interfaces.md) -* [Configuring btcd with Tor](https://github.com/btcsuite/btcd/tree/master/docs/configuring_tor.md) +* [What Ports Are Used by Default?](https://github.com/roasbeef/btcd/tree/master/docs/default_ports.md) +* [How To Listen on Specific Interfaces](https://github.com/roasbeef/btcd/tree/master/docs/configure_peer_server_listen_interfaces.md) +* [How To Configure RPC Server to Listen on Specific Interfaces](https://github.com/roasbeef/btcd/tree/master/docs/configure_rpc_server_listen_interfaces.md) +* [Configuring btcd with Tor](https://github.com/roasbeef/btcd/tree/master/docs/configuring_tor.md) @@ -258,12 +258,12 @@ information. -* [Code Contribution Guidelines](https://github.com/btcsuite/btcd/tree/master/docs/code_contribution_guidelines.md) +* [Code Contribution Guidelines](https://github.com/roasbeef/btcd/tree/master/docs/code_contribution_guidelines.md) -* [JSON-RPC Reference](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md) - * [RPC Examples](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md#ExampleCode) +* [JSON-RPC Reference](https://github.com/roasbeef/btcd/tree/master/docs/json_rpc_api.md) + * [RPC Examples](https://github.com/roasbeef/btcd/tree/master/docs/json_rpc_api.md#ExampleCode) @@ -272,28 +272,28 @@ information. robust and easy to use Websocket-enabled Bitcoin JSON-RPC client * [btcjson](https://github.com/btcsuite/btcd/tree/master/btcjson) - Provides an extensive API for the underlying JSON-RPC command and return values - * [wire](https://github.com/btcsuite/btcd/tree/master/wire) - Implements the + * [wire](https://github.com/roasbeef/btcd/tree/master/wire) - Implements the Bitcoin wire protocol - * [peer](https://github.com/btcsuite/btcd/tree/master/peer) - + * [peer](https://github.com/roasbeef/btcd/tree/master/peer) - Provides a common base for creating and managing Bitcoin network peers. - * [blockchain](https://github.com/btcsuite/btcd/tree/master/blockchain) - + * [blockchain](https://github.com/roasbeef/btcd/tree/master/blockchain) - Implements Bitcoin block handling and chain selection rules - * [blockchain/fullblocktests](https://github.com/btcsuite/btcd/tree/master/blockchain/fullblocktests) - + * [blockchain/fullblocktests](https://github.com/roasbeef/btcd/tree/master/blockchain/fullblocktests) - Provides a set of block tests for testing the consensus validation rules - * [txscript](https://github.com/btcsuite/btcd/tree/master/txscript) - + * [txscript](https://github.com/roasbeef/btcd/tree/master/txscript) - Implements the Bitcoin transaction scripting language - * [btcec](https://github.com/btcsuite/btcd/tree/master/btcec) - Implements + * [btcec](https://github.com/roasbeef/btcd/tree/master/btcec) - Implements support for the elliptic curve cryptographic functions needed for the Bitcoin scripts - * [database](https://github.com/btcsuite/btcd/tree/master/database) - + * [database](https://github.com/roasbeef/btcd/tree/master/database) - Provides a database interface for the Bitcoin block chain - * [mempool](https://github.com/btcsuite/btcd/tree/master/mempool) - + * [mempool](https://github.com/roasbeef/btcd/tree/master/mempool) - Package mempool provides a policy-enforced pool of unmined bitcoin transactions. - * [btcutil](https://github.com/btcsuite/btcutil) - Provides Bitcoin-specific + * [btcutil](https://github.com/roasbeef/btcutil) - Provides Bitcoin-specific convenience functions and types - * [chainhash](https://github.com/btcsuite/btcd/tree/master/chaincfg/chainhash) - + * [chainhash](https://github.com/roasbeef/btcd/tree/master/chaincfg/chainhash) - Provides a generic hash type and associated functions that allows the specific hash algorithm to be abstracted. - * [connmgr](https://github.com/btcsuite/btcd/tree/master/connmgr) - + * [connmgr](https://github.com/roasbeef/btcd/tree/master/connmgr) - Package connmgr implements a generic Bitcoin network connection manager. diff --git a/docs/code_contribution_guidelines.md b/docs/code_contribution_guidelines.md index b643e911a3..29613608f4 100644 --- a/docs/code_contribution_guidelines.md +++ b/docs/code_contribution_guidelines.md @@ -239,7 +239,7 @@ Further paragraphs come after blank lines. Prefix the summary with the subsystem/package when possible. Many other projects make use of the code and this makes it easier for them to tell when something they're using has changed. Have a look at [past -commits](https://github.com/btcsuite/btcd/commits/master) for examples of +commits](https://github.com/roasbeef/btcd/commits/master) for examples of commit messages. Here are some of the reasons why wrapping your commit messages to 72 columns is @@ -321,7 +321,7 @@ keep a clean commit history over a tangled weave of merge commits. However, regardless of the specific merge method used, the code will be integrated with the master branch and the pull request will be closed. -Rejoice as you will now be listed as a [contributor](https://github.com/btcsuite/btcd/graphs/contributors)! +Rejoice as you will now be listed as a [contributor](https://github.com/roasbeef/btcd/graphs/contributors)! @@ -351,5 +351,5 @@ Rejoice as you will now be listed as a [contributor](https://github.com/btcsuite ### 6.2. Licensing of Contributions All contributions must be licensed with the -[ISC license](https://github.com/btcsuite/btcd/blob/master/LICENSE). This is +[ISC license](https://github.com/roasbeef/btcd/blob/master/LICENSE). This is the same license as all of the code in the btcd suite. diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index 9b8b36b3bb..7fc3a23c51 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -1095,7 +1095,7 @@ package main import ( "github.com/btcsuite/btcrpcclient" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcutil" "io/ioutil" "log" "path/filepath" @@ -1156,9 +1156,9 @@ package main import ( "github.com/btcsuite/btcrpcclient" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" + "github.com/roasbeef/btcutil" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/wire" "io/ioutil" "log" "path/filepath" @@ -1248,9 +1248,9 @@ package main import ( "github.com/btcsuite/btcrpcclient" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" + "github.com/roasbeef/btcutil" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/wire" "io/ioutil" "log" "path/filepath" diff --git a/integration/rpctest/README.md b/integration/rpctest/README.md index fceeed20a0..26a53ef2b5 100644 --- a/integration/rpctest/README.md +++ b/integration/rpctest/README.md @@ -1,9 +1,9 @@ rpctest ======= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](http://img.shields.io/travis/roasbeef/btcd.svg)](https://travis-ci.org/roasbeef/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/integration/rpctest) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/roasbeef/btcd/integration/rpctest) Package rpctest provides a btcd-specific RPC testing harness crafting and executing integration tests by driving a `btcd` instance via the `RPC` @@ -20,7 +20,7 @@ systems/integration tests. ## Installation and Updating ```bash -$ go get -u github.com/btcsuite/btcd/integration/rpctest +$ go get -u github.com/roasbeef/btcd/integration/rpctest ``` ## License diff --git a/mining/cpuminer/README.md b/mining/cpuminer/README.md index 899a5aed03..205b8f0360 100644 --- a/mining/cpuminer/README.md +++ b/mining/cpuminer/README.md @@ -4,6 +4,7 @@ cpuminer [![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/mining/cpuminer) +======= ## Overview diff --git a/rpcadapters.go b/rpcadapters.go index 7d2c3a14d0..e0af0b0983 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -7,13 +7,13 @@ package main import ( "sync/atomic" - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/mempool" - "github.com/btcsuite/btcd/netsync" - "github.com/btcsuite/btcd/peer" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/Roasbeef/btcd/netsync" + "github.com/roasbeef/btcd/blockchain" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/mempool" + "github.com/roasbeef/btcd/peer" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) // rpcPeer provides a peer for use with the RPC server and implements the diff --git a/rpcclient/README.md b/rpcclient/README.md index 4d644110f5..f53fa76675 100644 --- a/rpcclient/README.md +++ b/rpcclient/README.md @@ -1,9 +1,9 @@ rpcclient ========= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](http://img.shields.io/travis/roasbeef/btcd.svg)](https://travis-ci.org/roasbeef/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/rpcclient) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/roasbeef/btcd/rpcclient) rpcclient implements a Websocket-enabled Bitcoin JSON-RPC client package written in [Go](http://golang.org/). It provides a robust and easy to use client for @@ -18,16 +18,16 @@ implement and the API is not stable yet. ## Documentation -* [API Reference](http://godoc.org/github.com/btcsuite/btcd/rpcclient) -* [btcd Websockets Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/btcdwebsockets) +* [API Reference](http://godoc.org/github.com/roasbeef/btcd/rpcclient) +* [btcd Websockets Example](https://github.com/roasbeef/btcd/rpcclient/blob/master/examples/btcdwebsockets) Connects to a btcd RPC server using TLS-secured websockets, registers for block connected and block disconnected notifications, and gets the current block count -* [btcwallet Websockets Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/btcwalletwebsockets) +* [btcwallet Websockets Example](https://github.com/roasbeef/btcd/rpcclient/blob/master/examples/btcwalletwebsockets) Connects to a btcwallet RPC server using TLS-secured websockets, registers for notifications about changes to account balances, and gets a list of unspent transaction outputs (utxos) the wallet can sign -* [Bitcoin Core HTTP POST Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/bitcoincorehttp) +* [Bitcoin Core HTTP POST Example](https://github.com/roasbeef/btcd/rpcclient/blob/master/examples/bitcoincorehttp) Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled and gets the current block count @@ -47,7 +47,7 @@ implement and the API is not stable yet. ## Installation ```bash -$ go get -u github.com/btcsuite/btcd/rpcclient +$ go get -u github.com/roasbeef/btcd/rpcclient ``` ## License diff --git a/rpcclient/doc.go b/rpcclient/doc.go index d4bbb64d65..f52bbc48d0 100644 --- a/rpcclient/doc.go +++ b/rpcclient/doc.go @@ -9,7 +9,7 @@ Overview This client provides a robust and easy to use client for interfacing with a Bitcoin RPC server that uses a btcd/bitcoin core compatible Bitcoin JSON-RPC -API. This client has been tested with btcd (https://github.com/btcsuite/btcd), +API. This client has been tested with btcd (https://github.com/roasbeef/btcd), btcwallet (https://github.com/btcsuite/btcwallet), and bitcoin core (https://github.com/bitcoin). diff --git a/rpcclient/examples/bitcoincorehttp/README.md b/rpcclient/examples/bitcoincorehttp/README.md index 4d1f0adfe1..b13d09a78a 100644 --- a/rpcclient/examples/bitcoincorehttp/README.md +++ b/rpcclient/examples/bitcoincorehttp/README.md @@ -10,7 +10,7 @@ block count. The first step is to use `go get` to download and install the rpcclient package: ```bash -$ go get github.com/btcsuite/btcd/rpcclient +$ go get github.com/roasbeef/btcd/rpcclient ``` Next, modify the `main.go` source to specify the correct RPC username and @@ -24,7 +24,7 @@ password for the RPC server: Finally, navigate to the example's directory and run it with: ```bash -$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/bitcoincorehttp +$ cd $GOPATH/src/github.com/roasbeef/btcd/rpcclient/examples/bitcoincorehttp $ go run *.go ``` diff --git a/rpcclient/examples/bitcoincorehttp/main.go b/rpcclient/examples/bitcoincorehttp/main.go index 489770a25b..0afdfab1e7 100644 --- a/rpcclient/examples/bitcoincorehttp/main.go +++ b/rpcclient/examples/bitcoincorehttp/main.go @@ -7,7 +7,7 @@ package main import ( "log" - "github.com/btcsuite/btcd/rpcclient" + "github.com/roasbeef/btcd/rpcclient" ) func main() { diff --git a/rpcclient/examples/btcdwebsockets/README.md b/rpcclient/examples/btcdwebsockets/README.md index a168648435..7187865d1d 100644 --- a/rpcclient/examples/btcdwebsockets/README.md +++ b/rpcclient/examples/btcdwebsockets/README.md @@ -13,7 +13,7 @@ demonstrate clean shutdown. The first step is to use `go get` to download and install the rpcclient package: ```bash -$ go get github.com/btcsuite/btcd/rpcclient +$ go get github.com/roasbeef/btcd/rpcclient ``` Next, modify the `main.go` source to specify the correct RPC username and @@ -27,7 +27,7 @@ password for the RPC server: Finally, navigate to the example's directory and run it with: ```bash -$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/btcdwebsockets +$ cd $GOPATH/src/github.com/roasbeef/btcd/rpcclient/examples/btcdwebsockets $ go run *.go ``` diff --git a/rpcclient/examples/btcdwebsockets/main.go b/rpcclient/examples/btcdwebsockets/main.go index 56d12d8274..f554cb45e4 100644 --- a/rpcclient/examples/btcdwebsockets/main.go +++ b/rpcclient/examples/btcdwebsockets/main.go @@ -10,9 +10,9 @@ import ( "path/filepath" "time" - "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/rpcclient" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) func main() { diff --git a/rpcclient/examples/btcwalletwebsockets/README.md b/rpcclient/examples/btcwalletwebsockets/README.md index e495dff80a..bb07bf1579 100644 --- a/rpcclient/examples/btcwalletwebsockets/README.md +++ b/rpcclient/examples/btcwalletwebsockets/README.md @@ -14,7 +14,7 @@ demonstrate clean shutdown. The first step is to use `go get` to download and install the rpcclient package: ```bash -$ go get github.com/btcsuite/btcd/rpcclient +$ go get github.com/roasbeef/btcd/rpcclient ``` Next, modify the `main.go` source to specify the correct RPC username and @@ -28,7 +28,7 @@ password for the RPC server: Finally, navigate to the example's directory and run it with: ```bash -$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/btcwalletwebsockets +$ cd $GOPATH/src/github.com/roasbeef/btcd/rpcclient/examples/btcwalletwebsockets $ go run *.go ``` diff --git a/rpcclient/examples/btcwalletwebsockets/main.go b/rpcclient/examples/btcwalletwebsockets/main.go index e803138d64..4d31443d2a 100644 --- a/rpcclient/examples/btcwalletwebsockets/main.go +++ b/rpcclient/examples/btcwalletwebsockets/main.go @@ -10,8 +10,8 @@ import ( "path/filepath" "time" - "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/rpcclient" + "github.com/roasbeef/btcutil" "github.com/davecgh/go-spew/spew" ) diff --git a/rpcclient/extensions.go b/rpcclient/extensions.go index d16cd5252e..1ceb16c473 100644 --- a/rpcclient/extensions.go +++ b/rpcclient/extensions.go @@ -12,10 +12,10 @@ import ( "encoding/json" "fmt" - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/btcjson" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) // FutureDebugLevelResult is a future promise to deliver the result of a diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 27f7f21f1b..9c6b790b05 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -23,7 +23,7 @@ import ( "sync/atomic" "time" - "github.com/btcsuite/btcd/btcjson" + "github.com/roasbeef/btcd/btcjson" "github.com/btcsuite/go-socks/socks" "github.com/btcsuite/websocket" ) diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 76a9d30580..5994f2a8dd 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -9,9 +9,9 @@ import ( "encoding/json" "errors" - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/btcjson" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcutil" ) // FutureGenerateResult is a future promise to deliver the result of a diff --git a/rpcclient/net.go b/rpcclient/net.go index aeda8b3c59..42d882b2cd 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -7,7 +7,7 @@ package rpcclient import ( "encoding/json" - "github.com/btcsuite/btcd/btcjson" + "github.com/roasbeef/btcd/btcjson" ) // AddNodeCommand enumerates the available commands that the AddNode function diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 2454a94696..0b15619455 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -13,10 +13,10 @@ import ( "fmt" "time" - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/btcjson" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) var ( diff --git a/rpcclient/rawrequest.go b/rpcclient/rawrequest.go index dd16fd049e..f8a6494fb1 100644 --- a/rpcclient/rawrequest.go +++ b/rpcclient/rawrequest.go @@ -8,7 +8,7 @@ import ( "encoding/json" "errors" - "github.com/btcsuite/btcd/btcjson" + "github.com/roasbeef/btcd/btcjson" ) // FutureRawResult is a future promise to deliver the result of a RawRequest RPC diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index e886f2250d..605678ccce 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -9,10 +9,10 @@ import ( "encoding/hex" "encoding/json" - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/btcjson" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) // SigHashType enumerates the available signature hashing types that the diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 10c12f1f70..9c7b291d33 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -8,11 +8,11 @@ import ( "encoding/json" "strconv" - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/btcjson" + "github.com/roasbeef/btcd/chaincfg" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) // ***************************** diff --git a/txscript/hashcache_test.go b/txscript/hashcache_test.go index 389918e2f2..09814bdfcc 100644 --- a/txscript/hashcache_test.go +++ b/txscript/hashcache_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/wire" + "github.com/roasbeef/btcd/wire" "github.com/davecgh/go-spew/spew" ) diff --git a/txscript/script.go b/txscript/script.go index 29f1e4d906..aac3d4aaaa 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -424,19 +424,6 @@ func calcHashOutputs(tx *wire.MsgTx) chainhash.Hash { return chainhash.DoubleHashH(b.Bytes()) } -// CalcWitnessSigHash exports calcWitnessSignatureHash so that signatures -// can be verified. -func CalcWitnessSigHash(subScript []byte, sigHashes *TxSigHashes, - hashType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { - parsedScript, err := parseScript(subScript) - if err != nil { - return nil, fmt.Errorf("cannot parse output script: %v", err) - } - sighash := calcWitnessSignatureHash( - parsedScript, sigHashes, hashType, tx, idx, amt) - return sighash, nil -} - // calcWitnessSignatureHash computes the sighash digest of a transaction's // segwit input using the new, optimized digest calculation algorithm defined // in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. diff --git a/txscript/script_test.go b/txscript/script_test.go index 6a725e275c..4abf3d786a 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -9,7 +9,7 @@ import ( "reflect" "testing" - "github.com/btcsuite/btcd/wire" + "github.com/roasbeef/btcd/wire" ) // TestParseOpcode tests for opcode parsing with bad data templates. From 7c2f7be2ea86d6740fd15e9ac7f336be38dba265 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 24 Aug 2017 16:29:57 -0700 Subject: [PATCH 0126/1056] wire: update compact filter messages to match wire.Message interface --- wire/README.md | 1 + wire/msgcfheaders.go | 6 +++--- wire/msgcfilter.go | 6 +++--- wire/msggetcfheaders.go | 4 ++-- wire/msggetcfilter.go | 4 ++-- wire/protocol_test.go | 3 +-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/wire/README.md b/wire/README.md index a720b644c4..646bc0a309 100644 --- a/wire/README.md +++ b/wire/README.md @@ -4,6 +4,7 @@ wire [![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/wire) +======= Package wire implements the bitcoin wire protocol. A comprehensive suite of tests with 100% test coverage is provided to ensure proper functionality. diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index aa26f01470..43676bba19 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -46,7 +46,7 @@ func (msg *MsgCFHeaders) AddCFHeader(headerHash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. -func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { +func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { // Read stop hash err := readElement(r, &msg.StopHash) if err != nil { @@ -90,7 +90,7 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. -func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32) error { +func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { // Write stop hash err := writeElement(w, msg.StopHash) if err != nil { @@ -140,7 +140,7 @@ func (msg *MsgCFHeaders) Deserialize(r io.Reader) error { // At the current time, there is no difference between the wire encoding // and the stable long-term storage format. As a result, make use of // BtcDecode. - return msg.BtcDecode(r, 0) + return msg.BtcDecode(r, 0, BaseEncoding) } // Command returns the protocol command string for the message. This is part diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index ed5c1fa1dc..d48065eb9b 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -24,7 +24,7 @@ type MsgCFilter struct { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. -func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32) error { +func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { var err error // Read the hash of the filter's block err = readElement(r, &msg.BlockHash) @@ -44,7 +44,7 @@ func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. -func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32) error { +func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { size := len(msg.Data) if size > MaxCFilterDataSize { str := fmt.Sprintf("cfilter size too large for message "+ @@ -78,7 +78,7 @@ func (msg *MsgCFilter) Deserialize(r io.Reader) error { // At the current time, there is no difference between the wire encoding // and the stable long-term storage format. As a result, make use of // BtcDecode. - return msg.BtcDecode(r, 0) + return msg.BtcDecode(r, 0, BaseEncoding) } // Command returns the protocol command string for the message. This is part diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index e66331c100..97df30d7ae 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -35,7 +35,7 @@ func (msg *MsgGetCFHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. -func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32) error { +func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { err := readElement(r, &msg.ProtocolVersion) if err != nil { return err @@ -75,7 +75,7 @@ func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. -func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32) error { +func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { // Limit to max block locator hashes per message. count := len(msg.BlockLocatorHashes) if count > MaxBlockLocatorsPerMsg { diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index f3ae5c9117..89dd5100e3 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -15,7 +15,7 @@ type MsgGetCFilter struct { Extended bool } -func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error { +func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { err := readElement(r, &msg.BlockHash) if err != nil { return err @@ -25,7 +25,7 @@ func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error { // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. -func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32) error { +func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { err := writeElement(w, &msg.BlockHash) if err != nil { return err diff --git a/wire/protocol_test.go b/wire/protocol_test.go index 9a968f5758..639dcc9fe8 100644 --- a/wire/protocol_test.go +++ b/wire/protocol_test.go @@ -17,9 +17,8 @@ func TestServiceFlagStringer(t *testing.T) { {SFNodeGetUTXO, "SFNodeGetUTXO"}, {SFNodeBloom, "SFNodeBloom"}, {SFNodeWitness, "SFNodeWitness"}, - {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|0xfffffff0"}, {SFNodeCF, "SFNodeCF"}, - {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeCF|0xfffffff0"}, + {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|SFNodeCF|0xffffffe0"}, } t.Logf("Running %d tests", len(tests)) From c8fdf8bf5960630d4619dde7987e65f1601e5f3b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 24 Aug 2017 16:30:18 -0700 Subject: [PATCH 0127/1056] rpcclient: add GetCFilterHeader and GetCFilter --- rpcclient/chain.go | 115 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 3 deletions(-) diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 2539bc80cb..ff34423932 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -10,9 +10,9 @@ import ( "encoding/hex" "encoding/json" - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" + "github.com/roasbeef/btcd/btcjson" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/wire" ) // FutureGetBestBlockHashResult is a future promise to deliver the result of a @@ -781,3 +781,112 @@ func (c *Client) InvalidateBlockAsync(blockHash *chainhash.Hash) FutureInvalidat func (c *Client) InvalidateBlock(blockHash *chainhash.Hash) error { return c.InvalidateBlockAsync(blockHash).Receive() } + +// FutureGetCFilterResult is a future promise to deliver the result of a +// GetCFilterAsync RPC invocation (or an applicable error). +type FutureGetCFilterResult chan *response + +// Receive waits for the response promised by the future and returns the raw +// filter requested from the server given its block hash. +func (r FutureGetCFilterResult) Receive() (*wire.MsgCFilter, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a string. + var filterHex string + err = json.Unmarshal(res, &filterHex) + if err != nil { + return nil, err + } + + // Decode the serialized cf hex to raw bytes. + serializedFilter, err := hex.DecodeString(filterHex) + if err != nil { + return nil, err + } + + // Assign the filter bytes to the correct field of the wire message. + // We aren't going to set the block hash or extended flag, since we + // don't actually get that back in the RPC response. + var msgCFilter wire.MsgCFilter + msgCFilter.Data = serializedFilter + return &msgCFilter, nil +} + +// GetCFilterAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetCFilter for the blocking version and more details. +func (c *Client) GetCFilterAsync(blockHash *chainhash.Hash, extended bool) FutureGetCFilterResult { + hash := "" + if blockHash != nil { + hash = blockHash.String() + } + + cmd := btcjson.NewGetCFilterCmd(hash, extended) + return c.sendCmd(cmd) +} + +// GetCFilter returns a raw filter from the server given its block hash. +func (c *Client) GetCFilter(blockHash *chainhash.Hash, extended bool) (*wire.MsgCFilter, error) { + return c.GetCFilterAsync(blockHash, extended).Receive() +} + +// FutureGetCFilterHeaderResult is a future promise to deliver the result of a +// GetCFilterHeaderAsync RPC invocation (or an applicable error). +type FutureGetCFilterHeaderResult chan *response + +// Receive waits for the response promised by the future and returns the raw +// filter header requested from the server given its block hash. +func (r FutureGetCFilterHeaderResult) Receive() (*wire.MsgCFHeaders, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a string. + var headerHex string + err = json.Unmarshal(res, &headerHex) + if err != nil { + return nil, err + } + + // Assign the decoded header into a hash + headerHash, err := chainhash.NewHashFromStr(headerHex) + if err != nil { + return nil, err + } + + // Assign the hash to a headers message and return it. + var msgCFHeaders wire.MsgCFHeaders + err = msgCFHeaders.AddCFHeader(headerHash) + if err != nil { + return nil, err + } + return &msgCFHeaders, nil + +} + +// GetCFilterHeaderAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function +// on the returned instance. +// +// See GetCFilterHeader for the blocking version and more details. +func (c *Client) GetCFilterHeaderAsync(blockHash *chainhash.Hash, extended bool) FutureGetCFilterHeaderResult { + hash := "" + if blockHash != nil { + hash = blockHash.String() + } + + cmd := btcjson.NewGetCFilterHeaderCmd(hash, extended) + return c.sendCmd(cmd) +} + +// GetCFilterHeader returns a raw filter header from the server given its block +// hash. +func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash, extended bool) (*wire.MsgCFHeaders, error) { + return c.GetCFilterHeaderAsync(blockHash, extended).Receive() +} From 5ab49ca22cd3a6901121d7ecbe8e72809b6faa96 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 24 Aug 2017 16:30:34 -0700 Subject: [PATCH 0128/1056] rpc: add indexers.CfIndex to config, utilize --- rpcserver.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 7c0ee34443..eeb5f5351c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2156,7 +2156,7 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return nil, rpcDecodeHexError(c.Hash) } - filterBytes, err := s.server.cfIndex.FilterByBlockHash(hash, c.Extended) + filterBytes, err := s.cfg.CfIndex.FilterByBlockHash(hash, c.Extended) if err != nil { rpcsLog.Debugf("Could not find committed filter for %v: %v", hash, err) @@ -2178,7 +2178,7 @@ func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan stru return nil, rpcDecodeHexError(c.Hash) } - headerBytes, err := s.server.cfIndex.FilterHeaderByBlockHash(hash, c.Extended) + headerBytes, err := s.cfg.CfIndex.FilterHeaderByBlockHash(hash, c.Extended) if len(headerBytes) > 0 { rpcsLog.Debugf("Found header of committed filter for %v", hash) } else { @@ -4232,6 +4232,7 @@ type rpcserverConfig struct { // of to provide additional data when queried. TxIndex *indexers.TxIndex AddrIndex *indexers.AddrIndex + CfIndex *indexers.CfIndex } // newRPCServer returns a new instance of the rpcServer struct. From 09723f48005e84724a857497cff4b7dd60d5fa87 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 29 Aug 2017 15:23:44 -0600 Subject: [PATCH 0129/1056] btcjson: add ErrRPCNoCFIndex for cases when cfindex is disabled --- btcjson/jsonrpcerr.go | 1 + 1 file changed, 1 insertion(+) diff --git a/btcjson/jsonrpcerr.go b/btcjson/jsonrpcerr.go index b3a48c0d37..c9431c5a96 100644 --- a/btcjson/jsonrpcerr.go +++ b/btcjson/jsonrpcerr.go @@ -71,6 +71,7 @@ const ( ErrRPCDifficulty RPCErrorCode = -5 ErrRPCOutOfRange RPCErrorCode = -1 ErrRPCNoTxInfo RPCErrorCode = -5 + ErrRPCNoCFIndex RPCErrorCode = -5 ErrRPCNoNewestBlockInfo RPCErrorCode = -5 ErrRPCInvalidTxVout RPCErrorCode = -5 ErrRPCRawTxString RPCErrorCode = -32602 From ac109cfb86e44df4c036b9eed6f5bdd7ce8baf35 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 29 Aug 2017 16:03:40 -0600 Subject: [PATCH 0130/1056] rpcserver: return correct error when --nocfilters is enabled --- rpcserver.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index eeb5f5351c..f6729d003e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2150,6 +2150,13 @@ func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan stru // handleGetCFilter implements the getcfilter command. func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + if s.cfg.CfIndex == nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCNoCFIndex, + Message: "The CF index must be enabled for this command", + } + } + c := cmd.(*btcjson.GetCFilterCmd) hash, err := chainhash.NewHashFromStr(c.Hash) if err != nil { @@ -2172,6 +2179,13 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) // handleGetCFilterHeader implements the getcfilterheader command. func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + if s.cfg.CfIndex == nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCNoCFIndex, + Message: "The CF index must be enabled for this command", + } + } + c := cmd.(*btcjson.GetCFilterHeaderCmd) hash, err := chainhash.NewHashFromStr(c.Hash) if err != nil { From c5c392c5c5647dd88b1c797f7b31c8933b560164 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 29 Aug 2017 16:04:04 -0600 Subject: [PATCH 0131/1056] server: init rpcserver with cfindex --- server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server.go b/server.go index efbb978442..0ef9c8ecc7 100644 --- a/server.go +++ b/server.go @@ -2564,6 +2564,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param CPUMiner: s.cpuMiner, TxIndex: s.txIndex, AddrIndex: s.addrIndex, + CfIndex: s.cfIndex, }) if err != nil { return nil, err From 8aeb8c3ef2b7c8c03f041c438c12d61d4c8fdb14 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 13 Oct 2017 14:22:07 -0700 Subject: [PATCH 0132/1056] peer: temporarily disable stall detection --- peer/peer.go | 1 + 1 file changed, 1 insertion(+) diff --git a/peer/peer.go b/peer/peer.go index 9a06774baa..ec84a0a08b 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1401,6 +1401,7 @@ out: continue } + continue log.Debugf("Peer %s appears to be stalled or "+ "misbehaving, %s timeout -- "+ "disconnecting", p, command) From 6cea6107741134bee1130f6f48156a64302fb20b Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 25 Oct 2017 17:09:53 -0600 Subject: [PATCH 0133/1056] integration/rpctest: queue block disconnected ntfns in memwallet --- integration/rpctest/memwallet.go | 81 +++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/integration/rpctest/memwallet.go b/integration/rpctest/memwallet.go index 9b2999f38c..0dccde10aa 100644 --- a/integration/rpctest/memwallet.go +++ b/integration/rpctest/memwallet.go @@ -56,6 +56,7 @@ func (u *utxo) isMature(height int32) bool { type chainUpdate struct { blockHeight int32 filteredTxns []*btcutil.Tx + isConnect bool // True if connect, false if disconnect } // undoEntry is functionally the opposite of a chainUpdate. An undoEntry is @@ -176,13 +177,14 @@ func (m *memWallet) SetRPCClient(rpcClient *rpcclient.Client) { } // IngestBlock is a call-back which is to be triggered each time a new block is -// connected to the main chain. Ingesting a block updates the wallet's internal -// utxo state based on the outputs created and destroyed within each block. +// connected to the main chain. It queues the update for the chain syncer, +// calling the private version in sequential order. func (m *memWallet) IngestBlock(height int32, header *wire.BlockHeader, filteredTxns []*btcutil.Tx) { // Append this new chain update to the end of the queue of new chain // updates. m.chainMtx.Lock() - m.chainUpdates = append(m.chainUpdates, &chainUpdate{height, filteredTxns}) + m.chainUpdates = append(m.chainUpdates, &chainUpdate{height, + filteredTxns, true}) m.chainMtx.Unlock() // Launch a goroutine to signal the chainSyncer that a new update is @@ -193,6 +195,30 @@ func (m *memWallet) IngestBlock(height int32, header *wire.BlockHeader, filtered }() } +// ingestBlock updates the wallet's internal utxo state based on the outputs +// created and destroyed within each block. +func (m *memWallet) ingestBlock(update *chainUpdate) { + // Update the latest synced height, then process each filtered + // transaction in the block creating and destroying utxos within + // the wallet as a result. + m.currentHeight = update.blockHeight + undo := &undoEntry{ + utxosDestroyed: make(map[wire.OutPoint]*utxo), + } + for _, tx := range update.filteredTxns { + mtx := tx.MsgTx() + isCoinbase := blockchain.IsCoinBaseTx(mtx) + txHash := mtx.TxHash() + m.evalOutputs(mtx.TxOut, &txHash, isCoinbase, undo) + m.evalInputs(mtx.TxIn, undo) + } + + // Finally, record the undo entry for this block so we can + // properly update our internal state in response to the block + // being re-org'd from the main chain. + m.reorgJournal[update.blockHeight] = undo +} + // chainSyncer is a goroutine dedicated to processing new blocks in order to // keep the wallet's utxo state up to date. // @@ -209,26 +235,12 @@ func (m *memWallet) chainSyncer() { m.chainUpdates = m.chainUpdates[1:] m.chainMtx.Unlock() - // Update the latest synced height, then process each filtered - // transaction in the block creating and destroying utxos within - // the wallet as a result. m.Lock() - m.currentHeight = update.blockHeight - undo := &undoEntry{ - utxosDestroyed: make(map[wire.OutPoint]*utxo), - } - for _, tx := range update.filteredTxns { - mtx := tx.MsgTx() - isCoinbase := blockchain.IsCoinBaseTx(mtx) - txHash := mtx.TxHash() - m.evalOutputs(mtx.TxOut, &txHash, isCoinbase, undo) - m.evalInputs(mtx.TxIn, undo) + if update.isConnect { + m.ingestBlock(update) + } else { + m.unwindBlock(update) } - - // Finally, record the undo entry for this block so we can - // properly update our internal state in response to the block - // being re-org'd from the main chain. - m.reorgJournal[update.blockHeight] = undo m.Unlock() } } @@ -285,13 +297,28 @@ func (m *memWallet) evalInputs(inputs []*wire.TxIn, undo *undoEntry) { } // UnwindBlock is a call-back which is to be executed each time a block is -// disconnected from the main chain. Unwinding a block undoes the effect that a -// particular block had on the wallet's internal utxo state. +// disconnected from the main chain. It queues the update for the chain syncer, +// calling the private version in sequential order. func (m *memWallet) UnwindBlock(height int32, header *wire.BlockHeader) { - m.Lock() - defer m.Unlock() + // Append this new chain update to the end of the queue of new chain + // updates. + m.chainMtx.Lock() + m.chainUpdates = append(m.chainUpdates, &chainUpdate{height, + nil, false}) + m.chainMtx.Unlock() + + // Launch a goroutine to signal the chainSyncer that a new update is + // available. We do this in a new goroutine in order to avoid blocking + // the main loop of the rpc client. + go func() { + m.chainUpdateSignal <- struct{}{} + }() +} - undo := m.reorgJournal[height] +// unwindBlock undoes the effect that a particular block had on the wallet's +// internal utxo state. +func (m *memWallet) unwindBlock(update *chainUpdate) { + undo := m.reorgJournal[update.blockHeight] for _, utxo := range undo.utxosCreated { delete(m.utxos, utxo) @@ -301,7 +328,7 @@ func (m *memWallet) UnwindBlock(height int32, header *wire.BlockHeader) { m.utxos[outPoint] = utxo } - delete(m.reorgJournal, height) + delete(m.reorgJournal, update.blockHeight) } // newAddress returns a new address from the wallet's hd key chain. It also From e2f65acf023f5bd36c6eea1c1825d61b69aa9a1c Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 25 Oct 2017 17:53:50 -0600 Subject: [PATCH 0134/1056] integration/rpctest: check `quit` in `solveBlock()`'s `solver()` closure --- integration/rpctest/blockgen.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/integration/rpctest/blockgen.go b/integration/rpctest/blockgen.go index 6c7218f776..de5821b0c1 100644 --- a/integration/rpctest/blockgen.go +++ b/integration/rpctest/blockgen.go @@ -45,12 +45,20 @@ func solveBlock(header *wire.BlockHeader, targetDifficulty *big.Int) bool { hdr.Nonce = i hash := hdr.BlockHash() if blockchain.HashToBig(&hash).Cmp(targetDifficulty) <= 0 { - results <- sbResult{true, i} - return + select { + case results <- sbResult{true, i}: + return + case <-quit: + return + } } } } - results <- sbResult{false, 0} + select { + case results <- sbResult{false, 0}: + case <-quit: + return + } } startNonce := uint32(0) From 621c73dad189b1e5ae2d308ee020aae94e5b25bd Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 13 Sep 2017 14:42:24 +0200 Subject: [PATCH 0135/1056] multi: change cfilter `Extended` bool to `FilterType` uint8 The cfilter BIP specifies that the filter type is a uint8. The current code encodes it correctly on the wire, but everywhere else, it's treated as a boolean (false for basic filter, true for extended). This commit corrects that to account for possible additional filter types in the future. All package changes are done in one commit as they're all interdependent. The following packages are updated: * blockchain/indexers * btcjson * peer * wire * main (server.go and rpcserver.go) --- blockchain/indexers/cfindex.go | 112 +++++++++++++++++---------------- btcjson/chainsvrcmds.go | 21 ++++--- btcjson/chainsvrcmds_test.go | 12 ++-- peer/peer_test.go | 4 +- rpcserver.go | 4 +- server.go | 12 ++-- wire/message_test.go | 4 +- wire/msgcfheaders.go | 10 +-- wire/msgcfilter.go | 20 +++--- wire/msggetcfheaders.go | 12 ++-- wire/msggetcfilter.go | 16 ++--- 11 files changed, 116 insertions(+), 111 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index d89013a0fd..0e7d3bbf92 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -30,21 +30,21 @@ var ( // the index. The rest of the buckets live below this bucket. cfIndexParentBucketKey = []byte("cfindexparentbucket") - // cfBasicIndexKey is the name of the db bucket used to house the - // block hash -> basic cf index (cf#0). - cfBasicIndexKey = []byte("cf0byhashidx") - - // cfBasicHeaderKey is the name of the db bucket used to house the - // block hash -> basic cf header index (cf#0). - cfBasicHeaderKey = []byte("cf0headerbyhashidx") + // cfIndexKeys is an array of db bucket names used to house indexes of + // block hashes to cfilters. + cfIndexKeys = [][]byte{ + []byte("cf0byhashidx"), + []byte("cf1byhashidx"), + } - // cfExtendedIndexKey is the name of the db bucket used to house the - // block hash -> extended cf index (cf#1). - cfExtendedIndexKey = []byte("cf1byhashidx") + // cfHeaderKeys is an array of db bucket names used to house indexes of + // block hashes to cf headers. + cfHeaderKeys = [][]byte{ + []byte("cf0headerbyhashidx"), + []byte("cf1headerbyhashidx"), + } - // cfExtendedHeaderKey is the name of the db bucket used to house the - // block hash -> extended cf header index (cf#1). - cfExtendedHeaderKey = []byte("cf1headerbyhashidx") + maxFilterType = uint8(len(cfHeaderKeys) - 1) ) // dbFetchFilter retrieves a block's basic or extended filter. A filter's @@ -131,27 +131,25 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { if err != nil { return err } - _, err = cfIndexParentBucket.CreateBucket(cfBasicIndexKey) - if err != nil { - return err - } - _, err = cfIndexParentBucket.CreateBucket(cfBasicHeaderKey) - if err != nil { - return err - } - _, err = cfIndexParentBucket.CreateBucket(cfExtendedIndexKey) - if err != nil { - return err + + for _, bucketName := range cfIndexKeys { + _, err = cfIndexParentBucket.CreateBucket(bucketName) + if err != nil { + return err + } } - _, err = cfIndexParentBucket.CreateBucket(cfExtendedHeaderKey) - if err != nil { - return err + + for _, bucketName := range cfHeaderKeys { + _, err = cfIndexParentBucket.CreateBucket(bucketName) + if err != nil { + return err + } } firstHeader := make([]byte, chainhash.HashSize) err = dbStoreFilterHeader( dbTx, - cfBasicHeaderKey, + cfHeaderKeys[0], &idx.chainParams.GenesisBlock.Header.PrevBlock, firstHeader, ) @@ -161,7 +159,7 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { return dbStoreFilterHeader( dbTx, - cfExtendedHeaderKey, + cfHeaderKeys[1], &idx.chainParams.GenesisBlock.Header.PrevBlock, firstHeader, ) @@ -170,15 +168,14 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { // storeFilter stores a given filter, and performs the steps needed to // generate the filter's header. func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, - extended bool) error { + filterType uint8) error { + if filterType > maxFilterType { + return errors.New("unsupported filter type") + } // Figure out which buckets to use. - fkey := cfBasicIndexKey - hkey := cfBasicHeaderKey - if extended { - fkey = cfExtendedIndexKey - hkey = cfExtendedHeaderKey - } + fkey := cfIndexKeys[filterType] + hkey := cfHeaderKeys[filterType] // Start by storing the filter. h := block.Hash() @@ -218,7 +215,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return err } - if err := storeFilter(dbTx, block, f, false); err != nil { + if err := storeFilter(dbTx, block, f, 0); err != nil { return err } @@ -227,7 +224,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return err } - return storeFilter(dbTx, block, f, true) + return storeFilter(dbTx, block, f, 1) } // DisconnectBlock is invoked by the index manager when a block has been @@ -236,26 +233,34 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { - err := dbDeleteFilter(dbTx, cfBasicIndexKey, block.Hash()) - if err != nil { - return err + for _, key := range cfIndexKeys { + err := dbDeleteFilter(dbTx, key, block.Hash()) + if err != nil { + return err + } } - return dbDeleteFilter(dbTx, cfExtendedIndexKey, block.Hash()) + for _, key := range cfHeaderKeys { + err := dbDeleteFilterHeader(dbTx, key, block.Hash()) + if err != nil { + return err + } + } + + return nil } // FilterByBlockHash returns the serialized contents of a block's basic or // extended committed filter. -func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { +func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, filterType uint8) ([]byte, error) { var f []byte err := idx.db.View(func(dbTx database.Tx) error { - var err error - key := cfBasicIndexKey - if extended { - key = cfExtendedIndexKey + if filterType > maxFilterType { + return errors.New("unsupported filter type") } - f, err = dbFetchFilter(dbTx, key, h) + var err error + f, err = dbFetchFilter(dbTx, cfIndexKeys[filterType], h) return err }) return f, err @@ -263,16 +268,15 @@ func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, extended bool) ([]byte, // FilterHeaderByBlockHash returns the serialized contents of a block's basic // or extended committed filter header. -func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, extended bool) ([]byte, error) { +func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, filterType uint8) ([]byte, error) { var fh []byte err := idx.db.View(func(dbTx database.Tx) error { - var err error - key := cfBasicHeaderKey - if extended { - key = cfExtendedHeaderKey + if filterType > 1 { + return errors.New("unsupported filter type") } - fh, err = dbFetchFilterHeader(dbTx, key, h) + var err error + fh, err = dbFetchFilterHeader(dbTx, cfHeaderKeys[filterType], h) return err }) return fh, err diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index f399397597..e7d736f0d4 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -278,33 +278,34 @@ func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd { Request: request, } } + // GetCFilterCmd defines the getcfilter JSON-RPC command. type GetCFilterCmd struct { - Hash string - Extended bool + Hash string + FilterType uint8 } // NewGetCFilterCmd returns a new instance which can be used to issue a // getcfilter JSON-RPC command. -func NewGetCFilterCmd(hash string, extended bool) *GetCFilterCmd { +func NewGetCFilterCmd(hash string, filterType uint8) *GetCFilterCmd { return &GetCFilterCmd{ - Hash: hash, - Extended: extended, + Hash: hash, + FilterType: filterType, } } // GetCFilterHeaderCmd defines the getcfilterheader JSON-RPC command. type GetCFilterHeaderCmd struct { - Hash string - Extended bool + Hash string + FilterType uint8 } // NewGetCFilterHeaderCmd returns a new instance which can be used to issue a // getcfilterheader JSON-RPC command. -func NewGetCFilterHeaderCmd(hash string, extended bool) *GetCFilterHeaderCmd { +func NewGetCFilterHeaderCmd(hash string, filterType uint8) *GetCFilterHeaderCmd { return &GetCFilterHeaderCmd{ - Hash: hash, - Extended: extended, + Hash: hash, + FilterType: filterType, } } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 1b2c33e707..cb284a4aed 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -320,27 +320,27 @@ func TestChainSvrCmds(t *testing.T) { { name: "getcfilter", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getcfilter", "123", false) + return btcjson.NewCmd("getcfilter", "123", 0) }, staticCmd: func() interface{} { - return btcjson.NewGetCFilterCmd("123", false) + return btcjson.NewGetCFilterCmd("123", 0) }, marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",false],"id":1}`, unmarshalled: &btcjson.GetCFilterCmd{ - Hash: "123", + Hash: "123", }, }, { name: "getcfilterheader", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getcfilterheader", "123", false) + return btcjson.NewCmd("getcfilterheader", "123", 0) }, staticCmd: func() interface{} { - return btcjson.NewGetCFilterHeaderCmd("123", false) + return btcjson.NewGetCFilterHeaderCmd("123", 0) }, marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",false],"id":1}`, unmarshalled: &btcjson.GetCFilterHeaderCmd{ - Hash: "123", + Hash: "123", }, }, { diff --git a/peer/peer_test.go b/peer/peer_test.go index acab18bb88..701df7441f 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -536,7 +536,7 @@ func TestPeerListeners(t *testing.T) { }, { "OnGetCFilter", - wire.NewMsgGetCFilter(&chainhash.Hash{}, false), + wire.NewMsgGetCFilter(&chainhash.Hash{}, 0), }, { "OnGetCFHeaders", @@ -544,7 +544,7 @@ func TestPeerListeners(t *testing.T) { }, { "OnCFilter", - wire.NewMsgCFilter(&chainhash.Hash{}, true, + wire.NewMsgCFilter(&chainhash.Hash{}, 1, []byte("payload")), }, { diff --git a/rpcserver.go b/rpcserver.go index f6729d003e..b10d5287b2 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2163,7 +2163,7 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return nil, rpcDecodeHexError(c.Hash) } - filterBytes, err := s.cfg.CfIndex.FilterByBlockHash(hash, c.Extended) + filterBytes, err := s.cfg.CfIndex.FilterByBlockHash(hash, c.FilterType) if err != nil { rpcsLog.Debugf("Could not find committed filter for %v: %v", hash, err) @@ -2192,7 +2192,7 @@ func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan stru return nil, rpcDecodeHexError(c.Hash) } - headerBytes, err := s.cfg.CfIndex.FilterHeaderByBlockHash(hash, c.Extended) + headerBytes, err := s.cfg.CfIndex.FilterHeaderByBlockHash(hash, c.FilterType) if len(headerBytes) > 0 { rpcsLog.Debugf("Found header of committed filter for %v", hash) } else { diff --git a/server.go b/server.go index 0ef9c8ecc7..272904afa4 100644 --- a/server.go +++ b/server.go @@ -747,7 +747,7 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { } filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash, - msg.Extended) + msg.FilterType) if len(filterBytes) > 0 { peerLog.Tracef("Obtained CF for %v", msg.BlockHash) @@ -756,7 +756,7 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { err) } - filterMsg := wire.NewMsgCFilter(&msg.BlockHash, msg.Extended, + filterMsg := wire.NewMsgCFilter(&msg.BlockHash, msg.FilterType, filterBytes) sp.QueueMessage(filterMsg, nil) } @@ -789,7 +789,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { // Fetch the raw committed filter header bytes from the // database. headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( - &msg.HashStop, msg.Extended) + &msg.HashStop, msg.FilterType) if (err != nil) || (len(headerBytes) == 0) { peerLog.Warnf("Could not obtain CF header for %v: %v", msg.HashStop, err) @@ -808,7 +808,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { headersMsg := wire.NewMsgCFHeaders() headersMsg.AddCFHeader(&header) headersMsg.StopHash = msg.HashStop - headersMsg.Extended = msg.Extended + headersMsg.FilterType = msg.FilterType sp.QueueMessage(headersMsg, nil) return } @@ -849,7 +849,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { // Fetch the raw committed filter header bytes from the // database. headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( - &hashList[i], msg.Extended) + &hashList[i], msg.FilterType) if (err != nil) || (len(headerBytes) == 0) { peerLog.Warnf("Could not obtain CF header for %v: %v", hashList[i], err) @@ -868,7 +868,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { headersMsg.AddCFHeader(&header) } - headersMsg.Extended = msg.Extended + headersMsg.FilterType = msg.FilterType headersMsg.StopHash = hashList[len(hashList)-1] sp.QueueMessage(headersMsg, nil) } diff --git a/wire/message_test.go b/wire/message_test.go index 88533f4d69..6bf7fd2b47 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -69,9 +69,9 @@ func TestMessage(t *testing.T) { bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0) msgMerkleBlock := NewMsgMerkleBlock(bh) msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") - msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, false) + msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, 0) msgGetCFHeaders := NewMsgGetCFHeaders() - msgCFilter := NewMsgCFilter(&chainhash.Hash{}, true, []byte("payload")) + msgCFilter := NewMsgCFilter(&chainhash.Hash{}, 1, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() tests := []struct { diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 43676bba19..cb5ca76e58 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -28,7 +28,7 @@ const ( // MsgGetCFHeaders for details on requesting the headers. type MsgCFHeaders struct { StopHash chainhash.Hash - Extended bool + FilterType uint8 HeaderHashes []*chainhash.Hash } @@ -53,8 +53,8 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) return err } - // Read extended flag - err = readElement(r, &msg.Extended) + // Read filter type + err = readElement(r, &msg.FilterType) if err != nil { return err } @@ -97,8 +97,8 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) return err } - // Write extended flag - err = writeElement(w, msg.Extended) + // Write filter type + err = writeElement(w, msg.FilterType) if err != nil { return err } diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index d48065eb9b..048d4b9834 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -17,9 +17,9 @@ const ( ) type MsgCFilter struct { - BlockHash chainhash.Hash - Extended bool - Data []byte + BlockHash chainhash.Hash + FilterType uint8 + Data []byte } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. @@ -31,8 +31,8 @@ func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) er if err != nil { return err } - // Read extended flag - err = readElement(r, &msg.Extended) + // Read filter type + err = readElement(r, &msg.FilterType) if err != nil { return err } @@ -57,7 +57,7 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) er return err } - err = writeElement(w, msg.Extended) + err = writeElement(w, msg.FilterType) if err != nil { return err } @@ -96,11 +96,11 @@ func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 { // NewMsgCFilter returns a new bitcoin cfilter message that conforms to the // Message interface. See MsgCFilter for details. -func NewMsgCFilter(blockHash *chainhash.Hash, extended bool, +func NewMsgCFilter(blockHash *chainhash.Hash, filterType uint8, data []byte) *MsgCFilter { return &MsgCFilter{ - BlockHash: *blockHash, - Extended: extended, - Data: data, + BlockHash: *blockHash, + FilterType: filterType, + Data: data, } } diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index 97df30d7ae..e8b7f30cf0 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -12,13 +12,13 @@ import ( ) // MsgGetCFHeaders is a message similar to MsgGetHeaders, but for committed -// filter headers. It allows to set the Extended field to get headers in the -// chain of basic (false) or extended (true) headers. +// filter headers. It allows to set the FilterType field to get headers in the +// chain of basic (0x00) or extended (0x01) headers. type MsgGetCFHeaders struct { ProtocolVersion uint32 BlockLocatorHashes []*chainhash.Hash HashStop chainhash.Hash - Extended bool + FilterType uint8 } // AddBlockLocatorHash adds a new block locator hash to the message. @@ -70,7 +70,7 @@ func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncodin return err } - return readElement(r, &msg.Extended) + return readElement(r, &msg.FilterType) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -106,7 +106,7 @@ func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncodin return err } - return writeElement(w, msg.Extended) + return writeElement(w, msg.FilterType) } // Command returns the protocol command string for the message. This is part @@ -119,7 +119,7 @@ func (msg *MsgGetCFHeaders) Command() string { // receiver. This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) MaxPayloadLength(pver uint32) uint32 { // Version 4 bytes + num block locator hashes (varInt) + max allowed - // block locators + hash stop + Extended flag 1 byte. + // block locators + hash stop + filter type 1 byte. return 4 + MaxVarIntPayload + (MaxBlockLocatorsPerMsg * chainhash.HashSize) + chainhash.HashSize + 1 } diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index 89dd5100e3..85c351df16 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -11,8 +11,8 @@ import ( ) type MsgGetCFilter struct { - BlockHash chainhash.Hash - Extended bool + BlockHash chainhash.Hash + FilterType uint8 } func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { @@ -20,7 +20,7 @@ func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) if err != nil { return err } - return readElement(r, &msg.Extended) + return readElement(r, &msg.FilterType) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -30,7 +30,7 @@ func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) if err != nil { return err } - return writeElement(w, msg.Extended) + return writeElement(w, msg.FilterType) } // Command returns the protocol command string for the message. This is part @@ -42,16 +42,16 @@ func (msg *MsgGetCFilter) Command() string { // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { - // Block hash + Extended flag. + // Block hash + filter type. return chainhash.HashSize + 1 } // NewMsgGetCFilter returns a new bitcoin getcfilter message that conforms to // the Message interface using the passed parameters and defaults for the // remaining fields. -func NewMsgGetCFilter(blockHash *chainhash.Hash, extended bool) *MsgGetCFilter { +func NewMsgGetCFilter(blockHash *chainhash.Hash, filterType uint8) *MsgGetCFilter { return &MsgGetCFilter{ - BlockHash: *blockHash, - Extended: extended, + BlockHash: *blockHash, + FilterType: filterType, } } From 89d6696560347700cc42cabdbd8a8f9a26b53f58 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 13 Sep 2017 17:16:58 +0200 Subject: [PATCH 0136/1056] wire: add getcftypes and cftypes messages --- wire/message.go | 8 ++++ wire/message_test.go | 4 ++ wire/msgcftypes.go | 92 +++++++++++++++++++++++++++++++++++++++++++ wire/msggetcftypes.go | 42 ++++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 wire/msgcftypes.go create mode 100644 wire/msggetcftypes.go diff --git a/wire/message.go b/wire/message.go index 9a34a2fa54..4b47455337 100644 --- a/wire/message.go +++ b/wire/message.go @@ -53,8 +53,10 @@ const ( CmdFeeFilter = "feefilter" CmdGetCFilter = "getcfilter" CmdGetCFHeaders = "getcfheaders" + CmdGetCFTypes = "getcftypes" CmdCFilter = "cfilter" CmdCFHeaders = "cfheaders" + CmdCFTypes = "cftypes" ) // MessageEncoding represents the wire message encoding format to be used. @@ -166,12 +168,18 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFHeaders: msg = &MsgGetCFHeaders{} + case CmdGetCFTypes: + msg = &MsgGetCFTypes{} + case CmdCFilter: msg = &MsgCFilter{} case CmdCFHeaders: msg = &MsgCFHeaders{} + case CmdCFTypes: + msg = &MsgCFTypes{} + default: return nil, fmt.Errorf("unhandled command [%s]", command) } diff --git a/wire/message_test.go b/wire/message_test.go index 6bf7fd2b47..2be2a5a0dd 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -71,8 +71,10 @@ func TestMessage(t *testing.T) { msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, 0) msgGetCFHeaders := NewMsgGetCFHeaders() + msgGetCFTypes := NewMsgGetCFTypes() msgCFilter := NewMsgCFilter(&chainhash.Hash{}, 1, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() + msgCFTypes := NewMsgCFTypes([]uint8{2}) tests := []struct { in Message // Value to encode @@ -104,8 +106,10 @@ func TestMessage(t *testing.T) { {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 62}, + {msgGetCFTypes, msgGetCFTypes, pver, MainNet, 24}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, + {msgCFTypes, msgCFTypes, pver, MainNet, 26}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcftypes.go b/wire/msgcftypes.go new file mode 100644 index 0000000000..92a8f718a5 --- /dev/null +++ b/wire/msgcftypes.go @@ -0,0 +1,92 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import "io" + +// MsgCFTypes is the cftypes message. +type MsgCFTypes struct { + NumFilters uint8 + SupportedFilters []uint8 +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + // Read the number of filter types supported + err := readElement(r, &msg.NumFilters) + if err != nil { + return err + } + + // Read each filter type. + msg.SupportedFilters = make([]uint8, msg.NumFilters) + for i := uint8(0); i < msg.NumFilters; i++ { + err = readElement(r, &msg.SupportedFilters[i]) + if err != nil { + return err + } + } + + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgCFTypes) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + // Write length of supported filters slice; don't trust that the caller + // has set it correctly. + err := writeElement(w, uint8(len(msg.SupportedFilters))) + if err != nil { + return err + } + + for i := range msg.SupportedFilters { + err = writeElement(w, msg.SupportedFilters[i]) + if err != nil { + return err + } + } + + return nil +} + +// Deserialize decodes a filter from r into the receiver using a format that is +// suitable for long-term storage such as a database. This function differs +// from BtcDecode in that BtcDecode decodes from the bitcoin wire protocol as +// it was sent across the network. The wire encoding can technically differ +// depending on the protocol version and doesn't even really need to match the +// format of a stored filter at all. As of the time this comment was written, +// the encoded filter is the same in both instances, but there is a distinct +// difference and separating the two allows the API to be flexible enough to +// deal with changes. +func (msg *MsgCFTypes) Deserialize(r io.Reader) error { + // At the current time, there is no difference between the wire encoding + // and the stable long-term storage format. As a result, make use of + // BtcDecode. + return msg.BtcDecode(r, 0, BaseEncoding) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgCFTypes) Command() string { + return CmdCFTypes +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgCFTypes) MaxPayloadLength(pver uint32) uint32 { + // 1 byte for NumFilters, and 1 byte for up to 255 filter types. + return 256 +} + +// NewMsgCFTypes returns a new bitcoin cftypes message that conforms to the +// Message interface. See MsgCFTypes for details. +func NewMsgCFTypes(filterTypes []uint8) *MsgCFTypes { + return &MsgCFTypes{ + NumFilters: uint8(len(filterTypes)), + SupportedFilters: filterTypes, + } +} diff --git a/wire/msggetcftypes.go b/wire/msggetcftypes.go new file mode 100644 index 0000000000..304ce87bf3 --- /dev/null +++ b/wire/msggetcftypes.go @@ -0,0 +1,42 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import "io" + +// MsgGetCFTypes is the getcftypes message. +type MsgGetCFTypes struct { +} + +// BtcDecode decodes the receiver from w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFTypes) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + return nil +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCFTypes) Command() string { + return CmdGetCFTypes +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCFTypes) MaxPayloadLength(pver uint32) uint32 { + // Empty message. + return 0 +} + +// NewMsgGetCFTypes returns a new bitcoin getcftypes message that conforms to +// the Message interface. +func NewMsgGetCFTypes() *MsgGetCFTypes { + return &MsgGetCFTypes{} +} From 1aa7a6166db950e1c80a87fc776a2c98c2ecbae1 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Oct 2017 13:34:31 -0600 Subject: [PATCH 0137/1056] wire: update messages to conform to BIP and fix comments --- wire/message_test.go | 2 +- wire/msgcfheaders.go | 5 +++-- wire/msgcfilter.go | 9 ++++++--- wire/msggetcfheaders.go | 17 +++-------------- wire/msggetcfilter.go | 4 ++++ 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/wire/message_test.go b/wire/message_test.go index 2be2a5a0dd..7d8cf9ccdd 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -105,7 +105,7 @@ func TestMessage(t *testing.T) { {msgMerkleBlock, msgMerkleBlock, pver, MainNet, 110}, {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, - {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 62}, + {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 58}, {msgGetCFTypes, msgGetCFTypes, pver, MainNet, 24}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index cb5ca76e58..6e1ce2a5dd 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -150,9 +150,10 @@ func (msg *MsgCFHeaders) Command() string { } // MaxPayloadLength returns the maximum length the payload can be for the -// receiver. This is part of the Message interface implementation. +// receiver. This is part of the Message interface implementation. func (msg *MsgCFHeaders) MaxPayloadLength(pver uint32) uint32 { - // Hash size + num headers (varInt) + (header size * max headers). + // Hash size + filter type + num headers (varInt) + + // (header size * max headers). return chainhash.HashSize + 1 + MaxVarIntPayload + (MaxCFHeaderPayload * MaxCFHeadersPerMsg) } diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index 048d4b9834..22329938f1 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -13,9 +13,13 @@ import ( const ( // MaxCFilterDataSize is the maximum byte size of a committed filter. - MaxCFilterDataSize = 262144 + // The maximum size is currently defined as 256KiB. + MaxCFilterDataSize = 256 * 1024 ) +// MsgCFilter implements the Message interface and represents a bitcoin cfilter +// message. It is used to deliver a committed filter in response to a +// getcfilter (MsgGetCFilter) message. type MsgCFilter struct { BlockHash chainhash.Hash FilterType uint8 @@ -25,9 +29,8 @@ type MsgCFilter struct { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - var err error // Read the hash of the filter's block - err = readElement(r, &msg.BlockHash) + err := readElement(r, &msg.BlockHash) if err != nil { return err } diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index e8b7f30cf0..d82ddcc82f 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -15,7 +15,6 @@ import ( // filter headers. It allows to set the FilterType field to get headers in the // chain of basic (0x00) or extended (0x01) headers. type MsgGetCFHeaders struct { - ProtocolVersion uint32 BlockLocatorHashes []*chainhash.Hash HashStop chainhash.Hash FilterType uint8 @@ -36,11 +35,6 @@ func (msg *MsgGetCFHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - err := readElement(r, &msg.ProtocolVersion) - if err != nil { - return err - } - // Read num block locator hashes and limit to max. count, err := ReadVarInt(r, pver) if err != nil { @@ -84,12 +78,7 @@ func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncodin return messageError("MsgGetHeaders.BtcEncode", str) } - err := writeElement(w, msg.ProtocolVersion) - if err != nil { - return err - } - - err = WriteVarInt(w, pver, uint64(count)) + err := WriteVarInt(w, pver, uint64(count)) if err != nil { return err } @@ -118,9 +107,9 @@ func (msg *MsgGetCFHeaders) Command() string { // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) MaxPayloadLength(pver uint32) uint32 { - // Version 4 bytes + num block locator hashes (varInt) + max allowed + // Num block locator hashes (varInt) + max allowed // block locators + hash stop + filter type 1 byte. - return 4 + MaxVarIntPayload + (MaxBlockLocatorsPerMsg * + return MaxVarIntPayload + (MaxBlockLocatorsPerMsg * chainhash.HashSize) + chainhash.HashSize + 1 } diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index 85c351df16..8ba677f5a5 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -10,11 +10,15 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" ) +// MsgGetCFilter implements the Message interface and represents a bitcoin +// getcfilter message. It is used to request a committed filter for a block. type MsgGetCFilter struct { BlockHash chainhash.Hash FilterType uint8 } +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { err := readElement(r, &msg.BlockHash) if err != nil { From 5fb5acd6436f265b4aec21bfc1f7ed8b7cdd5b66 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Oct 2017 14:28:49 -0600 Subject: [PATCH 0138/1056] btcjson: fix cfilter tests --- btcjson/chainsvrcmds_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index cb284a4aed..27fb9d6eb4 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -325,7 +325,7 @@ func TestChainSvrCmds(t *testing.T) { staticCmd: func() interface{} { return btcjson.NewGetCFilterCmd("123", 0) }, - marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",false],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",0],"id":1}`, unmarshalled: &btcjson.GetCFilterCmd{ Hash: "123", }, @@ -338,7 +338,7 @@ func TestChainSvrCmds(t *testing.T) { staticCmd: func() interface{} { return btcjson.NewGetCFilterHeaderCmd("123", 0) }, - marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",false],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",0],"id":1}`, unmarshalled: &btcjson.GetCFilterHeaderCmd{ Hash: "123", }, From 5c93ca639ad01da1c65632c0a326e129f86f1c3a Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Oct 2017 20:52:39 -0600 Subject: [PATCH 0139/1056] rpcclient: change "bool" to "uint8" for cfilter/cfheader type --- rpcclient/chain.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/rpcclient/chain.go b/rpcclient/chain.go index ff34423932..3e5c69e7bf 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -820,19 +820,21 @@ func (r FutureGetCFilterResult) Receive() (*wire.MsgCFilter, error) { // returned instance. // // See GetCFilter for the blocking version and more details. -func (c *Client) GetCFilterAsync(blockHash *chainhash.Hash, extended bool) FutureGetCFilterResult { +func (c *Client) GetCFilterAsync(blockHash *chainhash.Hash, + filterType uint8) FutureGetCFilterResult { hash := "" if blockHash != nil { hash = blockHash.String() } - cmd := btcjson.NewGetCFilterCmd(hash, extended) + cmd := btcjson.NewGetCFilterCmd(hash, filterType) return c.sendCmd(cmd) } // GetCFilter returns a raw filter from the server given its block hash. -func (c *Client) GetCFilter(blockHash *chainhash.Hash, extended bool) (*wire.MsgCFilter, error) { - return c.GetCFilterAsync(blockHash, extended).Receive() +func (c *Client) GetCFilter(blockHash *chainhash.Hash, + filterType uint8) (*wire.MsgCFilter, error) { + return c.GetCFilterAsync(blockHash, filterType).Receive() } // FutureGetCFilterHeaderResult is a future promise to deliver the result of a @@ -875,18 +877,20 @@ func (r FutureGetCFilterHeaderResult) Receive() (*wire.MsgCFHeaders, error) { // on the returned instance. // // See GetCFilterHeader for the blocking version and more details. -func (c *Client) GetCFilterHeaderAsync(blockHash *chainhash.Hash, extended bool) FutureGetCFilterHeaderResult { +func (c *Client) GetCFilterHeaderAsync(blockHash *chainhash.Hash, + filterType uint8) FutureGetCFilterHeaderResult { hash := "" if blockHash != nil { hash = blockHash.String() } - cmd := btcjson.NewGetCFilterHeaderCmd(hash, extended) + cmd := btcjson.NewGetCFilterHeaderCmd(hash, filterType) return c.sendCmd(cmd) } // GetCFilterHeader returns a raw filter header from the server given its block // hash. -func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash, extended bool) (*wire.MsgCFHeaders, error) { - return c.GetCFilterHeaderAsync(blockHash, extended).Receive() +func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash, + filterType uint8) (*wire.MsgCFHeaders, error) { + return c.GetCFilterHeaderAsync(blockHash, filterType).Receive() } From 2b7ebfd69804b349e9557f1e4b292dfb2fab0a5d Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Oct 2017 21:24:31 -0600 Subject: [PATCH 0140/1056] peer: add OnCFTypes and OnGetCFTypes callbacks --- peer/peer.go | 21 +++++++++++++++++++-- peer/peer_test.go | 14 ++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index ec84a0a08b..b6a5da5e28 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -126,10 +126,13 @@ type MessageListeners struct { // OnCFilter is invoked when a peer receives a cfilter bitcoin message. OnCFilter func(p *Peer, msg *wire.MsgCFilter) - // OnCFHeaders is invoked when a peer receives a cfheader bitcoin + // OnCFHeaders is invoked when a peer receives a cfheaders bitcoin // message. OnCFHeaders func(p *Peer, msg *wire.MsgCFHeaders) + // OnCFTypes is invoked when a peer receives a cftypes bitcoin message. + OnCFTypes func(p *Peer, msg *wire.MsgCFTypes) + // OnInv is invoked when a peer receives an inv bitcoin message. OnInv func(p *Peer, msg *wire.MsgInv) @@ -155,10 +158,14 @@ type MessageListeners struct { // message. OnGetCFilter func(p *Peer, msg *wire.MsgGetCFilter) - // OnGetCFHeaders is invoked when a peer receives a getcfheader + // OnGetCFHeaders is invoked when a peer receives a getcfheaders // bitcoin message. OnGetCFHeaders func(p *Peer, msg *wire.MsgGetCFHeaders) + // OnGetCFTypes is invoked when a peer receives a getcftypes bitcoin + // message. + OnGetCFTypes func(p *Peer, msg *wire.MsgGetCFTypes) + // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1601,6 +1608,11 @@ out: p.cfg.Listeners.OnGetCFHeaders(p, msg) } + case *wire.MsgGetCFTypes: + if p.cfg.Listeners.OnGetCFTypes != nil { + p.cfg.Listeners.OnGetCFTypes(p, msg) + } + case *wire.MsgCFilter: if p.cfg.Listeners.OnCFilter != nil { p.cfg.Listeners.OnCFilter(p, msg) @@ -1611,6 +1623,11 @@ out: p.cfg.Listeners.OnCFHeaders(p, msg) } + case *wire.MsgCFTypes: + if p.cfg.Listeners.OnCFTypes != nil { + p.cfg.Listeners.OnCFTypes(p, msg) + } + case *wire.MsgFeeFilter: if p.cfg.Listeners.OnFeeFilter != nil { p.cfg.Listeners.OnFeeFilter(p, msg) diff --git a/peer/peer_test.go b/peer/peer_test.go index 701df7441f..89d114b18a 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -405,12 +405,18 @@ func TestPeerListeners(t *testing.T) { OnGetCFHeaders: func(p *peer.Peer, msg *wire.MsgGetCFHeaders) { ok <- msg }, + OnGetCFTypes: func(p *peer.Peer, msg *wire.MsgGetCFTypes) { + ok <- msg + }, OnCFilter: func(p *peer.Peer, msg *wire.MsgCFilter) { ok <- msg }, OnCFHeaders: func(p *peer.Peer, msg *wire.MsgCFHeaders) { ok <- msg }, + OnCFTypes: func(p *peer.Peer, msg *wire.MsgCFTypes) { + ok <- msg + }, OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { ok <- msg }, @@ -542,6 +548,10 @@ func TestPeerListeners(t *testing.T) { "OnGetCFHeaders", wire.NewMsgGetCFHeaders(), }, + { + "OnGetCFTypes", + wire.NewMsgGetCFTypes(), + }, { "OnCFilter", wire.NewMsgCFilter(&chainhash.Hash{}, 1, @@ -551,6 +561,10 @@ func TestPeerListeners(t *testing.T) { "OnCFHeaders", wire.NewMsgCFHeaders(), }, + { + "OnCFTypes", + wire.NewMsgCFTypes([]uint8{0, 1}), + }, { "OnFeeFilter", wire.NewMsgFeeFilter(15000), From 5772bdde86e5d75adadb990422138ed17b853dec Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 10 Oct 2017 21:28:21 -0600 Subject: [PATCH 0141/1056] server: add OnGetCFTypes callback to serverPeer --- server.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server.go b/server.go index 272904afa4..450ebb0e6d 100644 --- a/server.go +++ b/server.go @@ -873,6 +873,18 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { sp.QueueMessage(headersMsg, nil) } +// OnGetCFTypes is invoked when a peer receives a getcftypes bitcoin message. +func (sp *serverPeer) OnGetCFTypes(_ *peer.Peer, msg *wire.MsgGetCFTypes) { + // Ignore getcftypes requests if cfg.NoCFilters is set or we're not in + // sync. + if cfg.NoCFilters || !sp.server.blockManager.IsCurrent() { + return + } + + cfTypesMsg := wire.NewMsgCFTypes([]uint8{0, 1}) + sp.QueueMessage(cfTypesMsg, nil) +} + // enforceNodeBloomFlag disconnects the peer if the server is not configured to // allow bloom filters. Additionally, if the peer has negotiated to a protocol // version that is high enough to observe the bloom filter service support bit, @@ -1722,6 +1734,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnGetHeaders: sp.OnGetHeaders, OnGetCFilter: sp.OnGetCFilter, OnGetCFHeaders: sp.OnGetCFHeaders, + OnGetCFTypes: sp.OnGetCFTypes, OnFeeFilter: sp.OnFeeFilter, OnFilterAdd: sp.OnFilterAdd, OnFilterClear: sp.OnFilterClear, From 8d2ce855ebdfd9ec194acd38b63a7889509c93a7 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 12 Oct 2017 19:37:27 -0600 Subject: [PATCH 0142/1056] wire: update service bits for xthin, bit 5, cfilters, and segwit2x --- wire/protocol.go | 17 +++++++++++++++++ wire/protocol_test.go | 5 ++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/wire/protocol.go b/wire/protocol.go index c767a5faae..8cc9838a55 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -72,9 +72,20 @@ const ( // and transactions including witness data (BIP0144). SFNodeWitness + // SFNodeXthin is a flag used to indicate a peer supports xthin blocks. + SFNodeXthin + + // SFNodeBit5 is a flag used to indicate a peer supports a service + // defined by bit 5. + SFNodeBit5 + // SFNodeCF is a flag used to indicate a peer supports committed // filters (CFs). SFNodeCF + + // SFNode2X is a flag used to indicate a peer is running the Segwit2X + // software. + SFNode2X ) // Map of service flags back to their constant names for pretty printing. @@ -83,7 +94,10 @@ var sfStrings = map[ServiceFlag]string{ SFNodeGetUTXO: "SFNodeGetUTXO", SFNodeBloom: "SFNodeBloom", SFNodeWitness: "SFNodeWitness", + SFNodeXthin: "SFNodeXthin", + SFNodeBit5: "SFNodeBit5", SFNodeCF: "SFNodeCF", + SFNode2X: "SFNode2X", } // orderedSFStrings is an ordered list of service flags from highest to @@ -93,7 +107,10 @@ var orderedSFStrings = []ServiceFlag{ SFNodeGetUTXO, SFNodeBloom, SFNodeWitness, + SFNodeXthin, + SFNodeBit5, SFNodeCF, + SFNode2X, } // String returns the ServiceFlag in human-readable form. diff --git a/wire/protocol_test.go b/wire/protocol_test.go index 639dcc9fe8..60bd0533e5 100644 --- a/wire/protocol_test.go +++ b/wire/protocol_test.go @@ -17,8 +17,11 @@ func TestServiceFlagStringer(t *testing.T) { {SFNodeGetUTXO, "SFNodeGetUTXO"}, {SFNodeBloom, "SFNodeBloom"}, {SFNodeWitness, "SFNodeWitness"}, + {SFNodeXthin, "SFNodeXthin"}, + {SFNodeBit5, "SFNodeBit5"}, {SFNodeCF, "SFNodeCF"}, - {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|SFNodeCF|0xffffffe0"}, + {SFNode2X, "SFNode2X"}, + {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|SFNodeXthin|SFNodeBit5|SFNodeCF|SFNode2X|0xffffff00"}, } t.Logf("Running %d tests", len(tests)) From c7e7acc7fda9bd72574fa4a5af3396b0637cc72e Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Oct 2017 00:24:57 -0600 Subject: [PATCH 0143/1056] multi: use hidden varint for cftypes count; make filter type enum, not uint8 --- blockchain/indexers/cfindex.go | 27 ++++++++++++++---------- btcjson/chainsvrcmds.go | 11 ++++++---- btcjson/chainsvrcmds_test.go | 23 +++++++++++++------- peer/peer_test.go | 10 +++++---- rpcclient/chain.go | 8 +++---- server.go | 3 ++- wire/message_test.go | 7 ++++--- wire/msgcfheaders.go | 2 +- wire/msgcfilter.go | 4 ++-- wire/msgcftypes.go | 38 +++++++++++++++++++++------------- wire/msggetcfheaders.go | 2 +- wire/msggetcfilter.go | 5 +++-- 12 files changed, 85 insertions(+), 55 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 0e7d3bbf92..1572effda4 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -15,6 +15,7 @@ import ( "github.com/btcsuite/btcutil/gcs" "github.com/btcsuite/btcutil/gcs/builder" "github.com/btcsuite/fastsha256" + "github.com/roasbeef/btcd/wire" ) const ( @@ -149,7 +150,7 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { firstHeader := make([]byte, chainhash.HashSize) err = dbStoreFilterHeader( dbTx, - cfHeaderKeys[0], + cfHeaderKeys[wire.GCSFilterRegular], &idx.chainParams.GenesisBlock.Header.PrevBlock, firstHeader, ) @@ -159,7 +160,7 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { return dbStoreFilterHeader( dbTx, - cfHeaderKeys[1], + cfHeaderKeys[wire.GCSFilterExtended], &idx.chainParams.GenesisBlock.Header.PrevBlock, firstHeader, ) @@ -168,8 +169,8 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { // storeFilter stores a given filter, and performs the steps needed to // generate the filter's header. func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, - filterType uint8) error { - if filterType > maxFilterType { + filterType wire.FilterType) error { + if uint8(filterType) > maxFilterType { return errors.New("unsupported filter type") } @@ -215,7 +216,8 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return err } - if err := storeFilter(dbTx, block, f, 0); err != nil { + if err := storeFilter(dbTx, block, f, + wire.GCSFilterRegular); err != nil { return err } @@ -224,7 +226,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return err } - return storeFilter(dbTx, block, f, 1) + return storeFilter(dbTx, block, f, wire.GCSFilterExtended) } // DisconnectBlock is invoked by the index manager when a block has been @@ -252,10 +254,11 @@ func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, // FilterByBlockHash returns the serialized contents of a block's basic or // extended committed filter. -func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, filterType uint8) ([]byte, error) { +func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, + filterType wire.FilterType) ([]byte, error) { var f []byte err := idx.db.View(func(dbTx database.Tx) error { - if filterType > maxFilterType { + if uint8(filterType) > maxFilterType { return errors.New("unsupported filter type") } @@ -268,15 +271,17 @@ func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, filterType uint8) ([]by // FilterHeaderByBlockHash returns the serialized contents of a block's basic // or extended committed filter header. -func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, filterType uint8) ([]byte, error) { +func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, + filterType wire.FilterType) ([]byte, error) { var fh []byte err := idx.db.View(func(dbTx database.Tx) error { - if filterType > 1 { + if uint8(filterType) > maxFilterType { return errors.New("unsupported filter type") } var err error - fh, err = dbFetchFilterHeader(dbTx, cfHeaderKeys[filterType], h) + fh, err = dbFetchFilterHeader(dbTx, + cfHeaderKeys[filterType], h) return err }) return fh, err diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index e7d736f0d4..18933da0b8 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -10,6 +10,8 @@ package btcjson import ( "encoding/json" "fmt" + + "github.com/roasbeef/btcd/wire" ) // AddNodeSubCmd defines the type used in the addnode JSON-RPC command for the @@ -282,12 +284,12 @@ func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd { // GetCFilterCmd defines the getcfilter JSON-RPC command. type GetCFilterCmd struct { Hash string - FilterType uint8 + FilterType wire.FilterType } // NewGetCFilterCmd returns a new instance which can be used to issue a // getcfilter JSON-RPC command. -func NewGetCFilterCmd(hash string, filterType uint8) *GetCFilterCmd { +func NewGetCFilterCmd(hash string, filterType wire.FilterType) *GetCFilterCmd { return &GetCFilterCmd{ Hash: hash, FilterType: filterType, @@ -297,12 +299,13 @@ func NewGetCFilterCmd(hash string, filterType uint8) *GetCFilterCmd { // GetCFilterHeaderCmd defines the getcfilterheader JSON-RPC command. type GetCFilterHeaderCmd struct { Hash string - FilterType uint8 + FilterType wire.FilterType } // NewGetCFilterHeaderCmd returns a new instance which can be used to issue a // getcfilterheader JSON-RPC command. -func NewGetCFilterHeaderCmd(hash string, filterType uint8) *GetCFilterHeaderCmd { +func NewGetCFilterHeaderCmd(hash string, + filterType wire.FilterType) *GetCFilterHeaderCmd { return &GetCFilterHeaderCmd{ Hash: hash, FilterType: filterType, diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 27fb9d6eb4..12fba7d9d1 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/wire" ) // TestChainSvrCmds tests all of the chain server commands marshal and unmarshal @@ -320,27 +321,33 @@ func TestChainSvrCmds(t *testing.T) { { name: "getcfilter", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getcfilter", "123", 0) + return btcjson.NewCmd("getcfilter", "123", + wire.GCSFilterExtended) }, staticCmd: func() interface{} { - return btcjson.NewGetCFilterCmd("123", 0) + return btcjson.NewGetCFilterCmd("123", + wire.GCSFilterExtended) }, - marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",0],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",1],"id":1}`, unmarshalled: &btcjson.GetCFilterCmd{ - Hash: "123", + Hash: "123", + FilterType: wire.GCSFilterExtended, }, }, { name: "getcfilterheader", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getcfilterheader", "123", 0) + return btcjson.NewCmd("getcfilterheader", "123", + wire.GCSFilterExtended) }, staticCmd: func() interface{} { - return btcjson.NewGetCFilterHeaderCmd("123", 0) + return btcjson.NewGetCFilterHeaderCmd("123", + wire.GCSFilterExtended) }, - marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",0],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",1],"id":1}`, unmarshalled: &btcjson.GetCFilterHeaderCmd{ - Hash: "123", + Hash: "123", + FilterType: wire.GCSFilterExtended, }, }, { diff --git a/peer/peer_test.go b/peer/peer_test.go index 89d114b18a..742f97c64a 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -542,7 +542,8 @@ func TestPeerListeners(t *testing.T) { }, { "OnGetCFilter", - wire.NewMsgGetCFilter(&chainhash.Hash{}, 0), + wire.NewMsgGetCFilter(&chainhash.Hash{}, + wire.GCSFilterRegular), }, { "OnGetCFHeaders", @@ -554,8 +555,8 @@ func TestPeerListeners(t *testing.T) { }, { "OnCFilter", - wire.NewMsgCFilter(&chainhash.Hash{}, 1, - []byte("payload")), + wire.NewMsgCFilter(&chainhash.Hash{}, + wire.GCSFilterRegular, []byte("payload")), }, { "OnCFHeaders", @@ -563,7 +564,8 @@ func TestPeerListeners(t *testing.T) { }, { "OnCFTypes", - wire.NewMsgCFTypes([]uint8{0, 1}), + wire.NewMsgCFTypes([]wire.FilterType{ + wire.GCSFilterRegular, wire.GCSFilterExtended}), }, { "OnFeeFilter", diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 3e5c69e7bf..41faea1839 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -821,7 +821,7 @@ func (r FutureGetCFilterResult) Receive() (*wire.MsgCFilter, error) { // // See GetCFilter for the blocking version and more details. func (c *Client) GetCFilterAsync(blockHash *chainhash.Hash, - filterType uint8) FutureGetCFilterResult { + filterType wire.FilterType) FutureGetCFilterResult { hash := "" if blockHash != nil { hash = blockHash.String() @@ -833,7 +833,7 @@ func (c *Client) GetCFilterAsync(blockHash *chainhash.Hash, // GetCFilter returns a raw filter from the server given its block hash. func (c *Client) GetCFilter(blockHash *chainhash.Hash, - filterType uint8) (*wire.MsgCFilter, error) { + filterType wire.FilterType) (*wire.MsgCFilter, error) { return c.GetCFilterAsync(blockHash, filterType).Receive() } @@ -878,7 +878,7 @@ func (r FutureGetCFilterHeaderResult) Receive() (*wire.MsgCFHeaders, error) { // // See GetCFilterHeader for the blocking version and more details. func (c *Client) GetCFilterHeaderAsync(blockHash *chainhash.Hash, - filterType uint8) FutureGetCFilterHeaderResult { + filterType wire.FilterType) FutureGetCFilterHeaderResult { hash := "" if blockHash != nil { hash = blockHash.String() @@ -891,6 +891,6 @@ func (c *Client) GetCFilterHeaderAsync(blockHash *chainhash.Hash, // GetCFilterHeader returns a raw filter header from the server given its block // hash. func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash, - filterType uint8) (*wire.MsgCFHeaders, error) { + filterType wire.FilterType) (*wire.MsgCFHeaders, error) { return c.GetCFilterHeaderAsync(blockHash, filterType).Receive() } diff --git a/server.go b/server.go index 450ebb0e6d..535240af09 100644 --- a/server.go +++ b/server.go @@ -881,7 +881,8 @@ func (sp *serverPeer) OnGetCFTypes(_ *peer.Peer, msg *wire.MsgGetCFTypes) { return } - cfTypesMsg := wire.NewMsgCFTypes([]uint8{0, 1}) + cfTypesMsg := wire.NewMsgCFTypes([]wire.FilterType{ + wire.GCSFilterRegular, wire.GCSFilterExtended}) sp.QueueMessage(cfTypesMsg, nil) } diff --git a/wire/message_test.go b/wire/message_test.go index 7d8cf9ccdd..897f36becc 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -69,12 +69,13 @@ func TestMessage(t *testing.T) { bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0) msgMerkleBlock := NewMsgMerkleBlock(bh) msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") - msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, 0) + msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, GCSFilterExtended) msgGetCFHeaders := NewMsgGetCFHeaders() msgGetCFTypes := NewMsgGetCFTypes() - msgCFilter := NewMsgCFilter(&chainhash.Hash{}, 1, []byte("payload")) + msgCFilter := NewMsgCFilter(&chainhash.Hash{}, GCSFilterExtended, + []byte("payload")) msgCFHeaders := NewMsgCFHeaders() - msgCFTypes := NewMsgCFTypes([]uint8{2}) + msgCFTypes := NewMsgCFTypes([]FilterType{GCSFilterExtended}) tests := []struct { in Message // Value to encode diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 6e1ce2a5dd..0186a53fdb 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -28,7 +28,7 @@ const ( // MsgGetCFHeaders for details on requesting the headers. type MsgCFHeaders struct { StopHash chainhash.Hash - FilterType uint8 + FilterType FilterType HeaderHashes []*chainhash.Hash } diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index 22329938f1..3ce33180f9 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -22,7 +22,7 @@ const ( // getcfilter (MsgGetCFilter) message. type MsgCFilter struct { BlockHash chainhash.Hash - FilterType uint8 + FilterType FilterType Data []byte } @@ -99,7 +99,7 @@ func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 { // NewMsgCFilter returns a new bitcoin cfilter message that conforms to the // Message interface. See MsgCFilter for details. -func NewMsgCFilter(blockHash *chainhash.Hash, filterType uint8, +func NewMsgCFilter(blockHash *chainhash.Hash, filterType FilterType, data []byte) *MsgCFilter { return &MsgCFilter{ BlockHash: *blockHash, diff --git a/wire/msgcftypes.go b/wire/msgcftypes.go index 92a8f718a5..17388e02f4 100644 --- a/wire/msgcftypes.go +++ b/wire/msgcftypes.go @@ -6,28 +6,40 @@ package wire import "io" +// FilterType is used to represent a filter type. +type FilterType uint8 + +const ( + // GCSFilterRegular is the regular filter type. + GCSFilterRegular FilterType = iota + + // GCSFilterExtended is the extended filter type. + GCSFilterExtended +) + // MsgCFTypes is the cftypes message. type MsgCFTypes struct { - NumFilters uint8 - SupportedFilters []uint8 + SupportedFilters []FilterType } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - // Read the number of filter types supported - err := readElement(r, &msg.NumFilters) + // Read the number of filter types supported. + count, err := ReadVarInt(r, pver) if err != nil { return err } // Read each filter type. - msg.SupportedFilters = make([]uint8, msg.NumFilters) - for i := uint8(0); i < msg.NumFilters; i++ { - err = readElement(r, &msg.SupportedFilters[i]) + msg.SupportedFilters = make([]FilterType, count) + for i := uint64(0); i < count; i++ { + var filterType uint8 + err = readElement(r, &filterType) if err != nil { return err } + msg.SupportedFilters[i] = FilterType(filterType) } return nil @@ -36,9 +48,8 @@ func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) er // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgCFTypes) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - // Write length of supported filters slice; don't trust that the caller - // has set it correctly. - err := writeElement(w, uint8(len(msg.SupportedFilters))) + // Write length of supported filters slice. We assume it's deduplicated. + err := WriteVarInt(w, pver, uint64(len(msg.SupportedFilters))) if err != nil { return err } @@ -78,15 +89,14 @@ func (msg *MsgCFTypes) Command() string { // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. func (msg *MsgCFTypes) MaxPayloadLength(pver uint32) uint32 { - // 1 byte for NumFilters, and 1 byte for up to 255 filter types. - return 256 + // 2 bytes for filter count, and 1 byte for up to 256 filter types. + return 258 } // NewMsgCFTypes returns a new bitcoin cftypes message that conforms to the // Message interface. See MsgCFTypes for details. -func NewMsgCFTypes(filterTypes []uint8) *MsgCFTypes { +func NewMsgCFTypes(filterTypes []FilterType) *MsgCFTypes { return &MsgCFTypes{ - NumFilters: uint8(len(filterTypes)), SupportedFilters: filterTypes, } } diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index d82ddcc82f..d93e4e627d 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -17,7 +17,7 @@ import ( type MsgGetCFHeaders struct { BlockLocatorHashes []*chainhash.Hash HashStop chainhash.Hash - FilterType uint8 + FilterType FilterType } // AddBlockLocatorHash adds a new block locator hash to the message. diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go index 8ba677f5a5..527a391e51 100644 --- a/wire/msggetcfilter.go +++ b/wire/msggetcfilter.go @@ -14,7 +14,7 @@ import ( // getcfilter message. It is used to request a committed filter for a block. type MsgGetCFilter struct { BlockHash chainhash.Hash - FilterType uint8 + FilterType FilterType } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. @@ -53,7 +53,8 @@ func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { // NewMsgGetCFilter returns a new bitcoin getcfilter message that conforms to // the Message interface using the passed parameters and defaults for the // remaining fields. -func NewMsgGetCFilter(blockHash *chainhash.Hash, filterType uint8) *MsgGetCFilter { +func NewMsgGetCFilter(blockHash *chainhash.Hash, + filterType FilterType) *MsgGetCFilter { return &MsgGetCFilter{ BlockHash: *blockHash, FilterType: filterType, From e0a357abb53836b194421577d4e6c8f4e5040377 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Oct 2017 11:36:39 -0600 Subject: [PATCH 0144/1056] server: add TODO for querying supported filter types --- server.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server.go b/server.go index 535240af09..92a3a6ff31 100644 --- a/server.go +++ b/server.go @@ -881,6 +881,8 @@ func (sp *serverPeer) OnGetCFTypes(_ *peer.Peer, msg *wire.MsgGetCFTypes) { return } + // TODO: update to query blockchain indexes and/or config for supported + // filter types. cfTypesMsg := wire.NewMsgCFTypes([]wire.FilterType{ wire.GCSFilterRegular, wire.GCSFilterExtended}) sp.QueueMessage(cfTypesMsg, nil) From f4060b107c87b133380872d0f1cf61e3fdc59bc1 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 31 Oct 2017 12:29:08 -0600 Subject: [PATCH 0145/1056] blockchain/indexers: check for `ErrNoData` in extended filters Since the tx hash has moved to the basic filter, generating an extended filter can result in `ErrNoData`. This is handled by writing a nil filter and giving it a zero hash. --- blockchain/indexers/cfindex.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 1572effda4..fd53ece0ea 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -222,7 +222,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, } f, err = builder.BuildExtFilter(block.MsgBlock()) - if err != nil { + if err != nil && err != gcs.ErrNoData { return err } From 6f32a79fd6812f3ee01f2f01fd029528d26b0591 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 2 Nov 2017 18:19:50 -0700 Subject: [PATCH 0146/1056] log: update to latest log rotator API --- log.go | 1 + 1 file changed, 1 insertion(+) diff --git a/log.go b/log.go index ae413a18cf..71accc7c9c 100644 --- a/log.go +++ b/log.go @@ -21,6 +21,7 @@ import ( "github.com/btcsuite/btcd/netsync" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btclog" "github.com/jrick/logrotate/rotator" ) From 10432160d5a04c4ce2d777577fa5e9a9e4802260 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 17 Nov 2017 15:51:08 -0800 Subject: [PATCH 0147/1056] multi: rebase to upstream, update API's --- blockchain/indexers/cfindex.go | 4 ++-- btcd.go | 2 +- netsync/interface.go | 14 +++++++------- rpcadapters.go | 2 +- server.go | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index fd53ece0ea..bd15271119 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -299,6 +299,6 @@ func NewCfIndex(db database.DB, chainParams *chaincfg.Params) *CfIndex { } // DropCfIndex drops the CF index from the provided database if exists. -func DropCfIndex(db database.DB) error { - return dropIndex(db, cfIndexParentBucketKey, cfIndexName) +func DropCfIndex(db database.DB, interrupt <-chan struct{}) error { + return dropIndex(db, cfIndexParentBucketKey, cfIndexName, interrupt) } diff --git a/btcd.go b/btcd.go index fdcebed3e9..a0ccb3eabc 100644 --- a/btcd.go +++ b/btcd.go @@ -136,7 +136,7 @@ func btcdMain(serverChan chan<- *server) error { return nil } if cfg.DropCfIndex { - if err := indexers.DropCfIndex(db); err != nil { + if err := indexers.DropCfIndex(db, interrupt); err != nil { btcdLog.Errorf("%v", err) return err } diff --git a/netsync/interface.go b/netsync/interface.go index 61a230ac4c..a177cb96d5 100644 --- a/netsync/interface.go +++ b/netsync/interface.go @@ -5,13 +5,13 @@ package netsync import ( - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/mempool" - "github.com/btcsuite/btcd/peer" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/blockchain" + "github.com/roasbeef/btcd/chaincfg" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/mempool" + "github.com/roasbeef/btcd/peer" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) // PeerNotifier exposes methods to notify peers of status changes to diff --git a/rpcadapters.go b/rpcadapters.go index e0af0b0983..aee62d13e8 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -7,10 +7,10 @@ package main import ( "sync/atomic" - "github.com/Roasbeef/btcd/netsync" "github.com/roasbeef/btcd/blockchain" "github.com/roasbeef/btcd/chaincfg/chainhash" "github.com/roasbeef/btcd/mempool" + "github.com/roasbeef/btcd/netsync" "github.com/roasbeef/btcd/peer" "github.com/roasbeef/btcd/wire" "github.com/roasbeef/btcutil" diff --git a/server.go b/server.go index 92a3a6ff31..b124914810 100644 --- a/server.go +++ b/server.go @@ -742,7 +742,7 @@ func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { // OnGetCFilter is invoked when a peer receives a getcfilter bitcoin message. func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { // Ignore getcfilter requests if not in sync. - if !sp.server.blockManager.IsCurrent() { + if !sp.server.syncManager.IsCurrent() { return } @@ -764,12 +764,12 @@ func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { // OnGetCFHeaders is invoked when a peer receives a getcfheader bitcoin message. func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { // Ignore getcfilterheader requests if not in sync. - if !sp.server.blockManager.IsCurrent() { + if !sp.server.syncManager.IsCurrent() { return } // Attempt to look up the height of the provided stop hash. - chain := sp.server.blockManager.chain + chain := sp.server.chain endIdx := int32(math.MaxInt32) height, err := chain.BlockHeightByHash(&msg.HashStop) if err == nil { @@ -877,7 +877,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { func (sp *serverPeer) OnGetCFTypes(_ *peer.Peer, msg *wire.MsgGetCFTypes) { // Ignore getcftypes requests if cfg.NoCFilters is set or we're not in // sync. - if cfg.NoCFilters || !sp.server.blockManager.IsCurrent() { + if cfg.NoCFilters || !sp.server.syncManager.IsCurrent() { return } From 404292179175cabf4a67a7b363d0306ee6ee84e3 Mon Sep 17 00:00:00 2001 From: Daniel Krawisz Date: Sun, 7 Aug 2016 05:22:52 -0500 Subject: [PATCH 0148/1056] feeEstimator class added with tests. The feeEstimator can keep track of how long it takes for unconfirmed txs to be mined into blocks. It can also roll itself back in the case of an orphan block. --- mempool/estimatefee.go | 493 ++++++++++++++++++++++++++++++++++++ mempool/estimatefee_test.go | 330 ++++++++++++++++++++++++ 2 files changed, 823 insertions(+) create mode 100644 mempool/estimatefee.go create mode 100644 mempool/estimatefee_test.go diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go new file mode 100644 index 0000000000..b9254a3734 --- /dev/null +++ b/mempool/estimatefee.go @@ -0,0 +1,493 @@ +// Copyright (c) 2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package mempool + +import ( + "errors" + "fmt" + "math" + "math/rand" + "sort" + "sync" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mining" + "github.com/btcsuite/btcutil" +) + +// TODO incorporate Alex Morcos' modifications to Gavin's initial model +// https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2014-October/006824.html + +// TODO store and restore the FeeEstimator state in the database. + +const ( + // estimateFeeDepth is the maximum number of blocks before a transaction + // is confirmed that we want to track. + estimateFeeDepth = 25 + + // estimateFeeBinSize is the number of txs stored in each bin. + estimateFeeBinSize = 100 + + // estimateFeeMaxReplacements is the max number of replacements that + // can be made by the txs found in a given block. + estimateFeeMaxReplacements = 10 +) + +// SatoshiPerByte is number with units of satoshis per byte. +type SatoshiPerByte float64 + +// ToSatoshiPerKb returns a float value that represents the given +// SatoshiPerByte converted to satoshis per kb. +func (rate SatoshiPerByte) ToSatoshiPerKb() float64 { + // If our rate is the error value, return that. + if rate == SatoshiPerByte(-1.0) { + return -1.0 + } + + return float64(rate) * 1024 +} + +// Fee returns the fee for a transaction of a given size for +// the given fee rate. +func (rate SatoshiPerByte) Fee(size uint32) btcutil.Amount { + // If our rate is the error value, return that. + if rate == SatoshiPerByte(-1) { + return btcutil.Amount(-1) + } + + return btcutil.Amount(float64(rate) * float64(size)) +} + +// NewSatoshiPerByte creates a SatoshiPerByte from an Amount and a +// size in bytes. +func NewSatoshiPerByte(fee btcutil.Amount, size uint32) SatoshiPerByte { + return SatoshiPerByte(float64(fee) / float64(size)) +} + +// observedTransaction represents an observed transaction and some +// additional data required for the fee estimation algorithm. +type observedTransaction struct { + // A transaction hash. + hash chainhash.Hash + + // The fee per byte of the transaction in satoshis. + feeRate SatoshiPerByte + + // The block height when it was observed. + observed int32 + + // The height of the block in which it was mined. + // If the transaction has not yet been mined, it is zero. + mined int32 +} + +// registeredBlock has the hash of a block and the list of transactions +// it mined which had been previously observed by the FeeEstimator. It +// is used if Rollback is called to reverse the effect of registering +// a block. +type registeredBlock struct { + hash *chainhash.Hash + transactions []*observedTransaction +} + +// FeeEstimator manages the data necessary to create +// fee estimations. It is safe for concurrent access. +type FeeEstimator struct { + maxRollback uint32 + binSize int + + // The maximum number of replacements that can be made in a single + // bin per block. Default is estimateFeeMaxReplacements + maxReplacements int + + // The minimum number of blocks that can be registered with the fee + // estimator before it will provide answers. + minRegisteredBlocks uint32 + + // The last known height. + lastKnownHeight int32 + + sync.RWMutex + observed map[chainhash.Hash]observedTransaction + bin [estimateFeeDepth][]*observedTransaction + numBlocksRegistered uint32 // The number of blocks that have been registered. + + // The cached estimates. + cached []SatoshiPerByte + + // Transactions that have been removed from the bins. This allows us to + // revert in case of an orphaned block. + dropped []registeredBlock +} + +// NewFeeEstimator creates a FeeEstimator for which at most maxRollback blocks +// can be unregistered and which returns an error unless minRegisteredBlocks +// have been registered with it. +func NewFeeEstimator(maxRollback, minRegisteredBlocks uint32) *FeeEstimator { + return &FeeEstimator{ + maxRollback: maxRollback, + minRegisteredBlocks: minRegisteredBlocks, + lastKnownHeight: mining.UnminedHeight, + binSize: estimateFeeBinSize, + maxReplacements: estimateFeeMaxReplacements, + observed: make(map[chainhash.Hash]observedTransaction), + dropped: make([]registeredBlock, 0, maxRollback), + } +} + +// ObserveTransaction is called when a new transaction is observed in the mempool. +func (ef *FeeEstimator) ObserveTransaction(t *TxDesc) { + ef.Lock() + defer ef.Unlock() + + hash := *t.Tx.Hash() + if _, ok := ef.observed[hash]; !ok { + size := uint32(t.Tx.MsgTx().SerializeSize()) + + ef.observed[hash] = observedTransaction{ + hash: hash, + feeRate: NewSatoshiPerByte(btcutil.Amount(t.Fee), size), + observed: t.Height, + mined: mining.UnminedHeight, + } + } +} + +// RegisterBlock informs the fee estimator of a new block to take into account. +func (ef *FeeEstimator) RegisterBlock(block *btcutil.Block) error { + ef.Lock() + defer ef.Unlock() + + // The previous sorted list is invalid, so delete it. + ef.cached = nil + + height := block.Height() + if height != ef.lastKnownHeight+1 && ef.lastKnownHeight != mining.UnminedHeight { + return fmt.Errorf("intermediate block not recorded; current height is %d; new height is %d", + ef.lastKnownHeight, height) + } + + // Update the last known height. + ef.lastKnownHeight = height + ef.numBlocksRegistered++ + + // Randomly order txs in block. + transactions := make(map[*btcutil.Tx]struct{}) + for _, t := range block.Transactions() { + transactions[t] = struct{}{} + } + + // Count the number of replacements we make per bin so that we don't + // replace too many. + var replacementCounts [estimateFeeDepth]int + + // Keep track of which txs were dropped in case of an orphan block. + dropped := registeredBlock{ + hash: block.Hash(), + transactions: make([]*observedTransaction, 0, 100), + } + + // Go through the txs in the block. + for t := range transactions { + hash := *t.Hash() + + // Have we observed this tx in the mempool? + o, ok := ef.observed[hash] + if !ok { + continue + } + + // Put the observed tx in the oppropriate bin. + o.mined = height + + blocksToConfirm := height - o.observed - 1 + + // This shouldn't happen but check just in case to avoid + // a panic later. + if blocksToConfirm >= estimateFeeDepth { + continue + } + + // Make sure we do not replace too many transactions per min. + if replacementCounts[blocksToConfirm] == ef.maxReplacements { + continue + } + + replacementCounts[blocksToConfirm]++ + + bin := ef.bin[blocksToConfirm] + + // Remove a random element and replace it with this new tx. + if len(bin) == ef.binSize { + l := ef.binSize - replacementCounts[blocksToConfirm] + drop := rand.Intn(l) + dropped.transactions = append(dropped.transactions, bin[drop]) + + bin[drop] = bin[l-1] + bin[l-1] = &o + } else { + ef.bin[blocksToConfirm] = append(bin, &o) + } + } + + // Go through the mempool for txs that have been in too long. + for hash, o := range ef.observed { + if height-o.observed >= estimateFeeDepth { + delete(ef.observed, hash) + } + } + + // Add dropped list to history. + if ef.maxRollback == 0 { + return nil + } + + if uint32(len(ef.dropped)) == ef.maxRollback { + ef.dropped = append(ef.dropped[1:], dropped) + } else { + ef.dropped = append(ef.dropped, dropped) + } + + return nil +} + +// Rollback unregisters a recently registered block from the FeeEstimator. +// This can be used to reverse the effect of an orphaned block on the fee +// estimator. The maximum number of rollbacks allowed is given by +// maxRollbacks. +// +// Note: not everything can be rolled back because some transactions are +// deleted if they have been observed too long ago. That means the result +// of Rollback won't always be exactly the same as if the last block had not +// happened, but it should be close enough. +func (ef *FeeEstimator) Rollback(block *btcutil.Block) error { + ef.Lock() + defer ef.Unlock() + + hash := block.Hash() + + // Find this block in the stack of recent registered blocks. + var n int + for n = 1; n < len(ef.dropped); n++ { + if ef.dropped[len(ef.dropped)-n].hash.IsEqual(hash) { + break + } + } + + if n == len(ef.dropped) { + return errors.New("no such block was recently registered") + } + + for i := 0; i < n; i++ { + err := ef.rollback() + if err != nil { + return err + } + } + + return nil +} + +// rollback rolls back the effect of the last block in the stack +// of registered blocks. +func (ef *FeeEstimator) rollback() error { + + // The previous sorted list is invalid, so delete it. + ef.cached = nil + + // pop the last list of dropped txs from the stack. + last := len(ef.dropped) - 1 + if last == -1 { + // Return if we cannot rollback. + return errors.New("max rollbacks reached") + } + + ef.numBlocksRegistered-- + + dropped := ef.dropped[last] + ef.dropped = ef.dropped[0:last] + + // where we are in each bin as we replace txs? + var replacementCounters [estimateFeeDepth]int + + var err error + + // Go through the txs in the dropped block. + for _, o := range dropped.transactions { + // Which bin was this tx in? + blocksToConfirm := o.mined - o.observed - 1 + + bin := ef.bin[blocksToConfirm] + + var counter = replacementCounters[blocksToConfirm] + + // Continue to go through that bin where we left off. + for { + if counter >= len(bin) { + // Create an error but keep going in case we can roll back + // more transactions successfully. + err = errors.New("illegal state: cannot rollback dropped transaction") + } + + prev := bin[counter] + + if prev.mined == ef.lastKnownHeight { + prev.mined = mining.UnminedHeight + + bin[counter] = o + + counter++ + break + } + + counter++ + } + } + + // Continue going through bins to find other txs to remove + // which did not replace any other when they were entered. + for i, j := range replacementCounters { + for { + l := len(ef.bin[i]) + if j >= l { + break + } + + prev := ef.bin[i][j] + + if prev.mined == ef.lastKnownHeight { + prev.mined = mining.UnminedHeight + + newBin := append(ef.bin[i][0:j], ef.bin[i][j+1:l]...) + // TODO This line should prevent an unintentional memory + // leak but it causes a panic when it is uncommented. + // ef.bin[i][j] = nil + ef.bin[i] = newBin + + continue + } + + j++ + } + } + + ef.lastKnownHeight-- + + return err +} + +// estimateFeeSet is a set of txs that can that is sorted +// by the fee per kb rate. +type estimateFeeSet struct { + feeRate []SatoshiPerByte + bin [estimateFeeDepth]uint32 +} + +func (b *estimateFeeSet) Len() int { return len(b.feeRate) } + +func (b *estimateFeeSet) Less(i, j int) bool { + return b.feeRate[i] > b.feeRate[j] +} + +func (b *estimateFeeSet) Swap(i, j int) { + b.feeRate[i], b.feeRate[j] = b.feeRate[j], b.feeRate[i] +} + +// estimateFee returns the estimated fee for a transaction +// to confirm in confirmations blocks from now, given +// the data set we have collected. +func (b *estimateFeeSet) estimateFee(confirmations int) SatoshiPerByte { + if confirmations <= 0 { + return SatoshiPerByte(math.Inf(1)) + } + + if confirmations > estimateFeeDepth { + return 0 + } + + var min, max uint32 = 0, 0 + for i := 0; i < confirmations-1; i++ { + min += b.bin[i] + } + + max = min + b.bin[confirmations-1] + + // We don't have any transactions! + if min == 0 && max == 0 { + return 0 + } + + return b.feeRate[(min+max-1)/2] * 1E-8 +} + +// newEstimateFeeSet creates a temporary data structure that +// can be used to find all fee estimates. +func (ef *FeeEstimator) newEstimateFeeSet() *estimateFeeSet { + set := &estimateFeeSet{} + + capacity := 0 + for i, b := range ef.bin { + l := len(b) + set.bin[i] = uint32(l) + capacity += l + } + + set.feeRate = make([]SatoshiPerByte, capacity) + + i := 0 + for _, b := range ef.bin { + for _, o := range b { + set.feeRate[i] = o.feeRate + i++ + } + } + + sort.Sort(set) + + return set +} + +// estimates returns the set of all fee estimates from 1 to estimateFeeDepth +// confirmations from now. +func (ef *FeeEstimator) estimates() []SatoshiPerByte { + set := ef.newEstimateFeeSet() + + estimates := make([]SatoshiPerByte, estimateFeeDepth) + for i := 0; i < estimateFeeDepth; i++ { + estimates[i] = set.estimateFee(i + 1) + } + + return estimates +} + +// EstimateFee estimates the fee per byte to have a tx confirmed a given +// number of blocks from now. +func (ef *FeeEstimator) EstimateFee(numBlocks uint32) (SatoshiPerByte, error) { + ef.Lock() + defer ef.Unlock() + + // If the number of registered blocks is below the minimum, return + // an error. + if ef.numBlocksRegistered < ef.minRegisteredBlocks { + return -1, errors.New("not enough blocks have been observed") + } + + if numBlocks == 0 { + return -1, errors.New("cannot confirm transaction in zero blocks") + } + + if numBlocks > estimateFeeDepth { + return -1, fmt.Errorf( + "can only estimate fees for up to %d blocks from now", + estimateFeeBinSize) + } + + // If there are no cached results, generate them. + if ef.cached == nil { + ef.cached = ef.estimates() + } + + return ef.cached[int(numBlocks)-1], nil +} diff --git a/mempool/estimatefee_test.go b/mempool/estimatefee_test.go new file mode 100644 index 0000000000..91595d9cd0 --- /dev/null +++ b/mempool/estimatefee_test.go @@ -0,0 +1,330 @@ +// Copyright (c) 2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package mempool + +import ( + "math/rand" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mining" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" +) + +// newTestFeeEstimator creates a feeEstimator with some different parameters +// for testing purposes. +func newTestFeeEstimator(binSize, maxReplacements, maxRollback uint32) *FeeEstimator { + return &FeeEstimator{ + maxRollback: maxRollback, + lastKnownHeight: mining.UnminedHeight, + binSize: int(binSize), + minRegisteredBlocks: 0, + maxReplacements: int(maxReplacements), + observed: make(map[chainhash.Hash]observedTransaction), + dropped: make([]registeredBlock, 0, maxRollback), + } +} + +type estimateFeeTester struct { + t *testing.T + version int32 + height int32 +} + +func (eft *estimateFeeTester) testTx(fee btcutil.Amount) *TxDesc { + eft.version++ + return &TxDesc{ + TxDesc: mining.TxDesc{ + Tx: btcutil.NewTx(&wire.MsgTx{ + Version: eft.version, + }), + Height: eft.height, + Fee: int64(fee), + }, + StartingPriority: 0, + } +} + +func expectedFeePerByte(t *TxDesc) SatoshiPerByte { + size := float64(t.TxDesc.Tx.MsgTx().SerializeSize()) + fee := float64(t.TxDesc.Fee) + + return SatoshiPerByte(fee / size * 1E-8) +} + +func (eft *estimateFeeTester) testBlock(txs []*wire.MsgTx) *btcutil.Block { + + eft.height++ + block := btcutil.NewBlock(&wire.MsgBlock{ + Transactions: txs, + }) + block.SetHeight(eft.height) + + return block +} + +func TestEstimateFee(t *testing.T) { + ef := newTestFeeEstimator(5, 3, 0) + eft := estimateFeeTester{t: t} + + // Try with no txs and get zero for all queries. + expected := SatoshiPerByte(0.0) + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f when estimator is empty; got %f", expected, estimated) + } + } + + // Now insert a tx. + tx := eft.testTx(1000000) + ef.ObserveTransaction(tx) + + // Expected should still be zero because this is still in the mempool. + expected = SatoshiPerByte(0.0) + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f when estimator has one tx in mempool; got %f", expected, estimated) + } + } + + // Change minRegisteredBlocks to make sure that works. Error return + // value expected. + ef.minRegisteredBlocks = 1 + expected = SatoshiPerByte(-1.0) + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f before any blocks have been registered; got %f", expected, estimated) + } + } + + // Record a block. + ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{tx.Tx.MsgTx()})) + expected = expectedFeePerByte(tx) + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f when one tx is binned; got %f", expected, estimated) + } + } + + // Create some more transactions. + txA := eft.testTx(500000) + txB := eft.testTx(2000000) + txC := eft.testTx(4000000) + ef.ObserveTransaction(txA) + ef.ObserveTransaction(txB) + ef.ObserveTransaction(txC) + + // Record 8 empty blocks. + for i := 0; i < 8; i++ { + ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{})) + } + + // Mine the first tx. + ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{txA.Tx.MsgTx()})) + + // Now the estimated amount should depend on the value + // of the argument to estimate fee. + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + if i > 8 { + expected = expectedFeePerByte(txA) + } else { + expected = expectedFeePerByte(tx) + } + if estimated != expected { + t.Errorf("Estimate fee error: expected %f on round %d; got %f", expected, i, estimated) + } + } + + // Record 5 more empty blocks. + for i := 0; i < 5; i++ { + ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{})) + } + + // Mine the next tx. + ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{txB.Tx.MsgTx()})) + + // Now the estimated amount should depend on the value + // of the argument to estimate fee. + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + if i <= 8 { + expected = expectedFeePerByte(txB) + } else if i <= 8+6 { + expected = expectedFeePerByte(tx) + } else { + expected = expectedFeePerByte(txA) + } + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f on round %d; got %f", expected, i, estimated) + } + } + + // Record 9 more empty blocks. + for i := 0; i < 10; i++ { + ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{})) + } + + // Mine txC. + ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{txC.Tx.MsgTx()})) + + // This should have no effect on the outcome because too + // many blocks have been mined for txC to be recorded. + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + if i <= 8 { + expected = expectedFeePerByte(txB) + } else if i <= 8+6 { + expected = expectedFeePerByte(tx) + } else { + expected = expectedFeePerByte(txA) + } + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f on round %d; got %f", expected, i, estimated) + } + } +} + +func (eft *estimateFeeTester) estimates(ef *FeeEstimator) [estimateFeeDepth]SatoshiPerByte { + + // Generate estimates + var estimates [estimateFeeDepth]SatoshiPerByte + for i := 0; i < estimateFeeDepth; i++ { + estimates[i], _ = ef.EstimateFee(1) + } + + // Check that all estimated fee results go in descending order. + for i := 1; i < estimateFeeDepth; i++ { + if estimates[i] > estimates[i-1] { + eft.t.Error("Estimates not in descending order.") + } + } + + return estimates +} + +func (eft *estimateFeeTester) round(ef *FeeEstimator, + txHistory [][]*TxDesc, blockHistory []*btcutil.Block, + estimateHistory [][estimateFeeDepth]SatoshiPerByte, + txPerRound, txPerBlock, maxRollback uint32) ([][]*TxDesc, + []*btcutil.Block, [][estimateFeeDepth]SatoshiPerByte) { + + // generate new txs. + var newTxs []*TxDesc + for i := uint32(0); i < txPerRound; i++ { + newTx := eft.testTx(btcutil.Amount(rand.Intn(1000000))) + ef.ObserveTransaction(newTx) + newTxs = append(newTxs, newTx) + } + + // Construct new tx history. + txHistory = append(txHistory, newTxs) + if len(txHistory) > estimateFeeDepth { + txHistory = txHistory[1 : estimateFeeDepth+1] + } + + // generate new block, with no duplicates. + newBlockTxs := make(map[chainhash.Hash]*wire.MsgTx) + i := uint32(0) + for i < txPerBlock { + n := rand.Intn(len(txHistory)) + m := rand.Intn(int(txPerRound)) + + tx := txHistory[n][m] + hash := *tx.Tx.Hash() + + if _, ok := newBlockTxs[hash]; ok { + continue + } + + newBlockTxs[hash] = tx.Tx.MsgTx() + i++ + } + + var newBlockList []*wire.MsgTx + for _, tx := range newBlockTxs { + newBlockList = append(newBlockList, tx) + } + + newBlock := eft.testBlock(newBlockList) + ef.RegisterBlock(newBlock) + + // return results. + estimates := eft.estimates(ef) + + // Return results + blockHistory = append(blockHistory, newBlock) + if len(blockHistory) > int(maxRollback) { + blockHistory = blockHistory[1 : maxRollback+1] + } + + return txHistory, blockHistory, append(estimateHistory, estimates) +} + +func TestEstimateFeeRollback(t *testing.T) { + txPerRound := uint32(20) + txPerBlock := uint32(10) + binSize := uint32(5) + maxReplacements := uint32(3) + stepsBack := 2 + rounds := 30 + + ef := newTestFeeEstimator(binSize, maxReplacements, uint32(stepsBack)) + eft := estimateFeeTester{t: t} + var txHistory [][]*TxDesc + var blockHistory []*btcutil.Block + estimateHistory := [][estimateFeeDepth]SatoshiPerByte{eft.estimates(ef)} + + // Make some initial rounds so that we have room to step back. + for round := 0; round < stepsBack-1; round++ { + txHistory, blockHistory, estimateHistory = + eft.round(ef, txHistory, blockHistory, estimateHistory, + txPerRound, txPerBlock, uint32(stepsBack)) + } + + for round := 0; round < rounds; round++ { + txHistory, blockHistory, estimateHistory = + eft.round(ef, txHistory, blockHistory, estimateHistory, + txPerRound, txPerBlock, uint32(stepsBack)) + + for step := 0; step < stepsBack; step++ { + err := ef.rollback() + if err != nil { + t.Fatal("Could not rollback: ", err) + } + + expected := estimateHistory[len(estimateHistory)-step-2] + estimates := eft.estimates(ef) + + // Ensure that these are both the same. + for i := 0; i < estimateFeeDepth; i++ { + if expected[i] != estimates[i] { + t.Errorf("Rollback value mismatch. Expected %f, got %f. ", + expected[i], estimates[i]) + } + } + } + + // Remove last estries from estimateHistory + estimateHistory = estimateHistory[0 : len(estimateHistory)-stepsBack] + + // replay the previous blocks. + for b := 0; b < stepsBack; b++ { + ef.RegisterBlock(blockHistory[b]) + estimateHistory = append(estimateHistory, eft.estimates(ef)) + } + } +} From e6d8b869aa8f68cdbc20f83cfb17c5cd710316b6 Mon Sep 17 00:00:00 2001 From: Daniel Krawisz Date: Mon, 13 Nov 2017 21:12:32 -0600 Subject: [PATCH 0149/1056] feeEstimator changed to FeeEstimator. A number of optimizations and improvements. Rollback takes a block hash rather than a BlockStamp. Increase rounds in TestEstimateFeeRollback to test dropping txs that have been in the mempool too long. --- mempool/estimatefee.go | 165 +++++++++++++---------- mempool/estimatefee_test.go | 252 ++++++++++++++++++++---------------- 2 files changed, 243 insertions(+), 174 deletions(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index b9254a3734..354eabca05 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -33,20 +33,27 @@ const ( // estimateFeeMaxReplacements is the max number of replacements that // can be made by the txs found in a given block. estimateFeeMaxReplacements = 10 + + bytePerKb = 1024 + + btcPerSatoshi = 1E-8 ) // SatoshiPerByte is number with units of satoshis per byte. type SatoshiPerByte float64 -// ToSatoshiPerKb returns a float value that represents the given +// BtcPerKilobyte is number with units of bitcoins per kilobyte. +type BtcPerKilobyte float64 + +// ToBtcPerKb returns a float value that represents the given // SatoshiPerByte converted to satoshis per kb. -func (rate SatoshiPerByte) ToSatoshiPerKb() float64 { +func (rate SatoshiPerByte) ToBtcPerKb() BtcPerKilobyte { // If our rate is the error value, return that. if rate == SatoshiPerByte(-1.0) { return -1.0 } - return float64(rate) * 1024 + return BtcPerKilobyte(float64(rate) * bytePerKb * btcPerSatoshi) } // Fee returns the fee for a transaction of a given size for @@ -88,7 +95,7 @@ type observedTransaction struct { // is used if Rollback is called to reverse the effect of registering // a block. type registeredBlock struct { - hash *chainhash.Hash + hash chainhash.Hash transactions []*observedTransaction } @@ -96,11 +103,11 @@ type registeredBlock struct { // fee estimations. It is safe for concurrent access. type FeeEstimator struct { maxRollback uint32 - binSize int + binSize int32 // The maximum number of replacements that can be made in a single // bin per block. Default is estimateFeeMaxReplacements - maxReplacements int + maxReplacements int32 // The minimum number of blocks that can be registered with the fee // estimator before it will provide answers. @@ -109,17 +116,19 @@ type FeeEstimator struct { // The last known height. lastKnownHeight int32 - sync.RWMutex - observed map[chainhash.Hash]observedTransaction - bin [estimateFeeDepth][]*observedTransaction - numBlocksRegistered uint32 // The number of blocks that have been registered. + // The number of blocks that have been registered. + numBlocksRegistered uint32 + + mtx sync.RWMutex + observed map[chainhash.Hash]*observedTransaction + bin [estimateFeeDepth][]*observedTransaction // The cached estimates. cached []SatoshiPerByte // Transactions that have been removed from the bins. This allows us to // revert in case of an orphaned block. - dropped []registeredBlock + dropped []*registeredBlock } // NewFeeEstimator creates a FeeEstimator for which at most maxRollback blocks @@ -132,21 +141,27 @@ func NewFeeEstimator(maxRollback, minRegisteredBlocks uint32) *FeeEstimator { lastKnownHeight: mining.UnminedHeight, binSize: estimateFeeBinSize, maxReplacements: estimateFeeMaxReplacements, - observed: make(map[chainhash.Hash]observedTransaction), - dropped: make([]registeredBlock, 0, maxRollback), + observed: make(map[chainhash.Hash]*observedTransaction), + dropped: make([]*registeredBlock, 0, maxRollback), } } // ObserveTransaction is called when a new transaction is observed in the mempool. func (ef *FeeEstimator) ObserveTransaction(t *TxDesc) { - ef.Lock() - defer ef.Unlock() + ef.mtx.Lock() + defer ef.mtx.Unlock() + + // If we haven't seen a block yet we don't know when this one arrived, + // so we ignore it. + if ef.lastKnownHeight == mining.UnminedHeight { + return + } hash := *t.Tx.Hash() if _, ok := ef.observed[hash]; !ok { size := uint32(t.Tx.MsgTx().SerializeSize()) - ef.observed[hash] = observedTransaction{ + ef.observed[hash] = &observedTransaction{ hash: hash, feeRate: NewSatoshiPerByte(btcutil.Amount(t.Fee), size), observed: t.Height, @@ -157,8 +172,8 @@ func (ef *FeeEstimator) ObserveTransaction(t *TxDesc) { // RegisterBlock informs the fee estimator of a new block to take into account. func (ef *FeeEstimator) RegisterBlock(block *btcutil.Block) error { - ef.Lock() - defer ef.Unlock() + ef.mtx.Lock() + defer ef.mtx.Unlock() // The previous sorted list is invalid, so delete it. ef.cached = nil @@ -184,8 +199,8 @@ func (ef *FeeEstimator) RegisterBlock(block *btcutil.Block) error { var replacementCounts [estimateFeeDepth]int // Keep track of which txs were dropped in case of an orphan block. - dropped := registeredBlock{ - hash: block.Hash(), + dropped := ®isteredBlock{ + hash: *block.Hash(), transactions: make([]*observedTransaction, 0, 100), } @@ -200,41 +215,50 @@ func (ef *FeeEstimator) RegisterBlock(block *btcutil.Block) error { } // Put the observed tx in the oppropriate bin. - o.mined = height - blocksToConfirm := height - o.observed - 1 + // This shouldn't happen if the fee estimator works correctly, + // but return an error if it does. + if o.mined != mining.UnminedHeight { + log.Error("Estimate fee: transaction ", hash.String(), " has already been mined") + return errors.New("Transaction has already been mined") + } + // This shouldn't happen but check just in case to avoid - // a panic later. + // an out-of-bounds array index later. if blocksToConfirm >= estimateFeeDepth { continue } // Make sure we do not replace too many transactions per min. - if replacementCounts[blocksToConfirm] == ef.maxReplacements { + if replacementCounts[blocksToConfirm] == int(ef.maxReplacements) { continue } + o.mined = height + replacementCounts[blocksToConfirm]++ bin := ef.bin[blocksToConfirm] // Remove a random element and replace it with this new tx. - if len(bin) == ef.binSize { - l := ef.binSize - replacementCounts[blocksToConfirm] + if len(bin) == int(ef.binSize) { + // Don't drop transactions we have just added from this same block. + l := int(ef.binSize) - replacementCounts[blocksToConfirm] drop := rand.Intn(l) dropped.transactions = append(dropped.transactions, bin[drop]) bin[drop] = bin[l-1] - bin[l-1] = &o + bin[l-1] = o } else { - ef.bin[blocksToConfirm] = append(bin, &o) + bin = append(bin, o) } + ef.bin[blocksToConfirm] = bin } // Go through the mempool for txs that have been in too long. for hash, o := range ef.observed { - if height-o.observed >= estimateFeeDepth { + if o.mined == mining.UnminedHeight && height-o.observed >= estimateFeeDepth { delete(ef.observed, hash) } } @@ -253,6 +277,14 @@ func (ef *FeeEstimator) RegisterBlock(block *btcutil.Block) error { return nil } +// LastKnownHeight returns the height of the last block which was registered. +func (ef *FeeEstimator) LastKnownHeight() int32 { + ef.mtx.Lock() + defer ef.mtx.Unlock() + + return ef.lastKnownHeight +} + // Rollback unregisters a recently registered block from the FeeEstimator. // This can be used to reverse the effect of an orphaned block on the fee // estimator. The maximum number of rollbacks allowed is given by @@ -262,29 +294,24 @@ func (ef *FeeEstimator) RegisterBlock(block *btcutil.Block) error { // deleted if they have been observed too long ago. That means the result // of Rollback won't always be exactly the same as if the last block had not // happened, but it should be close enough. -func (ef *FeeEstimator) Rollback(block *btcutil.Block) error { - ef.Lock() - defer ef.Unlock() - - hash := block.Hash() +func (ef *FeeEstimator) Rollback(hash *chainhash.Hash) error { + ef.mtx.Lock() + defer ef.mtx.Unlock() // Find this block in the stack of recent registered blocks. var n int - for n = 1; n < len(ef.dropped); n++ { + for n = 1; n <= len(ef.dropped); n++ { if ef.dropped[len(ef.dropped)-n].hash.IsEqual(hash) { break } } - if n == len(ef.dropped) { + if n > len(ef.dropped) { return errors.New("no such block was recently registered") } for i := 0; i < n; i++ { - err := ef.rollback() - if err != nil { - return err - } + ef.rollback() } return nil @@ -292,28 +319,24 @@ func (ef *FeeEstimator) Rollback(block *btcutil.Block) error { // rollback rolls back the effect of the last block in the stack // of registered blocks. -func (ef *FeeEstimator) rollback() error { - +func (ef *FeeEstimator) rollback() { // The previous sorted list is invalid, so delete it. ef.cached = nil // pop the last list of dropped txs from the stack. last := len(ef.dropped) - 1 if last == -1 { - // Return if we cannot rollback. - return errors.New("max rollbacks reached") + // Cannot really happen because the exported calling function + // only rolls back a block already known to be in the list + // of dropped transactions. + return } - ef.numBlocksRegistered-- - dropped := ef.dropped[last] - ef.dropped = ef.dropped[0:last] // where we are in each bin as we replace txs? var replacementCounters [estimateFeeDepth]int - var err error - // Go through the txs in the dropped block. for _, o := range dropped.transactions { // Which bin was this tx in? @@ -326,9 +349,8 @@ func (ef *FeeEstimator) rollback() error { // Continue to go through that bin where we left off. for { if counter >= len(bin) { - // Create an error but keep going in case we can roll back - // more transactions successfully. - err = errors.New("illegal state: cannot rollback dropped transaction") + // Panic, as we have entered an unrecoverable invalid state. + panic(errors.New("illegal state: cannot rollback dropped transaction")) } prev := bin[counter] @@ -344,6 +366,8 @@ func (ef *FeeEstimator) rollback() error { counter++ } + + replacementCounters[blocksToConfirm] = counter } // Continue going through bins to find other txs to remove @@ -373,9 +397,11 @@ func (ef *FeeEstimator) rollback() error { } } - ef.lastKnownHeight-- + ef.dropped = ef.dropped[0:last] - return err + // The number of blocks the fee estimator has seen is decrimented. + ef.numBlocksRegistered-- + ef.lastKnownHeight-- } // estimateFeeSet is a set of txs that can that is sorted @@ -407,19 +433,26 @@ func (b *estimateFeeSet) estimateFee(confirmations int) SatoshiPerByte { return 0 } - var min, max uint32 = 0, 0 - for i := 0; i < confirmations-1; i++ { - min += b.bin[i] + // We don't have any transactions! + if len(b.feeRate) == 0 { + return 0 } - max = min + b.bin[confirmations-1] + var min, max int = 0, 0 + for i := 0; i < confirmations-1; i++ { + min += int(b.bin[i]) + } - // We don't have any transactions! - if min == 0 && max == 0 { - return 0 + max = min + int(b.bin[confirmations-1]) - 1 + if max < min { + max = min + } + feeIndex := (min + max) / 2 + if feeIndex >= len(b.feeRate) { + feeIndex = len(b.feeRate) - 1 } - return b.feeRate[(min+max-1)/2] * 1E-8 + return b.feeRate[feeIndex] } // newEstimateFeeSet creates a temporary data structure that @@ -464,9 +497,9 @@ func (ef *FeeEstimator) estimates() []SatoshiPerByte { // EstimateFee estimates the fee per byte to have a tx confirmed a given // number of blocks from now. -func (ef *FeeEstimator) EstimateFee(numBlocks uint32) (SatoshiPerByte, error) { - ef.Lock() - defer ef.Unlock() +func (ef *FeeEstimator) EstimateFee(numBlocks uint32) (BtcPerKilobyte, error) { + ef.mtx.Lock() + defer ef.mtx.Unlock() // If the number of registered blocks is below the minimum, return // an error. @@ -489,5 +522,5 @@ func (ef *FeeEstimator) EstimateFee(numBlocks uint32) (SatoshiPerByte, error) { ef.cached = ef.estimates() } - return ef.cached[int(numBlocks)-1], nil + return ef.cached[int(numBlocks)-1].ToBtcPerKb(), nil } diff --git a/mempool/estimatefee_test.go b/mempool/estimatefee_test.go index 91595d9cd0..ae3dec4bbe 100644 --- a/mempool/estimatefee_test.go +++ b/mempool/estimatefee_test.go @@ -19,19 +19,30 @@ import ( func newTestFeeEstimator(binSize, maxReplacements, maxRollback uint32) *FeeEstimator { return &FeeEstimator{ maxRollback: maxRollback, - lastKnownHeight: mining.UnminedHeight, - binSize: int(binSize), + lastKnownHeight: 0, + binSize: int32(binSize), minRegisteredBlocks: 0, - maxReplacements: int(maxReplacements), - observed: make(map[chainhash.Hash]observedTransaction), - dropped: make([]registeredBlock, 0, maxRollback), + maxReplacements: int32(maxReplacements), + observed: make(map[chainhash.Hash]*observedTransaction), + dropped: make([]*registeredBlock, 0, maxRollback), } } +// lastBlock is a linked list of the block hashes which have been +// processed by the test FeeEstimator. +type lastBlock struct { + hash *chainhash.Hash + prev *lastBlock +} + +// estimateFeeTester interacts with the FeeEstimator to keep track +// of its expected state. type estimateFeeTester struct { + ef *FeeEstimator t *testing.T version int32 height int32 + last *lastBlock } func (eft *estimateFeeTester) testTx(fee btcutil.Amount) *TxDesc { @@ -48,30 +59,48 @@ func (eft *estimateFeeTester) testTx(fee btcutil.Amount) *TxDesc { } } -func expectedFeePerByte(t *TxDesc) SatoshiPerByte { +func expectedFeePerKilobyte(t *TxDesc) BtcPerKilobyte { size := float64(t.TxDesc.Tx.MsgTx().SerializeSize()) fee := float64(t.TxDesc.Fee) - return SatoshiPerByte(fee / size * 1E-8) + return SatoshiPerByte(fee / size).ToBtcPerKb() } -func (eft *estimateFeeTester) testBlock(txs []*wire.MsgTx) *btcutil.Block { - +func (eft *estimateFeeTester) newBlock(txs []*wire.MsgTx) { eft.height++ + block := btcutil.NewBlock(&wire.MsgBlock{ Transactions: txs, }) block.SetHeight(eft.height) - return block + eft.last = &lastBlock{block.Hash(), eft.last} + + eft.ef.RegisterBlock(block) +} + +func (eft *estimateFeeTester) rollback() { + if eft.last == nil { + return + } + + err := eft.ef.Rollback(eft.last.hash) + + if err != nil { + eft.t.Errorf("Could not rollback: %v", err) + } + + eft.height-- + eft.last = eft.last.prev } +// TestEstimateFee tests basic functionality in the FeeEstimator. func TestEstimateFee(t *testing.T) { - ef := newTestFeeEstimator(5, 3, 0) - eft := estimateFeeTester{t: t} + ef := newTestFeeEstimator(5, 3, 1) + eft := estimateFeeTester{ef: ef, t: t} // Try with no txs and get zero for all queries. - expected := SatoshiPerByte(0.0) + expected := BtcPerKilobyte(0.0) for i := uint32(1); i <= estimateFeeDepth; i++ { estimated, _ := ef.EstimateFee(i) @@ -85,7 +114,7 @@ func TestEstimateFee(t *testing.T) { ef.ObserveTransaction(tx) // Expected should still be zero because this is still in the mempool. - expected = SatoshiPerByte(0.0) + expected = BtcPerKilobyte(0.0) for i := uint32(1); i <= estimateFeeDepth; i++ { estimated, _ := ef.EstimateFee(i) @@ -97,7 +126,7 @@ func TestEstimateFee(t *testing.T) { // Change minRegisteredBlocks to make sure that works. Error return // value expected. ef.minRegisteredBlocks = 1 - expected = SatoshiPerByte(-1.0) + expected = BtcPerKilobyte(-1.0) for i := uint32(1); i <= estimateFeeDepth; i++ { estimated, _ := ef.EstimateFee(i) @@ -106,9 +135,35 @@ func TestEstimateFee(t *testing.T) { } } - // Record a block. - ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{tx.Tx.MsgTx()})) - expected = expectedFeePerByte(tx) + // Record a block with the new tx. + eft.newBlock([]*wire.MsgTx{tx.Tx.MsgTx()}) + expected = expectedFeePerKilobyte(tx) + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f when one tx is binned; got %f", expected, estimated) + } + } + + // Roll back the last block; this was an orphan block. + ef.minRegisteredBlocks = 0 + eft.rollback() + expected = BtcPerKilobyte(0.0) + for i := uint32(1); i <= estimateFeeDepth; i++ { + estimated, _ := ef.EstimateFee(i) + + if estimated != expected { + t.Errorf("Estimate fee error: expected %f after rolling back block; got %f", expected, estimated) + } + } + + // Record an empty block and then a block with the new tx. + // This test was made because of a bug that only appeared when there + // were no transactions in the first bin. + eft.newBlock([]*wire.MsgTx{}) + eft.newBlock([]*wire.MsgTx{tx.Tx.MsgTx()}) + expected = expectedFeePerKilobyte(tx) for i := uint32(1); i <= estimateFeeDepth; i++ { estimated, _ := ef.EstimateFee(i) @@ -125,22 +180,22 @@ func TestEstimateFee(t *testing.T) { ef.ObserveTransaction(txB) ef.ObserveTransaction(txC) - // Record 8 empty blocks. - for i := 0; i < 8; i++ { - ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{})) + // Record 7 empty blocks. + for i := 0; i < 7; i++ { + eft.newBlock([]*wire.MsgTx{}) } // Mine the first tx. - ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{txA.Tx.MsgTx()})) + eft.newBlock([]*wire.MsgTx{txA.Tx.MsgTx()}) // Now the estimated amount should depend on the value // of the argument to estimate fee. for i := uint32(1); i <= estimateFeeDepth; i++ { estimated, _ := ef.EstimateFee(i) - if i > 8 { - expected = expectedFeePerByte(txA) + if i > 2 { + expected = expectedFeePerKilobyte(txA) } else { - expected = expectedFeePerByte(tx) + expected = expectedFeePerKilobyte(tx) } if estimated != expected { t.Errorf("Estimate fee error: expected %f on round %d; got %f", expected, i, estimated) @@ -149,22 +204,22 @@ func TestEstimateFee(t *testing.T) { // Record 5 more empty blocks. for i := 0; i < 5; i++ { - ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{})) + eft.newBlock([]*wire.MsgTx{}) } // Mine the next tx. - ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{txB.Tx.MsgTx()})) + eft.newBlock([]*wire.MsgTx{txB.Tx.MsgTx()}) // Now the estimated amount should depend on the value // of the argument to estimate fee. for i := uint32(1); i <= estimateFeeDepth; i++ { estimated, _ := ef.EstimateFee(i) - if i <= 8 { - expected = expectedFeePerByte(txB) - } else if i <= 8+6 { - expected = expectedFeePerByte(tx) + if i <= 2 { + expected = expectedFeePerKilobyte(txB) + } else if i <= 8 { + expected = expectedFeePerKilobyte(tx) } else { - expected = expectedFeePerByte(txA) + expected = expectedFeePerKilobyte(txA) } if estimated != expected { @@ -174,22 +229,24 @@ func TestEstimateFee(t *testing.T) { // Record 9 more empty blocks. for i := 0; i < 10; i++ { - ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{})) + eft.newBlock([]*wire.MsgTx{}) } // Mine txC. - ef.RegisterBlock(eft.testBlock([]*wire.MsgTx{txC.Tx.MsgTx()})) + eft.newBlock([]*wire.MsgTx{txC.Tx.MsgTx()}) // This should have no effect on the outcome because too // many blocks have been mined for txC to be recorded. for i := uint32(1); i <= estimateFeeDepth; i++ { estimated, _ := ef.EstimateFee(i) - if i <= 8 { - expected = expectedFeePerByte(txB) + if i <= 2 { + expected = expectedFeePerKilobyte(txC) + } else if i <= 8 { + expected = expectedFeePerKilobyte(txB) } else if i <= 8+6 { - expected = expectedFeePerByte(tx) + expected = expectedFeePerKilobyte(tx) } else { - expected = expectedFeePerByte(txA) + expected = expectedFeePerKilobyte(txA) } if estimated != expected { @@ -198,133 +255,112 @@ func TestEstimateFee(t *testing.T) { } } -func (eft *estimateFeeTester) estimates(ef *FeeEstimator) [estimateFeeDepth]SatoshiPerByte { +func (eft *estimateFeeTester) estimates() [estimateFeeDepth]BtcPerKilobyte { // Generate estimates - var estimates [estimateFeeDepth]SatoshiPerByte + var estimates [estimateFeeDepth]BtcPerKilobyte for i := 0; i < estimateFeeDepth; i++ { - estimates[i], _ = ef.EstimateFee(1) + estimates[i], _ = eft.ef.EstimateFee(uint32(i + 1)) } // Check that all estimated fee results go in descending order. for i := 1; i < estimateFeeDepth; i++ { if estimates[i] > estimates[i-1] { - eft.t.Error("Estimates not in descending order.") + eft.t.Error("Estimates not in descending order; got ", + estimates[i], " for estimate ", i, " and ", estimates[i-1], " for ", (i - 1)) + panic("invalid state.") } } return estimates } -func (eft *estimateFeeTester) round(ef *FeeEstimator, - txHistory [][]*TxDesc, blockHistory []*btcutil.Block, - estimateHistory [][estimateFeeDepth]SatoshiPerByte, - txPerRound, txPerBlock, maxRollback uint32) ([][]*TxDesc, - []*btcutil.Block, [][estimateFeeDepth]SatoshiPerByte) { +func (eft *estimateFeeTester) round(txHistory [][]*TxDesc, + estimateHistory [][estimateFeeDepth]BtcPerKilobyte, + txPerRound, txPerBlock uint32) ([][]*TxDesc, [][estimateFeeDepth]BtcPerKilobyte) { // generate new txs. var newTxs []*TxDesc for i := uint32(0); i < txPerRound; i++ { newTx := eft.testTx(btcutil.Amount(rand.Intn(1000000))) - ef.ObserveTransaction(newTx) + eft.ef.ObserveTransaction(newTx) newTxs = append(newTxs, newTx) } - // Construct new tx history. - txHistory = append(txHistory, newTxs) - if len(txHistory) > estimateFeeDepth { - txHistory = txHistory[1 : estimateFeeDepth+1] + // Generate mempool. + mempool := make(map[*observedTransaction]*TxDesc) + for _, h := range txHistory { + for _, t := range h { + if o, exists := eft.ef.observed[*t.Tx.Hash()]; exists && o.mined == mining.UnminedHeight { + mempool[o] = t + } + } } // generate new block, with no duplicates. - newBlockTxs := make(map[chainhash.Hash]*wire.MsgTx) i := uint32(0) - for i < txPerBlock { - n := rand.Intn(len(txHistory)) - m := rand.Intn(int(txPerRound)) - - tx := txHistory[n][m] - hash := *tx.Tx.Hash() - - if _, ok := newBlockTxs[hash]; ok { - continue - } - - newBlockTxs[hash] = tx.Tx.MsgTx() + newBlockList := make([]*wire.MsgTx, 0, txPerBlock) + for _, t := range mempool { + newBlockList = append(newBlockList, t.TxDesc.Tx.MsgTx()) i++ - } - var newBlockList []*wire.MsgTx - for _, tx := range newBlockTxs { - newBlockList = append(newBlockList, tx) + if i == txPerBlock { + break + } } - newBlock := eft.testBlock(newBlockList) - ef.RegisterBlock(newBlock) + // Register a new block. + eft.newBlock(newBlockList) // return results. - estimates := eft.estimates(ef) + estimates := eft.estimates() // Return results - blockHistory = append(blockHistory, newBlock) - if len(blockHistory) > int(maxRollback) { - blockHistory = blockHistory[1 : maxRollback+1] - } - - return txHistory, blockHistory, append(estimateHistory, estimates) + return append(txHistory, newTxs), append(estimateHistory, estimates) } +// TestEstimateFeeRollback tests the rollback function, which undoes the +// effect of a adding a new block. func TestEstimateFeeRollback(t *testing.T) { - txPerRound := uint32(20) - txPerBlock := uint32(10) - binSize := uint32(5) - maxReplacements := uint32(3) + txPerRound := uint32(7) + txPerBlock := uint32(5) + binSize := uint32(6) + maxReplacements := uint32(4) stepsBack := 2 rounds := 30 - ef := newTestFeeEstimator(binSize, maxReplacements, uint32(stepsBack)) - eft := estimateFeeTester{t: t} + eft := estimateFeeTester{ef: newTestFeeEstimator(binSize, maxReplacements, uint32(stepsBack)), t: t} var txHistory [][]*TxDesc - var blockHistory []*btcutil.Block - estimateHistory := [][estimateFeeDepth]SatoshiPerByte{eft.estimates(ef)} - - // Make some initial rounds so that we have room to step back. - for round := 0; round < stepsBack-1; round++ { - txHistory, blockHistory, estimateHistory = - eft.round(ef, txHistory, blockHistory, estimateHistory, - txPerRound, txPerBlock, uint32(stepsBack)) - } + estimateHistory := [][estimateFeeDepth]BtcPerKilobyte{eft.estimates()} for round := 0; round < rounds; round++ { - txHistory, blockHistory, estimateHistory = - eft.round(ef, txHistory, blockHistory, estimateHistory, - txPerRound, txPerBlock, uint32(stepsBack)) + // Go forward a few rounds. + for step := 0; step <= stepsBack; step++ { + txHistory, estimateHistory = + eft.round(txHistory, estimateHistory, txPerRound, txPerBlock) + } + // Now go back. for step := 0; step < stepsBack; step++ { - err := ef.rollback() - if err != nil { - t.Fatal("Could not rollback: ", err) - } + eft.rollback() + // After rolling back, we should have the same estimated + // fees as before. expected := estimateHistory[len(estimateHistory)-step-2] - estimates := eft.estimates(ef) + estimates := eft.estimates() // Ensure that these are both the same. for i := 0; i < estimateFeeDepth; i++ { if expected[i] != estimates[i] { t.Errorf("Rollback value mismatch. Expected %f, got %f. ", expected[i], estimates[i]) + return } } } - // Remove last estries from estimateHistory + // Erase history. + txHistory = txHistory[0 : len(txHistory)-stepsBack] estimateHistory = estimateHistory[0 : len(estimateHistory)-stepsBack] - - // replay the previous blocks. - for b := 0; b < stepsBack; b++ { - ef.RegisterBlock(blockHistory[b]) - estimateHistory = append(estimateHistory, eft.estimates(ef)) - } } } From 1333ad7f783d496975d47eaf7b42c616f8476793 Mon Sep 17 00:00:00 2001 From: Daniel Krawisz Date: Mon, 13 Nov 2017 22:37:35 -0600 Subject: [PATCH 0150/1056] FeeEstimator added to server. Mempool alerts the fee estimator of new txs that it observes. The block manager alerts the fee estimator of new and orphaned blocks. Check for invalid state and recreate FeeEstimator if necessary. --- mempool/estimatefee.go | 9 +++++++++ mempool/mempool.go | 11 ++++++++++- netsync/interface.go | 2 ++ netsync/manager.go | 23 +++++++++++++++++++++++ server.go | 5 +++++ 5 files changed, 49 insertions(+), 1 deletion(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index 354eabca05..7f56403d2c 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -34,6 +34,15 @@ const ( // can be made by the txs found in a given block. estimateFeeMaxReplacements = 10 + // DefaultEstimateFeeMaxRollback is the default number of rollbacks + // allowed by the fee estimator for orphaned blocks. + DefaultEstimateFeeMaxRollback = 2 + + // DefaultEstimateFeeMinRegisteredBlocks is the default minimum + // number of blocks which must be observed by the fee estimator before + // it will provide fee estimations. + DefaultEstimateFeeMinRegisteredBlocks = 3 + bytePerKb = 1024 btcPerSatoshi = 1E-8 diff --git a/mempool/mempool.go b/mempool/mempool.go index 31d294a651..511ee6b46b 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -89,6 +89,10 @@ type Config struct { // indexing the unconfirmed transactions in the memory pool. // This can be nil if the address index is not enabled. AddrIndex *indexers.AddrIndex + + // FeeEstimatator provides a feeEstimator. If it is not nil, the mempool + // records all new transactions it observes into the feeEstimator. + FeeEstimator *FeeEstimator } // Policy houses the policy (configuration parameters) which is used to @@ -527,8 +531,8 @@ func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil }, StartingPriority: mining.CalcPriority(tx.MsgTx(), utxoView, height), } - mp.pool[*tx.Hash()] = txD + mp.pool[*tx.Hash()] = txD for _, txIn := range tx.MsgTx().TxIn { mp.outpoints[txIn.PreviousOutPoint] = tx } @@ -540,6 +544,11 @@ func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil mp.cfg.AddrIndex.AddUnconfirmedTx(tx, utxoView) } + // Record this tx for fee estimation if enabled. + if mp.cfg.FeeEstimator != nil { + mp.cfg.FeeEstimator.ObserveTransaction(txD) + } + return txD } diff --git a/netsync/interface.go b/netsync/interface.go index a177cb96d5..2e6edce8e3 100644 --- a/netsync/interface.go +++ b/netsync/interface.go @@ -36,4 +36,6 @@ type Config struct { DisableCheckpoints bool MaxPeers int + + FeeEstimator *mempool.FeeEstimator } diff --git a/netsync/manager.go b/netsync/manager.go index 7f1d3605bd..fe764a70c8 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -167,6 +167,9 @@ type SyncManager struct { headerList *list.List startHeader *list.Element nextCheckpoint *chaincfg.Checkpoint + + // An optional fee estimator. + feeEstimator *mempool.FeeEstimator } // resetHeaderState sets the headers-first mode state to values appropriate for @@ -1249,6 +1252,20 @@ func (sm *SyncManager) handleBlockchainNotification(notification *blockchain.Not sm.peerNotifier.AnnounceNewTransactions(acceptedTxs) } + // Register block with the fee estimator, if it exists. + if sm.feeEstimator != nil { + err := sm.feeEstimator.RegisterBlock(block) + + // If an error is somehow generated then the fee estimator + // has entered an invalid state. Since it doesn't know how + // to recover, create a new one. + if err != nil { + sm.feeEstimator = mempool.NewFeeEstimator( + mempool.DefaultEstimateFeeMaxRollback, + mempool.DefaultEstimateFeeMinRegisteredBlocks) + } + } + // A block has been disconnected from the main block chain. case blockchain.NTBlockDisconnected: block, ok := notification.Data.(*btcutil.Block) @@ -1269,6 +1286,11 @@ func (sm *SyncManager) handleBlockchainNotification(notification *blockchain.Not sm.txMemPool.RemoveTransaction(tx, true) } } + + // Rollback previous block recorded by the fee estimator. + if sm.feeEstimator != nil { + sm.feeEstimator.Rollback(block.Hash()) + } } } @@ -1417,6 +1439,7 @@ func New(config *Config) (*SyncManager, error) { msgChan: make(chan interface{}, config.MaxPeers*3), headerList: list.New(), quit: make(chan struct{}), + feeEstimator: config.FeeEstimator, } best := sm.chain.BestSnapshot() diff --git a/server.go b/server.go index b124914810..c9132471e1 100644 --- a/server.go +++ b/server.go @@ -2411,6 +2411,10 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param return nil, err } + feeEstimator := mempool.NewFeeEstimator( + mempool.DefaultEstimateFeeMaxRollback, + mempool.DefaultEstimateFeeMinRegisteredBlocks) + txC := mempool.Config{ Policy: mempool.Policy{ DisableRelayPriority: cfg.NoRelayPriority, @@ -2433,6 +2437,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param SigCache: s.sigCache, HashCache: s.hashCache, AddrIndex: s.addrIndex, + FeeEstimator: feeEstimator, } s.txMemPool = mempool.New(&txC) From 4fd446028fc600090ef5f0c5c5156afe602f76a6 Mon Sep 17 00:00:00 2001 From: Daniel Krawisz Date: Mon, 13 Nov 2017 16:39:16 -0600 Subject: [PATCH 0151/1056] Enable estimatefee rpc command. --- mempool/estimatefee.go | 6 +++--- mempool/estimatefee_test.go | 8 ++++---- rpcclient/chain.go | 37 +++++++++++++++++++++++++++++++++++++ rpcserver.go | 29 ++++++++++++++++++++++++++++- rpcserverhelp.go | 10 ++++++++++ server.go | 29 +++++++++++++++-------------- 6 files changed, 97 insertions(+), 22 deletions(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index 7f56403d2c..724f3c4e4b 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -12,9 +12,9 @@ import ( "sort" "sync" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/mining" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/mining" + "github.com/roasbeef/btcutil" ) // TODO incorporate Alex Morcos' modifications to Gavin's initial model diff --git a/mempool/estimatefee_test.go b/mempool/estimatefee_test.go index ae3dec4bbe..df73e322c8 100644 --- a/mempool/estimatefee_test.go +++ b/mempool/estimatefee_test.go @@ -8,10 +8,10 @@ import ( "math/rand" "testing" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/mining" - "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/roasbeef/btcd/mining" + "github.com/roasbeef/btcd/wire" + "github.com/roasbeef/btcutil" ) // newTestFeeEstimator creates a feeEstimator with some different parameters diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 41faea1839..3d8f9c813c 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -557,6 +557,43 @@ func (c *Client) GetRawMempoolVerbose() (map[string]btcjson.GetRawMempoolVerbose return c.GetRawMempoolVerboseAsync().Receive() } +// FutureEstimateFeeResult is a future promise to deliver the result of a +// EstimateFeeAsync RPC invocation (or an applicable error). +type FutureEstimateFeeResult chan *response + +// Receive waits for the response promised by the future and returns the info +// provided by the server. +func (r FutureEstimateFeeResult) Receive() (float64, error) { + res, err := receiveFuture(r) + if err != nil { + return -1, err + } + + // Unmarshal result as a getinfo result object. + var fee float64 + err = json.Unmarshal(res, &fee) + if err != nil { + return -1, err + } + + return fee, nil +} + +// EstimateFeeAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See EstimateFee for the blocking version and more details. +func (c *Client) EstimateFeeAsync(numBlocks int64) FutureEstimateFeeResult { + cmd := btcjson.NewEstimateFeeCmd(numBlocks) + return c.sendCmd(cmd) +} + +// EstimateFee provides an estimated fee in bitcoins per kilobyte. +func (c *Client) EstimateFee(numBlocks int64) (float64, error) { + return c.EstimateFeeAsync(numBlocks).Receive() +} + // FutureVerifyChainResult is a future promise to deliver the result of a // VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync // invocation (or an applicable error). diff --git a/rpcserver.go b/rpcserver.go index b10d5287b2..d437775a75 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -132,6 +132,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "debuglevel": handleDebugLevel, "decoderawtransaction": handleDecodeRawTransaction, "decodescript": handleDecodeScript, + "estimatefee": handleEstimateFee, "generate": handleGenerate, "getaddednodeinfo": handleGetAddedNodeInfo, "getbestblock": handleGetBestBlock, @@ -224,7 +225,6 @@ var rpcAskWallet = map[string]struct{}{ // Commands that are currently unimplemented, but should ultimately be. var rpcUnimplemented = map[string]struct{}{ - "estimatefee": {}, "estimatepriority": {}, "getchaintips": {}, "getmempoolentry": {}, @@ -254,6 +254,7 @@ var rpcLimited = map[string]struct{}{ "createrawtransaction": {}, "decoderawtransaction": {}, "decodescript": {}, + "estimatefee": {}, "getbestblock": {}, "getbestblockhash": {}, "getblock": {}, @@ -853,6 +854,28 @@ func handleDecodeScript(s *rpcServer, cmd interface{}, closeChan <-chan struct{} return reply, nil } +// handleEstimateFee handles estimatefee commands. +func handleEstimateFee(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.EstimateFeeCmd) + + if s.cfg.FeeEstimator == nil { + return nil, errors.New("Fee estimation disabled") + } + + if c.NumBlocks <= 0 { + return -1.0, errors.New("Parameter NumBlocks must be positive") + } + + feeRate, err := s.cfg.FeeEstimator.EstimateFee(uint32(c.NumBlocks)) + + if err != nil { + return -1.0, err + } + + // Convert to satoshis per kb. + return float64(feeRate.ToSatoshiPerKb()), nil +} + // handleGenerate handles generate commands. func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { // Respond with an error if there are no addresses to pay the @@ -4247,6 +4270,10 @@ type rpcserverConfig struct { TxIndex *indexers.TxIndex AddrIndex *indexers.AddrIndex CfIndex *indexers.CfIndex + + // The fee estimator keeps track of how long transactions are left in + // the mempool before they are mined into blocks. + FeeEstimator *mempool.FeeEstimator } // newRPCServer returns a new instance of the rpcServer struct. diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 19a3d724ed..c22448e1c0 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -115,6 +115,15 @@ var helpDescsEnUS = map[string]string{ "decodescript--synopsis": "Returns a JSON object with information about the provided hex-encoded script.", "decodescript-hexscript": "Hex-encoded script", + // EstimateFeeCmd help. + "estimatefee--synopsis": "Estimate the fee per kilobyte in satoshis " + + "required for a transaction to be mined before a certain number of " + + "blocks have been generated.", + "estimatefee-numblocks": "The maximum number of blocks which can be " + + "generated before the transaction is mined.", + "estimatefee--result0": "Estimated fee per kilobyte in satoshis for a block to " + + "be mined in the next NumBlocks blocks.", + // GenerateCmd help "generate--synopsis": "Generates a set number of blocks (simnet or regtest only) and returns a JSON\n" + " array of their hashes.", @@ -663,6 +672,7 @@ var rpcResultTypes = map[string][]interface{}{ "debuglevel": {(*string)(nil), (*string)(nil)}, "decoderawtransaction": {(*btcjson.TxRawDecodeResult)(nil)}, "decodescript": {(*btcjson.DecodeScriptResult)(nil)}, + "estimatefee": {(*float64)(nil)}, "generate": {(*[]string)(nil)}, "getaddednodeinfo": {(*[]string)(nil), (*[]btcjson.GetAddedNodeInfoResult)(nil)}, "getbestblock": {(*btcjson.GetBestBlockResult)(nil)}, diff --git a/server.go b/server.go index c9132471e1..fa9370ac9b 100644 --- a/server.go +++ b/server.go @@ -2572,20 +2572,21 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param } s.rpcServer, err = newRPCServer(&rpcserverConfig{ - Listeners: rpcListeners, - StartupTime: s.startupTime, - ConnMgr: &rpcConnManager{&s}, - SyncMgr: &rpcSyncMgr{&s, s.syncManager}, - TimeSource: s.timeSource, - Chain: s.chain, - ChainParams: chainParams, - DB: db, - TxMemPool: s.txMemPool, - Generator: blockTemplateGenerator, - CPUMiner: s.cpuMiner, - TxIndex: s.txIndex, - AddrIndex: s.addrIndex, - CfIndex: s.cfIndex, + Listeners: rpcListeners, + StartupTime: s.startupTime, + ConnMgr: &rpcConnManager{&s}, + SyncMgr: &rpcSyncMgr{&s, s.syncManager}, + TimeSource: s.timeSource, + Chain: s.chain, + ChainParams: chainParams, + DB: db, + TxMemPool: s.txMemPool, + Generator: blockTemplateGenerator, + CPUMiner: s.cpuMiner, + TxIndex: s.txIndex, + AddrIndex: s.addrIndex, + CfIndex: s.cfIndex, + FeeEstimator: feeEstimator, }) if err != nil { return nil, err From 47113d428cd666e2921ae64c1575ff830bb2341e Mon Sep 17 00:00:00 2001 From: Daniel Krawisz Date: Mon, 29 Aug 2016 23:39:19 -0500 Subject: [PATCH 0152/1056] It is now possible to save and restore the state of the FeeEstimator and the server searches the database for a previous state to load when the program is turned on. --- mempool/estimatefee.go | 218 +++++++++++++++++++++++++++++++++++- mempool/estimatefee_test.go | 58 ++++++++++ rpcserver.go | 2 +- server.go | 48 +++++++- 4 files changed, 318 insertions(+), 8 deletions(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index 724f3c4e4b..234c5cf4bb 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -5,11 +5,15 @@ package mempool import ( + "bytes" + "encoding/binary" "errors" "fmt" + "io" "math" "math/rand" "sort" + "strings" "sync" "github.com/roasbeef/btcd/chaincfg/chainhash" @@ -20,8 +24,6 @@ import ( // TODO incorporate Alex Morcos' modifications to Gavin's initial model // https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2014-October/006824.html -// TODO store and restore the FeeEstimator state in the database. - const ( // estimateFeeDepth is the maximum number of blocks before a transaction // is confirmed that we want to track. @@ -48,6 +50,12 @@ const ( btcPerSatoshi = 1E-8 ) +var ( + // EstimateFeeDatabaseKey is the key that we use to + // store the fee estimator in the database. + EstimateFeeDatabaseKey = []byte("estimatefee") +) + // SatoshiPerByte is number with units of satoshis per byte. type SatoshiPerByte float64 @@ -99,6 +107,29 @@ type observedTransaction struct { mined int32 } +func (o *observedTransaction) Serialize(w io.Writer) { + binary.Write(w, binary.BigEndian, o.hash) + binary.Write(w, binary.BigEndian, o.feeRate) + binary.Write(w, binary.BigEndian, o.observed) + binary.Write(w, binary.BigEndian, o.mined) +} + +func deserializeObservedTransaction(r io.Reader) (*observedTransaction, error) { + ot := observedTransaction{} + + // The first 32 bytes should be a hash. + binary.Read(r, binary.BigEndian, &ot.hash) + + // The next 8 are SatoshiPerByte + binary.Read(r, binary.BigEndian, &ot.feeRate) + + // And next there are two uint32's. + binary.Read(r, binary.BigEndian, &ot.observed) + binary.Read(r, binary.BigEndian, &ot.mined) + + return &ot, nil +} + // registeredBlock has the hash of a block and the list of transactions // it mined which had been previously observed by the FeeEstimator. It // is used if Rollback is called to reverse the effect of registering @@ -108,6 +139,15 @@ type registeredBlock struct { transactions []*observedTransaction } +func (rb *registeredBlock) serialize(w io.Writer, txs map[*observedTransaction]uint32) { + binary.Write(w, binary.BigEndian, rb.hash) + + binary.Write(w, binary.BigEndian, uint32(len(rb.transactions))) + for _, o := range rb.transactions { + binary.Write(w, binary.BigEndian, txs[o]) + } +} + // FeeEstimator manages the data necessary to create // fee estimations. It is safe for concurrent access. type FeeEstimator struct { @@ -533,3 +573,177 @@ func (ef *FeeEstimator) EstimateFee(numBlocks uint32) (BtcPerKilobyte, error) { return ef.cached[int(numBlocks)-1].ToBtcPerKb(), nil } + +// In case the format for the serialized version of the FeeEstimator changes, +// we use a version number. If the version number changes, it does not make +// sense to try to upgrade a previous version to a new version. Instead, just +// start fee estimation over. +const estimateFeeSaveVersion = 1 + +func deserializeRegisteredBlock(r io.Reader, txs map[uint32]*observedTransaction) (*registeredBlock, error) { + var lenTransactions uint32 + + rb := ®isteredBlock{} + binary.Read(r, binary.BigEndian, &rb.hash) + binary.Read(r, binary.BigEndian, &lenTransactions) + + rb.transactions = make([]*observedTransaction, lenTransactions) + + for i := uint32(0); i < lenTransactions; i++ { + var index uint32 + binary.Read(r, binary.BigEndian, &index) + rb.transactions[i] = txs[index] + } + + return rb, nil +} + +// FeeEstimatorState represents a saved FeeEstimator that can be +// restored with data from an earlier session of the program. +type FeeEstimatorState []byte + +// observedTxSet is a set of txs that can that is sorted +// by hash. It exists for serialization purposes so that +// a serialized state always comes out the same. +type observedTxSet []*observedTransaction + +func (q observedTxSet) Len() int { return len(q) } + +func (q observedTxSet) Less(i, j int) bool { + return strings.Compare(q[i].hash.String(), q[j].hash.String()) < 0 +} + +func (q observedTxSet) Swap(i, j int) { + q[i], q[j] = q[j], q[i] +} + +// Save records the current state of the FeeEstimator to a []byte that +// can be restored later. +func (ef *FeeEstimator) Save() FeeEstimatorState { + ef.mtx.Lock() + defer ef.mtx.Unlock() + + // TODO figure out what the capacity should be. + w := bytes.NewBuffer(make([]byte, 0)) + + binary.Write(w, binary.BigEndian, uint32(estimateFeeSaveVersion)) + + // Insert basic parameters. + binary.Write(w, binary.BigEndian, &ef.maxRollback) + binary.Write(w, binary.BigEndian, &ef.binSize) + binary.Write(w, binary.BigEndian, &ef.maxReplacements) + binary.Write(w, binary.BigEndian, &ef.minRegisteredBlocks) + binary.Write(w, binary.BigEndian, &ef.lastKnownHeight) + binary.Write(w, binary.BigEndian, &ef.numBlocksRegistered) + + // Put all the observed transactions in a sorted list. + var txCount uint32 + ots := make([]*observedTransaction, len(ef.observed)) + for hash := range ef.observed { + ots[txCount] = ef.observed[hash] + txCount++ + } + + sort.Sort(observedTxSet(ots)) + + txCount = 0 + observed := make(map[*observedTransaction]uint32) + binary.Write(w, binary.BigEndian, uint32(len(ef.observed))) + for _, ot := range ots { + ot.Serialize(w) + observed[ot] = txCount + txCount++ + } + + // Save all the right bins. + for _, list := range ef.bin { + + binary.Write(w, binary.BigEndian, uint32(len(list))) + + for _, o := range list { + binary.Write(w, binary.BigEndian, observed[o]) + } + } + + // Dropped transactions. + binary.Write(w, binary.BigEndian, uint32(len(ef.dropped))) + for _, registered := range ef.dropped { + registered.serialize(w, observed) + } + + // Commit the tx and return. + return FeeEstimatorState(w.Bytes()) +} + +// RestoreFeeEstimator takes a FeeEstimatorState that was previously +// returned by Save and restores it to a FeeEstimator +func RestoreFeeEstimator(data FeeEstimatorState) (*FeeEstimator, error) { + r := bytes.NewReader([]byte(data)) + + // Check version + var version uint32 + err := binary.Read(r, binary.BigEndian, &version) + if err != nil { + return nil, err + } + if version != estimateFeeSaveVersion { + return nil, fmt.Errorf("Incorrect version: expected %d found %d", estimateFeeSaveVersion, version) + } + + ef := &FeeEstimator{ + observed: make(map[chainhash.Hash]*observedTransaction), + } + + // Read basic parameters. + binary.Read(r, binary.BigEndian, &ef.maxRollback) + binary.Read(r, binary.BigEndian, &ef.binSize) + binary.Read(r, binary.BigEndian, &ef.maxReplacements) + binary.Read(r, binary.BigEndian, &ef.minRegisteredBlocks) + binary.Read(r, binary.BigEndian, &ef.lastKnownHeight) + binary.Read(r, binary.BigEndian, &ef.numBlocksRegistered) + + // Read transactions. + var numObserved uint32 + observed := make(map[uint32]*observedTransaction) + binary.Read(r, binary.BigEndian, &numObserved) + for i := uint32(0); i < numObserved; i++ { + ot, err := deserializeObservedTransaction(r) + if err != nil { + return nil, err + } + observed[i] = ot + ef.observed[ot.hash] = ot + } + + // Read bins. + for i := 0; i < estimateFeeDepth; i++ { + var numTransactions uint32 + binary.Read(r, binary.BigEndian, &numTransactions) + bin := make([]*observedTransaction, numTransactions) + for j := uint32(0); j < numTransactions; j++ { + var index uint32 + binary.Read(r, binary.BigEndian, &index) + + var exists bool + bin[j], exists = observed[index] + if !exists { + return nil, fmt.Errorf("Invalid transaction reference %d", index) + } + } + ef.bin[i] = bin + } + + // Read dropped transactions. + var numDropped uint32 + binary.Read(r, binary.BigEndian, &numDropped) + ef.dropped = make([]*registeredBlock, numDropped) + for i := uint32(0); i < numDropped; i++ { + var err error + ef.dropped[int(i)], err = deserializeRegisteredBlock(r, observed) + if err != nil { + return nil, err + } + } + + return ef, nil +} diff --git a/mempool/estimatefee_test.go b/mempool/estimatefee_test.go index df73e322c8..071306738e 100644 --- a/mempool/estimatefee_test.go +++ b/mempool/estimatefee_test.go @@ -5,6 +5,7 @@ package mempool import ( + "bytes" "math/rand" "testing" @@ -364,3 +365,60 @@ func TestEstimateFeeRollback(t *testing.T) { estimateHistory = estimateHistory[0 : len(estimateHistory)-stepsBack] } } + +func (eft *estimateFeeTester) checkSaveAndRestore( + previousEstimates [estimateFeeDepth]BtcPerKilobyte) { + + // Get the save state. + save := eft.ef.Save() + + // Save and restore database. + var err error + eft.ef, err = RestoreFeeEstimator(save) + if err != nil { + eft.t.Fatalf("Could not restore database: %s", err) + } + + // Save again and check that it matches the previous one. + redo := eft.ef.Save() + if !bytes.Equal(save, redo) { + eft.t.Fatalf("Restored states do not match: %v %v", save, redo) + } + + // Check that the results match. + newEstimates := eft.estimates() + + for i, prev := range previousEstimates { + if prev != newEstimates[i] { + eft.t.Error("Mismatch in estimate ", i, " after restore; got ", newEstimates[i], " but expected ", prev) + } + } +} + +// TestSave tests saving and restoring to a []byte. +func TestDatabase(t *testing.T) { + + txPerRound := uint32(7) + txPerBlock := uint32(5) + binSize := uint32(6) + maxReplacements := uint32(4) + rounds := 8 + + eft := estimateFeeTester{ef: newTestFeeEstimator(binSize, maxReplacements, uint32(rounds)+1), t: t} + var txHistory [][]*TxDesc + estimateHistory := [][estimateFeeDepth]BtcPerKilobyte{eft.estimates()} + + for round := 0; round < rounds; round++ { + eft.checkSaveAndRestore(estimateHistory[len(estimateHistory)-1]) + + // Go forward one step. + txHistory, estimateHistory = + eft.round(txHistory, estimateHistory, txPerRound, txPerBlock) + } + + // Reverse the process and try again. + for round := 1; round <= rounds; round++ { + eft.rollback() + eft.checkSaveAndRestore(estimateHistory[len(estimateHistory)-round-1]) + } +} diff --git a/rpcserver.go b/rpcserver.go index d437775a75..0dae52a7f4 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -873,7 +873,7 @@ func handleEstimateFee(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) } // Convert to satoshis per kb. - return float64(feeRate.ToSatoshiPerKb()), nil + return float64(feeRate), nil } // handleGenerate handles generate commands. diff --git a/server.go b/server.go index fa9370ac9b..ae01b5e2c6 100644 --- a/server.go +++ b/server.go @@ -230,6 +230,10 @@ type server struct { txIndex *indexers.TxIndex addrIndex *indexers.AddrIndex cfIndex *indexers.CfIndex + + // The fee estimator keeps track of how long transactions are left in + // the mempool before they are mined into blocks. + feeEstimator *mempool.FeeEstimator } // serverPeer extends the peer to maintain state shared by the server and @@ -2107,6 +2111,14 @@ func (s *server) Stop() error { s.rpcServer.Stop() } + // Save fee estimator state in the database. + s.db.Update(func(tx database.Tx) error { + metadata := tx.Metadata() + metadata.Put(mempool.EstimateFeeDatabaseKey, s.feeEstimator.Save()) + + return nil + }) + // Signal the remaining goroutines to quit. close(s.quit) return nil @@ -2411,9 +2423,35 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param return nil, err } - feeEstimator := mempool.NewFeeEstimator( - mempool.DefaultEstimateFeeMaxRollback, - mempool.DefaultEstimateFeeMinRegisteredBlocks) + // Search for a FeeEstimator state in the database. If none can be found + // or if it cannot be loaded, create a new one. + db.Update(func(tx database.Tx) error { + metadata := tx.Metadata() + feeEstimationData := metadata.Get(mempool.EstimateFeeDatabaseKey) + if feeEstimationData != nil { + // delete it from the database so that we don't try to restore the + // same thing again somehow. + metadata.Delete(mempool.EstimateFeeDatabaseKey) + + // If there is an error, log it and make a new fee estimator. + var err error + s.feeEstimator, err = mempool.RestoreFeeEstimator(feeEstimationData) + + if err != nil { + peerLog.Errorf("Failed to restore fee estimator %v", err) + } + } + + return nil + }) + + // If no feeEstimator has been found, or if the one that has been found + // is behind somehow, create a new one and start over. + if s.feeEstimator == nil || s.feeEstimator.LastKnownHeight() != s.chain.BestSnapshot().Height { + s.feeEstimator = mempool.NewFeeEstimator( + mempool.DefaultEstimateFeeMaxRollback, + mempool.DefaultEstimateFeeMinRegisteredBlocks) + } txC := mempool.Config{ Policy: mempool.Policy{ @@ -2437,7 +2475,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param SigCache: s.sigCache, HashCache: s.hashCache, AddrIndex: s.addrIndex, - FeeEstimator: feeEstimator, + FeeEstimator: s.feeEstimator, } s.txMemPool = mempool.New(&txC) @@ -2586,7 +2624,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param TxIndex: s.txIndex, AddrIndex: s.addrIndex, CfIndex: s.cfIndex, - FeeEstimator: feeEstimator, + FeeEstimator: s.feeEstimator, }) if err != nil { return nil, err From 5291c455c2d190a0899c3dc34cb09c3df5ec02a0 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 18 Nov 2017 14:08:15 -0800 Subject: [PATCH 0153/1056] server: properly set feeEstimator in newServer --- server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server.go b/server.go index ae01b5e2c6..3f6894ade4 100644 --- a/server.go +++ b/server.go @@ -2486,6 +2486,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param ChainParams: s.chainParams, DisableCheckpoints: cfg.DisableCheckpoints, MaxPeers: cfg.MaxPeers, + FeeEstimator: s.feeEstimator, }) if err != nil { return nil, err From ffe4c2f0ada8398c8ab93d4bc0aea2fbb29d8d01 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 23 Nov 2017 23:31:01 -0600 Subject: [PATCH 0154/1056] integration/rpctest: if unable to build btcd, use one in PATH --- integration/rpctest/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/rpctest/node.go b/integration/rpctest/node.go index 4d224130a8..6904499a08 100644 --- a/integration/rpctest/node.go +++ b/integration/rpctest/node.go @@ -44,7 +44,7 @@ type nodeConfig struct { func newConfig(prefix, certFile, keyFile string, extra []string) (*nodeConfig, error) { btcdPath, err := btcdExecutablePath() if err != nil { - return nil, err + btcdPath = "btcd" } a := &nodeConfig{ From 548c0f499b24e31fa18fe6a48493e01175b54fe8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 29 Mar 2017 15:59:36 -0700 Subject: [PATCH 0155/1056] connmgr: add ability to remove pending connections This commit adds the ability for callers to remove pending connections via a call to the Remove() method. With this change, upstream users of this package can use the connmgr for more elaborate connectivity needs as they can now cancel pending connections that are no longer needed. --- connmgr/connmanager.go | 47 +++++++++++++++++++++++++++++++++--- connmgr/connmanager_test.go | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go index 5f056b336b..26c8e59c88 100644 --- a/connmgr/connmanager.go +++ b/connmgr/connmanager.go @@ -143,6 +143,15 @@ type Config struct { Dial func(net.Addr) (net.Conn, error) } +// registerPending is used to register a pending connection attempt. By +// registering pending connection attempts we allow callers to cancel pending +// connection attempts before their successful or in the case they're not +// longer wanted. +type registerPending struct { + c *ConnReq + done chan struct{} +} + // handleConnected is used to queue a successful connection. type handleConnected struct { c *ConnReq @@ -217,12 +226,17 @@ func (cm *ConnManager) handleFailedConn(c *ConnReq) { // are processed and mapped by their assigned ids. func (cm *ConnManager) connHandler() { conns := make(map[uint64]*ConnReq, cm.cfg.TargetOutbound) + pendingConns := make(map[uint64]*ConnReq) out: for { select { case req := <-cm.requests: switch msg := req.(type) { + case registerPending: + pendingConns[msg.c.id] = msg.c + close(msg.done) + case handleConnected: connReq := msg.c connReq.updateState(ConnEstablished) @@ -232,12 +246,26 @@ out: connReq.retryCount = 0 cm.failedAttempts = 0 + delete(pendingConns, connReq.id) + if cm.cfg.OnConnection != nil { go cm.cfg.OnConnection(connReq, msg.conn) } case handleDisconnected: - if connReq, ok := conns[msg.id]; ok { + connReq, ok := conns[msg.id] + if !ok { + connReq, ok = pendingConns[msg.id] + if ok && !msg.retry { + connReq.updateState(ConnFailed) + + log.Debugf("Cancelling: %v", connReq) + delete(pendingConns, msg.id) + return + } + } + + if connReq != nil { connReq.updateState(ConnDisconnected) if connReq.conn != nil { connReq.conn.Close() @@ -304,8 +332,18 @@ func (cm *ConnManager) Connect(c *ConnReq) { } if atomic.LoadUint64(&c.id) == 0 { atomic.StoreUint64(&c.id, atomic.AddUint64(&cm.connReqCount, 1)) + + // Submit a request of a pending connection attempt to the + // connection manager. By registering the id before the + // connection is even established, we'll be able to later + // cancel the connection via the Remove method. + done := make(chan struct{}) + cm.requests <- registerPending{c, done} + <-done } + log.Debugf("Attempting to connect to %v", c) + conn, err := cm.cfg.Dial(c.Addr) if err != nil { cm.requests <- handleFailed{c, err} @@ -324,8 +362,11 @@ func (cm *ConnManager) Disconnect(id uint64) { cm.requests <- handleDisconnected{id, true} } -// Remove removes the connection corresponding to the given connection -// id from known connections. +// Remove removes the connection corresponding to the given connection id from +// known connections. +// +// NOTE: This method can also be used to cancel a lingering connection attempt +// that hasn't yet succeeded. func (cm *ConnManager) Remove(id uint64) { if atomic.LoadInt32(&cm.stop) != 0 { return diff --git a/connmgr/connmanager_test.go b/connmgr/connmanager_test.go index 03b6dd2e0f..99928931be 100644 --- a/connmgr/connmanager_test.go +++ b/connmgr/connmanager_test.go @@ -6,8 +6,10 @@ package connmgr import ( "errors" + "fmt" "io" "net" + "runtime" "sync/atomic" "testing" "time" @@ -421,6 +423,52 @@ func TestStopFailed(t *testing.T) { cmgr.Wait() } +// TestRemovePendingConnection tests that it's possible to cancel a pending +// connection, removing its internal state from the ConnMgr. +func TestRemovePendingConnection(t *testing.T) { + // Create a ConnMgr instance with an instance of a dialer that'll never + // succeed. + wait := make(chan struct{}) + indefiniteDialer := func(addr net.Addr) (net.Conn, error) { + <-wait + return nil, fmt.Errorf("error") + } + cmgr, err := New(&Config{ + Dial: indefiniteDialer, + }) + if err != nil { + t.Fatalf("New error: %v", err) + } + cmgr.Start() + + // Establish a connection request to a random IP we've chosen. + cr := &ConnReq{ + Addr: &net.TCPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: 18555, + }, + Permanent: true, + } + go cmgr.Connect(cr) + + runtime.Gosched() + + // The request launched above will actually never be able to establish + // a connection. So we'll cancel it _before_ it's able to be completed. + cmgr.Remove(cr.ID()) + + runtime.Gosched() + + // Now examine the status of the connection request, it should read a + // status of failed. + if cr.State() != ConnFailed { + t.Fatalf("request wasn't cancelled, status is: %v", cr.State()) + } + + close(wait) + cmgr.Stop() +} + // mockListener implements the net.Listener interface and is used to test // code that deals with net.Listeners without having to actually make any real // connections. From b26daffac9dfe496c91a859c35a8bbe33c054b61 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 28 Nov 2017 00:31:12 -0800 Subject: [PATCH 0156/1056] connmgr: adds cancellation of pending requests This commit extends the work started by roasbeef in the previous commit to bring full cancellation of pending connection requests. It also adds minor refactors to channel send/receives to help cleanup potentially lingering go routines. --- connmgr/connmanager.go | 178 ++++++++++++++++++++++++++++-------- connmgr/connmanager_test.go | 95 +++++++++++++++++-- 2 files changed, 230 insertions(+), 43 deletions(-) diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go index 26c8e59c88..4acc0b2d03 100644 --- a/connmgr/connmanager.go +++ b/connmgr/connmanager.go @@ -46,9 +46,10 @@ type ConnState uint8 // connection which was disconnected is categorized as disconnected. const ( ConnPending ConnState = iota + ConnFailing + ConnCanceled ConnEstablished ConnDisconnected - ConnFailed ) // ConnReq is the connection request to a network address. If permanent, the @@ -225,8 +226,16 @@ func (cm *ConnManager) handleFailedConn(c *ConnReq) { // connections so that we remain connected to the network. Connection requests // are processed and mapped by their assigned ids. func (cm *ConnManager) connHandler() { - conns := make(map[uint64]*ConnReq, cm.cfg.TargetOutbound) - pendingConns := make(map[uint64]*ConnReq) + + var ( + // pending holds all registered conn requests that have yet to + // succeed. + pending = make(map[uint64]*ConnReq) + + // conns represents the set of all actively connected peers. + conns = make(map[uint64]*ConnReq, cm.cfg.TargetOutbound) + ) + out: for { select { @@ -234,11 +243,23 @@ out: switch msg := req.(type) { case registerPending: - pendingConns[msg.c.id] = msg.c + connReq := msg.c + connReq.updateState(ConnPending) + pending[msg.c.id] = connReq close(msg.done) case handleConnected: connReq := msg.c + + if _, ok := pending[connReq.id]; !ok { + if msg.conn != nil { + msg.conn.Close() + } + log.Debugf("Ignoring connection for "+ + "canceled connreq=%v", connReq) + continue + } + connReq.updateState(ConnEstablished) connReq.conn = msg.conn conns[connReq.id] = connReq @@ -246,7 +267,7 @@ out: connReq.retryCount = 0 cm.failedAttempts = 0 - delete(pendingConns, connReq.id) + delete(pending, connReq.id) if cm.cfg.OnConnection != nil { go cm.cfg.OnConnection(connReq, msg.conn) @@ -255,39 +276,74 @@ out: case handleDisconnected: connReq, ok := conns[msg.id] if !ok { - connReq, ok = pendingConns[msg.id] - if ok && !msg.retry { - connReq.updateState(ConnFailed) - - log.Debugf("Cancelling: %v", connReq) - delete(pendingConns, msg.id) - return + connReq, ok = pending[msg.id] + if !ok { + log.Errorf("Unknown connid=%d", + msg.id) + continue } + + // Pending connection was found, remove + // it from pending map if we should + // ignore a later, successful + // connection. + connReq.updateState(ConnCanceled) + log.Debugf("Canceling: %v", connReq) + delete(pending, msg.id) + continue + } - if connReq != nil { - connReq.updateState(ConnDisconnected) - if connReq.conn != nil { - connReq.conn.Close() - } - log.Debugf("Disconnected from %v", connReq) - delete(conns, msg.id) + // An existing connection was located, mark as + // disconnected and execute disconnection + // callback. + log.Debugf("Disconnected from %v", connReq) + delete(conns, msg.id) - if cm.cfg.OnDisconnection != nil { - go cm.cfg.OnDisconnection(connReq) - } + if connReq.conn != nil { + connReq.conn.Close() + } - if uint32(len(conns)) < cm.cfg.TargetOutbound && msg.retry { - cm.handleFailedConn(connReq) - } - } else { - log.Errorf("Unknown connection: %d", msg.id) + if cm.cfg.OnDisconnection != nil { + go cm.cfg.OnDisconnection(connReq) + } + + // All internal state has been cleaned up, if + // this connection is being removed, we will + // make no further attempts with this request. + if !msg.retry { + connReq.updateState(ConnDisconnected) + continue + } + + // Otherwise, we will attempt a reconnection if + // we do not have enough peers, or if this is a + // persistent peer. The connection request is + // re added to the pending map, so that + // subsequent processing of connections and + // failures do not ignore the request. + if uint32(len(conns)) < cm.cfg.TargetOutbound || + connReq.Permanent { + + connReq.updateState(ConnPending) + log.Debugf("Reconnecting to %v", + connReq) + pending[msg.id] = connReq + cm.handleFailedConn(connReq) } case handleFailed: connReq := msg.c - connReq.updateState(ConnFailed) - log.Debugf("Failed to connect to %v: %v", connReq, msg.err) + + if _, ok := pending[connReq.id]; !ok { + log.Debugf("Ignoring connection for "+ + "canceled conn req: %v", connReq) + continue + } + + connReq.updateState(ConnFailing) + log.Debugf("Failed to connect to %v: %v", + connReq, msg.err) cm.handleFailedConn(connReq) } @@ -313,9 +369,31 @@ func (cm *ConnManager) NewConnReq() { c := &ConnReq{} atomic.StoreUint64(&c.id, atomic.AddUint64(&cm.connReqCount, 1)) + // Submit a request of a pending connection attempt to the connection + // manager. By registering the id before the connection is even + // established, we'll be able to later cancel the connection via the + // Remove method. + done := make(chan struct{}) + select { + case cm.requests <- registerPending{c, done}: + case <-cm.quit: + return + } + + // Wait for the registration to successfully add the pending conn req to + // the conn manager's internal state. + select { + case <-done: + case <-cm.quit: + return + } + addr, err := cm.cfg.GetNewAddress() if err != nil { - cm.requests <- handleFailed{c, err} + select { + case cm.requests <- handleFailed{c, err}: + case <-cm.quit: + } return } @@ -338,17 +416,35 @@ func (cm *ConnManager) Connect(c *ConnReq) { // connection is even established, we'll be able to later // cancel the connection via the Remove method. done := make(chan struct{}) - cm.requests <- registerPending{c, done} - <-done + select { + case cm.requests <- registerPending{c, done}: + case <-cm.quit: + return + } + + // Wait for the registration to successfully add the pending + // conn req to the conn manager's internal state. + select { + case <-done: + case <-cm.quit: + return + } } log.Debugf("Attempting to connect to %v", c) conn, err := cm.cfg.Dial(c.Addr) if err != nil { - cm.requests <- handleFailed{c, err} - } else { - cm.requests <- handleConnected{c, conn} + select { + case cm.requests <- handleFailed{c, err}: + case <-cm.quit: + } + return + } + + select { + case cm.requests <- handleConnected{c, conn}: + case <-cm.quit: } } @@ -359,7 +455,11 @@ func (cm *ConnManager) Disconnect(id uint64) { if atomic.LoadInt32(&cm.stop) != 0 { return } - cm.requests <- handleDisconnected{id, true} + + select { + case cm.requests <- handleDisconnected{id, true}: + case <-cm.quit: + } } // Remove removes the connection corresponding to the given connection id from @@ -371,7 +471,11 @@ func (cm *ConnManager) Remove(id uint64) { if atomic.LoadInt32(&cm.stop) != 0 { return } - cm.requests <- handleDisconnected{id, false} + + select { + case cm.requests <- handleDisconnected{id, false}: + case <-cm.quit: + } } // listenHandler accepts incoming connections on a given listener. It must be diff --git a/connmgr/connmanager_test.go b/connmgr/connmanager_test.go index 99928931be..67769deb96 100644 --- a/connmgr/connmanager_test.go +++ b/connmgr/connmanager_test.go @@ -9,7 +9,6 @@ import ( "fmt" "io" "net" - "runtime" "sync/atomic" "testing" "time" @@ -268,7 +267,7 @@ func TestRetryPermanent(t *testing.T) { t.Fatalf("retry: %v - want ID %v, got ID %v", cr.Addr, wantID, gotID) } gotState = cr.State() - wantState = ConnDisconnected + wantState = ConnPending if gotState != wantState { t.Fatalf("retry: %v - want state %v, got state %v", cr.Addr, wantState, gotState) } @@ -451,24 +450,108 @@ func TestRemovePendingConnection(t *testing.T) { } go cmgr.Connect(cr) - runtime.Gosched() + time.Sleep(10 * time.Millisecond) + + if cr.State() != ConnPending { + t.Fatalf("pending request hasn't been registered, status: %v", + cr.State()) + } // The request launched above will actually never be able to establish // a connection. So we'll cancel it _before_ it's able to be completed. cmgr.Remove(cr.ID()) - runtime.Gosched() + time.Sleep(10 * time.Millisecond) // Now examine the status of the connection request, it should read a // status of failed. - if cr.State() != ConnFailed { - t.Fatalf("request wasn't cancelled, status is: %v", cr.State()) + if cr.State() != ConnCanceled { + t.Fatalf("request wasn't canceled, status is: %v", cr.State()) } close(wait) cmgr.Stop() } +// TestCancelIgnoreDelayedConnection tests that a canceled connection request will +// not execute the on connection callback, even if an outstanding retry +// succeeds. +func TestCancelIgnoreDelayedConnection(t *testing.T) { + retryTimeout := 10 * time.Millisecond + + // Setup a dialer that will continue to return an error until the + // connect chan is signaled, the dial attempt immediately after will + // succeed in returning a connection. + connect := make(chan struct{}) + failingDialer := func(addr net.Addr) (net.Conn, error) { + select { + case <-connect: + return mockDialer(addr) + default: + } + + return nil, fmt.Errorf("error") + } + + connected := make(chan *ConnReq) + cmgr, err := New(&Config{ + Dial: failingDialer, + RetryDuration: retryTimeout, + OnConnection: func(c *ConnReq, conn net.Conn) { + connected <- c + }, + }) + if err != nil { + t.Fatalf("New error: %v", err) + } + cmgr.Start() + defer cmgr.Stop() + + // Establish a connection request to a random IP we've chosen. + cr := &ConnReq{ + Addr: &net.TCPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: 18555, + }, + } + cmgr.Connect(cr) + + // Allow for the first retry timeout to elapse. + time.Sleep(2 * retryTimeout) + + // Connection be marked as failed, even after reattempting to + // connect. + if cr.State() != ConnFailing { + t.Fatalf("failing request should have status failed, status: %v", + cr.State()) + } + + // Remove the connection, and then immediately allow the next connection + // to succeed. + cmgr.Remove(cr.ID()) + close(connect) + + // Allow the connection manager to process the removal. + time.Sleep(5 * time.Millisecond) + + // Now examine the status of the connection request, it should read a + // status of canceled. + if cr.State() != ConnCanceled { + t.Fatalf("request wasn't canceled, status is: %v", cr.State()) + } + + // Finally, the connection manager should not signal the on-connection + // callback, since we explicitly canceled this request. We give a + // generous window to ensure the connection manager's lienar backoff is + // allowed to properly elapse. + select { + case <-connected: + t.Fatalf("on-connect should not be called for canceled req") + case <-time.After(5 * retryTimeout): + } + +} + // mockListener implements the net.Listener interface and is used to test // code that deals with net.Listeners without having to actually make any real // connections. From b7930a11ab0068661dbad602c208f9fe78ff7681 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 15 Feb 2018 15:31:42 +0100 Subject: [PATCH 0157/1056] mempool/estimatefee: make 1 Kb = 1000 bytes This commit changes the value of bytesPerKb to 1000 from 1024. This is done to ensure consistency between the fee estimator and the mempool, where the feeRate is set to fee * 1000 / serializedSize --- mempool/estimatefee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index 234c5cf4bb..e3a46234fe 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -45,7 +45,7 @@ const ( // it will provide fee estimations. DefaultEstimateFeeMinRegisteredBlocks = 3 - bytePerKb = 1024 + bytePerKb = 1000 btcPerSatoshi = 1E-8 ) From 56be349be3225f1ada865a96f30b9dbfb2c8022b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 15 Feb 2018 16:06:20 +0100 Subject: [PATCH 0158/1056] mempool: use vsize when setting FeePerKB for mempool txs --- mempool/mempool.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 511ee6b46b..ac339bf3d1 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -527,7 +527,7 @@ func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil Added: time.Now(), Height: height, Fee: fee, - FeePerKB: fee * 1000 / int64(tx.MsgTx().SerializeSize()), + FeePerKB: fee * 1000 / GetTxVirtualSize(tx), }, StartingPriority: mining.CalcPriority(tx.MsgTx(), utxoView, height), } From 34d82682b08a8b05fea8513e328e56fcc26d00da Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 20 Feb 2018 17:05:48 -0800 Subject: [PATCH 0159/1056] mempool: switch fee estimation to use vsize as a base In this commit, we modify the fee estimation to use vsize as a base rather than size. A recent commit landed to track the fee rate using vsize in the mempool, and also correct some incorrect unit math. This is a follow up to that commit to ensure that fee estimation is uniform throughout. --- mempool/estimatefee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index e3a46234fe..ee72524016 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -208,7 +208,7 @@ func (ef *FeeEstimator) ObserveTransaction(t *TxDesc) { hash := *t.Tx.Hash() if _, ok := ef.observed[hash]; !ok { - size := uint32(t.Tx.MsgTx().SerializeSize()) + size := uint32(GetTxVirtualSize(t.Tx)) ef.observed[hash] = &observedTransaction{ hash: hash, From 621f347929083311e2aa6fc29e4054e79bcbbe8a Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 18 Jan 2018 18:00:42 -0800 Subject: [PATCH 0160/1056] wire: Remove cftypes and getcftypes commands. --- peer/peer.go | 17 ------- peer/peer_test.go | 15 ------- server.go | 16 ------- wire/message.go | 8 ---- wire/message_test.go | 4 -- wire/msgcfilter.go | 11 +++++ wire/msgcftypes.go | 102 ------------------------------------------ wire/msggetcftypes.go | 42 ----------------- 8 files changed, 11 insertions(+), 204 deletions(-) delete mode 100644 wire/msgcftypes.go delete mode 100644 wire/msggetcftypes.go diff --git a/peer/peer.go b/peer/peer.go index b6a5da5e28..86619c538e 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -130,9 +130,6 @@ type MessageListeners struct { // message. OnCFHeaders func(p *Peer, msg *wire.MsgCFHeaders) - // OnCFTypes is invoked when a peer receives a cftypes bitcoin message. - OnCFTypes func(p *Peer, msg *wire.MsgCFTypes) - // OnInv is invoked when a peer receives an inv bitcoin message. OnInv func(p *Peer, msg *wire.MsgInv) @@ -162,10 +159,6 @@ type MessageListeners struct { // bitcoin message. OnGetCFHeaders func(p *Peer, msg *wire.MsgGetCFHeaders) - // OnGetCFTypes is invoked when a peer receives a getcftypes bitcoin - // message. - OnGetCFTypes func(p *Peer, msg *wire.MsgGetCFTypes) - // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1608,11 +1601,6 @@ out: p.cfg.Listeners.OnGetCFHeaders(p, msg) } - case *wire.MsgGetCFTypes: - if p.cfg.Listeners.OnGetCFTypes != nil { - p.cfg.Listeners.OnGetCFTypes(p, msg) - } - case *wire.MsgCFilter: if p.cfg.Listeners.OnCFilter != nil { p.cfg.Listeners.OnCFilter(p, msg) @@ -1623,11 +1611,6 @@ out: p.cfg.Listeners.OnCFHeaders(p, msg) } - case *wire.MsgCFTypes: - if p.cfg.Listeners.OnCFTypes != nil { - p.cfg.Listeners.OnCFTypes(p, msg) - } - case *wire.MsgFeeFilter: if p.cfg.Listeners.OnFeeFilter != nil { p.cfg.Listeners.OnFeeFilter(p, msg) diff --git a/peer/peer_test.go b/peer/peer_test.go index 742f97c64a..5dc42a8864 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -405,18 +405,12 @@ func TestPeerListeners(t *testing.T) { OnGetCFHeaders: func(p *peer.Peer, msg *wire.MsgGetCFHeaders) { ok <- msg }, - OnGetCFTypes: func(p *peer.Peer, msg *wire.MsgGetCFTypes) { - ok <- msg - }, OnCFilter: func(p *peer.Peer, msg *wire.MsgCFilter) { ok <- msg }, OnCFHeaders: func(p *peer.Peer, msg *wire.MsgCFHeaders) { ok <- msg }, - OnCFTypes: func(p *peer.Peer, msg *wire.MsgCFTypes) { - ok <- msg - }, OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) { ok <- msg }, @@ -549,10 +543,6 @@ func TestPeerListeners(t *testing.T) { "OnGetCFHeaders", wire.NewMsgGetCFHeaders(), }, - { - "OnGetCFTypes", - wire.NewMsgGetCFTypes(), - }, { "OnCFilter", wire.NewMsgCFilter(&chainhash.Hash{}, @@ -562,11 +552,6 @@ func TestPeerListeners(t *testing.T) { "OnCFHeaders", wire.NewMsgCFHeaders(), }, - { - "OnCFTypes", - wire.NewMsgCFTypes([]wire.FilterType{ - wire.GCSFilterRegular, wire.GCSFilterExtended}), - }, { "OnFeeFilter", wire.NewMsgFeeFilter(15000), diff --git a/server.go b/server.go index 3f6894ade4..e49f9bfe1d 100644 --- a/server.go +++ b/server.go @@ -877,21 +877,6 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { sp.QueueMessage(headersMsg, nil) } -// OnGetCFTypes is invoked when a peer receives a getcftypes bitcoin message. -func (sp *serverPeer) OnGetCFTypes(_ *peer.Peer, msg *wire.MsgGetCFTypes) { - // Ignore getcftypes requests if cfg.NoCFilters is set or we're not in - // sync. - if cfg.NoCFilters || !sp.server.syncManager.IsCurrent() { - return - } - - // TODO: update to query blockchain indexes and/or config for supported - // filter types. - cfTypesMsg := wire.NewMsgCFTypes([]wire.FilterType{ - wire.GCSFilterRegular, wire.GCSFilterExtended}) - sp.QueueMessage(cfTypesMsg, nil) -} - // enforceNodeBloomFlag disconnects the peer if the server is not configured to // allow bloom filters. Additionally, if the peer has negotiated to a protocol // version that is high enough to observe the bloom filter service support bit, @@ -1741,7 +1726,6 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnGetHeaders: sp.OnGetHeaders, OnGetCFilter: sp.OnGetCFilter, OnGetCFHeaders: sp.OnGetCFHeaders, - OnGetCFTypes: sp.OnGetCFTypes, OnFeeFilter: sp.OnFeeFilter, OnFilterAdd: sp.OnFilterAdd, OnFilterClear: sp.OnFilterClear, diff --git a/wire/message.go b/wire/message.go index 4b47455337..9a34a2fa54 100644 --- a/wire/message.go +++ b/wire/message.go @@ -53,10 +53,8 @@ const ( CmdFeeFilter = "feefilter" CmdGetCFilter = "getcfilter" CmdGetCFHeaders = "getcfheaders" - CmdGetCFTypes = "getcftypes" CmdCFilter = "cfilter" CmdCFHeaders = "cfheaders" - CmdCFTypes = "cftypes" ) // MessageEncoding represents the wire message encoding format to be used. @@ -168,18 +166,12 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFHeaders: msg = &MsgGetCFHeaders{} - case CmdGetCFTypes: - msg = &MsgGetCFTypes{} - case CmdCFilter: msg = &MsgCFilter{} case CmdCFHeaders: msg = &MsgCFHeaders{} - case CmdCFTypes: - msg = &MsgCFTypes{} - default: return nil, fmt.Errorf("unhandled command [%s]", command) } diff --git a/wire/message_test.go b/wire/message_test.go index 897f36becc..69853f05d4 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -71,11 +71,9 @@ func TestMessage(t *testing.T) { msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, GCSFilterExtended) msgGetCFHeaders := NewMsgGetCFHeaders() - msgGetCFTypes := NewMsgGetCFTypes() msgCFilter := NewMsgCFilter(&chainhash.Hash{}, GCSFilterExtended, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() - msgCFTypes := NewMsgCFTypes([]FilterType{GCSFilterExtended}) tests := []struct { in Message // Value to encode @@ -107,10 +105,8 @@ func TestMessage(t *testing.T) { {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 58}, - {msgGetCFTypes, msgGetCFTypes, pver, MainNet, 24}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, - {msgCFTypes, msgCFTypes, pver, MainNet, 26}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index 3ce33180f9..77b4602c45 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -11,6 +11,17 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" ) +// FilterType is used to represent a filter type. +type FilterType uint8 + +const ( + // GCSFilterRegular is the regular filter type. + GCSFilterRegular FilterType = iota + + // GCSFilterExtended is the extended filter type. + GCSFilterExtended +) + const ( // MaxCFilterDataSize is the maximum byte size of a committed filter. // The maximum size is currently defined as 256KiB. diff --git a/wire/msgcftypes.go b/wire/msgcftypes.go deleted file mode 100644 index 17388e02f4..0000000000 --- a/wire/msgcftypes.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package wire - -import "io" - -// FilterType is used to represent a filter type. -type FilterType uint8 - -const ( - // GCSFilterRegular is the regular filter type. - GCSFilterRegular FilterType = iota - - // GCSFilterExtended is the extended filter type. - GCSFilterExtended -) - -// MsgCFTypes is the cftypes message. -type MsgCFTypes struct { - SupportedFilters []FilterType -} - -// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. -// This is part of the Message interface implementation. -func (msg *MsgCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - // Read the number of filter types supported. - count, err := ReadVarInt(r, pver) - if err != nil { - return err - } - - // Read each filter type. - msg.SupportedFilters = make([]FilterType, count) - for i := uint64(0); i < count; i++ { - var filterType uint8 - err = readElement(r, &filterType) - if err != nil { - return err - } - msg.SupportedFilters[i] = FilterType(filterType) - } - - return nil -} - -// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. -// This is part of the Message interface implementation. -func (msg *MsgCFTypes) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - // Write length of supported filters slice. We assume it's deduplicated. - err := WriteVarInt(w, pver, uint64(len(msg.SupportedFilters))) - if err != nil { - return err - } - - for i := range msg.SupportedFilters { - err = writeElement(w, msg.SupportedFilters[i]) - if err != nil { - return err - } - } - - return nil -} - -// Deserialize decodes a filter from r into the receiver using a format that is -// suitable for long-term storage such as a database. This function differs -// from BtcDecode in that BtcDecode decodes from the bitcoin wire protocol as -// it was sent across the network. The wire encoding can technically differ -// depending on the protocol version and doesn't even really need to match the -// format of a stored filter at all. As of the time this comment was written, -// the encoded filter is the same in both instances, but there is a distinct -// difference and separating the two allows the API to be flexible enough to -// deal with changes. -func (msg *MsgCFTypes) Deserialize(r io.Reader) error { - // At the current time, there is no difference between the wire encoding - // and the stable long-term storage format. As a result, make use of - // BtcDecode. - return msg.BtcDecode(r, 0, BaseEncoding) -} - -// Command returns the protocol command string for the message. This is part -// of the Message interface implementation. -func (msg *MsgCFTypes) Command() string { - return CmdCFTypes -} - -// MaxPayloadLength returns the maximum length the payload can be for the -// receiver. This is part of the Message interface implementation. -func (msg *MsgCFTypes) MaxPayloadLength(pver uint32) uint32 { - // 2 bytes for filter count, and 1 byte for up to 256 filter types. - return 258 -} - -// NewMsgCFTypes returns a new bitcoin cftypes message that conforms to the -// Message interface. See MsgCFTypes for details. -func NewMsgCFTypes(filterTypes []FilterType) *MsgCFTypes { - return &MsgCFTypes{ - SupportedFilters: filterTypes, - } -} diff --git a/wire/msggetcftypes.go b/wire/msggetcftypes.go deleted file mode 100644 index 304ce87bf3..0000000000 --- a/wire/msggetcftypes.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package wire - -import "io" - -// MsgGetCFTypes is the getcftypes message. -type MsgGetCFTypes struct { -} - -// BtcDecode decodes the receiver from w using the bitcoin protocol encoding. -// This is part of the Message interface implementation. -func (msg *MsgGetCFTypes) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - return nil -} - -// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. -// This is part of the Message interface implementation. -func (msg *MsgGetCFTypes) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - return nil -} - -// Command returns the protocol command string for the message. This is part -// of the Message interface implementation. -func (msg *MsgGetCFTypes) Command() string { - return CmdGetCFTypes -} - -// MaxPayloadLength returns the maximum length the payload can be for the -// receiver. This is part of the Message interface implementation. -func (msg *MsgGetCFTypes) MaxPayloadLength(pver uint32) uint32 { - // Empty message. - return 0 -} - -// NewMsgGetCFTypes returns a new bitcoin getcftypes message that conforms to -// the Message interface. -func NewMsgGetCFTypes() *MsgGetCFTypes { - return &MsgGetCFTypes{} -} From 07393c0dab581ed1a70aa24ca67da8acaf4c16af Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Fri, 19 Jan 2018 11:59:34 -0800 Subject: [PATCH 0161/1056] blockchain: HeightToHashRange function for pulling range of hashes. This functionality is required to implement BIP 157. --- blockchain/chain.go | 42 ++++++++++++++++++ blockchain/chain_test.go | 92 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index d00557e7ad..3b89446cf7 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1322,6 +1322,48 @@ func (b *BlockChain) HeightRange(startHeight, endHeight int32) ([]chainhash.Hash return hashes, nil } +// HeightToHashRange returns a range of block hashes for the given start height +// and end hash, inclusive on both ends. The hashes are for all blocks that are +// ancestors of endHash with height greater than or equal to startHeight. The +// end hash must belong to a block that is known to be valid. +// +// This function is safe for concurrent access. +func (b *BlockChain) HeightToHashRange(startHeight int32, + endHash *chainhash.Hash, maxResults int) ([]chainhash.Hash, error) { + + endNode := b.index.LookupNode(endHash) + if endNode == nil { + return nil, fmt.Errorf("no known block header with hash %v", endHash) + } + if !b.index.NodeStatus(endNode).KnownValid() { + return nil, fmt.Errorf("block %v is not yet validated", endHash) + } + endHeight := endNode.height + + if startHeight < 0 { + return nil, fmt.Errorf("start height (%d) is below 0", startHeight) + } + if startHeight > endHeight { + return nil, fmt.Errorf("start height (%d) is past end height (%d)", + startHeight, endHeight) + } + + resultsLength := int(endHeight - startHeight + 1) + if resultsLength > maxResults { + return nil, fmt.Errorf("number of results (%d) would exceed max (%d)", + resultsLength, maxResults) + } + + // Walk backwards from endHeight to startHeight, collecting block hashes. + node := endNode + hashes := make([]chainhash.Hash, resultsLength) + for i := resultsLength - 1; i >= 0; i-- { + hashes[i] = node.hash + node = node.parent + } + return hashes, nil +} + // locateInventory returns the node of the block after the first known block in // the locator along with the number of subsequent nodes needed to either reach // the provided stop hash or the provided max number of entries. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index afb07f9af7..d8459b68ed 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -800,3 +800,95 @@ func TestLocateInventory(t *testing.T) { } } } + +// TestHeightToHashRange ensures that fetching a range of block hashes by start +// height and end hash works as expected. +func TestHeightToHashRange(t *testing.T) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 + // \-> 16a -> 17a -> 18a (unvalidated) + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 18) + branch1Nodes := chainedNodes(branch0Nodes[14], 3) + for _, node := range branch0Nodes { + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + for _, node := range branch1Nodes { + if node.height < 18 { + chain.index.SetStatusFlags(node, statusValid) + } + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branch0Nodes)) + + tests := []struct { + name string + startHeight int32 // locator for requested inventory + endHash chainhash.Hash // stop hash for locator + maxResults int // max to locate, 0 = wire const + hashes []chainhash.Hash // expected located hashes + expectError bool + }{ + { + name: "blocks below tip", + startHeight: 11, + endHash: branch0Nodes[14].hash, + maxResults: 10, + hashes: nodeHashes(branch0Nodes, 10, 11, 12, 13, 14), + }, + { + name: "blocks on main chain", + startHeight: 15, + endHash: branch0Nodes[17].hash, + maxResults: 10, + hashes: nodeHashes(branch0Nodes, 14, 15, 16, 17), + }, + { + name: "blocks on stale chain", + startHeight: 15, + endHash: branch1Nodes[1].hash, + maxResults: 10, + hashes: append(nodeHashes(branch0Nodes, 14), + nodeHashes(branch1Nodes, 0, 1)...), + }, + { + name: "invalid start height", + startHeight: 19, + endHash: branch0Nodes[17].hash, + maxResults: 10, + expectError: true, + }, + { + name: "too many results", + startHeight: 1, + endHash: branch0Nodes[17].hash, + maxResults: 10, + expectError: true, + }, + { + name: "unvalidated block", + startHeight: 15, + endHash: branch1Nodes[2].hash, + maxResults: 10, + expectError: true, + }, + } + for _, test := range tests { + hashes, err := chain.HeightToHashRange(test.startHeight, &test.endHash, + test.maxResults) + if err != nil { + if !test.expectError { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + continue + } + + if !reflect.DeepEqual(hashes, test.hashes) { + t.Errorf("%s: unxpected hashes -- got %v, want %v", + test.name, hashes, test.hashes) + } + } +} From 185577f4c2837fb4f3b09e71522b9647dffcff10 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 22 Jan 2018 20:38:25 -0800 Subject: [PATCH 0162/1056] blockchain: Implement IntervalBlockHashes method. This will be used to respond to getcfcheckpt queries. --- blockchain/chain.go | 39 ++++++++++++++++++++++ blockchain/chain_test.go | 72 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index 3b89446cf7..cd2338359f 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1364,6 +1364,45 @@ func (b *BlockChain) HeightToHashRange(startHeight int32, return hashes, nil } +// IntervalBlockHashes returns hashes for all blocks that are ancestors of +// endHash where the block height is a positive multiple of interval. +// +// This function is safe for concurrent access. +func (b *BlockChain) IntervalBlockHashes(endHash *chainhash.Hash, interval int, +) ([]chainhash.Hash, error) { + + endNode := b.index.LookupNode(endHash) + if endNode == nil { + return nil, fmt.Errorf("no known block header with hash %v", endHash) + } + if !b.index.NodeStatus(endNode).KnownValid() { + return nil, fmt.Errorf("block %v is not yet validated", endHash) + } + endHeight := endNode.height + + resultsLength := int(endHeight) / interval + hashes := make([]chainhash.Hash, resultsLength) + + b.bestChain.mtx.Lock() + defer b.bestChain.mtx.Unlock() + + blockNode := endNode + for index := int(endHeight) / interval; index > 0; index-- { + // Use the bestChain chainView for faster lookups once lookup intersects + // the best chain. + blockHeight := int32(index * interval) + if b.bestChain.contains(blockNode) { + blockNode = b.bestChain.nodeByHeight(blockHeight) + } else { + blockNode = blockNode.Ancestor(blockHeight) + } + + hashes[index-1] = blockNode.hash + } + + return hashes, nil +} + // locateInventory returns the node of the block after the first known block in // the locator along with the number of subsequent nodes needed to either reach // the provided stop hash or the provided max number of entries. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index d8459b68ed..7de323bc8d 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -892,3 +892,75 @@ func TestHeightToHashRange(t *testing.T) { } } } + +// TestIntervalBlockHashes ensures that fetching block hashes at specified +// intervals by end hash works as expected. +func TestIntervalBlockHashes(t *testing.T) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 + // \-> 16a -> 17a -> 18a (unvalidated) + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 18) + branch1Nodes := chainedNodes(branch0Nodes[14], 3) + for _, node := range branch0Nodes { + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + for _, node := range branch1Nodes { + if node.height < 18 { + chain.index.SetStatusFlags(node, statusValid) + } + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branch0Nodes)) + + tests := []struct { + name string + endHash chainhash.Hash + interval int + hashes []chainhash.Hash + expectError bool + }{ + { + name: "blocks on main chain", + endHash: branch0Nodes[17].hash, + interval: 8, + hashes: nodeHashes(branch0Nodes, 7, 15), + }, + { + name: "blocks on stale chain", + endHash: branch1Nodes[1].hash, + interval: 8, + hashes: append(nodeHashes(branch0Nodes, 7), + nodeHashes(branch1Nodes, 0)...), + }, + { + name: "no results", + endHash: branch0Nodes[17].hash, + interval: 20, + hashes: []chainhash.Hash{}, + }, + { + name: "unvalidated block", + endHash: branch1Nodes[2].hash, + interval: 8, + expectError: true, + }, + } + for _, test := range tests { + hashes, err := chain.IntervalBlockHashes(&test.endHash, test.interval) + if err != nil { + if !test.expectError { + t.Errorf("%s: unexpected error: %v", test.name, err) + } + continue + } + + if !reflect.DeepEqual(hashes, test.hashes) { + t.Errorf("%s: unxpected hashes -- got %v, want %v", + test.name, hashes, test.hashes) + } + } +} From d07fd2f333eef9d5e3910f286cca74e2b37ea5e1 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Wed, 31 Jan 2018 23:38:10 -0800 Subject: [PATCH 0163/1056] blockchain/indexers: Reduce duplication in cfindex. The index will hold three types of entries for each filter type, block pair: filter, header, and hash. Since they all have similar methods and implementations, refactor to reduce duplication. --- blockchain/indexers/cfindex.go | 106 ++++++++++++--------------------- 1 file changed, 39 insertions(+), 67 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index bd15271119..2cab23f801 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -14,7 +14,6 @@ import ( "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs" "github.com/btcsuite/btcutil/gcs/builder" - "github.com/btcsuite/fastsha256" "github.com/roasbeef/btcd/wire" ) @@ -48,49 +47,21 @@ var ( maxFilterType = uint8(len(cfHeaderKeys) - 1) ) -// dbFetchFilter retrieves a block's basic or extended filter. A filter's -// absence is not considered an error. -func dbFetchFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { +// dbFetchFilterIdxEntry retrieves a data blob from the filter index database. +// An entry's absence is not considered an error. +func dbFetchFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Get(h[:]), nil } -// dbFetchFilterHeader retrieves a block's basic or extended filter header. -// A filter's absence is not considered an error. -func dbFetchFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) ([]byte, error) { - idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) - - fh := idx.Get(h[:]) - if len(fh) != fastsha256.Size { - return nil, errors.New("invalid filter header length") - } - - return fh, nil -} - -// dbStoreFilter stores a block's basic or extended filter. -func dbStoreFilter(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error { +// dbStoreFilterIdxEntry stores a data blob in the filter index database. +func dbStoreFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash, f []byte) error { idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Put(h[:], f) } -// dbStoreFilterHeader stores a block's basic or extended filter header. -func dbStoreFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash, fh []byte) error { - if len(fh) != fastsha256.Size { - return errors.New("invalid filter header length") - } - idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) - return idx.Put(h[:], fh) -} - -// dbDeleteFilter deletes a filter's basic or extended filter. -func dbDeleteFilter(dbTx database.Tx, key []byte, h *chainhash.Hash) error { - idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) - return idx.Delete(h[:]) -} - -// dbDeleteFilterHeader deletes a filter's basic or extended filter header. -func dbDeleteFilterHeader(dbTx database.Tx, key []byte, h *chainhash.Hash) error { +// dbDeleteFilterIdxEntry deletes a data blob from the filter index database. +func dbDeleteFilterIdxEntry(dbTx database.Tx, key []byte, h *chainhash.Hash) error { idx := dbTx.Metadata().Bucket(cfIndexParentBucketKey).Bucket(key) return idx.Delete(h[:]) } @@ -148,7 +119,7 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { } firstHeader := make([]byte, chainhash.HashSize) - err = dbStoreFilterHeader( + err = dbStoreFilterIdxEntry( dbTx, cfHeaderKeys[wire.GCSFilterRegular], &idx.chainParams.GenesisBlock.Header.PrevBlock, @@ -158,7 +129,7 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { return err } - return dbStoreFilterHeader( + return dbStoreFilterIdxEntry( dbTx, cfHeaderKeys[wire.GCSFilterExtended], &idx.chainParams.GenesisBlock.Header.PrevBlock, @@ -184,14 +155,14 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, if f != nil { basicFilterBytes = f.NBytes() } - err := dbStoreFilter(dbTx, fkey, h, basicFilterBytes) + err = dbStoreFilterIdxEntry(dbTx, fkey, h, filterBytes) if err != nil { return err } // Then fetch the previous block's filter header. ph := &block.MsgBlock().Header.PrevBlock - pfh, err := dbFetchFilterHeader(dbTx, hkey, ph) + pfh, err := dbFetchFilterIdxEntry(dbTx, hkey, ph) if err != nil { return err } @@ -201,8 +172,11 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, if err != nil { return err } - fh := builder.MakeHeaderForFilter(f, *prevHeader) - return dbStoreFilterHeader(dbTx, hkey, h, fh[:]) + fh, err := builder.MakeHeaderForFilter(f, *prevHeader) + if err != nil { + return err + } + return dbStoreFilterIdxEntry(dbTx, hkey, h, fh[:]) } // ConnectBlock is invoked by the index manager when a new block has been @@ -236,14 +210,14 @@ func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { for _, key := range cfIndexKeys { - err := dbDeleteFilter(dbTx, key, block.Hash()) + err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash()) if err != nil { return err } } for _, key := range cfHeaderKeys { - err := dbDeleteFilterHeader(dbTx, key, block.Hash()) + err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash()) if err != nil { return err } @@ -252,39 +226,37 @@ func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, return nil } -// FilterByBlockHash returns the serialized contents of a block's basic or -// extended committed filter. -func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, - filterType wire.FilterType) ([]byte, error) { - var f []byte - err := idx.db.View(func(dbTx database.Tx) error { - if uint8(filterType) > maxFilterType { - return errors.New("unsupported filter type") - } +// entryByBlockHash fetches a filter index entry of a particular type +// (eg. filter, filter header, etc) for a filter type and block hash. +func (idx *CfIndex) entryByBlockHash(filterTypeKeys [][]byte, + filterType wire.FilterType, h *chainhash.Hash) ([]byte, error) { + + if uint8(filterType) > maxFilterType { + return nil, errors.New("unsupported filter type") + } + key := filterTypeKeys[filterType] + var entry []byte + err := idx.db.View(func(dbTx database.Tx) error { var err error - f, err = dbFetchFilter(dbTx, cfIndexKeys[filterType], h) + entry, err = dbFetchFilterIdxEntry(dbTx, key, h) return err }) - return f, err + return entry, err +} + +// FilterByBlockHash returns the serialized contents of a block's basic or +// extended committed filter. +func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, + filterType wire.FilterType) ([]byte, error) { + return idx.entryByBlockHash(cfIndexKeys, filterType, h) } // FilterHeaderByBlockHash returns the serialized contents of a block's basic // or extended committed filter header. func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, filterType wire.FilterType) ([]byte, error) { - var fh []byte - err := idx.db.View(func(dbTx database.Tx) error { - if uint8(filterType) > maxFilterType { - return errors.New("unsupported filter type") - } - - var err error - fh, err = dbFetchFilterHeader(dbTx, - cfHeaderKeys[filterType], h) - return err - }) - return fh, err + return idx.entryByBlockHash(cfHeaderKeys, filterType, h) } // NewCfIndex returns a new instance of an indexer that is used to create a From e617483b4424cbbf82e567720469eb8662c3db5d Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 22 Jan 2018 12:59:20 -0800 Subject: [PATCH 0164/1056] blockchain/indexers: Store filter hashes with cfindex. --- blockchain/indexers/cfindex.go | 79 ++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 2cab23f801..51b3a7ce45 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -44,7 +44,18 @@ var ( []byte("cf1headerbyhashidx"), } + // cfHashKeys is an array of db bucket names used to house indexes of + // block hashes to cf hashes. + cfHashKeys = [][]byte{ + []byte("cf0hashbyhashidx"), + []byte("cf1hashbyhashidx"), + } + maxFilterType = uint8(len(cfHeaderKeys) - 1) + + // zeroHash is the chainhash.Hash value of all zero bytes, defined here for + // convenience. + zeroHash chainhash.Hash ) // dbFetchFilterIdxEntry retrieves a data blob from the filter index database. @@ -118,23 +129,14 @@ func (idx *CfIndex) Create(dbTx database.Tx) error { } } - firstHeader := make([]byte, chainhash.HashSize) - err = dbStoreFilterIdxEntry( - dbTx, - cfHeaderKeys[wire.GCSFilterRegular], - &idx.chainParams.GenesisBlock.Header.PrevBlock, - firstHeader, - ) - if err != nil { - return err + for _, bucketName := range cfHashKeys { + _, err = cfIndexParentBucket.CreateBucket(bucketName) + if err != nil { + return err + } } - return dbStoreFilterIdxEntry( - dbTx, - cfHeaderKeys[wire.GCSFilterExtended], - &idx.chainParams.GenesisBlock.Header.PrevBlock, - firstHeader, - ) + return nil } // storeFilter stores a given filter, and performs the steps needed to @@ -148,6 +150,7 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, // Figure out which buckets to use. fkey := cfIndexKeys[filterType] hkey := cfHeaderKeys[filterType] + hashkey := cfHashKeys[filterType] // Start by storing the filter. h := block.Hash() @@ -160,18 +163,34 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, return err } - // Then fetch the previous block's filter header. - ph := &block.MsgBlock().Header.PrevBlock - pfh, err := dbFetchFilterIdxEntry(dbTx, hkey, ph) + // Next store the filter hash. + filterHash, err := builder.GetFilterHash(f) if err != nil { return err } - - // Construct the new block's filter header, and store it. - prevHeader, err := chainhash.NewHash(pfh) + err = dbStoreFilterIdxEntry(dbTx, hashkey, h, filterHash[:]) if err != nil { return err } + + // Then fetch the previous block's filter header. + var prevHeader *chainhash.Hash + ph := &block.MsgBlock().Header.PrevBlock + if ph.IsEqual(&zeroHash) { + prevHeader = &zeroHash + } else { + pfh, err := dbFetchFilterIdxEntry(dbTx, hkey, ph) + if err != nil { + return err + } + + // Construct the new block's filter header, and store it. + prevHeader, err = chainhash.NewHash(pfh) + if err != nil { + return err + } + } + fh, err := builder.MakeHeaderForFilter(f, *prevHeader) if err != nil { return err @@ -190,8 +209,8 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return err } - if err := storeFilter(dbTx, block, f, - wire.GCSFilterRegular); err != nil { + err = storeFilter(dbTx, block, f, wire.GCSFilterRegular) + if err != nil { return err } @@ -223,6 +242,13 @@ func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, } } + for _, key := range cfHashKeys { + err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash()) + if err != nil { + return err + } + } + return nil } @@ -259,6 +285,13 @@ func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, return idx.entryByBlockHash(cfHeaderKeys, filterType, h) } +// FilterHeaderByBlockHash returns the serialized contents of a block's basic +// or extended committed filter hash. +func (idx *CfIndex) FilterHashByBlockHash(h *chainhash.Hash, + filterType wire.FilterType) ([]byte, error) { + return idx.entryByBlockHash(cfHashKeys, filterType, h) +} + // NewCfIndex returns a new instance of an indexer that is used to create a // mapping of the hashes of all blocks in the blockchain to their respective // committed filters. From 3425d33506a3a0db0a7182f20b3c6515eae0cd29 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 1 Feb 2018 00:00:45 -0800 Subject: [PATCH 0165/1056] blockchain/indexers: Add methods on CfIndex for batch retrieval. Fetching all items in one db transaction will save time when responding to getcfilters or getcfheaders requests. --- blockchain/indexers/cfindex.go | 47 +++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 51b3a7ce45..93d00fff69 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -271,6 +271,30 @@ func (idx *CfIndex) entryByBlockHash(filterTypeKeys [][]byte, return entry, err } +// entriesByBlockHashes batch fetches a filter index entry of a particular type +// (eg. filter, filter header, etc) for a filter type and slice of block hashes. +func (idx *CfIndex) entriesByBlockHashes(filterTypeKeys [][]byte, + filterType wire.FilterType, blockHashes []*chainhash.Hash) ([][]byte, error) { + + if uint8(filterType) > maxFilterType { + return nil, errors.New("unsupported filter type") + } + key := filterTypeKeys[filterType] + + entries := make([][]byte, 0, len(blockHashes)) + err := idx.db.View(func(dbTx database.Tx) error { + for _, blockHash := range blockHashes { + entry, err := dbFetchFilterIdxEntry(dbTx, key, blockHash) + if err != nil { + return err + } + entries = append(entries, entry) + } + return nil + }) + return entries, err +} + // FilterByBlockHash returns the serialized contents of a block's basic or // extended committed filter. func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, @@ -278,6 +302,13 @@ func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, return idx.entryByBlockHash(cfIndexKeys, filterType, h) } +// FiltersByBlockHashes returns the serialized contents of a block's basic or +// extended committed filter for a set of blocks by hash. +func (idx *CfIndex) FiltersByBlockHashes(blockHashes []*chainhash.Hash, + filterType wire.FilterType) ([][]byte, error) { + return idx.entriesByBlockHashes(cfIndexKeys, filterType, blockHashes) +} + // FilterHeaderByBlockHash returns the serialized contents of a block's basic // or extended committed filter header. func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, @@ -285,13 +316,27 @@ func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, return idx.entryByBlockHash(cfHeaderKeys, filterType, h) } -// FilterHeaderByBlockHash returns the serialized contents of a block's basic +// FilterHeadersByBlockHashes returns the serialized contents of a block's basic +// or extended committed filter header for a set of blocks by hash. +func (idx *CfIndex) FilterHeadersByBlockHashes(blockHashes []*chainhash.Hash, + filterType wire.FilterType) ([][]byte, error) { + return idx.entriesByBlockHashes(cfHeaderKeys, filterType, blockHashes) +} + +// FilterHashByBlockHash returns the serialized contents of a block's basic // or extended committed filter hash. func (idx *CfIndex) FilterHashByBlockHash(h *chainhash.Hash, filterType wire.FilterType) ([]byte, error) { return idx.entryByBlockHash(cfHashKeys, filterType, h) } +// FilterHashesByBlockHashes returns the serialized contents of a block's basic +// or extended committed filter hash for a set of blocks by hash. +func (idx *CfIndex) FilterHashesByBlockHashes(blockHashes []*chainhash.Hash, + filterType wire.FilterType) ([][]byte, error) { + return idx.entriesByBlockHashes(cfHashKeys, filterType, blockHashes) +} + // NewCfIndex returns a new instance of an indexer that is used to create a // mapping of the hashes of all blocks in the blockchain to their respective // committed filters. From daac60675e60d6f554b5abc5d9ee02d053fcedc2 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Thu, 18 Jan 2018 19:10:42 -0800 Subject: [PATCH 0166/1056] multi: Redefine GetCFilters to have StartHeight and StopHash. --- peer/peer.go | 10 ++--- peer/peer_test.go | 11 +++-- server.go | 44 +++++++++++++------- wire/message.go | 6 +-- wire/message_test.go | 6 +-- wire/msgcfilter.go | 22 +++++----- wire/msggetcfilter.go | 62 ---------------------------- wire/msggetcfilters.go | 91 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 149 insertions(+), 103 deletions(-) delete mode 100644 wire/msggetcfilter.go create mode 100644 wire/msggetcfilters.go diff --git a/peer/peer.go b/peer/peer.go index 86619c538e..b9d802a4c9 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -151,9 +151,9 @@ type MessageListeners struct { // message. OnGetHeaders func(p *Peer, msg *wire.MsgGetHeaders) - // OnGetCFilter is invoked when a peer receives a getcfilter bitcoin + // OnGetCFilters is invoked when a peer receives a getcfilters bitcoin // message. - OnGetCFilter func(p *Peer, msg *wire.MsgGetCFilter) + OnGetCFilters func(p *Peer, msg *wire.MsgGetCFilters) // OnGetCFHeaders is invoked when a peer receives a getcfheaders // bitcoin message. @@ -1591,9 +1591,9 @@ out: p.cfg.Listeners.OnGetHeaders(p, msg) } - case *wire.MsgGetCFilter: - if p.cfg.Listeners.OnGetCFilter != nil { - p.cfg.Listeners.OnGetCFilter(p, msg) + case *wire.MsgGetCFilters: + if p.cfg.Listeners.OnGetCFilters != nil { + p.cfg.Listeners.OnGetCFilters(p, msg) } case *wire.MsgGetCFHeaders: diff --git a/peer/peer_test.go b/peer/peer_test.go index 5dc42a8864..b4c0a4f44b 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -399,7 +399,7 @@ func TestPeerListeners(t *testing.T) { OnGetHeaders: func(p *peer.Peer, msg *wire.MsgGetHeaders) { ok <- msg }, - OnGetCFilter: func(p *peer.Peer, msg *wire.MsgGetCFilter) { + OnGetCFilters: func(p *peer.Peer, msg *wire.MsgGetCFilters) { ok <- msg }, OnGetCFHeaders: func(p *peer.Peer, msg *wire.MsgGetCFHeaders) { @@ -535,9 +535,8 @@ func TestPeerListeners(t *testing.T) { wire.NewMsgGetHeaders(), }, { - "OnGetCFilter", - wire.NewMsgGetCFilter(&chainhash.Hash{}, - wire.GCSFilterRegular), + "OnGetCFilters", + wire.NewMsgGetCFilters(wire.GCSFilterRegular, 0, &chainhash.Hash{}), }, { "OnGetCFHeaders", @@ -545,8 +544,8 @@ func TestPeerListeners(t *testing.T) { }, { "OnCFilter", - wire.NewMsgCFilter(&chainhash.Hash{}, - wire.GCSFilterRegular, []byte("payload")), + wire.NewMsgCFilter(wire.GCSFilterRegular, &chainhash.Hash{}, + []byte("payload")), }, { "OnCFHeaders", diff --git a/server.go b/server.go index e49f9bfe1d..71f71ed3d9 100644 --- a/server.go +++ b/server.go @@ -743,26 +743,42 @@ func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { sp.QueueMessage(&wire.MsgHeaders{Headers: blockHeaders}, nil) } -// OnGetCFilter is invoked when a peer receives a getcfilter bitcoin message. -func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) { - // Ignore getcfilter requests if not in sync. +// OnGetCFilters is invoked when a peer receives a getcfilters bitcoin message. +func (sp *serverPeer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) { + // Ignore getcfilters requests if not in sync. if !sp.server.syncManager.IsCurrent() { return } - filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash, - msg.FilterType) + hashes, err := sp.server.chain.HeightToHashRange(int32(msg.StartHeight), + &msg.StopHash, wire.MaxGetCFiltersReqRange) + if err != nil { + peerLog.Debugf("Invalid getcfilters request: %v", err) + return + } - if len(filterBytes) > 0 { - peerLog.Tracef("Obtained CF for %v", msg.BlockHash) - } else { - peerLog.Warnf("Could not obtain CF for %v: %v", msg.BlockHash, - err) + // Create []*chainhash.Hash from []chainhash.Hash to pass to + // FiltersByBlockHashes. + hashPtrs := make([]*chainhash.Hash, len(hashes)) + for i := range hashes { + hashPtrs[i] = &hashes[i] } - filterMsg := wire.NewMsgCFilter(&msg.BlockHash, msg.FilterType, - filterBytes) - sp.QueueMessage(filterMsg, nil) + filters, err := sp.server.cfIndex.FiltersByBlockHashes(hashPtrs, + msg.FilterType) + if err != nil { + peerLog.Errorf("Error retrieving cfilters: %v", err) + return + } + + for i, filterBytes := range filters { + if len(filterBytes) == 0 { + peerLog.Warnf("Could not obtain cfilter for %v", hashes[i]) + return + } + filterMsg := wire.NewMsgCFilter(msg.FilterType, &hashes[i], filterBytes) + sp.QueueMessage(filterMsg, nil) + } } // OnGetCFHeaders is invoked when a peer receives a getcfheader bitcoin message. @@ -1724,7 +1740,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnGetData: sp.OnGetData, OnGetBlocks: sp.OnGetBlocks, OnGetHeaders: sp.OnGetHeaders, - OnGetCFilter: sp.OnGetCFilter, + OnGetCFilters: sp.OnGetCFilters, OnGetCFHeaders: sp.OnGetCFHeaders, OnFeeFilter: sp.OnFeeFilter, OnFilterAdd: sp.OnFilterAdd, diff --git a/wire/message.go b/wire/message.go index 9a34a2fa54..f00267d729 100644 --- a/wire/message.go +++ b/wire/message.go @@ -51,7 +51,7 @@ const ( CmdReject = "reject" CmdSendHeaders = "sendheaders" CmdFeeFilter = "feefilter" - CmdGetCFilter = "getcfilter" + CmdGetCFilters = "getcfilters" CmdGetCFHeaders = "getcfheaders" CmdCFilter = "cfilter" CmdCFHeaders = "cfheaders" @@ -160,8 +160,8 @@ func makeEmptyMessage(command string) (Message, error) { case CmdFeeFilter: msg = &MsgFeeFilter{} - case CmdGetCFilter: - msg = &MsgGetCFilter{} + case CmdGetCFilters: + msg = &MsgGetCFilters{} case CmdGetCFHeaders: msg = &MsgGetCFHeaders{} diff --git a/wire/message_test.go b/wire/message_test.go index 69853f05d4..e36fe01bb2 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -69,9 +69,9 @@ func TestMessage(t *testing.T) { bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0) msgMerkleBlock := NewMsgMerkleBlock(bh) msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") - msgGetCFilter := NewMsgGetCFilter(&chainhash.Hash{}, GCSFilterExtended) + msgGetCFilters := NewMsgGetCFilters(GCSFilterExtended, 0, &chainhash.Hash{}) msgGetCFHeaders := NewMsgGetCFHeaders() - msgCFilter := NewMsgCFilter(&chainhash.Hash{}, GCSFilterExtended, + msgCFilter := NewMsgCFilter(GCSFilterExtended, &chainhash.Hash{}, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() @@ -103,7 +103,7 @@ func TestMessage(t *testing.T) { {msgFilterLoad, msgFilterLoad, pver, MainNet, 35}, {msgMerkleBlock, msgMerkleBlock, pver, MainNet, 110}, {msgReject, msgReject, pver, MainNet, 79}, - {msgGetCFilter, msgGetCFilter, pver, MainNet, 57}, + {msgGetCFilters, msgGetCFilters, pver, MainNet, 61}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 58}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index 77b4602c45..7387587fd4 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -30,26 +30,28 @@ const ( // MsgCFilter implements the Message interface and represents a bitcoin cfilter // message. It is used to deliver a committed filter in response to a -// getcfilter (MsgGetCFilter) message. +// getcfilters (MsgGetCFilters) message. type MsgCFilter struct { - BlockHash chainhash.Hash FilterType FilterType + BlockHash chainhash.Hash Data []byte } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - // Read the hash of the filter's block - err := readElement(r, &msg.BlockHash) + // Read filter type + err := readElement(r, &msg.FilterType) if err != nil { return err } - // Read filter type - err = readElement(r, &msg.FilterType) + + // Read the hash of the filter's block + err = readElement(r, &msg.BlockHash) if err != nil { return err } + // Read filter data msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize, "cfilter data") @@ -66,12 +68,12 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) er return messageError("MsgCFilter.BtcEncode", str) } - err := writeElement(w, msg.BlockHash) + err := writeElement(w, msg.FilterType) if err != nil { return err } - err = writeElement(w, msg.FilterType) + err = writeElement(w, msg.BlockHash) if err != nil { return err } @@ -110,11 +112,11 @@ func (msg *MsgCFilter) MaxPayloadLength(pver uint32) uint32 { // NewMsgCFilter returns a new bitcoin cfilter message that conforms to the // Message interface. See MsgCFilter for details. -func NewMsgCFilter(blockHash *chainhash.Hash, filterType FilterType, +func NewMsgCFilter(filterType FilterType, blockHash *chainhash.Hash, data []byte) *MsgCFilter { return &MsgCFilter{ - BlockHash: *blockHash, FilterType: filterType, + BlockHash: *blockHash, Data: data, } } diff --git a/wire/msggetcfilter.go b/wire/msggetcfilter.go deleted file mode 100644 index 527a391e51..0000000000 --- a/wire/msggetcfilter.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2017 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package wire - -import ( - "io" - - "github.com/btcsuite/btcd/chaincfg/chainhash" -) - -// MsgGetCFilter implements the Message interface and represents a bitcoin -// getcfilter message. It is used to request a committed filter for a block. -type MsgGetCFilter struct { - BlockHash chainhash.Hash - FilterType FilterType -} - -// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. -// This is part of the Message interface implementation. -func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - err := readElement(r, &msg.BlockHash) - if err != nil { - return err - } - return readElement(r, &msg.FilterType) -} - -// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. -// This is part of the Message interface implementation. -func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - err := writeElement(w, &msg.BlockHash) - if err != nil { - return err - } - return writeElement(w, msg.FilterType) -} - -// Command returns the protocol command string for the message. This is part -// of the Message interface implementation. -func (msg *MsgGetCFilter) Command() string { - return CmdGetCFilter -} - -// MaxPayloadLength returns the maximum length the payload can be for the -// receiver. This is part of the Message interface implementation. -func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 { - // Block hash + filter type. - return chainhash.HashSize + 1 -} - -// NewMsgGetCFilter returns a new bitcoin getcfilter message that conforms to -// the Message interface using the passed parameters and defaults for the -// remaining fields. -func NewMsgGetCFilter(blockHash *chainhash.Hash, - filterType FilterType) *MsgGetCFilter { - return &MsgGetCFilter{ - BlockHash: *blockHash, - FilterType: filterType, - } -} diff --git a/wire/msggetcfilters.go b/wire/msggetcfilters.go new file mode 100644 index 0000000000..1156eea840 --- /dev/null +++ b/wire/msggetcfilters.go @@ -0,0 +1,91 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "io" + + "github.com/roasbeef/btcd/chaincfg/chainhash" +) + +// MaxGetCFiltersReqRange the maximum number of filters that may be requested in +// a getcfheaders message. +const MaxGetCFiltersReqRange = 100 + +// MsgGetCFilters implements the Message interface and represents a bitcoin +// getcfilters message. It is used to request committed filters for a range of +// blocks. +type MsgGetCFilters struct { + FilterType FilterType + StartHeight uint32 + StopHash chainhash.Hash +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgGetCFilters) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + err := readElement(r, &msg.FilterType) + if err != nil { + return err + } + + err = readElement(r, &msg.StartHeight) + if err != nil { + return err + } + + err = readElement(r, &msg.StopHash) + if err != nil { + return err + } + + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFilters) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + err := writeElement(w, msg.FilterType) + if err != nil { + return err + } + + err = writeElement(w, &msg.StartHeight) + if err != nil { + return err + } + + err = writeElement(w, &msg.StopHash) + if err != nil { + return err + } + + return nil +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCFilters) Command() string { + return CmdGetCFilters +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCFilters) MaxPayloadLength(pver uint32) uint32 { + // Filter type + uint32 + block hash + return 1 + 4 + chainhash.HashSize +} + +// NewMsgGetCFilters returns a new bitcoin getcfilters message that conforms to +// the Message interface using the passed parameters and defaults for the +// remaining fields. +func NewMsgGetCFilters(filterType FilterType, startHeight uint32, + stopHash *chainhash.Hash) *MsgGetCFilters { + return &MsgGetCFilters{ + FilterType: filterType, + StartHeight: startHeight, + StopHash: *stopHash, + } +} From 7a53a058783408b17de5f24d2c334e429cdcd964 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Fri, 19 Jan 2018 12:34:28 -0800 Subject: [PATCH 0167/1056] multi: Redefine GetCFHeaders to have StartHeight and StopHash. --- peer/peer_test.go | 2 +- server.go | 93 +++++++++-------------------------------- wire/message_test.go | 4 +- wire/msggetcfheaders.go | 81 ++++++++++------------------------- 4 files changed, 44 insertions(+), 136 deletions(-) diff --git a/peer/peer_test.go b/peer/peer_test.go index b4c0a4f44b..cec2f5d2fd 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -540,7 +540,7 @@ func TestPeerListeners(t *testing.T) { }, { "OnGetCFHeaders", - wire.NewMsgGetCFHeaders(), + wire.NewMsgGetCFHeaders(wire.GCSFilterRegular, 0, &chainhash.Hash{}), }, { "OnCFilter", diff --git a/server.go b/server.go index 71f71ed3d9..4b8c468a15 100644 --- a/server.go +++ b/server.go @@ -788,91 +788,36 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { return } - // Attempt to look up the height of the provided stop hash. - chain := sp.server.chain - endIdx := int32(math.MaxInt32) - height, err := chain.BlockHeightByHash(&msg.HashStop) - if err == nil { - endIdx = height + 1 - } - - // There are no block locators so a specific header is being requested - // as identified by the stop hash. - if len(msg.BlockLocatorHashes) == 0 { - // No blocks with the stop hash were found so there is nothing - // to do. Just return. This behavior mirrors the reference - // implementation. - if endIdx == math.MaxInt32 { - return - } - - // Fetch the raw committed filter header bytes from the - // database. - headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( - &msg.HashStop, msg.FilterType) - if (err != nil) || (len(headerBytes) == 0) { - peerLog.Warnf("Could not obtain CF header for %v: %v", - msg.HashStop, err) - return - } - - // Deserialize the hash. - var header chainhash.Hash - err = header.SetBytes(headerBytes) - if err != nil { - peerLog.Warnf("Committed filter header deserialize "+ - "failed: %v", err) - return - } - - headersMsg := wire.NewMsgCFHeaders() - headersMsg.AddCFHeader(&header) - headersMsg.StopHash = msg.HashStop - headersMsg.FilterType = msg.FilterType - sp.QueueMessage(headersMsg, nil) - return + // Fetch the hashes from the block index. + hashList, err := sp.server.chain.HeightToHashRange(int32(msg.StartHeight), + &msg.StopHash, wire.MaxCFHeadersPerMsg) + if err != nil { + peerLog.Debugf("Invalid getcfheaders request: %v", err) } - - // Find the most recent known block based on the block locator. - // Use the block after the genesis block if no other blocks in the - // provided locator are known. This does mean the client will start - // over with the genesis block if unknown block locators are provided. - // This mirrors the behavior in the reference implementation. - startIdx := int32(1) - for _, hash := range msg.BlockLocatorHashes { - height, err := chain.BlockHeightByHash(hash) - if err == nil { - // Start with the next hash since we know this one. - startIdx = height + 1 - break - } + if len(hashList) == 0 { + return } - // Don't attempt to fetch more than we can put into a single message. - if endIdx-startIdx > wire.MaxBlockHeadersPerMsg { - endIdx = startIdx + wire.MaxBlockHeadersPerMsg + // Create []*chainhash.Hash from []chainhash.Hash to pass to + // FilterHeadersByBlockHashes. + hashPtrs := make([]*chainhash.Hash, len(hashList)) + for i := range hashList { + hashPtrs[i] = &hashList[i] } - // Fetch the inventory from the block database. - hashList, err := chain.HeightRange(startIdx, endIdx) + // Fetch the raw filter header bytes from the database for all blocks. + filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes(hashPtrs, + msg.FilterType) if err != nil { - peerLog.Warnf("Header lookup failed: %v", err) - return - } - if len(hashList) == 0 { + peerLog.Errorf("Error retrieving cfilters: %v", err) return } // Generate cfheaders message and send it. headersMsg := wire.NewMsgCFHeaders() - for i := range hashList { - // Fetch the raw committed filter header bytes from the - // database. - headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( - &hashList[i], msg.FilterType) - if (err != nil) || (len(headerBytes) == 0) { - peerLog.Warnf("Could not obtain CF header for %v: %v", - hashList[i], err) + for i, headerBytes := range filterHeaders { + if len(headerBytes) == 0 { + peerLog.Warnf("Could not obtain CF header for %v", hashList[i]) return } diff --git a/wire/message_test.go b/wire/message_test.go index e36fe01bb2..427fdf1c00 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -70,7 +70,7 @@ func TestMessage(t *testing.T) { msgMerkleBlock := NewMsgMerkleBlock(bh) msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilters := NewMsgGetCFilters(GCSFilterExtended, 0, &chainhash.Hash{}) - msgGetCFHeaders := NewMsgGetCFHeaders() + msgGetCFHeaders := NewMsgGetCFHeaders(GCSFilterExtended, 0, &chainhash.Hash{}) msgCFilter := NewMsgCFilter(GCSFilterExtended, &chainhash.Hash{}, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() @@ -104,7 +104,7 @@ func TestMessage(t *testing.T) { {msgMerkleBlock, msgMerkleBlock, pver, MainNet, 110}, {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilters, msgGetCFilters, pver, MainNet, 61}, - {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 58}, + {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 61}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, } diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index d93e4e627d..d792864362 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -5,7 +5,6 @@ package wire import ( - "fmt" "io" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -15,87 +14,51 @@ import ( // filter headers. It allows to set the FilterType field to get headers in the // chain of basic (0x00) or extended (0x01) headers. type MsgGetCFHeaders struct { - BlockLocatorHashes []*chainhash.Hash - HashStop chainhash.Hash - FilterType FilterType -} - -// AddBlockLocatorHash adds a new block locator hash to the message. -func (msg *MsgGetCFHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { - if len(msg.BlockLocatorHashes)+1 > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message [max %v]", - MaxBlockLocatorsPerMsg) - return messageError("MsgGetCFHeaders.AddBlockLocatorHash", str) - } - - msg.BlockLocatorHashes = append(msg.BlockLocatorHashes, hash) - return nil + FilterType FilterType + StartHeight uint32 + StopHash chainhash.Hash } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - // Read num block locator hashes and limit to max. - count, err := ReadVarInt(r, pver) + err := readElement(r, &msg.FilterType) if err != nil { return err } - if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ - "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetHeaders.BtcDecode", str) - } - // Create a contiguous slice of hashes to deserialize into in order to - // reduce the number of allocations. - locatorHashes := make([]chainhash.Hash, count) - msg.BlockLocatorHashes = make([]*chainhash.Hash, 0, count) - for i := uint64(0); i < count; i++ { - hash := &locatorHashes[i] - err := readElement(r, hash) - if err != nil { - return err - } - msg.AddBlockLocatorHash(hash) + err = readElement(r, &msg.StartHeight) + if err != nil { + return err } - err = readElement(r, &msg.HashStop) + err = readElement(r, &msg.StopHash) if err != nil { return err } - return readElement(r, &msg.FilterType) + return nil } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - // Limit to max block locator hashes per message. - count := len(msg.BlockLocatorHashes) - if count > MaxBlockLocatorsPerMsg { - str := fmt.Sprintf("too many block locator hashes for message "+ - "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) - return messageError("MsgGetHeaders.BtcEncode", str) - } - - err := WriteVarInt(w, pver, uint64(count)) + err := writeElement(w, msg.FilterType) if err != nil { return err } - for _, hash := range msg.BlockLocatorHashes { - err := writeElement(w, hash) - if err != nil { - return err - } + err = writeElement(w, &msg.StartHeight) + if err != nil { + return err } - err = writeElement(w, &msg.HashStop) + err = writeElement(w, &msg.StopHash) if err != nil { return err } - return writeElement(w, msg.FilterType) + return nil } // Command returns the protocol command string for the message. This is part @@ -107,18 +70,18 @@ func (msg *MsgGetCFHeaders) Command() string { // MaxPayloadLength returns the maximum length the payload can be for the // receiver. This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) MaxPayloadLength(pver uint32) uint32 { - // Num block locator hashes (varInt) + max allowed - // block locators + hash stop + filter type 1 byte. - return MaxVarIntPayload + (MaxBlockLocatorsPerMsg * - chainhash.HashSize) + chainhash.HashSize + 1 + // Filter type + uint32 + block hash + return 1 + 4 + chainhash.HashSize } // NewMsgGetCFHeaders returns a new bitcoin getcfheader message that conforms to // the Message interface using the passed parameters and defaults for the // remaining fields. -func NewMsgGetCFHeaders() *MsgGetCFHeaders { +func NewMsgGetCFHeaders(filterType FilterType, startHeight uint32, + stopHash *chainhash.Hash) *MsgGetCFHeaders { return &MsgGetCFHeaders{ - BlockLocatorHashes: make([]*chainhash.Hash, 0, - MaxBlockLocatorsPerMsg), + FilterType: filterType, + StartHeight: startHeight, + StopHash: *stopHash, } } From 175af180431c3b4344af643d8a49a2cbfe3ad8af Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Fri, 19 Jan 2018 13:06:39 -0800 Subject: [PATCH 0168/1056] multi: Modify CFHeaders message to have a PrevFilterHeader field. --- server.go | 52 +++++++++++++++++++++++++++++++++++++++++--- wire/message_test.go | 2 +- wire/msgcfheaders.go | 33 +++++++++++++++++++--------- 3 files changed, 73 insertions(+), 14 deletions(-) diff --git a/server.go b/server.go index 4b8c468a15..b20a29d409 100644 --- a/server.go +++ b/server.go @@ -788,13 +788,28 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { return } + startHeight := int32(msg.StartHeight) + maxResults := wire.MaxCFHeadersPerMsg + + // If StartHeight is positive, fetch the predecessor block hash so we can + // populate the PrevFilterHeader field. + if msg.StartHeight > 0 { + startHeight-- + maxResults++ + } + // Fetch the hashes from the block index. - hashList, err := sp.server.chain.HeightToHashRange(int32(msg.StartHeight), - &msg.StopHash, wire.MaxCFHeadersPerMsg) + hashList, err := sp.server.chain.HeightToHashRange(startHeight, + &msg.StopHash, maxResults) if err != nil { peerLog.Debugf("Invalid getcfheaders request: %v", err) } - if len(hashList) == 0 { + + // This is possible if StartHeight is one greater that the height of + // StopHash, and we pull a valid range of hashes including the previous + // filter header. + if len(hashList) == 0 || (msg.StartHeight > 0 && len(hashList) == 1) { + peerLog.Debug("No results for getcfheaders request") return } @@ -815,6 +830,37 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { // Generate cfheaders message and send it. headersMsg := wire.NewMsgCFHeaders() + + // Populate the PrevFilterHeader field. + if msg.StartHeight > 0 { + prevBlockHash := &hashList[0] + + // Fetch the raw committed filter header bytes from the + // database. + headerBytes, err := sp.server.cfIndex.FilterHeaderByBlockHash( + prevBlockHash, msg.FilterType) + if err != nil { + peerLog.Errorf("Error retrieving CF header: %v", err) + return + } + if len(headerBytes) == 0 { + peerLog.Warnf("Could not obtain CF header for %v", prevBlockHash) + return + } + + // Deserialize the hash into PrevFilterHeader. + err = headersMsg.PrevFilterHeader.SetBytes(headerBytes) + if err != nil { + peerLog.Warnf("Committed filter header deserialize "+ + "failed: %v", err) + return + } + + hashList = hashList[1:] + filterHeaders = filterHeaders[1:] + } + + // Populate HeaderHashes. for i, headerBytes := range filterHeaders { if len(headerBytes) == 0 { peerLog.Warnf("Could not obtain CF header for %v", hashList[i]) diff --git a/wire/message_test.go b/wire/message_test.go index 427fdf1c00..806a196e2f 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -106,7 +106,7 @@ func TestMessage(t *testing.T) { {msgGetCFilters, msgGetCFilters, pver, MainNet, 61}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 61}, {msgCFilter, msgCFilter, pver, MainNet, 65}, - {msgCFHeaders, msgCFHeaders, pver, MainNet, 58}, + {msgCFHeaders, msgCFHeaders, pver, MainNet, 90}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 0186a53fdb..a7ce306e4d 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -27,9 +27,10 @@ const ( // of committed filter headers per message is currently 2000. See // MsgGetCFHeaders for details on requesting the headers. type MsgCFHeaders struct { - StopHash chainhash.Hash - FilterType FilterType - HeaderHashes []*chainhash.Hash + FilterType FilterType + StopHash chainhash.Hash + PrevFilterHeader chainhash.Hash + HeaderHashes []*chainhash.Hash } // AddCFHeader adds a new committed filter header to the message. @@ -47,14 +48,20 @@ func (msg *MsgCFHeaders) AddCFHeader(headerHash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + // Read filter type + err := readElement(r, &msg.FilterType) + if err != nil { + return err + } + // Read stop hash - err := readElement(r, &msg.StopHash) + err = readElement(r, &msg.StopHash) if err != nil { return err } - // Read filter type - err = readElement(r, &msg.FilterType) + // Read prev filter header + err = readElement(r, &msg.PrevFilterHeader) if err != nil { return err } @@ -91,14 +98,20 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + // Write filter type + err := writeElement(w, msg.FilterType) + if err != nil { + return err + } + // Write stop hash - err := writeElement(w, msg.StopHash) + err = writeElement(w, msg.StopHash) if err != nil { return err } - // Write filter type - err = writeElement(w, msg.FilterType) + // Write prev filter header + err = writeElement(w, msg.PrevFilterHeader) if err != nil { return err } @@ -154,7 +167,7 @@ func (msg *MsgCFHeaders) Command() string { func (msg *MsgCFHeaders) MaxPayloadLength(pver uint32) uint32 { // Hash size + filter type + num headers (varInt) + // (header size * max headers). - return chainhash.HashSize + 1 + MaxVarIntPayload + + return 1 + chainhash.HashSize + chainhash.HashSize + MaxVarIntPayload + (MaxCFHeaderPayload * MaxCFHeadersPerMsg) } From 4c991c8783deb79b1f933ccba59cbe7f6c877fad Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 22 Jan 2018 13:14:46 -0800 Subject: [PATCH 0169/1056] wire: Populate cfheaders message with filter hashes instead of headers. --- server.go | 23 +++++++++++------------ wire/msgcfheaders.go | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/server.go b/server.go index b20a29d409..b19cb4540f 100644 --- a/server.go +++ b/server.go @@ -820,11 +820,11 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { hashPtrs[i] = &hashList[i] } - // Fetch the raw filter header bytes from the database for all blocks. - filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes(hashPtrs, + // Fetch the raw filter hash bytes from the database for all blocks. + filterHashes, err := sp.server.cfIndex.FilterHashesByBlockHashes(hashPtrs, msg.FilterType) if err != nil { - peerLog.Errorf("Error retrieving cfilters: %v", err) + peerLog.Errorf("Error retrieving cfilter hashes: %v", err) return } @@ -857,30 +857,29 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { } hashList = hashList[1:] - filterHeaders = filterHeaders[1:] + filterHashes = filterHashes[1:] } // Populate HeaderHashes. - for i, headerBytes := range filterHeaders { - if len(headerBytes) == 0 { - peerLog.Warnf("Could not obtain CF header for %v", hashList[i]) + for i, hashBytes := range filterHashes { + if len(hashBytes) == 0 { + peerLog.Warnf("Could not obtain CF hash for %v", hashList[i]) return } // Deserialize the hash. - var header chainhash.Hash - err = header.SetBytes(headerBytes) + filterHash, err := chainhash.NewHash(hashBytes) if err != nil { - peerLog.Warnf("Committed filter header deserialize "+ + peerLog.Warnf("Committed filter hash deserialize "+ "failed: %v", err) return } - headersMsg.AddCFHeader(&header) + headersMsg.AddCFHash(filterHash) } headersMsg.FilterType = msg.FilterType - headersMsg.StopHash = hashList[len(hashList)-1] + headersMsg.StopHash = msg.StopHash sp.QueueMessage(headersMsg, nil) } diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index a7ce306e4d..a35728070d 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -30,18 +30,18 @@ type MsgCFHeaders struct { FilterType FilterType StopHash chainhash.Hash PrevFilterHeader chainhash.Hash - HeaderHashes []*chainhash.Hash + FilterHashes []*chainhash.Hash } // AddCFHeader adds a new committed filter header to the message. -func (msg *MsgCFHeaders) AddCFHeader(headerHash *chainhash.Hash) error { - if len(msg.HeaderHashes)+1 > MaxCFHeadersPerMsg { +func (msg *MsgCFHeaders) AddCFHash(hash *chainhash.Hash) error { + if len(msg.FilterHashes)+1 > MaxCFHeadersPerMsg { str := fmt.Sprintf("too many block headers in message [max %v]", MaxBlockHeadersPerMsg) - return messageError("MsgCFHeaders.AddCFHeader", str) + return messageError("MsgCFHeaders.AddCFHash", str) } - msg.HeaderHashes = append(msg.HeaderHashes, headerHash) + msg.FilterHashes = append(msg.FilterHashes, hash) return nil } @@ -80,16 +80,16 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) return messageError("MsgCFHeaders.BtcDecode", str) } - // Create a contiguous slice of headers to deserialize into in order to + // Create a contiguous slice of hashes to deserialize into in order to // reduce the number of allocations. - msg.HeaderHashes = make([]*chainhash.Hash, 0, count) + msg.FilterHashes = make([]*chainhash.Hash, 0, count) for i := uint64(0); i < count; i++ { var cfh chainhash.Hash err := readElement(r, &cfh) if err != nil { return err } - msg.AddCFHeader(&cfh) + msg.AddCFHash(&cfh) } return nil @@ -117,7 +117,7 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) } // Limit to max committed headers per message. - count := len(msg.HeaderHashes) + count := len(msg.FilterHashes) if count > MaxCFHeadersPerMsg { str := fmt.Sprintf("too many committed filter headers for "+ "message [count %v, max %v]", count, @@ -130,7 +130,7 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) return err } - for _, cfh := range msg.HeaderHashes { + for _, cfh := range msg.FilterHashes { err := writeElement(w, cfh) if err != nil { return err @@ -175,6 +175,6 @@ func (msg *MsgCFHeaders) MaxPayloadLength(pver uint32) uint32 { // the Message interface. See MsgCFHeaders for details. func NewMsgCFHeaders() *MsgCFHeaders { return &MsgCFHeaders{ - HeaderHashes: make([]*chainhash.Hash, 0, MaxCFHeadersPerMsg), + FilterHashes: make([]*chainhash.Hash, 0, MaxCFHeadersPerMsg), } } From 336b18c584b8131564aa89c041ba91a21511f1b5 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 22 Jan 2018 13:56:27 -0800 Subject: [PATCH 0170/1056] wire: Define GetCFCheckpt message. --- peer/peer.go | 9 +++++ peer/peer_test.go | 7 ++++ wire/message.go | 4 +++ wire/message_test.go | 2 ++ wire/msggetcfcheckpt.go | 75 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 wire/msggetcfcheckpt.go diff --git a/peer/peer.go b/peer/peer.go index b9d802a4c9..4b1c3a532f 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -159,6 +159,10 @@ type MessageListeners struct { // bitcoin message. OnGetCFHeaders func(p *Peer, msg *wire.MsgGetCFHeaders) + // OnGetCFCheckpt is invoked when a peer receives a getcfcheckpt + // bitcoin message. + OnGetCFCheckpt func(p *Peer, msg *wire.MsgGetCFCheckpt) + // OnFeeFilter is invoked when a peer receives a feefilter bitcoin message. OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter) @@ -1601,6 +1605,11 @@ out: p.cfg.Listeners.OnGetCFHeaders(p, msg) } + case *wire.MsgGetCFCheckpt: + if p.cfg.Listeners.OnGetCFCheckpt != nil { + p.cfg.Listeners.OnGetCFCheckpt(p, msg) + } + case *wire.MsgCFilter: if p.cfg.Listeners.OnCFilter != nil { p.cfg.Listeners.OnCFilter(p, msg) diff --git a/peer/peer_test.go b/peer/peer_test.go index cec2f5d2fd..34ab1144d8 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -405,6 +405,9 @@ func TestPeerListeners(t *testing.T) { OnGetCFHeaders: func(p *peer.Peer, msg *wire.MsgGetCFHeaders) { ok <- msg }, + OnGetCFCheckpt: func(p *peer.Peer, msg *wire.MsgGetCFCheckpt) { + ok <- msg + }, OnCFilter: func(p *peer.Peer, msg *wire.MsgCFilter) { ok <- msg }, @@ -542,6 +545,10 @@ func TestPeerListeners(t *testing.T) { "OnGetCFHeaders", wire.NewMsgGetCFHeaders(wire.GCSFilterRegular, 0, &chainhash.Hash{}), }, + { + "OnGetCFCheckpt", + wire.NewMsgGetCFCheckpt(wire.GCSFilterRegular, &chainhash.Hash{}), + }, { "OnCFilter", wire.NewMsgCFilter(wire.GCSFilterRegular, &chainhash.Hash{}, diff --git a/wire/message.go b/wire/message.go index f00267d729..f055801e67 100644 --- a/wire/message.go +++ b/wire/message.go @@ -53,6 +53,7 @@ const ( CmdFeeFilter = "feefilter" CmdGetCFilters = "getcfilters" CmdGetCFHeaders = "getcfheaders" + CmdGetCFCheckpt = "getcfcheckpt" CmdCFilter = "cfilter" CmdCFHeaders = "cfheaders" ) @@ -166,6 +167,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdGetCFHeaders: msg = &MsgGetCFHeaders{} + case CmdGetCFCheckpt: + msg = &MsgGetCFCheckpt{} + case CmdCFilter: msg = &MsgCFilter{} diff --git a/wire/message_test.go b/wire/message_test.go index 806a196e2f..24a01cd86d 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -71,6 +71,7 @@ func TestMessage(t *testing.T) { msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") msgGetCFilters := NewMsgGetCFilters(GCSFilterExtended, 0, &chainhash.Hash{}) msgGetCFHeaders := NewMsgGetCFHeaders(GCSFilterExtended, 0, &chainhash.Hash{}) + msgGetCFCheckpt := NewMsgGetCFCheckpt(GCSFilterExtended, &chainhash.Hash{}) msgCFilter := NewMsgCFilter(GCSFilterExtended, &chainhash.Hash{}, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() @@ -105,6 +106,7 @@ func TestMessage(t *testing.T) { {msgReject, msgReject, pver, MainNet, 79}, {msgGetCFilters, msgGetCFilters, pver, MainNet, 61}, {msgGetCFHeaders, msgGetCFHeaders, pver, MainNet, 61}, + {msgGetCFCheckpt, msgGetCFCheckpt, pver, MainNet, 57}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 90}, } diff --git a/wire/msggetcfcheckpt.go b/wire/msggetcfcheckpt.go new file mode 100644 index 0000000000..12ecce4e21 --- /dev/null +++ b/wire/msggetcfcheckpt.go @@ -0,0 +1,75 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "io" + + "github.com/roasbeef/btcd/chaincfg/chainhash" +) + +// MsgGetCFCheckpt is a request for filter headers at evenly spaced intervals +// throughout the blockchain history. It allows to set the FilterType field to +// get headers in the chain of basic (0x00) or extended (0x01) headers. +type MsgGetCFCheckpt struct { + FilterType FilterType + StopHash chainhash.Hash +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgGetCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + err := readElement(r, &msg.FilterType) + if err != nil { + return err + } + + err = readElement(r, &msg.StopHash) + if err != nil { + return err + } + + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgGetCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + err := writeElement(w, msg.FilterType) + if err != nil { + return err + } + + err = writeElement(w, &msg.StopHash) + if err != nil { + return err + } + + return nil +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgGetCFCheckpt) Command() string { + return CmdGetCFCheckpt +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgGetCFCheckpt) MaxPayloadLength(pver uint32) uint32 { + // Filter type + uint32 + block hash + return 1 + chainhash.HashSize +} + +// NewMsgGetCFCheckpt returns a new bitcoin getcfcheckpt message that conforms +// to the Message interface using the passed parameters and defaults for the +// remaining fields. +func NewMsgGetCFCheckpt(filterType FilterType, stopHash *chainhash.Hash, +) *MsgGetCFCheckpt { + return &MsgGetCFCheckpt{ + FilterType: filterType, + StopHash: *stopHash, + } +} From 0581e18840700d61f9a406d795796ef24fd66794 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 22 Jan 2018 16:51:53 -0800 Subject: [PATCH 0171/1056] wire: Define CFCheckpt message. --- peer/peer.go | 4 ++ wire/message.go | 4 ++ wire/message_test.go | 2 + wire/msgcfcheckpt.go | 147 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 wire/msgcfcheckpt.go diff --git a/peer/peer.go b/peer/peer.go index 4b1c3a532f..64a6e759e5 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -130,6 +130,10 @@ type MessageListeners struct { // message. OnCFHeaders func(p *Peer, msg *wire.MsgCFHeaders) + // OnCFCheckpt is invoked when a peer receives a cfcheckpt bitcoin + // message. + OnCFCheckpt func(p *Peer, msg *wire.MsgCFCheckpt) + // OnInv is invoked when a peer receives an inv bitcoin message. OnInv func(p *Peer, msg *wire.MsgInv) diff --git a/wire/message.go b/wire/message.go index f055801e67..4f03cf5643 100644 --- a/wire/message.go +++ b/wire/message.go @@ -56,6 +56,7 @@ const ( CmdGetCFCheckpt = "getcfcheckpt" CmdCFilter = "cfilter" CmdCFHeaders = "cfheaders" + CmdCFCheckpt = "cfcheckpt" ) // MessageEncoding represents the wire message encoding format to be used. @@ -176,6 +177,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdCFHeaders: msg = &MsgCFHeaders{} + case CmdCFCheckpt: + msg = &MsgCFCheckpt{} + default: return nil, fmt.Errorf("unhandled command [%s]", command) } diff --git a/wire/message_test.go b/wire/message_test.go index 24a01cd86d..a174c49aff 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -75,6 +75,7 @@ func TestMessage(t *testing.T) { msgCFilter := NewMsgCFilter(GCSFilterExtended, &chainhash.Hash{}, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() + msgCFCheckpt := NewMsgCFCheckpt(GCSFilterExtended, &chainhash.Hash{}, 0) tests := []struct { in Message // Value to encode @@ -109,6 +110,7 @@ func TestMessage(t *testing.T) { {msgGetCFCheckpt, msgGetCFCheckpt, pver, MainNet, 57}, {msgCFilter, msgCFilter, pver, MainNet, 65}, {msgCFHeaders, msgCFHeaders, pver, MainNet, 90}, + {msgCFCheckpt, msgCFCheckpt, pver, MainNet, 58}, } t.Logf("Running %d tests", len(tests)) diff --git a/wire/msgcfcheckpt.go b/wire/msgcfcheckpt.go new file mode 100644 index 0000000000..179abe6672 --- /dev/null +++ b/wire/msgcfcheckpt.go @@ -0,0 +1,147 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "fmt" + "io" + + "github.com/roasbeef/btcd/chaincfg/chainhash" +) + +const ( + CFCheckptInterval = 1000 +) + +// MsgCFCheckpt implements the Message interface and represents a bitcoin +// cfcheckpt message. It is used to deliver committed filter header information +// in response to a getcfcheckpt message (MsgGetCFCheckpt). See MsgGetCFCheckpt +// for details on requesting the headers. +type MsgCFCheckpt struct { + FilterType FilterType + StopHash chainhash.Hash + FilterHeaders []*chainhash.Hash +} + +// AddCFHeader adds a new committed filter header to the message. +func (msg *MsgCFCheckpt) AddCFHeader(header *chainhash.Hash) error { + if len(msg.FilterHeaders) == cap(msg.FilterHeaders) { + str := fmt.Sprintf("FilterHeaders has insufficient capacity for "+ + "additional header: len = %d", len(msg.FilterHeaders)) + return messageError("MsgCFCheckpt.AddCFHeader", str) + } + + msg.FilterHeaders = append(msg.FilterHeaders, header) + return nil +} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + // Read filter type + err := readElement(r, &msg.FilterType) + if err != nil { + return err + } + + // Read stop hash + err = readElement(r, &msg.StopHash) + if err != nil { + return err + } + + // Read number of filter headers + count, err := ReadVarInt(r, pver) + if err != nil { + return err + } + + // Create a contiguous slice of hashes to deserialize into in order to + // reduce the number of allocations. + msg.FilterHeaders = make([]*chainhash.Hash, count, count) + for i := uint64(0); i < count; i++ { + var cfh chainhash.Hash + err := readElement(r, &cfh) + if err != nil { + return err + } + msg.FilterHeaders[i] = &cfh + } + + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + // Write filter type + err := writeElement(w, msg.FilterType) + if err != nil { + return err + } + + // Write stop hash + err = writeElement(w, msg.StopHash) + if err != nil { + return err + } + + // Write length of FilterHeaders slice + count := len(msg.FilterHeaders) + err = WriteVarInt(w, pver, uint64(count)) + if err != nil { + return err + } + + for _, cfh := range msg.FilterHeaders { + err := writeElement(w, cfh) + if err != nil { + return err + } + } + + return nil +} + +// Deserialize decodes a filter header from r into the receiver using a format +// that is suitable for long-term storage such as a database. This function +// differs from BtcDecode in that BtcDecode decodes from the bitcoin wire +// protocol as it was sent across the network. The wire encoding can +// technically differ depending on the protocol version and doesn't even really +// need to match the format of a stored filter header at all. As of the time +// this comment was written, the encoded filter header is the same in both +// instances, but there is a distinct difference and separating the two allows +// the API to be flexible enough to deal with changes. +func (msg *MsgCFCheckpt) Deserialize(r io.Reader) error { + // At the current time, there is no difference between the wire encoding + // and the stable long-term storage format. As a result, make use of + // BtcDecode. + return msg.BtcDecode(r, 0, BaseEncoding) +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgCFCheckpt) Command() string { + return CmdCFCheckpt +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgCFCheckpt) MaxPayloadLength(pver uint32) uint32 { + // Message size depends on the blockchain height, so return general limit + // for all messages. + return MaxMessagePayload +} + +// NewMsgCFCheckpt returns a new bitcoin cfheaders message that conforms to +// the Message interface. See MsgCFCheckpt for details. +func NewMsgCFCheckpt(filterType FilterType, stopHash *chainhash.Hash, + headersCount int) *MsgCFCheckpt { + return &MsgCFCheckpt{ + FilterType: filterType, + StopHash: *stopHash, + FilterHeaders: make([]*chainhash.Hash, 0, headersCount), + } +} From 4d0e856ea15a798b32e11363caf53582349490db Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Mon, 22 Jan 2018 20:39:30 -0800 Subject: [PATCH 0172/1056] server: Handler for getcfcheckpt messages. --- server.go | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/server.go b/server.go index b19cb4540f..f3e4c9f70b 100644 --- a/server.go +++ b/server.go @@ -186,6 +186,13 @@ func (ps *peerState) forAllPeers(closure func(sp *serverPeer)) { ps.forAllOutboundPeers(closure) } +// cfHeaderKV is a tuple of a filter header and its associated block hash. The +// struct is used to cache cfcheckpt responses. +type cfHeaderKV struct { + blockHash chainhash.Hash + filterHeader chainhash.Hash +} + // server provides a bitcoin server for handling communications to and from // bitcoin peers. type server struct { @@ -234,6 +241,11 @@ type server struct { // The fee estimator keeps track of how long transactions are left in // the mempool before they are mined into blocks. feeEstimator *mempool.FeeEstimator + + // cfCheckptCaches stores a cached slice of filter headers for cfcheckpt + // messages for each filter type. + cfCheckptCaches map[wire.FilterType][]cfHeaderKV + cfCheckptCachesMtx sync.RWMutex } // serverPeer extends the peer to maintain state shared by the server and @@ -883,6 +895,105 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { sp.QueueMessage(headersMsg, nil) } +// OnGetCFCheckpt is invoked when a peer receives a getcfcheckpt bitcoin message. +func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { + // Ignore getcfcheckpt requests if not in sync. + if !sp.server.syncManager.IsCurrent() { + return + } + + blockHashes, err := sp.server.chain.IntervalBlockHashes(&msg.StopHash, + wire.CFCheckptInterval) + if err != nil { + peerLog.Debugf("Invalid getcfilters request: %v", err) + return + } + + var updateCache bool + var checkptCache []cfHeaderKV + + if len(blockHashes) > len(checkptCache) { + // Update the cache if the checkpoint chain is longer than the cached + // one. This ensures that the cache is relatively stable and mostly + // overlaps with the best chain, since it follows the longest chain + // heuristic. + updateCache = true + + // Take write lock because we are going to update cache. + sp.server.cfCheckptCachesMtx.Lock() + defer sp.server.cfCheckptCachesMtx.Unlock() + + // Grow the checkptCache to be the length of blockHashes. + additionalLength := len(blockHashes) - len(checkptCache) + checkptCache = append(sp.server.cfCheckptCaches[msg.FilterType], + make([]cfHeaderKV, additionalLength)...) + } else { + updateCache = false + + // Take reader lock because we are not going to update cache. + sp.server.cfCheckptCachesMtx.RLock() + defer sp.server.cfCheckptCachesMtx.RUnlock() + + checkptCache = sp.server.cfCheckptCaches[msg.FilterType] + } + + // Iterate backwards until the block hash is found in the cache. + var forkIdx int + for forkIdx = len(checkptCache); forkIdx > 0; forkIdx-- { + if checkptCache[forkIdx-1].blockHash == blockHashes[forkIdx-1] { + break + } + } + + // Populate results with cached checkpoints. + checkptMsg := wire.NewMsgCFCheckpt(msg.FilterType, &msg.StopHash, + len(blockHashes)) + for i := 0; i < forkIdx; i++ { + checkptMsg.AddCFHeader(&checkptCache[i].filterHeader) + } + + // Look up any filter headers that aren't cached. + blockHashPtrs := make([]*chainhash.Hash, 0, len(blockHashes)-forkIdx) + for i := forkIdx; i < len(blockHashes); i++ { + blockHashPtrs = append(blockHashPtrs, &blockHashes[i]) + } + + filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes(blockHashPtrs, + msg.FilterType) + if err != nil { + peerLog.Errorf("Error retrieving cfilter headers: %v", err) + return + } + + for i, filterHeaderBytes := range filterHeaders { + if len(filterHeaderBytes) == 0 { + peerLog.Warnf("Could not obtain CF header for %v", blockHashPtrs[i]) + return + } + + filterHeader, err := chainhash.NewHash(filterHeaderBytes) + if err != nil { + peerLog.Warnf("Committed filter header deserialize "+ + "failed: %v", err) + return + } + + checkptMsg.AddCFHeader(filterHeader) + if updateCache { + checkptCache[forkIdx+i] = cfHeaderKV{ + blockHash: blockHashes[forkIdx+i], + filterHeader: *filterHeader, + } + } + } + + if updateCache { + sp.server.cfCheckptCaches[msg.FilterType] = checkptCache + } + + sp.QueueMessage(checkptMsg, nil) +} + // enforceNodeBloomFlag disconnects the peer if the server is not configured to // allow bloom filters. Additionally, if the peer has negotiated to a protocol // version that is high enough to observe the bloom filter service support bit, @@ -1732,6 +1843,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnGetHeaders: sp.OnGetHeaders, OnGetCFilters: sp.OnGetCFilters, OnGetCFHeaders: sp.OnGetCFHeaders, + OnGetCFCheckpt: sp.OnGetCFCheckpt, OnFeeFilter: sp.OnFeeFilter, OnFilterAdd: sp.OnFilterAdd, OnFilterClear: sp.OnFilterClear, @@ -2351,6 +2463,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param services: services, sigCache: txscript.NewSigCache(cfg.SigCacheMaxSize), hashCache: txscript.NewHashCache(cfg.SigCacheMaxSize), + cfCheckptCaches: make(map[wire.FilterType][]cfHeaderKV), } // Create the transaction and address indexes if needed. From 7b67f61fa64579922191374374fa8c3bff4236a8 Mon Sep 17 00:00:00 2001 From: Jim Posen Date: Wed, 31 Jan 2018 21:47:03 -0800 Subject: [PATCH 0173/1056] rpcclient: Put CFHeader in PrevFilterHeader field in RPC response. --- rpcclient/chain.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 3d8f9c813c..fd7a781e2d 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -900,11 +900,7 @@ func (r FutureGetCFilterHeaderResult) Receive() (*wire.MsgCFHeaders, error) { } // Assign the hash to a headers message and return it. - var msgCFHeaders wire.MsgCFHeaders - err = msgCFHeaders.AddCFHeader(headerHash) - if err != nil { - return nil, err - } + msgCFHeaders := wire.MsgCFHeaders{PrevFilterHeader: *headerHash} return &msgCFHeaders, nil } From ceb1caeb249cf3c7a8c1be2987af64bfffdd674d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 31 Mar 2018 16:38:14 -0700 Subject: [PATCH 0174/1056] wire: increase MaxGetCFiltersReqRange from 100 to 1000 --- wire/msggetcfilters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/msggetcfilters.go b/wire/msggetcfilters.go index 1156eea840..3ea88b390a 100644 --- a/wire/msggetcfilters.go +++ b/wire/msggetcfilters.go @@ -12,7 +12,7 @@ import ( // MaxGetCFiltersReqRange the maximum number of filters that may be requested in // a getcfheaders message. -const MaxGetCFiltersReqRange = 100 +const MaxGetCFiltersReqRange = 1000 // MsgGetCFilters implements the Message interface and represents a bitcoin // getcfilters message. It is used to request committed filters for a range of From 5394ca1afe86465d6c298b50cbdfd646f665b95c Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 23 Mar 2018 15:11:20 +0100 Subject: [PATCH 0175/1056] mempool: add CheckSpend method This commit adds a new method CheckSpend to the mempool, which takes an outpoint and returns any transaction in the mempool that spends this outpoint. --- mempool/mempool.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mempool/mempool.go b/mempool/mempool.go index ac339bf3d1..91dbb6dea5 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -571,6 +571,17 @@ func (mp *TxPool) checkPoolDoubleSpend(tx *btcutil.Tx) error { return nil } +// CheckSpends checks whether the passed outpoint is already spent by a +// transaction in the mempool. If that's the case the spending transaction will +// be returned, if not nil will be returned. +func (mp *TxPool) CheckSpend(op wire.OutPoint) *btcutil.Tx { + mp.mtx.RLock() + txR := mp.outpoints[op] + mp.mtx.RUnlock() + + return txR +} + // fetchInputUtxos loads utxo details about the input transactions referenced by // the passed transaction. First, it loads the details form the viewpoint of // the main chain, then it adjusts them based upon the contents of the From c758834800ea391ec27d0b2a78898444d497cb2c Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 23 Mar 2018 15:40:06 +0100 Subject: [PATCH 0176/1056] mempool_test: add TestCheckSpend --- mempool/mempool_test.go | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 6354126637..e1e5e7702c 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -794,3 +794,72 @@ func TestMultiInputOrphanDoubleSpend(t *testing.T) { // was not moved to the transaction pool. testPoolMembership(tc, doubleSpendTx, false, false) } + +// TestCheckSpend tests that CheckSpend returns the expected spends found in +// the mempool. +func TestCheckSpend(t *testing.T) { + t.Parallel() + + harness, outputs, err := newPoolHarness(&chaincfg.MainNetParams) + if err != nil { + t.Fatalf("unable to create test pool: %v", err) + } + + // The mempool is empty, so none of the spendable outputs should have a + // spend there. + for _, op := range outputs { + spend := harness.txPool.CheckSpend(op.outPoint) + if spend != nil { + t.Fatalf("Unexpeced spend found in pool: %v", spend) + } + } + + // Create a chain of transactions rooted with the first spendable + // output provided by the harness. + const txChainLength = 5 + chainedTxns, err := harness.CreateTxChain(outputs[0], txChainLength) + if err != nil { + t.Fatalf("unable to create transaction chain: %v", err) + } + for _, tx := range chainedTxns { + _, err := harness.txPool.ProcessTransaction(tx, true, + false, 0) + if err != nil { + t.Fatalf("ProcessTransaction: failed to accept "+ + "tx: %v", err) + } + } + + // The first tx in the chain should be the spend of the spendable + // output. + op := outputs[0].outPoint + spend := harness.txPool.CheckSpend(op) + if spend != chainedTxns[0] { + t.Fatalf("expected %v to be spent by %v, instead "+ + "got %v", op, chainedTxns[0], spend) + } + + // Now all but the last tx should be spent by the next. + for i := 0; i < len(chainedTxns)-1; i++ { + op = wire.OutPoint{ + Hash: *chainedTxns[i].Hash(), + Index: 0, + } + expSpend := chainedTxns[i+1] + spend = harness.txPool.CheckSpend(op) + if spend != expSpend { + t.Fatalf("expected %v to be spent by %v, instead "+ + "got %v", op, expSpend, spend) + } + } + + // The last tx should have no spend. + op = wire.OutPoint{ + Hash: *chainedTxns[txChainLength-1].Hash(), + Index: 0, + } + spend = harness.txPool.CheckSpend(op) + if spend != nil { + t.Fatalf("Unexpeced spend found in pool: %v", spend) + } +} From 3082ae92c3c6c184e91d0bbfc5f6ab902f1b513f Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Fri, 23 Mar 2018 15:44:35 +0100 Subject: [PATCH 0177/1056] rpcwebsocket: notify spends already in the mempool This commit adds a logic to the addSpentRequests that inspects the mempool for any spends of the outputs. Before this commit, a spend would only be checked when a transaction was first accepted into the mempool. --- rpcwebsocket.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index fcdcce2e7f..8b9d06b445 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -883,7 +883,7 @@ func (m *wsNotificationManager) RegisterSpentRequests(wsc *wsClient, ops []*wire // addSpentRequests modifies a map of watched outpoints to sets of websocket // clients to add a new request watch all of the outpoints in ops and create // and send a notification when spent to the websocket client wsc. -func (*wsNotificationManager) addSpentRequests(opMap map[wire.OutPoint]map[chan struct{}]*wsClient, +func (m *wsNotificationManager) addSpentRequests(opMap map[wire.OutPoint]map[chan struct{}]*wsClient, wsc *wsClient, ops []*wire.OutPoint) { for _, op := range ops { @@ -900,6 +900,22 @@ func (*wsNotificationManager) addSpentRequests(opMap map[wire.OutPoint]map[chan } cmap[wsc.quit] = wsc } + + // Check if any transactions spending these outputs already exists in + // the mempool, if so send the notification immediately. + spends := make(map[chainhash.Hash]*btcutil.Tx) + for _, op := range ops { + spend := m.server.cfg.TxMemPool.CheckSpend(*op) + if spend != nil { + rpcsLog.Debugf("Found existing mempool spend for "+ + "outpoint<%v>: %v", op, spend.Hash()) + spends[*spend.Hash()] = spend + } + } + + for _, spend := range spends { + m.notifyForTx(opMap, nil, spend, nil) + } } // UnregisterSpentRequest removes a request from the passed websocket client From b72e16f0d61e848dfbd81c8af0d1473f30e502c2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 14 May 2018 20:44:11 -0700 Subject: [PATCH 0178/1056] multi: correct all import paths --- CHANGES | 26 +++++----- blockchain/chainview_test.go | 2 +- blockchain/indexers/cfindex.go | 2 +- blockchain/notifications_test.go | 2 +- btcjson/chainsvrcmds.go | 2 +- docs/README.md | 48 +++++++++---------- docs/code_contribution_guidelines.md | 6 +-- docs/json_rpc_api.md | 14 +++--- integration/rpctest/README.md | 6 +-- mempool/estimatefee.go | 6 +-- mempool/estimatefee_test.go | 8 ++-- netsync/interface.go | 14 +++--- rpcadapters.go | 14 +++--- rpcclient/README.md | 14 +++--- rpcclient/chain.go | 6 +-- rpcclient/doc.go | 2 +- rpcclient/examples/bitcoincorehttp/README.md | 4 +- rpcclient/examples/bitcoincorehttp/main.go | 2 +- rpcclient/examples/btcdwebsockets/README.md | 4 +- rpcclient/examples/btcdwebsockets/main.go | 6 +-- .../examples/btcwalletwebsockets/README.md | 4 +- .../examples/btcwalletwebsockets/main.go | 4 +- rpcclient/extensions.go | 8 ++-- rpcclient/infrastructure.go | 2 +- rpcclient/mining.go | 6 +-- rpcclient/net.go | 2 +- rpcclient/notify.go | 8 ++-- rpcclient/rawrequest.go | 2 +- rpcclient/rawtransactions.go | 8 ++-- rpcclient/wallet.go | 10 ++-- txscript/hashcache_test.go | 2 +- txscript/script_test.go | 2 +- wire/msgcfcheckpt.go | 2 +- wire/msggetcfcheckpt.go | 2 +- wire/msggetcfilters.go | 2 +- 35 files changed, 126 insertions(+), 126 deletions(-) diff --git a/CHANGES b/CHANGES index b7aabf852d..6f7013e922 100644 --- a/CHANGES +++ b/CHANGES @@ -264,7 +264,7 @@ Changes in 0.10.0 (Sun Mar 01 2015) for version 3 blocks which are compatible with BIP0066 - Allow getblocktemplate to serve blocks when the current time is less than the minimum allowed time for a generated block template - (https://github.com/roasbeef/btcd/issues/209) + (https://github.com/btcsuite/btcd/issues/209) - Crypto changes: - Optimize scalar multiplication by the base point by using a pre-computed table which results in approximately a 35% speedup @@ -279,29 +279,29 @@ Changes in 0.10.0 (Sun Mar 01 2015) - Add a new parameter --addrindex which will enable the creation of an address index which can be queried to determine all transactions which involve a given address - (https://github.com/roasbeef/btcd/issues/190) + (https://github.com/btcsuite/btcd/issues/190) - Add a new logging subsystem for address index related operations - Support new searchrawtransactions RPC - (https://github.com/roasbeef/btcd/issues/185) + (https://github.com/btcsuite/btcd/issues/185) - RPC changes: - Require TLS version 1.2 as the minimum version for all TLS connections - Provide support for disabling TLS when only listening on localhost - (https://github.com/roasbeef/btcd/pull/192) + (https://github.com/btcsuite/btcd/pull/192) - Modify help output for all commands to provide much more consistent and detailed information - Correct case in getrawtransaction which would refuse to serve certain transactions with invalid scripts - (https://github.com/roasbeef/btcd/issues/210) + (https://github.com/btcsuite/btcd/issues/210) - Correct error handling in the getrawtransaction RPC which could lead to a crash in rare cases - (https://github.com/roasbeef/btcd/issues/196) + (https://github.com/btcsuite/btcd/issues/196) - Update getinfo RPC to include the appropriate 'timeoffset' calculated from the median network time - Modify listreceivedbyaddress result type to include txids field so it is compatible - Add 'iswatchonly' field to validateaddress result - Add 'startingpriority' and 'currentpriority' fields to getrawmempool - (https://github.com/roasbeef/btcd/issues/178) + (https://github.com/btcsuite/btcd/issues/178) - Don't omit the 'confirmations' field from getrawtransaction when it is zero - Websocket changes: @@ -317,7 +317,7 @@ Changes in 0.10.0 (Sun Mar 01 2015) dumping all of the commands - Make the usage syntax much more consistent and correct a few cases of misnamed fields - (https://github.com/roasbeef/btcd/issues/305) + (https://github.com/btcsuite/btcd/issues/305) - Improve usage errors to show the specific parameter number, reason, and error code - Only show the usage for specific command is shown when a valid command @@ -336,7 +336,7 @@ Changes in 0.10.0 (Sun Mar 01 2015) - Remove utility in favor of the RPC getblock method - Notable developer-related package changes: - Many of the core packages have been relocated into the btcd repository - (https://github.com/roasbeef/btcd/issues/214) + (https://github.com/btcsuite/btcd/issues/214) - A new version of the btcjson package that has been completely redesigned from the ground up based based upon how the project has evolved and lessons learned while using it since it was first written @@ -353,21 +353,21 @@ Changes in 0.10.0 (Sun Mar 01 2015) and using that data to calculate an offset against the local time - Misc changes: - Fix a slow memory leak due to tickers not being stopped - (https://github.com/roasbeef/btcd/issues/189) + (https://github.com/btcsuite/btcd/issues/189) - Fix an issue where a mix of orphans and SPV clients could trigger a condition where peers would no longer be served - (https://github.com/roasbeef/btcd/issues/231) + (https://github.com/btcsuite/btcd/issues/231) - The RPC username and password can now contain symbols which previously conflicted with special symbols used in URLs - Improve handling of obtaining random nonces to prevent cases where it could error when not enough entropy was available - Improve handling of home directory creation errors such as in the case - of unmounted symlinks (https://github.com/roasbeef/btcd/issues/193) + of unmounted symlinks (https://github.com/btcsuite/btcd/issues/193) - Improve the error reporting for rejected transactions to include the inputs which are missing and/or being double spent - Update sample config file with new options and correct a comment regarding the fact the RPC server only listens on localhost by default - (https://github.com/roasbeef/btcd/issues/218) + (https://github.com/btcsuite/btcd/issues/218) - Update the continuous integration builds to run several tools which help keep code quality high - Significant amount of internal code cleanup and improvements diff --git a/blockchain/chainview_test.go b/blockchain/chainview_test.go index bf49751d08..c59004fdaf 100644 --- a/blockchain/chainview_test.go +++ b/blockchain/chainview_test.go @@ -10,7 +10,7 @@ import ( "reflect" "testing" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcd/wire" ) // testNoncePrng provides a deterministic prng for the nonce in generated fake diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 93d00fff69..552fa953b2 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -14,7 +14,7 @@ import ( "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs" "github.com/btcsuite/btcutil/gcs/builder" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcd/wire" ) const ( diff --git a/blockchain/notifications_test.go b/blockchain/notifications_test.go index 11c60f8bff..fde58735df 100644 --- a/blockchain/notifications_test.go +++ b/blockchain/notifications_test.go @@ -7,7 +7,7 @@ package blockchain import ( "testing" - "github.com/roasbeef/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg" ) // TestNotifications ensures that notification callbacks are fired on events. diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 18933da0b8..a5e5647112 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -11,7 +11,7 @@ import ( "encoding/json" "fmt" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcd/wire" ) // AddNodeSubCmd defines the type used in the addnode JSON-RPC command for the diff --git a/docs/README.md b/docs/README.md index 09350d1842..c00d295e7a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -69,7 +69,7 @@ details on how to install on the supported operating systems. **2.1.1 Windows Installation**
-* Install the MSI available at: https://github.com/roasbeef/btcd/releases +* Install the MSI available at: https://github.com/btcsuite/btcd/releases * Launch btcd from the Start Menu
@@ -96,8 +96,8 @@ recommended that `GOPATH` is set to a directory in your home directory such as ```bash $ go get -u github.com/Masterminds/glide -$ git clone https://github.com/roasbeef/btcd $GOPATH/src/github.com/roasbeef/btcd -$ cd $GOPATH/src/github.com/roasbeef/btcd +$ git clone https://github.com/btcsuite/btcd $GOPATH/src/github.com/btcsuite/btcd +$ cd $GOPATH/src/github.com/btcsuite/btcd $ glide install $ go install . ./cmd/... ``` @@ -111,7 +111,7 @@ $ go install . ./cmd/... - Run the following commands to update btcd, all dependencies, and install it: ```bash -$ cd $GOPATH/src/github.com/roasbeef/btcd +$ cd $GOPATH/src/github.com/btcsuite/btcd $ git pull && glide install $ go install . ./cmd/... ``` @@ -129,7 +129,7 @@ $ go install . ./cmd/... **2.2 Configuration** -btcd has a number of [configuration](http://godoc.org/github.com/roasbeef/btcd) +btcd has a number of [configuration](http://godoc.org/github.com/btcsuite/btcd) options, which can be viewed by running: `$ btcd --help`. @@ -213,16 +213,16 @@ configuration necessary, however, there is an optional method to use a **3.1.1 bootstrap.dat** -* [Using bootstrap.dat](https://github.com/roasbeef/btcd/tree/master/docs/using_bootstrap_dat.md) +* [Using bootstrap.dat](https://github.com/btcsuite/btcd/tree/master/docs/using_bootstrap_dat.md) **3.1.2 Network Configuration** -* [What Ports Are Used by Default?](https://github.com/roasbeef/btcd/tree/master/docs/default_ports.md) -* [How To Listen on Specific Interfaces](https://github.com/roasbeef/btcd/tree/master/docs/configure_peer_server_listen_interfaces.md) -* [How To Configure RPC Server to Listen on Specific Interfaces](https://github.com/roasbeef/btcd/tree/master/docs/configure_rpc_server_listen_interfaces.md) -* [Configuring btcd with Tor](https://github.com/roasbeef/btcd/tree/master/docs/configuring_tor.md) +* [What Ports Are Used by Default?](https://github.com/btcsuite/btcd/tree/master/docs/default_ports.md) +* [How To Listen on Specific Interfaces](https://github.com/btcsuite/btcd/tree/master/docs/configure_peer_server_listen_interfaces.md) +* [How To Configure RPC Server to Listen on Specific Interfaces](https://github.com/btcsuite/btcd/tree/master/docs/configure_rpc_server_listen_interfaces.md) +* [Configuring btcd with Tor](https://github.com/btcsuite/btcd/tree/master/docs/configuring_tor.md) @@ -258,12 +258,12 @@ information. -* [Code Contribution Guidelines](https://github.com/roasbeef/btcd/tree/master/docs/code_contribution_guidelines.md) +* [Code Contribution Guidelines](https://github.com/btcsuite/btcd/tree/master/docs/code_contribution_guidelines.md) -* [JSON-RPC Reference](https://github.com/roasbeef/btcd/tree/master/docs/json_rpc_api.md) - * [RPC Examples](https://github.com/roasbeef/btcd/tree/master/docs/json_rpc_api.md#ExampleCode) +* [JSON-RPC Reference](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md) + * [RPC Examples](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md#ExampleCode) @@ -272,28 +272,28 @@ information. robust and easy to use Websocket-enabled Bitcoin JSON-RPC client * [btcjson](https://github.com/btcsuite/btcd/tree/master/btcjson) - Provides an extensive API for the underlying JSON-RPC command and return values - * [wire](https://github.com/roasbeef/btcd/tree/master/wire) - Implements the + * [wire](https://github.com/btcsuite/btcd/tree/master/wire) - Implements the Bitcoin wire protocol - * [peer](https://github.com/roasbeef/btcd/tree/master/peer) - + * [peer](https://github.com/btcsuite/btcd/tree/master/peer) - Provides a common base for creating and managing Bitcoin network peers. - * [blockchain](https://github.com/roasbeef/btcd/tree/master/blockchain) - + * [blockchain](https://github.com/btcsuite/btcd/tree/master/blockchain) - Implements Bitcoin block handling and chain selection rules - * [blockchain/fullblocktests](https://github.com/roasbeef/btcd/tree/master/blockchain/fullblocktests) - + * [blockchain/fullblocktests](https://github.com/btcsuite/btcd/tree/master/blockchain/fullblocktests) - Provides a set of block tests for testing the consensus validation rules - * [txscript](https://github.com/roasbeef/btcd/tree/master/txscript) - + * [txscript](https://github.com/btcsuite/btcd/tree/master/txscript) - Implements the Bitcoin transaction scripting language - * [btcec](https://github.com/roasbeef/btcd/tree/master/btcec) - Implements + * [btcec](https://github.com/btcsuite/btcd/tree/master/btcec) - Implements support for the elliptic curve cryptographic functions needed for the Bitcoin scripts - * [database](https://github.com/roasbeef/btcd/tree/master/database) - + * [database](https://github.com/btcsuite/btcd/tree/master/database) - Provides a database interface for the Bitcoin block chain - * [mempool](https://github.com/roasbeef/btcd/tree/master/mempool) - + * [mempool](https://github.com/btcsuite/btcd/tree/master/mempool) - Package mempool provides a policy-enforced pool of unmined bitcoin transactions. - * [btcutil](https://github.com/roasbeef/btcutil) - Provides Bitcoin-specific + * [btcutil](https://github.com/btcsuite/btcutil) - Provides Bitcoin-specific convenience functions and types - * [chainhash](https://github.com/roasbeef/btcd/tree/master/chaincfg/chainhash) - + * [chainhash](https://github.com/btcsuite/btcd/tree/master/chaincfg/chainhash) - Provides a generic hash type and associated functions that allows the specific hash algorithm to be abstracted. - * [connmgr](https://github.com/roasbeef/btcd/tree/master/connmgr) - + * [connmgr](https://github.com/btcsuite/btcd/tree/master/connmgr) - Package connmgr implements a generic Bitcoin network connection manager. diff --git a/docs/code_contribution_guidelines.md b/docs/code_contribution_guidelines.md index 29613608f4..b643e911a3 100644 --- a/docs/code_contribution_guidelines.md +++ b/docs/code_contribution_guidelines.md @@ -239,7 +239,7 @@ Further paragraphs come after blank lines. Prefix the summary with the subsystem/package when possible. Many other projects make use of the code and this makes it easier for them to tell when something they're using has changed. Have a look at [past -commits](https://github.com/roasbeef/btcd/commits/master) for examples of +commits](https://github.com/btcsuite/btcd/commits/master) for examples of commit messages. Here are some of the reasons why wrapping your commit messages to 72 columns is @@ -321,7 +321,7 @@ keep a clean commit history over a tangled weave of merge commits. However, regardless of the specific merge method used, the code will be integrated with the master branch and the pull request will be closed. -Rejoice as you will now be listed as a [contributor](https://github.com/roasbeef/btcd/graphs/contributors)! +Rejoice as you will now be listed as a [contributor](https://github.com/btcsuite/btcd/graphs/contributors)! @@ -351,5 +351,5 @@ Rejoice as you will now be listed as a [contributor](https://github.com/roasbeef ### 6.2. Licensing of Contributions All contributions must be licensed with the -[ISC license](https://github.com/roasbeef/btcd/blob/master/LICENSE). This is +[ISC license](https://github.com/btcsuite/btcd/blob/master/LICENSE). This is the same license as all of the code in the btcd suite. diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index 7fc3a23c51..9b8b36b3bb 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -1095,7 +1095,7 @@ package main import ( "github.com/btcsuite/btcrpcclient" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcutil" "io/ioutil" "log" "path/filepath" @@ -1156,9 +1156,9 @@ package main import ( "github.com/btcsuite/btcrpcclient" - "github.com/roasbeef/btcutil" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" "io/ioutil" "log" "path/filepath" @@ -1248,9 +1248,9 @@ package main import ( "github.com/btcsuite/btcrpcclient" - "github.com/roasbeef/btcutil" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" "io/ioutil" "log" "path/filepath" diff --git a/integration/rpctest/README.md b/integration/rpctest/README.md index 26a53ef2b5..fceeed20a0 100644 --- a/integration/rpctest/README.md +++ b/integration/rpctest/README.md @@ -1,9 +1,9 @@ rpctest ======= -[![Build Status](http://img.shields.io/travis/roasbeef/btcd.svg)](https://travis-ci.org/roasbeef/btcd) +[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/roasbeef/btcd/integration/rpctest) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/integration/rpctest) Package rpctest provides a btcd-specific RPC testing harness crafting and executing integration tests by driving a `btcd` instance via the `RPC` @@ -20,7 +20,7 @@ systems/integration tests. ## Installation and Updating ```bash -$ go get -u github.com/roasbeef/btcd/integration/rpctest +$ go get -u github.com/btcsuite/btcd/integration/rpctest ``` ## License diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index ee72524016..53933469b6 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -16,9 +16,9 @@ import ( "strings" "sync" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/mining" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mining" + "github.com/btcsuite/btcutil" ) // TODO incorporate Alex Morcos' modifications to Gavin's initial model diff --git a/mempool/estimatefee_test.go b/mempool/estimatefee_test.go index 071306738e..16dcfadc95 100644 --- a/mempool/estimatefee_test.go +++ b/mempool/estimatefee_test.go @@ -9,10 +9,10 @@ import ( "math/rand" "testing" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/mining" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mining" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) // newTestFeeEstimator creates a feeEstimator with some different parameters diff --git a/netsync/interface.go b/netsync/interface.go index 2e6edce8e3..3e6ca1c12d 100644 --- a/netsync/interface.go +++ b/netsync/interface.go @@ -5,13 +5,13 @@ package netsync import ( - "github.com/roasbeef/btcd/blockchain" - "github.com/roasbeef/btcd/chaincfg" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/mempool" - "github.com/roasbeef/btcd/peer" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mempool" + "github.com/btcsuite/btcd/peer" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) // PeerNotifier exposes methods to notify peers of status changes to diff --git a/rpcadapters.go b/rpcadapters.go index aee62d13e8..7d2c3a14d0 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -7,13 +7,13 @@ package main import ( "sync/atomic" - "github.com/roasbeef/btcd/blockchain" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/mempool" - "github.com/roasbeef/btcd/netsync" - "github.com/roasbeef/btcd/peer" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mempool" + "github.com/btcsuite/btcd/netsync" + "github.com/btcsuite/btcd/peer" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) // rpcPeer provides a peer for use with the RPC server and implements the diff --git a/rpcclient/README.md b/rpcclient/README.md index f53fa76675..b6077d2a82 100644 --- a/rpcclient/README.md +++ b/rpcclient/README.md @@ -1,9 +1,9 @@ rpcclient ========= -[![Build Status](http://img.shields.io/travis/roasbeef/btcd.svg)](https://travis-ci.org/roasbeef/btcd) +[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/roasbeef/btcd/rpcclient) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/rpcclient) rpcclient implements a Websocket-enabled Bitcoin JSON-RPC client package written in [Go](http://golang.org/). It provides a robust and easy to use client for @@ -18,16 +18,16 @@ implement and the API is not stable yet. ## Documentation -* [API Reference](http://godoc.org/github.com/roasbeef/btcd/rpcclient) -* [btcd Websockets Example](https://github.com/roasbeef/btcd/rpcclient/blob/master/examples/btcdwebsockets) +* [API Reference](http://godoc.org/github.com/btcsuite/btcd/rpcclient) +* [btcd Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcdwebsockets) Connects to a btcd RPC server using TLS-secured websockets, registers for block connected and block disconnected notifications, and gets the current block count -* [btcwallet Websockets Example](https://github.com/roasbeef/btcd/rpcclient/blob/master/examples/btcwalletwebsockets) +* [btcwallet Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcwalletwebsockets) Connects to a btcwallet RPC server using TLS-secured websockets, registers for notifications about changes to account balances, and gets a list of unspent transaction outputs (utxos) the wallet can sign -* [Bitcoin Core HTTP POST Example](https://github.com/roasbeef/btcd/rpcclient/blob/master/examples/bitcoincorehttp) +* [Bitcoin Core HTTP POST Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/bitcoincorehttp) Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled and gets the current block count @@ -47,7 +47,7 @@ implement and the API is not stable yet. ## Installation ```bash -$ go get -u github.com/roasbeef/btcd/rpcclient +$ go get -u github.com/btcsuite/btcd/rpcclient ``` ## License diff --git a/rpcclient/chain.go b/rpcclient/chain.go index fd7a781e2d..c21668918d 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -10,9 +10,9 @@ import ( "encoding/hex" "encoding/json" - "github.com/roasbeef/btcd/btcjson" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" ) // FutureGetBestBlockHashResult is a future promise to deliver the result of a diff --git a/rpcclient/doc.go b/rpcclient/doc.go index f52bbc48d0..d4bbb64d65 100644 --- a/rpcclient/doc.go +++ b/rpcclient/doc.go @@ -9,7 +9,7 @@ Overview This client provides a robust and easy to use client for interfacing with a Bitcoin RPC server that uses a btcd/bitcoin core compatible Bitcoin JSON-RPC -API. This client has been tested with btcd (https://github.com/roasbeef/btcd), +API. This client has been tested with btcd (https://github.com/btcsuite/btcd), btcwallet (https://github.com/btcsuite/btcwallet), and bitcoin core (https://github.com/bitcoin). diff --git a/rpcclient/examples/bitcoincorehttp/README.md b/rpcclient/examples/bitcoincorehttp/README.md index b13d09a78a..4d1f0adfe1 100644 --- a/rpcclient/examples/bitcoincorehttp/README.md +++ b/rpcclient/examples/bitcoincorehttp/README.md @@ -10,7 +10,7 @@ block count. The first step is to use `go get` to download and install the rpcclient package: ```bash -$ go get github.com/roasbeef/btcd/rpcclient +$ go get github.com/btcsuite/btcd/rpcclient ``` Next, modify the `main.go` source to specify the correct RPC username and @@ -24,7 +24,7 @@ password for the RPC server: Finally, navigate to the example's directory and run it with: ```bash -$ cd $GOPATH/src/github.com/roasbeef/btcd/rpcclient/examples/bitcoincorehttp +$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/bitcoincorehttp $ go run *.go ``` diff --git a/rpcclient/examples/bitcoincorehttp/main.go b/rpcclient/examples/bitcoincorehttp/main.go index 0afdfab1e7..489770a25b 100644 --- a/rpcclient/examples/bitcoincorehttp/main.go +++ b/rpcclient/examples/bitcoincorehttp/main.go @@ -7,7 +7,7 @@ package main import ( "log" - "github.com/roasbeef/btcd/rpcclient" + "github.com/btcsuite/btcd/rpcclient" ) func main() { diff --git a/rpcclient/examples/btcdwebsockets/README.md b/rpcclient/examples/btcdwebsockets/README.md index 7187865d1d..a168648435 100644 --- a/rpcclient/examples/btcdwebsockets/README.md +++ b/rpcclient/examples/btcdwebsockets/README.md @@ -13,7 +13,7 @@ demonstrate clean shutdown. The first step is to use `go get` to download and install the rpcclient package: ```bash -$ go get github.com/roasbeef/btcd/rpcclient +$ go get github.com/btcsuite/btcd/rpcclient ``` Next, modify the `main.go` source to specify the correct RPC username and @@ -27,7 +27,7 @@ password for the RPC server: Finally, navigate to the example's directory and run it with: ```bash -$ cd $GOPATH/src/github.com/roasbeef/btcd/rpcclient/examples/btcdwebsockets +$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/btcdwebsockets $ go run *.go ``` diff --git a/rpcclient/examples/btcdwebsockets/main.go b/rpcclient/examples/btcdwebsockets/main.go index f554cb45e4..56d12d8274 100644 --- a/rpcclient/examples/btcdwebsockets/main.go +++ b/rpcclient/examples/btcdwebsockets/main.go @@ -10,9 +10,9 @@ import ( "path/filepath" "time" - "github.com/roasbeef/btcd/rpcclient" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) func main() { diff --git a/rpcclient/examples/btcwalletwebsockets/README.md b/rpcclient/examples/btcwalletwebsockets/README.md index bb07bf1579..e495dff80a 100644 --- a/rpcclient/examples/btcwalletwebsockets/README.md +++ b/rpcclient/examples/btcwalletwebsockets/README.md @@ -14,7 +14,7 @@ demonstrate clean shutdown. The first step is to use `go get` to download and install the rpcclient package: ```bash -$ go get github.com/roasbeef/btcd/rpcclient +$ go get github.com/btcsuite/btcd/rpcclient ``` Next, modify the `main.go` source to specify the correct RPC username and @@ -28,7 +28,7 @@ password for the RPC server: Finally, navigate to the example's directory and run it with: ```bash -$ cd $GOPATH/src/github.com/roasbeef/btcd/rpcclient/examples/btcwalletwebsockets +$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/btcwalletwebsockets $ go run *.go ``` diff --git a/rpcclient/examples/btcwalletwebsockets/main.go b/rpcclient/examples/btcwalletwebsockets/main.go index 4d31443d2a..e803138d64 100644 --- a/rpcclient/examples/btcwalletwebsockets/main.go +++ b/rpcclient/examples/btcwalletwebsockets/main.go @@ -10,8 +10,8 @@ import ( "path/filepath" "time" - "github.com/roasbeef/btcd/rpcclient" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" ) diff --git a/rpcclient/extensions.go b/rpcclient/extensions.go index 1ceb16c473..d16cd5252e 100644 --- a/rpcclient/extensions.go +++ b/rpcclient/extensions.go @@ -12,10 +12,10 @@ import ( "encoding/json" "fmt" - "github.com/roasbeef/btcd/btcjson" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) // FutureDebugLevelResult is a future promise to deliver the result of a diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 9c6b790b05..27f7f21f1b 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -23,7 +23,7 @@ import ( "sync/atomic" "time" - "github.com/roasbeef/btcd/btcjson" + "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/go-socks/socks" "github.com/btcsuite/websocket" ) diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 5994f2a8dd..76a9d30580 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -9,9 +9,9 @@ import ( "encoding/json" "errors" - "github.com/roasbeef/btcd/btcjson" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcutil" ) // FutureGenerateResult is a future promise to deliver the result of a diff --git a/rpcclient/net.go b/rpcclient/net.go index 42d882b2cd..aeda8b3c59 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -7,7 +7,7 @@ package rpcclient import ( "encoding/json" - "github.com/roasbeef/btcd/btcjson" + "github.com/btcsuite/btcd/btcjson" ) // AddNodeCommand enumerates the available commands that the AddNode function diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 0b15619455..2454a94696 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -13,10 +13,10 @@ import ( "fmt" "time" - "github.com/roasbeef/btcd/btcjson" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) var ( diff --git a/rpcclient/rawrequest.go b/rpcclient/rawrequest.go index f8a6494fb1..dd16fd049e 100644 --- a/rpcclient/rawrequest.go +++ b/rpcclient/rawrequest.go @@ -8,7 +8,7 @@ import ( "encoding/json" "errors" - "github.com/roasbeef/btcd/btcjson" + "github.com/btcsuite/btcd/btcjson" ) // FutureRawResult is a future promise to deliver the result of a RawRequest RPC diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 605678ccce..e886f2250d 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -9,10 +9,10 @@ import ( "encoding/hex" "encoding/json" - "github.com/roasbeef/btcd/btcjson" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) // SigHashType enumerates the available signature hashing types that the diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 9c7b291d33..10c12f1f70 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -8,11 +8,11 @@ import ( "encoding/json" "strconv" - "github.com/roasbeef/btcd/btcjson" - "github.com/roasbeef/btcd/chaincfg" - "github.com/roasbeef/btcd/chaincfg/chainhash" - "github.com/roasbeef/btcd/wire" - "github.com/roasbeef/btcutil" + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" ) // ***************************** diff --git a/txscript/hashcache_test.go b/txscript/hashcache_test.go index 09814bdfcc..389918e2f2 100644 --- a/txscript/hashcache_test.go +++ b/txscript/hashcache_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" ) diff --git a/txscript/script_test.go b/txscript/script_test.go index 4abf3d786a..6a725e275c 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -9,7 +9,7 @@ import ( "reflect" "testing" - "github.com/roasbeef/btcd/wire" + "github.com/btcsuite/btcd/wire" ) // TestParseOpcode tests for opcode parsing with bad data templates. diff --git a/wire/msgcfcheckpt.go b/wire/msgcfcheckpt.go index 179abe6672..cdf32dd512 100644 --- a/wire/msgcfcheckpt.go +++ b/wire/msgcfcheckpt.go @@ -8,7 +8,7 @@ import ( "fmt" "io" - "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) const ( diff --git a/wire/msggetcfcheckpt.go b/wire/msggetcfcheckpt.go index 12ecce4e21..60ec26526b 100644 --- a/wire/msggetcfcheckpt.go +++ b/wire/msggetcfcheckpt.go @@ -7,7 +7,7 @@ package wire import ( "io" - "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) // MsgGetCFCheckpt is a request for filter headers at evenly spaced intervals diff --git a/wire/msggetcfilters.go b/wire/msggetcfilters.go index 3ea88b390a..7818bf15fc 100644 --- a/wire/msggetcfilters.go +++ b/wire/msggetcfilters.go @@ -7,7 +7,7 @@ package wire import ( "io" - "github.com/roasbeef/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) // MaxGetCFiltersReqRange the maximum number of filters that may be requested in From f48bc4342128169ab01ea6d7fa60192519e3bc54 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 21:03:14 -0700 Subject: [PATCH 0179/1056] build: restore glide.lock --- glide.lock | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 glide.lock diff --git a/glide.lock b/glide.lock new file mode 100644 index 0000000000..2733e9da1c --- /dev/null +++ b/glide.lock @@ -0,0 +1,69 @@ +hash: 976decfaf173d97d2e4572399490637aa12e217312a7d8b28813780a738e1151 +updated: 2018-05-15T21:02:54.227187628-07:00 +imports: +- name: github.com/aead/siphash + version: e404fcfc888570cadd1610538e2dbc89f66af814 +- name: github.com/btcsuite/btclog + version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a +- name: github.com/btcsuite/btcutil + version: b9afb0b9868a757e8fcc3c3adf5b129979f9b3e6 + subpackages: + - base58 + - bech32 + - bloom + - gcs + - gcs/builder + - hdkeychain +- name: github.com/btcsuite/go-socks + version: 4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f + subpackages: + - socks +- name: github.com/btcsuite/goleveldb + version: 7834afc9e8cd15233b6c3d97e12674a31ca24602 + subpackages: + - leveldb + - leveldb/cache + - leveldb/comparer + - leveldb/errors + - leveldb/filter + - leveldb/iterator + - leveldb/journal + - leveldb/memdb + - leveldb/opt + - leveldb/storage + - leveldb/table + - leveldb/util +- name: github.com/btcsuite/snappy-go + version: 0bdef8d067237991ddaa1bb6072a740bc40601ba +- name: github.com/btcsuite/websocket + version: 31079b6807923eb23992c421b114992b95131b55 +- name: github.com/btcsuite/winsvc + version: f8fb11f83f7e860e3769a08e6811d1b399a43722 + subpackages: + - eventlog + - mgr + - registry + - svc + - winapi +- name: github.com/davecgh/go-spew + version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 + subpackages: + - spew +- name: github.com/jessevdk/go-flags + version: 1679536dcc895411a9f5848d9a0250be7856448c +- name: github.com/jrick/logrotate + version: a93b200c26cbae3bb09dd0dc2c7c7fe1468a034a + subpackages: + - rotator +- name: github.com/kkdai/bstream + version: f71540b9dfdcfe64dbf2818e9b66423c6aafcacd +- name: github.com/roasbeef/btcd + version: 9978b939c33973be19b932fa7b936079bb7ba38d + subpackages: + - chaincfg/chainhash + - wire +- name: golang.org/x/crypto + version: 1a580b3eff7814fc9b40602fd35256c63b50f491 + subpackages: + - ripemd160 +testImports: [] From 2b7326ae5259ea84ffbfc253d93e8eab9f208583 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 May 2018 21:08:31 -0700 Subject: [PATCH 0180/1056] blockchain/indexers: use latest API for cf indexing --- blockchain/indexers/cfindex.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 552fa953b2..9cbf1bd50c 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -11,10 +11,10 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/gcs" "github.com/btcsuite/btcutil/gcs/builder" - "github.com/btcsuite/btcd/wire" ) const ( @@ -154,9 +154,9 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, // Start by storing the filter. h := block.Hash() - var basicFilterBytes []byte - if f != nil { - basicFilterBytes = f.NBytes() + filterBytes, err := f.NBytes() + if err != nil { + return err } err = dbStoreFilterIdxEntry(dbTx, fkey, h, filterBytes) if err != nil { @@ -205,7 +205,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { f, err := builder.BuildBasicFilter(block.MsgBlock()) - if err != nil && err != gcs.ErrNoData { + if err != nil { return err } @@ -215,7 +215,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, } f, err = builder.BuildExtFilter(block.MsgBlock()) - if err != nil && err != gcs.ErrNoData { + if err != nil { return err } From 5596b63846edd2ec9237d4e9c666d6982cff29cf Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 18 May 2018 18:55:52 -0700 Subject: [PATCH 0181/1056] multi: fix linter warnings --- mempool/mempool.go | 2 +- peer/peer.go | 5 ++++- rpcserverhelp.go | 6 +++--- wire/msgcfcheckpt.go | 4 +++- wire/msgcfheaders.go | 2 +- wire/msggetcfcheckpt.go | 17 +++-------------- wire/msggetcfheaders.go | 14 ++------------ wire/msggetcfilters.go | 14 ++------------ 8 files changed, 19 insertions(+), 45 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 91dbb6dea5..d4088fc743 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -571,7 +571,7 @@ func (mp *TxPool) checkPoolDoubleSpend(tx *btcutil.Tx) error { return nil } -// CheckSpends checks whether the passed outpoint is already spent by a +// CheckSpend checks whether the passed outpoint is already spent by a // transaction in the mempool. If that's the case the spending transaction will // be returned, if not nil will be returned. func (mp *TxPool) CheckSpend(op wire.OutPoint) *btcutil.Tx { diff --git a/peer/peer.go b/peer/peer.go index 64a6e759e5..9aecab5947 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1286,6 +1286,10 @@ func (p *Peer) maybeAddDeadline(pendingResponses map[string]time.Time, msgCmd st // Expects an inv message. pendingResponses[wire.CmdInv] = deadline + case wire.CmdGetBlocks: + // Expects an inv message. + pendingResponses[wire.CmdInv] = deadline + case wire.CmdGetData: // Expects a block, merkleblock, tx, or notfound message. pendingResponses[wire.CmdBlock] = deadline @@ -1409,7 +1413,6 @@ out: continue } - continue log.Debugf("Peer %s appears to be stalled or "+ "misbehaving, %s timeout -- "+ "disconnecting", p, command) diff --git a/rpcserverhelp.go b/rpcserverhelp.go index c22448e1c0..46d05a4dd0 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -333,9 +333,9 @@ var helpDescsEnUS = map[string]string{ "getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted", // GetCFilterCmd help. - "getcfilter--synopsis": "Returns a block's committed filter given its hash.", - "getcfilter-hash": "The hash of the block", - "getcfilter--result0": "The block's committed filter", + "getcfilter--synopsis": "Returns a block's committed filter given its hash.", + "getcfilter-hash": "The hash of the block", + "getcfilter--result0": "The block's committed filter", // GetConnectionCountCmd help. "getconnectioncount--synopsis": "Returns the number of active connections to other peers.", diff --git a/wire/msgcfcheckpt.go b/wire/msgcfcheckpt.go index cdf32dd512..32f9575e5b 100644 --- a/wire/msgcfcheckpt.go +++ b/wire/msgcfcheckpt.go @@ -12,6 +12,8 @@ import ( ) const ( + // CFCheckptInterval is the gap (in number of blocks) between each + // filter header checkpoint. CFCheckptInterval = 1000 ) @@ -60,7 +62,7 @@ func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) // Create a contiguous slice of hashes to deserialize into in order to // reduce the number of allocations. - msg.FilterHeaders = make([]*chainhash.Hash, count, count) + msg.FilterHeaders = make([]*chainhash.Hash, count) for i := uint64(0); i < count; i++ { var cfh chainhash.Hash err := readElement(r, &cfh) diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index a35728070d..40d30f9b46 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -33,7 +33,7 @@ type MsgCFHeaders struct { FilterHashes []*chainhash.Hash } -// AddCFHeader adds a new committed filter header to the message. +// AddCFHash adds a new filter hash to the message. func (msg *MsgCFHeaders) AddCFHash(hash *chainhash.Hash) error { if len(msg.FilterHashes)+1 > MaxCFHeadersPerMsg { str := fmt.Sprintf("too many block headers in message [max %v]", diff --git a/wire/msggetcfcheckpt.go b/wire/msggetcfcheckpt.go index 60ec26526b..c30a86cecd 100644 --- a/wire/msggetcfcheckpt.go +++ b/wire/msggetcfcheckpt.go @@ -26,12 +26,7 @@ func (msg *MsgGetCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncodin return err } - err = readElement(r, &msg.StopHash) - if err != nil { - return err - } - - return nil + return readElement(r, &msg.StopHash) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -42,12 +37,7 @@ func (msg *MsgGetCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncodin return err } - err = writeElement(w, &msg.StopHash) - if err != nil { - return err - } - - return nil + return writeElement(w, &msg.StopHash) } // Command returns the protocol command string for the message. This is part @@ -66,8 +56,7 @@ func (msg *MsgGetCFCheckpt) MaxPayloadLength(pver uint32) uint32 { // NewMsgGetCFCheckpt returns a new bitcoin getcfcheckpt message that conforms // to the Message interface using the passed parameters and defaults for the // remaining fields. -func NewMsgGetCFCheckpt(filterType FilterType, stopHash *chainhash.Hash, -) *MsgGetCFCheckpt { +func NewMsgGetCFCheckpt(filterType FilterType, stopHash *chainhash.Hash) *MsgGetCFCheckpt { return &MsgGetCFCheckpt{ FilterType: filterType, StopHash: *stopHash, diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index d792864362..03a1caf72f 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -32,12 +32,7 @@ func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncodin return err } - err = readElement(r, &msg.StopHash) - if err != nil { - return err - } - - return nil + return readElement(r, &msg.StopHash) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -53,12 +48,7 @@ func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncodin return err } - err = writeElement(w, &msg.StopHash) - if err != nil { - return err - } - - return nil + return writeElement(w, &msg.StopHash) } // Command returns the protocol command string for the message. This is part diff --git a/wire/msggetcfilters.go b/wire/msggetcfilters.go index 7818bf15fc..8002413826 100644 --- a/wire/msggetcfilters.go +++ b/wire/msggetcfilters.go @@ -36,12 +36,7 @@ func (msg *MsgGetCFilters) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding return err } - err = readElement(r, &msg.StopHash) - if err != nil { - return err - } - - return nil + return readElement(r, &msg.StopHash) } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -57,12 +52,7 @@ func (msg *MsgGetCFilters) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding return err } - err = writeElement(w, &msg.StopHash) - if err != nil { - return err - } - - return nil + return writeElement(w, &msg.StopHash) } // Command returns the protocol command string for the message. This is part From 4cb1c950e0e5b6656eb991241b29867e5fd14937 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 18 May 2018 19:17:54 -0700 Subject: [PATCH 0182/1056] rpc: add help for new gcs commands --- rpcserverhelp.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 46d05a4dd0..489e9a871f 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -333,9 +333,16 @@ var helpDescsEnUS = map[string]string{ "getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted", // GetCFilterCmd help. - "getcfilter--synopsis": "Returns a block's committed filter given its hash.", - "getcfilter-hash": "The hash of the block", - "getcfilter--result0": "The block's committed filter", + "getcfilter--synopsis": "Returns a block's committed filter given its hash.", + "getcfilter-filtertype": "The type of filter to return (0=regular, 1=extended)", + "getcfilter-hash": "The hash of the block", + "getcfilter--result0": "The block's committed filter", + + // GetCFilterHeaderCmd help. + "getcfilterheader--synopsis": "Returns a block's compact filter header given its hash.", + "getcfilterheader-filtertype": "The type of filter header to return (0=regular, 1=extended)", + "getcfilterheader-hash": "The hash of the block", + "getcfilterheader--result0": "The block's gcs filter header", // GetConnectionCountCmd help. "getconnectioncount--synopsis": "Returns the number of active connections to other peers.", @@ -684,6 +691,7 @@ var rpcResultTypes = map[string][]interface{}{ "getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil}, "getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)}, "getcfilter": {(*string)(nil)}, + "getcfilterheader": {(*string)(nil)}, "getconnectioncount": {(*int32)(nil)}, "getcurrentnet": {(*uint32)(nil)}, "getdifficulty": {(*float64)(nil)}, From d52471044ab259b656083399c4304ce6672308fd Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 22 May 2018 17:51:09 -0700 Subject: [PATCH 0183/1056] build: update glide to point to latest btcutil --- glide.lock | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/glide.lock b/glide.lock index 2733e9da1c..bcc6967077 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,12 @@ hash: 976decfaf173d97d2e4572399490637aa12e217312a7d8b28813780a738e1151 -updated: 2018-05-15T21:02:54.227187628-07:00 +updated: 2018-05-22T17:49:05.731817524-07:00 imports: - name: github.com/aead/siphash version: e404fcfc888570cadd1610538e2dbc89f66af814 - name: github.com/btcsuite/btclog version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a - name: github.com/btcsuite/btcutil - version: b9afb0b9868a757e8fcc3c3adf5b129979f9b3e6 + version: 45edb4b6e59ef7890c7f4be92da61d5ebfa50b65 subpackages: - base58 - bech32 @@ -57,11 +57,6 @@ imports: - rotator - name: github.com/kkdai/bstream version: f71540b9dfdcfe64dbf2818e9b66423c6aafcacd -- name: github.com/roasbeef/btcd - version: 9978b939c33973be19b932fa7b936079bb7ba38d - subpackages: - - chaincfg/chainhash - - wire - name: golang.org/x/crypto version: 1a580b3eff7814fc9b40602fd35256c63b50f491 subpackages: From bc0944904505aab55e089371a892be2f87883161 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 23 May 2018 20:47:11 -0700 Subject: [PATCH 0184/1056] glide: update btcutil deps --- glide.lock | 12 ++++++------ glide.yaml | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/glide.lock b/glide.lock index bcc6967077..fb1bf674db 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,12 @@ -hash: 976decfaf173d97d2e4572399490637aa12e217312a7d8b28813780a738e1151 -updated: 2018-05-22T17:49:05.731817524-07:00 +hash: c8cc08c3afbedc99feda4fed38a64bb1aa42da128520dcac028cfc7e7de06a6e +updated: 2018-05-23T20:46:41.891755246-07:00 imports: - name: github.com/aead/siphash version: e404fcfc888570cadd1610538e2dbc89f66af814 - name: github.com/btcsuite/btclog version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a - name: github.com/btcsuite/btcutil - version: 45edb4b6e59ef7890c7f4be92da61d5ebfa50b65 + version: d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4 subpackages: - base58 - bech32 @@ -46,7 +46,7 @@ imports: - svc - winapi - name: github.com/davecgh/go-spew - version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 + version: ecdeabc65495df2dec95d7c4a4c3e021903035e5 subpackages: - spew - name: github.com/jessevdk/go-flags @@ -56,9 +56,9 @@ imports: subpackages: - rotator - name: github.com/kkdai/bstream - version: f71540b9dfdcfe64dbf2818e9b66423c6aafcacd + version: f391b8402d23024e7c0f624b31267a89998fca95 - name: golang.org/x/crypto - version: 1a580b3eff7814fc9b40602fd35256c63b50f491 + version: 9419663f5a44be8b34ca85f08abc5fe1be11f8a3 subpackages: - ripemd160 testImports: [] diff --git a/glide.yaml b/glide.yaml index f42ad7035d..59dd550e44 100644 --- a/glide.yaml +++ b/glide.yaml @@ -2,6 +2,7 @@ package: github.com/btcsuite/btcd import: - package: github.com/btcsuite/btclog - package: github.com/btcsuite/btcutil + version: d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4 subpackages: - bloom - hdkeychain From a59ac5b18f028fabbd0f537094c995702a942dd3 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sun, 3 Sep 2017 02:59:15 -0500 Subject: [PATCH 0185/1056] multi: Rework utxoset/view to use outpoints. This modifies the utxoset in the database and related UtxoViewpoint to store and work with unspent transaction outputs on a per-output basis instead of at a transaction level. This was inspired by similar recent changes in Bitcoin Core. The primary motivation is to simplify the code, pave the way for a utxo cache, and generally focus on optimizing runtime performance. The tradeoff is that this approach does somewhat increase the size of the serialized utxoset since it means that the transaction hash is duplicated for each output as a part of the key and some additional details such as whether the containing transaction is a coinbase and the block height it was a part of are duplicated in each output. However, in practice, the size difference isn't all that large, disk space is relatively cheap, certainly cheaper than memory, and it is much more important to provide more efficient runtime operation since that is the ultimate purpose of the daemon. While performing this conversion, it also simplifies the code to remove the transaction version information from the utxoset as well as the spend journal. The logic for only serializing it under certain circumstances is complicated and it isn't actually used anywhere aside from the gettxout RPC where it also isn't used by anything important either. Consequently, this also removes the version field of the gettxout RPC result. The utxos in the database are automatically migrated to the new format with this commit and it is possible to interrupt and resume the migration process. Finally, it also updates the tests for the new format and adds a new function to the tests to convert the old test data to the new format for convenience. The data has already been converted and updated in the commit. An overview of the changes are as follows: - Remove transaction version from both spent and unspent output entries - Update utxo serialization format to exclude the version - Modify the spend journal serialization format - The old version field is now reserved and always stores zero and ignores it when reading - This allows old entries to be used by new code without having to migrate the entire spend journal - Remove version field from gettxout RPC result - Convert UtxoEntry to represent a specific utxo instead of a transaction with all remaining utxos - Optimize for memory usage with an eye towards a utxo cache - Combine details such as whether the txout was contained in a coinbase, is spent, and is modified into a single packed field of bit flags - Align entry fields to eliminate extra padding since ultimately there will be a lot of these in memory - Introduce a free list for serializing an outpoint to the database key format to significantly reduce pressure on the GC - Update all related functions that previously dealt with transaction hashes to accept outpoints instead - Update all callers accordingly - Only add individually requested outputs from the mempool when constructing a mempool view - Modify the spend journal to always store the block height and coinbase information with every spent txout - Introduce code to handle fetching the missing information from another utxo from the same transaction in the event an old style entry is encountered - Make use of a database cursor with seek to do this much more efficiently than testing every possible output - Always decompress data loaded from the database now that a utxo entry only consists of a specific output - Introduce upgrade code to migrate the utxo set to the new format - Store versions of the utxoset and spend journal buckets - Allow migration process to be interrupted and resumed - Update all tests to expect the correct encodings, remove tests that no longer apply, and add new ones for the new expected behavior - Convert old tests for the legacy utxo format deserialization code to test the new function that is used during upgrade - Update the utxostore test data and add function that was used to convert it - Introduce a few new functions on UtxoViewpoint - AddTxOut for adding an individual txout versus all of them - addTxOut to handle the common code between the new AddTxOut and existing AddTxOuts - RemoveEntry for removing an individual txout - fetchEntryByHash for fetching any remaining utxo for a given transaction hash --- blockchain/chain.go | 14 +- blockchain/chainio.go | 703 ++++++++++------------- blockchain/chainio_test.go | 469 +++------------ blockchain/common_test.go | 101 +++- blockchain/compress.go | 61 +- blockchain/compress_test.go | 110 ++-- blockchain/indexers/addrindex.go | 11 +- blockchain/scriptval.go | 42 +- blockchain/testdata/277647.utxostore.bz2 | Bin 36632 -> 36845 bytes blockchain/upgrade.go | 398 +++++++++++++ blockchain/upgrade_test.go | 116 ++++ blockchain/utxoviewpoint.go | 622 ++++++++++---------- blockchain/validate.go | 52 +- blockchain/weight.go | 26 +- btcjson/chainsvrresults.go | 1 - mempool/mempool.go | 42 +- mempool/mempool_test.go | 21 +- mempool/policy.go | 5 +- mining/mining.go | 21 +- mining/policy.go | 10 +- netsync/manager.go | 24 +- rpcserver.go | 13 +- wire/msgtx.go | 6 +- 23 files changed, 1519 insertions(+), 1349 deletions(-) create mode 100644 blockchain/upgrade_test.go diff --git a/blockchain/chain.go b/blockchain/chain.go index cd2338359f..b5a8ea54e0 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -399,7 +399,7 @@ func (b *BlockChain) calcSequenceLock(node *blockNode, tx *btcutil.Tx, utxoView nextHeight := node.height + 1 for txInIndex, txIn := range mTx.TxIn { - utxo := utxoView.LookupEntry(&txIn.PreviousOutPoint.Hash) + utxo := utxoView.LookupEntry(txIn.PreviousOutPoint) if utxo == nil { str := fmt.Sprintf("output %v referenced from "+ "transaction %s:%d either does not exist or "+ @@ -848,7 +848,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // journal. var stxos []spentTxOut err = b.db.View(func(dbTx database.Tx) error { - stxos, err = dbFetchSpendJournalEntry(dbTx, block, view) + stxos, err = dbFetchSpendJournalEntry(dbTx, block) return err }) if err != nil { @@ -859,7 +859,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error detachBlocks = append(detachBlocks, block) detachSpentTxOuts = append(detachSpentTxOuts, stxos) - err = view.disconnectTransactions(block, stxos) + err = view.disconnectTransactions(b.db, block, stxos) if err != nil { return err } @@ -961,7 +961,8 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Update the view to unspend all of the spent txos and remove // the utxos created by the block. - err = view.disconnectTransactions(block, detachSpentTxOuts[i]) + err = view.disconnectTransactions(b.db, block, + detachSpentTxOuts[i]) if err != nil { return err } @@ -1702,6 +1703,11 @@ func New(config *Config) (*BlockChain, error) { return nil, err } + // Perform any upgrades to the various chain-specific buckets as needed. + if err := b.maybeUpgradeDbBuckets(config.Interrupt); err != nil { + return nil, err + } + // Initialize and catch up all of the currently active optional indexes // as needed. if config.IndexManager != nil { diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 3b0e258418..27b702deaa 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -9,7 +9,7 @@ import ( "encoding/binary" "fmt" "math/big" - "sort" + "sync" "time" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -23,6 +23,15 @@ const ( // constant from wire and is only provided here for convenience since // wire.MaxBlockHeaderPayload is quite long. blockHdrSize = wire.MaxBlockHeaderPayload + + // latestUtxoSetBucketVersion is the current version of the utxo set + // bucket that is used to track all unspent outputs. + latestUtxoSetBucketVersion = 2 + + // latestSpendJournalBucketVersion is the current version of the spend + // journal bucket that is used to track all spent transactions for use + // in reorgs. + latestSpendJournalBucketVersion = 1 ) var ( @@ -42,13 +51,21 @@ var ( // chain state. chainStateKeyName = []byte("chainstate") + // spendJournalVersionKeyName is the name of the db key used to store + // the version of the spend journal currently in the database. + spendJournalVersionKeyName = []byte("spendjournalversion") + // spendJournalBucketName is the name of the db bucket used to house // transactions outputs that are spent in each block. spendJournalBucketName = []byte("spendjournal") + // utxoSetVersionKeyName is the name of the db key used to store the + // version of the utxo set currently in the database. + utxoSetVersionKeyName = []byte("utxosetversion") + // utxoSetBucketName is the name of the db bucket used to house the // unspent transaction output set. - utxoSetBucketName = []byte("utxoset") + utxoSetBucketName = []byte("utxosetv2") // byteOrder is the preferred byte order used for serializing numeric // fields for storage in the database. @@ -94,6 +111,45 @@ func isDbBucketNotFoundErr(err error) bool { return ok && dbErr.ErrorCode == database.ErrBucketNotFound } +// dbFetchVersion fetches an individual version with the given key from the +// metadata bucket. It is primarily used to track versions on entities such as +// buckets. It returns zero if the provided key does not exist. +func dbFetchVersion(dbTx database.Tx, key []byte) uint32 { + serialized := dbTx.Metadata().Get(key) + if serialized == nil { + return 0 + } + + return byteOrder.Uint32(serialized[:]) +} + +// dbPutVersion uses an existing database transaction to update the provided +// key in the metadata bucket to the given version. It is primarily used to +// track versions on entities such as buckets. +func dbPutVersion(dbTx database.Tx, key []byte, version uint32) error { + var serialized [4]byte + byteOrder.PutUint32(serialized[:], version) + return dbTx.Metadata().Put(key, serialized[:]) +} + +// dbFetchOrCreateVersion uses an existing database transaction to attempt to +// fetch the provided key from the metadata bucket as a version and in the case +// it doesn't exist, it adds the entry with the provided default version and +// returns that. This is useful during upgrades to automatically handle loading +// and adding version keys as necessary. +func dbFetchOrCreateVersion(dbTx database.Tx, key []byte, defaultVersion uint32) (uint32, error) { + version := dbFetchVersion(dbTx, key) + if version == 0 { + version = defaultVersion + err := dbPutVersion(dbTx, key, version) + if err != nil { + return 0, err + } + } + + return version, nil +} + // ----------------------------------------------------------------------------- // The transaction spend journal consists of an entry for each block connected // to the main chain which contains the transaction outputs the block spends @@ -110,18 +166,23 @@ func isDbBucketNotFoundErr(err error) bool { // // NOTE: This format is NOT self describing. The additional details such as // the number of entries (transaction inputs) are expected to come from the -// block itself and the utxo set. The rationale in doing this is to save a -// significant amount of space. This is also the reason the spent outputs are -// serialized in the reverse order they are spent because later transactions -// are allowed to spend outputs from earlier ones in the same block. +// block itself and the utxo set (for legacy entries). The rationale in doing +// this is to save space. This is also the reason the spent outputs are +// serialized in the reverse order they are spent because later transactions are +// allowed to spend outputs from earlier ones in the same block. +// +// The reserved field below used to keep track of the version of the containing +// transaction when the height in the header code was non-zero, however the +// height is always non-zero now, but keeping the extra reserved field allows +// backwards compatibility. // // The serialized format is: // -// [
],... +// [
],... // // Field Type Size // header code VLQ variable -// version VLQ variable +// reserved byte 1 // compressed txout // compressed amount VLQ variable // compressed script []byte variable @@ -130,23 +191,17 @@ func isDbBucketNotFoundErr(err error) bool { // bit 0 - containing transaction is a coinbase // bits 1-x - height of the block that contains the spent txout // -// NOTE: The header code and version are only encoded when the spent txout was -// the final unspent output of the containing transaction. Otherwise, the -// header code will be 0 and the version is not serialized at all. This is -// done because that information is only needed when the utxo set no longer -// has it. -// // Example 1: // From block 170 in main blockchain. // -// 1301320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c +// 1300320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c // <><><------------------------------------------------------------------> // | | | -// | version compressed txout +// | reserved compressed txout // header code // // - header code: 0x13 (coinbase, height 9) -// - transaction version: 1 +// - reserved: 0x00 // - compressed txout 0: // - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) // - 0x05: special script type pay-to-pubkey @@ -155,22 +210,22 @@ func isDbBucketNotFoundErr(err error) bool { // Example 2: // Adapted from block 100025 in main blockchain. // -// 0091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e868b99700186c64700b2fb57eadf61e106a100a7445a8c3f67898841ec -// <><----------------------------------------------><----><><----------------------------------------------> -// | | | | | -// | compressed txout | version compressed txout -// header code header code +// 8b99700091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e868b99700086c64700b2fb57eadf61e106a100a7445a8c3f67898841ec +// <----><><----------------------------------------------><----><><----------------------------------------------> +// | | | | | | +// | reserved compressed txout | reserved compressed txout +// header code header code // // - Last spent output: -// - header code: 0x00 (was not the final unspent output for containing tx) -// - transaction version: Nothing since header code is 0 +// - header code: 0x8b9970 (not coinbase, height 100024) +// - reserved: 0x00 // - compressed txout: // - 0x91f20f: VLQ-encoded compressed amount for 34405000000 (344.05 BTC) // - 0x00: special script type pay-to-pubkey-hash // - 0x6e...86: pubkey hash // - Second to last spent output: // - header code: 0x8b9970 (not coinbase, height 100024) -// - transaction version: 1 +// - reserved: 0x00 // - compressed txout: // - 0x86c647: VLQ-encoded compressed amount for 13761000000 (137.61 BTC) // - 0x00: special script type pay-to-pubkey-hash @@ -185,25 +240,15 @@ func isDbBucketNotFoundErr(err error) bool { // when this spent txout is spending the last unspent output of the containing // transaction. type spentTxOut struct { - compressed bool // The amount and public key script are compressed. - version int32 // The version of creating tx. amount int64 // The amount of the output. pkScript []byte // The public key script for the output. - - // These fields are only set when this is spending the final output of - // the creating tx. - height int32 // Height of the the block containing the creating tx. - isCoinBase bool // Whether creating tx is a coinbase. + height int32 // Height of the the block containing the creating tx. + isCoinBase bool // Whether creating tx is a coinbase. } // spentTxOutHeaderCode returns the calculated header code to be used when // serializing the provided stxo entry. func spentTxOutHeaderCode(stxo *spentTxOut) uint64 { - // The header code is 0 when there is no height set for the stxo. - if stxo.height == 0 { - return 0 - } - // As described in the serialization format comments, the header code // encodes the height shifted over one bit and the coinbase flag in the // lowest bit. @@ -218,13 +263,14 @@ func spentTxOutHeaderCode(stxo *spentTxOut) uint64 { // spentTxOutSerializeSize returns the number of bytes it would take to // serialize the passed stxo according to the format described above. func spentTxOutSerializeSize(stxo *spentTxOut) int { - headerCode := spentTxOutHeaderCode(stxo) - size := serializeSizeVLQ(headerCode) - if headerCode != 0 { - size += serializeSizeVLQ(uint64(stxo.version)) + size := serializeSizeVLQ(spentTxOutHeaderCode(stxo)) + if stxo.height > 0 { + // The legacy v1 spend journal format conditionally tracked the + // containing transaction version when the height was non-zero, + // so this is required for backwards compat. + size += serializeSizeVLQ(0) } - return size + compressedTxOutSize(uint64(stxo.amount), stxo.pkScript, - stxo.version, stxo.compressed) + return size + compressedTxOutSize(uint64(stxo.amount), stxo.pkScript) } // putSpentTxOut serializes the passed stxo according to the format described @@ -234,26 +280,20 @@ func spentTxOutSerializeSize(stxo *spentTxOut) int { func putSpentTxOut(target []byte, stxo *spentTxOut) int { headerCode := spentTxOutHeaderCode(stxo) offset := putVLQ(target, headerCode) - if headerCode != 0 { - offset += putVLQ(target[offset:], uint64(stxo.version)) + if stxo.height > 0 { + // The legacy v1 spend journal format conditionally tracked the + // containing transaction version when the height was non-zero, + // so this is required for backwards compat. + offset += putVLQ(target[offset:], 0) } return offset + putCompressedTxOut(target[offset:], uint64(stxo.amount), - stxo.pkScript, stxo.version, stxo.compressed) + stxo.pkScript) } // decodeSpentTxOut decodes the passed serialized stxo entry, possibly followed // by other data, into the passed stxo struct. It returns the number of bytes // read. -// -// Since the serialized stxo entry does not contain the height, version, or -// coinbase flag of the containing transaction when it still has utxos, the -// caller is responsible for passing in the containing transaction version in -// that case. The provided version is ignore when it is serialized as a part of -// the stxo. -// -// An error will be returned if the version is not serialized as a part of the -// stxo and is also not provided to the function. -func decodeSpentTxOut(serialized []byte, stxo *spentTxOut, txVersion int32) (int, error) { +func decodeSpentTxOut(serialized []byte, stxo *spentTxOut) (int, error) { // Ensure there are bytes to decode. if len(serialized) == 0 { return 0, errDeserialize("no serialized bytes") @@ -266,47 +306,34 @@ func decodeSpentTxOut(serialized []byte, stxo *spentTxOut, txVersion int32) (int "header code") } - // Decode the header code and deserialize the containing transaction - // version if needed. + // Decode the header code. // // Bit 0 indicates containing transaction is a coinbase. // Bits 1-x encode height of containing transaction. - if code != 0 { - version, bytesRead := deserializeVLQ(serialized[offset:]) + stxo.isCoinBase = code&0x01 != 0 + stxo.height = int32(code >> 1) + if stxo.height > 0 { + // The legacy v1 spend journal format conditionally tracked the + // containing transaction version when the height was non-zero, + // so this is required for backwards compat. + _, bytesRead := deserializeVLQ(serialized[offset:]) offset += bytesRead if offset >= len(serialized) { return offset, errDeserialize("unexpected end of data " + - "after version") - } - - stxo.isCoinBase = code&0x01 != 0 - stxo.height = int32(code >> 1) - stxo.version = int32(version) - } else { - // Ensure a tx version was specified if the stxo did not encode - // it. This should never happen unless there is database - // corruption or this function is being called without the - // proper state. - if txVersion == -1 { - return offset, AssertError("decodeSpentTxOut called " + - "without a containing tx version when the " + - "serialized stxo that does not encode the " + - "version") + "after reserved") } - stxo.version = txVersion } // Decode the compressed txout. - compAmount, compScript, bytesRead, err := decodeCompressedTxOut( - serialized[offset:], stxo.version) + amount, pkScript, bytesRead, err := decodeCompressedTxOut( + serialized[offset:]) offset += bytesRead if err != nil { return offset, errDeserialize(fmt.Sprintf("unable to decode "+ "txout: %v", err)) } - stxo.amount = int64(compAmount) - stxo.pkScript = compScript - stxo.compressed = true + stxo.amount = int64(amount) + stxo.pkScript = pkScript return offset, nil } @@ -315,9 +342,8 @@ func decodeSpentTxOut(serialized []byte, stxo *spentTxOut, txVersion int32) (int // // Since the serialization format is not self describing, as noted in the // format comments, this function also requires the transactions that spend the -// txouts and a utxo view that contains any remaining existing utxos in the -// transactions referenced by the inputs to the passed transasctions. -func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx, view *UtxoViewpoint) ([]spentTxOut, error) { +// txouts. +func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx) ([]spentTxOut, error) { // Calculate the total number of stxos. var numStxos int for _, tx := range txns { @@ -341,7 +367,6 @@ func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx, view *U // Loop backwards through all transactions so everything is read in // reverse order to match the serialization order. stxoIdx := numStxos - 1 - stxoInFlight := make(map[chainhash.Hash]int) offset := 0 stxos := make([]spentTxOut, numStxos) for txIdx := len(txns) - 1; txIdx > -1; txIdx-- { @@ -354,36 +379,7 @@ func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx, view *U stxo := &stxos[stxoIdx] stxoIdx-- - // Get the transaction version for the stxo based on - // whether or not it should be serialized as a part of - // the stxo. Recall that it is only serialized when the - // stxo spends the final utxo of a transaction. Since - // they are deserialized in reverse order, this means - // the first time an entry for a given containing tx is - // encountered that is not already in the utxo view it - // must have been the final spend and thus the extra - // data will be serialized with the stxo. Otherwise, - // the version must be pulled from the utxo entry. - // - // Since the view is not actually modified as the stxos - // are read here and it's possible later entries - // reference earlier ones, an inflight map is maintained - // to detect this case and pull the tx version from the - // entry that contains the version information as just - // described. - txVersion := int32(-1) - originHash := &txIn.PreviousOutPoint.Hash - entry := view.LookupEntry(originHash) - if entry != nil { - txVersion = entry.Version() - } else if idx, ok := stxoInFlight[*originHash]; ok { - txVersion = stxos[idx].version - } else { - stxoInFlight[*originHash] = stxoIdx + 1 - } - - n, err := decodeSpentTxOut(serialized[offset:], stxo, - txVersion) + n, err := decodeSpentTxOut(serialized[offset:], stxo) offset += n if err != nil { return nil, errDeserialize(fmt.Sprintf("unable "+ @@ -420,17 +416,18 @@ func serializeSpendJournalEntry(stxos []spentTxOut) []byte { return serialized } -// dbFetchSpendJournalEntry fetches the spend journal entry for the passed -// block and deserializes it into a slice of spent txout entries. The provided -// view MUST have the utxos referenced by all of the transactions available for -// the passed block since that information is required to reconstruct the spent -// txouts. -func dbFetchSpendJournalEntry(dbTx database.Tx, block *btcutil.Block, view *UtxoViewpoint) ([]spentTxOut, error) { +// dbFetchSpendJournalEntry fetches the spend journal entry for the passed block +// and deserializes it into a slice of spent txout entries. +// +// NOTE: Legacy entries will not have the coinbase flag or height set unless it +// was the final output spend in the containing transaction. It is up to the +// caller to handle this properly by looking the information up in the utxo set. +func dbFetchSpendJournalEntry(dbTx database.Tx, block *btcutil.Block) ([]spentTxOut, error) { // Exclude the coinbase transaction since it can't spend anything. spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) serialized := spendBucket.Get(block.Hash()[:]) blockTxns := block.MsgBlock().Transactions[1:] - stxos, err := deserializeSpendJournalEntry(serialized, blockTxns, view) + stxos, err := deserializeSpendJournalEntry(serialized, blockTxns) if err != nil { // Ensure any deserialization errors are returned as database // corruption errors. @@ -468,219 +465,161 @@ func dbRemoveSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash) erro // ----------------------------------------------------------------------------- // The unspent transaction output (utxo) set consists of an entry for each -// transaction which contains a utxo serialized using a format that is highly -// optimized to reduce space using domain specific compression algorithms. This -// format is a slightly modified version of the format used in Bitcoin Core. +// unspent output using a format that is optimized to reduce space using domain +// specific compression algorithms. This format is a slightly modified version +// of the format used in Bitcoin Core. // -// The serialized format is: +// Each entry is keyed by an outpoint as specified below. It is important to +// note that the key encoding uses a VLQ, which employs an MSB encoding so +// iteration of utxos when doing byte-wise comparisons will produce them in +// order. +// +// The serialized key format is: +// // -//
[,...] +// Field Type Size +// hash chainhash.Hash chainhash.HashSize +// output index VLQ variable +// +// The serialized value format is: +// +//
// // Field Type Size -// version VLQ variable -// block height VLQ variable // header code VLQ variable -// unspentness bitmap []byte variable -// compressed txouts +// compressed txout // compressed amount VLQ variable // compressed script []byte variable // // The serialized header code format is: // bit 0 - containing transaction is a coinbase -// bit 1 - output zero is unspent -// bit 2 - output one is unspent -// bits 3-x - number of bytes in unspentness bitmap. When both bits 1 and 2 -// are unset, it encodes N-1 since there must be at least one unspent -// output. -// -// The rationale for the header code scheme is as follows: -// - Transactions which only pay to a single output and a change output are -// extremely common, thus an extra byte for the unspentness bitmap can be -// avoided for them by encoding those two outputs in the low order bits. -// - Given it is encoded as a VLQ which can encode values up to 127 with a -// single byte, that leaves 4 bits to represent the number of bytes in the -// unspentness bitmap while still only consuming a single byte for the -// header code. In other words, an unspentness bitmap with up to 120 -// transaction outputs can be encoded with a single-byte header code. -// This covers the vast majority of transactions. -// - Encoding N-1 bytes when both bits 1 and 2 are unset allows an additional -// 8 outpoints to be encoded before causing the header code to require an -// additional byte. +// bits 1-x - height of the block that contains the unspent txout // // Example 1: // From tx in main blockchain: -// Blk 1, 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 +// Blk 1, 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098:0 // -// 010103320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52 -// <><><><------------------------------------------------------------------> -// | | \--------\ | -// | height | compressed txout 0 -// version header code +// 03320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52 +// <><------------------------------------------------------------------> +// | | +// header code compressed txout // -// - version: 1 -// - height: 1 -// - header code: 0x03 (coinbase, output zero unspent, 0 bytes of unspentness) -// - unspentness: Nothing since it is zero bytes -// - compressed txout 0: +// - header code: 0x03 (coinbase, height 1) +// - compressed txout: // - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) // - 0x04: special script type pay-to-pubkey // - 0x96...52: x-coordinate of the pubkey // // Example 2: // From tx in main blockchain: -// Blk 113931, 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f +// Blk 113931, 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f:2 // -// 0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58 -// <><----><><><------------------------------------------><--------------------------------------------> -// | | | \-------------------\ | | -// version | \--------\ unspentness | compressed txout 2 -// height header code compressed txout 0 +// 8cf316800900b8025be1b3efc63b0ad48e7f9f10e87544528d58 +// <----><------------------------------------------> +// | | +// header code compressed txout // -// - version: 1 -// - height: 113931 -// - header code: 0x0a (output zero unspent, 1 byte in unspentness bitmap) -// - unspentness: [0x01] (bit 0 is set, so output 0+2 = 2 is unspent) -// NOTE: It's +2 since the first two outputs are encoded in the header code -// - compressed txout 0: -// - 0x12: VLQ-encoded compressed amount for 20000000 (0.2 BTC) -// - 0x00: special script type pay-to-pubkey-hash -// - 0xe2...8a: pubkey hash -// - compressed txout 2: +// - header code: 0x8cf316 (not coinbase, height 113931) +// - compressed txout: // - 0x8009: VLQ-encoded compressed amount for 15000000 (0.15 BTC) // - 0x00: special script type pay-to-pubkey-hash // - 0xb8...58: pubkey hash // // Example 3: // From tx in main blockchain: -// Blk 338156, 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620 +// Blk 338156, 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620:22 // -// 0193d06c100000108ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6 -// <><----><><----><--------------------------------------------------> -// | | | \-----------------\ | -// version | \--------\ unspentness | -// height header code compressed txout 22 +// a8a2588ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6 +// <----><--------------------------------------------------> +// | | +// header code compressed txout // -// - version: 1 -// - height: 338156 -// - header code: 0x10 (2+1 = 3 bytes in unspentness bitmap) -// NOTE: It's +1 since neither bit 1 nor 2 are set, so N-1 is encoded. -// - unspentness: [0x00 0x00 0x10] (bit 20 is set, so output 20+2 = 22 is unspent) -// NOTE: It's +2 since the first two outputs are encoded in the header code -// - compressed txout 22: +// - header code: 0xa8a258 (not coinbase, height 338156) +// - compressed txout: // - 0x8ba5b9e763: VLQ-encoded compressed amount for 366875659 (3.66875659 BTC) // - 0x01: special script type pay-to-script-hash // - 0x1d...e6: script hash // ----------------------------------------------------------------------------- +// maxUint32VLQSerializeSize is the maximum number of bytes a max uint32 takes +// to serialize as a VLQ. +var maxUint32VLQSerializeSize = serializeSizeVLQ(1<<32 - 1) + +// outpointKeyPool defines a concurrent safe free list of byte slices used to +// provide temporary buffers for outpoint database keys. +var outpointKeyPool = sync.Pool{ + New: func() interface{} { + b := make([]byte, chainhash.HashSize+maxUint32VLQSerializeSize) + return &b // Pointer to slice to avoid boxing alloc. + }, +} + +// outpointKey returns a key suitable for use as a database key in the utxo set +// while making use of a free list. A new buffer is allocated if there are not +// already any available on the free list. The returned byte slice should be +// returned to the free list by using the recycleOutpointKey function when the +// caller is done with it _unless_ the slice will need to live for longer than +// the caller can calculate such as when used to write to the database. +func outpointKey(outpoint wire.OutPoint) *[]byte { + // A VLQ employs an MSB encoding, so they are useful not only to reduce + // the amount of storage space, but also so iteration of utxos when + // doing byte-wise comparisons will produce them in order. + key := outpointKeyPool.Get().(*[]byte) + idx := uint64(outpoint.Index) + *key = (*key)[:chainhash.HashSize+serializeSizeVLQ(idx)] + copy(*key, outpoint.Hash[:]) + putVLQ((*key)[chainhash.HashSize:], idx) + return key +} + +// recycleOutpointKey puts the provided byte slice, which should have been +// obtained via the outpointKey function, back on the free list. +func recycleOutpointKey(key *[]byte) { + outpointKeyPool.Put(key) +} + // utxoEntryHeaderCode returns the calculated header code to be used when -// serializing the provided utxo entry and the number of bytes needed to encode -// the unspentness bitmap. -func utxoEntryHeaderCode(entry *UtxoEntry, highestOutputIndex uint32) (uint64, int, error) { - // The first two outputs are encoded separately, so offset the index - // accordingly to calculate the correct number of bytes needed to encode - // up to the highest unspent output index. - numBitmapBytes := int((highestOutputIndex + 6) / 8) - - // As previously described, one less than the number of bytes is encoded - // when both output 0 and 1 are spent because there must be at least one - // unspent output. Adjust the number of bytes to encode accordingly and - // encode the value by shifting it over 3 bits. - output0Unspent := !entry.IsOutputSpent(0) - output1Unspent := !entry.IsOutputSpent(1) - var numBitmapBytesAdjustment int - if !output0Unspent && !output1Unspent { - if numBitmapBytes == 0 { - return 0, 0, AssertError("attempt to serialize utxo " + - "header for fully spent transaction") - } - numBitmapBytesAdjustment = 1 +// serializing the provided utxo entry. +func utxoEntryHeaderCode(entry *UtxoEntry) (uint64, error) { + if entry.IsSpent() { + return 0, AssertError("attempt to serialize spent utxo header") } - headerCode := uint64(numBitmapBytes-numBitmapBytesAdjustment) << 3 - // Set the coinbase, output 0, and output 1 bits in the header code - // accordingly. - if entry.isCoinBase { - headerCode |= 0x01 // bit 0 - } - if output0Unspent { - headerCode |= 0x02 // bit 1 - } - if output1Unspent { - headerCode |= 0x04 // bit 2 + // As described in the serialization format comments, the header code + // encodes the height shifted over one bit and the coinbase flag in the + // lowest bit. + headerCode := uint64(entry.BlockHeight()) << 1 + if entry.IsCoinBase() { + headerCode |= 0x01 } - return headerCode, numBitmapBytes, nil + return headerCode, nil } // serializeUtxoEntry returns the entry serialized to a format that is suitable // for long-term storage. The format is described in detail above. func serializeUtxoEntry(entry *UtxoEntry) ([]byte, error) { - // Fully spent entries have no serialization. - if entry.IsFullySpent() { + // Spent outputs have no serialization. + if entry.IsSpent() { return nil, nil } - // Determine the output order by sorting the sparse output index keys. - outputOrder := make([]int, 0, len(entry.sparseOutputs)) - for outputIndex := range entry.sparseOutputs { - outputOrder = append(outputOrder, int(outputIndex)) - } - sort.Ints(outputOrder) - - // Encode the header code and determine the number of bytes the - // unspentness bitmap needs. - highIndex := uint32(outputOrder[len(outputOrder)-1]) - headerCode, numBitmapBytes, err := utxoEntryHeaderCode(entry, highIndex) + // Encode the header code. + headerCode, err := utxoEntryHeaderCode(entry) if err != nil { return nil, err } // Calculate the size needed to serialize the entry. - size := serializeSizeVLQ(uint64(entry.version)) + - serializeSizeVLQ(uint64(entry.blockHeight)) + - serializeSizeVLQ(headerCode) + numBitmapBytes - for _, outputIndex := range outputOrder { - out := entry.sparseOutputs[uint32(outputIndex)] - if out.spent { - continue - } - size += compressedTxOutSize(uint64(out.amount), out.pkScript, - entry.version, out.compressed) - } + size := serializeSizeVLQ(headerCode) + + compressedTxOutSize(uint64(entry.Amount()), entry.PkScript()) - // Serialize the version, block height of the containing transaction, - // and header code. + // Serialize the header code followed by the compressed unspent + // transaction output. serialized := make([]byte, size) - offset := putVLQ(serialized, uint64(entry.version)) - offset += putVLQ(serialized[offset:], uint64(entry.blockHeight)) - offset += putVLQ(serialized[offset:], headerCode) - - // Serialize the unspentness bitmap. - for i := uint32(0); i < uint32(numBitmapBytes); i++ { - unspentBits := byte(0) - for j := uint32(0); j < 8; j++ { - // The first 2 outputs are encoded via the header code, - // so adjust the output index accordingly. - if !entry.IsOutputSpent(2 + i*8 + j) { - unspentBits |= 1 << uint8(j) - } - } - serialized[offset] = unspentBits - offset++ - } - - // Serialize the compressed unspent transaction outputs. Outputs that - // are already compressed are serialized without modifications. - for _, outputIndex := range outputOrder { - out := entry.sparseOutputs[uint32(outputIndex)] - if out.spent { - continue - } - - offset += putCompressedTxOut(serialized[offset:], - uint64(out.amount), out.pkScript, entry.version, - out.compressed) - } + offset := putVLQ(serialized, headerCode) + offset += putCompressedTxOut(serialized[offset:], uint64(entry.Amount()), + entry.PkScript()) return serialized, nil } @@ -689,23 +628,8 @@ func serializeUtxoEntry(entry *UtxoEntry) ([]byte, error) { // slice into a new UtxoEntry using a format that is suitable for long-term // storage. The format is described in detail above. func deserializeUtxoEntry(serialized []byte) (*UtxoEntry, error) { - // Deserialize the version. - version, bytesRead := deserializeVLQ(serialized) - offset := bytesRead - if offset >= len(serialized) { - return nil, errDeserialize("unexpected end of data after version") - } - - // Deserialize the block height. - blockHeight, bytesRead := deserializeVLQ(serialized[offset:]) - offset += bytesRead - if offset >= len(serialized) { - return nil, errDeserialize("unexpected end of data after height") - } - // Deserialize the header code. - code, bytesRead := deserializeVLQ(serialized[offset:]) - offset += bytesRead + code, offset := deserializeVLQ(serialized) if offset >= len(serialized) { return nil, errDeserialize("unexpected end of data after header") } @@ -713,101 +637,83 @@ func deserializeUtxoEntry(serialized []byte) (*UtxoEntry, error) { // Decode the header code. // // Bit 0 indicates whether the containing transaction is a coinbase. - // Bit 1 indicates output 0 is unspent. - // Bit 2 indicates output 1 is unspent. - // Bits 3-x encodes the number of non-zero unspentness bitmap bytes that - // follow. When both output 0 and 1 are spent, it encodes N-1. + // Bits 1-x encode height of containing transaction. isCoinBase := code&0x01 != 0 - output0Unspent := code&0x02 != 0 - output1Unspent := code&0x04 != 0 - numBitmapBytes := code >> 3 - if !output0Unspent && !output1Unspent { - numBitmapBytes++ - } + blockHeight := int32(code >> 1) - // Ensure there are enough bytes left to deserialize the unspentness - // bitmap. - if uint64(len(serialized[offset:])) < numBitmapBytes { - return nil, errDeserialize("unexpected end of data for " + - "unspentness bitmap") + // Decode the compressed unspent transaction output. + amount, pkScript, _, err := decodeCompressedTxOut(serialized[offset:]) + if err != nil { + return nil, errDeserialize(fmt.Sprintf("unable to decode "+ + "utxo: %v", err)) } - // Create a new utxo entry with the details deserialized above to house - // all of the utxos. - entry := newUtxoEntry(int32(version), isCoinBase, int32(blockHeight)) - - // Add sparse output for unspent outputs 0 and 1 as needed based on the - // details provided by the header code. - var outputIndexes []uint32 - if output0Unspent { - outputIndexes = append(outputIndexes, 0) + entry := &UtxoEntry{ + amount: int64(amount), + pkScript: pkScript, + blockHeight: blockHeight, + packedFlags: 0, } - if output1Unspent { - outputIndexes = append(outputIndexes, 1) + if isCoinBase { + entry.packedFlags |= tfCoinBase } - // Decode the unspentness bitmap adding a sparse output for each unspent - // output. - for i := uint32(0); i < uint32(numBitmapBytes); i++ { - unspentBits := serialized[offset] - for j := uint32(0); j < 8; j++ { - if unspentBits&0x01 != 0 { - // The first 2 outputs are encoded via the - // header code, so adjust the output number - // accordingly. - outputNum := 2 + i*8 + j - outputIndexes = append(outputIndexes, outputNum) - } - unspentBits >>= 1 - } - offset++ - } + return entry, nil +} - // Decode and add all of the utxos. - for i, outputIndex := range outputIndexes { - // Decode the next utxo. The script and amount fields of the - // utxo output are left compressed so decompression can be - // avoided on those that are not accessed. This is done since - // it is quite common for a redeeming transaction to only - // reference a single utxo from a referenced transaction. - compAmount, compScript, bytesRead, err := decodeCompressedTxOut( - serialized[offset:], int32(version)) - if err != nil { - return nil, errDeserialize(fmt.Sprintf("unable to "+ - "decode utxo at index %d: %v", i, err)) - } - offset += bytesRead +// dbFetchUtxoEntryByHash attempts to find and fetch a utxo for the given hash. +// It uses a cursor and seek to try and do this as efficiently as possible. +// +// When there are no entries for the provided hash, nil will be returned for the +// both the entry and the error. +func dbFetchUtxoEntryByHash(dbTx database.Tx, hash *chainhash.Hash) (*UtxoEntry, error) { + // Attempt to find an entry by seeking for the hash along with a zero + // index. Due to the fact the keys are serialized as , + // where the index uses an MSB encoding, if there are any entries for + // the hash at all, one will be found. + cursor := dbTx.Metadata().Bucket(utxoSetBucketName).Cursor() + key := outpointKey(wire.OutPoint{Hash: *hash, Index: 0}) + ok := cursor.Seek(*key) + recycleOutpointKey(key) + if !ok { + return nil, nil + } - entry.sparseOutputs[outputIndex] = &utxoOutput{ - spent: false, - compressed: true, - pkScript: compScript, - amount: int64(compAmount), - } + // An entry was found, but it could just be an entry with the next + // highest hash after the requested one, so make sure the hashes + // actually match. + cursorKey := cursor.Key() + if len(cursorKey) < chainhash.HashSize { + return nil, nil + } + if !bytes.Equal(hash[:], cursorKey[:chainhash.HashSize]) { + return nil, nil } - return entry, nil + return deserializeUtxoEntry(cursor.Value()) } -// dbFetchUtxoEntry uses an existing database transaction to fetch all unspent -// outputs for the provided Bitcoin transaction hash from the utxo set. +// dbFetchUtxoEntry uses an existing database transaction to fetch the specified +// transaction output from the utxo set. // -// When there is no entry for the provided hash, nil will be returned for the -// both the entry and the error. -func dbFetchUtxoEntry(dbTx database.Tx, hash *chainhash.Hash) (*UtxoEntry, error) { +// When there is no entry for the provided output, nil will be returned for both +// the entry and the error. +func dbFetchUtxoEntry(dbTx database.Tx, outpoint wire.OutPoint) (*UtxoEntry, error) { // Fetch the unspent transaction output information for the passed - // transaction hash. Return now when there is no entry. + // transaction output. Return now when there is no entry. + key := outpointKey(outpoint) utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) - serializedUtxo := utxoBucket.Get(hash[:]) + serializedUtxo := utxoBucket.Get(*key) + recycleOutpointKey(key) if serializedUtxo == nil { return nil, nil } // A non-nil zero-length entry means there is an entry in the database - // for a fully spent transaction which should never be the case. + // for a spent transaction output which should never be the case. if len(serializedUtxo) == 0 { return nil, AssertError(fmt.Sprintf("database contains entry "+ - "for fully spent tx %v", hash)) + "for spent tx output %v", outpoint)) } // Deserialize the utxo entry and return it. @@ -819,7 +725,7 @@ func dbFetchUtxoEntry(dbTx database.Tx, hash *chainhash.Hash) (*UtxoEntry, error return nil, database.Error{ ErrorCode: database.ErrCorruption, Description: fmt.Sprintf("corrupt utxo entry "+ - "for %v: %v", hash, err), + "for %v: %v", outpoint, err), } } @@ -835,36 +741,35 @@ func dbFetchUtxoEntry(dbTx database.Tx, hash *chainhash.Hash) (*UtxoEntry, error // to the database. func dbPutUtxoView(dbTx database.Tx, view *UtxoViewpoint) error { utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) - for txHashIter, entry := range view.entries { + for outpoint, entry := range view.entries { // No need to update the database if the entry was not modified. - if entry == nil || !entry.modified { + if entry == nil || !entry.isModified() { continue } - // Serialize the utxo entry without any entries that have been - // spent. - serialized, err := serializeUtxoEntry(entry) - if err != nil { - return err - } - - // Make a copy of the hash because the iterator changes on each - // loop iteration and thus slicing it directly would cause the - // data to change out from under the put/delete funcs below. - txHash := txHashIter - - // Remove the utxo entry if it is now fully spent. - if serialized == nil { - if err := utxoBucket.Delete(txHash[:]); err != nil { + // Remove the utxo entry if it is spent. + if entry.IsSpent() { + key := outpointKey(outpoint) + err := utxoBucket.Delete(*key) + recycleOutpointKey(key) + if err != nil { return err } continue } - // At this point the utxo entry is not fully spent, so store its - // serialization in the database. - err = utxoBucket.Put(txHash[:], serialized) + // Serialize and store the utxo entry. + serialized, err := serializeUtxoEntry(entry) + if err != nil { + return err + } + key := outpointKey(outpoint) + err = utxoBucket.Put(*key, serialized) + // NOTE: The key is intentionally not recycled here since the + // database interface contract prohibits modifications. It will + // be garbage collected normally when the database is done with + // it. if err != nil { return err } @@ -1111,19 +1016,31 @@ func (b *BlockChain) createChainState() error { return err } - // Create the bucket that houses the spend journal data. + // Create the bucket that houses the spend journal data and + // store its version. _, err = meta.CreateBucket(spendJournalBucketName) if err != nil { return err } + err = dbPutVersion(dbTx, utxoSetVersionKeyName, + latestUtxoSetBucketVersion) + if err != nil { + return err + } - // Create the bucket that houses the utxo set. Note that the - // genesis block coinbase transaction is intentionally not - // inserted here since it is not spendable by consensus rules. + // Create the bucket that houses the utxo set and store its + // version. Note that the genesis block coinbase transaction is + // intentionally not inserted here since it is not spendable by + // consensus rules. _, err = meta.CreateBucket(utxoSetBucketName) if err != nil { return err } + err = dbPutVersion(dbTx, spendJournalVersionKeyName, + latestSpendJournalBucketVersion) + if err != nil { + return err + } // Save the genesis block to the block index database. err = dbStoreBlockNode(dbTx, node) diff --git a/blockchain/chainio_test.go b/blockchain/chainio_test.go index a3fcb5af50..f62a39d2c6 100644 --- a/blockchain/chainio_test.go +++ b/blockchain/chainio_test.go @@ -11,7 +11,6 @@ import ( "reflect" "testing" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" ) @@ -38,19 +37,6 @@ func TestErrNotInMainChain(t *testing.T) { } } -// maybeDecompress decompresses the amount and public key script fields of the -// stxo and marks it decompressed if needed. -func (o *spentTxOut) maybeDecompress(version int32) { - // Nothing to do if it's not compressed. - if !o.compressed { - return - } - - o.amount = int64(decompressTxOutAmount(uint64(o.amount))) - o.pkScript = decompressScript(o.pkScript, version) - o.compressed = false -} - // TestStxoSerialization ensures serializing and deserializing spent transaction // output entries works as expected. func TestStxoSerialization(t *testing.T) { @@ -59,7 +45,6 @@ func TestStxoSerialization(t *testing.T) { tests := []struct { name string stxo spentTxOut - txVersion int32 // When the txout is not fully spent. serialized []byte }{ // From block 170 in main blockchain. @@ -70,9 +55,8 @@ func TestStxoSerialization(t *testing.T) { pkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), isCoinBase: true, height: 9, - version: 1, }, - serialized: hexToBytes("1301320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"), + serialized: hexToBytes("1300320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"), }, // Adapted from block 100025 in main blockchain. { @@ -82,19 +66,16 @@ func TestStxoSerialization(t *testing.T) { pkScript: hexToBytes("76a914b2fb57eadf61e106a100a7445a8c3f67898841ec88ac"), isCoinBase: false, height: 100024, - version: 1, }, - serialized: hexToBytes("8b99700186c64700b2fb57eadf61e106a100a7445a8c3f67898841ec"), + serialized: hexToBytes("8b99700086c64700b2fb57eadf61e106a100a7445a8c3f67898841ec"), }, // Adapted from block 100025 in main blockchain. { - name: "Does not spend last output", + name: "Does not spend last output, legacy format", stxo: spentTxOut{ amount: 34405000000, pkScript: hexToBytes("76a9146edbc6c4d31bae9f1ccc38538a114bf42de65e8688ac"), - version: 1, }, - txVersion: 1, serialized: hexToBytes("0091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e86"), }, } @@ -130,14 +111,12 @@ func TestStxoSerialization(t *testing.T) { // Ensure the serialized bytes are decoded back to the expected // stxo. var gotStxo spentTxOut - gotBytesRead, err := decodeSpentTxOut(test.serialized, &gotStxo, - test.txVersion) + gotBytesRead, err := decodeSpentTxOut(test.serialized, &gotStxo) if err != nil { t.Errorf("decodeSpentTxOut (%s): unexpected error: %v", test.name, err) continue } - gotStxo.maybeDecompress(test.stxo.version) if !reflect.DeepEqual(gotStxo, test.stxo) { t.Errorf("decodeSpentTxOut (%s) mismatched entries - "+ "got %v, want %v", test.name, gotStxo, test.stxo) @@ -160,7 +139,6 @@ func TestStxoDecodeErrors(t *testing.T) { tests := []struct { name string stxo spentTxOut - txVersion int32 // When the txout is not fully spent. serialized []byte bytesRead int // Expected number of bytes read. errType error @@ -173,39 +151,30 @@ func TestStxoDecodeErrors(t *testing.T) { bytesRead: 0, }, { - name: "no data after header code w/o version", + name: "no data after header code w/o reserved", stxo: spentTxOut{}, serialized: hexToBytes("00"), errType: errDeserialize(""), bytesRead: 1, }, { - name: "no data after header code with version", + name: "no data after header code with reserved", stxo: spentTxOut{}, serialized: hexToBytes("13"), errType: errDeserialize(""), bytesRead: 1, }, { - name: "no data after version", + name: "no data after reserved", stxo: spentTxOut{}, - serialized: hexToBytes("1301"), + serialized: hexToBytes("1300"), errType: errDeserialize(""), bytesRead: 2, }, - { - name: "no serialized tx version and passed -1", - stxo: spentTxOut{}, - txVersion: -1, - serialized: hexToBytes("003205"), - errType: AssertError(""), - bytesRead: 1, - }, { name: "incomplete compressed txout", stxo: spentTxOut{}, - txVersion: 1, - serialized: hexToBytes("0032"), + serialized: hexToBytes("1332"), errType: errDeserialize(""), bytesRead: 2, }, @@ -214,7 +183,7 @@ func TestStxoDecodeErrors(t *testing.T) { for _, test := range tests { // Ensure the expected error type is returned. gotBytesRead, err := decodeSpentTxOut(test.serialized, - &test.stxo, test.txVersion) + &test.stxo) if reflect.TypeOf(err) != reflect.TypeOf(test.errType) { t.Errorf("decodeSpentTxOut (%s): expected error type "+ "does not match - got %T, want %T", test.name, @@ -241,7 +210,6 @@ func TestSpendJournalSerialization(t *testing.T) { name string entry []spentTxOut blockTxns []*wire.MsgTx - utxoView *UtxoViewpoint serialized []byte }{ // From block 2 in main blockchain. @@ -249,7 +217,6 @@ func TestSpendJournalSerialization(t *testing.T) { name: "No spends", entry: nil, blockTxns: nil, - utxoView: NewUtxoViewpoint(), serialized: nil, }, // From block 170 in main blockchain. @@ -260,7 +227,6 @@ func TestSpendJournalSerialization(t *testing.T) { pkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), isCoinBase: true, height: 9, - version: 1, }}, blockTxns: []*wire.MsgTx{{ // Coinbase omitted. Version: 1, @@ -281,22 +247,21 @@ func TestSpendJournalSerialization(t *testing.T) { }}, LockTime: 0, }}, - utxoView: NewUtxoViewpoint(), - serialized: hexToBytes("1301320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"), + serialized: hexToBytes("1300320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"), }, // Adapted from block 100025 in main blockchain. { name: "Two txns when one spends last output, one doesn't", entry: []spentTxOut{{ - amount: 34405000000, - pkScript: hexToBytes("76a9146edbc6c4d31bae9f1ccc38538a114bf42de65e8688ac"), - version: 1, + amount: 34405000000, + pkScript: hexToBytes("76a9146edbc6c4d31bae9f1ccc38538a114bf42de65e8688ac"), + isCoinBase: false, + height: 100024, }, { amount: 13761000000, pkScript: hexToBytes("76a914b2fb57eadf61e106a100a7445a8c3f67898841ec88ac"), isCoinBase: false, height: 100024, - version: 1, }}, blockTxns: []*wire.MsgTx{{ // Coinbase omitted. Version: 1, @@ -335,73 +300,7 @@ func TestSpendJournalSerialization(t *testing.T) { }}, LockTime: 0, }}, - utxoView: &UtxoViewpoint{entries: map[chainhash.Hash]*UtxoEntry{ - *newHashFromStr("c0ed017828e59ad5ed3cf70ee7c6fb0f426433047462477dc7a5d470f987a537"): { - version: 1, - isCoinBase: false, - blockHeight: 100024, - sparseOutputs: map[uint32]*utxoOutput{ - 1: { - amount: 34405000000, - pkScript: hexToBytes("76a9142084541c3931677527a7eafe56fd90207c344eb088ac"), - }, - }, - }, - }}, - serialized: hexToBytes("8b99700186c64700b2fb57eadf61e106a100a7445a8c3f67898841ec0091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e86"), - }, - // Hand crafted. - { - name: "One tx, two inputs from same tx, neither spend last output", - entry: []spentTxOut{{ - amount: 165125632, - pkScript: hexToBytes("51"), - version: 1, - }, { - amount: 154370000, - pkScript: hexToBytes("51"), - version: 1, - }}, - blockTxns: []*wire.MsgTx{{ // Coinbase omitted. - Version: 1, - TxIn: []*wire.TxIn{{ - PreviousOutPoint: wire.OutPoint{ - Hash: *newHashFromStr("c0ed017828e59ad5ed3cf70ee7c6fb0f426433047462477dc7a5d470f987a537"), - Index: 1, - }, - SignatureScript: hexToBytes(""), - Sequence: 0xffffffff, - }, { - PreviousOutPoint: wire.OutPoint{ - Hash: *newHashFromStr("c0ed017828e59ad5ed3cf70ee7c6fb0f426433047462477dc7a5d470f987a537"), - Index: 2, - }, - SignatureScript: hexToBytes(""), - Sequence: 0xffffffff, - }}, - TxOut: []*wire.TxOut{{ - Value: 165125632, - PkScript: hexToBytes("51"), - }, { - Value: 154370000, - PkScript: hexToBytes("51"), - }}, - LockTime: 0, - }}, - utxoView: &UtxoViewpoint{entries: map[chainhash.Hash]*UtxoEntry{ - *newHashFromStr("c0ed017828e59ad5ed3cf70ee7c6fb0f426433047462477dc7a5d470f987a537"): { - version: 1, - isCoinBase: false, - blockHeight: 100000, - sparseOutputs: map[uint32]*utxoOutput{ - 0: { - amount: 165712179, - pkScript: hexToBytes("51"), - }, - }, - }, - }}, - serialized: hexToBytes("0087bc3707510084c3d19a790751"), + serialized: hexToBytes("8b99700086c64700b2fb57eadf61e106a100a7445a8c3f67898841ec8b99700091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e86"), }, } @@ -417,16 +316,12 @@ func TestSpendJournalSerialization(t *testing.T) { // Deserialize to a spend journal entry. gotEntry, err := deserializeSpendJournalEntry(test.serialized, - test.blockTxns, test.utxoView) + test.blockTxns) if err != nil { t.Errorf("deserializeSpendJournalEntry #%d (%s) "+ "unexpected error: %v", i, test.name, err) continue } - for stxoIdx := range gotEntry { - stxo := &gotEntry[stxoIdx] - stxo.maybeDecompress(test.entry[stxoIdx].version) - } // Ensure that the deserialized spend journal entry has the // correct properties. @@ -447,7 +342,6 @@ func TestSpendJournalErrors(t *testing.T) { tests := []struct { name string blockTxns []*wire.MsgTx - utxoView *UtxoViewpoint serialized []byte errType error }{ @@ -466,7 +360,6 @@ func TestSpendJournalErrors(t *testing.T) { }}, LockTime: 0, }}, - utxoView: NewUtxoViewpoint(), serialized: hexToBytes(""), errType: AssertError(""), }, @@ -484,7 +377,6 @@ func TestSpendJournalErrors(t *testing.T) { }}, LockTime: 0, }}, - utxoView: NewUtxoViewpoint(), serialized: hexToBytes("1301320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a"), errType: errDeserialize(""), }, @@ -494,7 +386,7 @@ func TestSpendJournalErrors(t *testing.T) { // Ensure the expected error type is returned and the returned // slice is nil. stxos, err := deserializeSpendJournalEntry(test.serialized, - test.blockTxns, test.utxoView) + test.blockTxns) if reflect.TypeOf(err) != reflect.TypeOf(test.errType) { t.Errorf("deserializeSpendJournalEntry (%s): expected "+ "error type does not match - got %T, want %T", @@ -521,187 +413,53 @@ func TestUtxoSerialization(t *testing.T) { serialized []byte }{ // From tx in main blockchain: - // 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 + // 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098:0 { - name: "Only output 0, coinbase", + name: "height 1, coinbase", entry: &UtxoEntry{ - version: 1, - isCoinBase: true, + amount: 5000000000, + pkScript: hexToBytes("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac"), blockHeight: 1, - sparseOutputs: map[uint32]*utxoOutput{ - 0: { - amount: 5000000000, - pkScript: hexToBytes("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac"), - }, - }, + packedFlags: tfCoinBase, }, - serialized: hexToBytes("010103320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"), + serialized: hexToBytes("03320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"), }, // From tx in main blockchain: - // 8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb + // 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098:0 { - name: "Only output 1, not coinbase", + name: "height 1, coinbase, spent", entry: &UtxoEntry{ - version: 1, - isCoinBase: false, - blockHeight: 100001, - sparseOutputs: map[uint32]*utxoOutput{ - 1: { - amount: 1000000, - pkScript: hexToBytes("76a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac"), - }, - }, - }, - serialized: hexToBytes("01858c21040700ee8bd501094a7d5ca318da2506de35e1cb025ddc"), - }, - // Adapted from tx in main blockchain: - // df3f3f442d9699857f7f49de4ff0b5d0f3448bec31cdc7b5bf6d25f2abd637d5 - { - name: "Only output 2, coinbase", - entry: &UtxoEntry{ - version: 1, - isCoinBase: true, - blockHeight: 99004, - sparseOutputs: map[uint32]*utxoOutput{ - 2: { - amount: 100937281, - pkScript: hexToBytes("76a914da33f77cee27c2a975ed5124d7e4f7f97513510188ac"), - }, - }, - }, - serialized: hexToBytes("0185843c010182b095bf4100da33f77cee27c2a975ed5124d7e4f7f975135101"), - }, - // Adapted from tx in main blockchain: - // 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f - { - name: "outputs 0 and 2 not coinbase", - entry: &UtxoEntry{ - version: 1, - isCoinBase: false, - blockHeight: 113931, - sparseOutputs: map[uint32]*utxoOutput{ - 0: { - amount: 20000000, - pkScript: hexToBytes("76a914e2ccd6ec7c6e2e581349c77e067385fa8236bf8a88ac"), - }, - 2: { - amount: 15000000, - pkScript: hexToBytes("76a914b8025be1b3efc63b0ad48e7f9f10e87544528d5888ac"), - }, - }, - }, - serialized: hexToBytes("0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58"), - }, - // Adapted from tx in main blockchain: - // 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f - { - name: "outputs 0 and 2, not coinbase, 1 marked spent", - entry: &UtxoEntry{ - version: 1, - isCoinBase: false, - blockHeight: 113931, - sparseOutputs: map[uint32]*utxoOutput{ - 0: { - amount: 20000000, - pkScript: hexToBytes("76a914e2ccd6ec7c6e2e581349c77e067385fa8236bf8a88ac"), - }, - 1: { // This won't be serialized. - spent: true, - amount: 1000000, - pkScript: hexToBytes("76a914e43031c3e46f20bf1ccee9553ce815de5a48467588ac"), - }, - 2: { - amount: 15000000, - pkScript: hexToBytes("76a914b8025be1b3efc63b0ad48e7f9f10e87544528d5888ac"), - }, - }, - }, - serialized: hexToBytes("0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58"), - }, - // Adapted from tx in main blockchain: - // 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f - { - name: "outputs 0 and 2, not coinbase, output 2 compressed", - entry: &UtxoEntry{ - version: 1, - isCoinBase: false, - blockHeight: 113931, - sparseOutputs: map[uint32]*utxoOutput{ - 0: { - amount: 20000000, - pkScript: hexToBytes("76a914e2ccd6ec7c6e2e581349c77e067385fa8236bf8a88ac"), - }, - 2: { - // Uncompressed Amount: 15000000 - // Uncompressed PkScript: 76a914b8025be1b3efc63b0ad48e7f9f10e87544528d5888ac - compressed: true, - amount: 137, - pkScript: hexToBytes("00b8025be1b3efc63b0ad48e7f9f10e87544528d58"), - }, - }, + amount: 5000000000, + pkScript: hexToBytes("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac"), + blockHeight: 1, + packedFlags: tfCoinBase | tfSpent, }, - serialized: hexToBytes("0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58"), + serialized: nil, }, - // Adapted from tx in main blockchain: - // 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f + // From tx in main blockchain: + // 8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb:1 { - name: "outputs 0 and 2, not coinbase, output 2 compressed, packed indexes reversed", + name: "height 100001, not coinbase", entry: &UtxoEntry{ - version: 1, - isCoinBase: false, - blockHeight: 113931, - sparseOutputs: map[uint32]*utxoOutput{ - 0: { - amount: 20000000, - pkScript: hexToBytes("76a914e2ccd6ec7c6e2e581349c77e067385fa8236bf8a88ac"), - }, - 2: { - // Uncompressed Amount: 15000000 - // Uncompressed PkScript: 76a914b8025be1b3efc63b0ad48e7f9f10e87544528d5888ac - compressed: true, - amount: 137, - pkScript: hexToBytes("00b8025be1b3efc63b0ad48e7f9f10e87544528d58"), - }, - }, + amount: 1000000, + pkScript: hexToBytes("76a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac"), + blockHeight: 100001, + packedFlags: 0, }, - serialized: hexToBytes("0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58"), + serialized: hexToBytes("8b99420700ee8bd501094a7d5ca318da2506de35e1cb025ddc"), }, // From tx in main blockchain: - // 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 + // 8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb:1 { - name: "Only output 0, coinbase, fully spent", + name: "height 100001, not coinbase, spent", entry: &UtxoEntry{ - version: 1, - isCoinBase: true, - blockHeight: 1, - sparseOutputs: map[uint32]*utxoOutput{ - 0: { - spent: true, - amount: 5000000000, - pkScript: hexToBytes("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac"), - }, - }, + amount: 1000000, + pkScript: hexToBytes("76a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac"), + blockHeight: 100001, + packedFlags: tfSpent, }, serialized: nil, }, - // Adapted from tx in main blockchain: - // 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620 - { - name: "Only output 22, not coinbase", - entry: &UtxoEntry{ - version: 1, - isCoinBase: false, - blockHeight: 338156, - sparseOutputs: map[uint32]*utxoOutput{ - 22: { - spent: false, - amount: 366875659, - pkScript: hexToBytes("a9141dd46a006572d820e448e12d2bbb38640bc718e687"), - }, - }, - }, - serialized: hexToBytes("0193d06c100000108ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6"), - }, } for i, test := range tests { @@ -719,9 +477,9 @@ func TestUtxoSerialization(t *testing.T) { continue } - // Don't try to deserialize if the test entry was fully spent - // since it will have a nil serialization. - if test.entry.IsFullySpent() { + // Don't try to deserialize if the test entry was spent since it + // will have a nil serialization. + if test.entry.IsSpent() { continue } @@ -733,85 +491,41 @@ func TestUtxoSerialization(t *testing.T) { continue } - // Ensure that the deserialized utxo entry has the same - // properties for the containing transaction and block height. - if utxoEntry.Version() != test.entry.Version() { + // The deserialized entry must not be marked spent since unspent + // entries are not serialized. + if utxoEntry.IsSpent() { + t.Errorf("deserializeUtxoEntry #%d (%s) output should "+ + "not be marked spent", i, test.name) + continue + } + + // Ensure the deserialized entry has the same properties as the + // ones in the test entry. + if utxoEntry.Amount() != test.entry.Amount() { t.Errorf("deserializeUtxoEntry #%d (%s) mismatched "+ - "version: got %d, want %d", i, test.name, - utxoEntry.Version(), test.entry.Version()) + "amounts: got %d, want %d", i, test.name, + utxoEntry.Amount(), test.entry.Amount()) continue } - if utxoEntry.IsCoinBase() != test.entry.IsCoinBase() { + + if !bytes.Equal(utxoEntry.PkScript(), test.entry.PkScript()) { t.Errorf("deserializeUtxoEntry #%d (%s) mismatched "+ - "coinbase flag: got %v, want %v", i, test.name, - utxoEntry.IsCoinBase(), test.entry.IsCoinBase()) + "scripts: got %x, want %x", i, test.name, + utxoEntry.PkScript(), test.entry.PkScript()) continue } if utxoEntry.BlockHeight() != test.entry.BlockHeight() { t.Errorf("deserializeUtxoEntry #%d (%s) mismatched "+ "block height: got %d, want %d", i, test.name, - utxoEntry.BlockHeight(), - test.entry.BlockHeight()) + utxoEntry.BlockHeight(), test.entry.BlockHeight()) continue } - if utxoEntry.IsFullySpent() != test.entry.IsFullySpent() { + if utxoEntry.IsCoinBase() != test.entry.IsCoinBase() { t.Errorf("deserializeUtxoEntry #%d (%s) mismatched "+ - "fully spent: got %v, want %v", i, test.name, - utxoEntry.IsFullySpent(), - test.entry.IsFullySpent()) - continue - } - - // Ensure all of the outputs in the test entry match the - // spentness of the output in the deserialized entry and the - // deserialized entry does not contain any additional utxos. - var numUnspent int - for outputIndex := range test.entry.sparseOutputs { - gotSpent := utxoEntry.IsOutputSpent(outputIndex) - wantSpent := test.entry.IsOutputSpent(outputIndex) - if !wantSpent { - numUnspent++ - } - if gotSpent != wantSpent { - t.Errorf("deserializeUtxoEntry #%d (%s) output "+ - "#%d: mismatched spent: got %v, want "+ - "%v", i, test.name, outputIndex, - gotSpent, wantSpent) - continue - - } - } - if len(utxoEntry.sparseOutputs) != numUnspent { - t.Errorf("deserializeUtxoEntry #%d (%s): mismatched "+ - "number of unspent outputs: got %d, want %d", i, - test.name, len(utxoEntry.sparseOutputs), - numUnspent) + "coinbase flag: got %v, want %v", i, test.name, + utxoEntry.IsCoinBase(), test.entry.IsCoinBase()) continue } - - // Ensure all of the amounts and scripts of the utxos in the - // deserialized entry match the ones in the test entry. - for outputIndex := range utxoEntry.sparseOutputs { - gotAmount := utxoEntry.AmountByIndex(outputIndex) - wantAmount := test.entry.AmountByIndex(outputIndex) - if gotAmount != wantAmount { - t.Errorf("deserializeUtxoEntry #%d (%s) "+ - "output #%d: mismatched amounts: got "+ - "%d, want %d", i, test.name, - outputIndex, gotAmount, wantAmount) - continue - } - - gotPkScript := utxoEntry.PkScriptByIndex(outputIndex) - wantPkScript := test.entry.PkScriptByIndex(outputIndex) - if !bytes.Equal(gotPkScript, wantPkScript) { - t.Errorf("deserializeUtxoEntry #%d (%s) "+ - "output #%d mismatched scripts: got "+ - "%x, want %x", i, test.name, - outputIndex, gotPkScript, wantPkScript) - continue - } - } } } @@ -821,23 +535,21 @@ func TestUtxoEntryHeaderCodeErrors(t *testing.T) { t.Parallel() tests := []struct { - name string - entry *UtxoEntry - code uint64 - bytesRead int // Expected number of bytes read. - errType error + name string + entry *UtxoEntry + code uint64 + errType error }{ { - name: "Force assertion due to fully spent tx", - entry: &UtxoEntry{}, - errType: AssertError(""), - bytesRead: 0, + name: "Force assertion due to spent output", + entry: &UtxoEntry{packedFlags: tfSpent}, + errType: AssertError(""), }, } for _, test := range tests { // Ensure the expected error type is returned and the code is 0. - code, gotBytesRead, err := utxoEntryHeaderCode(test.entry, 0) + code, err := utxoEntryHeaderCode(test.entry) if reflect.TypeOf(err) != reflect.TypeOf(test.errType) { t.Errorf("utxoEntryHeaderCode (%s): expected error "+ "type does not match - got %T, want %T", @@ -849,14 +561,6 @@ func TestUtxoEntryHeaderCodeErrors(t *testing.T) { "on error - got %d, want 0", test.name, code) continue } - - // Ensure the expected number of bytes read is returned. - if gotBytesRead != test.bytesRead { - t.Errorf("utxoEntryHeaderCode (%s): unexpected number "+ - "of bytes read - got %d, want %d", test.name, - gotBytesRead, test.bytesRead) - continue - } } } @@ -870,29 +574,14 @@ func TestUtxoEntryDeserializeErrors(t *testing.T) { serialized []byte errType error }{ - { - name: "no data after version", - serialized: hexToBytes("01"), - errType: errDeserialize(""), - }, - { - name: "no data after block height", - serialized: hexToBytes("0101"), - errType: errDeserialize(""), - }, { name: "no data after header code", - serialized: hexToBytes("010102"), - errType: errDeserialize(""), - }, - { - name: "not enough bytes for unspentness bitmap", - serialized: hexToBytes("01017800"), + serialized: hexToBytes("02"), errType: errDeserialize(""), }, { name: "incomplete compressed txout", - serialized: hexToBytes("01010232"), + serialized: hexToBytes("0232"), errType: errDeserialize(""), }, } diff --git a/blockchain/common_test.go b/blockchain/common_test.go index d6eff63dfb..dd392a6669 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -190,10 +190,10 @@ func chainSetup(dbName string, params *chaincfg.Params) (*BlockChain, func(), er // loadUtxoView returns a utxo view loaded from a file. func loadUtxoView(filename string) (*UtxoViewpoint, error) { // The utxostore file format is: - // + // // - // The serialized utxo len is a little endian uint32 and the serialized - // utxo uses the format described in chainio.go. + // The output index and serialized utxo len are little endian uint32s + // and the serialized utxo uses the format described in chainio.go. filename = filepath.Join("testdata", filename) fi, err := os.Open(filename) @@ -223,7 +223,14 @@ func loadUtxoView(filename string) (*UtxoViewpoint, error) { return nil, err } - // Num of serialize utxo entry bytes. + // Output index of the utxo entry. + var index uint32 + err = binary.Read(r, binary.LittleEndian, &index) + if err != nil { + return nil, err + } + + // Num of serialized utxo entry bytes. var numBytes uint32 err = binary.Read(r, binary.LittleEndian, &numBytes) if err != nil { @@ -238,16 +245,98 @@ func loadUtxoView(filename string) (*UtxoViewpoint, error) { } // Deserialize it and add it to the view. - utxoEntry, err := deserializeUtxoEntry(serialized) + entry, err := deserializeUtxoEntry(serialized) if err != nil { return nil, err } - view.Entries()[hash] = utxoEntry + view.Entries()[wire.OutPoint{Hash: hash, Index: index}] = entry } return view, nil } +// convertUtxoStore reads a utxostore from the legacy format and writes it back +// out using the latest format. It is only useful for converting utxostore data +// used in the tests, which has already been done. However, the code is left +// available for future reference. +func convertUtxoStore(r io.Reader, w io.Writer) error { + // The old utxostore file format was: + // + // + // The serialized utxo len was a little endian uint32 and the serialized + // utxo uses the format described in upgrade.go. + + littleEndian := binary.LittleEndian + for { + // Hash of the utxo entry. + var hash chainhash.Hash + _, err := io.ReadAtLeast(r, hash[:], len(hash[:])) + if err != nil { + // Expected EOF at the right offset. + if err == io.EOF { + break + } + return err + } + + // Num of serialized utxo entry bytes. + var numBytes uint32 + err = binary.Read(r, littleEndian, &numBytes) + if err != nil { + return err + } + + // Serialized utxo entry. + serialized := make([]byte, numBytes) + _, err = io.ReadAtLeast(r, serialized, int(numBytes)) + if err != nil { + return err + } + + // Deserialize the entry. + entries, err := deserializeUtxoEntryV0(serialized) + if err != nil { + return err + } + + // Loop through all of the utxos and write them out in the new + // format. + for outputIdx, entry := range entries { + // Reserialize the entries using the new format. + serialized, err := serializeUtxoEntry(entry) + if err != nil { + return err + } + + // Write the hash of the utxo entry. + _, err = w.Write(hash[:]) + if err != nil { + return err + } + + // Write the output index of the utxo entry. + err = binary.Write(w, littleEndian, outputIdx) + if err != nil { + return err + } + + // Write num of serialized utxo entry bytes. + err = binary.Write(w, littleEndian, uint32(len(serialized))) + if err != nil { + return err + } + + // Write the serialized utxo. + _, err = w.Write(serialized) + if err != nil { + return err + } + } + } + + return nil +} + // TstSetCoinbaseMaturity makes the ability to set the coinbase maturity // available when running tests. func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) { diff --git a/blockchain/compress.go b/blockchain/compress.go index 87328d0f31..611b9f0992 100644 --- a/blockchain/compress.go +++ b/blockchain/compress.go @@ -241,7 +241,7 @@ func isPubKey(script []byte) (bool, []byte) { // compressedScriptSize returns the number of bytes the passed script would take // when encoded with the domain specific compression algorithm described above. -func compressedScriptSize(pkScript []byte, version int32) int { +func compressedScriptSize(pkScript []byte) int { // Pay-to-pubkey-hash script. if valid, _ := isPubKeyHash(pkScript); valid { return 21 @@ -268,7 +268,7 @@ func compressedScriptSize(pkScript []byte, version int32) int { // script, possibly followed by other data, and returns the number of bytes it // occupies taking into account the special encoding of the script size by the // domain specific compression algorithm described above. -func decodeCompressedScriptSize(serialized []byte, version int32) int { +func decodeCompressedScriptSize(serialized []byte) int { scriptSize, bytesRead := deserializeVLQ(serialized) if bytesRead == 0 { return 0 @@ -296,7 +296,7 @@ func decodeCompressedScriptSize(serialized []byte, version int32) int { // target byte slice. The target byte slice must be at least large enough to // handle the number of bytes returned by the compressedScriptSize function or // it will panic. -func putCompressedScript(target, pkScript []byte, version int32) int { +func putCompressedScript(target, pkScript []byte) int { // Pay-to-pubkey-hash script. if valid, hash := isPubKeyHash(pkScript); valid { target[0] = cstPayToPubKeyHash @@ -344,7 +344,7 @@ func putCompressedScript(target, pkScript []byte, version int32) int { // NOTE: The script parameter must already have been proven to be long enough // to contain the number of bytes returned by decodeCompressedScriptSize or it // will panic. This is acceptable since it is only an internal function. -func decompressScript(compressedPkScript []byte, version int32) []byte { +func decompressScript(compressedPkScript []byte) []byte { // In practice this function will not be called with a zero-length or // nil script since the nil script encoding includes the length, however // the code below assumes the length exists, so just return nil now if @@ -542,43 +542,27 @@ func decompressTxOutAmount(amount uint64) uint64 { // ----------------------------------------------------------------------------- // compressedTxOutSize returns the number of bytes the passed transaction output -// fields would take when encoded with the format described above. The -// preCompressed flag indicates the provided amount and script are already -// compressed. This is useful since loaded utxo entries are not decompressed -// until the output is accessed. -func compressedTxOutSize(amount uint64, pkScript []byte, version int32, preCompressed bool) int { - if preCompressed { - return serializeSizeVLQ(amount) + len(pkScript) - } - +// fields would take when encoded with the format described above. +func compressedTxOutSize(amount uint64, pkScript []byte) int { return serializeSizeVLQ(compressTxOutAmount(amount)) + - compressedScriptSize(pkScript, version) + compressedScriptSize(pkScript) } -// putCompressedTxOut potentially compresses the passed amount and script -// according to their domain specific compression algorithms and encodes them -// directly into the passed target byte slice with the format described above. -// The preCompressed flag indicates the provided amount and script are already -// compressed in which case the values are not modified. This is useful since -// loaded utxo entries are not decompressed until the output is accessed. The -// target byte slice must be at least large enough to handle the number of bytes -// returned by the compressedTxOutSize function or it will panic. -func putCompressedTxOut(target []byte, amount uint64, pkScript []byte, version int32, preCompressed bool) int { - if preCompressed { - offset := putVLQ(target, amount) - copy(target[offset:], pkScript) - return offset + len(pkScript) - } - +// putCompressedTxOut compresses the passed amount and script according to their +// domain specific compression algorithms and encodes them directly into the +// passed target byte slice with the format described above. The target byte +// slice must be at least large enough to handle the number of bytes returned by +// the compressedTxOutSize function or it will panic. +func putCompressedTxOut(target []byte, amount uint64, pkScript []byte) int { offset := putVLQ(target, compressTxOutAmount(amount)) - offset += putCompressedScript(target[offset:], pkScript, version) + offset += putCompressedScript(target[offset:], pkScript) return offset } // decodeCompressedTxOut decodes the passed compressed txout, possibly followed -// by other data, into its compressed amount and compressed script and returns -// them along with the number of bytes they occupied. -func decodeCompressedTxOut(serialized []byte, version int32) (uint64, []byte, int, error) { +// by other data, into its uncompressed amount and script and returns them along +// with the number of bytes they occupied prior to decompression. +func decodeCompressedTxOut(serialized []byte) (uint64, []byte, int, error) { // Deserialize the compressed amount and ensure there are bytes // remaining for the compressed script. compressedAmount, bytesRead := deserializeVLQ(serialized) @@ -589,15 +573,14 @@ func decodeCompressedTxOut(serialized []byte, version int32) (uint64, []byte, in // Decode the compressed script size and ensure there are enough bytes // left in the slice for it. - scriptSize := decodeCompressedScriptSize(serialized[bytesRead:], version) + scriptSize := decodeCompressedScriptSize(serialized[bytesRead:]) if len(serialized[bytesRead:]) < scriptSize { return 0, nil, bytesRead, errDeserialize("unexpected end of " + "data after script size") } - // Make a copy of the compressed script so the original serialized data - // can be released as soon as possible. - compressedScript := make([]byte, scriptSize) - copy(compressedScript, serialized[bytesRead:bytesRead+scriptSize]) - return compressedAmount, compressedScript, bytesRead + scriptSize, nil + // Decompress and return the amount and script. + amount := decompressTxOutAmount(compressedAmount) + script := decompressScript(serialized[bytesRead : bytesRead+scriptSize]) + return amount, script, bytesRead + scriptSize, nil } diff --git a/blockchain/compress_test.go b/blockchain/compress_test.go index 10a7747b9f..b1a6ff2741 100644 --- a/blockchain/compress_test.go +++ b/blockchain/compress_test.go @@ -109,79 +109,66 @@ func TestScriptCompression(t *testing.T) { tests := []struct { name string - version int32 uncompressed []byte compressed []byte }{ { name: "nil", - version: 1, uncompressed: nil, compressed: hexToBytes("06"), }, { name: "pay-to-pubkey-hash 1", - version: 1, uncompressed: hexToBytes("76a9141018853670f9f3b0582c5b9ee8ce93764ac32b9388ac"), compressed: hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"), }, { name: "pay-to-pubkey-hash 2", - version: 1, uncompressed: hexToBytes("76a914e34cce70c86373273efcc54ce7d2a491bb4a0e8488ac"), compressed: hexToBytes("00e34cce70c86373273efcc54ce7d2a491bb4a0e84"), }, { name: "pay-to-script-hash 1", - version: 1, uncompressed: hexToBytes("a914da1745e9b549bd0bfa1a569971c77eba30cd5a4b87"), compressed: hexToBytes("01da1745e9b549bd0bfa1a569971c77eba30cd5a4b"), }, { name: "pay-to-script-hash 2", - version: 1, uncompressed: hexToBytes("a914f815b036d9bbbce5e9f2a00abd1bf3dc91e9551087"), compressed: hexToBytes("01f815b036d9bbbce5e9f2a00abd1bf3dc91e95510"), }, { name: "pay-to-pubkey compressed 0x02", - version: 1, uncompressed: hexToBytes("2102192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4ac"), compressed: hexToBytes("02192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), }, { name: "pay-to-pubkey compressed 0x03", - version: 1, uncompressed: hexToBytes("2103b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65ac"), compressed: hexToBytes("03b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), }, { name: "pay-to-pubkey uncompressed 0x04 even", - version: 1, uncompressed: hexToBytes("4104192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453eac"), compressed: hexToBytes("04192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), }, { name: "pay-to-pubkey uncompressed 0x04 odd", - version: 1, uncompressed: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), compressed: hexToBytes("0511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"), }, { name: "pay-to-pubkey invalid pubkey", - version: 1, uncompressed: hexToBytes("3302aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac"), compressed: hexToBytes("293302aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac"), }, { name: "null data", - version: 1, uncompressed: hexToBytes("6a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), compressed: hexToBytes("286a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), }, { name: "requires 2 size bytes - data push 200 bytes", - version: 1, uncompressed: append(hexToBytes("4cc8"), bytes.Repeat([]byte{0x00}, 200)...), // [0x80, 0x50] = 208 as a variable length quantity // [0x4c, 0xc8] = OP_PUSHDATA1 200 @@ -192,7 +179,7 @@ func TestScriptCompression(t *testing.T) { for _, test := range tests { // Ensure the function to calculate the serialized size without // actually serializing the value is calculated properly. - gotSize := compressedScriptSize(test.uncompressed, test.version) + gotSize := compressedScriptSize(test.uncompressed) if gotSize != len(test.compressed) { t.Errorf("compressedScriptSize (%s): did not get "+ "expected size - got %d, want %d", test.name, @@ -203,7 +190,7 @@ func TestScriptCompression(t *testing.T) { // Ensure the script compresses to the expected bytes. gotCompressed := make([]byte, gotSize) gotBytesWritten := putCompressedScript(gotCompressed, - test.uncompressed, test.version) + test.uncompressed) if !bytes.Equal(gotCompressed, test.compressed) { t.Errorf("putCompressedScript (%s): did not get "+ "expected bytes - got %x, want %x", test.name, @@ -220,8 +207,7 @@ func TestScriptCompression(t *testing.T) { // Ensure the compressed script size is properly decoded from // the compressed script. - gotDecodedSize := decodeCompressedScriptSize(test.compressed, - test.version) + gotDecodedSize := decodeCompressedScriptSize(test.compressed) if gotDecodedSize != len(test.compressed) { t.Errorf("decodeCompressedScriptSize (%s): did not get "+ "expected size - got %d, want %d", test.name, @@ -230,7 +216,7 @@ func TestScriptCompression(t *testing.T) { } // Ensure the script decompresses to the expected bytes. - gotDecompressed := decompressScript(test.compressed, test.version) + gotDecompressed := decompressScript(test.compressed) if !bytes.Equal(gotDecompressed, test.uncompressed) { t.Errorf("decompressScript (%s): did not get expected "+ "bytes - got %x, want %x", test.name, @@ -246,13 +232,13 @@ func TestScriptCompressionErrors(t *testing.T) { t.Parallel() // A nil script must result in a decoded size of 0. - if gotSize := decodeCompressedScriptSize(nil, 1); gotSize != 0 { + if gotSize := decodeCompressedScriptSize(nil); gotSize != 0 { t.Fatalf("decodeCompressedScriptSize with nil script did not "+ "return 0 - got %d", gotSize) } // A nil script must result in a nil decompressed script. - if gotScript := decompressScript(nil, 1); gotScript != nil { + if gotScript := decompressScript(nil); gotScript != nil { t.Fatalf("decompressScript with nil script did not return nil "+ "decompressed script - got %x", gotScript) } @@ -261,7 +247,7 @@ func TestScriptCompressionErrors(t *testing.T) { // in an invalid pubkey must result in a nil decompressed script. compressedScript := hexToBytes("04012d74d0cb94344c9569c2e77901573d8d" + "7903c3ebec3a957724895dca52c6b4") - if gotScript := decompressScript(compressedScript, 1); gotScript != nil { + if gotScript := decompressScript(compressedScript); gotScript != nil { t.Fatalf("decompressScript with compressed pay-to-"+ "uncompressed-pubkey that is invalid did not return "+ "nil decompressed script - got %x", gotScript) @@ -352,48 +338,35 @@ func TestCompressedTxOut(t *testing.T) { t.Parallel() tests := []struct { - name string - amount uint64 - compAmount uint64 - pkScript []byte - compPkScript []byte - version int32 - compressed []byte + name string + amount uint64 + pkScript []byte + compressed []byte }{ { - name: "nulldata with 0 BTC", - amount: 0, - compAmount: 0, - pkScript: hexToBytes("6a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), - compPkScript: hexToBytes("286a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), - version: 1, - compressed: hexToBytes("00286a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), + name: "nulldata with 0 BTC", + amount: 0, + pkScript: hexToBytes("6a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), + compressed: hexToBytes("00286a200102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"), }, { - name: "pay-to-pubkey-hash dust", - amount: 546, - compAmount: 4911, - pkScript: hexToBytes("76a9141018853670f9f3b0582c5b9ee8ce93764ac32b9388ac"), - compPkScript: hexToBytes("001018853670f9f3b0582c5b9ee8ce93764ac32b93"), - version: 1, - compressed: hexToBytes("a52f001018853670f9f3b0582c5b9ee8ce93764ac32b93"), + name: "pay-to-pubkey-hash dust", + amount: 546, + pkScript: hexToBytes("76a9141018853670f9f3b0582c5b9ee8ce93764ac32b9388ac"), + compressed: hexToBytes("a52f001018853670f9f3b0582c5b9ee8ce93764ac32b93"), }, { - name: "pay-to-pubkey uncompressed 1 BTC", - amount: 100000000, - compAmount: 9, - pkScript: hexToBytes("4104192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453eac"), - compPkScript: hexToBytes("04192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), - version: 1, - compressed: hexToBytes("0904192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), + name: "pay-to-pubkey uncompressed 1 BTC", + amount: 100000000, + pkScript: hexToBytes("4104192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453eac"), + compressed: hexToBytes("0904192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), }, } for _, test := range tests { // Ensure the function to calculate the serialized size without // actually serializing the txout is calculated properly. - gotSize := compressedTxOutSize(test.amount, test.pkScript, - test.version, false) + gotSize := compressedTxOutSize(test.amount, test.pkScript) if gotSize != len(test.compressed) { t.Errorf("compressedTxOutSize (%s): did not get "+ "expected size - got %d, want %d", test.name, @@ -404,7 +377,7 @@ func TestCompressedTxOut(t *testing.T) { // Ensure the txout compresses to the expected value. gotCompressed := make([]byte, gotSize) gotBytesWritten := putCompressedTxOut(gotCompressed, - test.amount, test.pkScript, test.version, false) + test.amount, test.pkScript) if !bytes.Equal(gotCompressed, test.compressed) { t.Errorf("compressTxOut (%s): did not get expected "+ "bytes - got %x, want %x", test.name, @@ -420,24 +393,24 @@ func TestCompressedTxOut(t *testing.T) { } // Ensure the serialized bytes are decoded back to the expected - // compressed values. + // uncompressed values. gotAmount, gotScript, gotBytesRead, err := decodeCompressedTxOut( - test.compressed, test.version) + test.compressed) if err != nil { t.Errorf("decodeCompressedTxOut (%s): unexpected "+ "error: %v", test.name, err) continue } - if gotAmount != test.compAmount { + if gotAmount != test.amount { t.Errorf("decodeCompressedTxOut (%s): did not get "+ "expected amount - got %d, want %d", - test.name, gotAmount, test.compAmount) + test.name, gotAmount, test.amount) continue } - if !bytes.Equal(gotScript, test.compPkScript) { + if !bytes.Equal(gotScript, test.pkScript) { t.Errorf("decodeCompressedTxOut (%s): did not get "+ "expected script - got %x, want %x", - test.name, gotScript, test.compPkScript) + test.name, gotScript, test.pkScript) continue } if gotBytesRead != len(test.compressed) { @@ -446,23 +419,6 @@ func TestCompressedTxOut(t *testing.T) { test.name, gotBytesRead, len(test.compressed)) continue } - - // Ensure the compressed values decompress to the expected - // txout. - gotAmount = decompressTxOutAmount(gotAmount) - if gotAmount != test.amount { - t.Errorf("decompressTxOut (%s): did not get expected "+ - "value - got %d, want %d", test.name, gotAmount, - test.amount) - continue - } - gotScript = decompressScript(gotScript, test.version) - if !bytes.Equal(gotScript, test.pkScript) { - t.Errorf("decompressTxOut (%s): did not get expected "+ - "script - got %x, want %x", test.name, - gotScript, test.pkScript) - continue - } } } @@ -473,7 +429,7 @@ func TestTxOutCompressionErrors(t *testing.T) { // A compressed txout with missing compressed script must error. compressedTxOut := hexToBytes("00") - _, _, _, err := decodeCompressedTxOut(compressedTxOut, 1) + _, _, _, err := decodeCompressedTxOut(compressedTxOut) if !isDeserializeErr(err) { t.Fatalf("decodeCompressedTxOut with missing compressed script "+ "did not return expected error type - got %T, want "+ @@ -482,7 +438,7 @@ func TestTxOutCompressionErrors(t *testing.T) { // A compressed txout with short compressed script must error. compressedTxOut = hexToBytes("0010") - _, _, _, err = decodeCompressedTxOut(compressedTxOut, 1) + _, _, _, err = decodeCompressedTxOut(compressedTxOut) if !isDeserializeErr(err) { t.Fatalf("decodeCompressedTxOut with short compressed script "+ "did not return expected error type - got %T, want "+ diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index c9fee91c5e..7d83de596e 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -703,14 +703,12 @@ func (idx *AddrIndex) indexBlock(data writeIndexData, block *btcutil.Block, view // The view should always have the input since // the index contract requires it, however, be // safe and simply ignore any missing entries. - origin := &txIn.PreviousOutPoint - entry := view.LookupEntry(&origin.Hash) + entry := view.LookupEntry(txIn.PreviousOutPoint) if entry == nil { continue } - pkScript := entry.PkScriptByIndex(origin.Index) - idx.indexPkScript(data, pkScript, txIdx) + idx.indexPkScript(data, entry.PkScript(), txIdx) } } @@ -872,15 +870,14 @@ func (idx *AddrIndex) AddUnconfirmedTx(tx *btcutil.Tx, utxoView *blockchain.Utxo // transaction has already been validated and thus all inputs are // already known to exist. for _, txIn := range tx.MsgTx().TxIn { - entry := utxoView.LookupEntry(&txIn.PreviousOutPoint.Hash) + entry := utxoView.LookupEntry(txIn.PreviousOutPoint) if entry == nil { // Ignore missing entries. This should never happen // in practice since the function comments specifically // call out all inputs must be available. continue } - pkScript := entry.PkScriptByIndex(txIn.PreviousOutPoint.Index) - idx.indexUnconfirmedAddresses(pkScript, tx) + idx.indexUnconfirmedAddresses(entry.PkScript(), tx) } // Index addresses of all created outputs. diff --git a/blockchain/scriptval.go b/blockchain/scriptval.go index f7c7601122..8ba59a4214 100644 --- a/blockchain/scriptval.go +++ b/blockchain/scriptval.go @@ -55,31 +55,16 @@ out: for { select { case txVI := <-v.validateChan: - // Ensure the referenced input transaction is available. + // Ensure the referenced input utxo is available. txIn := txVI.txIn - originTxHash := &txIn.PreviousOutPoint.Hash - originTxIndex := txIn.PreviousOutPoint.Index - txEntry := v.utxoView.LookupEntry(originTxHash) - if txEntry == nil { - str := fmt.Sprintf("unable to find input "+ - "transaction %v referenced from "+ - "transaction %v", originTxHash, - txVI.tx.Hash()) - err := ruleError(ErrMissingTxOut, str) - v.sendResult(err) - break out - } - - // Ensure the referenced input transaction public key - // script is available. - pkScript := txEntry.PkScriptByIndex(originTxIndex) - if pkScript == nil { + utxo := v.utxoView.LookupEntry(txIn.PreviousOutPoint) + if utxo == nil { str := fmt.Sprintf("unable to find unspent "+ - "output %v script referenced from "+ + "output %v referenced from "+ "transaction %s:%d", txIn.PreviousOutPoint, txVI.tx.Hash(), txVI.txInIndex) - err := ruleError(ErrBadTxInput, str) + err := ruleError(ErrMissingTxOut, str) v.sendResult(err) break out } @@ -87,18 +72,19 @@ out: // Create a new script engine for the script pair. sigScript := txIn.SignatureScript witness := txIn.Witness - inputAmount := txEntry.AmountByIndex(originTxIndex) + pkScript := utxo.PkScript() + inputAmount := utxo.Amount() vm, err := txscript.NewEngine(pkScript, txVI.tx.MsgTx(), txVI.txInIndex, v.flags, v.sigCache, txVI.sigHashes, inputAmount) if err != nil { str := fmt.Sprintf("failed to parse input "+ - "%s:%d which references output %s:%d - "+ + "%s:%d which references output %v - "+ "%v (input witness %x, input script "+ "bytes %x, prev output script bytes %x)", - txVI.tx.Hash(), txVI.txInIndex, originTxHash, - originTxIndex, err, witness, sigScript, - pkScript) + txVI.tx.Hash(), txVI.txInIndex, + txIn.PreviousOutPoint, err, witness, + sigScript, pkScript) err := ruleError(ErrScriptMalformed, str) v.sendResult(err) break out @@ -107,12 +93,12 @@ out: // Execute the script pair. if err := vm.Execute(); err != nil { str := fmt.Sprintf("failed to validate input "+ - "%s:%d which references output %s:%d - "+ + "%s:%d which references output %v - "+ "%v (input witness %x, input script "+ "bytes %x, prev output script bytes %x)", txVI.tx.Hash(), txVI.txInIndex, - originTxHash, originTxIndex, err, - witness, sigScript, pkScript) + txIn.PreviousOutPoint, err, witness, + sigScript, pkScript) err := ruleError(ErrScriptValidation, str) v.sendResult(err) break out diff --git a/blockchain/testdata/277647.utxostore.bz2 b/blockchain/testdata/277647.utxostore.bz2 index 3807a71299845e4c6dd7f8c037652b316e4c38ff..c12b65e2a712c5a712ad4aef2ebdc9538a09e606 100644 GIT binary patch literal 36845 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 diff --git a/blockchain/upgrade.go b/blockchain/upgrade.go index 5970913929..253ca62e1e 100644 --- a/blockchain/upgrade.go +++ b/blockchain/upgrade.go @@ -7,7 +7,9 @@ package blockchain import ( "bytes" "container/list" + "errors" "fmt" + "time" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" @@ -23,6 +25,23 @@ const ( blockHdrOffset = 12 ) +// errInterruptRequested indicates that an operation was cancelled due +// to a user-requested interrupt. +var errInterruptRequested = errors.New("interrupt requested") + +// interruptRequested returns true when the provided channel has been closed. +// This simplifies early shutdown slightly since the caller can just use an if +// statement instead of a select. +func interruptRequested(interrupted <-chan struct{}) bool { + select { + case <-interrupted: + return true + default: + } + + return false +} + // blockChainContext represents a particular block's placement in the block // chain. This is used by the block index migration to track block metadata that // will be written to disk. @@ -204,3 +223,382 @@ func determineMainChainBlocks(blocksMap map[chainhash.Hash]*blockChainContext, t blocksMap[*nextHash].mainChain = true } } + +// deserializeUtxoEntryV0 decodes a utxo entry from the passed serialized byte +// slice according to the legacy version 0 format into a map of utxos keyed by +// the output index within the transaction. The map is necessary because the +// previous format encoded all unspent outputs for a transaction using a single +// entry, whereas the new format encodes each unspent output individually. +// +// The legacy format is as follows: +// +//

[,...] +// +// Field Type Size +// version VLQ variable +// block height VLQ variable +// header code VLQ variable +// unspentness bitmap []byte variable +// compressed txouts +// compressed amount VLQ variable +// compressed script []byte variable +// +// The serialized header code format is: +// bit 0 - containing transaction is a coinbase +// bit 1 - output zero is unspent +// bit 2 - output one is unspent +// bits 3-x - number of bytes in unspentness bitmap. When both bits 1 and 2 +// are unset, it encodes N-1 since there must be at least one unspent +// output. +// +// The rationale for the header code scheme is as follows: +// - Transactions which only pay to a single output and a change output are +// extremely common, thus an extra byte for the unspentness bitmap can be +// avoided for them by encoding those two outputs in the low order bits. +// - Given it is encoded as a VLQ which can encode values up to 127 with a +// single byte, that leaves 4 bits to represent the number of bytes in the +// unspentness bitmap while still only consuming a single byte for the +// header code. In other words, an unspentness bitmap with up to 120 +// transaction outputs can be encoded with a single-byte header code. +// This covers the vast majority of transactions. +// - Encoding N-1 bytes when both bits 1 and 2 are unset allows an additional +// 8 outpoints to be encoded before causing the header code to require an +// additional byte. +// +// Example 1: +// From tx in main blockchain: +// Blk 1, 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 +// +// 010103320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52 +// <><><><------------------------------------------------------------------> +// | | \--------\ | +// | height | compressed txout 0 +// version header code +// +// - version: 1 +// - height: 1 +// - header code: 0x03 (coinbase, output zero unspent, 0 bytes of unspentness) +// - unspentness: Nothing since it is zero bytes +// - compressed txout 0: +// - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) +// - 0x04: special script type pay-to-pubkey +// - 0x96...52: x-coordinate of the pubkey +// +// Example 2: +// From tx in main blockchain: +// Blk 113931, 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f +// +// 0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58 +// <><----><><><------------------------------------------><--------------------------------------------> +// | | | \-------------------\ | | +// version | \--------\ unspentness | compressed txout 2 +// height header code compressed txout 0 +// +// - version: 1 +// - height: 113931 +// - header code: 0x0a (output zero unspent, 1 byte in unspentness bitmap) +// - unspentness: [0x01] (bit 0 is set, so output 0+2 = 2 is unspent) +// NOTE: It's +2 since the first two outputs are encoded in the header code +// - compressed txout 0: +// - 0x12: VLQ-encoded compressed amount for 20000000 (0.2 BTC) +// - 0x00: special script type pay-to-pubkey-hash +// - 0xe2...8a: pubkey hash +// - compressed txout 2: +// - 0x8009: VLQ-encoded compressed amount for 15000000 (0.15 BTC) +// - 0x00: special script type pay-to-pubkey-hash +// - 0xb8...58: pubkey hash +// +// Example 3: +// From tx in main blockchain: +// Blk 338156, 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620 +// +// 0193d06c100000108ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6 +// <><----><><----><--------------------------------------------------> +// | | | \-----------------\ | +// version | \--------\ unspentness | +// height header code compressed txout 22 +// +// - version: 1 +// - height: 338156 +// - header code: 0x10 (2+1 = 3 bytes in unspentness bitmap) +// NOTE: It's +1 since neither bit 1 nor 2 are set, so N-1 is encoded. +// - unspentness: [0x00 0x00 0x10] (bit 20 is set, so output 20+2 = 22 is unspent) +// NOTE: It's +2 since the first two outputs are encoded in the header code +// - compressed txout 22: +// - 0x8ba5b9e763: VLQ-encoded compressed amount for 366875659 (3.66875659 BTC) +// - 0x01: special script type pay-to-script-hash +// - 0x1d...e6: script hash +func deserializeUtxoEntryV0(serialized []byte) (map[uint32]*UtxoEntry, error) { + // Deserialize the version. + // + // NOTE: Ignore version since it is no longer used in the new format. + _, bytesRead := deserializeVLQ(serialized) + offset := bytesRead + if offset >= len(serialized) { + return nil, errDeserialize("unexpected end of data after version") + } + + // Deserialize the block height. + blockHeight, bytesRead := deserializeVLQ(serialized[offset:]) + offset += bytesRead + if offset >= len(serialized) { + return nil, errDeserialize("unexpected end of data after height") + } + + // Deserialize the header code. + code, bytesRead := deserializeVLQ(serialized[offset:]) + offset += bytesRead + if offset >= len(serialized) { + return nil, errDeserialize("unexpected end of data after header") + } + + // Decode the header code. + // + // Bit 0 indicates whether the containing transaction is a coinbase. + // Bit 1 indicates output 0 is unspent. + // Bit 2 indicates output 1 is unspent. + // Bits 3-x encodes the number of non-zero unspentness bitmap bytes that + // follow. When both output 0 and 1 are spent, it encodes N-1. + isCoinBase := code&0x01 != 0 + output0Unspent := code&0x02 != 0 + output1Unspent := code&0x04 != 0 + numBitmapBytes := code >> 3 + if !output0Unspent && !output1Unspent { + numBitmapBytes++ + } + + // Ensure there are enough bytes left to deserialize the unspentness + // bitmap. + if uint64(len(serialized[offset:])) < numBitmapBytes { + return nil, errDeserialize("unexpected end of data for " + + "unspentness bitmap") + } + + // Add sparse output for unspent outputs 0 and 1 as needed based on the + // details provided by the header code. + var outputIndexes []uint32 + if output0Unspent { + outputIndexes = append(outputIndexes, 0) + } + if output1Unspent { + outputIndexes = append(outputIndexes, 1) + } + + // Decode the unspentness bitmap adding a sparse output for each unspent + // output. + for i := uint32(0); i < uint32(numBitmapBytes); i++ { + unspentBits := serialized[offset] + for j := uint32(0); j < 8; j++ { + if unspentBits&0x01 != 0 { + // The first 2 outputs are encoded via the + // header code, so adjust the output number + // accordingly. + outputNum := 2 + i*8 + j + outputIndexes = append(outputIndexes, outputNum) + } + unspentBits >>= 1 + } + offset++ + } + + // Map to hold all of the converted outputs. + entries := make(map[uint32]*UtxoEntry) + + // All entries will need to potentially be marked as a coinbase. + var packedFlags txoFlags + if isCoinBase { + packedFlags |= tfCoinBase + } + + // Decode and add all of the utxos. + for i, outputIndex := range outputIndexes { + // Decode the next utxo. + amount, pkScript, bytesRead, err := decodeCompressedTxOut( + serialized[offset:]) + if err != nil { + return nil, errDeserialize(fmt.Sprintf("unable to "+ + "decode utxo at index %d: %v", i, err)) + } + offset += bytesRead + + // Create a new utxo entry with the details deserialized above. + entries[outputIndex] = &UtxoEntry{ + amount: int64(amount), + pkScript: pkScript, + blockHeight: int32(blockHeight), + packedFlags: packedFlags, + } + } + + return entries, nil +} + +// upgradeUtxoSetToV2 migrates the utxo set entries from version 1 to 2 in +// batches. It is guaranteed to updated if this returns without failure. +func upgradeUtxoSetToV2(db database.DB, interrupt <-chan struct{}) error { + // Hardcoded bucket names so updates to the global values do not affect + // old upgrades. + var ( + v1BucketName = []byte("utxoset") + v2BucketName = []byte("utxosetv2") + ) + + log.Infof("Upgrading utxo set to v2. This will take a while...") + start := time.Now() + + // Create the new utxo set bucket as needed. + err := db.Update(func(dbTx database.Tx) error { + _, err := dbTx.Metadata().CreateBucketIfNotExists(v2BucketName) + return err + }) + if err != nil { + return err + } + + // doBatch contains the primary logic for upgrading the utxo set from + // version 1 to 2 in batches. This is done because the utxo set can be + // huge and thus attempting to migrate in a single database transaction + // would result in massive memory usage and could potentially crash on + // many systems due to ulimits. + // + // It returns the number of utxos processed. + const maxUtxos = 200000 + doBatch := func(dbTx database.Tx) (uint32, error) { + v1Bucket := dbTx.Metadata().Bucket(v1BucketName) + v2Bucket := dbTx.Metadata().Bucket(v2BucketName) + v1Cursor := v1Bucket.Cursor() + + // Migrate utxos so long as the max number of utxos for this + // batch has not been exceeded. + var numUtxos uint32 + for ok := v1Cursor.First(); ok && numUtxos < maxUtxos; ok = + v1Cursor.Next() { + + // Old key was the transaction hash. + oldKey := v1Cursor.Key() + var txHash chainhash.Hash + copy(txHash[:], oldKey) + + // Deserialize the old entry which included all utxos + // for the given transaction. + utxos, err := deserializeUtxoEntryV0(v1Cursor.Value()) + if err != nil { + return 0, err + } + + // Add an entry for each utxo into the new bucket using + // the new format. + for txOutIdx, utxo := range utxos { + reserialized, err := serializeUtxoEntry(utxo) + if err != nil { + return 0, err + } + + key := outpointKey(wire.OutPoint{ + Hash: txHash, + Index: txOutIdx, + }) + err = v2Bucket.Put(*key, reserialized) + // NOTE: The key is intentionally not recycled + // here since the database interface contract + // prohibits modifications. It will be garbage + // collected normally when the database is done + // with it. + if err != nil { + return 0, err + } + } + + // Remove old entry. + err = v1Bucket.Delete(oldKey) + if err != nil { + return 0, err + } + + numUtxos += uint32(len(utxos)) + + if interruptRequested(interrupt) { + // No error here so the database transaction + // is not cancelled and therefore outstanding + // work is written to disk. + break + } + } + + return numUtxos, nil + } + + // Migrate all entries in batches for the reasons mentioned above. + var totalUtxos uint64 + for { + var numUtxos uint32 + err := db.Update(func(dbTx database.Tx) error { + var err error + numUtxos, err = doBatch(dbTx) + return err + }) + if err != nil { + return err + } + + if interruptRequested(interrupt) { + return errInterruptRequested + } + + if numUtxos == 0 { + break + } + + totalUtxos += uint64(numUtxos) + log.Infof("Migrated %d utxos (%d total)", numUtxos, totalUtxos) + } + + // Remove the old bucket and update the utxo set version once it has + // been fully migrated. + err = db.Update(func(dbTx database.Tx) error { + err := dbTx.Metadata().DeleteBucket(v1BucketName) + if err != nil { + return err + } + + return dbPutVersion(dbTx, utxoSetVersionKeyName, 2) + }) + if err != nil { + return err + } + + seconds := int64(time.Since(start) / time.Second) + log.Infof("Done upgrading utxo set. Total utxos: %d in %d seconds", + totalUtxos, seconds) + return nil +} + +// maybeUpgradeDbBuckets checks the database version of the buckets used by this +// package and performs any needed upgrades to bring them to the latest version. +// +// All buckets used by this package are guaranteed to be the latest version if +// this function returns without error. +func (b *BlockChain) maybeUpgradeDbBuckets(interrupt <-chan struct{}) error { + // Load or create bucket versions as needed. + var utxoSetVersion uint32 + err := b.db.Update(func(dbTx database.Tx) error { + // Load the utxo set version from the database or create it and + // initialize it to version 1 if it doesn't exist. + var err error + utxoSetVersion, err = dbFetchOrCreateVersion(dbTx, + utxoSetVersionKeyName, 1) + return err + }) + if err != nil { + return err + } + + // Update the utxo set to v2 if needed. + if utxoSetVersion < 2 { + if err := upgradeUtxoSetToV2(b.db, interrupt); err != nil { + return err + } + } + + return nil +} diff --git a/blockchain/upgrade_test.go b/blockchain/upgrade_test.go new file mode 100644 index 0000000000..97e7f55c35 --- /dev/null +++ b/blockchain/upgrade_test.go @@ -0,0 +1,116 @@ +// Copyright (c) 2015-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "reflect" + "testing" +) + +// TestDeserializeUtxoEntryV0 ensures deserializing unspent trasaction output +// entries from the legacy version 0 format works as expected. +func TestDeserializeUtxoEntryV0(t *testing.T) { + tests := []struct { + name string + entries map[uint32]*UtxoEntry + serialized []byte + }{ + // From tx in main blockchain: + // 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 + { + name: "Only output 0, coinbase", + entries: map[uint32]*UtxoEntry{ + 0: { + amount: 5000000000, + pkScript: hexToBytes("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac"), + blockHeight: 1, + packedFlags: tfCoinBase, + }, + }, + serialized: hexToBytes("010103320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"), + }, + // From tx in main blockchain: + // 8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb + { + name: "Only output 1, not coinbase", + entries: map[uint32]*UtxoEntry{ + 1: { + amount: 1000000, + pkScript: hexToBytes("76a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac"), + blockHeight: 100001, + packedFlags: 0, + }, + }, + serialized: hexToBytes("01858c21040700ee8bd501094a7d5ca318da2506de35e1cb025ddc"), + }, + // Adapted from tx in main blockchain: + // df3f3f442d9699857f7f49de4ff0b5d0f3448bec31cdc7b5bf6d25f2abd637d5 + { + name: "Only output 2, coinbase", + entries: map[uint32]*UtxoEntry{ + 2: { + amount: 100937281, + pkScript: hexToBytes("76a914da33f77cee27c2a975ed5124d7e4f7f97513510188ac"), + blockHeight: 99004, + packedFlags: tfCoinBase, + }, + }, + serialized: hexToBytes("0185843c010182b095bf4100da33f77cee27c2a975ed5124d7e4f7f975135101"), + }, + // Adapted from tx in main blockchain: + // 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f + { + name: "outputs 0 and 2 not coinbase", + entries: map[uint32]*UtxoEntry{ + 0: { + amount: 20000000, + pkScript: hexToBytes("76a914e2ccd6ec7c6e2e581349c77e067385fa8236bf8a88ac"), + blockHeight: 113931, + packedFlags: 0, + }, + 2: { + amount: 15000000, + pkScript: hexToBytes("76a914b8025be1b3efc63b0ad48e7f9f10e87544528d5888ac"), + blockHeight: 113931, + packedFlags: 0, + }, + }, + serialized: hexToBytes("0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58"), + }, + // Adapted from tx in main blockchain: + // 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620 + { + name: "Only output 22, not coinbase", + entries: map[uint32]*UtxoEntry{ + 22: { + amount: 366875659, + pkScript: hexToBytes("a9141dd46a006572d820e448e12d2bbb38640bc718e687"), + blockHeight: 338156, + packedFlags: 0, + }, + }, + serialized: hexToBytes("0193d06c100000108ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6"), + }, + } + + for i, test := range tests { + // Deserialize to map of utxos keyed by the output index. + entries, err := deserializeUtxoEntryV0(test.serialized) + if err != nil { + t.Errorf("deserializeUtxoEntryV0 #%d (%s) unexpected "+ + "error: %v", i, test.name, err) + continue + } + + // Ensure the deserialized entry has the same properties as the + // ones in the test entry. + if !reflect.DeepEqual(entries, test.entries) { + t.Errorf("deserializeUtxoEntryV0 #%d (%s) unexpected "+ + "entries: got %v, want %v", i, test.name, + entries, test.entries) + continue + } + } +} diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index f3d45cbb30..5af8423439 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -10,179 +10,104 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" ) -// utxoOutput houses details about an individual unspent transaction output such -// as whether or not it is spent, its public key script, and how much it pays. -// -// Standard public key scripts are stored in the database using a compressed -// format. Since the vast majority of scripts are of the standard form, a fairly -// significant savings is achieved by discarding the portions of the standard -// scripts that can be reconstructed. -// -// Also, since it is common for only a specific output in a given utxo entry to -// be referenced from a redeeming transaction, the script and amount for a given -// output is not uncompressed until the first time it is accessed. This -// provides a mechanism to avoid the overhead of needlessly uncompressing all -// outputs for a given utxo entry at the time of load. -type utxoOutput struct { - spent bool // Output is spent. - compressed bool // The amount and public key script are compressed. - amount int64 // The amount of the output. - pkScript []byte // The public key script for the output. -} +// txoFlags is a bitmask defining additional information and state for a +// transaction output in a utxo view. +type txoFlags uint8 -// maybeDecompress decompresses the amount and public key script fields of the -// utxo and marks it decompressed if needed. -func (o *utxoOutput) maybeDecompress(version int32) { - // Nothing to do if it's not compressed. - if !o.compressed { - return - } +const ( + // tfCoinBase indicates that a txout was contained in a coinbase tx. + tfCoinBase txoFlags = 1 << iota - o.amount = int64(decompressTxOutAmount(uint64(o.amount))) - o.pkScript = decompressScript(o.pkScript, version) - o.compressed = false -} + // tfSpent indicates that a txout is spent. + tfSpent -// UtxoEntry contains contextual information about an unspent transaction such -// as whether or not it is a coinbase transaction, which block it was found in, -// and the spent status of its outputs. + // tfModified indicates that a txout has been modified since it was + // loaded. + tfModified +) + +// UtxoEntry houses details about an individual transaction output in a utxo +// view such as whether or not it was contained in a coinbase tx, the height of +// the block that contains the tx, whether or not it is spent, its public key +// script, and how much it pays. type UtxoEntry struct { - modified bool // Entry changed since load. - version int32 // The version of this tx. - isCoinBase bool // Whether entry is a coinbase tx. - blockHeight int32 // Height of block containing tx. - sparseOutputs map[uint32]*utxoOutput // Sparse map of unspent outputs. + // NOTE: Additions, deletions, or modifications to the order of the + // definitions in this struct should not be changed without considering + // how it affects alignment on 64-bit platforms. The current order is + // specifically crafted to result in minimal padding. There will be a + // lot of these in memory, so a few extra bytes of padding adds up. + + amount int64 + pkScript []byte // The public key script for the output. + blockHeight int32 // Height of block containing tx. + + // packedFlags contains additional info about output such as whether it + // is a coinbase, whether it is spent, and whether it has been modified + // since it was loaded. This approach is used in order to reduce memory + // usage since there will be a lot of these in memory. + packedFlags txoFlags } -// Version returns the version of the transaction the utxo represents. -func (entry *UtxoEntry) Version() int32 { - return entry.version +// isModified returns whether or not the output has been modified since it was +// loaded. +func (entry *UtxoEntry) isModified() bool { + return entry.packedFlags&tfModified == tfModified } -// IsCoinBase returns whether or not the transaction the utxo entry represents -// is a coinbase. +// IsCoinBase returns whether or not the output was contained in a coinbase +// transaction. func (entry *UtxoEntry) IsCoinBase() bool { - return entry.isCoinBase + return entry.packedFlags&tfCoinBase == tfCoinBase } -// BlockHeight returns the height of the block containing the transaction the -// utxo entry represents. +// BlockHeight returns the height of the block containing the output. func (entry *UtxoEntry) BlockHeight() int32 { return entry.blockHeight } -// IsOutputSpent returns whether or not the provided output index has been -// spent based upon the current state of the unspent transaction output view -// the entry was obtained from. -// -// Returns true if the output index references an output that does not exist -// either due to it being invalid or because the output is not part of the view -// due to previously being spent/pruned. -func (entry *UtxoEntry) IsOutputSpent(outputIndex uint32) bool { - output, ok := entry.sparseOutputs[outputIndex] - if !ok { - return true - } - - return output.spent +// IsSpent returns whether or not the output has been spent based upon the +// current state of the unspent transaction output view it was obtained from. +func (entry *UtxoEntry) IsSpent() bool { + return entry.packedFlags&tfSpent == tfSpent } -// SpendOutput marks the output at the provided index as spent. Specifying an -// output index that does not exist will not have any effect. -func (entry *UtxoEntry) SpendOutput(outputIndex uint32) { - output, ok := entry.sparseOutputs[outputIndex] - if !ok { - return - } - +// Spend marks the output as spent. Spending an output that is already spent +// has no effect. +func (entry *UtxoEntry) Spend() { // Nothing to do if the output is already spent. - if output.spent { + if entry.IsSpent() { return } - entry.modified = true - output.spent = true + // Mark the output as spent and modified. + entry.packedFlags |= tfSpent | tfModified } -// IsFullySpent returns whether or not the transaction the utxo entry represents -// is fully spent. -func (entry *UtxoEntry) IsFullySpent() bool { - // The entry is not fully spent if any of the outputs are unspent. - for _, output := range entry.sparseOutputs { - if !output.spent { - return false - } - } - - return true +// Amount returns the amount of the output. +func (entry *UtxoEntry) Amount() int64 { + return entry.amount } -// AmountByIndex returns the amount of the provided output index. -// -// Returns 0 if the output index references an output that does not exist -// either due to it being invalid or because the output is not part of the view -// due to previously being spent/pruned. -func (entry *UtxoEntry) AmountByIndex(outputIndex uint32) int64 { - output, ok := entry.sparseOutputs[outputIndex] - if !ok { - return 0 - } - - // Ensure the output is decompressed before returning the amount. - output.maybeDecompress(entry.version) - return output.amount +// PkScript returns the public key script for the output. +func (entry *UtxoEntry) PkScript() []byte { + return entry.pkScript } -// PkScriptByIndex returns the public key script for the provided output index. -// -// Returns nil if the output index references an output that does not exist -// either due to it being invalid or because the output is not part of the view -// due to previously being spent/pruned. -func (entry *UtxoEntry) PkScriptByIndex(outputIndex uint32) []byte { - output, ok := entry.sparseOutputs[outputIndex] - if !ok { - return nil - } - - // Ensure the output is decompressed before returning the script. - output.maybeDecompress(entry.version) - return output.pkScript -} - -// Clone returns a deep copy of the utxo entry. +// Clone returns a shallow copy of the utxo entry. func (entry *UtxoEntry) Clone() *UtxoEntry { if entry == nil { return nil } - newEntry := &UtxoEntry{ - version: entry.version, - isCoinBase: entry.isCoinBase, - blockHeight: entry.blockHeight, - sparseOutputs: make(map[uint32]*utxoOutput), - } - for outputIndex, output := range entry.sparseOutputs { - newEntry.sparseOutputs[outputIndex] = &utxoOutput{ - spent: output.spent, - compressed: output.compressed, - amount: output.amount, - pkScript: output.pkScript, - } - } - return newEntry -} - -// newUtxoEntry returns a new unspent transaction output entry with the provided -// coinbase flag and block height ready to have unspent outputs added. -func newUtxoEntry(version int32, isCoinBase bool, blockHeight int32) *UtxoEntry { return &UtxoEntry{ - version: version, - isCoinBase: isCoinBase, - blockHeight: blockHeight, - sparseOutputs: make(map[uint32]*utxoOutput), + amount: entry.amount, + pkScript: entry.pkScript, + blockHeight: entry.blockHeight, + packedFlags: entry.packedFlags, } } @@ -194,7 +119,7 @@ func newUtxoEntry(version int32, isCoinBase bool, blockHeight int32) *UtxoEntry // The unspent outputs are needed by other transactions for things such as // script validation and double spend prevention. type UtxoViewpoint struct { - entries map[chainhash.Hash]*UtxoEntry + entries map[wire.OutPoint]*UtxoEntry bestHash chainhash.Hash } @@ -210,17 +135,60 @@ func (view *UtxoViewpoint) SetBestHash(hash *chainhash.Hash) { view.bestHash = *hash } -// LookupEntry returns information about a given transaction according to the -// current state of the view. It will return nil if the passed transaction -// hash does not exist in the view or is otherwise not available such as when -// it has been disconnected during a reorg. -func (view *UtxoViewpoint) LookupEntry(txHash *chainhash.Hash) *UtxoEntry { - entry, ok := view.entries[*txHash] - if !ok { - return nil +// LookupEntry returns information about a given transaction output according to +// the current state of the view. It will return nil if the passed output does +// not exist in the view or is otherwise not available such as when it has been +// disconnected during a reorg. +func (view *UtxoViewpoint) LookupEntry(outpoint wire.OutPoint) *UtxoEntry { + return view.entries[outpoint] +} + +// addTxOut adds the specified output to the view if it is not provably +// unspendable. When the view already has an entry for the output, it will be +// marked unspent. All fields will be updated for existing entries since it's +// possible it has changed during a reorg. +func (view *UtxoViewpoint) addTxOut(outpoint wire.OutPoint, txOut *wire.TxOut, isCoinBase bool, blockHeight int32) { + // Don't add provably unspendable outputs. + if txscript.IsUnspendable(txOut.PkScript) { + return } - return entry + // Update existing entries. All fields are updated because it's + // possible (although extremely unlikely) that the existing entry is + // being replaced by a different transaction with the same hash. This + // is allowed so long as the previous transaction is fully spent. + entry := view.LookupEntry(outpoint) + if entry == nil { + entry = new(UtxoEntry) + view.entries[outpoint] = entry + } + + entry.amount = txOut.Value + entry.pkScript = txOut.PkScript + entry.blockHeight = blockHeight + entry.packedFlags = tfModified + if isCoinBase { + entry.packedFlags |= tfCoinBase + } +} + +// AddTxOut adds the specified output of the passed transaction to the view if +// it exists and is not provably unspendable. When the view already has an +// entry for the output, it will be marked unspent. All fields will be updated +// for existing entries since it's possible it has changed during a reorg. +func (view *UtxoViewpoint) AddTxOut(tx *btcutil.Tx, txOutIdx uint32, blockHeight int32) { + // Can't add an output for an out of bounds index. + if txOutIdx >= uint32(len(tx.MsgTx().TxOut)) { + return + } + + // Update existing entries. All fields are updated because it's + // possible (although extremely unlikely) that the existing entry is + // being replaced by a different transaction with the same hash. This + // is allowed so long as the previous transaction is fully spent. + prevOut := wire.OutPoint{Hash: *tx.Hash(), Index: txOutIdx} + txOut := tx.MsgTx().TxOut[txOutIdx] + view.addTxOut(prevOut, txOut, IsCoinBase(tx), blockHeight) } // AddTxOuts adds all outputs in the passed transaction which are not provably @@ -228,45 +196,18 @@ func (view *UtxoViewpoint) LookupEntry(txHash *chainhash.Hash) *UtxoEntry { // outputs, they are simply marked unspent. All fields will be updated for // existing entries since it's possible it has changed during a reorg. func (view *UtxoViewpoint) AddTxOuts(tx *btcutil.Tx, blockHeight int32) { - // When there are not already any utxos associated with the transaction, - // add a new entry for it to the view. - entry := view.LookupEntry(tx.Hash()) - if entry == nil { - entry = newUtxoEntry(tx.MsgTx().Version, IsCoinBase(tx), - blockHeight) - view.entries[*tx.Hash()] = entry - } else { - entry.blockHeight = blockHeight - } - entry.modified = true - // Loop all of the transaction outputs and add those which are not // provably unspendable. + isCoinBase := IsCoinBase(tx) + prevOut := wire.OutPoint{Hash: *tx.Hash()} for txOutIdx, txOut := range tx.MsgTx().TxOut { - if txscript.IsUnspendable(txOut.PkScript) { - continue - } - // Update existing entries. All fields are updated because it's // possible (although extremely unlikely) that the existing // entry is being replaced by a different transaction with the // same hash. This is allowed so long as the previous // transaction is fully spent. - if output, ok := entry.sparseOutputs[uint32(txOutIdx)]; ok { - output.spent = false - output.compressed = false - output.amount = txOut.Value - output.pkScript = txOut.PkScript - continue - } - - // Add the unspent transaction output. - entry.sparseOutputs[uint32(txOutIdx)] = &utxoOutput{ - spent: false, - compressed: false, - amount: txOut.Value, - pkScript: txOut.PkScript, - } + prevOut.Index = uint32(txOutIdx) + view.addTxOut(prevOut, txOut, isCoinBase, blockHeight) } } @@ -287,39 +228,30 @@ func (view *UtxoViewpoint) connectTransaction(tx *btcutil.Tx, blockHeight int32, // if a slice was provided for the spent txout details, append an entry // to it. for _, txIn := range tx.MsgTx().TxIn { - originIndex := txIn.PreviousOutPoint.Index - entry := view.entries[txIn.PreviousOutPoint.Hash] - // Ensure the referenced utxo exists in the view. This should // never happen unless there is a bug is introduced in the code. + entry := view.entries[txIn.PreviousOutPoint] if entry == nil { return AssertError(fmt.Sprintf("view missing input %v", txIn.PreviousOutPoint)) } - entry.SpendOutput(originIndex) - - // Don't create the stxo details if not requested. - if stxos == nil { - continue - } - // Populate the stxo details using the utxo entry. When the - // transaction is fully spent, set the additional stxo fields - // accordingly since those details will no longer be available - // in the utxo set. - var stxo = spentTxOut{ - compressed: false, - version: entry.Version(), - amount: entry.AmountByIndex(originIndex), - pkScript: entry.PkScriptByIndex(originIndex), - } - if entry.IsFullySpent() { - stxo.height = entry.BlockHeight() - stxo.isCoinBase = entry.IsCoinBase() + // Only create the stxo details if requested. + if stxos != nil { + // Populate the stxo details using the utxo entry. + var stxo = spentTxOut{ + amount: entry.Amount(), + pkScript: entry.PkScript(), + height: entry.BlockHeight(), + isCoinBase: entry.IsCoinBase(), + } + *stxos = append(*stxos, stxo) } - // Append the entry to the provided spent txouts slice. - *stxos = append(*stxos, stxo) + // Mark the entry as spent. This is not done until after the + // relevant details have been accessed since spending it might + // clear the fields from memory in the future. + entry.Spend() } // Add the transaction's outputs as available utxos. @@ -346,11 +278,37 @@ func (view *UtxoViewpoint) connectTransactions(block *btcutil.Block, stxos *[]sp return nil } +// fetchEntryByHash attempts to find any available utxo for the given hash by +// searching the entire set of possible outputs for the given hash. It checks +// the view first and then falls back to the database if needed. +func (view *UtxoViewpoint) fetchEntryByHash(db database.DB, hash *chainhash.Hash) (*UtxoEntry, error) { + // First attempt to find a utxo with the provided hash in the view. + prevOut := wire.OutPoint{Hash: *hash} + for idx := uint32(0); idx < MaxOutputsPerBlock; idx++ { + prevOut.Index = idx + entry := view.LookupEntry(prevOut) + if entry != nil { + return entry, nil + } + } + + // Check the database since it doesn't exist in the view. This will + // often by the case since only specifically referenced utxos are loaded + // into the view. + var entry *UtxoEntry + err := db.View(func(dbTx database.Tx) error { + var err error + entry, err = dbFetchUtxoEntryByHash(dbTx, hash) + return err + }) + return entry, err +} + // disconnectTransactions updates the view by removing all of the transactions // created by the passed block, restoring all utxos the transactions spent by // using the provided spent txo information, and setting the best hash for the // view to the block before the passed block. -func (view *UtxoViewpoint) disconnectTransactions(block *btcutil.Block, stxos []spentTxOut) error { +func (view *UtxoViewpoint) disconnectTransactions(db database.DB, block *btcutil.Block, stxos []spentTxOut) error { // Sanity check the correct number of stxos are provided. if len(stxos) != countSpentOutputs(block) { return AssertError("disconnectTransactions called with bad " + @@ -365,25 +323,52 @@ func (view *UtxoViewpoint) disconnectTransactions(block *btcutil.Block, stxos [] for txIdx := len(transactions) - 1; txIdx > -1; txIdx-- { tx := transactions[txIdx] - // Clear this transaction from the view if it already exists or - // create a new empty entry for when it does not. This is done - // because the code relies on its existence in the view in order - // to signal modifications have happened. - isCoinbase := txIdx == 0 - entry := view.entries[*tx.Hash()] - if entry == nil { - entry = newUtxoEntry(tx.MsgTx().Version, isCoinbase, - block.Height()) - view.entries[*tx.Hash()] = entry + // All entries will need to potentially be marked as a coinbase. + var packedFlags txoFlags + isCoinBase := txIdx == 0 + if isCoinBase { + packedFlags |= tfCoinBase + } + + // Mark all of the spendable outputs originally created by the + // transaction as spent. It is instructive to note that while + // the outputs aren't actually being spent here, rather they no + // longer exist, since a pruned utxo set is used, there is no + // practical difference between a utxo that does not exist and + // one that has been spent. + // + // When the utxo does not already exist in the view, add an + // entry for it and then mark it spent. This is done because + // the code relies on its existence in the view in order to + // signal modifications have happened. + txHash := tx.Hash() + prevOut := wire.OutPoint{Hash: *txHash} + for txOutIdx, txOut := range tx.MsgTx().TxOut { + if txscript.IsUnspendable(txOut.PkScript) { + continue + } + + prevOut.Index = uint32(txOutIdx) + entry := view.entries[prevOut] + if entry == nil { + entry = &UtxoEntry{ + amount: txOut.Value, + pkScript: txOut.PkScript, + blockHeight: block.Height(), + packedFlags: packedFlags, + } + + view.entries[prevOut] = entry + } + + entry.Spend() } - entry.modified = true - entry.sparseOutputs = make(map[uint32]*utxoOutput) // Loop backwards through all of the transaction inputs (except // for the coinbase which has no inputs) and unspend the // referenced txos. This is necessary to match the order of the // spent txout entries. - if isCoinbase { + if isCoinBase { continue } for txInIdx := len(tx.MsgTx().TxIn) - 1; txInIdx > -1; txInIdx-- { @@ -393,40 +378,57 @@ func (view *UtxoViewpoint) disconnectTransactions(block *btcutil.Block, stxos [] stxoIdx-- // When there is not already an entry for the referenced - // transaction in the view, it means it was fully spent, + // output in the view, it means it was previously spent, // so create a new utxo entry in order to resurrect it. - txIn := tx.MsgTx().TxIn[txInIdx] - originHash := &txIn.PreviousOutPoint.Hash - originIndex := txIn.PreviousOutPoint.Index - entry := view.entries[*originHash] + originOut := &tx.MsgTx().TxIn[txInIdx].PreviousOutPoint + entry := view.entries[*originOut] if entry == nil { - entry = newUtxoEntry(stxo.version, - stxo.isCoinBase, stxo.height) - view.entries[*originHash] = entry + entry = new(UtxoEntry) + view.entries[*originOut] = entry } - // Mark the entry as modified since it is either new - // or will be changed below. - entry.modified = true - - // Restore the specific utxo using the stxo data from - // the spend journal if it doesn't already exist in the - // view. - output, ok := entry.sparseOutputs[originIndex] - if !ok { - // Add the unspent transaction output. - entry.sparseOutputs[originIndex] = &utxoOutput{ - spent: false, - compressed: stxo.compressed, - amount: stxo.amount, - pkScript: stxo.pkScript, + // The legacy v1 spend journal format only stored the + // coinbase flag and height when the output was the last + // unspent output of the transaction. As a result, when + // the information is missing, search for it by scanning + // all possible outputs of the transaction since it must + // be in one of them. + // + // It should be noted that this is quite inefficient, + // but it realistically will almost never run since all + // new entries include the information for all outputs + // and thus the only way this will be hit is if a long + // enough reorg happens such that a block with the old + // spend data is being disconnected. The probability of + // that in practice is extremely low to begin with and + // becomes vanishingly small the more new blocks are + // connected. In the case of a fresh database that has + // only ever run with the new v2 format, this code path + // will never run. + if stxo.height == 0 { + utxo, err := view.fetchEntryByHash(db, txHash) + if err != nil { + return err } - continue + if utxo == nil { + return AssertError(fmt.Sprintf("unable "+ + "to resurrect legacy stxo %v", + *originOut)) + } + + stxo.height = utxo.BlockHeight() + stxo.isCoinBase = utxo.IsCoinBase() } - // Mark the existing referenced transaction output as - // unspent. - output.spent = false + // Restore the utxo using the stxo data from the spend + // journal and mark it as modified. + entry.amount = stxo.amount + entry.pkScript = stxo.pkScript + entry.blockHeight = stxo.height + entry.packedFlags = tfModified + if stxo.isCoinBase { + entry.packedFlags |= tfCoinBase + } } } @@ -436,88 +438,94 @@ func (view *UtxoViewpoint) disconnectTransactions(block *btcutil.Block, stxos [] return nil } +// RemoveEntry removes the given transaction output from the current state of +// the view. It will have no effect if the passed output does not exist in the +// view. +func (view *UtxoViewpoint) RemoveEntry(outpoint wire.OutPoint) { + delete(view.entries, outpoint) +} + // Entries returns the underlying map that stores of all the utxo entries. -func (view *UtxoViewpoint) Entries() map[chainhash.Hash]*UtxoEntry { +func (view *UtxoViewpoint) Entries() map[wire.OutPoint]*UtxoEntry { return view.entries } // commit prunes all entries marked modified that are now fully spent and marks // all entries as unmodified. func (view *UtxoViewpoint) commit() { - for txHash, entry := range view.entries { - if entry == nil || (entry.modified && entry.IsFullySpent()) { - delete(view.entries, txHash) + for outpoint, entry := range view.entries { + if entry == nil || (entry.isModified() && entry.IsSpent()) { + delete(view.entries, outpoint) continue } - entry.modified = false + entry.packedFlags ^= tfModified } } // fetchUtxosMain fetches unspent transaction output data about the provided -// set of transactions from the point of view of the end of the main chain at -// the time of the call. +// set of outpoints from the point of view of the end of the main chain at the +// time of the call. // // Upon completion of this function, the view will contain an entry for each -// requested transaction. Fully spent transactions, or those which otherwise -// don't exist, will result in a nil entry in the view. -func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, txSet map[chainhash.Hash]struct{}) error { - // Nothing to do if there are no requested hashes. - if len(txSet) == 0 { +// requested outpoint. Spent outputs, or those which otherwise don't exist, +// will result in a nil entry in the view. +func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints map[wire.OutPoint]struct{}) error { + // Nothing to do if there are no requested outputs. + if len(outpoints) == 0 { return nil } - // Load the unspent transaction output information for the requested set - // of transactions from the point of view of the end of the main chain. + // Load the requested set of unspent transaction outputs from the point + // of view of the end of the main chain. // // NOTE: Missing entries are not considered an error here and instead // will result in nil entries in the view. This is intentionally done - // since other code uses the presence of an entry in the store as a way - // to optimize spend and unspend updates to apply only to the specific - // utxos that the caller needs access to. + // so other code can use the presence of an entry in the store as a way + // to unnecessarily avoid attempting to reload it from the database. return db.View(func(dbTx database.Tx) error { - for hash := range txSet { - hashCopy := hash - entry, err := dbFetchUtxoEntry(dbTx, &hashCopy) + for outpoint := range outpoints { + entry, err := dbFetchUtxoEntry(dbTx, outpoint) if err != nil { return err } - view.entries[hash] = entry + view.entries[outpoint] = entry } return nil }) } -// fetchUtxos loads utxo details about provided set of transaction hashes into -// the view from the database as needed unless they already exist in the view in -// which case they are ignored. -func (view *UtxoViewpoint) fetchUtxos(db database.DB, txSet map[chainhash.Hash]struct{}) error { - // Nothing to do if there are no requested hashes. - if len(txSet) == 0 { +// fetchUtxos loads the unspent transaction outputs for the provided set of +// outputs into the view from the database as needed unless they already exist +// in the view in which case they are ignored. +func (view *UtxoViewpoint) fetchUtxos(db database.DB, outpoints map[wire.OutPoint]struct{}) error { + // Nothing to do if there are no requested outputs. + if len(outpoints) == 0 { return nil } // Filter entries that are already in the view. - txNeededSet := make(map[chainhash.Hash]struct{}) - for hash := range txSet { + neededSet := make(map[wire.OutPoint]struct{}) + for outpoint := range outpoints { // Already loaded into the current view. - if _, ok := view.entries[hash]; ok { + if _, ok := view.entries[outpoint]; ok { continue } - txNeededSet[hash] = struct{}{} + neededSet[outpoint] = struct{}{} } // Request the input utxos from the database. - return view.fetchUtxosMain(db, txNeededSet) + return view.fetchUtxosMain(db, neededSet) } -// fetchInputUtxos loads utxo details about the input transactions referenced -// by the transactions in the given block into the view from the database as -// needed. In particular, referenced entries that are earlier in the block are -// added to the view and entries that are already in the view are not modified. +// fetchInputUtxos loads the unspent transaction outputs for the inputs +// referenced by the transactions in the given block into the view from the +// database as needed. In particular, referenced entries that are earlier in +// the block are added to the view and entries that are already in the view are +// not modified. func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) error { // Build a map of in-flight transactions because some of the inputs in // this block could be referencing other transactions earlier in this @@ -531,7 +539,7 @@ func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) // Loop through all of the transaction inputs (except for the coinbase // which has no inputs) collecting them into sets of what is needed and // what is already known (in-flight). - txNeededSet := make(map[chainhash.Hash]struct{}) + neededSet := make(map[wire.OutPoint]struct{}) for i, tx := range transactions[1:] { for _, txIn := range tx.MsgTx().TxIn { // It is acceptable for a transaction input to reference @@ -556,72 +564,74 @@ func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) // Don't request entries that are already in the view // from the database. - if _, ok := view.entries[*originHash]; ok { + if _, ok := view.entries[txIn.PreviousOutPoint]; ok { continue } - txNeededSet[*originHash] = struct{}{} + neededSet[txIn.PreviousOutPoint] = struct{}{} } } // Request the input utxos from the database. - return view.fetchUtxosMain(db, txNeededSet) + return view.fetchUtxosMain(db, neededSet) } // NewUtxoViewpoint returns a new empty unspent transaction output view. func NewUtxoViewpoint() *UtxoViewpoint { return &UtxoViewpoint{ - entries: make(map[chainhash.Hash]*UtxoEntry), + entries: make(map[wire.OutPoint]*UtxoEntry), } } -// FetchUtxoView loads utxo details about the input transactions referenced by +// FetchUtxoView loads unspent transaction outputs for the inputs referenced by // the passed transaction from the point of view of the end of the main chain. -// It also attempts to fetch the utxo details for the transaction itself so the -// returned view can be examined for duplicate unspent transaction outputs. +// It also attempts to fetch the utxos for the outputs of the transaction itself +// so the returned view can be examined for duplicate transactions. // // This function is safe for concurrent access however the returned view is NOT. func (b *BlockChain) FetchUtxoView(tx *btcutil.Tx) (*UtxoViewpoint, error) { - b.chainLock.RLock() - defer b.chainLock.RUnlock() - - // Create a set of needed transactions based on those referenced by the - // inputs of the passed transaction. Also, add the passed transaction - // itself as a way for the caller to detect duplicates that are not - // fully spent. - txNeededSet := make(map[chainhash.Hash]struct{}) - txNeededSet[*tx.Hash()] = struct{}{} + // Create a set of needed outputs based on those referenced by the + // inputs of the passed transaction and the outputs of the transaction + // itself. + neededSet := make(map[wire.OutPoint]struct{}) + prevOut := wire.OutPoint{Hash: *tx.Hash()} + for txOutIdx := range tx.MsgTx().TxOut { + prevOut.Index = uint32(txOutIdx) + neededSet[prevOut] = struct{}{} + } if !IsCoinBase(tx) { for _, txIn := range tx.MsgTx().TxIn { - txNeededSet[txIn.PreviousOutPoint.Hash] = struct{}{} + neededSet[txIn.PreviousOutPoint] = struct{}{} } } // Request the utxos from the point of view of the end of the main // chain. view := NewUtxoViewpoint() - err := view.fetchUtxosMain(b.db, txNeededSet) + b.chainLock.RLock() + err := view.fetchUtxosMain(b.db, neededSet) + b.chainLock.RUnlock() return view, err } -// FetchUtxoEntry loads and returns the unspent transaction output entry for the -// passed hash from the point of view of the end of the main chain. +// FetchUtxoEntry loads and returns the requested unspent transaction output +// from the point of view of the end of the main chain. // -// NOTE: Requesting a hash for which there is no data will NOT return an error. -// Instead both the entry and the error will be nil. This is done to allow -// pruning of fully spent transactions. In practice this means the caller must -// check if the returned entry is nil before invoking methods on it. +// NOTE: Requesting an output for which there is no data will NOT return an +// error. Instead both the entry and the error will be nil. This is done to +// allow pruning of spent transaction outputs. In practice this means the +// caller must check if the returned entry is nil before invoking methods on it. // // This function is safe for concurrent access however the returned entry (if // any) is NOT. -func (b *BlockChain) FetchUtxoEntry(txHash *chainhash.Hash) (*UtxoEntry, error) { +func (b *BlockChain) FetchUtxoEntry(outpoint wire.OutPoint) (*UtxoEntry, error) { b.chainLock.RLock() defer b.chainLock.RUnlock() var entry *UtxoEntry err := b.db.View(func(dbTx database.Tx) error { var err error - entry, err = dbFetchUtxoEntry(dbTx, txHash) + entry, err = dbFetchUtxoEntry(dbTx, outpoint) return err }) if err != nil { diff --git a/blockchain/validate.go b/blockchain/validate.go index f78d3ae63a..48e8b2941e 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -286,8 +286,7 @@ func CheckTransactionSanity(tx *btcutil.Tx) error { // Previous transaction outputs referenced by the inputs to this // transaction must not be null. for _, txIn := range msgTx.TxIn { - prevOut := &txIn.PreviousOutPoint - if isNullOutpoint(prevOut) { + if isNullOutpoint(&txIn.PreviousOutPoint) { return ruleError(ErrBadTxInput, "transaction "+ "input refers to previous output that "+ "is null") @@ -385,10 +384,8 @@ func CountP2SHSigOps(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint) totalSigOps := 0 for txInIndex, txIn := range msgTx.TxIn { // Ensure the referenced input transaction is available. - originTxHash := &txIn.PreviousOutPoint.Hash - originTxIndex := txIn.PreviousOutPoint.Index - txEntry := utxoView.LookupEntry(originTxHash) - if txEntry == nil || txEntry.IsOutputSpent(originTxIndex) { + utxo := utxoView.LookupEntry(txIn.PreviousOutPoint) + if utxo == nil || utxo.IsSpent() { str := fmt.Sprintf("output %v referenced from "+ "transaction %s:%d either does not exist or "+ "has already been spent", txIn.PreviousOutPoint, @@ -398,7 +395,7 @@ func CountP2SHSigOps(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint) // We're only interested in pay-to-script-hash types, so skip // this input if it's not one. - pkScript := txEntry.PkScriptByIndex(originTxIndex) + pkScript := utxo.PkScript() if !txscript.IsPayToScriptHash(pkScript) { continue } @@ -827,16 +824,21 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode // duplicated to effectively revert the overwritten transactions to a single // confirmation thereby making them vulnerable to a double spend. // -// For more details, see https://en.bitcoin.it/wiki/BIP_0030 and +// For more details, see +// https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki and // http://r6.ca/blog/20120206T005236Z.html. // // This function MUST be called with the chain state lock held (for reads). func (b *BlockChain) checkBIP0030(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error { - // Fetch utxo details for all of the transactions in this block. - // Typically, there will not be any utxos for any of the transactions. - fetchSet := make(map[chainhash.Hash]struct{}) + // Fetch utxos for all of the transaction ouputs in this block. + // Typically, there will not be any utxos for any of the outputs. + fetchSet := make(map[wire.OutPoint]struct{}) for _, tx := range block.Transactions() { - fetchSet[*tx.Hash()] = struct{}{} + prevOut := wire.OutPoint{Hash: *tx.Hash()} + for txOutIdx := range tx.MsgTx().TxOut { + prevOut.Index = uint32(txOutIdx) + fetchSet[prevOut] = struct{}{} + } } err := view.fetchUtxos(b.db, fetchSet) if err != nil { @@ -845,12 +847,12 @@ func (b *BlockChain) checkBIP0030(node *blockNode, block *btcutil.Block, view *U // Duplicate transactions are only allowed if the previous transaction // is fully spent. - for _, tx := range block.Transactions() { - txEntry := view.LookupEntry(tx.Hash()) - if txEntry != nil && !txEntry.IsFullySpent() { + for outpoint := range fetchSet { + utxo := view.LookupEntry(outpoint) + if utxo != nil && !utxo.IsSpent() { str := fmt.Sprintf("tried to overwrite transaction %v "+ "at block height %d that is not fully spent", - tx.Hash(), txEntry.blockHeight) + outpoint.Hash, utxo.BlockHeight()) return ruleError(ErrOverwriteTx, str) } } @@ -879,10 +881,8 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo var totalSatoshiIn int64 for txInIndex, txIn := range tx.MsgTx().TxIn { // Ensure the referenced input transaction is available. - originTxHash := &txIn.PreviousOutPoint.Hash - originTxIndex := txIn.PreviousOutPoint.Index - utxoEntry := utxoView.LookupEntry(originTxHash) - if utxoEntry == nil || utxoEntry.IsOutputSpent(originTxIndex) { + utxo := utxoView.LookupEntry(txIn.PreviousOutPoint) + if utxo == nil || utxo.IsSpent() { str := fmt.Sprintf("output %v referenced from "+ "transaction %s:%d either does not exist or "+ "has already been spent", txIn.PreviousOutPoint, @@ -892,15 +892,15 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo // Ensure the transaction is not spending coins which have not // yet reached the required coinbase maturity. - if utxoEntry.IsCoinBase() { - originHeight := utxoEntry.BlockHeight() + if utxo.IsCoinBase() { + originHeight := utxo.BlockHeight() blocksSincePrev := txHeight - originHeight coinbaseMaturity := int32(chainParams.CoinbaseMaturity) if blocksSincePrev < coinbaseMaturity { str := fmt.Sprintf("tried to spend coinbase "+ - "transaction %v from height %v at "+ - "height %v before required maturity "+ - "of %v blocks", originTxHash, + "transaction output %v from height %v "+ + "at height %v before required maturity "+ + "of %v blocks", txIn.PreviousOutPoint, originHeight, txHeight, coinbaseMaturity) return 0, ruleError(ErrImmatureSpend, str) @@ -913,7 +913,7 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo // a transaction are in a unit value known as a satoshi. One // bitcoin is a quantity of satoshi as defined by the // SatoshiPerBitcoin constant. - originTxSatoshi := utxoEntry.AmountByIndex(originTxIndex) + originTxSatoshi := utxo.Amount() if originTxSatoshi < 0 { str := fmt.Sprintf("transaction output has negative "+ "value of %v", btcutil.Amount(originTxSatoshi)) diff --git a/blockchain/weight.go b/blockchain/weight.go index 80de012f50..6f6292a1b6 100644 --- a/blockchain/weight.go +++ b/blockchain/weight.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2013-2017 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -8,6 +8,7 @@ import ( "fmt" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" ) @@ -34,6 +35,14 @@ const ( // receives compared to "base" data. A scale factor of 4, denotes that // witness data is 1/4 as cheap as regular non-witness data. WitnessScaleFactor = 4 + + // MinTxOutputWeight is the minimum possible weight for a transaction + // output. + MinTxOutputWeight = WitnessScaleFactor * wire.MinTxOutPayload + + // MaxOutputsPerBlock is the maximum number of transaction outputs there + // can be in a block of max weight size. + MaxOutputsPerBlock = MaxBlockWeight / MinTxOutputWeight ) // GetBlockWeight computes the value of the weight metric for a given block. @@ -71,9 +80,7 @@ func GetTransactionWeight(tx *btcutil.Tx) int64 { // legacy sig op count scaled according to the WitnessScaleFactor, the sig op // count for all p2sh inputs scaled by the WitnessScaleFactor, and finally the // unscaled sig op count for any inputs spending witness programs. -func GetSigOpCost(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint, - bip16, segWit bool) (int, error) { - +func GetSigOpCost(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint, bip16, segWit bool) (int, error) { numSigOps := CountSigOps(tx) * WitnessScaleFactor if bip16 { numP2SHSigOps, err := CountP2SHSigOps(tx, isCoinBaseTx, utxoView) @@ -86,11 +93,10 @@ func GetSigOpCost(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint, if segWit && !isCoinBaseTx { msgTx := tx.MsgTx() for txInIndex, txIn := range msgTx.TxIn { - // Ensure the referenced input transaction is available. - originTxHash := &txIn.PreviousOutPoint.Hash - originTxIndex := txIn.PreviousOutPoint.Index - txEntry := utxoView.LookupEntry(originTxHash) - if txEntry == nil || txEntry.IsOutputSpent(originTxIndex) { + // Ensure the referenced output is available and hasn't + // already been spent. + utxo := utxoView.LookupEntry(txIn.PreviousOutPoint) + if utxo == nil || utxo.IsSpent() { str := fmt.Sprintf("output %v referenced from "+ "transaction %s:%d either does not "+ "exist or has already been spent", @@ -101,7 +107,7 @@ func GetSigOpCost(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint, witness := txIn.Witness sigScript := txIn.SignatureScript - pkScript := txEntry.PkScriptByIndex(originTxIndex) + pkScript := utxo.PkScript() numSigOps += txscript.GetWitnessSigOpCount(sigScript, pkScript, witness) } diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 33d54d385d..24d6cf7cc4 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -289,7 +289,6 @@ type GetTxOutResult struct { Confirmations int64 `json:"confirmations"` Value float64 `json:"value"` ScriptPubKey ScriptPubKeyResult `json:"scriptPubKey"` - Version int32 `json:"version"` Coinbase bool `json:"coinbase"` } diff --git a/mempool/mempool.go b/mempool/mempool.go index d4088fc743..7bb7044543 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -595,15 +595,21 @@ func (mp *TxPool) fetchInputUtxos(tx *btcutil.Tx) (*blockchain.UtxoViewpoint, er } // Attempt to populate any missing inputs from the transaction pool. - for originHash, entry := range utxoView.Entries() { - if entry != nil && !entry.IsFullySpent() { + for _, txIn := range tx.MsgTx().TxIn { + prevOut := &txIn.PreviousOutPoint + entry := utxoView.LookupEntry(*prevOut) + if entry != nil && !entry.IsSpent() { continue } - if poolTxDesc, exists := mp.pool[originHash]; exists { - utxoView.AddTxOuts(poolTxDesc.Tx, mining.UnminedHeight) + if poolTxDesc, exists := mp.pool[prevOut.Hash]; exists { + // AddTxOut ignores out of range index values, so it is + // safe to call without bounds checking here. + utxoView.AddTxOut(poolTxDesc.Tx, prevOut.Index, + mining.UnminedHeight) } } + return utxoView, nil } @@ -733,25 +739,29 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec // Don't allow the transaction if it exists in the main chain and is not // not already fully spent. - txEntry := utxoView.LookupEntry(txHash) - if txEntry != nil && !txEntry.IsFullySpent() { - return nil, nil, txRuleError(wire.RejectDuplicate, - "transaction already exists") + prevOut := wire.OutPoint{Hash: *txHash} + for txOutIdx := range tx.MsgTx().TxOut { + prevOut.Index = uint32(txOutIdx) + entry := utxoView.LookupEntry(prevOut) + if entry != nil && !entry.IsSpent() { + return nil, nil, txRuleError(wire.RejectDuplicate, + "transaction already exists") + } + utxoView.RemoveEntry(prevOut) } - delete(utxoView.Entries(), *txHash) - // Transaction is an orphan if any of the referenced input transactions - // don't exist. Adding orphans to the orphan pool is not handled by - // this function, and the caller should use maybeAddOrphan if this - // behavior is desired. + // Transaction is an orphan if any of the referenced transaction outputs + // don't exist or are already spent. Adding orphans to the orphan pool + // is not handled by this function, and the caller should use + // maybeAddOrphan if this behavior is desired. var missingParents []*chainhash.Hash - for originHash, entry := range utxoView.Entries() { - if entry == nil || entry.IsFullySpent() { + for outpoint, entry := range utxoView.Entries() { + if entry == nil || entry.IsSpent() { // Must make a copy of the hash here since the iterator // is replaced and taking its address directly would // result in all of the entries pointing to the same // memory location and thus all be the final hash. - hashCopy := originHash + hashCopy := outpoint.Hash missingParents = append(missingParents, &hashCopy) } } diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index e1e5e7702c..7a29598bf2 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -31,10 +31,10 @@ type fakeChain struct { medianTimePast time.Time } -// FetchUtxoView loads utxo details about the input transactions referenced by -// the passed transaction from the point of view of the fake chain. -// It also attempts to fetch the utxo details for the transaction itself so the -// returned view can be examined for duplicate unspent transaction outputs. +// FetchUtxoView loads utxo details about the inputs referenced by the passed +// transaction from the point of view of the fake chain. It also attempts to +// fetch the utxos for the outputs of the transaction itself so the returned +// view can be examined for duplicate transactions. // // This function is safe for concurrent access however the returned view is NOT. func (s *fakeChain) FetchUtxoView(tx *btcutil.Tx) (*blockchain.UtxoViewpoint, error) { @@ -46,14 +46,17 @@ func (s *fakeChain) FetchUtxoView(tx *btcutil.Tx) (*blockchain.UtxoViewpoint, er // Add an entry for the tx itself to the new view. viewpoint := blockchain.NewUtxoViewpoint() - entry := s.utxos.LookupEntry(tx.Hash()) - viewpoint.Entries()[*tx.Hash()] = entry.Clone() + prevOut := wire.OutPoint{Hash: *tx.Hash()} + for txOutIdx := range tx.MsgTx().TxOut { + prevOut.Index = uint32(txOutIdx) + entry := s.utxos.LookupEntry(prevOut) + viewpoint.Entries()[prevOut] = entry.Clone() + } // Add entries for all of the inputs to the tx to the new view. for _, txIn := range tx.MsgTx().TxIn { - originHash := &txIn.PreviousOutPoint.Hash - entry := s.utxos.LookupEntry(originHash) - viewpoint.Entries()[*originHash] = entry.Clone() + entry := s.utxos.LookupEntry(txIn.PreviousOutPoint) + viewpoint.Entries()[txIn.PreviousOutPoint] = entry.Clone() } return viewpoint, nil diff --git a/mempool/policy.go b/mempool/policy.go index 89cd7a505e..f4e3b51ee7 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -98,9 +98,8 @@ func checkInputsStandard(tx *btcutil.Tx, utxoView *blockchain.UtxoViewpoint) err // It is safe to elide existence and index checks here since // they have already been checked prior to calling this // function. - prevOut := txIn.PreviousOutPoint - entry := utxoView.LookupEntry(&prevOut.Hash) - originPkScript := entry.PkScriptByIndex(prevOut.Index) + entry := utxoView.LookupEntry(txIn.PreviousOutPoint) + originPkScript := entry.PkScript() switch txscript.GetScriptClass(originPkScript) { case txscript.ScriptHashTy: numSigOps := txscript.GetPreciseSigOpCount( diff --git a/mining/mining.go b/mining/mining.go index 944b049bc3..44ec7dc761 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -222,14 +222,14 @@ type BlockTemplate struct { // mergeUtxoView adds all of the entries in viewB to viewA. The result is that // viewA will contain all of its original entries plus all of the entries // in viewB. It will replace any entries in viewB which also exist in viewA -// if the entry in viewA is fully spent. +// if the entry in viewA is spent. func mergeUtxoView(viewA *blockchain.UtxoViewpoint, viewB *blockchain.UtxoViewpoint) { viewAEntries := viewA.Entries() - for hash, entryB := range viewB.Entries() { - if entryA, exists := viewAEntries[hash]; !exists || - entryA == nil || entryA.IsFullySpent() { + for outpoint, entryB := range viewB.Entries() { + if entryA, exists := viewAEntries[outpoint]; !exists || + entryA == nil || entryA.IsSpent() { - viewAEntries[hash] = entryB + viewAEntries[outpoint] = entryB } } } @@ -291,11 +291,9 @@ func createCoinbaseTx(params *chaincfg.Params, coinbaseScript []byte, nextBlockH // which are not provably unspendable as available unspent transaction outputs. func spendTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil.Tx, height int32) error { for _, txIn := range tx.MsgTx().TxIn { - originHash := &txIn.PreviousOutPoint.Hash - originIndex := txIn.PreviousOutPoint.Index - entry := utxoView.LookupEntry(originHash) + entry := utxoView.LookupEntry(txIn.PreviousOutPoint) if entry != nil { - entry.SpendOutput(originIndex) + entry.Spend() } } @@ -540,9 +538,8 @@ mempoolLoop: prioItem := &txPrioItem{tx: tx} for _, txIn := range tx.MsgTx().TxIn { originHash := &txIn.PreviousOutPoint.Hash - originIndex := txIn.PreviousOutPoint.Index - utxoEntry := utxos.LookupEntry(originHash) - if utxoEntry == nil || utxoEntry.IsOutputSpent(originIndex) { + entry := utxos.LookupEntry(txIn.PreviousOutPoint) + if entry == nil || entry.IsSpent() { if !g.txSource.HaveTransaction(originHash) { log.Tracef("Skipping tx %s because it "+ "references unspent output %s "+ diff --git a/mining/policy.go b/mining/policy.go index 54b5305f0b..c3f059c521 100644 --- a/mining/policy.go +++ b/mining/policy.go @@ -67,16 +67,14 @@ func calcInputValueAge(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextB for _, txIn := range tx.TxIn { // Don't attempt to accumulate the total input age if the // referenced transaction output doesn't exist. - originHash := &txIn.PreviousOutPoint.Hash - originIndex := txIn.PreviousOutPoint.Index - txEntry := utxoView.LookupEntry(originHash) - if txEntry != nil && !txEntry.IsOutputSpent(originIndex) { + entry := utxoView.LookupEntry(txIn.PreviousOutPoint) + if entry != nil && !entry.IsSpent() { // Inputs with dependencies currently in the mempool // have their block height set to a special constant. // Their input age should computed as zero since their // parent hasn't made it into a block yet. var inputAge int32 - originHeight := txEntry.BlockHeight() + originHeight := entry.BlockHeight() if originHeight == UnminedHeight { inputAge = 0 } else { @@ -84,7 +82,7 @@ func calcInputValueAge(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextB } // Sum the input value times age. - inputValue := txEntry.AmountByIndex(originIndex) + inputValue := entry.Amount() totalInputAge += float64(inputValue * int64(inputAge)) } } diff --git a/netsync/manager.go b/netsync/manager.go index fe764a70c8..d75dd96134 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -898,12 +898,26 @@ func (sm *SyncManager) haveInventory(invVect *wire.InvVect) (bool, error) { } // Check if the transaction exists from the point of view of the - // end of the main chain. - entry, err := sm.chain.FetchUtxoEntry(&invVect.Hash) - if err != nil { - return false, err + // end of the main chain. Note that this is only a best effort + // since it is expensive to check existence of every output and + // the only purpose of this check is to avoid downloading + // already known transactions. Only the first two outputs are + // checked because the vast majority of transactions consist of + // two outputs where one is some form of "pay-to-somebody-else" + // and the other is a change output. + prevOut := wire.OutPoint{Hash: invVect.Hash} + for i := uint32(0); i < 2; i++ { + prevOut.Index = i + entry, err := sm.chain.FetchUtxoEntry(prevOut) + if err != nil { + return false, err + } + if entry != nil && !entry.IsSpent() { + return true, nil + } } - return entry != nil && !entry.IsFullySpent(), nil + + return false, nil } // The requested inventory is is an unsupported type, so just claim diff --git a/rpcserver.go b/rpcserver.go index 0dae52a7f4..e3f6430f21 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2667,7 +2667,6 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i // from there, otherwise attempt to fetch from the block database. var bestBlockHash string var confirmations int32 - var txVersion int32 var value int64 var pkScript []byte var isCoinbase bool @@ -2702,12 +2701,12 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i best := s.cfg.Chain.BestSnapshot() bestBlockHash = best.Hash.String() confirmations = 0 - txVersion = mtx.Version value = txOut.Value pkScript = txOut.PkScript isCoinbase = blockchain.IsCoinBaseTx(mtx) } else { - entry, err := s.cfg.Chain.FetchUtxoEntry(txHash) + out := wire.OutPoint{Hash: *txHash, Index: c.Vout} + entry, err := s.cfg.Chain.FetchUtxoEntry(out) if err != nil { return nil, rpcNoTxInfoError(txHash) } @@ -2717,16 +2716,15 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i // transaction already in the main chain. Mined transactions // that are spent by a mempool transaction are not affected by // this. - if entry == nil || entry.IsOutputSpent(c.Vout) { + if entry == nil || entry.IsSpent() { return nil, nil } best := s.cfg.Chain.BestSnapshot() bestBlockHash = best.Hash.String() confirmations = 1 + best.Height - entry.BlockHeight() - txVersion = entry.Version() - value = entry.AmountByIndex(c.Vout) - pkScript = entry.PkScriptByIndex(c.Vout) + value = entry.Amount() + pkScript = entry.PkScript() isCoinbase = entry.IsCoinBase() } @@ -2749,7 +2747,6 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i BestBlock: bestBlockHash, Confirmations: int64(confirmations), Value: btcutil.Amount(value).ToBTC(), - Version: txVersion, ScriptPubKey: btcjson.ScriptPubKeyResult{ Asm: disbuf, Hex: hex.EncodeToString(pkScript), diff --git a/wire/msgtx.go b/wire/msgtx.go index a5327cb3c6..4f10ef9f98 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -62,13 +62,13 @@ const ( // a transaction which fits into a message could possibly have. maxTxInPerMessage = (MaxMessagePayload / minTxInPayload) + 1 - // minTxOutPayload is the minimum payload size for a transaction output. + // MinTxOutPayload is the minimum payload size for a transaction output. // Value 8 bytes + Varint for PkScript length 1 byte. - minTxOutPayload = 9 + MinTxOutPayload = 9 // maxTxOutPerMessage is the maximum number of transactions outputs that // a transaction which fits into a message could possibly have. - maxTxOutPerMessage = (MaxMessagePayload / minTxOutPayload) + 1 + maxTxOutPerMessage = (MaxMessagePayload / MinTxOutPayload) + 1 // minTxPayload is the minimum payload size for a transaction. Note // that any realistically usable transaction must have at least one From bd1d6c9148bdb2feb9c96a85f284508cd1bc1dd4 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 29 May 2018 17:06:32 -0700 Subject: [PATCH 0186/1056] btcec/pubkey: verify decompressed y-coord is sqroot --- btcec/pubkey.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index b74917718f..cf49807522 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -32,8 +32,9 @@ func decompressPoint(curve *KoblitzCurve, x *big.Int, ybit bool) (*big.Int, erro x3 := new(big.Int).Mul(x, x) x3.Mul(x3, x) x3.Add(x3, curve.Params().B) + x3.Mod(x3, curve.Params().P) - // now calculate sqrt mod p of x2 + B + // Now calculate sqrt mod p of x^3 + B // This code used to do a full sqrt based on tonelli/shanks, // but this was replaced by the algorithms referenced in // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 @@ -42,9 +43,19 @@ func decompressPoint(curve *KoblitzCurve, x *big.Int, ybit bool) (*big.Int, erro if ybit != isOdd(y) { y.Sub(curve.Params().P, y) } + + // Check that y is a square root of x^3 + B. + y2 := new(big.Int).Mul(y, y) + y2.Mod(y2, curve.Params().P) + if y2.Cmp(x3) != 0 { + return nil, fmt.Errorf("invalid square root") + } + + // Verify that y-coord has expected parity. if ybit != isOdd(y) { return nil, fmt.Errorf("ybit doesn't match oddness") } + return y, nil } From 4bd5b1a43a8e5b64b9462d3048d2f8d290c7b851 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 30 May 2018 20:45:39 -0700 Subject: [PATCH 0187/1056] blockchain: add new FetchSpendJournal method --- blockchain/chainio.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 27b702deaa..84cd9b7730 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -246,6 +246,30 @@ type spentTxOut struct { isCoinBase bool // Whether creating tx is a coinbase. } +// FetchSpendJournal attempts to retrieve the spend journal, or the set of +// outputs spent for the target block. This provides a view of all the outputs +// that will be consumed once the target block is connected to the end of the +// main chain. +// +// This function is safe for concurrent access. +func (b *BlockChain) FetchSpendJournal(targetBlock *btcutil.Block) ([]SpentTxOut, error) { + b.chainLock.RLock() + defer b.chainLock.RUnlock() + + var spendEntries []SpentTxOut + err := b.db.View(func(dbTx database.Tx) error { + var err error + + spendEntries, err = dbFetchSpendJournalEntry(dbTx, targetBlock) + return err + }) + if err != nil { + return nil, err + } + + return spendEntries, nil +} + // spentTxOutHeaderCode returns the calculated header code to be used when // serializing the provided stxo entry. func spentTxOutHeaderCode(stxo *spentTxOut) uint64 { From e4d82bd6e26c1afbf9ff7e2a06bfca1f278e4ad5 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 28 May 2018 21:13:59 -0700 Subject: [PATCH 0188/1056] blockchain: publicly export spentTxOut and all attributes In this commit, we publicly export the spentTxOut struct and all its attributes. This is the first in a set of commits to optimize the existing address index by using the spend journal rather than manually re-creating the utxoViewPoint each time. --- blockchain/chain.go | 12 +++--- blockchain/chainio.go | 63 +++++++++++++++++-------------- blockchain/chainio_test.go | 74 ++++++++++++++++++------------------- blockchain/utxoviewpoint.go | 30 +++++++-------- blockchain/validate.go | 2 +- 5 files changed, 95 insertions(+), 86 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index b5a8ea54e0..c88bea6dd2 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -557,7 +557,9 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List // it would be inefficient to repeat it. // // This function MUST be called with the chain state lock held (for writes). -func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint, stxos []spentTxOut) error { +func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, + view *UtxoViewpoint, stxos []SpentTxOut) error { + // Make sure it's extending the end of the best chain. prevHash := &block.MsgBlock().Header.PrevBlock if !prevHash.IsEqual(&b.bestChain.Tip().hash) { @@ -816,7 +818,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // then they are needed again when doing the actual database updates. // Rather than doing two loads, cache the loaded data into these slices. detachBlocks := make([]*btcutil.Block, 0, detachNodes.Len()) - detachSpentTxOuts := make([][]spentTxOut, 0, detachNodes.Len()) + detachSpentTxOuts := make([][]SpentTxOut, 0, detachNodes.Len()) attachBlocks := make([]*btcutil.Block, 0, attachNodes.Len()) // Disconnect all of the blocks back to the point of the fork. This @@ -846,7 +848,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the spent txos for the block from the spend // journal. - var stxos []spentTxOut + var stxos []SpentTxOut err = b.db.View(func(dbTx database.Tx) error { stxos, err = dbFetchSpendJournalEntry(dbTx, block) return err @@ -990,7 +992,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // as spent and add all transactions being created by this block // to it. Also, provide an stxo slice so the spent txout // details are generated. - stxos := make([]spentTxOut, 0, countSpentOutputs(block)) + stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) err = view.connectTransactions(block, &stxos) if err != nil { return err @@ -1044,7 +1046,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // actually connecting the block. view := NewUtxoViewpoint() view.SetBestHash(parentHash) - stxos := make([]spentTxOut, 0, countSpentOutputs(block)) + stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) if !fastAdd { err := b.checkConnectBlock(node, block, view, &stxos) if err == nil { diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 84cd9b7730..8bd5627606 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -232,18 +232,25 @@ func dbFetchOrCreateVersion(dbTx database.Tx, key []byte, defaultVersion uint32) // - 0xb2...ec: pubkey hash // ----------------------------------------------------------------------------- -// spentTxOut contains a spent transaction output and potentially additional +// SpentTxOut contains a spent transaction output and potentially additional // contextual information such as whether or not it was contained in a coinbase // transaction, the version of the transaction it was contained in, and which // block height the containing transaction was included in. As described in // the comments above, the additional contextual information will only be valid // when this spent txout is spending the last unspent output of the containing // transaction. -type spentTxOut struct { - amount int64 // The amount of the output. - pkScript []byte // The public key script for the output. - height int32 // Height of the the block containing the creating tx. - isCoinBase bool // Whether creating tx is a coinbase. +type SpentTxOut struct { + // Amount is the amount of the output. + Amount int64 + + // PkScipt is the the public key script for the output. + PkScript []byte + + // Height is the height of the the block containing the creating tx. + Height int32 + + // Denotes if the creating tx is a coinbase. + IsCoinBase bool } // FetchSpendJournal attempts to retrieve the spend journal, or the set of @@ -272,12 +279,12 @@ func (b *BlockChain) FetchSpendJournal(targetBlock *btcutil.Block) ([]SpentTxOut // spentTxOutHeaderCode returns the calculated header code to be used when // serializing the provided stxo entry. -func spentTxOutHeaderCode(stxo *spentTxOut) uint64 { +func spentTxOutHeaderCode(stxo *SpentTxOut) uint64 { // As described in the serialization format comments, the header code // encodes the height shifted over one bit and the coinbase flag in the // lowest bit. - headerCode := uint64(stxo.height) << 1 - if stxo.isCoinBase { + headerCode := uint64(stxo.Height) << 1 + if stxo.IsCoinBase { headerCode |= 0x01 } @@ -286,38 +293,38 @@ func spentTxOutHeaderCode(stxo *spentTxOut) uint64 { // spentTxOutSerializeSize returns the number of bytes it would take to // serialize the passed stxo according to the format described above. -func spentTxOutSerializeSize(stxo *spentTxOut) int { +func spentTxOutSerializeSize(stxo *SpentTxOut) int { size := serializeSizeVLQ(spentTxOutHeaderCode(stxo)) - if stxo.height > 0 { + if stxo.Height > 0 { // The legacy v1 spend journal format conditionally tracked the // containing transaction version when the height was non-zero, // so this is required for backwards compat. size += serializeSizeVLQ(0) } - return size + compressedTxOutSize(uint64(stxo.amount), stxo.pkScript) + return size + compressedTxOutSize(uint64(stxo.Amount), stxo.PkScript) } // putSpentTxOut serializes the passed stxo according to the format described // above directly into the passed target byte slice. The target byte slice must // be at least large enough to handle the number of bytes returned by the -// spentTxOutSerializeSize function or it will panic. -func putSpentTxOut(target []byte, stxo *spentTxOut) int { +// SpentTxOutSerializeSize function or it will panic. +func putSpentTxOut(target []byte, stxo *SpentTxOut) int { headerCode := spentTxOutHeaderCode(stxo) offset := putVLQ(target, headerCode) - if stxo.height > 0 { + if stxo.Height > 0 { // The legacy v1 spend journal format conditionally tracked the // containing transaction version when the height was non-zero, // so this is required for backwards compat. offset += putVLQ(target[offset:], 0) } - return offset + putCompressedTxOut(target[offset:], uint64(stxo.amount), - stxo.pkScript) + return offset + putCompressedTxOut(target[offset:], uint64(stxo.Amount), + stxo.PkScript) } // decodeSpentTxOut decodes the passed serialized stxo entry, possibly followed // by other data, into the passed stxo struct. It returns the number of bytes // read. -func decodeSpentTxOut(serialized []byte, stxo *spentTxOut) (int, error) { +func decodeSpentTxOut(serialized []byte, stxo *SpentTxOut) (int, error) { // Ensure there are bytes to decode. if len(serialized) == 0 { return 0, errDeserialize("no serialized bytes") @@ -334,9 +341,9 @@ func decodeSpentTxOut(serialized []byte, stxo *spentTxOut) (int, error) { // // Bit 0 indicates containing transaction is a coinbase. // Bits 1-x encode height of containing transaction. - stxo.isCoinBase = code&0x01 != 0 - stxo.height = int32(code >> 1) - if stxo.height > 0 { + stxo.IsCoinBase = code&0x01 != 0 + stxo.Height = int32(code >> 1) + if stxo.Height > 0 { // The legacy v1 spend journal format conditionally tracked the // containing transaction version when the height was non-zero, // so this is required for backwards compat. @@ -356,8 +363,8 @@ func decodeSpentTxOut(serialized []byte, stxo *spentTxOut) (int, error) { return offset, errDeserialize(fmt.Sprintf("unable to decode "+ "txout: %v", err)) } - stxo.amount = int64(amount) - stxo.pkScript = pkScript + stxo.Amount = int64(amount) + stxo.PkScript = pkScript return offset, nil } @@ -367,7 +374,7 @@ func decodeSpentTxOut(serialized []byte, stxo *spentTxOut) (int, error) { // Since the serialization format is not self describing, as noted in the // format comments, this function also requires the transactions that spend the // txouts. -func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx) ([]spentTxOut, error) { +func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx) ([]SpentTxOut, error) { // Calculate the total number of stxos. var numStxos int for _, tx := range txns { @@ -392,7 +399,7 @@ func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx) ([]spen // reverse order to match the serialization order. stxoIdx := numStxos - 1 offset := 0 - stxos := make([]spentTxOut, numStxos) + stxos := make([]SpentTxOut, numStxos) for txIdx := len(txns) - 1; txIdx > -1; txIdx-- { tx := txns[txIdx] @@ -418,7 +425,7 @@ func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx) ([]spen // serializeSpendJournalEntry serializes all of the passed spent txouts into a // single byte slice according to the format described in detail above. -func serializeSpendJournalEntry(stxos []spentTxOut) []byte { +func serializeSpendJournalEntry(stxos []SpentTxOut) []byte { if len(stxos) == 0 { return nil } @@ -446,7 +453,7 @@ func serializeSpendJournalEntry(stxos []spentTxOut) []byte { // NOTE: Legacy entries will not have the coinbase flag or height set unless it // was the final output spend in the containing transaction. It is up to the // caller to handle this properly by looking the information up in the utxo set. -func dbFetchSpendJournalEntry(dbTx database.Tx, block *btcutil.Block) ([]spentTxOut, error) { +func dbFetchSpendJournalEntry(dbTx database.Tx, block *btcutil.Block) ([]SpentTxOut, error) { // Exclude the coinbase transaction since it can't spend anything. spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) serialized := spendBucket.Get(block.Hash()[:]) @@ -474,7 +481,7 @@ func dbFetchSpendJournalEntry(dbTx database.Tx, block *btcutil.Block) ([]spentTx // spend journal entry for the given block hash using the provided slice of // spent txouts. The spent txouts slice must contain an entry for every txout // the transactions in the block spend in the order they are spent. -func dbPutSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash, stxos []spentTxOut) error { +func dbPutSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash, stxos []SpentTxOut) error { spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) serialized := serializeSpendJournalEntry(stxos) return spendBucket.Put(blockHash[:], serialized) diff --git a/blockchain/chainio_test.go b/blockchain/chainio_test.go index f62a39d2c6..630af14e1c 100644 --- a/blockchain/chainio_test.go +++ b/blockchain/chainio_test.go @@ -44,37 +44,37 @@ func TestStxoSerialization(t *testing.T) { tests := []struct { name string - stxo spentTxOut + stxo SpentTxOut serialized []byte }{ // From block 170 in main blockchain. { name: "Spends last output of coinbase", - stxo: spentTxOut{ - amount: 5000000000, - pkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), - isCoinBase: true, - height: 9, + stxo: SpentTxOut{ + Amount: 5000000000, + PkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), + IsCoinBase: true, + Height: 9, }, serialized: hexToBytes("1300320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"), }, // Adapted from block 100025 in main blockchain. { name: "Spends last output of non coinbase", - stxo: spentTxOut{ - amount: 13761000000, - pkScript: hexToBytes("76a914b2fb57eadf61e106a100a7445a8c3f67898841ec88ac"), - isCoinBase: false, - height: 100024, + stxo: SpentTxOut{ + Amount: 13761000000, + PkScript: hexToBytes("76a914b2fb57eadf61e106a100a7445a8c3f67898841ec88ac"), + IsCoinBase: false, + Height: 100024, }, serialized: hexToBytes("8b99700086c64700b2fb57eadf61e106a100a7445a8c3f67898841ec"), }, // Adapted from block 100025 in main blockchain. { name: "Does not spend last output, legacy format", - stxo: spentTxOut{ - amount: 34405000000, - pkScript: hexToBytes("76a9146edbc6c4d31bae9f1ccc38538a114bf42de65e8688ac"), + stxo: SpentTxOut{ + Amount: 34405000000, + PkScript: hexToBytes("76a9146edbc6c4d31bae9f1ccc38538a114bf42de65e8688ac"), }, serialized: hexToBytes("0091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e86"), }, @@ -85,7 +85,7 @@ func TestStxoSerialization(t *testing.T) { // actually serializing it is calculated properly. gotSize := spentTxOutSerializeSize(&test.stxo) if gotSize != len(test.serialized) { - t.Errorf("spentTxOutSerializeSize (%s): did not get "+ + t.Errorf("SpentTxOutSerializeSize (%s): did not get "+ "expected size - got %d, want %d", test.name, gotSize, len(test.serialized)) continue @@ -110,7 +110,7 @@ func TestStxoSerialization(t *testing.T) { // Ensure the serialized bytes are decoded back to the expected // stxo. - var gotStxo spentTxOut + var gotStxo SpentTxOut gotBytesRead, err := decodeSpentTxOut(test.serialized, &gotStxo) if err != nil { t.Errorf("decodeSpentTxOut (%s): unexpected error: %v", @@ -138,42 +138,42 @@ func TestStxoDecodeErrors(t *testing.T) { tests := []struct { name string - stxo spentTxOut + stxo SpentTxOut serialized []byte bytesRead int // Expected number of bytes read. errType error }{ { name: "nothing serialized", - stxo: spentTxOut{}, + stxo: SpentTxOut{}, serialized: hexToBytes(""), errType: errDeserialize(""), bytesRead: 0, }, { name: "no data after header code w/o reserved", - stxo: spentTxOut{}, + stxo: SpentTxOut{}, serialized: hexToBytes("00"), errType: errDeserialize(""), bytesRead: 1, }, { name: "no data after header code with reserved", - stxo: spentTxOut{}, + stxo: SpentTxOut{}, serialized: hexToBytes("13"), errType: errDeserialize(""), bytesRead: 1, }, { name: "no data after reserved", - stxo: spentTxOut{}, + stxo: SpentTxOut{}, serialized: hexToBytes("1300"), errType: errDeserialize(""), bytesRead: 2, }, { name: "incomplete compressed txout", - stxo: spentTxOut{}, + stxo: SpentTxOut{}, serialized: hexToBytes("1332"), errType: errDeserialize(""), bytesRead: 2, @@ -208,7 +208,7 @@ func TestSpendJournalSerialization(t *testing.T) { tests := []struct { name string - entry []spentTxOut + entry []SpentTxOut blockTxns []*wire.MsgTx serialized []byte }{ @@ -222,11 +222,11 @@ func TestSpendJournalSerialization(t *testing.T) { // From block 170 in main blockchain. { name: "One tx with one input spends last output of coinbase", - entry: []spentTxOut{{ - amount: 5000000000, - pkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), - isCoinBase: true, - height: 9, + entry: []SpentTxOut{{ + Amount: 5000000000, + PkScript: hexToBytes("410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac"), + IsCoinBase: true, + Height: 9, }}, blockTxns: []*wire.MsgTx{{ // Coinbase omitted. Version: 1, @@ -252,16 +252,16 @@ func TestSpendJournalSerialization(t *testing.T) { // Adapted from block 100025 in main blockchain. { name: "Two txns when one spends last output, one doesn't", - entry: []spentTxOut{{ - amount: 34405000000, - pkScript: hexToBytes("76a9146edbc6c4d31bae9f1ccc38538a114bf42de65e8688ac"), - isCoinBase: false, - height: 100024, + entry: []SpentTxOut{{ + Amount: 34405000000, + PkScript: hexToBytes("76a9146edbc6c4d31bae9f1ccc38538a114bf42de65e8688ac"), + IsCoinBase: false, + Height: 100024, }, { - amount: 13761000000, - pkScript: hexToBytes("76a914b2fb57eadf61e106a100a7445a8c3f67898841ec88ac"), - isCoinBase: false, - height: 100024, + Amount: 13761000000, + PkScript: hexToBytes("76a914b2fb57eadf61e106a100a7445a8c3f67898841ec88ac"), + IsCoinBase: false, + Height: 100024, }}, blockTxns: []*wire.MsgTx{{ // Coinbase omitted. Version: 1, diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 5af8423439..08005d27a1 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -216,7 +216,7 @@ func (view *UtxoViewpoint) AddTxOuts(tx *btcutil.Tx, blockHeight int32) { // spent. In addition, when the 'stxos' argument is not nil, it will be updated // to append an entry for each spent txout. An error will be returned if the // view does not contain the required utxos. -func (view *UtxoViewpoint) connectTransaction(tx *btcutil.Tx, blockHeight int32, stxos *[]spentTxOut) error { +func (view *UtxoViewpoint) connectTransaction(tx *btcutil.Tx, blockHeight int32, stxos *[]SpentTxOut) error { // Coinbase transactions don't have any inputs to spend. if IsCoinBase(tx) { // Add the transaction's outputs as available utxos. @@ -239,11 +239,11 @@ func (view *UtxoViewpoint) connectTransaction(tx *btcutil.Tx, blockHeight int32, // Only create the stxo details if requested. if stxos != nil { // Populate the stxo details using the utxo entry. - var stxo = spentTxOut{ - amount: entry.Amount(), - pkScript: entry.PkScript(), - height: entry.BlockHeight(), - isCoinBase: entry.IsCoinBase(), + var stxo = SpentTxOut{ + Amount: entry.Amount(), + PkScript: entry.PkScript(), + Height: entry.BlockHeight(), + IsCoinBase: entry.IsCoinBase(), } *stxos = append(*stxos, stxo) } @@ -264,7 +264,7 @@ func (view *UtxoViewpoint) connectTransaction(tx *btcutil.Tx, blockHeight int32, // spend as spent, and setting the best hash for the view to the passed block. // In addition, when the 'stxos' argument is not nil, it will be updated to // append an entry for each spent txout. -func (view *UtxoViewpoint) connectTransactions(block *btcutil.Block, stxos *[]spentTxOut) error { +func (view *UtxoViewpoint) connectTransactions(block *btcutil.Block, stxos *[]SpentTxOut) error { for _, tx := range block.Transactions() { err := view.connectTransaction(tx, block.Height(), stxos) if err != nil { @@ -308,7 +308,7 @@ func (view *UtxoViewpoint) fetchEntryByHash(db database.DB, hash *chainhash.Hash // created by the passed block, restoring all utxos the transactions spent by // using the provided spent txo information, and setting the best hash for the // view to the block before the passed block. -func (view *UtxoViewpoint) disconnectTransactions(db database.DB, block *btcutil.Block, stxos []spentTxOut) error { +func (view *UtxoViewpoint) disconnectTransactions(db database.DB, block *btcutil.Block, stxos []SpentTxOut) error { // Sanity check the correct number of stxos are provided. if len(stxos) != countSpentOutputs(block) { return AssertError("disconnectTransactions called with bad " + @@ -405,7 +405,7 @@ func (view *UtxoViewpoint) disconnectTransactions(db database.DB, block *btcutil // connected. In the case of a fresh database that has // only ever run with the new v2 format, this code path // will never run. - if stxo.height == 0 { + if stxo.Height == 0 { utxo, err := view.fetchEntryByHash(db, txHash) if err != nil { return err @@ -416,17 +416,17 @@ func (view *UtxoViewpoint) disconnectTransactions(db database.DB, block *btcutil *originOut)) } - stxo.height = utxo.BlockHeight() - stxo.isCoinBase = utxo.IsCoinBase() + stxo.Height = utxo.BlockHeight() + stxo.IsCoinBase = utxo.IsCoinBase() } // Restore the utxo using the stxo data from the spend // journal and mark it as modified. - entry.amount = stxo.amount - entry.pkScript = stxo.pkScript - entry.blockHeight = stxo.height + entry.amount = stxo.Amount + entry.pkScript = stxo.PkScript + entry.blockHeight = stxo.Height entry.packedFlags = tfModified - if stxo.isCoinBase { + if stxo.IsCoinBase { entry.packedFlags |= tfCoinBase } } diff --git a/blockchain/validate.go b/blockchain/validate.go index 48e8b2941e..b971337fb5 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -986,7 +986,7 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo // with that node. // // This function MUST be called with the chain state lock held (for writes). -func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint, stxos *[]spentTxOut) error { +func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint, stxos *[]SpentTxOut) error { // If the side chain blocks end up in the database, a call to // CheckBlockSanity should be done here in case a previous version // allowed a block that is no longer valid. However, since the From ad69a7121b2b1d937c7287a67eaef910106244ce Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 28 May 2018 21:53:31 -0700 Subject: [PATCH 0189/1056] blockchain: update IndexManager interface to use spent txos In this commit, we update the IndexManager interface to use spent txos rather than the unspent output set for a particualr block. We do this in order to improve the performance of the current address index which requires reconstructing the utxo view from the PoV of that new block. In practice, this is very slow as we need to perform a series of random reads in order to reconstruct the utxo set. Instead, we can use the set of SpentTxOut's for that block as this already contains the previous output scripts which is what all of the current indexers really need. --- blockchain/chain.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index c88bea6dd2..84996f312f 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -640,7 +640,7 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, // optional indexes with the block being connected so they can // update themselves accordingly. if b.indexManager != nil { - err := b.indexManager.ConnectBlock(dbTx, block, view) + err := b.indexManager.ConnectBlock(dbTx, block, stxos) if err != nil { return err } @@ -741,8 +741,15 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view return err } + // Before we delete the spend journal entry for this back, + // we'll fetch it as is so the indexers can utilize if needed. + stxos, err := dbFetchSpendJournalEntry(dbTx, block) + if err != nil { + return err + } + // Update the transaction spend journal by removing the record - // that contains all txos spent by the block . + // that contains all txos spent by the block. err = dbRemoveSpendJournalEntry(dbTx, block.Hash()) if err != nil { return err @@ -752,7 +759,7 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view // optional indexes with the block being disconnected so they // can update themselves accordingly. if b.indexManager != nil { - err := b.indexManager.DisconnectBlock(dbTx, block, view) + err := b.indexManager.DisconnectBlock(dbTx, block, stxos) if err != nil { return err } @@ -1571,12 +1578,16 @@ type IndexManager interface { Init(*BlockChain, <-chan struct{}) error // ConnectBlock is invoked when a new block has been connected to the - // main chain. - ConnectBlock(database.Tx, *btcutil.Block, *UtxoViewpoint) error + // main chain. The set of output spent within a block is also passed in + // so indexers can access the previous output scripts input spent if + // required. + ConnectBlock(database.Tx, *btcutil.Block, []SpentTxOut) error // DisconnectBlock is invoked when a block has been disconnected from - // the main chain. - DisconnectBlock(database.Tx, *btcutil.Block, *UtxoViewpoint) error + // the main chain. The set of outputs scripts that were spent within + // this block is also returned so indexers can clean up the prior index + // state for this block. + DisconnectBlock(database.Tx, *btcutil.Block, []SpentTxOut) error } // Config is a descriptor which specifies the blockchain instance configuration. From a26e2634fab381777ab8c3225e94918ff09476a0 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 28 May 2018 21:55:34 -0700 Subject: [PATCH 0190/1056] blockchain/indexers: update indexing to use stxos instead of utxo view for blocks In this commit, we update all the indexers to use the stxo set for a particular block rather than the utxo view for the block. We do this as we can eliminate a large number of random reads for each block, and can instead deserialize a single instance of all the outputs spent in that block and feed in the prev input scripts to each indexer. --- blockchain/indexers/addrindex.go | 37 ++++++++------ blockchain/indexers/cfindex.go | 4 +- blockchain/indexers/common.go | 18 ++++--- blockchain/indexers/manager.go | 87 ++++++++++++++++++-------------- blockchain/indexers/txindex.go | 8 ++- 5 files changed, 90 insertions(+), 64 deletions(-) diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 7d83de596e..29d9030a2c 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -692,23 +692,26 @@ func (idx *AddrIndex) indexPkScript(data writeIndexData, pkScript []byte, txIdx // indexBlock extract all of the standard addresses from all of the transactions // in the passed block and maps each of them to the associated transaction using // the passed map. -func (idx *AddrIndex) indexBlock(data writeIndexData, block *btcutil.Block, view *blockchain.UtxoViewpoint) { +func (idx *AddrIndex) indexBlock(data writeIndexData, block *btcutil.Block, + stxos []blockchain.SpentTxOut) { + + stxoIndex := 0 for txIdx, tx := range block.Transactions() { // Coinbases do not reference any inputs. Since the block is // required to have already gone through full validation, it has // already been proven on the first transaction in the block is // a coinbase. if txIdx != 0 { - for _, txIn := range tx.MsgTx().TxIn { - // The view should always have the input since - // the index contract requires it, however, be - // safe and simply ignore any missing entries. - entry := view.LookupEntry(txIn.PreviousOutPoint) - if entry == nil { - continue - } - - idx.indexPkScript(data, entry.PkScript(), txIdx) + for range tx.MsgTx().TxIn { + // We'll access the slice of all the + // transactions spent in this block properly + // ordered to fetch the previous input script. + pkScript := stxos[stxoIndex].PkScript + idx.indexPkScript(data, pkScript, txIdx) + + // With an input indexed, we'll advance the + // stxo coutner. + stxoIndex++ } } @@ -723,7 +726,9 @@ func (idx *AddrIndex) indexBlock(data writeIndexData, block *btcutil.Block, view // the transactions in the block involve. // // This is part of the Indexer interface. -func (idx *AddrIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func (idx *AddrIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, + stxos []blockchain.SpentTxOut) error { + // The offset and length of the transactions within the serialized // block. txLocs, err := block.TxLoc() @@ -739,7 +744,7 @@ func (idx *AddrIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view // Build all of the address to transaction mappings in a local map. addrsToTxns := make(writeIndexData) - idx.indexBlock(addrsToTxns, block, view) + idx.indexBlock(addrsToTxns, block, stxos) // Add all of the index entries for each address. addrIdxBucket := dbTx.Metadata().Bucket(addrIndexKey) @@ -761,10 +766,12 @@ func (idx *AddrIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view // each transaction in the block involve. // // This is part of the Indexer interface. -func (idx *AddrIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func (idx *AddrIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, + stxos []blockchain.SpentTxOut) error { + // Build all of the address to transaction mappings in a local map. addrsToTxns := make(writeIndexData) - idx.indexBlock(addrsToTxns, block, view) + idx.indexBlock(addrsToTxns, block, stxos) // Remove all of the index entries for each address. bucket := dbTx.Metadata().Bucket(addrIndexKey) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 9cbf1bd50c..5caee7fd86 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -202,7 +202,7 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, // connected to the main chain. This indexer adds a hash-to-cf mapping for // every passed block. This is part of the Indexer interface. func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, - view *blockchain.UtxoViewpoint) error { + stxos []blockchain.SpentTxOut) error { f, err := builder.BuildBasicFilter(block.MsgBlock()) if err != nil { @@ -226,7 +226,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, // disconnected from the main chain. This indexer removes the hash-to-cf // mapping for every passed block. This is part of the Indexer interface. func (idx *CfIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, - view *blockchain.UtxoViewpoint) error { + _ []blockchain.SpentTxOut) error { for _, key := range cfIndexKeys { err := dbDeleteFilterIdxEntry(dbTx, key, block.Hash()) diff --git a/blockchain/indexers/common.go b/blockchain/indexers/common.go index 9b0320dcf9..a912bb4c70 100644 --- a/blockchain/indexers/common.go +++ b/blockchain/indexers/common.go @@ -50,13 +50,17 @@ type Indexer interface { // every load, including the case the index was just created. Init() error - // ConnectBlock is invoked when the index manager is notified that a new - // block has been connected to the main chain. - ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error - - // DisconnectBlock is invoked when the index manager is notified that a - // block has been disconnected from the main chain. - DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error + // ConnectBlock is invoked when a new block has been connected to the + // main chain. The set of output spent within a block is also passed in + // so indexers can access the pevious output scripts input spent if + // required. + ConnectBlock(database.Tx, *btcutil.Block, []blockchain.SpentTxOut) error + + // DisconnectBlock is invoked when a block has been disconnected from + // the main chain. The set of outputs scripts that were spent within + // this block is also returned so indexers can clean up the prior index + // state for this block + DisconnectBlock(database.Tx, *btcutil.Block, []blockchain.SpentTxOut) error } // AssertError identifies an error that indicates an internal code consistency diff --git a/blockchain/indexers/manager.go b/blockchain/indexers/manager.go index a7d2af203c..cf6fbd9666 100644 --- a/blockchain/indexers/manager.go +++ b/blockchain/indexers/manager.go @@ -68,7 +68,9 @@ func dbFetchIndexerTip(dbTx database.Tx, idxKey []byte) (*chainhash.Hash, int32, // given block using the provided indexer and updates the tip of the indexer // accordingly. An error will be returned if the current tip for the indexer is // not the previous block for the passed block. -func dbIndexConnectBlock(dbTx database.Tx, indexer Indexer, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func dbIndexConnectBlock(dbTx database.Tx, indexer Indexer, block *btcutil.Block, + stxo []blockchain.SpentTxOut) error { + // Assert that the block being connected properly connects to the // current tip of the index. idxKey := indexer.Key() @@ -84,7 +86,7 @@ func dbIndexConnectBlock(dbTx database.Tx, indexer Indexer, block *btcutil.Block } // Notify the indexer with the connected block so it can index it. - if err := indexer.ConnectBlock(dbTx, block, view); err != nil { + if err := indexer.ConnectBlock(dbTx, block, stxo); err != nil { return err } @@ -96,7 +98,9 @@ func dbIndexConnectBlock(dbTx database.Tx, indexer Indexer, block *btcutil.Block // given block using the provided indexer and updates the tip of the indexer // accordingly. An error will be returned if the current tip for the indexer is // not the passed block. -func dbIndexDisconnectBlock(dbTx database.Tx, indexer Indexer, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func dbIndexDisconnectBlock(dbTx database.Tx, indexer Indexer, block *btcutil.Block, + stxo []blockchain.SpentTxOut) error { + // Assert that the block being disconnected is the current tip of the // index. idxKey := indexer.Key() @@ -113,7 +117,7 @@ func dbIndexDisconnectBlock(dbTx database.Tx, indexer Indexer, block *btcutil.Bl // Notify the indexer with the disconnected block so it can remove all // of the appropriate entries. - if err := indexer.DisconnectBlock(dbTx, block, view); err != nil { + if err := indexer.DisconnectBlock(dbTx, block, stxo); err != nil { return err } @@ -299,7 +303,8 @@ func (m *Manager) Init(chain *blockchain.BlockChain, interrupt <-chan struct{}) // loaded directly since it is no longer in the main // chain and thus the chain.BlockByHash function would // error. - err = m.db.Update(func(dbTx database.Tx) error { + var block *btcutil.Block + err := m.db.View(func(dbTx database.Tx) error { blockBytes, err := dbTx.FetchBlock(hash) if err != nil { return err @@ -309,24 +314,27 @@ func (m *Manager) Init(chain *blockchain.BlockChain, interrupt <-chan struct{}) return err } block.SetHeight(height) + return err + }) + if err != nil { + return err + } - // When the index requires all of the referenced - // txouts they need to be retrieved from the - // transaction index. - var view *blockchain.UtxoViewpoint - if indexNeedsInputs(indexer) { - var err error - view, err = makeUtxoView(dbTx, block, - interrupt) - if err != nil { - return err - } - } + // We'll also grab the set of outputs spent by this + // block so we can remove them from the index. + spentTxos, err := chain.FetchSpendJournal(block) + if err != nil { + return err + } + // With the block and stxo set for that block retrieved, + // we can now update the index itself. + err = m.db.Update(func(dbTx database.Tx) error { // Remove all of the index entries associated // with the block and update the indexer tip. - err = dbIndexDisconnectBlock(dbTx, indexer, - block, view) + err = dbIndexDisconnectBlock( + dbTx, indexer, block, spentTxos, + ) if err != nil { return err } @@ -407,7 +415,7 @@ func (m *Manager) Init(chain *blockchain.BlockChain, interrupt <-chan struct{}) } // Connect the block for all indexes that need it. - var view *blockchain.UtxoViewpoint + var spentTxos []blockchain.SpentTxOut for i, indexer := range m.enabledIndexes { // Skip indexes that don't need to be updated with this // block. @@ -415,21 +423,20 @@ func (m *Manager) Init(chain *blockchain.BlockChain, interrupt <-chan struct{}) continue } - err := m.db.Update(func(dbTx database.Tx) error { - // When the index requires all of the referenced - // txouts and they haven't been loaded yet, they - // need to be retrieved from the transaction - // index. - if view == nil && indexNeedsInputs(indexer) { - var err error - view, err = makeUtxoView(dbTx, block, - interrupt) - if err != nil { - return err - } + // When the index requires all of the referenced txouts + // and they haven't been loaded yet, they need to be + // retrieved from the spend journal. + if spentTxos == nil && indexNeedsInputs(indexer) { + spentTxos, err = chain.FetchSpendJournal(block) + if err != nil { + return err } - return dbIndexConnectBlock(dbTx, indexer, block, - view) + } + + err := m.db.Update(func(dbTx database.Tx) error { + return dbIndexConnectBlock( + dbTx, indexer, block, spentTxos, + ) }) if err != nil { return err @@ -528,11 +535,13 @@ func makeUtxoView(dbTx database.Tx, block *btcutil.Block, interrupt <-chan struc // checks, and invokes each indexer. // // This is part of the blockchain.IndexManager interface. -func (m *Manager) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func (m *Manager) ConnectBlock(dbTx database.Tx, block *btcutil.Block, + stxos []blockchain.SpentTxOut) error { + // Call each of the currently active optional indexes with the block // being connected so they can update accordingly. for _, index := range m.enabledIndexes { - err := dbIndexConnectBlock(dbTx, index, block, view) + err := dbIndexConnectBlock(dbTx, index, block, stxos) if err != nil { return err } @@ -546,11 +555,13 @@ func (m *Manager) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blo // the index entries associated with the block. // // This is part of the blockchain.IndexManager interface. -func (m *Manager) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func (m *Manager) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, + stxo []blockchain.SpentTxOut) error { + // Call each of the currently active optional indexes with the block // being disconnected so they can update accordingly. for _, index := range m.enabledIndexes { - err := dbIndexDisconnectBlock(dbTx, index, block, view) + err := dbIndexDisconnectBlock(dbTx, index, block, stxo) if err != nil { return err } diff --git a/blockchain/indexers/txindex.go b/blockchain/indexers/txindex.go index 51fad698aa..00cfd00621 100644 --- a/blockchain/indexers/txindex.go +++ b/blockchain/indexers/txindex.go @@ -388,7 +388,9 @@ func (idx *TxIndex) Create(dbTx database.Tx) error { // for every transaction in the passed block. // // This is part of the Indexer interface. -func (idx *TxIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func (idx *TxIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, + stxos []blockchain.SpentTxOut) error { + // Increment the internal block ID to use for the block being connected // and add all of the transactions in the block to the index. newBlockID := idx.curBlockID + 1 @@ -411,7 +413,9 @@ func (idx *TxIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, view *b // hash-to-transaction mapping for every transaction in the block. // // This is part of the Indexer interface. -func (idx *TxIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, view *blockchain.UtxoViewpoint) error { +func (idx *TxIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, + stxos []blockchain.SpentTxOut) error { + // Remove all of the transactions in the block from the index. if err := dbRemoveTxIndexEntries(dbTx, block); err != nil { return err From 347cd3839f98054e274cbef5c57315ad3f2a40f1 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 29 May 2018 17:06:59 -0700 Subject: [PATCH 0191/1056] btcec/signature_test: adds small pubkey recovery tests --- btcec/signature_test.go | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/btcec/signature_test.go b/btcec/signature_test.go index a8b3e1e98c..a4b86bb828 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -11,6 +11,7 @@ import ( "encoding/hex" "fmt" "math/big" + "reflect" "testing" ) @@ -523,6 +524,67 @@ func TestSignCompact(t *testing.T) { } } +// recoveryTests assert basic tests for public key recovery from signatures. +// The cases are borrowed from github.com/fjl/btcec-issue. +var recoveryTests = []struct { + msg string + sig string + pub string + err error +}{ + { + // Valid curve point recovered. + msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", + sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549984a691139ad57a3f0b906637673aa2f63d1f55cb1a69199d4009eea23ceaddc93", + pub: "04E32DF42865E97135ACFB65F3BAE71BDC86F4D49150AD6A440B6F15878109880A0A2B2667F7E725CEEA70C673093BF67663E0312623C8E091B13CF2C0F11EF652", + }, + { + // Invalid curve point recovered. + msg: "00c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c", + sig: "0100b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f00b940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", + err: fmt.Errorf("invalid square root"), + }, + { + // Low R and S values. + msg: "ba09edc1275a285fb27bfe82c4eea240a907a0dbaf9e55764b8f318c37d5974f", + sig: "00000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000004", + pub: "04A7640409AA2083FDAD38B2D8DE1263B2251799591D840653FB02DBBA503D7745FCB83D80E08A1E02896BE691EA6AFFB8A35939A646F1FC79052A744B1C82EDC3", + }, +} + +func TestRecoverCompact(t *testing.T) { + for i, test := range recoveryTests { + msg := decodeHex(test.msg) + sig := decodeHex(test.sig) + + // Magic DER constant. + sig[0] += 27 + + pub, _, err := RecoverCompact(S256(), sig, msg) + + // Verify that returned error matches as expected. + if !reflect.DeepEqual(test.err, err) { + t.Errorf("unexpected error returned from pubkey "+ + "recovery #%d: wanted %v, got %v", + i, test.err, err) + continue + } + + // If check succeeded because a proper error was returned, we + // ignore the returned pubkey. + if err != nil { + continue + } + + // Otherwise, ensure the correct public key was recovered. + exPub, _ := ParsePubKey(decodeHex(test.pub), S256()) + if !exPub.IsEqual(pub) { + t.Errorf("unexpected recovered public key #%d: "+ + "want %v, got %v", i, exPub, pub) + } + } +} + func TestRFC6979(t *testing.T) { // Test vectors matching Trezor and CoreBitcoin implementations. // - https://github.com/trezor/trezor-crypto/blob/9fea8f8ab377dc514e40c6fd1f7c89a74c1d8dc6/tests.c#L432-L453 From fbe1bfa659c8fc23825433dd8ac75f9fc902b983 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 6 Jul 2018 21:40:27 +0200 Subject: [PATCH 0192/1056] server: print full name of cf index in main log --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index f3e4c9f70b..cbc13bc6dc 100644 --- a/server.go +++ b/server.go @@ -2493,7 +2493,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param indexes = append(indexes, s.addrIndex) } if !cfg.NoCFilters { - indxLog.Info("cf index is enabled") + indxLog.Info("Committed filter index is enabled") s.cfIndex = indexers.NewCfIndex(db, chainParams) indexes = append(indexes, s.cfIndex) } From 98769ddbdf2429380fdc54bd5465bf22293213e0 Mon Sep 17 00:00:00 2001 From: Tzu-Jung Lee Date: Wed, 30 May 2018 13:41:32 -0700 Subject: [PATCH 0193/1056] docs: Update example links in README --- rpcclient/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpcclient/README.md b/rpcclient/README.md index b6077d2a82..06be0d69e1 100644 --- a/rpcclient/README.md +++ b/rpcclient/README.md @@ -19,15 +19,15 @@ implement and the API is not stable yet. ## Documentation * [API Reference](http://godoc.org/github.com/btcsuite/btcd/rpcclient) -* [btcd Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcdwebsockets) +* [btcd Websockets Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/btcdwebsockets) Connects to a btcd RPC server using TLS-secured websockets, registers for block connected and block disconnected notifications, and gets the current block count -* [btcwallet Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcwalletwebsockets) +* [btcwallet Websockets Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/btcwalletwebsockets) Connects to a btcwallet RPC server using TLS-secured websockets, registers for notifications about changes to account balances, and gets a list of unspent transaction outputs (utxos) the wallet can sign -* [Bitcoin Core HTTP POST Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/bitcoincorehttp) +* [Bitcoin Core HTTP POST Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/bitcoincorehttp) Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled and gets the current block count From 1d99af29c73bc93e751f1679a5aa59cdd1bd2e84 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 6 Jul 2018 13:06:00 -0700 Subject: [PATCH 0194/1056] btcjson: fix formatting directives --- btcjson/chainsvrcmds_test.go | 4 ++-- btcjson/cmdparse_test.go | 12 ++++++------ btcjson/help_test.go | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 12fba7d9d1..0b3c7b7c3b 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1191,8 +1191,8 @@ func TestChainSvrCmdErrors(t *testing.T) { for i, test := range tests { err := json.Unmarshal([]byte(test.marshalled), &test.result) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { - t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+ - "want %T", i, test.name, err, test.err) + t.Errorf("Test #%d (%s) wrong error - got %T (%v), "+ + "want %T", i, test.name, err, err, test.err) continue } diff --git a/btcjson/cmdparse_test.go b/btcjson/cmdparse_test.go index 2f8fa1fb96..7c13a0bb44 100644 --- a/btcjson/cmdparse_test.go +++ b/btcjson/cmdparse_test.go @@ -387,8 +387,8 @@ func TestNewCmdErrors(t *testing.T) { for i, test := range tests { _, err := btcjson.NewCmd(test.method, test.args...) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { - t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+ - "want %T", i, test.name, err, test.err) + t.Errorf("Test #%d (%s) wrong error - got %T (%v), "+ + "want %T", i, test.name, err, err, test.err) continue } gotErrorCode := err.(btcjson.Error).ErrorCode @@ -435,8 +435,8 @@ func TestMarshalCmdErrors(t *testing.T) { for i, test := range tests { _, err := btcjson.MarshalCmd(test.id, test.cmd) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { - t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+ - "want %T", i, test.name, err, test.err) + t.Errorf("Test #%d (%s) wrong error - got %T (%v), "+ + "want %T", i, test.name, err, err, test.err) continue } gotErrorCode := err.(btcjson.Error).ErrorCode @@ -504,8 +504,8 @@ func TestUnmarshalCmdErrors(t *testing.T) { for i, test := range tests { _, err := btcjson.UnmarshalCmd(&test.request) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { - t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+ - "want %T", i, test.name, err, test.err) + t.Errorf("Test #%d (%s) wrong error - got %T (%v), "+ + "want %T", i, test.name, err, err, test.err) continue } gotErrorCode := err.(btcjson.Error).ErrorCode diff --git a/btcjson/help_test.go b/btcjson/help_test.go index 265e0c2c60..918aa14479 100644 --- a/btcjson/help_test.go +++ b/btcjson/help_test.go @@ -699,8 +699,8 @@ func TestGenerateHelpErrors(t *testing.T) { _, err := btcjson.GenerateHelp(test.method, nil, test.resultTypes...) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { - t.Errorf("Test #%d (%s) wrong error - got %T (%[2]v), "+ - "want %T", i, test.name, err, test.err) + t.Errorf("Test #%d (%s) wrong error - got %T (%v), "+ + "want %T", i, test.name, err, err, test.err) continue } gotErrorCode := err.(btcjson.Error).ErrorCode From 28d4261c2d336ac097aaf25761bd35d6fad80b0f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 6 Jul 2018 15:38:44 -0700 Subject: [PATCH 0195/1056] build: update glide for btcutil w/ latest BIP 158 --- glide.lock | 6 +++--- glide.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/glide.lock b/glide.lock index fb1bf674db..c101cf19d4 100644 --- a/glide.lock +++ b/glide.lock @@ -1,12 +1,12 @@ -hash: c8cc08c3afbedc99feda4fed38a64bb1aa42da128520dcac028cfc7e7de06a6e -updated: 2018-05-23T20:46:41.891755246-07:00 +hash: 30562f0035d9bb4d4ee531762e4f7f762ede916255e9aa781df58537651f7382 +updated: 2018-07-06T16:07:52.877260592-07:00 imports: - name: github.com/aead/siphash version: e404fcfc888570cadd1610538e2dbc89f66af814 - name: github.com/btcsuite/btclog version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a - name: github.com/btcsuite/btcutil - version: d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4 + version: ab6388e0c60ae4834a1f57511e20c17b5f78be4b subpackages: - base58 - bech32 diff --git a/glide.yaml b/glide.yaml index 59dd550e44..554610048a 100644 --- a/glide.yaml +++ b/glide.yaml @@ -2,7 +2,7 @@ package: github.com/btcsuite/btcd import: - package: github.com/btcsuite/btclog - package: github.com/btcsuite/btcutil - version: d4cc87b860166d00d6b5b9e0d3b3d71d6088d4d4 + version: ab6388e0c60ae4834a1f57511e20c17b5f78be4b subpackages: - bloom - hdkeychain From 66d632f32e76580a24bb0cd569fcebab44d45468 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 30 May 2018 20:54:23 -0700 Subject: [PATCH 0196/1056] wire: remove the extended filter --- wire/msgcfilter.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index 7387587fd4..097590b2ce 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -17,9 +17,6 @@ type FilterType uint8 const ( // GCSFilterRegular is the regular filter type. GCSFilterRegular FilterType = iota - - // GCSFilterExtended is the extended filter type. - GCSFilterExtended ) const ( From 942116c5ae393582e56df918a23b76b7511ded71 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 30 May 2018 20:54:34 -0700 Subject: [PATCH 0197/1056] rpc: remove extended fitler from help --- rpcserverhelp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 489e9a871f..c875d217aa 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -334,13 +334,13 @@ var helpDescsEnUS = map[string]string{ // GetCFilterCmd help. "getcfilter--synopsis": "Returns a block's committed filter given its hash.", - "getcfilter-filtertype": "The type of filter to return (0=regular, 1=extended)", + "getcfilter-filtertype": "The type of filter to return (0=regular)", "getcfilter-hash": "The hash of the block", "getcfilter--result0": "The block's committed filter", // GetCFilterHeaderCmd help. "getcfilterheader--synopsis": "Returns a block's compact filter header given its hash.", - "getcfilterheader-filtertype": "The type of filter header to return (0=regular, 1=extended)", + "getcfilterheader-filtertype": "The type of filter header to return (0=regular)", "getcfilterheader-hash": "The hash of the block", "getcfilterheader--result0": "The block's gcs filter header", From 576800a99ec8e1fdeca94bfece6a760a09fc87a7 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 30 May 2018 20:54:56 -0700 Subject: [PATCH 0198/1056] blockchain/indexer: remove extended filter --- blockchain/indexers/cfindex.go | 45 ++++++++++++---------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 5caee7fd86..c16c3a08c0 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -22,39 +22,36 @@ const ( cfIndexName = "committed filter index" ) -// Committed filters come in two flavours: basic and extended. They are -// generated and dropped in pairs, and both are indexed by a block's hash. -// Besides holding different content, they also live in different buckets. +// Committed filters come in one flavor currently: basic. They are generated +// and dropped in pairs, and both are indexed by a block's hash. Besides +// holding different content, they also live in different buckets. var ( - // cfIndexParentBucketKey is the name of the parent bucket used to house - // the index. The rest of the buckets live below this bucket. + // cfIndexParentBucketKey is the name of the parent bucket used to + // house the index. The rest of the buckets live below this bucket. cfIndexParentBucketKey = []byte("cfindexparentbucket") // cfIndexKeys is an array of db bucket names used to house indexes of // block hashes to cfilters. cfIndexKeys = [][]byte{ []byte("cf0byhashidx"), - []byte("cf1byhashidx"), } // cfHeaderKeys is an array of db bucket names used to house indexes of // block hashes to cf headers. cfHeaderKeys = [][]byte{ []byte("cf0headerbyhashidx"), - []byte("cf1headerbyhashidx"), } // cfHashKeys is an array of db bucket names used to house indexes of // block hashes to cf hashes. cfHashKeys = [][]byte{ []byte("cf0hashbyhashidx"), - []byte("cf1hashbyhashidx"), } maxFilterType = uint8(len(cfHeaderKeys) - 1) - // zeroHash is the chainhash.Hash value of all zero bytes, defined here for - // convenience. + // zeroHash is the chainhash.Hash value of all zero bytes, defined here + // for convenience. zeroHash chainhash.Hash ) @@ -106,7 +103,7 @@ func (idx *CfIndex) Name() string { // Create is invoked when the indexer manager determines the index needs to // be created for the first time. It creates buckets for the two hash-based cf -// indexes (simple, extended). +// indexes (regular only currently). func (idx *CfIndex) Create(dbTx database.Tx) error { meta := dbTx.Metadata() @@ -209,17 +206,7 @@ func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, return err } - err = storeFilter(dbTx, block, f, wire.GCSFilterRegular) - if err != nil { - return err - } - - f, err = builder.BuildExtFilter(block.MsgBlock()) - if err != nil { - return err - } - - return storeFilter(dbTx, block, f, wire.GCSFilterExtended) + return storeFilter(dbTx, block, f, wire.GCSFilterRegular) } // DisconnectBlock is invoked by the index manager when a block has been @@ -296,42 +283,42 @@ func (idx *CfIndex) entriesByBlockHashes(filterTypeKeys [][]byte, } // FilterByBlockHash returns the serialized contents of a block's basic or -// extended committed filter. +// committed filter. func (idx *CfIndex) FilterByBlockHash(h *chainhash.Hash, filterType wire.FilterType) ([]byte, error) { return idx.entryByBlockHash(cfIndexKeys, filterType, h) } // FiltersByBlockHashes returns the serialized contents of a block's basic or -// extended committed filter for a set of blocks by hash. +// committed filter for a set of blocks by hash. func (idx *CfIndex) FiltersByBlockHashes(blockHashes []*chainhash.Hash, filterType wire.FilterType) ([][]byte, error) { return idx.entriesByBlockHashes(cfIndexKeys, filterType, blockHashes) } // FilterHeaderByBlockHash returns the serialized contents of a block's basic -// or extended committed filter header. +// committed filter header. func (idx *CfIndex) FilterHeaderByBlockHash(h *chainhash.Hash, filterType wire.FilterType) ([]byte, error) { return idx.entryByBlockHash(cfHeaderKeys, filterType, h) } -// FilterHeadersByBlockHashes returns the serialized contents of a block's basic -// or extended committed filter header for a set of blocks by hash. +// FilterHeadersByBlockHashes returns the serialized contents of a block's +// basic committed filter header for a set of blocks by hash. func (idx *CfIndex) FilterHeadersByBlockHashes(blockHashes []*chainhash.Hash, filterType wire.FilterType) ([][]byte, error) { return idx.entriesByBlockHashes(cfHeaderKeys, filterType, blockHashes) } // FilterHashByBlockHash returns the serialized contents of a block's basic -// or extended committed filter hash. +// committed filter hash. func (idx *CfIndex) FilterHashByBlockHash(h *chainhash.Hash, filterType wire.FilterType) ([]byte, error) { return idx.entryByBlockHash(cfHashKeys, filterType, h) } // FilterHashesByBlockHashes returns the serialized contents of a block's basic -// or extended committed filter hash for a set of blocks by hash. +// committed filter hash for a set of blocks by hash. func (idx *CfIndex) FilterHashesByBlockHashes(blockHashes []*chainhash.Hash, filterType wire.FilterType) ([][]byte, error) { return idx.entriesByBlockHashes(cfHashKeys, filterType, blockHashes) From 102ca293f6cbdbda19c21697c25b66febc1a1bb9 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 14 Jun 2018 17:50:39 -0700 Subject: [PATCH 0199/1056] blockchain: pass in prevScript for constructing the basic filter --- blockchain/indexers/cfindex.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index c16c3a08c0..f8081be877 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -201,7 +201,12 @@ func storeFilter(dbTx database.Tx, block *btcutil.Block, f *gcs.Filter, func (idx *CfIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block, stxos []blockchain.SpentTxOut) error { - f, err := builder.BuildBasicFilter(block.MsgBlock()) + prevScripts := make([][]byte, len(stxos)) + for i, stxo := range stxos { + prevScripts[i] = stxo.PkScript + } + + f, err := builder.BuildBasicFilter(block.MsgBlock(), prevScripts) if err != nil { return err } From 298efd83591d109d672e11d93bc27b962a0e0a8b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 6 Jul 2018 12:38:17 -0700 Subject: [PATCH 0200/1056] blockchain/indexers: ensure the cfindex gets inputs --- blockchain/indexers/cfindex.go | 11 +++++++++++ blockchain/indexers/manager.go | 36 ---------------------------------- 2 files changed, 11 insertions(+), 36 deletions(-) diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index f8081be877..8ea147282b 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -83,6 +83,17 @@ type CfIndex struct { // Ensure the CfIndex type implements the Indexer interface. var _ Indexer = (*CfIndex)(nil) +// Ensure the CfIndex type implements the NeedsInputser interface. +var _ NeedsInputser = (*CfIndex)(nil) + +// NeedsInputs signals that the index requires the referenced inputs in order +// to properly create the index. +// +// This implements the NeedsInputser interface. +func (idx *CfIndex) NeedsInputs() bool { + return true +} + // Init initializes the hash-based cf index. This is part of the Indexer // interface. func (idx *CfIndex) Init() error { diff --git a/blockchain/indexers/manager.go b/blockchain/indexers/manager.go index cf6fbd9666..09dae62118 100644 --- a/blockchain/indexers/manager.go +++ b/blockchain/indexers/manager.go @@ -494,42 +494,6 @@ func dbFetchTx(dbTx database.Tx, hash *chainhash.Hash) (*wire.MsgTx, error) { return &msgTx, nil } -// makeUtxoView creates a mock unspent transaction output view by using the -// transaction index in order to look up all inputs referenced by the -// transactions in the block. This is sometimes needed when catching indexes up -// because many of the txouts could actually already be spent however the -// associated scripts are still required to index them. -func makeUtxoView(dbTx database.Tx, block *btcutil.Block, interrupt <-chan struct{}) (*blockchain.UtxoViewpoint, error) { - view := blockchain.NewUtxoViewpoint() - for txIdx, tx := range block.Transactions() { - // Coinbases do not reference any inputs. Since the block is - // required to have already gone through full validation, it has - // already been proven on the first transaction in the block is - // a coinbase. - if txIdx == 0 { - continue - } - - // Use the transaction index to load all of the referenced - // inputs and add their outputs to the view. - for _, txIn := range tx.MsgTx().TxIn { - originOut := &txIn.PreviousOutPoint - originTx, err := dbFetchTx(dbTx, &originOut.Hash) - if err != nil { - return nil, err - } - - view.AddTxOuts(btcutil.NewTx(originTx), 0) - } - - if interruptRequested(interrupt) { - return nil, errInterruptRequested - } - } - - return view, nil -} - // ConnectBlock must be invoked when a block is extending the main chain. It // keeps track of the state of each index it is managing, performs some sanity // checks, and invokes each indexer. From a05f62fabdec985789817f1c1be1223cd9195531 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 6 Jul 2018 15:47:02 -0700 Subject: [PATCH 0201/1056] btcjson: remove instances of the extended gcs filter --- btcjson/chainsvrcmds_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 0b3c7b7c3b..8cb4ee765a 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -322,32 +322,32 @@ func TestChainSvrCmds(t *testing.T) { name: "getcfilter", newCmd: func() (interface{}, error) { return btcjson.NewCmd("getcfilter", "123", - wire.GCSFilterExtended) + wire.GCSFilterRegular) }, staticCmd: func() interface{} { return btcjson.NewGetCFilterCmd("123", - wire.GCSFilterExtended) + wire.GCSFilterRegular) }, - marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",1],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123",0],"id":1}`, unmarshalled: &btcjson.GetCFilterCmd{ Hash: "123", - FilterType: wire.GCSFilterExtended, + FilterType: wire.GCSFilterRegular, }, }, { name: "getcfilterheader", newCmd: func() (interface{}, error) { return btcjson.NewCmd("getcfilterheader", "123", - wire.GCSFilterExtended) + wire.GCSFilterRegular) }, staticCmd: func() interface{} { return btcjson.NewGetCFilterHeaderCmd("123", - wire.GCSFilterExtended) + wire.GCSFilterRegular) }, - marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",1],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",0],"id":1}`, unmarshalled: &btcjson.GetCFilterHeaderCmd{ Hash: "123", - FilterType: wire.GCSFilterExtended, + FilterType: wire.GCSFilterRegular, }, }, { From 21b0303341865fea274e53557af44e2f21ec5f81 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 6 Jul 2018 15:47:15 -0700 Subject: [PATCH 0202/1056] wire: remove instances of the extended gcs filter --- wire/message_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wire/message_test.go b/wire/message_test.go index a174c49aff..3a422e66ba 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -69,13 +69,13 @@ func TestMessage(t *testing.T) { bh := NewBlockHeader(1, &chainhash.Hash{}, &chainhash.Hash{}, 0, 0) msgMerkleBlock := NewMsgMerkleBlock(bh) msgReject := NewMsgReject("block", RejectDuplicate, "duplicate block") - msgGetCFilters := NewMsgGetCFilters(GCSFilterExtended, 0, &chainhash.Hash{}) - msgGetCFHeaders := NewMsgGetCFHeaders(GCSFilterExtended, 0, &chainhash.Hash{}) - msgGetCFCheckpt := NewMsgGetCFCheckpt(GCSFilterExtended, &chainhash.Hash{}) - msgCFilter := NewMsgCFilter(GCSFilterExtended, &chainhash.Hash{}, + msgGetCFilters := NewMsgGetCFilters(GCSFilterRegular, 0, &chainhash.Hash{}) + msgGetCFHeaders := NewMsgGetCFHeaders(GCSFilterRegular, 0, &chainhash.Hash{}) + msgGetCFCheckpt := NewMsgGetCFCheckpt(GCSFilterRegular, &chainhash.Hash{}) + msgCFilter := NewMsgCFilter(GCSFilterRegular, &chainhash.Hash{}, []byte("payload")) msgCFHeaders := NewMsgCFHeaders() - msgCFCheckpt := NewMsgCFCheckpt(GCSFilterExtended, &chainhash.Hash{}, 0) + msgCFCheckpt := NewMsgCFCheckpt(GCSFilterRegular, &chainhash.Hash{}, 0) tests := []struct { in Message // Value to encode From b091d71646296e961b49b28d51a25e241fc26d66 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 11 Jul 2018 19:41:17 -0500 Subject: [PATCH 0203/1056] blockchain: Generalize chain reorg. This generalizes the reorganizeChain function in the blockchain package to allow it to rewind the chain in the case no attach nodes are provided or extend the chain in the case no detach nodes are provided. It also adds several assertions to ensure the assumptions about the state hold and cleans up the handling of setting invalid ancestor nodes in the case of a failed block validation. --- blockchain/chain.go | 92 +++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 24 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 84996f312f..c13fabd9ae 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1,4 +1,5 @@ -// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2013-2018 The btcsuite developers +// Copyright (c) 2015-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -819,6 +820,38 @@ func countSpentOutputs(block *btcutil.Block) int { // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error { + // Nothing to do if no reorganize nodes were provided. + if detachNodes.Len() == 0 && attachNodes.Len() == 0 { + return nil + } + + // Ensure the provided nodes match the current best chain. + tip := b.bestChain.Tip() + if detachNodes.Len() != 0 { + firstDetachNode := detachNodes.Front().Value.(*blockNode) + if firstDetachNode.hash != tip.hash { + return AssertError(fmt.Sprintf("reorganize nodes to detach are "+ + "not for the current best chain -- first detach node %v, "+ + "current chain %v", &firstDetachNode.hash, &tip.hash)) + } + } + + // Ensure the provided nodes are for the same fork point. + if attachNodes.Len() != 0 && detachNodes.Len() != 0 { + firstAttachNode := attachNodes.Front().Value.(*blockNode) + lastDetachNode := detachNodes.Back().Value.(*blockNode) + if firstAttachNode.parent.hash != lastDetachNode.parent.hash { + return AssertError(fmt.Sprintf("reorganize nodes do not have the "+ + "same fork point -- first attach parent %v, last detach "+ + "parent %v", &firstAttachNode.parent.hash, + &lastDetachNode.parent.hash)) + } + } + + // Track the old and new best chains heads. + oldBest := tip + newBest := tip + // All of the blocks to detach and related spend journal entries needed // to unspend transaction outputs in the blocks being disconnected must // be loaded from the database during the reorg check phase below and @@ -833,7 +866,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // database and using that information to unspend all of the spent txos // and remove the utxos created by the blocks. view := NewUtxoViewpoint() - view.SetBestHash(&b.bestChain.Tip().hash) + view.SetBestHash(&oldBest.hash) for e := detachNodes.Front(); e != nil; e = e.Next() { n := e.Value.(*blockNode) var block *btcutil.Block @@ -845,6 +878,11 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error if err != nil { return err } + if n.hash != *block.Hash() { + return AssertError(fmt.Sprintf("detach block node hash %v (height "+ + "%v) does not match previous parent block hash %v", &n.hash, + n.height, block.Hash())) + } // Load all of the utxos referenced by the block that aren't // already in the view. @@ -872,6 +910,15 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error if err != nil { return err } + + newBest = n.parent + } + + // Set the fork point only if there are nodes to attach since otherwise + // blocks are only being disconnected and thus there is no fork point. + var forkNode *blockNode + if attachNodes.Len() > 0 { + forkNode = newBest } // Perform several checks to verify each block that needs to be attached @@ -886,17 +933,9 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // at least a couple of ways accomplish that rollback, but both involve // tweaking the chain and/or database. This approach catches these // issues before ever modifying the chain. - var validationError error for e := attachNodes.Front(); e != nil; e = e.Next() { n := e.Value.(*blockNode) - // If any previous nodes in attachNodes failed validation, - // mark this one as having an invalid ancestor. - if validationError != nil { - b.index.SetStatusFlags(n, statusInvalidAncestor) - continue - } - var block *btcutil.Block err := b.db.View(func(dbTx database.Tx) error { var err error @@ -922,6 +961,8 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error if err != nil { return err } + + newBest = n continue } @@ -929,23 +970,24 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // thus will not be generated. This is done because the state // is not being immediately written to the database, so it is // not needed. + // + // In the case the block is determined to be invalid due to a + // rule violation, mark it as invalid and mark all of its + // descendants as having an invalid ancestor. err = b.checkConnectBlock(n, block, view, nil) if err != nil { - // If the block failed validation mark it as invalid, then - // continue to loop through remaining nodes, marking them as - // having an invalid ancestor. if _, ok := err.(RuleError); ok { b.index.SetStatusFlags(n, statusValidateFailed) - validationError = err - continue + for de := e.Next(); de != nil; de = de.Next() { + dn := de.Value.(*blockNode) + b.index.SetStatusFlags(dn, statusInvalidAncestor) + } } return err } b.index.SetStatusFlags(n, statusValid) - } - if validationError != nil { - return validationError + newBest = n } // Reset the view for the actual connection code below. This is @@ -1014,12 +1056,14 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Log the point where the chain forked and old and new best chain // heads. - firstAttachNode := attachNodes.Front().Value.(*blockNode) - firstDetachNode := detachNodes.Front().Value.(*blockNode) - lastAttachNode := attachNodes.Back().Value.(*blockNode) - log.Infof("REORGANIZE: Chain forks at %v", firstAttachNode.parent.hash) - log.Infof("REORGANIZE: Old best chain head was %v", firstDetachNode.hash) - log.Infof("REORGANIZE: New best chain head is %v", lastAttachNode.hash) + if forkNode != nil { + log.Infof("REORGANIZE: Chain forks at %v (height %v)", forkNode.hash, + forkNode.height) + } + log.Infof("REORGANIZE: Old best chain head was %v (height %v)", + &oldBest.hash, oldBest.height) + log.Infof("REORGANIZE: New best chain head is %v (height %v)", + newBest.hash, newBest.height) return nil } From f7366fb51b496fa70de3816ce51344c0a143cb5f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 14 Jul 2018 12:20:20 -0700 Subject: [PATCH 0204/1056] server: ensure we only fetch filters we know of --- server.go | 111 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/server.go b/server.go index cbc13bc6dc..12925eeabb 100644 --- a/server.go +++ b/server.go @@ -762,8 +762,21 @@ func (sp *serverPeer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) { return } - hashes, err := sp.server.chain.HeightToHashRange(int32(msg.StartHeight), - &msg.StopHash, wire.MaxGetCFiltersReqRange) + // We'll also ensure that the remote party is requesting a set of + // filters that we actually currently maintain. + switch msg.FilterType { + case wire.GCSFilterRegular: + break + + default: + peerLog.Debug("Filter request for unknown filter: %v", + msg.FilterType) + return + } + + hashes, err := sp.server.chain.HeightToHashRange( + int32(msg.StartHeight), &msg.StopHash, wire.MaxGetCFiltersReqRange, + ) if err != nil { peerLog.Debugf("Invalid getcfilters request: %v", err) return @@ -776,8 +789,9 @@ func (sp *serverPeer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) { hashPtrs[i] = &hashes[i] } - filters, err := sp.server.cfIndex.FiltersByBlockHashes(hashPtrs, - msg.FilterType) + filters, err := sp.server.cfIndex.FiltersByBlockHashes( + hashPtrs, msg.FilterType, + ) if err != nil { peerLog.Errorf("Error retrieving cfilters: %v", err) return @@ -785,10 +799,14 @@ func (sp *serverPeer) OnGetCFilters(_ *peer.Peer, msg *wire.MsgGetCFilters) { for i, filterBytes := range filters { if len(filterBytes) == 0 { - peerLog.Warnf("Could not obtain cfilter for %v", hashes[i]) + peerLog.Warnf("Could not obtain cfilter for %v", + hashes[i]) return } - filterMsg := wire.NewMsgCFilter(msg.FilterType, &hashes[i], filterBytes) + + filterMsg := wire.NewMsgCFilter( + msg.FilterType, &hashes[i], filterBytes, + ) sp.QueueMessage(filterMsg, nil) } } @@ -800,19 +818,32 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { return } + // We'll also ensure that the remote party is requesting a set of + // headers for filters that we actually currently maintain. + switch msg.FilterType { + case wire.GCSFilterRegular: + break + + default: + peerLog.Debug("Filter request for unknown headers for "+ + "filter: %v", msg.FilterType) + return + } + startHeight := int32(msg.StartHeight) maxResults := wire.MaxCFHeadersPerMsg - // If StartHeight is positive, fetch the predecessor block hash so we can - // populate the PrevFilterHeader field. + // If StartHeight is positive, fetch the predecessor block hash so we + // can populate the PrevFilterHeader field. if msg.StartHeight > 0 { startHeight-- maxResults++ } // Fetch the hashes from the block index. - hashList, err := sp.server.chain.HeightToHashRange(startHeight, - &msg.StopHash, maxResults) + hashList, err := sp.server.chain.HeightToHashRange( + startHeight, &msg.StopHash, maxResults, + ) if err != nil { peerLog.Debugf("Invalid getcfheaders request: %v", err) } @@ -833,8 +864,9 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { } // Fetch the raw filter hash bytes from the database for all blocks. - filterHashes, err := sp.server.cfIndex.FilterHashesByBlockHashes(hashPtrs, - msg.FilterType) + filterHashes, err := sp.server.cfIndex.FilterHashesByBlockHashes( + hashPtrs, msg.FilterType, + ) if err != nil { peerLog.Errorf("Error retrieving cfilter hashes: %v", err) return @@ -892,6 +924,7 @@ func (sp *serverPeer) OnGetCFHeaders(_ *peer.Peer, msg *wire.MsgGetCFHeaders) { headersMsg.FilterType = msg.FilterType headersMsg.StopHash = msg.StopHash + sp.QueueMessage(headersMsg, nil) } @@ -902,21 +935,38 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { return } - blockHashes, err := sp.server.chain.IntervalBlockHashes(&msg.StopHash, - wire.CFCheckptInterval) + // We'll also ensure that the remote party is requesting a set of + // checkpoints for filters that we actually currently maintain. + switch msg.FilterType { + case wire.GCSFilterRegular: + break + + default: + peerLog.Debug("Filter request for unknown checkpoints for "+ + "filter: %v", msg.FilterType) + return + } + + blockHashes, err := sp.server.chain.IntervalBlockHashes( + &msg.StopHash, wire.CFCheckptInterval, + ) if err != nil { peerLog.Debugf("Invalid getcfilters request: %v", err) return } - var updateCache bool - var checkptCache []cfHeaderKV + var ( + updateCache bool + checkptCache []cfHeaderKV + ) + // If the set of check points requested goes back further than what + // we've already generated in our cache, then we'll need to update it. if len(blockHashes) > len(checkptCache) { - // Update the cache if the checkpoint chain is longer than the cached - // one. This ensures that the cache is relatively stable and mostly - // overlaps with the best chain, since it follows the longest chain - // heuristic. + // Update the cache if the checkpoint chain is longer than the + // cached one. This ensures that the cache is relatively stable + // and mostly overlaps with the best chain, since it follows + // the longest chain heuristic. updateCache = true // Take write lock because we are going to update cache. @@ -925,9 +975,13 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { // Grow the checkptCache to be the length of blockHashes. additionalLength := len(blockHashes) - len(checkptCache) - checkptCache = append(sp.server.cfCheckptCaches[msg.FilterType], - make([]cfHeaderKV, additionalLength)...) + checkptCache = append( + sp.server.cfCheckptCaches[msg.FilterType], + make([]cfHeaderKV, additionalLength)..., + ) } else { + // Otherwise, we don't need to update the cache as we already + // have enough headers pre-generated. updateCache = false // Take reader lock because we are not going to update cache. @@ -946,8 +1000,9 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { } // Populate results with cached checkpoints. - checkptMsg := wire.NewMsgCFCheckpt(msg.FilterType, &msg.StopHash, - len(blockHashes)) + checkptMsg := wire.NewMsgCFCheckpt( + msg.FilterType, &msg.StopHash, len(blockHashes), + ) for i := 0; i < forkIdx; i++ { checkptMsg.AddCFHeader(&checkptCache[i].filterHeader) } @@ -958,8 +1013,9 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { blockHashPtrs = append(blockHashPtrs, &blockHashes[i]) } - filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes(blockHashPtrs, - msg.FilterType) + filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes( + blockHashPtrs, msg.FilterType, + ) if err != nil { peerLog.Errorf("Error retrieving cfilter headers: %v", err) return @@ -967,7 +1023,8 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { for i, filterHeaderBytes := range filterHeaders { if len(filterHeaderBytes) == 0 { - peerLog.Warnf("Could not obtain CF header for %v", blockHashPtrs[i]) + peerLog.Warnf("Could not obtain CF header for %v", + blockHashPtrs[i]) return } From 5e86c374110b3974675669c57e046deed0d70a85 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 14 Jul 2018 20:50:58 -0700 Subject: [PATCH 0205/1056] server: fix bug in cf checkpoint serving In this commit, we fix a bug in the way that we previously attempted to server cfcheckpoints. In the prior version we would never actually fetch the current length of the cache. As a result, after the first time the checkpoints were fetched, we would always continually grow the cache rather than using what's there if sufficient. In this commit, we fix this behavior by always checking the length, then either keeping the rite lock, or downgrading to a read lock if the size was sufficient. --- server.go | 79 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/server.go b/server.go index 12925eeabb..e41f27e528 100644 --- a/server.go +++ b/server.go @@ -947,6 +947,9 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { return } + // Now that we know the client is fetching a filter that we know of, + // we'll fetch the block hashes et each check point interval so we can + // compare against our cache, and create new check points if necessary. blockHashes, err := sp.server.chain.IntervalBlockHashes( &msg.StopHash, wire.CFCheckptInterval, ) @@ -955,43 +958,55 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { return } - var ( - updateCache bool - checkptCache []cfHeaderKV + checkptMsg := wire.NewMsgCFCheckpt( + msg.FilterType, &msg.StopHash, len(blockHashes), ) - // If the set of check points requested goes back further than what - // we've already generated in our cache, then we'll need to update it. - if len(blockHashes) > len(checkptCache) { - // Update the cache if the checkpoint chain is longer than the - // cached one. This ensures that the cache is relatively stable - // and mostly overlaps with the best chain, since it follows - // the longest chain heuristic. - updateCache = true + // Fetch the current existing cache so we can decide if we need to + // extend it or if its adequate as is. + sp.server.cfCheckptCachesMtx.Lock() + checkptCache := sp.server.cfCheckptCaches[msg.FilterType] - // Take write lock because we are going to update cache. - sp.server.cfCheckptCachesMtx.Lock() + // If the set of block hashes is beyond the current size of the cache, + // then we'll expand the size of the cache and also retain the write + // lock. + var updateCache bool + if len(blockHashes) > len(checkptCache) { + // Now that we know we'll need to modify the size of the cache, + // we'll defer the release of the write lock so we don't + // forget. defer sp.server.cfCheckptCachesMtx.Unlock() - // Grow the checkptCache to be the length of blockHashes. + // We'll mark that we need to update the cache for below and + // also expand the size of the cache in place. + updateCache = true + additionalLength := len(blockHashes) - len(checkptCache) + newEntries := make([]cfHeaderKV, additionalLength) + + peerLog.Infof("Growing size of checkpoint cache from %v to %v "+ + "block hashes", len(checkptCache), len(blockHashes)) + checkptCache = append( sp.server.cfCheckptCaches[msg.FilterType], - make([]cfHeaderKV, additionalLength)..., + newEntries..., ) } else { - // Otherwise, we don't need to update the cache as we already - // have enough headers pre-generated. - updateCache = false - - // Take reader lock because we are not going to update cache. + // Otherwise, we'll release the write lock, then grab the read + // lock, as the cache is already properly sized. + sp.server.cfCheckptCachesMtx.Unlock() sp.server.cfCheckptCachesMtx.RLock() - defer sp.server.cfCheckptCachesMtx.RUnlock() - checkptCache = sp.server.cfCheckptCaches[msg.FilterType] + peerLog.Tracef("Serving stale cache of size %v", + len(checkptCache)) + + defer sp.server.cfCheckptCachesMtx.RUnlock() } - // Iterate backwards until the block hash is found in the cache. + // Now that we know the cache is of an appropriate size, we'll iterate + // backwards until the find the block hash. We do this as it's possible + // a re-org has occurred so items in the db are now in the main china + // while the cache has been partially invalidated. var forkIdx int for forkIdx = len(checkptCache); forkIdx > 0; forkIdx-- { if checkptCache[forkIdx-1].blockHash == blockHashes[forkIdx-1] { @@ -999,20 +1014,19 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { } } - // Populate results with cached checkpoints. - checkptMsg := wire.NewMsgCFCheckpt( - msg.FilterType, &msg.StopHash, len(blockHashes), - ) + // Now that we know the how much of the cache is relevant for this + // query, we'll populate our check point message with the cache as is. + // Shortly below, we'll populate the new elements of the cache. for i := 0; i < forkIdx; i++ { checkptMsg.AddCFHeader(&checkptCache[i].filterHeader) } - // Look up any filter headers that aren't cached. + // We'll now collect the set of hashes that are beyond our cache so we + // can look up the filter headers to populate the final cache. blockHashPtrs := make([]*chainhash.Hash, 0, len(blockHashes)-forkIdx) for i := forkIdx; i < len(blockHashes); i++ { blockHashPtrs = append(blockHashPtrs, &blockHashes[i]) } - filterHeaders, err := sp.server.cfIndex.FilterHeadersByBlockHashes( blockHashPtrs, msg.FilterType, ) @@ -1021,6 +1035,8 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { return } + // Now that we have the full set of filter headers, we'll add them to + // the checkpoint message, and also update our cache in line. for i, filterHeaderBytes := range filterHeaders { if len(filterHeaderBytes) == 0 { peerLog.Warnf("Could not obtain CF header for %v", @@ -1036,6 +1052,9 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { } checkptMsg.AddCFHeader(filterHeader) + + // If the new main chain is longer than what's in the cache, + // then we'll override it beyond the fork point. if updateCache { checkptCache[forkIdx+i] = cfHeaderKV{ blockHash: blockHashes[forkIdx+i], @@ -1044,6 +1063,8 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { } } + // Finally, we'll update the cache if we need to, and send the final + // message back to the requesting peer. if updateCache { sp.server.cfCheckptCaches[msg.FilterType] = checkptCache } From 088eec67ec9d36d678a232c6dc88f3a335b42c95 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 21 Jul 2018 17:41:23 -0700 Subject: [PATCH 0206/1056] peer: ensure the version negotiation goroutine will always exit In this commit, we patch a goroutine leak within the peer struct. This goroutine leak can happen, if the remote side fails to actually finish negotiation the protocol before our timeout ticker ticks. In this case, the goroutine will be blocked on a send, as the channel is unfired. An example trace from a btcd node I had on testnet showed: ``` 3183 @ 0x42e78a 0x42e83e 0x40540b 0x4051a5 0x872f76 0x45bfc1 ``` So, all instances of the goroutine failing to exit due to the remote peer not finishing the p2p version negotiation handshake. Our fix is simple: make the `negotiateErr' channel unbuffered. With this simple change, we ensure that the goroutine will always exit even in the case that the parent goroutine exists due to a timeout. # Please enter the commit message for your changes. Lines starting --- peer/peer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peer/peer.go b/peer/peer.go index 9aecab5947..2fdf3e42bd 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -2053,7 +2053,7 @@ func (p *Peer) Disconnect() { func (p *Peer) start() error { log.Tracef("Starting peer %s", p) - negotiateErr := make(chan error) + negotiateErr := make(chan error, 1) go func() { if p.inbound { negotiateErr <- p.negotiateInboundProtocol() From 08619220b4b0bfb6e87b78e6a3eacf67ad5a6061 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 18 Jul 2018 15:29:50 +0200 Subject: [PATCH 0207/1056] config/peer: make trickleTimeout configurable --- config.go | 3 +++ peer/peer.go | 10 +++++----- server.go | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/config.go b/config.go index 772c5ef8dc..f5d892a7e3 100644 --- a/config.go +++ b/config.go @@ -47,6 +47,7 @@ const ( defaultMaxRPCConcurrentReqs = 20 defaultDbType = "ffldb" defaultFreeTxRelayLimit = 15.0 + defaultTrickleTimeout = time.Second * 10 defaultBlockMinSize = 0 defaultBlockMaxSize = 750000 defaultBlockMinWeight = 0 @@ -140,6 +141,7 @@ type config struct { MinRelayTxFee float64 `long:"minrelaytxfee" description:"The minimum transaction fee in BTC/kB to be considered a non-zero fee."` FreeTxRelayLimit float64 `long:"limitfreerelay" description:"Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute"` NoRelayPriority bool `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"` + TrickleTimeout time.Duration `long:"trickletimeout" description:"Minimum time between attempts to send new inventory to a connected peer"` MaxOrphanTxs int `long:"maxorphantx" description:"Max number of orphan transactions to keep in memory"` Generate bool `long:"generate" description:"Generate (mine) bitcoins using the CPU"` MiningAddrs []string `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"` @@ -415,6 +417,7 @@ func loadConfig() (*config, []string, error) { RPCCert: defaultRPCCertFile, MinRelayTxFee: mempool.DefaultMinRelayTxFee.ToBTC(), FreeTxRelayLimit: defaultFreeTxRelayLimit, + TrickleTimeout: defaultTrickleTimeout, BlockMinSize: defaultBlockMinSize, BlockMaxSize: defaultBlockMaxSize, BlockMinWeight: defaultBlockMinWeight, diff --git a/peer/peer.go b/peer/peer.go index 2fdf3e42bd..f0dd570647 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -64,10 +64,6 @@ const ( // stalling. The deadlines are adjusted for callback running times and // only checked on each stall tick interval. stallResponseTimeout = 30 * time.Second - - // trickleTimeout is the duration of the ticker which trickles down the - // inventory to a peer. - trickleTimeout = 10 * time.Second ) var ( @@ -268,6 +264,10 @@ type Config struct { // Listeners houses callback functions to be invoked on receiving peer // messages. Listeners MessageListeners + + // TrickleTimeout is the duration of the ticker which trickles down the + // inventory to a peer. + TrickleTimeout time.Duration } // minUint32 is a helper function to return the minimum of two uint32s. @@ -1693,7 +1693,7 @@ out: func (p *Peer) queueHandler() { pendingMsgs := list.New() invSendQueue := list.New() - trickleTicker := time.NewTicker(trickleTimeout) + trickleTicker := time.NewTicker(p.cfg.TrickleTimeout) defer trickleTicker.Stop() // We keep the waiting flag so that we know if we have a message queued diff --git a/server.go b/server.go index e41f27e528..8288d24679 100644 --- a/server.go +++ b/server.go @@ -1947,6 +1947,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { Services: sp.server.services, DisableRelayTx: cfg.BlocksOnly, ProtocolVersion: peer.MaxProtocolVersion, + TrickleTimeout: cfg.TrickleTimeout, } } From ee0740a289cab383ef786e7105965fdf20dbf1f7 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 24 Jul 2018 13:10:28 +0200 Subject: [PATCH 0208/1056] peer test: set TrickleTimeout for test configs --- peer/example_test.go | 2 ++ peer/peer_test.go | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/peer/example_test.go b/peer/example_test.go index e4429f8559..5c4b570de3 100644 --- a/peer/example_test.go +++ b/peer/example_test.go @@ -23,6 +23,7 @@ func mockRemotePeer() error { UserAgentName: "peer", // User agent name to advertise. UserAgentVersion: "1.0.0", // User agent version to advertise. ChainParams: &chaincfg.SimNetParams, + TrickleTimeout: time.Second * 10, } // Accept connections on the simnet port. @@ -69,6 +70,7 @@ func Example_newOutboundPeer() { UserAgentVersion: "1.0.0", // User agent version to advertise. ChainParams: &chaincfg.SimNetParams, Services: 0, + TrickleTimeout: time.Second * 10, Listeners: peer.MessageListeners{ OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) { fmt.Println("outbound: received version") diff --git a/peer/peer_test.go b/peer/peer_test.go index 34ab1144d8..e87d2f9565 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -236,6 +236,7 @@ func TestPeerConnection(t *testing.T) { ChainParams: &chaincfg.MainNetParams, ProtocolVersion: wire.RejectVersion, // Configure with older version Services: 0, + TrickleTimeout: time.Second * 10, } peer2Cfg := &peer.Config{ Listeners: peer1Cfg.Listeners, @@ -244,6 +245,7 @@ func TestPeerConnection(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: wire.SFNodeNetwork | wire.SFNodeWitness, + TrickleTimeout: time.Second * 10, } wantStats1 := peerStats{ @@ -447,6 +449,7 @@ func TestPeerListeners(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: wire.SFNodeBloom, + TrickleTimeout: time.Second * 10, } inConn, outConn := pipe( &conn{raddr: "10.0.0.1:8333"}, @@ -617,6 +620,7 @@ func TestOutboundPeer(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: 0, + TrickleTimeout: time.Second * 10, } r, w := io.Pipe() @@ -757,6 +761,7 @@ func TestUnsupportedVersionPeer(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: 0, + TrickleTimeout: time.Second * 10, } localNA := wire.NewNetAddressIPPort( From 90c2094cbd94284929dfd1fde04502e0cdc4d65a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 31 Jul 2018 21:15:02 -0700 Subject: [PATCH 0209/1056] server: always reply with get headers backport of https://github.com/decred/dcrd/pull/1295 --- server.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/server.go b/server.go index e41f27e528..65d77087ab 100644 --- a/server.go +++ b/server.go @@ -742,10 +742,6 @@ func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) { // This mirrors the behavior in the reference implementation. chain := sp.server.chain headers := chain.LocateHeaders(msg.BlockLocatorHashes, &msg.HashStop) - if len(headers) == 0 { - // Nothing to send. - return - } // Send found headers to the requesting peer. blockHeaders := make([]*wire.BlockHeader, len(headers)) From f470bf0fe82b7bb7c175b0d80a8bc71c61d1d2a4 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 1 Aug 2018 16:50:56 -0700 Subject: [PATCH 0210/1056] blockchain: Backport optimize exported header access. backport of https://github.com/decred/dcrd/pull/1273 Notable difference being that btcd mainline currenlty doesn't have a blockchain/blockindex_test.go file, so those changes are omitted. Great work @davecgh :) --- blockchain/chain.go | 26 +++++++++----------------- rpcserver.go | 8 ++++---- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index c13fabd9ae..c49d728bd3 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1242,25 +1242,17 @@ func (b *BlockChain) BestSnapshot() *BestState { return snapshot } -// FetchHeader returns the block header identified by the given hash or an error -// if it doesn't exist. -func (b *BlockChain) FetchHeader(hash *chainhash.Hash) (wire.BlockHeader, error) { - // Reconstruct the header from the block index if possible. - if node := b.index.LookupNode(hash); node != nil { - return node.Header(), nil - } - - // Fall back to loading it from the database. - var header *wire.BlockHeader - err := b.db.View(func(dbTx database.Tx) error { - var err error - header, err = dbFetchHeaderByHash(dbTx, hash) - return err - }) - if err != nil { +// HeaderByHash returns the block header identified by the given hash or an +// error if it doesn't exist. Note that this will return headers from both the +// main and side chains. +func (b *BlockChain) HeaderByHash(hash *chainhash.Hash) (wire.BlockHeader, error) { + node := b.index.LookupNode(hash) + if node == nil { + err := fmt.Errorf("block %s is not known", hash) return wire.BlockHeader{}, err } - return *header, nil + + return node.Header(), nil } // MainChainHasBlock returns whether or not the block with the given hash is in diff --git a/rpcserver.go b/rpcserver.go index e3f6430f21..8475ef57ec 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1320,7 +1320,7 @@ func handleGetBlockHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct if err != nil { return nil, rpcDecodeHexError(c.Hash) } - blockHeader, err := s.cfg.Chain.FetchHeader(hash) + blockHeader, err := s.cfg.Chain.HeaderByHash(hash) if err != nil { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCBlockNotFound, @@ -2442,7 +2442,7 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru } // Fetch the header from chain. - header, err := s.cfg.Chain.FetchHeader(hash) + header, err := s.cfg.Chain.HeaderByHash(hash) if err != nil { context := "Failed to fetch block header" return nil, internalRPCError(err.Error(), context) @@ -2634,7 +2634,7 @@ func handleGetRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan str var chainHeight int32 if blkHash != nil { // Fetch the header from chain. - header, err := s.cfg.Chain.FetchHeader(blkHash) + header, err := s.cfg.Chain.HeaderByHash(blkHash) if err != nil { context := "Failed to fetch block header" return nil, internalRPCError(err.Error(), context) @@ -3262,7 +3262,7 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan var blkHeight int32 if blkHash := rtx.blkHash; blkHash != nil { // Fetch the header from chain. - header, err := s.cfg.Chain.FetchHeader(blkHash) + header, err := s.cfg.Chain.HeaderByHash(blkHash) if err != nil { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCBlockNotFound, From 4b13e7969119739114913cb911a5ea5e27a7dede Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 8 Aug 2018 17:49:26 -0700 Subject: [PATCH 0211/1056] blockchain: in initChainState mark ancestors of best tip as valid if not marked In this commit, we add an additional consistency check within the `initChainState` method. It has been observed that at times, a block wil lbe written to disk (as it's valid), but then the block index isn't updated to reflect this. This can cause btcd to fail to do things like serve cfheaders for valid blocks. To partially remedy this, when we're loading in the index, we assume that all ancestors of the current chain tip are valid, and mark them as such. At the very end, we'll flush the index to ensure the state is fully consistent. Typically this will be a noop, as only dirty elements are flushed. --- blockchain/chainio.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 8bd5627606..8d76d3ca94 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1128,7 +1128,7 @@ func (b *BlockChain) initChainState() error { } // Attempt to load the chain state from the database. - return b.db.View(func(dbTx database.Tx) error { + err = b.db.View(func(dbTx database.Tx) error { // Fetch the stored chain state from the database metadata. // When it doesn't exist, it means the database hasn't been // initialized for use with chain yet, so break out now to allow @@ -1221,6 +1221,25 @@ func (b *BlockChain) initChainState() error { return err } + // As a final consistency check, we'll run through all the + // nodes which are ancestors of the current chain tip, and mark + // them as valid if they aren't already marked as such. This + // is a safe assumption as all the block before the current tip + // are valid by definition. + for iterNode := tip; iterNode != nil; iterNode = iterNode.parent { + // If this isn't already marked as valid in the index, then + // we'll mark it as valid now to ensure consistency once + // we're up and running. + if !iterNode.status.KnownValid() { + log.Infof("Block %v (height=%v) ancestor of "+ + "chain tip not marked as valid, "+ + "upgrading to valid for consistency", + iterNode.hash, iterNode.height) + + b.index.SetStatusFlags(iterNode, statusValid) + } + } + // Initialize the state related to the best block. blockSize := uint64(len(blockBytes)) blockWeight := uint64(GetBlockWeight(btcutil.NewBlock(&block))) @@ -1230,6 +1249,14 @@ func (b *BlockChain) initChainState() error { return nil }) + if err != nil { + return err + } + + // As we might have updated the index after it was loaded, we'll + // attempt to flush the index to the DB. This will only result in a + // write if the elements are dirty, so it'll usually be a noop. + return b.index.flushToDB() } // deserializeBlockRow parses a value in the block index bucket into a block From f9722295f8d55c947cdffef275cd96cba1348ebf Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 8 Aug 2018 18:26:22 -0700 Subject: [PATCH 0212/1056] blockchain: add new flushIndexState function within connectBestChain --- blockchain/chain.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index c49d728bd3..8c7e7621d7 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1085,6 +1085,17 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) { fastAdd := flags&BFFastAdd == BFFastAdd + flushIndexState := func() { + // Intentionally ignore errors writing updated node status to DB. If + // it fails to write, it's not the end of the world. If the block is + // valid, we flush in connectBlock and if the block is invalid, the + // worst that can happen is we revalidate the block after a restart. + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", + writeErr) + } + } + // We are extending the main (best) chain with a new block. This is the // most common case. parentHash := &block.MsgBlock().Header.PrevBlock @@ -1108,14 +1119,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla return false, err } - // Intentionally ignore errors writing updated node status to DB. If - // it fails to write, it's not the end of the world. If the block is - // valid, we flush in connectBlock and if the block is invalid, the - // worst that can happen is we revalidate the block after a restart. - if writeErr := b.index.flushToDB(); writeErr != nil { - log.Warnf("Error flushing block index changes to disk: %v", - writeErr) - } + flushIndexState() if err != nil { return false, err From 598808cfd08a4f440c0b1dd13ce65c99bfa88f22 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 8 Aug 2018 18:30:46 -0700 Subject: [PATCH 0213/1056] blockchain: mark blocks as invalid if they fail connectBlock --- blockchain/chain.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index 8c7e7621d7..3528a00722 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1144,6 +1144,17 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // Connect the block to the main chain. err := b.connectBlock(node, block, view, stxos) if err != nil { + // If we got hit with a rule error, then we'll mark + // that status of the block as invalid and flush the + // index state to disk before returning with the error. + if _, ok := err.(RuleError); ok { + b.index.SetStatusFlags( + node, statusValidateFailed, + ) + } + + flushIndexState() + return false, err } From 69f313436ff96d1cb0a99bb5398e079c90cefd8d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 8 Aug 2018 18:31:15 -0700 Subject: [PATCH 0214/1056] blockchain: during fastAdd or if block wasn't already valid, mark as valid in index --- blockchain/chain.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index 3528a00722..71c1b2ee77 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1158,6 +1158,14 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla return false, err } + // If this is fast add, or this block node isn't yet marked as + // valid, then we'll update its status and flush the state to + // disk again. + if fastAdd || !b.index.NodeStatus(node).KnownValid() { + b.index.SetStatusFlags(node, statusValid) + flushIndexState() + } + return true, nil } if fastAdd { From fd78330fd3fc5a0f079999123e3ec7cc283b70ad Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 20:03:20 -0500 Subject: [PATCH 0215/1056] peer: Minor function definition order cleanup. This rearranges some of the function definitions that pertain to initial peer version negotiation and bringup so they are more consistent with the preferred order used throughout the codebase. In particular, the functions are defined before they're first used and generally as close as possible to the first use when they're defined in the same file. There are no functional changes. Backported from Decred. --- peer/peer.go | 435 ++++++++++++++++++++++++++------------------------- 1 file changed, 218 insertions(+), 217 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index 2fdf3e42bd..0af2aa6d0f 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1,4 +1,5 @@ -// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2013-2018 The btcsuite developers +// Copyright (c) 2016-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -801,85 +802,6 @@ func (p *Peer) IsWitnessEnabled() bool { return witnessEnabled } -// localVersionMsg creates a version message that can be used to send to the -// remote peer. -func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { - var blockNum int32 - if p.cfg.NewestBlock != nil { - var err error - _, blockNum, err = p.cfg.NewestBlock() - if err != nil { - return nil, err - } - } - - theirNA := p.na - - // If we are behind a proxy and the connection comes from the proxy then - // we return an unroutable address as their address. This is to prevent - // leaking the tor proxy address. - if p.cfg.Proxy != "" { - proxyaddress, _, err := net.SplitHostPort(p.cfg.Proxy) - // invalid proxy means poorly configured, be on the safe side. - if err != nil || p.na.IP.String() == proxyaddress { - theirNA = wire.NewNetAddressIPPort(net.IP([]byte{0, 0, 0, 0}), 0, 0) - } - } - - // Create a wire.NetAddress with only the services set to use as the - // "addrme" in the version message. - // - // Older nodes previously added the IP and port information to the - // address manager which proved to be unreliable as an inbound - // connection from a peer didn't necessarily mean the peer itself - // accepted inbound connections. - // - // Also, the timestamp is unused in the version message. - ourNA := &wire.NetAddress{ - Services: p.cfg.Services, - } - - // Generate a unique nonce for this peer so self connections can be - // detected. This is accomplished by adding it to a size-limited map of - // recently seen nonces. - nonce := uint64(rand.Int63()) - sentNonces.Add(nonce) - - // Version message. - msg := wire.NewMsgVersion(ourNA, theirNA, nonce, blockNum) - msg.AddUserAgent(p.cfg.UserAgentName, p.cfg.UserAgentVersion, - p.cfg.UserAgentComments...) - - // XXX: bitcoind appears to always enable the full node services flag - // of the remote peer netaddress field in the version message regardless - // of whether it knows it supports it or not. Also, bitcoind sets - // the services field of the local peer to 0 regardless of support. - // - // Realistically, this should be set as follows: - // - For outgoing connections: - // - Set the local netaddress services to what the local peer - // actually supports - // - Set the remote netaddress services to 0 to indicate no services - // as they are still unknown - // - For incoming connections: - // - Set the local netaddress services to what the local peer - // actually supports - // - Set the remote netaddress services to the what was advertised by - // by the remote peer in its version message - msg.AddrYou.Services = wire.SFNodeNetwork - - // Advertise the services flag - msg.Services = p.cfg.Services - - // Advertise our max supported protocol version. - msg.ProtocolVersion = int32(p.cfg.ProtocolVersion) - - // Advertise if inv messages for transactions are desired. - msg.DisableRelayTx = p.cfg.DisableRelayTx - - return msg, nil -} - // PushAddrMsg sends an addr message to the connected peer using the provided // addresses. This function is useful over manually sending the message via // QueueMessage since it automatically limits the addresses to the maximum @@ -1041,72 +963,6 @@ func (p *Peer) PushRejectMsg(command string, code wire.RejectCode, reason string <-doneChan } -// handleRemoteVersionMsg is invoked when a version bitcoin message is received -// from the remote peer. It will return an error if the remote peer's version -// is not compatible with ours. -func (p *Peer) handleRemoteVersionMsg(msg *wire.MsgVersion) error { - // Detect self connections. - if !allowSelfConns && sentNonces.Exists(msg.Nonce) { - return errors.New("disconnecting peer connected to self") - } - - // Notify and disconnect clients that have a protocol version that is - // too old. - // - // NOTE: If minAcceptableProtocolVersion is raised to be higher than - // wire.RejectVersion, this should send a reject packet before - // disconnecting. - if uint32(msg.ProtocolVersion) < minAcceptableProtocolVersion { - reason := fmt.Sprintf("protocol version must be %d or greater", - minAcceptableProtocolVersion) - return errors.New(reason) - } - - // Updating a bunch of stats including block based stats, and the - // peer's time offset. - p.statsMtx.Lock() - p.lastBlock = msg.LastBlock - p.startingHeight = msg.LastBlock - p.timeOffset = msg.Timestamp.Unix() - time.Now().Unix() - p.statsMtx.Unlock() - - // Negotiate the protocol version. - p.flagsMtx.Lock() - p.advertisedProtoVer = uint32(msg.ProtocolVersion) - p.protocolVersion = minUint32(p.protocolVersion, p.advertisedProtoVer) - p.versionKnown = true - log.Debugf("Negotiated protocol version %d for peer %s", - p.protocolVersion, p) - - // Set the peer's ID. - p.id = atomic.AddInt32(&nodeCount, 1) - - // Set the supported services for the peer to what the remote peer - // advertised. - p.services = msg.Services - - // Set the remote peer's user agent. - p.userAgent = msg.UserAgent - - // Determine if the peer would like to receive witness data with - // transactions, or not. - if p.services&wire.SFNodeWitness == wire.SFNodeWitness { - p.witnessEnabled = true - } - p.flagsMtx.Unlock() - - // Once the version message has been exchanged, we're able to determine - // if this peer knows how to encode witness data over the wire - // protocol. If so, then we'll switch to a decoding mode which is - // prepared for the new transaction format introduced as part of - // BIP0144. - if p.services&wire.SFNodeWitness == wire.SFNodeWitness { - p.wireEncoding = wire.WitnessEncoding - } - - return nil -} - // handlePingMsg is invoked when a peer receives a ping bitcoin message. For // recent clients (protocol version > BIP0031Version), it replies with a pong // message. For older clients, it does nothing and anything other than failure @@ -1992,40 +1848,6 @@ func (p *Peer) QueueInventory(invVect *wire.InvVect) { p.outputInvChan <- invVect } -// AssociateConnection associates the given conn to the peer. Calling this -// function when the peer is already connected will have no effect. -func (p *Peer) AssociateConnection(conn net.Conn) { - // Already connected? - if !atomic.CompareAndSwapInt32(&p.connected, 0, 1) { - return - } - - p.conn = conn - p.timeConnected = time.Now() - - if p.inbound { - p.addr = p.conn.RemoteAddr().String() - - // Set up a NetAddress for the peer to be used with AddrManager. We - // only do this inbound because outbound set this up at connection time - // and no point recomputing. - na, err := newNetAddress(p.conn.RemoteAddr(), p.services) - if err != nil { - log.Errorf("Cannot create remote net address: %v", err) - p.Disconnect() - return - } - p.na = na - } - - go func() { - if err := p.start(); err != nil { - log.Debugf("Cannot start peer %v: %v", p, err) - p.Disconnect() - } - }() -} - // Connected returns whether or not the peer is currently connected. // // This function is safe for concurrent access. @@ -2049,51 +1871,72 @@ func (p *Peer) Disconnect() { close(p.quit) } -// start begins processing input and output messages. -func (p *Peer) start() error { - log.Tracef("Starting peer %s", p) +// handleRemoteVersionMsg is invoked when a version bitcoin message is received +// from the remote peer. It will return an error if the remote peer's version +// is not compatible with ours. +func (p *Peer) handleRemoteVersionMsg(msg *wire.MsgVersion) error { + // Detect self connections. + if !allowSelfConns && sentNonces.Exists(msg.Nonce) { + return errors.New("disconnecting peer connected to self") + } - negotiateErr := make(chan error, 1) - go func() { - if p.inbound { - negotiateErr <- p.negotiateInboundProtocol() - } else { - negotiateErr <- p.negotiateOutboundProtocol() - } - }() + // Notify and disconnect clients that have a protocol version that is + // too old. + // + // NOTE: If minAcceptableProtocolVersion is raised to be higher than + // wire.RejectVersion, this should send a reject packet before + // disconnecting. + if uint32(msg.ProtocolVersion) < minAcceptableProtocolVersion { + reason := fmt.Sprintf("protocol version must be %d or greater", + minAcceptableProtocolVersion) + return errors.New(reason) + } - // Negotiate the protocol within the specified negotiateTimeout. - select { - case err := <-negotiateErr: - if err != nil { - return err - } - case <-time.After(negotiateTimeout): - return errors.New("protocol negotiation timeout") + // Updating a bunch of stats including block based stats, and the + // peer's time offset. + p.statsMtx.Lock() + p.lastBlock = msg.LastBlock + p.startingHeight = msg.LastBlock + p.timeOffset = msg.Timestamp.Unix() - time.Now().Unix() + p.statsMtx.Unlock() + + // Negotiate the protocol version. + p.flagsMtx.Lock() + p.advertisedProtoVer = uint32(msg.ProtocolVersion) + p.protocolVersion = minUint32(p.protocolVersion, p.advertisedProtoVer) + p.versionKnown = true + log.Debugf("Negotiated protocol version %d for peer %s", + p.protocolVersion, p) + + // Set the peer's ID. + p.id = atomic.AddInt32(&nodeCount, 1) + + // Set the supported services for the peer to what the remote peer + // advertised. + p.services = msg.Services + + // Set the remote peer's user agent. + p.userAgent = msg.UserAgent + + // Determine if the peer would like to receive witness data with + // transactions, or not. + if p.services&wire.SFNodeWitness == wire.SFNodeWitness { + p.witnessEnabled = true } - log.Debugf("Connected to %s", p.Addr()) + p.flagsMtx.Unlock() - // The protocol has been negotiated successfully so start processing input - // and output messages. - go p.stallHandler() - go p.inHandler() - go p.queueHandler() - go p.outHandler() - go p.pingHandler() + // Once the version message has been exchanged, we're able to determine + // if this peer knows how to encode witness data over the wire + // protocol. If so, then we'll switch to a decoding mode which is + // prepared for the new transaction format introduced as part of + // BIP0144. + if p.services&wire.SFNodeWitness == wire.SFNodeWitness { + p.wireEncoding = wire.WitnessEncoding + } - // Send our verack message now that the IO processing machinery has started. - p.QueueMessage(wire.NewMsgVerAck(), nil) return nil } -// WaitForDisconnect waits until the peer has completely disconnected and all -// resources are cleaned up. This will happen if either the local or remote -// side has been disconnected or the peer is forcibly disconnected via -// Disconnect. -func (p *Peer) WaitForDisconnect() { - <-p.quit -} - // readRemoteVersionMsg waits for the next message to arrive from the remote // peer. If the next message is not a version message or the version is not // acceptable then return an error. @@ -2124,6 +1967,85 @@ func (p *Peer) readRemoteVersionMsg() error { return nil } +// localVersionMsg creates a version message that can be used to send to the +// remote peer. +func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { + var blockNum int32 + if p.cfg.NewestBlock != nil { + var err error + _, blockNum, err = p.cfg.NewestBlock() + if err != nil { + return nil, err + } + } + + theirNA := p.na + + // If we are behind a proxy and the connection comes from the proxy then + // we return an unroutable address as their address. This is to prevent + // leaking the tor proxy address. + if p.cfg.Proxy != "" { + proxyaddress, _, err := net.SplitHostPort(p.cfg.Proxy) + // invalid proxy means poorly configured, be on the safe side. + if err != nil || p.na.IP.String() == proxyaddress { + theirNA = wire.NewNetAddressIPPort(net.IP([]byte{0, 0, 0, 0}), 0, 0) + } + } + + // Create a wire.NetAddress with only the services set to use as the + // "addrme" in the version message. + // + // Older nodes previously added the IP and port information to the + // address manager which proved to be unreliable as an inbound + // connection from a peer didn't necessarily mean the peer itself + // accepted inbound connections. + // + // Also, the timestamp is unused in the version message. + ourNA := &wire.NetAddress{ + Services: p.cfg.Services, + } + + // Generate a unique nonce for this peer so self connections can be + // detected. This is accomplished by adding it to a size-limited map of + // recently seen nonces. + nonce := uint64(rand.Int63()) + sentNonces.Add(nonce) + + // Version message. + msg := wire.NewMsgVersion(ourNA, theirNA, nonce, blockNum) + msg.AddUserAgent(p.cfg.UserAgentName, p.cfg.UserAgentVersion, + p.cfg.UserAgentComments...) + + // XXX: bitcoind appears to always enable the full node services flag + // of the remote peer netaddress field in the version message regardless + // of whether it knows it supports it or not. Also, bitcoind sets + // the services field of the local peer to 0 regardless of support. + // + // Realistically, this should be set as follows: + // - For outgoing connections: + // - Set the local netaddress services to what the local peer + // actually supports + // - Set the remote netaddress services to 0 to indicate no services + // as they are still unknown + // - For incoming connections: + // - Set the local netaddress services to what the local peer + // actually supports + // - Set the remote netaddress services to the what was advertised by + // by the remote peer in its version message + msg.AddrYou.Services = wire.SFNodeNetwork + + // Advertise the services flag + msg.Services = p.cfg.Services + + // Advertise our max supported protocol version. + msg.ProtocolVersion = int32(p.cfg.ProtocolVersion) + + // Advertise if inv messages for transactions are desired. + msg.DisableRelayTx = p.cfg.DisableRelayTx + + return msg, nil +} + // writeLocalVersionMsg writes our version message to the remote peer. func (p *Peer) writeLocalVersionMsg() error { localVerMsg, err := p.localVersionMsg() @@ -2156,6 +2078,85 @@ func (p *Peer) negotiateOutboundProtocol() error { return p.readRemoteVersionMsg() } +// start begins processing input and output messages. +func (p *Peer) start() error { + log.Tracef("Starting peer %s", p) + + negotiateErr := make(chan error, 1) + go func() { + if p.inbound { + negotiateErr <- p.negotiateInboundProtocol() + } else { + negotiateErr <- p.negotiateOutboundProtocol() + } + }() + + // Negotiate the protocol within the specified negotiateTimeout. + select { + case err := <-negotiateErr: + if err != nil { + return err + } + case <-time.After(negotiateTimeout): + return errors.New("protocol negotiation timeout") + } + log.Debugf("Connected to %s", p.Addr()) + + // The protocol has been negotiated successfully so start processing input + // and output messages. + go p.stallHandler() + go p.inHandler() + go p.queueHandler() + go p.outHandler() + go p.pingHandler() + + // Send our verack message now that the IO processing machinery has started. + p.QueueMessage(wire.NewMsgVerAck(), nil) + return nil +} + +// AssociateConnection associates the given conn to the peer. Calling this +// function when the peer is already connected will have no effect. +func (p *Peer) AssociateConnection(conn net.Conn) { + // Already connected? + if !atomic.CompareAndSwapInt32(&p.connected, 0, 1) { + return + } + + p.conn = conn + p.timeConnected = time.Now() + + if p.inbound { + p.addr = p.conn.RemoteAddr().String() + + // Set up a NetAddress for the peer to be used with AddrManager. We + // only do this inbound because outbound set this up at connection time + // and no point recomputing. + na, err := newNetAddress(p.conn.RemoteAddr(), p.services) + if err != nil { + log.Errorf("Cannot create remote net address: %v", err) + p.Disconnect() + return + } + p.na = na + } + + go func() { + if err := p.start(); err != nil { + log.Debugf("Cannot start peer %v: %v", p, err) + p.Disconnect() + } + }() +} + +// WaitForDisconnect waits until the peer has completely disconnected and all +// resources are cleaned up. This will happen if either the local or remote +// side has been disconnected or the peer is forcibly disconnected via +// Disconnect. +func (p *Peer) WaitForDisconnect() { + <-p.quit +} + // newPeerBase returns a new base bitcoin peer based on the inbound flag. This // is used by the NewInboundPeer and NewOutboundPeer functions to perform base // setup needed by both types of peers. From f696d49c494caf99ba6280ab55f55d4711907408 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 15 Aug 2018 21:02:33 -0700 Subject: [PATCH 0216/1056] btcjson/chainsvrresults: use int64 for verbose getblock[header] confs This commit modifies the parsed fields in GetBlockVerbose and GetBlockHeaderVerbose from a uint64 to an int64. bitcoind will return -1 if the requested block is not in the main chain, which causes a panic when trying to serialize into a uint. --- btcjson/chainsvrresults.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 24d6cf7cc4..30c6369a32 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -11,7 +11,7 @@ import "encoding/json" // returns a hex-encoded string. type GetBlockHeaderVerboseResult struct { Hash string `json:"hash"` - Confirmations uint64 `json:"confirmations"` + Confirmations int64 `json:"confirmations"` Height int32 `json:"height"` Version int32 `json:"version"` VersionHex string `json:"versionHex"` @@ -29,7 +29,7 @@ type GetBlockHeaderVerboseResult struct { // hex-encoded string. type GetBlockVerboseResult struct { Hash string `json:"hash"` - Confirmations uint64 `json:"confirmations"` + Confirmations int64 `json:"confirmations"` StrippedSize int32 `json:"strippedsize"` Size int32 `json:"size"` Weight int32 `json:"weight"` From 85cb8f50a0b52e18c51b1492c512d2d6043d18e2 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 15 Aug 2018 21:05:34 -0700 Subject: [PATCH 0217/1056] rpcserver: convert verbose confirmations fields to int64 --- rpcserver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 8475ef57ec..6ade888d38 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1126,7 +1126,7 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i PreviousHash: blockHeader.PrevBlock.String(), Nonce: blockHeader.Nonce, Time: blockHeader.Timestamp.Unix(), - Confirmations: uint64(1 + best.Height - blockHeight), + Confirmations: int64(1 + best.Height - blockHeight), Height: int64(blockHeight), Size: int32(len(blkBytes)), StrippedSize: int32(blk.MsgBlock().SerializeSizeStripped()), @@ -1364,7 +1364,7 @@ func handleGetBlockHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct params := s.cfg.ChainParams blockHeaderReply := btcjson.GetBlockHeaderVerboseResult{ Hash: c.Hash, - Confirmations: uint64(1 + best.Height - blockHeight), + Confirmations: int64(1 + best.Height - blockHeight), Height: blockHeight, Version: blockHeader.Version, VersionHex: fmt.Sprintf("%08x", blockHeader.Version), From 9aa83ad423e9b531c1eef52239ee2d9348f26b6d Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Wed, 18 Jul 2018 19:13:49 -0700 Subject: [PATCH 0218/1056] integration/rpctest: disable the txindex by default In this commit, we disable the txindex by default as the flag cannot be overwritten by btcd once set. --- integration/rpctest/node.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/integration/rpctest/node.go b/integration/rpctest/node.go index 6904499a08..6aec2b1168 100644 --- a/integration/rpctest/node.go +++ b/integration/rpctest/node.go @@ -115,10 +115,6 @@ func (n *nodeConfig) arguments() []string { args = append(args, fmt.Sprintf("--rpccert=%s", n.certFile)) // --rpckey args = append(args, fmt.Sprintf("--rpckey=%s", n.keyFile)) - // --txindex - args = append(args, "--txindex") - // --addrindex - args = append(args, "--addrindex") if n.dataDir != "" { // --datadir args = append(args, fmt.Sprintf("--datadir=%s", n.dataDir)) From dfd7f6caf8db393940983ded615781b3c254fc39 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 23 Jul 2018 16:55:01 -0700 Subject: [PATCH 0219/1056] integration/rpctest: add ability to create txs without change outputs --- integration/csv_fork_test.go | 4 +-- integration/rpctest/memwallet.go | 43 ++++++++++++++++++------- integration/rpctest/rpc_harness.go | 26 +++++++++++---- integration/rpctest/rpc_harness_test.go | 8 ++--- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/integration/csv_fork_test.go b/integration/csv_fork_test.go index 3dd471b187..345217c864 100644 --- a/integration/csv_fork_test.go +++ b/integration/csv_fork_test.go @@ -53,7 +53,7 @@ func makeTestOutput(r *rpctest.Harness, t *testing.T, output := &wire.TxOut{PkScript: selfAddrScript, Value: 1e8} // Next, create and broadcast a transaction paying to the output. - fundTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + fundTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true) if err != nil { return nil, nil, nil, err } @@ -316,7 +316,7 @@ func createCSVOutput(r *rpctest.Harness, t *testing.T, // Finally create a valid transaction which creates the output crafted // above. - tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true) if err != nil { return nil, nil, nil, err } diff --git a/integration/rpctest/memwallet.go b/integration/rpctest/memwallet.go index 0dccde10aa..f16130750a 100644 --- a/integration/rpctest/memwallet.go +++ b/integration/rpctest/memwallet.go @@ -374,12 +374,15 @@ func (m *memWallet) NewAddress() (btcutil.Address, error) { } // fundTx attempts to fund a transaction sending amt bitcoin. The coins are -// selected such that the final amount spent pays enough fees as dictated by -// the passed fee rate. The passed fee rate should be expressed in -// satoshis-per-byte. +// selected such that the final amount spent pays enough fees as dictated by the +// passed fee rate. The passed fee rate should be expressed in +// satoshis-per-byte. The transaction being funded can optionally include a +// change output indicated by the change boolean. // // NOTE: The memWallet's mutex must be held when this function is called. -func (m *memWallet) fundTx(tx *wire.MsgTx, amt btcutil.Amount, feeRate btcutil.Amount) error { +func (m *memWallet) fundTx(tx *wire.MsgTx, amt btcutil.Amount, + feeRate btcutil.Amount, change bool) error { + const ( // spendSize is the largest number of bytes of a sigScript // which spends a p2pkh output: OP_DATA_73 OP_DATA_33 @@ -415,10 +418,11 @@ func (m *memWallet) fundTx(tx *wire.MsgTx, amt btcutil.Amount, feeRate btcutil.A continue } - // If we have any change left over, then add an additional - // output to the transaction reserved for change. + // If we have any change left over and we should create a change + // output, then add an additional output to the transaction + // reserved for it. changeVal := amtSelected - amt - reqFee - if changeVal > 0 { + if changeVal > 0 && change { addr, err := m.newAddress() if err != nil { return err @@ -448,7 +452,21 @@ func (m *memWallet) fundTx(tx *wire.MsgTx, amt btcutil.Amount, feeRate btcutil.A func (m *memWallet) SendOutputs(outputs []*wire.TxOut, feeRate btcutil.Amount) (*chainhash.Hash, error) { - tx, err := m.CreateTransaction(outputs, feeRate) + tx, err := m.CreateTransaction(outputs, feeRate, true) + if err != nil { + return nil, err + } + + return m.rpc.SendRawTransaction(tx, true) +} + +// SendOutputsWithoutChange creates and sends a transaction that pays to the +// specified outputs while observing the passed fee rate and ignoring a change +// output. The passed fee rate should be expressed in sat/b. +func (m *memWallet) SendOutputsWithoutChange(outputs []*wire.TxOut, + feeRate btcutil.Amount) (*chainhash.Hash, error) { + + tx, err := m.CreateTransaction(outputs, feeRate, false) if err != nil { return nil, err } @@ -458,10 +476,13 @@ func (m *memWallet) SendOutputs(outputs []*wire.TxOut, // CreateTransaction returns a fully signed transaction paying to the specified // outputs while observing the desired fee rate. The passed fee rate should be -// expressed in satoshis-per-byte. +// expressed in satoshis-per-byte. The transaction being created can optionally +// include a change output indicated by the change boolean. // // This function is safe for concurrent access. -func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, feeRate btcutil.Amount) (*wire.MsgTx, error) { +func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, + feeRate btcutil.Amount, change bool) (*wire.MsgTx, error) { + m.Lock() defer m.Unlock() @@ -476,7 +497,7 @@ func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, feeRate btcutil.Amo } // Attempt to fund the transaction with spendable utxos. - if err := m.fundTx(tx, outputAmt, feeRate); err != nil { + if err := m.fundTx(tx, outputAmt, feeRate, change); err != nil { return nil, err } diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index ea8868ce83..1c2612e47b 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -356,20 +356,32 @@ func (h *Harness) SendOutputs(targetOutputs []*wire.TxOut, return h.wallet.SendOutputs(targetOutputs, feeRate) } +// SendOutputsWithoutChange creates and sends a transaction that pays to the +// specified outputs while observing the passed fee rate and ignoring a change +// output. The passed fee rate should be expressed in sat/b. +// +// This function is safe for concurrent access. +func (h *Harness) SendOutputsWithoutChange(targetOutputs []*wire.TxOut, + feeRate btcutil.Amount) (*chainhash.Hash, error) { + + return h.wallet.SendOutputsWithoutChange(targetOutputs, feeRate) +} + // CreateTransaction returns a fully signed transaction paying to the specified // outputs while observing the desired fee rate. The passed fee rate should be -// expressed in satoshis-per-byte. Any unspent outputs selected as inputs for -// the crafted transaction are marked as unspendable in order to avoid -// potential double-spends by future calls to this method. If the created -// transaction is cancelled for any reason then the selected inputs MUST be -// freed via a call to UnlockOutputs. Otherwise, the locked inputs won't be +// expressed in satoshis-per-byte. The transaction being created can optionally +// include a change output indicated by the change boolean. Any unspent outputs +// selected as inputs for the crafted transaction are marked as unspendable in +// order to avoid potential double-spends by future calls to this method. If the +// created transaction is cancelled for any reason then the selected inputs MUST +// be freed via a call to UnlockOutputs. Otherwise, the locked inputs won't be // returned to the pool of spendable outputs. // // This function is safe for concurrent access. func (h *Harness) CreateTransaction(targetOutputs []*wire.TxOut, - feeRate btcutil.Amount) (*wire.MsgTx, error) { + feeRate btcutil.Amount, change bool) (*wire.MsgTx, error) { - return h.wallet.CreateTransaction(targetOutputs, feeRate) + return h.wallet.CreateTransaction(targetOutputs, feeRate, change) } // UnlockOutputs unlocks any outputs which were previously marked as diff --git a/integration/rpctest/rpc_harness_test.go b/integration/rpctest/rpc_harness_test.go index 20797d3834..717f8f45af 100644 --- a/integration/rpctest/rpc_harness_test.go +++ b/integration/rpctest/rpc_harness_test.go @@ -206,7 +206,7 @@ func testJoinMempools(r *Harness, t *testing.T) { t.Fatalf("unable to generate pkscript to addr: %v", err) } output := wire.NewTxOut(5e8, addrScript) - testTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + testTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true) if err != nil { t.Fatalf("coinbase spend failed: %v", err) } @@ -340,7 +340,7 @@ func testGenerateAndSubmitBlock(r *Harness, t *testing.T) { const numTxns = 5 txns := make([]*btcutil.Tx, 0, numTxns) for i := 0; i < numTxns; i++ { - tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true) if err != nil { t.Fatalf("unable to create tx: %v", err) } @@ -407,7 +407,7 @@ func testGenerateAndSubmitBlockWithCustomCoinbaseOutputs(r *Harness, const numTxns = 5 txns := make([]*btcutil.Tx, 0, numTxns) for i := 0; i < numTxns; i++ { - tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true) if err != nil { t.Fatalf("unable to create tx: %v", err) } @@ -522,7 +522,7 @@ func testMemWalletLockedOutputs(r *Harness, t *testing.T) { } outputAmt := btcutil.Amount(50 * btcutil.SatoshiPerBitcoin) output := wire.NewTxOut(int64(outputAmt), pkScript) - tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) + tx, err := r.CreateTransaction([]*wire.TxOut{output}, 10, true) if err != nil { t.Fatalf("unable to create transaction: %v", err) } From be191ca111b494bb1ccdbeb7295723ee56949d07 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 22 Aug 2018 19:46:27 -0700 Subject: [PATCH 0220/1056] blockchain/indexers: fix bug in indexer re-org catch up In this commit, we fix an existing bug in the re-org catch up logic for the `IndexManager`. Before this commit, we would assign the block to the _local_ scope rather than the outer scope. As a result, we would never properly bisect the chain to find the fork point to be able to reconcile the index state to the main chain only after a re-org occurs. Fixes #1261 --- blockchain/indexers/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockchain/indexers/manager.go b/blockchain/indexers/manager.go index 09dae62118..bc0804f8bd 100644 --- a/blockchain/indexers/manager.go +++ b/blockchain/indexers/manager.go @@ -309,7 +309,7 @@ func (m *Manager) Init(chain *blockchain.BlockChain, interrupt <-chan struct{}) if err != nil { return err } - block, err := btcutil.NewBlockFromBytes(blockBytes) + block, err = btcutil.NewBlockFromBytes(blockBytes) if err != nil { return err } From b36dce5032af374496770c8d992e79390a8d5fbb Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 22 Aug 2018 19:51:58 -0700 Subject: [PATCH 0221/1056] build: update siphash lib to latest version w/ ARM fix In this commit, we update the siphash lib we use to the latest version as it was discovered that the assembly for certain ARM machines has a flaw which causes it to compute an _incorrect_ siphash function. The upstream lib has since disabled the assembly after this was discovered. We update as well in order to ensure that ARM machines will produce the proper GCS filters. --- glide.lock | 6 +++--- glide.yaml | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/glide.lock b/glide.lock index c101cf19d4..67185c2268 100644 --- a/glide.lock +++ b/glide.lock @@ -1,8 +1,8 @@ -hash: 30562f0035d9bb4d4ee531762e4f7f762ede916255e9aa781df58537651f7382 -updated: 2018-07-06T16:07:52.877260592-07:00 +hash: e6f57b384b22282a2cb4e96aea9c46dc455b44336da09e64a9b19d13d877e7a4 +updated: 2018-08-22T19:51:39.57143044-07:00 imports: - name: github.com/aead/siphash - version: e404fcfc888570cadd1610538e2dbc89f66af814 + version: 83563a290f60225eb120d724600b9690c3fb536f - name: github.com/btcsuite/btclog version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a - name: github.com/btcsuite/btcutil diff --git a/glide.yaml b/glide.yaml index 554610048a..32c5ed61d3 100644 --- a/glide.yaml +++ b/glide.yaml @@ -33,3 +33,5 @@ import: - package: github.com/jessevdk/go-flags version: 1679536dcc895411a9f5848d9a0250be7856448c - package: github.com/jrick/logrotate +- package: github.com/aead/siphash + version: 83563a290f60225eb120d724600b9690c3fb536f From 07edce81b0ff7e5b5bce071a8f312289b0324728 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 22 Aug 2018 23:37:27 -0500 Subject: [PATCH 0222/1056] txscript: Cleanup strict signature enforcement. This cleans up the code for handling the checksig and checkmultisig opcode strict signatures to explicitly call out any semantics that are likely not obvious and improve readability. It also introduce new distinct errors for each condition which can result in a signature being rejected due to not following the strict encoding requirements and updates reference test adaptor accordingly. --- txscript/engine.go | 218 +++++++++++++++++++++++-------------- txscript/error.go | 84 +++++++++++++- txscript/error_test.go | 16 ++- txscript/reference_test.go | 8 +- 4 files changed, 237 insertions(+), 89 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index b5aef52a01..db661860c8 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -1,4 +1,5 @@ -// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2013-2018 The btcsuite developers +// Copyright (c) 2015-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -633,119 +634,170 @@ func (vm *Engine) checkSignatureEncoding(sig []byte) error { // - S is the arbitrary length big-endian encoded number which // represents the S value of the signature. The encoding rules are // identical as those for R. - - // Minimum length is when both numbers are 1 byte each. - // 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + - if len(sig) < 8 { - // Too short - str := fmt.Sprintf("malformed signature: too short: %d < 8", - len(sig)) - return scriptError(ErrSigDER, str) - } - - // Maximum length is when both numbers are 33 bytes each. It is 33 - // bytes because a 256-bit integer requires 32 bytes and an additional - // leading null byte might required if the high bit is set in the value. - // 0x30 + <1-byte> + 0x02 + 0x21 + <33 bytes> + 0x2 + 0x21 + <33 bytes> - if len(sig) > 72 { - // Too long - str := fmt.Sprintf("malformed signature: too long: %d > 72", - len(sig)) - return scriptError(ErrSigDER, str) - } - if sig[0] != 0x30 { - // Wrong type - str := fmt.Sprintf("malformed signature: format has wrong "+ - "type: 0x%x", sig[0]) - return scriptError(ErrSigDER, str) - } - if int(sig[1]) != len(sig)-2 { - // Invalid length + const ( + asn1SequenceID = 0x30 + asn1IntegerID = 0x02 + + // minSigLen is the minimum length of a DER encoded signature and is + // when both R and S are 1 byte each. + // + // 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + + minSigLen = 8 + + // maxSigLen is the maximum length of a DER encoded signature and is + // when both R and S are 33 bytes each. It is 33 bytes because a + // 256-bit integer requires 32 bytes and an additional leading null byte + // might required if the high bit is set in the value. + // + // 0x30 + <1-byte> + 0x02 + 0x21 + <33 bytes> + 0x2 + 0x21 + <33 bytes> + maxSigLen = 72 + + // sequenceOffset is the byte offset within the signature of the + // expected ASN.1 sequence identifier. + sequenceOffset = 0 + + // dataLenOffset is the byte offset within the signature of the expected + // total length of all remaining data in the signature. + dataLenOffset = 1 + + // rTypeOffset is the byte offset within the signature of the ASN.1 + // identifier for R and is expected to indicate an ASN.1 integer. + rTypeOffset = 2 + + // rLenOffset is the byte offset within the signature of the length of + // R. + rLenOffset = 3 + + // rOffset is the byte offset within the signature of R. + rOffset = 4 + ) + + // The signature must adhere to the minimum and maximum allowed length. + sigLen := len(sig) + if sigLen < minSigLen { + str := fmt.Sprintf("malformed signature: too short: %d < %d", sigLen, + minSigLen) + return scriptError(ErrSigTooShort, str) + } + if sigLen > maxSigLen { + str := fmt.Sprintf("malformed signature: too long: %d > %d", sigLen, + maxSigLen) + return scriptError(ErrSigTooLong, str) + } + + // The signature must start with the ASN.1 sequence identifier. + if sig[sequenceOffset] != asn1SequenceID { + str := fmt.Sprintf("malformed signature: format has wrong type: %#x", + sig[sequenceOffset]) + return scriptError(ErrSigInvalidSeqID, str) + } + + // The signature must indicate the correct amount of data for all elements + // related to R and S. + if int(sig[dataLenOffset]) != sigLen-2 { str := fmt.Sprintf("malformed signature: bad length: %d != %d", - sig[1], len(sig)-2) - return scriptError(ErrSigDER, str) + sig[dataLenOffset], sigLen-2) + return scriptError(ErrSigInvalidDataLen, str) } - rLen := int(sig[3]) - - // Make sure S is inside the signature. - if rLen+5 > len(sig) { - return scriptError(ErrSigDER, - "malformed signature: S out of bounds") + // Calculate the offsets of the elements related to S and ensure S is inside + // the signature. + // + // rLen specifies the length of the big-endian encoded number which + // represents the R value of the signature. + // + // sTypeOffset is the offset of the ASN.1 identifier for S and, like its R + // counterpart, is expected to indicate an ASN.1 integer. + // + // sLenOffset and sOffset are the byte offsets within the signature of the + // length of S and S itself, respectively. + rLen := int(sig[rLenOffset]) + sTypeOffset := rOffset + rLen + sLenOffset := sTypeOffset + 1 + if sTypeOffset >= sigLen { + str := "malformed signature: S type indicator missing" + return scriptError(ErrSigMissingSTypeID, str) + } + if sLenOffset >= sigLen { + str := "malformed signature: S length missing" + return scriptError(ErrSigMissingSLen, str) } - sLen := int(sig[rLen+5]) - - // The length of the elements does not match the length of the - // signature. - if rLen+sLen+6 != len(sig) { - return scriptError(ErrSigDER, - "malformed signature: invalid R length") + // The lengths of R and S must match the overall length of the signature. + // + // sLen specifies the length of the big-endian encoded number which + // represents the S value of the signature. + sOffset := sLenOffset + 1 + sLen := int(sig[sLenOffset]) + if sOffset+sLen != sigLen { + str := "malformed signature: invalid S length" + return scriptError(ErrSigInvalidSLen, str) } - // R elements must be integers. - if sig[2] != 0x02 { - return scriptError(ErrSigDER, - "malformed signature: missing first integer marker") + // R elements must be ASN.1 integers. + if sig[rTypeOffset] != asn1IntegerID { + str := fmt.Sprintf("malformed signature: R integer marker: %#x != %#x", + sig[rTypeOffset], asn1IntegerID) + return scriptError(ErrSigInvalidRIntID, str) } // Zero-length integers are not allowed for R. if rLen == 0 { - return scriptError(ErrSigDER, - "malformed signature: R length is zero") + str := "malformed signature: R length is zero" + return scriptError(ErrSigZeroRLen, str) } // R must not be negative. - if sig[4]&0x80 != 0 { - return scriptError(ErrSigDER, - "malformed signature: R value is negative") + if sig[rOffset]&0x80 != 0 { + str := "malformed signature: R is negative" + return scriptError(ErrSigNegativeR, str) } - // Null bytes at the start of R are not allowed, unless R would - // otherwise be interpreted as a negative number. - if rLen > 1 && sig[4] == 0x00 && sig[5]&0x80 == 0 { - return scriptError(ErrSigDER, - "malformed signature: invalid R value") + // Null bytes at the start of R are not allowed, unless R would otherwise be + // interpreted as a negative number. + if rLen > 1 && sig[rOffset] == 0x00 && sig[rOffset+1]&0x80 == 0 { + str := "malformed signature: R value has too much padding" + return scriptError(ErrSigTooMuchRPadding, str) } - // S elements must be integers. - if sig[rLen+4] != 0x02 { - return scriptError(ErrSigDER, - "malformed signature: missing second integer marker") + // S elements must be ASN.1 integers. + if sig[sTypeOffset] != asn1IntegerID { + str := fmt.Sprintf("malformed signature: S integer marker: %#x != %#x", + sig[sTypeOffset], asn1IntegerID) + return scriptError(ErrSigInvalidSIntID, str) } // Zero-length integers are not allowed for S. if sLen == 0 { - return scriptError(ErrSigDER, - "malformed signature: S length is zero") + str := "malformed signature: S length is zero" + return scriptError(ErrSigZeroSLen, str) } // S must not be negative. - if sig[rLen+6]&0x80 != 0 { - return scriptError(ErrSigDER, - "malformed signature: S value is negative") + if sig[sOffset]&0x80 != 0 { + str := "malformed signature: S is negative" + return scriptError(ErrSigNegativeS, str) } - // Null bytes at the start of S are not allowed, unless S would - // otherwise be interpreted as a negative number. - if sLen > 1 && sig[rLen+6] == 0x00 && sig[rLen+7]&0x80 == 0 { - return scriptError(ErrSigDER, - "malformed signature: invalid S value") + // Null bytes at the start of S are not allowed, unless S would otherwise be + // interpreted as a negative number. + if sLen > 1 && sig[sOffset] == 0x00 && sig[sOffset+1]&0x80 == 0 { + str := "malformed signature: S value has too much padding" + return scriptError(ErrSigTooMuchSPadding, str) } - // Verify the S value is <= half the order of the curve. This check is - // done because when it is higher, the complement modulo the order can - // be used instead which is a shorter encoding by 1 byte. Further, - // without enforcing this, it is possible to replace a signature in a - // valid transaction with the complement while still being a valid - // signature that verifies. This would result in changing the - // transaction hash and thus is source of malleability. + // Verify the S value is <= half the order of the curve. This check is done + // because when it is higher, the complement modulo the order can be used + // instead which is a shorter encoding by 1 byte. Further, without + // enforcing this, it is possible to replace a signature in a valid + // transaction with the complement while still being a valid signature that + // verifies. This would result in changing the transaction hash and thus is + // a source of malleability. if vm.hasFlag(ScriptVerifyLowS) { - sValue := new(big.Int).SetBytes(sig[rLen+6 : rLen+6+sLen]) + sValue := new(big.Int).SetBytes(sig[sOffset : sOffset+sLen]) if sValue.Cmp(halfOrder) > 0 { - return scriptError(ErrSigHighS, - "signature is not canonical due to "+ - "unnecessarily high S value") + return scriptError(ErrSigHighS, "signature is not canonical due "+ + "to unnecessarily high S value") } } diff --git a/txscript/error.go b/txscript/error.go index 0801388274..a61d02729f 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -175,9 +175,71 @@ const ( // one of the supported types. ErrInvalidSigHashType - // ErrSigDER is returned when a signature is not a canonically-encoded - // DER signature. - ErrSigDER + // ErrSigTooShort is returned when a signature that should be a + // canonically-encoded DER signature is too short. + ErrSigTooShort + + // ErrSigTooLong is returned when a signature that should be a + // canonically-encoded DER signature is too long. + ErrSigTooLong + + // ErrSigInvalidSeqID is returned when a signature that should be a + // canonically-encoded DER signature does not have the expected ASN.1 + // sequence ID. + ErrSigInvalidSeqID + + // ErrSigInvalidDataLen is returned a signature that should be a + // canonically-encoded DER signature does not specify the correct number + // of remaining bytes for the R and S portions. + ErrSigInvalidDataLen + + // ErrSigMissingSTypeID is returned a signature that should be a + // canonically-encoded DER signature does not provide the ASN.1 type ID + // for S. + ErrSigMissingSTypeID + + // ErrSigMissingSLen is returned when a signature that should be a + // canonically-encoded DER signature does not provide the length of S. + ErrSigMissingSLen + + // ErrSigInvalidSLen is returned a signature that should be a + // canonically-encoded DER signature does not specify the correct number + // of bytes for the S portion. + ErrSigInvalidSLen + + // ErrSigInvalidRIntID is returned when a signature that should be a + // canonically-encoded DER signature does not have the expected ASN.1 + // integer ID for R. + ErrSigInvalidRIntID + + // ErrSigZeroRLen is returned when a signature that should be a + // canonically-encoded DER signature has an R length of zero. + ErrSigZeroRLen + + // ErrSigNegativeR is returned when a signature that should be a + // canonically-encoded DER signature has a negative value for R. + ErrSigNegativeR + + // ErrSigTooMuchRPadding is returned when a signature that should be a + // canonically-encoded DER signature has too much padding for R. + ErrSigTooMuchRPadding + + // ErrSigInvalidSIntID is returned when a signature that should be a + // canonically-encoded DER signature does not have the expected ASN.1 + // integer ID for S. + ErrSigInvalidSIntID + + // ErrSigZeroSLen is returned when a signature that should be a + // canonically-encoded DER signature has an S length of zero. + ErrSigZeroSLen + + // ErrSigNegativeS is returned when a signature that should be a + // canonically-encoded DER signature has a negative value for S. + ErrSigNegativeS + + // ErrSigTooMuchSPadding is returned when a signature that should be a + // canonically-encoded DER signature has too much padding for S. + ErrSigTooMuchSPadding // ErrSigHighS is returned when the ScriptVerifyLowS flag is set and the // script contains any signatures whose S values are higher than the @@ -314,7 +376,21 @@ var errorCodeStrings = map[ErrorCode]string{ ErrUnbalancedConditional: "ErrUnbalancedConditional", ErrMinimalData: "ErrMinimalData", ErrInvalidSigHashType: "ErrInvalidSigHashType", - ErrSigDER: "ErrSigDER", + ErrSigTooShort: "ErrSigTooShort", + ErrSigTooLong: "ErrSigTooLong", + ErrSigInvalidSeqID: "ErrSigInvalidSeqID", + ErrSigInvalidDataLen: "ErrSigInvalidDataLen", + ErrSigMissingSTypeID: "ErrSigMissingSTypeID", + ErrSigMissingSLen: "ErrSigMissingSLen", + ErrSigInvalidSLen: "ErrSigInvalidSLen", + ErrSigInvalidRIntID: "ErrSigInvalidRIntID", + ErrSigZeroRLen: "ErrSigZeroRLen", + ErrSigNegativeR: "ErrSigNegativeR", + ErrSigTooMuchRPadding: "ErrSigTooMuchRPadding", + ErrSigInvalidSIntID: "ErrSigInvalidSIntID", + ErrSigZeroSLen: "ErrSigZeroSLen", + ErrSigNegativeS: "ErrSigNegativeS", + ErrSigTooMuchSPadding: "ErrSigTooMuchSPadding", ErrSigHighS: "ErrSigHighS", ErrNotPushOnly: "ErrNotPushOnly", ErrSigNullDummy: "ErrSigNullDummy", diff --git a/txscript/error_test.go b/txscript/error_test.go index 74dd9aa8d3..ebac85fdaa 100644 --- a/txscript/error_test.go +++ b/txscript/error_test.go @@ -47,7 +47,21 @@ func TestErrorCodeStringer(t *testing.T) { {ErrUnbalancedConditional, "ErrUnbalancedConditional"}, {ErrMinimalData, "ErrMinimalData"}, {ErrInvalidSigHashType, "ErrInvalidSigHashType"}, - {ErrSigDER, "ErrSigDER"}, + {ErrSigTooShort, "ErrSigTooShort"}, + {ErrSigTooLong, "ErrSigTooLong"}, + {ErrSigInvalidSeqID, "ErrSigInvalidSeqID"}, + {ErrSigInvalidDataLen, "ErrSigInvalidDataLen"}, + {ErrSigMissingSTypeID, "ErrSigMissingSTypeID"}, + {ErrSigMissingSLen, "ErrSigMissingSLen"}, + {ErrSigInvalidSLen, "ErrSigInvalidSLen"}, + {ErrSigInvalidRIntID, "ErrSigInvalidRIntID"}, + {ErrSigZeroRLen, "ErrSigZeroRLen"}, + {ErrSigNegativeR, "ErrSigNegativeR"}, + {ErrSigTooMuchRPadding, "ErrSigTooMuchRPadding"}, + {ErrSigInvalidSIntID, "ErrSigInvalidSIntID"}, + {ErrSigZeroSLen, "ErrSigZeroSLen"}, + {ErrSigNegativeS, "ErrSigNegativeS"}, + {ErrSigTooMuchSPadding, "ErrSigTooMuchSPadding"}, {ErrSigHighS, "ErrSigHighS"}, {ErrNotPushOnly, "ErrNotPushOnly"}, {ErrSigNullDummy, "ErrSigNullDummy"}, diff --git a/txscript/reference_test.go b/txscript/reference_test.go index 1af9359bf8..5015960b94 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -211,7 +211,13 @@ func parseExpectedResult(expected string) ([]ErrorCode, error) { case "PUBKEYTYPE": return []ErrorCode{ErrPubKeyType}, nil case "SIG_DER": - return []ErrorCode{ErrSigDER, ErrInvalidSigHashType}, nil + return []ErrorCode{ErrSigTooShort, ErrSigTooLong, + ErrSigInvalidSeqID, ErrSigInvalidDataLen, ErrSigMissingSTypeID, + ErrSigMissingSLen, ErrSigInvalidSLen, + ErrSigInvalidRIntID, ErrSigZeroRLen, ErrSigNegativeR, + ErrSigTooMuchRPadding, ErrSigInvalidSIntID, + ErrSigZeroSLen, ErrSigNegativeS, ErrSigTooMuchSPadding, + ErrInvalidSigHashType}, nil case "EVAL_FALSE": return []ErrorCode{ErrEvalFalse, ErrEmptyStack}, nil case "EQUALVERIFY": From 53d846d68c773185d8a1f2dee388db8867f1474f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 23 Aug 2018 22:47:21 -0700 Subject: [PATCH 0223/1056] glide: update lock w/ hash instead of semantic ver --- glide.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glide.lock b/glide.lock index 67185c2268..7d4dca901c 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: e6f57b384b22282a2cb4e96aea9c46dc455b44336da09e64a9b19d13d877e7a4 -updated: 2018-08-22T19:51:39.57143044-07:00 +hash: 4d4efdd452d746ef15b66d35caadb3cbd58bb299e9c1f5172e90b2f3f272863f +updated: 2018-08-23T22:38:49.421147894-07:00 imports: - name: github.com/aead/siphash version: 83563a290f60225eb120d724600b9690c3fb536f From 7a657ffa2e186e88cac16b56a161512ee64afe05 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 23 Aug 2018 22:47:59 -0700 Subject: [PATCH 0224/1056] wire/msgcfcheckpt: add sanity check for cf checkpoint parsing --- wire/msgcfcheckpt.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/wire/msgcfcheckpt.go b/wire/msgcfcheckpt.go index 32f9575e5b..fc3fd53295 100644 --- a/wire/msgcfcheckpt.go +++ b/wire/msgcfcheckpt.go @@ -5,6 +5,7 @@ package wire import ( + "errors" "fmt" "io" @@ -15,8 +16,17 @@ const ( // CFCheckptInterval is the gap (in number of blocks) between each // filter header checkpoint. CFCheckptInterval = 1000 + + // maxCFHeadersLen is the max number of filter headers we will attempt + // to decode. + maxCFHeadersLen = 100000 ) +// ErrInsaneCFHeaderCount signals that we were asked to decode an +// unreasonable number of cfilter headers. +var ErrInsaneCFHeaderCount = errors.New( + "refusing to decode unreasonable number of filter headers") + // MsgCFCheckpt implements the Message interface and represents a bitcoin // cfcheckpt message. It is used to deliver committed filter header information // in response to a getcfcheckpt message (MsgGetCFCheckpt). See MsgGetCFCheckpt @@ -60,6 +70,11 @@ func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) return err } + // Refuse to decode an insane number of cfheaders. + if count > maxCFHeadersLen { + return ErrInsaneCFHeaderCount + } + // Create a contiguous slice of hashes to deserialize into in order to // reduce the number of allocations. msg.FilterHeaders = make([]*chainhash.Hash, count) From 602bced5f580438f6c5915208d966c63e34b8988 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 23 Aug 2018 22:48:28 -0700 Subject: [PATCH 0225/1056] peer/peer: switch TrickleTimeout -> TrickleInterval --- peer/peer.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index 04332aa413..4fa77cf741 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -30,6 +30,10 @@ const ( // MaxProtocolVersion is the max protocol version the peer supports. MaxProtocolVersion = wire.FeeFilterVersion + // DefaultTrickleInterval is the min time between attempts to send an + // inv message to a peer. + DefaultTrickleInterval = 10 * time.Second + // minAcceptableProtocolVersion is the lowest protocol version that a // connected peer may support. minAcceptableProtocolVersion = wire.MultipleAddressVersion @@ -266,9 +270,9 @@ type Config struct { // messages. Listeners MessageListeners - // TrickleTimeout is the duration of the ticker which trickles down the + // TrickleInterval is the duration of the ticker which trickles down the // inventory to a peer. - TrickleTimeout time.Duration + TrickleInterval time.Duration } // minUint32 is a helper function to return the minimum of two uint32s. @@ -1549,7 +1553,7 @@ out: func (p *Peer) queueHandler() { pendingMsgs := list.New() invSendQueue := list.New() - trickleTicker := time.NewTicker(p.cfg.TrickleTimeout) + trickleTicker := time.NewTicker(p.cfg.TrickleInterval) defer trickleTicker.Stop() // We keep the waiting flag so that we know if we have a message queued @@ -2173,6 +2177,11 @@ func newPeerBase(origCfg *Config, inbound bool) *Peer { cfg.ChainParams = &chaincfg.TestNet3Params } + // Set the trickle interval if a non-positive value is specified. + if cfg.TrickleInterval <= 0 { + cfg.TrickleInterval = DefaultTrickleInterval + } + p := Peer{ inbound: inbound, wireEncoding: wire.BaseEncoding, From 7b402cd63bebf95e733de65f042ac88f0beda252 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 23 Aug 2018 22:48:55 -0700 Subject: [PATCH 0226/1056] peer/peer_test: switch TrickleTimeout -> TrickleInterval --- peer/peer_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/peer/peer_test.go b/peer/peer_test.go index e87d2f9565..daf87ab810 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -236,7 +236,7 @@ func TestPeerConnection(t *testing.T) { ChainParams: &chaincfg.MainNetParams, ProtocolVersion: wire.RejectVersion, // Configure with older version Services: 0, - TrickleTimeout: time.Second * 10, + TrickleInterval: time.Second * 10, } peer2Cfg := &peer.Config{ Listeners: peer1Cfg.Listeners, @@ -245,7 +245,7 @@ func TestPeerConnection(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: wire.SFNodeNetwork | wire.SFNodeWitness, - TrickleTimeout: time.Second * 10, + TrickleInterval: time.Second * 10, } wantStats1 := peerStats{ @@ -449,7 +449,7 @@ func TestPeerListeners(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: wire.SFNodeBloom, - TrickleTimeout: time.Second * 10, + TrickleInterval: time.Second * 10, } inConn, outConn := pipe( &conn{raddr: "10.0.0.1:8333"}, @@ -620,7 +620,7 @@ func TestOutboundPeer(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: 0, - TrickleTimeout: time.Second * 10, + TrickleInterval: time.Second * 10, } r, w := io.Pipe() @@ -761,7 +761,7 @@ func TestUnsupportedVersionPeer(t *testing.T) { UserAgentComments: []string{"comment"}, ChainParams: &chaincfg.MainNetParams, Services: 0, - TrickleTimeout: time.Second * 10, + TrickleInterval: time.Second * 10, } localNA := wire.NewNetAddressIPPort( From 475eafdc7068c574a9ff5051eadf3ea2779ca66f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 23 Aug 2018 22:49:09 -0700 Subject: [PATCH 0227/1056] peer/example_test: switch TrickleTimeout -> TrickleInterval --- peer/example_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peer/example_test.go b/peer/example_test.go index 5c4b570de3..a549fe21ec 100644 --- a/peer/example_test.go +++ b/peer/example_test.go @@ -23,7 +23,7 @@ func mockRemotePeer() error { UserAgentName: "peer", // User agent name to advertise. UserAgentVersion: "1.0.0", // User agent version to advertise. ChainParams: &chaincfg.SimNetParams, - TrickleTimeout: time.Second * 10, + TrickleInterval: time.Second * 10, } // Accept connections on the simnet port. @@ -70,7 +70,7 @@ func Example_newOutboundPeer() { UserAgentVersion: "1.0.0", // User agent version to advertise. ChainParams: &chaincfg.SimNetParams, Services: 0, - TrickleTimeout: time.Second * 10, + TrickleInterval: time.Second * 10, Listeners: peer.MessageListeners{ OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) { fmt.Println("outbound: received version") From eb8e117f863cf643167d1f9a93acded9987c8db3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 23 Aug 2018 22:49:26 -0700 Subject: [PATCH 0228/1056] config: use peer.DefaultTrickleInterval as default val --- config.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/config.go b/config.go index f5d892a7e3..e004e42860 100644 --- a/config.go +++ b/config.go @@ -27,6 +27,7 @@ import ( "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/mempool" + "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcutil" "github.com/btcsuite/go-socks/socks" flags "github.com/jessevdk/go-flags" @@ -47,7 +48,7 @@ const ( defaultMaxRPCConcurrentReqs = 20 defaultDbType = "ffldb" defaultFreeTxRelayLimit = 15.0 - defaultTrickleTimeout = time.Second * 10 + defaultTrickleInterval = peer.DefaultTrickleInterval defaultBlockMinSize = 0 defaultBlockMaxSize = 750000 defaultBlockMinWeight = 0 @@ -141,7 +142,7 @@ type config struct { MinRelayTxFee float64 `long:"minrelaytxfee" description:"The minimum transaction fee in BTC/kB to be considered a non-zero fee."` FreeTxRelayLimit float64 `long:"limitfreerelay" description:"Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute"` NoRelayPriority bool `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"` - TrickleTimeout time.Duration `long:"trickletimeout" description:"Minimum time between attempts to send new inventory to a connected peer"` + TrickleInterval time.Duration `long:"trickleinterval" description:"Minimum time between attempts to send new inventory to a connected peer"` MaxOrphanTxs int `long:"maxorphantx" description:"Max number of orphan transactions to keep in memory"` Generate bool `long:"generate" description:"Generate (mine) bitcoins using the CPU"` MiningAddrs []string `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"` @@ -417,7 +418,7 @@ func loadConfig() (*config, []string, error) { RPCCert: defaultRPCCertFile, MinRelayTxFee: mempool.DefaultMinRelayTxFee.ToBTC(), FreeTxRelayLimit: defaultFreeTxRelayLimit, - TrickleTimeout: defaultTrickleTimeout, + TrickleInterval: defaultTrickleInterval, BlockMinSize: defaultBlockMinSize, BlockMaxSize: defaultBlockMaxSize, BlockMinWeight: defaultBlockMinWeight, From ae733e7291f2959a0dc1702acb25f575a9ac36ca Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 23 Aug 2018 22:49:47 -0700 Subject: [PATCH 0229/1056] server: switch TrickleTimeout -> TrickleInterval --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index a581a081db..46a8686181 100644 --- a/server.go +++ b/server.go @@ -1943,7 +1943,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { Services: sp.server.services, DisableRelayTx: cfg.BlocksOnly, ProtocolVersion: peer.MaxProtocolVersion, - TrickleTimeout: cfg.TrickleTimeout, + TrickleInterval: cfg.TrickleInterval, } } From c8e6363e2246a517ca8408cec5518c176e80e426 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 27 Aug 2018 17:46:35 -0700 Subject: [PATCH 0230/1056] server: modify locking in OnGetCFCheckpt to allow for read concurrency In this commit, we modify the locking scheme when serving cf checkpoints for peers to allow the server to serve multiple peers at the same time. Before this commit, we would first grab the write lock, check to see for expansion, then release the read lock. In this commit we reverse this and instead will grab the read lock, and upgrade to the write lock if we need to actually expand the size of the cache. --- server.go | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/server.go b/server.go index 46a8686181..bdb8c5c702 100644 --- a/server.go +++ b/server.go @@ -960,7 +960,7 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { // Fetch the current existing cache so we can decide if we need to // extend it or if its adequate as is. - sp.server.cfCheckptCachesMtx.Lock() + sp.server.cfCheckptCachesMtx.RLock() checkptCache := sp.server.cfCheckptCaches[msg.FilterType] // If the set of block hashes is beyond the current size of the cache, @@ -969,34 +969,41 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { var updateCache bool if len(blockHashes) > len(checkptCache) { // Now that we know we'll need to modify the size of the cache, - // we'll defer the release of the write lock so we don't - // forget. + // we'll release the read lock and grab the write lock to + // possibly expand the cache size. + sp.server.cfCheckptCachesMtx.RUnlock() + + sp.server.cfCheckptCachesMtx.Lock() defer sp.server.cfCheckptCachesMtx.Unlock() - // We'll mark that we need to update the cache for below and - // also expand the size of the cache in place. - updateCache = true + // Now that we have the write lock, we'll check again as it's + // possible that the cache has already been expanded. + checkptCache = sp.server.cfCheckptCaches[msg.FilterType] - additionalLength := len(blockHashes) - len(checkptCache) - newEntries := make([]cfHeaderKV, additionalLength) + // If we still need to expand the cache, then We'll mark that + // we need to update the cache for below and also expand the + // size of the cache in place. + if len(blockHashes) > len(checkptCache) { + updateCache = true - peerLog.Infof("Growing size of checkpoint cache from %v to %v "+ - "block hashes", len(checkptCache), len(blockHashes)) + additionalLength := len(blockHashes) - len(checkptCache) + newEntries := make([]cfHeaderKV, additionalLength) - checkptCache = append( - sp.server.cfCheckptCaches[msg.FilterType], - newEntries..., - ) + peerLog.Infof("Growing size of checkpoint cache from %v to %v "+ + "block hashes", len(checkptCache), len(blockHashes)) + + checkptCache = append( + sp.server.cfCheckptCaches[msg.FilterType], + newEntries..., + ) + } } else { - // Otherwise, we'll release the write lock, then grab the read - // lock, as the cache is already properly sized. - sp.server.cfCheckptCachesMtx.Unlock() - sp.server.cfCheckptCachesMtx.RLock() + // Otherwise, we'll hold onto the read lock for the remainder + // of this method. + defer sp.server.cfCheckptCachesMtx.RUnlock() peerLog.Tracef("Serving stale cache of size %v", len(checkptCache)) - - defer sp.server.cfCheckptCachesMtx.RUnlock() } // Now that we know the cache is of an appropriate size, we'll iterate From 222a6dac0d99f222bbe95f2c055888d87baec07c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 27 Aug 2018 17:49:25 -0700 Subject: [PATCH 0231/1056] server: fix panic bug when looking for cf checkpoint cache intersection w/ chain In this commit, we fix a panic bug that can arise when we attempt to process a cf checkpoint message from a remote peer. Before this commit, if the size of the checkpoint cache was large than the number of checkpoints requested by the peer, we would panic with an out of bounds error. In order to prevent, this we'll now use the size of the requested set of hashes as our bound to ensure that we don't panic. --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index bdb8c5c702..7ac619a82b 100644 --- a/server.go +++ b/server.go @@ -1011,7 +1011,7 @@ func (sp *serverPeer) OnGetCFCheckpt(_ *peer.Peer, msg *wire.MsgGetCFCheckpt) { // a re-org has occurred so items in the db are now in the main china // while the cache has been partially invalidated. var forkIdx int - for forkIdx = len(checkptCache); forkIdx > 0; forkIdx-- { + for forkIdx = len(blockHashes); forkIdx > 0; forkIdx-- { if checkptCache[forkIdx-1].blockHash == blockHashes[forkIdx-1] { break } From 085a2b96e9c952576736abdfc29b5ca380d2b81b Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 11 Jul 2018 14:13:39 +0200 Subject: [PATCH 0232/1056] rpcclient: expose the Node command for RPC API. --- rpcclient/net.go | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/rpcclient/net.go b/rpcclient/net.go index aeda8b3c59..3b166cb934 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -63,6 +63,40 @@ func (c *Client) AddNode(host string, command AddNodeCommand) error { return c.AddNodeAsync(host, command).Receive() } +// FutureNodeResult is a future promise to deliver the result of a NodeAsync +// RPC invocation (or an applicable error). +type FutureNodeResult chan *response + +// Receive waits for the response promised by the future and returns an error if +// any occurred when performing the specified command. +func (r FutureNodeResult) Receive() error { + _, err := receiveFuture(r) + return err +} + +// NodeAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See Node for the blocking version and more details. +func (c *Client) NodeAsync(command btcjson.NodeSubCmd, host string, + connectSubCmd *string) FutureNodeResult { + cmd := btcjson.NewNodeCmd(command, host, connectSubCmd) + return c.sendCmd(cmd) +} + +// Node attempts to perform the passed node command on the host. +// For example, it can be used to add or a remove a persistent peer, or to do +// connect or diconnect a non-persistent one. +// +// The connectSubCmd should be set either "perm" or "temp", depending on +// whether we are targetting a persistent or non-persistent peer. Passing nil +// will cause the default value to be used, which currently is "temp". +func (c *Client) Node(command btcjson.NodeSubCmd, host string, + connectSubCmd *string) error { + return c.NodeAsync(command, host, connectSubCmd).Receive() +} + // FutureGetAddedNodeInfoResult is a future promise to deliver the result of a // GetAddedNodeInfoAsync RPC invocation (or an applicable error). type FutureGetAddedNodeInfoResult chan *response From badf5453e9a14026b0a8667b44771c977d3b0ea6 Mon Sep 17 00:00:00 2001 From: qshuai Date: Sat, 8 Sep 2018 22:34:41 +0800 Subject: [PATCH 0233/1056] server: Fix struct name mismatch --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index 7ac619a82b..2e91eee3b8 100644 --- a/server.go +++ b/server.go @@ -94,7 +94,7 @@ func (oa *onionAddr) Network() string { // Ensure onionAddr implements the net.Addr interface. var _ net.Addr = (*onionAddr)(nil) -// onionAddr implements the net.Addr interface with two struct fields +// simpleAddr implements the net.Addr interface with two struct fields type simpleAddr struct { net, addr string } From db8e412dc620fe7b53fe320c473b6d5fa1810772 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Thu, 20 Sep 2018 09:26:45 -0700 Subject: [PATCH 0234/1056] btcec/signature: fix DoS bug with signature parsing --- btcec/signature.go | 5 ++++- btcec/signature_test.go | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/btcec/signature.go b/btcec/signature.go index 6026c4241f..fedd92e9b9 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -112,7 +112,10 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) // length of remaining message siglen := sigStr[index] index++ - if int(siglen+2) > len(sigStr) { + + // siglen should be less than the entire message and greater than + // the minimal message of size 8. + if int(siglen+2) > len(sigStr) || int(siglen+2) < 8 { return nil, errors.New("malformed signature: bad length") } // trim the slice we're working on so we only look at what matters. diff --git a/btcec/signature_test.go b/btcec/signature_test.go index a4b86bb828..19ab772ef9 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -113,6 +113,12 @@ var signatureTests = []signatureTest{ der: true, isValid: false, }, + { + name: "invalid message length", + sig: []byte{0x30, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00}, + der: false, + isValid: false, + }, { name: "long len", sig: []byte{0x30, 0x45, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, From 25dfda9bd3f650dd9bb73c1a77bb566ac885c648 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 20:19:48 -0500 Subject: [PATCH 0235/1056] peer: Add duplicate version message test. This adds a test to ensure duplicate version messages are rejected. Backported from Decred. --- peer/peer.go | 2 +- peer/peer_test.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/peer/peer.go b/peer/peer.go index 4fa77cf741..ae61872aef 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1369,7 +1369,7 @@ out: p.stallControl <- stallControlMsg{sccHandlerStart, rmsg} switch msg := rmsg.(type) { case *wire.MsgVersion: - + // Limit to one version message per peer. p.PushRejectMsg(msg.Command(), wire.RejectDuplicate, "duplicate version message", nil, true) break out diff --git a/peer/peer_test.go b/peer/peer_test.go index daf87ab810..4c49040b11 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -1,4 +1,5 @@ // Copyright (c) 2015-2016 The btcsuite developers +// Copyright (c) 2016-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -856,6 +857,65 @@ func TestUnsupportedVersionPeer(t *testing.T) { } } +// TestDuplicateVersionMsg ensures that receiving a version message after one +// has already been received results in the peer being disconnected. +func TestDuplicateVersionMsg(t *testing.T) { + // Create a pair of peers that are connected to each other using a fake + // connection. + verack := make(chan struct{}) + peerCfg := &peer.Config{ + Listeners: peer.MessageListeners{ + OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { + verack <- struct{}{} + }, + }, + UserAgentName: "peer", + UserAgentVersion: "1.0", + ChainParams: &chaincfg.MainNetParams, + Services: 0, + } + inConn, outConn := pipe( + &conn{laddr: "10.0.0.1:9108", raddr: "10.0.0.2:9108"}, + &conn{laddr: "10.0.0.2:9108", raddr: "10.0.0.1:9108"}, + ) + outPeer, err := peer.NewOutboundPeer(peerCfg, inConn.laddr) + if err != nil { + t.Fatalf("NewOutboundPeer: unexpected err: %v\n", err) + } + outPeer.AssociateConnection(outConn) + inPeer := peer.NewInboundPeer(peerCfg) + inPeer.AssociateConnection(inConn) + // Wait for the veracks from the initial protocol version negotiation. + for i := 0; i < 2; i++ { + select { + case <-verack: + case <-time.After(time.Second): + t.Fatal("verack timeout") + } + } + // Queue a duplicate version message from the outbound peer and wait until + // it is sent. + done := make(chan struct{}) + outPeer.QueueMessage(&wire.MsgVersion{}, done) + select { + case <-done: + case <-time.After(time.Second): + t.Fatal("send duplicate version timeout") + } + // Ensure the peer that is the recipient of the duplicate version closes the + // connection. + disconnected := make(chan struct{}, 1) + go func() { + inPeer.WaitForDisconnect() + disconnected <- struct{}{} + }() + select { + case <-disconnected: + case <-time.After(time.Second): + t.Fatal("peer did not disconnect") + } +} + func init() { // Allow self connection when running the tests. peer.TstAllowSelfConns() From 8965887ca4d4b07acd126d13156737dbdf487f93 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Thu, 20 Sep 2018 20:19:11 -0700 Subject: [PATCH 0236/1056] btcec/signature: moved minimum signature length to a constant --- btcec/signature.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/btcec/signature.go b/btcec/signature.go index fedd92e9b9..92929c7d66 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -85,6 +85,11 @@ func (sig *Signature) IsEqual(otherSig *Signature) bool { sig.S.Cmp(otherSig.S) == 0 } +// minSigLen is the minimum length of a DER encoded signature and is +// when both R and S are 1 byte each. +// 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + +const minSigLen = 8 + func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { // Originally this code used encoding/asn1 in order to parse the // signature, but a number of problems were found with this approach. @@ -98,9 +103,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) signature := &Signature{} - // minimal message is when both numbers are 1 bytes. adding up to: - // 0x30 + len + 0x02 + 0x01 + + 0x2 + 0x01 + - if len(sigStr) < 8 { + if len(sigStr) < minSigLen { return nil, errors.New("malformed signature: too short") } // 0x30 @@ -115,7 +118,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) // siglen should be less than the entire message and greater than // the minimal message of size 8. - if int(siglen+2) > len(sigStr) || int(siglen+2) < 8 { + if int(siglen+2) > len(sigStr) || int(siglen+2) < minSigLen { return nil, errors.New("malformed signature: bad length") } // trim the slice we're working on so we only look at what matters. From 66d33037ec0f1c5d2aa66d0906c73efaa49309f3 Mon Sep 17 00:00:00 2001 From: Julian Meyer Date: Thu, 20 Sep 2018 20:24:03 -0700 Subject: [PATCH 0237/1056] btcec/signature: updated comment to reference constant instead of value --- btcec/signature.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcec/signature.go b/btcec/signature.go index 92929c7d66..a4781b00f9 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -117,7 +117,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) index++ // siglen should be less than the entire message and greater than - // the minimal message of size 8. + // the minimal message size. if int(siglen+2) > len(sigStr) || int(siglen+2) < minSigLen { return nil, errors.New("malformed signature: bad length") } From 118f55233b7d18c3bd8f7520a88d3e547b62a37f Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 20:44:44 -0500 Subject: [PATCH 0238/1056] peer: Rework version negotiation. This modifies the negotiation logic to ensure the callback has the opportunity to see the message before the peer is disconnected and improves the error handling when reading the remote version message. It also has the side effect of ensuring the protocol version is negotiated before sending reject messages with the exception of the first message not being a version message since negotiation is not possible in that case. This is being changed because it is useful for the server to see the message regardless in order to have the opportunity to things such as update the address manager and reject peers that don't have desired services. Backported from Decred. --- peer/peer.go | 113 +++++++++++++++++++++++++-------------------------- server.go | 6 +++ 2 files changed, 62 insertions(+), 57 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index ae61872aef..a4ea1fd4e3 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -34,9 +34,9 @@ const ( // inv message to a peer. DefaultTrickleInterval = 10 * time.Second - // minAcceptableProtocolVersion is the lowest protocol version that a + // MinAcceptableProtocolVersion is the lowest protocol version that a // connected peer may support. - minAcceptableProtocolVersion = wire.MultipleAddressVersion + MinAcceptableProtocolVersion = wire.MultipleAddressVersion // outputBufferSize is the number of elements the output channels use. outputBufferSize = 50 @@ -1875,26 +1875,42 @@ func (p *Peer) Disconnect() { close(p.quit) } -// handleRemoteVersionMsg is invoked when a version bitcoin message is received -// from the remote peer. It will return an error if the remote peer's version -// is not compatible with ours. -func (p *Peer) handleRemoteVersionMsg(msg *wire.MsgVersion) error { +// readRemoteVersionMsg waits for the next message to arrive from the remote +// peer. If the next message is not a version message or the version is not +// acceptable then return an error. +func (p *Peer) readRemoteVersionMsg() error { + // Read their version message. + remoteMsg, _, err := p.readMessage(wire.LatestEncoding) + if err != nil { + return err + } + + // Notify and disconnect clients if the first message is not a version + // message. + msg, ok := remoteMsg.(*wire.MsgVersion) + if !ok { + reason := "a version message must precede all others" + rejectMsg := wire.NewMsgReject(msg.Command(), wire.RejectMalformed, + reason) + _ = p.writeMessage(rejectMsg, wire.LatestEncoding) + return errors.New(reason) + } + // Detect self connections. if !allowSelfConns && sentNonces.Exists(msg.Nonce) { return errors.New("disconnecting peer connected to self") } - // Notify and disconnect clients that have a protocol version that is - // too old. - // - // NOTE: If minAcceptableProtocolVersion is raised to be higher than - // wire.RejectVersion, this should send a reject packet before - // disconnecting. - if uint32(msg.ProtocolVersion) < minAcceptableProtocolVersion { - reason := fmt.Sprintf("protocol version must be %d or greater", - minAcceptableProtocolVersion) - return errors.New(reason) - } + // Negotiate the protocol version and set the services to what the remote + // peer advertised. + p.flagsMtx.Lock() + p.advertisedProtoVer = uint32(msg.ProtocolVersion) + p.protocolVersion = minUint32(p.protocolVersion, p.advertisedProtoVer) + p.versionKnown = true + p.services = msg.Services + p.flagsMtx.Unlock() + log.Debugf("Negotiated protocol version %d for peer %s", + p.protocolVersion, p) // Updating a bunch of stats including block based stats, and the // peer's time offset. @@ -1904,22 +1920,10 @@ func (p *Peer) handleRemoteVersionMsg(msg *wire.MsgVersion) error { p.timeOffset = msg.Timestamp.Unix() - time.Now().Unix() p.statsMtx.Unlock() - // Negotiate the protocol version. + // Set the peer's ID, user agent, and potentially the flag which + // specifies the witness support is enabled. p.flagsMtx.Lock() - p.advertisedProtoVer = uint32(msg.ProtocolVersion) - p.protocolVersion = minUint32(p.protocolVersion, p.advertisedProtoVer) - p.versionKnown = true - log.Debugf("Negotiated protocol version %d for peer %s", - p.protocolVersion, p) - - // Set the peer's ID. p.id = atomic.AddInt32(&nodeCount, 1) - - // Set the supported services for the peer to what the remote peer - // advertised. - p.services = msg.Services - - // Set the remote peer's user agent. p.userAgent = msg.UserAgent // Determine if the peer would like to receive witness data with @@ -1938,36 +1942,29 @@ func (p *Peer) handleRemoteVersionMsg(msg *wire.MsgVersion) error { p.wireEncoding = wire.WitnessEncoding } - return nil -} - -// readRemoteVersionMsg waits for the next message to arrive from the remote -// peer. If the next message is not a version message or the version is not -// acceptable then return an error. -func (p *Peer) readRemoteVersionMsg() error { - // Read their version message. - msg, _, err := p.readMessage(wire.LatestEncoding) - if err != nil { - return err - } - - remoteVerMsg, ok := msg.(*wire.MsgVersion) - if !ok { - errStr := "A version message must precede all others" - log.Errorf(errStr) - - rejectMsg := wire.NewMsgReject(msg.Command(), wire.RejectMalformed, - errStr) - return p.writeMessage(rejectMsg, wire.LatestEncoding) + // Invoke the callback if specified. + if p.cfg.Listeners.OnVersion != nil { + p.cfg.Listeners.OnVersion(p, msg) } - if err := p.handleRemoteVersionMsg(remoteVerMsg); err != nil { - return err + // Notify and disconnect clients that have a protocol version that is + // too old. + // + // NOTE: If minAcceptableProtocolVersion is raised to be higher than + // wire.RejectVersion, this should send a reject packet before + // disconnecting. + if uint32(msg.ProtocolVersion) < MinAcceptableProtocolVersion { + // Send a reject message indicating the protocol version is + // obsolete and wait for the message to be sent before + // disconnecting. + reason := fmt.Sprintf("protocol version must be %d or greater", + MinAcceptableProtocolVersion) + rejectMsg := wire.NewMsgReject(msg.Command(), wire.RejectObsolete, + reason) + _ = p.writeMessage(rejectMsg, wire.LatestEncoding) + return errors.New(reason) } - if p.cfg.Listeners.OnVersion != nil { - p.cfg.Listeners.OnVersion(p, remoteVerMsg) - } return nil } @@ -2099,9 +2096,11 @@ func (p *Peer) start() error { select { case err := <-negotiateErr: if err != nil { + p.Disconnect() return err } case <-time.After(negotiateTimeout): + p.Disconnect() return errors.New("protocol negotiation timeout") } log.Debugf("Connected to %s", p.Addr()) diff --git a/server.go b/server.go index 2e91eee3b8..9c82ffa7e7 100644 --- a/server.go +++ b/server.go @@ -389,6 +389,12 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { // and is used to negotiate the protocol version details as well as kick start // the communications. func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { + // Ignore peers that have a protcol version that is too old. The peer + // negotiation logic will disconnect it after this callback returns. + if msg.ProtocolVersion < int32(peer.MinAcceptableProtocolVersion) { + return + } + // Add the remote peer time as a sample for creating an offset against // the local clock to keep the network time in sync. sp.server.timeSource.AddTimeSample(sp.Addr(), msg.Timestamp) From 7b103e243413d3af03257649ca2185ae78f8eb6f Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 21:24:53 -0500 Subject: [PATCH 0239/1056] peer: Allow OnVersion callback to reject peer. This modifies the OnVersion callback to allow a reject message to be returned in which case the message will be sent to the peer and the peer will be disconnected. Backported from Decred. --- peer/example_test.go | 6 ++++-- peer/peer.go | 10 ++++++++-- peer/peer_test.go | 3 ++- server.go | 11 ++++++----- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/peer/example_test.go b/peer/example_test.go index a549fe21ec..cb67683bae 100644 --- a/peer/example_test.go +++ b/peer/example_test.go @@ -1,4 +1,5 @@ -// Copyright (c) 2015-2016 The btcsuite developers +// Copyright (c) 2015-2018 The btcsuite developers +// Copyright (c) 2016-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -72,8 +73,9 @@ func Example_newOutboundPeer() { Services: 0, TrickleInterval: time.Second * 10, Listeners: peer.MessageListeners{ - OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) { + OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { fmt.Println("outbound: received version") + return nil }, OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { verack <- struct{}{} diff --git a/peer/peer.go b/peer/peer.go index a4ea1fd4e3..afb141738b 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -187,7 +187,9 @@ type MessageListeners struct { OnMerkleBlock func(p *Peer, msg *wire.MsgMerkleBlock) // OnVersion is invoked when a peer receives a version bitcoin message. - OnVersion func(p *Peer, msg *wire.MsgVersion) + // The caller may return a reject message in which case the message will + // be sent to the peer and the peer will be disconnected. + OnVersion func(p *Peer, msg *wire.MsgVersion) *wire.MsgReject // OnVerAck is invoked when a peer receives a verack bitcoin message. OnVerAck func(p *Peer, msg *wire.MsgVerAck) @@ -1944,7 +1946,11 @@ func (p *Peer) readRemoteVersionMsg() error { // Invoke the callback if specified. if p.cfg.Listeners.OnVersion != nil { - p.cfg.Listeners.OnVersion(p, msg) + rejectMsg := p.cfg.Listeners.OnVersion(p, msg) + if rejectMsg != nil { + _ = p.writeMessage(rejectMsg, wire.LatestEncoding) + return errors.New(rejectMsg.Reason) + } } // Notify and disconnect clients that have a protocol version that is diff --git a/peer/peer_test.go b/peer/peer_test.go index 4c49040b11..fff0ce3fd8 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -432,8 +432,9 @@ func TestPeerListeners(t *testing.T) { OnMerkleBlock: func(p *peer.Peer, msg *wire.MsgMerkleBlock) { ok <- msg }, - OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) { + OnVersion: func(p *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { ok <- msg + return nil }, OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { verack <- struct{}{} diff --git a/server.go b/server.go index 9c82ffa7e7..320238ad31 100644 --- a/server.go +++ b/server.go @@ -1,5 +1,5 @@ // Copyright (c) 2013-2017 The btcsuite developers -// Copyright (c) 2015-2017 The Decred developers +// Copyright (c) 2015-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -388,11 +388,11 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { // OnVersion is invoked when a peer receives a version bitcoin message // and is used to negotiate the protocol version details as well as kick start // the communications. -func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { +func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { // Ignore peers that have a protcol version that is too old. The peer // negotiation logic will disconnect it after this callback returns. if msg.ProtocolVersion < int32(peer.MinAcceptableProtocolVersion) { - return + return nil } // Add the remote peer time as a sample for creating an offset against @@ -424,7 +424,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { if err != nil { peerLog.Errorf("Unable to query for segwit "+ "soft-fork state: %v", err) - return + return nil } if segwitActive && !sp.IsWitnessEnabled() { @@ -432,7 +432,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { "peer %v, isn't segwit enabled and "+ "we need more segwit enabled peers", sp) sp.Disconnect() - return + return nil } // TODO(davec): Only do this if not doing the initial block @@ -463,6 +463,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) { // Add valid peer to the server. sp.server.AddPeer(sp) + return nil } // OnMemPool is invoked when a peer receives a mempool bitcoin message. From 9151ebc90b93c4be0ad70c1319bf929b3ec15820 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 21:30:24 -0500 Subject: [PATCH 0240/1056] server: Reject outbound conns to non-full nodes. This modifies the server connection code to reject outbound peers that do not offer full node services. --- server.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server.go b/server.go index 320238ad31..0f1d100f47 100644 --- a/server.go +++ b/server.go @@ -385,6 +385,12 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { } } +// hasServices returns whether or not the provided advertised service flags have +// all of the provided desired service flags set. +func hasServices(advertised, desired wire.ServiceFlag) bool { + return advertised&desired == desired +} + // OnVersion is invoked when a peer receives a version bitcoin message // and is used to negotiate the protocol version details as well as kick start // the communications. @@ -395,6 +401,18 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej return nil } + // Reject outbound peers that are not full nodes. + wantServices := wire.SFNodeNetwork + if !sp.Inbound() && !hasServices(msg.Services, wantServices) { + missingServices := wantServices & ^msg.Services + srvrLog.Debugf("Rejecting peer %s with services %v due to not "+ + "providing desired services %v", sp.Peer, msg.Services, + missingServices) + reason := fmt.Sprintf("required services %#x not offered", + uint64(missingServices)) + return wire.NewMsgReject(msg.Command(), wire.RejectNonstandard, reason) + } + // Add the remote peer time as a sample for creating an offset against // the local clock to keep the network time in sync. sp.server.timeSource.AddTimeSample(sp.Addr(), msg.Timestamp) From 4d1e1db9eae33fd30421b7048be1cc936609b69a Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 21:40:01 -0500 Subject: [PATCH 0241/1056] peer: Improve net address service adverts. This modifies the peer code which deals with advertising service flags via the net address fields of the version message as follows: - For outgoing connections: - Set the local netaddress services to what the local peer supports - Set the remote netaddress services to 0 to indicate no services as they are still unknown - For incoming connections: - Set the local netaddress services to what the local peer supports - Set the remote netaddress services to the what was advertised by the remote peer in its version message --- peer/peer.go | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index afb141738b..61bc619ffb 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1995,7 +1995,8 @@ func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { proxyaddress, _, err := net.SplitHostPort(p.cfg.Proxy) // invalid proxy means poorly configured, be on the safe side. if err != nil || p.na.IP.String() == proxyaddress { - theirNA = wire.NewNetAddressIPPort(net.IP([]byte{0, 0, 0, 0}), 0, 0) + theirNA = wire.NewNetAddressIPPort(net.IP([]byte{0, 0, 0, 0}), 0, + theirNA.Services) } } @@ -2023,25 +2024,7 @@ func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { msg.AddUserAgent(p.cfg.UserAgentName, p.cfg.UserAgentVersion, p.cfg.UserAgentComments...) - // XXX: bitcoind appears to always enable the full node services flag - // of the remote peer netaddress field in the version message regardless - // of whether it knows it supports it or not. Also, bitcoind sets - // the services field of the local peer to 0 regardless of support. - // - // Realistically, this should be set as follows: - // - For outgoing connections: - // - Set the local netaddress services to what the local peer - // actually supports - // - Set the remote netaddress services to 0 to indicate no services - // as they are still unknown - // - For incoming connections: - // - Set the local netaddress services to what the local peer - // actually supports - // - Set the remote netaddress services to the what was advertised by - // by the remote peer in its version message - msg.AddrYou.Services = wire.SFNodeNetwork - - // Advertise the services flag + // Advertise local services. msg.Services = p.cfg.Services // Advertise our max supported protocol version. @@ -2229,14 +2212,13 @@ func NewOutboundPeer(cfg *Config, addr string) (*Peer, error) { } if cfg.HostToNetAddress != nil { - na, err := cfg.HostToNetAddress(host, uint16(port), cfg.Services) + na, err := cfg.HostToNetAddress(host, uint16(port), 0) if err != nil { return nil, err } p.na = na } else { - p.na = wire.NewNetAddressIPPort(net.ParseIP(host), uint16(port), - cfg.Services) + p.na = wire.NewNetAddressIPPort(net.ParseIP(host), uint16(port), 0) } return p, nil From 24e23525fb15b3370c9db4cabe88efffa53827b5 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sun, 3 Jun 2018 03:27:33 -0500 Subject: [PATCH 0242/1056] addrmgr: Expose method to update services. This exposes a new method named SetServices to the address manager which can be used to update the services for a known address. This will be useful to keep known services up to date. Backported from Decred. --- addrmgr/addrmanager.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index 4dc8bdbd75..fc6930688b 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -1,4 +1,5 @@ // Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2015-2018 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -937,6 +938,25 @@ func (a *AddrManager) Good(addr *wire.NetAddress) { a.addrNew[newBucket][rmkey] = rmka } +// SetServices sets the services for the giiven address to the provided value. +func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFlag) { + a.mtx.Lock() + defer a.mtx.Unlock() + + ka := a.find(addr) + if ka == nil { + return + } + + // Update the services if needed. + if ka.na.Services != services { + // ka.na is immutable, so replace it. + naCopy := *ka.na + naCopy.Services = services + ka.na = &naCopy + } +} + // AddLocalAddress adds na to the list of known local addresses to advertise // with the given priority. func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPriority) error { From 4b20d4f86a9e285ff495da117f92d13036c5121b Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sun, 3 Jun 2018 03:29:22 -0500 Subject: [PATCH 0243/1056] server: Update addrmgr services on outbound conns. This adds code to update the address manager services for a known address to the services advertised by peers when they are connected to via an outbound connection. It is only done for outbound connections to help prevent malicious behavior from inbound connections. Backported from Decred. --- server.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index 0f1d100f47..3f431d2e60 100644 --- a/server.go +++ b/server.go @@ -395,6 +395,21 @@ func hasServices(advertised, desired wire.ServiceFlag) bool { // and is used to negotiate the protocol version details as well as kick start // the communications. func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgReject { + // Update the address manager with the advertised services for outbound + // connections in case they have changed. This is not done for inbound + // connections to help prevent malicious behavior and is skipped when + // running on the simulation test network since it is only intended to + // connect to specified peers and actively avoids advertising and + // connecting to discovered peers. + // + // NOTE: This is done before rejecting peers that are too old to ensure + // it is updated regardless in the case a new minimum protocol version is + // enforced and the remote node has not upgraded yet. + addrManager := sp.server.addrManager + if !cfg.SimNet && !sp.Inbound() { + addrManager.SetServices(sp.NA(), msg.Services) + } + // Ignore peers that have a protcol version that is too old. The peer // negotiation logic will disconnect it after this callback returns. if msg.ProtocolVersion < int32(peer.MinAcceptableProtocolVersion) { @@ -430,8 +445,6 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // to specified peers and actively avoids advertising and connecting to // discovered peers. if !cfg.SimNet { - addrManager := sp.server.addrManager - // Outbound connections. if !sp.Inbound() { // After soft-fork activation, only make outbound From d2c7892aa4b1dcbb12af862df1dcd6b18eddf4f9 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 22:57:57 -0500 Subject: [PATCH 0244/1056] server: Use local inbound var in version handler. This modifies the OnVersion handler for server peers to use a local variable for the inbound status of the peer in order to avoid grabbing the mutex multiple times. While here, it also does some light cleanup. There are no functional changes. Backported from Decred. --- server.go | 106 ++++++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/server.go b/server.go index 3f431d2e60..a6cd27807c 100644 --- a/server.go +++ b/server.go @@ -405,8 +405,9 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // NOTE: This is done before rejecting peers that are too old to ensure // it is updated regardless in the case a new minimum protocol version is // enforced and the remote node has not upgraded yet. + isInbound := sp.Inbound() addrManager := sp.server.addrManager - if !cfg.SimNet && !sp.Inbound() { + if !cfg.SimNet && !isInbound { addrManager.SetServices(sp.NA(), msg.Services) } @@ -418,7 +419,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // Reject outbound peers that are not full nodes. wantServices := wire.SFNodeNetwork - if !sp.Inbound() && !hasServices(msg.Services, wantServices) { + if !isInbound && !hasServices(msg.Services, wantServices) { missingServices := wantServices & ^msg.Services srvrLog.Debugf("Rejecting peer %s with services %v due to not "+ "providing desired services %v", sp.Peer, msg.Services, @@ -428,70 +429,65 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej return wire.NewMsgReject(msg.Command(), wire.RejectNonstandard, reason) } - // Add the remote peer time as a sample for creating an offset against - // the local clock to keep the network time in sync. - sp.server.timeSource.AddTimeSample(sp.Addr(), msg.Timestamp) - - // Signal the sync manager this peer is a new sync candidate. - sp.server.syncManager.NewPeer(sp.Peer) - - // Choose whether or not to relay transactions before a filter command - // is received. - sp.setDisableRelayTx(msg.DisableRelayTx) - // Update the address manager and request known addresses from the // remote peer for outbound connections. This is skipped when running // on the simulation test network since it is only intended to connect // to specified peers and actively avoids advertising and connecting to // discovered peers. - if !cfg.SimNet { - // Outbound connections. - if !sp.Inbound() { - // After soft-fork activation, only make outbound - // connection to peers if they flag that they're segwit - // enabled. - chain := sp.server.chain - segwitActive, err := chain.IsDeploymentActive(chaincfg.DeploymentSegwit) - if err != nil { - peerLog.Errorf("Unable to query for segwit "+ - "soft-fork state: %v", err) - return nil - } - - if segwitActive && !sp.IsWitnessEnabled() { - peerLog.Infof("Disconnecting non-segwit "+ - "peer %v, isn't segwit enabled and "+ - "we need more segwit enabled peers", sp) - sp.Disconnect() - return nil - } - - // TODO(davec): Only do this if not doing the initial block - // download and the local address is routable. - if !cfg.DisableListen /* && isCurrent? */ { - // Get address that best matches. - lna := addrManager.GetBestLocalAddress(sp.NA()) - if addrmgr.IsRoutable(lna) { - // Filter addresses the peer already knows about. - addresses := []*wire.NetAddress{lna} - sp.pushAddrMsg(addresses) - } - } + if !cfg.SimNet && !isInbound { + // After soft-fork activation, only make outbound + // connection to peers if they flag that they're segwit + // enabled. + chain := sp.server.chain + segwitActive, err := chain.IsDeploymentActive(chaincfg.DeploymentSegwit) + if err != nil { + peerLog.Errorf("Unable to query for segwit soft-fork state: %v", + err) + return nil + } - // Request known addresses if the server address manager needs - // more and the peer has a protocol version new enough to - // include a timestamp with addresses. - hasTimestamp := sp.ProtocolVersion() >= - wire.NetAddressTimeVersion - if addrManager.NeedMoreAddresses() && hasTimestamp { - sp.QueueMessage(wire.NewMsgGetAddr(), nil) + if segwitActive && !sp.IsWitnessEnabled() { + peerLog.Infof("Disconnecting non-segwit peer %v, isn't segwit "+ + "enabled and we need more segwit enabled peers", sp) + sp.Disconnect() + return nil + } + + // TODO(davec): Only do this if not doing the initial block + // download and the local address is routable. + if !cfg.DisableListen /* && isCurrent? */ { + // Get address that best matches. + lna := addrManager.GetBestLocalAddress(sp.NA()) + if addrmgr.IsRoutable(lna) { + // Filter addresses the peer already knows about. + addresses := []*wire.NetAddress{lna} + sp.pushAddrMsg(addresses) } + } - // Mark the address as a known good address. - addrManager.Good(sp.NA()) + // Request known addresses if the server address manager needs + // more and the peer has a protocol version new enough to + // include a timestamp with addresses. + hasTimestamp := sp.ProtocolVersion() >= wire.NetAddressTimeVersion + if addrManager.NeedMoreAddresses() && hasTimestamp { + sp.QueueMessage(wire.NewMsgGetAddr(), nil) } + + // Mark the address as a known good address. + addrManager.Good(sp.NA()) } + // Add the remote peer time as a sample for creating an offset against + // the local clock to keep the network time in sync. + sp.server.timeSource.AddTimeSample(sp.Addr(), msg.Timestamp) + + // Signal the sync manager this peer is a new sync candidate. + sp.server.syncManager.NewPeer(sp.Peer) + + // Choose whether or not to relay transactions before a filter command + // is received. + sp.setDisableRelayTx(msg.DisableRelayTx) + // Add valid peer to the server. sp.server.AddPeer(sp) return nil From c8b9fab8209e111ef9b770b3c7a9313276eab1d0 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 23:04:26 -0500 Subject: [PATCH 0245/1056] server: Only advertise local addr when current. This changes the server peers OnVersion handler to only advertise the server as a viable target for inbound connections when the server believes it is close the best known tip. Backported from Decred. --- server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server.go b/server.go index a6cd27807c..7fe114b14c 100644 --- a/server.go +++ b/server.go @@ -453,9 +453,9 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej return nil } - // TODO(davec): Only do this if not doing the initial block - // download and the local address is routable. - if !cfg.DisableListen /* && isCurrent? */ { + // Advertise the local address when the server accepts incoming + // connections and it believes itself to be close to the best known tip. + if !cfg.DisableListen && sp.server.syncManager.IsCurrent() { // Get address that best matches. lna := addrManager.GetBestLocalAddress(sp.NA()) if addrmgr.IsRoutable(lna) { From 8c981e4ef299d5376b6ebe87fa4dafccb83e0117 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Fri, 10 Aug 2018 23:11:19 -0500 Subject: [PATCH 0246/1056] server: Use local addr var in version handler. This modifies the OnVersion handler for server peers to use a local variable for the remote address of the peer in order to avoid grabbing the mutex multiple times. There are no functional changes. Backported from Decred. --- server.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server.go b/server.go index 7fe114b14c..42f34da5b2 100644 --- a/server.go +++ b/server.go @@ -406,9 +406,10 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // it is updated regardless in the case a new minimum protocol version is // enforced and the remote node has not upgraded yet. isInbound := sp.Inbound() + remoteAddr := sp.NA() addrManager := sp.server.addrManager if !cfg.SimNet && !isInbound { - addrManager.SetServices(sp.NA(), msg.Services) + addrManager.SetServices(remoteAddr, msg.Services) } // Ignore peers that have a protcol version that is too old. The peer @@ -457,7 +458,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // connections and it believes itself to be close to the best known tip. if !cfg.DisableListen && sp.server.syncManager.IsCurrent() { // Get address that best matches. - lna := addrManager.GetBestLocalAddress(sp.NA()) + lna := addrManager.GetBestLocalAddress(remoteAddr) if addrmgr.IsRoutable(lna) { // Filter addresses the peer already knows about. addresses := []*wire.NetAddress{lna} @@ -474,7 +475,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej } // Mark the address as a known good address. - addrManager.Good(sp.NA()) + addrManager.Good(remoteAddr) } // Add the remote peer time as a sample for creating an offset against From 93fa8107236605f395e9b20870968c23c0b3aa39 Mon Sep 17 00:00:00 2001 From: Daniel McNally Date: Thu, 27 Sep 2018 12:41:34 -0400 Subject: [PATCH 0247/1056] sampleconfig: Remove floating grave accent --- sample-btcd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample-btcd.conf b/sample-btcd.conf index 4508e387a0..e2beb99cf8 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -106,7 +106,7 @@ ; Disable banning of misbehaving peers. ; nobanning=1 -; Maximum allowed ban score before disconnecting and banning misbehaving peers.` +; Maximum allowed ban score before disconnecting and banning misbehaving peers. ; banthreshold=100 ; How long to ban misbehaving peers. Valid time units are {s, m, h}. From 5e578f546f54614cd709a9a0e394f9bbb8316195 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 1 Oct 2018 13:40:30 +0200 Subject: [PATCH 0248/1056] peer log: add MsgCFHeaders and MsgGetCFHeaders string representation --- peer/log.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/peer/log.go b/peer/log.go index 7469fd86f0..71bebd0d51 100644 --- a/peer/log.go +++ b/peer/log.go @@ -199,6 +199,14 @@ func messageSummary(msg wire.Message) string { case *wire.MsgHeaders: return fmt.Sprintf("num %d", len(msg.Headers)) + case *wire.MsgGetCFHeaders: + return fmt.Sprintf("start_height=%d, stop_hash=%v", + msg.StartHeight, msg.StopHash) + + case *wire.MsgCFHeaders: + return fmt.Sprintf("stop_hash=%v, num_filter_hashes=%d", + msg.StopHash, len(msg.FilterHashes)) + case *wire.MsgReject: // Ensure the variable length strings don't contain any // characters which are even remotely dangerous such as HTML From 4b5ff8c68737bbcabe9c4841019f7447d024d2f0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 1 Oct 2018 13:55:43 +0200 Subject: [PATCH 0249/1056] connmanager: check Addr for nil --- connmgr/connmanager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go index 4acc0b2d03..2116934ab5 100644 --- a/connmgr/connmanager.go +++ b/connmgr/connmanager.go @@ -89,7 +89,7 @@ func (c *ConnReq) State() ConnState { // String returns a human-readable string for the connection request. func (c *ConnReq) String() string { - if c.Addr.String() == "" { + if c.Addr == nil || c.Addr.String() == "" { return fmt.Sprintf("reqid %d", atomic.LoadUint64(&c.id)) } return fmt.Sprintf("%s (reqid %d)", c.Addr, atomic.LoadUint64(&c.id)) From 3dcf298fed2d5fd65918dc560b3942b2aa0629e8 Mon Sep 17 00:00:00 2001 From: junderw Date: Fri, 23 Nov 2018 14:55:01 +0900 Subject: [PATCH 0250/1056] Fix one-off bug in signRFC6979 --- btcec/signature.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/btcec/signature.go b/btcec/signature.go index a4781b00f9..bddb228315 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -427,9 +427,7 @@ func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { k := nonceRFC6979(privkey.D, hash) inv := new(big.Int).ModInverse(k, N) r, _ := privkey.Curve.ScalarBaseMult(k.Bytes()) - if r.Cmp(N) == 1 { - r.Sub(r, N) - } + r.Mod(r, N) if r.Sign() == 0 { return nil, errors.New("calculated R is zero") From f5b60801a5a706984571bdc25cc228be793f61e0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Thu, 29 Nov 2018 15:13:37 +0100 Subject: [PATCH 0251/1056] integration/rpctest: make exec path compatible with modules With the use of go modules, the btcdPkgPath will no longer be `github.com/btcsuite/btcd`, but end with a version string (e.g. btcd@v0.0.0-20181129140220-beb77e89572a). This trips up build.ImportDir, which will return a ImportPath of ".", since this package cannot be found in the go path. There are probably several ways of fixing this, by clever string magic, but seems easiest to just hardcode the btcd package name. --- integration/rpctest/btcd.go | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/integration/rpctest/btcd.go b/integration/rpctest/btcd.go index 3c87519737..29642c845e 100644 --- a/integration/rpctest/btcd.go +++ b/integration/rpctest/btcd.go @@ -6,7 +6,6 @@ package rpctest import ( "fmt" - "go/build" "os/exec" "path/filepath" "runtime" @@ -44,24 +43,14 @@ func btcdExecutablePath() (string, error) { return "", err } - // Determine import path of this package. Not necessarily btcsuite/btcd if - // this is a forked repo. - _, rpctestDir, _, ok := runtime.Caller(1) - if !ok { - return "", fmt.Errorf("Cannot get path to btcd source code") - } - btcdPkgPath := filepath.Join(rpctestDir, "..", "..", "..") - btcdPkg, err := build.ImportDir(btcdPkgPath, build.FindOnly) - if err != nil { - return "", fmt.Errorf("Failed to build btcd: %v", err) - } - // Build btcd and output an executable in a static temp path. outputPath := filepath.Join(testDir, "btcd") if runtime.GOOS == "windows" { outputPath += ".exe" } - cmd := exec.Command("go", "build", "-o", outputPath, btcdPkg.ImportPath) + cmd := exec.Command( + "go", "build", "-o", outputPath, "github.com/btcsuite/btcd", + ) err = cmd.Run() if err != nil { return "", fmt.Errorf("Failed to build btcd: %v", err) From 852b39bd6dd9dbd8bcc91992020776cd8da6ab2c Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 29 Nov 2018 17:34:23 -0800 Subject: [PATCH 0252/1056] build: add go.mod and go.sum for 1.11 modules --- go.mod | 17 +++++++++++++++++ go.sum | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 go.mod create mode 100644 go.sum diff --git a/go.mod b/go.mod new file mode 100644 index 0000000000..747e1554dd --- /dev/null +++ b/go.mod @@ -0,0 +1,17 @@ +module github.com/btcsuite/btcd + +require ( + github.com/aead/siphash v1.0.1 + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f + github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a + github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd + github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd + github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 + github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 + github.com/btcsuite/winsvc v1.0.0 + github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 + github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 + github.com/jrick/logrotate v1.0.0 + github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 + golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000000..b387e2e21b --- /dev/null +++ b/go.sum @@ -0,0 +1,25 @@ +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE= +github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 h1:9lP3x0pW80sDI6t1UMSLA4to18W7R7imwAI/sWS9S8Q= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= From 97c3fea94c5b529f7b6034428c9364bbdbdd0647 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 29 Nov 2018 17:38:24 -0800 Subject: [PATCH 0253/1056] build: remove glide.lock and glide.yaml --- glide.lock | 64 ------------------------------------------------------ glide.yaml | 37 ------------------------------- 2 files changed, 101 deletions(-) delete mode 100644 glide.lock delete mode 100644 glide.yaml diff --git a/glide.lock b/glide.lock deleted file mode 100644 index 7d4dca901c..0000000000 --- a/glide.lock +++ /dev/null @@ -1,64 +0,0 @@ -hash: 4d4efdd452d746ef15b66d35caadb3cbd58bb299e9c1f5172e90b2f3f272863f -updated: 2018-08-23T22:38:49.421147894-07:00 -imports: -- name: github.com/aead/siphash - version: 83563a290f60225eb120d724600b9690c3fb536f -- name: github.com/btcsuite/btclog - version: 84c8d2346e9fc8c7b947e243b9c24e6df9fd206a -- name: github.com/btcsuite/btcutil - version: ab6388e0c60ae4834a1f57511e20c17b5f78be4b - subpackages: - - base58 - - bech32 - - bloom - - gcs - - gcs/builder - - hdkeychain -- name: github.com/btcsuite/go-socks - version: 4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f - subpackages: - - socks -- name: github.com/btcsuite/goleveldb - version: 7834afc9e8cd15233b6c3d97e12674a31ca24602 - subpackages: - - leveldb - - leveldb/cache - - leveldb/comparer - - leveldb/errors - - leveldb/filter - - leveldb/iterator - - leveldb/journal - - leveldb/memdb - - leveldb/opt - - leveldb/storage - - leveldb/table - - leveldb/util -- name: github.com/btcsuite/snappy-go - version: 0bdef8d067237991ddaa1bb6072a740bc40601ba -- name: github.com/btcsuite/websocket - version: 31079b6807923eb23992c421b114992b95131b55 -- name: github.com/btcsuite/winsvc - version: f8fb11f83f7e860e3769a08e6811d1b399a43722 - subpackages: - - eventlog - - mgr - - registry - - svc - - winapi -- name: github.com/davecgh/go-spew - version: ecdeabc65495df2dec95d7c4a4c3e021903035e5 - subpackages: - - spew -- name: github.com/jessevdk/go-flags - version: 1679536dcc895411a9f5848d9a0250be7856448c -- name: github.com/jrick/logrotate - version: a93b200c26cbae3bb09dd0dc2c7c7fe1468a034a - subpackages: - - rotator -- name: github.com/kkdai/bstream - version: f391b8402d23024e7c0f624b31267a89998fca95 -- name: golang.org/x/crypto - version: 9419663f5a44be8b34ca85f08abc5fe1be11f8a3 - subpackages: - - ripemd160 -testImports: [] diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index 32c5ed61d3..0000000000 --- a/glide.yaml +++ /dev/null @@ -1,37 +0,0 @@ -package: github.com/btcsuite/btcd -import: -- package: github.com/btcsuite/btclog -- package: github.com/btcsuite/btcutil - version: ab6388e0c60ae4834a1f57511e20c17b5f78be4b - subpackages: - - bloom - - hdkeychain -- package: github.com/btcsuite/go-socks - subpackages: - - socks -- package: golang.org/x/crypto - subpackages: - - ripemd160 -- package: github.com/btcsuite/goleveldb - subpackages: - - leveldb - - leveldb/comparer - - leveldb/errors - - leveldb/filter - - leveldb/iterator - - leveldb/opt - - leveldb/util -- package: github.com/btcsuite/websocket -- package: github.com/btcsuite/winsvc - subpackages: - - eventlog - - mgr - - svc -- package: github.com/davecgh/go-spew - subpackages: - - spew -- package: github.com/jessevdk/go-flags - version: 1679536dcc895411a9f5848d9a0250be7856448c -- package: github.com/jrick/logrotate -- package: github.com/aead/siphash - version: 83563a290f60225eb120d724600b9690c3fb536f From 2a9e4372c884f5f3236b2ea2c53447b4b7b5d6d8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 29 Nov 2018 17:45:40 -0800 Subject: [PATCH 0254/1056] goclean: update for go modules --- goclean.sh | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/goclean.sh b/goclean.sh index 548baf8bdb..6d0e0ca104 100755 --- a/goclean.sh +++ b/goclean.sh @@ -11,13 +11,6 @@ set -ex -# Make sure glide is installed and $GOPATH/bin is in your path. -# $ go get -u github.com/Masterminds/glide -# $ glide install -if [ ! -x "$(type -p glide)" ]; then - exit 1 -fi - # Make sure gometalinter is installed and $GOPATH/bin is in your path. # $ go get -v github.com/alecthomas/gometalinter" # $ gometalinter --install" @@ -25,7 +18,7 @@ if [ ! -x "$(type -p gometalinter.v2)" ]; then exit 1 fi -linter_targets=$(glide novendor) +linter_targets=$(go list ./...) # Automatic checks test -z "$(gometalinter.v2 -j 4 --disable-all \ @@ -35,4 +28,4 @@ test -z "$(gometalinter.v2 -j 4 --disable-all \ --enable=gosimple \ --enable=unconvert \ --deadline=10m $linter_targets 2>&1 | grep -v 'ALL_CAPS\|OP_' 2>&1 | tee /dev/stderr)" -go test -tags rpctest $linter_targets +GO111MODULE=on go test -tags="rpctest" $linter_targets From 2f3be2e3377206081ef9c1b81a9ab14e497b33d7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 29 Nov 2018 17:45:59 -0800 Subject: [PATCH 0255/1056] travis: remove glide, only build 1.11.x, use modules --- .travis.yml | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0d4fb385e5..f65821e926 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,19 @@ language: go +cache: + directories: + - $GOCACHE + - $GOPATH + - $GOPATH/pkg/mod + - $GOPATH/github.com/golang + - $GOPATH/gopkg.in/alecthomas go: - - "1.9.5" - - "1.10.1" + - "1.11.x" sudo: false install: - - GLIDE_TAG=v0.12.3 - - GLIDE_DOWNLOAD="https://github.com/Masterminds/glide/releases/download/$GLIDE_TAG/glide-$GLIDE_TAG-linux-amd64.tar.gz" - - curl -L $GLIDE_DOWNLOAD | tar -xvz - export PATH=$PATH:$PWD/linux-amd64/ - - glide install - - go install . ./cmd/... - - go get -u gopkg.in/alecthomas/gometalinter.v2 - - gometalinter.v2 --install + - GO111MODULE=on go install . ./cmd/... + - GO111MODULE=off go get -u gopkg.in/alecthomas/gometalinter.v2 + - GO111MODULE=off gometalinter.v2 --install script: - export PATH=$PATH:$HOME/gopath/bin - ./goclean.sh From 20388be19633af2c01d1bc9e7396eaeb5169b3d0 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 29 Nov 2018 17:53:41 -0800 Subject: [PATCH 0256/1056] README: require go1.11, document module installation --- README.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 72e73a5560..2b126a6503 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ which are both under active development. ## Requirements -[Go](http://golang.org) 1.8 or newer. +[Go](http://golang.org) 1.11 or newer. ## Installation @@ -63,11 +63,8 @@ recommended that `GOPATH` is set to a directory in your home directory such as - Run the following commands to obtain btcd, all dependencies, and install it: ```bash -$ go get -u github.com/Masterminds/glide -$ git clone https://github.com/btcsuite/btcd $GOPATH/src/github.com/btcsuite/btcd $ cd $GOPATH/src/github.com/btcsuite/btcd -$ glide install -$ go install . ./cmd/... +$ GO111MODULE=on go install -v . ./cmd/... ``` - btcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did @@ -86,8 +83,8 @@ Install a newer MSI ```bash $ cd $GOPATH/src/github.com/btcsuite/btcd -$ git pull && glide install -$ go install . ./cmd/... +$ git pull +$ GO111MODULE=on go install -v . ./cmd/... ``` ## Getting Started From 2ecf0619f266a1b0e0f8969ab378d31b644dfb0f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 30 Nov 2018 13:52:58 -0800 Subject: [PATCH 0257/1056] build: tidy go modules --- go.mod | 8 +++++--- go.sum | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 747e1554dd..cbc8248b84 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,19 @@ module github.com/btcsuite/btcd require ( - github.com/aead/siphash v1.0.1 + github.com/aead/siphash v1.0.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd - github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 + github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 github.com/btcsuite/winsvc v1.0.0 github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 github.com/jrick/logrotate v1.0.0 - github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 + github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect + github.com/onsi/ginkgo v1.7.0 // indirect + github.com/onsi/gomega v1.4.3 // indirect golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 ) diff --git a/go.sum b/go.sum index b387e2e21b..2391754298 100644 --- a/go.sum +++ b/go.sum @@ -12,14 +12,42 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAn github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 h1:9lP3x0pW80sDI6t1UMSLA4to18W7R7imwAI/sWS9S8Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 5bda5314ca9549a589e63d7b2e6104492a0d5328 Mon Sep 17 00:00:00 2001 From: Shuai Qi Date: Wed, 9 Jan 2019 12:07:09 +0800 Subject: [PATCH 0258/1056] netsync+blockchain: fix typos --- blockchain/mediantime.go | 2 +- netsync/manager.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blockchain/mediantime.go b/blockchain/mediantime.go index ac0689e285..f9c15a23ea 100644 --- a/blockchain/mediantime.go +++ b/blockchain/mediantime.go @@ -18,7 +18,7 @@ const ( maxAllowedOffsetSecs = 70 * 60 // 1 hour 10 minutes // similarTimeSecs is the number of seconds in either direction from the - // local clock that is used to determine that it is likley wrong and + // local clock that is used to determine that it is likely wrong and // hence to show a warning. similarTimeSecs = 5 * 60 // 5 minutes ) diff --git a/netsync/manager.go b/netsync/manager.go index d75dd96134..2a940edbff 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -592,14 +592,14 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) { } // Meta-data about the new block this peer is reporting. We use this - // below to update this peer's lastest block height and the heights of + // below to update this peer's latest block height and the heights of // other peers based on their last announced block hash. This allows us // to dynamically update the block heights of peers, avoiding stale // heights when looking for a new sync peer. Upon acceptance of a block // or recognition of an orphan, we also use this information to update // the block heights over other peers who's invs may have been ignored // if we are actively syncing while the chain is not yet current or - // who may have lost the lock announcment race. + // who may have lost the lock announcement race. var heightUpdate int32 var blkHashUpdate *chainhash.Hash From 0cec774a75abe6721803e6f8d3f6c5935efc3cd0 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 4 Dec 2018 10:19:58 -0800 Subject: [PATCH 0259/1056] txscript: add support to re-derive output's PkScript from input In this commit, we extend the txscript package to support re-deriving the PkScript of an output by looking at the input's signature script/witness attempting to spend it. As of this commit, the only supported types are P2SH, v0 P2WSH, and v0 P2WPKH. This will serve useful to detect when a particular script has been spent on-chain. A set of test vectors has also been added for the supported script types to ensure its correctness. --- txscript/pkscript.go | 260 ++++++++++++++++++++++ txscript/pkscript_test.go | 440 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 700 insertions(+) create mode 100644 txscript/pkscript.go create mode 100644 txscript/pkscript_test.go diff --git a/txscript/pkscript.go b/txscript/pkscript.go new file mode 100644 index 0000000000..e2823a8b53 --- /dev/null +++ b/txscript/pkscript.go @@ -0,0 +1,260 @@ +package txscript + +import ( + "crypto/sha256" + "errors" + "fmt" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" + "golang.org/x/crypto/ripemd160" +) + +const ( + // pubKeyHashSigScriptLen is the length of a signature script attempting + // to spend a P2PKH script. The only other possible length value is 107 + // bytes, due to the signature within it. This length is determined by + // the following: + // 0x47 or 0x48 (71 or 72 byte data push) | <71 or 72 byte sig> | + // 0x21 (33 byte data push) | <33 byte compressed pubkey> + pubKeyHashSigScriptLen = 106 + + // compressedPubKeyLen is the length in bytes of a compressed public + // key. + compressedPubKeyLen = 33 + + // pubKeyHashLen is the length of a P2PKH script. + pubKeyHashLen = 25 + + // witnessV0PubKeyHashLen is the length of a P2WPKH script. + witnessV0PubKeyHashLen = 22 + + // scriptHashLen is the length of a P2SH script. + scriptHashLen = 23 + + // witnessV0ScriptHashLen is the length of a P2WSH script. + witnessV0ScriptHashLen = 34 + + // maxLen is the maximum script length supported by ParsePkScript. + maxLen = witnessV0ScriptHashLen +) + +var ( + // ErrUnsupportedScriptType is an error returned when we attempt to + // parse/re-compute an output script into a PkScript struct. + ErrUnsupportedScriptType = errors.New("unsupported script type") +) + +// PkScript is a wrapper struct around a byte array, allowing it to be used +// as a map index. +type PkScript struct { + // class is the type of the script encoded within the byte array. This + // is used to determine the correct length of the script within the byte + // array. + class ScriptClass + + // script is the script contained within a byte array. If the script is + // smaller than the length of the byte array, it will be padded with 0s + // at the end. + script [maxLen]byte +} + +// ParsePkScript parses an output script into the PkScript struct. +// ErrUnsupportedScriptType is returned when attempting to parse an unsupported +// script type. +func ParsePkScript(pkScript []byte) (PkScript, error) { + var outputScript PkScript + scriptClass, _, _, err := ExtractPkScriptAddrs( + pkScript, &chaincfg.MainNetParams, + ) + if err != nil { + return outputScript, fmt.Errorf("unable to parse script type: "+ + "%v", err) + } + + if !isSupportedScriptType(scriptClass) { + return outputScript, ErrUnsupportedScriptType + } + + outputScript.class = scriptClass + copy(outputScript.script[:], pkScript) + + return outputScript, nil +} + +// isSupportedScriptType determines whether the script type is supported by the +// PkScript struct. +func isSupportedScriptType(class ScriptClass) bool { + switch class { + case PubKeyHashTy, WitnessV0PubKeyHashTy, ScriptHashTy, + WitnessV0ScriptHashTy: + return true + default: + return false + } +} + +// Class returns the script type. +func (s PkScript) Class() ScriptClass { + return s.class +} + +// Script returns the script as a byte slice without any padding. +func (s PkScript) Script() []byte { + var script []byte + + switch s.class { + case PubKeyHashTy: + script = make([]byte, pubKeyHashLen) + copy(script, s.script[:pubKeyHashLen]) + + case WitnessV0PubKeyHashTy: + script = make([]byte, witnessV0PubKeyHashLen) + copy(script, s.script[:witnessV0PubKeyHashLen]) + + case ScriptHashTy: + script = make([]byte, scriptHashLen) + copy(script, s.script[:scriptHashLen]) + + case WitnessV0ScriptHashTy: + script = make([]byte, witnessV0ScriptHashLen) + copy(script, s.script[:witnessV0ScriptHashLen]) + + default: + // Unsupported script type. + return nil + } + + return script +} + +// Address encodes the script into an address for the given chain. +func (s PkScript) Address(chainParams *chaincfg.Params) (btcutil.Address, error) { + _, addrs, _, err := ExtractPkScriptAddrs(s.Script(), chainParams) + if err != nil { + return nil, fmt.Errorf("unable to parse address: %v", err) + } + + return addrs[0], nil +} + +// String returns a hex-encoded string representation of the script. +func (s PkScript) String() string { + str, _ := DisasmString(s.Script()) + return str +} + +// ComputePkScript computes the pkScript of an transaction output by looking at +// the transaction input's signature script or witness. +// +// NOTE: Only P2PKH, P2SH, P2WSH, and P2WPKH redeem scripts are supported. +func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) { + var pkScript PkScript + + // Ensure that either an input's signature script or a witness was + // provided. + if len(sigScript) == 0 && len(witness) == 0 { + return pkScript, ErrUnsupportedScriptType + } + + // We'll start by checking the input's signature script, if provided. + switch { + // If a signature script is provided with a length long enough to + // represent a P2PKH script, then we'll attempt to parse the compressed + // public key from it. + case len(sigScript) == pubKeyHashSigScriptLen || + len(sigScript) == pubKeyHashSigScriptLen+1: + + // The public key should be found as the last part of the + // signature script. We'll attempt to parse it to ensure this is + // a P2PKH redeem script. + pubKey := sigScript[len(sigScript)-compressedPubKeyLen:] + if btcec.IsCompressedPubKey(pubKey) { + pubKeyHash := hash160(pubKey) + script, err := payToPubKeyHashScript(pubKeyHash) + if err != nil { + return pkScript, err + } + + pkScript.class = PubKeyHashTy + copy(pkScript.script[:], script) + return pkScript, nil + } + + // If it isn't, we'll assume it is a P2SH signature script. + fallthrough + + // If we failed to parse a compressed public key from the script in the + // case above, or if the script length is not that of a P2PKH one, and + // our redeem script is only composed of data pushed, we can assume it's + // a P2SH signature script. + case len(sigScript) > 0 && IsPushOnlyScript(sigScript): + // The redeem script will always be the last data push of the + // signature script, so we'll parse the script into opcodes to + // obtain it. + parsedOpcodes, err := parseScript(sigScript) + if err != nil { + return pkScript, err + } + redeemScript := parsedOpcodes[len(parsedOpcodes)-1].data + + scriptHash := hash160(redeemScript) + script, err := payToScriptHashScript(scriptHash) + if err != nil { + return pkScript, err + } + + pkScript.class = ScriptHashTy + copy(pkScript.script[:], script) + return pkScript, nil + + case len(sigScript) > 0: + return pkScript, ErrUnsupportedScriptType + } + + // If a witness was provided instead, we'll use the last item of the + // witness stack to determine the proper witness type. + lastWitnessItem := witness[len(witness)-1] + + switch { + // If the witness stack has a size of 2 and its last item is a + // compressed public key, then this is a P2WPKH witness. + case len(witness) == 2 && len(lastWitnessItem) == compressedPubKeyLen: + pubKeyHash := hash160(lastWitnessItem) + script, err := payToWitnessPubKeyHashScript(pubKeyHash) + if err != nil { + return pkScript, err + } + + pkScript.class = WitnessV0PubKeyHashTy + copy(pkScript.script[:], script) + return pkScript, nil + + // For any other witnesses, we'll assume it's a P2WSH witness. + default: + scriptHash := sha256.Sum256(lastWitnessItem) + script, err := payToWitnessScriptHashScript(scriptHash[:]) + if err != nil { + return pkScript, err + } + + pkScript.class = WitnessV0ScriptHashTy + copy(pkScript.script[:], script) + return pkScript, nil + } +} + +// hash160 returns the RIPEMD160 hash of the SHA-256 HASH of the given data. +func hash160(data []byte) []byte { + h := sha256.Sum256(data) + return ripemd160h(h[:]) +} + +// ripemd160h returns the RIPEMD160 hash of the given data. +func ripemd160h(data []byte) []byte { + h := ripemd160.New() + h.Write(data) + return h.Sum(nil) +} diff --git a/txscript/pkscript_test.go b/txscript/pkscript_test.go new file mode 100644 index 0000000000..dd8928271a --- /dev/null +++ b/txscript/pkscript_test.go @@ -0,0 +1,440 @@ +package txscript + +import ( + "bytes" + "testing" + + "github.com/btcsuite/btcd/wire" +) + +// TestParsePkScript ensures that the supported script types can be parsed +// correctly and re-derived into its raw byte representation. +func TestParsePkScript(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + pkScript []byte + valid bool + }{ + { + name: "empty output script", + pkScript: []byte{}, + valid: false, + }, + { + name: "valid P2PKH", + pkScript: []byte{ + // OP_DUP + 0x76, + // OP_HASH160 + 0xa9, + // OP_DATA_20 + 0x14, + // <20-byte pubkey hash> + 0xf0, 0x7a, 0xb8, 0xce, 0x72, 0xda, 0x4e, 0x76, + 0x0b, 0x74, 0x7d, 0x48, 0xd6, 0x65, 0xec, 0x96, + 0xad, 0xf0, 0x24, 0xf5, + // OP_EQUALVERIFY + 0x88, + // OP_CHECKSIG + 0xac, + }, + valid: true, + }, + // Invalid P2PKH - same as above but replaced OP_CHECKSIG with + // OP_CHECKSIGVERIFY. + { + name: "invalid P2PKH", + pkScript: []byte{ + // OP_DUP + 0x76, + // OP_HASH160 + 0xa9, + // OP_DATA_20 + 0x14, + // <20-byte pubkey hash> + 0xf0, 0x7a, 0xb8, 0xce, 0x72, 0xda, 0x4e, 0x76, + 0x0b, 0x74, 0x7d, 0x48, 0xd6, 0x65, 0xec, 0x96, + 0xad, 0xf0, 0x24, 0xf5, + // OP_EQUALVERIFY + 0x88, + // OP_CHECKSIGVERIFY + 0xad, + }, + valid: false, + }, + { + name: "valid P2SH", + pkScript: []byte{ + // OP_HASH160 + 0xA9, + // OP_DATA_20 + 0x14, + // <20-byte script hash> + 0xec, 0x6f, 0x7a, 0x5a, 0xa8, 0xf2, 0xb1, 0x0c, + 0xa5, 0x15, 0x04, 0x52, 0x3a, 0x60, 0xd4, 0x03, + 0x06, 0xf6, 0x96, 0xcd, + // OP_EQUAL + 0x87, + }, + valid: true, + }, + // Invalid P2SH - same as above but replaced OP_EQUAL with + // OP_EQUALVERIFY. + { + name: "invalid P2SH", + pkScript: []byte{ + // OP_HASH160 + 0xA9, + // OP_DATA_20 + 0x14, + // <20-byte script hash> + 0xec, 0x6f, 0x7a, 0x5a, 0xa8, 0xf2, 0xb1, 0x0c, + 0xa5, 0x15, 0x04, 0x52, 0x3a, 0x60, 0xd4, 0x03, + 0x06, 0xf6, 0x96, 0xcd, + // OP_EQUALVERIFY + 0x88, + }, + valid: false, + }, + { + name: "valid v0 P2WSH", + pkScript: []byte{ + // OP_0 + 0x00, + // OP_DATA_32 + 0x20, + // <32-byte script hash> + 0xec, 0x6f, 0x7a, 0x5a, 0xa8, 0xf2, 0xb1, 0x0c, + 0xa5, 0x15, 0x04, 0x52, 0x3a, 0x60, 0xd4, 0x03, + 0x06, 0xf6, 0x96, 0xcd, 0x06, 0xf6, 0x96, 0xcd, + 0x06, 0xf6, 0x96, 0xcd, 0x06, 0xf6, 0x96, 0xcd, + }, + valid: true, + }, + // Invalid v0 P2WSH - same as above but missing one byte. + { + name: "invalid v0 P2WSH", + pkScript: []byte{ + // OP_0 + 0x00, + // OP_DATA_32 + 0x20, + // <32-byte script hash> + 0xec, 0x6f, 0x7a, 0x5a, 0xa8, 0xf2, 0xb1, 0x0c, + 0xa5, 0x15, 0x04, 0x52, 0x3a, 0x60, 0xd4, 0x03, + 0x06, 0xf6, 0x96, 0xcd, 0x06, 0xf6, 0x96, 0xcd, + 0x06, 0xf6, 0x96, 0xcd, 0x06, 0xf6, 0x96, + }, + valid: false, + }, + { + name: "valid v0 P2WPKH", + pkScript: []byte{ + // OP_0 + 0x00, + // OP_DATA_20 + 0x14, + // <20-byte pubkey hash> + 0xec, 0x6f, 0x7a, 0x5a, 0xa8, 0xf2, 0xb1, 0x0c, + 0xa5, 0x15, 0x04, 0x52, 0x3a, 0x60, 0xd4, 0x03, + 0x06, 0xf6, 0x96, 0xcd, + }, + valid: true, + }, + // Invalid v0 P2WPKH - same as above but missing one byte. + { + name: "invalid v0 P2WPKH", + pkScript: []byte{ + // OP_0 + 0x00, + // OP_DATA_20 + 0x14, + // <20-byte pubkey hash> + 0xec, 0x6f, 0x7a, 0x5a, 0xa8, 0xf2, 0xb1, 0x0c, + 0xa5, 0x15, 0x04, 0x52, 0x3a, 0x60, 0xd4, 0x03, + 0x06, 0xf6, 0x96, + }, + valid: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + pkScript, err := ParsePkScript(test.pkScript) + switch { + case err != nil && test.valid: + t.Fatalf("unable to parse valid pkScript=%x: %v", + test.pkScript, err) + case err == nil && !test.valid: + t.Fatalf("successfully parsed invalid pkScript=%x", + test.pkScript) + } + + if !test.valid { + return + } + + if !bytes.Equal(pkScript.Script(), test.pkScript) { + t.Fatalf("expected to re-derive pkScript=%x, "+ + "got pkScript=%x", test.pkScript, + pkScript.Script()) + } + }) + } +} + +// TestComputePkScript ensures that we can correctly re-derive an output's +// pkScript by looking at the input's signature script/witness attempting to +// spend it. +func TestComputePkScript(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + sigScript []byte + witness wire.TxWitness + class ScriptClass + pkScript []byte + }{ + { + name: "empty sigScript and witness", + sigScript: nil, + witness: nil, + class: NonStandardTy, + pkScript: nil, + }, + { + name: "P2PKH sigScript", + sigScript: []byte{ + // OP_DATA_71, + 0x47, + // <71-byte sig> + 0x30, 0x44, 0x02, 0x20, 0x65, 0x92, 0xd8, 0x8e, + 0x1d, 0x0a, 0x4a, 0x3c, 0xc5, 0x9f, 0x92, 0xae, + 0xfe, 0x62, 0x54, 0x74, 0xa9, 0x4d, 0x13, 0xa5, + 0x9f, 0x84, 0x97, 0x78, 0xfc, 0xe7, 0xdf, 0x4b, + 0xe0, 0xc2, 0x28, 0xd8, 0x02, 0x20, 0x2d, 0xea, + 0x36, 0x96, 0x19, 0x1f, 0xb7, 0x00, 0xc5, 0xa7, + 0x7e, 0x22, 0xd9, 0xfb, 0x6b, 0x42, 0x67, 0x42, + 0xa4, 0x2c, 0xac, 0xdb, 0x74, 0xa2, 0x7c, 0x43, + 0xcd, 0x89, 0xa0, 0xf9, 0x44, 0x54, 0x01, + // OP_DATA_33 + 0x21, + // <33-byte compressed pubkey> + 0x02, 0x7d, 0x56, 0x12, 0x09, 0x75, 0x31, 0xc2, + 0x17, 0xfd, 0xd4, 0xd2, 0xe1, 0x7a, 0x35, 0x4b, + 0x17, 0xf2, 0x7a, 0xef, 0x30, 0x9f, 0xb2, 0x7f, + 0x1f, 0x1f, 0x7b, 0x73, 0x7d, 0x9a, 0x24, 0x49, + 0x90, + }, + witness: nil, + class: PubKeyHashTy, + pkScript: []byte{ + // OP_DUP + 0x76, + // OP_HASH160 + 0xa9, + // OP_DATA_20 + 0x14, + // <20-byte pubkey hash> + 0xf0, 0x7a, 0xb8, 0xce, 0x72, 0xda, 0x4e, 0x76, + 0x0b, 0x74, 0x7d, 0x48, 0xd6, 0x65, 0xec, 0x96, + 0xad, 0xf0, 0x24, 0xf5, + // OP_EQUALVERIFY + 0x88, + // OP_CHECKSIG + 0xac, + }, + }, + { + name: "NP2WPKH sigScript", + // Since this is a NP2PKH output, the sigScript is a + // data push of a serialized v0 P2WPKH script. + sigScript: []byte{ + // OP_DATA_16 + 0x16, + // <22-byte redeem script> + 0x00, 0x14, 0x1d, 0x7c, 0xd6, 0xc7, 0x5c, 0x2e, + 0x86, 0xf4, 0xcb, 0xf9, 0x8e, 0xae, 0xd2, 0x21, + 0xb3, 0x0b, 0xd9, 0xa0, 0xb9, 0x28, + }, + // NP2PKH outputs include a witness, but it is not + // needed to reconstruct the pkScript. + witness: nil, + class: ScriptHashTy, + pkScript: []byte{ + // OP_HASH160 + 0xa9, + // OP_DATA_20 + 0x14, + // <20-byte script hash> + 0x90, 0x1c, 0x86, 0x94, 0xc0, 0x3f, 0xaf, 0xd5, + 0x52, 0x28, 0x10, 0xe0, 0x33, 0x0f, 0x26, 0xe6, + 0x7a, 0x85, 0x33, 0xcd, + // OP_EQUAL + 0x87, + }, + }, + { + name: "P2SH sigScript", + sigScript: []byte{ + 0x00, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, + 0xe6, 0xb6, 0x14, 0x1b, 0xa7, 0x24, 0x4f, 0x54, + 0x62, 0xb6, 0x2a, 0x3b, 0x27, 0x59, 0xde, 0xe4, + 0x46, 0x76, 0x19, 0x4e, 0x6c, 0x56, 0x8d, 0x5b, + 0x1c, 0xda, 0x96, 0x2d, 0x4f, 0x6d, 0x79, 0x02, + 0x21, 0x00, 0xa6, 0x6f, 0x60, 0x34, 0x46, 0x09, + 0x0a, 0x22, 0x3c, 0xec, 0x30, 0x33, 0xd9, 0x86, + 0x24, 0xd2, 0x73, 0xa8, 0x91, 0x55, 0xa5, 0xe6, + 0x96, 0x66, 0x0b, 0x6a, 0x50, 0xa3, 0x46, 0x45, + 0xbb, 0x67, 0x01, 0x48, 0x30, 0x45, 0x02, 0x21, + 0x00, 0xe2, 0x73, 0x49, 0xdb, 0x93, 0x82, 0xe1, + 0xf8, 0x8d, 0xae, 0x97, 0x5c, 0x71, 0x19, 0xb7, + 0x79, 0xb6, 0xda, 0x43, 0xa8, 0x4f, 0x16, 0x05, + 0x87, 0x11, 0x9f, 0xe8, 0x12, 0x1d, 0x85, 0xae, + 0xee, 0x02, 0x20, 0x6f, 0x23, 0x2d, 0x0a, 0x7b, + 0x4b, 0xfa, 0xcd, 0x56, 0xa0, 0x72, 0xcc, 0x2a, + 0x44, 0x81, 0x31, 0xd1, 0x0d, 0x73, 0x35, 0xf9, + 0xa7, 0x54, 0x8b, 0xee, 0x1f, 0x70, 0xc5, 0x71, + 0x0b, 0x37, 0x9e, 0x01, 0x47, 0x52, 0x21, 0x03, + 0xab, 0x11, 0x5d, 0xa6, 0xdf, 0x4f, 0x54, 0x0b, + 0xd6, 0xc9, 0xc4, 0xbe, 0x5f, 0xdd, 0xcc, 0x24, + 0x58, 0x8e, 0x7c, 0x2c, 0xaf, 0x13, 0x82, 0x28, + 0xdd, 0x0f, 0xce, 0x29, 0xfd, 0x65, 0xb8, 0x7c, + 0x21, 0x02, 0x15, 0xe8, 0xb7, 0xbf, 0xfe, 0x8d, + 0x9b, 0xbd, 0x45, 0x81, 0xf9, 0xc3, 0xb6, 0xf1, + 0x6d, 0x67, 0x08, 0x36, 0xc3, 0x0b, 0xb2, 0xe0, + 0x3e, 0xfd, 0x9d, 0x41, 0x03, 0xb5, 0x59, 0xeb, + 0x67, 0xcd, 0x52, 0xae, + }, + witness: nil, + class: ScriptHashTy, + pkScript: []byte{ + // OP_HASH160 + 0xA9, + // OP_DATA_20 + 0x14, + // <20-byte script hash> + 0x12, 0xd6, 0x9c, 0xd3, 0x38, 0xa3, 0x8d, 0x0d, + 0x77, 0x83, 0xcf, 0x22, 0x64, 0x97, 0x63, 0x3d, + 0x3c, 0x20, 0x79, 0xea, + // OP_EQUAL + 0x87, + }, + }, + // Invalid P2SH (non push-data only script). + { + name: "invalid P2SH sigScript", + sigScript: []byte{0x6b, 0x65, 0x6b}, // kek + witness: nil, + class: NonStandardTy, + pkScript: nil, + }, + { + name: "P2WSH witness", + sigScript: nil, + witness: [][]byte{ + []byte{}, + // Witness script. + []byte{ + 0x21, 0x03, 0x82, 0x62, 0xa6, 0xc6, + 0xce, 0xc9, 0x3c, 0x2d, 0x3e, 0xcd, + 0x6c, 0x60, 0x72, 0xef, 0xea, 0x86, + 0xd0, 0x2f, 0xf8, 0xe3, 0x32, 0x8b, + 0xbd, 0x02, 0x42, 0xb2, 0x0a, 0xf3, + 0x42, 0x59, 0x90, 0xac, 0xac, + }, + }, + class: WitnessV0ScriptHashTy, + pkScript: []byte{ + // OP_0 + 0x00, + // OP_DATA_32 + 0x20, + // <32-byte script hash> + 0x01, 0xd5, 0xd9, 0x2e, 0xff, 0xa6, 0xff, 0xba, + 0x3e, 0xfa, 0x37, 0x9f, 0x98, 0x30, 0xd0, 0xf7, + 0x56, 0x18, 0xb1, 0x33, 0x93, 0x82, 0x71, 0x52, + 0xd2, 0x6e, 0x43, 0x09, 0x00, 0x0e, 0x88, 0xb1, + }, + }, + { + name: "P2WPKH witness", + sigScript: nil, + witness: [][]byte{ + // Signature is not needed to re-derive the + // pkScript. + []byte{}, + // Compressed pubkey. + []byte{ + 0x03, 0x82, 0x62, 0xa6, 0xc6, 0xce, + 0xc9, 0x3c, 0x2d, 0x3e, 0xcd, 0x6c, + 0x60, 0x72, 0xef, 0xea, 0x86, 0xd0, + 0x2f, 0xf8, 0xe3, 0x32, 0x8b, 0xbd, + 0x02, 0x42, 0xb2, 0x0a, 0xf3, 0x42, + 0x59, 0x90, 0xac, + }, + }, + class: WitnessV0PubKeyHashTy, + pkScript: []byte{ + // OP_0 + 0x00, + // OP_DATA_20 + 0x14, + // <20-byte pubkey hash> + 0x1d, 0x7c, 0xd6, 0xc7, 0x5c, 0x2e, 0x86, 0xf4, + 0xcb, 0xf9, 0x8e, 0xae, 0xd2, 0x21, 0xb3, 0x0b, + 0xd9, 0xa0, 0xb9, 0x28, + }, + }, + // Invalid v0 P2WPKH - same as above but missing a byte on the + // public key. + { + name: "invalid P2WPKH witness", + sigScript: nil, + witness: [][]byte{ + // Signature is not needed to re-derive the + // pkScript. + []byte{}, + // Malformed compressed pubkey. + []byte{ + 0x03, 0x82, 0x62, 0xa6, 0xc6, 0xce, + 0xc9, 0x3c, 0x2d, 0x3e, 0xcd, 0x6c, + 0x60, 0x72, 0xef, 0xea, 0x86, 0xd0, + 0x2f, 0xf8, 0xe3, 0x32, 0x8b, 0xbd, + 0x02, 0x42, 0xb2, 0x0a, 0xf3, 0x42, + 0x59, 0x90, + }, + }, + class: WitnessV0PubKeyHashTy, + pkScript: nil, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + valid := test.pkScript != nil + pkScript, err := ComputePkScript( + test.sigScript, test.witness, + ) + if err != nil && valid { + t.Fatalf("unable to compute pkScript: %v", err) + } + + if !valid { + return + } + + if pkScript.Class() != test.class { + t.Fatalf("expected pkScript of type %v, got %v", + test.class, pkScript.Class()) + } + if !bytes.Equal(pkScript.Script(), test.pkScript) { + t.Fatalf("expected pkScript=%x, got pkScript=%x", + test.pkScript, pkScript.Script()) + } + }) + } +} From be2b6dc98ad36055fc8d0aadc5c09d628a5d285f Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 4 Dec 2018 10:21:56 -0800 Subject: [PATCH 0260/1056] rpcwebsocket: modify rescanKeys to take addresses as strings In this commit, we modify the rescanKeys struct, which contains the relevant keys that should be matched when rescanning the chain, to take addresses in their string representation. This ends up simplifying a lot of the logic as we no longer have to special-case specific script types. --- rpcwebsocket.go | 117 ++++-------------------------------------------- 1 file changed, 8 insertions(+), 109 deletions(-) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 8b9d06b445..1a758ffb55 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -20,8 +20,6 @@ import ( "sync" "time" - "golang.org/x/crypto/ripemd160" - "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg" @@ -31,6 +29,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/websocket" + "golang.org/x/crypto/ripemd160" ) const ( @@ -1978,12 +1977,8 @@ func deserializeOutpoints(serializedOuts []btcjson.OutPoint) ([]*wire.OutPoint, } type rescanKeys struct { - fallbacks map[string]struct{} - pubKeyHashes map[[ripemd160.Size]byte]struct{} - scriptHashes map[[ripemd160.Size]byte]struct{} - compressedPubKeys map[[33]byte]struct{} - uncompressedPubKeys map[[65]byte]struct{} - unspent map[wire.OutPoint]struct{} + addrs map[string]struct{} + unspent map[wire.OutPoint]struct{} } // unspentSlice returns a slice of currently-unspent outpoints for the rescan @@ -2052,57 +2047,8 @@ func rescanBlock(wsc *wsClient, lookups *rescanKeys, blk *btcutil.Block) { txout.PkScript, wsc.server.cfg.ChainParams) for _, addr := range addrs { - switch a := addr.(type) { - case *btcutil.AddressPubKeyHash: - if _, ok := lookups.pubKeyHashes[*a.Hash160()]; !ok { - continue - } - - case *btcutil.AddressScriptHash: - if _, ok := lookups.scriptHashes[*a.Hash160()]; !ok { - continue - } - - case *btcutil.AddressPubKey: - found := false - switch sa := a.ScriptAddress(); len(sa) { - case 33: // Compressed - var key [33]byte - copy(key[:], sa) - if _, ok := lookups.compressedPubKeys[key]; ok { - found = true - } - - case 65: // Uncompressed - var key [65]byte - copy(key[:], sa) - if _, ok := lookups.uncompressedPubKeys[key]; ok { - found = true - } - - default: - rpcsLog.Warnf("Skipping rescanned pubkey of unknown "+ - "serialized length %d", len(sa)) - continue - } - - // If the transaction output pays to the pubkey of - // a rescanned P2PKH address, include it as well. - if !found { - pkh := a.AddressPubKeyHash() - if _, ok := lookups.pubKeyHashes[*pkh.Hash160()]; !ok { - continue - } - } - - default: - // A new address type must have been added. Encode as a - // payment address string and check the fallback map. - addrStr := addr.EncodeAddress() - _, ok := lookups.fallbacks[addrStr] - if !ok { - continue - } + if _, ok := lookups.addrs[addr.String()]; !ok { + continue } outpoint := wire.OutPoint{ @@ -2353,58 +2299,11 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) { // Build lookup maps. lookups := rescanKeys{ - fallbacks: map[string]struct{}{}, - pubKeyHashes: map[[ripemd160.Size]byte]struct{}{}, - scriptHashes: map[[ripemd160.Size]byte]struct{}{}, - compressedPubKeys: map[[33]byte]struct{}{}, - uncompressedPubKeys: map[[65]byte]struct{}{}, - unspent: map[wire.OutPoint]struct{}{}, + addrs: map[string]struct{}{}, + unspent: map[wire.OutPoint]struct{}{}, } - var compressedPubkey [33]byte - var uncompressedPubkey [65]byte - params := wsc.server.cfg.ChainParams for _, addrStr := range cmd.Addresses { - addr, err := btcutil.DecodeAddress(addrStr, params) - if err != nil { - jsonErr := btcjson.RPCError{ - Code: btcjson.ErrRPCInvalidAddressOrKey, - Message: "Rescan address " + addrStr + ": " + - err.Error(), - } - return nil, &jsonErr - } - switch a := addr.(type) { - case *btcutil.AddressPubKeyHash: - lookups.pubKeyHashes[*a.Hash160()] = struct{}{} - - case *btcutil.AddressScriptHash: - lookups.scriptHashes[*a.Hash160()] = struct{}{} - - case *btcutil.AddressPubKey: - pubkeyBytes := a.ScriptAddress() - switch len(pubkeyBytes) { - case 33: // Compressed - copy(compressedPubkey[:], pubkeyBytes) - lookups.compressedPubKeys[compressedPubkey] = struct{}{} - - case 65: // Uncompressed - copy(uncompressedPubkey[:], pubkeyBytes) - lookups.uncompressedPubKeys[uncompressedPubkey] = struct{}{} - - default: - jsonErr := btcjson.RPCError{ - Code: btcjson.ErrRPCInvalidAddressOrKey, - Message: "Pubkey " + addrStr + " is of unknown length", - } - return nil, &jsonErr - } - - default: - // A new address type must have been added. Use encoded - // payment address string as a fallback until a fast path - // is added. - lookups.fallbacks[addrStr] = struct{}{} - } + lookups.addrs[addrStr] = struct{}{} } for _, outpoint := range outpoints { lookups.unspent[*outpoint] = struct{}{} From f6eae62a77102a618a731e04e0f219b1feccfbdb Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 4 Dec 2018 10:23:33 -0800 Subject: [PATCH 0261/1056] rpcwebsocket: detect and notify spend of script In this commit, we modify the rescanBlock method to also determine whether a script (encoded as an address in its rescanKeys) has been spent. Upon detecting a spend, a btcjson.RedeemingTxNtfn is sent to the client who requested it. --- rpcwebsocket.go | 68 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 1a758ffb55..eddac5ab06 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -2015,7 +2015,28 @@ func rescanBlock(wsc *wsClient, lookups *rescanKeys, blk *btcutil.Block) { spentNotified := false recvNotified := false + // notifySpend is a closure we'll use when we first detect that + // a transactions spends an outpoint/script in our filter list. + notifySpend := func() error { + if txHex == "" { + txHex = txHexString(tx.MsgTx()) + } + marshalledJSON, err := newRedeemingTxNotification( + txHex, tx.Index(), blk, + ) + if err != nil { + return fmt.Errorf("unable to marshal "+ + "btcjson.RedeeminTxNtfn: %v", err) + } + + return wsc.QueueNotification(marshalledJSON) + } + + // We'll start by iterating over the transaction's inputs to + // determine if it spends an outpoint/script in our filter list. for _, txin := range tx.MsgTx().TxIn { + // If it spends an outpoint, we'll dispatch a spend + // notification for the transaction. if _, ok := lookups.unspent[txin.PreviousOutPoint]; ok { delete(lookups.unspent, txin.PreviousOutPoint) @@ -2023,21 +2044,58 @@ func rescanBlock(wsc *wsClient, lookups *rescanKeys, blk *btcutil.Block) { continue } - if txHex == "" { - txHex = txHexString(tx.MsgTx()) + err := notifySpend() + + // Stop the rescan early if the websocket client + // disconnected. + if err == ErrClientQuit { + return } - marshalledJSON, err := newRedeemingTxNotification(txHex, tx.Index(), blk) if err != nil { - rpcsLog.Errorf("Failed to marshal redeemingtx notification: %v", err) + rpcsLog.Errorf("Unable to notify "+ + "redeeming transaction %v: %v", + tx.Hash(), err) continue } - err = wsc.QueueNotification(marshalledJSON) + spentNotified = true + } + + // We'll also recompute the pkScript the input is + // attempting to spend to determine whether it is + // relevant to us. + pkScript, err := txscript.ComputePkScript( + txin.SignatureScript, txin.Witness, + ) + if err != nil { + continue + } + addr, err := pkScript.Address(wsc.server.cfg.ChainParams) + if err != nil { + continue + } + + // If it is, we'll also dispatch a spend notification + // for this transaction if we haven't already. + if _, ok := lookups.addrs[addr.String()]; ok { + if spentNotified { + continue + } + + err := notifySpend() + // Stop the rescan early if the websocket client // disconnected. if err == ErrClientQuit { return } + if err != nil { + rpcsLog.Errorf("Unable to notify "+ + "redeeming transaction %v: %v", + tx.Hash(), err) + continue + } + spentNotified = true } } From 18a6867124c825d469482ddfdef7ca044d2328d3 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Wed, 6 Feb 2019 13:29:58 -0800 Subject: [PATCH 0262/1056] addrmgr/knownaddress: expose an address' service bits --- addrmgr/knownaddress.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/addrmgr/knownaddress.go b/addrmgr/knownaddress.go index 4a8da83e36..15469f374e 100644 --- a/addrmgr/knownaddress.go +++ b/addrmgr/knownaddress.go @@ -33,6 +33,11 @@ func (ka *KnownAddress) LastAttempt() time.Time { return ka.lastattempt } +// Services returns the services supported by the peer with the known address. +func (ka *KnownAddress) Services() wire.ServiceFlag { + return ka.na.Services +} + // chance returns the selection probability for a known address. The priority // depends upon how recently the address has been seen, how recently it was last // attempted and how often attempts to connect to it have failed. From 10f17a8bb0daa8a5883b49f410c7bacf71e91d29 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Wed, 6 Feb 2019 13:31:49 -0800 Subject: [PATCH 0263/1056] addrmgr: add AddrManager serialization test --- addrmgr/addrmanager.go | 37 +++++---- addrmgr/addrmanager_internal_test.go | 119 +++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 15 deletions(-) create mode 100644 addrmgr/addrmanager_internal_test.go diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index fc6930688b..89569aa09f 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -635,21 +635,9 @@ func (a *AddrManager) NeedMoreAddresses() bool { // AddressCache returns the current address cache. It must be treated as // read-only (but since it is a copy now, this is not as dangerous). func (a *AddrManager) AddressCache() []*wire.NetAddress { - a.mtx.Lock() - defer a.mtx.Unlock() - - addrIndexLen := len(a.addrIndex) - if addrIndexLen == 0 { - return nil - } - - allAddr := make([]*wire.NetAddress, 0, addrIndexLen) - // Iteration order is undefined here, but we randomise it anyway. - for _, v := range a.addrIndex { - allAddr = append(allAddr, v.na) - } + allAddr := a.getAddresses() - numAddresses := addrIndexLen * getAddrPercent / 100 + numAddresses := len(allAddr) * getAddrPercent / 100 if numAddresses > getAddrMax { numAddresses = getAddrMax } @@ -658,7 +646,7 @@ func (a *AddrManager) AddressCache() []*wire.NetAddress { // `numAddresses' since we are throwing the rest. for i := 0; i < numAddresses; i++ { // pick a number between current index and the end - j := rand.Intn(addrIndexLen-i) + i + j := rand.Intn(len(allAddr)-i) + i allAddr[i], allAddr[j] = allAddr[j], allAddr[i] } @@ -666,6 +654,25 @@ func (a *AddrManager) AddressCache() []*wire.NetAddress { return allAddr[0:numAddresses] } +// getAddresses returns all of the addresses currently found within the +// manager's address cache. +func (a *AddrManager) getAddresses() []*wire.NetAddress { + a.mtx.Lock() + defer a.mtx.Unlock() + + addrIndexLen := len(a.addrIndex) + if addrIndexLen == 0 { + return nil + } + + addrs := make([]*wire.NetAddress, 0, addrIndexLen) + for _, v := range a.addrIndex { + addrs = append(addrs, v.na) + } + + return addrs +} + // reset resets the address manager by reinitialising the random source // and allocating fresh empty bucket storage. func (a *AddrManager) reset() { diff --git a/addrmgr/addrmanager_internal_test.go b/addrmgr/addrmanager_internal_test.go new file mode 100644 index 0000000000..82036d379c --- /dev/null +++ b/addrmgr/addrmanager_internal_test.go @@ -0,0 +1,119 @@ +package addrmgr + +import ( + "io/ioutil" + "math/rand" + "net" + "os" + "testing" + + "github.com/btcsuite/btcd/wire" +) + +// randAddr generates a *wire.NetAddress backed by a random IPv4/IPv6 address. +func randAddr(t *testing.T) *wire.NetAddress { + t.Helper() + + ipv4 := rand.Intn(2) == 0 + var ip net.IP + if ipv4 { + var b [4]byte + if _, err := rand.Read(b[:]); err != nil { + t.Fatal(err) + } + ip = b[:] + } else { + var b [16]byte + if _, err := rand.Read(b[:]); err != nil { + t.Fatal(err) + } + ip = b[:] + } + + return &wire.NetAddress{ + Services: wire.ServiceFlag(rand.Uint64()), + IP: ip, + Port: uint16(rand.Uint32()), + } +} + +// assertAddr ensures that the two addresses match. The timestamp is not +// checked as it does not affect uniquely identifying a specific address. +func assertAddr(t *testing.T, got, expected *wire.NetAddress) { + if got.Services != expected.Services { + t.Fatalf("expected address services %v, got %v", + expected.Services, got.Services) + } + if !got.IP.Equal(expected.IP) { + t.Fatalf("expected address IP %v, got %v", expected.IP, got.IP) + } + if got.Port != expected.Port { + t.Fatalf("expected address port %d, got %d", expected.Port, + got.Port) + } +} + +// assertAddrs ensures that the manager's address cache matches the given +// expected addresses. +func assertAddrs(t *testing.T, addrMgr *AddrManager, + expectedAddrs map[string]*wire.NetAddress) { + + t.Helper() + + addrs := addrMgr.getAddresses() + + if len(addrs) != len(expectedAddrs) { + t.Fatalf("expected to find %d addresses, found %d", + len(expectedAddrs), len(addrs)) + } + + for _, addr := range addrs { + addrStr := NetAddressKey(addr) + expectedAddr, ok := expectedAddrs[addrStr] + if !ok { + t.Fatalf("expected to find address %v", addrStr) + } + + assertAddr(t, addr, expectedAddr) + } +} + +// TestAddrManagerSerialization ensures that we can properly serialize and +// deserialize the manager's current address cache. +func TestAddrManagerSerialization(t *testing.T) { + t.Parallel() + + // We'll start by creating our address manager backed by a temporary + // directory. + tempDir, err := ioutil.TempDir("", "addrmgr") + if err != nil { + t.Fatalf("unable to create temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + + addrMgr := New(tempDir, nil) + + // We'll be adding 5 random addresses to the manager. + const numAddrs = 5 + + expectedAddrs := make(map[string]*wire.NetAddress, numAddrs) + for i := 0; i < numAddrs; i++ { + addr := randAddr(t) + expectedAddrs[NetAddressKey(addr)] = addr + addrMgr.AddAddress(addr, randAddr(t)) + } + + // Now that the addresses have been added, we should be able to retrieve + // them. + assertAddrs(t, addrMgr, expectedAddrs) + + // Then, we'll persist these addresses to disk and restart the address + // manager. + addrMgr.savePeers() + addrMgr = New(tempDir, nil) + + // Finally, we'll read all of the addresses from disk and ensure they + // match as expected. + addrMgr.loadPeers() + assertAddrs(t, addrMgr, expectedAddrs) +} From bcd50ea838c984bb1e4756f5b1ed0021b52e9dd2 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Wed, 6 Feb 2019 13:32:52 -0800 Subject: [PATCH 0264/1056] addrmgr: store address' supported service bits In this commit, we update the serialized version of the AddressManager to also store each address' service bits. This allows an address' service bits to be properly set when read from disk, which allows external callers to reliably filter out addresses which do not support their required services. Since the service bits were not previously stored, the serialization version needed to be bumped. A test has been added to test the behavior of upgrading from version 1 to 2. --- addrmgr/addrmanager.go | 45 ++++++++++++++--- addrmgr/addrmanager_internal_test.go | 75 ++++++++++++++++++++++++++++ addrmgr/addrmanager_test.go | 4 +- 3 files changed, 114 insertions(+), 10 deletions(-) diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index 89569aa09f..a8a8fb3338 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -46,6 +46,7 @@ type AddrManager struct { nNew int lamtx sync.Mutex localAddresses map[string]*localAddress + version int } type serializedKnownAddress struct { @@ -55,6 +56,8 @@ type serializedKnownAddress struct { TimeStamp int64 LastAttempt int64 LastSuccess int64 + Services wire.ServiceFlag + SrcServices wire.ServiceFlag // no refcount or tried, that is available from context. } @@ -155,7 +158,7 @@ const ( getAddrPercent = 23 // serialisationVersion is the current version of the on-disk format. - serialisationVersion = 1 + serialisationVersion = 2 ) // updateAddress is a helper function to either update an address already known @@ -362,7 +365,7 @@ func (a *AddrManager) savePeers() { // First we make a serialisable datastructure so we can encode it to // json. sam := new(serializedAddrManager) - sam.Version = serialisationVersion + sam.Version = a.version copy(sam.Key[:], a.key[:]) sam.Addresses = make([]*serializedKnownAddress, len(a.addrIndex)) @@ -375,6 +378,10 @@ func (a *AddrManager) savePeers() { ska.Attempts = v.attempts ska.LastAttempt = v.lastattempt.Unix() ska.LastSuccess = v.lastsuccess.Unix() + if a.version > 1 { + ska.Services = v.na.Services + ska.SrcServices = v.srcAddr.Services + } // Tried and refs are implicit in the rest of the structure // and will be worked out from context on unserialisation. sam.Addresses[i] = ska @@ -451,24 +458,43 @@ func (a *AddrManager) deserializePeers(filePath string) error { return fmt.Errorf("error reading %s: %v", filePath, err) } - if sam.Version != serialisationVersion { + // Since decoding JSON is backwards compatible (i.e., only decodes + // fields it understands), we'll only return an error upon seeing a + // version past our latest supported version. + if sam.Version > serialisationVersion { return fmt.Errorf("unknown version %v in serialized "+ "addrmanager", sam.Version) } + copy(a.key[:], sam.Key[:]) for _, v := range sam.Addresses { ka := new(KnownAddress) - ka.na, err = a.DeserializeNetAddress(v.Addr) + + // The first version of the serialized address manager was not + // aware of the service bits associated with this address, so + // we'll assign a default of SFNodeNetwork to it. + if sam.Version == 1 { + v.Services = wire.SFNodeNetwork + } + ka.na, err = a.DeserializeNetAddress(v.Addr, v.Services) if err != nil { return fmt.Errorf("failed to deserialize netaddress "+ "%s: %v", v.Addr, err) } - ka.srcAddr, err = a.DeserializeNetAddress(v.Src) + + // The first version of the serialized address manager was not + // aware of the service bits associated with the source address, + // so we'll assign a default of SFNodeNetwork to it. + if sam.Version == 1 { + v.SrcServices = wire.SFNodeNetwork + } + ka.srcAddr, err = a.DeserializeNetAddress(v.Src, v.SrcServices) if err != nil { return fmt.Errorf("failed to deserialize netaddress "+ "%s: %v", v.Src, err) } + ka.attempts = v.Attempts ka.lastattempt = time.Unix(v.LastAttempt, 0) ka.lastsuccess = time.Unix(v.LastSuccess, 0) @@ -520,8 +546,10 @@ func (a *AddrManager) deserializePeers(filePath string) error { return nil } -// DeserializeNetAddress converts a given address string to a *wire.NetAddress -func (a *AddrManager) DeserializeNetAddress(addr string) (*wire.NetAddress, error) { +// DeserializeNetAddress converts a given address string to a *wire.NetAddress. +func (a *AddrManager) DeserializeNetAddress(addr string, + services wire.ServiceFlag) (*wire.NetAddress, error) { + host, portStr, err := net.SplitHostPort(addr) if err != nil { return nil, err @@ -531,7 +559,7 @@ func (a *AddrManager) DeserializeNetAddress(addr string) (*wire.NetAddress, erro return nil, err } - return a.HostToNetAddress(host, uint16(port), wire.SFNodeNetwork) + return a.HostToNetAddress(host, uint16(port), services) } // Start begins the core address handler which manages a pool of known @@ -1116,6 +1144,7 @@ func New(dataDir string, lookupFunc func(string) ([]net.IP, error)) *AddrManager rand: rand.New(rand.NewSource(time.Now().UnixNano())), quit: make(chan struct{}), localAddresses: make(map[string]*localAddress), + version: serialisationVersion, } am.reset() return &am diff --git a/addrmgr/addrmanager_internal_test.go b/addrmgr/addrmanager_internal_test.go index 82036d379c..1c19dceb18 100644 --- a/addrmgr/addrmanager_internal_test.go +++ b/addrmgr/addrmanager_internal_test.go @@ -117,3 +117,78 @@ func TestAddrManagerSerialization(t *testing.T) { addrMgr.loadPeers() assertAddrs(t, addrMgr, expectedAddrs) } + +// TestAddrManagerV1ToV2 ensures that we can properly upgrade the serialized +// version of the address manager from v1 to v2. +func TestAddrManagerV1ToV2(t *testing.T) { + t.Parallel() + + // We'll start by creating our address manager backed by a temporary + // directory. + tempDir, err := ioutil.TempDir("", "addrmgr") + if err != nil { + t.Fatalf("unable to create temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + + addrMgr := New(tempDir, nil) + + // As we're interested in testing the upgrade path from v1 to v2, we'll + // override the manager's current version. + addrMgr.version = 1 + + // We'll be adding 5 random addresses to the manager. Since this is v1, + // each addresses' services will not be stored. + const numAddrs = 5 + + expectedAddrs := make(map[string]*wire.NetAddress, numAddrs) + for i := 0; i < numAddrs; i++ { + addr := randAddr(t) + expectedAddrs[NetAddressKey(addr)] = addr + addrMgr.AddAddress(addr, randAddr(t)) + } + + // Then, we'll persist these addresses to disk and restart the address + // manager - overriding its version back to v1. + addrMgr.savePeers() + addrMgr = New(tempDir, nil) + addrMgr.version = 1 + + // When we read all of the addresses back from disk, we should expect to + // find all of them, but their services will be set to a default of + // SFNodeNetwork since they were not previously stored. After ensuring + // that this default is set, we'll override each addresses' services + // with the original value from when they were created. + addrMgr.loadPeers() + addrs := addrMgr.getAddresses() + if len(addrs) != len(expectedAddrs) { + t.Fatalf("expected to find %d adddresses, found %d", + len(expectedAddrs), len(addrs)) + } + for _, addr := range addrs { + addrStr := NetAddressKey(addr) + expectedAddr, ok := expectedAddrs[addrStr] + if !ok { + t.Fatalf("expected to find address %v", addrStr) + } + + if addr.Services != wire.SFNodeNetwork { + t.Fatalf("expected address services to be %v, got %v", + wire.SFNodeNetwork, addr.Services) + } + + addrMgr.SetServices(addr, expectedAddr.Services) + } + + // We'll also bump up the manager's version to v2, which should signal + // that it should include the address services when persisting its + // state. + addrMgr.version = 2 + addrMgr.savePeers() + + // Finally, we'll recreate the manager and ensure that the services were + // persisted correctly. + addrMgr = New(tempDir, nil) + addrMgr.loadPeers() + assertAddrs(t, addrMgr, expectedAddrs) +} diff --git a/addrmgr/addrmanager_test.go b/addrmgr/addrmanager_test.go index fcfe845fe7..676913e21e 100644 --- a/addrmgr/addrmanager_test.go +++ b/addrmgr/addrmanager_test.go @@ -262,7 +262,7 @@ func TestNeedMoreAddresses(t *testing.T) { var err error for i := 0; i < addrsToAdd; i++ { s := fmt.Sprintf("%d.%d.173.147:8333", i/128+60, i%128+60) - addrs[i], err = n.DeserializeNetAddress(s) + addrs[i], err = n.DeserializeNetAddress(s, wire.SFNodeNetwork) if err != nil { t.Errorf("Failed to turn %s into an address: %v", s, err) } @@ -290,7 +290,7 @@ func TestGood(t *testing.T) { var err error for i := 0; i < addrsToAdd; i++ { s := fmt.Sprintf("%d.173.147.%d:8333", i/64+60, i%64+60) - addrs[i], err = n.DeserializeNetAddress(s) + addrs[i], err = n.DeserializeNetAddress(s, wire.SFNodeNetwork) if err != nil { t.Errorf("Failed to turn %s into an address: %v", s, err) } From 2bdd957fe14516e5e70d8e38762eb7b41efc883b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 12 Feb 2019 18:36:55 -0800 Subject: [PATCH 0265/1056] build: update to latest version of btcutil In this commit, we update to the latest version of `btcutil`. This version contains a bug fix for the neutrino filter generation. The implementation within `btcutil` didn't fully comply with the BIP specification as it included some OP_RETURN outputs, rather than excluding them all. As a result, any active `btcd` node on mainnet/testnet will need to _drop their entire `cfindex`_ and re-index after this is merged in. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index cbc8248b84..1a3d420cc1 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/btcsuite/btcd require ( github.com/aead/siphash v1.0.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a + github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 // indirect diff --git a/go.sum b/go.sum index 2391754298..ed88ea0ec7 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a h1:RQMUrEILyYJEoAT34XS/kLu40vC0+po/UfxrBBA4qZE= -github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 h1:j3AgPKKZtZStM2nyhrDSLSYgT7YHrZKdSkq1OYeLjvM= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= From aa6e0f35703c1438cc45860ddc0c3f6e6c633c93 Mon Sep 17 00:00:00 2001 From: Mawueli Kofi Adzoe Date: Fri, 15 Mar 2019 13:16:42 -0700 Subject: [PATCH 0266/1056] docs: use go modules instead of glide Fixes https://github.com/btcsuite/btcd/issues/1379 --- docs/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/README.md b/docs/README.md index c00d295e7a..8fb7a15ed7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -95,11 +95,9 @@ recommended that `GOPATH` is set to a directory in your home directory such as - Run the following commands to obtain btcd, all dependencies, and install it: ```bash -$ go get -u github.com/Masterminds/glide $ git clone https://github.com/btcsuite/btcd $GOPATH/src/github.com/btcsuite/btcd $ cd $GOPATH/src/github.com/btcsuite/btcd -$ glide install -$ go install . ./cmd/... +$ GO111MODULE=on go install -v . ./cmd/... ``` - btcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did @@ -112,8 +110,7 @@ $ go install . ./cmd/... ```bash $ cd $GOPATH/src/github.com/btcsuite/btcd -$ git pull && glide install -$ go install . ./cmd/... +$ git pull && GO111MODULE=on go install -v . ./cmd/... ``` From 9bfb2ca0346b57e246cc96fa31074df521175240 Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Wed, 10 Apr 2019 05:54:18 +0300 Subject: [PATCH 0267/1056] connmgr: check for canceled connection before connect This will ensure cancelation is reliable for all cases. --- connmgr/connmanager.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go index 2116934ab5..9a68190267 100644 --- a/connmgr/connmanager.go +++ b/connmgr/connmanager.go @@ -408,6 +408,14 @@ func (cm *ConnManager) Connect(c *ConnReq) { if atomic.LoadInt32(&cm.stop) != 0 { return } + + // During the time we wait for retry there is a chance that + // this connection was already cancelled + if c.State() == ConnCanceled { + log.Debugf("Ignoring connect for canceled connreq=%v", c) + return + } + if atomic.LoadUint64(&c.id) == 0 { atomic.StoreUint64(&c.id, atomic.AddUint64(&cm.connReqCount, 1)) From d3ecdc91a9ac0305ca9c8af02b0dacb285e2a5cb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 9 Jan 2018 19:12:46 -0800 Subject: [PATCH 0268/1056] server: adds hybrid black/whitelist filtering to user agents --- server.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/server.go b/server.go index 42f34da5b2..ab2c31fe39 100644 --- a/server.go +++ b/server.go @@ -246,6 +246,14 @@ type server struct { // messages for each filter type. cfCheckptCaches map[wire.FilterType][]cfHeaderKV cfCheckptCachesMtx sync.RWMutex + + // agentBlacklist is a list of blacklisted substrings by which to filter + // user agents. + agentBlacklist []string + + // agentWhitelist is a list of whitelisted user agent substrings, no + // whitelisting will be applied if the list is empty or nil. + agentWhitelist []string } // serverPeer extends the peer to maintain state shared by the server and @@ -1586,6 +1594,12 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool { return false } + // Disconnect peers with unwanted user agents. + if sp.HasUndesiredUserAgent(s.agentBlacklist, s.agentWhitelist) { + sp.Disconnect() + return false + } + // Ignore new peers if we're shutting down. if atomic.LoadInt32(&s.shutdown) != 0 { srvrLog.Infof("New peer %s ignored - server is shutting down", sp) @@ -3133,3 +3147,47 @@ func mergeCheckpoints(defaultCheckpoints, additional []chaincfg.Checkpoint) []ch sort.Sort(checkpointSorter(checkpoints)) return checkpoints } + +// HasUndesiredUserAgent determines whether the server should continue to pursue +// a connection with this peer based on its advertised user agent. It performs +// the following steps: +// 1) Reject the peer if it contains a blacklisted agent. +// 2) If no whitelist is provided, accept all user agents. +// 3) Accept the peer if it contains a whitelisted agent. +// 4) Reject all other peers. +func (sp *serverPeer) HasUndesiredUserAgent(blacklistedAgents, + whitelistedAgents []string) bool { + + agent := sp.UserAgent() + + // First, if peer's user agent contains any blacklisted substring, we + // will ignore the connection request. + for _, blacklistedAgent := range blacklistedAgents { + if strings.Contains(agent, blacklistedAgent) { + srvrLog.Debugf("Ignoring peer %s, user agent "+ + "contains blacklisted user agent: %s", sp, + agent) + return true + } + } + + // If no whitelist is provided, we will accept all user agents. + if len(whitelistedAgents) == 0 { + return false + } + + // Peer's user agent passed blacklist. Now check to see if it contains + // one of our whitelisted user agents, if so accept. + for _, whitelistedAgent := range whitelistedAgents { + if strings.Contains(agent, whitelistedAgent) { + return false + } + } + + // Otherwise, the peer's user agent was not included in our whitelist. + // Ignore just in case it could stall the initial block download. + srvrLog.Debugf("Ignoring peer %s, user agent: %s not found in "+ + "whitelist", sp, agent) + + return true +} From 0e073b8058b634abfc618f983d3f978813050ada Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 9 Jan 2018 19:13:50 -0800 Subject: [PATCH 0269/1056] config: adds AgentWhitelist and AgentBlacklist to config --- config.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config.go b/config.go index e004e42860..5934f6bca4 100644 --- a/config.go +++ b/config.go @@ -106,6 +106,8 @@ type config struct { BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"` + AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."` + AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."` RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"` RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"` RPCLimitUser string `long:"rpclimituser" description:"Username for limited RPC connections"` From a9f23321d9561b0cebaa52d964b555bc61634500 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 15 Apr 2019 18:25:37 -0700 Subject: [PATCH 0270/1056] netsync/manager: prioritize higher height peers for sync peer This commit modifies the sync peer selection to prefer peers with a higher advertised height than our currently known best height. If no peers are known with a higher height, we will fall back to selecting a random peer with the same best height as our own. The current algorithm currently selects a random peer from the union of these two sets, while this approach will favor trying to make progress. This will likely help in selecting a good peer once already at tip, such as after a restart. Backport of https://github.com/gcash/bchd/pull/96 --- netsync/manager.go | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/netsync/manager.go b/netsync/manager.go index 2a940edbff..8444c8983c 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -6,6 +6,7 @@ package netsync import ( "container/list" + "math/rand" "net" "sync" "sync/atomic" @@ -236,7 +237,7 @@ func (sm *SyncManager) startSync() { } best := sm.chain.BestSnapshot() - var bestPeer *peerpkg.Peer + var higherPeers, equalPeers []*peerpkg.Peer for peer, state := range sm.peerStates { if !state.syncCandidate { continue @@ -258,9 +259,33 @@ func (sm *SyncManager) startSync() { continue } - // TODO(davec): Use a better algorithm to choose the best peer. - // For now, just pick the first available candidate. - bestPeer = peer + // If the peer is at the same height as us, we'll add it a set + // of backup peers in case we do not find one with a higher + // height. If we are synced up with all of our peers, all of + // them will be in this set. + if peer.LastBlock() == best.Height { + equalPeers = append(equalPeers, peer) + continue + } + + // This peer has a height greater than our own, we'll consider + // it in the set of better peers from which we'll randomly + // select. + higherPeers = append(higherPeers, peer) + } + + // Pick randomly from the set of peers greater than our block height, + // falling back to a random peer of the same height if none are greater. + // + // TODO(conner): Use a better algorithm to ranking peers based on + // observed metrics and/or sync in parallel. + var bestPeer *peerpkg.Peer + switch { + case len(higherPeers) > 0: + bestPeer = higherPeers[rand.Intn(len(higherPeers))] + + case len(equalPeers) > 0: + bestPeer = equalPeers[rand.Intn(len(equalPeers))] } // Start syncing from the best peer if one was selected. From 39592eba78bc139b9eeecdff978905d655c674cc Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 9 Jan 2018 19:13:25 -0800 Subject: [PATCH 0271/1056] btcd: pass user agent black and white lists to server --- btcd.go | 4 ++-- server.go | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/btcd.go b/btcd.go index a0ccb3eabc..c17d6ab48a 100644 --- a/btcd.go +++ b/btcd.go @@ -145,8 +145,8 @@ func btcdMain(serverChan chan<- *server) error { } // Create server and start it. - server, err := newServer(cfg.Listeners, db, activeNetParams.Params, - interrupt) + server, err := newServer(cfg.Listeners, cfg.AgentBlacklist, + cfg.AgentWhitelist, db, activeNetParams.Params, interrupt) if err != nil { // TODO: this logging could do with some beautifying. btcdLog.Errorf("Unable to start server on %v: %v", diff --git a/server.go b/server.go index ab2c31fe39..d8fac25640 100644 --- a/server.go +++ b/server.go @@ -2552,7 +2552,10 @@ func setupRPCListeners() ([]net.Listener, error) { // newServer returns a new btcd server configured to listen on addr for the // bitcoin network type specified by chainParams. Use start to begin accepting // connections from peers. -func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Params, interrupt <-chan struct{}) (*server, error) { +func newServer(listenAddrs, agentBlacklist, agentWhitelist []string, + db database.DB, chainParams *chaincfg.Params, + interrupt <-chan struct{}) (*server, error) { + services := defaultServices if cfg.NoPeerBloomFilters { services &^= wire.SFNodeBloom @@ -2576,6 +2579,13 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param } } + if len(agentBlacklist) > 0 { + srvrLog.Infof("User-agent blacklist %s", agentBlacklist) + } + if len(agentWhitelist) > 0 { + srvrLog.Infof("User-agent whitelist %s", agentWhitelist) + } + s := server{ chainParams: chainParams, addrManager: amgr, @@ -2595,6 +2605,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param sigCache: txscript.NewSigCache(cfg.SigCacheMaxSize), hashCache: txscript.NewHashCache(cfg.SigCacheMaxSize), cfCheckptCaches: make(map[wire.FilterType][]cfHeaderKV), + agentBlacklist: agentBlacklist, + agentWhitelist: agentWhitelist, } // Create the transaction and address indexes if needed. From 778c28fcd80eb4ad794e195c9c857d1a89c2d5bd Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 16 Jan 2019 20:08:59 -0800 Subject: [PATCH 0272/1056] chaincfg: update mainnet checkpoints --- chaincfg/params.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/chaincfg/params.go b/chaincfg/params.go index 9da7102b4a..4fb5f1d3d1 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -272,6 +272,13 @@ var MainNetParams = Params{ {343185, newHashFromStr("0000000000000000072b8bf361d01a6ba7d445dd024203fafc78768ed4368554")}, {352940, newHashFromStr("000000000000000010755df42dba556bb72be6a32f3ce0b6941ce4430152c9ff")}, {382320, newHashFromStr("00000000000000000a8dc6ed5b133d0eb2fd6af56203e4159789b092defd8ab2")}, + {400000, newHashFromStr("000000000000000004ec466ce4732fe6f1ed1cddc2ed4b328fff5224276e3f6f")}, + {430000, newHashFromStr("000000000000000001868b2bb3a285f3cc6b33ea234eb70facf4dcdf22186b87")}, + {460000, newHashFromStr("000000000000000000ef751bbce8e744ad303c47ece06c8d863e4d417efc258c")}, + {490000, newHashFromStr("000000000000000000de069137b17b8d5a3dfbd5b145b2dcfb203f15d0c4de90")}, + {520000, newHashFromStr("0000000000000000000d26984c0229c9f6962dc74db0a6d525f2f1640396f69c")}, + {550000, newHashFromStr("000000000000000000223b7a2298fb1c6c75fb0efc28a4c56853ff4112ec6bc9")}, + {560000, newHashFromStr("0000000000000000002c7b276daf6efb2b6aa68e2ce3be67ef925b3264ae7122")}, }, // Consensus rule change deployments. From 3fbc9997ce03a7ae5833a5c0ee819b94d7b4c50b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 16 Jan 2019 20:09:09 -0800 Subject: [PATCH 0273/1056] chaincfg: update testnet checkpoints --- chaincfg/params.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chaincfg/params.go b/chaincfg/params.go index 4fb5f1d3d1..54117b8713 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -446,6 +446,9 @@ var TestNet3Params = Params{ {800010, newHashFromStr("000000000017ed35296433190b6829db01e657d80631d43f5983fa403bfdb4c1")}, {900000, newHashFromStr("0000000000356f8d8924556e765b7a94aaebc6b5c8685dcfa2b1ee8b41acd89b")}, {1000007, newHashFromStr("00000000001ccb893d8a1f25b70ad173ce955e5f50124261bbbc50379a612ddf")}, + {1100007, newHashFromStr("00000000000abc7b2cd18768ab3dee20857326a818d1946ed6796f42d66dd1e8")}, + {1200007, newHashFromStr("00000000000004f2dc41845771909db57e04191714ed8c963f7e56713a7b6cea")}, + {1300007, newHashFromStr("0000000072eab69d54df75107c052b26b0395b44f77578184293bf1bb1dbd9fa")}, }, // Consensus rule change deployments. From b8cdcc3ffc115d5218063653b0e71af652c9df7e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 25 Apr 2019 17:38:31 -0700 Subject: [PATCH 0274/1056] build: update to latest version of btcutil In this commit, we update to the latest version of btcutil which contains a bug fix for filter matching, and as optimizations speed up both filter matching and constructions. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1a3d420cc1..9488a8bd39 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/btcsuite/btcd require ( github.com/aead/siphash v1.0.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 + github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 // indirect diff --git a/go.sum b/go.sum index ed88ea0ec7..dc773d4775 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803 h1:j3AgPKKZtZStM2nyhrDSLSYgT7YHrZKdSkq1OYeLjvM= -github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= From a015d8231ecc77d1fb27b1923f4cf9e55acb2aaf Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 15 Apr 2019 20:34:46 -0700 Subject: [PATCH 0275/1056] netsync/manager: split out handlePeerDone helpers Preemptively splits out portions of the handlePeerDone method so that they can be used in the stall detection logic added in the next commit. --- netsync/manager.go | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/netsync/manager.go b/netsync/manager.go index 8444c8983c..37c2670772 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -418,6 +418,19 @@ func (sm *SyncManager) handleDonePeerMsg(peer *peerpkg.Peer) { log.Infof("Lost peer %s", peer) + sm.clearRequestedState(state) + + if peer == sm.syncPeer { + // Update the sync peer. The server has already disconnected the + // peer before signaling to the sync manager. + sm.updateSyncPeer(false) + } +} + +// clearRequestedState wipes all expected transactions and blocks from the sync +// manager's requested maps that were requested under a peer's sync state, This +// allows them to be rerequested by a subsequent sync peer. +func (sm *SyncManager) clearRequestedState(state *peerSyncState) { // Remove requested transactions from the global map so that they will // be fetched from elsewhere next time we get an inv. for txHash := range state.requestedTxns { @@ -431,18 +444,29 @@ func (sm *SyncManager) handleDonePeerMsg(peer *peerpkg.Peer) { for blockHash := range state.requestedBlocks { delete(sm.requestedBlocks, blockHash) } +} - // Attempt to find a new peer to sync from if the quitting peer is the - // sync peer. Also, reset the headers-first state if in headers-first - // mode so - if sm.syncPeer == peer { - sm.syncPeer = nil - if sm.headersFirstMode { - best := sm.chain.BestSnapshot() - sm.resetHeaderState(&best.Hash, best.Height) - } - sm.startSync() +// updateSyncPeer choose a new sync peer to replace the current one. If +// dcSyncPeer is true, this method will also disconnect the current sync peer. +// If we are in header first mode, any header state related to prefetching is +// also reset in preparation for the next sync peer. +func (sm *SyncManager) updateSyncPeer(dcSyncPeer bool) { + log.Infof("Updating sync peer, no progress since: %v", + time.Since(sm.lastProgressTime)) + + // First, disconnect the current sync peer if requested. + if dcSyncPeer { + sm.syncPeer.Disconnect() } + + // Reset any header state before we choose our next active sync peer. + if sm.headersFirstMode { + best := sm.chain.BestSnapshot() + sm.resetHeaderState(&best.Hash, best.Height) + } + + sm.syncPeer = nil + sm.startSync() } // handleTxMsg handles transaction messages from all peers. From e7f99350994c27f6986b6a35b86d04c47121ebd3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 15 Apr 2019 20:35:45 -0700 Subject: [PATCH 0276/1056] netsync/manager: add syncPeer stall detector Adds stall detection when no blocks have been received from the sync peer for at least 3 minutes. The change backports parts of https://github.com/gcash/bchd/pull/105, though has different behavior, such as: - Rotating the sync peer at tip. - Only disconnecting the sync peer if they're height exceeds our own. Since we will instead rotate the sync peer at tip, this prevents us from disconnecting good peers while waiting for new blocks. - Not resetting the progress time when blocks are submitted via rpc. --- netsync/manager.go | 89 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 6 deletions(-) diff --git a/netsync/manager.go b/netsync/manager.go index 37c2670772..32715b8e1e 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -39,6 +39,14 @@ const ( // maxRequestedTxns is the maximum number of requested transactions // hashes to store in memory. maxRequestedTxns = wire.MaxInvPerMsg + + // maxStallDuration is the time after which we will disconnect our + // current sync peer if we haven't made progress. + maxStallDuration = 3 * time.Minute + + // stallSampleInterval the interval at which we will check to see if our + // sync has stalled. + stallSampleInterval = 30 * time.Second ) // zeroHash is the zero value hash (all zeros). It is defined as a convenience. @@ -157,11 +165,12 @@ type SyncManager struct { quit chan struct{} // These fields should only be accessed from the blockHandler thread - rejectedTxns map[chainhash.Hash]struct{} - requestedTxns map[chainhash.Hash]struct{} - requestedBlocks map[chainhash.Hash]struct{} - syncPeer *peerpkg.Peer - peerStates map[*peerpkg.Peer]*peerSyncState + rejectedTxns map[chainhash.Hash]struct{} + requestedTxns map[chainhash.Hash]struct{} + requestedBlocks map[chainhash.Hash]struct{} + syncPeer *peerpkg.Peer + peerStates map[*peerpkg.Peer]*peerSyncState + lastProgressTime time.Time // The following fields are used for headers-first mode. headersFirstMode bool @@ -335,6 +344,11 @@ func (sm *SyncManager) startSync() { bestPeer.PushGetBlocksMsg(locator, &zeroHash) } sm.syncPeer = bestPeer + + // Reset the last progress time now that we have a non-nil + // syncPeer to avoid instantly detecting it as stalled in the + // event the progress time hasn't been updated recently. + sm.lastProgressTime = time.Now() } else { log.Warnf("No sync peer candidates available") } @@ -402,6 +416,59 @@ func (sm *SyncManager) handleNewPeerMsg(peer *peerpkg.Peer) { } } +// handleStallSample will switch to a new sync peer if the current one has +// stalled. This is detected when by comparing the last progress timestamp with +// the current time, and disconnecting the peer if we stalled before reaching +// their highest advertised block. +func (sm *SyncManager) handleStallSample() { + if atomic.LoadInt32(&sm.shutdown) != 0 { + return + } + + // If we don't have an active sync peer, exit early. + if sm.syncPeer == nil { + return + } + + // If the stall timeout has not elapsed, exit early. + if time.Since(sm.lastProgressTime) <= maxStallDuration { + return + } + + // Check to see that the peer's sync state exists. + state, exists := sm.peerStates[sm.syncPeer] + if !exists { + return + } + + sm.clearRequestedState(state) + + disconnectSyncPeer := sm.shouldDCStalledSyncPeer() + sm.updateSyncPeer(disconnectSyncPeer) +} + +// shouldDCStalledSyncPeer determines whether or not we should disconnect a +// stalled sync peer. If the peer has stalled and its reported height is greater +// than our own best height, we will disconnect it. Otherwise, we will keep the +// peer connected in case we are already at tip. +func (sm *SyncManager) shouldDCStalledSyncPeer() bool { + lastBlock := sm.syncPeer.LastBlock() + startHeight := sm.syncPeer.StartingHeight() + + var peerHeight int32 + if lastBlock > startHeight { + peerHeight = lastBlock + } else { + peerHeight = startHeight + } + + // If we've stalled out yet the sync peer reports having more blocks for + // us we will disconnect them. This allows us at tip to not disconnect + // peers when we are equal or they temporarily lag behind us. + best := sm.chain.BestSnapshot() + return peerHeight > best.Height +} + // handleDonePeerMsg deals with peers that have signalled they are done. It // removes the peer as a candidate for syncing and in the case where it was // the current sync peer, attempts to select a new best peer to sync from. It @@ -451,7 +518,7 @@ func (sm *SyncManager) clearRequestedState(state *peerSyncState) { // If we are in header first mode, any header state related to prefetching is // also reset in preparation for the next sync peer. func (sm *SyncManager) updateSyncPeer(dcSyncPeer bool) { - log.Infof("Updating sync peer, no progress since: %v", + log.Debugf("Updating sync peer, no progress for: %v", time.Since(sm.lastProgressTime)) // First, disconnect the current sync peer if requested. @@ -683,6 +750,10 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) { peer.PushGetBlocksMsg(locator, orphanRoot) } } else { + if peer == sm.syncPeer { + sm.lastProgressTime = time.Now() + } + // When the block is not an orphan, log information about it and // update the chain state. sm.progressLogger.LogBlockHeight(bmsg.block) @@ -1199,6 +1270,9 @@ func (sm *SyncManager) limitMap(m map[chainhash.Hash]struct{}, limit int) { // important because the sync manager controls which blocks are needed and how // the fetching should proceed. func (sm *SyncManager) blockHandler() { + stallTicker := time.NewTicker(stallSampleInterval) + defer stallTicker.Stop() + out: for { select { @@ -1258,6 +1332,9 @@ out: "handler: %T", msg) } + case <-stallTicker.C: + sm.handleStallSample() + case <-sm.quit: break out } From d0558925999c46be45898fe27ac0085a076ef15d Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Sat, 11 May 2019 17:48:24 -0700 Subject: [PATCH 0277/1056] btcjson+rpc: match bitcoind's RPC error codes for rejected transactions --- btcjson/jsonrpcerr.go | 3 +++ rpcserver.go | 45 +++++++++++++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/btcjson/jsonrpcerr.go b/btcjson/jsonrpcerr.go index c9431c5a96..8996c47461 100644 --- a/btcjson/jsonrpcerr.go +++ b/btcjson/jsonrpcerr.go @@ -76,6 +76,9 @@ const ( ErrRPCInvalidTxVout RPCErrorCode = -5 ErrRPCRawTxString RPCErrorCode = -32602 ErrRPCDecodeHexString RPCErrorCode = -22 + ErrRPCTxError RPCErrorCode = -25 + ErrRPCTxRejected RPCErrorCode = -26 + ErrRPCTxAlreadyInChain RPCErrorCode = -27 ) // Errors that are specific to btcd. diff --git a/rpcserver.go b/rpcserver.go index 6ade888d38..a3cf1e0f7a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3323,19 +3323,44 @@ func handleSendRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan st if err != nil { // When the error is a rule error, it means the transaction was // simply rejected as opposed to something actually going wrong, - // so log it as such. Otherwise, something really did go wrong, - // so log it as an actual error. In both cases, a JSON-RPC - // error is returned to the client with the deserialization - // error code (to match bitcoind behavior). - if _, ok := err.(mempool.RuleError); ok { - rpcsLog.Debugf("Rejected transaction %v: %v", tx.Hash(), - err) - } else { + // so log it as such. Otherwise, something really did go wrong, + // so log it as an actual error and return. + ruleErr, ok := err.(mempool.RuleError) + if !ok { rpcsLog.Errorf("Failed to process transaction %v: %v", tx.Hash(), err) + + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCTxError, + Message: "TX rejected: " + err.Error(), + } } + + rpcsLog.Debugf("Rejected transaction %v: %v", tx.Hash(), err) + + // We'll then map the rule error to the appropriate RPC error, + // matching bitcoind's behavior. + code := btcjson.ErrRPCTxError + if txRuleErr, ok := ruleErr.Err.(mempool.TxRuleError); ok { + errDesc := txRuleErr.Description + switch { + case strings.Contains( + strings.ToLower(errDesc), "orphan transaction", + ): + code = btcjson.ErrRPCTxError + + case strings.Contains( + strings.ToLower(errDesc), "transaction already exists", + ): + code = btcjson.ErrRPCTxAlreadyInChain + + default: + code = btcjson.ErrRPCTxRejected + } + } + return nil, &btcjson.RPCError{ - Code: btcjson.ErrRPCDeserialization, + Code: code, Message: "TX rejected: " + err.Error(), } } @@ -4281,7 +4306,7 @@ func newRPCServer(config *rpcserverConfig) (*rpcServer, error) { gbtWorkState: newGbtWorkState(config.TimeSource), helpCacher: newHelpCacher(), requestProcessShutdown: make(chan struct{}), - quit: make(chan int), + quit: make(chan int), } if cfg.RPCUser != "" && cfg.RPCPass != "" { login := cfg.RPCUser + ":" + cfg.RPCPass From 545bc5d474e7798cadcfd22a703b2246a0d594a4 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 30 May 2019 12:29:45 -0700 Subject: [PATCH 0278/1056] txscript: handle variable length P2PKH signatures in ComputePkScript Since P2PKH signatures have variable lengths, we would attempt to parse P2PKH scripts as P2SH if they didn't fit the previous length constraints. --- btcec/signature.go | 10 ++++----- txscript/pkscript.go | 47 +++++++++++++++++++++++++-------------- txscript/pkscript_test.go | 9 ++++---- 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/btcec/signature.go b/btcec/signature.go index bddb228315..f1c4377499 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -85,10 +85,10 @@ func (sig *Signature) IsEqual(otherSig *Signature) bool { sig.S.Cmp(otherSig.S) == 0 } -// minSigLen is the minimum length of a DER encoded signature and is -// when both R and S are 1 byte each. +// MinSigLen is the minimum length of a DER encoded signature and is when both R +// and S are 1 byte each. // 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + -const minSigLen = 8 +const MinSigLen = 8 func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { // Originally this code used encoding/asn1 in order to parse the @@ -103,7 +103,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) signature := &Signature{} - if len(sigStr) < minSigLen { + if len(sigStr) < MinSigLen { return nil, errors.New("malformed signature: too short") } // 0x30 @@ -118,7 +118,7 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) // siglen should be less than the entire message and greater than // the minimal message size. - if int(siglen+2) > len(sigStr) || int(siglen+2) < minSigLen { + if int(siglen+2) > len(sigStr) || int(siglen+2) < MinSigLen { return nil, errors.New("malformed signature: bad length") } // trim the slice we're working on so we only look at what matters. diff --git a/txscript/pkscript.go b/txscript/pkscript.go index e2823a8b53..4f72ca16ca 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -13,13 +13,23 @@ import ( ) const ( - // pubKeyHashSigScriptLen is the length of a signature script attempting - // to spend a P2PKH script. The only other possible length value is 107 - // bytes, due to the signature within it. This length is determined by - // the following: - // 0x47 or 0x48 (71 or 72 byte data push) | <71 or 72 byte sig> | - // 0x21 (33 byte data push) | <33 byte compressed pubkey> - pubKeyHashSigScriptLen = 106 + // minPubKeyHashSigScriptLen is the minimum length of a signature script + // that spends a P2PKH output. The length is composed of the following: + // Signature length (1 byte) + // Signature (min 8 bytes) + // Signature hash type (1 byte) + // Public key length (1 byte) + // Public key (33 byte) + minPubKeyHashSigScriptLen = 1 + btcec.MinSigLen + 1 + 1 + 33 + + // maxPubKeyHashSigScriptLen is the maximum length of a signature script + // that spends a P2PKH output. The length is composed of the following: + // Signature length (1 byte) + // Signature (max 72 bytes) + // Signature hash type (1 byte) + // Public key length (1 byte) + // Public key (33 byte) + maxPubKeyHashSigScriptLen = 1 + 72 + 1 + 1 + 33 // compressedPubKeyLen is the length in bytes of a compressed public // key. @@ -161,11 +171,19 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) // We'll start by checking the input's signature script, if provided. switch { + case len(sigScript) == 0: + break + + // Since we only support P2PKH and P2SH scripts as the only non-witness + // script types, we should expect to see a push only script. + case !IsPushOnlyScript(sigScript): + return pkScript, ErrUnsupportedScriptType + // If a signature script is provided with a length long enough to // represent a P2PKH script, then we'll attempt to parse the compressed // public key from it. - case len(sigScript) == pubKeyHashSigScriptLen || - len(sigScript) == pubKeyHashSigScriptLen+1: + case len(sigScript) >= minPubKeyHashSigScriptLen && + len(sigScript) <= maxPubKeyHashSigScriptLen: // The public key should be found as the last part of the // signature script. We'll attempt to parse it to ensure this is @@ -183,14 +201,12 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) return pkScript, nil } - // If it isn't, we'll assume it is a P2SH signature script. fallthrough // If we failed to parse a compressed public key from the script in the - // case above, or if the script length is not that of a P2PKH one, and - // our redeem script is only composed of data pushed, we can assume it's - // a P2SH signature script. - case len(sigScript) > 0 && IsPushOnlyScript(sigScript): + // case above, or if the script length is not that of a P2PKH one, we + // can assume it's a P2SH signature script. + default: // The redeem script will always be the last data push of the // signature script, so we'll parse the script into opcodes to // obtain it. @@ -209,9 +225,6 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) pkScript.class = ScriptHashTy copy(pkScript.script[:], script) return pkScript, nil - - case len(sigScript) > 0: - return pkScript, ErrUnsupportedScriptType } // If a witness was provided instead, we'll use the last item of the diff --git a/txscript/pkscript_test.go b/txscript/pkscript_test.go index dd8928271a..841842c268 100644 --- a/txscript/pkscript_test.go +++ b/txscript/pkscript_test.go @@ -208,9 +208,9 @@ func TestComputePkScript(t *testing.T) { { name: "P2PKH sigScript", sigScript: []byte{ - // OP_DATA_71, - 0x47, - // <71-byte sig> + // OP_DATA_73, + 0x49, + // <73-byte sig> 0x30, 0x44, 0x02, 0x20, 0x65, 0x92, 0xd8, 0x8e, 0x1d, 0x0a, 0x4a, 0x3c, 0xc5, 0x9f, 0x92, 0xae, 0xfe, 0x62, 0x54, 0x74, 0xa9, 0x4d, 0x13, 0xa5, @@ -219,7 +219,8 @@ func TestComputePkScript(t *testing.T) { 0x36, 0x96, 0x19, 0x1f, 0xb7, 0x00, 0xc5, 0xa7, 0x7e, 0x22, 0xd9, 0xfb, 0x6b, 0x42, 0x67, 0x42, 0xa4, 0x2c, 0xac, 0xdb, 0x74, 0xa2, 0x7c, 0x43, - 0xcd, 0x89, 0xa0, 0xf9, 0x44, 0x54, 0x01, + 0xcd, 0x89, 0xa0, 0xf9, 0x44, 0x54, 0x12, 0x74, + 0x01, // OP_DATA_33 0x21, // <33-byte compressed pubkey> From 5328af0b6351cdf0ba2b653cc803ad6a5851fcef Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 30 May 2019 12:41:25 -0700 Subject: [PATCH 0279/1056] txscript: refactor ComputePkScript --- txscript/pkscript.go | 50 +++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/txscript/pkscript.go b/txscript/pkscript.go index 4f72ca16ca..0703ef5d05 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -156,28 +156,29 @@ func (s PkScript) String() string { return str } -// ComputePkScript computes the pkScript of an transaction output by looking at -// the transaction input's signature script or witness. +// ComputePkScript computes the script of an output by looking at the spending +// input's signature script or witness. // // NOTE: Only P2PKH, P2SH, P2WSH, and P2WPKH redeem scripts are supported. func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) { - var pkScript PkScript - - // Ensure that either an input's signature script or a witness was - // provided. - if len(sigScript) == 0 && len(witness) == 0 { - return pkScript, ErrUnsupportedScriptType + switch { + case len(sigScript) > 0: + return computeNonWitnessPkScript(sigScript) + case len(witness) > 0: + return computeWitnessPkScript(witness) + default: + return PkScript{}, ErrUnsupportedScriptType } +} - // We'll start by checking the input's signature script, if provided. +// computeNonWitnessPkScript computes the script of an output by looking at the +// spending input's signature script. +func computeNonWitnessPkScript(sigScript []byte) (PkScript, error) { switch { - case len(sigScript) == 0: - break - // Since we only support P2PKH and P2SH scripts as the only non-witness // script types, we should expect to see a push only script. case !IsPushOnlyScript(sigScript): - return pkScript, ErrUnsupportedScriptType + return PkScript{}, ErrUnsupportedScriptType // If a signature script is provided with a length long enough to // represent a P2PKH script, then we'll attempt to parse the compressed @@ -193,10 +194,10 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) pubKeyHash := hash160(pubKey) script, err := payToPubKeyHashScript(pubKeyHash) if err != nil { - return pkScript, err + return PkScript{}, err } - pkScript.class = PubKeyHashTy + pkScript := PkScript{class: PubKeyHashTy} copy(pkScript.script[:], script) return pkScript, nil } @@ -212,25 +213,30 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) // obtain it. parsedOpcodes, err := parseScript(sigScript) if err != nil { - return pkScript, err + return PkScript{}, err } redeemScript := parsedOpcodes[len(parsedOpcodes)-1].data scriptHash := hash160(redeemScript) script, err := payToScriptHashScript(scriptHash) if err != nil { - return pkScript, err + return PkScript{}, err } - pkScript.class = ScriptHashTy + pkScript := PkScript{class: ScriptHashTy} copy(pkScript.script[:], script) return pkScript, nil } +} - // If a witness was provided instead, we'll use the last item of the - // witness stack to determine the proper witness type. +// computeWitnessPkScript computes the script of an output by looking at the +// spending input's witness. +func computeWitnessPkScript(witness wire.TxWitness) (PkScript, error) { + // We'll use the last item of the witness stack to determine the proper + // witness type. lastWitnessItem := witness[len(witness)-1] + var pkScript PkScript switch { // If the witness stack has a size of 2 and its last item is a // compressed public key, then this is a P2WPKH witness. @@ -243,7 +249,6 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) pkScript.class = WitnessV0PubKeyHashTy copy(pkScript.script[:], script) - return pkScript, nil // For any other witnesses, we'll assume it's a P2WSH witness. default: @@ -255,8 +260,9 @@ func ComputePkScript(sigScript []byte, witness wire.TxWitness) (PkScript, error) pkScript.class = WitnessV0ScriptHashTy copy(pkScript.script[:], script) - return pkScript, nil } + + return pkScript, nil } // hash160 returns the RIPEMD160 hash of the SHA-256 HASH of the given data. From 95d0a371d9ee14856e66c9f216ee460b772be06e Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 2 May 2019 19:44:51 -0700 Subject: [PATCH 0280/1056] mempool: implement RBF signaling policy --- config.go | 1 + mempool/mempool.go | 342 +++++++++++++- mempool/mempool_test.go | 972 +++++++++++++++++++++++++++++++++++++++- server.go | 1 + 4 files changed, 1287 insertions(+), 29 deletions(-) diff --git a/config.go b/config.go index 5934f6bca4..3bcc65dacd 100644 --- a/config.go +++ b/config.go @@ -165,6 +165,7 @@ type config struct { DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."` RelayNonStd bool `long:"relaynonstd" description:"Relay non-standard transactions regardless of the default settings for the active network."` RejectNonStd bool `long:"rejectnonstd" description:"Reject non-standard transactions regardless of the default settings for the active network."` + RejectReplacement bool `long:"rejectreplacement" description:"Reject transactions that attempt to replace existing transactions within the mempool through the Replace-By-Fee (RBF) signaling policy."` lookup func(string) ([]net.IP, error) oniondial func(string, string, time.Duration) (net.Conn, error) dial func(string, string, time.Duration) (net.Conn, error) diff --git a/mempool/mempool.go b/mempool/mempool.go index 7bb7044543..35eaf23414 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -38,6 +38,16 @@ const ( // orphanExpireScanInterval is the minimum amount of time in between // scans of the orphan pool to evict expired transactions. orphanExpireScanInterval = time.Minute * 5 + + // MaxRBFSequence is the maximum sequence number an input can use to + // signal that the transaction spending it can be replaced using the + // Replace-By-Fee (RBF) policy. + MaxRBFSequence = 0xfffffffd + + // MaxReplacementEvictions is the maximum number of transactions that + // can be evicted from the mempool when accepting a transaction + // replacement. + MaxReplacementEvictions = 100 ) // Tag represents an identifier to use for tagging orphan transactions. The @@ -133,6 +143,11 @@ type Policy struct { // MinRelayTxFee defines the minimum transaction fee in BTC/kB to be // considered a non-zero fee. MinRelayTxFee btcutil.Amount + + // RejectReplacement, if true, rejects accepting replacement + // transactions using the Replace-By-Fee (RBF) signaling policy into + // the mempool. + RejectReplacement bool } // TxDesc is a descriptor containing a transaction in the mempool along with @@ -554,21 +569,200 @@ func (mp *TxPool) addTransaction(utxoView *blockchain.UtxoViewpoint, tx *btcutil // checkPoolDoubleSpend checks whether or not the passed transaction is // attempting to spend coins already spent by other transactions in the pool. -// Note it does not check for double spends against transactions already in the -// main chain. +// If it does, we'll check whether each of those transactions are signaling for +// replacement. If just one of them isn't, an error is returned. Otherwise, a +// boolean is returned signaling that the transaction is a replacement. Note it +// does not check for double spends against transactions already in the main +// chain. // // This function MUST be called with the mempool lock held (for reads). -func (mp *TxPool) checkPoolDoubleSpend(tx *btcutil.Tx) error { +func (mp *TxPool) checkPoolDoubleSpend(tx *btcutil.Tx) (bool, error) { + var isReplacement bool for _, txIn := range tx.MsgTx().TxIn { - if txR, exists := mp.outpoints[txIn.PreviousOutPoint]; exists { + conflict, ok := mp.outpoints[txIn.PreviousOutPoint] + if !ok { + continue + } + + // Reject the transaction if we don't accept replacement + // transactions or if it doesn't signal replacement. + if mp.cfg.Policy.RejectReplacement || + !mp.signalsReplacement(conflict, nil) { str := fmt.Sprintf("output %v already spent by "+ "transaction %v in the memory pool", - txIn.PreviousOutPoint, txR.Hash()) - return txRuleError(wire.RejectDuplicate, str) + txIn.PreviousOutPoint, conflict.Hash()) + return false, txRuleError(wire.RejectDuplicate, str) } + + isReplacement = true } - return nil + return isReplacement, nil +} + +// signalsReplacement determines if a transaction is signaling that it can be +// replaced using the Replace-By-Fee (RBF) policy. This policy specifies two +// ways a transaction can signal that it is replaceable: +// +// Explicit signaling: A transaction is considered to have opted in to allowing +// replacement of itself if any of its inputs have a sequence number less than +// 0xfffffffe. +// +// Inherited signaling: Transactions that don't explicitly signal replaceability +// are replaceable under this policy for as long as any one of their ancestors +// signals replaceability and remains unconfirmed. +// +// The cache is optional and serves as an optimization to avoid visiting +// transactions we've already determined don't signal replacement. +// +// This function MUST be called with the mempool lock held (for reads). +func (mp *TxPool) signalsReplacement(tx *btcutil.Tx, + cache map[chainhash.Hash]struct{}) bool { + + // If a cache was not provided, we'll initialize one now to use for the + // recursive calls. + if cache == nil { + cache = make(map[chainhash.Hash]struct{}) + } + + for _, txIn := range tx.MsgTx().TxIn { + if txIn.Sequence <= MaxRBFSequence { + return true + } + + hash := txIn.PreviousOutPoint.Hash + unconfirmedAncestor, ok := mp.pool[hash] + if !ok { + continue + } + + // If we've already determined the transaction doesn't signal + // replacement, we can avoid visiting it again. + if _, ok := cache[hash]; ok { + continue + } + + if mp.signalsReplacement(unconfirmedAncestor.Tx, cache) { + return true + } + + // Since the transaction doesn't signal replacement, we'll cache + // its result to ensure we don't attempt to determine so again. + cache[hash] = struct{}{} + } + + return false +} + +// txAncestors returns all of the unconfirmed ancestors of the given +// transaction. Given transactions A, B, and C where C spends B and B spends A, +// A and B are considered ancestors of C. +// +// The cache is optional and serves as an optimization to avoid visiting +// transactions we've already determined ancestors of. +// +// This function MUST be called with the mempool lock held (for reads). +func (mp *TxPool) txAncestors(tx *btcutil.Tx, + cache map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx) map[chainhash.Hash]*btcutil.Tx { + + // If a cache was not provided, we'll initialize one now to use for the + // recursive calls. + if cache == nil { + cache = make(map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx) + } + + ancestors := make(map[chainhash.Hash]*btcutil.Tx) + for _, txIn := range tx.MsgTx().TxIn { + parent, ok := mp.pool[txIn.PreviousOutPoint.Hash] + if !ok { + continue + } + ancestors[*parent.Tx.Hash()] = parent.Tx + + // Determine if the ancestors of this ancestor have already been + // computed. If they haven't, we'll do so now and cache them to + // use them later on if necessary. + moreAncestors, ok := cache[*parent.Tx.Hash()] + if !ok { + moreAncestors = mp.txAncestors(parent.Tx, cache) + cache[*parent.Tx.Hash()] = moreAncestors + } + + for hash, ancestor := range moreAncestors { + ancestors[hash] = ancestor + } + } + + return ancestors +} + +// txDescendants returns all of the unconfirmed descendants of the given +// transaction. Given transactions A, B, and C where C spends B and B spends A, +// B and C are considered descendants of A. A cache can be provided in order to +// easily retrieve the descendants of transactions we've already determined the +// descendants of. +// +// This function MUST be called with the mempool lock held (for reads). +func (mp *TxPool) txDescendants(tx *btcutil.Tx, + cache map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx) map[chainhash.Hash]*btcutil.Tx { + + // If a cache was not provided, we'll initialize one now to use for the + // recursive calls. + if cache == nil { + cache = make(map[chainhash.Hash]map[chainhash.Hash]*btcutil.Tx) + } + + // We'll go through all of the outputs of the transaction to determine + // if they are spent by any other mempool transactions. + descendants := make(map[chainhash.Hash]*btcutil.Tx) + op := wire.OutPoint{Hash: *tx.Hash()} + for i := range tx.MsgTx().TxOut { + op.Index = uint32(i) + descendant, ok := mp.outpoints[op] + if !ok { + continue + } + descendants[*descendant.Hash()] = descendant + + // Determine if the descendants of this descendant have already + // been computed. If they haven't, we'll do so now and cache + // them to use them later on if necessary. + moreDescendants, ok := cache[*descendant.Hash()] + if !ok { + moreDescendants = mp.txDescendants(descendant, cache) + cache[*descendant.Hash()] = moreDescendants + } + + for _, moreDescendant := range moreDescendants { + descendants[*moreDescendant.Hash()] = moreDescendant + } + } + + return descendants +} + +// txConflicts returns all of the unconfirmed transactions that would become +// conflicts if we were to accept the given transaction into the mempool. An +// unconfirmed conflict is known as a transaction that spends an output already +// spent by a different transaction within the mempool. Any descendants of these +// transactions are also considered conflicts as they would no longer exist. +// These are generally not allowed except for transactions that signal RBF +// support. +// +// This function MUST be called with the mempool lock held (for reads). +func (mp *TxPool) txConflicts(tx *btcutil.Tx) map[chainhash.Hash]*btcutil.Tx { + conflicts := make(map[chainhash.Hash]*btcutil.Tx) + for _, txIn := range tx.MsgTx().TxIn { + conflict, ok := mp.outpoints[txIn.PreviousOutPoint] + if !ok { + continue + } + conflicts[*conflict.Hash()] = conflict + for hash, descendant := range mp.txDescendants(conflict, nil) { + conflicts[hash] = descendant + } + } + return conflicts } // CheckSpend checks whether the passed outpoint is already spent by a @@ -631,6 +825,100 @@ func (mp *TxPool) FetchTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error) return nil, fmt.Errorf("transaction is not in the pool") } +// validateReplacement determines whether a transaction is deemed as a valid +// replacement of all of its conflicts according to the RBF policy. If it is +// valid, no error is returned. Otherwise, an error is returned indicating what +// went wrong. +// +// This function MUST be called with the mempool lock held (for reads). +func (mp *TxPool) validateReplacement(tx *btcutil.Tx, + txFee int64) (map[chainhash.Hash]*btcutil.Tx, error) { + + // First, we'll make sure the set of conflicting transactions doesn't + // exceed the maximum allowed. + conflicts := mp.txConflicts(tx) + if len(conflicts) > MaxReplacementEvictions { + str := fmt.Sprintf("replacement transaction %v evicts more "+ + "transactions than permitted: max is %v, evicts %v", + tx.Hash(), MaxReplacementEvictions, len(conflicts)) + return nil, txRuleError(wire.RejectNonstandard, str) + } + + // The set of conflicts (transactions we'll replace) and ancestors + // should not overlap, otherwise the replacement would be spending an + // output that no longer exists. + for ancestorHash := range mp.txAncestors(tx, nil) { + if _, ok := conflicts[ancestorHash]; !ok { + continue + } + str := fmt.Sprintf("replacement transaction %v spends parent "+ + "transaction %v", tx.Hash(), ancestorHash) + return nil, txRuleError(wire.RejectInvalid, str) + } + + // The replacement should have a higher fee rate than each of the + // conflicting transactions and a higher absolute fee than the fee sum + // of all the conflicting transactions. + // + // We usually don't want to accept replacements with lower fee rates + // than what they replaced as that would lower the fee rate of the next + // block. Requiring that the fee rate always be increased is also an + // easy-to-reason about way to prevent DoS attacks via replacements. + var ( + txSize = GetTxVirtualSize(tx) + txFeeRate = txFee * 1000 / txSize + conflictsFee int64 + conflictsParents = make(map[chainhash.Hash]struct{}) + ) + for hash, conflict := range conflicts { + if txFeeRate <= mp.pool[hash].FeePerKB { + str := fmt.Sprintf("replacement transaction %v has an "+ + "insufficient fee rate: needs more than %v, "+ + "has %v", tx.Hash(), mp.pool[hash].FeePerKB, + txFeeRate) + return nil, txRuleError(wire.RejectInsufficientFee, str) + } + + conflictsFee += mp.pool[hash].Fee + + // We'll track each conflict's parents to ensure the replacement + // isn't spending any new unconfirmed inputs. + for _, txIn := range conflict.MsgTx().TxIn { + conflictsParents[txIn.PreviousOutPoint.Hash] = struct{}{} + } + } + + // It should also have an absolute fee greater than all of the + // transactions it intends to replace and pay for its own bandwidth, + // which is determined by our minimum relay fee. + minFee := calcMinRequiredTxRelayFee(txSize, mp.cfg.Policy.MinRelayTxFee) + if txFee < conflictsFee+minFee { + str := fmt.Sprintf("replacement transaction %v has an "+ + "insufficient absolute fee: needs %v, has %v", + tx.Hash(), conflictsFee+minFee, txFee) + return nil, txRuleError(wire.RejectInsufficientFee, str) + } + + // Finally, it should not spend any new unconfirmed outputs, other than + // the ones already included in the parents of the conflicting + // transactions it'll replace. + for _, txIn := range tx.MsgTx().TxIn { + if _, ok := conflictsParents[txIn.PreviousOutPoint.Hash]; ok { + continue + } + // Confirmed outputs are valid to spend in the replacement. + if _, ok := mp.pool[txIn.PreviousOutPoint.Hash]; !ok { + continue + } + str := fmt.Sprintf("replacement transaction spends new "+ + "unconfirmed input %v not found in conflicting "+ + "transactions", txIn.PreviousOutPoint) + return nil, txRuleError(wire.RejectInvalid, str) + } + + return conflicts, nil +} + // maybeAcceptTransaction is the internal function which implements the public // MaybeAcceptTransaction. See the comment for MaybeAcceptTransaction for // more details. @@ -714,13 +1002,14 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec // The transaction may not use any of the same outputs as other // transactions already in the pool as that would ultimately result in a - // double spend. This check is intended to be quick and therefore only - // detects double spends within the transaction pool itself. The - // transaction could still be double spending coins from the main chain - // at this point. There is a more in-depth check that happens later - // after fetching the referenced transaction inputs from the main chain - // which examines the actual spend data and prevents double spends. - err = mp.checkPoolDoubleSpend(tx) + // double spend, unless those transactions signal for RBF. This check is + // intended to be quick and therefore only detects double spends within + // the transaction pool itself. The transaction could still be double + // spending coins from the main chain at this point. There is a more + // in-depth check that happens later after fetching the referenced + // transaction inputs from the main chain which examines the actual + // spend data and prevents double spends. + isReplacement, err := mp.checkPoolDoubleSpend(tx) if err != nil { return nil, nil, err } @@ -899,6 +1188,16 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec mp.cfg.Policy.FreeTxRelayLimit*10*1000) } + // If the transaction has any conflicts and we've made it this far, then + // we're processing a potential replacement. + var conflicts map[chainhash.Hash]*btcutil.Tx + if isReplacement { + conflicts, err = mp.validateReplacement(tx, txFee) + if err != nil { + return nil, nil, err + } + } + // Verify crypto signatures for each input and reject the transaction if // any don't verify. err = blockchain.ValidateTransactionScripts(tx, utxoView, @@ -911,7 +1210,20 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec return nil, nil, err } - // Add to transaction pool. + // Now that we've deemed the transaction as valid, we can add it to the + // mempool. If it ended up replacing any transactions, we'll remove them + // first. + for _, conflict := range conflicts { + log.Debugf("Replacing transaction %v (fee_rate=%v sat/kb) "+ + "with %v (fee_rate=%v sat/kb)\n", conflict.Hash(), + mp.pool[*conflict.Hash()].FeePerKB, tx.Hash(), + txFee*1000/serializedSize) + + // The conflict set should already include the descendants for + // each one, so we don't need to remove the redeemers within + // this call as they'll be removed eventually. + mp.removeTransaction(conflict, false) + } txD := mp.addTransaction(utxoView, tx, bestHeight, txFee) log.Debugf("Accepted transaction %v (pool size: %v)", txHash, diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 7a29598bf2..84aee10ab2 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -7,7 +7,7 @@ package mempool import ( "encoding/hex" "reflect" - "runtime" + "strings" "sync" "testing" "time" @@ -187,22 +187,30 @@ func (p *poolHarness) CreateCoinbaseTx(blockHeight int32, numOutputs uint32) (*b // inputs and generates the provided number of outputs by evenly splitting the // total input amount. All outputs will be to the payment script associated // with the harness and all inputs are assumed to do the same. -func (p *poolHarness) CreateSignedTx(inputs []spendableOutput, numOutputs uint32) (*btcutil.Tx, error) { +func (p *poolHarness) CreateSignedTx(inputs []spendableOutput, + numOutputs uint32, fee btcutil.Amount, + signalsReplacement bool) (*btcutil.Tx, error) { + // Calculate the total input amount and split it amongst the requested // number of outputs. var totalInput btcutil.Amount for _, input := range inputs { totalInput += input.amount } + totalInput -= fee amountPerOutput := int64(totalInput) / int64(numOutputs) remainder := int64(totalInput) - amountPerOutput*int64(numOutputs) tx := wire.NewMsgTx(wire.TxVersion) + sequence := wire.MaxTxInSequenceNum + if signalsReplacement { + sequence = MaxRBFSequence + } for _, input := range inputs { tx.AddTxIn(&wire.TxIn{ PreviousOutPoint: input.outPoint, SignatureScript: nil, - Sequence: wire.MaxTxInSequenceNum, + Sequence: sequence, }) } for i := uint32(0); i < numOutputs; i++ { @@ -356,33 +364,89 @@ type testContext struct { harness *poolHarness } +// addCoinbaseTx adds a spendable coinbase transaction to the test context's +// mock chain. +func (ctx *testContext) addCoinbaseTx(numOutputs uint32) *btcutil.Tx { + ctx.t.Helper() + + coinbaseHeight := ctx.harness.chain.BestHeight() + 1 + coinbase, err := ctx.harness.CreateCoinbaseTx(coinbaseHeight, numOutputs) + if err != nil { + ctx.t.Fatalf("unable to create coinbase: %v", err) + } + + ctx.harness.chain.utxos.AddTxOuts(coinbase, coinbaseHeight) + maturity := int32(ctx.harness.chainParams.CoinbaseMaturity) + ctx.harness.chain.SetHeight(coinbaseHeight + maturity) + ctx.harness.chain.SetMedianTimePast(time.Now()) + + return coinbase +} + +// addSignedTx creates a transaction that spends the inputs with the given fee. +// It can be added to the test context's mempool or mock chain based on the +// confirmed boolean. +func (ctx *testContext) addSignedTx(inputs []spendableOutput, + numOutputs uint32, fee btcutil.Amount, + signalsReplacement, confirmed bool) *btcutil.Tx { + + ctx.t.Helper() + + tx, err := ctx.harness.CreateSignedTx( + inputs, numOutputs, fee, signalsReplacement, + ) + if err != nil { + ctx.t.Fatalf("unable to create transaction: %v", err) + } + + if confirmed { + newHeight := ctx.harness.chain.BestHeight() + 1 + ctx.harness.chain.utxos.AddTxOuts(tx, newHeight) + ctx.harness.chain.SetHeight(newHeight) + ctx.harness.chain.SetMedianTimePast(time.Now()) + } else { + acceptedTxns, err := ctx.harness.txPool.ProcessTransaction( + tx, true, false, 0, + ) + if err != nil { + ctx.t.Fatalf("unable to process transaction: %v", err) + } + if len(acceptedTxns) != 1 { + ctx.t.Fatalf("expected one accepted transaction, got %d", + len(acceptedTxns)) + } + testPoolMembership(ctx, tx, false, true) + } + + return tx +} + // testPoolMembership tests the transaction pool associated with the provided // test context to determine if the passed transaction matches the provided // orphan pool and transaction pool status. It also further determines if it // should be reported as available by the HaveTransaction function based upon // the two flags and tests that condition as well. func testPoolMembership(tc *testContext, tx *btcutil.Tx, inOrphanPool, inTxPool bool) { + tc.t.Helper() + txHash := tx.Hash() gotOrphanPool := tc.harness.txPool.IsOrphanInPool(txHash) if inOrphanPool != gotOrphanPool { - _, file, line, _ := runtime.Caller(1) - tc.t.Fatalf("%s:%d -- IsOrphanInPool: want %v, got %v", file, - line, inOrphanPool, gotOrphanPool) + tc.t.Fatalf("IsOrphanInPool: want %v, got %v", inOrphanPool, + gotOrphanPool) } gotTxPool := tc.harness.txPool.IsTransactionInPool(txHash) if inTxPool != gotTxPool { - _, file, line, _ := runtime.Caller(1) - tc.t.Fatalf("%s:%d -- IsTransactionInPool: want %v, got %v", - file, line, inTxPool, gotTxPool) + tc.t.Fatalf("IsTransactionInPool: want %v, got %v", inTxPool, + gotTxPool) } gotHaveTx := tc.harness.txPool.HaveTransaction(txHash) wantHaveTx := inOrphanPool || inTxPool if wantHaveTx != gotHaveTx { - _, file, line, _ := runtime.Caller(1) - tc.t.Fatalf("%s:%d -- HaveTransaction: want %v, got %v", file, - line, wantHaveTx, gotHaveTx) + tc.t.Fatalf("HaveTransaction: want %v, got %v", wantHaveTx, + gotHaveTx) } } @@ -618,7 +682,7 @@ func TestBasicOrphanRemoval(t *testing.T) { nonChainedOrphanTx, err := harness.CreateSignedTx([]spendableOutput{{ amount: btcutil.Amount(5000000000), outPoint: wire.OutPoint{Hash: chainhash.Hash{}, Index: 0}, - }}, 1) + }}, 1, 0, false) if err != nil { t.Fatalf("unable to create signed tx: %v", err) } @@ -754,7 +818,7 @@ func TestMultiInputOrphanDoubleSpend(t *testing.T) { doubleSpendTx, err := harness.CreateSignedTx([]spendableOutput{ txOutToSpendableOut(chainedTxns[1], 0), txOutToSpendableOut(chainedTxns[maxOrphans], 0), - }, 1) + }, 1, 0, false) if err != nil { t.Fatalf("unable to create signed tx: %v", err) } @@ -866,3 +930,883 @@ func TestCheckSpend(t *testing.T) { t.Fatalf("Unexpeced spend found in pool: %v", spend) } } + +// TestSignalsReplacement tests that transactions properly signal they can be +// replaced using RBF. +func TestSignalsReplacement(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + setup func(ctx *testContext) *btcutil.Tx + signalsReplacement bool + }{ + { + // Transactions can signal replacement through + // inheritance if any of its ancestors does. + name: "non-signaling with unconfirmed non-signaling parent", + setup: func(ctx *testContext) *btcutil.Tx { + coinbase := ctx.addCoinbaseTx(1) + + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx(outs, 1, 0, false, false) + + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + return ctx.addSignedTx(outs, 1, 0, false, false) + }, + signalsReplacement: false, + }, + { + // Transactions can signal replacement through + // inheritance if any of its ancestors does, but they + // must be unconfirmed. + name: "non-signaling with confirmed signaling parent", + setup: func(ctx *testContext) *btcutil.Tx { + coinbase := ctx.addCoinbaseTx(1) + + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx(outs, 1, 0, true, true) + + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + return ctx.addSignedTx(outs, 1, 0, false, false) + }, + signalsReplacement: false, + }, + { + name: "inherited signaling", + setup: func(ctx *testContext) *btcutil.Tx { + coinbase := ctx.addCoinbaseTx(1) + + // We'll create a chain of transactions + // A -> B -> C where C is the transaction we'll + // be checking for replacement signaling. The + // transaction can signal replacement through + // any of its ancestors as long as they also + // signal replacement. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + a := ctx.addSignedTx(outs, 1, 0, true, false) + + aOut := txOutToSpendableOut(a, 0) + outs = []spendableOutput{aOut} + b := ctx.addSignedTx(outs, 1, 0, false, false) + + bOut := txOutToSpendableOut(b, 0) + outs = []spendableOutput{bOut} + return ctx.addSignedTx(outs, 1, 0, false, false) + }, + signalsReplacement: true, + }, + { + name: "explicit signaling", + setup: func(ctx *testContext) *btcutil.Tx { + coinbase := ctx.addCoinbaseTx(1) + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + return ctx.addSignedTx(outs, 1, 0, true, false) + }, + signalsReplacement: true, + }, + } + + for _, testCase := range testCases { + success := t.Run(testCase.name, func(t *testing.T) { + // We'll start each test by creating our mempool + // harness. + harness, _, err := newPoolHarness(&chaincfg.MainNetParams) + if err != nil { + t.Fatalf("unable to create test pool: %v", err) + } + ctx := &testContext{t, harness} + + // Each test includes a setup method, which will set up + // its required dependencies. The transaction returned + // is the one we'll be using to determine if it signals + // replacement support. + tx := testCase.setup(ctx) + + // Each test should match the expected response. + signalsReplacement := ctx.harness.txPool.signalsReplacement( + tx, nil, + ) + if signalsReplacement && !testCase.signalsReplacement { + ctx.t.Fatalf("expected transaction %v to not "+ + "signal replacement", tx.Hash()) + } + if !signalsReplacement && testCase.signalsReplacement { + ctx.t.Fatalf("expected transaction %v to "+ + "signal replacement", tx.Hash()) + } + }) + if !success { + break + } + } +} + +// TestCheckPoolDoubleSpend ensures that the mempool can properly detect +// unconfirmed double spends in the case of replacement and non-replacement +// transactions. +func TestCheckPoolDoubleSpend(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + setup func(ctx *testContext) *btcutil.Tx + isReplacement bool + }{ + { + // Transactions that don't double spend any inputs, + // regardless of whether they signal replacement or not, + // are valid. + name: "no double spend", + setup: func(ctx *testContext) *btcutil.Tx { + coinbase := ctx.addCoinbaseTx(1) + + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx(outs, 1, 0, false, false) + + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + return ctx.addSignedTx(outs, 2, 0, false, false) + }, + isReplacement: false, + }, + { + // Transactions that don't signal replacement and double + // spend inputs are invalid. + name: "non-replacement double spend", + setup: func(ctx *testContext) *btcutil.Tx { + coinbase1 := ctx.addCoinbaseTx(1) + coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) + outs := []spendableOutput{coinbaseOut1} + ctx.addSignedTx(outs, 1, 0, true, false) + + coinbase2 := ctx.addCoinbaseTx(1) + coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) + outs = []spendableOutput{coinbaseOut2} + ctx.addSignedTx(outs, 1, 0, false, false) + + // Create a transaction that spends both + // coinbase outputs that were spent above. This + // should be detected as a double spend as one + // of the transactions doesn't signal + // replacement. + outs = []spendableOutput{coinbaseOut1, coinbaseOut2} + tx, err := ctx.harness.CreateSignedTx( + outs, 1, 0, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx + }, + isReplacement: false, + }, + { + // Transactions that double spend inputs and signal + // replacement are invalid if the mempool's policy + // rejects replacements. + name: "reject replacement policy", + setup: func(ctx *testContext) *btcutil.Tx { + // Set the mempool's policy to reject + // replacements. Even if we have a transaction + // that spends inputs that signal replacement, + // it should still be rejected. + ctx.harness.txPool.cfg.Policy.RejectReplacement = true + + coinbase := ctx.addCoinbaseTx(1) + + // Create a replaceable parent that spends the + // coinbase output. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx(outs, 1, 0, true, false) + + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + ctx.addSignedTx(outs, 1, 0, false, false) + + // Create another transaction that spends the + // same coinbase output. Since the original + // spender of this output, all of its spends + // should also be conflicts. + outs = []spendableOutput{coinbaseOut} + tx, err := ctx.harness.CreateSignedTx( + outs, 2, 0, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx + }, + isReplacement: false, + }, + { + // Transactions that double spend inputs and signal + // replacement are valid as long as the mempool's policy + // accepts them. + name: "replacement double spend", + setup: func(ctx *testContext) *btcutil.Tx { + coinbase := ctx.addCoinbaseTx(1) + + // Create a replaceable parent that spends the + // coinbase output. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx(outs, 1, 0, true, false) + + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + ctx.addSignedTx(outs, 1, 0, false, false) + + // Create another transaction that spends the + // same coinbase output. Since the original + // spender of this output, all of its spends + // should also be conflicts. + outs = []spendableOutput{coinbaseOut} + tx, err := ctx.harness.CreateSignedTx( + outs, 2, 0, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx + }, + isReplacement: true, + }, + } + + for _, testCase := range testCases { + success := t.Run(testCase.name, func(t *testing.T) { + // We'll start each test by creating our mempool + // harness. + harness, _, err := newPoolHarness(&chaincfg.MainNetParams) + if err != nil { + t.Fatalf("unable to create test pool: %v", err) + } + ctx := &testContext{t, harness} + + // Each test includes a setup method, which will set up + // its required dependencies. The transaction returned + // is the one we'll be querying for the expected + // conflicts. + tx := testCase.setup(ctx) + + // Ensure that the mempool properly detected the double + // spend unless this is a replacement transaction. + isReplacement, err := + ctx.harness.txPool.checkPoolDoubleSpend(tx) + if testCase.isReplacement && err != nil { + t.Fatalf("expected no error for replacement "+ + "transaction, got: %v", err) + } + if isReplacement && !testCase.isReplacement { + t.Fatalf("expected replacement transaction") + } + if !isReplacement && testCase.isReplacement { + t.Fatalf("expected non-replacement transaction") + } + }) + if !success { + break + } + } +} + +// TestConflicts ensures that the mempool can properly detect conflicts when +// processing new incoming transactions. +func TestConflicts(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + + // setup sets up the required dependencies for each test. It + // returns the transaction we'll check for conflicts and its + // expected unique conflicts. + setup func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) + }{ + { + // Create a transaction that would introduce no + // conflicts in the mempool. This is done by not + // spending any outputs that are currently being spent + // within the mempool. + name: "no conflicts", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase := ctx.addCoinbaseTx(1) + + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx(outs, 1, 0, false, false) + + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + tx, err := ctx.harness.CreateSignedTx( + outs, 2, 0, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + }, + { + // Create a transaction that would introduce two + // conflicts in the mempool by spending two outputs + // which are each already being spent by a different + // transaction within the mempool. + name: "conflicts", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase1 := ctx.addCoinbaseTx(1) + coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) + outs := []spendableOutput{coinbaseOut1} + conflict1 := ctx.addSignedTx( + outs, 1, 0, false, false, + ) + + coinbase2 := ctx.addCoinbaseTx(1) + coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) + outs = []spendableOutput{coinbaseOut2} + conflict2 := ctx.addSignedTx( + outs, 1, 0, false, false, + ) + + // Create a transaction that spends both + // coinbase outputs that were spent above. + outs = []spendableOutput{coinbaseOut1, coinbaseOut2} + tx, err := ctx.harness.CreateSignedTx( + outs, 1, 0, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, []*btcutil.Tx{conflict1, conflict2} + }, + }, + { + // Create a transaction that would introduce two + // conflicts in the mempool by spending an output + // already being spent in the mempool by a different + // transaction. The second conflict stems from spending + // the transaction that spends the original spender of + // the output, i.e., a descendant of the original + // spender. + name: "descendant conflicts", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase := ctx.addCoinbaseTx(1) + + // Create a replaceable parent that spends the + // coinbase output. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx(outs, 1, 0, false, false) + + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + child := ctx.addSignedTx(outs, 1, 0, false, false) + + // Create another transaction that spends the + // same coinbase output. Since the original + // spender of this output has descendants, they + // should also be conflicts. + outs = []spendableOutput{coinbaseOut} + tx, err := ctx.harness.CreateSignedTx( + outs, 2, 0, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, []*btcutil.Tx{parent, child} + }, + }, + } + + for _, testCase := range testCases { + success := t.Run(testCase.name, func(t *testing.T) { + // We'll start each test by creating our mempool + // harness. + harness, _, err := newPoolHarness(&chaincfg.MainNetParams) + if err != nil { + t.Fatalf("unable to create test pool: %v", err) + } + ctx := &testContext{t, harness} + + // Each test includes a setup method, which will set up + // its required dependencies. The transaction returned + // is the one we'll be querying for the expected + // conflicts. + tx, conflicts := testCase.setup(ctx) + + // Assert the expected conflicts are returned. + txConflicts := ctx.harness.txPool.txConflicts(tx) + if len(txConflicts) != len(conflicts) { + ctx.t.Fatalf("expected %d conflicts, got %d", + len(conflicts), len(txConflicts)) + } + for _, conflict := range conflicts { + conflictHash := *conflict.Hash() + if _, ok := txConflicts[conflictHash]; !ok { + ctx.t.Fatalf("expected %v to be found "+ + "as a conflict", conflictHash) + } + } + }) + if !success { + break + } + } +} + +// TestAncestorsDescendants ensures that we can properly retrieve the +// unconfirmed ancestors and descendants of a transaction. +func TestAncestorsDescendants(t *testing.T) { + t.Parallel() + + // We'll start the test by initializing our mempool harness. + harness, outputs, err := newPoolHarness(&chaincfg.MainNetParams) + if err != nil { + t.Fatalf("unable to create test pool: %v", err) + } + ctx := &testContext{t, harness} + + // We'll be creating the following chain of unconfirmed transactions: + // + // B ---- + // / \ + // A E + // \ / + // C -- D + // + // where B and C spend A, D spends C, and E spends B and D. We set up a + // chain like so to properly detect ancestors and descendants past a + // single parent/child. + aInputs := outputs[:1] + a := ctx.addSignedTx(aInputs, 2, 0, false, false) + + bInputs := []spendableOutput{txOutToSpendableOut(a, 0)} + b := ctx.addSignedTx(bInputs, 1, 0, false, false) + + cInputs := []spendableOutput{txOutToSpendableOut(a, 1)} + c := ctx.addSignedTx(cInputs, 1, 0, false, false) + + dInputs := []spendableOutput{txOutToSpendableOut(c, 0)} + d := ctx.addSignedTx(dInputs, 1, 0, false, false) + + eInputs := []spendableOutput{ + txOutToSpendableOut(b, 0), txOutToSpendableOut(d, 0), + } + e := ctx.addSignedTx(eInputs, 1, 0, false, false) + + // We'll be querying for the ancestors of E. We should expect to see all + // of the transactions that it depends on. + expectedAncestors := map[chainhash.Hash]struct{}{ + *a.Hash(): struct{}{}, *b.Hash(): struct{}{}, + *c.Hash(): struct{}{}, *d.Hash(): struct{}{}, + } + ancestors := ctx.harness.txPool.txAncestors(e, nil) + if len(ancestors) != len(expectedAncestors) { + ctx.t.Fatalf("expected %d ancestors, got %d", + len(expectedAncestors), len(ancestors)) + } + for ancestorHash := range ancestors { + if _, ok := expectedAncestors[ancestorHash]; !ok { + ctx.t.Fatalf("found unexpected ancestor %v", + ancestorHash) + } + } + + // Then, we'll query for the descendants of A. We should expect to see + // all of the transactions that depend on it. + expectedDescendants := map[chainhash.Hash]struct{}{ + *b.Hash(): struct{}{}, *c.Hash(): struct{}{}, + *d.Hash(): struct{}{}, *e.Hash(): struct{}{}, + } + descendants := ctx.harness.txPool.txDescendants(a, nil) + if len(descendants) != len(expectedDescendants) { + ctx.t.Fatalf("expected %d descendants, got %d", + len(expectedDescendants), len(descendants)) + } + for descendantHash := range descendants { + if _, ok := expectedDescendants[descendantHash]; !ok { + ctx.t.Fatalf("found unexpected descendant %v", + descendantHash) + } + } +} + +// TestRBF tests the different cases required for a transaction to properly +// replace its conflicts given that they all signal replacement. +func TestRBF(t *testing.T) { + t.Parallel() + + const defaultFee = btcutil.SatoshiPerBitcoin + + testCases := []struct { + name string + setup func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) + err string + }{ + { + // A transaction cannot replace another if it doesn't + // signal replacement. + name: "non-replaceable parent", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase := ctx.addCoinbaseTx(1) + + // Create a transaction that spends the coinbase + // output and doesn't signal for replacement. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + ctx.addSignedTx(outs, 1, defaultFee, false, false) + + // Attempting to create another transaction that + // spends the same output should fail since the + // original transaction spending it doesn't + // signal replacement. + tx, err := ctx.harness.CreateSignedTx( + outs, 2, defaultFee, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + err: "already spent by transaction", + }, + { + // A transaction cannot replace another if we don't + // allow accepting replacement transactions. + name: "reject replacement policy", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + ctx.harness.txPool.cfg.Policy.RejectReplacement = true + + coinbase := ctx.addCoinbaseTx(1) + + // Create a transaction that spends the coinbase + // output and doesn't signal for replacement. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + ctx.addSignedTx(outs, 1, defaultFee, true, false) + + // Attempting to create another transaction that + // spends the same output should fail since the + // original transaction spending it doesn't + // signal replacement. + tx, err := ctx.harness.CreateSignedTx( + outs, 2, defaultFee, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + err: "already spent by transaction", + }, + { + // A transaction cannot replace another if doing so + // would cause more than 100 transactions being + // replaced. + name: "exceeds maximum conflicts", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + const numDescendants = 100 + coinbaseOuts := make( + []spendableOutput, numDescendants, + ) + for i := 0; i < numDescendants; i++ { + tx := ctx.addCoinbaseTx(1) + coinbaseOuts[i] = txOutToSpendableOut(tx, 0) + } + parent := ctx.addSignedTx( + coinbaseOuts, numDescendants, + defaultFee, true, false, + ) + + // We'll then spend each output of the parent + // transaction with a distinct transaction. + for i := uint32(0); i < numDescendants; i++ { + out := txOutToSpendableOut(parent, i) + outs := []spendableOutput{out} + ctx.addSignedTx( + outs, 1, defaultFee, false, false, + ) + } + + // We'll then create a replacement transaction + // by spending one of the coinbase outputs. + // Replacing the original spender of the + // coinbase output would evict the maximum + // number of transactions from the mempool, + // however, so we should reject it. + tx, err := ctx.harness.CreateSignedTx( + coinbaseOuts[:1], 1, defaultFee, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + err: "evicts more transactions than permitted", + }, + { + // A transaction cannot replace another if the + // replacement ends up spending an output that belongs + // to one of the transactions it replaces. + name: "replacement spends parent transaction", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase := ctx.addCoinbaseTx(1) + + // Create a transaction that spends the coinbase + // output and signals replacement. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx( + outs, 1, defaultFee, true, false, + ) + + // Attempting to create another transaction that + // spends it, but also replaces it, should be + // invalid. + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{coinbaseOut, parentOut} + tx, err := ctx.harness.CreateSignedTx( + outs, 2, defaultFee, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + err: "spends parent transaction", + }, + { + // A transaction cannot replace another if it has a + // lower fee rate than any of the transactions it + // intends to replace. + name: "insufficient fee rate", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase1 := ctx.addCoinbaseTx(1) + coinbase2 := ctx.addCoinbaseTx(1) + + // We'll create two transactions that each spend + // one of the coinbase outputs. The first will + // have a higher fee rate than the second. + coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) + outs := []spendableOutput{coinbaseOut1} + ctx.addSignedTx(outs, 1, defaultFee*2, true, false) + + coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) + outs = []spendableOutput{coinbaseOut2} + ctx.addSignedTx(outs, 1, defaultFee, true, false) + + // We'll then create the replacement transaction + // by spending the coinbase outputs. It will be + // an invalid one however, since it won't have a + // higher fee rate than the first transaction. + outs = []spendableOutput{coinbaseOut1, coinbaseOut2} + tx, err := ctx.harness.CreateSignedTx( + outs, 1, defaultFee*2, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + err: "insufficient fee rate", + }, + { + // A transaction cannot replace another if it doesn't + // have an absolute greater than the transactions its + // replacing _plus_ the replacement transaction's + // minimum relay fee. + name: "insufficient absolute fee", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase := ctx.addCoinbaseTx(1) + + // We'll create a transaction with two outputs + // and the default fee. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + ctx.addSignedTx(outs, 2, defaultFee, true, false) + + // We'll create a replacement transaction with + // one output, which should cause the + // transaction's absolute fee to be lower than + // the above's, so it'll be invalid. + tx, err := ctx.harness.CreateSignedTx( + outs, 1, defaultFee, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + err: "insufficient absolute fee", + }, + { + // A transaction cannot replace another if it introduces + // a new unconfirmed input that was not already in any + // of the transactions it's directly replacing. + name: "spends new unconfirmed input", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase1 := ctx.addCoinbaseTx(1) + coinbase2 := ctx.addCoinbaseTx(1) + + // We'll create two unconfirmed transactions + // from our coinbase transactions. + coinbaseOut1 := txOutToSpendableOut(coinbase1, 0) + outs := []spendableOutput{coinbaseOut1} + ctx.addSignedTx(outs, 1, defaultFee, true, false) + + coinbaseOut2 := txOutToSpendableOut(coinbase2, 0) + outs = []spendableOutput{coinbaseOut2} + newTx := ctx.addSignedTx( + outs, 1, defaultFee, false, false, + ) + + // We should not be able to accept a replacement + // transaction that spends an unconfirmed input + // that was not previously included. + newTxOut := txOutToSpendableOut(newTx, 0) + outs = []spendableOutput{coinbaseOut1, newTxOut} + tx, err := ctx.harness.CreateSignedTx( + outs, 1, defaultFee*2, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, nil + }, + err: "spends new unconfirmed input", + }, + { + // A transaction can replace another with a higher fee. + name: "higher fee", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase := ctx.addCoinbaseTx(1) + + // Create a transaction that we'll directly + // replace. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx( + outs, 1, defaultFee, true, false, + ) + + // Spend the parent transaction to create a + // descendant that will be indirectly replaced. + parentOut := txOutToSpendableOut(parent, 0) + outs = []spendableOutput{parentOut} + child := ctx.addSignedTx( + outs, 1, defaultFee, false, false, + ) + + // The replacement transaction should replace + // both transactions above since it has a higher + // fee and doesn't violate any other conditions + // within the RBF policy. + outs = []spendableOutput{coinbaseOut} + tx, err := ctx.harness.CreateSignedTx( + outs, 1, defaultFee*3, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create "+ + "transaction: %v", err) + } + + return tx, []*btcutil.Tx{parent, child} + }, + err: "", + }, + } + + for _, testCase := range testCases { + success := t.Run(testCase.name, func(t *testing.T) { + // We'll start each test by creating our mempool + // harness. + harness, _, err := newPoolHarness(&chaincfg.MainNetParams) + if err != nil { + t.Fatalf("unable to create test pool: %v", err) + } + + // We'll enable relay priority to ensure we can properly + // test fees between replacement transactions and the + // transactions it replaces. + harness.txPool.cfg.Policy.DisableRelayPriority = false + + // Each test includes a setup method, which will set up + // its required dependencies. The transaction returned + // is the intended replacement, which should replace the + // expected list of transactions. + ctx := &testContext{t, harness} + replacementTx, replacedTxs := testCase.setup(ctx) + + // Attempt to process the replacement transaction. If + // it's not a valid one, we should see the error + // expected by the test. + _, err = ctx.harness.txPool.ProcessTransaction( + replacementTx, false, false, 0, + ) + if testCase.err == "" && err != nil { + ctx.t.Fatalf("expected no error when "+ + "processing replacement transaction, "+ + "got: %v", err) + } + if testCase.err != "" && err == nil { + ctx.t.Fatalf("expected error when processing "+ + "replacement transaction: %v", + testCase.err) + } + if testCase.err != "" && err != nil { + if !strings.Contains(err.Error(), testCase.err) { + ctx.t.Fatalf("expected error: %v\n"+ + "got: %v", testCase.err, err) + } + } + + // If the replacement transaction is valid, we'll check + // that it has been included in the mempool and its + // conflicts have been removed. Otherwise, the conflicts + // should remain in the mempool. + valid := testCase.err == "" + for _, tx := range replacedTxs { + testPoolMembership(ctx, tx, false, !valid) + } + testPoolMembership(ctx, replacementTx, false, valid) + }) + if !success { + break + } + } +} diff --git a/server.go b/server.go index d8fac25640..bed4de9593 100644 --- a/server.go +++ b/server.go @@ -2709,6 +2709,7 @@ func newServer(listenAddrs, agentBlacklist, agentWhitelist []string, MaxSigOpCostPerTx: blockchain.MaxBlockSigOpsCost / 4, MinRelayTxFee: cfg.minRelayTxFee, MaxTxVersion: 2, + RejectReplacement: cfg.RejectReplacement, }, ChainParams: chainParams, FetchUtxoView: s.chain.FetchUtxoView, From 594e2ab48a8e309c910c4fee7ce73a529e26aa52 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 28 Jun 2019 15:43:47 -0700 Subject: [PATCH 0281/1056] rpc: extract primary rescan logic into scanBlockChunks helper func --- rpcwebsocket.go | 211 +++++++++++++++++++++++++++--------------------- 1 file changed, 119 insertions(+), 92 deletions(-) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index eddac5ab06..85e1eaa36e 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -2321,85 +2321,20 @@ func descendantBlock(prevHash *chainhash.Hash, curBlock *btcutil.Block) error { return nil } -// handleRescan implements the rescan command extension for websocket -// connections. -// -// NOTE: This does not smartly handle reorgs, and fixing requires database -// changes (for safe, concurrent access to full block ranges, and support -// for other chains than the best chain). It will, however, detect whether -// a reorg removed a block that was previously processed, and result in the -// handler erroring. Clients must handle this by finding a block still in -// the chain (perhaps from a rescanprogress notification) to resume their -// rescan. -func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) { - cmd, ok := icmd.(*btcjson.RescanCmd) - if !ok { - return nil, btcjson.ErrRPCInternal - } - - outpoints := make([]*wire.OutPoint, 0, len(cmd.OutPoints)) - for i := range cmd.OutPoints { - cmdOutpoint := &cmd.OutPoints[i] - blockHash, err := chainhash.NewHashFromStr(cmdOutpoint.Hash) - if err != nil { - return nil, rpcDecodeHexError(cmdOutpoint.Hash) - } - outpoint := wire.NewOutPoint(blockHash, cmdOutpoint.Index) - outpoints = append(outpoints, outpoint) - } - - numAddrs := len(cmd.Addresses) - if numAddrs == 1 { - rpcsLog.Info("Beginning rescan for 1 address") - } else { - rpcsLog.Infof("Beginning rescan for %d addresses", numAddrs) - } - - // Build lookup maps. - lookups := rescanKeys{ - addrs: map[string]struct{}{}, - unspent: map[wire.OutPoint]struct{}{}, - } - for _, addrStr := range cmd.Addresses { - lookups.addrs[addrStr] = struct{}{} - } - for _, outpoint := range outpoints { - lookups.unspent[*outpoint] = struct{}{} - } - - chain := wsc.server.cfg.Chain - - minBlockHash, err := chainhash.NewHashFromStr(cmd.BeginBlock) - if err != nil { - return nil, rpcDecodeHexError(cmd.BeginBlock) - } - minBlock, err := chain.BlockHeightByHash(minBlockHash) - if err != nil { - return nil, &btcjson.RPCError{ - Code: btcjson.ErrRPCBlockNotFound, - Message: "Error getting block: " + err.Error(), - } - } - - maxBlock := int32(math.MaxInt32) - if cmd.EndBlock != nil { - maxBlockHash, err := chainhash.NewHashFromStr(*cmd.EndBlock) - if err != nil { - return nil, rpcDecodeHexError(*cmd.EndBlock) - } - maxBlock, err = chain.BlockHeightByHash(maxBlockHash) - if err != nil { - return nil, &btcjson.RPCError{ - Code: btcjson.ErrRPCBlockNotFound, - Message: "Error getting block: " + err.Error(), - } - } - } +// scanBlockChunks executes a rescan in chunked stages. We do this to limit the +// amount of memory that we'll allocate to a given rescan. Every so often, +// we'll send back a rescan progress notification to the websockets client. The +// final block and block hash that we've scanned will be returned. +func scanBlockChunks(wsc *wsClient, cmd *btcjson.RescanCmd, lookups *rescanKeys, minBlock, + maxBlock int32, chain *blockchain.BlockChain) ( + *btcutil.Block, *chainhash.Hash, error) { // lastBlock and lastBlockHash track the previously-rescanned block. // They equal nil when no previous blocks have been rescanned. - var lastBlock *btcutil.Block - var lastBlockHash *chainhash.Hash + var ( + lastBlock *btcutil.Block + lastBlockHash *chainhash.Hash + ) // A ticker is created to wait at least 10 seconds before notifying the // websocket client of the current progress completed by the rescan. @@ -2422,7 +2357,7 @@ fetchRange: hashList, err := chain.HeightRange(minBlock, maxLoopBlock) if err != nil { rpcsLog.Errorf("Error looking up block range: %v", err) - return nil, &btcjson.RPCError{ + return nil, nil, &btcjson.RPCError{ Code: btcjson.ErrRPCDatabase, Message: "Database error: " + err.Error(), } @@ -2461,7 +2396,7 @@ fetchRange: if err != nil { rpcsLog.Errorf("Error fetching best block "+ "hash: %v", err) - return nil, &btcjson.RPCError{ + return nil, nil, &btcjson.RPCError{ Code: btcjson.ErrRPCDatabase, Message: "Database error: " + err.Error(), @@ -2484,7 +2419,7 @@ fetchRange: rpcsLog.Errorf("Error looking up "+ "block: %v", err) - return nil, &btcjson.RPCError{ + return nil, nil, &btcjson.RPCError{ Code: btcjson.ErrRPCDatabase, Message: "Database error: " + err.Error(), @@ -2497,7 +2432,7 @@ fetchRange: rpcsLog.Errorf("Stopping rescan for "+ "reorged block %v", cmd.EndBlock) - return nil, &ErrRescanReorg + return nil, nil, &ErrRescanReorg } // If the lookup for the previously valid block @@ -2511,10 +2446,11 @@ fetchRange: // before the range was evaluated, as it must be // reevaluated for the new hashList. minBlock += int32(i) - hashList, err = recoverFromReorg(chain, - minBlock, maxBlock, lastBlockHash) + hashList, err = recoverFromReorg( + chain, minBlock, maxBlock, lastBlockHash, + ) if err != nil { - return nil, err + return nil, nil, err } if len(hashList) == 0 { break fetchRange @@ -2526,7 +2462,7 @@ fetchRange: // as the last block from the old hashList. jsonErr := descendantBlock(lastBlockHash, blk) if jsonErr != nil { - return nil, jsonErr + return nil, nil, jsonErr } } @@ -2536,9 +2472,9 @@ fetchRange: case <-wsc.quit: rpcsLog.Debugf("Stopped rescan at height %v "+ "for disconnected client", blk.Height()) - return nil, nil + return nil, nil, nil default: - rescanBlock(wsc, &lookups, blk) + rescanBlock(wsc, lookups, blk) lastBlock = blk lastBlockHash = blk.Hash() } @@ -2552,8 +2488,10 @@ fetchRange: continue } - n := btcjson.NewRescanProgressNtfn(hashList[i].String(), - blk.Height(), blk.MsgBlock().Header.Timestamp.Unix()) + n := btcjson.NewRescanProgressNtfn( + hashList[i].String(), blk.Height(), + blk.MsgBlock().Header.Timestamp.Unix(), + ) mn, err := btcjson.MarshalCmd(nil, n) if err != nil { rpcsLog.Errorf("Failed to marshal rescan "+ @@ -2565,13 +2503,101 @@ fetchRange: // Finished if the client disconnected. rpcsLog.Debugf("Stopped rescan at height %v "+ "for disconnected client", blk.Height()) - return nil, nil + return nil, nil, nil } } minBlock += int32(len(hashList)) } + return lastBlock, lastBlockHash, nil +} + +// handleRescan implements the rescan command extension for websocket +// connections. +// +// NOTE: This does not smartly handle reorgs, and fixing requires database +// changes (for safe, concurrent access to full block ranges, and support +// for other chains than the best chain). It will, however, detect whether +// a reorg removed a block that was previously processed, and result in the +// handler erroring. Clients must handle this by finding a block still in +// the chain (perhaps from a rescanprogress notification) to resume their +// rescan. +func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) { + cmd, ok := icmd.(*btcjson.RescanCmd) + if !ok { + return nil, btcjson.ErrRPCInternal + } + + outpoints := make([]*wire.OutPoint, 0, len(cmd.OutPoints)) + for i := range cmd.OutPoints { + cmdOutpoint := &cmd.OutPoints[i] + blockHash, err := chainhash.NewHashFromStr(cmdOutpoint.Hash) + if err != nil { + return nil, rpcDecodeHexError(cmdOutpoint.Hash) + } + outpoint := wire.NewOutPoint(blockHash, cmdOutpoint.Index) + outpoints = append(outpoints, outpoint) + } + + numAddrs := len(cmd.Addresses) + if numAddrs == 1 { + rpcsLog.Info("Beginning rescan for 1 address") + } else { + rpcsLog.Infof("Beginning rescan for %d addresses", numAddrs) + } + + // Build lookup maps. + lookups := rescanKeys{ + addrs: map[string]struct{}{}, + unspent: map[wire.OutPoint]struct{}{}, + } + for _, addrStr := range cmd.Addresses { + lookups.addrs[addrStr] = struct{}{} + } + for _, outpoint := range outpoints { + lookups.unspent[*outpoint] = struct{}{} + } + + chain := wsc.server.cfg.Chain + + minBlockHash, err := chainhash.NewHashFromStr(cmd.BeginBlock) + if err != nil { + return nil, rpcDecodeHexError(cmd.BeginBlock) + } + minBlock, err := chain.BlockHeightByHash(minBlockHash) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCBlockNotFound, + Message: "Error getting block: " + err.Error(), + } + } + + maxBlock := int32(math.MaxInt32) + if cmd.EndBlock != nil { + maxBlockHash, err := chainhash.NewHashFromStr(*cmd.EndBlock) + if err != nil { + return nil, rpcDecodeHexError(*cmd.EndBlock) + } + maxBlock, err = chain.BlockHeightByHash(maxBlockHash) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCBlockNotFound, + Message: "Error getting block: " + err.Error(), + } + } + } + + // With all the arguments parsed, we'll execute our chunked rescan + // which will notify the clients of any address deposits or output + // spends. + lastBlock, lastBlockHash, err = scanBlockChunks( + wsc, cmd, &lookups, minBlock, maxBlock, chain, + ) + if err != nil { + return nil, err + } + // Notify websocket client of the finished rescan. Due to how btcd // asynchronously queues notifications to not block calling code, // there is no guarantee that any of the notifications created during @@ -2579,9 +2605,10 @@ fetchRange: // received before the rescan RPC returns. Therefore, another method // is needed to safely inform clients that all rescan notifications have // been sent. - n := btcjson.NewRescanFinishedNtfn(lastBlockHash.String(), - lastBlock.Height(), - lastBlock.MsgBlock().Header.Timestamp.Unix()) + n := btcjson.NewRescanFinishedNtfn( + lastBlockHash.String(), lastBlock.Height(), + lastBlock.MsgBlock().Header.Timestamp.Unix(), + ) if mn, err := btcjson.MarshalCmd(nil, n); err != nil { rpcsLog.Errorf("Failed to marshal rescan finished "+ "notification: %v", err) From 18c37d2eb7b5a0102f36237b67e43f41700bddca Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 28 Jun 2019 15:45:20 -0700 Subject: [PATCH 0282/1056] rpc: skip rescan if client has no addresses or UTXOs In this commit, we implement an optimization that will speed up clients that attempt to perform a rescan in the past with no addresses. If the client doesn't have any thing to search for, then we simply exit early and send them a rescan finished notification with the final block in our chain. --- rpcwebsocket.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 85e1eaa36e..b4bdadbc9a 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -2588,6 +2588,11 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) { } } + var ( + lastBlock *btcutil.Block + lastBlockHash *chainhash.Hash + ) + if len(lookups.addrs) != 0 || len(lookups.unspent) != 0 { // With all the arguments parsed, we'll execute our chunked rescan // which will notify the clients of any address deposits or output // spends. @@ -2597,6 +2602,22 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) { if err != nil { return nil, err } + } else { + rpcsLog.Infof("Skipping rescan as client has no addrs/utxos") + + // If we didn't actually do a rescan, then we'll give the + // client our best known block within the final rescan finished + // notification. + chainTip := chain.BestSnapshot() + lastBlockHash = &chainTip.Hash + lastBlock, err = chain.BlockByHash(lastBlockHash) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCBlockNotFound, + Message: "Error getting block: " + err.Error(), + } + } + } // Notify websocket client of the finished rescan. Due to how btcd // asynchronously queues notifications to not block calling code, From 677503515ebfc855ce80a6a126c276a672877893 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 7 Jul 2019 18:03:04 -0700 Subject: [PATCH 0283/1056] rpc: fix rescan bug if client disconnects In this commit, we fix a bug in the rescan logic after a recent refactoring that would cause the scanning node to potentially panic. If the client disconnected, before the rescan was finished, then we would return a nil `lastBlock` and `lastBlockHash`. We would then attempt to send the rescan finished notification, causing a panic. We remedy this by simply detecting this case (client disconnect), and existing once again as the prior code would, pre-refactoring. --- rpcwebsocket.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index b4bdadbc9a..32e466d115 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -2602,6 +2602,13 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) { if err != nil { return nil, err } + + // If the last block is nil, then this means that the client + // disconnected mid-rescan. As a result, we don't need to send + // anything back to them. + if lastBlock == nil { + return nil, nil + } } else { rpcsLog.Infof("Skipping rescan as client has no addrs/utxos") From 2cd83210b57d499665fc6d2951983334996bf7fe Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 20 Aug 2019 15:26:23 -0700 Subject: [PATCH 0284/1056] wire: only write message payload if there actually is one There are certain messages that won't have a payload, e.g., verack, causing an unnecessary write of 0 bytes. --- wire/message.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/wire/message.go b/wire/message.go index 4f03cf5643..e937647702 100644 --- a/wire/message.go +++ b/wire/message.go @@ -321,9 +321,13 @@ func WriteMessageWithEncodingN(w io.Writer, msg Message, pver uint32, return totalBytes, err } - // Write payload. - n, err = w.Write(payload) - totalBytes += n + // Only write the payload if there is one, e.g., verack messages don't + // have one. + if len(payload) > 0 { + n, err = w.Write(payload) + totalBytes += n + } + return totalBytes, err } From 5de9e5b6c2a415bc3f5d0c86951699dd70e3f4a1 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 20 Aug 2019 15:28:42 -0700 Subject: [PATCH 0285/1056] peer: include verack as part of version handshake It was possible for connections to bitcoind nodes to be closed from their side if the OnVersion callback queued a message to send. This is because bitcoind expects a verack message before attempting to process any other messages. To address this, we ensure the verack is sent as part of the handshake process, such that any queued messages happen after the fact. --- peer/peer.go | 99 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 75 insertions(+), 24 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index 61bc619ffb..11306ace49 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -1377,20 +1377,12 @@ out: break out case *wire.MsgVerAck: - - // No read lock is necessary because verAckReceived is not written - // to in any other goroutine. - if p.verAckReceived { - log.Infof("Already received 'verack' from peer %v -- "+ - "disconnecting", p) - break out - } - p.flagsMtx.Lock() - p.verAckReceived = true - p.flagsMtx.Unlock() - if p.cfg.Listeners.OnVerAck != nil { - p.cfg.Listeners.OnVerAck(p, msg) - } + // Limit to one verack message per peer. + p.PushRejectMsg( + msg.Command(), wire.RejectDuplicate, + "duplicate verack message", nil, true, + ) + break out case *wire.MsgGetAddr: if p.cfg.Listeners.OnGetAddr != nil { @@ -1974,6 +1966,40 @@ func (p *Peer) readRemoteVersionMsg() error { return nil } +// readRemoteVerAckMsg waits for the next message to arrive from the remote +// peer. If this message is not a verack message, then an error is returned. +// This method is to be used as part of the version negotiation upon a new +// connection. +func (p *Peer) readRemoteVerAckMsg() error { + // Read the next message from the wire. + remoteMsg, _, err := p.readMessage(wire.LatestEncoding) + if err != nil { + return err + } + + // It should be a verack message, otherwise send a reject message to the + // peer explaining why. + msg, ok := remoteMsg.(*wire.MsgVerAck) + if !ok { + reason := "a verack message must follow version" + rejectMsg := wire.NewMsgReject( + msg.Command(), wire.RejectMalformed, reason, + ) + _ = p.writeMessage(rejectMsg, wire.LatestEncoding) + return errors.New(reason) + } + + p.flagsMtx.Lock() + p.verAckReceived = true + p.flagsMtx.Unlock() + + if p.cfg.Listeners.OnVerAck != nil { + p.cfg.Listeners.OnVerAck(p, msg) + } + + return nil +} + // localVersionMsg creates a version message that can be used to send to the // remote peer. func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { @@ -2046,26 +2072,53 @@ func (p *Peer) writeLocalVersionMsg() error { return p.writeMessage(localVerMsg, wire.LatestEncoding) } -// negotiateInboundProtocol waits to receive a version message from the peer -// then sends our version message. If the events do not occur in that order then -// it returns an error. +// negotiateInboundProtocol performs the negotiation protocol for an inbound +// peer. The events should occur in the following order, otherwise an error is +// returned: +// +// 1. Remote peer sends their version. +// 2. We send our version. +// 3. We send our verack. +// 4. Remote peer sends their verack. func (p *Peer) negotiateInboundProtocol() error { if err := p.readRemoteVersionMsg(); err != nil { return err } - return p.writeLocalVersionMsg() + if err := p.writeLocalVersionMsg(); err != nil { + return err + } + + err := p.writeMessage(wire.NewMsgVerAck(), wire.LatestEncoding) + if err != nil { + return err + } + + return p.readRemoteVerAckMsg() } -// negotiateOutboundProtocol sends our version message then waits to receive a -// version message from the peer. If the events do not occur in that order then -// it returns an error. +// negotiateOutoundProtocol performs the negotiation protocol for an outbound +// peer. The events should occur in the following order, otherwise an error is +// returned: +// +// 1. We send our version. +// 2. Remote peer sends their version. +// 3. Remote peer sends their verack. +// 4. We send our verack. func (p *Peer) negotiateOutboundProtocol() error { if err := p.writeLocalVersionMsg(); err != nil { return err } - return p.readRemoteVersionMsg() + if err := p.readRemoteVersionMsg(); err != nil { + return err + } + + if err := p.readRemoteVerAckMsg(); err != nil { + return err + } + + return p.writeMessage(wire.NewMsgVerAck(), wire.LatestEncoding) } // start begins processing input and output messages. @@ -2102,8 +2155,6 @@ func (p *Peer) start() error { go p.outHandler() go p.pingHandler() - // Send our verack message now that the IO processing machinery has started. - p.QueueMessage(wire.NewMsgVerAck(), nil) return nil } From e3d3088b80acb3d7943d38c495525d013a564892 Mon Sep 17 00:00:00 2001 From: preminem <31085564+preminem@users.noreply.github.com> Date: Thu, 26 Sep 2019 08:19:03 +0800 Subject: [PATCH 0286/1056] btcjson+rpc: expose a transaction's weight via RPC --- btcjson/chainsvrresults.go | 3 +++ docs/json_rpc_api.md | 2 +- mempool/mempool.go | 1 + rpcserver.go | 1 + rpcserverhelp.go | 3 +++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 30c6369a32..cc9c085531 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -265,6 +265,7 @@ type GetPeerInfoResult struct { type GetRawMempoolVerboseResult struct { Size int32 `json:"size"` Vsize int32 `json:"vsize"` + Weight int32 `json:"weight"` Fee float64 `json:"fee"` Time int64 `json:"time"` Height int64 `json:"height"` @@ -505,6 +506,7 @@ type TxRawResult struct { Hash string `json:"hash,omitempty"` Size int32 `json:"size,omitempty"` Vsize int32 `json:"vsize,omitempty"` + Weight int32 `json:"weight,omitempty"` Version int32 `json:"version"` LockTime uint32 `json:"locktime"` Vin []Vin `json:"vin"` @@ -523,6 +525,7 @@ type SearchRawTransactionsResult struct { Hash string `json:"hash"` Size string `json:"size"` Vsize string `json:"vsize"` + Weight string `json:"weight"` Version int32 `json:"version"` LockTime uint32 `json:"locktime"` Vin []VinPrevOut `json:"vin"` diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index 9b8b36b3bb..51d4c82c3f 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -484,7 +484,7 @@ Example Return|`{`
  `"bytes": 310768,`
  `"size": |Description|Returns an array of hashes for all of the transactions currently in the memory pool.
The `verbose` flag specifies that each transaction is returned as a JSON object.| |Notes|Since btcd does not perform any mining, the priority related fields `startingpriority` and `currentpriority` that are available when the `verbose` flag is set are always 0.| |Returns (verbose=false)|`[ (json array of string)`
  `"transactionhash", (string) hash of the transaction`
  `...`
`]`| -|Returns (verbose=true)|`{ (json object)`
  `"transactionhash": { (json object)`
    `"size": n, (numeric) transaction size in bytes`
    `"vsize": n, (numeric) transaction virtual size`
    `"fee" : n, (numeric) transaction fee in bitcoins`
    `"time": n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT`
    `"height": n, (numeric) block height when transaction entered the pool`
    `"startingpriority": n, (numeric) priority when transaction entered the pool`
    `"currentpriority": n, (numeric) current priority`
    `"depends": [ (json array) unconfirmed transactions used as inputs for this transaction`
      `"transactionhash", (string) hash of the parent transaction`
      `...`
    `]`
  `}, ...`
`}`| +|Returns (verbose=true)|`{ (json object)`
  `"transactionhash": { (json object)`
    `"size": n, (numeric) transaction size in bytes`
    `"vsize": n, (numeric) transaction virtual size`
    `"weight": n, (numeric) The transaction's weight (between vsize*4-3 and vsize*4)`
    `"fee" : n, (numeric) transaction fee in bitcoins`
    `"time": n, (numeric) local time transaction entered pool in seconds since 1 Jan 1970 GMT`
    `"height": n, (numeric) block height when transaction entered the pool`
    `"startingpriority": n, (numeric) priority when transaction entered the pool`
    `"currentpriority": n, (numeric) current priority`
    `"depends": [ (json array) unconfirmed transactions used as inputs for this transaction`
      `"transactionhash", (string) hash of the parent transaction`
      `...`
    `]`
  `}, ...`
`}`| |Example Return (verbose=false)|`[`
  `"3480058a397b6ffcc60f7e3345a61370fded1ca6bef4b58156ed17987f20d4e7",`
  `"cbfe7c056a358c3a1dbced5a22b06d74b8650055d5195c1c2469e6b63a41514a"`
`]`| |Example Return (verbose=true)|`{`
  `"1697a19cede08694278f19584e8dcc87945f40c6b59a942dd8906f133ad3f9cc": {`
    `"size": 226,`
    `"fee" : 0.0001,`
    `"time": 1387992789,`
    `"height": 276836,`
    `"startingpriority": 0,`
    `"currentpriority": 0,`
    `"depends": [`
      `"aa96f672fcc5a1ec6a08a94aa46d6b789799c87bd6542967da25a96b2dee0afb",`
    `]`
`}`| [Return to Overview](#MethodOverview)
diff --git a/mempool/mempool.go b/mempool/mempool.go index 35eaf23414..63a86a16f5 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -1509,6 +1509,7 @@ func (mp *TxPool) RawMempoolVerbose() map[string]*btcjson.GetRawMempoolVerboseRe mpd := &btcjson.GetRawMempoolVerboseResult{ Size: int32(tx.MsgTx().SerializeSize()), Vsize: int32(GetTxVirtualSize(tx)), + Weight: int32(blockchain.GetTransactionWeight(tx)), Fee: btcutil.Amount(desc.Fee).ToBTC(), Time: desc.Added.Unix(), Height: int64(desc.Height), diff --git a/rpcserver.go b/rpcserver.go index a3cf1e0f7a..097ba2ec84 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -756,6 +756,7 @@ func createTxRawResult(chainParams *chaincfg.Params, mtx *wire.MsgTx, Hash: mtx.WitnessHash().String(), Size: int32(mtx.SerializeSize()), Vsize: int32(mempool.GetTxVirtualSize(btcutil.NewTx(mtx))), + Weight: int32(blockchain.GetTransactionWeight(btcutil.NewTx(mtx))), Vin: createVinList(mtx), Vout: createVoutList(mtx, chainParams, nil), Version: mtx.Version, diff --git a/rpcserverhelp.go b/rpcserverhelp.go index c875d217aa..e7637db69c 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -207,6 +207,7 @@ var helpDescsEnUS = map[string]string{ "txrawresult-blocktime": "Block time in seconds since the 1 Jan 1970 GMT", "txrawresult-size": "The size of the transaction in bytes", "txrawresult-vsize": "The virtual size of the transaction in bytes", + "txrawresult-weight": "The transaction's weight (between vsize*4-3 and vsize*4)", "txrawresult-hash": "The wtxid of the transaction", // SearchRawTransactionsResult help. @@ -223,6 +224,7 @@ var helpDescsEnUS = map[string]string{ "searchrawtransactionsresult-blocktime": "Block time in seconds since the 1 Jan 1970 GMT", "searchrawtransactionsresult-size": "The size of the transaction in bytes", "searchrawtransactionsresult-vsize": "The virtual size of the transaction in bytes", + "searchrawtransactionsresult-weight": "The transaction's weight (between vsize*4-3 and vsize*4)", // GetBlockVerboseResult help. "getblockverboseresult-hash": "The hash of the block (same as provided)", @@ -476,6 +478,7 @@ var helpDescsEnUS = map[string]string{ "getrawmempoolverboseresult-currentpriority": "Current priority", "getrawmempoolverboseresult-depends": "Unconfirmed transactions used as inputs for this transaction", "getrawmempoolverboseresult-vsize": "The virtual size of a transaction", + "getrawmempoolverboseresult-weight": "The transaction's weight (between vsize*4-3 and vsize*4)", // GetRawMempoolCmd help. "getrawmempool--synopsis": "Returns information about all of the transactions currently in the memory pool.", From 009f1993178a97d7466ff500fae086e4425676f1 Mon Sep 17 00:00:00 2001 From: "Iskander (Alex) Sharipov" Date: Thu, 26 Sep 2019 03:23:57 +0300 Subject: [PATCH 0287/1056] btcd: remove commented-out code Found using https://go-critic.github.io/overview#commentedOutCode-ref --- upnp.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/upnp.go b/upnp.go index a1f37e6507..feb256d072 100644 --- a/upnp.go +++ b/upnp.go @@ -298,7 +298,6 @@ func soapRequest(url, function, message string) (replyXML []byte, err error) { } req.Header.Set("Content-Type", "text/xml ; charset=\"utf-8\"") req.Header.Set("User-Agent", "Darwin/10.0.0, UPnP/1.0, MiniUPnPc/1.3") - //req.Header.Set("Transfer-Encoding", "chunked") req.Header.Set("SOAPAction", "\"urn:schemas-upnp-org:service:WANIPConnection:1#"+function+"\"") req.Header.Set("Connection", "Close") req.Header.Set("Cache-Control", "no-cache") @@ -313,7 +312,6 @@ func soapRequest(url, function, message string) (replyXML []byte, err error) { } if r.StatusCode >= 400 { - // log.Stderr(function, r.StatusCode) err = errors.New("Error " + strconv.Itoa(r.StatusCode) + " for " + function) r = nil return From ba530c4abb35ea824a1d3c01d74969b5564c3b08 Mon Sep 17 00:00:00 2001 From: Sad Pencil Date: Thu, 26 Sep 2019 08:28:57 +0800 Subject: [PATCH 0288/1056] btcec: correct the comment of recoverKeyFromSignature --- btcec/signature.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcec/signature.go b/btcec/signature.go index f1c4377499..deedd172d8 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -276,7 +276,7 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int { } // recoverKeyFromSignature recovers a public key from the signature "sig" on the -// given message hash "msg". Based on the algorithm found in section 5.1.5 of +// given message hash "msg". Based on the algorithm found in section 4.1.6 of // SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details // in the inner loop in Step 1. The counter provided is actually the j parameter // of the loop * 2 - on the first iteration of j we do the R case, else the -R From e159f05c6e40ccdf1176199767f4273ff32e549d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 25 Sep 2019 18:43:43 -0700 Subject: [PATCH 0289/1056] build: use go 1.13.x in travis --- .travis.yml | 2 +- go.mod | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f65821e926..5063496735 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ cache: - $GOPATH/github.com/golang - $GOPATH/gopkg.in/alecthomas go: - - "1.11.x" + - "1.13.x" sudo: false install: - export PATH=$PATH:$PWD/linux-amd64/ diff --git a/go.mod b/go.mod index 9488a8bd39..606399481f 100644 --- a/go.mod +++ b/go.mod @@ -17,3 +17,5 @@ require ( github.com/onsi/gomega v1.4.3 // indirect golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 ) + +go 1.12 From 4aeb189fc41791cb29945ed710f0d529b61e1aac Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 May 2019 22:46:50 -0700 Subject: [PATCH 0290/1056] btcec: benchmark ParsePubKey for compressed keys --- btcec/bench_test.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/btcec/bench_test.go b/btcec/bench_test.go index bebd886f1c..7ccd78cfb9 100644 --- a/btcec/bench_test.go +++ b/btcec/bench_test.go @@ -4,7 +4,10 @@ package btcec -import "testing" +import ( + "encoding/hex" + "testing" +) // BenchmarkAddJacobian benchmarks the secp256k1 curve addJacobian function with // Z values of 1 so that the associated optimizations are used. @@ -121,3 +124,22 @@ func BenchmarkFieldNormalize(b *testing.B) { f.Normalize() } } + +// BenchmarkParseCompressedPubKey benchmarks how long it takes to decompress and +// validate a compressed public key from a byte array. +func BenchmarkParseCompressedPubKey(b *testing.B) { + rawPk, _ := hex.DecodeString("0234f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6") + + var ( + pk *PublicKey + err error + ) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + pk, err = ParsePubKey(rawPk, S256()) + } + _ = pk + _ = err +} From 39500ed5ed1904c5b1a6182b98913bbedee0b412 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 May 2019 22:46:54 -0700 Subject: [PATCH 0291/1056] btcec/pubkey: remove redundant checks from compressed pubkey parsing As of https://github.com/btcsuite/btcd/pull/1193, decompressPoint now validates that the point is on the curve. The x and y cooordinates are also implicitly <= P, since the modular reduction is applied to both before the method returns. The checks are moved so that they are still applied when parsing an uncompressed pubkey, as the checks are not redundant in that path. --- btcec/pubkey.go | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index cf49807522..a6a492e7c3 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -102,6 +102,17 @@ func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err err if format == pubkeyHybrid && ybit != isOdd(pubkey.Y) { return nil, fmt.Errorf("ybit doesn't match oddness") } + + if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 { + return nil, fmt.Errorf("pubkey X parameter is >= to P") + } + if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 { + return nil, fmt.Errorf("pubkey Y parameter is >= to P") + } + if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { + return nil, fmt.Errorf("pubkey isn't on secp256k1 curve") + } + case PubKeyBytesLenCompressed: // format is 0x2 | solution, // solution determines which solution of the curve we use. @@ -115,20 +126,12 @@ func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err err if err != nil { return nil, err } + default: // wrong! return nil, fmt.Errorf("invalid pub key length %d", len(pubKeyStr)) } - if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 { - return nil, fmt.Errorf("pubkey X parameter is >= to P") - } - if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 { - return nil, fmt.Errorf("pubkey Y parameter is >= to P") - } - if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { - return nil, fmt.Errorf("pubkey isn't on secp256k1 curve") - } return &pubkey, nil } From c7d523f83ccb19ea4766e6523685105bd6c76e70 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 May 2019 22:46:59 -0700 Subject: [PATCH 0292/1056] btcec/pubkey: optimize decompressPoint using fieldVals This commit optimizes the decompressPoint subroutine, used in extracting compressed pubkeys and performing pubkey recovery. We do so by replacing the use of big.Int.Exp with with square-and-multiply exponentiation of btcec's more optimized fieldVals, reducing the overall latency and memory requirements of decompressPoint. Instead of operating on bits of Q = (P+1)/4, the exponentiation applies the square-and-multiply operations on full bytes of Q. Compared to the original speedup. Compared the bit-wise version, the improvement is roughly 10%. A new pair fieldVal methods called Sqrt and SqrtVal are added, which applies the square-and-multiply exponentiation using precomputed byte-slice of the value Q. Comparison against big.Int sqrt and SAM sqrt over bytes of Q: benchmark old ns/op new ns/op delta BenchmarkParseCompressedPubKey-8 35545 23119 -34.96% benchmark old allocs new allocs delta BenchmarkParseCompressedPubKey-8 35 6 -82.86% benchmark old bytes new bytes delta BenchmarkParseCompressedPubKey-8 2777 256 -90.78% --- btcec/btcec.go | 10 ++- btcec/field.go | 129 +++++++++++++++++++++++++++++++++++++++ btcec/field_test.go | 145 ++++++++++++++++++++++++++++++++++++++++++++ btcec/pubkey.go | 36 +++++------ 4 files changed, 301 insertions(+), 19 deletions(-) diff --git a/btcec/btcec.go b/btcec/btcec.go index 5e7ce875fd..2cb1d92913 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -36,10 +36,17 @@ var ( // interface from crypto/elliptic. type KoblitzCurve struct { *elliptic.CurveParams - q *big.Int + + // q is the value (P+1)/4 used to compute the square root of field + // elements. + q *big.Int + H int // cofactor of the curve. halfOrder *big.Int // half the order N + // fieldB is the constant B of the curve as a fieldVal. + fieldB *fieldVal + // byteSize is simply the bit size / 8 and is provided for convenience // since it is calculated repeatedly. byteSize int @@ -917,6 +924,7 @@ func initS256() { big.NewInt(1)), big.NewInt(4)) secp256k1.H = 1 secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1) + secp256k1.fieldB = new(fieldVal).SetByteSlice(secp256k1.B.Bytes()) // Provided for convenience since this gets computed repeatedly. secp256k1.byteSize = secp256k1.BitSize / 8 diff --git a/btcec/field.go b/btcec/field.go index 0f2be74c0c..c2bb84b3fe 100644 --- a/btcec/field.go +++ b/btcec/field.go @@ -102,6 +102,20 @@ const ( fieldPrimeWordOne = 0x3ffffbf ) +var ( + // fieldQBytes is the value Q = (P+1)/4 for the secp256k1 prime P. This + // value is used to efficiently compute the square root of values in the + // field via exponentiation. The value of Q in hex is: + // + // Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c + fieldQBytes = []byte{ + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x0c, + } +) + // fieldVal implements optimized fixed-precision arithmetic over the // secp256k1 finite field. This means all arithmetic is performed modulo // 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f. It @@ -1221,3 +1235,118 @@ func (f *fieldVal) Inverse() *fieldVal { f.Square().Square().Square().Square().Square() // f = a^(2^256 - 4294968320) return f.Mul(&a45) // f = a^(2^256 - 4294968275) = a^(p-2) } + +// SqrtVal computes the square root of x modulo the curve's prime, and stores +// the result in f. The square root is computed via exponentiation of x by the +// value Q = (P+1)/4 using the curve's precomputed big-endian representation of +// the Q. This method uses a modified version of square-and-multiply +// exponentiation over secp256k1 fieldVals to operate on bytes instead of bits, +// which offers better performance over both big.Int exponentiation and bit-wise +// square-and-multiply. +// +// NOTE: This method only works when P is intended to be the secp256k1 prime and +// is not constant time. The returned value is of magnitude 1, but is +// denormalized. +func (f *fieldVal) SqrtVal(x *fieldVal) *fieldVal { + // The following computation iteratively computes x^((P+1)/4) = x^Q + // using the recursive, piece-wise definition: + // + // x^n = (x^2)^(n/2) mod P if n is even + // x^n = x(x^2)^(n-1/2) mod P if n is odd + // + // Given n in its big-endian representation b_k, ..., b_0, x^n can be + // computed by defining the sequence r_k+1, ..., r_0, where: + // + // r_k+1 = 1 + // r_i = (r_i+1)^2 * x^b_i for i = k, ..., 0 + // + // The final value r_0 = x^n. + // + // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more + // details. + // + // This can be further optimized, by observing that the value of Q in + // secp256k1 has the value: + // + // Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c + // + // We can unroll the typical bit-wise interpretation of the + // exponentiation algorithm above to instead operate on bytes. + // This reduces the number of comparisons by an order of magnitude, + // reducing the overhead of failed branch predictions and additional + // comparisons in this method. + // + // Since there there are only 4 unique bytes of Q, this keeps the jump + // table small without the need to handle all possible 8-bit values. + // Further, we observe that 29 of the 32 bytes are 0xff; making the + // first case handle 0xff therefore optimizes the hot path. + f.SetInt(1) + for _, b := range fieldQBytes { + switch b { + + // Most common case, where all 8 bits are set. + case 0xff: + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + + // First byte of Q (0x3f), where all but the top two bits are + // set. Note that this case only applies six operations, since + // the highest bit of Q resides in bit six of the first byte. We + // ignore the first two bits, since squaring for these bits will + // result in an invalid result. We forgo squaring f before the + // first multiply, since 1^2 = 1. + case 0x3f: + f.Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + + // Byte 28 of Q (0xbf), where only bit 7 is unset. + case 0xbf: + f.Square().Mul(x) + f.Square() + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + f.Square().Mul(x) + + // Byte 31 of Q (0x0c), where only bits 3 and 4 are set. + default: + f.Square() + f.Square() + f.Square() + f.Square() + f.Square().Mul(x) + f.Square().Mul(x) + f.Square() + f.Square() + } + } + + return f +} + +// Sqrt computes the square root of f modulo the curve's prime, and stores the +// result in f. The square root is computed via exponentiation of x by the value +// Q = (P+1)/4 using the curve's precomputed big-endian representation of the Q. +// This method uses a modified version of square-and-multiply exponentiation +// over secp256k1 fieldVals to operate on bytes instead of bits, which offers +// better performance over both big.Int exponentiation and bit-wise +// square-and-multiply. +// +// NOTE: This method only works when P is intended to be the secp256k1 prime and +// is not constant time. The returned value is of magnitude 1, but is +// denormalized. +func (f *fieldVal) Sqrt() *fieldVal { + return f.SqrtVal(f) +} diff --git a/btcec/field_test.go b/btcec/field_test.go index dcfb704971..27b9730f65 100644 --- a/btcec/field_test.go +++ b/btcec/field_test.go @@ -6,6 +6,8 @@ package btcec import ( + "crypto/rand" + "fmt" "reflect" "testing" ) @@ -820,3 +822,146 @@ func TestInverse(t *testing.T) { } } } + +// randFieldVal returns a random, normalized element in the field. +func randFieldVal(t *testing.T) fieldVal { + var b [32]byte + if _, err := rand.Read(b[:]); err != nil { + t.Fatalf("unable to create random element: %v", err) + } + + var x fieldVal + return *x.SetBytes(&b).Normalize() +} + +type sqrtTest struct { + name string + in string + expected string +} + +// TestSqrt asserts that a fieldVal properly computes the square root modulo the +// sep256k1 prime. +func TestSqrt(t *testing.T) { + var tests []sqrtTest + + // No valid root exists for the negative of a square. + for i := uint(9); i > 0; i-- { + var ( + x fieldVal + s fieldVal // x^2 mod p + n fieldVal // -x^2 mod p + ) + + x.SetInt(i) + s.SquareVal(&x).Normalize() + n.NegateVal(&s, 1).Normalize() + + tests = append(tests, sqrtTest{ + name: fmt.Sprintf("-%d", i), + in: fmt.Sprintf("%x", *n.Bytes()), + }) + } + + // A root should exist for true squares. + for i := uint(0); i < 10; i++ { + var ( + x fieldVal + s fieldVal // x^2 mod p + ) + + x.SetInt(i) + s.SquareVal(&x).Normalize() + + tests = append(tests, sqrtTest{ + name: fmt.Sprintf("%d", i), + in: fmt.Sprintf("%x", *s.Bytes()), + expected: fmt.Sprintf("%x", *x.Bytes()), + }) + } + + // Compute a non-square element, by negating if it has a root. + ns := randFieldVal(t) + if new(fieldVal).SqrtVal(&ns).Square().Equals(&ns) { + ns.Negate(1).Normalize() + } + + // For large random field values, test that: + // 1) its square has a valid root. + // 2) the negative of its square has no root. + // 3) the product of its square with a non-square has no root. + for i := 0; i < 10; i++ { + var ( + x fieldVal + s fieldVal // x^2 mod p + n fieldVal // -x^2 mod p + m fieldVal // ns*x^2 mod p + ) + + x = randFieldVal(t) + s.SquareVal(&x).Normalize() + n.NegateVal(&s, 1).Normalize() + m.Mul2(&s, &ns).Normalize() + + // A root should exist for true squares. + tests = append(tests, sqrtTest{ + name: fmt.Sprintf("%x", *s.Bytes()), + in: fmt.Sprintf("%x", *s.Bytes()), + expected: fmt.Sprintf("%x", *x.Bytes()), + }) + + // No valid root exists for the negative of a square. + tests = append(tests, sqrtTest{ + name: fmt.Sprintf("-%x", *s.Bytes()), + in: fmt.Sprintf("%x", *n.Bytes()), + }) + + // No root should be computed for product of a square and + // non-square. + tests = append(tests, sqrtTest{ + name: fmt.Sprintf("ns*%x", *s.Bytes()), + in: fmt.Sprintf("%x", *m.Bytes()), + }) + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + testSqrt(t, test) + }) + } +} + +func testSqrt(t *testing.T, test sqrtTest) { + var ( + f fieldVal + root fieldVal + rootNeg fieldVal + ) + + f.SetHex(test.in).Normalize() + + // Compute sqrt(f) and its negative. + root.SqrtVal(&f).Normalize() + rootNeg.NegateVal(&root, 1).Normalize() + + switch { + + // If we expect a square root, verify that either the computed square + // root is +/- the expected value. + case len(test.expected) > 0: + var expected fieldVal + expected.SetHex(test.expected).Normalize() + if !root.Equals(&expected) && !rootNeg.Equals(&expected) { + t.Fatalf("fieldVal.Sqrt incorrect root\n"+ + "got: %v\ngot_neg: %v\nwant: %v", + root, rootNeg, expected) + } + + // Otherwise, we expect this input not to have a square root. + default: + if root.Square().Equals(&f) || rootNeg.Square().Equals(&f) { + t.Fatalf("fieldVal.Sqrt root should not exist\n"+ + "got: %v\ngot_neg: %v", root, rootNeg) + } + } +} diff --git a/btcec/pubkey.go b/btcec/pubkey.go index a6a492e7c3..c72f8705ab 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -22,41 +22,41 @@ func isOdd(a *big.Int) bool { return a.Bit(0) == 1 } -// decompressPoint decompresses a point on the given curve given the X point and +// decompressPoint decompresses a point on the secp256k1 curve given the X point and // the solution to use. -func decompressPoint(curve *KoblitzCurve, x *big.Int, ybit bool) (*big.Int, error) { - // TODO: This will probably only work for secp256k1 due to - // optimizations. +func decompressPoint(curve *KoblitzCurve, bigX *big.Int, ybit bool) (*big.Int, error) { + var x fieldVal + x.SetByteSlice(bigX.Bytes()) - // Y = +-sqrt(x^3 + B) - x3 := new(big.Int).Mul(x, x) - x3.Mul(x3, x) - x3.Add(x3, curve.Params().B) - x3.Mod(x3, curve.Params().P) + // Compute x^3 + B mod p. + var x3 fieldVal + x3.SquareVal(&x).Mul(&x) + x3.Add(curve.fieldB).Normalize() // Now calculate sqrt mod p of x^3 + B // This code used to do a full sqrt based on tonelli/shanks, // but this was replaced by the algorithms referenced in // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 - y := new(big.Int).Exp(x3, curve.QPlus1Div4(), curve.Params().P) - - if ybit != isOdd(y) { - y.Sub(curve.Params().P, y) + var y fieldVal + y.SqrtVal(&x3) + if ybit != y.IsOdd() { + y.Negate(1) } + y.Normalize() // Check that y is a square root of x^3 + B. - y2 := new(big.Int).Mul(y, y) - y2.Mod(y2, curve.Params().P) - if y2.Cmp(x3) != 0 { + var y2 fieldVal + y2.SquareVal(&y).Normalize() + if !y2.Equals(&x3) { return nil, fmt.Errorf("invalid square root") } // Verify that y-coord has expected parity. - if ybit != isOdd(y) { + if ybit != y.IsOdd() { return nil, fmt.Errorf("ybit doesn't match oddness") } - return y, nil + return new(big.Int).SetBytes(y.Bytes()[:]), nil } const ( From 2340ad388c7179de515dec1c58ce9c92f0825f91 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 14 May 2019 22:47:03 -0700 Subject: [PATCH 0293/1056] btcec/btcec: deprecate QPlus1Div4() in favor of Q() The previous naming suggested that the value ((P+1)/4+1)/4 was being returned, when in fact the returned value is simply (P+1)/4. The old method is superseded by Q(). --- btcec/btcec.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/btcec/btcec.go b/btcec/btcec.go index 2cb1d92913..de93a255a4 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -886,12 +886,22 @@ func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { return curve.fieldJacobianToBigAffine(qx, qy, qz) } -// QPlus1Div4 returns the Q+1/4 constant for the curve for use in calculating -// square roots via exponention. +// QPlus1Div4 returns the (P+1)/4 constant for the curve for use in calculating +// square roots via exponentiation. +// +// DEPRECATED: The actual value returned is (P+1)/4, where as the original +// method name implies that this value is (((P+1)/4)+1)/4. This method is kept +// to maintain backwards compatibility of the API. Use Q() instead. func (curve *KoblitzCurve) QPlus1Div4() *big.Int { return curve.q } +// Q returns the (P+1)/4 constant for the curve for use in calculating square +// roots via exponentiation. +func (curve *KoblitzCurve) Q() *big.Int { + return curve.q +} + var initonce sync.Once var secp256k1 KoblitzCurve From 06baabe5da28d17a1dd357594e2b8f5cc7ea3091 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 10 Oct 2019 12:03:47 -0400 Subject: [PATCH 0294/1056] server: mark address attempted on attempt rather than upon connection We should mark addresses as attempted when we attempt to connect to them, not once we establish a connection with said address. --- server.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server.go b/server.go index bed4de9593..7d5da9c1d7 100644 --- a/server.go +++ b/server.go @@ -2032,7 +2032,6 @@ func (s *server) outboundPeerConnected(c *connmgr.ConnReq, conn net.Conn) { sp.isWhitelisted = isWhitelisted(conn.RemoteAddr()) sp.AssociateConnection(conn) go s.peerDoneHandler(sp) - s.addrManager.Attempt(sp.NA()) } // peerDoneHandler handles peer disconnects by notifiying the server that it's @@ -2802,6 +2801,9 @@ func newServer(listenAddrs, agentBlacklist, agentWhitelist []string, continue } + // Mark an attempt for the valid address. + s.addrManager.Attempt(addr.NetAddress()) + addrString := addrmgr.NetAddressKey(addr.NetAddress()) return addrStringToNetAddr(addrString) } From ab6f3089f667f38172d9b45936206f0b4bc6f215 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 10 Oct 2019 12:10:52 -0400 Subject: [PATCH 0295/1056] server: mark address as connected within handleAddPeerMsg We do this to ensure the address manager contains live addresses. Previously, addresses with which we established connections with would not be marked as connected because it would be done once we disconnect peers. Given that we don't process all of the disconnect logic when we're shutting down, addresses of stable and good peers would never be marked as connected unless the connection was lost during operation. --- server.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server.go b/server.go index 7d5da9c1d7..eaaa1133ab 100644 --- a/server.go +++ b/server.go @@ -1651,6 +1651,12 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool { } } + // Update the address' last seen time if the peer has acknowledged + // our version and has sent us its version as well. + if sp.VerAckReceived() && sp.VersionKnown() && sp.NA() != nil { + s.addrManager.Connected(sp.NA()) + } + return true } @@ -1681,12 +1687,6 @@ func (s *server) handleDonePeerMsg(state *peerState, sp *serverPeer) { s.connManager.Disconnect(sp.connReq.ID()) } - // Update the address' last seen time if the peer has acknowledged - // our version and has sent us its version as well. - if sp.VerAckReceived() && sp.VersionKnown() && sp.NA() != nil { - s.addrManager.Connected(sp.NA()) - } - // If we get here it means that either we didn't know about the peer // or we purposefully deleted it. } From e47518c978d8d22d987a64a8eecbc305c693fd4e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 10 Oct 2019 15:54:11 -0700 Subject: [PATCH 0296/1056] btcd: bump version to v0.20.0-beta --- cmd/btcctl/version.go | 2 +- version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go index fb147bcda5..2195175c71 100644 --- a/cmd/btcctl/version.go +++ b/cmd/btcctl/version.go @@ -17,7 +17,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 12 + appMinor uint = 20 appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet diff --git a/version.go b/version.go index 192f4a7f58..92fd60fdd4 100644 --- a/version.go +++ b/version.go @@ -17,7 +17,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 12 + appMinor uint = 20 appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet From 45d66d46f9c5c917b643eab43a061f35157ece6b Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 10 Oct 2019 13:18:03 -0400 Subject: [PATCH 0297/1056] server: standardize use of connmanager's Disconnect and Remove methods The Disconnect method would still attempt to reconnect to the same peer, which could cause us to reconnect to bad/unstable peers if we came across them. Instead, we'll now use Remove whenever we intend to remove a peer that is not persistent. --- server.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/server.go b/server.go index eaaa1133ab..b518a66303 100644 --- a/server.go +++ b/server.go @@ -1671,24 +1671,26 @@ func (s *server) handleDonePeerMsg(state *peerState, sp *serverPeer) { } else { list = state.outboundPeers } + + // Regardless of whether the peer was found in our list, we'll inform + // our connection manager about the disconnection. This can happen if we + // process a peer's `done` message before its `add`. + if !sp.Inbound() { + if sp.persistent { + s.connManager.Disconnect(sp.connReq.ID()) + } else { + s.connManager.Remove(sp.connReq.ID()) + } + } + if _, ok := list[sp.ID()]; ok { if !sp.Inbound() && sp.VersionKnown() { state.outboundGroups[addrmgr.GroupKey(sp.NA())]-- } - if !sp.Inbound() && sp.connReq != nil { - s.connManager.Disconnect(sp.connReq.ID()) - } delete(list, sp.ID()) srvrLog.Debugf("Removed peer %s", sp) return } - - if sp.connReq != nil { - s.connManager.Disconnect(sp.connReq.ID()) - } - - // If we get here it means that either we didn't know about the peer - // or we purposefully deleted it. } // handleBanPeerMsg deals with banning peers. It is invoked from the @@ -2025,7 +2027,12 @@ func (s *server) outboundPeerConnected(c *connmgr.ConnReq, conn net.Conn) { p, err := peer.NewOutboundPeer(newPeerConfig(sp), c.Addr.String()) if err != nil { srvrLog.Debugf("Cannot create outbound peer %s: %v", c.Addr, err) - s.connManager.Disconnect(c.ID()) + if c.Permanent { + s.connManager.Disconnect(c.ID()) + } else { + s.connManager.Remove(c.ID()) + } + return } sp.Peer = p sp.connReq = c From 0d00cdf82c3266f014ec7ef7a7717daf28e69de6 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 10 Oct 2019 13:25:19 -0400 Subject: [PATCH 0298/1056] server: request new peer after disconnection of non-persistent peers Doing so ensures we reach our target number of outbound peers as soon as possible. This is only necessary after calls to connmgr.Remove, as these won't request a new peer connection. --- server.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server.go b/server.go index b518a66303..9f4c54d3e4 100644 --- a/server.go +++ b/server.go @@ -1680,6 +1680,7 @@ func (s *server) handleDonePeerMsg(state *peerState, sp *serverPeer) { s.connManager.Disconnect(sp.connReq.ID()) } else { s.connManager.Remove(sp.connReq.ID()) + go s.connManager.NewConnReq() } } @@ -2031,6 +2032,7 @@ func (s *server) outboundPeerConnected(c *connmgr.ConnReq, conn net.Conn) { s.connManager.Disconnect(c.ID()) } else { s.connManager.Remove(c.ID()) + go s.connManager.NewConnReq() } return } From 2083acdd247338336bf1a1b644b53be2960131aa Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 10 Oct 2019 16:17:57 -0700 Subject: [PATCH 0299/1056] release: add new release script and documentation In this commit, we add the new release script that will be used to build all release binaries going forward. We also remove the existing Conformal key as it's no longer in use, updating the README to reflect the new release build/verification process. --- README.md | 25 ++----- release/GIT-GPG-KEY-conformal.txt | 74 -------------------- release/README.md | 71 +++++++++++++++++++ release/release.sh | 109 ++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 93 deletions(-) delete mode 100644 release/GIT-GPG-KEY-conformal.txt create mode 100644 release/README.md create mode 100755 release/release.sh diff --git a/README.md b/README.md index 2b126a6503..a270fd2e97 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ which are both under active development. ## Requirements -[Go](http://golang.org) 1.11 or newer. +[Go](http://golang.org) 1.12 or newer. ## Installation @@ -118,25 +118,12 @@ is used for this project. The documentation is a work-in-progress. It is located in the [docs](https://github.com/btcsuite/btcd/tree/master/docs) folder. -## GPG Verification Key +## Release Verification -All official release tags are signed by Conformal so users can ensure the code -has not been tampered with and is coming from the btcsuite developers. To -verify the signature perform the following: - -- Download the Conformal public key: - https://raw.githubusercontent.com/btcsuite/btcd/master/release/GIT-GPG-KEY-conformal.txt - -- Import the public key into your GPG keyring: - ```bash - gpg --import GIT-GPG-KEY-conformal.txt - ``` - -- Verify the release tag with the following command where `TAG_NAME` is a - placeholder for the specific tag: - ```bash - git tag -v TAG_NAME - ``` +Please see our [documentation on the current build/verification +process](https://github.com/btcsuite/btcd/tree/master/release) for all our +releases for information on how to verify the integrity of published releases +using our reproducible build system. ## License diff --git a/release/GIT-GPG-KEY-conformal.txt b/release/GIT-GPG-KEY-conformal.txt deleted file mode 100644 index a6d1a2562d..0000000000 --- a/release/GIT-GPG-KEY-conformal.txt +++ /dev/null @@ -1,74 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 - -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 -=iic8 ------END PGP PUBLIC KEY BLOCK----- diff --git a/release/README.md b/release/README.md new file mode 100644 index 0000000000..10d1c80cc0 --- /dev/null +++ b/release/README.md @@ -0,0 +1,71 @@ +# `btcd`'s Reproducible Build System + +This package contains the build script that the `btcd` project uses in order to +build binaries for each new release. As of `go1.13`, with some new build flags, +binaries are now reproducible, allowing developers to build the binary on +distinct machines, and end up with a byte-for-byte identical binary. However, +this wasn't _fully_ solved in `go1.13`, as the build system still includes the +directory the binary is built into the binary itself. As a result, our scripts +utilize a work around needed until `go1.13.2`. + +## Building a New Release + +### macOS/Linux/Windows (WSL) + +No prior set up is needed on Linux or macOS is required in order to build the +release binaries. However, on Windows, the only way to build the release +binaries at the moment is by using the Windows Subsystem Linux. One can build +the release binaries following these steps: + +1. `git clone https://github.com/btcsuite/btcd.git +2. `cd btcd` +3. `./build/release/release.sh # is the name of the next + release/tag` + +This will then create a directory of the form `btcd-` containing archives +of the release binaries for each supported operating system and architecture, +and a manifest file containing the hash of each archive. + +## Verifying a Release + +With `go1.13`, it's now possible for third parties to verify release binaries. +Before this version of `go`, one had to trust the release manager(s) to build the +proper binary. With this new system, third parties can now _independently_ run +the release process, and verify that all the hashes of the release binaries +match exactly that of the release binaries produced by said third parties. + +To verify a release, one must obtain the following tools (many of these come +installed by default in most Unix systems): `gpg`/`gpg2`, `shashum`, and +`tar`/`unzip`. + +Once done, verifiers can proceed with the following steps: + +1. Acquire the archive containing the release binaries for one's specific + operating system and architecture, and the manifest file along with its + signature. +2. Verify the signature of the manifest file with `gpg --verify + manifest-.txt.sig`. This will require obtaining the PGP keys which + signed the manifest file, which are included in the release notes. +3. Recompute the `SHA256` hash of the archive with `shasum -a 256 `, + locate the corresponding one in the manifest file, and ensure they match + __exactly__. + +At this point, verifiers can use the release binaries acquired if they trust +the integrity of the release manager(s). Otherwise, one can proceed with the +guide to verify the release binaries were built properly by obtaining `shasum` +and `go` (matching the same version used in the release): + +4. Extract the release binaries contained within the archive, compute their + hashes as done above, and note them down. +5. Ensure `go` is installed, matching the same version as noted in the release + notes. +6. Obtain a copy of `btcd`'s source code with `git clone + https://github.com/btcsuite/btcd` and checkout the source code of the + release with `git checkout `. +7. Proceed to verify the tag with `git verify-tag ` and compile the + binaries from source for the intended operating system and architecture with + `BTCDBUILDSYS=OS-ARCH ./build/release/release.sh `. +8. Extract the archive found in the `btcd-` directory created by the + release script and recompute the `SHA256` hash of the release binaries (btcd + and btcctl) with `shasum -a 256 `. These should match __exactly__ + as the ones noted above. diff --git a/release/release.sh b/release/release.sh new file mode 100755 index 0000000000..53c73b8d1e --- /dev/null +++ b/release/release.sh @@ -0,0 +1,109 @@ +#!/bin/bash + +# Simple bash script to build basic btcd tools for all the platforms we support +# with the golang cross-compiler. +# +# Copyright (c) 2016 Company 0, LLC. +# Use of this source code is governed by the ISC +# license. + +set -e + +# If no tag specified, use date + version otherwise use tag. +if [[ $1x = x ]]; then + DATE=`date +%Y%m%d` + VERSION="01" + TAG=$DATE-$VERSION +else + TAG=$1 +fi + +go mod vendor +tar -cvzf vendor.tar.gz vendor + +PACKAGE=btcd +MAINDIR=$PACKAGE-$TAG +mkdir -p $MAINDIR + +cp vendor.tar.gz $MAINDIR/ +rm vendor.tar.gz +rm -r vendor + +PACKAGESRC="$MAINDIR/$PACKAGE-source-$TAG.tar" +git archive -o $PACKAGESRC HEAD +gzip -f $PACKAGESRC > "$PACKAGESRC.gz" + +cd $MAINDIR + +# If BTCDBUILDSYS is set the default list is ignored. Useful to release +# for a subset of systems/architectures. +SYS=${BTCDBUILDSYS:-" + darwin-386 + darwin-amd64 + dragonfly-amd64 + freebsd-386 + freebsd-amd64 + freebsd-arm + illumos-amd64 + linux-386 + linux-amd64 + linux-armv6 + linux-armv7 + linux-arm64 + linux-ppc64 + linux-ppc64le + linux-mips + linux-mipsle + linux-mips64 + linux-mips64le + linux-s390x + netbsd-386 + netbsd-amd64 + netbsd-arm + netbsd-arm64 + openbsd-386 + openbsd-amd64 + openbsd-arm + openbsd-arm64 + solaris-amd64 + windows-386 + windows-amd64 + windows-arm +"} + +# Use the first element of $GOPATH in the case where GOPATH is a list +# (something that is totally allowed). +PKG="github.com/btcsuite/btcd" +COMMIT=$(git describe --abbrev=40 --dirty) + +for i in $SYS; do + OS=$(echo $i | cut -f1 -d-) + ARCH=$(echo $i | cut -f2 -d-) + ARM= + + if [[ $ARCH = "armv6" ]]; then + ARCH=arm + ARM=6 + elif [[ $ARCH = "armv7" ]]; then + ARCH=arm + ARM=7 + fi + + mkdir $PACKAGE-$i-$TAG + cd $PACKAGE-$i-$TAG + + echo "Building:" $OS $ARCH $ARM + env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid=" github.com/btcsuite/btcd + env CGO_ENABLED=0 GOOS=$OS GOARCH=$ARCH GOARM=$ARM go build -v -trimpath -ldflags="-s -w -buildid=" github.com/btcsuite/btcd/cmd/btcctl + cd .. + + if [[ $OS = "windows" ]]; then + zip -r $PACKAGE-$i-$TAG.zip $PACKAGE-$i-$TAG + else + tar -cvzf $PACKAGE-$i-$TAG.tar.gz $PACKAGE-$i-$TAG + fi + + rm -r $PACKAGE-$i-$TAG +done + +shasum -a 256 * > manifest-$TAG.txt From 069ec701df22480be2a7d820f5a2095e8e38b19c Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 10 Oct 2019 18:00:37 -0700 Subject: [PATCH 0300/1056] btcec/pubkey: normalize sqrt(x^3) before checking parity This commit fixes an issue introduced in the recent #1429, where the output of SqrtVal is not normalized before using IsOdd() to compare with the expected parity of the y-coordinate. The IsOdd() is only guaranteed to work if the value has been denormalized, so a denormalized sqrt >= p would report the opposite parity. We fix this by normalizing both after compute sqrt(x^3) and when negating the root as directed by the ybit. --- btcec/pubkey.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index c72f8705ab..3c9d5d02d2 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -38,11 +38,10 @@ func decompressPoint(curve *KoblitzCurve, bigX *big.Int, ybit bool) (*big.Int, e // but this was replaced by the algorithms referenced in // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 var y fieldVal - y.SqrtVal(&x3) + y.SqrtVal(&x3).Normalize() if ybit != y.IsOdd() { - y.Negate(1) + y.Negate(1).Normalize() } - y.Normalize() // Check that y is a square root of x^3 + B. var y2 fieldVal From 11b84f5cb57a9edc1a86109344636b5598df192d Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 11 Oct 2019 18:17:21 -0400 Subject: [PATCH 0301/1056] server: signal SyncManager with new peer within AddPeer This makes the logic a bit more unified as previously it was possible we for us to report the new peer to the SyncManager, but for whatever reason failed to track the peer in the server internally within AddPeer. This change ensures this can no longer happen. --- server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server.go b/server.go index 9f4c54d3e4..17dc278348 100644 --- a/server.go +++ b/server.go @@ -490,9 +490,6 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // the local clock to keep the network time in sync. sp.server.timeSource.AddTimeSample(sp.Addr(), msg.Timestamp) - // Signal the sync manager this peer is a new sync candidate. - sp.server.syncManager.NewPeer(sp.Peer) - // Choose whether or not to relay transactions before a filter command // is received. sp.setDisableRelayTx(msg.DisableRelayTx) @@ -1657,6 +1654,9 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool { s.addrManager.Connected(sp.NA()) } + // Signal the sync manager this peer is a new sync candidate. + s.syncManager.NewPeer(sp.Peer) + return true } From a1a5bfa81957965f2b65ba661bd8632d25be6a64 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 11 Oct 2019 18:19:59 -0400 Subject: [PATCH 0302/1056] server: add new peers within OnVerAck instead of within OnVersion This change is needed as part of requiring peers to also send a verack message following their version message during protocol negotiation. Peers were previously added to the SyncManager before their message queues were started, causing the server to stall if a peer didn't provide a timely verack response following their version. We now do this within OnVerAck, which happens shortly before peer message queues are started. --- server.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index 17dc278348..bff032d9a7 100644 --- a/server.go +++ b/server.go @@ -494,11 +494,15 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej // is received. sp.setDisableRelayTx(msg.DisableRelayTx) - // Add valid peer to the server. - sp.server.AddPeer(sp) return nil } +// OnVerAck is invoked when a peer receives a verack bitcoin message and is used +// to kick start communication with them. +func (sp *serverPeer) OnVerAck(_ *peer.Peer, _ *wire.MsgVerAck) { + sp.server.AddPeer(sp) +} + // OnMemPool is invoked when a peer receives a mempool bitcoin message. // It creates and sends an inventory message with the contents of the memory // pool up to the maximum inventory allowed per message. When the peer has a @@ -1966,6 +1970,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { return &peer.Config{ Listeners: peer.MessageListeners{ OnVersion: sp.OnVersion, + OnVerAck: sp.OnVerAck, OnMemPool: sp.OnMemPool, OnTx: sp.OnTx, OnBlock: sp.OnBlock, From 769c4e152f0711aba7560a5d68005b0779b5f677 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 11 Oct 2019 18:24:31 -0400 Subject: [PATCH 0303/1056] server: request addresses from new peers once they can process messages This was previously done within the OnVersion listener, which should not be a blocking operation. It turns out that requesting these messages there can lead to blocking due to peers not being able to process messages since their message queues have yet to start. Therefore, we'll now request within handleAddPeerMsg, which should allow it to go through. --- server.go | 59 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/server.go b/server.go index bff032d9a7..630937fb39 100644 --- a/server.go +++ b/server.go @@ -438,11 +438,6 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej return wire.NewMsgReject(msg.Command(), wire.RejectNonstandard, reason) } - // Update the address manager and request known addresses from the - // remote peer for outbound connections. This is skipped when running - // on the simulation test network since it is only intended to connect - // to specified peers and actively avoids advertising and connecting to - // discovered peers. if !cfg.SimNet && !isInbound { // After soft-fork activation, only make outbound // connection to peers if they flag that they're segwit @@ -461,29 +456,6 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej sp.Disconnect() return nil } - - // Advertise the local address when the server accepts incoming - // connections and it believes itself to be close to the best known tip. - if !cfg.DisableListen && sp.server.syncManager.IsCurrent() { - // Get address that best matches. - lna := addrManager.GetBestLocalAddress(remoteAddr) - if addrmgr.IsRoutable(lna) { - // Filter addresses the peer already knows about. - addresses := []*wire.NetAddress{lna} - sp.pushAddrMsg(addresses) - } - } - - // Request known addresses if the server address manager needs - // more and the peer has a protocol version new enough to - // include a timestamp with addresses. - hasTimestamp := sp.ProtocolVersion() >= wire.NetAddressTimeVersion - if addrManager.NeedMoreAddresses() && hasTimestamp { - sp.QueueMessage(wire.NewMsgGetAddr(), nil) - } - - // Mark the address as a known good address. - addrManager.Good(remoteAddr) } // Add the remote peer time as a sample for creating an offset against @@ -1661,6 +1633,37 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool { // Signal the sync manager this peer is a new sync candidate. s.syncManager.NewPeer(sp.Peer) + // Update the address manager and request known addresses from the + // remote peer for outbound connections. This is skipped when running on + // the simulation test network since it is only intended to connect to + // specified peers and actively avoids advertising and connecting to + // discovered peers. + if !cfg.SimNet && !sp.Inbound() { + // Advertise the local address when the server accepts incoming + // connections and it believes itself to be close to the best + // known tip. + if !cfg.DisableListen && s.syncManager.IsCurrent() { + // Get address that best matches. + lna := s.addrManager.GetBestLocalAddress(sp.NA()) + if addrmgr.IsRoutable(lna) { + // Filter addresses the peer already knows about. + addresses := []*wire.NetAddress{lna} + sp.pushAddrMsg(addresses) + } + } + + // Request known addresses if the server address manager needs + // more and the peer has a protocol version new enough to + // include a timestamp with addresses. + hasTimestamp := sp.ProtocolVersion() >= wire.NetAddressTimeVersion + if s.addrManager.NeedMoreAddresses() && hasTimestamp { + sp.QueueMessage(wire.NewMsgGetAddr(), nil) + } + + // Mark the address as a known good address. + s.addrManager.Good(sp.NA()) + } + return true } From baeb789a7d789cf095b6c465c2a5754cf6e4dff7 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 11 Oct 2019 18:29:09 -0400 Subject: [PATCH 0304/1056] server: prevent adding peers if already disconnected This addresses an issue where the server ends up tracking a peer that has been disconnected due to it processing a peer's `done` message before its `add` message. --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index 630937fb39..1d7fdf9b71 100644 --- a/server.go +++ b/server.go @@ -1563,7 +1563,7 @@ func (s *server) handleUpdatePeerHeights(state *peerState, umsg updatePeerHeight // handleAddPeerMsg deals with adding new peers. It is invoked from the // peerHandler goroutine. func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool { - if sp == nil { + if sp == nil || !sp.Connected() { return false } From a41498d578a99c1619037746abd916176ea61052 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 Oct 2019 10:11:03 +0200 Subject: [PATCH 0305/1056] release: remove windows-arm --- release/release.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/release/release.sh b/release/release.sh index 53c73b8d1e..7b0885dac6 100755 --- a/release/release.sh +++ b/release/release.sh @@ -68,7 +68,6 @@ SYS=${BTCDBUILDSYS:-" solaris-amd64 windows-386 windows-amd64 - windows-arm "} # Use the first element of $GOPATH in the case where GOPATH is a list From a46f7b45abb3512c0a43c3c7f268162c48160a96 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 29 Oct 2019 18:49:37 -0700 Subject: [PATCH 0306/1056] rpcclient: add GetNetworkInfo method --- rpcclient/net.go | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/rpcclient/net.go b/rpcclient/net.go index 3b166cb934..6eb7362541 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -244,6 +244,43 @@ func (c *Client) Ping() error { return c.PingAsync().Receive() } +// FutureGetNetworkInfoResult is a future promise to deliver the result of a +// GetNetworkInfoAsync RPC invocation (or an applicable error). +type FutureGetNetworkInfoResult chan *response + +// Receive waits for the response promised by the future and returns data about +// the current network. +func (r FutureGetNetworkInfoResult) Receive() (*btcjson.GetNetworkInfoResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as an array of getpeerinfo result objects. + var networkInfo btcjson.GetNetworkInfoResult + err = json.Unmarshal(res, &networkInfo) + if err != nil { + return nil, err + } + + return &networkInfo, nil +} + +// GetNetworkInfoAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetNetworkInfo for the blocking version and more details. +func (c *Client) GetNetworkInfoAsync() FutureGetNetworkInfoResult { + cmd := btcjson.NewGetNetworkInfoCmd() + return c.sendCmd(cmd) +} + +// GetNetworkInfo returns data about the current network. +func (c *Client) GetNetworkInfo() (*btcjson.GetNetworkInfoResult, error) { + return c.GetNetworkInfoAsync().Receive() +} + // FutureGetPeerInfoResult is a future promise to deliver the result of a // GetPeerInfoAsync RPC invocation (or an applicable error). type FutureGetPeerInfoResult chan *response From bc21593480f27e1cdb320c5bbdfde3a382dc4b07 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 29 Oct 2019 19:38:38 -0700 Subject: [PATCH 0307/1056] server: remove peer from SyncManager on VerAckReceived Peers are now added to the SyncManager if we receive their verack, but we'd still attempt to remove them from the SyncManager if we didn't receive it. --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index 1d7fdf9b71..a0fc8099ec 100644 --- a/server.go +++ b/server.go @@ -2058,7 +2058,7 @@ func (s *server) peerDoneHandler(sp *serverPeer) { s.donePeers <- sp // Only tell sync manager we are gone if we ever told it we existed. - if sp.VersionKnown() { + if sp.VerAckReceived() { s.syncManager.DonePeer(sp.Peer) // Evict any remaining orphans that were sent by the peer. From e89d4fca24a0dee0d89f913c54412f1e6635b1ff Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 29 Oct 2019 18:50:11 -0700 Subject: [PATCH 0308/1056] rpcclient: allow retrieval of backend version --- rpcclient/infrastructure.go | 109 ++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 27f7f21f1b..7a8f1885d1 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -19,6 +19,7 @@ import ( "net" "net/http" "net/url" + "strings" "sync" "sync/atomic" "time" @@ -103,6 +104,22 @@ type jsonRequest struct { responseChan chan *response } +// BackendVersion represents the version of the backend the client is currently +// connected to. +type BackendVersion uint8 + +const ( + // BitcoindPre19 represents a bitcoind version before 0.19.0. + BitcoindPre19 BackendVersion = iota + + // BitcoindPost19 represents a bitcoind version equal to or greater than + // 0.19.0. + BitcoindPost19 + + // Btcd represents a catch-all btcd version. + Btcd +) + // Client represents a Bitcoin RPC client which allows easy access to the // various RPC methods available on a Bitcoin RPC server. Each of the wrapper // functions handle the details of converting the passed and return types to and @@ -129,6 +146,11 @@ type Client struct { // POST mode. httpClient *http.Client + // backendVersion is the version of the backend the client is currently + // connected to. This should be retrieved through GetVersion. + backendVersionMu sync.Mutex + backendVersion *BackendVersion + // mtx is a mutex to protect access to connection related fields. mtx sync.Mutex @@ -659,6 +681,12 @@ out: log.Infof("Reestablished connection to RPC server %s", c.config.Host) + // Reset the version in case the backend was + // disconnected due to an upgrade. + c.backendVersionMu.Lock() + c.backendVersion = nil + c.backendVersionMu.Unlock() + // Reset the connection state and signal the reconnect // has happened. c.wsConn = wsConn @@ -1332,3 +1360,84 @@ func (c *Client) Connect(tries int) error { // All connection attempts failed, so return the last error. return err } + +const ( + // bitcoind19Str is the string representation of bitcoind v0.19.0. + bitcoind19Str = "0.19.0" + + // bitcoindVersionPrefix specifies the prefix included in every bitcoind + // version exposed through GetNetworkInfo. + bitcoindVersionPrefix = "/Satoshi:" + + // bitcoindVersionSuffix specifies the suffix included in every bitcoind + // version exposed through GetNetworkInfo. + bitcoindVersionSuffix = "/" +) + +// parseBitcoindVersion parses the bitcoind version from its string +// representation. +func parseBitcoindVersion(version string) BackendVersion { + // Trim the version of its prefix and suffix to determine the + // appropriate version number. + version = strings.TrimPrefix( + strings.TrimSuffix(version, bitcoindVersionSuffix), + bitcoindVersionPrefix, + ) + switch { + case version < bitcoind19Str: + return BitcoindPre19 + default: + return BitcoindPost19 + } +} + +// BackendVersion retrieves the version of the backend the client is currently +// connected to. +func (c *Client) BackendVersion() (BackendVersion, error) { + c.backendVersionMu.Lock() + defer c.backendVersionMu.Unlock() + + if c.backendVersion != nil { + return *c.backendVersion, nil + } + + // We'll start by calling GetInfo. This method doesn't exist for + // bitcoind nodes as of v0.16.0, so we'll assume the client is connected + // to a btcd backend if it does exist. + info, err := c.GetInfo() + + switch err := err.(type) { + // Parse the btcd version and cache it. + case nil: + log.Debugf("Detected btcd version: %v", info.Version) + version := Btcd + c.backendVersion = &version + return *c.backendVersion, nil + + // Inspect the RPC error to ensure the method was not found, otherwise + // we actually ran into an error. + case *btcjson.RPCError: + if err.Code != btcjson.ErrRPCMethodNotFound.Code { + return 0, fmt.Errorf("unable to detect btcd version: "+ + "%v", err) + } + + default: + return 0, fmt.Errorf("unable to detect btcd version: %v", err) + } + + // Since the GetInfo method was not found, we assume the client is + // connected to a bitcoind backend, which exposes its version through + // GetNetworkInfo. + networkInfo, err := c.GetNetworkInfo() + if err != nil { + return 0, fmt.Errorf("unable to detect bitcoind version: %v", err) + } + + // Parse the bitcoind version and cache it. + log.Debugf("Detected bitcoind version: %v", networkInfo.SubVersion) + version := parseBitcoindVersion(networkInfo.SubVersion) + c.backendVersion = &version + + return *c.backendVersion, nil +} From 266851e329e2089fd2e0f082ddc6002c920be879 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 29 Oct 2019 18:50:46 -0700 Subject: [PATCH 0309/1056] btcjson+rpcclient: support new unified softfork bitcoind format --- btcjson/chainsvrresults.go | 48 ++++++++++++++----- integration/bip0009_test.go | 2 +- rpcclient/chain.go | 67 ++++++++++++++++++++++++--- rpcclient/chain_test.go | 92 +++++++++++++++++++++++++++++++++++++ rpcserver.go | 8 ++-- rpcserverhelp.go | 40 ++++++++++------ 6 files changed, 220 insertions(+), 37 deletions(-) create mode 100644 rpcclient/chain_test.go diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index cc9c085531..257a6c90c3 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -97,21 +97,45 @@ type Bip9SoftForkDescription struct { Since int32 `json:"since"` } +// SoftForks describes the current softforks enabled by the backend. Softforks +// activated through BIP9 are grouped together separate from any other softforks +// with different activation types. +type SoftForks struct { + SoftForks []*SoftForkDescription `json:"softforks"` + Bip9SoftForks map[string]*Bip9SoftForkDescription `json:"bip9_softforks"` +} + +// UnifiedSoftForks describes a softforks in a general manner, irrespective of +// its activation type. This was a format introduced by bitcoind v0.19.0 +type UnifiedSoftFork struct { + Type string `json:"type"` + BIP9SoftForkDescription *Bip9SoftForkDescription `json:"bip9"` + Height int32 `json:"height"` + Active bool `json:"active"` +} + +// UnifiedSoftForks describes the current softforks enabled the by the backend +// in a unified manner, i.e, softforks with different activation types are +// grouped together. This was a format introduced by bitcoind v0.19.0 +type UnifiedSoftForks struct { + SoftForks map[string]*UnifiedSoftFork `json:"softforks"` +} + // GetBlockChainInfoResult models the data returned from the getblockchaininfo // command. type GetBlockChainInfoResult struct { - Chain string `json:"chain"` - Blocks int32 `json:"blocks"` - Headers int32 `json:"headers"` - BestBlockHash string `json:"bestblockhash"` - Difficulty float64 `json:"difficulty"` - MedianTime int64 `json:"mediantime"` - VerificationProgress float64 `json:"verificationprogress,omitempty"` - Pruned bool `json:"pruned"` - PruneHeight int32 `json:"pruneheight,omitempty"` - ChainWork string `json:"chainwork,omitempty"` - SoftForks []*SoftForkDescription `json:"softforks"` - Bip9SoftForks map[string]*Bip9SoftForkDescription `json:"bip9_softforks"` + Chain string `json:"chain"` + Blocks int32 `json:"blocks"` + Headers int32 `json:"headers"` + BestBlockHash string `json:"bestblockhash"` + Difficulty float64 `json:"difficulty"` + MedianTime int64 `json:"mediantime"` + VerificationProgress float64 `json:"verificationprogress,omitempty"` + Pruned bool `json:"pruned"` + PruneHeight int32 `json:"pruneheight,omitempty"` + ChainWork string `json:"chainwork,omitempty"` + *SoftForks + *UnifiedSoftForks } // GetBlockTemplateResultTx models the transactions field of the diff --git a/integration/bip0009_test.go b/integration/bip0009_test.go index 181c8983ef..df3721b1e6 100644 --- a/integration/bip0009_test.go +++ b/integration/bip0009_test.go @@ -102,7 +102,7 @@ func assertSoftForkStatus(r *rpctest.Harness, t *testing.T, forkKey string, stat } // Ensure the key is available. - desc, ok := info.Bip9SoftForks[forkKey] + desc, ok := info.SoftForks.Bip9SoftForks[forkKey] if !ok { _, _, line, _ := runtime.Caller(1) t.Fatalf("assertion failed at line %d: softfork status for %q "+ diff --git a/rpcclient/chain.go b/rpcclient/chain.go index c21668918d..996d80458c 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -253,21 +253,73 @@ func (c *Client) GetDifficulty() (float64, error) { // FutureGetBlockChainInfoResult is a promise to deliver the result of a // GetBlockChainInfoAsync RPC invocation (or an applicable error). -type FutureGetBlockChainInfoResult chan *response +type FutureGetBlockChainInfoResult struct { + client *Client + Response chan *response +} + +// unmarshalPartialGetBlockChainInfoResult unmarshals the response into an +// instance of GetBlockChainInfoResult without populating the SoftForks and +// UnifiedSoftForks fields. +func unmarshalPartialGetBlockChainInfoResult(res []byte) (*btcjson.GetBlockChainInfoResult, error) { + var chainInfo btcjson.GetBlockChainInfoResult + if err := json.Unmarshal(res, &chainInfo); err != nil { + return nil, err + } + return &chainInfo, nil +} + +// unmarshalGetBlockChainInfoResultSoftForks properly unmarshals the softforks +// related fields into the GetBlockChainInfoResult instance. +func unmarshalGetBlockChainInfoResultSoftForks(chainInfo *btcjson.GetBlockChainInfoResult, + version BackendVersion, res []byte) error { + + switch version { + // Versions of bitcoind on or after v0.19.0 use the unified format. + case BitcoindPost19: + var softForks btcjson.UnifiedSoftForks + if err := json.Unmarshal(res, &softForks); err != nil { + return err + } + chainInfo.UnifiedSoftForks = &softForks + + // All other versions use the original format. + default: + var softForks btcjson.SoftForks + if err := json.Unmarshal(res, &softForks); err != nil { + return err + } + chainInfo.SoftForks = &softForks + } + + return nil +} // Receive waits for the response promised by the future and returns chain info // result provided by the server. func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResult, error) { - res, err := receiveFuture(r) + res, err := receiveFuture(r.Response) + if err != nil { + return nil, err + } + chainInfo, err := unmarshalPartialGetBlockChainInfoResult(res) if err != nil { return nil, err } - var chainInfo btcjson.GetBlockChainInfoResult - if err := json.Unmarshal(res, &chainInfo); err != nil { + // Inspect the version to determine how we'll need to parse the + // softforks from the response. + version, err := r.client.BackendVersion() + if err != nil { return nil, err } - return &chainInfo, nil + + err = unmarshalGetBlockChainInfoResultSoftForks(chainInfo, version, res) + if err != nil { + return nil, err + } + + return chainInfo, nil } // GetBlockChainInfoAsync returns an instance of a type that can be used to get @@ -277,7 +329,10 @@ func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResu // See GetBlockChainInfo for the blocking version and more details. func (c *Client) GetBlockChainInfoAsync() FutureGetBlockChainInfoResult { cmd := btcjson.NewGetBlockChainInfoCmd() - return c.sendCmd(cmd) + return FutureGetBlockChainInfoResult{ + client: c, + Response: c.sendCmd(cmd), + } } // GetBlockChainInfo returns information related to the processing state of diff --git a/rpcclient/chain_test.go b/rpcclient/chain_test.go new file mode 100644 index 0000000000..e32d547ce3 --- /dev/null +++ b/rpcclient/chain_test.go @@ -0,0 +1,92 @@ +package rpcclient + +import "testing" + +// TestUnmarshalGetBlockChainInfoResult ensures that the SoftForks and +// UnifiedSoftForks fields of GetBlockChainInfoResult are properly unmarshaled +// when using the expected backend version. +func TestUnmarshalGetBlockChainInfoResultSoftForks(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + version BackendVersion + res []byte + compatible bool + }{ + { + name: "bitcoind < 0.19.0 with separate softforks", + version: BitcoindPre19, + res: []byte(`{"softforks": [{"version": 2}]}`), + compatible: true, + }, + { + name: "bitcoind >= 0.19.0 with separate softforks", + version: BitcoindPost19, + res: []byte(`{"softforks": [{"version": 2}]}`), + compatible: false, + }, + { + name: "bitcoind < 0.19.0 with unified softforks", + version: BitcoindPre19, + res: []byte(`{"softforks": {"segwit": {"type": "bip9"}}}`), + compatible: false, + }, + { + name: "bitcoind >= 0.19.0 with unified softforks", + version: BitcoindPost19, + res: []byte(`{"softforks": {"segwit": {"type": "bip9"}}}`), + compatible: true, + }, + } + + for _, test := range tests { + success := t.Run(test.name, func(t *testing.T) { + // We'll start by unmarshaling the JSON into a struct. + // The SoftForks and UnifiedSoftForks field should not + // be set yet, as they are unmarshaled within a + // different function. + info, err := unmarshalPartialGetBlockChainInfoResult(test.res) + if err != nil { + t.Fatal(err) + } + if info.SoftForks != nil { + t.Fatal("expected SoftForks to be empty") + } + if info.UnifiedSoftForks != nil { + t.Fatal("expected UnifiedSoftForks to be empty") + } + + // Proceed to unmarshal the softforks of the response + // with the expected version. If the version is + // incompatible with the response, then this should + // fail. + err = unmarshalGetBlockChainInfoResultSoftForks( + info, test.version, test.res, + ) + if test.compatible && err != nil { + t.Fatalf("unable to unmarshal softforks: %v", err) + } + if !test.compatible && err == nil { + t.Fatal("expected to not unmarshal softforks") + } + if !test.compatible { + return + } + + // If the version is compatible with the response, we + // should expect to see the proper softforks field set. + if test.version == BitcoindPost19 && + info.SoftForks != nil { + t.Fatal("expected SoftForks to be empty") + } + if test.version == BitcoindPre19 && + info.UnifiedSoftForks != nil { + t.Fatal("expected UnifiedSoftForks to be empty") + } + }) + if !success { + return + } + } +} diff --git a/rpcserver.go b/rpcserver.go index 097ba2ec84..0a7ab8ed89 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1198,14 +1198,16 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str Difficulty: getDifficultyRatio(chainSnapshot.Bits, params), MedianTime: chainSnapshot.MedianTime.Unix(), Pruned: false, - Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription), + SoftForks: &btcjson.SoftForks{ + Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription), + }, } // Next, populate the response with information describing the current // status of soft-forks deployed via the super-majority block // signalling mechanism. height := chainSnapshot.Height - chainInfo.SoftForks = []*btcjson.SoftForkDescription{ + chainInfo.SoftForks.SoftForks = []*btcjson.SoftForkDescription{ { ID: "bip34", Version: 2, @@ -1281,7 +1283,7 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str // Finally, populate the soft-fork description with all the // information gathered above. - chainInfo.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{ + chainInfo.SoftForks.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{ Status: strings.ToLower(statusString), Bit: deploymentDetails.BitNumber, StartTime: int64(deploymentDetails.StartTime), diff --git a/rpcserverhelp.go b/rpcserverhelp.go index e7637db69c..7da266eac1 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -172,21 +172,18 @@ var helpDescsEnUS = map[string]string{ "getblockchaininfo--synopsis": "Returns information about the current blockchain state and the status of any active soft-fork deployments.", // GetBlockChainInfoResult help. - "getblockchaininforesult-chain": "The name of the chain the daemon is on (testnet, mainnet, etc)", - "getblockchaininforesult-blocks": "The number of blocks in the best known chain", - "getblockchaininforesult-headers": "The number of headers that we've gathered for in the best known chain", - "getblockchaininforesult-bestblockhash": "The block hash for the latest block in the main chain", - "getblockchaininforesult-difficulty": "The current chain difficulty", - "getblockchaininforesult-mediantime": "The median time from the PoV of the best block in the chain", - "getblockchaininforesult-verificationprogress": "An estimate for how much of the best chain we've verified", - "getblockchaininforesult-pruned": "A bool that indicates if the node is pruned or not", - "getblockchaininforesult-pruneheight": "The lowest block retained in the current pruned chain", - "getblockchaininforesult-chainwork": "The total cumulative work in the best chain", - "getblockchaininforesult-softforks": "The status of the super-majority soft-forks", - "getblockchaininforesult-bip9_softforks": "JSON object describing active BIP0009 deployments", - "getblockchaininforesult-bip9_softforks--key": "bip9_softforks", - "getblockchaininforesult-bip9_softforks--value": "An object describing a particular BIP009 deployment", - "getblockchaininforesult-bip9_softforks--desc": "The status of any defined BIP0009 soft-fork deployments", + "getblockchaininforesult-chain": "The name of the chain the daemon is on (testnet, mainnet, etc)", + "getblockchaininforesult-blocks": "The number of blocks in the best known chain", + "getblockchaininforesult-headers": "The number of headers that we've gathered for in the best known chain", + "getblockchaininforesult-bestblockhash": "The block hash for the latest block in the main chain", + "getblockchaininforesult-difficulty": "The current chain difficulty", + "getblockchaininforesult-mediantime": "The median time from the PoV of the best block in the chain", + "getblockchaininforesult-verificationprogress": "An estimate for how much of the best chain we've verified", + "getblockchaininforesult-pruned": "A bool that indicates if the node is pruned or not", + "getblockchaininforesult-pruneheight": "The lowest block retained in the current pruned chain", + "getblockchaininforesult-chainwork": "The total cumulative work in the best chain", + "getblockchaininforesult-softforks": "The status of the super-majority soft-forks", + "getblockchaininforesult-unifiedsoftforks": "The status of the super-majority soft-forks used by bitcoind on or after v0.19.0", // SoftForkDescription help. "softforkdescription-reject": "The current activation status of the softfork", @@ -194,6 +191,19 @@ var helpDescsEnUS = map[string]string{ "softforkdescription-id": "The string identifier for the soft fork", "-status": "A bool which indicates if the soft fork is active", + // SoftForks help. + "softforks-softforks": "The status of the super-majority soft-forks", + "softforks-bip9_softforks": "JSON object describing active BIP0009 deployments", + "softforks-bip9_softforks--key": "bip9_softforks", + "softforks-bip9_softforks--value": "An object describing a particular BIP009 deployment", + "softforks-bip9_softforks--desc": "The status of any defined BIP0009 soft-fork deployments", + + // UnifiedSoftForks help. + "unifiedsoftforks-softforks": "The status of the super-majority soft-forks used by bitcoind on or after v0.19.0", + "unifiedsoftforks-softforks--key": "softforks", + "unifiedsoftforks-softforks--value": "An object describing an active softfork deployment used by bitcoind on or after v0.19.0", + "unifiedsoftforks-softforks--desc": "JSON object describing an active softfork deployment used by bitcoind on or after v0.19.0", + // TxRawResult help. "txrawresult-hex": "Hex-encoded transaction", "txrawresult-txid": "The hash of the transaction", From 93a84aa0143f6bc0787891ab2fe9b0beb36f4b22 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 29 Oct 2019 18:51:12 -0700 Subject: [PATCH 0310/1056] btcjson: use correct json tag for Bip9SoftForkDescription.StartTime --- btcjson/chainsvrresults.go | 19 ++++++++++++++----- rpcserver.go | 8 ++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 257a6c90c3..7e6c710766 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -90,11 +90,20 @@ type SoftForkDescription struct { // Bip9SoftForkDescription describes the current state of a defined BIP0009 // version bits soft-fork. type Bip9SoftForkDescription struct { - Status string `json:"status"` - Bit uint8 `json:"bit"` - StartTime int64 `json:"startTime"` - Timeout int64 `json:"timeout"` - Since int32 `json:"since"` + Status string `json:"status"` + Bit uint8 `json:"bit"` + StartTime1 int64 `json:"startTime"` + StartTime2 int64 `json:"start_time"` + Timeout int64 `json:"timeout"` + Since int32 `json:"since"` +} + +// StartTime returns the starting time of the softfork as a Unix epoch. +func (d *Bip9SoftForkDescription) StartTime() int64 { + if d.StartTime1 != 0 { + return d.StartTime1 + } + return d.StartTime2 } // SoftForks describes the current softforks enabled by the backend. Softforks diff --git a/rpcserver.go b/rpcserver.go index 0a7ab8ed89..e762cc1a9d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1284,10 +1284,10 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str // Finally, populate the soft-fork description with all the // information gathered above. chainInfo.SoftForks.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{ - Status: strings.ToLower(statusString), - Bit: deploymentDetails.BitNumber, - StartTime: int64(deploymentDetails.StartTime), - Timeout: int64(deploymentDetails.ExpireTime), + Status: strings.ToLower(statusString), + Bit: deploymentDetails.BitNumber, + StartTime2: int64(deploymentDetails.StartTime), + Timeout: int64(deploymentDetails.ExpireTime), } } From e2e5cc694dda523225cc01166867411ecb6c8477 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Tue, 29 Oct 2019 18:51:59 -0700 Subject: [PATCH 0311/1056] btcjson+rpcclient: support new bitcoind sendrawtransaction request --- btcjson/chainsvrcmds.go | 12 ++++++++++++ rpcclient/rawtransactions.go | 32 +++++++++++++++++++++++++++++++- rpcserverhelp.go | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index a5e5647112..406357bd06 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -638,6 +638,7 @@ func NewSearchRawTransactionsCmd(address string, verbose, skip, count *int, vinE type SendRawTransactionCmd struct { HexTx string AllowHighFees *bool `jsonrpcdefault:"false"` + MaxFeeRate *int32 } // NewSendRawTransactionCmd returns a new instance which can be used to issue a @@ -652,6 +653,17 @@ func NewSendRawTransactionCmd(hexTx string, allowHighFees *bool) *SendRawTransac } } +// NewSendRawTransactionCmd returns a new instance which can be used to issue a +// sendrawtransaction JSON-RPC command to a bitcoind node. +// +// A 0 maxFeeRate indicates that a maximum fee rate won't be enforced. +func NewBitcoindSendRawTransactionCmd(hexTx string, maxFeeRate int32) *SendRawTransactionCmd { + return &SendRawTransactionCmd{ + HexTx: hexTx, + MaxFeeRate: &maxFeeRate, + } +} + // SetGenerateCmd defines the setgenerate JSON-RPC command. type SetGenerateCmd struct { Generate bool diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index e886f2250d..4bf4ee57fc 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -15,6 +15,12 @@ import ( "github.com/btcsuite/btcutil" ) +const ( + // defaultMaxFeeRate is the default maximum fee rate in sat/KB enforced + // by bitcoind v0.19.0 or after for transaction broadcast. + defaultMaxFeeRate = btcutil.SatoshiPerBitcoin / 10 +) + // SigHashType enumerates the available signature hashing types that the // SignRawTransaction function accepts. type SigHashType string @@ -296,7 +302,31 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut txHex = hex.EncodeToString(buf.Bytes()) } - cmd := btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees) + // Due to differences in the sendrawtransaction API for different + // backends, we'll need to inspect our version and construct the + // appropriate request. + version, err := c.BackendVersion() + if err != nil { + return newFutureError(err) + } + + var cmd *btcjson.SendRawTransactionCmd + switch version { + // Starting from bitcoind v0.19.0, the MaxFeeRate field should be used. + case BitcoindPost19: + // Using a 0 MaxFeeRate is interpreted as a maximum fee rate not + // being enforced by bitcoind. + var maxFeeRate int32 + if !allowHighFees { + maxFeeRate = defaultMaxFeeRate + } + cmd = btcjson.NewBitcoindSendRawTransactionCmd(txHex, maxFeeRate) + + // Otherwise, use the AllowHighFees field. + default: + cmd = btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees) + } + return c.sendCmd(cmd) } diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 7da266eac1..cc6935b512 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -552,6 +552,7 @@ var helpDescsEnUS = map[string]string{ "sendrawtransaction--synopsis": "Submits the serialized, hex-encoded transaction to the local peer and relays it to the network.", "sendrawtransaction-hextx": "Serialized, hex-encoded signed transaction", "sendrawtransaction-allowhighfees": "Whether or not to allow insanely high fees (btcd does not yet implement this parameter, so it has no effect)", + "sendrawtransaction-maxfeerate": "Used by bitcoind on or after v0.19.0", "sendrawtransaction--result0": "The hash of the transaction", // SetGenerateCmd help. From c2ca0a408e09db7f46b760c3cb8a280ede58d54a Mon Sep 17 00:00:00 2001 From: nsa Date: Fri, 8 Nov 2019 21:11:24 -0500 Subject: [PATCH 0312/1056] server: add addressesMtx to fix race condition --- server.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server.go b/server.go index 1d7fdf9b71..786d9b2a2c 100644 --- a/server.go +++ b/server.go @@ -273,6 +273,7 @@ type serverPeer struct { sentAddrs bool isWhitelisted bool filter *bloom.Filter + addressesMtx sync.RWMutex knownAddresses map[string]struct{} banScore connmgr.DynamicBanScore quit chan struct{} @@ -305,14 +306,18 @@ func (sp *serverPeer) newestBlock() (*chainhash.Hash, int32, error) { // addKnownAddresses adds the given addresses to the set of known addresses to // the peer to prevent sending duplicate addresses. func (sp *serverPeer) addKnownAddresses(addresses []*wire.NetAddress) { + sp.addressesMtx.Lock() for _, na := range addresses { sp.knownAddresses[addrmgr.NetAddressKey(na)] = struct{}{} } + sp.addressesMtx.Unlock() } // addressKnown true if the given address is already known to the peer. func (sp *serverPeer) addressKnown(na *wire.NetAddress) bool { + sp.addressesMtx.RLock() _, exists := sp.knownAddresses[addrmgr.NetAddressKey(na)] + sp.addressesMtx.RUnlock() return exists } From f3ec13030e4e828869954472cbc51ac36bee5c1d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 12 Nov 2019 18:27:49 -0800 Subject: [PATCH 0313/1056] btcd: bump version to v0.20.1-beta --- cmd/btcctl/version.go | 2 +- version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go index 2195175c71..f65cacef7e 100644 --- a/cmd/btcctl/version.go +++ b/cmd/btcctl/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 20 - appPatch uint = 0 + appPatch uint = 1 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. diff --git a/version.go b/version.go index 92fd60fdd4..fba55b5a37 100644 --- a/version.go +++ b/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 20 - appPatch uint = 0 + appPatch uint = 1 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. From 679910415778c6098c8511923f3c13674e56219d Mon Sep 17 00:00:00 2001 From: Jake Date: Mon, 10 Feb 2020 14:16:11 -0500 Subject: [PATCH 0314/1056] Remove $GOPATH Caching $GOPATH caching has led to flaky tests as per #1503 and #1536. The speedup is marginal and while the false negatives are a headache, false positives are potentially dangerous. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5063496735..5a611c3960 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,6 @@ language: go cache: directories: - $GOCACHE - - $GOPATH - $GOPATH/pkg/mod - $GOPATH/github.com/golang - $GOPATH/gopkg.in/alecthomas From eed57cdcf1b47292b31fa59bfc74bc6c5f920dd3 Mon Sep 17 00:00:00 2001 From: Jake Sylvestre Date: Wed, 22 Jan 2020 00:45:53 -0500 Subject: [PATCH 0315/1056] go fmt --- mempool/estimatefee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index 53933469b6..3546f6b356 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -47,7 +47,7 @@ const ( bytePerKb = 1000 - btcPerSatoshi = 1E-8 + btcPerSatoshi = 1e-8 ) var ( From 3eb4739b7583bd84743d79f7131f939d8018dffa Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Mon, 9 Jul 2018 18:41:43 -0300 Subject: [PATCH 0316/1056] Fix minRelayTxFee name in comment --- mempool/policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/policy.go b/mempool/policy.go index f4e3b51ee7..7e97329319 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -61,7 +61,7 @@ const ( func calcMinRequiredTxRelayFee(serializedSize int64, minRelayTxFee btcutil.Amount) int64 { // Calculate the minimum fee for a transaction to be allowed into the // mempool and relayed by scaling the base fee (which is the minimum - // free transaction relay fee). minTxRelayFee is in Satoshi/kB so + // free transaction relay fee). minRelayTxFee is in Satoshi/kB so // multiply by serializedSize (which is in bytes) and divide by 1000 to // get minimum Satoshis. minFee := (serializedSize * int64(minRelayTxFee)) / 1000 From 1639d6c070d904c4a716b8d8435b4d98461fa5c4 Mon Sep 17 00:00:00 2001 From: Henry Harder Date: Thu, 26 Dec 2019 16:59:10 -0500 Subject: [PATCH 0317/1056] release: add missing back tick in build docs --- release/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/README.md b/release/README.md index 10d1c80cc0..a5c9681947 100644 --- a/release/README.md +++ b/release/README.md @@ -17,7 +17,7 @@ release binaries. However, on Windows, the only way to build the release binaries at the moment is by using the Windows Subsystem Linux. One can build the release binaries following these steps: -1. `git clone https://github.com/btcsuite/btcd.git +1. `git clone https://github.com/btcsuite/btcd.git` 2. `cd btcd` 3. `./build/release/release.sh # is the name of the next release/tag` From 8bbbe98be9005a7d77837e23ddb783ef1f062b7a Mon Sep 17 00:00:00 2001 From: George Tankersley Date: Wed, 9 Oct 2019 16:18:20 -0400 Subject: [PATCH 0318/1056] peer: fix small typo --- peer/peer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peer/peer.go b/peer/peer.go index 11306ace49..200acb32af 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -2097,7 +2097,7 @@ func (p *Peer) negotiateInboundProtocol() error { return p.readRemoteVerAckMsg() } -// negotiateOutoundProtocol performs the negotiation protocol for an outbound +// negotiateOutboundProtocol performs the negotiation protocol for an outbound // peer. The events should occur in the following order, otherwise an error is // returned: // From 0c76fbd26ff682c6a2ceb8a8df2267503c66dedf Mon Sep 17 00:00:00 2001 From: Nisen Date: Sun, 3 Mar 2019 09:42:32 +0800 Subject: [PATCH 0319/1056] Fix comment error --- database/ffldb/interface_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/database/ffldb/interface_test.go b/database/ffldb/interface_test.go index 4989913de9..1ce991cc09 100644 --- a/database/ffldb/interface_test.go +++ b/database/ffldb/interface_test.go @@ -1299,8 +1299,7 @@ func testFetchBlockIO(tc *testContext, tx database.Tx) bool { return false } - // Ensure the block header fetched from the database matches the - // expected bytes. + // Ensure block hash exists as expected. hasBlock, err := tx.HasBlock(blockHash) if err != nil { tc.t.Errorf("HasBlock(%s): unexpected error: %v", From 318c89dfed25ecfa916b966c965e157f088d5205 Mon Sep 17 00:00:00 2001 From: Yash Bhutwala Date: Tue, 25 Jun 2019 19:57:39 -0400 Subject: [PATCH 0320/1056] fix comment of database.Tx to match code --- database/ffldb/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/ffldb/db.go b/database/ffldb/db.go index fd1ff895c3..b499442101 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -950,7 +950,7 @@ type pendingBlock struct { } // transaction represents a database transaction. It can either be read-only or -// read-write and implements the database.Bucket interface. The transaction +// read-write and implements the database.Tx interface. The transaction // provides a root bucket against which all read and writes occur. type transaction struct { managed bool // Is the transaction managed? From 46461dc84a2195ee699b1cf3997c075220db71ba Mon Sep 17 00:00:00 2001 From: "shuai.qi" Date: Sat, 6 Jul 2019 00:13:54 +0800 Subject: [PATCH 0321/1056] btcjson, rpclient: Fix typo --- btcjson/jsonrpc.go | 4 ++-- rpcclient/doc.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/btcjson/jsonrpc.go b/btcjson/jsonrpc.go index e99d9f4265..0ead85e5ee 100644 --- a/btcjson/jsonrpc.go +++ b/btcjson/jsonrpc.go @@ -22,10 +22,10 @@ type RPCError struct { Message string `json:"message,omitempty"` } -// Guarantee RPCError satisifies the builtin error interface. +// Guarantee RPCError satisfies the builtin error interface. var _, _ error = RPCError{}, (*RPCError)(nil) -// Error returns a string describing the RPC error. This satisifies the +// Error returns a string describing the RPC error. This satisfies the // builtin error interface. func (e RPCError) Error() string { return fmt.Sprintf("%d: %s", e.Code, e.Message) diff --git a/rpcclient/doc.go b/rpcclient/doc.go index d4bbb64d65..b682ba10f2 100644 --- a/rpcclient/doc.go +++ b/rpcclient/doc.go @@ -106,7 +106,7 @@ Some of the commands are extensions specific to a particular RPC server. For example, the DebugLevel call is an extension only provided by btcd (and btcwallet passthrough). Therefore if you call one of these commands against an RPC server that doesn't provide them, you will get an unimplemented error -from the server. An effort has been made to call out which commmands are +from the server. An effort has been made to call out which commands are extensions in their documentation. Also, it is important to realize that btcd intentionally separates the wallet From ef4cecf42b620a8074194e260631fe06e4501b60 Mon Sep 17 00:00:00 2001 From: qshuai Date: Tue, 29 Jan 2019 09:36:42 +0800 Subject: [PATCH 0322/1056] blockchain/indexers: Start a new line for long code --- blockchain/indexers/addrindex.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 29d9030a2c..4a9bf4ec68 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -155,7 +155,9 @@ func serializeAddrIndexEntry(blockID uint32, txLoc wire.TxLoc) []byte { // provided region struct according to the format described in detail above and // uses the passed block hash fetching function in order to conver the block ID // to the associated block hash. -func deserializeAddrIndexEntry(serialized []byte, region *database.BlockRegion, fetchBlockHash fetchBlockHashFunc) error { +func deserializeAddrIndexEntry(serialized []byte, region *database.BlockRegion, + fetchBlockHash fetchBlockHashFunc) error { + // Ensure there are enough bytes to decode. if len(serialized) < txEntrySize { return errDeserialize("unexpected end of data") @@ -182,7 +184,9 @@ func keyForLevel(addrKey [addrKeySize]byte, level uint8) [levelKeySize]byte { // dbPutAddrIndexEntry updates the address index to include the provided entry // according to the level-based scheme described in detail above. -func dbPutAddrIndexEntry(bucket internalBucket, addrKey [addrKeySize]byte, blockID uint32, txLoc wire.TxLoc) error { +func dbPutAddrIndexEntry(bucket internalBucket, addrKey [addrKeySize]byte, + blockID uint32, txLoc wire.TxLoc) error { + // Start with level 0 and its initial max number of entries. curLevel := uint8(0) maxLevelBytes := level0MaxEntries * txEntrySize @@ -253,7 +257,10 @@ func dbPutAddrIndexEntry(bucket internalBucket, addrKey [addrKeySize]byte, block // the given address key and the number of entries skipped since it could have // been less in the case where there are less total entries than the requested // number of entries to skip. -func dbFetchAddrIndexEntries(bucket internalBucket, addrKey [addrKeySize]byte, numToSkip, numRequested uint32, reverse bool, fetchBlockHash fetchBlockHashFunc) ([]database.BlockRegion, uint32, error) { +func dbFetchAddrIndexEntries(bucket internalBucket, addrKey [addrKeySize]byte, + numToSkip, numRequested uint32, reverse bool, + fetchBlockHash fetchBlockHashFunc) ([]database.BlockRegion, uint32, error) { + // When the reverse flag is not set, all levels need to be fetched // because numToSkip and numRequested are counted from the oldest // transactions (highest level) and thus the total count is needed. @@ -356,7 +363,9 @@ func maxEntriesForLevel(level uint8) int { // dbRemoveAddrIndexEntries removes the specified number of entries from from // the address index for the provided key. An assertion error will be returned // if the count exceeds the total number of entries in the index. -func dbRemoveAddrIndexEntries(bucket internalBucket, addrKey [addrKeySize]byte, count int) error { +func dbRemoveAddrIndexEntries(bucket internalBucket, addrKey [addrKeySize]byte, + count int) error { + // Nothing to do if no entries are being deleted. if count <= 0 { return nil @@ -796,7 +805,9 @@ func (idx *AddrIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block, // that involve a given address. // // This function is safe for concurrent access. -func (idx *AddrIndex) TxRegionsForAddress(dbTx database.Tx, addr btcutil.Address, numToSkip, numRequested uint32, reverse bool) ([]database.BlockRegion, uint32, error) { +func (idx *AddrIndex) TxRegionsForAddress(dbTx database.Tx, addr btcutil.Address, + numToSkip, numRequested uint32, reverse bool) ([]database.BlockRegion, uint32, error) { + addrKey, err := addrToKey(addr) if err != nil { return nil, 0, err From e2c08cc80b7071034ae36ea8e0359d0c0930ad74 Mon Sep 17 00:00:00 2001 From: mohanson Date: Mon, 27 Aug 2018 10:41:57 +0800 Subject: [PATCH 0323/1056] docs/json_rpc_api: update go examples --- docs/json_rpc_api.md | 69 ++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index 51d4c82c3f..4bb0625e89 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -1074,7 +1074,7 @@ various languages. **9.1 Go** This section provides examples of using the RPC interface using Go and the -[btcrpcclient](https://github.com/btcsuite/btcrpcclient) package. +[rpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) package. * [Using getblockcount to Retrieve the Current Block Height](#ExampleGetBlockCount) * [Using getblock to Retrieve the Genesis Block](#ExampleGetBlock) @@ -1086,7 +1086,7 @@ This section provides examples of using the RPC interface using Go and the **9.1.1 Using getblockcount to Retrieve the Current Block Height**
The following is an example Go application which uses the -[btcrpcclient](https://github.com/btcsuite/btcrpcclient) package to connect with +[rpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) package to connect with a btcd instance via Websockets, issues [getblockcount](#getblockcount) to retrieve the current block height, and displays it. @@ -1094,11 +1094,12 @@ retrieve the current block height, and displays it. package main import ( - "github.com/btcsuite/btcrpcclient" - "github.com/btcsuite/btcutil" "io/ioutil" "log" "path/filepath" + + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcutil" ) func main() { @@ -1114,14 +1115,14 @@ func main() { // Create a new RPC client using websockets. Since this example is // not long-lived, the connection will be closed as soon as the program // exits. - connCfg := &btcrpcclient.ConnConfig{ + connCfg := &rpcclient.ConnConfig{ Host: "localhost:8334", Endpoint: "ws", User: "yourrpcuser", Pass: "yourrpcpass", Certificates: certs, } - client, err := btcrpcclient.New(connCfg, nil) + client, err := rpcclient.New(connCfg, nil) if err != nil { log.Fatal(err) } @@ -1139,7 +1140,7 @@ func main() { Which results in: ```bash -Block count: 276978 +2018/08/27 11:17:27 Block count: 536027 ```
@@ -1147,7 +1148,7 @@ Block count: 276978 **9.1.2 Using getblock to Retrieve the Genesis Block**
The following is an example Go application which uses the -[btcrpcclient](https://github.com/btcsuite/btcrpcclient) package to connect with +[rpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) package to connect with a btcd instance via Websockets, issues [getblock](#getblock) to retrieve information about the Genesis block, and display a few details about it. @@ -1155,14 +1156,14 @@ information about the Genesis block, and display a few details about it. package main import ( - "github.com/btcsuite/btcrpcclient" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" "io/ioutil" "log" "path/filepath" "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcutil" ) func main() { @@ -1178,14 +1179,14 @@ func main() { // Create a new RPC client using websockets. Since this example is // not long-lived, the connection will be closed as soon as the program // exits. - connCfg := &btcrpcclient.ConnConfig{ + connCfg := &rpcclient.ConnConfig{ Host: "localhost:18334", Endpoint: "ws", User: "yourrpcuser", Pass: "yourrpcpass", Certificates: certs, } - client, err := btcrpcclient.New(connCfg, nil) + client, err := rpcclient.New(connCfg, nil) if err != nil { log.Fatal(err) } @@ -1199,7 +1200,7 @@ func main() { if err != nil { log.Fatal(err) } - block, err := client.GetBlockVerbose(blockHash, false) + block, err := client.GetBlockVerbose(blockHash) if err != nil { log.Fatal(err) } @@ -1225,7 +1226,7 @@ Previous Block: 0000000000000000000000000000000000000000000000000000000000000000 Next Block: 00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048 Merkle root: 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b Timestamp: 2009-01-03 18:15:05 +0000 UTC -Confirmations: 277290 +Confirmations: 534323 Difficulty: 1.000000 Size (in bytes): 285 Num transactions: 1 @@ -1237,7 +1238,7 @@ Num transactions: 1 Notifications (Websocket-specific)**
The following is an example Go application which uses the -[btcrpcclient](https://github.com/btcsuite/btcrpcclient) package to connect with +[rpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) package to connect with a btcd instance via Websockets and registers for [blockconnected](#blockconnected) and [blockdisconnected](#blockdisconnected) notifications with [notifyblocks](#notifyblocks). It also sets up handlers for @@ -1247,25 +1248,25 @@ the notifications. package main import ( - "github.com/btcsuite/btcrpcclient" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" "io/ioutil" "log" "path/filepath" "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcutil" ) func main() { // Setup handlers for blockconnected and blockdisconnected // notifications. - ntfnHandlers := btcrpcclient.NotificationHandlers{ - OnBlockConnected: func(hash *chainhash.Hash, height int32) { - log.Printf("Block connected: %v (%d)", hash, height) + ntfnHandlers := rpcclient.NotificationHandlers{ + OnBlockConnected: func(hash *chainhash.Hash, height int32, t time.Time) { + log.Printf("Block connected: %v (%d) %s", hash, height, t) }, - OnBlockDisconnected: func(hash *chainhash.Hash, height int32) { - log.Printf("Block disconnected: %v", hash, height) + OnBlockDisconnected: func(hash *chainhash.Hash, height int32, t time.Time) { + log.Printf("Block disconnected: %v (%d) %s", hash, height, t) }, } @@ -1279,14 +1280,14 @@ func main() { } // Create a new RPC client using websockets. - connCfg := &btcrpcclient.ConnConfig{ + connCfg := &rpcclient.ConnConfig{ Host: "localhost:8334", Endpoint: "ws", User: "yourrpcuser", Pass: "yourrpcpass", Certificates: certs, } - client, err := btcrpcclient.New(connCfg, &ntfnHandlers) + client, err := rpcclient.New(connCfg, &ntfnHandlers) if err != nil { log.Fatal(err) } @@ -1316,10 +1317,14 @@ func main() { Example output: ``` -2014/05/12 20:33:17 Client shutdown in 10 seconds... -2014/05/12 20:33:19 Block connected: 000000000000000007dff1f95f7b3f5eac2892a4123069517caf34e2c417650d (300461) -2014/05/12 20:33:27 Client shutting down... -2014/05/12 20:31:27 Client shutdown complete. +2018/08/27 10:35:43 Client shutdown in 10 seconds... +2018/08/27 10:35:44 Block connected: 00000000000000000003321723557df58914658dc6fd963d547292a0a4797454 (534747) 2018-08-02 06:37:52 +0800 CST +2018/08/27 10:35:47 Block connected: 0000000000000000002e12773b798fc61dffe00ed5c3e89d3c306f8058c51e13 (534748) 2018-08-02 06:39:54 +0800 CST +2018/08/27 10:35:49 Block connected: 0000000000000000001bb311cd849839ce88499b91a201922f55a1cfafabe267 (534749) 2018-08-02 06:44:22 +0800 CST +2018/08/27 10:35:50 Block connected: 00000000000000000019d7296c9b5c175369ad337ec44b76bd4728021a09b864 (534750) 2018-08-02 06:55:44 +0800 CST +2018/08/27 10:35:53 Block connected: 00000000000000000022db98cf47e944ed58ca450c819e8fef8f8c71ca5d9901 (534751) 2018-08-02 06:57:39 +0800 CST +2018/08/27 10:35:53 Client shutting down... +2018/08/27 10:35:53 Client shutdown complete. ```
From 06e5c43499a2f30a1f7d7c3b49de0073dfbbdd1f Mon Sep 17 00:00:00 2001 From: Kulpreet Singh Date: Wed, 18 Jul 2018 14:25:34 +0200 Subject: [PATCH 0324/1056] Add note about using gencerts when listening on specific interfaces --- docs/configure_peer_server_listen_interfaces.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/configure_peer_server_listen_interfaces.md b/docs/configure_peer_server_listen_interfaces.md index 26f5ec72a1..ac61137335 100644 --- a/docs/configure_peer_server_listen_interfaces.md +++ b/docs/configure_peer_server_listen_interfaces.md @@ -33,3 +33,11 @@ The following config file would configure btcd to only listen on localhost for b listen=127.0.0.1:8333 listen=[::1]:8333 ``` + +In addition, if you are starting btcd with TLS and want to make it +available via a hostname, then you will need to generate the TLS +certificates for that host. For example, + +``` +gencerts --host=myhostname.example.com --directory=/home/me/.btcd/ +``` From 160c388285f5ae4ccea484185b93b15d9e35a432 Mon Sep 17 00:00:00 2001 From: jalavosus Date: Fri, 31 Jan 2020 12:27:38 -0500 Subject: [PATCH 0325/1056] Refactor GetBlockCmd type and NewGetBlockCmd() function to follow the bitcoin json RPC verbosity format for getblock, which uses 0, 1, or 2 as parameters rather than a boolean true or false. --- btcjson/chainsvrcmds.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 406357bd06..031eafd606 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -130,8 +130,7 @@ func NewGetBestBlockHashCmd() *GetBestBlockHashCmd { // GetBlockCmd defines the getblock JSON-RPC command. type GetBlockCmd struct { Hash string - Verbose *bool `jsonrpcdefault:"true"` - VerboseTx *bool `jsonrpcdefault:"false"` + Verbosity *int `jsonrpcdefault:"0"` } // NewGetBlockCmd returns a new instance which can be used to issue a getblock @@ -139,11 +138,10 @@ type GetBlockCmd struct { // // The parameters which are pointers indicate they are optional. Passing nil // for optional parameters will use the default value. -func NewGetBlockCmd(hash string, verbose, verboseTx *bool) *GetBlockCmd { +func NewGetBlockCmd(hash string, verbosity *int) *GetBlockCmd { return &GetBlockCmd{ Hash: hash, - Verbose: verbose, - VerboseTx: verboseTx, + Verbosity: verbosity, } } From 468154a05228669a4eddc4166c749a2b075aba1b Mon Sep 17 00:00:00 2001 From: jalavosus Date: Fri, 31 Jan 2020 12:29:20 -0500 Subject: [PATCH 0326/1056] Refactor GetBlockVerboseResult into two separate types: one type for getblock "hash" verbosity=1, and a second type for getblock "hash" verbosity=2. This is necessary due to how getblock returns a block's transaction data based on the provided verbosity parameter. If verbosity=1, then getblock.Tx is an array of a block's transaction ids (txids) as strings. If verbosity=2, then getblock.Tx is an array of raw transaction data. --- btcjson/chainsvrresults.go | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 7e6c710766..81d0517e42 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -25,8 +25,11 @@ type GetBlockHeaderVerboseResult struct { } // GetBlockVerboseResult models the data from the getblock command when the -// verbose flag is set. When the verbose flag is not set, getblock returns a -// hex-encoded string. +// verbose flag is set to 1. When the verbose flag is set to 0, getblock returns a +// hex-encoded string. When the verbose flag is set to 1, getblock returns an object +// whose tx field is an array of transaction hashes. When the verbose flag is set to 2, +// getblock returns an object whose tx field is an array of raw transactions. +// Use GetBlockVerboseTxResult to unmarshal data received from passing verbose=2 to getblock. type GetBlockVerboseResult struct { Hash string `json:"hash"` Confirmations int64 `json:"confirmations"` @@ -38,7 +41,32 @@ type GetBlockVerboseResult struct { VersionHex string `json:"versionHex"` MerkleRoot string `json:"merkleroot"` Tx []string `json:"tx,omitempty"` - RawTx []TxRawResult `json:"rawtx,omitempty"` + RawTx []TxRawResult `json:"rawtx,omitempty"` // Note: this field is always empty when verbose != 2. + Time int64 `json:"time"` + Nonce uint32 `json:"nonce"` + Bits string `json:"bits"` + Difficulty float64 `json:"difficulty"` + PreviousHash string `json:"previousblockhash"` + NextHash string `json:"nextblockhash,omitempty"` +} + +// GetBlockVerboseTxResult models the data from the getblock command when the +// verbose flag is set to 2. When the verbose flag is set to 0, getblock returns a +// hex-encoded string. When the verbose flag is set to 1, getblock returns an object +// whose tx field is an array of transaction hashes. When the verbose flag is set to 2, +// getblock returns an object whose tx field is an array of raw transactions. +// Use GetBlockVerboseResult to unmarshal data received from passing verbose=1 to getblock. +type GetBlockVerboseTxResult struct { + Hash string `json:"hash"` + Confirmations int64 `json:"confirmations"` + StrippedSize int32 `json:"strippedsize"` + Size int32 `json:"size"` + Weight int32 `json:"weight"` + Height int64 `json:"height"` + Version int32 `json:"version"` + VersionHex string `json:"versionHex"` + MerkleRoot string `json:"merkleroot"` + Tx []TxRawResult `json:"tx,omitempty"` Time int64 `json:"time"` Nonce uint32 `json:"nonce"` Bits string `json:"bits"` From 57cb8e4b11a76282166442ec149625712edb945f Mon Sep 17 00:00:00 2001 From: jalavosus Date: Fri, 31 Jan 2020 12:31:47 -0500 Subject: [PATCH 0327/1056] Refactor FutureGetBlockVerboseResult into two types: FutureGetBlockVerboseResult, and FutureGetBlockVerboseTxResult. Due to differences in how getblock returns data based on the provided verbosity parameter, it's necessary to have two separate return types based on verbosity. This necessitates a separate unmarshalling function (represented throughout rpcclient/chain.go as Result.Receive()) to ensure that data is correctly unmarshalled and returned to the user. --- btcjson/chainsvrcmds_test.go | 31 ++++++++++++------------------- btcjson/cmdinfo_test.go | 2 +- btcjson/example_test.go | 12 +++++------- rpcclient/chain.go | 32 ++++++++++++++++++++++++++------ rpcserver.go | 4 ++-- 5 files changed, 46 insertions(+), 35 deletions(-) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 8cb4ee765a..a861af1aa7 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -142,50 +142,43 @@ func TestChainSvrCmds(t *testing.T) { { name: "getblock", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getblock", "123") + return btcjson.NewCmd("getblock", "123", btcjson.Int(0)) }, staticCmd: func() interface{} { - return btcjson.NewGetBlockCmd("123", nil, nil) + return btcjson.NewGetBlockCmd("123", btcjson.Int(0)) }, - marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123"],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",0],"id":1}`, unmarshalled: &btcjson.GetBlockCmd{ Hash: "123", - Verbose: btcjson.Bool(true), - VerboseTx: btcjson.Bool(false), + Verbosity: btcjson.Int(0), }, }, { name: "getblock required optional1", newCmd: func() (interface{}, error) { - // Intentionally use a source param that is - // more pointers than the destination to - // exercise that path. - verbosePtr := btcjson.Bool(true) - return btcjson.NewCmd("getblock", "123", &verbosePtr) + return btcjson.NewCmd("getblock", "123", btcjson.Int(1)) }, staticCmd: func() interface{} { - return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), nil) + return btcjson.NewGetBlockCmd("123", btcjson.Int(1)) }, - marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",true],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",1],"id":1}`, unmarshalled: &btcjson.GetBlockCmd{ Hash: "123", - Verbose: btcjson.Bool(true), - VerboseTx: btcjson.Bool(false), + Verbosity: btcjson.Int(1), }, }, { name: "getblock required optional2", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getblock", "123", true, true) + return btcjson.NewCmd("getblock", "123", btcjson.Int(2)) }, staticCmd: func() interface{} { - return btcjson.NewGetBlockCmd("123", btcjson.Bool(true), btcjson.Bool(true)) + return btcjson.NewGetBlockCmd("123", btcjson.Int(2)) }, - marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",true,true],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123",2],"id":1}`, unmarshalled: &btcjson.GetBlockCmd{ Hash: "123", - Verbose: btcjson.Bool(true), - VerboseTx: btcjson.Bool(true), + Verbosity: btcjson.Int(2), }, }, { diff --git a/btcjson/cmdinfo_test.go b/btcjson/cmdinfo_test.go index 044040279a..61a693e404 100644 --- a/btcjson/cmdinfo_test.go +++ b/btcjson/cmdinfo_test.go @@ -151,7 +151,7 @@ func TestMethodUsageText(t *testing.T) { { name: "getblock", method: "getblock", - expected: `getblock "hash" (verbose=true verbosetx=false)`, + expected: `getblock "hash" (verbosity=1)`, }, } diff --git a/btcjson/example_test.go b/btcjson/example_test.go index 527252c7fb..cbca495b38 100644 --- a/btcjson/example_test.go +++ b/btcjson/example_test.go @@ -21,7 +21,7 @@ func ExampleMarshalCmd() { // convenience function for creating a pointer out of a primitive for // optional parameters. blockHash := "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" - gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Bool(false), nil) + gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Int(1)) // Marshal the command to the format suitable for sending to the RPC // server. Typically the client would increment the id here which is @@ -38,7 +38,7 @@ func ExampleMarshalCmd() { fmt.Printf("%s\n", marshalledBytes) // Output: - // {"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",false],"id":1} + // {"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",1],"id":1} } // This example demonstrates how to unmarshal a JSON-RPC request and then @@ -46,7 +46,7 @@ func ExampleMarshalCmd() { func ExampleUnmarshalCmd() { // Ordinarily this would be read from the wire, but for this example, // it is hard coded here for clarity. - data := []byte(`{"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",false],"id":1}`) + data := []byte(`{"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",1],"id":1}`) // Unmarshal the raw bytes from the wire into a JSON-RPC request. var request btcjson.Request @@ -84,13 +84,11 @@ func ExampleUnmarshalCmd() { // Display the fields in the concrete command. fmt.Println("Hash:", gbCmd.Hash) - fmt.Println("Verbose:", *gbCmd.Verbose) - fmt.Println("VerboseTx:", *gbCmd.VerboseTx) + fmt.Println("Verbosity:", *gbCmd.Verbosity) // Output: // Hash: 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f - // Verbose: false - // VerboseTx: false + // Verbosity: 0 } // This example demonstrates how to marshal a JSON-RPC response. diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 996d80458c..6815e1fa78 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -97,7 +97,7 @@ func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult { hash = blockHash.String() } - cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), nil) + cmd := btcjson.NewGetBlockCmd(hash, nil) return c.sendCmd(cmd) } @@ -140,8 +140,9 @@ func (c *Client) GetBlockVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockV if blockHash != nil { hash = blockHash.String() } - - cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), nil) + // From the bitcoin-cli getblock documentation: + // "If verbosity is 1, returns an Object with information about block ." + cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(1)) return c.sendCmd(cmd) } @@ -154,18 +155,37 @@ func (c *Client) GetBlockVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockVe return c.GetBlockVerboseAsync(blockHash).Receive() } +type FutureGetBlockVerboseTxResult chan *response + +func (r FutureGetBlockVerboseTxResult) Receive() (*btcjson.GetBlockVerboseTxResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var blockResult btcjson.GetBlockVerboseTxResult + err = json.Unmarshal(res, &blockResult) + if err != nil { + return nil, err + } + + return &blockResult, nil +} + // GetBlockVerboseTxAsync returns an instance of a type that can be used to get // the result of the RPC at some future time by invoking the Receive function on // the returned instance. // // See GetBlockVerboseTx or the blocking version and more details. -func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseResult { +func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseTxResult { hash := "" if blockHash != nil { hash = blockHash.String() } + // From the bitcoin-cli getblock documentation: + // "If verbosity is 2, returns an Object with information about block and information about each transaction." + cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(2)) - cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), btcjson.Bool(true)) return c.sendCmd(cmd) } @@ -174,7 +194,7 @@ func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBloc // // See GetBlockVerbose if only transaction hashes are preferred. // See GetBlock to retrieve a raw block instead. -func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseResult, error) { +func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseTxResult, error) { return c.GetBlockVerboseTxAsync(blockHash).Receive() } diff --git a/rpcserver.go b/rpcserver.go index e762cc1a9d..2da7e9f57e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1084,7 +1084,7 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i // When the verbose flag isn't set, simply return the serialized block // as a hex-encoded string. - if c.Verbose != nil && !*c.Verbose { + if c.Verbosity != nil && *c.Verbosity == 0 { return hex.EncodeToString(blkBytes), nil } @@ -1137,7 +1137,7 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i NextHash: nextHashString, } - if c.VerboseTx == nil || !*c.VerboseTx { + if *c.Verbosity == 1 { transactions := blk.Transactions() txNames := make([]string, len(transactions)) for i, tx := range transactions { From a310aa6e7464e9624eb8078260e248c28c8f67bb Mon Sep 17 00:00:00 2001 From: jalavosus Date: Thu, 5 Mar 2020 06:35:34 -0500 Subject: [PATCH 0328/1056] All tests pass --- btcjson/cmdinfo_test.go | 2 +- btcjson/example_test.go | 6 +++--- rpcserverhelp.go | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/btcjson/cmdinfo_test.go b/btcjson/cmdinfo_test.go index 61a693e404..471fccfc77 100644 --- a/btcjson/cmdinfo_test.go +++ b/btcjson/cmdinfo_test.go @@ -151,7 +151,7 @@ func TestMethodUsageText(t *testing.T) { { name: "getblock", method: "getblock", - expected: `getblock "hash" (verbosity=1)`, + expected: `getblock "hash" (verbosity=0)`, }, } diff --git a/btcjson/example_test.go b/btcjson/example_test.go index cbca495b38..73dd804073 100644 --- a/btcjson/example_test.go +++ b/btcjson/example_test.go @@ -21,7 +21,7 @@ func ExampleMarshalCmd() { // convenience function for creating a pointer out of a primitive for // optional parameters. blockHash := "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" - gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Int(1)) + gbCmd := btcjson.NewGetBlockCmd(blockHash, btcjson.Int(0)) // Marshal the command to the format suitable for sending to the RPC // server. Typically the client would increment the id here which is @@ -38,7 +38,7 @@ func ExampleMarshalCmd() { fmt.Printf("%s\n", marshalledBytes) // Output: - // {"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",1],"id":1} + // {"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",0],"id":1} } // This example demonstrates how to unmarshal a JSON-RPC request and then @@ -46,7 +46,7 @@ func ExampleMarshalCmd() { func ExampleUnmarshalCmd() { // Ordinarily this would be read from the wire, but for this example, // it is hard coded here for clarity. - data := []byte(`{"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",1],"id":1}`) + data := []byte(`{"jsonrpc":"1.0","method":"getblock","params":["000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",0],"id":1}`) // Unmarshal the raw bytes from the wire into a JSON-RPC request. var request btcjson.Request diff --git a/rpcserverhelp.go b/rpcserverhelp.go index cc6935b512..cee2407566 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -162,10 +162,9 @@ var helpDescsEnUS = map[string]string{ // GetBlockCmd help. "getblock--synopsis": "Returns information about a block given its hash.", "getblock-hash": "The hash of the block", - "getblock-verbose": "Specifies the block is returned as a JSON object instead of hex-encoded string", - "getblock-verbosetx": "Specifies that each transaction is returned as a JSON object and only applies if the verbose flag is true (btcd extension)", - "getblock--condition0": "verbose=false", - "getblock--condition1": "verbose=true", + "getblock-verbosity": "Specifies whether the block data should be returned as a hex-encoded string (0), as parsed data with a slice of TXIDs (1), or as parsed data with parsed transaction data (2) ", + "getblock--condition0": "verbosity=0", + "getblock--condition1": "verbosity=1", "getblock--result0": "Hex-encoded bytes of the serialized block", // GetBlockChainInfoCmd help. From e9f15eda7e774d9bf6f49a7a10d3ed8440502265 Mon Sep 17 00:00:00 2001 From: "John C. Vernaleo" Date: Thu, 5 Mar 2020 16:46:29 -0500 Subject: [PATCH 0329/1056] rpcclient: Add net params to Client (#1467) * rpcclient: replace futures mainnet with params Adds a chaincfg.Params to the Client rpcclient: parse config to assign params * rpcclient: change address commands to Address * Change address future struct to contain a network field, so futures can return the correct type for Receive --- rpcclient/infrastructure.go | 71 ++++++++++++++++-------- rpcclient/wallet.go | 104 +++++++++++++++++++++++++----------- 2 files changed, 120 insertions(+), 55 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 7a8f1885d1..a2079886d3 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -25,6 +25,7 @@ import ( "time" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/go-socks/socks" "github.com/btcsuite/websocket" ) @@ -138,6 +139,10 @@ type Client struct { // config holds the connection configuration assoiated with this client. config *ConnConfig + // chainParams holds the params for the chain that this client is using, + // and is used for many wallet methods. + chainParams *chaincfg.Params + // wsConn is the underlying websocket connection when not in HTTP POST // mode. wsConn *websocket.Conn @@ -283,31 +288,29 @@ func (c *Client) trackRegisteredNtfns(cmd interface{}) { } } -type ( - // inMessage is the first type that an incoming message is unmarshaled - // into. It supports both requests (for notification support) and - // responses. The partially-unmarshaled message is a notification if - // the embedded ID (from the response) is nil. Otherwise, it is a - // response. - inMessage struct { - ID *float64 `json:"id"` - *rawNotification - *rawResponse - } +// inMessage is the first type that an incoming message is unmarshaled +// into. It supports both requests (for notification support) and +// responses. The partially-unmarshaled message is a notification if +// the embedded ID (from the response) is nil. Otherwise, it is a +// response. +type inMessage struct { + ID *float64 `json:"id"` + *rawNotification + *rawResponse +} - // rawNotification is a partially-unmarshaled JSON-RPC notification. - rawNotification struct { - Method string `json:"method"` - Params []json.RawMessage `json:"params"` - } +// rawNotification is a partially-unmarshaled JSON-RPC notification. +type rawNotification struct { + Method string `json:"method"` + Params []json.RawMessage `json:"params"` +} - // rawResponse is a partially-unmarshaled JSON-RPC response. For this - // to be valid (according to JSON-RPC 1.0 spec), ID may not be nil. - rawResponse struct { - Result json.RawMessage `json:"result"` - Error *btcjson.RPCError `json:"error"` - } -) +// rawResponse is a partially-unmarshaled JSON-RPC response. For this +// to be valid (according to JSON-RPC 1.0 spec), ID may not be nil. +type rawResponse struct { + Result json.RawMessage `json:"result"` + Error *btcjson.RPCError `json:"error"` +} // response is the raw bytes of a JSON-RPC result, or the error if the response // error object was non-null. @@ -1093,6 +1096,11 @@ type ConnConfig struct { // Pass is the passphrase to use to authenticate to the RPC server. Pass string + // Params is the string representing the network that the server + // is running. If there is no parameter set in the config, then + // mainnet will be used by default. + Params string + // DisableTLS specifies whether transport layer security should be // disabled. It is recommended to always use TLS if the RPC server // supports it as otherwise your username and password is sent across @@ -1290,6 +1298,23 @@ func New(config *ConnConfig, ntfnHandlers *NotificationHandlers) (*Client, error shutdown: make(chan struct{}), } + // Default network is mainnet, no parameters are necessary but if mainnet + // is specified it will be the param + switch config.Params { + case "": + fallthrough + case chaincfg.MainNetParams.Name: + client.chainParams = &chaincfg.MainNetParams + case chaincfg.TestNet3Params.Name: + client.chainParams = &chaincfg.TestNet3Params + case chaincfg.RegressionNetParams.Name: + client.chainParams = &chaincfg.RegressionNetParams + case chaincfg.SimNetParams.Name: + client.chainParams = &chaincfg.SimNetParams + default: + return nil, fmt.Errorf("rpcclient.New: Unknown chain %s", config.Params) + } + if start { log.Infof("Established connection to RPC server %s", config.Host) diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 27546f5de0..d43be26181 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -753,13 +753,16 @@ func (c *Client) SendManyComment(fromAccount string, // FutureAddMultisigAddressResult is a future promise to deliver the result of a // AddMultisigAddressAsync RPC invocation (or an applicable error). -type FutureAddMultisigAddressResult chan *response +type FutureAddMultisigAddressResult struct { + responseChannel chan *response + network *chaincfg.Params +} // Receive waits for the response promised by the future and returns the // multisignature address that requires the specified number of signatures for // the provided addresses. func (r FutureAddMultisigAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r) + res, err := receiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -771,7 +774,7 @@ func (r FutureAddMultisigAddressResult) Receive() (btcutil.Address, error) { return nil, err } - return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams) + return btcutil.DecodeAddress(addr, r.network) } // AddMultisigAddressAsync returns an instance of a type that can be used to get @@ -786,14 +789,17 @@ func (c *Client) AddMultisigAddressAsync(requiredSigs int, addresses []btcutil.A } cmd := btcjson.NewAddMultisigAddressCmd(requiredSigs, addrs, &account) - return c.sendCmd(cmd) + result := FutureAddMultisigAddressResult{ + network: c.chainParams, + responseChannel: c.sendCmd(cmd), + } + return result } // AddMultisigAddress adds a multisignature address that requires the specified // number of signatures for the provided addresses to the wallet. func (c *Client) AddMultisigAddress(requiredSigs int, addresses []btcutil.Address, account string) (btcutil.Address, error) { - return c.AddMultisigAddressAsync(requiredSigs, addresses, - account).Receive() + return c.AddMultisigAddressAsync(requiredSigs, addresses, account).Receive() } // FutureCreateMultisigResult is a future promise to deliver the result of a @@ -868,12 +874,15 @@ func (c *Client) CreateNewAccount(account string) error { // FutureGetNewAddressResult is a future promise to deliver the result of a // GetNewAddressAsync RPC invocation (or an applicable error). -type FutureGetNewAddressResult chan *response +type FutureGetNewAddressResult struct { + responseChannel chan *response + network *chaincfg.Params +} // Receive waits for the response promised by the future and returns a new // address. func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r) + res, err := receiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -885,7 +894,7 @@ func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) { return nil, err } - return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams) + return btcutil.DecodeAddress(addr, r.network) } // GetNewAddressAsync returns an instance of a type that can be used to get the @@ -895,23 +904,31 @@ func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) { // See GetNewAddress for the blocking version and more details. func (c *Client) GetNewAddressAsync(account string) FutureGetNewAddressResult { cmd := btcjson.NewGetNewAddressCmd(&account) - return c.sendCmd(cmd) + result := FutureGetNewAddressResult{ + network: c.chainParams, + responseChannel: c.sendCmd(cmd), + } + return result } -// GetNewAddress returns a new address. +// GetNewAddress returns a new address, and decodes based on the client's +// chain params. func (c *Client) GetNewAddress(account string) (btcutil.Address, error) { return c.GetNewAddressAsync(account).Receive() } // FutureGetRawChangeAddressResult is a future promise to deliver the result of // a GetRawChangeAddressAsync RPC invocation (or an applicable error). -type FutureGetRawChangeAddressResult chan *response +type FutureGetRawChangeAddressResult struct { + responseChannel chan *response + network *chaincfg.Params +} // Receive waits for the response promised by the future and returns a new // address for receiving change that will be associated with the provided // account. Note that this is only for raw transactions and NOT for normal use. func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r) + res, err := receiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -923,7 +940,7 @@ func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) { return nil, err } - return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams) + return btcutil.DecodeAddress(addr, r.network) } // GetRawChangeAddressAsync returns an instance of a type that can be used to @@ -933,7 +950,11 @@ func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) { // See GetRawChangeAddress for the blocking version and more details. func (c *Client) GetRawChangeAddressAsync(account string) FutureGetRawChangeAddressResult { cmd := btcjson.NewGetRawChangeAddressCmd(&account) - return c.sendCmd(cmd) + result := FutureGetRawChangeAddressResult{ + network: c.chainParams, + responseChannel: c.sendCmd(cmd), + } + return result } // GetRawChangeAddress returns a new address for receiving change that will be @@ -945,12 +966,15 @@ func (c *Client) GetRawChangeAddress(account string) (btcutil.Address, error) { // FutureAddWitnessAddressResult is a future promise to deliver the result of // a AddWitnessAddressAsync RPC invocation (or an applicable error). -type FutureAddWitnessAddressResult chan *response +type FutureAddWitnessAddressResult struct { + responseChannel chan *response + network *chaincfg.Params +} // Receive waits for the response promised by the future and returns the new // address. func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r) + res, err := receiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -962,7 +986,7 @@ func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) { return nil, err } - return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams) + return btcutil.DecodeAddress(addr, r.network) } // AddWitnessAddressAsync returns an instance of a type that can be used to get @@ -972,7 +996,11 @@ func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) { // See AddWitnessAddress for the blocking version and more details. func (c *Client) AddWitnessAddressAsync(address string) FutureAddWitnessAddressResult { cmd := btcjson.NewAddWitnessAddressCmd(address) - return c.sendCmd(cmd) + response := FutureAddWitnessAddressResult{ + network: c.chainParams, + responseChannel: c.sendCmd(cmd), + } + return response } // AddWitnessAddress adds a witness address for a script and returns the new @@ -983,12 +1011,15 @@ func (c *Client) AddWitnessAddress(address string) (btcutil.Address, error) { // FutureGetAccountAddressResult is a future promise to deliver the result of a // GetAccountAddressAsync RPC invocation (or an applicable error). -type FutureGetAccountAddressResult chan *response +type FutureGetAccountAddressResult struct { + responseChannel chan *response + network *chaincfg.Params +} // Receive waits for the response promised by the future and returns the current // Bitcoin address for receiving payments to the specified account. func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r) + res, err := receiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -1000,7 +1031,7 @@ func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) { return nil, err } - return btcutil.DecodeAddress(addr, &chaincfg.MainNetParams) + return btcutil.DecodeAddress(addr, r.network) } // GetAccountAddressAsync returns an instance of a type that can be used to get @@ -1010,7 +1041,11 @@ func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) { // See GetAccountAddress for the blocking version and more details. func (c *Client) GetAccountAddressAsync(account string) FutureGetAccountAddressResult { cmd := btcjson.NewGetAccountAddressCmd(account) - return c.sendCmd(cmd) + result := FutureGetAccountAddressResult{ + network: c.chainParams, + responseChannel: c.sendCmd(cmd), + } + return result } // GetAccountAddress returns the current Bitcoin address for receiving payments @@ -1086,12 +1121,15 @@ func (c *Client) SetAccount(address btcutil.Address, account string) error { // FutureGetAddressesByAccountResult is a future promise to deliver the result // of a GetAddressesByAccountAsync RPC invocation (or an applicable error). -type FutureGetAddressesByAccountResult chan *response +type FutureGetAddressesByAccountResult struct { + responseChannel chan *response + network *chaincfg.Params +} // Receive waits for the response promised by the future and returns the list of // addresses associated with the passed account. func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error) { - res, err := receiveFuture(r) + res, err := receiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -1103,17 +1141,15 @@ func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error) return nil, err } - addrs := make([]btcutil.Address, 0, len(addrStrings)) - for _, addrStr := range addrStrings { - addr, err := btcutil.DecodeAddress(addrStr, - &chaincfg.MainNetParams) + addresses := make([]btcutil.Address, len(addrStrings)) + for i, addrString := range addrStrings { + addresses[i], err = btcutil.DecodeAddress(addrString, r.network) if err != nil { return nil, err } - addrs = append(addrs, addr) } - return addrs, nil + return addresses, nil } // GetAddressesByAccountAsync returns an instance of a type that can be used to @@ -1123,7 +1159,11 @@ func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error) // See GetAddressesByAccount for the blocking version and more details. func (c *Client) GetAddressesByAccountAsync(account string) FutureGetAddressesByAccountResult { cmd := btcjson.NewGetAddressesByAccountCmd(account) - return c.sendCmd(cmd) + result := FutureGetAddressesByAccountResult{ + network: c.chainParams, + responseChannel: c.sendCmd(cmd), + } + return result } // GetAddressesByAccount returns the list of addresses associated with the From 1d0bfca5b0e96a3bfb8a47e23ce8d04ae13aad9d Mon Sep 17 00:00:00 2001 From: Tyler Chambers Date: Sun, 12 Jan 2020 17:11:46 -0500 Subject: [PATCH 0330/1056] fix error message --- txscript/engine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/engine.go b/txscript/engine.go index db661860c8..f2d7b303c1 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -586,7 +586,7 @@ func (vm *Engine) checkPubKeyEncoding(pubKey []byte) error { if vm.hasFlag(ScriptVerifyWitnessPubKeyType) && vm.isWitnessVersionActive(0) && !btcec.IsCompressedPubKey(pubKey) { - str := "only uncompressed keys are accepted post-segwit" + str := "only compressed keys are accepted post-segwit" return scriptError(ErrWitnessPubKeyType, str) } From 9e94ccbd0ed1c12ee7fcffa1c2288e60951bc25d Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Fri, 16 Mar 2018 09:12:18 +0100 Subject: [PATCH 0331/1056] server: Fix incorrect log message format --- server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index edbc1c036e..b9bb18d0f5 100644 --- a/server.go +++ b/server.go @@ -1221,7 +1221,7 @@ func (sp *serverPeer) OnGetAddr(_ *peer.Peer, msg *wire.MsgGetAddr) { // Do not accept getaddr requests from outbound peers. This reduces // fingerprinting attacks. if !sp.Inbound() { - peerLog.Debugf("Ignoring getaddr request from outbound peer ", + peerLog.Debugf("Ignoring getaddr request from outbound peer "+ "%v", sp) return } @@ -1229,7 +1229,7 @@ func (sp *serverPeer) OnGetAddr(_ *peer.Peer, msg *wire.MsgGetAddr) { // Only allow one getaddr request per connection to discourage // address stamping of inv announcements. if sp.sentAddrs { - peerLog.Debugf("Ignoring repeated getaddr request from peer ", + peerLog.Debugf("Ignoring repeated getaddr request from peer "+ "%v", sp) return } From 96f3808dc98509a0c471d70ad1862e30a252c6a9 Mon Sep 17 00:00:00 2001 From: Jin Date: Sat, 7 Mar 2020 07:55:05 +0800 Subject: [PATCH 0332/1056] BUG:dynamicbanscore deadlock --- connmgr/dynamicbanscore.go | 2 +- connmgr/dynamicbanscore_test.go | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/connmgr/dynamicbanscore.go b/connmgr/dynamicbanscore.go index bc3c2a4581..38180bac12 100644 --- a/connmgr/dynamicbanscore.go +++ b/connmgr/dynamicbanscore.go @@ -71,7 +71,7 @@ type DynamicBanScore struct { func (s *DynamicBanScore) String() string { s.mtx.Lock() r := fmt.Sprintf("persistent %v + transient %v at %v = %v as of now", - s.persistent, s.transient, s.lastUnix, s.Int()) + s.persistent, s.transient, s.lastUnix, s.int(time.Now())) s.mtx.Unlock() return r } diff --git a/connmgr/dynamicbanscore_test.go b/connmgr/dynamicbanscore_test.go index 6dcd64d476..c6d67b4910 100644 --- a/connmgr/dynamicbanscore_test.go +++ b/connmgr/dynamicbanscore_test.go @@ -66,3 +66,15 @@ func TestDynamicBanScoreReset(t *testing.T) { t.Errorf("Failed to reset ban score.") } } + +// TestDynamicBanScoreString +func TestDynamicBanScoreString(t *testing.T) { + var bs DynamicBanScore + base := time.Now() + + r := bs.increase(100, 50, base) + if r != 150 { + t.Errorf("Unexpected result %d after ban score increase.", r) + } + t.Log(bs.String()) +} From fd0921b9b4513d5b916377a0813067ecdf6cdd63 Mon Sep 17 00:00:00 2001 From: Daniel McNally Date: Tue, 18 Feb 2020 01:51:23 -0500 Subject: [PATCH 0333/1056] btcjson: add RPC_IN_WARMUP error code This adds an error code for the `RPC_IN_WARMUP` error code defined at https://github.com/bitcoin/bitcoin/blob/master/src/rpc/protocol.h#L49 which is thrown when bitcoind has started but has not yet finished verifying recent blocks and being ready for rpc calls. --- btcjson/jsonrpcerr.go | 1 + 1 file changed, 1 insertion(+) diff --git a/btcjson/jsonrpcerr.go b/btcjson/jsonrpcerr.go index 8996c47461..ea62fb55a6 100644 --- a/btcjson/jsonrpcerr.go +++ b/btcjson/jsonrpcerr.go @@ -39,6 +39,7 @@ const ( ErrRPCDatabase RPCErrorCode = -20 ErrRPCDeserialization RPCErrorCode = -22 ErrRPCVerify RPCErrorCode = -25 + ErrRPCInWarmup RPCErrorCode = -28 ) // Peer-to-peer client errors. From d9ce6b037f4eeaf86d1d39bcd33ab776d0f2b6e4 Mon Sep 17 00:00:00 2001 From: Iskander Sharipov Date: Fri, 14 Sep 2018 00:13:06 +0300 Subject: [PATCH 0334/1056] btcjson,rpcclient: use proper Deprecated comment format This makes godoc and other Go tools understand deprecation notice. Found using https://go-critic.github.io/overview#deprecatedComment-ref --- btcjson/chainsvrwscmds.go | 20 ++++++++++---------- btcjson/chainsvrwsntfns.go | 36 ++++++++++++++++++------------------ rpcclient/notify.go | 34 +++++++++++++++++----------------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/btcjson/chainsvrwscmds.go b/btcjson/chainsvrwscmds.go index bf973e2559..dfe499ec5d 100644 --- a/btcjson/chainsvrwscmds.go +++ b/btcjson/chainsvrwscmds.go @@ -80,7 +80,7 @@ func NewStopNotifyNewTransactionsCmd() *StopNotifyNewTransactionsCmd { // NotifyReceivedCmd defines the notifyreceived JSON-RPC command. // -// NOTE: Deprecated. Use LoadTxFilterCmd instead. +// Deprecated: Use LoadTxFilterCmd instead. type NotifyReceivedCmd struct { Addresses []string } @@ -88,7 +88,7 @@ type NotifyReceivedCmd struct { // NewNotifyReceivedCmd returns a new instance which can be used to issue a // notifyreceived JSON-RPC command. // -// NOTE: Deprecated. Use NewLoadTxFilterCmd instead. +// Deprecated: Use NewLoadTxFilterCmd instead. func NewNotifyReceivedCmd(addresses []string) *NotifyReceivedCmd { return &NotifyReceivedCmd{ Addresses: addresses, @@ -128,7 +128,7 @@ func NewLoadTxFilterCmd(reload bool, addresses []string, outPoints []OutPoint) * // NotifySpentCmd defines the notifyspent JSON-RPC command. // -// NOTE: Deprecated. Use LoadTxFilterCmd instead. +// Deprecated: Use LoadTxFilterCmd instead. type NotifySpentCmd struct { OutPoints []OutPoint } @@ -136,7 +136,7 @@ type NotifySpentCmd struct { // NewNotifySpentCmd returns a new instance which can be used to issue a // notifyspent JSON-RPC command. // -// NOTE: Deprecated. Use NewLoadTxFilterCmd instead. +// Deprecated: Use NewLoadTxFilterCmd instead. func NewNotifySpentCmd(outPoints []OutPoint) *NotifySpentCmd { return &NotifySpentCmd{ OutPoints: outPoints, @@ -145,7 +145,7 @@ func NewNotifySpentCmd(outPoints []OutPoint) *NotifySpentCmd { // StopNotifyReceivedCmd defines the stopnotifyreceived JSON-RPC command. // -// NOTE: Deprecated. Use LoadTxFilterCmd instead. +// Deprecated: Use LoadTxFilterCmd instead. type StopNotifyReceivedCmd struct { Addresses []string } @@ -153,7 +153,7 @@ type StopNotifyReceivedCmd struct { // NewStopNotifyReceivedCmd returns a new instance which can be used to issue a // stopnotifyreceived JSON-RPC command. // -// NOTE: Deprecated. Use NewLoadTxFilterCmd instead. +// Deprecated: Use NewLoadTxFilterCmd instead. func NewStopNotifyReceivedCmd(addresses []string) *StopNotifyReceivedCmd { return &StopNotifyReceivedCmd{ Addresses: addresses, @@ -162,7 +162,7 @@ func NewStopNotifyReceivedCmd(addresses []string) *StopNotifyReceivedCmd { // StopNotifySpentCmd defines the stopnotifyspent JSON-RPC command. // -// NOTE: Deprecated. Use LoadTxFilterCmd instead. +// Deprecated: Use LoadTxFilterCmd instead. type StopNotifySpentCmd struct { OutPoints []OutPoint } @@ -170,7 +170,7 @@ type StopNotifySpentCmd struct { // NewStopNotifySpentCmd returns a new instance which can be used to issue a // stopnotifyspent JSON-RPC command. // -// NOTE: Deprecated. Use NewLoadTxFilterCmd instead. +// Deprecated: Use NewLoadTxFilterCmd instead. func NewStopNotifySpentCmd(outPoints []OutPoint) *StopNotifySpentCmd { return &StopNotifySpentCmd{ OutPoints: outPoints, @@ -179,7 +179,7 @@ func NewStopNotifySpentCmd(outPoints []OutPoint) *StopNotifySpentCmd { // RescanCmd defines the rescan JSON-RPC command. // -// NOTE: Deprecated. Use RescanBlocksCmd instead. +// Deprecated: Use RescanBlocksCmd instead. type RescanCmd struct { BeginBlock string Addresses []string @@ -193,7 +193,7 @@ type RescanCmd struct { // The parameters which are pointers indicate they are optional. Passing nil // for optional parameters will use the default value. // -// NOTE: Deprecated. Use NewRescanBlocksCmd instead. +// Deprecated: Use NewRescanBlocksCmd instead. func NewRescanCmd(beginBlock string, addresses []string, outPoints []OutPoint, endBlock *string) *RescanCmd { return &RescanCmd{ BeginBlock: beginBlock, diff --git a/btcjson/chainsvrwsntfns.go b/btcjson/chainsvrwsntfns.go index 1f1562343c..58b7a54491 100644 --- a/btcjson/chainsvrwsntfns.go +++ b/btcjson/chainsvrwsntfns.go @@ -12,14 +12,14 @@ const ( // BlockConnectedNtfnMethod is the legacy, deprecated method used for // notifications from the chain server that a block has been connected. // - // NOTE: Deprecated. Use FilteredBlockConnectedNtfnMethod instead. + // Deprecated: Use FilteredBlockConnectedNtfnMethod instead. BlockConnectedNtfnMethod = "blockconnected" // BlockDisconnectedNtfnMethod is the legacy, deprecated method used for // notifications from the chain server that a block has been // disconnected. // - // NOTE: Deprecated. Use FilteredBlockDisconnectedNtfnMethod instead. + // Deprecated: Use FilteredBlockDisconnectedNtfnMethod instead. BlockDisconnectedNtfnMethod = "blockdisconnected" // FilteredBlockConnectedNtfnMethod is the new method used for @@ -35,7 +35,7 @@ const ( // notifications from the chain server that a transaction which pays to // a registered address has been processed. // - // NOTE: Deprecated. Use RelevantTxAcceptedNtfnMethod and + // Deprecated: Use RelevantTxAcceptedNtfnMethod and // FilteredBlockConnectedNtfnMethod instead. RecvTxNtfnMethod = "recvtx" @@ -43,7 +43,7 @@ const ( // notifications from the chain server that a transaction which spends a // registered outpoint has been processed. // - // NOTE: Deprecated. Use RelevantTxAcceptedNtfnMethod and + // Deprecated: Use RelevantTxAcceptedNtfnMethod and // FilteredBlockConnectedNtfnMethod instead. RedeemingTxNtfnMethod = "redeemingtx" @@ -51,14 +51,14 @@ const ( // notifications from the chain server that a legacy, deprecated rescan // operation has finished. // - // NOTE: Deprecated. Not used with rescanblocks command. + // Deprecated: Not used with rescanblocks command. RescanFinishedNtfnMethod = "rescanfinished" // RescanProgressNtfnMethod is the legacy, deprecated method used for // notifications from the chain server that a legacy, deprecated rescan // operation this is underway has made progress. // - // NOTE: Deprecated. Not used with rescanblocks command. + // Deprecated: Not used with rescanblocks command. RescanProgressNtfnMethod = "rescanprogress" // TxAcceptedNtfnMethod is the method used for notifications from the @@ -79,7 +79,7 @@ const ( // BlockConnectedNtfn defines the blockconnected JSON-RPC notification. // -// NOTE: Deprecated. Use FilteredBlockConnectedNtfn instead. +// Deprecated: Use FilteredBlockConnectedNtfn instead. type BlockConnectedNtfn struct { Hash string Height int32 @@ -89,7 +89,7 @@ type BlockConnectedNtfn struct { // NewBlockConnectedNtfn returns a new instance which can be used to issue a // blockconnected JSON-RPC notification. // -// NOTE: Deprecated. Use NewFilteredBlockConnectedNtfn instead. +// Deprecated: Use NewFilteredBlockConnectedNtfn instead. func NewBlockConnectedNtfn(hash string, height int32, time int64) *BlockConnectedNtfn { return &BlockConnectedNtfn{ Hash: hash, @@ -100,7 +100,7 @@ func NewBlockConnectedNtfn(hash string, height int32, time int64) *BlockConnecte // BlockDisconnectedNtfn defines the blockdisconnected JSON-RPC notification. // -// NOTE: Deprecated. Use FilteredBlockDisconnectedNtfn instead. +// Deprecated: Use FilteredBlockDisconnectedNtfn instead. type BlockDisconnectedNtfn struct { Hash string Height int32 @@ -110,7 +110,7 @@ type BlockDisconnectedNtfn struct { // NewBlockDisconnectedNtfn returns a new instance which can be used to issue a // blockdisconnected JSON-RPC notification. // -// NOTE: Deprecated. Use NewFilteredBlockDisconnectedNtfn instead. +// Deprecated: Use NewFilteredBlockDisconnectedNtfn instead. func NewBlockDisconnectedNtfn(hash string, height int32, time int64) *BlockDisconnectedNtfn { return &BlockDisconnectedNtfn{ Hash: hash, @@ -163,7 +163,7 @@ type BlockDetails struct { // RecvTxNtfn defines the recvtx JSON-RPC notification. // -// NOTE: Deprecated. Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn +// Deprecated: Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn // instead. type RecvTxNtfn struct { HexTx string @@ -173,7 +173,7 @@ type RecvTxNtfn struct { // NewRecvTxNtfn returns a new instance which can be used to issue a recvtx // JSON-RPC notification. // -// NOTE: Deprecated. Use NewRelevantTxAcceptedNtfn and +// Deprecated: Use NewRelevantTxAcceptedNtfn and // NewFilteredBlockConnectedNtfn instead. func NewRecvTxNtfn(hexTx string, block *BlockDetails) *RecvTxNtfn { return &RecvTxNtfn{ @@ -184,7 +184,7 @@ func NewRecvTxNtfn(hexTx string, block *BlockDetails) *RecvTxNtfn { // RedeemingTxNtfn defines the redeemingtx JSON-RPC notification. // -// NOTE: Deprecated. Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn +// Deprecated: Use RelevantTxAcceptedNtfn and FilteredBlockConnectedNtfn // instead. type RedeemingTxNtfn struct { HexTx string @@ -194,7 +194,7 @@ type RedeemingTxNtfn struct { // NewRedeemingTxNtfn returns a new instance which can be used to issue a // redeemingtx JSON-RPC notification. // -// NOTE: Deprecated. Use NewRelevantTxAcceptedNtfn and +// Deprecated: Use NewRelevantTxAcceptedNtfn and // NewFilteredBlockConnectedNtfn instead. func NewRedeemingTxNtfn(hexTx string, block *BlockDetails) *RedeemingTxNtfn { return &RedeemingTxNtfn{ @@ -205,7 +205,7 @@ func NewRedeemingTxNtfn(hexTx string, block *BlockDetails) *RedeemingTxNtfn { // RescanFinishedNtfn defines the rescanfinished JSON-RPC notification. // -// NOTE: Deprecated. Not used with rescanblocks command. +// Deprecated: Not used with rescanblocks command. type RescanFinishedNtfn struct { Hash string Height int32 @@ -215,7 +215,7 @@ type RescanFinishedNtfn struct { // NewRescanFinishedNtfn returns a new instance which can be used to issue a // rescanfinished JSON-RPC notification. // -// NOTE: Deprecated. Not used with rescanblocks command. +// Deprecated: Not used with rescanblocks command. func NewRescanFinishedNtfn(hash string, height int32, time int64) *RescanFinishedNtfn { return &RescanFinishedNtfn{ Hash: hash, @@ -226,7 +226,7 @@ func NewRescanFinishedNtfn(hash string, height int32, time int64) *RescanFinishe // RescanProgressNtfn defines the rescanprogress JSON-RPC notification. // -// NOTE: Deprecated. Not used with rescanblocks command. +// Deprecated: Not used with rescanblocks command. type RescanProgressNtfn struct { Hash string Height int32 @@ -236,7 +236,7 @@ type RescanProgressNtfn struct { // NewRescanProgressNtfn returns a new instance which can be used to issue a // rescanprogress JSON-RPC notification. // -// NOTE: Deprecated. Not used with rescanblocks command. +// Deprecated: Not used with rescanblocks command. func NewRescanProgressNtfn(hash string, height int32, time int64) *RescanProgressNtfn { return &RescanProgressNtfn{ Hash: hash, diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 2454a94696..1feb755605 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -95,7 +95,7 @@ type NotificationHandlers struct { // NotifyBlocks has been made to register for the notification and the // function is non-nil. // - // NOTE: Deprecated. Use OnFilteredBlockConnected instead. + // Deprecated: Use OnFilteredBlockConnected instead. OnBlockConnected func(hash *chainhash.Hash, height int32, t time.Time) // OnFilteredBlockConnected is invoked when a block is connected to the @@ -111,7 +111,7 @@ type NotificationHandlers struct { // NotifyBlocks has been made to register for the notification and the // function is non-nil. // - // NOTE: Deprecated. Use OnFilteredBlockDisconnected instead. + // Deprecated: Use OnFilteredBlockDisconnected instead. OnBlockDisconnected func(hash *chainhash.Hash, height int32, t time.Time) // OnFilteredBlockDisconnected is invoked when a block is disconnected @@ -127,7 +127,7 @@ type NotificationHandlers struct { // preceding call to NotifyReceived, Rescan, or RescanEndHeight has been // made to register for the notification and the function is non-nil. // - // NOTE: Deprecated. Use OnRelevantTxAccepted instead. + // Deprecated: Use OnRelevantTxAccepted instead. OnRecvTx func(transaction *btcutil.Tx, details *btcjson.BlockDetails) // OnRedeemingTx is invoked when a transaction that spends a registered @@ -141,7 +141,7 @@ type NotificationHandlers struct { // funds to the registered addresses. This means it is possible for // this to invoked indirectly as the result of a NotifyReceived call. // - // NOTE: Deprecated. Use OnRelevantTxAccepted instead. + // Deprecated: Use OnRelevantTxAccepted instead. OnRedeemingTx func(transaction *btcutil.Tx, details *btcjson.BlockDetails) // OnRelevantTxAccepted is invoked when an unmined transaction passes @@ -157,14 +157,14 @@ type NotificationHandlers struct { // result of a rescan request, due to how btcd may send various rescan // notifications after the rescan request has already returned. // - // NOTE: Deprecated. Not used with RescanBlocks. + // Deprecated: Not used with RescanBlocks. OnRescanFinished func(hash *chainhash.Hash, height int32, blkTime time.Time) // OnRescanProgress is invoked periodically when a rescan is underway. // It will only be invoked if a preceding call to Rescan or // RescanEndHeight has been made and the function is non-nil. // - // NOTE: Deprecated. Not used with RescanBlocks. + // Deprecated: Not used with RescanBlocks. OnRescanProgress func(hash *chainhash.Hash, height int32, blkTime time.Time) // OnTxAccepted is invoked when a transaction is accepted into the @@ -905,7 +905,7 @@ func (c *Client) NotifyBlocks() error { // FutureNotifySpentResult is a future promise to deliver the result of a // NotifySpentAsync RPC invocation (or an applicable error). // -// NOTE: Deprecated. Use FutureLoadTxFilterResult instead. +// Deprecated: Use FutureLoadTxFilterResult instead. type FutureNotifySpentResult chan *response // Receive waits for the response promised by the future and returns an error @@ -951,7 +951,7 @@ func newOutPointFromWire(op *wire.OutPoint) btcjson.OutPoint { // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use LoadTxFilterAsync instead. +// Deprecated: Use LoadTxFilterAsync instead. func (c *Client) NotifySpentAsync(outpoints []*wire.OutPoint) FutureNotifySpentResult { // Not supported in HTTP POST mode. if c.config.HTTPPostMode { @@ -983,7 +983,7 @@ func (c *Client) NotifySpentAsync(outpoints []*wire.OutPoint) FutureNotifySpentR // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use LoadTxFilter instead. +// Deprecated: Use LoadTxFilter instead. func (c *Client) NotifySpent(outpoints []*wire.OutPoint) error { return c.NotifySpentAsync(outpoints).Receive() } @@ -1040,7 +1040,7 @@ func (c *Client) NotifyNewTransactions(verbose bool) error { // FutureNotifyReceivedResult is a future promise to deliver the result of a // NotifyReceivedAsync RPC invocation (or an applicable error). // -// NOTE: Deprecated. Use FutureLoadTxFilterResult instead. +// Deprecated: Use FutureLoadTxFilterResult instead. type FutureNotifyReceivedResult chan *response // Receive waits for the response promised by the future and returns an error @@ -1078,7 +1078,7 @@ func (c *Client) notifyReceivedInternal(addresses []string) FutureNotifyReceived // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use LoadTxFilterAsync instead. +// Deprecated: Use LoadTxFilterAsync instead. func (c *Client) NotifyReceivedAsync(addresses []btcutil.Address) FutureNotifyReceivedResult { // Not supported in HTTP POST mode. if c.config.HTTPPostMode { @@ -1118,7 +1118,7 @@ func (c *Client) NotifyReceivedAsync(addresses []btcutil.Address) FutureNotifyRe // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use LoadTxFilter instead. +// Deprecated: Use LoadTxFilter instead. func (c *Client) NotifyReceived(addresses []btcutil.Address) error { return c.NotifyReceivedAsync(addresses).Receive() } @@ -1126,7 +1126,7 @@ func (c *Client) NotifyReceived(addresses []btcutil.Address) error { // FutureRescanResult is a future promise to deliver the result of a RescanAsync // or RescanEndHeightAsync RPC invocation (or an applicable error). // -// NOTE: Deprecated. Use FutureRescanBlocksResult instead. +// Deprecated: Use FutureRescanBlocksResult instead. type FutureRescanResult chan *response // Receive waits for the response promised by the future and returns an error @@ -1150,7 +1150,7 @@ func (r FutureRescanResult) Receive() error { // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use RescanBlocksAsync instead. +// Deprecated: Use RescanBlocksAsync instead. func (c *Client) RescanAsync(startBlock *chainhash.Hash, addresses []btcutil.Address, outpoints []*wire.OutPoint) FutureRescanResult { @@ -1215,7 +1215,7 @@ func (c *Client) RescanAsync(startBlock *chainhash.Hash, // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use RescanBlocks instead. +// Deprecated: Use RescanBlocks instead. func (c *Client) Rescan(startBlock *chainhash.Hash, addresses []btcutil.Address, outpoints []*wire.OutPoint) error { @@ -1231,7 +1231,7 @@ func (c *Client) Rescan(startBlock *chainhash.Hash, // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use RescanBlocksAsync instead. +// Deprecated: Use RescanBlocksAsync instead. func (c *Client) RescanEndBlockAsync(startBlock *chainhash.Hash, addresses []btcutil.Address, outpoints []*wire.OutPoint, endBlock *chainhash.Hash) FutureRescanResult { @@ -1293,7 +1293,7 @@ func (c *Client) RescanEndBlockAsync(startBlock *chainhash.Hash, // // NOTE: This is a btcd extension and requires a websocket connection. // -// NOTE: Deprecated. Use RescanBlocks instead. +// Deprecated: Use RescanBlocks instead. func (c *Client) RescanEndHeight(startBlock *chainhash.Hash, addresses []btcutil.Address, outpoints []*wire.OutPoint, endBlock *chainhash.Hash) error { From a8eadd2ce49aa6ac0be1672f971dcc3d173a9d80 Mon Sep 17 00:00:00 2001 From: Jake Sylvestre Date: Wed, 22 Jan 2020 01:13:15 -0500 Subject: [PATCH 0335/1056] update GetMempoolEntryResult to v0.19.0 https://bitcoincore.org/en/doc/0.19.0/rpc/blockchain/getmempoolentry/ --- btcjson/chainsvrresults.go | 40 +++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 81d0517e42..7ce32f4588 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -234,23 +234,35 @@ type GetBlockTemplateResult struct { RejectReasion string `json:"reject-reason,omitempty"` } +// GetMempoolEntryResult models the data returned from the getmempoolentry's +// fee field + +type MempoolFees struct { + Base float64 `json:"base"` + Modified float64 `json:"base"` + Ancestor float64 `json:"ancestor"` + Descendant float64 `json:"descendant"` +} + // GetMempoolEntryResult models the data returned from the getmempoolentry // command. type GetMempoolEntryResult struct { - Size int32 `json:"size"` - Fee float64 `json:"fee"` - ModifiedFee float64 `json:"modifiedfee"` - Time int64 `json:"time"` - Height int64 `json:"height"` - StartingPriority float64 `json:"startingpriority"` - CurrentPriority float64 `json:"currentpriority"` - DescendantCount int64 `json:"descendantcount"` - DescendantSize int64 `json:"descendantsize"` - DescendantFees float64 `json:"descendantfees"` - AncestorCount int64 `json:"ancestorcount"` - AncestorSize int64 `json:"ancestorsize"` - AncestorFees float64 `json:"ancestorfees"` - Depends []string `json:"depends"` + VSize int32 `json:"vsize"` + Size int32 `json:"size"` + Weight int64 `json:"weight"` + Fee float64 `json:"fee"` + ModifiedFee float64 `json:"modifiedfee"` + Time int64 `json:"time"` + Height int64 `json:"height"` + DescendantCount int64 `json:"descendantcount"` + DescendantSize int64 `json:"descendantsize"` + DescendantFees float64 `json:"descendantfees"` + AncestorCount int64 `json:"ancestorcount"` + AncestorSize int64 `json:"ancestorsize"` + AncestorFees float64 `json:"ancestorfees"` + WTxId string `json:"wtxid"` + Fees MempoolFees `json:"fees"` + Depends []string `json:"depends"` } // GetMempoolInfoResult models the data returned from the getmempoolinfo From 8b1be464630c54988cabe965c739a8b2575701ed Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Tue, 26 Nov 2019 14:33:48 +0100 Subject: [PATCH 0336/1056] Add generatetoaddress and estimatesmartfee RPCs --- btcjson/btcdextcmds.go | 18 ++++++++++++++ btcjson/btcdextcmds_test.go | 18 ++++++++++++++ btcjson/chainsvrresults.go | 8 ++++++ btcjson/walletsvrcmds.go | 25 +++++++++++++++++++ btcjson/walletsvrcmds_test.go | 28 +++++++++++++++++++++ rpcclient/chain.go | 35 ++++++++++++++++++++++++++ rpcclient/mining.go | 47 +++++++++++++++++++++++++++++++++++ 7 files changed, 179 insertions(+) diff --git a/btcjson/btcdextcmds.go b/btcjson/btcdextcmds.go index 963ccb3a3b..a3ca46ba71 100644 --- a/btcjson/btcdextcmds.go +++ b/btcjson/btcdextcmds.go @@ -59,6 +59,23 @@ func NewDebugLevelCmd(levelSpec string) *DebugLevelCmd { } } +// GenerateToAddressCmd defines the generatetoaddress JSON-RPC command. +type GenerateToAddressCmd struct { + NumBlocks int64 + Address string + MaxTries *int64 `jsonrpcdefault:"1000000"` +} + +// NewGenerateToAddressCmd returns a new instance which can be used to issue a +// generatetoaddress JSON-RPC command. +func NewGenerateToAddressCmd(numBlocks int64, address string, maxTries *int64) *GenerateToAddressCmd { + return &GenerateToAddressCmd{ + NumBlocks: numBlocks, + Address: address, + MaxTries: maxTries, + } +} + // GenerateCmd defines the generate JSON-RPC command. type GenerateCmd struct { NumBlocks uint32 @@ -131,6 +148,7 @@ func init() { MustRegisterCmd("debuglevel", (*DebugLevelCmd)(nil), flags) MustRegisterCmd("node", (*NodeCmd)(nil), flags) MustRegisterCmd("generate", (*GenerateCmd)(nil), flags) + MustRegisterCmd("generatetoaddress", (*GenerateToAddressCmd)(nil), flags) MustRegisterCmd("getbestblock", (*GetBestBlockCmd)(nil), flags) MustRegisterCmd("getcurrentnet", (*GetCurrentNetCmd)(nil), flags) MustRegisterCmd("getheaders", (*GetHeadersCmd)(nil), flags) diff --git a/btcjson/btcdextcmds_test.go b/btcjson/btcdextcmds_test.go index 10e6da3896..143ec5224f 100644 --- a/btcjson/btcdextcmds_test.go +++ b/btcjson/btcdextcmds_test.go @@ -114,6 +114,24 @@ func TestBtcdExtCmds(t *testing.T) { NumBlocks: 1, }, }, + { + name: "generatetoaddress", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("generatetoaddress", 1, "1Address") + }, + staticCmd: func() interface{} { + return btcjson.NewGenerateToAddressCmd(1, "1Address", nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"generatetoaddress","params":[1,"1Address"],"id":1}`, + unmarshalled: &btcjson.GenerateToAddressCmd{ + NumBlocks: 1, + Address: "1Address", + MaxTries: func() *int64 { + var i int64 = 1000000 + return &i + }(), + }, + }, { name: "getbestblock", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 7ce32f4588..a3a26c8976 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -624,3 +624,11 @@ type ValidateAddressChainResult struct { IsValid bool `json:"isvalid"` Address string `json:"address,omitempty"` } + +// EstimateSmartFeeResult models the data returned buy the chain server +// estimatesmartfee command +type EstimateSmartFeeResult struct { + FeeRate *float64 `json:"feerate,omitempty"` + Errors []string `json:"errors,omitempty"` + Blocks int64 `json:"blocks"` +} diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 6697555172..53bb93da14 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -81,6 +81,30 @@ func NewEncryptWalletCmd(passphrase string) *EncryptWalletCmd { } } +// EstimateSmartFeeMode defines the different fee estimation modes available +// for the estimatesmartfee JSON-RPC command. +type EstimateSmartFeeMode string + +var ( + EstimateModeUnset EstimateSmartFeeMode = "UNSET" + EstimateModeEconomical EstimateSmartFeeMode = "ECONOMICAL" + EstimateModeConservative EstimateSmartFeeMode = "CONSERVATIVE" +) + +// EstimateSmartFeeCmd defines the estimatesmartfee JSON-RPC command. +type EstimateSmartFeeCmd struct { + ConfTarget int64 + EstimateMode *EstimateSmartFeeMode `jsonrpcdefault:"\"CONSERVATIVE\""` +} + +// NewEstimateSmartFeeCmd returns a new instance which can be used to issue a +// estimatesmartfee JSON-RPC command. +func NewEstimateSmartFeeCmd(confTarget int64, mode *EstimateSmartFeeMode) *EstimateSmartFeeCmd { + return &EstimateSmartFeeCmd{ + ConfTarget: confTarget, EstimateMode: mode, + } +} + // EstimateFeeCmd defines the estimatefee JSON-RPC command. type EstimateFeeCmd struct { NumBlocks int64 @@ -662,6 +686,7 @@ func init() { MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags) MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags) MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags) + MustRegisterCmd("estimatesmartfee", (*EstimateSmartFeeCmd)(nil), flags) MustRegisterCmd("estimatefee", (*EstimateFeeCmd)(nil), flags) MustRegisterCmd("estimatepriority", (*EstimatePriorityCmd)(nil), flags) MustRegisterCmd("getaccount", (*GetAccountCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index efc08cc945..2e0f1d0f8e 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -128,6 +128,34 @@ func TestWalletSvrCmds(t *testing.T) { NumBlocks: 6, }, }, + { + name: "estimatesmartfee - no mode", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("estimatesmartfee", 6) + }, + staticCmd: func() interface{} { + return btcjson.NewEstimateSmartFeeCmd(6, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6],"id":1}`, + unmarshalled: &btcjson.EstimateSmartFeeCmd{ + ConfTarget: 6, + EstimateMode: &btcjson.EstimateModeConservative, + }, + }, + { + name: "estimatesmartfee - economical mode", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("estimatesmartfee", 6, btcjson.EstimateModeEconomical) + }, + staticCmd: func() interface{} { + return btcjson.NewEstimateSmartFeeCmd(6, &btcjson.EstimateModeEconomical) + }, + marshalled: `{"jsonrpc":"1.0","method":"estimatesmartfee","params":[6,"ECONOMICAL"],"id":1}`, + unmarshalled: &btcjson.EstimateSmartFeeCmd{ + ConfTarget: 6, + EstimateMode: &btcjson.EstimateModeEconomical, + }, + }, { name: "estimatepriority", newCmd: func() (interface{}, error) { diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 6815e1fa78..c656a19a8d 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -669,6 +669,41 @@ func (c *Client) EstimateFee(numBlocks int64) (float64, error) { return c.EstimateFeeAsync(numBlocks).Receive() } +// FutureEstimateFeeResult is a future promise to deliver the result of a +// EstimateSmartFeeAsync RPC invocation (or an applicable error). +type FutureEstimateSmartFeeResult chan *response + +// Receive waits for the response promised by the future and returns the +// estimated fee. +func (r FutureEstimateSmartFeeResult) Receive() (*btcjson.EstimateSmartFeeResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var verified btcjson.EstimateSmartFeeResult + err = json.Unmarshal(res, &verified) + if err != nil { + return nil, err + } + return &verified, nil +} + +// EstimateSmartFeeAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See EstimateSmartFee for the blocking version and more details. +func (c *Client) EstimateSmartFeeAsync(confTarget int64, mode *btcjson.EstimateSmartFeeMode) FutureEstimateSmartFeeResult { + cmd := btcjson.NewEstimateSmartFeeCmd(confTarget, mode) + return c.sendCmd(cmd) +} + +// EstimateSmartFee requests the server to estimate a fee level based on the given parameters. +func (c *Client) EstimateSmartFee(confTarget int64, mode *btcjson.EstimateSmartFeeMode) (*btcjson.EstimateSmartFeeResult, error) { + return c.EstimateSmartFeeAsync(confTarget, mode).Receive() +} + // FutureVerifyChainResult is a future promise to deliver the result of a // VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync // invocation (or an applicable error). diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 76a9d30580..8717d3278f 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -61,6 +61,53 @@ func (c *Client) Generate(numBlocks uint32) ([]*chainhash.Hash, error) { return c.GenerateAsync(numBlocks).Receive() } +// FutureGenerateToAddressResult is a future promise to deliver the result of a +// GenerateToAddressResult RPC invocation (or an applicable error). +type FutureGenerateToAddressResult chan *response + +// Receive waits for the response promised by the future and returns the hashes of +// of the generated blocks. +func (f FutureGenerateToAddressResult) Receive() ([]*chainhash.Hash, error) { + res, err := receiveFuture(f) + if err != nil { + return nil, err + } + + // Unmarshal result as a list of strings. + var result []string + err = json.Unmarshal(res, &result) + if err != nil { + return nil, err + } + + // Convert each block hash to a chainhash.Hash and store a pointer to + // each. + convertedResult := make([]*chainhash.Hash, len(result)) + for i, hashString := range result { + convertedResult[i], err = chainhash.NewHashFromStr(hashString) + if err != nil { + return nil, err + } + } + + return convertedResult, nil +} + +// GenerateToAddressAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GenerateToAddress for the blocking version and more details. +func (c *Client) GenerateToAddressAsync(numBlocks int64, address btcutil.Address, maxTries *int64) FutureGenerateToAddressResult { + cmd := btcjson.NewGenerateToAddressCmd(numBlocks, address.EncodeAddress(), maxTries) + return c.sendCmd(cmd) +} + +// GenerateToAddress generates numBlocks blocks to the given address and returns their hashes. +func (c *Client) GenerateToAddress(numBlocks int64, address btcutil.Address, maxTries *int64) ([]*chainhash.Hash, error) { + return c.GenerateToAddressAsync(numBlocks, address, maxTries).Receive() +} + // FutureGetGenerateResult is a future promise to deliver the result of a // GetGenerateAsync RPC invocation (or an applicable error). type FutureGetGenerateResult chan *response From cfcf4fb7625ab2e8ca26414e79b25cf979ff37b0 Mon Sep 17 00:00:00 2001 From: Ivan Kuznetsov Date: Wed, 27 Nov 2019 13:49:59 +0700 Subject: [PATCH 0337/1056] Implement 'getblockstats' JSON-RPC command --- btcjson/chainsvrcmds.go | 45 ++++++++++++++++++++++++++++++ btcjson/chainsvrcmds_test.go | 54 ++++++++++++++++++++++++++++++++++++ btcjson/chainsvrresults.go | 32 +++++++++++++++++++++ rpcclient/chain.go | 41 +++++++++++++++++++++++++++ 4 files changed, 172 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 031eafd606..90ab70ece7 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -191,6 +191,50 @@ func NewGetBlockHeaderCmd(hash string, verbose *bool) *GetBlockHeaderCmd { } } +// HashOrHeight defines a type that can be used as hash_or_height value in JSON-RPC commands. +type HashOrHeight struct { + Value interface{} +} + +// MarshalJSON implements the json.Marshaler interface +func (h HashOrHeight) MarshalJSON() ([]byte, error) { + return json.Marshal(h.Value) +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (h *HashOrHeight) UnmarshalJSON(data []byte) error { + var unmarshalled interface{} + if err := json.Unmarshal(data, &unmarshalled); err != nil { + return err + } + + switch v := unmarshalled.(type) { + case float64: + h.Value = int(v) + case string: + h.Value = v + default: + return fmt.Errorf("invalid hash_or_height value: %v", unmarshalled) + } + + return nil +} + +// GetBlockStatsCmd defines the getblockstats JSON-RPC command. +type GetBlockStatsCmd struct { + HashOrHeight HashOrHeight + Stats *[]string +} + +// NewGetBlockStatsCmd returns a new instance which can be used to issue a +// getblockstats JSON-RPC command. Either height or hash must be specified. +func NewGetBlockStatsCmd(hashOrHeight HashOrHeight, stats *[]string) *GetBlockStatsCmd { + return &GetBlockStatsCmd{ + HashOrHeight: hashOrHeight, + Stats: stats, + } +} + // TemplateRequest is a request object as defined in BIP22 // (https://en.bitcoin.it/wiki/BIP_0022), it is optionally provided as an // pointer argument to GetBlockTemplateCmd. @@ -798,6 +842,7 @@ func init() { MustRegisterCmd("getblockcount", (*GetBlockCountCmd)(nil), flags) MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags) MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags) + MustRegisterCmd("getblockstats", (*GetBlockStatsCmd)(nil), flags) MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags) MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags) MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index a861af1aa7..dca2332860 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -228,6 +228,60 @@ func TestChainSvrCmds(t *testing.T) { Verbose: btcjson.Bool(true), }, }, + { + name: "getblockstats height", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: 123}) + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: 123}, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":[123],"id":1}`, + unmarshalled: &btcjson.GetBlockStatsCmd{ + HashOrHeight: btcjson.HashOrHeight{Value: 123}, + }, + }, + { + name: "getblockstats hash", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: "deadbeef"}) + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: "deadbeef"}, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":["deadbeef"],"id":1}`, + unmarshalled: &btcjson.GetBlockStatsCmd{ + HashOrHeight: btcjson.HashOrHeight{Value: "deadbeef"}, + }, + }, + { + name: "getblockstats height optional stats", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: 123}, []string{"avgfee", "maxfee"}) + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: 123}, &[]string{"avgfee", "maxfee"}) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":[123,["avgfee","maxfee"]],"id":1}`, + unmarshalled: &btcjson.GetBlockStatsCmd{ + HashOrHeight: btcjson.HashOrHeight{Value: 123}, + Stats: &[]string{"avgfee", "maxfee"}, + }, + }, + { + name: "getblockstats hash optional stats", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockstats", btcjson.HashOrHeight{Value: "deadbeef"}, []string{"avgfee", "maxfee"}) + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: "deadbeef"}, &[]string{"avgfee", "maxfee"}) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockstats","params":["deadbeef",["avgfee","maxfee"]],"id":1}`, + unmarshalled: &btcjson.GetBlockStatsCmd{ + HashOrHeight: btcjson.HashOrHeight{Value: "deadbeef"}, + Stats: &[]string{"avgfee", "maxfee"}, + }, + }, { name: "getblocktemplate", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index a3a26c8976..8cd716d409 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -24,6 +24,38 @@ type GetBlockHeaderVerboseResult struct { NextHash string `json:"nextblockhash,omitempty"` } +// GetBlockStatsResult models the data from the getblockstats command. +type GetBlockStatsResult struct { + AverageFee int64 `json:"avgfee"` + AverageFeeRate int64 `json:"avgfeerate"` + AverageTxSize int64 `json:"avgtxsize"` + FeeratePercentiles []int64 `json:"feerate_percentiles"` + Hash string `json:"blockhash"` + Height int64 `json:"height"` + Ins int64 `json:"ins"` + MaxFee int64 `json:"maxfee"` + MaxFeeRate int64 `json:"maxfeerate"` + MaxTxSize int64 `json:"maxtxsize"` + MedianFee int64 `json:"medianfee"` + MedianTime int64 `json:"mediantime"` + MedianTxSize int64 `json:"mediantxsize"` + MinFee int64 `json:"minfee"` + MinFeeRate int64 `json:"minfeerate"` + MinTxSize int64 `json:"mintxsize"` + Outs int64 `json:"outs"` + SegWitTotalSize int64 `json:"swtotal_size"` + SegWitTotalWeight int64 `json:"swtotal_weight"` + SegWitTxs int64 `json:"swtxs"` + Subsidy int64 `json:"subsidy"` + Time int64 `json:"time"` + TotalOut int64 `json:"total_out"` + TotalSize int64 `json:"total_size"` + TotalWeight int64 `json:"total_weight"` + Txs int64 `json:"txs"` + UTXOIncrease int64 `json:"utxo_increase"` + UTXOSizeIncrease int64 `json:"utxo_size_inc"` +} + // GetBlockVerboseResult models the data from the getblock command when the // verbose flag is set to 1. When the verbose flag is set to 0, getblock returns a // hex-encoded string. When the verbose flag is set to 1, getblock returns an object diff --git a/rpcclient/chain.go b/rpcclient/chain.go index c656a19a8d..707978ca65 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -1037,3 +1037,44 @@ func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash, filterType wire.FilterType) (*wire.MsgCFHeaders, error) { return c.GetCFilterHeaderAsync(blockHash, filterType).Receive() } + +// FutureGetBlockStatsResult is a future promise to deliver the result of a +// GetBlockStatsAsync RPC invocation (or an applicable error). +type FutureGetBlockStatsResult chan *response + +// Receive waits for the response promised by the future and returns statistics +// of a block at a certain height. +func (r FutureGetBlockStatsResult) Receive() (*btcjson.GetBlockStatsResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var blockStats btcjson.GetBlockStatsResult + err = json.Unmarshal(res, &blockStats) + if err != nil { + return nil, err + } + + return &blockStats, nil +} + +// GetBlockStatsAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetBlockStats or the blocking version and more details. +func (c *Client) GetBlockStatsAsync(hashOrHeight interface{}, stats *[]string) FutureGetBlockStatsResult { + if hash, ok := hashOrHeight.(*chainhash.Hash); ok { + hashOrHeight = hash.String() + } + + cmd := btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: hashOrHeight}, stats) + return c.sendCmd(cmd) +} + +// GetBlockStats returns block statistics. First argument specifies height or hash of the target block. +// Second argument allows to select certain stats to return. +func (c *Client) GetBlockStats(hashOrHeight interface{}, stats *[]string) (*btcjson.GetBlockStatsResult, error) { + return c.GetBlockStatsAsync(hashOrHeight, stats).Receive() +} From 08b875155907c6f93694d3be6e8d8e67c159e084 Mon Sep 17 00:00:00 2001 From: Iskander Sharipov Date: Fri, 14 Sep 2018 00:19:24 +0300 Subject: [PATCH 0338/1056] cmd/btcctl: use regexp.MustCompile for constant patterns Found using https://go-critic.github.io/overview#regexpMust-ref --- cmd/btcctl/config.go | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index cd232a9e0a..282b17438f 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -295,10 +295,7 @@ func createDefaultConfigFile(destinationPath, serverConfigPath string) error { } // Extract the rpcuser - rpcUserRegexp, err := regexp.Compile(`(?m)^\s*rpcuser=([^\s]+)`) - if err != nil { - return err - } + rpcUserRegexp := regexp.MustCompile(`(?m)^\s*rpcuser=([^\s]+)`) userSubmatches := rpcUserRegexp.FindSubmatch(content) if userSubmatches == nil { // No user found, nothing to do @@ -306,10 +303,7 @@ func createDefaultConfigFile(destinationPath, serverConfigPath string) error { } // Extract the rpcpass - rpcPassRegexp, err := regexp.Compile(`(?m)^\s*rpcpass=([^\s]+)`) - if err != nil { - return err - } + rpcPassRegexp := regexp.MustCompile(`(?m)^\s*rpcpass=([^\s]+)`) passSubmatches := rpcPassRegexp.FindSubmatch(content) if passSubmatches == nil { // No password found, nothing to do @@ -317,10 +311,7 @@ func createDefaultConfigFile(destinationPath, serverConfigPath string) error { } // Extract the notls - noTLSRegexp, err := regexp.Compile(`(?m)^\s*notls=(0|1)(?:\s|$)`) - if err != nil { - return err - } + noTLSRegexp := regexp.MustCompile(`(?m)^\s*notls=(0|1)(?:\s|$)`) noTLSSubmatches := noTLSRegexp.FindSubmatch(content) // Create the destination directory if it does not exists From 57d44d022ecb4edac34e1ea7dbd62c7a592d3d58 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Mon, 2 Dec 2019 11:42:14 +0100 Subject: [PATCH 0339/1056] Try both TX serialization formats --- rpcclient/rawtransactions.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 4bf4ee57fc..23754d961d 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -233,8 +233,13 @@ func (r FutureCreateRawTransactionResult) Receive() (*wire.MsgTx, error) { // Deserialize the transaction and return it. var msgTx wire.MsgTx - if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil { - return nil, err + // we try both the new and old encoding format + witnessErr := msgTx.Deserialize(bytes.NewReader(serializedTx)) + if witnessErr != nil { + legacyErr := msgTx.DeserializeNoWitness(bytes.NewReader(serializedTx)) + if legacyErr != nil { + return nil, legacyErr + } } return &msgTx, nil } From 9f15a7e6af2ef99622c401250e4bc6300049d1b2 Mon Sep 17 00:00:00 2001 From: Murray Nesbitt Date: Tue, 14 Apr 2020 01:58:45 -0700 Subject: [PATCH 0340/1056] Alphabetize --help output; add missing options to doc.go --- cmd/addblock/config.go | 8 +- cmd/btcctl/config.go | 16 +- cmd/findcheckpoint/config.go | 6 +- cmd/gencerts/gencerts.go | 6 +- config.go | 120 +++++++-------- database/cmd/dbtool/globalconfig.go | 2 +- doc.go | 230 ++++++++++++++++------------ 7 files changed, 210 insertions(+), 178 deletions(-) diff --git a/cmd/addblock/config.go b/cmd/addblock/config.go index ae7a52fd2e..90620c8fda 100644 --- a/cmd/addblock/config.go +++ b/cmd/addblock/config.go @@ -34,15 +34,15 @@ var ( // // See loadConfig for details on the configuration load process. type config struct { + AddrIndex bool `long:"addrindex" description:"Build a full address-based transaction index which makes the searchrawtransactions RPC available"` DataDir string `short:"b" long:"datadir" description:"Location of the btcd data directory"` DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` - TestNet3 bool `long:"testnet" description:"Use the test network"` + InFile string `short:"i" long:"infile" description:"File containing the block(s)"` + Progress int `short:"p" long:"progress" description:"Show a progress message each time this number of seconds have passed -- Use 0 to disable progress announcements"` RegressionTest bool `long:"regtest" description:"Use the regression test network"` SimNet bool `long:"simnet" description:"Use the simulation test network"` - InFile string `short:"i" long:"infile" description:"File containing the block(s)"` + TestNet3 bool `long:"testnet" description:"Use the test network"` TxIndex bool `long:"txindex" description:"Build a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` - AddrIndex bool `long:"addrindex" description:"Build a full address-based transaction index which makes the searchrawtransactions RPC available"` - Progress int `short:"p" long:"progress" description:"Show a progress message each time this number of seconds have passed -- Use 0 to disable progress announcements"` } // filesExists reports whether the named file or directory exists. diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index 282b17438f..8ed85f352b 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -92,20 +92,20 @@ func listCommands() { // // See loadConfig for details on the configuration load process. type config struct { - ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` - ListCommands bool `short:"l" long:"listcommands" description:"List all of the supported commands and exit"` ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` - RPCUser string `short:"u" long:"rpcuser" description:"RPC username"` - RPCPassword string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password"` - RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"` - RPCCert string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"` + ListCommands bool `short:"l" long:"listcommands" description:"List all of the supported commands and exit"` NoTLS bool `long:"notls" description:"Disable TLS"` Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` - ProxyUser string `long:"proxyuser" description:"Username for proxy server"` ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` - TestNet3 bool `long:"testnet" description:"Connect to testnet"` + ProxyUser string `long:"proxyuser" description:"Username for proxy server"` + RPCCert string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"` + RPCPassword string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password"` + RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"` + RPCUser string `short:"u" long:"rpcuser" description:"RPC username"` SimNet bool `long:"simnet" description:"Connect to the simulation test network"` TLSSkipVerify bool `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"` + TestNet3 bool `long:"testnet" description:"Connect to testnet"` + ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` Wallet bool `long:"wallet" description:"Connect to wallet"` } diff --git a/cmd/findcheckpoint/config.go b/cmd/findcheckpoint/config.go index 1539db334c..87f04cecd5 100644 --- a/cmd/findcheckpoint/config.go +++ b/cmd/findcheckpoint/config.go @@ -37,11 +37,11 @@ var ( type config struct { DataDir string `short:"b" long:"datadir" description:"Location of the btcd data directory"` DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` - TestNet3 bool `long:"testnet" description:"Use the test network"` + UseGoOutput bool `short:"g" long:"gooutput" description:"Display the candidates using Go syntax that is ready to insert into the btcchain checkpoint list"` + NumCandidates int `short:"n" long:"numcandidates" description:"Max num of checkpoint candidates to show {1-20}"` RegressionTest bool `long:"regtest" description:"Use the regression test network"` SimNet bool `long:"simnet" description:"Use the simulation test network"` - NumCandidates int `short:"n" long:"numcandidates" description:"Max num of checkpoint candidates to show {1-20}"` - UseGoOutput bool `short:"g" long:"gooutput" description:"Display the candidates using Go syntax that is ready to insert into the btcchain checkpoint list"` + TestNet3 bool `long:"testnet" description:"Use the test network"` } // validDbType returns whether or not dbType is a supported database type. diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index a3a506363a..27d1073e74 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -18,10 +18,10 @@ import ( type config struct { Directory string `short:"d" long:"directory" description:"Directory to write certificate pair"` - Years int `short:"y" long:"years" description:"How many years a certificate is valid for"` - Organization string `short:"o" long:"org" description:"Organization in certificate"` - ExtraHosts []string `short:"H" long:"host" description:"Additional hosts/IPs to create certificate for"` Force bool `short:"f" long:"force" description:"Force overwriting of any old certs and keys"` + ExtraHosts []string `short:"H" long:"host" description:"Additional hosts/IPs to create certificate for"` + Organization string `short:"o" long:"org" description:"Organization in certificate"` + Years int `short:"y" long:"years" description:"How many years a certificate is valid for"` } func main() { diff --git a/config.go b/config.go index 3bcc65dacd..f3653485f2 100644 --- a/config.go +++ b/config.go @@ -93,79 +93,79 @@ func minUint32(a, b uint32) uint32 { // // See loadConfig for details on the configuration load process. type config struct { - ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` - ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` - DataDir string `short:"b" long:"datadir" description:"Directory to store data"` - LogDir string `long:"logdir" description:"Directory to log output."` + AddCheckpoints []string `long:"addcheckpoint" description:"Add a custom checkpoint. Format: ':'"` AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"` + AddrIndex bool `long:"addrindex" description:"Maintain a full address-based transaction index which makes the searchrawtransactions RPC available"` + AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."` + AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."`"` + BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` + BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` + BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"` + BlockMinSize uint32 `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"` + BlockMaxWeight uint32 `long:"blockmaxweight" description:"Maximum block weight to be used when creating a block"` + BlockMinWeight uint32 `long:"blockminweight" description:"Mininum block weight to be used when creating a block"` + BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"` + BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."` + ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"` - DisableListen bool `long:"nolisten" description:"Disable listening for incoming connections -- NOTE: Listening is automatically disabled if the --connect or --proxy options are used without also specifying listen interfaces via --listen"` + CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"` + DataDir string `short:"b" long:"datadir" description:"Directory to store data"` + DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` + DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify =,=,... to set the log level for individual subsystems -- Use show to list available subsystems"` + DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."` + DropCfIndex bool `long:"dropcfindex" description:"Deletes the index used for committed filtering (CF) support from the database on start up and then exits."` + DropTxIndex bool `long:"droptxindex" description:"Deletes the hash-based transaction index from the database on start up and then exits."` + ExternalIPs []string `long:"externalip" description:"Add an ip to the list of local addresses we claim to listen on to peers"` + Generate bool `long:"generate" description:"Generate (mine) bitcoins using the CPU"` + FreeTxRelayLimit float64 `long:"limitfreerelay" description:"Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute"` Listeners []string `long:"listen" description:"Add an interface/port to listen for connections (default all interfaces port: 8333, testnet: 18333)"` + LogDir string `long:"logdir" description:"Directory to log output."` + MaxOrphanTxs int `long:"maxorphantx" description:"Max number of orphan transactions to keep in memory"` MaxPeers int `long:"maxpeers" description:"Max number of inbound and outbound peers"` + MiningAddrs []string `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"` + MinRelayTxFee float64 `long:"minrelaytxfee" description:"The minimum transaction fee in BTC/kB to be considered a non-zero fee."` DisableBanning bool `long:"nobanning" description:"Disable banning of misbehaving peers"` - BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` - BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` - Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"` - AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."` - AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."` - RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"` - RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"` - RPCLimitUser string `long:"rpclimituser" description:"Username for limited RPC connections"` - RPCLimitPass string `long:"rpclimitpass" default-mask:"-" description:"Password for limited RPC connections"` - RPCListeners []string `long:"rpclisten" description:"Add an interface/port to listen for RPC connections (default port: 8334, testnet: 18334)"` - RPCCert string `long:"rpccert" description:"File containing the certificate file"` - RPCKey string `long:"rpckey" description:"File containing the certificate key"` - RPCMaxClients int `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"` - RPCMaxWebsockets int `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"` - RPCMaxConcurrentReqs int `long:"rpcmaxconcurrentreqs" description:"Max number of concurrent RPC requests that may be processed concurrently"` - RPCQuirks bool `long:"rpcquirks" description:"Mirror some JSON-RPC quirks of Bitcoin Core -- NOTE: Discouraged unless interoperability issues need to be worked around"` + NoCFilters bool `long:"nocfilters" description:"Disable committed filtering (CF) support"` + DisableCheckpoints bool `long:"nocheckpoints" description:"Disable built-in checkpoints. Don't do this unless you know what you're doing."` + DisableDNSSeed bool `long:"nodnsseed" description:"Disable DNS seeding for peers"` + DisableListen bool `long:"nolisten" description:"Disable listening for incoming connections -- NOTE: Listening is automatically disabled if the --connect or --proxy options are used without also specifying listen interfaces via --listen"` + NoOnion bool `long:"noonion" description:"Disable connecting to tor hidden services"` + NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"` + NoRelayPriority bool `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"` DisableRPC bool `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass or rpclimituser/rpclimitpass is specified"` DisableTLS bool `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"` - DisableDNSSeed bool `long:"nodnsseed" description:"Disable DNS seeding for peers"` - ExternalIPs []string `long:"externalip" description:"Add an ip to the list of local addresses we claim to listen on to peers"` - Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` - ProxyUser string `long:"proxyuser" description:"Username for proxy server"` - ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` OnionProxy string `long:"onion" description:"Connect to tor hidden services via SOCKS5 proxy (eg. 127.0.0.1:9050)"` - OnionProxyUser string `long:"onionuser" description:"Username for onion proxy server"` OnionProxyPass string `long:"onionpass" default-mask:"-" description:"Password for onion proxy server"` - NoOnion bool `long:"noonion" description:"Disable connecting to tor hidden services"` - TorIsolation bool `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` - TestNet3 bool `long:"testnet" description:"Use the test network"` + OnionProxyUser string `long:"onionuser" description:"Username for onion proxy server"` + Profile string `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65536"` + Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` + ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` + ProxyUser string `long:"proxyuser" description:"Username for proxy server"` RegressionTest bool `long:"regtest" description:"Use the regression test network"` + RejectNonStd bool `long:"rejectnonstd" description:"Reject non-standard transactions regardless of the default settings for the active network."` + RejectReplacement bool `long:"rejectreplacement" description:"Reject transactions that attempt to replace existing transactions within the mempool through the Replace-By-Fee (RBF) signaling policy."` + RelayNonStd bool `long:"relaynonstd" description:"Relay non-standard transactions regardless of the default settings for the active network."` + RPCCert string `long:"rpccert" description:"File containing the certificate file"` + RPCKey string `long:"rpckey" description:"File containing the certificate key"` + RPCLimitPass string `long:"rpclimitpass" default-mask:"-" description:"Password for limited RPC connections"` + RPCLimitUser string `long:"rpclimituser" description:"Username for limited RPC connections"` + RPCListeners []string `long:"rpclisten" description:"Add an interface/port to listen for RPC connections (default port: 8334, testnet: 18334)"` + RPCMaxClients int `long:"rpcmaxclients" description:"Max number of RPC clients for standard connections"` + RPCMaxConcurrentReqs int `long:"rpcmaxconcurrentreqs" description:"Max number of concurrent RPC requests that may be processed concurrently"` + RPCMaxWebsockets int `long:"rpcmaxwebsockets" description:"Max number of RPC websocket connections"` + RPCQuirks bool `long:"rpcquirks" description:"Mirror some JSON-RPC quirks of Bitcoin Core -- NOTE: Discouraged unless interoperability issues need to be worked around"` + RPCPass string `short:"P" long:"rpcpass" default-mask:"-" description:"Password for RPC connections"` + RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"` + SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"` SimNet bool `long:"simnet" description:"Use the simulation test network"` - AddCheckpoints []string `long:"addcheckpoint" description:"Add a custom checkpoint. Format: ':'"` - DisableCheckpoints bool `long:"nocheckpoints" description:"Disable built-in checkpoints. Don't do this unless you know what you're doing."` - DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` - Profile string `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65536"` - CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"` - DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify =,=,... to set the log level for individual subsystems -- Use show to list available subsystems"` - Upnp bool `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"` - MinRelayTxFee float64 `long:"minrelaytxfee" description:"The minimum transaction fee in BTC/kB to be considered a non-zero fee."` - FreeTxRelayLimit float64 `long:"limitfreerelay" description:"Limit relay of transactions with no transaction fee to the given amount in thousands of bytes per minute"` - NoRelayPriority bool `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"` + TestNet3 bool `long:"testnet" description:"Use the test network"` + TorIsolation bool `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` TrickleInterval time.Duration `long:"trickleinterval" description:"Minimum time between attempts to send new inventory to a connected peer"` - MaxOrphanTxs int `long:"maxorphantx" description:"Max number of orphan transactions to keep in memory"` - Generate bool `long:"generate" description:"Generate (mine) bitcoins using the CPU"` - MiningAddrs []string `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"` - BlockMinSize uint32 `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"` - BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"` - BlockMinWeight uint32 `long:"blockminweight" description:"Mininum block weight to be used when creating a block"` - BlockMaxWeight uint32 `long:"blockmaxweight" description:"Maximum block weight to be used when creating a block"` - BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"` - UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."` - NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"` - NoCFilters bool `long:"nocfilters" description:"Disable committed filtering (CF) support"` - DropCfIndex bool `long:"dropcfindex" description:"Deletes the index used for committed filtering (CF) support from the database on start up and then exits."` - SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"` - BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."` TxIndex bool `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` - DropTxIndex bool `long:"droptxindex" description:"Deletes the hash-based transaction index from the database on start up and then exits."` - AddrIndex bool `long:"addrindex" description:"Maintain a full address-based transaction index which makes the searchrawtransactions RPC available"` - DropAddrIndex bool `long:"dropaddrindex" description:"Deletes the address-based transaction index from the database on start up and then exits."` - RelayNonStd bool `long:"relaynonstd" description:"Relay non-standard transactions regardless of the default settings for the active network."` - RejectNonStd bool `long:"rejectnonstd" description:"Reject non-standard transactions regardless of the default settings for the active network."` - RejectReplacement bool `long:"rejectreplacement" description:"Reject transactions that attempt to replace existing transactions within the mempool through the Replace-By-Fee (RBF) signaling policy."` + UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."` + Upnp bool `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"` + ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` + Whitelists []string `long:"whitelist" description:"Add an IP network or IP that will not be banned. (eg. 192.168.1.0/24 or ::1)"` lookup func(string) ([]net.IP, error) oniondial func(string, string, time.Duration) (net.Conn, error) dial func(string, string, time.Duration) (net.Conn, error) diff --git a/database/cmd/dbtool/globalconfig.go b/database/cmd/dbtool/globalconfig.go index 5cbd9b3af9..aa1e0e0483 100644 --- a/database/cmd/dbtool/globalconfig.go +++ b/database/cmd/dbtool/globalconfig.go @@ -33,9 +33,9 @@ var ( type config struct { DataDir string `short:"b" long:"datadir" description:"Location of the btcd data directory"` DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` - TestNet3 bool `long:"testnet" description:"Use the test network"` RegressionTest bool `long:"regtest" description:"Use the regression test network"` SimNet bool `long:"simnet" description:"Use the simulation test network"` + TestNet3 bool `long:"testnet" description:"Use the test network"` } // fileExists reports whether the named file or directory exists. diff --git a/doc.go b/doc.go index ace26b0f99..8b9b99773a 100644 --- a/doc.go +++ b/doc.go @@ -21,105 +21,137 @@ Usage: btcd [OPTIONS] Application Options: - -V, --version Display version information and exit - -C, --configfile= Path to configuration file - -b, --datadir= Directory to store data - --logdir= Directory to log output. - -a, --addpeer= Add a peer to connect with at startup - --connect= Connect only to the specified peers at startup - --nolisten Disable listening for incoming connections -- NOTE: - Listening is automatically disabled if the --connect - or --proxy options are used without also specifying - listen interfaces via --listen - --listen= Add an interface/port to listen for connections - (default all interfaces port: 8333, testnet: 18333) - --maxpeers= Max number of inbound and outbound peers (125) - --nobanning Disable banning of misbehaving peers - --banduration= How long to ban misbehaving peers. Valid time units - are {s, m, h}. Minimum 1 second (24h0m0s) - --banthreshold= Maximum allowed ban score before disconnecting and - banning misbehaving peers. - --whitelist= Add an IP network or IP that will not be banned. - (eg. 192.168.1.0/24 or ::1) - -u, --rpcuser= Username for RPC connections - -P, --rpcpass= Password for RPC connections - --rpclimituser= Username for limited RPC connections - --rpclimitpass= Password for limited RPC connections - --rpclisten= Add an interface/port to listen for RPC connections - (default port: 8334, testnet: 18334) - --rpccert= File containing the certificate file - --rpckey= File containing the certificate key - --rpcmaxclients= Max number of RPC clients for standard connections - (10) - --rpcmaxwebsockets= Max number of RPC websocket connections (25) - --rpcquirks Mirror some JSON-RPC quirks of Bitcoin Core -- NOTE: - Discouraged unless interoperability issues need to - be worked around - --norpc Disable built-in RPC server -- NOTE: The RPC server - is disabled by default if no rpcuser/rpcpass or - rpclimituser/rpclimitpass is specified - --notls Disable TLS for the RPC server -- NOTE: This is only - allowed if the RPC server is bound to localhost - --nodnsseed Disable DNS seeding for peers - --externalip= Add an ip to the list of local addresses we claim to - listen on to peers - --proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050) - --proxyuser= Username for proxy server - --proxypass= Password for proxy server - --onion= Connect to tor hidden services via SOCKS5 proxy - (eg. 127.0.0.1:9050) - --onionuser= Username for onion proxy server - --onionpass= Password for onion proxy server - --noonion Disable connecting to tor hidden services - --torisolation Enable Tor stream isolation by randomizing user - credentials for each connection. - --testnet Use the test network - --regtest Use the regression test network - --simnet Use the simulation test network - --addcheckpoint= Add a custom checkpoint. Format: ':' - --nocheckpoints Disable built-in checkpoints. Don't do this unless - you know what you're doing. - --uacomment= Comment to add to the user agent -- - See BIP 14 for more information. - --dbtype= Database backend to use for the Block Chain (ffldb) - --profile= Enable HTTP profiling on given port -- NOTE port - must be between 1024 and 65536 - --cpuprofile= Write CPU profile to the specified file - -d, --debuglevel= Logging level for all subsystems {trace, debug, - info, warn, error, critical} -- You may also specify - =,=,... to set - the log level for individual subsystems -- Use show - to list available subsystems (info) - --upnp Use UPnP to map our listening port outside of NAT - --minrelaytxfee= The minimum transaction fee in BTC/kB to be - considered a non-zero fee. - --limitfreerelay= Limit relay of transactions with no transaction fee - to the given amount in thousands of bytes per - minute (15) - --norelaypriority Do not require free or low-fee transactions to have - high priority for relaying - --maxorphantx= Max number of orphan transactions to keep in memory - (100) - --generate Generate (mine) bitcoins using the CPU - --miningaddr= Add the specified payment address to the list of - addresses to use for generated blocks -- At least - one address is required if the generate option is - set - --blockminsize= Mininum block size in bytes to be used when creating - a block - --blockmaxsize= Maximum block size in bytes to be used when creating - a block (750000) - --blockprioritysize= Size in bytes for high-priority/low-fee transactions - when creating a block (50000) - --nopeerbloomfilters Disable bloom filtering support. - --nocfilters Disable committed filtering (CF) support. - --sigcachemaxsize= The maximum number of entries in the signature - verification cache. - --blocksonly Do not accept transactions from remote peers. - --relaynonstd Relay non-standard transactions regardless of the - default settings for the active network. - --rejectnonstd Reject non-standard transactions regardless of the - default settings for the active network. + --addcheckpoint= Add a custom checkpoint. Format: + ':' + -a, --addpeer= Add a peer to connect with at startup + --addrindex Maintain a full address-based transaction index + which makes the searchrawtransactions RPC + available + --banduration= How long to ban misbehaving peers. Valid time + units are {s, m, h}. Minimum 1 second (default: + 24h0m0s) + --banthreshold= Maximum allowed ban score before disconnecting + and banning misbehaving peers. (default: 100) + --blockmaxsize= Maximum block size in bytes to be used when + creating a block (default: 750000) + --blockminsize= Mininum block size in bytes to be used when + creating a block + --blockmaxweight= Maximum block weight to be used when creating a + block (default: 3000000) + --blockminweight= Mininum block weight to be used when creating a + block + --blockprioritysize= Size in bytes for high-priority/low-fee + transactions when creating a block (default: + 50000) + --blocksonly Do not accept transactions from remote peers. + -C, --configfile= Path to configuration file + --connect= Connect only to the specified peers at startup + --cpuprofile= Write CPU profile to the specified file + -b, --datadir= Directory to store data + --dbtype= Database backend to use for the Block Chain + (default: ffldb) + -d, --debuglevel= Logging level for all subsystems {trace, debug, + info, warn, error, critical} -- You may also + specify + =,=,... to + set the log level for individual subsystems -- + Use show to list available subsystems (default: + info) + --dropaddrindex Deletes the address-based transaction index from + the database on start up and then exits. + --dropcfindex Deletes the index used for committed filtering + (CF) support from the database on start up and + then exits. + --droptxindex Deletes the hash-based transaction index from the + database on start up and then exits. + --externalip= Add an ip to the list of local addresses we claim + to listen on to peers + --generate Generate (mine) bitcoins using the CPU + --limitfreerelay= Limit relay of transactions with no transaction + fee to the given amount in thousands of bytes per + minute (default: 15) + --listen= Add an interface/port to listen for connections + (default all interfaces port: 8333, testnet: + 18333) + --logdir= Directory to log output + --maxorphantx= Max number of orphan transactions to keep in + memory (default: 100) + --maxpeers= Max number of inbound and outbound peers + (default: 125) + --miningaddr= Add the specified payment address to the list of + addresses to use for generated blocks -- At least + one address is required if the generate option is + set + --minrelaytxfee= The minimum transaction fee in BTC/kB to be + considered a non-zero fee. (default: 1e-05) + --nobanning Disable banning of misbehaving peers + --nocfilters Disable committed filtering (CF) support + --nocheckpoints Disable built-in checkpoints. Don't do this + unless you know what you're doing. + --nodnsseed Disable DNS seeding for peers + --nolisten Disable listening for incoming connections -- + NOTE: Listening is automatically disabled if the + --connect or --proxy options are used without + also specifying listen interfaces via --listen + --noonion Disable connecting to tor hidden services + --nopeerbloomfilters Disable bloom filtering support + --norelaypriority Do not require free or low-fee transactions to + have high priority for relaying + --norpc Disable built-in RPC server -- NOTE: The RPC + server is disabled by default if no + rpcuser/rpcpass or rpclimituser/rpclimitpass is + specified + --notls Disable TLS for the RPC server -- NOTE: This is + only allowed if the RPC server is bound to + localhost + --onion= Connect to tor hidden services via SOCKS5 proxy + (eg. 127.0.0.1:9050) + --onionpass= Password for onion proxy server + --onionuser= Username for onion proxy server + --profile= Enable HTTP profiling on given port -- NOTE port + must be between 1024 and 65536 + --proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050) + --proxypass= Password for proxy server + --proxyuser= Username for proxy server + --regtest Use the regression test network + --rejectnonstd Reject non-standard transactions regardless of + the default settings for the active network. + --relaynonstd Relay non-standard transactions regardless of the + default settings for the active network. + --rpccert= File containing the certificate file + --rpckey= File containing the certificate key + --rpclimitpass= Password for limited RPC connections + --rpclimituser= Username for limited RPC connections + --rpclisten= Add an interface/port to listen for RPC + connections (default port: 8334, testnet: 18334) + --rpcmaxclients= Max number of RPC clients for standard + connections (default: 10) + --rpcmaxconcurrentreqs= Max number of concurrent RPC requests that may be + processed concurrently (default: 20) + --rpcmaxwebsockets= Max number of RPC websocket connections (default: + 25) + --rpcquirks Mirror some JSON-RPC quirks of Bitcoin Core -- + NOTE: Discouraged unless interoperability issues + need to be worked around + -P, --rpcpass= Password for RPC connections + -u, --rpcuser= Username for RPC connections + --sigcachemaxsize= The maximum number of entries in the signature + verification cache (default: 100000) + --simnet Use the simulation test network + --testnet Use the test network + --torisolation Enable Tor stream isolation by randomizing user + credentials for each connection. + --trickleinterval= Minimum time between attempts to send new + inventory to a connected peer (default: 10s) + --txindex Maintain a full hash-based transaction index + which makes all transactions available via the + getrawtransaction RPC + --uacomment= Comment to add to the user agent -- See BIP 14 + for more information. + --upnp Use UPnP to map our listening port outside of NAT + -V, --version Display version information and exit + --whitelist= Add an IP network or IP that will not be banned. + (eg. 192.168.1.0/24 or ::1) Help Options: -h, --help Show this help message From 8b54b0b96418b33c1e584c84c0ec5141647306e0 Mon Sep 17 00:00:00 2001 From: Dan Cline Date: Tue, 14 Apr 2020 07:35:22 -0400 Subject: [PATCH 0341/1056] config.go: remove extra quotes --- config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.go b/config.go index f3653485f2..96756f7f97 100644 --- a/config.go +++ b/config.go @@ -96,8 +96,8 @@ type config struct { AddCheckpoints []string `long:"addcheckpoint" description:"Add a custom checkpoint. Format: ':'"` AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"` AddrIndex bool `long:"addrindex" description:"Maintain a full address-based transaction index which makes the searchrawtransactions RPC available"` - AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."` - AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."`"` + AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."` + AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."` BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"` From 8512affc592e6e0331ca2ff03b469d22fc197fb0 Mon Sep 17 00:00:00 2001 From: tpkeeper Date: Wed, 6 May 2020 18:35:44 +0800 Subject: [PATCH 0342/1056] readme: remove duplicate word --- database/internal/treap/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/internal/treap/README.md b/database/internal/treap/README.md index ee49ef9bf6..f5314b4a05 100644 --- a/database/internal/treap/README.md +++ b/database/internal/treap/README.md @@ -8,7 +8,7 @@ treap Package treap implements a treap data structure that is used to hold ordered key/value pairs using a combination of binary search tree and heap semantics. It is a self-organizing and randomized data structure that doesn't require -complex operations to to maintain balance. Search, insert, and delete +complex operations to maintain balance. Search, insert, and delete operations are all O(log n). Both mutable and immutable variants are provided. The mutable variant is typically faster since it is able to simply update the From b29841558383a58530319ab4983a550261708d91 Mon Sep 17 00:00:00 2001 From: Antonin Hildebrand Date: Mon, 25 Mar 2019 23:24:06 +0100 Subject: [PATCH 0343/1056] Improve error message about non-active segwit on simnet I started playing with simnet and was confronted with error message: ``` [ERR] FNDG: Unable to broadcast funding tx for ChannelPoint(:0): -22: TX rejected: transaction has witness data, but segwit isn't active yet ``` I wasn't aware of the activation period so I got quite puzzled. Google helped. But I think the message could mention likely cause. Newly it optionally prints something like: ``` (The threshold for segwit activation is 300 blocks on simnet, current best height is 113) ``` --- mempool/mempool.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 63a86a16f5..7ada3d2907 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -927,7 +927,7 @@ func (mp *TxPool) validateReplacement(tx *btcutil.Tx, func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejectDupOrphans bool) ([]*chainhash.Hash, *TxDesc, error) { txHash := tx.Hash() - // If a transaction has iwtness data, and segwit isn't active yet, If + // If a transaction has witness data, and segwit isn't active yet, If // segwit isn't active yet, then we won't accept it into the mempool as // it can't be mined yet. if tx.MsgTx().HasWitness() { @@ -937,8 +937,14 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec } if !segwitActive { + simnetHint := "" + if mp.cfg.ChainParams.Net == wire.SimNet { + bestHeight := mp.cfg.BestHeight() + simnetHint = fmt.Sprintf(" (The threshold for segwit activation is 300 blocks on simnet, "+ + "current best height is %d)", bestHeight) + } str := fmt.Sprintf("transaction %v has witness data, "+ - "but segwit isn't active yet", txHash) + "but segwit isn't active yet%s", txHash, simnetHint) return nil, nil, txRuleError(wire.RejectNonstandard, str) } } From b470eee477280e03df6f4a5e7ce3d71d548deb40 Mon Sep 17 00:00:00 2001 From: Dan Cline Date: Tue, 14 Apr 2020 07:06:39 -0400 Subject: [PATCH 0344/1056] btcctl: add regtest mode to btcctl --- cmd/btcctl/config.go | 72 +++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index 8ed85f352b..939b6a8699 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcutil" flags "github.com/jessevdk/go-flags" ) @@ -92,42 +93,51 @@ func listCommands() { // // See loadConfig for details on the configuration load process. type config struct { - ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` - ListCommands bool `short:"l" long:"listcommands" description:"List all of the supported commands and exit"` - NoTLS bool `long:"notls" description:"Disable TLS"` - Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` - ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` - ProxyUser string `long:"proxyuser" description:"Username for proxy server"` - RPCCert string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"` - RPCPassword string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password"` - RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"` - RPCUser string `short:"u" long:"rpcuser" description:"RPC username"` - SimNet bool `long:"simnet" description:"Connect to the simulation test network"` - TLSSkipVerify bool `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"` - TestNet3 bool `long:"testnet" description:"Connect to testnet"` - ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` - Wallet bool `long:"wallet" description:"Connect to wallet"` + ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` + ListCommands bool `short:"l" long:"listcommands" description:"List all of the supported commands and exit"` + NoTLS bool `long:"notls" description:"Disable TLS"` + Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` + ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` + ProxyUser string `long:"proxyuser" description:"Username for proxy server"` + RegressionTest bool `long:"regtest" description:"Connect to the regression test network"` + RPCCert string `short:"c" long:"rpccert" description:"RPC server certificate chain for validation"` + RPCPassword string `short:"P" long:"rpcpass" default-mask:"-" description:"RPC password"` + RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"` + RPCUser string `short:"u" long:"rpcuser" description:"RPC username"` + SimNet bool `long:"simnet" description:"Connect to the simulation test network"` + TLSSkipVerify bool `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"` + TestNet3 bool `long:"testnet" description:"Connect to testnet"` + ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` + Wallet bool `long:"wallet" description:"Connect to wallet"` } // normalizeAddress returns addr with the passed default port appended if // there is not already a port specified. -func normalizeAddress(addr string, useTestNet3, useSimNet, useWallet bool) string { +func normalizeAddress(addr string, chain *chaincfg.Params, useWallet bool) (string, error) { _, _, err := net.SplitHostPort(addr) if err != nil { var defaultPort string - switch { - case useTestNet3: + switch chain { + case &chaincfg.TestNet3Params: if useWallet { defaultPort = "18332" } else { defaultPort = "18334" } - case useSimNet: + case &chaincfg.SimNetParams: if useWallet { defaultPort = "18554" } else { defaultPort = "18556" } + case &chaincfg.RegressionNetParams: + if useWallet { + // TODO: add port once regtest is supported in btcwallet + paramErr := fmt.Errorf("cannot use -wallet with -regtest, btcwallet not yet compatible with regtest") + return "", paramErr + } else { + defaultPort = "18334" + } default: if useWallet { defaultPort = "8332" @@ -136,9 +146,9 @@ func normalizeAddress(addr string, useTestNet3, useSimNet, useWallet bool) strin } } - return net.JoinHostPort(addr, defaultPort) + return net.JoinHostPort(addr, defaultPort), nil } - return addr + return addr, nil } // cleanAndExpandPath expands environement variables and leading ~ in the @@ -246,17 +256,27 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } + // default network is mainnet + network := &chaincfg.MainNetParams + // Multiple networks can't be selected simultaneously. numNets := 0 if cfg.TestNet3 { numNets++ + network = &chaincfg.TestNet3Params } if cfg.SimNet { numNets++ + network = &chaincfg.SimNetParams } + if cfg.RegressionTest { + numNets++ + network = &chaincfg.RegressionNetParams + } + if numNets > 1 { - str := "%s: The testnet and simnet params can't be used " + - "together -- choose one of the two" + str := "%s: Multiple network params can't be used " + + "together -- choose one" err := fmt.Errorf(str, "loadConfig") fmt.Fprintln(os.Stderr, err) return nil, nil, err @@ -273,8 +293,10 @@ func loadConfig() (*config, []string, error) { // Add default port to RPC server based on --testnet and --wallet flags // if needed. - cfg.RPCServer = normalizeAddress(cfg.RPCServer, cfg.TestNet3, - cfg.SimNet, cfg.Wallet) + cfg.RPCServer, err = normalizeAddress(cfg.RPCServer, network, cfg.Wallet) + if err != nil { + return nil, nil, err + } return &cfg, remainingArgs, nil } From a505b99ba37802797ad486cc3d0d811d5409de6d Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 13 May 2020 08:44:07 -0400 Subject: [PATCH 0345/1056] build: replace travis-ci with github actions. test go 1.14 use golangci-lint --- .github/workflows/go.yml | 27 +++++++++++++++++++++++++++ .travis.yml | 18 ------------------ README.md | 6 +++--- btcjson/chainsvrresults.go | 2 +- goclean.sh | 18 ++++-------------- mempool/mempool_test.go | 8 ++++---- txscript/pkscript_test.go | 12 ++++++------ 7 files changed, 45 insertions(+), 46 deletions(-) create mode 100644 .github/workflows/go.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000000..f722032b16 --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,27 @@ +name: Build and Test +on: [push, pull_request] +jobs: + build: + name: Go CI + runs-on: ubuntu-latest + strategy: + matrix: + go: [1.13, 1.14] + steps: + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go }} + - name: Check out source + uses: actions/checkout@v2 + - name: Install Linters + run: "curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.26.0" + - name: Build + env: + GO111MODULE: "on" + run: go build ./... + - name: Test + env: + GO111MODULE: "on" + run: | + sh ./goclean.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5a611c3960..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go -cache: - directories: - - $GOCACHE - - $GOPATH/pkg/mod - - $GOPATH/github.com/golang - - $GOPATH/gopkg.in/alecthomas -go: - - "1.13.x" -sudo: false -install: - - export PATH=$PATH:$PWD/linux-amd64/ - - GO111MODULE=on go install . ./cmd/... - - GO111MODULE=off go get -u gopkg.in/alecthomas/gometalinter.v2 - - GO111MODULE=off gometalinter.v2 --install -script: - - export PATH=$PATH:$HOME/gopath/bin - - ./goclean.sh diff --git a/README.md b/README.md index a270fd2e97..8c9d252ad4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ btcd ==== -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) -[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) +[![ISC License](https://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/btcsuite/btcd) btcd is an alternative full node bitcoin implementation written in Go (golang). diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 8cd716d409..d076b74691 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -271,7 +271,7 @@ type GetBlockTemplateResult struct { type MempoolFees struct { Base float64 `json:"base"` - Modified float64 `json:"base"` + Modified float64 `json:"modified"` Ancestor float64 `json:"ancestor"` Descendant float64 `json:"descendant"` } diff --git a/goclean.sh b/goclean.sh index 6d0e0ca104..4689ab360f 100755 --- a/goclean.sh +++ b/goclean.sh @@ -6,26 +6,16 @@ # 4. gosimple (https://github.com/dominikh/go-simple) # 5. unconvert (https://github.com/mdempsky/unconvert) # -# gometalinter (github.com/alecthomas/gometalinter) is used to run each static -# checker. set -ex -# Make sure gometalinter is installed and $GOPATH/bin is in your path. -# $ go get -v github.com/alecthomas/gometalinter" -# $ gometalinter --install" -if [ ! -x "$(type -p gometalinter.v2)" ]; then - exit 1 -fi - -linter_targets=$(go list ./...) +go test -tags="rpctest" ./... # Automatic checks -test -z "$(gometalinter.v2 -j 4 --disable-all \ +golangci-lint run --deadline=10m --disable-all \ --enable=gofmt \ --enable=golint \ --enable=vet \ --enable=gosimple \ ---enable=unconvert \ ---deadline=10m $linter_targets 2>&1 | grep -v 'ALL_CAPS\|OP_' 2>&1 | tee /dev/stderr)" -GO111MODULE=on go test -tags="rpctest" $linter_targets +--enable=unconvert + diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 84aee10ab2..6d43cfd86e 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -1418,8 +1418,8 @@ func TestAncestorsDescendants(t *testing.T) { // We'll be querying for the ancestors of E. We should expect to see all // of the transactions that it depends on. expectedAncestors := map[chainhash.Hash]struct{}{ - *a.Hash(): struct{}{}, *b.Hash(): struct{}{}, - *c.Hash(): struct{}{}, *d.Hash(): struct{}{}, + *a.Hash(): {}, *b.Hash(): {}, + *c.Hash(): {}, *d.Hash(): {}, } ancestors := ctx.harness.txPool.txAncestors(e, nil) if len(ancestors) != len(expectedAncestors) { @@ -1436,8 +1436,8 @@ func TestAncestorsDescendants(t *testing.T) { // Then, we'll query for the descendants of A. We should expect to see // all of the transactions that depend on it. expectedDescendants := map[chainhash.Hash]struct{}{ - *b.Hash(): struct{}{}, *c.Hash(): struct{}{}, - *d.Hash(): struct{}{}, *e.Hash(): struct{}{}, + *b.Hash(): {}, *c.Hash(): {}, + *d.Hash(): {}, *e.Hash(): {}, } descendants := ctx.harness.txPool.txDescendants(a, nil) if len(descendants) != len(expectedDescendants) { diff --git a/txscript/pkscript_test.go b/txscript/pkscript_test.go index 841842c268..49e2db8afa 100644 --- a/txscript/pkscript_test.go +++ b/txscript/pkscript_test.go @@ -337,9 +337,9 @@ func TestComputePkScript(t *testing.T) { name: "P2WSH witness", sigScript: nil, witness: [][]byte{ - []byte{}, + {}, // Witness script. - []byte{ + { 0x21, 0x03, 0x82, 0x62, 0xa6, 0xc6, 0xce, 0xc9, 0x3c, 0x2d, 0x3e, 0xcd, 0x6c, 0x60, 0x72, 0xef, 0xea, 0x86, @@ -367,9 +367,9 @@ func TestComputePkScript(t *testing.T) { witness: [][]byte{ // Signature is not needed to re-derive the // pkScript. - []byte{}, + {}, // Compressed pubkey. - []byte{ + { 0x03, 0x82, 0x62, 0xa6, 0xc6, 0xce, 0xc9, 0x3c, 0x2d, 0x3e, 0xcd, 0x6c, 0x60, 0x72, 0xef, 0xea, 0x86, 0xd0, @@ -398,9 +398,9 @@ func TestComputePkScript(t *testing.T) { witness: [][]byte{ // Signature is not needed to re-derive the // pkScript. - []byte{}, + {}, // Malformed compressed pubkey. - []byte{ + { 0x03, 0x82, 0x62, 0xa6, 0xc6, 0xce, 0xc9, 0x3c, 0x2d, 0x3e, 0xcd, 0x6c, 0x60, 0x72, 0xef, 0xea, 0x86, 0xd0, From bc8d63bf15e8e73e102a9ba93a75a6e1e3402cc7 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 13 May 2020 08:48:56 -0400 Subject: [PATCH 0346/1056] build: update deps --- go.mod | 15 +++++---------- go.sum | 23 ++++++++++++++++++++++- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 606399481f..15c261cef5 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,16 @@ module github.com/btcsuite/btcd require ( - github.com/aead/siphash v1.0.1 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d + github.com/btcsuite/btcutil v1.0.2 github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd - github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd - github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 // indirect + github.com/btcsuite/goleveldb v1.0.0 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 github.com/btcsuite/winsvc v1.0.0 - github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 - github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 + github.com/davecgh/go-spew v1.1.1 + github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 - github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect - github.com/onsi/ginkgo v1.7.0 // indirect - github.com/onsi/gomega v1.4.3 // indirect - golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 + golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 ) go 1.12 diff --git a/go.sum b/go.sum index dc773d4775..1ead212fc8 100644 --- a/go.sum +++ b/go.sum @@ -1,21 +1,29 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= @@ -24,6 +32,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= @@ -31,16 +41,27 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 h1:9lP3x0pW80sDI6t1UMSLA4to18W7R7imwAI/sWS9S8Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= From f7399e6157d38144d89517c9ca1d668e1615d9c3 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 13 May 2020 08:58:39 -0400 Subject: [PATCH 0347/1056] build: clean linter warnings --- blockchain/difficulty_test.go | 2 +- blockchain/indexers/addrindex_test.go | 4 ++-- btcec/pubkey_test.go | 6 +++--- btcec/signature_test.go | 3 +-- btcjson/register.go | 2 +- btcjson/register_test.go | 2 +- database/ffldb/whitebox_test.go | 4 ++-- goclean.sh | 3 --- rpcserverhelp.go | 2 +- server.go | 4 +--- txscript/opcode_test.go | 4 ++-- wire/common_test.go | 12 ++++++------ 12 files changed, 21 insertions(+), 27 deletions(-) diff --git a/blockchain/difficulty_test.go b/blockchain/difficulty_test.go index b42b7c730d..6fed37f136 100644 --- a/blockchain/difficulty_test.go +++ b/blockchain/difficulty_test.go @@ -63,7 +63,7 @@ func TestCalcWork(t *testing.T) { } for x, test := range tests { - bits := uint32(test.in) + bits := test.in r := CalcWork(bits) if r.Int64() != test.out { diff --git a/blockchain/indexers/addrindex_test.go b/blockchain/indexers/addrindex_test.go index 135ef19196..e545887f8b 100644 --- a/blockchain/indexers/addrindex_test.go +++ b/blockchain/indexers/addrindex_test.go @@ -68,7 +68,7 @@ func (b *addrIndexBucket) printLevels(addrKey [addrKeySize]byte) string { if !bytes.Equal(k[:levelOffset], addrKey[:]) { continue } - level := uint8(k[levelOffset]) + level := k[levelOffset] if level > highestLevel { highestLevel = level } @@ -105,7 +105,7 @@ func (b *addrIndexBucket) sanityCheck(addrKey [addrKeySize]byte, expectedTotal i if !bytes.Equal(k[:levelOffset], addrKey[:]) { continue } - level := uint8(k[levelOffset]) + level := k[levelOffset] if level > highestLevel { highestLevel = level } diff --git a/btcec/pubkey_test.go b/btcec/pubkey_test.go index 0a45f1c01d..68b61de10b 100644 --- a/btcec/pubkey_test.go +++ b/btcec/pubkey_test.go @@ -232,11 +232,11 @@ func TestPubKeys(t *testing.T) { var pkStr []byte switch test.format { case pubkeyUncompressed: - pkStr = (*PublicKey)(pk).SerializeUncompressed() + pkStr = pk.SerializeUncompressed() case pubkeyCompressed: - pkStr = (*PublicKey)(pk).SerializeCompressed() + pkStr = pk.SerializeCompressed() case pubkeyHybrid: - pkStr = (*PublicKey)(pk).SerializeHybrid() + pkStr = pk.SerializeHybrid() } if !bytes.Equal(test.key, pkStr) { t.Errorf("%s pubkey: serialized keys do not match.", diff --git a/btcec/signature_test.go b/btcec/signature_test.go index 19ab772ef9..d238741455 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -464,8 +464,7 @@ func TestSignatureSerialize(t *testing.T) { func testSignCompact(t *testing.T, tag string, curve *KoblitzCurve, data []byte, isCompressed bool) { - tmp, _ := NewPrivateKey(curve) - priv := (*PrivateKey)(tmp) + priv, _ := NewPrivateKey(curve) hashed := []byte("testing") sig, err := SignCompact(curve, priv, hashed, isCompressed) diff --git a/btcjson/register.go b/btcjson/register.go index 5de001c91e..10cd0f9a86 100644 --- a/btcjson/register.go +++ b/btcjson/register.go @@ -287,6 +287,6 @@ func RegisteredCmdMethods() []string { methods = append(methods, k) } - sort.Sort(sort.StringSlice(methods)) + sort.Strings(methods) return methods } diff --git a/btcjson/register_test.go b/btcjson/register_test.go index 3832678aaf..2d3ab10f3e 100644 --- a/btcjson/register_test.go +++ b/btcjson/register_test.go @@ -256,7 +256,7 @@ func TestRegisteredCmdMethods(t *testing.T) { // Ensure the returned methods are sorted. sortedMethods := make([]string, len(methods)) copy(sortedMethods, methods) - sort.Sort(sort.StringSlice(sortedMethods)) + sort.Strings(sortedMethods) if !reflect.DeepEqual(sortedMethods, methods) { t.Fatal("RegisteredCmdMethods: methods are not sorted") } diff --git a/database/ffldb/whitebox_test.go b/database/ffldb/whitebox_test.go index 4e529363dc..161d866d29 100644 --- a/database/ffldb/whitebox_test.go +++ b/database/ffldb/whitebox_test.go @@ -643,9 +643,9 @@ func TestFailureScenarios(t *testing.T) { // context. maxSize := int64(-1) if maxFileSize, ok := tc.maxFileSizes[fileNum]; ok { - maxSize = int64(maxFileSize) + maxSize = maxFileSize } - file := &mockFile{maxSize: int64(maxSize)} + file := &mockFile{maxSize: maxSize} tc.files[fileNum] = &lockableFile{file: file} return file, nil } diff --git a/goclean.sh b/goclean.sh index 4689ab360f..bb0cd7b600 100755 --- a/goclean.sh +++ b/goclean.sh @@ -1,7 +1,6 @@ #!/bin/bash # The script does automatic checking on a Go package and its sub-packages, including: # 1. gofmt (http://golang.org/cmd/gofmt/) -# 2. golint (https://github.com/golang/lint) # 3. go vet (http://golang.org/cmd/vet) # 4. gosimple (https://github.com/dominikh/go-simple) # 5. unconvert (https://github.com/mdempsky/unconvert) @@ -14,8 +13,6 @@ go test -tags="rpctest" ./... # Automatic checks golangci-lint run --deadline=10m --disable-all \ --enable=gofmt \ ---enable=golint \ --enable=vet \ --enable=gosimple \ --enable=unconvert - diff --git a/rpcserverhelp.go b/rpcserverhelp.go index cee2407566..63ad3d841e 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -818,7 +818,7 @@ func (c *helpCacher) rpcUsage(includeWebsockets bool) (string, error) { } } - sort.Sort(sort.StringSlice(usageTexts)) + sort.Strings(usageTexts) c.usage = strings.Join(usageTexts, "\n") return c.usage, nil } diff --git a/server.go b/server.go index b9bb18d0f5..9a76be8d4c 100644 --- a/server.go +++ b/server.go @@ -2270,9 +2270,7 @@ out: // When an InvVect has been added to a block, we can // now remove it, if it was present. case broadcastInventoryDel: - if _, ok := pendingInvs[*msg]; ok { - delete(pendingInvs, *msg) - } + delete(pendingInvs, *msg) } case <-timer.C: diff --git a/txscript/opcode_test.go b/txscript/opcode_test.go index 6e3205a209..1487dde590 100644 --- a/txscript/opcode_test.go +++ b/txscript/opcode_test.go @@ -124,7 +124,7 @@ func TestOpcodeDisasm(t *testing.T) { // OP_UNKNOWN#. case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc: - expectedStr = "OP_UNKNOWN" + strconv.Itoa(int(opcodeVal)) + expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) } pop := parsedOpcode{opcode: &opcodeArray[opcodeVal], data: data} @@ -190,7 +190,7 @@ func TestOpcodeDisasm(t *testing.T) { // OP_UNKNOWN#. case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc: - expectedStr = "OP_UNKNOWN" + strconv.Itoa(int(opcodeVal)) + expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) } pop := parsedOpcode{opcode: &opcodeArray[opcodeVal], data: data} diff --git a/wire/common_test.go b/wire/common_test.go index fa963d4b5d..46e3fa6613 100644 --- a/wire/common_test.go +++ b/wire/common_test.go @@ -118,15 +118,15 @@ func TestElementWire(t *testing.T) { }, }, { - ServiceFlag(SFNodeNetwork), + SFNodeNetwork, []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }, { - InvType(InvTypeTx), + InvTypeTx, []byte{0x01, 0x00, 0x00, 0x00}, }, { - BitcoinNet(MainNet), + MainNet, []byte{0xf9, 0xbe, 0xb4, 0xd9}, }, // Type not supported by the "fast" path and requires reflection. @@ -211,9 +211,9 @@ func TestElementWireErrors(t *testing.T) { }), 0, io.ErrShortWrite, io.EOF, }, - {ServiceFlag(SFNodeNetwork), 0, io.ErrShortWrite, io.EOF}, - {InvType(InvTypeTx), 0, io.ErrShortWrite, io.EOF}, - {BitcoinNet(MainNet), 0, io.ErrShortWrite, io.EOF}, + {SFNodeNetwork, 0, io.ErrShortWrite, io.EOF}, + {InvTypeTx, 0, io.ErrShortWrite, io.EOF}, + {MainNet, 0, io.ErrShortWrite, io.EOF}, } t.Logf("Running %d tests", len(tests)) From d38279ee7446d9ee17cb7242afb5ccb32c3775ec Mon Sep 17 00:00:00 2001 From: Henry Date: Thu, 14 May 2020 18:27:59 -0600 Subject: [PATCH 0348/1056] btcjson: change getblock default verbosity to 1 This change makes btcd's getblock command match bitcoind's. Previously the default verbosity was 0, which caused errors when using the rpcclient library to connect to a bitcoind node - getblock would unmarshall incorrectly since it didn't expect a verbosity=1 result when it did not specify verbosity. --- btcjson/chainsvrcmds.go | 2 +- btcjson/chainsvrcmds_test.go | 14 ++++++++++++++ btcjson/cmdinfo_test.go | 2 +- rpcclient/chain.go | 2 +- rpcserver.go | 6 ++---- rpcserverhelp.go | 4 ++-- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 90ab70ece7..2f3069fd15 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -130,7 +130,7 @@ func NewGetBestBlockHashCmd() *GetBestBlockHashCmd { // GetBlockCmd defines the getblock JSON-RPC command. type GetBlockCmd struct { Hash string - Verbosity *int `jsonrpcdefault:"0"` + Verbosity *int `jsonrpcdefault:"1"` } // NewGetBlockCmd returns a new instance which can be used to issue a getblock diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index dca2332860..8f3fd455c5 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -153,6 +153,20 @@ func TestChainSvrCmds(t *testing.T) { Verbosity: btcjson.Int(0), }, }, + { + name: "getblock default verbosity", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblock", "123") + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockCmd("123", nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblock","params":["123"],"id":1}`, + unmarshalled: &btcjson.GetBlockCmd{ + Hash: "123", + Verbosity: btcjson.Int(1), + }, + }, { name: "getblock required optional1", newCmd: func() (interface{}, error) { diff --git a/btcjson/cmdinfo_test.go b/btcjson/cmdinfo_test.go index 471fccfc77..61a693e404 100644 --- a/btcjson/cmdinfo_test.go +++ b/btcjson/cmdinfo_test.go @@ -151,7 +151,7 @@ func TestMethodUsageText(t *testing.T) { { name: "getblock", method: "getblock", - expected: `getblock "hash" (verbosity=0)`, + expected: `getblock "hash" (verbosity=1)`, }, } diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 707978ca65..a5ec9e5412 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -97,7 +97,7 @@ func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult { hash = blockHash.String() } - cmd := btcjson.NewGetBlockCmd(hash, nil) + cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(0)) return c.sendCmd(cmd) } diff --git a/rpcserver.go b/rpcserver.go index 2da7e9f57e..89817db856 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1081,14 +1081,12 @@ func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i Message: "Block not found", } } - - // When the verbose flag isn't set, simply return the serialized block - // as a hex-encoded string. + // If verbosity is 0, return the serialized block as a hex encoded string. if c.Verbosity != nil && *c.Verbosity == 0 { return hex.EncodeToString(blkBytes), nil } - // The verbose flag is set, so generate the JSON object and return it. + // Otherwise, generate the JSON object and return it. // Deserialize the block. blk, err := btcutil.NewBlockFromBytes(blkBytes) diff --git a/rpcserverhelp.go b/rpcserverhelp.go index cee2407566..38a5351355 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -243,8 +243,8 @@ var helpDescsEnUS = map[string]string{ "getblockverboseresult-version": "The block version", "getblockverboseresult-versionHex": "The block version in hexadecimal", "getblockverboseresult-merkleroot": "Root hash of the merkle tree", - "getblockverboseresult-tx": "The transaction hashes (only when verbosetx=false)", - "getblockverboseresult-rawtx": "The transactions as JSON objects (only when verbosetx=true)", + "getblockverboseresult-tx": "The transaction hashes (only when verbosity=1)", + "getblockverboseresult-rawtx": "The transactions as JSON objects (only when verbosity=2)", "getblockverboseresult-time": "The block time in seconds since 1 Jan 1970 GMT", "getblockverboseresult-nonce": "The block nonce", "getblockverboseresult-bits": "The bits which represent the block difficulty", From 742935e3a9da8c52350b2422cdba1ccbbf231d5d Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 14 May 2020 14:15:50 -0700 Subject: [PATCH 0349/1056] rpcclient: send legacy GetBlock request for backwards compatibility Without this, users of this library wouldn't be able to issue GetBlock requests to nodes which haven't updated to support the latest request format, namely the use of a single `int` parameter to denote verbosity instead of two `bool`s. --- rpcclient/chain.go | 95 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/rpcclient/chain.go b/rpcclient/chain.go index a5ec9e5412..6e701b1c97 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -52,14 +52,61 @@ func (c *Client) GetBestBlockHash() (*chainhash.Hash, error) { return c.GetBestBlockHashAsync().Receive() } +// legacyGetBlockRequest constructs and sends a legacy getblock request which +// contains two separate bools to denote verbosity, in contract to a single int +// parameter. +func (c *Client) legacyGetBlockRequest(hash string, verbose, + verboseTx bool) ([]byte, error) { + + hashJSON, err := json.Marshal(hash) + if err != nil { + return nil, err + } + verboseJSON, err := json.Marshal(btcjson.Bool(verbose)) + if err != nil { + return nil, err + } + verboseTxJSON, err := json.Marshal(btcjson.Bool(verboseTx)) + if err != nil { + return nil, err + } + return c.RawRequest("getblock", []json.RawMessage{ + hashJSON, verboseJSON, verboseTxJSON, + }) +} + +// waitForGetBlockRes waits for the response of a getblock request. If the +// response indicates an invalid parameter was provided, a legacy style of the +// request is resent and its response is returned instead. +func (c *Client) waitForGetBlockRes(respChan chan *response, hash string, + verbose, verboseTx bool) ([]byte, error) { + + res, err := receiveFuture(respChan) + + // If we receive an invalid parameter error, then we may be + // communicating with a btcd node which only understands the legacy + // request, so we'll try that. + if err, ok := err.(*btcjson.RPCError); ok && + err.Code == btcjson.ErrRPCInvalidParams.Code { + return c.legacyGetBlockRequest(hash, verbose, verboseTx) + } + + // Otherwise, we can return the response as is. + return res, err +} + // FutureGetBlockResult is a future promise to deliver the result of a // GetBlockAsync RPC invocation (or an applicable error). -type FutureGetBlockResult chan *response +type FutureGetBlockResult struct { + client *Client + hash string + Response chan *response +} // Receive waits for the response promised by the future and returns the raw // block requested from the server given its hash. func (r FutureGetBlockResult) Receive() (*wire.MsgBlock, error) { - res, err := receiveFuture(r) + res, err := r.client.waitForGetBlockRes(r.Response, r.hash, false, false) if err != nil { return nil, err } @@ -98,7 +145,11 @@ func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult { } cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(0)) - return c.sendCmd(cmd) + return FutureGetBlockResult{ + client: c, + hash: hash, + Response: c.sendCmd(cmd), + } } // GetBlock returns a raw block from the server given its hash. @@ -111,12 +162,16 @@ func (c *Client) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) { // FutureGetBlockVerboseResult is a future promise to deliver the result of a // GetBlockVerboseAsync RPC invocation (or an applicable error). -type FutureGetBlockVerboseResult chan *response +type FutureGetBlockVerboseResult struct { + client *Client + hash string + Response chan *response +} // Receive waits for the response promised by the future and returns the data // structure from the server with information about the requested block. func (r FutureGetBlockVerboseResult) Receive() (*btcjson.GetBlockVerboseResult, error) { - res, err := receiveFuture(r) + res, err := r.client.waitForGetBlockRes(r.Response, r.hash, true, false) if err != nil { return nil, err } @@ -143,7 +198,11 @@ func (c *Client) GetBlockVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockV // From the bitcoin-cli getblock documentation: // "If verbosity is 1, returns an Object with information about block ." cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(1)) - return c.sendCmd(cmd) + return FutureGetBlockVerboseResult{ + client: c, + hash: hash, + Response: c.sendCmd(cmd), + } } // GetBlockVerbose returns a data structure from the server with information @@ -155,10 +214,18 @@ func (c *Client) GetBlockVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockVe return c.GetBlockVerboseAsync(blockHash).Receive() } -type FutureGetBlockVerboseTxResult chan *response +// FutureGetBlockVerboseTxResult is a future promise to deliver the result of a +// GetBlockVerboseTxResult RPC invocation (or an applicable error). +type FutureGetBlockVerboseTxResult struct { + client *Client + hash string + Response chan *response +} +// Receive waits for the response promised by the future and returns a verbose +// version of the block including detailed information about its transactions. func (r FutureGetBlockVerboseTxResult) Receive() (*btcjson.GetBlockVerboseTxResult, error) { - res, err := receiveFuture(r) + res, err := r.client.waitForGetBlockRes(r.Response, r.hash, true, true) if err != nil { return nil, err } @@ -182,11 +249,17 @@ func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBloc if blockHash != nil { hash = blockHash.String() } + // From the bitcoin-cli getblock documentation: - // "If verbosity is 2, returns an Object with information about block and information about each transaction." + // + // If verbosity is 2, returns an Object with information about block + // and information about each transaction. cmd := btcjson.NewGetBlockCmd(hash, btcjson.Int(2)) - - return c.sendCmd(cmd) + return FutureGetBlockVerboseTxResult{ + client: c, + hash: hash, + Response: c.sendCmd(cmd), + } } // GetBlockVerboseTx returns a data structure from the server with information From 280845a8a4aebd432030201e50c74b0a29e01a94 Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Mon, 25 May 2020 20:15:11 +0000 Subject: [PATCH 0350/1056] rpcclient: Add cookie auth Based on Hugo Landau's cookie auth implementation for Namecoin's ncdns. Fixes https://github.com/btcsuite/btcd/issues/1054 --- rpcclient/cookiefile.go | 64 +++++++++++++++++++++++++++++++++++++ rpcclient/infrastructure.go | 41 ++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 rpcclient/cookiefile.go diff --git a/rpcclient/cookiefile.go b/rpcclient/cookiefile.go new file mode 100644 index 0000000000..9311fbbfcf --- /dev/null +++ b/rpcclient/cookiefile.go @@ -0,0 +1,64 @@ +// Copyright (c) 2017 The Namecoin developers +// Copyright (c) 2019 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package rpcclient + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + "time" +) + +func readCookieFile(path string) (username, password string, err error) { + b, err := ioutil.ReadFile(path) + if err != nil { + return + } + + s := strings.TrimSpace(string(b)) + parts := strings.SplitN(s, ":", 2) + if len(parts) != 2 { + err = fmt.Errorf("malformed cookie file") + return + } + + username, password = parts[0], parts[1] + return +} + +func cookieRetriever(path string) func() (username, password string, err error) { + lastCheckTime := time.Time{} + lastModTime := time.Time{} + + curUsername, curPassword := "", "" + var curError error + + doUpdate := func() { + if !lastCheckTime.IsZero() && time.Now().Before(lastCheckTime.Add(30*time.Second)) { + return + } + + lastCheckTime = time.Now() + + st, err := os.Stat(path) + if err != nil { + curError = err + return + } + + modTime := st.ModTime() + if !modTime.Equal(lastModTime) { + lastModTime = modTime + curUsername, curPassword, curError = readCookieFile(path) + } + } + + return func() (username, password string, err error) { + doUpdate() + return curUsername, curPassword, curError + } +} diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index a2079886d3..fa9e00e232 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -851,7 +851,12 @@ func (c *Client) sendPost(jReq *jsonRequest) { httpReq.Header.Set("Content-Type", "application/json") // Configure basic access authorization. - httpReq.SetBasicAuth(c.config.User, c.config.Pass) + user, pass, err := c.config.getAuth() + if err != nil { + jReq.responseChan <- &response{result: nil, err: err} + return + } + httpReq.SetBasicAuth(user, pass) log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id) c.sendPostRequest(httpReq, jReq) @@ -1096,6 +1101,15 @@ type ConnConfig struct { // Pass is the passphrase to use to authenticate to the RPC server. Pass string + // CookiePath is the path to a cookie file containing the username and + // passphrase to use to authenticate to the RPC server. It is used + // instead of User and Pass if non-empty. + CookiePath string + + // retrieveCookie is a function that returns the cookie username and + // passphrase. + retrieveCookie func() (username, passphrase string, err error) + // Params is the string representing the network that the server // is running. If there is no parameter set in the config, then // mainnet will be used by default. @@ -1149,6 +1163,25 @@ type ConnConfig struct { EnableBCInfoHacks bool } +// getAuth returns the username and passphrase that will actually be used for +// this connection. This will be the result of checking the cookie if a cookie +// path is configured; if not, it will be the user-configured username and +// passphrase. +func (config *ConnConfig) getAuth() (username, passphrase string, err error) { + // If cookie auth isn't in use, just use the supplied + // username/passphrase. + if config.CookiePath == "" { + return config.User, config.Pass, nil + } + + // Initialize the cookie retriever on first run. + if config.retrieveCookie == nil { + config.retrieveCookie = cookieRetriever(config.CookiePath) + } + + return config.retrieveCookie() +} + // newHTTPClient returns a new http client that is configured according to the // proxy and TLS settings in the associated connection configuration. func newHTTPClient(config *ConnConfig) (*http.Client, error) { @@ -1218,7 +1251,11 @@ func dial(config *ConnConfig) (*websocket.Conn, error) { // The RPC server requires basic authorization, so create a custom // request header with the Authorization header set. - login := config.User + ":" + config.Pass + user, pass, err := config.getAuth() + if err != nil { + return nil, err + } + login := user + ":" + pass auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login)) requestHeader := make(http.Header) requestHeader.Add("Authorization", auth) From 915788b8e6e0c65adad447fa2796de544fb0fc6a Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Wed, 9 Oct 2019 11:23:05 +0000 Subject: [PATCH 0351/1056] rpcclient: Refactor cookie caching --- rpcclient/cookiefile.go | 35 ----------------------------------- rpcclient/infrastructure.go | 35 ++++++++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/rpcclient/cookiefile.go b/rpcclient/cookiefile.go index 9311fbbfcf..b29e29b759 100644 --- a/rpcclient/cookiefile.go +++ b/rpcclient/cookiefile.go @@ -8,9 +8,7 @@ package rpcclient import ( "fmt" "io/ioutil" - "os" "strings" - "time" ) func readCookieFile(path string) (username, password string, err error) { @@ -29,36 +27,3 @@ func readCookieFile(path string) (username, password string, err error) { username, password = parts[0], parts[1] return } - -func cookieRetriever(path string) func() (username, password string, err error) { - lastCheckTime := time.Time{} - lastModTime := time.Time{} - - curUsername, curPassword := "", "" - var curError error - - doUpdate := func() { - if !lastCheckTime.IsZero() && time.Now().Before(lastCheckTime.Add(30*time.Second)) { - return - } - - lastCheckTime = time.Now() - - st, err := os.Stat(path) - if err != nil { - curError = err - return - } - - modTime := st.ModTime() - if !modTime.Equal(lastModTime) { - lastModTime = modTime - curUsername, curPassword, curError = readCookieFile(path) - } - } - - return func() (username, password string, err error) { - doUpdate() - return curUsername, curPassword, curError - } -} diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index fa9e00e232..42aeb49fbd 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -19,6 +19,7 @@ import ( "net" "net/http" "net/url" + "os" "strings" "sync" "sync/atomic" @@ -1106,9 +1107,11 @@ type ConnConfig struct { // instead of User and Pass if non-empty. CookiePath string - // retrieveCookie is a function that returns the cookie username and - // passphrase. - retrieveCookie func() (username, passphrase string, err error) + cookieLastCheckTime time.Time + cookieLastModTime time.Time + cookieLastUser string + cookieLastPass string + cookieLastErr error // Params is the string representing the network that the server // is running. If there is no parameter set in the config, then @@ -1174,12 +1177,30 @@ func (config *ConnConfig) getAuth() (username, passphrase string, err error) { return config.User, config.Pass, nil } - // Initialize the cookie retriever on first run. - if config.retrieveCookie == nil { - config.retrieveCookie = cookieRetriever(config.CookiePath) + return config.retrieveCookie() +} + +// retrieveCookie returns the cookie username and passphrase. +func (config *ConnConfig) retrieveCookie() (username, passphrase string, err error) { + if !config.cookieLastCheckTime.IsZero() && time.Now().Before(config.cookieLastCheckTime.Add(30*time.Second)) { + return config.cookieLastUser, config.cookieLastPass, config.cookieLastErr } - return config.retrieveCookie() + config.cookieLastCheckTime = time.Now() + + st, err := os.Stat(config.CookiePath) + if err != nil { + config.cookieLastErr = err + return config.cookieLastUser, config.cookieLastPass, config.cookieLastErr + } + + modTime := st.ModTime() + if !modTime.Equal(config.cookieLastModTime) { + config.cookieLastModTime = modTime + config.cookieLastUser, config.cookieLastPass, config.cookieLastErr = readCookieFile(config.CookiePath) + } + + return config.cookieLastUser, config.cookieLastPass, config.cookieLastErr } // newHTTPClient returns a new http client that is configured according to the From e6f163e61e4fcf13038d5775c079e3da27637282 Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Wed, 9 Oct 2019 11:08:42 +0000 Subject: [PATCH 0352/1056] rpcclient: Try user+pass auth before cookie auth --- rpcclient/infrastructure.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 42aeb49fbd..8609e7c5ad 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -1171,12 +1171,12 @@ type ConnConfig struct { // path is configured; if not, it will be the user-configured username and // passphrase. func (config *ConnConfig) getAuth() (username, passphrase string, err error) { - // If cookie auth isn't in use, just use the supplied - // username/passphrase. - if config.CookiePath == "" { + // Try username+passphrase auth first. + if config.Pass != "" { return config.User, config.Pass, nil } + // If no username or passphrase is set, try cookie auth. return config.retrieveCookie() } From 6d521ff8cdbb2bae1a9a16bb64f765aff8d4be56 Mon Sep 17 00:00:00 2001 From: JeremyRand Date: Thu, 10 Oct 2019 22:59:50 +0000 Subject: [PATCH 0353/1056] rpcclient: Read first line of cookie instead of trimming space --- rpcclient/cookiefile.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/rpcclient/cookiefile.go b/rpcclient/cookiefile.go index b29e29b759..c3f7068b30 100644 --- a/rpcclient/cookiefile.go +++ b/rpcclient/cookiefile.go @@ -6,18 +6,27 @@ package rpcclient import ( + "bufio" "fmt" - "io/ioutil" + "os" "strings" ) func readCookieFile(path string) (username, password string, err error) { - b, err := ioutil.ReadFile(path) + f, err := os.Open(path) if err != nil { return } + defer f.Close() + + scanner := bufio.NewScanner(f) + scanner.Scan() + err = scanner.Err() + if err != nil { + return + } + s := scanner.Text() - s := strings.TrimSpace(string(b)) parts := strings.SplitN(s, ":", 2) if len(parts) != 2 { err = fmt.Errorf("malformed cookie file") From 714de3f3c74d7719cd95ceb8a9c68cb7cf74c832 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Thu, 2 Apr 2020 11:01:56 +0200 Subject: [PATCH 0354/1056] rpcclient: serialize nil inputs to empty list --- btcjson/chainsvrcmds.go | 9 +++++++-- btcjson/chainsvrcmds_test.go | 15 +++++++++++++++ rpcclient/rawtransactions.go | 3 ++- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 2f3069fd15..1345f8f7c8 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -63,10 +63,15 @@ type CreateRawTransactionCmd struct { // NewCreateRawTransactionCmd returns a new instance which can be used to issue // a createrawtransaction JSON-RPC command. // -// Amounts are in BTC. +// Amounts are in BTC. Passing in nil and the empty slice as inputs is equivalent, +// both gets interpreted as the empty slice. func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]float64, lockTime *int64) *CreateRawTransactionCmd { - + // to make sure we're serializing this to the empty list and not null, we + // explicitly initialize the list + if inputs == nil { + inputs = []TransactionInput{} + } return &CreateRawTransactionCmd{ Inputs: inputs, Amounts: amounts, diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 8f3fd455c5..dd997ce5e9 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -60,6 +60,21 @@ func TestChainSvrCmds(t *testing.T) { Amounts: map[string]float64{"456": .0123}, }, }, + { + name: "createrawtransaction - no inputs", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("createrawtransaction", `[]`, `{"456":0.0123}`) + }, + staticCmd: func() interface{} { + amounts := map[string]float64{"456": .0123} + return btcjson.NewCreateRawTransactionCmd(nil, amounts, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"createrawtransaction","params":[[],{"456":0.0123}],"id":1}`, + unmarshalled: &btcjson.CreateRawTransactionCmd{ + Inputs: []btcjson.TransactionInput{}, + Amounts: map[string]float64{"456": .0123}, + }, + }, { name: "createrawtransaction optional", newCmd: func() (interface{}, error) { diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 23754d961d..63a086642a 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -261,7 +261,8 @@ func (c *Client) CreateRawTransactionAsync(inputs []btcjson.TransactionInput, } // CreateRawTransaction returns a new transaction spending the provided inputs -// and sending to the provided addresses. +// and sending to the provided addresses. If the inputs are either nil or an +// empty slice, it is interpreted as an empty slice. func (c *Client) CreateRawTransaction(inputs []btcjson.TransactionInput, amounts map[btcutil.Address]btcutil.Amount, lockTime *int64) (*wire.MsgTx, error) { From b11bf582c51fdf3888433575a104d301a095f337 Mon Sep 17 00:00:00 2001 From: Mikael Lindlof Date: Sun, 17 May 2020 13:02:24 +0100 Subject: [PATCH 0355/1056] Improve chain state init efficiency Remove unnecessary slice of all block indexes and remove DB iteration over all block indexes that used to determined the size of the slice. --- blockchain/chainio.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 8d76d3ca94..c456c006f3 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1149,18 +1149,9 @@ func (b *BlockChain) initChainState() error { blockIndexBucket := dbTx.Metadata().Bucket(blockIndexBucketName) - // Determine how many blocks will be loaded into the index so we can - // allocate the right amount. - var blockCount int32 - cursor := blockIndexBucket.Cursor() - for ok := cursor.First(); ok; ok = cursor.Next() { - blockCount++ - } - blockNodes := make([]blockNode, blockCount) - var i int32 var lastNode *blockNode - cursor = blockIndexBucket.Cursor() + cursor := blockIndexBucket.Cursor() for ok := cursor.First(); ok; ok = cursor.Next() { header, status, err := deserializeBlockRow(cursor.Value()) if err != nil { @@ -1193,7 +1184,7 @@ func (b *BlockChain) initChainState() error { // Initialize the block node for the block, connect it, // and add it to the block index. - node := &blockNodes[i] + node := new(blockNode) initBlockNode(node, header, parent) node.status = status b.index.addNode(node) From a383a7167007197578e780476cf5719c97dfd31b Mon Sep 17 00:00:00 2001 From: adiabat Date: Fri, 29 May 2020 12:03:02 -0400 Subject: [PATCH 0356/1056] Add blockchain.NewUtxoEntry() to directly create entries for UtxoViewpoint The current methods to add to a UtxoViewpoint don't allow for a situation where we have only UTXO data but not a whole transaction. This commit allows contstruction of a UtxoEntry without requiring a full MsgTx. AddTxOut() and AddTxOuts() both require a whole transaction, including the inputs, which are only used in order to calculate the txid. In some situations, such as with use of the utreexo accumulator, we only have the utxo data but not the transaction which created it. For reference, utreexo's initial usage of the blockchain.NewUtxoEntry() function is at https://github.com/mit-dci/utreexo/pull/135/files#diff-3f7b8f9991ea957f1f4ad9f5a95415f0R96 --- blockchain/utxoviewpoint.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 08005d27a1..b85765814d 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -111,6 +111,22 @@ func (entry *UtxoEntry) Clone() *UtxoEntry { } } +// NewUtxoEntry returns a new UtxoEntry built from the arguments. +func NewUtxoEntry( + txOut *wire.TxOut, blockHeight int32, isCoinbase bool) *UtxoEntry { + var cbFlag txoFlags + if isCoinbase { + cbFlag |= tfCoinBase + } + + return &UtxoEntry{ + amount: txOut.Value, + pkScript: txOut.PkScript, + blockHeight: blockHeight, + packedFlags: cbFlag, + } +} + // UtxoViewpoint represents a view into the set of unspent transaction outputs // from a specific point of view in the chain. For example, it could be for // the end of the main chain, some point in the history of the main chain, or From 73d69f09d095bb21eca304538a9e0f0586bae8d3 Mon Sep 17 00:00:00 2001 From: Mikael Lindlof Date: Mon, 11 May 2020 19:12:44 +0100 Subject: [PATCH 0357/1056] Add getchaintxstats JSON-RPC client command --- btcjson/chainsvrcmds.go | 19 ++++++++++ btcjson/chainsvrcmds_test.go | 38 +++++++++++++++++++ btcjson/chainsvrresults.go | 12 ++++++ rpcclient/chain.go | 73 ++++++++++++++++++++++++++++++++++++ 4 files changed, 142 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 1345f8f7c8..983a4e969f 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -368,6 +368,24 @@ func NewGetChainTipsCmd() *GetChainTipsCmd { return &GetChainTipsCmd{} } +// GetChainTxStatsCmd defines the getchaintxstats JSON-RPC command. +type GetChainTxStatsCmd struct { + NBlocks *int32 + BlockHash *string +} + +// NewGetChainTxStatsCmd returns a new instance which can be used to issue a +// getchaintxstats JSON-RPC command. +// +// The parameters which are pointers indicate they are optional. Passing nil +// for optional parameters will use the default value. +func NewGetChainTxStatsCmd(nBlocks *int32, blockHash *string) *GetChainTxStatsCmd { + return &GetChainTxStatsCmd{ + NBlocks: nBlocks, + BlockHash: blockHash, + } +} + // GetConnectionCountCmd defines the getconnectioncount JSON-RPC command. type GetConnectionCountCmd struct{} @@ -852,6 +870,7 @@ func init() { MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags) MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags) MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags) + MustRegisterCmd("getchaintxstats", (*GetChainTxStatsCmd)(nil), flags) MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags) MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags) MustRegisterCmd("getgenerate", (*GetGenerateCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index dd997ce5e9..400ad25a75 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -437,6 +437,44 @@ func TestChainSvrCmds(t *testing.T) { marshalled: `{"jsonrpc":"1.0","method":"getchaintips","params":[],"id":1}`, unmarshalled: &btcjson.GetChainTipsCmd{}, }, + { + name: "getchaintxstats", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getchaintxstats") + }, + staticCmd: func() interface{} { + return btcjson.NewGetChainTxStatsCmd(nil, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getchaintxstats","params":[],"id":1}`, + unmarshalled: &btcjson.GetChainTxStatsCmd{}, + }, + { + name: "getchaintxstats optional nblocks", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getchaintxstats", btcjson.Int32(1000)) + }, + staticCmd: func() interface{} { + return btcjson.NewGetChainTxStatsCmd(btcjson.Int32(1000), nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getchaintxstats","params":[1000],"id":1}`, + unmarshalled: &btcjson.GetChainTxStatsCmd{ + NBlocks: btcjson.Int32(1000), + }, + }, + { + name: "getchaintxstats optional nblocks and blockhash", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getchaintxstats", btcjson.Int32(1000), btcjson.String("0000afaf")) + }, + staticCmd: func() interface{} { + return btcjson.NewGetChainTxStatsCmd(btcjson.Int32(1000), btcjson.String("0000afaf")) + }, + marshalled: `{"jsonrpc":"1.0","method":"getchaintxstats","params":[1000,"0000afaf"],"id":1}`, + unmarshalled: &btcjson.GetChainTxStatsCmd{ + NBlocks: btcjson.Int32(1000), + BlockHash: btcjson.String("0000afaf"), + }, + }, { name: "getconnectioncount", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index d076b74691..0c4e66bb99 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -107,6 +107,18 @@ type GetBlockVerboseTxResult struct { NextHash string `json:"nextblockhash,omitempty"` } +// GetChainTxStatsResult models the data from the getchaintxstats command. +type GetChainTxStatsResult struct { + Time int64 `json:"time"` + TxCount int64 `json:"txcount"` + WindowFinalBlockHash string `json:"window_final_block_hash"` + WindowFinalBlockHeight int32 `json:"window_final_block_height"` + WindowBlockCount int32 `json:"window_block_count"` + WindowTxCount int32 `json:"window_tx_count"` + WindowInterval int32 `json:"window_interval"` + TxRate float64 `json:"txrate"` +} + // CreateMultiSigResult models the data returned from the createmultisig // command. type CreateMultiSigResult struct { diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 6e701b1c97..9f0c6c684d 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -307,6 +307,79 @@ func (c *Client) GetBlockCount() (int64, error) { return c.GetBlockCountAsync().Receive() } +// FutureGetChainTxStatsResult is a future promise to deliver the result of a +// GetChainTxStatsAsync RPC invocation (or an applicable error). +type FutureGetChainTxStatsResult chan *response + +// Receive waits for the response promised by the future and returns transaction statistics +func (r FutureGetChainTxStatsResult) Receive() (*btcjson.GetChainTxStatsResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var chainTxStats btcjson.GetChainTxStatsResult + err = json.Unmarshal(res, &chainTxStats) + if err != nil { + return nil, err + } + + return &chainTxStats, nil +} + +// GetChainTxStatsAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetChainTxStats for the blocking version and more details. +func (c *Client) GetChainTxStatsAsync() FutureGetChainTxStatsResult { + cmd := btcjson.NewGetChainTxStatsCmd(nil, nil) + return c.sendCmd(cmd) +} + +// GetChainTxStatsNBlocksAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetChainTxStatsNBlocks for the blocking version and more details. +func (c *Client) GetChainTxStatsNBlocksAsync(nBlocks int32) FutureGetChainTxStatsResult { + cmd := btcjson.NewGetChainTxStatsCmd(&nBlocks, nil) + return c.sendCmd(cmd) +} + +// GetChainTxStatsNBlocksBlockHashAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetChainTxStatsNBlocksBlockHash for the blocking version and more details. +func (c *Client) GetChainTxStatsNBlocksBlockHashAsync(nBlocks int32, blockHash chainhash.Hash) FutureGetChainTxStatsResult { + hash := blockHash.String() + cmd := btcjson.NewGetChainTxStatsCmd(&nBlocks, &hash) + return c.sendCmd(cmd) +} + +// GetChainTxStats returns statistics about the total number and rate of transactions in the chain. +// +// Size of the window is one month and it ends at chain tip. +func (c *Client) GetChainTxStats() (*btcjson.GetChainTxStatsResult, error) { + return c.GetChainTxStatsAsync().Receive() +} + +// GetChainTxStatsNBlocks returns statistics about the total number and rate of transactions in the chain. +// +// The argument specifies size of the window in number of blocks. The window ends at chain tip. +func (c *Client) GetChainTxStatsNBlocks(nBlocks int32) (*btcjson.GetChainTxStatsResult, error) { + return c.GetChainTxStatsNBlocksAsync(nBlocks).Receive() +} + +// GetChainTxStatsNBlocksBlockHash returns statistics about the total number and rate of transactions in the chain. +// +// First argument specifies size of the window in number of blocks. +// Second argument is the hash of the block that ends the window. +func (c *Client) GetChainTxStatsNBlocksBlockHash(nBlocks int32, blockHash chainhash.Hash) (*btcjson.GetChainTxStatsResult, error) { + return c.GetChainTxStatsNBlocksBlockHashAsync(nBlocks, blockHash).Receive() +} + // FutureGetDifficultyResult is a future promise to deliver the result of a // GetDifficultyAsync RPC invocation (or an applicable error). type FutureGetDifficultyResult chan *response From e4f59022a387f27253674d3a389047a23615b0f1 Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Mon, 2 Dec 2019 11:39:27 +0100 Subject: [PATCH 0358/1056] Add fundrawtransaction RPC call --- btcjson/chainsvrcmds.go | 33 ++++++++++++ btcjson/chainsvrcmds_test.go | 102 +++++++++++++++++++++++++++++++++++ btcjson/chainsvrresults.go | 56 ++++++++++++++++++- rpcclient/rawtransactions.go | 41 ++++++++++++++ 4 files changed, 231 insertions(+), 1 deletion(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 983a4e969f..d66478c305 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -8,6 +8,7 @@ package btcjson import ( + "encoding/hex" "encoding/json" "fmt" @@ -79,6 +80,37 @@ func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]fl } } +// FundRawTransactionOpts are the different options that can be passed to rawtransaction +type FundRawTransactionOpts struct { + ChangeAddress *string `json:"changeAddress,omitempty"` + ChangePosition *int `json:"changePosition,omitempty"` + ChangeType *string `json:"change_type,omitempty"` + IncludeWatching *bool `json:"includeWatching,omitempty"` + LockUnspents *bool `json:"lockUnspents,omitempty"` + FeeRate *float64 `json:"feeRate,omitempty"` // BTC/kB + SubtractFeeFromOutputs []int `json:"subtractFeeFromOutputs,omitempty"` + Replaceable *bool `json:"replaceable,omitempty"` + ConfTarget *int `json:"conf_target,omitempty"` + EstimateMode *EstimateSmartFeeMode `json:"estimate_mode,omitempty"` +} + +// FundRawTransactionCmd defines the fundrawtransaction JSON-RPC command +type FundRawTransactionCmd struct { + HexTx string + Options FundRawTransactionOpts + IsWitness *bool +} + +// NewFundRawTransactionCmd returns a new instance which can be used to issue +// a fundrawtransaction JSON-RPC command +func NewFundRawTransactionCmd(serializedTx []byte, opts FundRawTransactionOpts, isWitness *bool) *FundRawTransactionCmd { + return &FundRawTransactionCmd{ + HexTx: hex.EncodeToString(serializedTx), + Options: opts, + IsWitness: isWitness, + } +} + // DecodeRawTransactionCmd defines the decoderawtransaction JSON-RPC command. type DecodeRawTransactionCmd struct { HexTx string @@ -856,6 +888,7 @@ func init() { MustRegisterCmd("addnode", (*AddNodeCmd)(nil), flags) MustRegisterCmd("createrawtransaction", (*CreateRawTransactionCmd)(nil), flags) + MustRegisterCmd("fundrawtransaction", (*FundRawTransactionCmd)(nil), flags) MustRegisterCmd("decoderawtransaction", (*DecodeRawTransactionCmd)(nil), flags) MustRegisterCmd("decodescript", (*DecodeScriptCmd)(nil), flags) MustRegisterCmd("getaddednodeinfo", (*GetAddedNodeInfoCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 400ad25a75..e2b5025727 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -6,6 +6,7 @@ package btcjson_test import ( "bytes" + "encoding/hex" "encoding/json" "fmt" "reflect" @@ -95,7 +96,108 @@ func TestChainSvrCmds(t *testing.T) { LockTime: btcjson.Int64(12312333333), }, }, + { + name: "fundrawtransaction - empty opts", + newCmd: func() (i interface{}, e error) { + return btcjson.NewCmd("fundrawtransaction", "deadbeef", "{}") + }, + staticCmd: func() interface{} { + deadbeef, err := hex.DecodeString("deadbeef") + if err != nil { + panic(err) + } + return btcjson.NewFundRawTransactionCmd(deadbeef, btcjson.FundRawTransactionOpts{}, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"fundrawtransaction","params":["deadbeef",{}],"id":1}`, + unmarshalled: &btcjson.FundRawTransactionCmd{ + HexTx: "deadbeef", + Options: btcjson.FundRawTransactionOpts{}, + IsWitness: nil, + }, + }, + { + name: "fundrawtransaction - full opts", + newCmd: func() (i interface{}, e error) { + return btcjson.NewCmd("fundrawtransaction", "deadbeef", `{"changeAddress":"bcrt1qeeuctq9wutlcl5zatge7rjgx0k45228cxez655","changePosition":1,"change_type":"legacy","includeWatching":true,"lockUnspents":true,"feeRate":0.7,"subtractFeeFromOutputs":[0],"replaceable":true,"conf_target":8,"estimate_mode":"ECONOMICAL"}`) + }, + staticCmd: func() interface{} { + deadbeef, err := hex.DecodeString("deadbeef") + if err != nil { + panic(err) + } + changeAddress := "bcrt1qeeuctq9wutlcl5zatge7rjgx0k45228cxez655" + change := 1 + changeType := "legacy" + watching := true + lockUnspents := true + feeRate := 0.7 + replaceable := true + confTarget := 8 + return btcjson.NewFundRawTransactionCmd(deadbeef, btcjson.FundRawTransactionOpts{ + ChangeAddress: &changeAddress, + ChangePosition: &change, + ChangeType: &changeType, + IncludeWatching: &watching, + LockUnspents: &lockUnspents, + FeeRate: &feeRate, + SubtractFeeFromOutputs: []int{0}, + Replaceable: &replaceable, + ConfTarget: &confTarget, + EstimateMode: &btcjson.EstimateModeEconomical, + }, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"fundrawtransaction","params":["deadbeef",{"changeAddress":"bcrt1qeeuctq9wutlcl5zatge7rjgx0k45228cxez655","changePosition":1,"change_type":"legacy","includeWatching":true,"lockUnspents":true,"feeRate":0.7,"subtractFeeFromOutputs":[0],"replaceable":true,"conf_target":8,"estimate_mode":"ECONOMICAL"}],"id":1}`, + unmarshalled: func() interface{} { + changeAddress := "bcrt1qeeuctq9wutlcl5zatge7rjgx0k45228cxez655" + change := 1 + changeType := "legacy" + watching := true + lockUnspents := true + feeRate := 0.7 + replaceable := true + confTarget := 8 + return &btcjson.FundRawTransactionCmd{ + HexTx: "deadbeef", + Options: btcjson.FundRawTransactionOpts{ + ChangeAddress: &changeAddress, + ChangePosition: &change, + ChangeType: &changeType, + IncludeWatching: &watching, + LockUnspents: &lockUnspents, + FeeRate: &feeRate, + SubtractFeeFromOutputs: []int{0}, + Replaceable: &replaceable, + ConfTarget: &confTarget, + EstimateMode: &btcjson.EstimateModeEconomical, + }, + IsWitness: nil, + } + }(), + }, + { + name: "fundrawtransaction - iswitness", + newCmd: func() (i interface{}, e error) { + return btcjson.NewCmd("fundrawtransaction", "deadbeef", "{}", true) + }, + staticCmd: func() interface{} { + deadbeef, err := hex.DecodeString("deadbeef") + if err != nil { + panic(err) + } + t := true + return btcjson.NewFundRawTransactionCmd(deadbeef, btcjson.FundRawTransactionOpts{}, &t) + }, + marshalled: `{"jsonrpc":"1.0","method":"fundrawtransaction","params":["deadbeef",{},true],"id":1}`, + unmarshalled: &btcjson.FundRawTransactionCmd{ + HexTx: "deadbeef", + Options: btcjson.FundRawTransactionOpts{}, + IsWitness: func() *bool { + t := true + return &t + }(), + }, + }, { name: "decoderawtransaction", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 0c4e66bb99..a96319b235 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -4,7 +4,14 @@ package btcjson -import "encoding/json" +import ( + "bytes" + "encoding/hex" + "encoding/json" + + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" +) // GetBlockHeaderVerboseResult models the data from the getblockheader command when // the verbose flag is set. When the verbose flag is not set, getblockheader @@ -676,3 +683,50 @@ type EstimateSmartFeeResult struct { Errors []string `json:"errors,omitempty"` Blocks int64 `json:"blocks"` } + +var _ json.Unmarshaler = &FundRawTransactionResult{} + +type rawFundRawTransactionResult struct { + Transaction string `json:"hex"` + Fee float64 `json:"fee"` + ChangePosition int `json:"changepos"` +} + +// FundRawTransactionResult is the result of the fundrawtransaction JSON-RPC call +type FundRawTransactionResult struct { + Transaction *wire.MsgTx + Fee btcutil.Amount + ChangePosition int // the position of the added change output, or -1 +} + +// UnmarshalJSON unmarshals the result of the fundrawtransaction JSON-RPC call +func (f *FundRawTransactionResult) UnmarshalJSON(data []byte) error { + var rawRes rawFundRawTransactionResult + if err := json.Unmarshal(data, &rawRes); err != nil { + return err + } + + txBytes, err := hex.DecodeString(rawRes.Transaction) + if err != nil { + return err + } + + var msgTx wire.MsgTx + witnessErr := msgTx.Deserialize(bytes.NewReader(txBytes)) + if witnessErr != nil { + legacyErr := msgTx.DeserializeNoWitness(bytes.NewReader(txBytes)) + if legacyErr != nil { + return legacyErr + } + } + + fee, err := btcutil.NewAmount(rawRes.Fee) + if err != nil { + return err + } + + f.Transaction = &msgTx + f.Fee = fee + f.ChangePosition = rawRes.ChangePosition + return nil +} diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 63a086642a..4e8d4e4d9c 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -205,6 +205,47 @@ func (c *Client) DecodeRawTransaction(serializedTx []byte) (*btcjson.TxRawResult return c.DecodeRawTransactionAsync(serializedTx).Receive() } +// FutureFundRawTransactionResult is a future promise to deliver the result +// of a FutureFundRawTransactionAsync RPC invocation (or an applicable error). +type FutureFundRawTransactionResult chan *response + +// Receive waits for the response promised by the future and returns information +// about a funding attempt +func (r FutureFundRawTransactionResult) Receive() (*btcjson.FundRawTransactionResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var marshalled btcjson.FundRawTransactionResult + if err := json.Unmarshal(res, &marshalled); err != nil { + return nil, err + } + + return &marshalled, nil +} + +// FundRawTransactionAsync returns an instance of a type that can be used to +// get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See FundRawTransaction for the blocking version and more details. +func (c *Client) FundRawTransactionAsync(tx *wire.MsgTx, opts btcjson.FundRawTransactionOpts, isWitness *bool) FutureFundRawTransactionResult { + var txBuf bytes.Buffer + if err := tx.Serialize(&txBuf); err != nil { + return newFutureError(err) + } + + cmd := btcjson.NewFundRawTransactionCmd(txBuf.Bytes(), opts, isWitness) + return c.sendCmd(cmd) +} + +// FundRawTransaction returns the result of trying to fund the given transaction with +// funds from the node wallet +func (c *Client) FundRawTransaction(tx *wire.MsgTx, opts btcjson.FundRawTransactionOpts, isWitness *bool) (*btcjson.FundRawTransactionResult, error) { + return c.FundRawTransactionAsync(tx, opts, isWitness).Receive() +} + // FutureCreateRawTransactionResult is a future promise to deliver the result // of a CreateRawTransactionAsync RPC invocation (or an applicable error). type FutureCreateRawTransactionResult chan *response From 7b2ff5d180ed9557342d8f8534d9b72a6664573b Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Wed, 17 Jun 2020 23:29:50 -0300 Subject: [PATCH 0359/1056] Add getbalances RPC client command --- btcjson/walletsvrcmds.go | 10 ++++++++++ btcjson/walletsvrcmds_test.go | 11 +++++++++++ btcjson/walletsvrresults.go | 14 +++++++++++++ rpcclient/wallet.go | 37 +++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 53bb93da14..be1a67fbf0 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -188,6 +188,15 @@ func NewGetBalanceCmd(account *string, minConf *int) *GetBalanceCmd { } } +// GetBalancesCmd defines the getbalances JSON-RPC command. +type GetBalancesCmd struct{} + +// NewGetBalancesCmd returns a new instance which can be used to issue a +// getbalances JSON-RPC command. +func NewGetBalancesCmd() *GetBalancesCmd { + return &GetBalancesCmd{} +} + // GetNewAddressCmd defines the getnewaddress JSON-RPC command. type GetNewAddressCmd struct { Account *string @@ -693,6 +702,7 @@ func init() { MustRegisterCmd("getaccountaddress", (*GetAccountAddressCmd)(nil), flags) MustRegisterCmd("getaddressesbyaccount", (*GetAddressesByAccountCmd)(nil), flags) MustRegisterCmd("getbalance", (*GetBalanceCmd)(nil), flags) + MustRegisterCmd("getbalances", (*GetBalancesCmd)(nil), flags) MustRegisterCmd("getnewaddress", (*GetNewAddressCmd)(nil), flags) MustRegisterCmd("getrawchangeaddress", (*GetRawChangeAddressCmd)(nil), flags) MustRegisterCmd("getreceivedbyaccount", (*GetReceivedByAccountCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 2e0f1d0f8e..554a87413a 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -250,6 +250,17 @@ func TestWalletSvrCmds(t *testing.T) { MinConf: btcjson.Int(6), }, }, + { + name: "getbalances", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getbalances") + }, + staticCmd: func() interface{} { + return btcjson.NewGetBalancesCmd() + }, + marshalled: `{"jsonrpc":"1.0","method":"getbalances","params":[],"id":1}`, + unmarshalled: &btcjson.GetBalancesCmd{}, + }, { name: "getnewaddress", newCmd: func() (interface{}, error) { diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index 9246d131ae..6e69ed9066 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -159,3 +159,17 @@ type GetBestBlockResult struct { Hash string `json:"hash"` Height int32 `json:"height"` } + +// BalanceDetailsResult models the details data from the `getbalances` command. +type BalanceDetailsResult struct { + Trusted float64 `json:"trusted"` + UntrustedPending float64 `json:"untrusted_pending"` + Immature float64 `json:"immature"` + Used *float64 `json:"used"` +} + +// GetBalancesResult models the data returned from the getbalances command. +type GetBalancesResult struct { + Mine BalanceDetailsResult `json:"mine"` + WatchOnly *BalanceDetailsResult `json:"watchonly"` +} diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index d43be26181..e92d1aab28 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -1547,6 +1547,43 @@ func (c *Client) GetBalanceMinConf(account string, minConfirms int) (btcutil.Amo return c.GetBalanceMinConfAsync(account, minConfirms).Receive() } +// FutureGetBalancesResult is a future promise to deliver the result of a +// GetBalancesAsync RPC invocation (or an applicable error). +type FutureGetBalancesResult chan *response + +// Receive waits for the response promised by the future and returns the +// available balances from the server. +func (r FutureGetBalancesResult) Receive() (*btcjson.GetBalancesResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a floating point number. + var balances btcjson.GetBalancesResult + err = json.Unmarshal(res, &balances) + if err != nil { + return nil, err + } + + return &balances, nil +} + +// GetBalancesAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetBalances for the blocking version and more details. +func (c *Client) GetBalancesAsync() FutureGetBalancesResult { + cmd := btcjson.NewGetBalancesCmd() + return c.sendCmd(cmd) +} + +// GetBalances returns the available balances from the server. +func (c *Client) GetBalances() (*btcjson.GetBalancesResult, error) { + return c.GetBalancesAsync().Receive() +} + // FutureGetReceivedByAccountResult is a future promise to deliver the result of // a GetReceivedByAccountAsync or GetReceivedByAccountMinConfAsync RPC // invocation (or an applicable error). From e2d9cf4b55083056a458a86289d9a0651a00a02b Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Wed, 10 Jun 2020 10:57:12 +0530 Subject: [PATCH 0360/1056] rpcclient: Add GetTransactionWatchOnly method --- rpcclient/wallet.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index e92d1aab28..37bf9471e0 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -20,7 +20,8 @@ import ( // ***************************** // FutureGetTransactionResult is a future promise to deliver the result -// of a GetTransactionAsync RPC invocation (or an applicable error). +// of a GetTransactionAsync or GetTransactionWatchOnlyAsync RPC invocation +// (or an applicable error). type FutureGetTransactionResult chan *response // Receive waits for the response promised by the future and returns detailed @@ -63,6 +64,28 @@ func (c *Client) GetTransaction(txHash *chainhash.Hash) (*btcjson.GetTransaction return c.GetTransactionAsync(txHash).Receive() } +// GetTransactionWatchOnlyAsync returns an instance of a type that can be used +// to get the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetTransactionWatchOnly for the blocking version and more details. +func (c *Client) GetTransactionWatchOnlyAsync(txHash *chainhash.Hash, watchOnly bool) FutureGetTransactionResult { + hash := "" + if txHash != nil { + hash = txHash.String() + } + + cmd := btcjson.NewGetTransactionCmd(hash, &watchOnly) + return c.sendCmd(cmd) +} + +// GetTransactionWatchOnly returns detailed information about a wallet +// transaction, and allow including watch-only addresses in balance +// calculation and details. +func (c *Client) GetTransactionWatchOnly(txHash *chainhash.Hash, watchOnly bool) (*btcjson.GetTransactionResult, error) { + return c.GetTransactionWatchOnlyAsync(txHash, watchOnly).Receive() +} + // FutureListTransactionsResult is a future promise to deliver the result of a // ListTransactionsAsync, ListTransactionsCountAsync, or // ListTransactionsCountFromAsync RPC invocation (or an applicable error). From 875b51c9fb83e5521ef5b4f8c9c522126baa2041 Mon Sep 17 00:00:00 2001 From: Javed Khan Date: Fri, 3 Jul 2020 17:40:32 +0530 Subject: [PATCH 0361/1056] peer: knownInventory, sentNonces - use generic lru While here, also rename and generalize limitMap and apply to other maps which need to be bounded. --- go.mod | 1 + go.sum | 2 + netsync/manager.go | 50 ++++++------ peer/mruinvmap.go | 127 ----------------------------- peer/mruinvmap_test.go | 170 --------------------------------------- peer/mrunoncemap.go | 125 ---------------------------- peer/mrunoncemap_test.go | 152 ---------------------------------- peer/peer.go | 13 +-- 8 files changed, 34 insertions(+), 606 deletions(-) delete mode 100644 peer/mruinvmap.go delete mode 100644 peer/mruinvmap_test.go delete mode 100644 peer/mrunoncemap.go delete mode 100644 peer/mrunoncemap_test.go diff --git a/go.mod b/go.mod index 15c261cef5..80a3d7658f 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 github.com/btcsuite/winsvc v1.0.0 github.com/davecgh/go-spew v1.1.1 + github.com/decred/dcrd/lru v1.0.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 diff --git a/go.sum b/go.sum index 1ead212fc8..392d70f1b7 100644 --- a/go.sum +++ b/go.sum @@ -24,6 +24,8 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= diff --git a/netsync/manager.go b/netsync/manager.go index 32715b8e1e..51c2cbe4a8 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -147,6 +147,25 @@ type peerSyncState struct { requestedBlocks map[chainhash.Hash]struct{} } +// limitAdd is a helper function for maps that require a maximum limit by +// evicting a random value if adding the new value would cause it to +// overflow the maximum allowed. +func limitAdd(m map[chainhash.Hash]struct{}, hash chainhash.Hash, limit int) { + if len(m)+1 > limit { + // Remove a random entry from the map. For most compilers, Go's + // range statement iterates starting at a random item although + // that is not 100% guaranteed by the spec. The iteration order + // is not important here because an adversary would have to be + // able to pull off preimage attacks on the hashing function in + // order to target eviction of specific entries anyways. + for txHash := range m { + delete(m, txHash) + break + } + } + m[hash] = struct{}{} +} + // SyncManager is used to communicate block related messages with peers. The // SyncManager is started as by executing Start() in a goroutine. Once started, // it selects peers to sync from and starts the initial block download. Once the @@ -579,8 +598,7 @@ func (sm *SyncManager) handleTxMsg(tmsg *txMsg) { if err != nil { // Do not request this transaction again until a new block // has been processed. - sm.rejectedTxns[*txHash] = struct{}{} - sm.limitMap(sm.rejectedTxns, maxRejectedTxns) + limitAdd(sm.rejectedTxns, *txHash, maxRejectedTxns) // When the error is a rule error, it means the transaction was // simply rejected as opposed to something actually going wrong, @@ -1202,9 +1220,8 @@ func (sm *SyncManager) handleInvMsg(imsg *invMsg) { // Request the block if there is not already a pending // request. if _, exists := sm.requestedBlocks[iv.Hash]; !exists { - sm.requestedBlocks[iv.Hash] = struct{}{} - sm.limitMap(sm.requestedBlocks, maxRequestedBlocks) - state.requestedBlocks[iv.Hash] = struct{}{} + limitAdd(sm.requestedBlocks, iv.Hash, maxRequestedBlocks) + limitAdd(state.requestedBlocks, iv.Hash, maxRequestedBlocks) if peer.IsWitnessEnabled() { iv.Type = wire.InvTypeWitnessBlock @@ -1220,9 +1237,8 @@ func (sm *SyncManager) handleInvMsg(imsg *invMsg) { // Request the transaction if there is not already a // pending request. if _, exists := sm.requestedTxns[iv.Hash]; !exists { - sm.requestedTxns[iv.Hash] = struct{}{} - sm.limitMap(sm.requestedTxns, maxRequestedTxns) - state.requestedTxns[iv.Hash] = struct{}{} + limitAdd(sm.requestedTxns, iv.Hash, maxRequestedTxns) + limitAdd(state.requestedTxns, iv.Hash, maxRequestedTxns) // If the peer is capable, request the txn // including all witness data. @@ -1245,24 +1261,6 @@ func (sm *SyncManager) handleInvMsg(imsg *invMsg) { } } -// limitMap is a helper function for maps that require a maximum limit by -// evicting a random transaction if adding a new value would cause it to -// overflow the maximum allowed. -func (sm *SyncManager) limitMap(m map[chainhash.Hash]struct{}, limit int) { - if len(m)+1 > limit { - // Remove a random entry from the map. For most compilers, Go's - // range statement iterates starting at a random item although - // that is not 100% guaranteed by the spec. The iteration order - // is not important here because an adversary would have to be - // able to pull off preimage attacks on the hashing function in - // order to target eviction of specific entries anyways. - for txHash := range m { - delete(m, txHash) - return - } - } -} - // blockHandler is the main handler for the sync manager. It must be run as a // goroutine. It processes block and inv messages in a separate goroutine // from the peer handlers so the block (MsgBlock) messages are handled by a diff --git a/peer/mruinvmap.go b/peer/mruinvmap.go deleted file mode 100644 index 0bf1b2b34a..0000000000 --- a/peer/mruinvmap.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2013-2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package peer - -import ( - "bytes" - "container/list" - "fmt" - "sync" - - "github.com/btcsuite/btcd/wire" -) - -// mruInventoryMap provides a concurrency safe map that is limited to a maximum -// number of items with eviction for the oldest entry when the limit is -// exceeded. -type mruInventoryMap struct { - invMtx sync.Mutex - invMap map[wire.InvVect]*list.Element // nearly O(1) lookups - invList *list.List // O(1) insert, update, delete - limit uint -} - -// String returns the map as a human-readable string. -// -// This function is safe for concurrent access. -func (m *mruInventoryMap) String() string { - m.invMtx.Lock() - defer m.invMtx.Unlock() - - lastEntryNum := len(m.invMap) - 1 - curEntry := 0 - buf := bytes.NewBufferString("[") - for iv := range m.invMap { - buf.WriteString(fmt.Sprintf("%v", iv)) - if curEntry < lastEntryNum { - buf.WriteString(", ") - } - curEntry++ - } - buf.WriteString("]") - - return fmt.Sprintf("<%d>%s", m.limit, buf.String()) -} - -// Exists returns whether or not the passed inventory item is in the map. -// -// This function is safe for concurrent access. -func (m *mruInventoryMap) Exists(iv *wire.InvVect) bool { - m.invMtx.Lock() - _, exists := m.invMap[*iv] - m.invMtx.Unlock() - - return exists -} - -// Add adds the passed inventory to the map and handles eviction of the oldest -// item if adding the new item would exceed the max limit. Adding an existing -// item makes it the most recently used item. -// -// This function is safe for concurrent access. -func (m *mruInventoryMap) Add(iv *wire.InvVect) { - m.invMtx.Lock() - defer m.invMtx.Unlock() - - // When the limit is zero, nothing can be added to the map, so just - // return. - if m.limit == 0 { - return - } - - // When the entry already exists move it to the front of the list - // thereby marking it most recently used. - if node, exists := m.invMap[*iv]; exists { - m.invList.MoveToFront(node) - return - } - - // Evict the least recently used entry (back of the list) if the the new - // entry would exceed the size limit for the map. Also reuse the list - // node so a new one doesn't have to be allocated. - if uint(len(m.invMap))+1 > m.limit { - node := m.invList.Back() - lru := node.Value.(*wire.InvVect) - - // Evict least recently used item. - delete(m.invMap, *lru) - - // Reuse the list node of the item that was just evicted for the - // new item. - node.Value = iv - m.invList.MoveToFront(node) - m.invMap[*iv] = node - return - } - - // The limit hasn't been reached yet, so just add the new item. - node := m.invList.PushFront(iv) - m.invMap[*iv] = node -} - -// Delete deletes the passed inventory item from the map (if it exists). -// -// This function is safe for concurrent access. -func (m *mruInventoryMap) Delete(iv *wire.InvVect) { - m.invMtx.Lock() - if node, exists := m.invMap[*iv]; exists { - m.invList.Remove(node) - delete(m.invMap, *iv) - } - m.invMtx.Unlock() -} - -// newMruInventoryMap returns a new inventory map that is limited to the number -// of entries specified by limit. When the number of entries exceeds the limit, -// the oldest (least recently used) entry will be removed to make room for the -// new entry. -func newMruInventoryMap(limit uint) *mruInventoryMap { - m := mruInventoryMap{ - invMap: make(map[wire.InvVect]*list.Element), - invList: list.New(), - limit: limit, - } - return &m -} diff --git a/peer/mruinvmap_test.go b/peer/mruinvmap_test.go deleted file mode 100644 index e55746010b..0000000000 --- a/peer/mruinvmap_test.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2013-2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package peer - -import ( - "crypto/rand" - "fmt" - "testing" - - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" -) - -// TestMruInventoryMap ensures the MruInventoryMap behaves as expected including -// limiting, eviction of least-recently used entries, specific entry removal, -// and existence tests. -func TestMruInventoryMap(t *testing.T) { - // Create a bunch of fake inventory vectors to use in testing the mru - // inventory code. - numInvVects := 10 - invVects := make([]*wire.InvVect, 0, numInvVects) - for i := 0; i < numInvVects; i++ { - hash := &chainhash.Hash{byte(i)} - iv := wire.NewInvVect(wire.InvTypeBlock, hash) - invVects = append(invVects, iv) - } - - tests := []struct { - name string - limit int - }{ - {name: "limit 0", limit: 0}, - {name: "limit 1", limit: 1}, - {name: "limit 5", limit: 5}, - {name: "limit 7", limit: 7}, - {name: "limit one less than available", limit: numInvVects - 1}, - {name: "limit all available", limit: numInvVects}, - } - -testLoop: - for i, test := range tests { - // Create a new mru inventory map limited by the specified test - // limit and add all of the test inventory vectors. This will - // cause evicition since there are more test inventory vectors - // than the limits. - mruInvMap := newMruInventoryMap(uint(test.limit)) - for j := 0; j < numInvVects; j++ { - mruInvMap.Add(invVects[j]) - } - - // Ensure the limited number of most recent entries in the - // inventory vector list exist. - for j := numInvVects - test.limit; j < numInvVects; j++ { - if !mruInvMap.Exists(invVects[j]) { - t.Errorf("Exists #%d (%s) entry %s does not "+ - "exist", i, test.name, *invVects[j]) - continue testLoop - } - } - - // Ensure the entries before the limited number of most recent - // entries in the inventory vector list do not exist. - for j := 0; j < numInvVects-test.limit; j++ { - if mruInvMap.Exists(invVects[j]) { - t.Errorf("Exists #%d (%s) entry %s exists", i, - test.name, *invVects[j]) - continue testLoop - } - } - - // Readd the entry that should currently be the least-recently - // used entry so it becomes the most-recently used entry, then - // force an eviction by adding an entry that doesn't exist and - // ensure the evicted entry is the new least-recently used - // entry. - // - // This check needs at least 2 entries. - if test.limit > 1 { - origLruIndex := numInvVects - test.limit - mruInvMap.Add(invVects[origLruIndex]) - - iv := wire.NewInvVect(wire.InvTypeBlock, - &chainhash.Hash{0x00, 0x01}) - mruInvMap.Add(iv) - - // Ensure the original lru entry still exists since it - // was updated and should've have become the mru entry. - if !mruInvMap.Exists(invVects[origLruIndex]) { - t.Errorf("MRU #%d (%s) entry %s does not exist", - i, test.name, *invVects[origLruIndex]) - continue testLoop - } - - // Ensure the entry that should've become the new lru - // entry was evicted. - newLruIndex := origLruIndex + 1 - if mruInvMap.Exists(invVects[newLruIndex]) { - t.Errorf("MRU #%d (%s) entry %s exists", i, - test.name, *invVects[newLruIndex]) - continue testLoop - } - } - - // Delete all of the entries in the inventory vector list, - // including those that don't exist in the map, and ensure they - // no longer exist. - for j := 0; j < numInvVects; j++ { - mruInvMap.Delete(invVects[j]) - if mruInvMap.Exists(invVects[j]) { - t.Errorf("Delete #%d (%s) entry %s exists", i, - test.name, *invVects[j]) - continue testLoop - } - } - } -} - -// TestMruInventoryMapStringer tests the stringized output for the -// MruInventoryMap type. -func TestMruInventoryMapStringer(t *testing.T) { - // Create a couple of fake inventory vectors to use in testing the mru - // inventory stringer code. - hash1 := &chainhash.Hash{0x01} - hash2 := &chainhash.Hash{0x02} - iv1 := wire.NewInvVect(wire.InvTypeBlock, hash1) - iv2 := wire.NewInvVect(wire.InvTypeBlock, hash2) - - // Create new mru inventory map and add the inventory vectors. - mruInvMap := newMruInventoryMap(uint(2)) - mruInvMap.Add(iv1) - mruInvMap.Add(iv2) - - // Ensure the stringer gives the expected result. Since map iteration - // is not ordered, either entry could be first, so account for both - // cases. - wantStr1 := fmt.Sprintf("<%d>[%s, %s]", 2, *iv1, *iv2) - wantStr2 := fmt.Sprintf("<%d>[%s, %s]", 2, *iv2, *iv1) - gotStr := mruInvMap.String() - if gotStr != wantStr1 && gotStr != wantStr2 { - t.Fatalf("unexpected string representation - got %q, want %q "+ - "or %q", gotStr, wantStr1, wantStr2) - } -} - -// BenchmarkMruInventoryList performs basic benchmarks on the most recently -// used inventory handling. -func BenchmarkMruInventoryList(b *testing.B) { - // Create a bunch of fake inventory vectors to use in benchmarking - // the mru inventory code. - b.StopTimer() - numInvVects := 100000 - invVects := make([]*wire.InvVect, 0, numInvVects) - for i := 0; i < numInvVects; i++ { - hashBytes := make([]byte, chainhash.HashSize) - rand.Read(hashBytes) - hash, _ := chainhash.NewHash(hashBytes) - iv := wire.NewInvVect(wire.InvTypeBlock, hash) - invVects = append(invVects, iv) - } - b.StartTimer() - - // Benchmark the add plus evicition code. - limit := 20000 - mruInvMap := newMruInventoryMap(uint(limit)) - for i := 0; i < b.N; i++ { - mruInvMap.Add(invVects[i%numInvVects]) - } -} diff --git a/peer/mrunoncemap.go b/peer/mrunoncemap.go deleted file mode 100644 index 5f7c798429..0000000000 --- a/peer/mrunoncemap.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package peer - -import ( - "bytes" - "container/list" - "fmt" - "sync" -) - -// mruNonceMap provides a concurrency safe map that is limited to a maximum -// number of items with eviction for the oldest entry when the limit is -// exceeded. -type mruNonceMap struct { - mtx sync.Mutex - nonceMap map[uint64]*list.Element // nearly O(1) lookups - nonceList *list.List // O(1) insert, update, delete - limit uint -} - -// String returns the map as a human-readable string. -// -// This function is safe for concurrent access. -func (m *mruNonceMap) String() string { - m.mtx.Lock() - defer m.mtx.Unlock() - - lastEntryNum := len(m.nonceMap) - 1 - curEntry := 0 - buf := bytes.NewBufferString("[") - for nonce := range m.nonceMap { - buf.WriteString(fmt.Sprintf("%d", nonce)) - if curEntry < lastEntryNum { - buf.WriteString(", ") - } - curEntry++ - } - buf.WriteString("]") - - return fmt.Sprintf("<%d>%s", m.limit, buf.String()) -} - -// Exists returns whether or not the passed nonce is in the map. -// -// This function is safe for concurrent access. -func (m *mruNonceMap) Exists(nonce uint64) bool { - m.mtx.Lock() - _, exists := m.nonceMap[nonce] - m.mtx.Unlock() - - return exists -} - -// Add adds the passed nonce to the map and handles eviction of the oldest item -// if adding the new item would exceed the max limit. Adding an existing item -// makes it the most recently used item. -// -// This function is safe for concurrent access. -func (m *mruNonceMap) Add(nonce uint64) { - m.mtx.Lock() - defer m.mtx.Unlock() - - // When the limit is zero, nothing can be added to the map, so just - // return. - if m.limit == 0 { - return - } - - // When the entry already exists move it to the front of the list - // thereby marking it most recently used. - if node, exists := m.nonceMap[nonce]; exists { - m.nonceList.MoveToFront(node) - return - } - - // Evict the least recently used entry (back of the list) if the the new - // entry would exceed the size limit for the map. Also reuse the list - // node so a new one doesn't have to be allocated. - if uint(len(m.nonceMap))+1 > m.limit { - node := m.nonceList.Back() - lru := node.Value.(uint64) - - // Evict least recently used item. - delete(m.nonceMap, lru) - - // Reuse the list node of the item that was just evicted for the - // new item. - node.Value = nonce - m.nonceList.MoveToFront(node) - m.nonceMap[nonce] = node - return - } - - // The limit hasn't been reached yet, so just add the new item. - node := m.nonceList.PushFront(nonce) - m.nonceMap[nonce] = node -} - -// Delete deletes the passed nonce from the map (if it exists). -// -// This function is safe for concurrent access. -func (m *mruNonceMap) Delete(nonce uint64) { - m.mtx.Lock() - if node, exists := m.nonceMap[nonce]; exists { - m.nonceList.Remove(node) - delete(m.nonceMap, nonce) - } - m.mtx.Unlock() -} - -// newMruNonceMap returns a new nonce map that is limited to the number of -// entries specified by limit. When the number of entries exceeds the limit, -// the oldest (least recently used) entry will be removed to make room for the -// new entry. -func newMruNonceMap(limit uint) *mruNonceMap { - m := mruNonceMap{ - nonceMap: make(map[uint64]*list.Element), - nonceList: list.New(), - limit: limit, - } - return &m -} diff --git a/peer/mrunoncemap_test.go b/peer/mrunoncemap_test.go deleted file mode 100644 index bd7fb1082e..0000000000 --- a/peer/mrunoncemap_test.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package peer - -import ( - "fmt" - "testing" -) - -// TestMruNonceMap ensures the mruNonceMap behaves as expected including -// limiting, eviction of least-recently used entries, specific entry removal, -// and existence tests. -func TestMruNonceMap(t *testing.T) { - // Create a bunch of fake nonces to use in testing the mru nonce code. - numNonces := 10 - nonces := make([]uint64, 0, numNonces) - for i := 0; i < numNonces; i++ { - nonces = append(nonces, uint64(i)) - } - - tests := []struct { - name string - limit int - }{ - {name: "limit 0", limit: 0}, - {name: "limit 1", limit: 1}, - {name: "limit 5", limit: 5}, - {name: "limit 7", limit: 7}, - {name: "limit one less than available", limit: numNonces - 1}, - {name: "limit all available", limit: numNonces}, - } - -testLoop: - for i, test := range tests { - // Create a new mru nonce map limited by the specified test - // limit and add all of the test nonces. This will cause - // evicition since there are more test nonces than the limits. - mruNonceMap := newMruNonceMap(uint(test.limit)) - for j := 0; j < numNonces; j++ { - mruNonceMap.Add(nonces[j]) - } - - // Ensure the limited number of most recent entries in the list - // exist. - for j := numNonces - test.limit; j < numNonces; j++ { - if !mruNonceMap.Exists(nonces[j]) { - t.Errorf("Exists #%d (%s) entry %d does not "+ - "exist", i, test.name, nonces[j]) - continue testLoop - } - } - - // Ensure the entries before the limited number of most recent - // entries in the list do not exist. - for j := 0; j < numNonces-test.limit; j++ { - if mruNonceMap.Exists(nonces[j]) { - t.Errorf("Exists #%d (%s) entry %d exists", i, - test.name, nonces[j]) - continue testLoop - } - } - - // Readd the entry that should currently be the least-recently - // used entry so it becomes the most-recently used entry, then - // force an eviction by adding an entry that doesn't exist and - // ensure the evicted entry is the new least-recently used - // entry. - // - // This check needs at least 2 entries. - if test.limit > 1 { - origLruIndex := numNonces - test.limit - mruNonceMap.Add(nonces[origLruIndex]) - - mruNonceMap.Add(uint64(numNonces) + 1) - - // Ensure the original lru entry still exists since it - // was updated and should've have become the mru entry. - if !mruNonceMap.Exists(nonces[origLruIndex]) { - t.Errorf("MRU #%d (%s) entry %d does not exist", - i, test.name, nonces[origLruIndex]) - continue testLoop - } - - // Ensure the entry that should've become the new lru - // entry was evicted. - newLruIndex := origLruIndex + 1 - if mruNonceMap.Exists(nonces[newLruIndex]) { - t.Errorf("MRU #%d (%s) entry %d exists", i, - test.name, nonces[newLruIndex]) - continue testLoop - } - } - - // Delete all of the entries in the list, including those that - // don't exist in the map, and ensure they no longer exist. - for j := 0; j < numNonces; j++ { - mruNonceMap.Delete(nonces[j]) - if mruNonceMap.Exists(nonces[j]) { - t.Errorf("Delete #%d (%s) entry %d exists", i, - test.name, nonces[j]) - continue testLoop - } - } - } -} - -// TestMruNonceMapStringer tests the stringized output for the mruNonceMap type. -func TestMruNonceMapStringer(t *testing.T) { - // Create a couple of fake nonces to use in testing the mru nonce - // stringer code. - nonce1 := uint64(10) - nonce2 := uint64(20) - - // Create new mru nonce map and add the nonces. - mruNonceMap := newMruNonceMap(uint(2)) - mruNonceMap.Add(nonce1) - mruNonceMap.Add(nonce2) - - // Ensure the stringer gives the expected result. Since map iteration - // is not ordered, either entry could be first, so account for both - // cases. - wantStr1 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce1, nonce2) - wantStr2 := fmt.Sprintf("<%d>[%d, %d]", 2, nonce2, nonce1) - gotStr := mruNonceMap.String() - if gotStr != wantStr1 && gotStr != wantStr2 { - t.Fatalf("unexpected string representation - got %q, want %q "+ - "or %q", gotStr, wantStr1, wantStr2) - } -} - -// BenchmarkMruNonceList performs basic benchmarks on the most recently used -// nonce handling. -func BenchmarkMruNonceList(b *testing.B) { - // Create a bunch of fake nonces to use in benchmarking the mru nonce - // code. - b.StopTimer() - numNonces := 100000 - nonces := make([]uint64, 0, numNonces) - for i := 0; i < numNonces; i++ { - nonces = append(nonces, uint64(i)) - } - b.StartTimer() - - // Benchmark the add plus evicition code. - limit := 20000 - mruNonceMap := newMruNonceMap(uint(limit)) - for i := 0; i < b.N; i++ { - mruNonceMap.Add(nonces[i%numNonces]) - } -} diff --git a/peer/peer.go b/peer/peer.go index 200acb32af..82010f3b84 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -24,6 +24,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/go-socks/socks" "github.com/davecgh/go-spew/spew" + "github.com/decred/dcrd/lru" ) const ( @@ -82,7 +83,7 @@ var ( // sentNonces houses the unique nonces that are generated when pushing // version messages that are used to detect self connections. - sentNonces = newMruNonceMap(50) + sentNonces = lru.NewCache(50) // allowSelfConns is only used to allow the tests to bypass the self // connection detecting and disconnect logic since they intentionally @@ -450,7 +451,7 @@ type Peer struct { wireEncoding wire.MessageEncoding - knownInventory *mruInventoryMap + knownInventory lru.Cache prevGetBlocksMtx sync.Mutex prevGetBlocksBegin *chainhash.Hash prevGetBlocksStop *chainhash.Hash @@ -1626,7 +1627,7 @@ out: // Don't send inventory that became known after // the initial check. - if p.knownInventory.Exists(iv) { + if p.knownInventory.Contains(iv) { continue } @@ -1832,7 +1833,7 @@ func (p *Peer) QueueMessageWithEncoding(msg wire.Message, doneChan chan<- struct func (p *Peer) QueueInventory(invVect *wire.InvVect) { // Don't add the inventory to the send queue if the peer is already // known to have it. - if p.knownInventory.Exists(invVect) { + if p.knownInventory.Contains(invVect) { return } @@ -1891,7 +1892,7 @@ func (p *Peer) readRemoteVersionMsg() error { } // Detect self connections. - if !allowSelfConns && sentNonces.Exists(msg.Nonce) { + if !allowSelfConns && sentNonces.Contains(msg.Nonce) { return errors.New("disconnecting peer connected to self") } @@ -2224,7 +2225,7 @@ func newPeerBase(origCfg *Config, inbound bool) *Peer { p := Peer{ inbound: inbound, wireEncoding: wire.BaseEncoding, - knownInventory: newMruInventoryMap(maxKnownInventory), + knownInventory: lru.NewCache(maxKnownInventory), stallControl: make(chan stallControlMsg, 1), // nonblocking sync outputQueue: make(chan outMsg, outputBufferSize), sendQueue: make(chan outMsg, 1), // nonblocking sync From d28c7167a50d9224a53cae962f14ffa705554013 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Fri, 10 Jul 2020 01:35:17 +0530 Subject: [PATCH 0362/1056] btcec: Avoid panic in fieldVal.SetByteSlice for large inputs The implementation has been adapted from the dcrec module in dcrd. The bug was initially fixed in decred/dcrd@3d9cda1 while transitioning to a constant time algorithm. A large set of test vectors were subsequently added in decred/dcrd@8c6b52d. The function signature has been preserved for backwards compatibility. This means that returning whether the value has overflowed, and the corresponding test vectors have not been backported. This fixes #1170 and closes a previous attempt to fix the bug in #1178. --- btcec/field.go | 20 +++--- btcec/field_test.go | 154 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 8 deletions(-) diff --git a/btcec/field.go b/btcec/field.go index c2bb84b3fe..98105ed8e4 100644 --- a/btcec/field.go +++ b/btcec/field.go @@ -226,20 +226,24 @@ func (f *fieldVal) SetBytes(b *[32]byte) *fieldVal { return f } -// SetByteSlice packs the passed big-endian value into the internal field value -// representation. Only the first 32-bytes are used. As a result, it is up to -// the caller to ensure numbers of the appropriate size are used or the value -// will be truncated. +// SetByteSlice interprets the provided slice as a 256-bit big-endian unsigned +// integer (meaning it is truncated to the first 32 bytes), packs it into the +// internal field value representation, and returns the updated field value. +// +// Note that since passing a slice with more than 32 bytes is truncated, it is +// possible that the truncated value is less than the field prime. It is up to +// the caller to decide whether it needs to provide numbers of the appropriate +// size or if it is acceptable to use this function with the described +// truncation behavior. // // The field value is returned to support chaining. This enables syntax like: // f := new(fieldVal).SetByteSlice(byteSlice) func (f *fieldVal) SetByteSlice(b []byte) *fieldVal { var b32 [32]byte - for i := 0; i < len(b); i++ { - if i < 32 { - b32[i+(32-len(b))] = b[i] - } + if len(b) > 32 { + b = b[:32] } + copy(b32[32-len(b):], b) return f.SetBytes(&b32) } diff --git a/btcec/field_test.go b/btcec/field_test.go index 27b9730f65..4226ba55f9 100644 --- a/btcec/field_test.go +++ b/btcec/field_test.go @@ -7,6 +7,7 @@ package btcec import ( "crypto/rand" + "encoding/hex" "fmt" "reflect" "testing" @@ -965,3 +966,156 @@ func testSqrt(t *testing.T, test sqrtTest) { } } } + +// TestFieldSetBytes ensures that setting a field value to a 256-bit big-endian +// unsigned integer via both the slice and array methods works as expected for +// edge cases. Random cases are tested via the various other tests. +func TestFieldSetBytes(t *testing.T) { + tests := []struct { + name string // test description + in string // hex encoded test value + expected [10]uint32 // expected raw ints + }{{ + name: "zero", + in: "00", + expected: [10]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }, { + name: "field prime", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, + 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, + }, + }, { + name: "field prime - 1", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + expected: [10]uint32{ + 0x03fffc2e, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, + 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, + }, + }, { + name: "field prime + 1 (overflow in word zero)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", + expected: [10]uint32{ + 0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, + 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, + }, + }, { + name: "field prime first 32 bits", + in: "fffffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x00000003f, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, { + name: "field prime word zero", + in: "03fffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, { + name: "field prime first 64 bits", + in: "fffffffefffffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x03ffffbf, 0x00000fff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, { + name: "field prime word zero and one", + in: "0ffffefffffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x03ffffbf, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, { + name: "field prime first 96 bits", + in: "fffffffffffffffefffffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x0003ffff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, { + name: "field prime word zero, one, and two", + in: "3ffffffffffefffffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + }, { + name: "overflow in word one (prime + 1<<26)", + in: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff03fffc2f", + expected: [10]uint32{ + 0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, + 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, + }, + }, { + name: "(field prime - 1) * 2 NOT mod P, truncated >32 bytes", + in: "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffff85c", + expected: [10]uint32{ + 0x01fffff8, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, + 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x00007fff, + }, + }, { + name: "2^256 - 1", + in: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + expected: [10]uint32{ + 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, + 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, + }, + }, { + name: "alternating bits", + in: "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5", + expected: [10]uint32{ + 0x01a5a5a5, 0x01696969, 0x025a5a5a, 0x02969696, 0x01a5a5a5, + 0x01696969, 0x025a5a5a, 0x02969696, 0x01a5a5a5, 0x00296969, + }, + }, { + name: "alternating bits 2", + in: "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a", + expected: [10]uint32{ + 0x025a5a5a, 0x02969696, 0x01a5a5a5, 0x01696969, 0x025a5a5a, + 0x02969696, 0x01a5a5a5, 0x01696969, 0x025a5a5a, 0x00169696, + }, + }} + + for _, test := range tests { + inBytes := hexToBytes(test.in) + + // Ensure setting the bytes via the slice method works as expected. + var f fieldVal + f.SetByteSlice(inBytes) + if !reflect.DeepEqual(f.n, test.expected) { + t.Errorf("%s: unexpected result\ngot: %x\nwant: %x", test.name, f.n, + test.expected) + continue + } + + // Ensure setting the bytes via the array method works as expected. + var f2 fieldVal + var b32 [32]byte + truncatedInBytes := inBytes + if len(truncatedInBytes) > 32 { + truncatedInBytes = truncatedInBytes[:32] + } + copy(b32[32-len(truncatedInBytes):], truncatedInBytes) + f2.SetBytes(&b32) + if !reflect.DeepEqual(f2.n, test.expected) { + t.Errorf("%s: unexpected result\ngot: %x\nwant: %x", test.name, + f2.n, test.expected) + continue + } + } +} + +// hexToBytes converts the passed hex string into bytes and will panic if there +// is an error. This is only provided for the hard-coded constants so errors in +// the source code can be detected. It will only (and must only) be called with +// hard-coded values. +func hexToBytes(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + return b +} From c7390232d31db328daf298246d8a15c7dc86c9d3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 22 Jul 2020 09:57:15 +0200 Subject: [PATCH 0363/1056] config+service_windows: add flag to disable win service To run integration tests with btcd on Windows in non-interactive environments (such as the Travis build with Windows machines), we need to make sure we can still spawn a child process instead of only a windows background service. --- config.go | 1 + service_windows.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/config.go b/config.go index 96756f7f97..c44f3a837f 100644 --- a/config.go +++ b/config.go @@ -132,6 +132,7 @@ type config struct { NoOnion bool `long:"noonion" description:"Disable connecting to tor hidden services"` NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"` NoRelayPriority bool `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"` + NoWinService bool `long:"nowinservice" description:"Do not start as a background service on Windows -- NOTE: This flag only works on the command line, not in the config file"` DisableRPC bool `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass or rpclimituser/rpclimitpass is specified"` DisableTLS bool `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"` OnionProxy string `long:"onion" description:"Connect to tor hidden services via SOCKS5 proxy (eg. 127.0.0.1:9050)"` diff --git a/service_windows.go b/service_windows.go index 8101ae6514..378c9204f8 100644 --- a/service_windows.go +++ b/service_windows.go @@ -275,6 +275,22 @@ func performServiceCommand(command string) error { // returned to the caller so the application can determine whether to exit (when // running as a service) or launch in normal interactive mode. func serviceMain() (bool, error) { + // Don't run as a service if the user explicitly requested it. This is + // needed to run btcd on Windows in CI environments like Travis. + // We can't use the config struct to access the value because that's not + // parsed yet. But we add the flag to the struct anyway so the parser + // won't complain about it later. + noService := false + for _, arg := range os.Args { + if arg == "--nowinservice" { + noService = true + break + } + } + if noService { + return false, nil + } + // Don't run as a service if we're running interactively (or that can't // be determined due to an error). isInteractive, err := svc.IsAnInteractiveSession() From 3c56a6bd3a26585e60683b09bafe1513ca1fea7c Mon Sep 17 00:00:00 2001 From: qqjettkgjzhxmwj <37233887+JettScythe@users.noreply.github.com> Date: Tue, 21 Jul 2020 16:54:22 -0300 Subject: [PATCH 0364/1056] updated docs for getblock-verbosity fixes --- docs/json_rpc_api.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index 4bb0625e89..c33bd7a396 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -271,13 +271,13 @@ the method name for further details such as parameter and return information. | | | |---|---| |Method|getblock| -|Parameters|1. block hash (string, required) - the hash of the block
2. verbose (boolean, optional, default=true) - specifies the block is returned as a JSON object instead of hex-encoded string
3. verbosetx (boolean, optional, default=false) - specifies that each transaction is returned as a JSON object and only applies if the `verbose` flag is true.**This parameter is a btcd extension**| +|Parameters|1. block hash (string, required) - the hash of the block
2. verbosity (int, optional, default=1) - specifies the block is returned as a JSON object instead of hex-encoded string**This parameter is a btcd extension**| |Description|Returns information about a block given its hash.| -|Returns (verbose=false)|`"data" (string) hex-encoded bytes of the serialized block`| -|Returns (verbose=true, verbosetx=false)|`{ (json object)`
  `"hash": "blockhash", (string) the hash of the block (same as provided)`
  `"confirmations": n, (numeric) the number of confirmations`
  `"strippedsize", n (numeric) the size of the block without witness data`
  `"size": n, (numeric) the size of the block`
  `"weight": n, (numeric) value of the weight metric`
  `"height": n, (numeric) the height of the block in the block chain`
  `"version": n, (numeric) the block version`
  `"merkleroot": "hash", (string) root hash of the merkle tree`
  `"tx": [ (json array of string) the transaction hashes`
    `"transactionhash", (string) hash of the parent transaction`
    `...`
  `]`
  `"time": n, (numeric) the block time in seconds since 1 Jan 1970 GMT`
  `"nonce": n, (numeric) the block nonce`
  `"bits", n, (numeric) the bits which represent the block difficulty`
  `difficulty: n.nn, (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty`
  `"previousblockhash": "hash", (string) the hash of the previous block`
  `"nextblockhash": "hash", (string) the hash of the next block (only if there is one)`
`}`| -|Returns (verbose=true, verbosetx=true)|`{ (json object)`
  `"hash": "blockhash", (string) the hash of the block (same as provided)`
  `"confirmations": n, (numeric) the number of confirmations`
  `"strippedsize", n (numeric) the size of the block without witness data`
  `"size": n, (numeric) the size of the block`
  `"weight": n, (numeric) value of the weight metric`
  `"height": n, (numeric) the height of the block in the block chain`
  `"version": n, (numeric) the block version`
  `"merkleroot": "hash", (string) root hash of the merkle tree`
  `"rawtx": [ (array of json objects) the transactions as json objects`
    `(see getrawtransaction json object details)`
  `]`
  `"time": n, (numeric) the block time in seconds since 1 Jan 1970 GMT`
  `"nonce": n, (numeric) the block nonce`
  `"bits", n, (numeric) the bits which represent the block difficulty`
  `difficulty: n.nn, (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty`
  `"previousblockhash": "hash", (string) the hash of the previous block`
  `"nextblockhash": "hash", (string) the hash of the next block`
`}`| -|Example Return (verbose=false)|`"010000000000000000000000000000000000000000000000000000000000000000000000`
`3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49`
`ffff001d1dac2b7c01010000000100000000000000000000000000000000000000000000`
`00000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f`
`4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f`
`6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104`
`678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f`
`4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"`
**Newlines added for display purposes. The actual return does not contain newlines.**| -|Example Return (verbose=true, verbosetx=false)|`{`
  `"hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",`
  `"confirmations": 277113,`
  `"size": 285,`
  `"height": 0,`
  `"version": 1,`
  `"merkleroot": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",`
  `"tx": [`
    `"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"`
  `],`
  `"time": 1231006505,`
  `"nonce": 2083236893,`
  `"bits": "1d00ffff",`
  `"difficulty": 1,`
  `"previousblockhash": "0000000000000000000000000000000000000000000000000000000000000000",`
  `"nextblockhash": "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048"`
`}`| +|Returns (verbosity=0)|`"data" (string) hex-encoded bytes of the serialized block`| +|Returns (verbosity=1)|`{ (json object)`
  `"hash": "blockhash", (string) the hash of the block (same as provided)`
  `"confirmations": n, (numeric) the number of confirmations`
  `"strippedsize", n (numeric) the size of the block without witness data`
  `"size": n, (numeric) the size of the block`
  `"weight": n, (numeric) value of the weight metric`
  `"height": n, (numeric) the height of the block in the block chain`
  `"version": n, (numeric) the block version`
  `"merkleroot": "hash", (string) root hash of the merkle tree`
  `"tx": [ (json array of string) the transaction hashes`
    `"transactionhash", (string) hash of the parent transaction`
    `...`
  `]`
  `"time": n, (numeric) the block time in seconds since 1 Jan 1970 GMT`
  `"nonce": n, (numeric) the block nonce`
  `"bits", n, (numeric) the bits which represent the block difficulty`
  `difficulty: n.nn, (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty`
  `"previousblockhash": "hash", (string) the hash of the previous block`
  `"nextblockhash": "hash", (string) the hash of the next block (only if there is one)`
`}`| +|Returns (verbosity=2)|`{ (json object)`
  `"hash": "blockhash", (string) the hash of the block (same as provided)`
  `"confirmations": n, (numeric) the number of confirmations`
  `"strippedsize", n (numeric) the size of the block without witness data`
  `"size": n, (numeric) the size of the block`
  `"weight": n, (numeric) value of the weight metric`
  `"height": n, (numeric) the height of the block in the block chain`
  `"version": n, (numeric) the block version`
  `"merkleroot": "hash", (string) root hash of the merkle tree`
  `"rawtx": [ (array of json objects) the transactions as json objects`
    `(see getrawtransaction json object details)`
  `]`
  `"time": n, (numeric) the block time in seconds since 1 Jan 1970 GMT`
  `"nonce": n, (numeric) the block nonce`
  `"bits", n, (numeric) the bits which represent the block difficulty`
  `difficulty: n.nn, (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty`
  `"previousblockhash": "hash", (string) the hash of the previous block`
  `"nextblockhash": "hash", (string) the hash of the next block`
`}`| +|Example Return (verbosity=0)|`"010000000000000000000000000000000000000000000000000000000000000000000000`
`3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49`
`ffff001d1dac2b7c01010000000100000000000000000000000000000000000000000000`
`00000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f`
`4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f`
`6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104`
`678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f`
`4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000"`
**Newlines added for display purposes. The actual return does not contain newlines.**| +|Example Return (verbosity=1)|`{`
  `"hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",`
  `"confirmations": 277113,`
  `"size": 285,`
  `"height": 0,`
  `"version": 1,`
  `"merkleroot": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",`
  `"tx": [`
    `"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"`
  `],`
  `"time": 1231006505,`
  `"nonce": 2083236893,`
  `"bits": "1d00ffff",`
  `"difficulty": 1,`
  `"previousblockhash": "0000000000000000000000000000000000000000000000000000000000000000",`
  `"nextblockhash": "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048"`
`}`| [Return to Overview](#MethodOverview)
*** From 69773a7b41c1cb2f6914004764c7a02af05ca569 Mon Sep 17 00:00:00 2001 From: qqjettkgjzhxmwj <37233887+JettScythe@users.noreply.github.com> Date: Tue, 21 Jul 2020 17:24:02 -0300 Subject: [PATCH 0365/1056] Update json_rpc_api.md Corrections suggested by @onyb https://github.com/btcsuite/btcd/pull/1608#discussion_r458363077 --- docs/json_rpc_api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index c33bd7a396..61884df0a0 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -271,7 +271,7 @@ the method name for further details such as parameter and return information. | | | |---|---| |Method|getblock| -|Parameters|1. block hash (string, required) - the hash of the block
2. verbosity (int, optional, default=1) - specifies the block is returned as a JSON object instead of hex-encoded string**This parameter is a btcd extension**| +|Parameters|1. block hash (string, required) - the hash of the block
2. verbosity (int, optional, default=1) - Specifies whether the block data should be returned as a hex-encoded string (0), as parsed data with a slice of TXIDs (1), or as parsed data with parsed transaction data (2). |Description|Returns information about a block given its hash.| |Returns (verbosity=0)|`"data" (string) hex-encoded bytes of the serialized block`| |Returns (verbosity=1)|`{ (json object)`
  `"hash": "blockhash", (string) the hash of the block (same as provided)`
  `"confirmations": n, (numeric) the number of confirmations`
  `"strippedsize", n (numeric) the size of the block without witness data`
  `"size": n, (numeric) the size of the block`
  `"weight": n, (numeric) value of the weight metric`
  `"height": n, (numeric) the height of the block in the block chain`
  `"version": n, (numeric) the block version`
  `"merkleroot": "hash", (string) root hash of the merkle tree`
  `"tx": [ (json array of string) the transaction hashes`
    `"transactionhash", (string) hash of the parent transaction`
    `...`
  `]`
  `"time": n, (numeric) the block time in seconds since 1 Jan 1970 GMT`
  `"nonce": n, (numeric) the block nonce`
  `"bits", n, (numeric) the bits which represent the block difficulty`
  `difficulty: n.nn, (numeric) the proof-of-work difficulty as a multiple of the minimum difficulty`
  `"previousblockhash": "hash", (string) the hash of the previous block`
  `"nextblockhash": "hash", (string) the hash of the next block (only if there is one)`
`}`| From 24db7d7c0cea3bebf44f9f274db60c778acef94b Mon Sep 17 00:00:00 2001 From: Javed Khan Date: Fri, 10 Jul 2020 12:49:38 +0530 Subject: [PATCH 0366/1056] netsync: handle notfound messages from peers backport from https://github.com/decred/dcrd/pull/2253 When a peer sends a notfound message, remove the hash from requested map. Also increase notfound ban score and return early if it disconnects the peer. --- netsync/manager.go | 48 ++++++++++++++++++++++++++++++++++++++ server.go | 57 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 99 insertions(+), 6 deletions(-) diff --git a/netsync/manager.go b/netsync/manager.go index 51c2cbe4a8..603fca6ec8 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -79,6 +79,13 @@ type headersMsg struct { peer *peerpkg.Peer } +// notFoundMsg packages a bitcoin notfound message and the peer it came from +// together so the block handler has access to that information. +type notFoundMsg struct { + notFound *wire.MsgNotFound + peer *peerpkg.Peer +} + // donePeerMsg signifies a newly disconnected peer to the block handler. type donePeerMsg struct { peer *peerpkg.Peer @@ -1012,6 +1019,32 @@ func (sm *SyncManager) handleHeadersMsg(hmsg *headersMsg) { } } +// handleNotFoundMsg handles notfound messages from all peers. +func (sm *SyncManager) handleNotFoundMsg(nfmsg *notFoundMsg) { + peer := nfmsg.peer + state, exists := sm.peerStates[peer] + if !exists { + log.Warnf("Received notfound message from unknown peer %s", peer) + return + } + for _, inv := range nfmsg.notFound.InvList { + // verify the hash was actually announced by the peer + // before deleting from the global requested maps. + switch inv.Type { + case wire.InvTypeBlock: + if _, exists := state.requestedBlocks[inv.Hash]; exists { + delete(state.requestedBlocks, inv.Hash) + delete(sm.requestedBlocks, inv.Hash) + } + case wire.InvTypeTx: + if _, exists := state.requestedTxns[inv.Hash]; exists { + delete(state.requestedTxns, inv.Hash) + delete(sm.requestedTxns, inv.Hash) + } + } + } +} + // haveInventory returns whether or not the inventory represented by the passed // inventory vector is known. This includes checking all of the various places // inventory can be when it is in different states such as blocks that are part @@ -1293,6 +1326,9 @@ out: case *headersMsg: sm.handleHeadersMsg(msg) + case *notFoundMsg: + sm.handleNotFoundMsg(msg) + case *donePeerMsg: sm.handleDonePeerMsg(msg.peer) @@ -1490,6 +1526,18 @@ func (sm *SyncManager) QueueHeaders(headers *wire.MsgHeaders, peer *peerpkg.Peer sm.msgChan <- &headersMsg{headers: headers, peer: peer} } +// QueueNotFound adds the passed notfound message and peer to the block handling +// queue. +func (sm *SyncManager) QueueNotFound(notFound *wire.MsgNotFound, peer *peerpkg.Peer) { + // No channel handling here because peers do not need to block on + // reject messages. + if atomic.LoadInt32(&sm.shutdown) != 0 { + return + } + + sm.msgChan <- ¬FoundMsg{notFound: notFound, peer: peer} +} + // DonePeer informs the blockmanager that a peer has disconnected. func (sm *SyncManager) DonePeer(peer *peerpkg.Peer) { // Ignore if we are shutting down. diff --git a/server.go b/server.go index 9a76be8d4c..c9f23fa638 100644 --- a/server.go +++ b/server.go @@ -364,14 +364,14 @@ func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddress) { // threshold, a warning is logged including the reason provided. Further, if // the score is above the ban threshold, the peer will be banned and // disconnected. -func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { +func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) bool { // No warning is logged and no score is calculated if banning is disabled. if cfg.DisableBanning { - return + return false } if sp.isWhitelisted { peerLog.Debugf("Misbehaving whitelisted peer %s: %s", sp, reason) - return + return false } warnThreshold := cfg.BanThreshold >> 1 @@ -383,7 +383,7 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { peerLog.Warnf("Misbehaving peer %s: %s -- ban score is %d, "+ "it was not increased this time", sp, reason, score) } - return + return false } score := sp.banScore.Increase(persistent, transient) if score > warnThreshold { @@ -394,8 +394,10 @@ func (sp *serverPeer) addBanScore(persistent, transient uint32, reason string) { sp) sp.server.BanPeer(sp) sp.Disconnect() + return true } } + return false } // hasServices returns whether or not the provided advertised service flags have @@ -498,7 +500,9 @@ func (sp *serverPeer) OnMemPool(_ *peer.Peer, msg *wire.MsgMemPool) { // The ban score accumulates and passes the ban threshold if a burst of // mempool messages comes from a peer. The score decays each minute to // half of its value. - sp.addBanScore(0, 33, "mempool") + if sp.addBanScore(0, 33, "mempool") { + return + } // Generate inventory message with the available transactions in the // transaction memory pool. Limit it to the max allowed inventory @@ -638,7 +642,9 @@ func (sp *serverPeer) OnGetData(_ *peer.Peer, msg *wire.MsgGetData) { // bursts of small requests are not penalized as that would potentially ban // peers performing IBD. // This incremental score decays each minute to half of its value. - sp.addBanScore(0, uint32(length)*99/wire.MaxInvPerMsg, "getdata") + if sp.addBanScore(0, uint32(length)*99/wire.MaxInvPerMsg, "getdata") { + return + } // We wait on this wait channel periodically to prevent queuing // far more data than we can send in a reasonable time, wasting memory. @@ -1304,6 +1310,44 @@ func (sp *serverPeer) OnWrite(_ *peer.Peer, bytesWritten int, msg wire.Message, sp.server.AddBytesSent(uint64(bytesWritten)) } +// OnNotFound is invoked when a peer sends a notfound message. +func (sp *serverPeer) OnNotFound(p *peer.Peer, msg *wire.MsgNotFound) { + if !sp.Connected() { + return + } + + var numBlocks, numTxns uint32 + for _, inv := range msg.InvList { + switch inv.Type { + case wire.InvTypeBlock: + numBlocks++ + case wire.InvTypeTx: + numTxns++ + default: + peerLog.Debugf("Invalid inv type '%d' in notfound message from %s", + inv.Type, sp) + sp.Disconnect() + return + } + } + if numBlocks > 0 { + blockStr := pickNoun(uint64(numBlocks), "block", "blocks") + reason := fmt.Sprintf("%d %v not found", numBlocks, blockStr) + if sp.addBanScore(20*numBlocks, 0, reason) { + return + } + } + if numTxns > 0 { + txStr := pickNoun(uint64(numTxns), "transaction", "transactions") + reason := fmt.Sprintf("%d %v not found", numBlocks, txStr) + if sp.addBanScore(0, 10*numTxns, reason) { + return + } + } + + sp.server.syncManager.QueueNotFound(msg, p) +} + // randomUint16Number returns a random uint16 in a specified input range. Note // that the range is in zeroth ordering; if you pass it 1800, you will get // values from 0 to 1800. @@ -1998,6 +2042,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnAddr: sp.OnAddr, OnRead: sp.OnRead, OnWrite: sp.OnWrite, + OnNotFound: sp.OnNotFound, // Note: The reference client currently bans peers that send alerts // not signed with its key. We could verify against their key, but From 4255e1ed7b8bae4b316f121ceb04d4f0e23747f0 Mon Sep 17 00:00:00 2001 From: Dan Cline Date: Wed, 22 Jul 2020 22:01:38 -0400 Subject: [PATCH 0367/1056] release: update release script path --- release/README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/release/README.md b/release/README.md index a5c9681947..31b05d5c38 100644 --- a/release/README.md +++ b/release/README.md @@ -6,7 +6,7 @@ binaries are now reproducible, allowing developers to build the binary on distinct machines, and end up with a byte-for-byte identical binary. However, this wasn't _fully_ solved in `go1.13`, as the build system still includes the directory the binary is built into the binary itself. As a result, our scripts -utilize a work around needed until `go1.13.2`. +utilize a work around needed until `go1.13.2`. ## Building a New Release @@ -19,8 +19,7 @@ the release binaries following these steps: 1. `git clone https://github.com/btcsuite/btcd.git` 2. `cd btcd` -3. `./build/release/release.sh # is the name of the next - release/tag` +3. `./release/release.sh # is the name of the next release/tag` This will then create a directory of the form `btcd-` containing archives of the release binaries for each supported operating system and architecture, @@ -64,7 +63,7 @@ and `go` (matching the same version used in the release): release with `git checkout `. 7. Proceed to verify the tag with `git verify-tag ` and compile the binaries from source for the intended operating system and architecture with - `BTCDBUILDSYS=OS-ARCH ./build/release/release.sh `. + `BTCDBUILDSYS=OS-ARCH ./release/release.sh `. 8. Extract the archive found in the `btcd-` directory created by the release script and recompute the `SHA256` hash of the release binaries (btcd and btcctl) with `shasum -a 256 `. These should match __exactly__ From 2a0d6fd0e3386b8f882782944ab648d05ef5e926 Mon Sep 17 00:00:00 2001 From: Dan Cline Date: Sun, 26 Jul 2020 20:56:39 -0400 Subject: [PATCH 0368/1056] release: remove old scripts and update process doc - remove prep_release.sh and notes.sample - update license in release.sh - add notes for maintainers on the release process - mention CHANGES file modifications --- release/README.md | 116 ++++++++++++++++++++++- release/notes.sample | 6 -- release/prep_release.sh | 205 ---------------------------------------- release/release.sh | 9 +- 4 files changed, 120 insertions(+), 216 deletions(-) delete mode 100644 release/notes.sample delete mode 100644 release/prep_release.sh diff --git a/release/README.md b/release/README.md index 31b05d5c38..ea01c7d0bb 100644 --- a/release/README.md +++ b/release/README.md @@ -7,10 +7,84 @@ distinct machines, and end up with a byte-for-byte identical binary. However, this wasn't _fully_ solved in `go1.13`, as the build system still includes the directory the binary is built into the binary itself. As a result, our scripts utilize a work around needed until `go1.13.2`. +Every release should note which Go version was used to build the release, so +that version should be used for verifying the release. ## Building a New Release -### macOS/Linux/Windows (WSL) +### Tagging and pushing a new tag (for maintainers) + +Before running release scripts, a few things need to happen in order to finally +create a release and make sure there are no mistakes in the release process. + +First, make sure that before the tagged commit there are modifications to the +[CHANGES](../CHANGES) file committed. +The CHANGES file should be a changelog that roughly mirrors the release notes. +Generally, the PRs that have been merged since the last release have been +listed in the CHANGES file and categorized. +For example, these changes have had the following format in the past: +``` +Changes in X.YY.Z (Month Day Year): + - Protocol and Network-related changes: + - PR Title One (#PRNUM) + - PR Title Two (#PRNUMTWO) + ... + - RPC changes: + - Crypto changes: + ... + + - Contributors (alphabetical order): + - Contributor A + - Contributor B + - Contributor C + ... +``` + +If the previous tag is, for example, `vA.B.C`, then you can get the list of +contributors (from `vA.B.C` until the current `HEAD`) using the following command: +```bash +git log vA.B.C..HEAD --pretty="%an" | sort | uniq +``` +After committing changes to the CHANGES file, the tagged release commit +should be created. + +The tagged commit should be a commit that bumps version numbers in `version.go` +and `cmd/btcctl/version.go`. +For example (taken from [f3ec130](https://github.com/btcsuite/btcd/commit/f3ec13030e4e828869954472cbc51ac36bee5c1d)): +```diff +diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go +index 2195175c71..f65cacef7e 100644 +--- a/cmd/btcctl/version.go ++++ b/cmd/btcctl/version.go +@@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr + const ( + appMajor uint = 0 + appMinor uint = 20 +- appPatch uint = 0 ++ appPatch uint = 1 + + // appPreRelease MUST only contain characters from semanticAlphabet + // per the semantic versioning spec. +diff --git a/version.go b/version.go +index 92fd60fdd4..fba55b5a37 100644 +--- a/version.go ++++ b/version.go +@@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr + const ( + appMajor uint = 0 + appMinor uint = 20 +- appPatch uint = 0 ++ appPatch uint = 1 + + // appPreRelease MUST only contain characters from semanticAlphabet + // per the semantic versioning spec. +``` + +Next, this commit should be signed by the maintainer using `git commit -S`. +The commit should be tagged and signed with `git tag -s`, and should be +pushed using `git push origin TAG`. + +### Building a release on macOS/Linux/Windows (WSL) No prior set up is needed on Linux or macOS is required in order to build the release binaries. However, on Windows, the only way to build the release @@ -25,6 +99,46 @@ This will then create a directory of the form `btcd-` containing archives of the release binaries for each supported operating system and architecture, and a manifest file containing the hash of each archive. +### Pushing a release (for maintainers) + +Now that the directory `btcd-` is created, the manifest file needs to be +signed by a maintainer and the release files need to be published to GitHub. + +Sign the `manifest-.txt` file like so: +```sh +gpg --sign --detach-sig manifest-.txt +``` +This will create a file named `manifest-.txt.sig`, which will must +be included in the release files later. + +#### Note before publishing +Before publishing, go through the reproducible build process that is outlined +in this document with the files created from `release/release.sh`. This includes +verifying commit and tag signatures using `git verify-commit` and git `verify-tag` +respectively. + +Now that we've double-checked everything and have all of the necessary files, +it's time to publish release files on GitHub. +Follow [this documentation](https://docs.github.com/en/github/administering-a-repository/managing-releases-in-a-repository) +to create a release using the GitHub UI, and make sure to write release notes +which roughly follow the format of [previous release notes](https://github.com/btcsuite/btcd/releases/tag/v0.20.1-beta). +This is different from the [CHANGES](../CHANGES) file, which should be before the +tagged commit in the git history. +Much of the information in the release notes will be the same as the CHANGES +file. +It's important to include the Go version used to produce the release files in +the release notes, so users know the correct version of Go to use to reproduce +and verify the build. +When following the GitHub documentation, include every file in the `btcd-` +directory. + +At this point, a signed commit and tag on that commit should be pushed to the main +branch. The directory created from running `release/release.sh` should be included +as release files in the GitHub release UI, and the `manifest-.txt` file +signature, called `manifest-.txt.sig`, should also be included. +A release notes document should be created and written in the GitHub release UI. +Once all of this is done, feel free to click `Publish Release`! + ## Verifying a Release With `go1.13`, it's now possible for third parties to verify release binaries. diff --git a/release/notes.sample b/release/notes.sample deleted file mode 100644 index 86a79a61f5..0000000000 --- a/release/notes.sample +++ /dev/null @@ -1,6 +0,0 @@ -- Each release note is preceded by a dash -- Each release note must not exceed 74 characters per line -- Release notes that require a longer explanation than will fit on a - single line should be wrapped with the text indented as in this line -- No periods at the end of each release note -- Other minor cleanup and bug fixes diff --git a/release/prep_release.sh b/release/prep_release.sh deleted file mode 100644 index c64824a644..0000000000 --- a/release/prep_release.sh +++ /dev/null @@ -1,205 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2013 Conformal Systems LLC -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# -# Prepares for a release: -# - Bumps version according to specified level (major, minor, or patch) -# - Updates all version files and package control files with new version -# - Performs some basic validation on specified release notes -# - Updates project changes file with release notes -# - -PROJECT=btcd -PROJECT_UC=$(echo $PROJECT | tr '[:lower:]' '[:upper:]') -SCRIPT=$(basename $0) -VERFILE=../version.go -VERFILES="$VERFILE ../cmd/btcctl/version.go" -PROJ_CHANGES=../CHANGES - -# verify params -if [ $# -lt 2 ]; then - echo "usage: $SCRIPT {major | minor | patch} release-notes-file" - exit 1 -fi - -CUR_DIR=$(pwd) -cd "$(dirname $0)" - -# verify version files exist -for verfile in $VERFILES; do - if [ ! -f "$verfile" ]; then - echo "$SCRIPT: error: $verfile does not exist" 1>&2 - exit 1 - fi -done - -# verify changes file exists -if [ ! -f "$PROJ_CHANGES" ]; then - echo "$SCRIPT: error: $PROJ_CHANGES does not exist" 1>&2 - exit 1 -fi - -RTYPE="$1" -RELEASE_NOTES="$2" -if [ $(echo $RELEASE_NOTES | cut -c1) != "/" ]; then - RELEASE_NOTES="$CUR_DIR/$RELEASE_NOTES" -fi - -# verify valid release type -if [ "$RTYPE" != "major" -a "$RTYPE" != "minor" -a "$RTYPE" != "patch" ]; then - echo "$SCRIPT: error: release type must be major, minor, or patch" - exit 1 -fi - -# verify release notes -if [ ! -e "$RELEASE_NOTES" ]; then - echo "$SCRIPT: error: specified release notes file does not exist" - exit 1 -fi - -if [ ! -s "$RELEASE_NOTES" ]; then - echo "$SCRIPT: error: specified release notes file is empty" - exit 1 -fi - -# verify release notes format -while IFS='' read line; do - if [ -z "$line" ]; then - echo "$SCRIPT: error: release notes must not have blank lines" - exit 1 - fi - if [ ${#line} -gt 74 ]; then - echo -n "$SCRIPT: error: release notes must not contain lines " - echo "with more than 74 characters" - exit 1 - fi - if expr "$line" : ".*\.$" >/dev/null 2>&1 ; then - echo -n "$SCRIPT: error: release notes must not contain lines " - echo "that end in a period" - exit 1 - fi - if ! expr "$line" : "\-" >/dev/null 2>&1; then - if ! expr "$line" : " " >/dev/null 2>&1; then - echo -n "$SCRIPT: error: release notes must not contain lines " - echo "that do not begin with a dash and are not indented" - exit 1 - fi - fi -done <"$RELEASE_NOTES" - -# verify git is available -if ! type git >/dev/null 2>&1; then - echo -n "$SCRIPT: error: Unable to find 'git' in the system path." - exit 1 -fi - -# verify the git repository is on the master branch -BRANCH=$(git branch | grep '\*' | cut -c3-) -if [ "$BRANCH" != "master" ]; then - echo "$SCRIPT: error: git repository must be on the master branch." - exit 1 -fi - -# verify there are no uncommitted modifications prior to release modifications -NUM_MODIFIED=$(git diff 2>/dev/null | wc -l | sed 's/^[ \t]*//') -NUM_STAGED=$(git diff --cached 2>/dev/null | wc -l | sed 's/^[ \t]*//') -if [ "$NUM_MODIFIED" != "0" -o "$NUM_STAGED" != "0" ]; then - echo -n "$SCRIPT: error: the working directory contains uncommitted " - echo "modifications" - exit 1 -fi - -# get version -PAT_PREFIX="(^[[:space:]]+app" -PAT_SUFFIX='[[:space:]]+uint[[:space:]]+=[[:space:]]+)[0-9]+$' -MAJOR=$(egrep "${PAT_PREFIX}Major${PAT_SUFFIX}" $VERFILE | awk '{print $4}') -MINOR=$(egrep "${PAT_PREFIX}Minor${PAT_SUFFIX}" $VERFILE | awk '{print $4}') -PATCH=$(egrep "${PAT_PREFIX}Patch${PAT_SUFFIX}" $VERFILE | awk '{print $4}') -if [ -z "$MAJOR" -o -z "$MINOR" -o -z "$PATCH" ]; then - echo "$SCRIPT: error: unable to get version from $VERFILE" 1>&2 - exit 1 -fi - -# bump version according to level -if [ "$RTYPE" = "major" ]; then - MAJOR=$(expr $MAJOR + 1) - MINOR=0 - PATCH=0 -elif [ "$RTYPE" = "minor" ]; then - MINOR=$(expr $MINOR + 1) - PATCH=0 -elif [ "$RTYPE" = "patch" ]; then - PATCH=$(expr $PATCH + 1) -fi -PROJ_VER="$MAJOR.$MINOR.$PATCH" - -# update project changes with release notes -DATE=$(date "+%a %b %d %Y") -awk -v D="$DATE" -v VER="$PROJ_VER" ' -/=======/ && first_line==0 { - first_line=1 - print $0 - next -} -/=======/ && first_line==1 { - print $0 - print "" - print "Changes in "VER" ("D")" - exit -} -{ print $0 } -' <"$PROJ_CHANGES" >"${PROJ_CHANGES}.tmp" -cat "$RELEASE_NOTES" | sed 's/^/ /' >>"${PROJ_CHANGES}.tmp" -awk ' -/=======/ && first_line==0 { - first_line=1 - next -} -/=======/ && first_line==1 { - second_line=1 - next -} -second_line==1 { print $0 } -' <"$PROJ_CHANGES" >>"${PROJ_CHANGES}.tmp" - -# update version filef with new version -for verfile in $VERFILES; do - sed -E " - s/${PAT_PREFIX}Major${PAT_SUFFIX}/\1${MAJOR}/; - s/${PAT_PREFIX}Minor${PAT_SUFFIX}/\1${MINOR}/; - s/${PAT_PREFIX}Patch${PAT_SUFFIX}/\1${PATCH}/; - " <"$verfile" >"${verfile}.tmp" -done - - -# Apply changes -mv "${PROJ_CHANGES}.tmp" "$PROJ_CHANGES" -for verfile in $VERFILES; do - mv "${verfile}.tmp" "$verfile" -done - -echo "All files have been prepared for release." -echo "Use the following commands to review the changes for accuracy:" -echo " git status" -echo " git diff" -echo "" -echo "If everything is accurate, use the following commands to commit, tag," -echo "and push the changes" -echo " git commit -am \"Prepare for release ${PROJ_VER}.\"" -echo -n " git tag -a \"${PROJECT_UC}_${MAJOR}_${MINOR}_${PATCH}\" -m " -echo "\"Release ${PROJ_VER}\"" -echo " git push" -echo " git push --tags" diff --git a/release/release.sh b/release/release.sh index 7b0885dac6..cc65fb6cf1 100755 --- a/release/release.sh +++ b/release/release.sh @@ -1,11 +1,12 @@ #!/bin/bash +# Copyright (c) 2016 Company 0, LLC. +# Copyright (c) 2016-2020 The btcsuite developers +# Use of this source code is governed by an ISC +# license that can be found in the LICENSE file. + # Simple bash script to build basic btcd tools for all the platforms we support # with the golang cross-compiler. -# -# Copyright (c) 2016 Company 0, LLC. -# Use of this source code is governed by the ISC -# license. set -e From 4527c5671fd982a842521ceb3f3bc1869b37b739 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 24 Aug 2020 20:57:54 +0200 Subject: [PATCH 0369/1056] Update CHANGES file for 0.21.0 release Also updated changes for 0.20.1, and added a small note about changes since 0.12.0. --- CHANGES | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/CHANGES b/CHANGES index 6f7013e922..d38897b339 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,161 @@ User visible changes for btcd A full-node bitcoin implementation written in Go ============================================================================ +Changes in 0.21.0 (Thu Aug 27 2020) + - Network-related changes: + - Handle notfound messages from peers in netsync package (#1603) + - RPC changes: + - Add compatibility for getblock RPC changes in bitcoind 0.15.0 (#1529) + - Add new optional Params field to rpcclient.ConnConfig (#1467) + - Add new error code ErrRPCInWarmup in btcjson (#1541) + - Add compatibility for changes to getmempoolentry response in bitcoind + 0.19.0 (#1524) + - Add rpcclient methods for estimatesmartfee and generatetoaddress + commands (#1500) + - Add rpcclient method for getblockstats command (#1500) + - Parse serialized transaction from createrawtransaction command using + both segwit, and legacy format (#1502) + - Support cookie-based authentication in rpcclient (#1460) + - Add rpcclient method for getchaintxstats command (#1571) + - Add rpcclient method for fundrawtransaction command (#1553) + - Add rpcclient method for getbalances command (#1595) + - Add new method rpcclient.GetTransactionWatchOnly (#1592) + - Crypto changes: + - Fix panic in fieldVal.SetByteSlice when called with large values, and + improve the method to be 35% faster (#1602) + - btcctl changes: + - Added -regtest mode to btcctl (#1556) + - Misc changes: + - Fix a bug due to a deadlock in connmgr's dynamic ban scoring (#1509) + - Add blockchain.NewUtxoEntry() to directly create entries for + UtxoViewpoint (#1588) + - Replace LRU cache implementation in peer package with a generic one + from decred/dcrd (#1599) + - Contributors (alphabetical order): + - Anirudha Bose + - Antonin Hildebrand + - Dan Cline + - Daniel McNally + - David Hill + - Federico Bond + - George Tankersley + - Henry + - Henry Harder + - Iskander Sharipov + - Ivan Kuznetsov + - Jake Sylvestre + - Javed Khan + - JeremyRand + - Jin + - John C. Vernaleo + - Kulpreet Singh + - Mikael Lindlof + - Murray Nesbitt + - Nisen + - Olaoluwa Osuntokun + - Oliver Gugger + - Steven Roose + - Torkel Rogstad + - Tyler Chambers + - Wilmer Paulino + - Yash Bhutwala + - adiabat + - jalavosus + - mohanson + - qqjettkgjzhxmwj + - qshuai + - shuai.qi + - tpkeeper + +Changes in v0.20.1 (Wed Nov 13 2019) + - RPC changes: + - Add compatibility for bitcoind v0.19.0 in rpcclient and btcjson + packages (#1484) + - Contributors (alphabetical order): + - Eugene Zeigel + - Olaoluwa Osuntokun + - Wilmer Paulino + +Changes in v0.20.0 (Tue Oct 15 2019) + - Significant changes made since 0.12.0. See git log or refer to release + notes on GitHub for full details. + - Contributors (alphabetical order): + - Albert Puigsech Galicia + - Alex Akselrod + - Alex Bosworth + - Alex Manuskin + - Alok Menghrajani + - Anatoli Babenia + - Andy Weidenbaum + - Calvin McAnarney + - Chris Martin + - Chris Pacia + - Chris Shepherd + - Conner Fromknecht + - Craig Sturdy + - Cédric Félizard + - Daniel Krawisz + - Daniel Martí + - Daniel McNally + - Dario Nieuwenhuis + - Dave Collins + - David Hill + - David de Kloet + - GeertJohan + - Grace Noah + - Gregory Trubetskoy + - Hector Jusforgues + - Iskander (Alex) Sharipov + - Janus Troelsen + - Jasper + - Javed Khan + - Jeremiah Goyette + - Jim Posen + - Jimmy Song + - Johan T. Halseth + - John C. Vernaleo + - Jonathan Gillham + - Josh Rickmar + - Jon Underwood + - Jonathan Zeppettini + - Jouke Hofman + - Julian Meyer + - Kai + - Kamil Slowikowski + - Kefkius + - Leonardo Lazzaro + - Marco Peereboom + - Marko Bencun + - Mawueli Kofi Adzoe + - Michail Kargakis + - Mitchell Paull + - Nathan Bass + - Nicola 'tekNico' Larosa + - Olaoluwa Osuntokun + - Pedro Martelletto + - Ricardo Velhote + - Roei Erez + - Ruben de Vries + - Rune T. Aune + - Sad Pencil + - Shuai Qi + - Steven Roose + - Tadge Dryja + - Tibor Bősze + - Tomás Senart + - Tzu-Jung Lee + - Vadym Popov + - Waldir Pimenta + - Wilmer Paulino + - benma + - danda + - dskloet + - esemplastic + - jadeblaquiere + - nakagawa + - preminem + - qshuai + Changes in 0.12.0 (Fri Nov 20 2015) - Protocol and network related changes: - Add a new checkpoint at block height 382320 (#555) From 56cc42fe07c206e76812fc57a216b59c41189f04 Mon Sep 17 00:00:00 2001 From: "John C. Vernaleo" Date: Thu, 27 Aug 2020 15:36:47 -0400 Subject: [PATCH 0370/1056] btcd: bump version to v0.21.0-beta --- cmd/btcctl/version.go | 4 ++-- version.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go index f65cacef7e..f3a3e0b830 100644 --- a/cmd/btcctl/version.go +++ b/cmd/btcctl/version.go @@ -17,8 +17,8 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 20 - appPatch uint = 1 + appMinor uint = 21 + appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. diff --git a/version.go b/version.go index fba55b5a37..ac294de232 100644 --- a/version.go +++ b/version.go @@ -17,8 +17,8 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 20 - appPatch uint = 1 + appMinor uint = 21 + appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. From 70a0132485e5570ba3a1dede7a205fb55a127c9a Mon Sep 17 00:00:00 2001 From: Rjected Date: Mon, 26 Aug 2019 22:09:13 -0400 Subject: [PATCH 0371/1056] blockchain: remove unknown block version warning --- blockchain/chain.go | 15 ++---------- blockchain/thresholdstate.go | 10 ++------ blockchain/versionbits.go | 44 ------------------------------------ 3 files changed, 4 insertions(+), 65 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 71c1b2ee77..eea603ce8e 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -174,11 +174,7 @@ type BlockChain struct { // // unknownRulesWarned refers to warnings due to unknown rules being // activated. - // - // unknownVersionsWarned refers to warnings due to unknown versions - // being mined. - unknownRulesWarned bool - unknownVersionsWarned bool + unknownRulesWarned bool // The notifications field stores a slice of callbacks to be executed on // certain blockchain events. @@ -574,20 +570,13 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, "spent transaction out information") } - // No warnings about unknown rules or versions until the chain is - // current. + // No warnings about unknown rules until the chain is current. if b.isCurrent() { // Warn if any unknown new rules are either about to activate or // have already been activated. if err := b.warnUnknownRuleActivations(node); err != nil { return err } - - // Warn if a high enough percentage of the last blocks have - // unexpected versions. - if err := b.warnUnknownVersions(node); err != nil { - return err - } } // Write any block status changes to DB before updating best state. diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index 35a762552a..5da74a95af 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -310,7 +310,7 @@ func (b *BlockChain) deploymentState(prevNode *blockNode, deploymentID uint32) ( // initThresholdCaches initializes the threshold state caches for each warning // bit and defined deployment and provides warnings if the chain is current per -// the warnUnknownVersions and warnUnknownRuleActivations functions. +// the warnUnknownRuleActivations function. func (b *BlockChain) initThresholdCaches() error { // Initialize the warning and deployment caches by calculating the // threshold state for each of them. This will ensure the caches are @@ -335,15 +335,9 @@ func (b *BlockChain) initThresholdCaches() error { } } - // No warnings about unknown rules or versions until the chain is - // current. + // No warnings about unknown rules until the chain is current. if b.isCurrent() { - // Warn if a high enough percentage of the last blocks have - // unexpected versions. bestNode := b.bestChain.Tip() - if err := b.warnUnknownVersions(bestNode); err != nil { - return err - } // Warn if any unknown new rules are either about to activate or // have already been activated. diff --git a/blockchain/versionbits.go b/blockchain/versionbits.go index ef2a080257..28fcde7b69 100644 --- a/blockchain/versionbits.go +++ b/blockchain/versionbits.go @@ -26,15 +26,6 @@ const ( // vbNumBits is the total number of bits available for use with the // version bits scheme. vbNumBits = 29 - - // unknownVerNumToCheck is the number of previous blocks to consider - // when checking for a threshold of unknown block versions for the - // purposes of warning the user. - unknownVerNumToCheck = 100 - - // unknownVerWarnNum is the threshold of previous blocks that have an - // unknown version to use for the purposes of warning the user. - unknownVerWarnNum = unknownVerNumToCheck / 2 ) // bitConditionChecker provides a thresholdConditionChecker which can be used to @@ -264,38 +255,3 @@ func (b *BlockChain) warnUnknownRuleActivations(node *blockNode) error { return nil } - -// warnUnknownVersions logs a warning if a high enough percentage of the last -// blocks have unexpected versions. -// -// This function MUST be called with the chain state lock held (for writes) -func (b *BlockChain) warnUnknownVersions(node *blockNode) error { - // Nothing to do if already warned. - if b.unknownVersionsWarned { - return nil - } - - // Warn if enough previous blocks have unexpected versions. - numUpgraded := uint32(0) - for i := uint32(0); i < unknownVerNumToCheck && node != nil; i++ { - expectedVersion, err := b.calcNextBlockVersion(node.parent) - if err != nil { - return err - } - if expectedVersion > vbLegacyBlockVersion && - (node.version & ^expectedVersion) != 0 { - - numUpgraded++ - } - - node = node.parent - } - if numUpgraded > unknownVerWarnNum { - log.Warn("Unknown block versions are being mined, so new " + - "rules might be in effect. Are you running the " + - "latest version of the software?") - b.unknownVersionsWarned = true - } - - return nil -} From efae8e99678d9579aea0d7bd6b352289a17187b8 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 24 Aug 2020 20:53:04 +0200 Subject: [PATCH 0372/1056] Add rpclient implementation of getdescriptorinfo RPC --- btcjson/chainsvrcmds.go | 14 ++++++++++++ btcjson/chainsvrcmds_test.go | 11 ++++++++++ btcjson/chainsvrresults.go | 9 ++++++++ rpcclient/chain.go | 41 ++++++++++++++++++++++++++++++++++++ rpcclient/example_test.go | 31 +++++++++++++++++++++++++++ 5 files changed, 106 insertions(+) create mode 100644 rpcclient/example_test.go diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index d66478c305..1292e46c89 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -882,6 +882,19 @@ func NewVerifyTxOutProofCmd(proof string) *VerifyTxOutProofCmd { } } +// GetDescriptorInfoCmd defines the getdescriptorinfo JSON-RPC command. +type GetDescriptorInfoCmd struct { + Descriptor string +} + +// NewGetDescriptorInfoCmd returns a new instance which can be used to issue a +// getdescriptorinfo JSON-RPC command. +func NewGetDescriptorInfoCmd(descriptor string) *GetDescriptorInfoCmd { + return &GetDescriptorInfoCmd{ + Descriptor: descriptor, + } +} + func init() { // No special flags for commands in this file. flags := UsageFlag(0) @@ -937,4 +950,5 @@ func init() { MustRegisterCmd("verifychain", (*VerifyChainCmd)(nil), flags) MustRegisterCmd("verifymessage", (*VerifyMessageCmd)(nil), flags) MustRegisterCmd("verifytxoutproof", (*VerifyTxOutProofCmd)(nil), flags) + MustRegisterCmd("getdescriptorinfo", (*GetDescriptorInfoCmd)(nil), flags) } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index e2b5025727..9aeac49ecb 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1302,6 +1302,17 @@ func TestChainSvrCmds(t *testing.T) { Proof: "test", }, }, + { + name: "getdescriptorinfo", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getdescriptorinfo", "123") + }, + staticCmd: func() interface{} { + return btcjson.NewGetDescriptorInfoCmd("123") + }, + marshalled: `{"jsonrpc":"1.0","method":"getdescriptorinfo","params":["123"],"id":1}`, + unmarshalled: &btcjson.GetDescriptorInfoCmd{Descriptor: "123"}, + }, } t.Logf("Running %d tests", len(tests)) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index a96319b235..482e3d72d8 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -730,3 +730,12 @@ func (f *FundRawTransactionResult) UnmarshalJSON(data []byte) error { f.ChangePosition = rawRes.ChangePosition return nil } + +// GetDescriptorInfoResult models the data from the getdescriptorinfo command. +type GetDescriptorInfoResult struct { + Descriptor string `json:"descriptor"` // descriptor in canonical form, without private keys + Checksum string `json:"checksum"` // checksum for the input descriptor + IsRange bool `json:"isrange"` // whether the descriptor is ranged + IsSolvable bool `json:"issolvable"` // whether the descriptor is solvable + HasPrivateKeys bool `json:"hasprivatekeys"` // whether the descriptor has at least one private key +} diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 9f0c6c684d..c0c6a15922 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -1224,3 +1224,44 @@ func (c *Client) GetBlockStatsAsync(hashOrHeight interface{}, stats *[]string) F func (c *Client) GetBlockStats(hashOrHeight interface{}, stats *[]string) (*btcjson.GetBlockStatsResult, error) { return c.GetBlockStatsAsync(hashOrHeight, stats).Receive() } + +// FutureGetDescriptorInfoResult is a future promise to deliver the result of a +// GetDescriptorInfoAsync RPC invocation (or an applicable error). +type FutureGetDescriptorInfoResult chan *response + +// Receive waits for the response promised by the future and returns the analysed +// info of the descriptor. +func (r FutureGetDescriptorInfoResult) Receive() (*btcjson.GetDescriptorInfoResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var descriptorInfo btcjson.GetDescriptorInfoResult + err = json.Unmarshal(res, &descriptorInfo) + if err != nil { + return nil, err + } + return &descriptorInfo, nil +} + +// GetDescriptorInfoAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetDescriptorInfo for the blocking version and more details. +func (c *Client) GetDescriptorInfoAsync(descriptor string) FutureGetDescriptorInfoResult { + cmd := btcjson.NewGetDescriptorInfoCmd(descriptor) + return c.sendCmd(cmd) +} + +// GetDescriptorInfo returns the analysed info of a descriptor string, by invoking the +// getdescriptorinfo RPC. +// +// Use this function to analyse a descriptor string, or compute the checksum +// for a descriptor without one. +// +// See btcjson.GetDescriptorInfoResult for details about the result. +func (c *Client) GetDescriptorInfo(descriptor string) (*btcjson.GetDescriptorInfoResult, error) { + return c.GetDescriptorInfoAsync(descriptor).Receive() +} diff --git a/rpcclient/example_test.go b/rpcclient/example_test.go new file mode 100644 index 0000000000..c2c5290596 --- /dev/null +++ b/rpcclient/example_test.go @@ -0,0 +1,31 @@ +package rpcclient + +import ( + "fmt" +) + +func ExampleClient_GetDescriptorInfo() { + connCfg := &ConnConfig{ + Host: "localhost:8332", + User: "yourrpcuser", + Pass: "yourrpcpass", + HTTPPostMode: true, + DisableTLS: true, + } + client, err := New(connCfg, nil) + if err != nil { + log.Error(err) + return + } + defer client.Shutdown() + + descriptorInfo, err := client.GetDescriptorInfo( + "wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)") + if err != nil { + log.Error(err) + return + } + + fmt.Printf("%+v\n", descriptorInfo) + // &{Descriptor:wpkh([d34db33f/84'/0'/0']0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)#n9g43y4k Checksum:qwlqgth7 IsRange:false IsSolvable:true HasPrivateKeys:false} +} From 7d69fb9ba6a009817abdc62bc30b25ddc938225e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 16 Jul 2020 18:05:45 -0700 Subject: [PATCH 0373/1056] peer: prevent last block height going backwards This modifies the UpdateLastBlockHeight function to ensure the new height is after the existing height before updating it in order to prevent it from going backwards so it properly matches the intent of the function which is to report the latest known block height for the peer. Without this change, the value will properly start out at the latest known block height reported by the peer during version negotiation, however, it will be set to lower values when syncing from the peer due to requesting old blocks and blindly updating the height. It also adds a test to ensure proper functionality. This is a backport of https://github.com/decred/dcrd/pull/1747 --- peer/peer.go | 4 +++ peer/peer_test.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/peer/peer.go b/peer/peer.go index 82010f3b84..5b083a7467 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -495,6 +495,10 @@ func (p *Peer) String() string { // This function is safe for concurrent access. func (p *Peer) UpdateLastBlockHeight(newHeight int32) { p.statsMtx.Lock() + if newHeight <= p.lastBlock { + p.statsMtx.Unlock() + return + } log.Tracef("Updating last block height of peer %v from %v to %v", p.addr, p.lastBlock, newHeight) p.lastBlock = newHeight diff --git a/peer/peer_test.go b/peer/peer_test.go index fff0ce3fd8..6cc3113d1e 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -917,6 +917,72 @@ func TestDuplicateVersionMsg(t *testing.T) { } } +// TestUpdateLastBlockHeight ensures the last block height is set properly +// during the initial version negotiation and is only allowed to advance to +// higher values via the associated update function. +func TestUpdateLastBlockHeight(t *testing.T) { + // Create a pair of peers that are connected to each other using a fake + // connection and the remote peer starting at height 100. + const remotePeerHeight = 100 + verack := make(chan struct{}) + peerCfg := peer.Config{ + Listeners: peer.MessageListeners{ + OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { + verack <- struct{}{} + }, + }, + UserAgentName: "peer", + UserAgentVersion: "1.0", + ChainParams: &chaincfg.MainNetParams, + Services: 0, + } + remotePeerCfg := peerCfg + remotePeerCfg.NewestBlock = func() (*chainhash.Hash, int32, error) { + return &chainhash.Hash{}, remotePeerHeight, nil + } + inConn, outConn := pipe( + &conn{laddr: "10.0.0.1:9108", raddr: "10.0.0.2:9108"}, + &conn{laddr: "10.0.0.2:9108", raddr: "10.0.0.1:9108"}, + ) + localPeer, err := peer.NewOutboundPeer(&peerCfg, inConn.laddr) + if err != nil { + t.Fatalf("NewOutboundPeer: unexpected err: %v\n", err) + } + localPeer.AssociateConnection(outConn) + inPeer := peer.NewInboundPeer(&remotePeerCfg) + inPeer.AssociateConnection(inConn) + + // Wait for the veracks from the initial protocol version negotiation. + for i := 0; i < 2; i++ { + select { + case <-verack: + case <-time.After(time.Second): + t.Fatal("verack timeout") + } + } + + // Ensure the latest block height starts at the value reported by the remote + // peer via its version message. + if height := localPeer.LastBlock(); height != remotePeerHeight { + t.Fatalf("wrong starting height - got %d, want %d", height, + remotePeerHeight) + } + + // Ensure the latest block height is not allowed to go backwards. + localPeer.UpdateLastBlockHeight(remotePeerHeight - 1) + if height := localPeer.LastBlock(); height != remotePeerHeight { + t.Fatalf("height allowed to go backwards - got %d, want %d", height, + remotePeerHeight) + } + + // Ensure the latest block height is allowed to advance. + localPeer.UpdateLastBlockHeight(remotePeerHeight + 1) + if height := localPeer.LastBlock(); height != remotePeerHeight+1 { + t.Fatalf("height not allowed to advance - got %d, want %d", height, + remotePeerHeight+1) + } +} + func init() { // Allow self connection when running the tests. peer.TstAllowSelfConns() From 36d4ae08e87e227efae5997664ff652ebc7fdbe2 Mon Sep 17 00:00:00 2001 From: wakiyamap Date: Fri, 14 Aug 2020 17:46:02 +0900 Subject: [PATCH 0374/1056] Fix monetary unit --- rpcserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index 89817db856..6d684451b1 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -543,7 +543,7 @@ func handleCreateRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan params := s.cfg.ChainParams for encodedAddr, amount := range c.Amounts { // Ensure amount is in the valid range for monetary amounts. - if amount <= 0 || amount > btcutil.MaxSatoshi { + if amount <= 0 || amount*btcutil.SatoshiPerBitcoin > btcutil.MaxSatoshi { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCType, Message: "Invalid amount", From 7145eef75b483775e6457aa628f98fe1ae05758a Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 24 Aug 2020 20:47:32 +0200 Subject: [PATCH 0375/1056] rpcserver: add parity with bitcoind for validateaddress Updated the rpcserver handler for validateaddress JSON-RPC command to have parity with the bitcoind 0.20.0 interface. The new fields included are - isscript, iswitness, witness_version, and witness_program. The scriptPubKey field has been left out since it requires wallet access. This update has no impact on the rpcclient.ValidateAddress method, which uses the btcjson.ValidateAddressWalletResult type for modelling the response from bitcoind. --- btcjson/chainsvrresults.go | 12 ++++++++++-- rpcserver.go | 31 +++++++++++++++++++++++++++++++ rpcserverhelp.go | 8 ++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 482e3d72d8..6322580217 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -671,9 +671,17 @@ type TxRawDecodeResult struct { // ValidateAddressChainResult models the data returned by the chain server // validateaddress command. +// +// Compared to the Bitcoin Core version, this struct lacks the scriptPubKey +// field since it requires wallet access, which is outside the scope of btcd. +// Ref: https://bitcoincore.org/en/doc/0.20.0/rpc/util/validateaddress/ type ValidateAddressChainResult struct { - IsValid bool `json:"isvalid"` - Address string `json:"address,omitempty"` + IsValid bool `json:"isvalid"` + Address string `json:"address,omitempty"` + IsScript *bool `json:"isscript,omitempty"` + IsWitness *bool `json:"iswitness,omitempty"` + WitnessVersion *int32 `json:"witness_version,omitempty"` + WitnessProgram *string `json:"witness_program,omitempty"` } // EstimateSmartFeeResult models the data returned buy the chain server diff --git a/rpcserver.go b/rpcserver.go index 6d684451b1..aa154dd0e1 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3493,6 +3493,37 @@ func handleValidateAddress(s *rpcServer, cmd interface{}, closeChan <-chan struc return result, nil } + switch addr := addr.(type) { + case *btcutil.AddressPubKeyHash: + result.IsScript = btcjson.Bool(false) + result.IsWitness = btcjson.Bool(false) + + case *btcutil.AddressScriptHash: + result.IsScript = btcjson.Bool(true) + result.IsWitness = btcjson.Bool(false) + + case *btcutil.AddressPubKey: + result.IsScript = btcjson.Bool(false) + result.IsWitness = btcjson.Bool(false) + + case *btcutil.AddressWitnessPubKeyHash: + result.IsScript = btcjson.Bool(false) + result.IsWitness = btcjson.Bool(true) + result.WitnessVersion = btcjson.Int32(int32(addr.WitnessVersion())) + result.WitnessProgram = btcjson.String(hex.EncodeToString(addr.WitnessProgram())) + + case *btcutil.AddressWitnessScriptHash: + result.IsScript = btcjson.Bool(true) + result.IsWitness = btcjson.Bool(true) + result.WitnessVersion = btcjson.Int32(int32(addr.WitnessVersion())) + result.WitnessProgram = btcjson.String(hex.EncodeToString(addr.WitnessProgram())) + + default: + // Handle the case when a new Address is supported by btcutil, but none + // of the cases were matched in the switch block. The current behaviour + // is to do nothing, and only populate the Address and IsValid fields. + } + result.Address = addr.EncodeAddress() result.IsValid = true diff --git a/rpcserverhelp.go b/rpcserverhelp.go index cc3b33f3ce..9299f3e49d 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -575,8 +575,12 @@ var helpDescsEnUS = map[string]string{ "submitblock--result1": "The reason the block was rejected", // ValidateAddressResult help. - "validateaddresschainresult-isvalid": "Whether or not the address is valid", - "validateaddresschainresult-address": "The bitcoin address (only when isvalid is true)", + "validateaddresschainresult-isvalid": "Whether or not the address is valid", + "validateaddresschainresult-address": "The bitcoin address (only when isvalid is true)", + "validateaddresschainresult-isscript": "If the key is a script", + "validateaddresschainresult-iswitness": "If the address is a witness address", + "validateaddresschainresult-witness_version": "The version number of the witness program", + "validateaddresschainresult-witness_program": "The hex value of the witness program", // ValidateAddressCmd help. "validateaddress--synopsis": "Verify an address is valid.", From b68c50e33c394ec5214118fe9471534428d08f94 Mon Sep 17 00:00:00 2001 From: Mikael Lindlof Date: Sat, 16 May 2020 11:12:28 +0100 Subject: [PATCH 0376/1056] Add getblockfilter JSON-RPC client command Add type for second getblockfilter param --- btcjson/chainsvrcmds.go | 28 ++++++++++++++++++++++++++ btcjson/chainsvrcmds_test.go | 22 +++++++++++++++++++++ btcjson/chainsvrresults.go | 7 +++++++ btcjson/helpers.go | 8 ++++++++ rpcclient/chain.go | 38 ++++++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 1292e46c89..6383458528 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -200,6 +200,33 @@ func NewGetBlockCountCmd() *GetBlockCountCmd { return &GetBlockCountCmd{} } +// FilterTypeName defines the type used in the getblockfilter JSON-RPC command for the +// filter type field. +type FilterTypeName string + +const ( + // FilterTypeBasic is the basic filter type defined in BIP0158. + FilterTypeBasic FilterTypeName = "basic" +) + +// GetBlockFilterCmd defines the getblockfilter JSON-RPC command. +type GetBlockFilterCmd struct { + BlockHash string // The hash of the block + FilterType *FilterTypeName // The type name of the filter, default=basic +} + +// NewGetBlockFilterCmd returns a new instance which can be used to issue a +// getblockfilter JSON-RPC command. +// +// The parameters which are pointers indicate they are optional. Passing nil +// for optional parameters will use the default value. +func NewGetBlockFilterCmd(blockHash string, filterType *FilterTypeName) *GetBlockFilterCmd { + return &GetBlockFilterCmd{ + BlockHash: blockHash, + FilterType: filterType, + } +} + // GetBlockHashCmd defines the getblockhash JSON-RPC command. type GetBlockHashCmd struct { Index int64 @@ -909,6 +936,7 @@ func init() { MustRegisterCmd("getblock", (*GetBlockCmd)(nil), flags) MustRegisterCmd("getblockchaininfo", (*GetBlockChainInfoCmd)(nil), flags) MustRegisterCmd("getblockcount", (*GetBlockCountCmd)(nil), flags) + MustRegisterCmd("getblockfilter", (*GetBlockFilterCmd)(nil), flags) MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags) MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags) MustRegisterCmd("getblockstats", (*GetBlockStatsCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 9aeac49ecb..9087135d7e 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -334,6 +334,28 @@ func TestChainSvrCmds(t *testing.T) { marshalled: `{"jsonrpc":"1.0","method":"getblockcount","params":[],"id":1}`, unmarshalled: &btcjson.GetBlockCountCmd{}, }, + { + name: "getblockfilter", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockfilter", "0000afaf") + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockFilterCmd("0000afaf", nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockfilter","params":["0000afaf"],"id":1}`, + unmarshalled: &btcjson.GetBlockFilterCmd{"0000afaf", nil}, + }, + { + name: "getblockfilter optional filtertype", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockfilter", "0000afaf", "basic") + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockFilterCmd("0000afaf", btcjson.NewFilterTypeName(btcjson.FilterTypeBasic)) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockfilter","params":["0000afaf","basic"],"id":1}`, + unmarshalled: &btcjson.GetBlockFilterCmd{"0000afaf", btcjson.NewFilterTypeName(btcjson.FilterTypeBasic)}, + }, { name: "getblockhash", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 6322580217..5699c53c07 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -226,6 +226,13 @@ type GetBlockChainInfoResult struct { *UnifiedSoftForks } +// GetBlockFilterResult models the data returned from the getblockfilter +// command. +type GetBlockFilterResult struct { + Filter string `json:"filter"` // the hex-encoded filter data + Header string `json:"header"` // the hex-encoded filter header +} + // GetBlockTemplateResultTx models the transactions field of the // getblocktemplate command. type GetBlockTemplateResultTx struct { diff --git a/btcjson/helpers.go b/btcjson/helpers.go index d9b452e7c3..eda26cb885 100644 --- a/btcjson/helpers.go +++ b/btcjson/helpers.go @@ -75,3 +75,11 @@ func String(v string) *string { *p = v return p } + +// NewFilterTypeName is a helper routine that allocates a new FilterTypeName value to store v and +// returns a pointer to it. This is useful when assigning optional parameters. +func NewFilterTypeName(v FilterTypeName) *FilterTypeName { + p := new(FilterTypeName) + *p = v + return p +} diff --git a/rpcclient/chain.go b/rpcclient/chain.go index c0c6a15922..4d7c455dd0 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -508,6 +508,44 @@ func (c *Client) GetBlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) { return c.GetBlockChainInfoAsync().Receive() } +// FutureGetBlockFilterResult is a future promise to deliver the result of a +// GetBlockFilterAsync RPC invocation (or an applicable error). +type FutureGetBlockFilterResult chan *response + +// Receive waits for the response promised by the future and returns block filter +// result provided by the server. +func (r FutureGetBlockFilterResult) Receive() (*btcjson.GetBlockFilterResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var blockFilter btcjson.GetBlockFilterResult + err = json.Unmarshal(res, &blockFilter) + if err != nil { + return nil, err + } + + return &blockFilter, nil +} + +// GetBlockFilterAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetBlockFilter for the blocking version and more details. +func (c *Client) GetBlockFilterAsync(blockHash chainhash.Hash, filterType *btcjson.FilterTypeName) FutureGetBlockFilterResult { + hash := blockHash.String() + + cmd := btcjson.NewGetBlockFilterCmd(hash, filterType) + return c.sendCmd(cmd) +} + +// GetBlockFilter retrieves a BIP0157 content filter for a particular block. +func (c *Client) GetBlockFilter(blockHash chainhash.Hash, filterType *btcjson.FilterTypeName) (*btcjson.GetBlockFilterResult, error) { + return c.GetBlockFilterAsync(blockHash, filterType).Receive() +} + // FutureGetBlockHashResult is a future promise to deliver the result of a // GetBlockHashAsync RPC invocation (or an applicable error). type FutureGetBlockHashResult chan *response From d2c0123befbf2243d8dd35dd4976cb7d1f3c65aa Mon Sep 17 00:00:00 2001 From: Mikael Lindlof Date: Sat, 23 May 2020 19:54:49 +0100 Subject: [PATCH 0377/1056] Implement signmessagewithprivkey JSON-RPC command Reuse the Bitcoin message signature header const also in verifymessage. --- btcjson/chainsvrcmds.go | 19 +++++ btcjson/chainsvrcmds_test.go | 14 ++++ rpcserver.go | 141 +++++++++++++++++++++++------------ rpcserverhelp.go | 99 ++++++++++++------------ 4 files changed, 180 insertions(+), 93 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 6383458528..d751d9bce2 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -806,6 +806,24 @@ func NewSetGenerateCmd(generate bool, genProcLimit *int) *SetGenerateCmd { } } +// SignMessageWithPrivKeyCmd defines the signmessagewithprivkey JSON-RPC command. +type SignMessageWithPrivKeyCmd struct { + PrivKey string // base 58 Wallet Import format private key + Message string // Message to sign +} + +// NewSignMessageWithPrivKey returns a new instance which can be used to issue a +// signmessagewithprivkey JSON-RPC command. +// +// The first parameter is a private key in base 58 Wallet Import format. +// The second parameter is the message to sign. +func NewSignMessageWithPrivKey(privKey, message string) *SignMessageWithPrivKeyCmd { + return &SignMessageWithPrivKeyCmd{ + PrivKey: privKey, + Message: message, + } +} + // StopCmd defines the stop JSON-RPC command. type StopCmd struct{} @@ -971,6 +989,7 @@ func init() { MustRegisterCmd("searchrawtransactions", (*SearchRawTransactionsCmd)(nil), flags) MustRegisterCmd("sendrawtransaction", (*SendRawTransactionCmd)(nil), flags) MustRegisterCmd("setgenerate", (*SetGenerateCmd)(nil), flags) + MustRegisterCmd("signmessagewithprivkey", (*SignMessageWithPrivKeyCmd)(nil), flags) MustRegisterCmd("stop", (*StopCmd)(nil), flags) MustRegisterCmd("submitblock", (*SubmitBlockCmd)(nil), flags) MustRegisterCmd("uptime", (*UptimeCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 9087135d7e..b510b5ec21 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1186,6 +1186,20 @@ func TestChainSvrCmds(t *testing.T) { GenProcLimit: btcjson.Int(6), }, }, + { + name: "signmessagewithprivkey", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("signmessagewithprivkey", "5Hue", "Hey") + }, + staticCmd: func() interface{} { + return btcjson.NewSignMessageWithPrivKey("5Hue", "Hey") + }, + marshalled: `{"jsonrpc":"1.0","method":"signmessagewithprivkey","params":["5Hue","Hey"],"id":1}`, + unmarshalled: &btcjson.SignMessageWithPrivKeyCmd{ + PrivKey: "5Hue", + Message: "Hey", + }, + }, { name: "stop", newCmd: func() (interface{}, error) { diff --git a/rpcserver.go b/rpcserver.go index aa154dd0e1..7e00004123 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -127,52 +127,53 @@ type commandHandler func(*rpcServer, interface{}, <-chan struct{}) (interface{}, // a dependency loop. var rpcHandlers map[string]commandHandler var rpcHandlersBeforeInit = map[string]commandHandler{ - "addnode": handleAddNode, - "createrawtransaction": handleCreateRawTransaction, - "debuglevel": handleDebugLevel, - "decoderawtransaction": handleDecodeRawTransaction, - "decodescript": handleDecodeScript, - "estimatefee": handleEstimateFee, - "generate": handleGenerate, - "getaddednodeinfo": handleGetAddedNodeInfo, - "getbestblock": handleGetBestBlock, - "getbestblockhash": handleGetBestBlockHash, - "getblock": handleGetBlock, - "getblockchaininfo": handleGetBlockChainInfo, - "getblockcount": handleGetBlockCount, - "getblockhash": handleGetBlockHash, - "getblockheader": handleGetBlockHeader, - "getblocktemplate": handleGetBlockTemplate, - "getcfilter": handleGetCFilter, - "getcfilterheader": handleGetCFilterHeader, - "getconnectioncount": handleGetConnectionCount, - "getcurrentnet": handleGetCurrentNet, - "getdifficulty": handleGetDifficulty, - "getgenerate": handleGetGenerate, - "gethashespersec": handleGetHashesPerSec, - "getheaders": handleGetHeaders, - "getinfo": handleGetInfo, - "getmempoolinfo": handleGetMempoolInfo, - "getmininginfo": handleGetMiningInfo, - "getnettotals": handleGetNetTotals, - "getnetworkhashps": handleGetNetworkHashPS, - "getpeerinfo": handleGetPeerInfo, - "getrawmempool": handleGetRawMempool, - "getrawtransaction": handleGetRawTransaction, - "gettxout": handleGetTxOut, - "help": handleHelp, - "node": handleNode, - "ping": handlePing, - "searchrawtransactions": handleSearchRawTransactions, - "sendrawtransaction": handleSendRawTransaction, - "setgenerate": handleSetGenerate, - "stop": handleStop, - "submitblock": handleSubmitBlock, - "uptime": handleUptime, - "validateaddress": handleValidateAddress, - "verifychain": handleVerifyChain, - "verifymessage": handleVerifyMessage, - "version": handleVersion, + "addnode": handleAddNode, + "createrawtransaction": handleCreateRawTransaction, + "debuglevel": handleDebugLevel, + "decoderawtransaction": handleDecodeRawTransaction, + "decodescript": handleDecodeScript, + "estimatefee": handleEstimateFee, + "generate": handleGenerate, + "getaddednodeinfo": handleGetAddedNodeInfo, + "getbestblock": handleGetBestBlock, + "getbestblockhash": handleGetBestBlockHash, + "getblock": handleGetBlock, + "getblockchaininfo": handleGetBlockChainInfo, + "getblockcount": handleGetBlockCount, + "getblockhash": handleGetBlockHash, + "getblockheader": handleGetBlockHeader, + "getblocktemplate": handleGetBlockTemplate, + "getcfilter": handleGetCFilter, + "getcfilterheader": handleGetCFilterHeader, + "getconnectioncount": handleGetConnectionCount, + "getcurrentnet": handleGetCurrentNet, + "getdifficulty": handleGetDifficulty, + "getgenerate": handleGetGenerate, + "gethashespersec": handleGetHashesPerSec, + "getheaders": handleGetHeaders, + "getinfo": handleGetInfo, + "getmempoolinfo": handleGetMempoolInfo, + "getmininginfo": handleGetMiningInfo, + "getnettotals": handleGetNetTotals, + "getnetworkhashps": handleGetNetworkHashPS, + "getpeerinfo": handleGetPeerInfo, + "getrawmempool": handleGetRawMempool, + "getrawtransaction": handleGetRawTransaction, + "gettxout": handleGetTxOut, + "help": handleHelp, + "node": handleNode, + "ping": handlePing, + "searchrawtransactions": handleSearchRawTransactions, + "sendrawtransaction": handleSendRawTransaction, + "setgenerate": handleSetGenerate, + "signmessagewithprivkey": handleSignMessageWithPrivKey, + "stop": handleStop, + "submitblock": handleSubmitBlock, + "uptime": handleUptime, + "validateaddress": handleValidateAddress, + "verifychain": handleVerifyChain, + "verifymessage": handleVerifyMessage, + "version": handleVersion, } // list of commands that we recognize, but for which btcd has no support because @@ -3435,6 +3436,52 @@ func handleSetGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return nil, nil } +// Text used to signify that a signed message follows and to prevent +// inadvertently signing a transaction. +const messageSignatureHeader = "Bitcoin Signed Message:\n" + +// handleSignMessageWithPrivKey implements the signmessagewithprivkey command. +func handleSignMessageWithPrivKey(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.SignMessageWithPrivKeyCmd) + + wif, err := btcutil.DecodeWIF(c.PrivKey) + if err != nil { + message := "Invalid private key" + switch err { + case btcutil.ErrMalformedPrivateKey: + message = "Malformed private key" + case btcutil.ErrChecksumMismatch: + message = "Private key checksum mismatch" + } + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidAddressOrKey, + Message: message, + } + } + if !wif.IsForNet(s.cfg.ChainParams) { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidAddressOrKey, + Message: "Private key for wrong network", + } + } + + var buf bytes.Buffer + wire.WriteVarString(&buf, 0, messageSignatureHeader) + wire.WriteVarString(&buf, 0, c.Message) + messageHash := chainhash.DoubleHashB(buf.Bytes()) + + sig, err := btcec.SignCompact(btcec.S256(), wif.PrivKey, + messageHash, wif.CompressPubKey) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidAddressOrKey, + Message: "Sign failed", + } + } + + return base64.StdEncoding.EncodeToString(sig), nil +} + // handleStop implements the stop command. func handleStop(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { select { @@ -3615,7 +3662,7 @@ func handleVerifyMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{ // Validate the signature - this just shows that it was valid at all. // we will compare it with the key next. var buf bytes.Buffer - wire.WriteVarString(&buf, 0, "Bitcoin Signed Message:\n") + wire.WriteVarString(&buf, 0, messageSignatureHeader) wire.WriteVarString(&buf, 0, c.Message) expectedMessageHash := chainhash.DoubleHashB(buf.Bytes()) pk, wasCompressed, err := btcec.RecoverCompact(btcec.S256(), sig, diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 9299f3e49d..bd0f8fd7ff 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -559,6 +559,12 @@ var helpDescsEnUS = map[string]string{ "setgenerate-generate": "Use true to enable generation, false to disable it", "setgenerate-genproclimit": "The number of processors (cores) to limit generation to or -1 for default", + // SignMessageWithPrivKeyCmd help. + "signmessagewithprivkey--synopsis": "Sign a message with the private key of an address", + "signmessagewithprivkey-privkey": "The private key to sign the message with", + "signmessagewithprivkey-message": "The message to create a signature of", + "signmessagewithprivkey--result0": "The signature of the message encoded in base 64", + // StopCmd help. "stop--synopsis": "Shutdown btcd.", "stop--result0": "The string 'btcd stopping.'", @@ -691,52 +697,53 @@ var helpDescsEnUS = map[string]string{ // This information is used to generate the help. Each result type must be a // pointer to the type (or nil to indicate no return value). var rpcResultTypes = map[string][]interface{}{ - "addnode": nil, - "createrawtransaction": {(*string)(nil)}, - "debuglevel": {(*string)(nil), (*string)(nil)}, - "decoderawtransaction": {(*btcjson.TxRawDecodeResult)(nil)}, - "decodescript": {(*btcjson.DecodeScriptResult)(nil)}, - "estimatefee": {(*float64)(nil)}, - "generate": {(*[]string)(nil)}, - "getaddednodeinfo": {(*[]string)(nil), (*[]btcjson.GetAddedNodeInfoResult)(nil)}, - "getbestblock": {(*btcjson.GetBestBlockResult)(nil)}, - "getbestblockhash": {(*string)(nil)}, - "getblock": {(*string)(nil), (*btcjson.GetBlockVerboseResult)(nil)}, - "getblockcount": {(*int64)(nil)}, - "getblockhash": {(*string)(nil)}, - "getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)}, - "getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil}, - "getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)}, - "getcfilter": {(*string)(nil)}, - "getcfilterheader": {(*string)(nil)}, - "getconnectioncount": {(*int32)(nil)}, - "getcurrentnet": {(*uint32)(nil)}, - "getdifficulty": {(*float64)(nil)}, - "getgenerate": {(*bool)(nil)}, - "gethashespersec": {(*float64)(nil)}, - "getheaders": {(*[]string)(nil)}, - "getinfo": {(*btcjson.InfoChainResult)(nil)}, - "getmempoolinfo": {(*btcjson.GetMempoolInfoResult)(nil)}, - "getmininginfo": {(*btcjson.GetMiningInfoResult)(nil)}, - "getnettotals": {(*btcjson.GetNetTotalsResult)(nil)}, - "getnetworkhashps": {(*int64)(nil)}, - "getpeerinfo": {(*[]btcjson.GetPeerInfoResult)(nil)}, - "getrawmempool": {(*[]string)(nil), (*btcjson.GetRawMempoolVerboseResult)(nil)}, - "getrawtransaction": {(*string)(nil), (*btcjson.TxRawResult)(nil)}, - "gettxout": {(*btcjson.GetTxOutResult)(nil)}, - "node": nil, - "help": {(*string)(nil), (*string)(nil)}, - "ping": nil, - "searchrawtransactions": {(*string)(nil), (*[]btcjson.SearchRawTransactionsResult)(nil)}, - "sendrawtransaction": {(*string)(nil)}, - "setgenerate": nil, - "stop": {(*string)(nil)}, - "submitblock": {nil, (*string)(nil)}, - "uptime": {(*int64)(nil)}, - "validateaddress": {(*btcjson.ValidateAddressChainResult)(nil)}, - "verifychain": {(*bool)(nil)}, - "verifymessage": {(*bool)(nil)}, - "version": {(*map[string]btcjson.VersionResult)(nil)}, + "addnode": nil, + "createrawtransaction": {(*string)(nil)}, + "debuglevel": {(*string)(nil), (*string)(nil)}, + "decoderawtransaction": {(*btcjson.TxRawDecodeResult)(nil)}, + "decodescript": {(*btcjson.DecodeScriptResult)(nil)}, + "estimatefee": {(*float64)(nil)}, + "generate": {(*[]string)(nil)}, + "getaddednodeinfo": {(*[]string)(nil), (*[]btcjson.GetAddedNodeInfoResult)(nil)}, + "getbestblock": {(*btcjson.GetBestBlockResult)(nil)}, + "getbestblockhash": {(*string)(nil)}, + "getblock": {(*string)(nil), (*btcjson.GetBlockVerboseResult)(nil)}, + "getblockcount": {(*int64)(nil)}, + "getblockhash": {(*string)(nil)}, + "getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)}, + "getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil}, + "getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)}, + "getcfilter": {(*string)(nil)}, + "getcfilterheader": {(*string)(nil)}, + "getconnectioncount": {(*int32)(nil)}, + "getcurrentnet": {(*uint32)(nil)}, + "getdifficulty": {(*float64)(nil)}, + "getgenerate": {(*bool)(nil)}, + "gethashespersec": {(*float64)(nil)}, + "getheaders": {(*[]string)(nil)}, + "getinfo": {(*btcjson.InfoChainResult)(nil)}, + "getmempoolinfo": {(*btcjson.GetMempoolInfoResult)(nil)}, + "getmininginfo": {(*btcjson.GetMiningInfoResult)(nil)}, + "getnettotals": {(*btcjson.GetNetTotalsResult)(nil)}, + "getnetworkhashps": {(*int64)(nil)}, + "getpeerinfo": {(*[]btcjson.GetPeerInfoResult)(nil)}, + "getrawmempool": {(*[]string)(nil), (*btcjson.GetRawMempoolVerboseResult)(nil)}, + "getrawtransaction": {(*string)(nil), (*btcjson.TxRawResult)(nil)}, + "gettxout": {(*btcjson.GetTxOutResult)(nil)}, + "node": nil, + "help": {(*string)(nil), (*string)(nil)}, + "ping": nil, + "searchrawtransactions": {(*string)(nil), (*[]btcjson.SearchRawTransactionsResult)(nil)}, + "sendrawtransaction": {(*string)(nil)}, + "setgenerate": nil, + "signmessagewithprivkey": {(*string)(nil)}, + "stop": {(*string)(nil)}, + "submitblock": {nil, (*string)(nil)}, + "uptime": {(*int64)(nil)}, + "validateaddress": {(*btcjson.ValidateAddressChainResult)(nil)}, + "verifychain": {(*bool)(nil)}, + "verifymessage": {(*bool)(nil)}, + "version": {(*map[string]btcjson.VersionResult)(nil)}, // Websocket commands. "loadtxfilter": nil, From fffe4a909b895f97f75e343d50387f053d8e1f1c Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 24 Aug 2020 20:53:41 +0200 Subject: [PATCH 0378/1056] rpcclient: Implement importmulti JSON-RPC client command --- btcjson/walletsvrcmds.go | 208 ++++++++++++++++++++++++++++ btcjson/walletsvrcmds_test.go | 252 ++++++++++++++++++++++++++++++++++ btcjson/walletsvrresults.go | 11 ++ rpcclient/example_test.go | 52 +++++-- rpcclient/wallet.go | 38 +++++ 5 files changed, 550 insertions(+), 11 deletions(-) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index be1a67fbf0..a2c7398827 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -7,6 +7,11 @@ package btcjson +import ( + "encoding/json" + "fmt" +) + // AddMultisigAddressCmd defines the addmutisigaddress JSON-RPC command. type AddMultisigAddressCmd struct { NRequired int @@ -686,6 +691,208 @@ func NewWalletPassphraseChangeCmd(oldPassphrase, newPassphrase string) *WalletPa } } +// TimestampOrNow defines a type to represent a timestamp value in seconds, +// since epoch. +// +// The value can either be a integer, or the string "now". +// +// NOTE: Interpretation of the timestamp value depends upon the specific +// JSON-RPC command, where it is used. +type TimestampOrNow struct { + Value interface{} +} + +// MarshalJSON implements the json.Marshaler interface for TimestampOrNow +func (t TimestampOrNow) MarshalJSON() ([]byte, error) { + return json.Marshal(t.Value) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for TimestampOrNow +func (t *TimestampOrNow) UnmarshalJSON(data []byte) error { + var unmarshalled interface{} + if err := json.Unmarshal(data, &unmarshalled); err != nil { + return err + } + + switch v := unmarshalled.(type) { + case float64: + t.Value = int(v) + case string: + if v != "now" { + return fmt.Errorf("invalid timestamp value: %v", unmarshalled) + } + t.Value = v + default: + return fmt.Errorf("invalid timestamp value: %v", unmarshalled) + } + return nil +} + +// ScriptPubKeyAddress represents an address, to be used in conjunction with +// ScriptPubKey. +type ScriptPubKeyAddress struct { + Address string `json:"address"` +} + +// ScriptPubKey represents a script (as a string) or an address +// (as a ScriptPubKeyAddress). +type ScriptPubKey struct { + Value interface{} +} + +// MarshalJSON implements the json.Marshaler interface for ScriptPubKey +func (s ScriptPubKey) MarshalJSON() ([]byte, error) { + return json.Marshal(s.Value) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for ScriptPubKey +func (s *ScriptPubKey) UnmarshalJSON(data []byte) error { + var unmarshalled interface{} + if err := json.Unmarshal(data, &unmarshalled); err != nil { + return err + } + + switch v := unmarshalled.(type) { + case string: + s.Value = v + case map[string]interface{}: + s.Value = ScriptPubKeyAddress{Address: v["address"].(string)} + default: + return fmt.Errorf("invalid scriptPubKey value: %v", unmarshalled) + } + return nil +} + +// DescriptorRange specifies the limits of a ranged Descriptor. +// +// Descriptors are typically ranged when specified in the form of generic HD +// chain paths. +// Example of a ranged descriptor: pkh(tpub.../*) +// +// The value can be an int to specify the end of the range, or the range +// itself, as []int{begin, end}. +type DescriptorRange struct { + Value interface{} +} + +// MarshalJSON implements the json.Marshaler interface for DescriptorRange +func (r DescriptorRange) MarshalJSON() ([]byte, error) { + return json.Marshal(r.Value) +} + +// UnmarshalJSON implements the json.Unmarshaler interface for DescriptorRange +func (r *DescriptorRange) UnmarshalJSON(data []byte) error { + var unmarshalled interface{} + if err := json.Unmarshal(data, &unmarshalled); err != nil { + return err + } + + switch v := unmarshalled.(type) { + case float64: + r.Value = int(v) + case []interface{}: + if len(v) != 2 { + return fmt.Errorf("expected [begin,end] integer range, got: %v", unmarshalled) + } + r.Value = []int{ + int(v[0].(float64)), + int(v[1].(float64)), + } + default: + return fmt.Errorf("invalid descriptor range value: %v", unmarshalled) + } + return nil +} + +// ImportMultiRequest defines the request struct to be passed to the +// ImportMultiCmd, as an array. +type ImportMultiRequest struct { + // Descriptor to import, in canonical form. If using Descriptor, do not + // also provide ScriptPubKey, RedeemScript, WitnessScript, PubKeys, or Keys. + Descriptor *string `json:"desc,omitempty"` + + // Script/address to import. Should not be provided if using Descriptor. + ScriptPubKey *ScriptPubKey `json:"scriptPubKey,omitempty"` + + // Creation time of the key in seconds since epoch (Jan 1 1970 GMT), or + // the string "now" to substitute the current synced blockchain time. + // + // The timestamp of the oldest key will determine how far back blockchain + // rescans need to begin for missing wallet transactions. + // + // Specifying "now" bypasses scanning. Useful for keys that are known to + // never have been used. + // + // Specifying 0 scans the entire blockchain. + Timestamp TimestampOrNow `json:"timestamp"` + + // Allowed only if the ScriptPubKey is a P2SH or P2SH-P2WSH + // address/scriptPubKey. + RedeemScript *string `json:"redeemscript,omitempty"` + + // Allowed only if the ScriptPubKey is a P2SH-P2WSH or P2WSH + // address/scriptPubKey. + WitnessScript *string `json:"witnessscript,omitempty"` + + // Array of strings giving pubkeys to import. They must occur in P2PKH or + // P2WPKH scripts. They are not required when the private key is also + // provided (see Keys). + PubKeys *[]string `json:"pubkeys,omitempty"` + + // Array of strings giving private keys to import. The corresponding + // public keys must occur in the output or RedeemScript. + Keys *[]string `json:"keys,omitempty"` + + // If the provided Descriptor is ranged, this specifies the end + // (as an int) or the range (as []int{begin, end}) to import. + Range *DescriptorRange `json:"range,omitempty"` + + // States whether matching outputs should be treated as not incoming + // payments (also known as change). + Internal *bool `json:"internal,omitempty"` + + // States whether matching outputs should be considered watchonly. + // + // If an address/script is imported without all of the private keys + // required to spend from that address, set this field to true. + // + // If all the private keys are provided and the address/script is + // spendable, set this field to false. + WatchOnly *bool `json:"watchonly,omitempty"` + + // Label to assign to the address. Only allowed when Internal is false. + Label *string `json:"label,omitempty"` + + // States whether imported public keys should be added to the keypool for + // when users request new addresses. Only allowed when wallet private keys + // are disabled. + KeyPool *bool `json:"keypool,omitempty"` +} + +// ImportMultiRequest defines the options struct, provided to the +// ImportMultiCmd as a pointer argument. +type ImportMultiOptions struct { + Rescan bool `json:"rescan"` // Rescan the blockchain after all imports +} + +// ImportMultiCmd defines the importmulti JSON-RPC command. +type ImportMultiCmd struct { + Requests []ImportMultiRequest + Options *ImportMultiOptions +} + +// NewImportMultiCmd returns a new instance which can be used to issue +// an importmulti JSON-RPC command. +// +// The parameters which are pointers indicate they are optional. Passing nil +// for optional parameters will use the default value. +func NewImportMultiCmd(requests []ImportMultiRequest, options *ImportMultiOptions) *ImportMultiCmd { + return &ImportMultiCmd{ + Requests: requests, + Options: options, + } +} + func init() { // The commands in this file are only usable with a wallet server. flags := UFWalletOnly @@ -709,6 +916,7 @@ func init() { MustRegisterCmd("getreceivedbyaddress", (*GetReceivedByAddressCmd)(nil), flags) MustRegisterCmd("gettransaction", (*GetTransactionCmd)(nil), flags) MustRegisterCmd("getwalletinfo", (*GetWalletInfoCmd)(nil), flags) + MustRegisterCmd("importmulti", (*ImportMultiCmd)(nil), flags) MustRegisterCmd("importprivkey", (*ImportPrivKeyCmd)(nil), flags) MustRegisterCmd("keypoolrefill", (*KeyPoolRefillCmd)(nil), flags) MustRegisterCmd("listaccounts", (*ListAccountsCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 554a87413a..bc09588268 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -1243,6 +1243,258 @@ func TestWalletSvrCmds(t *testing.T) { NewPassphrase: "new", }, }, + { + name: "importmulti with descriptor + options", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "importmulti", + // Cannot use a native string, due to special types like timestamp. + []btcjson.ImportMultiRequest{ + {Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: 0}}, + }, + `{"rescan": true}`, + ) + }, + staticCmd: func() interface{} { + requests := []btcjson.ImportMultiRequest{ + {Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: 0}}, + } + options := btcjson.ImportMultiOptions{Rescan: true} + return btcjson.NewImportMultiCmd(requests, &options) + }, + marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0}],{"rescan":true}],"id":1}`, + unmarshalled: &btcjson.ImportMultiCmd{ + Requests: []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + }, + }, + Options: &btcjson.ImportMultiOptions{Rescan: true}, + }, + }, + { + name: "importmulti with descriptor + no options", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "importmulti", + // Cannot use a native string, due to special types like timestamp. + []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + WatchOnly: btcjson.Bool(false), + Internal: btcjson.Bool(true), + Label: btcjson.String("aaa"), + KeyPool: btcjson.Bool(false), + }, + }, + ) + }, + staticCmd: func() interface{} { + requests := []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + WatchOnly: btcjson.Bool(false), + Internal: btcjson.Bool(true), + Label: btcjson.String("aaa"), + KeyPool: btcjson.Bool(false), + }, + } + return btcjson.NewImportMultiCmd(requests, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"internal":true,"watchonly":false,"label":"aaa","keypool":false}]],"id":1}`, + unmarshalled: &btcjson.ImportMultiCmd{ + Requests: []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + WatchOnly: btcjson.Bool(false), + Internal: btcjson.Bool(true), + Label: btcjson.String("aaa"), + KeyPool: btcjson.Bool(false), + }, + }, + }, + }, + { + name: "importmulti with descriptor + string timestamp", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "importmulti", + // Cannot use a native string, due to special types like timestamp. + []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: "now"}, + }, + }, + ) + }, + staticCmd: func() interface{} { + requests := []btcjson.ImportMultiRequest{ + {Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: "now"}}, + } + return btcjson.NewImportMultiCmd(requests, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":"now"}]],"id":1}`, + unmarshalled: &btcjson.ImportMultiCmd{ + Requests: []btcjson.ImportMultiRequest{ + {Descriptor: btcjson.String("123"), Timestamp: btcjson.TimestampOrNow{Value: "now"}}, + }, + }, + }, + { + name: "importmulti with scriptPubKey script", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "importmulti", + // Cannot use a native string, due to special types like timestamp and scriptPubKey + []btcjson.ImportMultiRequest{ + { + ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"}, + RedeemScript: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + PubKeys: &[]string{"aaa"}, + }, + }, + ) + }, + staticCmd: func() interface{} { + requests := []btcjson.ImportMultiRequest{ + { + ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"}, + RedeemScript: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + PubKeys: &[]string{"aaa"}, + }, + } + return btcjson.NewImportMultiCmd(requests, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"scriptPubKey":"script","timestamp":0,"redeemscript":"123","pubkeys":["aaa"]}]],"id":1}`, + unmarshalled: &btcjson.ImportMultiCmd{ + Requests: []btcjson.ImportMultiRequest{ + { + ScriptPubKey: &btcjson.ScriptPubKey{Value: "script"}, + RedeemScript: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + PubKeys: &[]string{"aaa"}, + }, + }, + }, + }, + { + name: "importmulti with scriptPubKey address", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "importmulti", + // Cannot use a native string, due to special types like timestamp and scriptPubKey + []btcjson.ImportMultiRequest{ + { + ScriptPubKey: &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}}, + WitnessScript: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Keys: &[]string{"aaa"}, + }, + }, + ) + }, + staticCmd: func() interface{} { + requests := []btcjson.ImportMultiRequest{ + { + ScriptPubKey: &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}}, + WitnessScript: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Keys: &[]string{"aaa"}, + }, + } + return btcjson.NewImportMultiCmd(requests, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"scriptPubKey":{"address":"addr"},"timestamp":0,"witnessscript":"123","keys":["aaa"]}]],"id":1}`, + unmarshalled: &btcjson.ImportMultiCmd{ + Requests: []btcjson.ImportMultiRequest{ + { + ScriptPubKey: &btcjson.ScriptPubKey{Value: btcjson.ScriptPubKeyAddress{Address: "addr"}}, + WitnessScript: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Keys: &[]string{"aaa"}, + }, + }, + }, + }, + { + name: "importmulti with ranged (int) descriptor", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "importmulti", + // Cannot use a native string, due to special types like timestamp. + []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Range: &btcjson.DescriptorRange{Value: 7}, + }, + }, + ) + }, + staticCmd: func() interface{} { + requests := []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Range: &btcjson.DescriptorRange{Value: 7}, + }, + } + return btcjson.NewImportMultiCmd(requests, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"range":7}]],"id":1}`, + unmarshalled: &btcjson.ImportMultiCmd{ + Requests: []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Range: &btcjson.DescriptorRange{Value: 7}, + }, + }, + }, + }, + { + name: "importmulti with ranged (slice) descriptor", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "importmulti", + // Cannot use a native string, due to special types like timestamp. + []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Range: &btcjson.DescriptorRange{Value: []int{1, 7}}, + }, + }, + ) + }, + staticCmd: func() interface{} { + requests := []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Range: &btcjson.DescriptorRange{Value: []int{1, 7}}, + }, + } + return btcjson.NewImportMultiCmd(requests, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"importmulti","params":[[{"desc":"123","timestamp":0,"range":[1,7]}]],"id":1}`, + unmarshalled: &btcjson.ImportMultiCmd{ + Requests: []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String("123"), + Timestamp: btcjson.TimestampOrNow{Value: 0}, + Range: &btcjson.DescriptorRange{Value: []int{1, 7}}, + }, + }, + }, + }, } t.Logf("Running %d tests", len(tests)) diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index 6e69ed9066..d860eceb39 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -173,3 +173,14 @@ type GetBalancesResult struct { Mine BalanceDetailsResult `json:"mine"` WatchOnly *BalanceDetailsResult `json:"watchonly"` } + +// ImportMultiResults is a slice that models the result of the importmulti command. +// +// Each item in the slice contains the execution result corresponding to the input +// requests of type btcjson.ImportMultiRequest, passed to the ImportMulti[Async] +// function. +type ImportMultiResults []struct { + Success bool `json:"success"` + Error *RPCError `json:"error,omitempty"` + Warnings *[]string `json:"warnings,omitempty"` +} diff --git a/rpcclient/example_test.go b/rpcclient/example_test.go index c2c5290596..6083e115ec 100644 --- a/rpcclient/example_test.go +++ b/rpcclient/example_test.go @@ -2,30 +2,60 @@ package rpcclient import ( "fmt" + + "github.com/btcsuite/btcd/btcjson" ) +var connCfg = &ConnConfig{ + Host: "localhost:8332", + User: "yourrpcuser", + Pass: "yourrpcpass", + HTTPPostMode: true, + DisableTLS: true, +} + func ExampleClient_GetDescriptorInfo() { - connCfg := &ConnConfig{ - Host: "localhost:8332", - User: "yourrpcuser", - Pass: "yourrpcpass", - HTTPPostMode: true, - DisableTLS: true, - } client, err := New(connCfg, nil) if err != nil { - log.Error(err) - return + panic(err) } defer client.Shutdown() descriptorInfo, err := client.GetDescriptorInfo( "wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)") if err != nil { - log.Error(err) - return + panic(err) } fmt.Printf("%+v\n", descriptorInfo) // &{Descriptor:wpkh([d34db33f/84'/0'/0']0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)#n9g43y4k Checksum:qwlqgth7 IsRange:false IsSolvable:true HasPrivateKeys:false} } + +func ExampleClient_ImportMulti() { + client, err := New(connCfg, nil) + if err != nil { + panic(err) + } + defer client.Shutdown() + + requests := []btcjson.ImportMultiRequest{ + { + Descriptor: btcjson.String( + "pkh([f34db33f/44'/0'/0']xpub6Cc939fyHvfB9pPLWd3bSyyQFvgKbwhidca49jGCM5Hz5ypEPGf9JVXB4NBuUfPgoHnMjN6oNgdC9KRqM11RZtL8QLW6rFKziNwHDYhZ6Kx/0/*)#ed7px9nu"), + Range: &btcjson.DescriptorRange{Value: []int{0, 100}}, + Timestamp: btcjson.TimestampOrNow{Value: 0}, // scan from genesis + WatchOnly: btcjson.Bool(true), + KeyPool: btcjson.Bool(false), + Internal: btcjson.Bool(false), + }, + } + opts := &btcjson.ImportMultiOptions{Rescan: true} + + resp, err := client.ImportMulti(requests, opts) + if err != nil { + panic(err) + } + + fmt.Println(resp[0].Success) + // true +} diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 37bf9471e0..d4069aad62 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2203,6 +2203,44 @@ func (c *Client) ImportAddressRescan(address string, account string, rescan bool return c.ImportAddressRescanAsync(address, account, rescan).Receive() } +// FutureImportMultiResult is a future promise to deliver the result of an +// ImportMultiAsync RPC invocation (or an applicable error). +type FutureImportMultiResult chan *response + +// Receive waits for the response promised by the future and returns the result +// of importing multiple addresses/scripts. +func (r FutureImportMultiResult) Receive() (btcjson.ImportMultiResults, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var importMultiResults btcjson.ImportMultiResults + err = json.Unmarshal(res, &importMultiResults) + if err != nil { + return nil, err + } + return importMultiResults, nil +} + +// ImportMultiAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See ImportMulti for the blocking version and more details. +func (c *Client) ImportMultiAsync(requests []btcjson.ImportMultiRequest, options *btcjson.ImportMultiOptions) FutureImportMultiResult { + cmd := btcjson.NewImportMultiCmd(requests, options) + return c.sendCmd(cmd) +} + +// ImportMulti imports addresses/scripts, optionally rescanning the blockchain +// from the earliest creation time of the imported scripts. +// +// See btcjson.ImportMultiRequest for details on the requests parameter. +func (c *Client) ImportMulti(requests []btcjson.ImportMultiRequest, options *btcjson.ImportMultiOptions) (btcjson.ImportMultiResults, error) { + return c.ImportMultiAsync(requests, options).Receive() +} + // FutureImportPrivKeyResult is a future promise to deliver the result of an // ImportPrivKeyAsync RPC invocation (or an applicable error). type FutureImportPrivKeyResult chan *response From 90a5c7997c9a4c38e850fec3559601d838be37b2 Mon Sep 17 00:00:00 2001 From: Christian Lehmann Date: Thu, 5 Sep 2019 15:37:43 +0200 Subject: [PATCH 0379/1056] Add Dockerfile to build and run btcd on Docker. --- Dockerfile | 40 +++++++++++ docs/README.md | 9 +++ docs/using_docker.md | 160 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 Dockerfile create mode 100644 docs/using_docker.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..7cb47e0138 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +# This Dockerfile builds btcd from source and creates a small (55 MB) docker container based on alpine linux. +# +# Clone this repository and run the following command to build and tag a fresh btcd amd64 container: +# +# docker build . -t yourregistry/btcd +# +# You can use the following command to buid an arm64v8 container: +# +# docker build . -t yourregistry/btcd --build-arg ARCH=arm64v8 +# +# For more information how to use this docker image visit: +# https://github.com/btcsuite/btcd/tree/master/docs +# +# 8333 Mainnet Bitcoin peer-to-peer port +# 8334 Mainet RPC port + +ARG ARCH=amd64 + +FROM golang:1.14-alpine3.12 AS build-container + +ARG ARCH +ENV GO111MODULE=on + +ADD . /app +WORKDIR /app +RUN set -ex \ + && if [ "${ARCH}" = "amd64" ]; then export GOARCH=amd64; fi \ + && if [ "${ARCH}" = "arm64v8" ]; then export GOARCH=arm64; fi \ + && echo "Compiling for $GOARCH" \ + && go install -v . ./cmd/... + +FROM $ARCH/alpine:3.12 + +COPY --from=build-container /go/bin /bin + +VOLUME ["/root/.btcd"] + +EXPOSE 8333 8334 + +ENTRYPOINT ["btcd"] diff --git a/docs/README.md b/docs/README.md index afc58a631e..15d7e739f9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,6 +20,7 @@ 1. [Code Contribution Guidelines](#ContributionGuidelines) 2. [JSON-RPC Reference](#JSONRPCReference) 3. [The btcsuite Bitcoin-related Go Packages](#GoPackages) +6. [Using Docker](#Docker)
@@ -294,3 +295,11 @@ information. specific hash algorithm to be abstracted. * [connmgr](https://github.com/btcsuite/btcd/tree/master/connmgr) - Package connmgr implements a generic Bitcoin network connection manager. + + + +### 6. Using Docker + +You can run btcd in a Docker container, without the need to compile the source by yourself. Visit the [Using Docker](https://github.com/btcsuite/btcd/tree/master/docs/using_docker.md) page for more inrormation and examples. + +* [Using Docker](https://github.com/btcsuite/btcd/tree/master/docs/using_docker.md) details page diff --git a/docs/using_docker.md b/docs/using_docker.md new file mode 100644 index 0000000000..0809abc1c8 --- /dev/null +++ b/docs/using_docker.md @@ -0,0 +1,160 @@ +# Using Docker + +- [Using Docker](#using-docker) + - [Introduction](#introduction) + - [Docker volumes](#docker-volumes) + - [Known error messages when starting the btcd container](#known-error-messages-when-starting-the-btcd-container) + - [Examples](#examples) + - [Preamble](#preamble) + - [Full node without RPC port](#full-node-without-rpc-port) + - [Full node with RPC port](#full-node-with-rpc-port) + - [Full node with RPC port running on TESTNET](#full-node-with-rpc-port-running-on-testnet) + +## Introduction + +With Docker you can easily set up *btcd* to run your Bitcoin full node. You can find the official *btcd* Docker images on Docker Hub [btcsuite/btcd](https://hub.docker.com/r/btcsuite/btcd). The Docker source file of this image is located at [Dockerfile](https://github.com/btcsuite/btcd/blob/master/Dockerfile). + +This documentation focuses on running Docker container with *docker-compose.yml* files. These files are better to read and you can use them as a template for your own use. For more information about Docker and Docker compose visit the official [Docker documentation](https://docs.docker.com/). + +## Docker volumes + +**Special diskspace hint**: The following examples are using a Docker managed volume. The volume is named *btcd-data* This will use a lot of disk space, because it contains the full Bitcoin blockchain. Please make yourself familiar with [Docker volumes](https://docs.docker.com/storage/volumes/). + +The *btcd-data* volume will be reused, if you upgrade your *docker-compose.yml* file. Keep in mind, that it is not automatically removed by Docker, if you delete the btcd container. If you don't need the volume anymore, please delete it manually with the command: + +```bash +docker volume ls +docker volume rm btcd-data +``` + +For binding a local folder to your *btcd* container please read the [Docker documentation](https://docs.docker.com/). The preferred way is to use a Docker managed volume. + +## Known error messages when starting the btcd container + +We pass all needed arguments to *btcd* as command line parameters in our *docker-compose.yml* file. It doesn't make sense to create a *btcd.conf* file. This would make things too complicated. Anyhow *btcd* will complain with following log messages when starting. These messages can be ignored: + +```bash +Error creating a default config file: open /sample-btcd.conf: no such file or directory +... +[WRN] BTCD: open /root/.btcd/btcd.conf: no such file or directory +``` + +## Examples + +### Preamble + +All following examples uses some defaults: + +- container_name: btcd + Name of the docker container that is be shown by e.g. ```docker ps -a``` + +- hostname: btcd **(very important to set a fixed name before first start)** + The internal hostname in the docker container. By default, docker is recreating the hostname every time you change the *docker-compose.yml* file. The default hostnames look like *ef00548d4fa5*. This is a problem when using the *btcd* RPC port. The RPC port is using a certificate to validate the hostname. If the hostname changes you need to recreate the certificate. To avoid this, you should set a fixed hostname before the first start. This ensures, that the docker volume is created with a certificate with this hostname. + +- restart: unless-stopped + Starts the *btcd* container when Docker starts, except that when the container is stopped (manually or otherwise), it is not restarted even after Docker restarts. + +To use the following examples create an empty directory. In this directory create a file named *docker-compose.yml*, copy and paste the example into the *docker-compose.yml* file and run it. + +```bash +mkdir ~/btcd-docker +cd ~/btcd-docker +touch docker-compose.yaml +nano docker-compose.yaml (use your favourite editor to edit the compose file) +docker-compose up (creates and starts a new btcd container) +``` + +With the following commands you can control *docker-compose*: + +```docker-compose up -d``` (creates and starts the container in background) + +```docker-compose down``` (stops and delete the container. **The docker volume btcd-data will not be deleted**) + +```docker-compose stop``` (stops the container) + +```docker-compose start``` (starts the container) + +```docker ps -a``` (list all running and stopped container) + +```docker volume ls``` (lists all docker volumes) + +```docker logs btcd``` (shows the log ) + +```docker-compose help``` (brings up some helpful information) + +### Full node without RPC port + +Let's start with an easy example. If you just want to create a full node without the need of using the RPC port, you can use the following example. This example will launch *btcd* and exposes only the default p2p port 8333 to the outside world: + +```yaml +version: "2" + +services: + btcd: + container_name: btcd + hostname: btcd + image: btcsuite/btcd:latest + restart: unless-stopped + volumes: + - btcd-data:/root/.btcd + ports: + - 8333:8333 + +volumes: + btcd-data: +``` + +### Full node with RPC port + +To use the RPC port of *btcd* you need to specify a *username* and a very strong *password*. If you want to connect to the RPC port from the internet, you need to expose port 8334(RPC) as well. + +```yaml +version: "2" + +services: + btcd: + container_name: btcd + hostname: btcd + image: btcsuite/btcd:latest + restart: unless-stopped + volumes: + - btcd-data:/root/.btcd + ports: + - 8333:8333 + - 8334:8334 + command: [ + "--rpcuser=[CHOOSE_A_USERNAME]", + "--rpcpass=[CREATE_A_VERY_HARD_PASSWORD]" + ] + +volumes: + btcd-data: +``` + +### Full node with RPC port running on TESTNET + +To run a node on testnet, you need to provide the *--testnet* argument. The ports for testnet are 18333 (p2p) and 18334 (RPC): + +```yaml +version: "2" + +services: + btcd: + container_name: btcd + hostname: btcd + image: btcsuite/btcd:latest + restart: unless-stopped + volumes: + - btcd-data:/root/.btcd + ports: + - 18333:18333 + - 18334:18334 + command: [ + "--testnet", + "--rpcuser=[CHOOSE_A_USERNAME]", + "--rpcpass=[CREATE_A_VERY_HARD_PASSWORD]" + ] + +volumes: + btcd-data: +``` From d13e907952ae818bc1c3abe1c011ae5f38f8fd18 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 27 Aug 2020 16:11:21 -0300 Subject: [PATCH 0380/1056] btcd: fix conversion of int to string failing in Go 1.15 --- upnp.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/upnp.go b/upnp.go index feb256d072..c74e4ed79a 100644 --- a/upnp.go +++ b/upnp.go @@ -36,6 +36,7 @@ import ( "bytes" "encoding/xml" "errors" + "fmt" "net" "net/http" "os" @@ -229,7 +230,7 @@ func getServiceURL(rootURL string) (url string, err error) { } defer r.Body.Close() if r.StatusCode >= 400 { - err = errors.New(string(r.StatusCode)) + err = errors.New(fmt.Sprint(r.StatusCode)) return } var root root From 35194e2dacf8c918abe77ac85ca220cc8a9fd1e6 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 27 Aug 2020 21:30:27 -0300 Subject: [PATCH 0381/1056] btcjson,wire: fix invalid use of string(x) to convert byte value --- btcjson/cmdparse_test.go | 2 +- wire/message.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/btcjson/cmdparse_test.go b/btcjson/cmdparse_test.go index 7c13a0bb44..dd951dcbd7 100644 --- a/btcjson/cmdparse_test.go +++ b/btcjson/cmdparse_test.go @@ -201,7 +201,7 @@ func TestAssignFieldErrors(t *testing.T) { }{ { name: "general incompatible int -> string", - dest: string(0), + dest: "\x00", src: int(0), err: btcjson.Error{ErrorCode: btcjson.ErrInvalidType}, }, diff --git a/wire/message.go b/wire/message.go index e937647702..fe45a11fb1 100644 --- a/wire/message.go +++ b/wire/message.go @@ -213,7 +213,7 @@ func readMessageHeader(r io.Reader) (int, *messageHeader, error) { readElements(hr, &hdr.magic, &command, &hdr.length, &hdr.checksum) // Strip trailing zeros from command string. - hdr.command = string(bytes.TrimRight(command[:], string(0))) + hdr.command = string(bytes.TrimRight(command[:], "\x00")) return n, &hdr, nil } From 355472b0f79a72d2445ed2f0d9e5e472b25814f4 Mon Sep 17 00:00:00 2001 From: Christian Lehmann Date: Mon, 9 Sep 2019 17:24:56 +0200 Subject: [PATCH 0382/1056] Major rework on documentation to make it compatible to readthedocs.org --- README.md | 2 +- docs/.gitignore | 1 + docs/Makefile | 20 ++ docs/README.md | 305 ------------------ docs/code_contribution_guidelines.md | 106 ++---- docs/conf.py | 77 +++++ docs/configuration.md | 190 +++++++++++ ...configure_peer_server_listen_interfaces.md | 43 --- .../configure_rpc_server_listen_interfaces.md | 47 --- docs/configuring_tor.md | 96 ++---- docs/contact.md | 15 + docs/controlling.md | 34 ++ docs/default_ports.md | 15 - docs/developer_resources.md | 37 +++ docs/index.md | 57 ++++ docs/installation.md | 76 +++++ docs/json_rpc_api.md | 3 +- docs/make.bat | 35 ++ docs/mining.md | 30 ++ docs/requirements.txt | 1 + docs/table_of_content.md | 13 + docs/update.md | 8 + docs/using_bootstrap_dat.md | 79 ----- docs/wallet.md | 5 + 24 files changed, 655 insertions(+), 640 deletions(-) create mode 100644 docs/.gitignore create mode 100644 docs/Makefile delete mode 100644 docs/README.md create mode 100644 docs/conf.py create mode 100644 docs/configuration.md delete mode 100644 docs/configure_peer_server_listen_interfaces.md delete mode 100644 docs/configure_rpc_server_listen_interfaces.md create mode 100644 docs/contact.md create mode 100644 docs/controlling.md delete mode 100644 docs/default_ports.md create mode 100644 docs/developer_resources.md create mode 100644 docs/index.md create mode 100644 docs/installation.md create mode 100644 docs/make.bat create mode 100644 docs/mining.md create mode 100644 docs/requirements.txt create mode 100644 docs/table_of_content.md create mode 100644 docs/update.md delete mode 100644 docs/using_bootstrap_dat.md create mode 100644 docs/wallet.md diff --git a/README.md b/README.md index 8c9d252ad4..352252dd16 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ transactions based on miner requirements ("standard" transactions). One key difference between btcd and Bitcoin Core is that btcd does *NOT* include wallet functionality and this was a very intentional design decision. See the -blog entry [here](https://blog.conformal.com/btcd-not-your-moms-bitcoin-daemon) +blog entry [here](https://web.archive.org/web/20171125143919/https://blog.conformal.com/btcd-not-your-moms-bitcoin-daemon) for more details. This means you can't actually make or receive payments directly with btcd. That functionality is provided by the [btcwallet](https://github.com/btcsuite/btcwallet) and diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000000..a485625d42 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +/_build diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000000..d4bb2cbb9e --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 15d7e739f9..0000000000 --- a/docs/README.md +++ /dev/null @@ -1,305 +0,0 @@ -### Table of Contents -1. [About](#About) -2. [Getting Started](#GettingStarted) - 1. [Installation](#Installation) - 1. [Windows](#WindowsInstallation) - 2. [Linux/BSD/MacOSX/POSIX](#PosixInstallation) - 1. [Gentoo Linux](#GentooInstallation) - 2. [Configuration](#Configuration) - 3. [Controlling and Querying btcd via btcctl](#BtcctlConfig) - 4. [Mining](#Mining) -3. [Help](#Help) - 1. [Startup](#Startup) - 1. [Using bootstrap.dat](#BootstrapDat) - 2. [Network Configuration](#NetworkConfig) - 3. [Wallet](#Wallet) -4. [Contact](#Contact) - 1. [IRC](#ContactIRC) - 2. [Mailing Lists](#MailingLists) -5. [Developer Resources](#DeveloperResources) - 1. [Code Contribution Guidelines](#ContributionGuidelines) - 2. [JSON-RPC Reference](#JSONRPCReference) - 3. [The btcsuite Bitcoin-related Go Packages](#GoPackages) -6. [Using Docker](#Docker) - - - -### 1. About - -btcd is a full node bitcoin implementation written in [Go](http://golang.org), -licensed under the [copyfree](http://www.copyfree.org) ISC License. - -This project is currently under active development and is in a Beta state. It -is extremely stable and has been in production use since October 2013. - -It properly downloads, validates, and serves the block chain using the exact -rules (including consensus bugs) for block acceptance as Bitcoin Core. We have -taken great care to avoid btcd causing a fork to the block chain. It includes a -full block validation testing framework which contains all of the 'official' -block acceptance tests (and some additional ones) that is run on every pull -request to help ensure it properly follows consensus. Also, it passes all of -the JSON test data in the Bitcoin Core code. - -It also properly relays newly mined blocks, maintains a transaction pool, and -relays individual transactions that have not yet made it into a block. It -ensures all individual transactions admitted to the pool follow the rules -required by the block chain and also includes more strict checks which filter -transactions based on miner requirements ("standard" transactions). - -One key difference between btcd and Bitcoin Core is that btcd does *NOT* include -wallet functionality and this was a very intentional design decision. See the -blog entry [here](https://web.archive.org/web/20171125143919/https://blog.conformal.com/btcd-not-your-moms-bitcoin-daemon) -for more details. This means you can't actually make or receive payments -directly with btcd. That functionality is provided by the -[btcwallet](https://github.com/btcsuite/btcwallet) and -[Paymetheus](https://github.com/btcsuite/Paymetheus) (Windows-only) projects -which are both under active development. - - - -### 2. Getting Started - - - -**2.1 Installation** - -The first step is to install btcd. See one of the following sections for -details on how to install on the supported operating systems. - - - -**2.1.1 Windows Installation**
- -* Install the MSI available at: https://github.com/btcsuite/btcd/releases -* Launch btcd from the Start Menu - -
- -**2.1.2 Linux/BSD/MacOSX/POSIX Installation** - - -- Install Go according to the installation instructions here: - http://golang.org/doc/install - -- Ensure Go was installed properly and is a supported version: - -```bash -$ go version -$ go env GOROOT GOPATH -``` - -NOTE: The `GOROOT` and `GOPATH` above must not be the same path. It is -recommended that `GOPATH` is set to a directory in your home directory such as -`~/goprojects` to avoid write permission issues. It is also recommended to add -`$GOPATH/bin` to your `PATH` at this point. - -- Run the following commands to obtain btcd, all dependencies, and install it: - -```bash -$ git clone https://github.com/btcsuite/btcd $GOPATH/src/github.com/btcsuite/btcd -$ cd $GOPATH/src/github.com/btcsuite/btcd -$ GO111MODULE=on go install -v . ./cmd/... -``` - -- btcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did - not already add the bin directory to your system path during Go installation, - we recommend you do so now. - -**Updating** - -- Run the following commands to update btcd, all dependencies, and install it: - -```bash -$ cd $GOPATH/src/github.com/btcsuite/btcd -$ git pull && GO111MODULE=on go install -v . ./cmd/... -``` - - - -**2.1.2.1 Gentoo Linux Installation** - -* Install Layman and enable the Bitcoin overlay. - * https://gitlab.com/bitcoin/gentoo -* Copy or symlink `/var/lib/layman/bitcoin/Documentation/package.keywords/btcd-live` to `/etc/portage/package.keywords/` -* Install btcd: `$ emerge net-p2p/btcd` - - - -**2.2 Configuration** - -btcd has a number of [configuration](http://godoc.org/github.com/btcsuite/btcd) -options, which can be viewed by running: `$ btcd --help`. - - - -**2.3 Controlling and Querying btcd via btcctl** - -btcctl is a command line utility that can be used to both control and query btcd -via [RPC](http://www.wikipedia.org/wiki/Remote_procedure_call). btcd does -**not** enable its RPC server by default; You must configure at minimum both an -RPC username and password or both an RPC limited username and password: - -* btcd.conf configuration file -``` -[Application Options] -rpcuser=myuser -rpcpass=SomeDecentp4ssw0rd -rpclimituser=mylimituser -rpclimitpass=Limitedp4ssw0rd -``` -* btcctl.conf configuration file -``` -[Application Options] -rpcuser=myuser -rpcpass=SomeDecentp4ssw0rd -``` -OR -``` -[Application Options] -rpclimituser=mylimituser -rpclimitpass=Limitedp4ssw0rd -``` -For a list of available options, run: `$ btcctl --help` - - - -**2.4 Mining** - -btcd supports the `getblocktemplate` RPC. -The limited user cannot access this RPC. - - -**1. Add the payment addresses with the `miningaddr` option.** - -``` -[Application Options] -rpcuser=myuser -rpcpass=SomeDecentp4ssw0rd -miningaddr=12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX -miningaddr=1M83ju3EChKYyysmM2FXtLNftbacagd8FR -``` - -**2. Add btcd's RPC TLS certificate to system Certificate Authority list.** - -`cgminer` uses [curl](http://curl.haxx.se/) to fetch data from the RPC server. -Since curl validates the certificate by default, we must install the `btcd` RPC -certificate into the default system Certificate Authority list. - -**Ubuntu** - -1. Copy rpc.cert to /usr/share/ca-certificates: `# cp /home/user/.btcd/rpc.cert /usr/share/ca-certificates/btcd.crt` -2. Add btcd.crt to /etc/ca-certificates.conf: `# echo btcd.crt >> /etc/ca-certificates.conf` -3. Update the CA certificate list: `# update-ca-certificates` - -**3. Set your mining software url to use https.** - -`$ cgminer -o https://127.0.0.1:8334 -u rpcuser -p rpcpassword` - - - -### 3. Help - - - -**3.1 Startup** - -Typically btcd will run and start downloading the block chain with no extra -configuration necessary, however, there is an optional method to use a -`bootstrap.dat` file that may speed up the initial block chain download process. - - - -**3.1.1 bootstrap.dat** - -* [Using bootstrap.dat](https://github.com/btcsuite/btcd/tree/master/docs/using_bootstrap_dat.md) - - - -**3.1.2 Network Configuration** - -* [What Ports Are Used by Default?](https://github.com/btcsuite/btcd/tree/master/docs/default_ports.md) -* [How To Listen on Specific Interfaces](https://github.com/btcsuite/btcd/tree/master/docs/configure_peer_server_listen_interfaces.md) -* [How To Configure RPC Server to Listen on Specific Interfaces](https://github.com/btcsuite/btcd/tree/master/docs/configure_rpc_server_listen_interfaces.md) -* [Configuring btcd with Tor](https://github.com/btcsuite/btcd/tree/master/docs/configuring_tor.md) - - - -**3.1 Wallet** - -btcd was intentionally developed without an integrated wallet for security -reasons. Please see [btcwallet](https://github.com/btcsuite/btcwallet) for more -information. - - - - -### 4. Contact - - - -**4.1 IRC** - -* [irc.freenode.net](irc://irc.freenode.net), channel `#btcd` - - - -**4.2 Mailing Lists** - -* btcd: discussion - of btcd and its packages. -* btcd-commits: - readonly mail-out of source code changes. - - - -### 5. Developer Resources - - - -* [Code Contribution Guidelines](https://github.com/btcsuite/btcd/tree/master/docs/code_contribution_guidelines.md) - - - -* [JSON-RPC Reference](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md) - * [RPC Examples](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md#ExampleCode) - - - -* The btcsuite Bitcoin-related Go Packages: - * [btcrpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) - Implements a - robust and easy to use Websocket-enabled Bitcoin JSON-RPC client - * [btcjson](https://github.com/btcsuite/btcd/tree/master/btcjson) - Provides an extensive API - for the underlying JSON-RPC command and return values - * [wire](https://github.com/btcsuite/btcd/tree/master/wire) - Implements the - Bitcoin wire protocol - * [peer](https://github.com/btcsuite/btcd/tree/master/peer) - - Provides a common base for creating and managing Bitcoin network peers. - * [blockchain](https://github.com/btcsuite/btcd/tree/master/blockchain) - - Implements Bitcoin block handling and chain selection rules - * [blockchain/fullblocktests](https://github.com/btcsuite/btcd/tree/master/blockchain/fullblocktests) - - Provides a set of block tests for testing the consensus validation rules - * [txscript](https://github.com/btcsuite/btcd/tree/master/txscript) - - Implements the Bitcoin transaction scripting language - * [btcec](https://github.com/btcsuite/btcd/tree/master/btcec) - Implements - support for the elliptic curve cryptographic functions needed for the - Bitcoin scripts - * [database](https://github.com/btcsuite/btcd/tree/master/database) - - Provides a database interface for the Bitcoin block chain - * [mempool](https://github.com/btcsuite/btcd/tree/master/mempool) - - Package mempool provides a policy-enforced pool of unmined bitcoin - transactions. - * [btcutil](https://github.com/btcsuite/btcutil) - Provides Bitcoin-specific - convenience functions and types - * [chainhash](https://github.com/btcsuite/btcd/tree/master/chaincfg/chainhash) - - Provides a generic hash type and associated functions that allows the - specific hash algorithm to be abstracted. - * [connmgr](https://github.com/btcsuite/btcd/tree/master/connmgr) - - Package connmgr implements a generic Bitcoin network connection manager. - - - -### 6. Using Docker - -You can run btcd in a Docker container, without the need to compile the source by yourself. Visit the [Using Docker](https://github.com/btcsuite/btcd/tree/master/docs/using_docker.md) page for more inrormation and examples. - -* [Using Docker](https://github.com/btcsuite/btcd/tree/master/docs/using_docker.md) details page diff --git a/docs/code_contribution_guidelines.md b/docs/code_contribution_guidelines.md index b643e911a3..a135ad937a 100644 --- a/docs/code_contribution_guidelines.md +++ b/docs/code_contribution_guidelines.md @@ -1,23 +1,4 @@ -### Table of Contents -1. [Overview](#Overview)
-2. [Minimum Recommended Skillset](#MinSkillset)
-3. [Required Reading](#ReqReading)
-4. [Development Practices](#DevelopmentPractices)
-4.1. [Share Early, Share Often](#ShareEarly)
-4.2. [Testing](#Testing)
-4.3. [Code Documentation and Commenting](#CodeDocumentation)
-4.4. [Model Git Commit Messages](#ModelGitCommitMessages)
-5. [Code Approval Process](#CodeApproval)
-5.1 [Code Review](#CodeReview)
-5.2 [Rework Code (if needed)](#CodeRework)
-5.3 [Acceptance](#CodeAcceptance)
-6. [Contribution Standards](#Standards)
-6.1. [Contribution Checklist](#Checklist)
-6.2. [Licensing of Contributions](#Licensing)
- -
- -### 1. Overview +# Code contribution guidelines Developing cryptocurrencies is an exciting endeavor that touches a wide variety of areas such as wire protocols, peer-to-peer networking, databases, @@ -38,9 +19,7 @@ is outlined on this page. We highly encourage code contributions, however it is imperative that you adhere to the guidelines established on this page. - - -### 2. Minimum Recommended Skillset +## Minimum Recommended Skillset The following list is a set of core competencies that we recommend you possess before you really start attempting to contribute code to the project. These are @@ -64,9 +43,7 @@ if you wish to contribute to the cryptography code, you should have a good understanding of the various aspects involved with cryptography such as the security and performance implications. - - -### 3. Required Reading +## Required Reading - [Effective Go](http://golang.org/doc/effective_go.html) - The entire btcd suite follows the guidelines in this document. For your code to be accepted, @@ -74,17 +51,13 @@ security and performance implications. - [Original Satoshi Whitepaper](http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCkQFjAA&url=http%3A%2F%2Fbitcoin.org%2Fbitcoin.pdf&ei=os3VUuH8G4SlsASV74GoAg&usg=AFQjCNEipPLigou_1MfB7DQjXCNdlylrBg&sig2=FaHDuT5z36GMWDEnybDJLg&bvm=bv.59378465,d.b2I) - This is the white paper that started it all. Having a solid foundation to build on will make the code much more comprehensible. - - -### 4. Development Practices +## Development Practices Developers are expected to work in their own trees and submit pull requests when they feel their feature or bug fix is ready for integration into the master branch. - - -### 4.1 Share Early, Share Often +## Share Early, Share Often We firmly believe in the share early, share often approach. The basic premise of the approach is to announce your plans **before** you start work, and once @@ -105,9 +78,7 @@ This approach has several benefits: - The quicker your changes are merged to master, the less time you will need to spend rebasing and otherwise trying to keep up with the main code base - - -### 4.2 Testing +## Testing One of the major design goals of all core btcd packages is to aim for complete test coverage. This is financial software so bugs and regressions can cost @@ -126,15 +97,14 @@ checking coverage statistics straight forward. For more information about the test coverage tools, see the [golang cover blog post](http://blog.golang.org/cover). A quick summary of test practices follows: + - All new code should be accompanied by tests that ensure the code behaves correctly when given expected values, and, perhaps even more importantly, that it handles errors gracefully - When you fix a bug, it should be accompanied by tests which exercise the bug to both prove it has been resolved and to prevent future regressions - - -### 4.3 Code Documentation and Commenting +## Code Documentation and Commenting - At a minimum every function must be commented with its intended purpose and any assumptions that it makes @@ -144,16 +114,20 @@ A quick summary of test practices follows: variety of automated presentations such as [godoc.org](https://godoc.org) - The general rule of thumb is to look at it as if you were completely unfamiliar with the code and ask yourself, would this give me enough - information to understand what this function does and how I'd probably want - to use it? + information to understand what this function does and how I'd probably want + to use it? - Exported functions should also include detailed information the caller of the - function will likely need to know and/or understand:

+ function will likely need to know and/or understand: + **WRONG** + ```Go // convert a compact uint32 to big.Int func CompactToBig(compact uint32) *big.Int { ``` + **RIGHT** + ```Go // CompactToBig converts a compact representation of a whole number N to a // big integer. The representation is similar to IEEE754 floating point @@ -180,31 +154,35 @@ func CompactToBig(compact uint32) *big.Int { // sign bit, but it is implemented here to stay consistent with bitcoind. func CompactToBig(compact uint32) *big.Int { ``` + - Comments in the body of the code are highly encouraged, but they should explain the intention of the code as opposed to just calling out the - obvious

+ obvious + **WRONG** + ```Go // return err if amt is less than 5460 if amt < 5460 { - return err + return err } ``` + **RIGHT** + ```Go // Treat transactions with amounts less than the amount which is considered dust // as non-standard. if amt < 5460 { - return err + return err } ``` + **NOTE:** The above should really use a constant as opposed to a magic number, but it was left as a magic number to show how much of a difference a good comment can make. -
- -### 4.4 Model Git Commit Messages +## Model Git Commit Messages This project prefers to keep a clean commit history with well-formed commit messages. This section illustrates a model commit message and provides a bit @@ -214,7 +192,7 @@ being provided here. Here’s a model Git commit message: -``` +```text Short (50 chars or less) summary of changes More detailed explanatory text, if necessary. Wrap it to about 72 @@ -255,22 +233,18 @@ a good thing. wrap our plain text emails such that there’s room for a few levels of nested reply indicators without overflow in an 80 column terminal. - - -### 5. Code Approval Process +## Code Approval Process This section describes the code approval process that is used for code contributions. This is how to get your changes into btcd. - - -### 5.1 Code Review +## Code Review All code which is submitted will need to be reviewed before inclusion into the master branch. This process is performed by the project maintainers and usually other committers who are interested in the area you are working in as well. -##### Code Review Timeframe +## Code Review Timeframe The timeframe for a code review will vary greatly depending on factors such as the number of other pull requests which need to be reviewed, the size and @@ -286,7 +260,7 @@ days, while large or far reaching changes may take weeks. This is a good reason to stick with the [Share Early, Share Often](#ShareOften) development practice outlined above. -##### What is the review looking for? +## What is the review looking for? The review is mainly ensuring the code follows the [Development Practices](#DevelopmentPractices) and [Code Contribution Standards](#Standards). However, there are a few other @@ -298,9 +272,7 @@ checks which are generally performed as follows: - The change is not something which is deemed inappropriate by community consensus - - -### 5.2 Rework Code (if needed) +## Rework Code (if needed) After the code review, the change will be accepted immediately if no issues are found. If there are any concerns or questions, you will be provided with @@ -311,9 +283,7 @@ make the necessary changes. This process will continue until the code is finally accepted. - - -### 5.3 Acceptance +## Acceptance Once your code is accepted, it will be integrated with the master branch. Typically it will be rebased and fast-forward merged to master as we prefer to @@ -323,13 +293,9 @@ the master branch and the pull request will be closed. Rejoice as you will now be listed as a [contributor](https://github.com/btcsuite/btcd/graphs/contributors)! - +## Contribution Standards -### 6. Contribution Standards - - - -### 6.1. Contribution Checklist +## Contribution Checklist - [  ] All changes are Go version 1.3 compliant - [  ] The code being submitted is commented according to the @@ -346,9 +312,7 @@ Rejoice as you will now be listed as a [contributor](https://github.com/btcsuite - [  ] Running [golint](https://github.com/golang/lint) does not report any **new** issues that did not already exist - - -### 6.2. Licensing of Contributions +## Licensing of Contributions All contributions must be licensed with the [ISC license](https://github.com/btcsuite/btcd/blob/master/LICENSE). This is diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000000..3db163052b --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,77 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) +import recommonmark +from recommonmark.transform import AutoStructify + +# -- Project information ----------------------------------------------------- + +project = 'btcd' +copyright = '2020, btcd' +author = 'btcsuite developers' + +# The full version, including alpha/beta/rc tags +release = 'beta' + +source_suffix = ['.md'] + +# The master toctree document. +master_doc = 'index' + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx.ext.mathjax', + 'sphinx_markdown_tables', + 'recommonmark', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# app setup hook +def setup(app): + app.add_config_value('recommonmark_config', { + #'url_resolver': lambda url: github_doc_root + url, + 'auto_toc_tree_section': 'Contents', + 'enable_math': False, + 'enable_inline_math': False, + 'enable_eval_rst': True, + 'enable_auto_doc_ref': True, + }, True) + app.add_transform(AutoStructify) diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000000..132c07a1df --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,190 @@ +# Configuration + +btcd has a number of [configuration](http://godoc.org/github.com/btcsuite/btcd) +options, which can be viewed by running: `$ btcd --help`. + +## Peer server listen interface + +btcd allows you to bind to specific interfaces which enables you to setup +configurations with varying levels of complexity. The listen parameter can be +specified on the command line as shown below with the -- prefix or in the +configuration file without the -- prefix (as can all long command line options). +The configuration file takes one entry per line. + +**NOTE:** The listen flag can be specified multiple times to listen on multiple +interfaces as a couple of the examples below illustrate. + +Command Line Examples: + +|Flags|Comment| +|----------|------------| +|--listen=|all interfaces on default port which is changed by `--testnet` and `--regtest` (**default**)| +|--listen=0.0.0.0|all IPv4 interfaces on default port which is changed by `--testnet` and `--regtest`| +|--listen=::|all IPv6 interfaces on default port which is changed by `--testnet` and `--regtest`| +|--listen=:8333|all interfaces on port 8333| +|--listen=0.0.0.0:8333|all IPv4 interfaces on port 8333| +|--listen=[::]:8333|all IPv6 interfaces on port 8333| +|--listen=127.0.0.1:8333|only IPv4 localhost on port 8333| +|--listen=[::1]:8333|only IPv6 localhost on port 8333| +|--listen=:8336|all interfaces on non-standard port 8336| +|--listen=0.0.0.0:8336|all IPv4 interfaces on non-standard port 8336| +|--listen=[::]:8336|all IPv6 interfaces on non-standard port 8336| +|--listen=127.0.0.1:8337 --listen=[::1]:8333|IPv4 localhost on port 8337 and IPv6 localhost on port 8333| +|--listen=:8333 --listen=:8337|all interfaces on ports 8333 and 8337| + +The following config file would configure btcd to only listen on localhost for both IPv4 and IPv6: + +```text +[Application Options] + +listen=127.0.0.1:8333 +listen=[::1]:8333 +``` + +In addition, if you are starting btcd with TLS and want to make it +available via a hostname, then you will need to generate the TLS +certificates for that host. For example, + +``` +gencerts --host=myhostname.example.com --directory=/home/me/.btcd/ +``` + +## RPC server listen interface + +btcd allows you to bind the RPC server to specific interfaces which enables you +to setup configurations with varying levels of complexity. The `rpclisten` +parameter can be specified on the command line as shown below with the -- prefix +or in the configuration file without the -- prefix (as can all long command line +options). The configuration file takes one entry per line. + +A few things to note regarding the RPC server: + +* The RPC server will **not** be enabled unless the `rpcuser` and `rpcpass` + options are specified. +* When the `rpcuser` and `rpcpass` and/or `rpclimituser` and `rpclimitpass` + options are specified, the RPC server will only listen on localhost IPv4 and + IPv6 interfaces by default. You will need to override the RPC listen + interfaces to include external interfaces if you want to connect from a remote + machine. +* The RPC server has TLS enabled by default, even for localhost. You may use + the `--notls` option to disable it, but only when all listeners are on + localhost interfaces. +* The `--rpclisten` flag can be specified multiple times to listen on multiple + interfaces as a couple of the examples below illustrate. +* The RPC server is disabled by default when using the `--regtest` and + `--simnet` networks. You can override this by specifying listen interfaces. + +Command Line Examples: + +|Flags|Comment| +|----------|------------| +|--rpclisten=|all interfaces on default port which is changed by `--testnet`| +|--rpclisten=0.0.0.0|all IPv4 interfaces on default port which is changed by `--testnet`| +|--rpclisten=::|all IPv6 interfaces on default port which is changed by `--testnet`| +|--rpclisten=:8334|all interfaces on port 8334| +|--rpclisten=0.0.0.0:8334|all IPv4 interfaces on port 8334| +|--rpclisten=[::]:8334|all IPv6 interfaces on port 8334| +|--rpclisten=127.0.0.1:8334|only IPv4 localhost on port 8334| +|--rpclisten=[::1]:8334|only IPv6 localhost on port 8334| +|--rpclisten=:8336|all interfaces on non-standard port 8336| +|--rpclisten=0.0.0.0:8336|all IPv4 interfaces on non-standard port 8336| +|--rpclisten=[::]:8336|all IPv6 interfaces on non-standard port 8336| +|--rpclisten=127.0.0.1:8337 --listen=[::1]:8334|IPv4 localhost on port 8337 and IPv6 localhost on port 8334| +|--rpclisten=:8334 --listen=:8337|all interfaces on ports 8334 and 8337| + +The following config file would configure the btcd RPC server to listen to all interfaces on the default port, including external interfaces, for both IPv4 and IPv6: + +```text +[Application Options] + +rpclisten= +``` + +## Default ports + +While btcd is highly configurable when it comes to the network configuration, +the following is intended to be a quick reference for the default ports used so +port forwarding can be configured as required. + +btcd provides a `--upnp` flag which can be used to automatically map the bitcoin +peer-to-peer listening port if your router supports UPnP. If your router does +not support UPnP, or you don't wish to use it, please note that only the bitcoin +peer-to-peer port should be forwarded unless you specifically want to allow RPC +access to your btcd from external sources such as in more advanced network +configurations. + +|Name|Port| +|----|----| +|Default Bitcoin peer-to-peer port|TCP 8333| +|Default RPC port|TCP 8334| + +## Using bootstrap.dat + +### What is bootstrap.dat? + +It is a flat, binary file containing bitcoin blockchain data starting from the +genesis block and continuing through a relatively recent block height depending +on the last time it was updated. + +See [this](https://bitcointalk.org/index.php?topic=145386.0) thread on +bitcointalk for more details. + +**NOTE:** Using bootstrap.dat is entirely optional. Btcd will download the +block chain from other peers through the Bitcoin protocol with no extra +configuration needed. + +### What are the pros and cons of using bootstrap.dat? + +Pros: + +* Typically accelerates the initial process of bringing up a new node as it + downloads from public P2P nodes and generally is able to achieve faster + download speeds +* It is particularly beneficial when bringing up multiple nodes as you only need + to download the data once + +Cons: + +* Requires you to setup and configure a torrent client if you don't already have + one available +* Requires roughly twice as much disk space since you'll need the flat file as + well as the imported database + +### Where do I get bootstrap.dat? + +The bootstrap.dat file is made available via a torrent. See +[this](https://bitcointalk.org/index.php?topic=145386.0) thread on bitcointalk +for the torrent download details. + +### How do I know I can trust the bootstrap.dat I downloaded? + +You don't need to trust the file as the `addblock` utility verifies every block +using the same rules that are used when downloading the block chain normally +through the Bitcoin protocol. Additionally, the chain rules contain hard-coded +checkpoints for the known-good block chain at periodic intervals. This ensures +that not only is it a valid chain, but it is the same chain that everyone else +is using. + +### How do I use bootstrap.dat with btcd? + +btcd comes with a separate utility named `addblock` which can be used to import +`bootstrap.dat`. This approach is used since the import is a one-time operation +and we prefer to keep the daemon itself as lightweight as possible. + +1. Stop btcd if it is already running. This is required since addblock needs to + access the database used by btcd and it will be locked if btcd is using it. +2. Note the path to the downloaded bootstrap.dat file. +3. Run the addblock utility with the `-i` argument pointing to the location of + boostrap.dat: + +**Windows:** + +```bat +"%PROGRAMFILES%\Btcd Suite\Btcd\addblock" -i C:\Path\To\bootstrap.dat +``` + +**Linux/Unix/BSD/POSIX:** + +```bash +$GOPATH/bin/addblock -i /path/to/bootstrap.dat +``` diff --git a/docs/configure_peer_server_listen_interfaces.md b/docs/configure_peer_server_listen_interfaces.md deleted file mode 100644 index ac61137335..0000000000 --- a/docs/configure_peer_server_listen_interfaces.md +++ /dev/null @@ -1,43 +0,0 @@ -btcd allows you to bind to specific interfaces which enables you to setup -configurations with varying levels of complexity. The listen parameter can be -specified on the command line as shown below with the -- prefix or in the -configuration file without the -- prefix (as can all long command line options). -The configuration file takes one entry per line. - -**NOTE:** The listen flag can be specified multiple times to listen on multiple -interfaces as a couple of the examples below illustrate. - -Command Line Examples: - -|Flags|Comment| -|----------|------------| -|--listen=|all interfaces on default port which is changed by `--testnet` and `--regtest` (**default**)| -|--listen=0.0.0.0|all IPv4 interfaces on default port which is changed by `--testnet` and `--regtest`| -|--listen=::|all IPv6 interfaces on default port which is changed by `--testnet` and `--regtest`| -|--listen=:8333|all interfaces on port 8333| -|--listen=0.0.0.0:8333|all IPv4 interfaces on port 8333| -|--listen=[::]:8333|all IPv6 interfaces on port 8333| -|--listen=127.0.0.1:8333|only IPv4 localhost on port 8333| -|--listen=[::1]:8333|only IPv6 localhost on port 8333| -|--listen=:8336|all interfaces on non-standard port 8336| -|--listen=0.0.0.0:8336|all IPv4 interfaces on non-standard port 8336| -|--listen=[::]:8336|all IPv6 interfaces on non-standard port 8336| -|--listen=127.0.0.1:8337 --listen=[::1]:8333|IPv4 localhost on port 8337 and IPv6 localhost on port 8333| -|--listen=:8333 --listen=:8337|all interfaces on ports 8333 and 8337| - -The following config file would configure btcd to only listen on localhost for both IPv4 and IPv6: - -```text -[Application Options] - -listen=127.0.0.1:8333 -listen=[::1]:8333 -``` - -In addition, if you are starting btcd with TLS and want to make it -available via a hostname, then you will need to generate the TLS -certificates for that host. For example, - -``` -gencerts --host=myhostname.example.com --directory=/home/me/.btcd/ -``` diff --git a/docs/configure_rpc_server_listen_interfaces.md b/docs/configure_rpc_server_listen_interfaces.md deleted file mode 100644 index 3115d6a16f..0000000000 --- a/docs/configure_rpc_server_listen_interfaces.md +++ /dev/null @@ -1,47 +0,0 @@ -btcd allows you to bind the RPC server to specific interfaces which enables you -to setup configurations with varying levels of complexity. The `rpclisten` -parameter can be specified on the command line as shown below with the -- prefix -or in the configuration file without the -- prefix (as can all long command line -options). The configuration file takes one entry per line. - -A few things to note regarding the RPC server: -* The RPC server will **not** be enabled unless the `rpcuser` and `rpcpass` - options are specified. -* When the `rpcuser` and `rpcpass` and/or `rpclimituser` and `rpclimitpass` - options are specified, the RPC server will only listen on localhost IPv4 and - IPv6 interfaces by default. You will need to override the RPC listen - interfaces to include external interfaces if you want to connect from a remote - machine. -* The RPC server has TLS enabled by default, even for localhost. You may use - the `--notls` option to disable it, but only when all listeners are on - localhost interfaces. -* The `--rpclisten` flag can be specified multiple times to listen on multiple - interfaces as a couple of the examples below illustrate. -* The RPC server is disabled by default when using the `--regtest` and - `--simnet` networks. You can override this by specifying listen interfaces. - -Command Line Examples: - -|Flags|Comment| -|----------|------------| -|--rpclisten=|all interfaces on default port which is changed by `--testnet`| -|--rpclisten=0.0.0.0|all IPv4 interfaces on default port which is changed by `--testnet`| -|--rpclisten=::|all IPv6 interfaces on default port which is changed by `--testnet`| -|--rpclisten=:8334|all interfaces on port 8334| -|--rpclisten=0.0.0.0:8334|all IPv4 interfaces on port 8334| -|--rpclisten=[::]:8334|all IPv6 interfaces on port 8334| -|--rpclisten=127.0.0.1:8334|only IPv4 localhost on port 8334| -|--rpclisten=[::1]:8334|only IPv6 localhost on port 8334| -|--rpclisten=:8336|all interfaces on non-standard port 8336| -|--rpclisten=0.0.0.0:8336|all IPv4 interfaces on non-standard port 8336| -|--rpclisten=[::]:8336|all IPv6 interfaces on non-standard port 8336| -|--rpclisten=127.0.0.1:8337 --listen=[::1]:8334|IPv4 localhost on port 8337 and IPv6 localhost on port 8334| -|--rpclisten=:8334 --listen=:8337|all interfaces on ports 8334 and 8337| - -The following config file would configure the btcd RPC server to listen to all interfaces on the default port, including external interfaces, for both IPv4 and IPv6: - -```text -[Application Options] - -rpclisten= -``` diff --git a/docs/configuring_tor.md b/docs/configuring_tor.md index 442930d6e3..ecb03bfc32 100644 --- a/docs/configuring_tor.md +++ b/docs/configuring_tor.md @@ -1,25 +1,4 @@ -### Table of Contents -1. [Overview](#Overview)
-2. [Client-Only](#Client)
-2.1 [Description](#ClientDescription)
-2.2 [Command Line Example](#ClientCLIExample)
-2.3 [Config File Example](#ClientConfigFileExample)
-3. [Client-Server via Tor Hidden Service](#HiddenService)
-3.1 [Description](#HiddenServiceDescription)
-3.2 [Command Line Example](#HiddenServiceCLIExample)
-3.3 [Config File Example](#HiddenServiceConfigFileExample)
-4. [Bridge Mode (Not Anonymous)](#Bridge)
-4.1 [Description](#BridgeDescription)
-4.2 [Command Line Example](#BridgeCLIExample)
-4.3 [Config File Example](#BridgeConfigFileExample)
-5. [Tor Stream Isolation](#TorStreamIsolation)
-5.1 [Description](#TorStreamIsolationDescription)
-5.2 [Command Line Example](#TorStreamIsolationCLIExample)
-5.3 [Config File Example](#TorStreamIsolationFileExample)
- -
- -### 1. Overview +# Configuring TOR btcd provides full support for anonymous networking via the [Tor Project](https://www.torproject.org/), including [client-only](#Client) @@ -34,13 +13,7 @@ network to run as both a client and a server so others may connect to you to as you are connecting to them. We recommend you take the time to setup a Tor hidden service for this reason. - - -### 2. Client-Only - - - -**2.1 Description**
+## Client-only Configuring btcd as a Tor client is straightforward. The first step is obviously to install Tor and ensure it is working. Once that is done, all that @@ -58,17 +31,13 @@ NOTE: Specifying the `--proxy` flag disables listening by default since you will not be reachable for inbound connections unless you also configure a Tor [hidden service](#HiddenService). -
- -**2.2 Command Line Example**
+### Command line example ```bash -$ ./btcd --proxy=127.0.0.1:9050 +./btcd --proxy=127.0.0.1:9050 ``` -
- -**2.3 Config File Example**
+### Config file example ```text [Application Options] @@ -76,13 +45,7 @@ $ ./btcd --proxy=127.0.0.1:9050 proxy=127.0.0.1:9050 ``` -
- -### 3. Client-Server via Tor Hidden Service - - - -**3.1 Description**
+## Client-server via Tor hidden service The first step is to configure Tor to provide a hidden service. Documentation for this can be found on the Tor project website @@ -103,23 +66,20 @@ HiddenServicePort 8333 127.0.0.1:8333 Once Tor is configured to provide the hidden service and you have obtained your generated .onion address, configuring btcd as a Tor hidden service requires three flags: + * `--proxy` to identify the Tor (SOCKS 5) proxy to use for outgoing traffic. This is typically 127.0.0.1:9050. * `--listen` to enable listening for inbound connections since `--proxy` disables listening by default * `--externalip` to set the .onion address that is advertised to other peers -
- -**3.2 Command Line Example**
+### Command line example ```bash -$ ./btcd --proxy=127.0.0.1:9050 --listen=127.0.0.1 --externalip=fooanon.onion +./btcd --proxy=127.0.0.1:9050 --listen=127.0.0.1 --externalip=fooanon.onion ``` -
- -**3.3 Config File Example**
+### Config file example ```text [Application Options] @@ -129,13 +89,7 @@ listen=127.0.0.1 externalip=fooanon.onion ``` -
- -### 4. Bridge Mode (Not Anonymous) - - - -**4.1 Description**
+## Bridge mode (not anonymous) btcd provides support for operating as a bridge between regular nodes and hidden service nodes. In particular this means only traffic which is directed to or @@ -154,17 +108,13 @@ mode, you only need to specify your hidden service's .onion address via the `--externalip` flag since traffic to and from .onion addresses are already routed via Tor due to the `--onion` flag. -
- -**4.2 Command Line Example**
+### Command line example ```bash -$ ./btcd --onion=127.0.0.1:9050 --externalip=fooanon.onion +./btcd --onion=127.0.0.1:9050 --externalip=fooanon.onion ``` -
- -**4.3 Config File Example**
+### Config file example ```text [Application Options] @@ -173,13 +123,7 @@ onion=127.0.0.1:9050 externalip=fooanon.onion ``` -
- -### 5. Tor Stream Isolation - - - -**5.1 Description**
+## Tor stream isolation Tor stream isolation forces Tor to build a new circuit for each connection making it harder to correlate connections. @@ -187,17 +131,13 @@ making it harder to correlate connections. btcd provides support for Tor stream isolation by using the `--torisolation` flag. This option requires --proxy or --onionproxy to be set. -
- -**5.2 Command Line Example**
+### Command line example ```bash -$ ./btcd --proxy=127.0.0.1:9050 --torisolation +./btcd --proxy=127.0.0.1:9050 --torisolation ``` -
- -**5.3 Config File Example**
+### Config file example ```text [Application Options] diff --git a/docs/contact.md b/docs/contact.md new file mode 100644 index 0000000000..88b425e8bc --- /dev/null +++ b/docs/contact.md @@ -0,0 +1,15 @@ +# Contact + +## IRC + +* [irc.freenode.net](irc://irc.freenode.net), channel `#btcd` + +## Mailing Lists + +* [btcd](mailto:btcd+subscribe@opensource.conformal.com): discussion of btcd and its packages. +* [btcd-commits](mailto:btcd-commits+subscribe@opensource.conformal.com): readonly mail-out of source code changes. + +## Issue Tracker + +The [integrated github issue tracker](https://github.com/btcsuite/btcd/issues) +is used for this project. diff --git a/docs/controlling.md b/docs/controlling.md new file mode 100644 index 0000000000..93ab403b2e --- /dev/null +++ b/docs/controlling.md @@ -0,0 +1,34 @@ +# Controlling and querying btcd via btcctl + +btcctl is a command line utility that can be used to both control and query btcd +via [RPC](http://www.wikipedia.org/wiki/Remote_procedure_call). btcd does +**not** enable its RPC server by default; You must configure at minimum both an +RPC username and password or both an RPC limited username and password: + +* btcd.conf configuration file + +```bash +[Application Options] +rpcuser=myuser +rpcpass=SomeDecentp4ssw0rd +rpclimituser=mylimituser +rpclimitpass=Limitedp4ssw0rd +``` + +* btcctl.conf configuration file + +```bash +[Application Options] +rpcuser=myuser +rpcpass=SomeDecentp4ssw0rd +``` + +OR + +```bash +[Application Options] +rpclimituser=mylimituser +rpclimitpass=Limitedp4ssw0rd +``` + +For a list of available options, run: `$ btcctl --help` diff --git a/docs/default_ports.md b/docs/default_ports.md deleted file mode 100644 index 14e4eea2a7..0000000000 --- a/docs/default_ports.md +++ /dev/null @@ -1,15 +0,0 @@ -While btcd is highly configurable when it comes to the network configuration, -the following is intended to be a quick reference for the default ports used so -port forwarding can be configured as required. - -btcd provides a `--upnp` flag which can be used to automatically map the bitcoin -peer-to-peer listening port if your router supports UPnP. If your router does -not support UPnP, or you don't wish to use it, please note that only the bitcoin -peer-to-peer port should be forwarded unless you specifically want to allow RPC -access to your btcd from external sources such as in more advanced network -configurations. - -|Name|Port| -|----|----| -|Default Bitcoin peer-to-peer port|TCP 8333| -|Default RPC port|TCP 8334| diff --git a/docs/developer_resources.md b/docs/developer_resources.md new file mode 100644 index 0000000000..cec8ce9972 --- /dev/null +++ b/docs/developer_resources.md @@ -0,0 +1,37 @@ +# Developer Resources + +* [Code Contribution Guidelines](https://github.com/btcsuite/btcd/tree/master/docs/code_contribution_guidelines.md) + +* [JSON-RPC Reference](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md) + * [RPC Examples](https://github.com/btcsuite/btcd/tree/master/docs/json_rpc_api.md#ExampleCode) + +* The btcsuite Bitcoin-related Go Packages: + * [btcrpcclient](https://github.com/btcsuite/btcd/tree/master/rpcclient) - Implements a + robust and easy to use Websocket-enabled Bitcoin JSON-RPC client + * [btcjson](https://github.com/btcsuite/btcd/tree/master/btcjson) - Provides an extensive API + for the underlying JSON-RPC command and return values + * [wire](https://github.com/btcsuite/btcd/tree/master/wire) - Implements the + Bitcoin wire protocol + * [peer](https://github.com/btcsuite/btcd/tree/master/peer) - + Provides a common base for creating and managing Bitcoin network peers. + * [blockchain](https://github.com/btcsuite/btcd/tree/master/blockchain) - + Implements Bitcoin block handling and chain selection rules + * [blockchain/fullblocktests](https://github.com/btcsuite/btcd/tree/master/blockchain/fullblocktests) - + Provides a set of block tests for testing the consensus validation rules + * [txscript](https://github.com/btcsuite/btcd/tree/master/txscript) - + Implements the Bitcoin transaction scripting language + * [btcec](https://github.com/btcsuite/btcd/tree/master/btcec) - Implements + support for the elliptic curve cryptographic functions needed for the + Bitcoin scripts + * [database](https://github.com/btcsuite/btcd/tree/master/database) - + Provides a database interface for the Bitcoin block chain + * [mempool](https://github.com/btcsuite/btcd/tree/master/mempool) - + Package mempool provides a policy-enforced pool of unmined bitcoin + transactions. + * [btcutil](https://github.com/btcsuite/btcutil) - Provides Bitcoin-specific + convenience functions and types + * [chainhash](https://github.com/btcsuite/btcd/tree/master/chaincfg/chainhash) - + Provides a generic hash type and associated functions that allows the + specific hash algorithm to be abstracted. + * [connmgr](https://github.com/btcsuite/btcd/tree/master/connmgr) - + Package connmgr implements a generic Bitcoin network connection manager. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000000..5dc0dfcf56 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,57 @@ +# btcd + +[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd) + +btcd is an alternative full node bitcoin implementation written in Go (golang). + +This project is currently under active development and is in a Beta state. It +is extremely stable and has been in production use since October 2013. + +It properly downloads, validates, and serves the block chain using the exact +rules (including consensus bugs) for block acceptance as Bitcoin Core. We have +taken great care to avoid btcd causing a fork to the block chain. It includes a +full block validation testing framework which contains all of the 'official' +block acceptance tests (and some additional ones) that is run on every pull +request to help ensure it properly follows consensus. Also, it passes all of +the JSON test data in the Bitcoin Core code. + +It also properly relays newly mined blocks, maintains a transaction pool, and +relays individual transactions that have not yet made it into a block. It +ensures all individual transactions admitted to the pool follow the rules +required by the block chain and also includes more strict checks which filter +transactions based on miner requirements ("standard" transactions). + +One key difference between btcd and Bitcoin Core is that btcd does *NOT* include +wallet functionality and this was a very intentional design decision. See the +blog entry [here](https://web.archive.org/web/20171125143919/https://blog.conformal.com/btcd-not-your-moms-bitcoin-daemon) +for more details. This means you can't actually make or receive payments +directly with btcd. That functionality is provided by the +[btcwallet](https://github.com/btcsuite/btcwallet) and +[Paymetheus](https://github.com/btcsuite/Paymetheus) (Windows-only) projects +which are both under active development. + +## Documentation + +Documentation is a work-in-progress. It is available at [btcd.readthedocs.io](https://btcd.readthedocs.io/en/docu/). + +## Contents + +* [Installation](installation.md) +* [Update](update.md) +* [Configuration](configuration.md) +* [Configuring TOR](configuring_tor.md) +* [Docker](using_docker.md) +* [Controlling](controlling.md) +* [Mining](mining.md) +* [Wallet](wallet.md) +* [Developer resources](developer_resources.md) +* [JSON RPC API](json_rpc_api.md) +* [Code contribution guidelines](code_contribution_guidelines.md) +* [Contact](contact.md) + +## License + +btcd is licensed under the [copyfree](http://copyfree.org) ISC License. + diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000000..3eea886e4c --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,76 @@ +# Installation + +The first step is to install btcd. See one of the following sections for +details on how to install on the supported operating systems. + +## Requirements + +[Go](http://golang.org) 1.11 or newer. + +## GPG Verification Key + +All official release tags are signed by Conformal so users can ensure the code +has not been tampered with and is coming from the btcsuite developers. To +verify the signature perform the following: + +* Download the Conformal public key: + https://raw.githubusercontent.com/btcsuite/btcd/master/release/GIT-GPG-KEY-conformal.txt + +* Import the public key into your GPG keyring: + + ```bash + gpg --import GIT-GPG-KEY-conformal.txt + ``` + +* Verify the release tag with the following command where `TAG_NAME` is a + placeholder for the specific tag: + + ```bash + git tag -v TAG_NAME + ``` + +## Windows Installation + +* Install the MSI available at: [btcd windows installer](https://github.com/btcsuite/btcd/releases) +* Launch btcd from the Start Menu + +## Linux/BSD/MacOSX/POSIX Installation + +* Install Go according to the [installation instructions](http://golang.org/doc/install) +* Ensure Go was installed properly and is a supported version: + +```bash +go version +go env GOROOT GOPATH +``` + +NOTE: The `GOROOT` and `GOPATH` above must not be the same path. It is +recommended that `GOPATH` is set to a directory in your home directory such as +`~/goprojects` to avoid write permission issues. It is also recommended to add +`$GOPATH/bin` to your `PATH` at this point. + +* Run the following commands to obtain btcd, all dependencies, and install it: + +```bash +git clone https://github.com/btcsuite/btcd $GOPATH/src/github.com/btcsuite/btcd +cd $GOPATH/src/github.com/btcsuite/btcd +GO111MODULE=on go install -v . ./cmd/... +``` + +* btcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did + not already add the bin directory to your system path during Go installation, + we recommend you do so now. + +## Gentoo Linux Installation + +* [Install Layman](https://gitlab.com/bitcoin/gentoo) and enable the Bitcoin overlay. +* Copy or symlink `/var/lib/layman/bitcoin/Documentation/package.keywords/btcd-live` to `/etc/portage/package.keywords/` +* Install btcd: `$ emerge net-p2p/btcd` + +## Startup + +Typically btcd will run and start downloading the block chain with no extra +configuration necessary, however, there is an optional method to use a +`bootstrap.dat` file that may speed up the initial block chain download process. + +* [Using bootstrap.dat](https://github.com/btcsuite/btcd/tree/master/docs/using_bootstrap_dat.md) diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index 61884df0a0..db292d2ba2 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -1,4 +1,5 @@ -### Table of Contents +# JSON RPC API + 1. [Overview](#Overview)
2. [HTTP POST Versus Websockets](#HttpPostVsWebsockets)
3. [Authentication](#Authentication)
diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000000..922152e96a --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/mining.md b/docs/mining.md new file mode 100644 index 0000000000..29a3e89858 --- /dev/null +++ b/docs/mining.md @@ -0,0 +1,30 @@ +# Mining + +btcd supports the `getblocktemplate` RPC. +The limited user cannot access this RPC. + +## Add the payment addresses with the `miningaddr` option + +```bash +[Application Options] +rpcuser=myuser +rpcpass=SomeDecentp4ssw0rd +miningaddr=12c6DSiU4Rq3P4ZxziKxzrL5LmMBrzjrJX +miningaddr=1M83ju3EChKYyysmM2FXtLNftbacagd8FR +``` + +## Add btcd's RPC TLS certificate to system Certificate Authority list + +`cgminer` uses [curl](http://curl.haxx.se/) to fetch data from the RPC server. +Since curl validates the certificate by default, we must install the `btcd` RPC +certificate into the default system Certificate Authority list. + +## Ubuntu + +1. Copy rpc.cert to /usr/share/ca-certificates: `# cp /home/user/.btcd/rpc.cert /usr/share/ca-certificates/btcd.crt` +2. Add btcd.crt to /etc/ca-certificates.conf: `# echo btcd.crt >> /etc/ca-certificates.conf` +3. Update the CA certificate list: `# update-ca-certificates` + +## Set your mining software url to use https + +`cgminer -o https://127.0.0.1:8334 -u rpcuser -p rpcpassword` diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000000..e16dd4b38f --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1 @@ +sphinx_markdown_tables diff --git a/docs/table_of_content.md b/docs/table_of_content.md new file mode 100644 index 0000000000..85f08a97b3 --- /dev/null +++ b/docs/table_of_content.md @@ -0,0 +1,13 @@ +# Contents + +* [Installation](installation.md) +* [Update](update.md) +* [Configuration](configuration.md) +* [Configuring TOR](configuring_tor.md) +* [Controlling](controlling.md) +* [Mining](mining.md) +* [Wallet](wallet.md) +* [Developer resources](developer_resources.md) +* [JSON RPC API](json_rpc_api.md) +* [Code contribution guidelines](code_contribution_guidelines.md) +* [Contact](contact.md) diff --git a/docs/update.md b/docs/update.md new file mode 100644 index 0000000000..1fb847cf9f --- /dev/null +++ b/docs/update.md @@ -0,0 +1,8 @@ +# Update + +* Run the following commands to update btcd, all dependencies, and install it: + +```bash +cd $GOPATH/src/github.com/btcsuite/btcd +git pull && GO111MODULE=on go install -v . ./cmd/... +``` diff --git a/docs/using_bootstrap_dat.md b/docs/using_bootstrap_dat.md deleted file mode 100644 index de7e08c0ce..0000000000 --- a/docs/using_bootstrap_dat.md +++ /dev/null @@ -1,79 +0,0 @@ -### Table of Contents -1. [What is bootstrap.dat?](#What)
-2. [What are the pros and cons of using bootstrap.dat?](#ProsCons) -3. [Where do I get bootstrap.dat?](#Obtaining) -4. [How do I know I can trust the bootstrap.dat I downloaded?](#Trust) -5. [How do I use bootstrap.dat with btcd?](#Importing) - -
- -### 1. What is bootstrap.dat? - -It is a flat, binary file containing bitcoin blockchain data starting from the -genesis block and continuing through a relatively recent block height depending -on the last time it was updated. - -See [this](https://bitcointalk.org/index.php?topic=145386.0) thread on -bitcointalk for more details. - -**NOTE:** Using bootstrap.dat is entirely optional. Btcd will download the -block chain from other peers through the Bitcoin protocol with no extra -configuration needed. - - - -### 2. What are the pros and cons of using bootstrap.dat? - -Pros: -- Typically accelerates the initial process of bringing up a new node as it - downloads from public P2P nodes and generally is able to achieve faster - download speeds -- It is particularly beneficial when bringing up multiple nodes as you only need - to download the data once - -Cons: -- Requires you to setup and configure a torrent client if you don't already have - one available -- Requires roughly twice as much disk space since you'll need the flat file as - well as the imported database - - - -### 3. Where do I get bootstrap.dat? - -The bootstrap.dat file is made available via a torrent. See -[this](https://bitcointalk.org/index.php?topic=145386.0) thread on bitcointalk -for the torrent download details. - - - -### 4. How do I know I can trust the bootstrap.dat I downloaded? - -You don't need to trust the file as the `addblock` utility verifies every block -using the same rules that are used when downloading the block chain normally -through the Bitcoin protocol. Additionally, the chain rules contain hard-coded -checkpoints for the known-good block chain at periodic intervals. This ensures -that not only is it a valid chain, but it is the same chain that everyone else -is using. - - - -### 5. How do I use bootstrap.dat with btcd? - -btcd comes with a separate utility named `addblock` which can be used to import -`bootstrap.dat`. This approach is used since the import is a one-time operation -and we prefer to keep the daemon itself as lightweight as possible. - -1. Stop btcd if it is already running. This is required since addblock needs to - access the database used by btcd and it will be locked if btcd is using it. -2. Note the path to the downloaded bootstrap.dat file. -3. Run the addblock utility with the `-i` argument pointing to the location of - boostrap.dat:

-**Windows:** -```bat -C:\> "%PROGRAMFILES%\Btcd Suite\Btcd\addblock" -i C:\Path\To\bootstrap.dat -``` -**Linux/Unix/BSD/POSIX:** -```bash -$ $GOPATH/bin/addblock -i /path/to/bootstrap.dat -``` diff --git a/docs/wallet.md b/docs/wallet.md new file mode 100644 index 0000000000..cc123aa7d5 --- /dev/null +++ b/docs/wallet.md @@ -0,0 +1,5 @@ +# Wallet + +btcd was intentionally developed without an integrated wallet for security +reasons. Please see [btcwallet](https://github.com/btcsuite/btcwallet) for more +information. From 23d149cbfbfa13938dcb64ed62f22250eb6d239d Mon Sep 17 00:00:00 2001 From: Christian Lehmann Date: Tue, 1 Sep 2020 07:42:37 +0200 Subject: [PATCH 0383/1056] Added symlink to index.md for github readme preview. --- docs/README.md | 1 + 1 file changed, 1 insertion(+) create mode 120000 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 120000 index 0000000000..dd0ea36c8e --- /dev/null +++ b/docs/README.md @@ -0,0 +1 @@ +index.md \ No newline at end of file From 61634447e719206c2f67e51c6d6fb3b516330a9e Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 3 Sep 2020 18:53:16 +0800 Subject: [PATCH 0384/1056] btcd+netsync: support witness tx and block in notfound msg --- netsync/manager.go | 5 +++++ server.go | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/netsync/manager.go b/netsync/manager.go index 603fca6ec8..2b6c041156 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -1031,11 +1031,16 @@ func (sm *SyncManager) handleNotFoundMsg(nfmsg *notFoundMsg) { // verify the hash was actually announced by the peer // before deleting from the global requested maps. switch inv.Type { + case wire.InvTypeWitnessBlock: + fallthrough case wire.InvTypeBlock: if _, exists := state.requestedBlocks[inv.Hash]; exists { delete(state.requestedBlocks, inv.Hash) delete(sm.requestedBlocks, inv.Hash) } + + case wire.InvTypeWitnessTx: + fallthrough case wire.InvTypeTx: if _, exists := state.requestedTxns[inv.Hash]; exists { delete(state.requestedTxns, inv.Hash) diff --git a/server.go b/server.go index c9f23fa638..ba7932a1a4 100644 --- a/server.go +++ b/server.go @@ -1321,8 +1321,12 @@ func (sp *serverPeer) OnNotFound(p *peer.Peer, msg *wire.MsgNotFound) { switch inv.Type { case wire.InvTypeBlock: numBlocks++ + case wire.InvTypeWitnessBlock: + numBlocks++ case wire.InvTypeTx: numTxns++ + case wire.InvTypeWitnessTx: + numTxns++ default: peerLog.Debugf("Invalid inv type '%d' in notfound message from %s", inv.Type, sp) From 8facfdd04db86fcee25d368c1b2e9133551e316d Mon Sep 17 00:00:00 2001 From: Hanjun Kim Date: Thu, 16 Apr 2020 00:20:56 +0900 Subject: [PATCH 0385/1056] btcec: set curve name in CurveParams Set curve name(secp256k1) in KoblitzCurve.CurveParams Fixes #1564 --- btcec/btcec.go | 1 + 1 file changed, 1 insertion(+) diff --git a/btcec/btcec.go b/btcec/btcec.go index de93a255a4..6000c479df 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -930,6 +930,7 @@ func initS256() { secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") secp256k1.BitSize = 256 + secp256k1.Name = "secp256k1" secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P, big.NewInt(1)), big.NewInt(4)) secp256k1.H = 1 From 7cbf95675a26e90b88d0252f0835939cde464e6f Mon Sep 17 00:00:00 2001 From: Hanjun Kim Date: Sat, 18 Jul 2020 18:42:01 +0900 Subject: [PATCH 0386/1056] btcec: add a comment indicating where curve name taken from Related with #1565 --- btcec/btcec.go | 1 + 1 file changed, 1 insertion(+) diff --git a/btcec/btcec.go b/btcec/btcec.go index 6000c479df..a2e20f4b31 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -930,6 +930,7 @@ func initS256() { secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") secp256k1.BitSize = 256 + // Curve name taken from https://safecurves.cr.yp.to/. secp256k1.Name = "secp256k1" secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P, big.NewInt(1)), big.NewInt(4)) From ba3fe57507ba8af1c9887932a19841d7ab373bf3 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Tue, 8 Sep 2020 15:43:02 +0200 Subject: [PATCH 0387/1056] rpcclient: support listtransactions RPC with watchonly argument Co-authored-by: Gert-Jaap Glasbergen --- rpcclient/wallet.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index d4069aad62..4f263f102c 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -164,6 +164,25 @@ func (c *Client) ListTransactionsCountFrom(account string, count, from int) ([]b return c.ListTransactionsCountFromAsync(account, count, from).Receive() } +// ListTransactionsCountFromWatchOnlyAsync returns an instance of a type that can be used +// to get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See ListTransactionsCountFromWatchOnly for the blocking version and more details. +func (c *Client) ListTransactionsCountFromWatchOnlyAsync(account string, count, from int, watchOnly bool) FutureListTransactionsResult { + cmd := btcjson.NewListTransactionsCmd(&account, &count, &from, &watchOnly) + return c.sendCmd(cmd) +} + +// ListTransactionsCountFromWatchOnly returns a list of the most recent transactions up +// to the passed count while skipping the first 'from' transactions. It will include or +// exclude transactions from watch-only addresses based on the passed value for the watchOnly parameter +// +// See the ListTransactions and ListTransactionsCount functions to use defaults. +func (c *Client) ListTransactionsCountFromWatchOnly(account string, count, from int, watchOnly bool) ([]btcjson.ListTransactionsResult, error) { + return c.ListTransactionsCountFromWatchOnlyAsync(account, count, from, watchOnly).Receive() +} + // FutureListUnspentResult is a future promise to deliver the result of a // ListUnspentAsync, ListUnspentMinAsync, ListUnspentMinMaxAsync, or // ListUnspentMinMaxAddressesAsync RPC invocation (or an applicable error). From 95fea6420c92fb90c145ddd087def415731634a3 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 13 Jul 2020 23:24:40 +0900 Subject: [PATCH 0388/1056] blockchain: Remove unnecessary tx hash --- blockchain/validate.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/blockchain/validate.go b/blockchain/validate.go index b971337fb5..f41d54e6b1 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -877,7 +877,6 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo return 0, nil } - txHash := tx.Hash() var totalSatoshiIn int64 for txInIndex, txIn := range tx.MsgTx().TxIn { // Ensure the referenced input transaction is available. @@ -954,7 +953,7 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo if totalSatoshiIn < totalSatoshiOut { str := fmt.Sprintf("total value of all transaction inputs for "+ "transaction %v is %v which is less than the amount "+ - "spent of %v", txHash, totalSatoshiIn, totalSatoshiOut) + "spent of %v", tx.Hash(), totalSatoshiIn, totalSatoshiOut) return 0, ruleError(ErrSpendTooHigh, str) } From 3b926ef77b8cafee93e8898ddc4684cd2606aec6 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Sun, 6 Sep 2020 20:37:44 +0200 Subject: [PATCH 0389/1056] btcjson: update ListTransactionsResult for Bitcoin 0.20.0 This only adds new fields as optional, in order to make this change backwards compatible with older versions of Bitcoin Core. --- btcjson/walletsvrresults.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index d860eceb39..4ad74b1ed1 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -64,6 +64,7 @@ type ListTransactionsResult struct { Amount float64 `json:"amount"` BIP125Replaceable string `json:"bip125-replaceable,omitempty"` BlockHash string `json:"blockhash,omitempty"` + BlockHeight *int32 `json:"blockheight,omitempty"` BlockIndex *int64 `json:"blockindex,omitempty"` BlockTime int64 `json:"blocktime,omitempty"` Category string `json:"category"` @@ -71,6 +72,7 @@ type ListTransactionsResult struct { Fee *float64 `json:"fee,omitempty"` Generated bool `json:"generated,omitempty"` InvolvesWatchOnly bool `json:"involveswatchonly,omitempty"` + Label *string `json:"label,omitempty"` Time int64 `json:"time"` TimeReceived int64 `json:"timereceived"` Trusted bool `json:"trusted"` From bdab8dfe81c92667a2e2bf9044e068398be50549 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 24 Aug 2020 20:48:23 +0200 Subject: [PATCH 0390/1056] chaincfg: Add RegisterHDKeyID func to populate HD key ID pairs Currently, the only way to register HD version bytes is by initializing chaincfg.Params struct, and registering it during package init. RegisterHDKeyID provides a way to populate custom HD version bytes, without having to create new chaincfg.Params instances. This is useful for library packages who want to use non-standard version bytes for serializing extended keys, such as the ones documented in SLIP-0132. This function is complementary to HDPrivateKeyToPublicKeyID, which is used to lookup previously registered key IDs. --- chaincfg/params.go | 33 ++++++++++++++++++++++++- chaincfg/params_test.go | 53 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/chaincfg/params.go b/chaincfg/params.go index 54117b8713..7e4327984c 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -588,6 +588,10 @@ var ( // is intended to identify the network for a hierarchical deterministic // private extended key is not registered. ErrUnknownHDKeyID = errors.New("unknown hd private extended key bytes") + + // ErrInvalidHDKeyID describes an error where the provided hierarchical + // deterministic version bytes, or hd key id, is malformed. + ErrInvalidHDKeyID = errors.New("invalid hd extended key version bytes") ) var ( @@ -619,7 +623,11 @@ func Register(params *Params) error { registeredNets[params.Net] = struct{}{} pubKeyHashAddrIDs[params.PubKeyHashAddrID] = struct{}{} scriptHashAddrIDs[params.ScriptHashAddrID] = struct{}{} - hdPrivToPubKeyIDs[params.HDPrivateKeyID] = params.HDPublicKeyID[:] + + err := RegisterHDKeyID(params.HDPublicKeyID[:], params.HDPrivateKeyID[:]) + if err != nil { + return err + } // A valid Bech32 encoded segwit address always has as prefix the // human-readable part for the given net followed by '1'. @@ -666,6 +674,29 @@ func IsBech32SegwitPrefix(prefix string) bool { return ok } +// RegisterHDKeyID registers a public and private hierarchical deterministic +// extended key ID pair. +// +// Non-standard HD version bytes, such as the ones documented in SLIP-0132, +// should be registered using this method for library packages to lookup key +// IDs (aka HD version bytes). When the provided key IDs are invalid, the +// ErrInvalidHDKeyID error will be returned. +// +// Reference: +// SLIP-0132 : Registered HD version bytes for BIP-0032 +// https://github.com/satoshilabs/slips/blob/master/slip-0132.md +func RegisterHDKeyID(hdPublicKeyID []byte, hdPrivateKeyID []byte) error { + if len(hdPublicKeyID) != 4 || len(hdPrivateKeyID) != 4 { + return ErrInvalidHDKeyID + } + + var keyID [4]byte + copy(keyID[:], hdPrivateKeyID) + hdPrivToPubKeyIDs[keyID] = hdPublicKeyID + + return nil +} + // HDPrivateKeyToPublicKeyID accepts a private hierarchical deterministic // extended key id and returns the associated public key id. When the provided // id is not registered, the ErrUnknownHDKeyID error will be returned. diff --git a/chaincfg/params_test.go b/chaincfg/params_test.go index 277a56bdd5..d9e1516812 100644 --- a/chaincfg/params_test.go +++ b/chaincfg/params_test.go @@ -4,7 +4,10 @@ package chaincfg -import "testing" +import ( + "bytes" + "testing" +) // TestInvalidHashStr ensures the newShaHashFromStr function panics when used to // with an invalid hash string. @@ -33,3 +36,51 @@ func TestMustRegisterPanic(t *testing.T) { // Intentionally try to register duplicate params to force a panic. mustRegister(&MainNetParams) } + +func TestRegisterHDKeyID(t *testing.T) { + t.Parallel() + + // Ref: https://github.com/satoshilabs/slips/blob/master/slip-0132.md + hdKeyIDZprv := []byte{0x02, 0xaa, 0x7a, 0x99} + hdKeyIDZpub := []byte{0x02, 0xaa, 0x7e, 0xd3} + + if err := RegisterHDKeyID(hdKeyIDZpub, hdKeyIDZprv); err != nil { + t.Fatalf("RegisterHDKeyID: expected no error, got %v", err) + } + + got, err := HDPrivateKeyToPublicKeyID(hdKeyIDZprv) + if err != nil { + t.Fatalf("HDPrivateKeyToPublicKeyID: expected no error, got %v", err) + } + + if !bytes.Equal(got, hdKeyIDZpub) { + t.Fatalf("HDPrivateKeyToPublicKeyID: expected result %v, got %v", + hdKeyIDZpub, got) + } +} + +func TestInvalidHDKeyID(t *testing.T) { + t.Parallel() + + prvValid := []byte{0x02, 0xaa, 0x7a, 0x99} + pubValid := []byte{0x02, 0xaa, 0x7e, 0xd3} + prvInvalid := []byte{0x00} + pubInvalid := []byte{0x00} + + if err := RegisterHDKeyID(pubInvalid, prvValid); err != ErrInvalidHDKeyID { + t.Fatalf("RegisterHDKeyID: want err ErrInvalidHDKeyID, got %v", err) + } + + if err := RegisterHDKeyID(pubValid, prvInvalid); err != ErrInvalidHDKeyID { + t.Fatalf("RegisterHDKeyID: want err ErrInvalidHDKeyID, got %v", err) + } + + if err := RegisterHDKeyID(pubInvalid, prvInvalid); err != ErrInvalidHDKeyID { + t.Fatalf("RegisterHDKeyID: want err ErrInvalidHDKeyID, got %v", err) + } + + // FIXME: The error type should be changed to ErrInvalidHDKeyID. + if _, err := HDPrivateKeyToPublicKeyID(prvInvalid); err != ErrUnknownHDKeyID { + t.Fatalf("HDPrivateKeyToPublicKeyID: want err ErrUnknownHDKeyID, got %v", err) + } +} From eb05726dacc7252ae8f1bc8689745bec0e9fc23f Mon Sep 17 00:00:00 2001 From: Mikael Lindlof Date: Sun, 14 Jun 2020 19:00:20 +0100 Subject: [PATCH 0391/1056] Nullable optional JSON-RPC parameters Fix command marshalling dropping params following params with nil value. #1591 Allow specifying null parameter value from command line. --- btcjson/cmdparse.go | 16 ++++++--- btcjson/cmdparse_test.go | 74 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/btcjson/cmdparse.go b/btcjson/cmdparse.go index 48c6278a61..117f72f187 100644 --- a/btcjson/cmdparse.go +++ b/btcjson/cmdparse.go @@ -16,19 +16,20 @@ import ( func makeParams(rt reflect.Type, rv reflect.Value) []interface{} { numFields := rt.NumField() params := make([]interface{}, 0, numFields) + lastParam := -1 for i := 0; i < numFields; i++ { rtf := rt.Field(i) rvf := rv.Field(i) + params = append(params, rvf.Interface()) if rtf.Type.Kind() == reflect.Ptr { if rvf.IsNil() { - break + // Omit optional null params unless a non-null param follows + continue } - rvf.Elem() } - params = append(params, rvf.Interface()) + lastParam = i } - - return params + return params[:lastParam+1] } // MarshalCmd marshals the passed command to a JSON-RPC request byte slice that @@ -255,6 +256,11 @@ func assignField(paramNum int, fieldName string, dest reflect.Value, src reflect return nil } + // Optional variables can be set null using "null" string + if destIndirects > 0 && src.String() == "null" { + return nil + } + // When the destination has more indirects than the source, the extra // pointers have to be created. Only create enough pointers to reach // the same level of indirection as the source so the dest can simply be diff --git a/btcjson/cmdparse_test.go b/btcjson/cmdparse_test.go index dd951dcbd7..71547271df 100644 --- a/btcjson/cmdparse_test.go +++ b/btcjson/cmdparse_test.go @@ -162,6 +162,18 @@ func TestAssignField(t *testing.T) { src: `{"1Address":1.5}`, expected: map[string]float64{"1Address": 1.5}, }, + { + name: `null optional field - "null" -> *int32`, + dest: btcjson.Int32(0), + src: "null", + expected: nil, + }, + { + name: `null optional field - "null" -> *string`, + dest: btcjson.String(""), + src: "null", + expected: nil, + }, } t.Logf("Running %d tests", len(tests)) @@ -175,6 +187,15 @@ func TestAssignField(t *testing.T) { continue } + // Check case where null string is used on optional field + if dst.Kind() == reflect.Ptr && test.src == "null" { + if !dst.IsNil() { + t.Errorf("Test #%d (%s) unexpected value - got %v, "+ + "want nil", i, test.name, dst.Interface()) + } + continue + } + // Inidirect through to the base types to ensure their values // are the same. for dst.Kind() == reflect.Ptr { @@ -401,6 +422,59 @@ func TestNewCmdErrors(t *testing.T) { } } +// TestMarshalCmd tests the MarshalCmd function. +func TestMarshalCmd(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + id interface{} + cmd interface{} + expected string + }{ + { + name: "include all parameters", + id: 1, + cmd: btcjson.NewGetNetworkHashPSCmd(btcjson.Int(100), btcjson.Int(2000)), + expected: `{"jsonrpc":"1.0","method":"getnetworkhashps","params":[100,2000],"id":1}`, + }, + { + name: "include padding null parameter", + id: 1, + cmd: btcjson.NewGetNetworkHashPSCmd(nil, btcjson.Int(2000)), + expected: `{"jsonrpc":"1.0","method":"getnetworkhashps","params":[null,2000],"id":1}`, + }, + { + name: "omit single unnecessary null parameter", + id: 1, + cmd: btcjson.NewGetNetworkHashPSCmd(btcjson.Int(100), nil), + expected: `{"jsonrpc":"1.0","method":"getnetworkhashps","params":[100],"id":1}`, + }, + { + name: "omit unnecessary null parameters", + id: 1, + cmd: btcjson.NewGetNetworkHashPSCmd(nil, nil), + expected: `{"jsonrpc":"1.0","method":"getnetworkhashps","params":[],"id":1}`, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + bytes, err := btcjson.MarshalCmd(test.id, test.cmd) + if err != nil { + t.Errorf("Test #%d (%s) wrong error - got %T (%v)", + i, test.name, err, err) + continue + } + marshalled := string(bytes) + if marshalled != test.expected { + t.Errorf("Test #%d (%s) mismatched marshall result - got "+ + "%v, want %v", i, test.name, marshalled, test.expected) + continue + } + } +} + // TestMarshalCmdErrors tests the error paths of the MarshalCmd function. func TestMarshalCmdErrors(t *testing.T) { t.Parallel() From 2547246f84db364949e5535a597e01d7b3fc8b53 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 24 Aug 2020 20:58:47 +0200 Subject: [PATCH 0392/1056] GitHub Actions: Enable Go Race detector and code coverage This modifies the goclean.sh script to run tests with the race detector enabled. It also enables code coverage, and uploads the results to coveralls.io. Running tests with -race and -cover flags was disabled in 6487ba1 and 6788df7 respectively, due to some limits on time/goroutines being hit on Travis CI. Since we have migrated to GitHub Actions, it is desirable to bring them back. --- .github/workflows/go.yml | 5 +++++ .gitignore | 4 ++++ README.md | 1 + goclean.sh | 5 +++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f722032b16..7573dbe5ef 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -25,3 +25,8 @@ jobs: GO111MODULE: "on" run: | sh ./goclean.sh + + - name: Send coverage + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: profile.cov diff --git a/.gitignore b/.gitignore index 72fb9416ea..c3effe5fc7 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,7 @@ _cgo_export.* _testmain.go *.exe + +# Code coverage files +profile.tmp +profile.cov diff --git a/README.md b/README.md index 352252dd16..d0ec992423 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ btcd ==== [![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) +[![Coverage Status](https://coveralls.io/repos/github/btcsuite/btcd/badge.svg?branch=master)](https://coveralls.io/github/btcsuite/btcd?branch=master) [![ISC License](https://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/btcsuite/btcd) diff --git a/goclean.sh b/goclean.sh index bb0cd7b600..dad9f8f1dc 100755 --- a/goclean.sh +++ b/goclean.sh @@ -4,11 +4,12 @@ # 3. go vet (http://golang.org/cmd/vet) # 4. gosimple (https://github.com/dominikh/go-simple) # 5. unconvert (https://github.com/mdempsky/unconvert) -# +# 6. race detector (http://blog.golang.org/race-detector) +# 7. test coverage (http://blog.golang.org/cover) set -ex -go test -tags="rpctest" ./... +env GORACE="halt_on_error=1" go test -race -tags="rpctest" -covermode atomic -coverprofile=profile.cov ./... # Automatic checks golangci-lint run --deadline=10m --disable-all \ From fff96610aa6a3d82280363ca682ea2745d7d842b Mon Sep 17 00:00:00 2001 From: Mikael Lindlof Date: Sun, 31 May 2020 13:30:50 +0100 Subject: [PATCH 0393/1056] rpc: Add getnodeaddresses JSON-RPC support Add NodeAddresses function to rpcserverConnManager interface for fetching known node addresses. --- btcjson/chainsvrcmds.go | 17 ++++++++++++++++ btcjson/chainsvrcmds_test.go | 26 ++++++++++++++++++++++++ btcjson/chainsvrresults.go | 10 +++++++++ rpcadapters.go | 9 +++++++++ rpcclient/net.go | 37 ++++++++++++++++++++++++++++++++++ rpcserver.go | 39 ++++++++++++++++++++++++++++++++++++ rpcserverhelp.go | 12 +++++++++++ 7 files changed, 150 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index d751d9bce2..793bb503ba 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -557,6 +557,22 @@ func NewGetNetworkHashPSCmd(numBlocks, height *int) *GetNetworkHashPSCmd { } } +// GetNodeAddressesCmd defines the getnodeaddresses JSON-RPC command. +type GetNodeAddressesCmd struct { + Count *int32 `jsonrpcdefault:"1"` +} + +// NewGetNodeAddressesCmd returns a new instance which can be used to issue a +// getnodeaddresses JSON-RPC command. +// +// The parameters which are pointers indicate they are optional. Passing nil +// for optional parameters will use the default value. +func NewGetNodeAddressesCmd(count *int32) *GetNodeAddressesCmd { + return &GetNodeAddressesCmd{ + Count: count, + } +} + // GetPeerInfoCmd defines the getpeerinfo JSON-RPC command. type GetPeerInfoCmd struct{} @@ -974,6 +990,7 @@ func init() { MustRegisterCmd("getnetworkinfo", (*GetNetworkInfoCmd)(nil), flags) MustRegisterCmd("getnettotals", (*GetNetTotalsCmd)(nil), flags) MustRegisterCmd("getnetworkhashps", (*GetNetworkHashPSCmd)(nil), flags) + MustRegisterCmd("getnodeaddresses", (*GetNodeAddressesCmd)(nil), flags) MustRegisterCmd("getpeerinfo", (*GetPeerInfoCmd)(nil), flags) MustRegisterCmd("getrawmempool", (*GetRawMempoolCmd)(nil), flags) MustRegisterCmd("getrawtransaction", (*GetRawTransactionCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index b510b5ec21..c7752d2ba8 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -753,6 +753,32 @@ func TestChainSvrCmds(t *testing.T) { Height: btcjson.Int(123), }, }, + { + name: "getnodeaddresses", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getnodeaddresses") + }, + staticCmd: func() interface{} { + return btcjson.NewGetNodeAddressesCmd(nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getnodeaddresses","params":[],"id":1}`, + unmarshalled: &btcjson.GetNodeAddressesCmd{ + Count: btcjson.Int32(1), + }, + }, + { + name: "getnodeaddresses optional", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getnodeaddresses", 10) + }, + staticCmd: func() interface{} { + return btcjson.NewGetNodeAddressesCmd(btcjson.Int32(10)) + }, + marshalled: `{"jsonrpc":"1.0","method":"getnodeaddresses","params":[10],"id":1}`, + unmarshalled: &btcjson.GetNodeAddressesCmd{ + Count: btcjson.Int32(10), + }, + }, { name: "getpeerinfo", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 5699c53c07..eb9a006077 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -365,6 +365,16 @@ type GetNetworkInfoResult struct { Warnings string `json:"warnings"` } +// GetNodeAddressesResult models the data returned from the getnodeaddresses +// command. +type GetNodeAddressesResult struct { + // Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen + Time int64 `json:"time"` + Services uint64 `json:"services"` // The services offered + Address string `json:"address"` // The address of the node + Port uint16 `json:"port"` // The port of the node +} + // GetPeerInfoResult models the data returned from the getpeerinfo command. type GetPeerInfoResult struct { ID int32 `json:"id"` diff --git a/rpcadapters.go b/rpcadapters.go index 7d2c3a14d0..ddcdf79bf7 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -223,6 +223,15 @@ func (cm *rpcConnManager) RelayTransactions(txns []*mempool.TxDesc) { cm.server.relayTransactions(txns) } +// NodeAddresses returns an array consisting node addresses which can +// potentially be used to find new nodes in the network. +// +// This function is safe for concurrent access and is part of the +// rpcserverConnManager interface implementation. +func (cm *rpcConnManager) NodeAddresses() []*wire.NetAddress { + return cm.server.addrManager.AddressCache() +} + // rpcSyncMgr provides a block manager for use with the RPC server and // implements the rpcserverSyncManager interface. type rpcSyncMgr struct { diff --git a/rpcclient/net.go b/rpcclient/net.go index 6eb7362541..8f781e4ed8 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -281,6 +281,43 @@ func (c *Client) GetNetworkInfo() (*btcjson.GetNetworkInfoResult, error) { return c.GetNetworkInfoAsync().Receive() } +// FutureGetNodeAddressesResult is a future promise to deliver the result of a +// GetNodeAddressesAsync RPC invocation (or an applicable error). +type FutureGetNodeAddressesResult chan *response + +// Receive waits for the response promised by the future and returns data about +// known node addresses. +func (r FutureGetNodeAddressesResult) Receive() ([]btcjson.GetNodeAddressesResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as an array of getnodeaddresses result objects. + var nodeAddresses []btcjson.GetNodeAddressesResult + err = json.Unmarshal(res, &nodeAddresses) + if err != nil { + return nil, err + } + + return nodeAddresses, nil +} + +// GetNodeAddressesAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetNodeAddresses for the blocking version and more details. +func (c *Client) GetNodeAddressesAsync(count *int32) FutureGetNodeAddressesResult { + cmd := btcjson.NewGetNodeAddressesCmd(count) + return c.sendCmd(cmd) +} + +// GetNodeAddresses returns data about known node addresses. +func (c *Client) GetNodeAddresses(count *int32) ([]btcjson.GetNodeAddressesResult, error) { + return c.GetNodeAddressesAsync(count).Receive() +} + // FutureGetPeerInfoResult is a future promise to deliver the result of a // GetPeerInfoAsync RPC invocation (or an applicable error). type FutureGetPeerInfoResult chan *response diff --git a/rpcserver.go b/rpcserver.go index 7e00004123..d7b68bf81b 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -156,6 +156,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "getmininginfo": handleGetMiningInfo, "getnettotals": handleGetNetTotals, "getnetworkhashps": handleGetNetworkHashPS, + "getnodeaddresses": handleGetNodeAddresses, "getpeerinfo": handleGetPeerInfo, "getrawmempool": handleGetRawMempool, "getrawtransaction": handleGetRawTransaction, @@ -2477,6 +2478,40 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru return hashesPerSec.Int64(), nil } +// handleGetNodeAddresses implements the getnodeaddresses command. +func handleGetNodeAddresses(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.GetNodeAddressesCmd) + + count := int32(1) + if c.Count != nil { + count = *c.Count + if count <= 0 { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidParameter, + Message: "Address count out of range", + } + } + } + + nodes := s.cfg.ConnMgr.NodeAddresses() + if n := int32(len(nodes)); n < count { + count = n + } + + addresses := make([]*btcjson.GetNodeAddressesResult, 0, count) + for _, node := range nodes[:count] { + address := &btcjson.GetNodeAddressesResult{ + Time: node.Timestamp.Unix(), + Services: uint64(node.Services), + Address: node.IP.String(), + Port: node.Port, + } + addresses = append(addresses, address) + } + + return addresses, nil +} + // handleGetPeerInfo implements the getpeerinfo command. func handleGetPeerInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { peers := s.cfg.ConnMgr.ConnectedPeers() @@ -4298,6 +4333,10 @@ type rpcserverConnManager interface { // RelayTransactions generates and relays inventory vectors for all of // the passed transactions to all connected peers. RelayTransactions(txns []*mempool.TxDesc) + + // NodeAddresses returns an array consisting node addresses which can + // potentially be used to find new nodes in the network. + NodeAddresses() []*wire.NetAddress } // rpcserverSyncManager represents a sync manager for use with the RPC server. diff --git a/rpcserverhelp.go b/rpcserverhelp.go index bd0f8fd7ff..ca6d2e79c7 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -452,6 +452,17 @@ var helpDescsEnUS = map[string]string{ "getnettotalsresult-totalbytessent": "Total bytes sent", "getnettotalsresult-timemillis": "Number of milliseconds since 1 Jan 1970 GMT", + // GetNodeAddressesResult help. + "getnodeaddressesresult-time": "Timestamp in seconds since epoch (Jan 1 1970 GMT) keeping track of when the node was last seen", + "getnodeaddressesresult-services": "The services offered", + "getnodeaddressesresult-address": "The address of the node", + "getnodeaddressesresult-port": "The port of the node", + + // GetNodeAddressesCmd help. + "getnodeaddresses--synopsis": "Return known addresses which can potentially be used to find new nodes in the network", + "getnodeaddresses-count": "How many addresses to return. Limited to the smaller of 2500 or 23% of all known addresses", + "getnodeaddresses--result0": "List of node addresses", + // GetPeerInfoResult help. "getpeerinforesult-id": "A unique node ID", "getpeerinforesult-addr": "The ip address and port of the peer", @@ -726,6 +737,7 @@ var rpcResultTypes = map[string][]interface{}{ "getmininginfo": {(*btcjson.GetMiningInfoResult)(nil)}, "getnettotals": {(*btcjson.GetNetTotalsResult)(nil)}, "getnetworkhashps": {(*int64)(nil)}, + "getnodeaddresses": {(*[]btcjson.GetNodeAddressesResult)(nil)}, "getpeerinfo": {(*[]btcjson.GetPeerInfoResult)(nil)}, "getrawmempool": {(*[]string)(nil), (*btcjson.GetRawMempoolVerboseResult)(nil)}, "getrawtransaction": {(*string)(nil), (*btcjson.TxRawResult)(nil)}, From 6f49f1f1943cb0a372c6e7da5b302714a0a8ea6f Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 30 Apr 2020 12:55:57 -0300 Subject: [PATCH 0394/1056] btcjson,rpcclient: add support for PSBT commands to rpcclient --- btcjson/chainsvrcmds.go | 15 +++++- btcjson/chainsvrcmds_test.go | 4 +- btcjson/walletsvrcmds.go | 87 ++++++++++++++++++++++++++++++++++ btcjson/walletsvrcmds_test.go | 76 ++++++++++++++++++++++++++++++ btcjson/walletsvrresults.go | 15 ++++++ rpcclient/wallet.go | 89 +++++++++++++++++++++++++++++++++++ 6 files changed, 283 insertions(+), 3 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 793bb503ba..a499169de3 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -80,11 +80,24 @@ func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]fl } } +// ChangeType defines the different output types to use for the change address +// of a transaction built by the node. +type ChangeType string + +var ( + // ChangeTypeLegacy indicates a P2PKH change address type. + ChangeTypeLegacy ChangeType = "legacy" + // ChangeTypeP2SHSegWit indicates a P2WPKH-in-P2SH change address type. + ChangeTypeP2SHSegWit ChangeType = "p2sh-segwit" + // ChangeTypeBech32 indicates a P2WPKH change address type. + ChangeTypeBech32 ChangeType = "bech32" +) + // FundRawTransactionOpts are the different options that can be passed to rawtransaction type FundRawTransactionOpts struct { ChangeAddress *string `json:"changeAddress,omitempty"` ChangePosition *int `json:"changePosition,omitempty"` - ChangeType *string `json:"change_type,omitempty"` + ChangeType *ChangeType `json:"change_type,omitempty"` IncludeWatching *bool `json:"includeWatching,omitempty"` LockUnspents *bool `json:"lockUnspents,omitempty"` FeeRate *float64 `json:"feeRate,omitempty"` // BTC/kB diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index c7752d2ba8..bb589fdf6c 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -127,7 +127,7 @@ func TestChainSvrCmds(t *testing.T) { } changeAddress := "bcrt1qeeuctq9wutlcl5zatge7rjgx0k45228cxez655" change := 1 - changeType := "legacy" + changeType := btcjson.ChangeTypeLegacy watching := true lockUnspents := true feeRate := 0.7 @@ -151,7 +151,7 @@ func TestChainSvrCmds(t *testing.T) { unmarshalled: func() interface{} { changeAddress := "bcrt1qeeuctq9wutlcl5zatge7rjgx0k45228cxez655" change := 1 - changeType := "legacy" + changeType := btcjson.ChangeTypeLegacy watching := true lockUnspents := true feeRate := 0.7 diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index a2c7398827..97cc7ed679 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -8,8 +8,11 @@ package btcjson import ( + "encoding/hex" "encoding/json" "fmt" + + "github.com/btcsuite/btcutil" ) // AddMultisigAddressCmd defines the addmutisigaddress JSON-RPC command. @@ -893,6 +896,88 @@ func NewImportMultiCmd(requests []ImportMultiRequest, options *ImportMultiOption } } +// PsbtInput represents an input to include in the PSBT created by the +// WalletCreateFundedPsbtCmd command. +type PsbtInput struct { + Txid string `json:"txid"` + Vout uint32 `json:"vout"` + Sequence uint32 `json:"sequence"` +} + +// PsbtOutput represents an output to include in the PSBT created by the +// WalletCreateFundedPsbtCmd command. +type PsbtOutput map[string]interface{} + +// NewPsbtOutput returns a new instance of a PSBT output to use with the +// WalletCreateFundedPsbtCmd command. +func NewPsbtOutput(address string, amount btcutil.Amount) PsbtOutput { + return PsbtOutput{address: amount.ToBTC()} +} + +// NewPsbtDataOutput returns a new instance of a PSBT data output to use with +// the WalletCreateFundedPsbtCmd command. +func NewPsbtDataOutput(data []byte) PsbtOutput { + return PsbtOutput{"data": hex.EncodeToString(data)} +} + +// WalletCreateFundedPsbtOpts represents the optional options struct provided +// with a WalletCreateFundedPsbtCmd command. +type WalletCreateFundedPsbtOpts struct { + ChangeAddress *string `json:"changeAddress,omitempty"` + ChangePosition *int64 `json:"changePosition,omitempty"` + ChangeType *ChangeType `json:"change_type,omitempty"` + IncludeWatching *bool `json:"includeWatching,omitempty"` + LockUnspents *bool `json:"lockUnspents,omitempty"` + FeeRate *int64 `json:"feeRate,omitempty"` + SubtractFeeFromOutputs *[]int64 `json:"subtractFeeFromOutputs,omitempty"` + Replaceable *bool `json:"replaceable,omitempty"` + ConfTarget *int64 `json:"conf_target,omitempty"` + EstimateMode *string `json:"estimate_mode,omitempty"` +} + +// WalletCreateFundedPsbtCmd defines the walletcreatefundedpsbt JSON-RPC command. +type WalletCreateFundedPsbtCmd struct { + Inputs []PsbtInput + Outputs []PsbtOutput + Locktime *uint32 + Options *WalletCreateFundedPsbtOpts + Bip32Derivs *bool +} + +// NewWalletCreateFundedPsbtCmd returns a new instance which can be used to issue a +// walletcreatefundedpsbt JSON-RPC command. +func NewWalletCreateFundedPsbtCmd( + inputs []PsbtInput, outputs []PsbtOutput, locktime *uint32, + options *WalletCreateFundedPsbtOpts, bip32Derivs *bool, +) *WalletCreateFundedPsbtCmd { + return &WalletCreateFundedPsbtCmd{ + Inputs: inputs, + Outputs: outputs, + Locktime: locktime, + Options: options, + Bip32Derivs: bip32Derivs, + } +} + +// WalletProcessPsbtCmd defines the walletprocesspsbt JSON-RPC command. +type WalletProcessPsbtCmd struct { + Psbt string + Sign *bool `jsonrpcdefault:"true"` + SighashType *string `jsonrpcdefault:"\"ALL\""` + Bip32Derivs *bool +} + +// NewWalletProcessPsbtCmd returns a new instance which can be used to issue a +// walletprocesspsbt JSON-RPC command. +func NewWalletProcessPsbtCmd(psbt string, sign *bool, sighashType *string, bip32Derivs *bool) *WalletProcessPsbtCmd { + return &WalletProcessPsbtCmd{ + Psbt: psbt, + Sign: sign, + SighashType: sighashType, + Bip32Derivs: bip32Derivs, + } +} + func init() { // The commands in this file are only usable with a wallet server. flags := UFWalletOnly @@ -939,4 +1024,6 @@ func init() { MustRegisterCmd("walletlock", (*WalletLockCmd)(nil), flags) MustRegisterCmd("walletpassphrase", (*WalletPassphraseCmd)(nil), flags) MustRegisterCmd("walletpassphrasechange", (*WalletPassphraseChangeCmd)(nil), flags) + MustRegisterCmd("walletcreatefundedpsbt", (*WalletCreateFundedPsbtCmd)(nil), flags) + MustRegisterCmd("walletprocesspsbt", (*WalletProcessPsbtCmd)(nil), flags) } diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index bc09588268..c45dfed1ad 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcutil" ) // TestWalletSvrCmds tests all of the wallet server commands marshal and @@ -1495,6 +1496,81 @@ func TestWalletSvrCmds(t *testing.T) { }, }, }, + { + name: "walletcreatefundedpsbt", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "walletcreatefundedpsbt", + []btcjson.PsbtInput{ + { + Txid: "1234", + Vout: 0, + Sequence: 0, + }, + }, + []btcjson.PsbtOutput{ + btcjson.NewPsbtOutput("1234", btcutil.Amount(1234)), + btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}), + }, + btcjson.Uint32(1), + btcjson.WalletCreateFundedPsbtOpts{}, + btcjson.Bool(true), + ) + }, + staticCmd: func() interface{} { + return btcjson.NewWalletCreateFundedPsbtCmd( + []btcjson.PsbtInput{ + { + Txid: "1234", + Vout: 0, + Sequence: 0, + }, + }, + []btcjson.PsbtOutput{ + btcjson.NewPsbtOutput("1234", btcutil.Amount(1234)), + btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}), + }, + btcjson.Uint32(1), + &btcjson.WalletCreateFundedPsbtOpts{}, + btcjson.Bool(true), + ) + }, + marshalled: `{"jsonrpc":"1.0","method":"walletcreatefundedpsbt","params":[[{"txid":"1234","vout":0,"sequence":0}],[{"1234":0.00001234},{"data":"01020304"}],1,{},true],"id":1}`, + unmarshalled: &btcjson.WalletCreateFundedPsbtCmd{ + Inputs: []btcjson.PsbtInput{ + { + Txid: "1234", + Vout: 0, + Sequence: 0, + }, + }, + Outputs: []btcjson.PsbtOutput{ + btcjson.NewPsbtOutput("1234", btcutil.Amount(1234)), + btcjson.NewPsbtDataOutput([]byte{1, 2, 3, 4}), + }, + Locktime: btcjson.Uint32(1), + Options: &btcjson.WalletCreateFundedPsbtOpts{}, + Bip32Derivs: btcjson.Bool(true), + }, + }, + { + name: "walletprocesspsbt", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "walletprocesspsbt", "1234", btcjson.Bool(true), btcjson.String("ALL"), btcjson.Bool(true)) + }, + staticCmd: func() interface{} { + return btcjson.NewWalletProcessPsbtCmd( + "1234", btcjson.Bool(true), btcjson.String("ALL"), btcjson.Bool(true)) + }, + marshalled: `{"jsonrpc":"1.0","method":"walletprocesspsbt","params":["1234",true,"ALL",true],"id":1}`, + unmarshalled: &btcjson.WalletProcessPsbtCmd{ + Psbt: "1234", + Sign: btcjson.Bool(true), + SighashType: btcjson.String("ALL"), + Bip32Derivs: btcjson.Bool(true), + }, + }, } t.Logf("Running %d tests", len(tests)) diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index 4ad74b1ed1..0cb78d482f 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -186,3 +186,18 @@ type ImportMultiResults []struct { Error *RPCError `json:"error,omitempty"` Warnings *[]string `json:"warnings,omitempty"` } + +// WalletCreateFundedPsbtResult models the data returned from the +// walletcreatefundedpsbtresult command. +type WalletCreateFundedPsbtResult struct { + Psbt string `json:"psbt"` + Fee float64 `json:"fee"` + ChangePos int64 `json:"changepos"` +} + +// WalletProcessPsbtResult models the data returned from the +// walletprocesspsbtresult command. +type WalletProcessPsbtResult struct { + Psbt string `json:"psbt"` + Complete bool `json:"complete"` +} diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 4f263f102c..6b04ced7bc 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2424,6 +2424,95 @@ func (c *Client) GetInfo() (*btcjson.InfoWalletResult, error) { return c.GetInfoAsync().Receive() } +// FutureImportPubKeyResult is a future promise to deliver the result of an +// WalletCreateFundedPsbt RPC invocation (or an applicable error). +type FutureWalletCreateFundedPsbtResult chan *response + +// Receive waits for the response promised by the future and returns the +// partially signed transaction in PSBT format along with the resulting fee +// and change output index. +func (r FutureWalletCreateFundedPsbtResult) Receive() (*btcjson.WalletCreateFundedPsbtResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a getinfo result object. + var psbtRes btcjson.WalletCreateFundedPsbtResult + err = json.Unmarshal(res, &psbtRes) + if err != nil { + return nil, err + } + + return &psbtRes, nil +} + +// WalletCreateFundedPsbtAsync returns an instance of a type that can be used +// to get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See WalletCreateFundedPsbt for the blocking version and more details. +func (c *Client) WalletCreateFundedPsbtAsync( + inputs []btcjson.PsbtInput, outputs []btcjson.PsbtOutput, locktime *uint32, + options *btcjson.WalletCreateFundedPsbtOpts, bip32Derivs *bool, +) FutureWalletCreateFundedPsbtResult { + cmd := btcjson.NewWalletCreateFundedPsbtCmd(inputs, outputs, locktime, options, bip32Derivs) + return c.sendCmd(cmd) +} + +// WalletCreateFundedPsbt creates and funds a transaction in the Partially +// Signed Transaction format. Inputs will be added if supplied inputs are not +// enough. +func (c *Client) WalletCreateFundedPsbt( + inputs []btcjson.PsbtInput, outputs []btcjson.PsbtOutput, locktime *uint32, + options *btcjson.WalletCreateFundedPsbtOpts, bip32Derivs *bool, +) (*btcjson.WalletCreateFundedPsbtResult, error) { + return c.WalletCreateFundedPsbtAsync(inputs, outputs, locktime, options, bip32Derivs).Receive() +} + +// FutureWalletProcessPsbtResult is a future promise to deliver the result of a +// WalletCreateFundedPsb RPC invocation (or an applicable error). +type FutureWalletProcessPsbtResult chan *response + +// Receive waits for the response promised by the future and returns an updated +// PSBT with signed inputs from the wallet and a boolen indicating if the the +// transaction has a complete set of signatures. +func (r FutureWalletProcessPsbtResult) Receive() (*btcjson.WalletProcessPsbtResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a getinfo result object. + var psbtRes btcjson.WalletProcessPsbtResult + err = json.Unmarshal(res, &psbtRes) + if err != nil { + return nil, err + } + + return &psbtRes, nil +} + +// WalletProcessPsbtAsync returns an instance of a type that can be used +// to get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See WalletProcessPsbt for the blocking version and more details. +func (c *Client) WalletProcessPsbtAsync( + psbt string, sign *bool, sighashType SigHashType, bip32Derivs *bool, +) FutureWalletProcessPsbtResult { + cmd := btcjson.NewWalletProcessPsbtCmd(psbt, sign, btcjson.String(sighashType.String()), bip32Derivs) + return c.sendCmd(cmd) +} + +// WalletProcessPsbt updates a PSBT with input information from our wallet and +// then signs inputs. +func (c *Client) WalletProcessPsbt( + psbt string, sign *bool, sighashType SigHashType, bip32Derivs *bool, +) (*btcjson.WalletProcessPsbtResult, error) { + return c.WalletProcessPsbtAsync(psbt, sign, sighashType, bip32Derivs).Receive() +} + // TODO(davec): Implement // backupwallet (NYI in btcwallet) // encryptwallet (Won't be supported by btcwallet since it's always encrypted) From 5ae1f21cd959414d40b3f67535d6989a9f485bac Mon Sep 17 00:00:00 2001 From: Andrew Tugarinov Date: Tue, 8 Sep 2020 23:15:49 +0700 Subject: [PATCH 0395/1056] Added ListSinceBlockMinConfWatchOnly method. --- btcjson/walletsvrcmds_test.go | 15 +++++++++++++++ rpcclient/wallet.go | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index c45dfed1ad..2e1780c10d 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -708,6 +708,21 @@ func TestWalletSvrCmds(t *testing.T) { IncludeWatchOnly: btcjson.Bool(true), }, }, + { + name: "listsinceblock pad null", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("listsinceblock", "null", 1, false) + }, + staticCmd: func() interface{} { + return btcjson.NewListSinceBlockCmd(nil, btcjson.Int(1), btcjson.Bool(false)) + }, + marshalled: `{"jsonrpc":"1.0","method":"listsinceblock","params":[null,1,false],"id":1}`, + unmarshalled: &btcjson.ListSinceBlockCmd{ + BlockHash: nil, + TargetConfirmations: btcjson.Int(1), + IncludeWatchOnly: btcjson.Bool(false), + }, + }, { name: "listtransactions", newCmd: func() (interface{}, error) { diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 6b04ced7bc..c80f6ba7d2 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -326,6 +326,7 @@ func (c *Client) ListSinceBlockAsync(blockHash *chainhash.Hash) FutureListSinceB // minimum confirmations as a filter. // // See ListSinceBlockMinConf to override the minimum number of confirmations. +// See ListSinceBlockMinConfWatchOnly to override the minimum number of confirmations and watch only parameter. func (c *Client) ListSinceBlock(blockHash *chainhash.Hash) (*btcjson.ListSinceBlockResult, error) { return c.ListSinceBlockAsync(blockHash).Receive() } @@ -354,6 +355,30 @@ func (c *Client) ListSinceBlockMinConf(blockHash *chainhash.Hash, minConfirms in return c.ListSinceBlockMinConfAsync(blockHash, minConfirms).Receive() } +// ListSinceBlockMinConfWatchOnlyAsync returns an instance of a type that can be used to +// get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See ListSinceBlockMinConfWatchOnly for the blocking version and more details. +func (c *Client) ListSinceBlockMinConfWatchOnlyAsync(blockHash *chainhash.Hash, minConfirms int, watchOnly bool) FutureListSinceBlockResult { + var hash *string + if blockHash != nil { + hash = btcjson.String(blockHash.String()) + } + + cmd := btcjson.NewListSinceBlockCmd(hash, &minConfirms, &watchOnly) + return c.sendCmd(cmd) +} + +// ListSinceBlockMinConfWatchOnly returns all transactions added in blocks since the +// specified block hash, or all transactions if it is nil, using the specified +// number of minimum confirmations as a filter. +// +// See ListSinceBlock to use the default minimum number of confirmations and default watch only paremeter. +func (c *Client) ListSinceBlockMinConfWatchOnly(blockHash *chainhash.Hash, minConfirms int, watchOnly bool) (*btcjson.ListSinceBlockResult, error) { + return c.ListSinceBlockMinConfWatchOnlyAsync(blockHash, minConfirms, watchOnly).Receive() +} + // ************************** // Transaction Send Functions // ************************** From ff59bbc14a3441dda427c1e6d1feaa8b7eb411a1 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Sun, 13 Sep 2020 16:45:10 +0200 Subject: [PATCH 0396/1056] wire: add proper types for flag field and improve docs Summary of changes: - Add a new const TxFlagMarker to indicate the flag prefix byte. - Add a new TxFlag type to enumerate the flags supported by the tx parser. This allows us to avoid hardcoded magics, and will make it easier to support new flags in future. - Improve code comments. Closes #1598. --- wire/msgtx.go | 70 ++++++++++++++++++++++++++++++---------------- wire/msgtx_test.go | 12 ++++---- 2 files changed, 52 insertions(+), 30 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index 4f10ef9f98..1e2f69fad4 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -109,14 +109,38 @@ const ( maxWitnessItemSize = 11000 ) -// witnessMarkerBytes are a pair of bytes specific to the witness encoding. If -// this sequence is encoutered, then it indicates a transaction has iwtness -// data. The first byte is an always 0x00 marker byte, which allows decoders to -// distinguish a serialized transaction with witnesses from a regular (legacy) -// one. The second byte is the Flag field, which at the moment is always 0x01, -// but may be extended in the future to accommodate auxiliary non-committed -// fields. -var witessMarkerBytes = []byte{0x00, 0x01} +// TxFlagMarker is the first byte of the FLAG field in a bitcoin tx +// message. It allows decoders to distinguish a regular serialized +// transaction from one that would require a different parsing logic. +// +// Position of FLAG in a bitcoin tx message: +// ┌─────────┬────────────────────┬─────────────┬─────┐ +// │ VERSION │ FLAG │ TX-IN-COUNT │ ... │ +// │ 4 bytes │ 2 bytes (optional) │ varint │ │ +// └─────────┴────────────────────┴─────────────┴─────┘ +// +// Zooming into the FLAG field: +// ┌── FLAG ─────────────┬────────┐ +// │ TxFlagMarker (0x00) │ TxFlag │ +// │ 1 byte │ 1 byte │ +// └─────────────────────┴────────┘ +const TxFlagMarker = 0x00 + +// TxFlag is the second byte of the FLAG field in a bitcoin tx message. +// It indicates the decoding logic to use in the transaction parser, if +// TxFlagMarker is detected in the tx message. +// +// As of writing this, only the witness flag (0x01) is supported, but may be +// extended in the future to accommodate auxiliary non-committed fields. +type TxFlag = byte + +const ( + // WitnessFlag is a flag specific to witness encoding. If the TxFlagMarker + // is encountered followed by the WitnessFlag, then it indicates a + // transaction has witness data. This allows decoders to distinguish a + // serialized transaction with witnesses from a legacy one. + WitnessFlag TxFlag = 0x01 +) // scriptFreeList defines a free list of byte slices (up to the maximum number // defined by the freeListMaxItems constant) that have a cap according to the @@ -420,18 +444,19 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error return err } - // A count of zero (meaning no TxIn's to the uninitiated) indicates - // this is a transaction with witness data. - var flag [1]byte - if count == 0 && enc == WitnessEncoding { - // Next, we need to read the flag, which is a single byte. + // A count of zero (meaning no TxIn's to the uninitiated) means that the + // value is a TxFlagMarker, and hence indicates the presence of a flag. + var flag [1]TxFlag + if count == TxFlagMarker && enc == WitnessEncoding { + // The count varint was in fact the flag marker byte. Next, we need to + // read the flag value, which is a single byte. if _, err = io.ReadFull(r, flag[:]); err != nil { return err } - // At the moment, the flag MUST be 0x01. In the future other - // flag types may be supported. - if flag[0] != 0x01 { + // At the moment, the flag MUST be WitnessFlag (0x01). In the future + // other flag types may be supported. + if flag[0] != WitnessFlag { str := fmt.Sprintf("witness tx but flag byte is %x", flag) return messageError("MsgTx.BtcDecode", str) } @@ -690,14 +715,11 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error // defined in BIP0144. doWitness := enc == WitnessEncoding && msg.HasWitness() if doWitness { - // After the txn's Version field, we include two additional - // bytes specific to the witness encoding. The first byte is an - // always 0x00 marker byte, which allows decoders to - // distinguish a serialized transaction with witnesses from a - // regular (legacy) one. The second byte is the Flag field, - // which at the moment is always 0x01, but may be extended in - // the future to accommodate auxiliary non-committed fields. - if _, err := w.Write(witessMarkerBytes); err != nil { + // After the transaction's Version field, we include two additional + // bytes specific to the witness encoding. This byte sequence is known + // as a flag. The first byte is a marker byte (TxFlagMarker) and the + // second one is the flag value to indicate presence of witness data. + if _, err := w.Write([]byte{TxFlagMarker, WitnessFlag}); err != nil { return err } } diff --git a/wire/msgtx_test.go b/wire/msgtx_test.go index dd809f81e2..66965043e6 100644 --- a/wire/msgtx_test.go +++ b/wire/msgtx_test.go @@ -935,9 +935,9 @@ var multiWitnessTx = &MsgTx{ // tests. var multiWitnessTxEncoded = []byte{ 0x1, 0x0, 0x0, 0x0, // Version - 0x0, // Marker byte indicating 0 inputs, or a segwit encoded tx - 0x1, // Flag byte - 0x1, // Varint for number of inputs + TxFlagMarker, // Marker byte indicating 0 inputs, or a segwit encoded tx + WitnessFlag, // Flag byte + 0x1, // Varint for number of inputs 0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0, 0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2, 0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8, @@ -978,9 +978,9 @@ var multiWitnessTxEncoded = []byte{ // being set to 0x01, the flag is 0x00, which should trigger a decoding error. var multiWitnessTxEncodedNonZeroFlag = []byte{ 0x1, 0x0, 0x0, 0x0, // Version - 0x0, // Marker byte indicating 0 inputs, or a segwit encoded tx - 0x0, // Incorrect flag byte (should be 0x01) - 0x1, // Varint for number of inputs + TxFlagMarker, // Marker byte indicating 0 inputs, or a segwit encoded tx + 0x0, // Incorrect flag byte (should be 0x01) + 0x1, // Varint for number of inputs 0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0, 0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2, 0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8, From 42782bba1816beb4da478e8abbef17312d3590a5 Mon Sep 17 00:00:00 2001 From: ipriver Date: Mon, 7 Sep 2020 19:14:21 +0300 Subject: [PATCH 0397/1056] removed unnecessary GOMAXPROCS function calls --- blockchain/scriptval_test.go | 3 --- btcd.go | 3 --- cmd/addblock/addblock.go | 4 +--- database/cmd/dbtool/main.go | 4 ---- database/ffldb/driver_test.go | 2 -- 5 files changed, 1 insertion(+), 15 deletions(-) diff --git a/blockchain/scriptval_test.go b/blockchain/scriptval_test.go index 56450b7a03..031f04801f 100644 --- a/blockchain/scriptval_test.go +++ b/blockchain/scriptval_test.go @@ -6,7 +6,6 @@ package blockchain import ( "fmt" - "runtime" "testing" "github.com/btcsuite/btcd/txscript" @@ -15,8 +14,6 @@ import ( // TestCheckBlockScripts ensures that validating the all of the scripts in a // known-good block doesn't return an error. func TestCheckBlockScripts(t *testing.T) { - runtime.GOMAXPROCS(runtime.NumCPU()) - testBlockNum := 277647 blockDataFile := fmt.Sprintf("%d.dat.bz2", testBlockNum) blocks, err := loadBlocks(blockDataFile) diff --git a/btcd.go b/btcd.go index c17d6ab48a..3ace182cd8 100644 --- a/btcd.go +++ b/btcd.go @@ -297,9 +297,6 @@ func loadBlockDB() (database.DB, error) { } func main() { - // Use all processor cores. - runtime.GOMAXPROCS(runtime.NumCPU()) - // Block and transaction processing can cause bursty allocations. This // limits the garbage collector from excessively overallocating during // bursts. This value was arrived at with the help of profiling live diff --git a/cmd/addblock/addblock.go b/cmd/addblock/addblock.go index 15b61b6880..8b44f307e4 100644 --- a/cmd/addblock/addblock.go +++ b/cmd/addblock/addblock.go @@ -7,7 +7,6 @@ package main import ( "os" "path/filepath" - "runtime" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain/indexers" @@ -119,8 +118,7 @@ func realMain() error { } func main() { - // Use all processor cores and up some limits. - runtime.GOMAXPROCS(runtime.NumCPU()) + // up some limits. if err := limits.SetLimits(); err != nil { os.Exit(1) } diff --git a/database/cmd/dbtool/main.go b/database/cmd/dbtool/main.go index 9eccd5989b..73c59a6e7d 100644 --- a/database/cmd/dbtool/main.go +++ b/database/cmd/dbtool/main.go @@ -7,7 +7,6 @@ package main import ( "os" "path/filepath" - "runtime" "strings" "github.com/btcsuite/btcd/database" @@ -106,9 +105,6 @@ func realMain() error { } func main() { - // Use all processor cores. - runtime.GOMAXPROCS(runtime.NumCPU()) - // Work around defer not working after os.Exit() if err := realMain(); err != nil { os.Exit(1) diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index 8ba6691af3..f3db909d79 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -9,7 +9,6 @@ import ( "os" "path/filepath" "reflect" - "runtime" "testing" "github.com/btcsuite/btcd/chaincfg" @@ -278,7 +277,6 @@ func TestInterface(t *testing.T) { } // Run all of the interface tests against the database. - runtime.GOMAXPROCS(runtime.NumCPU()) // Change the maximum file size to a small value to force multiple flat // files with the test data set. From c693bd8bc510a83d2fd78541ceea340c66efa913 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Sun, 13 Sep 2020 09:47:39 +0200 Subject: [PATCH 0398/1056] rpcclient: add deriveaddresses RPC command --- btcjson/chainsvrcmds.go | 98 +++++++++++++++++++++--------------- btcjson/chainsvrcmds_test.go | 45 +++++++++++++++++ btcjson/chainsvrresults.go | 3 ++ rpcclient/chain.go | 41 +++++++++++++++ rpcclient/example_test.go | 18 +++++++ 5 files changed, 164 insertions(+), 41 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index a499169de3..b15bce898a 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -80,6 +80,47 @@ func NewCreateRawTransactionCmd(inputs []TransactionInput, amounts map[string]fl } } +// DecodeRawTransactionCmd defines the decoderawtransaction JSON-RPC command. +type DecodeRawTransactionCmd struct { + HexTx string +} + +// NewDecodeRawTransactionCmd returns a new instance which can be used to issue +// a decoderawtransaction JSON-RPC command. +func NewDecodeRawTransactionCmd(hexTx string) *DecodeRawTransactionCmd { + return &DecodeRawTransactionCmd{ + HexTx: hexTx, + } +} + +// DecodeScriptCmd defines the decodescript JSON-RPC command. +type DecodeScriptCmd struct { + HexScript string +} + +// NewDecodeScriptCmd returns a new instance which can be used to issue a +// decodescript JSON-RPC command. +func NewDecodeScriptCmd(hexScript string) *DecodeScriptCmd { + return &DecodeScriptCmd{ + HexScript: hexScript, + } +} + +// DeriveAddressesCmd defines the deriveaddresses JSON-RPC command. +type DeriveAddressesCmd struct { + Descriptor string + Range *DescriptorRange +} + +// NewDeriveAddressesCmd returns a new instance which can be used to issue a +// deriveaddresses JSON-RPC command. +func NewDeriveAddressesCmd(descriptor string, descriptorRange *DescriptorRange) *DeriveAddressesCmd { + return &DeriveAddressesCmd{ + Descriptor: descriptor, + Range: descriptorRange, + } +} + // ChangeType defines the different output types to use for the change address // of a transaction built by the node. type ChangeType string @@ -124,32 +165,6 @@ func NewFundRawTransactionCmd(serializedTx []byte, opts FundRawTransactionOpts, } } -// DecodeRawTransactionCmd defines the decoderawtransaction JSON-RPC command. -type DecodeRawTransactionCmd struct { - HexTx string -} - -// NewDecodeRawTransactionCmd returns a new instance which can be used to issue -// a decoderawtransaction JSON-RPC command. -func NewDecodeRawTransactionCmd(hexTx string) *DecodeRawTransactionCmd { - return &DecodeRawTransactionCmd{ - HexTx: hexTx, - } -} - -// DecodeScriptCmd defines the decodescript JSON-RPC command. -type DecodeScriptCmd struct { - HexScript string -} - -// NewDecodeScriptCmd returns a new instance which can be used to issue a -// decodescript JSON-RPC command. -func NewDecodeScriptCmd(hexScript string) *DecodeScriptCmd { - return &DecodeScriptCmd{ - HexScript: hexScript, - } -} - // GetAddedNodeInfoCmd defines the getaddednodeinfo JSON-RPC command. type GetAddedNodeInfoCmd struct { DNS bool @@ -467,6 +482,19 @@ func NewGetConnectionCountCmd() *GetConnectionCountCmd { return &GetConnectionCountCmd{} } +// GetDescriptorInfoCmd defines the getdescriptorinfo JSON-RPC command. +type GetDescriptorInfoCmd struct { + Descriptor string +} + +// NewGetDescriptorInfoCmd returns a new instance which can be used to issue a +// getdescriptorinfo JSON-RPC command. +func NewGetDescriptorInfoCmd(descriptor string) *GetDescriptorInfoCmd { + return &GetDescriptorInfoCmd{ + Descriptor: descriptor, + } +} + // GetDifficultyCmd defines the getdifficulty JSON-RPC command. type GetDifficultyCmd struct{} @@ -956,28 +984,16 @@ func NewVerifyTxOutProofCmd(proof string) *VerifyTxOutProofCmd { } } -// GetDescriptorInfoCmd defines the getdescriptorinfo JSON-RPC command. -type GetDescriptorInfoCmd struct { - Descriptor string -} - -// NewGetDescriptorInfoCmd returns a new instance which can be used to issue a -// getdescriptorinfo JSON-RPC command. -func NewGetDescriptorInfoCmd(descriptor string) *GetDescriptorInfoCmd { - return &GetDescriptorInfoCmd{ - Descriptor: descriptor, - } -} - func init() { // No special flags for commands in this file. flags := UsageFlag(0) MustRegisterCmd("addnode", (*AddNodeCmd)(nil), flags) MustRegisterCmd("createrawtransaction", (*CreateRawTransactionCmd)(nil), flags) - MustRegisterCmd("fundrawtransaction", (*FundRawTransactionCmd)(nil), flags) MustRegisterCmd("decoderawtransaction", (*DecodeRawTransactionCmd)(nil), flags) MustRegisterCmd("decodescript", (*DecodeScriptCmd)(nil), flags) + MustRegisterCmd("deriveaddresses", (*DeriveAddressesCmd)(nil), flags) + MustRegisterCmd("fundrawtransaction", (*FundRawTransactionCmd)(nil), flags) MustRegisterCmd("getaddednodeinfo", (*GetAddedNodeInfoCmd)(nil), flags) MustRegisterCmd("getbestblockhash", (*GetBestBlockHashCmd)(nil), flags) MustRegisterCmd("getblock", (*GetBlockCmd)(nil), flags) @@ -993,6 +1009,7 @@ func init() { MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags) MustRegisterCmd("getchaintxstats", (*GetChainTxStatsCmd)(nil), flags) MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags) + MustRegisterCmd("getdescriptorinfo", (*GetDescriptorInfoCmd)(nil), flags) MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags) MustRegisterCmd("getgenerate", (*GetGenerateCmd)(nil), flags) MustRegisterCmd("gethashespersec", (*GetHashesPerSecCmd)(nil), flags) @@ -1027,5 +1044,4 @@ func init() { MustRegisterCmd("verifychain", (*VerifyChainCmd)(nil), flags) MustRegisterCmd("verifymessage", (*VerifyMessageCmd)(nil), flags) MustRegisterCmd("verifytxoutproof", (*VerifyTxOutProofCmd)(nil), flags) - MustRegisterCmd("getdescriptorinfo", (*GetDescriptorInfoCmd)(nil), flags) } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index bb589fdf6c..bdf16bbee8 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -220,6 +220,51 @@ func TestChainSvrCmds(t *testing.T) { marshalled: `{"jsonrpc":"1.0","method":"decodescript","params":["00"],"id":1}`, unmarshalled: &btcjson.DecodeScriptCmd{HexScript: "00"}, }, + { + name: "deriveaddresses no range", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("deriveaddresses", "00") + }, + staticCmd: func() interface{} { + return btcjson.NewDeriveAddressesCmd("00", nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"deriveaddresses","params":["00"],"id":1}`, + unmarshalled: &btcjson.DeriveAddressesCmd{Descriptor: "00"}, + }, + { + name: "deriveaddresses int range", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "deriveaddresses", "00", btcjson.DescriptorRange{Value: 2}) + }, + staticCmd: func() interface{} { + return btcjson.NewDeriveAddressesCmd( + "00", &btcjson.DescriptorRange{Value: 2}) + }, + marshalled: `{"jsonrpc":"1.0","method":"deriveaddresses","params":["00",2],"id":1}`, + unmarshalled: &btcjson.DeriveAddressesCmd{ + Descriptor: "00", + Range: &btcjson.DescriptorRange{Value: 2}, + }, + }, + { + name: "deriveaddresses slice range", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "deriveaddresses", "00", + btcjson.DescriptorRange{Value: []int{0, 2}}, + ) + }, + staticCmd: func() interface{} { + return btcjson.NewDeriveAddressesCmd( + "00", &btcjson.DescriptorRange{Value: []int{0, 2}}) + }, + marshalled: `{"jsonrpc":"1.0","method":"deriveaddresses","params":["00",[0,2]],"id":1}`, + unmarshalled: &btcjson.DeriveAddressesCmd{ + Descriptor: "00", + Range: &btcjson.DescriptorRange{Value: []int{0, 2}}, + }, + }, { name: "getaddednodeinfo", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index eb9a006077..bdd135b559 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -764,3 +764,6 @@ type GetDescriptorInfoResult struct { IsSolvable bool `json:"issolvable"` // whether the descriptor is solvable HasPrivateKeys bool `json:"hasprivatekeys"` // whether the descriptor has at least one private key } + +// DeriveAddressesResult models the data from the deriveaddresses command. +type DeriveAddressesResult []string diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 4d7c455dd0..35adbc1000 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -1263,6 +1263,45 @@ func (c *Client) GetBlockStats(hashOrHeight interface{}, stats *[]string) (*btcj return c.GetBlockStatsAsync(hashOrHeight, stats).Receive() } +// FutureDeriveAddressesResult is a future promise to deliver the result of an +// DeriveAddressesAsync RPC invocation (or an applicable error). +type FutureDeriveAddressesResult chan *response + +// Receive waits for the response promised by the future and derives one or more addresses +// corresponding to the given output descriptor. +func (r FutureDeriveAddressesResult) Receive() (*btcjson.DeriveAddressesResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var deriveAddressesResult btcjson.DeriveAddressesResult + + err = json.Unmarshal(res, &deriveAddressesResult) + if err != nil { + return nil, err + } + + return &deriveAddressesResult, nil +} + +// DeriveAddressesAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See DeriveAddresses for the blocking version and more details. +func (c *Client) DeriveAddressesAsync(descriptor string, descriptorRange *btcjson.DescriptorRange) FutureDeriveAddressesResult { + cmd := btcjson.NewDeriveAddressesCmd(descriptor, descriptorRange) + return c.sendCmd(cmd) +} + +// DeriveAddresses derives one or more addresses corresponding to an output +// descriptor. If a ranged descriptor is used, the end or the range +// (in [begin,end] notation) to derive must be specified. +func (c *Client) DeriveAddresses(descriptor string, descriptorRange *btcjson.DescriptorRange) (*btcjson.DeriveAddressesResult, error) { + return c.DeriveAddressesAsync(descriptor, descriptorRange).Receive() +} + // FutureGetDescriptorInfoResult is a future promise to deliver the result of a // GetDescriptorInfoAsync RPC invocation (or an applicable error). type FutureGetDescriptorInfoResult chan *response @@ -1276,10 +1315,12 @@ func (r FutureGetDescriptorInfoResult) Receive() (*btcjson.GetDescriptorInfoResu } var descriptorInfo btcjson.GetDescriptorInfoResult + err = json.Unmarshal(res, &descriptorInfo) if err != nil { return nil, err } + return &descriptorInfo, nil } diff --git a/rpcclient/example_test.go b/rpcclient/example_test.go index 6083e115ec..c9474512fa 100644 --- a/rpcclient/example_test.go +++ b/rpcclient/example_test.go @@ -59,3 +59,21 @@ func ExampleClient_ImportMulti() { fmt.Println(resp[0].Success) // true } + +func ExampleClient_DeriveAddresses() { + client, err := New(connCfg, nil) + if err != nil { + panic(err) + } + defer client.Shutdown() + + addrs, err := client.DeriveAddresses( + "pkh([f34db33f/44'/0'/0']xpub6Cc939fyHvfB9pPLWd3bSyyQFvgKbwhidca49jGCM5Hz5ypEPGf9JVXB4NBuUfPgoHnMjN6oNgdC9KRqM11RZtL8QLW6rFKziNwHDYhZ6Kx/0/*)#ed7px9nu", + &btcjson.DescriptorRange{Value: []int{0, 2}}) + if err != nil { + panic(err) + } + + fmt.Printf("%+v\n", addrs) + // &[14NjenDKkGGq1McUgoSkeUHJpW3rrKLbPW 1Pn6i3cvdGhqbdgNjXHfbaYfiuviPiymXj 181x1NbgGYKLeMXkDdXEAqepG75EgU8XtG] +} From 297c6120bbf93294cca95f22a64bf7c5feb2c3e9 Mon Sep 17 00:00:00 2001 From: Jake Sylvestre Date: Thu, 17 Sep 2020 01:38:18 -0400 Subject: [PATCH 0399/1056] ci: add go 1.15 to tests --- .github/workflows/go.yml | 2 +- README.md | 2 +- go.mod | 2 +- release/README.md | 7 ++----- release/release.sh | 1 - 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f722032b16..a6a6b59749 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go: [1.13, 1.14] + go: [1.14, 1.15] steps: - name: Set up Go uses: actions/setup-go@v2 diff --git a/README.md b/README.md index 8c9d252ad4..4f53f1bbc1 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ which are both under active development. ## Requirements -[Go](http://golang.org) 1.12 or newer. +[Go](http://golang.org) 1.14 or newer. ## Installation diff --git a/go.mod b/go.mod index 80a3d7658f..c53b23d222 100644 --- a/go.mod +++ b/go.mod @@ -14,4 +14,4 @@ require ( golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 ) -go 1.12 +go 1.14 diff --git a/release/README.md b/release/README.md index ea01c7d0bb..7128ef1f16 100644 --- a/release/README.md +++ b/release/README.md @@ -3,10 +3,7 @@ This package contains the build script that the `btcd` project uses in order to build binaries for each new release. As of `go1.13`, with some new build flags, binaries are now reproducible, allowing developers to build the binary on -distinct machines, and end up with a byte-for-byte identical binary. However, -this wasn't _fully_ solved in `go1.13`, as the build system still includes the -directory the binary is built into the binary itself. As a result, our scripts -utilize a work around needed until `go1.13.2`. +distinct machines, and end up with a byte-for-byte identical binary. Every release should note which Go version was used to build the release, so that version should be used for verifying the release. @@ -181,4 +178,4 @@ and `go` (matching the same version used in the release): 8. Extract the archive found in the `btcd-` directory created by the release script and recompute the `SHA256` hash of the release binaries (btcd and btcctl) with `shasum -a 256 `. These should match __exactly__ - as the ones noted above. + as the ones noted above. \ No newline at end of file diff --git a/release/release.sh b/release/release.sh index cc65fb6cf1..de49f64122 100755 --- a/release/release.sh +++ b/release/release.sh @@ -39,7 +39,6 @@ cd $MAINDIR # If BTCDBUILDSYS is set the default list is ignored. Useful to release # for a subset of systems/architectures. SYS=${BTCDBUILDSYS:-" - darwin-386 darwin-amd64 dragonfly-amd64 freebsd-386 From e5521de652133c1d59df6fc505fd3f6e5c23bea9 Mon Sep 17 00:00:00 2001 From: Tristyn Date: Wed, 16 Sep 2020 18:30:48 -0700 Subject: [PATCH 0400/1056] sample-btcd.conf: fix typo --- sample-btcd.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sample-btcd.conf b/sample-btcd.conf index e2beb99cf8..0a765fcabe 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -324,7 +324,7 @@ ; sizes have the highest priority. One consequence of this is that as low-fee ; or free transactions age, they raise in priority thereby making them more ; likely to be included in this section of a new block. This value is limited -; by the blackmaxsize option and will be limited as needed. +; by the blockmaxsize option and will be limited as needed. ; blockprioritysize=50000 From f4024160f30d98097866cfb092e27cba46adb4ac Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Fri, 18 Sep 2020 00:10:32 +0200 Subject: [PATCH 0401/1056] btcjson: add test for null params in searchrawtransactions Closes PR #1476. --- btcjson/chainsvrcmds_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index bdf16bbee8..d44a2ece6f 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1201,6 +1201,26 @@ func TestChainSvrCmds(t *testing.T) { FilterAddrs: &[]string{"1Address"}, }, }, + { + name: "searchrawtransactions", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("searchrawtransactions", "1Address", 0, 5, 10, "null", true, []string{"1Address"}) + }, + staticCmd: func() interface{} { + return btcjson.NewSearchRawTransactionsCmd("1Address", + btcjson.Int(0), btcjson.Int(5), btcjson.Int(10), nil, btcjson.Bool(true), &[]string{"1Address"}) + }, + marshalled: `{"jsonrpc":"1.0","method":"searchrawtransactions","params":["1Address",0,5,10,null,true,["1Address"]],"id":1}`, + unmarshalled: &btcjson.SearchRawTransactionsCmd{ + Address: "1Address", + Verbose: btcjson.Int(0), + Skip: btcjson.Int(5), + Count: btcjson.Int(10), + VinExtra: nil, + Reverse: btcjson.Bool(true), + FilterAddrs: &[]string{"1Address"}, + }, + }, { name: "sendrawtransaction", newCmd: func() (interface{}, error) { From 6daaf73544d70aea67efe468651648a6d03c7b25 Mon Sep 17 00:00:00 2001 From: Elliott Minns Date: Mon, 21 Sep 2020 08:42:35 -0500 Subject: [PATCH 0402/1056] GetBlockTemplate RPC client implementation (#1629) * GetBlockTemplate RPC client implementation * Txid added to the getblocktemplate result * Omitempty for TxID and improved comment for GetBlockTemplate 'rules' field --- btcjson/chainsvrcmds.go | 4 ++++ btcjson/chainsvrresults.go | 6 ++++-- rpcclient/mining.go | 37 ++++++++++++++++++++++++++++++++++++- rpcserverhelp.go | 2 ++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index b15bce898a..0e683af003 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -350,6 +350,10 @@ type TemplateRequest struct { // "proposal". Data string `json:"data,omitempty"` WorkID string `json:"workid,omitempty"` + + // list of supported softfork deployments, by name + // Ref: https://en.bitcoin.it/wiki/BIP_0009#getblocktemplate_changes. + Rules []string `json:"rules,omitempty"` } // convertTemplateRequestField potentially converts the provided value as diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index bdd135b559..9cafe33494 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -236,8 +236,10 @@ type GetBlockFilterResult struct { // GetBlockTemplateResultTx models the transactions field of the // getblocktemplate command. type GetBlockTemplateResultTx struct { - Data string `json:"data"` - Hash string `json:"hash"` + Data string `json:"data"` + Hash string `json:"hash"` + // TODO: remove omitempty once implemented in rpcserver + TxID string `json:"txid,omitempty"` Depends []int64 `json:"depends"` Fee int64 `json:"fee"` SigOps int64 `json:"sigops"` diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 8717d3278f..431054e155 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -461,4 +461,39 @@ func (c *Client) SubmitBlock(block *btcutil.Block, options *btcjson.SubmitBlockO return c.SubmitBlockAsync(block, options).Receive() } -// TODO(davec): Implement GetBlockTemplate +// FutureGetBlockTemplateResponse is a future promise to deliver the result of a +// GetBlockTemplateAsync RPC invocation (or an applicable error). +type FutureGetBlockTemplateResponse chan *response + +// Receive waits for the response promised by the future and returns an error if +// any occurred when retrieving the block template. +func (r FutureGetBlockTemplateResponse) Receive() (*btcjson.GetBlockTemplateResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a getwork result object. + var result btcjson.GetBlockTemplateResult + err = json.Unmarshal(res, &result) + if err != nil { + return nil, err + } + + return &result, nil +} + +// GetBlockTemplateAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetBlockTemplate for the blocking version and more details. +func (c *Client) GetBlockTemplateAsync(req *btcjson.TemplateRequest) FutureGetBlockTemplateResponse { + cmd := btcjson.NewGetBlockTemplateCmd(req) + return c.sendCmd(cmd) +} + +// GetBlockTemplate returns a new block template for mining. +func (c *Client) GetBlockTemplate(req *btcjson.TemplateRequest) (*btcjson.GetBlockTemplateResult, error) { + return c.GetBlockTemplateAsync(req).Receive() +} diff --git a/rpcserverhelp.go b/rpcserverhelp.go index ca6d2e79c7..75a63be0af 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -295,6 +295,7 @@ var helpDescsEnUS = map[string]string{ "templaterequest-target": "The desired target for the block template (this parameter is ignored)", "templaterequest-data": "Hex-encoded block data (only for mode=proposal)", "templaterequest-workid": "The server provided workid if provided in block template (not applicable)", + "templaterequest-rules": "Specific block rules that are to be enforced e.g. '[\"segwit\"]", // GetBlockTemplateResultTx help. "getblocktemplateresulttx-data": "Hex-encoded transaction data (byte-for-byte)", @@ -302,6 +303,7 @@ var helpDescsEnUS = map[string]string{ "getblocktemplateresulttx-depends": "Other transactions before this one (by 1-based index in the 'transactions' list) that must be present in the final block if this one is", "getblocktemplateresulttx-fee": "Difference in value between transaction inputs and outputs (in Satoshi)", "getblocktemplateresulttx-sigops": "Total number of signature operations as counted for purposes of block limits", + "getblocktemplateresulttx-txid": "The transaction id, can be different from hash.", "getblocktemplateresulttx-weight": "The weight of the transaction", // GetBlockTemplateResultAux help. From ac3f235eb958ff6402f8a96a1612feccd95a81aa Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Tue, 15 Sep 2020 23:30:59 +0200 Subject: [PATCH 0403/1056] rpcclient: implement getaddressinfo command Fields such as label, and labelspurpose are not included, since they are deprecated, and will be removed in Bitcoin Core 0.21. --- btcjson/walletsvrcmds.go | 16 ++++- btcjson/walletsvrcmds_test.go | 15 +++- btcjson/walletsvrresults.go | 117 ++++++++++++++++++++++++++++++- btcjson/walletsvrresults_test.go | 80 +++++++++++++++++++++ rpcclient/example_test.go | 31 +++++++- rpcclient/wallet.go | 37 +++++++++- txscript/standard.go | 20 +++++- txscript/standard_test.go | 40 ++++++++++- 8 files changed, 349 insertions(+), 7 deletions(-) create mode 100644 btcjson/walletsvrresults_test.go diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 97cc7ed679..b21fb18712 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The btcsuite developers +// Copyright (c) 2014-2020 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -178,6 +178,19 @@ func NewGetAddressesByAccountCmd(account string) *GetAddressesByAccountCmd { } } +// GetAddressInfoCmd defines the getaddressinfo JSON-RPC command. +type GetAddressInfoCmd struct { + Address string +} + +// NewGetAddressInfoCmd returns a new instance which can be used to issue a +// getaddressinfo JSON-RPC command. +func NewGetAddressInfoCmd(address string) *GetAddressInfoCmd { + return &GetAddressInfoCmd{ + Address: address, + } +} + // GetBalanceCmd defines the getbalance JSON-RPC command. type GetBalanceCmd struct { Account *string @@ -993,6 +1006,7 @@ func init() { MustRegisterCmd("getaccount", (*GetAccountCmd)(nil), flags) MustRegisterCmd("getaccountaddress", (*GetAccountAddressCmd)(nil), flags) MustRegisterCmd("getaddressesbyaccount", (*GetAddressesByAccountCmd)(nil), flags) + MustRegisterCmd("getaddressinfo", (*GetAddressInfoCmd)(nil), flags) MustRegisterCmd("getbalance", (*GetBalanceCmd)(nil), flags) MustRegisterCmd("getbalances", (*GetBalancesCmd)(nil), flags) MustRegisterCmd("getnewaddress", (*GetNewAddressCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 2e1780c10d..d19aa32aac 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2014 The btcsuite developers +// Copyright (c) 2014-2020 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -209,6 +209,19 @@ func TestWalletSvrCmds(t *testing.T) { Account: "acct", }, }, + { + name: "getaddressinfo", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getaddressinfo", "1234") + }, + staticCmd: func() interface{} { + return btcjson.NewGetAddressInfoCmd("1234") + }, + marshalled: `{"jsonrpc":"1.0","method":"getaddressinfo","params":["1234"],"id":1}`, + unmarshalled: &btcjson.GetAddressInfoCmd{ + Address: "1234", + }, + }, { name: "getbalance", newCmd: func() (interface{}, error) { diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index 0cb78d482f..1b9393ab5c 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -1,9 +1,124 @@ -// Copyright (c) 2014 The btcsuite developers +// Copyright (c) 2014-2020 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package btcjson +import ( + "encoding/json" + "github.com/btcsuite/btcd/txscript" +) + +// embeddedAddressInfo includes all getaddressinfo output fields, excluding +// metadata and relation to the wallet. +// +// It represents the non-metadata/non-wallet fields for GetAddressInfo, as well +// as the precise fields for an embedded P2SH or P2WSH address. +type embeddedAddressInfo struct { + Address string `json:"address"` + ScriptPubKey string `json:"scriptPubKey"` + Solvable bool `json:"solvable"` + Descriptor *string `json:"desc,omitempty"` + IsScript bool `json:"isscript"` + IsChange bool `json:"ischange"` + IsWitness bool `json:"iswitness"` + WitnessVersion int `json:"witness_version,omitempty"` + WitnessProgram *string `json:"witness_program,omitempty"` + ScriptType *txscript.ScriptClass `json:"script,omitempty"` + Hex *string `json:"hex,omitempty"` + PubKeys *[]string `json:"pubkeys,omitempty"` + SignaturesRequired *int `json:"sigsrequired,omitempty"` + PubKey *string `json:"pubkey,omitempty"` + IsCompressed *bool `json:"iscompressed,omitempty"` + HDMasterFingerprint *string `json:"hdmasterfingerprint,omitempty"` + Labels []string `json:"labels"` +} + +// GetAddressInfoResult models the result of the getaddressinfo command. It +// contains information about a bitcoin address. +// +// Reference: https://bitcoincore.org/en/doc/0.20.0/rpc/wallet/getaddressinfo +// +// The GetAddressInfoResult has three segments: +// 1. General information about the address. +// 2. Metadata (Timestamp, HDKeyPath, HDSeedID) and wallet fields +// (IsMine, IsWatchOnly). +// 3. Information about the embedded address in case of P2SH or P2WSH. +// Same structure as (1). +type GetAddressInfoResult struct { + embeddedAddressInfo + IsMine bool `json:"ismine"` + IsWatchOnly bool `json:"iswatchonly"` + Timestamp *int `json:"timestamp,omitempty"` + HDKeyPath *string `json:"hdkeypath,omitempty"` + HDSeedID *string `json:"hdseedid,omitempty"` + Embedded *embeddedAddressInfo `json:"embedded,omitempty"` +} + +// UnmarshalJSON provides a custom unmarshaller for GetAddressInfoResult. +// It is adapted to avoid creating a duplicate raw struct for unmarshalling +// the JSON bytes into. +// +// Reference: http://choly.ca/post/go-json-marshalling +func (e *GetAddressInfoResult) UnmarshalJSON(data []byte) error { + // Step 1: Create type aliases of the original struct, including the + // embedded one. + type Alias GetAddressInfoResult + type EmbeddedAlias embeddedAddressInfo + + // Step 2: Create an anonymous struct with raw replacements for the special + // fields. + aux := &struct { + ScriptType *string `json:"script,omitempty"` + Embedded *struct { + ScriptType *string `json:"script,omitempty"` + *EmbeddedAlias + } `json:"embedded,omitempty"` + *Alias + }{ + Alias: (*Alias)(e), + } + + // Step 3: Unmarshal the data into the anonymous struct. + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + // Step 4: Convert the raw fields to the desired types + var ( + sc *txscript.ScriptClass + err error + ) + + if aux.ScriptType != nil { + sc, err = txscript.NewScriptClass(*aux.ScriptType) + if err != nil { + return err + } + } + + e.ScriptType = sc + + if aux.Embedded != nil { + var ( + embeddedSc *txscript.ScriptClass + err error + ) + + if aux.Embedded.ScriptType != nil { + embeddedSc, err = txscript.NewScriptClass(*aux.Embedded.ScriptType) + if err != nil { + return err + } + } + + e.Embedded = (*embeddedAddressInfo)(aux.Embedded.EmbeddedAlias) + e.Embedded.ScriptType = embeddedSc + } + + return nil +} + // GetTransactionDetailsResult models the details data from the gettransaction command. // // This models the "short" version of the ListTransactionsResult type, which diff --git a/btcjson/walletsvrresults_test.go b/btcjson/walletsvrresults_test.go new file mode 100644 index 0000000000..173226b8b5 --- /dev/null +++ b/btcjson/walletsvrresults_test.go @@ -0,0 +1,80 @@ +// Copyright (c) 2020 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcjson + +import ( + "encoding/json" + "errors" + "reflect" + "testing" + + "github.com/btcsuite/btcd/txscript" + "github.com/davecgh/go-spew/spew" +) + +// TestGetAddressInfoResult ensures that custom unmarshalling of +// GetAddressInfoResult works as intended. +func TestGetAddressInfoResult(t *testing.T) { + t.Parallel() + + // arbitrary script class to use in tests + nonStandard, _ := txscript.NewScriptClass("nonstandard") + + tests := []struct { + name string + result string + want GetAddressInfoResult + wantErr error + }{ + { + name: "GetAddressInfoResult - no ScriptType", + result: `{}`, + want: GetAddressInfoResult{}, + }, + { + name: "GetAddressInfoResult - ScriptType", + result: `{"script":"nonstandard","address":"1abc"}`, + want: GetAddressInfoResult{ + embeddedAddressInfo: embeddedAddressInfo{ + Address: "1abc", + ScriptType: nonStandard, + }, + }, + }, + { + name: "GetAddressInfoResult - embedded ScriptType", + result: `{"embedded": {"script":"nonstandard","address":"121313"}}`, + want: GetAddressInfoResult{ + Embedded: &embeddedAddressInfo{ + Address: "121313", + ScriptType: nonStandard, + }, + }, + }, + { + name: "GetAddressInfoResult - invalid ScriptType", + result: `{"embedded": {"script":"foo","address":"121313"}}`, + wantErr: txscript.ErrUnsupportedScriptType, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + var out GetAddressInfoResult + err := json.Unmarshal([]byte(test.result), &out) + if err != nil && !errors.Is(err, test.wantErr) { + t.Errorf("Test #%d (%s) unexpected error: %v, want: %v", i, + test.name, err, test.wantErr) + continue + } + + if !reflect.DeepEqual(out, test.want) { + t.Errorf("Test #%d (%s) unexpected unmarshalled data - "+ + "got %v, want %v", i, test.name, spew.Sdump(out), + spew.Sdump(test.want)) + continue + } + } +} diff --git a/rpcclient/example_test.go b/rpcclient/example_test.go index c9474512fa..e930778a01 100644 --- a/rpcclient/example_test.go +++ b/rpcclient/example_test.go @@ -1,8 +1,11 @@ +// Copyright (c) 2020 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + package rpcclient import ( "fmt" - "github.com/btcsuite/btcd/btcjson" ) @@ -77,3 +80,29 @@ func ExampleClient_DeriveAddresses() { fmt.Printf("%+v\n", addrs) // &[14NjenDKkGGq1McUgoSkeUHJpW3rrKLbPW 1Pn6i3cvdGhqbdgNjXHfbaYfiuviPiymXj 181x1NbgGYKLeMXkDdXEAqepG75EgU8XtG] } + +func ExampleClient_GetAddressInfo() { + connCfg = &ConnConfig{ + Host: "localhost:18332", + User: "user", + Pass: "pass", + HTTPPostMode: true, + DisableTLS: true, + } + + client, err := New(connCfg, nil) + if err != nil { + panic(err) + } + defer client.Shutdown() + + info, err := client.GetAddressInfo("2NF1FbxtUAsvdU4uW1UC2xkBVatp6cYQuJ3") + if err != nil { + panic(err) + } + + fmt.Println(info.Address) // 2NF1FbxtUAsvdU4uW1UC2xkBVatp6cYQuJ3 + fmt.Println(info.ScriptType.String()) // witness_v0_keyhash + fmt.Println(*info.HDKeyPath) // m/49'/1'/0'/0/4 + fmt.Println(info.Embedded.Address) // tb1q3x2h2kh57wzg7jz00jhwn0ycvqtdk2ane37j27 +} diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index c80f6ba7d2..10bdfca6d8 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2017 The btcsuite developers +// Copyright (c) 2014-2020 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -939,6 +939,41 @@ func (c *Client) CreateNewAccount(account string) error { return c.CreateNewAccountAsync(account).Receive() } +// FutureGetAddressInfoResult is a future promise to deliver the result of an +// GetAddressInfoAsync RPC invocation (or an applicable error). +type FutureGetAddressInfoResult chan *response + +// Receive waits for the response promised by the future and returns the information +// about the given bitcoin address. +func (r FutureGetAddressInfoResult) Receive() (*btcjson.GetAddressInfoResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var getAddressInfoResult btcjson.GetAddressInfoResult + err = json.Unmarshal(res, &getAddressInfoResult) + if err != nil { + return nil, err + } + return &getAddressInfoResult, nil +} + +// GetAddressInfoAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetAddressInfo for the blocking version and more details. +func (c *Client) GetAddressInfoAsync(address string) FutureGetAddressInfoResult { + cmd := btcjson.NewGetAddressInfoCmd(address) + return c.sendCmd(cmd) +} + +// GetAddressInfo returns information about the given bitcoin address. +func (c *Client) GetAddressInfo(address string) (*btcjson.GetAddressInfoResult, error) { + return c.GetAddressInfoAsync(address).Receive() +} + // FutureGetNewAddressResult is a future promise to deliver the result of a // GetNewAddressAsync RPC invocation (or an applicable error). type FutureGetNewAddressResult struct { diff --git a/txscript/standard.go b/txscript/standard.go index a7e929d101..2cad218e95 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2013-2020 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -58,6 +58,7 @@ const ( WitnessV0ScriptHashTy // Pay to witness script hash. MultiSigTy // Multi signature. NullDataTy // Empty data-only (provably prunable). + WitnessUnknownTy // Witness unknown ) // scriptClassToName houses the human-readable strings which describe each @@ -71,6 +72,7 @@ var scriptClassToName = []string{ WitnessV0ScriptHashTy: "witness_v0_scripthash", MultiSigTy: "multisig", NullDataTy: "nulldata", + WitnessUnknownTy: "witness_unknown", } // String implements the Stringer interface by returning the name of @@ -188,6 +190,22 @@ func GetScriptClass(script []byte) ScriptClass { return typeOfScript(pops) } +// NewScriptClass returns the ScriptClass corresponding to the string name +// provided as argument. ErrUnsupportedScriptType error is returned if the +// name doesn't correspond to any known ScriptClass. +// +// Not to be confused with GetScriptClass. +func NewScriptClass(name string) (*ScriptClass, error) { + for i, n := range scriptClassToName { + if n == name { + value := ScriptClass(i) + return &value, nil + } + } + + return nil, fmt.Errorf("%w: %s", ErrUnsupportedScriptType, name) +} + // expectedInputs returns the number of arguments required by a script. // If the script is of unknown type such that the number can not be determined // then -1 is returned. We are an internal function and thus assume that class diff --git a/txscript/standard_test.go b/txscript/standard_test.go index e24d5f615b..37dd8f8a37 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2013-2020 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -7,6 +7,7 @@ package txscript import ( "bytes" "encoding/hex" + "errors" "reflect" "testing" @@ -1213,3 +1214,40 @@ func TestNullDataScript(t *testing.T) { } } } + +// TestNewScriptClass tests whether NewScriptClass returns a valid ScriptClass. +func TestNewScriptClass(t *testing.T) { + tests := []struct { + name string + scriptName string + want *ScriptClass + wantErr error + }{ + { + name: "NewScriptClass - ok", + scriptName: NullDataTy.String(), + want: func() *ScriptClass { + s := NullDataTy + return &s + }(), + }, + { + name: "NewScriptClass - invalid", + scriptName: "foo", + wantErr: ErrUnsupportedScriptType, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := NewScriptClass(tt.scriptName) + if err != nil && !errors.Is(err, tt.wantErr) { + t.Errorf("NewScriptClass() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewScriptClass() got = %v, want %v", got, tt.want) + } + }) + } +} From 134051378620b1c1410c84396439a0c4937c7a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedger=20M=C3=BCffke?= Date: Wed, 23 Sep 2020 08:47:26 +0200 Subject: [PATCH 0404/1056] Fix link to using bootstrap.dat --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 3eea886e4c..c3c206060b 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -73,4 +73,4 @@ Typically btcd will run and start downloading the block chain with no extra configuration necessary, however, there is an optional method to use a `bootstrap.dat` file that may speed up the initial block chain download process. -* [Using bootstrap.dat](https://github.com/btcsuite/btcd/tree/master/docs/using_bootstrap_dat.md) +* [Using bootstrap.dat](https://github.com/btcsuite/btcd/blob/master/docs/configuration.md#using-bootstrapdat) From e9a51e8dcd673c563a549676ebd4384b0318a9b7 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Sun, 20 Sep 2020 15:46:32 +0200 Subject: [PATCH 0405/1056] rpcclient: implement getwalletinfo command --- btcjson/walletsvrresults.go | 54 ++++++++++++++++++++++++++++++++ btcjson/walletsvrresults_test.go | 47 +++++++++++++++++++++++++++ rpcclient/example_test.go | 26 ++++++++++----- rpcclient/wallet.go | 36 ++++++++++++++++++++- 4 files changed, 154 insertions(+), 9 deletions(-) diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index 1b9393ab5c..2569dde424 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -6,6 +6,8 @@ package btcjson import ( "encoding/json" + "fmt" + "github.com/btcsuite/btcd/txscript" ) @@ -150,6 +152,58 @@ type GetTransactionResult struct { Hex string `json:"hex"` } +type ScanningOrFalse struct { + Value interface{} +} + +type ScanProgress struct { + Duration int `json:"duration"` + Progress float64 `json:"progress"` +} + +// MarshalJSON implements the json.Marshaler interface +func (h ScanningOrFalse) MarshalJSON() ([]byte, error) { + return json.Marshal(h.Value) +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (h *ScanningOrFalse) UnmarshalJSON(data []byte) error { + var unmarshalled interface{} + if err := json.Unmarshal(data, &unmarshalled); err != nil { + return err + } + + switch v := unmarshalled.(type) { + case bool: + h.Value = v + case map[string]interface{}: + h.Value = ScanProgress{ + Duration: int(v["duration"].(float64)), + Progress: v["progress"].(float64), + } + default: + return fmt.Errorf("invalid scanning value: %v", unmarshalled) + } + + return nil +} + +// GetWalletInfoResult models the result of the getwalletinfo command. +type GetWalletInfoResult struct { + WalletName string `json:"walletname"` + WalletVersion int `json:"walletversion"` + TransactionCount int `json:"txcount"` + KeyPoolOldest int `json:"keypoololdest"` + KeyPoolSize int `json:"keypoolsize"` + KeyPoolSizeHDInternal *int `json:"keypoolsize_hd_internal,omitempty"` + UnlockedUntil *int `json:"unlocked_until,omitempty"` + PayTransactionFee float64 `json:"paytxfee"` + HDSeedID *string `json:"hdseedid,omitempty"` + PrivateKeysEnabled bool `json:"private_keys_enabled"` + AvoidReuse bool `json:"avoid_reuse"` + Scanning ScanningOrFalse `json:"scanning"` +} + // InfoWalletResult models the data returned by the wallet server getinfo // command. type InfoWalletResult struct { diff --git a/btcjson/walletsvrresults_test.go b/btcjson/walletsvrresults_test.go index 173226b8b5..fd44b066b8 100644 --- a/btcjson/walletsvrresults_test.go +++ b/btcjson/walletsvrresults_test.go @@ -78,3 +78,50 @@ func TestGetAddressInfoResult(t *testing.T) { } } } + +// TestGetWalletInfoResult ensures that custom unmarshalling of +// GetWalletInfoResult works as intended. +func TestGetWalletInfoResult(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + result string + want GetWalletInfoResult + }{ + { + name: "GetWalletInfoResult - not scanning", + result: `{"scanning":false}`, + want: GetWalletInfoResult{ + Scanning: ScanningOrFalse{Value: false}, + }, + }, + { + name: "GetWalletInfoResult - scanning", + result: `{"scanning":{"duration":10,"progress":1.0}}`, + want: GetWalletInfoResult{ + Scanning: ScanningOrFalse{ + Value: ScanProgress{Duration: 10, Progress: 1.0}, + }, + }, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + var out GetWalletInfoResult + err := json.Unmarshal([]byte(test.result), &out) + if err != nil { + t.Errorf("Test #%d (%s) unexpected error: %v", i, + test.name, err) + continue + } + + if !reflect.DeepEqual(out, test.want) { + t.Errorf("Test #%d (%s) unexpected unmarshalled data - "+ + "got %v, want %v", i, test.name, spew.Sdump(out), + spew.Sdump(test.want)) + continue + } + } +} diff --git a/rpcclient/example_test.go b/rpcclient/example_test.go index e930778a01..ba8bb5ecb5 100644 --- a/rpcclient/example_test.go +++ b/rpcclient/example_test.go @@ -82,14 +82,6 @@ func ExampleClient_DeriveAddresses() { } func ExampleClient_GetAddressInfo() { - connCfg = &ConnConfig{ - Host: "localhost:18332", - User: "user", - Pass: "pass", - HTTPPostMode: true, - DisableTLS: true, - } - client, err := New(connCfg, nil) if err != nil { panic(err) @@ -106,3 +98,21 @@ func ExampleClient_GetAddressInfo() { fmt.Println(*info.HDKeyPath) // m/49'/1'/0'/0/4 fmt.Println(info.Embedded.Address) // tb1q3x2h2kh57wzg7jz00jhwn0ycvqtdk2ane37j27 } + +func ExampleClient_GetWalletInfo() { + client, err := New(connCfg, nil) + if err != nil { + panic(err) + } + defer client.Shutdown() + + info, err := client.GetWalletInfo() + if err != nil { + panic(err) + } + + fmt.Println(info.WalletVersion) // 169900 + fmt.Println(info.TransactionCount) // 22 + fmt.Println(*info.HDSeedID) // eb44e4e9b864ef17e7ba947da746375b000f5d94 + fmt.Println(info.Scanning.Value) // false +} diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 10bdfca6d8..3824de990c 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2573,10 +2573,44 @@ func (c *Client) WalletProcessPsbt( return c.WalletProcessPsbtAsync(psbt, sign, sighashType, bip32Derivs).Receive() } +// FutureGetWalletInfoResult is a future promise to deliver the result of an +// GetWalletInfoAsync RPC invocation (or an applicable error). +type FutureGetWalletInfoResult chan *response + +// Receive waits for the response promised by the future and returns the result +// of wallet state info. +func (r FutureGetWalletInfoResult) Receive() (*btcjson.GetWalletInfoResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var getWalletInfoResult btcjson.GetWalletInfoResult + err = json.Unmarshal(res, &getWalletInfoResult) + if err != nil { + return nil, err + } + return &getWalletInfoResult, nil +} + +// GetWalletInfoAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetWalletInfo for the blocking version and more details. +func (c *Client) GetWalletInfoAsync() FutureGetWalletInfoResult { + cmd := btcjson.NewGetWalletInfoCmd() + return c.sendCmd(cmd) +} + +// GetWalletInfo returns various wallet state info. +func (c *Client) GetWalletInfo() (*btcjson.GetWalletInfoResult, error) { + return c.GetWalletInfoAsync().Receive() +} + // TODO(davec): Implement // backupwallet (NYI in btcwallet) // encryptwallet (Won't be supported by btcwallet since it's always encrypted) -// getwalletinfo (NYI in btcwallet or btcjson) // listaddressgroupings (NYI in btcwallet) // listreceivedbyaccount (NYI in btcwallet) From 0bf42f447686272b7bd8c41a04727edd090d5f31 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 21 Sep 2020 23:11:48 +0200 Subject: [PATCH 0406/1056] rpcserver: add txid to getblocktemplate response --- btcjson/chainsvrresults.go | 7 +++---- rpcserver.go | 7 ++++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 9cafe33494..aeb1f6ac7f 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -236,10 +236,9 @@ type GetBlockFilterResult struct { // GetBlockTemplateResultTx models the transactions field of the // getblocktemplate command. type GetBlockTemplateResultTx struct { - Data string `json:"data"` - Hash string `json:"hash"` - // TODO: remove omitempty once implemented in rpcserver - TxID string `json:"txid,omitempty"` + Data string `json:"data"` + Hash string `json:"hash"` + TxID string `json:"txid"` Depends []int64 `json:"depends"` Fee int64 `json:"fee"` SigOps int64 `json:"sigops"` diff --git a/rpcserver.go b/rpcserver.go index d7b68bf81b..9a52301ee8 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1689,8 +1689,8 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld transactions := make([]btcjson.GetBlockTemplateResultTx, 0, numTx-1) txIndex := make(map[chainhash.Hash]int64, numTx) for i, tx := range msgBlock.Transactions { - txHash := tx.TxHash() - txIndex[txHash] = int64(i) + txID := tx.TxHash() + txIndex[txID] = int64(i) // Skip the coinbase transaction. if i == 0 { @@ -1724,7 +1724,8 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld bTx := btcutil.NewTx(tx) resultTx := btcjson.GetBlockTemplateResultTx{ Data: hex.EncodeToString(txBuf.Bytes()), - Hash: txHash.String(), + TxID: txID.String(), + Hash: tx.WitnessHash().String(), Depends: depends, Fee: template.Fees[i], SigOps: template.SigOpCosts[i], From 584c3823342c4eb2b538928b50be2881059f06a5 Mon Sep 17 00:00:00 2001 From: Henry Fisher Date: Fri, 10 Apr 2020 18:09:29 -0700 Subject: [PATCH 0407/1056] rpc: add signrawtransactionwithwallet interface Adds interface for issuing a signrawtransactionwithwallet command. Note that this does not add functionality for the btcd rpc server itself, it simply assumes that the RPC client has this ability and gives an API for interacting with the RPC client. rpc: add signrawtransactionwithwallet interface --- btcjson/walletsvrcmds.go | 34 ++++++++ btcjson/walletsvrcmds_test.go | 97 +++++++++++++++++++++++ btcjson/walletsvrresults.go | 8 ++ rpcclient/rawtransactions.go | 145 +++++++++++++++++++++++++++++++++- 4 files changed, 283 insertions(+), 1 deletion(-) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index b21fb18712..c3ecc0c862 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -668,6 +668,39 @@ func NewSignRawTransactionCmd(hexEncodedTx string, inputs *[]RawTxInput, privKey } } +// RawTxWitnessInput models the data needed for raw transaction input that is used in +// the SignRawTransactionWithWalletCmd struct. The RedeemScript is required for P2SH inputs, +// the WitnessScript is required for P2WSH or P2SH-P2WSH witness scripts, and the Amount is +// required for Segwit inputs. Otherwise, those fields can be left blank. +type RawTxWitnessInput struct { + Txid string `json:"txid"` + Vout uint32 `json:"vout"` + ScriptPubKey string `json:"scriptPubKey"` + RedeemScript *string `json:"redeemScript,omitempty"` + WitnessScript *string `json:"witnessScript,omitempty"` + Amount *float64 `json:"amount,omitempty"` // In BTC +} + +// SignRawTransactionWithWalletCmd defines the signrawtransactionwithwallet JSON-RPC command. +type SignRawTransactionWithWalletCmd struct { + RawTx string + Inputs *[]RawTxWitnessInput + SigHashType *string `jsonrpcdefault:"\"ALL\""` +} + +// NewSignRawTransactionWithWalletCmd returns a new instance which can be used to issue a +// signrawtransactionwithwallet JSON-RPC command. +// +// The parameters which are pointers indicate they are optional. Passing nil +// for optional parameters will use the default value. +func NewSignRawTransactionWithWalletCmd(hexEncodedTx string, inputs *[]RawTxWitnessInput, sigHashType *string) *SignRawTransactionWithWalletCmd { + return &SignRawTransactionWithWalletCmd{ + RawTx: hexEncodedTx, + Inputs: inputs, + SigHashType: sigHashType, + } +} + // WalletLockCmd defines the walletlock JSON-RPC command. type WalletLockCmd struct{} @@ -1035,6 +1068,7 @@ func init() { MustRegisterCmd("settxfee", (*SetTxFeeCmd)(nil), flags) MustRegisterCmd("signmessage", (*SignMessageCmd)(nil), flags) MustRegisterCmd("signrawtransaction", (*SignRawTransactionCmd)(nil), flags) + MustRegisterCmd("signrawtransactionwithwallet", (*SignRawTransactionWithWalletCmd)(nil), flags) MustRegisterCmd("walletlock", (*WalletLockCmd)(nil), flags) MustRegisterCmd("walletpassphrase", (*WalletPassphraseCmd)(nil), flags) MustRegisterCmd("walletpassphrasechange", (*WalletPassphraseChangeCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index d19aa32aac..38c7c3bd7c 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -1233,6 +1233,103 @@ func TestWalletSvrCmds(t *testing.T) { Flags: btcjson.String("ALL"), }, }, + { + name: "signrawtransactionwithwallet", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("signrawtransactionwithwallet", "001122") + }, + staticCmd: func() interface{} { + return btcjson.NewSignRawTransactionWithWalletCmd("001122", nil, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122"],"id":1}`, + unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{ + RawTx: "001122", + Inputs: nil, + SigHashType: btcjson.String("ALL"), + }, + }, + { + name: "signrawtransactionwithwallet optional1", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01","witnessScript":"02","amount":1.5}]`) + }, + staticCmd: func() interface{} { + txInputs := []btcjson.RawTxWitnessInput{ + { + Txid: "123", + Vout: 1, + ScriptPubKey: "00", + RedeemScript: btcjson.String("01"), + WitnessScript: btcjson.String("02"), + Amount: btcjson.Float64(1.5), + }, + } + + return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01","witnessScript":"02","amount":1.5}]],"id":1}`, + unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{ + RawTx: "001122", + Inputs: &[]btcjson.RawTxWitnessInput{ + { + Txid: "123", + Vout: 1, + ScriptPubKey: "00", + RedeemScript: btcjson.String("01"), + WitnessScript: btcjson.String("02"), + Amount: btcjson.Float64(1.5), + }, + }, + SigHashType: btcjson.String("ALL"), + }, + }, + { + name: "signrawtransactionwithwallet optional1 with blank fields in input", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]`) + }, + staticCmd: func() interface{} { + txInputs := []btcjson.RawTxWitnessInput{ + { + Txid: "123", + Vout: 1, + ScriptPubKey: "00", + RedeemScript: btcjson.String("01"), + }, + } + + return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[{"txid":"123","vout":1,"scriptPubKey":"00","redeemScript":"01"}]],"id":1}`, + unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{ + RawTx: "001122", + Inputs: &[]btcjson.RawTxWitnessInput{ + { + Txid: "123", + Vout: 1, + ScriptPubKey: "00", + RedeemScript: btcjson.String("01"), + }, + }, + SigHashType: btcjson.String("ALL"), + }, + }, + { + name: "signrawtransactionwithwallet optional2", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("signrawtransactionwithwallet", "001122", `[]`, "ALL") + }, + staticCmd: func() interface{} { + txInputs := []btcjson.RawTxWitnessInput{} + return btcjson.NewSignRawTransactionWithWalletCmd("001122", &txInputs, btcjson.String("ALL")) + }, + marshalled: `{"jsonrpc":"1.0","method":"signrawtransactionwithwallet","params":["001122",[],"ALL"],"id":1}`, + unmarshalled: &btcjson.SignRawTransactionWithWalletCmd{ + RawTx: "001122", + Inputs: &[]btcjson.RawTxWitnessInput{}, + SigHashType: btcjson.String("ALL"), + }, + }, { name: "walletlock", newCmd: func() (interface{}, error) { diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index 2569dde424..e2ba201daf 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -308,6 +308,14 @@ type SignRawTransactionResult struct { Errors []SignRawTransactionError `json:"errors,omitempty"` } +// SignRawTransactionWithWalletResult models the data from the +// signrawtransactionwithwallet command. +type SignRawTransactionWithWalletResult struct { + Hex string `json:"hex"` + Complete bool `json:"complete"` + Errors []SignRawTransactionError `json:"errors,omitempty"` +} + // ValidateAddressWalletResult models the data returned by the wallet server // validateaddress command. type ValidateAddressWalletResult struct { diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 4e8d4e4d9c..35038ed9d3 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -555,7 +555,7 @@ func (c *Client) SignRawTransaction4Async(tx *wire.MsgTx, return c.sendCmd(cmd) } -// SignRawTransaction4 signs inputs for the passed transaction using the +// SignRawTransaction4 signs inputs for the passed transaction using // the specified signature hash type given the list of information about extra // input transactions and a potential list of private keys needed to perform // the signing process. The private keys, if specified, must be in wallet @@ -582,6 +582,149 @@ func (c *Client) SignRawTransaction4(tx *wire.MsgTx, hashType).Receive() } +// FutureSignRawTransactionWithWalletResult is a future promise to deliver +// the result of the SignRawTransactionWithWalletAsync RPC invocation (or +// an applicable error). +type FutureSignRawTransactionWithWalletResult chan *response + +// Receive waits for the response promised by the future and returns the +// signed transaction as well as whether or not all inputs are now signed. +func (r FutureSignRawTransactionWithWalletResult) Receive() (*wire.MsgTx, bool, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, false, err + } + + // Unmarshal as a signtransactionwithwallet result. + var signRawTxWithWalletResult btcjson.SignRawTransactionWithWalletResult + err = json.Unmarshal(res, &signRawTxWithWalletResult) + if err != nil { + return nil, false, err + } + + // Decode the serialized transaction hex to raw bytes. + serializedTx, err := hex.DecodeString(signRawTxWithWalletResult.Hex) + if err != nil { + return nil, false, err + } + + // Deserialize the transaction and return it. + var msgTx wire.MsgTx + if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil { + return nil, false, err + } + + return &msgTx, signRawTxWithWalletResult.Complete, nil +} + +// SignRawTransactionWithWalletAsync returns an instance of a type that can be used +// to get the result of the RPC at some future time by invoking the Receive function +// on the returned instance. +// +// See SignRawTransactionWithWallet for the blocking version and more details. +func (c *Client) SignRawTransactionWithWalletAsync(tx *wire.MsgTx) FutureSignRawTransactionWithWalletResult { + txHex := "" + if tx != nil { + // Serialize the transaction and convert to hex string. + buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) + if err := tx.Serialize(buf); err != nil { + return newFutureError(err) + } + txHex = hex.EncodeToString(buf.Bytes()) + } + + cmd := btcjson.NewSignRawTransactionWithWalletCmd(txHex, nil, nil) + return c.sendCmd(cmd) +} + +// SignRawTransactionWithWallet signs inputs for the passed transaction and returns +// the signed transaction as well as whether or not all inputs are now signed. +// +// This function assumes the RPC server already knows the input transactions for the +// passed transaction which needs to be signed and uses the default signature hash +// type. Use one of the SignRawTransactionWithWallet# variants to specify that +// information if needed. +func (c *Client) SignRawTransactionWithWallet(tx *wire.MsgTx) (*wire.MsgTx, bool, error) { + return c.SignRawTransactionWithWalletAsync(tx).Receive() +} + +// SignRawTransactionWithWallet2Async returns an instance of a type that can be +// used to get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See SignRawTransactionWithWallet2 for the blocking version and more details. +func (c *Client) SignRawTransactionWithWallet2Async(tx *wire.MsgTx, + inputs []btcjson.RawTxWitnessInput) FutureSignRawTransactionWithWalletResult { + + txHex := "" + if tx != nil { + // Serialize the transaction and convert to hex string. + buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) + if err := tx.Serialize(buf); err != nil { + return newFutureError(err) + } + txHex = hex.EncodeToString(buf.Bytes()) + } + + cmd := btcjson.NewSignRawTransactionWithWalletCmd(txHex, &inputs, nil) + return c.sendCmd(cmd) +} + +// SignRawTransactionWithWallet2 signs inputs for the passed transaction given the +// list of information about the input transactions needed to perform the signing +// process. +// +// This only input transactions that need to be specified are ones the +// RPC server does not already know. Already known input transactions will be +// merged with the specified transactions. +// +// See SignRawTransactionWithWallet if the RPC server already knows the input +// transactions. +func (c *Client) SignRawTransactionWithWallet2(tx *wire.MsgTx, + inputs []btcjson.RawTxWitnessInput) (*wire.MsgTx, bool, error) { + + return c.SignRawTransactionWithWallet2Async(tx, inputs).Receive() +} + +// SignRawTransactionWithWallet3Async returns an instance of a type that can +// be used to get the result of the RPC at some future time by invoking the +// Receive function on the returned instance. +// +// See SignRawTransactionWithWallet3 for the blocking version and more details. +func (c *Client) SignRawTransactionWithWallet3Async(tx *wire.MsgTx, + inputs []btcjson.RawTxWitnessInput, hashType SigHashType) FutureSignRawTransactionWithWalletResult { + + txHex := "" + if tx != nil { + // Serialize the transaction and convert to hex string. + buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) + if err := tx.Serialize(buf); err != nil { + return newFutureError(err) + } + txHex = hex.EncodeToString(buf.Bytes()) + } + + cmd := btcjson.NewSignRawTransactionWithWalletCmd(txHex, &inputs, btcjson.String(string(hashType))) + return c.sendCmd(cmd) +} + +// SignRawTransactionWithWallet3 signs inputs for the passed transaction using +// the specified signature hash type given the list of information about extra +// input transactions. +// +// The only input transactions that need to be specified are ones the RPC server +// does not already know. This means the list of transaction inputs can be nil +// if the RPC server already knows them all. +// +// This function should only used if a non-default signature hash type is +// desired. Otherwise, see SignRawTransactionWithWallet if the RPC server already +// knows the input transactions, or SignRawTransactionWihWallet2 if it does not. +func (c *Client) SignRawTransactionWithWallet3(tx *wire.MsgTx, + inputs []btcjson.RawTxWitnessInput, hashType SigHashType) (*wire.MsgTx, bool, error) { + + return c.SignRawTransactionWithWallet3Async(tx, inputs, hashType).Receive() +} + // FutureSearchRawTransactionsResult is a future promise to deliver the result // of the SearchRawTransactionsAsync RPC invocation (or an applicable error). type FutureSearchRawTransactionsResult chan *response From 6519c04a6fcea38faee9b5febcd49fb10ea95128 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Mon, 28 Sep 2020 14:42:18 +0200 Subject: [PATCH 0408/1056] rpcclient: implement gettxoutsetinfo command --- btcjson/chainsvrresults.go | 60 ++++++++++++++++++++++++++++ btcjson/chainsvrresults_test.go | 71 +++++++++++++++++++++++++++++++++ rpcclient/chain.go | 38 ++++++++++++++++++ rpcclient/example_test.go | 19 +++++++++ 4 files changed, 188 insertions(+) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index aeb1f6ac7f..689fbe6742 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -9,6 +9,8 @@ import ( "encoding/hex" "encoding/json" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" ) @@ -435,6 +437,64 @@ type GetTxOutResult struct { Coinbase bool `json:"coinbase"` } +// GetTxOutSetInfoResult models the data from the gettxoutsetinfo command. +type GetTxOutSetInfoResult struct { + Height int64 `json:"height"` + BestBlock chainhash.Hash `json:"bestblock"` + Transactions int64 `json:"transactions"` + TxOuts int64 `json:"txouts"` + BogoSize int64 `json:"bogosize"` + HashSerialized chainhash.Hash `json:"hash_serialized_2"` + DiskSize int64 `json:"disk_size"` + TotalAmount btcutil.Amount `json:"total_amount"` +} + +// UnmarshalJSON unmarshals the result of the gettxoutsetinfo JSON-RPC call +func (g *GetTxOutSetInfoResult) UnmarshalJSON(data []byte) error { + // Step 1: Create type aliases of the original struct. + type Alias GetTxOutSetInfoResult + + // Step 2: Create an anonymous struct with raw replacements for the special + // fields. + aux := &struct { + BestBlock string `json:"bestblock"` + HashSerialized string `json:"hash_serialized_2"` + TotalAmount float64 `json:"total_amount"` + *Alias + }{ + Alias: (*Alias)(g), + } + + // Step 3: Unmarshal the data into the anonymous struct. + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + // Step 4: Convert the raw fields to the desired types + blockHash, err := chainhash.NewHashFromStr(aux.BestBlock) + if err != nil { + return err + } + + g.BestBlock = *blockHash + + serializedHash, err := chainhash.NewHashFromStr(aux.HashSerialized) + if err != nil { + return err + } + + g.HashSerialized = *serializedHash + + amount, err := btcutil.NewAmount(aux.TotalAmount) + if err != nil { + return err + } + + g.TotalAmount = amount + + return nil +} + // GetNetTotalsResult models the data returned from the getnettotals command. type GetNetTotalsResult struct { TotalBytesRecv uint64 `json:"totalbytesrecv"` diff --git a/btcjson/chainsvrresults_test.go b/btcjson/chainsvrresults_test.go index 1d568e2658..0bab922b0d 100644 --- a/btcjson/chainsvrresults_test.go +++ b/btcjson/chainsvrresults_test.go @@ -6,8 +6,13 @@ package btcjson_test import ( "encoding/json" + "reflect" "testing" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcutil" + "github.com/davecgh/go-spew/spew" + "github.com/btcsuite/btcd/btcjson" ) @@ -86,3 +91,69 @@ func TestChainSvrCustomResults(t *testing.T) { } } } + +// TestGetTxOutSetInfoResult ensures that custom unmarshalling of +// GetTxOutSetInfoResult works as intended. +func TestGetTxOutSetInfoResult(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + result string + want btcjson.GetTxOutSetInfoResult + }{ + { + name: "GetTxOutSetInfoResult - not scanning", + result: `{"height":123,"bestblock":"000000000000005f94116250e2407310463c0a7cf950f1af9ebe935b1c0687ab","transactions":1,"txouts":1,"bogosize":1,"hash_serialized_2":"9a0a561203ff052182993bc5d0cb2c620880bfafdbd80331f65fd9546c3e5c3e","disk_size":1,"total_amount":0.2}`, + want: btcjson.GetTxOutSetInfoResult{ + Height: 123, + BestBlock: func() chainhash.Hash { + h, err := chainhash.NewHashFromStr("000000000000005f94116250e2407310463c0a7cf950f1af9ebe935b1c0687ab") + if err != nil { + panic(err) + } + + return *h + }(), + Transactions: 1, + TxOuts: 1, + BogoSize: 1, + HashSerialized: func() chainhash.Hash { + h, err := chainhash.NewHashFromStr("9a0a561203ff052182993bc5d0cb2c620880bfafdbd80331f65fd9546c3e5c3e") + if err != nil { + panic(err) + } + + return *h + }(), + DiskSize: 1, + TotalAmount: func() btcutil.Amount { + a, err := btcutil.NewAmount(0.2) + if err != nil { + panic(err) + } + + return a + }(), + }, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + var out btcjson.GetTxOutSetInfoResult + err := json.Unmarshal([]byte(test.result), &out) + if err != nil { + t.Errorf("Test #%d (%s) unexpected error: %v", i, + test.name, err) + continue + } + + if !reflect.DeepEqual(out, test.want) { + t.Errorf("Test #%d (%s) unexpected unmarshalled data - "+ + "got %v, want %v", i, test.name, spew.Sdump(out), + spew.Sdump(test.want)) + continue + } + } +} diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 35adbc1000..d478da7a00 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -1026,6 +1026,44 @@ func (c *Client) GetTxOut(txHash *chainhash.Hash, index uint32, mempool bool) (* return c.GetTxOutAsync(txHash, index, mempool).Receive() } +// FutureGetTxOutSetInfoResult is a future promise to deliver the result of a +// GetTxOutSetInfoAsync RPC invocation (or an applicable error). +type FutureGetTxOutSetInfoResult chan *response + +// Receive waits for the response promised by the future and returns the +// results of GetTxOutSetInfoAsync RPC invocation. +func (r FutureGetTxOutSetInfoResult) Receive() (*btcjson.GetTxOutSetInfoResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as an gettxoutsetinfo result object. + var txOutSetInfo *btcjson.GetTxOutSetInfoResult + err = json.Unmarshal(res, &txOutSetInfo) + if err != nil { + return nil, err + } + + return txOutSetInfo, nil +} + +// GetTxOutSetInfoAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetTxOutSetInfo for the blocking version and more details. +func (c *Client) GetTxOutSetInfoAsync() FutureGetTxOutSetInfoResult { + cmd := btcjson.NewGetTxOutSetInfoCmd() + return c.sendCmd(cmd) +} + +// GetTxOutSetInfo returns the statistics about the unspent transaction output +// set. +func (c *Client) GetTxOutSetInfo() (*btcjson.GetTxOutSetInfoResult, error) { + return c.GetTxOutSetInfoAsync().Receive() +} + // FutureRescanBlocksResult is a future promise to deliver the result of a // RescanBlocksAsync RPC invocation (or an applicable error). // diff --git a/rpcclient/example_test.go b/rpcclient/example_test.go index ba8bb5ecb5..35159317b5 100644 --- a/rpcclient/example_test.go +++ b/rpcclient/example_test.go @@ -116,3 +116,22 @@ func ExampleClient_GetWalletInfo() { fmt.Println(*info.HDSeedID) // eb44e4e9b864ef17e7ba947da746375b000f5d94 fmt.Println(info.Scanning.Value) // false } + +func ExampleClient_GetTxOutSetInfo() { + client, err := New(connCfg, nil) + if err != nil { + panic(err) + } + defer client.Shutdown() + + r, err := client.GetTxOutSetInfo() + if err != nil { + panic(err) + } + + fmt.Println(r.TotalAmount.String()) // 20947654.56996054 BTC + fmt.Println(r.BestBlock.String()) // 000000000000005f94116250e2407310463c0a7cf950f1af9ebe935b1c0687ab + fmt.Println(r.TxOuts) // 24280607 + fmt.Println(r.Transactions) // 9285603 + fmt.Println(r.DiskSize) // 1320871611 +} From 6adfc07d1ea97599c7e06cf6ea84daa0c0ef57e6 Mon Sep 17 00:00:00 2001 From: David Mazary Date: Sat, 3 Oct 2020 21:12:09 -0400 Subject: [PATCH 0409/1056] Unmarshal hashes/second as float in GetMiningInfoResult --- btcjson/chainsvrresults.go | 4 +-- btcjson/chainsvrresults_test.go | 46 +++++++++++++++++++++++++++++++-- rpcserver.go | 4 +-- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 689fbe6742..00f8cd6149 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -673,8 +673,8 @@ type GetMiningInfoResult struct { Errors string `json:"errors"` Generate bool `json:"generate"` GenProcLimit int32 `json:"genproclimit"` - HashesPerSec int64 `json:"hashespersec"` - NetworkHashPS int64 `json:"networkhashps"` + HashesPerSec float64 `json:"hashespersec"` + NetworkHashPS float64 `json:"networkhashps"` PooledTx uint64 `json:"pooledtx"` TestNet bool `json:"testnet"` } diff --git a/btcjson/chainsvrresults_test.go b/btcjson/chainsvrresults_test.go index 0bab922b0d..72dcd8d7ec 100644 --- a/btcjson/chainsvrresults_test.go +++ b/btcjson/chainsvrresults_test.go @@ -9,11 +9,10 @@ import ( "reflect" "testing" + "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcutil" "github.com/davecgh/go-spew/spew" - - "github.com/btcsuite/btcd/btcjson" ) // TestChainSvrCustomResults ensures any results that have custom marshalling @@ -157,3 +156,46 @@ func TestGetTxOutSetInfoResult(t *testing.T) { } } } + +// TestChainSvrMiningInfoResults ensures GetMiningInfoResults are unmarshalled correctly +func TestChainSvrMiningInfoResults(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + result string + expected btcjson.GetMiningInfoResult + }{ + { + name: "mining info with integer networkhashps", + result: `{"networkhashps": 89790618491361}`, + expected: btcjson.GetMiningInfoResult{ + NetworkHashPS: 89790618491361, + }, + }, + { + name: "mining info with scientific notation networkhashps", + result: `{"networkhashps": 8.9790618491361e+13}`, + expected: btcjson.GetMiningInfoResult{ + NetworkHashPS: 89790618491361, + }, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + var miningInfoResult btcjson.GetMiningInfoResult + err := json.Unmarshal([]byte(test.result), &miningInfoResult) + if err != nil { + t.Errorf("Test #%d (%s) unexpected error: %v", i, + test.name, err) + continue + } + if miningInfoResult != test.expected { + t.Errorf("Test #%d (%s) unexpected marhsalled data - "+ + "got %+v, want %+v", i, test.name, miningInfoResult, + test.expected) + continue + } + } +} diff --git a/rpcserver.go b/rpcserver.go index 9a52301ee8..f159f2397f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2366,8 +2366,8 @@ func handleGetMiningInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{ Difficulty: getDifficultyRatio(best.Bits, s.cfg.ChainParams), Generate: s.cfg.CPUMiner.IsMining(), GenProcLimit: s.cfg.CPUMiner.NumWorkers(), - HashesPerSec: int64(s.cfg.CPUMiner.HashesPerSecond()), - NetworkHashPS: networkHashesPerSec, + HashesPerSec: s.cfg.CPUMiner.HashesPerSecond(), + NetworkHashPS: float64(networkHashesPerSec), PooledTx: uint64(s.cfg.TxMemPool.Count()), TestNet: cfg.TestNet3, } From 1d75e0a8854337de76bbbb10cebb301ff1c7ef3a Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Tue, 6 Oct 2020 14:28:19 +0200 Subject: [PATCH 0410/1056] rpcclient: add more wallet commands Implement backupwallet, dumpwallet, loadwallet and unloadwallet. --- btcjson/chainsvrresults.go | 11 +++ btcjson/walletsvrcmds.go | 36 +++++++++ btcjson/walletsvrcmds_test.go | 43 +++++++++++ rpcclient/wallet.go | 139 ++++++++++++++++++++++++++++++++-- 4 files changed, 224 insertions(+), 5 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 00f8cd6149..e70900d87b 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -828,3 +828,14 @@ type GetDescriptorInfoResult struct { // DeriveAddressesResult models the data from the deriveaddresses command. type DeriveAddressesResult []string + +// LoadWalletResult models the data from the loadwallet command +type LoadWalletResult struct { + Name string `json:"name"` + Warning string `json:"warning"` +} + +// DumpWalletResult models the data from the dumpwallet command +type DumpWalletResult struct { + Filename string `json:"filename"` +} diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index c3ecc0c862..f63a59445b 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -313,6 +313,39 @@ func NewGetWalletInfoCmd() *GetWalletInfoCmd { return &GetWalletInfoCmd{} } +// BackupWalletCmd defines the backupwallet JSON-RPC command +type BackupWalletCmd struct { + Destination string +} + +// NewBackupWalletCmd returns a new instance which can be used to issue a +// backupwallet JSON-RPC command +func NewBackupWalletCmd(destination string) *BackupWalletCmd { + return &BackupWalletCmd{Destination: destination} +} + +// UnloadWalletCmd defines the unloadwallet JSON-RPC command +type UnloadWalletCmd struct { + WalletName *string +} + +// NewUnloadWalletCmd returns a new instance which can be used to issue a +// unloadwallet JSON-RPC command. +func NewUnloadWalletCmd(walletName *string) *UnloadWalletCmd { + return &UnloadWalletCmd{WalletName: walletName} +} + +// LoadWalletCmd defines the loadwallet JSON-RPC command +type LoadWalletCmd struct { + WalletName string +} + +// NewLoadWalletCmd returns a new instance which can be used to issue a +// loadwallet JSON-RPC command +func NewLoadWalletCmd(walletName string) *LoadWalletCmd { + return &LoadWalletCmd{WalletName: walletName} +} + // ImportPrivKeyCmd defines the importprivkey JSON-RPC command. type ImportPrivKeyCmd struct { PrivKey string @@ -1030,6 +1063,7 @@ func init() { MustRegisterCmd("addmultisigaddress", (*AddMultisigAddressCmd)(nil), flags) MustRegisterCmd("addwitnessaddress", (*AddWitnessAddressCmd)(nil), flags) + MustRegisterCmd("backupwallet", (*BackupWalletCmd)(nil), flags) MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags) MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags) MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags) @@ -1059,6 +1093,7 @@ func init() { MustRegisterCmd("listsinceblock", (*ListSinceBlockCmd)(nil), flags) MustRegisterCmd("listtransactions", (*ListTransactionsCmd)(nil), flags) MustRegisterCmd("listunspent", (*ListUnspentCmd)(nil), flags) + MustRegisterCmd("loadwallet", (*LoadWalletCmd)(nil), flags) MustRegisterCmd("lockunspent", (*LockUnspentCmd)(nil), flags) MustRegisterCmd("move", (*MoveCmd)(nil), flags) MustRegisterCmd("sendfrom", (*SendFromCmd)(nil), flags) @@ -1069,6 +1104,7 @@ func init() { MustRegisterCmd("signmessage", (*SignMessageCmd)(nil), flags) MustRegisterCmd("signrawtransaction", (*SignRawTransactionCmd)(nil), flags) MustRegisterCmd("signrawtransactionwithwallet", (*SignRawTransactionWithWalletCmd)(nil), flags) + MustRegisterCmd("unloadwallet", (*UnloadWalletCmd)(nil), flags) MustRegisterCmd("walletlock", (*WalletLockCmd)(nil), flags) MustRegisterCmd("walletpassphrase", (*WalletPassphraseCmd)(nil), flags) MustRegisterCmd("walletpassphrasechange", (*WalletPassphraseChangeCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 38c7c3bd7c..5d36a12ab4 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -75,6 +75,49 @@ func TestWalletSvrCmds(t *testing.T) { Address: "1address", }, }, + { + name: "backupwallet", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("backupwallet", "backup.dat") + }, + staticCmd: func() interface{} { + return btcjson.NewBackupWalletCmd("backup.dat") + }, + marshalled: `{"jsonrpc":"1.0","method":"backupwallet","params":["backup.dat"],"id":1}`, + unmarshalled: &btcjson.BackupWalletCmd{Destination: "backup.dat"}, + }, + { + name: "loadwallet", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("loadwallet", "wallet.dat") + }, + staticCmd: func() interface{} { + return btcjson.NewLoadWalletCmd("wallet.dat") + }, + marshalled: `{"jsonrpc":"1.0","method":"loadwallet","params":["wallet.dat"],"id":1}`, + unmarshalled: &btcjson.LoadWalletCmd{WalletName: "wallet.dat"}, + }, + { + name: "unloadwallet", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("unloadwallet", "default") + }, + staticCmd: func() interface{} { + return btcjson.NewUnloadWalletCmd(btcjson.String("default")) + }, + marshalled: `{"jsonrpc":"1.0","method":"unloadwallet","params":["default"],"id":1}`, + unmarshalled: &btcjson.UnloadWalletCmd{WalletName: btcjson.String("default")}, + }, + {name: "unloadwallet - nil arg", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("unloadwallet") + }, + staticCmd: func() interface{} { + return btcjson.NewUnloadWalletCmd(nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"unloadwallet","params":[],"id":1}`, + unmarshalled: &btcjson.UnloadWalletCmd{WalletName: nil}, + }, { name: "createmultisig", newCmd: func() (interface{}, error) { diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 3824de990c..c7064bfe5f 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2608,12 +2608,141 @@ func (c *Client) GetWalletInfo() (*btcjson.GetWalletInfoResult, error) { return c.GetWalletInfoAsync().Receive() } +// FutureBackupWalletResult is a future promise to deliver the result of an +// BackupWalletAsync RPC invocation (or an applicable error) +type FutureBackupWalletResult chan *response + +// Receive waits for the response promised by the future +func (r FutureBackupWalletResult) Receive() error { + _, err := receiveFuture(r) + return err +} + +// BackupWalletAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See BackupWallet for the blocking version and more details. +func (c *Client) BackupWalletAsync(destination string) FutureBackupWalletResult { + return c.sendCmd(btcjson.NewBackupWalletCmd(destination)) +} + +// BackupWallet safely copies current wallet file to destination, which can +// be a directory or a path with filename +func (c *Client) BackupWallet(destination string) error { + return c.BackupWalletAsync(destination).Receive() +} + +// FutureDumpWalletResult is a future promise to deliver the result of an +// DumpWallet RPC invocation (or an applicable error) +type FutureDumpWalletResult chan *response + +// Receive waits for the response promised by the future +func (r FutureDumpWalletResult) Receive() (*btcjson.DumpWalletResult, error) { + bytes, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var res btcjson.DumpWalletResult + err = json.Unmarshal(bytes, &res) + return &res, err +} + +// DumpWalletAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See DumpWalletAsync for the blocking version and more details. +func (c *Client) DumpWalletAsync(destination string) FutureDumpWalletResult { + return c.sendCmd(btcjson.NewDumpWalletCmd(destination)) +} + +// DumpWallet dumps all wallet keys in a human-readable format to a server-side file. +func (c *Client) DumpWallet(destination string) (*btcjson.DumpWalletResult, error) { + return c.DumpWalletAsync(destination).Receive() +} + +// FutureImportWalletResult is a future promise to deliver the result of an +// ImportWalletAsync RPC invocation (or an applicable error) +type FutureImportWalletResult chan *response + +// Receive waits for the response promised by the future +func (r FutureImportWalletResult) Receive() error { + _, err := receiveFuture(r) + return err +} + +// ImportWalletAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See ImportWallet for the blocking version and more details. +func (c *Client) ImportWalletAsync(filename string) FutureImportWalletResult { + return c.sendCmd(btcjson.NewImportWalletCmd(filename)) +} + +// ImportWallet imports keys from a wallet dump file (see DumpWallet). +func (c *Client) ImportWallet(filename string) error { + return c.ImportWalletAsync(filename).Receive() +} + +// FutureUnloadWalletResult is a future promise to deliver the result of an +// UnloadWalletAsync RPC invocation (or an applicable error) +type FutureUnloadWalletResult chan *response + +// Receive waits for the response promised by the future +func (r FutureUnloadWalletResult) Receive() error { + _, err := receiveFuture(r) + return err +} + +// UnloadWalletAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See UnloadWallet for the blocking version and more details. +func (c *Client) UnloadWalletAsync(walletName *string) FutureUnloadWalletResult { + return c.sendCmd(btcjson.NewUnloadWalletCmd(walletName)) +} + +// UnloadWallet unloads the referenced wallet. If the RPC server URL already +// contains the name of the wallet, like http://127.0.0.1:8332/wallet/, +// the parameter must be nil, or it'll return an error. +func (c *Client) UnloadWallet(walletName *string) error { + return c.UnloadWalletAsync(walletName).Receive() +} + +// FutureLoadWalletResult is a future promise to deliver the result of an +// LoadWalletAsync RPC invocation (or an applicable error) +type FutureLoadWalletResult chan *response + +// Receive waits for the response promised by the future +func (r FutureLoadWalletResult) Receive() (*btcjson.LoadWalletResult, error) { + bytes, err := receiveFuture(r) + if err != nil { + return nil, err + } + var result btcjson.LoadWalletResult + err = json.Unmarshal(bytes, &result) + return &result, err +} + +// LoadWalletAsync returns an instance of a type that can be used to get the result +// of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See LoadWallet for the blocking version and more details. +func (c *Client) LoadWalletAsync(walletName string) FutureLoadWalletResult { + return c.sendCmd(btcjson.NewLoadWalletCmd(walletName)) +} + +// LoadWallet loads a wallet from a wallet file or directory. +func (c *Client) LoadWallet(walletName string) (*btcjson.LoadWalletResult, error) { + return c.LoadWalletAsync(walletName).Receive() +} + // TODO(davec): Implement -// backupwallet (NYI in btcwallet) // encryptwallet (Won't be supported by btcwallet since it's always encrypted) // listaddressgroupings (NYI in btcwallet) // listreceivedbyaccount (NYI in btcwallet) - -// DUMP -// importwallet (NYI in btcwallet) -// dumpwallet (NYI in btcwallet) From 5e56ca05e15ac2a081990d4cfe16f0c54682e4c5 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Thu, 8 Oct 2020 23:28:09 +0200 Subject: [PATCH 0411/1056] btcjson: add new JSON-RPC errors and document them --- btcjson/jsonrpcerr.go | 133 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 18 deletions(-) diff --git a/btcjson/jsonrpcerr.go b/btcjson/jsonrpcerr.go index ea62fb55a6..d67b58bbb6 100644 --- a/btcjson/jsonrpcerr.go +++ b/btcjson/jsonrpcerr.go @@ -30,36 +30,133 @@ var ( // General application defined JSON errors. const ( - ErrRPCMisc RPCErrorCode = -1 + // ErrRPCMisc indicates an exception thrown during command handling. + ErrRPCMisc RPCErrorCode = -1 + + // ErrRPCForbiddenBySafeMode indicates that server is in safe mode, and + // command is not allowed in safe mode. ErrRPCForbiddenBySafeMode RPCErrorCode = -2 - ErrRPCType RPCErrorCode = -3 + + // ErrRPCType indicates that an unexpected type was passed as parameter. + ErrRPCType RPCErrorCode = -3 + + // ErrRPCInvalidAddressOrKey indicates an invalid address or key. ErrRPCInvalidAddressOrKey RPCErrorCode = -5 - ErrRPCOutOfMemory RPCErrorCode = -7 - ErrRPCInvalidParameter RPCErrorCode = -8 - ErrRPCDatabase RPCErrorCode = -20 - ErrRPCDeserialization RPCErrorCode = -22 - ErrRPCVerify RPCErrorCode = -25 - ErrRPCInWarmup RPCErrorCode = -28 + + // ErrRPCOutOfMemory indicates that the server ran out of memory during + // operation. + ErrRPCOutOfMemory RPCErrorCode = -7 + + // ErrRPCInvalidParameter indicates an invalid, missing, or duplicate + // parameter. + ErrRPCInvalidParameter RPCErrorCode = -8 + + // ErrRPCDatabase indicates a database error. + ErrRPCDatabase RPCErrorCode = -20 + + // ErrRPCDeserialization indicates an error parsing or validating structure + // in raw format. + ErrRPCDeserialization RPCErrorCode = -22 + + // ErrRPCVerify indicates a general error during transaction or block + // submission. + ErrRPCVerify RPCErrorCode = -25 + + // ErrRPCVerifyRejected indicates that transaction or block was rejected by + // network rules. + ErrRPCVerifyRejected RPCErrorCode = -26 + + // ErrRPCVerifyAlreadyInChain indicates that submitted transaction is + // already in chain. + ErrRPCVerifyAlreadyInChain RPCErrorCode = -27 + + // ErrRPCInWarmup indicates that client is still warming up. + ErrRPCInWarmup RPCErrorCode = -28 + + // ErrRPCInWarmup indicates that the RPC error is deprecated. + ErrRPCMethodDeprecated RPCErrorCode = -32 ) // Peer-to-peer client errors. const ( - ErrRPCClientNotConnected RPCErrorCode = -9 + // ErrRPCClientNotConnected indicates that Bitcoin is not connected. + ErrRPCClientNotConnected RPCErrorCode = -9 + + // ErrRPCClientInInitialDownload indicates that client is still downloading + // initial blocks. ErrRPCClientInInitialDownload RPCErrorCode = -10 - ErrRPCClientNodeNotAdded RPCErrorCode = -24 + + // ErrRPCClientNodeAlreadyAdded indicates that node is already added. + ErrRPCClientNodeAlreadyAdded RPCErrorCode = -23 + + // ErrRPCClientNodeNotAdded indicates that node has not been added before. + ErrRPCClientNodeNotAdded RPCErrorCode = -24 + + // ErrRPCClientNodeNotConnected indicates that node to disconnect was not + // found in connected nodes. + ErrRPCClientNodeNotConnected RPCErrorCode = -29 + + // ErrRPCClientInvalidIPOrSubnet indicates an invalid IP/Subnet. + ErrRPCClientInvalidIPOrSubnet RPCErrorCode = -30 + + // ErrRPCClientP2PDisabled indicates that no valid connection manager + // instance was found. + ErrRPCClientP2PDisabled RPCErrorCode = -31 +) + +// Chain errors +const ( + // ErrRPCClientMempoolDisabled indicates that no mempool instance was + // found. + ErrRPCClientMempoolDisabled RPCErrorCode = -33 ) // Wallet JSON errors const ( - ErrRPCWallet RPCErrorCode = -4 - ErrRPCWalletInsufficientFunds RPCErrorCode = -6 - ErrRPCWalletInvalidAccountName RPCErrorCode = -11 - ErrRPCWalletKeypoolRanOut RPCErrorCode = -12 - ErrRPCWalletUnlockNeeded RPCErrorCode = -13 + // ErrRPCWallet indicates an unspecified problem with wallet, for + // example, key not found, etc. + ErrRPCWallet RPCErrorCode = -4 + + // ErrRPCWalletInsufficientFunds indicates that there are not enough + // funds in wallet or account. + ErrRPCWalletInsufficientFunds RPCErrorCode = -6 + + // ErrRPCWalletInvalidAccountName indicates an invalid label name. + ErrRPCWalletInvalidAccountName RPCErrorCode = -11 + + // ErrRPCWalletKeypoolRanOut indicates that the keypool ran out, and that + // keypoolrefill must be called first. + ErrRPCWalletKeypoolRanOut RPCErrorCode = -12 + + // ErrRPCWalletUnlockNeeded indicates that the wallet passphrase must be + // entered first with the walletpassphrase RPC. + ErrRPCWalletUnlockNeeded RPCErrorCode = -13 + + // ErrRPCWalletPassphraseIncorrect indicates that the wallet passphrase + // that was entered was incorrect. ErrRPCWalletPassphraseIncorrect RPCErrorCode = -14 - ErrRPCWalletWrongEncState RPCErrorCode = -15 - ErrRPCWalletEncryptionFailed RPCErrorCode = -16 - ErrRPCWalletAlreadyUnlocked RPCErrorCode = -17 + + // ErrRPCWalletWrongEncState indicates that a command was given in wrong + // wallet encryption state, for example, encrypting an encrypted wallet. + ErrRPCWalletWrongEncState RPCErrorCode = -15 + + // ErrRPCWalletEncryptionFailed indicates a failure to encrypt the wallet. + ErrRPCWalletEncryptionFailed RPCErrorCode = -16 + + // ErrRPCWalletAlreadyUnlocked indicates an attempt to unlock a wallet + // that was already unlocked. + ErrRPCWalletAlreadyUnlocked RPCErrorCode = -17 + + // ErrRPCWalletNotFound indicates that an invalid wallet was specified, + // which does not exist. It can also indicate an attempt to unload a + // wallet that was not previously loaded. + // + // Not to be confused with ErrRPCNoWallet, which is specific to btcd. + ErrRPCWalletNotFound RPCErrorCode = -18 + + // ErrRPCWalletNotSpecified indicates that no wallet was specified, for + // example, when there are multiple wallets loaded. + ErrRPCWalletNotSpecified RPCErrorCode = -19 ) // Specific Errors related to commands. These are the ones a user of the RPC From 535f25593d47297f2c7f27fac7725c3b9b05727d Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Fri, 9 Oct 2020 22:20:49 +0200 Subject: [PATCH 0412/1056] rpcclient: implement createwallet with functional options --- btcjson/walletsvrcmds.go | 23 ++++++++++ btcjson/walletsvrcmds_test.go | 55 +++++++++++++++++++++++ btcjson/walletsvrresults.go | 6 +++ rpcclient/example_test.go | 23 +++++++++- rpcclient/wallet.go | 85 +++++++++++++++++++++++++++++++++++ 5 files changed, 190 insertions(+), 2 deletions(-) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index f63a59445b..2ff9ae1832 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -63,6 +63,28 @@ func NewCreateMultisigCmd(nRequired int, keys []string) *CreateMultisigCmd { } } +// CreateWalletCmd defines the createwallet JSON-RPC command. +type CreateWalletCmd struct { + WalletName string + DisablePrivateKeys *bool `jsonrpcdefault:"false"` + Blank *bool `jsonrpcdefault:"false"` + Passphrase *string `jsonrpcdefault:"\"\""` + AvoidReuse *bool `jsonrpcdefault:"false"` +} + +// NewCreateWalletCmd returns a new instance which can be used to issue a +// createwallet JSON-RPC command. +func NewCreateWalletCmd(walletName string, disablePrivateKeys *bool, + blank *bool, passphrase *string, avoidReuse *bool) *CreateWalletCmd { + return &CreateWalletCmd{ + WalletName: walletName, + DisablePrivateKeys: disablePrivateKeys, + Blank: blank, + Passphrase: passphrase, + AvoidReuse: avoidReuse, + } +} + // DumpPrivKeyCmd defines the dumpprivkey JSON-RPC command. type DumpPrivKeyCmd struct { Address string @@ -1065,6 +1087,7 @@ func init() { MustRegisterCmd("addwitnessaddress", (*AddWitnessAddressCmd)(nil), flags) MustRegisterCmd("backupwallet", (*BackupWalletCmd)(nil), flags) MustRegisterCmd("createmultisig", (*CreateMultisigCmd)(nil), flags) + MustRegisterCmd("createwallet", (*CreateWalletCmd)(nil), flags) MustRegisterCmd("dumpprivkey", (*DumpPrivKeyCmd)(nil), flags) MustRegisterCmd("encryptwallet", (*EncryptWalletCmd)(nil), flags) MustRegisterCmd("estimatesmartfee", (*EstimateSmartFeeCmd)(nil), flags) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 5d36a12ab4..9ee6f0c749 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -62,6 +62,61 @@ func TestWalletSvrCmds(t *testing.T) { Account: btcjson.String("test"), }, }, + { + name: "createwallet", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("createwallet", "mywallet", true, true, "secret", true) + }, + staticCmd: func() interface{} { + return btcjson.NewCreateWalletCmd("mywallet", + btcjson.Bool(true), btcjson.Bool(true), + btcjson.String("secret"), btcjson.Bool(true)) + }, + marshalled: `{"jsonrpc":"1.0","method":"createwallet","params":["mywallet",true,true,"secret",true],"id":1}`, + unmarshalled: &btcjson.CreateWalletCmd{ + WalletName: "mywallet", + DisablePrivateKeys: btcjson.Bool(true), + Blank: btcjson.Bool(true), + Passphrase: btcjson.String("secret"), + AvoidReuse: btcjson.Bool(true), + }, + }, + { + name: "createwallet - optional1", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("createwallet", "mywallet") + }, + staticCmd: func() interface{} { + return btcjson.NewCreateWalletCmd("mywallet", + nil, nil, nil, nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"createwallet","params":["mywallet"],"id":1}`, + unmarshalled: &btcjson.CreateWalletCmd{ + WalletName: "mywallet", + DisablePrivateKeys: btcjson.Bool(false), + Blank: btcjson.Bool(false), + Passphrase: btcjson.String(""), + AvoidReuse: btcjson.Bool(false), + }, + }, + { + name: "createwallet - optional2", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("createwallet", "mywallet", "null", "null", "secret") + }, + staticCmd: func() interface{} { + return btcjson.NewCreateWalletCmd("mywallet", + nil, nil, btcjson.String("secret"), nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"createwallet","params":["mywallet",null,null,"secret"],"id":1}`, + unmarshalled: &btcjson.CreateWalletCmd{ + WalletName: "mywallet", + DisablePrivateKeys: nil, + Blank: nil, + Passphrase: btcjson.String("secret"), + AvoidReuse: btcjson.Bool(false), + }, + }, { name: "addwitnessaddress", newCmd: func() (interface{}, error) { diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index e2ba201daf..78a6e647f5 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -11,6 +11,12 @@ import ( "github.com/btcsuite/btcd/txscript" ) +// CreateWalletResult models the result of the createwallet command. +type CreateWalletResult struct { + Name string `json:"name"` + Warning string `json:"warning"` +} + // embeddedAddressInfo includes all getaddressinfo output fields, excluding // metadata and relation to the wallet. // diff --git a/rpcclient/example_test.go b/rpcclient/example_test.go index 35159317b5..9ba9adadef 100644 --- a/rpcclient/example_test.go +++ b/rpcclient/example_test.go @@ -11,8 +11,8 @@ import ( var connCfg = &ConnConfig{ Host: "localhost:8332", - User: "yourrpcuser", - Pass: "yourrpcpass", + User: "user", + Pass: "pass", HTTPPostMode: true, DisableTLS: true, } @@ -135,3 +135,22 @@ func ExampleClient_GetTxOutSetInfo() { fmt.Println(r.Transactions) // 9285603 fmt.Println(r.DiskSize) // 1320871611 } + +func ExampleClient_CreateWallet() { + client, err := New(connCfg, nil) + if err != nil { + panic(err) + } + defer client.Shutdown() + + r, err := client.CreateWallet( + "mywallet", + WithCreateWalletBlank(), + WithCreateWalletPassphrase("secret"), + ) + if err != nil { + panic(err) + } + + fmt.Println(r.Name) // mywallet +} diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index c7064bfe5f..4bff252304 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -939,6 +939,91 @@ func (c *Client) CreateNewAccount(account string) error { return c.CreateNewAccountAsync(account).Receive() } +// FutureCreateWalletResult is a future promise to deliver the result of a +// CreateWalletAsync RPC invocation (or an applicable error). +type FutureCreateWalletResult chan *response + +// Receive waits for the response promised by the future and returns the +// result of creating a new wallet. +func (r FutureCreateWalletResult) Receive() (*btcjson.CreateWalletResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var createWalletResult btcjson.CreateWalletResult + err = json.Unmarshal(res, &createWalletResult) + if err != nil { + return nil, err + } + return &createWalletResult, nil +} + +// CreateWalletOpt defines a functional-option to be used with CreateWallet +// method. +type CreateWalletOpt func(*btcjson.CreateWalletCmd) + +// WithCreateWalletDisablePrivateKeys disables the possibility of private keys +// to be used with a wallet created using the CreateWallet method. Using this +// option will make the wallet watch-only. +func WithCreateWalletDisablePrivateKeys() CreateWalletOpt { + return func(c *btcjson.CreateWalletCmd) { + c.DisablePrivateKeys = btcjson.Bool(true) + } +} + +// WithCreateWalletBlank specifies creation of a blank wallet. +func WithCreateWalletBlank() CreateWalletOpt { + return func(c *btcjson.CreateWalletCmd) { + c.Blank = btcjson.Bool(true) + } +} + +// WithCreateWalletPassphrase specifies a passphrase to encrypt the wallet +// with. +func WithCreateWalletPassphrase(value string) CreateWalletOpt { + return func(c *btcjson.CreateWalletCmd) { + c.Passphrase = btcjson.String(value) + } +} + +// WithCreateWalletAvoidReuse specifies keeping track of coin reuse, and +// treat dirty and clean coins differently with privacy considerations in mind. +func WithCreateWalletAvoidReuse() CreateWalletOpt { + return func(c *btcjson.CreateWalletCmd) { + c.AvoidReuse = btcjson.Bool(true) + } +} + +// CreateWalletAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See CreateWallet for the blocking version and more details. +func (c *Client) CreateWalletAsync(name string, opts ...CreateWalletOpt) FutureCreateWalletResult { + cmd := btcjson.NewCreateWalletCmd(name, nil, nil, nil, nil) + + // Apply each specified option to mutate the default command. + for _, opt := range opts { + opt(cmd) + } + + return c.sendCmd(cmd) +} + +// CreateWallet creates a new wallet account, with the possibility to use +// private keys. +// +// Optional parameters can be specified using functional-options pattern. The +// following functions are available: +// * WithCreateWalletDisablePrivateKeys +// * WithCreateWalletBlank +// * WithCreateWalletPassphrase +// * WithCreateWalletAvoidReuse +func (c *Client) CreateWallet(name string, opts ...CreateWalletOpt) (*btcjson.CreateWalletResult, error) { + return c.CreateWalletAsync(name, opts...).Receive() +} + // FutureGetAddressInfoResult is a future promise to deliver the result of an // GetAddressInfoAsync RPC invocation (or an applicable error). type FutureGetAddressInfoResult chan *response From f070f7f2bea6b3e04537e5fb1c53d360ceb19814 Mon Sep 17 00:00:00 2001 From: Armando Ochoa Date: Tue, 3 Nov 2020 23:13:20 +0700 Subject: [PATCH 0413/1056] rpcclient: fix documentation typos --- rpcclient/wallet.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 4bff252304..011e91062b 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -262,8 +262,8 @@ func (c *Client) ListUnspent() ([]btcjson.ListUnspentResult, error) { } // ListUnspentMin returns all unspent transaction outputs known to a wallet, -// using the specified number of minimum conformations and default number of -// maximum confiramtions (999999) as a filter. +// using the specified number of minimum confirmations and default number of +// maximum confirmations (999999) as a filter. func (c *Client) ListUnspentMin(minConf int) ([]btcjson.ListUnspentResult, error) { return c.ListUnspentMinAsync(minConf).Receive() } @@ -374,7 +374,7 @@ func (c *Client) ListSinceBlockMinConfWatchOnlyAsync(blockHash *chainhash.Hash, // specified block hash, or all transactions if it is nil, using the specified // number of minimum confirmations as a filter. // -// See ListSinceBlock to use the default minimum number of confirmations and default watch only paremeter. +// See ListSinceBlock to use the default minimum number of confirmations and default watch only parameter. func (c *Client) ListSinceBlockMinConfWatchOnly(blockHash *chainhash.Hash, minConfirms int, watchOnly bool) (*btcjson.ListSinceBlockResult, error) { return c.ListSinceBlockMinConfWatchOnlyAsync(blockHash, minConfirms, watchOnly).Receive() } @@ -572,7 +572,7 @@ func (c *Client) SendToAddressCommentAsync(address btcutil.Address, // SendToAddressComment sends the passed amount to the given address and stores // the provided comment and comment to in the wallet. The comment parameter is // intended to be used for the purpose of the transaction while the commentTo -// parameter is indended to be used for who the transaction is being sent to. +// parameter is intended to be used for who the transaction is being sent to. // // The comments are not part of the transaction and are only internal // to the wallet. @@ -678,7 +678,7 @@ func (c *Client) SendFromCommentAsync(fromAccount string, // SendFromComment sends the passed amount to the given address using the // provided account as a source of funds and stores the provided comment and // comment to in the wallet. The comment parameter is intended to be used for -// the purpose of the transaction while the commentTo parameter is indended to +// the purpose of the transaction while the commentTo parameter is intended to // be used for who the transaction is being sent to. Only funds with the passed // number of minimum confirmations will be used. // From 925006483747d39fa6d6038a8270a979bccfdadd Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 11 Nov 2020 14:16:03 +0100 Subject: [PATCH 0414/1056] integration: allow setting custom btcd exe path To allow using a custom btcd executable, we allow specifying a path to a file. If the path is empty, the harness will fall back to compiling one from scratch. --- integration/bip0009_test.go | 4 ++-- integration/csv_fork_test.go | 4 ++-- integration/rpcserver_test.go | 4 +++- integration/rpctest/node.go | 16 ++++++++++++---- integration/rpctest/rpc_harness.go | 9 ++++++--- integration/rpctest/rpc_harness_test.go | 12 ++++++------ 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/integration/bip0009_test.go b/integration/bip0009_test.go index df3721b1e6..b72065594c 100644 --- a/integration/bip0009_test.go +++ b/integration/bip0009_test.go @@ -129,7 +129,7 @@ func assertSoftForkStatus(r *rpctest.Harness, t *testing.T, forkKey string, stat // specific soft fork deployment to test. func testBIP0009(t *testing.T, forkKey string, deploymentID uint32) { // Initialize the primary mining node with only the genesis block. - r, err := rpctest.New(&chaincfg.RegressionNetParams, nil, nil) + r, err := rpctest.New(&chaincfg.RegressionNetParams, nil, nil, "") if err != nil { t.Fatalf("unable to create primary harness: %v", err) } @@ -320,7 +320,7 @@ func TestBIP0009Mining(t *testing.T) { t.Parallel() // Initialize the primary mining node with only the genesis block. - r, err := rpctest.New(&chaincfg.SimNetParams, nil, nil) + r, err := rpctest.New(&chaincfg.SimNetParams, nil, nil, "") if err != nil { t.Fatalf("unable to create primary harness: %v", err) } diff --git a/integration/csv_fork_test.go b/integration/csv_fork_test.go index 345217c864..b623487e59 100644 --- a/integration/csv_fork_test.go +++ b/integration/csv_fork_test.go @@ -109,7 +109,7 @@ func TestBIP0113Activation(t *testing.T) { t.Parallel() btcdCfg := []string{"--rejectnonstd"} - r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg) + r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg, "") if err != nil { t.Fatal("unable to create primary harness: ", err) } @@ -405,7 +405,7 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { // relative lock times. btcdCfg := []string{"--rejectnonstd"} - r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg) + r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg, "") if err != nil { t.Fatal("unable to create primary harness: ", err) } diff --git a/integration/rpcserver_test.go b/integration/rpcserver_test.go index df526442be..e5528453d4 100644 --- a/integration/rpcserver_test.go +++ b/integration/rpcserver_test.go @@ -109,7 +109,9 @@ func TestMain(m *testing.M) { // ensure that non-standard transactions aren't accepted into the // mempool or relayed. btcdCfg := []string{"--rejectnonstd"} - primaryHarness, err = rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg) + primaryHarness, err = rpctest.New( + &chaincfg.SimNetParams, nil, btcdCfg, "", + ) if err != nil { fmt.Println("unable to create primary harness: ", err) os.Exit(1) diff --git a/integration/rpctest/node.go b/integration/rpctest/node.go index 6aec2b1168..73dc15fca9 100644 --- a/integration/rpctest/node.go +++ b/integration/rpctest/node.go @@ -41,10 +41,18 @@ type nodeConfig struct { } // newConfig returns a newConfig with all default values. -func newConfig(prefix, certFile, keyFile string, extra []string) (*nodeConfig, error) { - btcdPath, err := btcdExecutablePath() - if err != nil { - btcdPath = "btcd" +func newConfig(prefix, certFile, keyFile string, extra []string, + customExePath string) (*nodeConfig, error) { + + var btcdPath string + if customExePath != "" { + btcdPath = customExePath + } else { + var err error + btcdPath, err = btcdExecutablePath() + if err != nil { + btcdPath = "btcd" + } } a := &nodeConfig{ diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 1c2612e47b..ee7b62fd31 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -94,11 +94,12 @@ type Harness struct { // New creates and initializes new instance of the rpc test harness. // Optionally, websocket handlers and a specified configuration may be passed. // In the case that a nil config is passed, a default configuration will be -// used. +// used. If a custom btcd executable is specified, it will be used to start the +// harness node. Otherwise a new binary is built on demand. // // NOTE: This function is safe for concurrent access. func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers, - extraArgs []string) (*Harness, error) { + extraArgs []string, customExePath string) (*Harness, error) { harnessStateMtx.Lock() defer harnessStateMtx.Unlock() @@ -144,7 +145,9 @@ func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers, miningAddr := fmt.Sprintf("--miningaddr=%s", wallet.coinbaseAddr) extraArgs = append(extraArgs, miningAddr) - config, err := newConfig("rpctest", certFile, keyFile, extraArgs) + config, err := newConfig( + "rpctest", certFile, keyFile, extraArgs, customExePath, + ) if err != nil { return nil, err } diff --git a/integration/rpctest/rpc_harness_test.go b/integration/rpctest/rpc_harness_test.go index 717f8f45af..25faf96901 100644 --- a/integration/rpctest/rpc_harness_test.go +++ b/integration/rpctest/rpc_harness_test.go @@ -105,7 +105,7 @@ func assertConnectedTo(t *testing.T, nodeA *Harness, nodeB *Harness) { func testConnectNode(r *Harness, t *testing.T) { // Create a fresh test harness. - harness, err := New(&chaincfg.SimNetParams, nil, nil) + harness, err := New(&chaincfg.SimNetParams, nil, nil, "") if err != nil { t.Fatal(err) } @@ -153,7 +153,7 @@ func testActiveHarnesses(r *Harness, t *testing.T) { numInitialHarnesses := len(ActiveHarnesses()) // Create a single test harness. - harness1, err := New(&chaincfg.SimNetParams, nil, nil) + harness1, err := New(&chaincfg.SimNetParams, nil, nil, "") if err != nil { t.Fatal(err) } @@ -181,7 +181,7 @@ func testJoinMempools(r *Harness, t *testing.T) { // Create a local test harness with only the genesis block. The nodes // will be synced below so the same transaction can be sent to both // nodes without it being an orphan. - harness, err := New(&chaincfg.SimNetParams, nil, nil) + harness, err := New(&chaincfg.SimNetParams, nil, nil, "") if err != nil { t.Fatal(err) } @@ -281,7 +281,7 @@ func testJoinMempools(r *Harness, t *testing.T) { func testJoinBlocks(r *Harness, t *testing.T) { // Create a second harness with only the genesis block so it is behind // the main harness. - harness, err := New(&chaincfg.SimNetParams, nil, nil) + harness, err := New(&chaincfg.SimNetParams, nil, nil, "") if err != nil { t.Fatal(err) } @@ -469,7 +469,7 @@ func testGenerateAndSubmitBlockWithCustomCoinbaseOutputs(r *Harness, func testMemWalletReorg(r *Harness, t *testing.T) { // Create a fresh harness, we'll be using the main harness to force a // re-org on this local harness. - harness, err := New(&chaincfg.SimNetParams, nil, nil) + harness, err := New(&chaincfg.SimNetParams, nil, nil, "") if err != nil { t.Fatal(err) } @@ -566,7 +566,7 @@ const ( func TestMain(m *testing.M) { var err error - mainHarness, err = New(&chaincfg.SimNetParams, nil, nil) + mainHarness, err = New(&chaincfg.SimNetParams, nil, nil, "") if err != nil { fmt.Println("unable to create main harness: ", err) os.Exit(1) From 93cc7f36cffbd66e3ad181dbc19aea5e05bc6b8b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 11 Nov 2020 14:24:14 +0100 Subject: [PATCH 0415/1056] integration: allow overwriting address generator --- integration/rpctest/rpc_harness.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index ee7b62fd31..e8cd7e89dd 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -58,6 +58,13 @@ var ( // Used to protest concurrent access to above declared variables. harnessStateMtx sync.RWMutex + + // ListenAddressGenerator is a function that is used to generate two + // listen addresses (host:port), one for the P2P listener and one for + // the RPC listener. This is exported to allow overwriting of the + // default behavior which isn't very concurrency safe (just selecting + // a random port can produce collisions and therefore flakes). + ListenAddressGenerator = generateListeningAddresses ) // HarnessTestCase represents a test-case which utilizes an instance of the @@ -153,7 +160,7 @@ func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers, } // Generate p2p+rpc listening addresses. - config.listen, config.rpcListen = generateListeningAddresses() + config.listen, config.rpcListen = ListenAddressGenerator() // Create the testing node bounded to the simnet. node, err := newNode(config, nodeTestData) From 65d2b7a18cf4fc89680f67ea2e541abe0c17489b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 11 Nov 2020 14:29:17 +0100 Subject: [PATCH 0416/1056] integration: allow specifying connection behavior --- integration/rpctest/rpc_harness.go | 42 +++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index e8cd7e89dd..aaf9e90621 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -34,6 +34,14 @@ const ( // BlockVersion is the default block version used when generating // blocks. BlockVersion = 4 + + // DefaultMaxConnectionRetries is the default number of times we re-try + // to connect to the node after starting it. + DefaultMaxConnectionRetries = 20 + + // DefaultConnectionRetryTimeout is the default duration we wait between + // two connection attempts. + DefaultConnectionRetryTimeout = 50 * time.Millisecond ) var ( @@ -58,7 +66,7 @@ var ( // Used to protest concurrent access to above declared variables. harnessStateMtx sync.RWMutex - + // ListenAddressGenerator is a function that is used to generate two // listen addresses (host:port), one for the P2P listener and one for // the RPC listener. This is exported to allow overwriting of the @@ -85,15 +93,22 @@ type Harness struct { // to. ActiveNet *chaincfg.Params + // MaxConnRetries is the maximum number of times we re-try to connect to + // the node after starting it. + MaxConnRetries int + + // ConnectionRetryTimeout is the duration we wait between two connection + // attempts. + ConnectionRetryTimeout time.Duration + Node *rpcclient.Client node *node handlers *rpcclient.NotificationHandlers wallet *memWallet - testNodeDir string - maxConnRetries int - nodeNum int + testNodeDir string + nodeNum int sync.Mutex } @@ -200,13 +215,14 @@ func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers, } h := &Harness{ - handlers: handlers, - node: node, - maxConnRetries: 20, - testNodeDir: nodeTestData, - ActiveNet: activeNet, - nodeNum: nodeNum, - wallet: wallet, + handlers: handlers, + node: node, + MaxConnRetries: DefaultMaxConnectionRetries, + ConnectionRetryTimeout: DefaultConnectionRetryTimeout, + testNodeDir: nodeTestData, + ActiveNet: activeNet, + nodeNum: nodeNum, + wallet: wallet, } // Track this newly created test instance within the package level @@ -322,9 +338,9 @@ func (h *Harness) connectRPCClient() error { var err error rpcConf := h.node.config.rpcConnConfig() - for i := 0; i < h.maxConnRetries; i++ { + for i := 0; i < h.MaxConnRetries; i++ { if client, err = rpcclient.New(&rpcConf, h.handlers); err != nil { - time.Sleep(time.Duration(i) * 50 * time.Millisecond) + time.Sleep(time.Duration(i) * h.ConnectionRetryTimeout) continue } break From 9fd26cf7953033a9e955b43e2dd7330c260f2a5e Mon Sep 17 00:00:00 2001 From: Liran Sharir Date: Tue, 10 Nov 2020 16:27:55 -0500 Subject: [PATCH 0417/1056] integration/rpctest: randomizes port in rpctest.New to reduce collisions --- integration/rpctest/rpc_harness.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 1c2612e47b..ab58d16a3e 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -7,6 +7,7 @@ package rpctest import ( "fmt" "io/ioutil" + "math/rand" "net" "os" "path/filepath" @@ -40,16 +41,6 @@ var ( // current number of active test nodes. numTestInstances = 0 - // processID is the process ID of the current running process. It is - // used to calculate ports based upon it when launching an rpc - // harnesses. The intent is to allow multiple process to run in - // parallel without port collisions. - // - // It should be noted however that there is still some small probability - // that there will be port collisions either due to other processes - // running or simply due to the stars aligning on the process IDs. - processID = os.Getpid() - // testInstances is a private package-level slice used to keep track of // all active test harnesses. This global can be used to perform // various "joins", shutdown several active harnesses after a test, @@ -477,13 +468,14 @@ func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs( // addresses designated for the current rpc test. If there haven't been any // test instances created, the default ports are used. Otherwise, in order to // support multiple test nodes running at once, the p2p and rpc port are -// incremented after each initialization. +// picked at random between {min/max}PeerPort and {min/max}RPCPort respectively. func generateListeningAddresses() (string, string) { localhost := "127.0.0.1" + rand.Seed(time.Now().UnixNano()) + portString := func(minPort, maxPort int) string { - port := minPort + numTestInstances + ((20 * processID) % - (maxPort - minPort)) + port := minPort + rand.Intn(maxPort-minPort) return strconv.Itoa(port) } From 9e8bb3eddba2fb9ce953f3658b386ae39f115d8e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 12 Nov 2020 10:08:54 +0100 Subject: [PATCH 0418/1056] btcjson+rpcserverhelp: restore bitcoind compatibility The PR #1594 introduced a change that made the order of parameters relevant, if one of them is nil. This makes it harder to be backward compatible with the same JSON message if an existing parameter in bitcoind was re-purposed to have a different meaning. --- btcjson/chainsvrcmds.go | 68 ++++++++++++++++++++++++++++++++---- btcjson/chainsvrcmds_test.go | 34 ++++++++++++++---- rpcserverhelp.go | 10 +++--- 3 files changed, 93 insertions(+), 19 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 0e683af003..aa1d4415da 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -11,6 +11,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + "reflect" "github.com/btcsuite/btcd/wire" ) @@ -819,11 +820,60 @@ func NewSearchRawTransactionsCmd(address string, verbose, skip, count *int, vinE } } +// AllowHighFeesOrMaxFeeRate defines a type that can either be the legacy +// allowhighfees boolean field or the new maxfeerate int field. +type AllowHighFeesOrMaxFeeRate struct { + Value interface{} +} + +// String returns the string representation of this struct, used for printing +// the marshaled default value in the help text. +func (a AllowHighFeesOrMaxFeeRate) String() string { + b, _ := a.MarshalJSON() + return string(b) +} + +// MarshalJSON implements the json.Marshaler interface +func (a AllowHighFeesOrMaxFeeRate) MarshalJSON() ([]byte, error) { + // The default value is false which only works with the legacy versions. + if a.Value == nil || + (reflect.ValueOf(a.Value).Kind() == reflect.Ptr && + reflect.ValueOf(a.Value).IsNil()) { + + return json.Marshal(false) + } + + return json.Marshal(a.Value) +} + +// UnmarshalJSON implements the json.Unmarshaler interface +func (a *AllowHighFeesOrMaxFeeRate) UnmarshalJSON(data []byte) error { + if len(data) == 0 { + return nil + } + + var unmarshalled interface{} + if err := json.Unmarshal(data, &unmarshalled); err != nil { + return err + } + + switch v := unmarshalled.(type) { + case bool: + a.Value = Bool(v) + case float64: + a.Value = Int32(int32(v)) + default: + return fmt.Errorf("invalid allowhighfees or maxfeerate value: "+ + "%v", unmarshalled) + } + + return nil +} + // SendRawTransactionCmd defines the sendrawtransaction JSON-RPC command. type SendRawTransactionCmd struct { - HexTx string - AllowHighFees *bool `jsonrpcdefault:"false"` - MaxFeeRate *int32 + HexTx string + FeeSetting *AllowHighFeesOrMaxFeeRate `jsonrpcdefault:"false"` } // NewSendRawTransactionCmd returns a new instance which can be used to issue a @@ -833,8 +883,10 @@ type SendRawTransactionCmd struct { // for optional parameters will use the default value. func NewSendRawTransactionCmd(hexTx string, allowHighFees *bool) *SendRawTransactionCmd { return &SendRawTransactionCmd{ - HexTx: hexTx, - AllowHighFees: allowHighFees, + HexTx: hexTx, + FeeSetting: &AllowHighFeesOrMaxFeeRate{ + Value: allowHighFees, + }, } } @@ -844,8 +896,10 @@ func NewSendRawTransactionCmd(hexTx string, allowHighFees *bool) *SendRawTransac // A 0 maxFeeRate indicates that a maximum fee rate won't be enforced. func NewBitcoindSendRawTransactionCmd(hexTx string, maxFeeRate int32) *SendRawTransactionCmd { return &SendRawTransactionCmd{ - HexTx: hexTx, - MaxFeeRate: &maxFeeRate, + HexTx: hexTx, + FeeSetting: &AllowHighFeesOrMaxFeeRate{ + Value: &maxFeeRate, + }, } } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index d44a2ece6f..263d6d7e5d 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1224,29 +1224,49 @@ func TestChainSvrCmds(t *testing.T) { { name: "sendrawtransaction", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("sendrawtransaction", "1122") + return btcjson.NewCmd("sendrawtransaction", "1122", &btcjson.AllowHighFeesOrMaxFeeRate{}) }, staticCmd: func() interface{} { return btcjson.NewSendRawTransactionCmd("1122", nil) }, - marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122"],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122",false],"id":1}`, unmarshalled: &btcjson.SendRawTransactionCmd{ - HexTx: "1122", - AllowHighFees: btcjson.Bool(false), + HexTx: "1122", + FeeSetting: &btcjson.AllowHighFeesOrMaxFeeRate{ + Value: btcjson.Bool(false), + }, }, }, { name: "sendrawtransaction optional", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("sendrawtransaction", "1122", false) + return btcjson.NewCmd("sendrawtransaction", "1122", &btcjson.AllowHighFeesOrMaxFeeRate{Value: btcjson.Bool(false)}) }, staticCmd: func() interface{} { return btcjson.NewSendRawTransactionCmd("1122", btcjson.Bool(false)) }, marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122",false],"id":1}`, unmarshalled: &btcjson.SendRawTransactionCmd{ - HexTx: "1122", - AllowHighFees: btcjson.Bool(false), + HexTx: "1122", + FeeSetting: &btcjson.AllowHighFeesOrMaxFeeRate{ + Value: btcjson.Bool(false), + }, + }, + }, + { + name: "sendrawtransaction optional, bitcoind >= 0.19.0", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("sendrawtransaction", "1122", &btcjson.AllowHighFeesOrMaxFeeRate{Value: btcjson.Int32(1234)}) + }, + staticCmd: func() interface{} { + return btcjson.NewBitcoindSendRawTransactionCmd("1122", 1234) + }, + marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122",1234],"id":1}`, + unmarshalled: &btcjson.SendRawTransactionCmd{ + HexTx: "1122", + FeeSetting: &btcjson.AllowHighFeesOrMaxFeeRate{ + Value: btcjson.Int32(1234), + }, }, }, { diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 75a63be0af..c1cb8cd0b7 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -561,11 +561,11 @@ var helpDescsEnUS = map[string]string{ "searchrawtransactions--result0": "Hex-encoded serialized transaction", // SendRawTransactionCmd help. - "sendrawtransaction--synopsis": "Submits the serialized, hex-encoded transaction to the local peer and relays it to the network.", - "sendrawtransaction-hextx": "Serialized, hex-encoded signed transaction", - "sendrawtransaction-allowhighfees": "Whether or not to allow insanely high fees (btcd does not yet implement this parameter, so it has no effect)", - "sendrawtransaction-maxfeerate": "Used by bitcoind on or after v0.19.0", - "sendrawtransaction--result0": "The hash of the transaction", + "sendrawtransaction--synopsis": "Submits the serialized, hex-encoded transaction to the local peer and relays it to the network.", + "sendrawtransaction-hextx": "Serialized, hex-encoded signed transaction", + "sendrawtransaction-feesetting": "Whether or not to allow insanely high fees in bitcoind < v0.19.0 or the max fee rate for bitcoind v0.19.0 and later (btcd does not yet implement this parameter, so it has no effect)", + "sendrawtransaction--result0": "The hash of the transaction", + "allowhighfeesormaxfeerate-value": "Either the boolean value for the allowhighfees parameter in bitcoind < v0.19.0 or the numerical value for the maxfeerate field in bitcoind v0.19.0 and later", // SetGenerateCmd help. "setgenerate--synopsis": "Set the server to generate coins (mine) or not.", From 0886f1e5c1fd28ad24aaca4dbccc5f4ab85e58ca Mon Sep 17 00:00:00 2001 From: Iskander Sharipov Date: Fri, 14 Sep 2018 00:35:08 +0300 Subject: [PATCH 0419/1056] simplify s[:] to s where s is a slice Found using https://go-critic.github.io/overview#unslice-ref --- blockchain/chainio.go | 4 ++-- database/ffldb/blockio.go | 2 +- wire/fixedIO_test.go | 2 +- wire/message.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index c456c006f3..f40ba465e9 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -120,7 +120,7 @@ func dbFetchVersion(dbTx database.Tx, key []byte) uint32 { return 0 } - return byteOrder.Uint32(serialized[:]) + return byteOrder.Uint32(serialized) } // dbPutVersion uses an existing database transaction to update the provided @@ -943,7 +943,7 @@ func serializeBestChainState(state bestChainState) []byte { byteOrder.PutUint32(serializedData[offset:], workSumBytesLen) offset += 4 copy(serializedData[offset:], workSumBytes) - return serializedData[:] + return serializedData } // deserializeBestChainState deserializes the passed serialized best chain diff --git a/database/ffldb/blockio.go b/database/ffldb/blockio.go index 3d7782f93c..8fb27ab283 100644 --- a/database/ffldb/blockio.go +++ b/database/ffldb/blockio.go @@ -474,7 +474,7 @@ func (s *blockStore) writeBlock(rawBlock []byte) (blockLocation, error) { _, _ = hasher.Write(scratch[:]) // Serialized block. - if err := s.writeData(rawBlock[:], "block"); err != nil { + if err := s.writeData(rawBlock, "block"); err != nil { return blockLocation{}, err } _, _ = hasher.Write(rawBlock) diff --git a/wire/fixedIO_test.go b/wire/fixedIO_test.go index 731c463892..ccd67ae411 100644 --- a/wire/fixedIO_test.go +++ b/wire/fixedIO_test.go @@ -68,7 +68,7 @@ func (fr *fixedReader) Read(p []byte) (n int, err error) { func newFixedReader(max int, buf []byte) io.Reader { b := make([]byte, max) if buf != nil { - copy(b[:], buf) + copy(b, buf) } iobuf := bytes.NewBuffer(b) diff --git a/wire/message.go b/wire/message.go index fe45a11fb1..eae1cf88de 100644 --- a/wire/message.go +++ b/wire/message.go @@ -401,7 +401,7 @@ func ReadMessageWithEncodingN(r io.Reader, pver uint32, btcnet BitcoinNet, // Test checksum. checksum := chainhash.DoubleHashB(payload)[0:4] - if !bytes.Equal(checksum[:], hdr.checksum[:]) { + if !bytes.Equal(checksum, hdr.checksum[:]) { str := fmt.Sprintf("payload checksum failed - header "+ "indicates %v, but actual checksum is %v.", hdr.checksum, checksum) From 610bb55ae85ccbc73958f44df1fba0ba888559ce Mon Sep 17 00:00:00 2001 From: 10gic <2391796+10gic@users.noreply.github.com> Date: Fri, 20 Nov 2020 17:58:10 +0800 Subject: [PATCH 0420/1056] rpcclient: add ExtraHeaders in ConnConfig --- rpcclient/infrastructure.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 8609e7c5ad..4f15ed1430 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -850,6 +850,9 @@ func (c *Client) sendPost(jReq *jsonRequest) { } httpReq.Close = true httpReq.Header.Set("Content-Type", "application/json") + for key, value := range c.config.ExtraHeaders { + httpReq.Header.Set(key, value) + } // Configure basic access authorization. user, pass, err := c.config.getAuth() @@ -1161,6 +1164,10 @@ type ConnConfig struct { // flag can be set to true to use basic HTTP POST requests instead. HTTPPostMode bool + // ExtraHeaders specifies the extra headers when perform request. It's + // useful when RPC provider need customized headers. + ExtraHeaders map[string]string + // EnableBCInfoHacks is an option provided to enable compatibility hacks // when connecting to blockchain.info RPC server EnableBCInfoHacks bool @@ -1280,6 +1287,9 @@ func dial(config *ConnConfig) (*websocket.Conn, error) { auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login)) requestHeader := make(http.Header) requestHeader.Add("Authorization", auth) + for key, value := range config.ExtraHeaders { + requestHeader.Add(key, value) + } // Dial the connection. url := fmt.Sprintf("%s://%s/%s", scheme, config.Host, config.Endpoint) From 29c9ff351c4b4716e823071b8fe42c617f4cd6e2 Mon Sep 17 00:00:00 2001 From: Yaacov Akiba Slama Date: Mon, 23 Nov 2020 15:17:10 +0200 Subject: [PATCH 0421/1056] Add support for receiving sendaddrv2 message from a peer --- wire/message.go | 4 ++++ wire/msgsendaddrv2.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 wire/msgsendaddrv2.go diff --git a/wire/message.go b/wire/message.go index eae1cf88de..6d3147a81d 100644 --- a/wire/message.go +++ b/wire/message.go @@ -57,6 +57,7 @@ const ( CmdCFilter = "cfilter" CmdCFHeaders = "cfheaders" CmdCFCheckpt = "cfcheckpt" + CmdSendAddrV2 = "sendaddrv2" ) // MessageEncoding represents the wire message encoding format to be used. @@ -99,6 +100,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdVerAck: msg = &MsgVerAck{} + case CmdSendAddrV2: + msg = &MsgSendAddrV2{} + case CmdGetAddr: msg = &MsgGetAddr{} diff --git a/wire/msgsendaddrv2.go b/wire/msgsendaddrv2.go new file mode 100644 index 0000000000..d6d19efb27 --- /dev/null +++ b/wire/msgsendaddrv2.go @@ -0,0 +1,42 @@ +package wire + +import ( + "io" +) + +// MsgSendAddrV2 defines a bitcoin sendaddrv2 message which is used for a peer +// to signal support for receiving ADDRV2 messages (BIP155). It implements the +// Message interface. +// +// This message has no payload. +type MsgSendAddrV2 struct{} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgSendAddrV2) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgSendAddrV2) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { + return nil +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgSendAddrV2) Command() string { + return CmdSendAddrV2 +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgSendAddrV2) MaxPayloadLength(pver uint32) uint32 { + return 0 +} + +// NewMsgSendAddrV2 returns a new bitcoin sendaddrv2 message that conforms to the +// Message interface. +func NewMsgSendAddrV2() *MsgSendAddrV2 { + return &MsgSendAddrV2{} +} From 12abc84cb22f26c87d468bd9ebbeb5d836f5a5d1 Mon Sep 17 00:00:00 2001 From: ebiiim Date: Wed, 13 Jan 2021 00:36:00 +0900 Subject: [PATCH 0422/1056] fixed broken link --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 5dc0dfcf56..c286d47a51 100644 --- a/docs/index.md +++ b/docs/index.md @@ -34,7 +34,7 @@ which are both under active development. ## Documentation -Documentation is a work-in-progress. It is available at [btcd.readthedocs.io](https://btcd.readthedocs.io/en/docu/). +Documentation is a work-in-progress. It is available at [btcd.readthedocs.io](https://btcd.readthedocs.io). ## Contents From e747eb9284f643b3074bd3c69901a5ffb2e6152e Mon Sep 17 00:00:00 2001 From: Victor Lavaud Date: Thu, 14 Jan 2021 20:39:43 +0100 Subject: [PATCH 0423/1056] Add support for arm32v7 in Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 7cb47e0138..3bbc25712b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,6 +25,7 @@ ADD . /app WORKDIR /app RUN set -ex \ && if [ "${ARCH}" = "amd64" ]; then export GOARCH=amd64; fi \ + && if [ "${ARCH}" = "arm32v7" ]; then export GOARCH=arm; fi \ && if [ "${ARCH}" = "arm64v8" ]; then export GOARCH=arm64; fi \ && echo "Compiling for $GOARCH" \ && go install -v . ./cmd/... From c3ece697dab966a9b8854facead71755d226eead Mon Sep 17 00:00:00 2001 From: Vinayak Borkar Date: Mon, 4 Jan 2021 01:55:26 -0800 Subject: [PATCH 0424/1056] Fixes btcsuite/btcd#1653 --- btcjson/chainsvrresults.go | 1 + 1 file changed, 1 insertion(+) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index e70900d87b..bfe4d6b532 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -108,6 +108,7 @@ type GetBlockVerboseTxResult struct { VersionHex string `json:"versionHex"` MerkleRoot string `json:"merkleroot"` Tx []TxRawResult `json:"tx,omitempty"` + RawTx []TxRawResult `json:"rawtx,omitempty"` // Deprecated: removed in Bitcoin Core Time int64 `json:"time"` Nonce uint32 `json:"nonce"` Bits string `json:"bits"` From 7bbd9b0284de8492ae738ad8d722772925fa5a86 Mon Sep 17 00:00:00 2001 From: Steven Kreuzer Date: Sun, 3 Jan 2021 02:24:39 +0000 Subject: [PATCH 0425/1056] btcjson: Update fields in GetBlockChainInfoResult Update the fields of GetBlockChainInfoResult to reflect the current state of the RPC returned by other full-node implementations. * InitialBlockDownload - Node is in Initial Block Download mode if True. * SizeOnDisk - The estimated size of the block and undo files on disk. --- btcjson/chainsvrresults.go | 2 ++ rpcserverhelp.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index bfe4d6b532..9799494ca3 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -222,9 +222,11 @@ type GetBlockChainInfoResult struct { Difficulty float64 `json:"difficulty"` MedianTime int64 `json:"mediantime"` VerificationProgress float64 `json:"verificationprogress,omitempty"` + InitialBlockDownload bool `json:"initialblockdownload,omitempty"` Pruned bool `json:"pruned"` PruneHeight int32 `json:"pruneheight,omitempty"` ChainWork string `json:"chainwork,omitempty"` + SizeOnDisk int64 `json:"size_on_disk,omitempty"` *SoftForks *UnifiedSoftForks } diff --git a/rpcserverhelp.go b/rpcserverhelp.go index c1cb8cd0b7..654fee0169 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -181,6 +181,8 @@ var helpDescsEnUS = map[string]string{ "getblockchaininforesult-pruned": "A bool that indicates if the node is pruned or not", "getblockchaininforesult-pruneheight": "The lowest block retained in the current pruned chain", "getblockchaininforesult-chainwork": "The total cumulative work in the best chain", + "getblockchaininforesult-size_on_disk": "The estimated size of the block and undo files on disk", + "getblockchaininforesult-initialblockdownload": "Estimate of whether this node is in Initial Block Download mode", "getblockchaininforesult-softforks": "The status of the super-majority soft-forks", "getblockchaininforesult-unifiedsoftforks": "The status of the super-majority soft-forks used by bitcoind on or after v0.19.0", From 77fd96753c8571937663bc913ddc0c938fc4f05b Mon Sep 17 00:00:00 2001 From: Dan Cline Date: Fri, 14 Aug 2020 18:38:55 -0400 Subject: [PATCH 0426/1056] txscript: add benchmark for IsUnspendable - create benchmarks to measure allocations - add test for benchmark input - create a low alloc parseScriptTemplate - refactor parsing logic for a single opcode --- txscript/opcode.go | 73 +++++++++++++++++++++++++ txscript/script.go | 114 ++++++++++++++++------------------------ txscript/script_test.go | 35 ++++++++++++ 3 files changed, 153 insertions(+), 69 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 5ffb398277..a878a9667b 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -656,6 +656,79 @@ func (pop *parsedOpcode) isDisabled() bool { } } +// checkParseableInScript checks whether or not the current opcode is able to be +// parsed at a certain position in a script. +// This returns the position of the next opcode to be parsed in the script. +func (pop *parsedOpcode) checkParseableInScript(script []byte, scriptPos int) (int, error) { + // Parse data out of instruction. + switch { + // No additional data. Note that some of the opcodes, notably + // OP_1NEGATE, OP_0, and OP_[1-16] represent the data + // themselves. + case pop.opcode.length == 1: + scriptPos++ + + // Data pushes of specific lengths -- OP_DATA_[1-75]. + case pop.opcode.length > 1: + if len(script[scriptPos:]) < pop.opcode.length { + str := fmt.Sprintf("opcode %s requires %d "+ + "bytes, but script only has %d remaining", + pop.opcode.name, pop.opcode.length, len(script[scriptPos:])) + return 0, scriptError(ErrMalformedPush, str) + } + + // Slice out the data. + pop.data = script[scriptPos+1 : scriptPos+pop.opcode.length] + scriptPos += pop.opcode.length + + // Data pushes with parsed lengths -- OP_PUSHDATAP{1,2,4}. + case pop.opcode.length < 0: + var l uint + off := scriptPos + 1 + + if len(script[off:]) < -pop.opcode.length { + str := fmt.Sprintf("opcode %s requires %d "+ + "bytes, but script only has %d remaining", + pop.opcode.name, -pop.opcode.length, len(script[off:])) + return 0, scriptError(ErrMalformedPush, str) + } + + // Next -length bytes are little endian length of data. + switch pop.opcode.length { + case -1: + l = uint(script[off]) + case -2: + l = ((uint(script[off+1]) << 8) | + uint(script[off])) + case -4: + l = ((uint(script[off+3]) << 24) | + (uint(script[off+2]) << 16) | + (uint(script[off+1]) << 8) | + uint(script[off])) + default: + str := fmt.Sprintf("invalid opcode length %d", + pop.opcode.length) + return 0, scriptError(ErrMalformedPush, str) + } + + // Move offset to beginning of the data. + off += -pop.opcode.length + + // Disallow entries that do not fit script or were + // sign extended. + if int(l) > len(script[off:]) || int(l) < 0 { + str := fmt.Sprintf("opcode %s pushes %d bytes, "+ + "but script only has %d remaining", + pop.opcode.name, int(l), len(script[off:])) + return 0, scriptError(ErrMalformedPush, str) + } + + pop.data = script[off : off+int(l)] + scriptPos += 1 - pop.opcode.length + int(l) + } + return scriptPos, nil +} + // alwaysIllegal returns whether or not the opcode is always illegal when passed // over by the program counter even if in a non-executed branch (it isn't a // coincidence that they are conditionals). diff --git a/txscript/script.go b/txscript/script.go index aac3d4aaaa..92a50e3761 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -196,86 +196,58 @@ func IsPushOnlyScript(script []byte) bool { // the list of parsed opcodes up to the point of failure along with the error. func parseScriptTemplate(script []byte, opcodes *[256]opcode) ([]parsedOpcode, error) { retScript := make([]parsedOpcode, 0, len(script)) + var err error for i := 0; i < len(script); { instr := script[i] op := &opcodes[instr] pop := parsedOpcode{opcode: op} + i, err = pop.checkParseableInScript(script, i) + if err != nil { + return retScript, err + } - // Parse data out of instruction. - switch { - // No additional data. Note that some of the opcodes, notably - // OP_1NEGATE, OP_0, and OP_[1-16] represent the data - // themselves. - case op.length == 1: - i++ - - // Data pushes of specific lengths -- OP_DATA_[1-75]. - case op.length > 1: - if len(script[i:]) < op.length { - str := fmt.Sprintf("opcode %s requires %d "+ - "bytes, but script only has %d remaining", - op.name, op.length, len(script[i:])) - return retScript, scriptError(ErrMalformedPush, - str) - } + retScript = append(retScript, pop) + } - // Slice out the data. - pop.data = script[i+1 : i+op.length] - i += op.length - - // Data pushes with parsed lengths -- OP_PUSHDATAP{1,2,4}. - case op.length < 0: - var l uint - off := i + 1 - - if len(script[off:]) < -op.length { - str := fmt.Sprintf("opcode %s requires %d "+ - "bytes, but script only has %d remaining", - op.name, -op.length, len(script[off:])) - return retScript, scriptError(ErrMalformedPush, - str) - } + return retScript, nil +} - // Next -length bytes are little endian length of data. - switch op.length { - case -1: - l = uint(script[off]) - case -2: - l = ((uint(script[off+1]) << 8) | - uint(script[off])) - case -4: - l = ((uint(script[off+3]) << 24) | - (uint(script[off+2]) << 16) | - (uint(script[off+1]) << 8) | - uint(script[off])) - default: - str := fmt.Sprintf("invalid opcode length %d", - op.length) - return retScript, scriptError(ErrMalformedPush, - str) - } +// checkScriptTemplateParseable is the same as parseScriptTemplate but does not +// return the list of opcodes up until the point of failure so that this can be +// used in functions which do not necessarily have a need for the failed list of +// opcodes, such as IsUnspendable. +// +// This function returns a pointer to a byte. This byte is nil if the parsing +// has an error, or if the script length is zero. If the script length is not +// zero and parsing succeeds, then the first opcode parsed will be returned. +// +// Not returning the full opcode list up until failure also has the benefit of +// reducing GC pressure, as the list would get immediately thrown away. +func checkScriptTemplateParseable(script []byte, opcodes *[256]opcode) (*byte, error) { + var err error - // Move offset to beginning of the data. - off += -op.length - - // Disallow entries that do not fit script or were - // sign extended. - if int(l) > len(script[off:]) || int(l) < 0 { - str := fmt.Sprintf("opcode %s pushes %d bytes, "+ - "but script only has %d remaining", - op.name, int(l), len(script[off:])) - return retScript, scriptError(ErrMalformedPush, - str) - } + // A script of length zero is an unspendable script but it is parseable. + var firstOpcode byte + var numParsedInstr uint = 0 - pop.data = script[off : off+int(l)] - i += 1 - op.length + int(l) + for i := 0; i < len(script); { + instr := script[i] + op := &opcodes[instr] + pop := parsedOpcode{opcode: op} + i, err = pop.checkParseableInScript(script, i) + if err != nil { + return nil, err } - retScript = append(retScript, pop) + // if this is a op_return then it is unspendable so we set the first + // parsed instruction in case it's an op_return + if numParsedInstr == 0 { + firstOpcode = pop.opcode.value + } + numParsedInstr++ } - return retScript, nil + return &firstOpcode, nil } // parseScript preparses the script in bytes into a list of parsedOpcodes while @@ -851,10 +823,14 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int { // guaranteed to fail at execution. This allows inputs to be pruned instantly // when entering the UTXO set. func IsUnspendable(pkScript []byte) bool { - pops, err := parseScript(pkScript) + // Not provably unspendable + if len(pkScript) == 0 { + return false + } + firstOpcode, err := checkScriptTemplateParseable(pkScript, &opcodeArray) if err != nil { return true } - return len(pops) > 0 && pops[0].opcode.value == OP_RETURN + return firstOpcode != nil && *firstOpcode == OP_RETURN } diff --git a/txscript/script_test.go b/txscript/script_test.go index 6a725e275c..34c8ef9740 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -4301,6 +4301,28 @@ func TestIsUnspendable(t *testing.T) { 0xfa, 0x0b, 0x5c, 0x88, 0xac}, expected: false, }, + { + // Spendable + pkScript: []byte{0xa9, 0x14, 0x82, 0x1d, 0xba, 0x94, 0xbc, 0xfb, + 0xa2, 0x57, 0x36, 0xa3, 0x9e, 0x5d, 0x14, 0x5d, 0x69, 0x75, + 0xba, 0x8c, 0x0b, 0x42, 0x87}, + expected: false, + }, + { + // Not Necessarily Unspendable + pkScript: []byte{}, + expected: false, + }, + { + // Spendable + pkScript: []byte{OP_TRUE}, + expected: false, + }, + { + // Unspendable + pkScript: []byte{OP_RETURN}, + expected: true, + }, } for i, test := range tests { @@ -4312,3 +4334,16 @@ func TestIsUnspendable(t *testing.T) { } } } + +// BenchmarkIsUnspendable adds a benchmark to compare the time and allocations +// necessary for the IsUnspendable function. +func BenchmarkIsUnspendable(b *testing.B) { + pkScriptToUse := []byte{0xa9, 0x14, 0x82, 0x1d, 0xba, 0x94, 0xbc, 0xfb, 0xa2, 0x57, 0x36, 0xa3, 0x9e, 0x5d, 0x14, 0x5d, 0x69, 0x75, 0xba, 0x8c, 0x0b, 0x42, 0x87} + var res bool = false + for i := 0; i < b.N; i++ { + res = IsUnspendable(pkScriptToUse) + } + if res { + b.Fatalf("Benchmark should never have res be %t\n", res) + } +} From 1dd693480cbfea6cffb1d1fa947fb1ccbb9d3acb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 2 Feb 2021 12:42:28 -0800 Subject: [PATCH 0427/1056] txscript/hashcache_test: always add inputs during getTxn TestHashCacheAddContainsHashes flakes fairly regularly when rebasing PR #1684 with: txid wasn't inserted into cache but was found. With probabilty 1/10^2 there will be no inputs on the transaction. This reduces the entropy in the txid, and I belive is the primary cause of the flake. --- txscript/hashcache_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/txscript/hashcache_test.go b/txscript/hashcache_test.go index 389918e2f2..09b71fafa6 100644 --- a/txscript/hashcache_test.go +++ b/txscript/hashcache_test.go @@ -18,7 +18,7 @@ func genTestTx() (*wire.MsgTx, error) { tx := wire.NewMsgTx(2) tx.Version = rand.Int31() - numTxins := rand.Intn(11) + numTxins := 1 + rand.Intn(11) for i := 0; i < numTxins; i++ { randTxIn := wire.TxIn{ PreviousOutPoint: wire.OutPoint{ @@ -34,7 +34,7 @@ func genTestTx() (*wire.MsgTx, error) { tx.TxIn = append(tx.TxIn, &randTxIn) } - numTxouts := rand.Intn(11) + numTxouts := 1 + rand.Intn(11) for i := 0; i < numTxouts; i++ { randTxOut := wire.TxOut{ Value: rand.Int63(), From 5300a19d06d29171637fcb067dd5d3af6895d900 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 2 Feb 2021 13:24:27 -0800 Subject: [PATCH 0428/1056] txscript/hashcache_test: call rand.Seed once in init This resolves the more fundamental flake in the unit tests noted in the prior commit. Because multiple unit tests call rand.Seed in parallel, it's possible they can be executed with the same unix timestamp (in seconds). If the second call happens between generating the hash cache and checking that the cache doesn't contain a random txn, the random transaction is in fact a duplicate of one generated earlier since the RNG state was reset. To remedy, we initialize rand.Seed once in the init function. --- txscript/hashcache_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/txscript/hashcache_test.go b/txscript/hashcache_test.go index 09b71fafa6..cee59b9956 100644 --- a/txscript/hashcache_test.go +++ b/txscript/hashcache_test.go @@ -13,6 +13,10 @@ import ( "github.com/davecgh/go-spew/spew" ) +func init() { + rand.Seed(time.Now().Unix()) +} + // genTestTx creates a random transaction for uses within test cases. func genTestTx() (*wire.MsgTx, error) { tx := wire.NewMsgTx(2) @@ -56,8 +60,6 @@ func genTestTx() (*wire.MsgTx, error) { func TestHashCacheAddContainsHashes(t *testing.T) { t.Parallel() - rand.Seed(time.Now().Unix()) - cache := NewHashCache(10) var err error @@ -109,8 +111,6 @@ func TestHashCacheAddContainsHashes(t *testing.T) { func TestHashCacheAddGet(t *testing.T) { t.Parallel() - rand.Seed(time.Now().Unix()) - cache := NewHashCache(10) // To start, we'll generate a random transaction and compute the set of @@ -144,8 +144,6 @@ func TestHashCacheAddGet(t *testing.T) { func TestHashCachePurge(t *testing.T) { t.Parallel() - rand.Seed(time.Now().Unix()) - cache := NewHashCache(10) var err error From 31b66488b497fb3da2038bad8bb181a66e5454e2 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Wed, 3 Feb 2021 21:01:10 +0100 Subject: [PATCH 0429/1056] btcec: validate R and S signature components in RecoverCompact --- btcec/signature.go | 21 ++++++++++++++++++++- btcec/signature_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/btcec/signature.go b/btcec/signature.go index deedd172d8..cdd7cedfb8 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -284,6 +284,25 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int { // format and thus we match bitcoind's behaviour here. func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte, iter int, doChecks bool) (*PublicKey, error) { + // Parse and validate the R and S signature components. + // + // Fail if r and s are not in [1, N-1]. + if sig.R.Cmp(curve.Params().N) != -1 { + return nil, errors.New("signature R is >= curve order") + } + + if sig.R.Sign() == 0 { + return nil, errors.New("signature R is 0") + } + + if sig.S.Cmp(curve.Params().N) != -1 { + return nil, errors.New("signature S is >= curve order") + } + + if sig.S.Sign() == 0 { + return nil, errors.New("signature S is 0") + } + // 1.1 x = (n * i) + r Rx := new(big.Int).Mul(curve.Params().N, new(big.Int).SetInt64(int64(iter/2))) @@ -393,7 +412,7 @@ func SignCompact(curve *KoblitzCurve, key *PrivateKey, // RecoverCompact verifies the compact signature "signature" of "hash" for the // Koblitz curve in "curve". If the signature matches then the recovered public -// key will be returned as well as a boolen if the original key was compressed +// key will be returned as well as a boolean if the original key was compressed // or not, else an error will be returned. func RecoverCompact(curve *KoblitzCurve, signature, hash []byte) (*PublicKey, bool, error) { diff --git a/btcec/signature_test.go b/btcec/signature_test.go index d238741455..ba02a03f76 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -555,6 +555,40 @@ var recoveryTests = []struct { sig: "00000000000000000000000000000000000000000000000000000000000000002c0000000000000000000000000000000000000000000000000000000000000004", pub: "04A7640409AA2083FDAD38B2D8DE1263B2251799591D840653FB02DBBA503D7745FCB83D80E08A1E02896BE691EA6AFFB8A35939A646F1FC79052A744B1C82EDC3", }, + { + // Zero R value + // + // Test case contributed by Ethereum Swarm: GH-1651 + msg: "3060d2c77c1e192d62ad712fb400e04e6f779914a6876328ff3b213fa85d2012", + sig: "65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037a3", + err: fmt.Errorf("signature R is 0"), + }, + { + // Zero R value + // + // Test case contributed by Ethereum Swarm: GH-1651 + msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054", + sig: "060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007c", + err: fmt.Errorf("signature R is 0"), + }, + { + // R = N (curve order of secp256k1) + msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054", + sig: "65fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414100000000000000000000000000000000000000000000000000000000000037a3", + err: fmt.Errorf("signature R is >= curve order"), + }, + { + // Zero S value + msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", + sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e549980000000000000000000000000000000000000000000000000000000000000000", + err: fmt.Errorf("signature S is 0"), + }, + { + // S = N (curve order of secp256k1) + msg: "ce0677bb30baa8cf067c88db9811f4333d131bf8bcf12fe7065d211dce971008", + sig: "0190f27b8b488db00b00606796d2987f6a5f59ae62ea05effe84fef5b8b0e54998fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + err: fmt.Errorf("signature S is >= curve order"), + }, } func TestRecoverCompact(t *testing.T) { From 2a1aa5129e2dc8d0f7441f723dc55ac12795d867 Mon Sep 17 00:00:00 2001 From: Jake Sylvestre Date: Sat, 5 Dec 2020 22:39:40 -0500 Subject: [PATCH 0430/1056] Add Batch JSON-RPC support (rpc client & server) --- btcjson/btcdextcmds_test.go | 4 +- btcjson/btcwalletextcmds_test.go | 4 +- btcjson/chainsvrcmds_test.go | 4 +- btcjson/chainsvrwscmds_test.go | 4 +- btcjson/chainsvrwsntfns_test.go | 4 +- btcjson/cmdparse.go | 4 +- btcjson/cmdparse_test.go | 12 +- btcjson/example_test.go | 8 +- btcjson/jsonrpc.go | 150 ++++- btcjson/jsonrpc_test.go | 12 +- btcjson/walletsvrcmds_test.go | 4 +- btcjson/walletsvrwscmds_test.go | 4 +- btcjson/walletsvrwsntfns_test.go | 4 +- cmd/btcctl/btcctl.go | 2 +- integration/bip0009_test.go | 14 +- integration/csv_fork_test.go | 36 +- integration/rpcserver_test.go | 60 +- integration/rpctest/rpc_harness.go | 57 +- integration/rpctest/rpc_harness_test.go | 18 +- integration/rpctest/utils.go | 14 +- .../examples/bitcoincorehttpbulk/README.md | 31 + .../examples/bitcoincorehttpbulk/main.go | 46 ++ rpcclient/infrastructure.go | 166 +++++- rpcclient/rawrequest.go | 2 +- rpcserver.go | 306 +++++++--- rpcwebsocket.go | 554 +++++++++++++----- 26 files changed, 1180 insertions(+), 344 deletions(-) create mode 100644 rpcclient/examples/bitcoincorehttpbulk/README.md create mode 100644 rpcclient/examples/bitcoincorehttpbulk/main.go diff --git a/btcjson/btcdextcmds_test.go b/btcjson/btcdextcmds_test.go index 143ec5224f..aaa44144e4 100644 --- a/btcjson/btcdextcmds_test.go +++ b/btcjson/btcdextcmds_test.go @@ -211,7 +211,7 @@ func TestBtcdExtCmds(t *testing.T) { for i, test := range tests { // Marshal the command as created by the new static command // creation function. - marshalled, err := btcjson.MarshalCmd(testID, test.staticCmd()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -235,7 +235,7 @@ func TestBtcdExtCmds(t *testing.T) { // Marshal the command as created by the generic new command // creation function. - marshalled, err = btcjson.MarshalCmd(testID, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/btcjson/btcwalletextcmds_test.go b/btcjson/btcwalletextcmds_test.go index 58de1c81d0..dea1c61465 100644 --- a/btcjson/btcwalletextcmds_test.go +++ b/btcjson/btcwalletextcmds_test.go @@ -145,7 +145,7 @@ func TestBtcWalletExtCmds(t *testing.T) { for i, test := range tests { // Marshal the command as created by the new static command // creation function. - marshalled, err := btcjson.MarshalCmd(testID, test.staticCmd()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -169,7 +169,7 @@ func TestBtcWalletExtCmds(t *testing.T) { // Marshal the command as created by the generic new command // creation function. - marshalled, err = btcjson.MarshalCmd(testID, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 263d6d7e5d..7d3a68dc41 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1466,7 +1466,7 @@ func TestChainSvrCmds(t *testing.T) { for i, test := range tests { // Marshal the command as created by the new static command // creation function. - marshalled, err := btcjson.MarshalCmd(testID, test.staticCmd()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -1491,7 +1491,7 @@ func TestChainSvrCmds(t *testing.T) { // Marshal the command as created by the generic new command // creation function. - marshalled, err = btcjson.MarshalCmd(testID, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/btcjson/chainsvrwscmds_test.go b/btcjson/chainsvrwscmds_test.go index b0cd63cc61..03fb22c8e0 100644 --- a/btcjson/chainsvrwscmds_test.go +++ b/btcjson/chainsvrwscmds_test.go @@ -233,7 +233,7 @@ func TestChainSvrWsCmds(t *testing.T) { for i, test := range tests { // Marshal the command as created by the new static command // creation function. - marshalled, err := btcjson.MarshalCmd(testID, test.staticCmd()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -257,7 +257,7 @@ func TestChainSvrWsCmds(t *testing.T) { // Marshal the command as created by the generic new command // creation function. - marshalled, err = btcjson.MarshalCmd(testID, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/btcjson/chainsvrwsntfns_test.go b/btcjson/chainsvrwsntfns_test.go index 2da1e7ad2f..e2b234c2a0 100644 --- a/btcjson/chainsvrwsntfns_test.go +++ b/btcjson/chainsvrwsntfns_test.go @@ -231,7 +231,7 @@ func TestChainSvrWsNtfns(t *testing.T) { for i, test := range tests { // Marshal the notification as created by the new static // creation function. The ID is nil for notifications. - marshalled, err := btcjson.MarshalCmd(nil, test.staticNtfn()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, test.staticNtfn()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -256,7 +256,7 @@ func TestChainSvrWsNtfns(t *testing.T) { // Marshal the notification as created by the generic new // notification creation function. The ID is nil for // notifications. - marshalled, err = btcjson.MarshalCmd(nil, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, nil, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/btcjson/cmdparse.go b/btcjson/cmdparse.go index 117f72f187..4fb8dd6260 100644 --- a/btcjson/cmdparse.go +++ b/btcjson/cmdparse.go @@ -36,7 +36,7 @@ func makeParams(rt reflect.Type, rv reflect.Value) []interface{} { // is suitable for transmission to an RPC server. The provided command type // must be a registered type. All commands provided by this package are // registered by default. -func MarshalCmd(id interface{}, cmd interface{}) ([]byte, error) { +func MarshalCmd(rpcVersion RPCVersion, id interface{}, cmd interface{}) ([]byte, error) { // Look up the cmd type and error out if not registered. rt := reflect.TypeOf(cmd) registerLock.RLock() @@ -60,7 +60,7 @@ func MarshalCmd(id interface{}, cmd interface{}) ([]byte, error) { params := makeParams(rt.Elem(), rv.Elem()) // Generate and marshal the final JSON-RPC request. - rawCmd, err := NewRequest(id, method, params) + rawCmd, err := NewRequest(rpcVersion, id, method, params) if err != nil { return nil, err } diff --git a/btcjson/cmdparse_test.go b/btcjson/cmdparse_test.go index 71547271df..f2585edf5c 100644 --- a/btcjson/cmdparse_test.go +++ b/btcjson/cmdparse_test.go @@ -460,7 +460,7 @@ func TestMarshalCmd(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - bytes, err := btcjson.MarshalCmd(test.id, test.cmd) + bytes, err := btcjson.MarshalCmd(btcjson.RpcVersion1, test.id, test.cmd) if err != nil { t.Errorf("Test #%d (%s) wrong error - got %T (%v)", i, test.name, err, err) @@ -507,7 +507,7 @@ func TestMarshalCmdErrors(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - _, err := btcjson.MarshalCmd(test.id, test.cmd) + _, err := btcjson.MarshalCmd(btcjson.RpcVersion1, test.id, test.cmd) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { t.Errorf("Test #%d (%s) wrong error - got %T (%v), "+ "want %T", i, test.name, err, err, test.err) @@ -535,7 +535,7 @@ func TestUnmarshalCmdErrors(t *testing.T) { { name: "unregistered type", request: btcjson.Request{ - Jsonrpc: "1.0", + Jsonrpc: btcjson.RpcVersion1, Method: "bogusmethod", Params: nil, ID: nil, @@ -545,7 +545,7 @@ func TestUnmarshalCmdErrors(t *testing.T) { { name: "incorrect number of params", request: btcjson.Request{ - Jsonrpc: "1.0", + Jsonrpc: btcjson.RpcVersion1, Method: "getblockcount", Params: []json.RawMessage{[]byte(`"bogusparam"`)}, ID: nil, @@ -555,7 +555,7 @@ func TestUnmarshalCmdErrors(t *testing.T) { { name: "invalid type for a parameter", request: btcjson.Request{ - Jsonrpc: "1.0", + Jsonrpc: btcjson.RpcVersion1, Method: "getblock", Params: []json.RawMessage{[]byte("1")}, ID: nil, @@ -565,7 +565,7 @@ func TestUnmarshalCmdErrors(t *testing.T) { { name: "invalid JSON for a parameter", request: btcjson.Request{ - Jsonrpc: "1.0", + Jsonrpc: btcjson.RpcVersion1, Method: "getblock", Params: []json.RawMessage{[]byte(`"1`)}, ID: nil, diff --git a/btcjson/example_test.go b/btcjson/example_test.go index 73dd804073..74478e7482 100644 --- a/btcjson/example_test.go +++ b/btcjson/example_test.go @@ -27,7 +27,7 @@ func ExampleMarshalCmd() { // server. Typically the client would increment the id here which is // request so the response can be identified. id := 1 - marshalledBytes, err := btcjson.MarshalCmd(id, gbCmd) + marshalledBytes, err := btcjson.MarshalCmd(btcjson.RpcVersion1, id, gbCmd) if err != nil { fmt.Println(err) return @@ -95,7 +95,7 @@ func ExampleUnmarshalCmd() { func ExampleMarshalResponse() { // Marshal a new JSON-RPC response. For example, this is a response // to a getblockheight request. - marshalledBytes, err := btcjson.MarshalResponse(1, 350001, nil) + marshalledBytes, err := btcjson.MarshalResponse(btcjson.RpcVersion1, 1, 350001, nil) if err != nil { fmt.Println(err) return @@ -107,7 +107,7 @@ func ExampleMarshalResponse() { fmt.Printf("%s\n", marshalledBytes) // Output: - // {"result":350001,"error":null,"id":1} + // {"jsonrpc":"1.0","result":350001,"error":null,"id":1} } // This example demonstrates how to unmarshal a JSON-RPC response and then @@ -116,7 +116,7 @@ func Example_unmarshalResponse() { // Ordinarily this would be read from the wire, but for this example, // it is hard coded here for clarity. This is an example response to a // getblockheight request. - data := []byte(`{"result":350001,"error":null,"id":1}`) + data := []byte(`{"jsonrpc":"1.0","result":350001,"error":null,"id":1}`) // Unmarshal the raw bytes from the wire into a JSON-RPC response. var response btcjson.Response diff --git a/btcjson/jsonrpc.go b/btcjson/jsonrpc.go index 0ead85e5ee..553a7bc37f 100644 --- a/btcjson/jsonrpc.go +++ b/btcjson/jsonrpc.go @@ -9,6 +9,33 @@ import ( "fmt" ) +// RPCVersion is a type to indicate RPC versions. +type RPCVersion string + +const ( + // version 1 of rpc + RpcVersion1 RPCVersion = RPCVersion("1.0") + // version 2 of rpc + RpcVersion2 RPCVersion = RPCVersion("2.0") +) + +var validRpcVersions = []RPCVersion{RpcVersion1, RpcVersion2} + +// check if the rpc version is a valid version +func (r RPCVersion) IsValid() bool { + for _, version := range validRpcVersions { + if version == r { + return true + } + } + return false +} + +// cast rpc version to a string +func (r RPCVersion) String() string { + return string(r) +} + // RPCErrorCode represents an error code to be used as a part of an RPCError // which is in turn used in a JSON-RPC Response object. // @@ -67,21 +94,74 @@ func IsValidIDType(id interface{}) bool { // requests, however this struct it being exported in case the caller wants to // construct raw requests for some reason. type Request struct { - Jsonrpc string `json:"jsonrpc"` + Jsonrpc RPCVersion `json:"jsonrpc"` Method string `json:"method"` Params []json.RawMessage `json:"params"` ID interface{} `json:"id"` } -// NewRequest returns a new JSON-RPC 1.0 request object given the provided id, -// method, and parameters. The parameters are marshalled into a json.RawMessage -// for the Params field of the returned request object. This function is only -// provided in case the caller wants to construct raw requests for some reason. -// -// Typically callers will instead want to create a registered concrete command -// type with the NewCmd or NewCmd functions and call the MarshalCmd -// function with that command to generate the marshalled JSON-RPC request. -func NewRequest(id interface{}, method string, params []interface{}) (*Request, error) { +// UnmarshalJSON is a custom unmarshal func for the Request struct. The param +// field defaults to an empty json.RawMessage array it is omitted by the request +// or nil if the supplied value is invalid. +func (request *Request) UnmarshalJSON(b []byte) error { + // Step 1: Create a type alias of the original struct. + type Alias Request + + // Step 2: Create an anonymous struct with raw replacements for the special + // fields. + aux := &struct { + Jsonrpc string `json:"jsonrpc"` + Params []interface{} `json:"params"` + *Alias + }{ + Alias: (*Alias)(request), + } + + // Step 3: Unmarshal the data into the anonymous struct. + err := json.Unmarshal(b, &aux) + if err != nil { + return err + } + + // Step 4: Convert the raw fields to the desired types + + version := RPCVersion(aux.Jsonrpc) + if version.IsValid() { + request.Jsonrpc = version + } + + rawParams := make([]json.RawMessage, 0) + + for _, param := range aux.Params { + marshalledParam, err := json.Marshal(param) + if err != nil { + return err + } + + rawMessage := json.RawMessage(marshalledParam) + rawParams = append(rawParams, rawMessage) + } + + request.Params = rawParams + + return nil +} + +// NewRequest returns a new JSON-RPC request object given the provided rpc +// version, id, method, and parameters. The parameters are marshalled into a +// json.RawMessage for the Params field of the returned request object. This +// function is only provided in case the caller wants to construct raw requests +// for some reason. Typically callers will instead want to create a registered +// concrete command type with the NewCmd or NewCmd functions and call the +// MarshalCmd function with that command to generate the marshalled JSON-RPC +// request. +func NewRequest(rpcVersion RPCVersion, id interface{}, method string, params []interface{}) (*Request, error) { + // default to JSON-RPC 1.0 if RPC type is not specified + if !rpcVersion.IsValid() { + str := fmt.Sprintf("rpcversion '%s' is invalid", rpcVersion) + return nil, makeError(ErrInvalidType, str) + } + if !IsValidIDType(id) { str := fmt.Sprintf("the id of type '%T' is invalid", id) return nil, makeError(ErrInvalidType, str) @@ -98,30 +178,35 @@ func NewRequest(id interface{}, method string, params []interface{}) (*Request, } return &Request{ - Jsonrpc: "1.0", + Jsonrpc: rpcVersion, ID: id, Method: method, Params: rawParams, }, nil } -// Response is the general form of a JSON-RPC response. The type of the Result -// field varies from one command to the next, so it is implemented as an -// interface. The ID field has to be a pointer for Go to put a null in it when +// Response is the general form of a JSON-RPC response. The type of the +// Result field varies from one command to the next, so it is implemented as an +// interface. The ID field has to be a pointer to allow for a nil value when // empty. type Response struct { - Result json.RawMessage `json:"result"` - Error *RPCError `json:"error"` - ID *interface{} `json:"id"` + Jsonrpc RPCVersion `json:"jsonrpc"` + Result json.RawMessage `json:"result"` + Error *RPCError `json:"error"` + ID *interface{} `json:"id"` } -// NewResponse returns a new JSON-RPC response object given the provided id, -// marshalled result, and RPC error. This function is only provided in case the -// caller wants to construct raw responses for some reason. -// +// NewResponse returns a new JSON-RPC response object given the provided rpc +// version, id, marshalled result, and RPC error. This function is only +// provided in case the caller wants to construct raw responses for some reason. // Typically callers will instead want to create the fully marshalled JSON-RPC // response to send over the wire with the MarshalResponse function. -func NewResponse(id interface{}, marshalledResult []byte, rpcErr *RPCError) (*Response, error) { +func NewResponse(rpcVersion RPCVersion, id interface{}, marshalledResult []byte, rpcErr *RPCError) (*Response, error) { + if !rpcVersion.IsValid() { + str := fmt.Sprintf("rpcversion '%s' is invalid", rpcVersion) + return nil, makeError(ErrInvalidType, str) + } + if !IsValidIDType(id) { str := fmt.Sprintf("the id of type '%T' is invalid", id) return nil, makeError(ErrInvalidType, str) @@ -129,20 +214,27 @@ func NewResponse(id interface{}, marshalledResult []byte, rpcErr *RPCError) (*Re pid := &id return &Response{ - Result: marshalledResult, - Error: rpcErr, - ID: pid, + Jsonrpc: rpcVersion, + Result: marshalledResult, + Error: rpcErr, + ID: pid, }, nil } -// MarshalResponse marshals the passed id, result, and RPCError to a JSON-RPC -// response byte slice that is suitable for transmission to a JSON-RPC client. -func MarshalResponse(id interface{}, result interface{}, rpcErr *RPCError) ([]byte, error) { +// MarshalResponse marshals the passed rpc version, id, result, and RPCError to +// a JSON-RPC response byte slice that is suitable for transmission to a +// JSON-RPC client. +func MarshalResponse(rpcVersion RPCVersion, id interface{}, result interface{}, rpcErr *RPCError) ([]byte, error) { + if !rpcVersion.IsValid() { + str := fmt.Sprintf("rpcversion '%s' is invalid", rpcVersion) + return nil, makeError(ErrInvalidType, str) + } + marshalledResult, err := json.Marshal(result) if err != nil { return nil, err } - response, err := NewResponse(id, marshalledResult, rpcErr) + response, err := NewResponse(rpcVersion, id, marshalledResult, rpcErr) if err != nil { return nil, err } diff --git a/btcjson/jsonrpc_test.go b/btcjson/jsonrpc_test.go index 7a5d75618c..13d98e89f5 100644 --- a/btcjson/jsonrpc_test.go +++ b/btcjson/jsonrpc_test.go @@ -68,7 +68,7 @@ func TestMarshalResponse(t *testing.T) { name: "ordinary bool result with no error", result: true, jsonErr: nil, - expected: []byte(`{"result":true,"error":null,"id":1}`), + expected: []byte(`{"jsonrpc":"1.0","result":true,"error":null,"id":1}`), }, { name: "result with error", @@ -76,14 +76,14 @@ func TestMarshalResponse(t *testing.T) { jsonErr: func() *btcjson.RPCError { return btcjson.NewRPCError(btcjson.ErrRPCBlockNotFound, "123 not found") }(), - expected: []byte(`{"result":null,"error":{"code":-5,"message":"123 not found"},"id":1}`), + expected: []byte(`{"jsonrpc":"1.0","result":null,"error":{"code":-5,"message":"123 not found"},"id":1}`), }, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { _, _ = i, test - marshalled, err := btcjson.MarshalResponse(testID, test.result, test.jsonErr) + marshalled, err := btcjson.MarshalResponse(btcjson.RpcVersion1, testID, test.result, test.jsonErr) if err != nil { t.Errorf("Test #%d (%s) unexpected error: %v", i, test.name, err) @@ -104,7 +104,7 @@ func TestMiscErrors(t *testing.T) { // Force an error in NewRequest by giving it a parameter type that is // not supported. - _, err := btcjson.NewRequest(nil, "test", []interface{}{make(chan int)}) + _, err := btcjson.NewRequest(btcjson.RpcVersion1, nil, "test", []interface{}{make(chan int)}) if err == nil { t.Error("NewRequest: did not receive error") return @@ -113,7 +113,7 @@ func TestMiscErrors(t *testing.T) { // Force an error in MarshalResponse by giving it an id type that is not // supported. wantErr := btcjson.Error{ErrorCode: btcjson.ErrInvalidType} - _, err = btcjson.MarshalResponse(make(chan int), nil, nil) + _, err = btcjson.MarshalResponse(btcjson.RpcVersion1, make(chan int), nil, nil) if jerr, ok := err.(btcjson.Error); !ok || jerr.ErrorCode != wantErr.ErrorCode { t.Errorf("MarshalResult: did not receive expected error - got "+ "%v (%[1]T), want %v (%[2]T)", err, wantErr) @@ -122,7 +122,7 @@ func TestMiscErrors(t *testing.T) { // Force an error in MarshalResponse by giving it a result type that // can't be marshalled. - _, err = btcjson.MarshalResponse(1, make(chan int), nil) + _, err = btcjson.MarshalResponse(btcjson.RpcVersion1, 1, make(chan int), nil) if _, ok := err.(*json.UnsupportedTypeError); !ok { wantErr := &json.UnsupportedTypeError{} t.Errorf("MarshalResult: did not receive expected error - got "+ diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 9ee6f0c749..9c68d260f6 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -1800,7 +1800,7 @@ func TestWalletSvrCmds(t *testing.T) { for i, test := range tests { // Marshal the command as created by the new static command // creation function. - marshalled, err := btcjson.MarshalCmd(testID, test.staticCmd()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -1824,7 +1824,7 @@ func TestWalletSvrCmds(t *testing.T) { // Marshal the command as created by the generic new command // creation function. - marshalled, err = btcjson.MarshalCmd(testID, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/btcjson/walletsvrwscmds_test.go b/btcjson/walletsvrwscmds_test.go index 17144b6ea7..110a893b23 100644 --- a/btcjson/walletsvrwscmds_test.go +++ b/btcjson/walletsvrwscmds_test.go @@ -195,7 +195,7 @@ func TestWalletSvrWsCmds(t *testing.T) { for i, test := range tests { // Marshal the command as created by the new static command // creation function. - marshalled, err := btcjson.MarshalCmd(testID, test.staticCmd()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, testID, test.staticCmd()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -219,7 +219,7 @@ func TestWalletSvrWsCmds(t *testing.T) { // Marshal the command as created by the generic new command // creation function. - marshalled, err = btcjson.MarshalCmd(testID, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, testID, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/btcjson/walletsvrwsntfns_test.go b/btcjson/walletsvrwsntfns_test.go index 7662b3c2a1..111916627e 100644 --- a/btcjson/walletsvrwsntfns_test.go +++ b/btcjson/walletsvrwsntfns_test.go @@ -122,7 +122,7 @@ func TestWalletSvrWsNtfns(t *testing.T) { for i, test := range tests { // Marshal the notification as created by the new static // creation function. The ID is nil for notifications. - marshalled, err := btcjson.MarshalCmd(nil, test.staticNtfn()) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, test.staticNtfn()) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) @@ -147,7 +147,7 @@ func TestWalletSvrWsNtfns(t *testing.T) { // Marshal the notification as created by the generic new // notification creation function. The ID is nil for // notifications. - marshalled, err = btcjson.MarshalCmd(nil, cmd) + marshalled, err = btcjson.MarshalCmd(btcjson.RpcVersion1, nil, cmd) if err != nil { t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i, test.name, err) diff --git a/cmd/btcctl/btcctl.go b/cmd/btcctl/btcctl.go index 5c412f867f..771d5f7ed7 100644 --- a/cmd/btcctl/btcctl.go +++ b/cmd/btcctl/btcctl.go @@ -127,7 +127,7 @@ func main() { // Marshal the command into a JSON-RPC byte slice in preparation for // sending it to the RPC server. - marshalledJSON, err := btcjson.MarshalCmd(1, cmd) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, 1, cmd) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/integration/bip0009_test.go b/integration/bip0009_test.go index b72065594c..9bdec34fbb 100644 --- a/integration/bip0009_test.go +++ b/integration/bip0009_test.go @@ -33,7 +33,7 @@ const ( // ensures its version either has the provided bit set or unset per the set // flag. func assertVersionBit(r *rpctest.Harness, t *testing.T, hash *chainhash.Hash, bit uint8, set bool) { - block, err := r.Node.GetBlock(hash) + block, err := r.Client.GetBlock(hash) if err != nil { t.Fatalf("failed to retrieve block %v: %v", hash, err) } @@ -53,7 +53,7 @@ func assertVersionBit(r *rpctest.Harness, t *testing.T, hash *chainhash.Hash, bi // assertChainHeight retrieves the current chain height from the given test // harness and ensures it matches the provided expected height. func assertChainHeight(r *rpctest.Harness, t *testing.T, expectedHeight uint32) { - height, err := r.Node.GetBlockCount() + height, err := r.Client.GetBlockCount() if err != nil { t.Fatalf("failed to retrieve block height: %v", err) } @@ -96,7 +96,7 @@ func assertSoftForkStatus(r *rpctest.Harness, t *testing.T, forkKey string, stat "threshold state %v to string", line, state) } - info, err := r.Node.GetBlockChainInfo() + info, err := r.Client.GetBlockChainInfo() if err != nil { t.Fatalf("failed to retrieve chain info: %v", err) } @@ -339,7 +339,7 @@ func TestBIP0009Mining(t *testing.T) { // in the defined threshold state. deployment := &r.ActiveNet.Deployments[chaincfg.DeploymentTestDummy] testDummyBitNum := deployment.BitNumber - hashes, err := r.Node.Generate(1) + hashes, err := r.Client.Generate(1) if err != nil { t.Fatalf("unable to generate blocks: %v", err) } @@ -358,7 +358,7 @@ func TestBIP0009Mining(t *testing.T) { // dummy deployment as started. confirmationWindow := r.ActiveNet.MinerConfirmationWindow numNeeded := confirmationWindow - 1 - hashes, err = r.Node.Generate(numNeeded) + hashes, err = r.Client.Generate(numNeeded) if err != nil { t.Fatalf("failed to generated %d blocks: %v", numNeeded, err) } @@ -373,7 +373,7 @@ func TestBIP0009Mining(t *testing.T) { // The last generated block should still have the test bit set in the // version since the btcd mining code will have recognized the test // dummy deployment as locked in. - hashes, err = r.Node.Generate(confirmationWindow) + hashes, err = r.Client.Generate(confirmationWindow) if err != nil { t.Fatalf("failed to generated %d blocks: %v", confirmationWindow, err) @@ -392,7 +392,7 @@ func TestBIP0009Mining(t *testing.T) { // version since the btcd mining code will have recognized the test // dummy deployment as activated and thus there is no longer any need // to set the bit. - hashes, err = r.Node.Generate(confirmationWindow) + hashes, err = r.Client.Generate(confirmationWindow) if err != nil { t.Fatalf("failed to generated %d blocks: %v", confirmationWindow, err) diff --git a/integration/csv_fork_test.go b/integration/csv_fork_test.go index b623487e59..3146634966 100644 --- a/integration/csv_fork_test.go +++ b/integration/csv_fork_test.go @@ -57,14 +57,14 @@ func makeTestOutput(r *rpctest.Harness, t *testing.T, if err != nil { return nil, nil, nil, err } - txHash, err := r.Node.SendRawTransaction(fundTx, true) + txHash, err := r.Client.SendRawTransaction(fundTx, true) if err != nil { return nil, nil, nil, err } // The transaction created above should be included within the next // generated block. - blockHash, err := r.Node.Generate(1) + blockHash, err := r.Client.Generate(1) if err != nil { return nil, nil, nil, err } @@ -151,7 +151,7 @@ func TestBIP0113Activation(t *testing.T) { // We set the lock-time of the transaction to just one minute after the // current MTP of the chain. - chainInfo, err := r.Node.GetBlockChainInfo() + chainInfo, err := r.Client.GetBlockChainInfo() if err != nil { t.Fatalf("unable to query for chain info: %v", err) } @@ -167,7 +167,7 @@ func TestBIP0113Activation(t *testing.T) { // This transaction should be rejected from the mempool as using MTP // for transactions finality is now a policy rule. Additionally, the // exact error should be the rejection of a non-final transaction. - _, err = r.Node.SendRawTransaction(tx, true) + _, err = r.Client.SendRawTransaction(tx, true) if err == nil { t.Fatalf("transaction accepted, but should be non-final") } else if !strings.Contains(err.Error(), "not finalized") { @@ -201,7 +201,7 @@ func TestBIP0113Activation(t *testing.T) { // height 299. The getblockchaininfo call checks the state for the // block AFTER the current height. numBlocks := (r.ActiveNet.MinerConfirmationWindow * 2) - 4 - if _, err := r.Node.Generate(numBlocks); err != nil { + if _, err := r.Client.Generate(numBlocks); err != nil { t.Fatalf("unable to generate blocks: %v", err) } @@ -220,7 +220,7 @@ func TestBIP0113Activation(t *testing.T) { // rejected. timeLockDeltas := []int64{-1, 0, 1} for _, timeLockDelta := range timeLockDeltas { - chainInfo, err = r.Node.GetBlockChainInfo() + chainInfo, err = r.Client.GetBlockChainInfo() if err != nil { t.Fatalf("unable to query for chain info: %v", err) } @@ -257,7 +257,7 @@ func TestBIP0113Activation(t *testing.T) { // accepted as it has a lock-time of one // second _before_ the current MTP. - _, err = r.Node.SendRawTransaction(tx, true) + _, err = r.Client.SendRawTransaction(tx, true) if err == nil && timeLockDelta >= 0 { t.Fatal("transaction was accepted into the mempool " + "but should be rejected!") @@ -366,7 +366,7 @@ func spendCSVOutput(redeemScript []byte, csvUTXO *wire.OutPoint, func assertTxInBlock(r *rpctest.Harness, t *testing.T, blockHash *chainhash.Hash, txid *chainhash.Hash) { - block, err := r.Node.GetBlock(blockHash) + block, err := r.Client.GetBlock(blockHash) if err != nil { t.Fatalf("unable to get block: %v", err) } @@ -449,10 +449,10 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { // As the transaction is p2sh it should be accepted into the // mempool and found within the next generated block. - if _, err := r.Node.SendRawTransaction(tx, true); err != nil { + if _, err := r.Client.SendRawTransaction(tx, true); err != nil { t.Fatalf("unable to broadcast tx: %v", err) } - blocks, err := r.Node.Generate(1) + blocks, err := r.Client.Generate(1) if err != nil { t.Fatalf("unable to generate blocks: %v", err) } @@ -469,7 +469,7 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { // This transaction should be rejected from the mempool since // CSV validation is already mempool policy pre-fork. - _, err = r.Node.SendRawTransaction(spendingTx, true) + _, err = r.Client.SendRawTransaction(spendingTx, true) if err == nil { t.Fatalf("transaction should have been rejected, but was " + "instead accepted") @@ -496,7 +496,7 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { // height 299. The getblockchaininfo call checks the state for the // block AFTER the current height. numBlocks := (r.ActiveNet.MinerConfirmationWindow * 2) - 8 - if _, err := r.Node.Generate(numBlocks); err != nil { + if _, err := r.Client.Generate(numBlocks); err != nil { t.Fatalf("unable to generate blocks: %v", err) } @@ -530,7 +530,7 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { t.Fatalf("unable to create CSV output: %v", err) } - if _, err := r.Node.SendRawTransaction(tx, true); err != nil { + if _, err := r.Client.SendRawTransaction(tx, true); err != nil { t.Fatalf("unable to broadcast transaction: %v", err) } @@ -542,17 +542,17 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { } // Mine a single block including all the transactions generated above. - if _, err := r.Node.Generate(1); err != nil { + if _, err := r.Client.Generate(1); err != nil { t.Fatalf("unable to generate block: %v", err) } // Now mine 10 additional blocks giving the inputs generated above a // age of 11. Space out each block 10 minutes after the previous block. - prevBlockHash, err := r.Node.GetBestBlockHash() + prevBlockHash, err := r.Client.GetBestBlockHash() if err != nil { t.Fatalf("unable to get prior block hash: %v", err) } - prevBlock, err := r.Node.GetBlock(prevBlockHash) + prevBlock, err := r.Client.GetBlock(prevBlockHash) if err != nil { t.Fatalf("unable to get block: %v", err) } @@ -652,7 +652,7 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { } for i, test := range tests { - txid, err := r.Node.SendRawTransaction(test.tx, true) + txid, err := r.Client.SendRawTransaction(test.tx, true) switch { // Test case passes, nothing further to report. case test.accept && err == nil: @@ -686,7 +686,7 @@ func TestBIP0068AndBIP0112Activation(t *testing.T) { // Generate a block, the transaction should be included within // the newly mined block. - blockHashes, err := r.Node.Generate(1) + blockHashes, err := r.Client.Generate(1) if err != nil { t.Fatalf("unable to mine block: %v", err) } diff --git a/integration/rpcserver_test.go b/integration/rpcserver_test.go index e5528453d4..5875b35353 100644 --- a/integration/rpcserver_test.go +++ b/integration/rpcserver_test.go @@ -15,22 +15,24 @@ import ( "testing" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/integration/rpctest" + "github.com/btcsuite/btcd/rpcclient" ) func testGetBestBlock(r *rpctest.Harness, t *testing.T) { - _, prevbestHeight, err := r.Node.GetBestBlock() + _, prevbestHeight, err := r.Client.GetBestBlock() if err != nil { t.Fatalf("Call to `getbestblock` failed: %v", err) } // Create a new block connecting to the current tip. - generatedBlockHashes, err := r.Node.Generate(1) + generatedBlockHashes, err := r.Client.Generate(1) if err != nil { t.Fatalf("Unable to generate block: %v", err) } - bestHash, bestHeight, err := r.Node.GetBestBlock() + bestHash, bestHeight, err := r.Client.GetBestBlock() if err != nil { t.Fatalf("Call to `getbestblock` failed: %v", err) } @@ -50,17 +52,17 @@ func testGetBestBlock(r *rpctest.Harness, t *testing.T) { func testGetBlockCount(r *rpctest.Harness, t *testing.T) { // Save the current count. - currentCount, err := r.Node.GetBlockCount() + currentCount, err := r.Client.GetBlockCount() if err != nil { t.Fatalf("Unable to get block count: %v", err) } - if _, err := r.Node.Generate(1); err != nil { + if _, err := r.Client.Generate(1); err != nil { t.Fatalf("Unable to generate block: %v", err) } // Count should have increased by one. - newCount, err := r.Node.GetBlockCount() + newCount, err := r.Client.GetBlockCount() if err != nil { t.Fatalf("Unable to get block count: %v", err) } @@ -72,17 +74,17 @@ func testGetBlockCount(r *rpctest.Harness, t *testing.T) { func testGetBlockHash(r *rpctest.Harness, t *testing.T) { // Create a new block connecting to the current tip. - generatedBlockHashes, err := r.Node.Generate(1) + generatedBlockHashes, err := r.Client.Generate(1) if err != nil { t.Fatalf("Unable to generate block: %v", err) } - info, err := r.Node.GetInfo() + info, err := r.Client.GetInfo() if err != nil { t.Fatalf("call to getinfo cailed: %v", err) } - blockHash, err := r.Node.GetBlockHash(int64(info.Blocks)) + blockHash, err := r.Client.GetBlockHash(int64(info.Blocks)) if err != nil { t.Fatalf("Call to `getblockhash` failed: %v", err) } @@ -94,10 +96,50 @@ func testGetBlockHash(r *rpctest.Harness, t *testing.T) { } } +func testBulkClient(r *rpctest.Harness, t *testing.T) { + // Create a new block connecting to the current tip. + generatedBlockHashes, err := r.Client.Generate(20) + if err != nil { + t.Fatalf("Unable to generate block: %v", err) + } + + var futureBlockResults []rpcclient.FutureGetBlockResult + for _, hash := range generatedBlockHashes { + futureBlockResults = append(futureBlockResults, r.BatchClient.GetBlockAsync(hash)) + } + + err = r.BatchClient.Send() + if err != nil { + t.Fatal(err) + } + + isKnownBlockHash := func(blockHash chainhash.Hash) bool { + for _, hash := range generatedBlockHashes { + if blockHash.IsEqual(hash) { + return true + } + } + return false + } + + for _, block := range futureBlockResults { + msgBlock, err := block.Receive() + if err != nil { + t.Fatal(err) + } + blockHash := msgBlock.Header.BlockHash() + if !isKnownBlockHash(blockHash) { + t.Fatalf("expected hash %s to be in generated hash list", blockHash) + } + } + +} + var rpcTestCases = []rpctest.HarnessTestCase{ testGetBestBlock, testGetBlockCount, testGetBlockHash, + testBulkClient, } var primaryHarness *rpctest.Harness diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index ff8c0216b1..679ae4e478 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -92,9 +92,10 @@ type Harness struct { // attempts. ConnectionRetryTimeout time.Duration - Node *rpcclient.Client - node *node - handlers *rpcclient.NotificationHandlers + Client *rpcclient.Client + BatchClient *rpcclient.Client + node *node + handlers *rpcclient.NotificationHandlers wallet *memWallet @@ -245,13 +246,13 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { // Filter transactions that pay to the coinbase associated with the // wallet. filterAddrs := []btcutil.Address{h.wallet.coinbaseAddr} - if err := h.Node.LoadTxFilter(true, filterAddrs, nil); err != nil { + if err := h.Client.LoadTxFilter(true, filterAddrs, nil); err != nil { return err } // Ensure btcd properly dispatches our registered call-back for each new // block. Otherwise, the memWallet won't function properly. - if err := h.Node.NotifyBlocks(); err != nil { + if err := h.Client.NotifyBlocks(); err != nil { return err } @@ -260,7 +261,7 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { if createTestChain && numMatureOutputs != 0 { numToGenerate := (uint32(h.ActiveNet.CoinbaseMaturity) + numMatureOutputs) - _, err := h.Node.Generate(numToGenerate) + _, err := h.Client.Generate(numToGenerate) if err != nil { return err } @@ -268,7 +269,7 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { // Block until the wallet has fully synced up to the tip of the main // chain. - _, height, err := h.Node.GetBestBlock() + _, height, err := h.Client.GetBestBlock() if err != nil { return err } @@ -289,8 +290,12 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { // // This function MUST be called with the harness state mutex held (for writes). func (h *Harness) tearDown() error { - if h.Node != nil { - h.Node.Shutdown() + if h.Client != nil { + h.Client.Shutdown() + } + + if h.BatchClient != nil { + h.BatchClient.Shutdown() } if err := h.node.shutdown(); err != nil { @@ -325,24 +330,38 @@ func (h *Harness) TearDown() error { // we're not able to establish a connection, this function returns with an // error. func (h *Harness) connectRPCClient() error { - var client *rpcclient.Client + var client, batchClient *rpcclient.Client var err error rpcConf := h.node.config.rpcConnConfig() + batchConf := h.node.config.rpcConnConfig() + batchConf.HTTPPostMode = true for i := 0; i < h.MaxConnRetries; i++ { - if client, err = rpcclient.New(&rpcConf, h.handlers); err != nil { - time.Sleep(time.Duration(i) * h.ConnectionRetryTimeout) - continue + fail := false + if client == nil { + if client, err = rpcclient.New(&rpcConf, h.handlers); err != nil { + time.Sleep(time.Duration(i) * h.ConnectionRetryTimeout) + fail = true + } + } + if batchClient == nil { + if batchClient, err = rpcclient.NewBatch(&batchConf); err != nil { + time.Sleep(time.Duration(i) * h.ConnectionRetryTimeout) + fail = true + } + } + if !fail { + break } - break } - if client == nil { + if client == nil || batchClient == nil { return fmt.Errorf("connection timeout") } - h.Node = client + h.Client = client h.wallet.SetRPCClient(client) + h.BatchClient = batchClient return nil } @@ -464,11 +483,11 @@ func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs( blockVersion = BlockVersion } - prevBlockHash, prevBlockHeight, err := h.Node.GetBestBlock() + prevBlockHash, prevBlockHeight, err := h.Client.GetBestBlock() if err != nil { return nil, err } - mBlock, err := h.Node.GetBlock(prevBlockHash) + mBlock, err := h.Client.GetBlock(prevBlockHash) if err != nil { return nil, err } @@ -483,7 +502,7 @@ func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs( } // Submit the block to the simnet node. - if err := h.Node.SubmitBlock(newBlock, nil); err != nil { + if err := h.Client.SubmitBlock(newBlock, nil); err != nil { return nil, err } diff --git a/integration/rpctest/rpc_harness_test.go b/integration/rpctest/rpc_harness_test.go index 25faf96901..df753e3126 100644 --- a/integration/rpctest/rpc_harness_test.go +++ b/integration/rpctest/rpc_harness_test.go @@ -43,7 +43,7 @@ func testSendOutputs(r *Harness, t *testing.T) { } assertTxMined := func(txid *chainhash.Hash, blockHash *chainhash.Hash) { - block, err := r.Node.GetBlock(blockHash) + block, err := r.Client.GetBlock(blockHash) if err != nil { t.Fatalf("unable to get block: %v", err) } @@ -67,7 +67,7 @@ func testSendOutputs(r *Harness, t *testing.T) { // Generate a single block, the transaction the wallet created should // be found in this block. - blockHashes, err := r.Node.Generate(1) + blockHashes, err := r.Client.Generate(1) if err != nil { t.Fatalf("unable to generate single block: %v", err) } @@ -76,7 +76,7 @@ func testSendOutputs(r *Harness, t *testing.T) { // Next, generate a spend much greater than the block reward. This // transaction should also have been mined properly. txid = genSpend(btcutil.Amount(500 * btcutil.SatoshiPerBitcoin)) - blockHashes, err = r.Node.Generate(1) + blockHashes, err = r.Client.Generate(1) if err != nil { t.Fatalf("unable to generate single block: %v", err) } @@ -84,7 +84,7 @@ func testSendOutputs(r *Harness, t *testing.T) { } func assertConnectedTo(t *testing.T, nodeA *Harness, nodeB *Harness) { - nodeAPeers, err := nodeA.Node.GetPeerInfo() + nodeAPeers, err := nodeA.Client.GetPeerInfo() if err != nil { t.Fatalf("unable to get nodeA's peer info") } @@ -170,7 +170,7 @@ func testActiveHarnesses(r *Harness, t *testing.T) { func testJoinMempools(r *Harness, t *testing.T) { // Assert main test harness has no transactions in its mempool. - pooledHashes, err := r.Node.GetRawMempool() + pooledHashes, err := r.Client.GetRawMempool() if err != nil { t.Fatalf("unable to get mempool for main test harness: %v", err) } @@ -210,7 +210,7 @@ func testJoinMempools(r *Harness, t *testing.T) { if err != nil { t.Fatalf("coinbase spend failed: %v", err) } - if _, err := r.Node.SendRawTransaction(testTx, true); err != nil { + if _, err := r.Client.SendRawTransaction(testTx, true); err != nil { t.Fatalf("send transaction failed: %v", err) } @@ -219,7 +219,7 @@ func testJoinMempools(r *Harness, t *testing.T) { harnessSynced := make(chan struct{}) go func() { for { - poolHashes, err := r.Node.GetRawMempool() + poolHashes, err := r.Client.GetRawMempool() if err != nil { t.Fatalf("failed to retrieve harness mempool: %v", err) } @@ -262,7 +262,7 @@ func testJoinMempools(r *Harness, t *testing.T) { // Send the transaction to the local harness which will result in synced // mempools. - if _, err := harness.Node.SendRawTransaction(testTx, true); err != nil { + if _, err := harness.Client.SendRawTransaction(testTx, true); err != nil { t.Fatalf("send transaction failed: %v", err) } @@ -612,7 +612,7 @@ func TestHarness(t *testing.T) { // Current tip should be at a height of numMatureOutputs plus the // required number of blocks for coinbase maturity. - nodeInfo, err := mainHarness.Node.GetInfo() + nodeInfo, err := mainHarness.Client.GetInfo() if err != nil { t.Fatalf("unable to execute getinfo on node: %v", err) } diff --git a/integration/rpctest/utils.go b/integration/rpctest/utils.go index fc7d938dcf..d4d76f2ee6 100644 --- a/integration/rpctest/utils.go +++ b/integration/rpctest/utils.go @@ -49,7 +49,7 @@ func syncMempools(nodes []*Harness) error { retry: for !poolsMatch { - firstPool, err := nodes[0].Node.GetRawMempool() + firstPool, err := nodes[0].Client.GetRawMempool() if err != nil { return err } @@ -58,7 +58,7 @@ retry: // first node, then we're done. Otherwise, drop back to the top // of the loop and retry after a short wait period. for _, node := range nodes[1:] { - nodePool, err := node.Node.GetRawMempool() + nodePool, err := node.Client.GetRawMempool() if err != nil { return err } @@ -84,7 +84,7 @@ retry: var prevHash *chainhash.Hash var prevHeight int32 for _, node := range nodes { - blockHash, blockHeight, err := node.Node.GetBestBlock() + blockHash, blockHeight, err := node.Client.GetBestBlock() if err != nil { return err } @@ -108,24 +108,24 @@ retry: // therefore in the case of disconnects, "from" will attempt to reestablish a // connection to the "to" harness. func ConnectNode(from *Harness, to *Harness) error { - peerInfo, err := from.Node.GetPeerInfo() + peerInfo, err := from.Client.GetPeerInfo() if err != nil { return err } numPeers := len(peerInfo) targetAddr := to.node.config.listen - if err := from.Node.AddNode(targetAddr, rpcclient.ANAdd); err != nil { + if err := from.Client.AddNode(targetAddr, rpcclient.ANAdd); err != nil { return err } // Block until a new connection has been established. - peerInfo, err = from.Node.GetPeerInfo() + peerInfo, err = from.Client.GetPeerInfo() if err != nil { return err } for len(peerInfo) <= numPeers { - peerInfo, err = from.Node.GetPeerInfo() + peerInfo, err = from.Client.GetPeerInfo() if err != nil { return err } diff --git a/rpcclient/examples/bitcoincorehttpbulk/README.md b/rpcclient/examples/bitcoincorehttpbulk/README.md new file mode 100644 index 0000000000..ca900b6e79 --- /dev/null +++ b/rpcclient/examples/bitcoincorehttpbulk/README.md @@ -0,0 +1,31 @@ +Bitcoin Core Batch HTTP POST Example +============================== + +This example shows how to use the rpclient package to connect to a Bitcoin Core RPC server using HTTP POST and batch JSON-RPC mode with TLS disabled. + +## Running the Example + +The first step is to use `go get` to download and install the rpcclient package: + +```bash +$ go get github.com/btcsuite/btcd/rpcclient +``` + +Next, modify the `main.go` source to specify the correct RPC username and +password for the RPC server: + +```Go + User: "yourrpcuser", + Pass: "yourrpcpass", +``` + +Finally, navigate to the example's directory and run it with: + +```bash +$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/bitcoincorehttp +$ go run *.go +``` + +## License + +This example is licensed under the [copyfree](http://copyfree.org) ISC License. diff --git a/rpcclient/examples/bitcoincorehttpbulk/main.go b/rpcclient/examples/bitcoincorehttpbulk/main.go new file mode 100644 index 0000000000..3dce058da0 --- /dev/null +++ b/rpcclient/examples/bitcoincorehttpbulk/main.go @@ -0,0 +1,46 @@ +// Copyright (c) 2014-2020 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "log" + + "github.com/btcsuite/btcd/rpcclient" +) + +func main() { + // Connect to local bitcoin core RPC server using HTTP POST mode. + connCfg := &rpcclient.ConnConfig{ + Host: "localhost:8332", + User: "yourrpcuser", + Pass: "yourrpcpass", + DisableConnectOnNew: true, + HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode + DisableTLS: true, // Bitcoin core does not provide TLS by default + } + batchClient, err := rpcclient.NewBatch(connCfg) + defer batchClient.Shutdown() + + if err != nil { + log.Fatal(err) + } + + // batch mode requires async requests + blockCount := batchClient.GetBlockCountAsync() + block1 := batchClient.GetBlockHashAsync(1) + batchClient.GetBlockHashAsync(2) + batchClient.GetBlockHashAsync(3) + block4 := batchClient.GetBlockHashAsync(4) + difficulty := batchClient.GetDifficultyAsync() + + // sends all queued batch requests + batchClient.Send() + + fmt.Println(blockCount.Receive()) + fmt.Println(block1.Receive()) + fmt.Println(block4.Receive()) + fmt.Println(difficulty.Receive()) +} diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 4f15ed1430..798f027911 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -163,6 +163,10 @@ type Client struct { // disconnected indicated whether or not the server is disconnected. disconnected bool + // whether or not to batch requests, false unless changed by Batch() + batch bool + batchList *list.List + // retryCount holds the number of times the client has tried to // reconnect to the RPC server. retryCount int64 @@ -220,8 +224,13 @@ func (c *Client) addRequest(jReq *jsonRequest) error { default: } - element := c.requestList.PushBack(jReq) - c.requestMap[jReq.id] = element + if !c.batch { + element := c.requestList.PushBack(jReq) + c.requestMap[jReq.id] = element + } else { + element := c.batchList.PushBack(jReq) + c.requestMap[jReq.id] = element + } return nil } @@ -289,6 +298,41 @@ func (c *Client) trackRegisteredNtfns(cmd interface{}) { } } +// FutureGetBulkResult waits for the responses promised by the future +// and returns them in a channel +type FutureGetBulkResult chan *response + +// Receive waits for the response promised by the future and returns an map +// of results by request id +func (r FutureGetBulkResult) Receive() (BulkResult, error) { + m := make(BulkResult) + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + var arr []IndividualBulkResult + err = json.Unmarshal(res, &arr) + if err != nil { + return nil, err + } + + for _, results := range arr { + m[results.Id] = results + } + + return m, nil +} + +// IndividualBulkResult represents one result +// from a bulk json rpc api +type IndividualBulkResult struct { + Result interface{} `json:"result"` + Error *btcjson.RPCError `json:"error"` + Id uint64 `json:"id"` +} + +type BulkResult = map[uint64]IndividualBulkResult + // inMessage is the first type that an incoming message is unmarshaled // into. It supports both requests (for notification support) and // responses. The partially-unmarshaled message is a notification if @@ -741,7 +785,12 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) { // Try to unmarshal the response as a regular JSON-RPC response. var resp rawResponse - err = json.Unmarshal(respBytes, &resp) + var batchResponse json.RawMessage + if c.batch { + err = json.Unmarshal(respBytes, &batchResponse) + } else { + err = json.Unmarshal(respBytes, &resp) + } if err != nil { // When the response itself isn't a valid JSON-RPC response // return an error which includes the HTTP status code and raw @@ -751,8 +800,14 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) { jReq.responseChan <- &response{err: err} return } - - res, err := resp.result() + var res []byte + if c.batch { + // errors must be dealt with downstream since a whole request cannot + // "error out" other than through the status code error handled above + res, err = batchResponse, nil + } else { + res, err = resp.result() + } jReq.responseChan <- &response{result: res, err: err} } @@ -875,7 +930,13 @@ func (c *Client) sendRequest(jReq *jsonRequest) { // POST mode, the command is issued via an HTTP client. Otherwise, // the command is issued via the asynchronous websocket channels. if c.config.HTTPPostMode { - c.sendPost(jReq) + if c.batch { + if err := c.addRequest(jReq); err != nil { + log.Warn(err) + } + } else { + c.sendPost(jReq) + } return } @@ -905,6 +966,10 @@ func (c *Client) sendRequest(jReq *jsonRequest) { // future. It handles both websocket and HTTP POST mode depending on the // configuration of the client. func (c *Client) sendCmd(cmd interface{}) chan *response { + rpcVersion := btcjson.RpcVersion1 + if c.batch { + rpcVersion = btcjson.RpcVersion2 + } // Get the method associated with the command. method, err := btcjson.CmdMethod(cmd) if err != nil { @@ -913,7 +978,7 @@ func (c *Client) sendCmd(cmd interface{}) chan *response { // Marshal the command. id := c.NextID() - marshalledJSON, err := btcjson.MarshalCmd(id, cmd) + marshalledJSON, err := btcjson.MarshalCmd(rpcVersion, id, cmd) if err != nil { return newFutureError(err) } @@ -927,6 +992,7 @@ func (c *Client) sendCmd(cmd interface{}) chan *response { marshalledJSON: marshalledJSON, responseChan: responseChan, } + c.sendRequest(jReq) return responseChan @@ -1357,6 +1423,8 @@ func New(config *ConnConfig, ntfnHandlers *NotificationHandlers) (*Client, error httpClient: httpClient, requestMap: make(map[uint64]*list.Element), requestList: list.New(), + batch: false, + batchList: list.New(), ntfnHandlers: ntfnHandlers, ntfnState: newNotificationState(), sendChan: make(chan []byte, sendBufferSize), @@ -1397,6 +1465,24 @@ func New(config *ConnConfig, ntfnHandlers *NotificationHandlers) (*Client, error return client, nil } +// Batch is a factory that creates a client able to interact with the server using +// JSON-RPC 2.0. The client is capable of accepting an arbitrary number of requests +// and having the server process the all at the same time. It's compatible with both +// btcd and bitcoind +func NewBatch(config *ConnConfig) (*Client, error) { + if !config.HTTPPostMode { + return nil, errors.New("http post mode is required to use batch client") + } + // notification parameter is nil since notifications are not supported in POST mode. + client, err := New(config, nil) + if err != nil { + return nil, err + } + client.batch = true //copy the client with changed batch setting + client.start() + return client, nil +} + // Connect establishes the initial websocket connection. This is necessary when // a client was created after setting the DisableConnectOnNew field of the // Config struct. @@ -1534,3 +1620,69 @@ func (c *Client) BackendVersion() (BackendVersion, error) { return *c.backendVersion, nil } + +func (c *Client) sendAsync() FutureGetBulkResult { + // convert the array of marshalled json requests to a single request we can send + responseChan := make(chan *response, 1) + marshalledRequest := []byte("[") + for iter := c.batchList.Front(); iter != nil; iter = iter.Next() { + request := iter.Value.(*jsonRequest) + marshalledRequest = append(marshalledRequest, request.marshalledJSON...) + marshalledRequest = append(marshalledRequest, []byte(",")...) + } + if len(marshalledRequest) > 0 { + // removes the trailing comma to process the request individually + marshalledRequest = marshalledRequest[:len(marshalledRequest)-1] + } + marshalledRequest = append(marshalledRequest, []byte("]")...) + request := jsonRequest{ + id: c.NextID(), + method: "", + cmd: nil, + marshalledJSON: marshalledRequest, + responseChan: responseChan, + } + c.sendPost(&request) + return responseChan +} + +// Marshall's bulk requests and sends to the server +// creates a response channel to receive the response +func (c *Client) Send() error { + // if batchlist is empty, there's nothing to send + if c.batchList.Len() == 0 { + return nil + } + + // clear batchlist in case of an error + defer func() { + c.batchList = list.New() + }() + + result, err := c.sendAsync().Receive() + + if err != nil { + return err + } + + for iter := c.batchList.Front(); iter != nil; iter = iter.Next() { + var requestError error + request := iter.Value.(*jsonRequest) + individualResult := result[request.id] + fullResult, err := json.Marshal(individualResult.Result) + if err != nil { + return err + } + + if individualResult.Error != nil { + requestError = individualResult.Error + } + + result := response{ + result: fullResult, + err: requestError, + } + request.responseChan <- &result + } + return nil +} diff --git a/rpcclient/rawrequest.go b/rpcclient/rawrequest.go index dd16fd049e..baead8bb90 100644 --- a/rpcclient/rawrequest.go +++ b/rpcclient/rawrequest.go @@ -44,7 +44,7 @@ func (c *Client) RawRequestAsync(method string, params []json.RawMessage) Future // than custom commands. id := c.NextID() rawRequest := &btcjson.Request{ - Jsonrpc: "1.0", + Jsonrpc: btcjson.RpcVersion1, ID: id, Method: method, Params: params, diff --git a/rpcserver.go b/rpcserver.go index f159f2397f..8e351bd27c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -101,6 +101,9 @@ var ( // declared here to avoid the overhead of creating the slice on every // invocation for constant data. gbtCapabilities = []string{"proposal"} + + // JSON 2.0 batched request prefix + batchedRequestPrefix = []byte("[") ) // Errors @@ -3939,10 +3942,11 @@ func (s *rpcServer) checkAuth(r *http.Request, require bool) (bool, bool, error) // a known concrete command along with any error that might have happened while // parsing it. type parsedRPCCmd struct { - id interface{} - method string - cmd interface{} - err *btcjson.RPCError + jsonrpc btcjson.RPCVersion + id interface{} + method string + cmd interface{} + err *btcjson.RPCError } // standardCmdResult checks that a parsed command is a standard Bitcoin JSON-RPC @@ -3975,9 +3979,11 @@ handled: // is suitable for use in replies if the command is invalid in some way such as // an unregistered command or invalid parameters. func parseCmd(request *btcjson.Request) *parsedRPCCmd { - var parsedCmd parsedRPCCmd - parsedCmd.id = request.ID - parsedCmd.method = request.Method + parsedCmd := parsedRPCCmd{ + jsonrpc: request.Jsonrpc, + id: request.ID, + method: request.Method, + } cmd, err := btcjson.UnmarshalCmd(request) if err != nil { @@ -4004,7 +4010,7 @@ func parseCmd(request *btcjson.Request) *parsedRPCCmd { // createMarshalledReply returns a new marshalled JSON-RPC response given the // passed parameters. It will automatically convert errors that are not of // the type *btcjson.RPCError to the appropriate type as needed. -func createMarshalledReply(id, result interface{}, replyErr error) ([]byte, error) { +func createMarshalledReply(rpcVersion btcjson.RPCVersion, id interface{}, result interface{}, replyErr error) ([]byte, error) { var jsonErr *btcjson.RPCError if replyErr != nil { if jErr, ok := replyErr.(*btcjson.RPCError); ok { @@ -4014,7 +4020,67 @@ func createMarshalledReply(id, result interface{}, replyErr error) ([]byte, erro } } - return btcjson.MarshalResponse(id, result, jsonErr) + return btcjson.MarshalResponse(rpcVersion, id, result, jsonErr) +} + +// processRequest determines the incoming request type (single or batched), +// parses it and returns a marshalled response. +func (s *rpcServer) processRequest(request *btcjson.Request, isAdmin bool, closeChan <-chan struct{}) []byte { + var result interface{} + var err error + var jsonErr *btcjson.RPCError + + if !isAdmin { + if _, ok := rpcLimited[request.Method]; !ok { + jsonErr = internalRPCError("limited user not "+ + "authorized for this method", "") + } + } + + if jsonErr == nil { + if request.Method == "" || request.Params == nil { + jsonErr = &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: "Invalid request: malformed", + } + msg, err := createMarshalledReply(request.Jsonrpc, request.ID, result, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + return nil + } + return msg + } + + // Valid requests with no ID (notifications) must not have a response + // per the JSON-RPC spec. + if request.ID == nil { + return nil + } + + // Attempt to parse the JSON-RPC request into a known + // concrete command. + parsedCmd := parseCmd(request) + if parsedCmd.err != nil { + jsonErr = parsedCmd.err + } else { + result, err = s.standardCmdResult(parsedCmd, + closeChan) + if err != nil { + jsonErr = &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: "Invalid request: malformed", + } + } + } + } + + // Marshal the response. + msg, err := createMarshalledReply(request.Jsonrpc, request.ID, result, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + return nil + } + return msg } // jsonRPCRead handles reading and responding to RPC messages. @@ -4059,80 +4125,186 @@ func (s *rpcServer) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin conn.SetReadDeadline(timeZeroVal) // Attempt to parse the raw body into a JSON-RPC request. - var responseID interface{} - var jsonErr error - var result interface{} - var request btcjson.Request - if err := json.Unmarshal(body, &request); err != nil { - jsonErr = &btcjson.RPCError{ - Code: btcjson.ErrRPCParse.Code, - Message: "Failed to parse request: " + err.Error(), + // Setup a close notifier. Since the connection is hijacked, + // the CloseNotifer on the ResponseWriter is not available. + closeChan := make(chan struct{}, 1) + go func() { + _, err = conn.Read(make([]byte, 1)) + if err != nil { + close(closeChan) } + }() + + var results []json.RawMessage + var batchSize int + var batchedRequest bool + + // Determine request type + if bytes.HasPrefix(body, batchedRequestPrefix) { + batchedRequest = true } - if jsonErr == nil { - // The JSON-RPC 1.0 spec defines that notifications must have their "id" - // set to null and states that notifications do not have a response. - // - // A JSON-RPC 2.0 notification is a request with "json-rpc":"2.0", and - // without an "id" member. The specification states that notifications - // must not be responded to. JSON-RPC 2.0 permits the null value as a - // valid request id, therefore such requests are not notifications. - // - // Bitcoin Core serves requests with "id":null or even an absent "id", - // and responds to such requests with "id":null in the response. - // - // Btcd does not respond to any request without and "id" or "id":null, - // regardless the indicated JSON-RPC protocol version unless RPC quirks - // are enabled. With RPC quirks enabled, such requests will be responded - // to if the reqeust does not indicate JSON-RPC version. - // - // RPC quirks can be enabled by the user to avoid compatibility issues - // with software relying on Core's behavior. - if request.ID == nil && !(cfg.RPCQuirks && request.Jsonrpc == "") { - return + + // Process a single request + if !batchedRequest { + var req btcjson.Request + var resp json.RawMessage + err = json.Unmarshal(body, &req) + if err != nil { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCParse.Code, + Message: fmt.Sprintf("Failed to parse request: %v", + err), + } + resp, err = btcjson.MarshalResponse(btcjson.RpcVersion1, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to create reply: %v", err) + } } - // The parse was at least successful enough to have an ID so - // set it for the response. - responseID = request.ID + if err == nil { + // The JSON-RPC 1.0 spec defines that notifications must have their "id" + // set to null and states that notifications do not have a response. + // + // A JSON-RPC 2.0 notification is a request with "json-rpc":"2.0", and + // without an "id" member. The specification states that notifications + // must not be responded to. JSON-RPC 2.0 permits the null value as a + // valid request id, therefore such requests are not notifications. + // + // Bitcoin Core serves requests with "id":null or even an absent "id", + // and responds to such requests with "id":null in the response. + // + // Btcd does not respond to any request without and "id" or "id":null, + // regardless the indicated JSON-RPC protocol version unless RPC quirks + // are enabled. With RPC quirks enabled, such requests will be responded + // to if the reqeust does not indicate JSON-RPC version. + // + // RPC quirks can be enabled by the user to avoid compatibility issues + // with software relying on Core's behavior. + if req.ID == nil && !(cfg.RPCQuirks && req.Jsonrpc == "") { + return + } + resp = s.processRequest(&req, isAdmin, closeChan) + } - // Setup a close notifier. Since the connection is hijacked, - // the CloseNotifer on the ResponseWriter is not available. - closeChan := make(chan struct{}, 1) - go func() { - _, err := conn.Read(make([]byte, 1)) + if resp != nil { + results = append(results, resp) + } + } + + // Process a batched request + if batchedRequest { + var batchedRequests []interface{} + var resp json.RawMessage + err = json.Unmarshal(body, &batchedRequests) + if err != nil { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCParse.Code, + Message: fmt.Sprintf("Failed to parse request: %v", + err), + } + resp, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) if err != nil { - close(closeChan) + rpcsLog.Errorf("Failed to create reply: %v", err) } - }() - // Check if the user is limited and set error if method unauthorized - if !isAdmin { - if _, ok := rpcLimited[request.Method]; !ok { - jsonErr = &btcjson.RPCError{ - Code: btcjson.ErrRPCInvalidParams.Code, - Message: "limited user not authorized for this method", + if resp != nil { + results = append(results, resp) + } + } + + if err == nil { + // Response with an empty batch error if the batch size is zero + if len(batchedRequests) == 0 { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: "Invalid request: empty batch", + } + resp, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + } + + if resp != nil { + results = append(results, resp) + } + } + + // Process each batch entry individually + if len(batchedRequests) > 0 { + batchSize = len(batchedRequests) + + for _, entry := range batchedRequests { + var reqBytes []byte + reqBytes, err = json.Marshal(entry) + if err != nil { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: fmt.Sprintf("Invalid request: %v", + err), + } + resp, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to create reply: %v", err) + } + + if resp != nil { + results = append(results, resp) + } + continue + } + + var req btcjson.Request + err := json.Unmarshal(reqBytes, &req) + if err != nil { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: fmt.Sprintf("Invalid request: %v", + err), + } + resp, err = btcjson.MarshalResponse("", nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to create reply: %v", err) + } + + if resp != nil { + results = append(results, resp) + } + continue + } + + resp = s.processRequest(&req, isAdmin, closeChan) + if resp != nil { + results = append(results, resp) + } } } } + } - if jsonErr == nil { - // Attempt to parse the JSON-RPC request into a known concrete - // command. - parsedCmd := parseCmd(&request) - if parsedCmd.err != nil { - jsonErr = parsedCmd.err - } else { - result, jsonErr = s.standardCmdResult(parsedCmd, closeChan) + var msg = []byte{} + if batchedRequest && batchSize > 0 { + if len(results) > 0 { + // Form the batched response json + var buffer bytes.Buffer + buffer.WriteByte('[') + for idx, reply := range results { + if idx == len(results)-1 { + buffer.Write(reply) + buffer.WriteByte(']') + break + } + buffer.Write(reply) + buffer.WriteByte(',') } + msg = buffer.Bytes() } } - // Marshal the response. - msg, err := createMarshalledReply(responseID, result, jsonErr) - if err != nil { - rpcsLog.Errorf("Failed to marshal reply: %v", err) - return + if !batchedRequest || batchSize == 0 { + // Respond with the first results entry for single requests + if len(results) > 0 { + msg = results[0] + } } // Write the response. diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 32e466d115..356a897455 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -695,7 +695,7 @@ func (*wsNotificationManager) notifyBlockConnected(clients map[chan struct{}]*ws // Notify interested websocket clients about the connected block. ntfn := btcjson.NewBlockConnectedNtfn(block.Hash().String(), block.Height(), block.MsgBlock().Header.Timestamp.Unix()) - marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) if err != nil { rpcsLog.Errorf("Failed to marshal block connected notification: "+ "%v", err) @@ -719,7 +719,7 @@ func (*wsNotificationManager) notifyBlockDisconnected(clients map[chan struct{}] // Notify interested websocket clients about the disconnected block. ntfn := btcjson.NewBlockDisconnectedNtfn(block.Hash().String(), block.Height(), block.MsgBlock().Header.Timestamp.Unix()) - marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) if err != nil { rpcsLog.Errorf("Failed to marshal block disconnected "+ "notification: %v", err) @@ -765,7 +765,7 @@ func (m *wsNotificationManager) notifyFilteredBlockConnected(clients map[chan st ntfn.SubscribedTxs = subscribedTxs[quitChan] // Marshal and queue notification. - marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) if err != nil { rpcsLog.Errorf("Failed to marshal filtered block "+ "connected notification: %v", err) @@ -796,7 +796,7 @@ func (*wsNotificationManager) notifyFilteredBlockDisconnected(clients map[chan s } ntfn := btcjson.NewFilteredBlockDisconnectedNtfn(block.Height(), hex.EncodeToString(w.Bytes())) - marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) if err != nil { rpcsLog.Errorf("Failed to marshal filtered block disconnected "+ "notification: %v", err) @@ -831,7 +831,7 @@ func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClie } ntfn := btcjson.NewTxAcceptedNtfn(txHashStr, btcutil.Amount(amount).ToBTC()) - marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) if err != nil { rpcsLog.Errorf("Failed to marshal tx notification: %s", err.Error()) return @@ -854,7 +854,7 @@ func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClie } verboseNtfn = btcjson.NewTxAcceptedVerboseNtfn(*rawTx) - marshalledJSONVerbose, err = btcjson.MarshalCmd(nil, + marshalledJSONVerbose, err = btcjson.MarshalCmd(btcjson.RpcVersion1, nil, verboseNtfn) if err != nil { rpcsLog.Errorf("Failed to marshal verbose tx "+ @@ -980,7 +980,7 @@ func blockDetails(block *btcutil.Block, txIndex int) *btcjson.BlockDetails { func newRedeemingTxNotification(txHex string, index int, block *btcutil.Block) ([]byte, error) { // Create and marshal the notification. ntfn := btcjson.NewRedeemingTxNtfn(txHex, blockDetails(block, index)) - return btcjson.MarshalCmd(nil, ntfn) + return btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) } // notifyForTxOuts examines each transaction output, notifying interested @@ -1016,7 +1016,7 @@ func (m *wsNotificationManager) notifyForTxOuts(ops map[wire.OutPoint]map[chan s ntfn := btcjson.NewRecvTxNtfn(txHex, blockDetails(block, tx.Index())) - marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) if err != nil { rpcsLog.Errorf("Failed to marshal processedtx notification: %v", err) continue @@ -1047,7 +1047,7 @@ func (m *wsNotificationManager) notifyRelevantTxAccepted(tx *btcutil.Tx, if len(clientsToNotify) != 0 { n := btcjson.NewRelevantTxAcceptedNtfn(txHexString(tx.MsgTx())) - marshalled, err := btcjson.MarshalCmd(nil, n) + marshalled, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, n) if err != nil { rpcsLog.Errorf("Failed to marshal notification: %v", err) return @@ -1323,153 +1323,435 @@ out: break out } - var request btcjson.Request - err = json.Unmarshal(msg, &request) - if err != nil { - if !c.authenticated { - break out - } + var batchedRequest bool - jsonErr := &btcjson.RPCError{ - Code: btcjson.ErrRPCParse.Code, - Message: "Failed to parse request: " + err.Error(), - } - reply, err := createMarshalledReply(nil, nil, jsonErr) - if err != nil { - rpcsLog.Errorf("Failed to marshal parse failure "+ - "reply: %v", err) - continue - } - c.SendMessage(reply, nil) - continue + // Determine request type + if bytes.HasPrefix(msg, batchedRequestPrefix) { + batchedRequest = true } - // The JSON-RPC 1.0 spec defines that notifications must have their "id" - // set to null and states that notifications do not have a response. - // - // A JSON-RPC 2.0 notification is a request with "json-rpc":"2.0", and - // without an "id" member. The specification states that notifications - // must not be responded to. JSON-RPC 2.0 permits the null value as a - // valid request id, therefore such requests are not notifications. - // - // Bitcoin Core serves requests with "id":null or even an absent "id", - // and responds to such requests with "id":null in the response. - // - // Btcd does not respond to any request without and "id" or "id":null, - // regardless the indicated JSON-RPC protocol version unless RPC quirks - // are enabled. With RPC quirks enabled, such requests will be responded - // to if the reqeust does not indicate JSON-RPC version. - // - // RPC quirks can be enabled by the user to avoid compatibility issues - // with software relying on Core's behavior. - if request.ID == nil && !(cfg.RPCQuirks && request.Jsonrpc == "") { - if !c.authenticated { - break out - } - continue - } + if !batchedRequest { + var req btcjson.Request + var reply json.RawMessage + err = json.Unmarshal(msg, &req) + if err != nil { + // only process requests from authenticated clients + if !c.authenticated { + break out + } - cmd := parseCmd(&request) - if cmd.err != nil { - if !c.authenticated { - break out + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCParse.Code, + Message: "Failed to parse request: " + err.Error(), + } + reply, err = createMarshalledReply(btcjson.RpcVersion1, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + continue + } + c.SendMessage(reply, nil) + continue } - reply, err := createMarshalledReply(cmd.id, nil, cmd.err) - if err != nil { - rpcsLog.Errorf("Failed to marshal parse failure "+ - "reply: %v", err) + if req.Method == "" || req.Params == nil { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: "Invalid request: malformed", + } + reply, err := createMarshalledReply(req.Jsonrpc, req.ID, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + continue + } + c.SendMessage(reply, nil) continue } - c.SendMessage(reply, nil) - continue - } - rpcsLog.Debugf("Received command <%s> from %s", cmd.method, c.addr) - - // Check auth. The client is immediately disconnected if the - // first request of an unauthentiated websocket client is not - // the authenticate request, an authenticate request is received - // when the client is already authenticated, or incorrect - // authentication credentials are provided in the request. - switch authCmd, ok := cmd.cmd.(*btcjson.AuthenticateCmd); { - case c.authenticated && ok: - rpcsLog.Warnf("Websocket client %s is already authenticated", - c.addr) - break out - case !c.authenticated && !ok: - rpcsLog.Warnf("Unauthenticated websocket message " + - "received") - break out - case !c.authenticated: - // Check credentials. - login := authCmd.Username + ":" + authCmd.Passphrase - auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login)) - authSha := sha256.Sum256([]byte(auth)) - cmp := subtle.ConstantTimeCompare(authSha[:], c.server.authsha[:]) - limitcmp := subtle.ConstantTimeCompare(authSha[:], c.server.limitauthsha[:]) - if cmp != 1 && limitcmp != 1 { - rpcsLog.Warnf("Auth failure.") - break out + + // Valid requests with no ID (notifications) must not have a response + // per the JSON-RPC spec. + if req.ID == nil { + if !c.authenticated { + break out + } + continue } - c.authenticated = true - c.isAdmin = cmp == 1 - // Marshal and send response. - reply, err := createMarshalledReply(cmd.id, nil, nil) - if err != nil { - rpcsLog.Errorf("Failed to marshal authenticate reply: "+ - "%v", err.Error()) + cmd := parseCmd(&req) + if cmd.err != nil { + // Only process requests from authenticated clients + if !c.authenticated { + break out + } + + reply, err = createMarshalledReply(cmd.jsonrpc, cmd.id, nil, cmd.err) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + continue + } + c.SendMessage(reply, nil) continue } - c.SendMessage(reply, nil) - continue - } - // Check if the client is using limited RPC credentials and - // error when not authorized to call this RPC. - if !c.isAdmin { - if _, ok := rpcLimited[request.Method]; !ok { - jsonErr := &btcjson.RPCError{ - Code: btcjson.ErrRPCInvalidParams.Code, - Message: "limited user not authorized for this method", + rpcsLog.Debugf("Received command <%s> from %s", cmd.method, c.addr) + + // Check auth. The client is immediately disconnected if the + // first request of an unauthentiated websocket client is not + // the authenticate request, an authenticate request is received + // when the client is already authenticated, or incorrect + // authentication credentials are provided in the request. + switch authCmd, ok := cmd.cmd.(*btcjson.AuthenticateCmd); { + case c.authenticated && ok: + rpcsLog.Warnf("Websocket client %s is already authenticated", + c.addr) + break out + case !c.authenticated && !ok: + rpcsLog.Warnf("Unauthenticated websocket message " + + "received") + break out + case !c.authenticated: + // Check credentials. + login := authCmd.Username + ":" + authCmd.Passphrase + auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login)) + authSha := sha256.Sum256([]byte(auth)) + cmp := subtle.ConstantTimeCompare(authSha[:], c.server.authsha[:]) + limitcmp := subtle.ConstantTimeCompare(authSha[:], c.server.limitauthsha[:]) + if cmp != 1 && limitcmp != 1 { + rpcsLog.Warnf("Auth failure.") + break out } + c.authenticated = true + c.isAdmin = cmp == 1 + // Marshal and send response. - reply, err := createMarshalledReply(request.ID, nil, jsonErr) + reply, err = createMarshalledReply(cmd.jsonrpc, cmd.id, nil, nil) if err != nil { - rpcsLog.Errorf("Failed to marshal parse failure "+ - "reply: %v", err) + rpcsLog.Errorf("Failed to marshal authenticate reply: "+ + "%v", err.Error()) continue } c.SendMessage(reply, nil) continue } + + // Check if the client is using limited RPC credentials and + // error when not authorized to call the supplied RPC. + if !c.isAdmin { + if _, ok := rpcLimited[req.Method]; !ok { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidParams.Code, + Message: "limited user not authorized for this method", + } + // Marshal and send response. + reply, err = createMarshalledReply("", req.ID, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal parse failure "+ + "reply: %v", err) + continue + } + c.SendMessage(reply, nil) + continue + } + } + + // Asynchronously handle the request. A semaphore is used to + // limit the number of concurrent requests currently being + // serviced. If the semaphore can not be acquired, simply wait + // until a request finished before reading the next RPC request + // from the websocket client. + // + // This could be a little fancier by timing out and erroring + // when it takes too long to service the request, but if that is + // done, the read of the next request should not be blocked by + // this semaphore, otherwise the next request will be read and + // will probably sit here for another few seconds before timing + // out as well. This will cause the total timeout duration for + // later requests to be much longer than the check here would + // imply. + // + // If a timeout is added, the semaphore acquiring should be + // moved inside of the new goroutine with a select statement + // that also reads a time.After channel. This will unblock the + // read of the next request from the websocket client and allow + // many requests to be waited on concurrently. + c.serviceRequestSem.acquire() + go func() { + c.serviceRequest(cmd) + c.serviceRequestSem.release() + }() } - // Asynchronously handle the request. A semaphore is used to - // limit the number of concurrent requests currently being - // serviced. If the semaphore can not be acquired, simply wait - // until a request finished before reading the next RPC request - // from the websocket client. - // - // This could be a little fancier by timing out and erroring - // when it takes too long to service the request, but if that is - // done, the read of the next request should not be blocked by - // this semaphore, otherwise the next request will be read and - // will probably sit here for another few seconds before timing - // out as well. This will cause the total timeout duration for - // later requests to be much longer than the check here would - // imply. - // - // If a timeout is added, the semaphore acquiring should be - // moved inside of the new goroutine with a select statement - // that also reads a time.After channel. This will unblock the - // read of the next request from the websocket client and allow - // many requests to be waited on concurrently. - c.serviceRequestSem.acquire() - go func() { - c.serviceRequest(cmd) + // Process a batched request + if batchedRequest { + var batchedRequests []interface{} + var results []json.RawMessage + var batchSize int + var reply json.RawMessage + c.serviceRequestSem.acquire() + err = json.Unmarshal(msg, &batchedRequests) + if err != nil { + // Only process requests from authenticated clients + if !c.authenticated { + break out + } + + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCParse.Code, + Message: fmt.Sprintf("Failed to parse request: %v", + err), + } + reply, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to create reply: %v", err) + } + + if reply != nil { + results = append(results, reply) + } + } + + if err == nil { + // Response with an empty batch error if the batch size is zero + if len(batchedRequests) == 0 { + if !c.authenticated { + break out + } + + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: "Invalid request: empty batch", + } + reply, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + } + + if reply != nil { + results = append(results, reply) + } + } + + // Process each batch entry individually + if len(batchedRequests) > 0 { + batchSize = len(batchedRequests) + for _, entry := range batchedRequests { + var reqBytes []byte + reqBytes, err = json.Marshal(entry) + if err != nil { + // Only process requests from authenticated clients + if !c.authenticated { + break out + } + + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: fmt.Sprintf("Invalid request: %v", + err), + } + reply, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to create reply: %v", err) + continue + } + + if reply != nil { + results = append(results, reply) + } + continue + } + + var req btcjson.Request + err := json.Unmarshal(reqBytes, &req) + if err != nil { + // Only process requests from authenticated clients + if !c.authenticated { + break out + } + + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: fmt.Sprintf("Invalid request: %v", + err), + } + reply, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to create reply: %v", err) + continue + } + + if reply != nil { + results = append(results, reply) + } + continue + } + + if req.Method == "" || req.Params == nil { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: "Invalid request: malformed", + } + reply, err := createMarshalledReply(req.Jsonrpc, req.ID, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + continue + } + + if reply != nil { + results = append(results, reply) + } + continue + } + + // Valid requests with no ID (notifications) must not have a response + // per the JSON-RPC spec. + if req.ID == nil { + if !c.authenticated { + break out + } + continue + } + + cmd := parseCmd(&req) + if cmd.err != nil { + // Only process requests from authenticated clients + if !c.authenticated { + break out + } + + reply, err = createMarshalledReply(cmd.jsonrpc, cmd.id, nil, cmd.err) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply: %v", err) + continue + } + + if reply != nil { + results = append(results, reply) + } + continue + } + + rpcsLog.Debugf("Received command <%s> from %s", cmd.method, c.addr) + + // Check auth. The client is immediately disconnected if the + // first request of an unauthentiated websocket client is not + // the authenticate request, an authenticate request is received + // when the client is already authenticated, or incorrect + // authentication credentials are provided in the request. + switch authCmd, ok := cmd.cmd.(*btcjson.AuthenticateCmd); { + case c.authenticated && ok: + rpcsLog.Warnf("Websocket client %s is already authenticated", + c.addr) + break out + case !c.authenticated && !ok: + rpcsLog.Warnf("Unauthenticated websocket message " + + "received") + break out + case !c.authenticated: + // Check credentials. + login := authCmd.Username + ":" + authCmd.Passphrase + auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login)) + authSha := sha256.Sum256([]byte(auth)) + cmp := subtle.ConstantTimeCompare(authSha[:], c.server.authsha[:]) + limitcmp := subtle.ConstantTimeCompare(authSha[:], c.server.limitauthsha[:]) + if cmp != 1 && limitcmp != 1 { + rpcsLog.Warnf("Auth failure.") + break out + } + + c.authenticated = true + c.isAdmin = cmp == 1 + + // Marshal and send response. + reply, err = createMarshalledReply(cmd.jsonrpc, cmd.id, nil, nil) + if err != nil { + rpcsLog.Errorf("Failed to marshal authenticate reply: "+ + "%v", err.Error()) + continue + } + + if reply != nil { + results = append(results, reply) + } + continue + } + + // Check if the client is using limited RPC credentials and + // error when not authorized to call the supplied RPC. + if !c.isAdmin { + if _, ok := rpcLimited[req.Method]; !ok { + jsonErr := &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidParams.Code, + Message: "limited user not authorized for this method", + } + // Marshal and send response. + reply, err = createMarshalledReply(req.Jsonrpc, req.ID, nil, jsonErr) + if err != nil { + rpcsLog.Errorf("Failed to marshal parse failure "+ + "reply: %v", err) + continue + } + + if reply != nil { + results = append(results, reply) + } + continue + } + } + + // Lookup the websocket extension for the command, if it doesn't + // exist fallback to handling the command as a standard command. + var resp interface{} + wsHandler, ok := wsHandlers[cmd.method] + if ok { + resp, err = wsHandler(c, cmd.cmd) + } else { + resp, err = c.server.standardCmdResult(cmd, nil) + } + + // Marshal request output. + reply, err := createMarshalledReply(cmd.jsonrpc, cmd.id, resp, err) + if err != nil { + rpcsLog.Errorf("Failed to marshal reply for <%s> "+ + "command: %v", cmd.method, err) + return + } + + if reply != nil { + results = append(results, reply) + } + } + } + } + + // generate reply + var payload = []byte{} + if batchedRequest && batchSize > 0 { + if len(results) > 0 { + // Form the batched response json + var buffer bytes.Buffer + buffer.WriteByte('[') + for idx, marshalledReply := range results { + if idx == len(results)-1 { + buffer.Write(marshalledReply) + buffer.WriteByte(']') + break + } + buffer.Write(marshalledReply) + buffer.WriteByte(',') + } + payload = buffer.Bytes() + } + } + + if !batchedRequest || batchSize == 0 { + // Respond with the first results entry for single requests + if len(results) > 0 { + payload = results[0] + } + } + + c.SendMessage(payload, nil) c.serviceRequestSem.release() - }() + } } // Ensure the connection is closed. @@ -1495,7 +1777,7 @@ func (c *wsClient) serviceRequest(r *parsedRPCCmd) { } else { result, err = c.server.standardCmdResult(r, nil) } - reply, err := createMarshalledReply(r.id, result, err) + reply, err := createMarshalledReply(r.jsonrpc, r.id, result, err) if err != nil { rpcsLog.Errorf("Failed to marshal reply for <%s> "+ "command: %v", r.method, err) @@ -2125,7 +2407,7 @@ func rescanBlock(wsc *wsClient, lookups *rescanKeys, blk *btcutil.Block) { ntfn := btcjson.NewRecvTxNtfn(txHex, blockDetails(blk, tx.Index())) - marshalledJSON, err := btcjson.MarshalCmd(nil, ntfn) + marshalledJSON, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, ntfn) if err != nil { rpcsLog.Errorf("Failed to marshal recvtx notification: %v", err) return @@ -2492,7 +2774,7 @@ fetchRange: hashList[i].String(), blk.Height(), blk.MsgBlock().Header.Timestamp.Unix(), ) - mn, err := btcjson.MarshalCmd(nil, n) + mn, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, n) if err != nil { rpcsLog.Errorf("Failed to marshal rescan "+ "progress notification: %v", err) @@ -2637,7 +2919,7 @@ func handleRescan(wsc *wsClient, icmd interface{}) (interface{}, error) { lastBlockHash.String(), lastBlock.Height(), lastBlock.MsgBlock().Header.Timestamp.Unix(), ) - if mn, err := btcjson.MarshalCmd(nil, n); err != nil { + if mn, err := btcjson.MarshalCmd(btcjson.RpcVersion1, nil, n); err != nil { rpcsLog.Errorf("Failed to marshal rescan finished "+ "notification: %v", err) } else { From dff2198fc543e7ae86f25bbf63193024fde7f5b1 Mon Sep 17 00:00:00 2001 From: Appelberg-s Date: Mon, 11 Jan 2021 19:39:22 +0100 Subject: [PATCH 0431/1056] Fix error message returned by EstimateFee When you provide an argument to EstimateFee(numblocks uint32) that exceeds the estimateFeeDepth (which is set to 25), you get an error message that says "can only estimate fees for up to 100 blocks from now". The variable used in the if condition and the variable used for creating the error message should be the same. --- mempool/estimatefee.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index 3546f6b356..55fe4810df 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -563,7 +563,7 @@ func (ef *FeeEstimator) EstimateFee(numBlocks uint32) (BtcPerKilobyte, error) { if numBlocks > estimateFeeDepth { return -1, fmt.Errorf( "can only estimate fees for up to %d blocks from now", - estimateFeeBinSize) + estimateFeeDepth) } // If there are no cached results, generate them. From d08785547a8744481774e72782d26cb34f84d532 Mon Sep 17 00:00:00 2001 From: Jake Sylvestre Date: Thu, 4 Mar 2021 17:12:45 -0500 Subject: [PATCH 0432/1056] docs: update shields --- README.md | 2 +- blockchain/README.md | 10 +++++----- blockchain/fullblocktests/README.md | 4 ++-- blockchain/indexers/README.md | 4 ++-- btcec/README.md | 12 ++++++------ btcjson/README.md | 12 ++++++------ chaincfg/README.md | 4 ++-- chaincfg/chainhash/README.md | 4 ++-- connmgr/README.md | 4 ++-- database/README.md | 8 ++++---- database/ffldb/README.md | 4 ++-- database/internal/treap/README.md | 4 ++-- docs/code_contribution_guidelines.md | 2 +- docs/configuration.md | 2 +- docs/index.md | 4 ++-- integration/README.md | 2 +- integration/rpctest/README.md | 4 ++-- mempool/README.md | 4 ++-- mining/README.md | 4 ++-- mining/cpuminer/README.md | 4 ++-- netsync/README.md | 4 ++-- peer/README.md | 6 +++--- peer/doc.go | 2 +- rpcclient/README.md | 6 +++--- txscript/README.md | 10 +++++----- wire/README.md | 4 ++-- 26 files changed, 65 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 3e91cda3d4..62fa223aae 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ btcd [![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![Coverage Status](https://coveralls.io/repos/github/btcsuite/btcd/badge.svg?branch=master)](https://coveralls.io/github/btcsuite/btcd?branch=master) [![ISC License](https://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/btcsuite/btcd) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd) btcd is an alternative full node bitcoin implementation written in Go (golang). diff --git a/blockchain/README.md b/blockchain/README.md index de5611bcae..2237780c10 100644 --- a/blockchain/README.md +++ b/blockchain/README.md @@ -1,9 +1,9 @@ blockchain ========== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/blockchain) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain) Package blockchain implements bitcoin block handling and chain selection rules. The test coverage is currently only around 60%, but will be increasing over @@ -61,18 +61,18 @@ is by no means exhaustive: ## Examples -* [ProcessBlock Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-BlockChain-ProcessBlock) +* [ProcessBlock Example](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain#example-BlockChain-ProcessBlock) Demonstrates how to create a new chain instance and use ProcessBlock to attempt to add a block to the chain. This example intentionally attempts to insert a duplicate genesis block to illustrate how an invalid block is handled. -* [CompactToBig Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-CompactToBig) +* [CompactToBig Example](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain#example-CompactToBig) Demonstrates how to convert the compact "bits" in a block header which represent the target difficulty to a big integer and display it using the typical hex notation. -* [BigToCompact Example](http://godoc.org/github.com/btcsuite/btcd/blockchain#example-BigToCompact) +* [BigToCompact Example](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain#example-BigToCompact) Demonstrates how to convert a target difficulty into the compact "bits" in a block header which represent that target difficulty. diff --git a/blockchain/fullblocktests/README.md b/blockchain/fullblocktests/README.md index 41f4b934e9..943989be35 100644 --- a/blockchain/fullblocktests/README.md +++ b/blockchain/fullblocktests/README.md @@ -1,9 +1,9 @@ fullblocktests ============== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/blockchain/fullblocktests) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain/fullblocktests) Package fullblocktests provides a set of full block tests to be used for testing the consensus validation rules. The tests are intended to be flexible enough to diff --git a/blockchain/indexers/README.md b/blockchain/indexers/README.md index 20a721f3f2..f48491520a 100644 --- a/blockchain/indexers/README.md +++ b/blockchain/indexers/README.md @@ -1,9 +1,9 @@ indexers ======== -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/blockchain/indexers?status.png)](http://godoc.org/github.com/btcsuite/btcd/blockchain/indexers) +[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain/indexers?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain/indexers) Package indexers implements optional block chain indexes. diff --git a/btcec/README.md b/btcec/README.md index 130bd200a0..a6dd2cf285 100644 --- a/btcec/README.md +++ b/btcec/README.md @@ -1,9 +1,9 @@ btcec ===== -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcec) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/btcec?status.png)](http://godoc.org/github.com/btcsuite/btcd/btcec) +[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/btcec?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/btcec) Package btcec implements elliptic curve cryptography needed for working with Bitcoin (secp256k1 only for now). It is designed so that it may be used with the @@ -25,19 +25,19 @@ $ go get -u github.com/btcsuite/btcd/btcec ## Examples -* [Sign Message](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--SignMessage) +* [Sign Message](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--SignMessage) Demonstrates signing a message with a secp256k1 private key that is first parsed form raw bytes and serializing the generated signature. -* [Verify Signature](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--VerifySignature) +* [Verify Signature](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--VerifySignature) Demonstrates verifying a secp256k1 signature against a public key that is first parsed from raw bytes. The signature is also parsed from raw bytes. -* [Encryption](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--EncryptMessage) +* [Encryption](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--EncryptMessage) Demonstrates encrypting a message for a public key that is first parsed from raw bytes, then decrypting it using the corresponding private key. -* [Decryption](http://godoc.org/github.com/btcsuite/btcd/btcec#example-package--DecryptMessage) +* [Decryption](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--DecryptMessage) Demonstrates decrypting a message using a private key that is first parsed from raw bytes. diff --git a/btcjson/README.md b/btcjson/README.md index b643579543..48f322635e 100644 --- a/btcjson/README.md +++ b/btcjson/README.md @@ -1,9 +1,9 @@ btcjson ======= -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/btcjson) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/btcjson) Package btcjson implements concrete types for marshalling to and from the bitcoin JSON-RPC API. A comprehensive suite of tests is provided to ensure @@ -30,17 +30,17 @@ $ go get -u github.com/btcsuite/btcd/btcjson ## Examples -* [Marshal Command](http://godoc.org/github.com/btcsuite/btcd/btcjson#example-MarshalCmd) +* [Marshal Command](https://pkg.go.dev/github.com/btcsuite/btcd/btcjson#example-MarshalCmd) Demonstrates how to create and marshal a command into a JSON-RPC request. -* [Unmarshal Command](http://godoc.org/github.com/btcsuite/btcd/btcjson#example-UnmarshalCmd) +* [Unmarshal Command](https://pkg.go.dev/github.com/btcsuite/btcd/btcjson#example-UnmarshalCmd) Demonstrates how to unmarshal a JSON-RPC request and then unmarshal the concrete request into a concrete command. -* [Marshal Response](http://godoc.org/github.com/btcsuite/btcd/btcjson#example-MarshalResponse) +* [Marshal Response](https://pkg.go.dev/github.com/btcsuite/btcd/btcjson#example-MarshalResponse) Demonstrates how to marshal a JSON-RPC response. -* [Unmarshal Response](http://godoc.org/github.com/btcsuite/btcd/btcjson#example-package--UnmarshalResponse) +* [Unmarshal Response](https://pkg.go.dev/github.com/btcsuite/btcd/btcjson#example-package--UnmarshalResponse) Demonstrates how to unmarshal a JSON-RPC response and then unmarshal the result field in the response to a concrete type. diff --git a/chaincfg/README.md b/chaincfg/README.md index 880446fdc7..72fac2e7dc 100644 --- a/chaincfg/README.md +++ b/chaincfg/README.md @@ -1,9 +1,9 @@ chaincfg ======== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/chaincfg) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/chaincfg) Package chaincfg defines chain configuration parameters for the three standard Bitcoin networks and provides the ability for callers to define their own custom diff --git a/chaincfg/chainhash/README.md b/chaincfg/chainhash/README.md index fc49d9cd93..b7ddf19ef7 100644 --- a/chaincfg/chainhash/README.md +++ b/chaincfg/chainhash/README.md @@ -1,9 +1,9 @@ chainhash ========= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/chaincfg/chainhash) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/chaincfg/chainhash) ======= chainhash provides a generic hash type and associated functions that allows the diff --git a/connmgr/README.md b/connmgr/README.md index 6f3968cecb..b1aa3cc7d0 100644 --- a/connmgr/README.md +++ b/connmgr/README.md @@ -1,9 +1,9 @@ connmgr ======= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/connmgr) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/connmgr) Package connmgr implements a generic Bitcoin network connection manager. diff --git a/database/README.md b/database/README.md index c51c9cc66b..21563d1af8 100644 --- a/database/README.md +++ b/database/README.md @@ -1,9 +1,9 @@ database ======== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/database) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/database) Package database provides a block and metadata storage database. @@ -42,11 +42,11 @@ $ go get -u github.com/btcsuite/btcd/database ## Examples -* [Basic Usage Example](http://godoc.org/github.com/btcsuite/btcd/database#example-package--BasicUsage) +* [Basic Usage Example](https://pkg.go.dev/github.com/btcsuite/btcd/database#example-package--BasicUsage) Demonstrates creating a new database and using a managed read-write transaction to store and retrieve metadata. -* [Block Storage and Retrieval Example](http://godoc.org/github.com/btcsuite/btcd/database#example-package--BlockStorageAndRetrieval) +* [Block Storage and Retrieval Example](https://pkg.go.dev/github.com/btcsuite/btcd/database#example-package--BlockStorageAndRetrieval) Demonstrates creating a new database, using a managed read-write transaction to store a block, and then using a managed read-only transaction to fetch the block. diff --git a/database/ffldb/README.md b/database/ffldb/README.md index ebaa5a7e01..5b855faa55 100644 --- a/database/ffldb/README.md +++ b/database/ffldb/README.md @@ -1,9 +1,9 @@ ffldb ===== -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/database/ffldb?status.png)](http://godoc.org/github.com/btcsuite/btcd/database/ffldb) +[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/database/ffldb?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/database/ffldb) ======= Package ffldb implements a driver for the database package that uses leveldb for diff --git a/database/internal/treap/README.md b/database/internal/treap/README.md index f5314b4a05..14c3159a50 100644 --- a/database/internal/treap/README.md +++ b/database/internal/treap/README.md @@ -1,9 +1,9 @@ treap ===== -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/database/internal/treap?status.png)](http://godoc.org/github.com/btcsuite/btcd/database/internal/treap) +[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/database/internal/treap?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/database/internal/treap) Package treap implements a treap data structure that is used to hold ordered key/value pairs using a combination of binary search tree and heap semantics. diff --git a/docs/code_contribution_guidelines.md b/docs/code_contribution_guidelines.md index a135ad937a..c0a7eecc5f 100644 --- a/docs/code_contribution_guidelines.md +++ b/docs/code_contribution_guidelines.md @@ -111,7 +111,7 @@ A quick summary of test practices follows: - Function comments must always begin with the name of the function per [Effective Go](http://golang.org/doc/effective_go.html) - Function comments should be complete sentences since they allow a wide - variety of automated presentations such as [godoc.org](https://godoc.org) + variety of automated presentations such as [go.dev](https://go.dev) - The general rule of thumb is to look at it as if you were completely unfamiliar with the code and ask yourself, would this give me enough information to understand what this function does and how I'd probably want diff --git a/docs/configuration.md b/docs/configuration.md index 132c07a1df..c6f95b274c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,6 +1,6 @@ # Configuration -btcd has a number of [configuration](http://godoc.org/github.com/btcsuite/btcd) +btcd has a number of [configuration](https://pkg.go.dev/github.com/btcsuite/btcd) options, which can be viewed by running: `$ btcd --help`. ## Peer server listen interface diff --git a/docs/index.md b/docs/index.md index c286d47a51..9d980626d4 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,8 @@ # btcd -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd) btcd is an alternative full node bitcoin implementation written in Go (golang). diff --git a/integration/README.md b/integration/README.md index 52bbf51167..5f6f14eace 100644 --- a/integration/README.md +++ b/integration/README.md @@ -1,7 +1,7 @@ integration =========== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) This contains integration tests which make use of the diff --git a/integration/rpctest/README.md b/integration/rpctest/README.md index fceeed20a0..79f45bc857 100644 --- a/integration/rpctest/README.md +++ b/integration/rpctest/README.md @@ -1,9 +1,9 @@ rpctest ======= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/integration/rpctest) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/integration/rpctest) Package rpctest provides a btcd-specific RPC testing harness crafting and executing integration tests by driving a `btcd` instance via the `RPC` diff --git a/mempool/README.md b/mempool/README.md index d9b8d73b5c..5f1e4a4cd1 100644 --- a/mempool/README.md +++ b/mempool/README.md @@ -1,9 +1,9 @@ mempool ======= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/mempool) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/mempool) Package mempool provides a policy-enforced pool of unmined bitcoin transactions. diff --git a/mining/README.md b/mining/README.md index 5295215f8e..3abd195355 100644 --- a/mining/README.md +++ b/mining/README.md @@ -1,9 +1,9 @@ mining ====== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/mining) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/mining) ## Overview diff --git a/mining/cpuminer/README.md b/mining/cpuminer/README.md index 205b8f0360..47247be98f 100644 --- a/mining/cpuminer/README.md +++ b/mining/cpuminer/README.md @@ -1,9 +1,9 @@ cpuminer ======== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/mining/cpuminer) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/mining/cpuminer) ======= ## Overview diff --git a/netsync/README.md b/netsync/README.md index d5e141151d..a4966815fd 100644 --- a/netsync/README.md +++ b/netsync/README.md @@ -1,9 +1,9 @@ netsync ======= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/netsync) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/netsync) ## Overview diff --git a/peer/README.md b/peer/README.md index 1a0ba36e8d..217f5dc3dc 100644 --- a/peer/README.md +++ b/peer/README.md @@ -1,9 +1,9 @@ peer ==== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/peer) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/peer) Package peer provides a common base for creating and managing bitcoin network peers. @@ -63,7 +63,7 @@ $ go get -u github.com/btcsuite/btcd/peer ## Examples -* [New Outbound Peer Example](https://godoc.org/github.com/btcsuite/btcd/peer#example-package--NewOutboundPeer) +* [New Outbound Peer Example](https://pkg.go.dev/github.com/btcsuite/btcd/peer#example-package--NewOutboundPeer) Demonstrates the basic process for initializing and creating an outbound peer. Peers negotiate by exchanging version and verack messages. For demonstration, a simple handler for the version message is attached to the peer. diff --git a/peer/doc.go b/peer/doc.go index cd822fe1cf..88fae8e850 100644 --- a/peer/doc.go +++ b/peer/doc.go @@ -145,6 +145,6 @@ raw message bytes using a format similar to hexdump -C. Bitcoin Improvement Proposals This package supports all BIPS supported by the wire package. -(https://godoc.org/github.com/btcsuite/btcd/wire#hdr-Bitcoin_Improvement_Proposals) +(https://pkg.go.dev/github.com/btcsuite/btcd/wire#hdr-Bitcoin_Improvement_Proposals) */ package peer diff --git a/rpcclient/README.md b/rpcclient/README.md index 06be0d69e1..08b16f7560 100644 --- a/rpcclient/README.md +++ b/rpcclient/README.md @@ -1,9 +1,9 @@ rpcclient ========= -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/rpcclient) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/rpcclient) rpcclient implements a Websocket-enabled Bitcoin JSON-RPC client package written in [Go](http://golang.org/). It provides a robust and easy to use client for @@ -18,7 +18,7 @@ implement and the API is not stable yet. ## Documentation -* [API Reference](http://godoc.org/github.com/btcsuite/btcd/rpcclient) +* [API Reference](https://pkg.go.dev/github.com/btcsuite/btcd/rpcclient) * [btcd Websockets Example](https://github.com/btcsuite/btcd/tree/master/rpcclient/examples/btcdwebsockets) Connects to a btcd RPC server using TLS-secured websockets, registers for block connected and block disconnected notifications, and gets the current diff --git a/txscript/README.md b/txscript/README.md index 5793173451..004c586d61 100644 --- a/txscript/README.md +++ b/txscript/README.md @@ -1,9 +1,9 @@ txscript ======== -[![Build Status](https://travis-ci.org/btcsuite/btcd.png?branch=master)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/txscript?status.png)](http://godoc.org/github.com/btcsuite/btcd/txscript) +[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/txscript?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/txscript) Package txscript implements the bitcoin transaction script language. There is a comprehensive test suite. @@ -26,15 +26,15 @@ $ go get -u github.com/btcsuite/btcd/txscript ## Examples -* [Standard Pay-to-pubkey-hash Script](http://godoc.org/github.com/btcsuite/btcd/txscript#example-PayToAddrScript) +* [Standard Pay-to-pubkey-hash Script](https://pkg.go.dev/github.com/btcsuite/btcd/txscript#example-PayToAddrScript) Demonstrates creating a script which pays to a bitcoin address. It also prints the created script hex and uses the DisasmString function to display the disassembled script. -* [Extracting Details from Standard Scripts](http://godoc.org/github.com/btcsuite/btcd/txscript#example-ExtractPkScriptAddrs) +* [Extracting Details from Standard Scripts](https://pkg.go.dev/github.com/btcsuite/btcd/txscript#example-ExtractPkScriptAddrs) Demonstrates extracting information from a standard public key script. -* [Manually Signing a Transaction Output](http://godoc.org/github.com/btcsuite/btcd/txscript#example-SignTxOutput) +* [Manually Signing a Transaction Output](https://pkg.go.dev/github.com/btcsuite/btcd/txscript#example-SignTxOutput) Demonstrates manually creating and signing a redeem transaction. ## GPG Verification Key diff --git a/wire/README.md b/wire/README.md index 646bc0a309..8660bbfd54 100644 --- a/wire/README.md +++ b/wire/README.md @@ -1,9 +1,9 @@ wire ==== -[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd) +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/wire) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/wire) ======= Package wire implements the bitcoin wire protocol. A comprehensive suite of From 556620fea68b464f53b25cb1dc2e041e8040653b Mon Sep 17 00:00:00 2001 From: Gustavo Chain Date: Tue, 9 Mar 2021 10:37:31 +0100 Subject: [PATCH 0433/1056] rpcserver: Fix Error message returned by processRequest When processRequest can't find a rpc command, standardCmdResult returns a `btcjson.ErrRPCMethodNotFound` but it gets ignored and a `btcjson.ErrRPCInvalidRequest` is returned instead. This makes processRequest return the right error message. --- rpcserver.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 8e351bd27c..1cd3d69cf4 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4066,9 +4066,13 @@ func (s *rpcServer) processRequest(request *btcjson.Request, isAdmin bool, close result, err = s.standardCmdResult(parsedCmd, closeChan) if err != nil { - jsonErr = &btcjson.RPCError{ - Code: btcjson.ErrRPCInvalidRequest.Code, - Message: "Invalid request: malformed", + if rpcErr, ok := err.(*btcjson.RPCError); ok { + jsonErr = rpcErr + } else { + jsonErr = &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidRequest.Code, + Message: "Invalid request: malformed", + } } } } From fdb479f1213f892fc52a17dde311d5b441a4cbf8 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Thu, 11 Mar 2021 18:24:13 -0800 Subject: [PATCH 0434/1056] peer: allow external testing of peer.Peer The previous use of allowSelfConns prevented this, as users aren't able to invoke peer.TstAllowSelfConns themselves due to being part of a test file, which aren't exported at the library level, leading to a "disconnecting peer connected to self" error upon establishing a mock connection between two peers. By including the option at the config level instead (false by default, prevents connections to self) we enable users of the peer library to properly test the behavior of the peer.Peer struct externally. --- peer/example_test.go | 2 ++ peer/export_test.go | 18 ------------------ peer/peer.go | 12 ++++++------ peer/peer_test.go | 12 +++++++----- 4 files changed, 15 insertions(+), 29 deletions(-) delete mode 100644 peer/export_test.go diff --git a/peer/example_test.go b/peer/example_test.go index cb67683bae..d4662a2b4c 100644 --- a/peer/example_test.go +++ b/peer/example_test.go @@ -25,6 +25,7 @@ func mockRemotePeer() error { UserAgentVersion: "1.0.0", // User agent version to advertise. ChainParams: &chaincfg.SimNetParams, TrickleInterval: time.Second * 10, + AllowSelfConns: true, } // Accept connections on the simnet port. @@ -81,6 +82,7 @@ func Example_newOutboundPeer() { verack <- struct{}{} }, }, + AllowSelfConns: true, } p, err := peer.NewOutboundPeer(peerCfg, "127.0.0.1:18555") if err != nil { diff --git a/peer/export_test.go b/peer/export_test.go deleted file mode 100644 index 06ec78a1a5..0000000000 --- a/peer/export_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -/* -This test file is part of the peer package rather than than the peer_test -package so it can bridge access to the internals to properly test cases which -are either not possible or can't reliably be tested via the public interface. -The functions are only exported while the tests are being run. -*/ - -package peer - -// TstAllowSelfConns allows the test package to allow self connections by -// disabling the detection logic. -func TstAllowSelfConns() { - allowSelfConns = true -} diff --git a/peer/peer.go b/peer/peer.go index 5b083a7467..92ac3d27e8 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -84,11 +84,6 @@ var ( // sentNonces houses the unique nonces that are generated when pushing // version messages that are used to detect self connections. sentNonces = lru.NewCache(50) - - // allowSelfConns is only used to allow the tests to bypass the self - // connection detecting and disconnect logic since they intentionally - // do so for testing purposes. - allowSelfConns bool ) // MessageListeners defines callback function pointers to invoke with message @@ -276,6 +271,11 @@ type Config struct { // TrickleInterval is the duration of the ticker which trickles down the // inventory to a peer. TrickleInterval time.Duration + + // AllowSelfConns is only used to allow the tests to bypass the self + // connection detecting and disconnect logic since they intentionally + // do so for testing purposes. + AllowSelfConns bool } // minUint32 is a helper function to return the minimum of two uint32s. @@ -1896,7 +1896,7 @@ func (p *Peer) readRemoteVersionMsg() error { } // Detect self connections. - if !allowSelfConns && sentNonces.Contains(msg.Nonce) { + if !p.cfg.AllowSelfConns && sentNonces.Contains(msg.Nonce) { return errors.New("disconnecting peer connected to self") } diff --git a/peer/peer_test.go b/peer/peer_test.go index 6cc3113d1e..dd7f36aa3a 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -238,6 +238,7 @@ func TestPeerConnection(t *testing.T) { ProtocolVersion: wire.RejectVersion, // Configure with older version Services: 0, TrickleInterval: time.Second * 10, + AllowSelfConns: true, } peer2Cfg := &peer.Config{ Listeners: peer1Cfg.Listeners, @@ -247,6 +248,7 @@ func TestPeerConnection(t *testing.T) { ChainParams: &chaincfg.MainNetParams, Services: wire.SFNodeNetwork | wire.SFNodeWitness, TrickleInterval: time.Second * 10, + AllowSelfConns: true, } wantStats1 := peerStats{ @@ -452,6 +454,7 @@ func TestPeerListeners(t *testing.T) { ChainParams: &chaincfg.MainNetParams, Services: wire.SFNodeBloom, TrickleInterval: time.Second * 10, + AllowSelfConns: true, } inConn, outConn := pipe( &conn{raddr: "10.0.0.1:8333"}, @@ -623,6 +626,7 @@ func TestOutboundPeer(t *testing.T) { ChainParams: &chaincfg.MainNetParams, Services: 0, TrickleInterval: time.Second * 10, + AllowSelfConns: true, } r, w := io.Pipe() @@ -764,6 +768,7 @@ func TestUnsupportedVersionPeer(t *testing.T) { ChainParams: &chaincfg.MainNetParams, Services: 0, TrickleInterval: time.Second * 10, + AllowSelfConns: true, } localNA := wire.NewNetAddressIPPort( @@ -874,6 +879,7 @@ func TestDuplicateVersionMsg(t *testing.T) { UserAgentVersion: "1.0", ChainParams: &chaincfg.MainNetParams, Services: 0, + AllowSelfConns: true, } inConn, outConn := pipe( &conn{laddr: "10.0.0.1:9108", raddr: "10.0.0.2:9108"}, @@ -935,6 +941,7 @@ func TestUpdateLastBlockHeight(t *testing.T) { UserAgentVersion: "1.0", ChainParams: &chaincfg.MainNetParams, Services: 0, + AllowSelfConns: true, } remotePeerCfg := peerCfg remotePeerCfg.NewestBlock = func() (*chainhash.Hash, int32, error) { @@ -982,8 +989,3 @@ func TestUpdateLastBlockHeight(t *testing.T) { remotePeerHeight+1) } } - -func init() { - // Allow self connection when running the tests. - peer.TstAllowSelfConns() -} From f86ae60936d7134fad9bf0ab1b3a1c261abe79b7 Mon Sep 17 00:00:00 2001 From: Gustavo Chain Date: Tue, 9 Mar 2021 18:22:04 +0100 Subject: [PATCH 0435/1056] addrmgr: Use RLock/RUnlock when possible --- addrmgr/addrmanager.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index a8a8fb3338..fa8f27bcae 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -30,7 +30,7 @@ import ( // AddrManager provides a concurrency safe address manager for caching potential // peers on the bitcoin network. type AddrManager struct { - mtx sync.Mutex + mtx sync.RWMutex peersFile string lookupFunc func(string) ([]net.IP, error) rand *rand.Rand @@ -645,8 +645,8 @@ func (a *AddrManager) numAddresses() int { // NumAddresses returns the number of addresses known to the address manager. func (a *AddrManager) NumAddresses() int { - a.mtx.Lock() - defer a.mtx.Unlock() + a.mtx.RLock() + defer a.mtx.RUnlock() return a.numAddresses() } @@ -654,8 +654,8 @@ func (a *AddrManager) NumAddresses() int { // NeedMoreAddresses returns whether or not the address manager needs more // addresses. func (a *AddrManager) NeedMoreAddresses() bool { - a.mtx.Lock() - defer a.mtx.Unlock() + a.mtx.RLock() + defer a.mtx.RUnlock() return a.numAddresses() < needAddressThreshold } @@ -685,8 +685,8 @@ func (a *AddrManager) AddressCache() []*wire.NetAddress { // getAddresses returns all of the addresses currently found within the // manager's address cache. func (a *AddrManager) getAddresses() []*wire.NetAddress { - a.mtx.Lock() - defer a.mtx.Unlock() + a.mtx.RLock() + defer a.mtx.RUnlock() addrIndexLen := len(a.addrIndex) if addrIndexLen == 0 { From f133593b932d1eee4d21623d6044760958e69953 Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Mon, 25 Jan 2021 14:13:18 -0800 Subject: [PATCH 0436/1056] build: update btcutil dependency --- go.mod | 2 +- go.sum | 5 +++-- integration/rpctest/memwallet.go | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c53b23d222..049b97fe6c 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/btcsuite/btcd require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v1.0.2 + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/goleveldb v1.0.0 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 diff --git a/go.sum b/go.sum index 392d70f1b7..e259d0ec77 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= -github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= @@ -22,6 +22,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= diff --git a/integration/rpctest/memwallet.go b/integration/rpctest/memwallet.go index f16130750a..59b0ef4c08 100644 --- a/integration/rpctest/memwallet.go +++ b/integration/rpctest/memwallet.go @@ -125,7 +125,7 @@ func newMemWallet(net *chaincfg.Params, harnessID uint32) (*memWallet, error) { // The first child key from the hd root is reserved as the coinbase // generation address. - coinbaseChild, err := hdRoot.Child(0) + coinbaseChild, err := hdRoot.Derive(0) if err != nil { return nil, err } @@ -337,7 +337,7 @@ func (m *memWallet) unwindBlock(update *chainUpdate) { func (m *memWallet) newAddress() (btcutil.Address, error) { index := m.hdIndex - childKey, err := m.hdRoot.Child(index) + childKey, err := m.hdRoot.Derive(index) if err != nil { return nil, err } @@ -509,7 +509,7 @@ func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, outPoint := txIn.PreviousOutPoint utxo := m.utxos[outPoint] - extendedKey, err := m.hdRoot.Child(utxo.keyIndex) + extendedKey, err := m.hdRoot.Derive(utxo.keyIndex) if err != nil { return nil, err } From 540786fda6c6d9328eacf005fa84aef5ed1ec725 Mon Sep 17 00:00:00 2001 From: Jake Sylvestre Date: Tue, 13 Apr 2021 09:02:41 -0400 Subject: [PATCH 0437/1056] rpcclient: fix documentation typo --- rpcclient/net.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcclient/net.go b/rpcclient/net.go index 8f781e4ed8..8c191ff66f 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -90,7 +90,7 @@ func (c *Client) NodeAsync(command btcjson.NodeSubCmd, host string, // connect or diconnect a non-persistent one. // // The connectSubCmd should be set either "perm" or "temp", depending on -// whether we are targetting a persistent or non-persistent peer. Passing nil +// whether we are targeting a persistent or non-persistent peer. Passing nil // will cause the default value to be used, which currently is "temp". func (c *Client) Node(command btcjson.NodeSubCmd, host string, connectSubCmd *string) error { From 2d7825cf709fc6ac15921cecfd4d62ec78ccbba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A8le=20Oul=C3=A8s?= Date: Sun, 21 Mar 2021 19:54:48 +0000 Subject: [PATCH 0438/1056] btcjson: Updated TxRawResult.Version from int32 to uint32 --- btcjson/chainsvrresults.go | 2 +- rpcserver.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 9799494ca3..59f18c74c8 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -712,7 +712,7 @@ type TxRawResult struct { Size int32 `json:"size,omitempty"` Vsize int32 `json:"vsize,omitempty"` Weight int32 `json:"weight,omitempty"` - Version int32 `json:"version"` + Version uint32 `json:"version"` LockTime uint32 `json:"locktime"` Vin []Vin `json:"vin"` Vout []Vout `json:"vout"` diff --git a/rpcserver.go b/rpcserver.go index 1cd3d69cf4..2c9a518543 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -764,7 +764,7 @@ func createTxRawResult(chainParams *chaincfg.Params, mtx *wire.MsgTx, Weight: int32(blockchain.GetTransactionWeight(btcutil.NewTx(mtx))), Vin: createVinList(mtx), Vout: createVoutList(mtx, chainParams, nil), - Version: mtx.Version, + Version: uint32(mtx.Version), LockTime: mtx.LockTime, } From 73ecb5997bcf3d69482bd3780c02472f0bde699a Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 24 Dec 2020 16:51:59 +0100 Subject: [PATCH 0439/1056] wire+chaincfg: add signet params This commit adds all necessary chain parameters for connecting to the public signet network. Reference: https://github.com/bitcoin/bitcoin/pull/18267 --- chaincfg/genesis.go | 28 +++++++++ chaincfg/genesis_test.go | 68 ++++++++++++++++++++ chaincfg/params.go | 132 +++++++++++++++++++++++++++++++++++++++ chaincfg/params_test.go | 49 +++++++++++++++ 4 files changed, 277 insertions(+) diff --git a/chaincfg/genesis.go b/chaincfg/genesis.go index ee47b84ce4..73d286102b 100644 --- a/chaincfg/genesis.go +++ b/chaincfg/genesis.go @@ -170,3 +170,31 @@ var simNetGenesisBlock = wire.MsgBlock{ }, Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, } + +// sigNetGenesisHash is the hash of the first block in the block chain for the +// signet test network. +var sigNetGenesisHash = chainhash.Hash{ + 0xf6, 0x1e, 0xee, 0x3b, 0x63, 0xa3, 0x80, 0xa4, + 0x77, 0xa0, 0x63, 0xaf, 0x32, 0xb2, 0xbb, 0xc9, + 0x7c, 0x9f, 0xf9, 0xf0, 0x1f, 0x2c, 0x42, 0x25, + 0xe9, 0x73, 0x98, 0x81, 0x08, 0x00, 0x00, 0x00, +} + +// sigNetGenesisMerkleRoot is the hash of the first transaction in the genesis +// block for the signet test network. It is the same as the merkle root for +// the main network. +var sigNetGenesisMerkleRoot = genesisMerkleRoot + +// sigNetGenesisBlock defines the genesis block of the block chain which serves +// as the public transaction ledger for the signet test network. +var sigNetGenesisBlock = wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: chainhash.Hash{}, // 0000000000000000000000000000000000000000000000000000000000000000 + MerkleRoot: sigNetGenesisMerkleRoot, // 4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b + Timestamp: time.Unix(1598918400, 0), // 2020-09-01 00:00:00 +0000 UTC + Bits: 0x1e0377ae, // 503543726 [00000377ae000000000000000000000000000000000000000000000000000000] + Nonce: 52613770, + }, + Transactions: []*wire.MsgTx{&genesisCoinbaseTx}, +} diff --git a/chaincfg/genesis_test.go b/chaincfg/genesis_test.go index d04a72f758..1daf847916 100644 --- a/chaincfg/genesis_test.go +++ b/chaincfg/genesis_test.go @@ -118,6 +118,33 @@ func TestSimNetGenesisBlock(t *testing.T) { } } +// TestSigNetGenesisBlock tests the genesis block of the signet test network for +// validity by checking the encoded bytes and hashes. +func TestSigNetGenesisBlock(t *testing.T) { + // Encode the genesis block to raw bytes. + var buf bytes.Buffer + err := SigNetParams.GenesisBlock.Serialize(&buf) + if err != nil { + t.Fatalf("TestSigNetGenesisBlock: %v", err) + } + + // Ensure the encoded block matches the expected bytes. + if !bytes.Equal(buf.Bytes(), sigNetGenesisBlockBytes) { + t.Fatalf("TestSigNetGenesisBlock: Genesis block does not "+ + "appear valid - got %v, want %v", + spew.Sdump(buf.Bytes()), + spew.Sdump(sigNetGenesisBlockBytes)) + } + + // Check hash of the block against expected hash. + hash := SigNetParams.GenesisBlock.BlockHash() + if !SigNetParams.GenesisHash.IsEqual(&hash) { + t.Fatalf("TestSigNetGenesisBlock: Genesis block hash does "+ + "not appear valid - got %v, want %v", spew.Sdump(hash), + spew.Sdump(SigNetParams.GenesisHash)) + } +} + // genesisBlockBytes are the wire encoded bytes for the genesis block of the // main network as of protocol version 60002. var genesisBlockBytes = []byte{ @@ -281,3 +308,44 @@ var simNetGenesisBlockBytes = []byte{ 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, /* |.Lp+k.._|*/ 0xac, 0x00, 0x00, 0x00, 0x00, /* |.....| */ } + +// sigNetGenesisBlockBytes are the wire encoded bytes for the genesis block of +// the signet test network as of protocol version 70002. +var sigNetGenesisBlockBytes = []byte{ + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |...@....| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x3b, 0xa3, 0xed, 0xfd, /* |........| */ + 0x7a, 0x7b, 0x12, 0xb2, 0x7a, 0xc7, 0x2c, 0x3e, /* |....;...| */ + 0x67, 0x76, 0x8f, 0x61, 0x7f, 0xc8, 0x1b, 0xc3, /* |z{..z.,>| */ + 0x88, 0x8a, 0x51, 0x32, 0x3a, 0x9f, 0xb8, 0xaa, /* |gv.a....| */ + 0x4b, 0x1e, 0x5e, 0x4a, 0x00, 0x8f, 0x4d, 0x5f, /* |..Q2:...| */ + 0xae, 0x77, 0x03, 0x1e, 0x8a, 0xd2, 0x22, 0x03, /* |K.^J..M_| */ + 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, /* |.w....".| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* |........| */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, /* |........| */ + 0xff, 0xff, 0x4d, 0x04, 0xff, 0xff, 0x00, 0x1d, /* |........| */ + 0x01, 0x04, 0x45, 0x54, 0x68, 0x65, 0x20, 0x54, /* |..M.....| */ + 0x69, 0x6d, 0x65, 0x73, 0x20, 0x30, 0x33, 0x2f, /* |..EThe T| */ + 0x4a, 0x61, 0x6e, 0x2f, 0x32, 0x30, 0x30, 0x39, /* |imes 03/| */ + 0x20, 0x43, 0x68, 0x61, 0x6e, 0x63, 0x65, 0x6c, /* |Jan/2009| */ + 0x6c, 0x6f, 0x72, 0x20, 0x6f, 0x6e, 0x20, 0x62, /* | Chancel| */ + 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x6f, 0x66, 0x20, /* |lor on b| */ + 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x62, /* |rink of| */ + 0x61, 0x69, 0x6c, 0x6f, 0x75, 0x74, 0x20, 0x66, /* |second b| */ + 0x6f, 0x72, 0x20, 0x62, 0x61, 0x6e, 0x6b, 0x73, /* |ailout f| */ + 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf2, 0x05, /* |or banks| */ + 0x2a, 0x01, 0x00, 0x00, 0x00, 0x43, 0x41, 0x04, /* |........| */ + 0x67, 0x8a, 0xfd, 0xb0, 0xfe, 0x55, 0x48, 0x27, /* |*....CA.| */ + 0x19, 0x67, 0xf1, 0xa6, 0x71, 0x30, 0xb7, 0x10, /* |g....UH'| */ + 0x5c, 0xd6, 0xa8, 0x28, 0xe0, 0x39, 0x09, 0xa6, /* |.g..q0..| */ + 0x79, 0x62, 0xe0, 0xea, 0x1f, 0x61, 0xde, 0xb6, /* |\..(.9..| */ + 0x49, 0xf6, 0xbc, 0x3f, 0x4c, 0xef, 0x38, 0xc4, /* |yb...a..| */ + 0xf3, 0x55, 0x04, 0xe5, 0x1e, 0xc1, 0x12, 0xde, /* |I..?L.8.| */ + 0x5c, 0x38, 0x4d, 0xf7, 0xba, 0x0b, 0x8d, 0x57, /* |.U......| */ + 0x8a, 0x4c, 0x70, 0x2b, 0x6b, 0xf1, 0x1d, 0x5f, /* |\8M....W| */ + 0xac, 0x00, 0x00, 0x00, 0x00, /* |.....| */ +} diff --git a/chaincfg/params.go b/chaincfg/params.go index 7e4327984c..cb1568632c 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -5,6 +5,8 @@ package chaincfg import ( + "encoding/binary" + "encoding/hex" "errors" "math" "math/big" @@ -38,6 +40,30 @@ var ( // simNetPowLimit is the highest proof of work value a Bitcoin block // can have for the simulation test network. It is the value 2^255 - 1. simNetPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 255), bigOne) + + // sigNetPowLimit is the highest proof of work value a bitcoin block can + // have for the signet test network. It is the value 0x0377ae << 216. + sigNetPowLimit = new(big.Int).Lsh(new(big.Int).SetInt64(0x0377ae), 216) + + // DefaultSignetChallenge is the byte representation of the signet + // challenge for the default (public, Taproot enabled) signet network. + // This is the binary equivalent of the bitcoin script + // 1 03ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d1e086be430 + // 0359ef5021964fe22d6f8e05b2463c9540ce96883fe3b278760f048f5189f2e6c4 2 + // OP_CHECKMULTISIG + DefaultSignetChallenge, _ = hex.DecodeString( + "512103ad5e0edad18cb1f0fc0d28a3d4f1f3e445640337489abb10404f2d" + + "1e086be430210359ef5021964fe22d6f8e05b2463c9540ce9688" + + "3fe3b278760f048f5189f2e6c452ae", + ) + + // DefaultSignetDNSSeeds is the list of seed nodes for the default + // (public, Taproot enabled) signet network. + DefaultSignetDNSSeeds = []DNSSeed{ + {"178.128.221.177", false}, + {"2a01:7c8:d005:390::5", false}, + {"v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333", false}, + } ) // Checkpoint identifies a known good point in the block chain. Using @@ -96,6 +122,11 @@ const ( // includes the deployment of BIPS 141, 142, 144, 145, 147 and 173. DeploymentSegwit + // DeploymentTaproot defines the rule change deployment ID for the + // Taproot (+Schnorr) soft-fork package. The taproot package includes + // the deployment of BIPS 340, 341 and 342. + DeploymentTaproot + // NOTE: DefinedDeployments must always come last since it is used to // determine how many defined deployments there currently are. @@ -578,6 +609,107 @@ var SimNetParams = Params{ HDCoinType: 115, // ASCII for s } +// SigNetParams defines the network parameters for the default public signet +// Bitcoin network. Not to be confused with the regression test network, this +// network is sometimes simply called "signet" or "taproot signet". +var SigNetParams = CustomSignetParams( + DefaultSignetChallenge, DefaultSignetDNSSeeds, +) + +// CustomSignetParams creates network parameters for a custom signet network +// from a challenge. The challenge is the binary compiled version of the block +// challenge script. +func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params { + // The message start is defined as the first four bytes of the sha256d + // of the challenge script, as a single push (i.e. prefixed with the + // challenge script length). + challengeLength := byte(len(challenge)) + hashDouble := chainhash.DoubleHashB( + append([]byte{challengeLength}, challenge...), + ) + + // We use little endian encoding of the hash prefix to be in line with + // the other wire network identities. + net := binary.LittleEndian.Uint32(hashDouble[0:4]) + return Params{ + Name: "signet", + Net: wire.BitcoinNet(net), + DefaultPort: "38333", + DNSSeeds: dnsSeeds, + + // Chain parameters + GenesisBlock: &sigNetGenesisBlock, + GenesisHash: &sigNetGenesisHash, + PowLimit: sigNetPowLimit, + PowLimitBits: 0x1e0377ae, + BIP0034Height: 1, + BIP0065Height: 1, + BIP0066Height: 1, + CoinbaseMaturity: 100, + SubsidyReductionInterval: 210000, + TargetTimespan: time.Hour * 24 * 14, // 14 days + TargetTimePerBlock: time.Minute * 10, // 10 minutes + RetargetAdjustmentFactor: 4, // 25% less, 400% more + ReduceMinDifficulty: false, + MinDiffReductionTime: time.Minute * 20, // TargetTimePerBlock * 2 + GenerateSupported: false, + + // Checkpoints ordered from oldest to newest. + Checkpoints: nil, + + // Consensus rule change deployments. + // + // The miner confirmation window is defined as: + // target proof of work timespan / target proof of work spacing + RuleChangeActivationThreshold: 1916, // 95% of 2016 + MinerConfirmationWindow: 2016, + Deployments: [DefinedDeployments]ConsensusDeployment{ + DeploymentTestDummy: { + BitNumber: 28, + StartTime: 1199145601, // January 1, 2008 UTC + ExpireTime: 1230767999, // December 31, 2008 UTC + }, + DeploymentCSV: { + BitNumber: 0, + StartTime: 0, // Always available for vote + ExpireTime: math.MaxInt64, // Never expires + }, + DeploymentSegwit: { + BitNumber: 1, + StartTime: 0, // Always available for vote + ExpireTime: math.MaxInt64, // Never expires. + }, + DeploymentTaproot: { + BitNumber: 2, + StartTime: 0, // Always available for vote + ExpireTime: math.MaxInt64, // Never expires. + }, + }, + + // Mempool parameters + RelayNonStdTxs: false, + + // Human-readable part for Bech32 encoded segwit addresses, as defined in + // BIP 173. + Bech32HRPSegwit: "tb", // always tb for test net + + // Address encoding magics + PubKeyHashAddrID: 0x6f, // starts with m or n + ScriptHashAddrID: 0xc4, // starts with 2 + WitnessPubKeyHashAddrID: 0x03, // starts with QW + WitnessScriptHashAddrID: 0x28, // starts with T7n + PrivateKeyID: 0xef, // starts with 9 (uncompressed) or c (compressed) + + // BIP32 hierarchical deterministic extended key magics + HDPrivateKeyID: [4]byte{0x04, 0x35, 0x83, 0x94}, // starts with tprv + HDPublicKeyID: [4]byte{0x04, 0x35, 0x87, 0xcf}, // starts with tpub + + // BIP44 coin type used in the hierarchical deterministic path for + // address generation. + HDCoinType: 1, + } +} + var ( // ErrDuplicateNet describes an error where the parameters for a Bitcoin // network could not be set due to the network already being a standard diff --git a/chaincfg/params_test.go b/chaincfg/params_test.go index d9e1516812..4166ce0a23 100644 --- a/chaincfg/params_test.go +++ b/chaincfg/params_test.go @@ -6,6 +6,8 @@ package chaincfg import ( "bytes" + "encoding/hex" + "math/big" "testing" ) @@ -84,3 +86,50 @@ func TestInvalidHDKeyID(t *testing.T) { t.Fatalf("HDPrivateKeyToPublicKeyID: want err ErrUnknownHDKeyID, got %v", err) } } + +func TestSigNetPowLimit(t *testing.T) { + sigNetPowLimitHex, _ := hex.DecodeString( + "00000377ae000000000000000000000000000000000000000000000000000000", + ) + powLimit := new(big.Int).SetBytes(sigNetPowLimitHex) + if sigNetPowLimit.Cmp(powLimit) != 0 { + t.Fatalf("Signet PoW limit bits (%s) not equal to big int (%s)", + sigNetPowLimit.Text(16), powLimit.Text(16)) + } + + if compactToBig(sigNetGenesisBlock.Header.Bits).Cmp(powLimit) != 0 { + t.Fatalf("Signet PoW limit header bits (%d) not equal to big "+ + "int (%s)", sigNetGenesisBlock.Header.Bits, + powLimit.Text(16)) + } +} + +// compactToBig is a copy of the blockchain.CompactToBig function. We copy it +// here so we don't run into a circular dependency just because of a test. +func compactToBig(compact uint32) *big.Int { + // Extract the mantissa, sign bit, and exponent. + mantissa := compact & 0x007fffff + isNegative := compact&0x00800000 != 0 + exponent := uint(compact >> 24) + + // Since the base for the exponent is 256, the exponent can be treated + // as the number of bytes to represent the full 256-bit number. So, + // treat the exponent as the number of bytes and shift the mantissa + // right or left accordingly. This is equivalent to: + // N = mantissa * 256^(exponent-3) + var bn *big.Int + if exponent <= 3 { + mantissa >>= 8 * (3 - exponent) + bn = big.NewInt(int64(mantissa)) + } else { + bn = big.NewInt(int64(mantissa)) + bn.Lsh(bn, 8*(exponent-3)) + } + + // Make it negative if the sign bit is set. + if isNegative { + bn = bn.Neg(bn) + } + + return bn +} From 3eac153437340fc90ec8a17d3e0fc6c64bc979b3 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Sun, 14 Feb 2021 15:49:11 +0100 Subject: [PATCH 0440/1056] config+params: add signet config option This commit adds the --signet command line flag (or signet config option) for starting btcd in signet mode. --- config.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++++---- doc.go | 2 +- params.go | 7 +++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/config.go b/config.go index c44f3a837f..7124fe9290 100644 --- a/config.go +++ b/config.go @@ -8,6 +8,7 @@ import ( "bufio" "crypto/rand" "encoding/base64" + "encoding/hex" "errors" "fmt" "io" @@ -159,6 +160,9 @@ type config struct { RPCUser string `short:"u" long:"rpcuser" description:"Username for RPC connections"` SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"` SimNet bool `long:"simnet" description:"Use the simulation test network"` + SigNet bool `long:"signet" description:"Use the signet test network"` + SigNetChallenge string `long:"signetchallenge" description:"Connect to a custom signet network defined by this challenge instead of using the global default signet test network -- Can be specified multiple times"` + SigNetSeedNode []string `long:"signetseednode" description:"Specify a seed node for the signet network instead of using the global default signet network seed nodes"` TestNet3 bool `long:"testnet" description:"Use the test network"` TorIsolation bool `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` TrickleInterval time.Duration `long:"trickleinterval" description:"Minimum time between attempts to send new inventory to a connected peer"` @@ -475,8 +479,8 @@ func loadConfig() (*config, []string, error) { // Load additional config from file. var configFileError error parser := newConfigParser(&cfg, &serviceOpts, flags.Default) - if !(preCfg.RegressionTest || preCfg.SimNet) || preCfg.ConfigFile != - defaultConfigFile { + if !(preCfg.RegressionTest || preCfg.SimNet || preCfg.SigNet) || + preCfg.ConfigFile != defaultConfigFile { if _, err := os.Stat(preCfg.ConfigFile); os.IsNotExist(err) { err := createDefaultConfigFile(preCfg.ConfigFile) @@ -550,9 +554,49 @@ func loadConfig() (*config, []string, error) { activeNetParams = &simNetParams cfg.DisableDNSSeed = true } + if cfg.SigNet { + numNets++ + activeNetParams = &sigNetParams + + // Let the user overwrite the default signet parameters. The + // challenge defines the actual signet network to join and the + // seed nodes are needed for network discovery. + sigNetChallenge := chaincfg.DefaultSignetChallenge + sigNetSeeds := chaincfg.DefaultSignetDNSSeeds + if cfg.SigNetChallenge != "" { + challenge, err := hex.DecodeString(cfg.SigNetChallenge) + if err != nil { + str := "%s: Invalid signet challenge, hex " + + "decode failed: %v" + err := fmt.Errorf(str, funcName, err) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + sigNetChallenge = challenge + } + + if len(cfg.SigNetSeedNode) > 0 { + sigNetSeeds = make( + []chaincfg.DNSSeed, len(cfg.SigNetSeedNode), + ) + for idx, seed := range cfg.SigNetSeedNode { + sigNetSeeds[idx] = chaincfg.DNSSeed{ + Host: seed, + HasFiltering: false, + } + } + } + + chainParams := chaincfg.CustomSignetParams( + sigNetChallenge, sigNetSeeds, + ) + activeNetParams.Params = &chainParams + } if numNets > 1 { - str := "%s: The testnet, regtest, segnet, and simnet params " + - "can't be used together -- choose one of the four" + str := "%s: The testnet, regtest, segnet, signet and simnet " + + "params can't be used together -- choose one of the " + + "five" err := fmt.Errorf(str, funcName) fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, usageMessage) diff --git a/doc.go b/doc.go index 8b9b99773a..70d0d9e45c 100644 --- a/doc.go +++ b/doc.go @@ -72,7 +72,7 @@ Application Options: minute (default: 15) --listen= Add an interface/port to listen for connections (default all interfaces port: 8333, testnet: - 18333) + 18333, signet: 38333) --logdir= Directory to log output --maxorphantx= Max number of orphan transactions to keep in memory (default: 100) diff --git a/params.go b/params.go index 14eeff0717..b4d1453dfb 100644 --- a/params.go +++ b/params.go @@ -55,6 +55,13 @@ var simNetParams = params{ rpcPort: "18556", } +// sigNetParams contains parameters specific to the Signet network +// (wire.SigNet). +var sigNetParams = params{ + Params: &chaincfg.SigNetParams, + rpcPort: "38332", +} + // netName returns the name used when referring to a bitcoin network. At the // time of writing, btcd currently places blocks for testnet version 3 in the // data and log directory "testnet", which does not match the Name field of the From 8a62cf0ef5e3deb27f042543e2748b0b2b120da0 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Wed, 17 Feb 2021 11:07:12 +0100 Subject: [PATCH 0441/1056] rpcserver: add taproot deployment to getblockchaininfo --- rpcserver.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rpcserver.go b/rpcserver.go index 2c9a518543..d184072942 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1256,6 +1256,9 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str case chaincfg.DeploymentSegwit: forkName = "segwit" + case chaincfg.DeploymentTaproot: + forkName = "taproot" + default: return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInternal.Code, From 7d1ab0b4d769cd86cfd63b0b7c52601b32011edb Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 22 Mar 2021 18:26:58 +0100 Subject: [PATCH 0442/1056] btcctl: add signet param This commit adds the --signet command line flag to the btcctl utility. --- cmd/btcctl/config.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index 939b6a8699..1cc2a260f3 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -107,6 +107,7 @@ type config struct { SimNet bool `long:"simnet" description:"Connect to the simulation test network"` TLSSkipVerify bool `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"` TestNet3 bool `long:"testnet" description:"Connect to testnet"` + SigNet bool `long:"signet" description:"Connect to signet"` ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"` Wallet bool `long:"wallet" description:"Connect to wallet"` } @@ -138,6 +139,12 @@ func normalizeAddress(addr string, chain *chaincfg.Params, useWallet bool) (stri } else { defaultPort = "18334" } + case &chaincfg.SigNetParams: + if useWallet { + defaultPort = "38332" + } else { + defaultPort = "38332" + } default: if useWallet { defaultPort = "8332" @@ -273,6 +280,10 @@ func loadConfig() (*config, []string, error) { numNets++ network = &chaincfg.RegressionNetParams } + if cfg.SigNet { + numNets++ + network = &chaincfg.SigNetParams + } if numNets > 1 { str := "%s: Multiple network params can't be used " + From f0f4784c1ccf8cdafb3c72b8f251fa5290174297 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 26 Apr 2021 13:53:22 +0200 Subject: [PATCH 0443/1056] mining: extract witness commitment add into method --- mining/mining.go | 78 +++++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/mining/mining.go b/mining/mining.go index 44ec7dc761..e918328df8 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -803,40 +803,7 @@ mempoolLoop: // OP_RETURN output within the coinbase transaction. var witnessCommitment []byte if witnessIncluded { - // The witness of the coinbase transaction MUST be exactly 32-bytes - // of all zeroes. - var witnessNonce [blockchain.CoinbaseWitnessDataLen]byte - coinbaseTx.MsgTx().TxIn[0].Witness = wire.TxWitness{witnessNonce[:]} - - // Next, obtain the merkle root of a tree which consists of the - // wtxid of all transactions in the block. The coinbase - // transaction will have a special wtxid of all zeroes. - witnessMerkleTree := blockchain.BuildMerkleTreeStore(blockTxns, - true) - witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1] - - // The preimage to the witness commitment is: - // witnessRoot || coinbaseWitness - var witnessPreimage [64]byte - copy(witnessPreimage[:32], witnessMerkleRoot[:]) - copy(witnessPreimage[32:], witnessNonce[:]) - - // The witness commitment itself is the double-sha256 of the - // witness preimage generated above. With the commitment - // generated, the witness script for the output is: OP_RETURN - // OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading - // prefix is referred to as the "witness magic bytes". - witnessCommitment = chainhash.DoubleHashB(witnessPreimage[:]) - witnessScript := append(blockchain.WitnessMagicBytes, witnessCommitment...) - - // Finally, create the OP_RETURN carrying witness commitment - // output as an additional output within the coinbase. - commitmentOutput := &wire.TxOut{ - Value: 0, - PkScript: witnessScript, - } - coinbaseTx.MsgTx().TxOut = append(coinbaseTx.MsgTx().TxOut, - commitmentOutput) + witnessCommitment = AddWitnessCommitment(coinbaseTx, blockTxns) } // Calculate the required difficulty for the block. The timestamp @@ -895,6 +862,49 @@ mempoolLoop: }, nil } +// AddWitnessCommitment adds the witness commitment as an OP_RETURN outpout +// within the coinbase tx. The raw commitment is returned. +func AddWitnessCommitment(coinbaseTx *btcutil.Tx, + blockTxns []*btcutil.Tx) []byte { + + // The witness of the coinbase transaction MUST be exactly 32-bytes + // of all zeroes. + var witnessNonce [blockchain.CoinbaseWitnessDataLen]byte + coinbaseTx.MsgTx().TxIn[0].Witness = wire.TxWitness{witnessNonce[:]} + + // Next, obtain the merkle root of a tree which consists of the + // wtxid of all transactions in the block. The coinbase + // transaction will have a special wtxid of all zeroes. + witnessMerkleTree := blockchain.BuildMerkleTreeStore(blockTxns, + true) + witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1] + + // The preimage to the witness commitment is: + // witnessRoot || coinbaseWitness + var witnessPreimage [64]byte + copy(witnessPreimage[:32], witnessMerkleRoot[:]) + copy(witnessPreimage[32:], witnessNonce[:]) + + // The witness commitment itself is the double-sha256 of the + // witness preimage generated above. With the commitment + // generated, the witness script for the output is: OP_RETURN + // OP_DATA_36 {0xaa21a9ed || witnessCommitment}. The leading + // prefix is referred to as the "witness magic bytes". + witnessCommitment := chainhash.DoubleHashB(witnessPreimage[:]) + witnessScript := append(blockchain.WitnessMagicBytes, witnessCommitment...) + + // Finally, create the OP_RETURN carrying witness commitment + // output as an additional output within the coinbase. + commitmentOutput := &wire.TxOut{ + Value: 0, + PkScript: witnessScript, + } + coinbaseTx.MsgTx().TxOut = append(coinbaseTx.MsgTx().TxOut, + commitmentOutput) + + return witnessCommitment +} + // UpdateBlockTime updates the timestamp in the header of the passed block to // the current time while taking into account the median time of the last // several blocks to ensure the new time is after that time per the chain From 37a6e8485b69f9514d74d153843477c73d1b0473 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Mon, 26 Apr 2021 13:53:51 +0200 Subject: [PATCH 0444/1056] rpctest: add witness commitment when calling CreateBlock If we tried to include transactions having witnesses, the block would be invalid since the witness commitment was not added. --- integration/rpctest/blockgen.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/integration/rpctest/blockgen.go b/integration/rpctest/blockgen.go index de5821b0c1..0d802f5a48 100644 --- a/integration/rpctest/blockgen.go +++ b/integration/rpctest/blockgen.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" @@ -181,6 +182,21 @@ func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx, if inclusionTxs != nil { blockTxns = append(blockTxns, inclusionTxs...) } + + // We must add the witness commitment to the coinbase if any + // transactions are segwit. + witnessIncluded := false + for i := 1; i < len(blockTxns); i++ { + if blockTxns[i].MsgTx().HasWitness() { + witnessIncluded = true + break + } + } + + if witnessIncluded { + _ = mining.AddWitnessCommitment(coinbaseTx, blockTxns) + } + merkles := blockchain.BuildMerkleTreeStore(blockTxns, false) var block wire.MsgBlock block.Header = wire.BlockHeader{ From 0ec4bdc1b8e162efffed446a80f297c188543088 Mon Sep 17 00:00:00 2001 From: "John C. Vernaleo" Date: Sun, 18 Apr 2021 16:46:27 -0400 Subject: [PATCH 0445/1056] Don't reference the readme that we don't produce --- README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/README.md b/README.md index 62fa223aae..957369a239 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,6 @@ which are both under active development. ## Installation -#### Windows - MSI Available - https://github.com/btcsuite/btcd/releases #### Linux/BSD/MacOSX/POSIX - Build from Source @@ -74,10 +72,6 @@ $ GO111MODULE=on go install -v . ./cmd/... ## Updating -#### Windows - -Install a newer MSI - #### Linux/BSD/MacOSX/POSIX - Build from Source - Run the following commands to update btcd, all dependencies, and install it: @@ -94,10 +88,6 @@ btcd has several configuration options available to tweak how it runs, but all of the basic operations described in the intro section work with zero configuration. -#### Windows (Installed from MSI) - -Launch btcd from your Start menu. - #### Linux/BSD/POSIX/Source ```bash From 7b6c2b342379f3cba880d9f3cc14c77fc7500969 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 May 2021 14:22:09 +0200 Subject: [PATCH 0446/1056] chaincfg: fix deployment bit numbers On signet all previous soft forks and also taproot are always activated, meaning the version is always 0x20000000 for all blocks. To make sure they activate properly in `btcd` we therefore need to use the correct bit to mask the version. This means that on any custom signet there would need to be 2016 blocks mined before SegWit or Taproot can be used. --- chaincfg/params.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chaincfg/params.go b/chaincfg/params.go index cb1568632c..a6d8d3e551 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -670,17 +670,17 @@ func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params { ExpireTime: 1230767999, // December 31, 2008 UTC }, DeploymentCSV: { - BitNumber: 0, + BitNumber: 29, StartTime: 0, // Always available for vote ExpireTime: math.MaxInt64, // Never expires }, DeploymentSegwit: { - BitNumber: 1, + BitNumber: 29, StartTime: 0, // Always available for vote ExpireTime: math.MaxInt64, // Never expires. }, DeploymentTaproot: { - BitNumber: 2, + BitNumber: 29, StartTime: 0, // Always available for vote ExpireTime: math.MaxInt64, // Never expires. }, From ee5896bad5be6b35d9308d1698aee2fb77863279 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 12 May 2021 17:47:26 -0700 Subject: [PATCH 0447/1056] mempool: add additional test case for inherited RBF replacement In this commit, we add an additional test case for inherited RBF replacement. This test case asserts that if a parent is marked as being replaceable, but the child isn't, then the child can still be replaced as according to BIP 125 it shoudl _inhreit_ the replaceability of its parent. The addition of this test case was prompted by the recently discovered Bitcoin Core "CVE" [1]. It turns out that bitcoind doesn't properly implement BIP 125. Namely it fails to allow a child to "inherit" replaceability if its parent is also replaceable. Our implementation makes this trait rather explicit due to its recursive implementation. Kudos to the original implementer @wpaulino for getting this correct. [1]: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-May/018893.html. --- mempool/mempool_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 6d43cfd86e..96d5054417 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -1749,6 +1749,47 @@ func TestRBF(t *testing.T) { }, err: "", }, + { + // A transaction that doesn't signal replacement, can + // be replaced if the parent signals replacement. + name: "inherited replacement", + setup: func(ctx *testContext) (*btcutil.Tx, []*btcutil.Tx) { + coinbase := ctx.addCoinbaseTx(1) + + // Create an initial parent transaction that + // marks replacement, we won't be replacing + // this directly however. + coinbaseOut := txOutToSpendableOut(coinbase, 0) + outs := []spendableOutput{coinbaseOut} + parent := ctx.addSignedTx( + outs, 1, defaultFee, true, false, + ) + + // Now create a transaction that spends that + // parent transaction, which is marked as NOT + // being RBF-able. + parentOut := txOutToSpendableOut(parent, 0) + parentOuts := []spendableOutput{parentOut} + childNoReplace := ctx.addSignedTx( + parentOuts, 1, defaultFee, false, false, + ) + + // Now we'll create another transaction that + // replaces the *child* only. This should work + // as the parent has been marked for RBF, even + // though the child hasn't. + respendOuts := []spendableOutput{parentOut} + childReplace, err := ctx.harness.CreateSignedTx( + respendOuts, 1, defaultFee*3, false, + ) + if err != nil { + ctx.t.Fatalf("unable to create child tx: %v", err) + } + + return childReplace, []*btcutil.Tx{childNoReplace} + }, + err: "", + }, } for _, testCase := range testCases { From 418f9204f49c71e6a481653237f00a781c29ea77 Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Wed, 26 May 2021 03:17:24 +0530 Subject: [PATCH 0448/1056] Update CHANGES file for 0.22.0 release --- CHANGES | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index d38897b339..6c5be7fa3a 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,126 @@ User visible changes for btcd A full-node bitcoin implementation written in Go ============================================================================ +Changes in 0.22.0 (Thu May 27 2021) + - Protocol and network-related changes: + - Add support for witness tx and block in notfound msg (#1625) + - Add support for receiving sendaddrv2 messages from a peer (#1670) + - Fix bug in peer package causing last block height to go backwards + (#1606) + - Add chain parameters for connecting to the public Signet network + (#1692, #1718) + - Crypto changes: + - Fix bug causing panic due to bad R and S signature components in + btcec.RecoverCompact (#1691) + - Set the name (secp256k1) in the CurveParams of the S256 curve + (#1565) + - Notable developer-related package changes: + - Remove unknown block version warning in the blockchain package, + due to false positives triggered by AsicBoost (#1463) + - Add chaincfg.RegisterHDKeyID function to populate HD key ID pairs + (#1617) + - Add new method mining.AddWitnessCommitment to add the witness + commitment as an OP_RETURN output within the coinbase transaction. + (#1716) + - RPC changes: + - Support Batch JSON-RPC in rpcclient and server (#1583) + - Add rpcclient method to invoke getdescriptorinfo JSON-RPC command + (#1578) + - Update the rpcserver handler for validateaddress JSON-RPC command to + have parity with the bitcoind 0.20.0 interface (#1613) + - Add rpcclient method to invoke getblockfilter JSON-RPC command + (#1579) + - Add signmessagewithprivkey JSON-RPC command in rpcserver (#1585) + - Add rpcclient method to invoke importmulti JSON-RPC command (#1579) + - Add watchOnly argument in rpcclient method to invoke + listtransactions JSON-RPC command (#1628) + - Update btcjson.ListTransactionsResult for compatibility with Bitcoin + Core 0.20.0 (#1626) + - Support nullable optional JSON-RPC parameters (#1594) + - Add rpcclient and server method to invoke getnodeaddresses JSON-RPC + command (#1590) + - Add rpcclient methods to invoke PSBT JSON-RPC commands (#1596) + - Add rpcclient method to invoke listsinceblock with the + include_watchonly parameter enabled (#1451) + - Add rpcclient method to invoke deriveaddresses JSON-RPC command + (#1631) + - Add rpcclient method to invoke getblocktemplate JSON-RPC command + (#1629) + - Add rpcclient method to invoke getaddressinfo JSON-RPC command + (#1633) + - Add rpcclient method to invoke getwalletinfo JSON-RPC command + (#1638) + - Fix error message in rpcserver when an unknown RPC command is + encountered (#1695) + - Fix error message returned by estimatefee when the number of blocks + exceeds the max depth (#1678) + - Update btcjson.GetBlockChainInfoResult to include new fields in + Bitcoin Core (#1676) + - Add ExtraHeaders in rpcclient.ConnConfig struct (#1669) + - Fix bitcoind compatibility issue with the sendrawtransaction + JSON-RPC command (#1659) + - Add new JSON-RPC errors to btcjson package, and documented them + (#1648) + - Add rpcclient method to invoke createwallet JSON-RPC command + (#1650) + - Add rpcclient methods to invoke backupwallet, dumpwallet, loadwallet + and unloadwallet JSON-RPC commands (#1645) + - Fix unmarshalling error in getmininginfo JSON-RPC command, for valid + integers in scientific notation (#1644) + - Add rpcclient method to invoke gettxoutsetinfo JSON-RPC command + (#1641) + - Add rpcclient method to invoke signrawtransactionwithwallet JSON-RPC + command (#1642) + - Add txid to getblocktemplate response of rpcserver (#1639) + - Fix monetary unit used in createrawtransaction JSON-RPC command in + rpcserver (#1614) + - Add rawtx field to btcjson.GetBlockVerboseTxResult to provide + backwards compatibility with older versions of Bitcoin Core (#1677) + - Misc changes: + - Update btcutil dependency (#1704) + - Add Dockerfile to build and run btcd on Docker (#1465) + - Rework documentation and publish on https://btcd.readthedocs.io (#1468) + - Add support for Go 1.15 (#1619) + - Add Go 1.14 as the minimum supported version of Golang (#1621) + - Contributors (alphabetical order): + - 10gic + - Andrew Tugarinov + - Anirudha Bose + - Appelberg-s + - Armando Ochoa + - Aurèle Oulès + - Calvin Kim + - Christian Lehmann + - Conner Fromknecht + - Dan Cline + - David Mazary + - Elliott Minns + - Federico Bond + - Friedger Müffke + - Gustavo Chain + - Hanjun Kim + - Henry Fisher + - Iskander Sharipov + - Jake Sylvestre + - Johan T. Halseth + - John C. Vernaleo + - Liran Sharir + - Mikael Lindlof + - Olaoluwa Osuntokun + - Oliver Gugger + - Rjected + - Steven Kreuzer + - Torkel Rogstad + - Tristyn + - Victor Lavaud + - Vinayak Borkar + - Wilmer Paulino + - Yaacov Akiba Slama + - ebiiim + - ipriver + - wakiyamap + - yyforyongyu + Changes in 0.21.0 (Thu Aug 27 2020) - Network-related changes: - Handle notfound messages from peers in netsync package (#1603) @@ -26,7 +146,7 @@ Changes in 0.21.0 (Thu Aug 27 2020) - Fix panic in fieldVal.SetByteSlice when called with large values, and improve the method to be 35% faster (#1602) - btcctl changes: - - Added -regtest mode to btcctl (#1556) + - Add -regtest mode to btcctl (#1556) - Misc changes: - Fix a bug due to a deadlock in connmgr's dynamic ban scoring (#1509) - Add blockchain.NewUtxoEntry() to directly create entries for From aaf19b26f3abfc5b0374042881d8e43cf1d95a8c Mon Sep 17 00:00:00 2001 From: "John C. Vernaleo" Date: Wed, 26 May 2021 11:13:28 -0400 Subject: [PATCH 0449/1056] btcd: bump version to v0.22.0-beta --- cmd/btcctl/version.go | 2 +- version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go index f3a3e0b830..edb42dbe7d 100644 --- a/cmd/btcctl/version.go +++ b/cmd/btcctl/version.go @@ -17,7 +17,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 21 + appMinor uint = 22 appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet diff --git a/version.go b/version.go index ac294de232..d6ff9171aa 100644 --- a/version.go +++ b/version.go @@ -17,7 +17,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 21 + appMinor uint = 22 appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet From 63438c6d3661a7dec09013f7731035abdf1eb4bc Mon Sep 17 00:00:00 2001 From: Anirudha Bose Date: Tue, 1 Jun 2021 21:27:38 +0530 Subject: [PATCH 0450/1056] Update release date for v0.22.0-beta in CHANGES file --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 6c5be7fa3a..fd59a88672 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,7 @@ User visible changes for btcd A full-node bitcoin implementation written in Go ============================================================================ -Changes in 0.22.0 (Thu May 27 2021) +Changes in 0.22.0 (Tue Jun 01 2021) - Protocol and network-related changes: - Add support for witness tx and block in notfound msg (#1625) - Add support for receiving sendaddrv2 messages from a peer (#1670) From 505915dc3f2877e5d561d8eb03c6a7c05e61d462 Mon Sep 17 00:00:00 2001 From: Gabriel Nasr Date: Fri, 25 Jun 2021 15:20:16 -0300 Subject: [PATCH 0451/1056] btcjson: Update WalletCreateFundedPsbtOpts.FeeRate from *int64 to *float64 --- btcjson/walletsvrcmds.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 2ff9ae1832..e8ed62372b 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -1029,7 +1029,7 @@ type WalletCreateFundedPsbtOpts struct { ChangeType *ChangeType `json:"change_type,omitempty"` IncludeWatching *bool `json:"includeWatching,omitempty"` LockUnspents *bool `json:"lockUnspents,omitempty"` - FeeRate *int64 `json:"feeRate,omitempty"` + FeeRate *float64 `json:"feeRate,omitempty"` SubtractFeeFromOutputs *[]int64 `json:"subtractFeeFromOutputs,omitempty"` Replaceable *bool `json:"replaceable,omitempty"` ConfTarget *int64 `json:"conf_target,omitempty"` From b3e6bd6161d66f67655af2e7536b92db882a48f7 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 15 Jul 2021 16:01:20 +0900 Subject: [PATCH 0452/1056] rpcserverhelp: Remove extra period for gettxout--synopsis --- rpcserverhelp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 654fee0169..570b5b0500 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -528,7 +528,7 @@ var helpDescsEnUS = map[string]string{ "gettxoutresult-coinbase": "Whether or not the transaction is a coinbase", // GetTxOutCmd help. - "gettxout--synopsis": "Returns information about an unspent transaction output..", + "gettxout--synopsis": "Returns information about an unspent transaction output.", "gettxout-txid": "The hash of the transaction", "gettxout-vout": "The index of the output", "gettxout-includemempool": "Include the mempool when true", From f5a1fb9965e4415c619c032e04ac21731f92167a Mon Sep 17 00:00:00 2001 From: eugene Date: Mon, 2 Aug 2021 11:14:52 -0400 Subject: [PATCH 0453/1056] mempool: export isDust for use in other projects This changes isDust to IsDust so other golang projects (btcwallet or lnd) can use the precise dust calculation used by btcd. --- mempool/policy.go | 6 +++--- mempool/policy_test.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mempool/policy.go b/mempool/policy.go index 7e97329319..74142bf60c 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -172,12 +172,12 @@ func checkPkScriptStandard(pkScript []byte, scriptClass txscript.ScriptClass) er return nil } -// isDust returns whether or not the passed transaction output amount is +// IsDust returns whether or not the passed transaction output amount is // considered dust or not based on the passed minimum transaction relay fee. // Dust is defined in terms of the minimum transaction relay fee. In // particular, if the cost to the network to spend coins is more than 1/3 of the // minimum transaction relay fee, it is considered dust. -func isDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { +func IsDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { // Unspendable outputs are considered dust. if txscript.IsUnspendable(txOut.PkScript) { return true @@ -351,7 +351,7 @@ func checkTransactionStandard(tx *btcutil.Tx, height int32, // "dust". if scriptClass == txscript.NullDataTy { numNullDataOutputs++ - } else if isDust(txOut, minRelayTxFee) { + } else if IsDust(txOut, minRelayTxFee) { str := fmt.Sprintf("transaction output %d: payment "+ "of %d is dust", i, txOut.Value) return txRuleError(wire.RejectDust, str) diff --git a/mempool/policy_test.go b/mempool/policy_test.go index 9dd618ad6e..b9cdbac47a 100644 --- a/mempool/policy_test.go +++ b/mempool/policy_test.go @@ -204,7 +204,7 @@ func TestCheckPkScriptStandard(t *testing.T) { } } -// TestDust tests the isDust API. +// TestDust tests the IsDust API. func TestDust(t *testing.T) { pkScript := []byte{0x76, 0xa9, 0x21, 0x03, 0x2f, 0x7e, 0x43, 0x0a, 0xa4, 0xc9, 0xd1, 0x59, 0x43, 0x7e, 0x84, 0xb9, @@ -268,7 +268,7 @@ func TestDust(t *testing.T) { }, } for _, test := range tests { - res := isDust(&test.txOut, test.relayFee) + res := IsDust(&test.txOut, test.relayFee) if res != test.isDust { t.Fatalf("Dust test '%s' failed: want %v got %v", test.name, test.isDust, res) From f9d72f05a4bcf5288a237b652ad2b9a5fea4630c Mon Sep 17 00:00:00 2001 From: "John C. Vernaleo" Date: Wed, 26 May 2021 11:19:15 -0400 Subject: [PATCH 0454/1056] Switch irc to libera.chat --- README.md | 4 ++-- docs/contact.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 957369a239..556673825e 100644 --- a/README.md +++ b/README.md @@ -96,9 +96,9 @@ $ ./btcd ## IRC -- irc.freenode.net +- irc.libera.chat - channel #btcd -- [webchat](https://webchat.freenode.net/?channels=btcd) +- [webchat](https://web.libera.chat/gamja/?channels=btcd) ## Issue Tracker diff --git a/docs/contact.md b/docs/contact.md index 88b425e8bc..1ed9fc0b3a 100644 --- a/docs/contact.md +++ b/docs/contact.md @@ -2,7 +2,7 @@ ## IRC -* [irc.freenode.net](irc://irc.freenode.net), channel `#btcd` +* [irc.libera.chat](irc://irc.libera.chat), channel `#btcd` ## Mailing Lists From 3e2d8464f12b2e534e9764b0e4d4a48217c157e0 Mon Sep 17 00:00:00 2001 From: JeremyRand <244188+JeremyRand@users.noreply.github.com> Date: Thu, 2 Sep 2021 06:39:55 +0000 Subject: [PATCH 0455/1056] rpcclient: Export symbols needed for custom commands (#1457) * rpcclient: Export sendCmd and response This facilitates using custom commands with rpcclient. See https://github.com/btcsuite/btcd/issues/1083 * rpcclient: Export receiveFuture This facilitates using custom commands with rpcclient. See https://github.com/btcsuite/btcd/issues/1083 * rpcclient: Add customcommand example * rpcclient: remove "Namecoin" from customcommand readme heading --- rpcclient/chain.go | 230 +++++----- rpcclient/examples/customcommand/README.md | 32 ++ rpcclient/examples/customcommand/main.go | 110 +++++ rpcclient/extensions.go | 72 ++-- rpcclient/infrastructure.go | 58 +-- rpcclient/mining.go | 92 ++-- rpcclient/net.go | 80 ++-- rpcclient/notify.go | 60 +-- rpcclient/rawrequest.go | 10 +- rpcclient/rawtransactions.go | 98 ++--- rpcclient/wallet.go | 480 ++++++++++----------- 11 files changed, 732 insertions(+), 590 deletions(-) create mode 100644 rpcclient/examples/customcommand/README.md create mode 100644 rpcclient/examples/customcommand/main.go diff --git a/rpcclient/chain.go b/rpcclient/chain.go index d478da7a00..a97543fd3c 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -17,12 +17,12 @@ import ( // FutureGetBestBlockHashResult is a future promise to deliver the result of a // GetBestBlockAsync RPC invocation (or an applicable error). -type FutureGetBestBlockHashResult chan *response +type FutureGetBestBlockHashResult chan *Response -// Receive waits for the response promised by the future and returns the hash of +// Receive waits for the Response promised by the future and returns the hash of // the best block in the longest block chain. func (r FutureGetBestBlockHashResult) Receive() (*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -43,7 +43,7 @@ func (r FutureGetBestBlockHashResult) Receive() (*chainhash.Hash, error) { // See GetBestBlockHash for the blocking version and more details. func (c *Client) GetBestBlockHashAsync() FutureGetBestBlockHashResult { cmd := btcjson.NewGetBestBlockHashCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBestBlockHash returns the hash of the best block in the longest block @@ -75,13 +75,13 @@ func (c *Client) legacyGetBlockRequest(hash string, verbose, }) } -// waitForGetBlockRes waits for the response of a getblock request. If the -// response indicates an invalid parameter was provided, a legacy style of the -// request is resent and its response is returned instead. -func (c *Client) waitForGetBlockRes(respChan chan *response, hash string, +// waitForGetBlockRes waits for the Response of a getblock request. If the +// Response indicates an invalid parameter was provided, a legacy style of the +// request is resent and its Response is returned instead. +func (c *Client) waitForGetBlockRes(respChan chan *Response, hash string, verbose, verboseTx bool) ([]byte, error) { - res, err := receiveFuture(respChan) + res, err := ReceiveFuture(respChan) // If we receive an invalid parameter error, then we may be // communicating with a btcd node which only understands the legacy @@ -91,7 +91,7 @@ func (c *Client) waitForGetBlockRes(respChan chan *response, hash string, return c.legacyGetBlockRequest(hash, verbose, verboseTx) } - // Otherwise, we can return the response as is. + // Otherwise, we can return the Response as is. return res, err } @@ -100,10 +100,10 @@ func (c *Client) waitForGetBlockRes(respChan chan *response, hash string, type FutureGetBlockResult struct { client *Client hash string - Response chan *response + Response chan *Response } -// Receive waits for the response promised by the future and returns the raw +// Receive waits for the Response promised by the future and returns the raw // block requested from the server given its hash. func (r FutureGetBlockResult) Receive() (*wire.MsgBlock, error) { res, err := r.client.waitForGetBlockRes(r.Response, r.hash, false, false) @@ -148,7 +148,7 @@ func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult { return FutureGetBlockResult{ client: c, hash: hash, - Response: c.sendCmd(cmd), + Response: c.SendCmd(cmd), } } @@ -165,10 +165,10 @@ func (c *Client) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) { type FutureGetBlockVerboseResult struct { client *Client hash string - Response chan *response + Response chan *Response } -// Receive waits for the response promised by the future and returns the data +// Receive waits for the Response promised by the future and returns the data // structure from the server with information about the requested block. func (r FutureGetBlockVerboseResult) Receive() (*btcjson.GetBlockVerboseResult, error) { res, err := r.client.waitForGetBlockRes(r.Response, r.hash, true, false) @@ -201,7 +201,7 @@ func (c *Client) GetBlockVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockV return FutureGetBlockVerboseResult{ client: c, hash: hash, - Response: c.sendCmd(cmd), + Response: c.SendCmd(cmd), } } @@ -219,10 +219,10 @@ func (c *Client) GetBlockVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockVe type FutureGetBlockVerboseTxResult struct { client *Client hash string - Response chan *response + Response chan *Response } -// Receive waits for the response promised by the future and returns a verbose +// Receive waits for the Response promised by the future and returns a verbose // version of the block including detailed information about its transactions. func (r FutureGetBlockVerboseTxResult) Receive() (*btcjson.GetBlockVerboseTxResult, error) { res, err := r.client.waitForGetBlockRes(r.Response, r.hash, true, true) @@ -258,7 +258,7 @@ func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBloc return FutureGetBlockVerboseTxResult{ client: c, hash: hash, - Response: c.sendCmd(cmd), + Response: c.SendCmd(cmd), } } @@ -273,12 +273,12 @@ func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlock // FutureGetBlockCountResult is a future promise to deliver the result of a // GetBlockCountAsync RPC invocation (or an applicable error). -type FutureGetBlockCountResult chan *response +type FutureGetBlockCountResult chan *Response -// Receive waits for the response promised by the future and returns the number +// Receive waits for the Response promised by the future and returns the number // of blocks in the longest block chain. func (r FutureGetBlockCountResult) Receive() (int64, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -299,7 +299,7 @@ func (r FutureGetBlockCountResult) Receive() (int64, error) { // See GetBlockCount for the blocking version and more details. func (c *Client) GetBlockCountAsync() FutureGetBlockCountResult { cmd := btcjson.NewGetBlockCountCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBlockCount returns the number of blocks in the longest block chain. @@ -309,11 +309,11 @@ func (c *Client) GetBlockCount() (int64, error) { // FutureGetChainTxStatsResult is a future promise to deliver the result of a // GetChainTxStatsAsync RPC invocation (or an applicable error). -type FutureGetChainTxStatsResult chan *response +type FutureGetChainTxStatsResult chan *Response -// Receive waits for the response promised by the future and returns transaction statistics +// Receive waits for the Response promised by the future and returns transaction statistics func (r FutureGetChainTxStatsResult) Receive() (*btcjson.GetChainTxStatsResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -334,7 +334,7 @@ func (r FutureGetChainTxStatsResult) Receive() (*btcjson.GetChainTxStatsResult, // See GetChainTxStats for the blocking version and more details. func (c *Client) GetChainTxStatsAsync() FutureGetChainTxStatsResult { cmd := btcjson.NewGetChainTxStatsCmd(nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetChainTxStatsNBlocksAsync returns an instance of a type that can be used to get @@ -344,7 +344,7 @@ func (c *Client) GetChainTxStatsAsync() FutureGetChainTxStatsResult { // See GetChainTxStatsNBlocks for the blocking version and more details. func (c *Client) GetChainTxStatsNBlocksAsync(nBlocks int32) FutureGetChainTxStatsResult { cmd := btcjson.NewGetChainTxStatsCmd(&nBlocks, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetChainTxStatsNBlocksBlockHashAsync returns an instance of a type that can be used to get @@ -355,7 +355,7 @@ func (c *Client) GetChainTxStatsNBlocksAsync(nBlocks int32) FutureGetChainTxStat func (c *Client) GetChainTxStatsNBlocksBlockHashAsync(nBlocks int32, blockHash chainhash.Hash) FutureGetChainTxStatsResult { hash := blockHash.String() cmd := btcjson.NewGetChainTxStatsCmd(&nBlocks, &hash) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetChainTxStats returns statistics about the total number and rate of transactions in the chain. @@ -382,12 +382,12 @@ func (c *Client) GetChainTxStatsNBlocksBlockHash(nBlocks int32, blockHash chainh // FutureGetDifficultyResult is a future promise to deliver the result of a // GetDifficultyAsync RPC invocation (or an applicable error). -type FutureGetDifficultyResult chan *response +type FutureGetDifficultyResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // proof-of-work difficulty as a multiple of the minimum difficulty. func (r FutureGetDifficultyResult) Receive() (float64, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -408,7 +408,7 @@ func (r FutureGetDifficultyResult) Receive() (float64, error) { // See GetDifficulty for the blocking version and more details. func (c *Client) GetDifficultyAsync() FutureGetDifficultyResult { cmd := btcjson.NewGetDifficultyCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetDifficulty returns the proof-of-work difficulty as a multiple of the @@ -421,7 +421,7 @@ func (c *Client) GetDifficulty() (float64, error) { // GetBlockChainInfoAsync RPC invocation (or an applicable error). type FutureGetBlockChainInfoResult struct { client *Client - Response chan *response + Response chan *Response } // unmarshalPartialGetBlockChainInfoResult unmarshals the response into an @@ -461,10 +461,10 @@ func unmarshalGetBlockChainInfoResultSoftForks(chainInfo *btcjson.GetBlockChainI return nil } -// Receive waits for the response promised by the future and returns chain info +// Receive waits for the Response promised by the future and returns chain info // result provided by the server. func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResult, error) { - res, err := receiveFuture(r.Response) + res, err := ReceiveFuture(r.Response) if err != nil { return nil, err } @@ -497,7 +497,7 @@ func (c *Client) GetBlockChainInfoAsync() FutureGetBlockChainInfoResult { cmd := btcjson.NewGetBlockChainInfoCmd() return FutureGetBlockChainInfoResult{ client: c, - Response: c.sendCmd(cmd), + Response: c.SendCmd(cmd), } } @@ -510,12 +510,12 @@ func (c *Client) GetBlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) { // FutureGetBlockFilterResult is a future promise to deliver the result of a // GetBlockFilterAsync RPC invocation (or an applicable error). -type FutureGetBlockFilterResult chan *response +type FutureGetBlockFilterResult chan *Response -// Receive waits for the response promised by the future and returns block filter +// Receive waits for the Response promised by the future and returns block filter // result provided by the server. func (r FutureGetBlockFilterResult) Receive() (*btcjson.GetBlockFilterResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -538,7 +538,7 @@ func (c *Client) GetBlockFilterAsync(blockHash chainhash.Hash, filterType *btcjs hash := blockHash.String() cmd := btcjson.NewGetBlockFilterCmd(hash, filterType) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBlockFilter retrieves a BIP0157 content filter for a particular block. @@ -548,12 +548,12 @@ func (c *Client) GetBlockFilter(blockHash chainhash.Hash, filterType *btcjson.Fi // FutureGetBlockHashResult is a future promise to deliver the result of a // GetBlockHashAsync RPC invocation (or an applicable error). -type FutureGetBlockHashResult chan *response +type FutureGetBlockHashResult chan *Response -// Receive waits for the response promised by the future and returns the hash of +// Receive waits for the Response promised by the future and returns the hash of // the block in the best block chain at the given height. func (r FutureGetBlockHashResult) Receive() (*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -574,7 +574,7 @@ func (r FutureGetBlockHashResult) Receive() (*chainhash.Hash, error) { // See GetBlockHash for the blocking version and more details. func (c *Client) GetBlockHashAsync(blockHeight int64) FutureGetBlockHashResult { cmd := btcjson.NewGetBlockHashCmd(blockHeight) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBlockHash returns the hash of the block in the best block chain at the @@ -585,12 +585,12 @@ func (c *Client) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) { // FutureGetBlockHeaderResult is a future promise to deliver the result of a // GetBlockHeaderAsync RPC invocation (or an applicable error). -type FutureGetBlockHeaderResult chan *response +type FutureGetBlockHeaderResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // blockheader requested from the server given its hash. func (r FutureGetBlockHeaderResult) Receive() (*wire.BlockHeader, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -629,7 +629,7 @@ func (c *Client) GetBlockHeaderAsync(blockHash *chainhash.Hash) FutureGetBlockHe } cmd := btcjson.NewGetBlockHeaderCmd(hash, btcjson.Bool(false)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBlockHeader returns the blockheader from the server given its hash. @@ -642,12 +642,12 @@ func (c *Client) GetBlockHeader(blockHash *chainhash.Hash) (*wire.BlockHeader, e // FutureGetBlockHeaderVerboseResult is a future promise to deliver the result of a // GetBlockAsync RPC invocation (or an applicable error). -type FutureGetBlockHeaderVerboseResult chan *response +type FutureGetBlockHeaderVerboseResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // data structure of the blockheader requested from the server given its hash. func (r FutureGetBlockHeaderVerboseResult) Receive() (*btcjson.GetBlockHeaderVerboseResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -674,7 +674,7 @@ func (c *Client) GetBlockHeaderVerboseAsync(blockHash *chainhash.Hash) FutureGet } cmd := btcjson.NewGetBlockHeaderCmd(hash, btcjson.Bool(true)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBlockHeaderVerbose returns a data structure with information about the @@ -687,13 +687,13 @@ func (c *Client) GetBlockHeaderVerbose(blockHash *chainhash.Hash) (*btcjson.GetB // FutureGetMempoolEntryResult is a future promise to deliver the result of a // GetMempoolEntryAsync RPC invocation (or an applicable error). -type FutureGetMempoolEntryResult chan *response +type FutureGetMempoolEntryResult chan *Response -// Receive waits for the response promised by the future and returns a data +// Receive waits for the Response promised by the future and returns a data // structure with information about the transaction in the memory pool given // its hash. func (r FutureGetMempoolEntryResult) Receive() (*btcjson.GetMempoolEntryResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -715,7 +715,7 @@ func (r FutureGetMempoolEntryResult) Receive() (*btcjson.GetMempoolEntryResult, // See GetMempoolEntry for the blocking version and more details. func (c *Client) GetMempoolEntryAsync(txHash string) FutureGetMempoolEntryResult { cmd := btcjson.NewGetMempoolEntryCmd(txHash) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetMempoolEntry returns a data structure with information about the @@ -726,12 +726,12 @@ func (c *Client) GetMempoolEntry(txHash string) (*btcjson.GetMempoolEntryResult, // FutureGetRawMempoolResult is a future promise to deliver the result of a // GetRawMempoolAsync RPC invocation (or an applicable error). -type FutureGetRawMempoolResult chan *response +type FutureGetRawMempoolResult chan *Response -// Receive waits for the response promised by the future and returns the hashes +// Receive waits for the Response promised by the future and returns the hashes // of all transactions in the memory pool. func (r FutureGetRawMempoolResult) Receive() ([]*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -763,7 +763,7 @@ func (r FutureGetRawMempoolResult) Receive() ([]*chainhash.Hash, error) { // See GetRawMempool for the blocking version and more details. func (c *Client) GetRawMempoolAsync() FutureGetRawMempoolResult { cmd := btcjson.NewGetRawMempoolCmd(btcjson.Bool(false)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetRawMempool returns the hashes of all transactions in the memory pool. @@ -776,13 +776,13 @@ func (c *Client) GetRawMempool() ([]*chainhash.Hash, error) { // FutureGetRawMempoolVerboseResult is a future promise to deliver the result of // a GetRawMempoolVerboseAsync RPC invocation (or an applicable error). -type FutureGetRawMempoolVerboseResult chan *response +type FutureGetRawMempoolVerboseResult chan *Response -// Receive waits for the response promised by the future and returns a map of +// Receive waits for the Response promised by the future and returns a map of // transaction hashes to an associated data structure with information about the // transaction for all transactions in the memory pool. func (r FutureGetRawMempoolVerboseResult) Receive() (map[string]btcjson.GetRawMempoolVerboseResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -804,7 +804,7 @@ func (r FutureGetRawMempoolVerboseResult) Receive() (map[string]btcjson.GetRawMe // See GetRawMempoolVerbose for the blocking version and more details. func (c *Client) GetRawMempoolVerboseAsync() FutureGetRawMempoolVerboseResult { cmd := btcjson.NewGetRawMempoolCmd(btcjson.Bool(true)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetRawMempoolVerbose returns a map of transaction hashes to an associated @@ -818,12 +818,12 @@ func (c *Client) GetRawMempoolVerbose() (map[string]btcjson.GetRawMempoolVerbose // FutureEstimateFeeResult is a future promise to deliver the result of a // EstimateFeeAsync RPC invocation (or an applicable error). -type FutureEstimateFeeResult chan *response +type FutureEstimateFeeResult chan *Response -// Receive waits for the response promised by the future and returns the info +// Receive waits for the Response promised by the future and returns the info // provided by the server. func (r FutureEstimateFeeResult) Receive() (float64, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return -1, err } @@ -845,7 +845,7 @@ func (r FutureEstimateFeeResult) Receive() (float64, error) { // See EstimateFee for the blocking version and more details. func (c *Client) EstimateFeeAsync(numBlocks int64) FutureEstimateFeeResult { cmd := btcjson.NewEstimateFeeCmd(numBlocks) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // EstimateFee provides an estimated fee in bitcoins per kilobyte. @@ -855,12 +855,12 @@ func (c *Client) EstimateFee(numBlocks int64) (float64, error) { // FutureEstimateFeeResult is a future promise to deliver the result of a // EstimateSmartFeeAsync RPC invocation (or an applicable error). -type FutureEstimateSmartFeeResult chan *response +type FutureEstimateSmartFeeResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // estimated fee. func (r FutureEstimateSmartFeeResult) Receive() (*btcjson.EstimateSmartFeeResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -880,7 +880,7 @@ func (r FutureEstimateSmartFeeResult) Receive() (*btcjson.EstimateSmartFeeResult // See EstimateSmartFee for the blocking version and more details. func (c *Client) EstimateSmartFeeAsync(confTarget int64, mode *btcjson.EstimateSmartFeeMode) FutureEstimateSmartFeeResult { cmd := btcjson.NewEstimateSmartFeeCmd(confTarget, mode) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // EstimateSmartFee requests the server to estimate a fee level based on the given parameters. @@ -891,13 +891,13 @@ func (c *Client) EstimateSmartFee(confTarget int64, mode *btcjson.EstimateSmartF // FutureVerifyChainResult is a future promise to deliver the result of a // VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync // invocation (or an applicable error). -type FutureVerifyChainResult chan *response +type FutureVerifyChainResult chan *Response -// Receive waits for the response promised by the future and returns whether +// Receive waits for the Response promised by the future and returns whether // or not the chain verified based on the check level and number of blocks // to verify specified in the original call. func (r FutureVerifyChainResult) Receive() (bool, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return false, err } @@ -918,7 +918,7 @@ func (r FutureVerifyChainResult) Receive() (bool, error) { // See VerifyChain for the blocking version and more details. func (c *Client) VerifyChainAsync() FutureVerifyChainResult { cmd := btcjson.NewVerifyChainCmd(nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // VerifyChain requests the server to verify the block chain database using @@ -936,7 +936,7 @@ func (c *Client) VerifyChain() (bool, error) { // See VerifyChainLevel for the blocking version and more details. func (c *Client) VerifyChainLevelAsync(checkLevel int32) FutureVerifyChainResult { cmd := btcjson.NewVerifyChainCmd(&checkLevel, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // VerifyChainLevel requests the server to verify the block chain database using @@ -959,7 +959,7 @@ func (c *Client) VerifyChainLevel(checkLevel int32) (bool, error) { // See VerifyChainBlocks for the blocking version and more details. func (c *Client) VerifyChainBlocksAsync(checkLevel, numBlocks int32) FutureVerifyChainResult { cmd := btcjson.NewVerifyChainCmd(&checkLevel, &numBlocks) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // VerifyChainBlocks requests the server to verify the block chain database @@ -979,12 +979,12 @@ func (c *Client) VerifyChainBlocks(checkLevel, numBlocks int32) (bool, error) { // FutureGetTxOutResult is a future promise to deliver the result of a // GetTxOutAsync RPC invocation (or an applicable error). -type FutureGetTxOutResult chan *response +type FutureGetTxOutResult chan *Response -// Receive waits for the response promised by the future and returns a +// Receive waits for the Response promised by the future and returns a // transaction given its hash. func (r FutureGetTxOutResult) Receive() (*btcjson.GetTxOutResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1017,7 +1017,7 @@ func (c *Client) GetTxOutAsync(txHash *chainhash.Hash, index uint32, mempool boo } cmd := btcjson.NewGetTxOutCmd(hash, index, &mempool) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetTxOut returns the transaction output info if it's unspent and @@ -1028,12 +1028,12 @@ func (c *Client) GetTxOut(txHash *chainhash.Hash, index uint32, mempool bool) (* // FutureGetTxOutSetInfoResult is a future promise to deliver the result of a // GetTxOutSetInfoAsync RPC invocation (or an applicable error). -type FutureGetTxOutSetInfoResult chan *response +type FutureGetTxOutSetInfoResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // results of GetTxOutSetInfoAsync RPC invocation. func (r FutureGetTxOutSetInfoResult) Receive() (*btcjson.GetTxOutSetInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1055,7 +1055,7 @@ func (r FutureGetTxOutSetInfoResult) Receive() (*btcjson.GetTxOutSetInfoResult, // See GetTxOutSetInfo for the blocking version and more details. func (c *Client) GetTxOutSetInfoAsync() FutureGetTxOutSetInfoResult { cmd := btcjson.NewGetTxOutSetInfoCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetTxOutSetInfo returns the statistics about the unspent transaction output @@ -1069,15 +1069,15 @@ func (c *Client) GetTxOutSetInfo() (*btcjson.GetTxOutSetInfoResult, error) { // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. -type FutureRescanBlocksResult chan *response +type FutureRescanBlocksResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // discovered rescanblocks data. // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. func (r FutureRescanBlocksResult) Receive() ([]btcjson.RescannedBlock, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1106,7 +1106,7 @@ func (c *Client) RescanBlocksAsync(blockHashes []chainhash.Hash) FutureRescanBlo } cmd := btcjson.NewRescanBlocksCmd(strBlockHashes) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // RescanBlocks rescans the blocks identified by blockHashes, in order, using @@ -1121,12 +1121,12 @@ func (c *Client) RescanBlocks(blockHashes []chainhash.Hash) ([]btcjson.Rescanned // FutureInvalidateBlockResult is a future promise to deliver the result of a // InvalidateBlockAsync RPC invocation (or an applicable error). -type FutureInvalidateBlockResult chan *response +type FutureInvalidateBlockResult chan *Response -// Receive waits for the response promised by the future and returns the raw +// Receive waits for the Response promised by the future and returns the raw // block requested from the server given its hash. func (r FutureInvalidateBlockResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1143,7 +1143,7 @@ func (c *Client) InvalidateBlockAsync(blockHash *chainhash.Hash) FutureInvalidat } cmd := btcjson.NewInvalidateBlockCmd(hash) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // InvalidateBlock invalidates a specific block. @@ -1153,12 +1153,12 @@ func (c *Client) InvalidateBlock(blockHash *chainhash.Hash) error { // FutureGetCFilterResult is a future promise to deliver the result of a // GetCFilterAsync RPC invocation (or an applicable error). -type FutureGetCFilterResult chan *response +type FutureGetCFilterResult chan *Response -// Receive waits for the response promised by the future and returns the raw +// Receive waits for the Response promised by the future and returns the raw // filter requested from the server given its block hash. func (r FutureGetCFilterResult) Receive() (*wire.MsgCFilter, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1197,7 +1197,7 @@ func (c *Client) GetCFilterAsync(blockHash *chainhash.Hash, } cmd := btcjson.NewGetCFilterCmd(hash, filterType) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetCFilter returns a raw filter from the server given its block hash. @@ -1208,12 +1208,12 @@ func (c *Client) GetCFilter(blockHash *chainhash.Hash, // FutureGetCFilterHeaderResult is a future promise to deliver the result of a // GetCFilterHeaderAsync RPC invocation (or an applicable error). -type FutureGetCFilterHeaderResult chan *response +type FutureGetCFilterHeaderResult chan *Response -// Receive waits for the response promised by the future and returns the raw +// Receive waits for the Response promised by the future and returns the raw // filter header requested from the server given its block hash. func (r FutureGetCFilterHeaderResult) Receive() (*wire.MsgCFHeaders, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1250,7 +1250,7 @@ func (c *Client) GetCFilterHeaderAsync(blockHash *chainhash.Hash, } cmd := btcjson.NewGetCFilterHeaderCmd(hash, filterType) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetCFilterHeader returns a raw filter header from the server given its block @@ -1262,12 +1262,12 @@ func (c *Client) GetCFilterHeader(blockHash *chainhash.Hash, // FutureGetBlockStatsResult is a future promise to deliver the result of a // GetBlockStatsAsync RPC invocation (or an applicable error). -type FutureGetBlockStatsResult chan *response +type FutureGetBlockStatsResult chan *Response -// Receive waits for the response promised by the future and returns statistics +// Receive waits for the Response promised by the future and returns statistics // of a block at a certain height. func (r FutureGetBlockStatsResult) Receive() (*btcjson.GetBlockStatsResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1292,7 +1292,7 @@ func (c *Client) GetBlockStatsAsync(hashOrHeight interface{}, stats *[]string) F } cmd := btcjson.NewGetBlockStatsCmd(btcjson.HashOrHeight{Value: hashOrHeight}, stats) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBlockStats returns block statistics. First argument specifies height or hash of the target block. @@ -1303,12 +1303,12 @@ func (c *Client) GetBlockStats(hashOrHeight interface{}, stats *[]string) (*btcj // FutureDeriveAddressesResult is a future promise to deliver the result of an // DeriveAddressesAsync RPC invocation (or an applicable error). -type FutureDeriveAddressesResult chan *response +type FutureDeriveAddressesResult chan *Response -// Receive waits for the response promised by the future and derives one or more addresses +// Receive waits for the Response promised by the future and derives one or more addresses // corresponding to the given output descriptor. func (r FutureDeriveAddressesResult) Receive() (*btcjson.DeriveAddressesResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1330,7 +1330,7 @@ func (r FutureDeriveAddressesResult) Receive() (*btcjson.DeriveAddressesResult, // See DeriveAddresses for the blocking version and more details. func (c *Client) DeriveAddressesAsync(descriptor string, descriptorRange *btcjson.DescriptorRange) FutureDeriveAddressesResult { cmd := btcjson.NewDeriveAddressesCmd(descriptor, descriptorRange) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // DeriveAddresses derives one or more addresses corresponding to an output @@ -1342,12 +1342,12 @@ func (c *Client) DeriveAddresses(descriptor string, descriptorRange *btcjson.Des // FutureGetDescriptorInfoResult is a future promise to deliver the result of a // GetDescriptorInfoAsync RPC invocation (or an applicable error). -type FutureGetDescriptorInfoResult chan *response +type FutureGetDescriptorInfoResult chan *Response -// Receive waits for the response promised by the future and returns the analysed +// Receive waits for the Response promised by the future and returns the analysed // info of the descriptor. func (r FutureGetDescriptorInfoResult) Receive() (*btcjson.GetDescriptorInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1369,7 +1369,7 @@ func (r FutureGetDescriptorInfoResult) Receive() (*btcjson.GetDescriptorInfoResu // See GetDescriptorInfo for the blocking version and more details. func (c *Client) GetDescriptorInfoAsync(descriptor string) FutureGetDescriptorInfoResult { cmd := btcjson.NewGetDescriptorInfoCmd(descriptor) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetDescriptorInfo returns the analysed info of a descriptor string, by invoking the diff --git a/rpcclient/examples/customcommand/README.md b/rpcclient/examples/customcommand/README.md new file mode 100644 index 0000000000..0e36d649cc --- /dev/null +++ b/rpcclient/examples/customcommand/README.md @@ -0,0 +1,32 @@ +Custom Command Example +====================== + +This example shows how to use custom commands with the rpcclient package, by +implementing the `name_show` command from Namecoin Core. + +## Running the Example + +The first step is to use `go get` to download and install the rpcclient package: + +```bash +$ go get github.com/btcsuite/btcd/rpcclient +``` + +Next, modify the `main.go` source to specify the correct RPC username and +password for the RPC server of your Namecoin Core node: + +```Go + User: "yourrpcuser", + Pass: "yourrpcpass", +``` + +Finally, navigate to the example's directory and run it with: + +```bash +$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/customcommand +$ go run *.go +``` + +## License + +This example is licensed under the [copyfree](http://copyfree.org) ISC License. diff --git a/rpcclient/examples/customcommand/main.go b/rpcclient/examples/customcommand/main.go new file mode 100644 index 0000000000..1e14c06fe4 --- /dev/null +++ b/rpcclient/examples/customcommand/main.go @@ -0,0 +1,110 @@ +// Copyright (c) 2014-2017 The btcsuite developers +// Copyright (c) 2019-2020 The Namecoin developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package main + +import ( + "encoding/json" + "log" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/rpcclient" +) + +// NameShowCmd defines the name_show JSON-RPC command. +type NameShowCmd struct { + Name string +} + +// NameShowResult models the data from the name_show command. +type NameShowResult struct { + Name string `json:"name"` + NameEncoding string `json:"name_encoding"` + NameError string `json:"name_error"` + Value string `json:"value"` + ValueEncoding string `json:"value_encoding"` + ValueError string `json:"value_error"` + TxID string `json:"txid"` + Vout uint32 `json:"vout"` + Address string `json:"address"` + IsMine bool `json:"ismine"` + Height int32 `json:"height"` + ExpiresIn int32 `json:"expires_in"` + Expired bool `json:"expired"` +} + +// FutureNameShowResult is a future promise to deliver the result +// of a NameShowAsync RPC invocation (or an applicable error). +type FutureNameShowResult chan *rpcclient.Response + +// Receive waits for the Response promised by the future and returns detailed +// information about a name. +func (r FutureNameShowResult) Receive() (*NameShowResult, error) { + res, err := rpcclient.ReceiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a name_show result object + var nameShow NameShowResult + err = json.Unmarshal(res, &nameShow) + if err != nil { + return nil, err + } + + return &nameShow, nil +} + +// NameShowAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See NameShow for the blocking version and more details. +func NameShowAsync(c *rpcclient.Client, name string) FutureNameShowResult { + cmd := &NameShowCmd{ + Name: name, + } + return c.SendCmd(cmd) +} + +// NameShow returns detailed information about a name. +func NameShow(c *rpcclient.Client, name string) (*NameShowResult, error) { + return NameShowAsync(c, name).Receive() +} + +func init() { + // No special flags for commands in this file. + flags := btcjson.UsageFlag(0) + + btcjson.MustRegisterCmd("name_show", (*NameShowCmd)(nil), flags) +} + +func main() { + // Connect to local namecoin core RPC server using HTTP POST mode. + connCfg := &rpcclient.ConnConfig{ + Host: "localhost:8336", + User: "yourrpcuser", + Pass: "yourrpcpass", + HTTPPostMode: true, // Namecoin core only supports HTTP POST mode + DisableTLS: true, // Namecoin core does not provide TLS by default + } + // Notice the notification parameter is nil since notifications are + // not supported in HTTP POST mode. + client, err := rpcclient.New(connCfg, nil) + if err != nil { + log.Fatal(err) + } + defer client.Shutdown() + + // Get the current block count. + result, err := NameShow(client, "d/namecoin") + if err != nil { + log.Fatal(err) + } + + value := result.Value + + log.Printf("Value of d/namecoin: %s", value) +} diff --git a/rpcclient/extensions.go b/rpcclient/extensions.go index d16cd5252e..c8615293e3 100644 --- a/rpcclient/extensions.go +++ b/rpcclient/extensions.go @@ -20,13 +20,13 @@ import ( // FutureDebugLevelResult is a future promise to deliver the result of a // DebugLevelAsync RPC invocation (or an applicable error). -type FutureDebugLevelResult chan *response +type FutureDebugLevelResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of setting the debug logging level to the passed level specification or the // list of of the available subsystems for the special keyword 'show'. func (r FutureDebugLevelResult) Receive() (string, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return "", err } @@ -49,7 +49,7 @@ func (r FutureDebugLevelResult) Receive() (string, error) { // NOTE: This is a btcd extension. func (c *Client) DebugLevelAsync(levelSpec string) FutureDebugLevelResult { cmd := btcjson.NewDebugLevelCmd(levelSpec) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // DebugLevel dynamically sets the debug logging level to the passed level @@ -68,11 +68,11 @@ func (c *Client) DebugLevel(levelSpec string) (string, error) { // FutureCreateEncryptedWalletResult is a future promise to deliver the error // result of a CreateEncryptedWalletAsync RPC invocation. -type FutureCreateEncryptedWalletResult chan *response +type FutureCreateEncryptedWalletResult chan *Response -// Receive waits for and returns the error response promised by the future. +// Receive waits for and returns the error Response promised by the future. func (r FutureCreateEncryptedWalletResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -85,7 +85,7 @@ func (r FutureCreateEncryptedWalletResult) Receive() error { // NOTE: This is a btcwallet extension. func (c *Client) CreateEncryptedWalletAsync(passphrase string) FutureCreateEncryptedWalletResult { cmd := btcjson.NewCreateEncryptedWalletCmd(passphrase) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // CreateEncryptedWallet requests the creation of an encrypted wallet. Wallets @@ -102,12 +102,12 @@ func (c *Client) CreateEncryptedWallet(passphrase string) error { // FutureListAddressTransactionsResult is a future promise to deliver the result // of a ListAddressTransactionsAsync RPC invocation (or an applicable error). -type FutureListAddressTransactionsResult chan *response +type FutureListAddressTransactionsResult chan *Response -// Receive waits for the response promised by the future and returns information +// Receive waits for the Response promised by the future and returns information // about all transactions associated with the provided addresses. func (r FutureListAddressTransactionsResult) Receive() ([]btcjson.ListTransactionsResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -135,7 +135,7 @@ func (c *Client) ListAddressTransactionsAsync(addresses []btcutil.Address, accou addrs = append(addrs, addr.EncodeAddress()) } cmd := btcjson.NewListAddressTransactionsCmd(addrs, &account) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListAddressTransactions returns information about all transactions associated @@ -148,12 +148,12 @@ func (c *Client) ListAddressTransactions(addresses []btcutil.Address, account st // FutureGetBestBlockResult is a future promise to deliver the result of a // GetBestBlockAsync RPC invocation (or an applicable error). -type FutureGetBestBlockResult chan *response +type FutureGetBestBlockResult chan *Response -// Receive waits for the response promised by the future and returns the hash +// Receive waits for the Response promised by the future and returns the hash // and height of the block in the longest (best) chain. func (r FutureGetBestBlockResult) Receive() (*chainhash.Hash, int32, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, 0, err } @@ -183,7 +183,7 @@ func (r FutureGetBestBlockResult) Receive() (*chainhash.Hash, int32, error) { // NOTE: This is a btcd extension. func (c *Client) GetBestBlockAsync() FutureGetBestBlockResult { cmd := btcjson.NewGetBestBlockCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBestBlock returns the hash and height of the block in the longest (best) @@ -196,12 +196,12 @@ func (c *Client) GetBestBlock() (*chainhash.Hash, int32, error) { // FutureGetCurrentNetResult is a future promise to deliver the result of a // GetCurrentNetAsync RPC invocation (or an applicable error). -type FutureGetCurrentNetResult chan *response +type FutureGetCurrentNetResult chan *Response -// Receive waits for the response promised by the future and returns the network +// Receive waits for the Response promised by the future and returns the network // the server is running on. func (r FutureGetCurrentNetResult) Receive() (wire.BitcoinNet, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -225,7 +225,7 @@ func (r FutureGetCurrentNetResult) Receive() (wire.BitcoinNet, error) { // NOTE: This is a btcd extension. func (c *Client) GetCurrentNetAsync() FutureGetCurrentNetResult { cmd := btcjson.NewGetCurrentNetCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetCurrentNet returns the network the server is running on. @@ -240,15 +240,15 @@ func (c *Client) GetCurrentNet() (wire.BitcoinNet, error) { // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. -type FutureGetHeadersResult chan *response +type FutureGetHeadersResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // getheaders result. // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -292,7 +292,7 @@ func (c *Client) GetHeadersAsync(blockLocators []chainhash.Hash, hashStop *chain hash = hashStop.String() } cmd := btcjson.NewGetHeadersCmd(locators, hash) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetHeaders mimics the wire protocol getheaders and headers messages by @@ -307,12 +307,12 @@ func (c *Client) GetHeaders(blockLocators []chainhash.Hash, hashStop *chainhash. // FutureExportWatchingWalletResult is a future promise to deliver the result of // an ExportWatchingWalletAsync RPC invocation (or an applicable error). -type FutureExportWatchingWalletResult chan *response +type FutureExportWatchingWalletResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // exported wallet. func (r FutureExportWatchingWalletResult) Receive() ([]byte, []byte, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, nil, err } @@ -361,7 +361,7 @@ func (r FutureExportWatchingWalletResult) Receive() ([]byte, []byte, error) { // NOTE: This is a btcwallet extension. func (c *Client) ExportWatchingWalletAsync(account string) FutureExportWatchingWalletResult { cmd := btcjson.NewExportWatchingWalletCmd(&account, btcjson.Bool(true)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ExportWatchingWallet returns the raw bytes for a watching-only version of @@ -376,12 +376,12 @@ func (c *Client) ExportWatchingWallet(account string) ([]byte, []byte, error) { // FutureSessionResult is a future promise to deliver the result of a // SessionAsync RPC invocation (or an applicable error). -type FutureSessionResult chan *response +type FutureSessionResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // session result. func (r FutureSessionResult) Receive() (*btcjson.SessionResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -410,7 +410,7 @@ func (c *Client) SessionAsync() FutureSessionResult { } cmd := btcjson.NewSessionCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // Session returns details regarding a websocket client's current connection. @@ -427,16 +427,16 @@ func (c *Client) Session() (*btcjson.SessionResult, error) { // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. -type FutureVersionResult chan *response +type FutureVersionResult chan *Response -// Receive waits for the response promised by the future and returns the version +// Receive waits for the Response promised by the future and returns the version // result. // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. func (r FutureVersionResult) Receive() (map[string]btcjson.VersionResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -461,7 +461,7 @@ func (r FutureVersionResult) Receive() (map[string]btcjson.VersionResult, // github.com/decred/dcrrpcclient. func (c *Client) VersionAsync() FutureVersionResult { cmd := btcjson.NewVersionCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // Version returns information about the server's JSON-RPC API versions. diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 798f027911..7255289282 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -103,7 +103,7 @@ type jsonRequest struct { method string cmd interface{} marshalledJSON []byte - responseChan chan *response + responseChan chan *Response } // BackendVersion represents the version of the backend the client is currently @@ -300,13 +300,13 @@ func (c *Client) trackRegisteredNtfns(cmd interface{}) { // FutureGetBulkResult waits for the responses promised by the future // and returns them in a channel -type FutureGetBulkResult chan *response +type FutureGetBulkResult chan *Response // Receive waits for the response promised by the future and returns an map // of results by request id func (r FutureGetBulkResult) Receive() (BulkResult, error) { m := make(BulkResult) - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -357,9 +357,9 @@ type rawResponse struct { Error *btcjson.RPCError `json:"error"` } -// response is the raw bytes of a JSON-RPC result, or the error if the response +// Response is the raw bytes of a JSON-RPC result, or the error if the response // error object was non-null. -type response struct { +type Response struct { result []byte err error } @@ -440,7 +440,7 @@ func (c *Client) handleMessage(msg []byte) { // Deliver the response. result, err := in.rawResponse.result() - request.responseChan <- &response{result: result, err: err} + request.responseChan <- &Response{result: result, err: err} } // shouldLogReadError returns whether or not the passed error, which is expected @@ -770,7 +770,7 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) { log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id) httpResponse, err := c.httpClient.Do(details.httpRequest) if err != nil { - jReq.responseChan <- &response{err: err} + jReq.responseChan <- &Response{err: err} return } @@ -779,7 +779,7 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) { httpResponse.Body.Close() if err != nil { err = fmt.Errorf("error reading json reply: %v", err) - jReq.responseChan <- &response{err: err} + jReq.responseChan <- &Response{err: err} return } @@ -797,7 +797,7 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) { // response bytes. err = fmt.Errorf("status code: %d, response: %q", httpResponse.StatusCode, string(respBytes)) - jReq.responseChan <- &response{err: err} + jReq.responseChan <- &Response{err: err} return } var res []byte @@ -808,7 +808,7 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) { } else { res, err = resp.result() } - jReq.responseChan <- &response{result: res, err: err} + jReq.responseChan <- &Response{result: res, err: err} } // sendPostHandler handles all outgoing messages when the client is running @@ -835,7 +835,7 @@ cleanup: for { select { case details := <-c.sendPostChan: - details.jsonRequest.responseChan <- &response{ + details.jsonRequest.responseChan <- &Response{ result: nil, err: ErrClientShutdown, } @@ -856,7 +856,7 @@ func (c *Client) sendPostRequest(httpReq *http.Request, jReq *jsonRequest) { // Don't send the message if shutting down. select { case <-c.shutdown: - jReq.responseChan <- &response{result: nil, err: ErrClientShutdown} + jReq.responseChan <- &Response{result: nil, err: ErrClientShutdown} default: } @@ -869,17 +869,17 @@ func (c *Client) sendPostRequest(httpReq *http.Request, jReq *jsonRequest) { // newFutureError returns a new future result channel that already has the // passed error waitin on the channel with the reply set to nil. This is useful // to easily return errors from the various Async functions. -func newFutureError(err error) chan *response { - responseChan := make(chan *response, 1) - responseChan <- &response{err: err} +func newFutureError(err error) chan *Response { + responseChan := make(chan *Response, 1) + responseChan <- &Response{err: err} return responseChan } -// receiveFuture receives from the passed futureResult channel to extract a +// ReceiveFuture receives from the passed futureResult channel to extract a // reply or any errors. The examined errors include an error in the // futureResult and the error in the reply from the server. This will block // until the result is available on the passed channel. -func receiveFuture(f chan *response) ([]byte, error) { +func ReceiveFuture(f chan *Response) ([]byte, error) { // Wait for a response on the returned channel. r := <-f return r.result, r.err @@ -900,7 +900,7 @@ func (c *Client) sendPost(jReq *jsonRequest) { bodyReader := bytes.NewReader(jReq.marshalledJSON) httpReq, err := http.NewRequest("POST", url, bodyReader) if err != nil { - jReq.responseChan <- &response{result: nil, err: err} + jReq.responseChan <- &Response{result: nil, err: err} return } httpReq.Close = true @@ -912,7 +912,7 @@ func (c *Client) sendPost(jReq *jsonRequest) { // Configure basic access authorization. user, pass, err := c.config.getAuth() if err != nil { - jReq.responseChan <- &response{result: nil, err: err} + jReq.responseChan <- &Response{result: nil, err: err} return } httpReq.SetBasicAuth(user, pass) @@ -945,7 +945,7 @@ func (c *Client) sendRequest(jReq *jsonRequest) { select { case <-c.connEstablished: default: - jReq.responseChan <- &response{err: ErrClientNotConnected} + jReq.responseChan <- &Response{err: ErrClientNotConnected} return } @@ -954,18 +954,18 @@ func (c *Client) sendRequest(jReq *jsonRequest) { // channel. Then send the marshalled request via the websocket // connection. if err := c.addRequest(jReq); err != nil { - jReq.responseChan <- &response{err: err} + jReq.responseChan <- &Response{err: err} return } log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id) c.sendMessage(jReq.marshalledJSON) } -// sendCmd sends the passed command to the associated server and returns a +// SendCmd sends the passed command to the associated server and returns a // response channel on which the reply will be delivered at some point in the // future. It handles both websocket and HTTP POST mode depending on the // configuration of the client. -func (c *Client) sendCmd(cmd interface{}) chan *response { +func (c *Client) SendCmd(cmd interface{}) chan *Response { rpcVersion := btcjson.RpcVersion1 if c.batch { rpcVersion = btcjson.RpcVersion2 @@ -984,7 +984,7 @@ func (c *Client) sendCmd(cmd interface{}) chan *response { } // Generate the request and send it along with a channel to respond on. - responseChan := make(chan *response, 1) + responseChan := make(chan *Response, 1) jReq := &jsonRequest{ id: id, method: method, @@ -1004,7 +1004,7 @@ func (c *Client) sendCmd(cmd interface{}) chan *response { func (c *Client) sendCmdAndWait(cmd interface{}) (interface{}, error) { // Marshal the command to JSON-RPC, send it to the connected server, and // wait for a response on the returned channel. - return receiveFuture(c.sendCmd(cmd)) + return ReceiveFuture(c.SendCmd(cmd)) } // Disconnected returns whether or not the server is disconnected. If a @@ -1085,7 +1085,7 @@ func (c *Client) Disconnect() { if c.config.DisableAutoReconnect { for e := c.requestList.Front(); e != nil; e = e.Next() { req := e.Value.(*jsonRequest) - req.responseChan <- &response{ + req.responseChan <- &Response{ result: nil, err: ErrClientDisconnect, } @@ -1113,7 +1113,7 @@ func (c *Client) Shutdown() { // Send the ErrClientShutdown error to any pending requests. for e := c.requestList.Front(); e != nil; e = e.Next() { req := e.Value.(*jsonRequest) - req.responseChan <- &response{ + req.responseChan <- &Response{ result: nil, err: ErrClientShutdown, } @@ -1623,7 +1623,7 @@ func (c *Client) BackendVersion() (BackendVersion, error) { func (c *Client) sendAsync() FutureGetBulkResult { // convert the array of marshalled json requests to a single request we can send - responseChan := make(chan *response, 1) + responseChan := make(chan *Response, 1) marshalledRequest := []byte("[") for iter := c.batchList.Front(); iter != nil; iter = iter.Next() { request := iter.Value.(*jsonRequest) @@ -1678,7 +1678,7 @@ func (c *Client) Send() error { requestError = individualResult.Error } - result := response{ + result := Response{ result: fullResult, err: requestError, } diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 431054e155..15473e24be 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -16,12 +16,12 @@ import ( // FutureGenerateResult is a future promise to deliver the result of a // GenerateAsync RPC invocation (or an applicable error). -type FutureGenerateResult chan *response +type FutureGenerateResult chan *Response -// Receive waits for the response promised by the future and returns a list of +// Receive waits for the Response promised by the future and returns a list of // block hashes generated by the call. func (r FutureGenerateResult) Receive() ([]*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -53,7 +53,7 @@ func (r FutureGenerateResult) Receive() ([]*chainhash.Hash, error) { // See Generate for the blocking version and more details. func (c *Client) GenerateAsync(numBlocks uint32) FutureGenerateResult { cmd := btcjson.NewGenerateCmd(numBlocks) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // Generate generates numBlocks blocks and returns their hashes. @@ -63,12 +63,12 @@ func (c *Client) Generate(numBlocks uint32) ([]*chainhash.Hash, error) { // FutureGenerateToAddressResult is a future promise to deliver the result of a // GenerateToAddressResult RPC invocation (or an applicable error). -type FutureGenerateToAddressResult chan *response +type FutureGenerateToAddressResult chan *Response -// Receive waits for the response promised by the future and returns the hashes of +// Receive waits for the Response promised by the future and returns the hashes of // of the generated blocks. func (f FutureGenerateToAddressResult) Receive() ([]*chainhash.Hash, error) { - res, err := receiveFuture(f) + res, err := ReceiveFuture(f) if err != nil { return nil, err } @@ -100,7 +100,7 @@ func (f FutureGenerateToAddressResult) Receive() ([]*chainhash.Hash, error) { // See GenerateToAddress for the blocking version and more details. func (c *Client) GenerateToAddressAsync(numBlocks int64, address btcutil.Address, maxTries *int64) FutureGenerateToAddressResult { cmd := btcjson.NewGenerateToAddressCmd(numBlocks, address.EncodeAddress(), maxTries) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GenerateToAddress generates numBlocks blocks to the given address and returns their hashes. @@ -110,12 +110,12 @@ func (c *Client) GenerateToAddress(numBlocks int64, address btcutil.Address, max // FutureGetGenerateResult is a future promise to deliver the result of a // GetGenerateAsync RPC invocation (or an applicable error). -type FutureGetGenerateResult chan *response +type FutureGetGenerateResult chan *Response -// Receive waits for the response promised by the future and returns true if the +// Receive waits for the Response promised by the future and returns true if the // server is set to mine, otherwise false. func (r FutureGetGenerateResult) Receive() (bool, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return false, err } @@ -137,7 +137,7 @@ func (r FutureGetGenerateResult) Receive() (bool, error) { // See GetGenerate for the blocking version and more details. func (c *Client) GetGenerateAsync() FutureGetGenerateResult { cmd := btcjson.NewGetGenerateCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetGenerate returns true if the server is set to mine, otherwise false. @@ -147,12 +147,12 @@ func (c *Client) GetGenerate() (bool, error) { // FutureSetGenerateResult is a future promise to deliver the result of a // SetGenerateAsync RPC invocation (or an applicable error). -type FutureSetGenerateResult chan *response +type FutureSetGenerateResult chan *Response -// Receive waits for the response promised by the future and returns an error if +// Receive waits for the Response promised by the future and returns an error if // any occurred when setting the server to generate coins (mine) or not. func (r FutureSetGenerateResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -163,7 +163,7 @@ func (r FutureSetGenerateResult) Receive() error { // See SetGenerate for the blocking version and more details. func (c *Client) SetGenerateAsync(enable bool, numCPUs int) FutureSetGenerateResult { cmd := btcjson.NewSetGenerateCmd(enable, &numCPUs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SetGenerate sets the server to generate coins (mine) or not. @@ -173,13 +173,13 @@ func (c *Client) SetGenerate(enable bool, numCPUs int) error { // FutureGetHashesPerSecResult is a future promise to deliver the result of a // GetHashesPerSecAsync RPC invocation (or an applicable error). -type FutureGetHashesPerSecResult chan *response +type FutureGetHashesPerSecResult chan *Response -// Receive waits for the response promised by the future and returns a recent +// Receive waits for the Response promised by the future and returns a recent // hashes per second performance measurement while generating coins (mining). // Zero is returned if the server is not mining. func (r FutureGetHashesPerSecResult) Receive() (int64, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return -1, err } @@ -201,7 +201,7 @@ func (r FutureGetHashesPerSecResult) Receive() (int64, error) { // See GetHashesPerSec for the blocking version and more details. func (c *Client) GetHashesPerSecAsync() FutureGetHashesPerSecResult { cmd := btcjson.NewGetHashesPerSecCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetHashesPerSec returns a recent hashes per second performance measurement @@ -213,12 +213,12 @@ func (c *Client) GetHashesPerSec() (int64, error) { // FutureGetMiningInfoResult is a future promise to deliver the result of a // GetMiningInfoAsync RPC invocation (or an applicable error). -type FutureGetMiningInfoResult chan *response +type FutureGetMiningInfoResult chan *Response -// Receive waits for the response promised by the future and returns the mining +// Receive waits for the Response promised by the future and returns the mining // information. func (r FutureGetMiningInfoResult) Receive() (*btcjson.GetMiningInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -240,7 +240,7 @@ func (r FutureGetMiningInfoResult) Receive() (*btcjson.GetMiningInfoResult, erro // See GetMiningInfo for the blocking version and more details. func (c *Client) GetMiningInfoAsync() FutureGetMiningInfoResult { cmd := btcjson.NewGetMiningInfoCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetMiningInfo returns mining information. @@ -250,13 +250,13 @@ func (c *Client) GetMiningInfo() (*btcjson.GetMiningInfoResult, error) { // FutureGetNetworkHashPS is a future promise to deliver the result of a // GetNetworkHashPSAsync RPC invocation (or an applicable error). -type FutureGetNetworkHashPS chan *response +type FutureGetNetworkHashPS chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // estimated network hashes per second for the block heights provided by the // parameters. func (r FutureGetNetworkHashPS) Receive() (int64, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return -1, err } @@ -278,7 +278,7 @@ func (r FutureGetNetworkHashPS) Receive() (int64, error) { // See GetNetworkHashPS for the blocking version and more details. func (c *Client) GetNetworkHashPSAsync() FutureGetNetworkHashPS { cmd := btcjson.NewGetNetworkHashPSCmd(nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetNetworkHashPS returns the estimated network hashes per second using the @@ -297,7 +297,7 @@ func (c *Client) GetNetworkHashPS() (int64, error) { // See GetNetworkHashPS2 for the blocking version and more details. func (c *Client) GetNetworkHashPS2Async(blocks int) FutureGetNetworkHashPS { cmd := btcjson.NewGetNetworkHashPSCmd(&blocks, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetNetworkHashPS2 returns the estimated network hashes per second for the @@ -318,7 +318,7 @@ func (c *Client) GetNetworkHashPS2(blocks int) (int64, error) { // See GetNetworkHashPS3 for the blocking version and more details. func (c *Client) GetNetworkHashPS3Async(blocks, height int) FutureGetNetworkHashPS { cmd := btcjson.NewGetNetworkHashPSCmd(&blocks, &height) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetNetworkHashPS3 returns the estimated network hashes per second for the @@ -333,12 +333,12 @@ func (c *Client) GetNetworkHashPS3(blocks, height int) (int64, error) { // FutureGetWork is a future promise to deliver the result of a // GetWorkAsync RPC invocation (or an applicable error). -type FutureGetWork chan *response +type FutureGetWork chan *Response -// Receive waits for the response promised by the future and returns the hash +// Receive waits for the Response promised by the future and returns the hash // data to work on. func (r FutureGetWork) Receive() (*btcjson.GetWorkResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -360,7 +360,7 @@ func (r FutureGetWork) Receive() (*btcjson.GetWorkResult, error) { // See GetWork for the blocking version and more details. func (c *Client) GetWorkAsync() FutureGetWork { cmd := btcjson.NewGetWorkCmd(nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetWork returns hash data to work on. @@ -372,12 +372,12 @@ func (c *Client) GetWork() (*btcjson.GetWorkResult, error) { // FutureGetWorkSubmit is a future promise to deliver the result of a // GetWorkSubmitAsync RPC invocation (or an applicable error). -type FutureGetWorkSubmit chan *response +type FutureGetWorkSubmit chan *Response -// Receive waits for the response promised by the future and returns whether +// Receive waits for the Response promised by the future and returns whether // or not the submitted block header was accepted. func (r FutureGetWorkSubmit) Receive() (bool, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return false, err } @@ -399,7 +399,7 @@ func (r FutureGetWorkSubmit) Receive() (bool, error) { // See GetWorkSubmit for the blocking version and more details. func (c *Client) GetWorkSubmitAsync(data string) FutureGetWorkSubmit { cmd := btcjson.NewGetWorkCmd(&data) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetWorkSubmit submits a block header which is a solution to previously @@ -412,12 +412,12 @@ func (c *Client) GetWorkSubmit(data string) (bool, error) { // FutureSubmitBlockResult is a future promise to deliver the result of a // SubmitBlockAsync RPC invocation (or an applicable error). -type FutureSubmitBlockResult chan *response +type FutureSubmitBlockResult chan *Response -// Receive waits for the response promised by the future and returns an error if +// Receive waits for the Response promised by the future and returns an error if // any occurred when submitting the block. func (r FutureSubmitBlockResult) Receive() error { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return err } @@ -453,7 +453,7 @@ func (c *Client) SubmitBlockAsync(block *btcutil.Block, options *btcjson.SubmitB } cmd := btcjson.NewSubmitBlockCmd(blockHex, options) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SubmitBlock attempts to submit a new block into the bitcoin network. @@ -463,12 +463,12 @@ func (c *Client) SubmitBlock(block *btcutil.Block, options *btcjson.SubmitBlockO // FutureGetBlockTemplateResponse is a future promise to deliver the result of a // GetBlockTemplateAsync RPC invocation (or an applicable error). -type FutureGetBlockTemplateResponse chan *response +type FutureGetBlockTemplateResponse chan *Response -// Receive waits for the response promised by the future and returns an error if +// Receive waits for the Response promised by the future and returns an error if // any occurred when retrieving the block template. func (r FutureGetBlockTemplateResponse) Receive() (*btcjson.GetBlockTemplateResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -490,7 +490,7 @@ func (r FutureGetBlockTemplateResponse) Receive() (*btcjson.GetBlockTemplateResu // See GetBlockTemplate for the blocking version and more details. func (c *Client) GetBlockTemplateAsync(req *btcjson.TemplateRequest) FutureGetBlockTemplateResponse { cmd := btcjson.NewGetBlockTemplateCmd(req) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBlockTemplate returns a new block template for mining. diff --git a/rpcclient/net.go b/rpcclient/net.go index 8c191ff66f..da2006c224 100644 --- a/rpcclient/net.go +++ b/rpcclient/net.go @@ -35,12 +35,12 @@ func (cmd AddNodeCommand) String() string { // FutureAddNodeResult is a future promise to deliver the result of an // AddNodeAsync RPC invocation (or an applicable error). -type FutureAddNodeResult chan *response +type FutureAddNodeResult chan *Response -// Receive waits for the response promised by the future and returns an error if +// Receive waits for the Response promised by the future and returns an error if // any occurred when performing the specified command. func (r FutureAddNodeResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -51,7 +51,7 @@ func (r FutureAddNodeResult) Receive() error { // See AddNode for the blocking version and more details. func (c *Client) AddNodeAsync(host string, command AddNodeCommand) FutureAddNodeResult { cmd := btcjson.NewAddNodeCmd(host, btcjson.AddNodeSubCmd(command)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // AddNode attempts to perform the passed command on the passed persistent peer. @@ -65,12 +65,12 @@ func (c *Client) AddNode(host string, command AddNodeCommand) error { // FutureNodeResult is a future promise to deliver the result of a NodeAsync // RPC invocation (or an applicable error). -type FutureNodeResult chan *response +type FutureNodeResult chan *Response -// Receive waits for the response promised by the future and returns an error if +// Receive waits for the Response promised by the future and returns an error if // any occurred when performing the specified command. func (r FutureNodeResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -82,7 +82,7 @@ func (r FutureNodeResult) Receive() error { func (c *Client) NodeAsync(command btcjson.NodeSubCmd, host string, connectSubCmd *string) FutureNodeResult { cmd := btcjson.NewNodeCmd(command, host, connectSubCmd) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // Node attempts to perform the passed node command on the host. @@ -99,12 +99,12 @@ func (c *Client) Node(command btcjson.NodeSubCmd, host string, // FutureGetAddedNodeInfoResult is a future promise to deliver the result of a // GetAddedNodeInfoAsync RPC invocation (or an applicable error). -type FutureGetAddedNodeInfoResult chan *response +type FutureGetAddedNodeInfoResult chan *Response -// Receive waits for the response promised by the future and returns information +// Receive waits for the Response promised by the future and returns information // about manually added (persistent) peers. func (r FutureGetAddedNodeInfoResult) Receive() ([]btcjson.GetAddedNodeInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -126,7 +126,7 @@ func (r FutureGetAddedNodeInfoResult) Receive() ([]btcjson.GetAddedNodeInfoResul // See GetAddedNodeInfo for the blocking version and more details. func (c *Client) GetAddedNodeInfoAsync(peer string) FutureGetAddedNodeInfoResult { cmd := btcjson.NewGetAddedNodeInfoCmd(true, &peer) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetAddedNodeInfo returns information about manually added (persistent) peers. @@ -139,12 +139,12 @@ func (c *Client) GetAddedNodeInfo(peer string) ([]btcjson.GetAddedNodeInfoResult // FutureGetAddedNodeInfoNoDNSResult is a future promise to deliver the result // of a GetAddedNodeInfoNoDNSAsync RPC invocation (or an applicable error). -type FutureGetAddedNodeInfoNoDNSResult chan *response +type FutureGetAddedNodeInfoNoDNSResult chan *Response -// Receive waits for the response promised by the future and returns a list of +// Receive waits for the Response promised by the future and returns a list of // manually added (persistent) peers. func (r FutureGetAddedNodeInfoNoDNSResult) Receive() ([]string, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -166,7 +166,7 @@ func (r FutureGetAddedNodeInfoNoDNSResult) Receive() ([]string, error) { // See GetAddedNodeInfoNoDNS for the blocking version and more details. func (c *Client) GetAddedNodeInfoNoDNSAsync(peer string) FutureGetAddedNodeInfoNoDNSResult { cmd := btcjson.NewGetAddedNodeInfoCmd(false, &peer) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetAddedNodeInfoNoDNS returns a list of manually added (persistent) peers. @@ -180,12 +180,12 @@ func (c *Client) GetAddedNodeInfoNoDNS(peer string) ([]string, error) { // FutureGetConnectionCountResult is a future promise to deliver the result // of a GetConnectionCountAsync RPC invocation (or an applicable error). -type FutureGetConnectionCountResult chan *response +type FutureGetConnectionCountResult chan *Response -// Receive waits for the response promised by the future and returns the number +// Receive waits for the Response promised by the future and returns the number // of active connections to other peers. func (r FutureGetConnectionCountResult) Receive() (int64, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -207,7 +207,7 @@ func (r FutureGetConnectionCountResult) Receive() (int64, error) { // See GetConnectionCount for the blocking version and more details. func (c *Client) GetConnectionCountAsync() FutureGetConnectionCountResult { cmd := btcjson.NewGetConnectionCountCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetConnectionCount returns the number of active connections to other peers. @@ -217,12 +217,12 @@ func (c *Client) GetConnectionCount() (int64, error) { // FuturePingResult is a future promise to deliver the result of a PingAsync RPC // invocation (or an applicable error). -type FuturePingResult chan *response +type FuturePingResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of queueing a ping to be sent to each connected peer. func (r FuturePingResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -233,7 +233,7 @@ func (r FuturePingResult) Receive() error { // See Ping for the blocking version and more details. func (c *Client) PingAsync() FuturePingResult { cmd := btcjson.NewPingCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // Ping queues a ping to be sent to each connected peer. @@ -246,12 +246,12 @@ func (c *Client) Ping() error { // FutureGetNetworkInfoResult is a future promise to deliver the result of a // GetNetworkInfoAsync RPC invocation (or an applicable error). -type FutureGetNetworkInfoResult chan *response +type FutureGetNetworkInfoResult chan *Response -// Receive waits for the response promised by the future and returns data about +// Receive waits for the Response promised by the future and returns data about // the current network. func (r FutureGetNetworkInfoResult) Receive() (*btcjson.GetNetworkInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -273,7 +273,7 @@ func (r FutureGetNetworkInfoResult) Receive() (*btcjson.GetNetworkInfoResult, er // See GetNetworkInfo for the blocking version and more details. func (c *Client) GetNetworkInfoAsync() FutureGetNetworkInfoResult { cmd := btcjson.NewGetNetworkInfoCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetNetworkInfo returns data about the current network. @@ -283,12 +283,12 @@ func (c *Client) GetNetworkInfo() (*btcjson.GetNetworkInfoResult, error) { // FutureGetNodeAddressesResult is a future promise to deliver the result of a // GetNodeAddressesAsync RPC invocation (or an applicable error). -type FutureGetNodeAddressesResult chan *response +type FutureGetNodeAddressesResult chan *Response -// Receive waits for the response promised by the future and returns data about +// Receive waits for the Response promised by the future and returns data about // known node addresses. func (r FutureGetNodeAddressesResult) Receive() ([]btcjson.GetNodeAddressesResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -310,7 +310,7 @@ func (r FutureGetNodeAddressesResult) Receive() ([]btcjson.GetNodeAddressesResul // See GetNodeAddresses for the blocking version and more details. func (c *Client) GetNodeAddressesAsync(count *int32) FutureGetNodeAddressesResult { cmd := btcjson.NewGetNodeAddressesCmd(count) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetNodeAddresses returns data about known node addresses. @@ -320,12 +320,12 @@ func (c *Client) GetNodeAddresses(count *int32) ([]btcjson.GetNodeAddressesResul // FutureGetPeerInfoResult is a future promise to deliver the result of a // GetPeerInfoAsync RPC invocation (or an applicable error). -type FutureGetPeerInfoResult chan *response +type FutureGetPeerInfoResult chan *Response -// Receive waits for the response promised by the future and returns data about +// Receive waits for the Response promised by the future and returns data about // each connected network peer. func (r FutureGetPeerInfoResult) Receive() ([]btcjson.GetPeerInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -347,7 +347,7 @@ func (r FutureGetPeerInfoResult) Receive() ([]btcjson.GetPeerInfoResult, error) // See GetPeerInfo for the blocking version and more details. func (c *Client) GetPeerInfoAsync() FutureGetPeerInfoResult { cmd := btcjson.NewGetPeerInfoCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetPeerInfo returns data about each connected network peer. @@ -357,12 +357,12 @@ func (c *Client) GetPeerInfo() ([]btcjson.GetPeerInfoResult, error) { // FutureGetNetTotalsResult is a future promise to deliver the result of a // GetNetTotalsAsync RPC invocation (or an applicable error). -type FutureGetNetTotalsResult chan *response +type FutureGetNetTotalsResult chan *Response -// Receive waits for the response promised by the future and returns network +// Receive waits for the Response promised by the future and returns network // traffic statistics. func (r FutureGetNetTotalsResult) Receive() (*btcjson.GetNetTotalsResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -384,7 +384,7 @@ func (r FutureGetNetTotalsResult) Receive() (*btcjson.GetNetTotalsResult, error) // See GetNetTotals for the blocking version and more details. func (c *Client) GetNetTotalsAsync() FutureGetNetTotalsResult { cmd := btcjson.NewGetNetTotalsCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetNetTotals returns network traffic statistics. diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 1feb755605..6879099acd 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -69,9 +69,9 @@ func newNotificationState() *notificationState { // result waiting on the channel with the reply set to nil. This is useful // to ignore things such as notifications when the caller didn't specify any // notification handlers. -func newNilFutureResult() chan *response { - responseChan := make(chan *response, 1) - responseChan <- &response{result: nil, err: nil} +func newNilFutureResult() chan *Response { + responseChan := make(chan *Response, 1) + responseChan <- &Response{result: nil, err: nil} return responseChan } @@ -856,12 +856,12 @@ func parseWalletLockStateNtfnParams(params []json.RawMessage) (account string, // FutureNotifyBlocksResult is a future promise to deliver the result of a // NotifyBlocksAsync RPC invocation (or an applicable error). -type FutureNotifyBlocksResult chan *response +type FutureNotifyBlocksResult chan *Response -// Receive waits for the response promised by the future and returns an error +// Receive waits for the Response promised by the future and returns an error // if the registration was not successful. func (r FutureNotifyBlocksResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -885,7 +885,7 @@ func (c *Client) NotifyBlocksAsync() FutureNotifyBlocksResult { } cmd := btcjson.NewNotifyBlocksCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // NotifyBlocks registers the client to receive notifications when blocks are @@ -906,12 +906,12 @@ func (c *Client) NotifyBlocks() error { // NotifySpentAsync RPC invocation (or an applicable error). // // Deprecated: Use FutureLoadTxFilterResult instead. -type FutureNotifySpentResult chan *response +type FutureNotifySpentResult chan *Response -// Receive waits for the response promised by the future and returns an error +// Receive waits for the Response promised by the future and returns an error // if the registration was not successful. func (r FutureNotifySpentResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -931,7 +931,7 @@ func (c *Client) notifySpentInternal(outpoints []btcjson.OutPoint) FutureNotifyS } cmd := btcjson.NewNotifySpentCmd(outpoints) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // newOutPointFromWire constructs the btcjson representation of a transaction @@ -969,7 +969,7 @@ func (c *Client) NotifySpentAsync(outpoints []*wire.OutPoint) FutureNotifySpentR ops = append(ops, newOutPointFromWire(outpoint)) } cmd := btcjson.NewNotifySpentCmd(ops) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // NotifySpent registers the client to receive notifications when the passed @@ -990,12 +990,12 @@ func (c *Client) NotifySpent(outpoints []*wire.OutPoint) error { // FutureNotifyNewTransactionsResult is a future promise to deliver the result // of a NotifyNewTransactionsAsync RPC invocation (or an applicable error). -type FutureNotifyNewTransactionsResult chan *response +type FutureNotifyNewTransactionsResult chan *Response -// Receive waits for the response promised by the future and returns an error +// Receive waits for the Response promised by the future and returns an error // if the registration was not successful. func (r FutureNotifyNewTransactionsResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1019,7 +1019,7 @@ func (c *Client) NotifyNewTransactionsAsync(verbose bool) FutureNotifyNewTransac } cmd := btcjson.NewNotifyNewTransactionsCmd(&verbose) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // NotifyNewTransactions registers the client to receive notifications every @@ -1041,12 +1041,12 @@ func (c *Client) NotifyNewTransactions(verbose bool) error { // NotifyReceivedAsync RPC invocation (or an applicable error). // // Deprecated: Use FutureLoadTxFilterResult instead. -type FutureNotifyReceivedResult chan *response +type FutureNotifyReceivedResult chan *Response -// Receive waits for the response promised by the future and returns an error +// Receive waits for the Response promised by the future and returns an error // if the registration was not successful. func (r FutureNotifyReceivedResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1067,7 +1067,7 @@ func (c *Client) notifyReceivedInternal(addresses []string) FutureNotifyReceived // Convert addresses to strings. cmd := btcjson.NewNotifyReceivedCmd(addresses) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // NotifyReceivedAsync returns an instance of a type that can be used to get the @@ -1097,7 +1097,7 @@ func (c *Client) NotifyReceivedAsync(addresses []btcutil.Address) FutureNotifyRe addrs = append(addrs, addr.String()) } cmd := btcjson.NewNotifyReceivedCmd(addrs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // NotifyReceived registers the client to receive notifications every time a @@ -1127,12 +1127,12 @@ func (c *Client) NotifyReceived(addresses []btcutil.Address) error { // or RescanEndHeightAsync RPC invocation (or an applicable error). // // Deprecated: Use FutureRescanBlocksResult instead. -type FutureRescanResult chan *response +type FutureRescanResult chan *Response -// Receive waits for the response promised by the future and returns an error +// Receive waits for the Response promised by the future and returns an error // if the rescan was not successful. func (r FutureRescanResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1185,7 +1185,7 @@ func (c *Client) RescanAsync(startBlock *chainhash.Hash, } cmd := btcjson.NewRescanCmd(startBlockHashStr, addrs, ops, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // Rescan rescans the block chain starting from the provided starting block to @@ -1270,7 +1270,7 @@ func (c *Client) RescanEndBlockAsync(startBlock *chainhash.Hash, cmd := btcjson.NewRescanCmd(startBlockHashStr, addrs, ops, &endBlockHashStr) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // RescanEndHeight rescans the block chain starting from the provided starting @@ -1307,15 +1307,15 @@ func (c *Client) RescanEndHeight(startBlock *chainhash.Hash, // // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient // and requires a websocket connection. -type FutureLoadTxFilterResult chan *response +type FutureLoadTxFilterResult chan *Response -// Receive waits for the response promised by the future and returns an error +// Receive waits for the Response promised by the future and returns an error // if the registration was not successful. // // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient // and requires a websocket connection. func (r FutureLoadTxFilterResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1343,7 +1343,7 @@ func (c *Client) LoadTxFilterAsync(reload bool, addresses []btcutil.Address, } cmd := btcjson.NewLoadTxFilterCmd(reload, addrStrs, outPointObjects) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // LoadTxFilter loads, reloads, or adds data to a websocket client's transaction diff --git a/rpcclient/rawrequest.go b/rpcclient/rawrequest.go index baead8bb90..f446b0082b 100644 --- a/rpcclient/rawrequest.go +++ b/rpcclient/rawrequest.go @@ -13,12 +13,12 @@ import ( // FutureRawResult is a future promise to deliver the result of a RawRequest RPC // invocation (or an applicable error). -type FutureRawResult chan *response +type FutureRawResult chan *Response -// Receive waits for the response promised by the future and returns the raw +// Receive waits for the Response promised by the future and returns the raw // response, or an error if the request was unsuccessful. func (r FutureRawResult) Receive() (json.RawMessage, error) { - return receiveFuture(r) + return ReceiveFuture(r) } // RawRequestAsync returns an instance of a type that can be used to get the @@ -39,7 +39,7 @@ func (c *Client) RawRequestAsync(method string, params []json.RawMessage) Future } // Create a raw JSON-RPC request using the provided method and params - // and marshal it. This is done rather than using the sendCmd function + // and marshal it. This is done rather than using the SendCmd function // since that relies on marshalling registered btcjson commands rather // than custom commands. id := c.NextID() @@ -55,7 +55,7 @@ func (c *Client) RawRequestAsync(method string, params []json.RawMessage) Future } // Generate the request and send it along with a channel to respond on. - responseChan := make(chan *response, 1) + responseChan := make(chan *Response, 1) jReq := &jsonRequest{ id: id, method: method, diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 35038ed9d3..cfc322c769 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -66,12 +66,12 @@ func (s SigHashType) String() string { // FutureGetRawTransactionResult is a future promise to deliver the result of a // GetRawTransactionAsync RPC invocation (or an applicable error). -type FutureGetRawTransactionResult chan *response +type FutureGetRawTransactionResult chan *Response -// Receive waits for the response promised by the future and returns a +// Receive waits for the Response promised by the future and returns a // transaction given its hash. func (r FutureGetRawTransactionResult) Receive() (*btcutil.Tx, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -109,7 +109,7 @@ func (c *Client) GetRawTransactionAsync(txHash *chainhash.Hash) FutureGetRawTran } cmd := btcjson.NewGetRawTransactionCmd(hash, btcjson.Int(0)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetRawTransaction returns a transaction given its hash. @@ -123,12 +123,12 @@ func (c *Client) GetRawTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error) // FutureGetRawTransactionVerboseResult is a future promise to deliver the // result of a GetRawTransactionVerboseAsync RPC invocation (or an applicable // error). -type FutureGetRawTransactionVerboseResult chan *response +type FutureGetRawTransactionVerboseResult chan *Response -// Receive waits for the response promised by the future and returns information +// Receive waits for the Response promised by the future and returns information // about a transaction given its hash. func (r FutureGetRawTransactionVerboseResult) Receive() (*btcjson.TxRawResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -155,7 +155,7 @@ func (c *Client) GetRawTransactionVerboseAsync(txHash *chainhash.Hash) FutureGet } cmd := btcjson.NewGetRawTransactionCmd(hash, btcjson.Int(1)) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetRawTransactionVerbose returns information about a transaction given @@ -168,12 +168,12 @@ func (c *Client) GetRawTransactionVerbose(txHash *chainhash.Hash) (*btcjson.TxRa // FutureDecodeRawTransactionResult is a future promise to deliver the result // of a DecodeRawTransactionAsync RPC invocation (or an applicable error). -type FutureDecodeRawTransactionResult chan *response +type FutureDecodeRawTransactionResult chan *Response -// Receive waits for the response promised by the future and returns information +// Receive waits for the Response promised by the future and returns information // about a transaction given its serialized bytes. func (r FutureDecodeRawTransactionResult) Receive() (*btcjson.TxRawResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -196,7 +196,7 @@ func (r FutureDecodeRawTransactionResult) Receive() (*btcjson.TxRawResult, error func (c *Client) DecodeRawTransactionAsync(serializedTx []byte) FutureDecodeRawTransactionResult { txHex := hex.EncodeToString(serializedTx) cmd := btcjson.NewDecodeRawTransactionCmd(txHex) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // DecodeRawTransaction returns information about a transaction given its @@ -207,12 +207,12 @@ func (c *Client) DecodeRawTransaction(serializedTx []byte) (*btcjson.TxRawResult // FutureFundRawTransactionResult is a future promise to deliver the result // of a FutureFundRawTransactionAsync RPC invocation (or an applicable error). -type FutureFundRawTransactionResult chan *response +type FutureFundRawTransactionResult chan *Response -// Receive waits for the response promised by the future and returns information +// Receive waits for the Response promised by the future and returns information // about a funding attempt func (r FutureFundRawTransactionResult) Receive() (*btcjson.FundRawTransactionResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -237,7 +237,7 @@ func (c *Client) FundRawTransactionAsync(tx *wire.MsgTx, opts btcjson.FundRawTra } cmd := btcjson.NewFundRawTransactionCmd(txBuf.Bytes(), opts, isWitness) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // FundRawTransaction returns the result of trying to fund the given transaction with @@ -248,13 +248,13 @@ func (c *Client) FundRawTransaction(tx *wire.MsgTx, opts btcjson.FundRawTransact // FutureCreateRawTransactionResult is a future promise to deliver the result // of a CreateRawTransactionAsync RPC invocation (or an applicable error). -type FutureCreateRawTransactionResult chan *response +type FutureCreateRawTransactionResult chan *Response -// Receive waits for the response promised by the future and returns a new +// Receive waits for the Response promised by the future and returns a new // transaction spending the provided inputs and sending to the provided // addresses. func (r FutureCreateRawTransactionResult) Receive() (*wire.MsgTx, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -298,7 +298,7 @@ func (c *Client) CreateRawTransactionAsync(inputs []btcjson.TransactionInput, convertedAmts[addr.String()] = amount.ToBTC() } cmd := btcjson.NewCreateRawTransactionCmd(inputs, convertedAmts, lockTime) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // CreateRawTransaction returns a new transaction spending the provided inputs @@ -312,13 +312,13 @@ func (c *Client) CreateRawTransaction(inputs []btcjson.TransactionInput, // FutureSendRawTransactionResult is a future promise to deliver the result // of a SendRawTransactionAsync RPC invocation (or an applicable error). -type FutureSendRawTransactionResult chan *response +type FutureSendRawTransactionResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of submitting the encoded transaction to the server which then relays it to // the network. func (r FutureSendRawTransactionResult) Receive() (*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -374,7 +374,7 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut cmd = btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees) } - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendRawTransaction submits the encoded transaction to the server which will @@ -386,12 +386,12 @@ func (c *Client) SendRawTransaction(tx *wire.MsgTx, allowHighFees bool) (*chainh // FutureSignRawTransactionResult is a future promise to deliver the result // of one of the SignRawTransactionAsync family of RPC invocations (or an // applicable error). -type FutureSignRawTransactionResult chan *response +type FutureSignRawTransactionResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // signed transaction as well as whether or not all inputs are now signed. func (r FutureSignRawTransactionResult) Receive() (*wire.MsgTx, bool, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, false, err } @@ -435,7 +435,7 @@ func (c *Client) SignRawTransactionAsync(tx *wire.MsgTx) FutureSignRawTransactio } cmd := btcjson.NewSignRawTransactionCmd(txHex, nil, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignRawTransaction signs inputs for the passed transaction and returns the @@ -466,7 +466,7 @@ func (c *Client) SignRawTransaction2Async(tx *wire.MsgTx, inputs []btcjson.RawTx } cmd := btcjson.NewSignRawTransactionCmd(txHex, &inputs, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignRawTransaction2 signs inputs for the passed transaction given the list @@ -504,7 +504,7 @@ func (c *Client) SignRawTransaction3Async(tx *wire.MsgTx, cmd := btcjson.NewSignRawTransactionCmd(txHex, &inputs, &privKeysWIF, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignRawTransaction3 signs inputs for the passed transaction given the list @@ -552,7 +552,7 @@ func (c *Client) SignRawTransaction4Async(tx *wire.MsgTx, cmd := btcjson.NewSignRawTransactionCmd(txHex, &inputs, &privKeysWIF, btcjson.String(string(hashType))) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignRawTransaction4 signs inputs for the passed transaction using @@ -585,12 +585,12 @@ func (c *Client) SignRawTransaction4(tx *wire.MsgTx, // FutureSignRawTransactionWithWalletResult is a future promise to deliver // the result of the SignRawTransactionWithWalletAsync RPC invocation (or // an applicable error). -type FutureSignRawTransactionWithWalletResult chan *response +type FutureSignRawTransactionWithWalletResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // signed transaction as well as whether or not all inputs are now signed. func (r FutureSignRawTransactionWithWalletResult) Receive() (*wire.MsgTx, bool, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, false, err } @@ -634,7 +634,7 @@ func (c *Client) SignRawTransactionWithWalletAsync(tx *wire.MsgTx) FutureSignRaw } cmd := btcjson.NewSignRawTransactionWithWalletCmd(txHex, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignRawTransactionWithWallet signs inputs for the passed transaction and returns @@ -667,7 +667,7 @@ func (c *Client) SignRawTransactionWithWallet2Async(tx *wire.MsgTx, } cmd := btcjson.NewSignRawTransactionWithWalletCmd(txHex, &inputs, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignRawTransactionWithWallet2 signs inputs for the passed transaction given the @@ -705,7 +705,7 @@ func (c *Client) SignRawTransactionWithWallet3Async(tx *wire.MsgTx, } cmd := btcjson.NewSignRawTransactionWithWalletCmd(txHex, &inputs, btcjson.String(string(hashType))) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignRawTransactionWithWallet3 signs inputs for the passed transaction using @@ -727,12 +727,12 @@ func (c *Client) SignRawTransactionWithWallet3(tx *wire.MsgTx, // FutureSearchRawTransactionsResult is a future promise to deliver the result // of the SearchRawTransactionsAsync RPC invocation (or an applicable error). -type FutureSearchRawTransactionsResult chan *response +type FutureSearchRawTransactionsResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // found raw transactions. func (r FutureSearchRawTransactionsResult) Receive() ([]*wire.MsgTx, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -775,7 +775,7 @@ func (c *Client) SearchRawTransactionsAsync(address btcutil.Address, skip, count verbose := btcjson.Int(0) cmd := btcjson.NewSearchRawTransactionsCmd(addr, verbose, &skip, &count, nil, &reverse, &filterAddrs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SearchRawTransactions returns transactions that involve the passed address. @@ -792,12 +792,12 @@ func (c *Client) SearchRawTransactions(address btcutil.Address, skip, count int, // FutureSearchRawTransactionsVerboseResult is a future promise to deliver the // result of the SearchRawTransactionsVerboseAsync RPC invocation (or an // applicable error). -type FutureSearchRawTransactionsVerboseResult chan *response +type FutureSearchRawTransactionsVerboseResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // found raw transactions. func (r FutureSearchRawTransactionsVerboseResult) Receive() ([]*btcjson.SearchRawTransactionsResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -828,7 +828,7 @@ func (c *Client) SearchRawTransactionsVerboseAsync(address btcutil.Address, skip } cmd := btcjson.NewSearchRawTransactionsCmd(addr, verbose, &skip, &count, prevOut, &reverse, filterAddrs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SearchRawTransactionsVerbose returns a list of data structures that describe @@ -847,12 +847,12 @@ func (c *Client) SearchRawTransactionsVerbose(address btcutil.Address, skip, // FutureDecodeScriptResult is a future promise to deliver the result // of a DecodeScriptAsync RPC invocation (or an applicable error). -type FutureDecodeScriptResult chan *response +type FutureDecodeScriptResult chan *Response -// Receive waits for the response promised by the future and returns information +// Receive waits for the Response promised by the future and returns information // about a script given its serialized bytes. func (r FutureDecodeScriptResult) Receive() (*btcjson.DecodeScriptResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -875,7 +875,7 @@ func (r FutureDecodeScriptResult) Receive() (*btcjson.DecodeScriptResult, error) func (c *Client) DecodeScriptAsync(serializedScript []byte) FutureDecodeScriptResult { scriptHex := hex.EncodeToString(serializedScript) cmd := btcjson.NewDecodeScriptCmd(scriptHex) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // DecodeScript returns information about a script given its serialized bytes. diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 011e91062b..71435d99f8 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -22,12 +22,12 @@ import ( // FutureGetTransactionResult is a future promise to deliver the result // of a GetTransactionAsync or GetTransactionWatchOnlyAsync RPC invocation // (or an applicable error). -type FutureGetTransactionResult chan *response +type FutureGetTransactionResult chan *Response -// Receive waits for the response promised by the future and returns detailed +// Receive waits for the Response promised by the future and returns detailed // information about a wallet transaction. func (r FutureGetTransactionResult) Receive() (*btcjson.GetTransactionResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -54,7 +54,7 @@ func (c *Client) GetTransactionAsync(txHash *chainhash.Hash) FutureGetTransactio } cmd := btcjson.NewGetTransactionCmd(hash, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetTransaction returns detailed information about a wallet transaction. @@ -76,7 +76,7 @@ func (c *Client) GetTransactionWatchOnlyAsync(txHash *chainhash.Hash, watchOnly } cmd := btcjson.NewGetTransactionCmd(hash, &watchOnly) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetTransactionWatchOnly returns detailed information about a wallet @@ -89,12 +89,12 @@ func (c *Client) GetTransactionWatchOnly(txHash *chainhash.Hash, watchOnly bool) // FutureListTransactionsResult is a future promise to deliver the result of a // ListTransactionsAsync, ListTransactionsCountAsync, or // ListTransactionsCountFromAsync RPC invocation (or an applicable error). -type FutureListTransactionsResult chan *response +type FutureListTransactionsResult chan *Response -// Receive waits for the response promised by the future and returns a list of +// Receive waits for the Response promised by the future and returns a list of // the most recent transactions. func (r FutureListTransactionsResult) Receive() ([]btcjson.ListTransactionsResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -116,7 +116,7 @@ func (r FutureListTransactionsResult) Receive() ([]btcjson.ListTransactionsResul // See ListTransactions for the blocking version and more details. func (c *Client) ListTransactionsAsync(account string) FutureListTransactionsResult { cmd := btcjson.NewListTransactionsCmd(&account, nil, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListTransactions returns a list of the most recent transactions. @@ -134,7 +134,7 @@ func (c *Client) ListTransactions(account string) ([]btcjson.ListTransactionsRes // See ListTransactionsCount for the blocking version and more details. func (c *Client) ListTransactionsCountAsync(account string, count int) FutureListTransactionsResult { cmd := btcjson.NewListTransactionsCmd(&account, &count, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListTransactionsCount returns a list of the most recent transactions up @@ -153,7 +153,7 @@ func (c *Client) ListTransactionsCount(account string, count int) ([]btcjson.Lis // See ListTransactionsCountFrom for the blocking version and more details. func (c *Client) ListTransactionsCountFromAsync(account string, count, from int) FutureListTransactionsResult { cmd := btcjson.NewListTransactionsCmd(&account, &count, &from, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListTransactionsCountFrom returns a list of the most recent transactions up @@ -171,7 +171,7 @@ func (c *Client) ListTransactionsCountFrom(account string, count, from int) ([]b // See ListTransactionsCountFromWatchOnly for the blocking version and more details. func (c *Client) ListTransactionsCountFromWatchOnlyAsync(account string, count, from int, watchOnly bool) FutureListTransactionsResult { cmd := btcjson.NewListTransactionsCmd(&account, &count, &from, &watchOnly) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListTransactionsCountFromWatchOnly returns a list of the most recent transactions up @@ -186,15 +186,15 @@ func (c *Client) ListTransactionsCountFromWatchOnly(account string, count, from // FutureListUnspentResult is a future promise to deliver the result of a // ListUnspentAsync, ListUnspentMinAsync, ListUnspentMinMaxAsync, or // ListUnspentMinMaxAddressesAsync RPC invocation (or an applicable error). -type FutureListUnspentResult chan *response +type FutureListUnspentResult chan *Response -// Receive waits for the response promised by the future and returns all +// Receive waits for the Response promised by the future and returns all // unspent wallet transaction outputs returned by the RPC call. If the // future wac returned by a call to ListUnspentMinAsync, ListUnspentMinMaxAsync, // or ListUnspentMinMaxAddressesAsync, the range may be limited by the // parameters of the RPC invocation. func (r FutureListUnspentResult) Receive() ([]btcjson.ListUnspentResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -216,7 +216,7 @@ func (r FutureListUnspentResult) Receive() ([]btcjson.ListUnspentResult, error) // See ListUnspent for the blocking version and more details. func (c *Client) ListUnspentAsync() FutureListUnspentResult { cmd := btcjson.NewListUnspentCmd(nil, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListUnspentMinAsync returns an instance of a type that can be used to get @@ -226,7 +226,7 @@ func (c *Client) ListUnspentAsync() FutureListUnspentResult { // See ListUnspentMin for the blocking version and more details. func (c *Client) ListUnspentMinAsync(minConf int) FutureListUnspentResult { cmd := btcjson.NewListUnspentCmd(&minConf, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListUnspentMinMaxAsync returns an instance of a type that can be used to get @@ -236,7 +236,7 @@ func (c *Client) ListUnspentMinAsync(minConf int) FutureListUnspentResult { // See ListUnspentMinMax for the blocking version and more details. func (c *Client) ListUnspentMinMaxAsync(minConf, maxConf int) FutureListUnspentResult { cmd := btcjson.NewListUnspentCmd(&minConf, &maxConf, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListUnspentMinMaxAddressesAsync returns an instance of a type that can be @@ -251,7 +251,7 @@ func (c *Client) ListUnspentMinMaxAddressesAsync(minConf, maxConf int, addrs []b } cmd := btcjson.NewListUnspentCmd(&minConf, &maxConf, &addrStrs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListUnspent returns all unspent transaction outputs known to a wallet, using @@ -285,13 +285,13 @@ func (c *Client) ListUnspentMinMaxAddresses(minConf, maxConf int, addrs []btcuti // FutureListSinceBlockResult is a future promise to deliver the result of a // ListSinceBlockAsync or ListSinceBlockMinConfAsync RPC invocation (or an // applicable error). -type FutureListSinceBlockResult chan *response +type FutureListSinceBlockResult chan *Response -// Receive waits for the response promised by the future and returns all +// Receive waits for the Response promised by the future and returns all // transactions added in blocks since the specified block hash, or all // transactions if it is nil. func (r FutureListSinceBlockResult) Receive() (*btcjson.ListSinceBlockResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -318,7 +318,7 @@ func (c *Client) ListSinceBlockAsync(blockHash *chainhash.Hash) FutureListSinceB } cmd := btcjson.NewListSinceBlockCmd(hash, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListSinceBlock returns all transactions added in blocks since the specified @@ -343,7 +343,7 @@ func (c *Client) ListSinceBlockMinConfAsync(blockHash *chainhash.Hash, minConfir } cmd := btcjson.NewListSinceBlockCmd(hash, &minConfirms, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListSinceBlockMinConf returns all transactions added in blocks since the @@ -367,7 +367,7 @@ func (c *Client) ListSinceBlockMinConfWatchOnlyAsync(blockHash *chainhash.Hash, } cmd := btcjson.NewListSinceBlockCmd(hash, &minConfirms, &watchOnly) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListSinceBlockMinConfWatchOnly returns all transactions added in blocks since the @@ -385,12 +385,12 @@ func (c *Client) ListSinceBlockMinConfWatchOnly(blockHash *chainhash.Hash, minCo // FutureLockUnspentResult is a future promise to deliver the error result of a // LockUnspentAsync RPC invocation. -type FutureLockUnspentResult chan *response +type FutureLockUnspentResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of locking or unlocking the unspent output(s). func (r FutureLockUnspentResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -408,7 +408,7 @@ func (c *Client) LockUnspentAsync(unlock bool, ops []*wire.OutPoint) FutureLockU } } cmd := btcjson.NewLockUnspentCmd(unlock, outputs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // LockUnspent marks outputs as locked or unlocked, depending on the value of @@ -434,12 +434,12 @@ func (c *Client) LockUnspent(unlock bool, ops []*wire.OutPoint) error { // FutureListLockUnspentResult is a future promise to deliver the result of a // ListLockUnspentAsync RPC invocation (or an applicable error). -type FutureListLockUnspentResult chan *response +type FutureListLockUnspentResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of all currently locked unspent outputs. func (r FutureListLockUnspentResult) Receive() ([]*wire.OutPoint, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -471,7 +471,7 @@ func (r FutureListLockUnspentResult) Receive() ([]*wire.OutPoint, error) { // See ListLockUnspent for the blocking version and more details. func (c *Client) ListLockUnspentAsync() FutureListLockUnspentResult { cmd := btcjson.NewListLockUnspentCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListLockUnspent returns a slice of outpoints for all unspent outputs marked @@ -483,13 +483,13 @@ func (c *Client) ListLockUnspent() ([]*wire.OutPoint, error) { // FutureSetTxFeeResult is a future promise to deliver the result of a // SetTxFeeAsync RPC invocation (or an applicable error). -type FutureSetTxFeeResult chan *response +type FutureSetTxFeeResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of setting an optional transaction fee per KB that helps ensure transactions // are processed quickly. Most transaction are 1KB. func (r FutureSetTxFeeResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -500,7 +500,7 @@ func (r FutureSetTxFeeResult) Receive() error { // See SetTxFee for the blocking version and more details. func (c *Client) SetTxFeeAsync(fee btcutil.Amount) FutureSetTxFeeResult { cmd := btcjson.NewSetTxFeeCmd(fee.ToBTC()) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SetTxFee sets an optional transaction fee per KB that helps ensure @@ -511,12 +511,12 @@ func (c *Client) SetTxFee(fee btcutil.Amount) error { // FutureSendToAddressResult is a future promise to deliver the result of a // SendToAddressAsync RPC invocation (or an applicable error). -type FutureSendToAddressResult chan *response +type FutureSendToAddressResult chan *Response -// Receive waits for the response promised by the future and returns the hash +// Receive waits for the Response promised by the future and returns the hash // of the transaction sending the passed amount to the given address. func (r FutureSendToAddressResult) Receive() (*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -539,7 +539,7 @@ func (r FutureSendToAddressResult) Receive() (*chainhash.Hash, error) { func (c *Client) SendToAddressAsync(address btcutil.Address, amount btcutil.Amount) FutureSendToAddressResult { addr := address.EncodeAddress() cmd := btcjson.NewSendToAddressCmd(addr, amount.ToBTC(), nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendToAddress sends the passed amount to the given address. @@ -566,7 +566,7 @@ func (c *Client) SendToAddressCommentAsync(address btcutil.Address, addr := address.EncodeAddress() cmd := btcjson.NewSendToAddressCmd(addr, amount.ToBTC(), &comment, &commentTo) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendToAddressComment sends the passed amount to the given address and stores @@ -589,13 +589,13 @@ func (c *Client) SendToAddressComment(address btcutil.Address, amount btcutil.Am // FutureSendFromResult is a future promise to deliver the result of a // SendFromAsync, SendFromMinConfAsync, or SendFromCommentAsync RPC invocation // (or an applicable error). -type FutureSendFromResult chan *response +type FutureSendFromResult chan *Response -// Receive waits for the response promised by the future and returns the hash +// Receive waits for the Response promised by the future and returns the hash // of the transaction sending amount to the given address using the provided // account as a source of funds. func (r FutureSendFromResult) Receive() (*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -619,7 +619,7 @@ func (c *Client) SendFromAsync(fromAccount string, toAddress btcutil.Address, am addr := toAddress.EncodeAddress() cmd := btcjson.NewSendFromCmd(fromAccount, addr, amount.ToBTC(), nil, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendFrom sends the passed amount to the given address using the provided @@ -643,7 +643,7 @@ func (c *Client) SendFromMinConfAsync(fromAccount string, toAddress btcutil.Addr addr := toAddress.EncodeAddress() cmd := btcjson.NewSendFromCmd(fromAccount, addr, amount.ToBTC(), &minConfirms, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendFromMinConf sends the passed amount to the given address using the @@ -672,7 +672,7 @@ func (c *Client) SendFromCommentAsync(fromAccount string, addr := toAddress.EncodeAddress() cmd := btcjson.NewSendFromCmd(fromAccount, addr, amount.ToBTC(), &minConfirms, &comment, &commentTo) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendFromComment sends the passed amount to the given address using the @@ -697,13 +697,13 @@ func (c *Client) SendFromComment(fromAccount string, toAddress btcutil.Address, // FutureSendManyResult is a future promise to deliver the result of a // SendManyAsync, SendManyMinConfAsync, or SendManyCommentAsync RPC invocation // (or an applicable error). -type FutureSendManyResult chan *response +type FutureSendManyResult chan *Response -// Receive waits for the response promised by the future and returns the hash +// Receive waits for the Response promised by the future and returns the hash // of the transaction sending multiple amounts to multiple addresses using the // provided account as a source of funds. func (r FutureSendManyResult) Receive() (*chainhash.Hash, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -729,7 +729,7 @@ func (c *Client) SendManyAsync(fromAccount string, amounts map[btcutil.Address]b convertedAmounts[addr.EncodeAddress()] = amount.ToBTC() } cmd := btcjson.NewSendManyCmd(fromAccount, convertedAmounts, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendMany sends multiple amounts to multiple addresses using the provided @@ -759,7 +759,7 @@ func (c *Client) SendManyMinConfAsync(fromAccount string, } cmd := btcjson.NewSendManyCmd(fromAccount, convertedAmounts, &minConfirms, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendManyMinConf sends multiple amounts to multiple addresses using the @@ -793,7 +793,7 @@ func (c *Client) SendManyCommentAsync(fromAccount string, } cmd := btcjson.NewSendManyCmd(fromAccount, convertedAmounts, &minConfirms, &comment) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SendManyComment sends multiple amounts to multiple addresses using the @@ -821,15 +821,15 @@ func (c *Client) SendManyComment(fromAccount string, // FutureAddMultisigAddressResult is a future promise to deliver the result of a // AddMultisigAddressAsync RPC invocation (or an applicable error). type FutureAddMultisigAddressResult struct { - responseChannel chan *response + responseChannel chan *Response network *chaincfg.Params } -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // multisignature address that requires the specified number of signatures for // the provided addresses. func (r FutureAddMultisigAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r.responseChannel) + res, err := ReceiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -858,7 +858,7 @@ func (c *Client) AddMultisigAddressAsync(requiredSigs int, addresses []btcutil.A cmd := btcjson.NewAddMultisigAddressCmd(requiredSigs, addrs, &account) result := FutureAddMultisigAddressResult{ network: c.chainParams, - responseChannel: c.sendCmd(cmd), + responseChannel: c.SendCmd(cmd), } return result } @@ -871,12 +871,12 @@ func (c *Client) AddMultisigAddress(requiredSigs int, addresses []btcutil.Addres // FutureCreateMultisigResult is a future promise to deliver the result of a // CreateMultisigAsync RPC invocation (or an applicable error). -type FutureCreateMultisigResult chan *response +type FutureCreateMultisigResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // multisignature address and script needed to redeem it. func (r FutureCreateMultisigResult) Receive() (*btcjson.CreateMultiSigResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -903,7 +903,7 @@ func (c *Client) CreateMultisigAsync(requiredSigs int, addresses []btcutil.Addre } cmd := btcjson.NewCreateMultisigCmd(requiredSigs, addrs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // CreateMultisig creates a multisignature address that requires the specified @@ -915,12 +915,12 @@ func (c *Client) CreateMultisig(requiredSigs int, addresses []btcutil.Address) ( // FutureCreateNewAccountResult is a future promise to deliver the result of a // CreateNewAccountAsync RPC invocation (or an applicable error). -type FutureCreateNewAccountResult chan *response +type FutureCreateNewAccountResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // result of creating new account. func (r FutureCreateNewAccountResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -931,7 +931,7 @@ func (r FutureCreateNewAccountResult) Receive() error { // See CreateNewAccount for the blocking version and more details. func (c *Client) CreateNewAccountAsync(account string) FutureCreateNewAccountResult { cmd := btcjson.NewCreateNewAccountCmd(account) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // CreateNewAccount creates a new wallet account. @@ -941,12 +941,12 @@ func (c *Client) CreateNewAccount(account string) error { // FutureCreateWalletResult is a future promise to deliver the result of a // CreateWalletAsync RPC invocation (or an applicable error). -type FutureCreateWalletResult chan *response +type FutureCreateWalletResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // result of creating a new wallet. func (r FutureCreateWalletResult) Receive() (*btcjson.CreateWalletResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1008,7 +1008,7 @@ func (c *Client) CreateWalletAsync(name string, opts ...CreateWalletOpt) FutureC opt(cmd) } - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // CreateWallet creates a new wallet account, with the possibility to use @@ -1026,12 +1026,12 @@ func (c *Client) CreateWallet(name string, opts ...CreateWalletOpt) (*btcjson.Cr // FutureGetAddressInfoResult is a future promise to deliver the result of an // GetAddressInfoAsync RPC invocation (or an applicable error). -type FutureGetAddressInfoResult chan *response +type FutureGetAddressInfoResult chan *Response -// Receive waits for the response promised by the future and returns the information +// Receive waits for the Response promised by the future and returns the information // about the given bitcoin address. func (r FutureGetAddressInfoResult) Receive() (*btcjson.GetAddressInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1051,7 +1051,7 @@ func (r FutureGetAddressInfoResult) Receive() (*btcjson.GetAddressInfoResult, er // See GetAddressInfo for the blocking version and more details. func (c *Client) GetAddressInfoAsync(address string) FutureGetAddressInfoResult { cmd := btcjson.NewGetAddressInfoCmd(address) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetAddressInfo returns information about the given bitcoin address. @@ -1062,14 +1062,14 @@ func (c *Client) GetAddressInfo(address string) (*btcjson.GetAddressInfoResult, // FutureGetNewAddressResult is a future promise to deliver the result of a // GetNewAddressAsync RPC invocation (or an applicable error). type FutureGetNewAddressResult struct { - responseChannel chan *response + responseChannel chan *Response network *chaincfg.Params } -// Receive waits for the response promised by the future and returns a new +// Receive waits for the Response promised by the future and returns a new // address. func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r.responseChannel) + res, err := ReceiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -1093,7 +1093,7 @@ func (c *Client) GetNewAddressAsync(account string) FutureGetNewAddressResult { cmd := btcjson.NewGetNewAddressCmd(&account) result := FutureGetNewAddressResult{ network: c.chainParams, - responseChannel: c.sendCmd(cmd), + responseChannel: c.SendCmd(cmd), } return result } @@ -1107,15 +1107,15 @@ func (c *Client) GetNewAddress(account string) (btcutil.Address, error) { // FutureGetRawChangeAddressResult is a future promise to deliver the result of // a GetRawChangeAddressAsync RPC invocation (or an applicable error). type FutureGetRawChangeAddressResult struct { - responseChannel chan *response + responseChannel chan *Response network *chaincfg.Params } -// Receive waits for the response promised by the future and returns a new +// Receive waits for the Response promised by the future and returns a new // address for receiving change that will be associated with the provided // account. Note that this is only for raw transactions and NOT for normal use. func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r.responseChannel) + res, err := ReceiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -1139,7 +1139,7 @@ func (c *Client) GetRawChangeAddressAsync(account string) FutureGetRawChangeAddr cmd := btcjson.NewGetRawChangeAddressCmd(&account) result := FutureGetRawChangeAddressResult{ network: c.chainParams, - responseChannel: c.sendCmd(cmd), + responseChannel: c.SendCmd(cmd), } return result } @@ -1154,14 +1154,14 @@ func (c *Client) GetRawChangeAddress(account string) (btcutil.Address, error) { // FutureAddWitnessAddressResult is a future promise to deliver the result of // a AddWitnessAddressAsync RPC invocation (or an applicable error). type FutureAddWitnessAddressResult struct { - responseChannel chan *response + responseChannel chan *Response network *chaincfg.Params } -// Receive waits for the response promised by the future and returns the new +// Receive waits for the Response promised by the future and returns the new // address. func (r FutureAddWitnessAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r.responseChannel) + res, err := ReceiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -1185,7 +1185,7 @@ func (c *Client) AddWitnessAddressAsync(address string) FutureAddWitnessAddressR cmd := btcjson.NewAddWitnessAddressCmd(address) response := FutureAddWitnessAddressResult{ network: c.chainParams, - responseChannel: c.sendCmd(cmd), + responseChannel: c.SendCmd(cmd), } return response } @@ -1199,14 +1199,14 @@ func (c *Client) AddWitnessAddress(address string) (btcutil.Address, error) { // FutureGetAccountAddressResult is a future promise to deliver the result of a // GetAccountAddressAsync RPC invocation (or an applicable error). type FutureGetAccountAddressResult struct { - responseChannel chan *response + responseChannel chan *Response network *chaincfg.Params } -// Receive waits for the response promised by the future and returns the current +// Receive waits for the Response promised by the future and returns the current // Bitcoin address for receiving payments to the specified account. func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) { - res, err := receiveFuture(r.responseChannel) + res, err := ReceiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -1230,7 +1230,7 @@ func (c *Client) GetAccountAddressAsync(account string) FutureGetAccountAddressR cmd := btcjson.NewGetAccountAddressCmd(account) result := FutureGetAccountAddressResult{ network: c.chainParams, - responseChannel: c.sendCmd(cmd), + responseChannel: c.SendCmd(cmd), } return result } @@ -1243,12 +1243,12 @@ func (c *Client) GetAccountAddress(account string) (btcutil.Address, error) { // FutureGetAccountResult is a future promise to deliver the result of a // GetAccountAsync RPC invocation (or an applicable error). -type FutureGetAccountResult chan *response +type FutureGetAccountResult chan *Response -// Receive waits for the response promised by the future and returns the account +// Receive waits for the Response promised by the future and returns the account // associated with the passed address. func (r FutureGetAccountResult) Receive() (string, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return "", err } @@ -1271,7 +1271,7 @@ func (r FutureGetAccountResult) Receive() (string, error) { func (c *Client) GetAccountAsync(address btcutil.Address) FutureGetAccountResult { addr := address.EncodeAddress() cmd := btcjson.NewGetAccountCmd(addr) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetAccount returns the account associated with the passed address. @@ -1281,12 +1281,12 @@ func (c *Client) GetAccount(address btcutil.Address) (string, error) { // FutureSetAccountResult is a future promise to deliver the result of a // SetAccountAsync RPC invocation (or an applicable error). -type FutureSetAccountResult chan *response +type FutureSetAccountResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of setting the account to be associated with the passed address. func (r FutureSetAccountResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1298,7 +1298,7 @@ func (r FutureSetAccountResult) Receive() error { func (c *Client) SetAccountAsync(address btcutil.Address, account string) FutureSetAccountResult { addr := address.EncodeAddress() cmd := btcjson.NewSetAccountCmd(addr, account) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SetAccount sets the account associated with the passed address. @@ -1309,14 +1309,14 @@ func (c *Client) SetAccount(address btcutil.Address, account string) error { // FutureGetAddressesByAccountResult is a future promise to deliver the result // of a GetAddressesByAccountAsync RPC invocation (or an applicable error). type FutureGetAddressesByAccountResult struct { - responseChannel chan *response + responseChannel chan *Response network *chaincfg.Params } -// Receive waits for the response promised by the future and returns the list of +// Receive waits for the Response promised by the future and returns the list of // addresses associated with the passed account. func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error) { - res, err := receiveFuture(r.responseChannel) + res, err := ReceiveFuture(r.responseChannel) if err != nil { return nil, err } @@ -1348,7 +1348,7 @@ func (c *Client) GetAddressesByAccountAsync(account string) FutureGetAddressesBy cmd := btcjson.NewGetAddressesByAccountCmd(account) result := FutureGetAddressesByAccountResult{ network: c.chainParams, - responseChannel: c.sendCmd(cmd), + responseChannel: c.SendCmd(cmd), } return result } @@ -1362,12 +1362,12 @@ func (c *Client) GetAddressesByAccount(account string) ([]btcutil.Address, error // FutureMoveResult is a future promise to deliver the result of a MoveAsync, // MoveMinConfAsync, or MoveCommentAsync RPC invocation (or an applicable // error). -type FutureMoveResult chan *response +type FutureMoveResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of the move operation. func (r FutureMoveResult) Receive() (bool, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return false, err } @@ -1390,7 +1390,7 @@ func (r FutureMoveResult) Receive() (bool, error) { func (c *Client) MoveAsync(fromAccount, toAccount string, amount btcutil.Amount) FutureMoveResult { cmd := btcjson.NewMoveCmd(fromAccount, toAccount, amount.ToBTC(), nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // Move moves specified amount from one account in your wallet to another. Only @@ -1411,7 +1411,7 @@ func (c *Client) MoveMinConfAsync(fromAccount, toAccount string, cmd := btcjson.NewMoveCmd(fromAccount, toAccount, amount.ToBTC(), &minConfirms, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // MoveMinConf moves specified amount from one account in your wallet to @@ -1434,7 +1434,7 @@ func (c *Client) MoveCommentAsync(fromAccount, toAccount string, cmd := btcjson.NewMoveCmd(fromAccount, toAccount, amount.ToBTC(), &minConfirms, &comment) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // MoveComment moves specified amount from one account in your wallet to @@ -1452,12 +1452,12 @@ func (c *Client) MoveComment(fromAccount, toAccount string, amount btcutil.Amoun // FutureRenameAccountResult is a future promise to deliver the result of a // RenameAccountAsync RPC invocation (or an applicable error). -type FutureRenameAccountResult chan *response +type FutureRenameAccountResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // result of creating new account. func (r FutureRenameAccountResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1468,7 +1468,7 @@ func (r FutureRenameAccountResult) Receive() error { // See RenameAccount for the blocking version and more details. func (c *Client) RenameAccountAsync(oldAccount, newAccount string) FutureRenameAccountResult { cmd := btcjson.NewRenameAccountCmd(oldAccount, newAccount) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // RenameAccount creates a new wallet account. @@ -1478,12 +1478,12 @@ func (c *Client) RenameAccount(oldAccount, newAccount string) error { // FutureValidateAddressResult is a future promise to deliver the result of a // ValidateAddressAsync RPC invocation (or an applicable error). -type FutureValidateAddressResult chan *response +type FutureValidateAddressResult chan *Response -// Receive waits for the response promised by the future and returns information +// Receive waits for the Response promised by the future and returns information // about the given bitcoin address. func (r FutureValidateAddressResult) Receive() (*btcjson.ValidateAddressWalletResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1506,7 +1506,7 @@ func (r FutureValidateAddressResult) Receive() (*btcjson.ValidateAddressWalletRe func (c *Client) ValidateAddressAsync(address btcutil.Address) FutureValidateAddressResult { addr := address.EncodeAddress() cmd := btcjson.NewValidateAddressCmd(addr) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ValidateAddress returns information about the given bitcoin address. @@ -1516,12 +1516,12 @@ func (c *Client) ValidateAddress(address btcutil.Address) (*btcjson.ValidateAddr // FutureKeyPoolRefillResult is a future promise to deliver the result of a // KeyPoolRefillAsync RPC invocation (or an applicable error). -type FutureKeyPoolRefillResult chan *response +type FutureKeyPoolRefillResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of refilling the key pool. func (r FutureKeyPoolRefillResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -1532,7 +1532,7 @@ func (r FutureKeyPoolRefillResult) Receive() error { // See KeyPoolRefill for the blocking version and more details. func (c *Client) KeyPoolRefillAsync() FutureKeyPoolRefillResult { cmd := btcjson.NewKeyPoolRefillCmd(nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // KeyPoolRefill fills the key pool as necessary to reach the default size. @@ -1549,7 +1549,7 @@ func (c *Client) KeyPoolRefill() error { // See KeyPoolRefillSize for the blocking version and more details. func (c *Client) KeyPoolRefillSizeAsync(newSize uint) FutureKeyPoolRefillResult { cmd := btcjson.NewKeyPoolRefillCmd(&newSize) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // KeyPoolRefillSize fills the key pool as necessary to reach the specified @@ -1565,12 +1565,12 @@ func (c *Client) KeyPoolRefillSize(newSize uint) error { // FutureListAccountsResult is a future promise to deliver the result of a // ListAccountsAsync or ListAccountsMinConfAsync RPC invocation (or an // applicable error). -type FutureListAccountsResult chan *response +type FutureListAccountsResult chan *Response -// Receive waits for the response promised by the future and returns returns a +// Receive waits for the Response promised by the future and returns returns a // map of account names and their associated balances. func (r FutureListAccountsResult) Receive() (map[string]btcutil.Amount, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1602,7 +1602,7 @@ func (r FutureListAccountsResult) Receive() (map[string]btcutil.Amount, error) { // See ListAccounts for the blocking version and more details. func (c *Client) ListAccountsAsync() FutureListAccountsResult { cmd := btcjson.NewListAccountsCmd(nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListAccounts returns a map of account names and their associated balances @@ -1620,7 +1620,7 @@ func (c *Client) ListAccounts() (map[string]btcutil.Amount, error) { // See ListAccountsMinConf for the blocking version and more details. func (c *Client) ListAccountsMinConfAsync(minConfirms int) FutureListAccountsResult { cmd := btcjson.NewListAccountsCmd(&minConfirms) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListAccountsMinConf returns a map of account names and their associated @@ -1634,12 +1634,12 @@ func (c *Client) ListAccountsMinConf(minConfirms int) (map[string]btcutil.Amount // FutureGetBalanceResult is a future promise to deliver the result of a // GetBalanceAsync or GetBalanceMinConfAsync RPC invocation (or an applicable // error). -type FutureGetBalanceResult chan *response +type FutureGetBalanceResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // available balance from the server for the specified account. func (r FutureGetBalanceResult) Receive() (btcutil.Amount, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -1663,12 +1663,12 @@ func (r FutureGetBalanceResult) Receive() (btcutil.Amount, error) { // that the result is expected to be a string which is then parsed into // a float64 value // This is required for compatibility with servers like blockchain.info -type FutureGetBalanceParseResult chan *response +type FutureGetBalanceParseResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // available balance from the server for the specified account. func (r FutureGetBalanceParseResult) Receive() (btcutil.Amount, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -1699,7 +1699,7 @@ func (r FutureGetBalanceParseResult) Receive() (btcutil.Amount, error) { // See GetBalance for the blocking version and more details. func (c *Client) GetBalanceAsync(account string) FutureGetBalanceResult { cmd := btcjson.NewGetBalanceCmd(&account, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBalance returns the available balance from the server for the specified @@ -1718,7 +1718,7 @@ func (c *Client) GetBalance(account string) (btcutil.Amount, error) { // See GetBalanceMinConf for the blocking version and more details. func (c *Client) GetBalanceMinConfAsync(account string, minConfirms int) FutureGetBalanceResult { cmd := btcjson.NewGetBalanceCmd(&account, &minConfirms) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBalanceMinConf returns the available balance from the server for the @@ -1736,12 +1736,12 @@ func (c *Client) GetBalanceMinConf(account string, minConfirms int) (btcutil.Amo // FutureGetBalancesResult is a future promise to deliver the result of a // GetBalancesAsync RPC invocation (or an applicable error). -type FutureGetBalancesResult chan *response +type FutureGetBalancesResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // available balances from the server. func (r FutureGetBalancesResult) Receive() (*btcjson.GetBalancesResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1763,7 +1763,7 @@ func (r FutureGetBalancesResult) Receive() (*btcjson.GetBalancesResult, error) { // See GetBalances for the blocking version and more details. func (c *Client) GetBalancesAsync() FutureGetBalancesResult { cmd := btcjson.NewGetBalancesCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetBalances returns the available balances from the server. @@ -1774,12 +1774,12 @@ func (c *Client) GetBalances() (*btcjson.GetBalancesResult, error) { // FutureGetReceivedByAccountResult is a future promise to deliver the result of // a GetReceivedByAccountAsync or GetReceivedByAccountMinConfAsync RPC // invocation (or an applicable error). -type FutureGetReceivedByAccountResult chan *response +type FutureGetReceivedByAccountResult chan *Response -// Receive waits for the response promised by the future and returns the total +// Receive waits for the Response promised by the future and returns the total // amount received with the specified account. func (r FutureGetReceivedByAccountResult) Receive() (btcutil.Amount, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -1806,7 +1806,7 @@ func (r FutureGetReceivedByAccountResult) Receive() (btcutil.Amount, error) { // See GetReceivedByAccount for the blocking version and more details. func (c *Client) GetReceivedByAccountAsync(account string) FutureGetReceivedByAccountResult { cmd := btcjson.NewGetReceivedByAccountCmd(account, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetReceivedByAccount returns the total amount received with the specified @@ -1825,7 +1825,7 @@ func (c *Client) GetReceivedByAccount(account string) (btcutil.Amount, error) { // See GetReceivedByAccountMinConf for the blocking version and more details. func (c *Client) GetReceivedByAccountMinConfAsync(account string, minConfirms int) FutureGetReceivedByAccountResult { cmd := btcjson.NewGetReceivedByAccountCmd(account, &minConfirms) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetReceivedByAccountMinConf returns the total amount received with the @@ -1839,12 +1839,12 @@ func (c *Client) GetReceivedByAccountMinConf(account string, minConfirms int) (b // FutureGetUnconfirmedBalanceResult is a future promise to deliver the result // of a GetUnconfirmedBalanceAsync RPC invocation (or an applicable error). -type FutureGetUnconfirmedBalanceResult chan *response +type FutureGetUnconfirmedBalanceResult chan *Response -// Receive waits for the response promised by the future and returns returns the +// Receive waits for the Response promised by the future and returns returns the // unconfirmed balance from the server for the specified account. func (r FutureGetUnconfirmedBalanceResult) Receive() (btcutil.Amount, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -1871,7 +1871,7 @@ func (r FutureGetUnconfirmedBalanceResult) Receive() (btcutil.Amount, error) { // See GetUnconfirmedBalance for the blocking version and more details. func (c *Client) GetUnconfirmedBalanceAsync(account string) FutureGetUnconfirmedBalanceResult { cmd := btcjson.NewGetUnconfirmedBalanceCmd(&account) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetUnconfirmedBalance returns the unconfirmed balance from the server for @@ -1883,12 +1883,12 @@ func (c *Client) GetUnconfirmedBalance(account string) (btcutil.Amount, error) { // FutureGetReceivedByAddressResult is a future promise to deliver the result of // a GetReceivedByAddressAsync or GetReceivedByAddressMinConfAsync RPC // invocation (or an applicable error). -type FutureGetReceivedByAddressResult chan *response +type FutureGetReceivedByAddressResult chan *Response -// Receive waits for the response promised by the future and returns the total +// Receive waits for the Response promised by the future and returns the total // amount received by the specified address. func (r FutureGetReceivedByAddressResult) Receive() (btcutil.Amount, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return 0, err } @@ -1916,7 +1916,7 @@ func (r FutureGetReceivedByAddressResult) Receive() (btcutil.Amount, error) { func (c *Client) GetReceivedByAddressAsync(address btcutil.Address) FutureGetReceivedByAddressResult { addr := address.EncodeAddress() cmd := btcjson.NewGetReceivedByAddressCmd(addr, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } @@ -1937,7 +1937,7 @@ func (c *Client) GetReceivedByAddress(address btcutil.Address) (btcutil.Amount, func (c *Client) GetReceivedByAddressMinConfAsync(address btcutil.Address, minConfirms int) FutureGetReceivedByAddressResult { addr := address.EncodeAddress() cmd := btcjson.NewGetReceivedByAddressCmd(addr, &minConfirms) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetReceivedByAddressMinConf returns the total amount received by the specified @@ -1952,12 +1952,12 @@ func (c *Client) GetReceivedByAddressMinConf(address btcutil.Address, minConfirm // of a ListReceivedByAccountAsync, ListReceivedByAccountMinConfAsync, or // ListReceivedByAccountIncludeEmptyAsync RPC invocation (or an applicable // error). -type FutureListReceivedByAccountResult chan *response +type FutureListReceivedByAccountResult chan *Response -// Receive waits for the response promised by the future and returns a list of +// Receive waits for the Response promised by the future and returns a list of // balances by account. func (r FutureListReceivedByAccountResult) Receive() ([]btcjson.ListReceivedByAccountResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -1979,7 +1979,7 @@ func (r FutureListReceivedByAccountResult) Receive() ([]btcjson.ListReceivedByAc // See ListReceivedByAccount for the blocking version and more details. func (c *Client) ListReceivedByAccountAsync() FutureListReceivedByAccountResult { cmd := btcjson.NewListReceivedByAccountCmd(nil, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListReceivedByAccount lists balances by account using the default number @@ -2000,7 +2000,7 @@ func (c *Client) ListReceivedByAccount() ([]btcjson.ListReceivedByAccountResult, // See ListReceivedByAccountMinConf for the blocking version and more details. func (c *Client) ListReceivedByAccountMinConfAsync(minConfirms int) FutureListReceivedByAccountResult { cmd := btcjson.NewListReceivedByAccountCmd(&minConfirms, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListReceivedByAccountMinConf lists balances by account using the specified @@ -2022,7 +2022,7 @@ func (c *Client) ListReceivedByAccountMinConf(minConfirms int) ([]btcjson.ListRe func (c *Client) ListReceivedByAccountIncludeEmptyAsync(minConfirms int, includeEmpty bool) FutureListReceivedByAccountResult { cmd := btcjson.NewListReceivedByAccountCmd(&minConfirms, &includeEmpty, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListReceivedByAccountIncludeEmpty lists balances by account using the @@ -2039,12 +2039,12 @@ func (c *Client) ListReceivedByAccountIncludeEmpty(minConfirms int, includeEmpty // of a ListReceivedByAddressAsync, ListReceivedByAddressMinConfAsync, or // ListReceivedByAddressIncludeEmptyAsync RPC invocation (or an applicable // error). -type FutureListReceivedByAddressResult chan *response +type FutureListReceivedByAddressResult chan *Response -// Receive waits for the response promised by the future and returns a list of +// Receive waits for the Response promised by the future and returns a list of // balances by address. func (r FutureListReceivedByAddressResult) Receive() ([]btcjson.ListReceivedByAddressResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2066,7 +2066,7 @@ func (r FutureListReceivedByAddressResult) Receive() ([]btcjson.ListReceivedByAd // See ListReceivedByAddress for the blocking version and more details. func (c *Client) ListReceivedByAddressAsync() FutureListReceivedByAddressResult { cmd := btcjson.NewListReceivedByAddressCmd(nil, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListReceivedByAddress lists balances by address using the default number @@ -2087,7 +2087,7 @@ func (c *Client) ListReceivedByAddress() ([]btcjson.ListReceivedByAddressResult, // See ListReceivedByAddressMinConf for the blocking version and more details. func (c *Client) ListReceivedByAddressMinConfAsync(minConfirms int) FutureListReceivedByAddressResult { cmd := btcjson.NewListReceivedByAddressCmd(&minConfirms, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListReceivedByAddressMinConf lists balances by address using the specified @@ -2109,7 +2109,7 @@ func (c *Client) ListReceivedByAddressMinConf(minConfirms int) ([]btcjson.ListRe func (c *Client) ListReceivedByAddressIncludeEmptyAsync(minConfirms int, includeEmpty bool) FutureListReceivedByAddressResult { cmd := btcjson.NewListReceivedByAddressCmd(&minConfirms, &includeEmpty, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ListReceivedByAddressIncludeEmpty lists balances by address using the @@ -2128,12 +2128,12 @@ func (c *Client) ListReceivedByAddressIncludeEmpty(minConfirms int, includeEmpty // FutureWalletLockResult is a future promise to deliver the result of a // WalletLockAsync RPC invocation (or an applicable error). -type FutureWalletLockResult chan *response +type FutureWalletLockResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of locking the wallet. func (r FutureWalletLockResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2144,7 +2144,7 @@ func (r FutureWalletLockResult) Receive() error { // See WalletLock for the blocking version and more details. func (c *Client) WalletLockAsync() FutureWalletLockResult { cmd := btcjson.NewWalletLockCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // WalletLock locks the wallet by removing the encryption key from memory. @@ -2167,12 +2167,12 @@ func (c *Client) WalletPassphrase(passphrase string, timeoutSecs int64) error { // FutureWalletPassphraseChangeResult is a future promise to deliver the result // of a WalletPassphraseChangeAsync RPC invocation (or an applicable error). -type FutureWalletPassphraseChangeResult chan *response +type FutureWalletPassphraseChangeResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of changing the wallet passphrase. func (r FutureWalletPassphraseChangeResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2183,7 +2183,7 @@ func (r FutureWalletPassphraseChangeResult) Receive() error { // See WalletPassphraseChange for the blocking version and more details. func (c *Client) WalletPassphraseChangeAsync(old, new string) FutureWalletPassphraseChangeResult { cmd := btcjson.NewWalletPassphraseChangeCmd(old, new) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // WalletPassphraseChange changes the wallet passphrase from the specified old @@ -2198,12 +2198,12 @@ func (c *Client) WalletPassphraseChange(old, new string) error { // FutureSignMessageResult is a future promise to deliver the result of a // SignMessageAsync RPC invocation (or an applicable error). -type FutureSignMessageResult chan *response +type FutureSignMessageResult chan *Response -// Receive waits for the response promised by the future and returns the message +// Receive waits for the Response promised by the future and returns the message // signed with the private key of the specified address. func (r FutureSignMessageResult) Receive() (string, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return "", err } @@ -2226,7 +2226,7 @@ func (r FutureSignMessageResult) Receive() (string, error) { func (c *Client) SignMessageAsync(address btcutil.Address, message string) FutureSignMessageResult { addr := address.EncodeAddress() cmd := btcjson.NewSignMessageCmd(addr, message) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // SignMessage signs a message with the private key of the specified address. @@ -2239,12 +2239,12 @@ func (c *Client) SignMessage(address btcutil.Address, message string) (string, e // FutureVerifyMessageResult is a future promise to deliver the result of a // VerifyMessageAsync RPC invocation (or an applicable error). -type FutureVerifyMessageResult chan *response +type FutureVerifyMessageResult chan *Response -// Receive waits for the response promised by the future and returns whether or +// Receive waits for the Response promised by the future and returns whether or // not the message was successfully verified. func (r FutureVerifyMessageResult) Receive() (bool, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return false, err } @@ -2267,7 +2267,7 @@ func (r FutureVerifyMessageResult) Receive() (bool, error) { func (c *Client) VerifyMessageAsync(address btcutil.Address, signature, message string) FutureVerifyMessageResult { addr := address.EncodeAddress() cmd := btcjson.NewVerifyMessageCmd(addr, signature, message) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // VerifyMessage verifies a signed message. @@ -2284,13 +2284,13 @@ func (c *Client) VerifyMessage(address btcutil.Address, signature, message strin // FutureDumpPrivKeyResult is a future promise to deliver the result of a // DumpPrivKeyAsync RPC invocation (or an applicable error). -type FutureDumpPrivKeyResult chan *response +type FutureDumpPrivKeyResult chan *Response -// Receive waits for the response promised by the future and returns the private +// Receive waits for the Response promised by the future and returns the private // key corresponding to the passed address encoded in the wallet import format // (WIF) func (r FutureDumpPrivKeyResult) Receive() (*btcutil.WIF, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2313,7 +2313,7 @@ func (r FutureDumpPrivKeyResult) Receive() (*btcutil.WIF, error) { func (c *Client) DumpPrivKeyAsync(address btcutil.Address) FutureDumpPrivKeyResult { addr := address.EncodeAddress() cmd := btcjson.NewDumpPrivKeyCmd(addr) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // DumpPrivKey gets the private key corresponding to the passed address encoded @@ -2327,12 +2327,12 @@ func (c *Client) DumpPrivKey(address btcutil.Address) (*btcutil.WIF, error) { // FutureImportAddressResult is a future promise to deliver the result of an // ImportAddressAsync RPC invocation (or an applicable error). -type FutureImportAddressResult chan *response +type FutureImportAddressResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of importing the passed public address. func (r FutureImportAddressResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2343,7 +2343,7 @@ func (r FutureImportAddressResult) Receive() error { // See ImportAddress for the blocking version and more details. func (c *Client) ImportAddressAsync(address string) FutureImportAddressResult { cmd := btcjson.NewImportAddressCmd(address, "", nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportAddress imports the passed public address. @@ -2358,7 +2358,7 @@ func (c *Client) ImportAddress(address string) error { // See ImportAddress for the blocking version and more details. func (c *Client) ImportAddressRescanAsync(address string, account string, rescan bool) FutureImportAddressResult { cmd := btcjson.NewImportAddressCmd(address, account, &rescan) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportAddressRescan imports the passed public address. When rescan is true, @@ -2369,12 +2369,12 @@ func (c *Client) ImportAddressRescan(address string, account string, rescan bool // FutureImportMultiResult is a future promise to deliver the result of an // ImportMultiAsync RPC invocation (or an applicable error). -type FutureImportMultiResult chan *response +type FutureImportMultiResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of importing multiple addresses/scripts. func (r FutureImportMultiResult) Receive() (btcjson.ImportMultiResults, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2394,7 +2394,7 @@ func (r FutureImportMultiResult) Receive() (btcjson.ImportMultiResults, error) { // See ImportMulti for the blocking version and more details. func (c *Client) ImportMultiAsync(requests []btcjson.ImportMultiRequest, options *btcjson.ImportMultiOptions) FutureImportMultiResult { cmd := btcjson.NewImportMultiCmd(requests, options) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportMulti imports addresses/scripts, optionally rescanning the blockchain @@ -2407,13 +2407,13 @@ func (c *Client) ImportMulti(requests []btcjson.ImportMultiRequest, options *btc // FutureImportPrivKeyResult is a future promise to deliver the result of an // ImportPrivKeyAsync RPC invocation (or an applicable error). -type FutureImportPrivKeyResult chan *response +type FutureImportPrivKeyResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of importing the passed private key which must be the wallet import format // (WIF). func (r FutureImportPrivKeyResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2429,7 +2429,7 @@ func (c *Client) ImportPrivKeyAsync(privKeyWIF *btcutil.WIF) FutureImportPrivKey } cmd := btcjson.NewImportPrivKeyCmd(wif, nil, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportPrivKey imports the passed private key which must be the wallet import @@ -2450,7 +2450,7 @@ func (c *Client) ImportPrivKeyLabelAsync(privKeyWIF *btcutil.WIF, label string) } cmd := btcjson.NewImportPrivKeyCmd(wif, &label, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportPrivKeyLabel imports the passed private key which must be the wallet import @@ -2471,7 +2471,7 @@ func (c *Client) ImportPrivKeyRescanAsync(privKeyWIF *btcutil.WIF, label string, } cmd := btcjson.NewImportPrivKeyCmd(wif, &label, &rescan) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportPrivKeyRescan imports the passed private key which must be the wallet import @@ -2483,12 +2483,12 @@ func (c *Client) ImportPrivKeyRescan(privKeyWIF *btcutil.WIF, label string, resc // FutureImportPubKeyResult is a future promise to deliver the result of an // ImportPubKeyAsync RPC invocation (or an applicable error). -type FutureImportPubKeyResult chan *response +type FutureImportPubKeyResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of importing the passed public key. func (r FutureImportPubKeyResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2499,7 +2499,7 @@ func (r FutureImportPubKeyResult) Receive() error { // See ImportPubKey for the blocking version and more details. func (c *Client) ImportPubKeyAsync(pubKey string) FutureImportPubKeyResult { cmd := btcjson.NewImportPubKeyCmd(pubKey, nil) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportPubKey imports the passed public key. @@ -2514,7 +2514,7 @@ func (c *Client) ImportPubKey(pubKey string) error { // See ImportPubKey for the blocking version and more details. func (c *Client) ImportPubKeyRescanAsync(pubKey string, rescan bool) FutureImportPubKeyResult { cmd := btcjson.NewImportPubKeyCmd(pubKey, &rescan) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // ImportPubKeyRescan imports the passed public key. When rescan is true, the @@ -2532,12 +2532,12 @@ func (c *Client) ImportPubKeyRescan(pubKey string, rescan bool) error { // FutureGetInfoResult is a future promise to deliver the result of a // GetInfoAsync RPC invocation (or an applicable error). -type FutureGetInfoResult chan *response +type FutureGetInfoResult chan *Response -// Receive waits for the response promised by the future and returns the info +// Receive waits for the Response promised by the future and returns the info // provided by the server. func (r FutureGetInfoResult) Receive() (*btcjson.InfoWalletResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2559,7 +2559,7 @@ func (r FutureGetInfoResult) Receive() (*btcjson.InfoWalletResult, error) { // See GetInfo for the blocking version and more details. func (c *Client) GetInfoAsync() FutureGetInfoResult { cmd := btcjson.NewGetInfoCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetInfo returns miscellaneous info regarding the RPC server. The returned @@ -2571,13 +2571,13 @@ func (c *Client) GetInfo() (*btcjson.InfoWalletResult, error) { // FutureImportPubKeyResult is a future promise to deliver the result of an // WalletCreateFundedPsbt RPC invocation (or an applicable error). -type FutureWalletCreateFundedPsbtResult chan *response +type FutureWalletCreateFundedPsbtResult chan *Response -// Receive waits for the response promised by the future and returns the +// Receive waits for the Response promised by the future and returns the // partially signed transaction in PSBT format along with the resulting fee // and change output index. func (r FutureWalletCreateFundedPsbtResult) Receive() (*btcjson.WalletCreateFundedPsbtResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2602,7 +2602,7 @@ func (c *Client) WalletCreateFundedPsbtAsync( options *btcjson.WalletCreateFundedPsbtOpts, bip32Derivs *bool, ) FutureWalletCreateFundedPsbtResult { cmd := btcjson.NewWalletCreateFundedPsbtCmd(inputs, outputs, locktime, options, bip32Derivs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // WalletCreateFundedPsbt creates and funds a transaction in the Partially @@ -2617,13 +2617,13 @@ func (c *Client) WalletCreateFundedPsbt( // FutureWalletProcessPsbtResult is a future promise to deliver the result of a // WalletCreateFundedPsb RPC invocation (or an applicable error). -type FutureWalletProcessPsbtResult chan *response +type FutureWalletProcessPsbtResult chan *Response -// Receive waits for the response promised by the future and returns an updated +// Receive waits for the Response promised by the future and returns an updated // PSBT with signed inputs from the wallet and a boolen indicating if the the // transaction has a complete set of signatures. func (r FutureWalletProcessPsbtResult) Receive() (*btcjson.WalletProcessPsbtResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2647,7 +2647,7 @@ func (c *Client) WalletProcessPsbtAsync( psbt string, sign *bool, sighashType SigHashType, bip32Derivs *bool, ) FutureWalletProcessPsbtResult { cmd := btcjson.NewWalletProcessPsbtCmd(psbt, sign, btcjson.String(sighashType.String()), bip32Derivs) - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // WalletProcessPsbt updates a PSBT with input information from our wallet and @@ -2660,12 +2660,12 @@ func (c *Client) WalletProcessPsbt( // FutureGetWalletInfoResult is a future promise to deliver the result of an // GetWalletInfoAsync RPC invocation (or an applicable error). -type FutureGetWalletInfoResult chan *response +type FutureGetWalletInfoResult chan *Response -// Receive waits for the response promised by the future and returns the result +// Receive waits for the Response promised by the future and returns the result // of wallet state info. func (r FutureGetWalletInfoResult) Receive() (*btcjson.GetWalletInfoResult, error) { - res, err := receiveFuture(r) + res, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2685,7 +2685,7 @@ func (r FutureGetWalletInfoResult) Receive() (*btcjson.GetWalletInfoResult, erro // See GetWalletInfo for the blocking version and more details. func (c *Client) GetWalletInfoAsync() FutureGetWalletInfoResult { cmd := btcjson.NewGetWalletInfoCmd() - return c.sendCmd(cmd) + return c.SendCmd(cmd) } // GetWalletInfo returns various wallet state info. @@ -2695,11 +2695,11 @@ func (c *Client) GetWalletInfo() (*btcjson.GetWalletInfoResult, error) { // FutureBackupWalletResult is a future promise to deliver the result of an // BackupWalletAsync RPC invocation (or an applicable error) -type FutureBackupWalletResult chan *response +type FutureBackupWalletResult chan *Response -// Receive waits for the response promised by the future +// Receive waits for the Response promised by the future func (r FutureBackupWalletResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2709,7 +2709,7 @@ func (r FutureBackupWalletResult) Receive() error { // // See BackupWallet for the blocking version and more details. func (c *Client) BackupWalletAsync(destination string) FutureBackupWalletResult { - return c.sendCmd(btcjson.NewBackupWalletCmd(destination)) + return c.SendCmd(btcjson.NewBackupWalletCmd(destination)) } // BackupWallet safely copies current wallet file to destination, which can @@ -2720,11 +2720,11 @@ func (c *Client) BackupWallet(destination string) error { // FutureDumpWalletResult is a future promise to deliver the result of an // DumpWallet RPC invocation (or an applicable error) -type FutureDumpWalletResult chan *response +type FutureDumpWalletResult chan *Response -// Receive waits for the response promised by the future +// Receive waits for the Response promised by the future func (r FutureDumpWalletResult) Receive() (*btcjson.DumpWalletResult, error) { - bytes, err := receiveFuture(r) + bytes, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2740,7 +2740,7 @@ func (r FutureDumpWalletResult) Receive() (*btcjson.DumpWalletResult, error) { // // See DumpWalletAsync for the blocking version and more details. func (c *Client) DumpWalletAsync(destination string) FutureDumpWalletResult { - return c.sendCmd(btcjson.NewDumpWalletCmd(destination)) + return c.SendCmd(btcjson.NewDumpWalletCmd(destination)) } // DumpWallet dumps all wallet keys in a human-readable format to a server-side file. @@ -2750,11 +2750,11 @@ func (c *Client) DumpWallet(destination string) (*btcjson.DumpWalletResult, erro // FutureImportWalletResult is a future promise to deliver the result of an // ImportWalletAsync RPC invocation (or an applicable error) -type FutureImportWalletResult chan *response +type FutureImportWalletResult chan *Response -// Receive waits for the response promised by the future +// Receive waits for the Response promised by the future func (r FutureImportWalletResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2764,7 +2764,7 @@ func (r FutureImportWalletResult) Receive() error { // // See ImportWallet for the blocking version and more details. func (c *Client) ImportWalletAsync(filename string) FutureImportWalletResult { - return c.sendCmd(btcjson.NewImportWalletCmd(filename)) + return c.SendCmd(btcjson.NewImportWalletCmd(filename)) } // ImportWallet imports keys from a wallet dump file (see DumpWallet). @@ -2774,11 +2774,11 @@ func (c *Client) ImportWallet(filename string) error { // FutureUnloadWalletResult is a future promise to deliver the result of an // UnloadWalletAsync RPC invocation (or an applicable error) -type FutureUnloadWalletResult chan *response +type FutureUnloadWalletResult chan *Response -// Receive waits for the response promised by the future +// Receive waits for the Response promised by the future func (r FutureUnloadWalletResult) Receive() error { - _, err := receiveFuture(r) + _, err := ReceiveFuture(r) return err } @@ -2788,7 +2788,7 @@ func (r FutureUnloadWalletResult) Receive() error { // // See UnloadWallet for the blocking version and more details. func (c *Client) UnloadWalletAsync(walletName *string) FutureUnloadWalletResult { - return c.sendCmd(btcjson.NewUnloadWalletCmd(walletName)) + return c.SendCmd(btcjson.NewUnloadWalletCmd(walletName)) } // UnloadWallet unloads the referenced wallet. If the RPC server URL already @@ -2800,11 +2800,11 @@ func (c *Client) UnloadWallet(walletName *string) error { // FutureLoadWalletResult is a future promise to deliver the result of an // LoadWalletAsync RPC invocation (or an applicable error) -type FutureLoadWalletResult chan *response +type FutureLoadWalletResult chan *Response -// Receive waits for the response promised by the future +// Receive waits for the Response promised by the future func (r FutureLoadWalletResult) Receive() (*btcjson.LoadWalletResult, error) { - bytes, err := receiveFuture(r) + bytes, err := ReceiveFuture(r) if err != nil { return nil, err } @@ -2819,7 +2819,7 @@ func (r FutureLoadWalletResult) Receive() (*btcjson.LoadWalletResult, error) { // // See LoadWallet for the blocking version and more details. func (c *Client) LoadWalletAsync(walletName string) FutureLoadWalletResult { - return c.sendCmd(btcjson.NewLoadWalletCmd(walletName)) + return c.SendCmd(btcjson.NewLoadWalletCmd(walletName)) } // LoadWallet loads a wallet from a wallet file or directory. From 73f7eac903576be8c8c08b2069c7a400be047ec7 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 13 Sep 2021 21:11:26 +0200 Subject: [PATCH 0456/1056] btcec: check if recovered pk is at point of infinity --- btcec/signature.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/btcec/signature.go b/btcec/signature.go index cdd7cedfb8..8a8f8301b7 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -353,6 +353,10 @@ func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte, // step to prevent the jacobian conversion back and forth. Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy) + if Qx.Sign() == 0 && Qy.Sign() == 0 { + return nil, errors.New("point (Qx, Qy) equals the point at infinity") + } + return &PublicKey{ Curve: curve, X: Qx, From 5e6736aad5785f9a3dc8912a122085271f7941c0 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 13 Sep 2021 21:38:27 +0200 Subject: [PATCH 0457/1056] btcec: added testcase for point at infinity --- btcec/signature_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/btcec/signature_test.go b/btcec/signature_test.go index ba02a03f76..b58d186775 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -549,6 +549,12 @@ var recoveryTests = []struct { sig: "0100b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f00b940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", err: fmt.Errorf("invalid square root"), }, + { + // Point at infinity recovered + msg: "6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9", + sig: "0079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9", + err: fmt.Errorf("point (Qx, Qy) equals the point at infinity"), + }, { // Low R and S values. msg: "ba09edc1275a285fb27bfe82c4eea240a907a0dbaf9e55764b8f318c37d5974f", From 7ae5b74dee05b366e6931cdada4c61e9b40a57b6 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 15 Sep 2021 18:18:04 -0700 Subject: [PATCH 0458/1056] build: bump min Go version to 1.16.8 add Go 1.17.1 --- .github/workflows/go.yml | 2 +- README.md | 2 +- docs/installation.md | 2 +- go.mod | 2 +- go.sum | 11 ----------- 5 files changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 8803194d69..c7ffb79033 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go: [1.14, 1.15] + go: [1.16.8, 1.17.1] steps: - name: Set up Go uses: actions/setup-go@v2 diff --git a/README.md b/README.md index 556673825e..5ec1454fcc 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ which are both under active development. ## Requirements -[Go](http://golang.org) 1.14 or newer. +[Go](http://golang.org) 1.16 or newer. ## Installation diff --git a/docs/installation.md b/docs/installation.md index c3c206060b..a74db56022 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -5,7 +5,7 @@ details on how to install on the supported operating systems. ## Requirements -[Go](http://golang.org) 1.11 or newer. +[Go](http://golang.org) 1.16 or newer. ## GPG Verification Key diff --git a/go.mod b/go.mod index 049b97fe6c..7722564f57 100644 --- a/go.mod +++ b/go.mod @@ -14,4 +14,4 @@ require ( golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 ) -go 1.14 +go 1.16 diff --git a/go.sum b/go.sum index e259d0ec77..4c5a352a89 100644 --- a/go.sum +++ b/go.sum @@ -3,17 +3,14 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= @@ -27,13 +24,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -47,27 +41,22 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44 h1:9lP3x0pW80sDI6t1UMSLA4to18W7R7imwAI/sWS9S8Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= From f8e6854197cd337b652c1260999a8a397d0d4703 Mon Sep 17 00:00:00 2001 From: eugene Date: Mon, 16 Aug 2021 12:40:38 -0400 Subject: [PATCH 0459/1056] mempool: introduce GetDustThreshold to export dust limit calculation This commit modifies no behavior and would allow other projects to retrieve the dust limit for a particular output type before the amount of the output is known. This is particularly useful in the Lightning Network for channel negotiation. --- mempool/policy.go | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/mempool/policy.go b/mempool/policy.go index 74142bf60c..1fe850797f 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -172,17 +172,10 @@ func checkPkScriptStandard(pkScript []byte, scriptClass txscript.ScriptClass) er return nil } -// IsDust returns whether or not the passed transaction output amount is -// considered dust or not based on the passed minimum transaction relay fee. -// Dust is defined in terms of the minimum transaction relay fee. In -// particular, if the cost to the network to spend coins is more than 1/3 of the -// minimum transaction relay fee, it is considered dust. -func IsDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { - // Unspendable outputs are considered dust. - if txscript.IsUnspendable(txOut.PkScript) { - return true - } - +// GetDustThreshold calculates the dust limit for a *wire.TxOut by taking the +// size of a typical spending transaction and multiplying it by 3 to account +// for the minimum dust relay fee of 3000sat/kvb. +func GetDustThreshold(txOut *wire.TxOut) int64 { // The total serialized size consists of the output and the associated // input script to redeem it. Since there is no input script // to redeem it yet, use the minimum size of a typical input script. @@ -253,6 +246,20 @@ func IsDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { totalSize += 107 } + return 3 * int64(totalSize) +} + +// IsDust returns whether or not the passed transaction output amount is +// considered dust or not based on the passed minimum transaction relay fee. +// Dust is defined in terms of the minimum transaction relay fee. In +// particular, if the cost to the network to spend coins is more than 1/3 of the +// minimum transaction relay fee, it is considered dust. +func IsDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { + // Unspendable outputs are considered dust. + if txscript.IsUnspendable(txOut.PkScript) { + return true + } + // The output is considered dust if the cost to the network to spend the // coins is more than 1/3 of the minimum free transaction relay fee. // minFreeTxRelayFee is in Satoshi/KB, so multiply by 1000 to @@ -265,7 +272,7 @@ func IsDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { // // The following is equivalent to (value/totalSize) * (1/3) * 1000 // without needing to do floating point math. - return txOut.Value*1000/(3*int64(totalSize)) < int64(minRelayTxFee) + return txOut.Value*1000/GetDustThreshold(txOut) < int64(minRelayTxFee) } // checkTransactionStandard performs a series of checks on a transaction to From 4caf037c52afca038148cf2513f8c41945e57c07 Mon Sep 17 00:00:00 2001 From: naveen <172697+naveensrinivasan@users.noreply.github.com> Date: Fri, 17 Sep 2021 15:07:31 +0000 Subject: [PATCH 0460/1056] Upgraded the docker version to 1.16 With this changes https://github.com/btcsuite/btcd/pull/1753/ merged in the docker image also has to be upgraded. --- Dockerfile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3bbc25712b..ec45ee64c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,13 @@ # 8334 Mainet RPC port ARG ARCH=amd64 - -FROM golang:1.14-alpine3.12 AS build-container +# using the SHA256 instead of tags +# https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests +# https://cloud.google.com/architecture/using-container-images +# https://github.com/google/go-containerregistry/blob/main/cmd/crane/README.md +# ➜ ~ crane digest golang:1.16-alpine3.12 +# sha256:db2475a1dbb2149508e5db31d7d77a75e6600d54be645f37681f03f2762169ba +FROM golang@sha256:db2475a1dbb2149508e5db31d7d77a75e6600d54be645f37681f03f2762169ba AS build-container ARG ARCH ENV GO111MODULE=on From e98a1a1b4cd7c59465a8f21bce80839b99a7337e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 15 Sep 2021 18:12:37 -0700 Subject: [PATCH 0461/1056] peer+server: add new config option to optionally disable stall detection In this commit, we add a new config options that allows one to start `btcd` in an operating mode that disables the stall detection. This can be useful in simnet/regtest integration tests settings where it's important that `btcd` holds on to its possibly sole connection to the only other node in the test harness. A new config flag has been added to gate this behavior, which is off by default. --- config.go | 12 ++++++++++++ peer/peer.go | 15 +++++++++++++++ server.go | 23 ++++++++++++----------- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/config.go b/config.go index 7124fe9290..156084bcf9 100644 --- a/config.go +++ b/config.go @@ -29,6 +29,7 @@ import ( _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/peer" + "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/btcsuite/go-socks/socks" flags "github.com/jessevdk/go-flags" @@ -135,6 +136,7 @@ type config struct { NoRelayPriority bool `long:"norelaypriority" description:"Do not require free or low-fee transactions to have high priority for relaying"` NoWinService bool `long:"nowinservice" description:"Do not start as a background service on Windows -- NOTE: This flag only works on the command line, not in the config file"` DisableRPC bool `long:"norpc" description:"Disable built-in RPC server -- NOTE: The RPC server is disabled by default if no rpcuser/rpcpass or rpclimituser/rpclimitpass is specified"` + DisableStallHandler bool `long:"nostalldetect" description:"Disables the stall handler system for each peer, useful in simnet/regtest integration tests frameworks"` DisableTLS bool `long:"notls" description:"Disable TLS for the RPC server -- NOTE: This is only allowed if the RPC server is bound to localhost"` OnionProxy string `long:"onion" description:"Connect to tor hidden services via SOCKS5 proxy (eg. 127.0.0.1:9050)"` OnionProxyPass string `long:"onionpass" default-mask:"-" description:"Password for onion proxy server"` @@ -603,6 +605,16 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } + // If mainnet is active, then we won't allow the stall handler to be + // disabled. + if activeNetParams.Params.Net == wire.MainNet && cfg.DisableStallHandler { + str := "%s: stall handler cannot be disabled on mainnet" + err := fmt.Errorf(str, funcName) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + // Set the default policy for relaying non-standard transactions // according to the default of the active network. The set // configuration value takes precedence over the default value for the diff --git a/peer/peer.go b/peer/peer.go index 92ac3d27e8..a7b925802f 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -276,6 +276,13 @@ type Config struct { // connection detecting and disconnect logic since they intentionally // do so for testing purposes. AllowSelfConns bool + + // DisableStallHandler if true, then the stall handler that attempts to + // disconnect from peers that appear to be taking too long to respond + // to requests won't be activated. This can be useful in certain simnet + // scenarios where the stall behavior isn't important to the system + // under test. + DisableStallHandler bool } // minUint32 is a helper function to return the minimum of two uint32s. @@ -1202,6 +1209,10 @@ out: for { select { case msg := <-p.stallControl: + if p.cfg.DisableStallHandler { + continue + } + switch msg.command { case sccSendMessage: // Add a deadline for the expected response @@ -1264,6 +1275,10 @@ out: } case <-stallTicker.C: + if p.cfg.DisableStallHandler { + continue + } + // Calculate the offset to apply to the deadline based // on how long the handlers have taken to execute since // the last tick. diff --git a/server.go b/server.go index ba7932a1a4..746c48dde3 100644 --- a/server.go +++ b/server.go @@ -2054,17 +2054,18 @@ func newPeerConfig(sp *serverPeer) *peer.Config { // other implementations' alert messages, we will not relay theirs. OnAlert: nil, }, - NewestBlock: sp.newestBlock, - HostToNetAddress: sp.server.addrManager.HostToNetAddress, - Proxy: cfg.Proxy, - UserAgentName: userAgentName, - UserAgentVersion: userAgentVersion, - UserAgentComments: cfg.UserAgentComments, - ChainParams: sp.server.chainParams, - Services: sp.server.services, - DisableRelayTx: cfg.BlocksOnly, - ProtocolVersion: peer.MaxProtocolVersion, - TrickleInterval: cfg.TrickleInterval, + NewestBlock: sp.newestBlock, + HostToNetAddress: sp.server.addrManager.HostToNetAddress, + Proxy: cfg.Proxy, + UserAgentName: userAgentName, + UserAgentVersion: userAgentVersion, + UserAgentComments: cfg.UserAgentComments, + ChainParams: sp.server.chainParams, + Services: sp.server.services, + DisableRelayTx: cfg.BlocksOnly, + ProtocolVersion: peer.MaxProtocolVersion, + TrickleInterval: cfg.TrickleInterval, + DisableStallHandler: cfg.DisableStallHandler, } } From a148fa797a732aefd189514b666cab11bab914c0 Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Wed, 20 Oct 2021 11:59:18 -0500 Subject: [PATCH 0462/1056] addrmgr: make KnownAddress methods thread-safe This gives KnownAddress a sync.RWMutex so the exported methods may safely access the na (*wire.NetAddress) and lastattempt fields. The AddrManager is updated to lock the new KnownAddress mutex before assigning to na or lastattempt. The other KnownAddress fields are only accessed by AddrManager, using its own Mutex for synchronization. --- addrmgr/addrmanager.go | 17 ++++++++++++++--- addrmgr/knownaddress.go | 11 +++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index fa8f27bcae..4c737b937e 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -176,7 +176,7 @@ func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddress) { // TODO: only update addresses periodically. // Update the last seen time and services. // note that to prevent causing excess garbage on getaddr - // messages the netaddresses in addrmaanger are *immutable*, + // messages the netaddresses in addrmanager are *immutable*, // if we need to change them then we replace the pointer with a // new copy so that we don't have to copy every na for getaddr. if netAddr.Timestamp.After(ka.na.Timestamp) || @@ -186,7 +186,9 @@ func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddress) { naCopy := *ka.na naCopy.Timestamp = netAddr.Timestamp naCopy.AddService(netAddr.Services) + ka.mtx.Lock() ka.na = &naCopy + ka.mtx.Unlock() } // If already in tried, we have nothing to do here. @@ -857,8 +859,11 @@ func (a *AddrManager) Attempt(addr *wire.NetAddress) { return } // set last tried time to now + now := time.Now() + ka.mtx.Lock() ka.attempts++ - ka.lastattempt = time.Now() + ka.lastattempt = now + ka.mtx.Unlock() } // Connected Marks the given address as currently connected and working at the @@ -880,7 +885,9 @@ func (a *AddrManager) Connected(addr *wire.NetAddress) { // ka.na is immutable, so replace it. naCopy := *ka.na naCopy.Timestamp = time.Now() + ka.mtx.Lock() ka.na = &naCopy + ka.mtx.Unlock() } } @@ -899,11 +906,13 @@ func (a *AddrManager) Good(addr *wire.NetAddress) { // ka.Timestamp is not updated here to avoid leaking information // about currently connected peers. now := time.Now() + ka.mtx.Lock() ka.lastsuccess = now ka.lastattempt = now ka.attempts = 0 + ka.mtx.Unlock() // tried and refs synchronized via a.mtx - // move to tried set, optionally evicting other addresses if neeed. + // move to tried set, optionally evicting other addresses if need. if ka.tried { return } @@ -988,7 +997,9 @@ func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFl // ka.na is immutable, so replace it. naCopy := *ka.na naCopy.Services = services + ka.mtx.Lock() ka.na = &naCopy + ka.mtx.Unlock() } } diff --git a/addrmgr/knownaddress.go b/addrmgr/knownaddress.go index 15469f374e..5a7674f45b 100644 --- a/addrmgr/knownaddress.go +++ b/addrmgr/knownaddress.go @@ -5,6 +5,7 @@ package addrmgr import ( + "sync" "time" "github.com/btcsuite/btcd/wire" @@ -13,6 +14,7 @@ import ( // KnownAddress tracks information about a known network address that is used // to determine how viable an address is. type KnownAddress struct { + mtx sync.RWMutex // na and lastattempt na *wire.NetAddress srcAddr *wire.NetAddress attempts int @@ -25,19 +27,28 @@ type KnownAddress struct { // NetAddress returns the underlying wire.NetAddress associated with the // known address. func (ka *KnownAddress) NetAddress() *wire.NetAddress { + ka.mtx.RLock() + defer ka.mtx.RUnlock() return ka.na } // LastAttempt returns the last time the known address was attempted. func (ka *KnownAddress) LastAttempt() time.Time { + ka.mtx.RLock() + defer ka.mtx.RUnlock() return ka.lastattempt } // Services returns the services supported by the peer with the known address. func (ka *KnownAddress) Services() wire.ServiceFlag { + ka.mtx.RLock() + defer ka.mtx.RUnlock() return ka.na.Services } +// The unexported methods, chance and isBad, are used from within AddrManager +// where KnownAddress field access is synchronized via it's own Mutex. + // chance returns the selection probability for a known address. The priority // depends upon how recently the address has been seen, how recently it was last // attempted and how often attempts to connect to it have failed. From d590f3f77d3dd218fb33d297bc84493f1d61bba8 Mon Sep 17 00:00:00 2001 From: pengyonghui <421640644@qq.com> Date: Mon, 18 Oct 2021 15:11:12 +0800 Subject: [PATCH 0463/1056] fix typo --- mempool/mempool.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 7ada3d2907..5595a11bfe 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -1032,8 +1032,8 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec return nil, nil, err } - // Don't allow the transaction if it exists in the main chain and is not - // not already fully spent. + // Don't allow the transaction if it exists in the main chain and is + // already fully spent. prevOut := wire.OutPoint{Hash: *txHash} for txOutIdx := range tx.MsgTx().TxOut { prevOut.Index = uint32(txOutIdx) From c56a053fdfb6389c4855ee00918fdc4d177f03f2 Mon Sep 17 00:00:00 2001 From: pengyonghui <421640644@qq.com> Date: Mon, 18 Oct 2021 15:48:51 +0800 Subject: [PATCH 0464/1056] fix typos --- mempool/mempool.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index 5595a11bfe..b54856c8b3 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -1054,7 +1054,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec if entry == nil || entry.IsSpent() { // Must make a copy of the hash here since the iterator // is replaced and taking its address directly would - // result in all of the entries pointing to the same + // result in all the entries pointing to the same // memory location and thus all be the final hash. hashCopy := outpoint.Hash missingParents = append(missingParents, &hashCopy) @@ -1100,7 +1100,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec if err != nil { // Attempt to extract a reject code from the error so // it can be retained. When not possible, fall back to - // a non standard error. + // a non-standard error. rejectCode, found := extractRejectCode(err) if !found { rejectCode = wire.RejectNonstandard @@ -1143,7 +1143,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec // calculated below on its own would encourage several small // transactions to avoid fees rather than one single larger transaction // which is more desirable. Therefore, as long as the size of the - // transaction does not exceeed 1000 less than the reserved space for + // transaction does not exceed 1000 less than the reserved space for // high-priority transactions, don't require a fee for it. serializedSize := GetTxVirtualSize(tx) minFee := calcMinRequiredTxRelayFee(serializedSize, @@ -1194,7 +1194,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec mp.cfg.Policy.FreeTxRelayLimit*10*1000) } - // If the transaction has any conflicts and we've made it this far, then + // If the transaction has any conflicts, and we've made it this far, then // we're processing a potential replacement. var conflicts map[chainhash.Hash]*btcutil.Tx if isReplacement { @@ -1366,7 +1366,7 @@ func (mp *TxPool) ProcessOrphans(acceptedTx *btcutil.Tx) []*TxDesc { // // It returns a slice of transactions added to the mempool. When the // error is nil, the list will include the passed transaction itself along -// with any additional orphan transaactions that were added as a result of +// with any additional orphan transactions that were added as a result of // the passed one being accepted. // // This function is safe for concurrent access. @@ -1435,7 +1435,7 @@ func (mp *TxPool) Count() int { return count } -// TxHashes returns a slice of hashes for all of the transactions in the memory +// TxHashes returns a slice of hashes for all the transactions in the memory // pool. // // This function is safe for concurrent access. @@ -1488,7 +1488,7 @@ func (mp *TxPool) MiningDescs() []*mining.TxDesc { return descs } -// RawMempoolVerbose returns all of the entries in the mempool as a fully +// RawMempoolVerbose returns all the entries in the mempool as a fully // populated btcjson result. // // This function is safe for concurrent access. From 31791ba4dc6ef913b1e8eb7bfb6746b1a118e405 Mon Sep 17 00:00:00 2001 From: naveen <172697+naveensrinivasan@users.noreply.github.com> Date: Fri, 17 Sep 2021 16:03:07 +0000 Subject: [PATCH 0465/1056] Included permissions for GitHub action The default GitHub Action is write which is not required for this action. --- .github/workflows/go.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index c7ffb79033..5da1bebc63 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -2,6 +2,9 @@ name: Build and Test on: [push, pull_request] jobs: build: + # https://github.blog/changelog/2021-04-20-github-actions-control-permissions-for-github_token/ + permissions: + contents: read name: Go CI runs-on: ubuntu-latest strategy: From 65e986844ebd50f0eb47ade893c53103585fce4e Mon Sep 17 00:00:00 2001 From: Aarush Bhat Date: Mon, 6 Sep 2021 11:19:39 +0530 Subject: [PATCH 0466/1056] Update connmanager_test.go --- connmgr/connmanager_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connmgr/connmanager_test.go b/connmgr/connmanager_test.go index 67769deb96..94cb65ff2a 100644 --- a/connmgr/connmanager_test.go +++ b/connmgr/connmanager_test.go @@ -464,7 +464,7 @@ func TestRemovePendingConnection(t *testing.T) { time.Sleep(10 * time.Millisecond) // Now examine the status of the connection request, it should read a - // status of failed. + // status of ConnCanceled. if cr.State() != ConnCanceled { t.Fatalf("request wasn't canceled, status is: %v", cr.State()) } From cc7327c194daa4562d9ff472817c3e61448dfa8b Mon Sep 17 00:00:00 2001 From: 3nprob <3nprob@3nprob> Date: Sat, 21 Aug 2021 22:04:31 +0900 Subject: [PATCH 0467/1056] rpcclient: Add retry with backoffs to HTTP POST requests Adds behavior similar to the retries of persistent RPC connections to HTTP request. * Initial backoff: 500ms * Linear increase * Max retries: 10 Room for future improvement: * Make configurable * Add jitter * Tests for retry behavior --- rpcclient/infrastructure.go | 121 ++++++++++++++++++------------------ 1 file changed, 60 insertions(+), 61 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 7255289282..63874c1b4e 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -86,15 +86,11 @@ const ( // connectionRetryInterval is the amount of time to wait in between // retries when automatically reconnecting to an RPC server. connectionRetryInterval = time.Second * 5 -) -// sendPostDetails houses an HTTP POST request to send to an RPC server as well -// as the original JSON-RPC command and a channel to reply on when the server -// responds with the result. -type sendPostDetails struct { - httpRequest *http.Request - jsonRequest *jsonRequest -} + // requestRetryInterval is the initial amount of time to wait in between + // retries when sending HTTP POST requests. + requestRetryInterval = time.Millisecond * 500 +) // jsonRequest holds information about a json request that is used to properly // detect, interpret, and deliver a reply to it. @@ -183,7 +179,7 @@ type Client struct { // Networking infrastructure. sendChan chan []byte - sendPostChan chan *sendPostDetails + sendPostChan chan *jsonRequest connEstablished chan struct{} disconnect chan struct{} shutdown chan struct{} @@ -765,10 +761,50 @@ out: // handleSendPostMessage handles performing the passed HTTP request, reading the // result, unmarshalling it, and delivering the unmarshalled result to the // provided response channel. -func (c *Client) handleSendPostMessage(details *sendPostDetails) { - jReq := details.jsonRequest - log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id) - httpResponse, err := c.httpClient.Do(details.httpRequest) +func (c *Client) handleSendPostMessage(jReq *jsonRequest) { + protocol := "http" + if !c.config.DisableTLS { + protocol = "https" + } + url := protocol + "://" + c.config.Host + + var err error + var backoff time.Duration + var httpResponse *http.Response + tries := 10 + for i := 0; tries == 0 || i < tries; i++ { + bodyReader := bytes.NewReader(jReq.marshalledJSON) + httpReq, err := http.NewRequest("POST", url, bodyReader) + if err != nil { + jReq.responseChan <- &Response{result: nil, err: err} + return + } + httpReq.Close = true + httpReq.Header.Set("Content-Type", "application/json") + for key, value := range c.config.ExtraHeaders { + httpReq.Header.Set(key, value) + } + + // Configure basic access authorization. + user, pass, err := c.config.getAuth() + if err != nil { + jReq.responseChan <- &Response{result: nil, err: err} + return + } + httpReq.SetBasicAuth(user, pass) + + httpResponse, err = c.httpClient.Do(httpReq) + if err != nil { + backoff = requestRetryInterval * time.Duration(i+1) + if backoff > time.Minute { + backoff = time.Minute + } + log.Debugf("Failed command [%s] with id %d attempt %d. Retrying in %v... \n", jReq.method, jReq.id, i, backoff) + time.Sleep(backoff) + continue + } + break + } if err != nil { jReq.responseChan <- &Response{err: err} return @@ -821,8 +857,8 @@ out: // Send any messages ready for send until the shutdown channel // is closed. select { - case details := <-c.sendPostChan: - c.handleSendPostMessage(details) + case jReq := <-c.sendPostChan: + c.handleSendPostMessage(jReq) case <-c.shutdown: break out @@ -834,8 +870,8 @@ out: cleanup: for { select { - case details := <-c.sendPostChan: - details.jsonRequest.responseChan <- &Response{ + case jReq := <-c.sendPostChan: + jReq.responseChan <- &Response{ result: nil, err: ErrClientShutdown, } @@ -852,7 +888,7 @@ cleanup: // sendPostRequest sends the passed HTTP request to the RPC server using the // HTTP client associated with the client. It is backed by a buffered channel, // so it will not block until the send channel is full. -func (c *Client) sendPostRequest(httpReq *http.Request, jReq *jsonRequest) { +func (c *Client) sendPostRequest(jReq *jsonRequest) { // Don't send the message if shutting down. select { case <-c.shutdown: @@ -860,10 +896,9 @@ func (c *Client) sendPostRequest(httpReq *http.Request, jReq *jsonRequest) { default: } - c.sendPostChan <- &sendPostDetails{ - jsonRequest: jReq, - httpRequest: httpReq, - } + log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id) + + c.sendPostChan <- jReq } // newFutureError returns a new future result channel that already has the @@ -885,42 +920,6 @@ func ReceiveFuture(f chan *Response) ([]byte, error) { return r.result, r.err } -// sendPost sends the passed request to the server by issuing an HTTP POST -// request using the provided response channel for the reply. Typically a new -// connection is opened and closed for each command when using this method, -// however, the underlying HTTP client might coalesce multiple commands -// depending on several factors including the remote server configuration. -func (c *Client) sendPost(jReq *jsonRequest) { - // Generate a request to the configured RPC server. - protocol := "http" - if !c.config.DisableTLS { - protocol = "https" - } - url := protocol + "://" + c.config.Host - bodyReader := bytes.NewReader(jReq.marshalledJSON) - httpReq, err := http.NewRequest("POST", url, bodyReader) - if err != nil { - jReq.responseChan <- &Response{result: nil, err: err} - return - } - httpReq.Close = true - httpReq.Header.Set("Content-Type", "application/json") - for key, value := range c.config.ExtraHeaders { - httpReq.Header.Set(key, value) - } - - // Configure basic access authorization. - user, pass, err := c.config.getAuth() - if err != nil { - jReq.responseChan <- &Response{result: nil, err: err} - return - } - httpReq.SetBasicAuth(user, pass) - - log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id) - c.sendPostRequest(httpReq, jReq) -} - // sendRequest sends the passed json request to the associated server using the // provided response channel for the reply. It handles both websocket and HTTP // POST mode depending on the configuration of the client. @@ -935,7 +934,7 @@ func (c *Client) sendRequest(jReq *jsonRequest) { log.Warn(err) } } else { - c.sendPost(jReq) + c.sendPostRequest(jReq) } return } @@ -1428,7 +1427,7 @@ func New(config *ConnConfig, ntfnHandlers *NotificationHandlers) (*Client, error ntfnHandlers: ntfnHandlers, ntfnState: newNotificationState(), sendChan: make(chan []byte, sendBufferSize), - sendPostChan: make(chan *sendPostDetails, sendPostBufferSize), + sendPostChan: make(chan *jsonRequest, sendPostBufferSize), connEstablished: connEstablished, disconnect: make(chan struct{}), shutdown: make(chan struct{}), @@ -1642,7 +1641,7 @@ func (c *Client) sendAsync() FutureGetBulkResult { marshalledJSON: marshalledRequest, responseChan: responseChan, } - c.sendPost(&request) + c.sendPostRequest(&request) return responseChan } From 843d7607ef8d984ed53fcf8432792b3f852b7594 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:00 -0500 Subject: [PATCH 0468/1056] txscript: Add benchmark for CalcSignatureHash --- txscript/bench_test.go | 52 ++++++++++++++++++++++++++++++++ txscript/data/many_inputs_tx.hex | 1 + 2 files changed, 53 insertions(+) create mode 100644 txscript/bench_test.go create mode 100644 txscript/data/many_inputs_tx.hex diff --git a/txscript/bench_test.go b/txscript/bench_test.go new file mode 100644 index 0000000000..b129b80386 --- /dev/null +++ b/txscript/bench_test.go @@ -0,0 +1,52 @@ +// Copyright (c) 2018-2019 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txscript + +import ( + "bytes" + "fmt" + "io/ioutil" + "testing" + + "github.com/btcsuite/btcd/wire" +) + +var ( + // manyInputsBenchTx is a transaction that contains a lot of inputs which is + // useful for benchmarking signature hash calculation. + manyInputsBenchTx wire.MsgTx + + // A mock previous output script to use in the signing benchmark. + prevOutScript = hexToBytes("a914f5916158e3e2c4551c1796708db8367207ed13bb87") +) + +func init() { + // tx 620f57c92cf05a7f7e7f7d28255d5f7089437bc48e34dcfebf7751d08b7fb8f5 + txHex, err := ioutil.ReadFile("data/many_inputs_tx.hex") + if err != nil { + panic(fmt.Sprintf("unable to read benchmark tx file: %v", err)) + } + + txBytes := hexToBytes(string(txHex)) + err = manyInputsBenchTx.Deserialize(bytes.NewReader(txBytes)) + if err != nil { + panic(err) + } +} + +// BenchmarkCalcSigHash benchmarks how long it takes to calculate the signature +// hashes for all inputs of a transaction with many inputs. +func BenchmarkCalcSigHash(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for j := 0; j < len(manyInputsBenchTx.TxIn); j++ { + _, err := CalcSignatureHash(prevOutScript, SigHashAll, + &manyInputsBenchTx, j) + if err != nil { + b.Fatalf("failed to calc signature hash: %v", err) + } + } + } +} diff --git a/txscript/data/many_inputs_tx.hex b/txscript/data/many_inputs_tx.hex new file mode 100644 index 0000000000..2f9833de02 --- /dev/null +++ b/txscript/data/many_inputs_tx.hex @@ -0,0 +1 @@ +010000005901fa054079e69a46e5aacd8b57f94c3c99744d68c6097957eaa9021c344141a90000000000ffffffff020706fa6444e4c9d110274488a4641161165370cd11a208ad3a3a00178e1d9c0000000000ffffffff0210805cd4cceae0873daaf8b81d2eb7122cdcdf2dfae5a90569378f847e293c0000000000ffffffff021d93a6970f13f10f6b8b1b5763f772f1f37350f893cb305005319a76069f5a0000000000ffffffff021fa71c8d5f8c455820e6d83c6fca218ed2e70391c7dfba4119168c7ebc68c30000000000ffffffff0227b4b9041f1c8ac86ea16f48909c94adac7081b26a36ed5863e4c53175262b0000000000ffffffff0228a49d6e91275b9d0d8aa5f6e81d4e1e9cd957ecfdabd6df68fe6f4970a0b60000000000ffffffff022db9dd2128b6d1f1eba30a681f062f6eaad362e58b23e6cadcd2cb8d65d6880000000000ffffffff0243411baa5b4b3357849e505310dbd29a8a50e6324c4655e403043ac07ce9d10000000000ffffffff024b630ce631441c527d555c237bb68b694d50010b7723957ef4537185eef6c40000000000ffffffff025312b6a2f95a25a109b4f0b46fb35abd74b15a39241291dd3673f1dd58fd3b0000000000ffffffff02554f0d7fe6df9454c8152c6f46429596abc08b57d7cfbc7f5f22db8a0787e00000000000ffffffff025793409101621f48c0f9ebdef0867088c015c5e412ccbdd1d32a5de62ae1b80000000000ffffffff025b53aa8359a7a3fd92d69ef96be30dfed1ea99fa03db0050f3f6d3b9e2b7320000000000ffffffff025cfc35711a57b373b807bbfaadf0950b81a74d0215a0508f2e62989bdbb4aa0000000000ffffffff025ddd8921db66b54f1ad8ef2eae70913d22e5579e2781a1e485fc6a555f6e410000000000ffffffff026466da9b3ebf93b07e7de704789d5ae04f584fa39043716a9830edf5bf99140000000000ffffffff027904d29d4cb521d7c884325b1d42434bc99b6d712681e5e254597821a944550000000000ffffffff027c662f67150bca47a7b23f0fb7c50956b21a4f46b9f4c4a304d51ce9c5900f0000000000ffffffff027ef5afdeab2ec6515a739dc00c2ef8994303c19a74fd0512f8306fb601d10f0000000000ffffffff0284cdef7bdd0c45efdecb2a3a68079d7e01ccc8e229a3e72160ec93218b1ad90000000000ffffffff028885c672656acd03755167361be6ccd94ad72c5e3890773f11a5c627f046890000000000ffffffff028b372c55109471551db0aa772aa66321862fb3a11e4cd7a31cdc4ed989436d0000000000ffffffff0290198f3a73a8febae55d559676303ae495acbad11dde304c21483a951078270000000000ffffffff0298dc5698fb1823ee1ec7469936e0b9b71e69e843d993b2c0096ac3c1d86bb20000000000ffffffff029c5d6da641328e356368383951c5dad56398f29f58a922eb54afaf888e41430000000000ffffffff02d702320af97f4f498aedf0886cd6123692f6d7b6f0b1da3910703648bc80c40000000000ffffffff02d90670fc2d34b7fcfce03ecb3a3650a4cd384eca645c2b05263721e9a5c19f0000000000ffffffff02de1f9e03b532c0bd6a28a7066c81b7abf0f9dc7e40003f638b9a872fa9a74c0000000000ffffffff02ded955aaf74a935a479fb08d4e8ded2a99664cb2235bc617627616e0e313630000000000ffffffff02e3f8ded8a0d2716817259e4144faa83facd27a5c9550c7c65835cc2c93738a0000000000ffffffff03012cf75972966f2c7abb609b43c7e85dd65cada0ee20118c80d92d766a32400000000000ffffffff0307efdd04c2f3e033a0294aaa894b4245695876fc76c12b8523d448ef05e6620000000000ffffffff030db2a3d8afa67b68f0ae663cc88bee0af0a8900e88f099d2ee648603e7b0e30000000000ffffffff03133fb852424925f55c8a660fdec8a10dce9bb9b500bf07bc73e2641f1a55310000000000ffffffff0313954647c73d9c63e4e83d36e337b17797be10eb0d641deaff0c768aa6db060000000000ffffffff031bfd6a0bfc310e204fc0eb5e1c83b9d21dab82847b909db111a371ffdcb5a20000000000ffffffff032588268e35fbd648c621638633ef8188e8b946ebd3d5833a18d9bae556ee5c0000000000ffffffff03378677fc365f67102c2559a2a4300344d41a63920e7450951fc6d8d63fb0110000000000ffffffff033c9955351d351b4f5ac398adce94b2a7ed3ab14a1c790c8e4742b1558c6b200000000000ffffffff034061cfcca9fb77d28d2411f4502c3696e0aa28b040f6780a4bd00c3fa8a02b0000000000ffffffff034b063b587eb75409e56b5ff2f9cc24a994e3ecbf9de56bd46983443067e81b0000000000ffffffff034cb2f8a145b3a55bb07dcdb904859808b29a5f53a01ba3a3cd707211afb7190000000000ffffffff034f96fa5e134b5310731b23fa9235aad58008c7c61f1b8128542b51622a52250000000000ffffffff0357236d19aef1428f117c3067a89adbecfe234ef32d744acdd6b6a5107a95e90000000000ffffffff0362504fcc65272e50ba6cc4583b4b1486592b59d943ab375ea7d6f44ba8038c0000000000ffffffff0369b02dad4259759408f8a3b1fad3c24df0873b767a9d0f1d50bd68f18c789d0000000000ffffffff036e080ba3f983e5bd7d8700dfd4b510a502231d0112c38e804b59d8a84026230000000000ffffffff038298149c290f73c535c3a184d181316ef695146a58d3bb3d2e61ed993cc11c0000000000ffffffff038538c9d6b8200609e4ca2443910daa6d9bbe772b2793e11fcf1763202c998b0000000000ffffffff038aad027dade93191c546648f7125bda82c895f1d80bf174d9637e533e12a1a0000000000ffffffff03960708a37a5654abd75755d1b8f49a84cdbde4676e14fd4863b125a94e9fc40000000000ffffffff03b0e09c55ecabf221c30a086c812e35bc9b586547cde8a83961a7ffa9067cb20000000000ffffffff03b28e682c13e7ada60cb905f8070109ec5a7800a0424c5f7afb6bd3039d48cd0000000000ffffffff03b7e8adc6174ca369ec31b4f944a6b74231d09254fde6b2bfe3416f3c6096ad0000000000ffffffff03c4f1eef6176ce6a2114dce78dd292f6db20fdae7c534d22cbada58befad6cf0000000000ffffffff03c7b5bf7fef69ae11c467f68fb551d58424e8723d05ce3ccf88385187898a710000000000ffffffff03d5150f5295b1e817f44fa34cade950c13789c4129e98eb32634aaad2abe13e0000000000ffffffff03d8250c9557188c7672009c4b14f37f96528e3f9c6889607b2e25299efe08720000000000ffffffff03de1dc49d0146dcc0cdbeb84c68a14ecb7075aba67d6494a5c8d098147843640000000000ffffffff03df8c8392bc17eddab688530697c2c221420464eb643ca8edfd30d7371ed5460000000000ffffffff03ea1dbbe72e20229648695a9b01e09b6080fb1c4632931fb810c5bfbe4b4eed0000000000ffffffff03ebf599f34a7d2cfe7bda1722f76e3df5c7fe299fd5c6e4099cfec4f551f46b0000000000ffffffff03edf95bb2c93c07d734ee8b3b1de4d4085c6b65cdbc3ca23eceec0c4d2b29a00000000000ffffffff03fe259ab7c4c03447011200d7d5236f4b1eeffd075926b78650cf1a59d570590000000000ffffffff040f71baef9c5273ac67fcba44ab29456a820274654624255c27e53ff62fdf8e0000000000ffffffff042938cae95e712592060f872cca771dfcd0218562928311c81127c3170a57bc0000000000ffffffff043a09d788547db3d1bfd8512000f9ad8bb3caab6fc24fd186663542c9f06d750000000000ffffffff043fe8a5586d0309c8dad9277bfba04fb27e7a39d279c0c9a2232e2927874d470000000000ffffffff04426f1fb4981529c32ba5756f59a2211ee9d2b9cab2c5de06a07680e833c33c0000000000ffffffff04454fa62f2c03d785307982ae406224025343f19f183e0fdff83d8e1d4cc1500000000000ffffffff04496141484d641e3b0a661210b225df50221b13bcbcb3cb8c86786890c745db0000000000ffffffff045731a8be6bfab1f9d62d2b2158591029cae655fbde8c8bdee80f183e72ca4e0000000000ffffffff04610a21533b98d3360a6f2c65be5685a1bb3a43f67da08dc1674a0f517618990000000000ffffffff0471b7883558587879bd53e13694069d95acc0d809fd0a65125ba3acdcfd66900000000000ffffffff04729b78d9b706fcb20c9cbb49ec1baf5fa782ff44d45d9a23868bcbdcbca1330000000000ffffffff04747b056b7cdd34c9891845220c2b7227a7c7c4f90e1ced6f36fd2197b26af90000000000ffffffff047a37d63a2a17986896072c77fa2e068f6e593dc64bf2ad8e180fde729fe3250000000000ffffffff04875cf5c94486e6596beaffbd7d08cf5e3111df06a89f59d65989d1485949190000000000ffffffff048944d4aa4d42ae9e864bea755a4c934713c63ce1c61d177a1ef03fd679ee330000000000ffffffff0489d5c9638a3f689c232fc1b9b59e5f82bd2e720744c4405d6537d7931edb030000000000ffffffff04a206bfdb054b041ddca180111aad2abf7b31813e4551da3a29bfb16c03534c0000000000ffffffff04a5feab7629e0cd9569aa62ea70f7ab3fdd58d3aa9bf73e8f76ac32a949d31a0000000000ffffffff04a70237d798a0b48b5abf682b806f31ff425406d93e74cde1ab4b9939ce9bc20000000000ffffffff04acd550baa26049b3dc52fb9efef1cca0b8dfa228c64482440d7217a81e587a0000000000ffffffff04b1caf936f5746da6d683eb00ae36b885fd031a8928df91e3172b1ca17f4e520000000000ffffffff04c45bd25f17cc765d8a67ca80a801c1f1c2131eb51b7b8ceb71eb898582b0380000000000ffffffff04c99a8ab69a640f9891aff371876a9d0c9043cda0430cbd436145c5574c124b0000000000ffffffff04cc0c4723cf9952c0a51db275c9d11370a95f478de98dce603d09de8e3d8e680000000000ffffffff02c6afbe970400000000001976a914c055f905fe8d14a2766801307a418f1e03ba566e88ac5ee85e0d00000000000017a914f5916158e3e2c4551c1796708db8367207ed13bb8700000000000000005923aaa80d0000000018f6020000000000fd4301473044022044e60dc7ff9d720bdc8329f97c5b321a84e0846fed248b23d399d222a074bff402204aaab1ed5df1e4b94d627d8b06171df51140e65eb056536e91103b75d032cacf0147304402200fcc38b7bff890fbd390f4bd1057c72df74c2487a3cd20edee80a20d6b2ce02902200b7893fa29f24e09358b6777a946d40166bc71c25f8e5f850059a1914e25959401473044022006430580bc312023db40b6928ba0c39141a8a59bb0613c5f6feca1c1f9b2bce90220055ffd441357bc34c246024281a7b394c7ee6a2a3c013689d95a3b9dbbb98d9e014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000009503030000000000fd4501473044022059a8f1680e80b50cb8a9180c1fabe8a66e84b34fb6c10912715fa71a5bc0f9770220531c0836d4de61d8e291c517cda25919a8b822b80b5737068120411976e5577e01483045022100a48b720930c142235cc5585a97a11d20e73a81049791526cdcee34d36f92fcef02204d2523393dfc4ba21451fa563b08f53df7c7115b65a9f2f01fd578474d308eaa01483045022100a73d3ebefadefc6dd9c7041b32bf7a3a25e49afd41bb3251c502ae6fef89316102201652f9ee39ef09335f5c8e83b3fc7591b592ff0651c5e8c4786875710cb9d1bb014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000006113030000000000fd4501483045022100a5af3c72e2e15539caf81189fa020cd4b3ac5432c512dc48772d825dfca7c60802203ad5f3caaf54593b8068ce50db67111ac166c2efb73b52b30dfb7884682faadc0147304402207796a265903387a8a612cf47a8df0aae7c251a339590b24b6d813fb4cfb2dacc022076df8e67ec560d8fb74ec7ed0cd368a4da09c98846635c662e5484f5ac5b862101483045022100eb3318b340dd14f8fb797af81d8c1784668f082e54e58cd59c1224890d7f6c19022064ce22ff6bb93806930dd34dcbc846d38028db4d4d4b9c5527b6d493dba01cbd014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000099f2020000000000fd460148304502210081e68619898e8b0f9eadf2b5a324fdd7a684f935bf2cb72eef221e4310631ebc02206c7d5f1067d2980a95bfdf3b8530898ee94138dd99715c44e30b0894a5a6031b01483045022100f675ced0b828f2bae7a8046b41869ff865c081a79e32cbd400baa8ad99a975cb022075f347b57272df25c5d49c810af71fd1ba515b27166e61ad0c2bcbbd746a818101483045022100f271a0a0a8c5cfd149bf99411c4504d9905e6f9ce9f9787744c9593cab7f1c1b0220527057676ffcdd60caf0812b20b08b94ee1f935b44614b29bb9ab59e5bc0080c014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000001b02030000000000fd4401483045022100d068f2da5ba187b9d16b06dc87f1ff241063efaa786e07668abd06f8c2bea77e02206c541479ba49347104b386c36df7e14bc087bff7a17bd9c4096356a8c780fb2701473044022027336ad739d3ae08d1d136a9b7002a97873199d82abdd4bfd0531d62294116a9022001925305ccab8a328b873126baf7977b51154b4f0436685fc21f483ad347fb8b01473044022031a20fbdd66cf2a0d59ed37eda8ac50772c25adc62035b53ea675200fc85cc1c02204c1ab7d35c53ab9a5086fbcb669452367d68c8a3f07e47843c8fc2e2dbbbccc2014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000c7f9020000000000fd4301473044022022bfa36e676571479c3dff1d1a5a5c0cee3677b5ac45c14314d242bee32664270220736875bcd0807c93c3a542dbf98c753c7164ad6830acec833cc43e157eb665180147304402203c2d6ce11bff536cd9bd4f58a930649f708a5735a26971dfd8d4efa7748c48b302201e4c69309d99c41d1c19ee200fe23547f1972173f0954e8833b8ba8ecedb6aca0147304402200e9ac49f352071840f13104f247d1a506a637d898495ffcc4aec7743ca56a2e702203e279aea8208e3128dc27173a6cfbab2bd8c2bc8f273794028ac77a129d5cab7014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000005210030000000000fd4401483045022100d8e2743e7051807e428574f9c881781b40daf0ec572dcc30357350c48683fd84022032a131a11df9571b53284a2cdceb7668e7b6442897fbfd54dfc7e26f8a3a19130147304402207798db2d9031f37eca9788b63869a91b100abfff8ba9966c91c42636e43c56bc0220499af71936bfae1579f6ae8d88dd6ff980ae1dc4fa8d1c5585d08a6461ce1e1301473044022062d193f3c5f74685fbccdd8795515f67b88c8a9aac089591fdc07a8238cbf5390220200f0d61cf48c33f7800150c8af578107c20875846b4a0f2af2a4aff9d2b172e014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000dcfb020000000000fd4501483045022100e4711a4de4d6cb64e8cdaae2a4a5033c1ae87549c8d419b42b8170ee5217e04602202784ec57a6591083dbabaabd49dea7cddd3f8a32d9497e23d4b4219a56a9395f01483045022100fd776ca1d482c1d39e3a414bd0e6d353637ef626929ca5ee37db62e3dbe3501802202abe2e1279e5a354745fc5c8f8dcf367c616d82f91052925b1e2880f3906e7670147304402201976bceee0c3bb19da53e80a10a92dd6d135c86e581f349268f58b7d6b387bb5022042616ed8eee7f19ba7bee1fd5ae5415b521615aae99c45d56f9bde39d2577b9c014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000008f00030000000000fd4501483045022100fda77866c51a7ded28a6e12d3459e32b33401b1c0426f3c727ba4542ded40d1302205981be0eafc9b2c702038844769765df04bef8e17c80d1fef65c2bdba0a8e6ca01473044022018343c7eb59ef103fe102361f9ab8c789dadcfb3e60dc9b25b429165a9625af10220367f3f95f988ae6bc29c8a400687ffd70d009fe0b650994f48c1875620440fe501483045022100ac63791400e4ab5fee7f8c8ac602017409764dd7ef7ffc07d793298277661a2202200c3de5c22cad718ae83c101e987b66f31f62cc3364e8c8505407ebf11b392b66014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000006211030000000000fd4501473044022029a09ec85ea2c7741cdab03fb1185d94029a5511bbe830d11ac22dfa7f21f452022060d4039356c9cf06be106dc81390025735cde670de5c0a5a38e3946cca95211e01483045022100ca82755fa0c2a23e207c665099d102d13a393ace8cfabee79b1a6f97ffb001a2022014e2ef964e3fb5e90743c54e620d40d79ef111be1299d917f762c442d40c2f770148304502210094e9d5926748124f8c215fb006ec2bec55e4cf469a7f8579a339c08a267ed2540220323b0224d9964cd55b9ccc3f1dd919073d83edb293d022b00497b8681624bec3014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000b009030000000000fd4501483045022100a308d49610b603e9ff378fb40620f255216f3325aedc8d9a909f9c5e8983cd4e02205c93d14a43aa5d4cf7a3d4d483c6d47ccb8c2c4b78647e6cbe490ca6e03cfad601473044022004b8e60724ecba532e2677411e2617cbc49ba42cd4843423d724797aed8ba60f0220198d033cf732b5451d5ef00666ecd19bf4ea8a08f6c5fc16f4e153f1759021ba01483045022100e6217183d6869b431befccd5f4b12372028e7975640cebaeefd5f5172b871ad10220152db2015f3a8c16129f34e2488a4cf19a85f26956e3818f2cf76fdc9c43fd35014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000005805030000000000fd4401473044022011d6116b37d985ed52d59aa4fee1c67a44668f55d2db37fcecc3cf89245994a002202ecb47c384e42351995cfac7ee0fa8f55053dbaa11784a1890be84c164a5cdfd01483045022100922746c881c2becbadee3859902d93c9f623d1ccf3cdc0231d31e3ee806a1db90220715d1689faa159f4abe4959063e4dd8f108b4dae79167367843dc31e0fd46e97014730440220280556147f23f8cad1907869154a98b025baae29367cc80c6d23a3a0d3b6443e02207a62c31f1331459885ee236245d3e122013b77b304ed512914b05acd1886ce79014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d000000004bff020000000000fd45014730440220053f5cb6b633930fc7ccd1abd012292cee5b64d6d5c25220f9d9f22ab16d1df40220430e464f5823ee503616dfbfca55fdd01949cca336c8586f4e1de72ec3f3063201483045022100e16f4708245ca99bb01ab257f495d6a33b2db4ee9ee5089a6a2074ea9070d8f602201d3302d14c85f11b2f42af10e2ac31739f085036f26aa1723c3cfd2d4b35b2b501483045022100a0be245e53ce42f783481e3ff658c13ac850eda7ad21b8206bb48fa20fa2bc5d022072963db0ace1449652a083be585dc75574490248d1069c0a48f7f7a6902fddc2014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000001703030000000000fd4401473044022029960cfa720d3818d4d2d7a55fb1a68323e34678a2a8fa3e68505cd78184cf9d0220723861ca8cee7eaed1f503a9668d9866ccae44f15a3e9da77e4dd23679715e4201483045022100f3054837f1aa88101e983b28466b679fc43fac26c48d0359c4b881ed3cf8e73b02204f4579fffdb2a96fc82b0ede6bb5eab53a86b0bc04e1ea0fc1bae9953ff5a7f90147304402207e3132303406ca2924ad934d49e4027f52083638f08d73bed7138b6d267948ea022018720dc7f47cb13d3d37555c0abeca90cb00060ce1308a3de317d63da5d1f4f1014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000002f3020000000000fd4301473044022012cdbabc4d98705db72c8a6448d8b5e5483b404ce0ff26fad16b3751ccd667be022044bda8f743f51515281b41e7b7a0347e8d52e9aff07ad0c4c84486034b2257a201473044022021e2029bd87c699931a5eb4f997e56f1efe1dcc26a7fb8c8147a762bbea389ac02202ff5feed06720f5bba0c12107dca3d83c349a35c43256429b8f12eacc6b5df16014730440220269980cf3256b87c9ff83b29e3005b6af9c85c5a8fb7a501055b486bb51fe3e0022073196474be83c9cc24a843777835b97c4eca0ddf7956547f6cdc48a1cb42ddb3014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000030f9020000000000fd450147304402204442fa3cbc6d9ca9a217069f984e8fa1bda35a825d6bf39804c92faed97f2b8d02200976a8fa7653918fa23dc3adf15408d09a8069b033f4addb723a028f9928fbda01483045022100a36c038f7e49fea33c9f2a26a4d8e510095d42912ba1cabdd7da19ceccd2466802203b78e02c86e2fec18eea2ae2b94f1e6736dfa7a3453be9ee571c90832978509901483045022100af4a52bf94e8618d387c8f54feccdf0ef49b6b5503102cd405ab28c48c6597ea022031053ae17323c0fb24dc2cbd3107ca374279cac0b54c4a6633747effec83fc9c014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000006508030000000000fd440147304402206391486dc686a643c26e9b43038b2cb1b465ee6ba81ba9203d0d82f9550bd26602202ca9ebd53b20a6238c3d8abd4236b10d9ca304f5e5808db4d5004ab9ede10ad101483045022100e419233679a71a3380b662425657eca9ad26cb425a8aaaceb10de1847b3957ae02206780b4b428765f9bcee90443aaa497ade22fb813951205fd53c999f7ae27c168014730440220656dd7808be7db3a7e448608ccd3b8696cdefb687de8a4e37a58a2a0db8c714b022044683a0d0299b6eaed1ef4162d85f563aced9306d3e4a84961a301604234649d014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000cb13030000000000fd440147304402200ec0afc3a6b07063c61400fdd53e5419bb755bfcc99b1d6d2cf275b3f6848c75022036fa64742979454ce0c6b2e16963dca1d4509360cd35cb85fe533982a2ad9e690147304402206ca03acffd0198c7ea1d78e713eb45812dd0a296929bd679137dfe56f3f0601702201b9d6b25d85e86bc747b8c9d19a1a2329b02ca9de22a914419cec25bcd68e6fe01483045022100d22e473e19fda86e31314fedde03e1710f5de93efa284dab5f86817c99c9417602200bc43a59bee8a46bbc813ce52cdc76066903820af43d4caf173000543f672c6d014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d000000005efd020000000000fd440147304402205b7ef22035cfb0b11b62354d91f97910937de864369708e3e35376d4f620a1780220496aa95cdab061367e571568269afdc2d0a8fbb83b1bfd08c062d057041fada001483045022100db48444eda15deaab63bc6f3f5f31546d3b44a5a9412323445eb3e0853b440c80220201d7c95c47b5beed4a1139c27a79dbcd30f288ac106a208f43c61a0989f3e0801473044022040693ca2c95a33d5e8e7218b99a6df8507e9b8bf72014d19cae77d489b57b76102201883ef3c9df0b017e8fcf5b0af1bfbd61556d5bf347d77544e3bd263641fcd1c014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000046fb020000000000fd4301473044022005b50050f39f996b5f91e8e2c297e66521d5f72f2f4bec9993dbc44908f662be022001734f6df9a192f00e131fd8627b37b2afdbac8afafc38513b02c52ff305efad014730440220749ef2b72f235127bcc7c949f171ccfcc1ee87a9979543df9b568b323d9707260220440ae76846f8691bc471aa479e876a5fe01ce0e1f8311045cd8de1e7e58e4f890147304402201f5d4ea7f8fe9f08dac2020f4a2242645b27541b3cc591235fe927bfeed375a8022077627f400a799de27063ca0f2ea2d3ba5b8398bbac368a0501066097ad649e3a014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000009a09030000000000fd4501483045022100b83b84be0a0e613dd5e9dd7c6bec573a81bf95f83b546a4a717e3b708cc18bc802204bf97f877e03608103e30aeb9aab39c8f8d6e22cd9e89e66e7be74277bd7b7e201483045022100a9fe153e507bdebaf820f73e016ca8c7c61e3a07cfe7c79d74d674219c3aeb94022030abb047356650b8bb79d9eee45a9030c5cc55466568285e6d6f97cd6be577830147304402203da91297cb8e456b0089bbae43ad02d636f3f3777017c5b0224da4cf31ac5e5c022002a0ab0167395ee04f8e0f37fa261a80bff532c118a6f9fef229c5a9315115bb014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000cd0e030000000000fd4401473044022002012e7841bfd2dca62a5667f9bda8cc9b9e4ef86f8d0d6cca322b5bdb06a9b702206d5428e45ed0e18cb980b385cebc86eb6dcac59ee19f84afdc0c95ef0e782bfd01473044022073c34e5025fda812d8990f1f8cb16fbd4665554e8c467527b2c5c21132fbdf0b02206c22e854f2b704932e8134c46c40c738fc65939b2a516cceeafadd0c80f85efe01483045022100d808f0812a4a124c074166d87084bb3a38a6c632846a8ab4be7c69bda49b880702201a3625f5641c6a3a414196dc3b356f59b9bb8a44cd7623d601f28cb03691cd39014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000007fb020000000000fd4401483045022100e5357e2b20252b028d10d746c386959ba296630f08d94906a36251bf331073b102202c55e9e3a482e27326731821d25fa4c09103ec60c4cdced3f6774e6f1bc929970147304402202e58674ad455a4172f87439beaee82f59842d0c4565a88a358ebe8db35e2204702203cbffea9df59094f823f598cdb252927b1af451f522c8ca24d52274baa2c5f440147304402201a078f0959625258d4ef1bf7918b852bcf1629f8e79e2a95c1e6ffca017b7417022071dfe182e18f1debf0163e85ece438f1f3326e2eae39eab8d9c7a6cd8f179bd6014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000043fc020000000000fd450147304402201d697bdcd56006044872b398bac35b2c736f6bc22080ba7c81f5038de6a87a3702204c832224547a5bd89dbc5639e763dba74e3b35e77234078b425b7157b67f401e01483045022100bd54f0d2fdb584b15215e1eb8af08a2094f9ebabe0db8b01e107d0d6ca7c55f402204b1c9e9d368361903fe3cc99e48d045672818ae5ee15b3fc46e1c84049ed1c7a01483045022100e62ff90682934ec550ea89646de3a8d8bad4919bfd7d04a343aa490ca380d49d022046b3c4d8354661d6061798201cdec35744471b61bc55d83fa403d1aa6aa3b2b0014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d000000000cf6020000000000fd450147304402202d47018ec27c8d18a170cf22fa9f16df5da26c9ec85b5e7ab1220d7619d3bfb80220391bce1206a19b54496101317aa853f59fe8685f4ef1080525ec13149bfbe0e801483045022100ebab59d9714232e70788b14713364d8fa9c6284e0c2f173a3376521fffcdc80e0220624b5b801a7127e41c4378582026262e917a35c69ddb6fdf0de7ecaa26017904014830450221008905e07026703b5c1f6793fa9d749981369235d540fe0127be7b5d8cd18e401f022017b7e658adf3ad47487dc49c6aa8e88cc4d3b97f87ed0771299ef4026a8d8995014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453aea4a2d10a00000000c506030000000000fd4401483045022100c73924d67aaa9977d5b85fbad560b5315d36a657a402913be2aa90a1d12300e2022048b79577559462b4fd8c348a0b4d98caa20cff2c8a0363eda46037fd11782432014730440220345499c9d88b6989f158f7f980fa6f78f0a4b57d70f159739bf631b788fdbd3702207340e0fb636061cd9b7de0723d196b5f406d24120cb84f1236e3873f6e2fd6540147304402203332474e7a96938334a32052a802abb131d7a5000fb8fe1b903ca2474217d514022022533f3d58829d55689671efa27901878cfb75b20f5c696bb00ef4fcabde125f014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d000000002afd020000000000fd4601483045022100e7e10b3fa44e3bac1a8a5baa89ee3f34f437a37572a111d75ebc323007220956022007332c4fa0a81b99711a87342f7e13e720d09122f6f8d91ba093346d17cacbbf01483045022100d8f075435a1f1e6b3352beb482e899b95ee611551a499539c0004d703588a4cc02201b339915bf5cc5b1f4ca95d507576e58dfe20b2a2a3f9e97adc37c8f1f2921b301483045022100a25df71a3f33e602652db2a3ea88a65522edaf1e05c0900c87ef7149dafa9ed80220300d23d4abf09c979ad36916da78de09656f4c38a4fdac72454a888babc3f22b014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000b90f030000000000fd4501483045022100b6240b6c0f35b38bfc074939789eb53550f6c570487245666cdb825c13b95fe002200789f35de73db6342d1a3fd381ae55f5e801e1d170e7c9672c8179ddb7c9738101483045022100fb1a47917fef805908d2e02ff317a685a9550e5edc0aa8ef8568282575d4f6c802204a6b7a54338332ccff52ba21310cb0dca6a6b97370f1a621566c9214e03b49d20147304402203ef5647f608b1e921ed139dc54bfaf5e5ac3d959b88f3dc7a2ade0729f62818002205df3b44fab36a105bcecbe1f6b2794f692e0fe65eaa6d78126279c52db2a438e014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000004b10030000000000fd450147304402204cdd0d63816bd37ceaf959d323788b35a629d6b167cb2337ac81c0adae1366450220271435beb70cd8a18ddbcf98356de296ec16847a7a3e1a7c36d400f332374af601483045022100842dbb08884f9834eae867feedfa0ed158175348ee671aca1b470a9c5a723ee202201b9c8ffb52dc70fde054f18ab5a0419b603880bba4c9dec47d46bafb25c061dc01483045022100848c18295767444c5e0670930a0e0436fad251964bd4884ff5671db1a3f19d76022016edbdb3e65f99cdede5e957a941f3f35889342818f6805e0126e715a335aefe014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000001402030000000000fd430147304402202b7fe153e0a3f19123f677cfde86578aa546f8a46550806758b053d0b45b89710220792803175b29dab2c6e8c751436b30213a3b409c8d7cb0299f29a69522b120880147304402204e67807d8a30c8358cec44173c7a0727f542b4dc131f9701f2555a27cc17b628022044487b404d9edc2e2e8f553ac874c5dc549d9b261694752759d101ec00cc44c10147304402206d537d0aa88752db936ee48e986afd68338411ff68797ee2f80ce537bbf41d9002201d276c24365b68d18ce4020792c5d9558c7134495af96bcc55721d795c7662c2014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453aee854ed0a00000000f1fe020000000000fd4501483045022100a53176fb86d2190592abe80725917bfd5ab910b942d6f9648510e91730f3986b02205db19b272d2a2be3e315f2c9526a02c23f043c7b643128284faf734ce1d8930401483045022100be116b856b1f0ecac3c621c21a09d484a4bb86468a93e37f7c6d684c74c9031202205bcb65f89495e4575a1e5babb08cbd2aa21b200bbb9af1bd789b2a5b68c804f50147304402202a0dffdd955e6a5764e06113b5b712e789e956e7b6bcfaa225da8ef66e446c1b0220455f54d546976dd492b94f1693aa9d7e76dfffe3a7e861cec5f809fd5ac18caa014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000b305030000000000fd450148304502210098e4071de0540dd5d502e71a962803452695d3033ae1df83855e238197e2073e02202b825fb2190c784c050c375e1f520c0a2a85f9925fb43ffe58cdd25708e2877701483045022100892cb91af82982c870671e956805fa7aec721b82962311f4c51f959889ca8efc022051766e50a95d2ac480851b98f129889a4dd566c69b6ecda9654b3d4064aa40760147304402206ad1b9cd9af3c1e69ce32f42f1eb9ceab84e99b9f04cd14ab8842ad065a5589e022020b98e515e17d59e415d11b1be3e4fc34783d547200960ec96a4f67b6741aa58014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000018f8020000000000fd4501483045022100e500b89edaca4c2408069dd40b9645eec796f536ed10811016aceaaeba48b9b102201bc364c56b9647a7c6c53b235418a78c8d8faddf793bf3ffdbba41818b9a401601483045022100a9695d1776c81442dfc4931a960188be256f58c46ff546d1e872015c8ddf56a2022012443c230d3257b64bc8ee05d18269c211becf4b9ed3a5c7a3b63e2e216dabd8014730440220073a21f37e0d3cf9d706dde6e4fc2232395f4bf1982785ed04c61b1144f7c00f02202c7b18f4893413590bb4fb139896826bba6fc3e1205fa43fae30d8e7cce48edc014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000fe08030000000000fd4401483045022100ed3f9d7fedec8c9f8bbf1afb2b7b1edb3e4e8b9dfaf789f1effe19a32dea4728022046cba3fe18f0c1107d3fe2436d037aa8fee47e830cef788fa86541c84ac02a490147304402207326ffc63de54f4554f56a7da2072cb4bf89479bbdcf22d00169f4c3d7054a5c0220717c3c86a5470ad7f7a4900cc13e05a0a929ecc00e3ad58ac5850508ebcf7a6a01473044022052cfcc5fcd981d38c150af8897bbad4541a8aa2742d31369bf0c37c4670ec5eb02206031643bea000d5d33e180a75627cfa7bacd9eedc0926eaec773e529255c6262014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453aea4a2d10a00000000e001030000000000fd450147304402206c7e38bf498a7ff831513413e5bf283b93fa456993162fb698a88933e1451fa60220669d5f75d9817f3ec08607f4b3b0ffc3f4190b5f7cbfa3336f1b64dac28178f001483045022100d8a58946dc73974ead5766e023a11eb2f32d3b7d7e482ff92255137fa6aede21022040c02e902a208a25b10296ee0a5466c6a8ce211ae2a6e2b7a541d2ea69fa4fbb014830450221009bafaf344ef873797281daf907d4e1171d8220e47bac5888e5cc72f3e219ef85022029773c52b7785abb77d72c22fbda1f9cc2a8536ccca43ec756bc9655ce6a9a84014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000980a030000000000fd45014830450221009be858cd5d4a8bce15d433d040be529a38cf38d9358919a9c04a1ca26127e3e402203de44aed9159f37e4b04ca449621d82040eab2528e2cdb7539708574899175c80147304402207271dd94d087a7b2174f3c3ccea7b92e29c84c6471224269f30faea34f2b77bb022000c9e94e92ea9f311d7a6260a2283f879115eb84d319d0da3cdb724b2b66da890148304502210093397c395481625411641fec29b5f8c37b4163e6bf886843080082f14dc716c402202f1b776d07f69ac148ec36a257ed43a2a016cc3257b091f1180bdffe9fb8fd39014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453aee854ed0a0000000047f3020000000000fd4401483045022100e59a2bba52457cd3a884568aefb50a2500309e0262243553b31da735cd281d1402201c238950f19cff6cecb3e75a7308c6a0e9addb39001b36e12454575dd695ef07014730440220679cb79f57fdabea76ea42e3f145aea59f3cfd4401c4c5b1693b2ba03a2054b202205e3e2accd4d889e6fe4ce0a4ee8d6618dc79aa1f3b2d3bfb664d83d25d6562b501473044022043b80b0e55ea34ff22377a57c4633c1c5fdb57d53d04176c1673cc67e56d63a802207081bacf923edaa05c4848a11fbac160eaf3a33bb495c26361f85f3ff1fc482b014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000be08030000000000fd4601483045022100ebac21191cfac6123e0a66e7c6af7febc1a1ce2e63c4e6fa1e4f75d6d2f39dab02203d592a16f40f8c8c88817d0788457d66bdb35dde14b02b90c7c353d040d4af9101483045022100827b7e2ef669a5d1407b98562a4cd45f302f6e2489c1bef3b8bdc6a0592bd922022036fd1961511848f84c9e8c633044033501091c5e756e28a4787846156cb00f9201483045022100e330508c7b1072b3644bdaab4a6219a7cd7ddd364ec0729534385e2e6e7fdf5502200dfa2bc091014c8cc134728c60c40f21f737203e5c5c04740fbea54bba8eed04014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000f5f2020000000000fd45014830450221009db0475dc62ee80b8b49bac4d0138de52f985642f5ac40b75f46b643e4115767022042a464c53ebf57bfcefa05634ceb14e7669b86e94bea517c68e2264d676c70f80147304402205e563709bdcb24975892a67eddf3958a31d3a58471c6c0e0cb6891be80b9eeb802203c69bdf9042af7429f1555cba2180108834b3d3b139514274fe5c30aeb9f054901483045022100f792db494bef64ca96ec49891434bd33f511db09d214a3ac323343d758e2d3c702203a86fd817a81cb84610fb948d6b3ec7f4d4fed24da15ae9ee245606c4f5c42ab014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000bef8020000000000fd4501483045022100ca7a5b358614ba7615381667ed1d6ee7b2332d520caa6c5c6c1b4aab12fc4bd9022062990a8aef2fa44dc073cafaa2f3e95c3534ee075ba998beb716756f985b8f4601483045022100eb982763c3fdacf7bb59642df124f090cc5e55287b28c206a47c8a3ec8f08add0220668510362e0da663f117235f3aacdfa7fce13abfdd2c54425cf63d1b32c0b56d014730440220447bb198dc7466bfcf815e6b91e2431b970f6eba34a02260c224e503622e126902207c8fd1e1bdd32def46f7442df011f58a561b04477b372da26888c2a38d2bbb53014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000580a030000000000fd45014730440220702dd862dda92c7b3b214909a1f9dab7653a2f9103b7a62d6646d02c651b34e7022022e3c90cbf41c1fa2a5aa89ee139eee2e656a640947e8431c63c54e1e944763501483045022100f0781151a884d97b3de74df629265914f8d0253581e789a2eb511ef76568a4d602200f33782718c74ed75c25d66426f2037690d0ef3734fd06017bbd65d992b68bbe014830450221009d56003be4df82e009e4584088807d5f4a4322151865681dd04645c63b7a5a010220584ade2f5b18756f6c3cec7dd391cd174fa9103c747c8ea0d0fdf6877a4fc882014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000006407030000000000fd440147304402205d00ab5aa7656681bcde46fb484802c2a304249dddee6555e680067577805f2b02207541b235dbef5e123e7b392c63497ea074c26f08d004e766a7711dca4e2696ec01483045022100fed3c2fa5de22702bfb31075897e03b433fa593ae0fb80794103566c490a595102203f5b01c8e7296be4e2f1a836b9be4d073bd2378816ed09baf416188d9b25c3b00147304402202cc6e2988cf32e02b25b2a2d853a507857ff6eac50427c4def421f20aa36e9cc02201313060f0fedb86d1dc00b41b437705fae3e5e3df23b254a2343afde89e17ee9014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000074f3020000000000fd44014730440220681a9e9bcbffa35a8328fbbdb173d803042ab1a858c4ca9ed0e4f5a67d453c8e02205820f9fcbb4414d41c28e3509806443a869168cd1e17b428549ec2495161f5180147304402201339021529c4f6eb6dd22b56752ad5b2df7e1e8d978439c9578f0e907974711002202c63c6b1386bea4536364610c38ac0994ae863f9f35bef25850d6173901f794701483045022100bb021e7846352c38f3fd4fd21179b448a8d34295de73fa41c57a5f972e91c355022008f06f8bd66571e4027556cfa9124b4e1e518a9e82470261db3f0a3972efbcb6014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000e1f8020000000000fd4601483045022100f30681d06bbe18241bfeeb7cdd484bfb44efcd579f2c2e2ae53cdb68fa5032e202200d96812f571f9d8e8fa0756e351c7a779c46cf4ac62a6825f14a5020b771988c01483045022100996344d3a16c60b94789cd5ae4d3cfd8f0b660520c8e7602e0f8a7aae705b127022008d6d5577a2b90e2462bbccb88c79cfa2936d001e1b14ea530261235460c0778014830450221009a64402bdfdaaa64d429576b0c77601e8da643dab7437e8cfd27db5a56c05d2002202d263058b96116381e1879ad483c664341174f341537665c1ba7b8a33e378e75014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000086f9020000000000fd46014830450221009b8535b0fbf8f854787cd30b5109010183dae5807fa34e66e15cd6066dcb6b2502200783da464daec7780b546c0b6a4c274afe5f4698987820d36d6f9d5798ba2b7b01483045022100ccf647bcc6a89c6cca668aa5d4cb8577b8b1ebde8caf476c4270d96c631f6b8b022072e9d434ae2130352841477494a39168fda21ba51af04f372416a12b2a3eeb3601483045022100b71cf0b31f05baf22586a01f0e1869e8a37c9fb50e1470c6d82f0e8c7e709bff022050bb9d7638620264be1f8d69a477be454dd753beaf0ad6dd92f3d996f62910ac014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000007e08030000000000fd44014730440220563b7ed04dfec4aa05efd0911b384ae4995b1ec21be2572013f924268db89c9902205b3c939ecf522cfcd9d4678bcbfe23a31a3fab94043725be1d1e0c2a1ac6faf001483045022100bcfa16f8de773f97dbf9dcab27ead17ac1b3bfaeb16733d1bc355380595730a7022000d0125f418f48606a41c8b6f3e7dbcc21fd45f8c64be25513d58f56a0cbb0bc01473044022038b52dabadc8e617c7efaea42019fb8732a1bec5fa7a696c4c050b36968b637f02205b0bb3befba6a9fad35b34b99280523ebc37c20ba2eb9996d91c3f25a8d2a933014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000001c0b030000000000fd4601483045022100df6c07633b6669c8a73e33a004924e1a1e488329a165bf73871a6153cd222b9b0220240131a2687dcb6ce091ddb241d9e533362b29e351a7e181180b09a6c395a3e301483045022100884e519da7405180a348e67a6f9065d6a28520168924cebdc291f00aa28901e402204ff72a4d9bdb0f4fe667eeb0ef658a0414fe978c71193649235251ec99e0ea1d01483045022100c54d7fc08cca52150fe97c943e8d174306f125a459f3e71b489e7d497cea63270220101d71cd023d9131e98a1630a1566ba445b8e006aed4171d09f859aedbfb010a014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000befa020000000000fd4401483045022100e1c1a88390bc698025e6e40d1005a028e02f48f4708a2d8adb6b388e8ff83c33022013afc0b581e7b70d7f515d32bb1c7da68ff84dd741dbfb35855213467fc04cd30147304402205775454f05bf5fdd98df0d27b91eeb68955477768b9f50015f41a79b6f55b67002206861d59d11023c98d3a8df4edbc30a6008f615624fb18bc7d09c76d91f3abace01473044022055e4148ace2edcef6fd14e2aa7524ba7cdc397eaa025d2decfe8dff9ef93cfd402203cbdf55e08018990bcea1255149f31661fd568f1542c3c34ad9865161382a845014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000005507030000000000fd4501483045022100db1d65c4c10c62a9a727e8702730347528a810c18734666efbb8a9fb372d553c02205e3c8dee1c43ada5aab36e5e91291129dc06bca5dbcb2f72b143e98bbf8b506a01483045022100c824496528cf45264250c975ad4926e216c51a757aafe4d374b43d20fc3f108802205f3555d6c1c819be780e0fdb0b73e90727a9ffd86620c2eae6e71dba4bbb696001473044022045e218224cb0e51b36a8fedba5309d4bd0e0f3b3c89eaca58c1100a658f5370702202aefbb0c45f6044af9e8f873909e122f317c0d70872374308b6a4506ca4918fe014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000ba10030000000000fd4501483045022100a5ad7fa4026ee61e4c1e390a9d7cad33e7a23c8e84eac552ed5bd226350f2cec0220053a68add02401a90cbe70dd3ca95e02f7f3fa9c7554c9b85eb2ef9dbd7570d3014730440220458d2a918740dd329e7d3cfdb2035251503a472138b9ab19f18361ba1c05c40e0220523a8a265bbab021a019d54934bbccf0d7070342acf3ddbfb4c4d85671b34fcb01483045022100f8a7da4ff094abe375185b727847cbcf4dfb9edc7aa2c7d067153c6e4f59a479022001e0b4d4b71c818e3790accac1fcc7ab94c7949c9942224ab8146f31fe5b1fd8014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000003d0b030000000000fd44014830450221009ff8642e68b10e870a62eef426786fd90385f27ad7aeb2ed86313ef5572cf69202206ae5e31a87ee7537329c5a791ad06666797542d0d53e5e803565c46e850fdbe10147304402206477af187868ba99a2fd16ef32c5718e0710e497cf3b63c8d0451fc91aa2973e0220756a79e9d3c7ab5478caaa194c620ef6c5cb051105cd8d5906d2234226bf17420147304402200b6bec9b2956c32bdc2d39dd77790ee8469253cbed7ae4b1006eea6786bff7ab02207fde3b16eb595c5cbe2c022907f157a64a5d8dde2ce2a354228f6bf447a7b874014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453aea4a2d10a00000000f301030000000000fd4601483045022100b927e3f030945624fb57a1c78083dd5ecbd16bee095f1427fee2dcd8fe3571b4022059fae4cbe0bea4848e4d1e398f4d2aa4b2a17614fdbad4f1448a920cf73e189001483045022100f7fff756ed604f5239b0312d195e67880242c4090d92df66c2ee925c88acad9e02201aa1785336c8bdb7c604ba39809d889fcf5ee8eb63c90f4a04fe2726c58418fa01483045022100bda45c1641278939fa116163fbefbe1977628506882f873768a3c478739727d802200498f9e44d1e820ebc8e5d77e961aaf889bb72935b9274085fed3fa15f77e2f2014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000078f7020000000000fd440147304402207d4a786eaf1b2a169916850e5452c4e220b790fb3f2ad669a75aa54aed1a469c02205bce95b79ea705713d6c78fed676d2f0a0af31e4716b3d91f4f3722ac571357a01483045022100e5aa71c4430cc8acbec03d7a666c90e675df226bfd9e64f36e72da3fa3615a1c022038b8e99f6a16de52780723ee3f2b72ecd193002222df75db1035629ecce2a03b014730440220097f37a7c2996aa2e49aa2f36dc1669912a4cf2e5dd092751ed9df53188e078c0220676faaa01133f821bb044cf2d6f50a459c25c4b19eaf0145b4430967db73b01d014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453aee854ed0a00000000dcfd020000000000fd4501483045022100e60da48ef5ba5b29ab98cbe2ef99ff0a2bc92cd85024e49e5ca3597f12bcf300022048e6b0090e5c8057477dd7eb3789ae0b8fbdf5362421eda08c76d859ad7b544b01483045022100b4cdbbd212bbda1f70d6793d9956039d7edaa8fd70bfea7fb6a04bed7319e3780220425f48e5b29e7452107e19fddaec28e5846e04a2df14b80fc143bfd71e6266df014730440220279c65bad108d0007d821385aaad55ecad775a436de2b4e32988815020764847022067a86c7c33ece430d743102f84a9c48b29b9de9da821b6666929b13fb34e96e0014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000000f8020000000000fd4501483045022100e0d21364935dc638b62cc87e9a198a47afaa348143c28c35e3c1d4424bdf4121022008bd790132b5f6192ea6187f5cb5a9ffc6435eff720357382739d1a961fd9d890147304402203aab999b99e7753f39e2ef8d450241b911f6ffc4d9e858ca6743b2a5b7ff236802206344c728587b60b56672c4ada3fa58778cf4905697d46d026e1019eba70d1e3d014830450221009525cca77d25075ea465237b5259c3227c2924507e74851db33a71d6434a90fa02207fad277b64c89ade6a42a682f049b462e8257be13ee27cd16145b52bf60847ec014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d000000004ef5020000000000fd430147304402205879477cf645049300fbcb532853fd3672c4f00ebe8866df4479feec600e4217022021e95feaf3015d9d03fe78b3a0b5b61003e4182709aa7db198a050d9ca6d54be0147304402202df5b7711a3ca99433ca9a6bc6894e95ee4f1c5c94811f771e22fc7eba8514ed02206a2763d0ccd7a641d2bbca36110a4d0972bf5ab2e4660306bf8af866117759670147304402202a22e0d36d9f55d479414abfdba71a933083f44704997d0eeafca51a3dd8d37802201a4ec8031ee9325834f31805fa8bd50e5f9fa165b965f2027500ef0ee0b8138d014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453aea4a2d10a000000004412030000000000fd43014730440220221ca9f2149986b521ded423d8bf044b33502c128d5820c7ef6ea240a5bac8cb0220567cfd17e603a28a961f2a2ee88443ae709f5fab0d3cea9aa6232f5ea2570e000147304402202e38267764d91a348d25b328c11ad05323228bb3769334527418cc83df6815b7022072d856c6d2d45b1947f99e9c8e695da78c97e956eec9d75e2ac2f7cb450ae4240147304402202baa2f128838ad113ebdd95bd16db144ccd1f29be98fe435f145e7ca954c44b40220279934a60ff066f77c05031d6624cd1c7de4e120835162a2d43021526ad84bd1014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000006c0a030000000000fd4601483045022100c858877b7ebab9df2f7b0681239c92e6c03e95d963e42a075fad8c452e045b3a02202e04bbef330e7fbec49a7ba9859a6cadfd61830ab858362a2a695ad4db84ec8c014830450221009139aef771bb21f6ccd0b357d5e62f0991f98e67039b4ef146ca74c7a95883a00220268ea8e98573e4199ddaa75d2bb08f6b694af8bd383614f59e8699eacd7850be014830450221009694018de0f453d6732941e22309064ef42127d412ad135808acd9031e058fbd02202b4d893c63a553fe2401c983d4ab5a2f1ae9d411c195470be7d895ea4284b86f014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000ed10030000000000fd450147304402204a295e4d135f4f6421bea46bdd97d452b23b262408d77fe38c1f090f5f88651f02206f79e3a47f198091c92cf5733f9ab0acb3347e21f1d66ebc53e01db3dbd6845701483045022100a606efb31d0eb4cc4112721878cc3bf2fd0fa2b2cd3337a98cd3304e0cd2e38c02204b6117547daae39c06d7477c8f5e9e0e0d767007326df7b027cf80ec36282af1014830450221009d3a3360ead284b47ccc8a13eb1ad8de55563dbc5ff0a98744fde8947ff5484202203c350ab88bd4650aaa762bb1379022abedfd9316e9771e3c516190d07fce0349014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000be09030000000000fd4501483045022100bc76c0450c83c1a704cebf734d36f64e1ecdc76fdc1cd6e5f7986caab2d1dea902206bd1907f48bde52c8761bea4b7cbb848b2331ea58e6fbe683ecf2d60990001400147304402203287582617de76c70e8f73fba20100471cd40b4d6cff4b883a9ed88922c96dde02206e36f90628e7822206d93fb668e759ed62d6b73d3ecde935187d239c84d296a401483045022100957d7302576e215c6e97eeab33854a139f88839377eaf10edd1f80d7567ed5e102204452ec2dd7f273d586d7ca83f80c554c73531ec689bd961b524c2d0f2b16049e014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000fa10030000000000fd4501483045022100abeb8758b4ccf148e91c24c43b46c34330210bfa56eda2afa91c64f496215b21022046c5ac2cdb04ff964369cc6137b8c6b1133422640769d9f7bcd66cc45bea71b501483045022100901da0b92045f0c0195447fd2ef83b9cd6944e75e685e38a6ebafb16a03087a0022031f2261fa0f6486d000daa590875596ddd40fe99e943ee9d6bb8bd9129b0f90801473044022021e942e7c2e562631492f4c7bdab659af69efec054e5cf8432b9cca6e2b35579022051ce1c6da198abca7414783ef73e9119d6a345a0f0f989c53d74fb506c5c8fc8014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000850a030000000000fd44014730440220132a4fcc7f1a8f6f3fe4cd9ccb32fe3433a4e450f8594424e2389368f6a7203b0220075d01f8b9ed12b416d1d04cb9e95ceccfeeb420fb49720b4a3f0d1404be2f390147304402203707b8551104cac7c862aab1a2f730208f8ecee7180ac474b409be4c6af73fe0022023e293d0368a43397a93928d61586bc41c6c7bb1793b2bd2639ba8520014783a01483045022100d4504304bfa64c675045ffedf26e9b85a3ab839df273d93e2b1b9ff12338c7c50220080f395e7663fb9539181eee186a6960d69319333cbeb4fd5d596226c7cafa34014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000066f7020000000000fd44014730440220048efe6d5dd87a48a1deba890723e0e568ba8fe0112d29537237e0a1ea1c38070220197fda66031d9df627b79538eb4de824b9b49d94fab8aed185674ea4beac7bb901473044022006bc3ef529905db1a6729c0c8755267f63b3de05a0e1df68f9a2a983596e780e0220017582ffba0935ae9c8739bd6be3d21f9aec531ebe36e12073a5ee985df0110a01483045022100ef338afebdcddc9f46ac98ae9d9f936e44241cc46584096980690174b223da3b022062e0cbe00bc6ee9588ddf92e3c9c74f55632743d3d43dba4e43747fb380a4727014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000003901030000000000fd4601483045022100b21b940e774245ff2cbd5e797973a36ae61bd59c5a24081e73894f5823150d4202207c90190110b9607b151db47b81e7008b3fbf18ab952f83cae3189e4324a21709014830450221008949ea570a61d78294fbe8c2453a211e152b0b2190078b3cb085ef58fa2d47de02206dcede7043213254f01ed0e4b73d1f5d4550ac5fdcb815972b788edd1dc626b901483045022100f8b59f01836c28cbde52114bc8bebf8ece08f45ffe1660266e0dcdc187687bed02200b59ef8ca9b9a4d8d9c937014ac9bf66b7638101c89f10549cb28ee2bd7ce63f014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000004313030000000000fd440147304402205cfc98a5c55837d45207a22a7e20b646d0805a4d35e4bd10b2bbf3fff6ec0f1502207df92aa9d79c5eca866ddc95c446c774947a824e0901361dd42073f277212b66014830450221008845063e4b5c6387f1333d76010493b23d79d47f19b227b659daf8c12369e87a02203b7002cdd2ebf3974be41a5c0dd6ed267cad19b2fdd0526260e52a738bba2de4014730440220575a271b955e464d335bb32cece0813fc730be1c98f3b41d70739e9457c8b6d602206dba0e5fb0f0b3465736cfed2bab04e8f7defbb9f11c35cf1601b95fdaaa8829014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000a8f6020000000000fd45014830450221009cb6793416713945a3b6b08e10139d5c58f3ad21ba52f45913bbeb33d8ce1f5d02202e550c9d430adfaa81b4c9f6f27c2de234dfdf3936c5ad8a3beead34a8a62fde01483045022100807dfe6e8df9e514b6850f94c04efae0e927466c88bae4985d1f5a8014a5504302205265e75bb3d7b2ecbed322b35e998d904a2e4f2a44d5906807ed06566dbf14320147304402204a629c423c8ddb65ebfd05dccc9510aa3e8119b02d73e5997d559b7f9ad6a87d022029190b7200278ad005bf2f1a7aed9c864f9733ac3ec5bd7102ab18de6f44cd17014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000a6f5020000000000fd450148304502210094ef0e131bead508301ecf03a7ffa18ec9263bc3666450d2bddcfa752107310002207b8cac555f7a132aa98e41d2feff833fed68752601d0f84031eb870307630a480147304402203dffac6f1e5b22325cf2ff59a98665a827852a36225bb7db58c013022ce037cf0220502c495cfae8edbd53ca9e8b6b9bb4efbd1278966fd9156297959696d445c06f01483045022100f9d9f9b2058abc9aeb02bcebf6f5b22faaa6356ca640550b3c20744cbdee77fb022051c28736be4150081d5aef3e2253a5ce9d3ab9c4578beb398561029be530ebf3014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000003307030000000000fd44014730440220521bdce46b83ae123bcc4f0a008d2bd5cf76e76e0f98f21e029cdb2d0a4f868d02201d3abecb1216d4b41e6c6b23ad87feb8f7ba7735508a4f33d701289f736f366d0147304402203d15fd7c4c578a8acc93a1ec867199efec7f3cd532adf75e9a689af0a2b9399d0220598e77fbdb195843a2699c3464bbb5ccc55e608ec06fb2723c449469766d212c01483045022100e82cc5d9dde9a9086518ec2c18fa867ebb46112e37d65d9f34d88ac741996c95022053e900ac59bb0a391677ea209611b858a89540e59d66056852f8bf23fe5670d6014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d000000007eff020000000000fd4401483045022100d71d8a50ea69c55f7fd08defa76bf1b4da053e3575544b0471c461bf5aef137902207fd9f81b4a551bb7afa8dd1b69a0f6b1f2c4e24aa93c992fa82f82471aa8f72701473044022047ab50ee3683939bfef7410135d6b8de00f9405ca5f2faf22979df74bd4ce974022077f23743ab8ae449862ffd48caf40cbac62fdad49e005b7212852d085e82ee020147304402202e98296f1568f3b1fae805d2d6bc6fccd59bf4c5d6f1565b644d142297d7c40902207abe8a1988115e0ab88180cf90821005e645d97ce360d372f2f329fe2a284f76014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000008604030000000000fd4601483045022100d0befa3dba35057e2ef9b8b6d873dbe983166816ceb84eb875b346ce720a6b33022018d3acee74afd13496e6f1c06e7802d7813ad42a890be8a83280dc06ea23941c01483045022100822d27a60f0e4a8c37acfaadbb0be6d49c0981613610fa63c1f162d24e79e4500220316448804078b2df0d126fb9ec97dc1584ca84567332aa3dc2acab6f573856b0014830450221008fd2b5a6421611baaa3deb3739720dfec37f5cf95f93aff572dd92dca8925fa202205d2b99181fc69d7a46c7c58367a3927b1f6fdcf136142cf85f250837fe643454014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000180c030000000000fd44014830450221009c3ccf4b91b6e425a70216bafbcd277682da8bdbdff336b6f58cb97dfc3204cb022058f650ea3ad9d26b2c66f17cacdd10bee5446caa1ee34145061c227a56620225014730440220092afde83e1995e9964b85224dfc4a3782df00a0f982eb4ad3b38d083428149b02207669684a16f7af5563fe061874c80d9e35e745abbaf7396c7f71267f50fe52010147304402202858c626b1245cdfceefa6440e0c0ca838c10d6114098fca6df76559577de29302203fac70696457e9bfec335fa3a892ec3a2161a34c5bdec4a375d63f76a8d51fbe014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000066f4020000000000fd440147304402202397ebef3e1c8008050009f306560d15c5395fa07fae571fb55910749c3fb321022044acc8eab9dc7e1a9b4ab2cb167d0f944398a0b5e2c4d6e007f6f64779ab011301483045022100f4da2295f9558216c77cd9a0c56e0afc84e3ff1e6ec6b286ea5d7ab5a9f0b4b9022047d7353598ee12ea23234fa4fcdc05d7f9930f276cf4ecee76d128fe148596700147304402205216b5502fa0f62c6d5c9844f7b29ada8cda0fdce7d4dbacf8466adffb0eb6680220735d293adb02fb781f1cc02f9d1ef5a64c9436a95b4fc111dc0d69525ebadb03014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000004e09030000000000fd4501483045022100972f0d3af3ad98263fb8f500d6dc9bc75a589148b712ac0c7f95c78feb5a516102207316e12601bfb099b54075e67563a09df9e023094411ad19cbb5850a3778f067014830450221008ef3b3fc80b147b0ec47663d8756ee4d59e6ebbfd53a6d8629d1f30e9d17b70c02206583b2dd5b4f25d219e05da7fc34203ef667e0d49530e6211827f9f3041d3092014730440220088d12eb6a4424bb67b1aa85b8854cec0a959a62ee26e825a64bdc69c5e1219602206912f9adc20c5fe9f46ec852a6f433f276d1480f6a495a7984cf676a925a4f02014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000d80b030000000000fd4401473044022061236f509bf2232223af7219d64a2064dc4c12de828d46a1313b8f97b8a1b73b022043e93a6c2884668dc499ef67e370a6d736318ad39708183d2a702945a53e7cb2014830450221008e6deec7ff876824ee0f5a61f874eb5c303edd2717f5ca866afac208d591cb1502202fef21def83459e46dcb60387fa6ecac65adaf2ebec8d1c4bad92d1b0a928dda014730440220298c9412d02c1c39acfcb9dffa66cb5745904dae9d5f619b29d909cb9d6538ea02201dd6ca43c5fbe2038b6c347ce4e6a35e6d3e6f9703647661f0aa941cfd6136bc014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000b70c030000000000fd4501483045022100ed44d291e5e7c67d7817a0c1efead142048af4b2925df521f5ee011a6bbb797c0220268bc28e0b7f3cefd25b765801d25bc6de760361d5efc4ff4cc37721f191770c0147304402203425355cf89de0872aac696e9a54e1eb47d71b67a878b4291e505f5358b4c8f102205b7bf0aecb2c022fb93d72512fe820b1f9c0f396a80a75dbc72517d41006e12001483045022100b73867e6de73cf880d7eaa7a70f74685284ea52f3fae71eca4e8905d88367248022033f60a882ec544e5607201602229ddc7508c39ec25de2ee9e18e0bffc8f1130f014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000dcfe020000000000fd4501483045022100e565de2989fb12d59dceb8717fa7efe1d430031701a178e93a860b6e7c593b5302207a2c8ee53cc8deceb79e959fdbe72f7fc30e97e51652ee6043687a9f68e24eee01473044022035da650da8f643511b343b3314aab45635f5c7a70d09a34eccf208ee8c0285a602206d3125eeb0ba309c14dbac2a67fc807f8e805d210e8b4d36966ca67e80e8c5a001483045022100d2336814da44438d4e6792dec2ed9017ffe295dff7877a326eda47e76bfa587302200e5ddfdf57537fb32b0ff333744c4a426488b8199923de93691e138e7a00928a014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000ca0e030000000000fd440148304502210085f57e21fb1cd388db4e5c62353dc7f520eab422f3d7ef8624552d1385199ce502206565aa1221fc512ae6236bafc08cb8157d774e1d499ebbbe712c10032f5aaf1601473044022047a029d05cfc8da77b76625abb93ee65fa4ffd23672a7d0348e45c145cba13050220740e4bb703957e56da185bfcaece5e4d3cc602271201dadb2d5afb5475c96283014730440220573c5fd3b203915a057765b361f08082e2d891e57bcd010ecaf6e8d307358b54022018848d5a770f33d667e792853f454359d1bf1c1c846dd00ee3cb3296602dd5b8014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d000000000bf8020000000000fd450147304402203b89df3d311981d4918681f0ee17a629ea632592342085cf1c1794f75626b7d00220141f2bb0d18b5f07d5549d279437c82319ba23b5e23d8b37ee217150331fe05f01483045022100a5b0d516a0457646836b850c195c8389b2747abbf747a557e96059190ad1e38302202ab7e8d5001290350544299dc3556e9abb9da2e8f91dd2ce3b00fa0c718cdec601483045022100f7f5b03dd0f3d6a7edf18847427ac60fb49cb626b074cae1ea95f233960a0729022000aff8e788a856b194effca3a08594ce28d97138143f0b205556886b4a098fec014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000008705030000000000fd4501483045022100c9728ad82c64ab5d548752adf590654a58eb4bfaba85f1f504b57708abc3eb5902204c36886103e1aa4da4c96bb52182710806b25b9b18310d4b9eb574027eddb3100147304402205017577d2e107371b7c8bd17bc15e128e4e1186cef93ed260d6f54947e94382602200ef247802da72844a33163e6d12136027538c6855ff5761aa5ffc65fda7c810a01483045022100b56e938da3ea2ae0248afa7f6be5e8f7ddb81cd3c82e16a41919864482c28ca102202eeb3e20e95448e46c340736d980fc1b75d860264edb814f01e0e430521f51d4014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000004203030000000000fd4501473044022032a1358398cad98c16a8829ffc75fc7b44f77b93d5627dc717b66a44b59dff7102207b0472f44654abdfe1a24eda879f28838bd5184dfba238fb1b3d4ed0adba15a7014830450221008cbaf2f1616afd756d773443a52e55acafdf5202c7cecc5d0775d681de0e903902201218f989b0300a0d75672676a20c3136ef671f5a4c52ea34213eed22b3ee382401483045022100bb7ccc2f7822a511aac2104ef57e34a04c37f3e09bcff1bc779df446a0840d020220789dece4f3172564a56b6001dfddfc1b79e41ab6d156a40f020bb5dde18877a6014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d0000000054fc020000000000fd4401473044022021c6612e0d9d3a57628d54fdfb7ee9756d41ad3247c8c460c499164b6ced3fb302206cb072bf1b753b8ff407b767160acf074f6f34286f4caf3ab5061fb4c980fd270147304402203b4f06ae4d5314e5dd95341c9668b16bc4a71efa1ea4bda2403d2be25e9baf8e02200f09352867d755d614bdb6af4cf22211c93c420fec4fa6fcdacae32b11d1036a01483045022100efd849b2c87782427ce6241c9cb87c60eb0202c12d1ce5f2306b25e857aa8f8d02202eac2b493b0be06093bd4c35d111fb5bdcf24d5795449ebdcbbf234237ecb837014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae23aaa80d00000000c2f3020000000000fd450147304402202649f1955b9a482cab0eef5bde264adf912f5c9351c5d9c10ebd74a7b41dda4602205675c9cfb36ad8ed29e7d431bb7b362e001e999b52d10939636147d19d8de00a01483045022100cbe00b8a033296b9b9e269388a63fb96c4a8f75085c941fa32b037a5991932cb0220020788969972594ccac489afad39bcad1534628f6a649ad5b34f14e5e9421d8401483045022100b7160b1edb5919751ecf6d18c98cceeac9f5941c1854af8560432b34b77dd74b02207105457d94cc4839df8af02f9abc34302eca1b061666e6516d859ec73d89a748014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000009209030000000000fd4401483045022100a54e526956343cfc84ce3e428c138d40381003386375d4ebf9d246101ff678e402201c80e61034511ae79e486380e3a652af58ad5b489aa15f29ec56fb84864e768f0147304402203bdeb20123223d56f13e68817d4a29c87e690540019813b2cdcb4fecbab7044b0220396a1d6971b69b4ef3e63e8727f093b3d7bface1d677a798b4a2d5ece218e8fb0147304402203ff11e576e45e7254fa5959c93956a97c09bb123e95da708001f2ede5f9ba8c602200f9f36ba15933a54a4758d97b7842776bd9706c6a8fab6a58649b9040824634f014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000670a030000000000fd4301473044022029bb920d11e2bf9201d18e7730f3bc5f6553e62bc8314336ae9c8a5859914c1502203bdacff928d4d666507dd2583b9442959c88726a817c67348817cd65e6c3606601473044022077a8ad215d7005f651f3b73a4f5a2e33e98dd2168268e04eb41af2ed6435ce2d02200af0d91cd2880f4158d175e28bce4ddc3fe50ad78b87f969c3662ae242930d980147304402205479fac1941e63c1de3cb25c4760b13f6b62ca59cf7942fb3170fd2d195678f9022040e827f224ea5551a4dad03daaf0ad63ea470b4fceffa8e4bd495e7560f32289014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000fc11030000000000fd440147304402205c09825c601853704b1b0231fbee7591c79b6cbaf30e2e955a0b6a72793b370502203fa13d433613f7e6e63419d5db0ade84cb18d699da64a2138fc086afb6066e8301483045022100eafd46546faf8c4e1152145d0a5c30ef070d5e455b6b3b685e1cb8f47cc2a0030220452568d3b52d7a6f7b1f30f321cb4481aaf8af3d7223d5e3de2d6612fa2c41bc01473044022012fc1168c457070445b883dfbbad6996a9dca5eb006b3755daeee5908918a6bc022063b589fae666c446199742cd78eb1843385660f2a962492476c6cacf3997c9eb014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000a60f030000000000fd4501483045022100872b40bd06e8bcf66cbc8ce478d9ccb62972670682146d19b06e63b919a86da0022071cf9163b60e61078f4a5be7a46cee4978585f7eb27387c0b27ae696c3d79f4701483045022100848eb32ab0284db06df29338a34ec5d63660d8ff8838501acc00694b203a346b02203f67e1f2a8d05894f14e965748ef9391675c263afc356519f3516df5adbc87ff0147304402201a20d9f8b3e236b0807d84a7d7e041d77ee26f002d2b77c695fecca316c01b5e022035edbd8bbd6917b892166fcf4b8202b93609e04440ef7b6d850c12409cb3c1e5014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d000000008409030000000000fd4401473044022009153c7b1bfdfe8ac504213c3ba3321ede43e2dc89261d803601ed6e87cace55022051969259b11cacb80d06ca68563ebdbf8a6e85fa88e9c14afc5797dc82f0fdca01483045022100951209e2d941dd5ba148ef2a0d4a0eaf09c9e0c22051719cb5f3a762517964ab02204acdcfddb8b8aa6a1f61b5126dfb607a472b22d5f731e1318f2405732fc54e750147304402200cd5be575d4b681975316726c211db5fbbc3037d29acdeb06bb7c72119fce5db0220514ea54faba32014d3422ca09c2ebcd332888370249af76809a9f5e4c380dfe6014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000e600030000000000fd45014830450221008d99ed1beda44a35e04ed4b6a20a9335c29d6fa974011c06f7a4467420b7ea39022041faf1da827bf32bc43e56a3de62512491209b1175c8779afe3e07731db7620001483045022100f38d3d3adec74d05204c0c9f0b79521abdc57f23d9599a0423d0227294a0ae3e02204ffe4c18ccf208ce95ade49bb78cfdd86aded1071e1fcede37e19252ee0b7882014730440220477a3fa0d716f8ca73d0f5cd55508231dc05d90d14ee670527f30c7f68406e4302201ee6504b744a53375afb2e84fab902ff8d299d6d897bed9db8dcbd85fd890bad014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae4e0b860d00000000ed13030000000000fd4301473044022075d9d2d1d73ff65f1c3cb5fc705aa3f117b866901a527607c81807408fc924180220062031fca37eed36da2f119ad7f5018f8fdd6ca01f42c4bfebbe8550c17e8d690147304402202897a5b6ecb4426de79bc5be348c4b359c7a9adfec0c152345538bfd5279a3e8022053992fd5f382089e1f41e0c47a1ecc11cdd604dfc46210e6053b7f690e7ec0bb01473044022031a31eeaac96cce93cd3a5fe3d75e7faf99f17a5bba04a6a8387057815663ced0220266867c47ad462ab2e5a794b5db1325e0dd75588aa45e10dfb9c219918eb7af3014c69532102bc2a9206d10e5d5173583cbafebc78998745abeca13ed33151c93afbd850ca8e2103c995ce342de266d561d6ab4b06c7a14adb0f0b30002997f076f71c8f8ac93c98210330d6c9371b561d2b961a5987d336c0186a9c5dacd6ed4551420b5977e46a29b453ae \ No newline at end of file From 47806df63d2eba938fd1c27ff55b69ed7651daf4 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 23:45:31 -0800 Subject: [PATCH 0469/1056] txscript: Add benchmark for CalcWitnessSigHash --- txscript/bench_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index b129b80386..037ce531f7 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -50,3 +50,23 @@ func BenchmarkCalcSigHash(b *testing.B) { } } } + +// BenchmarkCalcWitnessSigHash benchmarks how long it takes to calculate the +// witness signature hashes for all inputs of a transaction with many inputs. +func BenchmarkCalcWitnessSigHash(b *testing.B) { + sigHashes := NewTxSigHashes(&manyInputsBenchTx) + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for j := 0; j < len(manyInputsBenchTx.TxIn); j++ { + _, err := CalcWitnessSigHash( + prevOutScript, sigHashes, SigHashAll, + &manyInputsBenchTx, j, 5, + ) + if err != nil { + b.Fatalf("failed to calc signature hash: %v", err) + } + } + } +} From bcb9643d39d86d21ce7bf0ac11464663b22df931 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:02 -0500 Subject: [PATCH 0470/1056] txscript: Add benchmark for script parsing. --- txscript/bench_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 037ce531f7..51f9aeab4c 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -70,3 +70,43 @@ func BenchmarkCalcWitnessSigHash(b *testing.B) { } } } + +// genComplexScript returns a script comprised of half as many opcodes as the +// maximum allowed followed by as many max size data pushes fit without +// exceeding the max allowed script size. +func genComplexScript() ([]byte, error) { + var scriptLen int + builder := NewScriptBuilder() + for i := 0; i < MaxOpsPerScript/2; i++ { + builder.AddOp(OP_TRUE) + scriptLen++ + } + maxData := bytes.Repeat([]byte{0x02}, MaxScriptElementSize) + for i := 0; i < (MaxScriptSize-scriptLen)/(MaxScriptElementSize+3); i++ { + builder.AddData(maxData) + } + return builder.Script() +} + +// BenchmarkScriptParsing benchmarks how long it takes to parse a very large +// script. +func BenchmarkScriptParsing(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + pops, err := parseScript(script) + if err != nil { + b.Fatalf("failed to parse script: %v", err) + } + + for _, pop := range pops { + _ = pop.opcode + _ = pop.data + } + } +} From c997417978f04881cb0cce570fd9c2cb6d74ed27 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:03 -0500 Subject: [PATCH 0471/1056] txscript: Introduce zero-alloc script tokenizer. This implements an efficient and zero-allocation script tokenizer that is exported to both provide a new capability to tokenize scripts to external consumers of the API as well as to serve as a base for refactoring the existing highly inefficient internal code. It is important to note that this tokenizer is intended to be used in consensus critical code in the future, so it must exactly follow the existing semantics. The current script parsing mechanism used throughout the txscript module is to fully tokenize the scripts into an array of internal parsed opcodes which are then examined and passed around in order to implement virtually everything related to scripts. While that approach does simplify the analysis of certain scripts and thus provide some nice properties in that regard, it is both extremely inefficient in many cases, and makes it impossible for external consumers of the API to implement any form of custom script analysis without manually implementing a bunch of error prone tokenizing code or, alternatively, the script engine exposing internal structures. For example, as shown by profiling the total memory allocations of an initial sync, the existing script parsing code allocates a total of around 295.12GB, which equates to around 50% of all allocations performed. The zero-alloc tokenizer this introduces will allow that to be reduced to virtually zero. The following is a before and after comparison of tokenizing a large script with a high opcode count using the existing code versus the tokenizer this introduces for both speed and memory allocations: benchmark old ns/op new ns/op delta BenchmarkScriptParsing-8 63464 677 -98.93% benchmark old allocs new allocs delta BenchmarkScriptParsing-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkScriptParsing-8 311299 0 -100.00% The following is an overview of the changes: - Introduce new error code ErrUnsupportedScriptVersion - Implement zero-allocation script tokenizer - Add a full suite of tests to ensure the tokenizer works as intended and follows the required consensus semantics - Add an example of using the new tokenizer to count the number of opcodes in a script - Update README.md to include the new example - Update script parsing benchmark to use the new tokenizer --- txscript/README.md | 4 + txscript/bench_test.go | 15 ++- txscript/error.go | 6 + txscript/error_test.go | 2 + txscript/example_test.go | 32 +++++ txscript/tokenizer.go | 186 ++++++++++++++++++++++++++ txscript/tokenizer_test.go | 259 +++++++++++++++++++++++++++++++++++++ 7 files changed, 497 insertions(+), 7 deletions(-) create mode 100644 txscript/tokenizer.go create mode 100644 txscript/tokenizer_test.go diff --git a/txscript/README.md b/txscript/README.md index 004c586d61..f0abb51884 100644 --- a/txscript/README.md +++ b/txscript/README.md @@ -37,6 +37,10 @@ $ go get -u github.com/btcsuite/btcd/txscript * [Manually Signing a Transaction Output](https://pkg.go.dev/github.com/btcsuite/btcd/txscript#example-SignTxOutput) Demonstrates manually creating and signing a redeem transaction. +* [Counting Opcodes in Scripts](http://godoc.org/github.com/decred/dcrd/txscript#example-ScriptTokenizer) + Demonstrates creating a script tokenizer instance and using it to count the + number of opcodes a script contains. + ## GPG Verification Key All official release tags are signed by Conformal so users can ensure the code diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 51f9aeab4c..673d1cc31d 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -96,17 +96,18 @@ func BenchmarkScriptParsing(b *testing.B) { b.Fatalf("failed to create benchmark script: %v", err) } + const scriptVersion = 0 b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { - pops, err := parseScript(script) - if err != nil { - b.Fatalf("failed to parse script: %v", err) + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + _ = tokenizer.Opcode() + _ = tokenizer.Data() + _ = tokenizer.ByteIndex() } - - for _, pop := range pops { - _ = pop.opcode - _ = pop.data + if err := tokenizer.Err(); err != nil { + b.Fatalf("failed to parse script: %v", err) } } } diff --git a/txscript/error.go b/txscript/error.go index a61d02729f..f42b893ea4 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -1,4 +1,5 @@ // Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2019 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -47,6 +48,10 @@ const ( // the provided data exceeds MaxDataCarrierSize. ErrTooMuchNullData + // ErrUnsupportedScriptVersion is returned when an unsupported script + // version is passed to a function which deals with script analysis. + ErrUnsupportedScriptVersion + // ------------------------------------------ // Failures related to final execution state. // ------------------------------------------ @@ -352,6 +357,7 @@ var errorCodeStrings = map[ErrorCode]string{ ErrNotMultisigScript: "ErrNotMultisigScript", ErrTooManyRequiredSigs: "ErrTooManyRequiredSigs", ErrTooMuchNullData: "ErrTooMuchNullData", + ErrUnsupportedScriptVersion: "ErrUnsupportedScriptVersion", ErrEarlyReturn: "ErrEarlyReturn", ErrEmptyStack: "ErrEmptyStack", ErrEvalFalse: "ErrEvalFalse", diff --git a/txscript/error_test.go b/txscript/error_test.go index ebac85fdaa..abfa156577 100644 --- a/txscript/error_test.go +++ b/txscript/error_test.go @@ -1,4 +1,5 @@ // Copyright (c) 2017 The btcsuite developers +// Copyright (c) 2015-2019 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -22,6 +23,7 @@ func TestErrorCodeStringer(t *testing.T) { {ErrUnsupportedAddress, "ErrUnsupportedAddress"}, {ErrTooManyRequiredSigs, "ErrTooManyRequiredSigs"}, {ErrTooMuchNullData, "ErrTooMuchNullData"}, + {ErrUnsupportedScriptVersion, "ErrUnsupportedScriptVersion"}, {ErrNotMultisigScript, "ErrNotMultisigScript"}, {ErrEarlyReturn, "ErrEarlyReturn"}, {ErrEmptyStack, "ErrEmptyStack"}, diff --git a/txscript/example_test.go b/txscript/example_test.go index 7bf2b3f059..6e17341c4a 100644 --- a/txscript/example_test.go +++ b/txscript/example_test.go @@ -1,4 +1,5 @@ // Copyright (c) 2014-2016 The btcsuite developers +// Copyright (c) 2015-2019 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -180,3 +181,34 @@ func ExampleSignTxOutput() { // Output: // Transaction successfully signed } + +// This example demonstrates creating a script tokenizer instance and using it +// to count the number of opcodes a script contains. +func ExampleScriptTokenizer() { + // Create a script to use in the example. Ordinarily this would come from + // some other source. + hash160 := btcutil.Hash160([]byte("example")) + script, err := txscript.NewScriptBuilder().AddOp(txscript.OP_DUP). + AddOp(txscript.OP_HASH160).AddData(hash160). + AddOp(txscript.OP_EQUALVERIFY).AddOp(txscript.OP_CHECKSIG).Script() + if err != nil { + fmt.Printf("failed to build script: %v\n", err) + return + } + + // Create a tokenizer to iterate the script and count the number of opcodes. + const scriptVersion = 0 + var numOpcodes int + tokenizer := txscript.MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + numOpcodes++ + } + if tokenizer.Err() != nil { + fmt.Printf("script failed to parse: %v\n", err) + } else { + fmt.Printf("script contains %d opcode(s)\n", numOpcodes) + } + + // Output: + // script contains 5 opcode(s) +} diff --git a/txscript/tokenizer.go b/txscript/tokenizer.go new file mode 100644 index 0000000000..72e00f07e2 --- /dev/null +++ b/txscript/tokenizer.go @@ -0,0 +1,186 @@ +// Copyright (c) 2019 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txscript + +import ( + "encoding/binary" + "fmt" +) + +// opcodeArrayRef is used to break initialization cycles. +var opcodeArrayRef *[256]opcode + +func init() { + opcodeArrayRef = &opcodeArray +} + +// ScriptTokenizer provides a facility for easily and efficiently tokenizing +// transaction scripts without creating allocations. Each successive opcode is +// parsed with the Next function, which returns false when iteration is +// complete, either due to successfully tokenizing the entire script or +// encountering a parse error. In the case of failure, the Err function may be +// used to obtain the specific parse error. +// +// Upon successfully parsing an opcode, the opcode and data associated with it +// may be obtained via the Opcode and Data functions, respectively. +// +// The ByteIndex function may be used to obtain the tokenizer's current offset +// into the raw script. +type ScriptTokenizer struct { + script []byte + version uint16 + offset int32 + op *opcode + data []byte + err error +} + +// Done returns true when either all opcodes have been exhausted or a parse +// failure was encountered and therefore the state has an associated error. +func (t *ScriptTokenizer) Done() bool { + return t.err != nil || t.offset >= int32(len(t.script)) +} + +// Next attempts to parse the next opcode and returns whether or not it was +// successful. It will not be successful if invoked when already at the end of +// the script, a parse failure is encountered, or an associated error already +// exists due to a previous parse failure. +// +// In the case of a true return, the parsed opcode and data can be obtained with +// the associated functions and the offset into the script will either point to +// the next opcode or the end of the script if the final opcode was parsed. +// +// In the case of a false return, the parsed opcode and data will be the last +// successfully parsed values (if any) and the offset into the script will +// either point to the failing opcode or the end of the script if the function +// was invoked when already at the end of the script. +// +// Invoking this function when already at the end of the script is not +// considered an error and will simply return false. +func (t *ScriptTokenizer) Next() bool { + if t.Done() { + return false + } + + op := &opcodeArrayRef[t.script[t.offset]] + switch { + // No additional data. Note that some of the opcodes, notably OP_1NEGATE, + // OP_0, and OP_[1-16] represent the data themselves. + case op.length == 1: + t.offset++ + t.op = op + t.data = nil + return true + + // Data pushes of specific lengths -- OP_DATA_[1-75]. + case op.length > 1: + script := t.script[t.offset:] + if len(script) < op.length { + str := fmt.Sprintf("opcode %s requires %d bytes, but script only "+ + "has %d remaining", op.name, op.length, len(script)) + t.err = scriptError(ErrMalformedPush, str) + return false + } + + // Move the offset forward and set the opcode and data accordingly. + t.offset += int32(op.length) + t.op = op + t.data = script[1:op.length] + return true + + // Data pushes with parsed lengths -- OP_PUSHDATA{1,2,4}. + case op.length < 0: + script := t.script[t.offset+1:] + if len(script) < -op.length { + str := fmt.Sprintf("opcode %s requires %d bytes, but script only "+ + "has %d remaining", op.name, -op.length, len(script)) + t.err = scriptError(ErrMalformedPush, str) + return false + } + + // Next -length bytes are little endian length of data. + var dataLen int32 + switch op.length { + case -1: + dataLen = int32(script[0]) + case -2: + dataLen = int32(binary.LittleEndian.Uint16(script[:2])) + case -4: + dataLen = int32(binary.LittleEndian.Uint32(script[:4])) + default: + // In practice it should be impossible to hit this + // check as each op code is predefined, and only uses + // the specified lengths. + str := fmt.Sprintf("invalid opcode length %d", op.length) + t.err = scriptError(ErrMalformedPush, str) + return false + } + + // Move to the beginning of the data. + script = script[-op.length:] + + // Disallow entries that do not fit script or were sign extended. + if dataLen > int32(len(script)) || dataLen < 0 { + str := fmt.Sprintf("opcode %s pushes %d bytes, but script only "+ + "has %d remaining", op.name, dataLen, len(script)) + t.err = scriptError(ErrMalformedPush, str) + return false + } + + // Move the offset forward and set the opcode and data accordingly. + t.offset += 1 + int32(-op.length) + dataLen + t.op = op + t.data = script[:dataLen] + return true + } + + // The only remaining case is an opcode with length zero which is + // impossible. + panic("unreachable") +} + +// Script returns the full script associated with the tokenizer. +func (t *ScriptTokenizer) Script() []byte { + return t.script +} + +// ByteIndex returns the current offset into the full script that will be parsed +// next and therefore also implies everything before it has already been parsed. +func (t *ScriptTokenizer) ByteIndex() int32 { + return t.offset +} + +// Opcode returns the current opcode associated with the tokenizer. +func (t *ScriptTokenizer) Opcode() byte { + return t.op.value +} + +// Data returns the data associated with the most recently successfully parsed +// opcode. +func (t *ScriptTokenizer) Data() []byte { + return t.data +} + +// Err returns any errors currently associated with the tokenizer. This will +// only be non-nil in the case a parsing error was encountered. +func (t *ScriptTokenizer) Err() error { + return t.err +} + +// MakeScriptTokenizer returns a new instance of a script tokenizer. Passing +// an unsupported script version will result in the returned tokenizer +// immediately having an err set accordingly. +// +// See the docs for ScriptTokenizer for more details. +func MakeScriptTokenizer(scriptVersion uint16, script []byte) ScriptTokenizer { + // Only version 0 scripts are currently supported. + var err error + if scriptVersion != 0 { + str := fmt.Sprintf("script version %d is not supported", scriptVersion) + err = scriptError(ErrUnsupportedScriptVersion, str) + + } + return ScriptTokenizer{version: scriptVersion, script: script, err: err} +} diff --git a/txscript/tokenizer_test.go b/txscript/tokenizer_test.go new file mode 100644 index 0000000000..fd008bfc54 --- /dev/null +++ b/txscript/tokenizer_test.go @@ -0,0 +1,259 @@ +// Copyright (c) 2019 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txscript + +import ( + "bytes" + "fmt" + "testing" +) + +// TestScriptTokenizer ensures a wide variety of behavior provided by the script +// tokenizer performs as expected. +func TestScriptTokenizer(t *testing.T) { + t.Skip() + + type expectedResult struct { + op byte // expected parsed opcode + data []byte // expected parsed data + index int32 // expected index into raw script after parsing token + } + + type tokenizerTest struct { + name string // test description + script []byte // the script to tokenize + expected []expectedResult // the expected info after parsing each token + finalIdx int32 // the expected final byte index + err error // expected error + } + + // Add both positive and negative tests for OP_DATA_1 through OP_DATA_75. + const numTestsHint = 100 // Make prealloc linter happy. + tests := make([]tokenizerTest, 0, numTestsHint) + for op := byte(OP_DATA_1); op < OP_DATA_75; op++ { + data := bytes.Repeat([]byte{0x01}, int(op)) + tests = append(tests, tokenizerTest{ + name: fmt.Sprintf("OP_DATA_%d", op), + script: append([]byte{op}, data...), + expected: []expectedResult{{op, data, 1 + int32(op)}}, + finalIdx: 1 + int32(op), + err: nil, + }) + + // Create test that provides one less byte than the data push requires. + tests = append(tests, tokenizerTest{ + name: fmt.Sprintf("short OP_DATA_%d", op), + script: append([]byte{op}, data[1:]...), + expected: nil, + finalIdx: 0, + err: scriptError(ErrMalformedPush, ""), + }) + } + + // Add both positive and negative tests for OP_PUSHDATA{1,2,4}. + data := mustParseShortForm("0x01{76}") + tests = append(tests, []tokenizerTest{{ + name: "OP_PUSHDATA1", + script: mustParseShortForm("OP_PUSHDATA1 0x4c 0x01{76}"), + expected: []expectedResult{{OP_PUSHDATA1, data, 2 + int32(len(data))}}, + finalIdx: 2 + int32(len(data)), + err: nil, + }, { + name: "OP_PUSHDATA1 no data length", + script: mustParseShortForm("OP_PUSHDATA1"), + expected: nil, + finalIdx: 0, + err: scriptError(ErrMalformedPush, ""), + }, { + name: "OP_PUSHDATA1 short data by 1 byte", + script: mustParseShortForm("OP_PUSHDATA1 0x4c 0x01{75}"), + expected: nil, + finalIdx: 0, + err: scriptError(ErrMalformedPush, ""), + }, { + name: "OP_PUSHDATA2", + script: mustParseShortForm("OP_PUSHDATA2 0x4c00 0x01{76}"), + expected: []expectedResult{{OP_PUSHDATA2, data, 3 + int32(len(data))}}, + finalIdx: 3 + int32(len(data)), + err: nil, + }, { + name: "OP_PUSHDATA2 no data length", + script: mustParseShortForm("OP_PUSHDATA2"), + expected: nil, + finalIdx: 0, + err: scriptError(ErrMalformedPush, ""), + }, { + name: "OP_PUSHDATA2 short data by 1 byte", + script: mustParseShortForm("OP_PUSHDATA2 0x4c00 0x01{75}"), + expected: nil, + finalIdx: 0, + err: scriptError(ErrMalformedPush, ""), + }, { + name: "OP_PUSHDATA4", + script: mustParseShortForm("OP_PUSHDATA4 0x4c000000 0x01{76}"), + expected: []expectedResult{{OP_PUSHDATA4, data, 5 + int32(len(data))}}, + finalIdx: 5 + int32(len(data)), + err: nil, + }, { + name: "OP_PUSHDATA4 no data length", + script: mustParseShortForm("OP_PUSHDATA4"), + expected: nil, + finalIdx: 0, + err: scriptError(ErrMalformedPush, ""), + }, { + name: "OP_PUSHDATA4 short data by 1 byte", + script: mustParseShortForm("OP_PUSHDATA4 0x4c000000 0x01{75}"), + expected: nil, + finalIdx: 0, + err: scriptError(ErrMalformedPush, ""), + }}...) + + // Add tests for OP_0, and OP_1 through OP_16 (small integers/true/false). + opcodes := []byte{OP_0} + for op := byte(OP_1); op < OP_16; op++ { + opcodes = append(opcodes, op) + } + for _, op := range opcodes { + tests = append(tests, tokenizerTest{ + name: fmt.Sprintf("OP_%d", op), + script: []byte{op}, + expected: []expectedResult{{op, nil, 1}}, + finalIdx: 1, + err: nil, + }) + } + + // Add various positive and negative tests for multi-opcode scripts. + tests = append(tests, []tokenizerTest{{ + name: "pay-to-pubkey-hash", + script: mustParseShortForm("DUP HASH160 DATA_20 0x01{20} EQUAL CHECKSIG"), + expected: []expectedResult{ + {OP_DUP, nil, 1}, {OP_HASH160, nil, 2}, + {OP_DATA_20, mustParseShortForm("0x01{20}"), 23}, + {OP_EQUAL, nil, 24}, {OP_CHECKSIG, nil, 25}, + }, + finalIdx: 25, + err: nil, + }, { + name: "almost pay-to-pubkey-hash (short data)", + script: mustParseShortForm("DUP HASH160 DATA_20 0x01{17} EQUAL CHECKSIG"), + expected: []expectedResult{ + {OP_DUP, nil, 1}, {OP_HASH160, nil, 2}, + }, + finalIdx: 2, + err: scriptError(ErrMalformedPush, ""), + }, { + name: "almost pay-to-pubkey-hash (overlapped data)", + script: mustParseShortForm("DUP HASH160 DATA_20 0x01{19} EQUAL CHECKSIG"), + expected: []expectedResult{ + {OP_DUP, nil, 1}, {OP_HASH160, nil, 2}, + {OP_DATA_20, mustParseShortForm("0x01{19} EQUAL"), 23}, + {OP_CHECKSIG, nil, 24}, + }, + finalIdx: 24, + err: nil, + }, { + name: "pay-to-script-hash", + script: mustParseShortForm("HASH160 DATA_20 0x01{20} EQUAL"), + expected: []expectedResult{ + {OP_HASH160, nil, 1}, + {OP_DATA_20, mustParseShortForm("0x01{20}"), 22}, + {OP_EQUAL, nil, 23}, + }, + finalIdx: 23, + err: nil, + }, { + name: "almost pay-to-script-hash (short data)", + script: mustParseShortForm("HASH160 DATA_20 0x01{18} EQUAL"), + expected: []expectedResult{ + {OP_HASH160, nil, 1}, + }, + finalIdx: 1, + err: scriptError(ErrMalformedPush, ""), + }, { + name: "almost pay-to-script-hash (overlapped data)", + script: mustParseShortForm("HASH160 DATA_20 0x01{19} EQUAL"), + expected: []expectedResult{ + {OP_HASH160, nil, 1}, + {OP_DATA_20, mustParseShortForm("0x01{19} EQUAL"), 22}, + }, + finalIdx: 22, + err: nil, + }}...) + + const scriptVersion = 0 + for _, test := range tests { + tokenizer := MakeScriptTokenizer(scriptVersion, test.script) + var opcodeNum int + for tokenizer.Next() { + // Ensure Next never returns true when there is an error set. + if err := tokenizer.Err(); err != nil { + t.Fatalf("%q: Next returned true when tokenizer has err: %v", + test.name, err) + } + + // Ensure the test data expects a token to be parsed. + op := tokenizer.Opcode() + data := tokenizer.Data() + if opcodeNum >= len(test.expected) { + t.Fatalf("%q: unexpected token '%d' (data: '%x')", test.name, + op, data) + } + expected := &test.expected[opcodeNum] + + // Ensure the opcode and data are the expected values. + if op != expected.op { + t.Fatalf("%q: unexpected opcode -- got %v, want %v", test.name, + op, expected.op) + } + if !bytes.Equal(data, expected.data) { + t.Fatalf("%q: unexpected data -- got %x, want %x", test.name, + data, expected.data) + } + + tokenizerIdx := tokenizer.ByteIndex() + if tokenizerIdx != expected.index { + t.Fatalf("%q: unexpected byte index -- got %d, want %d", + test.name, tokenizerIdx, expected.index) + } + + opcodeNum++ + } + + // Ensure the tokenizer claims it is done. This should be the case + // regardless of whether or not there was a parse error. + if !tokenizer.Done() { + t.Fatalf("%q: tokenizer claims it is not done", test.name) + } + + // Ensure the error is as expected. + if test.err == nil && tokenizer.Err() != nil { + t.Fatalf("%q: unexpected tokenizer err -- got %v, want nil", + test.name, tokenizer.Err()) + } else if test.err != nil { + if !IsErrorCode(tokenizer.Err(), test.err.(Error).ErrorCode) { + t.Fatalf("%q: unexpected tokenizer err -- got %v, want %v", + test.name, tokenizer.Err(), test.err.(Error).ErrorCode) + } + } + + // Ensure the final index is the expected value. + tokenizerIdx := tokenizer.ByteIndex() + if tokenizerIdx != test.finalIdx { + t.Fatalf("%q: unexpected final byte index -- got %d, want %d", + test.name, tokenizerIdx, test.finalIdx) + } + } +} + +// TestScriptTokenizerUnsupportedVersion ensures the tokenizer fails immediately +// with an unsupported script version. +func TestScriptTokenizerUnsupportedVersion(t *testing.T) { + const scriptVersion = 65535 + tokenizer := MakeScriptTokenizer(scriptVersion, nil) + if !IsErrorCode(tokenizer.Err(), ErrUnsupportedScriptVersion) { + t.Fatalf("script tokenizer did not error with unsupported version") + } +} From 099784267e52bc6ea11a0012aab56a78e083cb9c Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:04 -0500 Subject: [PATCH 0472/1056] txscript: Add benchmark for DisasmString. --- txscript/bench_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 673d1cc31d..3b1ed40d8e 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -111,3 +111,21 @@ func BenchmarkScriptParsing(b *testing.B) { } } } + +// BenchmarkDisasmString benchmarks how long it takes to disassemble a very +// large script. +func BenchmarkDisasmString(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := DisasmString(script) + if err != nil { + b.Fatalf("failed to disasm script: %v", err) + } + } +} From f980c9a28d943e926e2a4241b4e89de3e0a6fca6 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:05 -0500 Subject: [PATCH 0473/1056] txscript: Optimize script disasm. This converts the DisasmString function to make use of the new zero-allocation script tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. In order to facilitate this, the opcode disassembly functionality is split into a separate function called disasmOpcode that accepts the opcode struct and data independently as opposed to requiring a parsed opcode. The new function also accepts a pointer to a string builder so the disassembly can be more efficiently be built. While here, the comment is modified to explicitly call out the script version semantics. The following is a before and after comparison of a large script: benchmark old ns/op new ns/op delta BenchmarkDisasmString-8 102902 40124 -61.01% benchmark old allocs new allocs delta BenchmarkDisasmString-8 46 51 +10.87% benchmark old bytes new bytes delta BenchmarkDisasmString-8 389324 130552 -66.47% --- txscript/opcode.go | 65 +++++++++++++++++++++++++++++----------------- txscript/script.go | 30 ++++++++++++++------- 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index a878a9667b..7383f881e9 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -9,8 +9,10 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/binary" + "encoding/hex" "fmt" "hash" + "strings" "golang.org/x/crypto/ripemd160" @@ -815,45 +817,60 @@ func (pop *parsedOpcode) checkMinimalDataPush() error { return nil } -// print returns a human-readable string representation of the opcode for use -// in script disassembly. -func (pop *parsedOpcode) print(oneline bool) string { - // The reference implementation one-line disassembly replaces opcodes - // which represent values (e.g. OP_0 through OP_16 and OP_1NEGATE) - // with the raw value. However, when not doing a one-line dissassembly, - // we prefer to show the actual opcode names. Thus, only replace the - // opcodes in question when the oneline flag is set. - opcodeName := pop.opcode.name - if oneline { +// disasmOpcode writes a human-readable disassembly of the provided opcode and +// data into the provided buffer. The compact flag indicates the disassembly +// should print a more compact representation of data-carrying and small integer +// opcodes. For example, OP_0 through OP_16 are replaced with the numeric value +// and data pushes are printed as only the hex representation of the data as +// opposed to including the opcode that specifies the amount of data to push as +// well. +func disasmOpcode(buf *strings.Builder, op *opcode, data []byte, compact bool) { + // Replace opcode which represent values (e.g. OP_0 through OP_16 and + // OP_1NEGATE) with the raw value when performing a compact disassembly. + opcodeName := op.name + if compact { if replName, ok := opcodeOnelineRepls[opcodeName]; ok { opcodeName = replName } - // Nothing more to do for non-data push opcodes. - if pop.opcode.length == 1 { - return opcodeName + // Either write the human-readable opcode or the parsed data in hex for + // data-carrying opcodes. + switch { + case op.length == 1: + buf.WriteString(opcodeName) + + default: + buf.WriteString(hex.EncodeToString(data)) } - return fmt.Sprintf("%x", pop.data) + return } - // Nothing more to do for non-data push opcodes. - if pop.opcode.length == 1 { - return opcodeName - } + buf.WriteString(opcodeName) + + switch op.length { + // Only write the opcode name for non-data push opcodes. + case 1: + return // Add length for the OP_PUSHDATA# opcodes. - retString := opcodeName - switch pop.opcode.length { case -1: - retString += fmt.Sprintf(" 0x%02x", len(pop.data)) + buf.WriteString(fmt.Sprintf(" 0x%02x", len(data))) case -2: - retString += fmt.Sprintf(" 0x%04x", len(pop.data)) + buf.WriteString(fmt.Sprintf(" 0x%04x", len(data))) case -4: - retString += fmt.Sprintf(" 0x%08x", len(pop.data)) + buf.WriteString(fmt.Sprintf(" 0x%08x", len(data))) } - return fmt.Sprintf("%s 0x%02x", retString, pop.data) + buf.WriteString(fmt.Sprintf(" 0x%02x", data)) +} + +// print returns a human-readable string representation of the opcode for use +// in script disassembly. +func (pop *parsedOpcode) print(compact bool) string { + var buf strings.Builder + disasmOpcode(&buf, pop.opcode, pop.data, compact) + return buf.String() } // bytes returns any data associated with the opcode encoded as it would be in diff --git a/txscript/script.go b/txscript/script.go index 92a50e3761..b7c2ef96f6 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/binary" "fmt" + "strings" "time" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -275,20 +276,29 @@ func unparseScript(pops []parsedOpcode) ([]byte, error) { // script up to the point the failure occurred along with the string '[error]' // appended. In addition, the reason the script failed to parse is returned // if the caller wants more information about the failure. -func DisasmString(buf []byte) (string, error) { - var disbuf bytes.Buffer - opcodes, err := parseScript(buf) - for _, pop := range opcodes { - disbuf.WriteString(pop.print(true)) +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func DisasmString(script []byte) (string, error) { + const scriptVersion = 0 + + var disbuf strings.Builder + tokenizer := MakeScriptTokenizer(scriptVersion, script) + if tokenizer.Next() { + disasmOpcode(&disbuf, tokenizer.op, tokenizer.Data(), true) + } + for tokenizer.Next() { disbuf.WriteByte(' ') + disasmOpcode(&disbuf, tokenizer.op, tokenizer.Data(), true) } - if disbuf.Len() > 0 { - disbuf.Truncate(disbuf.Len() - 1) - } - if err != nil { + if tokenizer.Err() != nil { + if tokenizer.ByteIndex() != 0 { + disbuf.WriteByte(' ') + } disbuf.WriteString("[error]") } - return disbuf.String(), err + return disbuf.String(), tokenizer.Err() } // removeOpcode will remove any opcode matching ``opcode'' from the opcode From af757d3d0d21468c994401da82816837a9314f62 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 18 Apr 2019 20:11:36 -0700 Subject: [PATCH 0474/1056] txscript: Introduce raw script sighash calc func. This introduces a new function named calcSignatureHashRaw which accepts the raw script bytes to calculate the script hash versus requiring the parsed opcode only to unparse them later in order to make it more flexible for working with raw scripts. Since there are several places in the rest of the code that currently only have access to the parsed opcodes, this modifies the existing calcSignatureHash to first unparse the script before calling the new function. Backport of decred/dcrd:f306a72a16eaabfb7054a26f9d9f850b87b00279 --- txscript/opcode.go | 10 ++++++++-- txscript/reference_test.go | 7 ++++++- txscript/script.go | 41 ++++++++++++++++++++++++++++---------- txscript/sign.go | 5 ++++- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 7383f881e9..893bebdf8d 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -2198,7 +2198,10 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error { // to sign itself. subScript = removeOpcodeByData(subScript, fullSigBytes) - hash = calcSignatureHash(subScript, hashType, &vm.tx, vm.txIdx) + hash, err = calcSignatureHash(subScript, hashType, &vm.tx, vm.txIdx) + if err != nil { + return err + } } pubKey, err := btcec.ParsePubKey(pkBytes, btcec.S256()) @@ -2467,7 +2470,10 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { return err } } else { - hash = calcSignatureHash(script, hashType, &vm.tx, vm.txIdx) + hash, err = calcSignatureHash(script, hashType, &vm.tx, vm.txIdx) + if err != nil { + return err + } } var valid bool diff --git a/txscript/reference_test.go b/txscript/reference_test.go index 5015960b94..6ac9b68f51 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -863,8 +863,13 @@ func TestCalcSignatureHash(t *testing.T) { } hashType := SigHashType(testVecF64ToUint32(test[3].(float64))) - hash := calcSignatureHash(parsedScript, hashType, &tx, + hash, err := calcSignatureHash(parsedScript, hashType, &tx, int(test[2].(float64))) + if err != nil { + t.Errorf("TestCalcSignatureHash failed test #%d: "+ + "Failed to compute sighash: %v", i, err) + continue + } expectedHash, _ := chainhash.NewHashFromStr(test[4].(string)) if !bytes.Equal(hash, expectedHash[:]) { diff --git a/txscript/script.go b/txscript/script.go index b7c2ef96f6..52bb5b6b35 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -572,13 +572,12 @@ func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx if err != nil { return nil, fmt.Errorf("cannot parse output script: %v", err) } - return calcSignatureHash(parsedScript, hashType, tx, idx), nil + return calcSignatureHash(parsedScript, hashType, tx, idx) } -// calcSignatureHash will, given a script and hash type for the current script -// engine instance, calculate the signature hash to be used for signing and -// verification. -func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.MsgTx, idx int) []byte { +// calcSignatureHashRaw computes the signature hash for the specified input of +// the target transaction observing the desired signature hash type. +func calcSignatureHashRaw(sigScript []byte, hashType SigHashType, tx *wire.MsgTx, idx int) []byte { // The SigHashSingle signature type signs only the corresponding input // and output (the output with the same index number as the input). // @@ -606,17 +605,24 @@ func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.Msg } // Remove all instances of OP_CODESEPARATOR from the script. - script = removeOpcode(script, OP_CODESEPARATOR) + filteredScript := make([]byte, 0, len(sigScript)) + const scriptVersion = 0 + tokenizer := MakeScriptTokenizer(scriptVersion, sigScript) + var prevOffset int32 + for tokenizer.Next() { + if tokenizer.Opcode() != OP_CODESEPARATOR { + filteredScript = append(filteredScript, + sigScript[prevOffset:tokenizer.ByteIndex()]...) + } + prevOffset = tokenizer.ByteIndex() + } // Make a shallow copy of the transaction, zeroing out the script for // all inputs that are not currently being processed. txCopy := shallowCopyTx(tx) for i := range txCopy.TxIn { if i == idx { - // UnparseScript cannot fail here because removeOpcode - // above only returns a valid script. - sigScript, _ := unparseScript(script) - txCopy.TxIn[idx].SignatureScript = sigScript + txCopy.TxIn[idx].SignatureScript = filteredScript } else { txCopy.TxIn[i].SignatureScript = nil } @@ -670,6 +676,21 @@ func calcSignatureHash(script []parsedOpcode, hashType SigHashType, tx *wire.Msg return chainhash.DoubleHashB(wbuf.Bytes()) } +// calcSignatureHash computes the signature hash for the specified input of the +// target transaction observing the desired signature hash type. +// +// DEPRECATED: Use calcSignatureHashRaw instead +func calcSignatureHash(prevOutScript []parsedOpcode, hashType SigHashType, + tx *wire.MsgTx, idx int) ([]byte, error) { + + sigScript, err := unparseScript(prevOutScript) + if err != nil { + return nil, err + } + + return calcSignatureHashRaw(sigScript, hashType, tx, idx), nil +} + // asSmallInt returns the passed opcode, which must be true according to // isSmallInt(), as an integer. func asSmallInt(op *opcode) int { diff --git a/txscript/sign.go b/txscript/sign.go index 42af9686cb..b9f8b2dbb4 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -345,7 +345,10 @@ sigLoop: // however, assume no sigs etc are in the script since that // would make the transaction nonstandard and thus not // MultiSigTy, so we just need to hash the full thing. - hash := calcSignatureHash(pkPops, hashType, tx, idx) + hash, err := calcSignatureHash(pkPops, hashType, tx, idx) + if err != nil { + panic(fmt.Sprintf("cannot compute sighash: %v", err)) + } for _, addr := range addresses { // All multisig addresses should be pubkey addresses From c19535b1454325ac363070fe1cdbfe2fbd12bdb0 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:07 -0500 Subject: [PATCH 0475/1056] txscript: Optimize CalcSignatureHash. This modifies the CalcSignatureHash function to make use of the new signature hash calculation function that accepts raw scripts without needing to first parse them. Consequently, it also doubles as a slight optimization to the execution time and a significant reduction in the number of allocations. In order to convert the CalcScriptHash function and keep the same semantics, a new function named checkScriptParses is introduced which will quickly determine if a script can be fully parsed without failure and return the parse failure in the case it can't. The following is a before and after comparison of analyzing a large multiple input transaction: benchmark old ns/op new ns/op delta BenchmarkCalcSigHash-8 3627895 3619477 -0.23% benchmark old allocs new allocs delta BenchmarkCalcSigHash-8 1335 801 -40.00% benchmark old bytes new bytes delta BenchmarkCalcSigHash-8 1373812 1293354 -5.86% --- txscript/script.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 52bb5b6b35..112c24acb1 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -567,12 +567,17 @@ func shallowCopyTx(tx *wire.MsgTx) wire.MsgTx { // CalcSignatureHash will, given a script and hash type for the current script // engine instance, calculate the signature hash to be used for signing and // verification. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) { - parsedScript, err := parseScript(script) - if err != nil { - return nil, fmt.Errorf("cannot parse output script: %v", err) + const scriptVersion = 0 + if err := checkScriptParses(scriptVersion, script); err != nil { + return nil, err } - return calcSignatureHash(parsedScript, hashType, tx, idx) + + return calcSignatureHashRaw(script, hashType, tx, idx), nil } // calcSignatureHashRaw computes the signature hash for the specified input of @@ -850,6 +855,15 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int { return 0 } +// checkScriptParses returns an error if the provided script fails to parse. +func checkScriptParses(scriptVersion uint16, script []byte) error { + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + // Nothing to do. + } + return tokenizer.Err() +} + // IsUnspendable returns whether the passed public key script is unspendable, or // guaranteed to fail at execution. This allows inputs to be pruned instantly // when entering the UTXO set. From c6f4cafe57cac8fb527be53b6418fe96c655265e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 18 Apr 2019 21:12:34 -0700 Subject: [PATCH 0476/1056] txscript/reference_test: Convert sighash calc test This converts the tests for calculating signature hashes to use the exported function which handles the raw script versus the now deprecated variant requiring parsed opcodes. Backport of 06f769ef72e6042e7f2b5ff1c512ef1371d615e5 --- txscript/reference_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/txscript/reference_test.go b/txscript/reference_test.go index 6ac9b68f51..9d9c8f39ed 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -836,6 +836,7 @@ func TestCalcSignatureHash(t *testing.T) { err) } + const scriptVersion = 0 for i, test := range tests { if i == 0 { // Skip first line -- contains comments only. @@ -855,15 +856,14 @@ func TestCalcSignatureHash(t *testing.T) { } subScript, _ := hex.DecodeString(test[1].(string)) - parsedScript, err := parseScript(subScript) - if err != nil { + if err := checkScriptParses(scriptVersion, subScript); err != nil { t.Errorf("TestCalcSignatureHash failed test #%d: "+ "Failed to parse sub-script: %v", i, err) continue } hashType := SigHashType(testVecF64ToUint32(test[3].(float64))) - hash, err := calcSignatureHash(parsedScript, hashType, &tx, + hash, err := CalcSignatureHash(subScript, hashType, &tx, int(test[2].(float64))) if err != nil { t.Errorf("TestCalcSignatureHash failed test #%d: "+ From 583b74040dc92978e9c258b7ea64e3da01f361f2 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:09 -0500 Subject: [PATCH 0477/1056] txscript: Make isSmallInt accept raw opcode. This converts the isSmallInt function to accept an opcode as a byte instead of the internal opcode data struct in order to make it more flexible for raw script analysis. The comment is modified to explicitly call out the script version semantics. Finally, it updates all callers accordingly. --- txscript/script.go | 14 ++++++++------ txscript/standard.go | 10 +++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 112c24acb1..58b8e69f0f 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -1,4 +1,5 @@ // Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2019 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -45,11 +46,12 @@ const ( // isSmallInt returns whether or not the opcode is considered a small integer, // which is an OP_0, or OP_1 through OP_16. -func isSmallInt(op *opcode) bool { - if op.value == OP_0 || (op.value >= OP_1 && op.value <= OP_16) { - return true - } - return false +// +// NOTE: This function is only valid for version 0 opcodes. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func isSmallInt(op byte) bool { + return op == OP_0 || (op >= OP_1 && op <= OP_16) } // isScriptHash returns true if the script passed is a pay-to-script-hash @@ -136,7 +138,7 @@ func IsWitnessProgram(script []byte) bool { // bytes. func isWitnessProgram(pops []parsedOpcode) bool { return len(pops) == 2 && - isSmallInt(pops[0].opcode) && + isSmallInt(pops[0].opcode.value) && canonicalPush(pops[1]) && (len(pops[1].data) >= 2 && len(pops[1].data) <= 40) } diff --git a/txscript/standard.go b/txscript/standard.go index 2cad218e95..a447303d62 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -115,10 +115,10 @@ func isMultiSig(pops []parsedOpcode) bool { if l < 4 { return false } - if !isSmallInt(pops[0].opcode) { + if !isSmallInt(pops[0].opcode.value) { return false } - if !isSmallInt(pops[l-2].opcode) { + if !isSmallInt(pops[l-2].opcode.value) { return false } if pops[l-1].opcode.value != OP_CHECKMULTISIG { @@ -153,7 +153,7 @@ func isNullData(pops []parsedOpcode) bool { return l == 2 && pops[0].opcode.value == OP_RETURN && - (isSmallInt(pops[1].opcode) || pops[1].opcode.value <= + (isSmallInt(pops[1].opcode.value) || pops[1].opcode.value <= OP_PUSHDATA4) && len(pops[1].data) <= MaxDataCarrierSize } @@ -705,7 +705,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa return nil, nil } pushes.SecretSize = int64(locktime) - } else if op := pops[2].opcode; isSmallInt(op) { + } else if op := pops[2].opcode; isSmallInt(op.value) { pushes.SecretSize = int64(asSmallInt(op)) } else { return nil, nil @@ -716,7 +716,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa return nil, nil } pushes.LockTime = int64(locktime) - } else if op := pops[11].opcode; isSmallInt(op) { + } else if op := pops[11].opcode; isSmallInt(op.value) { pushes.LockTime = int64(asSmallInt(op)) } else { return nil, nil From dfb1a6797b724873f8d3f785b76f86b9c58a6200 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:11 -0500 Subject: [PATCH 0478/1056] txscript: Make asSmallInt accept raw opcode. This converts the asSmallInt function to accept an opcode as a byte instead of the internal opcode data struct in order to make it more flexible for raw script analysis. It also updates all callers accordingly. --- txscript/script.go | 10 +++++----- txscript/standard.go | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 58b8e69f0f..3dfd82e139 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -159,7 +159,7 @@ func ExtractWitnessProgramInfo(script []byte) (int, []byte, error) { "unable to extract version or witness program") } - witnessVersion := asSmallInt(pops[0].opcode) + witnessVersion := asSmallInt(pops[0].opcode.value) witnessProgram := pops[1].data return witnessVersion, witnessProgram, nil @@ -700,12 +700,12 @@ func calcSignatureHash(prevOutScript []parsedOpcode, hashType SigHashType, // asSmallInt returns the passed opcode, which must be true according to // isSmallInt(), as an integer. -func asSmallInt(op *opcode) int { - if op.value == OP_0 { +func asSmallInt(op byte) int { + if op == OP_0 { return 0 } - return int(op.value - (OP_1 - 1)) + return int(op - (OP_1 - 1)) } // getSigOpCount is the implementation function for counting the number of @@ -730,7 +730,7 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { if precise && i > 0 && pops[i-1].opcode.value >= OP_1 && pops[i-1].opcode.value <= OP_16 { - nSigs += asSmallInt(pops[i-1].opcode) + nSigs += asSmallInt(pops[i-1].opcode.value) } else { nSigs += MaxPubKeysPerMultiSig } diff --git a/txscript/standard.go b/txscript/standard.go index a447303d62..94b3cce57b 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -127,7 +127,7 @@ func isMultiSig(pops []parsedOpcode) bool { // Verify the number of pubkeys specified matches the actual number // of pubkeys provided. - if l-2-1 != asSmallInt(pops[l-2].opcode) { + if l-2-1 != asSmallInt(pops[l-2].opcode.value) { return false } @@ -238,7 +238,7 @@ func expectedInputs(pops []parsedOpcode, class ScriptClass) int { // the original bitcoind bug where OP_CHECKMULTISIG pops an // additional item from the stack, add an extra expected input // for the extra push that is required to compensate. - return asSmallInt(pops[0].opcode) + 1 + return asSmallInt(pops[0].opcode.value) + 1 case NullDataTy: fallthrough @@ -395,8 +395,8 @@ func CalcMultiSigStats(script []byte) (int, int, error) { return 0, 0, scriptError(ErrNotMultisigScript, str) } - numSigs := asSmallInt(pops[0].opcode) - numPubKeys := asSmallInt(pops[len(pops)-2].opcode) + numSigs := asSmallInt(pops[0].opcode.value) + numPubKeys := asSmallInt(pops[len(pops)-2].opcode.value) return numPubKeys, numSigs, nil } @@ -617,8 +617,8 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script // Therefore the number of required signatures is the 1st item // on the stack and the number of public keys is the 2nd to last // item on the stack. - requiredSigs = asSmallInt(pops[0].opcode) - numPubKeys := asSmallInt(pops[len(pops)-2].opcode) + requiredSigs = asSmallInt(pops[0].opcode.value) + numPubKeys := asSmallInt(pops[len(pops)-2].opcode.value) // Extract the public keys while skipping any that are invalid. addrs = make([]btcutil.Address, 0, numPubKeys) @@ -706,7 +706,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa } pushes.SecretSize = int64(locktime) } else if op := pops[2].opcode; isSmallInt(op.value) { - pushes.SecretSize = int64(asSmallInt(op)) + pushes.SecretSize = int64(asSmallInt(op.value)) } else { return nil, nil } @@ -717,7 +717,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa } pushes.LockTime = int64(locktime) } else if op := pops[11].opcode; isSmallInt(op.value) { - pushes.LockTime = int64(asSmallInt(op)) + pushes.LockTime = int64(asSmallInt(op.value)) } else { return nil, nil } From 05aa488a877faa2fabdac38e024f9f72aa3abe4a Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:38 -0500 Subject: [PATCH 0479/1056] txscript: Add benchmark for IsPayToPubKey --- txscript/bench_test.go | 15 +++++++++++++++ txscript/script.go | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 3b1ed40d8e..6415c595a5 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -129,3 +129,18 @@ func BenchmarkDisasmString(b *testing.B) { } } } + +// BenchmarkIsPubKeyScript benchmarks how long it takes to analyze a very large +// script to determine if it is a standard pay-to-pubkey script. +func BenchmarkIsPubKeyScript(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsPayToPubKey(script) + } +} diff --git a/txscript/script.go b/txscript/script.go index 3dfd82e139..c642069ced 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -63,6 +63,16 @@ func isScriptHash(pops []parsedOpcode) bool { pops[2].opcode.value == OP_EQUAL } +// IsPayToPubKey returns true if the script is in the standard pay-to-pubkey +// (P2PK) format, false otherwise. +func IsPayToPubKey(script []byte) bool { + pops, err := parseScript(script) + if err != nil { + return false + } + return isPubkey(pops) +} + // IsPayToScriptHash returns true if the script is in the standard // pay-to-script-hash (P2SH) format, false otherwise. func IsPayToScriptHash(script []byte) bool { From 99cb679b6f170003834de4ca326bfcf960bc1629 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 14:06:56 -0800 Subject: [PATCH 0480/1056] txscript: Optimize IsPayToPubKey This converts the IsPayToScriptHash function to analyze the raw script instead of using the far less efficient parseScript, thereby significantly optimizing the function. In order to accomplish this, it introduces four new functions: extractCompressedPubKey, extractUncompressedPubKey, extractPubKey, and isPubKeyScript. The extractPubKey function makes use of extractCompressedPubKey and extractUncompressedPubKey to combine their functionality as a convenience and isPubKeyScript is defined in terms of extractPubKey. The extractCompressedPubKey works with the raw script bytes to simultaneously determine if the script is a pay-to-compressed-pubkey script, and in the case it is, extract and return the raw compressed pubkey bytes. Similarly, the extractUncompressedPubKey works in the same way except it determines if the script is a pay-to-uncompressed-pubkey script and returns the raw uncompressed pubkey bytes in the case it is. The extract function approach was chosen because it is common for callers to want to only extract relevant details from a script if the script is of the specific type. Extracting those details requires performing the exact same checks to ensure the script is of the correct type, so it is more efficient to combine the two into one and define the type determination in terms of the result so long as the extraction does not require allocations. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkIsPubKeyScript-8 62323 2.97 -100.00% benchmark old allocs new allocs delta BenchmarkIsPubKeyScript-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsPubKeyScript-8 311299 0 -100.00% --- txscript/script.go | 6 +---- txscript/standard.go | 58 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index c642069ced..00df52167b 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -66,11 +66,7 @@ func isScriptHash(pops []parsedOpcode) bool { // IsPayToPubKey returns true if the script is in the standard pay-to-pubkey // (P2PK) format, false otherwise. func IsPayToPubKey(script []byte) bool { - pops, err := parseScript(script) - if err != nil { - return false - } - return isPubkey(pops) + return isPubKeyScript(script) } // IsPayToScriptHash returns true if the script is in the standard diff --git a/txscript/standard.go b/txscript/standard.go index 94b3cce57b..0a835dbb4f 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -85,6 +85,64 @@ func (t ScriptClass) String() string { return scriptClassToName[t] } +// extractCompressedPubKey extracts a compressed public key from the passed +// script if it is a standard pay-to-compressed-secp256k1-pubkey script. It +// will return nil otherwise. +func extractCompressedPubKey(script []byte) []byte { + // A pay-to-compressed-pubkey script is of the form: + // OP_DATA_33 <33-byte compressed pubkey> OP_CHECKSIG + + // All compressed secp256k1 public keys must start with 0x02 or 0x03. + if len(script) == 35 && + script[34] == OP_CHECKSIG && + script[0] == OP_DATA_33 && + (script[1] == 0x02 || script[1] == 0x03) { + + return script[1:34] + } + + return nil +} + +// extractUncompressedPubKey extracts an uncompressed public key from the +// passed script if it is a standard pay-to-uncompressed-secp256k1-pubkey +// script. It will return nil otherwise. +func extractUncompressedPubKey(script []byte) []byte { + // A pay-to-uncompressed-pubkey script is of the form: + // OP_DATA_65 <65-byte uncompressed pubkey> OP_CHECKSIG + // + // All non-hybrid uncompressed secp256k1 public keys must start with 0x04. + // Hybrid uncompressed secp256k1 public keys start with 0x06 or 0x07: + // - 0x06 => hybrid format for even Y coords + // - 0x07 => hybrid format for odd Y coords + if len(script) == 67 && + script[66] == OP_CHECKSIG && + script[0] == OP_DATA_65 && + (script[1] == 0x04 || script[1] == 0x06 || script[1] == 0x07) { + + return script[1:66] + } + return nil +} + +// extractPubKey extracts either compressed or uncompressed public key from the +// passed script if it is a either a standard pay-to-compressed-secp256k1-pubkey +// or pay-to-uncompressed-secp256k1-pubkey script, respectively. It will return +// nil otherwise. +func extractPubKey(script []byte) []byte { + if pubKey := extractCompressedPubKey(script); pubKey != nil { + return pubKey + } + return extractUncompressedPubKey(script) +} + +// isPubKeyScript returns whether or not the passed script is either a standard +// pay-to-compressed-secp256k1-pubkey or pay-to-uncompressed-secp256k1-pubkey +// script. +func isPubKeyScript(script []byte) bool { + return extractPubKey(script) != nil +} + // isPubkey returns true if the script passed is a pay-to-pubkey transaction, // false otherwise. func isPubkey(pops []parsedOpcode) bool { From 2d2608c34e293f5d95b132aba67bf1b58de8926f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 14:52:11 -0800 Subject: [PATCH 0481/1056] txscript: Add benchmark for IsPayToPubKeyHash --- txscript/bench_test.go | 15 +++++++++++++++ txscript/script.go | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 6415c595a5..401b9683a5 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -144,3 +144,18 @@ func BenchmarkIsPubKeyScript(b *testing.B) { _ = IsPayToPubKey(script) } } + +// BenchmarkIsPubKeyHashScript benchmarks how long it takes to analyze a very +// large script to determine if it is a standard pay-to-pubkey-hash script. +func BenchmarkIsPubKeyHashScript(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsPayToPubKeyHash(script) + } +} diff --git a/txscript/script.go b/txscript/script.go index 00df52167b..fb4fc8bc88 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -69,6 +69,16 @@ func IsPayToPubKey(script []byte) bool { return isPubKeyScript(script) } +// IsPayToPubKeyHash returns true if the script is in the standard +// pay-to-pubkey-hash (P2PKH) format, false otherwise. +func IsPayToPubKeyHash(script []byte) bool { + pops, err := parseScript(script) + if err != nil { + return false + } + return isPubkeyHash(pops) +} + // IsPayToScriptHash returns true if the script is in the standard // pay-to-script-hash (P2SH) format, false otherwise. func IsPayToScriptHash(script []byte) bool { From c771f4fb386e42a9363b614c58b536504feea0c2 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 14:09:28 -0800 Subject: [PATCH 0482/1056] txscript: Optimize IsPayToPubKeyHash This converts the IsPayToPubKeyHash function to analyze the raw script instead of using the far less efficient parseScript, thereby significantly optimization the function. In order to accomplish this, it introduces two new functions. The first one is named extractPubKeyHash and works with the raw script bytes to simultaneously determine if the script is a pay-to-pubkey-hash script, and in the case it is, extract and return the hash. The second new function is named isPubKeyHashScript and is defined in terms of the former. The extract function approach was chosen because it is common for callers to want to only extract relevant details from a script if the script is of the specific type. Extracting those details requires performing the exact same checks to ensure the script is of the correct type, so it is more efficient to combine the two into one and define the type determination in terms of the result so long as the extraction does not require allocations. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkIsPubKeyHashScript-8 62228 0.45 -100.00% benchmark old allocs new allocs delta BenchmarkIsPubKeyHashScript-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsPubKeyHashScript-8 311299 0 -100.00% --- txscript/script.go | 6 +----- txscript/standard.go | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index fb4fc8bc88..b154c1106d 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -72,11 +72,7 @@ func IsPayToPubKey(script []byte) bool { // IsPayToPubKeyHash returns true if the script is in the standard // pay-to-pubkey-hash (P2PKH) format, false otherwise. func IsPayToPubKeyHash(script []byte) bool { - pops, err := parseScript(script) - if err != nil { - return false - } - return isPubkeyHash(pops) + return isPubKeyHashScript(script) } // IsPayToScriptHash returns true if the script is in the standard diff --git a/txscript/standard.go b/txscript/standard.go index 0a835dbb4f..f7948f7930 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -143,6 +143,30 @@ func isPubKeyScript(script []byte) bool { return extractPubKey(script) != nil } +// extractPubKeyHash extracts the public key hash from the passed script if it +// is a standard pay-to-pubkey-hash script. It will return nil otherwise. +func extractPubKeyHash(script []byte) []byte { + // A pay-to-pubkey-hash script is of the form: + // OP_DUP OP_HASH160 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG + if len(script) == 25 && + script[0] == OP_DUP && + script[1] == OP_HASH160 && + script[2] == OP_DATA_20 && + script[23] == OP_EQUALVERIFY && + script[24] == OP_CHECKSIG { + + return script[3:23] + } + + return nil +} + +// isPubKeyHashScript returns whether or not the passed script is a standard +// pay-to-pubkey-hash script. +func isPubKeyHashScript(script []byte) bool { + return extractPubKeyHash(script) != nil +} + // isPubkey returns true if the script passed is a pay-to-pubkey transaction, // false otherwise. func isPubkey(pops []parsedOpcode) bool { From 665c29802ed3b6034396e4195b2abad8c77d2ab5 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:13 -0500 Subject: [PATCH 0483/1056] txscript: Add benchmark for IsPayToScriptHash. --- txscript/bench_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 401b9683a5..e47cf21fbe 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -159,3 +159,18 @@ func BenchmarkIsPubKeyHashScript(b *testing.B) { _ = IsPayToPubKeyHash(script) } } + +// BenchmarkIsPayToScriptHash benchmarks how long it takes IsPayToScriptHash to +// analyze a very large script. +func BenchmarkIsPayToScriptHash(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsPayToScriptHash(script) + } +} From 215af7ff5427d405d0443aa9b0c4bdb120f55f80 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:14 -0500 Subject: [PATCH 0484/1056] txscript: Optimize IsPayToScriptHash. This converts the IsPayToScriptHash function to analyze the raw script instead of using the far less efficient parseScript thereby significantly optimizing the function. In order to accomplish this, it introduces two new functions. The first one is named extractScriptHash and works with the raw script bytes to simultaneously determine if the script is a p2sh script, and in the case it is, extract and return the hash. The second new function is named isScriptHashScript and is defined in terms of the former. The extract function approach was chosen because it is common for callers to want to only extract relevant details from a script if the script is of the specific type. Extracting those details requires performing the exact same checks to ensure the script is of the correct type, so it is more efficient to combine the two into one and define the type determination in terms of the result so long as the extraction does not require allocations. Finally, this also deprecates the isScriptHash function that requires opcodes in favor of the new functions and modifies the comment on IsPayToScriptHash to explicitly call out the script version semantics. The following is a before and after comparison of analyzing a large script that is not a p2sh script: benchmark old ns/op new ns/op delta BenchmarkIsPayToScriptHash-8 62393 0.60 -100.00% benchmark old allocs new allocs delta BenchmarkIsPayToScriptHash-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsPayToScriptHash-8 311299 0 -100.00% --- txscript/script.go | 14 +++++++++----- txscript/standard.go | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index b154c1106d..a8cfd16656 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -56,6 +56,8 @@ func isSmallInt(op byte) bool { // isScriptHash returns true if the script passed is a pay-to-script-hash // transaction, false otherwise. +// +// DEPRECATED. Use isScriptHashScript or extractScriptHash instead. func isScriptHash(pops []parsedOpcode) bool { return len(pops) == 3 && pops[0].opcode.value == OP_HASH160 && @@ -77,12 +79,14 @@ func IsPayToPubKeyHash(script []byte) bool { // IsPayToScriptHash returns true if the script is in the standard // pay-to-script-hash (P2SH) format, false otherwise. +// +// WARNING: This function always treats the passed script as version 0. Great +// care must be taken if introducing a new script version because it is used in +// consensus which, unfortunately as of the time of this writing, does not check +// script versions before determining if the script is a P2SH which means nodes +// on existing rules will analyze new version scripts as if they were version 0. func IsPayToScriptHash(script []byte) bool { - pops, err := parseScript(script) - if err != nil { - return false - } - return isScriptHash(pops) + return isScriptHashScript(script) } // isWitnessScriptHash returns true if the passed script is a diff --git a/txscript/standard.go b/txscript/standard.go index f7948f7930..a02f87232d 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -167,6 +167,32 @@ func isPubKeyHashScript(script []byte) bool { return extractPubKeyHash(script) != nil } +// extractScriptHash extracts the script hash from the passed script if it is a +// standard pay-to-script-hash script. It will return nil otherwise. +// +// NOTE: This function is only valid for version 0 opcodes. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func extractScriptHash(script []byte) []byte { + // A pay-to-script-hash script is of the form: + // OP_HASH160 <20-byte scripthash> OP_EQUAL + if len(script) == 23 && + script[0] == OP_HASH160 && + script[1] == OP_DATA_20 && + script[22] == OP_EQUAL { + + return script[2:22] + } + + return nil +} + +// isScriptHashScript returns whether or not the passed script is a standard +// pay-to-script-hash script. +func isScriptHashScript(script []byte) bool { + return extractScriptHash(script) != nil +} + // isPubkey returns true if the script passed is a pay-to-pubkey transaction, // false otherwise. func isPubkey(pops []parsedOpcode) bool { From 4d31d1599dc351183246aa4e85c9d77b199105f9 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:15 -0500 Subject: [PATCH 0485/1056] txscript: Add benchmarks for IsMutlsigScript. --- txscript/bench_test.go | 45 ++++++++++++++++++++++++++++++++++++++++++ txscript/standard.go | 21 ++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index e47cf21fbe..49be4958c6 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -174,3 +174,48 @@ func BenchmarkIsPayToScriptHash(b *testing.B) { _ = IsPayToScriptHash(script) } } + +// BenchmarkIsMultisigScriptLarge benchmarks how long it takes IsMultisigScript +// to analyze a very large script. +func BenchmarkIsMultisigScriptLarge(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + isMultisig, err := IsMultisigScript(script) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + if isMultisig { + b.Fatalf("script should NOT be reported as mutisig script") + } + } +} + +// BenchmarkIsMultisigScript benchmarks how long it takes IsMultisigScript to +// analyze a 1-of-2 multisig public key script. +func BenchmarkIsMultisigScript(b *testing.B) { + multisigShortForm := "1 " + + "DATA_33 " + + "0x030478aaaa2be30772f1e69e581610f1840b3cf2fe7228ee0281cd599e5746f81e " + + "DATA_33 " + + "0x0284f4d078b236a9ff91661f8ffbe012737cd3507566f30fd97d25f2b23539f3cd " + + "2 CHECKMULTISIG" + pkScript := mustParseShortForm(multisigShortForm) + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + isMultisig, err := IsMultisigScript(pkScript) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + if !isMultisig { + b.Fatalf("script should be reported as a mutisig script") + } + } +} diff --git a/txscript/standard.go b/txscript/standard.go index a02f87232d..25483aebe5 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -248,6 +248,27 @@ func isMultiSig(pops []parsedOpcode) bool { return true } +// IsMultisigScript returns whether or not the passed script is a standard +// multisignature script. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +// +// The error is DEPRECATED and will be removed in the major version bump. +func IsMultisigScript(script []byte) (bool, error) { + if len(script) == 0 || script == nil { + return false, nil + } + + pops, err := parseScript(script) + if err != nil { + return false, err + } + + return isMultiSig(pops), nil +} + // isNullData returns true if the passed script is a null data transaction, // false otherwise. func isNullData(pops []parsedOpcode) bool { From 0eaae2663ba9955de61a2c6bf52b008dd40cc7f6 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:16 -0500 Subject: [PATCH 0486/1056] txscript: Optimize IsMultisigScript. This converts the IsMultisigScript function to make use of the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. In order to accomplish this, it introduces two new functions. The first one is named extractMultisigScriptDetails and works with the raw script bytes to simultaneously determine if the script is a multisignature script, and in the case it is, extract and return the relevant details. The second new function is named isMultisigScript and is defined in terms of the former. The extract function accepts the script version, raw script bytes, and a flag to determine whether or not the public keys should also be extracted. The flag is provided because extracting pubkeys results in an allocation that the caller might wish to avoid. The extract function approach was chosen because it is common for callers to want to only extract relevant details from a script if the script is of the specific type. Extracting those details requires performing the exact same checks to ensure the script is of the correct type, so it is more efficient to combine the two into one and define the type determination in terms of the result so long as the extraction does not require allocations. It is important to note that this new implementation intentionally has a semantic difference from the existing implementation in that it will now correctly identify a multisig script with zero pubkeys whereas previously it incorrectly required at least one pubkey. This change is acceptable because the function only deals with standardness rather than consensus rules. Finally, this also deprecates the isMultiSig function that requires opcodes in favor of the new functions and deprecates the error return on the export IsMultisigScript function since it really does not make sense given the purpose of the function. The following is a before and after comparison of analyzing both a large script that is not a multisig script and a 1-of-2 multisig public key script: benchmark old ns/op new ns/op delta BenchmarkIsMultisigScriptLarge-8 64166 5.52 -99.99% BenchmarkIsMultisigScript-8 630 59.4 -90.57% benchmark old allocs new allocs delta BenchmarkIsMultisigScriptLarge-8 1 0 -100.00% BenchmarkIsMultisigScript-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsMultisigScriptLarge-8 311299 0 -100.00% BenchmarkIsMultisigScript-8 2304 0 -100.00% --- txscript/engine.go | 21 ++++++++ txscript/standard.go | 116 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 127 insertions(+), 10 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index f2d7b303c1..3c76b74794 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -580,6 +580,27 @@ func (vm *Engine) checkHashTypeEncoding(hashType SigHashType) error { return nil } +// isStrictPubKeyEncoding returns whether or not the passed public key adheres +// to the strict encoding requirements. +func isStrictPubKeyEncoding(pubKey []byte) bool { + if len(pubKey) == 33 && (pubKey[0] == 0x02 || pubKey[0] == 0x03) { + // Compressed + return true + } + if len(pubKey) == 65 { + switch pubKey[0] { + case 0x04: + // Uncompressed + return true + + case 0x06, 0x07: + // Hybrid + return true + } + } + return false +} + // checkPubKeyEncoding returns whether or not the passed public key adheres to // the strict encoding requirements if enabled. func (vm *Engine) checkPubKeyEncoding(pubKey []byte) error { diff --git a/txscript/standard.go b/txscript/standard.go index 25483aebe5..096de4e561 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -216,6 +216,8 @@ func isPubkeyHash(pops []parsedOpcode) bool { // isMultiSig returns true if the passed script is a multisig transaction, false // otherwise. +// +// DEPECATED. Use isMultisigScript or extractMultisigScriptDetails instead. func isMultiSig(pops []parsedOpcode) bool { // The absolute minimum is 1 pubkey: // OP_0/OP_1-16 OP_1 OP_CHECKMULTISIG @@ -248,6 +250,108 @@ func isMultiSig(pops []parsedOpcode) bool { return true } +// multiSigDetails houses details extracted from a standard multisig script. +type multiSigDetails struct { + requiredSigs int + numPubKeys int + pubKeys [][]byte + valid bool +} + +// extractMultisigScriptDetails attempts to extract details from the passed +// script if it is a standard multisig script. The returned details struct will +// have the valid flag set to false otherwise. +// +// The extract pubkeys flag indicates whether or not the pubkeys themselves +// should also be extracted and is provided because extracting them results in +// an allocation that the caller might wish to avoid. The pubKeys member of +// the returned details struct will be nil when the flag is false. +// +// NOTE: This function is only valid for version 0 scripts. The returned +// details struct will always be empty and have the valid flag set to false for +// other script versions. +func extractMultisigScriptDetails(scriptVersion uint16, script []byte, extractPubKeys bool) multiSigDetails { + // The only currently supported script version is 0. + if scriptVersion != 0 { + return multiSigDetails{} + } + + // A multi-signature script is of the form: + // NUM_SIGS PUBKEY PUBKEY PUBKEY ... NUM_PUBKEYS OP_CHECKMULTISIG + + // The script can't possibly be a multisig script if it doesn't end with + // OP_CHECKMULTISIG or have at least two small integer pushes preceding it. + // Fail fast to avoid more work below. + if len(script) < 3 || script[len(script)-1] != OP_CHECKMULTISIG { + return multiSigDetails{} + } + + // The first opcode must be a small integer specifying the number of + // signatures required. + tokenizer := MakeScriptTokenizer(scriptVersion, script) + if !tokenizer.Next() || !isSmallInt(tokenizer.Opcode()) { + return multiSigDetails{} + } + requiredSigs := asSmallInt(tokenizer.Opcode()) + + // The next series of opcodes must either push public keys or be a small + // integer specifying the number of public keys. + var numPubKeys int + var pubKeys [][]byte + if extractPubKeys { + pubKeys = make([][]byte, 0, MaxPubKeysPerMultiSig) + } + for tokenizer.Next() { + if isSmallInt(tokenizer.Opcode()) { + break + } + + data := tokenizer.Data() + numPubKeys++ + if !isStrictPubKeyEncoding(data) { + continue + } + if extractPubKeys { + pubKeys = append(pubKeys, data) + } + } + if tokenizer.Done() { + return multiSigDetails{} + } + + // The next opcode must be a small integer specifying the number of public + // keys required. + op := tokenizer.Opcode() + if !isSmallInt(op) || asSmallInt(op) != numPubKeys { + return multiSigDetails{} + } + + // There must only be a single opcode left unparsed which will be + // OP_CHECKMULTISIG per the check above. + if int32(len(tokenizer.Script()))-tokenizer.ByteIndex() != 1 { + return multiSigDetails{} + } + + return multiSigDetails{ + requiredSigs: requiredSigs, + numPubKeys: numPubKeys, + pubKeys: pubKeys, + valid: true, + } +} + +// isMultisigScript returns whether or not the passed script is a standard +// multisig script. +// +// NOTE: This function is only valid for version 0 scripts. It will always +// return false for other script versions. +func isMultisigScript(scriptVersion uint16, script []byte) bool { + // Since this is only checking the form of the script, don't extract the + // public keys to avoid the allocation. + details := extractMultisigScriptDetails(scriptVersion, script, false) + return details.valid +} + // IsMultisigScript returns whether or not the passed script is a standard // multisignature script. // @@ -257,16 +361,8 @@ func isMultiSig(pops []parsedOpcode) bool { // // The error is DEPRECATED and will be removed in the major version bump. func IsMultisigScript(script []byte) (bool, error) { - if len(script) == 0 || script == nil { - return false, nil - } - - pops, err := parseScript(script) - if err != nil { - return false, err - } - - return isMultiSig(pops), nil + const scriptVersion = 0 + return isMultisigScript(scriptVersion, script), nil } // isNullData returns true if the passed script is a null data transaction, From 02dab1695f3d99299f6448523529197cfca584d3 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:17 -0500 Subject: [PATCH 0487/1056] txscript: Add benchmarks for IsMutlsigSigScript. --- txscript/bench_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++ txscript/standard.go | 18 ++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 49be4958c6..41d79ccba1 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -219,3 +219,51 @@ func BenchmarkIsMultisigScript(b *testing.B) { } } } + +// BenchmarkIsMultisigSigScript benchmarks how long it takes IsMultisigSigScript +// to analyze a very large script. +func BenchmarkIsMultisigSigScriptLarge(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if IsMultisigSigScript(script) { + b.Fatalf("script should NOT be reported as mutisig sig script") + } + } +} + +// BenchmarkIsMultisigSigScript benchmarks how long it takes IsMultisigSigScript +// to analyze both a 1-of-2 multisig public key script (which should be false) +// and a signature script comprised of a pay-to-script-hash 1-of-2 multisig +// redeem script (which should be true). +func BenchmarkIsMultisigSigScript(b *testing.B) { + multisigShortForm := "1 " + + "DATA_33 " + + "0x030478aaaa2be30772f1e69e581610f1840b3cf2fe7228ee0281cd599e5746f81e " + + "DATA_33 " + + "0x0284f4d078b236a9ff91661f8ffbe012737cd3507566f30fd97d25f2b23539f3cd " + + "2 CHECKMULTISIG" + pkScript := mustParseShortForm(multisigShortForm) + + sigHex := "0x304402205795c3ab6ba11331eeac757bf1fc9c34bef0c7e1a9c8bd5eebb8" + + "82f3b79c5838022001e0ab7b4c7662e4522dc5fa479e4b4133fa88c6a53d895dc1d5" + + "2eddc7bbcf2801 " + sigScript := mustParseShortForm("DATA_71 " + sigHex + "DATA_71 " + + multisigShortForm) + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if IsMultisigSigScript(pkScript) { + b.Fatalf("script should NOT be reported as mutisig sig script") + } + if !IsMultisigSigScript(sigScript) { + b.Fatalf("script should be reported as a mutisig sig script") + } + } +} diff --git a/txscript/standard.go b/txscript/standard.go index 096de4e561..51dcbfb9ca 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -365,6 +365,24 @@ func IsMultisigScript(script []byte) (bool, error) { return isMultisigScript(scriptVersion, script), nil } +// IsMultisigSigScript takes a script, parses it, then returns whether or +// not it is a multisignature script. +func IsMultisigSigScript(script []byte) bool { + if len(script) == 0 || script == nil { + return false + } + pops, err := parseScript(script) + if err != nil { + return false + } + subPops, err := parseScript(pops[len(pops)-1].data) + if err != nil { + return false + } + + return isMultiSig(subPops) +} + // isNullData returns true if the passed script is a null data transaction, // false otherwise. func isNullData(pops []parsedOpcode) bool { From 34ebf0f32f4729eb5f37133cae9f9f2b4fdc7033 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:18 -0500 Subject: [PATCH 0488/1056] txscript: Optimize IsMultisigSigScript. This converts the IsMultisigSigScript function to analyze the raw script and make use of the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. In order to accomplish this, it first rejects scripts that can't possibly fit the bill due to the final byte of what would be the redeem script not being the appropriate opcode or the overall script not having enough bytes. Then, it uses a new function that is introduced named finalOpcodeData that uses the tokenizer to return any data associated with the final opcode in the signature script (which will be nil for non-push opcodes or if the script fails to parse) and analyzes it as if it were a redeem script when it is non nil. It is also worth noting that this new implementation intentionally has the same semantic difference from the existing implementation as the updated IsMultisigScript function in regards to allowing zero pubkeys whereas previously it incorrectly required at least one pubkey. Finally, the comment is modified to explicitly call out the script version semantics. The following is a before and after comparison of analyzing a large script that is not a multisig script and both a 1-of-2 multisig public key script (which should be false) and a signature script comprised of a pay-to-script-hash 1-of-2 multisig redeem script (which should be true): benchmark old ns/op new ns/op delta BenchmarkIsMultisigSigScriptLarge-8 69328 2.93 -100.00% BenchmarkIsMultisigSigScript-8 2375 146 -93.85% benchmark old allocs new allocs delta BenchmarkIsMultisigSigScriptLarge-8 5 0 -100.00% BenchmarkIsMultisigSigScript-8 3 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsMultisigSigScriptLarge-8 330035 0 -100.00% BenchmarkIsMultisigSigScript-8 9472 0 -100.00% --- txscript/script.go | 19 +++++++++++++++++++ txscript/standard.go | 37 +++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index a8cfd16656..eb5be8b7ca 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -769,6 +769,25 @@ func GetSigOpCount(script []byte) int { return getSigOpCount(pops, false) } +// finalOpcodeData returns the data associated with the final opcode in the +// script. It will return nil if the script fails to parse. +func finalOpcodeData(scriptVersion uint16, script []byte) []byte { + // Avoid unnecessary work. + if len(script) == 0 { + return nil + } + + var data []byte + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + data = tokenizer.Data() + } + if tokenizer.Err() != nil { + return nil + } + return data +} + // GetPreciseSigOpCount returns the number of signature operations in // scriptPubKey. If bip16 is true then scriptSig may be searched for the // Pay-To-Script-Hash script in order to find the precise number of signature diff --git a/txscript/standard.go b/txscript/standard.go index 51dcbfb9ca..272b42b8fa 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -365,22 +365,39 @@ func IsMultisigScript(script []byte) (bool, error) { return isMultisigScript(scriptVersion, script), nil } -// IsMultisigSigScript takes a script, parses it, then returns whether or -// not it is a multisignature script. +// IsMultisigSigScript returns whether or not the passed script appears to be a +// signature script which consists of a pay-to-script-hash multi-signature +// redeem script. Determining if a signature script is actually a redemption of +// pay-to-script-hash requires the associated public key script which is often +// expensive to obtain. Therefore, this makes a fast best effort guess that has +// a high probability of being correct by checking if the signature script ends +// with a data push and treating that data push as if it were a p2sh redeem +// script +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func IsMultisigSigScript(script []byte) bool { - if len(script) == 0 || script == nil { - return false - } - pops, err := parseScript(script) - if err != nil { + const scriptVersion = 0 + + // The script can't possibly be a multisig signature script if it doesn't + // end with OP_CHECKMULTISIG in the redeem script or have at least two small + // integers preceding it, and the redeem script itself must be preceded by + // at least a data push opcode. Fail fast to avoid more work below. + if len(script) < 4 || script[len(script)-1] != OP_CHECKMULTISIG { return false } - subPops, err := parseScript(pops[len(pops)-1].data) - if err != nil { + + // Parse through the script to find the last opcode and any data it might + // push and treat it as a p2sh redeem script even though it might not + // actually be one. + possibleRedeemScript := finalOpcodeData(scriptVersion, script) + if possibleRedeemScript == nil { return false } - return isMultiSig(subPops) + // Finally, return if that possible redeem script is a multisig script. + return isMultisigScript(scriptVersion, possibleRedeemScript) } // isNullData returns true if the passed script is a null data transaction, From ce1513df03cfc708b2f6eacd1080e6f078455c84 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:25 -0500 Subject: [PATCH 0489/1056] txscript: Add benchmark for IsPushOnlyScript. --- txscript/bench_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 41d79ccba1..ca64267a8e 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -267,3 +267,18 @@ func BenchmarkIsMultisigSigScript(b *testing.B) { } } } + +// BenchmarkIsPushOnlyScript benchmarks how long it takes IsPushOnlyScript to +// analyze a very large script. +func BenchmarkIsPushOnlyScript(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsPushOnlyScript(script) + } +} From 2d5f7cf82540247f716d65f91dcbc934e67ccb67 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:26 -0500 Subject: [PATCH 0490/1056] txscript: Optimize IsPushOnlyScript. This converts the IsPushOnlyScript function to make use of the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. It also deprecates the isPushOnly function that requires opcodes in favor of the new function and modifies the comment on IsPushOnlyScript to explicitly call out the script version semantics. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkIsPushOnlyScript-8 62412 622 -99.00% benchmark old allocs new allocs delta BenchmarkIsPushOnlyScript-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsPushOnlyScript-8 311299 0 -100.00% --- txscript/script.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index eb5be8b7ca..43048e9526 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -182,6 +182,8 @@ func ExtractWitnessProgramInfo(script []byte) (int, []byte, error) { } // isPushOnly returns true if the script only pushes data, false otherwise. +// +// DEPRECATED. Use IsPushOnlyScript instead. func isPushOnly(pops []parsedOpcode) bool { // NOTE: This function does NOT verify opcodes directly since it is // internal and is only called with parsed opcodes for scripts that did @@ -199,15 +201,27 @@ func isPushOnly(pops []parsedOpcode) bool { return true } -// IsPushOnlyScript returns whether or not the passed script only pushes data. +// IsPushOnlyScript returns whether or not the passed script only pushes data +// according to the consensus definition of pushing data. // -// False will be returned when the script does not parse. +// WARNING: This function always treats the passed script as version 0. Great +// care must be taken if introducing a new script version because it is used in +// consensus which, unfortunately as of the time of this writing, does not check +// script versions before checking if it is a push only script which means nodes +// on existing rules will treat new version scripts as if they were version 0. func IsPushOnlyScript(script []byte) bool { - pops, err := parseScript(script) - if err != nil { - return false + const scriptVersion = 0 + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + // All opcodes up to OP_16 are data push instructions. + // NOTE: This does consider OP_RESERVED to be a data push instruction, + // but execution of OP_RESERVED will fail anyway and matches the + // behavior required by consensus. + if tokenizer.Opcode() > OP_16 { + return false + } } - return isPushOnly(pops) + return tokenizer.Err() == nil } // parseScriptTemplate is the same as parseScript but allows the passing of the From e422d42d7fdde45c222810363d24b8eb3340cf2a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 01:43:18 -0700 Subject: [PATCH 0491/1056] txscript: Add benchmark IsPayToWitnessPubkeyHash --- txscript/bench_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index ca64267a8e..de6636d9e7 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -282,3 +282,18 @@ func BenchmarkIsPushOnlyScript(b *testing.B) { _ = IsPushOnlyScript(script) } } + +// BenchmarkIsWitnessPubKeyHash benchmarks how long it takes to analyze a very +// large script to determine if it is a standard witness pubkey hash script. +func BenchmarkIsWitnessPubKeyHash(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsPayToWitnessPubKeyHash(script) + } +} From 54d08ebd5fa1706790e2cf73e87804b071368a0c Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 13:22:40 -0800 Subject: [PATCH 0492/1056] txscript: Optimize IsPayToWitnessPubKeyHash This converts the IsPayToWitnessPubKeyHash function to analyze the raw script instead of the far less efficient parseScript, thereby significantly optimizing the function. In order to accomplish this, it introduces two new functions. The first one is named extractWitnessPubKeyHash and works with the raw script bytes to simultaneously deteremine if the script is a p2wkh, and in case it is, extract and return the hash. The second new function is name isWitnessPubKeyHashScript which is defined in terms of the former. The extract function is approach was chosen because it is common for callers to want to only extract relevant details from the script if the script is of the specific type. Extracting those details requires the exact same checks to ensure the script is of the correct type, so it is more efficient to combine the two and define the type determination in terms of the result so long as the extraction does not require allocations. Finally, this deprecates the isWitnessPubKeyHash function that requires opcodes in favor of the new functions and modifies the comment on IsPayToWitnessPubKeyHash to explicitly call out the script version semantics. The following is a before and after comparison of executing IsPayToWitnessPubKeyHash on a large script: benchmark old ns/op new ns/op delta BenchmarkIsWitnessPubKeyHash-8 68927 0.53 -100.00% benchmark old allocs new allocs delta BenchmarkIsWitnessPubKeyHash-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsWitnessPubKeyHash-8 311299 0 -100.00% --- txscript/script.go | 6 +----- txscript/standard.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 43048e9526..59dc2e272b 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -110,11 +110,7 @@ func IsPayToWitnessScriptHash(script []byte) bool { // IsPayToWitnessPubKeyHash returns true if the is in the standard // pay-to-witness-pubkey-hash (P2WKH) format, false otherwise. func IsPayToWitnessPubKeyHash(script []byte) bool { - pops, err := parseScript(script) - if err != nil { - return false - } - return isWitnessPubKeyHash(pops) + return isWitnessPubKeyHashScript(script) } // isWitnessPubKeyHash returns true if the passed script is a diff --git a/txscript/standard.go b/txscript/standard.go index 272b42b8fa..513c9ce181 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -400,6 +400,27 @@ func IsMultisigSigScript(script []byte) bool { return isMultisigScript(scriptVersion, possibleRedeemScript) } +// extractWitnessPubKeyHash extracts the witness public key hash from the passed +// script if it is a standard pay-to-witness-pubkey-hash script. It will return +// nil otherwise. +func extractWitnessPubKeyHash(script []byte) []byte { + // A pay-to-witness-pubkey-hash script is of the form: + // OP_0 OP_DATA_20 <20-byte-hash> + if len(script) == 22 && + script[0] == OP_0 && + script[1] == OP_DATA_20 { + + return script[2:22] + } + return nil +} + +// isWitnessPubKeyHashScript returns whether or not the passed script is a +// standard pay-to-witness-pubkey-hash script. +func isWitnessPubKeyHashScript(script []byte) bool { + return extractWitnessPubKeyHash(script) != nil +} + // isNullData returns true if the passed script is a null data transaction, // false otherwise. func isNullData(pops []parsedOpcode) bool { From 728ce1001d210f291796a0ad1748be2fc3abd505 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 01:57:31 -0700 Subject: [PATCH 0493/1056] txscript: Add benchmark for IsPayToWitnessScriptHash --- txscript/bench_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index de6636d9e7..529d32f7ff 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -297,3 +297,18 @@ func BenchmarkIsWitnessPubKeyHash(b *testing.B) { _ = IsPayToWitnessPubKeyHash(script) } } + +// BenchmarkIsWitnessScriptHash benchmarks how long it takes to analyze a very +// large script to determine if it is a standard witness script hash script. +func BenchmarkIsWitnessScriptHash(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsPayToWitnessScriptHash(script) + } +} From 55a6bb5e325b8a9511e485160420c0acf236b44a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 13:39:10 -0800 Subject: [PATCH 0494/1056] txscript: Optimize IsPayToWitnessScriptHash This converts the IsPayToWitnessScriptHash function to analyze the raw script instead of using the far less efficient parseScript, thereby significantly optimizing the function. In order to accomplish this, it introduces two new functions. The first one is named extractWitnessScriptHash and works with the raw script byte to simultaneously deteremine if the script is a p2wsh script, and in the case that is is, extract and return the hash. The second new function is named isWitnessScriptHashScript and is defined in terms of the former. The extract function approach was chosed because it is common for callers to want to only extract relevant details from a script if the script is of the specific type. Extracting those details requires performing the exact same checks to ensure the script is of the correct type, so it is more efficient to combine the two into one and define the type determination in terms of the result, so long as the extraction does not require allocations. Finally, this also deprecates the isWitnessScriptHash function that requires opcodes in favor of the new functions and modifies the comment on IsPayToWitnessScriptHash to call out the script version semantics. The following is a before and after comparison of executing IsPayToWitnessScriptHash on a large script: benchmark old ns/op new ns/op delta BenchmarkIsWitnessScriptHash-8 62774 0.63 -100.00% benchmark old allocs new allocs delta BenchmarkIsWitnessScriptHash-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsWitnessScriptHash-8 311299 0 -100.00% --- txscript/script.go | 6 +----- txscript/standard.go | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 59dc2e272b..5968cec72a 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -100,11 +100,7 @@ func isWitnessScriptHash(pops []parsedOpcode) bool { // IsPayToWitnessScriptHash returns true if the is in the standard // pay-to-witness-script-hash (P2WSH) format, false otherwise. func IsPayToWitnessScriptHash(script []byte) bool { - pops, err := parseScript(script) - if err != nil { - return false - } - return isWitnessScriptHash(pops) + return isWitnessScriptHashScript(script) } // IsPayToWitnessPubKeyHash returns true if the is in the standard diff --git a/txscript/standard.go b/txscript/standard.go index 513c9ce181..a53180f148 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -421,6 +421,28 @@ func isWitnessPubKeyHashScript(script []byte) bool { return extractWitnessPubKeyHash(script) != nil } +// extractWitnessScriptHash extracts the witness script hash from the passed +// script if it is standard pay-to-witness-script-hash script. It will return +// nil otherwise. +func extractWitnessScriptHash(script []byte) []byte { + // A pay-to-witness-script-hash script is of the form: + // OP_0 OP_DATA_32 <32-byte-hash> + if len(script) == 34 && + script[0] == OP_0 && + script[1] == OP_DATA_32 { + + return script[2:34] + } + + return nil +} + +// isWitnessScriptHashScript returns whether or not the passed script is a +// standard pay-to-witness-script-hash script. +func isWitnessScriptHashScript(script []byte) bool { + return extractWitnessScriptHash(script) != nil +} + // isNullData returns true if the passed script is a null data transaction, // false otherwise. func isNullData(pops []parsedOpcode) bool { From e4118c914fb8cdcced379a41b62f95402796cbed Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:49 -0500 Subject: [PATCH 0495/1056] txscript: Add benchmark for IsNullData --- txscript/bench_test.go | 15 +++++++++++++++ txscript/script.go | 10 ++++++++++ 2 files changed, 25 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 529d32f7ff..fda8377141 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -312,3 +312,18 @@ func BenchmarkIsWitnessScriptHash(b *testing.B) { _ = IsPayToWitnessScriptHash(script) } } + +// BenchmarkIsNullDataScript benchmarks how long it takes to analyze a very +// large script to determine if it is a standard nulldata script. +func BenchmarkIsNullDataScript(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsNullData(script) + } +} diff --git a/txscript/script.go b/txscript/script.go index 5968cec72a..7f812207f9 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -151,6 +151,16 @@ func isWitnessProgram(pops []parsedOpcode) bool { (len(pops[1].data) >= 2 && len(pops[1].data) <= 40) } +// IsNullData returns true if the passed script is a null data script, false +// otherwise. +func IsNullData(script []byte) bool { + pops, err := parseScript(script) + if err != nil { + return false + } + return isNullData(pops) +} + // ExtractWitnessProgramInfo attempts to extract the witness program version, // as well as the witness program itself from the passed script. func ExtractWitnessProgramInfo(script []byte) (int, []byte, error) { From 5f771c1aaa5db7427011de1478182ed0d95ecf37 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 15:15:34 -0800 Subject: [PATCH 0496/1056] txscript: Optimize IsNullData This converts the IsNullData function to analyze the raw script instead of using the far less efficient parseScript, thereby significantly optimizing the function. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkIsNullDataScript-8 62495 2.65 -100.00% benchmark old allocs new allocs delta BenchmarkIsNullDataScript-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsNullDataScript-8 311299 0 -100.00% --- txscript/script.go | 7 ++----- txscript/standard.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 7f812207f9..691e31cc64 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -154,11 +154,8 @@ func isWitnessProgram(pops []parsedOpcode) bool { // IsNullData returns true if the passed script is a null data script, false // otherwise. func IsNullData(script []byte) bool { - pops, err := parseScript(script) - if err != nil { - return false - } - return isNullData(pops) + const scriptVersion = 0 + return isNullDataScript(scriptVersion, script) } // ExtractWitnessProgramInfo attempts to extract the witness program version, diff --git a/txscript/standard.go b/txscript/standard.go index a53180f148..9825f61bea 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -461,6 +461,41 @@ func isNullData(pops []parsedOpcode) bool { len(pops[1].data) <= MaxDataCarrierSize } +// isNullDataScript returns whether or not the passed script is a standard +// null data script. +// +// NOTE: This function is only valid for version 0 scripts. It will always +// return false for other script versions. +func isNullDataScript(scriptVersion uint16, script []byte) bool { + // The only currently supported script version is 0. + if scriptVersion != 0 { + return false + } + + // A null script is of the form: + // OP_RETURN + // + // Thus, it can either be a single OP_RETURN or an OP_RETURN followed by a + // data push up to MaxDataCarrierSize bytes. + + // The script can't possibly be a a null data script if it doesn't start + // with OP_RETURN. Fail fast to avoid more work below. + if len(script) < 1 || script[0] != OP_RETURN { + return false + } + + // Single OP_RETURN. + if len(script) == 1 { + return true + } + + // OP_RETURN followed by data push up to MaxDataCarrierSize bytes. + tokenizer := MakeScriptTokenizer(scriptVersion, script[1:]) + return tokenizer.Next() && tokenizer.Done() && + (isSmallInt(tokenizer.Opcode()) || tokenizer.Opcode() <= OP_PUSHDATA4) && + len(tokenizer.Data()) <= MaxDataCarrierSize +} + // scriptType returns the type of the script being inspected from the known // standard types. func typeOfScript(pops []parsedOpcode) ScriptClass { From 77660b7fb0e2de0fd4d159fd09e29bf4025690df Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:20 -0500 Subject: [PATCH 0497/1056] txscript: Add benchmark for IsUnspendable. --- txscript/bench_test.go | 14 ++++++++++++++ txscript/script_test.go | 13 ------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index fda8377141..c8f7d0f790 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -327,3 +327,17 @@ func BenchmarkIsNullDataScript(b *testing.B) { _ = IsNullData(script) } } + +// BenchmarkIsUnspendable benchmarks how long it takes IsUnspendable to analyze +// a very large script. +func BenchmarkIsUnspendable(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = IsUnspendable(script) + } +} diff --git a/txscript/script_test.go b/txscript/script_test.go index 34c8ef9740..665d9ef633 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -4334,16 +4334,3 @@ func TestIsUnspendable(t *testing.T) { } } } - -// BenchmarkIsUnspendable adds a benchmark to compare the time and allocations -// necessary for the IsUnspendable function. -func BenchmarkIsUnspendable(b *testing.B) { - pkScriptToUse := []byte{0xa9, 0x14, 0x82, 0x1d, 0xba, 0x94, 0xbc, 0xfb, 0xa2, 0x57, 0x36, 0xa3, 0x9e, 0x5d, 0x14, 0x5d, 0x69, 0x75, 0xba, 0x8c, 0x0b, 0x42, 0x87} - var res bool = false - for i := 0; i < b.N; i++ { - res = IsUnspendable(pkScriptToUse) - } - if res { - b.Fatalf("Benchmark should never have res be %t\n", res) - } -} From e98b7c1a9a10ae18e2e724aceeee57c216095517 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:21 -0500 Subject: [PATCH 0498/1056] txscript: Optimize IsUnspendable. This converts the IsUnspendable function to make use of a combination of raw script analysis and the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. It is important to note that this new implementation intentionally has a semantic difference from the existing implementation in that it will now report scripts that are larger than the max allowed script size are unspendable as well. Finally, the comment is modified to explicitly call out the script version semantics. Note: this function was recently optimized in master, so the gains here are less noticable than other optimizations. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkIsUnspendable-8 656 584 -10.98% benchmark old allocs new allocs delta BenchmarkIsUnspendable-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsUnspendable-8 1 0 -100.00% --- txscript/script.go | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 691e31cc64..e933167d4c 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -917,15 +917,22 @@ func checkScriptParses(scriptVersion uint16, script []byte) error { // IsUnspendable returns whether the passed public key script is unspendable, or // guaranteed to fail at execution. This allows inputs to be pruned instantly // when entering the UTXO set. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func IsUnspendable(pkScript []byte) bool { - // Not provably unspendable - if len(pkScript) == 0 { - return false - } - firstOpcode, err := checkScriptTemplateParseable(pkScript, &opcodeArray) - if err != nil { + // The script is unspendable if starts with OP_RETURN or is guaranteed + // to fail at execution due to being larger than the max allowed script + // size. + switch { + case len(pkScript) > 0 && pkScript[0] == OP_RETURN: + return true + case len(pkScript) > MaxScriptSize: return true } - return firstOpcode != nil && *firstOpcode == OP_RETURN + // The script is unspendable if it is guaranteed to fail at execution. + const scriptVersion = 0 + return checkScriptParses(scriptVersion, pkScript) != nil } From 549a1f26f2de278362b0b7643954c2e5a5a5dd58 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 00:35:28 -0700 Subject: [PATCH 0499/1056] txscript/engine: Optimize new engine push only script This modifies the check for whether or not a pay-to-script-hash signature script is a push only script to make use of the new and more efficient raw script function. Also, since the script will have already been checked further above when the ScriptVerifySigPushOnly flags is set, avoid checking it again in that case. Backport of af67951b9a66df3aac1bf3d6376af0730287bbf2 --- txscript/engine.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/txscript/engine.go b/txscript/engine.go index 3c76b74794..06f454d372 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -946,7 +946,11 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags if vm.hasFlag(ScriptBip16) && isScriptHash(vm.scripts[1]) { // Only accept input scripts that push data for P2SH. - if !isPushOnly(vm.scripts[0]) { + // Notice that the push only checks have already been done when + // the flag to verify signature scripts are push only is set + // above, so avoid checking again. + alreadyChecked := vm.hasFlag(ScriptVerifySigPushOnly) + if !alreadyChecked && !isPushOnly(vm.scripts[0]) { return nil, scriptError(ErrNotPushOnly, "pay to script hash is not push only") } From a59e01c23c057d904cf4b23df0d85620b42a39cd Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 00:43:38 -0700 Subject: [PATCH 0500/1056] txscript/engine: Use optimized IsPushOnlyScript --- txscript/engine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/engine.go b/txscript/engine.go index 06f454d372..f0a9485164 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -950,7 +950,7 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags // the flag to verify signature scripts are push only is set // above, so avoid checking again. alreadyChecked := vm.hasFlag(ScriptVerifySigPushOnly) - if !alreadyChecked && !isPushOnly(vm.scripts[0]) { + if !alreadyChecked && !IsPushOnlyScript(scriptSig) { return nil, scriptError(ErrNotPushOnly, "pay to script hash is not push only") } From 1be3450efb84a7eda89fe1b2040f570e4809a9ae Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 00:49:23 -0700 Subject: [PATCH 0501/1056] txscript/engine: Use optimized isScriptHashScript --- txscript/engine.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/engine.go b/txscript/engine.go index f0a9485164..703baef79b 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -944,7 +944,7 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags vm.scriptIdx++ } - if vm.hasFlag(ScriptBip16) && isScriptHash(vm.scripts[1]) { + if vm.hasFlag(ScriptBip16) && isScriptHashScript(scriptPubKey) { // Only accept input scripts that push data for P2SH. // Notice that the push only checks have already been done when // the flag to verify signature scripts are push only is set From 98dd6a900f3a1f997ffab68651e49f2772b25d5e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 00:50:54 -0700 Subject: [PATCH 0502/1056] txscript/engine: Check ps2h push before parsing script This moves the check for non push-only pay-to-script-hash signature scripts before the script parsing logic when creating a new engine instance to avoid the extra overhead in the error case. --- txscript/engine.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 703baef79b..576adc7188 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -918,6 +918,21 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags "signature script is not push only") } + // The signature script must only contain data pushes for PS2H which is + // determined based on the form of the public key script. + if vm.hasFlag(ScriptBip16) && isScriptHashScript(scriptPubKey) { + // Only accept input scripts that push data for P2SH. + // Notice that the push only checks have already been done when + // the flag to verify signature scripts are push only is set + // above, so avoid checking again. + alreadyChecked := vm.hasFlag(ScriptVerifySigPushOnly) + if !alreadyChecked && !IsPushOnlyScript(scriptSig) { + return nil, scriptError(ErrNotPushOnly, + "pay to script hash is not push only") + } + vm.bip16 = true + } + // The engine stores the scripts in parsed form using a slice. This // allows multiple scripts to be executed in sequence. For example, // with a pay-to-script-hash transaction, there will be ultimately be @@ -943,19 +958,6 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags if len(scripts[0]) == 0 { vm.scriptIdx++ } - - if vm.hasFlag(ScriptBip16) && isScriptHashScript(scriptPubKey) { - // Only accept input scripts that push data for P2SH. - // Notice that the push only checks have already been done when - // the flag to verify signature scripts are push only is set - // above, so avoid checking again. - alreadyChecked := vm.hasFlag(ScriptVerifySigPushOnly) - if !alreadyChecked && !IsPushOnlyScript(scriptSig) { - return nil, scriptError(ErrNotPushOnly, - "pay to script hash is not push only") - } - vm.bip16 = true - } if vm.hasFlag(ScriptVerifyMinimalData) { vm.dstack.verifyMinimalData = true vm.astack.verifyMinimalData = true From 8316a06a0ee4f90512d232ce4ccd00f072ff4e0c Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:19 -0500 Subject: [PATCH 0503/1056] txscript: Add benchmark for GetSigOpCount. --- txscript/bench_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index c8f7d0f790..7d0b90c4ad 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -341,3 +341,18 @@ func BenchmarkIsUnspendable(b *testing.B) { _ = IsUnspendable(script) } } + +// BenchmarkGetSigOpCount benchmarks how long it takes to count the signature +// operations of a very large script. +func BenchmarkGetSigOpCount(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = GetSigOpCount(script) + } +} From 4d5c0b25295855676463942e487635a5cdc45a15 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:20 -0500 Subject: [PATCH 0504/1056] txscript: Optimize GetSigOpCount. This converts the GetSigOpCount function to make use of the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. A new function named countSigOpsV0 which accepts the raw script is introduced to perform the bulk of the work so it can be reused for precise signature operation counting as well in a later commit. It retains the same semantics in terms of counting the number of signature operations either up to the first parse error or the end of the script in the case it parses successfully as required by consensus. Finally, this also deprecates the getSigOpCount function that requires opcodes in favor of the new function and modifies the comment on GetSigOpCount to explicitly call out the script version semantics. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkGetSigOpCount-8 61051 677 -98.89% benchmark old allocs new allocs delta BenchmarkGetSigOpCount-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkGetSigOpCount-8 311299 0 -100.00% --- txscript/script.go | 66 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index e933167d4c..32654f788d 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -741,6 +741,8 @@ func asSmallInt(op byte) int { // signature operations in the script provided by pops. If precise mode is // requested then we attempt to count the number of operations for a multisig // op. Otherwise we use the maximum. +// +// DEPRECATED. Use countSigOpsV0 instead. func getSigOpCount(pops []parsedOpcode, precise bool) int { nSigs := 0 for i, pop := range pops { @@ -771,15 +773,71 @@ func getSigOpCount(pops []parsedOpcode, precise bool) int { return nSigs } +// countSigOpsV0 returns the number of signature operations in the provided +// script up to the point of the first parse failure or the entire script when +// there are no parse failures. The precise flag attempts to accurately count +// the number of operations for a multisig operation versus using the maximum +// allowed. +// +// WARNING: This function always treats the passed script as version 0. Great +// care must be taken if introducing a new script version because it is used in +// consensus which, unfortunately as of the time of this writing, does not check +// script versions before counting their signature operations which means nodes +// on existing rules will count new version scripts as if they were version 0. +func countSigOpsV0(script []byte, precise bool) int { + const scriptVersion = 0 + + numSigOps := 0 + tokenizer := MakeScriptTokenizer(scriptVersion, script) + prevOp := byte(OP_INVALIDOPCODE) + for tokenizer.Next() { + switch tokenizer.Opcode() { + case OP_CHECKSIG, OP_CHECKSIGVERIFY: + numSigOps++ + + case OP_CHECKMULTISIG, OP_CHECKMULTISIGVERIFY: + // Note that OP_0 is treated as the max number of sigops here in + // precise mode despite it being a valid small integer in order to + // highly discourage multisigs with zero pubkeys. + // + // Also, even though this is referred to as "precise" counting, it's + // not really precise at all due to the small int opcodes only + // covering 1 through 16 pubkeys, which means this will count any + // more than that value (e.g. 17, 18 19) as the maximum number of + // allowed pubkeys. This is, unfortunately, now part of + // the Bitcion consensus rules, due to historical + // reasons. This could be made more correct with a new + // script version, however, ideally all multisignaure + // operations in new script versions should move to + // aggregated schemes such as Schnorr instead. + if precise && prevOp >= OP_1 && prevOp <= OP_16 { + numSigOps += asSmallInt(prevOp) + } else { + numSigOps += MaxPubKeysPerMultiSig + } + + default: + // Not a sigop. + } + + prevOp = tokenizer.Opcode() + } + + return numSigOps +} + // GetSigOpCount provides a quick count of the number of signature operations // in a script. a CHECKSIG operations counts for 1, and a CHECK_MULTISIG for 20. // If the script fails to parse, then the count up to the point of failure is // returned. +// +// WARNING: This function always treats the passed script as version 0. Great +// care must be taken if introducing a new script version because it is used in +// consensus which, unfortunately as of the time of this writing, does not check +// script versions before counting their signature operations which means nodes +// on existing rules will count new version scripts as if they were version 0. func GetSigOpCount(script []byte) int { - // Don't check error since parseScript returns the parsed-up-to-error - // list of pops. - pops, _ := parseScript(script) - return getSigOpCount(pops, false) + return countSigOpsV0(script, false) } // finalOpcodeData returns the data associated with the final opcode in the From cc802d14079debe347b699bb69c913069e679c6a Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:30 -0500 Subject: [PATCH 0505/1056] txscript: Add benchmark for GetPreciseSigOpCount. --- txscript/bench_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 7d0b90c4ad..817eb98f04 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -356,3 +356,29 @@ func BenchmarkGetSigOpCount(b *testing.B) { _ = GetSigOpCount(script) } } + +// BenchmarkGetPreciseSigOpCount benchmarks how long it takes to count the +// signature operations of a very large script using the more precise counting +// method. +func BenchmarkGetPreciseSigOpCount(b *testing.B) { + redeemScript, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + // Create a fake pay-to-script-hash to pass the necessary checks and create + // the signature script accordingly by pushing the generated "redeem" script + // as the final data push so the benchmark will cover the p2sh path. + scriptHash := "0x0000000000000000000000000000000000000001" + pkScript := mustParseShortForm("HASH160 DATA_20 " + scriptHash + " EQUAL") + sigScript, err := NewScriptBuilder().AddFullData(redeemScript).Script() + if err != nil { + b.Fatalf("failed to create signature script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = GetPreciseSigOpCount(sigScript, pkScript, true) + } +} From a4a21c0b087b9e73ec33def05d4a8d06671eea16 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:31 -0500 Subject: [PATCH 0506/1056] txscript: Optimize GetPreciseSigOpCount. This converts the GetPreciseSigOpCount function to use a combination of raw script analysis and the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. In particular it uses the recently converted isScriptHashScript, IsPushOnlyScript, and countSigOpsV0 functions along with the recently added finalOpcodeData functions. It also modifies the comment to explicitly call out the script version semantics. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkGetPreciseSigOpCount-8 130223 742 -99.43% benchmark old allocs new allocs delta BenchmarkGetPreciseSigOpCount-8 3 0 -100.00% benchmark old bytes new bytes delta BenchmarkGetPreciseSigOpCount-8 623367 0 -100.00% --- txscript/script.go | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 32654f788d..aee1aaacad 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -864,44 +864,44 @@ func finalOpcodeData(scriptVersion uint16, script []byte) []byte { // Pay-To-Script-Hash script in order to find the precise number of signature // operations in the transaction. If the script fails to parse, then the count // up to the point of failure is returned. -func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, bip16 bool) int { - // Don't check error since parseScript returns the parsed-up-to-error - // list of pops. - pops, _ := parseScript(scriptPubKey) - - // Treat non P2SH transactions as normal. - if !(bip16 && isScriptHash(pops)) { - return getSigOpCount(pops, true) - } +// +// WARNING: This function always treats the passed script as version 0. Great +// care must be taken if introducing a new script version because it is used in +// consensus which, unfortunately as of the time of this writing, does not check +// script versions before counting their signature operations which means nodes +// on existing rules will count new version scripts as if they were version 0. +// +// The third parameter is DEPRECATED and is unused. +func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, _ bool) int { + const scriptVersion = 0 - // The public key script is a pay-to-script-hash, so parse the signature - // script to get the final item. Scripts that fail to fully parse count - // as 0 signature operations. - sigPops, err := parseScript(scriptSig) - if err != nil { - return 0 + // Treat non P2SH transactions as normal. Note that signature operation + // counting includes all operations up to the first parse failure. + if !isScriptHashScript(scriptPubKey) { + return countSigOpsV0(scriptPubKey, true) } // The signature script must only push data to the stack for P2SH to be // a valid pair, so the signature operation count is 0 when that is not // the case. - if !isPushOnly(sigPops) || len(sigPops) == 0 { + if len(scriptSig) == 0 || !IsPushOnlyScript(scriptSig) { return 0 } // The P2SH script is the last item the signature script pushes to the // stack. When the script is empty, there are no signature operations. - shScript := sigPops[len(sigPops)-1].data - if len(shScript) == 0 { + // + // Notice that signature scripts that fail to fully parse count as 0 + // signature operations unlike public key and redeem scripts. + redeemScript := finalOpcodeData(scriptVersion, scriptSig) + if len(redeemScript) == 0 { return 0 } - // Parse the P2SH script and don't check the error since parseScript - // returns the parsed-up-to-error list of pops and the consensus rules - // dictate signature operations are counted up to the first parse - // failure. - shPops, _ := parseScript(shScript) - return getSigOpCount(shPops, true) + // Return the more precise sigops count for the redeem script. Note that + // signature operation counting includes all operations up to the first + // parse failure. + return countSigOpsV0(redeemScript, true) } // GetWitnessSigOpCount returns the number of signature operations generated by From 26d63c61dce4be4721d27506203cd00a5dbd5e4a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 12:58:03 -0800 Subject: [PATCH 0507/1056] txscript: add GetWitnessSigOpCountBenchmarks --- txscript/bench_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 817eb98f04..52965dca93 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -382,3 +382,44 @@ func BenchmarkGetPreciseSigOpCount(b *testing.B) { _ = GetPreciseSigOpCount(sigScript, pkScript, true) } } + +// BenchmarkGetWitnessSigOpCount benchmarks how long it takes to count the +// witness signature operations of a very large script. +func BenchmarkGetWitnessSigOpCountP2WKH(b *testing.B) { + pkScript := mustParseShortForm("OP_0 DATA_20 0x0000000000000000000000000000000000000000") + redeemScript, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + witness := wire.TxWitness{ + redeemScript, + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = GetWitnessSigOpCount(nil, pkScript, witness) + } +} + +// BenchmarkGetWitnessSigOpCount benchmarks how long it takes to count the +// witness signature operations of a very large script. +func BenchmarkGetWitnessSigOpCountNested(b *testing.B) { + pkScript := mustParseShortForm("HASH160 DATA_20 0x0000000000000000000000000000000000000000 OP_EQUAL") + sigScript := mustParseShortForm("DATA_22 0x001600000000000000000000000000000000000000000000") + redeemScript, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + witness := wire.TxWitness{ + redeemScript, + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = GetWitnessSigOpCount(sigScript, pkScript, witness) + } +} From 77863f5649cbd55e58e2c3ebdd8587de9edcaef7 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 14:14:53 -0800 Subject: [PATCH 0508/1056] txscript: Optimize GetWitnessSigOpCount This converts the GetWitnessSigOpCount function to use a combination of raw script analysis and the new tokenizer instead of the far less efficeint parseScript, thereby significantly optimizing the funciton. In particular, it use the recently added countSigOpsv0 in precise mode to avoid calling paseScript. --- txscript/script.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index aee1aaacad..b69c915afc 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -955,8 +955,7 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int { len(witness) > 0: witnessScript := witness[len(witness)-1] - pops, _ := parseScript(witnessScript) - return getSigOpCount(pops, true) + return countSigOpsV0(witnessScript, true) } } From 69d560c03cea944cf48114732304e2285b7cbbb5 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:32 -0500 Subject: [PATCH 0509/1056] txscript: Add benchmark for GetScriptClass. --- txscript/bench_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 52965dca93..aba3d1239e 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -423,3 +423,18 @@ func BenchmarkGetWitnessSigOpCountNested(b *testing.B) { _ = GetWitnessSigOpCount(sigScript, pkScript, witness) } } + +// BenchmarkGetScriptClass benchmarks how long it takes GetScriptClass to +// analyze a very large script. +func BenchmarkGetScriptClass(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _ = GetScriptClass(script) + } +} From 9b06388f7696fe6e1a4398c2bac6e7277a916067 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:33 -0500 Subject: [PATCH 0510/1056] txscript: Make typeOfScript accept raw script. This converts the typeOfScript function to accept a script version and raw script instead of an array of internal parsed opcodes in order to make it more flexible for raw script analysis. Also, this adds a comment to CalcScriptInfo to call out the specific version semantics and deprecates the function since nothing currently uses it, and the relevant information can now be obtained by callers more directly through the use of the new script tokenizer. All other callers are updated accordingly. --- txscript/standard.go | 46 ++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 9825f61bea..54c043181b 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -498,7 +498,19 @@ func isNullDataScript(scriptVersion uint16, script []byte) bool { // scriptType returns the type of the script being inspected from the known // standard types. -func typeOfScript(pops []parsedOpcode) ScriptClass { +// +// NOTE: All scripts that are not version 0 are currently considered non +// standard. +func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { + if scriptVersion != 0 { + return NonStandardTy + } + + pops, err := parseScript(script) + if err != nil { + return NonStandardTy + } + if isPubkey(pops) { return PubKeyTy } else if isPubkeyHash(pops) { @@ -521,11 +533,8 @@ func typeOfScript(pops []parsedOpcode) ScriptClass { // // NonStandardTy will be returned when the script does not parse. func GetScriptClass(script []byte) ScriptClass { - pops, err := parseScript(script) - if err != nil { - return NonStandardTy - } - return typeOfScript(pops) + const scriptVersion = 0 + return typeOfScript(scriptVersion, script) } // NewScriptClass returns the ScriptClass corresponding to the string name @@ -608,9 +617,17 @@ type ScriptInfo struct { // pair. It will error if the pair is in someway invalid such that they can not // be analysed, i.e. if they do not parse or the pkScript is not a push-only // script +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +// +// DEPRECATED. This will be removed in the next major version bump. func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, bip16, segwit bool) (*ScriptInfo, error) { + const scriptVersion = 0 + sigPops, err := parseScript(sigScript) if err != nil { return nil, err @@ -621,9 +638,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, return nil, err } - // Push only sigScript makes little sense. si := new(ScriptInfo) - si.PkScriptClass = typeOfScript(pkPops) + si.PkScriptClass = typeOfScript(scriptVersion, pkScript) // Can't have a signature script that doesn't just push data. if !isPushOnly(sigPops) { @@ -644,7 +660,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, return nil, err } - shInputs := expectedInputs(shPops, typeOfScript(shPops)) + redeemClass := typeOfScript(scriptVersion, script) + shInputs := expectedInputs(shPops, redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -671,7 +688,9 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, // Extract the pushed witness program from the sigScript so we // can determine the number of expected inputs. pkPops, _ := parseScript(sigScript[1:]) - shInputs := expectedInputs(pkPops, typeOfScript(pkPops)) + + redeemClass := typeOfScript(scriptVersion, sigScript[1:]) + shInputs := expectedInputs(pkPops, redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -691,7 +710,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, witnessScript := witness[len(witness)-1] pops, _ := parseScript(witnessScript) - shInputs := expectedInputs(pops, typeOfScript(pops)) + redeemClass := typeOfScript(scriptVersion, witnessScript) + shInputs := expectedInputs(pops, redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -888,7 +908,9 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return NonStandardTy, nil, 0, err } - scriptClass := typeOfScript(pops) + const scriptVersion = 0 + scriptClass := typeOfScript(scriptVersion, pkScript) + switch scriptClass { case PubKeyHashTy: // A pay-to-pubkey-hash script is of the form: From 3b86e0a0e2df9f20caa68c1dc6fcd67f0b9aa524 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:34 -0500 Subject: [PATCH 0511/1056] txscript: Optimize typeOfScript pay-to-script-hash. This begins the process of converting the typeOfScript function to use a combination of raw script analysis and the new tokenizer instead of the far less efficient parsed opcodes with the intent of significantly optimizing the function. In order to ease the review process, each script type will be converted in a separate commit and the typeOfScript function will be updated such that the script is only parsed as a fallback for the cases that are not already converted to more efficient raw script variants. In particular, for this commit, since the ability to detect pay-to-script-hash via raw script analysis is now available, the function is simply updated to make use of it. --- txscript/standard.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 54c043181b..fb3bb9821c 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -506,6 +506,11 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return NonStandardTy } + switch { + case isScriptHashScript(script): + return ScriptHashTy + } + pops, err := parseScript(script) if err != nil { return NonStandardTy @@ -517,8 +522,6 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return PubKeyHashTy } else if isWitnessPubKeyHash(pops) { return WitnessV0PubKeyHashTy - } else if isScriptHash(pops) { - return ScriptHashTy } else if isWitnessScriptHash(pops) { return WitnessV0ScriptHashTy } else if isMultiSig(pops) { From 671b5fefeff4cf07ae1805106c68b90fba291f79 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:35 -0500 Subject: [PATCH 0512/1056] txscript: Remove unused isScriptHash function. --- txscript/script.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index b69c915afc..ca6520c8be 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -54,17 +54,6 @@ func isSmallInt(op byte) bool { return op == OP_0 || (op >= OP_1 && op <= OP_16) } -// isScriptHash returns true if the script passed is a pay-to-script-hash -// transaction, false otherwise. -// -// DEPRECATED. Use isScriptHashScript or extractScriptHash instead. -func isScriptHash(pops []parsedOpcode) bool { - return len(pops) == 3 && - pops[0].opcode.value == OP_HASH160 && - pops[1].opcode.value == OP_DATA_20 && - pops[2].opcode.value == OP_EQUAL -} - // IsPayToPubKey returns true if the script is in the standard pay-to-pubkey // (P2PK) format, false otherwise. func IsPayToPubKey(script []byte) bool { From 71bf51e82c57b0d4a68ed3f6d35d94d3e7928d9d Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:36 -0500 Subject: [PATCH 0513/1056] txscript: Optimize typeOfScript multisig. This continues the process of converting the typeOfScript function to use a combination of raw script analysis and the new tokenizer instead of the far less efficient parsed opcodes. In particular, for this commit, since the ability to detect multisig scripts via the new tokenizer is now available, the function is simply updated to make use of it. --- txscript/standard.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index fb3bb9821c..dcd75214d3 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -509,6 +509,8 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { switch { case isScriptHashScript(script): return ScriptHashTy + case isMultisigScript(scriptVersion, script): + return MultiSigTy } pops, err := parseScript(script) @@ -524,8 +526,6 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return WitnessV0PubKeyHashTy } else if isWitnessScriptHash(pops) { return WitnessV0ScriptHashTy - } else if isMultiSig(pops) { - return MultiSigTy } else if isNullData(pops) { return NullDataTy } From 6e86f0d09bc57573312a9b63044dea64992ff480 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:37 -0500 Subject: [PATCH 0514/1056] txscript: Remove unused isMultiSig function. --- txscript/standard.go | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index dcd75214d3..2722bc4156 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -214,42 +214,6 @@ func isPubkeyHash(pops []parsedOpcode) bool { } -// isMultiSig returns true if the passed script is a multisig transaction, false -// otherwise. -// -// DEPECATED. Use isMultisigScript or extractMultisigScriptDetails instead. -func isMultiSig(pops []parsedOpcode) bool { - // The absolute minimum is 1 pubkey: - // OP_0/OP_1-16 OP_1 OP_CHECKMULTISIG - l := len(pops) - if l < 4 { - return false - } - if !isSmallInt(pops[0].opcode.value) { - return false - } - if !isSmallInt(pops[l-2].opcode.value) { - return false - } - if pops[l-1].opcode.value != OP_CHECKMULTISIG { - return false - } - - // Verify the number of pubkeys specified matches the actual number - // of pubkeys provided. - if l-2-1 != asSmallInt(pops[l-2].opcode.value) { - return false - } - - for _, pop := range pops[1 : l-2] { - // Valid pubkeys are either 33 or 65 bytes. - if len(pop.data) != 33 && len(pop.data) != 65 { - return false - } - } - return true -} - // multiSigDetails houses details extracted from a standard multisig script. type multiSigDetails struct { requiredSigs int From 8b64adc234cfbfd68394898f2eeea0199fdefdb6 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 14:07:19 -0800 Subject: [PATCH 0515/1056] txscript: Optimze typeOfScript pay-to-pubkey This continues the process of converting the typeOfScript function to use a combination of raw script analysis and the new tokenizer instead of the face less efficient parsed opcodes, with the intent of significantly optimizing the function. In particular, it converts the detection of pay-to-pubkey scripts to use raw script analysis. --- txscript/standard.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 2722bc4156..52a3747838 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -471,6 +471,8 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { } switch { + case isPubKeyScript(script): + return PubKeyTy case isScriptHashScript(script): return ScriptHashTy case isMultisigScript(scriptVersion, script): @@ -482,9 +484,7 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return NonStandardTy } - if isPubkey(pops) { - return PubKeyTy - } else if isPubkeyHash(pops) { + if isPubkeyHash(pops) { return PubKeyHashTy } else if isWitnessPubKeyHash(pops) { return WitnessV0PubKeyHashTy From 1133ea0bb3c95654e827a8ab31531c6163046f4a Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:40 -0500 Subject: [PATCH 0516/1056] txscript: Remove unused isPubkey function. --- txscript/standard.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 52a3747838..d2aa0e99eb 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -193,15 +193,6 @@ func isScriptHashScript(script []byte) bool { return extractScriptHash(script) != nil } -// isPubkey returns true if the script passed is a pay-to-pubkey transaction, -// false otherwise. -func isPubkey(pops []parsedOpcode) bool { - // Valid pubkeys are either 33 or 65 bytes. - return len(pops) == 2 && - (len(pops[0].data) == 33 || len(pops[0].data) == 65) && - pops[1].opcode.value == OP_CHECKSIG -} - // isPubkeyHash returns true if the script passed is a pay-to-pubkey-hash // transaction, false otherwise. func isPubkeyHash(pops []parsedOpcode) bool { From 13f646243d26d34ec46dfd7f9b40d5c8aaae5d59 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:45 -0500 Subject: [PATCH 0517/1056] txscript: Optimize typeOfScript pay-to-pubkey-hash. This continues the process of converting the typeOfScript function to use a combination of raw script analysis and the new tokenizer instead of the far less efficient parsed opcodes. In particular, it converts the detection of pay-to-pubkey-hash scripts to use raw script analysis. --- txscript/standard.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index d2aa0e99eb..08c6054e03 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -464,6 +464,8 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { switch { case isPubKeyScript(script): return PubKeyTy + case isPubKeyHashScript(script): + return PubKeyHashTy case isScriptHashScript(script): return ScriptHashTy case isMultisigScript(scriptVersion, script): @@ -475,9 +477,7 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return NonStandardTy } - if isPubkeyHash(pops) { - return PubKeyHashTy - } else if isWitnessPubKeyHash(pops) { + if isWitnessPubKeyHash(pops) { return WitnessV0PubKeyHashTy } else if isWitnessScriptHash(pops) { return WitnessV0ScriptHashTy From d02f97e04a5243e0343763b30c798863d63f577b Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:46 -0500 Subject: [PATCH 0518/1056] txscript: Remove unused isPubkeyHash function. --- txscript/standard.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 08c6054e03..ff382537f4 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -193,18 +193,6 @@ func isScriptHashScript(script []byte) bool { return extractScriptHash(script) != nil } -// isPubkeyHash returns true if the script passed is a pay-to-pubkey-hash -// transaction, false otherwise. -func isPubkeyHash(pops []parsedOpcode) bool { - return len(pops) == 5 && - pops[0].opcode.value == OP_DUP && - pops[1].opcode.value == OP_HASH160 && - pops[2].opcode.value == OP_DATA_20 && - pops[3].opcode.value == OP_EQUALVERIFY && - pops[4].opcode.value == OP_CHECKSIG - -} - // multiSigDetails houses details extracted from a standard multisig script. type multiSigDetails struct { requiredSigs int From d80863da921d21dcea851605ca8d74b621bb339e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 4 Feb 2021 15:15:45 -0800 Subject: [PATCH 0519/1056] txscript: Optimize typeOfScript for null data scripts This continues the process of converting the typeOfScript function to use a combination of raw script analysize and the tokenizer instead of parsed opcode, with the intent of significanty optimizing the function. In particular, it converts the detection of null data scripts to use raw script analysis. --- txscript/standard.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index ff382537f4..bae2b0c5d0 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -458,6 +458,8 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return ScriptHashTy case isMultisigScript(scriptVersion, script): return MultiSigTy + case isNullDataScript(scriptVersion, script): + return NullDataTy } pops, err := parseScript(script) @@ -469,9 +471,8 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return WitnessV0PubKeyHashTy } else if isWitnessScriptHash(pops) { return WitnessV0ScriptHashTy - } else if isNullData(pops) { - return NullDataTy } + return NonStandardTy } From 78046b3815ac525e86edde8f302b757369856f9e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:11:51 -0500 Subject: [PATCH 0520/1056] txscript: Remove unused isNullData function. --- txscript/standard.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index bae2b0c5d0..85b285826d 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -386,24 +386,6 @@ func isWitnessScriptHashScript(script []byte) bool { return extractWitnessScriptHash(script) != nil } -// isNullData returns true if the passed script is a null data transaction, -// false otherwise. -func isNullData(pops []parsedOpcode) bool { - // A nulldata transaction is either a single OP_RETURN or an - // OP_RETURN SMALLDATA (where SMALLDATA is a data push up to - // MaxDataCarrierSize bytes). - l := len(pops) - if l == 1 && pops[0].opcode.value == OP_RETURN { - return true - } - - return l == 2 && - pops[0].opcode.value == OP_RETURN && - (isSmallInt(pops[1].opcode.value) || pops[1].opcode.value <= - OP_PUSHDATA4) && - len(pops[1].data) <= MaxDataCarrierSize -} - // isNullDataScript returns whether or not the passed script is a standard // null data script. // From 847a262d78933c57e6062151ceef8aba17896264 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 01:46:52 -0700 Subject: [PATCH 0521/1056] txscript: Optimize typeOfScript witness-pubkey-hash This continues the process of converting the typeOfScript function to use a combination of raw script analysis and the new tokenizer instead of the far less efficient parsed opcodes. In particular, it converts the detection of witness pubkey hash scripts to use raw script analysis and the new tokenizer. The following is a before and after comparison of analyzing a large script: benchmark old ns/op new ns/op delta BenchmarkIsWitnessPubKeyHash-8 61688 62839 +1.87% benchmark old allocs new allocs delta BenchmarkIsWitnessPubKeyHash-8 1 1 +0.00% benchmark old bytes new bytes delta BenchmarkIsWitnessPubKeyHash-8 311299 311299 +0.00% --- txscript/standard.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 85b285826d..5d5c668794 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -355,6 +355,7 @@ func extractWitnessPubKeyHash(script []byte) []byte { return script[2:22] } + return nil } @@ -438,6 +439,8 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return PubKeyHashTy case isScriptHashScript(script): return ScriptHashTy + case isWitnessPubKeyHashScript(script): + return WitnessV0PubKeyHashTy case isMultisigScript(scriptVersion, script): return MultiSigTy case isNullDataScript(scriptVersion, script): @@ -449,9 +452,7 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return NonStandardTy } - if isWitnessPubKeyHash(pops) { - return WitnessV0PubKeyHashTy - } else if isWitnessScriptHash(pops) { + if isWitnessScriptHash(pops) { return WitnessV0ScriptHashTy } From 1a60e11da7ab917a6725ce10d37da7b7f8634ed5 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 02:04:01 -0700 Subject: [PATCH 0522/1056] txscript: Optimize typeOfScript for witness-script-hash This concludes the process of converting the typeOfScript function to use a combination of raw script analysis and the new tokenizer instead of the far less efficient parsed opcodes. In particular, it converts the detection of witness script hash scripts to use raw script analysis and the new tokenizer. With all of the limbs now useing optimized variants, the following is a before an after comparison of calling GetScriptClass on a large script: benchmark old ns/op new ns/op delta BenchmarkGetScriptClass-8 61515 15.3 -99.98% benchmark old allocs new allocs delta BenchmarkGetScriptClass-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkGetScriptClass-8 311299 0 -100.00% --- txscript/standard.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 5d5c668794..dd751cbe98 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -441,22 +441,15 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { return ScriptHashTy case isWitnessPubKeyHashScript(script): return WitnessV0PubKeyHashTy + case isWitnessScriptHashScript(script): + return WitnessV0ScriptHashTy case isMultisigScript(scriptVersion, script): return MultiSigTy case isNullDataScript(scriptVersion, script): return NullDataTy - } - - pops, err := parseScript(script) - if err != nil { + default: return NonStandardTy } - - if isWitnessScriptHash(pops) { - return WitnessV0ScriptHashTy - } - - return NonStandardTy } // GetScriptClass returns the class of the script passed. From 43846b1edf9f281a88b02e91b361ebdd30b692db Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 02:05:04 -0700 Subject: [PATCH 0523/1056] txscript: Remove unused isWitnessScriptHash --- txscript/script.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index ca6520c8be..0d041a8bf9 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -78,14 +78,6 @@ func IsPayToScriptHash(script []byte) bool { return isScriptHashScript(script) } -// isWitnessScriptHash returns true if the passed script is a -// pay-to-witness-script-hash transaction, false otherwise. -func isWitnessScriptHash(pops []parsedOpcode) bool { - return len(pops) == 2 && - pops[0].opcode.value == OP_0 && - pops[1].opcode.value == OP_DATA_32 -} - // IsPayToWitnessScriptHash returns true if the is in the standard // pay-to-witness-script-hash (P2WSH) format, false otherwise. func IsPayToWitnessScriptHash(script []byte) bool { From 705d24cab4bb7f9f0891736c4a983abd8d846146 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:09 -0500 Subject: [PATCH 0524/1056] txscript: Convert CalcScriptInfo. This converts CalcScriptInfo and dependent expectedInputs to make use of the new script tokenizer as well as several of the other recently added raw script analysis functions in order to remove the reliance on parsed opcodes as a step towards utlimately removing them altogether. It is worth noting that this has the side effect of significantly optimizing the function as well, however, since it is deprecated, no benchmarks are provided. --- txscript/standard.go | 72 +++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index dd751cbe98..fea6799f76 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -481,7 +481,11 @@ func NewScriptClass(name string) (*ScriptClass, error) { // then -1 is returned. We are an internal function and thus assume that class // is the real class of pops (and we can thus assume things that were determined // while finding out the type). -func expectedInputs(pops []parsedOpcode, class ScriptClass) int { +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func expectedInputs(script []byte, class ScriptClass) int { switch class { case PubKeyTy: return 1 @@ -508,7 +512,7 @@ func expectedInputs(pops []parsedOpcode, class ScriptClass) int { // the original bitcoind bug where OP_CHECKMULTISIG pops an // additional item from the stack, add an extra expected input // for the extra push that is required to compensate. - return asSmallInt(pops[0].opcode.value) + 1 + return asSmallInt(script[0]) + 1 case NullDataTy: fallthrough @@ -549,52 +553,52 @@ type ScriptInfo struct { func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, bip16, segwit bool) (*ScriptInfo, error) { + // Count the number of opcodes in the signature script while also ensuring + // that successfully parses. Since there is a check below to ensure the + // script is push only, this equates to the number of inputs to the public + // key script. const scriptVersion = 0 - - sigPops, err := parseScript(sigScript) - if err != nil { + var numInputs int + tokenizer := MakeScriptTokenizer(scriptVersion, sigScript) + for tokenizer.Next() { + numInputs++ + } + if err := tokenizer.Err(); err != nil { return nil, err } - pkPops, err := parseScript(pkScript) - if err != nil { + if err := checkScriptParses(scriptVersion, pkScript); err != nil { return nil, err } - si := new(ScriptInfo) - si.PkScriptClass = typeOfScript(scriptVersion, pkScript) - // Can't have a signature script that doesn't just push data. - if !isPushOnly(sigPops) { + if !IsPushOnlyScript(sigScript) { return nil, scriptError(ErrNotPushOnly, "signature script is not push only") } - si.ExpectedInputs = expectedInputs(pkPops, si.PkScriptClass) + si := new(ScriptInfo) + si.PkScriptClass = typeOfScript(scriptVersion, pkScript) + + si.ExpectedInputs = expectedInputs(pkScript, si.PkScriptClass) switch { // Count sigops taking into account pay-to-script-hash. case si.PkScriptClass == ScriptHashTy && bip16 && !segwit: - // The pay-to-hash-script is the final data push of the - // signature script. - script := sigPops[len(sigPops)-1].data - shPops, err := parseScript(script) - if err != nil { - return nil, err - } - - redeemClass := typeOfScript(scriptVersion, script) - shInputs := expectedInputs(shPops, redeemClass) - if shInputs == -1 { + // The redeem script is the final data push of the signature script. + redeemScript := finalOpcodeData(scriptVersion, sigScript) + reedeemClass := typeOfScript(scriptVersion, redeemScript) + rsInputs := expectedInputs(redeemScript, reedeemClass) + if rsInputs == -1 { si.ExpectedInputs = -1 } else { - si.ExpectedInputs += shInputs + si.ExpectedInputs += rsInputs } - si.SigOps = getSigOpCount(shPops, true) + si.SigOps = countSigOpsV0(redeemScript, true) // All entries pushed to stack (or are OP_RESERVED and exec // will fail). - si.NumInputs = len(sigPops) + si.NumInputs = numInputs // If segwit is active, and this is a regular p2wkh output, then we'll // treat the script as a p2pkh output in essence. @@ -610,10 +614,8 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, // Extract the pushed witness program from the sigScript so we // can determine the number of expected inputs. - pkPops, _ := parseScript(sigScript[1:]) - redeemClass := typeOfScript(scriptVersion, sigScript[1:]) - shInputs := expectedInputs(pkPops, redeemClass) + shInputs := expectedInputs(sigScript[1:], redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -623,18 +625,14 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, si.SigOps = GetWitnessSigOpCount(sigScript, pkScript, witness) si.NumInputs = len(witness) - si.NumInputs += len(sigPops) + si.NumInputs += numInputs // If segwit is active, and this is a p2wsh output, then we'll need to // examine the witness script to generate accurate script info. case si.PkScriptClass == WitnessV0ScriptHashTy && segwit: - // The witness script is the final element of the witness - // stack. witnessScript := witness[len(witness)-1] - pops, _ := parseScript(witnessScript) - redeemClass := typeOfScript(scriptVersion, witnessScript) - shInputs := expectedInputs(pops, redeemClass) + shInputs := expectedInputs(witnessScript, redeemClass) if shInputs == -1 { si.ExpectedInputs = -1 } else { @@ -645,11 +643,11 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, si.NumInputs = len(witness) default: - si.SigOps = getSigOpCount(pkPops, true) + si.SigOps = countSigOpsV0(pkScript, true) // All entries pushed to stack (or are OP_RESERVED and exec // will fail). - si.NumInputs = len(sigPops) + si.NumInputs = numInputs } return si, nil From 6c212fd7ee9e0ab2fcd6287d0c5ed26c0b9cf043 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:10 -0500 Subject: [PATCH 0525/1056] txscript: Remove unused isPushOnly function. --- txscript/script.go | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 0d041a8bf9..7e0e3669d2 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -161,26 +161,6 @@ func ExtractWitnessProgramInfo(script []byte) (int, []byte, error) { return witnessVersion, witnessProgram, nil } -// isPushOnly returns true if the script only pushes data, false otherwise. -// -// DEPRECATED. Use IsPushOnlyScript instead. -func isPushOnly(pops []parsedOpcode) bool { - // NOTE: This function does NOT verify opcodes directly since it is - // internal and is only called with parsed opcodes for scripts that did - // not have any parse errors. Thus, consensus is properly maintained. - - for _, pop := range pops { - // All opcodes up to OP_16 are data push instructions. - // NOTE: This does consider OP_RESERVED to be a data push - // instruction, but execution of OP_RESERVED will fail anyways - // and matches the behavior required by consensus. - if pop.opcode.value > OP_16 { - return false - } - } - return true -} - // IsPushOnlyScript returns whether or not the passed script only pushes data // according to the consensus definition of pushing data. // @@ -901,11 +881,7 @@ func GetWitnessSigOpCount(sigScript, pkScript []byte, witness wire.TxWitness) in // Next, we'll check the sigScript to see if this is a nested p2sh // witness program. This is a case wherein the sigScript is actually a // datapush of a p2wsh witness program. - sigPops, err := parseScript(sigScript) - if err != nil { - return 0 - } - if IsPayToScriptHash(pkScript) && isPushOnly(sigPops) && + if IsPayToScriptHash(pkScript) && IsPushOnlyScript(sigScript) && IsWitnessProgram(sigScript[1:]) { return getWitnessSigOps(sigScript[1:], witness) } From 8c54905959569b573f019ffc8e4eeb624505a8d9 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:11 -0500 Subject: [PATCH 0526/1056] txscript: Remove unused getSigOpCount function. --- txscript/script.go | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 7e0e3669d2..10ff4315e0 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -698,42 +698,6 @@ func asSmallInt(op byte) int { return int(op - (OP_1 - 1)) } -// getSigOpCount is the implementation function for counting the number of -// signature operations in the script provided by pops. If precise mode is -// requested then we attempt to count the number of operations for a multisig -// op. Otherwise we use the maximum. -// -// DEPRECATED. Use countSigOpsV0 instead. -func getSigOpCount(pops []parsedOpcode, precise bool) int { - nSigs := 0 - for i, pop := range pops { - switch pop.opcode.value { - case OP_CHECKSIG: - fallthrough - case OP_CHECKSIGVERIFY: - nSigs++ - case OP_CHECKMULTISIG: - fallthrough - case OP_CHECKMULTISIGVERIFY: - // If we are being precise then look for familiar - // patterns for multisig, for now all we recognize is - // OP_1 - OP_16 to signify the number of pubkeys. - // Otherwise, we use the max of 20. - if precise && i > 0 && - pops[i-1].opcode.value >= OP_1 && - pops[i-1].opcode.value <= OP_16 { - nSigs += asSmallInt(pops[i-1].opcode.value) - } else { - nSigs += MaxPubKeysPerMultiSig - } - default: - // Not a sigop. - } - } - - return nSigs -} - // countSigOpsV0 returns the number of signature operations in the provided // script up to the point of the first parse failure or the entire script when // there are no parse failures. The precise flag attempts to accurately count From 7791f92f6f09390f310c918966178fe189c1632a Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:13 -0500 Subject: [PATCH 0527/1056] txscript: Optimize CalcMultiSigStats. This converts the CalcMultiSigStats function to make use of the new extractMultisigScriptDetails function instead of the far less efficient parseScript thereby significantly optimizing the function. The tests are also updated accordingly. The following is a before and after comparison of analyzing a standard multisig script: benchmark old ns/op new ns/op delta --------------------------------------------------------------- BenchmarkCalcMultiSigStats 972 79.5 -91.82% benchmark old allocs new allocs delta --------------------------------------------------------------- BenchmarkCalcMultiSigStats 1 0 -100.00% benchmark old bytes new bytes delta --------------------------------------------------------------- BenchmarkCalcMultiSigStats 2304 0 -100.00% --- txscript/standard.go | 26 ++++++++++---------------- txscript/standard_test.go | 8 ++------ 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index fea6799f76..3bb12b9aba 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -656,27 +656,21 @@ func CalcScriptInfo(sigScript, pkScript []byte, witness wire.TxWitness, // CalcMultiSigStats returns the number of public keys and signatures from // a multi-signature transaction script. The passed script MUST already be // known to be a multi-signature script. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func CalcMultiSigStats(script []byte) (int, int, error) { - pops, err := parseScript(script) - if err != nil { - return 0, 0, err - } - - // A multi-signature script is of the pattern: - // NUM_SIGS PUBKEY PUBKEY PUBKEY... NUM_PUBKEYS OP_CHECKMULTISIG - // Therefore the number of signatures is the oldest item on the stack - // and the number of pubkeys is the 2nd to last. Also, the absolute - // minimum for a multi-signature script is 1 pubkey, so at least 4 - // items must be on the stack per: - // OP_1 PUBKEY OP_1 OP_CHECKMULTISIG - if len(pops) < 4 { + // The public keys are not needed here, so pass false to avoid the extra + // allocation. + const scriptVersion = 0 + details := extractMultisigScriptDetails(scriptVersion, script, false) + if !details.valid { str := fmt.Sprintf("script %x is not a multisig script", script) return 0, 0, scriptError(ErrNotMultisigScript, str) } - numSigs := asSmallInt(pops[0].opcode.value) - numPubKeys := asSmallInt(pops[len(pops)-2].opcode.value) - return numPubKeys, numSigs, nil + return details.numPubKeys, details.requiredSigs, nil } // payToPubKeyHashScript creates a new script to pay a transaction diff --git a/txscript/standard_test.go b/txscript/standard_test.go index 37dd8f8a37..582d30eee4 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -832,7 +832,7 @@ func TestCalcMultiSigStats(t *testing.T) { name: "short script", script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" + "e03909a67962e0ea1f61d", - err: scriptError(ErrMalformedPush, ""), + err: scriptError(ErrNotMultisigScript, ""), }, { name: "stack underflow", @@ -843,11 +843,7 @@ func TestCalcMultiSigStats(t *testing.T) { }, { name: "multisig script", - script: "0 DATA_72 0x30450220106a3e4ef0b51b764a2887226" + - "2ffef55846514dacbdcbbdd652c849d395b4384022100" + - "e03ae554c3cbb40600d31dd46fc33f25e47bf8525b1fe" + - "07282e3b6ecb5f3bb2801 CODESEPARATOR 1 DATA_33 " + - "0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" + + script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da45329a0" + "0357b3a7886211ab414d55a 1 CHECKMULTISIG", err: nil, }, From c4f6302189c7c928a2e89212d3727a308512920d Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:18 -0500 Subject: [PATCH 0528/1056] txscript: Add benchmark for PushedData. --- txscript/bench_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index aba3d1239e..26b7c9feb8 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -438,3 +438,21 @@ func BenchmarkGetScriptClass(b *testing.B) { _ = GetScriptClass(script) } } + +// BenchmarkPushedData benchmarks how long it takes to extract the pushed data +// from a very large script. +func BenchmarkPushedData(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := PushedData(script) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + } +} From 0a4f228dd10296da4c06484577112bf0411e7fff Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:19 -0500 Subject: [PATCH 0529/1056] txscript: Optimize PushedData. This converts the PushedData function to make use of the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. Also, the comment is modified to explicitly call out the script version semantics. The following is a before and after comparison of extracting the data from a very large script: benchmark old ns/op new ns/op delta BenchmarkPushedData-8 64837 1790 -97.24% benchmark old allocs new allocs delta BenchmarkPushedData-8 7 6 -14.29% benchmark old bytes new bytes delta BenchmarkPushedData-8 312816 1520 -99.51% --- txscript/standard.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 3bb12b9aba..0607b305f3 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -791,20 +791,25 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er // PushedData returns an array of byte slices containing any pushed data found // in the passed script. This includes OP_0, but not OP_1 - OP_16. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func PushedData(script []byte) ([][]byte, error) { - pops, err := parseScript(script) - if err != nil { - return nil, err - } + const scriptVersion = 0 var data [][]byte - for _, pop := range pops { - if pop.data != nil { - data = append(data, pop.data) - } else if pop.opcode.value == OP_0 { + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + if tokenizer.Data() != nil { + data = append(data, tokenizer.Data()) + } else if tokenizer.Opcode() == OP_0 { data = append(data, nil) } } + if err := tokenizer.Err(); err != nil { + return nil, err + } return data, nil } From da9fdabbd5bae2c07aca03af811bfb33b05dd3d6 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:22 -0500 Subject: [PATCH 0530/1056] txscript: Make canonicalPush accept raw opcode. This renames the canonicalPush function to isCanonicalPush and converts it to accept an opcode as a byte and the associate data as a byte slice instead of the internal parse opcode data struct in order to make it more flexible for raw script analysis. It also updates all callers and tests accordingly. --- txscript/engine.go | 5 +++- txscript/script.go | 23 ++++++++------ txscript/script_test.go | 66 ++++++++++++++++++----------------------- txscript/standard.go | 4 +-- 4 files changed, 49 insertions(+), 49 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 576adc7188..ef7ad33e3c 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -875,6 +875,7 @@ func (vm *Engine) SetAltStack(data [][]byte) { // engine according to the description provided by each flag. func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags, sigCache *SigCache, hashCache *TxSigHashes, inputAmount int64) (*Engine, error) { + const scriptVersion = 0 // The provided transaction input index must refer to a valid input. if txIdx < 0 || txIdx >= len(tx.TxIn) { @@ -994,7 +995,9 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags // data push of the witness program, otherwise we // reintroduce malleability. sigPops := vm.scripts[0] - if len(sigPops) == 1 && canonicalPush(sigPops[0]) && + if len(sigPops) == 1 && + isCanonicalPush(sigPops[0].opcode.value, + sigPops[0].data) && IsWitnessProgram(sigPops[0].data) { witProgram = sigPops[0].data diff --git a/txscript/script.go b/txscript/script.go index 10ff4315e0..52bedf2699 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -128,7 +128,7 @@ func IsWitnessProgram(script []byte) bool { func isWitnessProgram(pops []parsedOpcode) bool { return len(pops) == 2 && isSmallInt(pops[0].opcode.value) && - canonicalPush(pops[1]) && + isCanonicalPush(pops[1].opcode.value, pops[1].data) && (len(pops[1].data) >= 2 && len(pops[1].data) <= 40) } @@ -305,13 +305,16 @@ func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { return retScript } -// canonicalPush returns true if the object is either not a push instruction -// or the push instruction contained wherein is matches the canonical form -// or using the smallest instruction to do the job. False otherwise. -func canonicalPush(pop parsedOpcode) bool { - opcode := pop.opcode.value - data := pop.data - dataLen := len(pop.data) +// isCanonicalPush returns true if the opcode is either not a push instruction +// or the data associated with the push instruction uses the smallest +// instruction to do the job. False otherwise. +// +// For example, it is possible to push a value of 1 to the stack as "OP_1", +// "OP_DATA_1 0x01", "OP_PUSHDATA1 0x01 0x01", and others, however, the first +// only takes a single byte, while the rest take more. Only the first is +// considered canonical. +func isCanonicalPush(opcode byte, data []byte) bool { + dataLen := len(data) if opcode > OP_16 { return true } @@ -336,7 +339,9 @@ func canonicalPush(pop parsedOpcode) bool { func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { retScript := make([]parsedOpcode, 0, len(pkscript)) for _, pop := range pkscript { - if !canonicalPush(pop) || !bytes.Contains(pop.data, data) { + if !isCanonicalPush(pop.opcode.value, pop.data) || + !bytes.Contains(pop.data, data) { + retScript = append(retScript, pop) } } diff --git a/txscript/script_test.go b/txscript/script_test.go index 665d9ef633..62c51e4181 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -3740,31 +3740,25 @@ func TestPushedData(t *testing.T) { } } -// TestHasCanonicalPush ensures the canonicalPush function works as expected. +// TestHasCanonicalPush ensures the isCanonicalPush function works as expected. func TestHasCanonicalPush(t *testing.T) { t.Parallel() + const scriptVersion = 0 for i := 0; i < 65535; i++ { script, err := NewScriptBuilder().AddInt64(int64(i)).Script() if err != nil { - t.Errorf("Script: test #%d unexpected error: %v\n", i, - err) + t.Errorf("Script: test #%d unexpected error: %v\n", i, err) continue } - if result := IsPushOnlyScript(script); !result { - t.Errorf("IsPushOnlyScript: test #%d failed: %x\n", i, - script) + if !IsPushOnlyScript(script) { + t.Errorf("IsPushOnlyScript: test #%d failed: %x\n", i, script) continue } - pops, err := parseScript(script) - if err != nil { - t.Errorf("parseScript: #%d failed: %v", i, err) - continue - } - for _, pop := range pops { - if result := canonicalPush(pop); !result { - t.Errorf("canonicalPush: test #%d failed: %x\n", - i, script) + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + if !isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) { + t.Errorf("isCanonicalPush: test #%d failed: %x\n", i, script) break } } @@ -3774,21 +3768,17 @@ func TestHasCanonicalPush(t *testing.T) { builder.AddData(bytes.Repeat([]byte{0x49}, i)) script, err := builder.Script() if err != nil { - t.Errorf("StandardPushesTests test #%d unexpected error: %v\n", i, err) - continue - } - if result := IsPushOnlyScript(script); !result { - t.Errorf("StandardPushesTests IsPushOnlyScript test #%d failed: %x\n", i, script) + t.Errorf("Script: test #%d unexpected error: %v\n", i, err) continue } - pops, err := parseScript(script) - if err != nil { - t.Errorf("StandardPushesTests #%d failed to TstParseScript: %v", i, err) + if !IsPushOnlyScript(script) { + t.Errorf("IsPushOnlyScript: test #%d failed: %x\n", i, script) continue } - for _, pop := range pops { - if result := canonicalPush(pop); !result { - t.Errorf("StandardPushesTests TstHasCanonicalPushes test #%d failed: %x\n", i, script) + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + if !isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) { + t.Errorf("isCanonicalPush: test #%d failed: %x\n", i, script) break } } @@ -4213,11 +4203,13 @@ func TestIsPayToWitnessPubKeyHash(t *testing.T) { } } -// TestHasCanonicalPushes ensures the canonicalPush function properly determines -// what is considered a canonical push for the purposes of removeOpcodeByData. +// TestHasCanonicalPushes ensures the isCanonicalPush function properly +// determines what is considered a canonical push for the purposes of +// removeOpcodeByData. func TestHasCanonicalPushes(t *testing.T) { t.Parallel() + const scriptVersion = 0 tests := []struct { name string script string @@ -4236,20 +4228,20 @@ func TestHasCanonicalPushes(t *testing.T) { }, } - for i, test := range tests { + for _, test := range tests { script := mustParseShortForm(test.script) - pops, err := parseScript(script) - if err != nil { + if err := checkScriptParses(scriptVersion, script); err != nil { if test.expected { - t.Errorf("TstParseScript #%d failed: %v", i, err) + t.Errorf("%q: script parse failed: %v", test.name, err) } continue } - for _, pop := range pops { - if canonicalPush(pop) != test.expected { - t.Errorf("canonicalPush: #%d (%s) wrong result"+ - "\ngot: %v\nwant: %v", i, test.name, - true, test.expected) + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + result := isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) + if result != test.expected { + t.Errorf("%q: isCanonicalPush wrong result\ngot: %v\nwant: %v", + test.name, result, test.expected) break } } diff --git a/txscript/standard.go b/txscript/standard.go index 0607b305f3..d97072f155 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -953,7 +953,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa } isAtomicSwap := pops[0].opcode.value == OP_IF && pops[1].opcode.value == OP_SIZE && - canonicalPush(pops[2]) && + isCanonicalPush(pops[2].opcode.value, pops[2].data) && pops[3].opcode.value == OP_EQUALVERIFY && pops[4].opcode.value == OP_SHA256 && pops[5].opcode.value == OP_DATA_32 && @@ -962,7 +962,7 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa pops[8].opcode.value == OP_HASH160 && pops[9].opcode.value == OP_DATA_20 && pops[10].opcode.value == OP_ELSE && - canonicalPush(pops[11]) && + isCanonicalPush(pops[11].opcode.value, pops[11].data) && pops[12].opcode.value == OP_CHECKLOCKTIMEVERIFY && pops[13].opcode.value == OP_DROP && pops[14].opcode.value == OP_DUP && From 81b80328bd21ae8845a8ca3cb0760898b7119e43 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:24 -0500 Subject: [PATCH 0531/1056] txscript: Add ExtractAtomicSwapDataPushes benches. --- txscript/bench_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 26b7c9feb8..456db25d52 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -456,3 +456,44 @@ func BenchmarkPushedData(b *testing.B) { } } } + +// BenchmarkExtractAtomicSwapDataPushesLarge benchmarks how long it takes +// ExtractAtomicSwapDataPushes to analyze a very large script. +func BenchmarkExtractAtomicSwapDataPushesLarge(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + const scriptVersion = 0 + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := ExtractAtomicSwapDataPushes(scriptVersion, script) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + } +} + +// BenchmarkExtractAtomicSwapDataPushesLarge benchmarks how long it takes +// ExtractAtomicSwapDataPushes to analyze a standard atomic swap script. +func BenchmarkExtractAtomicSwapDataPushes(b *testing.B) { + secret := "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" + recipient := "0000000000000000000000000000000000000001" + refund := "0000000000000000000000000000000000000002" + script := mustParseShortForm(fmt.Sprintf("IF SIZE 32 EQUALVERIFY SHA256 "+ + "DATA_32 0x%s EQUALVERIFY DUP HASH160 DATA_20 0x%s ELSE 300000 "+ + "CHECKLOCKTIMEVERIFY DROP DUP HASH160 DATA_20 0x%s ENDIF "+ + "EQUALVERIFY CHECKSIG", secret, recipient, refund)) + + const scriptVersion = 0 + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, err := ExtractAtomicSwapDataPushes(scriptVersion, script) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + } +} From 6ec9b73a53a1f7480a5c251e639b754d95f25c27 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 03:05:55 -0700 Subject: [PATCH 0532/1056] txscript/scriptnum: add maxscriptnum and maxcltvlength --- txscript/scriptnum.go | 20 ++++-- txscript/scriptnum_test.go | 126 ++++++++++++++++++------------------- txscript/stack.go | 4 +- 3 files changed, 81 insertions(+), 69 deletions(-) diff --git a/txscript/scriptnum.go b/txscript/scriptnum.go index a89d5f39cc..81f2636121 100644 --- a/txscript/scriptnum.go +++ b/txscript/scriptnum.go @@ -12,9 +12,21 @@ const ( maxInt32 = 1<<31 - 1 minInt32 = -1 << 31 - // defaultScriptNumLen is the default number of bytes - // data being interpreted as an integer may be. - defaultScriptNumLen = 4 + // maxScriptNumLen is the maximum number of bytes data being interpreted + // as an integer may be for the majority of op codes. + maxScriptNumLen = 4 + + // cltvMaxScriptNumLen is the maximum number of bytes data being interpreted + // as an integer may be for by-time and by-height locks as interpreted by + // CHECKLOCKTIMEVERIFY. + // + // The value comes from the fact that the current transaction locktime + // is a uint32 resulting in a maximum locktime of 2^32-1 (the year + // 2106). However, scriptNums are signed and therefore a standard + // 4-byte scriptNum would only support up to a maximum of 2^31-1 (the + // year 2038). Thus, a 5-byte scriptNum is needed since it will support + // up to 2^39-1 which allows dates beyond the current locktime limit. + cltvMaxScriptNumLen = 5 ) // scriptNum represents a numeric value used in the scripting engine with @@ -178,7 +190,7 @@ func (n scriptNum) Int32() int32 { // before an ErrStackNumberTooBig is returned. This effectively limits the // range of allowed values. // WARNING: Great care should be taken if passing a value larger than -// defaultScriptNumLen, which could lead to addition and multiplication +// maxScriptNumLen, which could lead to addition and multiplication // overflows. // // See the Bytes function documentation for example encodings. diff --git a/txscript/scriptnum_test.go b/txscript/scriptnum_test.go index e32862b736..668f912f6f 100644 --- a/txscript/scriptnum_test.go +++ b/txscript/scriptnum_test.go @@ -104,35 +104,35 @@ func TestMakeScriptNum(t *testing.T) { err error }{ // Minimal encoding must reject negative 0. - {hexToBytes("80"), 0, defaultScriptNumLen, true, errMinimalData}, + {hexToBytes("80"), 0, maxScriptNumLen, true, errMinimalData}, // Minimally encoded valid values with minimal encoding flag. // Should not error and return expected integral number. - {nil, 0, defaultScriptNumLen, true, nil}, - {hexToBytes("01"), 1, defaultScriptNumLen, true, nil}, - {hexToBytes("81"), -1, defaultScriptNumLen, true, nil}, - {hexToBytes("7f"), 127, defaultScriptNumLen, true, nil}, - {hexToBytes("ff"), -127, defaultScriptNumLen, true, nil}, - {hexToBytes("8000"), 128, defaultScriptNumLen, true, nil}, - {hexToBytes("8080"), -128, defaultScriptNumLen, true, nil}, - {hexToBytes("8100"), 129, defaultScriptNumLen, true, nil}, - {hexToBytes("8180"), -129, defaultScriptNumLen, true, nil}, - {hexToBytes("0001"), 256, defaultScriptNumLen, true, nil}, - {hexToBytes("0081"), -256, defaultScriptNumLen, true, nil}, - {hexToBytes("ff7f"), 32767, defaultScriptNumLen, true, nil}, - {hexToBytes("ffff"), -32767, defaultScriptNumLen, true, nil}, - {hexToBytes("008000"), 32768, defaultScriptNumLen, true, nil}, - {hexToBytes("008080"), -32768, defaultScriptNumLen, true, nil}, - {hexToBytes("ffff00"), 65535, defaultScriptNumLen, true, nil}, - {hexToBytes("ffff80"), -65535, defaultScriptNumLen, true, nil}, - {hexToBytes("000008"), 524288, defaultScriptNumLen, true, nil}, - {hexToBytes("000088"), -524288, defaultScriptNumLen, true, nil}, - {hexToBytes("000070"), 7340032, defaultScriptNumLen, true, nil}, - {hexToBytes("0000f0"), -7340032, defaultScriptNumLen, true, nil}, - {hexToBytes("00008000"), 8388608, defaultScriptNumLen, true, nil}, - {hexToBytes("00008080"), -8388608, defaultScriptNumLen, true, nil}, - {hexToBytes("ffffff7f"), 2147483647, defaultScriptNumLen, true, nil}, - {hexToBytes("ffffffff"), -2147483647, defaultScriptNumLen, true, nil}, + {nil, 0, maxScriptNumLen, true, nil}, + {hexToBytes("01"), 1, maxScriptNumLen, true, nil}, + {hexToBytes("81"), -1, maxScriptNumLen, true, nil}, + {hexToBytes("7f"), 127, maxScriptNumLen, true, nil}, + {hexToBytes("ff"), -127, maxScriptNumLen, true, nil}, + {hexToBytes("8000"), 128, maxScriptNumLen, true, nil}, + {hexToBytes("8080"), -128, maxScriptNumLen, true, nil}, + {hexToBytes("8100"), 129, maxScriptNumLen, true, nil}, + {hexToBytes("8180"), -129, maxScriptNumLen, true, nil}, + {hexToBytes("0001"), 256, maxScriptNumLen, true, nil}, + {hexToBytes("0081"), -256, maxScriptNumLen, true, nil}, + {hexToBytes("ff7f"), 32767, maxScriptNumLen, true, nil}, + {hexToBytes("ffff"), -32767, maxScriptNumLen, true, nil}, + {hexToBytes("008000"), 32768, maxScriptNumLen, true, nil}, + {hexToBytes("008080"), -32768, maxScriptNumLen, true, nil}, + {hexToBytes("ffff00"), 65535, maxScriptNumLen, true, nil}, + {hexToBytes("ffff80"), -65535, maxScriptNumLen, true, nil}, + {hexToBytes("000008"), 524288, maxScriptNumLen, true, nil}, + {hexToBytes("000088"), -524288, maxScriptNumLen, true, nil}, + {hexToBytes("000070"), 7340032, maxScriptNumLen, true, nil}, + {hexToBytes("0000f0"), -7340032, maxScriptNumLen, true, nil}, + {hexToBytes("00008000"), 8388608, maxScriptNumLen, true, nil}, + {hexToBytes("00008080"), -8388608, maxScriptNumLen, true, nil}, + {hexToBytes("ffffff7f"), 2147483647, maxScriptNumLen, true, nil}, + {hexToBytes("ffffffff"), -2147483647, maxScriptNumLen, true, nil}, {hexToBytes("ffffffff7f"), 549755813887, 5, true, nil}, {hexToBytes("ffffffffff"), -549755813887, 5, true, nil}, {hexToBytes("ffffffffffffff7f"), 9223372036854775807, 8, true, nil}, @@ -145,50 +145,50 @@ func TestMakeScriptNum(t *testing.T) { // Minimally encoded values that are out of range for data that // is interpreted as script numbers with the minimal encoding // flag set. Should error and return 0. - {hexToBytes("0000008000"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("0000008080"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("0000009000"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("0000009080"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("0000000001"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("0000000081"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffffffffff00"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffffffffff80"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffffffffff7f"), 0, defaultScriptNumLen, true, errNumTooBig}, - {hexToBytes("ffffffffffffffff"), 0, defaultScriptNumLen, true, errNumTooBig}, + {hexToBytes("0000008000"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("0000008080"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("0000009000"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("0000009080"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffff00"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffff80"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("0000000001"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("0000000081"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffffffff00"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffffffff80"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffffffffff00"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffffffffff80"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffffffffff7f"), 0, maxScriptNumLen, true, errNumTooBig}, + {hexToBytes("ffffffffffffffff"), 0, maxScriptNumLen, true, errNumTooBig}, // Non-minimally encoded, but otherwise valid values with // minimal encoding flag. Should error and return 0. - {hexToBytes("00"), 0, defaultScriptNumLen, true, errMinimalData}, // 0 - {hexToBytes("0100"), 0, defaultScriptNumLen, true, errMinimalData}, // 1 - {hexToBytes("7f00"), 0, defaultScriptNumLen, true, errMinimalData}, // 127 - {hexToBytes("800000"), 0, defaultScriptNumLen, true, errMinimalData}, // 128 - {hexToBytes("810000"), 0, defaultScriptNumLen, true, errMinimalData}, // 129 - {hexToBytes("000100"), 0, defaultScriptNumLen, true, errMinimalData}, // 256 - {hexToBytes("ff7f00"), 0, defaultScriptNumLen, true, errMinimalData}, // 32767 - {hexToBytes("00800000"), 0, defaultScriptNumLen, true, errMinimalData}, // 32768 - {hexToBytes("ffff0000"), 0, defaultScriptNumLen, true, errMinimalData}, // 65535 - {hexToBytes("00000800"), 0, defaultScriptNumLen, true, errMinimalData}, // 524288 - {hexToBytes("00007000"), 0, defaultScriptNumLen, true, errMinimalData}, // 7340032 - {hexToBytes("0009000100"), 0, 5, true, errMinimalData}, // 16779520 + {hexToBytes("00"), 0, maxScriptNumLen, true, errMinimalData}, // 0 + {hexToBytes("0100"), 0, maxScriptNumLen, true, errMinimalData}, // 1 + {hexToBytes("7f00"), 0, maxScriptNumLen, true, errMinimalData}, // 127 + {hexToBytes("800000"), 0, maxScriptNumLen, true, errMinimalData}, // 128 + {hexToBytes("810000"), 0, maxScriptNumLen, true, errMinimalData}, // 129 + {hexToBytes("000100"), 0, maxScriptNumLen, true, errMinimalData}, // 256 + {hexToBytes("ff7f00"), 0, maxScriptNumLen, true, errMinimalData}, // 32767 + {hexToBytes("00800000"), 0, maxScriptNumLen, true, errMinimalData}, // 32768 + {hexToBytes("ffff0000"), 0, maxScriptNumLen, true, errMinimalData}, // 65535 + {hexToBytes("00000800"), 0, maxScriptNumLen, true, errMinimalData}, // 524288 + {hexToBytes("00007000"), 0, maxScriptNumLen, true, errMinimalData}, // 7340032 + {hexToBytes("0009000100"), 0, 5, true, errMinimalData}, // 16779520 // Non-minimally encoded, but otherwise valid values without // minimal encoding flag. Should not error and return expected // integral number. - {hexToBytes("00"), 0, defaultScriptNumLen, false, nil}, - {hexToBytes("0100"), 1, defaultScriptNumLen, false, nil}, - {hexToBytes("7f00"), 127, defaultScriptNumLen, false, nil}, - {hexToBytes("800000"), 128, defaultScriptNumLen, false, nil}, - {hexToBytes("810000"), 129, defaultScriptNumLen, false, nil}, - {hexToBytes("000100"), 256, defaultScriptNumLen, false, nil}, - {hexToBytes("ff7f00"), 32767, defaultScriptNumLen, false, nil}, - {hexToBytes("00800000"), 32768, defaultScriptNumLen, false, nil}, - {hexToBytes("ffff0000"), 65535, defaultScriptNumLen, false, nil}, - {hexToBytes("00000800"), 524288, defaultScriptNumLen, false, nil}, - {hexToBytes("00007000"), 7340032, defaultScriptNumLen, false, nil}, + {hexToBytes("00"), 0, maxScriptNumLen, false, nil}, + {hexToBytes("0100"), 1, maxScriptNumLen, false, nil}, + {hexToBytes("7f00"), 127, maxScriptNumLen, false, nil}, + {hexToBytes("800000"), 128, maxScriptNumLen, false, nil}, + {hexToBytes("810000"), 129, maxScriptNumLen, false, nil}, + {hexToBytes("000100"), 256, maxScriptNumLen, false, nil}, + {hexToBytes("ff7f00"), 32767, maxScriptNumLen, false, nil}, + {hexToBytes("00800000"), 32768, maxScriptNumLen, false, nil}, + {hexToBytes("ffff0000"), 65535, maxScriptNumLen, false, nil}, + {hexToBytes("00000800"), 524288, maxScriptNumLen, false, nil}, + {hexToBytes("00007000"), 7340032, maxScriptNumLen, false, nil}, {hexToBytes("0009000100"), 16779520, 5, false, nil}, } diff --git a/txscript/stack.go b/txscript/stack.go index eb1d8cfdfe..923047d93e 100644 --- a/txscript/stack.go +++ b/txscript/stack.go @@ -86,7 +86,7 @@ func (s *stack) PopInt() (scriptNum, error) { return 0, err } - return makeScriptNum(so, s.verifyMinimalData, defaultScriptNumLen) + return makeScriptNum(so, s.verifyMinimalData, maxScriptNumLen) } // PopBool pops the value off the top of the stack, converts it into a bool, and @@ -123,7 +123,7 @@ func (s *stack) PeekInt(idx int32) (scriptNum, error) { return 0, err } - return makeScriptNum(so, s.verifyMinimalData, defaultScriptNumLen) + return makeScriptNum(so, s.verifyMinimalData, maxScriptNumLen) } // PeekBool returns the Nth item on the stack as a bool without removing it. From 367a75a3f410da2eda19b19b06e9b2eba24511b8 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:25 -0500 Subject: [PATCH 0533/1056] txscript: Optimize ExtractAtomicSwapDataPushes. This converts the ExtractAtomicSwapDataPushes function to make use of the new tokenizer instead of the far less efficient parseScript thereby significantly optimizing the function. The new implementation is designed such that it should be fairly easy to move the function into the atomic swap tools where it more naturally belongs now that the tokenizer makes it possible to analyze scripts outside of the txscript module. Consequently, this also deprecates the function. The following is a before and after comparison of attempting to extract from both a typical atomic swap script and a very large non-atomic swap script: benchmark old ns/op new ns/op delta BenchmarkExtractAtomicSwapDataPushesLarge-8 61332 44.4 -99.93% BenchmarkExtractAtomicSwapDataPushes-8 990 260 -73.74% benchmark old allocs new allocs delta BenchmarkExtractAtomicSwapDataPushesLarge-8 1 0 -100.00% BenchmarkExtractAtomicSwapDataPushes-8 2 1 -50.00% benchmark old bytes new bytes delta BenchmarkExtractAtomicSwapDataPushesLarge-8 311299 0 -100.00% BenchmarkExtractAtomicSwapDataPushes-8 3168 96 -96.97% --- txscript/standard.go | 140 +++++++++++++++++++++++++++---------------- 1 file changed, 89 insertions(+), 51 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index d97072f155..041516e2d5 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -942,64 +942,102 @@ type AtomicSwapDataPushes struct { // // This function is only defined in the txscript package due to API limitations // which prevent callers using txscript to parse nonstandard scripts. +// +// DEPRECATED. This will be removed in the next major version bump. The error +// should also likely be removed if the code is reimplemented by any callers +// since any errors result in a nil result anyway. func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDataPushes, error) { - pops, err := parseScript(pkScript) - if err != nil { - return nil, err + // An atomic swap is of the form: + // IF + // SIZE EQUALVERIFY SHA256 <32-byte secret> EQUALVERIFY DUP + // HASH160 <20-byte recipient hash> + // ELSE + // CHECKLOCKTIMEVERIFY DROP DUP HASH160 <20-byte refund hash> + // ENDIF + // EQUALVERIFY CHECKSIG + type templateMatch struct { + expectCanonicalInt bool + maxIntBytes int + opcode byte + extractedInt int64 + extractedData []byte } - - if len(pops) != 20 { - return nil, nil - } - isAtomicSwap := pops[0].opcode.value == OP_IF && - pops[1].opcode.value == OP_SIZE && - isCanonicalPush(pops[2].opcode.value, pops[2].data) && - pops[3].opcode.value == OP_EQUALVERIFY && - pops[4].opcode.value == OP_SHA256 && - pops[5].opcode.value == OP_DATA_32 && - pops[6].opcode.value == OP_EQUALVERIFY && - pops[7].opcode.value == OP_DUP && - pops[8].opcode.value == OP_HASH160 && - pops[9].opcode.value == OP_DATA_20 && - pops[10].opcode.value == OP_ELSE && - isCanonicalPush(pops[11].opcode.value, pops[11].data) && - pops[12].opcode.value == OP_CHECKLOCKTIMEVERIFY && - pops[13].opcode.value == OP_DROP && - pops[14].opcode.value == OP_DUP && - pops[15].opcode.value == OP_HASH160 && - pops[16].opcode.value == OP_DATA_20 && - pops[17].opcode.value == OP_ENDIF && - pops[18].opcode.value == OP_EQUALVERIFY && - pops[19].opcode.value == OP_CHECKSIG - if !isAtomicSwap { - return nil, nil + var template = [20]templateMatch{ + {opcode: OP_IF}, + {opcode: OP_SIZE}, + {expectCanonicalInt: true, maxIntBytes: maxScriptNumLen}, + {opcode: OP_EQUALVERIFY}, + {opcode: OP_SHA256}, + {opcode: OP_DATA_32}, + {opcode: OP_EQUALVERIFY}, + {opcode: OP_DUP}, + {opcode: OP_HASH160}, + {opcode: OP_DATA_20}, + {opcode: OP_ELSE}, + {expectCanonicalInt: true, maxIntBytes: cltvMaxScriptNumLen}, + {opcode: OP_CHECKLOCKTIMEVERIFY}, + {opcode: OP_DROP}, + {opcode: OP_DUP}, + {opcode: OP_HASH160}, + {opcode: OP_DATA_20}, + {opcode: OP_ENDIF}, + {opcode: OP_EQUALVERIFY}, + {opcode: OP_CHECKSIG}, } - pushes := new(AtomicSwapDataPushes) - copy(pushes.SecretHash[:], pops[5].data) - copy(pushes.RecipientHash160[:], pops[9].data) - copy(pushes.RefundHash160[:], pops[16].data) - if pops[2].data != nil { - locktime, err := makeScriptNum(pops[2].data, true, 5) - if err != nil { + var templateOffset int + tokenizer := MakeScriptTokenizer(version, pkScript) + for tokenizer.Next() { + // Not an atomic swap script if it has more opcodes than expected in the + // template. + if templateOffset >= len(template) { return nil, nil } - pushes.SecretSize = int64(locktime) - } else if op := pops[2].opcode; isSmallInt(op.value) { - pushes.SecretSize = int64(asSmallInt(op.value)) - } else { - return nil, nil - } - if pops[11].data != nil { - locktime, err := makeScriptNum(pops[11].data, true, 5) - if err != nil { - return nil, nil + + op := tokenizer.Opcode() + data := tokenizer.Data() + tplEntry := &template[templateOffset] + if tplEntry.expectCanonicalInt { + switch { + case data != nil: + val, err := makeScriptNum(data, true, tplEntry.maxIntBytes) + if err != nil { + return nil, err + } + tplEntry.extractedInt = int64(val) + + case isSmallInt(op): + tplEntry.extractedInt = int64(asSmallInt(op)) + + // Not an atomic swap script if the opcode does not push an int. + default: + return nil, nil + } + } else { + if op != tplEntry.opcode { + return nil, nil + } + + tplEntry.extractedData = data } - pushes.LockTime = int64(locktime) - } else if op := pops[11].opcode; isSmallInt(op.value) { - pushes.LockTime = int64(asSmallInt(op.value)) - } else { + + templateOffset++ + } + if err := tokenizer.Err(); err != nil { + return nil, err + } + if !tokenizer.Done() || templateOffset != len(template) { return nil, nil } - return pushes, nil + + // At this point, the script appears to be an atomic swap, so populate and + // return the extacted data. + pushes := AtomicSwapDataPushes{ + SecretSize: template[2].extractedInt, + LockTime: template[11].extractedInt, + } + copy(pushes.SecretHash[:], template[5].extractedData) + copy(pushes.RecipientHash160[:], template[9].extractedData) + copy(pushes.RefundHash160[:], template[16].extractedData) + return &pushes, nil } From 33ee3e2f53476fa96b80093aa3cbbaaea7091682 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:26 -0500 Subject: [PATCH 0534/1056] txscript: Add ExtractPkScriptAddrs benchmarks. --- txscript/bench_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 456db25d52..cac2920280 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -10,6 +10,7 @@ import ( "io/ioutil" "testing" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" ) @@ -497,3 +498,40 @@ func BenchmarkExtractAtomicSwapDataPushes(b *testing.B) { } } } + +// BenchmarkExtractPkScriptAddrsLarge benchmarks how long it takes to analyze +// and potentially extract addresses from a very large non-standard script. +func BenchmarkExtractPkScriptAddrsLarge(b *testing.B) { + script, err := genComplexScript() + if err != nil { + b.Fatalf("failed to create benchmark script: %v", err) + } + + params := &chaincfg.MainNetParams + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, _, _, err := ExtractPkScriptAddrs(script, params) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + } +} + +// BenchmarkExtractPkScriptAddrs benchmarks how long it takes to analyze and +// potentially extract addresses from a typical script. +func BenchmarkExtractPkScriptAddrs(b *testing.B) { + script := mustParseShortForm("OP_DUP HASH160 " + + "DATA_20 0x0102030405060708090a0b0c0d0e0f1011121314 " + + "EQUAL") + + params := &chaincfg.MainNetParams + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + _, _, _, err := ExtractPkScriptAddrs(script, params) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + } +} From 055be988c06449007774923b6ff7a8adf8bab945 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:27 -0500 Subject: [PATCH 0535/1056] txscript: Optimize ExtractPkScriptAddrs scripthash. This begins the process of converting the ExtractPkScriptAddrs function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In order to ease the review process, the detection of each script type will be converted in a separate commit such that the script is only parsed as a fallback for the cases that are not already converted to more efficient variants. In particular, this converts the detection for pay-to-script-hash scripts. --- txscript/standard.go | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 041516e2d5..f55cbf9849 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -813,11 +813,36 @@ func PushedData(script []byte) ([][]byte, error) { return data, nil } +// scriptHashToAddrs is a convenience function to attempt to convert the passed +// hash to a pay-to-script-hash address housed within an address slice. It is +// used to consolidate common code. +func scriptHashToAddrs(hash []byte, params *chaincfg.Params) []btcutil.Address { + // Skip the hash if it's invalid for some reason. + var addrs []btcutil.Address + addr, err := btcutil.NewAddressScriptHashFromHash(hash, params) + if err == nil { + addrs = append(addrs, addr) + } + return addrs +} + // ExtractPkScriptAddrs returns the type of script, addresses and required // signatures associated with the passed PkScript. Note that it only works for // 'standard' transaction script types. Any data such as public keys which are // invalid are omitted from the results. func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (ScriptClass, []btcutil.Address, int, error) { + + // Avoid parsing the script for the cases that already have the able to + // work with raw scripts. + + // Check for pay-to-script-hash. + if hash := extractScriptHash(pkScript); hash != nil { + return ScriptHashTy, scriptHashToAddrs(hash, chainParams), 1, nil + } + + // Fall back to slow path. Ultimately these are intended to be replaced by + // faster variants based on the unparsed raw scripts. + var addrs []btcutil.Address var requiredSigs int @@ -867,18 +892,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script addrs = append(addrs, addr) } - case ScriptHashTy: - // A pay-to-script-hash script is of the form: - // OP_HASH160 OP_EQUAL - // Therefore the script hash is the 2nd item on the stack. - // Skip the script hash if it's invalid for some reason. - requiredSigs = 1 - addr, err := btcutil.NewAddressScriptHashFromHash(pops[1].data, - chainParams) - if err == nil { - addrs = append(addrs, addr) - } - case WitnessV0ScriptHashTy: // A pay-to-witness-script-hash script is of the form: // OP_0 <32-byte hash> From 16bd6633b64f2fa8b91c580900136545e4cbf350 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:28 -0500 Subject: [PATCH 0536/1056] txscript: Optimize ExtractPkScriptAddrs pubkeyhash. This continues the process of converting the ExtractPkScriptAddrs function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In particular, this converts the detection for pay-to-pubkey-hash scripts. --- txscript/standard.go | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index f55cbf9849..af50660635 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -813,6 +813,19 @@ func PushedData(script []byte) ([][]byte, error) { return data, nil } +// pubKeyHashToAddrs is a convenience function to attempt to convert the +// passed hash to a pay-to-pubkey-hash address housed within an address +// slice. It is used to consolidate common code. +func pubKeyHashToAddrs(hash []byte, params *chaincfg.Params) []btcutil.Address { + // Skip the pubkey hash if it's invalid for some reason. + var addrs []btcutil.Address + addr, err := btcutil.NewAddressPubKeyHash(hash, params) + if err == nil { + addrs = append(addrs, addr) + } + return addrs +} + // scriptHashToAddrs is a convenience function to attempt to convert the passed // hash to a pay-to-script-hash address housed within an address slice. It is // used to consolidate common code. @@ -835,6 +848,11 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script // Avoid parsing the script for the cases that already have the able to // work with raw scripts. + // Check for pay-to-pubkey-hash script. + if hash := extractPubKeyHash(pkScript); hash != nil { + return PubKeyHashTy, pubKeyHashToAddrs(hash, chainParams), 1, nil + } + // Check for pay-to-script-hash. if hash := extractScriptHash(pkScript); hash != nil { return ScriptHashTy, scriptHashToAddrs(hash, chainParams), 1, nil @@ -857,18 +875,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script scriptClass := typeOfScript(scriptVersion, pkScript) switch scriptClass { - case PubKeyHashTy: - // A pay-to-pubkey-hash script is of the form: - // OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG - // Therefore the pubkey hash is the 3rd item on the stack. - // Skip the pubkey hash if it's invalid for some reason. - requiredSigs = 1 - addr, err := btcutil.NewAddressPubKeyHash(pops[2].data, - chainParams) - if err == nil { - addrs = append(addrs, addr) - } - case WitnessV0PubKeyHashTy: // A pay-to-witness-pubkey-hash script is of thw form: // OP_0 <20-byte hash> From 0e810b4ef4a06de24f804f71bbbe12b96edd71e9 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:31 -0500 Subject: [PATCH 0537/1056] txscript: Optimize ExtractPkScriptAddrs pubkey. This continues the process of converting the ExtractPkScriptAddrs function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In particular, this converts the detection for pay-to-pubkey scripts. --- txscript/standard.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index af50660635..6377598c93 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -858,6 +858,16 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return ScriptHashTy, scriptHashToAddrs(hash, chainParams), 1, nil } + // Check for pay-to-pubkey script. + if data := extractPubKey(pkScript); data != nil { + var addrs []btcutil.Address + addr, err := btcutil.NewAddressPubKey(data, chainParams) + if err == nil { + addrs = append(addrs, addr) + } + return PubKeyTy, addrs, 1, nil + } + // Fall back to slow path. Ultimately these are intended to be replaced by // faster variants based on the unparsed raw scripts. @@ -887,17 +897,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script addrs = append(addrs, addr) } - case PubKeyTy: - // A pay-to-pubkey script is of the form: - // OP_CHECKSIG - // Therefore the pubkey is the first item on the stack. - // Skip the pubkey if it's invalid for some reason. - requiredSigs = 1 - addr, err := btcutil.NewAddressPubKey(pops[0].data, chainParams) - if err == nil { - addrs = append(addrs, addr) - } - case WitnessV0ScriptHashTy: // A pay-to-witness-script-hash script is of the form: // OP_0 <32-byte hash> From 0bc18254d403ea3d1a77626fa86dc0091c83be15 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:33 -0500 Subject: [PATCH 0538/1056] txscript: Optimize ExtractPkScriptAddrs multisig. This continues the process of converting the ExtractPkScriptAddrs function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In particular, this converts the detection for multisig scripts. Also, since the remaining slow path cases are all recursive calls, the parsed opcodes are no longer used, so parsing is removed. --- txscript/standard.go | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 6377598c93..b187ac012e 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -868,11 +868,27 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return PubKeyTy, addrs, 1, nil } + // Check for multi-signature script. + const scriptVersion = 0 + details := extractMultisigScriptDetails(scriptVersion, pkScript, true) + if details.valid { + // Convert the public keys while skipping any that are invalid. + addrs := make([]btcutil.Address, 0, len(details.pubKeys)) + for _, pubkey := range details.pubKeys { + addr, err := btcutil.NewAddressPubKey(pubkey, chainParams) + if err == nil { + addrs = append(addrs, addr) + } + } + return MultiSigTy, addrs, details.requiredSigs, nil + } + // Fall back to slow path. Ultimately these are intended to be replaced by // faster variants based on the unparsed raw scripts. var addrs []btcutil.Address var requiredSigs int + var err error // No valid addresses or required signatures if the script doesn't // parse. @@ -881,7 +897,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return NonStandardTy, nil, 0, err } - const scriptVersion = 0 scriptClass := typeOfScript(scriptVersion, pkScript) switch scriptClass { @@ -909,25 +924,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script addrs = append(addrs, addr) } - case MultiSigTy: - // A multi-signature script is of the form: - // ... OP_CHECKMULTISIG - // Therefore the number of required signatures is the 1st item - // on the stack and the number of public keys is the 2nd to last - // item on the stack. - requiredSigs = asSmallInt(pops[0].opcode.value) - numPubKeys := asSmallInt(pops[len(pops)-2].opcode.value) - - // Extract the public keys while skipping any that are invalid. - addrs = make([]btcutil.Address, 0, numPubKeys) - for i := 0; i < numPubKeys; i++ { - addr, err := btcutil.NewAddressPubKey(pops[i+1].data, - chainParams) - if err == nil { - addrs = append(addrs, addr) - } - } - case NullDataTy: // Null data transactions have no addresses or required // signatures. From 507a4dcc005dea7bf3c1742498cd68de6977a9de Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:38 -0500 Subject: [PATCH 0539/1056] txscript: Optimize ExtractPkScriptAddrs nulldata. This continues the process of converting the ExtractPkScriptAddrs function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In particular, this converts the detection for nulldata scripts, removes the slow path fallback code since it is the final case, and modifies the comment to call out the script version semantics. The following is a before and after comparison of analyzing both a typical standard script and a very large non-standard script: benchmark old ns/op new ns/op delta ----------------------------------------------------------------------- BenchmarkExtractPkScriptAddrsLarge 132400 44.4 -99.97% BenchmarkExtractPkScriptAddrs 1265 231 -81.74% benchmark old allocs new allocs delta ----------------------------------------------------------------------- BenchmarkExtractPkScriptAddrsLarge 1 0 -100.00% BenchmarkExtractPkScriptAddrs 5 2 -60.00% benchmark old bytes new bytes delta ----------------------------------------------------------------------- BenchmarkExtractPkScriptAddrsLarge 466944 0 -100.00% BenchmarkExtractPkScriptAddrs 1600 48 -97.00% --- txscript/standard.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index b187ac012e..89c2196663 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -843,11 +843,12 @@ func scriptHashToAddrs(hash []byte, params *chaincfg.Params) []btcutil.Address { // signatures associated with the passed PkScript. Note that it only works for // 'standard' transaction script types. Any data such as public keys which are // invalid are omitted from the results. +// +// NOTE: This function only attempts to identify version 0 scripts. The return +// value will indicate a nonstandard script type for other script versions along +// with an invalid script version error. func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (ScriptClass, []btcutil.Address, int, error) { - // Avoid parsing the script for the cases that already have the able to - // work with raw scripts. - // Check for pay-to-pubkey-hash script. if hash := extractPubKeyHash(pkScript); hash != nil { return PubKeyHashTy, pubKeyHashToAddrs(hash, chainParams), 1, nil @@ -883,6 +884,12 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return MultiSigTy, addrs, details.requiredSigs, nil } + // Check for null data script. + if isNullDataScript(scriptVersion, pkScript) { + // Null data transactions have no addresses or required signatures. + return NullDataTy, nil, 0, nil + } + // Fall back to slow path. Ultimately these are intended to be replaced by // faster variants based on the unparsed raw scripts. @@ -924,15 +931,13 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script addrs = append(addrs, addr) } - case NullDataTy: - // Null data transactions have no addresses or required - // signatures. - case NonStandardTy: // Don't attempt to extract addresses or required signatures for // nonstandard transactions. } + // Don't attempt to extract addresses or required signatures for nonstandard + // transactions. return scriptClass, addrs, requiredSigs, nil } From ae7fffbe52af902984f38c55e558a2334ef1fe69 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:18:51 -0700 Subject: [PATCH 0540/1056] txscript: Optimize ExtractPkScriptAddrs witness pubkey hash This continues the process of converting the ExtractPkScriptAddrs function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In particular, this converts the extraction for witness-pubkey-hash scripts. --- txscript/standard.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 89c2196663..c0178250c9 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -890,6 +890,15 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return NullDataTy, nil, 0, nil } + if hash := extractWitnessPubKeyHash(pkScript); hash != nil { + var addrs []btcutil.Address + addr, err := btcutil.NewAddressWitnessPubKeyHash(hash, chainParams) + if err == nil { + addrs = append(addrs, addr) + } + return WitnessV0PubKeyHashTy, addrs, 1, nil + } + // Fall back to slow path. Ultimately these are intended to be replaced by // faster variants based on the unparsed raw scripts. @@ -907,18 +916,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script scriptClass := typeOfScript(scriptVersion, pkScript) switch scriptClass { - case WitnessV0PubKeyHashTy: - // A pay-to-witness-pubkey-hash script is of thw form: - // OP_0 <20-byte hash> - // Therefore, the pubkey hash is the second item on the stack. - // Skip the pubkey hash if it's invalid for some reason. - requiredSigs = 1 - addr, err := btcutil.NewAddressWitnessPubKeyHash(pops[1].data, - chainParams) - if err == nil { - addrs = append(addrs, addr) - } - case WitnessV0ScriptHashTy: // A pay-to-witness-script-hash script is of the form: // OP_0 <32-byte hash> From a83152214ccf3fd4972a011e065e37a982343778 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:22:52 -0700 Subject: [PATCH 0541/1056] txscript: Optimize ExtractPkScriptAddrs witness script hash This continues the process of converting the ExtractPkScriptAddrs function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In particular, this converts the extract of witness-pay-to-script-hash scripts. --- txscript/standard.go | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index c0178250c9..d9f8a9a3e3 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -899,35 +899,24 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return WitnessV0PubKeyHashTy, addrs, 1, nil } + if hash := extractWitnessScriptHash(pkScript); hash != nil { + var addrs []btcutil.Address + addr, err := btcutil.NewAddressWitnessScriptHash(hash, chainParams) + if err == nil { + addrs = append(addrs, addr) + } + return WitnessV0ScriptHashTy, addrs, 1, nil + } + // Fall back to slow path. Ultimately these are intended to be replaced by // faster variants based on the unparsed raw scripts. var addrs []btcutil.Address var requiredSigs int - var err error - - // No valid addresses or required signatures if the script doesn't - // parse. - pops, err := parseScript(pkScript) - if err != nil { - return NonStandardTy, nil, 0, err - } scriptClass := typeOfScript(scriptVersion, pkScript) switch scriptClass { - case WitnessV0ScriptHashTy: - // A pay-to-witness-script-hash script is of the form: - // OP_0 <32-byte hash> - // Therefore, the script hash is the second item on the stack. - // Skip the script hash if it's invalid for some reason. - requiredSigs = 1 - addr, err := btcutil.NewAddressWitnessScriptHash(pops[1].data, - chainParams) - if err == nil { - addrs = append(addrs, addr) - } - case NonStandardTy: // Don't attempt to extract addresses or required signatures for // nonstandard transactions. From 1034a66b357483b61c368232a4df9fc40ddc45ad Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:32:37 -0700 Subject: [PATCH 0542/1056] txscript: Optimize ExtractPkScriptAddr assume non-standard if no success This completes the process of converting the ExtractPkScriptAddr function to use the optimized extraction functions recently introduced as part of the typeOfScript conversion. In particular, this cleans up the final remaining case for non-standard transactions. The method now returns NonStandardTy direclty if no other branch was taken. The following is a before and after comparison of attempting to extract pkscript addrs from a very large, non-standard script. benchmark old ns/op new ns/op delta BenchmarkExtractPkScriptAddrsLarge-8 60713 17.0 -99.97% BenchmarkExtractPkScriptAddrs-8 289 17.0 -94.12% benchmark old allocs new allocs delta BenchmarkExtractPkScriptAddrsLarge-8 1 0 -100.00% BenchmarkExtractPkScriptAddrs-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkExtractPkScriptAddrsLarge-8 311299 0 -100.00% BenchmarkExtractPkScriptAddrs-8 768 0 -100.00% --- txscript/standard.go | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index d9f8a9a3e3..326d14d828 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -908,23 +908,8 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return WitnessV0ScriptHashTy, addrs, 1, nil } - // Fall back to slow path. Ultimately these are intended to be replaced by - // faster variants based on the unparsed raw scripts. - - var addrs []btcutil.Address - var requiredSigs int - - scriptClass := typeOfScript(scriptVersion, pkScript) - - switch scriptClass { - case NonStandardTy: - // Don't attempt to extract addresses or required signatures for - // nonstandard transactions. - } - - // Don't attempt to extract addresses or required signatures for nonstandard - // transactions. - return scriptClass, addrs, requiredSigs, nil + // If none of the above passed, then the address must be non-standard. + return NonStandardTy, nil, 0, nil } // AtomicSwapDataPushes houses the data pushes found in atomic swap contracts. From 6fb1c82fe5d14b4b2d7bba13c2d727051107aa25 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 18:58:28 -0700 Subject: [PATCH 0543/1056] txscript: Optimize IsWitnessProgram --- txscript/script.go | 17 +++-------------- txscript/standard.go | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 52bedf2699..1ca953dea4 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -103,20 +103,7 @@ func isWitnessPubKeyHash(pops []parsedOpcode) bool { // witness program must be a small integer (from 0-16), followed by 2-40 bytes // of pushed data. func IsWitnessProgram(script []byte) bool { - // The length of the script must be between 4 and 42 bytes. The - // smallest program is the witness version, followed by a data push of - // 2 bytes. The largest allowed witness program has a data push of - // 40-bytes. - if len(script) < 4 || len(script) > 42 { - return false - } - - pops, err := parseScript(script) - if err != nil { - return false - } - - return isWitnessProgram(pops) + return isWitnessProgramScript(script) } // isWitnessProgram returns true if the passed script is a witness program, and @@ -125,6 +112,8 @@ func IsWitnessProgram(script []byte) bool { // first opcode MUST be a small integer (0-16), the push data MUST be // canonical, and finally the size of the push data must be between 2 and 40 // bytes. +// +// DEPRECATED: Use isWitnessProgramScript instead. func isWitnessProgram(pops []parsedOpcode) bool { return len(pops) == 2 && isSmallInt(pops[0].opcode.value) && diff --git a/txscript/standard.go b/txscript/standard.go index 326d14d828..4b7d9be5bb 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -387,6 +387,51 @@ func isWitnessScriptHashScript(script []byte) bool { return extractWitnessScriptHash(script) != nil } +// isWitnessProgramScript returns true if the passed script is a witness +// program, and false otherwise. A witness program MUST adhere to the following +// constraints: there must be exactly two pops (program version and the program +// itself), the first opcode MUST be a small integer (0-16), the push data MUST +// be canonical, and finally the size of the push data must be between 2 and 40 +// bytes. +// +// The length of the script must be between 4 and 42 bytes. The +// smallest program is the witness version, followed by a data push of +// 2 bytes. The largest allowed witness program has a data push of +// 40-bytes. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func isWitnessProgramScript(script []byte) bool { + // Skip parsing if we know the program is invalid based on size. + if len(script) < 4 || len(script) > 42 { + return false + } + + const scriptVersion = 0 + tokenizer := MakeScriptTokenizer(scriptVersion, script) + + // The first opcode must be a small int. + if !tokenizer.Next() || + !isSmallInt(tokenizer.Opcode()) { + + return false + } + + // The second opcode must be a canonical data push, the length of the + // data push is bounded to 40 by the initial check on overall script + // length. + if !tokenizer.Next() || + !isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) { + + return false + } + + // The witness program is valid if there are no more opcodes, and we + // terminated without a parsing error. + return tokenizer.Done() && tokenizer.Err() == nil +} + // isNullDataScript returns whether or not the passed script is a standard // null data script. // From 8b706344a1fbbc5307058d2d9beaa054cb43ab49 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:39:28 -0700 Subject: [PATCH 0544/1056] txscript: Return witness version and program in one pass --- txscript/standard.go | 52 +++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 4b7d9be5bb..e3cf770730 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -387,25 +387,13 @@ func isWitnessScriptHashScript(script []byte) bool { return extractWitnessScriptHash(script) != nil } -// isWitnessProgramScript returns true if the passed script is a witness -// program, and false otherwise. A witness program MUST adhere to the following -// constraints: there must be exactly two pops (program version and the program -// itself), the first opcode MUST be a small integer (0-16), the push data MUST -// be canonical, and finally the size of the push data must be between 2 and 40 -// bytes. -// -// The length of the script must be between 4 and 42 bytes. The -// smallest program is the witness version, followed by a data push of -// 2 bytes. The largest allowed witness program has a data push of -// 40-bytes. -// -// NOTE: This function is only valid for version 0 scripts. Since the function -// does not accept a script version, the results are undefined for other script -// versions. -func isWitnessProgramScript(script []byte) bool { +// extractWitnessProgramInfo returns the version and program if the passed +// script constitutes a valid witness program. The alst return value indicates +// whether or not the script is a valid witness program. +func extractWitnessProgramInfo(script []byte) (int, []byte, bool) { // Skip parsing if we know the program is invalid based on size. if len(script) < 4 || len(script) > 42 { - return false + return 0, nil, false } const scriptVersion = 0 @@ -415,8 +403,9 @@ func isWitnessProgramScript(script []byte) bool { if !tokenizer.Next() || !isSmallInt(tokenizer.Opcode()) { - return false + return 0, nil, false } + version := asSmallInt(tokenizer.Opcode()) // The second opcode must be a canonical data push, the length of the // data push is bounded to 40 by the initial check on overall script @@ -424,12 +413,35 @@ func isWitnessProgramScript(script []byte) bool { if !tokenizer.Next() || !isCanonicalPush(tokenizer.Opcode(), tokenizer.Data()) { - return false + return 0, nil, false } + program := tokenizer.Data() // The witness program is valid if there are no more opcodes, and we // terminated without a parsing error. - return tokenizer.Done() && tokenizer.Err() == nil + valid := tokenizer.Done() && tokenizer.Err() == nil + + return version, program, valid +} + +// isWitnessProgramScript returns true if the passed script is a witness +// program, and false otherwise. A witness program MUST adhere to the following +// constraints: there must be exactly two pops (program version and the program +// itself), the first opcode MUST be a small integer (0-16), the push data MUST +// be canonical, and finally the size of the push data must be between 2 and 40 +// bytes. +// +// The length of the script must be between 4 and 42 bytes. The +// smallest program is the witness version, followed by a data push of +// 2 bytes. The largest allowed witness program has a data push of +// 40-bytes. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func isWitnessProgramScript(script []byte) bool { + _, _, valid := extractWitnessProgramInfo(script) + return valid } // isNullDataScript returns whether or not the passed script is a standard From 4b03b593912e1513937d98d7351bf8a58176063f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 5 Feb 2021 01:58:59 -0800 Subject: [PATCH 0545/1056] txscript: Use internal analysis methods for GetWitnessSigOpCount --- txscript/script.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 1ca953dea4..57c7b9be17 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -832,15 +832,15 @@ func GetPreciseSigOpCount(scriptSig, scriptPubKey []byte, _ bool) int { func GetWitnessSigOpCount(sigScript, pkScript []byte, witness wire.TxWitness) int { // If this is a regular witness program, then we can proceed directly // to counting its signature operations without any further processing. - if IsWitnessProgram(pkScript) { + if isWitnessProgramScript(pkScript) { return getWitnessSigOps(pkScript, witness) } // Next, we'll check the sigScript to see if this is a nested p2sh // witness program. This is a case wherein the sigScript is actually a // datapush of a p2wsh witness program. - if IsPayToScriptHash(pkScript) && IsPushOnlyScript(sigScript) && - IsWitnessProgram(sigScript[1:]) { + if isScriptHashScript(pkScript) && IsPushOnlyScript(sigScript) && + len(sigScript) > 0 && isWitnessProgramScript(sigScript[1:]) { return getWitnessSigOps(sigScript[1:], witness) } From d410d7d7d4fe116508e7aa9a180bd77dd5b9b8c3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:43:43 -0700 Subject: [PATCH 0546/1056] txscript: Optimize ExtractWitnessProgramInfo --- txscript/script.go | 13 +++---------- txscript/standard.go | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 57c7b9be17..9d7de56cbd 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -131,23 +131,16 @@ func IsNullData(script []byte) bool { // ExtractWitnessProgramInfo attempts to extract the witness program version, // as well as the witness program itself from the passed script. func ExtractWitnessProgramInfo(script []byte) (int, []byte, error) { - pops, err := parseScript(script) - if err != nil { - return 0, nil, err - } - // If at this point, the scripts doesn't resemble a witness program, // then we'll exit early as there isn't a valid version or program to // extract. - if !isWitnessProgram(pops) { + version, program, valid := extractWitnessProgramInfo(script) + if !valid { return 0, nil, fmt.Errorf("script is not a witness program, " + "unable to extract version or witness program") } - witnessVersion := asSmallInt(pops[0].opcode.value) - witnessProgram := pops[1].data - - return witnessVersion, witnessProgram, nil + return version, program, nil } // IsPushOnlyScript returns whether or not the passed script only pushes data diff --git a/txscript/standard.go b/txscript/standard.go index e3cf770730..44902971e9 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -388,7 +388,7 @@ func isWitnessScriptHashScript(script []byte) bool { } // extractWitnessProgramInfo returns the version and program if the passed -// script constitutes a valid witness program. The alst return value indicates +// script constitutes a valid witness program. The last return value indicates // whether or not the script is a valid witness program. func extractWitnessProgramInfo(script []byte) (int, []byte, bool) { // Skip parsing if we know the program is invalid based on size. From 7ad3a10442d80b204e8276f524d4859aa4d55887 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:46 -0500 Subject: [PATCH 0547/1056] txscript: mergeMultiSig function def order cleanup. This moves the function definition for mergeMultiSig so it is more consistent with the preferred order used through the codebase. In particular, the functions are defined before they're first used and generally as close as possible to the first use when they're defined in the same file. --- txscript/sign.go | 135 ++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 67 deletions(-) diff --git a/txscript/sign.go b/txscript/sign.go index b9f8b2dbb4..587910649c 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -212,73 +212,6 @@ func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, } } -// mergeScripts merges sigScript and prevScript assuming they are both -// partial solutions for pkScript spending output idx of tx. class, addresses -// and nrequired are the result of extracting the addresses from pkscript. -// The return value is the best effort merging of the two scripts. Calling this -// function with addresses, class and nrequired that do not match pkScript is -// an error and results in undefined behaviour. -func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, - pkScript []byte, class ScriptClass, addresses []btcutil.Address, - nRequired int, sigScript, prevScript []byte) []byte { - - // TODO: the scripthash and multisig paths here are overly - // inefficient in that they will recompute already known data. - // some internal refactoring could probably make this avoid needless - // extra calculations. - switch class { - case ScriptHashTy: - // Remove the last push in the script and then recurse. - // this could be a lot less inefficient. - sigPops, err := parseScript(sigScript) - if err != nil || len(sigPops) == 0 { - return prevScript - } - prevPops, err := parseScript(prevScript) - if err != nil || len(prevPops) == 0 { - return sigScript - } - - // assume that script in sigPops is the correct one, we just - // made it. - script := sigPops[len(sigPops)-1].data - - // We already know this information somewhere up the stack. - class, addresses, nrequired, _ := - ExtractPkScriptAddrs(script, chainParams) - - // regenerate scripts. - sigScript, _ := unparseScript(sigPops) - prevScript, _ := unparseScript(prevPops) - - // Merge - mergedScript := mergeScripts(chainParams, tx, idx, script, - class, addresses, nrequired, sigScript, prevScript) - - // Reappend the script and return the result. - builder := NewScriptBuilder() - builder.AddOps(mergedScript) - builder.AddData(script) - finalScript, _ := builder.Script() - return finalScript - case MultiSigTy: - return mergeMultiSig(tx, idx, addresses, nRequired, pkScript, - sigScript, prevScript) - - // It doesn't actually make sense to merge anything other than multiig - // and scripthash (because it could contain multisig). Everything else - // has either zero signature, can't be spent, or has a single signature - // which is either present or not. The other two cases are handled - // above. In the conflict case here we just assume the longest is - // correct (this matches behaviour of the reference implementation). - default: - if len(sigScript) > len(prevScript) { - return sigScript - } - return prevScript - } -} - // mergeMultiSig combines the two signature scripts sigScript and prevScript // that both provide signatures for pkScript in output idx of tx. addresses // and nRequired should be the results from extracting the addresses from @@ -397,6 +330,74 @@ sigLoop: return script } +// mergeScripts merges sigScript and prevScript assuming they are both +// partial solutions for pkScript spending output idx of tx. class, addresses +// and nrequired are the result of extracting the addresses from pkscript. +// The return value is the best effort merging of the two scripts. Calling this +// function with addresses, class and nrequired that do not match pkScript is +// an error and results in undefined behaviour. +func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, + pkScript []byte, class ScriptClass, addresses []btcutil.Address, + nRequired int, sigScript, prevScript []byte) []byte { + + // TODO(oga) the scripthash and multisig paths here are overly + // inefficient in that they will recompute already known data. + // some internal refactoring could probably make this avoid needless + // extra calculations. + switch class { + case ScriptHashTy: + // Remove the last push in the script and then recurse. + // this could be a lot less inefficient. + sigPops, err := parseScript(sigScript) + if err != nil || len(sigPops) == 0 { + return prevScript + } + prevPops, err := parseScript(prevScript) + if err != nil || len(prevPops) == 0 { + return sigScript + } + + // assume that script in sigPops is the correct one, we just + // made it. + script := sigPops[len(sigPops)-1].data + + // We already know this information somewhere up the stack, + // therefore the error is ignored. + class, addresses, nrequired, _ := + ExtractPkScriptAddrs(script, chainParams) + + // regenerate scripts. + sigScript, _ := unparseScript(sigPops) + prevScript, _ := unparseScript(prevPops) + + // Merge + mergedScript := mergeScripts(chainParams, tx, idx, script, + class, addresses, nrequired, sigScript, prevScript) + + // Reappend the script and return the result. + builder := NewScriptBuilder() + builder.AddOps(mergedScript) + builder.AddData(script) + finalScript, _ := builder.Script() + return finalScript + case MultiSigTy: + return mergeMultiSig(tx, idx, addresses, nRequired, pkScript, + sigScript, prevScript) + + // It doesn't actually make sense to merge anything other than multiig + // and scripthash (because it could contain multisig). Everything else + // has either zero signature, can't be spent, or has a single signature + // which is either present or not. The other two cases are handled + // above. In the conflict case here we just assume the longest is + // correct (this matches behaviour of the reference implementation). + default: + if len(sigScript) > len(prevScript) { + return sigScript + } + return prevScript + } +} + // KeyDB is an interface type provided to SignTxOutput, it encapsulates // any user state required to get the private keys for an address. type KeyDB interface { From dd609d6e36f3e6c7a4a0262cd0004733854d35c1 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 15:25:18 -0700 Subject: [PATCH 0548/1056] txscript: Introduce calcWitnessSignatureHashRaw --- txscript/script.go | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 9d7de56cbd..4651798541 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -385,7 +385,7 @@ func calcHashOutputs(tx *wire.MsgTx) chainhash.Hash { return chainhash.DoubleHashH(b.Bytes()) } -// calcWitnessSignatureHash computes the sighash digest of a transaction's +// calcWitnessSignatureHashRaw computes the sighash digest of a transaction's // segwit input using the new, optimized digest calculation algorithm defined // in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. // This function makes use of pre-calculated sighash fragments stored within @@ -396,7 +396,7 @@ func calcHashOutputs(tx *wire.MsgTx) chainhash.Hash { // being spent, in addition to the final transaction fee. In the case the // wallet if fed an invalid input amount, the real sighash will differ causing // the produced signature to be invalid. -func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes, +func calcWitnessSignatureHashRaw(scriptSig []byte, sigHashes *TxSigHashes, hashType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { // As a sanity check, ensure the passed input index for the transaction @@ -446,7 +446,7 @@ func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes, binary.LittleEndian.PutUint32(bIndex[:], txIn.PreviousOutPoint.Index) sigHash.Write(bIndex[:]) - if isWitnessPubKeyHash(subScript) { + if isWitnessPubKeyHashScript(scriptSig) { // The script code for a p2wkh is a length prefix varint for // the next 25 bytes, followed by a re-creation of the original // p2pkh pk script. @@ -454,15 +454,14 @@ func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes, sigHash.Write([]byte{OP_DUP}) sigHash.Write([]byte{OP_HASH160}) sigHash.Write([]byte{OP_DATA_20}) - sigHash.Write(subScript[1].data) + sigHash.Write(extractWitnessPubKeyHash(scriptSig)) sigHash.Write([]byte{OP_EQUALVERIFY}) sigHash.Write([]byte{OP_CHECKSIG}) } else { // For p2wsh outputs, and future outputs, the script code is // the original script, with all code separators removed, // serialized with a var int length prefix. - rawScript, _ := unparseScript(subScript) - wire.WriteVarBytes(&sigHash, 0, rawScript) + wire.WriteVarBytes(&sigHash, 0, scriptSig) } // Next, add the input amount, and sequence number of the input being @@ -501,6 +500,30 @@ func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes, return chainhash.DoubleHashB(sigHash.Bytes()), nil } +// calcWitnessSignatureHash computes the sighash digest of a transaction's +// segwit input using the new, optimized digest calculation algorithm defined +// in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. +// This function makes use of pre-calculated sighash fragments stored within +// the passed HashCache to eliminate duplicate hashing computations when +// calculating the final digest, reducing the complexity from O(N^2) to O(N). +// Additionally, signatures now cover the input value of the referenced unspent +// output. This allows offline, or hardware wallets to compute the exact amount +// being spent, in addition to the final transaction fee. In the case the +// wallet if fed an invalid input amount, the real sighash will differ causing +// the produced signature to be invalid. +// +// DEPRECATED: Use calcWitnessSignatureHashRaw instead. +func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes, + hashType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { + + script, err := unparseScript(subScript) + if err != nil { + return nil, err + } + + return calcWitnessSignatureHashRaw(script, sigHashes, hashType, tx, idx, amt) +} + // CalcWitnessSigHash computes the sighash digest for the specified input of // the target transaction observing the desired sig hash type. func CalcWitnessSigHash(script []byte, sigHashes *TxSigHashes, hType SigHashType, From ed9e17a043bdab0427b3f3b8113b9cc27e90cd84 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 20:09:07 -0700 Subject: [PATCH 0549/1056] txscript: Remove unused isWitnessPubKeyHash --- txscript/script.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 4651798541..10e0a1ca61 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -90,14 +90,6 @@ func IsPayToWitnessPubKeyHash(script []byte) bool { return isWitnessPubKeyHashScript(script) } -// isWitnessPubKeyHash returns true if the passed script is a -// pay-to-witness-pubkey-hash, and false otherwise. -func isWitnessPubKeyHash(pops []parsedOpcode) bool { - return len(pops) == 2 && - pops[0].opcode.value == OP_0 && - pops[1].opcode.value == OP_DATA_20 -} - // IsWitnessProgram returns true if the passed script is a valid witness // program which is encoded according to the passed witness program version. A // witness program must be a small integer (from 0-16), followed by 2-40 bytes From e00fec15571157f1241c8347893cb030ee28e034 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 15:26:10 -0700 Subject: [PATCH 0550/1056] txscript: Use optimized calcWitnessSignatureHashRaw w/o parsing --- txscript/script.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 10e0a1ca61..6798be1cb5 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -521,13 +521,12 @@ func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes, func CalcWitnessSigHash(script []byte, sigHashes *TxSigHashes, hType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { - parsedScript, err := parseScript(script) - if err != nil { - return nil, fmt.Errorf("cannot parse output script: %v", err) + const scriptVersion = 0 + if err := checkScriptParses(scriptVersion, script); err != nil { + return nil, err } - return calcWitnessSignatureHash(parsedScript, sigHashes, hType, tx, idx, - amt) + return calcWitnessSignatureHashRaw(script, sigHashes, hType, tx, idx, amt) } // shallowCopyTx creates a shallow copy of the transaction for use when From f3354beb12ceaf97b0ab25a2ac3d9817231fa663 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:50 -0500 Subject: [PATCH 0551/1056] txscript: Use raw scripts in SignTxOutput. This converts SignTxOutput and supporting funcs, namely sign, mergeScripts and mergeMultiSig, to make use of the new tokenizer as well as some recently added funcs that deal with raw scripts in order to remove the reliance on parsed opcodes as a step towards utlimately removing them altogether and updates the comments to explicitly call out the script version semantics. It is worth noting that this has the side effect of optimizing the function as well, however, since this change is not focused on the optimization aspects, no benchmarks are provided. --- txscript/sign.go | 88 ++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/txscript/sign.go b/txscript/sign.go index 587910649c..4d63a9b245 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -218,37 +218,44 @@ func sign(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, // pkScript. Since this function is internal only we assume that the arguments // have come from other functions internally and thus are all consistent with // each other, behaviour is undefined if this contract is broken. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []btcutil.Address, nRequired int, pkScript, sigScript, prevScript []byte) []byte { - // This is an internal only function and we already parsed this script - // as ok for multisig (this is how we got here), so if this fails then - // all assumptions are broken and who knows which way is up? - pkPops, _ := parseScript(pkScript) - - sigPops, err := parseScript(sigScript) - if err != nil || len(sigPops) == 0 { + // Nothing to merge if either the new or previous signature scripts are + // empty. + if len(sigScript) == 0 { return prevScript } - - prevPops, err := parseScript(prevScript) - if err != nil || len(prevPops) == 0 { + if len(prevScript) == 0 { return sigScript } // Convenience function to avoid duplication. - extractSigs := func(pops []parsedOpcode, sigs [][]byte) [][]byte { - for _, pop := range pops { - if len(pop.data) != 0 { - sigs = append(sigs, pop.data) + var possibleSigs [][]byte + extractSigs := func(script []byte) error { + const scriptVersion = 0 + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + if data := tokenizer.Data(); len(data) != 0 { + possibleSigs = append(possibleSigs, data) } } - return sigs + return tokenizer.Err() } - possibleSigs := make([][]byte, 0, len(sigPops)+len(prevPops)) - possibleSigs = extractSigs(sigPops, possibleSigs) - possibleSigs = extractSigs(prevPops, possibleSigs) + // Attempt to extract signatures from the two scripts. Return the other + // script that is intended to be merged in the case signature extraction + // fails for some reason. + if err := extractSigs(sigScript); err != nil { + return prevScript + } + if err := extractSigs(prevScript); err != nil { + return sigScript + } // Now we need to match the signatures to pubkeys, the only real way to // do that is to try to verify them all and match it to the pubkey @@ -278,10 +285,7 @@ sigLoop: // however, assume no sigs etc are in the script since that // would make the transaction nonstandard and thus not // MultiSigTy, so we just need to hash the full thing. - hash, err := calcSignatureHash(pkPops, hashType, tx, idx) - if err != nil { - panic(fmt.Sprintf("cannot compute sighash: %v", err)) - } + hash := calcSignatureHashRaw(pkScript, hashType, tx, idx) for _, addr := range addresses { // All multisig addresses should be pubkey addresses @@ -336,6 +340,10 @@ sigLoop: // The return value is the best effort merging of the two scripts. Calling this // function with addresses, class and nrequired that do not match pkScript is // an error and results in undefined behaviour. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, pkScript []byte, class ScriptClass, addresses []btcutil.Address, nRequired int, sigScript, prevScript []byte) []byte { @@ -344,32 +352,34 @@ func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, // inefficient in that they will recompute already known data. // some internal refactoring could probably make this avoid needless // extra calculations. + const scriptVersion = 0 switch class { case ScriptHashTy: - // Remove the last push in the script and then recurse. - // this could be a lot less inefficient. - sigPops, err := parseScript(sigScript) - if err != nil || len(sigPops) == 0 { + // Nothing to merge if either the new or previous signature + // scripts are empty or fail to parse. + if len(sigScript) == 0 || + checkScriptParses(scriptVersion, sigScript) != nil { + return prevScript } - prevPops, err := parseScript(prevScript) - if err != nil || len(prevPops) == 0 { + if len(prevScript) == 0 || + checkScriptParses(scriptVersion, prevScript) != nil { + return sigScript } - // assume that script in sigPops is the correct one, we just - // made it. - script := sigPops[len(sigPops)-1].data + // Remove the last push in the script and then recurse. + // this could be a lot less inefficient. + // + // Assume that final script is the correct one since it was just + // made and it is a pay-to-script-hash. + script := finalOpcodeData(scriptVersion, sigScript) // We already know this information somewhere up the stack, // therefore the error is ignored. class, addresses, nrequired, _ := ExtractPkScriptAddrs(script, chainParams) - // regenerate scripts. - sigScript, _ := unparseScript(sigPops) - prevScript, _ := unparseScript(prevPops) - // Merge mergedScript := mergeScripts(chainParams, tx, idx, script, class, addresses, nrequired, sigScript, prevScript) @@ -380,6 +390,7 @@ func mergeScripts(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, builder.AddData(script) finalScript, _ := builder.Script() return finalScript + case MultiSigTy: return mergeMultiSig(tx, idx, addresses, nRequired, pkScript, sigScript, prevScript) @@ -408,8 +419,7 @@ type KeyDB interface { type KeyClosure func(btcutil.Address) (*btcec.PrivateKey, bool, error) // GetKey implements KeyDB by returning the result of calling the closure. -func (kc KeyClosure) GetKey(address btcutil.Address) (*btcec.PrivateKey, - bool, error) { +func (kc KeyClosure) GetKey(address btcutil.Address) (*btcec.PrivateKey, bool, error) { return kc(address) } @@ -434,6 +444,10 @@ func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) { // getScript. If previousScript is provided then the results in previousScript // will be merged in a type-dependent manner with the newly generated. // signature script. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. func SignTxOutput(chainParams *chaincfg.Params, tx *wire.MsgTx, idx int, pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB, previousScript []byte) ([]byte, error) { From 30874ff76b167796960cbd57178305cfefb2b0da Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:51 -0500 Subject: [PATCH 0552/1056] txscript: Implement efficient opcode data removal. This introduces a new function named removeOpcodeByDataRaw which accepts the raw scripts and data to remove versus requiring the parsed opcodes to both significantly optimize it as well as make it more flexible for working with raw scripts. There are several places in the rest of the code that currently only have access to the parsed opcodes, so this only introduces the function for use in the future and deprecates the existing one. Note that, in practice, the script will never actually contain the data that is intended to be removed since the function is only used during signature verification to remove the signature itself which would require some incredibly non-standard code to create. Thus, as an optimization, it avoids allocating a new script unless there is actually a match that needs to be removed. Finally, it updates the tests to use the new function. --- txscript/script.go | 55 +++++++++++++++++++++++++++++++++++++++++ txscript/script_test.go | 13 +++++----- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 6798be1cb5..336a2c8b29 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -310,6 +310,8 @@ func isCanonicalPush(opcode byte, data []byte) bool { // removeOpcodeByData will return the script minus any opcodes that would push // the passed data to the stack. +// +// DEPRECATED. Use removeOpcodeByDataRaw instead. func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { retScript := make([]parsedOpcode, 0, len(pkscript)) for _, pop := range pkscript { @@ -323,6 +325,59 @@ func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { } +// removeOpcodeByDataRaw will return the script minus any opcodes that perform a +// canonical push of data that contains the passed data to remove. This +// function assumes it is provided a version 0 script as any future version of +// script should avoid this functionality since it is unncessary due to the +// signature scripts not being part of the witness-free transaction hash. +// +// WARNING: This will return the passed script unmodified unless a modification +// is necessary in which case the modified script is returned. This implies +// callers may NOT rely on being able to safely mutate either the passed or +// returned script without potentially modifying the same data. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func removeOpcodeByDataRaw(script []byte, dataToRemove []byte) []byte { + // Avoid work when possible. + if len(script) == 0 || len(dataToRemove) == 0 { + return script + } + + // Parse through the script looking for a canonical data push that contains + // the data to remove. + const scriptVersion = 0 + var result []byte + var prevOffset int32 + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + // In practice, the script will basically never actually contain the + // data since this function is only used during signature verification + // to remove the signature itself which would require some incredibly + // non-standard code to create. + // + // Thus, as an optimization, avoid allocating a new script unless there + // is actually a match that needs to be removed. + op, data := tokenizer.Opcode(), tokenizer.Data() + if isCanonicalPush(op, data) && bytes.Contains(data, dataToRemove) { + if result == nil { + fullPushLen := tokenizer.ByteIndex() - prevOffset + result = make([]byte, 0, int32(len(script))-fullPushLen) + result = append(result, script[0:prevOffset]...) + } + } else if result != nil { + result = append(result, script[prevOffset:tokenizer.ByteIndex()]...) + } + + prevOffset = tokenizer.ByteIndex() + } + if result == nil { + result = script + } + return result +} + // calcHashPrevOuts calculates a single hash of all the previous outputs // (txid:index) referenced within the passed transaction. This calculated hash // can be re-used when validating all inputs spending segwit outputs, with a diff --git a/txscript/script_test.go b/txscript/script_test.go index 62c51e4181..9a64865e35 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -4129,16 +4129,15 @@ func TestRemoveOpcodeByData(t *testing.T) { }, } - // tstRemoveOpcodeByData is a convenience function to parse the provided - // raw script, remove the passed data, then unparse the result back - // into a raw script. + // tstRemoveOpcodeByData is a convenience function to ensure the provided + // script parses before attempting to remove the passed data. + const scriptVersion = 0 tstRemoveOpcodeByData := func(script []byte, data []byte) ([]byte, error) { - pops, err := parseScript(script) - if err != nil { + if err := checkScriptParses(scriptVersion, script); err != nil { return nil, err } - pops = removeOpcodeByData(pops, data) - return unparseScript(pops) + + return removeOpcodeByDataRaw(script, data), nil } for _, test := range tests { From a4720f30e532c6c2815dd8ea626cf371ad2dca0e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 16:26:22 -0700 Subject: [PATCH 0553/1056] txscript: Optimize removeOpcodeRaw --- txscript/script.go | 39 +++++++++++++++++++++++++++++++++++++++ txscript/script_test.go | 7 +++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 336a2c8b29..7bfe44b3b9 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -269,6 +269,8 @@ func DisasmString(script []byte) (string, error) { // removeOpcode will remove any opcode matching ``opcode'' from the opcode // stream in pkscript +// +// DEPRECATED. Use removeOpcodeRaw instead. func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { retScript := make([]parsedOpcode, 0, len(pkscript)) for _, pop := range pkscript { @@ -279,6 +281,43 @@ func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { return retScript } +// removeOpcodeRaw will return the script after removing any opcodes that match +// `opcode`. If the opcode does not appear in script, the original script will +// be returned unmodified. Otherwise, a new script will be allocated to contain +// the filtered script. This metehod assumes that the script parses +// successfully. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func removeOpcodeRaw(script []byte, opcode byte) []byte { + // Avoid work when possible. + if len(script) == 0 { + return script + } + + const scriptVersion = 0 + var result []byte + var prevOffset int32 + + tokenizer := MakeScriptTokenizer(scriptVersion, script) + for tokenizer.Next() { + if tokenizer.Opcode() == opcode { + if result == nil { + result = make([]byte, 0, len(script)) + result = append(result, script[:prevOffset]...) + } + } else if result != nil { + result = append(result, script[prevOffset:tokenizer.ByteIndex()]...) + } + prevOffset = tokenizer.ByteIndex() + } + if result == nil { + return script + } + return result +} + // isCanonicalPush returns true if the opcode is either not a push instruction // or the data associated with the push instruction uses the smallest // instruction to do the job. False otherwise. diff --git a/txscript/script_test.go b/txscript/script_test.go index 9a64865e35..02c364ce31 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -3981,13 +3981,12 @@ func TestRemoveOpcodes(t *testing.T) { // tstRemoveOpcode is a convenience function to parse the provided // raw script, remove the passed opcode, then unparse the result back // into a raw script. + const scriptVersion = 0 tstRemoveOpcode := func(script []byte, opcode byte) ([]byte, error) { - pops, err := parseScript(script) - if err != nil { + if err := checkScriptParses(scriptVersion, script); err != nil { return nil, err } - pops = removeOpcode(pops, opcode) - return unparseScript(pops) + return removeOpcodeRaw(script, opcode), nil } for _, test := range tests { From 2ddcdb91f5bcb8df7fab43cbf1b92cccaadeb6fc Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 20:11:34 -0700 Subject: [PATCH 0554/1056] txscript: Remove unused removeOpcode --- txscript/script.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 7bfe44b3b9..7c8423bb50 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -267,20 +267,6 @@ func DisasmString(script []byte) (string, error) { return disbuf.String(), tokenizer.Err() } -// removeOpcode will remove any opcode matching ``opcode'' from the opcode -// stream in pkscript -// -// DEPRECATED. Use removeOpcodeRaw instead. -func removeOpcode(pkscript []parsedOpcode, opcode byte) []parsedOpcode { - retScript := make([]parsedOpcode, 0, len(pkscript)) - for _, pop := range pkscript { - if pop.opcode.value != opcode { - retScript = append(retScript, pop) - } - } - return retScript -} - // removeOpcodeRaw will return the script after removing any opcodes that match // `opcode`. If the opcode does not appear in script, the original script will // be returned unmodified. Otherwise, a new script will be allocated to contain From a2ab5b66816c8270185d43d20de7f11681be8afa Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 16:28:26 -0700 Subject: [PATCH 0555/1056] txscript: Use removeOpcodeRaw for CODESEP in calcSigHash --- txscript/script.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 7c8423bb50..0be0a7b8b3 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -683,24 +683,14 @@ func calcSignatureHashRaw(sigScript []byte, hashType SigHashType, tx *wire.MsgTx } // Remove all instances of OP_CODESEPARATOR from the script. - filteredScript := make([]byte, 0, len(sigScript)) - const scriptVersion = 0 - tokenizer := MakeScriptTokenizer(scriptVersion, sigScript) - var prevOffset int32 - for tokenizer.Next() { - if tokenizer.Opcode() != OP_CODESEPARATOR { - filteredScript = append(filteredScript, - sigScript[prevOffset:tokenizer.ByteIndex()]...) - } - prevOffset = tokenizer.ByteIndex() - } + sigScript = removeOpcodeRaw(sigScript, OP_CODESEPARATOR) // Make a shallow copy of the transaction, zeroing out the script for // all inputs that are not currently being processed. txCopy := shallowCopyTx(tx) for i := range txCopy.TxIn { if i == idx { - txCopy.TxIn[idx].SignatureScript = filteredScript + txCopy.TxIn[idx].SignatureScript = sigScript } else { txCopy.TxIn[i].SignatureScript = nil } From 484f7b1fef6a62eabe31f8c8a9fa44d15e2310b2 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:52 -0500 Subject: [PATCH 0556/1056] txscript: Make isDisabled accept raw opcode. This converts the isDisabled function defined on a parsed opcode to a standalone function which accepts an opcode as a byte instead in order to make it more flexible for raw script analysis. It also updates all callers accordingly. --- txscript/engine.go | 42 +++++++++++++++++++++++++++++++++++++++++- txscript/opcode.go | 39 --------------------------------------- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index ef7ad33e3c..00973a03a4 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -154,12 +154,52 @@ func (vm *Engine) isBranchExecuting() bool { return vm.condStack[len(vm.condStack)-1] == OpCondTrue } +// isOpcodeDisabled returns whether or not the opcode is disabled and thus is +// always bad to see in the instruction stream (even if turned off by a +// conditional). +func isOpcodeDisabled(opcode byte) bool { + switch opcode { + case OP_CAT: + return true + case OP_SUBSTR: + return true + case OP_LEFT: + return true + case OP_RIGHT: + return true + case OP_INVERT: + return true + case OP_AND: + return true + case OP_OR: + return true + case OP_XOR: + return true + case OP_2MUL: + return true + case OP_2DIV: + return true + case OP_MUL: + return true + case OP_DIV: + return true + case OP_MOD: + return true + case OP_LSHIFT: + return true + case OP_RSHIFT: + return true + default: + return false + } +} + // executeOpcode peforms execution on the passed opcode. It takes into account // whether or not it is hidden by conditionals, but some rules still must be // tested in this case. func (vm *Engine) executeOpcode(pop *parsedOpcode) error { // Disabled opcodes are fail on program counter. - if pop.isDisabled() { + if isOpcodeDisabled(pop.opcode.value) { str := fmt.Sprintf("attempt to execute disabled opcode %s", pop.opcode.name) return scriptError(ErrDisabledOpcode, str) diff --git a/txscript/opcode.go b/txscript/opcode.go index 893bebdf8d..62c6649d3d 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -619,45 +619,6 @@ type parsedOpcode struct { data []byte } -// isDisabled returns whether or not the opcode is disabled and thus is always -// bad to see in the instruction stream (even if turned off by a conditional). -func (pop *parsedOpcode) isDisabled() bool { - switch pop.opcode.value { - case OP_CAT: - return true - case OP_SUBSTR: - return true - case OP_LEFT: - return true - case OP_RIGHT: - return true - case OP_INVERT: - return true - case OP_AND: - return true - case OP_OR: - return true - case OP_XOR: - return true - case OP_2MUL: - return true - case OP_2DIV: - return true - case OP_MUL: - return true - case OP_DIV: - return true - case OP_MOD: - return true - case OP_LSHIFT: - return true - case OP_RSHIFT: - return true - default: - return false - } -} - // checkParseableInScript checks whether or not the current opcode is able to be // parsed at a certain position in a script. // This returns the position of the next opcode to be parsed in the script. From c6410257eb2894ee086fda5bb5ce88e33a44011a Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:53 -0500 Subject: [PATCH 0557/1056] txscript: Make alwaysIllegal accept raw opcode. This converts the alwaysIllegal function defined on a parsed opcode to a standalone function named isOpcodeAlwaysIllegal which accepts an opcode as a byte instead in order to make it more flexible for raw script analysis. It also updates all callers accordingly. --- txscript/engine.go | 16 +++++++++++++++- txscript/opcode.go | 14 -------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 00973a03a4..1c6a124b0c 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -194,6 +194,20 @@ func isOpcodeDisabled(opcode byte) bool { } } +// isOpcodeAlwaysIllegal returns whether or not the opcode is always illegal +// when passed over by the program counter even if in a non-executed branch (it +// isn't a coincidence that they are conditionals). +func isOpcodeAlwaysIllegal(opcode byte) bool { + switch opcode { + case OP_VERIF: + return true + case OP_VERNOTIF: + return true + default: + return false + } +} + // executeOpcode peforms execution on the passed opcode. It takes into account // whether or not it is hidden by conditionals, but some rules still must be // tested in this case. @@ -206,7 +220,7 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error { } // Always-illegal opcodes are fail on program counter. - if pop.alwaysIllegal() { + if isOpcodeAlwaysIllegal(pop.opcode.value) { str := fmt.Sprintf("attempt to execute reserved opcode %s", pop.opcode.name) return scriptError(ErrReservedOpcode, str) diff --git a/txscript/opcode.go b/txscript/opcode.go index 62c6649d3d..dc4ec50eb5 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -692,20 +692,6 @@ func (pop *parsedOpcode) checkParseableInScript(script []byte, scriptPos int) (i return scriptPos, nil } -// alwaysIllegal returns whether or not the opcode is always illegal when passed -// over by the program counter even if in a non-executed branch (it isn't a -// coincidence that they are conditionals). -func (pop *parsedOpcode) alwaysIllegal() bool { - switch pop.opcode.value { - case OP_VERIF: - return true - case OP_VERNOTIF: - return true - default: - return false - } -} - // isConditional returns whether or not the opcode is a conditional opcode which // changes the conditional execution stack when executed. func (pop *parsedOpcode) isConditional() bool { From 62c608f2654367caedef75e4370155d2cd0c0024 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:54 -0500 Subject: [PATCH 0558/1056] txscript: Make isConditional accept raw opcode. This converts the isConditional function defined on a parsed opcode to a standalone function named isOpcodeConditional which accepts an opcode as a byte instead in order to make it more flexible for raw script analysis. It also updates all callers accordingly. --- txscript/engine.go | 19 ++++++++++++++++++- txscript/opcode.go | 17 ----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 1c6a124b0c..ddb26de58f 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -208,6 +208,23 @@ func isOpcodeAlwaysIllegal(opcode byte) bool { } } +// isOpcodeConditional returns whether or not the opcode is a conditional opcode +// which changes the conditional execution stack when executed. +func isOpcodeConditional(opcode byte) bool { + switch opcode { + case OP_IF: + return true + case OP_NOTIF: + return true + case OP_ELSE: + return true + case OP_ENDIF: + return true + default: + return false + } +} + // executeOpcode peforms execution on the passed opcode. It takes into account // whether or not it is hidden by conditionals, but some rules still must be // tested in this case. @@ -243,7 +260,7 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error { // Nothing left to do when this is not a conditional opcode and it is // not in an executing branch. - if !vm.isBranchExecuting() && !pop.isConditional() { + if !vm.isBranchExecuting() && !isOpcodeConditional(pop.opcode.value) { return nil } diff --git a/txscript/opcode.go b/txscript/opcode.go index dc4ec50eb5..7705f59b02 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -692,23 +692,6 @@ func (pop *parsedOpcode) checkParseableInScript(script []byte, scriptPos int) (i return scriptPos, nil } -// isConditional returns whether or not the opcode is a conditional opcode which -// changes the conditional execution stack when executed. -func (pop *parsedOpcode) isConditional() bool { - switch pop.opcode.value { - case OP_IF: - return true - case OP_NOTIF: - return true - case OP_ELSE: - return true - case OP_ENDIF: - return true - default: - return false - } -} - // checkMinimalDataPush returns whether or not the current data push uses the // smallest possible opcode to represent it. For example, the value 15 could // be pushed with OP_DATA_1 15 (among other variations); however, OP_15 is a From 710bd5646e55a520054c4620e507b8867b864e64 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:55 -0500 Subject: [PATCH 0559/1056] txscript: Make min push accept raw opcode and data. This converts the checkMinimalDataPush function defined on a parsed opcode to a standalone function which accepts an opcode and data slice instead in order to make it more flexible for raw script analysis. It also updates all callers accordingly. --- txscript/engine.go | 51 +++++++++++++++++++++++++++++++++++++++++- txscript/opcode.go | 55 ---------------------------------------------- 2 files changed, 50 insertions(+), 56 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index ddb26de58f..a2dfad4c32 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -225,6 +225,55 @@ func isOpcodeConditional(opcode byte) bool { } } +// checkMinimalDataPush returns whether or not the provided opcode is the +// smallest possible way to represent the given data. For example, the value 15 +// could be pushed with OP_DATA_1 15 (among other variations); however, OP_15 is +// a single opcode that represents the same value and is only a single byte +// versus two bytes. +func checkMinimalDataPush(op *opcode, data []byte) error { + opcodeVal := op.value + dataLen := len(data) + switch { + case dataLen == 0 && opcodeVal != OP_0: + str := fmt.Sprintf("zero length data push is encoded with opcode %s "+ + "instead of OP_0", op.name) + return scriptError(ErrMinimalData, str) + case dataLen == 1 && data[0] >= 1 && data[0] <= 16: + if opcodeVal != OP_1+data[0]-1 { + // Should have used OP_1 .. OP_16 + str := fmt.Sprintf("data push of the value %d encoded with opcode "+ + "%s instead of OP_%d", data[0], op.name, data[0]) + return scriptError(ErrMinimalData, str) + } + case dataLen == 1 && data[0] == 0x81: + if opcodeVal != OP_1NEGATE { + str := fmt.Sprintf("data push of the value -1 encoded with opcode "+ + "%s instead of OP_1NEGATE", op.name) + return scriptError(ErrMinimalData, str) + } + case dataLen <= 75: + if int(opcodeVal) != dataLen { + // Should have used a direct push + str := fmt.Sprintf("data push of %d bytes encoded with opcode %s "+ + "instead of OP_DATA_%d", dataLen, op.name, dataLen) + return scriptError(ErrMinimalData, str) + } + case dataLen <= 255: + if opcodeVal != OP_PUSHDATA1 { + str := fmt.Sprintf("data push of %d bytes encoded with opcode %s "+ + "instead of OP_PUSHDATA1", dataLen, op.name) + return scriptError(ErrMinimalData, str) + } + case dataLen <= 65535: + if opcodeVal != OP_PUSHDATA2 { + str := fmt.Sprintf("data push of %d bytes encoded with opcode %s "+ + "instead of OP_PUSHDATA2", dataLen, op.name) + return scriptError(ErrMinimalData, str) + } + } + return nil +} + // executeOpcode peforms execution on the passed opcode. It takes into account // whether or not it is hidden by conditionals, but some rules still must be // tested in this case. @@ -269,7 +318,7 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error { if vm.dstack.verifyMinimalData && vm.isBranchExecuting() && pop.opcode.value >= 0 && pop.opcode.value <= OP_PUSHDATA4 { - if err := pop.checkMinimalDataPush(); err != nil { + if err := checkMinimalDataPush(pop.opcode, pop.data); err != nil { return err } } diff --git a/txscript/opcode.go b/txscript/opcode.go index 7705f59b02..95b4758055 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -692,61 +692,6 @@ func (pop *parsedOpcode) checkParseableInScript(script []byte, scriptPos int) (i return scriptPos, nil } -// checkMinimalDataPush returns whether or not the current data push uses the -// smallest possible opcode to represent it. For example, the value 15 could -// be pushed with OP_DATA_1 15 (among other variations); however, OP_15 is a -// single opcode that represents the same value and is only a single byte versus -// two bytes. -func (pop *parsedOpcode) checkMinimalDataPush() error { - data := pop.data - dataLen := len(data) - opcode := pop.opcode.value - - if dataLen == 0 && opcode != OP_0 { - str := fmt.Sprintf("zero length data push is encoded with "+ - "opcode %s instead of OP_0", pop.opcode.name) - return scriptError(ErrMinimalData, str) - } else if dataLen == 1 && data[0] >= 1 && data[0] <= 16 { - if opcode != OP_1+data[0]-1 { - // Should have used OP_1 .. OP_16 - str := fmt.Sprintf("data push of the value %d encoded "+ - "with opcode %s instead of OP_%d", data[0], - pop.opcode.name, data[0]) - return scriptError(ErrMinimalData, str) - } - } else if dataLen == 1 && data[0] == 0x81 { - if opcode != OP_1NEGATE { - str := fmt.Sprintf("data push of the value -1 encoded "+ - "with opcode %s instead of OP_1NEGATE", - pop.opcode.name) - return scriptError(ErrMinimalData, str) - } - } else if dataLen <= 75 { - if int(opcode) != dataLen { - // Should have used a direct push - str := fmt.Sprintf("data push of %d bytes encoded "+ - "with opcode %s instead of OP_DATA_%d", dataLen, - pop.opcode.name, dataLen) - return scriptError(ErrMinimalData, str) - } - } else if dataLen <= 255 { - if opcode != OP_PUSHDATA1 { - str := fmt.Sprintf("data push of %d bytes encoded "+ - "with opcode %s instead of OP_PUSHDATA1", - dataLen, pop.opcode.name) - return scriptError(ErrMinimalData, str) - } - } else if dataLen <= 65535 { - if opcode != OP_PUSHDATA2 { - str := fmt.Sprintf("data push of %d bytes encoded "+ - "with opcode %s instead of OP_PUSHDATA2", - dataLen, pop.opcode.name) - return scriptError(ErrMinimalData, str) - } - } - return nil -} - // disasmOpcode writes a human-readable disassembly of the provided opcode and // data into the provided buffer. The compact flag indicates the disassembly // should print a more compact representation of data-carrying and small integer From 54036e8bab1d8c8a596b2afbf2b0f4641b69a49f Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:56 -0500 Subject: [PATCH 0560/1056] txscript: Convert to use non-parsed opcode disasm. This converts the engine's current program counter disasembly to make use of the standalone disassembly function to remove the dependency on the parsed opcode struct. It also updates the tests accordingly. --- txscript/engine.go | 7 +++++-- txscript/opcode.go | 8 -------- txscript/opcode_test.go | 10 ++++++---- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index a2dfad4c32..191de29f5c 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -10,6 +10,7 @@ import ( "crypto/sha256" "fmt" "math/big" + "strings" "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/wire" @@ -331,8 +332,10 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error { // provided position in the script. It does no error checking and leaves that // to the caller to provide a valid offset. func (vm *Engine) disasm(scriptIdx int, scriptOff int) string { - return fmt.Sprintf("%02x:%04x: %s", scriptIdx, scriptOff, - vm.scripts[scriptIdx][scriptOff].print(false)) + var buf strings.Builder + pop := vm.scripts[scriptIdx][scriptOff] + disasmOpcode(&buf, pop.opcode, pop.data, false) + return fmt.Sprintf("%02x:%04x: %s", scriptIdx, scriptOff, buf.String()) } // validPC returns an error if the current script position is valid for diff --git a/txscript/opcode.go b/txscript/opcode.go index 95b4758055..a0d050529a 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -740,14 +740,6 @@ func disasmOpcode(buf *strings.Builder, op *opcode, data []byte, compact bool) { buf.WriteString(fmt.Sprintf(" 0x%02x", data)) } -// print returns a human-readable string representation of the opcode for use -// in script disassembly. -func (pop *parsedOpcode) print(compact bool) string { - var buf strings.Builder - disasmOpcode(&buf, pop.opcode, pop.data, compact) - return buf.String() -} - // bytes returns any data associated with the opcode encoded as it would be in // a script. This is used for unparsing scripts from parsed opcodes. func (pop *parsedOpcode) bytes() ([]byte, error) { diff --git a/txscript/opcode_test.go b/txscript/opcode_test.go index 1487dde590..3c5abf9da9 100644 --- a/txscript/opcode_test.go +++ b/txscript/opcode_test.go @@ -127,8 +127,9 @@ func TestOpcodeDisasm(t *testing.T) { expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) } - pop := parsedOpcode{opcode: &opcodeArray[opcodeVal], data: data} - gotStr := pop.print(true) + var buf strings.Builder + disasmOpcode(&buf, &opcodeArray[opcodeVal], data, true) + gotStr := buf.String() if gotStr != expectedStr { t.Errorf("pop.print (opcode %x): Unexpected disasm "+ "string - got %v, want %v", opcodeVal, gotStr, @@ -193,8 +194,9 @@ func TestOpcodeDisasm(t *testing.T) { expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) } - pop := parsedOpcode{opcode: &opcodeArray[opcodeVal], data: data} - gotStr := pop.print(false) + var buf strings.Builder + disasmOpcode(&buf, &opcodeArray[opcodeVal], data, false) + gotStr := buf.String() if gotStr != expectedStr { t.Errorf("pop.print (opcode %x): Unexpected disasm "+ "string - got %v, want %v", opcodeVal, gotStr, From d6b968c3ea24a55b51af05f764975e782b9bb677 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:58 -0500 Subject: [PATCH 0561/1056] txscript: Refactor engine to use raw scripts. This refactors the script engine to store and step through raw scripts by making using of the new zero-allocation script tokenizer as opposed to the less efficient method of storing and stepping through parsed opcodes. It also improves several aspects while refactoring such as optimizing the disassembly trace, showing all scripts in the trace in the case of execution failure, and providing additional comments describing the purpose of each field in the engine. It should be noted that this is a step towards removing the parsed opcode struct and associated supporting code altogether, however, in order to ease the review process, this retains the struct and all function signatures for opcode execution which make use of an individual parsed opcode. Those will be updated in future commits. The following is an overview of the changes: - Modify internal engine scripts slice to use raw scripts instead of parsed opcodes - Introduce a tokenizer to the engine to track the current script - Remove no longer needed script offset parameter from the engine since that is tracked by the tokenizer - Add an opcode index counter for disassembly purposes to the engine - Update check for valid program counter to only consider the script index - Update tests for bad program counter accordingly - Rework the NewEngine function - Store the raw scripts - Setup the initial tokenizer - Explicitly check against version 0 instead of DefaultScriptVersion which would break consensus if changed - Check the scripts parse according to version 0 semantics to retain current consensus rules - Improve comments throughout - Rework the Step function - Use the tokenizer and raw scripts - Create a parsed opcode on the fly for now to retain existing opcode execution function signatures - Improve comments throughout - Update the Execute function - Explicitly check against version 0 instead of DefaultScriptVersion which would break consensus if changed - Improve the disassembly tracing in the case of error - Update the CheckErrorCondition function - Modify clean stack error message to make sense in all cases - Improve the comments - Update the DisasmPC and DisasmScript functions on the engine - Use the tokenizer - Optimize construction via the use of strings.Builder - Modify the subScript function to return the raw script bytes since the parsed opcodes are no longer stored - Update the various signature checking opcodes to use the raw opcode data removal and signature hash calculation functions since the subscript is now a raw script - opcodeCheckSig - opcodeCheckMultiSig - opcodeCheckSigAlt --- txscript/engine.go | 373 +++++++++++++++++++++++++++------------- txscript/engine_test.go | 19 +- txscript/opcode.go | 20 +-- 3 files changed, 266 insertions(+), 146 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 191de29f5c..1afb8324dd 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -119,21 +119,84 @@ var halfOrder = new(big.Int).Rsh(btcec.S256().N, 1) // Engine is the virtual machine that executes scripts. type Engine struct { - scripts [][]parsedOpcode + // The following fields are set when the engine is created and must not be + // changed afterwards. The entries of the signature cache are mutated + // during execution, however, the cache pointer itself is not changed. + // + // flags specifies the additional flags which modify the execution behavior + // of the engine. + // + // tx identifies the transaction that contains the input which in turn + // contains the signature script being executed. + // + // txIdx identifies the input index within the transaction that contains + // the signature script being executed. + // + // version specifies the version of the public key script to execute. Since + // signature scripts redeem public keys scripts, this means the same version + // also extends to signature scripts and redeem scripts in the case of + // pay-to-script-hash. + // + // bip16 specifies that the public key script is of a special form that + // indicates it is a BIP16 pay-to-script-hash and therefore the + // execution must be treated as such. + // + // sigCache caches the results of signature verifications. This is useful + // since transaction scripts are often executed more than once from various + // contexts (e.g. new block templates, when transactions are first seen + // prior to being mined, part of full block verification, etc). + flags ScriptFlags + tx wire.MsgTx + txIdx int + version uint16 + bip16 bool + sigCache *SigCache + hashCache *TxSigHashes + + // The following fields handle keeping track of the current execution state + // of the engine. + // + // scripts houses the raw scripts that are executed by the engine. This + // includes the signature script as well as the public key script. It also + // includes the redeem script in the case of pay-to-script-hash. + // + // scriptIdx tracks the index into the scripts array for the current program + // counter. + // + // opcodeIdx tracks the number of the opcode within the current script for + // the current program counter. Note that it differs from the actual byte + // index into the script and is really only used for disassembly purposes. + // + // lastCodeSep specifies the position within the current script of the last + // OP_CODESEPARATOR. + // + // tokenizer provides the token stream of the current script being executed + // and doubles as state tracking for the program counter within the script. + // + // savedFirstStack keeps a copy of the stack from the first script when + // performing pay-to-script-hash execution. + // + // dstack is the primary data stack the various opcodes push and pop data + // to and from during execution. + // + // astack is the alternate data stack the various opcodes push and pop data + // to and from during execution. + // + // condStack tracks the conditional execution state with support for + // multiple nested conditional execution opcodes. + // + // numOps tracks the total number of non-push operations in a script and is + // primarily used to enforce maximum limits. + scripts [][]byte scriptIdx int - scriptOff int + opcodeIdx int lastCodeSep int - dstack stack // data stack - astack stack // alt stack - tx wire.MsgTx - txIdx int + tokenizer ScriptTokenizer + savedFirstStack [][]byte + dstack stack + astack stack condStack []int numOps int - flags ScriptFlags - sigCache *SigCache - hashCache *TxSigHashes - bip16 bool // treat execution as pay-to-script-hash - savedFirstStack [][]byte // stack from first script for bip16 scripts witnessVersion int witnessProgram []byte inputAmount int64 @@ -327,44 +390,17 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error { return pop.opcode.opfunc(pop, vm) } -// disasm is a helper function to produce the output for DisasmPC and -// DisasmScript. It produces the opcode prefixed by the program counter at the -// provided position in the script. It does no error checking and leaves that -// to the caller to provide a valid offset. -func (vm *Engine) disasm(scriptIdx int, scriptOff int) string { - var buf strings.Builder - pop := vm.scripts[scriptIdx][scriptOff] - disasmOpcode(&buf, pop.opcode, pop.data, false) - return fmt.Sprintf("%02x:%04x: %s", scriptIdx, scriptOff, buf.String()) -} - -// validPC returns an error if the current script position is valid for -// execution, nil otherwise. -func (vm *Engine) validPC() error { +// checkValidPC returns an error if the current script position is not valid for +// execution. +func (vm *Engine) checkValidPC() error { if vm.scriptIdx >= len(vm.scripts) { - str := fmt.Sprintf("past input scripts %v:%v %v:xxxx", - vm.scriptIdx, vm.scriptOff, len(vm.scripts)) - return scriptError(ErrInvalidProgramCounter, str) - } - if vm.scriptOff >= len(vm.scripts[vm.scriptIdx]) { - str := fmt.Sprintf("past input scripts %v:%v %v:%04d", - vm.scriptIdx, vm.scriptOff, vm.scriptIdx, - len(vm.scripts[vm.scriptIdx])) + str := fmt.Sprintf("script index %d beyond total scripts %d", + vm.scriptIdx, len(vm.scripts)) return scriptError(ErrInvalidProgramCounter, str) } return nil } -// curPC returns either the current script and offset, or an error if the -// position isn't valid. -func (vm *Engine) curPC() (script int, off int, err error) { - err = vm.validPC() - if err != nil { - return 0, 0, err - } - return vm.scriptIdx, vm.scriptOff, nil -} - // isWitnessVersionActive returns true if a witness program was extracted // during the initialization of the Engine, and the program's version matches // the specified version. @@ -392,7 +428,9 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error { if err != nil { return err } - pops, err := parseScript(pkScript) + + const scriptVersion = 0 + err = checkScriptParses(vm.version, pkScript) if err != nil { return err } @@ -400,7 +438,7 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error { // Set the stack to the provided witness stack, then // append the pkScript generated above as the next // script to execute. - vm.scripts = append(vm.scripts, pops) + vm.scripts = append(vm.scripts, pkScript) vm.SetStack(witness) case payToWitnessScriptHashDataSize: // P2WSH @@ -430,10 +468,10 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error { "witness program hash mismatch") } - // With all the validity checks passed, parse the - // script into individual op-codes so w can execute it - // as the next script. - pops, err := parseScript(witnessScript) + // With all the validity checks passed, assert that the + // script parses without failure. + const scriptVersion = 0 + err := checkScriptParses(vm.version, witnessScript) if err != nil { return err } @@ -441,7 +479,7 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error { // The hash matched successfully, so use the witness as // the stack, and set the witnessScript to be the next // script executed. - vm.scripts = append(vm.scripts, pops) + vm.scripts = append(vm.scripts, witnessScript) vm.SetStack(witness[:len(witness)-1]) default: @@ -482,18 +520,50 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error { } // DisasmPC returns the string for the disassembly of the opcode that will be -// next to execute when Step() is called. +// next to execute when Step is called. func (vm *Engine) DisasmPC() (string, error) { - scriptIdx, scriptOff, err := vm.curPC() - if err != nil { + if err := vm.checkValidPC(); err != nil { return "", err } - return vm.disasm(scriptIdx, scriptOff), nil + + // Create a copy of the current tokenizer and parse the next opcode in the + // copy to avoid mutating the current one. + peekTokenizer := vm.tokenizer + if !peekTokenizer.Next() { + // Note that due to the fact that all scripts are checked for parse + // failures before this code ever runs, there should never be an error + // here, but check again to be safe in case a refactor breaks that + // assumption or new script versions are introduced with different + // semantics. + if err := peekTokenizer.Err(); err != nil { + return "", err + } + + // Note that this should be impossible to hit in practice because the + // only way it could happen would be for the final opcode of a script to + // already be parsed without the script index having been updated, which + // is not the case since stepping the script always increments the + // script index when parsing and executing the final opcode of a script. + // + // However, check again to be safe in case a refactor breaks that + // assumption or new script versions are introduced with different + // semantics. + str := fmt.Sprintf("program counter beyond script index %d (bytes %x)", + vm.scriptIdx, vm.scripts[vm.scriptIdx]) + return "", scriptError(ErrInvalidProgramCounter, str) + } + + var buf strings.Builder + disasmOpcode(&buf, peekTokenizer.op, peekTokenizer.Data(), false) + return fmt.Sprintf("%02x:%04x: %s", vm.scriptIdx, vm.opcodeIdx, + buf.String()), nil } // DisasmScript returns the disassembly string for the script at the requested // offset index. Index 0 is the signature script and 1 is the public key -// script. +// script. In the case of pay-to-script-hash, index 2 is the redeem script once +// the execution has progressed far enough to have successfully verified script +// hash and thus add the script to the scripts to execute. func (vm *Engine) DisasmScript(idx int) (string, error) { if idx >= len(vm.scripts) { str := fmt.Sprintf("script index %d >= total scripts %d", idx, @@ -501,19 +571,25 @@ func (vm *Engine) DisasmScript(idx int) (string, error) { return "", scriptError(ErrInvalidIndex, str) } - var disstr string - for i := range vm.scripts[idx] { - disstr = disstr + vm.disasm(idx, i) + "\n" + var disbuf strings.Builder + script := vm.scripts[idx] + tokenizer := MakeScriptTokenizer(vm.version, script) + var opcodeIdx int + for tokenizer.Next() { + disbuf.WriteString(fmt.Sprintf("%02x:%04x: ", idx, opcodeIdx)) + disasmOpcode(&disbuf, tokenizer.op, tokenizer.Data(), false) + disbuf.WriteByte('\n') + opcodeIdx++ } - return disstr, nil + return disbuf.String(), tokenizer.Err() } // CheckErrorCondition returns nil if the running script has ended and was // successful, leaving a a true boolean on the stack. An error otherwise, // including if the script has not finished. func (vm *Engine) CheckErrorCondition(finalScript bool) error { - // Check execution is actually done. When pc is past the end of script - // array there are no more scripts to run. + // Check execution is actually done by ensuring the script index is after + // the final script in the array script. if vm.scriptIdx < len(vm.scripts) { return scriptError(ErrScriptUnfinished, "error check when script unfinished") @@ -527,11 +603,14 @@ func (vm *Engine) CheckErrorCondition(finalScript bool) error { "have clean stack") } + // The final script must end with exactly one data stack item when the + // verify clean stack flag is set. Otherwise, there must be at least one + // data stack item in order to interpret it as a boolean. if finalScript && vm.hasFlag(ScriptVerifyCleanStack) && vm.dstack.Depth() != 1 { - str := fmt.Sprintf("stack contains %d unexpected items", - vm.dstack.Depth()-1) + str := fmt.Sprintf("stack must contain exactly one item (contains %d)", + vm.dstack.Depth()) return scriptError(ErrCleanStack, str) } else if vm.dstack.Depth() < 1 { return scriptError(ErrEmptyStack, @@ -545,10 +624,14 @@ func (vm *Engine) CheckErrorCondition(finalScript bool) error { if !v { // Log interesting data. log.Tracef("%v", newLogClosure(func() string { - dis0, _ := vm.DisasmScript(0) - dis1, _ := vm.DisasmScript(1) - return fmt.Sprintf("scripts failed: script0: %s\n"+ - "script1: %s", dis0, dis1) + var buf strings.Builder + buf.WriteString("scripts failed:\n") + for i := range vm.scripts { + dis, _ := vm.DisasmScript(i) + buf.WriteString(fmt.Sprintf("script%d:\n", i)) + buf.WriteString(dis) + } + return buf.String() })) return scriptError(ErrEvalFalse, "false stack entry at end of script execution") @@ -556,25 +639,39 @@ func (vm *Engine) CheckErrorCondition(finalScript bool) error { return nil } -// Step will execute the next instruction and move the program counter to the -// next opcode in the script, or the next script if the current has ended. Step -// will return true in the case that the last opcode was successfully executed. +// Step executes the next instruction and moves the program counter to the next +// opcode in the script, or the next script if the current has ended. Step will +// return true in the case that the last opcode was successfully executed. // // The result of calling Step or any other method is undefined if an error is // returned. func (vm *Engine) Step() (done bool, err error) { - // Verify that it is pointing to a valid script address. - err = vm.validPC() - if err != nil { + // Verify the engine is pointing to a valid program counter. + if err := vm.checkValidPC(); err != nil { return true, err } - opcode := &vm.scripts[vm.scriptIdx][vm.scriptOff] - vm.scriptOff++ + + // Attempt to parse the next opcode from the current script. + if !vm.tokenizer.Next() { + // Note that due to the fact that all scripts are checked for parse + // failures before this code ever runs, there should never be an error + // here, but check again to be safe in case a refactor breaks that + // assumption or new script versions are introduced with different + // semantics. + if err := vm.tokenizer.Err(); err != nil { + return false, err + } + + str := fmt.Sprintf("attempt to step beyond script index %d (bytes %x)", + vm.scriptIdx, vm.scripts[vm.scriptIdx]) + return true, scriptError(ErrInvalidProgramCounter, str) + } // Execute the opcode while taking into account several things such as - // disabled opcodes, illegal opcodes, maximum allowed operations per - // script, maximum script element sizes, and conditionals. - err = vm.executeOpcode(opcode) + // disabled opcodes, illegal opcodes, maximum allowed operations per script, + // maximum script element sizes, and conditionals. + pop := parsedOpcode{opcode: vm.tokenizer.op, data: vm.tokenizer.Data()} + err = vm.executeOpcode(&pop) if err != nil { return true, err } @@ -589,43 +686,53 @@ func (vm *Engine) Step() (done bool, err error) { } // Prepare for next instruction. - if vm.scriptOff >= len(vm.scripts[vm.scriptIdx]) { - // Illegal to have an `if' that straddles two scripts. - if err == nil && len(vm.condStack) != 0 { + vm.opcodeIdx++ + if vm.tokenizer.Done() { + // Illegal to have a conditional that straddles two scripts. + if len(vm.condStack) != 0 { return false, scriptError(ErrUnbalancedConditional, "end of script reached in conditional execution") } - // Alt stack doesn't persist. + // Alt stack doesn't persist between scripts. _ = vm.astack.DropN(vm.astack.Depth()) - vm.numOps = 0 // number of ops is per script. - vm.scriptOff = 0 - if vm.scriptIdx == 0 && vm.bip16 { + // The number of operations is per script. + vm.numOps = 0 + + // Reset the opcode index for the next script. + vm.opcodeIdx = 0 + + // Advance to the next script as needed. + switch { + case vm.scriptIdx == 0 && vm.bip16: vm.scriptIdx++ vm.savedFirstStack = vm.GetStack() - } else if vm.scriptIdx == 1 && vm.bip16 { + + case vm.scriptIdx == 1 && vm.bip16: // Put us past the end for CheckErrorCondition() vm.scriptIdx++ - // Check script ran successfully and pull the script - // out of the first stack and execute that. + + // Check script ran successfully. err := vm.CheckErrorCondition(false) if err != nil { return false, err } + // Obtain the redeem script from the first stack and ensure it + // parses. script := vm.savedFirstStack[len(vm.savedFirstStack)-1] - pops, err := parseScript(script) - if err != nil { + if err := checkScriptParses(vm.version, script); err != nil { return false, err } - vm.scripts = append(vm.scripts, pops) + vm.scripts = append(vm.scripts, script) - // Set stack to be the stack from first script minus the + // Set stack to be the stack from first script minus the redeem // script itself vm.SetStack(vm.savedFirstStack[:len(vm.savedFirstStack)-1]) - } else if (vm.scriptIdx == 1 && vm.witnessProgram != nil) || - (vm.scriptIdx == 2 && vm.witnessProgram != nil && vm.bip16) { // Nested P2SH. + + case vm.scriptIdx == 1 && vm.witnessProgram != nil, + vm.scriptIdx == 2 && vm.witnessProgram != nil && vm.bip16: // np2sh vm.scriptIdx++ @@ -633,30 +740,46 @@ func (vm *Engine) Step() (done bool, err error) { if err := vm.verifyWitnessProgram(witness); err != nil { return false, err } - } else { + + default: vm.scriptIdx++ } - // there are zero length scripts in the wild - if vm.scriptIdx < len(vm.scripts) && vm.scriptOff >= len(vm.scripts[vm.scriptIdx]) { + + // Skip empty scripts. + if vm.scriptIdx < len(vm.scripts) && len(vm.scripts[vm.scriptIdx]) == 0 { vm.scriptIdx++ } + vm.lastCodeSep = 0 if vm.scriptIdx >= len(vm.scripts) { return true, nil } + + // Finally, update the current tokenizer used to parse through scripts + // one opcode at a time to start from the beginning of the new script + // associated with the program counter. + vm.tokenizer = MakeScriptTokenizer(vm.version, vm.scripts[vm.scriptIdx]) } + return false, nil } // Execute will execute all scripts in the script engine and return either nil // for successful validation or an error if one occurred. func (vm *Engine) Execute() (err error) { + // All script versions other than 0 currently execute without issue, + // making all outputs to them anyone can pay. In the future this + // will allow for the addition of new scripting languages. + if vm.version != 0 { + return nil + } + done := false for !done { log.Tracef("%v", newLogClosure(func() string { dis, err := vm.DisasmPC() if err != nil { - return fmt.Sprintf("stepping (%v)", err) + return fmt.Sprintf("stepping - failed to disasm pc: %v", err) } return fmt.Sprintf("stepping %v", dis) })) @@ -668,7 +791,7 @@ func (vm *Engine) Execute() (err error) { log.Tracef("%v", newLogClosure(func() string { var dstr, astr string - // if we're tracing, dump the stacks. + // Log the non-empty stacks when tracing. if vm.dstack.Depth() != 0 { dstr = "Stack:\n" + vm.dstack.String() } @@ -684,7 +807,7 @@ func (vm *Engine) Execute() (err error) { } // subScript returns the script since the last OP_CODESEPARATOR. -func (vm *Engine) subScript() []parsedOpcode { +func (vm *Engine) subScript() []byte { return vm.scripts[vm.scriptIdx][vm.lastCodeSep:] } @@ -1008,10 +1131,10 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags } scriptSig := tx.TxIn[txIdx].SignatureScript - // When both the signature script and public key script are empty the - // result is necessarily an error since the stack would end up being - // empty which is equivalent to a false top element. Thus, just return - // the relevant error now as an optimization. + // When both the signature script and public key script are empty the result + // is necessarily an error since the stack would end up being empty which is + // equivalent to a false top element. Thus, just return the relevant error + // now as an optimization. if len(scriptSig) == 0 && len(scriptPubKey) == 0 { return nil, scriptError(ErrEvalFalse, "false stack entry at end of script execution") @@ -1057,29 +1180,28 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags vm.bip16 = true } - // The engine stores the scripts in parsed form using a slice. This - // allows multiple scripts to be executed in sequence. For example, - // with a pay-to-script-hash transaction, there will be ultimately be - // a third script to execute. + // The engine stores the scripts using a slice. This allows multiple + // scripts to be executed in sequence. For example, with a + // pay-to-script-hash transaction, there will be ultimately be a third + // script to execute. scripts := [][]byte{scriptSig, scriptPubKey} - vm.scripts = make([][]parsedOpcode, len(scripts)) - for i, scr := range scripts { + for _, scr := range scripts { if len(scr) > MaxScriptSize { - str := fmt.Sprintf("script size %d is larger than max "+ - "allowed size %d", len(scr), MaxScriptSize) + str := fmt.Sprintf("script size %d is larger than max allowed "+ + "size %d", len(scr), MaxScriptSize) return nil, scriptError(ErrScriptTooBig, str) } - var err error - vm.scripts[i], err = parseScript(scr) - if err != nil { + + const scriptVersion = 0 + if err := checkScriptParses(scriptVersion, scr); err != nil { return nil, err } } + vm.scripts = scripts // Advance the program counter to the public key script if the signature - // script is empty since there is nothing to execute for it in that - // case. - if len(scripts[0]) == 0 { + // script is empty since there is nothing to execute for it in that case. + if len(scriptSig) == 0 { vm.scriptIdx++ } if vm.hasFlag(ScriptVerifyMinimalData) { @@ -1103,7 +1225,7 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags var witProgram []byte switch { - case isWitnessProgram(vm.scripts[1]): + case IsWitnessProgram(vm.scripts[1]): // The scriptSig must be *empty* for all native witness // programs, otherwise we introduce malleability. if len(scriptSig) != 0 { @@ -1118,12 +1240,11 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags // data push of the witness program, otherwise we // reintroduce malleability. sigPops := vm.scripts[0] - if len(sigPops) == 1 && - isCanonicalPush(sigPops[0].opcode.value, - sigPops[0].data) && - IsWitnessProgram(sigPops[0].data) { + if len(sigPops) > 2 && + isCanonicalPush(sigPops[0], sigPops[1:]) && + IsWitnessProgram(sigPops[1:]) { - witProgram = sigPops[0].data + witProgram = sigPops[1:] } else { errStr := "signature script for witness " + "nested p2sh is not canonical" @@ -1150,6 +1271,10 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags } + // Setup the current tokenizer used to parse through the script one opcode + // at a time with the script associated with the program counter. + vm.tokenizer = MakeScriptTokenizer(scriptVersion, scripts[vm.scriptIdx]) + vm.tx = *tx vm.txIdx = txIdx diff --git a/txscript/engine_test.go b/txscript/engine_test.go index 2e8c522c1a..5818080dfd 100644 --- a/txscript/engine_test.go +++ b/txscript/engine_test.go @@ -1,4 +1,5 @@ // Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2019 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -11,16 +12,16 @@ import ( "github.com/btcsuite/btcd/wire" ) -// TestBadPC sets the pc to a deliberately bad result then confirms that Step() +// TestBadPC sets the pc to a deliberately bad result then confirms that Step // and Disasm fail correctly. func TestBadPC(t *testing.T) { t.Parallel() tests := []struct { - script, off int + scriptIdx int }{ - {script: 2, off: 0}, - {script: 0, off: 2}, + {scriptIdx: 2}, + {scriptIdx: 3}, } // tx with almost empty scripts. @@ -59,20 +60,20 @@ func TestBadPC(t *testing.T) { t.Errorf("Failed to create script: %v", err) } - // set to after all scripts - vm.scriptIdx = test.script - vm.scriptOff = test.off + // Set to after all scripts. + vm.scriptIdx = test.scriptIdx + // Ensure attempting to step fails. _, err = vm.Step() if err == nil { t.Errorf("Step with invalid pc (%v) succeeds!", test) continue } + // Ensure attempting to disassemble the current program counter fails. _, err = vm.DisasmPC() if err == nil { - t.Errorf("DisasmPC with invalid pc (%v) succeeds!", - test) + t.Errorf("DisasmPC with invalid pc (%v) succeeds!", test) } } } diff --git a/txscript/opcode.go b/txscript/opcode.go index a0d050529a..950121c69d 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1981,7 +1981,7 @@ func opcodeHash256(op *parsedOpcode, vm *Engine) error { // // This opcode does not change the contents of the data stack. func opcodeCodeSeparator(op *parsedOpcode, vm *Engine) error { - vm.lastCodeSep = vm.scriptOff + vm.lastCodeSep = int(vm.tokenizer.ByteIndex()) return nil } @@ -2055,7 +2055,7 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error { sigHashes = NewTxSigHashes(&vm.tx) } - hash, err = calcWitnessSignatureHash(subScript, sigHashes, hashType, + hash, err = calcWitnessSignatureHashRaw(subScript, sigHashes, hashType, &vm.tx, vm.txIdx, vm.inputAmount) if err != nil { return err @@ -2063,12 +2063,9 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error { } else { // Remove the signature since there is no way for a signature // to sign itself. - subScript = removeOpcodeByData(subScript, fullSigBytes) + subScript = removeOpcodeByDataRaw(subScript, fullSigBytes) - hash, err = calcSignatureHash(subScript, hashType, &vm.tx, vm.txIdx) - if err != nil { - return err - } + hash = calcSignatureHashRaw(subScript, hashType, &vm.tx, vm.txIdx) } pubKey, err := btcec.ParsePubKey(pkBytes, btcec.S256()) @@ -2239,7 +2236,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { // no way for a signature to sign itself. if !vm.isWitnessVersionActive(0) { for _, sigInfo := range signatures { - script = removeOpcodeByData(script, sigInfo.signature) + script = removeOpcodeByDataRaw(script, sigInfo.signature) } } @@ -2331,16 +2328,13 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { sigHashes = NewTxSigHashes(&vm.tx) } - hash, err = calcWitnessSignatureHash(script, sigHashes, hashType, + hash, err = calcWitnessSignatureHashRaw(script, sigHashes, hashType, &vm.tx, vm.txIdx, vm.inputAmount) if err != nil { return err } } else { - hash, err = calcSignatureHash(script, hashType, &vm.tx, vm.txIdx) - if err != nil { - return err - } + hash = calcSignatureHashRaw(script, hashType, &vm.tx, vm.txIdx) } var valid bool From 06c8bea6c76f73f8afa214a99d45fe9c65a20d2d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:05:20 -0700 Subject: [PATCH 0562/1056] txscript: Remove unused calcSignatureHash --- txscript/script.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 0be0a7b8b3..8ff39e209a 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -744,21 +744,6 @@ func calcSignatureHashRaw(sigScript []byte, hashType SigHashType, tx *wire.MsgTx return chainhash.DoubleHashB(wbuf.Bytes()) } -// calcSignatureHash computes the signature hash for the specified input of the -// target transaction observing the desired signature hash type. -// -// DEPRECATED: Use calcSignatureHashRaw instead -func calcSignatureHash(prevOutScript []parsedOpcode, hashType SigHashType, - tx *wire.MsgTx, idx int) ([]byte, error) { - - sigScript, err := unparseScript(prevOutScript) - if err != nil { - return nil, err - } - - return calcSignatureHashRaw(sigScript, hashType, tx, idx), nil -} - // asSmallInt returns the passed opcode, which must be true according to // isSmallInt(), as an integer. func asSmallInt(op byte) int { From 03d1fb0f86ac8dc65c6e67b31069630fce70fb69 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 20:09:59 -0700 Subject: [PATCH 0563/1056] txscript: Remove unused isWitnessProgram --- txscript/script.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 8ff39e209a..6557c64d1e 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -98,21 +98,6 @@ func IsWitnessProgram(script []byte) bool { return isWitnessProgramScript(script) } -// isWitnessProgram returns true if the passed script is a witness program, and -// false otherwise. A witness program MUST adhere to the following constraints: -// there must be exactly two pops (program version and the program itself), the -// first opcode MUST be a small integer (0-16), the push data MUST be -// canonical, and finally the size of the push data must be between 2 and 40 -// bytes. -// -// DEPRECATED: Use isWitnessProgramScript instead. -func isWitnessProgram(pops []parsedOpcode) bool { - return len(pops) == 2 && - isSmallInt(pops[0].opcode.value) && - isCanonicalPush(pops[1].opcode.value, pops[1].data) && - (len(pops[1].data) >= 2 && len(pops[1].data) <= 40) -} - // IsNullData returns true if the passed script is a null data script, false // otherwise. func IsNullData(script []byte) bool { From 07ab66b790e0b732868548e0624c62a7b03a2863 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:12:59 -0500 Subject: [PATCH 0564/1056] txscript: Remove unused removeOpcodeByData func. --- txscript/script.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 6557c64d1e..242fc2d875 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -318,23 +318,6 @@ func isCanonicalPush(opcode byte, data []byte) bool { return true } -// removeOpcodeByData will return the script minus any opcodes that would push -// the passed data to the stack. -// -// DEPRECATED. Use removeOpcodeByDataRaw instead. -func removeOpcodeByData(pkscript []parsedOpcode, data []byte) []parsedOpcode { - retScript := make([]parsedOpcode, 0, len(pkscript)) - for _, pop := range pkscript { - if !isCanonicalPush(pop.opcode.value, pop.data) || - !bytes.Contains(pop.data, data) { - - retScript = append(retScript, pop) - } - } - return retScript - -} - // removeOpcodeByDataRaw will return the script minus any opcodes that perform a // canonical push of data that contains the passed data to remove. This // function assumes it is provided a version 0 script as any future version of From 911db90858acff024c54715b5336c95285e695ae Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:13:00 -0500 Subject: [PATCH 0565/1056] txscript: Rename removeOpcodeByDataRaw func. This renames the removeOpcodeByDataRaw to removeOpcodeByData now that the old version has been removed. --- txscript/opcode.go | 4 ++-- txscript/script.go | 4 ++-- txscript/script_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 950121c69d..1d8ee25ea8 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -2063,7 +2063,7 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error { } else { // Remove the signature since there is no way for a signature // to sign itself. - subScript = removeOpcodeByDataRaw(subScript, fullSigBytes) + subScript = removeOpcodeByData(subScript, fullSigBytes) hash = calcSignatureHashRaw(subScript, hashType, &vm.tx, vm.txIdx) } @@ -2236,7 +2236,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { // no way for a signature to sign itself. if !vm.isWitnessVersionActive(0) { for _, sigInfo := range signatures { - script = removeOpcodeByDataRaw(script, sigInfo.signature) + script = removeOpcodeByData(script, sigInfo.signature) } } diff --git a/txscript/script.go b/txscript/script.go index 242fc2d875..266c36ddce 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -318,7 +318,7 @@ func isCanonicalPush(opcode byte, data []byte) bool { return true } -// removeOpcodeByDataRaw will return the script minus any opcodes that perform a +// removeOpcodeByData will return the script minus any opcodes that perform a // canonical push of data that contains the passed data to remove. This // function assumes it is provided a version 0 script as any future version of // script should avoid this functionality since it is unncessary due to the @@ -332,7 +332,7 @@ func isCanonicalPush(opcode byte, data []byte) bool { // NOTE: This function is only valid for version 0 scripts. Since the function // does not accept a script version, the results are undefined for other script // versions. -func removeOpcodeByDataRaw(script []byte, dataToRemove []byte) []byte { +func removeOpcodeByData(script []byte, dataToRemove []byte) []byte { // Avoid work when possible. if len(script) == 0 || len(dataToRemove) == 0 { return script diff --git a/txscript/script_test.go b/txscript/script_test.go index 02c364ce31..7db065de44 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -4136,7 +4136,7 @@ func TestRemoveOpcodeByData(t *testing.T) { return nil, err } - return removeOpcodeByDataRaw(script, data), nil + return removeOpcodeByData(script, data), nil } for _, test := range tests { From 94e99cf6b7d572ebe46eebc79d04a4a2cb071001 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:07:18 -0700 Subject: [PATCH 0566/1056] txscript: Rename calcSignatureHashRaw --- txscript/opcode.go | 4 ++-- txscript/script.go | 8 ++++---- txscript/sign.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 1d8ee25ea8..9e0320aed9 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -2065,7 +2065,7 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error { // to sign itself. subScript = removeOpcodeByData(subScript, fullSigBytes) - hash = calcSignatureHashRaw(subScript, hashType, &vm.tx, vm.txIdx) + hash = calcSignatureHash(subScript, hashType, &vm.tx, vm.txIdx) } pubKey, err := btcec.ParsePubKey(pkBytes, btcec.S256()) @@ -2334,7 +2334,7 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { return err } } else { - hash = calcSignatureHashRaw(script, hashType, &vm.tx, vm.txIdx) + hash = calcSignatureHash(script, hashType, &vm.tx, vm.txIdx) } var valid bool diff --git a/txscript/script.go b/txscript/script.go index 266c36ddce..2e3431d025 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -618,12 +618,12 @@ func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx return nil, err } - return calcSignatureHashRaw(script, hashType, tx, idx), nil + return calcSignatureHash(script, hashType, tx, idx), nil } -// calcSignatureHashRaw computes the signature hash for the specified input of -// the target transaction observing the desired signature hash type. -func calcSignatureHashRaw(sigScript []byte, hashType SigHashType, tx *wire.MsgTx, idx int) []byte { +// calcSignatureHash computes the signature hash for the specified input of the +// target transaction observing the desired signature hash type. +func calcSignatureHash(sigScript []byte, hashType SigHashType, tx *wire.MsgTx, idx int) []byte { // The SigHashSingle signature type signs only the corresponding input // and output (the output with the same index number as the input). // diff --git a/txscript/sign.go b/txscript/sign.go index 4d63a9b245..51c69103cf 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -285,7 +285,7 @@ sigLoop: // however, assume no sigs etc are in the script since that // would make the transaction nonstandard and thus not // MultiSigTy, so we just need to hash the full thing. - hash := calcSignatureHashRaw(pkScript, hashType, tx, idx) + hash := calcSignatureHash(pkScript, hashType, tx, idx) for _, addr := range addresses { // All multisig addresses should be pubkey addresses From 69f3a39c1c96ba024ed332dd12f86f8f5cf7ba33 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:10:48 -0700 Subject: [PATCH 0567/1056] txscript/sign: Use calcWitnessSigHashRaw for witness sigs --- txscript/sign.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/txscript/sign.go b/txscript/sign.go index 51c69103cf..138e31cdd4 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -22,12 +22,7 @@ func RawTxInWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64, subScript []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { - parsedScript, err := parseScript(subScript) - if err != nil { - return nil, fmt.Errorf("cannot parse output script: %v", err) - } - - hash, err := calcWitnessSignatureHash(parsedScript, sigHashes, hashType, tx, + hash, err := calcWitnessSignatureHashRaw(subScript, sigHashes, hashType, tx, idx, amt) if err != nil { return nil, err From 753367299342906c9323cf94a14b151f282c9e4a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:31:33 -0700 Subject: [PATCH 0568/1056] txscript/pkscript: Use finalOpcodeData to extract redeem script --- txscript/pkscript.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/txscript/pkscript.go b/txscript/pkscript.go index 0703ef5d05..f5b11e6d53 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -211,11 +211,12 @@ func computeNonWitnessPkScript(sigScript []byte) (PkScript, error) { // The redeem script will always be the last data push of the // signature script, so we'll parse the script into opcodes to // obtain it. - parsedOpcodes, err := parseScript(sigScript) + const scriptVersion = 0 + err := checkScriptParses(scriptVersion, sigScript) if err != nil { return PkScript{}, err } - redeemScript := parsedOpcodes[len(parsedOpcodes)-1].data + redeemScript := finalOpcodeData(scriptVersion, sigScript) scriptHash := hash160(redeemScript) script, err := payToScriptHashScript(scriptHash) From 6e5fbf8ea85ca1689d00421f2966436166c2e072 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:13:03 -0500 Subject: [PATCH 0569/1056] txscript: Remove unused parseScript func. --- txscript/script.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 2e3431d025..1a8890b914 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -202,12 +202,6 @@ func checkScriptTemplateParseable(script []byte, opcodes *[256]opcode) (*byte, e return &firstOpcode, nil } -// parseScript preparses the script in bytes into a list of parsedOpcodes while -// applying a number of sanity checks. -func parseScript(script []byte) ([]parsedOpcode, error) { - return parseScriptTemplate(script, &opcodeArray) -} - // unparseScript reversed the action of parseScript and returns the // parsedOpcodes as a list of bytes func unparseScript(pops []parsedOpcode) ([]byte, error) { From e06b11a999da91b6e0179795def1f2ee67e3b159 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 19 Apr 2019 19:48:25 -0700 Subject: [PATCH 0570/1056] txscript: Remove unused calcWitnessSignatureHash --- txscript/script.go | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 1a8890b914..97c2f40102 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -534,30 +534,6 @@ func calcWitnessSignatureHashRaw(scriptSig []byte, sigHashes *TxSigHashes, return chainhash.DoubleHashB(sigHash.Bytes()), nil } -// calcWitnessSignatureHash computes the sighash digest of a transaction's -// segwit input using the new, optimized digest calculation algorithm defined -// in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. -// This function makes use of pre-calculated sighash fragments stored within -// the passed HashCache to eliminate duplicate hashing computations when -// calculating the final digest, reducing the complexity from O(N^2) to O(N). -// Additionally, signatures now cover the input value of the referenced unspent -// output. This allows offline, or hardware wallets to compute the exact amount -// being spent, in addition to the final transaction fee. In the case the -// wallet if fed an invalid input amount, the real sighash will differ causing -// the produced signature to be invalid. -// -// DEPRECATED: Use calcWitnessSignatureHashRaw instead. -func calcWitnessSignatureHash(subScript []parsedOpcode, sigHashes *TxSigHashes, - hashType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { - - script, err := unparseScript(subScript) - if err != nil { - return nil, err - } - - return calcWitnessSignatureHashRaw(script, sigHashes, hashType, tx, idx, amt) -} - // CalcWitnessSigHash computes the sighash digest for the specified input of // the target transaction observing the desired sig hash type. func CalcWitnessSigHash(script []byte, sigHashes *TxSigHashes, hType SigHashType, From 491b7b59fc4ad2ed8fb516a0105c2ff44a014397 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:13:04 -0500 Subject: [PATCH 0571/1056] txscript: Remove unused unparseScript func. Also remove tests associated with unparsing opcodes accordingly. --- txscript/script.go | 14 - txscript/script_test.go | 3651 --------------------------------------- 2 files changed, 3665 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index 97c2f40102..0dbe4683d7 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -202,20 +202,6 @@ func checkScriptTemplateParseable(script []byte, opcodes *[256]opcode) (*byte, e return &firstOpcode, nil } -// unparseScript reversed the action of parseScript and returns the -// parsedOpcodes as a list of bytes -func unparseScript(pops []parsedOpcode) ([]byte, error) { - script := make([]byte, 0, len(pops)) - for _, pop := range pops { - b, err := pop.bytes() - if err != nil { - return nil, err - } - script = append(script, b...) - } - return script, nil -} - // DisasmString formats a disassembled script for one line printing. When the // script fails to parse, the returned string will contain the disassembled // script up to the point the failure occurred along with the string '[error]' diff --git a/txscript/script_test.go b/txscript/script_test.go index 7db065de44..b6e7ff4203 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -28,3657 +28,6 @@ func TestParseOpcode(t *testing.T) { } } -// TestUnparsingInvalidOpcodes tests for errors when unparsing invalid parsed -// opcodes. -func TestUnparsingInvalidOpcodes(t *testing.T) { - tests := []struct { - name string - pop *parsedOpcode - expectedErr error - }{ - { - name: "OP_FALSE", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_FALSE], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_FALSE long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_FALSE], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_1 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_1], - data: nil, - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_1", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_1], - data: make([]byte, 1), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_1 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_1], - data: make([]byte, 2), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_2 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_2], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_2", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_2], - data: make([]byte, 2), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_2 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_2], - data: make([]byte, 3), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_3 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_3], - data: make([]byte, 2), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_3", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_3], - data: make([]byte, 3), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_3 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_3], - data: make([]byte, 4), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_4 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_4], - data: make([]byte, 3), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_4", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_4], - data: make([]byte, 4), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_4 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_4], - data: make([]byte, 5), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_5 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_5], - data: make([]byte, 4), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_5", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_5], - data: make([]byte, 5), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_5 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_5], - data: make([]byte, 6), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_6 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_6], - data: make([]byte, 5), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_6", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_6], - data: make([]byte, 6), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_6 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_6], - data: make([]byte, 7), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_7 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_7], - data: make([]byte, 6), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_7", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_7], - data: make([]byte, 7), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_7 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_7], - data: make([]byte, 8), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_8 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_8], - data: make([]byte, 7), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_8", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_8], - data: make([]byte, 8), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_8 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_8], - data: make([]byte, 9), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_9 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_9], - data: make([]byte, 8), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_9", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_9], - data: make([]byte, 9), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_9 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_9], - data: make([]byte, 10), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_10 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_10], - data: make([]byte, 9), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_10", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_10], - data: make([]byte, 10), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_10 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_10], - data: make([]byte, 11), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_11 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_11], - data: make([]byte, 10), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_11", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_11], - data: make([]byte, 11), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_11 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_11], - data: make([]byte, 12), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_12 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_12], - data: make([]byte, 11), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_12", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_12], - data: make([]byte, 12), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_12 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_12], - data: make([]byte, 13), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_13 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_13], - data: make([]byte, 12), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_13", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_13], - data: make([]byte, 13), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_13 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_13], - data: make([]byte, 14), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_14 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_14], - data: make([]byte, 13), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_14", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_14], - data: make([]byte, 14), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_14 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_14], - data: make([]byte, 15), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_15 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_15], - data: make([]byte, 14), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_15", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_15], - data: make([]byte, 15), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_15 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_15], - data: make([]byte, 16), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_16 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_16], - data: make([]byte, 15), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_16", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_16], - data: make([]byte, 16), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_16 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_16], - data: make([]byte, 17), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_17 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_17], - data: make([]byte, 16), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_17", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_17], - data: make([]byte, 17), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_17 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_17], - data: make([]byte, 18), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_18 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_18], - data: make([]byte, 17), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_18", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_18], - data: make([]byte, 18), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_18 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_18], - data: make([]byte, 19), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_19 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_19], - data: make([]byte, 18), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_19", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_19], - data: make([]byte, 19), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_19 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_19], - data: make([]byte, 20), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_20 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_20], - data: make([]byte, 19), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_20", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_20], - data: make([]byte, 20), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_20 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_20], - data: make([]byte, 21), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_21 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_21], - data: make([]byte, 20), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_21", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_21], - data: make([]byte, 21), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_21 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_21], - data: make([]byte, 22), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_22 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_22], - data: make([]byte, 21), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_22", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_22], - data: make([]byte, 22), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_22 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_22], - data: make([]byte, 23), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_23 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_23], - data: make([]byte, 22), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_23", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_23], - data: make([]byte, 23), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_23 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_23], - data: make([]byte, 24), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_24 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_24], - data: make([]byte, 23), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_24", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_24], - data: make([]byte, 24), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_24 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_24], - data: make([]byte, 25), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_25 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_25], - data: make([]byte, 24), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_25", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_25], - data: make([]byte, 25), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_25 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_25], - data: make([]byte, 26), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_26 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_26], - data: make([]byte, 25), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_26", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_26], - data: make([]byte, 26), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_26 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_26], - data: make([]byte, 27), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_27 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_27], - data: make([]byte, 26), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_27", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_27], - data: make([]byte, 27), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_27 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_27], - data: make([]byte, 28), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_28 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_28], - data: make([]byte, 27), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_28", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_28], - data: make([]byte, 28), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_28 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_28], - data: make([]byte, 29), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_29 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_29], - data: make([]byte, 28), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_29", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_29], - data: make([]byte, 29), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_29 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_29], - data: make([]byte, 30), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_30 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_30], - data: make([]byte, 29), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_30", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_30], - data: make([]byte, 30), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_30 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_30], - data: make([]byte, 31), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_31 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_31], - data: make([]byte, 30), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_31", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_31], - data: make([]byte, 31), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_31 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_31], - data: make([]byte, 32), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_32 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_32], - data: make([]byte, 31), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_32", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_32], - data: make([]byte, 32), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_32 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_32], - data: make([]byte, 33), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_33 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_33], - data: make([]byte, 32), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_33", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_33], - data: make([]byte, 33), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_33 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_33], - data: make([]byte, 34), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_34 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_34], - data: make([]byte, 33), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_34", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_34], - data: make([]byte, 34), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_34 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_34], - data: make([]byte, 35), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_35 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_35], - data: make([]byte, 34), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_35", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_35], - data: make([]byte, 35), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_35 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_35], - data: make([]byte, 36), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_36 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_36], - data: make([]byte, 35), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_36", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_36], - data: make([]byte, 36), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_36 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_36], - data: make([]byte, 37), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_37 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_37], - data: make([]byte, 36), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_37", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_37], - data: make([]byte, 37), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_37 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_37], - data: make([]byte, 38), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_38 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_38], - data: make([]byte, 37), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_38", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_38], - data: make([]byte, 38), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_38 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_38], - data: make([]byte, 39), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_39 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_39], - data: make([]byte, 38), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_39", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_39], - data: make([]byte, 39), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_39 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_39], - data: make([]byte, 40), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_40 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_40], - data: make([]byte, 39), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_40", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_40], - data: make([]byte, 40), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_40 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_40], - data: make([]byte, 41), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_41 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_41], - data: make([]byte, 40), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_41", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_41], - data: make([]byte, 41), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_41 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_41], - data: make([]byte, 42), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_42 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_42], - data: make([]byte, 41), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_42", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_42], - data: make([]byte, 42), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_42 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_42], - data: make([]byte, 43), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_43 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_43], - data: make([]byte, 42), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_43", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_43], - data: make([]byte, 43), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_43 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_43], - data: make([]byte, 44), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_44 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_44], - data: make([]byte, 43), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_44", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_44], - data: make([]byte, 44), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_44 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_44], - data: make([]byte, 45), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_45 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_45], - data: make([]byte, 44), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_45", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_45], - data: make([]byte, 45), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_45 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_45], - data: make([]byte, 46), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_46 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_46], - data: make([]byte, 45), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_46", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_46], - data: make([]byte, 46), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_46 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_46], - data: make([]byte, 47), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_47 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_47], - data: make([]byte, 46), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_47", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_47], - data: make([]byte, 47), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_47 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_47], - data: make([]byte, 48), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_48 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_48], - data: make([]byte, 47), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_48", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_48], - data: make([]byte, 48), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_48 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_48], - data: make([]byte, 49), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_49 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_49], - data: make([]byte, 48), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_49", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_49], - data: make([]byte, 49), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_49 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_49], - data: make([]byte, 50), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_50 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_50], - data: make([]byte, 49), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_50", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_50], - data: make([]byte, 50), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_50 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_50], - data: make([]byte, 51), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_51 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_51], - data: make([]byte, 50), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_51", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_51], - data: make([]byte, 51), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_51 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_51], - data: make([]byte, 52), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_52 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_52], - data: make([]byte, 51), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_52", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_52], - data: make([]byte, 52), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_52 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_52], - data: make([]byte, 53), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_53 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_53], - data: make([]byte, 52), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_53", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_53], - data: make([]byte, 53), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_53 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_53], - data: make([]byte, 54), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_54 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_54], - data: make([]byte, 53), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_54", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_54], - data: make([]byte, 54), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_54 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_54], - data: make([]byte, 55), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_55 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_55], - data: make([]byte, 54), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_55", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_55], - data: make([]byte, 55), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_55 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_55], - data: make([]byte, 56), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_56 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_56], - data: make([]byte, 55), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_56", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_56], - data: make([]byte, 56), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_56 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_56], - data: make([]byte, 57), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_57 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_57], - data: make([]byte, 56), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_57", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_57], - data: make([]byte, 57), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_57 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_57], - data: make([]byte, 58), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_58 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_58], - data: make([]byte, 57), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_58", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_58], - data: make([]byte, 58), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_58 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_58], - data: make([]byte, 59), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_59 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_59], - data: make([]byte, 58), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_59", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_59], - data: make([]byte, 59), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_59 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_59], - data: make([]byte, 60), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_60 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_60], - data: make([]byte, 59), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_60", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_60], - data: make([]byte, 60), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_60 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_60], - data: make([]byte, 61), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_61 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_61], - data: make([]byte, 60), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_61", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_61], - data: make([]byte, 61), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_61 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_61], - data: make([]byte, 62), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_62 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_62], - data: make([]byte, 61), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_62", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_62], - data: make([]byte, 62), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_62 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_62], - data: make([]byte, 63), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_63 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_63], - data: make([]byte, 62), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_63", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_63], - data: make([]byte, 63), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_63 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_63], - data: make([]byte, 64), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_64 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_64], - data: make([]byte, 63), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_64", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_64], - data: make([]byte, 64), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_64 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_64], - data: make([]byte, 65), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_65 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_65], - data: make([]byte, 64), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_65", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_65], - data: make([]byte, 65), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_65 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_65], - data: make([]byte, 66), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_66 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_66], - data: make([]byte, 65), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_66", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_66], - data: make([]byte, 66), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_66 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_66], - data: make([]byte, 67), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_67 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_67], - data: make([]byte, 66), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_67", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_67], - data: make([]byte, 67), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_67 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_67], - data: make([]byte, 68), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_68 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_68], - data: make([]byte, 67), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_68", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_68], - data: make([]byte, 68), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_68 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_68], - data: make([]byte, 69), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_69 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_69], - data: make([]byte, 68), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_69", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_69], - data: make([]byte, 69), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_69 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_69], - data: make([]byte, 70), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_70 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_70], - data: make([]byte, 69), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_70", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_70], - data: make([]byte, 70), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_70 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_70], - data: make([]byte, 71), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_71 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_71], - data: make([]byte, 70), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_71", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_71], - data: make([]byte, 71), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_71 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_71], - data: make([]byte, 72), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_72 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_72], - data: make([]byte, 71), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_72", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_72], - data: make([]byte, 72), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_72 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_72], - data: make([]byte, 73), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_73 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_73], - data: make([]byte, 72), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_73", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_73], - data: make([]byte, 73), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_73 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_73], - data: make([]byte, 74), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_74 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_74], - data: make([]byte, 73), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_74", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_74], - data: make([]byte, 74), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_74 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_74], - data: make([]byte, 75), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_75 short", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_75], - data: make([]byte, 74), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DATA_75", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_75], - data: make([]byte, 75), - }, - expectedErr: nil, - }, - { - name: "OP_DATA_75 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DATA_75], - data: make([]byte, 76), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_PUSHDATA1", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PUSHDATA1], - data: []byte{0, 1, 2, 3, 4}, - }, - expectedErr: nil, - }, - { - name: "OP_PUSHDATA2", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PUSHDATA2], - data: []byte{0, 1, 2, 3, 4}, - }, - expectedErr: nil, - }, - { - name: "OP_PUSHDATA4", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PUSHDATA1], - data: []byte{0, 1, 2, 3, 4}, - }, - expectedErr: nil, - }, - { - name: "OP_1NEGATE", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_1NEGATE], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_1NEGATE long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_1NEGATE], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_RESERVED", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RESERVED], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_RESERVED long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RESERVED], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_TRUE", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_TRUE], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_TRUE long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_TRUE], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_3", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_3], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_3 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_3], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_4", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_4], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_4 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_4], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_5", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_5], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_5 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_5], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_6", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_6], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_6 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_6], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_7", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_7], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_7 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_7], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_8", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_8], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_8 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_8], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_9", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_9], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_9 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_9], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_10", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_10], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_10 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_10], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_11", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_11], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_11 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_11], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_12", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_12], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_12 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_12], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_13", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_13], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_13 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_13], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_14", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_14], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_14 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_14], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_15", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_15], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_15 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_15], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_16", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_16], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_16 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_16], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_VER", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VER], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_VER long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VER], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_IF", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_IF], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_IF long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_IF], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOTIF", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOTIF], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOTIF long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOTIF], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_VERIF", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VERIF], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_VERIF long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VERIF], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_VERNOTIF", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VERNOTIF], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_VERNOTIF long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VERNOTIF], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_ELSE", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ELSE], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_ELSE long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ELSE], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_ENDIF", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ENDIF], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_ENDIF long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ENDIF], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_VERIFY", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VERIFY], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_VERIFY long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_VERIFY], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_RETURN", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RETURN], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_RETURN long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RETURN], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_TOALTSTACK", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_TOALTSTACK], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_TOALTSTACK long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_TOALTSTACK], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_FROMALTSTACK", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_FROMALTSTACK], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_FROMALTSTACK long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_FROMALTSTACK], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2DROP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2DROP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2DROP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2DROP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2DUP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2DUP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2DUP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2DUP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_3DUP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_3DUP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_3DUP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_3DUP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2OVER", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2OVER], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2OVER long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2OVER], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2ROT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2ROT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2ROT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2ROT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2SWAP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2SWAP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2SWAP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2SWAP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_IFDUP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_IFDUP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_IFDUP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_IFDUP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DEPTH", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DEPTH], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_DEPTH long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DEPTH], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DROP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DROP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_DROP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DROP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DUP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DUP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_DUP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DUP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NIP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NIP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NIP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NIP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_OVER", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_OVER], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_OVER long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_OVER], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_PICK", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PICK], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_PICK long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PICK], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_ROLL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ROLL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_ROLL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ROLL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_ROT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ROT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_ROT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ROT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_SWAP", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SWAP], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_SWAP long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SWAP], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_TUCK", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_TUCK], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_TUCK long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_TUCK], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_CAT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CAT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_CAT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CAT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_SUBSTR", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SUBSTR], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_SUBSTR long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SUBSTR], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_LEFT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LEFT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_LEFT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LEFT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_LEFT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LEFT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_LEFT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LEFT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_RIGHT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RIGHT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_RIGHT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RIGHT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_SIZE", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SIZE], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_SIZE long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SIZE], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_INVERT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_INVERT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_INVERT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_INVERT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_AND", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_AND], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_AND long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_AND], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_OR", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_OR], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_OR long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_OR], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_XOR", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_XOR], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_XOR long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_XOR], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_EQUAL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_EQUAL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_EQUAL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_EQUAL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_EQUALVERIFY", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_EQUALVERIFY], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_EQUALVERIFY long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_EQUALVERIFY], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_RESERVED1", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RESERVED1], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_RESERVED1 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RESERVED1], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_RESERVED2", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RESERVED2], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_RESERVED2 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RESERVED2], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_1ADD", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_1ADD], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_1ADD long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_1ADD], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_1SUB", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_1SUB], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_1SUB long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_1SUB], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2MUL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2MUL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2MUL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2MUL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_2DIV", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2DIV], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_2DIV long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_2DIV], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NEGATE", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NEGATE], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NEGATE long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NEGATE], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_ABS", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ABS], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_ABS long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ABS], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_0NOTEQUAL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_0NOTEQUAL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_0NOTEQUAL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_0NOTEQUAL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_ADD", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ADD], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_ADD long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_ADD], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_SUB", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SUB], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_SUB long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SUB], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_MUL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MUL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_MUL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MUL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_DIV", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DIV], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_DIV long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_DIV], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_MOD", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MOD], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_MOD long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MOD], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_LSHIFT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LSHIFT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_LSHIFT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LSHIFT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_RSHIFT", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RSHIFT], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_RSHIFT long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RSHIFT], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_BOOLAND", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_BOOLAND], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_BOOLAND long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_BOOLAND], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_BOOLOR", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_BOOLOR], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_BOOLOR long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_BOOLOR], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NUMEQUAL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NUMEQUAL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NUMEQUAL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NUMEQUAL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NUMEQUALVERIFY", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NUMEQUALVERIFY], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NUMEQUALVERIFY long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NUMEQUALVERIFY], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NUMNOTEQUAL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NUMNOTEQUAL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NUMNOTEQUAL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NUMNOTEQUAL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_LESSTHAN", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LESSTHAN], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_LESSTHAN long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LESSTHAN], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_GREATERTHAN", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_GREATERTHAN], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_GREATERTHAN long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_GREATERTHAN], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_LESSTHANOREQUAL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LESSTHANOREQUAL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_LESSTHANOREQUAL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_LESSTHANOREQUAL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_GREATERTHANOREQUAL", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_GREATERTHANOREQUAL], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_GREATERTHANOREQUAL long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_GREATERTHANOREQUAL], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_MIN", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MIN], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_MIN long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MIN], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_MAX", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MAX], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_MAX long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_MAX], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_WITHIN", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_WITHIN], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_WITHIN long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_WITHIN], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_RIPEMD160", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RIPEMD160], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_RIPEMD160 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_RIPEMD160], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_SHA1", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SHA1], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_SHA1 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SHA1], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_SHA256", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SHA256], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_SHA256 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_SHA256], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_HASH160", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_HASH160], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_HASH160 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_HASH160], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_HASH256", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_HASH256], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_HASH256 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_HASH256], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_CODESAPERATOR", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CODESEPARATOR], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_CODESEPARATOR long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CODESEPARATOR], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_CHECKSIG", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKSIG], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_CHECKSIG long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKSIG], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_CHECKSIGVERIFY", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKSIGVERIFY], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_CHECKSIGVERIFY long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKSIGVERIFY], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_CHECKMULTISIG", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKMULTISIG], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_CHECKMULTISIG long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKMULTISIG], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_CHECKMULTISIGVERIFY", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKMULTISIGVERIFY], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_CHECKMULTISIGVERIFY long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_CHECKMULTISIGVERIFY], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP1", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP1], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP1 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP1], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP2", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP2], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP2 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP2], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP3", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP3], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP3 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP3], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP4", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP4], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP4 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP4], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP5", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP5], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP5 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP5], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP6", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP6], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP6 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP6], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP7", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP7], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP7 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP7], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP8", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP8], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP8 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP8], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP9", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP9], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP9 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP9], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_NOP10", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP10], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_NOP10 long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_NOP10], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_PUBKEYHASH", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PUBKEYHASH], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_PUBKEYHASH long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PUBKEYHASH], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_PUBKEY", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PUBKEY], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_PUBKEY long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_PUBKEY], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - { - name: "OP_INVALIDOPCODE", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_INVALIDOPCODE], - data: nil, - }, - expectedErr: nil, - }, - { - name: "OP_INVALIDOPCODE long", - pop: &parsedOpcode{ - opcode: &opcodeArray[OP_INVALIDOPCODE], - data: make([]byte, 1), - }, - expectedErr: scriptError(ErrInternal, ""), - }, - } - - for _, test := range tests { - _, err := test.pop.bytes() - if e := tstCheckScriptError(err, test.expectedErr); e != nil { - t.Errorf("Parsed opcode test '%s': %v", test.name, e) - continue - } - } -} - // TestPushedData ensured the PushedData function extracts the expected data out // of various scripts. func TestPushedData(t *testing.T) { From ca044fefcb80f4cc0ed966895ea390d4d956cd5d Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:13:05 -0500 Subject: [PATCH 0572/1056] txscript: Remove unused parsedOpcode.bytes func. --- txscript/opcode.go | 57 ---------------------------------------------- 1 file changed, 57 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 9e0320aed9..515e1cf2b1 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -8,7 +8,6 @@ import ( "bytes" "crypto/sha1" "crypto/sha256" - "encoding/binary" "encoding/hex" "fmt" "hash" @@ -740,62 +739,6 @@ func disasmOpcode(buf *strings.Builder, op *opcode, data []byte, compact bool) { buf.WriteString(fmt.Sprintf(" 0x%02x", data)) } -// bytes returns any data associated with the opcode encoded as it would be in -// a script. This is used for unparsing scripts from parsed opcodes. -func (pop *parsedOpcode) bytes() ([]byte, error) { - var retbytes []byte - if pop.opcode.length > 0 { - retbytes = make([]byte, 1, pop.opcode.length) - } else { - retbytes = make([]byte, 1, 1+len(pop.data)- - pop.opcode.length) - } - - retbytes[0] = pop.opcode.value - if pop.opcode.length == 1 { - if len(pop.data) != 0 { - str := fmt.Sprintf("internal consistency error - "+ - "parsed opcode %s has data length %d when %d "+ - "was expected", pop.opcode.name, len(pop.data), - 0) - return nil, scriptError(ErrInternal, str) - } - return retbytes, nil - } - nbytes := pop.opcode.length - if pop.opcode.length < 0 { - l := len(pop.data) - // tempting just to hardcode to avoid the complexity here. - switch pop.opcode.length { - case -1: - retbytes = append(retbytes, byte(l)) - nbytes = int(retbytes[1]) + len(retbytes) - case -2: - retbytes = append(retbytes, byte(l&0xff), - byte(l>>8&0xff)) - nbytes = int(binary.LittleEndian.Uint16(retbytes[1:])) + - len(retbytes) - case -4: - retbytes = append(retbytes, byte(l&0xff), - byte((l>>8)&0xff), byte((l>>16)&0xff), - byte((l>>24)&0xff)) - nbytes = int(binary.LittleEndian.Uint32(retbytes[1:])) + - len(retbytes) - } - } - - retbytes = append(retbytes, pop.data...) - - if len(retbytes) != nbytes { - str := fmt.Sprintf("internal consistency error - "+ - "parsed opcode %s has data length %d when %d was "+ - "expected", pop.opcode.name, len(retbytes), nbytes) - return nil, scriptError(ErrInternal, str) - } - - return retbytes, nil -} - // ******************************************* // Opcode implementation functions start here. // ******************************************* From 595d379fa6c1a588b9e3f58210132da6c6de3825 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:13:06 -0500 Subject: [PATCH 0573/1056] txscript: Remove unused parseScriptTemplate func. Also remove tests associated with the func accordingly. --- txscript/opcode.go | 73 ----------------------------------------- txscript/script.go | 59 --------------------------------- txscript/script_test.go | 16 --------- 3 files changed, 148 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 515e1cf2b1..d6fc494c89 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -618,79 +618,6 @@ type parsedOpcode struct { data []byte } -// checkParseableInScript checks whether or not the current opcode is able to be -// parsed at a certain position in a script. -// This returns the position of the next opcode to be parsed in the script. -func (pop *parsedOpcode) checkParseableInScript(script []byte, scriptPos int) (int, error) { - // Parse data out of instruction. - switch { - // No additional data. Note that some of the opcodes, notably - // OP_1NEGATE, OP_0, and OP_[1-16] represent the data - // themselves. - case pop.opcode.length == 1: - scriptPos++ - - // Data pushes of specific lengths -- OP_DATA_[1-75]. - case pop.opcode.length > 1: - if len(script[scriptPos:]) < pop.opcode.length { - str := fmt.Sprintf("opcode %s requires %d "+ - "bytes, but script only has %d remaining", - pop.opcode.name, pop.opcode.length, len(script[scriptPos:])) - return 0, scriptError(ErrMalformedPush, str) - } - - // Slice out the data. - pop.data = script[scriptPos+1 : scriptPos+pop.opcode.length] - scriptPos += pop.opcode.length - - // Data pushes with parsed lengths -- OP_PUSHDATAP{1,2,4}. - case pop.opcode.length < 0: - var l uint - off := scriptPos + 1 - - if len(script[off:]) < -pop.opcode.length { - str := fmt.Sprintf("opcode %s requires %d "+ - "bytes, but script only has %d remaining", - pop.opcode.name, -pop.opcode.length, len(script[off:])) - return 0, scriptError(ErrMalformedPush, str) - } - - // Next -length bytes are little endian length of data. - switch pop.opcode.length { - case -1: - l = uint(script[off]) - case -2: - l = ((uint(script[off+1]) << 8) | - uint(script[off])) - case -4: - l = ((uint(script[off+3]) << 24) | - (uint(script[off+2]) << 16) | - (uint(script[off+1]) << 8) | - uint(script[off])) - default: - str := fmt.Sprintf("invalid opcode length %d", - pop.opcode.length) - return 0, scriptError(ErrMalformedPush, str) - } - - // Move offset to beginning of the data. - off += -pop.opcode.length - - // Disallow entries that do not fit script or were - // sign extended. - if int(l) > len(script[off:]) || int(l) < 0 { - str := fmt.Sprintf("opcode %s pushes %d bytes, "+ - "but script only has %d remaining", - pop.opcode.name, int(l), len(script[off:])) - return 0, scriptError(ErrMalformedPush, str) - } - - pop.data = script[off : off+int(l)] - scriptPos += 1 - pop.opcode.length + int(l) - } - return scriptPos, nil -} - // disasmOpcode writes a human-readable disassembly of the provided opcode and // data into the provided buffer. The compact flag indicates the disassembly // should print a more compact representation of data-carrying and small integer diff --git a/txscript/script.go b/txscript/script.go index 0dbe4683d7..696bfe2d17 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -143,65 +143,6 @@ func IsPushOnlyScript(script []byte) bool { return tokenizer.Err() == nil } -// parseScriptTemplate is the same as parseScript but allows the passing of the -// template list for testing purposes. When there are parse errors, it returns -// the list of parsed opcodes up to the point of failure along with the error. -func parseScriptTemplate(script []byte, opcodes *[256]opcode) ([]parsedOpcode, error) { - retScript := make([]parsedOpcode, 0, len(script)) - var err error - for i := 0; i < len(script); { - instr := script[i] - op := &opcodes[instr] - pop := parsedOpcode{opcode: op} - i, err = pop.checkParseableInScript(script, i) - if err != nil { - return retScript, err - } - - retScript = append(retScript, pop) - } - - return retScript, nil -} - -// checkScriptTemplateParseable is the same as parseScriptTemplate but does not -// return the list of opcodes up until the point of failure so that this can be -// used in functions which do not necessarily have a need for the failed list of -// opcodes, such as IsUnspendable. -// -// This function returns a pointer to a byte. This byte is nil if the parsing -// has an error, or if the script length is zero. If the script length is not -// zero and parsing succeeds, then the first opcode parsed will be returned. -// -// Not returning the full opcode list up until failure also has the benefit of -// reducing GC pressure, as the list would get immediately thrown away. -func checkScriptTemplateParseable(script []byte, opcodes *[256]opcode) (*byte, error) { - var err error - - // A script of length zero is an unspendable script but it is parseable. - var firstOpcode byte - var numParsedInstr uint = 0 - - for i := 0; i < len(script); { - instr := script[i] - op := &opcodes[instr] - pop := parsedOpcode{opcode: op} - i, err = pop.checkParseableInScript(script, i) - if err != nil { - return nil, err - } - - // if this is a op_return then it is unspendable so we set the first - // parsed instruction in case it's an op_return - if numParsedInstr == 0 { - firstOpcode = pop.opcode.value - } - numParsedInstr++ - } - - return &firstOpcode, nil -} - // DisasmString formats a disassembled script for one line printing. When the // script fails to parse, the returned string will contain the disassembled // script up to the point the failure occurred along with the string '[error]' diff --git a/txscript/script_test.go b/txscript/script_test.go index b6e7ff4203..86f94d84f4 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -12,22 +12,6 @@ import ( "github.com/btcsuite/btcd/wire" ) -// TestParseOpcode tests for opcode parsing with bad data templates. -func TestParseOpcode(t *testing.T) { - // Deep copy the array and make one of the opcodes invalid by setting it - // to the wrong length. - fakeArray := opcodeArray - fakeArray[OP_PUSHDATA4] = opcode{value: OP_PUSHDATA4, - name: "OP_PUSHDATA4", length: -8, opfunc: opcodePushData} - - // This script would be fine if -8 was a valid length. - _, err := parseScriptTemplate([]byte{OP_PUSHDATA4, 0x1, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00}, &fakeArray) - if err == nil { - t.Errorf("no error with dodgy opcode array!") - } -} - // TestPushedData ensured the PushedData function extracts the expected data out // of various scripts. func TestPushedData(t *testing.T) { From ef3d06e62b76818163e8302384afcdb44874cf46 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:13:07 -0500 Subject: [PATCH 0574/1056] txscript: Make executeOpcode take opcode and data. This converts the executeOpcode function defined on the engine to accept an opcode and data slice instead of a parsed opcode as a step towards removing the parsed opcode struct and associated supporting code altogether. It also updates all callers accordingly. --- txscript/engine.go | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 1afb8324dd..a91dc9612f 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -341,23 +341,21 @@ func checkMinimalDataPush(op *opcode, data []byte) error { // executeOpcode peforms execution on the passed opcode. It takes into account // whether or not it is hidden by conditionals, but some rules still must be // tested in this case. -func (vm *Engine) executeOpcode(pop *parsedOpcode) error { +func (vm *Engine) executeOpcode(op *opcode, data []byte) error { // Disabled opcodes are fail on program counter. - if isOpcodeDisabled(pop.opcode.value) { - str := fmt.Sprintf("attempt to execute disabled opcode %s", - pop.opcode.name) + if isOpcodeDisabled(op.value) { + str := fmt.Sprintf("attempt to execute disabled opcode %s", op.name) return scriptError(ErrDisabledOpcode, str) } // Always-illegal opcodes are fail on program counter. - if isOpcodeAlwaysIllegal(pop.opcode.value) { - str := fmt.Sprintf("attempt to execute reserved opcode %s", - pop.opcode.name) + if isOpcodeAlwaysIllegal(op.value) { + str := fmt.Sprintf("attempt to execute reserved opcode %s", op.name) return scriptError(ErrReservedOpcode, str) } // Note that this includes OP_RESERVED which counts as a push operation. - if pop.opcode.value > OP_16 { + if op.value > OP_16 { vm.numOps++ if vm.numOps > MaxOpsPerScript { str := fmt.Sprintf("exceeded max operation limit of %d", @@ -365,29 +363,30 @@ func (vm *Engine) executeOpcode(pop *parsedOpcode) error { return scriptError(ErrTooManyOperations, str) } - } else if len(pop.data) > MaxScriptElementSize { + } else if len(data) > MaxScriptElementSize { str := fmt.Sprintf("element size %d exceeds max allowed size %d", - len(pop.data), MaxScriptElementSize) + len(data), MaxScriptElementSize) return scriptError(ErrElementTooBig, str) } // Nothing left to do when this is not a conditional opcode and it is // not in an executing branch. - if !vm.isBranchExecuting() && !isOpcodeConditional(pop.opcode.value) { + if !vm.isBranchExecuting() && !isOpcodeConditional(op.value) { return nil } // Ensure all executed data push opcodes use the minimal encoding when // the minimal data verification flag is set. if vm.dstack.verifyMinimalData && vm.isBranchExecuting() && - pop.opcode.value >= 0 && pop.opcode.value <= OP_PUSHDATA4 { + op.value >= 0 && op.value <= OP_PUSHDATA4 { - if err := checkMinimalDataPush(pop.opcode, pop.data); err != nil { + if err := checkMinimalDataPush(op, data); err != nil { return err } } - return pop.opcode.opfunc(pop, vm) + pop := parsedOpcode{opcode: op, data: data} + return op.opfunc(&pop, vm) } // checkValidPC returns an error if the current script position is not valid for @@ -670,8 +669,7 @@ func (vm *Engine) Step() (done bool, err error) { // Execute the opcode while taking into account several things such as // disabled opcodes, illegal opcodes, maximum allowed operations per script, // maximum script element sizes, and conditionals. - pop := parsedOpcode{opcode: vm.tokenizer.op, data: vm.tokenizer.Data()} - err = vm.executeOpcode(&pop) + err = vm.executeOpcode(vm.tokenizer.op, vm.tokenizer.Data()) if err != nil { return true, err } From b95ba0ac95e04336f552b42864af824ba221d345 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Wed, 13 Mar 2019 01:13:08 -0500 Subject: [PATCH 0575/1056] txscript: Make op callbacks take opcode and data. This converts the callback function defined on the internal opcode struct to accept the opcode and data slice instead of a parsed opcode as the final step towards removing the parsed opcode struct and associated supporting code altogether. It also updates all of the callbacks and tests accordingly and finally removes the now unused parsedOpcode struct. The final results for the raw script analysis and tokenizer optimizations are as follows: benchmark old ns/op new ns/op delta BenchmarkIsPayToScriptHash-8 62393 0.51 -100.00% BenchmarkIsPubKeyHashScript-8 62228 0.56 -100.00% BenchmarkGetSigOpCount-8 61051 658 -98.92% BenchmarkExtractPkScriptAddrsLarge-8 60713 17.2 -99.97% BenchmarkExtractPkScriptAddrs-8 289 17.9 -93.81% BenchmarkIsWitnessPubKeyHash-8 61688 0.42 -100.00% BenchmarkIsUnspendable-8 656 520 -20.73% BenchmarkExtractAtomicSwapDataPushesLarge-8 61332 44.0 -99.93% BenchmarkExtractAtomicSwapDataPushes-8 990 260 -73.74% BenchmarkDisasmString-8 102902 39754 -61.37% BenchmarkGetPreciseSigOpCount-8 130223 715 -99.45% BenchmarkScriptParsing-8 63464 681 -98.93% BenchmarkIsMultisigScriptLarge-8 64166 5.83 -99.99% BenchmarkIsMultisigScript-8 630 58.5 -90.71% BenchmarkPushedData-8 64837 1779 -97.26% BenchmarkCalcSigHash-8 3627895 3605459 -0.62% BenchmarkIsPubKeyScript-8 62323 2.83 -100.00% BenchmarkIsPushOnlyScript-8 62412 569 -99.09% BenchmarkIsWitnessScriptHash-8 61243 0.56 -100.00% BenchmarkGetScriptClass-8 61515 16.4 -99.97% BenchmarkIsNullDataScript-8 62495 2.53 -100.00% BenchmarkIsMultisigSigScriptLarge-8 69328 2.52 -100.00% BenchmarkIsMultisigSigScript-8 2375 141 -94.06% BenchmarkGetWitnessSigOpCountP2WKH-8 504 72.0 -85.71% BenchmarkGetWitnessSigOpCountNested-8 1158 136 -88.26% BenchmarkIsWitnessPubKeyHash-8 68927 0.53 -100.00% BenchmarkIsWitnessScriptHash-8 62774 0.63 -100.00% benchmark old allocs new allocs delta BenchmarkIsPayToScriptHash-8 1 0 -100.00% BenchmarkIsPubKeyHashScript-8 1 0 -100.00% BenchmarkGetSigOpCount-8 1 0 -100.00% BenchmarkExtractPkScriptAddrsLarge-8 1 0 -100.00% BenchmarkExtractPkScriptAddrs-8 1 0 -100.00% BenchmarkIsWitnessPubKeyHash-8 1 0 -100.00% BenchmarkIsUnspendable-8 1 0 -100.00% BenchmarkExtractAtomicSwapDataPushesLarge-8 1 0 -100.00% BenchmarkExtractAtomicSwapDataPushes-8 2 1 -50.00% BenchmarkDisasmString-8 46 51 +10.87% BenchmarkGetPreciseSigOpCount-8 3 0 -100.00% BenchmarkScriptParsing-8 1 0 -100.00% BenchmarkIsMultisigScriptLarge-8 1 0 -100.00% BenchmarkIsMultisigScript-8 1 0 -100.00% BenchmarkPushedData-8 7 6 -14.29% BenchmarkCalcSigHash-8 1335 712 -46.67% BenchmarkIsPubKeyScript-8 1 0 -100.00% BenchmarkIsPushOnlyScript-8 1 0 -100.00% BenchmarkIsWitnessScriptHash-8 1 0 -100.00% BenchmarkGetScriptClass-8 1 0 -100.00% BenchmarkIsNullDataScript-8 1 0 -100.00% BenchmarkIsMultisigSigScriptLarge-8 5 0 -100.00% BenchmarkIsMultisigSigScript-8 3 0 -100.00% BenchmarkGetWitnessSigOpCountP2WKH-8 2 0 -100.00% BenchmarkGetWitnessSigOpCountNested-8 4 0 -100.00% BenchmarkIsWitnessPubKeyHash-8 1 0 -100.00% BenchmarkIsWitnessScriptHash-8 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkIsPayToScriptHash-8 311299 0 -100.00% BenchmarkIsPubKeyHashScript-8 311299 0 -100.00% BenchmarkGetSigOpCount-8 311299 0 -100.00% BenchmarkExtractPkScriptAddrsLarge-8 311299 0 -100.00% BenchmarkExtractPkScriptAddrs-8 768 0 -100.00% BenchmarkIsWitnessPubKeyHash-8 311299 0 -100.00% BenchmarkIsUnspendable-8 1 0 -100.00% BenchmarkExtractAtomicSwapDataPushesLarge-8 311299 0 -100.00% BenchmarkExtractAtomicSwapDataPushes-8 3168 96 -96.97% BenchmarkDisasmString-8 389324 130552 -66.47% BenchmarkGetPreciseSigOpCount-8 623367 0 -100.00% BenchmarkScriptParsing-8 311299 0 -100.00% BenchmarkIsMultisigScriptLarge-8 311299 0 -100.00% BenchmarkIsMultisigScript-8 2304 0 -100.00% BenchmarkPushedData-8 312816 1520 -99.51% BenchmarkCalcSigHash-8 1373812 1290507 -6.06% BenchmarkIsPubKeyScript-8 311299 0 -100.00% BenchmarkIsPushOnlyScript-8 311299 0 -100.00% BenchmarkIsWitnessScriptHash-8 311299 0 -100.00% BenchmarkGetScriptClass-8 311299 0 -100.00% BenchmarkIsNullDataScript-8 311299 0 -100.00% BenchmarkIsMultisigSigScriptLarge-8 330035 0 -100.00% BenchmarkIsMultisigSigScript-8 9472 0 -100.00% BenchmarkGetWitnessSigOpCountP2WKH-8 1408 0 -100.00% BenchmarkGetWitnessSigOpCountNested-8 3200 0 -100.00% BenchmarkIsWitnessPubKeyHash-8 311299 0 -100.00% BenchmarkIsWitnessScriptHash-8 311299 0 -100.00% --- txscript/engine.go | 3 +- txscript/opcode.go | 183 +++++++++++++++++++--------------------- txscript/opcode_test.go | 4 +- 3 files changed, 90 insertions(+), 100 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index a91dc9612f..0814e7eb96 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -385,8 +385,7 @@ func (vm *Engine) executeOpcode(op *opcode, data []byte) error { } } - pop := parsedOpcode{opcode: op, data: data} - return op.opfunc(&pop, vm) + return op.opfunc(op, data, vm) } // checkValidPC returns an error if the current script position is not valid for diff --git a/txscript/opcode.go b/txscript/opcode.go index d6fc494c89..4c31be3f75 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -28,7 +28,7 @@ type opcode struct { value byte name string length int - opfunc func(*parsedOpcode, *Engine) error + opfunc func(*opcode, []byte, *Engine) error } // These constants are the values of the official opcodes used on the btc wiki, @@ -611,13 +611,6 @@ var opcodeOnelineRepls = map[string]string{ "OP_16": "16", } -// parsedOpcode represents an opcode that has been parsed and includes any -// potential data associated with it. -type parsedOpcode struct { - opcode *opcode - data []byte -} - // disasmOpcode writes a human-readable disassembly of the provided opcode and // data into the provided buffer. The compact flag indicates the disassembly // should print a more compact representation of data-carrying and small integer @@ -676,45 +669,42 @@ func disasmOpcode(buf *strings.Builder, op *opcode, data []byte, compact bool) { // opcodes before executing in an initial parse step, the consensus rules // dictate the script doesn't fail until the program counter passes over a // disabled opcode (even when they appear in a branch that is not executed). -func opcodeDisabled(op *parsedOpcode, vm *Engine) error { - str := fmt.Sprintf("attempt to execute disabled opcode %s", - op.opcode.name) +func opcodeDisabled(op *opcode, data []byte, vm *Engine) error { + str := fmt.Sprintf("attempt to execute disabled opcode %s", op.name) return scriptError(ErrDisabledOpcode, str) } // opcodeReserved is a common handler for all reserved opcodes. It returns an // appropriate error indicating the opcode is reserved. -func opcodeReserved(op *parsedOpcode, vm *Engine) error { - str := fmt.Sprintf("attempt to execute reserved opcode %s", - op.opcode.name) +func opcodeReserved(op *opcode, data []byte, vm *Engine) error { + str := fmt.Sprintf("attempt to execute reserved opcode %s", op.name) return scriptError(ErrReservedOpcode, str) } // opcodeInvalid is a common handler for all invalid opcodes. It returns an // appropriate error indicating the opcode is invalid. -func opcodeInvalid(op *parsedOpcode, vm *Engine) error { - str := fmt.Sprintf("attempt to execute invalid opcode %s", - op.opcode.name) +func opcodeInvalid(op *opcode, data []byte, vm *Engine) error { + str := fmt.Sprintf("attempt to execute invalid opcode %s", op.name) return scriptError(ErrReservedOpcode, str) } // opcodeFalse pushes an empty array to the data stack to represent false. Note // that 0, when encoded as a number according to the numeric encoding consensus // rules, is an empty array. -func opcodeFalse(op *parsedOpcode, vm *Engine) error { +func opcodeFalse(op *opcode, data []byte, vm *Engine) error { vm.dstack.PushByteArray(nil) return nil } // opcodePushData is a common handler for the vast majority of opcodes that push // raw data (bytes) to the data stack. -func opcodePushData(op *parsedOpcode, vm *Engine) error { - vm.dstack.PushByteArray(op.data) +func opcodePushData(op *opcode, data []byte, vm *Engine) error { + vm.dstack.PushByteArray(data) return nil } // opcode1Negate pushes -1, encoded as a number, to the data stack. -func opcode1Negate(op *parsedOpcode, vm *Engine) error { +func opcode1Negate(op *opcode, data []byte, vm *Engine) error { vm.dstack.PushInt(scriptNum(-1)) return nil } @@ -722,23 +712,24 @@ func opcode1Negate(op *parsedOpcode, vm *Engine) error { // opcodeN is a common handler for the small integer data push opcodes. It // pushes the numeric value the opcode represents (which will be from 1 to 16) // onto the data stack. -func opcodeN(op *parsedOpcode, vm *Engine) error { +func opcodeN(op *opcode, data []byte, vm *Engine) error { // The opcodes are all defined consecutively, so the numeric value is // the difference. - vm.dstack.PushInt(scriptNum((op.opcode.value - (OP_1 - 1)))) + vm.dstack.PushInt(scriptNum((op.value - (OP_1 - 1)))) return nil } // opcodeNop is a common handler for the NOP family of opcodes. As the name // implies it generally does nothing, however, it will return an error when // the flag to discourage use of NOPs is set for select opcodes. -func opcodeNop(op *parsedOpcode, vm *Engine) error { - switch op.opcode.value { +func opcodeNop(op *opcode, data []byte, vm *Engine) error { + switch op.value { case OP_NOP1, OP_NOP4, OP_NOP5, OP_NOP6, OP_NOP7, OP_NOP8, OP_NOP9, OP_NOP10: + if vm.hasFlag(ScriptDiscourageUpgradableNops) { - str := fmt.Sprintf("OP_NOP%d reserved for soft-fork "+ - "upgrades", op.opcode.value-(OP_NOP1-1)) + str := fmt.Sprintf("%v reserved for soft-fork "+ + "upgrades", op.name) return scriptError(ErrDiscourageUpgradableNOPs, str) } } @@ -801,7 +792,7 @@ func popIfBool(vm *Engine) (bool, error) { // // Data stack transformation: [... bool] -> [...] // Conditional stack transformation: [...] -> [... OpCondValue] -func opcodeIf(op *parsedOpcode, vm *Engine) error { +func opcodeIf(op *opcode, data []byte, vm *Engine) error { condVal := OpCondFalse if vm.isBranchExecuting() { ok, err := popIfBool(vm) @@ -835,7 +826,7 @@ func opcodeIf(op *parsedOpcode, vm *Engine) error { // // Data stack transformation: [... bool] -> [...] // Conditional stack transformation: [...] -> [... OpCondValue] -func opcodeNotIf(op *parsedOpcode, vm *Engine) error { +func opcodeNotIf(op *opcode, data []byte, vm *Engine) error { condVal := OpCondFalse if vm.isBranchExecuting() { ok, err := popIfBool(vm) @@ -858,10 +849,10 @@ func opcodeNotIf(op *parsedOpcode, vm *Engine) error { // An error is returned if there has not already been a matching OP_IF. // // Conditional stack transformation: [... OpCondValue] -> [... !OpCondValue] -func opcodeElse(op *parsedOpcode, vm *Engine) error { +func opcodeElse(op *opcode, data []byte, vm *Engine) error { if len(vm.condStack) == 0 { str := fmt.Sprintf("encountered opcode %s with no matching "+ - "opcode to begin conditional execution", op.opcode.name) + "opcode to begin conditional execution", op.name) return scriptError(ErrUnbalancedConditional, str) } @@ -884,10 +875,10 @@ func opcodeElse(op *parsedOpcode, vm *Engine) error { // An error is returned if there has not already been a matching OP_IF. // // Conditional stack transformation: [... OpCondValue] -> [...] -func opcodeEndif(op *parsedOpcode, vm *Engine) error { +func opcodeEndif(op *opcode, data []byte, vm *Engine) error { if len(vm.condStack) == 0 { str := fmt.Sprintf("encountered opcode %s with no matching "+ - "opcode to begin conditional execution", op.opcode.name) + "opcode to begin conditional execution", op.name) return scriptError(ErrUnbalancedConditional, str) } @@ -900,14 +891,14 @@ func opcodeEndif(op *parsedOpcode, vm *Engine) error { // item on the stack or when that item evaluates to false. In the latter case // where the verification fails specifically due to the top item evaluating // to false, the returned error will use the passed error code. -func abstractVerify(op *parsedOpcode, vm *Engine, c ErrorCode) error { +func abstractVerify(op *opcode, vm *Engine, c ErrorCode) error { verified, err := vm.dstack.PopBool() if err != nil { return err } if !verified { - str := fmt.Sprintf("%s failed", op.opcode.name) + str := fmt.Sprintf("%s failed", op.name) return scriptError(c, str) } return nil @@ -915,13 +906,13 @@ func abstractVerify(op *parsedOpcode, vm *Engine, c ErrorCode) error { // opcodeVerify examines the top item on the data stack as a boolean value and // verifies it evaluates to true. An error is returned if it does not. -func opcodeVerify(op *parsedOpcode, vm *Engine) error { +func opcodeVerify(op *opcode, data []byte, vm *Engine) error { return abstractVerify(op, vm, ErrVerify) } // opcodeReturn returns an appropriate error since it is always an error to // return early from a script. -func opcodeReturn(op *parsedOpcode, vm *Engine) error { +func opcodeReturn(op *opcode, data []byte, vm *Engine) error { return scriptError(ErrEarlyReturn, "script returned early") } @@ -951,7 +942,7 @@ func verifyLockTime(txLockTime, threshold, lockTime int64) error { // validating if the transaction outputs are spendable yet. If flag // ScriptVerifyCheckLockTimeVerify is not set, the code continues as if OP_NOP2 // were executed. -func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error { +func opcodeCheckLockTimeVerify(op *opcode, data []byte, vm *Engine) error { // If the ScriptVerifyCheckLockTimeVerify script flag is not set, treat // opcode as OP_NOP2 instead. if !vm.hasFlag(ScriptVerifyCheckLockTimeVerify) { @@ -1025,7 +1016,7 @@ func opcodeCheckLockTimeVerify(op *parsedOpcode, vm *Engine) error { // validating if the transaction outputs are spendable yet. If flag // ScriptVerifyCheckSequenceVerify is not set, the code continues as if OP_NOP3 // were executed. -func opcodeCheckSequenceVerify(op *parsedOpcode, vm *Engine) error { +func opcodeCheckSequenceVerify(op *opcode, data []byte, vm *Engine) error { // If the ScriptVerifyCheckSequenceVerify script flag is not set, treat // opcode as OP_NOP3 instead. if !vm.hasFlag(ScriptVerifyCheckSequenceVerify) { @@ -1102,7 +1093,7 @@ func opcodeCheckSequenceVerify(op *parsedOpcode, vm *Engine) error { // // Main data stack transformation: [... x1 x2 x3] -> [... x1 x2] // Alt data stack transformation: [... y1 y2 y3] -> [... y1 y2 y3 x3] -func opcodeToAltStack(op *parsedOpcode, vm *Engine) error { +func opcodeToAltStack(op *opcode, data []byte, vm *Engine) error { so, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1117,7 +1108,7 @@ func opcodeToAltStack(op *parsedOpcode, vm *Engine) error { // // Main data stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 y3] // Alt data stack transformation: [... y1 y2 y3] -> [... y1 y2] -func opcodeFromAltStack(op *parsedOpcode, vm *Engine) error { +func opcodeFromAltStack(op *opcode, data []byte, vm *Engine) error { so, err := vm.astack.PopByteArray() if err != nil { return err @@ -1130,35 +1121,35 @@ func opcodeFromAltStack(op *parsedOpcode, vm *Engine) error { // opcode2Drop removes the top 2 items from the data stack. // // Stack transformation: [... x1 x2 x3] -> [... x1] -func opcode2Drop(op *parsedOpcode, vm *Engine) error { +func opcode2Drop(op *opcode, data []byte, vm *Engine) error { return vm.dstack.DropN(2) } // opcode2Dup duplicates the top 2 items on the data stack. // // Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x2 x3] -func opcode2Dup(op *parsedOpcode, vm *Engine) error { +func opcode2Dup(op *opcode, data []byte, vm *Engine) error { return vm.dstack.DupN(2) } // opcode3Dup duplicates the top 3 items on the data stack. // // Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x1 x2 x3] -func opcode3Dup(op *parsedOpcode, vm *Engine) error { +func opcode3Dup(op *opcode, data []byte, vm *Engine) error { return vm.dstack.DupN(3) } // opcode2Over duplicates the 2 items before the top 2 items on the data stack. // // Stack transformation: [... x1 x2 x3 x4] -> [... x1 x2 x3 x4 x1 x2] -func opcode2Over(op *parsedOpcode, vm *Engine) error { +func opcode2Over(op *opcode, data []byte, vm *Engine) error { return vm.dstack.OverN(2) } // opcode2Rot rotates the top 6 items on the data stack to the left twice. // // Stack transformation: [... x1 x2 x3 x4 x5 x6] -> [... x3 x4 x5 x6 x1 x2] -func opcode2Rot(op *parsedOpcode, vm *Engine) error { +func opcode2Rot(op *opcode, data []byte, vm *Engine) error { return vm.dstack.RotN(2) } @@ -1166,7 +1157,7 @@ func opcode2Rot(op *parsedOpcode, vm *Engine) error { // before them. // // Stack transformation: [... x1 x2 x3 x4] -> [... x3 x4 x1 x2] -func opcode2Swap(op *parsedOpcode, vm *Engine) error { +func opcode2Swap(op *opcode, data []byte, vm *Engine) error { return vm.dstack.SwapN(2) } @@ -1174,7 +1165,7 @@ func opcode2Swap(op *parsedOpcode, vm *Engine) error { // // Stack transformation (x1==0): [... x1] -> [... x1] // Stack transformation (x1!=0): [... x1] -> [... x1 x1] -func opcodeIfDup(op *parsedOpcode, vm *Engine) error { +func opcodeIfDup(op *opcode, data []byte, vm *Engine) error { so, err := vm.dstack.PeekByteArray(0) if err != nil { return err @@ -1194,7 +1185,7 @@ func opcodeIfDup(op *parsedOpcode, vm *Engine) error { // Stack transformation: [...] -> [... ] // Example with 2 items: [x1 x2] -> [x1 x2 2] // Example with 3 items: [x1 x2 x3] -> [x1 x2 x3 3] -func opcodeDepth(op *parsedOpcode, vm *Engine) error { +func opcodeDepth(op *opcode, data []byte, vm *Engine) error { vm.dstack.PushInt(scriptNum(vm.dstack.Depth())) return nil } @@ -1202,28 +1193,28 @@ func opcodeDepth(op *parsedOpcode, vm *Engine) error { // opcodeDrop removes the top item from the data stack. // // Stack transformation: [... x1 x2 x3] -> [... x1 x2] -func opcodeDrop(op *parsedOpcode, vm *Engine) error { +func opcodeDrop(op *opcode, data []byte, vm *Engine) error { return vm.dstack.DropN(1) } // opcodeDup duplicates the top item on the data stack. // // Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x3] -func opcodeDup(op *parsedOpcode, vm *Engine) error { +func opcodeDup(op *opcode, data []byte, vm *Engine) error { return vm.dstack.DupN(1) } // opcodeNip removes the item before the top item on the data stack. // // Stack transformation: [... x1 x2 x3] -> [... x1 x3] -func opcodeNip(op *parsedOpcode, vm *Engine) error { +func opcodeNip(op *opcode, data []byte, vm *Engine) error { return vm.dstack.NipN(1) } // opcodeOver duplicates the item before the top item on the data stack. // // Stack transformation: [... x1 x2 x3] -> [... x1 x2 x3 x2] -func opcodeOver(op *parsedOpcode, vm *Engine) error { +func opcodeOver(op *opcode, data []byte, vm *Engine) error { return vm.dstack.OverN(1) } @@ -1233,7 +1224,7 @@ func opcodeOver(op *parsedOpcode, vm *Engine) error { // Stack transformation: [xn ... x2 x1 x0 n] -> [xn ... x2 x1 x0 xn] // Example with n=1: [x2 x1 x0 1] -> [x2 x1 x0 x1] // Example with n=2: [x2 x1 x0 2] -> [x2 x1 x0 x2] -func opcodePick(op *parsedOpcode, vm *Engine) error { +func opcodePick(op *opcode, data []byte, vm *Engine) error { val, err := vm.dstack.PopInt() if err != nil { return err @@ -1248,7 +1239,7 @@ func opcodePick(op *parsedOpcode, vm *Engine) error { // Stack transformation: [xn ... x2 x1 x0 n] -> [... x2 x1 x0 xn] // Example with n=1: [x2 x1 x0 1] -> [x2 x0 x1] // Example with n=2: [x2 x1 x0 2] -> [x1 x0 x2] -func opcodeRoll(op *parsedOpcode, vm *Engine) error { +func opcodeRoll(op *opcode, data []byte, vm *Engine) error { val, err := vm.dstack.PopInt() if err != nil { return err @@ -1260,14 +1251,14 @@ func opcodeRoll(op *parsedOpcode, vm *Engine) error { // opcodeRot rotates the top 3 items on the data stack to the left. // // Stack transformation: [... x1 x2 x3] -> [... x2 x3 x1] -func opcodeRot(op *parsedOpcode, vm *Engine) error { +func opcodeRot(op *opcode, data []byte, vm *Engine) error { return vm.dstack.RotN(1) } // opcodeSwap swaps the top two items on the stack. // // Stack transformation: [... x1 x2] -> [... x2 x1] -func opcodeSwap(op *parsedOpcode, vm *Engine) error { +func opcodeSwap(op *opcode, data []byte, vm *Engine) error { return vm.dstack.SwapN(1) } @@ -1275,7 +1266,7 @@ func opcodeSwap(op *parsedOpcode, vm *Engine) error { // second-to-top item. // // Stack transformation: [... x1 x2] -> [... x2 x1 x2] -func opcodeTuck(op *parsedOpcode, vm *Engine) error { +func opcodeTuck(op *opcode, data []byte, vm *Engine) error { return vm.dstack.Tuck() } @@ -1283,7 +1274,7 @@ func opcodeTuck(op *parsedOpcode, vm *Engine) error { // stack. // // Stack transformation: [... x1] -> [... x1 len(x1)] -func opcodeSize(op *parsedOpcode, vm *Engine) error { +func opcodeSize(op *opcode, data []byte, vm *Engine) error { so, err := vm.dstack.PeekByteArray(0) if err != nil { return err @@ -1297,7 +1288,7 @@ func opcodeSize(op *parsedOpcode, vm *Engine) error { // bytes, and pushes the result, encoded as a boolean, back to the stack. // // Stack transformation: [... x1 x2] -> [... bool] -func opcodeEqual(op *parsedOpcode, vm *Engine) error { +func opcodeEqual(op *opcode, data []byte, vm *Engine) error { a, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1318,8 +1309,8 @@ func opcodeEqual(op *parsedOpcode, vm *Engine) error { // evaluates to true. An error is returned if it does not. // // Stack transformation: [... x1 x2] -> [... bool] -> [...] -func opcodeEqualVerify(op *parsedOpcode, vm *Engine) error { - err := opcodeEqual(op, vm) +func opcodeEqualVerify(op *opcode, data []byte, vm *Engine) error { + err := opcodeEqual(op, data, vm) if err == nil { err = abstractVerify(op, vm, ErrEqualVerify) } @@ -1330,7 +1321,7 @@ func opcodeEqualVerify(op *parsedOpcode, vm *Engine) error { // it with its incremented value (plus 1). // // Stack transformation: [... x1 x2] -> [... x1 x2+1] -func opcode1Add(op *parsedOpcode, vm *Engine) error { +func opcode1Add(op *opcode, data []byte, vm *Engine) error { m, err := vm.dstack.PopInt() if err != nil { return err @@ -1344,7 +1335,7 @@ func opcode1Add(op *parsedOpcode, vm *Engine) error { // it with its decremented value (minus 1). // // Stack transformation: [... x1 x2] -> [... x1 x2-1] -func opcode1Sub(op *parsedOpcode, vm *Engine) error { +func opcode1Sub(op *opcode, data []byte, vm *Engine) error { m, err := vm.dstack.PopInt() if err != nil { return err @@ -1358,7 +1349,7 @@ func opcode1Sub(op *parsedOpcode, vm *Engine) error { // it with its negation. // // Stack transformation: [... x1 x2] -> [... x1 -x2] -func opcodeNegate(op *parsedOpcode, vm *Engine) error { +func opcodeNegate(op *opcode, data []byte, vm *Engine) error { m, err := vm.dstack.PopInt() if err != nil { return err @@ -1372,7 +1363,7 @@ func opcodeNegate(op *parsedOpcode, vm *Engine) error { // it with its absolute value. // // Stack transformation: [... x1 x2] -> [... x1 abs(x2)] -func opcodeAbs(op *parsedOpcode, vm *Engine) error { +func opcodeAbs(op *opcode, data []byte, vm *Engine) error { m, err := vm.dstack.PopInt() if err != nil { return err @@ -1397,7 +1388,7 @@ func opcodeAbs(op *parsedOpcode, vm *Engine) error { // Stack transformation (x2==0): [... x1 0] -> [... x1 1] // Stack transformation (x2!=0): [... x1 1] -> [... x1 0] // Stack transformation (x2!=0): [... x1 17] -> [... x1 0] -func opcodeNot(op *parsedOpcode, vm *Engine) error { +func opcodeNot(op *opcode, data []byte, vm *Engine) error { m, err := vm.dstack.PopInt() if err != nil { return err @@ -1417,7 +1408,7 @@ func opcodeNot(op *parsedOpcode, vm *Engine) error { // Stack transformation (x2==0): [... x1 0] -> [... x1 0] // Stack transformation (x2!=0): [... x1 1] -> [... x1 1] // Stack transformation (x2!=0): [... x1 17] -> [... x1 1] -func opcode0NotEqual(op *parsedOpcode, vm *Engine) error { +func opcode0NotEqual(op *opcode, data []byte, vm *Engine) error { m, err := vm.dstack.PopInt() if err != nil { return err @@ -1434,7 +1425,7 @@ func opcode0NotEqual(op *parsedOpcode, vm *Engine) error { // them with their sum. // // Stack transformation: [... x1 x2] -> [... x1+x2] -func opcodeAdd(op *parsedOpcode, vm *Engine) error { +func opcodeAdd(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1454,7 +1445,7 @@ func opcodeAdd(op *parsedOpcode, vm *Engine) error { // entry. // // Stack transformation: [... x1 x2] -> [... x1-x2] -func opcodeSub(op *parsedOpcode, vm *Engine) error { +func opcodeSub(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1476,7 +1467,7 @@ func opcodeSub(op *parsedOpcode, vm *Engine) error { // Stack transformation (x1!=0, x2==0): [... 5 0] -> [... 0] // Stack transformation (x1==0, x2!=0): [... 0 7] -> [... 0] // Stack transformation (x1!=0, x2!=0): [... 4 8] -> [... 1] -func opcodeBoolAnd(op *parsedOpcode, vm *Engine) error { +func opcodeBoolAnd(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1503,7 +1494,7 @@ func opcodeBoolAnd(op *parsedOpcode, vm *Engine) error { // Stack transformation (x1!=0, x2==0): [... 5 0] -> [... 1] // Stack transformation (x1==0, x2!=0): [... 0 7] -> [... 1] // Stack transformation (x1!=0, x2!=0): [... 4 8] -> [... 1] -func opcodeBoolOr(op *parsedOpcode, vm *Engine) error { +func opcodeBoolOr(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1528,7 +1519,7 @@ func opcodeBoolOr(op *parsedOpcode, vm *Engine) error { // // Stack transformation (x1==x2): [... 5 5] -> [... 1] // Stack transformation (x1!=x2): [... 5 7] -> [... 0] -func opcodeNumEqual(op *parsedOpcode, vm *Engine) error { +func opcodeNumEqual(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1556,8 +1547,8 @@ func opcodeNumEqual(op *parsedOpcode, vm *Engine) error { // to true. An error is returned if it does not. // // Stack transformation: [... x1 x2] -> [... bool] -> [...] -func opcodeNumEqualVerify(op *parsedOpcode, vm *Engine) error { - err := opcodeNumEqual(op, vm) +func opcodeNumEqualVerify(op *opcode, data []byte, vm *Engine) error { + err := opcodeNumEqual(op, data, vm) if err == nil { err = abstractVerify(op, vm, ErrNumEqualVerify) } @@ -1569,7 +1560,7 @@ func opcodeNumEqualVerify(op *parsedOpcode, vm *Engine) error { // // Stack transformation (x1==x2): [... 5 5] -> [... 0] // Stack transformation (x1!=x2): [... 5 7] -> [... 1] -func opcodeNumNotEqual(op *parsedOpcode, vm *Engine) error { +func opcodeNumNotEqual(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1594,7 +1585,7 @@ func opcodeNumNotEqual(op *parsedOpcode, vm *Engine) error { // otherwise a 0. // // Stack transformation: [... x1 x2] -> [... bool] -func opcodeLessThan(op *parsedOpcode, vm *Engine) error { +func opcodeLessThan(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1619,7 +1610,7 @@ func opcodeLessThan(op *parsedOpcode, vm *Engine) error { // with a 1, otherwise a 0. // // Stack transformation: [... x1 x2] -> [... bool] -func opcodeGreaterThan(op *parsedOpcode, vm *Engine) error { +func opcodeGreaterThan(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1643,7 +1634,7 @@ func opcodeGreaterThan(op *parsedOpcode, vm *Engine) error { // replaced with a 1, otherwise a 0. // // Stack transformation: [... x1 x2] -> [... bool] -func opcodeLessThanOrEqual(op *parsedOpcode, vm *Engine) error { +func opcodeLessThanOrEqual(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1667,7 +1658,7 @@ func opcodeLessThanOrEqual(op *parsedOpcode, vm *Engine) error { // item, they are replaced with a 1, otherwise a 0. // // Stack transformation: [... x1 x2] -> [... bool] -func opcodeGreaterThanOrEqual(op *parsedOpcode, vm *Engine) error { +func opcodeGreaterThanOrEqual(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1691,7 +1682,7 @@ func opcodeGreaterThanOrEqual(op *parsedOpcode, vm *Engine) error { // them with the minimum of the two. // // Stack transformation: [... x1 x2] -> [... min(x1, x2)] -func opcodeMin(op *parsedOpcode, vm *Engine) error { +func opcodeMin(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1715,7 +1706,7 @@ func opcodeMin(op *parsedOpcode, vm *Engine) error { // them with the maximum of the two. // // Stack transformation: [... x1 x2] -> [... max(x1, x2)] -func opcodeMax(op *parsedOpcode, vm *Engine) error { +func opcodeMax(op *opcode, data []byte, vm *Engine) error { v0, err := vm.dstack.PopInt() if err != nil { return err @@ -1743,7 +1734,7 @@ func opcodeMax(op *parsedOpcode, vm *Engine) error { // the third-to-top item is the value to test. // // Stack transformation: [... x1 min max] -> [... bool] -func opcodeWithin(op *parsedOpcode, vm *Engine) error { +func opcodeWithin(op *opcode, data []byte, vm *Engine) error { maxVal, err := vm.dstack.PopInt() if err != nil { return err @@ -1777,7 +1768,7 @@ func calcHash(buf []byte, hasher hash.Hash) []byte { // replaces it with ripemd160(data). // // Stack transformation: [... x1] -> [... ripemd160(x1)] -func opcodeRipemd160(op *parsedOpcode, vm *Engine) error { +func opcodeRipemd160(op *opcode, data []byte, vm *Engine) error { buf, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1791,7 +1782,7 @@ func opcodeRipemd160(op *parsedOpcode, vm *Engine) error { // with sha1(data). // // Stack transformation: [... x1] -> [... sha1(x1)] -func opcodeSha1(op *parsedOpcode, vm *Engine) error { +func opcodeSha1(op *opcode, data []byte, vm *Engine) error { buf, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1806,7 +1797,7 @@ func opcodeSha1(op *parsedOpcode, vm *Engine) error { // it with sha256(data). // // Stack transformation: [... x1] -> [... sha256(x1)] -func opcodeSha256(op *parsedOpcode, vm *Engine) error { +func opcodeSha256(op *opcode, data []byte, vm *Engine) error { buf, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1821,7 +1812,7 @@ func opcodeSha256(op *parsedOpcode, vm *Engine) error { // it with ripemd160(sha256(data)). // // Stack transformation: [... x1] -> [... ripemd160(sha256(x1))] -func opcodeHash160(op *parsedOpcode, vm *Engine) error { +func opcodeHash160(op *opcode, data []byte, vm *Engine) error { buf, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1836,7 +1827,7 @@ func opcodeHash160(op *parsedOpcode, vm *Engine) error { // it with sha256(sha256(data)). // // Stack transformation: [... x1] -> [... sha256(sha256(x1))] -func opcodeHash256(op *parsedOpcode, vm *Engine) error { +func opcodeHash256(op *opcode, data []byte, vm *Engine) error { buf, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1850,7 +1841,7 @@ func opcodeHash256(op *parsedOpcode, vm *Engine) error { // seen OP_CODESEPARATOR which is used during signature checking. // // This opcode does not change the contents of the data stack. -func opcodeCodeSeparator(op *parsedOpcode, vm *Engine) error { +func opcodeCodeSeparator(op *opcode, data []byte, vm *Engine) error { vm.lastCodeSep = int(vm.tokenizer.ByteIndex()) return nil } @@ -1869,7 +1860,7 @@ func opcodeCodeSeparator(op *parsedOpcode, vm *Engine) error { // cryptographic methods against the provided public key. // // Stack transformation: [... signature pubkey] -> [... bool] -func opcodeCheckSig(op *parsedOpcode, vm *Engine) error { +func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { pkBytes, err := vm.dstack.PopByteArray() if err != nil { return err @@ -1984,9 +1975,9 @@ func opcodeCheckSig(op *parsedOpcode, vm *Engine) error { // The opcodeCheckSig function is invoked followed by opcodeVerify. See the // documentation for each of those opcodes for more details. // -// Stack transformation: signature pubkey] -> [... bool] -> [...] -func opcodeCheckSigVerify(op *parsedOpcode, vm *Engine) error { - err := opcodeCheckSig(op, vm) +// Stack transformation: [... signature pubkey] -> [... bool] -> [...] +func opcodeCheckSigVerify(op *opcode, data []byte, vm *Engine) error { + err := opcodeCheckSig(op, data, vm) if err == nil { err = abstractVerify(op, vm, ErrCheckSigVerify) } @@ -2021,7 +2012,7 @@ type parsedSigInfo struct { // // Stack transformation: // [... dummy [sig ...] numsigs [pubkey ...] numpubkeys] -> [... bool] -func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { +func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { numKeys, err := vm.dstack.PopInt() if err != nil { return err @@ -2247,8 +2238,8 @@ func opcodeCheckMultiSig(op *parsedOpcode, vm *Engine) error { // // Stack transformation: // [... dummy [sig ...] numsigs [pubkey ...] numpubkeys] -> [... bool] -> [...] -func opcodeCheckMultiSigVerify(op *parsedOpcode, vm *Engine) error { - err := opcodeCheckMultiSig(op, vm) +func opcodeCheckMultiSigVerify(op *opcode, data []byte, vm *Engine) error { + err := opcodeCheckMultiSig(op, data, vm) if err == nil { err = abstractVerify(op, vm, ErrCheckMultiSigVerify) } diff --git a/txscript/opcode_test.go b/txscript/opcode_test.go index 3c5abf9da9..91263c21b1 100644 --- a/txscript/opcode_test.go +++ b/txscript/opcode_test.go @@ -23,8 +23,8 @@ func TestOpcodeDisabled(t *testing.T) { OP_LSHIFT, OP_RSHIFT, } for _, opcodeVal := range tests { - pop := parsedOpcode{opcode: &opcodeArray[opcodeVal], data: nil} - err := opcodeDisabled(&pop, nil) + op := &opcodeArray[opcodeVal] + err := opcodeDisabled(op, nil, nil) if !IsErrorCode(err, ErrDisabledOpcode) { t.Errorf("opcodeDisabled: unexpected error - got %v, "+ "want %v", err, ErrDisabledOpcode) From 3be166e3ae1521d0cf3472c204a348bca647995d Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 17 Nov 2021 12:46:12 +0900 Subject: [PATCH 0576/1056] go.mod, go.sum: Update goleveldb Goleveldb recently had a PR in where memory allocation was reduced drastically (github.com/syndtr/goleveldb/pull/367). Update goleveldb to use that PR. --- go.mod | 3 ++- go.sum | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 7722564f57..767c2740db 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,8 @@ require ( github.com/decred/dcrd/lru v1.0.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 - golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) go 1.16 diff --git a/go.sum b/go.sum index 4c5a352a89..e9ee276db4 100644 --- a/go.sum +++ b/go.sum @@ -25,7 +25,18 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -35,28 +46,56 @@ github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= @@ -64,3 +103,5 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 780cc0889fd2f326e4a2a9b513d8d30ff37e0cd2 Mon Sep 17 00:00:00 2001 From: Tomasz Ziolkowski Date: Fri, 15 Oct 2021 16:56:27 +0200 Subject: [PATCH 0577/1056] reduce redundant memory allocatio - resolves btcsuite/btcd#1699 Signed-off-by: Tomasz Ziolkowski --- connmgr/tor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connmgr/tor.go b/connmgr/tor.go index 2b22ae51f2..a2e512dba1 100644 --- a/connmgr/tor.go +++ b/connmgr/tor.go @@ -76,7 +76,7 @@ func TorLookupIP(host, proxy string) ([]net.IP, error) { return nil, ErrTorUnrecognizedAuthMethod } - buf = make([]byte, 7+len(host)) + buf = make([]byte, 6+len(host)) buf[0] = 5 // protocol version buf[1] = '\xF0' // Tor Resolve buf[2] = 0 // reserved From ec9ca7d782a203fea9639f4122f22bf1fd79bef7 Mon Sep 17 00:00:00 2001 From: Matthew Bajorek Date: Sun, 5 Dec 2021 15:15:15 -0500 Subject: [PATCH 0578/1056] rpcclient+rpcserver: Change getnetworkhashps return type to be a float to be in line with bitcoin core --- rpcclient/mining.go | 12 ++++++------ rpcserver.go | 20 ++++++++++---------- rpcserverhelp.go | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 15473e24be..717825eeaa 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -255,14 +255,14 @@ type FutureGetNetworkHashPS chan *Response // Receive waits for the Response promised by the future and returns the // estimated network hashes per second for the block heights provided by the // parameters. -func (r FutureGetNetworkHashPS) Receive() (int64, error) { +func (r FutureGetNetworkHashPS) Receive() (float64, error) { res, err := ReceiveFuture(r) if err != nil { return -1, err } - // Unmarshal result as an int64. - var result int64 + // Unmarshal result as an float64. + var result float64 err = json.Unmarshal(res, &result) if err != nil { return 0, err @@ -286,7 +286,7 @@ func (c *Client) GetNetworkHashPSAsync() FutureGetNetworkHashPS { // // See GetNetworkHashPS2 to override the number of blocks to use and // GetNetworkHashPS3 to override the height at which to calculate the estimate. -func (c *Client) GetNetworkHashPS() (int64, error) { +func (c *Client) GetNetworkHashPS() (float64, error) { return c.GetNetworkHashPSAsync().Receive() } @@ -307,7 +307,7 @@ func (c *Client) GetNetworkHashPS2Async(blocks int) FutureGetNetworkHashPS { // // See GetNetworkHashPS to use defaults and GetNetworkHashPS3 to override the // height at which to calculate the estimate. -func (c *Client) GetNetworkHashPS2(blocks int) (int64, error) { +func (c *Client) GetNetworkHashPS2(blocks int) (float64, error) { return c.GetNetworkHashPS2Async(blocks).Receive() } @@ -327,7 +327,7 @@ func (c *Client) GetNetworkHashPS3Async(blocks, height int) FutureGetNetworkHash // of blocks since the last difficulty change will be used. // // See GetNetworkHashPS and GetNetworkHashPS2 to use defaults. -func (c *Client) GetNetworkHashPS3(blocks, height int) (int64, error) { +func (c *Client) GetNetworkHashPS3(blocks, height int) (float64, error) { return c.GetNetworkHashPS3Async(blocks, height).Receive() } diff --git a/rpcserver.go b/rpcserver.go index d184072942..6f60261a9c 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2355,11 +2355,11 @@ func handleGetMiningInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{ if err != nil { return nil, err } - networkHashesPerSec, ok := networkHashesPerSecIface.(int64) + networkHashesPerSec, ok := networkHashesPerSecIface.(float64) if !ok { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInternal.Code, - Message: "networkHashesPerSec is not an int64", + Message: "networkHashesPerSec is not a float64", } } @@ -2373,7 +2373,7 @@ func handleGetMiningInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{ Generate: s.cfg.CPUMiner.IsMining(), GenProcLimit: s.cfg.CPUMiner.NumWorkers(), HashesPerSec: s.cfg.CPUMiner.HashesPerSecond(), - NetworkHashPS: float64(networkHashesPerSec), + NetworkHashPS: networkHashesPerSec, PooledTx: uint64(s.cfg.TxMemPool.Count()), TestNet: cfg.TestNet3, } @@ -2393,8 +2393,8 @@ func handleGetNetTotals(s *rpcServer, cmd interface{}, closeChan <-chan struct{} // handleGetNetworkHashPS implements the getnetworkhashps command. func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { - // Note: All valid error return paths should return an int64. - // Literal zeros are inferred as int, and won't coerce to int64 + // Note: All valid error return paths should return a float64. + // Literal zeros are inferred as int, and won't coerce to float64 // because the return value is an interface{}. c := cmd.(*btcjson.GetNetworkHashPSCmd) @@ -2409,7 +2409,7 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru endHeight = int32(*c.Height) } if endHeight > best.Height || endHeight == 0 { - return int64(0), nil + return float64(0), nil } if endHeight < 0 { endHeight = best.Height @@ -2476,13 +2476,13 @@ func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan stru // Calculate the difference in seconds between the min and max block // timestamps and avoid division by zero in the case where there is no // time difference. - timeDiff := int64(maxTimestamp.Sub(minTimestamp) / time.Second) + timeDiff := maxTimestamp.Sub(minTimestamp).Seconds() if timeDiff == 0 { - return int64(0), nil + return timeDiff, nil } - hashesPerSec := new(big.Int).Div(totalWork, big.NewInt(timeDiff)) - return hashesPerSec.Int64(), nil + hashesPerSec, _ := new(big.Float).Quo(new(big.Float).SetInt(totalWork), new(big.Float).SetFloat64(timeDiff)).Float64() + return hashesPerSec, nil } // handleGetNodeAddresses implements the getnodeaddresses command. diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 570b5b0500..16bbb62a2b 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -740,7 +740,7 @@ var rpcResultTypes = map[string][]interface{}{ "getmempoolinfo": {(*btcjson.GetMempoolInfoResult)(nil)}, "getmininginfo": {(*btcjson.GetMiningInfoResult)(nil)}, "getnettotals": {(*btcjson.GetNetTotalsResult)(nil)}, - "getnetworkhashps": {(*int64)(nil)}, + "getnetworkhashps": {(*float64)(nil)}, "getnodeaddresses": {(*[]btcjson.GetNodeAddressesResult)(nil)}, "getpeerinfo": {(*[]btcjson.GetPeerInfoResult)(nil)}, "getrawmempool": {(*[]string)(nil), (*btcjson.GetRawMempoolVerboseResult)(nil)}, From a1f43e4d846ea01f38d1cf459652f1133370a85c Mon Sep 17 00:00:00 2001 From: Matthew Bajorek Date: Sun, 5 Dec 2021 15:15:41 -0500 Subject: [PATCH 0579/1056] integration: Add unit tests for all three GetNetworkHashPS client methods --- integration/rpcserver_test.go | 156 ++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/integration/rpcserver_test.go b/integration/rpcserver_test.go index 5875b35353..13325bc1d7 100644 --- a/integration/rpcserver_test.go +++ b/integration/rpcserver_test.go @@ -13,7 +13,9 @@ import ( "os" "runtime/debug" "testing" + "time" + "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/integration/rpctest" @@ -135,11 +137,165 @@ func testBulkClient(r *rpctest.Harness, t *testing.T) { } +func calculateHashesPerSecBetweenBlockHeights(r *rpctest.Harness, t *testing.T, startHeight, endHeight int64) float64 { + var totalWork int64 = 0 + var minTimestamp, maxTimestamp time.Time + + for curHeight := startHeight; curHeight <= endHeight; curHeight++ { + hash, err := r.Client.GetBlockHash(curHeight) + + if err != nil { + t.Fatal(err) + } + + blockHeader, err := r.Client.GetBlockHeader(hash) + + if err != nil { + t.Fatal(err) + } + + if curHeight == startHeight { + minTimestamp = blockHeader.Timestamp + continue + } + + totalWork += blockchain.CalcWork(blockHeader.Bits).Int64() + + if curHeight == endHeight { + maxTimestamp = blockHeader.Timestamp + } + } + + timeDiff := maxTimestamp.Sub(minTimestamp).Seconds() + + if timeDiff == 0 { + return 0 + } + + return float64(totalWork) / timeDiff +} + +func testGetNetworkHashPS(r *rpctest.Harness, t *testing.T) { + networkHashPS, err := r.Client.GetNetworkHashPS() + + if err != nil { + t.Fatal(err) + } + + expectedNetworkHashPS := calculateHashesPerSecBetweenBlockHeights(r, t, 28, 148) + + if networkHashPS != expectedNetworkHashPS { + t.Fatalf("Network hashes per second should be %f but received: %f", expectedNetworkHashPS, networkHashPS) + } +} + +func testGetNetworkHashPS2(r *rpctest.Harness, t *testing.T) { + networkHashPS2BlockTests := []struct { + blocks int + expectedStartHeight int64 + expectedEndHeight int64 + }{ + // Test receiving command for negative blocks + {blocks: -200, expectedStartHeight: 0, expectedEndHeight: 148}, + // Test receiving command for 0 blocks + {blocks: 0, expectedStartHeight: 0, expectedEndHeight: 148}, + // Test receiving command for less than total blocks -> expectedStartHeight = 148 - 100 = 48 + {blocks: 100, expectedStartHeight: 48, expectedEndHeight: 148}, + // Test receiving command for exact total blocks -> expectedStartHeight = 148 - 148 = 0 + {blocks: 148, expectedStartHeight: 0, expectedEndHeight: 148}, + // Test receiving command for greater than total blocks + {blocks: 200, expectedStartHeight: 0, expectedEndHeight: 148}, + } + + for _, networkHashPS2BlockTest := range networkHashPS2BlockTests { + blocks := networkHashPS2BlockTest.blocks + expectedStartHeight := networkHashPS2BlockTest.expectedStartHeight + expectedEndHeight := networkHashPS2BlockTest.expectedEndHeight + + networkHashPS, err := r.Client.GetNetworkHashPS2(blocks) + + if err != nil { + t.Fatal(err) + } + + expectedNetworkHashPS := calculateHashesPerSecBetweenBlockHeights(r, t, expectedStartHeight, expectedEndHeight) + + if networkHashPS != expectedNetworkHashPS { + t.Fatalf("Network hashes per second should be %f but received: %f", expectedNetworkHashPS, networkHashPS) + } + } +} + +func testGetNetworkHashPS3(r *rpctest.Harness, t *testing.T) { + networkHashPS3BlockTests := []struct { + height int + blocks int + expectedStartHeight int64 + expectedEndHeight int64 + }{ + // Test receiving command for negative height -> expectedEndHeight force to 148 + // - And negative blocks -> expectedStartHeight = 148 - ((148 % 2016) + 1) = -1 -> forced to 0 + {height: -200, blocks: -120, expectedStartHeight: 0, expectedEndHeight: 148}, + // - And zero blocks -> expectedStartHeight = 148 - ((148 % 2016) + 1) = -1 -> forced to 0 + {height: -200, blocks: 0, expectedStartHeight: 0, expectedEndHeight: 148}, + // - And positive blocks less than total blocks -> expectedStartHeight = 148 - 100 = 48 + {height: -200, blocks: 100, expectedStartHeight: 48, expectedEndHeight: 148}, + // - And positive blocks equal to total blocks + {height: -200, blocks: 148, expectedStartHeight: 0, expectedEndHeight: 148}, + // - And positive blocks greater than total blocks + {height: -200, blocks: 250, expectedStartHeight: 0, expectedEndHeight: 148}, + + // Test receiving command for zero height + // - Should return 0 similar to expected start height and expected end height both being 0 + // (blocks is irrelevant to output) + {height: 0, blocks: 120, expectedStartHeight: 0, expectedEndHeight: 0}, + + // Tests for valid block height -> expectedEndHeight set as height + // - And negative blocks -> expectedStartHeight = 148 - ((148 % 2016) + 1) = -1 -> forced to 0 + {height: 100, blocks: -120, expectedStartHeight: 0, expectedEndHeight: 100}, + // - And zero blocks -> expectedStartHeight = 148 - ((148 % 2016) + 1) = -1 -> forced to 0 + {height: 100, blocks: 0, expectedStartHeight: 0, expectedEndHeight: 100}, + // - And positive blocks less than command blocks -> expectedStartHeight = 100 - 70 = 30 + {height: 100, blocks: 70, expectedStartHeight: 30, expectedEndHeight: 100}, + // - And positive blocks equal to command blocks -> expectedStartHeight = 100 - 100 = 0 + {height: 100, blocks: 100, expectedStartHeight: 0, expectedEndHeight: 100}, + // - And positive blocks greater than command blocks -> expectedStartHeight = 100 - 200 = -100 -> forced to 0 + {height: 100, blocks: 200, expectedStartHeight: 0, expectedEndHeight: 100}, + + // Test receiving command for height greater than block height + // - Should return 0 similar to expected start height and expected end height both being 0 + // (blocks is irrelevant to output) + {height: 200, blocks: 120, expectedStartHeight: 0, expectedEndHeight: 0}, + } + + for _, networkHashPS3BlockTest := range networkHashPS3BlockTests { + blocks := networkHashPS3BlockTest.blocks + height := networkHashPS3BlockTest.height + expectedStartHeight := networkHashPS3BlockTest.expectedStartHeight + expectedEndHeight := networkHashPS3BlockTest.expectedEndHeight + + networkHashPS, err := r.Client.GetNetworkHashPS3(blocks, height) + + if err != nil { + t.Fatal(err) + } + + expectedNetworkHashPS := calculateHashesPerSecBetweenBlockHeights(r, t, expectedStartHeight, expectedEndHeight) + + if networkHashPS != expectedNetworkHashPS { + t.Fatalf("Network hashes per second should be %f but received: %f", expectedNetworkHashPS, networkHashPS) + } + } +} + var rpcTestCases = []rpctest.HarnessTestCase{ testGetBestBlock, testGetBlockCount, testGetBlockHash, testBulkClient, + testGetNetworkHashPS, + testGetNetworkHashPS2, + testGetNetworkHashPS3, } var primaryHarness *rpctest.Harness From 5cd3533e2b049e78f7a8f3b9fef2c0e4247f7a71 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 24 Dec 2021 16:34:26 -0800 Subject: [PATCH 0580/1056] btcutil: move btcutil into new sub-module In this commit, we move `btcutil` as well as its sub-module, the `psbt` package into the `btcd` repo itself. --- btcutil/LICENSE | 16 + btcutil/README.md | 49 + btcutil/address.go | 720 ++++++++++++ btcutil/address_test.go | 1012 +++++++++++++++++ btcutil/amount.go | 122 ++ btcutil/amount_test.go | 309 +++++ btcutil/appdata.go | 105 ++ btcutil/appdata_test.go | 133 +++ btcutil/base58/README.md | 34 + btcutil/base58/alphabet.go | 49 + btcutil/base58/base58.go | 138 +++ btcutil/base58/base58_test.go | 101 ++ btcutil/base58/base58bench_test.go | 47 + btcutil/base58/base58check.go | 52 + btcutil/base58/base58check_test.go | 69 ++ btcutil/base58/cov_report.sh | 17 + btcutil/base58/doc.go | 29 + btcutil/base58/example_test.go | 71 ++ btcutil/base58/genalphabet.go | 79 ++ btcutil/bech32/README.md | 29 + btcutil/bech32/bech32.go | 442 ++++++++ btcutil/bech32/bech32_test.go | 691 +++++++++++ btcutil/bech32/doc.go | 15 + btcutil/bech32/error.go | 87 ++ btcutil/bech32/example_test.go | 49 + btcutil/bech32/version.go | 43 + btcutil/block.go | 265 +++++ btcutil/block_test.go | 556 +++++++++ btcutil/bloom/README.md | 30 + btcutil/bloom/cov_report.sh | 17 + btcutil/bloom/example_test.go | 45 + btcutil/bloom/filter.go | 354 ++++++ btcutil/bloom/filter_test.go | 660 +++++++++++ btcutil/bloom/merkleblock.go | 125 ++ btcutil/bloom/merkleblock_test.go | 74 ++ btcutil/bloom/murmurhash3.go | 72 ++ btcutil/bloom/murmurhash3_test.go | 45 + btcutil/bloom/test_coverage.txt | 28 + btcutil/certgen.go | 144 +++ btcutil/certgen_test.go | 123 ++ btcutil/coinset/README.md | 71 ++ btcutil/coinset/coins.go | 396 +++++++ btcutil/coinset/coins_test.go | 260 +++++ btcutil/coinset/cov_report.sh | 17 + btcutil/coinset/test_coverage.txt | 31 + btcutil/const.go | 16 + btcutil/cov_report.sh | 17 + btcutil/doc.go | 46 + btcutil/example_test.go | 76 ++ btcutil/gcs/README.md | 24 + btcutil/gcs/builder/builder.go | 371 ++++++ btcutil/gcs/builder/builder_test.go | 281 +++++ btcutil/gcs/doc.go | 24 + btcutil/gcs/gcs.go | 541 +++++++++ btcutil/gcs/gcs_test.go | 368 ++++++ btcutil/gcs/gcsbench_test.go | 237 ++++ btcutil/go.mod | 13 + btcutil/go.sum | 43 + btcutil/hash160.go | 23 + btcutil/hdkeychain/README.md | 59 + btcutil/hdkeychain/bench_test.go | 84 ++ btcutil/hdkeychain/cov_report.sh | 17 + btcutil/hdkeychain/doc.go | 84 ++ btcutil/hdkeychain/example_test.go | 182 +++ btcutil/hdkeychain/extendedkey.go | 706 ++++++++++++ btcutil/hdkeychain/extendedkey_test.go | 1209 ++++++++++++++++++++ btcutil/hdkeychain/test_coverage.txt | 20 + btcutil/internal_test.go | 147 +++ btcutil/net.go | 18 + btcutil/net_noop.go | 19 + btcutil/psbt/bip32.go | 77 ++ btcutil/psbt/creator.go | 63 ++ btcutil/psbt/extractor.go | 81 ++ btcutil/psbt/finalizer.go | 462 ++++++++ btcutil/psbt/go.mod | 17 + btcutil/psbt/go.sum | 39 + btcutil/psbt/partial_input.go | 361 ++++++ btcutil/psbt/partial_output.go | 139 +++ btcutil/psbt/partialsig.go | 52 + btcutil/psbt/psbt.go | 407 +++++++ btcutil/psbt/psbt_test.go | 1448 ++++++++++++++++++++++++ btcutil/psbt/signer.go | 155 +++ btcutil/psbt/sort.go | 102 ++ btcutil/psbt/sort_test.go | 167 +++ btcutil/psbt/types.go | 149 +++ btcutil/psbt/updater.go | 377 ++++++ btcutil/psbt/utils.go | 422 +++++++ btcutil/psbt/utils_test.go | 370 ++++++ btcutil/tx.go | 124 ++ btcutil/tx_test.go | 136 +++ btcutil/txsort/README.md | 31 + btcutil/txsort/doc.go | 20 + btcutil/txsort/testdata/bip69-1.hex | 1 + btcutil/txsort/testdata/bip69-2.hex | 1 + btcutil/txsort/testdata/bip69-3.hex | 1 + btcutil/txsort/testdata/bip69-4.hex | 1 + btcutil/txsort/testdata/bip69-5.hex | 1 + btcutil/txsort/txsort.go | 95 ++ btcutil/txsort/txsort_test.go | 124 ++ btcutil/wif.go | 169 +++ btcutil/wif_test.go | 160 +++ 101 files changed, 18198 insertions(+) create mode 100644 btcutil/LICENSE create mode 100644 btcutil/README.md create mode 100644 btcutil/address.go create mode 100644 btcutil/address_test.go create mode 100644 btcutil/amount.go create mode 100644 btcutil/amount_test.go create mode 100644 btcutil/appdata.go create mode 100644 btcutil/appdata_test.go create mode 100644 btcutil/base58/README.md create mode 100644 btcutil/base58/alphabet.go create mode 100644 btcutil/base58/base58.go create mode 100644 btcutil/base58/base58_test.go create mode 100644 btcutil/base58/base58bench_test.go create mode 100644 btcutil/base58/base58check.go create mode 100644 btcutil/base58/base58check_test.go create mode 100644 btcutil/base58/cov_report.sh create mode 100644 btcutil/base58/doc.go create mode 100644 btcutil/base58/example_test.go create mode 100644 btcutil/base58/genalphabet.go create mode 100644 btcutil/bech32/README.md create mode 100644 btcutil/bech32/bech32.go create mode 100644 btcutil/bech32/bech32_test.go create mode 100644 btcutil/bech32/doc.go create mode 100644 btcutil/bech32/error.go create mode 100644 btcutil/bech32/example_test.go create mode 100644 btcutil/bech32/version.go create mode 100644 btcutil/block.go create mode 100644 btcutil/block_test.go create mode 100644 btcutil/bloom/README.md create mode 100644 btcutil/bloom/cov_report.sh create mode 100644 btcutil/bloom/example_test.go create mode 100644 btcutil/bloom/filter.go create mode 100644 btcutil/bloom/filter_test.go create mode 100644 btcutil/bloom/merkleblock.go create mode 100644 btcutil/bloom/merkleblock_test.go create mode 100644 btcutil/bloom/murmurhash3.go create mode 100644 btcutil/bloom/murmurhash3_test.go create mode 100644 btcutil/bloom/test_coverage.txt create mode 100644 btcutil/certgen.go create mode 100644 btcutil/certgen_test.go create mode 100644 btcutil/coinset/README.md create mode 100644 btcutil/coinset/coins.go create mode 100644 btcutil/coinset/coins_test.go create mode 100644 btcutil/coinset/cov_report.sh create mode 100644 btcutil/coinset/test_coverage.txt create mode 100644 btcutil/const.go create mode 100644 btcutil/cov_report.sh create mode 100644 btcutil/doc.go create mode 100644 btcutil/example_test.go create mode 100644 btcutil/gcs/README.md create mode 100644 btcutil/gcs/builder/builder.go create mode 100644 btcutil/gcs/builder/builder_test.go create mode 100644 btcutil/gcs/doc.go create mode 100644 btcutil/gcs/gcs.go create mode 100644 btcutil/gcs/gcs_test.go create mode 100644 btcutil/gcs/gcsbench_test.go create mode 100644 btcutil/go.mod create mode 100644 btcutil/go.sum create mode 100644 btcutil/hash160.go create mode 100644 btcutil/hdkeychain/README.md create mode 100644 btcutil/hdkeychain/bench_test.go create mode 100644 btcutil/hdkeychain/cov_report.sh create mode 100644 btcutil/hdkeychain/doc.go create mode 100644 btcutil/hdkeychain/example_test.go create mode 100644 btcutil/hdkeychain/extendedkey.go create mode 100644 btcutil/hdkeychain/extendedkey_test.go create mode 100644 btcutil/hdkeychain/test_coverage.txt create mode 100644 btcutil/internal_test.go create mode 100644 btcutil/net.go create mode 100644 btcutil/net_noop.go create mode 100644 btcutil/psbt/bip32.go create mode 100644 btcutil/psbt/creator.go create mode 100644 btcutil/psbt/extractor.go create mode 100644 btcutil/psbt/finalizer.go create mode 100644 btcutil/psbt/go.mod create mode 100644 btcutil/psbt/go.sum create mode 100644 btcutil/psbt/partial_input.go create mode 100644 btcutil/psbt/partial_output.go create mode 100644 btcutil/psbt/partialsig.go create mode 100644 btcutil/psbt/psbt.go create mode 100644 btcutil/psbt/psbt_test.go create mode 100644 btcutil/psbt/signer.go create mode 100644 btcutil/psbt/sort.go create mode 100644 btcutil/psbt/sort_test.go create mode 100644 btcutil/psbt/types.go create mode 100644 btcutil/psbt/updater.go create mode 100644 btcutil/psbt/utils.go create mode 100644 btcutil/psbt/utils_test.go create mode 100644 btcutil/tx.go create mode 100644 btcutil/tx_test.go create mode 100644 btcutil/txsort/README.md create mode 100644 btcutil/txsort/doc.go create mode 100644 btcutil/txsort/testdata/bip69-1.hex create mode 100644 btcutil/txsort/testdata/bip69-2.hex create mode 100644 btcutil/txsort/testdata/bip69-3.hex create mode 100644 btcutil/txsort/testdata/bip69-4.hex create mode 100644 btcutil/txsort/testdata/bip69-5.hex create mode 100644 btcutil/txsort/txsort.go create mode 100644 btcutil/txsort/txsort_test.go create mode 100644 btcutil/wif.go create mode 100644 btcutil/wif_test.go diff --git a/btcutil/LICENSE b/btcutil/LICENSE new file mode 100644 index 0000000000..3e7b16791f --- /dev/null +++ b/btcutil/LICENSE @@ -0,0 +1,16 @@ +ISC License + +Copyright (c) 2013-2017 The btcsuite developers +Copyright (c) 2016-2017 The Lightning Network Developers + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/btcutil/README.md b/btcutil/README.md new file mode 100644 index 0000000000..ad32607ca5 --- /dev/null +++ b/btcutil/README.md @@ -0,0 +1,49 @@ +btcutil +======= + +[![Build Status](https://github.com/btcsuite/btcd/btcutil/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/btcutil/actions) +[![ISC License](https://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/btcsuite/btcd/btcutil) + +Package btcutil provides bitcoin-specific convenience functions and types. +A comprehensive suite of tests is provided to ensure proper functionality. See +`test_coverage.txt` for the gocov coverage report. Alternatively, if you are +running a POSIX OS, you can run the `cov_report.sh` script for a real-time +report. + +This package was developed for btcd, an alternative full-node implementation of +bitcoin which is under active development by Conformal. Although it was +primarily written for btcd, this package has intentionally been designed so it +can be used as a standalone package for any projects needing the functionality +provided. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil +``` + +## GPG Verification Key + +All official release tags are signed by Conformal so users can ensure the code +has not been tampered with and is coming from the btcsuite developers. To +verify the signature perform the following: + +- Download the public key from the Conformal website at + https://opensource.conformal.com/GIT-GPG-KEY-conformal.txt + +- Import the public key into your GPG keyring: + ```bash + gpg --import GIT-GPG-KEY-conformal.txt + ``` + +- Verify the release tag with the following command where `TAG_NAME` is a + placeholder for the specific tag: + ```bash + git tag -v TAG_NAME + ``` + +## License + +Package btcutil is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/address.go b/btcutil/address.go new file mode 100644 index 0000000000..7f7ccbbd7b --- /dev/null +++ b/btcutil/address.go @@ -0,0 +1,720 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "bytes" + "encoding/hex" + "errors" + "fmt" + "strings" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/btcutil/base58" + "github.com/btcsuite/btcd/btcutil/bech32" + "golang.org/x/crypto/ripemd160" +) + +// UnsupportedWitnessVerError describes an error where a segwit address being +// decoded has an unsupported witness version. +type UnsupportedWitnessVerError byte + +func (e UnsupportedWitnessVerError) Error() string { + return fmt.Sprintf("unsupported witness version: %#x", byte(e)) +} + +// UnsupportedWitnessProgLenError describes an error where a segwit address +// being decoded has an unsupported witness program length. +type UnsupportedWitnessProgLenError int + +func (e UnsupportedWitnessProgLenError) Error() string { + return fmt.Sprintf("unsupported witness program length: %d", int(e)) +} + +var ( + // ErrChecksumMismatch describes an error where decoding failed due + // to a bad checksum. + ErrChecksumMismatch = errors.New("checksum mismatch") + + // ErrUnknownAddressType describes an error where an address can not + // decoded as a specific address type due to the string encoding + // beginning with an identifier byte unknown to any standard or + // registered (via chaincfg.Register) network. + ErrUnknownAddressType = errors.New("unknown address type") + + // ErrAddressCollision describes an error where an address can not + // be uniquely determined as either a pay-to-pubkey-hash or + // pay-to-script-hash address since the leading identifier is used for + // describing both address kinds, but for different networks. Rather + // than assuming or defaulting to one or the other, this error is + // returned and the caller must decide how to decode the address. + ErrAddressCollision = errors.New("address collision") +) + +// encodeAddress returns a human-readable payment address given a ripemd160 hash +// and netID which encodes the bitcoin network and address type. It is used +// in both pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address +// encoding. +func encodeAddress(hash160 []byte, netID byte) string { + // Format is 1 byte for a network and address class (i.e. P2PKH vs + // P2SH), 20 bytes for a RIPEMD160 hash, and 4 bytes of checksum. + return base58.CheckEncode(hash160[:ripemd160.Size], netID) +} + +// encodeSegWitAddress creates a bech32 (or bech32m for SegWit v1) encoded +// address string representation from witness version and witness program. +func encodeSegWitAddress(hrp string, witnessVersion byte, witnessProgram []byte) (string, error) { + // Group the address bytes into 5 bit groups, as this is what is used to + // encode each character in the address string. + converted, err := bech32.ConvertBits(witnessProgram, 8, 5, true) + if err != nil { + return "", err + } + + // Concatenate the witness version and program, and encode the resulting + // bytes using bech32 encoding. + combined := make([]byte, len(converted)+1) + combined[0] = witnessVersion + copy(combined[1:], converted) + + var bech string + switch witnessVersion { + case 0: + bech, err = bech32.Encode(hrp, combined) + + case 1: + bech, err = bech32.EncodeM(hrp, combined) + + default: + return "", fmt.Errorf("unsupported witness version %d", + witnessVersion) + } + if err != nil { + return "", err + } + + // Check validity by decoding the created address. + version, program, err := decodeSegWitAddress(bech) + if err != nil { + return "", fmt.Errorf("invalid segwit address: %v", err) + } + + if version != witnessVersion || !bytes.Equal(program, witnessProgram) { + return "", fmt.Errorf("invalid segwit address") + } + + return bech, nil +} + +// Address is an interface type for any type of destination a transaction +// output may spend to. This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash +// (P2PKH), and pay-to-script-hash (P2SH). Address is designed to be generic +// enough that other kinds of addresses may be added in the future without +// changing the decoding and encoding API. +type Address interface { + // String returns the string encoding of the transaction output + // destination. + // + // Please note that String differs subtly from EncodeAddress: String + // will return the value as a string without any conversion, while + // EncodeAddress may convert destination types (for example, + // converting pubkeys to P2PKH addresses) before encoding as a + // payment address string. + String() string + + // EncodeAddress returns the string encoding of the payment address + // associated with the Address value. See the comment on String + // for how this method differs from String. + EncodeAddress() string + + // ScriptAddress returns the raw bytes of the address to be used + // when inserting the address into a txout's script. + ScriptAddress() []byte + + // IsForNet returns whether or not the address is associated with the + // passed bitcoin network. + IsForNet(*chaincfg.Params) bool +} + +// DecodeAddress decodes the string encoding of an address and returns +// the Address if addr is a valid encoding for a known address type. +// +// The bitcoin network the address is associated with is extracted if possible. +// When the address does not encode the network, such as in the case of a raw +// public key, the address will be associated with the passed defaultNet. +func DecodeAddress(addr string, defaultNet *chaincfg.Params) (Address, error) { + // Bech32 encoded segwit addresses start with a human-readable part + // (hrp) followed by '1'. For Bitcoin mainnet the hrp is "bc", and for + // testnet it is "tb". If the address string has a prefix that matches + // one of the prefixes for the known networks, we try to decode it as + // a segwit address. + oneIndex := strings.LastIndexByte(addr, '1') + if oneIndex > 1 { + prefix := addr[:oneIndex+1] + if chaincfg.IsBech32SegwitPrefix(prefix) { + witnessVer, witnessProg, err := decodeSegWitAddress(addr) + if err != nil { + return nil, err + } + + // We currently only support P2WPKH and P2WSH, which is + // witness version 0 and P2TR which is witness version + // 1. + if witnessVer != 0 && witnessVer != 1 { + return nil, UnsupportedWitnessVerError(witnessVer) + } + + // The HRP is everything before the found '1'. + hrp := prefix[:len(prefix)-1] + + switch len(witnessProg) { + case 20: + return newAddressWitnessPubKeyHash(hrp, witnessProg) + case 32: + if witnessVer == 1 { + return newAddressTaproot(hrp, witnessProg) + } + + return newAddressWitnessScriptHash(hrp, witnessProg) + default: + return nil, UnsupportedWitnessProgLenError(len(witnessProg)) + } + } + } + + // Serialized public keys are either 65 bytes (130 hex chars) if + // uncompressed/hybrid or 33 bytes (66 hex chars) if compressed. + if len(addr) == 130 || len(addr) == 66 { + serializedPubKey, err := hex.DecodeString(addr) + if err != nil { + return nil, err + } + return NewAddressPubKey(serializedPubKey, defaultNet) + } + + // Switch on decoded length to determine the type. + decoded, netID, err := base58.CheckDecode(addr) + if err != nil { + if err == base58.ErrChecksum { + return nil, ErrChecksumMismatch + } + return nil, errors.New("decoded address is of unknown format") + } + switch len(decoded) { + case ripemd160.Size: // P2PKH or P2SH + isP2PKH := netID == defaultNet.PubKeyHashAddrID + isP2SH := netID == defaultNet.ScriptHashAddrID + switch hash160 := decoded; { + case isP2PKH && isP2SH: + return nil, ErrAddressCollision + case isP2PKH: + return newAddressPubKeyHash(hash160, netID) + case isP2SH: + return newAddressScriptHashFromHash(hash160, netID) + default: + return nil, ErrUnknownAddressType + } + + default: + return nil, errors.New("decoded address is of unknown size") + } +} + +// decodeSegWitAddress parses a bech32 encoded segwit address string and +// returns the witness version and witness program byte representation. +func decodeSegWitAddress(address string) (byte, []byte, error) { + // Decode the bech32 encoded address. + _, data, bech32version, err := bech32.DecodeGeneric(address) + if err != nil { + return 0, nil, err + } + + // The first byte of the decoded address is the witness version, it must + // exist. + if len(data) < 1 { + return 0, nil, fmt.Errorf("no witness version") + } + + // ...and be <= 16. + version := data[0] + if version > 16 { + return 0, nil, fmt.Errorf("invalid witness version: %v", version) + } + + // The remaining characters of the address returned are grouped into + // words of 5 bits. In order to restore the original witness program + // bytes, we'll need to regroup into 8 bit words. + regrouped, err := bech32.ConvertBits(data[1:], 5, 8, false) + if err != nil { + return 0, nil, err + } + + // The regrouped data must be between 2 and 40 bytes. + if len(regrouped) < 2 || len(regrouped) > 40 { + return 0, nil, fmt.Errorf("invalid data length") + } + + // For witness version 0, address MUST be exactly 20 or 32 bytes. + if version == 0 && len(regrouped) != 20 && len(regrouped) != 32 { + return 0, nil, fmt.Errorf("invalid data length for witness "+ + "version 0: %v", len(regrouped)) + } + + // For witness version 0, the bech32 encoding must be used. + if version == 0 && bech32version != bech32.Version0 { + return 0, nil, fmt.Errorf("invalid checksum expected bech32 " + + "encoding for address with witness version 0") + } + + // For witness version 1, the bech32m encoding must be used. + if version == 1 && bech32version != bech32.VersionM { + return 0, nil, fmt.Errorf("invalid checksum expected bech32m " + + "encoding for address with witness version 1") + } + + return version, regrouped, nil +} + +// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH) +// transaction. +type AddressPubKeyHash struct { + hash [ripemd160.Size]byte + netID byte +} + +// NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash mustbe 20 +// bytes. +func NewAddressPubKeyHash(pkHash []byte, net *chaincfg.Params) (*AddressPubKeyHash, error) { + return newAddressPubKeyHash(pkHash, net.PubKeyHashAddrID) +} + +// newAddressPubKeyHash is the internal API to create a pubkey hash address +// with a known leading identifier byte for a network, rather than looking +// it up through its parameters. This is useful when creating a new address +// structure from a string encoding where the identifier byte is already +// known. +func newAddressPubKeyHash(pkHash []byte, netID byte) (*AddressPubKeyHash, error) { + // Check for a valid pubkey hash length. + if len(pkHash) != ripemd160.Size { + return nil, errors.New("pkHash must be 20 bytes") + } + + addr := &AddressPubKeyHash{netID: netID} + copy(addr.hash[:], pkHash) + return addr, nil +} + +// EncodeAddress returns the string encoding of a pay-to-pubkey-hash +// address. Part of the Address interface. +func (a *AddressPubKeyHash) EncodeAddress() string { + return encodeAddress(a.hash[:], a.netID) +} + +// ScriptAddress returns the bytes to be included in a txout script to pay +// to a pubkey hash. Part of the Address interface. +func (a *AddressPubKeyHash) ScriptAddress() []byte { + return a.hash[:] +} + +// IsForNet returns whether or not the pay-to-pubkey-hash address is associated +// with the passed bitcoin network. +func (a *AddressPubKeyHash) IsForNet(net *chaincfg.Params) bool { + return a.netID == net.PubKeyHashAddrID +} + +// String returns a human-readable string for the pay-to-pubkey-hash address. +// This is equivalent to calling EncodeAddress, but is provided so the type can +// be used as a fmt.Stringer. +func (a *AddressPubKeyHash) String() string { + return a.EncodeAddress() +} + +// Hash160 returns the underlying array of the pubkey hash. This can be useful +// when an array is more appropriate than a slice (for example, when used as map +// keys). +func (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte { + return &a.hash +} + +// AddressScriptHash is an Address for a pay-to-script-hash (P2SH) +// transaction. +type AddressScriptHash struct { + hash [ripemd160.Size]byte + netID byte +} + +// NewAddressScriptHash returns a new AddressScriptHash. +func NewAddressScriptHash(serializedScript []byte, net *chaincfg.Params) (*AddressScriptHash, error) { + scriptHash := Hash160(serializedScript) + return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID) +} + +// NewAddressScriptHashFromHash returns a new AddressScriptHash. scriptHash +// must be 20 bytes. +func NewAddressScriptHashFromHash(scriptHash []byte, net *chaincfg.Params) (*AddressScriptHash, error) { + return newAddressScriptHashFromHash(scriptHash, net.ScriptHashAddrID) +} + +// newAddressScriptHashFromHash is the internal API to create a script hash +// address with a known leading identifier byte for a network, rather than +// looking it up through its parameters. This is useful when creating a new +// address structure from a string encoding where the identifier byte is already +// known. +func newAddressScriptHashFromHash(scriptHash []byte, netID byte) (*AddressScriptHash, error) { + // Check for a valid script hash length. + if len(scriptHash) != ripemd160.Size { + return nil, errors.New("scriptHash must be 20 bytes") + } + + addr := &AddressScriptHash{netID: netID} + copy(addr.hash[:], scriptHash) + return addr, nil +} + +// EncodeAddress returns the string encoding of a pay-to-script-hash +// address. Part of the Address interface. +func (a *AddressScriptHash) EncodeAddress() string { + return encodeAddress(a.hash[:], a.netID) +} + +// ScriptAddress returns the bytes to be included in a txout script to pay +// to a script hash. Part of the Address interface. +func (a *AddressScriptHash) ScriptAddress() []byte { + return a.hash[:] +} + +// IsForNet returns whether or not the pay-to-script-hash address is associated +// with the passed bitcoin network. +func (a *AddressScriptHash) IsForNet(net *chaincfg.Params) bool { + return a.netID == net.ScriptHashAddrID +} + +// String returns a human-readable string for the pay-to-script-hash address. +// This is equivalent to calling EncodeAddress, but is provided so the type can +// be used as a fmt.Stringer. +func (a *AddressScriptHash) String() string { + return a.EncodeAddress() +} + +// Hash160 returns the underlying array of the script hash. This can be useful +// when an array is more appropriate than a slice (for example, when used as map +// keys). +func (a *AddressScriptHash) Hash160() *[ripemd160.Size]byte { + return &a.hash +} + +// PubKeyFormat describes what format to use for a pay-to-pubkey address. +type PubKeyFormat int + +const ( + // PKFUncompressed indicates the pay-to-pubkey address format is an + // uncompressed public key. + PKFUncompressed PubKeyFormat = iota + + // PKFCompressed indicates the pay-to-pubkey address format is a + // compressed public key. + PKFCompressed + + // PKFHybrid indicates the pay-to-pubkey address format is a hybrid + // public key. + PKFHybrid +) + +// AddressPubKey is an Address for a pay-to-pubkey transaction. +type AddressPubKey struct { + pubKeyFormat PubKeyFormat + pubKey *btcec.PublicKey + pubKeyHashID byte +} + +// NewAddressPubKey returns a new AddressPubKey which represents a pay-to-pubkey +// address. The serializedPubKey parameter must be a valid pubkey and can be +// uncompressed, compressed, or hybrid. +func NewAddressPubKey(serializedPubKey []byte, net *chaincfg.Params) (*AddressPubKey, error) { + pubKey, err := btcec.ParsePubKey(serializedPubKey, btcec.S256()) + if err != nil { + return nil, err + } + + // Set the format of the pubkey. This probably should be returned + // from btcec, but do it here to avoid API churn. We already know the + // pubkey is valid since it parsed above, so it's safe to simply examine + // the leading byte to get the format. + pkFormat := PKFUncompressed + switch serializedPubKey[0] { + case 0x02, 0x03: + pkFormat = PKFCompressed + case 0x06, 0x07: + pkFormat = PKFHybrid + } + + return &AddressPubKey{ + pubKeyFormat: pkFormat, + pubKey: pubKey, + pubKeyHashID: net.PubKeyHashAddrID, + }, nil +} + +// serialize returns the serialization of the public key according to the +// format associated with the address. +func (a *AddressPubKey) serialize() []byte { + switch a.pubKeyFormat { + default: + fallthrough + case PKFUncompressed: + return a.pubKey.SerializeUncompressed() + + case PKFCompressed: + return a.pubKey.SerializeCompressed() + + case PKFHybrid: + return a.pubKey.SerializeHybrid() + } +} + +// EncodeAddress returns the string encoding of the public key as a +// pay-to-pubkey-hash. Note that the public key format (uncompressed, +// compressed, etc) will change the resulting address. This is expected since +// pay-to-pubkey-hash is a hash of the serialized public key which obviously +// differs with the format. At the time of this writing, most Bitcoin addresses +// are pay-to-pubkey-hash constructed from the uncompressed public key. +// +// Part of the Address interface. +func (a *AddressPubKey) EncodeAddress() string { + return encodeAddress(Hash160(a.serialize()), a.pubKeyHashID) +} + +// ScriptAddress returns the bytes to be included in a txout script to pay +// to a public key. Setting the public key format will affect the output of +// this function accordingly. Part of the Address interface. +func (a *AddressPubKey) ScriptAddress() []byte { + return a.serialize() +} + +// IsForNet returns whether or not the pay-to-pubkey address is associated +// with the passed bitcoin network. +func (a *AddressPubKey) IsForNet(net *chaincfg.Params) bool { + return a.pubKeyHashID == net.PubKeyHashAddrID +} + +// String returns the hex-encoded human-readable string for the pay-to-pubkey +// address. This is not the same as calling EncodeAddress. +func (a *AddressPubKey) String() string { + return hex.EncodeToString(a.serialize()) +} + +// Format returns the format (uncompressed, compressed, etc) of the +// pay-to-pubkey address. +func (a *AddressPubKey) Format() PubKeyFormat { + return a.pubKeyFormat +} + +// SetFormat sets the format (uncompressed, compressed, etc) of the +// pay-to-pubkey address. +func (a *AddressPubKey) SetFormat(pkFormat PubKeyFormat) { + a.pubKeyFormat = pkFormat +} + +// AddressPubKeyHash returns the pay-to-pubkey address converted to a +// pay-to-pubkey-hash address. Note that the public key format (uncompressed, +// compressed, etc) will change the resulting address. This is expected since +// pay-to-pubkey-hash is a hash of the serialized public key which obviously +// differs with the format. At the time of this writing, most Bitcoin addresses +// are pay-to-pubkey-hash constructed from the uncompressed public key. +func (a *AddressPubKey) AddressPubKeyHash() *AddressPubKeyHash { + addr := &AddressPubKeyHash{netID: a.pubKeyHashID} + copy(addr.hash[:], Hash160(a.serialize())) + return addr +} + +// PubKey returns the underlying public key for the address. +func (a *AddressPubKey) PubKey() *btcec.PublicKey { + return a.pubKey +} + +// AddressSegWit is the base address type for all SegWit addresses. +type AddressSegWit struct { + hrp string + witnessVersion byte + witnessProgram []byte +} + +// EncodeAddress returns the bech32 (or bech32m for SegWit v1) string encoding +// of an AddressSegWit. +// +// NOTE: This method is part of the Address interface. +func (a *AddressSegWit) EncodeAddress() string { + str, err := encodeSegWitAddress( + a.hrp, a.witnessVersion, a.witnessProgram[:], + ) + if err != nil { + return "" + } + return str +} + +// ScriptAddress returns the witness program for this address. +// +// NOTE: This method is part of the Address interface. +func (a *AddressSegWit) ScriptAddress() []byte { + return a.witnessProgram[:] +} + +// IsForNet returns whether the AddressSegWit is associated with the passed +// bitcoin network. +// +// NOTE: This method is part of the Address interface. +func (a *AddressSegWit) IsForNet(net *chaincfg.Params) bool { + return a.hrp == net.Bech32HRPSegwit +} + +// String returns a human-readable string for the AddressWitnessPubKeyHash. +// This is equivalent to calling EncodeAddress, but is provided so the type +// can be used as a fmt.Stringer. +// +// NOTE: This method is part of the Address interface. +func (a *AddressSegWit) String() string { + return a.EncodeAddress() +} + +// Hrp returns the human-readable part of the bech32 (or bech32m for SegWit v1) +// encoded AddressSegWit. +func (a *AddressSegWit) Hrp() string { + return a.hrp +} + +// WitnessVersion returns the witness version of the AddressSegWit. +func (a *AddressSegWit) WitnessVersion() byte { + return a.witnessVersion +} + +// WitnessProgram returns the witness program of the AddressSegWit. +func (a *AddressSegWit) WitnessProgram() []byte { + return a.witnessProgram[:] +} + +// AddressWitnessPubKeyHash is an Address for a pay-to-witness-pubkey-hash +// (P2WPKH) output. See BIP 173 for further details regarding native segregated +// witness address encoding: +// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki +type AddressWitnessPubKeyHash struct { + AddressSegWit +} + +// NewAddressWitnessPubKeyHash returns a new AddressWitnessPubKeyHash. +func NewAddressWitnessPubKeyHash(witnessProg []byte, + net *chaincfg.Params) (*AddressWitnessPubKeyHash, error) { + + return newAddressWitnessPubKeyHash(net.Bech32HRPSegwit, witnessProg) +} + +// newAddressWitnessPubKeyHash is an internal helper function to create an +// AddressWitnessPubKeyHash with a known human-readable part, rather than +// looking it up through its parameters. +func newAddressWitnessPubKeyHash(hrp string, + witnessProg []byte) (*AddressWitnessPubKeyHash, error) { + + // Check for valid program length for witness version 0, which is 20 + // for P2WPKH. + if len(witnessProg) != 20 { + return nil, errors.New("witness program must be 20 " + + "bytes for p2wpkh") + } + + addr := &AddressWitnessPubKeyHash{ + AddressSegWit{ + hrp: strings.ToLower(hrp), + witnessVersion: 0x00, + witnessProgram: witnessProg, + }, + } + + return addr, nil +} + +// Hash160 returns the witness program of the AddressWitnessPubKeyHash as a +// byte array. +func (a *AddressWitnessPubKeyHash) Hash160() *[20]byte { + var pubKeyHashWitnessProgram [20]byte + copy(pubKeyHashWitnessProgram[:], a.witnessProgram) + return &pubKeyHashWitnessProgram +} + +// AddressWitnessScriptHash is an Address for a pay-to-witness-script-hash +// (P2WSH) output. See BIP 173 for further details regarding native segregated +// witness address encoding: +// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki +type AddressWitnessScriptHash struct { + AddressSegWit +} + +// NewAddressWitnessScriptHash returns a new AddressWitnessPubKeyHash. +func NewAddressWitnessScriptHash(witnessProg []byte, + net *chaincfg.Params) (*AddressWitnessScriptHash, error) { + + return newAddressWitnessScriptHash(net.Bech32HRPSegwit, witnessProg) +} + +// newAddressWitnessScriptHash is an internal helper function to create an +// AddressWitnessScriptHash with a known human-readable part, rather than +// looking it up through its parameters. +func newAddressWitnessScriptHash(hrp string, + witnessProg []byte) (*AddressWitnessScriptHash, error) { + + // Check for valid program length for witness version 0, which is 32 + // for P2WSH. + if len(witnessProg) != 32 { + return nil, errors.New("witness program must be 32 " + + "bytes for p2wsh") + } + + addr := &AddressWitnessScriptHash{ + AddressSegWit{ + hrp: strings.ToLower(hrp), + witnessVersion: 0x00, + witnessProgram: witnessProg, + }, + } + + return addr, nil +} + +// AddressTaproot is an Address for a pay-to-taproot (P2TR) output. See BIP 341 +// for further details. +type AddressTaproot struct { + AddressSegWit +} + +// NewAddressTaproot returns a new AddressTaproot. +func NewAddressTaproot(witnessProg []byte, + net *chaincfg.Params) (*AddressTaproot, error) { + + return newAddressTaproot(net.Bech32HRPSegwit, witnessProg) +} + +// newAddressWitnessScriptHash is an internal helper function to create an +// AddressWitnessScriptHash with a known human-readable part, rather than +// looking it up through its parameters. +func newAddressTaproot(hrp string, + witnessProg []byte) (*AddressTaproot, error) { + + // Check for valid program length for witness version 1, which is 32 + // for P2TR. + if len(witnessProg) != 32 { + return nil, errors.New("witness program must be 32 bytes for " + + "p2tr") + } + + addr := &AddressTaproot{ + AddressSegWit{ + hrp: strings.ToLower(hrp), + witnessVersion: 0x01, + witnessProgram: witnessProg, + }, + } + + return addr, nil +} diff --git a/btcutil/address_test.go b/btcutil/address_test.go new file mode 100644 index 0000000000..52472b7923 --- /dev/null +++ b/btcutil/address_test.go @@ -0,0 +1,1012 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil_test + +import ( + "bytes" + "encoding/hex" + "fmt" + "reflect" + "strings" + "testing" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" + "golang.org/x/crypto/ripemd160" +) + +type CustomParamStruct struct { + Net wire.BitcoinNet + PubKeyHashAddrID byte + ScriptHashAddrID byte + Bech32HRPSegwit string +} + +var CustomParams = CustomParamStruct{ + Net: 0xdbb6c0fb, // litecoin mainnet HD version bytes + PubKeyHashAddrID: 0x30, // starts with L + ScriptHashAddrID: 0x32, // starts with M + Bech32HRPSegwit: "ltc", // starts with ltc +} + +// We use this function to be able to test functionality in DecodeAddress for +// defaultNet addresses +func applyCustomParams(params chaincfg.Params, customParams CustomParamStruct) chaincfg.Params { + params.Net = customParams.Net + params.PubKeyHashAddrID = customParams.PubKeyHashAddrID + params.ScriptHashAddrID = customParams.ScriptHashAddrID + params.Bech32HRPSegwit = customParams.Bech32HRPSegwit + return params +} + +var customParams = applyCustomParams(chaincfg.MainNetParams, CustomParams) + +func TestAddresses(t *testing.T) { + tests := []struct { + name string + addr string + encoded string + valid bool + result btcutil.Address + f func() (btcutil.Address, error) + net *chaincfg.Params + }{ + // Positive P2PKH tests. + { + name: "mainnet p2pkh", + addr: "1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", + encoded: "1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", + valid: true, + result: btcutil.TstAddressPubKeyHash( + [ripemd160.Size]byte{ + 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, + 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84}, + chaincfg.MainNetParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, + 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84} + return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "mainnet p2pkh 2", + addr: "12MzCDwodF9G1e7jfwLXfR164RNtx4BRVG", + encoded: "12MzCDwodF9G1e7jfwLXfR164RNtx4BRVG", + valid: true, + result: btcutil.TstAddressPubKeyHash( + [ripemd160.Size]byte{ + 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, + 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa}, + chaincfg.MainNetParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, + 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa} + return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "litecoin mainnet p2pkh", + addr: "LM2WMpR1Rp6j3Sa59cMXMs1SPzj9eXpGc1", + encoded: "LM2WMpR1Rp6j3Sa59cMXMs1SPzj9eXpGc1", + valid: true, + result: btcutil.TstAddressPubKeyHash( + [ripemd160.Size]byte{ + 0x13, 0xc6, 0x0d, 0x8e, 0x68, 0xd7, 0x34, 0x9f, 0x5b, 0x4c, + 0xa3, 0x62, 0xc3, 0x95, 0x4b, 0x15, 0x04, 0x50, 0x61, 0xb1}, + CustomParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0x13, 0xc6, 0x0d, 0x8e, 0x68, 0xd7, 0x34, 0x9f, 0x5b, 0x4c, + 0xa3, 0x62, 0xc3, 0x95, 0x4b, 0x15, 0x04, 0x50, 0x61, 0xb1} + return btcutil.NewAddressPubKeyHash(pkHash, &customParams) + }, + net: &customParams, + }, + { + name: "testnet p2pkh", + addr: "mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", + encoded: "mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", + valid: true, + result: btcutil.TstAddressPubKeyHash( + [ripemd160.Size]byte{ + 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, + 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f}, + chaincfg.TestNet3Params.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, + 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f} + return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + + // Negative P2PKH tests. + { + name: "p2pkh wrong hash length", + addr: "", + valid: false, + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0x00, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, + 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, + 0xaa} + return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "p2pkh bad checksum", + addr: "1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gY", + valid: false, + net: &chaincfg.MainNetParams, + }, + + // Positive P2SH tests. + { + // Taken from transactions: + // output: 3c9018e8d5615c306d72397f8f5eef44308c98fb576a88e030c25456b4f3a7ac + // input: 837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba. + name: "mainnet p2sh", + addr: "3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC", + encoded: "3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC", + valid: true, + result: btcutil.TstAddressScriptHash( + [ripemd160.Size]byte{ + 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0xf2, + 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0x10}, + chaincfg.MainNetParams.ScriptHashAddrID), + f: func() (btcutil.Address, error) { + script := []byte{ + 0x52, 0x41, 0x04, 0x91, 0xbb, 0xa2, 0x51, 0x09, 0x12, 0xa5, + 0xbd, 0x37, 0xda, 0x1f, 0xb5, 0xb1, 0x67, 0x30, 0x10, 0xe4, + 0x3d, 0x2c, 0x6d, 0x81, 0x2c, 0x51, 0x4e, 0x91, 0xbf, 0xa9, + 0xf2, 0xeb, 0x12, 0x9e, 0x1c, 0x18, 0x33, 0x29, 0xdb, 0x55, + 0xbd, 0x86, 0x8e, 0x20, 0x9a, 0xac, 0x2f, 0xbc, 0x02, 0xcb, + 0x33, 0xd9, 0x8f, 0xe7, 0x4b, 0xf2, 0x3f, 0x0c, 0x23, 0x5d, + 0x61, 0x26, 0xb1, 0xd8, 0x33, 0x4f, 0x86, 0x41, 0x04, 0x86, + 0x5c, 0x40, 0x29, 0x3a, 0x68, 0x0c, 0xb9, 0xc0, 0x20, 0xe7, + 0xb1, 0xe1, 0x06, 0xd8, 0xc1, 0x91, 0x6d, 0x3c, 0xef, 0x99, + 0xaa, 0x43, 0x1a, 0x56, 0xd2, 0x53, 0xe6, 0x92, 0x56, 0xda, + 0xc0, 0x9e, 0xf1, 0x22, 0xb1, 0xa9, 0x86, 0x81, 0x8a, 0x7c, + 0xb6, 0x24, 0x53, 0x2f, 0x06, 0x2c, 0x1d, 0x1f, 0x87, 0x22, + 0x08, 0x48, 0x61, 0xc5, 0xc3, 0x29, 0x1c, 0xcf, 0xfe, 0xf4, + 0xec, 0x68, 0x74, 0x41, 0x04, 0x8d, 0x24, 0x55, 0xd2, 0x40, + 0x3e, 0x08, 0x70, 0x8f, 0xc1, 0xf5, 0x56, 0x00, 0x2f, 0x1b, + 0x6c, 0xd8, 0x3f, 0x99, 0x2d, 0x08, 0x50, 0x97, 0xf9, 0x97, + 0x4a, 0xb0, 0x8a, 0x28, 0x83, 0x8f, 0x07, 0x89, 0x6f, 0xba, + 0xb0, 0x8f, 0x39, 0x49, 0x5e, 0x15, 0xfa, 0x6f, 0xad, 0x6e, + 0xdb, 0xfb, 0x1e, 0x75, 0x4e, 0x35, 0xfa, 0x1c, 0x78, 0x44, + 0xc4, 0x1f, 0x32, 0x2a, 0x18, 0x63, 0xd4, 0x62, 0x13, 0x53, + 0xae} + return btcutil.NewAddressScriptHash(script, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "litecoin mainnet P2SH ", + addr: "MVcg9uEvtWuP5N6V48EHfEtbz48qR8TKZ9", + encoded: "MVcg9uEvtWuP5N6V48EHfEtbz48qR8TKZ9", + valid: true, + result: btcutil.TstAddressScriptHash( + [ripemd160.Size]byte{ + 0xee, 0x34, 0xac, 0x67, 0x6b, 0xda, 0xf6, 0xe3, 0x70, 0xc8, + 0xc8, 0x20, 0xb9, 0x48, 0xed, 0xfa, 0xd3, 0xa8, 0x73, 0xd8}, + CustomParams.ScriptHashAddrID), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0xEE, 0x34, 0xAC, 0x67, 0x6B, 0xDA, 0xF6, 0xE3, 0x70, 0xC8, + 0xC8, 0x20, 0xB9, 0x48, 0xED, 0xFA, 0xD3, 0xA8, 0x73, 0xD8} + return btcutil.NewAddressScriptHashFromHash(pkHash, &customParams) + }, + net: &customParams, + }, + { + // Taken from transactions: + // output: b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d + // input: (not yet redeemed at time test was written) + name: "mainnet p2sh 2", + addr: "3NukJ6fYZJ5Kk8bPjycAnruZkE5Q7UW7i8", + encoded: "3NukJ6fYZJ5Kk8bPjycAnruZkE5Q7UW7i8", + valid: true, + result: btcutil.TstAddressScriptHash( + [ripemd160.Size]byte{ + 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, + 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4}, + chaincfg.MainNetParams.ScriptHashAddrID), + f: func() (btcutil.Address, error) { + hash := []byte{ + 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, + 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4} + return btcutil.NewAddressScriptHashFromHash(hash, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + // Taken from bitcoind base58_keys_valid. + name: "testnet p2sh", + addr: "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", + encoded: "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", + valid: true, + result: btcutil.TstAddressScriptHash( + [ripemd160.Size]byte{ + 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, + 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a}, + chaincfg.TestNet3Params.ScriptHashAddrID), + f: func() (btcutil.Address, error) { + hash := []byte{ + 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, + 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a} + return btcutil.NewAddressScriptHashFromHash(hash, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + + // Negative P2SH tests. + { + name: "p2sh wrong hash length", + addr: "", + valid: false, + f: func() (btcutil.Address, error) { + hash := []byte{ + 0x00, 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, + 0xf2, 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, + 0x10} + return btcutil.NewAddressScriptHashFromHash(hash, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + + // Positive P2PK tests. + { + name: "mainnet p2pk compressed (0x02)", + addr: "02192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4", + encoded: "13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4}, + btcutil.PKFCompressed, chaincfg.MainNetParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "mainnet p2pk compressed (0x03)", + addr: "03b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65", + encoded: "15sHANNUBSh6nDp8XkDPmQcW6n3EFwmvE6", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65}, + btcutil.PKFCompressed, chaincfg.MainNetParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "mainnet p2pk uncompressed (0x04)", + addr: "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2" + + "e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3", + encoded: "12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3}, + btcutil.PKFUncompressed, chaincfg.MainNetParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "mainnet p2pk hybrid (0x06)", + addr: "06192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4" + + "0d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453e", + encoded: "1Ja5rs7XBZnK88EuLVcFqYGMEbBitzchmX", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, + 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, + 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, + 0x44, 0xd3, 0x3f, 0x45, 0x3e}, + btcutil.PKFHybrid, chaincfg.MainNetParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, + 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, + 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, + 0x44, 0xd3, 0x3f, 0x45, 0x3e} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "mainnet p2pk hybrid (0x07)", + addr: "07b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65" + + "37a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b", + encoded: "1ExqMmf6yMxcBMzHjbj41wbqYuqoX6uBLG", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, + 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, + 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, + 0x1e, 0x09, 0x08, 0xef, 0x7b}, + btcutil.PKFHybrid, chaincfg.MainNetParams.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, + 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, + 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, + 0x1e, 0x09, 0x08, 0xef, 0x7b} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "testnet p2pk compressed (0x02)", + addr: "02192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4", + encoded: "mhiDPVP2nJunaAgTjzWSHCYfAqxxrxzjmo", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4}, + btcutil.PKFCompressed, chaincfg.TestNet3Params.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + { + name: "testnet p2pk compressed (0x03)", + addr: "03b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65", + encoded: "mkPETRTSzU8MZLHkFKBmbKppxmdw9qT42t", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65}, + btcutil.PKFCompressed, chaincfg.TestNet3Params.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + { + name: "testnet p2pk uncompressed (0x04)", + addr: "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5" + + "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3", + encoded: "mh8YhPYEAYs3E7EVyKtB5xrcfMExkkdEMF", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3}, + btcutil.PKFUncompressed, chaincfg.TestNet3Params.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, + 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, + 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, + 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, + 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, + 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, + 0xf6, 0x56, 0xb4, 0x12, 0xa3} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + { + name: "testnet p2pk hybrid (0x06)", + addr: "06192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b" + + "40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453e", + encoded: "my639vCVzbDZuEiX44adfTUg6anRomZLEP", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, + 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, + 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, + 0x44, 0xd3, 0x3f, 0x45, 0x3e}, + btcutil.PKFHybrid, chaincfg.TestNet3Params.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, + 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, + 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, + 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, + 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, + 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, + 0x44, 0xd3, 0x3f, 0x45, 0x3e} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + { + name: "testnet p2pk hybrid (0x07)", + addr: "07b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e6" + + "537a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b", + encoded: "muUnepk5nPPrxUTuTAhRqrpAQuSWS5fVii", + valid: true, + result: btcutil.TstAddressPubKey( + []byte{ + 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, + 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, + 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, + 0x1e, 0x09, 0x08, 0xef, 0x7b}, + btcutil.PKFHybrid, chaincfg.TestNet3Params.PubKeyHashAddrID), + f: func() (btcutil.Address, error) { + serializedPubKey := []byte{ + 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, + 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, + 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, + 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, + 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, + 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, + 0x1e, 0x09, 0x08, 0xef, 0x7b} + return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + // Segwit address tests. + { + name: "segwit mainnet p2wpkh v0", + addr: "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", + encoded: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", + valid: true, + result: btcutil.TstAddressWitnessPubKeyHash( + 0, + [20]byte{ + 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, + 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}, + chaincfg.MainNetParams.Bech32HRPSegwit), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, + 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6} + return btcutil.NewAddressWitnessPubKeyHash(pkHash, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit mainnet p2wsh v0", + addr: "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", + encoded: "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", + valid: true, + result: btcutil.TstAddressWitnessScriptHash( + 0, + [32]byte{ + 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, + 0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, + 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1, + 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}, + chaincfg.MainNetParams.Bech32HRPSegwit), + f: func() (btcutil.Address, error) { + scriptHash := []byte{ + 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, + 0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, + 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1, + 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62} + return btcutil.NewAddressWitnessScriptHash(scriptHash, &chaincfg.MainNetParams) + }, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit testnet p2wpkh v0", + addr: "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx", + encoded: "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx", + valid: true, + result: btcutil.TstAddressWitnessPubKeyHash( + 0, + [20]byte{ + 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, + 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}, + chaincfg.TestNet3Params.Bech32HRPSegwit), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, + 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6} + return btcutil.NewAddressWitnessPubKeyHash(pkHash, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit testnet p2wsh v0", + addr: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", + encoded: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", + valid: true, + result: btcutil.TstAddressWitnessScriptHash( + 0, + [32]byte{ + 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, + 0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, + 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1, + 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62}, + chaincfg.TestNet3Params.Bech32HRPSegwit), + f: func() (btcutil.Address, error) { + scriptHash := []byte{ + 0x18, 0x63, 0x14, 0x3c, 0x14, 0xc5, 0x16, 0x68, + 0x04, 0xbd, 0x19, 0x20, 0x33, 0x56, 0xda, 0x13, + 0x6c, 0x98, 0x56, 0x78, 0xcd, 0x4d, 0x27, 0xa1, + 0xb8, 0xc6, 0x32, 0x96, 0x04, 0x90, 0x32, 0x62} + return btcutil.NewAddressWitnessScriptHash(scriptHash, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit testnet p2wsh witness v0", + addr: "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", + encoded: "tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", + valid: true, + result: btcutil.TstAddressWitnessScriptHash( + 0, + [32]byte{ + 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, + 0x21, 0xb2, 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, + 0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c, 0x6c, 0xe2, + 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33}, + chaincfg.TestNet3Params.Bech32HRPSegwit), + f: func() (btcutil.Address, error) { + scriptHash := []byte{ + 0x00, 0x00, 0x00, 0xc4, 0xa5, 0xca, 0xd4, 0x62, + 0x21, 0xb2, 0xa1, 0x87, 0x90, 0x5e, 0x52, 0x66, + 0x36, 0x2b, 0x99, 0xd5, 0xe9, 0x1c, 0x6c, 0xe2, + 0x4d, 0x16, 0x5d, 0xab, 0x93, 0xe8, 0x64, 0x33} + return btcutil.NewAddressWitnessScriptHash(scriptHash, &chaincfg.TestNet3Params) + }, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit litecoin mainnet p2wpkh v0", + addr: "LTC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KGMN4N9", + encoded: "ltc1qw508d6qejxtdg4y5r3zarvary0c5xw7kgmn4n9", + valid: true, + result: btcutil.TstAddressWitnessPubKeyHash( + 0, + [20]byte{ + 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, + 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6}, + CustomParams.Bech32HRPSegwit, + ), + f: func() (btcutil.Address, error) { + pkHash := []byte{ + 0x75, 0x1e, 0x76, 0xe8, 0x19, 0x91, 0x96, 0xd4, 0x54, 0x94, + 0x1c, 0x45, 0xd1, 0xb3, 0xa3, 0x23, 0xf1, 0x43, 0x3b, 0xd6} + return btcutil.NewAddressWitnessPubKeyHash(pkHash, &customParams) + }, + net: &customParams, + }, + + // P2TR address tests. + { + name: "segwit v1 mainnet p2tr", + addr: "bc1paardr2nczq0rx5rqpfwnvpzm497zvux64y0f7wjgcs7xuuuh2nnqwr2d5c", + encoded: "bc1paardr2nczq0rx5rqpfwnvpzm497zvux64y0f7wjgcs7xuuuh2nnqwr2d5c", + valid: true, + result: btcutil.TstAddressTaproot( + 1, [32]byte{ + 0xef, 0x46, 0xd1, 0xaa, 0x78, 0x10, 0x1e, 0x33, + 0x50, 0x60, 0x0a, 0x5d, 0x36, 0x04, 0x5b, 0xa9, + 0x7c, 0x26, 0x70, 0xda, 0xa9, 0x1e, 0x9f, 0x3a, + 0x48, 0xc4, 0x3c, 0x6e, 0x73, 0x97, 0x54, 0xe6, + }, chaincfg.MainNetParams.Bech32HRPSegwit, + ), + f: func() (btcutil.Address, error) { + scriptHash := []byte{ + 0xef, 0x46, 0xd1, 0xaa, 0x78, 0x10, 0x1e, 0x33, + 0x50, 0x60, 0x0a, 0x5d, 0x36, 0x04, 0x5b, 0xa9, + 0x7c, 0x26, 0x70, 0xda, 0xa9, 0x1e, 0x9f, 0x3a, + 0x48, 0xc4, 0x3c, 0x6e, 0x73, 0x97, 0x54, 0xe6, + } + return btcutil.NewAddressTaproot( + scriptHash, &chaincfg.MainNetParams, + ) + }, + net: &chaincfg.MainNetParams, + }, + + // Invalid bech32m tests. Source: + // https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki + { + name: "segwit v1 invalid human-readable part", + addr: "tc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq5zuyut", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v1 mainnet bech32 instead of bech32m", + addr: "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqh2y7hd", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v1 testnet bech32 instead of bech32m", + addr: "tb1z0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqglt7rf", + valid: false, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit v1 mainnet bech32 instead of bech32m upper case", + addr: "BC1S0XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ54WELL", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v0 mainnet bech32m instead of bech32", + addr: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kemeawh", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v1 testnet bech32 instead of bech32m second test", + addr: "tb1q0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq24jc47", + valid: false, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit v1 mainnet bech32m invalid character in checksum", + addr: "bc1p38j9r5y49hruaue7wxjce0updqjuyyx0kh56v8s25huc6995vvpql3jow4", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit mainnet witness v17", + addr: "BC130XLXVLHEMJA6C4DQV22UAPCTQUPFHLXM9H8Z3K2E72Q4K9HCZ7VQ7ZWS8R", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v1 mainnet bech32m invalid program length (1 byte)", + addr: "bc1pw5dgrnzv", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v1 mainnet bech32m invalid program length (41 bytes)", + addr: "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v8n0nx0muaewav253zgeav", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v1 testnet bech32m mixed case", + addr: "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vq47Zagq", + valid: false, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit v1 mainnet bech32m zero padding of more than 4 bits", + addr: "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7v07qwwzcrf", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit v1 mainnet bech32m non-zero padding in 8-to-5-conversion", + addr: "tb1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vpggkg4j", + valid: false, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit v1 mainnet bech32m empty data section", + addr: "bc1gmk9yu", + valid: false, + net: &chaincfg.MainNetParams, + }, + + // Unsupported witness versions (version 0 and 1 only supported at this point) + { + name: "segwit mainnet witness v16", + addr: "BC1SW50QA3JX3S", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit mainnet witness v2", + addr: "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", + valid: false, + net: &chaincfg.MainNetParams, + }, + // Invalid segwit addresses + { + name: "segwit invalid hrp", + addr: "tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty", + valid: false, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit invalid checksum", + addr: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t5", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit invalid witness version", + addr: "BC13W508D6QEJXTDG4Y5R3ZARVARY0C5XW7KN40WF2", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit invalid program length", + addr: "bc1rw5uspcuh", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit invalid program length", + addr: "bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit invalid program length for witness version 0 (per BIP141)", + addr: "BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P", + valid: false, + net: &chaincfg.MainNetParams, + }, + { + name: "segwit mixed case", + addr: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sL5k7", + valid: false, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit zero padding of more than 4 bits", + addr: "tb1pw508d6qejxtdg4y5r3zarqfsj6c3", + valid: false, + net: &chaincfg.TestNet3Params, + }, + { + name: "segwit non-zero padding in 8-to-5 conversion", + addr: "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv", + valid: false, + net: &chaincfg.TestNet3Params, + }, + } + + if err := chaincfg.Register(&customParams); err != nil { + panic(err) + } + + for _, test := range tests { + // Decode addr and compare error against valid. + decoded, err := btcutil.DecodeAddress(test.addr, test.net) + if (err == nil) != test.valid { + t.Errorf("%v: decoding test failed: %v", test.name, err) + return + } + + if err == nil { + // Ensure the stringer returns the same address as the + // original. + if decodedStringer, ok := decoded.(fmt.Stringer); ok { + addr := test.addr + + // For Segwit addresses the string representation + // will always be lower case, so in that case we + // convert the original to lower case first. + if strings.Contains(test.name, "segwit") { + addr = strings.ToLower(addr) + } + + if addr != decodedStringer.String() { + t.Errorf("%v: String on decoded value does not match expected value: %v != %v", + test.name, test.addr, decodedStringer.String()) + return + } + } + + // Encode again and compare against the original. + encoded := decoded.EncodeAddress() + if test.encoded != encoded { + t.Errorf("%v: decoding and encoding produced different addresses: %v != %v", + test.name, test.encoded, encoded) + return + } + + // Perform type-specific calculations. + var saddr []byte + switch d := decoded.(type) { + case *btcutil.AddressPubKeyHash: + saddr = btcutil.TstAddressSAddr(encoded) + + case *btcutil.AddressScriptHash: + saddr = btcutil.TstAddressSAddr(encoded) + + case *btcutil.AddressPubKey: + // Ignore the error here since the script + // address is checked below. + saddr, _ = hex.DecodeString(d.String()) + case *btcutil.AddressWitnessPubKeyHash: + saddr = btcutil.TstAddressSegwitSAddr(encoded) + case *btcutil.AddressWitnessScriptHash: + saddr = btcutil.TstAddressSegwitSAddr(encoded) + case *btcutil.AddressTaproot: + saddr = btcutil.TstAddressTaprootSAddr(encoded) + } + + // Check script address, as well as the Hash160 method for P2PKH and + // P2SH addresses. + if !bytes.Equal(saddr, decoded.ScriptAddress()) { + t.Errorf("%v: script addresses do not match:\n%x != \n%x", + test.name, saddr, decoded.ScriptAddress()) + return + } + switch a := decoded.(type) { + case *btcutil.AddressPubKeyHash: + if h := a.Hash160()[:]; !bytes.Equal(saddr, h) { + t.Errorf("%v: hashes do not match:\n%x != \n%x", + test.name, saddr, h) + return + } + + case *btcutil.AddressScriptHash: + if h := a.Hash160()[:]; !bytes.Equal(saddr, h) { + t.Errorf("%v: hashes do not match:\n%x != \n%x", + test.name, saddr, h) + return + } + + case *btcutil.AddressWitnessPubKeyHash: + if hrp := a.Hrp(); test.net.Bech32HRPSegwit != hrp { + t.Errorf("%v: hrps do not match:\n%x != \n%x", + test.name, test.net.Bech32HRPSegwit, hrp) + return + } + + expVer := test.result.(*btcutil.AddressWitnessPubKeyHash).WitnessVersion() + if v := a.WitnessVersion(); v != expVer { + t.Errorf("%v: witness versions do not match:\n%x != \n%x", + test.name, expVer, v) + return + } + + if p := a.WitnessProgram(); !bytes.Equal(saddr, p) { + t.Errorf("%v: witness programs do not match:\n%x != \n%x", + test.name, saddr, p) + return + } + + case *btcutil.AddressWitnessScriptHash: + if hrp := a.Hrp(); test.net.Bech32HRPSegwit != hrp { + t.Errorf("%v: hrps do not match:\n%x != \n%x", + test.name, test.net.Bech32HRPSegwit, hrp) + return + } + + expVer := test.result.(*btcutil.AddressWitnessScriptHash).WitnessVersion() + if v := a.WitnessVersion(); v != expVer { + t.Errorf("%v: witness versions do not match:\n%x != \n%x", + test.name, expVer, v) + return + } + + if p := a.WitnessProgram(); !bytes.Equal(saddr, p) { + t.Errorf("%v: witness programs do not match:\n%x != \n%x", + test.name, saddr, p) + return + } + } + + // Ensure the address is for the expected network. + if !decoded.IsForNet(test.net) { + t.Errorf("%v: calculated network does not match expected", + test.name) + return + } + } else { + // If there is an error, make sure we can print it + // correctly. + errStr := err.Error() + if errStr == "" { + t.Errorf("%v: error was non-nil but message is"+ + "empty: %v", test.name, err) + } + } + + if !test.valid { + // If address is invalid, but a creation function exists, + // verify that it returns a nil addr and non-nil error. + if test.f != nil { + _, err := test.f() + if err == nil { + t.Errorf("%v: address is invalid but creating new address succeeded", + test.name) + return + } + } + continue + } + + // Valid test, compare address created with f against expected result. + addr, err := test.f() + if err != nil { + t.Errorf("%v: address is valid but creating new address failed with error %v", + test.name, err) + return + } + + if !reflect.DeepEqual(addr, test.result) { + t.Errorf("%v: created address does not match expected result", + test.name) + return + } + } +} diff --git a/btcutil/amount.go b/btcutil/amount.go new file mode 100644 index 0000000000..71714153aa --- /dev/null +++ b/btcutil/amount.go @@ -0,0 +1,122 @@ +// Copyright (c) 2013, 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "errors" + "math" + "strconv" +) + +// AmountUnit describes a method of converting an Amount to something +// other than the base unit of a bitcoin. The value of the AmountUnit +// is the exponent component of the decadic multiple to convert from +// an amount in bitcoin to an amount counted in units. +type AmountUnit int + +// These constants define various units used when describing a bitcoin +// monetary amount. +const ( + AmountMegaBTC AmountUnit = 6 + AmountKiloBTC AmountUnit = 3 + AmountBTC AmountUnit = 0 + AmountMilliBTC AmountUnit = -3 + AmountMicroBTC AmountUnit = -6 + AmountSatoshi AmountUnit = -8 +) + +// String returns the unit as a string. For recognized units, the SI +// prefix is used, or "Satoshi" for the base unit. For all unrecognized +// units, "1eN BTC" is returned, where N is the AmountUnit. +func (u AmountUnit) String() string { + switch u { + case AmountMegaBTC: + return "MBTC" + case AmountKiloBTC: + return "kBTC" + case AmountBTC: + return "BTC" + case AmountMilliBTC: + return "mBTC" + case AmountMicroBTC: + return "μBTC" + case AmountSatoshi: + return "Satoshi" + default: + return "1e" + strconv.FormatInt(int64(u), 10) + " BTC" + } +} + +// Amount represents the base bitcoin monetary unit (colloquially referred +// to as a `Satoshi'). A single Amount is equal to 1e-8 of a bitcoin. +type Amount int64 + +// round converts a floating point number, which may or may not be representable +// as an integer, to the Amount integer type by rounding to the nearest integer. +// This is performed by adding or subtracting 0.5 depending on the sign, and +// relying on integer truncation to round the value to the nearest Amount. +func round(f float64) Amount { + if f < 0 { + return Amount(f - 0.5) + } + return Amount(f + 0.5) +} + +// NewAmount creates an Amount from a floating point value representing +// some value in bitcoin. NewAmount errors if f is NaN or +-Infinity, but +// does not check that the amount is within the total amount of bitcoin +// producible as f may not refer to an amount at a single moment in time. +// +// NewAmount is for specifically for converting BTC to Satoshi. +// For creating a new Amount with an int64 value which denotes a quantity of Satoshi, +// do a simple type conversion from type int64 to Amount. +// See GoDoc for example: http://godoc.org/github.com/btcsuite/btcd/btcutil#example-Amount +func NewAmount(f float64) (Amount, error) { + // The amount is only considered invalid if it cannot be represented + // as an integer type. This may happen if f is NaN or +-Infinity. + switch { + case math.IsNaN(f): + fallthrough + case math.IsInf(f, 1): + fallthrough + case math.IsInf(f, -1): + return 0, errors.New("invalid bitcoin amount") + } + + return round(f * SatoshiPerBitcoin), nil +} + +// ToUnit converts a monetary amount counted in bitcoin base units to a +// floating point value representing an amount of bitcoin. +func (a Amount) ToUnit(u AmountUnit) float64 { + return float64(a) / math.Pow10(int(u+8)) +} + +// ToBTC is the equivalent of calling ToUnit with AmountBTC. +func (a Amount) ToBTC() float64 { + return a.ToUnit(AmountBTC) +} + +// Format formats a monetary amount counted in bitcoin base units as a +// string for a given unit. The conversion will succeed for any unit, +// however, known units will be formated with an appended label describing +// the units with SI notation, or "Satoshi" for the base unit. +func (a Amount) Format(u AmountUnit) string { + units := " " + u.String() + return strconv.FormatFloat(a.ToUnit(u), 'f', -int(u+8), 64) + units +} + +// String is the equivalent of calling Format with AmountBTC. +func (a Amount) String() string { + return a.Format(AmountBTC) +} + +// MulF64 multiplies an Amount by a floating point value. While this is not +// an operation that must typically be done by a full node or wallet, it is +// useful for services that build on top of bitcoin (for example, calculating +// a fee by multiplying by a percentage). +func (a Amount) MulF64(f float64) Amount { + return round(float64(a) * f) +} diff --git a/btcutil/amount_test.go b/btcutil/amount_test.go new file mode 100644 index 0000000000..2b6c3f753d --- /dev/null +++ b/btcutil/amount_test.go @@ -0,0 +1,309 @@ +// Copyright (c) 2013, 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil_test + +import ( + "math" + "testing" + + . "github.com/btcsuite/btcd/btcutil" +) + +func TestAmountCreation(t *testing.T) { + tests := []struct { + name string + amount float64 + valid bool + expected Amount + }{ + // Positive tests. + { + name: "zero", + amount: 0, + valid: true, + expected: 0, + }, + { + name: "max producible", + amount: 21e6, + valid: true, + expected: MaxSatoshi, + }, + { + name: "min producible", + amount: -21e6, + valid: true, + expected: -MaxSatoshi, + }, + { + name: "exceeds max producible", + amount: 21e6 + 1e-8, + valid: true, + expected: MaxSatoshi + 1, + }, + { + name: "exceeds min producible", + amount: -21e6 - 1e-8, + valid: true, + expected: -MaxSatoshi - 1, + }, + { + name: "one hundred", + amount: 100, + valid: true, + expected: 100 * SatoshiPerBitcoin, + }, + { + name: "fraction", + amount: 0.01234567, + valid: true, + expected: 1234567, + }, + { + name: "rounding up", + amount: 54.999999999999943157, + valid: true, + expected: 55 * SatoshiPerBitcoin, + }, + { + name: "rounding down", + amount: 55.000000000000056843, + valid: true, + expected: 55 * SatoshiPerBitcoin, + }, + + // Negative tests. + { + name: "not-a-number", + amount: math.NaN(), + valid: false, + }, + { + name: "-infinity", + amount: math.Inf(-1), + valid: false, + }, + { + name: "+infinity", + amount: math.Inf(1), + valid: false, + }, + } + + for _, test := range tests { + a, err := NewAmount(test.amount) + switch { + case test.valid && err != nil: + t.Errorf("%v: Positive test Amount creation failed with: %v", test.name, err) + continue + case !test.valid && err == nil: + t.Errorf("%v: Negative test Amount creation succeeded (value %v) when should fail", test.name, a) + continue + } + + if a != test.expected { + t.Errorf("%v: Created amount %v does not match expected %v", test.name, a, test.expected) + continue + } + } +} + +func TestAmountUnitConversions(t *testing.T) { + tests := []struct { + name string + amount Amount + unit AmountUnit + converted float64 + s string + }{ + { + name: "MBTC", + amount: MaxSatoshi, + unit: AmountMegaBTC, + converted: 21, + s: "21 MBTC", + }, + { + name: "kBTC", + amount: 44433322211100, + unit: AmountKiloBTC, + converted: 444.33322211100, + s: "444.333222111 kBTC", + }, + { + name: "BTC", + amount: 44433322211100, + unit: AmountBTC, + converted: 444333.22211100, + s: "444333.222111 BTC", + }, + { + name: "mBTC", + amount: 44433322211100, + unit: AmountMilliBTC, + converted: 444333222.11100, + s: "444333222.111 mBTC", + }, + { + + name: "μBTC", + amount: 44433322211100, + unit: AmountMicroBTC, + converted: 444333222111.00, + s: "444333222111 μBTC", + }, + { + + name: "satoshi", + amount: 44433322211100, + unit: AmountSatoshi, + converted: 44433322211100, + s: "44433322211100 Satoshi", + }, + { + + name: "non-standard unit", + amount: 44433322211100, + unit: AmountUnit(-1), + converted: 4443332.2211100, + s: "4443332.22111 1e-1 BTC", + }, + } + + for _, test := range tests { + f := test.amount.ToUnit(test.unit) + if f != test.converted { + t.Errorf("%v: converted value %v does not match expected %v", test.name, f, test.converted) + continue + } + + s := test.amount.Format(test.unit) + if s != test.s { + t.Errorf("%v: format '%v' does not match expected '%v'", test.name, s, test.s) + continue + } + + // Verify that Amount.ToBTC works as advertised. + f1 := test.amount.ToUnit(AmountBTC) + f2 := test.amount.ToBTC() + if f1 != f2 { + t.Errorf("%v: ToBTC does not match ToUnit(AmountBTC): %v != %v", test.name, f1, f2) + } + + // Verify that Amount.String works as advertised. + s1 := test.amount.Format(AmountBTC) + s2 := test.amount.String() + if s1 != s2 { + t.Errorf("%v: String does not match Format(AmountBitcoin): %v != %v", test.name, s1, s2) + } + } +} + +func TestAmountMulF64(t *testing.T) { + tests := []struct { + name string + amt Amount + mul float64 + res Amount + }{ + { + name: "Multiply 0.1 BTC by 2", + amt: 100e5, // 0.1 BTC + mul: 2, + res: 200e5, // 0.2 BTC + }, + { + name: "Multiply 0.2 BTC by 0.02", + amt: 200e5, // 0.2 BTC + mul: 1.02, + res: 204e5, // 0.204 BTC + }, + { + name: "Multiply 0.1 BTC by -2", + amt: 100e5, // 0.1 BTC + mul: -2, + res: -200e5, // -0.2 BTC + }, + { + name: "Multiply 0.2 BTC by -0.02", + amt: 200e5, // 0.2 BTC + mul: -1.02, + res: -204e5, // -0.204 BTC + }, + { + name: "Multiply -0.1 BTC by 2", + amt: -100e5, // -0.1 BTC + mul: 2, + res: -200e5, // -0.2 BTC + }, + { + name: "Multiply -0.2 BTC by 0.02", + amt: -200e5, // -0.2 BTC + mul: 1.02, + res: -204e5, // -0.204 BTC + }, + { + name: "Multiply -0.1 BTC by -2", + amt: -100e5, // -0.1 BTC + mul: -2, + res: 200e5, // 0.2 BTC + }, + { + name: "Multiply -0.2 BTC by -0.02", + amt: -200e5, // -0.2 BTC + mul: -1.02, + res: 204e5, // 0.204 BTC + }, + { + name: "Round down", + amt: 49, // 49 Satoshis + mul: 0.01, + res: 0, + }, + { + name: "Round up", + amt: 50, // 50 Satoshis + mul: 0.01, + res: 1, // 1 Satoshi + }, + { + name: "Multiply by 0.", + amt: 1e8, // 1 BTC + mul: 0, + res: 0, // 0 BTC + }, + { + name: "Multiply 1 by 0.5.", + amt: 1, // 1 Satoshi + mul: 0.5, + res: 1, // 1 Satoshi + }, + { + name: "Multiply 100 by 66%.", + amt: 100, // 100 Satoshis + mul: 0.66, + res: 66, // 66 Satoshis + }, + { + name: "Multiply 100 by 66.6%.", + amt: 100, // 100 Satoshis + mul: 0.666, + res: 67, // 67 Satoshis + }, + { + name: "Multiply 100 by 2/3.", + amt: 100, // 100 Satoshis + mul: 2.0 / 3, + res: 67, // 67 Satoshis + }, + } + + for _, test := range tests { + a := test.amt.MulF64(test.mul) + if a != test.res { + t.Errorf("%v: expected %v got %v", test.name, test.res, a) + } + } +} diff --git a/btcutil/appdata.go b/btcutil/appdata.go new file mode 100644 index 0000000000..e36cf7c4a4 --- /dev/null +++ b/btcutil/appdata.go @@ -0,0 +1,105 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "os" + "os/user" + "path/filepath" + "runtime" + "strings" + "unicode" +) + +// appDataDir returns an operating system specific directory to be used for +// storing application data for an application. See AppDataDir for more +// details. This unexported version takes an operating system argument +// primarily to enable the testing package to properly test the function by +// forcing an operating system that is not the currently one. +func appDataDir(goos, appName string, roaming bool) string { + if appName == "" || appName == "." { + return "." + } + + // The caller really shouldn't prepend the appName with a period, but + // if they do, handle it gracefully by trimming it. + appName = strings.TrimPrefix(appName, ".") + appNameUpper := string(unicode.ToUpper(rune(appName[0]))) + appName[1:] + appNameLower := string(unicode.ToLower(rune(appName[0]))) + appName[1:] + + // Get the OS specific home directory via the Go standard lib. + var homeDir string + usr, err := user.Current() + if err == nil { + homeDir = usr.HomeDir + } + + // Fall back to standard HOME environment variable that works + // for most POSIX OSes if the directory from the Go standard + // lib failed. + if err != nil || homeDir == "" { + homeDir = os.Getenv("HOME") + } + + switch goos { + // Attempt to use the LOCALAPPDATA or APPDATA environment variable on + // Windows. + case "windows": + // Windows XP and before didn't have a LOCALAPPDATA, so fallback + // to regular APPDATA when LOCALAPPDATA is not set. + appData := os.Getenv("LOCALAPPDATA") + if roaming || appData == "" { + appData = os.Getenv("APPDATA") + } + + if appData != "" { + return filepath.Join(appData, appNameUpper) + } + + case "darwin": + if homeDir != "" { + return filepath.Join(homeDir, "Library", + "Application Support", appNameUpper) + } + + case "plan9": + if homeDir != "" { + return filepath.Join(homeDir, appNameLower) + } + + default: + if homeDir != "" { + return filepath.Join(homeDir, "."+appNameLower) + } + } + + // Fall back to the current directory if all else fails. + return "." +} + +// AppDataDir returns an operating system specific directory to be used for +// storing application data for an application. +// +// The appName parameter is the name of the application the data directory is +// being requested for. This function will prepend a period to the appName for +// POSIX style operating systems since that is standard practice. An empty +// appName or one with a single dot is treated as requesting the current +// directory so only "." will be returned. Further, the first character +// of appName will be made lowercase for POSIX style operating systems and +// uppercase for Mac and Windows since that is standard practice. +// +// The roaming parameter only applies to Windows where it specifies the roaming +// application data profile (%APPDATA%) should be used instead of the local one +// (%LOCALAPPDATA%) that is used by default. +// +// Example results: +// dir := AppDataDir("myapp", false) +// POSIX (Linux/BSD): ~/.myapp +// Mac OS: $HOME/Library/Application Support/Myapp +// Windows: %LOCALAPPDATA%\Myapp +// Plan 9: $home/myapp +func AppDataDir(appName string, roaming bool) string { + return appDataDir(runtime.GOOS, appName, roaming) +} diff --git a/btcutil/appdata_test.go b/btcutil/appdata_test.go new file mode 100644 index 0000000000..061b1b5d80 --- /dev/null +++ b/btcutil/appdata_test.go @@ -0,0 +1,133 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil_test + +import ( + "os" + "os/user" + "path/filepath" + "runtime" + "testing" + "unicode" + + "github.com/btcsuite/btcd/btcutil" +) + +// TestAppDataDir tests the API for AppDataDir to ensure it gives expected +// results for various operating systems. +func TestAppDataDir(t *testing.T) { + // App name plus upper and lowercase variants. + appName := "myapp" + appNameUpper := string(unicode.ToUpper(rune(appName[0]))) + appName[1:] + appNameLower := string(unicode.ToLower(rune(appName[0]))) + appName[1:] + + // When we're on Windows, set the expected local and roaming directories + // per the environment vars. When we aren't on Windows, the function + // should return the current directory when forced to provide the + // Windows path since the environment variables won't exist. + winLocal := "." + winRoaming := "." + if runtime.GOOS == "windows" { + localAppData := os.Getenv("LOCALAPPDATA") + roamingAppData := os.Getenv("APPDATA") + if localAppData == "" { + localAppData = roamingAppData + } + winLocal = filepath.Join(localAppData, appNameUpper) + winRoaming = filepath.Join(roamingAppData, appNameUpper) + } + + // Get the home directory to use for testing expected results. + var homeDir string + usr, err := user.Current() + if err != nil { + t.Errorf("user.Current: %v", err) + return + } + homeDir = usr.HomeDir + + // Mac app data directory. + macAppData := filepath.Join(homeDir, "Library", "Application Support") + + tests := []struct { + goos string + appName string + roaming bool + want string + }{ + // Various combinations of application name casing, leading + // period, operating system, and roaming flags. + {"windows", appNameLower, false, winLocal}, + {"windows", appNameUpper, false, winLocal}, + {"windows", "." + appNameLower, false, winLocal}, + {"windows", "." + appNameUpper, false, winLocal}, + {"windows", appNameLower, true, winRoaming}, + {"windows", appNameUpper, true, winRoaming}, + {"windows", "." + appNameLower, true, winRoaming}, + {"windows", "." + appNameUpper, true, winRoaming}, + {"linux", appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"linux", appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"linux", "." + appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"linux", "." + appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"darwin", appNameLower, false, filepath.Join(macAppData, appNameUpper)}, + {"darwin", appNameUpper, false, filepath.Join(macAppData, appNameUpper)}, + {"darwin", "." + appNameLower, false, filepath.Join(macAppData, appNameUpper)}, + {"darwin", "." + appNameUpper, false, filepath.Join(macAppData, appNameUpper)}, + {"openbsd", appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"openbsd", appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"openbsd", "." + appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"openbsd", "." + appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"freebsd", appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"freebsd", appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"freebsd", "." + appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"freebsd", "." + appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"netbsd", appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"netbsd", appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"netbsd", "." + appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"netbsd", "." + appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"plan9", appNameLower, false, filepath.Join(homeDir, appNameLower)}, + {"plan9", appNameUpper, false, filepath.Join(homeDir, appNameLower)}, + {"plan9", "." + appNameLower, false, filepath.Join(homeDir, appNameLower)}, + {"plan9", "." + appNameUpper, false, filepath.Join(homeDir, appNameLower)}, + {"unrecognized", appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"unrecognized", appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + {"unrecognized", "." + appNameLower, false, filepath.Join(homeDir, "."+appNameLower)}, + {"unrecognized", "." + appNameUpper, false, filepath.Join(homeDir, "."+appNameLower)}, + + // No application name provided, so expect current directory. + {"windows", "", false, "."}, + {"windows", "", true, "."}, + {"linux", "", false, "."}, + {"darwin", "", false, "."}, + {"openbsd", "", false, "."}, + {"freebsd", "", false, "."}, + {"netbsd", "", false, "."}, + {"plan9", "", false, "."}, + {"unrecognized", "", false, "."}, + + // Single dot provided for application name, so expect current + // directory. + {"windows", ".", false, "."}, + {"windows", ".", true, "."}, + {"linux", ".", false, "."}, + {"darwin", ".", false, "."}, + {"openbsd", ".", false, "."}, + {"freebsd", ".", false, "."}, + {"netbsd", ".", false, "."}, + {"plan9", ".", false, "."}, + {"unrecognized", ".", false, "."}, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + ret := btcutil.TstAppDataDir(test.goos, test.appName, test.roaming) + if ret != test.want { + t.Errorf("appDataDir #%d (%s) does not match - "+ + "expected got %s, want %s", i, test.goos, ret, + test.want) + continue + } + } +} diff --git a/btcutil/base58/README.md b/btcutil/base58/README.md new file mode 100644 index 0000000000..abdb78155d --- /dev/null +++ b/btcutil/base58/README.md @@ -0,0 +1,34 @@ +base58 +========== + +[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)](https://travis-ci.org/btcsuite/btcutil) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/btcutil/base58) + +Package base58 provides an API for encoding and decoding to and from the +modified base58 encoding. It also provides an API to do Base58Check encoding, +as described [here](https://en.bitcoin.it/wiki/Base58Check_encoding). + +A comprehensive suite of tests is provided to ensure proper functionality. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil/base58 +``` + +## Examples + +* [Decode Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/base58#example-Decode) + Demonstrates how to decode modified base58 encoded data. +* [Encode Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/base58#example-Encode) + Demonstrates how to encode data using the modified base58 encoding scheme. +* [CheckDecode Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/base58#example-CheckDecode) + Demonstrates how to decode Base58Check encoded data. +* [CheckEncode Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/base58#example-CheckEncode) + Demonstrates how to encode data using the Base58Check encoding scheme. + +## License + +Package base58 is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/base58/alphabet.go b/btcutil/base58/alphabet.go new file mode 100644 index 0000000000..6bb39fef11 --- /dev/null +++ b/btcutil/base58/alphabet.go @@ -0,0 +1,49 @@ +// Copyright (c) 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// AUTOGENERATED by genalphabet.go; do not edit. + +package base58 + +const ( + // alphabet is the modified base58 alphabet used by Bitcoin. + alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + + alphabetIdx0 = '1' +) + +var b58 = [256]byte{ + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 255, 255, 255, 255, 255, 255, + 255, 9, 10, 11, 12, 13, 14, 15, + 16, 255, 17, 18, 19, 20, 21, 255, + 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 255, 255, 255, 255, 255, + 255, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 255, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, +} diff --git a/btcutil/base58/base58.go b/btcutil/base58/base58.go new file mode 100644 index 0000000000..8ee5956718 --- /dev/null +++ b/btcutil/base58/base58.go @@ -0,0 +1,138 @@ +// Copyright (c) 2013-2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package base58 + +import ( + "math/big" +) + +//go:generate go run genalphabet.go + +var bigRadix = [...]*big.Int{ + big.NewInt(0), + big.NewInt(58), + big.NewInt(58 * 58), + big.NewInt(58 * 58 * 58), + big.NewInt(58 * 58 * 58 * 58), + big.NewInt(58 * 58 * 58 * 58 * 58), + big.NewInt(58 * 58 * 58 * 58 * 58 * 58), + big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58), + big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58), + big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58), + bigRadix10, +} + +var bigRadix10 = big.NewInt(58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58 * 58) // 58^10 + +// Decode decodes a modified base58 string to a byte slice. +func Decode(b string) []byte { + answer := big.NewInt(0) + scratch := new(big.Int) + + // Calculating with big.Int is slow for each iteration. + // x += b58[b[i]] * j + // j *= 58 + // + // Instead we can try to do as much calculations on int64. + // We can represent a 10 digit base58 number using an int64. + // + // Hence we'll try to convert 10, base58 digits at a time. + // The rough idea is to calculate `t`, such that: + // + // t := b58[b[i+9]] * 58^9 ... + b58[b[i+1]] * 58^1 + b58[b[i]] * 58^0 + // x *= 58^10 + // x += t + // + // Of course, in addition, we'll need to handle boundary condition when `b` is not multiple of 58^10. + // In that case we'll use the bigRadix[n] lookup for the appropriate power. + for t := b; len(t) > 0; { + n := len(t) + if n > 10 { + n = 10 + } + + total := uint64(0) + for _, v := range t[:n] { + tmp := b58[v] + if tmp == 255 { + return []byte("") + } + total = total*58 + uint64(tmp) + } + + answer.Mul(answer, bigRadix[n]) + scratch.SetUint64(total) + answer.Add(answer, scratch) + + t = t[n:] + } + + tmpval := answer.Bytes() + + var numZeros int + for numZeros = 0; numZeros < len(b); numZeros++ { + if b[numZeros] != alphabetIdx0 { + break + } + } + flen := numZeros + len(tmpval) + val := make([]byte, flen) + copy(val[numZeros:], tmpval) + + return val +} + +// Encode encodes a byte slice to a modified base58 string. +func Encode(b []byte) string { + x := new(big.Int) + x.SetBytes(b) + + // maximum length of output is log58(2^(8*len(b))) == len(b) * 8 / log(58) + maxlen := int(float64(len(b))*1.365658237309761) + 1 + answer := make([]byte, 0, maxlen) + mod := new(big.Int) + for x.Sign() > 0 { + // Calculating with big.Int is slow for each iteration. + // x, mod = x / 58, x % 58 + // + // Instead we can try to do as much calculations on int64. + // x, mod = x / 58^10, x % 58^10 + // + // Which will give us mod, which is 10 digit base58 number. + // We'll loop that 10 times to convert to the answer. + + x.DivMod(x, bigRadix10, mod) + if x.Sign() == 0 { + // When x = 0, we need to ensure we don't add any extra zeros. + m := mod.Int64() + for m > 0 { + answer = append(answer, alphabet[m%58]) + m /= 58 + } + } else { + m := mod.Int64() + for i := 0; i < 10; i++ { + answer = append(answer, alphabet[m%58]) + m /= 58 + } + } + } + + // leading zero bytes + for _, i := range b { + if i != 0 { + break + } + answer = append(answer, alphabetIdx0) + } + + // reverse + alen := len(answer) + for i := 0; i < alen/2; i++ { + answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i] + } + + return string(answer) +} diff --git a/btcutil/base58/base58_test.go b/btcutil/base58/base58_test.go new file mode 100644 index 0000000000..b868d1d401 --- /dev/null +++ b/btcutil/base58/base58_test.go @@ -0,0 +1,101 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package base58_test + +import ( + "bytes" + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/btcutil/base58" +) + +var stringTests = []struct { + in string + out string +}{ + {"", ""}, + {" ", "Z"}, + {"-", "n"}, + {"0", "q"}, + {"1", "r"}, + {"-1", "4SU"}, + {"11", "4k8"}, + {"abc", "ZiCa"}, + {"1234598760", "3mJr7AoUXx2Wqd"}, + {"abcdefghijklmnopqrstuvwxyz", "3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f"}, + {"00000000000000000000000000000000000000000000000000000000000000", "3sN2THZeE9Eh9eYrwkvZqNstbHGvrxSAM7gXUXvyFQP8XvQLUqNCS27icwUeDT7ckHm4FUHM2mTVh1vbLmk7y"}, +} + +var invalidStringTests = []struct { + in string + out string +}{ + {"0", ""}, + {"O", ""}, + {"I", ""}, + {"l", ""}, + {"3mJr0", ""}, + {"O3yxU", ""}, + {"3sNI", ""}, + {"4kl8", ""}, + {"0OIl", ""}, + {"!@#$%^&*()-_=+~`", ""}, +} + +var hexTests = []struct { + in string + out string +}{ + {"", ""}, + {"61", "2g"}, + {"626262", "a3gV"}, + {"636363", "aPEr"}, + {"73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"}, + {"00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"}, + {"516b6fcd0f", "ABnLTmg"}, + {"bf4f89001e670274dd", "3SEo3LWLoPntC"}, + {"572e4794", "3EFU7m"}, + {"ecac89cad93923c02321", "EJDM8drfXA6uyA"}, + {"10c8511e", "Rt5zm"}, + {"00000000000000000000", "1111111111"}, + {"000111d38e5fc9071ffcd20b4a763cc9ae4f252bb4e48fd66a835e252ada93ff480d6dd43dc62a641155a5", "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"}, + {"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "1cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"}, +} + +func TestBase58(t *testing.T) { + // Encode tests + for x, test := range stringTests { + tmp := []byte(test.in) + if res := base58.Encode(tmp); res != test.out { + t.Errorf("Encode test #%d failed: got: %s want: %s", + x, res, test.out) + continue + } + } + + // Decode tests + for x, test := range hexTests { + b, err := hex.DecodeString(test.in) + if err != nil { + t.Errorf("hex.DecodeString failed failed #%d: got: %s", x, test.in) + continue + } + if res := base58.Decode(test.out); !bytes.Equal(res, b) { + t.Errorf("Decode test #%d failed: got: %q want: %q", + x, res, test.in) + continue + } + } + + // Decode with invalid input + for x, test := range invalidStringTests { + if res := base58.Decode(test.in); string(res) != test.out { + t.Errorf("Decode invalidString test #%d failed: got: %q want: %q", + x, res, test.out) + continue + } + } +} diff --git a/btcutil/base58/base58bench_test.go b/btcutil/base58/base58bench_test.go new file mode 100644 index 0000000000..c7286e53c7 --- /dev/null +++ b/btcutil/base58/base58bench_test.go @@ -0,0 +1,47 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package base58_test + +import ( + "bytes" + "testing" + + "github.com/btcsuite/btcd/btcutil/base58" +) + +var ( + raw5k = bytes.Repeat([]byte{0xff}, 5000) + raw100k = bytes.Repeat([]byte{0xff}, 100*1000) + encoded5k = base58.Encode(raw5k) + encoded100k = base58.Encode(raw100k) +) + +func BenchmarkBase58Encode_5K(b *testing.B) { + b.SetBytes(int64(len(raw5k))) + for i := 0; i < b.N; i++ { + base58.Encode(raw5k) + } +} + +func BenchmarkBase58Encode_100K(b *testing.B) { + b.SetBytes(int64(len(raw100k))) + for i := 0; i < b.N; i++ { + base58.Encode(raw100k) + } +} + +func BenchmarkBase58Decode_5K(b *testing.B) { + b.SetBytes(int64(len(encoded5k))) + for i := 0; i < b.N; i++ { + base58.Decode(encoded5k) + } +} + +func BenchmarkBase58Decode_100K(b *testing.B) { + b.SetBytes(int64(len(encoded100k))) + for i := 0; i < b.N; i++ { + base58.Decode(encoded100k) + } +} diff --git a/btcutil/base58/base58check.go b/btcutil/base58/base58check.go new file mode 100644 index 0000000000..402c3233f4 --- /dev/null +++ b/btcutil/base58/base58check.go @@ -0,0 +1,52 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package base58 + +import ( + "crypto/sha256" + "errors" +) + +// ErrChecksum indicates that the checksum of a check-encoded string does not verify against +// the checksum. +var ErrChecksum = errors.New("checksum error") + +// ErrInvalidFormat indicates that the check-encoded string has an invalid format. +var ErrInvalidFormat = errors.New("invalid format: version and/or checksum bytes missing") + +// checksum: first four bytes of sha256^2 +func checksum(input []byte) (cksum [4]byte) { + h := sha256.Sum256(input) + h2 := sha256.Sum256(h[:]) + copy(cksum[:], h2[:4]) + return +} + +// CheckEncode prepends a version byte and appends a four byte checksum. +func CheckEncode(input []byte, version byte) string { + b := make([]byte, 0, 1+len(input)+4) + b = append(b, version) + b = append(b, input...) + cksum := checksum(b) + b = append(b, cksum[:]...) + return Encode(b) +} + +// CheckDecode decodes a string that was encoded with CheckEncode and verifies the checksum. +func CheckDecode(input string) (result []byte, version byte, err error) { + decoded := Decode(input) + if len(decoded) < 5 { + return nil, 0, ErrInvalidFormat + } + version = decoded[0] + var cksum [4]byte + copy(cksum[:], decoded[len(decoded)-4:]) + if checksum(decoded[:len(decoded)-4]) != cksum { + return nil, 0, ErrChecksum + } + payload := decoded[1 : len(decoded)-4] + result = append(result, payload...) + return +} diff --git a/btcutil/base58/base58check_test.go b/btcutil/base58/base58check_test.go new file mode 100644 index 0000000000..e180b16391 --- /dev/null +++ b/btcutil/base58/base58check_test.go @@ -0,0 +1,69 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package base58_test + +import ( + "testing" + + "github.com/btcsuite/btcd/btcutil/base58" +) + +var checkEncodingStringTests = []struct { + version byte + in string + out string +}{ + {20, "", "3MNQE1X"}, + {20, " ", "B2Kr6dBE"}, + {20, "-", "B3jv1Aft"}, + {20, "0", "B482yuaX"}, + {20, "1", "B4CmeGAC"}, + {20, "-1", "mM7eUf6kB"}, + {20, "11", "mP7BMTDVH"}, + {20, "abc", "4QiVtDjUdeq"}, + {20, "1234598760", "ZmNb8uQn5zvnUohNCEPP"}, + {20, "abcdefghijklmnopqrstuvwxyz", "K2RYDcKfupxwXdWhSAxQPCeiULntKm63UXyx5MvEH2"}, + {20, "00000000000000000000000000000000000000000000000000000000000000", "bi1EWXwJay2udZVxLJozuTb8Meg4W9c6xnmJaRDjg6pri5MBAxb9XwrpQXbtnqEoRV5U2pixnFfwyXC8tRAVC8XxnjK"}, +} + +func TestBase58Check(t *testing.T) { + for x, test := range checkEncodingStringTests { + // test encoding + if res := base58.CheckEncode([]byte(test.in), test.version); res != test.out { + t.Errorf("CheckEncode test #%d failed: got %s, want: %s", x, res, test.out) + } + + // test decoding + res, version, err := base58.CheckDecode(test.out) + switch { + case err != nil: + t.Errorf("CheckDecode test #%d failed with err: %v", x, err) + + case version != test.version: + t.Errorf("CheckDecode test #%d failed: got version: %d want: %d", x, version, test.version) + + case string(res) != test.in: + t.Errorf("CheckDecode test #%d failed: got: %s want: %s", x, res, test.in) + } + } + + // test the two decoding failure cases + // case 1: checksum error + _, _, err := base58.CheckDecode("3MNQE1Y") + if err != base58.ErrChecksum { + t.Error("Checkdecode test failed, expected ErrChecksum") + } + // case 2: invalid formats (string lengths below 5 mean the version byte and/or the checksum + // bytes are missing). + testString := "" + for len := 0; len < 4; len++ { + testString += "x" + _, _, err = base58.CheckDecode(testString) + if err != base58.ErrInvalidFormat { + t.Error("Checkdecode test failed, expected ErrInvalidFormat") + } + } + +} diff --git a/btcutil/base58/cov_report.sh b/btcutil/base58/cov_report.sh new file mode 100644 index 0000000000..307f05b76c --- /dev/null +++ b/btcutil/base58/cov_report.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# This script uses gocov to generate a test coverage report. +# The gocov tool my be obtained with the following command: +# go get github.com/axw/gocov/gocov +# +# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. + +# Check for gocov. +type gocov >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo >&2 "This script requires the gocov tool." + echo >&2 "You may obtain it with the following command:" + echo >&2 "go get github.com/axw/gocov/gocov" + exit 1 +fi +gocov test | gocov report diff --git a/btcutil/base58/doc.go b/btcutil/base58/doc.go new file mode 100644 index 0000000000..9a2c0e6e3d --- /dev/null +++ b/btcutil/base58/doc.go @@ -0,0 +1,29 @@ +// Copyright (c) 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package base58 provides an API for working with modified base58 and Base58Check +encodings. + +Modified Base58 Encoding + +Standard base58 encoding is similar to standard base64 encoding except, as the +name implies, it uses a 58 character alphabet which results in an alphanumeric +string and allows some characters which are problematic for humans to be +excluded. Due to this, there can be various base58 alphabets. + +The modified base58 alphabet used by Bitcoin, and hence this package, omits the +0, O, I, and l characters that look the same in many fonts and are therefore +hard to humans to distinguish. + +Base58Check Encoding Scheme + +The Base58Check encoding scheme is primarily used for Bitcoin addresses at the +time of this writing, however it can be used to generically encode arbitrary +byte arrays into human-readable strings along with a version byte that can be +used to differentiate the same payload. For Bitcoin addresses, the extra +version is used to differentiate the network of otherwise identical public keys +which helps prevent using an address intended for one network on another. +*/ +package base58 diff --git a/btcutil/base58/example_test.go b/btcutil/base58/example_test.go new file mode 100644 index 0000000000..babb35d3f4 --- /dev/null +++ b/btcutil/base58/example_test.go @@ -0,0 +1,71 @@ +// Copyright (c) 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package base58_test + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcutil/base58" +) + +// This example demonstrates how to decode modified base58 encoded data. +func ExampleDecode() { + // Decode example modified base58 encoded data. + encoded := "25JnwSn7XKfNQ" + decoded := base58.Decode(encoded) + + // Show the decoded data. + fmt.Println("Decoded Data:", string(decoded)) + + // Output: + // Decoded Data: Test data +} + +// This example demonstrates how to encode data using the modified base58 +// encoding scheme. +func ExampleEncode() { + // Encode example data with the modified base58 encoding scheme. + data := []byte("Test data") + encoded := base58.Encode(data) + + // Show the encoded data. + fmt.Println("Encoded Data:", encoded) + + // Output: + // Encoded Data: 25JnwSn7XKfNQ +} + +// This example demonstrates how to decode Base58Check encoded data. +func ExampleCheckDecode() { + // Decode an example Base58Check encoded data. + encoded := "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa" + decoded, version, err := base58.CheckDecode(encoded) + if err != nil { + fmt.Println(err) + return + } + + // Show the decoded data. + fmt.Printf("Decoded data: %x\n", decoded) + fmt.Println("Version Byte:", version) + + // Output: + // Decoded data: 62e907b15cbf27d5425399ebf6f0fb50ebb88f18 + // Version Byte: 0 +} + +// This example demonstrates how to encode data using the Base58Check encoding +// scheme. +func ExampleCheckEncode() { + // Encode example data with the Base58Check encoding scheme. + data := []byte("Test data") + encoded := base58.CheckEncode(data, 0) + + // Show the encoded data. + fmt.Println("Encoded Data:", encoded) + + // Output: + // Encoded Data: 182iP79GRURMp7oMHDU +} diff --git a/btcutil/base58/genalphabet.go b/btcutil/base58/genalphabet.go new file mode 100644 index 0000000000..010cbee39e --- /dev/null +++ b/btcutil/base58/genalphabet.go @@ -0,0 +1,79 @@ +// Copyright (c) 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +//+build ignore + +package main + +import ( + "bytes" + "io" + "log" + "os" + "strconv" +) + +var ( + start = []byte(`// Copyright (c) 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// AUTOGENERATED by genalphabet.go; do not edit. + +package base58 + +const ( + // alphabet is the modified base58 alphabet used by Bitcoin. + alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + + alphabetIdx0 = '1' +) + +var b58 = [256]byte{`) + + end = []byte(`}`) + + alphabet = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz") + tab = []byte("\t") + invalid = []byte("255") + comma = []byte(",") + space = []byte(" ") + nl = []byte("\n") +) + +func write(w io.Writer, b []byte) { + _, err := w.Write(b) + if err != nil { + log.Fatal(err) + } +} + +func main() { + fi, err := os.Create("alphabet.go") + if err != nil { + log.Fatal(err) + } + defer fi.Close() + + write(fi, start) + write(fi, nl) + for i := byte(0); i < 32; i++ { + write(fi, tab) + for j := byte(0); j < 8; j++ { + idx := bytes.IndexByte(alphabet, i*8+j) + if idx == -1 { + write(fi, invalid) + } else { + write(fi, strconv.AppendInt(nil, int64(idx), 10)) + } + write(fi, comma) + if j != 7 { + write(fi, space) + } + } + write(fi, nl) + } + write(fi, end) + write(fi, nl) +} diff --git a/btcutil/bech32/README.md b/btcutil/bech32/README.md new file mode 100644 index 0000000000..471cd50ee9 --- /dev/null +++ b/btcutil/bech32/README.md @@ -0,0 +1,29 @@ +bech32 +========== + +[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)](https://travis-ci.org/btcsuite/btcutil) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/btcutil/bech32?status.png)](http://godoc.org/github.com/btcsuite/btcd/btcutil/bech32) + +Package bech32 provides a Go implementation of the bech32 format specified in +[BIP 173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki). + +Test vectors from BIP 173 are added to ensure compatibility with the BIP. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil/bech32 +``` + +## Examples + +* [Bech32 decode Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/bech32#example-Bech32Decode) + Demonstrates how to decode a bech32 encoded string. +* [Bech32 encode Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/bech32#example-BechEncode) + Demonstrates how to encode data into a bech32 string. + +## License + +Package bech32 is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/bech32/bech32.go b/btcutil/bech32/bech32.go new file mode 100644 index 0000000000..c1e00106e6 --- /dev/null +++ b/btcutil/bech32/bech32.go @@ -0,0 +1,442 @@ +// Copyright (c) 2017 The btcsuite developers +// Copyright (c) 2019 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bech32 + +import ( + "strings" +) + +// charset is the set of characters used in the data section of bech32 strings. +// Note that this is ordered, such that for a given charset[i], i is the binary +// value of the character. +const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" + +// gen encodes the generator polynomial for the bech32 BCH checksum. +var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3} + +// toBytes converts each character in the string 'chars' to the value of the +// index of the correspoding character in 'charset'. +func toBytes(chars string) ([]byte, error) { + decoded := make([]byte, 0, len(chars)) + for i := 0; i < len(chars); i++ { + index := strings.IndexByte(charset, chars[i]) + if index < 0 { + return nil, ErrNonCharsetChar(chars[i]) + } + decoded = append(decoded, byte(index)) + } + return decoded, nil +} + +// bech32Polymod calculates the BCH checksum for a given hrp, values and +// checksum data. Checksum is optional, and if nil a 0 checksum is assumed. +// +// Values and checksum (if provided) MUST be encoded as 5 bits per element (base +// 32), otherwise the results are undefined. +// +// For more details on the polymod calculation, please refer to BIP 173. +func bech32Polymod(hrp string, values, checksum []byte) int { + chk := 1 + + // Account for the high bits of the HRP in the checksum. + for i := 0; i < len(hrp); i++ { + b := chk >> 25 + hiBits := int(hrp[i]) >> 5 + chk = (chk&0x1ffffff)<<5 ^ hiBits + for i := 0; i < 5; i++ { + if (b>>uint(i))&1 == 1 { + chk ^= gen[i] + } + } + } + + // Account for the separator (0) between high and low bits of the HRP. + // x^0 == x, so we eliminate the redundant xor used in the other rounds. + b := chk >> 25 + chk = (chk & 0x1ffffff) << 5 + for i := 0; i < 5; i++ { + if (b>>uint(i))&1 == 1 { + chk ^= gen[i] + } + } + + // Account for the low bits of the HRP. + for i := 0; i < len(hrp); i++ { + b := chk >> 25 + loBits := int(hrp[i]) & 31 + chk = (chk&0x1ffffff)<<5 ^ loBits + for i := 0; i < 5; i++ { + if (b>>uint(i))&1 == 1 { + chk ^= gen[i] + } + } + } + + // Account for the values. + for _, v := range values { + b := chk >> 25 + chk = (chk&0x1ffffff)<<5 ^ int(v) + for i := 0; i < 5; i++ { + if (b>>uint(i))&1 == 1 { + chk ^= gen[i] + } + } + } + + if checksum == nil { + // A nil checksum is used during encoding, so assume all bytes are zero. + // x^0 == x, so we eliminate the redundant xor used in the other rounds. + for v := 0; v < 6; v++ { + b := chk >> 25 + chk = (chk & 0x1ffffff) << 5 + for i := 0; i < 5; i++ { + if (b>>uint(i))&1 == 1 { + chk ^= gen[i] + } + } + } + } else { + // Checksum is provided during decoding, so use it. + for _, v := range checksum { + b := chk >> 25 + chk = (chk&0x1ffffff)<<5 ^ int(v) + for i := 0; i < 5; i++ { + if (b>>uint(i))&1 == 1 { + chk ^= gen[i] + } + } + } + } + + return chk +} + +// writeBech32Checksum calculates the checksum data expected for a string that +// will have the given hrp and payload data and writes it to the provided string +// builder. +// +// The payload data MUST be encoded as a base 32 (5 bits per element) byte slice +// and the hrp MUST only use the allowed character set (ascii chars between 33 +// and 126), otherwise the results are undefined. +// +// For more details on the checksum calculation, please refer to BIP 173. +func writeBech32Checksum(hrp string, data []byte, bldr *strings.Builder, + version Version) { + + bech32Const := int(VersionToConsts[version]) + polymod := bech32Polymod(hrp, data, nil) ^ bech32Const + for i := 0; i < 6; i++ { + b := byte((polymod >> uint(5*(5-i))) & 31) + + // This can't fail, given we explicitly cap the previous b byte by the + // first 31 bits. + c := charset[b] + bldr.WriteByte(c) + } +} + +// bech32VerifyChecksum verifies whether the bech32 string specified by the +// provided hrp and payload data (encoded as 5 bits per element byte slice) has +// the correct checksum suffix. The version of bech32 used (bech32 OG, or +// bech32m) is also returned to allow the caller to perform proper address +// validation (segwitv0 should use bech32, v1+ should use bech32m). +// +// Data MUST have more than 6 elements, otherwise this function panics. +// +// For more details on the checksum verification, please refer to BIP 173. +func bech32VerifyChecksum(hrp string, data []byte) (Version, bool) { + checksum := data[len(data)-6:] + values := data[:len(data)-6] + polymod := bech32Polymod(hrp, values, checksum) + + // Before BIP-350, we'd always check this against a static constant of + // 1 to know if the checksum was computed properly. As we want to + // generically support decoding for bech32m as well as bech32, we'll + // look up the returned value and compare it to the set of defined + // constants. + bech32Version, ok := ConstsToVersion[ChecksumConst(polymod)] + if ok { + return bech32Version, true + } + + return VersionUnknown, false +} + +// DecodeNoLimit is a bech32 checksum version aware arbitrary string length +// decoder. This function will return the version of the decoded checksum +// constant so higher level validation can be performed to ensure the correct +// version of bech32 was used when encoding. +func decodeNoLimit(bech string) (string, []byte, Version, error) { + // The minimum allowed size of a bech32 string is 8 characters, since it + // needs a non-empty HRP, a separator, and a 6 character checksum. + if len(bech) < 8 { + return "", nil, VersionUnknown, ErrInvalidLength(len(bech)) + } + + // Only ASCII characters between 33 and 126 are allowed. + var hasLower, hasUpper bool + for i := 0; i < len(bech); i++ { + if bech[i] < 33 || bech[i] > 126 { + return "", nil, VersionUnknown, ErrInvalidCharacter(bech[i]) + } + + // The characters must be either all lowercase or all uppercase. Testing + // directly with ascii codes is safe here, given the previous test. + hasLower = hasLower || (bech[i] >= 97 && bech[i] <= 122) + hasUpper = hasUpper || (bech[i] >= 65 && bech[i] <= 90) + if hasLower && hasUpper { + return "", nil, VersionUnknown, ErrMixedCase{} + } + } + + // Bech32 standard uses only the lowercase for of strings for checksum + // calculation. + if hasUpper { + bech = strings.ToLower(bech) + } + + // The string is invalid if the last '1' is non-existent, it is the + // first character of the string (no human-readable part) or one of the + // last 6 characters of the string (since checksum cannot contain '1'). + one := strings.LastIndexByte(bech, '1') + if one < 1 || one+7 > len(bech) { + return "", nil, VersionUnknown, ErrInvalidSeparatorIndex(one) + } + + // The human-readable part is everything before the last '1'. + hrp := bech[:one] + data := bech[one+1:] + + // Each character corresponds to the byte with value of the index in + // 'charset'. + decoded, err := toBytes(data) + if err != nil { + return "", nil, VersionUnknown, err + } + + // Verify if the checksum (stored inside decoded[:]) is valid, given the + // previously decoded hrp. + bech32Version, ok := bech32VerifyChecksum(hrp, decoded) + if !ok { + // Invalid checksum. Calculate what it should have been, so that the + // error contains this information. + + // Extract the payload bytes and actual checksum in the string. + actual := bech[len(bech)-6:] + payload := decoded[:len(decoded)-6] + + // Calculate the expected checksum, given the hrp and payload + // data. We'll actually compute _both_ possibly valid checksum + // to further aide in debugging. + var expectedBldr strings.Builder + expectedBldr.Grow(6) + writeBech32Checksum(hrp, payload, &expectedBldr, Version0) + expectedVersion0 := expectedBldr.String() + + var b strings.Builder + b.Grow(6) + writeBech32Checksum(hrp, payload, &expectedBldr, VersionM) + expectedVersionM := expectedBldr.String() + + err = ErrInvalidChecksum{ + Expected: expectedVersion0, + ExpectedM: expectedVersionM, + Actual: actual, + } + return "", nil, VersionUnknown, err + } + + // We exclude the last 6 bytes, which is the checksum. + return hrp, decoded[:len(decoded)-6], bech32Version, nil +} + +// DecodeNoLimit decodes a bech32 encoded string, returning the human-readable +// part and the data part excluding the checksum. This function does NOT +// validate against the BIP-173 maximum length allowed for bech32 strings and +// is meant for use in custom applications (such as lightning network payment +// requests), NOT on-chain addresses. +// +// Note that the returned data is 5-bit (base32) encoded and the human-readable +// part will be lowercase. +func DecodeNoLimit(bech string) (string, []byte, error) { + hrp, data, _, err := decodeNoLimit(bech) + return hrp, data, err +} + +// Decode decodes a bech32 encoded string, returning the human-readable part and +// the data part excluding the checksum. +// +// Note that the returned data is 5-bit (base32) encoded and the human-readable +// part will be lowercase. +func Decode(bech string) (string, []byte, error) { + // The maximum allowed length for a bech32 string is 90. + if len(bech) > 90 { + return "", nil, ErrInvalidLength(len(bech)) + } + + hrp, data, _, err := decodeNoLimit(bech) + return hrp, data, err +} + +// DecodeGeneric is identical to the existing Decode method, but will also +// return bech32 version that matches the decoded checksum. This method should +// be used when decoding segwit addresses, as it enables additional +// verification to ensure the proper checksum is used. +func DecodeGeneric(bech string) (string, []byte, Version, error) { + // The maximum allowed length for a bech32 string is 90. + if len(bech) > 90 { + return "", nil, VersionUnknown, ErrInvalidLength(len(bech)) + } + + return decodeNoLimit(bech) +} + +// encodeGeneric is the base bech32 encoding function that is aware of the +// existence of the checksum versions. This method is private, as the Encode +// and EncodeM methods are intended to be used instead. +func encodeGeneric(hrp string, data []byte, + version Version) (string, error) { + + // The resulting bech32 string is the concatenation of the lowercase + // hrp, the separator 1, data and the 6-byte checksum. + hrp = strings.ToLower(hrp) + var bldr strings.Builder + bldr.Grow(len(hrp) + 1 + len(data) + 6) + bldr.WriteString(hrp) + bldr.WriteString("1") + + // Write the data part, using the bech32 charset. + for _, b := range data { + if int(b) >= len(charset) { + return "", ErrInvalidDataByte(b) + } + bldr.WriteByte(charset[b]) + } + + // Calculate and write the checksum of the data. + writeBech32Checksum(hrp, data, &bldr, version) + + return bldr.String(), nil +} + +// Encode encodes a byte slice into a bech32 string with the given +// human-readable part (HRP). The HRP will be converted to lowercase if needed +// since mixed cased encodings are not permitted and lowercase is used for +// checksum purposes. Note that the bytes must each encode 5 bits (base32). +func Encode(hrp string, data []byte) (string, error) { + return encodeGeneric(hrp, data, Version0) +} + +// EncodeM is the exactly same as the Encode method, but it uses the new +// bech32m constant instead of the original one. It should be used whenever one +// attempts to encode a segwit address of v1 and beyond. +func EncodeM(hrp string, data []byte) (string, error) { + return encodeGeneric(hrp, data, VersionM) +} + +// ConvertBits converts a byte slice where each byte is encoding fromBits bits, +// to a byte slice where each byte is encoding toBits bits. +func ConvertBits(data []byte, fromBits, toBits uint8, pad bool) ([]byte, error) { + if fromBits < 1 || fromBits > 8 || toBits < 1 || toBits > 8 { + return nil, ErrInvalidBitGroups{} + } + + // Determine the maximum size the resulting array can have after base + // conversion, so that we can size it a single time. This might be off + // by a byte depending on whether padding is used or not and if the input + // data is a multiple of both fromBits and toBits, but we ignore that and + // just size it to the maximum possible. + maxSize := len(data)*int(fromBits)/int(toBits) + 1 + + // The final bytes, each byte encoding toBits bits. + regrouped := make([]byte, 0, maxSize) + + // Keep track of the next byte we create and how many bits we have + // added to it out of the toBits goal. + nextByte := byte(0) + filledBits := uint8(0) + + for _, b := range data { + + // Discard unused bits. + b <<= 8 - fromBits + + // How many bits remaining to extract from the input data. + remFromBits := fromBits + for remFromBits > 0 { + // How many bits remaining to be added to the next byte. + remToBits := toBits - filledBits + + // The number of bytes to next extract is the minimum of + // remFromBits and remToBits. + toExtract := remFromBits + if remToBits < toExtract { + toExtract = remToBits + } + + // Add the next bits to nextByte, shifting the already + // added bits to the left. + nextByte = (nextByte << toExtract) | (b >> (8 - toExtract)) + + // Discard the bits we just extracted and get ready for + // next iteration. + b <<= toExtract + remFromBits -= toExtract + filledBits += toExtract + + // If the nextByte is completely filled, we add it to + // our regrouped bytes and start on the next byte. + if filledBits == toBits { + regrouped = append(regrouped, nextByte) + filledBits = 0 + nextByte = 0 + } + } + } + + // We pad any unfinished group if specified. + if pad && filledBits > 0 { + nextByte <<= toBits - filledBits + regrouped = append(regrouped, nextByte) + filledBits = 0 + nextByte = 0 + } + + // Any incomplete group must be <= 4 bits, and all zeroes. + if filledBits > 0 && (filledBits > 4 || nextByte != 0) { + return nil, ErrInvalidIncompleteGroup{} + } + + return regrouped, nil +} + +// EncodeFromBase256 converts a base256-encoded byte slice into a base32-encoded +// byte slice and then encodes it into a bech32 string with the given +// human-readable part (HRP). The HRP will be converted to lowercase if needed +// since mixed cased encodings are not permitted and lowercase is used for +// checksum purposes. +func EncodeFromBase256(hrp string, data []byte) (string, error) { + converted, err := ConvertBits(data, 8, 5, true) + if err != nil { + return "", err + } + return Encode(hrp, converted) +} + +// DecodeToBase256 decodes a bech32-encoded string into its associated +// human-readable part (HRP) and base32-encoded data, converts that data to a +// base256-encoded byte slice and returns it along with the lowercase HRP. +func DecodeToBase256(bech string) (string, []byte, error) { + hrp, data, err := Decode(bech) + if err != nil { + return "", nil, err + } + converted, err := ConvertBits(data, 5, 8, false) + if err != nil { + return "", nil, err + } + return hrp, converted, nil +} diff --git a/btcutil/bech32/bech32_test.go b/btcutil/bech32/bech32_test.go new file mode 100644 index 0000000000..1e04905a61 --- /dev/null +++ b/btcutil/bech32/bech32_test.go @@ -0,0 +1,691 @@ +// Copyright (c) 2017-2020 The btcsuite developers +// Copyright (c) 2019 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bech32 + +import ( + "bytes" + "encoding/hex" + "fmt" + "strings" + "testing" +) + +// TestBech32 tests whether decoding and re-encoding the valid BIP-173 test +// vectors works and if decoding invalid test vectors fails for the correct +// reason. +func TestBech32(t *testing.T) { + tests := []struct { + str string + expectedError error + }{ + {"A12UEL5L", nil}, + {"a12uel5l", nil}, + {"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", nil}, + {"abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", nil}, + {"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", nil}, + {"split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", nil}, + {"split1checkupstagehandshakeupstreamerranterredcaperred2y9e2w", ErrInvalidChecksum{"2y9e3w", "2y9e3wlc445v", "2y9e2w"}}, // invalid checksum + {"s lit1checkupstagehandshakeupstreamerranterredcaperredp8hs2p", ErrInvalidCharacter(' ')}, // invalid character (space) in hrp + {"spl\x7Ft1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", ErrInvalidCharacter(127)}, // invalid character (DEL) in hrp + {"split1cheo2y9e2w", ErrNonCharsetChar('o')}, // invalid character (o) in data part + {"split1a2y9w", ErrInvalidSeparatorIndex(5)}, // too short data part + {"1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", ErrInvalidSeparatorIndex(0)}, // empty hrp + {"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", ErrInvalidLength(91)}, // too long + + // Additional test vectors used in bitcoin core + {" 1nwldj5", ErrInvalidCharacter(' ')}, + {"\x7f" + "1axkwrx", ErrInvalidCharacter(0x7f)}, + {"\x801eym55h", ErrInvalidCharacter(0x80)}, + {"an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx", ErrInvalidLength(91)}, + {"pzry9x0s0muk", ErrInvalidSeparatorIndex(-1)}, + {"1pzry9x0s0muk", ErrInvalidSeparatorIndex(0)}, + {"x1b4n0q5v", ErrNonCharsetChar(98)}, + {"li1dgmt3", ErrInvalidSeparatorIndex(2)}, + {"de1lg7wt\xff", ErrInvalidCharacter(0xff)}, + {"A1G7SGD8", ErrInvalidChecksum{"2uel5l", "2uel5llqfn3a", "g7sgd8"}}, + {"10a06t8", ErrInvalidLength(7)}, + {"1qzzfhee", ErrInvalidSeparatorIndex(0)}, + {"a12UEL5L", ErrMixedCase{}}, + {"A12uEL5L", ErrMixedCase{}}, + } + + for i, test := range tests { + str := test.str + hrp, decoded, err := Decode(str) + if test.expectedError != err { + t.Errorf("%d: expected decoding error %v "+ + "instead got %v", i, test.expectedError, err) + continue + } + + if err != nil { + // End test case here if a decoding error was expected. + continue + } + + // Check that it encodes to the same string + encoded, err := Encode(hrp, decoded) + if err != nil { + t.Errorf("encoding failed: %v", err) + } + + if encoded != strings.ToLower(str) { + t.Errorf("expected data to encode to %v, but got %v", + str, encoded) + } + + // Flip a bit in the string an make sure it is caught. + pos := strings.LastIndexAny(str, "1") + flipped := str[:pos+1] + string((str[pos+1] ^ 1)) + str[pos+2:] + _, _, err = Decode(flipped) + if err == nil { + t.Error("expected decoding to fail") + } + } +} + +// TestBech32M tests that the following set of strings, based on the test +// vectors in BIP-350 are either valid or invalid using the new bech32m +// checksum algo. Some of these strings are similar to the set of above test +// vectors, but end up with different checksums. +func TestBech32M(t *testing.T) { + tests := []struct { + str string + expectedError error + }{ + {"A1LQFN3A", nil}, + {"a1lqfn3a", nil}, + {"an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6", nil}, + {"abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx", nil}, + {"11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8", nil}, + {"split1checkupstagehandshakeupstreamerranterredcaperredlc445v", nil}, + {"?1v759aa", nil}, + + // Additional test vectors used in bitcoin core + {"\x201xj0phk", ErrInvalidCharacter('\x20')}, + {"\x7f1g6xzxy", ErrInvalidCharacter('\x7f')}, + {"\x801vctc34", ErrInvalidCharacter('\x80')}, + {"an84characterslonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11d6pts4", ErrInvalidLength(91)}, + {"qyrz8wqd2c9m", ErrInvalidSeparatorIndex(-1)}, + {"1qyrz8wqd2c9m", ErrInvalidSeparatorIndex(0)}, + {"y1b0jsk6g", ErrNonCharsetChar(98)}, + {"lt1igcx5c0", ErrNonCharsetChar(105)}, + {"in1muywd", ErrInvalidSeparatorIndex(2)}, + {"mm1crxm3i", ErrNonCharsetChar(105)}, + {"au1s5cgom", ErrNonCharsetChar(111)}, + {"M1VUXWEZ", ErrInvalidChecksum{"mzl49c", "mzl49cw70eq6", "vuxwez"}}, + {"16plkw9", ErrInvalidLength(7)}, + {"1p2gdwpf", ErrInvalidSeparatorIndex(0)}, + + {" 1nwldj5", ErrInvalidCharacter(' ')}, + {"\x7f" + "1axkwrx", ErrInvalidCharacter(0x7f)}, + {"\x801eym55h", ErrInvalidCharacter(0x80)}, + } + + for i, test := range tests { + str := test.str + hrp, decoded, err := Decode(str) + if test.expectedError != err { + t.Errorf("%d: (%v) expected decoding error %v "+ + "instead got %v", i, str, test.expectedError, + err) + continue + } + + if err != nil { + // End test case here if a decoding error was expected. + continue + } + + // Check that it encodes to the same string, using bech32 m. + encoded, err := EncodeM(hrp, decoded) + if err != nil { + t.Errorf("encoding failed: %v", err) + } + + if encoded != strings.ToLower(str) { + t.Errorf("expected data to encode to %v, but got %v", + str, encoded) + } + + // Flip a bit in the string an make sure it is caught. + pos := strings.LastIndexAny(str, "1") + flipped := str[:pos+1] + string((str[pos+1] ^ 1)) + str[pos+2:] + _, _, err = Decode(flipped) + if err == nil { + t.Error("expected decoding to fail") + } + } +} + +// TestBech32DecodeGeneric tests that given a bech32 string, or a bech32m +// string, the proper checksum version is returned so that callers can perform +// segwit addr validation. +func TestBech32DecodeGeneric(t *testing.T) { + tests := []struct { + str string + version Version + }{ + {"A1LQFN3A", VersionM}, + {"a1lqfn3a", VersionM}, + {"an83characterlonghumanreadablepartthatcontainsthetheexcludedcharactersbioandnumber11sg7hg6", VersionM}, + {"abcdef1l7aum6echk45nj3s0wdvt2fg8x9yrzpqzd3ryx", VersionM}, + {"11llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllludsr8", VersionM}, + {"split1checkupstagehandshakeupstreamerranterredcaperredlc445v", VersionM}, + {"?1v759aa", VersionM}, + + {"A12UEL5L", Version0}, + {"a12uel5l", Version0}, + {"an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", Version0}, + {"abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", Version0}, + {"11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", Version0}, + {"split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", Version0}, + + {"BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", Version0}, + {"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", Version0}, + {"bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kt5nd6y", VersionM}, + {"BC1SW50QGDZ25J", VersionM}, + {"bc1zw508d6qejxtdg4y5r3zarvaryvaxxpcs", VersionM}, + {"tb1qqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesrxh6hy", Version0}, + {"tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", VersionM}, + {"bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0", VersionM}, + } + for i, test := range tests { + _, _, version, err := DecodeGeneric(test.str) + if err != nil { + t.Errorf("%d: (%v) unexpected error during "+ + "decoding: %v", i, test.str, err) + continue + } + + if version != test.version { + t.Errorf("(%v): invalid version: expected %v, got %v", + test.str, test.version, version) + } + } +} + +// TestMixedCaseEncode ensures mixed case HRPs are converted to lowercase as +// expected when encoding and that decoding the produced encoding when converted +// to all uppercase produces the lowercase HRP and original data. +func TestMixedCaseEncode(t *testing.T) { + tests := []struct { + name string + hrp string + data string + encoded string + }{{ + name: "all uppercase HRP with no data", + hrp: "A", + data: "", + encoded: "a12uel5l", + }, { + name: "all uppercase HRP with data", + hrp: "UPPERCASE", + data: "787878", + encoded: "uppercase10pu8sss7kmp", + }, { + name: "mixed case HRP even offsets uppercase", + hrp: "AbCdEf", + data: "00443214c74254b635cf84653a56d7c675be77df", + encoded: "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", + }, { + name: "mixed case HRP odd offsets uppercase ", + hrp: "aBcDeF", + data: "00443214c74254b635cf84653a56d7c675be77df", + encoded: "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", + }, { + name: "all lowercase HRP", + hrp: "abcdef", + data: "00443214c74254b635cf84653a56d7c675be77df", + encoded: "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", + }} + + for _, test := range tests { + // Convert the text hex to bytes, convert those bytes from base256 to + // base32, then ensure the encoded result with the HRP provided in the + // test data is as expected. + data, err := hex.DecodeString(test.data) + if err != nil { + t.Errorf("%q: invalid hex %q: %v", test.name, test.data, err) + continue + } + convertedData, err := ConvertBits(data, 8, 5, true) + if err != nil { + t.Errorf("%q: unexpected convert bits error: %v", test.name, + err) + continue + } + gotEncoded, err := Encode(test.hrp, convertedData) + if err != nil { + t.Errorf("%q: unexpected encode error: %v", test.name, err) + continue + } + if gotEncoded != test.encoded { + t.Errorf("%q: mismatched encoding -- got %q, want %q", test.name, + gotEncoded, test.encoded) + continue + } + + // Ensure the decoding the expected lowercase encoding converted to all + // uppercase produces the lowercase HRP and original data. + gotHRP, gotData, err := Decode(strings.ToUpper(test.encoded)) + if err != nil { + t.Errorf("%q: unexpected decode error: %v", test.name, err) + continue + } + wantHRP := strings.ToLower(test.hrp) + if gotHRP != wantHRP { + t.Errorf("%q: mismatched decoded HRP -- got %q, want %q", test.name, + gotHRP, wantHRP) + continue + } + convertedGotData, err := ConvertBits(gotData, 5, 8, false) + if err != nil { + t.Errorf("%q: unexpected convert bits error: %v", test.name, + err) + continue + } + if !bytes.Equal(convertedGotData, data) { + t.Errorf("%q: mismatched data -- got %x, want %x", test.name, + convertedGotData, data) + continue + } + } +} + +// TestCanDecodeUnlimtedBech32 tests whether decoding a large bech32 string works +// when using the DecodeNoLimit version +func TestCanDecodeUnlimtedBech32(t *testing.T) { + input := "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq5kx0yd" + + // Sanity check that an input of this length errors on regular Decode() + _, _, err := Decode(input) + if err == nil { + t.Fatalf("Test vector not appropriate") + } + + // Try and decode it. + hrp, data, err := DecodeNoLimit(input) + if err != nil { + t.Fatalf("Expected decoding of large string to work. Got error: %v", err) + } + + // Verify data for correctness. + if hrp != "1" { + t.Fatalf("Unexpected hrp: %v", hrp) + } + decodedHex := fmt.Sprintf("%x", data) + expected := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000" + if decodedHex != expected { + t.Fatalf("Unexpected decoded data: %s", decodedHex) + } +} + +// TestBech32Base256 ensures decoding and encoding various bech32, HRPs, and +// data produces the expected results when using EncodeFromBase256 and +// DecodeToBase256. It includes tests for proper handling of case +// manipulations. +func TestBech32Base256(t *testing.T) { + tests := []struct { + name string // test name + encoded string // bech32 string to decode + hrp string // expected human-readable part + data string // expected hex-encoded data + err error // expected error + }{{ + name: "all uppercase, no data", + encoded: "A12UEL5L", + hrp: "a", + data: "", + }, { + name: "long hrp with separator and excluded chars, no data", + encoded: "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", + hrp: "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio", + data: "", + }, { + name: "6 char hrp with data with leading zero", + encoded: "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", + hrp: "abcdef", + data: "00443214c74254b635cf84653a56d7c675be77df", + }, { + name: "hrp same as separator and max length encoded string", + encoded: "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", + hrp: "1", + data: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + }, { + name: "5 char hrp with data chosen to produce human-readable data part", + encoded: "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", + hrp: "split", + data: "c5f38b70305f519bf66d85fb6cf03058f3dde463ecd7918f2dc743918f2d", + }, { + name: "same as previous but with checksum invalidated", + encoded: "split1checkupstagehandshakeupstreamerranterredcaperred2y9e2w", + err: ErrInvalidChecksum{"2y9e3w", "2y9e3wlc445v", "2y9e2w"}, + }, { + name: "hrp with invalid character (space)", + encoded: "s lit1checkupstagehandshakeupstreamerranterredcaperredp8hs2p", + err: ErrInvalidCharacter(' '), + }, { + name: "hrp with invalid character (DEL)", + encoded: "spl\x7ft1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", + err: ErrInvalidCharacter(127), + }, { + name: "data part with invalid character (o)", + encoded: "split1cheo2y9e2w", + err: ErrNonCharsetChar('o'), + }, { + name: "data part too short", + encoded: "split1a2y9w", + err: ErrInvalidSeparatorIndex(5), + }, { + name: "empty hrp", + encoded: "1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", + err: ErrInvalidSeparatorIndex(0), + }, { + name: "no separator", + encoded: "pzry9x0s0muk", + err: ErrInvalidSeparatorIndex(-1), + }, { + name: "too long by one char", + encoded: "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", + err: ErrInvalidLength(91), + }, { + name: "invalid due to mixed case in hrp", + encoded: "aBcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", + err: ErrMixedCase{}, + }, { + name: "invalid due to mixed case in data part", + encoded: "abcdef1Qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", + err: ErrMixedCase{}, + }} + + for _, test := range tests { + // Ensure the decode either produces an error or not as expected. + str := test.encoded + gotHRP, gotData, err := DecodeToBase256(str) + if test.err != err { + t.Errorf("%q: unexpected decode error -- got %v, want %v", + test.name, err, test.err) + continue + } + if err != nil { + // End test case here if a decoding error was expected. + continue + } + + // Ensure the expected HRP and original data are as expected. + if gotHRP != test.hrp { + t.Errorf("%q: mismatched decoded HRP -- got %q, want %q", test.name, + gotHRP, test.hrp) + continue + } + data, err := hex.DecodeString(test.data) + if err != nil { + t.Errorf("%q: invalid hex %q: %v", test.name, test.data, err) + continue + } + if !bytes.Equal(gotData, data) { + t.Errorf("%q: mismatched data -- got %x, want %x", test.name, + gotData, data) + continue + } + + // Encode the same data with the HRP converted to all uppercase and + // ensure the result is the lowercase version of the original encoded + // bech32 string. + gotEncoded, err := EncodeFromBase256(strings.ToUpper(test.hrp), data) + if err != nil { + t.Errorf("%q: unexpected uppercase HRP encode error: %v", test.name, + err) + } + wantEncoded := strings.ToLower(str) + if gotEncoded != wantEncoded { + t.Errorf("%q: mismatched encoding -- got %q, want %q", test.name, + gotEncoded, wantEncoded) + } + + // Encode the same data with the HRP converted to all lowercase and + // ensure the result is the lowercase version of the original encoded + // bech32 string. + gotEncoded, err = EncodeFromBase256(strings.ToLower(test.hrp), data) + if err != nil { + t.Errorf("%q: unexpected lowercase HRP encode error: %v", test.name, + err) + } + if gotEncoded != wantEncoded { + t.Errorf("%q: mismatched encoding -- got %q, want %q", test.name, + gotEncoded, wantEncoded) + } + + // Encode the same data with the HRP converted to mixed upper and + // lowercase and ensure the result is the lowercase version of the + // original encoded bech32 string. + var mixedHRPBuilder strings.Builder + for i, r := range test.hrp { + if i%2 == 0 { + mixedHRPBuilder.WriteString(strings.ToUpper(string(r))) + continue + } + mixedHRPBuilder.WriteRune(r) + } + gotEncoded, err = EncodeFromBase256(mixedHRPBuilder.String(), data) + if err != nil { + t.Errorf("%q: unexpected lowercase HRP encode error: %v", test.name, + err) + } + if gotEncoded != wantEncoded { + t.Errorf("%q: mismatched encoding -- got %q, want %q", test.name, + gotEncoded, wantEncoded) + } + + // Ensure a bit flip in the string is caught. + pos := strings.LastIndexAny(test.encoded, "1") + flipped := str[:pos+1] + string((str[pos+1] ^ 1)) + str[pos+2:] + _, _, err = DecodeToBase256(flipped) + if err == nil { + t.Error("expected decoding to fail") + } + } +} + +// BenchmarkEncodeDecodeCycle performs a benchmark for a full encode/decode +// cycle of a bech32 string. It also reports the allocation count, which we +// expect to be 2 for a fully optimized cycle. +func BenchmarkEncodeDecodeCycle(b *testing.B) { + // Use a fixed, 49-byte raw data for testing. + inputData, err := hex.DecodeString("cbe6365ddbcda9a9915422c3f091c13f8c7b2f263b8d34067bd12c274408473fa764871c9dd51b1bb34873b3473b633ed1") + if err != nil { + b.Fatalf("failed to initialize input data: %v", err) + } + + // Convert this into a 79-byte, base 32 byte slice. + base32Input, err := ConvertBits(inputData, 8, 5, true) + if err != nil { + b.Fatalf("failed to convert input to 32 bits-per-element: %v", err) + } + + // Use a fixed hrp for the tests. This should generate an encoded bech32 + // string of size 90 (the maximum allowed by BIP-173). + hrp := "bc" + + // Begin the benchmark. Given that we test one roundtrip per iteration + // (that is, one Encode() and one Decode() operation), we expect at most + // 2 allocations per reported test op. + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + str, err := Encode(hrp, base32Input) + if err != nil { + b.Fatalf("failed to encode input: %v", err) + } + + _, _, err = Decode(str) + if err != nil { + b.Fatalf("failed to decode string: %v", err) + } + } +} + +// TestConvertBits tests whether base conversion works using TestConvertBits(). +func TestConvertBits(t *testing.T) { + tests := []struct { + input string + output string + fromBits uint8 + toBits uint8 + pad bool + }{ + // Trivial empty conversions. + {"", "", 8, 5, false}, + {"", "", 8, 5, true}, + {"", "", 5, 8, false}, + {"", "", 5, 8, true}, + + // Conversions of 0 value with/without padding. + {"00", "00", 8, 5, false}, + {"00", "0000", 8, 5, true}, + {"0000", "00", 5, 8, false}, + {"0000", "0000", 5, 8, true}, + + // Testing when conversion ends exactly at the byte edge. This makes + // both padded and unpadded versions the same. + {"0000000000", "0000000000000000", 8, 5, false}, + {"0000000000", "0000000000000000", 8, 5, true}, + {"0000000000000000", "0000000000", 5, 8, false}, + {"0000000000000000", "0000000000", 5, 8, true}, + + // Conversions of full byte sequences. + {"ffffff", "1f1f1f1f1e", 8, 5, true}, + {"1f1f1f1f1e", "ffffff", 5, 8, false}, + {"1f1f1f1f1e", "ffffff00", 5, 8, true}, + + // Sample random conversions. + {"c9ca", "190705", 8, 5, false}, + {"c9ca", "19070500", 8, 5, true}, + {"19070500", "c9ca", 5, 8, false}, + {"19070500", "c9ca00", 5, 8, true}, + + // Test cases tested on TestConvertBitsFailures with their corresponding + // fixes. + {"ff", "1f1c", 8, 5, true}, + {"1f1c10", "ff20", 5, 8, true}, + + // Large conversions. + { + "cbe6365ddbcda9a9915422c3f091c13f8c7b2f263b8d34067bd12c274408473fa764871c9dd51b1bb34873b3473b633ed1", + "190f13030c170e1b1916141a13040a14040b011f01040e01071e0607160b1906070e06130801131b1a0416020e110008081c1f1a0e19040703120e1d0a06181b160d0407070c1a07070d11131d1408", + 8, 5, true, + }, + { + "190f13030c170e1b1916141a13040a14040b011f01040e01071e0607160b1906070e06130801131b1a0416020e110008081c1f1a0e19040703120e1d0a06181b160d0407070c1a07070d11131d1408", + "cbe6365ddbcda9a9915422c3f091c13f8c7b2f263b8d34067bd12c274408473fa764871c9dd51b1bb34873b3473b633ed100", + 5, 8, true, + }, + } + + for i, tc := range tests { + input, err := hex.DecodeString(tc.input) + if err != nil { + t.Fatalf("invalid test input data: %v", err) + } + + expected, err := hex.DecodeString(tc.output) + if err != nil { + t.Fatalf("invalid test output data: %v", err) + } + + actual, err := ConvertBits(input, tc.fromBits, tc.toBits, tc.pad) + if err != nil { + t.Fatalf("test case %d failed: %v", i, err) + } + + if !bytes.Equal(actual, expected) { + t.Fatalf("test case %d has wrong output; expected=%x actual=%x", + i, expected, actual) + } + } +} + +// TestConvertBitsFailures tests for the expected conversion failures of +// ConvertBits(). +func TestConvertBitsFailures(t *testing.T) { + tests := []struct { + input string + fromBits uint8 + toBits uint8 + pad bool + err error + }{ + // Not enough output bytes when not using padding. + {"ff", 8, 5, false, ErrInvalidIncompleteGroup{}}, + {"1f1c10", 5, 8, false, ErrInvalidIncompleteGroup{}}, + + // Unsupported bit conversions. + {"", 0, 5, false, ErrInvalidBitGroups{}}, + {"", 10, 5, false, ErrInvalidBitGroups{}}, + {"", 5, 0, false, ErrInvalidBitGroups{}}, + {"", 5, 10, false, ErrInvalidBitGroups{}}, + } + + for i, tc := range tests { + input, err := hex.DecodeString(tc.input) + if err != nil { + t.Fatalf("invalid test input data: %v", err) + } + + _, err = ConvertBits(input, tc.fromBits, tc.toBits, tc.pad) + if err != tc.err { + t.Fatalf("test case %d failure: expected '%v' got '%v'", i, + tc.err, err) + } + } + +} + +// BenchmarkConvertBitsDown benchmarks the speed and memory allocation behavior +// of ConvertBits when converting from a higher base into a lower base (e.g. 8 +// => 5). +// +// Only a single allocation is expected, which is used for the output array. +func BenchmarkConvertBitsDown(b *testing.B) { + // Use a fixed, 49-byte raw data for testing. + inputData, err := hex.DecodeString("cbe6365ddbcda9a9915422c3f091c13f8c7b2f263b8d34067bd12c274408473fa764871c9dd51b1bb34873b3473b633ed1") + if err != nil { + b.Fatalf("failed to initialize input data: %v", err) + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := ConvertBits(inputData, 8, 5, true) + if err != nil { + b.Fatalf("error converting bits: %v", err) + } + } +} + +// BenchmarkConvertBitsDown benchmarks the speed and memory allocation behavior +// of ConvertBits when converting from a lower base into a higher base (e.g. 5 +// => 8). +// +// Only a single allocation is expected, which is used for the output array. +func BenchmarkConvertBitsUp(b *testing.B) { + // Use a fixed, 79-byte raw data for testing. + inputData, err := hex.DecodeString("190f13030c170e1b1916141a13040a14040b011f01040e01071e0607160b1906070e06130801131b1a0416020e110008081c1f1a0e19040703120e1d0a06181b160d0407070c1a07070d11131d1408") + if err != nil { + b.Fatalf("failed to initialize input data: %v", err) + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, err := ConvertBits(inputData, 8, 5, true) + if err != nil { + b.Fatalf("error converting bits: %v", err) + } + } +} diff --git a/btcutil/bech32/doc.go b/btcutil/bech32/doc.go new file mode 100644 index 0000000000..2d64fbe0bf --- /dev/null +++ b/btcutil/bech32/doc.go @@ -0,0 +1,15 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package bech32 provides a Go implementation of the bech32 format specified in +BIP 173. + +Bech32 strings consist of a human-readable part (hrp), followed by the +separator 1, then a checksummed data part encoded using the 32 characters +"qpzry9x8gf2tvdw0s3jn54khce6mua7l". + +More info: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki +*/ +package bech32 diff --git a/btcutil/bech32/error.go b/btcutil/bech32/error.go new file mode 100644 index 0000000000..e8b1fe8c30 --- /dev/null +++ b/btcutil/bech32/error.go @@ -0,0 +1,87 @@ +// Copyright (c) 2019 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bech32 + +import ( + "fmt" +) + +// ErrMixedCase is returned when the bech32 string has both lower and uppercase +// characters. +type ErrMixedCase struct{} + +func (e ErrMixedCase) Error() string { + return "string not all lowercase or all uppercase" +} + +// ErrInvalidBitGroups is returned when conversion is attempted between byte +// slices using bit-per-element of unsupported value. +type ErrInvalidBitGroups struct{} + +func (e ErrInvalidBitGroups) Error() string { + return "only bit groups between 1 and 8 allowed" +} + +// ErrInvalidIncompleteGroup is returned when then byte slice used as input has +// data of wrong length. +type ErrInvalidIncompleteGroup struct{} + +func (e ErrInvalidIncompleteGroup) Error() string { + return "invalid incomplete group" +} + +// ErrInvalidLength is returned when the bech32 string has an invalid length +// given the BIP-173 defined restrictions. +type ErrInvalidLength int + +func (e ErrInvalidLength) Error() string { + return fmt.Sprintf("invalid bech32 string length %d", int(e)) +} + +// ErrInvalidCharacter is returned when the bech32 string has a character +// outside the range of the supported charset. +type ErrInvalidCharacter rune + +func (e ErrInvalidCharacter) Error() string { + return fmt.Sprintf("invalid character in string: '%c'", rune(e)) +} + +// ErrInvalidSeparatorIndex is returned when the separator character '1' is +// in an invalid position in the bech32 string. +type ErrInvalidSeparatorIndex int + +func (e ErrInvalidSeparatorIndex) Error() string { + return fmt.Sprintf("invalid separator index %d", int(e)) +} + +// ErrNonCharsetChar is returned when a character outside of the specific +// bech32 charset is used in the string. +type ErrNonCharsetChar rune + +func (e ErrNonCharsetChar) Error() string { + return fmt.Sprintf("invalid character not part of charset: %v", int(e)) +} + +// ErrInvalidChecksum is returned when the extracted checksum of the string +// is different than what was expected. Both the original version, as well as +// the new bech32m checksum may be specified. +type ErrInvalidChecksum struct { + Expected string + ExpectedM string + Actual string +} + +func (e ErrInvalidChecksum) Error() string { + return fmt.Sprintf("invalid checksum (expected (bech32=%v, "+ + "bech32m=%v), got %v)", e.Expected, e.ExpectedM, e.Actual) +} + +// ErrInvalidDataByte is returned when a byte outside the range required for +// conversion into a string was found. +type ErrInvalidDataByte byte + +func (e ErrInvalidDataByte) Error() string { + return fmt.Sprintf("invalid data byte: %v", byte(e)) +} diff --git a/btcutil/bech32/example_test.go b/btcutil/bech32/example_test.go new file mode 100644 index 0000000000..290baaed6c --- /dev/null +++ b/btcutil/bech32/example_test.go @@ -0,0 +1,49 @@ +// Copyright (c) 2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bech32_test + +import ( + "encoding/hex" + "fmt" + + "github.com/btcsuite/btcd/btcutil/bech32" +) + +// This example demonstrates how to decode a bech32 encoded string. +func ExampleDecode() { + encoded := "bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx" + hrp, decoded, err := bech32.Decode(encoded) + if err != nil { + fmt.Println("Error:", err) + } + + // Show the decoded data. + fmt.Println("Decoded human-readable part:", hrp) + fmt.Println("Decoded Data:", hex.EncodeToString(decoded)) + + // Output: + // Decoded human-readable part: bc + // Decoded Data: 010e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e160e140f070d1a001912060b0d081504140311021d030c1d03040f1814060e1e16 +} + +// This example demonstrates how to encode data into a bech32 string. +func ExampleEncode() { + data := []byte("Test data") + // Convert test data to base32: + conv, err := bech32.ConvertBits(data, 8, 5, true) + if err != nil { + fmt.Println("Error:", err) + } + encoded, err := bech32.Encode("customHrp!11111q", conv) + if err != nil { + fmt.Println("Error:", err) + } + + // Show the encoded data. + fmt.Println("Encoded Data:", encoded) + + // Output: + // Encoded Data: customhrp!11111q123jhxapqv3shgcgkxpuhe +} diff --git a/btcutil/bech32/version.go b/btcutil/bech32/version.go new file mode 100644 index 0000000000..147037db9a --- /dev/null +++ b/btcutil/bech32/version.go @@ -0,0 +1,43 @@ +package bech32 + +// ChecksumConst is a type that represents the currently defined bech32 +// checksum constants. +type ChecksumConst int + +const ( + // Version0Const is the original constant used in the checksum + // verification for bech32. + Version0Const ChecksumConst = 1 + + // VersionMConst is the new constant used for bech32m checksum + // verification. + VersionMConst ChecksumConst = 0x2bc830a3 +) + +// Version defines the current set of bech32 versions. +type Version uint8 + +const ( + // Version0 defines the original bech version. + Version0 Version = iota + + // VersionM is the new bech32 version defined in BIP-350, also known as + // bech32m. + VersionM + + // VersionUnknown denotes an unknown bech version. + VersionUnknown +) + +// VersionToConsts maps bech32 versions to the checksum constant to be used +// when encoding, and asserting a particular version when decoding. +var VersionToConsts = map[Version]ChecksumConst{ + Version0: Version0Const, + VersionM: VersionMConst, +} + +// ConstsToVersion maps a bech32 constant to the version it's associated with. +var ConstsToVersion = map[ChecksumConst]Version{ + Version0Const: Version0, + VersionMConst: VersionM, +} diff --git a/btcutil/block.go b/btcutil/block.go new file mode 100644 index 0000000000..7d38abc4a0 --- /dev/null +++ b/btcutil/block.go @@ -0,0 +1,265 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "bytes" + "fmt" + "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// OutOfRangeError describes an error due to accessing an element that is out +// of range. +type OutOfRangeError string + +// BlockHeightUnknown is the value returned for a block height that is unknown. +// This is typically because the block has not been inserted into the main chain +// yet. +const BlockHeightUnknown = int32(-1) + +// Error satisfies the error interface and prints human-readable errors. +func (e OutOfRangeError) Error() string { + return string(e) +} + +// Block defines a bitcoin block that provides easier and more efficient +// manipulation of raw blocks. It also memoizes hashes for the block and its +// transactions on their first access so subsequent accesses don't have to +// repeat the relatively expensive hashing operations. +type Block struct { + msgBlock *wire.MsgBlock // Underlying MsgBlock + serializedBlock []byte // Serialized bytes for the block + serializedBlockNoWitness []byte // Serialized bytes for block w/o witness data + blockHash *chainhash.Hash // Cached block hash + blockHeight int32 // Height in the main block chain + transactions []*Tx // Transactions + txnsGenerated bool // ALL wrapped transactions generated +} + +// MsgBlock returns the underlying wire.MsgBlock for the Block. +func (b *Block) MsgBlock() *wire.MsgBlock { + // Return the cached block. + return b.msgBlock +} + +// Bytes returns the serialized bytes for the Block. This is equivalent to +// calling Serialize on the underlying wire.MsgBlock, however it caches the +// result so subsequent calls are more efficient. +func (b *Block) Bytes() ([]byte, error) { + // Return the cached serialized bytes if it has already been generated. + if len(b.serializedBlock) != 0 { + return b.serializedBlock, nil + } + + // Serialize the MsgBlock. + w := bytes.NewBuffer(make([]byte, 0, b.msgBlock.SerializeSize())) + err := b.msgBlock.Serialize(w) + if err != nil { + return nil, err + } + serializedBlock := w.Bytes() + + // Cache the serialized bytes and return them. + b.serializedBlock = serializedBlock + return serializedBlock, nil +} + +// BytesNoWitness returns the serialized bytes for the block with transactions +// encoded without any witness data. +func (b *Block) BytesNoWitness() ([]byte, error) { + // Return the cached serialized bytes if it has already been generated. + if len(b.serializedBlockNoWitness) != 0 { + return b.serializedBlockNoWitness, nil + } + + // Serialize the MsgBlock. + var w bytes.Buffer + err := b.msgBlock.SerializeNoWitness(&w) + if err != nil { + return nil, err + } + serializedBlock := w.Bytes() + + // Cache the serialized bytes and return them. + b.serializedBlockNoWitness = serializedBlock + return serializedBlock, nil +} + +// Hash returns the block identifier hash for the Block. This is equivalent to +// calling BlockHash on the underlying wire.MsgBlock, however it caches the +// result so subsequent calls are more efficient. +func (b *Block) Hash() *chainhash.Hash { + // Return the cached block hash if it has already been generated. + if b.blockHash != nil { + return b.blockHash + } + + // Cache the block hash and return it. + hash := b.msgBlock.BlockHash() + b.blockHash = &hash + return &hash +} + +// Tx returns a wrapped transaction (btcutil.Tx) for the transaction at the +// specified index in the Block. The supplied index is 0 based. That is to +// say, the first transaction in the block is txNum 0. This is nearly +// equivalent to accessing the raw transaction (wire.MsgTx) from the +// underlying wire.MsgBlock, however the wrapped transaction has some helpful +// properties such as caching the hash so subsequent calls are more efficient. +func (b *Block) Tx(txNum int) (*Tx, error) { + // Ensure the requested transaction is in range. + numTx := uint64(len(b.msgBlock.Transactions)) + if txNum < 0 || uint64(txNum) >= numTx { + str := fmt.Sprintf("transaction index %d is out of range - max %d", + txNum, numTx-1) + return nil, OutOfRangeError(str) + } + + // Generate slice to hold all of the wrapped transactions if needed. + if len(b.transactions) == 0 { + b.transactions = make([]*Tx, numTx) + } + + // Return the wrapped transaction if it has already been generated. + if b.transactions[txNum] != nil { + return b.transactions[txNum], nil + } + + // Generate and cache the wrapped transaction and return it. + newTx := NewTx(b.msgBlock.Transactions[txNum]) + newTx.SetIndex(txNum) + b.transactions[txNum] = newTx + return newTx, nil +} + +// Transactions returns a slice of wrapped transactions (btcutil.Tx) for all +// transactions in the Block. This is nearly equivalent to accessing the raw +// transactions (wire.MsgTx) in the underlying wire.MsgBlock, however it +// instead provides easy access to wrapped versions (btcutil.Tx) of them. +func (b *Block) Transactions() []*Tx { + // Return transactions if they have ALL already been generated. This + // flag is necessary because the wrapped transactions are lazily + // generated in a sparse fashion. + if b.txnsGenerated { + return b.transactions + } + + // Generate slice to hold all of the wrapped transactions if needed. + if len(b.transactions) == 0 { + b.transactions = make([]*Tx, len(b.msgBlock.Transactions)) + } + + // Generate and cache the wrapped transactions for all that haven't + // already been done. + for i, tx := range b.transactions { + if tx == nil { + newTx := NewTx(b.msgBlock.Transactions[i]) + newTx.SetIndex(i) + b.transactions[i] = newTx + } + } + + b.txnsGenerated = true + return b.transactions +} + +// TxHash returns the hash for the requested transaction number in the Block. +// The supplied index is 0 based. That is to say, the first transaction in the +// block is txNum 0. This is equivalent to calling TxHash on the underlying +// wire.MsgTx, however it caches the result so subsequent calls are more +// efficient. +func (b *Block) TxHash(txNum int) (*chainhash.Hash, error) { + // Attempt to get a wrapped transaction for the specified index. It + // will be created lazily if needed or simply return the cached version + // if it has already been generated. + tx, err := b.Tx(txNum) + if err != nil { + return nil, err + } + + // Defer to the wrapped transaction which will return the cached hash if + // it has already been generated. + return tx.Hash(), nil +} + +// TxLoc returns the offsets and lengths of each transaction in a raw block. +// It is used to allow fast indexing into transactions within the raw byte +// stream. +func (b *Block) TxLoc() ([]wire.TxLoc, error) { + rawMsg, err := b.Bytes() + if err != nil { + return nil, err + } + rbuf := bytes.NewBuffer(rawMsg) + + var mblock wire.MsgBlock + txLocs, err := mblock.DeserializeTxLoc(rbuf) + if err != nil { + return nil, err + } + return txLocs, err +} + +// Height returns the saved height of the block in the block chain. This value +// will be BlockHeightUnknown if it hasn't already explicitly been set. +func (b *Block) Height() int32 { + return b.blockHeight +} + +// SetHeight sets the height of the block in the block chain. +func (b *Block) SetHeight(height int32) { + b.blockHeight = height +} + +// NewBlock returns a new instance of a bitcoin block given an underlying +// wire.MsgBlock. See Block. +func NewBlock(msgBlock *wire.MsgBlock) *Block { + return &Block{ + msgBlock: msgBlock, + blockHeight: BlockHeightUnknown, + } +} + +// NewBlockFromBytes returns a new instance of a bitcoin block given the +// serialized bytes. See Block. +func NewBlockFromBytes(serializedBlock []byte) (*Block, error) { + br := bytes.NewReader(serializedBlock) + b, err := NewBlockFromReader(br) + if err != nil { + return nil, err + } + b.serializedBlock = serializedBlock + return b, nil +} + +// NewBlockFromReader returns a new instance of a bitcoin block given a +// Reader to deserialize the block. See Block. +func NewBlockFromReader(r io.Reader) (*Block, error) { + // Deserialize the bytes into a MsgBlock. + var msgBlock wire.MsgBlock + err := msgBlock.Deserialize(r) + if err != nil { + return nil, err + } + + b := Block{ + msgBlock: &msgBlock, + blockHeight: BlockHeightUnknown, + } + return &b, nil +} + +// NewBlockFromBlockAndBytes returns a new instance of a bitcoin block given +// an underlying wire.MsgBlock and the serialized bytes for it. See Block. +func NewBlockFromBlockAndBytes(msgBlock *wire.MsgBlock, serializedBlock []byte) *Block { + return &Block{ + msgBlock: msgBlock, + serializedBlock: serializedBlock, + blockHeight: BlockHeightUnknown, + } +} diff --git a/btcutil/block_test.go b/btcutil/block_test.go new file mode 100644 index 0000000000..e24b9842f7 --- /dev/null +++ b/btcutil/block_test.go @@ -0,0 +1,556 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil_test + +import ( + "bytes" + "io" + "reflect" + "testing" + "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" + "github.com/davecgh/go-spew/spew" +) + +// TestBlock tests the API for Block. +func TestBlock(t *testing.T) { + b := btcutil.NewBlock(&Block100000) + + // Ensure we get the same data back out. + if msgBlock := b.MsgBlock(); !reflect.DeepEqual(msgBlock, &Block100000) { + t.Errorf("MsgBlock: mismatched MsgBlock - got %v, want %v", + spew.Sdump(msgBlock), spew.Sdump(&Block100000)) + } + + // Ensure block height set and get work properly. + wantHeight := int32(100000) + b.SetHeight(wantHeight) + if gotHeight := b.Height(); gotHeight != wantHeight { + t.Errorf("Height: mismatched height - got %v, want %v", + gotHeight, wantHeight) + } + + // Hash for block 100,000. + wantHashStr := "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506" + wantHash, err := chainhash.NewHashFromStr(wantHashStr) + if err != nil { + t.Errorf("NewHashFromStr: %v", err) + } + + // Request the hash multiple times to test generation and caching. + for i := 0; i < 2; i++ { + hash := b.Hash() + if !hash.IsEqual(wantHash) { + t.Errorf("Hash #%d mismatched hash - got %v, want %v", + i, hash, wantHash) + } + } + + // Hashes for the transactions in Block100000. + wantTxHashes := []string{ + "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87", + "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4", + "6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4", + "e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d", + } + + // Create a new block to nuke all cached data. + b = btcutil.NewBlock(&Block100000) + + // Request hash for all transactions one at a time via Tx. + for i, txHash := range wantTxHashes { + wantHash, err := chainhash.NewHashFromStr(txHash) + if err != nil { + t.Errorf("NewHashFromStr: %v", err) + } + + // Request the hash multiple times to test generation and + // caching. + for j := 0; j < 2; j++ { + tx, err := b.Tx(i) + if err != nil { + t.Errorf("Tx #%d: %v", i, err) + continue + } + + hash := tx.Hash() + if !hash.IsEqual(wantHash) { + t.Errorf("Hash #%d mismatched hash - got %v, "+ + "want %v", j, hash, wantHash) + continue + } + } + } + + // Create a new block to nuke all cached data. + b = btcutil.NewBlock(&Block100000) + + // Request slice of all transactions multiple times to test generation + // and caching. + for i := 0; i < 2; i++ { + transactions := b.Transactions() + + // Ensure we get the expected number of transactions. + if len(transactions) != len(wantTxHashes) { + t.Errorf("Transactions #%d mismatched number of "+ + "transactions - got %d, want %d", i, + len(transactions), len(wantTxHashes)) + continue + } + + // Ensure all of the hashes match. + for j, tx := range transactions { + wantHash, err := chainhash.NewHashFromStr(wantTxHashes[j]) + if err != nil { + t.Errorf("NewHashFromStr: %v", err) + } + + hash := tx.Hash() + if !hash.IsEqual(wantHash) { + t.Errorf("Transactions #%d mismatched hashes "+ + "- got %v, want %v", j, hash, wantHash) + continue + } + } + } + + // Serialize the test block. + var block100000Buf bytes.Buffer + err = Block100000.Serialize(&block100000Buf) + if err != nil { + t.Errorf("Serialize: %v", err) + } + block100000Bytes := block100000Buf.Bytes() + + // Request serialized bytes multiple times to test generation and + // caching. + for i := 0; i < 2; i++ { + serializedBytes, err := b.Bytes() + if err != nil { + t.Errorf("Bytes: %v", err) + continue + } + if !bytes.Equal(serializedBytes, block100000Bytes) { + t.Errorf("Bytes #%d wrong bytes - got %v, want %v", i, + spew.Sdump(serializedBytes), + spew.Sdump(block100000Bytes)) + continue + } + } + + // Transaction offsets and length for the transaction in Block100000. + wantTxLocs := []wire.TxLoc{ + {TxStart: 81, TxLen: 144}, + {TxStart: 225, TxLen: 259}, + {TxStart: 484, TxLen: 257}, + {TxStart: 741, TxLen: 225}, + } + + // Ensure the transaction location information is accurate. + txLocs, err := b.TxLoc() + if err != nil { + t.Errorf("TxLoc: %v", err) + return + } + if !reflect.DeepEqual(txLocs, wantTxLocs) { + t.Errorf("TxLoc: mismatched transaction location information "+ + "- got %v, want %v", spew.Sdump(txLocs), + spew.Sdump(wantTxLocs)) + } +} + +// TestNewBlockFromBytes tests creation of a Block from serialized bytes. +func TestNewBlockFromBytes(t *testing.T) { + // Serialize the test block. + var block100000Buf bytes.Buffer + err := Block100000.Serialize(&block100000Buf) + if err != nil { + t.Errorf("Serialize: %v", err) + } + block100000Bytes := block100000Buf.Bytes() + + // Create a new block from the serialized bytes. + b, err := btcutil.NewBlockFromBytes(block100000Bytes) + if err != nil { + t.Errorf("NewBlockFromBytes: %v", err) + return + } + + // Ensure we get the same data back out. + serializedBytes, err := b.Bytes() + if err != nil { + t.Errorf("Bytes: %v", err) + return + } + if !bytes.Equal(serializedBytes, block100000Bytes) { + t.Errorf("Bytes: wrong bytes - got %v, want %v", + spew.Sdump(serializedBytes), + spew.Sdump(block100000Bytes)) + } + + // Ensure the generated MsgBlock is correct. + if msgBlock := b.MsgBlock(); !reflect.DeepEqual(msgBlock, &Block100000) { + t.Errorf("MsgBlock: mismatched MsgBlock - got %v, want %v", + spew.Sdump(msgBlock), spew.Sdump(&Block100000)) + } +} + +// TestNewBlockFromBlockAndBytes tests creation of a Block from a MsgBlock and +// raw bytes. +func TestNewBlockFromBlockAndBytes(t *testing.T) { + // Serialize the test block. + var block100000Buf bytes.Buffer + err := Block100000.Serialize(&block100000Buf) + if err != nil { + t.Errorf("Serialize: %v", err) + } + block100000Bytes := block100000Buf.Bytes() + + // Create a new block from the serialized bytes. + b := btcutil.NewBlockFromBlockAndBytes(&Block100000, block100000Bytes) + + // Ensure we get the same data back out. + serializedBytes, err := b.Bytes() + if err != nil { + t.Errorf("Bytes: %v", err) + return + } + if !bytes.Equal(serializedBytes, block100000Bytes) { + t.Errorf("Bytes: wrong bytes - got %v, want %v", + spew.Sdump(serializedBytes), + spew.Sdump(block100000Bytes)) + } + if msgBlock := b.MsgBlock(); !reflect.DeepEqual(msgBlock, &Block100000) { + t.Errorf("MsgBlock: mismatched MsgBlock - got %v, want %v", + spew.Sdump(msgBlock), spew.Sdump(&Block100000)) + } +} + +// TestBlockErrors tests the error paths for the Block API. +func TestBlockErrors(t *testing.T) { + // Ensure out of range errors are as expected. + wantErr := "transaction index -1 is out of range - max 3" + testErr := btcutil.OutOfRangeError(wantErr) + if testErr.Error() != wantErr { + t.Errorf("OutOfRangeError: wrong error - got %v, want %v", + testErr.Error(), wantErr) + } + + // Serialize the test block. + var block100000Buf bytes.Buffer + err := Block100000.Serialize(&block100000Buf) + if err != nil { + t.Errorf("Serialize: %v", err) + } + block100000Bytes := block100000Buf.Bytes() + + // Create a new block from the serialized bytes. + b, err := btcutil.NewBlockFromBytes(block100000Bytes) + if err != nil { + t.Errorf("NewBlockFromBytes: %v", err) + return + } + + // Truncate the block byte buffer to force errors. + shortBytes := block100000Bytes[:80] + _, err = btcutil.NewBlockFromBytes(shortBytes) + if err != io.EOF { + t.Errorf("NewBlockFromBytes: did not get expected error - "+ + "got %v, want %v", err, io.EOF) + } + + // Ensure TxHash returns expected error on invalid indices. + _, err = b.TxHash(-1) + if _, ok := err.(btcutil.OutOfRangeError); !ok { + t.Errorf("TxHash: wrong error - got: %v <%T>, "+ + "want: <%T>", err, err, btcutil.OutOfRangeError("")) + } + _, err = b.TxHash(len(Block100000.Transactions)) + if _, ok := err.(btcutil.OutOfRangeError); !ok { + t.Errorf("TxHash: wrong error - got: %v <%T>, "+ + "want: <%T>", err, err, btcutil.OutOfRangeError("")) + } + + // Ensure Tx returns expected error on invalid indices. + _, err = b.Tx(-1) + if _, ok := err.(btcutil.OutOfRangeError); !ok { + t.Errorf("Tx: wrong error - got: %v <%T>, "+ + "want: <%T>", err, err, btcutil.OutOfRangeError("")) + } + _, err = b.Tx(len(Block100000.Transactions)) + if _, ok := err.(btcutil.OutOfRangeError); !ok { + t.Errorf("Tx: wrong error - got: %v <%T>, "+ + "want: <%T>", err, err, btcutil.OutOfRangeError("")) + } + + // Ensure TxLoc returns expected error with short byte buffer. + // This makes use of the test package only function, SetBlockBytes, to + // inject a short byte buffer. + b.SetBlockBytes(shortBytes) + _, err = b.TxLoc() + if err != io.EOF { + t.Errorf("TxLoc: did not get expected error - "+ + "got %v, want %v", err, io.EOF) + } +} + +// Block100000 defines block 100,000 of the block chain. It is used to +// test Block operations. +var Block100000 = wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: chainhash.Hash([32]byte{ // Make go vet happy. + 0x50, 0x12, 0x01, 0x19, 0x17, 0x2a, 0x61, 0x04, + 0x21, 0xa6, 0xc3, 0x01, 0x1d, 0xd3, 0x30, 0xd9, + 0xdf, 0x07, 0xb6, 0x36, 0x16, 0xc2, 0xcc, 0x1f, + 0x1c, 0xd0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + }), // 000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250 + MerkleRoot: chainhash.Hash([32]byte{ // Make go vet happy. + 0x66, 0x57, 0xa9, 0x25, 0x2a, 0xac, 0xd5, 0xc0, + 0xb2, 0x94, 0x09, 0x96, 0xec, 0xff, 0x95, 0x22, + 0x28, 0xc3, 0x06, 0x7c, 0xc3, 0x8d, 0x48, 0x85, + 0xef, 0xb5, 0xa4, 0xac, 0x42, 0x47, 0xe9, 0xf3, + }), // f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 + Timestamp: time.Unix(1293623863, 0), // 2010-12-29 11:57:43 +0000 UTC + Bits: 0x1b04864c, // 453281356 + Nonce: 0x10572b0f, // 274148111 + }, + Transactions: []*wire.MsgTx{ + { + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{}, + Index: 0xffffffff, + }, + SignatureScript: []byte{ + 0x04, 0x4c, 0x86, 0x04, 0x1b, 0x02, 0x06, 0x02, + }, + Sequence: 0xffffffff, + Witness: [][]byte{ + {0x04, 0x31}, + {0x01, 0x43}, + }, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x12a05f200, // 5000000000 + PkScript: []byte{ + 0x41, // OP_DATA_65 + 0x04, 0x1b, 0x0e, 0x8c, 0x25, 0x67, 0xc1, 0x25, + 0x36, 0xaa, 0x13, 0x35, 0x7b, 0x79, 0xa0, 0x73, + 0xdc, 0x44, 0x44, 0xac, 0xb8, 0x3c, 0x4e, 0xc7, + 0xa0, 0xe2, 0xf9, 0x9d, 0xd7, 0x45, 0x75, 0x16, + 0xc5, 0x81, 0x72, 0x42, 0xda, 0x79, 0x69, 0x24, + 0xca, 0x4e, 0x99, 0x94, 0x7d, 0x08, 0x7f, 0xed, + 0xf9, 0xce, 0x46, 0x7c, 0xb9, 0xf7, 0xc6, 0x28, + 0x70, 0x78, 0xf8, 0x01, 0xdf, 0x27, 0x6f, 0xdf, + 0x84, // 65-byte signature + 0xac, // OP_CHECKSIG + }, + }, + }, + LockTime: 0, + }, + { + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash([32]byte{ // Make go vet happy. + 0x03, 0x2e, 0x38, 0xe9, 0xc0, 0xa8, 0x4c, 0x60, + 0x46, 0xd6, 0x87, 0xd1, 0x05, 0x56, 0xdc, 0xac, + 0xc4, 0x1d, 0x27, 0x5e, 0xc5, 0x5f, 0xc0, 0x07, + 0x79, 0xac, 0x88, 0xfd, 0xf3, 0x57, 0xa1, 0x87, + }), // 87a157f3fd88ac7907c05fc55e271dc4acdc5605d187d646604ca8c0e9382e03 + Index: 0, + }, + SignatureScript: []byte{ + 0x49, // OP_DATA_73 + 0x30, 0x46, 0x02, 0x21, 0x00, 0xc3, 0x52, 0xd3, + 0xdd, 0x99, 0x3a, 0x98, 0x1b, 0xeb, 0xa4, 0xa6, + 0x3a, 0xd1, 0x5c, 0x20, 0x92, 0x75, 0xca, 0x94, + 0x70, 0xab, 0xfc, 0xd5, 0x7d, 0xa9, 0x3b, 0x58, + 0xe4, 0xeb, 0x5d, 0xce, 0x82, 0x02, 0x21, 0x00, + 0x84, 0x07, 0x92, 0xbc, 0x1f, 0x45, 0x60, 0x62, + 0x81, 0x9f, 0x15, 0xd3, 0x3e, 0xe7, 0x05, 0x5c, + 0xf7, 0xb5, 0xee, 0x1a, 0xf1, 0xeb, 0xcc, 0x60, + 0x28, 0xd9, 0xcd, 0xb1, 0xc3, 0xaf, 0x77, 0x48, + 0x01, // 73-byte signature + 0x41, // OP_DATA_65 + 0x04, 0xf4, 0x6d, 0xb5, 0xe9, 0xd6, 0x1a, 0x9d, + 0xc2, 0x7b, 0x8d, 0x64, 0xad, 0x23, 0xe7, 0x38, + 0x3a, 0x4e, 0x6c, 0xa1, 0x64, 0x59, 0x3c, 0x25, + 0x27, 0xc0, 0x38, 0xc0, 0x85, 0x7e, 0xb6, 0x7e, + 0xe8, 0xe8, 0x25, 0xdc, 0xa6, 0x50, 0x46, 0xb8, + 0x2c, 0x93, 0x31, 0x58, 0x6c, 0x82, 0xe0, 0xfd, + 0x1f, 0x63, 0x3f, 0x25, 0xf8, 0x7c, 0x16, 0x1b, + 0xc6, 0xf8, 0xa6, 0x30, 0x12, 0x1d, 0xf2, 0xb3, + 0xd3, // 65-byte pubkey + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0x2123e300, // 556000000 + PkScript: []byte{ + 0x76, // OP_DUP + 0xa9, // OP_HASH160 + 0x14, // OP_DATA_20 + 0xc3, 0x98, 0xef, 0xa9, 0xc3, 0x92, 0xba, 0x60, + 0x13, 0xc5, 0xe0, 0x4e, 0xe7, 0x29, 0x75, 0x5e, + 0xf7, 0xf5, 0x8b, 0x32, + 0x88, // OP_EQUALVERIFY + 0xac, // OP_CHECKSIG + }, + }, + { + Value: 0x108e20f00, // 4444000000 + PkScript: []byte{ + 0x76, // OP_DUP + 0xa9, // OP_HASH160 + 0x14, // OP_DATA_20 + 0x94, 0x8c, 0x76, 0x5a, 0x69, 0x14, 0xd4, 0x3f, + 0x2a, 0x7a, 0xc1, 0x77, 0xda, 0x2c, 0x2f, 0x6b, + 0x52, 0xde, 0x3d, 0x7c, + 0x88, // OP_EQUALVERIFY + 0xac, // OP_CHECKSIG + }, + }, + }, + LockTime: 0, + }, + { + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash([32]byte{ // Make go vet happy. + 0xc3, 0x3e, 0xbf, 0xf2, 0xa7, 0x09, 0xf1, 0x3d, + 0x9f, 0x9a, 0x75, 0x69, 0xab, 0x16, 0xa3, 0x27, + 0x86, 0xaf, 0x7d, 0x7e, 0x2d, 0xe0, 0x92, 0x65, + 0xe4, 0x1c, 0x61, 0xd0, 0x78, 0x29, 0x4e, 0xcf, + }), // cf4e2978d0611ce46592e02d7e7daf8627a316ab69759a9f3df109a7f2bf3ec3 + Index: 1, + }, + SignatureScript: []byte{ + 0x47, // OP_DATA_71 + 0x30, 0x44, 0x02, 0x20, 0x03, 0x2d, 0x30, 0xdf, + 0x5e, 0xe6, 0xf5, 0x7f, 0xa4, 0x6c, 0xdd, 0xb5, + 0xeb, 0x8d, 0x0d, 0x9f, 0xe8, 0xde, 0x6b, 0x34, + 0x2d, 0x27, 0x94, 0x2a, 0xe9, 0x0a, 0x32, 0x31, + 0xe0, 0xba, 0x33, 0x3e, 0x02, 0x20, 0x3d, 0xee, + 0xe8, 0x06, 0x0f, 0xdc, 0x70, 0x23, 0x0a, 0x7f, + 0x5b, 0x4a, 0xd7, 0xd7, 0xbc, 0x3e, 0x62, 0x8c, + 0xbe, 0x21, 0x9a, 0x88, 0x6b, 0x84, 0x26, 0x9e, + 0xae, 0xb8, 0x1e, 0x26, 0xb4, 0xfe, 0x01, + 0x41, // OP_DATA_65 + 0x04, 0xae, 0x31, 0xc3, 0x1b, 0xf9, 0x12, 0x78, + 0xd9, 0x9b, 0x83, 0x77, 0xa3, 0x5b, 0xbc, 0xe5, + 0xb2, 0x7d, 0x9f, 0xff, 0x15, 0x45, 0x68, 0x39, + 0xe9, 0x19, 0x45, 0x3f, 0xc7, 0xb3, 0xf7, 0x21, + 0xf0, 0xba, 0x40, 0x3f, 0xf9, 0x6c, 0x9d, 0xee, + 0xb6, 0x80, 0xe5, 0xfd, 0x34, 0x1c, 0x0f, 0xc3, + 0xa7, 0xb9, 0x0d, 0xa4, 0x63, 0x1e, 0xe3, 0x95, + 0x60, 0x63, 0x9d, 0xb4, 0x62, 0xe9, 0xcb, 0x85, + 0x0f, // 65-byte pubkey + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0xf4240, // 1000000 + PkScript: []byte{ + 0x76, // OP_DUP + 0xa9, // OP_HASH160 + 0x14, // OP_DATA_20 + 0xb0, 0xdc, 0xbf, 0x97, 0xea, 0xbf, 0x44, 0x04, + 0xe3, 0x1d, 0x95, 0x24, 0x77, 0xce, 0x82, 0x2d, + 0xad, 0xbe, 0x7e, 0x10, + 0x88, // OP_EQUALVERIFY + 0xac, // OP_CHECKSIG + }, + }, + { + Value: 0x11d260c0, // 299000000 + PkScript: []byte{ + 0x76, // OP_DUP + 0xa9, // OP_HASH160 + 0x14, // OP_DATA_20 + 0x6b, 0x12, 0x81, 0xee, 0xc2, 0x5a, 0xb4, 0xe1, + 0xe0, 0x79, 0x3f, 0xf4, 0xe0, 0x8a, 0xb1, 0xab, + 0xb3, 0x40, 0x9c, 0xd9, + 0x88, // OP_EQUALVERIFY + 0xac, // OP_CHECKSIG + }, + }, + }, + LockTime: 0, + }, + { + Version: 1, + TxIn: []*wire.TxIn{ + { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash([32]byte{ // Make go vet happy. + 0x0b, 0x60, 0x72, 0xb3, 0x86, 0xd4, 0xa7, 0x73, + 0x23, 0x52, 0x37, 0xf6, 0x4c, 0x11, 0x26, 0xac, + 0x3b, 0x24, 0x0c, 0x84, 0xb9, 0x17, 0xa3, 0x90, + 0x9b, 0xa1, 0xc4, 0x3d, 0xed, 0x5f, 0x51, 0xf4, + }), // f4515fed3dc4a19b90a317b9840c243bac26114cf637522373a7d486b372600b + Index: 0, + }, + SignatureScript: []byte{ + 0x49, // OP_DATA_73 + 0x30, 0x46, 0x02, 0x21, 0x00, 0xbb, 0x1a, 0xd2, + 0x6d, 0xf9, 0x30, 0xa5, 0x1c, 0xce, 0x11, 0x0c, + 0xf4, 0x4f, 0x7a, 0x48, 0xc3, 0xc5, 0x61, 0xfd, + 0x97, 0x75, 0x00, 0xb1, 0xae, 0x5d, 0x6b, 0x6f, + 0xd1, 0x3d, 0x0b, 0x3f, 0x4a, 0x02, 0x21, 0x00, + 0xc5, 0xb4, 0x29, 0x51, 0xac, 0xed, 0xff, 0x14, + 0xab, 0xba, 0x27, 0x36, 0xfd, 0x57, 0x4b, 0xdb, + 0x46, 0x5f, 0x3e, 0x6f, 0x8d, 0xa1, 0x2e, 0x2c, + 0x53, 0x03, 0x95, 0x4a, 0xca, 0x7f, 0x78, 0xf3, + 0x01, // 73-byte signature + 0x41, // OP_DATA_65 + 0x04, 0xa7, 0x13, 0x5b, 0xfe, 0x82, 0x4c, 0x97, + 0xec, 0xc0, 0x1e, 0xc7, 0xd7, 0xe3, 0x36, 0x18, + 0x5c, 0x81, 0xe2, 0xaa, 0x2c, 0x41, 0xab, 0x17, + 0x54, 0x07, 0xc0, 0x94, 0x84, 0xce, 0x96, 0x94, + 0xb4, 0x49, 0x53, 0xfc, 0xb7, 0x51, 0x20, 0x65, + 0x64, 0xa9, 0xc2, 0x4d, 0xd0, 0x94, 0xd4, 0x2f, + 0xdb, 0xfd, 0xd5, 0xaa, 0xd3, 0xe0, 0x63, 0xce, + 0x6a, 0xf4, 0xcf, 0xaa, 0xea, 0x4e, 0xa1, 0x4f, + 0xbb, // 65-byte pubkey + }, + Sequence: 0xffffffff, + }, + }, + TxOut: []*wire.TxOut{ + { + Value: 0xf4240, // 1000000 + PkScript: []byte{ + 0x76, // OP_DUP + 0xa9, // OP_HASH160 + 0x14, // OP_DATA_20 + 0x39, 0xaa, 0x3d, 0x56, 0x9e, 0x06, 0xa1, 0xd7, + 0x92, 0x6d, 0xc4, 0xbe, 0x11, 0x93, 0xc9, 0x9b, + 0xf2, 0xeb, 0x9e, 0xe0, + 0x88, // OP_EQUALVERIFY + 0xac, // OP_CHECKSIG + }, + }, + }, + LockTime: 0, + }, + }, +} diff --git a/btcutil/bloom/README.md b/btcutil/bloom/README.md new file mode 100644 index 0000000000..4a5c937f88 --- /dev/null +++ b/btcutil/bloom/README.md @@ -0,0 +1,30 @@ +bloom +===== + +[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)](https://travis-ci.org/btcsuite/btcutil) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/btcutil/bloom) + +Package bloom provides an API for dealing with bitcoin-specific bloom filters. + +A comprehensive suite of tests is provided to ensure proper functionality. See +`test_coverage.txt` for the gocov coverage report. Alternatively, if you are +running a POSIX OS, you can run the `cov_report.sh` script for a real-time +report. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil/bloom +``` + +## Examples + +* [NewFilter Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/bloom#example-NewFilter) + Demonstrates how to create a new bloom filter, add a transaction hash to it, + and check if the filter matches the transaction. + +## License + +Package bloom is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/bloom/cov_report.sh b/btcutil/bloom/cov_report.sh new file mode 100644 index 0000000000..307f05b76c --- /dev/null +++ b/btcutil/bloom/cov_report.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# This script uses gocov to generate a test coverage report. +# The gocov tool my be obtained with the following command: +# go get github.com/axw/gocov/gocov +# +# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. + +# Check for gocov. +type gocov >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo >&2 "This script requires the gocov tool." + echo >&2 "You may obtain it with the following command:" + echo >&2 "go get github.com/axw/gocov/gocov" + exit 1 +fi +gocov test | gocov report diff --git a/btcutil/bloom/example_test.go b/btcutil/bloom/example_test.go new file mode 100644 index 0000000000..bcd5d0190b --- /dev/null +++ b/btcutil/bloom/example_test.go @@ -0,0 +1,45 @@ +// Copyright (c) 2014-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bloom_test + +import ( + "fmt" + "math/rand" + "time" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil/bloom" +) + +// This example demonstrates how to create a new bloom filter, add a transaction +// hash to it, and check if the filter matches the transaction. +func ExampleNewFilter() { + rand.Seed(time.Now().UnixNano()) + tweak := rand.Uint32() + + // Create a new bloom filter intended to hold 10 elements with a 0.01% + // false positive rate and does not include any automatic update + // functionality when transactions are matched. + filter := bloom.NewFilter(10, tweak, 0.0001, wire.BloomUpdateNone) + + // Create a transaction hash and add it to the filter. This particular + // trasaction is the first transaction in block 310,000 of the main + // bitcoin block chain. + txHashStr := "fd611c56ca0d378cdcd16244b45c2ba9588da3adac367c4ef43e808b280b8a45" + txHash, err := chainhash.NewHashFromStr(txHashStr) + if err != nil { + fmt.Println(err) + return + } + filter.AddHash(txHash) + + // Show that the filter matches. + matches := filter.Matches(txHash[:]) + fmt.Println("Filter Matches?:", matches) + + // Output: + // Filter Matches?: true +} diff --git a/btcutil/bloom/filter.go b/btcutil/bloom/filter.go new file mode 100644 index 0000000000..8c4527ea29 --- /dev/null +++ b/btcutil/bloom/filter.go @@ -0,0 +1,354 @@ +// Copyright (c) 2014-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bloom + +import ( + "encoding/binary" + "math" + "sync" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" +) + +// ln2Squared is simply the square of the natural log of 2. +const ln2Squared = math.Ln2 * math.Ln2 + +// minUint32 is a convenience function to return the minimum value of the two +// passed uint32 values. +func minUint32(a, b uint32) uint32 { + if a < b { + return a + } + return b +} + +// Filter defines a bitcoin bloom filter that provides easy manipulation of raw +// filter data. +type Filter struct { + mtx sync.Mutex + msgFilterLoad *wire.MsgFilterLoad +} + +// NewFilter creates a new bloom filter instance, mainly to be used by SPV +// clients. The tweak parameter is a random value added to the seed value. +// The false positive rate is the probability of a false positive where 1.0 is +// "match everything" and zero is unachievable. Thus, providing any false +// positive rates less than 0 or greater than 1 will be adjusted to the valid +// range. +// +// For more information on what values to use for both elements and fprate, +// see https://en.wikipedia.org/wiki/Bloom_filter. +func NewFilter(elements, tweak uint32, fprate float64, flags wire.BloomUpdateType) *Filter { + // Massage the false positive rate to sane values. + if fprate > 1.0 { + fprate = 1.0 + } + if fprate < 1e-9 { + fprate = 1e-9 + } + + // Calculate the size of the filter in bytes for the given number of + // elements and false positive rate. + // + // Equivalent to m = -(n*ln(p) / ln(2)^2), where m is in bits. + // Then clamp it to the maximum filter size and convert to bytes. + dataLen := uint32(-1 * float64(elements) * math.Log(fprate) / ln2Squared) + dataLen = minUint32(dataLen, wire.MaxFilterLoadFilterSize*8) / 8 + + // Calculate the number of hash functions based on the size of the + // filter calculated above and the number of elements. + // + // Equivalent to k = (m/n) * ln(2) + // Then clamp it to the maximum allowed hash funcs. + hashFuncs := uint32(float64(dataLen*8) / float64(elements) * math.Ln2) + hashFuncs = minUint32(hashFuncs, wire.MaxFilterLoadHashFuncs) + + data := make([]byte, dataLen) + msg := wire.NewMsgFilterLoad(data, hashFuncs, tweak, flags) + + return &Filter{ + msgFilterLoad: msg, + } +} + +// LoadFilter creates a new Filter instance with the given underlying +// wire.MsgFilterLoad. +func LoadFilter(filter *wire.MsgFilterLoad) *Filter { + return &Filter{ + msgFilterLoad: filter, + } +} + +// IsLoaded returns true if a filter is loaded, otherwise false. +// +// This function is safe for concurrent access. +func (bf *Filter) IsLoaded() bool { + bf.mtx.Lock() + loaded := bf.msgFilterLoad != nil + bf.mtx.Unlock() + return loaded +} + +// Reload loads a new filter replacing any existing filter. +// +// This function is safe for concurrent access. +func (bf *Filter) Reload(filter *wire.MsgFilterLoad) { + bf.mtx.Lock() + bf.msgFilterLoad = filter + bf.mtx.Unlock() +} + +// Unload unloads the bloom filter. +// +// This function is safe for concurrent access. +func (bf *Filter) Unload() { + bf.mtx.Lock() + bf.msgFilterLoad = nil + bf.mtx.Unlock() +} + +// hash returns the bit offset in the bloom filter which corresponds to the +// passed data for the given independent hash function number. +func (bf *Filter) hash(hashNum uint32, data []byte) uint32 { + // bitcoind: 0xfba4c795 chosen as it guarantees a reasonable bit + // difference between hashNum values. + // + // Note that << 3 is equivalent to multiplying by 8, but is faster. + // Thus the returned hash is brought into range of the number of bits + // the filter has and returned. + mm := MurmurHash3(hashNum*0xfba4c795+bf.msgFilterLoad.Tweak, data) + return mm % (uint32(len(bf.msgFilterLoad.Filter)) << 3) +} + +// matches returns true if the bloom filter might contain the passed data and +// false if it definitely does not. +// +// This function MUST be called with the filter lock held. +func (bf *Filter) matches(data []byte) bool { + if bf.msgFilterLoad == nil { + return false + } + + // The bloom filter does not contain the data if any of the bit offsets + // which result from hashing the data using each independent hash + // function are not set. The shifts and masks below are a faster + // equivalent of: + // arrayIndex := idx / 8 (idx >> 3) + // bitOffset := idx % 8 (idx & 7) + /// if filter[arrayIndex] & 1<>3]&(1<<(idx&7)) == 0 { + return false + } + } + return true +} + +// Matches returns true if the bloom filter might contain the passed data and +// false if it definitely does not. +// +// This function is safe for concurrent access. +func (bf *Filter) Matches(data []byte) bool { + bf.mtx.Lock() + match := bf.matches(data) + bf.mtx.Unlock() + return match +} + +// matchesOutPoint returns true if the bloom filter might contain the passed +// outpoint and false if it definitely does not. +// +// This function MUST be called with the filter lock held. +func (bf *Filter) matchesOutPoint(outpoint *wire.OutPoint) bool { + // Serialize + var buf [chainhash.HashSize + 4]byte + copy(buf[:], outpoint.Hash[:]) + binary.LittleEndian.PutUint32(buf[chainhash.HashSize:], outpoint.Index) + + return bf.matches(buf[:]) +} + +// MatchesOutPoint returns true if the bloom filter might contain the passed +// outpoint and false if it definitely does not. +// +// This function is safe for concurrent access. +func (bf *Filter) MatchesOutPoint(outpoint *wire.OutPoint) bool { + bf.mtx.Lock() + match := bf.matchesOutPoint(outpoint) + bf.mtx.Unlock() + return match +} + +// add adds the passed byte slice to the bloom filter. +// +// This function MUST be called with the filter lock held. +func (bf *Filter) add(data []byte) { + if bf.msgFilterLoad == nil { + return + } + + // Adding data to a bloom filter consists of setting all of the bit + // offsets which result from hashing the data using each independent + // hash function. The shifts and masks below are a faster equivalent + // of: + // arrayIndex := idx / 8 (idx >> 3) + // bitOffset := idx % 8 (idx & 7) + /// filter[arrayIndex] |= 1<>3] |= (1 << (7 & idx)) + } +} + +// Add adds the passed byte slice to the bloom filter. +// +// This function is safe for concurrent access. +func (bf *Filter) Add(data []byte) { + bf.mtx.Lock() + bf.add(data) + bf.mtx.Unlock() +} + +// AddHash adds the passed chainhash.Hash to the Filter. +// +// This function is safe for concurrent access. +func (bf *Filter) AddHash(hash *chainhash.Hash) { + bf.mtx.Lock() + bf.add(hash[:]) + bf.mtx.Unlock() +} + +// addOutPoint adds the passed transaction outpoint to the bloom filter. +// +// This function MUST be called with the filter lock held. +func (bf *Filter) addOutPoint(outpoint *wire.OutPoint) { + // Serialize + var buf [chainhash.HashSize + 4]byte + copy(buf[:], outpoint.Hash[:]) + binary.LittleEndian.PutUint32(buf[chainhash.HashSize:], outpoint.Index) + + bf.add(buf[:]) +} + +// AddOutPoint adds the passed transaction outpoint to the bloom filter. +// +// This function is safe for concurrent access. +func (bf *Filter) AddOutPoint(outpoint *wire.OutPoint) { + bf.mtx.Lock() + bf.addOutPoint(outpoint) + bf.mtx.Unlock() +} + +// maybeAddOutpoint potentially adds the passed outpoint to the bloom filter +// depending on the bloom update flags and the type of the passed public key +// script. +// +// This function MUST be called with the filter lock held. +func (bf *Filter) maybeAddOutpoint(pkScript []byte, outHash *chainhash.Hash, outIdx uint32) { + switch bf.msgFilterLoad.Flags { + case wire.BloomUpdateAll: + outpoint := wire.NewOutPoint(outHash, outIdx) + bf.addOutPoint(outpoint) + case wire.BloomUpdateP2PubkeyOnly: + class := txscript.GetScriptClass(pkScript) + if class == txscript.PubKeyTy || class == txscript.MultiSigTy { + outpoint := wire.NewOutPoint(outHash, outIdx) + bf.addOutPoint(outpoint) + } + } +} + +// matchTxAndUpdate returns true if the bloom filter matches data within the +// passed transaction, otherwise false is returned. If the filter does match +// the passed transaction, it will also update the filter depending on the bloom +// update flags set via the loaded filter if needed. +// +// This function MUST be called with the filter lock held. +func (bf *Filter) matchTxAndUpdate(tx *btcutil.Tx) bool { + // Check if the filter matches the hash of the transaction. + // This is useful for finding transactions when they appear in a block. + matched := bf.matches(tx.Hash()[:]) + + // Check if the filter matches any data elements in the public key + // scripts of any of the outputs. When it does, add the outpoint that + // matched so transactions which spend from the matched transaction are + // also included in the filter. This removes the burden of updating the + // filter for this scenario from the client. It is also more efficient + // on the network since it avoids the need for another filteradd message + // from the client and avoids some potential races that could otherwise + // occur. + for i, txOut := range tx.MsgTx().TxOut { + pushedData, err := txscript.PushedData(txOut.PkScript) + if err != nil { + continue + } + + for _, data := range pushedData { + if !bf.matches(data) { + continue + } + + matched = true + bf.maybeAddOutpoint(txOut.PkScript, tx.Hash(), uint32(i)) + break + } + } + + // Nothing more to do if a match has already been made. + if matched { + return true + } + + // At this point, the transaction and none of the data elements in the + // public key scripts of its outputs matched. + + // Check if the filter matches any outpoints this transaction spends or + // any data elements in the signature scripts of any of the inputs. + for _, txin := range tx.MsgTx().TxIn { + if bf.matchesOutPoint(&txin.PreviousOutPoint) { + return true + } + + pushedData, err := txscript.PushedData(txin.SignatureScript) + if err != nil { + continue + } + for _, data := range pushedData { + if bf.matches(data) { + return true + } + } + } + + return false +} + +// MatchTxAndUpdate returns true if the bloom filter matches data within the +// passed transaction, otherwise false is returned. If the filter does match +// the passed transaction, it will also update the filter depending on the bloom +// update flags set via the loaded filter if needed. +// +// This function is safe for concurrent access. +func (bf *Filter) MatchTxAndUpdate(tx *btcutil.Tx) bool { + bf.mtx.Lock() + match := bf.matchTxAndUpdate(tx) + bf.mtx.Unlock() + return match +} + +// MsgFilterLoad returns the underlying wire.MsgFilterLoad for the bloom +// filter. +// +// This function is safe for concurrent access. +func (bf *Filter) MsgFilterLoad() *wire.MsgFilterLoad { + bf.mtx.Lock() + msg := bf.msgFilterLoad + bf.mtx.Unlock() + return msg +} diff --git a/btcutil/bloom/filter_test.go b/btcutil/bloom/filter_test.go new file mode 100644 index 0000000000..1811dbf57e --- /dev/null +++ b/btcutil/bloom/filter_test.go @@ -0,0 +1,660 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bloom_test + +import ( + "bytes" + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/bloom" +) + +// TestFilterLarge ensures a maximum sized filter can be created. +func TestFilterLarge(t *testing.T) { + f := bloom.NewFilter(100000000, 0, 0.01, wire.BloomUpdateNone) + if len(f.MsgFilterLoad().Filter) > wire.MaxFilterLoadFilterSize { + t.Errorf("TestFilterLarge test failed: %d > %d", + len(f.MsgFilterLoad().Filter), wire.MaxFilterLoadFilterSize) + } +} + +// TestFilterLoad ensures loading and unloading of a filter pass. +func TestFilterLoad(t *testing.T) { + merkle := wire.MsgFilterLoad{} + + f := bloom.LoadFilter(&merkle) + if !f.IsLoaded() { + t.Errorf("TestFilterLoad IsLoaded test failed: want %v got %v", + true, !f.IsLoaded()) + return + } + f.Unload() + if f.IsLoaded() { + t.Errorf("TestFilterLoad IsLoaded test failed: want %v got %v", + f.IsLoaded(), false) + return + } +} + +// TestFilterInsert ensures inserting data into the filter causes that data +// to be matched and the resulting serialized MsgFilterLoad is the expected +// value. +func TestFilterInsert(t *testing.T) { + var tests = []struct { + hex string + insert bool + }{ + {"99108ad8ed9bb6274d3980bab5a85c048f0950c8", true}, + {"19108ad8ed9bb6274d3980bab5a85c048f0950c8", false}, + {"b5a2c786d9ef4658287ced5914b37a1b4aa32eee", true}, + {"b9300670b4c5366e95b2699e8b18bc75e5f729c5", true}, + } + + f := bloom.NewFilter(3, 0, 0.01, wire.BloomUpdateAll) + + for i, test := range tests { + data, err := hex.DecodeString(test.hex) + if err != nil { + t.Errorf("TestFilterInsert DecodeString failed: %v\n", err) + return + } + if test.insert { + f.Add(data) + } + + result := f.Matches(data) + if test.insert != result { + t.Errorf("TestFilterInsert Matches test #%d failure: got %v want %v\n", + i, result, test.insert) + return + } + } + + want, err := hex.DecodeString("03614e9b050000000000000001") + if err != nil { + t.Errorf("TestFilterInsert DecodeString failed: %v\n", err) + return + } + + got := bytes.NewBuffer(nil) + err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding) + if err != nil { + t.Errorf("TestFilterInsert BtcDecode failed: %v\n", err) + return + } + + if !bytes.Equal(got.Bytes(), want) { + t.Errorf("TestFilterInsert failure: got %v want %v\n", + got.Bytes(), want) + return + } +} + +// TestFilterFPRange checks that new filters made with out of range +// false positive targets result in either max or min false positive rates. +func TestFilterFPRange(t *testing.T) { + tests := []struct { + name string + hash string + want string + filter *bloom.Filter + }{ + { + name: "fprates > 1 should be clipped at 1", + hash: "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041", + want: "00000000000000000001", + filter: bloom.NewFilter(1, 0, 20.9999999769, wire.BloomUpdateAll), + }, + { + name: "fprates less than 1e-9 should be clipped at min", + hash: "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041", + want: "0566d97a91a91b0000000000000001", + filter: bloom.NewFilter(1, 0, 0, wire.BloomUpdateAll), + }, + { + name: "negative fprates should be clipped at min", + hash: "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041", + want: "0566d97a91a91b0000000000000001", + filter: bloom.NewFilter(1, 0, -1, wire.BloomUpdateAll), + }, + } + + for _, test := range tests { + // Convert test input to appropriate types. + hash, err := chainhash.NewHashFromStr(test.hash) + if err != nil { + t.Errorf("NewHashFromStr unexpected error: %v", err) + continue + } + want, err := hex.DecodeString(test.want) + if err != nil { + t.Errorf("DecodeString unexpected error: %v\n", err) + continue + } + + // Add the test hash to the bloom filter and ensure the + // filter serializes to the expected bytes. + f := test.filter + f.AddHash(hash) + got := bytes.NewBuffer(nil) + err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding) + if err != nil { + t.Errorf("BtcDecode unexpected error: %v\n", err) + continue + } + if !bytes.Equal(got.Bytes(), want) { + t.Errorf("serialized filter mismatch: got %x want %x\n", + got.Bytes(), want) + continue + } + } +} + +// TestFilterInsert ensures inserting data into the filter with a tweak causes +// that data to be matched and the resulting serialized MsgFilterLoad is the +// expected value. +func TestFilterInsertWithTweak(t *testing.T) { + var tests = []struct { + hex string + insert bool + }{ + {"99108ad8ed9bb6274d3980bab5a85c048f0950c8", true}, + {"19108ad8ed9bb6274d3980bab5a85c048f0950c8", false}, + {"b5a2c786d9ef4658287ced5914b37a1b4aa32eee", true}, + {"b9300670b4c5366e95b2699e8b18bc75e5f729c5", true}, + } + + f := bloom.NewFilter(3, 2147483649, 0.01, wire.BloomUpdateAll) + + for i, test := range tests { + data, err := hex.DecodeString(test.hex) + if err != nil { + t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err) + return + } + if test.insert { + f.Add(data) + } + + result := f.Matches(data) + if test.insert != result { + t.Errorf("TestFilterInsertWithTweak Matches test #%d failure: got %v want %v\n", + i, result, test.insert) + return + } + } + + want, err := hex.DecodeString("03ce4299050000000100008001") + if err != nil { + t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err) + return + } + got := bytes.NewBuffer(nil) + err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding) + if err != nil { + t.Errorf("TestFilterInsertWithTweak BtcDecode failed: %v\n", err) + return + } + + if !bytes.Equal(got.Bytes(), want) { + t.Errorf("TestFilterInsertWithTweak failure: got %v want %v\n", + got.Bytes(), want) + return + } +} + +// TestFilterInsertKey ensures inserting public keys and addresses works as +// expected. +func TestFilterInsertKey(t *testing.T) { + secret := "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C" + + wif, err := btcutil.DecodeWIF(secret) + if err != nil { + t.Errorf("TestFilterInsertKey DecodeWIF failed: %v", err) + return + } + + f := bloom.NewFilter(2, 0, 0.001, wire.BloomUpdateAll) + f.Add(wif.SerializePubKey()) + f.Add(btcutil.Hash160(wif.SerializePubKey())) + + want, err := hex.DecodeString("038fc16b080000000000000001") + if err != nil { + t.Errorf("TestFilterInsertWithTweak DecodeString failed: %v\n", err) + return + } + got := bytes.NewBuffer(nil) + err = f.MsgFilterLoad().BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding) + if err != nil { + t.Errorf("TestFilterInsertWithTweak BtcDecode failed: %v\n", err) + return + } + + if !bytes.Equal(got.Bytes(), want) { + t.Errorf("TestFilterInsertWithTweak failure: got %v want %v\n", + got.Bytes(), want) + return + } +} + +func TestFilterBloomMatch(t *testing.T) { + str := "01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e" + + "88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7" + + "c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d2" + + "7d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee" + + "51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5e" + + "eef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c33" + + "9ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3" + + "bc6e2754dbcff1988ac2f15de00000000001976a914a266436d296554760" + + "8b9e15d9032a7b9d64fa43188ac00000000" + strBytes, err := hex.DecodeString(str) + if err != nil { + t.Errorf("TestFilterBloomMatch DecodeString failure: %v", err) + return + } + tx, err := btcutil.NewTxFromBytes(strBytes) + if err != nil { + t.Errorf("TestFilterBloomMatch NewTxFromBytes failure: %v", err) + return + } + spendingTxBytes := []byte{0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, + 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, + 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, + 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, + 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, + 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, + 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, + 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, + 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, + 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, + 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, + 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, + 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, + 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, + 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, + 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, + 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, + 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, + 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, + 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, + 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, + 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, + 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, + 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, + 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, + 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, + 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, + 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00} + + spendingTx, err := btcutil.NewTxFromBytes(spendingTxBytes) + if err != nil { + t.Errorf("TestFilterBloomMatch NewTxFromBytes failure: %v", err) + return + } + + f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr := "b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b" + hash, err := chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err) + return + } + f.AddHash(hash) + if !f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch didn't match hash %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "6bff7fcd4f8565ef406dd5d63d4ff94f318fe82027fd4dc451b04474019f74b4" + hashBytes, err := hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err) + return + } + f.Add(hashBytes) + if !f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch didn't match hash %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "30450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065" + + "f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643" + + "ac4cb7cb3c462aced7f14711a01" + hashBytes, err = hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err) + return + } + f.Add(hashBytes) + if !f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch didn't match input signature %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95" + + "c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe" + + "76036c339" + hashBytes, err = hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err) + return + } + f.Add(hashBytes) + if !f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch didn't match input pubkey %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "04943fdd508053c75000106d3bc6e2754dbcff19" + hashBytes, err = hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err) + return + } + f.Add(hashBytes) + if !f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch didn't match output address %s", inputStr) + } + if !f.MatchTxAndUpdate(spendingTx) { + t.Errorf("TestFilterBloomMatch spendingTx didn't match output address %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "a266436d2965547608b9e15d9032a7b9d64fa431" + hashBytes, err = hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err) + return + } + f.Add(hashBytes) + if !f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch didn't match output address %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b" + hash, err = chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err) + return + } + outpoint := wire.NewOutPoint(hash, 0) + f.AddOutPoint(outpoint) + if !f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch didn't match outpoint %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "00000009e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436" + hash, err = chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err) + return + } + f.AddHash(hash) + if f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch matched hash %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "0000006d2965547608b9e15d9032a7b9d64fa431" + hashBytes, err = hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch DecodeString failed: %v\n", err) + return + } + f.Add(hashBytes) + if f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch matched address %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "90c122d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b" + hash, err = chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err) + return + } + outpoint = wire.NewOutPoint(hash, 1) + f.AddOutPoint(outpoint) + if f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch matched outpoint %s", inputStr) + } + + f = bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + inputStr = "000000d70786e899529d71dbeba91ba216982fb6ba58f3bdaab65e73b7e9260b" + hash, err = chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestFilterBloomMatch NewHashFromStr failed: %v\n", err) + return + } + outpoint = wire.NewOutPoint(hash, 0) + f.AddOutPoint(outpoint) + if f.MatchTxAndUpdate(tx) { + t.Errorf("TestFilterBloomMatch matched outpoint %s", inputStr) + } +} + +func TestFilterInsertUpdateNone(t *testing.T) { + f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateNone) + + // Add the generation pubkey + inputStr := "04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c" + + "876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a" + + "2252247d97a46a91" + inputBytes, err := hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterInsertUpdateNone DecodeString failed: %v", err) + return + } + f.Add(inputBytes) + + // Add the output address for the 4th transaction + inputStr = "b6efd80d99179f4f4ff6f4dd0a007d018c385d21" + inputBytes, err = hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterInsertUpdateNone DecodeString failed: %v", err) + return + } + f.Add(inputBytes) + + inputStr = "147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b" + hash, err := chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestFilterInsertUpdateNone NewHashFromStr failed: %v", err) + return + } + outpoint := wire.NewOutPoint(hash, 0) + + if f.MatchesOutPoint(outpoint) { + t.Errorf("TestFilterInsertUpdateNone matched outpoint %s", inputStr) + return + } + + inputStr = "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041" + hash, err = chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestFilterInsertUpdateNone NewHashFromStr failed: %v", err) + return + } + outpoint = wire.NewOutPoint(hash, 0) + + if f.MatchesOutPoint(outpoint) { + t.Errorf("TestFilterInsertUpdateNone matched outpoint %s", inputStr) + return + } +} + +func TestFilterInsertP2PubKeyOnly(t *testing.T) { + blockStr := "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc" + + "880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367" + + "117b3c30c1f8fdd0d9728776381b4d4c86041b554b85290701000000010" + + "00000000000000000000000000000000000000000000000000000000000" + + "0000ffffffff07044c86041b0136ffffffff0100f2052a0100000043410" + + "4eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c876f2" + + "c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a22522" + + "47d97a46a91ac000000000100000001bcad20a6a29827d1424f08989255" + + "120bf7f3e9e3cdaaa6bb31b0737fe048724300000000494830450220356" + + "e834b046cadc0f8ebb5a8a017b02de59c86305403dad52cd77b55af062e" + + "a10221009253cd6c119d4729b77c978e1e2aa19f5ea6e0e52b3f16e32fa" + + "608cd5bab753901ffffffff02008d380c010000001976a9142b4b8072ec" + + "bba129b6453c63e129e643207249ca88ac0065cd1d000000001976a9141" + + "b8dd13b994bcfc787b32aeadf58ccb3615cbd5488ac0000000001000000" + + "03fdacf9b3eb077412e7a968d2e4f11b9a9dee312d666187ed77ee7d26a" + + "f16cb0b000000008c493046022100ea1608e70911ca0de5af51ba57ad23" + + "b9a51db8d28f82c53563c56a05c20f5a87022100a8bdc8b4a8acc8634c6" + + "b420410150775eb7f2474f5615f7fccd65af30f310fbf01410465fdf49e" + + "29b06b9a1582287b6279014f834edc317695d125ef623c1cc3aaece245b" + + "d69fcad7508666e9c74a49dc9056d5fc14338ef38118dc4afae5fe2c585" + + "caffffffff309e1913634ecb50f3c4f83e96e70b2df071b497b8973a3e7" + + "5429df397b5af83000000004948304502202bdb79c596a9ffc24e96f438" + + "6199aba386e9bc7b6071516e2b51dda942b3a1ed022100c53a857e76b72" + + "4fc14d45311eac5019650d415c3abb5428f3aae16d8e69bec2301ffffff" + + "ff2089e33491695080c9edc18a428f7d834db5b6d372df13ce2b1b0e0cb" + + "cb1e6c10000000049483045022100d4ce67c5896ee251c810ac1ff9cecc" + + "d328b497c8f553ab6e08431e7d40bad6b5022033119c0c2b7d792d31f11" + + "87779c7bd95aefd93d90a715586d73801d9b47471c601ffffffff010071" + + "4460030000001976a914c7b55141d097ea5df7a0ed330cf794376e53ec8" + + "d88ac0000000001000000045bf0e214aa4069a3e792ecee1e1bf0c1d397" + + "cde8dd08138f4b72a00681743447000000008b48304502200c45de8c4f3" + + "e2c1821f2fc878cba97b1e6f8807d94930713aa1c86a67b9bf1e4022100" + + "8581abfef2e30f957815fc89978423746b2086375ca8ecf359c85c2a5b7" + + "c88ad01410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf64852" + + "61c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270efb1d" + + "3ae37079b794a92d7ec95ffffffffd669f7d7958d40fc59d2253d88e0f2" + + "48e29b599c80bbcec344a83dda5f9aa72c000000008a473044022078124" + + "c8beeaa825f9e0b30bff96e564dd859432f2d0cb3b72d3d5d93d38d7e93" + + "0220691d233b6c0f995be5acb03d70a7f7a65b6bc9bdd426260f38a1346" + + "669507a3601410462bb73f76ca0994fcb8b4271e6fb7561f5c0f9ca0cf6" + + "485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f4d87270e" + + "fb1d3ae37079b794a92d7ec95fffffffff878af0d93f5229a68166cf051" + + "fd372bb7a537232946e0a46f53636b4dafdaa4000000008c49304602210" + + "0c717d1714551663f69c3c5759bdbb3a0fcd3fab023abc0e522fe6440de" + + "35d8290221008d9cbe25bffc44af2b18e81c58eb37293fd7fe1c2e7b46f" + + "c37ee8c96c50ab1e201410462bb73f76ca0994fcb8b4271e6fb7561f5c0" + + "f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018ffd6238f" + + "4d87270efb1d3ae37079b794a92d7ec95ffffffff27f2b668859cd7f2f8" + + "94aa0fd2d9e60963bcd07c88973f425f999b8cbfd7a1e2000000008c493" + + "046022100e00847147cbf517bcc2f502f3ddc6d284358d102ed20d47a8a" + + "a788a62f0db780022100d17b2d6fa84dcaf1c95d88d7e7c30385aecf415" + + "588d749afd3ec81f6022cecd701410462bb73f76ca0994fcb8b4271e6fb" + + "7561f5c0f9ca0cf6485261c4a0dc894f4ab844c6cdfb97cd0b60ffb5018" + + "ffd6238f4d87270efb1d3ae37079b794a92d7ec95ffffffff0100c817a8" + + "040000001976a914b6efd80d99179f4f4ff6f4dd0a007d018c385d2188a" + + "c000000000100000001834537b2f1ce8ef9373a258e10545ce5a50b758d" + + "f616cd4356e0032554ebd3c4000000008b483045022100e68f422dd7c34" + + "fdce11eeb4509ddae38201773dd62f284e8aa9d96f85099d0b002202243" + + "bd399ff96b649a0fad05fa759d6a882f0af8c90cf7632c2840c29070aec" + + "20141045e58067e815c2f464c6a2a15f987758374203895710c2d452442" + + "e28496ff38ba8f5fd901dc20e29e88477167fe4fc299bf818fd0d9e1632" + + "d467b2a3d9503b1aaffffffff0280d7e636030000001976a914f34c3e10" + + "eb387efe872acb614c89e78bfca7815d88ac404b4c00000000001976a91" + + "4a84e272933aaf87e1715d7786c51dfaeb5b65a6f88ac00000000010000" + + "000143ac81c8e6f6ef307dfe17f3d906d999e23e0189fda838c5510d850" + + "927e03ae7000000008c4930460221009c87c344760a64cb8ae6685a3eec" + + "2c1ac1bed5b88c87de51acd0e124f266c16602210082d07c037359c3a25" + + "7b5c63ebd90f5a5edf97b2ac1c434b08ca998839f346dd40141040ba7e5" + + "21fa7946d12edbb1d1e95a15c34bd4398195e86433c92b431cd315f455f" + + "e30032ede69cad9d1e1ed6c3c4ec0dbfced53438c625462afb792dcb098" + + "544bffffffff0240420f00000000001976a9144676d1b820d63ec272f19" + + "00d59d43bc6463d96f888ac40420f00000000001976a914648d04341d00" + + "d7968b3405c034adc38d4d8fb9bd88ac00000000010000000248cc91750" + + "1ea5c55f4a8d2009c0567c40cfe037c2e71af017d0a452ff705e3f10000" + + "00008b483045022100bf5fdc86dc5f08a5d5c8e43a8c9d5b1ed8c65562e" + + "280007b52b133021acd9acc02205e325d613e555f772802bf413d36ba80" + + "7892ed1a690a77811d3033b3de226e0a01410429fa713b124484cb2bd7b" + + "5557b2c0b9df7b2b1fee61825eadc5ae6c37a9920d38bfccdc7dc3cb0c4" + + "7d7b173dbc9db8d37db0a33ae487982c59c6f8606e9d1791ffffffff41e" + + "d70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d0" + + "68000000008b4830450221008513ad65187b903aed1102d1d0c47688127" + + "658c51106753fed0151ce9c16b80902201432b9ebcb87bd04ceb2de6603" + + "5fbbaf4bf8b00d1cfe41f1a1f7338f9ad79d210141049d4cf80125bf50b" + + "e1709f718c07ad15d0fc612b7da1f5570dddc35f2a352f0f27c978b0682" + + "0edca9ef982c35fda2d255afba340068c5035552368bc7200c1488fffff" + + "fff0100093d00000000001976a9148edb68822f1ad580b043c7b3df2e40" + + "0f8699eb4888ac00000000" + blockBytes, err := hex.DecodeString(blockStr) + if err != nil { + t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err) + return + } + block, err := btcutil.NewBlockFromBytes(blockBytes) + if err != nil { + t.Errorf("TestFilterInsertP2PubKeyOnly NewBlockFromBytes failed: %v", err) + return + } + + f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateP2PubkeyOnly) + + // Generation pubkey + inputStr := "04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c" + + "876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a" + + "2252247d97a46a91" + inputBytes, err := hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err) + return + } + f.Add(inputBytes) + + // Output address of 4th transaction + inputStr = "b6efd80d99179f4f4ff6f4dd0a007d018c385d21" + inputBytes, err = hex.DecodeString(inputStr) + if err != nil { + t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err) + return + } + f.Add(inputBytes) + + // Ignore return value -- this is just used to update the filter. + _, _ = bloom.NewMerkleBlock(block, f) + + // We should match the generation pubkey + inputStr = "147caa76786596590baa4e98f5d9f48b86c7765e489f7a6ff3360fe5c674360b" + hash, err := chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestMerkleBlockP2PubKeyOnly NewHashFromStr failed: %v", err) + return + } + outpoint := wire.NewOutPoint(hash, 0) + if !f.MatchesOutPoint(outpoint) { + t.Errorf("TestMerkleBlockP2PubKeyOnly didn't match the generation "+ + "outpoint %s", inputStr) + return + } + + // We should not match the 4th transaction, which is not p2pk + inputStr = "02981fa052f0481dbc5868f4fc2166035a10f27a03cfd2de67326471df5bc041" + hash, err = chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestMerkleBlockP2PubKeyOnly NewHashFromStr failed: %v", err) + return + } + outpoint = wire.NewOutPoint(hash, 0) + if f.MatchesOutPoint(outpoint) { + t.Errorf("TestMerkleBlockP2PubKeyOnly matched outpoint %s", inputStr) + return + } +} + +func TestFilterReload(t *testing.T) { + f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + + bFilter := bloom.LoadFilter(f.MsgFilterLoad()) + if bFilter.MsgFilterLoad() == nil { + t.Errorf("TestFilterReload LoadFilter test failed") + return + } + bFilter.Reload(nil) + + if bFilter.MsgFilterLoad() != nil { + t.Errorf("TestFilterReload Reload test failed") + } +} diff --git a/btcutil/bloom/merkleblock.go b/btcutil/bloom/merkleblock.go new file mode 100644 index 0000000000..101a8f9194 --- /dev/null +++ b/btcutil/bloom/merkleblock.go @@ -0,0 +1,125 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bloom + +import ( + "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" +) + +// merkleBlock is used to house intermediate information needed to generate a +// wire.MsgMerkleBlock according to a filter. +type merkleBlock struct { + numTx uint32 + allHashes []*chainhash.Hash + finalHashes []*chainhash.Hash + matchedBits []byte + bits []byte +} + +// calcTreeWidth calculates and returns the the number of nodes (width) or a +// merkle tree at the given depth-first height. +func (m *merkleBlock) calcTreeWidth(height uint32) uint32 { + return (m.numTx + (1 << height) - 1) >> height +} + +// calcHash returns the hash for a sub-tree given a depth-first height and +// node position. +func (m *merkleBlock) calcHash(height, pos uint32) *chainhash.Hash { + if height == 0 { + return m.allHashes[pos] + } + + var right *chainhash.Hash + left := m.calcHash(height-1, pos*2) + if pos*2+1 < m.calcTreeWidth(height-1) { + right = m.calcHash(height-1, pos*2+1) + } else { + right = left + } + return blockchain.HashMerkleBranches(left, right) +} + +// traverseAndBuild builds a partial merkle tree using a recursive depth-first +// approach. As it calculates the hashes, it also saves whether or not each +// node is a parent node and a list of final hashes to be included in the +// merkle block. +func (m *merkleBlock) traverseAndBuild(height, pos uint32) { + // Determine whether this node is a parent of a matched node. + var isParent byte + for i := pos << height; i < (pos+1)< 1 { + height++ + } + + // Build the depth-first partial merkle tree. + mBlock.traverseAndBuild(height, 0) + + // Create and return the merkle block. + msgMerkleBlock := wire.MsgMerkleBlock{ + Header: block.MsgBlock().Header, + Transactions: mBlock.numTx, + Hashes: make([]*chainhash.Hash, 0, len(mBlock.finalHashes)), + Flags: make([]byte, (len(mBlock.bits)+7)/8), + } + for _, hash := range mBlock.finalHashes { + _ = msgMerkleBlock.AddTxHash(hash) + } + for i := uint32(0); i < uint32(len(mBlock.bits)); i++ { + msgMerkleBlock.Flags[i/8] |= mBlock.bits[i] << (i % 8) + } + return &msgMerkleBlock, matchedIndices +} diff --git a/btcutil/bloom/merkleblock_test.go b/btcutil/bloom/merkleblock_test.go new file mode 100644 index 0000000000..15e21a4bb7 --- /dev/null +++ b/btcutil/bloom/merkleblock_test.go @@ -0,0 +1,74 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bloom_test + +import ( + "bytes" + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/bloom" +) + +func TestMerkleBlock3(t *testing.T) { + blockStr := "0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b" + + "4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdc" + + "c96b2c3ff60abe184f196367291b4d4c86041b8fa45d630101000000010" + + "00000000000000000000000000000000000000000000000000000000000" + + "0000ffffffff08044c86041b020a02ffffffff0100f2052a01000000434" + + "104ecd3229b0571c3be876feaac0442a9f13c5a572742927af1dc623353" + + "ecf8c202225f64868137a18cdd85cbbb4c74fbccfd4f49639cf1bdc94a5" + + "672bb15ad5d4cac00000000" + blockBytes, err := hex.DecodeString(blockStr) + if err != nil { + t.Errorf("TestMerkleBlock3 DecodeString failed: %v", err) + return + } + blk, err := btcutil.NewBlockFromBytes(blockBytes) + if err != nil { + t.Errorf("TestMerkleBlock3 NewBlockFromBytes failed: %v", err) + return + } + + f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll) + + inputStr := "63194f18be0af63f2c6bc9dc0f777cbefed3d9415c4af83f3ee3a3d669c00cb5" + hash, err := chainhash.NewHashFromStr(inputStr) + if err != nil { + t.Errorf("TestMerkleBlock3 NewHashFromStr failed: %v", err) + return + } + + f.AddHash(hash) + + mBlock, _ := bloom.NewMerkleBlock(blk, f) + + wantStr := "0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4" + + "b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc" + + "96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50c" + + "c069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196" + + "30101" + want, err := hex.DecodeString(wantStr) + if err != nil { + t.Errorf("TestMerkleBlock3 DecodeString failed: %v", err) + return + } + + got := bytes.NewBuffer(nil) + err = mBlock.BtcEncode(got, wire.ProtocolVersion, wire.LatestEncoding) + if err != nil { + t.Errorf("TestMerkleBlock3 BtcEncode failed: %v", err) + return + } + + if !bytes.Equal(want, got.Bytes()) { + t.Errorf("TestMerkleBlock3 failed merkle block comparison: "+ + "got %v want %v", got.Bytes(), want) + return + } +} diff --git a/btcutil/bloom/murmurhash3.go b/btcutil/bloom/murmurhash3.go new file mode 100644 index 0000000000..6bb562ecba --- /dev/null +++ b/btcutil/bloom/murmurhash3.go @@ -0,0 +1,72 @@ +// Copyright (c) 2013, 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bloom + +import ( + "encoding/binary" +) + +// The following constants are used by the MurmurHash3 algorithm. +const ( + murmurC1 = 0xcc9e2d51 + murmurC2 = 0x1b873593 + murmurR1 = 15 + murmurR2 = 13 + murmurM = 5 + murmurN = 0xe6546b64 +) + +// MurmurHash3 implements a non-cryptographic hash function using the +// MurmurHash3 algorithm. This implementation yields a 32-bit hash value which +// is suitable for general hash-based lookups. The seed can be used to +// effectively randomize the hash function. This makes it ideal for use in +// bloom filters which need multiple independent hash functions. +func MurmurHash3(seed uint32, data []byte) uint32 { + dataLen := uint32(len(data)) + hash := seed + k := uint32(0) + numBlocks := dataLen / 4 + + // Calculate the hash in 4-byte chunks. + for i := uint32(0); i < numBlocks; i++ { + k = binary.LittleEndian.Uint32(data[i*4:]) + k *= murmurC1 + k = (k << murmurR1) | (k >> (32 - murmurR1)) + k *= murmurC2 + + hash ^= k + hash = (hash << murmurR2) | (hash >> (32 - murmurR2)) + hash = hash*murmurM + murmurN + } + + // Handle remaining bytes. + tailIdx := numBlocks * 4 + k = 0 + + switch dataLen & 3 { + case 3: + k ^= uint32(data[tailIdx+2]) << 16 + fallthrough + case 2: + k ^= uint32(data[tailIdx+1]) << 8 + fallthrough + case 1: + k ^= uint32(data[tailIdx]) + k *= murmurC1 + k = (k << murmurR1) | (k >> (32 - murmurR1)) + k *= murmurC2 + hash ^= k + } + + // Finalization. + hash ^= dataLen + hash ^= hash >> 16 + hash *= 0x85ebca6b + hash ^= hash >> 13 + hash *= 0xc2b2ae35 + hash ^= hash >> 16 + + return hash +} diff --git a/btcutil/bloom/murmurhash3_test.go b/btcutil/bloom/murmurhash3_test.go new file mode 100644 index 0000000000..9c102d5f8c --- /dev/null +++ b/btcutil/bloom/murmurhash3_test.go @@ -0,0 +1,45 @@ +// Copyright (c) 2013, 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package bloom_test + +import ( + "testing" + + "github.com/btcsuite/btcd/btcutil/bloom" +) + +// TestMurmurHash3 ensure the MurmurHash3 function produces the correct hash +// when given various seeds and data. +func TestMurmurHash3(t *testing.T) { + var tests = []struct { + seed uint32 + data []byte + out uint32 + }{ + {0x00000000, []byte{}, 0x00000000}, + {0xfba4c795, []byte{}, 0x6a396f08}, + {0xffffffff, []byte{}, 0x81f16f39}, + {0x00000000, []byte{0x00}, 0x514e28b7}, + {0xfba4c795, []byte{0x00}, 0xea3f0b17}, + {0x00000000, []byte{0xff}, 0xfd6cf10d}, + {0x00000000, []byte{0x00, 0x11}, 0x16c6b7ab}, + {0x00000000, []byte{0x00, 0x11, 0x22}, 0x8eb51c3d}, + {0x00000000, []byte{0x00, 0x11, 0x22, 0x33}, 0xb4471bf8}, + {0x00000000, []byte{0x00, 0x11, 0x22, 0x33, 0x44}, 0xe2301fa8}, + {0x00000000, []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, 0xfc2e4a15}, + {0x00000000, []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66}, 0xb074502c}, + {0x00000000, []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}, 0x8034d2a0}, + {0x00000000, []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, 0xb4698def}, + } + + for i, test := range tests { + result := bloom.MurmurHash3(test.seed, test.data) + if result != test.out { + t.Errorf("MurmurHash3 test #%d failed: got %v want %v\n", + i, result, test.out) + continue + } + } +} diff --git a/btcutil/bloom/test_coverage.txt b/btcutil/bloom/test_coverage.txt new file mode 100644 index 0000000000..e503f26feb --- /dev/null +++ b/btcutil/bloom/test_coverage.txt @@ -0,0 +1,28 @@ + +github.com/conformal/btcutil/bloom/murmurhash3.go MurmurHash3 100.00% (31/31) +github.com/conformal/btcutil/bloom/merkleblock.go NewMerkleBlock 100.00% (19/19) +github.com/conformal/btcutil/bloom/merkleblock.go merkleBlock.traverseAndBuild 100.00% (10/10) +github.com/conformal/btcutil/bloom/merkleblock.go merkleBlock.calcHash 100.00% (8/8) +github.com/conformal/btcutil/bloom/filter.go Filter.maybeAddOutpoint 100.00% (7/7) +github.com/conformal/btcutil/bloom/filter.go Filter.addOutPoint 100.00% (4/4) +github.com/conformal/btcutil/bloom/filter.go Filter.IsLoaded 100.00% (4/4) +github.com/conformal/btcutil/bloom/filter.go Filter.MsgFilterLoad 100.00% (4/4) +github.com/conformal/btcutil/bloom/filter.go Filter.matchesOutPoint 100.00% (4/4) +github.com/conformal/btcutil/bloom/filter.go Filter.MatchesOutPoint 100.00% (4/4) +github.com/conformal/btcutil/bloom/filter.go Filter.MatchTxAndUpdate 100.00% (4/4) +github.com/conformal/btcutil/bloom/filter.go Filter.Matches 100.00% (4/4) +github.com/conformal/btcutil/bloom/filter.go Filter.Add 100.00% (3/3) +github.com/conformal/btcutil/bloom/filter.go Filter.Reload 100.00% (3/3) +github.com/conformal/btcutil/bloom/filter.go Filter.Unload 100.00% (3/3) +github.com/conformal/btcutil/bloom/filter.go Filter.AddShaHash 100.00% (3/3) +github.com/conformal/btcutil/bloom/filter.go Filter.AddOutPoint 100.00% (3/3) +github.com/conformal/btcutil/bloom/filter.go minUint32 100.00% (3/3) +github.com/conformal/btcutil/bloom/filter.go Filter.hash 100.00% (2/2) +github.com/conformal/btcutil/bloom/merkleblock.go merkleBlock.calcTreeWidth 100.00% (1/1) +github.com/conformal/btcutil/bloom/filter.go LoadFilter 100.00% (1/1) +github.com/conformal/btcutil/bloom/filter.go Filter.matchTxAndUpdate 91.30% (21/23) +github.com/conformal/btcutil/bloom/filter.go Filter.matches 85.71% (6/7) +github.com/conformal/btcutil/bloom/filter.go NewFilter 81.82% (9/11) +github.com/conformal/btcutil/bloom/filter.go Filter.add 80.00% (4/5) +github.com/conformal/btcutil/bloom ---------------------------- 96.49% (165/171) + diff --git a/btcutil/certgen.go b/btcutil/certgen.go new file mode 100644 index 0000000000..52e2d9cc95 --- /dev/null +++ b/btcutil/certgen.go @@ -0,0 +1,144 @@ +// Copyright (c) 2013-2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + _ "crypto/sha512" // Needed for RegisterHash in init + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "fmt" + "math/big" + "net" + "os" + "time" +) + +// NewTLSCertPair returns a new PEM-encoded x.509 certificate pair +// based on a 521-bit ECDSA private key. The machine's local interface +// addresses and all variants of IPv4 and IPv6 localhost are included as +// valid IP addresses. +func NewTLSCertPair(organization string, validUntil time.Time, extraHosts []string) (cert, key []byte, err error) { + now := time.Now() + if validUntil.Before(now) { + return nil, nil, errors.New("validUntil would create an already-expired certificate") + } + + priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) + if err != nil { + return nil, nil, err + } + + // end of ASN.1 time + endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC) + if validUntil.After(endOfTime) { + validUntil = endOfTime + } + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return nil, nil, fmt.Errorf("failed to generate serial number: %s", err) + } + + host, err := os.Hostname() + if err != nil { + return nil, nil, err + } + + ipAddresses := []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")} + dnsNames := []string{host} + if host != "localhost" { + dnsNames = append(dnsNames, "localhost") + } + + addIP := func(ipAddr net.IP) { + for _, ip := range ipAddresses { + if ip.Equal(ipAddr) { + return + } + } + ipAddresses = append(ipAddresses, ipAddr) + } + addHost := func(host string) { + for _, dnsName := range dnsNames { + if host == dnsName { + return + } + } + dnsNames = append(dnsNames, host) + } + + addrs, err := interfaceAddrs() + if err != nil { + return nil, nil, err + } + for _, a := range addrs { + ipAddr, _, err := net.ParseCIDR(a.String()) + if err == nil { + addIP(ipAddr) + } + } + + for _, hostStr := range extraHosts { + host, _, err := net.SplitHostPort(hostStr) + if err != nil { + host = hostStr + } + if ip := net.ParseIP(host); ip != nil { + addIP(ip) + } else { + addHost(host) + } + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{organization}, + CommonName: host, + }, + NotBefore: now.Add(-time.Hour * 24), + NotAfter: validUntil, + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | + x509.KeyUsageCertSign, + IsCA: true, // so can sign self. + BasicConstraintsValid: true, + + DNSNames: dnsNames, + IPAddresses: ipAddresses, + } + + derBytes, err := x509.CreateCertificate(rand.Reader, &template, + &template, &priv.PublicKey, priv) + if err != nil { + return nil, nil, fmt.Errorf("failed to create certificate: %v", err) + } + + certBuf := &bytes.Buffer{} + err = pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + if err != nil { + return nil, nil, fmt.Errorf("failed to encode certificate: %v", err) + } + + keybytes, err := x509.MarshalECPrivateKey(priv) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal private key: %v", err) + } + + keyBuf := &bytes.Buffer{} + err = pem.Encode(keyBuf, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keybytes}) + if err != nil { + return nil, nil, fmt.Errorf("failed to encode private key: %v", err) + } + + return certBuf.Bytes(), keyBuf.Bytes(), nil +} diff --git a/btcutil/certgen_test.go b/btcutil/certgen_test.go new file mode 100644 index 0000000000..81aeea5d6a --- /dev/null +++ b/btcutil/certgen_test.go @@ -0,0 +1,123 @@ +// Copyright (c) 2013-2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil_test + +import ( + "crypto/x509" + "encoding/pem" + "net" + "testing" + "time" + + "github.com/btcsuite/btcd/btcutil" + //"github.com/davecgh/go-spew/spew" +) + +// TestNewTLSCertPair ensures the NewTLSCertPair function works as expected. +func TestNewTLSCertPair(t *testing.T) { + // Certs don't support sub-second precision, so truncate it now to + // ensure the checks later don't fail due to nanosecond precision + // differences. + validUntil := time.Unix(time.Now().Add(10*365*24*time.Hour).Unix(), 0) + org := "test autogenerated cert" + extraHosts := []string{"testtlscert.bogus", "localhost", "127.0.0.1"} + cert, key, err := btcutil.NewTLSCertPair(org, validUntil, extraHosts) + if err != nil { + t.Fatalf("failed with unexpected error: %v", err) + } + + // Ensure the PEM-encoded cert that is returned can be decoded. + pemCert, _ := pem.Decode(cert) + if pemCert == nil { + t.Fatalf("pem.Decode was unable to decode the certificate") + } + + // Ensure the PEM-encoded key that is returned can be decoded. + pemKey, _ := pem.Decode(key) + if pemCert == nil { + t.Fatalf("pem.Decode was unable to decode the key") + } + + // Ensure the DER-encoded key bytes can be successfully parsed. + _, err = x509.ParseECPrivateKey(pemKey.Bytes) + if err != nil { + t.Fatalf("failed with unexpected error: %v", err) + } + + // Ensure the DER-encoded cert bytes can be successfully into an X.509 + // certificate. + x509Cert, err := x509.ParseCertificate(pemCert.Bytes) + if err != nil { + t.Fatalf("failed with unexpected error: %v", err) + } + + // Ensure the specified organization is correct. + x509Orgs := x509Cert.Subject.Organization + if len(x509Orgs) == 0 || x509Orgs[0] != org { + x509Org := "" + if len(x509Orgs) > 0 { + x509Org = x509Orgs[0] + } + t.Fatalf("generated cert organization field mismatch, got "+ + "'%v', want '%v'", x509Org, org) + } + + // Ensure the specified valid until value is correct. + if !x509Cert.NotAfter.Equal(validUntil) { + t.Fatalf("generated cert valid until field mismatch, got %v, "+ + "want %v", x509Cert.NotAfter, validUntil) + } + + // Ensure the specified extra hosts are present. + for _, host := range extraHosts { + if err := x509Cert.VerifyHostname(host); err != nil { + t.Fatalf("failed to verify extra host '%s'", host) + } + } + + // Ensure that the Common Name is also the first SAN DNS name. + cn := x509Cert.Subject.CommonName + san0 := x509Cert.DNSNames[0] + if cn != san0 { + t.Errorf("common name %s does not match first SAN %s", cn, san0) + } + + // Ensure there are no duplicate hosts or IPs. + hostCounts := make(map[string]int) + for _, host := range x509Cert.DNSNames { + hostCounts[host]++ + } + ipCounts := make(map[string]int) + for _, ip := range x509Cert.IPAddresses { + ipCounts[string(ip)]++ + } + for host, count := range hostCounts { + if count != 1 { + t.Errorf("host %s appears %d times in certificate", host, count) + } + } + for ipStr, count := range ipCounts { + if count != 1 { + t.Errorf("ip %s appears %d times in certificate", net.IP(ipStr), count) + } + } + + // Ensure the cert can be use for the intended purposes. + if !x509Cert.IsCA { + t.Fatal("generated cert is not a certificate authority") + } + if x509Cert.KeyUsage&x509.KeyUsageKeyEncipherment == 0 { + t.Fatal("generated cert can't be used for key encipherment") + } + if x509Cert.KeyUsage&x509.KeyUsageDigitalSignature == 0 { + t.Fatal("generated cert can't be used for digital signatures") + } + if x509Cert.KeyUsage&x509.KeyUsageCertSign == 0 { + t.Fatal("generated cert can't be used for signing other certs") + } + if !x509Cert.BasicConstraintsValid { + t.Fatal("generated cert does not have valid basic constraints") + } +} diff --git a/btcutil/coinset/README.md b/btcutil/coinset/README.md new file mode 100644 index 0000000000..4fc239ad5e --- /dev/null +++ b/btcutil/coinset/README.md @@ -0,0 +1,71 @@ +coinset +======= + +[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)](https://travis-ci.org/btcsuite/btcutil) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/btcutil/coinset) + +Package coinset provides bitcoin-specific convenience functions for selecting +from and managing sets of unspent transaction outpoints (UTXOs). + +A comprehensive suite of tests is provided to ensure proper functionality. See +`test_coverage.txt` for the gocov coverage report. Alternatively, if you are +running a POSIX OS, you can run the `cov_report.sh` script for a real-time +report. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil/coinset +``` + +## Usage + +Each unspent transaction outpoint is represented by the Coin interface. An +example of a concrete type that implements Coin is coinset.SimpleCoin. + +The typical use case for this library is for creating raw bitcoin transactions +given a set of Coins that may be spent by the user, for example as below: + +```Go +var unspentCoins = []coinset.Coin{ ... } +``` + +When the user needs to spend a certain amount, they will need to select a +subset of these coins which contain at least that value. CoinSelector is +an interface that represents types that implement coin selection algos, +subject to various criteria. There are a few examples of CoinSelector's: + +- MinIndexCoinSelector + +- MinNumberCoinSelector + +- MaxValueAgeCoinSelector + +- MinPriorityCoinSelector + +For example, if the user wishes to maximize the probability that their +transaction is mined quickly, they could use the MaxValueAgeCoinSelector to +select high priority coins, then also attach a relatively high fee. + +```Go +selector := &coinset.MaxValueAgeCoinSelector{ + MaxInputs: 10, + MinAmountChange: 10000, +} +selectedCoins, err := selector.CoinSelect(targetAmount + bigFee, unspentCoins) +if err != nil { + return err +} +msgTx := coinset.NewMsgTxWithInputCoins(selectedCoins) +... + +``` + +The user can then create the msgTx.TxOut's as required, then sign the +transaction and transmit it to the network. + +## License + +Package coinset is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/coinset/coins.go b/btcutil/coinset/coins.go new file mode 100644 index 0000000000..9d813418b6 --- /dev/null +++ b/btcutil/coinset/coins.go @@ -0,0 +1,396 @@ +// Copyright (c) 2014-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package coinset + +import ( + "container/list" + "errors" + "sort" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" +) + +// Coin represents a spendable transaction outpoint +type Coin interface { + Hash() *chainhash.Hash + Index() uint32 + Value() btcutil.Amount + PkScript() []byte + NumConfs() int64 + ValueAge() int64 +} + +// Coins represents a set of Coins +type Coins interface { + Coins() []Coin +} + +// CoinSet is a utility struct for the modifications of a set of +// Coins that implements the Coins interface. To create a CoinSet, +// you must call NewCoinSet with nil for an empty set or a slice of +// coins as the initial contents. +// +// It is important to note that the all the Coins being added or removed +// from a CoinSet must have a constant ValueAge() during the use of +// the CoinSet, otherwise the cached values will be incorrect. +type CoinSet struct { + coinList *list.List + totalValue btcutil.Amount + totalValueAge int64 +} + +// Ensure that CoinSet is a Coins +var _ Coins = NewCoinSet(nil) + +// NewCoinSet creates a CoinSet containing the coins provided. +// To create an empty CoinSet, you may pass null as the coins input parameter. +func NewCoinSet(coins []Coin) *CoinSet { + newCoinSet := &CoinSet{ + coinList: list.New(), + totalValue: 0, + totalValueAge: 0, + } + for _, coin := range coins { + newCoinSet.PushCoin(coin) + } + return newCoinSet +} + +// Coins returns a new slice of the coins contained in the set. +func (cs *CoinSet) Coins() []Coin { + coins := make([]Coin, cs.coinList.Len()) + for i, e := 0, cs.coinList.Front(); e != nil; i, e = i+1, e.Next() { + coins[i] = e.Value.(Coin) + } + return coins +} + +// TotalValue returns the total value of the coins in the set. +func (cs *CoinSet) TotalValue() (value btcutil.Amount) { + return cs.totalValue +} + +// TotalValueAge returns the total value * number of confirmations +// of the coins in the set. +func (cs *CoinSet) TotalValueAge() (valueAge int64) { + return cs.totalValueAge +} + +// Num returns the number of coins in the set +func (cs *CoinSet) Num() int { + return cs.coinList.Len() +} + +// PushCoin adds a coin to the end of the list and updates +// the cached value amounts. +func (cs *CoinSet) PushCoin(c Coin) { + cs.coinList.PushBack(c) + cs.totalValue += c.Value() + cs.totalValueAge += c.ValueAge() +} + +// PopCoin removes the last coin on the list and returns it. +func (cs *CoinSet) PopCoin() Coin { + back := cs.coinList.Back() + if back == nil { + return nil + } + return cs.removeElement(back) +} + +// ShiftCoin removes the first coin on the list and returns it. +func (cs *CoinSet) ShiftCoin() Coin { + front := cs.coinList.Front() + if front == nil { + return nil + } + return cs.removeElement(front) +} + +// removeElement updates the cached value amounts in the CoinSet, +// removes the element from the list, then returns the Coin that +// was removed to the caller. +func (cs *CoinSet) removeElement(e *list.Element) Coin { + c := e.Value.(Coin) + cs.coinList.Remove(e) + cs.totalValue -= c.Value() + cs.totalValueAge -= c.ValueAge() + return c +} + +// NewMsgTxWithInputCoins takes the coins in the CoinSet and makes them +// the inputs to a new wire.MsgTx which is returned. +func NewMsgTxWithInputCoins(txVersion int32, inputCoins Coins) *wire.MsgTx { + msgTx := wire.NewMsgTx(txVersion) + coins := inputCoins.Coins() + msgTx.TxIn = make([]*wire.TxIn, len(coins)) + for i, coin := range coins { + msgTx.TxIn[i] = &wire.TxIn{ + PreviousOutPoint: wire.OutPoint{ + Hash: *coin.Hash(), + Index: coin.Index(), + }, + SignatureScript: nil, + Sequence: wire.MaxTxInSequenceNum, + } + } + return msgTx +} + +var ( + // ErrCoinsNoSelectionAvailable is returned when a CoinSelector believes there is no + // possible combination of coins which can meet the requirements provided to the selector. + ErrCoinsNoSelectionAvailable = errors.New("no coin selection possible") +) + +// satisfiesTargetValue checks that the totalValue is either exactly the targetValue +// or is greater than the targetValue by at least the minChange amount. +func satisfiesTargetValue(targetValue, minChange, totalValue btcutil.Amount) bool { + return (totalValue == targetValue || totalValue >= targetValue+minChange) +} + +// CoinSelector is an interface that wraps the CoinSelect method. +// +// CoinSelect will attempt to select a subset of the coins which has at +// least the targetValue amount. CoinSelect is not guaranteed to return a +// selection of coins even if the total value of coins given is greater +// than the target value. +// +// The exact choice of coins in the subset will be implementation specific. +// +// It is important to note that the Coins being used as inputs need to have +// a constant ValueAge() during the execution of CoinSelect. +type CoinSelector interface { + CoinSelect(targetValue btcutil.Amount, coins []Coin) (Coins, error) +} + +// MinIndexCoinSelector is a CoinSelector that attempts to construct a +// selection of coins whose total value is at least targetValue and prefers +// any number of lower indexes (as in the ordered array) over higher ones. +type MinIndexCoinSelector struct { + MaxInputs int + MinChangeAmount btcutil.Amount +} + +// CoinSelect will attempt to select coins using the algorithm described +// in the MinIndexCoinSelector struct. +func (s MinIndexCoinSelector) CoinSelect(targetValue btcutil.Amount, coins []Coin) (Coins, error) { + cs := NewCoinSet(nil) + for n := 0; n < len(coins) && n < s.MaxInputs; n++ { + cs.PushCoin(coins[n]) + if satisfiesTargetValue(targetValue, s.MinChangeAmount, cs.TotalValue()) { + return cs, nil + } + } + return nil, ErrCoinsNoSelectionAvailable +} + +// MinNumberCoinSelector is a CoinSelector that attempts to construct +// a selection of coins whose total value is at least targetValue +// that uses as few of the inputs as possible. +type MinNumberCoinSelector struct { + MaxInputs int + MinChangeAmount btcutil.Amount +} + +// CoinSelect will attempt to select coins using the algorithm described +// in the MinNumberCoinSelector struct. +func (s MinNumberCoinSelector) CoinSelect(targetValue btcutil.Amount, coins []Coin) (Coins, error) { + sortedCoins := make([]Coin, 0, len(coins)) + sortedCoins = append(sortedCoins, coins...) + sort.Sort(sort.Reverse(byAmount(sortedCoins))) + + return MinIndexCoinSelector(s).CoinSelect(targetValue, sortedCoins) +} + +// MaxValueAgeCoinSelector is a CoinSelector that attempts to construct +// a selection of coins whose total value is at least targetValue +// that has as much input value-age as possible. +// +// This would be useful in the case where you want to maximize +// likelihood of the inclusion of your transaction in the next mined +// block. +type MaxValueAgeCoinSelector struct { + MaxInputs int + MinChangeAmount btcutil.Amount +} + +// CoinSelect will attempt to select coins using the algorithm described +// in the MaxValueAgeCoinSelector struct. +func (s MaxValueAgeCoinSelector) CoinSelect(targetValue btcutil.Amount, coins []Coin) (Coins, error) { + sortedCoins := make([]Coin, 0, len(coins)) + sortedCoins = append(sortedCoins, coins...) + sort.Sort(sort.Reverse(byValueAge(sortedCoins))) + + return MinIndexCoinSelector(s).CoinSelect(targetValue, sortedCoins) +} + +// MinPriorityCoinSelector is a CoinSelector that attempts to construct +// a selection of coins whose total value is at least targetValue and +// whose average value-age per input is greater than MinAvgValueAgePerInput. +// If there is change, it must exceed MinChangeAmount to be a valid selection. +// +// When possible, MinPriorityCoinSelector will attempt to reduce the average +// input priority over the threshold, but no guarantees will be made as to +// minimality of the selection. The selection below is almost certainly +// suboptimal. +// +type MinPriorityCoinSelector struct { + MaxInputs int + MinChangeAmount btcutil.Amount + MinAvgValueAgePerInput int64 +} + +// CoinSelect will attempt to select coins using the algorithm described +// in the MinPriorityCoinSelector struct. +func (s MinPriorityCoinSelector) CoinSelect(targetValue btcutil.Amount, coins []Coin) (Coins, error) { + possibleCoins := make([]Coin, 0, len(coins)) + possibleCoins = append(possibleCoins, coins...) + + sort.Sort(byValueAge(possibleCoins)) + + // find the first coin with sufficient valueAge + cutoffIndex := -1 + for i := 0; i < len(possibleCoins); i++ { + if possibleCoins[i].ValueAge() >= s.MinAvgValueAgePerInput { + cutoffIndex = i + break + } + } + if cutoffIndex < 0 { + return nil, ErrCoinsNoSelectionAvailable + } + + // create sets of input coins that will obey minimum average valueAge + for i := cutoffIndex; i < len(possibleCoins); i++ { + possibleHighCoins := possibleCoins[cutoffIndex : i+1] + + // choose a set of high-enough valueAge coins + highSelect, err := (&MinNumberCoinSelector{ + MaxInputs: s.MaxInputs, + MinChangeAmount: s.MinChangeAmount, + }).CoinSelect(targetValue, possibleHighCoins) + + if err != nil { + // attempt to add available low priority to make a solution + + for numLow := 1; numLow <= cutoffIndex && numLow+(i-cutoffIndex) <= s.MaxInputs; numLow++ { + allHigh := NewCoinSet(possibleCoins[cutoffIndex : i+1]) + newTargetValue := targetValue - allHigh.TotalValue() + newMaxInputs := allHigh.Num() + numLow + if newMaxInputs > numLow { + newMaxInputs = numLow + } + newMinAvgValueAge := ((s.MinAvgValueAgePerInput * int64(allHigh.Num()+numLow)) - allHigh.TotalValueAge()) / int64(numLow) + + // find the minimum priority that can be added to set + lowSelect, err := (&MinPriorityCoinSelector{ + MaxInputs: newMaxInputs, + MinChangeAmount: s.MinChangeAmount, + MinAvgValueAgePerInput: newMinAvgValueAge, + }).CoinSelect(newTargetValue, possibleCoins[0:cutoffIndex]) + + if err != nil { + continue + } + + for _, coin := range lowSelect.Coins() { + allHigh.PushCoin(coin) + } + + return allHigh, nil + } + // oh well, couldn't fix, try to add more high priority to the set. + } else { + extendedCoins := NewCoinSet(highSelect.Coins()) + + // attempt to lower priority towards target with lowest ones first + for n := 0; n < cutoffIndex; n++ { + if extendedCoins.Num() >= s.MaxInputs { + break + } + if possibleCoins[n].ValueAge() == 0 { + continue + } + + extendedCoins.PushCoin(possibleCoins[n]) + if extendedCoins.TotalValueAge()/int64(extendedCoins.Num()) < s.MinAvgValueAgePerInput { + extendedCoins.PopCoin() + continue + } + } + return extendedCoins, nil + } + } + + return nil, ErrCoinsNoSelectionAvailable +} + +type byValueAge []Coin + +func (a byValueAge) Len() int { return len(a) } +func (a byValueAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byValueAge) Less(i, j int) bool { return a[i].ValueAge() < a[j].ValueAge() } + +type byAmount []Coin + +func (a byAmount) Len() int { return len(a) } +func (a byAmount) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a byAmount) Less(i, j int) bool { return a[i].Value() < a[j].Value() } + +// SimpleCoin defines a concrete instance of Coin that is backed by a +// btcutil.Tx, a specific outpoint index, and the number of confirmations +// that transaction has had. +type SimpleCoin struct { + Tx *btcutil.Tx + TxIndex uint32 + TxNumConfs int64 +} + +// Ensure that SimpleCoin is a Coin +var _ Coin = &SimpleCoin{} + +// Hash returns the hash value of the transaction on which the Coin is an output +func (c *SimpleCoin) Hash() *chainhash.Hash { + return c.Tx.Hash() +} + +// Index returns the index of the output on the transaction which the Coin represents +func (c *SimpleCoin) Index() uint32 { + return c.TxIndex +} + +// txOut returns the TxOut of the transaction the Coin represents +func (c *SimpleCoin) txOut() *wire.TxOut { + return c.Tx.MsgTx().TxOut[c.TxIndex] +} + +// Value returns the value of the Coin +func (c *SimpleCoin) Value() btcutil.Amount { + return btcutil.Amount(c.txOut().Value) +} + +// PkScript returns the outpoint script of the Coin. +// +// This can be used to determine what type of script the Coin uses +// and extract standard addresses if possible using +// txscript.ExtractPkScriptAddrs for example. +func (c *SimpleCoin) PkScript() []byte { + return c.txOut().PkScript +} + +// NumConfs returns the number of confirmations that the transaction the Coin references +// has had. +func (c *SimpleCoin) NumConfs() int64 { + return c.TxNumConfs +} + +// ValueAge returns the product of the value and the number of confirmations. This is +// used as an input to calculate the priority of the transaction. +func (c *SimpleCoin) ValueAge() int64 { + return c.TxNumConfs * int64(c.Value()) +} diff --git a/btcutil/coinset/coins_test.go b/btcutil/coinset/coins_test.go new file mode 100644 index 0000000000..874dc6c6d6 --- /dev/null +++ b/btcutil/coinset/coins_test.go @@ -0,0 +1,260 @@ +// Copyright (c) 2014-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package coinset_test + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "fmt" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/coinset" +) + +type TestCoin struct { + TxHash *chainhash.Hash + TxIndex uint32 + TxValue btcutil.Amount + TxNumConfs int64 +} + +func (c *TestCoin) Hash() *chainhash.Hash { return c.TxHash } +func (c *TestCoin) Index() uint32 { return c.TxIndex } +func (c *TestCoin) Value() btcutil.Amount { return c.TxValue } +func (c *TestCoin) PkScript() []byte { return nil } +func (c *TestCoin) NumConfs() int64 { return c.TxNumConfs } +func (c *TestCoin) ValueAge() int64 { return int64(c.TxValue) * c.TxNumConfs } + +func NewCoin(index int64, value btcutil.Amount, numConfs int64) coinset.Coin { + h := sha256.New() + _, _ = h.Write([]byte(fmt.Sprintf("%d", index))) + hash, _ := chainhash.NewHash(h.Sum(nil)) + c := &TestCoin{ + TxHash: hash, + TxIndex: 0, + TxValue: value, + TxNumConfs: numConfs, + } + return coinset.Coin(c) +} + +type coinSelectTest struct { + selector coinset.CoinSelector + inputCoins []coinset.Coin + targetValue btcutil.Amount + expectedCoins []coinset.Coin + expectedError error +} + +func testCoinSelector(tests []coinSelectTest, t *testing.T) { + for testIndex, test := range tests { + cs, err := test.selector.CoinSelect(test.targetValue, test.inputCoins) + if err != test.expectedError { + t.Errorf("[%d] expected a different error: got=%v, expected=%v", testIndex, err, test.expectedError) + continue + } + if test.expectedCoins != nil { + if cs == nil { + t.Errorf("[%d] expected non-nil coinset", testIndex) + continue + } + coins := cs.Coins() + if len(coins) != len(test.expectedCoins) { + t.Errorf("[%d] expected different number of coins: got=%d, expected=%d", testIndex, len(coins), len(test.expectedCoins)) + continue + } + for n := 0; n < len(test.expectedCoins); n++ { + if coins[n] != test.expectedCoins[n] { + t.Errorf("[%d] expected different coins at coin index %d: got=%#v, expected=%#v", testIndex, n, coins[n], test.expectedCoins[n]) + continue + } + } + coinSet := coinset.NewCoinSet(coins) + if coinSet.TotalValue() < test.targetValue { + t.Errorf("[%d] targetValue not satistifed", testIndex) + continue + } + } + } +} + +var coins = []coinset.Coin{ + NewCoin(1, 100000000, 1), + NewCoin(2, 10000000, 20), + NewCoin(3, 50000000, 0), + NewCoin(4, 25000000, 6), +} + +func TestCoinSet(t *testing.T) { + cs := coinset.NewCoinSet(nil) + if cs.PopCoin() != nil { + t.Error("Expected popCoin of empty to be nil") + } + if cs.ShiftCoin() != nil { + t.Error("Expected shiftCoin of empty to be nil") + } + + cs.PushCoin(coins[0]) + cs.PushCoin(coins[1]) + cs.PushCoin(coins[2]) + if cs.PopCoin() != coins[2] { + t.Error("Expected third coin") + } + if cs.ShiftCoin() != coins[0] { + t.Error("Expected first coin") + } + + mtx := coinset.NewMsgTxWithInputCoins(wire.TxVersion, cs) + if len(mtx.TxIn) != 1 { + t.Errorf("Expected only 1 TxIn, got %d", len(mtx.TxIn)) + } + op := mtx.TxIn[0].PreviousOutPoint + if !op.Hash.IsEqual(coins[1].Hash()) || op.Index != coins[1].Index() { + t.Errorf("Expected the second coin to be added as input to mtx") + } +} + +var minIndexSelectors = []coinset.MinIndexCoinSelector{ + {MaxInputs: 10, MinChangeAmount: 10000}, + {MaxInputs: 2, MinChangeAmount: 10000}, +} + +var minIndexTests = []coinSelectTest{ + {minIndexSelectors[0], coins, coins[0].Value() - minIndexSelectors[0].MinChangeAmount, []coinset.Coin{coins[0]}, nil}, + {minIndexSelectors[0], coins, coins[0].Value() - minIndexSelectors[0].MinChangeAmount + 1, []coinset.Coin{coins[0], coins[1]}, nil}, + {minIndexSelectors[0], coins, 100000000, []coinset.Coin{coins[0]}, nil}, + {minIndexSelectors[0], coins, 110000000, []coinset.Coin{coins[0], coins[1]}, nil}, + {minIndexSelectors[0], coins, 140000000, []coinset.Coin{coins[0], coins[1], coins[2]}, nil}, + {minIndexSelectors[0], coins, 200000000, nil, coinset.ErrCoinsNoSelectionAvailable}, + {minIndexSelectors[1], coins, 10000000, []coinset.Coin{coins[0]}, nil}, + {minIndexSelectors[1], coins, 110000000, []coinset.Coin{coins[0], coins[1]}, nil}, + {minIndexSelectors[1], coins, 140000000, nil, coinset.ErrCoinsNoSelectionAvailable}, +} + +func TestMinIndexSelector(t *testing.T) { + testCoinSelector(minIndexTests, t) +} + +var minNumberSelectors = []coinset.MinNumberCoinSelector{ + {MaxInputs: 10, MinChangeAmount: 10000}, + {MaxInputs: 2, MinChangeAmount: 10000}, +} + +var minNumberTests = []coinSelectTest{ + {minNumberSelectors[0], coins, coins[0].Value() - minNumberSelectors[0].MinChangeAmount, []coinset.Coin{coins[0]}, nil}, + {minNumberSelectors[0], coins, coins[0].Value() - minNumberSelectors[0].MinChangeAmount + 1, []coinset.Coin{coins[0], coins[2]}, nil}, + {minNumberSelectors[0], coins, 100000000, []coinset.Coin{coins[0]}, nil}, + {minNumberSelectors[0], coins, 110000000, []coinset.Coin{coins[0], coins[2]}, nil}, + {minNumberSelectors[0], coins, 160000000, []coinset.Coin{coins[0], coins[2], coins[3]}, nil}, + {minNumberSelectors[0], coins, 184990000, []coinset.Coin{coins[0], coins[2], coins[3], coins[1]}, nil}, + {minNumberSelectors[0], coins, 184990001, nil, coinset.ErrCoinsNoSelectionAvailable}, + {minNumberSelectors[0], coins, 200000000, nil, coinset.ErrCoinsNoSelectionAvailable}, + {minNumberSelectors[1], coins, 10000000, []coinset.Coin{coins[0]}, nil}, + {minNumberSelectors[1], coins, 110000000, []coinset.Coin{coins[0], coins[2]}, nil}, + {minNumberSelectors[1], coins, 140000000, []coinset.Coin{coins[0], coins[2]}, nil}, +} + +func TestMinNumberSelector(t *testing.T) { + testCoinSelector(minNumberTests, t) +} + +var maxValueAgeSelectors = []coinset.MaxValueAgeCoinSelector{ + {MaxInputs: 10, MinChangeAmount: 10000}, + {MaxInputs: 2, MinChangeAmount: 10000}, +} + +var maxValueAgeTests = []coinSelectTest{ + {maxValueAgeSelectors[0], coins, 100000, []coinset.Coin{coins[1]}, nil}, + {maxValueAgeSelectors[0], coins, 10000000, []coinset.Coin{coins[1]}, nil}, + {maxValueAgeSelectors[0], coins, 10000001, []coinset.Coin{coins[1], coins[3]}, nil}, + {maxValueAgeSelectors[0], coins, 35000000, []coinset.Coin{coins[1], coins[3]}, nil}, + {maxValueAgeSelectors[0], coins, 135000000, []coinset.Coin{coins[1], coins[3], coins[0]}, nil}, + {maxValueAgeSelectors[0], coins, 185000000, []coinset.Coin{coins[1], coins[3], coins[0], coins[2]}, nil}, + {maxValueAgeSelectors[0], coins, 200000000, nil, coinset.ErrCoinsNoSelectionAvailable}, + {maxValueAgeSelectors[1], coins, 40000000, nil, coinset.ErrCoinsNoSelectionAvailable}, + {maxValueAgeSelectors[1], coins, 35000000, []coinset.Coin{coins[1], coins[3]}, nil}, + {maxValueAgeSelectors[1], coins, 34990001, nil, coinset.ErrCoinsNoSelectionAvailable}, +} + +func TestMaxValueAgeSelector(t *testing.T) { + testCoinSelector(maxValueAgeTests, t) +} + +var minPrioritySelectors = []coinset.MinPriorityCoinSelector{ + {MaxInputs: 10, MinChangeAmount: 10000, MinAvgValueAgePerInput: 100000000}, + {MaxInputs: 02, MinChangeAmount: 10000, MinAvgValueAgePerInput: 200000000}, + {MaxInputs: 02, MinChangeAmount: 10000, MinAvgValueAgePerInput: 150000000}, + {MaxInputs: 03, MinChangeAmount: 10000, MinAvgValueAgePerInput: 150000000}, + {MaxInputs: 10, MinChangeAmount: 10000, MinAvgValueAgePerInput: 1000000000}, + {MaxInputs: 10, MinChangeAmount: 10000, MinAvgValueAgePerInput: 175000000}, + {MaxInputs: 02, MinChangeAmount: 10000, MinAvgValueAgePerInput: 125000000}, +} + +var connectedCoins = []coinset.Coin{coins[0], coins[1], coins[3]} + +var minPriorityTests = []coinSelectTest{ + {minPrioritySelectors[0], connectedCoins, 100000000, []coinset.Coin{coins[0]}, nil}, + {minPrioritySelectors[0], connectedCoins, 125000000, []coinset.Coin{coins[0], coins[3]}, nil}, + {minPrioritySelectors[0], connectedCoins, 135000000, []coinset.Coin{coins[0], coins[3], coins[1]}, nil}, + {minPrioritySelectors[0], connectedCoins, 140000000, nil, coinset.ErrCoinsNoSelectionAvailable}, + {minPrioritySelectors[1], connectedCoins, 100000000, nil, coinset.ErrCoinsNoSelectionAvailable}, + {minPrioritySelectors[1], connectedCoins, 10000000, []coinset.Coin{coins[1]}, nil}, + {minPrioritySelectors[1], connectedCoins, 100000000, nil, coinset.ErrCoinsNoSelectionAvailable}, + {minPrioritySelectors[2], connectedCoins, 11000000, []coinset.Coin{coins[3]}, nil}, + {minPrioritySelectors[2], connectedCoins, 25000001, []coinset.Coin{coins[3], coins[1]}, nil}, + {minPrioritySelectors[3], connectedCoins, 25000001, []coinset.Coin{coins[3], coins[1], coins[0]}, nil}, + {minPrioritySelectors[3], connectedCoins, 100000000, []coinset.Coin{coins[3], coins[1], coins[0]}, nil}, + {minPrioritySelectors[3], []coinset.Coin{coins[1], coins[2]}, 10000000, []coinset.Coin{coins[1]}, nil}, + {minPrioritySelectors[4], connectedCoins, 1, nil, coinset.ErrCoinsNoSelectionAvailable}, + {minPrioritySelectors[5], connectedCoins, 20000000, []coinset.Coin{coins[1], coins[3]}, nil}, + {minPrioritySelectors[6], connectedCoins, 25000000, []coinset.Coin{coins[3], coins[0]}, nil}, +} + +func TestMinPrioritySelector(t *testing.T) { + testCoinSelector(minPriorityTests, t) +} + +var ( + // should be two outpoints, with 1st one having 0.035BTC value. + testSimpleCoinNumConfs = int64(1) + testSimpleCoinTxHash = "9b5965c86de51d5dc824e179a05cf232db78c80ae86ca9d7cb2a655b5e19c1e2" + testSimpleCoinTxHex = "0100000001a214a110f79e4abe073865ea5b3745c6e82c913bad44be70652804a5e4003b0a010000008c493046022100edd18a69664efa57264be207100c203e6cade1888cbb88a0ad748548256bb2f0022100f1027dc2e6c7f248d78af1dd90027b5b7d8ec563bb62aa85d4e74d6376f3868c0141048f3757b65ed301abd1b0e8942d1ab5b50594d3314cff0299f300c696376a0a9bf72e74710a8af7a5372d4af4bb519e2701a094ef48c8e48e3b65b28502452dceffffffff02e0673500000000001976a914686dd149a79b4a559d561fbc396d3e3c6628b98d88ace86ef102000000001976a914ac3f995655e81b875b38b64351d6f896ddbfc68588ac00000000" + testSimpleCoinTxValue0 = btcutil.Amount(3500000) + testSimpleCoinTxValueAge0 = int64(testSimpleCoinTxValue0) * testSimpleCoinNumConfs + testSimpleCoinTxPkScript0Hex = "76a914686dd149a79b4a559d561fbc396d3e3c6628b98d88ac" + testSimpleCoinTxPkScript0Bytes, _ = hex.DecodeString(testSimpleCoinTxPkScript0Hex) + testSimpleCoinTxBytes, _ = hex.DecodeString(testSimpleCoinTxHex) + testSimpleCoinTx, _ = btcutil.NewTxFromBytes(testSimpleCoinTxBytes) + testSimpleCoin = &coinset.SimpleCoin{ + Tx: testSimpleCoinTx, + TxIndex: 0, + TxNumConfs: testSimpleCoinNumConfs, + } +) + +func TestSimpleCoin(t *testing.T) { + if testSimpleCoin.Hash().String() != testSimpleCoinTxHash { + t.Error("Different value for tx hash than expected") + } + if testSimpleCoin.Index() != 0 { + t.Error("Different value for index of outpoint than expected") + } + if testSimpleCoin.Value() != testSimpleCoinTxValue0 { + t.Error("Different value of coin value than expected") + } + if !bytes.Equal(testSimpleCoin.PkScript(), testSimpleCoinTxPkScript0Bytes) { + t.Error("Different value of coin pkScript than expected") + } + if testSimpleCoin.NumConfs() != 1 { + t.Error("Differet value of num confs than expected") + } + if testSimpleCoin.ValueAge() != testSimpleCoinTxValueAge0 { + t.Error("Different value of coin value * age than expected") + } +} diff --git a/btcutil/coinset/cov_report.sh b/btcutil/coinset/cov_report.sh new file mode 100644 index 0000000000..307f05b76c --- /dev/null +++ b/btcutil/coinset/cov_report.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# This script uses gocov to generate a test coverage report. +# The gocov tool my be obtained with the following command: +# go get github.com/axw/gocov/gocov +# +# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. + +# Check for gocov. +type gocov >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo >&2 "This script requires the gocov tool." + echo >&2 "You may obtain it with the following command:" + echo >&2 "go get github.com/axw/gocov/gocov" + exit 1 +fi +gocov test | gocov report diff --git a/btcutil/coinset/test_coverage.txt b/btcutil/coinset/test_coverage.txt new file mode 100644 index 0000000000..0e3e15d9f7 --- /dev/null +++ b/btcutil/coinset/test_coverage.txt @@ -0,0 +1,31 @@ + +github.com/conformal/btcutil/coinset/coins.go MinPriorityCoinSelector.CoinSelect 100.00% (39/39) +github.com/conformal/btcutil/coinset/coins.go NewMsgTxWithInputCoins 100.00% (6/6) +github.com/conformal/btcutil/coinset/coins.go MinIndexCoinSelector.CoinSelect 100.00% (6/6) +github.com/conformal/btcutil/coinset/coins.go CoinSet.removeElement 100.00% (5/5) +github.com/conformal/btcutil/coinset/coins.go NewCoinSet 100.00% (4/4) +github.com/conformal/btcutil/coinset/coins.go CoinSet.Coins 100.00% (4/4) +github.com/conformal/btcutil/coinset/coins.go CoinSet.PopCoin 100.00% (4/4) +github.com/conformal/btcutil/coinset/coins.go CoinSet.ShiftCoin 100.00% (4/4) +github.com/conformal/btcutil/coinset/coins.go MinNumberCoinSelector.CoinSelect 100.00% (4/4) +github.com/conformal/btcutil/coinset/coins.go MaxValueAgeCoinSelector.CoinSelect 100.00% (4/4) +github.com/conformal/btcutil/coinset/coins.go CoinSet.PushCoin 100.00% (3/3) +github.com/conformal/btcutil/coinset/coins.go CoinSet.TotalValueAge 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go SimpleCoin.NumConfs 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go SimpleCoin.ValueAge 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go CoinSet.TotalValue 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go byValueAge.Len 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go byValueAge.Swap 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go byValueAge.Less 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go byAmount.Len 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go byAmount.Swap 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go byAmount.Less 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go SimpleCoin.Hash 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go SimpleCoin.Index 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go SimpleCoin.txOut 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go SimpleCoin.Value 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go SimpleCoin.PkScript 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go CoinSet.Num 100.00% (1/1) +github.com/conformal/btcutil/coinset/coins.go satisfiesTargetValue 100.00% (1/1) +github.com/conformal/btcutil/coinset ---------------------------------- 100.00% (100/100) + diff --git a/btcutil/const.go b/btcutil/const.go new file mode 100644 index 0000000000..c73946056f --- /dev/null +++ b/btcutil/const.go @@ -0,0 +1,16 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +const ( + // SatoshiPerBitcent is the number of satoshi in one bitcoin cent. + SatoshiPerBitcent = 1e6 + + // SatoshiPerBitcoin is the number of satoshi in one bitcoin (1 BTC). + SatoshiPerBitcoin = 1e8 + + // MaxSatoshi is the maximum transaction amount allowed in satoshi. + MaxSatoshi = 21e6 * SatoshiPerBitcoin +) diff --git a/btcutil/cov_report.sh b/btcutil/cov_report.sh new file mode 100644 index 0000000000..307f05b76c --- /dev/null +++ b/btcutil/cov_report.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# This script uses gocov to generate a test coverage report. +# The gocov tool my be obtained with the following command: +# go get github.com/axw/gocov/gocov +# +# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. + +# Check for gocov. +type gocov >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo >&2 "This script requires the gocov tool." + echo >&2 "You may obtain it with the following command:" + echo >&2 "go get github.com/axw/gocov/gocov" + exit 1 +fi +gocov test | gocov report diff --git a/btcutil/doc.go b/btcutil/doc.go new file mode 100644 index 0000000000..36cda1c782 --- /dev/null +++ b/btcutil/doc.go @@ -0,0 +1,46 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package btcutil provides bitcoin-specific convenience functions and types. + +Block Overview + +A Block defines a bitcoin block that provides easier and more efficient +manipulation of raw wire protocol blocks. It also memoizes hashes for the +block and its transactions on their first access so subsequent accesses don't +have to repeat the relatively expensive hashing operations. + +Tx Overview + +A Tx defines a bitcoin transaction that provides more efficient manipulation of +raw wire protocol transactions. It memoizes the hash for the transaction on its +first access so subsequent accesses don't have to repeat the relatively +expensive hashing operations. + +Address Overview + +The Address interface provides an abstraction for a Bitcoin address. While the +most common type is a pay-to-pubkey-hash, Bitcoin already supports others and +may well support more in the future. This package currently provides +implementations for the pay-to-pubkey, pay-to-pubkey-hash, and +pay-to-script-hash address types. + +To decode/encode an address: + + // NOTE: The default network is only used for address types which do not + // already contain that information. At this time, that is only + // pay-to-pubkey addresses. + addrString := "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962" + + "e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d57" + + "8a4c702b6bf11d5f" + defaultNet := &chaincfg.MainNetParams + addr, err := btcutil.DecodeAddress(addrString, defaultNet) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(addr.EncodeAddress()) +*/ +package btcutil diff --git a/btcutil/example_test.go b/btcutil/example_test.go new file mode 100644 index 0000000000..6b62fdd44f --- /dev/null +++ b/btcutil/example_test.go @@ -0,0 +1,76 @@ +package btcutil_test + +import ( + "fmt" + "math" + + "github.com/btcsuite/btcd/btcutil" +) + +func ExampleAmount() { + + a := btcutil.Amount(0) + fmt.Println("Zero Satoshi:", a) + + a = btcutil.Amount(1e8) + fmt.Println("100,000,000 Satoshis:", a) + + a = btcutil.Amount(1e5) + fmt.Println("100,000 Satoshis:", a) + // Output: + // Zero Satoshi: 0 BTC + // 100,000,000 Satoshis: 1 BTC + // 100,000 Satoshis: 0.001 BTC +} + +func ExampleNewAmount() { + amountOne, err := btcutil.NewAmount(1) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(amountOne) //Output 1 + + amountFraction, err := btcutil.NewAmount(0.01234567) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(amountFraction) //Output 2 + + amountZero, err := btcutil.NewAmount(0) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(amountZero) //Output 3 + + amountNaN, err := btcutil.NewAmount(math.NaN()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println(amountNaN) //Output 4 + + // Output: 1 BTC + // 0.01234567 BTC + // 0 BTC + // invalid bitcoin amount +} + +func ExampleAmount_unitConversions() { + amount := btcutil.Amount(44433322211100) + + fmt.Println("Satoshi to kBTC:", amount.Format(btcutil.AmountKiloBTC)) + fmt.Println("Satoshi to BTC:", amount) + fmt.Println("Satoshi to MilliBTC:", amount.Format(btcutil.AmountMilliBTC)) + fmt.Println("Satoshi to MicroBTC:", amount.Format(btcutil.AmountMicroBTC)) + fmt.Println("Satoshi to Satoshi:", amount.Format(btcutil.AmountSatoshi)) + + // Output: + // Satoshi to kBTC: 444.333222111 kBTC + // Satoshi to BTC: 444333.222111 BTC + // Satoshi to MilliBTC: 444333222.111 mBTC + // Satoshi to MicroBTC: 444333222111 μBTC + // Satoshi to Satoshi: 44433322211100 Satoshi +} diff --git a/btcutil/gcs/README.md b/btcutil/gcs/README.md new file mode 100644 index 0000000000..ee0c120401 --- /dev/null +++ b/btcutil/gcs/README.md @@ -0,0 +1,24 @@ +gcs +========== + +[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)] +(https://travis-ci.org/btcsuite/btcutil) [![ISC License] +(http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://godoc.org/github.com/btcsuite/btcd/btcutil/gcs?status.png)] +(http://godoc.org/github.com/btcsuite/btcd/btcutil/gcs) + +Package gcs provides an API for building and using a Golomb-coded set filter +similar to that described [here](http://giovanni.bajo.it/post/47119962313/golomb-coded-sets-smaller-than-bloom-filters). + +A comprehensive suite of tests is provided to ensure proper functionality. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil/gcs +``` + +## License + +Package gcs is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/gcs/builder/builder.go b/btcutil/gcs/builder/builder.go new file mode 100644 index 0000000000..6f15ec7a68 --- /dev/null +++ b/btcutil/gcs/builder/builder.go @@ -0,0 +1,371 @@ +// Copyright (c) 2017 The btcsuite developers +// Copyright (c) 2017 The Lightning Network Developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package builder + +import ( + "crypto/rand" + "fmt" + "math" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil/gcs" +) + +const ( + // DefaultP is the default collision probability (2^-19) + DefaultP = 19 + + // DefaultM is the default value used for the hash range. + DefaultM uint64 = 784931 +) + +// GCSBuilder is a utility class that makes building GCS filters convenient. +type GCSBuilder struct { + p uint8 + + m uint64 + + key [gcs.KeySize]byte + + // data is a set of entries represented as strings. This is done to + // deduplicate items as they are added. + data map[string]struct{} + err error +} + +// RandomKey is a utility function that returns a cryptographically random +// [gcs.KeySize]byte usable as a key for a GCS filter. +func RandomKey() ([gcs.KeySize]byte, error) { + var key [gcs.KeySize]byte + + // Read a byte slice from rand.Reader. + randKey := make([]byte, gcs.KeySize) + _, err := rand.Read(randKey) + + // This shouldn't happen unless the user is on a system that doesn't + // have a system CSPRNG. OK to panic in this case. + if err != nil { + return key, err + } + + // Copy the byte slice to a [gcs.KeySize]byte array and return it. + copy(key[:], randKey) + return key, nil +} + +// DeriveKey is a utility function that derives a key from a chainhash.Hash by +// truncating the bytes of the hash to the appopriate key size. +func DeriveKey(keyHash *chainhash.Hash) [gcs.KeySize]byte { + var key [gcs.KeySize]byte + copy(key[:], keyHash.CloneBytes()) + return key +} + +// Key retrieves the key with which the builder will build a filter. This is +// useful if the builder is created with a random initial key. +func (b *GCSBuilder) Key() ([gcs.KeySize]byte, error) { + // Do nothing if the builder's errored out. + if b.err != nil { + return [gcs.KeySize]byte{}, b.err + } + + return b.key, nil +} + +// SetKey sets the key with which the builder will build a filter to the passed +// [gcs.KeySize]byte. +func (b *GCSBuilder) SetKey(key [gcs.KeySize]byte) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + copy(b.key[:], key[:]) + return b +} + +// SetKeyFromHash sets the key with which the builder will build a filter to a +// key derived from the passed chainhash.Hash using DeriveKey(). +func (b *GCSBuilder) SetKeyFromHash(keyHash *chainhash.Hash) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + return b.SetKey(DeriveKey(keyHash)) +} + +// SetP sets the filter's probability after calling Builder(). +func (b *GCSBuilder) SetP(p uint8) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + // Basic sanity check. + if p > 32 { + b.err = gcs.ErrPTooBig + return b + } + + b.p = p + return b +} + +// SetM sets the filter's modulous value after calling Builder(). +func (b *GCSBuilder) SetM(m uint64) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + // Basic sanity check. + if m > uint64(math.MaxUint32) { + b.err = gcs.ErrPTooBig + return b + } + + b.m = m + return b +} + +// Preallocate sets the estimated filter size after calling Builder() to reduce +// the probability of memory reallocations. If the builder has already had data +// added to it, Preallocate has no effect. +func (b *GCSBuilder) Preallocate(n uint32) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + if b.data == nil { + b.data = make(map[string]struct{}, n) + } + + return b +} + +// AddEntry adds a []byte to the list of entries to be included in the GCS +// filter when it's built. +func (b *GCSBuilder) AddEntry(data []byte) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + b.data[string(data)] = struct{}{} + return b +} + +// AddEntries adds all the []byte entries in a [][]byte to the list of entries +// to be included in the GCS filter when it's built. +func (b *GCSBuilder) AddEntries(data [][]byte) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + for _, entry := range data { + b.AddEntry(entry) + } + return b +} + +// AddHash adds a chainhash.Hash to the list of entries to be included in the +// GCS filter when it's built. +func (b *GCSBuilder) AddHash(hash *chainhash.Hash) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + return b.AddEntry(hash.CloneBytes()) +} + +// AddWitness adds each item of the passed filter stack to the filter, and then +// adds each item as a script. +func (b *GCSBuilder) AddWitness(witness wire.TxWitness) *GCSBuilder { + // Do nothing if the builder's already errored out. + if b.err != nil { + return b + } + + return b.AddEntries(witness) +} + +// Build returns a function which builds a GCS filter with the given parameters +// and data. +func (b *GCSBuilder) Build() (*gcs.Filter, error) { + // Do nothing if the builder's already errored out. + if b.err != nil { + return nil, b.err + } + + // We'll ensure that all the parmaters we need to actually build the + // filter properly are set. + if b.p == 0 { + return nil, fmt.Errorf("p value is not set, cannot build") + } + if b.m == 0 { + return nil, fmt.Errorf("m value is not set, cannot build") + } + + dataSlice := make([][]byte, 0, len(b.data)) + for item := range b.data { + dataSlice = append(dataSlice, []byte(item)) + } + + return gcs.BuildGCSFilter(b.p, b.m, b.key, dataSlice) +} + +// WithKeyPNM creates a GCSBuilder with specified key and the passed +// probability, modulus and estimated filter size. +func WithKeyPNM(key [gcs.KeySize]byte, p uint8, n uint32, m uint64) *GCSBuilder { + b := GCSBuilder{} + return b.SetKey(key).SetP(p).SetM(m).Preallocate(n) +} + +// WithKeyPM creates a GCSBuilder with specified key and the passed +// probability. Estimated filter size is set to zero, which means more +// reallocations are done when building the filter. +func WithKeyPM(key [gcs.KeySize]byte, p uint8, m uint64) *GCSBuilder { + return WithKeyPNM(key, p, 0, m) +} + +// WithKey creates a GCSBuilder with specified key. Probability is set to 19 +// (2^-19 collision probability). Estimated filter size is set to zero, which +// means more reallocations are done when building the filter. +func WithKey(key [gcs.KeySize]byte) *GCSBuilder { + return WithKeyPNM(key, DefaultP, 0, DefaultM) +} + +// WithKeyHashPNM creates a GCSBuilder with key derived from the specified +// chainhash.Hash and the passed probability and estimated filter size. +func WithKeyHashPNM(keyHash *chainhash.Hash, p uint8, n uint32, + m uint64) *GCSBuilder { + + return WithKeyPNM(DeriveKey(keyHash), p, n, m) +} + +// WithKeyHashPM creates a GCSBuilder with key derived from the specified +// chainhash.Hash and the passed probability. Estimated filter size is set to +// zero, which means more reallocations are done when building the filter. +func WithKeyHashPM(keyHash *chainhash.Hash, p uint8, m uint64) *GCSBuilder { + return WithKeyHashPNM(keyHash, p, 0, m) +} + +// WithKeyHash creates a GCSBuilder with key derived from the specified +// chainhash.Hash. Probability is set to 20 (2^-20 collision probability). +// Estimated filter size is set to zero, which means more reallocations are +// done when building the filter. +func WithKeyHash(keyHash *chainhash.Hash) *GCSBuilder { + return WithKeyHashPNM(keyHash, DefaultP, 0, DefaultM) +} + +// WithRandomKeyPNM creates a GCSBuilder with a cryptographically random key and +// the passed probability and estimated filter size. +func WithRandomKeyPNM(p uint8, n uint32, m uint64) *GCSBuilder { + key, err := RandomKey() + if err != nil { + b := GCSBuilder{err: err} + return &b + } + return WithKeyPNM(key, p, n, m) +} + +// WithRandomKeyPM creates a GCSBuilder with a cryptographically random key and +// the passed probability. Estimated filter size is set to zero, which means +// more reallocations are done when building the filter. +func WithRandomKeyPM(p uint8, m uint64) *GCSBuilder { + return WithRandomKeyPNM(p, 0, m) +} + +// WithRandomKey creates a GCSBuilder with a cryptographically random key. +// Probability is set to 20 (2^-20 collision probability). Estimated filter +// size is set to zero, which means more reallocations are done when +// building the filter. +func WithRandomKey() *GCSBuilder { + return WithRandomKeyPNM(DefaultP, 0, DefaultM) +} + +// BuildBasicFilter builds a basic GCS filter from a block. A basic GCS filter +// will contain all the previous output scripts spent by inputs within a block, +// as well as the data pushes within all the outputs created within a block. +func BuildBasicFilter(block *wire.MsgBlock, prevOutScripts [][]byte) (*gcs.Filter, error) { + blockHash := block.BlockHash() + b := WithKeyHash(&blockHash) + + // If the filter had an issue with the specified key, then we force it + // to bubble up here by calling the Key() function. + _, err := b.Key() + if err != nil { + return nil, err + } + + // In order to build a basic filter, we'll range over the entire block, + // adding each whole script itself. + for _, tx := range block.Transactions { + // For each output in a transaction, we'll add each of the + // individual data pushes within the script. + for _, txOut := range tx.TxOut { + if len(txOut.PkScript) == 0 { + continue + } + + // In order to allow the filters to later be committed + // to within an OP_RETURN output, we ignore all + // OP_RETURNs to avoid a circular dependency. + if txOut.PkScript[0] == txscript.OP_RETURN { + continue + } + + b.AddEntry(txOut.PkScript) + } + } + + // In the second pass, we'll also add all the prevOutScripts + // individually as elements. + for _, prevScript := range prevOutScripts { + if len(prevScript) == 0 { + continue + } + + b.AddEntry(prevScript) + } + + return b.Build() +} + +// GetFilterHash returns the double-SHA256 of the filter. +func GetFilterHash(filter *gcs.Filter) (chainhash.Hash, error) { + filterData, err := filter.NBytes() + if err != nil { + return chainhash.Hash{}, err + } + + return chainhash.DoubleHashH(filterData), nil +} + +// MakeHeaderForFilter makes a filter chain header for a filter, given the +// filter and the previous filter chain header. +func MakeHeaderForFilter(filter *gcs.Filter, prevHeader chainhash.Hash) (chainhash.Hash, error) { + filterTip := make([]byte, 2*chainhash.HashSize) + filterHash, err := GetFilterHash(filter) + if err != nil { + return chainhash.Hash{}, err + } + + // In the buffer we created above we'll compute hash || prevHash as an + // intermediate value. + copy(filterTip, filterHash[:]) + copy(filterTip[chainhash.HashSize:], prevHeader[:]) + + // The final filter hash is the double-sha256 of the hash computed + // above. + return chainhash.DoubleHashH(filterTip), nil +} diff --git a/btcutil/gcs/builder/builder_test.go b/btcutil/gcs/builder/builder_test.go new file mode 100644 index 0000000000..59768380b1 --- /dev/null +++ b/btcutil/gcs/builder/builder_test.go @@ -0,0 +1,281 @@ +// Copyright (c) 2017 The btcsuite developers +// Copyright (c) 2017 The Lightning Network Developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package builder_test + +import ( + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/gcs" + "github.com/btcsuite/btcd/btcutil/gcs/builder" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +var ( + // List of values for building a filter + contents = [][]byte{ + []byte("Alex"), + []byte("Bob"), + []byte("Charlie"), + []byte("Dick"), + []byte("Ed"), + []byte("Frank"), + []byte("George"), + []byte("Harry"), + []byte("Ilya"), + []byte("John"), + []byte("Kevin"), + []byte("Larry"), + []byte("Michael"), + []byte("Nate"), + []byte("Owen"), + []byte("Paul"), + []byte("Quentin"), + } + + testKey = [16]byte{0x4c, 0xb1, 0xab, 0x12, 0x57, 0x62, 0x1e, 0x41, + 0x3b, 0x8b, 0x0e, 0x26, 0x64, 0x8d, 0x4a, 0x15} + + testHash = "000000000000000000496d7ff9bd2c96154a8d64260e8b3b411e625712abb14c" + + testAddr = "3Nxwenay9Z8Lc9JBiywExpnEFiLp6Afp8v" + + witness = [][]byte{ + {0x4c, 0xb1, 0xab, 0x12, 0x57, 0x62, 0x1e, 0x41, + 0x3b, 0x8b, 0x0e, 0x26, 0x64, 0x8d, 0x4a, 0x15, + 0x3b, 0x8b, 0x0e, 0x26, 0x64, 0x8d, 0x4a, 0x15, + 0x3b, 0x8b, 0x0e, 0x26, 0x64, 0x8d, 0x4a, 0x15}, + + {0xdd, 0xa3, 0x5a, 0x14, 0x88, 0xfb, 0x97, 0xb6, + 0xeb, 0x3f, 0xe6, 0xe9, 0xef, 0x2a, 0x25, 0x81, + 0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9, + 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98, + 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98, + 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98}, + } +) + +// TestUseBlockHash tests using a block hash as a filter key. +func TestUseBlockHash(t *testing.T) { + // Block hash #448710, pretty high difficulty. + hash, err := chainhash.NewHashFromStr(testHash) + if err != nil { + t.Fatalf("Hash from string failed: %s", err.Error()) + } + + // wire.OutPoint + outPoint := wire.OutPoint{ + Hash: *hash, + Index: 4321, + } + + // btcutil.Address + addr, err := btcutil.DecodeAddress(testAddr, &chaincfg.MainNetParams) + if err != nil { + t.Fatalf("Address decode failed: %s", err.Error()) + } + addrBytes, err := txscript.NewScriptBuilder(). + AddOp(txscript.OP_HASH160).AddData(addr.ScriptAddress()). + AddOp(txscript.OP_EQUAL).Script() + if err != nil { + t.Fatalf("Address script build failed: %s", err.Error()) + } + + // Create a GCSBuilder with a key hash and check that the key is derived + // correctly, then test it. + b := builder.WithKeyHash(hash) + key, err := b.Key() + if err != nil { + t.Fatalf("Builder instantiation with key hash failed: %s", + err.Error()) + } + if key != testKey { + t.Fatalf("Key not derived correctly from key hash:\n%s\n%s", + hex.EncodeToString(key[:]), + hex.EncodeToString(testKey[:])) + } + BuilderTest(b, hash, builder.DefaultP, outPoint, addrBytes, witness, t) + + // Create a GCSBuilder with a key hash and non-default P and test it. + b = builder.WithKeyHashPM(hash, 30, 90) + BuilderTest(b, hash, 30, outPoint, addrBytes, witness, t) + + // Create a GCSBuilder with a random key, set the key from a hash + // manually, check that the key is correct, and test it. + b = builder.WithRandomKey() + b.SetKeyFromHash(hash) + key, err = b.Key() + if err != nil { + t.Fatalf("Builder instantiation with known key failed: %s", + err.Error()) + } + if key != testKey { + t.Fatalf("Key not copied correctly from known key:\n%s\n%s", + hex.EncodeToString(key[:]), + hex.EncodeToString(testKey[:])) + } + BuilderTest(b, hash, builder.DefaultP, outPoint, addrBytes, witness, t) + + // Create a GCSBuilder with a random key and test it. + b = builder.WithRandomKey() + key1, err := b.Key() + if err != nil { + t.Fatalf("Builder instantiation with random key failed: %s", + err.Error()) + } + t.Logf("Random Key 1: %s", hex.EncodeToString(key1[:])) + BuilderTest(b, hash, builder.DefaultP, outPoint, addrBytes, witness, t) + + // Create a GCSBuilder with a random key and non-default P and test it. + b = builder.WithRandomKeyPM(30, 90) + key2, err := b.Key() + if err != nil { + t.Fatalf("Builder instantiation with random key failed: %s", + err.Error()) + } + t.Logf("Random Key 2: %s", hex.EncodeToString(key2[:])) + if key2 == key1 { + t.Fatalf("Random keys are the same!") + } + BuilderTest(b, hash, 30, outPoint, addrBytes, witness, t) + + // Create a GCSBuilder with a known key and test it. + b = builder.WithKey(testKey) + key, err = b.Key() + if err != nil { + t.Fatalf("Builder instantiation with known key failed: %s", + err.Error()) + } + if key != testKey { + t.Fatalf("Key not copied correctly from known key:\n%s\n%s", + hex.EncodeToString(key[:]), + hex.EncodeToString(testKey[:])) + } + BuilderTest(b, hash, builder.DefaultP, outPoint, addrBytes, witness, t) + + // Create a GCSBuilder with a known key and non-default P and test it. + b = builder.WithKeyPM(testKey, 30, 90) + key, err = b.Key() + if err != nil { + t.Fatalf("Builder instantiation with known key failed: %s", + err.Error()) + } + if key != testKey { + t.Fatalf("Key not copied correctly from known key:\n%s\n%s", + hex.EncodeToString(key[:]), + hex.EncodeToString(testKey[:])) + } + BuilderTest(b, hash, 30, outPoint, addrBytes, witness, t) + + // Create a GCSBuilder with a known key and too-high P and ensure error + // works throughout all functions that use it. + b = builder.WithRandomKeyPM(33, 99).SetKeyFromHash(hash).SetKey(testKey) + b.SetP(30).AddEntry(hash.CloneBytes()).AddEntries(contents). + AddHash(hash).AddEntry(addrBytes) + _, err = b.Key() + if err != gcs.ErrPTooBig { + t.Fatalf("No error on P too big!") + } + _, err = b.Build() + if err != gcs.ErrPTooBig { + t.Fatalf("No error on P too big!") + } +} + +func BuilderTest(b *builder.GCSBuilder, hash *chainhash.Hash, p uint8, + outPoint wire.OutPoint, addrBytes []byte, witness wire.TxWitness, + t *testing.T) { + + key, err := b.Key() + if err != nil { + t.Fatalf("Builder instantiation with key hash failed: %s", + err.Error()) + } + + // Build a filter and test matches. + b.AddEntries(contents) + f, err := b.Build() + if err != nil { + t.Fatalf("Filter build failed: %s", err.Error()) + } + if f.P() != p { + t.Fatalf("Filter built with wrong probability") + } + match, err := f.Match(key, []byte("Nate")) + if err != nil { + t.Fatalf("Filter match failed: %s", err) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + match, err = f.Match(key, []byte("weks")) + if err != nil { + t.Fatalf("Filter match failed: %s", err) + } + if match { + t.Logf("False positive match, should be 1 in 2**%d!", + builder.DefaultP) + } + + // Add a hash, build a filter, and test matches + b.AddHash(hash) + f, err = b.Build() + if err != nil { + t.Fatalf("Filter build failed: %s", err.Error()) + } + match, err = f.Match(key, hash.CloneBytes()) + if err != nil { + t.Fatalf("Filter match failed: %s", err) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + + // Add a script, build a filter, and test matches + b.AddEntry(addrBytes) + f, err = b.Build() + if err != nil { + t.Fatalf("Filter build failed: %s", err.Error()) + } + match, err = f.MatchAny(key, [][]byte{addrBytes}) + if err != nil { + t.Fatalf("Filter match any failed: %s", err) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + + // Add a routine witness stack, build a filter, and test that it + // matches. + b.AddWitness(witness) + f, err = b.Build() + if err != nil { + t.Fatalf("Filter build failed: %s", err.Error()) + } + match, err = f.MatchAny(key, witness) + if err != nil { + t.Fatalf("Filter match any failed: %s", err) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + + // Check that adding duplicate items does not increase filter size. + originalSize := f.N() + b.AddEntry(addrBytes) + b.AddWitness(witness) + f, err = b.Build() + if err != nil { + t.Fatalf("Filter build failed: %s", err.Error()) + } + if f.N() != originalSize { + t.Fatal("Filter size increased with duplicate items") + } +} diff --git a/btcutil/gcs/doc.go b/btcutil/gcs/doc.go new file mode 100644 index 0000000000..780fd76631 --- /dev/null +++ b/btcutil/gcs/doc.go @@ -0,0 +1,24 @@ +// Copyright (c) 2016-2017 The btcsuite developers +// Copyright (c) 2016-2017 The Lightning Network Developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package gcs provides an API for building and using a Golomb-coded set filter. + +Golomb-Coded Set + +A Golomb-coded set is a probabilistic data structure used similarly to a Bloom +filter. A filter uses constant-size overhead plus on average n+2 bits per +item added to the filter, where 2^-n is the desired false positive (collision) +probability. + +GCS use in Bitcoin + +GCS filters are a proposed mechanism for storing and transmitting per-block +filters in Bitcoin. The usage is intended to be the inverse of Bloom filters: +a full node would send an SPV node the GCS filter for a block, which the SPV +node would check against its list of relevant items. The suggested collision +probability for Bitcoin use is 2^-20. +*/ +package gcs diff --git a/btcutil/gcs/gcs.go b/btcutil/gcs/gcs.go new file mode 100644 index 0000000000..fbffb06131 --- /dev/null +++ b/btcutil/gcs/gcs.go @@ -0,0 +1,541 @@ +// Copyright (c) 2016-2017 The btcsuite developers +// Copyright (c) 2016-2017 The Lightning Network Developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package gcs + +import ( + "bytes" + "fmt" + "io" + "sort" + + "github.com/aead/siphash" + "github.com/btcsuite/btcd/wire" + "github.com/kkdai/bstream" +) + +// Inspired by https://github.com/rasky/gcs + +var ( + // ErrNTooBig signifies that the filter can't handle N items. + ErrNTooBig = fmt.Errorf("N is too big to fit in uint32") + + // ErrPTooBig signifies that the filter can't handle `1/2**P` + // collision probability. + ErrPTooBig = fmt.Errorf("P is too big to fit in uint32") +) + +const ( + // KeySize is the size of the byte array required for key material for + // the SipHash keyed hash function. + KeySize = 16 + + // varIntProtoVer is the protocol version to use for serializing N as a + // VarInt. + varIntProtoVer uint32 = 0 +) + +// fastReduction calculates a mapping that's more ore less equivalent to: x mod +// N. However, instead of using a mod operation, which using a non-power of two +// will lead to slowness on many processors due to unnecessary division, we +// instead use a "multiply-and-shift" trick which eliminates all divisions, +// described in: +// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ +// +// * v * N >> log_2(N) +// +// In our case, using 64-bit integers, log_2 is 64. As most processors don't +// support 128-bit arithmetic natively, we'll be super portable and unfold the +// operation into several operations with 64-bit arithmetic. As inputs, we the +// number to reduce, and our modulus N divided into its high 32-bits and lower +// 32-bits. +func fastReduction(v, nHi, nLo uint64) uint64 { + // First, we'll spit the item we need to reduce into its higher and + // lower bits. + vhi := v >> 32 + vlo := uint64(uint32(v)) + + // Then, we distribute multiplication over each part. + vnphi := vhi * nHi + vnpmid := vhi * nLo + npvmid := nHi * vlo + vnplo := vlo * nLo + + // We calculate the carry bit. + carry := (uint64(uint32(vnpmid)) + uint64(uint32(npvmid)) + + (vnplo >> 32)) >> 32 + + // Last, we add the high bits, the middle bits, and the carry. + v = vnphi + (vnpmid >> 32) + (npvmid >> 32) + carry + + return v +} + +// Filter describes an immutable filter that can be built from a set of data +// elements, serialized, deserialized, and queried in a thread-safe manner. The +// serialized form is compressed as a Golomb Coded Set (GCS), but does not +// include N or P to allow the user to encode the metadata separately if +// necessary. The hash function used is SipHash, a keyed function; the key used +// in building the filter is required in order to match filter values and is +// not included in the serialized form. +type Filter struct { + n uint32 + p uint8 + modulusNP uint64 + + filterData []byte +} + +// BuildGCSFilter builds a new GCS filter with the collision probability of +// `1/(2**P)`, key `key`, and including every `[]byte` in `data` as a member of +// the set. +func BuildGCSFilter(P uint8, M uint64, key [KeySize]byte, data [][]byte) (*Filter, error) { // nolint:gocritic + // Some initial parameter checks: make sure we have data from which to + // build the filter, and make sure our parameters will fit the hash + // function we're using. + if uint64(len(data)) >= (1 << 32) { + return nil, ErrNTooBig + } + if P > 32 { + return nil, ErrPTooBig + } + + // Create the filter object and insert metadata. + f := Filter{ + n: uint32(len(data)), + p: P, + } + + // First we'll compute the value of m, which is the modulus we use + // within our finite field. We want to compute: mScalar * 2^P. We use + // math.Round in order to round the value up, rather than down. + f.modulusNP = uint64(f.n) * M + + // Shortcut if the filter is empty. + if f.n == 0 { + return &f, nil + } + + // Build the filter. + values := make([]uint64, 0, len(data)) + b := bstream.NewBStreamWriter(0) + + // Insert the hash (fast-ranged over a space of N*P) of each data + // element into a slice and sort the slice. This can be greatly + // optimized with native 128-bit multiplication, but we're going to be + // fully portable for now. + // + // First, we cache the high and low bits of modulusNP for the + // multiplication of 2 64-bit integers into a 128-bit integer. + nphi := f.modulusNP >> 32 + nplo := uint64(uint32(f.modulusNP)) + for _, d := range data { + // For each datum, we assign the initial hash to a uint64. + v := siphash.Sum64(d, &key) + + v = fastReduction(v, nphi, nplo) + values = append(values, v) + } + sort.Slice(values, func(i, j int) bool { return values[i] < values[j] }) + + // Write the sorted list of values into the filter bitstream, + // compressing it using Golomb coding. + var value, lastValue, remainder uint64 + for _, v := range values { + // Calculate the difference between this value and the last, + // modulo P. + remainder = (v - lastValue) & ((uint64(1) << f.p) - 1) + + // Calculate the difference between this value and the last, + // divided by P. + value = (v - lastValue - remainder) >> f.p + lastValue = v + + // Write the P multiple into the bitstream in unary; the + // average should be around 1 (2 bits - 0b10). + for value > 0 { + b.WriteBit(true) + value-- + } + b.WriteBit(false) + + // Write the remainder as a big-endian integer with enough bits + // to represent the appropriate collision probability. + b.WriteBits(remainder, int(f.p)) + } + + // Copy the bitstream into the filter object and return the object. + f.filterData = b.Bytes() + + return &f, nil +} + +// FromBytes deserializes a GCS filter from a known N, P, and serialized filter +// as returned by Bytes(). +func FromBytes(N uint32, P uint8, M uint64, d []byte) (*Filter, error) { // nolint:gocritic + // Basic sanity check. + if P > 32 { + return nil, ErrPTooBig + } + + // Create the filter object and insert metadata. + f := &Filter{ + n: N, + p: P, + } + + // First we'll compute the value of m, which is the modulus we use + // within our finite field. We want to compute: mScalar * 2^P. We use + // math.Round in order to round the value up, rather than down. + f.modulusNP = uint64(f.n) * M + + // Copy the filter. + f.filterData = make([]byte, len(d)) + copy(f.filterData, d) + + return f, nil +} + +// FromNBytes deserializes a GCS filter from a known P, and serialized N and +// filter as returned by NBytes(). +func FromNBytes(P uint8, M uint64, d []byte) (*Filter, error) { // nolint:gocritic + buffer := bytes.NewBuffer(d) + N, err := wire.ReadVarInt(buffer, varIntProtoVer) + if err != nil { + return nil, err + } + if N >= (1 << 32) { + return nil, ErrNTooBig + } + return FromBytes(uint32(N), P, M, buffer.Bytes()) +} + +// Bytes returns the serialized format of the GCS filter, which does not +// include N or P (returned by separate methods) or the key used by SipHash. +func (f *Filter) Bytes() ([]byte, error) { + filterData := make([]byte, len(f.filterData)) + copy(filterData, f.filterData) + return filterData, nil +} + +// NBytes returns the serialized format of the GCS filter with N, which does +// not include P (returned by a separate method) or the key used by SipHash. +func (f *Filter) NBytes() ([]byte, error) { + var buffer bytes.Buffer + buffer.Grow(wire.VarIntSerializeSize(uint64(f.n)) + len(f.filterData)) + + err := wire.WriteVarInt(&buffer, varIntProtoVer, uint64(f.n)) + if err != nil { + return nil, err + } + + _, err = buffer.Write(f.filterData) + if err != nil { + return nil, err + } + + return buffer.Bytes(), nil +} + +// PBytes returns the serialized format of the GCS filter with P, which does +// not include N (returned by a separate method) or the key used by SipHash. +func (f *Filter) PBytes() ([]byte, error) { + filterData := make([]byte, len(f.filterData)+1) + filterData[0] = f.p + copy(filterData[1:], f.filterData) + return filterData, nil +} + +// NPBytes returns the serialized format of the GCS filter with N and P, which +// does not include the key used by SipHash. +func (f *Filter) NPBytes() ([]byte, error) { + var buffer bytes.Buffer + buffer.Grow(wire.VarIntSerializeSize(uint64(f.n)) + 1 + len(f.filterData)) + + err := wire.WriteVarInt(&buffer, varIntProtoVer, uint64(f.n)) + if err != nil { + return nil, err + } + + err = buffer.WriteByte(f.p) + if err != nil { + return nil, err + } + + _, err = buffer.Write(f.filterData) + if err != nil { + return nil, err + } + + return buffer.Bytes(), nil +} + +// P returns the filter's collision probability as a negative power of 2 (that +// is, a collision probability of `1/2**20` is represented as 20). +func (f *Filter) P() uint8 { + return f.p +} + +// N returns the size of the data set used to build the filter. +func (f *Filter) N() uint32 { + return f.n +} + +// Match checks whether a []byte value is likely (within collision probability) +// to be a member of the set represented by the filter. +func (f *Filter) Match(key [KeySize]byte, data []byte) (bool, error) { + // Create a filter bitstream. + filterData, err := f.Bytes() + if err != nil { + return false, err + } + + b := bstream.NewBStreamReader(filterData) + + // We take the high and low bits of modulusNP for the multiplication + // of 2 64-bit integers into a 128-bit integer. + nphi := f.modulusNP >> 32 + nplo := uint64(uint32(f.modulusNP)) + + // Then we hash our search term with the same parameters as the filter. + term := siphash.Sum64(data, &key) + term = fastReduction(term, nphi, nplo) + + // Go through the search filter and look for the desired value. + var value uint64 + for i := uint32(0); i < f.N(); i++ { + // Read the difference between previous and new value from + // bitstream. + delta, err := f.readFullUint64(b) + if err != nil { + if err == io.EOF { + return false, nil + } + return false, err + } + + // Add the delta to the previous value. + value += delta + switch { + + // The current value matches our query term, success. + case value == term: + return true, nil + + // The current value is greater than our query term, thus no + // future decoded value can match because the values + // monotonically increase. + case value > term: + return false, nil + } + } + + // All values were decoded and none produced a successful match. This + // indicates that the items in the filter were all smaller than our + // target. + return false, nil +} + +// MatchAny returns checks whether any []byte value is likely (within collision +// probability) to be a member of the set represented by the filter faster than +// calling Match() for each value individually. +func (f *Filter) MatchAny(key [KeySize]byte, data [][]byte) (bool, error) { + // TODO(conner): add real heuristics to query optimization + switch { + + case len(data) >= int(f.N()/2): + return f.HashMatchAny(key, data) + + default: + return f.ZipMatchAny(key, data) + } +} + +// ZipMatchAny returns checks whether any []byte value is likely (within +// collision probability) to be a member of the set represented by the filter +// faster than calling Match() for each value individually. +// +// NOTE: This method should outperform HashMatchAny when the number of query +// entries is smaller than the number of filter entries. +func (f *Filter) ZipMatchAny(key [KeySize]byte, data [][]byte) (bool, error) { + // Basic anity check. + if len(data) == 0 { + return false, nil + } + + // Create a filter bitstream. + filterData, err := f.Bytes() + if err != nil { + return false, err + } + + b := bstream.NewBStreamReader(filterData) + + // Create an uncompressed filter of the search values. + values := make([]uint64, 0, len(data)) + + // First, we cache the high and low bits of modulusNP for the + // multiplication of 2 64-bit integers into a 128-bit integer. + nphi := f.modulusNP >> 32 + nplo := uint64(uint32(f.modulusNP)) + for _, d := range data { + // For each datum, we assign the initial hash to a uint64. + v := siphash.Sum64(d, &key) + + // We'll then reduce the value down to the range of our + // modulus. + v = fastReduction(v, nphi, nplo) + values = append(values, v) + } + sort.Slice(values, func(i, j int) bool { return values[i] < values[j] }) + + querySize := len(values) + + // Zip down the filters, comparing values until we either run out of + // values to compare in one of the filters or we reach a matching + // value. + var ( + value uint64 + queryIndex int + ) +out: + for i := uint32(0); i < f.N(); i++ { + // Advance filter we're searching or return false if we're at + // the end because nothing matched. + delta, err := f.readFullUint64(b) + if err != nil { + if err == io.EOF { + return false, nil + } + return false, err + } + value += delta + + for { + switch { + + // All query items have been exhausted and we haven't + // had a match, therefore there are no matches. + case queryIndex == querySize: + return false, nil + + // The current item in the query matches the decoded + // value, success. + case values[queryIndex] == value: + return true, nil + + // The current item in the query is greater than the + // current decoded value, continue to decode the next + // delta and try again. + case values[queryIndex] > value: + continue out + } + + queryIndex++ + } + } + + // All items in the filter were decoded and none produced a successful + // match. + return false, nil +} + +// HashMatchAny returns checks whether any []byte value is likely (within +// collision probability) to be a member of the set represented by the filter +// faster than calling Match() for each value individually. +// +// NOTE: This method should outperform MatchAny if the number of query entries +// approaches the number of filter entries, len(data) >= f.N(). +func (f *Filter) HashMatchAny(key [KeySize]byte, data [][]byte) (bool, error) { + // Basic sanity check. + if len(data) == 0 { + return false, nil + } + + // Create a filter bitstream. + filterData, err := f.Bytes() + if err != nil { + return false, err + } + + b := bstream.NewBStreamReader(filterData) + + var ( + values = make(map[uint32]struct{}, f.N()) + lastValue uint64 + ) + + // First, decompress the filter and construct an index of the keys + // contained within the filter. Index construction terminates after all + // values have been read from the bitstream. + for { + // Read the next diff value from the filter, add it to the + // last value, and set the new value in the index. + value, err := f.readFullUint64(b) + if err == nil { + lastValue += value + values[uint32(lastValue)] = struct{}{} + continue + } else if err == io.EOF { + break + } + + return false, err + } + + // We cache the high and low bits of modulusNP for the multiplication of + // 2 64-bit integers into a 128-bit integer. + nphi := f.modulusNP >> 32 + nplo := uint64(uint32(f.modulusNP)) + + // Finally, run through the provided data items, querying the index to + // determine if the filter contains any elements of interest. + for _, d := range data { + // For each datum, we assign the initial hash to + // a uint64. + v := siphash.Sum64(d, &key) + + // We'll then reduce the value down to the range + // of our modulus. + v = fastReduction(v, nphi, nplo) + + if _, ok := values[uint32(v)]; !ok { + continue + } + + return true, nil + } + + return false, nil +} + +// readFullUint64 reads a value represented by the sum of a unary multiple of +// the filter's P modulus (`2**P`) and a big-endian P-bit remainder. +func (f *Filter) readFullUint64(b *bstream.BStream) (uint64, error) { + var quotient uint64 + + // Count the 1s until we reach a 0. + c, err := b.ReadBit() + if err != nil { + return 0, err + } + for c { + quotient++ + c, err = b.ReadBit() + if err != nil { + return 0, err + } + } + + // Read P bits. + remainder, err := b.ReadBits(int(f.p)) + if err != nil { + return 0, err + } + + // Add the multiple and the remainder. + v := (quotient << f.p) + remainder + return v, nil +} diff --git a/btcutil/gcs/gcs_test.go b/btcutil/gcs/gcs_test.go new file mode 100644 index 0000000000..8ae49f0507 --- /dev/null +++ b/btcutil/gcs/gcs_test.go @@ -0,0 +1,368 @@ +// Copyright (c) 2016-2017 The btcsuite developers +// Copyright (c) 2016-2017 The Lightning Network Developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package gcs_test + +import ( + "bytes" + "encoding/binary" + "math/rand" + "testing" + + "github.com/btcsuite/btcd/btcutil/gcs" +) + +var ( + // No need to allocate an err variable in every test + err error + + // Collision probability for the tests (1/2**19) + P = uint8(19) + + // Modulus value for the tests. + M uint64 = 784931 + + // Filters are conserved between tests but we must define with an + // interface which functions we're testing because the gcsFilter type + // isn't exported + filter, filter2, filter3 *gcs.Filter + + // We need to use the same key for building and querying the filters + key [gcs.KeySize]byte + + // List of values for building a filter + contents = [][]byte{ + []byte("Alex"), + []byte("Bob"), + []byte("Charlie"), + []byte("Dick"), + []byte("Ed"), + []byte("Frank"), + []byte("George"), + []byte("Harry"), + []byte("Ilya"), + []byte("John"), + []byte("Kevin"), + []byte("Larry"), + []byte("Michael"), + []byte("Nate"), + []byte("Owen"), + []byte("Paul"), + []byte("Quentin"), + } + + // List of values for querying a filter using MatchAny() + contents2 = [][]byte{ + []byte("Alice"), + []byte("Betty"), + []byte("Charmaine"), + []byte("Donna"), + []byte("Edith"), + []byte("Faina"), + []byte("Georgia"), + []byte("Hannah"), + []byte("Ilsbeth"), + []byte("Jennifer"), + []byte("Kayla"), + []byte("Lena"), + []byte("Michelle"), + []byte("Natalie"), + []byte("Ophelia"), + []byte("Peggy"), + []byte("Queenie"), + } +) + +// TestGCSFilterBuild builds a test filter with a randomized key. For Bitcoin +// use, deterministic filter generation is desired. Therefore, a key that's +// derived deterministically would be required. +func TestGCSFilterBuild(t *testing.T) { + for i := 0; i < gcs.KeySize; i += 4 { + binary.BigEndian.PutUint32(key[i:], rand.Uint32()) + } + filter, err = gcs.BuildGCSFilter(P, M, key, contents) + if err != nil { + t.Fatalf("Filter build failed: %s", err.Error()) + } +} + +// TestGCSMatchZeroHash ensures that Match and MatchAny properly match an item +// if it's hash after the reduction is zero. This is accomplished by brute +// forcing a specific target whose hash is zero given a certain (P, M, key, +// len(elements)) combination. In this case, P and M are the default, key was +// chosen randomly, and len(elements) is 13. The target 4-byte value of 16060032 +// is the first such 32-bit value, thus we use the number 0-11 as the other +// elements in the filter since we know they won't collide. We test both the +// positive and negative cases, when the zero hash item is in the filter and +// when it is excluded. In the negative case, the 32-bit value of 12 is added to +// the filter instead of the target. +func TestGCSMatchZeroHash(t *testing.T) { + t.Run("include zero", func(t *testing.T) { + testGCSMatchZeroHash(t, true) + }) + t.Run("exclude zero", func(t *testing.T) { + testGCSMatchZeroHash(t, false) + }) +} + +func testGCSMatchZeroHash(t *testing.T, includeZeroHash bool) { + key := [gcs.KeySize]byte{ + 0x25, 0x28, 0x0d, 0x25, 0x26, 0xe1, 0xd3, 0xc7, + 0xa5, 0x71, 0x85, 0x34, 0x92, 0xa5, 0x7e, 0x68, + } + + // Construct the target data to match, whose hash is zero after applying + // the reduction with the parameters in the test. + target := make([]byte, 4) + binary.BigEndian.PutUint32(target, 16060032) + + // Construct the set of 13 items including the target, using the 32-bit + // values of 0 through 11 as the first 12 items. We known none of these + // hash to zero since the brute force ended well beyond them. + elements := make([][]byte, 0, 13) + for i := 0; i < 12; i++ { + data := make([]byte, 4) + binary.BigEndian.PutUint32(data, uint32(i)) + elements = append(elements, data) + } + + // If the filter should include the zero hash element, add the target + // which we know hashes to zero. Otherwise add 32-bit value of 12 which + // we know does not hash to zero. + if includeZeroHash { + elements = append(elements, target) + } else { + data := make([]byte, 4) + binary.BigEndian.PutUint32(data, 12) + elements = append(elements, data) + } + + filter, err := gcs.BuildGCSFilter(P, M, key, elements) + if err != nil { + t.Fatalf("unable to build filter: %v", err) + } + + match, err := filter.Match(key, target) + if err != nil { + t.Fatalf("unable to match: %v", err) + } + + // We should only get a match iff the target was included. + if match != includeZeroHash { + t.Fatalf("expected match from Match: %t, got %t", + includeZeroHash, match) + } + + match, err = filter.MatchAny(key, [][]byte{target}) + if err != nil { + t.Fatalf("unable to match any: %v", err) + } + + // We should only get a match iff the target was included. + if match != includeZeroHash { + t.Fatalf("expected match from MatchAny: %t, got %t", + includeZeroHash, match) + } +} + +// TestGCSFilterCopy deserializes and serializes a filter to create a copy. +func TestGCSFilterCopy(t *testing.T) { + serialized2, err := filter.Bytes() + if err != nil { + t.Fatalf("Filter Bytes() failed: %v", err) + } + filter2, err = gcs.FromBytes(filter.N(), P, M, serialized2) + if err != nil { + t.Fatalf("Filter copy failed: %s", err.Error()) + } + serialized3, err := filter.NBytes() + if err != nil { + t.Fatalf("Filter NBytes() failed: %v", err) + } + filter3, err = gcs.FromNBytes(filter.P(), M, serialized3) + if err != nil { + t.Fatalf("Filter copy failed: %s", err.Error()) + } +} + +// TestGCSFilterMetadata checks that the filter metadata is built and copied +// correctly. +func TestGCSFilterMetadata(t *testing.T) { + if filter.P() != P { + t.Fatal("P not correctly stored in filter metadata") + } + if filter.N() != uint32(len(contents)) { + t.Fatal("N not correctly stored in filter metadata") + } + if filter.P() != filter2.P() { + t.Fatal("P doesn't match between copied filters") + } + if filter.P() != filter3.P() { + t.Fatal("P doesn't match between copied filters") + } + if filter.N() != filter2.N() { + t.Fatal("N doesn't match between copied filters") + } + if filter.N() != filter3.N() { + t.Fatal("N doesn't match between copied filters") + } + serialized, err := filter.Bytes() + if err != nil { + t.Fatalf("Filter Bytes() failed: %v", err) + } + serialized2, err := filter2.Bytes() + if err != nil { + t.Fatalf("Filter Bytes() failed: %v", err) + } + if !bytes.Equal(serialized, serialized2) { + t.Fatal("Bytes don't match between copied filters") + } + serialized3, err := filter3.Bytes() + if err != nil { + t.Fatalf("Filter Bytes() failed: %v", err) + } + if !bytes.Equal(serialized, serialized3) { + t.Fatal("Bytes don't match between copied filters") + } + serialized4, err := filter3.Bytes() + if err != nil { + t.Fatalf("Filter Bytes() failed: %v", err) + } + if !bytes.Equal(serialized, serialized4) { + t.Fatal("Bytes don't match between copied filters") + } +} + +// TestGCSFilterMatch checks that both the built and copied filters match +// correctly, logging any false positives without failing on them. +func TestGCSFilterMatch(t *testing.T) { + match, err := filter.Match(key, []byte("Nate")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + match, err = filter2.Match(key, []byte("Nate")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + match, err = filter.Match(key, []byte("Quentin")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + match, err = filter2.Match(key, []byte("Quentin")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if !match { + t.Fatal("Filter didn't match when it should have!") + } + match, err = filter.Match(key, []byte("Nates")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if match { + t.Logf("False positive match, should be 1 in 2**%d!", P) + } + match, err = filter2.Match(key, []byte("Nates")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if match { + t.Logf("False positive match, should be 1 in 2**%d!", P) + } + match, err = filter.Match(key, []byte("Quentins")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if match { + t.Logf("False positive match, should be 1 in 2**%d!", P) + } + match, err = filter2.Match(key, []byte("Quentins")) + if err != nil { + t.Fatalf("Filter match failed: %s", err.Error()) + } + if match { + t.Logf("False positive match, should be 1 in 2**%d!", P) + } +} + +// AnyMatcher is the function signature of our matching algorithms. +type AnyMatcher func(key [gcs.KeySize]byte, data [][]byte) (bool, error) + +// TestGCSFilterMatchAnySuite checks that all of our matching algorithms +// properly match a list correctly when using built or copied filters, logging +// any false positives without failing on them. +func TestGCSFilterMatchAnySuite(t *testing.T) { + funcs := []struct { + name string + matchAny func(*gcs.Filter) AnyMatcher + }{ + { + "default", + func(f *gcs.Filter) AnyMatcher { + return f.MatchAny + }, + }, + { + "hash", + func(f *gcs.Filter) AnyMatcher { + return f.HashMatchAny + }, + }, + { + "zip", + func(f *gcs.Filter) AnyMatcher { + return f.ZipMatchAny + }, + }, + } + + for _, test := range funcs { + test := test + + t.Run(test.name, func(t *testing.T) { + contentsCopy := make([][]byte, len(contents2)) + copy(contentsCopy, contents2) + + match, err := test.matchAny(filter)(key, contentsCopy) + if err != nil { + t.Fatalf("Filter match any failed: %s", err.Error()) + } + if match { + t.Logf("False positive match, should be 1 in 2**%d!", P) + } + match, err = test.matchAny(filter2)(key, contentsCopy) + if err != nil { + t.Fatalf("Filter match any failed: %s", err.Error()) + } + if match { + t.Logf("False positive match, should be 1 in 2**%d!", P) + } + contentsCopy = append(contentsCopy, []byte("Nate")) + match, err = test.matchAny(filter)(key, contentsCopy) + if err != nil { + t.Fatalf("Filter match any failed: %s", err.Error()) + } + if !match { + t.Fatal("Filter didn't match any when it should have!") + } + match, err = test.matchAny(filter2)(key, contentsCopy) + if err != nil { + t.Fatalf("Filter match any failed: %s", err.Error()) + } + if !match { + t.Fatal("Filter didn't match any when it should have!") + } + }) + } +} diff --git a/btcutil/gcs/gcsbench_test.go b/btcutil/gcs/gcsbench_test.go new file mode 100644 index 0000000000..14125a16c0 --- /dev/null +++ b/btcutil/gcs/gcsbench_test.go @@ -0,0 +1,237 @@ +// Copyright (c) 2016-2017 The btcsuite developers +// Copyright (c) 2016-2017 The Lightning Network Developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package gcs_test + +import ( + "encoding/binary" + "math/rand" + "testing" + + "github.com/btcsuite/btcd/btcutil/gcs" +) + +func genRandFilterElements(numElements uint) ([][]byte, error) { + testContents := make([][]byte, numElements) + for i := range testContents { + randElem := make([]byte, 32) + if _, err := rand.Read(randElem); err != nil { + return nil, err + } + testContents[i] = randElem + } + + return testContents, nil +} + +var ( + generatedFilter *gcs.Filter +) + +// BenchmarkGCSFilterBuild benchmarks building a filter. +func BenchmarkGCSFilterBuild50000(b *testing.B) { + var testKey [gcs.KeySize]byte + for i := 0; i < gcs.KeySize; i += 4 { + binary.BigEndian.PutUint32(testKey[i:], rand.Uint32()) + } + + randFilterElems, genErr := genRandFilterElements(50000) + if err != nil { + b.Fatalf("unable to generate random item: %v", genErr) + } + + b.ReportAllocs() + b.ResetTimer() + + var localFilter *gcs.Filter + for i := 0; i < b.N; i++ { + localFilter, err = gcs.BuildGCSFilter( + P, M, key, randFilterElems, + ) + if err != nil { + b.Fatalf("unable to generate filter: %v", err) + } + } + generatedFilter = localFilter +} + +// BenchmarkGCSFilterBuild benchmarks building a filter. +func BenchmarkGCSFilterBuild100000(b *testing.B) { + var testKey [gcs.KeySize]byte + for i := 0; i < gcs.KeySize; i += 4 { + binary.BigEndian.PutUint32(testKey[i:], rand.Uint32()) + } + + randFilterElems, genErr := genRandFilterElements(100000) + if err != nil { + b.Fatalf("unable to generate random item: %v", genErr) + } + + b.ReportAllocs() + b.ResetTimer() + + var localFilter *gcs.Filter + for i := 0; i < b.N; i++ { + localFilter, err = gcs.BuildGCSFilter( + P, M, key, randFilterElems, + ) + if err != nil { + b.Fatalf("unable to generate filter: %v", err) + } + } + generatedFilter = localFilter +} + +var ( + match bool +) + +// BenchmarkGCSFilterMatch benchmarks querying a filter for a single value. +func BenchmarkGCSFilterMatch(b *testing.B) { + filter, err := gcs.BuildGCSFilter(P, M, key, contents) + if err != nil { + b.Fatalf("Failed to build filter") + } + + b.ReportAllocs() + b.ResetTimer() + + var localMatch bool + for i := 0; i < b.N; i++ { + _, err = filter.Match(key, []byte("Nate")) + if err != nil { + b.Fatalf("unable to match filter: %v", err) + } + + localMatch, err = filter.Match(key, []byte("Nates")) + if err != nil { + b.Fatalf("unable to match filter: %v", err) + } + } + match = localMatch +} + +var ( + randElems100, _ = genRandFilterElements(100) + randElems1000, _ = genRandFilterElements(1000) + randElems10000, _ = genRandFilterElements(10000) + randElems100000, _ = genRandFilterElements(100000) + randElems1000000, _ = genRandFilterElements(1000000) + randElems10000000, _ = genRandFilterElements(10000000) + + filterElems1000, _ = genRandFilterElements(1000) + filter1000, _ = gcs.BuildGCSFilter(P, M, key, filterElems1000) + filterElems5000, _ = genRandFilterElements(5000) + filter5000, _ = gcs.BuildGCSFilter(P, M, key, filterElems5000) + filterElems10000, _ = genRandFilterElements(10000) + filter10000, _ = gcs.BuildGCSFilter(P, M, key, filterElems10000) +) + +// matchAnyBenchmarks contains combinations of random filters and queries used +// to measure performance of various MatchAny implementations. +var matchAnyBenchmarks = []struct { + name string + query [][]byte + filter *gcs.Filter +}{ + {"q100-f1K", randElems100, filter1000}, + {"q1K-f1K", randElems1000, filter1000}, + {"q10K-f1K", randElems10000, filter1000}, + {"q100K-f1K", randElems100000, filter1000}, + {"q1M-f1K", randElems1000000, filter1000}, + {"q10M-f1K", randElems10000000, filter1000}, + + {"q100-f5K", randElems100, filter5000}, + {"q1K-f5K", randElems1000, filter5000}, + {"q10K-f5K", randElems10000, filter5000}, + {"q100K-f5K", randElems100000, filter5000}, + {"q1M-f5K", randElems1000000, filter5000}, + {"q10M-f5K", randElems10000000, filter5000}, + + {"q100-f10K", randElems100, filter10000}, + {"q1K-f10K", randElems1000, filter10000}, + {"q10K-f10K", randElems10000, filter10000}, + {"q100K-f10K", randElems100000, filter10000}, + {"q1M-f10K", randElems1000000, filter10000}, + {"q10M-f10K", randElems10000000, filter10000}, +} + +// BenchmarkGCSFilterMatchAny benchmarks the sort-and-zip MatchAny impl. +func BenchmarkGCSFilterZipMatchAny(b *testing.B) { + for _, test := range matchAnyBenchmarks { + test := test + + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + + var ( + localMatch bool + err error + ) + + for i := 0; i < b.N; i++ { + localMatch, err = test.filter.ZipMatchAny( + key, test.query, + ) + if err != nil { + b.Fatalf("unable to match filter: %v", err) + } + } + match = localMatch + }) + } +} + +// BenchmarkGCSFilterMatchAny benchmarks the hash-join MatchAny impl. +func BenchmarkGCSFilterHashMatchAny(b *testing.B) { + for _, test := range matchAnyBenchmarks { + test := test + + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + + var ( + localMatch bool + err error + ) + + for i := 0; i < b.N; i++ { + localMatch, err = test.filter.HashMatchAny( + key, test.query, + ) + if err != nil { + b.Fatalf("unable to match filter: %v", err) + } + } + match = localMatch + }) + } +} + +// BenchmarkGCSFilterMatchAny benchmarks the hybrid MatchAny impl. +func BenchmarkGCSFilterMatchAny(b *testing.B) { + for _, test := range matchAnyBenchmarks { + test := test + + b.Run(test.name, func(b *testing.B) { + b.ReportAllocs() + + var ( + localMatch bool + err error + ) + + for i := 0; i < b.N; i++ { + localMatch, err = test.filter.MatchAny( + key, test.query, + ) + if err != nil { + b.Fatalf("unable to match filter: %v", err) + } + } + match = localMatch + }) + } +} diff --git a/btcutil/go.mod b/btcutil/go.mod new file mode 100644 index 0000000000..8d3c35b7e4 --- /dev/null +++ b/btcutil/go.mod @@ -0,0 +1,13 @@ +module github.com/btcsuite/btcd/btcutil + +go 1.16 + +require ( + github.com/aead/siphash v1.0.1 + github.com/btcsuite/btcd v0.20.1-beta + github.com/davecgh/go-spew v1.1.1 + github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 +) + +replace github.com/btcsuite/btcd => ../ diff --git a/btcutil/go.sum b/btcutil/go.sum new file mode 100644 index 0000000000..58fe70e411 --- /dev/null +++ b/btcutil/go.sum @@ -0,0 +1,43 @@ +github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/hash160.go b/btcutil/hash160.go new file mode 100644 index 0000000000..fa26e09bf9 --- /dev/null +++ b/btcutil/hash160.go @@ -0,0 +1,23 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "crypto/sha256" + "hash" + + "golang.org/x/crypto/ripemd160" +) + +// Calculate the hash of hasher over buf. +func calcHash(buf []byte, hasher hash.Hash) []byte { + _, _ = hasher.Write(buf) + return hasher.Sum(nil) +} + +// Hash160 calculates the hash ripemd160(sha256(b)). +func Hash160(buf []byte) []byte { + return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) +} diff --git a/btcutil/hdkeychain/README.md b/btcutil/hdkeychain/README.md new file mode 100644 index 0000000000..eaf57d7c58 --- /dev/null +++ b/btcutil/hdkeychain/README.md @@ -0,0 +1,59 @@ +hdkeychain +========== + +[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)](https://travis-ci.org/btcsuite/btcutil) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/btcutil/hdkeychain) + +Package hdkeychain provides an API for bitcoin hierarchical deterministic +extended keys (BIP0032). + +A comprehensive suite of tests is provided to ensure proper functionality. See +`test_coverage.txt` for the gocov coverage report. Alternatively, if you are +running a POSIX OS, you can run the `cov_report.sh` script for a real-time +report. + +## Feature Overview + +- Full BIP0032 implementation +- Single type for private and public extended keys +- Convenient cryptograpically secure seed generation +- Simple creation of master nodes +- Support for multi-layer derivation +- Easy serialization and deserialization for both private and public extended + keys +- Support for custom networks by registering them with chaincfg +- Obtaining the underlying EC pubkeys, EC privkeys, and associated bitcoin + addresses ties in seamlessly with existing btcec and btcutil types which + provide powerful tools for working with them to do things like sign + transations and generate payment scripts +- Uses the btcec package which is highly optimized for secp256k1 +- Code examples including: + - Generating a cryptographically secure random seed and deriving a + master node from it + - Default HD wallet layout as described by BIP0032 + - Audits use case as described by BIP0032 +- Comprehensive test coverage including the BIP0032 test vectors +- Benchmarks + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil/hdkeychain +``` + +## Examples + +* [NewMaster Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/hdkeychain#example-NewMaster) + Demonstrates how to generate a cryptographically random seed then use it to + create a new master node (extended key). +* [Default Wallet Layout Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/hdkeychain#example-package--DefaultWalletLayout) + Demonstrates the default hierarchical deterministic wallet layout as described + in BIP0032. +* [Audits Use Case Example](http://godoc.org/github.com/btcsuite/btcd/btcutil/hdkeychain#example-package--Audits) + Demonstrates the audits use case in BIP0032. + +## License + +Package hdkeychain is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/hdkeychain/bench_test.go b/btcutil/hdkeychain/bench_test.go new file mode 100644 index 0000000000..285ef3e8d6 --- /dev/null +++ b/btcutil/hdkeychain/bench_test.go @@ -0,0 +1,84 @@ +// Copyright (c) 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package hdkeychain_test + +import ( + "testing" + + "github.com/btcsuite/btcd/btcutil/hdkeychain" +) + +// bip0032MasterPriv1 is the master private extended key from the first set of +// test vectors in BIP0032. +const bip0032MasterPriv1 = "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbP" + + "y6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" + +// BenchmarkDeriveHardened benchmarks how long it takes to derive a hardened +// child from a master private extended key. +func BenchmarkDeriveHardened(b *testing.B) { + b.StopTimer() + masterKey, err := hdkeychain.NewKeyFromString(bip0032MasterPriv1) + if err != nil { + b.Errorf("Failed to decode master seed: %v", err) + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + _, _ = masterKey.Derive(hdkeychain.HardenedKeyStart) + } +} + +// BenchmarkDeriveNormal benchmarks how long it takes to derive a normal +// (non-hardened) child from a master private extended key. +func BenchmarkDeriveNormal(b *testing.B) { + b.StopTimer() + masterKey, err := hdkeychain.NewKeyFromString(bip0032MasterPriv1) + if err != nil { + b.Errorf("Failed to decode master seed: %v", err) + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + _, _ = masterKey.Derive(0) + } +} + +// BenchmarkPrivToPub benchmarks how long it takes to convert a private extended +// key to a public extended key. +func BenchmarkPrivToPub(b *testing.B) { + b.StopTimer() + masterKey, err := hdkeychain.NewKeyFromString(bip0032MasterPriv1) + if err != nil { + b.Errorf("Failed to decode master seed: %v", err) + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + _, _ = masterKey.Neuter() + } +} + +// BenchmarkDeserialize benchmarks how long it takes to deserialize a private +// extended key. +func BenchmarkDeserialize(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = hdkeychain.NewKeyFromString(bip0032MasterPriv1) + } +} + +// BenchmarkSerialize benchmarks how long it takes to serialize a private +// extended key. +func BenchmarkSerialize(b *testing.B) { + b.StopTimer() + masterKey, err := hdkeychain.NewKeyFromString(bip0032MasterPriv1) + if err != nil { + b.Errorf("Failed to decode master seed: %v", err) + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + _ = masterKey.String() + } +} diff --git a/btcutil/hdkeychain/cov_report.sh b/btcutil/hdkeychain/cov_report.sh new file mode 100644 index 0000000000..307f05b76c --- /dev/null +++ b/btcutil/hdkeychain/cov_report.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +# This script uses gocov to generate a test coverage report. +# The gocov tool my be obtained with the following command: +# go get github.com/axw/gocov/gocov +# +# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH. + +# Check for gocov. +type gocov >/dev/null 2>&1 +if [ $? -ne 0 ]; then + echo >&2 "This script requires the gocov tool." + echo >&2 "You may obtain it with the following command:" + echo >&2 "go get github.com/axw/gocov/gocov" + exit 1 +fi +gocov test | gocov report diff --git a/btcutil/hdkeychain/doc.go b/btcutil/hdkeychain/doc.go new file mode 100644 index 0000000000..dcf74f6b51 --- /dev/null +++ b/btcutil/hdkeychain/doc.go @@ -0,0 +1,84 @@ +// Copyright (c) 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package hdkeychain provides an API for bitcoin hierarchical deterministic +extended keys (BIP0032). + +Overview + +The ability to implement hierarchical deterministic wallets depends on the +ability to create and derive hierarchical deterministic extended keys. + +At a high level, this package provides support for those hierarchical +deterministic extended keys by providing an ExtendedKey type and supporting +functions. Each extended key can either be a private or public extended key +which itself is capable of deriving a child extended key. + +Determining the Extended Key Type + +Whether an extended key is a private or public extended key can be determined +with the IsPrivate function. + +Transaction Signing Keys and Payment Addresses + +In order to create and sign transactions, or provide others with addresses to +send funds to, the underlying key and address material must be accessible. This +package provides the ECPubKey, ECPrivKey, and Address functions for this +purpose. + +The Master Node + +As previously mentioned, the extended keys are hierarchical meaning they are +used to form a tree. The root of that tree is called the master node and this +package provides the NewMaster function to create it from a cryptographically +random seed. The GenerateSeed function is provided as a convenient way to +create a random seed for use with the NewMaster function. + +Deriving Children + +Once you have created a tree root (or have deserialized an extended key as +discussed later), the child extended keys can be derived by using the Derive +function. The Derive function supports deriving both normal (non-hardened) and +hardened child extended keys. In order to derive a hardened extended key, use +the HardenedKeyStart constant + the hardened key number as the index to the +Derive function. This provides the ability to cascade the keys into a tree and +hence generate the hierarchical deterministic key chains. + +Normal vs Hardened Derived Extended Keys + +A private extended key can be used to derive both hardened and non-hardened +(normal) child private and public extended keys. A public extended key can only +be used to derive non-hardened child public extended keys. As enumerated in +BIP0032 "knowledge of the extended public key plus any non-hardened private key +descending from it is equivalent to knowing the extended private key (and thus +every private and public key descending from it). This means that extended +public keys must be treated more carefully than regular public keys. It is also +the reason for the existence of hardened keys, and why they are used for the +account level in the tree. This way, a leak of an account-specific (or below) +private key never risks compromising the master or other accounts." + +Neutering a Private Extended Key + +A private extended key can be converted to a new instance of the corresponding +public extended key with the Neuter function. The original extended key is not +modified. A public extended key is still capable of deriving non-hardened child +public extended keys. + +Serializing and Deserializing Extended Keys + +Extended keys are serialized and deserialized with the String and +NewKeyFromString functions. The serialized key is a Base58-encoded string which +looks like the following: + public key: xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw + private key: xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 + +Network + +Extended keys are much like normal Bitcoin addresses in that they have version +bytes which tie them to a specific network. The SetNet and IsForNet functions +are provided to set and determinine which network an extended key is associated +with. +*/ +package hdkeychain diff --git a/btcutil/hdkeychain/example_test.go b/btcutil/hdkeychain/example_test.go new file mode 100644 index 0000000000..7489d387a7 --- /dev/null +++ b/btcutil/hdkeychain/example_test.go @@ -0,0 +1,182 @@ +// Copyright (c) 2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package hdkeychain_test + +import ( + "fmt" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/btcutil/hdkeychain" +) + +// This example demonstrates how to generate a cryptographically random seed +// then use it to create a new master node (extended key). +func ExampleNewMaster() { + // Generate a random seed at the recommended length. + seed, err := hdkeychain.GenerateSeed(hdkeychain.RecommendedSeedLen) + if err != nil { + fmt.Println(err) + return + } + + // Generate a new master node using the seed. + key, err := hdkeychain.NewMaster(seed, &chaincfg.MainNetParams) + if err != nil { + fmt.Println(err) + return + } + + // Show that the generated master node extended key is private. + fmt.Println("Private Extended Key?:", key.IsPrivate()) + + // Output: + // Private Extended Key?: true +} + +// This example demonstrates the default hierarchical deterministic wallet +// layout as described in BIP0032. +func Example_defaultWalletLayout() { + // The default wallet layout described in BIP0032 is: + // + // Each account is composed of two keypair chains: an internal and an + // external one. The external keychain is used to generate new public + // addresses, while the internal keychain is used for all other + // operations (change addresses, generation addresses, ..., anything + // that doesn't need to be communicated). + // + // * m/iH/0/k + // corresponds to the k'th keypair of the external chain of account + // number i of the HDW derived from master m. + // * m/iH/1/k + // corresponds to the k'th keypair of the internal chain of account + // number i of the HDW derived from master m. + + // Ordinarily this would either be read from some encrypted source + // and be decrypted or generated as the NewMaster example shows, but + // for the purposes of this example, the private extended key for the + // master node is being hard coded here. + master := "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jP" + + "PqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" + + // Start by getting an extended key instance for the master node. + // This gives the path: + // m + masterKey, err := hdkeychain.NewKeyFromString(master) + if err != nil { + fmt.Println(err) + return + } + + // Derive the extended key for account 0. This gives the path: + // m/0H + acct0, err := masterKey.Derive(hdkeychain.HardenedKeyStart + 0) + if err != nil { + fmt.Println(err) + return + } + + // Derive the extended key for the account 0 external chain. This + // gives the path: + // m/0H/0 + acct0Ext, err := acct0.Derive(0) + if err != nil { + fmt.Println(err) + return + } + + // Derive the extended key for the account 0 internal chain. This gives + // the path: + // m/0H/1 + acct0Int, err := acct0.Derive(1) + if err != nil { + fmt.Println(err) + return + } + + // At this point, acct0Ext and acct0Int are ready to derive the keys for + // the external and internal wallet chains. + + // Derive the 10th extended key for the account 0 external chain. This + // gives the path: + // m/0H/0/10 + acct0Ext10, err := acct0Ext.Derive(10) + if err != nil { + fmt.Println(err) + return + } + + // Derive the 1st extended key for the account 0 internal chain. This + // gives the path: + // m/0H/1/0 + acct0Int0, err := acct0Int.Derive(0) + if err != nil { + fmt.Println(err) + return + } + + // Get and show the address associated with the extended keys for the + // main bitcoin network. + acct0ExtAddr, err := acct0Ext10.Address(&chaincfg.MainNetParams) + if err != nil { + fmt.Println(err) + return + } + acct0IntAddr, err := acct0Int0.Address(&chaincfg.MainNetParams) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("Account 0 External Address 10:", acct0ExtAddr) + fmt.Println("Account 0 Internal Address 0:", acct0IntAddr) + + // Output: + // Account 0 External Address 10: 1HVccubUT8iKTapMJ5AnNA4sLRN27xzQ4F + // Account 0 Internal Address 0: 1J5rebbkQaunJTUoNVREDbeB49DqMNFFXk +} + +// This example demonstrates the audits use case in BIP0032. +func Example_audits() { + // The audits use case described in BIP0032 is: + // + // In case an auditor needs full access to the list of incoming and + // outgoing payments, one can share all account public extended keys. + // This will allow the auditor to see all transactions from and to the + // wallet, in all accounts, but not a single secret key. + // + // * N(m/*) + // corresponds to the neutered master extended key (also called + // the master public extended key) + + // Ordinarily this would either be read from some encrypted source + // and be decrypted or generated as the NewMaster example shows, but + // for the purposes of this example, the private extended key for the + // master node is being hard coded here. + master := "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jP" + + "PqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" + + // Start by getting an extended key instance for the master node. + // This gives the path: + // m + masterKey, err := hdkeychain.NewKeyFromString(master) + if err != nil { + fmt.Println(err) + return + } + + // Neuter the master key to generate a master public extended key. This + // gives the path: + // N(m/*) + masterPubKey, err := masterKey.Neuter() + if err != nil { + fmt.Println(err) + return + } + + // Share the master public extended key with the auditor. + fmt.Println("Audit key N(m/*):", masterPubKey) + + // Output: + // Audit key N(m/*): xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8 +} diff --git a/btcutil/hdkeychain/extendedkey.go b/btcutil/hdkeychain/extendedkey.go new file mode 100644 index 0000000000..4145c5c23e --- /dev/null +++ b/btcutil/hdkeychain/extendedkey.go @@ -0,0 +1,706 @@ +// Copyright (c) 2014-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package hdkeychain + +// References: +// [BIP32]: BIP0032 - Hierarchical Deterministic Wallets +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki + +import ( + "bytes" + "crypto/hmac" + "crypto/rand" + "crypto/sha512" + "encoding/binary" + "errors" + "fmt" + "math/big" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/base58" +) + +const ( + // RecommendedSeedLen is the recommended length in bytes for a seed + // to a master node. + RecommendedSeedLen = 32 // 256 bits + + // HardenedKeyStart is the index at which a hardened key starts. Each + // extended key has 2^31 normal child keys and 2^31 hardened child keys. + // Thus the range for normal child keys is [0, 2^31 - 1] and the range + // for hardened child keys is [2^31, 2^32 - 1]. + HardenedKeyStart = 0x80000000 // 2^31 + + // MinSeedBytes is the minimum number of bytes allowed for a seed to + // a master node. + MinSeedBytes = 16 // 128 bits + + // MaxSeedBytes is the maximum number of bytes allowed for a seed to + // a master node. + MaxSeedBytes = 64 // 512 bits + + // serializedKeyLen is the length of a serialized public or private + // extended key. It consists of 4 bytes version, 1 byte depth, 4 bytes + // fingerprint, 4 bytes child number, 32 bytes chain code, and 33 bytes + // public/private key data. + serializedKeyLen = 4 + 1 + 4 + 4 + 32 + 33 // 78 bytes + + // maxUint8 is the max positive integer which can be serialized in a uint8 + maxUint8 = 1<<8 - 1 +) + +var ( + // ErrDeriveHardFromPublic describes an error in which the caller + // attempted to derive a hardened extended key from a public key. + ErrDeriveHardFromPublic = errors.New("cannot derive a hardened key " + + "from a public key") + + // ErrDeriveBeyondMaxDepth describes an error in which the caller + // has attempted to derive more than 255 keys from a root key. + ErrDeriveBeyondMaxDepth = errors.New("cannot derive a key with more than " + + "255 indices in its path") + + // ErrNotPrivExtKey describes an error in which the caller attempted + // to extract a private key from a public extended key. + ErrNotPrivExtKey = errors.New("unable to create private keys from a " + + "public extended key") + + // ErrInvalidChild describes an error in which the child at a specific + // index is invalid due to the derived key falling outside of the valid + // range for secp256k1 private keys. This error indicates the caller + // should simply ignore the invalid child extended key at this index and + // increment to the next index. + ErrInvalidChild = errors.New("the extended key at this index is invalid") + + // ErrUnusableSeed describes an error in which the provided seed is not + // usable due to the derived key falling outside of the valid range for + // secp256k1 private keys. This error indicates the caller must choose + // another seed. + ErrUnusableSeed = errors.New("unusable seed") + + // ErrInvalidSeedLen describes an error in which the provided seed or + // seed length is not in the allowed range. + ErrInvalidSeedLen = fmt.Errorf("seed length must be between %d and %d "+ + "bits", MinSeedBytes*8, MaxSeedBytes*8) + + // ErrBadChecksum describes an error in which the checksum encoded with + // a serialized extended key does not match the calculated value. + ErrBadChecksum = errors.New("bad extended key checksum") + + // ErrInvalidKeyLen describes an error in which the provided serialized + // key is not the expected length. + ErrInvalidKeyLen = errors.New("the provided serialized extended key " + + "length is invalid") +) + +// masterKey is the master key used along with a random seed used to generate +// the master node in the hierarchical tree. +var masterKey = []byte("Bitcoin seed") + +// ExtendedKey houses all the information needed to support a hierarchical +// deterministic extended key. See the package overview documentation for +// more details on how to use extended keys. +type ExtendedKey struct { + key []byte // This will be the pubkey for extended pub keys + pubKey []byte // This will only be set for extended priv keys + chainCode []byte + depth uint8 + parentFP []byte + childNum uint32 + version []byte + isPrivate bool +} + +// NewExtendedKey returns a new instance of an extended key with the given +// fields. No error checking is performed here as it's only intended to be a +// convenience method used to create a populated struct. This function should +// only be used by applications that need to create custom ExtendedKeys. All +// other applications should just use NewMaster, Derive, or Neuter. +func NewExtendedKey(version, key, chainCode, parentFP []byte, depth uint8, + childNum uint32, isPrivate bool) *ExtendedKey { + + // NOTE: The pubKey field is intentionally left nil so it is only + // computed and memoized as required. + return &ExtendedKey{ + key: key, + chainCode: chainCode, + depth: depth, + parentFP: parentFP, + childNum: childNum, + version: version, + isPrivate: isPrivate, + } +} + +// pubKeyBytes returns bytes for the serialized compressed public key associated +// with this extended key in an efficient manner including memoization as +// necessary. +// +// When the extended key is already a public key, the key is simply returned as +// is since it's already in the correct form. However, when the extended key is +// a private key, the public key will be calculated and memoized so future +// accesses can simply return the cached result. +func (k *ExtendedKey) pubKeyBytes() []byte { + // Just return the key if it's already an extended public key. + if !k.isPrivate { + return k.key + } + + // This is a private extended key, so calculate and memoize the public + // key if needed. + if len(k.pubKey) == 0 { + pkx, pky := btcec.S256().ScalarBaseMult(k.key) + pubKey := btcec.PublicKey{Curve: btcec.S256(), X: pkx, Y: pky} + k.pubKey = pubKey.SerializeCompressed() + } + + return k.pubKey +} + +// IsPrivate returns whether or not the extended key is a private extended key. +// +// A private extended key can be used to derive both hardened and non-hardened +// child private and public extended keys. A public extended key can only be +// used to derive non-hardened child public extended keys. +func (k *ExtendedKey) IsPrivate() bool { + return k.isPrivate +} + +// Depth returns the current derivation level with respect to the root. +// +// The root key has depth zero, and the field has a maximum of 255 due to +// how depth is serialized. +func (k *ExtendedKey) Depth() uint8 { + return k.depth +} + +// Version returns the extended key's hardened derivation version. This can be +// used to identify the extended key's type. +func (k *ExtendedKey) Version() []byte { + return k.version +} + +// ParentFingerprint returns a fingerprint of the parent extended key from which +// this one was derived. +func (k *ExtendedKey) ParentFingerprint() uint32 { + return binary.BigEndian.Uint32(k.parentFP) +} + +// ChainCode returns the chain code part of this extended key. +// +// It is identical for both public and private extended keys. +func (k *ExtendedKey) ChainCode() []byte { + return append([]byte{}, k.chainCode...) +} + +// Derive returns a derived child extended key at the given index. +// +// IMPORTANT: if you were previously using the Child method, this method is incompatible. +// The Child method had a BIP-32 standard compatibility issue. You have to check whether +// any hardened derivations in your derivation path are affected by this issue, via the +// IsAffectedByIssue172 method and migrate the wallet if so. This method does conform +// to the standard. If you need the old behavior, use DeriveNonStandard. +// +// When this extended key is a private extended key (as determined by the IsPrivate +// function), a private extended key will be derived. Otherwise, the derived +// extended key will be also be a public extended key. +// +// When the index is greater to or equal than the HardenedKeyStart constant, the +// derived extended key will be a hardened extended key. It is only possible to +// derive a hardened extended key from a private extended key. Consequently, +// this function will return ErrDeriveHardFromPublic if a hardened child +// extended key is requested from a public extended key. +// +// A hardened extended key is useful since, as previously mentioned, it requires +// a parent private extended key to derive. In other words, normal child +// extended public keys can be derived from a parent public extended key (no +// knowledge of the parent private key) whereas hardened extended keys may not +// be. +// +// NOTE: There is an extremely small chance (< 1 in 2^127) the specific child +// index does not derive to a usable child. The ErrInvalidChild error will be +// returned if this should occur, and the caller is expected to ignore the +// invalid child and simply increment to the next index. +func (k *ExtendedKey) Derive(i uint32) (*ExtendedKey, error) { + // Prevent derivation of children beyond the max allowed depth. + if k.depth == maxUint8 { + return nil, ErrDeriveBeyondMaxDepth + } + + // There are four scenarios that could happen here: + // 1) Private extended key -> Hardened child private extended key + // 2) Private extended key -> Non-hardened child private extended key + // 3) Public extended key -> Non-hardened child public extended key + // 4) Public extended key -> Hardened child public extended key (INVALID!) + + // Case #4 is invalid, so error out early. + // A hardened child extended key may not be created from a public + // extended key. + isChildHardened := i >= HardenedKeyStart + if !k.isPrivate && isChildHardened { + return nil, ErrDeriveHardFromPublic + } + + // The data used to derive the child key depends on whether or not the + // child is hardened per [BIP32]. + // + // For hardened children: + // 0x00 || ser256(parentKey) || ser32(i) + // + // For normal children: + // serP(parentPubKey) || ser32(i) + keyLen := 33 + data := make([]byte, keyLen+4) + if isChildHardened { + // Case #1. + // When the child is a hardened child, the key is known to be a + // private key due to the above early return. Pad it with a + // leading zero as required by [BIP32] for deriving the child. + // Additionally, right align it if it's shorter than 32 bytes. + offset := 33 - len(k.key) + copy(data[offset:], k.key) + } else { + // Case #2 or #3. + // This is either a public or private extended key, but in + // either case, the data which is used to derive the child key + // starts with the secp256k1 compressed public key bytes. + copy(data, k.pubKeyBytes()) + } + binary.BigEndian.PutUint32(data[keyLen:], i) + + // Take the HMAC-SHA512 of the current key's chain code and the derived + // data: + // I = HMAC-SHA512(Key = chainCode, Data = data) + hmac512 := hmac.New(sha512.New, k.chainCode) + _, _ = hmac512.Write(data) + ilr := hmac512.Sum(nil) + + // Split "I" into two 32-byte sequences Il and Ir where: + // Il = intermediate key used to derive the child + // Ir = child chain code + il := ilr[:len(ilr)/2] + childChainCode := ilr[len(ilr)/2:] + + // Both derived public or private keys rely on treating the left 32-byte + // sequence calculated above (Il) as a 256-bit integer that must be + // within the valid range for a secp256k1 private key. There is a small + // chance (< 1 in 2^127) this condition will not hold, and in that case, + // a child extended key can't be created for this index and the caller + // should simply increment to the next index. + ilNum := new(big.Int).SetBytes(il) + if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { + return nil, ErrInvalidChild + } + + // The algorithm used to derive the child key depends on whether or not + // a private or public child is being derived. + // + // For private children: + // childKey = parse256(Il) + parentKey + // + // For public children: + // childKey = serP(point(parse256(Il)) + parentKey) + var isPrivate bool + var childKey []byte + if k.isPrivate { + // Case #1 or #2. + // Add the parent private key to the intermediate private key to + // derive the final child key. + // + // childKey = parse256(Il) + parenKey + keyNum := new(big.Int).SetBytes(k.key) + ilNum.Add(ilNum, keyNum) + ilNum.Mod(ilNum, btcec.S256().N) + childKey = ilNum.Bytes() + isPrivate = true + } else { + // Case #3. + // Calculate the corresponding intermediate public key for + // intermediate private key. + ilx, ily := btcec.S256().ScalarBaseMult(il) + if ilx.Sign() == 0 || ily.Sign() == 0 { + return nil, ErrInvalidChild + } + + // Convert the serialized compressed parent public key into X + // and Y coordinates so it can be added to the intermediate + // public key. + pubKey, err := btcec.ParsePubKey(k.key, btcec.S256()) + if err != nil { + return nil, err + } + + // Add the intermediate public key to the parent public key to + // derive the final child key. + // + // childKey = serP(point(parse256(Il)) + parentKey) + childX, childY := btcec.S256().Add(ilx, ily, pubKey.X, pubKey.Y) + pk := btcec.PublicKey{Curve: btcec.S256(), X: childX, Y: childY} + childKey = pk.SerializeCompressed() + } + + // The fingerprint of the parent for the derived child is the first 4 + // bytes of the RIPEMD160(SHA256(parentPubKey)). + parentFP := btcutil.Hash160(k.pubKeyBytes())[:4] + return NewExtendedKey(k.version, childKey, childChainCode, parentFP, + k.depth+1, i, isPrivate), nil +} + +// Returns true if this key was affected by the BIP-32 issue in the Child +// method (since renamed to DeriveNonStandard). +func (k *ExtendedKey) IsAffectedByIssue172() bool { + return len(k.key) < 32 +} + +// Deprecated: This is a non-standard derivation that is affected by issue #172. +// 1-of-256 hardened derivations will be wrong. See note in the Derive method +// and IsAffectedByIssue172. +func (k *ExtendedKey) DeriveNonStandard(i uint32) (*ExtendedKey, error) { + if k.depth == maxUint8 { + return nil, ErrDeriveBeyondMaxDepth + } + + isChildHardened := i >= HardenedKeyStart + if !k.isPrivate && isChildHardened { + return nil, ErrDeriveHardFromPublic + } + + keyLen := 33 + data := make([]byte, keyLen+4) + if isChildHardened { + copy(data[1:], k.key) + } else { + copy(data, k.pubKeyBytes()) + } + binary.BigEndian.PutUint32(data[keyLen:], i) + + hmac512 := hmac.New(sha512.New, k.chainCode) + _, _ = hmac512.Write(data) + ilr := hmac512.Sum(nil) + + il := ilr[:len(ilr)/2] + childChainCode := ilr[len(ilr)/2:] + + ilNum := new(big.Int).SetBytes(il) + if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { + return nil, ErrInvalidChild + } + + var isPrivate bool + var childKey []byte + if k.isPrivate { + keyNum := new(big.Int).SetBytes(k.key) + ilNum.Add(ilNum, keyNum) + ilNum.Mod(ilNum, btcec.S256().N) + childKey = ilNum.Bytes() + isPrivate = true + } else { + ilx, ily := btcec.S256().ScalarBaseMult(il) + if ilx.Sign() == 0 || ily.Sign() == 0 { + return nil, ErrInvalidChild + } + + pubKey, err := btcec.ParsePubKey(k.key, btcec.S256()) + if err != nil { + return nil, err + } + + childX, childY := btcec.S256().Add(ilx, ily, pubKey.X, pubKey.Y) + pk := btcec.PublicKey{Curve: btcec.S256(), X: childX, Y: childY} + childKey = pk.SerializeCompressed() + } + + parentFP := btcutil.Hash160(k.pubKeyBytes())[:4] + return NewExtendedKey(k.version, childKey, childChainCode, parentFP, + k.depth+1, i, isPrivate), nil +} + +// ChildNum returns the index at which the child extended key was derived. +// +// Extended keys with ChildNum value between 0 and 2^31-1 are normal child +// keys, and those with a value between 2^31 and 2^32-1 are hardened keys. +func (k *ExtendedKey) ChildIndex() uint32 { + return k.childNum +} + +// Neuter returns a new extended public key from this extended private key. The +// same extended key will be returned unaltered if it is already an extended +// public key. +// +// As the name implies, an extended public key does not have access to the +// private key, so it is not capable of signing transactions or deriving +// child extended private keys. However, it is capable of deriving further +// child extended public keys. +func (k *ExtendedKey) Neuter() (*ExtendedKey, error) { + // Already an extended public key. + if !k.isPrivate { + return k, nil + } + + // Get the associated public extended key version bytes. + version, err := chaincfg.HDPrivateKeyToPublicKeyID(k.version) + if err != nil { + return nil, err + } + + // Convert it to an extended public key. The key for the new extended + // key will simply be the pubkey of the current extended private key. + // + // This is the function N((k,c)) -> (K, c) from [BIP32]. + return NewExtendedKey(version, k.pubKeyBytes(), k.chainCode, k.parentFP, + k.depth, k.childNum, false), nil +} + +// CloneWithVersion returns a new extended key cloned from this extended key, +// but using the provided HD version bytes. The version must be a private HD +// key ID for an extended private key, and a public HD key ID for an extended +// public key. +// +// This method creates a new copy and therefore does not mutate the original +// extended key instance. +// +// Unlike Neuter(), this does NOT convert an extended private key to an +// extended public key. It is particularly useful for converting between +// standard BIP0032 extended keys (serializable to xprv/xpub) and keys based +// on the SLIP132 standard (serializable to yprv/ypub, zprv/zpub, etc.). +// +// References: +// [SLIP132]: SLIP-0132 - Registered HD version bytes for BIP-0032 +// https://github.com/satoshilabs/slips/blob/master/slip-0132.md +func (k *ExtendedKey) CloneWithVersion(version []byte) (*ExtendedKey, error) { + if len(version) != 4 { + // TODO: The semantically correct error to return here is + // ErrInvalidHDKeyID (introduced in btcsuite/btcd#1617). Update the + // error type once available in a stable btcd / chaincfg release. + return nil, chaincfg.ErrUnknownHDKeyID + } + + // Initialize a new extended key instance with the same fields as the + // current extended private/public key and the provided HD version bytes. + return NewExtendedKey(version, k.key, k.chainCode, k.parentFP, + k.depth, k.childNum, k.isPrivate), nil +} + +// ECPubKey converts the extended key to a btcec public key and returns it. +func (k *ExtendedKey) ECPubKey() (*btcec.PublicKey, error) { + return btcec.ParsePubKey(k.pubKeyBytes(), btcec.S256()) +} + +// ECPrivKey converts the extended key to a btcec private key and returns it. +// As you might imagine this is only possible if the extended key is a private +// extended key (as determined by the IsPrivate function). The ErrNotPrivExtKey +// error will be returned if this function is called on a public extended key. +func (k *ExtendedKey) ECPrivKey() (*btcec.PrivateKey, error) { + if !k.isPrivate { + return nil, ErrNotPrivExtKey + } + + privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), k.key) + return privKey, nil +} + +// Address converts the extended key to a standard bitcoin pay-to-pubkey-hash +// address for the passed network. +func (k *ExtendedKey) Address(net *chaincfg.Params) (*btcutil.AddressPubKeyHash, error) { + pkHash := btcutil.Hash160(k.pubKeyBytes()) + return btcutil.NewAddressPubKeyHash(pkHash, net) +} + +// paddedAppend appends the src byte slice to dst, returning the new slice. +// If the length of the source is smaller than the passed size, leading zero +// bytes are appended to the dst slice before appending src. +func paddedAppend(size uint, dst, src []byte) []byte { + for i := 0; i < int(size)-len(src); i++ { + dst = append(dst, 0) + } + return append(dst, src...) +} + +// String returns the extended key as a human-readable base58-encoded string. +func (k *ExtendedKey) String() string { + if len(k.key) == 0 { + return "zeroed extended key" + } + + var childNumBytes [4]byte + binary.BigEndian.PutUint32(childNumBytes[:], k.childNum) + + // The serialized format is: + // version (4) || depth (1) || parent fingerprint (4)) || + // child num (4) || chain code (32) || key data (33) || checksum (4) + serializedBytes := make([]byte, 0, serializedKeyLen+4) + serializedBytes = append(serializedBytes, k.version...) + serializedBytes = append(serializedBytes, k.depth) + serializedBytes = append(serializedBytes, k.parentFP...) + serializedBytes = append(serializedBytes, childNumBytes[:]...) + serializedBytes = append(serializedBytes, k.chainCode...) + if k.isPrivate { + serializedBytes = append(serializedBytes, 0x00) + serializedBytes = paddedAppend(32, serializedBytes, k.key) + } else { + serializedBytes = append(serializedBytes, k.pubKeyBytes()...) + } + + checkSum := chainhash.DoubleHashB(serializedBytes)[:4] + serializedBytes = append(serializedBytes, checkSum...) + return base58.Encode(serializedBytes) +} + +// IsForNet returns whether or not the extended key is associated with the +// passed bitcoin network. +func (k *ExtendedKey) IsForNet(net *chaincfg.Params) bool { + return bytes.Equal(k.version, net.HDPrivateKeyID[:]) || + bytes.Equal(k.version, net.HDPublicKeyID[:]) +} + +// SetNet associates the extended key, and any child keys yet to be derived from +// it, with the passed network. +func (k *ExtendedKey) SetNet(net *chaincfg.Params) { + if k.isPrivate { + k.version = net.HDPrivateKeyID[:] + } else { + k.version = net.HDPublicKeyID[:] + } +} + +// zero sets all bytes in the passed slice to zero. This is used to +// explicitly clear private key material from memory. +func zero(b []byte) { + lenb := len(b) + for i := 0; i < lenb; i++ { + b[i] = 0 + } +} + +// Zero manually clears all fields and bytes in the extended key. This can be +// used to explicitly clear key material from memory for enhanced security +// against memory scraping. This function only clears this particular key and +// not any children that have already been derived. +func (k *ExtendedKey) Zero() { + zero(k.key) + zero(k.pubKey) + zero(k.chainCode) + zero(k.parentFP) + k.version = nil + k.key = nil + k.depth = 0 + k.childNum = 0 + k.isPrivate = false +} + +// NewMaster creates a new master node for use in creating a hierarchical +// deterministic key chain. The seed must be between 128 and 512 bits and +// should be generated by a cryptographically secure random generation source. +// +// NOTE: There is an extremely small chance (< 1 in 2^127) the provided seed +// will derive to an unusable secret key. The ErrUnusable error will be +// returned if this should occur, so the caller must check for it and generate a +// new seed accordingly. +func NewMaster(seed []byte, net *chaincfg.Params) (*ExtendedKey, error) { + // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. + if len(seed) < MinSeedBytes || len(seed) > MaxSeedBytes { + return nil, ErrInvalidSeedLen + } + + // First take the HMAC-SHA512 of the master key and the seed data: + // I = HMAC-SHA512(Key = "Bitcoin seed", Data = S) + hmac512 := hmac.New(sha512.New, masterKey) + _, _ = hmac512.Write(seed) + lr := hmac512.Sum(nil) + + // Split "I" into two 32-byte sequences Il and Ir where: + // Il = master secret key + // Ir = master chain code + secretKey := lr[:len(lr)/2] + chainCode := lr[len(lr)/2:] + + // Ensure the key in usable. + secretKeyNum := new(big.Int).SetBytes(secretKey) + if secretKeyNum.Cmp(btcec.S256().N) >= 0 || secretKeyNum.Sign() == 0 { + return nil, ErrUnusableSeed + } + + parentFP := []byte{0x00, 0x00, 0x00, 0x00} + return NewExtendedKey(net.HDPrivateKeyID[:], secretKey, chainCode, + parentFP, 0, 0, true), nil +} + +// NewKeyFromString returns a new extended key instance from a base58-encoded +// extended key. +func NewKeyFromString(key string) (*ExtendedKey, error) { + // The base58-decoded extended key must consist of a serialized payload + // plus an additional 4 bytes for the checksum. + decoded := base58.Decode(key) + if len(decoded) != serializedKeyLen+4 { + return nil, ErrInvalidKeyLen + } + + // The serialized format is: + // version (4) || depth (1) || parent fingerprint (4)) || + // child num (4) || chain code (32) || key data (33) || checksum (4) + + // Split the payload and checksum up and ensure the checksum matches. + payload := decoded[:len(decoded)-4] + checkSum := decoded[len(decoded)-4:] + expectedCheckSum := chainhash.DoubleHashB(payload)[:4] + if !bytes.Equal(checkSum, expectedCheckSum) { + return nil, ErrBadChecksum + } + + // Deserialize each of the payload fields. + version := payload[:4] + depth := payload[4:5][0] + parentFP := payload[5:9] + childNum := binary.BigEndian.Uint32(payload[9:13]) + chainCode := payload[13:45] + keyData := payload[45:78] + + // The key data is a private key if it starts with 0x00. Serialized + // compressed pubkeys either start with 0x02 or 0x03. + isPrivate := keyData[0] == 0x00 + if isPrivate { + // Ensure the private key is valid. It must be within the range + // of the order of the secp256k1 curve and not be 0. + keyData = keyData[1:] + keyNum := new(big.Int).SetBytes(keyData) + if keyNum.Cmp(btcec.S256().N) >= 0 || keyNum.Sign() == 0 { + return nil, ErrUnusableSeed + } + } else { + // Ensure the public key parses correctly and is actually on the + // secp256k1 curve. + _, err := btcec.ParsePubKey(keyData, btcec.S256()) + if err != nil { + return nil, err + } + } + + return NewExtendedKey(version, keyData, chainCode, parentFP, depth, + childNum, isPrivate), nil +} + +// GenerateSeed returns a cryptographically secure random seed that can be used +// as the input for the NewMaster function to generate a new master node. +// +// The length is in bytes and it must be between 16 and 64 (128 to 512 bits). +// The recommended length is 32 (256 bits) as defined by the RecommendedSeedLen +// constant. +func GenerateSeed(length uint8) ([]byte, error) { + // Per [BIP32], the seed must be in range [MinSeedBytes, MaxSeedBytes]. + if length < MinSeedBytes || length > MaxSeedBytes { + return nil, ErrInvalidSeedLen + } + + buf := make([]byte, length) + _, err := rand.Read(buf) + if err != nil { + return nil, err + } + + return buf, nil +} diff --git a/btcutil/hdkeychain/extendedkey_test.go b/btcutil/hdkeychain/extendedkey_test.go new file mode 100644 index 0000000000..dd6deb514e --- /dev/null +++ b/btcutil/hdkeychain/extendedkey_test.go @@ -0,0 +1,1209 @@ +// Copyright (c) 2014-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package hdkeychain + +// References: +// [BIP32]: BIP0032 - Hierarchical Deterministic Wallets +// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "errors" + "math" + "reflect" + "testing" + + "github.com/btcsuite/btcd/chaincfg" +) + +// TestBIP0032Vectors tests the vectors provided by [BIP32] to ensure the +// derivation works as intended. +func TestBIP0032Vectors(t *testing.T) { + // The master seeds for each of the two test vectors in [BIP32]. + testVec1MasterHex := "000102030405060708090a0b0c0d0e0f" + testVec2MasterHex := "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542" + testVec3MasterHex := "4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be" + hkStart := uint32(0x80000000) + + tests := []struct { + name string + master string + path []uint32 + wantPub string + wantPriv string + net *chaincfg.Params + }{ + // Test vector 1 + { + name: "test vector 1 chain m", + master: testVec1MasterHex, + path: []uint32{}, + wantPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + wantPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 1 chain m/0H", + master: testVec1MasterHex, + path: []uint32{hkStart}, + wantPub: "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw", + wantPriv: "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 1 chain m/0H/1", + master: testVec1MasterHex, + path: []uint32{hkStart, 1}, + wantPub: "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ", + wantPriv: "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 1 chain m/0H/1/2H", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2}, + wantPub: "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5", + wantPriv: "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 1 chain m/0H/1/2H/2", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2, 2}, + wantPub: "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV", + wantPriv: "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 1 chain m/0H/1/2H/2/1000000000", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000}, + wantPub: "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy", + wantPriv: "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", + net: &chaincfg.MainNetParams, + }, + + // Test vector 2 + { + name: "test vector 2 chain m", + master: testVec2MasterHex, + path: []uint32{}, + wantPub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB", + wantPriv: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 2 chain m/0", + master: testVec2MasterHex, + path: []uint32{0}, + wantPub: "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH", + wantPriv: "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 2 chain m/0/2147483647H", + master: testVec2MasterHex, + path: []uint32{0, hkStart + 2147483647}, + wantPub: "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a", + wantPriv: "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 2 chain m/0/2147483647H/1", + master: testVec2MasterHex, + path: []uint32{0, hkStart + 2147483647, 1}, + wantPub: "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon", + wantPriv: "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 2 chain m/0/2147483647H/1/2147483646H", + master: testVec2MasterHex, + path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646}, + wantPub: "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL", + wantPriv: "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 2 chain m/0/2147483647H/1/2147483646H/2", + master: testVec2MasterHex, + path: []uint32{0, hkStart + 2147483647, 1, hkStart + 2147483646, 2}, + wantPub: "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt", + wantPriv: "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", + net: &chaincfg.MainNetParams, + }, + + // Test vector 3 + { + name: "test vector 3 chain m", + master: testVec3MasterHex, + path: []uint32{}, + wantPub: "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13", + wantPriv: "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6", + net: &chaincfg.MainNetParams, + }, + { + name: "test vector 3 chain m/0H", + master: testVec3MasterHex, + path: []uint32{hkStart}, + wantPub: "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y", + wantPriv: "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", + net: &chaincfg.MainNetParams, + }, + + // Test vector 1 - Testnet + { + name: "test vector 1 chain m - testnet", + master: testVec1MasterHex, + path: []uint32{}, + wantPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", + wantPriv: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart}, + wantPub: "tpubD8eQVK4Kdxg3gHrF62jGP7dKVCoYiEB8dFSpuTawkL5YxTus5j5pf83vaKnii4bc6v2NVEy81P2gYrJczYne3QNNwMTS53p5uzDyHvnw2jm", + wantPriv: "tprv8bxNLu25VazNnppTCP4fyhyCvBHcYtzE3wr3cwYeL4HA7yf6TLGEUdS4QC1vLT63TkjRssqJe4CvGNEC8DzW5AoPUw56D1Ayg6HY4oy8QZ9", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1 - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1}, + wantPub: "tpubDApXh6cD2fZ7WjtgpHd8yrWyYaneiFuRZa7fVjMkgxsmC1QzoXW8cgx9zQFJ81Jx4deRGfRE7yXA9A3STsxXj4CKEZJHYgpMYikkas9DBTP", + wantPriv: "tprv8e8VYgZxtHsSdGrtvdxYaSrryZGiYviWzGWtDDKTGh5NMXAEB8gYSCLHpFCywNs5uqV7ghRjimALQJkRFZnUrLHpzi2pGkwqLtbubgWuQ8q", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1/2H - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2}, + wantPub: "tpubDDRojdS4jYQXNugn4t2WLrZ7mjfAyoVQu7MLk4eurqFCbrc7cHLZX8W5YRS8ZskGR9k9t3PqVv68bVBjAyW4nWM9pTGRddt3GQftg6MVQsm", + wantPriv: "tprv8gjmbDPpbAirVSezBEMuwSu1Ci9EpUJWKokZTYccSZSomNMLytWyLdtDNHRbucNaRJWWHANf9AzEdWVAqahfyRjVMKbNRhBmxAM8EJr7R15", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1/2H/2 - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2, 2}, + wantPub: "tpubDFfCa4Z1v25WTPAVm9EbEMiRrYwucPocLbEe12BPBGooxxEUg42vihy1DkRWyftztTsL23snYezF9uXjGGwGW6pQjEpcTpmsH6ajpf4CVPn", + wantPriv: "tprv8iyAReWmmePqZv8hsVZzpx4KHXRyT4chmHdriW95m11R8Tyi3fDLYDM93bq4NGn1V6eCu5cE3zSQ6hPd31F2ApKXkZgTyn1V78pHjkq1V2v", + net: &chaincfg.TestNet3Params, + }, + { + name: "test vector 1 chain m/0H/1/2H/2/1000000000 - testnet", + master: testVec1MasterHex, + path: []uint32{hkStart, 1, hkStart + 2, 2, 1000000000}, + wantPub: "tpubDHNy3kAG39ThyiwwsgoKY4iRenXDRtce8qdCFJZXPMCJg5dsCUHayp84raLTpvyiNA9sXPob5rgqkKvkN8S7MMyXbnEhGJMW64Cf4vFAoaF", + wantPriv: "tprv8kgvuL81tmn36Fv9z38j8f4K5m1HGZRjZY2QxnXDy5PuqbP6a5TzoKWCgTcGHBu66W3TgSbAu2yX6sPza5FkHmy564Sh6gmCPUNeUt4yj2x", + net: &chaincfg.TestNet3Params, + }, + } + +tests: + for i, test := range tests { + masterSeed, err := hex.DecodeString(test.master) + if err != nil { + t.Errorf("DecodeString #%d (%s): unexpected error: %v", + i, test.name, err) + continue + } + + extKey, err := NewMaster(masterSeed, test.net) + if err != nil { + t.Errorf("NewMaster #%d (%s): unexpected error when "+ + "creating new master key: %v", i, test.name, + err) + continue + } + + for _, childNum := range test.path { + var err error + extKey, err = extKey.Derive(childNum) + if err != nil { + t.Errorf("err: %v", err) + continue tests + } + } + + if extKey.Depth() != uint8(len(test.path)) { + t.Errorf("Depth of key %d should match fixture path: %v", + extKey.Depth(), len(test.path)) + continue + } + + privStr := extKey.String() + if privStr != test.wantPriv { + t.Errorf("Serialize #%d (%s): mismatched serialized "+ + "private extended key -- got: %s, want: %s", i, + test.name, privStr, test.wantPriv) + continue + } + + pubKey, err := extKey.Neuter() + if err != nil { + t.Errorf("Neuter #%d (%s): unexpected error: %v ", i, + test.name, err) + continue + } + + // Neutering a second time should have no effect. + pubKey, err = pubKey.Neuter() + if err != nil { + t.Errorf("Neuter #%d (%s): unexpected error: %v", i, + test.name, err) + return + } + + pubStr := pubKey.String() + if pubStr != test.wantPub { + t.Errorf("Neuter #%d (%s): mismatched serialized "+ + "public extended key -- got: %s, want: %s", i, + test.name, pubStr, test.wantPub) + continue + } + } +} + +// TestPrivateDerivation tests several vectors which derive private keys from +// other private keys works as intended. +func TestPrivateDerivation(t *testing.T) { + // The private extended keys for test vectors in [BIP32]. + testVec1MasterPrivKey := "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi" + testVec2MasterPrivKey := "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U" + + tests := []struct { + name string + master string + path []uint32 + wantPriv string + }{ + // Test vector 1 + { + name: "test vector 1 chain m", + master: testVec1MasterPrivKey, + path: []uint32{}, + wantPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + }, + { + name: "test vector 1 chain m/0", + master: testVec1MasterPrivKey, + path: []uint32{0}, + wantPriv: "xprv9uHRZZhbkedL37eZEnyrNsQPFZYRAvjy5rt6M1nbEkLSo378x1CQQLo2xxBvREwiK6kqf7GRNvsNEchwibzXaV6i5GcsgyjBeRguXhKsi4R", + }, + { + name: "test vector 1 chain m/0/1", + master: testVec1MasterPrivKey, + path: []uint32{0, 1}, + wantPriv: "xprv9ww7sMFLzJMzy7bV1qs7nGBxgKYrgcm3HcJvGb4yvNhT9vxXC7eX7WVULzCfxucFEn2TsVvJw25hH9d4mchywguGQCZvRgsiRaTY1HCqN8G", + }, + { + name: "test vector 1 chain m/0/1/2", + master: testVec1MasterPrivKey, + path: []uint32{0, 1, 2}, + wantPriv: "xprv9xrdP7iD2L1YZCgR9AecDgpDMZSTzP5KCfUykGXgjBxLgp1VFHsEeL3conzGAkbc1MigG1o8YqmfEA2jtkPdf4vwMaGJC2YSDbBTPAjfRUi", + }, + { + name: "test vector 1 chain m/0/1/2/2", + master: testVec1MasterPrivKey, + path: []uint32{0, 1, 2, 2}, + wantPriv: "xprvA2J8Hq4eiP7xCEBP7gzRJGJnd9CHTkEU6eTNMrZ6YR7H5boik8daFtDZxmJDfdMSKHwroCfAfsBKWWidRfBQjpegy6kzXSkQGGoMdWKz5Xh", + }, + { + name: "test vector 1 chain m/0/1/2/2/1000000000", + master: testVec1MasterPrivKey, + path: []uint32{0, 1, 2, 2, 1000000000}, + wantPriv: "xprvA3XhazxncJqJsQcG85Gg61qwPQKiobAnWjuPpjKhExprZjfse6nErRwTMwGe6uGWXPSykZSTiYb2TXAm7Qhwj8KgRd2XaD21Styu6h6AwFz", + }, + + // Test vector 2 + { + name: "test vector 2 chain m", + master: testVec2MasterPrivKey, + path: []uint32{}, + wantPriv: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", + }, + { + name: "test vector 2 chain m/0", + master: testVec2MasterPrivKey, + path: []uint32{0}, + wantPriv: "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", + }, + { + name: "test vector 2 chain m/0/2147483647", + master: testVec2MasterPrivKey, + path: []uint32{0, 2147483647}, + wantPriv: "xprv9wSp6B7cXJWXZRpDbxkFg3ry2fuSyUfvboJ5Yi6YNw7i1bXmq9QwQ7EwMpeG4cK2pnMqEx1cLYD7cSGSCtruGSXC6ZSVDHugMsZgbuY62m6", + }, + { + name: "test vector 2 chain m/0/2147483647/1", + master: testVec2MasterPrivKey, + path: []uint32{0, 2147483647, 1}, + wantPriv: "xprv9ysS5br6UbWCRCJcggvpUNMyhVWgD7NypY9gsVTMYmuRtZg8izyYC5Ey4T931WgWbfJwRDwfVFqV3b29gqHDbuEpGcbzf16pdomk54NXkSm", + }, + { + name: "test vector 2 chain m/0/2147483647/1/2147483646", + master: testVec2MasterPrivKey, + path: []uint32{0, 2147483647, 1, 2147483646}, + wantPriv: "xprvA2LfeWWwRCxh4iqigcDMnUf2E3nVUFkntc93nmUYBtb9rpSPYWa8MY3x9ZHSLZkg4G84UefrDruVK3FhMLSJsGtBx883iddHNuH1LNpRrEp", + }, + { + name: "test vector 2 chain m/0/2147483647/1/2147483646/2", + master: testVec2MasterPrivKey, + path: []uint32{0, 2147483647, 1, 2147483646, 2}, + wantPriv: "xprvA48ALo8BDjcRET68R5RsPzF3H7WeyYYtHcyUeLRGBPHXu6CJSGjwW7dWoeUWTEzT7LG3qk6Eg6x2ZoqD8gtyEFZecpAyvchksfLyg3Zbqam", + }, + + // Custom tests to trigger specific conditions. + { + // Seed 000000000000000000000000000000da. + name: "Derived privkey with zero high byte m/0", + master: "xprv9s21ZrQH143K4FR6rNeqEK4EBhRgLjWLWhA3pw8iqgAKk82ypz58PXbrzU19opYcxw8JDJQF4id55PwTsN1Zv8Xt6SKvbr2KNU5y8jN8djz", + path: []uint32{0}, + wantPriv: "xprv9uC5JqtViMmgcAMUxcsBCBFA7oYCNs4bozPbyvLfddjHou4rMiGEHipz94xNaPb1e4f18TRoPXfiXx4C3cDAcADqxCSRSSWLvMBRWPctSN9", + }, + } + +tests: + for i, test := range tests { + extKey, err := NewKeyFromString(test.master) + if err != nil { + t.Errorf("NewKeyFromString #%d (%s): unexpected error "+ + "creating extended key: %v", i, test.name, + err) + continue + } + + for _, childNum := range test.path { + var err error + extKey, err = extKey.Derive(childNum) + if err != nil { + t.Errorf("err: %v", err) + continue tests + } + } + + privStr := extKey.String() + if privStr != test.wantPriv { + t.Errorf("Derive #%d (%s): mismatched serialized "+ + "private extended key -- got: %s, want: %s", i, + test.name, privStr, test.wantPriv) + continue + } + } +} + +// TestPublicDerivation tests several vectors which derive public keys from +// other public keys works as intended. +func TestPublicDerivation(t *testing.T) { + // The public extended keys for test vectors in [BIP32]. + testVec1MasterPubKey := "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8" + testVec2MasterPubKey := "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB" + + tests := []struct { + name string + master string + path []uint32 + wantPub string + }{ + // Test vector 1 + { + name: "test vector 1 chain m", + master: testVec1MasterPubKey, + path: []uint32{}, + wantPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + }, + { + name: "test vector 1 chain m/0", + master: testVec1MasterPubKey, + path: []uint32{0}, + wantPub: "xpub68Gmy5EVb2BdFbj2LpWrk1M7obNuaPTpT5oh9QCCo5sRfqSHVYWex97WpDZzszdzHzxXDAzPLVSwybe4uPYkSk4G3gnrPqqkV9RyNzAcNJ1", + }, + { + name: "test vector 1 chain m/0/1", + master: testVec1MasterPubKey, + path: []uint32{0, 1}, + wantPub: "xpub6AvUGrnEpfvJBbfx7sQ89Q8hEMPM65UteqEX4yUbUiES2jHfjexmfJoxCGSwFMZiPBaKQT1RiKWrKfuDV4vpgVs4Xn8PpPTR2i79rwHd4Zr", + }, + { + name: "test vector 1 chain m/0/1/2", + master: testVec1MasterPubKey, + path: []uint32{0, 1, 2}, + wantPub: "xpub6BqyndF6rhZqmgktFCBcapkwubGxPqoAZtQaYewJHXVKZcLdnqBVC8N6f6FSHWUghjuTLeubWyQWfJdk2G3tGgvgj3qngo4vLTnnSjAZckv", + }, + { + name: "test vector 1 chain m/0/1/2/2", + master: testVec1MasterPubKey, + path: []uint32{0, 1, 2, 2}, + wantPub: "xpub6FHUhLbYYkgFQiFrDiXRfQFXBB2msCxKTsNyAExi6keFxQ8sHfwpogY3p3s1ePSpUqLNYks5T6a3JqpCGszt4kxbyq7tUoFP5c8KWyiDtPp", + }, + { + name: "test vector 1 chain m/0/1/2/2/1000000000", + master: testVec1MasterPubKey, + path: []uint32{0, 1, 2, 2, 1000000000}, + wantPub: "xpub6GX3zWVgSgPc5tgjE6ogT9nfwSADD3tdsxpzd7jJoJMqSY12Be6VQEFwDCp6wAQoZsH2iq5nNocHEaVDxBcobPrkZCjYW3QUmoDYzMFBDu9", + }, + + // Test vector 2 + { + name: "test vector 2 chain m", + master: testVec2MasterPubKey, + path: []uint32{}, + wantPub: "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB", + }, + { + name: "test vector 2 chain m/0", + master: testVec2MasterPubKey, + path: []uint32{0}, + wantPub: "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH", + }, + { + name: "test vector 2 chain m/0/2147483647", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647}, + wantPub: "xpub6ASAVgeWMg4pmutghzHG3BohahjwNwPmy2DgM6W9wGegtPrvNgjBwuZRD7hSDFhYfunq8vDgwG4ah1gVzZysgp3UsKz7VNjCnSUJJ5T4fdD", + }, + { + name: "test vector 2 chain m/0/2147483647/1", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647, 1}, + wantPub: "xpub6CrnV7NzJy4VdgP5niTpqWJiFXMAca6qBm5Hfsry77SQmN1HGYHnjsZSujoHzdxf7ZNK5UVrmDXFPiEW2ecwHGWMFGUxPC9ARipss9rXd4b", + }, + { + name: "test vector 2 chain m/0/2147483647/1/2147483646", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647, 1, 2147483646}, + wantPub: "xpub6FL2423qFaWzHCvBndkN9cbkn5cysiUeFq4eb9t9kE88jcmY63tNuLNRzpHPdAM4dUpLhZ7aUm2cJ5zF7KYonf4jAPfRqTMTRBNkQL3Tfta", + }, + { + name: "test vector 2 chain m/0/2147483647/1/2147483646/2", + master: testVec2MasterPubKey, + path: []uint32{0, 2147483647, 1, 2147483646, 2}, + wantPub: "xpub6H7WkJf547AiSwAbX6xsm8Bmq9M9P1Gjequ5SipsjipWmtXSyp4C3uwzewedGEgAMsDy4jEvNTWtxLyqqHY9C12gaBmgUdk2CGmwachwnWK", + }, + } + +tests: + for i, test := range tests { + extKey, err := NewKeyFromString(test.master) + if err != nil { + t.Errorf("NewKeyFromString #%d (%s): unexpected error "+ + "creating extended key: %v", i, test.name, + err) + continue + } + + for _, childNum := range test.path { + var err error + extKey, err = extKey.Derive(childNum) + if err != nil { + t.Errorf("err: %v", err) + continue tests + } + } + + pubStr := extKey.String() + if pubStr != test.wantPub { + t.Errorf("Derive #%d (%s): mismatched serialized "+ + "public extended key -- got: %s, want: %s", i, + test.name, pubStr, test.wantPub) + continue + } + } +} + +// TestGenerateSeed ensures the GenerateSeed function works as intended. +func TestGenerateSeed(t *testing.T) { + wantErr := errors.New("seed length must be between 128 and 512 bits") + + tests := []struct { + name string + length uint8 + err error + }{ + // Test various valid lengths. + {name: "16 bytes", length: 16}, + {name: "17 bytes", length: 17}, + {name: "20 bytes", length: 20}, + {name: "32 bytes", length: 32}, + {name: "64 bytes", length: 64}, + + // Test invalid lengths. + {name: "15 bytes", length: 15, err: wantErr}, + {name: "65 bytes", length: 65, err: wantErr}, + } + + for i, test := range tests { + seed, err := GenerateSeed(test.length) + if !reflect.DeepEqual(err, test.err) { + t.Errorf("GenerateSeed #%d (%s): unexpected error -- "+ + "want %v, got %v", i, test.name, test.err, err) + continue + } + + if test.err == nil && len(seed) != int(test.length) { + t.Errorf("GenerateSeed #%d (%s): length mismatch -- "+ + "got %d, want %d", i, test.name, len(seed), + test.length) + continue + } + } +} + +// TestExtendedKeyAPI ensures the API on the ExtendedKey type works as intended. +func TestExtendedKeyAPI(t *testing.T) { + tests := []struct { + name string + extKey string + isPrivate bool + parentFP uint32 + chainCode []byte + childNum uint32 + privKey string + privKeyErr error + pubKey string + address string + }{ + { + name: "test vector 1 master node private", + extKey: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + isPrivate: true, + parentFP: 0, + chainCode: []byte{135, 61, 255, 129, 192, 47, 82, 86, 35, 253, 31, 229, 22, 126, 172, 58, 85, 160, 73, 222, 61, 49, 75, 180, 46, 226, 39, 255, 237, 55, 213, 8}, + childNum: 0, + privKey: "e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35", + pubKey: "0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2", + address: "15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma", + }, + { + name: "test vector 1 chain m/0H/1/2H public", + extKey: "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5", + isPrivate: false, + parentFP: 3203769081, + chainCode: []byte{4, 70, 107, 156, 200, 225, 97, 233, 102, 64, 156, 165, 41, 134, 197, 132, 240, 126, 157, 200, 31, 115, 93, 182, 131, 195, 255, 110, 199, 177, 80, 63}, + childNum: 2147483650, + privKeyErr: ErrNotPrivExtKey, + pubKey: "0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2", + address: "1NjxqbA9aZWnh17q1UW3rB4EPu79wDXj7x", + }, + } + + for i, test := range tests { + key, err := NewKeyFromString(test.extKey) + if err != nil { + t.Errorf("NewKeyFromString #%d (%s): unexpected "+ + "error: %v", i, test.name, err) + continue + } + + if key.IsPrivate() != test.isPrivate { + t.Errorf("IsPrivate #%d (%s): mismatched key type -- "+ + "want private %v, got private %v", i, test.name, + test.isPrivate, key.IsPrivate()) + continue + } + + parentFP := key.ParentFingerprint() + if parentFP != test.parentFP { + t.Errorf("ParentFingerprint #%d (%s): mismatched "+ + "parent fingerprint -- want %d, got %d", i, + test.name, test.parentFP, parentFP) + continue + } + + chainCode := key.ChainCode() + if !bytes.Equal(chainCode, test.chainCode) { + t.Errorf("ChainCode #%d (%s): want %v, got %v", i, + test.name, test.chainCode, chainCode) + continue + } + + childIndex := key.ChildIndex() + if childIndex != test.childNum { + t.Errorf("ChildIndex #%d (%s): want %d, got %d", i, + test.name, test.childNum, childIndex) + continue + } + + serializedKey := key.String() + if serializedKey != test.extKey { + t.Errorf("String #%d (%s): mismatched serialized key "+ + "-- want %s, got %s", i, test.name, test.extKey, + serializedKey) + continue + } + + privKey, err := key.ECPrivKey() + if !reflect.DeepEqual(err, test.privKeyErr) { + t.Errorf("ECPrivKey #%d (%s): mismatched error: want "+ + "%v, got %v", i, test.name, test.privKeyErr, err) + continue + } + if test.privKeyErr == nil { + privKeyStr := hex.EncodeToString(privKey.Serialize()) + if privKeyStr != test.privKey { + t.Errorf("ECPrivKey #%d (%s): mismatched "+ + "private key -- want %s, got %s", i, + test.name, test.privKey, privKeyStr) + continue + } + } + + pubKey, err := key.ECPubKey() + if err != nil { + t.Errorf("ECPubKey #%d (%s): unexpected error: %v", i, + test.name, err) + continue + } + pubKeyStr := hex.EncodeToString(pubKey.SerializeCompressed()) + if pubKeyStr != test.pubKey { + t.Errorf("ECPubKey #%d (%s): mismatched public key -- "+ + "want %s, got %s", i, test.name, test.pubKey, + pubKeyStr) + continue + } + + addr, err := key.Address(&chaincfg.MainNetParams) + if err != nil { + t.Errorf("Address #%d (%s): unexpected error: %v", i, + test.name, err) + continue + } + if addr.EncodeAddress() != test.address { + t.Errorf("Address #%d (%s): mismatched address -- want "+ + "%s, got %s", i, test.name, test.address, + addr.EncodeAddress()) + continue + } + } +} + +// TestNet ensures the network related APIs work as intended. +func TestNet(t *testing.T) { + tests := []struct { + name string + key string + origNet *chaincfg.Params + newNet *chaincfg.Params + newPriv string + newPub string + isPrivate bool + }{ + // Private extended keys. + { + name: "mainnet -> simnet", + key: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + origNet: &chaincfg.MainNetParams, + newNet: &chaincfg.SimNetParams, + newPriv: "sprv8Erh3X3hFeKunvVdAGQQtambRPapECWiTDtvsTGdyrhzhbYgnSZajRRWbihzvq4AM4ivm6uso31VfKaukwJJUs3GYihXP8ebhMb3F2AHu3P", + newPub: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk", + isPrivate: true, + }, + { + name: "simnet -> mainnet", + key: "sprv8Erh3X3hFeKunvVdAGQQtambRPapECWiTDtvsTGdyrhzhbYgnSZajRRWbihzvq4AM4ivm6uso31VfKaukwJJUs3GYihXP8ebhMb3F2AHu3P", + origNet: &chaincfg.SimNetParams, + newNet: &chaincfg.MainNetParams, + newPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + isPrivate: true, + }, + { + name: "mainnet -> regtest", + key: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + origNet: &chaincfg.MainNetParams, + newNet: &chaincfg.RegressionNetParams, + newPriv: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m", + newPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", + isPrivate: true, + }, + { + name: "regtest -> mainnet", + key: "tprv8ZgxMBicQKsPeDgjzdC36fs6bMjGApWDNLR9erAXMs5skhMv36j9MV5ecvfavji5khqjWaWSFhN3YcCUUdiKH6isR4Pwy3U5y5egddBr16m", + origNet: &chaincfg.RegressionNetParams, + newNet: &chaincfg.MainNetParams, + newPriv: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + isPrivate: true, + }, + + // Public extended keys. + { + name: "mainnet -> simnet", + key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + origNet: &chaincfg.MainNetParams, + newNet: &chaincfg.SimNetParams, + newPub: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk", + isPrivate: false, + }, + { + name: "simnet -> mainnet", + key: "spub4Tr3T2ab61tD1Qa6GHwRFiiKyRRJdfEZpSpXfqgFYCEyaPsqKysqHDjzSzMJSiUEGbcsG3w2SLMoTqn44B8x6u3MLRRkYfACTUBnHK79THk", + origNet: &chaincfg.SimNetParams, + newNet: &chaincfg.MainNetParams, + newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + isPrivate: false, + }, + { + name: "mainnet -> regtest", + key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + origNet: &chaincfg.MainNetParams, + newNet: &chaincfg.RegressionNetParams, + newPub: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", + isPrivate: false, + }, + { + name: "regtest -> mainnet", + key: "tpubD6NzVbkrYhZ4XgiXtGrdW5XDAPFCL9h7we1vwNCpn8tGbBcgfVYjXyhWo4E1xkh56hjod1RhGjxbaTLV3X4FyWuejifB9jusQ46QzG87VKp", + origNet: &chaincfg.RegressionNetParams, + newNet: &chaincfg.MainNetParams, + newPub: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + isPrivate: false, + }, + } + + for i, test := range tests { + extKey, err := NewKeyFromString(test.key) + if err != nil { + t.Errorf("NewKeyFromString #%d (%s): unexpected error "+ + "creating extended key: %v", i, test.name, + err) + continue + } + + if !extKey.IsForNet(test.origNet) { + t.Errorf("IsForNet #%d (%s): key is not for expected "+ + "network %v", i, test.name, test.origNet.Name) + continue + } + + extKey.SetNet(test.newNet) + if !extKey.IsForNet(test.newNet) { + t.Errorf("SetNet/IsForNet #%d (%s): key is not for "+ + "expected network %v", i, test.name, + test.newNet.Name) + continue + } + + if test.isPrivate { + privStr := extKey.String() + if privStr != test.newPriv { + t.Errorf("Serialize #%d (%s): mismatched serialized "+ + "private extended key -- got: %s, want: %s", i, + test.name, privStr, test.newPriv) + continue + } + + extKey, err = extKey.Neuter() + if err != nil { + t.Errorf("Neuter #%d (%s): unexpected error: %v ", i, + test.name, err) + continue + } + } + + pubStr := extKey.String() + if pubStr != test.newPub { + t.Errorf("Neuter #%d (%s): mismatched serialized "+ + "public extended key -- got: %s, want: %s", i, + test.name, pubStr, test.newPub) + continue + } + } +} + +// TestErrors performs some negative tests for various invalid cases to ensure +// the errors are handled properly. +func TestErrors(t *testing.T) { + // Should get an error when seed has too few bytes. + net := &chaincfg.MainNetParams + _, err := NewMaster(bytes.Repeat([]byte{0x00}, 15), net) + if err != ErrInvalidSeedLen { + t.Fatalf("NewMaster: mismatched error -- got: %v, want: %v", + err, ErrInvalidSeedLen) + } + + // Should get an error when seed has too many bytes. + _, err = NewMaster(bytes.Repeat([]byte{0x00}, 65), net) + if err != ErrInvalidSeedLen { + t.Fatalf("NewMaster: mismatched error -- got: %v, want: %v", + err, ErrInvalidSeedLen) + } + + // Generate a new key and neuter it to a public extended key. + seed, err := GenerateSeed(RecommendedSeedLen) + if err != nil { + t.Fatalf("GenerateSeed: unexpected error: %v", err) + } + extKey, err := NewMaster(seed, net) + if err != nil { + t.Fatalf("NewMaster: unexpected error: %v", err) + } + pubKey, err := extKey.Neuter() + if err != nil { + t.Fatalf("Neuter: unexpected error: %v", err) + } + + // Deriving a hardened child extended key should fail from a public key. + _, err = pubKey.Derive(HardenedKeyStart) + if err != ErrDeriveHardFromPublic { + t.Fatalf("Derive: mismatched error -- got: %v, want: %v", + err, ErrDeriveHardFromPublic) + } + + // NewKeyFromString failure tests. + tests := []struct { + name string + key string + err error + neuter bool + neuterErr error + }{ + { + name: "invalid key length", + key: "xpub1234", + err: ErrInvalidKeyLen, + }, + { + name: "bad checksum", + key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EBygr15", + err: ErrBadChecksum, + }, + { + name: "pubkey not on curve", + key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ1hr9Rwbk95YadvBkQXxzHBSngB8ndpW6QH7zhhsXZ2jHyZqPjk", + err: errors.New("invalid square root"), + }, + { + name: "unsupported version", + key: "xbad4LfUL9eKmA66w2GJdVMqhvDmYGJpTGjWRAtjHqoUY17sGaymoMV9Cm3ocn9Ud6Hh2vLFVC7KSKCRVVrqc6dsEdsTjRV1WUmkK85YEUujAPX", + err: nil, + neuter: true, + neuterErr: chaincfg.ErrUnknownHDKeyID, + }, + } + + for i, test := range tests { + extKey, err := NewKeyFromString(test.key) + if !reflect.DeepEqual(err, test.err) { + t.Errorf("NewKeyFromString #%d (%s): mismatched error "+ + "-- got: %v, want: %v", i, test.name, err, + test.err) + continue + } + + if test.neuter { + _, err := extKey.Neuter() + if !reflect.DeepEqual(err, test.neuterErr) { + t.Errorf("Neuter #%d (%s): mismatched error "+ + "-- got: %v, want: %v", i, test.name, + err, test.neuterErr) + continue + } + } + } +} + +// TestZero ensures that zeroing an extended key works as intended. +func TestZero(t *testing.T) { + tests := []struct { + name string + master string + extKey string + net *chaincfg.Params + }{ + // Test vector 1 + { + name: "test vector 1 chain m", + master: "000102030405060708090a0b0c0d0e0f", + extKey: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + net: &chaincfg.MainNetParams, + }, + + // Test vector 2 + { + name: "test vector 2 chain m", + master: "fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542", + extKey: "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", + net: &chaincfg.MainNetParams, + }, + } + + // Use a closure to test that a key is zeroed since the tests create + // keys in different ways and need to test the same things multiple + // times. + testZeroed := func(i int, testName string, key *ExtendedKey) bool { + // Zeroing a key should result in it no longer being private + if key.IsPrivate() { + t.Errorf("IsPrivate #%d (%s): mismatched key type -- "+ + "want private %v, got private %v", i, testName, + false, key.IsPrivate()) + return false + } + + parentFP := key.ParentFingerprint() + if parentFP != 0 { + t.Errorf("ParentFingerprint #%d (%s): mismatched "+ + "parent fingerprint -- want %d, got %d", i, + testName, 0, parentFP) + return false + } + + wantKey := "zeroed extended key" + serializedKey := key.String() + if serializedKey != wantKey { + t.Errorf("String #%d (%s): mismatched serialized key "+ + "-- want %s, got %s", i, testName, wantKey, + serializedKey) + return false + } + + wantErr := ErrNotPrivExtKey + _, err := key.ECPrivKey() + if !reflect.DeepEqual(err, wantErr) { + t.Errorf("ECPrivKey #%d (%s): mismatched error: want "+ + "%v, got %v", i, testName, wantErr, err) + return false + } + + wantErr = errors.New("pubkey string is empty") + _, err = key.ECPubKey() + if !reflect.DeepEqual(err, wantErr) { + t.Errorf("ECPubKey #%d (%s): mismatched error: want "+ + "%v, got %v", i, testName, wantErr, err) + return false + } + + wantAddr := "1HT7xU2Ngenf7D4yocz2SAcnNLW7rK8d4E" + addr, err := key.Address(&chaincfg.MainNetParams) + if err != nil { + t.Errorf("Address #%d (%s): unexpected error: %v", i, + testName, err) + return false + } + if addr.EncodeAddress() != wantAddr { + t.Errorf("Address #%d (%s): mismatched address -- want "+ + "%s, got %s", i, testName, wantAddr, + addr.EncodeAddress()) + return false + } + + return true + } + + for i, test := range tests { + // Create new key from seed and get the neutered version. + masterSeed, err := hex.DecodeString(test.master) + if err != nil { + t.Errorf("DecodeString #%d (%s): unexpected error: %v", + i, test.name, err) + continue + } + key, err := NewMaster(masterSeed, test.net) + if err != nil { + t.Errorf("NewMaster #%d (%s): unexpected error when "+ + "creating new master key: %v", i, test.name, + err) + continue + } + neuteredKey, err := key.Neuter() + if err != nil { + t.Errorf("Neuter #%d (%s): unexpected error: %v", i, + test.name, err) + continue + } + + // Ensure both non-neutered and neutered keys are zeroed + // properly. + key.Zero() + if !testZeroed(i, test.name+" from seed not neutered", key) { + continue + } + neuteredKey.Zero() + if !testZeroed(i, test.name+" from seed neutered", key) { + continue + } + + // Deserialize key and get the neutered version. + key, err = NewKeyFromString(test.extKey) + if err != nil { + t.Errorf("NewKeyFromString #%d (%s): unexpected "+ + "error: %v", i, test.name, err) + continue + } + neuteredKey, err = key.Neuter() + if err != nil { + t.Errorf("Neuter #%d (%s): unexpected error: %v", i, + test.name, err) + continue + } + + // Ensure both non-neutered and neutered keys are zeroed + // properly. + key.Zero() + if !testZeroed(i, test.name+" deserialized not neutered", key) { + continue + } + neuteredKey.Zero() + if !testZeroed(i, test.name+" deserialized neutered", key) { + continue + } + } +} + +// TestMaximumDepth ensures that attempting to retrieve a child key when already +// at the maximum depth is not allowed. The serialization of a BIP32 key uses +// uint8 to encode the depth. This implicitly bounds the depth of the tree to +// 255 derivations. Here we test that an error is returned after 'max uint8'. +func TestMaximumDepth(t *testing.T) { + net := &chaincfg.MainNetParams + extKey, err := NewMaster([]byte(`abcd1234abcd1234abcd1234abcd1234`), net) + if err != nil { + t.Fatalf("NewMaster: unexpected error: %v", err) + } + + for i := uint8(0); i < math.MaxUint8; i++ { + if extKey.Depth() != i { + t.Fatalf("extendedkey depth %d should match expected value %d", + extKey.Depth(), i) + } + newKey, err := extKey.Derive(1) + if err != nil { + t.Fatalf("Derive: unexpected error: %v", err) + } + extKey = newKey + } + + noKey, err := extKey.Derive(1) + if err != ErrDeriveBeyondMaxDepth { + t.Fatalf("Derive: mismatched error: want %v, got %v", + ErrDeriveBeyondMaxDepth, err) + } + if noKey != nil { + t.Fatal("Derive: deriving 256th key should not succeed") + } +} + +// TestCloneWithVersion ensures proper conversion between standard and SLIP132 +// extended keys. +// +// The following tool was used for generating the tests: +// https://jlopp.github.io/xpub-converter +func TestCloneWithVersion(t *testing.T) { + tests := []struct { + name string + key string + version []byte + want string + wantErr error + }{ + { + name: "test xpub to zpub", + key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + version: []byte{0x04, 0xb2, 0x47, 0x46}, + want: "zpub6jftahH18ngZxUuv6oSniLNrBCSSE1B4EEU59bwTCEt8x6aS6b2mdfLxbS4QS53g85SWWP6wexqeer516433gYpZQoJie2tcMYdJ1SYYYAL", + }, + { + name: "test zpub to xpub", + key: "zpub6jftahH18ngZxUuv6oSniLNrBCSSE1B4EEU59bwTCEt8x6aS6b2mdfLxbS4QS53g85SWWP6wexqeer516433gYpZQoJie2tcMYdJ1SYYYAL", + version: []byte{0x04, 0x88, 0xb2, 0x1e}, + want: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8", + }, + { + name: "test xprv to zprv", + key: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + version: []byte{0x04, 0xb2, 0x43, 0x0c}, + want: "zprvAWgYBBk7JR8GjzqSzmunMCS7dAbwpYTCs1YUMDXqduMA5JFHZ3iX5s2UkAR6vBdcCYYa1S5o1fVLrKsrnpCQ4WpUd6aVUWP1bS2Yy5DoaKv", + }, + { + name: "test zprv to xprv", + key: "zprvAWgYBBk7JR8GjzqSzmunMCS7dAbwpYTCs1YUMDXqduMA5JFHZ3iX5s2UkAR6vBdcCYYa1S5o1fVLrKsrnpCQ4WpUd6aVUWP1bS2Yy5DoaKv", + version: []byte{0x04, 0x88, 0xad, 0xe4}, + want: "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + }, + { + name: "test invalid key id", + key: "zprvAWgYBBk7JR8GjzqSzmunMCS7dAbwpYTCs1YUMDXqduMA5JFHZ3iX5s2UkAR6vBdcCYYa1S5o1fVLrKsrnpCQ4WpUd6aVUWP1bS2Yy5DoaKv", + version: []byte{0x4B, 0x1D}, + wantErr: chaincfg.ErrUnknownHDKeyID, + }, + } + + for i, test := range tests { + extKey, err := NewKeyFromString(test.key) + if err != nil { + panic(err) // This is never expected to fail. + } + + got, err := extKey.CloneWithVersion(test.version) + if !reflect.DeepEqual(err, test.wantErr) { + t.Errorf("CloneWithVersion #%d (%s): unexpected error -- "+ + "want %v, got %v", i, test.name, test.wantErr, err) + continue + } + + if test.wantErr == nil { + if k := got.String(); k != test.want { + t.Errorf("CloneWithVersion #%d (%s): "+ + "got %s, want %s", i, test.name, k, test.want) + continue + } + } + } +} + +// TestLeadingZero ensures that deriving children from keys with a leading zero byte is done according +// to the BIP-32 standard and that the legacy method generates a backwards-compatible result. +func TestLeadingZero(t *testing.T) { + // The 400th seed results in a m/0' public key with a leading zero, allowing us to test + // the desired behavior. + ii := 399 + seed := make([]byte, 32) + binary.BigEndian.PutUint32(seed[28:], uint32(ii)) + masterKey, err := NewMaster(seed, &chaincfg.MainNetParams) + if err != nil { + t.Fatalf("hdkeychain.NewMaster failed: %v", err) + } + child0, err := masterKey.Derive(0 + HardenedKeyStart) + if err != nil { + t.Fatalf("masterKey.Derive failed: %v", err) + } + if !child0.IsAffectedByIssue172() { + t.Fatal("expected child0 to be affected by issue 172") + } + child1, err := child0.Derive(0 + HardenedKeyStart) + if err != nil { + t.Fatalf("child0.Derive failed: %v", err) + } + if child1.IsAffectedByIssue172() { + t.Fatal("did not expect child1 to be affected by issue 172") + } + + child1nonstandard, err := child0.DeriveNonStandard(0 + HardenedKeyStart) + if err != nil { + t.Fatalf("child0.DeriveNonStandard failed: %v", err) + } + + // This is the correct result based on BIP32 + if hex.EncodeToString(child1.key) != "a9b6b30a5b90b56ed48728c73af1d8a7ef1e9cc372ec21afcc1d9bdf269b0988" { + t.Error("incorrect standard BIP32 derivation") + } + + if hex.EncodeToString(child1nonstandard.key) != "ea46d8f58eb863a2d371a938396af8b0babe85c01920f59a8044412e70e837ee" { + t.Error("incorrect btcutil backwards compatible BIP32-like derivation") + } + + if !child0.IsAffectedByIssue172() { + t.Error("child 0 should be affected by issue 172") + } + + if child1.IsAffectedByIssue172() { + t.Error("child 1 should not be affected by issue 172") + } +} diff --git a/btcutil/hdkeychain/test_coverage.txt b/btcutil/hdkeychain/test_coverage.txt new file mode 100644 index 0000000000..c0bc7ef035 --- /dev/null +++ b/btcutil/hdkeychain/test_coverage.txt @@ -0,0 +1,20 @@ + +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.String 100.00% (18/18) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Zero 100.00% (9/9) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.pubKeyBytes 100.00% (7/7) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Neuter 100.00% (6/6) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.ECPrivKey 100.00% (4/4) +github.com/conformal/btcutil/hdkeychain/extendedkey.go zero 100.00% (3/3) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.SetNet 100.00% (3/3) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Address 100.00% (2/2) +github.com/conformal/btcutil/hdkeychain/extendedkey.go newExtendedKey 100.00% (1/1) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.IsPrivate 100.00% (1/1) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.ParentFingerprint 100.00% (1/1) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.ECPubKey 100.00% (1/1) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.IsForNet 100.00% (1/1) +github.com/conformal/btcutil/hdkeychain/extendedkey.go NewKeyFromString 95.83% (23/24) +github.com/conformal/btcutil/hdkeychain/extendedkey.go ExtendedKey.Child 91.67% (33/36) +github.com/conformal/btcutil/hdkeychain/extendedkey.go NewMaster 91.67% (11/12) +github.com/conformal/btcutil/hdkeychain/extendedkey.go GenerateSeed 85.71% (6/7) +github.com/conformal/btcutil/hdkeychain ----------------------------- 95.59% (130/136) + diff --git a/btcutil/internal_test.go b/btcutil/internal_test.go new file mode 100644 index 0000000000..6d1efa0199 --- /dev/null +++ b/btcutil/internal_test.go @@ -0,0 +1,147 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +This test file is part of the btcutil package rather than than the +btcutil_test package so it can bridge access to the internals to properly test +cases which are either not possible or can't reliably be tested via the public +interface. The functions are only exported while the tests are being run. +*/ + +package btcutil + +import ( + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcutil/base58" + "github.com/btcsuite/btcd/btcutil/bech32" + "golang.org/x/crypto/ripemd160" +) + +// SetBlockBytes sets the internal serialized block byte buffer to the passed +// buffer. It is used to inject errors and is only available to the test +// package. +func (b *Block) SetBlockBytes(buf []byte) { + b.serializedBlock = buf +} + +// TstAppDataDir makes the internal appDataDir function available to the test +// package. +func TstAppDataDir(goos, appName string, roaming bool) string { + return appDataDir(goos, appName, roaming) +} + +// TstAddressPubKeyHash makes an AddressPubKeyHash, setting the +// unexported fields with the parameters hash and netID. +func TstAddressPubKeyHash(hash [ripemd160.Size]byte, + netID byte) *AddressPubKeyHash { + + return &AddressPubKeyHash{ + hash: hash, + netID: netID, + } +} + +// TstAddressScriptHash makes an AddressScriptHash, setting the +// unexported fields with the parameters hash and netID. +func TstAddressScriptHash(hash [ripemd160.Size]byte, + netID byte) *AddressScriptHash { + + return &AddressScriptHash{ + hash: hash, + netID: netID, + } +} + +// TstAddressWitnessPubKeyHash creates an AddressWitnessPubKeyHash, initiating +// the fields as given. +func TstAddressWitnessPubKeyHash(version byte, program [20]byte, + hrp string) *AddressWitnessPubKeyHash { + + return &AddressWitnessPubKeyHash{ + AddressSegWit{ + hrp: hrp, + witnessVersion: version, + witnessProgram: program[:], + }, + } +} + +// TstAddressWitnessScriptHash creates an AddressWitnessScriptHash, initiating +// the fields as given. +func TstAddressWitnessScriptHash(version byte, program [32]byte, + hrp string) *AddressWitnessScriptHash { + + return &AddressWitnessScriptHash{ + AddressSegWit{ + hrp: hrp, + witnessVersion: version, + witnessProgram: program[:], + }, + } +} + +// TstAddressTaproot creates an AddressTaproot, initiating the fields as given. +func TstAddressTaproot(version byte, program [32]byte, + hrp string) *AddressTaproot { + + return &AddressTaproot{ + AddressSegWit{ + hrp: hrp, + witnessVersion: version, + witnessProgram: program[:], + }, + } +} + +// TstAddressPubKey makes an AddressPubKey, setting the unexported fields with +// the parameters. +func TstAddressPubKey(serializedPubKey []byte, pubKeyFormat PubKeyFormat, + netID byte) *AddressPubKey { + + pubKey, _ := btcec.ParsePubKey(serializedPubKey, btcec.S256()) + return &AddressPubKey{ + pubKeyFormat: pubKeyFormat, + pubKey: pubKey, + pubKeyHashID: netID, + } +} + +// TstAddressSAddr returns the expected script address bytes for +// P2PKH and P2SH bitcoin addresses. +func TstAddressSAddr(addr string) []byte { + decoded := base58.Decode(addr) + return decoded[1 : 1+ripemd160.Size] +} + +// TstAddressSegwitSAddr returns the expected witness program bytes for +// bech32 encoded P2WPKH and P2WSH bitcoin addresses. +func TstAddressSegwitSAddr(addr string) []byte { + _, data, err := bech32.Decode(addr) + if err != nil { + return []byte{} + } + + // First byte is version, rest is base 32 encoded data. + data, err = bech32.ConvertBits(data[1:], 5, 8, false) + if err != nil { + return []byte{} + } + return data +} + +// TstAddressTaprootSAddr returns the expected witness program bytes for a +// bech32m encoded P2TR bitcoin address. +func TstAddressTaprootSAddr(addr string) []byte { + _, data, err := bech32.Decode(addr) + if err != nil { + return []byte{} + } + + // First byte is version, rest is base 32 encoded data. + data, err = bech32.ConvertBits(data[1:], 5, 8, false) + if err != nil { + return []byte{} + } + return data +} diff --git a/btcutil/net.go b/btcutil/net.go new file mode 100644 index 0000000000..bf11733c64 --- /dev/null +++ b/btcutil/net.go @@ -0,0 +1,18 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// +build !appengine + +package btcutil + +import ( + "net" +) + +// interfaceAddrs returns a list of the system's network interface addresses. +// It is wrapped here so that we can substitute it for other functions when +// building for systems that do not allow access to net.InterfaceAddrs(). +func interfaceAddrs() ([]net.Addr, error) { + return net.InterfaceAddrs() +} diff --git a/btcutil/net_noop.go b/btcutil/net_noop.go new file mode 100644 index 0000000000..b0b7c2e40a --- /dev/null +++ b/btcutil/net_noop.go @@ -0,0 +1,19 @@ +// Copyright (c) 2013-2014 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// +build appengine + +package btcutil + +import ( + "net" +) + +// interfaceAddrs returns a list of the system's network interface addresses. +// It is wrapped here so that we can substitute it for a no-op function that +// returns an empty slice of net.Addr when building for systems that do not +// allow access to net.InterfaceAddrs(). +func interfaceAddrs() ([]net.Addr, error) { + return []net.Addr{}, nil +} diff --git a/btcutil/psbt/bip32.go b/btcutil/psbt/bip32.go new file mode 100644 index 0000000000..9fbfc73b61 --- /dev/null +++ b/btcutil/psbt/bip32.go @@ -0,0 +1,77 @@ +package psbt + +import ( + "bytes" + "encoding/binary" +) + +// Bip32Derivation encapsulates the data for the input and output +// Bip32Derivation key-value fields. +// +// TODO(roasbeef): use hdkeychain here instead? +type Bip32Derivation struct { + // PubKey is the raw pubkey serialized in compressed format. + PubKey []byte + + // MasterKeyFingerprint is the finger print of the master pubkey. + MasterKeyFingerprint uint32 + + // Bip32Path is the BIP 32 path with child index as a distinct integer. + Bip32Path []uint32 +} + +// checkValid ensures that the PubKey in the Bip32Derivation struct is valid. +func (pb *Bip32Derivation) checkValid() bool { + return validatePubkey(pb.PubKey) +} + +// Bip32Sorter implements sort.Interface for the Bip32Derivation struct. +type Bip32Sorter []*Bip32Derivation + +func (s Bip32Sorter) Len() int { return len(s) } + +func (s Bip32Sorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func (s Bip32Sorter) Less(i, j int) bool { + return bytes.Compare(s[i].PubKey, s[j].PubKey) < 0 +} + +// readBip32Derivation deserializes a byte slice containing chunks of 4 byte +// little endian encodings of uint32 values, the first of which is the +// masterkeyfingerprint and the remainder of which are the derivation path. +func readBip32Derivation(path []byte) (uint32, []uint32, error) { + + if len(path)%4 != 0 || len(path)/4-1 < 1 { + return 0, nil, ErrInvalidPsbtFormat + } + + masterKeyInt := binary.LittleEndian.Uint32(path[:4]) + + var paths []uint32 + for i := 4; i < len(path); i += 4 { + paths = append(paths, binary.LittleEndian.Uint32(path[i:i+4])) + } + + return masterKeyInt, paths, nil +} + +// SerializeBIP32Derivation takes a master key fingerprint as defined in BIP32, +// along with a path specified as a list of uint32 values, and returns a +// bytestring specifying the derivation in the format required by BIP174: // +// master key fingerprint (4) || child index (4) || child index (4) || .... +func SerializeBIP32Derivation(masterKeyFingerprint uint32, + bip32Path []uint32) []byte { + + var masterKeyBytes [4]byte + binary.LittleEndian.PutUint32(masterKeyBytes[:], masterKeyFingerprint) + + derivationPath := make([]byte, 0, 4+4*len(bip32Path)) + derivationPath = append(derivationPath, masterKeyBytes[:]...) + for _, path := range bip32Path { + var pathbytes [4]byte + binary.LittleEndian.PutUint32(pathbytes[:], path) + derivationPath = append(derivationPath, pathbytes[:]...) + } + + return derivationPath +} diff --git a/btcutil/psbt/creator.go b/btcutil/psbt/creator.go new file mode 100644 index 0000000000..a5f832e0dd --- /dev/null +++ b/btcutil/psbt/creator.go @@ -0,0 +1,63 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package psbt + +import ( + "github.com/btcsuite/btcd/wire" +) + +// MinTxVersion is the lowest transaction version that we'll permit. +const MinTxVersion = 1 + +// New on provision of an input and output 'skeleton' for the transaction, a +// new partially populated PBST packet. The populated packet will include the +// unsigned transaction, and the set of known inputs and outputs contained +// within the unsigned transaction. The values of nLockTime, nSequence (per +// input) and transaction version (must be 1 of 2) must be specified here. Note +// that the default nSequence value is wire.MaxTxInSequenceNum. Referencing +// the PSBT BIP, this function serves the roles of teh Creator. +func New(inputs []*wire.OutPoint, + outputs []*wire.TxOut, version int32, nLockTime uint32, + nSequences []uint32) (*Packet, error) { + + // Create the new struct; the input and output lists will be empty, the + // unsignedTx object must be constructed and serialized, and that + // serialization should be entered as the only entry for the + // globalKVPairs list. + // + // Ensure that the version of the transaction is greater then our + // minimum allowed transaction version. There must be one sequence + // number per input. + if version < MinTxVersion || len(nSequences) != len(inputs) { + return nil, ErrInvalidPsbtFormat + } + + unsignedTx := wire.NewMsgTx(version) + unsignedTx.LockTime = nLockTime + for i, in := range inputs { + unsignedTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: *in, + Sequence: nSequences[i], + }) + } + for _, out := range outputs { + unsignedTx.AddTxOut(out) + } + + // The input and output lists are empty, but there is a list of those + // two lists, and each one must be of length matching the unsigned + // transaction; the unknown list can be nil. + pInputs := make([]PInput, len(unsignedTx.TxIn)) + pOutputs := make([]POutput, len(unsignedTx.TxOut)) + + // This new Psbt is "raw" and contains no key-value fields, so sanity + // checking with c.Cpsbt.SanityCheck() is not required. + return &Packet{ + UnsignedTx: unsignedTx, + Inputs: pInputs, + Outputs: pOutputs, + Unknowns: nil, + }, nil +} diff --git a/btcutil/psbt/extractor.go b/btcutil/psbt/extractor.go new file mode 100644 index 0000000000..dc7f10fddb --- /dev/null +++ b/btcutil/psbt/extractor.go @@ -0,0 +1,81 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package psbt + +// The Extractor requires provision of a single PSBT +// in which all necessary signatures are encoded, and +// uses it to construct a fully valid network serialized +// transaction. + +import ( + "bytes" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +// Extract takes a finalized psbt.Packet and outputs a finalized transaction +// instance. Note that if the PSBT is in-complete, then an error +// ErrIncompletePSBT will be returned. As the extracted transaction has been +// fully finalized, it will be ready for network broadcast once returned. +func Extract(p *Packet) (*wire.MsgTx, error) { + // If the packet isn't complete, then we'll return an error as it + // doesn't have all the required witness data. + if !p.IsComplete() { + return nil, ErrIncompletePSBT + } + + // First, we'll make a copy of the underlying unsigned transaction (the + // initial template) so we don't mutate it during our activates below. + finalTx := p.UnsignedTx.Copy() + + // For each input, we'll now populate any relevant witness and + // sigScript data. + for i, tin := range finalTx.TxIn { + // We'll grab the corresponding internal packet input which + // matches this materialized transaction input and emplace that + // final sigScript (if present). + pInput := p.Inputs[i] + if pInput.FinalScriptSig != nil { + tin.SignatureScript = pInput.FinalScriptSig + } + + // Similarly, if there's a final witness, then we'll also need + // to extract that as well, parsing the lower-level transaction + // encoding. + if pInput.FinalScriptWitness != nil { + // In order to set the witness, need to re-deserialize + // the field as encoded within the PSBT packet. For + // each input, the witness is encoded as a stack with + // one or more items. + witnessReader := bytes.NewReader( + pInput.FinalScriptWitness, + ) + + // First we extract the number of witness elements + // encoded in the above witnessReader. + witCount, err := wire.ReadVarInt(witnessReader, 0) + if err != nil { + return nil, err + } + + // Now that we know how may inputs we'll need, we'll + // construct a packing slice, then read out each input + // (with a varint prefix) from the witnessReader. + tin.Witness = make(wire.TxWitness, witCount) + for j := uint64(0); j < witCount; j++ { + wit, err := wire.ReadVarBytes( + witnessReader, 0, txscript.MaxScriptSize, "witness", + ) + if err != nil { + return nil, err + } + tin.Witness[j] = wit + } + } + } + + return finalTx, nil +} diff --git a/btcutil/psbt/finalizer.go b/btcutil/psbt/finalizer.go new file mode 100644 index 0000000000..0bf9dbb56e --- /dev/null +++ b/btcutil/psbt/finalizer.go @@ -0,0 +1,462 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package psbt + +// The Finalizer requires provision of a single PSBT input +// in which all necessary signatures are encoded, and +// uses it to construct valid final sigScript and scriptWitness +// fields. +// NOTE that p2sh (legacy) and p2wsh currently support only +// multisig and no other custom script. + +import ( + "github.com/btcsuite/btcd/txscript" +) + +// isFinalized considers this input finalized if it contains at least one of +// the FinalScriptSig or FinalScriptWitness are filled (which only occurs in a +// successful call to Finalize*). +func isFinalized(p *Packet, inIndex int) bool { + input := p.Inputs[inIndex] + return input.FinalScriptSig != nil || input.FinalScriptWitness != nil +} + +// isFinalizableWitnessInput returns true if the target input is a witness UTXO +// that can be finalized. +func isFinalizableWitnessInput(pInput *PInput) bool { + pkScript := pInput.WitnessUtxo.PkScript + + switch { + // If this is a native witness output, then we require both + // the witness script, but not a redeem script. + case txscript.IsWitnessProgram(pkScript): + if txscript.IsPayToWitnessScriptHash(pkScript) { + if pInput.WitnessScript == nil || + pInput.RedeemScript != nil { + return false + } + } else { + // A P2WKH output on the other hand doesn't need + // neither a witnessScript or redeemScript. + if pInput.WitnessScript != nil || + pInput.RedeemScript != nil { + return false + } + } + + // For nested P2SH inputs, we verify that a witness script is known. + case txscript.IsPayToScriptHash(pkScript): + if pInput.RedeemScript == nil { + return false + } + + // If this is a nested P2SH input, then it must also have a + // witness script, while we don't need one for P2WKH. + if txscript.IsPayToWitnessScriptHash(pInput.RedeemScript) { + if pInput.WitnessScript == nil { + return false + } + } else if txscript.IsPayToWitnessPubKeyHash(pInput.RedeemScript) { + if pInput.WitnessScript != nil { + return false + } + } else { + // unrecognized type + return false + } + + // If this isn't a nested nested P2SH output or a native witness + // output, then we can't finalize this input as we don't understand it. + default: + return false + } + + return true +} + +// isFinalizableLegacyInput returns true of the passed input a legacy input +// (non-witness) that can be finalized. +func isFinalizableLegacyInput(p *Packet, pInput *PInput, inIndex int) bool { + // If the input has a witness, then it's invalid. + if pInput.WitnessScript != nil { + return false + } + + // Otherwise, we'll verify that we only have a RedeemScript if the prev + // output script is P2SH. + outIndex := p.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index + if txscript.IsPayToScriptHash(pInput.NonWitnessUtxo.TxOut[outIndex].PkScript) { + if pInput.RedeemScript == nil { + return false + } + } else { + if pInput.RedeemScript != nil { + return false + } + } + + return true +} + +// isFinalizable checks whether the structure of the entry for the input of the +// psbt.Packet at index inIndex contains sufficient information to finalize +// this input. +func isFinalizable(p *Packet, inIndex int) bool { + pInput := p.Inputs[inIndex] + + // The input cannot be finalized without any signatures + if pInput.PartialSigs == nil { + return false + } + + // For an input to be finalized, we'll one of two possible top-level + // UTXOs present. Each UTXO type has a distinct set of requirements to + // be considered finalized. + switch { + + // A witness input must be either native P2WSH or nested P2SH with all + // relevant sigScript or witness data populated. + case pInput.WitnessUtxo != nil: + if !isFinalizableWitnessInput(&pInput) { + return false + } + + case pInput.NonWitnessUtxo != nil: + if !isFinalizableLegacyInput(p, &pInput, inIndex) { + return false + } + + // If neither a known UTXO type isn't present at all, then we'll + // return false as we need one of them. + default: + return false + } + + return true +} + +// MaybeFinalize attempts to finalize the input at index inIndex in the PSBT p, +// returning true with no error if it succeeds, OR if the input has already +// been finalized. +func MaybeFinalize(p *Packet, inIndex int) (bool, error) { + if isFinalized(p, inIndex) { + return true, nil + } + + if !isFinalizable(p, inIndex) { + return false, ErrNotFinalizable + } + + if err := Finalize(p, inIndex); err != nil { + return false, err + } + + return true, nil +} + +// MaybeFinalizeAll attempts to finalize all inputs of the psbt.Packet that are +// not already finalized, and returns an error if it fails to do so. +func MaybeFinalizeAll(p *Packet) error { + + for i := range p.UnsignedTx.TxIn { + success, err := MaybeFinalize(p, i) + if err != nil || !success { + return err + } + } + + return nil +} + +// Finalize assumes that the provided psbt.Packet struct has all partial +// signatures and redeem scripts/witness scripts already prepared for the +// specified input, and so removes all temporary data and replaces them with +// completed sigScript and witness fields, which are stored in key-types 07 and +// 08. The witness/non-witness utxo fields in the inputs (key-types 00 and 01) +// are left intact as they may be needed for validation (?). If there is any +// invalid or incomplete data, an error is returned. +func Finalize(p *Packet, inIndex int) error { + pInput := p.Inputs[inIndex] + + // Depending on the UTXO type, we either attempt to finalize it as a + // witness or legacy UTXO. + switch { + case pInput.WitnessUtxo != nil: + if err := finalizeWitnessInput(p, inIndex); err != nil { + return err + } + + case pInput.NonWitnessUtxo != nil: + if err := finalizeNonWitnessInput(p, inIndex); err != nil { + return err + } + + default: + return ErrInvalidPsbtFormat + } + + // Before returning we sanity check the PSBT to ensure we don't extract + // an invalid transaction or produce an invalid intermediate state. + if err := p.SanityCheck(); err != nil { + return err + } + + return nil +} + +// checkFinalScriptSigWitness checks whether a given input in the psbt.Packet +// struct already has the fields 07 (FinalInScriptSig) or 08 (FinalInWitness). +// If so, it returns true. It does not modify the Psbt. +func checkFinalScriptSigWitness(p *Packet, inIndex int) bool { + pInput := p.Inputs[inIndex] + + if pInput.FinalScriptSig != nil { + return true + } + + if pInput.FinalScriptWitness != nil { + return true + } + + return false +} + +// finalizeNonWitnessInput attempts to create a PsbtInFinalScriptSig field for +// the input at index inIndex, and removes all other fields except for the UTXO +// field, for an input of type non-witness, or returns an error. +func finalizeNonWitnessInput(p *Packet, inIndex int) error { + // If this input has already been finalized, then we'll return an error + // as we can't proceed. + if checkFinalScriptSigWitness(p, inIndex) { + return ErrInputAlreadyFinalized + } + + // Our goal here is to construct a sigScript given the pubkey, + // signature (keytype 02), of which there might be multiple, and the + // redeem script field (keytype 04) if present (note, it is not present + // for p2pkh type inputs). + var sigScript []byte + + pInput := p.Inputs[inIndex] + containsRedeemScript := pInput.RedeemScript != nil + + var ( + pubKeys [][]byte + sigs [][]byte + ) + for _, ps := range pInput.PartialSigs { + pubKeys = append(pubKeys, ps.PubKey) + + sigOK := checkSigHashFlags(ps.Signature, &pInput) + if !sigOK { + return ErrInvalidSigHashFlags + } + + sigs = append(sigs, ps.Signature) + } + + // We have failed to identify at least 1 (sig, pub) pair in the PSBT, + // which indicates it was not ready to be finalized. As a result, we + // can't proceed. + if len(sigs) < 1 || len(pubKeys) < 1 { + return ErrNotFinalizable + } + + // If this input doesn't need a redeem script (P2PKH), then we'll + // construct a simple sigScript that's just the signature then the + // pubkey (OP_CHECKSIG). + var err error + if !containsRedeemScript { + // At this point, we should only have a single signature and + // pubkey. + if len(sigs) != 1 || len(pubKeys) != 1 { + return ErrNotFinalizable + } + + // In this case, our sigScript is just: . + builder := txscript.NewScriptBuilder() + builder.AddData(sigs[0]).AddData(pubKeys[0]) + sigScript, err = builder.Script() + if err != nil { + return err + } + } else { + // This is assumed p2sh multisig Given redeemScript and pubKeys + // we can decide in what order signatures must be appended. + orderedSigs, err := extractKeyOrderFromScript( + pInput.RedeemScript, pubKeys, sigs, + ) + if err != nil { + return err + } + + // At this point, we assume that this is a mult-sig input, so + // we construct our sigScript which looks something like this + // (mind the extra element for the extra multi-sig pop): + // * + // + // TODO(waxwing): the below is specific to the multisig case. + builder := txscript.NewScriptBuilder() + builder.AddOp(txscript.OP_FALSE) + for _, os := range orderedSigs { + builder.AddData(os) + } + builder.AddData(pInput.RedeemScript) + sigScript, err = builder.Script() + if err != nil { + return err + } + } + + // At this point, a sigScript has been constructed. Remove all fields + // other than non-witness utxo (00) and finaliscriptsig (07) + newInput := NewPsbtInput(pInput.NonWitnessUtxo, nil) + newInput.FinalScriptSig = sigScript + + // Overwrite the entry in the input list at the correct index. Note + // that this removes all the other entries in the list for this input + // index. + p.Inputs[inIndex] = *newInput + + return nil +} + +// finalizeWitnessInput attempts to create PsbtInFinalScriptSig field and +// PsbtInFinalScriptWitness field for input at index inIndex, and removes all +// other fields except for the utxo field, for an input of type witness, or +// returns an error. +func finalizeWitnessInput(p *Packet, inIndex int) error { + // If this input has already been finalized, then we'll return an error + // as we can't proceed. + if checkFinalScriptSigWitness(p, inIndex) { + return ErrInputAlreadyFinalized + } + + // Depending on the actual output type, we'll either populate a + // serializedWitness or a witness as well asa sigScript. + var ( + sigScript []byte + serializedWitness []byte + ) + + pInput := p.Inputs[inIndex] + + // First we'll validate and collect the pubkey+sig pairs from the set + // of partial signatures. + var ( + pubKeys [][]byte + sigs [][]byte + ) + for _, ps := range pInput.PartialSigs { + pubKeys = append(pubKeys, ps.PubKey) + + sigOK := checkSigHashFlags(ps.Signature, &pInput) + if !sigOK { + return ErrInvalidSigHashFlags + + } + + sigs = append(sigs, ps.Signature) + } + + // If at this point, we don't have any pubkey+sig pairs, then we bail + // as we can't proceed. + if len(sigs) == 0 || len(pubKeys) == 0 { + return ErrNotFinalizable + } + + containsRedeemScript := pInput.RedeemScript != nil + cointainsWitnessScript := pInput.WitnessScript != nil + + // If there's no redeem script, then we assume that this is native + // segwit input. + var err error + if !containsRedeemScript { + // If we have only a sigley pubkey+sig pair, and no witness + // script, then we assume this is a P2WKH input. + if len(pubKeys) == 1 && len(sigs) == 1 && + !cointainsWitnessScript { + + serializedWitness, err = writePKHWitness( + sigs[0], pubKeys[0], + ) + if err != nil { + return err + } + } else { + // Otherwise, we must have a witnessScript field, so + // we'll generate a valid multi-sig witness. + // + // NOTE: We tacitly assume multisig. + // + // TODO(roasbeef): need to add custom finalize for + // non-multisig P2WSH outputs (HTLCs, delay outputs, + // etc). + if !cointainsWitnessScript { + return ErrNotFinalizable + } + + serializedWitness, err = getMultisigScriptWitness( + pInput.WitnessScript, pubKeys, sigs, + ) + if err != nil { + return err + } + } + } else { + // Otherwise, we assume that this is a p2wsh multi-sig output, + // which is nested in a p2sh, or a p2wkh nested in a p2sh. + // + // In this case, we'll take the redeem script (the witness + // program in this case), and push it on the stack within the + // sigScript. + builder := txscript.NewScriptBuilder() + builder.AddData(pInput.RedeemScript) + sigScript, err = builder.Script() + if err != nil { + return err + } + + // If don't have a witness script, then we assume this is a + // nested p2wkh output. + if !cointainsWitnessScript { + // Assumed p2sh-p2wkh Here the witness is just (sig, + // pub) as for p2pkh case + if len(sigs) != 1 || len(pubKeys) != 1 { + return ErrNotFinalizable + } + + serializedWitness, err = writePKHWitness(sigs[0], pubKeys[0]) + if err != nil { + return err + } + + } else { + // Otherwise, we assume that this is a p2wsh multi-sig, + // so we generate the proper witness. + serializedWitness, err = getMultisigScriptWitness( + pInput.WitnessScript, pubKeys, sigs, + ) + if err != nil { + return err + } + } + } + + // At this point, a witness has been constructed, and a sigScript (if + // nested; else it's []). Remove all fields other than witness utxo + // (01) and finalscriptsig (07), finalscriptwitness (08). + newInput := NewPsbtInput(nil, pInput.WitnessUtxo) + if len(sigScript) > 0 { + newInput.FinalScriptSig = sigScript + } + + newInput.FinalScriptWitness = serializedWitness + + // Finally, we overwrite the entry in the input list at the correct + // index. + p.Inputs[inIndex] = *newInput + return nil +} diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod new file mode 100644 index 0000000000..55ac1ca956 --- /dev/null +++ b/btcutil/psbt/go.mod @@ -0,0 +1,17 @@ +module github.com/btcsuite/btcd/btcutil/psbt + +go 1.17 + +require ( + github.com/btcsuite/btcd v0.20.1-beta + github.com/btcsuite/btcd/btcutil v0.0.0-20190425235716-9e5f4b9a998d + github.com/davecgh/go-spew v1.1.1 +) + +require ( + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect +) + +replace github.com/btcsuite/btcd/btcutil => ../ diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum new file mode 100644 index 0000000000..4898b254c6 --- /dev/null +++ b/btcutil/psbt/go.sum @@ -0,0 +1,39 @@ +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/psbt/partial_input.go b/btcutil/psbt/partial_input.go new file mode 100644 index 0000000000..4783c74d31 --- /dev/null +++ b/btcutil/psbt/partial_input.go @@ -0,0 +1,361 @@ +package psbt + +import ( + "bytes" + "encoding/binary" + "io" + "sort" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +// PInput is a struct encapsulating all the data that can be attached to any +// specific input of the PSBT. +type PInput struct { + NonWitnessUtxo *wire.MsgTx + WitnessUtxo *wire.TxOut + PartialSigs []*PartialSig + SighashType txscript.SigHashType + RedeemScript []byte + WitnessScript []byte + Bip32Derivation []*Bip32Derivation + FinalScriptSig []byte + FinalScriptWitness []byte + Unknowns []*Unknown +} + +// NewPsbtInput creates an instance of PsbtInput given either a nonWitnessUtxo +// or a witnessUtxo. +// +// NOTE: Only one of the two arguments should be specified, with the other +// being `nil`; otherwise the created PsbtInput object will fail IsSane() +// checks and will not be usable. +func NewPsbtInput(nonWitnessUtxo *wire.MsgTx, + witnessUtxo *wire.TxOut) *PInput { + + return &PInput{ + NonWitnessUtxo: nonWitnessUtxo, + WitnessUtxo: witnessUtxo, + PartialSigs: []*PartialSig{}, + SighashType: 0, + RedeemScript: nil, + WitnessScript: nil, + Bip32Derivation: []*Bip32Derivation{}, + FinalScriptSig: nil, + FinalScriptWitness: nil, + Unknowns: nil, + } +} + +// IsSane returns true only if there are no conflicting values in the Psbt +// PInput. For segwit v0 no checks are currently implemented. +func (pi *PInput) IsSane() bool { + + // TODO(guggero): Implement sanity checks for segwit v1. For segwit v0 + // it is unsafe to only rely on the witness UTXO so we don't check that + // only one is set anymore. + // See https://github.com/bitcoin/bitcoin/pull/19215. + + return true +} + +// deserialize attempts to deserialize a new PInput from the passed io.Reader. +func (pi *PInput) deserialize(r io.Reader) error { + for { + keyint, keydata, err := getKey(r) + if err != nil { + return err + } + if keyint == -1 { + // Reached separator byte + break + } + value, err := wire.ReadVarBytes( + r, 0, MaxPsbtValueLength, "PSBT value", + ) + if err != nil { + return err + } + + switch InputType(keyint) { + + case NonWitnessUtxoType: + if pi.NonWitnessUtxo != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + tx := wire.NewMsgTx(2) + + err := tx.Deserialize(bytes.NewReader(value)) + if err != nil { + return err + } + pi.NonWitnessUtxo = tx + + case WitnessUtxoType: + if pi.WitnessUtxo != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + txout, err := readTxOut(value) + if err != nil { + return err + } + pi.WitnessUtxo = txout + + case PartialSigType: + newPartialSig := PartialSig{ + PubKey: keydata, + Signature: value, + } + + if !newPartialSig.checkValid() { + return ErrInvalidPsbtFormat + } + + // Duplicate keys are not allowed + for _, x := range pi.PartialSigs { + if bytes.Equal(x.PubKey, newPartialSig.PubKey) { + return ErrDuplicateKey + } + } + + pi.PartialSigs = append(pi.PartialSigs, &newPartialSig) + + case SighashType: + if pi.SighashType != 0 { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + // Bounds check on value here since the sighash type must be a + // 32-bit unsigned integer. + if len(value) != 4 { + return ErrInvalidKeydata + } + + shtype := txscript.SigHashType( + binary.LittleEndian.Uint32(value), + ) + pi.SighashType = shtype + + case RedeemScriptInputType: + if pi.RedeemScript != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + pi.RedeemScript = value + + case WitnessScriptInputType: + if pi.WitnessScript != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + pi.WitnessScript = value + + case Bip32DerivationInputType: + if !validatePubkey(keydata) { + return ErrInvalidPsbtFormat + } + master, derivationPath, err := readBip32Derivation(value) + if err != nil { + return err + } + + // Duplicate keys are not allowed + for _, x := range pi.Bip32Derivation { + if bytes.Equal(x.PubKey, keydata) { + return ErrDuplicateKey + } + } + + pi.Bip32Derivation = append( + pi.Bip32Derivation, + &Bip32Derivation{ + PubKey: keydata, + MasterKeyFingerprint: master, + Bip32Path: derivationPath, + }, + ) + + case FinalScriptSigType: + if pi.FinalScriptSig != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + pi.FinalScriptSig = value + + case FinalScriptWitnessType: + if pi.FinalScriptWitness != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + pi.FinalScriptWitness = value + + default: + // A fall through case for any proprietary types. + keyintanddata := []byte{byte(keyint)} + keyintanddata = append(keyintanddata, keydata...) + newUnknown := &Unknown{ + Key: keyintanddata, + Value: value, + } + + // Duplicate key+keydata are not allowed + for _, x := range pi.Unknowns { + if bytes.Equal(x.Key, newUnknown.Key) && + bytes.Equal(x.Value, newUnknown.Value) { + return ErrDuplicateKey + } + } + + pi.Unknowns = append(pi.Unknowns, newUnknown) + } + } + + return nil +} + +// serialize attempts to serialize the target PInput into the passed io.Writer. +func (pi *PInput) serialize(w io.Writer) error { + + if !pi.IsSane() { + return ErrInvalidPsbtFormat + } + + if pi.NonWitnessUtxo != nil { + var buf bytes.Buffer + err := pi.NonWitnessUtxo.Serialize(&buf) + if err != nil { + return err + } + + err = serializeKVPairWithType( + w, uint8(NonWitnessUtxoType), nil, buf.Bytes(), + ) + if err != nil { + return err + } + } + if pi.WitnessUtxo != nil { + var buf bytes.Buffer + err := wire.WriteTxOut(&buf, 0, 0, pi.WitnessUtxo) + if err != nil { + return err + } + + err = serializeKVPairWithType( + w, uint8(WitnessUtxoType), nil, buf.Bytes(), + ) + if err != nil { + return err + } + } + + if pi.FinalScriptSig == nil && pi.FinalScriptWitness == nil { + sort.Sort(PartialSigSorter(pi.PartialSigs)) + for _, ps := range pi.PartialSigs { + err := serializeKVPairWithType( + w, uint8(PartialSigType), ps.PubKey, + ps.Signature, + ) + if err != nil { + return err + } + } + + if pi.SighashType != 0 { + var shtBytes [4]byte + binary.LittleEndian.PutUint32( + shtBytes[:], uint32(pi.SighashType), + ) + + err := serializeKVPairWithType( + w, uint8(SighashType), nil, shtBytes[:], + ) + if err != nil { + return err + } + } + + if pi.RedeemScript != nil { + err := serializeKVPairWithType( + w, uint8(RedeemScriptInputType), nil, + pi.RedeemScript, + ) + if err != nil { + return err + } + } + + if pi.WitnessScript != nil { + err := serializeKVPairWithType( + w, uint8(WitnessScriptInputType), nil, + pi.WitnessScript, + ) + if err != nil { + return err + } + } + + sort.Sort(Bip32Sorter(pi.Bip32Derivation)) + for _, kd := range pi.Bip32Derivation { + err := serializeKVPairWithType( + w, + uint8(Bip32DerivationInputType), kd.PubKey, + SerializeBIP32Derivation( + kd.MasterKeyFingerprint, kd.Bip32Path, + ), + ) + if err != nil { + return err + } + } + } + + if pi.FinalScriptSig != nil { + err := serializeKVPairWithType( + w, uint8(FinalScriptSigType), nil, pi.FinalScriptSig, + ) + if err != nil { + return err + } + } + + if pi.FinalScriptWitness != nil { + err := serializeKVPairWithType( + w, uint8(FinalScriptWitnessType), nil, pi.FinalScriptWitness, + ) + if err != nil { + return err + } + } + + // Unknown is a special case; we don't have a key type, only a key and + // a value field + for _, kv := range pi.Unknowns { + err := serializeKVpair(w, kv.Key, kv.Value) + if err != nil { + return err + } + } + + return nil +} diff --git a/btcutil/psbt/partial_output.go b/btcutil/psbt/partial_output.go new file mode 100644 index 0000000000..64d1bd4cae --- /dev/null +++ b/btcutil/psbt/partial_output.go @@ -0,0 +1,139 @@ +package psbt + +import ( + "bytes" + "io" + "sort" + + "github.com/btcsuite/btcd/wire" +) + +// POutput is a struct encapsulating all the data that can be attached +// to any specific output of the PSBT. +type POutput struct { + RedeemScript []byte + WitnessScript []byte + Bip32Derivation []*Bip32Derivation +} + +// NewPsbtOutput creates an instance of PsbtOutput; the three parameters +// redeemScript, witnessScript and Bip32Derivation are all allowed to be +// `nil`. +func NewPsbtOutput(redeemScript []byte, witnessScript []byte, + bip32Derivation []*Bip32Derivation) *POutput { + return &POutput{ + RedeemScript: redeemScript, + WitnessScript: witnessScript, + Bip32Derivation: bip32Derivation, + } +} + +// deserialize attempts to recode a new POutput from the passed io.Reader. +func (po *POutput) deserialize(r io.Reader) error { + for { + keyint, keydata, err := getKey(r) + if err != nil { + return err + } + if keyint == -1 { + // Reached separator byte + break + } + + value, err := wire.ReadVarBytes( + r, 0, MaxPsbtValueLength, "PSBT value", + ) + if err != nil { + return err + } + + switch OutputType(keyint) { + + case RedeemScriptOutputType: + if po.RedeemScript != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + po.RedeemScript = value + + case WitnessScriptOutputType: + if po.WitnessScript != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + po.WitnessScript = value + + case Bip32DerivationOutputType: + if !validatePubkey(keydata) { + return ErrInvalidKeydata + } + master, derivationPath, err := readBip32Derivation(value) + if err != nil { + return err + } + + // Duplicate keys are not allowed + for _, x := range po.Bip32Derivation { + if bytes.Equal(x.PubKey, keydata) { + return ErrDuplicateKey + } + } + + po.Bip32Derivation = append(po.Bip32Derivation, + &Bip32Derivation{ + PubKey: keydata, + MasterKeyFingerprint: master, + Bip32Path: derivationPath, + }, + ) + + default: + // Unknown type is allowed for inputs but not outputs. + return ErrInvalidPsbtFormat + } + } + + return nil +} + +// serialize attempts to write out the target POutput into the passed +// io.Writer. +func (po *POutput) serialize(w io.Writer) error { + if po.RedeemScript != nil { + err := serializeKVPairWithType( + w, uint8(RedeemScriptOutputType), nil, po.RedeemScript, + ) + if err != nil { + return err + } + } + if po.WitnessScript != nil { + err := serializeKVPairWithType( + w, uint8(WitnessScriptOutputType), nil, po.WitnessScript, + ) + if err != nil { + return err + } + } + + sort.Sort(Bip32Sorter(po.Bip32Derivation)) + for _, kd := range po.Bip32Derivation { + err := serializeKVPairWithType(w, + uint8(Bip32DerivationOutputType), + kd.PubKey, + SerializeBIP32Derivation( + kd.MasterKeyFingerprint, + kd.Bip32Path, + ), + ) + if err != nil { + return err + } + } + + return nil +} diff --git a/btcutil/psbt/partialsig.go b/btcutil/psbt/partialsig.go new file mode 100644 index 0000000000..e11bb80de7 --- /dev/null +++ b/btcutil/psbt/partialsig.go @@ -0,0 +1,52 @@ +package psbt + +import ( + "bytes" + + "github.com/btcsuite/btcd/btcec" +) + +// PartialSig encapsulate a (BTC public key, ECDSA signature) +// pair, note that the fields are stored as byte slices, not +// btcec.PublicKey or btcec.Signature (because manipulations will +// be with the former not the latter, here); compliance with consensus +// serialization is enforced with .checkValid() +type PartialSig struct { + PubKey []byte + Signature []byte +} + +// PartialSigSorter implements sort.Interface for PartialSig. +type PartialSigSorter []*PartialSig + +func (s PartialSigSorter) Len() int { return len(s) } + +func (s PartialSigSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func (s PartialSigSorter) Less(i, j int) bool { + return bytes.Compare(s[i].PubKey, s[j].PubKey) < 0 +} + +// validatePubkey checks if pubKey is *any* valid pubKey serialization in a +// Bitcoin context (compressed/uncomp. OK). +func validatePubkey(pubKey []byte) bool { + _, err := btcec.ParsePubKey(pubKey, btcec.S256()) + return err == nil +} + +// validateSignature checks that the passed byte slice is a valid DER-encoded +// ECDSA signature, including the sighash flag. It does *not* of course +// validate the signature against any message or public key. +func validateSignature(sig []byte) bool { + _, err := btcec.ParseDERSignature(sig, btcec.S256()) + return err == nil +} + +// checkValid checks that both the pbukey and sig are valid. See the methods +// (PartialSig, validatePubkey, validateSignature) for more details. +// +// TODO(waxwing): update for Schnorr will be needed here if/when that +// activates. +func (ps *PartialSig) checkValid() bool { + return validatePubkey(ps.PubKey) && validateSignature(ps.Signature) +} diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go new file mode 100644 index 0000000000..73126c3eb2 --- /dev/null +++ b/btcutil/psbt/psbt.go @@ -0,0 +1,407 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// Package psbt is an implementation of Partially Signed Bitcoin +// Transactions (PSBT). The format is defined in BIP 174: +// https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki +package psbt + +import ( + "bytes" + "encoding/base64" + "errors" + + "io" + + "github.com/btcsuite/btcd/wire" +) + +// psbtMagicLength is the length of the magic bytes used to signal the start of +// a serialized PSBT packet. +const psbtMagicLength = 5 + +var ( + // psbtMagic is the separator + psbtMagic = [psbtMagicLength]byte{0x70, + 0x73, 0x62, 0x74, 0xff, // = "psbt" + 0xff sep + } +) + +// MaxPsbtValueLength is the size of the largest transaction serialization +// that could be passed in a NonWitnessUtxo field. This is definitely +//less than 4M. +const MaxPsbtValueLength = 4000000 + +// MaxPsbtKeyLength is the length of the largest key that we'll successfully +// deserialize from the wire. Anything more will return ErrInvalidKeydata. +const MaxPsbtKeyLength = 10000 + +var ( + + // ErrInvalidPsbtFormat is a generic error for any situation in which a + // provided Psbt serialization does not conform to the rules of BIP174. + ErrInvalidPsbtFormat = errors.New("Invalid PSBT serialization format") + + // ErrDuplicateKey indicates that a passed Psbt serialization is invalid + // due to having the same key repeated in the same key-value pair. + ErrDuplicateKey = errors.New("Invalid Psbt due to duplicate key") + + // ErrInvalidKeydata indicates that a key-value pair in the PSBT + // serialization contains data in the key which is not valid. + ErrInvalidKeydata = errors.New("Invalid key data") + + // ErrInvalidMagicBytes indicates that a passed Psbt serialization is invalid + // due to having incorrect magic bytes. + ErrInvalidMagicBytes = errors.New("Invalid Psbt due to incorrect magic bytes") + + // ErrInvalidRawTxSigned indicates that the raw serialized transaction in the + // global section of the passed Psbt serialization is invalid because it + // contains scriptSigs/witnesses (i.e. is fully or partially signed), which + // is not allowed by BIP174. + ErrInvalidRawTxSigned = errors.New("Invalid Psbt, raw transaction must " + + "be unsigned.") + + // ErrInvalidPrevOutNonWitnessTransaction indicates that the transaction + // hash (i.e. SHA256^2) of the fully serialized previous transaction + // provided in the NonWitnessUtxo key-value field doesn't match the prevout + // hash in the UnsignedTx field in the PSBT itself. + ErrInvalidPrevOutNonWitnessTransaction = errors.New("Prevout hash does " + + "not match the provided non-witness utxo serialization") + + // ErrInvalidSignatureForInput indicates that the signature the user is + // trying to append to the PSBT is invalid, either because it does + // not correspond to the previous transaction hash, or redeem script, + // or witness script. + // NOTE this does not include ECDSA signature checking. + ErrInvalidSignatureForInput = errors.New("Signature does not correspond " + + "to this input") + + // ErrInputAlreadyFinalized indicates that the PSBT passed to a Finalizer + // already contains the finalized scriptSig or witness. + ErrInputAlreadyFinalized = errors.New("Cannot finalize PSBT, finalized " + + "scriptSig or scriptWitnes already exists") + + // ErrIncompletePSBT indicates that the Extractor object + // was unable to successfully extract the passed Psbt struct because + // it is not complete + ErrIncompletePSBT = errors.New("PSBT cannot be extracted as it is " + + "incomplete") + + // ErrNotFinalizable indicates that the PSBT struct does not have + // sufficient data (e.g. signatures) for finalization + ErrNotFinalizable = errors.New("PSBT is not finalizable") + + // ErrInvalidSigHashFlags indicates that a signature added to the PSBT + // uses Sighash flags that are not in accordance with the requirement + // according to the entry in PsbtInSighashType, or otherwise not the + // default value (SIGHASH_ALL) + ErrInvalidSigHashFlags = errors.New("Invalid Sighash Flags") + + // ErrUnsupportedScriptType indicates that the redeem script or + // scriptwitness given is not supported by this codebase, or is otherwise + // not valid. + ErrUnsupportedScriptType = errors.New("Unsupported script type") +) + +// Unknown is a struct encapsulating a key-value pair for which the key type is +// unknown by this package; these fields are allowed in both the 'Global' and +// the 'Input' section of a PSBT. +type Unknown struct { + Key []byte + Value []byte +} + +// Packet is the actual psbt repreesntation. It is a is a set of 1 + N + M +// key-value pair lists, 1 global, defining the unsigned transaction structure +// with N inputs and M outputs. These key-value pairs can contain scripts, +// signatures, key derivations and other transaction-defining data. +type Packet struct { + // UnsignedTx is the decoded unsigned transaction for this PSBT. + UnsignedTx *wire.MsgTx // Deserialization of unsigned tx + + // Inputs contains all the information needed to properly sign this + // target input within the above transaction. + Inputs []PInput + + // Outputs contains all information required to spend any outputs + // produced by this PSBT. + Outputs []POutput + + // Unknowns are the set of custom types (global only) within this PSBT. + Unknowns []Unknown +} + +// validateUnsignedTx returns true if the transaction is unsigned. Note that +// more basic sanity requirements, such as the presence of inputs and outputs, +// is implicitly checked in the call to MsgTx.Deserialize(). +func validateUnsignedTX(tx *wire.MsgTx) bool { + for _, tin := range tx.TxIn { + if len(tin.SignatureScript) != 0 || len(tin.Witness) != 0 { + return false + } + } + + return true +} + +// NewFromUnsignedTx creates a new Psbt struct, without any signatures (i.e. +// only the global section is non-empty) using the passed unsigned transaction. +func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) { + + if !validateUnsignedTX(tx) { + return nil, ErrInvalidRawTxSigned + } + + inSlice := make([]PInput, len(tx.TxIn)) + outSlice := make([]POutput, len(tx.TxOut)) + unknownSlice := make([]Unknown, 0) + + retPsbt := Packet{ + UnsignedTx: tx, + Inputs: inSlice, + Outputs: outSlice, + Unknowns: unknownSlice, + } + + return &retPsbt, nil +} + +// NewFromRawBytes returns a new instance of a Packet struct created by reading +// from a byte slice. If the format is invalid, an error is returned. If the +// argument b64 is true, the passed byte slice is decoded from base64 encoding +// before processing. +// +// NOTE: To create a Packet from one's own data, rather than reading in a +// serialization from a counterparty, one should use a psbt.New. +func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { + + // If the PSBT is encoded in bas64, then we'll create a new wrapper + // reader that'll allow us to incrementally decode the contents of the + // io.Reader. + if b64 { + based64EncodedReader := r + r = base64.NewDecoder(base64.StdEncoding, based64EncodedReader) + } + + // The Packet struct does not store the fixed magic bytes, but they + // must be present or the serialization must be explicitly rejected. + var magic [5]byte + if _, err := io.ReadFull(r, magic[:]); err != nil { + return nil, err + } + if magic != psbtMagic { + return nil, ErrInvalidMagicBytes + } + + // Next we parse the GLOBAL section. There is currently only 1 known + // key type, UnsignedTx. We insist this exists first; unknowns are + // allowed, but only after. + keyint, keydata, err := getKey(r) + if err != nil { + return nil, err + } + if GlobalType(keyint) != UnsignedTxType || keydata != nil { + return nil, ErrInvalidPsbtFormat + } + + // Now that we've verified the global type is present, we'll decode it + // into a proper unsigned transaction, and validate it. + value, err := wire.ReadVarBytes( + r, 0, MaxPsbtValueLength, "PSBT value", + ) + if err != nil { + return nil, err + } + msgTx := wire.NewMsgTx(2) + err = msgTx.Deserialize(bytes.NewReader(value)) + if err != nil { + // If there are no inputs in this yet incomplete transaction, + // the wire package still incorrectly assumes it's encoded in + // the witness format. We can fix this by just trying the non- + // witness encoding too. If that also fails, it's probably an + // invalid transaction. + msgTx = wire.NewMsgTx(2) + err2 := msgTx.DeserializeNoWitness(bytes.NewReader(value)) + + // If the second attempt also failed, something else is wrong + // and it probably makes more sense to return the original + // error instead of the error from the workaround. + if err2 != nil { + return nil, err + } + } + if !validateUnsignedTX(msgTx) { + return nil, ErrInvalidRawTxSigned + } + + // Next we parse any unknowns that may be present, making sure that we + // break at the separator. + var unknownSlice []Unknown + for { + keyint, keydata, err := getKey(r) + if err != nil { + return nil, ErrInvalidPsbtFormat + } + if keyint == -1 { + break + } + + value, err := wire.ReadVarBytes( + r, 0, MaxPsbtValueLength, "PSBT value", + ) + if err != nil { + return nil, err + } + + keyintanddata := []byte{byte(keyint)} + keyintanddata = append(keyintanddata, keydata...) + + newUnknown := Unknown{ + Key: keyintanddata, + Value: value, + } + unknownSlice = append(unknownSlice, newUnknown) + } + + // Next we parse the INPUT section. + inSlice := make([]PInput, len(msgTx.TxIn)) + for i := range msgTx.TxIn { + input := PInput{} + err = input.deserialize(r) + if err != nil { + return nil, err + } + + inSlice[i] = input + } + + // Next we parse the OUTPUT section. + outSlice := make([]POutput, len(msgTx.TxOut)) + for i := range msgTx.TxOut { + output := POutput{} + err = output.deserialize(r) + if err != nil { + return nil, err + } + + outSlice[i] = output + } + + // Populate the new Packet object + newPsbt := Packet{ + UnsignedTx: msgTx, + Inputs: inSlice, + Outputs: outSlice, + Unknowns: unknownSlice, + } + + // Extended sanity checking is applied here to make sure the + // externally-passed Packet follows all the rules. + if err = newPsbt.SanityCheck(); err != nil { + return nil, err + } + + return &newPsbt, nil +} + +// Serialize creates a binary serialization of the referenced Packet struct +// with lexicographical ordering (by key) of the subsections. +func (p *Packet) Serialize(w io.Writer) error { + + // First we write out the precise set of magic bytes that identify a + // valid PSBT transaction. + if _, err := w.Write(psbtMagic[:]); err != nil { + return err + } + + // Next we prep to write out the unsigned transaction by first + // serializing it into an intermediate buffer. + serializedTx := bytes.NewBuffer( + make([]byte, 0, p.UnsignedTx.SerializeSize()), + ) + if err := p.UnsignedTx.Serialize(serializedTx); err != nil { + return err + } + + // Now that we have the serialized transaction, we'll write it out to + // the proper global type. + err := serializeKVPairWithType( + w, uint8(UnsignedTxType), nil, serializedTx.Bytes(), + ) + if err != nil { + return err + } + + // With that our global section is done, so we'll write out the + // separator. + separator := []byte{0x00} + if _, err := w.Write(separator); err != nil { + return err + } + + for _, pInput := range p.Inputs { + err := pInput.serialize(w) + if err != nil { + return err + } + + if _, err := w.Write(separator); err != nil { + return err + } + } + + for _, pOutput := range p.Outputs { + err := pOutput.serialize(w) + if err != nil { + return err + } + + if _, err := w.Write(separator); err != nil { + return err + } + } + + return nil +} + +// B64Encode returns the base64 encoding of the serialization of +// the current PSBT, or an error if the encoding fails. +func (p *Packet) B64Encode() (string, error) { + var b bytes.Buffer + if err := p.Serialize(&b); err != nil { + return "", err + } + + return base64.StdEncoding.EncodeToString(b.Bytes()), nil +} + +// IsComplete returns true only if all of the inputs are +// finalized; this is particularly important in that it decides +// whether the final extraction to a network serialized signed +// transaction will be possible. +func (p *Packet) IsComplete() bool { + for i := 0; i < len(p.UnsignedTx.TxIn); i++ { + if !isFinalized(p, i) { + return false + } + } + return true +} + +// SanityCheck checks conditions on a PSBT to ensure that it obeys the +// rules of BIP174, and returns true if so, false if not. +func (p *Packet) SanityCheck() error { + + if !validateUnsignedTX(p.UnsignedTx) { + return ErrInvalidRawTxSigned + } + + for _, tin := range p.Inputs { + if !tin.IsSane() { + return ErrInvalidPsbtFormat + } + } + + return nil +} diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go new file mode 100644 index 0000000000..12038fbfa0 --- /dev/null +++ b/btcutil/psbt/psbt_test.go @@ -0,0 +1,1448 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package psbt + +import ( + "bytes" + "encoding/base64" + "encoding/binary" + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" + "github.com/davecgh/go-spew/spew" +) + +// Test vectors from: +// // https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#test-vectors + +// createPsbtFromSignedTx is a utility function to create a PSBT from an +// already-signed transaction, so we can test reconstructing, signing and +// extracting it. Returned are: an unsigned transaction serialization, a list +// of scriptSigs, one per input, and a list of witnesses, one per input. +func createPsbtFromSignedTx(serializedSignedTx []byte) ( + *Packet, [][]byte, []wire.TxWitness, error) { + + tx := wire.NewMsgTx(2) + err := tx.Deserialize(bytes.NewReader(serializedSignedTx)) + if err != nil { + return nil, nil, nil, err + } + scriptSigs := make([][]byte, 0, len(tx.TxIn)) + witnesses := make([]wire.TxWitness, 0, len(tx.TxIn)) + tx2 := tx.Copy() + + // Blank out signature info in inputs + for i, tin := range tx2.TxIn { + tin.SignatureScript = nil + scriptSigs = append(scriptSigs, tx.TxIn[i].SignatureScript) + tin.Witness = nil + witnesses = append(witnesses, tx.TxIn[i].Witness) + + } + + // Outputs always contain: (value, scriptPubkey) so don't need + // amending. Now tx2 is tx with all signing data stripped out + unsignedPsbt, err := NewFromUnsignedTx(tx2) + if err != nil { + return nil, nil, nil, err + } + return unsignedPsbt, scriptSigs, witnesses, nil +} + +// These are all valid PSBTs +var validPsbtHex = map[int]string{ + 0: "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000", + 1: "70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000", + 2: "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001030401000000000000", + 3: "70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000", + 4: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + 5: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000", +} + +// These are all invalid PSBTs for the indicated +// reasons. +var invalidPsbtHex = map[int]string{ + // wire format, not PSBT format + 0: "0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300", + // missing outputs + 1: "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000", + // Filled in scriptSig in unsigned tx + 2: "70736274ff0100fd0a010200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be4000000006a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa88292feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000", + // No unsigned tx + 3: "70736274ff000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000", + // Duplicate keys in an input + 4: "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000000", + // Invalid global transaction typed key + 5: "70736274ff020001550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + // Invalid input witness utxo typed key + 6: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac000000000002010020955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + // Invalid pubkey length for input partial signature typed key + 7: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87210203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd46304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + // Invalid redeemscript typed key + 8: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a01020400220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + // Invalid witness script typed key + 9: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d568102050047522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + // Invalid bip32 typed key + 10: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae210603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd10b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + // Invalid non-witness utxo typed key + 11: "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f0000000000020000bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + // Invalid final scriptsig typed key + 12: "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000020700da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + // Invalid final script witness typed key + 13: "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903020800da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + // Invalid pubkey in output BIP32 derivation paths typed key + 14: "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00210203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca58710d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + // Invalid input sighash type typed key + 15: "70736274ff0100730200000001301ae986e516a1ec8ac5b4bc6573d32f83b465e23ad76167d68b38e730b4dbdb0000000000ffffffff02747b01000000000017a91403aa17ae882b5d0d54b25d63104e4ffece7b9ea2876043993b0000000017a914b921b1ba6f722e4bfa83b6557a3139986a42ec8387000000000001011f00ca9a3b00000000160014d2d94b64ae08587eefc8eeb187c601e939f9037c0203000100000000010016001462e9e982fff34dd8239610316b090cd2a3b747cb000100220020876bad832f1d168015ed41232a9ea65a1815d9ef13c0ef8759f64b5b2b278a65010125512103b7ce23a01c5b4bf00a642537cdfabb315b668332867478ef51309d2bd57f8a8751ae00", + // Invalid output redeemscript typed key + 16: "70736274ff0100730200000001301ae986e516a1ec8ac5b4bc6573d32f83b465e23ad76167d68b38e730b4dbdb0000000000ffffffff02747b01000000000017a91403aa17ae882b5d0d54b25d63104e4ffece7b9ea2876043993b0000000017a914b921b1ba6f722e4bfa83b6557a3139986a42ec8387000000000001011f00ca9a3b00000000160014d2d94b64ae08587eefc8eeb187c601e939f9037c0002000016001462e9e982fff34dd8239610316b090cd2a3b747cb000100220020876bad832f1d168015ed41232a9ea65a1815d9ef13c0ef8759f64b5b2b278a65010125512103b7ce23a01c5b4bf00a642537cdfabb315b668332867478ef51309d2bd57f8a8751ae00", + // Invalid output witnessScript typed key + 17: "70736274ff0100730200000001301ae986e516a1ec8ac5b4bc6573d32f83b465e23ad76167d68b38e730b4dbdb0000000000ffffffff02747b01000000000017a91403aa17ae882b5d0d54b25d63104e4ffece7b9ea2876043993b0000000017a914b921b1ba6f722e4bfa83b6557a3139986a42ec8387000000000001011f00ca9a3b00000000160014d2d94b64ae08587eefc8eeb187c601e939f9037c00010016001462e9e982fff34dd8239610316b090cd2a3b747cb000100220020876bad832f1d168015ed41232a9ea65a1815d9ef13c0ef8759f64b5b2b278a6521010025512103b7ce23a01c5b4bf00a642537cdfabb315b668332867478ef51309d2bd57f8a8751ae00", + // Additional cases outside the existing test vectors. + // Invalid duplicate PartialSig + 18: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a01220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", + // Invalid duplicate BIP32 derivation (different derivs, same key) + 19: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba670000008000000080050000800000", +} + +// This tests that valid PSBT serializations can be parsed +// into Psbt structs. +func TestReadValidPsbtAndReserialize(t *testing.T) { + for _, v := range validPsbtHex { + PsbtBytes, err := hex.DecodeString(v) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + testPsbt, err := NewFromRawBytes( + bytes.NewReader(PsbtBytes), false, + ) + if err != nil { + t.Fatalf("unable to parse psbt: %v", err) + } + + t.Logf("Successfully parsed test, got transaction: %v", + spew.Sdump(testPsbt.UnsignedTx)) + + var b bytes.Buffer + err = testPsbt.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize created Psbt: %v", err) + } + + raw := b.Bytes() + if !bytes.Equal(raw, PsbtBytes) { + t.Fatalf("Serialized PSBT didn't match: %v", + hex.EncodeToString(raw)) + } + } +} + +func TestReadInvalidPsbt(t *testing.T) { + for _, v := range invalidPsbtHex { + PsbtBytes, err := hex.DecodeString(v) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + _, err = NewFromRawBytes(bytes.NewReader(PsbtBytes), false) + if err == nil { + t.Fatalf("Incorrectly validated psbt: %v", + hex.EncodeToString(PsbtBytes)) + } + + t.Logf("Correctly got error: %v", err) + } +} + +func TestSanityCheck(t *testing.T) { + // TODO(guggero): Remove when checks for segwit v1 are implemented. + t.Skip("Skipping PSBT sanity checks for segwit v0.") + + // Test strategy: + // 1. Create an invalid PSBT from a serialization + // Then ensure that the sanity check fails. + // 2. Create a valid PSBT from a serialization + // Then create an updater, add a witness utxo to a non-witness + // utxo. + // Then ensure that the sanity check fails. + // Then add a witnessScript field to a non-witness utxo. + // Then ensure that the sanity check fails. + + // index 1 contains a psbt with two inputs, first non-witness, + // second witness. + psbtraw1, err := hex.DecodeString(validPsbtHex[1]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + psbt1, err := NewFromRawBytes(bytes.NewReader(psbtraw1), false) + if err != nil { + t.Fatalf("Unable to create Psbt struct: %v", err) + } + + // Add a non-witness utxo field to input2 using raw insertion function, + // so that it becomes invalid, then NewUpdater should fail. + nonWitnessUtxoRaw, err := hex.DecodeString( + CUTestHexData["NonWitnessUtxo"], + ) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + nonWitnessUtxo := wire.NewMsgTx(2) + err = nonWitnessUtxo.Deserialize(bytes.NewReader(nonWitnessUtxoRaw)) + if err != nil { + t.Fatalf("Unable to deserialize: %v", err) + } + inputs1 := &psbt1.Inputs[1] + inputs1.NonWitnessUtxo = nonWitnessUtxo + + // The PSBT is now in an inconsistent state; Updater creation should + // fail. + updater, err := NewUpdater(psbt1) + if err == nil { + t.Fatalf("Failed to identify invalid PSBT state ( " + + "witness, non-witness fields)") + } + + // Overwrite back with the correct psbt + psbtraw1, err = hex.DecodeString(validPsbtHex[1]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + psbt1, err = NewFromRawBytes(bytes.NewReader(psbtraw1), false) + updater, err = NewUpdater(psbt1) + if err != nil { + t.Fatalf("Unable to create Updater: %v", err) + } + + // Create a fake non-witness utxo field to overlap with + // the existing witness input at index 1. + tx := wire.NewMsgTx(2) + err = tx.Deserialize(bytes.NewReader(nonWitnessUtxoRaw)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + err = updater.AddInNonWitnessUtxo(tx, 1) + if err == nil { + t.Fatalf("Incorrectly accepted Psbt with conflicting witness " + + "and non-witness utxo entries in the same input.") + } + + // Now we try again; this time we try to add a witnessScript + // key-value pair to an input which is non-witness, which should + // also be rejected. + psbt2, err := NewFromRawBytes( + bytes.NewReader(psbtraw1), false, + ) + if err != nil { + t.Fatalf("Unable to create Psbt struct: %v", err) + } + updater2, err := NewUpdater(psbt2) + if err != nil { + t.Fatalf("Got error creating updater2: %v", err) + } + witnessScript, err := hex.DecodeString( + CUTestHexData["Input2WitnessScript"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + err = updater2.AddInWitnessScript(witnessScript, 0) + if err == nil { + t.Fatalf("Incorrectly accepted adding witness script field " + + "to non-witness utxo") + } +} + +// Data for creation and updating tests +// =============================================================================== +var CUTestHexData = map[string]string{ + "scriptPubkey1": "0014d85c2b71d0060b09c9886aeb815e50991dda124d", + "scriptPubkey2": "001400aea9a2e5f0f876a588df5546e8742d1d87008f", + "txid1": "75ddabb27b8845f5247975c8a5ba7c6f336c4570708ebe230caf6db5217ae858", + "txid2": "1dea7cd05979072a3578cab271c02244ea8a090bbb46aa680a65ecd027048d83", + "COPsbtHex": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000000000000000000", + "NonWitnessUtxo": "0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000", + "WitnessUtxo": "00c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887", + // After adding witnessutxo and nonwitness utxo to inputs: + "UOPsbtHex": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887000000", + "Input1RedeemScript": "5221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae", + "Input2RedeemScript": "00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903", + "Input2WitnessScript": "522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae", + // After adding redeemscripts and witness scripts to inputs: + "UOPsbtHex2": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88701042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae000000", + // After adding bip32 derivations to inputs and outputs: + "UOPsbtHex3": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88701042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + //After adding sighash types to inputs + "UOPsbtHex4": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", +} + +// Just one example sanity check of B64 construction; after sighash appending above +var CUTestB64Data = map[string]string{ + "UOPsbtB644": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABAwQBAAAAAQRHUiEClYO/Oa4KYJdHrRma3dY0+mEIVZ1sXNObTCGD8auW4H8hAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXUq4iBgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfxDZDGpPAAAAgAAAAIAAAACAIgYC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtcQ2QxqTwAAAIAAAACAAQAAgAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", +} + +var CUTestAmountData = map[string]int64{ + "amount1": 149990000, + "amount2": 100000000, + "amount3": 200000000, +} + +var CUTestIndexData = map[string]uint32{ + "index1": 0, + "index2": 1, +} + +var CUMasterKeyFingerPrint = "d90c6a4f" + +var CUTestPathData = map[string][]uint32{ + "dpath1": {0 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000}, + "dpath2": {0 + 0x80000000, 0 + 0x80000000, 1 + 0x80000000}, + "dpath3": {0 + 0x80000000, 0 + 0x80000000, 2 + 0x80000000}, + "dpath4": {0 + 0x80000000, 0 + 0x80000000, 3 + 0x80000000}, + "dpath5": {0 + 0x80000000, 0 + 0x80000000, 4 + 0x80000000}, + "dpath6": {0 + 0x80000000, 0 + 0x80000000, 5 + 0x80000000}, +} + +var CUTestPubkeyData = map[string]string{ + "pub1": "029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f", + "pub2": "02dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7", + "pub3": "03089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc", + "pub4": "023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73", + "pub5": "03a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca58771", + "pub6": "027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b50051096", +} + +// =============================================================================== + +func TestPsbtCreator(t *testing.T) { + spkOut1, err := hex.DecodeString(CUTestHexData["scriptPubkey1"]) + if err != nil { + t.Fatalf("Error: %v", err) + } + spkOut2, err := hex.DecodeString(CUTestHexData["scriptPubkey2"]) + if err != nil { + t.Fatalf("Error: %v", err) + } + out1 := wire.NewTxOut(CUTestAmountData["amount1"], spkOut1) + out2 := wire.NewTxOut(CUTestAmountData["amount2"], spkOut2) + outputs := []*wire.TxOut{out1, out2} + hash1, err := chainhash.NewHashFromStr(CUTestHexData["txid1"]) + if err != nil { + t.Fatalf("Error: %v", err) + } + prevOut1 := wire.NewOutPoint(hash1, uint32(0)) + hash2, err := chainhash.NewHashFromStr(CUTestHexData["txid2"]) + if err != nil { + t.Fatalf("Error: %v", err) + } + prevOut2 := wire.NewOutPoint(hash2, uint32(1)) + inputs := []*wire.OutPoint{prevOut1, prevOut2} + + // Check creation fails with invalid sequences: + nSequences := []uint32{wire.MaxTxInSequenceNum} + _, err = New(inputs, outputs, int32(3), uint32(0), nSequences) + if err == nil { + t.Fatalf("Did not error when creating transaction with " + + "invalid nSequences") + } + nSequences = append(nSequences, wire.MaxTxInSequenceNum) + + // Check creation fails with invalid version + _, err = New(inputs, outputs, int32(0), uint32(0), nSequences) + if err == nil { + t.Fatalf("Did not error when creating transaction with " + + "invalid version (3)") + } + + // Use valid data to create: + cPsbt, err := New(inputs, outputs, int32(2), uint32(0), nSequences) + var b bytes.Buffer + err = cPsbt.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize created Psbt: %v", err) + } + if CUTestHexData["COPsbtHex"] != hex.EncodeToString(b.Bytes()) { + t.Fatalf("Failed to create expected psbt, instead got: %v", + hex.EncodeToString(b.Bytes())) + } + + // Now simulate passing the created PSBT to an Updater + updater, err := NewUpdater(cPsbt) + if err != nil { + t.Fatalf("Unable to create Updater object") + } + tx := wire.NewMsgTx(2) + nonWitnessUtxoHex, err := hex.DecodeString( + CUTestHexData["NonWitnessUtxo"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + err = tx.Deserialize(bytes.NewReader(nonWitnessUtxoHex)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + witnessUtxoHex, err := hex.DecodeString( + CUTestHexData["WitnessUtxo"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + txout := wire.TxOut{Value: CUTestAmountData["amount3"], + PkScript: witnessUtxoHex[9:]} + err = updater.AddInNonWitnessUtxo(tx, 0) + if err != nil { + t.Fatalf("Unable to add NonWitness Utxo to inputs: %v", err) + } + err = updater.AddInWitnessUtxo(&txout, 1) + if err != nil { + t.Fatalf("Unable to add Witness Utxo to inputs: %v", err) + } + + b.Reset() + + err = updater.Upsbt.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize updated Psbt: %v", err) + } + if CUTestHexData["UOPsbtHex"] != hex.EncodeToString(b.Bytes()) { + t.Fatal("Failed to create valid updated PSBT after utxos") + } + input1RedeemScript, err := hex.DecodeString(CUTestHexData["Input1RedeemScript"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + err = updater.AddInRedeemScript(input1RedeemScript, 0) + if err != nil { + t.Fatalf("Unable to add redeem script: %v", err) + } + input2RedeemScript, err := hex.DecodeString(CUTestHexData["Input2RedeemScript"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + err = updater.AddInRedeemScript(input2RedeemScript, 1) + if err != nil { + t.Fatalf("Unable to add redeem script: %v", err) + } + input2WitnessScript, err := hex.DecodeString(CUTestHexData["Input2WitnessScript"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + err = updater.AddInWitnessScript(input2WitnessScript, 1) + if err != nil { + t.Fatalf("Unable to add witness script: %v", err) + } + + b.Reset() + err = updater.Upsbt.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize updated Psbt: %v", err) + } + if CUTestHexData["UOPsbtHex2"] != hex.EncodeToString(b.Bytes()) { + t.Fatal("Failed to create valid updated PSBT after redeem scripts") + } + masterKey, err := hex.DecodeString(CUMasterKeyFingerPrint) + masterKeyInt := binary.LittleEndian.Uint32(masterKey) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + input1Path1 := CUTestPathData["dpath1"] + input1Path2 := CUTestPathData["dpath2"] + input1Key1, err := hex.DecodeString(CUTestPubkeyData["pub1"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + input1Key2, err := hex.DecodeString(CUTestPubkeyData["pub2"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + err = updater.AddInBip32Derivation(masterKeyInt, input1Path1, input1Key1, 0) + if err != nil { + t.Fatal("Failed to add first key derivation for input 1") + } + err = updater.AddInBip32Derivation(masterKeyInt, input1Path2, input1Key2, 0) + if err != nil { + t.Fatal("Failed to add second key derivation for input 1") + } + input2Path1 := CUTestPathData["dpath3"] + input2Path2 := CUTestPathData["dpath4"] + input2Key1, err := hex.DecodeString(CUTestPubkeyData["pub3"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + input2Key2, err := hex.DecodeString(CUTestPubkeyData["pub4"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + // check invalid pubkeys are not accepted + borkedInput2Key1 := append([]byte{0xff}, input2Key1...) + err = updater.AddInBip32Derivation(masterKeyInt, input2Path1, + borkedInput2Key1, 1) + if err == nil { + t.Fatalf("Expected invalid pubkey, got: %v", err) + } + + err = updater.AddInBip32Derivation(masterKeyInt, input2Path1, input2Key1, 1) + if err != nil { + t.Fatal("Failed to add first key derivation for input 2") + } + err = updater.AddInBip32Derivation(masterKeyInt, input2Path2, input2Key2, 1) + if err != nil { + t.Fatal("Failed to add second key derivation for input 2") + } + output1Key1, err := hex.DecodeString(CUTestPubkeyData["pub5"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + output1Path := CUTestPathData["dpath5"] + + // check invalid pubkeys are not accepted + borkedOutput1Key1 := append([]byte{0xab}, output1Key1[:13]...) + err = updater.AddOutBip32Derivation(masterKeyInt, output1Path, + borkedOutput1Key1, 0) + if err == nil { + t.Fatalf("Expected invalid pubkey, got: %v", err) + } + + err = updater.AddOutBip32Derivation(masterKeyInt, output1Path, output1Key1, 0) + if err != nil { + t.Fatal("Failed to add key to first output") + } + output2Key1, err := hex.DecodeString(CUTestPubkeyData["pub6"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + output2Path := CUTestPathData["dpath6"] + err = updater.AddOutBip32Derivation(masterKeyInt, output2Path, output2Key1, 1) + if err != nil { + t.Fatal("Failed to add key to second output") + } + + b.Reset() + err = updater.Upsbt.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize updated Psbt: %v", err) + } + if CUTestHexData["UOPsbtHex3"] != hex.EncodeToString(b.Bytes()) { + t.Fatal("Failed to create valid updated PSBT after BIP32 derivations") + } + err = updater.AddInSighashType(txscript.SigHashType(1), 0) + if err != nil { + t.Fatal("Failed to add sighash type to first input") + } + err = updater.AddInSighashType(txscript.SigHashType(1), 1) + if err != nil { + t.Fatal("Failed to add sighash type to second input") + } + + b.Reset() + err = updater.Upsbt.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize updated Psbt: %v", err) + } + if CUTestHexData["UOPsbtHex4"] != hex.EncodeToString(b.Bytes()) { + t.Fatal("Failed to create valid updated PSBT after sighash types") + } + b644, err := updater.Upsbt.B64Encode() + if err != nil { + t.Fatalf("Unable to B64Encode updated Psbt: %v", err) + } + if b644 != CUTestB64Data["UOPsbtB644"] { + t.Fatalf("Failed to base64 encode updated PSBT after sighash "+ + "types: %v", b644) + } +} + +// Signing test data taken from +// https://github.com/achow101/bitcoin/blob/020628e3a4e88e36647eaf92bac4b3552796ac6a/test/functional/data/rpc_psbt.json +var signerPsbtData = map[string]string{ + "signer1Privkey1": "cP53pDbR5WtAD8dYAW9hhTjuvvTVaEiQBdrz9XPrgLBeRFiyCbQr", + "signer1Privkey2": "cR6SXDoyfQrcp4piaiHE97Rsgta9mNhGTen9XeonVgwsh4iSgw6d", + "signer1PsbtB64": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAQMEAQAAAAABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEEIgAgjCNTFzdDtZXftKB7crqOQuN5fadOh/59nXSX47ICiQMBBUdSIQMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3CECOt2QTz1tz1nduQaw3uI1Kbf/ue1Q5ehhUZJoYCIfDnNSriIGAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zENkMak8AAACAAAAAgAMAAIAiBgMIncEMesbbVPkTKa9hczPbOIzq0MIx9yM3nRuZAwsC3BDZDGpPAAAAgAAAAIACAACAAQMEAQAAAAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", + "signer1Result": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + "signer2Privkey1": "cT7J9YpCwY3AVRFSjN6ukeEeWY6mhpbJPxRaDaP5QTdygQRxP9Au", + "signer2Privkey2": "cNBc3SWUip9PPm1GjRoLEJT6T41iNzCYtD7qro84FMnM5zEqeJsE", + "signer2Psbt": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f000000800000008001000080010304010000000001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88701042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f0000008000000080020000800103040100000000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + "signer2Result": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f618765000000220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8872202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", +} + +func TestPsbtSigner(t *testing.T) { + psbt1, err := NewFromRawBytes( + bytes.NewReader([]byte(signerPsbtData["signer1PsbtB64"])), + true, + ) + if err != nil { + t.Fatalf("Failed to parse PSBT: %v", err) + } + psbtUpdater1 := Updater{ + Upsbt: psbt1, + } + sig1, err := hex.DecodeString("3044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01") + pub1, err := hex.DecodeString("029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f") + res, err := psbtUpdater1.Sign(0, sig1, pub1, nil, nil) + if err != nil || res != 0 { + t.Fatalf("Error from adding signatures: %v %v", err, res) + } + sig2, err := hex.DecodeString("3044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01") + pub2, err := hex.DecodeString("03089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc") + res, err = psbtUpdater1.Sign(1, sig2, pub2, nil, nil) + if err != nil || res != 0 { + t.Fatalf("Error from adding signatures: %v %v", err, res) + } + signer1Result, err := hex.DecodeString(signerPsbtData["signer1Result"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + var b bytes.Buffer + err = psbtUpdater1.Upsbt.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize updated Psbt: %v", err) + } + if !bytes.Equal(b.Bytes(), signer1Result) { + t.Fatalf("Failed to add signatures correctly") + } +} + +// Finalizer-extractor test + +var finalizerPsbtData = map[string]string{ + "finalizeb64": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAAiAgKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgf0cwRAIgdAGK1BgAl7hzMjwAFXILNoTMgSOJEEjn282bVa1nnJkCIHPTabdA4+tT3O+jOCPIBwUUylWn3ZVE8VfBZ5EyYRGMASICAtq2H/SaFNtqfQKwzR+7ePxLGDErW05U2uTbovv+9TbXSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAQEDBAEAAAABBEdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSriIGApWDvzmuCmCXR60Zmt3WNPphCFWdbFzTm0whg/GrluB/ENkMak8AAACAAAAAgAAAAIAiBgLath/0mhTban0CsM0fu3j8SxgxK1tOVNrk26L7/vU21xDZDGpPAAAAgAAAAIABAACAAAEBIADC6wsAAAAAF6kUt/X69A49QKWkWbHbNTXyty+pIeiHIgIDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtxHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwEiAgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8Oc0cwRAIgZfRbpZmLWaJ//hp77QFq8fH5DVSzqo90UKpfVqJRA70CIH9yRwOtHtuWaAsoS1bU/8uI9/t1nqu+CKow8puFE4PSAQEDBAEAAAABBCIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQVHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4iBgI63ZBPPW3PWd25BrDe4jUpt/+57VDl6GFRkmhgIh8OcxDZDGpPAAAAgAAAAIADAACAIgYDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwQ2QxqTwAAAIAAAACAAgAAgAAiAgOppMN/WZbTqiXbrGtXCvBlA5RJKUJGCzVHU+2e7KWHcRDZDGpPAAAAgAAAAIAEAACAACICAn9jmXV9Lv9VoTatAsaEsYOLZVbl8bazQoKpS2tQBRCWENkMak8AAACAAAAAgAUAAIAA", + "finalize": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000002202029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01220202dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d7483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01010304010000000104475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae2206029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f10d90c6a4f000000800000008000000080220602dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d710d90c6a4f0000008000000080010000800001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887220203089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f012202023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d2010103040100000001042200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903010547522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae2206023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7310d90c6a4f000000800000008003000080220603089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc10d90c6a4f00000080000000800200008000220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + "resultb64": "cHNidP8BAJoCAAAAAljoeiG1ba8MI76OcHBFbDNvfLqlyHV5JPVFiHuyq911AAAAAAD/////g40EJ9DsZQpoqka7CwmK6kQiwHGyyng1Kgd5WdB86h0BAAAAAP////8CcKrwCAAAAAAWABTYXCtx0AYLCcmIauuBXlCZHdoSTQDh9QUAAAAAFgAUAK6pouXw+HaliN9VRuh0LR2HAI8AAAAAAAEAuwIAAAABqtc5MQGL0l+ErkALaISL4J23BurCrBgpi6vucatlb4sAAAAASEcwRAIgWPb8fGoz4bMVSNSByCbAFb0wE1qtQs1neQ2rZtKtJDsCIEoc7SYExnNbY5PltBaR3XiwDwxZQvufdRhW+qk4FX26Af7///8CgPD6AgAAAAAXqRQPuUY0IWlrgsgzryQceMF9295JNIfQ8gonAQAAABepFCnKdPigj4GZlCgYXJe12FLkBj9hh2UAAAABB9oARzBEAiB0AYrUGACXuHMyPAAVcgs2hMyBI4kQSOfbzZtVrWecmQIgc9Npt0Dj61Pc76M4I8gHBRTKVafdlUTxV8FnkTJhEYwBSDBFAiEA9hA4swjcHahlo0hSdG8BV3KTQgjG0kRUOTzZm98iF3cCIAVuZ1pnWm0KArhbFOXikHTYolqbV2C+ooFvZhkQoAbqAUdSIQKVg785rgpgl0etGZrd1jT6YQhVnWxc05tMIYPxq5bgfyEC2rYf9JoU22p9ArDNH7t4/EsYMStbTlTa5Nui+/71NtdSrgABASAAwusLAAAAABepFLf1+vQOPUClpFmx2zU18rcvqSHohwEHIyIAIIwjUxc3Q7WV37Sge3K6jkLjeX2nTof+fZ10l+OyAokDAQjaBABHMEQCIGLrelVhB6fHP0WsSrWh3d9vcHX7EnWWmn84Pv/3hLyyAiAMBdu3Rw2/LwhVfdNWxzJcHtMJE+mWzThAlF2xIijaXwFHMEQCIGX0W6WZi1mif/4ae+0BavHx+Q1Us6qPdFCqX1aiUQO9AiB/ckcDrR7blmgLKEtW1P/LiPf7dZ6rvgiqMPKbhROD0gFHUiEDCJ3BDHrG21T5EymvYXMz2ziM6tDCMfcjN50bmQMLAtwhAjrdkE89bc9Z3bkGsN7iNSm3/7ntUOXoYVGSaGAiHw5zUq4AIgIDqaTDf1mW06ol26xrVwrwZQOUSSlCRgs1R1Ptnuylh3EQ2QxqTwAAAIAAAACABAAAgAAiAgJ/Y5l1fS7/VaE2rQLGhLGDi2VW5fG2s0KCqUtrUAUQlhDZDGpPAAAAgAAAAIAFAACAAA==", + "result": "70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000", + "network": "0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000", + "twoOfThree": "70736274ff01005e01000000019a5fdb3c36f2168ea34a031857863c63bb776fd8a8a9149efd7341dfaf81c9970000000000ffffffff01e013a8040000000022002001c3a65ccfa5b39e31e6bafa504446200b9c88c58b4f21eb7e18412aff154e3f000000000001012bc817a80400000000220020114c9ab91ea00eb3e81a7aa4d0d8f1bc6bd8761f8f00dbccb38060dc2b9fdd5522020242ecd19afda551d58f496c17e3f51df4488089df4caafac3285ed3b9c590f6a847304402207c6ab50f421c59621323460aaf0f731a1b90ca76eddc635aed40e4d2fc86f97e02201b3f8fe931f1f94fde249e2b5b4dbfaff2f9df66dd97c6b518ffa746a4390bd1012202039f0acfe5a292aafc5331f18f6360a3cc53d645ebf0cc7f0509630b22b5d9f547473044022075329343e01033ebe5a22ea6eecf6361feca58752716bdc2260d7f449360a0810220299740ed32f694acc5f99d80c988bb270a030f63947f775382daf4669b272da0010103040100000001056952210242ecd19afda551d58f496c17e3f51df4488089df4caafac3285ed3b9c590f6a821035a654524d301dd0265c2370225a6837298b8ca2099085568cc61a8491287b63921039f0acfe5a292aafc5331f18f6360a3cc53d645ebf0cc7f0509630b22b5d9f54753ae22060242ecd19afda551d58f496c17e3f51df4488089df4caafac3285ed3b9c590f6a818d5f7375b2c000080000000800000008000000000010000002206035a654524d301dd0265c2370225a6837298b8ca2099085568cc61a8491287b63918e2314cf32c000080000000800000008000000000010000002206039f0acfe5a292aafc5331f18f6360a3cc53d645ebf0cc7f0509630b22b5d9f54718e524a1ce2c000080000000800000008000000000010000000000", +} + +func TestFinalize2of3(t *testing.T) { + b, err := hex.DecodeString(finalizerPsbtData["twoOfThree"]) + if err != nil { + t.Fatalf("Error decoding hex: %v", err) + } + p, err := NewFromRawBytes(bytes.NewReader(b), false) + if p.IsComplete() { + t.Fatalf("Psbt is complete") + } + err = MaybeFinalizeAll(p) + if err != nil { + t.Fatalf("Error in MaybeFinalizeAll: %v", err) + } + if !p.IsComplete() { + t.Fatalf("Psbt is not complete") + } +} + +func TestPsbtExtractor(t *testing.T) { + rawToFinalize, err := base64.StdEncoding.DecodeString( + finalizerPsbtData["finalizeb64"], + ) + if err != nil { + t.Fatalf("Error decoding b64: %v", err) + } + + psbt1, err := NewFromRawBytes( + bytes.NewReader(rawToFinalize), false, + ) + if err != nil { + t.Fatalf("Failed to parse PSBT: %v", err) + } + + for i := range psbt1.Inputs { + err = Finalize(psbt1, i) + if err != nil { + t.Fatalf("Error from finalizing PSBT: %v", err) + } + } + + finalizer1Result, err := base64.StdEncoding.DecodeString( + finalizerPsbtData["resultb64"], + ) + if err != nil { + t.Fatalf("Unable to decode b64: %v", err) + } + finalToNetworkExpected, err := hex.DecodeString(finalizerPsbtData["network"]) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + tx, err := Extract(psbt1) + if err != nil { + t.Fatalf("Failed to extract: %v", err) + } + var resultToNetwork bytes.Buffer + if err := tx.Serialize(&resultToNetwork); err != nil { + t.Fatalf("unable to serialize: %v", err) + } + + var b bytes.Buffer + err = psbt1.Serialize(&b) + if err != nil { + t.Fatalf("Unable to serialize updated Psbt: %v", err) + } + if !bytes.Equal(b.Bytes(), finalizer1Result) { + t.Fatalf("Failed to finalize transaction: expected %x, "+ + "got %x", finalizer1Result, b.Bytes()) + } + if !bytes.Equal(finalToNetworkExpected, resultToNetwork.Bytes()) { + t.Fatalf("Failed to network serialize transaction: %x", b.Bytes()) + } +} + +func TestImportFromCore1(t *testing.T) { + // This example #1 was created manually using Bitcoin Core 0.17 regtest. + // It contains two inputs, one p2wkh and one p2pkh (non-witness). + // We take the created PSBT as input, then add the fields for each input + // separately, then finalize and extract, and compare with the network + // serialized tx output from Core. + imported := "cHNidP8BAJwCAAAAAjaoF6eKeGsPiDQxxqqhFDfHWjBtZzRqmaZmvyCVWZ5JAQAAAAD/////RhypNiFfnQSMNpo0SGsgIvDOyMQFAYEHZXD5jp4kCrUAAAAAAP////8CgCcSjAAAAAAXqRQFWy8ScSkkhlGMwfOnx15YwRzApofwX5MDAAAAABepFAt4TyLfGnL9QY6GLYHbpSQj+QclhwAAAAAAAAAAAA==" + psbt1, err := NewFromRawBytes(bytes.NewReader([]byte(imported)), true) + if err != nil { + t.Fatalf("Failed to parse PSBT: %v", err) + } + + // update with the first input's utxo (witness) and the second input's utxo + // (non-witness) + fundingTxInput1Hex := "02000000014f2cbac7d7691fafca30313097d79be9e78aa6670752fcb1fc15508e77586efb000000004847304402201b5568d7cab977ae0892840b779d84e36d62e42fd93b95e648aaebeacd2577d602201d2ebda2b0cddfa0c1a71d3cbcb602e7c9c860a41ed8b4d18d40c92ccbe92aed01feffffff028c636f91000000001600147447b6d7e6193499565779c8eb5184fcfdfee6ef00879303000000001600149e88f2828a074ebf64af23c2168d1816258311d72d010000" + fundingTxInput2Hex := "020000000001012f03f70c673d83d65da0e8d0db3867b3e7d7bfbd34fd6be65892042e57576eb00000000000feffffff028027128c000000001976a91485780899b61a5506f342bd67a2f635181f50c8b788acb8032c040000000017a914e2e3d32d42d6f043cab39708a6073301df5039db8702473044022047ae396fd8aba8f67482ad16e315fe680db585c1ac6422ffb18dacd9cf5bac350220321176fd6157ef51d9eae9230b0b5bd7dd29bb6247a879189e6aaa8091f3020201210368081f7ff37dfadbed407eba17b232f959e41e6ac78741192c805ebf80d487852f010000" + fundingTxInput1Bytes, err := hex.DecodeString(fundingTxInput1Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + txFund1 := wire.NewMsgTx(2) + err = txFund1.Deserialize(bytes.NewReader(fundingTxInput1Bytes)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + // First input is witness, take correct output: + txFund1Out := txFund1.TxOut[1] + + fundingTxInput2Bytes, err := hex.DecodeString(fundingTxInput2Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + txFund2 := wire.NewMsgTx(2) + err = txFund2.Deserialize(bytes.NewReader(fundingTxInput2Bytes)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + psbtupdater1 := Updater{Upsbt: psbt1} + psbtupdater1.AddInWitnessUtxo(txFund1Out, 0) + err = psbtupdater1.AddInNonWitnessUtxo(txFund2, 1) + if err != nil { + t.Fatalf("Error inserting non-witness utxo: %v", err) + } + + // Signing was done with Core; we manually insert the relevant input + // entries here. + sig1Hex := "304402200da03ac9890f5d724c42c83c2a62844c08425a274f1a5bca50dcde4126eb20dd02205278897b65cb8e390a0868c9582133c7157b2ad3e81c1c70d8fbd65f51a5658b01" + sig1, err := hex.DecodeString(sig1Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + pub1Hex := "024d6b24f372dd4551277c8df4ecc0655101e11c22894c8e05a3468409c865a72c" + pub1, err := hex.DecodeString(pub1Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + // Check that invalid pubkeys are not accepted. + pubInvalid := append(pub1, 0x00) + + res, err := psbtupdater1.Sign(0, sig1, pubInvalid, nil, nil) + if err == nil { + t.Fatalf("Incorrectly accepted invalid pubkey: %v", + pubInvalid) + } + + res, err = psbtupdater1.Sign(0, sig1, pub1, nil, nil) + if err != nil || res != 0 { + t.Fatalf("Error from adding signatures: %v %v", err, res) + } + + sig2Hex := "3044022014eb9c4858f71c9f280bc68402aa742a5187f54c56c8eb07c902eb1eb5804e5502203d66656de8386b9b044346d5605f5ae2b200328fb30476f6ac993fc0dbb0455901" + sig2, err := hex.DecodeString(sig2Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + pub2Hex := "03b4c79acdf4e7d978bef4019c421e4c6c67044ed49d27322dc90e808d8080e862" + pub2, err := hex.DecodeString(pub2Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + // =============================================================== + // Before adding the signature, we'll make a new PSBT with + // modifications to the input data and check it fails sanity checks. + + // First an invalid tx: + psbtBorkedInput2, _ := NewFromRawBytes(bytes.NewReader([]byte(imported)), true) + borkedUpdater, err := NewUpdater(psbtBorkedInput2) + if err != nil { + t.Fatalf("NewUpdater failed while trying to create borked "+ + "version: %v", err) + } + borkedUpdater.AddInWitnessUtxo(txFund1Out, 0) + + res, err = borkedUpdater.Sign(0, sig2, pub2, nil, nil) + if err != ErrInvalidSignatureForInput { + t.Fatalf("AddPartialSig succeeded, but should have failed "+ + "due to mismatch between pubkey and prevOut; err was: %v", err) + } + + // Next, a valid tx serialization, but not the right one + wrongTxBytes, err := hex.DecodeString("020000000001012d1d7b17356d0ad8232a5817d2d2fa5cd97d803c0ed03e013e97b65f4f1e5e7501000000171600147848cfb25bb163c7c63732615980a25eddbadc7bfeffffff022a8227630000000017a91472128ae6b6a1b74e499bedb5efb1cb09c9a6713287107240000000000017a91485f81cb970d854e2513ebf5c5b5d09e4509f4af3870247304402201c09aa8bcd18753ef01d8712a55eea5a0f69b6c4cc2944ac942264ff0662c91402201fc1390bf8b0023dd12ae78d7ec181124e106de57bc8f00812ae92bd024d3045012103ba077fc011aa59393bfe17cf491b3a02a9c4d39df122b2148322da0ec23508f459430800") + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + wrongTx := wire.NewMsgTx(2) + err = wrongTx.Deserialize(bytes.NewReader(wrongTxBytes)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + psbtBorkedInput2.Inputs[1] = *NewPsbtInput(wrongTx, nil) + res, err = borkedUpdater.Sign(1, sig2, pub2, nil, nil) + if err != ErrInvalidSignatureForInput { + t.Fatalf("Error should have been invalid sig for input, was: %v", err) + } + // ====================================================== + + res, err = psbtupdater1.Sign(1, sig2, pub2, nil, nil) + if err != nil || res != 0 { + t.Fatalf("Failed to add signature to second input: %v %v", err, res) + } + + // Neither input (p2pkh and p2wkh) require redeem script nor witness script, + // so there are no more fields to add; we are ready to finalize. + err = Finalize(psbt1, 0) + if err != nil { + t.Fatalf("Failed to finalize the first input, %v", err) + } + if psbt1.IsComplete() { + t.Fatalf("PSBT was complete but has not been fully finalized") + } + err = Finalize(psbt1, 1) + if err != nil { + t.Fatalf("Failed to finalize second input, %v", err) + } + + tx, err := Extract(psbt1) + if err != nil { + t.Fatalf("unable to extract tx: %v", err) + } + var networkSerializedTx bytes.Buffer + if err := tx.Serialize(&networkSerializedTx); err != nil { + t.Fatalf("unable to encode tx: %v", err) + } + + expectedTx := "0200000000010236a817a78a786b0f883431c6aaa11437c75a306d67346a99a666bf2095599e490100000000ffffffff461ca936215f9d048c369a34486b2022f0cec8c4050181076570f98e9e240ab5000000006a473044022014eb9c4858f71c9f280bc68402aa742a5187f54c56c8eb07c902eb1eb5804e5502203d66656de8386b9b044346d5605f5ae2b200328fb30476f6ac993fc0dbb04559012103b4c79acdf4e7d978bef4019c421e4c6c67044ed49d27322dc90e808d8080e862ffffffff028027128c0000000017a914055b2f1271292486518cc1f3a7c75e58c11cc0a687f05f93030000000017a9140b784f22df1a72fd418e862d81dba52423f90725870247304402200da03ac9890f5d724c42c83c2a62844c08425a274f1a5bca50dcde4126eb20dd02205278897b65cb8e390a0868c9582133c7157b2ad3e81c1c70d8fbd65f51a5658b0121024d6b24f372dd4551277c8df4ecc0655101e11c22894c8e05a3468409c865a72c0000000000" + expectedTxBytes, err := hex.DecodeString(expectedTx) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + if !bytes.Equal(expectedTxBytes, networkSerializedTx.Bytes()) { + t.Fatalf("The produced network transaction did not match the expected: %x \n %x \n", + networkSerializedTx.Bytes(), expectedTxBytes) + } + +} + +func TestImportFromCore2(t *testing.T) { + // This example #2 was created manually using Bitcoin Core 0.17 regtest. + // It contains two inputs, one p2sh-p2wkh and one fake utxo. + // The PSBT has been created with walletcreatepsbt and then partial-signed + // on the real input with walletprocessbst in Core. + // We first check that the updating here, using the Core created signature, + // redeem script and signature for the p2sh-p2wkh input, creates the + // same partial-signed intermediate transaction as Core did after + // walletprocesspsbt. + // We then attach a fake + // input of type p2sh-p2wsh, attach its witnessUtxo, redeemscript and + // witnessscript fields, and then finalize the whole transaction. Unlike + // the previous example, we cannot here compare with a Core produced + // network serialized final transaction, because of the fake input. + imported := "cHNidP8BAJsCAAAAAkxTQ+rig5QNnUS5nMc+Pccow4IcOJeQRcNNw+7p5ZA5AQAAAAD/////qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoNAAAAAP////8CAIYOcAAAAAAWABQ1l7nn13RubTwqRQU2BnVV5WlXBWAxMbUAAAAAF6kUkiuXUjfWFgTp6nl/gf9+8zIWR6KHAAAAAAAAAAAA" + psbt1, err := NewFromRawBytes(bytes.NewReader([]byte(imported)), true) + if err != nil { + t.Fatalf("Failed to parse PSBT: %v", err) + } + + // update with the first input's utxo, taken from its funding + // transaction + fundingTxInput1Hex := "02000000017b260536a3c17aee49c41a9b36fdf01a418e0c04df06fbabcb0d4f590b95d175000000006a473044022074a5a13159b6c12d77881c9501aa5c18616fb76c1809fc4d55f18a2e63159a6702200d1aa72be6056a41808898d24da93c0c0192cad65b7c2cc86e00b3e0fbbd57f601210212cc429d61fde565d0c2271a3e4fdb063cb49ae2257fa71460be753ceb56d175feffffff02bc060d8f0000000017a9140b56c31b5dc5a5a22c45a7850e707ad602d94a3087008352840000000017a9149f3679d67a9a486238764f618a93b82a7d999103879a000000" + fundingTxInput1Bytes, err := hex.DecodeString(fundingTxInput1Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + txFund1 := wire.NewMsgTx(2) + err = txFund1.Deserialize(bytes.NewReader(fundingTxInput1Bytes)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + // First input is witness, take correct output: + txFund1Out := txFund1.TxOut[1] + + psbtupdater1 := Updater{Upsbt: psbt1} + psbtupdater1.AddInWitnessUtxo(txFund1Out, 0) + + // This input is p2sh-p2wkh, so it requires a redeemscript but not + // a witness script. The redeemscript is the witness program. + redeemScript, err := hex.DecodeString("00147aed39420a8b7ab98a83791327ccb70819d1fbe2") + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + psbtupdater1.AddInRedeemScript(redeemScript, 0) + + // Signing for the first input was done with Core; we manually insert the + // relevant input entries here. + sig1Hex := "30440220546d182d00e45ef659c329dce6197dc19e0abc795e2c9279873f5a887998b273022044143113fc3475d04fc8d5113e0bbcb42d80514a9f1a2247e9b2a7878e20d44901" + sig1, err := hex.DecodeString(sig1Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + pub1Hex := "02bb3ce35af26f4c826eab3e5fc263ef56871b26686a8a995599b7ee6576613104" + pub1, err := hex.DecodeString(pub1Hex) + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + res, err := psbtupdater1.Sign(0, sig1, pub1, nil, nil) + if err != nil || res != 0 { + t.Fatalf("Unable to add partial signature: %v %v", err, res) + } + + // Since this input is now finalizable, we do so: + err = Finalize(psbt1, 0) + if err != nil { + t.Fatalf("Failed to finalize the first input: %v", err) + } + if psbt1.IsComplete() { + t.Fatalf("PSBT was complete but has not been fully finalized") + } + + // Core also adds the OutRedeemScript field for the output it knows about. + // Note that usually we would not of course re-create, but rather start + // from the half-signed version; so this is needed only for a sanity check + // that we can recreate the half-signed. + output2RedeemScript, err := hex.DecodeString("0014e0846bd17848ab40ca1f56b655c6fa31667880cc") + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + psbtupdater1.AddOutRedeemScript(output2RedeemScript, 1) + // The main function of the test is to compare the thus-generated + // partially (not completely) signed transaction with that generated and + // encoded by Core. + expectedPsbtPartialB64 := "cHNidP8BAJsCAAAAAkxTQ+rig5QNnUS5nMc+Pccow4IcOJeQRcNNw+7p5ZA5AQAAAAD/////qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqoNAAAAAP////8CAIYOcAAAAAAWABQ1l7nn13RubTwqRQU2BnVV5WlXBWAxMbUAAAAAF6kUkiuXUjfWFgTp6nl/gf9+8zIWR6KHAAAAAAABASAAg1KEAAAAABepFJ82edZ6mkhiOHZPYYqTuCp9mZEDhwEHFxYAFHrtOUIKi3q5ioN5EyfMtwgZ0fviAQhrAkcwRAIgVG0YLQDkXvZZwync5hl9wZ4KvHleLJJ5hz9aiHmYsnMCIEQUMRP8NHXQT8jVET4LvLQtgFFKnxoiR+myp4eOINRJASECuzzjWvJvTIJuqz5fwmPvVocbJmhqiplVmbfuZXZhMQQAAAABABYAFOCEa9F4SKtAyh9WtlXG+jFmeIDMAA==" + generatedPsbtPartialB64, err := psbt1.B64Encode() + if err != nil { + t.Fatalf("Unable to B64Encode Psbt: %v", err) + } + if expectedPsbtPartialB64 != generatedPsbtPartialB64 { + t.Fatalf("Partial did not match expected: %v", generatedPsbtPartialB64) + } + + // We now simulate adding the signing data for the second (fake) input, + // and check that we can finalize and extract. This input is p2sh-p2wsh. + // the second input is fake, we're going to make it witness type, + // so create a TxOut struct that fits + fakeTxOutSerialized, err := hex.DecodeString("00c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e887") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + fakevalSerialized := binary.LittleEndian.Uint64(fakeTxOutSerialized[:8]) + fakeScriptPubKey := fakeTxOutSerialized[9:] + txFund2Out := wire.NewTxOut(int64(fakevalSerialized), fakeScriptPubKey) + psbt2, err := NewFromRawBytes(bytes.NewReader([]byte(expectedPsbtPartialB64)), true) + if err != nil { + t.Fatalf("Failed to load partial PSBT: %v", err) + } + psbtupdater2, err := NewUpdater(psbt2) + if err != nil { + t.Fatalf("Failed to create updater: %v", err) + } + psbtupdater2.AddInWitnessUtxo(txFund2Out, 1) + // Add redeemScript, which is the witnessscript/program: + redeemScript, err = hex.DecodeString("00208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + err = psbtupdater2.AddInRedeemScript(redeemScript, 1) + if err != nil { + t.Fatalf("Failed to add redeemscript to second input: %v", err) + } + // Add witnessScript, which here is multisig: + witnessScript, err := hex.DecodeString("522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + // To test multisig checks, add a nonsense version of the multisig script + witnessScriptNonsense, err := hex.DecodeString("52ffff") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + err = psbtupdater2.AddInWitnessScript(witnessScript, 1) + if err != nil { + t.Fatalf("Failed to add witnessscript to second input: %v", err) + } + // Construct the two partial signatures to be added + sig21, err := hex.DecodeString("3044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + pub21, err := hex.DecodeString("03089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + sig22, err := hex.DecodeString("3044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d201") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + pub22, err := hex.DecodeString("023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + res, err = psbtupdater2.Sign(1, sig21, pub21, nil, nil) + + // Check that the finalization procedure fails here due to not + // meeting the multisig policy + success, err := MaybeFinalize(psbt2, 1) + if success { + t.Fatalf("Incorrectly succeeded in finalizing without sigs") + } + if err != ErrUnsupportedScriptType { + t.Fatalf("Got unexpected error type: %v", err) + } + + res, err = psbtupdater2.Sign(1, sig22, pub22, nil, nil) + + // Check that the finalization procedure also fails with a nonsense + // script + err = psbtupdater2.AddInWitnessScript(witnessScriptNonsense, 1) + if err != nil { + t.Fatalf("Failed to add witnessscript to second input: %v", err) + } + success, err = MaybeFinalize(psbt2, 1) + if success { + t.Fatalf("Incorrectly succeeded in finalizing with invalid msigscript") + } + if err != ErrUnsupportedScriptType { + t.Fatalf("Got unexpected error type: %v", err) + } + + // Restore the correct witnessScript to complete correctly + err = psbtupdater2.AddInWitnessScript(witnessScript, 1) + if err != nil { + t.Fatalf("Failed to add witnessscript to second input: %v", err) + } + + success, err = MaybeFinalize(psbt2, 1) + if !success { + if err != nil { + t.Fatalf("Failed to finalize second input: %v", err) + } else { + t.Fatalf("Input was not finalizable") + } + } + + // Add a (fake) witnessOut descriptor field to one of the outputs, + // for coverage purposes (we aren't currently using this field) + psbtupdater2.AddOutWitnessScript([]byte{0xff, 0xff, 0xff}, 0) + + // Sanity check; we should not have lost the additional output entry + // provided by Core initially + uoutput1 := psbtupdater2.Upsbt.Outputs[1] + if uoutput1.RedeemScript == nil { + t.Fatalf("PSBT should contain outredeemscript entry, but it does not.") + } + // Nor should we have lost our fake witnessscript output entry + uoutput2 := psbtupdater2.Upsbt.Outputs[0] + if uoutput2.WitnessScript == nil { + t.Fatalf("PSBT should contain outwitnessscript but it does not.") + } + var tx bytes.Buffer + networkSerializedTx, err := Extract(psbt2) + if err != nil { + t.Fatalf("unable to extract tx: %v", err) + } + if err := networkSerializedTx.Serialize(&tx); err != nil { + t.Fatalf("unable to encode tx: %v", err) + } + expectedSerializedTx, err := hex.DecodeString("020000000001024c5343eae283940d9d44b99cc73e3dc728c3821c38979045c34dc3eee9e5903901000000171600147aed39420a8b7ab98a83791327ccb70819d1fbe2ffffffffaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0d000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0200860e70000000001600143597b9e7d7746e6d3c2a450536067555e5695705603131b50000000017a914922b975237d61604e9ea797f81ff7ef3321647a287024730440220546d182d00e45ef659c329dce6197dc19e0abc795e2c9279873f5a887998b273022044143113fc3475d04fc8d5113e0bbcb42d80514a9f1a2247e9b2a7878e20d449012102bb3ce35af26f4c826eab3e5fc263ef56871b26686a8a995599b7ee65766131040400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000") + if err != nil { + t.Fatalf("Failed to decode hex: %v", err) + } + if !bytes.Equal(expectedSerializedTx, tx.Bytes()) { + t.Fatalf("Failed to create correct network serialized "+ + "transaction: expected %x, got %x", + expectedSerializedTx, tx.Bytes()) + } +} + +func TestMaybeFinalizeAll(t *testing.T) { + // The following data is from a 3rd transaction from Core, + // using 3 inputs, all p2wkh. + imported := "cHNidP8BAKQCAAAAAzJyXH13IqBFvvZ7y1VSgUgkMvMoPgP5CfFNqsjQexKQAQAAAAD/////fMdLydu5bsoiHN9cFSaBL0Qnq2KLSKx0RA4b938CAgQAAAAAAP/////yKNgfsDAHr/zFz8R9k8EFI26allfg9DdE8Gzj6tGlegEAAAAA/////wHw9E0OAAAAABYAFDnPCRduiEWmmSc1j30SJ8k9u7PHAAAAAAAAAAAA" + psbt1, err := NewFromRawBytes(bytes.NewReader([]byte(imported)), true) + if err != nil { + t.Fatalf("Failed to parse PSBT: %v", err) + } + + // update with the first input's utxo, taken from its funding + // transaction + fundingTxInput1, err := hex.DecodeString("020000000001017b260536a3c17aee49c41a9b36fdf01a418e0c04df06fbabcb0d4f590b95d1750100000017160014af82cd4409241b1de892726324bd780e3b5cd8aafeffffff02a85f9800000000001600149d21f8b306ddfd4dd035080689e88b4c3471e3cc801d2c0400000000160014d97ccd3dfb60820d7d33d862371ca5a73039bd560247304402201a1d2fdb5a7190b7fa59907769f0fc9c91fd3b34f6424acf5868a8ac21ec287102200a59b9d076ecf98c88f2196ed2be0aafff4966ead754041182fff5f92115a783012103604ffd31dc71db2e32c20f09eafe6353cd7515d3648aff829bb4879b553e30629a000000") + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + fundingTxInput2, err := hex.DecodeString("020000000001019c27b886e420fcadb077706b0933efa8bb53e3a250c3ec45cfdba5e05e233f360100000000feffffff0200b4c404000000001600140853f50c7d2d5d2af326a75efdbc83b62551e89afce31c0d000000001600142d6936c082c35607ec3bdb334a932d928150b75802473044022000d962f5e5e6425f9de21da7ac65b4fd8af8f6bfbd33c7ba022827c73866b477022034c59935c1ea10b5ba335d93f55a200c2588ec6058b8c7aedd10d5cbc4654f99012102c30e9f0cd98f6a805464d6b8a326b5679b6c3262934341855ee0436eaedfd2869a000000") + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + fundingTxInput3, err := hex.DecodeString("02000000012bf4331bb95df4eadb14f7a28db3fecdc5e87f08c29c2332b66338dd606699f60000000048473044022075ed43f508528da47673550a785702e9a93eca84a11faea91c4e9c66fcab3c9e022054a37610bd40b12263a5933188f062b718e007f290cecde2b6e41da3e1ebbddf01feffffff020c99a8240100000016001483bd916985726094d6d1c5b969722da580b5966a804a5d05000000001600140a2ee13a6696d75006af5e8a026ea49316087dae9a000000") + if err != nil { + t.Fatalf("Unable to decode hex: %v", err) + } + + psbtupdater1 := Updater{Upsbt: psbt1} + tx := wire.NewMsgTx(2) + err = tx.Deserialize(bytes.NewReader(fundingTxInput1)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + txFund1Out := tx.TxOut[1] + psbtupdater1.AddInWitnessUtxo(txFund1Out, 0) + + tx = wire.NewMsgTx(2) + err = tx.Deserialize(bytes.NewReader(fundingTxInput2)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + txFund2Out := tx.TxOut[0] + psbtupdater1.AddInWitnessUtxo(txFund2Out, 1) + + tx = wire.NewMsgTx(2) + err = tx.Deserialize(bytes.NewReader(fundingTxInput3)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + txFund3Out := tx.TxOut[1] + psbtupdater1.AddInWitnessUtxo(txFund3Out, 2) + + // To be ready for finalization, we need to have partial signature + // fields for each input + sig1, _ := hex.DecodeString("30440220027605ee8015970baf02a72652967a543e1b29a6882d799738ed1baee508822702203818a2f1b9770c46a473f47ad7ae90bcc129a5d047f00fae354c80197a7cf50601") + pub1, _ := hex.DecodeString("03235fc1f9dc8bbf6fa3df35dfeb0dd486f2d488f139579885eb684510f004f6c1") + sig2, _ := hex.DecodeString("304402206f5aea4621696610de48736b95a89b1d3a434a4e536d9aae65e039c477cf4c7202203b27a18b0f63be7d3bbf5be1bc2306a7ec8c2da12c2820ff07b73c7f3f1d4d7301") + pub2, _ := hex.DecodeString("022011b496f0603a268b55a781c7be0c3849f605f09cb2e917ed44288b8144a752") + sig3, _ := hex.DecodeString("3044022036dbc6f8f85a856e7803cbbcf0a97b7a74806fc592e92d7c06826f911610b98e0220111d43c4b20f756581791334d9c5cbb1a9c07558f28404cabf01c782897ad50501") + pub3, _ := hex.DecodeString("0381772a80c69e275e20d7f014555b13031e9cacf1c54a44a67ab2bc7eba64f227") + res, err := psbtupdater1.Sign(0, sig1, pub1, nil, nil) + if err != nil || res != 0 { + t.Fatalf("Failed to add partial signature for input 0: %v %v", err, res) + } + res, err = psbtupdater1.Sign(1, sig2, pub2, nil, nil) + if err != nil || res != 0 { + t.Fatalf("Failed to add partial signature for input 1: %v %v", err, res) + } + + // Not ready for finalize all, check it fails: + err = MaybeFinalizeAll(psbt1) + if err != ErrNotFinalizable { + t.Fatalf("Expected finalization failure, got: %v", err) + } + + res, err = psbtupdater1.Sign(2, sig3, pub3, nil, nil) + + // Since this input is now finalizable and is p2wkh only, we can do + // all at once: + err = MaybeFinalizeAll(psbt1) + if err != nil { + t.Fatalf("Failed to finalize PSBT: %v", err) + } + if !psbt1.IsComplete() { + t.Fatalf("PSBT was finalized but not marked complete") + } + +} + +func TestFromUnsigned(t *testing.T) { + serTx, err := hex.DecodeString("00000000000101e165f072311e71825b47a4797221d7ae56d4b40b7707c540049aee43302448a40000000000feffffff0212f1126a0000000017a9143e836801b2b15aa193449d815c62d6c4b6227c898780778e060000000017a914ba4bdb0b07d67bc60f59c1f4fe54170565254974870000000000") + if err != nil { + t.Fatalf("Error: %v", err) + } + tx := wire.NewMsgTx(2) + err = tx.Deserialize(bytes.NewReader(serTx)) + if err != nil { + t.Fatalf("Error: %v", err) + } + psbt1, err := NewFromUnsignedTx(tx) + if err != nil { + t.Fatalf("Error: %v", err) + } + encoded, err := psbt1.B64Encode() + if err != nil { + t.Fatalf("Unable to B64Encode Psbt: %v", err) + } + + // Compare with output of Core: + fromCoreB64 := "cHNidP8BAHMAAAAAAeFl8HIxHnGCW0ekeXIh165W1LQLdwfFQASa7kMwJEikAAAAAAD+////AhLxEmoAAAAAF6kUPoNoAbKxWqGTRJ2BXGLWxLYifImHgHeOBgAAAAAXqRS6S9sLB9Z7xg9ZwfT+VBcFZSVJdIcAAAAAAAAAAA==" + if encoded != fromCoreB64 { + t.Fatalf("Got incorrect b64: %v", encoded) + } + _, err = NewFromRawBytes(bytes.NewReader([]byte(fromCoreB64)), true) + if err != nil { + t.Fatalf("Error: %v", err) + } +} + +func TestNonWitnessToWitness(t *testing.T) { + // We'll start with a PSBT produced by Core for which + // the first input is signed and we'll provided the signatures for + // the other three inputs; they are p2sh-p2wkh, p2wkh and legacy + // respectively. + // In each case we'll *first* attach the NonWitnessUtxo field, + // and then call sign; in the first two but not the third case, the + // NonWitnessUtxo will automatically be replaced with the WitnessUtxo. + // Finally we'll check that the fully finalized PSBT produced matches + // the one produced by Core for the same keys. + + psbt1B64 := "cHNidP8BAM4CAAAABHtBMXY+SX95xidmWJP67CTQ02FPUpbNhIxNplAdlvk+AQAAAAD/////G2mt4bX7+sVi1jdbuBa5Q/xsJdgzFCgdHHSZq3ewK6YAAAAAAP/////NrbZb7GzfAg4kOqFWAIbXabq4cAvtVGv+eecIIv1KggEAAAAA/////73s9ifprgErlaONH1rgpNs3l6+t+mz2XGTHsTVWCem/AQAAAAD/////AfAmclMAAAAAF6kUQwsEC5nzbdY5meON2ZQ2thmeFgOHAAAAAAABASAAZc0dAAAAABepFPAv3VTMu5+4WN+/HIji6kG9RpzKhwEHFxYAFLN3PqXSyIHWKqm4ah5m9erc/3OoAQhrAkcwRAIgH7kzGO2iskfCvX0dgkDuzfqJ7tAu7KUZOeykTkJ1SYkCIBv4QRZK1hLz45D0gs+Lz93OE4s37lkPVE+SlXZtazWEASEC3jaf19MMferBn0Bn5lxXJGOqoqmfSvnHclQvB5gJ3nEAAAAAAQAWABTB+Qcq6iqdSvvc6959kd7XHrhYFgA=" + nwutxo1ser, _ := hex.DecodeString("02000000017f7baa6b7377541c4aca372d2dce8e1098ba44aa8379b7ea87644ef27e08ec240000000048473044022072e3b94c33cb5128518cd3903cc0ca19e8c234ac6d462e01ae2bb1da7768ed7d0220167d7ad89f6e1bbb3b866ae6fc2f67b5e7d51eb4f33f7bfe3f4b2673856b815001feffffff0200c2eb0b0000000017a9142dd25c78db2e2e09376eab9cb342e1b03005abe487e4ab953e0000000017a914120b8ca3fb4c7f852e30d4e3714fb64027a0b4c38721020000") + nwutxo2ser, _ := hex.DecodeString("0200000001f51b0bb5d945dd5532448a4d3fb88134d0bd90493813515f9c2ddb1fa15b9ba60000000048473044022047d83caf88d398245c006374bfa9f27ae968f5f51d640cacd5a214ed2cba397a02204519b26035496855f574a72b73bdcfa46d53995faf64c8f0ab394b628cc5383901feffffff020ccb9f3800000000160014e13544a3c718faa6c5ad7089a6660383c12b072700a3e11100000000160014a5439b477c116b79bd4c7c5131f3e58d54f27bb721020000") + nwutxo3ser, _ := hex.DecodeString("0200000001eb452f0fc9a8c39edb79f7174763f3cb25dc56db455926e411719a115ef16509000000004847304402205aa80cc615eb4b3f6e89696db4eadd192581a6c46f5c09807d3d98ece1d77355022025007e58c1992a1e5d877ee324bfe0a65db26d29f80941cfa277ac3efbcad2a701feffffff02bce9a9320000000017a9141590e852ac66eb8798afeb2a5ed67c568a2d6561870084d717000000001976a914a57ea05eacf94900d5fb92bccd273cfdb90af36f88ac21020000") + + nwutxo1 := wire.NewMsgTx(2) + err := nwutxo1.Deserialize(bytes.NewReader(nwutxo1ser)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + nwutxo2 := wire.NewMsgTx(2) + err = nwutxo2.Deserialize(bytes.NewReader(nwutxo2ser)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + nwutxo3 := wire.NewMsgTx(2) + err = nwutxo3.Deserialize(bytes.NewReader(nwutxo3ser)) + if err != nil { + t.Fatalf("Error deserializing transaction: %v", err) + } + + // import the PSBT + psbt1, err := NewFromRawBytes(bytes.NewReader([]byte(psbt1B64)), true) + if err != nil { + t.Fatalf("Failed to create PSBT: %v", err) + } + + // check that we recognize the finality of the first input + if !isFinalized(psbt1, 0) { + t.Fatalf("First input incorrectly read as not finalized.") + } + + // Add NonWitnessUtxo fields for each of the other three inputs + u := Updater{Upsbt: psbt1} + u.AddInNonWitnessUtxo(nwutxo1, 1) + u.AddInNonWitnessUtxo(nwutxo2, 2) + u.AddInNonWitnessUtxo(nwutxo3, 3) + + // Signatures for each of those inputs were created with Core: + sig1, _ := hex.DecodeString("304402205676877e6162ce40a49ee5a74443cdc1e7915637c42da7b872c2ec2298fd371b02203c1d4a05b1e2a7a588d9ec9b8d4892d2cd59bebe0e777483477a0ec692ebbe6d01") + pub1, _ := hex.DecodeString("02534f23cb88a048b649672967263bd7570312d5d31d066fa7b303970010a77b2b") + redeemScript1, _ := hex.DecodeString("00142412be29368c0260cb841eecd9b59d7e01174aa1") + + sig2, _ := hex.DecodeString("3044022065d0a349709b8d8043cfd644cf6c196c1f601a22e1b3fdfbf8c0cc2a80fe2f1702207c87d36b666a8862e81ec5df288707f517d2f35ea1548feb82019de2c8de90f701") + pub2, _ := hex.DecodeString("0257d88eaf1e79b72ea0a33ae89b57dae95ea68499bdc6770257e010ab899f0abb") + + sig3, _ := hex.DecodeString("30440220290abcaacbd759c4f989762a9ee3468a9231788aab8f50bf65955d8597d8dd3602204d7e394f4419dc5392c6edba6945837458dd750a030ac67a746231903a8eb7db01") + pub3, _ := hex.DecodeString("0388025f50bb51c0469421ed13381f22f9d46a070ec2837e055c49c5876f0d0968") + + // Add the signatures and any scripts needed to the inputs + res, err := u.Sign(1, sig1, pub1, redeemScript1, nil) + if res != 0 || err != nil { + t.Fatalf("Failed to sign at index %v res %v err %v", 1, res, err) + } + res, err = u.Sign(2, sig2, pub2, nil, nil) + if res != 0 || err != nil { + t.Fatalf("Failed to sign at index %v res %v err %v", 2, res, err) + } + res, err = u.Sign(3, sig3, pub3, nil, nil) + if res != 0 || err != nil { + t.Fatalf("Failed to sign at index %v res %v err %v", 3, res, err) + } + + // Attempt to finalize the rest of the transaction + _, err = MaybeFinalize(psbt1, 1) + if err != nil { + t.Fatalf("Failed to finalize input 1 %v", err) + } + _, err = MaybeFinalize(psbt1, 2) + if err != nil { + t.Fatalf("Failed to finalize input 2 %v", err) + } + _, err = MaybeFinalize(psbt1, 3) + if err != nil { + t.Fatalf("Failed to finalize input 3 %v", err) + } + + // Finally we can check whether both the B64 encoding of the PSBT, + // and the final network serialized signed transaction, that we generated + // with Core using the 2 wallets, matches what this code produces: + expectedFinalizedPsbt := "cHNidP8BAM4CAAAABHtBMXY+SX95xidmWJP67CTQ02FPUpbNhIxNplAdlvk+AQAAAAD/////G2mt4bX7+sVi1jdbuBa5Q/xsJdgzFCgdHHSZq3ewK6YAAAAAAP/////NrbZb7GzfAg4kOqFWAIbXabq4cAvtVGv+eecIIv1KggEAAAAA/////73s9ifprgErlaONH1rgpNs3l6+t+mz2XGTHsTVWCem/AQAAAAD/////AfAmclMAAAAAF6kUQwsEC5nzbdY5meON2ZQ2thmeFgOHAAAAAAABASAAZc0dAAAAABepFPAv3VTMu5+4WN+/HIji6kG9RpzKhwEHFxYAFLN3PqXSyIHWKqm4ah5m9erc/3OoAQhrAkcwRAIgH7kzGO2iskfCvX0dgkDuzfqJ7tAu7KUZOeykTkJ1SYkCIBv4QRZK1hLz45D0gs+Lz93OE4s37lkPVE+SlXZtazWEASEC3jaf19MMferBn0Bn5lxXJGOqoqmfSvnHclQvB5gJ3nEAAQEgAMLrCwAAAAAXqRQt0lx42y4uCTduq5yzQuGwMAWr5IcBBxcWABQkEr4pNowCYMuEHuzZtZ1+ARdKoQEIawJHMEQCIFZ2h35hYs5ApJ7lp0RDzcHnkVY3xC2nuHLC7CKY/TcbAiA8HUoFseKnpYjZ7JuNSJLSzVm+vg53dINHeg7Gkuu+bQEhAlNPI8uIoEi2SWcpZyY711cDEtXTHQZvp7MDlwAQp3srAAEBHwCj4REAAAAAFgAUpUObR3wRa3m9THxRMfPljVTye7cBCGsCRzBEAiBl0KNJcJuNgEPP1kTPbBlsH2AaIuGz/fv4wMwqgP4vFwIgfIfTa2ZqiGLoHsXfKIcH9RfS816hVI/rggGd4sjekPcBIQJX2I6vHnm3LqCjOuibV9rpXqaEmb3GdwJX4BCriZ8KuwABAL0CAAAAAetFLw/JqMOe23n3F0dj88sl3FbbRVkm5BFxmhFe8WUJAAAAAEhHMEQCIFqoDMYV60s/bolpbbTq3RklgabEb1wJgH09mOzh13NVAiAlAH5YwZkqHl2HfuMkv+CmXbJtKfgJQc+id6w++8rSpwH+////ArzpqTIAAAAAF6kUFZDoUqxm64eYr+sqXtZ8VootZWGHAITXFwAAAAAZdqkUpX6gXqz5SQDV+5K8zSc8/bkK82+IrCECAAABB2pHMEQCICkKvKrL11nE+Yl2Kp7jRoqSMXiKq49Qv2WVXYWX2N02AiBNfjlPRBncU5LG7bppRYN0WN11CgMKxnp0YjGQOo632wEhA4gCX1C7UcBGlCHtEzgfIvnUagcOwoN+BVxJxYdvDQloAAEAFgAUwfkHKuoqnUr73OvefZHe1x64WBYA" + calculatedPsbt, err := u.Upsbt.B64Encode() + if err != nil { + t.Fatalf("Failed to base64 encode") + } + if expectedFinalizedPsbt != calculatedPsbt { + t.Fatalf("Failed to generate correct PSBT") + } + + expectedNetworkSer, _ := hex.DecodeString("020000000001047b4131763e497f79c627665893faec24d0d3614f5296cd848c4da6501d96f93e0100000017160014b3773ea5d2c881d62aa9b86a1e66f5eadcff73a8ffffffff1b69ade1b5fbfac562d6375bb816b943fc6c25d83314281d1c7499ab77b02ba600000000171600142412be29368c0260cb841eecd9b59d7e01174aa1ffffffffcdadb65bec6cdf020e243aa1560086d769bab8700bed546bfe79e70822fd4a820100000000ffffffffbdecf627e9ae012b95a38d1f5ae0a4db3797afadfa6cf65c64c7b1355609e9bf010000006a4730440220290abcaacbd759c4f989762a9ee3468a9231788aab8f50bf65955d8597d8dd3602204d7e394f4419dc5392c6edba6945837458dd750a030ac67a746231903a8eb7db01210388025f50bb51c0469421ed13381f22f9d46a070ec2837e055c49c5876f0d0968ffffffff01f02672530000000017a914430b040b99f36dd63999e38dd99436b6199e1603870247304402201fb93318eda2b247c2bd7d1d8240eecdfa89eed02eeca51939eca44e4275498902201bf841164ad612f3e390f482cf8bcfddce138b37ee590f544f9295766d6b3584012102de369fd7d30c7deac19f4067e65c572463aaa2a99f4af9c772542f079809de710247304402205676877e6162ce40a49ee5a74443cdc1e7915637c42da7b872c2ec2298fd371b02203c1d4a05b1e2a7a588d9ec9b8d4892d2cd59bebe0e777483477a0ec692ebbe6d012102534f23cb88a048b649672967263bd7570312d5d31d066fa7b303970010a77b2b02473044022065d0a349709b8d8043cfd644cf6c196c1f601a22e1b3fdfbf8c0cc2a80fe2f1702207c87d36b666a8862e81ec5df288707f517d2f35ea1548feb82019de2c8de90f701210257d88eaf1e79b72ea0a33ae89b57dae95ea68499bdc6770257e010ab899f0abb0000000000") + tx, err := Extract(psbt1) + if err != nil { + t.Fatalf("Failed to extract: %v", err) + } + var b bytes.Buffer + if err := tx.Serialize(&b); err != nil { + t.Fatalf("unable to encode tx: %v", err) + } + if !bytes.Equal(expectedNetworkSer, b.Bytes()) { + t.Fatalf("Expected serialized transaction was not produced: %x", b.Bytes()) + } +} + +// TestEmptyInputSerialization tests the special serialization case for a wire +// transaction that has no inputs. +func TestEmptyInputSerialization(t *testing.T) { + // Create and serialize a new, empty PSBT. The wire package will assume + // it's a non-witness transaction, as there are no inputs. + psbt, err := New(nil, nil, 2, 0, nil) + if err != nil { + t.Fatalf("failed to create empty PSBT: %v", err) + } + var buf bytes.Buffer + err = psbt.Serialize(&buf) + if err != nil { + t.Fatalf("failed to serialize empty PSBT: %v", err) + } + + // Try to deserialize the empty transaction again. The wire package will + // assume it's a witness transaction because of the special case where + // there are no inputs. This assumption is wrong and the first attempt + // will fail. But a workaround should try again to deserialize the TX + // with the non-witness format. + psbt2, err := NewFromRawBytes(&buf, false) + if err != nil { + t.Fatalf("failed to deserialize empty PSBT: %v", err) + } + if len(psbt2.UnsignedTx.TxIn) > 0 || len(psbt2.UnsignedTx.TxOut) > 0 { + t.Fatalf("deserialized transaction not empty") + } +} + +// TestWitnessForNonWitnessUtxo makes sure that a packet that only has a non- +// witness UTXO set can still be signed correctly by adding witness data. This +// is to make sure that PSBTs following the CVE-2020-14199 bugfix are not +// rejected. See https://github.com/bitcoin/bitcoin/pull/19215. +func TestWitnessForNonWitnessUtxo(t *testing.T) { + // Our witness UTXO is index 1 of this raw transaction from the test + // vectors. + prevTxRaw, _ := hex.DecodeString("0200000000010158e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7501000000171600145f275f436b09a8cc9a2eb2a2f528485c68a56323feffffff02d8231f1b0100000017a914aed962d6654f9a2b36608eb9d64d2b260db4f1118700c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e88702483045022100a22edcc6e5bc511af4cc4ae0de0fcd75c7e04d8c1c3a8aa9d820ed4b967384ec02200642963597b9b1bc22c75e9f3e117284a962188bf5e8a74c895089046a20ad770121035509a48eb623e10aace8bfd0212fdb8a8e5af3c94b0b133b95e114cab89e4f7965000000") + prevTx := wire.NewMsgTx(2) + err := prevTx.Deserialize(bytes.NewReader(prevTxRaw)) + if err != nil { + t.Fatalf("failed to deserialize previous TX: %v", err) + } + + // First create a packet that contains one input and one output. + outPkScript, _ := hex.DecodeString(CUTestHexData["scriptPubkey1"]) + packet := &Packet{ + UnsignedTx: &wire.MsgTx{ + Version: 2, + LockTime: 0, + TxIn: []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{ + Hash: prevTx.TxHash(), + Index: 1, + }, + }}, + TxOut: []*wire.TxOut{{ + PkScript: outPkScript, + Value: 1.9 * btcutil.SatoshiPerBitcoin, + }}, + }, + Inputs: []PInput{{}}, + Outputs: []POutput{{}}, + } + + // Create an updater for the packet. This also performs a sanity check. + updater, err := NewUpdater(packet) + if err != nil { + t.Fatalf("failed to sanity check raw packet: %v", err) + } + + // Now add our witness UTXO to the input. But because hardware wallets + // that are patched against CVE-2020-14199 require the full non-witness + // UTXO to be set for all inputs, we do what Core does and add the full + // transaction in the NonWitnessUtxo instead of just the outpoint in + // WitnessUtxo. + err = updater.AddInNonWitnessUtxo(prevTx, 0) + if err != nil { + t.Fatalf("failed to update non-witness UTXO: %v", err) + } + + // Then add the redeem scripts and witness scripts. + redeemScript, _ := hex.DecodeString(CUTestHexData["Input2RedeemScript"]) + err = updater.AddInRedeemScript(redeemScript, 0) + if err != nil { + t.Fatalf("failed to update redeem script: %v", err) + } + witnessScript, _ := hex.DecodeString(CUTestHexData["Input2WitnessScript"]) + err = updater.AddInWitnessScript(witnessScript, 0) + if err != nil { + t.Fatalf("failed to update redeem script: %v", err) + } + + // Add the first of the two partial signatures. + sig1, _ := hex.DecodeString("3044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01") + pub1, _ := hex.DecodeString("03089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc") + res, err := updater.Sign(0, sig1, pub1, nil, nil) + if err != nil { + t.Fatalf("failed to sign with pubkey 1: %v", err) + } + if res != SignSuccesful { + t.Fatalf("signing was not successful, got result %v", res) + } + + // Check that the finalization procedure fails here due to not + // meeting the multisig policy + success, err := MaybeFinalize(packet, 0) + if success { + t.Fatalf("Incorrectly succeeded in finalizing without sigs") + } + if err != ErrUnsupportedScriptType { + t.Fatalf("Got unexpected error type: %v", err) + } + + // Add the second partial signature. + sig2, _ := hex.DecodeString("3044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d201") + pub2, _ := hex.DecodeString("023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e73") + res, err = updater.Sign(0, sig2, pub2, nil, nil) + if err != nil { + t.Fatalf("failed to sign with pubkey 2: %v", err) + } + if res != SignSuccesful { + t.Fatalf("signing was not successful, got result %v", res) + } + + // Finally make sure we can finalize the packet and extract the raw TX. + err = MaybeFinalizeAll(packet) + if err != nil { + t.Fatalf("error finalizing PSBT: %v", err) + } + _, err = Extract(packet) + if err != nil { + t.Fatalf("unable to extract funding TX: %v", err) + } +} diff --git a/btcutil/psbt/signer.go b/btcutil/psbt/signer.go new file mode 100644 index 0000000000..588265317f --- /dev/null +++ b/btcutil/psbt/signer.go @@ -0,0 +1,155 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package psbt + +// signer encapsulates the role 'Signer' as specified in BIP174; it controls +// the insertion of signatures; the Sign() function will attempt to insert +// signatures using Updater.addPartialSignature, after first ensuring the Psbt +// is in the correct state. + +import ( + "github.com/btcsuite/btcd/txscript" +) + +// SignOutcome is a enum-like value that expresses the outcome of a call to the +// Sign method. +type SignOutcome int + +const ( + // SignSuccesful indicates that the partial signature was successfully + // attached. + SignSuccesful = 0 + + // SignFinalized indicates that this input is already finalized, so the provided + // signature was *not* attached + SignFinalized = 1 + + // SignInvalid indicates that the provided signature data was not valid. In this case + // an error will also be returned. + SignInvalid = -1 +) + +// Sign allows the caller to sign a PSBT at a particular input; they +// must provide a signature and a pubkey, both as byte slices; they can also +// optionally provide both witnessScript and/or redeemScript, otherwise these +// arguments must be set as nil (and in that case, they must already be present +// in the PSBT if required for signing to succeed). +// +// This serves as a wrapper around Updater.addPartialSignature; it ensures that +// the redeemScript and witnessScript are updated as needed (note that the +// Updater is allowed to add redeemScripts and witnessScripts independently, +// before signing), and ensures that the right form of utxo field +// (NonWitnessUtxo or WitnessUtxo) is included in the input so that signature +// insertion (and then finalization) can take place. +func (u *Updater) Sign(inIndex int, sig []byte, pubKey []byte, + redeemScript []byte, witnessScript []byte) (SignOutcome, error) { + + if isFinalized(u.Upsbt, inIndex) { + return SignFinalized, nil + } + + // Add the witnessScript to the PSBT in preparation. If it already + // exists, it will be overwritten. + if witnessScript != nil { + err := u.AddInWitnessScript(witnessScript, inIndex) + if err != nil { + return SignInvalid, err + } + } + + // Add the redeemScript to the PSBT in preparation. If it already + // exists, it will be overwritten. + if redeemScript != nil { + err := u.AddInRedeemScript(redeemScript, inIndex) + if err != nil { + return SignInvalid, err + } + } + + // At this point, the PSBT must have the requisite witnessScript or + // redeemScript fields for signing to succeed. + // + // Case 1: if witnessScript is present, it must be of type witness; + // if not, signature insertion will of course fail. + switch { + case u.Upsbt.Inputs[inIndex].WitnessScript != nil: + if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil { + err := nonWitnessToWitness(u.Upsbt, inIndex) + if err != nil { + return SignInvalid, err + } + } + + err := u.addPartialSignature(inIndex, sig, pubKey) + if err != nil { + return SignInvalid, err + } + + // Case 2: no witness script, only redeem script; can be legacy p2sh or + // p2sh-wrapped p2wkh. + case u.Upsbt.Inputs[inIndex].RedeemScript != nil: + // We only need to decide if the input is witness, and we don't + // rely on the witnessutxo/nonwitnessutxo in the PSBT, instead + // we check the redeemScript content. + if txscript.IsWitnessProgram(redeemScript) { + if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil { + err := nonWitnessToWitness(u.Upsbt, inIndex) + if err != nil { + return SignInvalid, err + } + } + } + + // If it is not a valid witness program, we here assume that + // the provided WitnessUtxo/NonWitnessUtxo field was correct. + err := u.addPartialSignature(inIndex, sig, pubKey) + if err != nil { + return SignInvalid, err + } + + // Case 3: Neither provided only works for native p2wkh, or non-segwit + // non-p2sh. To check if it's segwit, check the scriptPubKey of the + // output. + default: + if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil { + outIndex := u.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index + script := u.Upsbt.Inputs[inIndex].NonWitnessUtxo.TxOut[outIndex].PkScript + + if txscript.IsWitnessProgram(script) { + err := nonWitnessToWitness(u.Upsbt, inIndex) + if err != nil { + return SignInvalid, err + } + } + } + + err := u.addPartialSignature(inIndex, sig, pubKey) + if err != nil { + return SignInvalid, err + } + } + + return SignSuccesful, nil +} + +// nonWitnessToWitness extracts the TxOut from the existing NonWitnessUtxo +// field in the given PSBT input and sets it as type witness by replacing the +// NonWitnessUtxo field with a WitnessUtxo field. See +// https://github.com/bitcoin/bitcoin/pull/14197. +func nonWitnessToWitness(p *Packet, inIndex int) error { + outIndex := p.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index + txout := p.Inputs[inIndex].NonWitnessUtxo.TxOut[outIndex] + + // TODO(guggero): For segwit v1, we'll want to remove the NonWitnessUtxo + // from the packet. For segwit v0 it is unsafe to only rely on the + // witness UTXO. See https://github.com/bitcoin/bitcoin/pull/19215. + // p.Inputs[inIndex].NonWitnessUtxo = nil + + u := Updater{ + Upsbt: p, + } + + return u.AddInWitnessUtxo(txout, inIndex) +} diff --git a/btcutil/psbt/sort.go b/btcutil/psbt/sort.go new file mode 100644 index 0000000000..2232d68feb --- /dev/null +++ b/btcutil/psbt/sort.go @@ -0,0 +1,102 @@ +package psbt + +import ( + "bytes" + "sort" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +// InPlaceSort modifies the passed packet's wire TX inputs and outputs to be +// sorted based on BIP 69. The sorting happens in a way that the packet's +// partial inputs and outputs are also modified to match the sorted TxIn and +// TxOuts of the wire transaction. +// +// WARNING: This function must NOT be called with packages that already contain +// (partial) witness data since it will mutate the transaction if it's not +// already sorted. This can cause issues if you mutate a tx in a block, for +// example, which would invalidate the block. It could also cause cached hashes, +// such as in a btcutil.Tx to become invalidated. +// +// The function should only be used if the caller is creating the transaction or +// is otherwise 100% positive mutating will not cause adverse affects due to +// other dependencies. +func InPlaceSort(packet *Packet) error { + // To make sure we don't run into any nil pointers or array index + // violations during sorting, do a very basic sanity check first. + err := VerifyInputOutputLen(packet, false, false) + if err != nil { + return err + } + + sort.Sort(&sortableInputs{p: packet}) + sort.Sort(&sortableOutputs{p: packet}) + + return nil +} + +// sortableInputs is a simple wrapper around a packet that implements the +// sort.Interface for sorting the wire and partial inputs of a packet. +type sortableInputs struct { + p *Packet +} + +// sortableOutputs is a simple wrapper around a packet that implements the +// sort.Interface for sorting the wire and partial outputs of a packet. +type sortableOutputs struct { + p *Packet +} + +// For sortableInputs and sortableOutputs, three functions are needed to make +// them sortable with sort.Sort() -- Len, Less, and Swap. +// Len and Swap are trivial. Less is BIP 69 specific. +func (s *sortableInputs) Len() int { return len(s.p.UnsignedTx.TxIn) } +func (s sortableOutputs) Len() int { return len(s.p.UnsignedTx.TxOut) } + +// Swap swaps two inputs. +func (s *sortableInputs) Swap(i, j int) { + tx := s.p.UnsignedTx + tx.TxIn[i], tx.TxIn[j] = tx.TxIn[j], tx.TxIn[i] + s.p.Inputs[i], s.p.Inputs[j] = s.p.Inputs[j], s.p.Inputs[i] +} + +// Swap swaps two outputs. +func (s *sortableOutputs) Swap(i, j int) { + tx := s.p.UnsignedTx + tx.TxOut[i], tx.TxOut[j] = tx.TxOut[j], tx.TxOut[i] + s.p.Outputs[i], s.p.Outputs[j] = s.p.Outputs[j], s.p.Outputs[i] +} + +// Less is the input comparison function. First sort based on input hash +// (reversed / rpc-style), then index. +func (s *sortableInputs) Less(i, j int) bool { + ins := s.p.UnsignedTx.TxIn + + // Input hashes are the same, so compare the index. + ihash := ins[i].PreviousOutPoint.Hash + jhash := ins[j].PreviousOutPoint.Hash + if ihash == jhash { + return ins[i].PreviousOutPoint.Index < + ins[j].PreviousOutPoint.Index + } + + // At this point, the hashes are not equal, so reverse them to + // big-endian and return the result of the comparison. + const hashSize = chainhash.HashSize + for b := 0; b < hashSize/2; b++ { + ihash[b], ihash[hashSize-1-b] = ihash[hashSize-1-b], ihash[b] + jhash[b], jhash[hashSize-1-b] = jhash[hashSize-1-b], jhash[b] + } + return bytes.Compare(ihash[:], jhash[:]) == -1 +} + +// Less is the output comparison function. First sort based on amount (smallest +// first), then PkScript. +func (s *sortableOutputs) Less(i, j int) bool { + outs := s.p.UnsignedTx.TxOut + + if outs[i].Value == outs[j].Value { + return bytes.Compare(outs[i].PkScript, outs[j].PkScript) < 0 + } + return outs[i].Value < outs[j].Value +} diff --git a/btcutil/psbt/sort_test.go b/btcutil/psbt/sort_test.go new file mode 100644 index 0000000000..3dee0f48d8 --- /dev/null +++ b/btcutil/psbt/sort_test.go @@ -0,0 +1,167 @@ +package psbt + +import ( + "reflect" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +func TestInPlaceSort(t *testing.T) { + testCases := []struct { + name string + packet *Packet + expectedTxIn []*wire.TxIn + expectedTxOut []*wire.TxOut + expectedPIn []PInput + expectedPOut []POutput + expectErr bool + }{{ + name: "packet nil", + packet: nil, + expectErr: true, + }, { + name: "no inputs or outputs", + packet: &Packet{UnsignedTx: &wire.MsgTx{}}, + expectErr: false, + }, { + name: "inputs only", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{ + TxIn: []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{99, 88}, + Index: 7, + }, + }, { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{77, 88}, + Index: 12, + }, + }, { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{77, 88}, + Index: 7, + }, + }}, + }, + // Abuse the SighashType as an index to make sure the + // partial inputs are also sorted together with the wire + // inputs. + Inputs: []PInput{{ + SighashType: 0, + }, { + SighashType: 1, + }, { + SighashType: 2, + }}, + }, + expectedTxIn: []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{77, 88}, + Index: 7, + }, + }, { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{77, 88}, + Index: 12, + }, + }, { + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{99, 88}, + Index: 7, + }, + }}, + expectedPIn: []PInput{{ + SighashType: 2, + }, { + SighashType: 1, + }, { + SighashType: 0, + }}, + expectErr: false, + }, { + name: "outputs only", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{ + TxOut: []*wire.TxOut{{ + PkScript: []byte{99, 88}, + Value: 7, + }, { + PkScript: []byte{77, 88}, + Value: 12, + }, { + PkScript: []byte{77, 88}, + Value: 7, + }}, + }, + // Abuse the RedeemScript as an index to make sure the + // partial inputs are also sorted together with the wire + // inputs. + Outputs: []POutput{{ + RedeemScript: []byte{0}, + }, { + RedeemScript: []byte{1}, + }, { + RedeemScript: []byte{2}, + }}, + }, + expectedTxOut: []*wire.TxOut{{ + PkScript: []byte{77, 88}, + Value: 7, + }, { + PkScript: []byte{99, 88}, + Value: 7, + }, { + PkScript: []byte{77, 88}, + Value: 12, + }}, + expectedPOut: []POutput{{ + RedeemScript: []byte{2}, + }, { + RedeemScript: []byte{0}, + }, { + RedeemScript: []byte{1}, + }}, + expectErr: false, + }} + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + p := tc.packet + err := InPlaceSort(p) + if (tc.expectErr && err == nil) || + (!tc.expectErr && err != nil) { + + t.Fatalf("got error '%v' but wanted it to be "+ + "nil: %v", err, tc.expectErr) + } + + // Don't continue on this special test case. + if p == nil { + return + } + + tx := p.UnsignedTx + if !reflect.DeepEqual(tx.TxIn, tc.expectedTxIn) { + t.Fatalf("unexpected txin, got %#v wanted %#v", + tx.TxIn, tc.expectedTxIn) + } + if !reflect.DeepEqual(tx.TxOut, tc.expectedTxOut) { + t.Fatalf("unexpected txout, got %#v wanted %#v", + tx.TxOut, tc.expectedTxOut) + } + + if !reflect.DeepEqual(p.Inputs, tc.expectedPIn) { + t.Fatalf("unexpected pin, got %#v wanted %#v", + p.Inputs, tc.expectedPIn) + } + if !reflect.DeepEqual(p.Outputs, tc.expectedPOut) { + t.Fatalf("unexpected pout, got %#v wanted %#v", + p.Inputs, tc.expectedPOut) + } + }) + } +} diff --git a/btcutil/psbt/types.go b/btcutil/psbt/types.go new file mode 100644 index 0000000000..1b4a26a4dc --- /dev/null +++ b/btcutil/psbt/types.go @@ -0,0 +1,149 @@ +package psbt + +// GlobalType is the set of types that are used at the global scope level +// within the PSBT. +type GlobalType uint8 + +const ( + // UnsignedTxType is the global scope key that houses the unsigned + // transaction of the PSBT. The value is a transaction in network + // serialization. The scriptSigs and witnesses for each input must be + // empty. The transaction must be in the old serialization format + // (without witnesses). A PSBT must have a transaction, otherwise it is + // invalid. + UnsignedTxType GlobalType = 0 + + // XpubType houses a global xpub for the entire PSBT packet. + // + // The key ({0x01}|{xpub}) is he 78 byte serialized extended public key + // as defined by BIP 32. Extended public keys are those that can be + // used to derive public keys used in the inputs and outputs of this + // transaction. It should be the public key at the highest hardened + // derivation index so that + // the unhardened child keys used in the transaction can be derived. + // + // The value is the master key fingerprint as defined by BIP 32 + // concatenated with the derivation path of the public key. The + // derivation path is represented as 32-bit little endian unsigned + // integer indexes concatenated with each other. The number of 32 bit + // unsigned integer indexes must match the depth provided in the + // extended public key. + XpubType GlobalType = 1 + + // VersionType houses the global version number of this PSBT. There is + // no key (only contains the byte type), then the value if omitted, is + // assumed to be zero. + VersionType GlobalType = 0xFB + + // ProprietaryGlobalType is used to house any proper chary global-scope + // keys within the PSBT. + // + // The key is ({0xFC}||{subtype}|{key data}) a variable length + // identifier prefix, followed by a subtype, followed by the key data + // itself. + // + // The value is any data as defined by the proprietary type user. + ProprietaryGlobalType = 0xFC +) + +// InputType is the set of types that are defined for each input included +// within the PSBT. +type InputType uint32 + +const ( + // NonWitnessUtxoType has no key ({0x00}) and houses the transaction in + // network serialization format the current input spends from. This + // should only be present for inputs which spend non-segwit outputs. + // However, if it is unknown whether an input spends a segwit output, + // this type should be used. The entire input transaction is needed in + // order to be able to verify the values of the input (pre-segwit they + // aren't in the signature digest). + NonWitnessUtxoType InputType = 0 + + // WitnessUtxoType has no key ({0x01}), and houses the entire + // transaction output in network serialization which the current input + // spends from. This should only be present for inputs which spend + // segwit outputs, including P2SH embedded ones (value || script). + WitnessUtxoType InputType = 1 + + // PartialSigType is used to include a partial signature with key + // ({0x02}|{public key}). + // + // The value is the signature as would be pushed to the stack from a + // scriptSig or witness.. + PartialSigType InputType = 2 + + // SighashType is an empty key ({0x03}). + // + // The value contains the 32-bit unsigned integer specifying the + // sighash type to be used for this input. Signatures for this input + // must use the sighash type, finalizers must fail to finalize inputs + // which have signatures that do not match the specified sighash type. + // Signers who cannot produce signatures with the sighash type must not + // provide a signature. + SighashType InputType = 3 + + // RedeemScriptInputType is an empty key ({0x40}). + // + // The value is the redeem script of the input if present. + RedeemScriptInputType InputType = 4 + + // WitnessScriptInputType is an empty key ({0x05}). + // + // The value is the witness script of this input, if it has one. + WitnessScriptInputType InputType = 5 + + // Bip32DerivationInputType is a type that carries the pubkey along + // with the key ({0x06}|{public key}). + // + // The value is master key fingerprint as defined by BIP 32 + // concatenated with the derivation path of the public key. The + // derivation path is represented as 32 bit unsigned integer indexes + // concatenated with each other. Public keys are those that will be + // needed to sign this input. + Bip32DerivationInputType InputType = 6 + + // FinalScriptSigType is an empty key ({0x07}). + // + // The value contains a fully constructed scriptSig with signatures and + // any other scripts necessary for the input to pass validation. + FinalScriptSigType InputType = 7 + + // FinalScriptWitnessType is an empty key ({0x08}). The value is a + // fully constructed scriptWitness with signatures and any other + // scripts necessary for the input to pass validation. + FinalScriptWitnessType InputType = 8 + + // ProprietaryInputType is a custom type for use by devs. + // + // The key ({0xFC}||{subtype}|{key data}), is a Variable length + // identifier prefix, followed by a subtype, followed by the key data + // itself. + // + // The value is any value data as defined by the proprietary type user. + ProprietaryInputType InputType = 0xFC +) + +// OutputType is the set of types defined per output within the PSBT. +type OutputType uint32 + +const ( + // RedeemScriptOutputType is an empty key ({0x00}> + // + // The value is the redeemScript for this output if it has one. + RedeemScriptOutputType OutputType = 0 + + // WitnessScriptOutputType is an empty key ({0x01}). + // + // The value is the witness script of this input, if it has one. + WitnessScriptOutputType OutputType = 1 + + j // Bip32DerivationOutputType is used to communicate derivation information + // needed to spend this output. The key is ({0x02}|{public key}). + // + // The value is master key fingerprint concatenated with the derivation + // path of the public key. The derivation path is represented as 32-bit + // little endian unsigned integer indexes concatenated with each other. + // Public keys are those needed to spend this output. + Bip32DerivationOutputType OutputType = 2 +) diff --git a/btcutil/psbt/updater.go b/btcutil/psbt/updater.go new file mode 100644 index 0000000000..56a33654b6 --- /dev/null +++ b/btcutil/psbt/updater.go @@ -0,0 +1,377 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package psbt + +// The Updater requires provision of a single PSBT and is able to add data to +// both input and output sections. It can be called repeatedly to add more +// data. It also allows addition of signatures via the addPartialSignature +// function; this is called internally to the package in the Sign() function of +// Updater, located in signer.go + +import ( + "bytes" + "crypto/sha256" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil" +) + +// Updater encapsulates the role 'Updater' as specified in BIP174; it accepts +// Psbt structs and has methods to add fields to the inputs and outputs. +type Updater struct { + Upsbt *Packet +} + +// NewUpdater returns a new instance of Updater, if the passed Psbt struct is +// in a valid form, else an error. +func NewUpdater(p *Packet) (*Updater, error) { + if err := p.SanityCheck(); err != nil { + return nil, err + } + + return &Updater{Upsbt: p}, nil + +} + +// AddInNonWitnessUtxo adds the utxo information for an input which is +// non-witness. This requires provision of a full transaction (which is the +// source of the corresponding prevOut), and the input index. If addition of +// this key-value pair to the Psbt fails, an error is returned. +func (p *Updater) AddInNonWitnessUtxo(tx *wire.MsgTx, inIndex int) error { + if inIndex > len(p.Upsbt.Inputs)-1 { + return ErrInvalidPrevOutNonWitnessTransaction + } + + p.Upsbt.Inputs[inIndex].NonWitnessUtxo = tx + + if err := p.Upsbt.SanityCheck(); err != nil { + return ErrInvalidPsbtFormat + } + + return nil +} + +// AddInWitnessUtxo adds the utxo information for an input which is witness. +// This requires provision of a full transaction *output* (which is the source +// of the corresponding prevOut); not the full transaction because BIP143 means +// the output information is sufficient, and the input index. If addition of +// this key-value pair to the Psbt fails, an error is returned. +func (p *Updater) AddInWitnessUtxo(txout *wire.TxOut, inIndex int) error { + if inIndex > len(p.Upsbt.Inputs)-1 { + return ErrInvalidPsbtFormat + } + + p.Upsbt.Inputs[inIndex].WitnessUtxo = txout + + if err := p.Upsbt.SanityCheck(); err != nil { + return ErrInvalidPsbtFormat + } + + return nil +} + +// addPartialSignature allows the Updater role to insert fields of type partial +// signature into a Psbt, consisting of both the pubkey (as keydata) and the +// ECDSA signature (as value). Note that the Signer role is encapsulated in +// this function; signatures are only allowed to be added that follow the +// sanity-check on signing rules explained in the BIP under `Signer`; if the +// rules are not satisfied, an ErrInvalidSignatureForInput is returned. +// +// NOTE: This function does *not* validate the ECDSA signature itself. +func (p *Updater) addPartialSignature(inIndex int, sig []byte, + pubkey []byte) error { + + partialSig := PartialSig{ + PubKey: pubkey, Signature: sig, + } + + // First validate the passed (sig, pub). + if !partialSig.checkValid() { + return ErrInvalidPsbtFormat + } + + pInput := p.Upsbt.Inputs[inIndex] + + // First check; don't add duplicates. + for _, x := range pInput.PartialSigs { + if bytes.Equal(x.PubKey, partialSig.PubKey) { + return ErrDuplicateKey + } + } + + // Attaching signature without utxo field is not allowed. + if pInput.WitnessUtxo == nil && pInput.NonWitnessUtxo == nil { + return ErrInvalidPsbtFormat + } + + // Next, we perform a series of additional sanity checks. + if pInput.NonWitnessUtxo != nil { + if len(p.Upsbt.UnsignedTx.TxIn) < inIndex+1 { + return ErrInvalidPrevOutNonWitnessTransaction + } + + if pInput.NonWitnessUtxo.TxHash() != + p.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Hash { + return ErrInvalidSignatureForInput + } + + // To validate that the redeem script matches, we must pull out + // the scriptPubKey of the corresponding output and compare + // that with the P2SH scriptPubKey that is generated by + // redeemScript. + if pInput.RedeemScript != nil { + outIndex := p.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index + scriptPubKey := pInput.NonWitnessUtxo.TxOut[outIndex].PkScript + scriptHash := btcutil.Hash160(pInput.RedeemScript) + + scriptHashScript, err := txscript.NewScriptBuilder(). + AddOp(txscript.OP_HASH160). + AddData(scriptHash). + AddOp(txscript.OP_EQUAL). + Script() + if err != nil { + return err + } + + if !bytes.Equal(scriptHashScript, scriptPubKey) { + return ErrInvalidSignatureForInput + } + } + + } + + // It could be that we set both the non-witness and witness UTXO fields + // in case it's from a wallet that patched the CVE-2020-14199 + // vulnerability. We detect whether the input being spent is actually a + // witness input and then copy it over to the witness UTXO field in the + // signer. Run the witness checks as well, even if we might already have + // checked the script hash. But that should be a negligible performance + // penalty. + if pInput.WitnessUtxo != nil { + scriptPubKey := pInput.WitnessUtxo.PkScript + + var script []byte + if pInput.RedeemScript != nil { + scriptHash := btcutil.Hash160(pInput.RedeemScript) + scriptHashScript, err := txscript.NewScriptBuilder(). + AddOp(txscript.OP_HASH160). + AddData(scriptHash). + AddOp(txscript.OP_EQUAL). + Script() + if err != nil { + return err + } + + if !bytes.Equal(scriptHashScript, scriptPubKey) { + return ErrInvalidSignatureForInput + } + + script = pInput.RedeemScript + } else { + script = scriptPubKey + } + + // If a witnessScript field is present, this is a P2WSH, + // whether nested or not (that is handled by the assignment to + // `script` above); in that case, sanity check that `script` is + // the p2wsh of witnessScript. Contrariwise, if no + // witnessScript field is present, this will be signed as + // p2wkh. + if pInput.WitnessScript != nil { + witnessScriptHash := sha256.Sum256(pInput.WitnessScript) + witnessScriptHashScript, err := txscript.NewScriptBuilder(). + AddOp(txscript.OP_0). + AddData(witnessScriptHash[:]). + Script() + if err != nil { + return err + } + + if !bytes.Equal(script, witnessScriptHashScript[:]) { + return ErrInvalidSignatureForInput + } + } else { + // Otherwise, this is a p2wkh input. + pubkeyHash := btcutil.Hash160(pubkey) + pubkeyHashScript, err := txscript.NewScriptBuilder(). + AddOp(txscript.OP_0). + AddData(pubkeyHash). + Script() + if err != nil { + return err + } + + // Validate that we're able to properly reconstruct the + // witness program. + if !bytes.Equal(pubkeyHashScript, script) { + return ErrInvalidSignatureForInput + } + } + } + + p.Upsbt.Inputs[inIndex].PartialSigs = append( + p.Upsbt.Inputs[inIndex].PartialSigs, &partialSig, + ) + + if err := p.Upsbt.SanityCheck(); err != nil { + return err + } + + // Addition of a non-duplicate-key partial signature cannot violate + // sanity-check rules. + return nil +} + +// AddInSighashType adds the sighash type information for an input. The +// sighash type is passed as a 32 bit unsigned integer, along with the index +// for the input. An error is returned if addition of this key-value pair to +// the Psbt fails. +func (p *Updater) AddInSighashType(sighashType txscript.SigHashType, + inIndex int) error { + + p.Upsbt.Inputs[inIndex].SighashType = sighashType + + if err := p.Upsbt.SanityCheck(); err != nil { + return err + } + return nil +} + +// AddInRedeemScript adds the redeem script information for an input. The +// redeem script is passed serialized, as a byte slice, along with the index of +// the input. An error is returned if addition of this key-value pair to the +// Psbt fails. +func (p *Updater) AddInRedeemScript(redeemScript []byte, + inIndex int) error { + + p.Upsbt.Inputs[inIndex].RedeemScript = redeemScript + + if err := p.Upsbt.SanityCheck(); err != nil { + return ErrInvalidPsbtFormat + } + + return nil +} + +// AddInWitnessScript adds the witness script information for an input. The +// witness script is passed serialized, as a byte slice, along with the index +// of the input. An error is returned if addition of this key-value pair to the +// Psbt fails. +func (p *Updater) AddInWitnessScript(witnessScript []byte, + inIndex int) error { + + p.Upsbt.Inputs[inIndex].WitnessScript = witnessScript + + if err := p.Upsbt.SanityCheck(); err != nil { + return err + } + + return nil +} + +// AddInBip32Derivation takes a master key fingerprint as defined in BIP32, a +// BIP32 path as a slice of uint32 values, and a serialized pubkey as a byte +// slice, along with the integer index of the input, and inserts this data into +// that input. +// +// NOTE: This can be called multiple times for the same input. An error is +// returned if addition of this key-value pair to the Psbt fails. +func (p *Updater) AddInBip32Derivation(masterKeyFingerprint uint32, + bip32Path []uint32, pubKeyData []byte, inIndex int) error { + + bip32Derivation := Bip32Derivation{ + PubKey: pubKeyData, + MasterKeyFingerprint: masterKeyFingerprint, + Bip32Path: bip32Path, + } + + if !bip32Derivation.checkValid() { + return ErrInvalidPsbtFormat + } + + // Don't allow duplicate keys + for _, x := range p.Upsbt.Inputs[inIndex].Bip32Derivation { + if bytes.Equal(x.PubKey, bip32Derivation.PubKey) { + return ErrDuplicateKey + } + } + + p.Upsbt.Inputs[inIndex].Bip32Derivation = append( + p.Upsbt.Inputs[inIndex].Bip32Derivation, &bip32Derivation, + ) + + if err := p.Upsbt.SanityCheck(); err != nil { + return err + } + + return nil +} + +// AddOutBip32Derivation takes a master key fingerprint as defined in BIP32, a +// BIP32 path as a slice of uint32 values, and a serialized pubkey as a byte +// slice, along with the integer index of the output, and inserts this data +// into that output. +// +// NOTE: That this can be called multiple times for the same output. An error +// is returned if addition of this key-value pair to the Psbt fails. +func (p *Updater) AddOutBip32Derivation(masterKeyFingerprint uint32, + bip32Path []uint32, pubKeyData []byte, outIndex int) error { + + bip32Derivation := Bip32Derivation{ + PubKey: pubKeyData, + MasterKeyFingerprint: masterKeyFingerprint, + Bip32Path: bip32Path, + } + + if !bip32Derivation.checkValid() { + return ErrInvalidPsbtFormat + } + + // Don't allow duplicate keys + for _, x := range p.Upsbt.Outputs[outIndex].Bip32Derivation { + if bytes.Equal(x.PubKey, bip32Derivation.PubKey) { + return ErrDuplicateKey + } + } + + p.Upsbt.Outputs[outIndex].Bip32Derivation = append( + p.Upsbt.Outputs[outIndex].Bip32Derivation, &bip32Derivation, + ) + + if err := p.Upsbt.SanityCheck(); err != nil { + return err + } + + return nil +} + +// AddOutRedeemScript takes a redeem script as a byte slice and appends it to +// the output at index outIndex. +func (p *Updater) AddOutRedeemScript(redeemScript []byte, + outIndex int) error { + + p.Upsbt.Outputs[outIndex].RedeemScript = redeemScript + + if err := p.Upsbt.SanityCheck(); err != nil { + return ErrInvalidPsbtFormat + } + + return nil +} + +// AddOutWitnessScript takes a witness script as a byte slice and appends it to +// the output at index outIndex. +func (p *Updater) AddOutWitnessScript(witnessScript []byte, + outIndex int) error { + + p.Upsbt.Outputs[outIndex].WitnessScript = witnessScript + + if err := p.Upsbt.SanityCheck(); err != nil { + return err + } + + return nil +} diff --git a/btcutil/psbt/utils.go b/btcutil/psbt/utils.go new file mode 100644 index 0000000000..494d04070f --- /dev/null +++ b/btcutil/psbt/utils.go @@ -0,0 +1,422 @@ +// Copyright (c) 2018 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package psbt + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "io" + "sort" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +// WriteTxWitness is a utility function due to non-exported witness +// serialization (writeTxWitness encodes the bitcoin protocol encoding for a +// transaction input's witness into w). +func WriteTxWitness(w io.Writer, wit [][]byte) error { + if err := wire.WriteVarInt(w, 0, uint64(len(wit))); err != nil { + return err + } + + for _, item := range wit { + err := wire.WriteVarBytes(w, 0, item) + if err != nil { + return err + } + } + return nil +} + +// writePKHWitness writes a witness for a p2wkh spending input +func writePKHWitness(sig []byte, pub []byte) ([]byte, error) { + var ( + buf bytes.Buffer + witnessItems = [][]byte{sig, pub} + ) + + if err := WriteTxWitness(&buf, witnessItems); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// checkIsMultisigScript is a utility function to check whether a given +// redeemscript fits the standard multisig template used in all P2SH based +// multisig, given a set of pubkeys for redemption. +func checkIsMultiSigScript(pubKeys [][]byte, sigs [][]byte, + script []byte) bool { + + // First insist that the script type is multisig. + if txscript.GetScriptClass(script) != txscript.MultiSigTy { + return false + } + + // Inspect the script to ensure that the number of sigs and pubkeys is + // correct + _, numSigs, err := txscript.CalcMultiSigStats(script) + if err != nil { + return false + } + + // If the number of sigs provided, doesn't match the number of required + // pubkeys, then we can't proceed as we're not yet final. + if numSigs != len(pubKeys) || numSigs != len(sigs) { + return false + } + + return true +} + +// extractKeyOrderFromScript is a utility function to extract an ordered list +// of signatures, given a serialized script (redeemscript or witness script), a +// list of pubkeys and the signatures corresponding to those pubkeys. This +// function is used to ensure that the signatures will be embedded in the final +// scriptSig or scriptWitness in the correct order. +func extractKeyOrderFromScript(script []byte, expectedPubkeys [][]byte, + sigs [][]byte) ([][]byte, error) { + + // If this isn't a proper finalized multi-sig script, then we can't + // proceed. + if !checkIsMultiSigScript(expectedPubkeys, sigs, script) { + return nil, ErrUnsupportedScriptType + } + + // Arrange the pubkeys and sigs into a slice of format: + // * [[pub,sig], [pub,sig],..] + type sigWithPub struct { + pubKey []byte + sig []byte + } + var pubsSigs []sigWithPub + for i, pub := range expectedPubkeys { + pubsSigs = append(pubsSigs, sigWithPub{ + pubKey: pub, + sig: sigs[i], + }) + } + + // Now that we have the set of (pubkey, sig) pairs, we'll construct a + // position map that we can use to swap the order in the slice above to + // match how things are laid out in the script. + type positionEntry struct { + index int + value sigWithPub + } + var positionMap []positionEntry + + // For each pubkey in our pubsSigs slice, we'll now construct a proper + // positionMap entry, based on _where_ in the script the pubkey first + // appears. + for _, p := range pubsSigs { + pos := bytes.Index(script, p.pubKey) + if pos < 0 { + return nil, errors.New("script does not contain pubkeys") + } + + positionMap = append(positionMap, positionEntry{ + index: pos, + value: p, + }) + } + + // Now that we have the position map full populated, we'll use the + // index data to properly sort the entries in the map based on where + // they appear in the script. + sort.Slice(positionMap, func(i, j int) bool { + return positionMap[i].index < positionMap[j].index + }) + + // Finally, we can simply iterate through the position map in order to + // extract the proper signature ordering. + sortedSigs := make([][]byte, 0, len(positionMap)) + for _, x := range positionMap { + sortedSigs = append(sortedSigs, x.value.sig) + } + + return sortedSigs, nil +} + +// getMultisigScriptWitness creates a full psbt serialized Witness field for +// the transaction, given the public keys and signatures to be appended. This +// function will only accept witnessScripts of the type M of N multisig. This +// is used for both p2wsh and nested p2wsh multisig cases. +func getMultisigScriptWitness(witnessScript []byte, pubKeys [][]byte, + sigs [][]byte) ([]byte, error) { + + // First using the script as a guide, we'll properly order the sigs + // according to how their corresponding pubkeys appear in the + // witnessScript. + orderedSigs, err := extractKeyOrderFromScript( + witnessScript, pubKeys, sigs, + ) + if err != nil { + return nil, err + } + + // Now that we know the proper order, we'll append each of the + // signatures into a new witness stack, then top it off with the + // witness script at the end, prepending the nil as we need the extra + // pop.. + witnessElements := make(wire.TxWitness, 0, len(sigs)+2) + witnessElements = append(witnessElements, nil) + for _, os := range orderedSigs { + witnessElements = append(witnessElements, os) + } + witnessElements = append(witnessElements, witnessScript) + + // Now that we have the full witness stack, we'll serialize it in the + // expected format, and return the final bytes. + var buf bytes.Buffer + if err = WriteTxWitness(&buf, witnessElements); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// checkSigHashFlags compares the sighash flag byte on a signature with the +// value expected according to any PsbtInSighashType field in this section of +// the PSBT, and returns true if they match, false otherwise. +// If no SighashType field exists, it is assumed to be SIGHASH_ALL. +// +// TODO(waxwing): sighash type not restricted to one byte in future? +func checkSigHashFlags(sig []byte, input *PInput) bool { + expectedSighashType := txscript.SigHashAll + if input.SighashType != 0 { + expectedSighashType = input.SighashType + } + + return expectedSighashType == txscript.SigHashType(sig[len(sig)-1]) +} + +// serializeKVpair writes out a kv pair using a varbyte prefix for each. +func serializeKVpair(w io.Writer, key []byte, value []byte) error { + if err := wire.WriteVarBytes(w, 0, key); err != nil { + return err + } + + return wire.WriteVarBytes(w, 0, value) +} + +// serializeKVPairWithType writes out to the passed writer a type coupled with +// a key. +func serializeKVPairWithType(w io.Writer, kt uint8, keydata []byte, + value []byte) error { + + // If the key has no data, then we write a blank slice. + if keydata == nil { + keydata = []byte{} + } + + // The final key to be written is: {type} || {keyData} + serializedKey := append([]byte{kt}, keydata...) + return serializeKVpair(w, serializedKey, value) +} + +// getKey retrieves a single key - both the key type and the keydata (if +// present) from the stream and returns the key type as an integer, or -1 if +// the key was of zero length. This integer is is used to indicate the presence +// of a separator byte which indicates the end of a given key-value pair list, +// and the keydata as a byte slice or nil if none is present. +func getKey(r io.Reader) (int, []byte, error) { + + // For the key, we read the varint separately, instead of using the + // available ReadVarBytes, because we have a specific treatment of 0x00 + // here: + count, err := wire.ReadVarInt(r, 0) + if err != nil { + return -1, nil, ErrInvalidPsbtFormat + } + if count == 0 { + // A separator indicates end of key-value pair list. + return -1, nil, nil + } + + // Check that we don't attempt to decode a dangerously large key. + if count > MaxPsbtKeyLength { + return -1, nil, ErrInvalidKeydata + } + + // Next, we ready out the designated number of bytes, which may include + // a type, key, and optional data. + keyTypeAndData := make([]byte, count) + if _, err := io.ReadFull(r, keyTypeAndData[:]); err != nil { + return -1, nil, err + } + + keyType := int(string(keyTypeAndData)[0]) + + // Note that the second return value will usually be empty, since most + // keys contain no more than the key type byte. + if len(keyTypeAndData) == 1 { + return keyType, nil, nil + } + + // Otherwise, we return the key, along with any data that it may + // contain. + return keyType, keyTypeAndData[1:], nil + +} + +// readTxOut is a limited version of wire.ReadTxOut, because the latter is not +// exported. +func readTxOut(txout []byte) (*wire.TxOut, error) { + if len(txout) < 10 { + return nil, ErrInvalidPsbtFormat + } + + valueSer := binary.LittleEndian.Uint64(txout[:8]) + scriptPubKey := txout[9:] + + return wire.NewTxOut(int64(valueSer), scriptPubKey), nil +} + +// SumUtxoInputValues tries to extract the sum of all inputs specified in the +// UTXO fields of the PSBT. An error is returned if an input is specified that +// does not contain any UTXO information. +func SumUtxoInputValues(packet *Packet) (int64, error) { + // We take the TX ins of the unsigned TX as the truth for how many + // inputs there should be, as the fields in the extra data part of the + // PSBT can be empty. + if len(packet.UnsignedTx.TxIn) != len(packet.Inputs) { + return 0, fmt.Errorf("TX input length doesn't match PSBT " + + "input length") + } + + inputSum := int64(0) + for idx, in := range packet.Inputs { + switch { + case in.WitnessUtxo != nil: + // Witness UTXOs only need to reference the TxOut. + inputSum += in.WitnessUtxo.Value + + case in.NonWitnessUtxo != nil: + // Non-witness UTXOs reference to the whole transaction + // the UTXO resides in. + utxOuts := in.NonWitnessUtxo.TxOut + txIn := packet.UnsignedTx.TxIn[idx] + + // Check that utxOuts actually has enough space to + // contain the previous outpoint's index. + opIdx := txIn.PreviousOutPoint.Index + if opIdx >= uint32(len(utxOuts)) { + return 0, fmt.Errorf("input %d has malformed "+ + "TxOut field", idx) + } + + inputSum += utxOuts[txIn.PreviousOutPoint.Index].Value + + default: + return 0, fmt.Errorf("input %d has no UTXO information", + idx) + } + } + return inputSum, nil +} + +// TxOutsEqual returns true if two transaction outputs are equal. +func TxOutsEqual(out1, out2 *wire.TxOut) bool { + if out1 == nil || out2 == nil { + return out1 == out2 + } + return out1.Value == out2.Value && + bytes.Equal(out1.PkScript, out2.PkScript) +} + +// VerifyOutputsEqual verifies that the two slices of transaction outputs are +// deep equal to each other. We do the length check and manual loop to provide +// better error messages to the user than just returning "not equal". +func VerifyOutputsEqual(outs1, outs2 []*wire.TxOut) error { + if len(outs1) != len(outs2) { + return fmt.Errorf("number of outputs are different") + } + for idx, out := range outs1 { + // There is a byte slice in the output so we can't use the + // equality operator. + if !TxOutsEqual(out, outs2[idx]) { + return fmt.Errorf("output %d is different", idx) + } + } + return nil +} + +// VerifyInputPrevOutpointsEqual verifies that the previous outpoints of the +// two slices of transaction inputs are deep equal to each other. We do the +// length check and manual loop to provide better error messages to the user +// than just returning "not equal". +func VerifyInputPrevOutpointsEqual(ins1, ins2 []*wire.TxIn) error { + if len(ins1) != len(ins2) { + return fmt.Errorf("number of inputs are different") + } + for idx, in := range ins1 { + if in.PreviousOutPoint != ins2[idx].PreviousOutPoint { + return fmt.Errorf("previous outpoint of input %d is "+ + "different", idx) + } + } + return nil +} + +// VerifyInputOutputLen makes sure a packet is non-nil, contains a non-nil wire +// transaction and that the wire input/output lengths match the partial input/ +// output lengths. A caller also can specify if they expect any inputs and/or +// outputs to be contained in the packet. +func VerifyInputOutputLen(packet *Packet, needInputs, needOutputs bool) error { + if packet == nil || packet.UnsignedTx == nil { + return fmt.Errorf("PSBT packet cannot be nil") + } + + if len(packet.UnsignedTx.TxIn) != len(packet.Inputs) { + return fmt.Errorf("invalid PSBT, wire inputs don't match " + + "partial inputs") + } + if len(packet.UnsignedTx.TxOut) != len(packet.Outputs) { + return fmt.Errorf("invalid PSBT, wire outputs don't match " + + "partial outputs") + } + + if needInputs && len(packet.UnsignedTx.TxIn) == 0 { + return fmt.Errorf("PSBT packet must contain at least one " + + "input") + } + if needOutputs && len(packet.UnsignedTx.TxOut) == 0 { + return fmt.Errorf("PSBT packet must contain at least one " + + "output") + } + + return nil +} + +// NewFromSignedTx is a utility function to create a packet from an +// already-signed transaction. Returned are: an unsigned transaction +// serialization, a list of scriptSigs, one per input, and a list of witnesses, +// one per input. +func NewFromSignedTx(tx *wire.MsgTx) (*Packet, [][]byte, + []wire.TxWitness, error) { + + scriptSigs := make([][]byte, 0, len(tx.TxIn)) + witnesses := make([]wire.TxWitness, 0, len(tx.TxIn)) + tx2 := tx.Copy() + + // Blank out signature info in inputs + for i, tin := range tx2.TxIn { + tin.SignatureScript = nil + scriptSigs = append(scriptSigs, tx.TxIn[i].SignatureScript) + tin.Witness = nil + witnesses = append(witnesses, tx.TxIn[i].Witness) + } + + // Outputs always contain: (value, scriptPubkey) so don't need + // amending. Now tx2 is tx with all signing data stripped out + unsignedPsbt, err := NewFromUnsignedTx(tx2) + if err != nil { + return nil, nil, nil, err + } + return unsignedPsbt, scriptSigs, witnesses, nil +} diff --git a/btcutil/psbt/utils_test.go b/btcutil/psbt/utils_test.go new file mode 100644 index 0000000000..90593ffca5 --- /dev/null +++ b/btcutil/psbt/utils_test.go @@ -0,0 +1,370 @@ +package psbt + +import ( + "bytes" + "reflect" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +func TestSumUtxoInputValues(t *testing.T) { + // Expect sum to fail for packet with non-matching txIn and PInputs. + tx := wire.NewMsgTx(2) + badPacket, err := NewFromUnsignedTx(tx) + if err != nil { + t.Fatalf("could not create packet from TX: %v", err) + } + badPacket.Inputs = append(badPacket.Inputs, PInput{}) + + _, err = SumUtxoInputValues(badPacket) + if err == nil { + t.Fatalf("expected sum of bad packet to fail") + } + + // Expect sum to fail if any inputs don't have UTXO information added. + op := []*wire.OutPoint{{}, {}} + noUtxoInfoPacket, err := New(op, nil, 2, 0, []uint32{0, 0}) + if err != nil { + t.Fatalf("could not create new packet: %v", err) + } + + _, err = SumUtxoInputValues(noUtxoInfoPacket) + if err == nil { + t.Fatalf("expected sum of missing UTXO info to fail") + } + + // Create a packet that is OK and contains both witness and non-witness + // UTXO information. + okPacket, err := New(op, nil, 2, 0, []uint32{0, 0}) + if err != nil { + t.Fatalf("could not create new packet: %v", err) + } + okPacket.Inputs[0].WitnessUtxo = &wire.TxOut{Value: 1234} + okPacket.Inputs[1].NonWitnessUtxo = &wire.MsgTx{ + TxOut: []*wire.TxOut{{Value: 6543}}, + } + + sum, err := SumUtxoInputValues(okPacket) + if err != nil { + t.Fatalf("could not sum input: %v", err) + } + if sum != (1234 + 6543) { + t.Fatalf("unexpected sum, got %d wanted %d", sum, 1234+6543) + } + + // Create a malformed packet where NonWitnessUtxo.TxOut does not + // contain the index specified by the PreviousOutPoint in the + // packet's Unsigned.TxIn field. + badOp := []*wire.OutPoint{{}, {Index: 500}} + malformedPacket, err := New(badOp, nil, 2, 0, []uint32{0, 0}) + if err != nil { + t.Fatalf("could not create malformed packet: %v", err) + } + malformedPacket.Inputs[0].WitnessUtxo = &wire.TxOut{Value: 1234} + malformedPacket.Inputs[1].NonWitnessUtxo = &wire.MsgTx{ + TxOut: []*wire.TxOut{{Value: 6543}}, + } + + _, err = SumUtxoInputValues(malformedPacket) + if err == nil { + t.Fatalf("expected sum of malformed packet to fail") + } +} + +func TestTxOutsEqual(t *testing.T) { + testCases := []struct { + name string + out1 *wire.TxOut + out2 *wire.TxOut + expectEqual bool + }{{ + name: "both nil", + out1: nil, + out2: nil, + expectEqual: true, + }, { + name: "one nil", + out1: nil, + out2: &wire.TxOut{}, + expectEqual: false, + }, { + name: "both empty", + out1: &wire.TxOut{}, + out2: &wire.TxOut{}, + expectEqual: true, + }, { + name: "one pk script set", + out1: &wire.TxOut{}, + out2: &wire.TxOut{ + PkScript: []byte("foo"), + }, + expectEqual: false, + }, { + name: "both fully set", + out1: &wire.TxOut{ + Value: 1234, + PkScript: []byte("bar"), + }, + out2: &wire.TxOut{ + Value: 1234, + PkScript: []byte("bar"), + }, + expectEqual: true, + }} + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + result := TxOutsEqual(tc.out1, tc.out2) + if result != tc.expectEqual { + t.Fatalf("unexpected result, got %v wanted %v", + result, tc.expectEqual) + } + }) + } +} + +func TestVerifyOutputsEqual(t *testing.T) { + testCases := []struct { + name string + outs1 []*wire.TxOut + outs2 []*wire.TxOut + expectErr bool + }{{ + name: "both nil", + outs1: nil, + outs2: nil, + expectErr: false, + }, { + name: "one nil", + outs1: nil, + outs2: []*wire.TxOut{{}}, + expectErr: true, + }, { + name: "both empty", + outs1: []*wire.TxOut{{}}, + outs2: []*wire.TxOut{{}}, + expectErr: false, + }, { + name: "one pk script set", + outs1: []*wire.TxOut{{}}, + outs2: []*wire.TxOut{{ + PkScript: []byte("foo"), + }}, + expectErr: true, + }, { + name: "both fully set", + outs1: []*wire.TxOut{{ + Value: 1234, + PkScript: []byte("bar"), + }, {}}, + outs2: []*wire.TxOut{{ + Value: 1234, + PkScript: []byte("bar"), + }, {}}, + expectErr: false, + }} + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := VerifyOutputsEqual(tc.outs1, tc.outs2) + if (tc.expectErr && err == nil) || + (!tc.expectErr && err != nil) { + + t.Fatalf("got error '%v' but wanted it to be "+ + "nil: %v", err, tc.expectErr) + } + }) + } +} + +func TestVerifyInputPrevOutpointsEqual(t *testing.T) { + testCases := []struct { + name string + ins1 []*wire.TxIn + ins2 []*wire.TxIn + expectErr bool + }{{ + name: "both nil", + ins1: nil, + ins2: nil, + expectErr: false, + }, { + name: "one nil", + ins1: nil, + ins2: []*wire.TxIn{{}}, + expectErr: true, + }, { + name: "both empty", + ins1: []*wire.TxIn{{}}, + ins2: []*wire.TxIn{{}}, + expectErr: false, + }, { + name: "one previous output set", + ins1: []*wire.TxIn{{}}, + ins2: []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{11, 22, 33}, + Index: 7, + }, + }}, + expectErr: true, + }, { + name: "both fully set", + ins1: []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{11, 22, 33}, + Index: 7, + }, + }, {}}, + ins2: []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{ + Hash: chainhash.Hash{11, 22, 33}, + Index: 7, + }, + }, {}}, + expectErr: false, + }} + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := VerifyInputPrevOutpointsEqual(tc.ins1, tc.ins2) + if (tc.expectErr && err == nil) || + (!tc.expectErr && err != nil) { + + t.Fatalf("got error '%v' but wanted it to be "+ + "nil: %v", err, tc.expectErr) + } + }) + } +} + +func TestVerifyInputOutputLen(t *testing.T) { + testCases := []struct { + name string + packet *Packet + needInputs bool + needOutputs bool + expectErr bool + }{{ + name: "packet nil", + packet: nil, + expectErr: true, + }, { + name: "wire tx nil", + packet: &Packet{}, + expectErr: true, + }, { + name: "both empty don't need outputs", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{}, + }, + expectErr: false, + }, { + name: "both empty but need outputs", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{}, + }, + needOutputs: true, + expectErr: true, + }, { + name: "both empty but need inputs", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{}, + }, + needInputs: true, + expectErr: true, + }, { + name: "input len mismatch", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{ + TxIn: []*wire.TxIn{{}}, + }, + }, + needInputs: true, + expectErr: true, + }, { + name: "output len mismatch", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{ + TxOut: []*wire.TxOut{{}}, + }, + }, + needOutputs: true, + expectErr: true, + }, { + name: "all fully set", + packet: &Packet{ + UnsignedTx: &wire.MsgTx{ + TxIn: []*wire.TxIn{{}}, + TxOut: []*wire.TxOut{{}}, + }, + Inputs: []PInput{{}}, + Outputs: []POutput{{}}, + }, + needInputs: true, + needOutputs: true, + expectErr: false, + }} + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + err := VerifyInputOutputLen( + tc.packet, tc.needInputs, tc.needOutputs, + ) + if (tc.expectErr && err == nil) || + (!tc.expectErr && err != nil) { + + t.Fatalf("got error '%v' but wanted it to be "+ + "nil: %v", err, tc.expectErr) + } + }) + } +} + +func TestNewFromSignedTx(t *testing.T) { + orig := &wire.MsgTx{ + TxIn: []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{}, + SignatureScript: []byte("script"), + Witness: [][]byte{[]byte("witness")}, + Sequence: 1234, + }}, + TxOut: []*wire.TxOut{{ + PkScript: []byte{77, 88}, + Value: 99, + }}, + } + + packet, scripts, witnesses, err := NewFromSignedTx(orig) + if err != nil { + t.Fatalf("could not create packet from signed TX: %v", err) + } + + tx := packet.UnsignedTx + expectedTxIn := []*wire.TxIn{{ + PreviousOutPoint: wire.OutPoint{}, + Sequence: 1234, + }} + if !reflect.DeepEqual(tx.TxIn, expectedTxIn) { + t.Fatalf("unexpected txin, got %#v wanted %#v", + tx.TxIn, expectedTxIn) + } + if !reflect.DeepEqual(tx.TxOut, orig.TxOut) { + t.Fatalf("unexpected txout, got %#v wanted %#v", + tx.TxOut, orig.TxOut) + } + if len(scripts) != 1 || !bytes.Equal(scripts[0], []byte("script")) { + t.Fatalf("script not extracted correctly") + } + if len(witnesses) != 1 || + !bytes.Equal(witnesses[0][0], []byte("witness")) { + + t.Fatalf("witness not extracted correctly") + } +} diff --git a/btcutil/tx.go b/btcutil/tx.go new file mode 100644 index 0000000000..5633fef90e --- /dev/null +++ b/btcutil/tx.go @@ -0,0 +1,124 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "bytes" + "io" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// TxIndexUnknown is the value returned for a transaction index that is unknown. +// This is typically because the transaction has not been inserted into a block +// yet. +const TxIndexUnknown = -1 + +// Tx defines a bitcoin transaction that provides easier and more efficient +// manipulation of raw transactions. It also memoizes the hash for the +// transaction on its first access so subsequent accesses don't have to repeat +// the relatively expensive hashing operations. +type Tx struct { + msgTx *wire.MsgTx // Underlying MsgTx + txHash *chainhash.Hash // Cached transaction hash + txHashWitness *chainhash.Hash // Cached transaction witness hash + txHasWitness *bool // If the transaction has witness data + txIndex int // Position within a block or TxIndexUnknown +} + +// MsgTx returns the underlying wire.MsgTx for the transaction. +func (t *Tx) MsgTx() *wire.MsgTx { + // Return the cached transaction. + return t.msgTx +} + +// Hash returns the hash of the transaction. This is equivalent to +// calling TxHash on the underlying wire.MsgTx, however it caches the +// result so subsequent calls are more efficient. +func (t *Tx) Hash() *chainhash.Hash { + // Return the cached hash if it has already been generated. + if t.txHash != nil { + return t.txHash + } + + // Cache the hash and return it. + hash := t.msgTx.TxHash() + t.txHash = &hash + return &hash +} + +// WitnessHash returns the witness hash (wtxid) of the transaction. This is +// equivalent to calling WitnessHash on the underlying wire.MsgTx, however it +// caches the result so subsequent calls are more efficient. +func (t *Tx) WitnessHash() *chainhash.Hash { + // Return the cached hash if it has already been generated. + if t.txHashWitness != nil { + return t.txHashWitness + } + + // Cache the hash and return it. + hash := t.msgTx.WitnessHash() + t.txHashWitness = &hash + return &hash +} + +// HasWitness returns false if none of the inputs within the transaction +// contain witness data, true false otherwise. This equivalent to calling +// HasWitness on the underlying wire.MsgTx, however it caches the result so +// subsequent calls are more efficient. +func (t *Tx) HasWitness() bool { + if t.txHasWitness != nil { + return *t.txHasWitness + } + + hasWitness := t.msgTx.HasWitness() + t.txHasWitness = &hasWitness + return hasWitness +} + +// Index returns the saved index of the transaction within a block. This value +// will be TxIndexUnknown if it hasn't already explicitly been set. +func (t *Tx) Index() int { + return t.txIndex +} + +// SetIndex sets the index of the transaction in within a block. +func (t *Tx) SetIndex(index int) { + t.txIndex = index +} + +// NewTx returns a new instance of a bitcoin transaction given an underlying +// wire.MsgTx. See Tx. +func NewTx(msgTx *wire.MsgTx) *Tx { + return &Tx{ + msgTx: msgTx, + txIndex: TxIndexUnknown, + } +} + +// NewTxFromBytes returns a new instance of a bitcoin transaction given the +// serialized bytes. See Tx. +func NewTxFromBytes(serializedTx []byte) (*Tx, error) { + br := bytes.NewReader(serializedTx) + return NewTxFromReader(br) +} + +// NewTxFromReader returns a new instance of a bitcoin transaction given a +// Reader to deserialize the transaction. See Tx. +func NewTxFromReader(r io.Reader) (*Tx, error) { + // Deserialize the bytes into a MsgTx. + var msgTx wire.MsgTx + err := msgTx.Deserialize(r) + if err != nil { + return nil, err + } + + t := Tx{ + msgTx: &msgTx, + txIndex: TxIndexUnknown, + } + return &t, nil +} diff --git a/btcutil/tx_test.go b/btcutil/tx_test.go new file mode 100644 index 0000000000..828fc065b1 --- /dev/null +++ b/btcutil/tx_test.go @@ -0,0 +1,136 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil_test + +import ( + "bytes" + "io" + "reflect" + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/btcutil" + "github.com/davecgh/go-spew/spew" +) + +// TestTx tests the API for Tx. +func TestTx(t *testing.T) { + testTx := Block100000.Transactions[0] + tx := btcutil.NewTx(testTx) + + // Ensure we get the same data back out. + if msgTx := tx.MsgTx(); !reflect.DeepEqual(msgTx, testTx) { + t.Errorf("MsgTx: mismatched MsgTx - got %v, want %v", + spew.Sdump(msgTx), spew.Sdump(testTx)) + } + + // Ensure transaction index set and get work properly. + wantIndex := 0 + tx.SetIndex(0) + if gotIndex := tx.Index(); gotIndex != wantIndex { + t.Errorf("Index: mismatched index - got %v, want %v", + gotIndex, wantIndex) + } + + // Hash for block 100,000 transaction 0. + wantHashStr := "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87" + wantHash, err := chainhash.NewHashFromStr(wantHashStr) + if err != nil { + t.Errorf("NewHashFromStr: %v", err) + } + + // Request the hash multiple times to test generation and caching. + for i := 0; i < 2; i++ { + hash := tx.Hash() + if !hash.IsEqual(wantHash) { + t.Errorf("Hash #%d mismatched hash - got %v, want %v", i, + hash, wantHash) + } + } +} + +// TestNewTxFromBytes tests creation of a Tx from serialized bytes. +func TestNewTxFromBytes(t *testing.T) { + // Serialize the test transaction. + testTx := Block100000.Transactions[0] + var testTxBuf bytes.Buffer + err := testTx.Serialize(&testTxBuf) + if err != nil { + t.Errorf("Serialize: %v", err) + } + testTxBytes := testTxBuf.Bytes() + + // Create a new transaction from the serialized bytes. + tx, err := btcutil.NewTxFromBytes(testTxBytes) + if err != nil { + t.Errorf("NewTxFromBytes: %v", err) + return + } + + // Ensure the generated MsgTx is correct. + if msgTx := tx.MsgTx(); !reflect.DeepEqual(msgTx, testTx) { + t.Errorf("MsgTx: mismatched MsgTx - got %v, want %v", + spew.Sdump(msgTx), spew.Sdump(testTx)) + } +} + +// TestTxErrors tests the error paths for the Tx API. +func TestTxErrors(t *testing.T) { + // Serialize the test transaction. + testTx := Block100000.Transactions[0] + var testTxBuf bytes.Buffer + err := testTx.Serialize(&testTxBuf) + if err != nil { + t.Errorf("Serialize: %v", err) + } + testTxBytes := testTxBuf.Bytes() + + // Truncate the transaction byte buffer to force errors. + shortBytes := testTxBytes[:4] + _, err = btcutil.NewTxFromBytes(shortBytes) + if err != io.EOF { + t.Errorf("NewTxFromBytes: did not get expected error - "+ + "got %v, want %v", err, io.EOF) + } +} + +// TestTxHasWitness tests the HasWitness() method. +func TestTxHasWitness(t *testing.T) { + msgTx := Block100000.Transactions[0] // contains witness data + tx := btcutil.NewTx(msgTx) + + tx.WitnessHash() // Populate the witness hash cache + tx.HasWitness() // Should not fail (see btcsuite/btcd#1543) + + if !tx.HasWitness() { + t.Errorf("HasWitness: got false, want true") + } + + for _, msgTxWithoutWitness := range Block100000.Transactions[1:] { + txWithoutWitness := btcutil.NewTx(msgTxWithoutWitness) + if txWithoutWitness.HasWitness() { + t.Errorf("HasWitness: got false, want true") + } + } +} + +// TestTxWitnessHash tests the WitnessHash() method. +func TestTxWitnessHash(t *testing.T) { + msgTx := Block100000.Transactions[0] // contains witness data + tx := btcutil.NewTx(msgTx) + + if tx.WitnessHash().IsEqual(tx.Hash()) { + t.Errorf("WitnessHash: witness hash and tx id must NOT be same - "+ + "got %v, want %v", tx.WitnessHash(), tx.Hash()) + } + + for _, msgTxWithoutWitness := range Block100000.Transactions[1:] { + txWithoutWitness := btcutil.NewTx(msgTxWithoutWitness) + if !txWithoutWitness.WitnessHash().IsEqual(txWithoutWitness.Hash()) { + t.Errorf("WitnessHash: witness hash and tx id must be same - "+ + "got %v, want %v", txWithoutWitness.WitnessHash(), txWithoutWitness.Hash()) + } + } +} diff --git a/btcutil/txsort/README.md b/btcutil/txsort/README.md new file mode 100644 index 0000000000..cb8e4130d1 --- /dev/null +++ b/btcutil/txsort/README.md @@ -0,0 +1,31 @@ +txsort +====== + +[![Build Status](http://img.shields.io/travis/btcsuite/btcutil.svg)](https://travis-ci.org/btcsuite/btcutil) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](http://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/btcutil/txsort) + +Package txsort provides the transaction sorting according to [BIP 69](https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki). + +BIP 69 defines a standard lexicographical sort order of transaction inputs and +outputs. This is useful to standardize transactions for faster multi-party +agreement as well as preventing information leaks in a single-party use case. + +The BIP goes into more detail, but for a quick and simplistic overview, the +order for inputs is defined as first sorting on the previous output hash and +then on the index as a tie breaker. The order for outputs is defined as first +sorting on the amount and then on the raw public key script bytes as a tie +breaker. + +A comprehensive suite of tests is provided to ensure proper functionality. + +## Installation and Updating + +```bash +$ go get -u github.com/btcsuite/btcd/btcutil/txsort +``` + +## License + +Package txsort is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/btcutil/txsort/doc.go b/btcutil/txsort/doc.go new file mode 100644 index 0000000000..e89c4d23d3 --- /dev/null +++ b/btcutil/txsort/doc.go @@ -0,0 +1,20 @@ +// Copyright (c) 2015 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +/* +Package txsort provides the transaction sorting according to BIP 69. + +Overview + +BIP 69 defines a standard lexicographical sort order of transaction inputs and +outputs. This is useful to standardize transactions for faster multi-party +agreement as well as preventing information leaks in a single-party use case. + +The BIP goes into more detail, but for a quick and simplistic overview, the +order for inputs is defined as first sorting on the previous output hash and +then on the index as a tie breaker. The order for outputs is defined as first +sorting on the amount and then on the raw public key script bytes as a tie +breaker. +*/ +package txsort diff --git a/btcutil/txsort/testdata/bip69-1.hex b/btcutil/txsort/testdata/bip69-1.hex new file mode 100644 index 0000000000..dbd18422b7 --- /dev/null +++ b/btcutil/txsort/testdata/bip69-1.hex @@ -0,0 +1 @@ +0100000011aad553bb1650007e9982a8ac79d227cd8c831e1573b11f25573a37664e5f3e64000000006a47304402205438cedd30ee828b0938a863e08d810526123746c1f4abee5b7bc2312373450c02207f26914f4275f8f0040ab3375bacc8c5d610c095db8ed0785de5dc57456591a601210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffc26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f5485d1fde028000000006b483045022100f81d98c1de9bb61063a5e6671d191b400fda3a07d886e663799760393405439d0220234303c9af4bad3d665f00277fe70cdd26cd56679f114a40d9107249d29c979401210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff456a9e597129f5df2e11b842833fc19a94c563f57449281d3cd01249a830a1f0000000006a47304402202310b00924794ef68a8f09564fd0bb128838c66bc45d1a3f95c5cab52680f166022039fc99138c29f6c434012b14aca651b1c02d97324d6bd9dd0ffced0782c7e3bd01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff571fb3e02278217852dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e000000006b483045022100d276251f1f4479d8521269ec8b1b45c6f0e779fcf1658ec627689fa8a55a9ca50220212a1e307e6182479818c543e1b47d62e4fc3ce6cc7fc78183c7071d245839df01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff5d8de50362ff33d3526ac3602e9ee25c1a349def086a7fc1d9941aaeb9e91d38010000006b4830450221008768eeb1240451c127b88d89047dd387d13357ce5496726fc7813edc6acd55ac022015187451c3fb66629af38fdb061dfb39899244b15c45e4a7ccc31064a059730d01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff60ad3408b89ea19caf3abd5e74e7a084344987c64b1563af52242e9d2a8320f3000000006b4830450221009be4261ec050ebf33fa3d47248c7086e4c247cafbb100ea7cee4aa81cd1383f5022008a70d6402b153560096c849d7da6fe61c771a60e41ff457aac30673ceceafee01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffe9b483a8ac4129780c88d1babe41e89dc10a26dedbf14f80a28474e9a11104de010000006b4830450221009bc40eee321b39b5dc26883f79cd1f5a226fc6eed9e79e21d828f4c23190c57e022078182fd6086e265589105023d9efa4cba83f38c674a499481bd54eee196b033f01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffe28db9462d3004e21e765e03a45ecb147f136a20ba8bca78ba60ebfc8e2f8b3b000000006a47304402200fb572b7c6916515452e370c2b6f97fcae54abe0793d804a5a53e419983fae1602205191984b6928bf4a1e25b00e5b5569a0ce1ecb82db2dea75fe4378673b53b9e801210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff7a1ef65ff1b7b7740c662ab6c9735ace4a16279c23a1db5709ed652918ffff54010000006a47304402206bc218a925f7280d615c8ea4f0131a9f26e7fc64cff6eeeb44edb88aba14f1910220779d5d67231bc2d2d93c3c5ab74dcd193dd3d04023e58709ad7ffbf95161be6201210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff850cecf958468ca7ffa6a490afe13b8c271b1326b0ddc1fdfdf9f3c7e365fdba000000006a473044022047df98cc26bd2bfdc5b2b97c27aead78a214810ff023e721339292d5ce50823d02205fe99dc5f667908974dae40cc7a9475af7fa6671ba44f64a00fcd01fa12ab523012102ca46fa75454650afba1784bc7b079d687e808634411e4beff1f70e44596308a1ffffffff8640e312040e476cf6727c60ca3f4a3ad51623500aacdda96e7728dbdd99e8a5000000006a47304402205566aa84d3d84226d5ab93e6f253b57b3ef37eb09bb73441dae35de86271352a02206ee0b7f800f73695a2073a2967c9ad99e19f6ddf18ce877adf822e408ba9291e01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff91c1889c5c24b93b56e643121f7a05a34c10c5495c450504c7b5afcb37e11d7a000000006b483045022100df61d45bbaa4571cdd6c5c822cba458cdc55285cdf7ba9cd5bb9fc18096deb9102201caf8c771204df7fd7c920c4489da7bc3a60e1d23c1a97e237c63afe53250b4a01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff2470947216eb81ea0eeeb4fe19362ec05767db01c3aa3006bb499e8b6d6eaa26010000006a473044022031501a0b2846b8822a32b9947b058d89d32fc758e009fc2130c2e5effc925af70220574ef3c9e350cef726c75114f0701fd8b188c6ec5f84adce0ed5c393828a5ae001210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff0abcd77d65cc14363f8262898335f184d6da5ad060ff9e40bf201741022c2b40010000006b483045022100a6ac110802b699f9a2bff0eea252d32e3d572b19214d49d8bb7405efa2af28f1022033b7563eb595f6d7ed7ec01734e17b505214fe0851352ed9c3c8120d53268e9a01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffa43bebbebf07452a893a95bfea1d5db338d23579be172fe803dce02eeb7c037d010000006b483045022100ebc77ed0f11d15fe630fe533dc350c2ddc1c81cfeb81d5a27d0587163f58a28c02200983b2a32a1014bab633bfc9258083ac282b79566b6b3fa45c1e6758610444f401210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffb102113fa46ce949616d9cda00f6b10231336b3928eaaac6bfe42d1bf3561d6c010000006a473044022010f8731929a55c1c49610722e965635529ed895b2292d781b183d465799906b20220098359adcbc669cd4b294cc129b110fe035d2f76517248f4b7129f3bf793d07f01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffffb861fab2cde188499758346be46b5fbec635addfc4e7b0c8a07c0a908f2b11b4000000006a47304402207328142bb02ef5d6496a210300f4aea71f67683b842fa3df32cae6c88b49a9bb022020f56ddff5042260cfda2c9f39b7dec858cc2f4a76a987cd2dc25945b04e15fe01210391064d5b2d1c70f264969046fcff853a7e2bfde5d121d38dc5ebd7bc37c2b210ffffffff027064d817000000001976a9144a5fba237213a062f6f57978f796390bdcf8d01588ac00902f50090000001976a9145be32612930b8323add2212a4ec03c1562084f8488ac00000000 \ No newline at end of file diff --git a/btcutil/txsort/testdata/bip69-2.hex b/btcutil/txsort/testdata/bip69-2.hex new file mode 100644 index 0000000000..c42d0d2dc1 --- /dev/null +++ b/btcutil/txsort/testdata/bip69-2.hex @@ -0,0 +1 @@ +010000000255605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d28350000000049483045022100aa46504baa86df8a33b1192b1b9367b4d729dc41e389f2c04f3e5c7f0559aae702205e82253a54bf5c4f65b7428551554b2045167d6d206dfe6a2e198127d3f7df1501ffffffff55605dc6f5c3dc148b6da58442b0b2cd422be385eab2ebea4119ee9c268d2835010000004847304402202329484c35fa9d6bb32a55a70c0982f606ce0e3634b69006138683bcd12cbb6602200c28feb1e2555c3210f1dddb299738b4ff8bbe9667b68cb8764b5ac17b7adf0001ffffffff0200e1f505000000004341046a0765b5865641ce08dd39690aade26dfbf5511430ca428a3089261361cef170e3929a68aee3d8d4848b0c5111b0a37b82b86ad559fd2a745b44d8e8d9dfdc0cac00180d8f000000004341044a656f065871a353f216ca26cef8dde2f03e8c16202d2e8ad769f02032cb86a5eb5e56842e92e19141d60a01928f8dd2c875a390f67c1f6c94cfc617c0ea45afac00000000 \ No newline at end of file diff --git a/btcutil/txsort/testdata/bip69-3.hex b/btcutil/txsort/testdata/bip69-3.hex new file mode 100644 index 0000000000..6fd859a9cf --- /dev/null +++ b/btcutil/txsort/testdata/bip69-3.hex @@ -0,0 +1 @@ +0100000001d992e5a888a86d4c7a6a69167a4728ee69497509740fc5f456a24528c340219a000000008b483045022100f0519bdc9282ff476da1323b8ef7ffe33f495c1a8d52cc522b437022d83f6a230220159b61d197fbae01b4a66622a23bc3f1def65d5fa24efd5c26fa872f3a246b8e014104839f9023296a1fabb133140128ca2709f6818c7d099491690bd8ac0fd55279def6a2ceb6ab7b5e4a71889b6e739f09509565eec789e86886f6f936fa42097adeffffffff02000fe208010000001976a914948c765a6914d43f2a7ac177da2c2f6b52de3d7c88ac00e32321000000001976a9140c34f4e29ab5a615d5ea28d4817f12b137d62ed588ac00000000 \ No newline at end of file diff --git a/btcutil/txsort/testdata/bip69-4.hex b/btcutil/txsort/testdata/bip69-4.hex new file mode 100644 index 0000000000..f41d23f8b2 --- /dev/null +++ b/btcutil/txsort/testdata/bip69-4.hex @@ -0,0 +1 @@ +01000000059daf0abe7a92618546a9dbcfd65869b6178c66ec21ccfda878c1175979cfd9ef000000004a493046022100c2f7f25be5de6ce88ac3c1a519514379e91f39b31ddff279a3db0b1a229b708b022100b29efbdbd9837cc6a6c7318aa4900ed7e4d65662c34d1622a2035a3a5534a99a01ffffffffd516330ebdf075948da56db13d22632a4fb941122df2884397dda45d451acefb0000000048473044022051243debe6d4f2b433bee0cee78c5c4073ead0e3bde54296dbed6176e128659c022044417bfe16f44eb7b6eb0cdf077b9ce972a332e15395c09ca5e4f602958d266101ffffffffe1f5aa33961227b3c344e57179417ce01b7ccd421117fe2336289b70489883f900000000484730440220593252bb992ce3c85baf28d6e3aa32065816271d2c822398fe7ee28a856bc943022066d429dd5025d3c86fd8fd8a58e183a844bd94aa312cefe00388f57c85b0ca3201ffffffffe207e83718129505e6a7484831442f668164ae659fddb82e9e5421a081fb90d50000000049483045022067cf27eb733e5bcae412a586b25a74417c237161a084167c2a0b439abfebdcb2022100efcc6baa6824b4c5205aa967e0b76d31abf89e738d4b6b014e788c9a8cccaf0c01ffffffffe23b8d9d80a9e9d977fab3c94dbe37befee63822443c3ec5ae5a713ede66c3940000000049483045022020f2eb35036666b1debe0d1d2e77a36d5d9c4e96c1dba23f5100f193dbf524790221008ce79bc1321fb4357c6daee818038d41544749127751726e46b2b320c8b565a201ffffffff0200ba1dd2050000001976a914366a27645806e817a6cd40bc869bdad92fe5509188ac40420f00000000001976a914ee8bd501094a7d5ca318da2506de35e1cb025ddc88ac00000000 \ No newline at end of file diff --git a/btcutil/txsort/testdata/bip69-5.hex b/btcutil/txsort/testdata/bip69-5.hex new file mode 100644 index 0000000000..e1cb4d6131 --- /dev/null +++ b/btcutil/txsort/testdata/bip69-5.hex @@ -0,0 +1 @@ +01000000011f636d0003f673b3aeea4971daef16b8eed784cf6e8019a5ae7da4985fbb06e5000000008a47304402205103941e2b11e746dfa817888d422f6e7f4d16dbbfb8ffa61d15ffb924a84b8802202fe861b0f23f17139d15a3374bfc6c7196d371f3d1a324e31cc0aadbba87e53c0141049e7e1b251a7e26cae9ee7553b278ef58ef3c28b4b20134d51b747d9b18b0a19b94b66cef320e2549dec0ea3d725cb4c742f368928b1fb74b4603e24a1e262c80ffffffff0240420f00000000001976a914bcfa0e27218a7c97257b351b03a9eac95c25a23988ac40420f00000000001976a9140c6a68f20bafc678164d171ee4f077adfa9b091688ac00000000 \ No newline at end of file diff --git a/btcutil/txsort/txsort.go b/btcutil/txsort/txsort.go new file mode 100644 index 0000000000..f72a7db970 --- /dev/null +++ b/btcutil/txsort/txsort.go @@ -0,0 +1,95 @@ +// Copyright (c) 2015-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// Provides functions for sorting tx inputs and outputs according to BIP 69 +// (https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki) + +package txsort + +import ( + "bytes" + "sort" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// InPlaceSort modifies the passed transaction inputs and outputs to be sorted +// based on BIP 69. +// +// WARNING: This function must NOT be called with published transactions since +// it will mutate the transaction if it's not already sorted. This can cause +// issues if you mutate a tx in a block, for example, which would invalidate the +// block. It could also cause cached hashes, such as in a btcutil.Tx to become +// invalidated. +// +// The function should only be used if the caller is creating the transaction or +// is otherwise 100% positive mutating will not cause adverse affects due to +// other dependencies. +func InPlaceSort(tx *wire.MsgTx) { + sort.Sort(sortableInputSlice(tx.TxIn)) + sort.Sort(sortableOutputSlice(tx.TxOut)) +} + +// Sort returns a new transaction with the inputs and outputs sorted based on +// BIP 69. The passed transaction is not modified and the new transaction +// might have a different hash if any sorting was done. +func Sort(tx *wire.MsgTx) *wire.MsgTx { + txCopy := tx.Copy() + sort.Sort(sortableInputSlice(txCopy.TxIn)) + sort.Sort(sortableOutputSlice(txCopy.TxOut)) + return txCopy +} + +// IsSorted checks whether tx has inputs and outputs sorted according to BIP +// 69. +func IsSorted(tx *wire.MsgTx) bool { + if !sort.IsSorted(sortableInputSlice(tx.TxIn)) { + return false + } + if !sort.IsSorted(sortableOutputSlice(tx.TxOut)) { + return false + } + return true +} + +type sortableInputSlice []*wire.TxIn +type sortableOutputSlice []*wire.TxOut + +// For SortableInputSlice and SortableOutputSlice, three functions are needed +// to make it sortable with sort.Sort() -- Len, Less, and Swap +// Len and Swap are trivial. Less is BIP 69 specific. +func (s sortableInputSlice) Len() int { return len(s) } +func (s sortableOutputSlice) Len() int { return len(s) } +func (s sortableOutputSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s sortableInputSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// Input comparison function. +// First sort based on input hash (reversed / rpc-style), then index. +func (s sortableInputSlice) Less(i, j int) bool { + // Input hashes are the same, so compare the index. + ihash := s[i].PreviousOutPoint.Hash + jhash := s[j].PreviousOutPoint.Hash + if ihash == jhash { + return s[i].PreviousOutPoint.Index < s[j].PreviousOutPoint.Index + } + + // At this point, the hashes are not equal, so reverse them to + // big-endian and return the result of the comparison. + const hashSize = chainhash.HashSize + for b := 0; b < hashSize/2; b++ { + ihash[b], ihash[hashSize-1-b] = ihash[hashSize-1-b], ihash[b] + jhash[b], jhash[hashSize-1-b] = jhash[hashSize-1-b], jhash[b] + } + return bytes.Compare(ihash[:], jhash[:]) == -1 +} + +// Output comparison function. +// First sort based on amount (smallest first), then PkScript. +func (s sortableOutputSlice) Less(i, j int) bool { + if s[i].Value == s[j].Value { + return bytes.Compare(s[i].PkScript, s[j].PkScript) < 0 + } + return s[i].Value < s[j].Value +} diff --git a/btcutil/txsort/txsort_test.go b/btcutil/txsort/txsort_test.go new file mode 100644 index 0000000000..7d5c2d3eaf --- /dev/null +++ b/btcutil/txsort/txsort_test.go @@ -0,0 +1,124 @@ +// Copyright (c) 2015-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txsort_test + +import ( + "bytes" + "encoding/hex" + "io/ioutil" + "path/filepath" + "testing" + + "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/btcutil/txsort" +) + +// TestSort ensures the transaction sorting works according to the BIP. +func TestSort(t *testing.T) { + tests := []struct { + name string + hexFile string + isSorted bool + unsortedHash string + sortedHash string + }{ + { + name: "first test case from BIP 69 - sorts inputs only, based on hash", + hexFile: "bip69-1.hex", + isSorted: false, + unsortedHash: "0a6a357e2f7796444e02638749d9611c008b253fb55f5dc88b739b230ed0c4c3", + sortedHash: "839503cb611a3e3734bd521c608f881be2293ff77b7384057ab994c794fce623", + }, + { + name: "second test case from BIP 69 - already sorted", + hexFile: "bip69-2.hex", + isSorted: true, + unsortedHash: "28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f", + sortedHash: "28204cad1d7fc1d199e8ef4fa22f182de6258a3eaafe1bbe56ebdcacd3069a5f", + }, + { + name: "block 100001 tx[1] - sorts outputs only, based on amount", + hexFile: "bip69-3.hex", + isSorted: false, + unsortedHash: "fbde5d03b027d2b9ba4cf5d4fecab9a99864df2637b25ea4cbcb1796ff6550ca", + sortedHash: "0a8c246c55f6b82f094d211f4f57167bf2ea4898741d218b09bdb2536fd8d13f", + }, + { + name: "block 100001 tx[2] - sorts both inputs and outputs", + hexFile: "bip69-4.hex", + isSorted: false, + unsortedHash: "8131ffb0a2c945ecaf9b9063e59558784f9c3a74741ce6ae2a18d0571dac15bb", + sortedHash: "a3196553b928b0b6154b002fa9a1ce875adabc486fedaaaf4c17430fd4486329", + }, + { + name: "block 100998 tx[6] - sorts outputs only, based on output script", + hexFile: "bip69-5.hex", + isSorted: false, + unsortedHash: "ff85e8fc92e71bbc217e3ea9a3bacb86b435e52b6df0b089d67302c293a2b81d", + sortedHash: "9a6c24746de024f77cac9b2138694f11101d1c66289261224ca52a25155a7c94", + }, + } + + for _, test := range tests { + // Load and deserialize the test transaction. + filePath := filepath.Join("testdata", test.hexFile) + txHexBytes, err := ioutil.ReadFile(filePath) + if err != nil { + t.Errorf("ReadFile (%s): failed to read test file: %v", + test.name, err) + continue + } + txBytes, err := hex.DecodeString(string(txHexBytes)) + if err != nil { + t.Errorf("DecodeString (%s): failed to decode tx: %v", + test.name, err) + continue + } + var tx wire.MsgTx + err = tx.Deserialize(bytes.NewReader(txBytes)) + if err != nil { + t.Errorf("Deserialize (%s): unexpected error %v", + test.name, err) + continue + } + + // Ensure the sort order of the original transaction matches the + // expected value. + if got := txsort.IsSorted(&tx); got != test.isSorted { + t.Errorf("IsSorted (%s): sort does not match "+ + "expected - got %v, want %v", test.name, got, + test.isSorted) + continue + } + + // Sort the transaction and ensure the resulting hash is the + // expected value. + sortedTx := txsort.Sort(&tx) + if got := sortedTx.TxHash().String(); got != test.sortedHash { + t.Errorf("Sort (%s): sorted hash does not match "+ + "expected - got %v, want %v", test.name, got, + test.sortedHash) + continue + } + + // Ensure the original transaction is not modified. + if got := tx.TxHash().String(); got != test.unsortedHash { + t.Errorf("Sort (%s): unsorted hash does not match "+ + "expected - got %v, want %v", test.name, got, + test.unsortedHash) + continue + } + + // Now sort the transaction using the mutable version and ensure + // the resulting hash is the expected value. + txsort.InPlaceSort(&tx) + if got := tx.TxHash().String(); got != test.sortedHash { + t.Errorf("SortMutate (%s): sorted hash does not match "+ + "expected - got %v, want %v", test.name, got, + test.sortedHash) + continue + } + } +} diff --git a/btcutil/wif.go b/btcutil/wif.go new file mode 100644 index 0000000000..e727a0c44a --- /dev/null +++ b/btcutil/wif.go @@ -0,0 +1,169 @@ +// Copyright (c) 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil + +import ( + "bytes" + "errors" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/btcutil/base58" +) + +// ErrMalformedPrivateKey describes an error where a WIF-encoded private +// key cannot be decoded due to being improperly formatted. This may occur +// if the byte length is incorrect or an unexpected magic number was +// encountered. +var ErrMalformedPrivateKey = errors.New("malformed private key") + +// compressMagic is the magic byte used to identify a WIF encoding for +// an address created from a compressed serialized public key. +const compressMagic byte = 0x01 + +// WIF contains the individual components described by the Wallet Import Format +// (WIF). A WIF string is typically used to represent a private key and its +// associated address in a way that may be easily copied and imported into or +// exported from wallet software. WIF strings may be decoded into this +// structure by calling DecodeWIF or created with a user-provided private key +// by calling NewWIF. +type WIF struct { + // PrivKey is the private key being imported or exported. + PrivKey *btcec.PrivateKey + + // CompressPubKey specifies whether the address controlled by the + // imported or exported private key was created by hashing a + // compressed (33-byte) serialized public key, rather than an + // uncompressed (65-byte) one. + CompressPubKey bool + + // netID is the bitcoin network identifier byte used when + // WIF encoding the private key. + netID byte +} + +// NewWIF creates a new WIF structure to export an address and its private key +// as a string encoded in the Wallet Import Format. The compress argument +// specifies whether the address intended to be imported or exported was created +// by serializing the public key compressed rather than uncompressed. +func NewWIF(privKey *btcec.PrivateKey, net *chaincfg.Params, compress bool) (*WIF, error) { + if net == nil { + return nil, errors.New("no network") + } + return &WIF{privKey, compress, net.PrivateKeyID}, nil +} + +// IsForNet returns whether or not the decoded WIF structure is associated +// with the passed bitcoin network. +func (w *WIF) IsForNet(net *chaincfg.Params) bool { + return w.netID == net.PrivateKeyID +} + +// DecodeWIF creates a new WIF structure by decoding the string encoding of +// the import format. +// +// The WIF string must be a base58-encoded string of the following byte +// sequence: +// +// * 1 byte to identify the network, must be 0x80 for mainnet or 0xef for +// either testnet3 or the regression test network +// * 32 bytes of a binary-encoded, big-endian, zero-padded private key +// * Optional 1 byte (equal to 0x01) if the address being imported or exported +// was created by taking the RIPEMD160 after SHA256 hash of a serialized +// compressed (33-byte) public key +// * 4 bytes of checksum, must equal the first four bytes of the double SHA256 +// of every byte before the checksum in this sequence +// +// If the base58-decoded byte sequence does not match this, DecodeWIF will +// return a non-nil error. ErrMalformedPrivateKey is returned when the WIF +// is of an impossible length or the expected compressed pubkey magic number +// does not equal the expected value of 0x01. ErrChecksumMismatch is returned +// if the expected WIF checksum does not match the calculated checksum. +func DecodeWIF(wif string) (*WIF, error) { + decoded := base58.Decode(wif) + decodedLen := len(decoded) + var compress bool + + // Length of base58 decoded WIF must be 32 bytes + an optional 1 byte + // (0x01) if compressed, plus 1 byte for netID + 4 bytes of checksum. + switch decodedLen { + case 1 + btcec.PrivKeyBytesLen + 1 + 4: + if decoded[33] != compressMagic { + return nil, ErrMalformedPrivateKey + } + compress = true + case 1 + btcec.PrivKeyBytesLen + 4: + compress = false + default: + return nil, ErrMalformedPrivateKey + } + + // Checksum is first four bytes of double SHA256 of the identifier byte + // and privKey. Verify this matches the final 4 bytes of the decoded + // private key. + var tosum []byte + if compress { + tosum = decoded[:1+btcec.PrivKeyBytesLen+1] + } else { + tosum = decoded[:1+btcec.PrivKeyBytesLen] + } + cksum := chainhash.DoubleHashB(tosum)[:4] + if !bytes.Equal(cksum, decoded[decodedLen-4:]) { + return nil, ErrChecksumMismatch + } + + netID := decoded[0] + privKeyBytes := decoded[1 : 1+btcec.PrivKeyBytesLen] + privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) + return &WIF{privKey, compress, netID}, nil +} + +// String creates the Wallet Import Format string encoding of a WIF structure. +// See DecodeWIF for a detailed breakdown of the format and requirements of +// a valid WIF string. +func (w *WIF) String() string { + // Precalculate size. Maximum number of bytes before base58 encoding + // is one byte for the network, 32 bytes of private key, possibly one + // extra byte if the pubkey is to be compressed, and finally four + // bytes of checksum. + encodeLen := 1 + btcec.PrivKeyBytesLen + 4 + if w.CompressPubKey { + encodeLen++ + } + + a := make([]byte, 0, encodeLen) + a = append(a, w.netID) + // Pad and append bytes manually, instead of using Serialize, to + // avoid another call to make. + a = paddedAppend(btcec.PrivKeyBytesLen, a, w.PrivKey.D.Bytes()) + if w.CompressPubKey { + a = append(a, compressMagic) + } + cksum := chainhash.DoubleHashB(a)[:4] + a = append(a, cksum...) + return base58.Encode(a) +} + +// SerializePubKey serializes the associated public key of the imported or +// exported private key in either a compressed or uncompressed format. The +// serialization format chosen depends on the value of w.CompressPubKey. +func (w *WIF) SerializePubKey() []byte { + pk := (*btcec.PublicKey)(&w.PrivKey.PublicKey) + if w.CompressPubKey { + return pk.SerializeCompressed() + } + return pk.SerializeUncompressed() +} + +// paddedAppend appends the src byte slice to dst, returning the new slice. +// If the length of the source is smaller than the passed size, leading zero +// bytes are appended to the dst slice before appending src. +func paddedAppend(size uint, dst, src []byte) []byte { + for i := 0; i < int(size)-len(src); i++ { + dst = append(dst, 0) + } + return append(dst, src...) +} diff --git a/btcutil/wif_test.go b/btcutil/wif_test.go new file mode 100644 index 0000000000..1c21b4871b --- /dev/null +++ b/btcutil/wif_test.go @@ -0,0 +1,160 @@ +// Copyright (c) 2013 - 2020 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcutil_test + +import ( + "bytes" + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/chaincfg" + . "github.com/btcsuite/btcd/btcutil" +) + +func TestEncodeDecodeWIF(t *testing.T) { + validEncodeCases := []struct { + privateKey []byte // input + net *chaincfg.Params // input + compress bool // input + wif string // output + publicKey []byte // output + name string // name of subtest + }{ + { + privateKey: []byte{ + 0x0c, 0x28, 0xfc, 0xa3, 0x86, 0xc7, 0xa2, 0x27, + 0x60, 0x0b, 0x2f, 0xe5, 0x0b, 0x7c, 0xae, 0x11, + 0xec, 0x86, 0xd3, 0xbf, 0x1f, 0xbe, 0x47, 0x1b, + 0xe8, 0x98, 0x27, 0xe1, 0x9d, 0x72, 0xaa, 0x1d}, + net: &chaincfg.MainNetParams, + compress: false, + wif: "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ", + publicKey: []byte{ + 0x04, 0xd0, 0xde, 0x0a, 0xae, 0xae, 0xfa, 0xd0, + 0x2b, 0x8b, 0xdc, 0x8a, 0x01, 0xa1, 0xb8, 0xb1, + 0x1c, 0x69, 0x6b, 0xd3, 0xd6, 0x6a, 0x2c, 0x5f, + 0x10, 0x78, 0x0d, 0x95, 0xb7, 0xdf, 0x42, 0x64, + 0x5c, 0xd8, 0x52, 0x28, 0xa6, 0xfb, 0x29, 0x94, + 0x0e, 0x85, 0x8e, 0x7e, 0x55, 0x84, 0x2a, 0xe2, + 0xbd, 0x11, 0x5d, 0x1e, 0xd7, 0xcc, 0x0e, 0x82, + 0xd9, 0x34, 0xe9, 0x29, 0xc9, 0x76, 0x48, 0xcb, + 0x0a}, + name: "encodeValidUncompressedMainNetWif", + }, + { + privateKey: []byte{ + 0xdd, 0xa3, 0x5a, 0x14, 0x88, 0xfb, 0x97, 0xb6, + 0xeb, 0x3f, 0xe6, 0xe9, 0xef, 0x2a, 0x25, 0x81, + 0x4e, 0x39, 0x6f, 0xb5, 0xdc, 0x29, 0x5f, 0xe9, + 0x94, 0xb9, 0x67, 0x89, 0xb2, 0x1a, 0x03, 0x98}, + net: &chaincfg.TestNet3Params, + compress: true, + wif: "cV1Y7ARUr9Yx7BR55nTdnR7ZXNJphZtCCMBTEZBJe1hXt2kB684q", + publicKey: []byte{ + 0x02, 0xee, 0xc2, 0x54, 0x06, 0x61, 0xb0, 0xc3, + 0x9d, 0x27, 0x15, 0x70, 0x74, 0x24, 0x13, 0xbd, + 0x02, 0x93, 0x2d, 0xd0, 0x09, 0x34, 0x93, 0xfd, + 0x0b, 0xec, 0xed, 0x0b, 0x7f, 0x93, 0xad, 0xde, + 0xc4}, + name: "encodeValidCompressedTestNet3Wif", + }, + } + + for _, validCase := range validEncodeCases { + validCase := validCase + + t.Run(validCase.name, func(t *testing.T) { + priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), validCase.privateKey) + wif, err := NewWIF(priv, validCase.net, validCase.compress) + if err != nil { + t.Fatalf("NewWIF failed: expected no error, got '%v'", err) + } + + if !wif.IsForNet(validCase.net) { + t.Fatal("IsForNet failed: got 'false', want 'true'") + } + + if gotPubKey := wif.SerializePubKey(); !bytes.Equal(gotPubKey, validCase.publicKey) { + t.Fatalf("SerializePubKey failed: got '%s', want '%s'", + hex.EncodeToString(gotPubKey), hex.EncodeToString(validCase.publicKey)) + } + + // Test that encoding the WIF structure matches the expected string. + got := wif.String() + if got != validCase.wif { + t.Fatalf("NewWIF failed: want '%s', got '%s'", + validCase.wif, got) + } + + // Test that decoding the expected string results in the original WIF + // structure. + decodedWif, err := DecodeWIF(got) + if err != nil { + t.Fatalf("DecodeWIF failed: expected no error, got '%v'", err) + } + if decodedWifString := decodedWif.String(); decodedWifString != validCase.wif { + t.Fatalf("NewWIF failed: want '%v', got '%v'", validCase.wif, decodedWifString) + } + }) + } + + invalidDecodeCases := []struct { + name string + wif string + err error + }{ + { + name: "decodeInvalidLengthWif", + wif: "deadbeef", + err: ErrMalformedPrivateKey, + }, + { + name: "decodeInvalidCompressMagicWif", + wif: "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sfZr2ym", + err: ErrMalformedPrivateKey, + }, + { + name: "decodeInvalidChecksumWif", + wif: "5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTj", + err: ErrChecksumMismatch, + }, + } + + for _, invalidCase := range invalidDecodeCases { + invalidCase := invalidCase + + t.Run(invalidCase.name, func(t *testing.T) { + decodedWif, err := DecodeWIF(invalidCase.wif) + if decodedWif != nil { + t.Fatalf("DecodeWIF: unexpectedly succeeded - got '%v', want '%v'", + decodedWif, nil) + } + if err != invalidCase.err { + t.Fatalf("DecodeWIF: expected error '%v', got '%v'", + invalidCase.err, err) + } + }) + } + + t.Run("encodeInvalidNetworkWif", func(t *testing.T) { + privateKey := []byte{ + 0x0c, 0x28, 0xfc, 0xa3, 0x86, 0xc7, 0xa2, 0x27, + 0x60, 0x0b, 0x2f, 0xe5, 0x0b, 0x7c, 0xae, 0x11, + 0xec, 0x86, 0xd3, 0xbf, 0x1f, 0xbe, 0x47, 0x1b, + 0xe8, 0x98, 0x27, 0xe1, 0x9d, 0x72, 0xaa, 0x1d} + priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), privateKey) + + wif, err := NewWIF(priv, nil, true) + + if wif != nil { + t.Fatalf("NewWIF: unexpectedly succeeded - got '%v', want '%v'", + wif, nil) + } + if err == nil || err.Error() != "no network" { + t.Fatalf("NewWIF: expected error 'no network', got '%v'", err) + } + }) +} From caac0f821a6731408ba59bfe110b011eb0969c18 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 24 Dec 2021 16:43:16 -0800 Subject: [PATCH 0581/1056] multi: update btcutil imports to point to new sub-module In this commit, we update all the btcutil imports to point to the new sub-module. In the same commit, we also modify the recently added `btcutil/go.mod` file as we need to continue pointing to the _old_ version of btcd, until we merge this PR and push a new tag. --- blockchain/accept.go | 2 +- blockchain/bench_test.go | 2 +- blockchain/chain.go | 2 +- blockchain/chain_test.go | 2 +- blockchain/chainio.go | 2 +- blockchain/checkpoints.go | 2 +- blockchain/common_test.go | 2 +- blockchain/example_test.go | 2 +- blockchain/fullblocks_test.go | 2 +- blockchain/fullblocktests/generate.go | 2 +- blockchain/indexers/addrindex.go | 2 +- blockchain/indexers/blocklogger.go | 2 +- blockchain/indexers/cfindex.go | 6 +-- blockchain/indexers/common.go | 2 +- blockchain/indexers/manager.go | 2 +- blockchain/indexers/txindex.go | 2 +- blockchain/merkle.go | 2 +- blockchain/merkle_test.go | 2 +- blockchain/process.go | 2 +- blockchain/scriptval.go | 2 +- blockchain/utxoviewpoint.go | 2 +- blockchain/validate.go | 2 +- blockchain/validate_test.go | 2 +- blockchain/weight.go | 2 +- btcjson/chainsvrresults.go | 2 +- btcjson/chainsvrresults_test.go | 2 +- btcjson/walletsvrcmds.go | 2 +- btcjson/walletsvrcmds_test.go | 2 +- btcutil/go.mod | 2 - btcutil/go.sum | 42 +++++++++++++++++++ chaincfg/README.md | 2 +- chaincfg/doc.go | 2 +- cmd/addblock/config.go | 2 +- cmd/addblock/import.go | 2 +- cmd/btcctl/config.go | 2 +- cmd/findcheckpoint/config.go | 2 +- cmd/gencerts/gencerts.go | 2 +- config.go | 2 +- database/cmd/dbtool/globalconfig.go | 2 +- database/cmd/dbtool/insecureimport.go | 2 +- database/example_test.go | 10 ++++- database/ffldb/bench_test.go | 2 +- database/ffldb/db.go | 2 +- database/ffldb/driver_test.go | 2 +- database/ffldb/interface_test.go | 2 +- database/ffldb/whitebox_test.go | 2 +- database/interface.go | 2 +- docs/developer_resources.md | 2 +- docs/json_rpc_api.md | 6 +-- go.mod | 19 +++++++-- go.sum | 26 ++++-------- integration/csv_fork_test.go | 2 +- integration/rpctest/blockgen.go | 2 +- integration/rpctest/memwallet.go | 4 +- integration/rpctest/node.go | 2 +- integration/rpctest/rpc_harness.go | 2 +- integration/rpctest/rpc_harness_test.go | 2 +- mempool/estimatefee.go | 2 +- mempool/estimatefee_test.go | 2 +- mempool/mempool.go | 2 +- mempool/mempool_test.go | 2 +- mempool/policy.go | 2 +- mempool/policy_test.go | 2 +- mining/cpuminer/cpuminer.go | 2 +- mining/mining.go | 2 +- mining/mining_test.go | 2 +- mining/policy.go | 2 +- mining/policy_test.go | 2 +- netsync/blocklogger.go | 2 +- netsync/interface.go | 2 +- netsync/manager.go | 2 +- rpcadapters.go | 2 +- rpcclient/examples/btcdwebsockets/main.go | 2 +- .../examples/btcwalletwebsockets/main.go | 2 +- rpcclient/extensions.go | 2 +- rpcclient/mining.go | 2 +- rpcclient/notify.go | 2 +- rpcclient/rawtransactions.go | 2 +- rpcclient/wallet.go | 2 +- rpcserver.go | 2 +- rpcwebsocket.go | 2 +- server.go | 4 +- txscript/example_test.go | 2 +- txscript/pkscript.go | 2 +- txscript/reference_test.go | 2 +- txscript/sign.go | 2 +- txscript/sign_test.go | 2 +- txscript/standard.go | 2 +- txscript/standard_test.go | 2 +- 89 files changed, 165 insertions(+), 114 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index f85d6558e8..44ccbf997a 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -8,7 +8,7 @@ import ( "fmt" "github.com/btcsuite/btcd/database" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // maybeAcceptBlock potentially accepts a block into the block chain and, if diff --git a/blockchain/bench_test.go b/blockchain/bench_test.go index 43d3152b37..eee4340bc8 100644 --- a/blockchain/bench_test.go +++ b/blockchain/bench_test.go @@ -7,7 +7,7 @@ package blockchain import ( "testing" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // BenchmarkIsCoinBase performs a simple benchmark against the IsCoinBase diff --git a/blockchain/chain.go b/blockchain/chain.go index eea603ce8e..92bfb26876 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -16,7 +16,7 @@ import ( "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index 7de323bc8d..34356326b9 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // TestHaveBlock tests the HaveBlock API to ensure proper functionality. diff --git a/blockchain/chainio.go b/blockchain/chainio.go index f40ba465e9..fa41254da6 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/checkpoints.go b/blockchain/checkpoints.go index af3b6d924e..dbfa9d146d 100644 --- a/blockchain/checkpoints.go +++ b/blockchain/checkpoints.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // CheckpointConfirmations is the number of blocks before the end of the current diff --git a/blockchain/common_test.go b/blockchain/common_test.go index dd392a6669..8de699c416 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -20,7 +20,7 @@ import ( _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/example_test.go b/blockchain/example_test.go index 691d0927f2..7f15e59bc6 100644 --- a/blockchain/example_test.go +++ b/blockchain/example_test.go @@ -14,7 +14,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // This example demonstrates how to create a new chain instance and use diff --git a/blockchain/fullblocks_test.go b/blockchain/fullblocks_test.go index 3ae0d0eb51..3cc7c87b70 100644 --- a/blockchain/fullblocks_test.go +++ b/blockchain/fullblocks_test.go @@ -20,7 +20,7 @@ import ( _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 82d3a036e9..9555116842 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -24,7 +24,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 4a9bf4ec68..2f0e2eeba1 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/indexers/blocklogger.go b/blockchain/indexers/blocklogger.go index 88d6f26998..3671c0162a 100644 --- a/blockchain/indexers/blocklogger.go +++ b/blockchain/indexers/blocklogger.go @@ -9,7 +9,7 @@ import ( "time" "github.com/btcsuite/btclog" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // blockProgressLogger provides periodic logging for other services in order diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 8ea147282b..fa0ee3c0a6 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -12,9 +12,9 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/gcs" - "github.com/btcsuite/btcutil/gcs/builder" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/gcs" + "github.com/btcsuite/btcd/btcutil/gcs/builder" ) const ( diff --git a/blockchain/indexers/common.go b/blockchain/indexers/common.go index a912bb4c70..07b2feca5d 100644 --- a/blockchain/indexers/common.go +++ b/blockchain/indexers/common.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/database" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/blockchain/indexers/manager.go b/blockchain/indexers/manager.go index bc0804f8bd..8c87ca0771 100644 --- a/blockchain/indexers/manager.go +++ b/blockchain/indexers/manager.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/blockchain/indexers/txindex.go b/blockchain/indexers/txindex.go index 00cfd00621..f1d734e06b 100644 --- a/blockchain/indexers/txindex.go +++ b/blockchain/indexers/txindex.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/merkle.go b/blockchain/merkle.go index 8f3f6b97ea..d7e567b283 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/merkle_test.go b/blockchain/merkle_test.go index 275ffef37d..1a224586fa 100644 --- a/blockchain/merkle_test.go +++ b/blockchain/merkle_test.go @@ -7,7 +7,7 @@ package blockchain import ( "testing" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // TestMerkle tests the BuildMerkleTreeStore API. diff --git a/blockchain/process.go b/blockchain/process.go index 6d2161bb95..c367b4ceff 100644 --- a/blockchain/process.go +++ b/blockchain/process.go @@ -10,7 +10,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // BehaviorFlags is a bitmask defining tweaks to the normal behavior when diff --git a/blockchain/scriptval.go b/blockchain/scriptval.go index 8ba59a4214..8869e23f27 100644 --- a/blockchain/scriptval.go +++ b/blockchain/scriptval.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // txValidateItem holds a transaction along with which input to validate. diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index b85765814d..3398693225 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // txoFlags is a bitmask defining additional information and state for a diff --git a/blockchain/validate.go b/blockchain/validate.go index f41d54e6b1..575861e2d3 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/validate_test.go b/blockchain/validate_test.go index 9bf2ff42e8..d5d17781d3 100644 --- a/blockchain/validate_test.go +++ b/blockchain/validate_test.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // TestSequenceLocksActive tests the SequenceLockActive function to ensure it diff --git a/blockchain/weight.go b/blockchain/weight.go index 6f6292a1b6..5a6f257be5 100644 --- a/blockchain/weight.go +++ b/blockchain/weight.go @@ -9,7 +9,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 59f18c74c8..8062d9d990 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // GetBlockHeaderVerboseResult models the data from the getblockheader command when diff --git a/btcjson/chainsvrresults_test.go b/btcjson/chainsvrresults_test.go index 72dcd8d7ec..aee514a9a4 100644 --- a/btcjson/chainsvrresults_test.go +++ b/btcjson/chainsvrresults_test.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/davecgh/go-spew/spew" ) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index e8ed62372b..1e061529d3 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -12,7 +12,7 @@ import ( "encoding/json" "fmt" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // AddMultisigAddressCmd defines the addmutisigaddress JSON-RPC command. diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 9c68d260f6..396153ef04 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -12,7 +12,7 @@ import ( "testing" "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // TestWalletSvrCmds tests all of the wallet server commands marshal and diff --git a/btcutil/go.mod b/btcutil/go.mod index 8d3c35b7e4..71014ebed5 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -9,5 +9,3 @@ require ( github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) - -replace github.com/btcsuite/btcd => ../ diff --git a/btcutil/go.sum b/btcutil/go.sum index 58fe70e411..c51f84dd2d 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -9,35 +9,77 @@ github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+q github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/chaincfg/README.md b/chaincfg/README.md index 72fac2e7dc..d1a534bafe 100644 --- a/chaincfg/README.md +++ b/chaincfg/README.md @@ -24,7 +24,7 @@ import ( "fmt" "log" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" ) diff --git a/chaincfg/doc.go b/chaincfg/doc.go index 3659adbf46..1595b2769f 100644 --- a/chaincfg/doc.go +++ b/chaincfg/doc.go @@ -25,7 +25,7 @@ // "fmt" // "log" // -// "github.com/btcsuite/btcutil" +// "github.com/btcsuite/btcd/btcutil" // "github.com/btcsuite/btcd/chaincfg" // ) // diff --git a/cmd/addblock/config.go b/cmd/addblock/config.go index 90620c8fda..c638196534 100644 --- a/cmd/addblock/config.go +++ b/cmd/addblock/config.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" flags "github.com/jessevdk/go-flags" ) diff --git a/cmd/addblock/import.go b/cmd/addblock/import.go index b7a30369ec..4875ce11cb 100644 --- a/cmd/addblock/import.go +++ b/cmd/addblock/import.go @@ -16,7 +16,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) var zeroHash = chainhash.Hash{} diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index 1cc2a260f3..3db735c5d8 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" flags "github.com/jessevdk/go-flags" ) diff --git a/cmd/findcheckpoint/config.go b/cmd/findcheckpoint/config.go index 87f04cecd5..5671b5b186 100644 --- a/cmd/findcheckpoint/config.go +++ b/cmd/findcheckpoint/config.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" flags "github.com/jessevdk/go-flags" ) diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index 27d1073e74..c0a27ad37b 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" flags "github.com/jessevdk/go-flags" ) diff --git a/config.go b/config.go index 156084bcf9..5eca3f2174 100644 --- a/config.go +++ b/config.go @@ -30,7 +30,7 @@ import ( "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/go-socks/socks" flags "github.com/jessevdk/go-flags" ) diff --git a/database/cmd/dbtool/globalconfig.go b/database/cmd/dbtool/globalconfig.go index aa1e0e0483..2ec746a43d 100644 --- a/database/cmd/dbtool/globalconfig.go +++ b/database/cmd/dbtool/globalconfig.go @@ -14,7 +14,7 @@ import ( "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/database/cmd/dbtool/insecureimport.go b/database/cmd/dbtool/insecureimport.go index 7564eb68ad..a01c74bb55 100644 --- a/database/cmd/dbtool/insecureimport.go +++ b/database/cmd/dbtool/insecureimport.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // importCmd defines the configuration options for the insecureimport command. diff --git a/database/example_test.go b/database/example_test.go index 8b6fe7bce4..b64baf2c8e 100644 --- a/database/example_test.go +++ b/database/example_test.go @@ -7,14 +7,15 @@ package database_test import ( "bytes" "fmt" + "io/ioutil" "os" "path/filepath" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" ) // This example demonstrates creating a new database. @@ -122,9 +123,14 @@ func Example_blockStorageAndRetrieval() { // Typically you wouldn't want to remove the database right away like // this, nor put it in the temp directory, but it's done here to ensure // the example cleans up after itself. - dbPath := filepath.Join(os.TempDir(), "exampleblkstorage") + dbPath, err := ioutil.TempDir("", "exampleblkstorage") + if err != nil { + fmt.Println(err) + return + } db, err := database.Create("ffldb", dbPath, wire.MainNet) if err != nil { + fmt.Println("fail here") fmt.Println(err) return } diff --git a/database/ffldb/bench_test.go b/database/ffldb/bench_test.go index 8d020313d8..f4a0eb32e5 100644 --- a/database/ffldb/bench_test.go +++ b/database/ffldb/bench_test.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // BenchmarkBlockHeader benchmarks how long it takes to load the mainnet genesis diff --git a/database/ffldb/db.go b/database/ffldb/db.go index b499442101..ee36b5b006 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -18,7 +18,7 @@ import ( "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database/internal/treap" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/goleveldb/leveldb" "github.com/btcsuite/goleveldb/leveldb/comparer" ldberrors "github.com/btcsuite/goleveldb/leveldb/errors" diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index f3db909d79..ef35f07840 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -14,7 +14,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database/ffldb" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // dbType is the database type name for this driver. diff --git a/database/ffldb/interface_test.go b/database/ffldb/interface_test.go index 1ce991cc09..af26faccab 100644 --- a/database/ffldb/interface_test.go +++ b/database/ffldb/interface_test.go @@ -29,7 +29,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/database/ffldb/whitebox_test.go b/database/ffldb/whitebox_test.go index 161d866d29..1db69e4215 100644 --- a/database/ffldb/whitebox_test.go +++ b/database/ffldb/whitebox_test.go @@ -20,7 +20,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/goleveldb/leveldb" ldberrors "github.com/btcsuite/goleveldb/leveldb/errors" ) diff --git a/database/interface.go b/database/interface.go index 435a8ff581..aa88cc3723 100644 --- a/database/interface.go +++ b/database/interface.go @@ -9,7 +9,7 @@ package database import ( "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // Cursor represents a cursor over key/value pairs and nested buckets of a diff --git a/docs/developer_resources.md b/docs/developer_resources.md index cec8ce9972..c595c8330e 100644 --- a/docs/developer_resources.md +++ b/docs/developer_resources.md @@ -28,7 +28,7 @@ * [mempool](https://github.com/btcsuite/btcd/tree/master/mempool) - Package mempool provides a policy-enforced pool of unmined bitcoin transactions. - * [btcutil](https://github.com/btcsuite/btcutil) - Provides Bitcoin-specific + * [btcutil](https://github.com/btcsuite/btcd/btcutil) - Provides Bitcoin-specific convenience functions and types * [chainhash](https://github.com/btcsuite/btcd/tree/master/chaincfg/chainhash) - Provides a generic hash type and associated functions that allows the diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index db292d2ba2..d1b43ce8c4 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -1100,7 +1100,7 @@ import ( "path/filepath" "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) func main() { @@ -1164,7 +1164,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) func main() { @@ -1256,7 +1256,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) func main() { diff --git a/go.mod b/go.mod index 767c2740db..a2e5bed578 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/btcsuite/btcd require ( + github.com/btcsuite/btcd/btcutil v1.0.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/goleveldb v1.0.0 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 @@ -11,8 +11,21 @@ require ( github.com/decred/dcrd/lru v1.0.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 - github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) -go 1.16 +require ( + github.com/aead/siphash v1.0.1 // indirect + github.com/btcsuite/snappy-go v1.0.0 // indirect + github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect + github.com/onsi/ginkgo v1.14.0 // indirect + github.com/onsi/gomega v1.10.1 // indirect + golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc // indirect + golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed // indirect + golang.org/x/text v0.3.3 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +) + +replace github.com/btcsuite/btcd/btcutil => ./btcutil + +go 1.17 diff --git a/go.sum b/go.sum index e9ee276db4..a23498435b 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,6 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= @@ -19,12 +17,12 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -33,11 +31,9 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= @@ -46,49 +42,46 @@ github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -97,11 +90,10 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/integration/csv_fork_test.go b/integration/csv_fork_test.go index 3146634966..5ffd5d5ab2 100644 --- a/integration/csv_fork_test.go +++ b/integration/csv_fork_test.go @@ -21,7 +21,7 @@ import ( "github.com/btcsuite/btcd/integration/rpctest" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/integration/rpctest/blockgen.go b/integration/rpctest/blockgen.go index 0d802f5a48..a35c66e6ac 100644 --- a/integration/rpctest/blockgen.go +++ b/integration/rpctest/blockgen.go @@ -17,7 +17,7 @@ import ( "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // solveBlock attempts to find a nonce which makes the passed block header hash diff --git a/integration/rpctest/memwallet.go b/integration/rpctest/memwallet.go index 59b0ef4c08..c94124d82c 100644 --- a/integration/rpctest/memwallet.go +++ b/integration/rpctest/memwallet.go @@ -17,8 +17,8 @@ import ( "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/hdkeychain" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/hdkeychain" ) var ( diff --git a/integration/rpctest/node.go b/integration/rpctest/node.go index 73dc15fca9..be52a15404 100644 --- a/integration/rpctest/node.go +++ b/integration/rpctest/node.go @@ -15,7 +15,7 @@ import ( "time" rpc "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // nodeConfig contains all the args, and data required to launch a btcd process diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 679ae4e478..cb49e42c26 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -20,7 +20,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/integration/rpctest/rpc_harness_test.go b/integration/rpctest/rpc_harness_test.go index df753e3126..d1184eb6ba 100644 --- a/integration/rpctest/rpc_harness_test.go +++ b/integration/rpctest/rpc_harness_test.go @@ -17,7 +17,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) func testSendOutputs(r *Harness, t *testing.T) { diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index 55fe4810df..f3a7cfe95b 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -18,7 +18,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // TODO incorporate Alex Morcos' modifications to Gavin's initial model diff --git a/mempool/estimatefee_test.go b/mempool/estimatefee_test.go index 16dcfadc95..c5ea85c635 100644 --- a/mempool/estimatefee_test.go +++ b/mempool/estimatefee_test.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // newTestFeeEstimator creates a feeEstimator with some different parameters diff --git a/mempool/mempool.go b/mempool/mempool.go index b54856c8b3..f830a51382 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -20,7 +20,7 @@ import ( "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 96d5054417..96777b9758 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -18,7 +18,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // fakeChain is used by the pool harness to provide generated test utxos and diff --git a/mempool/policy.go b/mempool/policy.go index 1fe850797f..edba16ac2e 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/mempool/policy_test.go b/mempool/policy_test.go index b9cdbac47a..a81f98ea83 100644 --- a/mempool/policy_test.go +++ b/mempool/policy_test.go @@ -14,7 +14,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // TestCalcMinRequiredTxRelayFee tests the calcMinRequiredTxRelayFee API. diff --git a/mining/cpuminer/cpuminer.go b/mining/cpuminer/cpuminer.go index 3d5b3b1936..038e6645bb 100644 --- a/mining/cpuminer/cpuminer.go +++ b/mining/cpuminer/cpuminer.go @@ -17,7 +17,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/mining/mining.go b/mining/mining.go index e918328df8..4ed61f3f32 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/mining/mining_test.go b/mining/mining_test.go index 362253e5fe..ba1d97771c 100644 --- a/mining/mining_test.go +++ b/mining/mining_test.go @@ -9,7 +9,7 @@ import ( "math/rand" "testing" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // TestTxFeePrioHeap ensures the priority queue for transaction fees and diff --git a/mining/policy.go b/mining/policy.go index c3f059c521..f8ce411602 100644 --- a/mining/policy.go +++ b/mining/policy.go @@ -7,7 +7,7 @@ package mining import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/mining/policy_test.go b/mining/policy_test.go index f66a9c8dbd..0a362f5471 100644 --- a/mining/policy_test.go +++ b/mining/policy_test.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // newHashFromStr converts the passed big-endian hex string into a diff --git a/netsync/blocklogger.go b/netsync/blocklogger.go index 18480e782a..788192ccb2 100644 --- a/netsync/blocklogger.go +++ b/netsync/blocklogger.go @@ -9,7 +9,7 @@ import ( "time" "github.com/btcsuite/btclog" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // blockProgressLogger provides periodic logging for other services in order diff --git a/netsync/interface.go b/netsync/interface.go index 3e6ca1c12d..2ce479bf2d 100644 --- a/netsync/interface.go +++ b/netsync/interface.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // PeerNotifier exposes methods to notify peers of status changes to diff --git a/netsync/manager.go b/netsync/manager.go index 2b6c041156..a297bb3f24 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -19,7 +19,7 @@ import ( "github.com/btcsuite/btcd/mempool" peerpkg "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/rpcadapters.go b/rpcadapters.go index ddcdf79bf7..02d33710ac 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/netsync" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // rpcPeer provides a peer for use with the RPC server and implements the diff --git a/rpcclient/examples/btcdwebsockets/main.go b/rpcclient/examples/btcdwebsockets/main.go index 56d12d8274..1f18b9aab4 100644 --- a/rpcclient/examples/btcdwebsockets/main.go +++ b/rpcclient/examples/btcdwebsockets/main.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) func main() { diff --git a/rpcclient/examples/btcwalletwebsockets/main.go b/rpcclient/examples/btcwalletwebsockets/main.go index e803138d64..7f177e0b1f 100644 --- a/rpcclient/examples/btcwalletwebsockets/main.go +++ b/rpcclient/examples/btcwalletwebsockets/main.go @@ -11,7 +11,7 @@ import ( "time" "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/davecgh/go-spew/spew" ) diff --git a/rpcclient/extensions.go b/rpcclient/extensions.go index c8615293e3..efb6c1c710 100644 --- a/rpcclient/extensions.go +++ b/rpcclient/extensions.go @@ -15,7 +15,7 @@ import ( "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // FutureDebugLevelResult is a future promise to deliver the result of a diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 717825eeaa..680a63b6d5 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // FutureGenerateResult is a future promise to deliver the result of a diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 6879099acd..225af281cf 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -16,7 +16,7 @@ import ( "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index cfc322c769..3643f2b0ca 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 71435d99f8..7268ad0a19 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -12,7 +12,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // ***************************** diff --git a/rpcserver.go b/rpcserver.go index 6f60261a9c..8a4ecaac8d 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -40,7 +40,7 @@ import ( "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/websocket" ) diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 356a897455..4d140b4825 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -27,7 +27,7 @@ import ( "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/websocket" "golang.org/x/crypto/ripemd160" ) diff --git a/server.go b/server.go index 746c48dde3..45bfb17ee4 100644 --- a/server.go +++ b/server.go @@ -36,8 +36,8 @@ import ( "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcutil/bloom" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/bloom" ) const ( diff --git a/txscript/example_test.go b/txscript/example_test.go index 6e17341c4a..7983b08ff2 100644 --- a/txscript/example_test.go +++ b/txscript/example_test.go @@ -14,7 +14,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // This example demonstrates creating a script which pays to a bitcoin address. diff --git a/txscript/pkscript.go b/txscript/pkscript.go index f5b11e6d53..f8aa783aef 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -8,7 +8,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" "golang.org/x/crypto/ripemd160" ) diff --git a/txscript/reference_test.go b/txscript/reference_test.go index 9d9c8f39ed..3d4c591427 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -17,7 +17,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // scriptTestName returns a descriptive test name for the given reference script diff --git a/txscript/sign.go b/txscript/sign.go index 138e31cdd4..84d8d1f3ea 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // RawTxInWitnessSignature returns the serialized ECDA signature for the input diff --git a/txscript/sign_test.go b/txscript/sign_test.go index b97a8a64d4..47084f18bf 100644 --- a/txscript/sign_test.go +++ b/txscript/sign_test.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) type addressToKey struct { diff --git a/txscript/standard.go b/txscript/standard.go index 44902971e9..343a9b2727 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -9,7 +9,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/txscript/standard_test.go b/txscript/standard_test.go index 582d30eee4..809bf485d9 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -13,7 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcd/btcutil" ) // mustParseShortForm parses the passed short form script and returns the From 3cacbd489ecba886a8f9c1d37eca7a6f70ced3d1 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 24 Dec 2021 16:48:35 -0800 Subject: [PATCH 0582/1056] build: adapt btcutil Makefile for usage in project In this commit, we adapt the Makefile that was being used for the btcutil project to work for btcd as well. The Makefile is pretty simple, and is just a series of templated commands. Overtime, we can pull in some of the `lnd` additions as well, which we use to handle our reproducible build and verification system. --- .github/workflows/go.yml | 72 +++++++++++++++++------ Makefile | 124 +++++++++++++++++++++++++++++++++++++++ goclean.sh | 19 ------ 3 files changed, 177 insertions(+), 38 deletions(-) create mode 100644 Makefile delete mode 100755 goclean.sh diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 5da1bebc63..b015b3c175 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,35 +1,69 @@ name: Build and Test on: [push, pull_request] + +env: + # go needs absolute directories, using the $HOME variable doesn't work here. + GOCACHE: /home/runner/work/go/pkg/build + GOPATH: /home/runner/work/go + GO_VERSION: 1.17.5 + jobs: build: - # https://github.blog/changelog/2021-04-20-github-actions-control-permissions-for-github_token/ - permissions: - contents: read - name: Go CI + name: Build runs-on: ubuntu-latest - strategy: - matrix: - go: [1.16.8, 1.17.1] steps: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: ${{ matrix.go }} + go-version: ${{ env.GO_VERSION }} + - name: Check out source uses: actions/checkout@v2 - - name: Install Linters - run: "curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.26.0" + - name: Build - env: - GO111MODULE: "on" - run: go build ./... + run: make build + + test-cover: + name: Unit coverage + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Check out source + uses: actions/checkout@v2 + - name: Test - env: - GO111MODULE: "on" - run: | - sh ./goclean.sh + run: make unit-cover - - name: Send coverage + - name: Send top-level coverage uses: shogo82148/actions-goveralls@v1 with: - path-to-profile: profile.cov + path-to-profile: coverage.txt + + - name: Send btcutil coverage + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: btcutil/coverage.txt + + - name: Send btcutil coverage for psbt package + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: btcutil/psbt/coverage.txt + + test-race: + name: Unit race + runs-on: ubuntu-latest + steps: + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Check out source + uses: actions/checkout@v2 + + - name: Test + run: make unit-race diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000..5db0871ad1 --- /dev/null +++ b/Makefile @@ -0,0 +1,124 @@ +PKG := github.com/btcsuite/btcd + +LINT_PKG := github.com/golangci/golangci-lint/cmd/golangci-lint +GOACC_PKG := github.com/ory/go-acc +GOIMPORTS_PKG := golang.org/x/tools/cmd/goimports + +GO_BIN := ${GOPATH}/bin +LINT_BIN := $(GO_BIN)/golangci-lint +GOACC_BIN := $(GO_BIN)/go-acc + +LINT_COMMIT := v1.18.0 +GOACC_COMMIT := 80342ae2e0fcf265e99e76bcc4efd022c7c3811b + +DEPGET := cd /tmp && GO111MODULE=on go get -v +GOBUILD := GO111MODULE=on go build -v +GOINSTALL := GO111MODULE=on go install -v +DEV_TAGS := rpctest +GOTEST := GO111MODULE=on go test -v -tags=$(DEV_TAGS) + +GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*") + +RM := rm -f +CP := cp +MAKE := make +XARGS := xargs -L 1 + +# Linting uses a lot of memory, so keep it under control by limiting the number +# of workers if requested. +ifneq ($(workers),) +LINT_WORKERS = --concurrency=$(workers) +endif + +LINT = $(LINT_BIN) run -v $(LINT_WORKERS) + +GREEN := "\\033[0;32m" +NC := "\\033[0m" +define print + echo $(GREEN)$1$(NC) +endef + +default: build + +all: build check + +# ============ +# DEPENDENCIES +# ============ + +$(LINT_BIN): + @$(call print, "Fetching linter") + $(DEPGET) $(LINT_PKG)@$(LINT_COMMIT) + +$(GOACC_BIN): + @$(call print, "Fetching go-acc") + $(DEPGET) $(GOACC_PKG)@$(GOACC_COMMIT) + +goimports: + @$(call print, "Installing goimports.") + $(DEPGET) $(GOIMPORTS_PKG) + +# ============ +# INSTALLATION +# ============ + +build: + @$(call print, "Building all binaries") + $(GOBUILD) $(PKG) + $(GOBUILD) $(PKG)/cmd/btcctl + $(GOBUILD) $(PKG)/cmd/gencerts + $(GOBUILD) $(PKG)/cmd/findcheckpoint + $(GOBUILD) $(PKG)/cmd/addblock + +# ======= +# TESTING +# ======= + +check: unit + +unit: + @$(call print, "Running unit tests.") + $(GOTEST) ./... -test.timeout=20m + cd btcutil; $(GOTEST) ./... -test.timeout=20m + cd btcutil/psbt; $(GOTEST) ./... -test.timeout=20m + +unit-cover: $(GOACC_BIN) + @$(call print, "Running unit coverage tests.") + $(GOACC_BIN) ./... + cd btcutil; $(GOACC_BIN) ./... + cd btcutil/psbt; $(GOACC_BIN) ./... + +unit-race: + @$(call print, "Running unit race tests.") + env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... + cd btcutil; env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... + cd btcutil/psbt; env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... + +# ========= +# UTILITIES +# ========= + +fmt: goimports + @$(call print, "Fixing imports.") + goimports -w $(GOFILES_NOVENDOR) + @$(call print, "Formatting source.") + gofmt -l -w -s $(GOFILES_NOVENDOR) + +lint: $(LINT_BIN) + @$(call print, "Linting source.") + $(LINT) + +clean: + @$(call print, "Cleaning source.$(NC)") + $(RM) coverage.txt btcutil/coverage.txt btcutil/psbt/coverage.txt + +.PHONY: all \ + default \ + build \ + check \ + unit \ + unit-cover \ + unit-race \ + fmt \ + lint \ + clean diff --git a/goclean.sh b/goclean.sh deleted file mode 100755 index dad9f8f1dc..0000000000 --- a/goclean.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -# The script does automatic checking on a Go package and its sub-packages, including: -# 1. gofmt (http://golang.org/cmd/gofmt/) -# 3. go vet (http://golang.org/cmd/vet) -# 4. gosimple (https://github.com/dominikh/go-simple) -# 5. unconvert (https://github.com/mdempsky/unconvert) -# 6. race detector (http://blog.golang.org/race-detector) -# 7. test coverage (http://blog.golang.org/cover) - -set -ex - -env GORACE="halt_on_error=1" go test -race -tags="rpctest" -covermode atomic -coverprofile=profile.cov ./... - -# Automatic checks -golangci-lint run --deadline=10m --disable-all \ ---enable=gofmt \ ---enable=vet \ ---enable=gosimple \ ---enable=unconvert From 161863e7fc63c1945be2452e3b7032fde54f9481 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 10 Jan 2022 19:40:11 -0800 Subject: [PATCH 0583/1056] btcutil: update modules to replace to top-level btcd repo Now that the new `btcutil/v1.0.0` tag has been pushed, we update the new internal modules to point to the top-level `btcd` repo via replace directives. --- btcutil/go.mod | 4 +++- btcutil/go.sum | 16 +++----------- btcutil/psbt/go.mod | 7 +++--- btcutil/psbt/go.sum | 53 +++++++++++++++++++++++++++++++++++---------- go.mod | 6 ----- go.sum | 10 +-------- 6 files changed, 53 insertions(+), 43 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index 71014ebed5..eaf71339e1 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -4,8 +4,10 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 - github.com/btcsuite/btcd v0.20.1-beta + github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c github.com/davecgh/go-spew v1.1.1 github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) + +replace github.com/btcsuite/btcd => ../ diff --git a/btcutil/go.sum b/btcutil/go.sum index c51f84dd2d..f4eb4bca26 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -1,21 +1,15 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= @@ -32,21 +26,17 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 55ac1ca956..485abcff67 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -3,15 +3,16 @@ module github.com/btcsuite/btcd/btcutil/psbt go 1.17 require ( - github.com/btcsuite/btcd v0.20.1-beta - github.com/btcsuite/btcd/btcutil v0.0.0-20190425235716-9e5f4b9a998d + github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c + github.com/btcsuite/btcd/btcutil v1.0.0 github.com/davecgh/go-spew v1.1.1 ) require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d // indirect golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect ) replace github.com/btcsuite/btcd/btcutil => ../ + +replace github.com/btcsuite/btcd => ../.. diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index 4898b254c6..921a146260 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -1,39 +1,70 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/go.mod b/go.mod index a2e5bed578..2c2bb9229f 100644 --- a/go.mod +++ b/go.mod @@ -18,12 +18,6 @@ require ( github.com/aead/siphash v1.0.1 // indirect github.com/btcsuite/snappy-go v1.0.0 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect - github.com/onsi/ginkgo v1.14.0 // indirect - github.com/onsi/gomega v1.10.1 // indirect - golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc // indirect - golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed // indirect - golang.org/x/text v0.3.3 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) replace github.com/btcsuite/btcd/btcutil => ./btcutil diff --git a/go.sum b/go.sum index a23498435b..3b35b00620 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,18 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= @@ -35,7 +31,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= @@ -45,16 +40,13 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= From dc4dc15d8c89c019847a2bb8df2833825e8403c4 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 19 Mar 2021 17:12:47 -0700 Subject: [PATCH 0584/1056] chaincfg: create new abstract deployment starter/ender interfaces In this commit, we create a series of new interfaces that'll allow us to abstract "when" exactly a deployment starts and ends. As is, all deployments start/end based on a unix timestamp, which is compared against the MTP of a given block to determine if a new deployment has started or ended. This works fine for BIP 9 which uses time based timeouts, but not so much for BIP 8. In order to prep a future refactor that allows our version bits implementation to support both time and block based start/end times, this new abstraction has been introduced. --- chaincfg/deployment_time_frame.go | 181 ++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 chaincfg/deployment_time_frame.go diff --git a/chaincfg/deployment_time_frame.go b/chaincfg/deployment_time_frame.go new file mode 100644 index 0000000000..7178d9b26d --- /dev/null +++ b/chaincfg/deployment_time_frame.go @@ -0,0 +1,181 @@ +package chaincfg + +import ( + "fmt" + "time" + + "github.com/btcsuite/btcd/wire" +) + +var ( + // ErrNoBlockClock is returned when an operation fails due to lack of + // synchornization with the current up to date block clock. + ErrNoBlockClock = fmt.Errorf("no block clock synchronized") +) + +// BlockClock is an abstraction over the past median time computation. The past +// median time computation is used in several consensus checks such as CSV, and +// also BIP 9 version bits. This interface allows callers to abstract away the +// computation of the past median time from the perspective of a given block +// header. +type BlockClock interface { + // PastMedianTime returns the past median time from the PoV of the + // passed block header. The past median time is the median time of the + // 11 blocks prior to the passed block header. + PastMedianTime(*wire.BlockHeader) (time.Time, error) +} + +// ConsensusDeploymentStarter determines if a given consensus deployment has +// started. A deployment has started once according to the current "time", the +// deployment is eligible for activation once a perquisite condition has +// passed. +type ConsensusDeploymentStarter interface { + // HasStarted returns true if the consensus deployment has started. + HasStarted(*wire.BlockHeader) (bool, error) +} + +// ClockConsensusDeploymentStarter is a more specialized version of the +// ConsensusDeploymentStarter that uses a BlockClock in order to determine if a +// deployment has started or not. +// +// NOTE: Any calls to HasStarted will _fail_ with ErrNoBlockClock if they +// happen before SynchronizeClock is executed. +type ClockConsensusDeploymentStarter interface { + ConsensusDeploymentStarter + + // SynchronizeClock synchronizes the target ConsensusDeploymentStarter + // with the current up-to date BlockClock. + SynchronizeClock(clock BlockClock) +} + +// ConsensusDeploymentEnder determines if a given consensus deployment has +// ended. A deployment has ended once according got eh current "time", the +// deployment is no longer eligible for activation. +type ConsensusDeploymentEnder interface { + // HasEnded returns true if the consensus deployment has ended. + HasEnded(*wire.BlockHeader) (bool, error) +} + +// ClockConsensusDeploymentEnder is a more specialized version of the +// ConsensusDeploymentEnder that uses a BlockClock in order to determine if a +// deployment has started or not. +// +// NOTE: Any calls to HasEnded will _fail_ with ErrNoBlockClock if they +// happen before SynchronizeClock is executed. +type ClockConsensusDeploymentEnder interface { + ConsensusDeploymentEnder + + // SynchronizeClock synchronizes the target ConsensusDeploymentStarter + // with the current up-to date BlockClock. + SynchronizeClock(clock BlockClock) +} + +// MedianTimeDeploymentStarter is a ClockConsensusDeploymentStarter that uses +// the median time past of a target block node to determine if a deployment has +// started. +type MedianTimeDeploymentStarter struct { + blockClock BlockClock + + startTime time.Time +} + +// NewMedianTimeDeploymentStarter returns a new instance of a +// MedianTimeDeploymentStarter for a given start time. +func NewMedianTimeDeploymentStarter(startTime time.Time) *MedianTimeDeploymentStarter { + return &MedianTimeDeploymentStarter{ + startTime: startTime, + } +} + +// SynchronizeClock synchronizes the target ConsensusDeploymentStarter with the +// current up-to date BlockClock. +func (m *MedianTimeDeploymentStarter) SynchronizeClock(clock BlockClock) { + m.blockClock = clock +} + +// HasStarted returns true if the consensus deployment has started. +func (m *MedianTimeDeploymentStarter) HasStarted(blkHeader *wire.BlockHeader) (bool, error) { + switch { + // If we haven't yet been synchronized with a block clock, then we + // can't tell the time, so we'll fail. + case m.blockClock == nil: + return false, ErrNoBlockClock + + // If the time is "zero", then the deployment has always started. + case m.startTime.IsZero(): + return true, nil + } + + medianTime, err := m.blockClock.PastMedianTime(blkHeader) + if err != nil { + return false, err + } + + // We check both after and equal here as after will fail for equivalent + // times, and we want to be inclusive. + return medianTime.After(m.startTime) || medianTime.Equal(m.startTime), nil +} + +// StartTime returns the raw start time of the deployment. +func (m *MedianTimeDeploymentStarter) StartTime() time.Time { + return m.startTime +} + +// A compile-time assertion to ensure MedianTimeDeploymentStarter implements +// the ClockConsensusDeploymentStarter interface. +var _ ClockConsensusDeploymentStarter = (*MedianTimeDeploymentStarter)(nil) + +// MedianTimeDeploymentEnder is a ClockConsensusDeploymentEnder that uses the +// median time past of a target block to determine if a deployment has ended. +type MedianTimeDeploymentEnder struct { + blockClock BlockClock + + endTime time.Time +} + +// NewMedianTimeDeploymentEnder returns a new instance of the +// MedianTimeDeploymentEnder anchored around the passed endTime. +func NewMedianTimeDeploymentEnder(endTime time.Time) *MedianTimeDeploymentEnder { + return &MedianTimeDeploymentEnder{ + endTime: endTime, + } +} + +// HasEnded returns true if the deployment has ended. +func (m *MedianTimeDeploymentEnder) HasEnded(blkHeader *wire.BlockHeader) (bool, error) { + switch { + // If we haven't yet been synchronized with a block clock, then we can't tell + // the time, so we'll we haven't yet been synchronized with a block + // clock, then w can't tell the time, so we'll fail. + case m.blockClock == nil: + return false, ErrNoBlockClock + + // If the time is "zero", then the deployment never ends. + case m.endTime.IsZero(): + return false, nil + } + + medianTime, err := m.blockClock.PastMedianTime(blkHeader) + if err != nil { + return false, err + } + + // We check both after and equal here as after will fail for equivalent + // times, and we want to be inclusive. + return medianTime.After(m.endTime) || medianTime.Equal(m.endTime), nil +} + +// MedianTimeDeploymentEnder returns the raw end time of the deployment. +func (m *MedianTimeDeploymentEnder) EndTime() time.Time { + return m.endTime +} + +// SynchronizeClock synchronizes the target ConsensusDeploymentEnder with the +// current up-to date BlockClock. +func (m *MedianTimeDeploymentEnder) SynchronizeClock(clock BlockClock) { + m.blockClock = clock +} + +// A compile-time assertion to ensure MedianTimeDeploymentEnder implements the +// ClockConsensusDeploymentStarter interface. +var _ ClockConsensusDeploymentEnder = (*MedianTimeDeploymentEnder)(nil) From 2b6370dfd73c010c693270d74fd49cbfde72a234 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 19 Mar 2021 17:16:26 -0700 Subject: [PATCH 0585/1056] chaincfg: use DeploymentStarter/DeploymentEnder instead of start/end times In this commit, we utilize the recently added ConsensusDeploymentStarter and ConsensusDeploymentEnder interfaces. Concrete implementations of this interface based on the median time past comparison are used now in the ConsensusDeployment struct instead of hard coded start/end times. Along the way, we had to switch to using the "zero time": time.Time{}, in place of 0 and math.MaxInt64 as comparison (After/Before) seems to be broken in the Go stdlib for times very far in the future. It appears Go isn't ready to handle the heat death of the universe. --- chaincfg/deployment_time_frame.go | 8 +- chaincfg/params.go | 173 ++++++++++++++++++++---------- rpcserver.go | 13 ++- 3 files changed, 134 insertions(+), 60 deletions(-) diff --git a/chaincfg/deployment_time_frame.go b/chaincfg/deployment_time_frame.go index 7178d9b26d..f26d429090 100644 --- a/chaincfg/deployment_time_frame.go +++ b/chaincfg/deployment_time_frame.go @@ -80,7 +80,9 @@ type MedianTimeDeploymentStarter struct { } // NewMedianTimeDeploymentStarter returns a new instance of a -// MedianTimeDeploymentStarter for a given start time. +// MedianTimeDeploymentStarter for a given start time. Using a time.Time +// instance where IsZero() is true, indicates that a deployment should be +// considered to always have been started. func NewMedianTimeDeploymentStarter(startTime time.Time) *MedianTimeDeploymentStarter { return &MedianTimeDeploymentStarter{ startTime: startTime, @@ -134,7 +136,9 @@ type MedianTimeDeploymentEnder struct { } // NewMedianTimeDeploymentEnder returns a new instance of the -// MedianTimeDeploymentEnder anchored around the passed endTime. +// MedianTimeDeploymentEnder anchored around the passed endTime. Using a +// time.Time instance where IsZero() is true, indicates that a deployment +// should be considered to never end. func NewMedianTimeDeploymentEnder(endTime time.Time) *MedianTimeDeploymentEnder { return &MedianTimeDeploymentEnder{ endTime: endTime, diff --git a/chaincfg/params.go b/chaincfg/params.go index a6d8d3e551..468106d5e7 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -8,7 +8,6 @@ import ( "encoding/binary" "encoding/hex" "errors" - "math" "math/big" "strings" "time" @@ -95,13 +94,13 @@ type ConsensusDeployment struct { // this particular soft-fork deployment refers to. BitNumber uint8 - // StartTime is the median block time after which voting on the - // deployment starts. - StartTime uint64 + // DeploymentStarter is used to determine if the given + // ConsensusDeployment has started or not. + DeploymentStarter ConsensusDeploymentStarter - // ExpireTime is the median block time after which the attempted - // deployment expires. - ExpireTime uint64 + // DeploymentEnder is used to determine if the given + // ConsensusDeployment has ended or not. + DeploymentEnder ConsensusDeploymentEnder } // Constants that define the deployment offset in the deployments field of the @@ -320,19 +319,31 @@ var MainNetParams = Params{ MinerConfirmationWindow: 2016, // Deployments: [DefinedDeployments]ConsensusDeployment{ DeploymentTestDummy: { - BitNumber: 28, - StartTime: 1199145601, // January 1, 2008 UTC - ExpireTime: 1230767999, // December 31, 2008 UTC + BitNumber: 28, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(11991456010, 0), // January 1, 2008 UTC + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1230767999, 0), // December 31, 2008 UTC + ), }, DeploymentCSV: { - BitNumber: 0, - StartTime: 1462060800, // May 1st, 2016 - ExpireTime: 1493596800, // May 1st, 2017 + BitNumber: 0, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1462060800, 0), // May 1st, 2016 + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1493596800, 0), // May 1st, 2017 + ), }, DeploymentSegwit: { - BitNumber: 1, - StartTime: 1479168000, // November 15, 2016 UTC - ExpireTime: 1510704000, // November 15, 2017 UTC. + BitNumber: 1, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1479168000, 0), // November 15, 2016 UTC + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1510704000, 0), // November 15, 2017 UTC. + ), }, }, @@ -396,19 +407,31 @@ var RegressionNetParams = Params{ MinerConfirmationWindow: 144, Deployments: [DefinedDeployments]ConsensusDeployment{ DeploymentTestDummy: { - BitNumber: 28, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires + BitNumber: 28, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), }, DeploymentCSV: { - BitNumber: 0, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires + BitNumber: 0, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), }, DeploymentSegwit: { - BitNumber: 1, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires. + BitNumber: 1, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires. + ), }, }, @@ -490,19 +513,31 @@ var TestNet3Params = Params{ MinerConfirmationWindow: 2016, Deployments: [DefinedDeployments]ConsensusDeployment{ DeploymentTestDummy: { - BitNumber: 28, - StartTime: 1199145601, // January 1, 2008 UTC - ExpireTime: 1230767999, // December 31, 2008 UTC + BitNumber: 28, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1199145601, 0), // January 1, 2008 UTC + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1230767999, 0), // December 31, 2008 UTC + ), }, DeploymentCSV: { - BitNumber: 0, - StartTime: 1456790400, // March 1st, 2016 - ExpireTime: 1493596800, // May 1st, 2017 + BitNumber: 0, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1456790400, 0), // March 1st, 2016 + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1493596800, 0), // May 1st, 2017 + ), }, DeploymentSegwit: { - BitNumber: 1, - StartTime: 1462060800, // May 1, 2016 UTC - ExpireTime: 1493596800, // May 1, 2017 UTC. + BitNumber: 1, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1462060800, 0), // May 1, 2016 UTC + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1493596800, 0), // May 1, 2017 UTC. + ), }, }, @@ -570,19 +605,31 @@ var SimNetParams = Params{ MinerConfirmationWindow: 100, Deployments: [DefinedDeployments]ConsensusDeployment{ DeploymentTestDummy: { - BitNumber: 28, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires + BitNumber: 28, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), }, DeploymentCSV: { - BitNumber: 0, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires + BitNumber: 0, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), }, DeploymentSegwit: { - BitNumber: 1, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires. + BitNumber: 1, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires. + ), }, }, @@ -665,24 +712,40 @@ func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params { MinerConfirmationWindow: 2016, Deployments: [DefinedDeployments]ConsensusDeployment{ DeploymentTestDummy: { - BitNumber: 28, - StartTime: 1199145601, // January 1, 2008 UTC - ExpireTime: 1230767999, // December 31, 2008 UTC + BitNumber: 28, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1199145601, 0), // January 1, 2008 UTC + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1230767999, 0), // December 31, 2008 UTC + ), }, DeploymentCSV: { - BitNumber: 29, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires + BitNumber: 29, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), }, DeploymentSegwit: { - BitNumber: 29, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires. + BitNumber: 29, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), }, DeploymentTaproot: { - BitNumber: 29, - StartTime: 0, // Always available for vote - ExpireTime: math.MaxInt64, // Never expires. + BitNumber: 29, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), }, }, diff --git a/rpcserver.go b/rpcserver.go index 8a4ecaac8d..1dd0659677 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -31,6 +31,7 @@ import ( "github.com/btcsuite/btcd/blockchain/indexers" "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" @@ -40,7 +41,6 @@ import ( "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/websocket" ) @@ -1289,11 +1289,18 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str // Finally, populate the soft-fork description with all the // information gathered above. + var startTime, endTime int64 + if starter, ok := deploymentDetails.DeploymentStarter.(*chaincfg.MedianTimeDeploymentStarter); ok { + startTime = starter.StartTime().Unix() + } + if ender, ok := deploymentDetails.DeploymentEnder.(*chaincfg.MedianTimeDeploymentEnder); ok { + endTime = ender.EndTime().Unix() + } chainInfo.SoftForks.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{ Status: strings.ToLower(statusString), Bit: deploymentDetails.BitNumber, - StartTime2: int64(deploymentDetails.StartTime), - Timeout: int64(deploymentDetails.ExpireTime), + StartTime2: startTime, + Timeout: endTime, } } From 298d6165be603b0efcd9d4ec48508fd1e0fad3fa Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 19 Mar 2021 17:18:57 -0700 Subject: [PATCH 0586/1056] blockchain: update version bits logic to use HasStarted/HasEnded for deployments In this commit, we update our version bits logic to use the newly added HasStarted and HasEnded methods for consensus deployments. Along the way, wee modify the thresholdConditionChecker` interface to be based off the new chaincfg interfaces. In addition, we add a new method `PastMedianTime`, in order to allow the chain itself to be used as a `chaincfg.BlockClock`. This serves to make the logic more generic in order to support both block height and time based soft fork timeouts. --- blockchain/chain.go | 16 ++++++++++- blockchain/common_test.go | 18 +++++++++++-- blockchain/thresholdstate.go | 51 ++++++++++++++++++++++------------- blockchain/versionbits.go | 52 ++++++++++++++++++++---------------- 4 files changed, 93 insertions(+), 44 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 92bfb26876..4d1a839441 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -11,12 +11,12 @@ import ( "sync" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -1757,6 +1757,20 @@ func New(config *Config) (*BlockChain, error) { deploymentCaches: newThresholdCaches(chaincfg.DefinedDeployments), } + // Ensure all the deployments are synchronized with our clock if + // needed. + for _, deployment := range b.chainParams.Deployments { + deploymentStarter := deployment.DeploymentStarter + if clockStarter, ok := deploymentStarter.(chaincfg.ClockConsensusDeploymentStarter); ok { + clockStarter.SynchronizeClock(&b) + } + + deploymentEnder := deployment.DeploymentEnder + if clockEnder, ok := deploymentEnder.(chaincfg.ClockConsensusDeploymentEnder); ok { + clockEnder.SynchronizeClock(&b) + } + } + // Initialize the chain state from the passed database. When the db // does not yet contain any chain state, both it and the chain state // will be initialized to contain only the genesis block. diff --git a/blockchain/common_test.go b/blockchain/common_test.go index 8de699c416..1973689ea1 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -14,13 +14,13 @@ import ( "strings" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -357,7 +357,7 @@ func newFakeChain(params *chaincfg.Params) *BlockChain { targetTimespan := int64(params.TargetTimespan / time.Second) targetTimePerBlock := int64(params.TargetTimePerBlock / time.Second) adjustmentFactor := params.RetargetAdjustmentFactor - return &BlockChain{ + b := &BlockChain{ chainParams: params, timeSource: NewMedianTime(), minRetargetTimespan: targetTimespan / adjustmentFactor, @@ -368,6 +368,20 @@ func newFakeChain(params *chaincfg.Params) *BlockChain { warningCaches: newThresholdCaches(vbNumBits), deploymentCaches: newThresholdCaches(chaincfg.DefinedDeployments), } + + for _, deployment := range params.Deployments { + deploymentStarter := deployment.DeploymentStarter + if clockStarter, ok := deploymentStarter.(chaincfg.ClockConsensusDeploymentStarter); ok { + clockStarter.SynchronizeClock(b) + } + + deploymentEnder := deployment.DeploymentEnder + if clockEnder, ok := deploymentEnder.(chaincfg.ClockConsensusDeploymentEnder); ok { + clockEnder.SynchronizeClock(b) + } + } + + return b } // newFakeNode creates a block node connected to the passed parent with the diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index 5da74a95af..6f3841bbe1 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -6,8 +6,10 @@ package blockchain import ( "fmt" + "time" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" ) // ThresholdState define the various threshold states used when voting on @@ -66,14 +68,13 @@ func (t ThresholdState) String() string { // thresholdConditionChecker provides a generic interface that is invoked to // determine when a consensus rule change threshold should be changed. type thresholdConditionChecker interface { - // BeginTime returns the unix timestamp for the median block time after - // which voting on a rule change starts (at the next window). - BeginTime() uint64 + // HasStarted returns true if based on the passed block blockNode the + // consensus is eligible for deployment. + HasStarted(*blockNode) bool - // EndTime returns the unix timestamp for the median block time after - // which an attempted rule change fails if it has not already been - // locked in or activated. - EndTime() uint64 + // HasEnded returns true if the target consensus rule change has expired + // or timed out. + HasEnded(*blockNode) bool // RuleChangeActivationThreshold is the number of blocks for which the // condition must be true in order to lock in a rule change. @@ -121,6 +122,27 @@ func newThresholdCaches(numCaches uint32) []thresholdStateCache { return caches } +// PastMedianTime returns the past median time from the PoV of the passed block +// header. The past median time is the median time of the 11 blocks prior to +// the passed block header. +// +// NOTE: This is part of the chainfg.BlockClock interface +func (b *BlockChain) PastMedianTime(blockHeader *wire.BlockHeader) (time.Time, error) { + prevHash := blockHeader.PrevBlock + prevNode := b.index.LookupNode(&prevHash) + + // If we can't find the previous node, then we can't compute the block + // time since it requires us to walk backwards from this node. + if prevNode == nil { + return time.Time{}, fmt.Errorf("blockHeader(%v) has no "+ + "previous node", blockHeader.BlockHash()) + } + + blockNode := newBlockNode(blockHeader, prevNode) + + return blockNode.CalcPastMedianTime(), nil +} + // thresholdState returns the current rule change threshold state for the block // AFTER the given node and deployment ID. The cache is used to ensure the // threshold states for previous windows are only calculated once. @@ -150,13 +172,9 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit break } - // The start and expiration times are based on the median block - // time, so calculate it now. - medianTime := prevNode.CalcPastMedianTime() - // The state is simply defined if the start time hasn't been // been reached yet. - if uint64(medianTime.Unix()) < checker.BeginTime() { + if !checker.HasStarted(prevNode) { cache.Update(&prevNode.hash, ThresholdDefined) break } @@ -192,9 +210,7 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit case ThresholdDefined: // The deployment of the rule change fails if it expires // before it is accepted and locked in. - medianTime := prevNode.CalcPastMedianTime() - medianTimeUnix := uint64(medianTime.Unix()) - if medianTimeUnix >= checker.EndTime() { + if checker.HasEnded(prevNode) { state = ThresholdFailed break } @@ -202,15 +218,14 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit // The state for the rule moves to the started state // once its start time has been reached (and it hasn't // already expired per the above). - if medianTimeUnix >= checker.BeginTime() { + if checker.HasStarted(prevNode) { state = ThresholdStarted } case ThresholdStarted: // The deployment of the rule change fails if it expires // before it is accepted and locked in. - medianTime := prevNode.CalcPastMedianTime() - if uint64(medianTime.Unix()) >= checker.EndTime() { + if checker.HasEnded(prevNode) { state = ThresholdFailed break } diff --git a/blockchain/versionbits.go b/blockchain/versionbits.go index 28fcde7b69..dbe4eb1d61 100644 --- a/blockchain/versionbits.go +++ b/blockchain/versionbits.go @@ -5,8 +5,6 @@ package blockchain import ( - "math" - "github.com/btcsuite/btcd/chaincfg" ) @@ -42,27 +40,26 @@ type bitConditionChecker struct { // interface. var _ thresholdConditionChecker = bitConditionChecker{} -// BeginTime returns the unix timestamp for the median block time after which -// voting on a rule change starts (at the next window). +// HasStarted returns true if based on the passed block blockNode the consensus +// is eligible for deployment. // -// Since this implementation checks for unknown rules, it returns 0 so the rule +// Since this implementation checks for unknown rules, it returns true so // is always treated as active. // // This is part of the thresholdConditionChecker interface implementation. -func (c bitConditionChecker) BeginTime() uint64 { - return 0 +func (c bitConditionChecker) HasStarted(_ *blockNode) bool { + return true } -// EndTime returns the unix timestamp for the median block time after which an -// attempted rule change fails if it has not already been locked in or -// activated. +// HasStarted returns true if based on the passed block blockNode the consensus +// is eligible for deployment. // -// Since this implementation checks for unknown rules, it returns the maximum -// possible timestamp so the rule is always treated as active. +// Since this implementation checks for unknown rules, it returns false so the +// rule is always treated as active. // // This is part of the thresholdConditionChecker interface implementation. -func (c bitConditionChecker) EndTime() uint64 { - return math.MaxUint64 +func (c bitConditionChecker) HasEnded(_ *blockNode) bool { + return false } // RuleChangeActivationThreshold is the number of blocks for which the condition @@ -123,27 +120,36 @@ type deploymentChecker struct { // interface. var _ thresholdConditionChecker = deploymentChecker{} -// BeginTime returns the unix timestamp for the median block time after which -// voting on a rule change starts (at the next window). +// HasEnded returns true if the target consensus rule change has expired +// or timed out (at the next window). // // This implementation returns the value defined by the specific deployment the // checker is associated with. // // This is part of the thresholdConditionChecker interface implementation. -func (c deploymentChecker) BeginTime() uint64 { - return c.deployment.StartTime +func (c deploymentChecker) HasStarted(blkNode *blockNode) bool { + // Can't fail as we make sure to set the clock above when we + // instantiate *BlockChain. + header := blkNode.Header() + started, _ := c.deployment.DeploymentStarter.HasStarted(&header) + + return started } -// EndTime returns the unix timestamp for the median block time after which an -// attempted rule change fails if it has not already been locked in or -// activated. +// HasEnded returns true if the target consensus rule change has expired +// or timed out. // // This implementation returns the value defined by the specific deployment the // checker is associated with. // // This is part of the thresholdConditionChecker interface implementation. -func (c deploymentChecker) EndTime() uint64 { - return c.deployment.ExpireTime +func (c deploymentChecker) HasEnded(blkNode *blockNode) bool { + // Can't fail as we make sure to set the clock above when we + // instantiate *BlockChain. + header := blkNode.Header() + ended, _ := c.deployment.DeploymentEnder.HasEnded(&header) + + return ended } // RuleChangeActivationThreshold is the number of blocks for which the condition From 0556c7084f37418e1223b6e9e2b79a0c86591c95 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 11 Jan 2022 19:58:44 -0800 Subject: [PATCH 0587/1056] build: don't run the integration tests w/ -race --- Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5db0871ad1..6dc6d9471b 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ DEPGET := cd /tmp && GO111MODULE=on go get -v GOBUILD := GO111MODULE=on go build -v GOINSTALL := GO111MODULE=on go install -v DEV_TAGS := rpctest -GOTEST := GO111MODULE=on go test -v -tags=$(DEV_TAGS) +GOTEST_DEV = GO111MODULE=on go test -v -tags=$(DEV_TAGS) +GOTEST := GO111MODULE=on go test -v GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*") @@ -78,9 +79,9 @@ check: unit unit: @$(call print, "Running unit tests.") - $(GOTEST) ./... -test.timeout=20m - cd btcutil; $(GOTEST) ./... -test.timeout=20m - cd btcutil/psbt; $(GOTEST) ./... -test.timeout=20m + $(GOTEST_DEV) ./... -test.timeout=20m + cd btcutil; $(GOTEST_DEV) ./... -test.timeout=20m + cd btcutil/psbt; $(GOTEST_DEV) ./... -test.timeout=20m unit-cover: $(GOACC_BIN) @$(call print, "Running unit coverage tests.") From 38737a8ae35cce8f63f2d655c8f3bf02de38036a Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 13 Jan 2022 17:29:54 -0800 Subject: [PATCH 0588/1056] chainparams: add new DeploymentTestDummyMinActivation In this commit, we add a new "dummy" deployment that adds the new params used to activate taproot. We chose to add a new deployment as unlike the bitcoind codebase, we don't currently "bury" soft forks that have happened in the past (hard code an activation height). The old taproot deployment has been removed as with the way the array works, a deployment needs to be defined for _all_ networks. --- chaincfg/params.go | 78 ++++++++++++++++++++++++++++++++++++++++------ rpcserver.go | 6 ++-- 2 files changed, 72 insertions(+), 12 deletions(-) diff --git a/chaincfg/params.go b/chaincfg/params.go index 468106d5e7..c8ddc85d69 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -94,6 +94,19 @@ type ConsensusDeployment struct { // this particular soft-fork deployment refers to. BitNumber uint8 + // MinActivationHeight is an optional field that when set (default + // value being zero), modifies the traditional BIP 9 state machine by + // only transitioning from LockedIn to Active once the block height is + // greater than (or equal to) thus specified height. + MinActivationHeight uint32 + + // CustomActivationThreshold if set (non-zero), will _override_ the + // existing RuleChangeActivationThreshold value set at the + // network/chain level. This value divided by the active + // MinerConfirmationWindow denotes the threshold required for + // activation. A value of 1815 block denotes a 90% threshold. + CustomActivationThreshold uint32 + // DeploymentStarter is used to determine if the given // ConsensusDeployment has started or not. DeploymentStarter ConsensusDeploymentStarter @@ -111,6 +124,12 @@ const ( // purposes. DeploymentTestDummy = iota + // DeploymentTestDummyMinActivation defines the rule change deployment + // ID for testing purposes. This differs from the DeploymentTestDummy + // in that it specifies the newer params the taproot fork used for + // activation: a custom threshold and a min activation height. + DeploymentTestDummyMinActivation + // DeploymentCSV defines the rule change deployment ID for the CSV // soft-fork package. The CSV package includes the deployment of BIPS // 68, 112, and 113. @@ -121,11 +140,6 @@ const ( // includes the deployment of BIPS 141, 142, 144, 145, 147 and 173. DeploymentSegwit - // DeploymentTaproot defines the rule change deployment ID for the - // Taproot (+Schnorr) soft-fork package. The taproot package includes - // the deployment of BIPS 340, 341 and 342. - DeploymentTaproot - // NOTE: DefinedDeployments must always come last since it is used to // determine how many defined deployments there currently are. @@ -327,6 +341,17 @@ var MainNetParams = Params{ time.Unix(1230767999, 0), // December 31, 2008 UTC ), }, + DeploymentTestDummyMinActivation: { + BitNumber: 22, + CustomActivationThreshold: 1815, // Only needs 90% hash rate. + MinActivationHeight: 10_0000, // Can only activate after height 10k. + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), + }, DeploymentCSV: { BitNumber: 0, DeploymentStarter: NewMedianTimeDeploymentStarter( @@ -415,6 +440,17 @@ var RegressionNetParams = Params{ time.Time{}, // Never expires ), }, + DeploymentTestDummyMinActivation: { + BitNumber: 22, + CustomActivationThreshold: 72, // Only needs 50% hash rate. + MinActivationHeight: 600, // Can only activate after height 600. + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), + }, DeploymentCSV: { BitNumber: 0, DeploymentStarter: NewMedianTimeDeploymentStarter( @@ -521,6 +557,17 @@ var TestNet3Params = Params{ time.Unix(1230767999, 0), // December 31, 2008 UTC ), }, + DeploymentTestDummyMinActivation: { + BitNumber: 22, + CustomActivationThreshold: 1815, // Only needs 90% hash rate. + MinActivationHeight: 10_0000, // Can only activate after height 10k. + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), + }, DeploymentCSV: { BitNumber: 0, DeploymentStarter: NewMedianTimeDeploymentStarter( @@ -613,6 +660,17 @@ var SimNetParams = Params{ time.Time{}, // Never expires ), }, + DeploymentTestDummyMinActivation: { + BitNumber: 22, + CustomActivationThreshold: 50, // Only needs 50% hash rate. + MinActivationHeight: 600, // Can only activate after height 600. + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), + }, DeploymentCSV: { BitNumber: 0, DeploymentStarter: NewMedianTimeDeploymentStarter( @@ -720,8 +778,10 @@ func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params { time.Unix(1230767999, 0), // December 31, 2008 UTC ), }, - DeploymentCSV: { - BitNumber: 29, + DeploymentTestDummyMinActivation: { + BitNumber: 22, + CustomActivationThreshold: 1815, // Only needs 90% hash rate. + MinActivationHeight: 10_0000, // Can only activate after height 10k. DeploymentStarter: NewMedianTimeDeploymentStarter( time.Time{}, // Always available for vote ), @@ -729,7 +789,7 @@ func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params { time.Time{}, // Never expires ), }, - DeploymentSegwit: { + DeploymentCSV: { BitNumber: 29, DeploymentStarter: NewMedianTimeDeploymentStarter( time.Time{}, // Always available for vote @@ -738,7 +798,7 @@ func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params { time.Time{}, // Never expires ), }, - DeploymentTaproot: { + DeploymentSegwit: { BitNumber: 29, DeploymentStarter: NewMedianTimeDeploymentStarter( time.Time{}, // Always available for vote diff --git a/rpcserver.go b/rpcserver.go index 1dd0659677..8c4b765266 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1250,15 +1250,15 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str case chaincfg.DeploymentTestDummy: forkName = "dummy" + case chaincfg.DeploymentTestDummyMinActivation: + forkName = "dummy-min-activation" + case chaincfg.DeploymentCSV: forkName = "csv" case chaincfg.DeploymentSegwit: forkName = "segwit" - case chaincfg.DeploymentTaproot: - forkName = "taproot" - default: return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInternal.Code, From c6b66ee79c77f3ca41de8844de14ade81d0a1b19 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 13 Jan 2022 17:42:07 -0800 Subject: [PATCH 0589/1056] blockchain+integration: add support for min activation height and custom thresholds In this commit, we extend the existing version bits state machine to add support for the new minimum activation height and custom block threshold for activation. We then extend the existing BIP 9 tests (tho this isn't really BIP 9 anymore...) to exercise the new min activation height logic. --- blockchain/thresholdstate.go | 68 +++++++++++++++++++++++++++--------- blockchain/versionbits.go | 63 +++++++++++++++++++++++++++++++++ integration/bip0009_test.go | 44 +++++++++++++++++++++-- 3 files changed, 157 insertions(+), 18 deletions(-) diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index 6f3841bbe1..29b62e468f 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -72,8 +72,8 @@ type thresholdConditionChecker interface { // consensus is eligible for deployment. HasStarted(*blockNode) bool - // HasEnded returns true if the target consensus rule change has expired - // or timed out. + // HasEnded returns true if the target consensus rule change has + // expired or timed out. HasEnded(*blockNode) bool // RuleChangeActivationThreshold is the number of blocks for which the @@ -84,10 +84,23 @@ type thresholdConditionChecker interface { // state retarget window. MinerConfirmationWindow() uint32 - // Condition returns whether or not the rule change activation condition - // has been met. This typically involves checking whether or not the - // bit associated with the condition is set, but can be more complex as - // needed. + // EligibleToActivate returns true if a custom deployment can + // transition from the LockedIn to the Active state. For normal + // deployments, this always returns true. However, some deployments add + // extra rules like a minimum activation height, which can be + // abstracted into a generic arbitrary check at the final state via + // this method. + EligibleToActivate(*blockNode) bool + + // IsSpeedy returns true if this is to be a "speedy" deployment. A + // speedy deployment differs from a regular one in that only after a + // miner block confirmation window can the deployment expire. + IsSpeedy() bool + + // Condition returns whether or not the rule change activation + // condition has been met. This typically involves checking whether or + // not the bit associated with the condition is set, but can be more + // complex as needed. Condition(*blockNode) (bool, error) } @@ -208,9 +221,11 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit switch state { case ThresholdDefined: - // The deployment of the rule change fails if it expires - // before it is accepted and locked in. - if checker.HasEnded(prevNode) { + // The deployment of the rule change fails if it + // expires before it is accepted and locked in. However + // speed deployments can only transition to failed + // after a confirmation window. + if !checker.IsSpeedy() && checker.HasEnded(prevNode) { state = ThresholdFailed break } @@ -223,9 +238,10 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit } case ThresholdStarted: - // The deployment of the rule change fails if it expires - // before it is accepted and locked in. - if checker.HasEnded(prevNode) { + // The deployment of the rule change fails if it + // expires before it is accepted and locked in, but + // only if this deployment isn't speedy. + if !checker.IsSpeedy() && checker.HasEnded(prevNode) { state = ThresholdFailed break } @@ -248,17 +264,37 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit countNode = countNode.parent } + switch { // The state is locked in if the number of blocks in the // period that voted for the rule change meets the // activation threshold. - if count >= checker.RuleChangeActivationThreshold() { + case count >= checker.RuleChangeActivationThreshold(): state = ThresholdLockedIn + + // If this is a speedy deployment, we didn't meet the + // threshold above, and the deployment has expired, then + // we transition to failed. + case checker.IsSpeedy() && checker.HasEnded(prevNode): + state = ThresholdFailed } case ThresholdLockedIn: - // The new rule becomes active when its previous state - // was locked in. - state = ThresholdActive + // At this point, we'll consult the deployment see if a + // custom deployment has any other arbitrary conditions + // that need to pass before execution. This might be a + // minimum activation height or another policy. + // + // If we aren't eligible to active yet, then we'll just + // stay in the locked in position. + if !checker.EligibleToActivate(prevNode) { + state = ThresholdLockedIn + + } else { + // The new rule becomes active when its + // previous state was locked in assuming it's + // now eligible to activate. + state = ThresholdActive + } // Nothing to do if the previous state is active or failed since // they are both terminal states. diff --git a/blockchain/versionbits.go b/blockchain/versionbits.go index dbe4eb1d61..0d1f898c0a 100644 --- a/blockchain/versionbits.go +++ b/blockchain/versionbits.go @@ -108,6 +108,32 @@ func (c bitConditionChecker) Condition(node *blockNode) (bool, error) { return uint32(expectedVersion)&conditionMask == 0, nil } +// EligibleToActivate returns true if a custom deployment can transition from +// the LockedIn to the Active state. For normal deployments, this always +// returns true. However, some deployments add extra rules like a minimum +// activation height, which can be abstracted into a generic arbitrary check at +// the final state via this method. +// +// This implementation always returns true, as it's used to warn about other +// unknown deployments. +// +// This is part of the thresholdConditionChecker interface implementation. +func (c bitConditionChecker) EligibleToActivate(blkNode *blockNode) bool { + return true +} + +// IsSpeedy returns true if this is to be a "speedy" deployment. A speedy +// deployment differs from a regular one in that only after a miner block +// confirmation window can the deployment expire. +// +// This implementation returns false, as we want to always be warned if +// something is about to activate. +// +// This is part of the thresholdConditionChecker interface implementation. +func (c bitConditionChecker) IsSpeedy() bool { + return false +} + // deploymentChecker provides a thresholdConditionChecker which can be used to // test a specific deployment rule. This is required for properly detecting // and activating consensus rule changes. @@ -160,6 +186,12 @@ func (c deploymentChecker) HasEnded(blkNode *blockNode) bool { // // This is part of the thresholdConditionChecker interface implementation. func (c deploymentChecker) RuleChangeActivationThreshold() uint32 { + // Some deployments like taproot used a custom activation threshold + // that ovverides the network level threshold. + if c.deployment.CustomActivationThreshold != 0 { + return c.deployment.CustomActivationThreshold + } + return c.chain.chainParams.RuleChangeActivationThreshold } @@ -174,6 +206,37 @@ func (c deploymentChecker) MinerConfirmationWindow() uint32 { return c.chain.chainParams.MinerConfirmationWindow } +// EligibleToActivate returns true if a custom deployment can transition from +// the LockedIn to the Active state. For normal deployments, this always +// returns true. However, some deployments add extra rules like a minimum +// activation height, which can be abstracted into a generic arbitrary check at +// the final state via this method. +// +// This implementation always returns true, unless a minimum activation height +// is specified. +// +// This is part of the thresholdConditionChecker interface implementation. +func (c deploymentChecker) EligibleToActivate(blkNode *blockNode) bool { + // No activation height, so it's always ready to go. + if c.deployment.MinActivationHeight == 0 { + return true + } + + // If the _next_ block (as this is the prior block to the one being + // connected is the min height or beyond, then this can activate. + return uint32(blkNode.height)+1 >= c.deployment.MinActivationHeight +} + +// IsSpeedy returns true if this is to be a "speedy" deployment. A speedy +// deployment differs from a regular one in that only after a miner block +// confirmation window can the deployment expire. This implementation returns +// true if a min activation height is set. +// +// This is part of the thresholdConditionChecker interface implementation. +func (c deploymentChecker) IsSpeedy() bool { + return c.deployment.MinActivationHeight != 0 +} + // Condition returns true when the specific bit defined by the deployment // associated with the checker is set. // diff --git a/integration/bip0009_test.go b/integration/bip0009_test.go index 9bdec34fbb..67b15f3a5b 100644 --- a/integration/bip0009_test.go +++ b/integration/bip0009_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // This file is ignored during the regular tests due to the following build tag. +//go:build rpctest // +build rpctest package integration @@ -196,6 +197,9 @@ func testBIP0009(t *testing.T, forkKey string, deploymentID uint32) { } deployment := &r.ActiveNet.Deployments[deploymentID] activationThreshold := r.ActiveNet.RuleChangeActivationThreshold + if deployment.CustomActivationThreshold != 0 { + activationThreshold = deployment.CustomActivationThreshold + } signalForkVersion := int32(1< Date: Sun, 23 Jan 2022 19:06:21 -0800 Subject: [PATCH 0590/1056] blockchain: refactor new thresholdState method, test BIP9 transitions In this commit, we extract the BIP 9 state transition logic from the thresholdState method into a new thresholdStateTransition function that allows us to test all the defined state transitions, including the modified "speedy trial" logic. --- blockchain/thresholdstate.go | 182 ++++++++++++++++------------- blockchain/thresholdstate_test.go | 184 ++++++++++++++++++++++++++++++ 2 files changed, 285 insertions(+), 81 deletions(-) diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index 29b62e468f..b96c9bd3db 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -156,6 +156,99 @@ func (b *BlockChain) PastMedianTime(blockHeader *wire.BlockHeader) (time.Time, e return blockNode.CalcPastMedianTime(), nil } +// thresholdStateTransition given a state, a previous node, and a toeholds +// checker, this function transitions to the next state as defined by BIP 009. +// This state transition function is also aware of the "speedy trial" +// modifications made to BIP 0009 as part of the taproot softfork activation. +func thresholdStateTransition(state ThresholdState, prevNode *blockNode, + checker thresholdConditionChecker, + confirmationWindow int32) (ThresholdState, error) { + + switch state { + case ThresholdDefined: + // The deployment of the rule change fails if it + // expires before it is accepted and locked in. However + // speed deployments can only transition to failed + // after a confirmation window. + if !checker.IsSpeedy() && checker.HasEnded(prevNode) { + state = ThresholdFailed + break + } + + // The state for the rule moves to the started state + // once its start time has been reached (and it hasn't + // already expired per the above). + if checker.HasStarted(prevNode) { + state = ThresholdStarted + } + + case ThresholdStarted: + // The deployment of the rule change fails if it + // expires before it is accepted and locked in, but + // only if this deployment isn't speedy. + if !checker.IsSpeedy() && checker.HasEnded(prevNode) { + state = ThresholdFailed + break + } + + // At this point, the rule change is still being voted + // on by the miners, so iterate backwards through the + // confirmation window to count all of the votes in it. + var count uint32 + countNode := prevNode + for i := int32(0); i < confirmationWindow; i++ { + condition, err := checker.Condition(countNode) + if err != nil { + return ThresholdFailed, err + } + if condition { + count++ + } + + // Get the previous block node. + countNode = countNode.parent + } + + switch { + // The state is locked in if the number of blocks in the + // period that voted for the rule change meets the + // activation threshold. + case count >= checker.RuleChangeActivationThreshold(): + state = ThresholdLockedIn + + // If this is a speedy deployment, we didn't meet the + // threshold above, and the deployment has expired, then + // we transition to failed. + case checker.IsSpeedy() && checker.HasEnded(prevNode): + state = ThresholdFailed + } + + case ThresholdLockedIn: + // At this point, we'll consult the deployment see if a + // custom deployment has any other arbitrary conditions + // that need to pass before execution. This might be a + // minimum activation height or another policy. + // + // If we aren't eligible to active yet, then we'll just + // stay in the locked in position. + if !checker.EligibleToActivate(prevNode) { + state = ThresholdLockedIn + } else { + // The new rule becomes active when its + // previous state was locked in assuming it's + // now eligible to activate. + state = ThresholdActive + } + + // Nothing to do if the previous state is active or failed since + // they are both terminal states. + case ThresholdActive: + case ThresholdFailed: + } + + return state, nil +} + // thresholdState returns the current rule change threshold state for the block // AFTER the given node and deployment ID. The cache is used to ensure the // threshold states for previous windows are only calculated once. @@ -216,90 +309,17 @@ func (b *BlockChain) thresholdState(prevNode *blockNode, checker thresholdCondit // Since each threshold state depends on the state of the previous // window, iterate starting from the oldest unknown window. + var err error for neededNum := len(neededStates) - 1; neededNum >= 0; neededNum-- { prevNode := neededStates[neededNum] - switch state { - case ThresholdDefined: - // The deployment of the rule change fails if it - // expires before it is accepted and locked in. However - // speed deployments can only transition to failed - // after a confirmation window. - if !checker.IsSpeedy() && checker.HasEnded(prevNode) { - state = ThresholdFailed - break - } - - // The state for the rule moves to the started state - // once its start time has been reached (and it hasn't - // already expired per the above). - if checker.HasStarted(prevNode) { - state = ThresholdStarted - } - - case ThresholdStarted: - // The deployment of the rule change fails if it - // expires before it is accepted and locked in, but - // only if this deployment isn't speedy. - if !checker.IsSpeedy() && checker.HasEnded(prevNode) { - state = ThresholdFailed - break - } - - // At this point, the rule change is still being voted - // on by the miners, so iterate backwards through the - // confirmation window to count all of the votes in it. - var count uint32 - countNode := prevNode - for i := int32(0); i < confirmationWindow; i++ { - condition, err := checker.Condition(countNode) - if err != nil { - return ThresholdFailed, err - } - if condition { - count++ - } - - // Get the previous block node. - countNode = countNode.parent - } - - switch { - // The state is locked in if the number of blocks in the - // period that voted for the rule change meets the - // activation threshold. - case count >= checker.RuleChangeActivationThreshold(): - state = ThresholdLockedIn - - // If this is a speedy deployment, we didn't meet the - // threshold above, and the deployment has expired, then - // we transition to failed. - case checker.IsSpeedy() && checker.HasEnded(prevNode): - state = ThresholdFailed - } - - case ThresholdLockedIn: - // At this point, we'll consult the deployment see if a - // custom deployment has any other arbitrary conditions - // that need to pass before execution. This might be a - // minimum activation height or another policy. - // - // If we aren't eligible to active yet, then we'll just - // stay in the locked in position. - if !checker.EligibleToActivate(prevNode) { - state = ThresholdLockedIn - - } else { - // The new rule becomes active when its - // previous state was locked in assuming it's - // now eligible to activate. - state = ThresholdActive - } - - // Nothing to do if the previous state is active or failed since - // they are both terminal states. - case ThresholdActive: - case ThresholdFailed: + // Based on the current state, the previous node, and the + // condition checker, transition to the next threshold state. + state, err = thresholdStateTransition( + state, prevNode, checker, confirmationWindow, + ) + if err != nil { + return state, err } // Update the cache to avoid recalculating the state in the diff --git a/blockchain/thresholdstate_test.go b/blockchain/thresholdstate_test.go index c65f5a4465..8d527137e3 100644 --- a/blockchain/thresholdstate_test.go +++ b/blockchain/thresholdstate_test.go @@ -132,3 +132,187 @@ nextTest: } } } + +type customDeploymentChecker struct { + started bool + ended bool + + eligible bool + + isSpeedy bool + + conditionTrue bool + + activationThreshold uint32 + minerWindow uint32 +} + +func (c customDeploymentChecker) HasStarted(_ *blockNode) bool { + return c.started +} + +func (c customDeploymentChecker) HasEnded(_ *blockNode) bool { + return c.ended +} + +func (c customDeploymentChecker) RuleChangeActivationThreshold() uint32 { + return c.activationThreshold +} + +func (c customDeploymentChecker) MinerConfirmationWindow() uint32 { + return c.minerWindow +} + +func (c customDeploymentChecker) EligibleToActivate(_ *blockNode) bool { + return c.eligible +} + +func (c customDeploymentChecker) IsSpeedy() bool { + return c.isSpeedy +} + +func (c customDeploymentChecker) Condition(_ *blockNode) (bool, error) { + return c.conditionTrue, nil +} + +// TestThresholdStateTransition tests that the thresholdStateTransition +// properly implements the BIP 009 state machine, along with the speedy trial +// augments. +func TestThresholdStateTransition(t *testing.T) { + t.Parallel() + + // Prev node always points back to itself, effectively creating an + // infinite chain for the purposes of this test. + prevNode := &blockNode{} + prevNode.parent = prevNode + + window := int32(2016) + + testCases := []struct { + currentState ThresholdState + nextState ThresholdState + + checker thresholdConditionChecker + }{ + // From defined, we stay there if we haven't started the + // window, and the window hasn't ended. + { + currentState: ThresholdDefined, + nextState: ThresholdDefined, + + checker: &customDeploymentChecker{}, + }, + + // From defined, we go to failed if the window has ended, and + // this isn't a speedy trial. + { + currentState: ThresholdDefined, + nextState: ThresholdFailed, + + checker: &customDeploymentChecker{ + ended: true, + }, + }, + + // From defined, even if the window has ended, we go to started + // if this isn't a speedy trial. + { + currentState: ThresholdDefined, + nextState: ThresholdStarted, + + checker: &customDeploymentChecker{ + started: true, + }, + }, + + // From started, we go to failed if this isn't speed, and the + // deployment has ended. + { + currentState: ThresholdStarted, + nextState: ThresholdFailed, + + checker: &customDeploymentChecker{ + ended: true, + }, + }, + + // From started, we go to locked in if the window passed the + // condition. + { + currentState: ThresholdStarted, + nextState: ThresholdLockedIn, + + checker: &customDeploymentChecker{ + started: true, + conditionTrue: true, + }, + }, + + // From started, we go to failed if this is a speedy trial, and + // the condition wasn't met in the window. + { + currentState: ThresholdStarted, + nextState: ThresholdFailed, + + checker: &customDeploymentChecker{ + started: true, + ended: true, + isSpeedy: true, + conditionTrue: false, + activationThreshold: 1815, + }, + }, + + // From locked in, we go straight to active is this isn't a + // speedy trial. + { + currentState: ThresholdLockedIn, + nextState: ThresholdActive, + + checker: &customDeploymentChecker{ + eligible: true, + }, + }, + + // From locked in, we remain in locked in if we're not yet + // eligible to activate. + { + currentState: ThresholdLockedIn, + nextState: ThresholdLockedIn, + + checker: &customDeploymentChecker{}, + }, + + // From active, we always stay here. + { + currentState: ThresholdActive, + nextState: ThresholdActive, + + checker: &customDeploymentChecker{}, + }, + + // From failed, we always stay here. + { + currentState: ThresholdFailed, + nextState: ThresholdFailed, + + checker: &customDeploymentChecker{}, + }, + } + for i, testCase := range testCases { + nextState, err := thresholdStateTransition( + testCase.currentState, prevNode, testCase.checker, + window, + ) + if err != nil { + t.Fatalf("#%v: unable to transition to next "+ + "state: %v", i, err) + } + + if nextState != testCase.nextState { + t.Fatalf("#%v: incorrect state transition: "+ + "expected %v got %v", i, testCase.nextState, + nextState) + } + } +} From 0b245cca4f4c0d091a4466a77b9de70523dc1af0 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 13 Jan 2022 17:51:30 -0800 Subject: [PATCH 0591/1056] btcjson+rpc: add min activation height to soft fork RPC response --- btcjson/chainsvrresults.go | 15 ++++++++------- rpcserver.go | 9 +++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 8062d9d990..7b771b12f7 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -11,8 +11,8 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/wire" ) // GetBlockHeaderVerboseResult models the data from the getblockheader command when @@ -172,12 +172,13 @@ type SoftForkDescription struct { // Bip9SoftForkDescription describes the current state of a defined BIP0009 // version bits soft-fork. type Bip9SoftForkDescription struct { - Status string `json:"status"` - Bit uint8 `json:"bit"` - StartTime1 int64 `json:"startTime"` - StartTime2 int64 `json:"start_time"` - Timeout int64 `json:"timeout"` - Since int32 `json:"since"` + Status string `json:"status"` + Bit uint8 `json:"bit"` + StartTime1 int64 `json:"startTime"` + StartTime2 int64 `json:"start_time"` + Timeout int64 `json:"timeout"` + Since int32 `json:"since"` + MinActivationHeight int32 `json:"min_activation_height"` } // StartTime returns the starting time of the softfork as a Unix epoch. diff --git a/rpcserver.go b/rpcserver.go index 8c4b765266..e000af5a4f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1297,10 +1297,11 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str endTime = ender.EndTime().Unix() } chainInfo.SoftForks.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{ - Status: strings.ToLower(statusString), - Bit: deploymentDetails.BitNumber, - StartTime2: startTime, - Timeout: endTime, + Status: strings.ToLower(statusString), + Bit: deploymentDetails.BitNumber, + StartTime2: startTime, + Timeout: endTime, + MinActivationHeight: int32(deploymentDetails.MinActivationHeight), } } From 87e8fe92c9328f971044389ed768ea3cc5c6b3d5 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 18 Nov 2021 18:25:56 -0800 Subject: [PATCH 0592/1056] btcec: convert package into go module, alias to dcrec In this commit, we turn the package into a new Go module (version 2), and then port over the current set of types and functions to mainly alias to the more optimized and maintained dcrec variant. Taking a look at the benchmarks, most operations other than normalization (which IIRC is a bit slower now due to constant time fixes) enjoy some nice speeds up: ``` benchcmp is deprecated in favor of benchstat: https://pkg.go.dev/golang.org/x/perf/cmd/benchstat benchmark old ns/op new ns/op delta BenchmarkAddJacobian-8 464 328 -29.20% BenchmarkAddJacobianNotZOne-8 1138 372 -67.27% BenchmarkScalarBaseMult-8 47336 31531 -33.39% BenchmarkScalarBaseMultLarge-8 42465 32057 -24.51% BenchmarkScalarMult-8 123355 117579 -4.68% BenchmarkNAF-8 582 168 -71.12% BenchmarkSigVerify-8 175414 120794 -31.14% BenchmarkFieldNormalize-8 23.8 24.4 +2.39% BenchmarkParseCompressedPubKey-8 24282 10907 -55.08% ``` --- btcec/README.md | 36 +- btcec/bench_test.go | 162 +++-- btcec/btcec.go | 961 +-------------------------- btcec/btcec_test.go | 245 +++---- btcec/ciphering.go | 204 +----- btcec/ciphering_test.go | 147 +---- btcec/curve.go | 60 ++ btcec/error.go | 16 + btcec/example_test.go | 94 +-- btcec/field.go | 1395 ++------------------------------------- btcec/field_test.go | 1048 +++++++++++++---------------- btcec/genprecomps.go | 63 -- btcec/gensecp256k1.go | 203 ------ btcec/go.mod | 9 + btcec/go.sum | 49 ++ btcec/modnscalar.go | 42 ++ btcec/precompute.go | 67 -- btcec/privkey.go | 56 +- btcec/privkey_test.go | 10 +- btcec/pubkey.go | 173 +---- btcec/pubkey_test.go | 6 +- btcec/secp256k1.go | 10 - btcec/signature.go | 493 +++----------- btcec/signature_test.go | 130 ++-- 24 files changed, 1125 insertions(+), 4554 deletions(-) create mode 100644 btcec/curve.go create mode 100644 btcec/error.go delete mode 100644 btcec/genprecomps.go delete mode 100644 btcec/gensecp256k1.go create mode 100644 btcec/go.mod create mode 100644 btcec/go.sum create mode 100644 btcec/modnscalar.go delete mode 100644 btcec/precompute.go delete mode 100644 btcec/secp256k1.go diff --git a/btcec/README.md b/btcec/README.md index a6dd2cf285..cbf63dd045 100644 --- a/btcec/README.md +++ b/btcec/README.md @@ -3,7 +3,7 @@ btcec [![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) [![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) -[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/btcec?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/btcec) +[![GoDoc](https://pkg.go.dev/github.com/btcsuite/btcd/btcec/v2?status.png)](https://pkg.go.dev/github.com/btcsuite/btcd/btcec/v2) Package btcec implements elliptic curve cryptography needed for working with Bitcoin (secp256k1 only for now). It is designed so that it may be used with the @@ -20,47 +20,19 @@ use secp256k1 elliptic curve cryptography. ## Installation and Updating ```bash -$ go get -u github.com/btcsuite/btcd/btcec +$ go install -u -v github.com/btcsuite/btcd/btcec/v2 ``` ## Examples -* [Sign Message](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--SignMessage) +* [Sign Message](https://pkg.go.dev/github.com/btcsuite/btcd/btcec/v2#example-package--SignMessage) Demonstrates signing a message with a secp256k1 private key that is first parsed form raw bytes and serializing the generated signature. -* [Verify Signature](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--VerifySignature) +* [Verify Signature](https://pkg.go.dev/github.com/btcsuite/btcd/btcec/v2#example-package--VerifySignature) Demonstrates verifying a secp256k1 signature against a public key that is first parsed from raw bytes. The signature is also parsed from raw bytes. -* [Encryption](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--EncryptMessage) - Demonstrates encrypting a message for a public key that is first parsed from - raw bytes, then decrypting it using the corresponding private key. - -* [Decryption](https://pkg.go.dev/github.com/btcsuite/btcd/btcec#example-package--DecryptMessage) - Demonstrates decrypting a message using a private key that is first parsed - from raw bytes. - -## GPG Verification Key - -All official release tags are signed by Conformal so users can ensure the code -has not been tampered with and is coming from the btcsuite developers. To -verify the signature perform the following: - -- Download the public key from the Conformal website at - https://opensource.conformal.com/GIT-GPG-KEY-conformal.txt - -- Import the public key into your GPG keyring: - ```bash - gpg --import GIT-GPG-KEY-conformal.txt - ``` - -- Verify the release tag with the following command where `TAG_NAME` is a - placeholder for the specific tag: - ```bash - git tag -v TAG_NAME - ``` - ## License Package btcec is licensed under the [copyfree](http://copyfree.org) ISC License diff --git a/btcec/bench_test.go b/btcec/bench_test.go index 7ccd78cfb9..475a4afd6e 100644 --- a/btcec/bench_test.go +++ b/btcec/bench_test.go @@ -6,43 +6,114 @@ package btcec import ( "encoding/hex" + "math/big" "testing" + + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) -// BenchmarkAddJacobian benchmarks the secp256k1 curve addJacobian function with +// setHex decodes the passed big-endian hex string into the internal field value +// representation. Only the first 32-bytes are used. +// +// This is NOT constant time. +// +// The field value is returned to support chaining. This enables syntax like: +// f := new(FieldVal).SetHex("0abc").Add(1) so that f = 0x0abc + 1 +func setHex(hexString string) *FieldVal { + if len(hexString)%2 != 0 { + hexString = "0" + hexString + } + bytes, _ := hex.DecodeString(hexString) + + var f FieldVal + f.SetByteSlice(bytes) + + return &f +} + +// hexToFieldVal converts the passed hex string into a FieldVal and will panic +// if there is an error. This is only provided for the hard-coded constants so +// errors in the source code can be detected. It will only (and must only) be +// called with hard-coded values. +func hexToFieldVal(s string) *FieldVal { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + var f FieldVal + if overflow := f.SetByteSlice(b); overflow { + panic("hex in source file overflows mod P: " + s) + } + return &f +} + +// fromHex converts the passed hex string into a big integer pointer and will +// panic is there is an error. This is only provided for the hard-coded +// constants so errors in the source code can bet detected. It will only (and +// must only) be called for initialization purposes. +func fromHex(s string) *big.Int { + if s == "" { + return big.NewInt(0) + } + r, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("invalid hex in source file: " + s) + } + return r +} + +// jacobianPointFromHex decodes the passed big-endian hex strings into a +// Jacobian point with its internal fields set to the resulting values. Only +// the first 32-bytes are used. +func jacobianPointFromHex(x, y, z string) JacobianPoint { + var p JacobianPoint + p.X = *setHex(x) + p.Y = *setHex(y) + p.Z = *setHex(z) + + return p +} + +// BenchmarkAddNonConst benchmarks the secp256k1 curve AddNonConst function with // Z values of 1 so that the associated optimizations are used. func BenchmarkAddJacobian(b *testing.B) { - b.StopTimer() - x1 := new(fieldVal).SetHex("34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6") - y1 := new(fieldVal).SetHex("0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232") - z1 := new(fieldVal).SetHex("1") - x2 := new(fieldVal).SetHex("34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6") - y2 := new(fieldVal).SetHex("0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232") - z2 := new(fieldVal).SetHex("1") - x3, y3, z3 := new(fieldVal), new(fieldVal), new(fieldVal) - curve := S256() - b.StartTimer() + p1 := jacobianPointFromHex( + "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6", + "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232", + "1", + ) + p2 := jacobianPointFromHex( + "34f9460f0e4f08393d192b3c5133a6ba099aa0ad9fd54ebccfacdfa239ff49c6", + "0b71ea9bd730fd8923f6d25a7a91e7dd7728a960686cb5a901bb419e0f2ca232", + "1", + ) + + b.ReportAllocs() + b.ResetTimer() + var result JacobianPoint for i := 0; i < b.N; i++ { - curve.addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3) + secp.AddNonConst(&p1, &p2, &result) } } -// BenchmarkAddJacobianNotZOne benchmarks the secp256k1 curve addJacobian +// BenchmarkAddNonConstNotZOne benchmarks the secp256k1 curve AddNonConst // function with Z values other than one so the optimizations associated with // Z=1 aren't used. func BenchmarkAddJacobianNotZOne(b *testing.B) { - b.StopTimer() - x1 := new(fieldVal).SetHex("d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718") - y1 := new(fieldVal).SetHex("5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190") - z1 := new(fieldVal).SetHex("2") - x2 := new(fieldVal).SetHex("91abba6a34b7481d922a4bd6a04899d5a686f6cf6da4e66a0cb427fb25c04bd4") - y2 := new(fieldVal).SetHex("03fede65e30b4e7576a2abefc963ddbf9fdccbf791b77c29beadefe49951f7d1") - z2 := new(fieldVal).SetHex("3") - x3, y3, z3 := new(fieldVal), new(fieldVal), new(fieldVal) - curve := S256() - b.StartTimer() + x1 := setHex("d3e5183c393c20e4f464acf144ce9ae8266a82b67f553af33eb37e88e7fd2718") + y1 := setHex("5b8f54deb987ec491fb692d3d48f3eebb9454b034365ad480dda0cf079651190") + z1 := setHex("2") + x2 := setHex("91abba6a34b7481d922a4bd6a04899d5a686f6cf6da4e66a0cb427fb25c04bd4") + y2 := setHex("03fede65e30b4e7576a2abefc963ddbf9fdccbf791b77c29beadefe49951f7d1") + z2 := setHex("3") + p1 := MakeJacobianPoint(x1, y1, z1) + p2 := MakeJacobianPoint(x2, y2, z2) + + b.ReportAllocs() + b.ResetTimer() + var result JacobianPoint for i := 0; i < b.N; i++ { - curve.addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3) + AddNonConst(&p1, &p2, &result) } } @@ -77,12 +148,20 @@ func BenchmarkScalarMult(b *testing.B) { } } -// BenchmarkNAF benchmarks the NAF function. -func BenchmarkNAF(b *testing.B) { - k := fromHex("d74bf844b0862475103d96a611cf2d898447e288d34b360bc885cb8ce7c00575") - for i := 0; i < b.N; i++ { - NAF(k.Bytes()) +// hexToModNScalar converts the passed hex string into a ModNScalar and will +// panic if there is an error. This is only provided for the hard-coded +// constants so errors in the source code can be detected. It will only (and +// must only) be called with hard-coded values. +func hexToModNScalar(s string) *ModNScalar { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + var scalar ModNScalar + if overflow := scalar.SetByteSlice(b); overflow { + panic("hex in source file overflows mod N scalar: " + s) } + return &scalar } // BenchmarkSigVerify benchmarks how long it takes the secp256k1 curve to @@ -91,27 +170,26 @@ func BenchmarkSigVerify(b *testing.B) { b.StopTimer() // Randomly generated keypair. // Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d - pubKey := PublicKey{ - Curve: S256(), - X: fromHex("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab"), - Y: fromHex("ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52"), - } + pubKey := NewPublicKey( + hexToFieldVal("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab"), + hexToFieldVal("ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52"), + ) // Double sha256 of []byte{0x01, 0x02, 0x03, 0x04} msgHash := fromHex("8de472e2399610baaa7f84840547cd409434e31f5d3bd71e4d947f283874f9c0") - sig := Signature{ - R: fromHex("fef45d2892953aa5bbcdb057b5e98b208f1617a7498af7eb765574e29b5d9c2c"), - S: fromHex("d47563f52aac6b04b55de236b7c515eb9311757db01e02cff079c3ca6efb063f"), - } + sig := NewSignature( + hexToModNScalar("fef45d2892953aa5bbcdb057b5e98b208f1617a7498af7eb765574e29b5d9c2c"), + hexToModNScalar("d47563f52aac6b04b55de236b7c515eb9311757db01e02cff079c3ca6efb063f"), + ) - if !sig.Verify(msgHash.Bytes(), &pubKey) { + if !sig.Verify(msgHash.Bytes(), pubKey) { b.Errorf("Signature failed to verify") return } b.StartTimer() for i := 0; i < b.N; i++ { - sig.Verify(msgHash.Bytes(), &pubKey) + sig.Verify(msgHash.Bytes(), pubKey) } } @@ -119,7 +197,7 @@ func BenchmarkSigVerify(b *testing.B) { // to perform normalization (which includes modular reduction). func BenchmarkFieldNormalize(b *testing.B) { // The normalize function is constant time so default value is fine. - f := new(fieldVal) + var f FieldVal for i := 0; i < b.N; i++ { f.Normalize() } @@ -138,7 +216,7 @@ func BenchmarkParseCompressedPubKey(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - pk, err = ParsePubKey(rawPk, S256()) + pk, err = ParsePubKey(rawPk) } _ = pk _ = err diff --git a/btcec/btcec.go b/btcec/btcec.go index a2e20f4b31..efde8d6a81 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -20,959 +20,22 @@ package btcec // reverse the transform than to operate in affine coordinates. import ( - "crypto/elliptic" - "math/big" - "sync" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) -var ( - // fieldOne is simply the integer 1 in field representation. It is - // used to avoid needing to create it multiple times during the internal - // arithmetic. - fieldOne = new(fieldVal).SetInt(1) -) - -// KoblitzCurve supports a koblitz curve implementation that fits the ECC Curve -// interface from crypto/elliptic. -type KoblitzCurve struct { - *elliptic.CurveParams - - // q is the value (P+1)/4 used to compute the square root of field - // elements. - q *big.Int - - H int // cofactor of the curve. - halfOrder *big.Int // half the order N - - // fieldB is the constant B of the curve as a fieldVal. - fieldB *fieldVal - - // byteSize is simply the bit size / 8 and is provided for convenience - // since it is calculated repeatedly. - byteSize int - - // bytePoints - bytePoints *[32][256][3]fieldVal - - // The next 6 values are used specifically for endomorphism - // optimizations in ScalarMult. - - // lambda must fulfill lambda^3 = 1 mod N where N is the order of G. - lambda *big.Int - - // beta must fulfill beta^3 = 1 mod P where P is the prime field of the - // curve. - beta *fieldVal - - // See the EndomorphismVectors in gensecp256k1.go to see how these are - // derived. - a1 *big.Int - b1 *big.Int - a2 *big.Int - b2 *big.Int -} - -// Params returns the parameters for the curve. -func (curve *KoblitzCurve) Params() *elliptic.CurveParams { - return curve.CurveParams -} - -// bigAffineToField takes an affine point (x, y) as big integers and converts -// it to an affine point as field values. -func (curve *KoblitzCurve) bigAffineToField(x, y *big.Int) (*fieldVal, *fieldVal) { - x3, y3 := new(fieldVal), new(fieldVal) - x3.SetByteSlice(x.Bytes()) - y3.SetByteSlice(y.Bytes()) - - return x3, y3 -} - -// fieldJacobianToBigAffine takes a Jacobian point (x, y, z) as field values and -// converts it to an affine point as big integers. -func (curve *KoblitzCurve) fieldJacobianToBigAffine(x, y, z *fieldVal) (*big.Int, *big.Int) { - // Inversions are expensive and both point addition and point doubling - // are faster when working with points that have a z value of one. So, - // if the point needs to be converted to affine, go ahead and normalize - // the point itself at the same time as the calculation is the same. - var zInv, tempZ fieldVal - zInv.Set(z).Inverse() // zInv = Z^-1 - tempZ.SquareVal(&zInv) // tempZ = Z^-2 - x.Mul(&tempZ) // X = X/Z^2 (mag: 1) - y.Mul(tempZ.Mul(&zInv)) // Y = Y/Z^3 (mag: 1) - z.SetInt(1) // Z = 1 (mag: 1) - - // Normalize the x and y values. - x.Normalize() - y.Normalize() - - // Convert the field values for the now affine point to big.Ints. - x3, y3 := new(big.Int), new(big.Int) - x3.SetBytes(x.Bytes()[:]) - y3.SetBytes(y.Bytes()[:]) - return x3, y3 -} - -// IsOnCurve returns boolean if the point (x,y) is on the curve. -// Part of the elliptic.Curve interface. This function differs from the -// crypto/elliptic algorithm since a = 0 not -3. -func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool { - // Convert big ints to field values for faster arithmetic. - fx, fy := curve.bigAffineToField(x, y) - - // Elliptic curve equation for secp256k1 is: y^2 = x^3 + 7 - y2 := new(fieldVal).SquareVal(fy).Normalize() - result := new(fieldVal).SquareVal(fx).Mul(fx).AddInt(7).Normalize() - return y2.Equals(result) -} - -// addZ1AndZ2EqualsOne adds two Jacobian points that are already known to have -// z values of 1 and stores the result in (x3, y3, z3). That is to say -// (x1, y1, 1) + (x2, y2, 1) = (x3, y3, z3). It performs faster addition than -// the generic add routine since less arithmetic is needed due to the ability to -// avoid the z value multiplications. -func (curve *KoblitzCurve) addZ1AndZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) { - // To compute the point addition efficiently, this implementation splits - // the equation into intermediate elements which are used to minimize - // the number of field multiplications using the method shown at: - // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl - // - // In particular it performs the calculations using the following: - // H = X2-X1, HH = H^2, I = 4*HH, J = H*I, r = 2*(Y2-Y1), V = X1*I - // X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*Y1*J, Z3 = 2*H - // - // This results in a cost of 4 field multiplications, 2 field squarings, - // 6 field additions, and 5 integer multiplications. - - // When the x coordinates are the same for two points on the curve, the - // y coordinates either must be the same, in which case it is point - // doubling, or they are opposite and the result is the point at - // infinity per the group law for elliptic curve cryptography. - x1.Normalize() - y1.Normalize() - x2.Normalize() - y2.Normalize() - if x1.Equals(x2) { - if y1.Equals(y2) { - // Since x1 == x2 and y1 == y2, point doubling must be - // done, otherwise the addition would end up dividing - // by zero. - curve.doubleJacobian(x1, y1, z1, x3, y3, z3) - return - } - - // Since x1 == x2 and y1 == -y2, the sum is the point at - // infinity per the group law. - x3.SetInt(0) - y3.SetInt(0) - z3.SetInt(0) - return - } - - // Calculate X3, Y3, and Z3 according to the intermediate elements - // breakdown above. - var h, i, j, r, v fieldVal - var negJ, neg2V, negX3 fieldVal - h.Set(x1).Negate(1).Add(x2) // H = X2-X1 (mag: 3) - i.SquareVal(&h).MulInt(4) // I = 4*H^2 (mag: 4) - j.Mul2(&h, &i) // J = H*I (mag: 1) - r.Set(y1).Negate(1).Add(y2).MulInt(2) // r = 2*(Y2-Y1) (mag: 6) - v.Mul2(x1, &i) // V = X1*I (mag: 1) - negJ.Set(&j).Negate(1) // negJ = -J (mag: 2) - neg2V.Set(&v).MulInt(2).Negate(2) // neg2V = -(2*V) (mag: 3) - x3.Set(&r).Square().Add(&negJ).Add(&neg2V) // X3 = r^2-J-2*V (mag: 6) - negX3.Set(x3).Negate(6) // negX3 = -X3 (mag: 7) - j.Mul(y1).MulInt(2).Negate(2) // J = -(2*Y1*J) (mag: 3) - y3.Set(&v).Add(&negX3).Mul(&r).Add(&j) // Y3 = r*(V-X3)-2*Y1*J (mag: 4) - z3.Set(&h).MulInt(2) // Z3 = 2*H (mag: 6) - - // Normalize the resulting field values to a magnitude of 1 as needed. - x3.Normalize() - y3.Normalize() - z3.Normalize() -} - -// addZ1EqualsZ2 adds two Jacobian points that are already known to have the -// same z value and stores the result in (x3, y3, z3). That is to say -// (x1, y1, z1) + (x2, y2, z1) = (x3, y3, z3). It performs faster addition than -// the generic add routine since less arithmetic is needed due to the known -// equivalence. -func (curve *KoblitzCurve) addZ1EqualsZ2(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) { - // To compute the point addition efficiently, this implementation splits - // the equation into intermediate elements which are used to minimize - // the number of field multiplications using a slightly modified version - // of the method shown at: - // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-mmadd-2007-bl - // - // In particular it performs the calculations using the following: - // A = X2-X1, B = A^2, C=Y2-Y1, D = C^2, E = X1*B, F = X2*B - // X3 = D-E-F, Y3 = C*(E-X3)-Y1*(F-E), Z3 = Z1*A - // - // This results in a cost of 5 field multiplications, 2 field squarings, - // 9 field additions, and 0 integer multiplications. - - // When the x coordinates are the same for two points on the curve, the - // y coordinates either must be the same, in which case it is point - // doubling, or they are opposite and the result is the point at - // infinity per the group law for elliptic curve cryptography. - x1.Normalize() - y1.Normalize() - x2.Normalize() - y2.Normalize() - if x1.Equals(x2) { - if y1.Equals(y2) { - // Since x1 == x2 and y1 == y2, point doubling must be - // done, otherwise the addition would end up dividing - // by zero. - curve.doubleJacobian(x1, y1, z1, x3, y3, z3) - return - } - - // Since x1 == x2 and y1 == -y2, the sum is the point at - // infinity per the group law. - x3.SetInt(0) - y3.SetInt(0) - z3.SetInt(0) - return - } - - // Calculate X3, Y3, and Z3 according to the intermediate elements - // breakdown above. - var a, b, c, d, e, f fieldVal - var negX1, negY1, negE, negX3 fieldVal - negX1.Set(x1).Negate(1) // negX1 = -X1 (mag: 2) - negY1.Set(y1).Negate(1) // negY1 = -Y1 (mag: 2) - a.Set(&negX1).Add(x2) // A = X2-X1 (mag: 3) - b.SquareVal(&a) // B = A^2 (mag: 1) - c.Set(&negY1).Add(y2) // C = Y2-Y1 (mag: 3) - d.SquareVal(&c) // D = C^2 (mag: 1) - e.Mul2(x1, &b) // E = X1*B (mag: 1) - negE.Set(&e).Negate(1) // negE = -E (mag: 2) - f.Mul2(x2, &b) // F = X2*B (mag: 1) - x3.Add2(&e, &f).Negate(3).Add(&d) // X3 = D-E-F (mag: 5) - negX3.Set(x3).Negate(5).Normalize() // negX3 = -X3 (mag: 1) - y3.Set(y1).Mul(f.Add(&negE)).Negate(3) // Y3 = -(Y1*(F-E)) (mag: 4) - y3.Add(e.Add(&negX3).Mul(&c)) // Y3 = C*(E-X3)+Y3 (mag: 5) - z3.Mul2(z1, &a) // Z3 = Z1*A (mag: 1) - - // Normalize the resulting field values to a magnitude of 1 as needed. - x3.Normalize() - y3.Normalize() -} - -// addZ2EqualsOne adds two Jacobian points when the second point is already -// known to have a z value of 1 (and the z value for the first point is not 1) -// and stores the result in (x3, y3, z3). That is to say (x1, y1, z1) + -// (x2, y2, 1) = (x3, y3, z3). It performs faster addition than the generic -// add routine since less arithmetic is needed due to the ability to avoid -// multiplications by the second point's z value. -func (curve *KoblitzCurve) addZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3 *fieldVal) { - // To compute the point addition efficiently, this implementation splits - // the equation into intermediate elements which are used to minimize - // the number of field multiplications using the method shown at: - // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl - // - // In particular it performs the calculations using the following: - // Z1Z1 = Z1^2, U2 = X2*Z1Z1, S2 = Y2*Z1*Z1Z1, H = U2-X1, HH = H^2, - // I = 4*HH, J = H*I, r = 2*(S2-Y1), V = X1*I - // X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*Y1*J, Z3 = (Z1+H)^2-Z1Z1-HH - // - // This results in a cost of 7 field multiplications, 4 field squarings, - // 9 field additions, and 4 integer multiplications. - - // When the x coordinates are the same for two points on the curve, the - // y coordinates either must be the same, in which case it is point - // doubling, or they are opposite and the result is the point at - // infinity per the group law for elliptic curve cryptography. Since - // any number of Jacobian coordinates can represent the same affine - // point, the x and y values need to be converted to like terms. Due to - // the assumption made for this function that the second point has a z - // value of 1 (z2=1), the first point is already "converted". - var z1z1, u2, s2 fieldVal - x1.Normalize() - y1.Normalize() - z1z1.SquareVal(z1) // Z1Z1 = Z1^2 (mag: 1) - u2.Set(x2).Mul(&z1z1).Normalize() // U2 = X2*Z1Z1 (mag: 1) - s2.Set(y2).Mul(&z1z1).Mul(z1).Normalize() // S2 = Y2*Z1*Z1Z1 (mag: 1) - if x1.Equals(&u2) { - if y1.Equals(&s2) { - // Since x1 == x2 and y1 == y2, point doubling must be - // done, otherwise the addition would end up dividing - // by zero. - curve.doubleJacobian(x1, y1, z1, x3, y3, z3) - return - } - - // Since x1 == x2 and y1 == -y2, the sum is the point at - // infinity per the group law. - x3.SetInt(0) - y3.SetInt(0) - z3.SetInt(0) - return - } - - // Calculate X3, Y3, and Z3 according to the intermediate elements - // breakdown above. - var h, hh, i, j, r, rr, v fieldVal - var negX1, negY1, negX3 fieldVal - negX1.Set(x1).Negate(1) // negX1 = -X1 (mag: 2) - h.Add2(&u2, &negX1) // H = U2-X1 (mag: 3) - hh.SquareVal(&h) // HH = H^2 (mag: 1) - i.Set(&hh).MulInt(4) // I = 4 * HH (mag: 4) - j.Mul2(&h, &i) // J = H*I (mag: 1) - negY1.Set(y1).Negate(1) // negY1 = -Y1 (mag: 2) - r.Set(&s2).Add(&negY1).MulInt(2) // r = 2*(S2-Y1) (mag: 6) - rr.SquareVal(&r) // rr = r^2 (mag: 1) - v.Mul2(x1, &i) // V = X1*I (mag: 1) - x3.Set(&v).MulInt(2).Add(&j).Negate(3) // X3 = -(J+2*V) (mag: 4) - x3.Add(&rr) // X3 = r^2+X3 (mag: 5) - negX3.Set(x3).Negate(5) // negX3 = -X3 (mag: 6) - y3.Set(y1).Mul(&j).MulInt(2).Negate(2) // Y3 = -(2*Y1*J) (mag: 3) - y3.Add(v.Add(&negX3).Mul(&r)) // Y3 = r*(V-X3)+Y3 (mag: 4) - z3.Add2(z1, &h).Square() // Z3 = (Z1+H)^2 (mag: 1) - z3.Add(z1z1.Add(&hh).Negate(2)) // Z3 = Z3-(Z1Z1+HH) (mag: 4) - - // Normalize the resulting field values to a magnitude of 1 as needed. - x3.Normalize() - y3.Normalize() - z3.Normalize() -} - -// addGeneric adds two Jacobian points (x1, y1, z1) and (x2, y2, z2) without any -// assumptions about the z values of the two points and stores the result in -// (x3, y3, z3). That is to say (x1, y1, z1) + (x2, y2, z2) = (x3, y3, z3). It -// is the slowest of the add routines due to requiring the most arithmetic. -func (curve *KoblitzCurve) addGeneric(x1, y1, z1, x2, y2, z2, x3, y3, z3 *fieldVal) { - // To compute the point addition efficiently, this implementation splits - // the equation into intermediate elements which are used to minimize - // the number of field multiplications using the method shown at: - // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl - // - // In particular it performs the calculations using the following: - // Z1Z1 = Z1^2, Z2Z2 = Z2^2, U1 = X1*Z2Z2, U2 = X2*Z1Z1, S1 = Y1*Z2*Z2Z2 - // S2 = Y2*Z1*Z1Z1, H = U2-U1, I = (2*H)^2, J = H*I, r = 2*(S2-S1) - // V = U1*I - // X3 = r^2-J-2*V, Y3 = r*(V-X3)-2*S1*J, Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H - // - // This results in a cost of 11 field multiplications, 5 field squarings, - // 9 field additions, and 4 integer multiplications. - - // When the x coordinates are the same for two points on the curve, the - // y coordinates either must be the same, in which case it is point - // doubling, or they are opposite and the result is the point at - // infinity. Since any number of Jacobian coordinates can represent the - // same affine point, the x and y values need to be converted to like - // terms. - var z1z1, z2z2, u1, u2, s1, s2 fieldVal - z1z1.SquareVal(z1) // Z1Z1 = Z1^2 (mag: 1) - z2z2.SquareVal(z2) // Z2Z2 = Z2^2 (mag: 1) - u1.Set(x1).Mul(&z2z2).Normalize() // U1 = X1*Z2Z2 (mag: 1) - u2.Set(x2).Mul(&z1z1).Normalize() // U2 = X2*Z1Z1 (mag: 1) - s1.Set(y1).Mul(&z2z2).Mul(z2).Normalize() // S1 = Y1*Z2*Z2Z2 (mag: 1) - s2.Set(y2).Mul(&z1z1).Mul(z1).Normalize() // S2 = Y2*Z1*Z1Z1 (mag: 1) - if u1.Equals(&u2) { - if s1.Equals(&s2) { - // Since x1 == x2 and y1 == y2, point doubling must be - // done, otherwise the addition would end up dividing - // by zero. - curve.doubleJacobian(x1, y1, z1, x3, y3, z3) - return - } - - // Since x1 == x2 and y1 == -y2, the sum is the point at - // infinity per the group law. - x3.SetInt(0) - y3.SetInt(0) - z3.SetInt(0) - return - } - - // Calculate X3, Y3, and Z3 according to the intermediate elements - // breakdown above. - var h, i, j, r, rr, v fieldVal - var negU1, negS1, negX3 fieldVal - negU1.Set(&u1).Negate(1) // negU1 = -U1 (mag: 2) - h.Add2(&u2, &negU1) // H = U2-U1 (mag: 3) - i.Set(&h).MulInt(2).Square() // I = (2*H)^2 (mag: 2) - j.Mul2(&h, &i) // J = H*I (mag: 1) - negS1.Set(&s1).Negate(1) // negS1 = -S1 (mag: 2) - r.Set(&s2).Add(&negS1).MulInt(2) // r = 2*(S2-S1) (mag: 6) - rr.SquareVal(&r) // rr = r^2 (mag: 1) - v.Mul2(&u1, &i) // V = U1*I (mag: 1) - x3.Set(&v).MulInt(2).Add(&j).Negate(3) // X3 = -(J+2*V) (mag: 4) - x3.Add(&rr) // X3 = r^2+X3 (mag: 5) - negX3.Set(x3).Negate(5) // negX3 = -X3 (mag: 6) - y3.Mul2(&s1, &j).MulInt(2).Negate(2) // Y3 = -(2*S1*J) (mag: 3) - y3.Add(v.Add(&negX3).Mul(&r)) // Y3 = r*(V-X3)+Y3 (mag: 4) - z3.Add2(z1, z2).Square() // Z3 = (Z1+Z2)^2 (mag: 1) - z3.Add(z1z1.Add(&z2z2).Negate(2)) // Z3 = Z3-(Z1Z1+Z2Z2) (mag: 4) - z3.Mul(&h) // Z3 = Z3*H (mag: 1) - - // Normalize the resulting field values to a magnitude of 1 as needed. - x3.Normalize() - y3.Normalize() -} - -// addJacobian adds the passed Jacobian points (x1, y1, z1) and (x2, y2, z2) -// together and stores the result in (x3, y3, z3). -func (curve *KoblitzCurve) addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3 *fieldVal) { - // A point at infinity is the identity according to the group law for - // elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P. - if (x1.IsZero() && y1.IsZero()) || z1.IsZero() { - x3.Set(x2) - y3.Set(y2) - z3.Set(z2) - return - } - if (x2.IsZero() && y2.IsZero()) || z2.IsZero() { - x3.Set(x1) - y3.Set(y1) - z3.Set(z1) - return - } - - // Faster point addition can be achieved when certain assumptions are - // met. For example, when both points have the same z value, arithmetic - // on the z values can be avoided. This section thus checks for these - // conditions and calls an appropriate add function which is accelerated - // by using those assumptions. - z1.Normalize() - z2.Normalize() - isZ1One := z1.Equals(fieldOne) - isZ2One := z2.Equals(fieldOne) - switch { - case isZ1One && isZ2One: - curve.addZ1AndZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3) - return - case z1.Equals(z2): - curve.addZ1EqualsZ2(x1, y1, z1, x2, y2, x3, y3, z3) - return - case isZ2One: - curve.addZ2EqualsOne(x1, y1, z1, x2, y2, x3, y3, z3) - return - } - - // None of the above assumptions are true, so fall back to generic - // point addition. - curve.addGeneric(x1, y1, z1, x2, y2, z2, x3, y3, z3) -} - -// Add returns the sum of (x1,y1) and (x2,y2). Part of the elliptic.Curve -// interface. -func (curve *KoblitzCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { - // A point at infinity is the identity according to the group law for - // elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P. - if x1.Sign() == 0 && y1.Sign() == 0 { - return x2, y2 - } - if x2.Sign() == 0 && y2.Sign() == 0 { - return x1, y1 - } - - // Convert the affine coordinates from big integers to field values - // and do the point addition in Jacobian projective space. - fx1, fy1 := curve.bigAffineToField(x1, y1) - fx2, fy2 := curve.bigAffineToField(x2, y2) - fx3, fy3, fz3 := new(fieldVal), new(fieldVal), new(fieldVal) - fOne := new(fieldVal).SetInt(1) - curve.addJacobian(fx1, fy1, fOne, fx2, fy2, fOne, fx3, fy3, fz3) - - // Convert the Jacobian coordinate field values back to affine big - // integers. - return curve.fieldJacobianToBigAffine(fx3, fy3, fz3) -} - -// doubleZ1EqualsOne performs point doubling on the passed Jacobian point -// when the point is already known to have a z value of 1 and stores -// the result in (x3, y3, z3). That is to say (x3, y3, z3) = 2*(x1, y1, 1). It -// performs faster point doubling than the generic routine since less arithmetic -// is needed due to the ability to avoid multiplication by the z value. -func (curve *KoblitzCurve) doubleZ1EqualsOne(x1, y1, x3, y3, z3 *fieldVal) { - // This function uses the assumptions that z1 is 1, thus the point - // doubling formulas reduce to: - // - // X3 = (3*X1^2)^2 - 8*X1*Y1^2 - // Y3 = (3*X1^2)*(4*X1*Y1^2 - X3) - 8*Y1^4 - // Z3 = 2*Y1 - // - // To compute the above efficiently, this implementation splits the - // equation into intermediate elements which are used to minimize the - // number of field multiplications in favor of field squarings which - // are roughly 35% faster than field multiplications with the current - // implementation at the time this was written. - // - // This uses a slightly modified version of the method shown at: - // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl - // - // In particular it performs the calculations using the following: - // A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C) - // E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C - // Z3 = 2*Y1 - // - // This results in a cost of 1 field multiplication, 5 field squarings, - // 6 field additions, and 5 integer multiplications. - var a, b, c, d, e, f fieldVal - z3.Set(y1).MulInt(2) // Z3 = 2*Y1 (mag: 2) - a.SquareVal(x1) // A = X1^2 (mag: 1) - b.SquareVal(y1) // B = Y1^2 (mag: 1) - c.SquareVal(&b) // C = B^2 (mag: 1) - b.Add(x1).Square() // B = (X1+B)^2 (mag: 1) - d.Set(&a).Add(&c).Negate(2) // D = -(A+C) (mag: 3) - d.Add(&b).MulInt(2) // D = 2*(B+D)(mag: 8) - e.Set(&a).MulInt(3) // E = 3*A (mag: 3) - f.SquareVal(&e) // F = E^2 (mag: 1) - x3.Set(&d).MulInt(2).Negate(16) // X3 = -(2*D) (mag: 17) - x3.Add(&f) // X3 = F+X3 (mag: 18) - f.Set(x3).Negate(18).Add(&d).Normalize() // F = D-X3 (mag: 1) - y3.Set(&c).MulInt(8).Negate(8) // Y3 = -(8*C) (mag: 9) - y3.Add(f.Mul(&e)) // Y3 = E*F+Y3 (mag: 10) - - // Normalize the field values back to a magnitude of 1. - x3.Normalize() - y3.Normalize() - z3.Normalize() -} - -// doubleGeneric performs point doubling on the passed Jacobian point without -// any assumptions about the z value and stores the result in (x3, y3, z3). -// That is to say (x3, y3, z3) = 2*(x1, y1, z1). It is the slowest of the point -// doubling routines due to requiring the most arithmetic. -func (curve *KoblitzCurve) doubleGeneric(x1, y1, z1, x3, y3, z3 *fieldVal) { - // Point doubling formula for Jacobian coordinates for the secp256k1 - // curve: - // X3 = (3*X1^2)^2 - 8*X1*Y1^2 - // Y3 = (3*X1^2)*(4*X1*Y1^2 - X3) - 8*Y1^4 - // Z3 = 2*Y1*Z1 - // - // To compute the above efficiently, this implementation splits the - // equation into intermediate elements which are used to minimize the - // number of field multiplications in favor of field squarings which - // are roughly 35% faster than field multiplications with the current - // implementation at the time this was written. - // - // This uses a slightly modified version of the method shown at: - // http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l - // - // In particular it performs the calculations using the following: - // A = X1^2, B = Y1^2, C = B^2, D = 2*((X1+B)^2-A-C) - // E = 3*A, F = E^2, X3 = F-2*D, Y3 = E*(D-X3)-8*C - // Z3 = 2*Y1*Z1 - // - // This results in a cost of 1 field multiplication, 5 field squarings, - // 6 field additions, and 5 integer multiplications. - var a, b, c, d, e, f fieldVal - z3.Mul2(y1, z1).MulInt(2) // Z3 = 2*Y1*Z1 (mag: 2) - a.SquareVal(x1) // A = X1^2 (mag: 1) - b.SquareVal(y1) // B = Y1^2 (mag: 1) - c.SquareVal(&b) // C = B^2 (mag: 1) - b.Add(x1).Square() // B = (X1+B)^2 (mag: 1) - d.Set(&a).Add(&c).Negate(2) // D = -(A+C) (mag: 3) - d.Add(&b).MulInt(2) // D = 2*(B+D)(mag: 8) - e.Set(&a).MulInt(3) // E = 3*A (mag: 3) - f.SquareVal(&e) // F = E^2 (mag: 1) - x3.Set(&d).MulInt(2).Negate(16) // X3 = -(2*D) (mag: 17) - x3.Add(&f) // X3 = F+X3 (mag: 18) - f.Set(x3).Negate(18).Add(&d).Normalize() // F = D-X3 (mag: 1) - y3.Set(&c).MulInt(8).Negate(8) // Y3 = -(8*C) (mag: 9) - y3.Add(f.Mul(&e)) // Y3 = E*F+Y3 (mag: 10) - - // Normalize the field values back to a magnitude of 1. - x3.Normalize() - y3.Normalize() - z3.Normalize() -} - -// doubleJacobian doubles the passed Jacobian point (x1, y1, z1) and stores the -// result in (x3, y3, z3). -func (curve *KoblitzCurve) doubleJacobian(x1, y1, z1, x3, y3, z3 *fieldVal) { - // Doubling a point at infinity is still infinity. - if y1.IsZero() || z1.IsZero() { - x3.SetInt(0) - y3.SetInt(0) - z3.SetInt(0) - return - } - - // Slightly faster point doubling can be achieved when the z value is 1 - // by avoiding the multiplication on the z value. This section calls - // a point doubling function which is accelerated by using that - // assumption when possible. - if z1.Normalize().Equals(fieldOne) { - curve.doubleZ1EqualsOne(x1, y1, x3, y3, z3) - return - } - - // Fall back to generic point doubling which works with arbitrary z - // values. - curve.doubleGeneric(x1, y1, z1, x3, y3, z3) -} - -// Double returns 2*(x1,y1). Part of the elliptic.Curve interface. -func (curve *KoblitzCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { - if y1.Sign() == 0 { - return new(big.Int), new(big.Int) - } - - // Convert the affine coordinates from big integers to field values - // and do the point doubling in Jacobian projective space. - fx1, fy1 := curve.bigAffineToField(x1, y1) - fx3, fy3, fz3 := new(fieldVal), new(fieldVal), new(fieldVal) - fOne := new(fieldVal).SetInt(1) - curve.doubleJacobian(fx1, fy1, fOne, fx3, fy3, fz3) - - // Convert the Jacobian coordinate field values back to affine big - // integers. - return curve.fieldJacobianToBigAffine(fx3, fy3, fz3) -} - -// splitK returns a balanced length-two representation of k and their signs. -// This is algorithm 3.74 from [GECC]. -// -// One thing of note about this algorithm is that no matter what c1 and c2 are, -// the final equation of k = k1 + k2 * lambda (mod n) will hold. This is -// provable mathematically due to how a1/b1/a2/b2 are computed. -// -// c1 and c2 are chosen to minimize the max(k1,k2). -func (curve *KoblitzCurve) splitK(k []byte) ([]byte, []byte, int, int) { - // All math here is done with big.Int, which is slow. - // At some point, it might be useful to write something similar to - // fieldVal but for N instead of P as the prime field if this ends up - // being a bottleneck. - bigIntK := new(big.Int) - c1, c2 := new(big.Int), new(big.Int) - tmp1, tmp2 := new(big.Int), new(big.Int) - k1, k2 := new(big.Int), new(big.Int) - - bigIntK.SetBytes(k) - // c1 = round(b2 * k / n) from step 4. - // Rounding isn't really necessary and costs too much, hence skipped - c1.Mul(curve.b2, bigIntK) - c1.Div(c1, curve.N) - // c2 = round(b1 * k / n) from step 4 (sign reversed to optimize one step) - // Rounding isn't really necessary and costs too much, hence skipped - c2.Mul(curve.b1, bigIntK) - c2.Div(c2, curve.N) - // k1 = k - c1 * a1 - c2 * a2 from step 5 (note c2's sign is reversed) - tmp1.Mul(c1, curve.a1) - tmp2.Mul(c2, curve.a2) - k1.Sub(bigIntK, tmp1) - k1.Add(k1, tmp2) - // k2 = - c1 * b1 - c2 * b2 from step 5 (note c2's sign is reversed) - tmp1.Mul(c1, curve.b1) - tmp2.Mul(c2, curve.b2) - k2.Sub(tmp2, tmp1) - - // Note Bytes() throws out the sign of k1 and k2. This matters - // since k1 and/or k2 can be negative. Hence, we pass that - // back separately. - return k1.Bytes(), k2.Bytes(), k1.Sign(), k2.Sign() -} - -// moduloReduce reduces k from more than 32 bytes to 32 bytes and under. This -// is done by doing a simple modulo curve.N. We can do this since G^N = 1 and -// thus any other valid point on the elliptic curve has the same order. -func (curve *KoblitzCurve) moduloReduce(k []byte) []byte { - // Since the order of G is curve.N, we can use a much smaller number - // by doing modulo curve.N - if len(k) > curve.byteSize { - // Reduce k by performing modulo curve.N. - tmpK := new(big.Int).SetBytes(k) - tmpK.Mod(tmpK, curve.N) - return tmpK.Bytes() - } - - return k -} - -// NAF takes a positive integer k and returns the Non-Adjacent Form (NAF) as two -// byte slices. The first is where 1s will be. The second is where -1s will -// be. NAF is convenient in that on average, only 1/3rd of its values are -// non-zero. This is algorithm 3.30 from [GECC]. -// -// Essentially, this makes it possible to minimize the number of operations -// since the resulting ints returned will be at least 50% 0s. -func NAF(k []byte) ([]byte, []byte) { - // The essence of this algorithm is that whenever we have consecutive 1s - // in the binary, we want to put a -1 in the lowest bit and get a bunch - // of 0s up to the highest bit of consecutive 1s. This is due to this - // identity: - // 2^n + 2^(n-1) + 2^(n-2) + ... + 2^(n-k) = 2^(n+1) - 2^(n-k) - // - // The algorithm thus may need to go 1 more bit than the length of the - // bits we actually have, hence bits being 1 bit longer than was - // necessary. Since we need to know whether adding will cause a carry, - // we go from right-to-left in this addition. - var carry, curIsOne, nextIsOne bool - // these default to zero - retPos := make([]byte, len(k)+1) - retNeg := make([]byte, len(k)+1) - for i := len(k) - 1; i >= 0; i-- { - curByte := k[i] - for j := uint(0); j < 8; j++ { - curIsOne = curByte&1 == 1 - if j == 7 { - if i == 0 { - nextIsOne = false - } else { - nextIsOne = k[i-1]&1 == 1 - } - } else { - nextIsOne = curByte&2 == 2 - } - if carry { - if curIsOne { - // This bit is 1, so continue to carry - // and don't need to do anything. - } else { - // We've hit a 0 after some number of - // 1s. - if nextIsOne { - // Start carrying again since - // a new sequence of 1s is - // starting. - retNeg[i+1] += 1 << j - } else { - // Stop carrying since 1s have - // stopped. - carry = false - retPos[i+1] += 1 << j - } - } - } else if curIsOne { - if nextIsOne { - // If this is the start of at least 2 - // consecutive 1s, set the current one - // to -1 and start carrying. - retNeg[i+1] += 1 << j - carry = true - } else { - // This is a singleton, not consecutive - // 1s. - retPos[i+1] += 1 << j - } - } - curByte >>= 1 - } - } - if carry { - retPos[0] = 1 - return retPos, retNeg - } - return retPos[1:], retNeg[1:] -} - -// ScalarMult returns k*(Bx, By) where k is a big endian integer. -// Part of the elliptic.Curve interface. -func (curve *KoblitzCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { - // Point Q = ∞ (point at infinity). - qx, qy, qz := new(fieldVal), new(fieldVal), new(fieldVal) - - // Decompose K into k1 and k2 in order to halve the number of EC ops. - // See Algorithm 3.74 in [GECC]. - k1, k2, signK1, signK2 := curve.splitK(curve.moduloReduce(k)) - - // The main equation here to remember is: - // k * P = k1 * P + k2 * ϕ(P) - // - // P1 below is P in the equation, P2 below is ϕ(P) in the equation - p1x, p1y := curve.bigAffineToField(Bx, By) - p1yNeg := new(fieldVal).NegateVal(p1y, 1) - p1z := new(fieldVal).SetInt(1) - - // NOTE: ϕ(x,y) = (βx,y). The Jacobian z coordinate is 1, so this math - // goes through. - p2x := new(fieldVal).Mul2(p1x, curve.beta) - p2y := new(fieldVal).Set(p1y) - p2yNeg := new(fieldVal).NegateVal(p2y, 1) - p2z := new(fieldVal).SetInt(1) - - // Flip the positive and negative values of the points as needed - // depending on the signs of k1 and k2. As mentioned in the equation - // above, each of k1 and k2 are multiplied by the respective point. - // Since -k * P is the same thing as k * -P, and the group law for - // elliptic curves states that P(x, y) = -P(x, -y), it's faster and - // simplifies the code to just make the point negative. - if signK1 == -1 { - p1y, p1yNeg = p1yNeg, p1y - } - if signK2 == -1 { - p2y, p2yNeg = p2yNeg, p2y - } +// KoblitzCurve provides an implementation for secp256k1 that fits the ECC +// Curve interface from crypto/elliptic. +type KoblitzCurve = secp.KoblitzCurve - // NAF versions of k1 and k2 should have a lot more zeros. - // - // The Pos version of the bytes contain the +1s and the Neg versions - // contain the -1s. - k1PosNAF, k1NegNAF := NAF(k1) - k2PosNAF, k2NegNAF := NAF(k2) - k1Len := len(k1PosNAF) - k2Len := len(k2PosNAF) - - m := k1Len - if m < k2Len { - m = k2Len - } - - // Add left-to-right using the NAF optimization. See algorithm 3.77 - // from [GECC]. This should be faster overall since there will be a lot - // more instances of 0, hence reducing the number of Jacobian additions - // at the cost of 1 possible extra doubling. - var k1BytePos, k1ByteNeg, k2BytePos, k2ByteNeg byte - for i := 0; i < m; i++ { - // Since we're going left-to-right, pad the front with 0s. - if i < m-k1Len { - k1BytePos = 0 - k1ByteNeg = 0 - } else { - k1BytePos = k1PosNAF[i-(m-k1Len)] - k1ByteNeg = k1NegNAF[i-(m-k1Len)] - } - if i < m-k2Len { - k2BytePos = 0 - k2ByteNeg = 0 - } else { - k2BytePos = k2PosNAF[i-(m-k2Len)] - k2ByteNeg = k2NegNAF[i-(m-k2Len)] - } - - for j := 7; j >= 0; j-- { - // Q = 2 * Q - curve.doubleJacobian(qx, qy, qz, qx, qy, qz) - - if k1BytePos&0x80 == 0x80 { - curve.addJacobian(qx, qy, qz, p1x, p1y, p1z, - qx, qy, qz) - } else if k1ByteNeg&0x80 == 0x80 { - curve.addJacobian(qx, qy, qz, p1x, p1yNeg, p1z, - qx, qy, qz) - } - - if k2BytePos&0x80 == 0x80 { - curve.addJacobian(qx, qy, qz, p2x, p2y, p2z, - qx, qy, qz) - } else if k2ByteNeg&0x80 == 0x80 { - curve.addJacobian(qx, qy, qz, p2x, p2yNeg, p2z, - qx, qy, qz) - } - k1BytePos <<= 1 - k1ByteNeg <<= 1 - k2BytePos <<= 1 - k2ByteNeg <<= 1 - } - } - - // Convert the Jacobian coordinate field values back to affine big.Ints. - return curve.fieldJacobianToBigAffine(qx, qy, qz) -} - -// ScalarBaseMult returns k*G where G is the base point of the group and k is a -// big endian integer. -// Part of the elliptic.Curve interface. -func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { - newK := curve.moduloReduce(k) - diff := len(curve.bytePoints) - len(newK) - - // Point Q = ∞ (point at infinity). - qx, qy, qz := new(fieldVal), new(fieldVal), new(fieldVal) - - // curve.bytePoints has all 256 byte points for each 8-bit window. The - // strategy is to add up the byte points. This is best understood by - // expressing k in base-256 which it already sort of is. - // Each "digit" in the 8-bit window can be looked up using bytePoints - // and added together. - for i, byteVal := range newK { - p := curve.bytePoints[diff+i][byteVal] - curve.addJacobian(qx, qy, qz, &p[0], &p[1], &p[2], qx, qy, qz) - } - return curve.fieldJacobianToBigAffine(qx, qy, qz) -} - -// QPlus1Div4 returns the (P+1)/4 constant for the curve for use in calculating -// square roots via exponentiation. -// -// DEPRECATED: The actual value returned is (P+1)/4, where as the original -// method name implies that this value is (((P+1)/4)+1)/4. This method is kept -// to maintain backwards compatibility of the API. Use Q() instead. -func (curve *KoblitzCurve) QPlus1Div4() *big.Int { - return curve.q -} - -// Q returns the (P+1)/4 constant for the curve for use in calculating square -// roots via exponentiation. -func (curve *KoblitzCurve) Q() *big.Int { - return curve.q -} - -var initonce sync.Once -var secp256k1 KoblitzCurve - -func initAll() { - initS256() -} - -// fromHex converts the passed hex string into a big integer pointer and will -// panic is there is an error. This is only provided for the hard-coded -// constants so errors in the source code can bet detected. It will only (and -// must only) be called for initialization purposes. -func fromHex(s string) *big.Int { - r, ok := new(big.Int).SetString(s, 16) - if !ok { - panic("invalid hex in source file: " + s) - } - return r +// S256 returns a Curve which implements secp256k1. +func S256() *KoblitzCurve { + return secp.S256() } -func initS256() { - // Curve parameters taken from [SECG] section 2.4.1. - secp256k1.CurveParams = new(elliptic.CurveParams) - secp256k1.P = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F") - secp256k1.N = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141") - secp256k1.B = fromHex("0000000000000000000000000000000000000000000000000000000000000007") - secp256k1.Gx = fromHex("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798") - secp256k1.Gy = fromHex("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8") - secp256k1.BitSize = 256 - // Curve name taken from https://safecurves.cr.yp.to/. - secp256k1.Name = "secp256k1" - secp256k1.q = new(big.Int).Div(new(big.Int).Add(secp256k1.P, - big.NewInt(1)), big.NewInt(4)) - secp256k1.H = 1 - secp256k1.halfOrder = new(big.Int).Rsh(secp256k1.N, 1) - secp256k1.fieldB = new(fieldVal).SetByteSlice(secp256k1.B.Bytes()) +// CurveParams contains the parameters for the secp256k1 curve. +type CurveParams = secp.CurveParams - // Provided for convenience since this gets computed repeatedly. - secp256k1.byteSize = secp256k1.BitSize / 8 - - // Deserialize and set the pre-computed table used to accelerate scalar - // base multiplication. This is hard-coded data, so any errors are - // panics because it means something is wrong in the source code. - if err := loadS256BytePoints(); err != nil { - panic(err) - } - - // Next 6 constants are from Hal Finney's bitcointalk.org post: - // https://bitcointalk.org/index.php?topic=3238.msg45565#msg45565 - // May he rest in peace. - // - // They have also been independently derived from the code in the - // EndomorphismVectors function in gensecp256k1.go. - secp256k1.lambda = fromHex("5363AD4CC05C30E0A5261C028812645A122E22EA20816678DF02967C1B23BD72") - secp256k1.beta = new(fieldVal).SetHex("7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE") - secp256k1.a1 = fromHex("3086D221A7D46BCDE86C90E49284EB15") - secp256k1.b1 = fromHex("-E4437ED6010E88286F547FA90ABFE4C3") - secp256k1.a2 = fromHex("114CA50F7A8E2F3F657C1108D9D44CFD8") - secp256k1.b2 = fromHex("3086D221A7D46BCDE86C90E49284EB15") - - // Alternatively, we can use the parameters below, however, they seem - // to be about 8% slower. - // secp256k1.lambda = fromHex("AC9C52B33FA3CF1F5AD9E3FD77ED9BA4A880B9FC8EC739C2E0CFC810B51283CE") - // secp256k1.beta = new(fieldVal).SetHex("851695D49A83F8EF919BB86153CBCB16630FB68AED0A766A3EC693D68E6AFA40") - // secp256k1.a1 = fromHex("E4437ED6010E88286F547FA90ABFE4C3") - // secp256k1.b1 = fromHex("-3086D221A7D46BCDE86C90E49284EB15") - // secp256k1.a2 = fromHex("3086D221A7D46BCDE86C90E49284EB15") - // secp256k1.b2 = fromHex("114CA50F7A8E2F3F657C1108D9D44CFD8") -} - -// S256 returns a Curve which implements secp256k1. -func S256() *KoblitzCurve { - initonce.Do(initAll) - return &secp256k1 +// Params returns the secp256k1 curve parameters for convenience. +func Params() *CurveParams { + return secp.Params() } diff --git a/btcec/btcec_test.go b/btcec/btcec_test.go index 42a69037bc..5fdd638f22 100644 --- a/btcec/btcec_test.go +++ b/btcec/btcec_test.go @@ -15,17 +15,17 @@ import ( // isJacobianOnS256Curve returns boolean if the point (x,y,z) is on the // secp256k1 curve. -func isJacobianOnS256Curve(x, y, z *fieldVal) bool { +func isJacobianOnS256Curve(point *JacobianPoint) bool { // Elliptic curve equation for secp256k1 is: y^2 = x^3 + 7 // In Jacobian coordinates, Y = y/z^3 and X = x/z^2 // Thus: // (y/z^3)^2 = (x/z^2)^3 + 7 // y^2/z^6 = x^3/z^6 + 7 // y^2 = x^3 + 7*z^6 - var y2, z2, x3, result fieldVal - y2.SquareVal(y).Normalize() - z2.SquareVal(z) - x3.SquareVal(x).Mul(x) + var y2, z2, x3, result FieldVal + y2.SquareVal(&point.Y).Normalize() + z2.SquareVal(&point.Z) + x3.SquareVal(&point.X).Mul(&point.X) result.SquareVal(&z2).Mul(&z2).MulInt(7).Add(&x3).Normalize() return y2.Equals(&result) } @@ -222,43 +222,37 @@ func TestAddJacobian(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - // Convert hex to field values. - x1 := new(fieldVal).SetHex(test.x1) - y1 := new(fieldVal).SetHex(test.y1) - z1 := new(fieldVal).SetHex(test.z1) - x2 := new(fieldVal).SetHex(test.x2) - y2 := new(fieldVal).SetHex(test.y2) - z2 := new(fieldVal).SetHex(test.z2) - x3 := new(fieldVal).SetHex(test.x3) - y3 := new(fieldVal).SetHex(test.y3) - z3 := new(fieldVal).SetHex(test.z3) + // Convert hex to Jacobian points. + p1 := jacobianPointFromHex(test.x1, test.y1, test.z1) + p2 := jacobianPointFromHex(test.x2, test.y2, test.z2) + want := jacobianPointFromHex(test.x3, test.y3, test.z3) // Ensure the test data is using points that are actually on // the curve (or the point at infinity). - if !z1.IsZero() && !isJacobianOnS256Curve(x1, y1, z1) { + if !p1.Z.IsZero() && !isJacobianOnS256Curve(&p1) { t.Errorf("#%d first point is not on the curve -- "+ "invalid test data", i) continue } - if !z2.IsZero() && !isJacobianOnS256Curve(x2, y2, z2) { + if !p2.Z.IsZero() && !isJacobianOnS256Curve(&p2) { t.Errorf("#%d second point is not on the curve -- "+ "invalid test data", i) continue } - if !z3.IsZero() && !isJacobianOnS256Curve(x3, y3, z3) { + if !want.Z.IsZero() && !isJacobianOnS256Curve(&want) { t.Errorf("#%d expected point is not on the curve -- "+ "invalid test data", i) continue } // Add the two points. - rx, ry, rz := new(fieldVal), new(fieldVal), new(fieldVal) - S256().addJacobian(x1, y1, z1, x2, y2, z2, rx, ry, rz) + var r JacobianPoint + AddNonConst(&p1, &p2, &r) // Ensure result matches expected. - if !rx.Equals(x3) || !ry.Equals(y3) || !rz.Equals(z3) { + if !r.X.Equals(&want.X) || !r.Y.Equals(&want.Y) || !r.Z.Equals(&want.Z) { t.Errorf("#%d wrong result\ngot: (%v, %v, %v)\n"+ - "want: (%v, %v, %v)", i, rx, ry, rz, x3, y3, z3) + "want: (%v, %v, %v)", i, r.X, r.Y, r.Z, want.X, want.Y, want.Z) continue } } @@ -360,6 +354,15 @@ func TestAddAffine(t *testing.T) { } } +// isStrictlyEqual returns whether or not the two Jacobian points are strictly +// equal for use in the tests. Recall that several Jacobian points can be +// equal in affine coordinates, while not having the same coordinates in +// projective space, so the two points not being equal doesn't necessarily mean +// they aren't actually the same affine point. +func isStrictlyEqual(p, other *JacobianPoint) bool { + return p.X.Equals(&other.X) && p.Y.Equals(&other.Y) && p.Z.Equals(&other.Z) +} + // TestDoubleJacobian tests doubling of points projected in Jacobian // coordinates. func TestDoubleJacobian(t *testing.T) { @@ -408,34 +411,31 @@ func TestDoubleJacobian(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { // Convert hex to field values. - x1 := new(fieldVal).SetHex(test.x1) - y1 := new(fieldVal).SetHex(test.y1) - z1 := new(fieldVal).SetHex(test.z1) - x3 := new(fieldVal).SetHex(test.x3) - y3 := new(fieldVal).SetHex(test.y3) - z3 := new(fieldVal).SetHex(test.z3) + p1 := jacobianPointFromHex(test.x1, test.y1, test.z1) + want := jacobianPointFromHex(test.x3, test.y3, test.z3) // Ensure the test data is using points that are actually on // the curve (or the point at infinity). - if !z1.IsZero() && !isJacobianOnS256Curve(x1, y1, z1) { + if !p1.Z.IsZero() && !isJacobianOnS256Curve(&p1) { t.Errorf("#%d first point is not on the curve -- "+ "invalid test data", i) continue } - if !z3.IsZero() && !isJacobianOnS256Curve(x3, y3, z3) { + if !want.Z.IsZero() && !isJacobianOnS256Curve(&want) { t.Errorf("#%d expected point is not on the curve -- "+ "invalid test data", i) continue } // Double the point. - rx, ry, rz := new(fieldVal), new(fieldVal), new(fieldVal) - S256().doubleJacobian(x1, y1, z1, rx, ry, rz) + var result JacobianPoint + DoubleNonConst(&p1, &result) // Ensure result matches expected. - if !rx.Equals(x3) || !ry.Equals(y3) || !rz.Equals(z3) { + if !isStrictlyEqual(&result, &want) { t.Errorf("#%d wrong result\ngot: (%v, %v, %v)\n"+ - "want: (%v, %v, %v)", i, rx, ry, rz, x3, y3, z3) + "want: (%v, %v, %v)", i, result.X, result.Y, result.Z, + want.X, want.Y, want.Z) continue } } @@ -663,6 +663,64 @@ func TestScalarMultRand(t *testing.T) { } } +var ( + // Next 6 constants are from Hal Finney's bitcointalk.org post: + // https://bitcointalk.org/index.php?topic=3238.msg45565#msg45565 + // May he rest in peace. + // + // They have also been independently derived from the code in the + // EndomorphismVectors function in genstatics.go. + endomorphismLambda = fromHex("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72") + endomorphismBeta = hexToFieldVal("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee") + endomorphismA1 = fromHex("3086d221a7d46bcde86c90e49284eb15") + endomorphismB1 = fromHex("-e4437ed6010e88286f547fa90abfe4c3") + endomorphismA2 = fromHex("114ca50f7a8e2f3f657c1108d9d44cfd8") + endomorphismB2 = fromHex("3086d221a7d46bcde86c90e49284eb15") +) + +// splitK returns a balanced length-two representation of k and their signs. +// This is algorithm 3.74 from [GECC]. +// +// One thing of note about this algorithm is that no matter what c1 and c2 are, +// the final equation of k = k1 + k2 * lambda (mod n) will hold. This is +// provable mathematically due to how a1/b1/a2/b2 are computed. +// +// c1 and c2 are chosen to minimize the max(k1,k2). +func splitK(k []byte) ([]byte, []byte, int, int) { + // All math here is done with big.Int, which is slow. + // At some point, it might be useful to write something similar to + // FieldVal but for N instead of P as the prime field if this ends up + // being a bottleneck. + bigIntK := new(big.Int) + c1, c2 := new(big.Int), new(big.Int) + tmp1, tmp2 := new(big.Int), new(big.Int) + k1, k2 := new(big.Int), new(big.Int) + + bigIntK.SetBytes(k) + // c1 = round(b2 * k / n) from step 4. + // Rounding isn't really necessary and costs too much, hence skipped + c1.Mul(endomorphismB2, bigIntK) + c1.Div(c1, Params().N) + // c2 = round(b1 * k / n) from step 4 (sign reversed to optimize one step) + // Rounding isn't really necessary and costs too much, hence skipped + c2.Mul(endomorphismB1, bigIntK) + c2.Div(c2, Params().N) + // k1 = k - c1 * a1 - c2 * a2 from step 5 (note c2's sign is reversed) + tmp1.Mul(c1, endomorphismA1) + tmp2.Mul(c2, endomorphismA2) + k1.Sub(bigIntK, tmp1) + k1.Add(k1, tmp2) + // k2 = - c1 * b1 - c2 * b2 from step 5 (note c2's sign is reversed) + tmp1.Mul(c1, endomorphismB1) + tmp2.Mul(c2, endomorphismB2) + k2.Sub(tmp2, tmp1) + + // Note Bytes() throws out the sign of k1 and k2. This matters + // since k1 and/or k2 can be negative. Hence, we pass that + // back separately. + return k1.Bytes(), k2.Bytes(), k1.Sign(), k2.Sign() +} + func TestSplitK(t *testing.T) { tests := []struct { k string @@ -719,7 +777,7 @@ func TestSplitK(t *testing.T) { if !ok { t.Errorf("%d: bad value for k: %s", i, test.k) } - k1, k2, k1Sign, k2Sign := s256.splitK(k.Bytes()) + k1, k2, k1Sign, k2Sign := splitK(k.Bytes()) k1str := fmt.Sprintf("%064x", k1) if test.k1 != k1str { t.Errorf("%d: bad k1: got %v, want %v", i, k1str, test.k1) @@ -740,7 +798,7 @@ func TestSplitK(t *testing.T) { k2Int := new(big.Int).SetBytes(k2) k2SignInt := new(big.Int).SetInt64(int64(k2Sign)) k2Int.Mul(k2Int, k2SignInt) - gotK := new(big.Int).Mul(k2Int, s256.lambda) + gotK := new(big.Int).Mul(k2Int, endomorphismLambda) gotK.Add(k1Int, gotK) gotK.Mod(gotK, s256.N) if k.Cmp(gotK) != 0 { @@ -759,14 +817,14 @@ func TestSplitKRand(t *testing.T) { break } k := new(big.Int).SetBytes(bytesK) - k1, k2, k1Sign, k2Sign := s256.splitK(bytesK) + k1, k2, k1Sign, k2Sign := splitK(bytesK) k1Int := new(big.Int).SetBytes(k1) k1SignInt := new(big.Int).SetInt64(int64(k1Sign)) k1Int.Mul(k1Int, k1SignInt) k2Int := new(big.Int).SetBytes(k2) k2SignInt := new(big.Int).SetInt64(int64(k2Sign)) k2Int.Mul(k2Int, k2SignInt) - gotK := new(big.Int).Mul(k2Int, s256.lambda) + gotK := new(big.Int).Mul(k2Int, endomorphismLambda) gotK.Add(k1Int, gotK) gotK.Mod(gotK, s256.N) if k.Cmp(gotK) != 0 { @@ -778,12 +836,13 @@ func TestSplitKRand(t *testing.T) { // Test this curve's usage with the ecdsa package. func testKeyGeneration(t *testing.T, c *KoblitzCurve, tag string) { - priv, err := NewPrivateKey(c) + priv, err := NewPrivateKey() if err != nil { t.Errorf("%s: error: %s", tag, err) return } - if !c.IsOnCurve(priv.PublicKey.X, priv.PublicKey.Y) { + pub := priv.PubKey() + if !c.IsOnCurve(pub.X(), pub.Y()) { t.Errorf("%s: public key invalid: %s", tag, err) } } @@ -793,15 +852,11 @@ func TestKeyGeneration(t *testing.T) { } func testSignAndVerify(t *testing.T, c *KoblitzCurve, tag string) { - priv, _ := NewPrivateKey(c) + priv, _ := NewPrivateKey() pub := priv.PubKey() hashed := []byte("testing") - sig, err := priv.Sign(hashed) - if err != nil { - t.Errorf("%s: error signing: %s", tag, err) - return - } + sig := Sign(priv, hashed) if !sig.Verify(hashed, pub) { t.Errorf("%s: Verify failed", tag) @@ -817,73 +872,41 @@ func TestSignAndVerify(t *testing.T) { testSignAndVerify(t, S256(), "S256") } -func TestNAF(t *testing.T) { - tests := []string{ - "6df2b5d30854069ccdec40ae022f5c948936324a4e9ebed8eb82cfd5a6b6d766", - "b776e53fb55f6b006a270d42d64ec2b1", - "d6cc32c857f1174b604eefc544f0c7f7", - "45c53aa1bb56fcd68c011e2dad6758e4", - "a2e79d200f27f2360fba57619936159b", +// checkNAFEncoding returns an error if the provided positive and negative +// portions of an overall NAF encoding do not adhere to the requirements or they +// do not sum back to the provided original value. +func checkNAFEncoding(pos, neg []byte, origValue *big.Int) error { + // NAF must not have a leading zero byte and the number of negative + // bytes must not exceed the positive portion. + if len(pos) > 0 && pos[0] == 0 { + return fmt.Errorf("positive has leading zero -- got %x", pos) } - negOne := big.NewInt(-1) - one := big.NewInt(1) - two := big.NewInt(2) - for i, test := range tests { - want, _ := new(big.Int).SetString(test, 16) - nafPos, nafNeg := NAF(want.Bytes()) - got := big.NewInt(0) - // Check that the NAF representation comes up with the right number - for i := 0; i < len(nafPos); i++ { - bytePos := nafPos[i] - byteNeg := nafNeg[i] - for j := 7; j >= 0; j-- { - got.Mul(got, two) - if bytePos&0x80 == 0x80 { - got.Add(got, one) - } else if byteNeg&0x80 == 0x80 { - got.Add(got, negOne) - } - bytePos <<= 1 - byteNeg <<= 1 - } - } - if got.Cmp(want) != 0 { - t.Errorf("%d: Failed NAF got %X want %X", i, got, want) - } + if len(neg) > len(pos) { + return fmt.Errorf("negative has len %d > pos len %d", len(neg), + len(pos)) } -} -func TestNAFRand(t *testing.T) { - negOne := big.NewInt(-1) - one := big.NewInt(1) - two := big.NewInt(2) - for i := 0; i < 1024; i++ { - data := make([]byte, 32) - _, err := rand.Read(data) - if err != nil { - t.Fatalf("failed to read random data at %d", i) - break - } - nafPos, nafNeg := NAF(data) - want := new(big.Int).SetBytes(data) - got := big.NewInt(0) - // Check that the NAF representation comes up with the right number - for i := 0; i < len(nafPos); i++ { - bytePos := nafPos[i] - byteNeg := nafNeg[i] - for j := 7; j >= 0; j-- { - got.Mul(got, two) - if bytePos&0x80 == 0x80 { - got.Add(got, one) - } else if byteNeg&0x80 == 0x80 { - got.Add(got, negOne) - } - bytePos <<= 1 - byteNeg <<= 1 - } - } - if got.Cmp(want) != 0 { - t.Errorf("%d: Failed NAF got %X want %X", i, got, want) - } + // Ensure the result doesn't have any adjacent non-zero digits. + gotPos := new(big.Int).SetBytes(pos) + gotNeg := new(big.Int).SetBytes(neg) + posOrNeg := new(big.Int).Or(gotPos, gotNeg) + prevBit := posOrNeg.Bit(0) + for bit := 1; bit < posOrNeg.BitLen(); bit++ { + thisBit := posOrNeg.Bit(bit) + if prevBit == 1 && thisBit == 1 { + return fmt.Errorf("adjacent non-zero digits found at bit pos %d", + bit-1) + } + prevBit = thisBit } + + // Ensure the resulting positive and negative portions of the overall + // NAF representation sum back to the original value. + gotValue := new(big.Int).Sub(gotPos, gotNeg) + if origValue.Cmp(gotValue) != 0 { + return fmt.Errorf("pos-neg is not original value: got %x, want %x", + gotValue, origValue) + } + + return nil } diff --git a/btcec/ciphering.go b/btcec/ciphering.go index b18c9b7a30..88d93e2766 100644 --- a/btcec/ciphering.go +++ b/btcec/ciphering.go @@ -5,212 +5,12 @@ package btcec import ( - "bytes" - "crypto/aes" - "crypto/cipher" - "crypto/hmac" - "crypto/rand" - "crypto/sha256" - "crypto/sha512" - "errors" - "io" -) - -var ( - // ErrInvalidMAC occurs when Message Authentication Check (MAC) fails - // during decryption. This happens because of either invalid private key or - // corrupt ciphertext. - ErrInvalidMAC = errors.New("invalid mac hash") - - // errInputTooShort occurs when the input ciphertext to the Decrypt - // function is less than 134 bytes long. - errInputTooShort = errors.New("ciphertext too short") - - // errUnsupportedCurve occurs when the first two bytes of the encrypted - // text aren't 0x02CA (= 712 = secp256k1, from OpenSSL). - errUnsupportedCurve = errors.New("unsupported curve") - - errInvalidXLength = errors.New("invalid X length, must be 32") - errInvalidYLength = errors.New("invalid Y length, must be 32") - errInvalidPadding = errors.New("invalid PKCS#7 padding") - - // 0x02CA = 714 - ciphCurveBytes = [2]byte{0x02, 0xCA} - // 0x20 = 32 - ciphCoordLength = [2]byte{0x00, 0x20} + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) // GenerateSharedSecret generates a shared secret based on a private key and a // public key using Diffie-Hellman key exchange (ECDH) (RFC 4753). // RFC5903 Section 9 states we should only return x. func GenerateSharedSecret(privkey *PrivateKey, pubkey *PublicKey) []byte { - x, _ := pubkey.Curve.ScalarMult(pubkey.X, pubkey.Y, privkey.D.Bytes()) - return x.Bytes() -} - -// Encrypt encrypts data for the target public key using AES-256-CBC. It also -// generates a private key (the pubkey of which is also in the output). The only -// supported curve is secp256k1. The `structure' that it encodes everything into -// is: -// -// struct { -// // Initialization Vector used for AES-256-CBC -// IV [16]byte -// // Public Key: curve(2) + len_of_pubkeyX(2) + pubkeyX + -// // len_of_pubkeyY(2) + pubkeyY (curve = 714) -// PublicKey [70]byte -// // Cipher text -// Data []byte -// // HMAC-SHA-256 Message Authentication Code -// HMAC [32]byte -// } -// -// The primary aim is to ensure byte compatibility with Pyelliptic. Also, refer -// to section 5.8.1 of ANSI X9.63 for rationale on this format. -func Encrypt(pubkey *PublicKey, in []byte) ([]byte, error) { - ephemeral, err := NewPrivateKey(S256()) - if err != nil { - return nil, err - } - ecdhKey := GenerateSharedSecret(ephemeral, pubkey) - derivedKey := sha512.Sum512(ecdhKey) - keyE := derivedKey[:32] - keyM := derivedKey[32:] - - paddedIn := addPKCSPadding(in) - // IV + Curve params/X/Y + padded plaintext/ciphertext + HMAC-256 - out := make([]byte, aes.BlockSize+70+len(paddedIn)+sha256.Size) - iv := out[:aes.BlockSize] - if _, err = io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - // start writing public key - pb := ephemeral.PubKey().SerializeUncompressed() - offset := aes.BlockSize - - // curve and X length - copy(out[offset:offset+4], append(ciphCurveBytes[:], ciphCoordLength[:]...)) - offset += 4 - // X - copy(out[offset:offset+32], pb[1:33]) - offset += 32 - // Y length - copy(out[offset:offset+2], ciphCoordLength[:]) - offset += 2 - // Y - copy(out[offset:offset+32], pb[33:]) - offset += 32 - - // start encryption - block, err := aes.NewCipher(keyE) - if err != nil { - return nil, err - } - mode := cipher.NewCBCEncrypter(block, iv) - mode.CryptBlocks(out[offset:len(out)-sha256.Size], paddedIn) - - // start HMAC-SHA-256 - hm := hmac.New(sha256.New, keyM) - hm.Write(out[:len(out)-sha256.Size]) // everything is hashed - copy(out[len(out)-sha256.Size:], hm.Sum(nil)) // write checksum - - return out, nil -} - -// Decrypt decrypts data that was encrypted using the Encrypt function. -func Decrypt(priv *PrivateKey, in []byte) ([]byte, error) { - // IV + Curve params/X/Y + 1 block + HMAC-256 - if len(in) < aes.BlockSize+70+aes.BlockSize+sha256.Size { - return nil, errInputTooShort - } - - // read iv - iv := in[:aes.BlockSize] - offset := aes.BlockSize - - // start reading pubkey - if !bytes.Equal(in[offset:offset+2], ciphCurveBytes[:]) { - return nil, errUnsupportedCurve - } - offset += 2 - - if !bytes.Equal(in[offset:offset+2], ciphCoordLength[:]) { - return nil, errInvalidXLength - } - offset += 2 - - xBytes := in[offset : offset+32] - offset += 32 - - if !bytes.Equal(in[offset:offset+2], ciphCoordLength[:]) { - return nil, errInvalidYLength - } - offset += 2 - - yBytes := in[offset : offset+32] - offset += 32 - - pb := make([]byte, 65) - pb[0] = byte(0x04) // uncompressed - copy(pb[1:33], xBytes) - copy(pb[33:], yBytes) - // check if (X, Y) lies on the curve and create a Pubkey if it does - pubkey, err := ParsePubKey(pb, S256()) - if err != nil { - return nil, err - } - - // check for cipher text length - if (len(in)-aes.BlockSize-offset-sha256.Size)%aes.BlockSize != 0 { - return nil, errInvalidPadding // not padded to 16 bytes - } - - // read hmac - messageMAC := in[len(in)-sha256.Size:] - - // generate shared secret - ecdhKey := GenerateSharedSecret(priv, pubkey) - derivedKey := sha512.Sum512(ecdhKey) - keyE := derivedKey[:32] - keyM := derivedKey[32:] - - // verify mac - hm := hmac.New(sha256.New, keyM) - hm.Write(in[:len(in)-sha256.Size]) // everything is hashed - expectedMAC := hm.Sum(nil) - if !hmac.Equal(messageMAC, expectedMAC) { - return nil, ErrInvalidMAC - } - - // start decryption - block, err := aes.NewCipher(keyE) - if err != nil { - return nil, err - } - mode := cipher.NewCBCDecrypter(block, iv) - // same length as ciphertext - plaintext := make([]byte, len(in)-offset-sha256.Size) - mode.CryptBlocks(plaintext, in[offset:len(in)-sha256.Size]) - - return removePKCSPadding(plaintext) -} - -// Implement PKCS#7 padding with block size of 16 (AES block size). - -// addPKCSPadding adds padding to a block of data -func addPKCSPadding(src []byte) []byte { - padding := aes.BlockSize - len(src)%aes.BlockSize - padtext := bytes.Repeat([]byte{byte(padding)}, padding) - return append(src, padtext...) -} - -// removePKCSPadding removes padding from data that was added with addPKCSPadding -func removePKCSPadding(src []byte) ([]byte, error) { - length := len(src) - padLength := int(src[length-1]) - if padLength > aes.BlockSize || length < aes.BlockSize { - return nil, errInvalidPadding - } - - return src[:length-padLength], nil + return secp.GenerateSharedSecret(privkey, pubkey) } diff --git a/btcec/ciphering_test.go b/btcec/ciphering_test.go index 819f18846c..c6bea3da73 100644 --- a/btcec/ciphering_test.go +++ b/btcec/ciphering_test.go @@ -6,17 +6,16 @@ package btcec import ( "bytes" - "encoding/hex" "testing" ) func TestGenerateSharedSecret(t *testing.T) { - privKey1, err := NewPrivateKey(S256()) + privKey1, err := NewPrivateKey() if err != nil { t.Errorf("private key generation error: %s", err) return } - privKey2, err := NewPrivateKey(S256()) + privKey2, err := NewPrivateKey() if err != nil { t.Errorf("private key generation error: %s", err) return @@ -30,145 +29,3 @@ func TestGenerateSharedSecret(t *testing.T) { secret1, secret2) } } - -// Test 1: Encryption and decryption -func TestCipheringBasic(t *testing.T) { - privkey, err := NewPrivateKey(S256()) - if err != nil { - t.Fatal("failed to generate private key") - } - - in := []byte("Hey there dude. How are you doing? This is a test.") - - out, err := Encrypt(privkey.PubKey(), in) - if err != nil { - t.Fatal("failed to encrypt:", err) - } - - dec, err := Decrypt(privkey, out) - if err != nil { - t.Fatal("failed to decrypt:", err) - } - - if !bytes.Equal(in, dec) { - t.Error("decrypted data doesn't match original") - } -} - -// Test 2: Byte compatibility with Pyelliptic -func TestCiphering(t *testing.T) { - pb, _ := hex.DecodeString("fe38240982f313ae5afb3e904fb8215fb11af1200592b" + - "fca26c96c4738e4bf8f") - privkey, _ := PrivKeyFromBytes(S256(), pb) - - in := []byte("This is just a test.") - out, _ := hex.DecodeString("b0d66e5adaa5ed4e2f0ca68e17b8f2fc02ca002009e3" + - "3487e7fa4ab505cf34d98f131be7bd258391588ca7804acb30251e71a04e0020ecf" + - "df0f84608f8add82d7353af780fbb28868c713b7813eb4d4e61f7b75d7534dd9856" + - "9b0ba77cf14348fcff80fee10e11981f1b4be372d93923e9178972f69937ec850ed" + - "6c3f11ff572ddd5b2bedf9f9c0b327c54da02a28fcdce1f8369ffec") - - dec, err := Decrypt(privkey, out) - if err != nil { - t.Fatal("failed to decrypt:", err) - } - - if !bytes.Equal(in, dec) { - t.Error("decrypted data doesn't match original") - } -} - -func TestCipheringErrors(t *testing.T) { - privkey, err := NewPrivateKey(S256()) - if err != nil { - t.Fatal("failed to generate private key") - } - - tests1 := []struct { - ciphertext []byte // input ciphertext - }{ - {bytes.Repeat([]byte{0x00}, 133)}, // errInputTooShort - {bytes.Repeat([]byte{0x00}, 134)}, // errUnsupportedCurve - {bytes.Repeat([]byte{0x02, 0xCA}, 134)}, // errInvalidXLength - {bytes.Repeat([]byte{0x02, 0xCA, 0x00, 0x20}, 134)}, // errInvalidYLength - {[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xCA, 0x00, 0x20, // curve and X length - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // X - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x20, // Y length - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Y - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }}, // invalid pubkey - {[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xCA, 0x00, 0x20, // curve and X length - 0x11, 0x5C, 0x42, 0xE7, 0x57, 0xB2, 0xEF, 0xB7, // X - 0x67, 0x1C, 0x57, 0x85, 0x30, 0xEC, 0x19, 0x1A, - 0x13, 0x59, 0x38, 0x1E, 0x6A, 0x71, 0x12, 0x7A, - 0x9D, 0x37, 0xC4, 0x86, 0xFD, 0x30, 0xDA, 0xE5, - 0x00, 0x20, // Y length - 0x7E, 0x76, 0xDC, 0x58, 0xF6, 0x93, 0xBD, 0x7E, // Y - 0x70, 0x10, 0x35, 0x8C, 0xE6, 0xB1, 0x65, 0xE4, - 0x83, 0xA2, 0x92, 0x10, 0x10, 0xDB, 0x67, 0xAC, - 0x11, 0xB1, 0xB5, 0x1B, 0x65, 0x19, 0x53, 0xD2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext - // padding not aligned to 16 bytes - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }}, // errInvalidPadding - {[]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // IV - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0xCA, 0x00, 0x20, // curve and X length - 0x11, 0x5C, 0x42, 0xE7, 0x57, 0xB2, 0xEF, 0xB7, // X - 0x67, 0x1C, 0x57, 0x85, 0x30, 0xEC, 0x19, 0x1A, - 0x13, 0x59, 0x38, 0x1E, 0x6A, 0x71, 0x12, 0x7A, - 0x9D, 0x37, 0xC4, 0x86, 0xFD, 0x30, 0xDA, 0xE5, - 0x00, 0x20, // Y length - 0x7E, 0x76, 0xDC, 0x58, 0xF6, 0x93, 0xBD, 0x7E, // Y - 0x70, 0x10, 0x35, 0x8C, 0xE6, 0xB1, 0x65, 0xE4, - 0x83, 0xA2, 0x92, 0x10, 0x10, 0xDB, 0x67, 0xAC, - 0x11, 0xB1, 0xB5, 0x1B, 0x65, 0x19, 0x53, 0xD2, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ciphertext - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MAC - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }}, // ErrInvalidMAC - } - - for i, test := range tests1 { - _, err = Decrypt(privkey, test.ciphertext) - if err == nil { - t.Errorf("Decrypt #%d did not get error", i) - } - } - - // test error from removePKCSPadding - tests2 := []struct { - in []byte // input data - }{ - {bytes.Repeat([]byte{0x11}, 17)}, - {bytes.Repeat([]byte{0x07}, 15)}, - } - for i, test := range tests2 { - _, err = removePKCSPadding(test.in) - if err == nil { - t.Errorf("removePKCSPadding #%d did not get error", i) - } - } -} diff --git a/btcec/curve.go b/btcec/curve.go new file mode 100644 index 0000000000..b86c591374 --- /dev/null +++ b/btcec/curve.go @@ -0,0 +1,60 @@ +package btcec + +import ( + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +// JacobianPoint is an element of the group formed by the secp256k1 curve in +// Jacobian projective coordinates and thus represents a point on the curve. +type JacobianPoint = secp.JacobianPoint + +// MakeJacobianPoint returns a Jacobian point with the provided X, Y, and Z +// coordinates. +func MakeJacobianPoint(x, y, z *FieldVal) JacobianPoint { + return secp.MakeJacobianPoint(x, y, z) +} + +// AddNonConst adds the passed Jacobian points together and stores the result +// in the provided result param in *non-constant* time. +func AddNonConst(p1, p2, result *JacobianPoint) { + secp.AddNonConst(p1, p2, result) +} + +// DecompressY attempts to calculate the Y coordinate for the given X +// coordinate such that the result pair is a point on the secp256k1 curve. It +// adjusts Y based on the desired oddness and returns whether or not it was +// successful since not all X coordinates are valid. +// +// The magnitude of the provided X coordinate field val must be a max of 8 for +// a correct result. The resulting Y field val will have a max magnitude of 2. +func DecompressY(x *FieldVal, odd bool, resultY *FieldVal) bool { + return secp.DecompressY(x, odd, resultY) +} + +// DoubleNonConst doubles the passed Jacobian point and stores the result in +// the provided result parameter in *non-constant* time. +// +// NOTE: The point must be normalized for this function to return the correct +// result. The resulting point will be normalized. +func DoubleNonConst(p, result *JacobianPoint) { + secp.DoubleNonConst(p, result) +} + +// ScalarBaseMultNonConst multiplies k*G where G is the base point of the group +// and k is a big endian integer. The result is stored in Jacobian coordinates +// (x1, y1, z1). +// +// NOTE: The resulting point will be normalized. +func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) { + secp.ScalarBaseMultNonConst(k, result) +} + +// ScalarMultNonConst multiplies k*P where k is a big endian integer modulo the +// curve order and P is a point in Jacobian projective coordinates and stores +// the result in the provided Jacobian point. +// +// NOTE: The point must be normalized for this function to return the correct +// result. The resulting point will be normalized. +func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint) { + secp.ScalarMultNonConst(k, point, result) +} diff --git a/btcec/error.go b/btcec/error.go new file mode 100644 index 0000000000..39c9172bc3 --- /dev/null +++ b/btcec/error.go @@ -0,0 +1,16 @@ +package btcec + +import ( + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +// Error identifies an error related to public key cryptography using a +// sec256k1 curve. It has full support for errors.Is and errors.As, so the +// caller can ascertain the specific reason for the error by checking the +// underlying error. +type Error = secp.Error + +// ErrorKind identifies a kind of error. It has full support for errors.Is and +// errors.As, so the caller can directly check against an error kind when +// determining the reason for an error. +type ErrorKind = secp.ErrorKind diff --git a/btcec/example_test.go b/btcec/example_test.go index ca51ee87cc..b73f102c32 100644 --- a/btcec/example_test.go +++ b/btcec/example_test.go @@ -8,7 +8,7 @@ import ( "encoding/hex" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -22,16 +22,12 @@ func Example_signMessage() { fmt.Println(err) return } - privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes) + privKey, pubKey := btcec.PrivKeyFromBytes(pkBytes) // Sign a message using the private key. message := "test message" messageHash := chainhash.DoubleHashB([]byte(message)) - signature, err := privKey.Sign(messageHash) - if err != nil { - fmt.Println(err) - return - } + signature := btcec.Sign(privKey, messageHash) // Serialize and display the signature. fmt.Printf("Serialized Signature: %x\n", signature.Serialize()) @@ -56,7 +52,7 @@ func Example_verifySignature() { fmt.Println(err) return } - pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) + pubKey, err := btcec.ParsePubKey(pubKeyBytes) if err != nil { fmt.Println(err) return @@ -71,7 +67,7 @@ func Example_verifySignature() { fmt.Println(err) return } - signature, err := btcec.ParseSignature(sigBytes, btcec.S256()) + signature, err := btcec.ParseSignature(sigBytes) if err != nil { fmt.Println(err) return @@ -86,83 +82,3 @@ func Example_verifySignature() { // Output: // Signature Verified? true } - -// This example demonstrates encrypting a message for a public key that is first -// parsed from raw bytes, then decrypting it using the corresponding private key. -func Example_encryptMessage() { - // Decode the hex-encoded pubkey of the recipient. - pubKeyBytes, err := hex.DecodeString("04115c42e757b2efb7671c578530ec191a1" + - "359381e6a71127a9d37c486fd30dae57e76dc58f693bd7e7010358ce6b165e483a29" + - "21010db67ac11b1b51b651953d2") // uncompressed pubkey - if err != nil { - fmt.Println(err) - return - } - pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) - if err != nil { - fmt.Println(err) - return - } - - // Encrypt a message decryptable by the private key corresponding to pubKey - message := "test message" - ciphertext, err := btcec.Encrypt(pubKey, []byte(message)) - if err != nil { - fmt.Println(err) - return - } - - // Decode the hex-encoded private key. - pkBytes, err := hex.DecodeString("a11b0a4e1a132305652ee7a8eb7848f6ad" + - "5ea381e3ce20a2c086a2e388230811") - if err != nil { - fmt.Println(err) - return - } - // note that we already have corresponding pubKey - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes) - - // Try decrypting and verify if it's the same message. - plaintext, err := btcec.Decrypt(privKey, ciphertext) - if err != nil { - fmt.Println(err) - return - } - - fmt.Println(string(plaintext)) - - // Output: - // test message -} - -// This example demonstrates decrypting a message using a private key that is -// first parsed from raw bytes. -func Example_decryptMessage() { - // Decode the hex-encoded private key. - pkBytes, err := hex.DecodeString("a11b0a4e1a132305652ee7a8eb7848f6ad" + - "5ea381e3ce20a2c086a2e388230811") - if err != nil { - fmt.Println(err) - return - } - - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), pkBytes) - - ciphertext, err := hex.DecodeString("35f644fbfb208bc71e57684c3c8b437402ca" + - "002047a2f1b38aa1a8f1d5121778378414f708fe13ebf7b4a7bb74407288c1958969" + - "00207cf4ac6057406e40f79961c973309a892732ae7a74ee96cd89823913b8b8d650" + - "a44166dc61ea1c419d47077b748a9c06b8d57af72deb2819d98a9d503efc59fc8307" + - "d14174f8b83354fac3ff56075162") - - // Try decrypting the message. - plaintext, err := btcec.Decrypt(privKey, ciphertext) - if err != nil { - fmt.Println(err) - return - } - - fmt.Println(string(plaintext)) - - // Output: - // test message -} diff --git a/btcec/field.go b/btcec/field.go index 98105ed8e4..fef6f345da 100644 --- a/btcec/field.go +++ b/btcec/field.go @@ -1,1356 +1,43 @@ -// Copyright (c) 2013-2016 The btcsuite developers -// Copyright (c) 2013-2016 Dave Collins -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - package btcec -// References: -// [HAC]: Handbook of Applied Cryptography Menezes, van Oorschot, Vanstone. -// http://cacr.uwaterloo.ca/hac/ - -// All elliptic curve operations for secp256k1 are done in a finite field -// characterized by a 256-bit prime. Given this precision is larger than the -// biggest available native type, obviously some form of bignum math is needed. -// This package implements specialized fixed-precision field arithmetic rather -// than relying on an arbitrary-precision arithmetic package such as math/big -// for dealing with the field math since the size is known. As a result, rather -// large performance gains are achieved by taking advantage of many -// optimizations not available to arbitrary-precision arithmetic and generic -// modular arithmetic algorithms. -// -// There are various ways to internally represent each finite field element. -// For example, the most obvious representation would be to use an array of 4 -// uint64s (64 bits * 4 = 256 bits). However, that representation suffers from -// a couple of issues. First, there is no native Go type large enough to handle -// the intermediate results while adding or multiplying two 64-bit numbers, and -// second there is no space left for overflows when performing the intermediate -// arithmetic between each array element which would lead to expensive carry -// propagation. -// -// Given the above, this implementation represents the the field elements as -// 10 uint32s with each word (array entry) treated as base 2^26. This was -// chosen for the following reasons: -// 1) Most systems at the current time are 64-bit (or at least have 64-bit -// registers available for specialized purposes such as MMX) so the -// intermediate results can typically be done using a native register (and -// using uint64s to avoid the need for additional half-word arithmetic) -// 2) In order to allow addition of the internal words without having to -// propagate the the carry, the max normalized value for each register must -// be less than the number of bits available in the register -// 3) Since we're dealing with 32-bit values, 64-bits of overflow is a -// reasonable choice for #2 -// 4) Given the need for 256-bits of precision and the properties stated in #1, -// #2, and #3, the representation which best accommodates this is 10 uint32s -// with base 2^26 (26 bits * 10 = 260 bits, so the final word only needs 22 -// bits) which leaves the desired 64 bits (32 * 10 = 320, 320 - 256 = 64) for -// overflow -// -// Since it is so important that the field arithmetic is extremely fast for -// high performance crypto, this package does not perform any validation where -// it ordinarily would. For example, some functions only give the correct -// result is the field is normalized and there is no checking to ensure it is. -// While I typically prefer to ensure all state and input is valid for most -// packages, this code is really only used internally and every extra check -// counts. - -import ( - "encoding/hex" -) - -// Constants used to make the code more readable. -const ( - twoBitsMask = 0x3 - fourBitsMask = 0xf - sixBitsMask = 0x3f - eightBitsMask = 0xff -) - -// Constants related to the field representation. -const ( - // fieldWords is the number of words used to internally represent the - // 256-bit value. - fieldWords = 10 - - // fieldBase is the exponent used to form the numeric base of each word. - // 2^(fieldBase*i) where i is the word position. - fieldBase = 26 - - // fieldOverflowBits is the minimum number of "overflow" bits for each - // word in the field value. - fieldOverflowBits = 32 - fieldBase - - // fieldBaseMask is the mask for the bits in each word needed to - // represent the numeric base of each word (except the most significant - // word). - fieldBaseMask = (1 << fieldBase) - 1 - - // fieldMSBBits is the number of bits in the most significant word used - // to represent the value. - fieldMSBBits = 256 - (fieldBase * (fieldWords - 1)) - - // fieldMSBMask is the mask for the bits in the most significant word - // needed to represent the value. - fieldMSBMask = (1 << fieldMSBBits) - 1 - - // fieldPrimeWordZero is word zero of the secp256k1 prime in the - // internal field representation. It is used during negation. - fieldPrimeWordZero = 0x3fffc2f - - // fieldPrimeWordOne is word one of the secp256k1 prime in the - // internal field representation. It is used during negation. - fieldPrimeWordOne = 0x3ffffbf -) - -var ( - // fieldQBytes is the value Q = (P+1)/4 for the secp256k1 prime P. This - // value is used to efficiently compute the square root of values in the - // field via exponentiation. The value of Q in hex is: - // - // Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c - fieldQBytes = []byte{ - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0x0c, - } -) - -// fieldVal implements optimized fixed-precision arithmetic over the -// secp256k1 finite field. This means all arithmetic is performed modulo -// 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f. It -// represents each 256-bit value as 10 32-bit integers in base 2^26. This -// provides 6 bits of overflow in each word (10 bits in the most significant -// word) for a total of 64 bits of overflow (9*6 + 10 = 64). It only implements -// the arithmetic needed for elliptic curve operations. -// -// The following depicts the internal representation: -// ----------------------------------------------------------------- -// | n[9] | n[8] | ... | n[0] | -// | 32 bits available | 32 bits available | ... | 32 bits available | -// | 22 bits for value | 26 bits for value | ... | 26 bits for value | -// | 10 bits overflow | 6 bits overflow | ... | 6 bits overflow | -// | Mult: 2^(26*9) | Mult: 2^(26*8) | ... | Mult: 2^(26*0) | -// ----------------------------------------------------------------- -// -// For example, consider the number 2^49 + 1. It would be represented as: -// n[0] = 1 -// n[1] = 2^23 -// n[2..9] = 0 -// -// The full 256-bit value is then calculated by looping i from 9..0 and -// doing sum(n[i] * 2^(26i)) like so: -// n[9] * 2^(26*9) = 0 * 2^234 = 0 -// n[8] * 2^(26*8) = 0 * 2^208 = 0 -// ... -// n[1] * 2^(26*1) = 2^23 * 2^26 = 2^49 -// n[0] * 2^(26*0) = 1 * 2^0 = 1 -// Sum: 0 + 0 + ... + 2^49 + 1 = 2^49 + 1 -type fieldVal struct { - n [10]uint32 -} - -// String returns the field value as a human-readable hex string. -func (f fieldVal) String() string { - t := new(fieldVal).Set(&f).Normalize() - return hex.EncodeToString(t.Bytes()[:]) -} - -// Zero sets the field value to zero. A newly created field value is already -// set to zero. This function can be useful to clear an existing field value -// for reuse. -func (f *fieldVal) Zero() { - f.n[0] = 0 - f.n[1] = 0 - f.n[2] = 0 - f.n[3] = 0 - f.n[4] = 0 - f.n[5] = 0 - f.n[6] = 0 - f.n[7] = 0 - f.n[8] = 0 - f.n[9] = 0 -} - -// Set sets the field value equal to the passed value. -// -// The field value is returned to support chaining. This enables syntax like: -// f := new(fieldVal).Set(f2).Add(1) so that f = f2 + 1 where f2 is not -// modified. -func (f *fieldVal) Set(val *fieldVal) *fieldVal { - *f = *val - return f -} - -// SetInt sets the field value to the passed integer. This is a convenience -// function since it is fairly common to perform some arithemetic with small -// native integers. -// -// The field value is returned to support chaining. This enables syntax such -// as f := new(fieldVal).SetInt(2).Mul(f2) so that f = 2 * f2. -func (f *fieldVal) SetInt(ui uint) *fieldVal { - f.Zero() - f.n[0] = uint32(ui) - return f -} - -// SetBytes packs the passed 32-byte big-endian value into the internal field -// value representation. -// -// The field value is returned to support chaining. This enables syntax like: -// f := new(fieldVal).SetBytes(byteArray).Mul(f2) so that f = ba * f2. -func (f *fieldVal) SetBytes(b *[32]byte) *fieldVal { - // Pack the 256 total bits across the 10 uint32 words with a max of - // 26-bits per word. This could be done with a couple of for loops, - // but this unrolled version is significantly faster. Benchmarks show - // this is about 34 times faster than the variant which uses loops. - f.n[0] = uint32(b[31]) | uint32(b[30])<<8 | uint32(b[29])<<16 | - (uint32(b[28])&twoBitsMask)<<24 - f.n[1] = uint32(b[28])>>2 | uint32(b[27])<<6 | uint32(b[26])<<14 | - (uint32(b[25])&fourBitsMask)<<22 - f.n[2] = uint32(b[25])>>4 | uint32(b[24])<<4 | uint32(b[23])<<12 | - (uint32(b[22])&sixBitsMask)<<20 - f.n[3] = uint32(b[22])>>6 | uint32(b[21])<<2 | uint32(b[20])<<10 | - uint32(b[19])<<18 - f.n[4] = uint32(b[18]) | uint32(b[17])<<8 | uint32(b[16])<<16 | - (uint32(b[15])&twoBitsMask)<<24 - f.n[5] = uint32(b[15])>>2 | uint32(b[14])<<6 | uint32(b[13])<<14 | - (uint32(b[12])&fourBitsMask)<<22 - f.n[6] = uint32(b[12])>>4 | uint32(b[11])<<4 | uint32(b[10])<<12 | - (uint32(b[9])&sixBitsMask)<<20 - f.n[7] = uint32(b[9])>>6 | uint32(b[8])<<2 | uint32(b[7])<<10 | - uint32(b[6])<<18 - f.n[8] = uint32(b[5]) | uint32(b[4])<<8 | uint32(b[3])<<16 | - (uint32(b[2])&twoBitsMask)<<24 - f.n[9] = uint32(b[2])>>2 | uint32(b[1])<<6 | uint32(b[0])<<14 - return f -} - -// SetByteSlice interprets the provided slice as a 256-bit big-endian unsigned -// integer (meaning it is truncated to the first 32 bytes), packs it into the -// internal field value representation, and returns the updated field value. -// -// Note that since passing a slice with more than 32 bytes is truncated, it is -// possible that the truncated value is less than the field prime. It is up to -// the caller to decide whether it needs to provide numbers of the appropriate -// size or if it is acceptable to use this function with the described -// truncation behavior. -// -// The field value is returned to support chaining. This enables syntax like: -// f := new(fieldVal).SetByteSlice(byteSlice) -func (f *fieldVal) SetByteSlice(b []byte) *fieldVal { - var b32 [32]byte - if len(b) > 32 { - b = b[:32] - } - copy(b32[32-len(b):], b) - return f.SetBytes(&b32) -} - -// SetHex decodes the passed big-endian hex string into the internal field value -// representation. Only the first 32-bytes are used. -// -// The field value is returned to support chaining. This enables syntax like: -// f := new(fieldVal).SetHex("0abc").Add(1) so that f = 0x0abc + 1 -func (f *fieldVal) SetHex(hexString string) *fieldVal { - if len(hexString)%2 != 0 { - hexString = "0" + hexString - } - bytes, _ := hex.DecodeString(hexString) - return f.SetByteSlice(bytes) -} - -// Normalize normalizes the internal field words into the desired range and -// performs fast modular reduction over the secp256k1 prime by making use of the -// special form of the prime. -func (f *fieldVal) Normalize() *fieldVal { - // The field representation leaves 6 bits of overflow in each word so - // intermediate calculations can be performed without needing to - // propagate the carry to each higher word during the calculations. In - // order to normalize, we need to "compact" the full 256-bit value to - // the right while propagating any carries through to the high order - // word. - // - // Since this field is doing arithmetic modulo the secp256k1 prime, we - // also need to perform modular reduction over the prime. - // - // Per [HAC] section 14.3.4: Reduction method of moduli of special form, - // when the modulus is of the special form m = b^t - c, highly efficient - // reduction can be achieved. - // - // The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits - // this criteria. - // - // 4294968273 in field representation (base 2^26) is: - // n[0] = 977 - // n[1] = 64 - // That is to say (2^26 * 64) + 977 = 4294968273 - // - // The algorithm presented in the referenced section typically repeats - // until the quotient is zero. However, due to our field representation - // we already know to within one reduction how many times we would need - // to repeat as it's the uppermost bits of the high order word. Thus we - // can simply multiply the magnitude by the field representation of the - // prime and do a single iteration. After this step there might be an - // additional carry to bit 256 (bit 22 of the high order word). - t9 := f.n[9] - m := t9 >> fieldMSBBits - t9 = t9 & fieldMSBMask - t0 := f.n[0] + m*977 - t1 := (t0 >> fieldBase) + f.n[1] + (m << 6) - t0 = t0 & fieldBaseMask - t2 := (t1 >> fieldBase) + f.n[2] - t1 = t1 & fieldBaseMask - t3 := (t2 >> fieldBase) + f.n[3] - t2 = t2 & fieldBaseMask - t4 := (t3 >> fieldBase) + f.n[4] - t3 = t3 & fieldBaseMask - t5 := (t4 >> fieldBase) + f.n[5] - t4 = t4 & fieldBaseMask - t6 := (t5 >> fieldBase) + f.n[6] - t5 = t5 & fieldBaseMask - t7 := (t6 >> fieldBase) + f.n[7] - t6 = t6 & fieldBaseMask - t8 := (t7 >> fieldBase) + f.n[8] - t7 = t7 & fieldBaseMask - t9 = (t8 >> fieldBase) + t9 - t8 = t8 & fieldBaseMask - - // At this point, the magnitude is guaranteed to be one, however, the - // value could still be greater than the prime if there was either a - // carry through to bit 256 (bit 22 of the higher order word) or the - // value is greater than or equal to the field characteristic. The - // following determines if either or these conditions are true and does - // the final reduction in constant time. - // - // Note that the if/else statements here intentionally do the bitwise - // operators even when it won't change the value to ensure constant time - // between the branches. Also note that 'm' will be zero when neither - // of the aforementioned conditions are true and the value will not be - // changed when 'm' is zero. - m = 1 - if t9 == fieldMSBMask { - m &= 1 - } else { - m &= 0 - } - if t2&t3&t4&t5&t6&t7&t8 == fieldBaseMask { - m &= 1 - } else { - m &= 0 - } - if ((t0+977)>>fieldBase + t1 + 64) > fieldBaseMask { - m &= 1 - } else { - m &= 0 - } - if t9>>fieldMSBBits != 0 { - m |= 1 - } else { - m |= 0 - } - t0 = t0 + m*977 - t1 = (t0 >> fieldBase) + t1 + (m << 6) - t0 = t0 & fieldBaseMask - t2 = (t1 >> fieldBase) + t2 - t1 = t1 & fieldBaseMask - t3 = (t2 >> fieldBase) + t3 - t2 = t2 & fieldBaseMask - t4 = (t3 >> fieldBase) + t4 - t3 = t3 & fieldBaseMask - t5 = (t4 >> fieldBase) + t5 - t4 = t4 & fieldBaseMask - t6 = (t5 >> fieldBase) + t6 - t5 = t5 & fieldBaseMask - t7 = (t6 >> fieldBase) + t7 - t6 = t6 & fieldBaseMask - t8 = (t7 >> fieldBase) + t8 - t7 = t7 & fieldBaseMask - t9 = (t8 >> fieldBase) + t9 - t8 = t8 & fieldBaseMask - t9 = t9 & fieldMSBMask // Remove potential multiple of 2^256. - - // Finally, set the normalized and reduced words. - f.n[0] = t0 - f.n[1] = t1 - f.n[2] = t2 - f.n[3] = t3 - f.n[4] = t4 - f.n[5] = t5 - f.n[6] = t6 - f.n[7] = t7 - f.n[8] = t8 - f.n[9] = t9 - return f -} - -// PutBytes unpacks the field value to a 32-byte big-endian value using the -// passed byte array. There is a similar function, Bytes, which unpacks the -// field value into a new array and returns that. This version is provided -// since it can be useful to cut down on the number of allocations by allowing -// the caller to reuse a buffer. -// -// The field value must be normalized for this function to return the correct -// result. -func (f *fieldVal) PutBytes(b *[32]byte) { - // Unpack the 256 total bits from the 10 uint32 words with a max of - // 26-bits per word. This could be done with a couple of for loops, - // but this unrolled version is a bit faster. Benchmarks show this is - // about 10 times faster than the variant which uses loops. - b[31] = byte(f.n[0] & eightBitsMask) - b[30] = byte((f.n[0] >> 8) & eightBitsMask) - b[29] = byte((f.n[0] >> 16) & eightBitsMask) - b[28] = byte((f.n[0]>>24)&twoBitsMask | (f.n[1]&sixBitsMask)<<2) - b[27] = byte((f.n[1] >> 6) & eightBitsMask) - b[26] = byte((f.n[1] >> 14) & eightBitsMask) - b[25] = byte((f.n[1]>>22)&fourBitsMask | (f.n[2]&fourBitsMask)<<4) - b[24] = byte((f.n[2] >> 4) & eightBitsMask) - b[23] = byte((f.n[2] >> 12) & eightBitsMask) - b[22] = byte((f.n[2]>>20)&sixBitsMask | (f.n[3]&twoBitsMask)<<6) - b[21] = byte((f.n[3] >> 2) & eightBitsMask) - b[20] = byte((f.n[3] >> 10) & eightBitsMask) - b[19] = byte((f.n[3] >> 18) & eightBitsMask) - b[18] = byte(f.n[4] & eightBitsMask) - b[17] = byte((f.n[4] >> 8) & eightBitsMask) - b[16] = byte((f.n[4] >> 16) & eightBitsMask) - b[15] = byte((f.n[4]>>24)&twoBitsMask | (f.n[5]&sixBitsMask)<<2) - b[14] = byte((f.n[5] >> 6) & eightBitsMask) - b[13] = byte((f.n[5] >> 14) & eightBitsMask) - b[12] = byte((f.n[5]>>22)&fourBitsMask | (f.n[6]&fourBitsMask)<<4) - b[11] = byte((f.n[6] >> 4) & eightBitsMask) - b[10] = byte((f.n[6] >> 12) & eightBitsMask) - b[9] = byte((f.n[6]>>20)&sixBitsMask | (f.n[7]&twoBitsMask)<<6) - b[8] = byte((f.n[7] >> 2) & eightBitsMask) - b[7] = byte((f.n[7] >> 10) & eightBitsMask) - b[6] = byte((f.n[7] >> 18) & eightBitsMask) - b[5] = byte(f.n[8] & eightBitsMask) - b[4] = byte((f.n[8] >> 8) & eightBitsMask) - b[3] = byte((f.n[8] >> 16) & eightBitsMask) - b[2] = byte((f.n[8]>>24)&twoBitsMask | (f.n[9]&sixBitsMask)<<2) - b[1] = byte((f.n[9] >> 6) & eightBitsMask) - b[0] = byte((f.n[9] >> 14) & eightBitsMask) -} - -// Bytes unpacks the field value to a 32-byte big-endian value. See PutBytes -// for a variant that allows the a buffer to be passed which can be useful to -// to cut down on the number of allocations by allowing the caller to reuse a -// buffer. -// -// The field value must be normalized for this function to return correct -// result. -func (f *fieldVal) Bytes() *[32]byte { - b := new([32]byte) - f.PutBytes(b) - return b -} - -// IsZero returns whether or not the field value is equal to zero. -func (f *fieldVal) IsZero() bool { - // The value can only be zero if no bits are set in any of the words. - // This is a constant time implementation. - bits := f.n[0] | f.n[1] | f.n[2] | f.n[3] | f.n[4] | - f.n[5] | f.n[6] | f.n[7] | f.n[8] | f.n[9] - - return bits == 0 -} - -// IsOdd returns whether or not the field value is an odd number. -// -// The field value must be normalized for this function to return correct -// result. -func (f *fieldVal) IsOdd() bool { - // Only odd numbers have the bottom bit set. - return f.n[0]&1 == 1 -} - -// Equals returns whether or not the two field values are the same. Both -// field values being compared must be normalized for this function to return -// the correct result. -func (f *fieldVal) Equals(val *fieldVal) bool { - // Xor only sets bits when they are different, so the two field values - // can only be the same if no bits are set after xoring each word. - // This is a constant time implementation. - bits := (f.n[0] ^ val.n[0]) | (f.n[1] ^ val.n[1]) | (f.n[2] ^ val.n[2]) | - (f.n[3] ^ val.n[3]) | (f.n[4] ^ val.n[4]) | (f.n[5] ^ val.n[5]) | - (f.n[6] ^ val.n[6]) | (f.n[7] ^ val.n[7]) | (f.n[8] ^ val.n[8]) | - (f.n[9] ^ val.n[9]) - - return bits == 0 -} - -// NegateVal negates the passed value and stores the result in f. The caller -// must provide the magnitude of the passed value for a correct result. -// -// The field value is returned to support chaining. This enables syntax like: -// f.NegateVal(f2).AddInt(1) so that f = -f2 + 1. -func (f *fieldVal) NegateVal(val *fieldVal, magnitude uint32) *fieldVal { - // Negation in the field is just the prime minus the value. However, - // in order to allow negation against a field value without having to - // normalize/reduce it first, multiply by the magnitude (that is how - // "far" away it is from the normalized value) to adjust. Also, since - // negating a value pushes it one more order of magnitude away from the - // normalized range, add 1 to compensate. - // - // For some intuition here, imagine you're performing mod 12 arithmetic - // (picture a clock) and you are negating the number 7. So you start at - // 12 (which is of course 0 under mod 12) and count backwards (left on - // the clock) 7 times to arrive at 5. Notice this is just 12-7 = 5. - // Now, assume you're starting with 19, which is a number that is - // already larger than the modulus and congruent to 7 (mod 12). When a - // value is already in the desired range, its magnitude is 1. Since 19 - // is an additional "step", its magnitude (mod 12) is 2. Since any - // multiple of the modulus is conguent to zero (mod m), the answer can - // be shortcut by simply mulplying the magnitude by the modulus and - // subtracting. Keeping with the example, this would be (2*12)-19 = 5. - f.n[0] = (magnitude+1)*fieldPrimeWordZero - val.n[0] - f.n[1] = (magnitude+1)*fieldPrimeWordOne - val.n[1] - f.n[2] = (magnitude+1)*fieldBaseMask - val.n[2] - f.n[3] = (magnitude+1)*fieldBaseMask - val.n[3] - f.n[4] = (magnitude+1)*fieldBaseMask - val.n[4] - f.n[5] = (magnitude+1)*fieldBaseMask - val.n[5] - f.n[6] = (magnitude+1)*fieldBaseMask - val.n[6] - f.n[7] = (magnitude+1)*fieldBaseMask - val.n[7] - f.n[8] = (magnitude+1)*fieldBaseMask - val.n[8] - f.n[9] = (magnitude+1)*fieldMSBMask - val.n[9] - - return f -} - -// Negate negates the field value. The existing field value is modified. The -// caller must provide the magnitude of the field value for a correct result. -// -// The field value is returned to support chaining. This enables syntax like: -// f.Negate().AddInt(1) so that f = -f + 1. -func (f *fieldVal) Negate(magnitude uint32) *fieldVal { - return f.NegateVal(f, magnitude) -} - -// AddInt adds the passed integer to the existing field value and stores the -// result in f. This is a convenience function since it is fairly common to -// perform some arithemetic with small native integers. -// -// The field value is returned to support chaining. This enables syntax like: -// f.AddInt(1).Add(f2) so that f = f + 1 + f2. -func (f *fieldVal) AddInt(ui uint) *fieldVal { - // Since the field representation intentionally provides overflow bits, - // it's ok to use carryless addition as the carry bit is safely part of - // the word and will be normalized out. - f.n[0] += uint32(ui) - - return f -} - -// Add adds the passed value to the existing field value and stores the result -// in f. -// -// The field value is returned to support chaining. This enables syntax like: -// f.Add(f2).AddInt(1) so that f = f + f2 + 1. -func (f *fieldVal) Add(val *fieldVal) *fieldVal { - // Since the field representation intentionally provides overflow bits, - // it's ok to use carryless addition as the carry bit is safely part of - // each word and will be normalized out. This could obviously be done - // in a loop, but the unrolled version is faster. - f.n[0] += val.n[0] - f.n[1] += val.n[1] - f.n[2] += val.n[2] - f.n[3] += val.n[3] - f.n[4] += val.n[4] - f.n[5] += val.n[5] - f.n[6] += val.n[6] - f.n[7] += val.n[7] - f.n[8] += val.n[8] - f.n[9] += val.n[9] - - return f -} - -// Add2 adds the passed two field values together and stores the result in f. -// -// The field value is returned to support chaining. This enables syntax like: -// f3.Add2(f, f2).AddInt(1) so that f3 = f + f2 + 1. -func (f *fieldVal) Add2(val *fieldVal, val2 *fieldVal) *fieldVal { - // Since the field representation intentionally provides overflow bits, - // it's ok to use carryless addition as the carry bit is safely part of - // each word and will be normalized out. This could obviously be done - // in a loop, but the unrolled version is faster. - f.n[0] = val.n[0] + val2.n[0] - f.n[1] = val.n[1] + val2.n[1] - f.n[2] = val.n[2] + val2.n[2] - f.n[3] = val.n[3] + val2.n[3] - f.n[4] = val.n[4] + val2.n[4] - f.n[5] = val.n[5] + val2.n[5] - f.n[6] = val.n[6] + val2.n[6] - f.n[7] = val.n[7] + val2.n[7] - f.n[8] = val.n[8] + val2.n[8] - f.n[9] = val.n[9] + val2.n[9] - - return f -} - -// MulInt multiplies the field value by the passed int and stores the result in -// f. Note that this function can overflow if multiplying the value by any of -// the individual words exceeds a max uint32. Therefore it is important that -// the caller ensures no overflows will occur before using this function. -// -// The field value is returned to support chaining. This enables syntax like: -// f.MulInt(2).Add(f2) so that f = 2 * f + f2. -func (f *fieldVal) MulInt(val uint) *fieldVal { - // Since each word of the field representation can hold up to - // fieldOverflowBits extra bits which will be normalized out, it's safe - // to multiply each word without using a larger type or carry - // propagation so long as the values won't overflow a uint32. This - // could obviously be done in a loop, but the unrolled version is - // faster. - ui := uint32(val) - f.n[0] *= ui - f.n[1] *= ui - f.n[2] *= ui - f.n[3] *= ui - f.n[4] *= ui - f.n[5] *= ui - f.n[6] *= ui - f.n[7] *= ui - f.n[8] *= ui - f.n[9] *= ui - - return f -} - -// Mul multiplies the passed value to the existing field value and stores the -// result in f. Note that this function can overflow if multiplying any -// of the individual words exceeds a max uint32. In practice, this means the -// magnitude of either value involved in the multiplication must be a max of -// 8. -// -// The field value is returned to support chaining. This enables syntax like: -// f.Mul(f2).AddInt(1) so that f = (f * f2) + 1. -func (f *fieldVal) Mul(val *fieldVal) *fieldVal { - return f.Mul2(f, val) -} - -// Mul2 multiplies the passed two field values together and stores the result -// result in f. Note that this function can overflow if multiplying any of -// the individual words exceeds a max uint32. In practice, this means the -// magnitude of either value involved in the multiplication must be a max of -// 8. -// -// The field value is returned to support chaining. This enables syntax like: -// f3.Mul2(f, f2).AddInt(1) so that f3 = (f * f2) + 1. -func (f *fieldVal) Mul2(val *fieldVal, val2 *fieldVal) *fieldVal { - // This could be done with a couple of for loops and an array to store - // the intermediate terms, but this unrolled version is significantly - // faster. - - // Terms for 2^(fieldBase*0). - m := uint64(val.n[0]) * uint64(val2.n[0]) - t0 := m & fieldBaseMask - - // Terms for 2^(fieldBase*1). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[1]) + - uint64(val.n[1])*uint64(val2.n[0]) - t1 := m & fieldBaseMask - - // Terms for 2^(fieldBase*2). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[2]) + - uint64(val.n[1])*uint64(val2.n[1]) + - uint64(val.n[2])*uint64(val2.n[0]) - t2 := m & fieldBaseMask - - // Terms for 2^(fieldBase*3). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[3]) + - uint64(val.n[1])*uint64(val2.n[2]) + - uint64(val.n[2])*uint64(val2.n[1]) + - uint64(val.n[3])*uint64(val2.n[0]) - t3 := m & fieldBaseMask - - // Terms for 2^(fieldBase*4). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[4]) + - uint64(val.n[1])*uint64(val2.n[3]) + - uint64(val.n[2])*uint64(val2.n[2]) + - uint64(val.n[3])*uint64(val2.n[1]) + - uint64(val.n[4])*uint64(val2.n[0]) - t4 := m & fieldBaseMask - - // Terms for 2^(fieldBase*5). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[5]) + - uint64(val.n[1])*uint64(val2.n[4]) + - uint64(val.n[2])*uint64(val2.n[3]) + - uint64(val.n[3])*uint64(val2.n[2]) + - uint64(val.n[4])*uint64(val2.n[1]) + - uint64(val.n[5])*uint64(val2.n[0]) - t5 := m & fieldBaseMask - - // Terms for 2^(fieldBase*6). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[6]) + - uint64(val.n[1])*uint64(val2.n[5]) + - uint64(val.n[2])*uint64(val2.n[4]) + - uint64(val.n[3])*uint64(val2.n[3]) + - uint64(val.n[4])*uint64(val2.n[2]) + - uint64(val.n[5])*uint64(val2.n[1]) + - uint64(val.n[6])*uint64(val2.n[0]) - t6 := m & fieldBaseMask - - // Terms for 2^(fieldBase*7). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[7]) + - uint64(val.n[1])*uint64(val2.n[6]) + - uint64(val.n[2])*uint64(val2.n[5]) + - uint64(val.n[3])*uint64(val2.n[4]) + - uint64(val.n[4])*uint64(val2.n[3]) + - uint64(val.n[5])*uint64(val2.n[2]) + - uint64(val.n[6])*uint64(val2.n[1]) + - uint64(val.n[7])*uint64(val2.n[0]) - t7 := m & fieldBaseMask - - // Terms for 2^(fieldBase*8). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[8]) + - uint64(val.n[1])*uint64(val2.n[7]) + - uint64(val.n[2])*uint64(val2.n[6]) + - uint64(val.n[3])*uint64(val2.n[5]) + - uint64(val.n[4])*uint64(val2.n[4]) + - uint64(val.n[5])*uint64(val2.n[3]) + - uint64(val.n[6])*uint64(val2.n[2]) + - uint64(val.n[7])*uint64(val2.n[1]) + - uint64(val.n[8])*uint64(val2.n[0]) - t8 := m & fieldBaseMask - - // Terms for 2^(fieldBase*9). - m = (m >> fieldBase) + - uint64(val.n[0])*uint64(val2.n[9]) + - uint64(val.n[1])*uint64(val2.n[8]) + - uint64(val.n[2])*uint64(val2.n[7]) + - uint64(val.n[3])*uint64(val2.n[6]) + - uint64(val.n[4])*uint64(val2.n[5]) + - uint64(val.n[5])*uint64(val2.n[4]) + - uint64(val.n[6])*uint64(val2.n[3]) + - uint64(val.n[7])*uint64(val2.n[2]) + - uint64(val.n[8])*uint64(val2.n[1]) + - uint64(val.n[9])*uint64(val2.n[0]) - t9 := m & fieldBaseMask - - // Terms for 2^(fieldBase*10). - m = (m >> fieldBase) + - uint64(val.n[1])*uint64(val2.n[9]) + - uint64(val.n[2])*uint64(val2.n[8]) + - uint64(val.n[3])*uint64(val2.n[7]) + - uint64(val.n[4])*uint64(val2.n[6]) + - uint64(val.n[5])*uint64(val2.n[5]) + - uint64(val.n[6])*uint64(val2.n[4]) + - uint64(val.n[7])*uint64(val2.n[3]) + - uint64(val.n[8])*uint64(val2.n[2]) + - uint64(val.n[9])*uint64(val2.n[1]) - t10 := m & fieldBaseMask - - // Terms for 2^(fieldBase*11). - m = (m >> fieldBase) + - uint64(val.n[2])*uint64(val2.n[9]) + - uint64(val.n[3])*uint64(val2.n[8]) + - uint64(val.n[4])*uint64(val2.n[7]) + - uint64(val.n[5])*uint64(val2.n[6]) + - uint64(val.n[6])*uint64(val2.n[5]) + - uint64(val.n[7])*uint64(val2.n[4]) + - uint64(val.n[8])*uint64(val2.n[3]) + - uint64(val.n[9])*uint64(val2.n[2]) - t11 := m & fieldBaseMask - - // Terms for 2^(fieldBase*12). - m = (m >> fieldBase) + - uint64(val.n[3])*uint64(val2.n[9]) + - uint64(val.n[4])*uint64(val2.n[8]) + - uint64(val.n[5])*uint64(val2.n[7]) + - uint64(val.n[6])*uint64(val2.n[6]) + - uint64(val.n[7])*uint64(val2.n[5]) + - uint64(val.n[8])*uint64(val2.n[4]) + - uint64(val.n[9])*uint64(val2.n[3]) - t12 := m & fieldBaseMask - - // Terms for 2^(fieldBase*13). - m = (m >> fieldBase) + - uint64(val.n[4])*uint64(val2.n[9]) + - uint64(val.n[5])*uint64(val2.n[8]) + - uint64(val.n[6])*uint64(val2.n[7]) + - uint64(val.n[7])*uint64(val2.n[6]) + - uint64(val.n[8])*uint64(val2.n[5]) + - uint64(val.n[9])*uint64(val2.n[4]) - t13 := m & fieldBaseMask - - // Terms for 2^(fieldBase*14). - m = (m >> fieldBase) + - uint64(val.n[5])*uint64(val2.n[9]) + - uint64(val.n[6])*uint64(val2.n[8]) + - uint64(val.n[7])*uint64(val2.n[7]) + - uint64(val.n[8])*uint64(val2.n[6]) + - uint64(val.n[9])*uint64(val2.n[5]) - t14 := m & fieldBaseMask - - // Terms for 2^(fieldBase*15). - m = (m >> fieldBase) + - uint64(val.n[6])*uint64(val2.n[9]) + - uint64(val.n[7])*uint64(val2.n[8]) + - uint64(val.n[8])*uint64(val2.n[7]) + - uint64(val.n[9])*uint64(val2.n[6]) - t15 := m & fieldBaseMask - - // Terms for 2^(fieldBase*16). - m = (m >> fieldBase) + - uint64(val.n[7])*uint64(val2.n[9]) + - uint64(val.n[8])*uint64(val2.n[8]) + - uint64(val.n[9])*uint64(val2.n[7]) - t16 := m & fieldBaseMask - - // Terms for 2^(fieldBase*17). - m = (m >> fieldBase) + - uint64(val.n[8])*uint64(val2.n[9]) + - uint64(val.n[9])*uint64(val2.n[8]) - t17 := m & fieldBaseMask - - // Terms for 2^(fieldBase*18). - m = (m >> fieldBase) + uint64(val.n[9])*uint64(val2.n[9]) - t18 := m & fieldBaseMask - - // What's left is for 2^(fieldBase*19). - t19 := m >> fieldBase - - // At this point, all of the terms are grouped into their respective - // base. - // - // Per [HAC] section 14.3.4: Reduction method of moduli of special form, - // when the modulus is of the special form m = b^t - c, highly efficient - // reduction can be achieved per the provided algorithm. - // - // The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits - // this criteria. - // - // 4294968273 in field representation (base 2^26) is: - // n[0] = 977 - // n[1] = 64 - // That is to say (2^26 * 64) + 977 = 4294968273 - // - // Since each word is in base 26, the upper terms (t10 and up) start - // at 260 bits (versus the final desired range of 256 bits), so the - // field representation of 'c' from above needs to be adjusted for the - // extra 4 bits by multiplying it by 2^4 = 16. 4294968273 * 16 = - // 68719492368. Thus, the adjusted field representation of 'c' is: - // n[0] = 977 * 16 = 15632 - // n[1] = 64 * 16 = 1024 - // That is to say (2^26 * 1024) + 15632 = 68719492368 - // - // To reduce the final term, t19, the entire 'c' value is needed instead - // of only n[0] because there are no more terms left to handle n[1]. - // This means there might be some magnitude left in the upper bits that - // is handled below. - m = t0 + t10*15632 - t0 = m & fieldBaseMask - m = (m >> fieldBase) + t1 + t10*1024 + t11*15632 - t1 = m & fieldBaseMask - m = (m >> fieldBase) + t2 + t11*1024 + t12*15632 - t2 = m & fieldBaseMask - m = (m >> fieldBase) + t3 + t12*1024 + t13*15632 - t3 = m & fieldBaseMask - m = (m >> fieldBase) + t4 + t13*1024 + t14*15632 - t4 = m & fieldBaseMask - m = (m >> fieldBase) + t5 + t14*1024 + t15*15632 - t5 = m & fieldBaseMask - m = (m >> fieldBase) + t6 + t15*1024 + t16*15632 - t6 = m & fieldBaseMask - m = (m >> fieldBase) + t7 + t16*1024 + t17*15632 - t7 = m & fieldBaseMask - m = (m >> fieldBase) + t8 + t17*1024 + t18*15632 - t8 = m & fieldBaseMask - m = (m >> fieldBase) + t9 + t18*1024 + t19*68719492368 - t9 = m & fieldMSBMask - m = m >> fieldMSBBits - - // At this point, if the magnitude is greater than 0, the overall value - // is greater than the max possible 256-bit value. In particular, it is - // "how many times larger" than the max value it is. - // - // The algorithm presented in [HAC] section 14.3.4 repeats until the - // quotient is zero. However, due to the above, we already know at - // least how many times we would need to repeat as it's the value - // currently in m. Thus we can simply multiply the magnitude by the - // field representation of the prime and do a single iteration. Notice - // that nothing will be changed when the magnitude is zero, so we could - // skip this in that case, however always running regardless allows it - // to run in constant time. The final result will be in the range - // 0 <= result <= prime + (2^64 - c), so it is guaranteed to have a - // magnitude of 1, but it is denormalized. - d := t0 + m*977 - f.n[0] = uint32(d & fieldBaseMask) - d = (d >> fieldBase) + t1 + m*64 - f.n[1] = uint32(d & fieldBaseMask) - f.n[2] = uint32((d >> fieldBase) + t2) - f.n[3] = uint32(t3) - f.n[4] = uint32(t4) - f.n[5] = uint32(t5) - f.n[6] = uint32(t6) - f.n[7] = uint32(t7) - f.n[8] = uint32(t8) - f.n[9] = uint32(t9) - - return f -} - -// Square squares the field value. The existing field value is modified. Note -// that this function can overflow if multiplying any of the individual words -// exceeds a max uint32. In practice, this means the magnitude of the field -// must be a max of 8 to prevent overflow. -// -// The field value is returned to support chaining. This enables syntax like: -// f.Square().Mul(f2) so that f = f^2 * f2. -func (f *fieldVal) Square() *fieldVal { - return f.SquareVal(f) -} - -// SquareVal squares the passed value and stores the result in f. Note that -// this function can overflow if multiplying any of the individual words -// exceeds a max uint32. In practice, this means the magnitude of the field -// being squred must be a max of 8 to prevent overflow. -// -// The field value is returned to support chaining. This enables syntax like: -// f3.SquareVal(f).Mul(f) so that f3 = f^2 * f = f^3. -func (f *fieldVal) SquareVal(val *fieldVal) *fieldVal { - // This could be done with a couple of for loops and an array to store - // the intermediate terms, but this unrolled version is significantly - // faster. - - // Terms for 2^(fieldBase*0). - m := uint64(val.n[0]) * uint64(val.n[0]) - t0 := m & fieldBaseMask - - // Terms for 2^(fieldBase*1). - m = (m >> fieldBase) + 2*uint64(val.n[0])*uint64(val.n[1]) - t1 := m & fieldBaseMask - - // Terms for 2^(fieldBase*2). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[2]) + - uint64(val.n[1])*uint64(val.n[1]) - t2 := m & fieldBaseMask - - // Terms for 2^(fieldBase*3). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[3]) + - 2*uint64(val.n[1])*uint64(val.n[2]) - t3 := m & fieldBaseMask - - // Terms for 2^(fieldBase*4). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[4]) + - 2*uint64(val.n[1])*uint64(val.n[3]) + - uint64(val.n[2])*uint64(val.n[2]) - t4 := m & fieldBaseMask - - // Terms for 2^(fieldBase*5). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[5]) + - 2*uint64(val.n[1])*uint64(val.n[4]) + - 2*uint64(val.n[2])*uint64(val.n[3]) - t5 := m & fieldBaseMask - - // Terms for 2^(fieldBase*6). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[6]) + - 2*uint64(val.n[1])*uint64(val.n[5]) + - 2*uint64(val.n[2])*uint64(val.n[4]) + - uint64(val.n[3])*uint64(val.n[3]) - t6 := m & fieldBaseMask - - // Terms for 2^(fieldBase*7). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[7]) + - 2*uint64(val.n[1])*uint64(val.n[6]) + - 2*uint64(val.n[2])*uint64(val.n[5]) + - 2*uint64(val.n[3])*uint64(val.n[4]) - t7 := m & fieldBaseMask - - // Terms for 2^(fieldBase*8). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[8]) + - 2*uint64(val.n[1])*uint64(val.n[7]) + - 2*uint64(val.n[2])*uint64(val.n[6]) + - 2*uint64(val.n[3])*uint64(val.n[5]) + - uint64(val.n[4])*uint64(val.n[4]) - t8 := m & fieldBaseMask - - // Terms for 2^(fieldBase*9). - m = (m >> fieldBase) + - 2*uint64(val.n[0])*uint64(val.n[9]) + - 2*uint64(val.n[1])*uint64(val.n[8]) + - 2*uint64(val.n[2])*uint64(val.n[7]) + - 2*uint64(val.n[3])*uint64(val.n[6]) + - 2*uint64(val.n[4])*uint64(val.n[5]) - t9 := m & fieldBaseMask - - // Terms for 2^(fieldBase*10). - m = (m >> fieldBase) + - 2*uint64(val.n[1])*uint64(val.n[9]) + - 2*uint64(val.n[2])*uint64(val.n[8]) + - 2*uint64(val.n[3])*uint64(val.n[7]) + - 2*uint64(val.n[4])*uint64(val.n[6]) + - uint64(val.n[5])*uint64(val.n[5]) - t10 := m & fieldBaseMask - - // Terms for 2^(fieldBase*11). - m = (m >> fieldBase) + - 2*uint64(val.n[2])*uint64(val.n[9]) + - 2*uint64(val.n[3])*uint64(val.n[8]) + - 2*uint64(val.n[4])*uint64(val.n[7]) + - 2*uint64(val.n[5])*uint64(val.n[6]) - t11 := m & fieldBaseMask - - // Terms for 2^(fieldBase*12). - m = (m >> fieldBase) + - 2*uint64(val.n[3])*uint64(val.n[9]) + - 2*uint64(val.n[4])*uint64(val.n[8]) + - 2*uint64(val.n[5])*uint64(val.n[7]) + - uint64(val.n[6])*uint64(val.n[6]) - t12 := m & fieldBaseMask - - // Terms for 2^(fieldBase*13). - m = (m >> fieldBase) + - 2*uint64(val.n[4])*uint64(val.n[9]) + - 2*uint64(val.n[5])*uint64(val.n[8]) + - 2*uint64(val.n[6])*uint64(val.n[7]) - t13 := m & fieldBaseMask - - // Terms for 2^(fieldBase*14). - m = (m >> fieldBase) + - 2*uint64(val.n[5])*uint64(val.n[9]) + - 2*uint64(val.n[6])*uint64(val.n[8]) + - uint64(val.n[7])*uint64(val.n[7]) - t14 := m & fieldBaseMask - - // Terms for 2^(fieldBase*15). - m = (m >> fieldBase) + - 2*uint64(val.n[6])*uint64(val.n[9]) + - 2*uint64(val.n[7])*uint64(val.n[8]) - t15 := m & fieldBaseMask - - // Terms for 2^(fieldBase*16). - m = (m >> fieldBase) + - 2*uint64(val.n[7])*uint64(val.n[9]) + - uint64(val.n[8])*uint64(val.n[8]) - t16 := m & fieldBaseMask - - // Terms for 2^(fieldBase*17). - m = (m >> fieldBase) + 2*uint64(val.n[8])*uint64(val.n[9]) - t17 := m & fieldBaseMask - - // Terms for 2^(fieldBase*18). - m = (m >> fieldBase) + uint64(val.n[9])*uint64(val.n[9]) - t18 := m & fieldBaseMask - - // What's left is for 2^(fieldBase*19). - t19 := m >> fieldBase - - // At this point, all of the terms are grouped into their respective - // base. - // - // Per [HAC] section 14.3.4: Reduction method of moduli of special form, - // when the modulus is of the special form m = b^t - c, highly efficient - // reduction can be achieved per the provided algorithm. - // - // The secp256k1 prime is equivalent to 2^256 - 4294968273, so it fits - // this criteria. - // - // 4294968273 in field representation (base 2^26) is: - // n[0] = 977 - // n[1] = 64 - // That is to say (2^26 * 64) + 977 = 4294968273 - // - // Since each word is in base 26, the upper terms (t10 and up) start - // at 260 bits (versus the final desired range of 256 bits), so the - // field representation of 'c' from above needs to be adjusted for the - // extra 4 bits by multiplying it by 2^4 = 16. 4294968273 * 16 = - // 68719492368. Thus, the adjusted field representation of 'c' is: - // n[0] = 977 * 16 = 15632 - // n[1] = 64 * 16 = 1024 - // That is to say (2^26 * 1024) + 15632 = 68719492368 - // - // To reduce the final term, t19, the entire 'c' value is needed instead - // of only n[0] because there are no more terms left to handle n[1]. - // This means there might be some magnitude left in the upper bits that - // is handled below. - m = t0 + t10*15632 - t0 = m & fieldBaseMask - m = (m >> fieldBase) + t1 + t10*1024 + t11*15632 - t1 = m & fieldBaseMask - m = (m >> fieldBase) + t2 + t11*1024 + t12*15632 - t2 = m & fieldBaseMask - m = (m >> fieldBase) + t3 + t12*1024 + t13*15632 - t3 = m & fieldBaseMask - m = (m >> fieldBase) + t4 + t13*1024 + t14*15632 - t4 = m & fieldBaseMask - m = (m >> fieldBase) + t5 + t14*1024 + t15*15632 - t5 = m & fieldBaseMask - m = (m >> fieldBase) + t6 + t15*1024 + t16*15632 - t6 = m & fieldBaseMask - m = (m >> fieldBase) + t7 + t16*1024 + t17*15632 - t7 = m & fieldBaseMask - m = (m >> fieldBase) + t8 + t17*1024 + t18*15632 - t8 = m & fieldBaseMask - m = (m >> fieldBase) + t9 + t18*1024 + t19*68719492368 - t9 = m & fieldMSBMask - m = m >> fieldMSBBits - - // At this point, if the magnitude is greater than 0, the overall value - // is greater than the max possible 256-bit value. In particular, it is - // "how many times larger" than the max value it is. - // - // The algorithm presented in [HAC] section 14.3.4 repeats until the - // quotient is zero. However, due to the above, we already know at - // least how many times we would need to repeat as it's the value - // currently in m. Thus we can simply multiply the magnitude by the - // field representation of the prime and do a single iteration. Notice - // that nothing will be changed when the magnitude is zero, so we could - // skip this in that case, however always running regardless allows it - // to run in constant time. The final result will be in the range - // 0 <= result <= prime + (2^64 - c), so it is guaranteed to have a - // magnitude of 1, but it is denormalized. - n := t0 + m*977 - f.n[0] = uint32(n & fieldBaseMask) - n = (n >> fieldBase) + t1 + m*64 - f.n[1] = uint32(n & fieldBaseMask) - f.n[2] = uint32((n >> fieldBase) + t2) - f.n[3] = uint32(t3) - f.n[4] = uint32(t4) - f.n[5] = uint32(t5) - f.n[6] = uint32(t6) - f.n[7] = uint32(t7) - f.n[8] = uint32(t8) - f.n[9] = uint32(t9) - - return f -} - -// Inverse finds the modular multiplicative inverse of the field value. The -// existing field value is modified. -// -// The field value is returned to support chaining. This enables syntax like: -// f.Inverse().Mul(f2) so that f = f^-1 * f2. -func (f *fieldVal) Inverse() *fieldVal { - // Fermat's little theorem states that for a nonzero number a and prime - // prime p, a^(p-1) = 1 (mod p). Since the multipliciative inverse is - // a*b = 1 (mod p), it follows that b = a*a^(p-2) = a^(p-1) = 1 (mod p). - // Thus, a^(p-2) is the multiplicative inverse. - // - // In order to efficiently compute a^(p-2), p-2 needs to be split into - // a sequence of squares and multipications that minimizes the number of - // multiplications needed (since they are more costly than squarings). - // Intermediate results are saved and reused as well. - // - // The secp256k1 prime - 2 is 2^256 - 4294968275. - // - // This has a cost of 258 field squarings and 33 field multiplications. - var a2, a3, a4, a10, a11, a21, a42, a45, a63, a1019, a1023 fieldVal - a2.SquareVal(f) - a3.Mul2(&a2, f) - a4.SquareVal(&a2) - a10.SquareVal(&a4).Mul(&a2) - a11.Mul2(&a10, f) - a21.Mul2(&a10, &a11) - a42.SquareVal(&a21) - a45.Mul2(&a42, &a3) - a63.Mul2(&a42, &a21) - a1019.SquareVal(&a63).Square().Square().Square().Mul(&a11) - a1023.Mul2(&a1019, &a4) - f.Set(&a63) // f = a^(2^6 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^11 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^16 - 1024) - f.Mul(&a1023) // f = a^(2^16 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^21 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^26 - 1024) - f.Mul(&a1023) // f = a^(2^26 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^31 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^36 - 1024) - f.Mul(&a1023) // f = a^(2^36 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^41 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^46 - 1024) - f.Mul(&a1023) // f = a^(2^46 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^51 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^56 - 1024) - f.Mul(&a1023) // f = a^(2^56 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^61 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^66 - 1024) - f.Mul(&a1023) // f = a^(2^66 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^71 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^76 - 1024) - f.Mul(&a1023) // f = a^(2^76 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^81 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^86 - 1024) - f.Mul(&a1023) // f = a^(2^86 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^91 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^96 - 1024) - f.Mul(&a1023) // f = a^(2^96 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^101 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^106 - 1024) - f.Mul(&a1023) // f = a^(2^106 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^111 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^116 - 1024) - f.Mul(&a1023) // f = a^(2^116 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^121 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^126 - 1024) - f.Mul(&a1023) // f = a^(2^126 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^131 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^136 - 1024) - f.Mul(&a1023) // f = a^(2^136 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^141 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^146 - 1024) - f.Mul(&a1023) // f = a^(2^146 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^151 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^156 - 1024) - f.Mul(&a1023) // f = a^(2^156 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^161 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^166 - 1024) - f.Mul(&a1023) // f = a^(2^166 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^171 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^176 - 1024) - f.Mul(&a1023) // f = a^(2^176 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^181 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^186 - 1024) - f.Mul(&a1023) // f = a^(2^186 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^191 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^196 - 1024) - f.Mul(&a1023) // f = a^(2^196 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^201 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^206 - 1024) - f.Mul(&a1023) // f = a^(2^206 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^211 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^216 - 1024) - f.Mul(&a1023) // f = a^(2^216 - 1) - f.Square().Square().Square().Square().Square() // f = a^(2^221 - 32) - f.Square().Square().Square().Square().Square() // f = a^(2^226 - 1024) - f.Mul(&a1019) // f = a^(2^226 - 5) - f.Square().Square().Square().Square().Square() // f = a^(2^231 - 160) - f.Square().Square().Square().Square().Square() // f = a^(2^236 - 5120) - f.Mul(&a1023) // f = a^(2^236 - 4097) - f.Square().Square().Square().Square().Square() // f = a^(2^241 - 131104) - f.Square().Square().Square().Square().Square() // f = a^(2^246 - 4195328) - f.Mul(&a1023) // f = a^(2^246 - 4194305) - f.Square().Square().Square().Square().Square() // f = a^(2^251 - 134217760) - f.Square().Square().Square().Square().Square() // f = a^(2^256 - 4294968320) - return f.Mul(&a45) // f = a^(2^256 - 4294968275) = a^(p-2) -} - -// SqrtVal computes the square root of x modulo the curve's prime, and stores -// the result in f. The square root is computed via exponentiation of x by the -// value Q = (P+1)/4 using the curve's precomputed big-endian representation of -// the Q. This method uses a modified version of square-and-multiply -// exponentiation over secp256k1 fieldVals to operate on bytes instead of bits, -// which offers better performance over both big.Int exponentiation and bit-wise -// square-and-multiply. -// -// NOTE: This method only works when P is intended to be the secp256k1 prime and -// is not constant time. The returned value is of magnitude 1, but is -// denormalized. -func (f *fieldVal) SqrtVal(x *fieldVal) *fieldVal { - // The following computation iteratively computes x^((P+1)/4) = x^Q - // using the recursive, piece-wise definition: - // - // x^n = (x^2)^(n/2) mod P if n is even - // x^n = x(x^2)^(n-1/2) mod P if n is odd - // - // Given n in its big-endian representation b_k, ..., b_0, x^n can be - // computed by defining the sequence r_k+1, ..., r_0, where: - // - // r_k+1 = 1 - // r_i = (r_i+1)^2 * x^b_i for i = k, ..., 0 - // - // The final value r_0 = x^n. - // - // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more - // details. - // - // This can be further optimized, by observing that the value of Q in - // secp256k1 has the value: - // - // Q = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c - // - // We can unroll the typical bit-wise interpretation of the - // exponentiation algorithm above to instead operate on bytes. - // This reduces the number of comparisons by an order of magnitude, - // reducing the overhead of failed branch predictions and additional - // comparisons in this method. - // - // Since there there are only 4 unique bytes of Q, this keeps the jump - // table small without the need to handle all possible 8-bit values. - // Further, we observe that 29 of the 32 bytes are 0xff; making the - // first case handle 0xff therefore optimizes the hot path. - f.SetInt(1) - for _, b := range fieldQBytes { - switch b { - - // Most common case, where all 8 bits are set. - case 0xff: - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - - // First byte of Q (0x3f), where all but the top two bits are - // set. Note that this case only applies six operations, since - // the highest bit of Q resides in bit six of the first byte. We - // ignore the first two bits, since squaring for these bits will - // result in an invalid result. We forgo squaring f before the - // first multiply, since 1^2 = 1. - case 0x3f: - f.Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - - // Byte 28 of Q (0xbf), where only bit 7 is unset. - case 0xbf: - f.Square().Mul(x) - f.Square() - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - f.Square().Mul(x) - - // Byte 31 of Q (0x0c), where only bits 3 and 4 are set. - default: - f.Square() - f.Square() - f.Square() - f.Square() - f.Square().Mul(x) - f.Square().Mul(x) - f.Square() - f.Square() - } - } - - return f -} - -// Sqrt computes the square root of f modulo the curve's prime, and stores the -// result in f. The square root is computed via exponentiation of x by the value -// Q = (P+1)/4 using the curve's precomputed big-endian representation of the Q. -// This method uses a modified version of square-and-multiply exponentiation -// over secp256k1 fieldVals to operate on bytes instead of bits, which offers -// better performance over both big.Int exponentiation and bit-wise -// square-and-multiply. -// -// NOTE: This method only works when P is intended to be the secp256k1 prime and -// is not constant time. The returned value is of magnitude 1, but is -// denormalized. -func (f *fieldVal) Sqrt() *fieldVal { - return f.SqrtVal(f) -} +import secp "github.com/decred/dcrd/dcrec/secp256k1/v4" + +// FieldVal implements optimized fixed-precision arithmetic over the secp256k1 +// finite field. This means all arithmetic is performed modulo +// '0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'. +// +// WARNING: Since it is so important for the field arithmetic to be extremely +// fast for high performance crypto, this type does not perform any validation +// of documented preconditions where it ordinarily would. As a result, it is +// IMPERATIVE for callers to understand some key concepts that are described +// below and ensure the methods are called with the necessary preconditions +// that each method is documented with. For example, some methods only give the +// correct result if the field value is normalized and others require the field +// values involved to have a maximum magnitude and THERE ARE NO EXPLICIT CHECKS +// TO ENSURE THOSE PRECONDITIONS ARE SATISFIED. This does, unfortunately, make +// the type more difficult to use correctly and while I typically prefer to +// ensure all state and input is valid for most code, this is a bit of an +// exception because those extra checks really add up in what ends up being +// critical hot paths. +// +// The first key concept when working with this type is normalization. In order +// to avoid the need to propagate a ton of carries, the internal representation +// provides additional overflow bits for each word of the overall 256-bit +// value. This means that there are multiple internal representations for the +// same value and, as a result, any methods that rely on comparison of the +// value, such as equality and oddness determination, require the caller to +// provide a normalized value. +// +// The second key concept when working with this type is magnitude. As +// previously mentioned, the internal representation provides additional +// overflow bits which means that the more math operations that are performed +// on the field value between normalizations, the more those overflow bits +// accumulate. The magnitude is effectively that maximum possible number of +// those overflow bits that could possibly be required as a result of a given +// operation. Since there are only a limited number of overflow bits available, +// this implies that the max possible magnitude MUST be tracked by the caller +// and the caller MUST normalize the field value if a given operation would +// cause the magnitude of the result to exceed the max allowed value. +// +// IMPORTANT: The max allowed magnitude of a field value is 64. +type FieldVal = secp.FieldVal diff --git a/btcec/field_test.go b/btcec/field_test.go index 4226ba55f9..6ade97a1eb 100644 --- a/btcec/field_test.go +++ b/btcec/field_test.go @@ -6,70 +6,30 @@ package btcec import ( - "crypto/rand" + "math/rand" + "encoding/hex" - "fmt" - "reflect" "testing" ) -// TestSetInt ensures that setting a field value to various native integers -// works as expected. -func TestSetInt(t *testing.T) { - tests := []struct { - in uint - raw [10]uint32 - }{ - {5, [10]uint32{5, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - // 2^26 - {67108864, [10]uint32{67108864, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - // 2^26 + 1 - {67108865, [10]uint32{67108865, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - // 2^32 - 1 - {4294967295, [10]uint32{4294967295, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, - } - - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetInt(test.in) - if !reflect.DeepEqual(f.n, test.raw) { - t.Errorf("fieldVal.Set #%d wrong result\ngot: %v\n"+ - "want: %v", i, f.n, test.raw) - continue - } - } -} - -// TestZero ensures that zeroing a field value zero works as expected. -func TestZero(t *testing.T) { - f := new(fieldVal).SetInt(2) - f.Zero() - for idx, rawInt := range f.n { - if rawInt != 0 { - t.Errorf("internal field integer at index #%d is not "+ - "zero - got %d", idx, rawInt) - } - } -} - // TestIsZero ensures that checking if a field IsZero works as expected. func TestIsZero(t *testing.T) { - f := new(fieldVal) + f := new(FieldVal) if !f.IsZero() { t.Errorf("new field value is not zero - got %v (rawints %x)", f, - f.n) + f.String()) } f.SetInt(1) if f.IsZero() { t.Errorf("field claims it's zero when it's not - got %v "+ - "(raw rawints %x)", f, f.n) + "(raw rawints %x)", f, f.String()) } f.Zero() if !f.IsZero() { t.Errorf("field claims it's not zero when it is - got %v "+ - "(raw rawints %x)", f, f.n) + "(raw rawints %x)", f, f.String()) } } @@ -147,10 +107,10 @@ func TestStringer(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - f := new(fieldVal).SetHex(test.in) + f := setHex(test.in) result := f.String() if result != test.expected { - t.Errorf("fieldVal.String #%d wrong result\ngot: %v\n"+ + t.Errorf("FieldVal.String #%d wrong result\ngot: %v\n"+ "want: %v", i, result, test.expected) continue } @@ -313,15 +273,16 @@ func TestNormalize(t *testing.T) { } t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal) + for range tests { + // TODO(roasbeef): can't access internal state + /*f := new(FieldVal) f.n = test.raw f.Normalize() if !reflect.DeepEqual(f.n, test.normalized) { - t.Errorf("fieldVal.Normalize #%d wrong result\n"+ + t.Errorf("FieldVal.Normalize #%d wrong result\n"+ "got: %x\nwant: %x", i, f.n, test.normalized) continue - } + }*/ } } @@ -344,10 +305,10 @@ func TestIsOdd(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - f := new(fieldVal).SetHex(test.in) + f := setHex(test.in) result := f.IsOdd() if result != test.expected { - t.Errorf("fieldVal.IsOdd #%d wrong result\n"+ + t.Errorf("FieldVal.IsOdd #%d wrong result\n"+ "got: %v\nwant: %v", i, result, test.expected) continue } @@ -377,11 +338,11 @@ func TestEquals(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() - f2 := new(fieldVal).SetHex(test.in2).Normalize() + f := setHex(test.in1).Normalize() + f2 := setHex(test.in2).Normalize() result := f.Equals(f2) if result != test.expected { - t.Errorf("fieldVal.Equals #%d wrong result\n"+ + t.Errorf("FieldVal.Equals #%d wrong result\n"+ "got: %v\nwant: %v", i, result, test.expected) continue } @@ -425,347 +386,419 @@ func TestNegate(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - f := new(fieldVal).SetHex(test.in).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() + f := setHex(test.in).Normalize() + expected := setHex(test.expected).Normalize() result := f.Negate(1).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Negate #%d wrong result\n"+ + t.Errorf("FieldVal.Negate #%d wrong result\n"+ "got: %v\nwant: %v", i, result, expected) continue } } } -// TestAddInt ensures that adding an integer to field values via AddInt works as -// expected. -func TestAddInt(t *testing.T) { +// TestFieldAddInt ensures that adding an integer to field values via AddInt +// works as expected. +func TestFieldAddInt(t *testing.T) { tests := []struct { + name string // test description in1 string // hex encoded value - in2 uint // unsigned integer to add to the value above + in2 uint16 // unsigned integer to add to the value above expected string // expected hex encoded value - }{ - {"0", 1, "1"}, - {"1", 0, "1"}, - {"1", 1, "2"}, - // secp256k1 prime-1 + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", 1, "0"}, - // secp256k1 prime + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 1, "1"}, - // Random samples. - { - "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d6c1", - 0x10f, - "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d7d0", - }, - { - "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41deea9cecf", - 0x2cf11d41, - "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41e1b9aec10", - }, - { - "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f7105122c9c", - 0x4829aa2d, - "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f714d3bd6c9", - }, - { - "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee09a015e2a6", - 0xa21265a5, - "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee0a4228484b", - }, - } + }{{ + name: "zero + one", + in1: "0", + in2: 1, + expected: "1", + }, { + name: "one + zero", + in1: "1", + in2: 0, + expected: "1", + }, { + name: "one + one", + in1: "1", + in2: 1, + expected: "2", + }, { + name: "secp256k1 prime-1 + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: 1, + expected: "0", + }, { + name: "secp256k1 prime + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: 1, + expected: "1", + }, { + name: "random sampling #1", + in1: "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d6c1", + in2: 0x10f, + expected: "ff95ad9315aff04ab4af0ce673620c7145dc85d03bab5ba4b09ca2c4dec2d7d0", + }, { + name: "random sampling #2", + in1: "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41deea9cecf", + in2: 0x3196, + expected: "44bdae6b772e7987941f1ba314e6a5b7804a4c12c00961b57d20f41deeaa0065", + }, { + name: "random sampling #3", + in1: "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f7105122c9c", + in2: 0x966f, + expected: "88c3ecae67b591935fb1f6a9499c35315ffad766adca665c50b55f710512c30b", + }, { + name: "random sampling #4", + in1: "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee09a015e2a6", + in2: 0xc54, + expected: "8523e9edf360ca32a95aae4e57fcde5a542b471d08a974d94ea0ee09a015eefa", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() + for _, test := range tests { + f := setHex(test.in1).Normalize() + expected := setHex(test.expected).Normalize() result := f.AddInt(test.in2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.AddInt #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: wrong result -- got: %v -- want: %v", test.name, + result, expected) continue } } } -// TestAdd ensures that adding two field values together via Add works as -// expected. -func TestAdd(t *testing.T) { +// TestFieldAdd ensures that adding two field values together via Add and Add2 +// works as expected. +func TestFieldAdd(t *testing.T) { tests := []struct { + name string // test description in1 string // first hex encoded value in2 string // second hex encoded value to add expected string // expected hex encoded value - }{ - {"0", "1", "1"}, - {"1", "0", "1"}, - {"1", "1", "2"}, - // secp256k1 prime-1 + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1", "0"}, - // secp256k1 prime + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "1", "1"}, - // Random samples. - { - "2b2012f975404e5065b4292fb8bed0a5d315eacf24c74d8b27e73bcc5430edcc", - "2c3cefa4e4753e8aeec6ac4c12d99da4d78accefda3b7885d4c6bab46c86db92", - "575d029e59b58cdb547ad57bcb986e4aaaa0b7beff02c610fcadf680c0b7c95e", - }, - { - "8131e8722fe59bb189692b96c9f38de92885730f1dd39ab025daffb94c97f79c", - "ff5454b765f0aab5f0977dcc629becc84cabeb9def48e79c6aadb2622c490fa9", - "80863d2995d646677a00a9632c8f7ab175315ead0d1c824c9088b21c78e10b16", - }, - { - "c7c95e93d0892b2b2cdd77e80eb646ea61be7a30ac7e097e9f843af73fad5c22", - "3afe6f91a74dfc1c7f15c34907ee981656c37236d946767dd53ccad9190e437c", - "02c7ce2577d72747abf33b3116a4df00b881ec6785c47ffc74c105d158bba36f", - }, - { - "fd1c26f6a23381e5d785ba889494ec059369b888ad8431cd67d8c934b580dbe1", - "a475aa5a31dcca90ef5b53c097d9133d6b7117474b41e7877bb199590fc0489c", - "a191d150d4104c76c6e10e492c6dff42fedacfcff8c61954e38a628ec541284e", - }, - } + }{{ + name: "zero + one", + in1: "0", + in2: "1", + expected: "1", + }, { + name: "one + zero", + in1: "1", + in2: "0", + expected: "1", + }, { + name: "secp256k1 prime-1 + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: "1", + expected: "0", + }, { + name: "secp256k1 prime + 1", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: "1", + expected: "1", + }, { + name: "random sampling #1", + in1: "2b2012f975404e5065b4292fb8bed0a5d315eacf24c74d8b27e73bcc5430edcc", + in2: "2c3cefa4e4753e8aeec6ac4c12d99da4d78accefda3b7885d4c6bab46c86db92", + expected: "575d029e59b58cdb547ad57bcb986e4aaaa0b7beff02c610fcadf680c0b7c95e", + }, { + name: "random sampling #2", + in1: "8131e8722fe59bb189692b96c9f38de92885730f1dd39ab025daffb94c97f79c", + in2: "ff5454b765f0aab5f0977dcc629becc84cabeb9def48e79c6aadb2622c490fa9", + expected: "80863d2995d646677a00a9632c8f7ab175315ead0d1c824c9088b21c78e10b16", + }, { + name: "random sampling #3", + in1: "c7c95e93d0892b2b2cdd77e80eb646ea61be7a30ac7e097e9f843af73fad5c22", + in2: "3afe6f91a74dfc1c7f15c34907ee981656c37236d946767dd53ccad9190e437c", + expected: "2c7ce2577d72747abf33b3116a4df00b881ec6785c47ffc74c105d158bba36f", + }, { + name: "random sampling #4", + in1: "fd1c26f6a23381e5d785ba889494ec059369b888ad8431cd67d8c934b580dbe1", + in2: "a475aa5a31dcca90ef5b53c097d9133d6b7117474b41e7877bb199590fc0489c", + expected: "a191d150d4104c76c6e10e492c6dff42fedacfcff8c61954e38a628ec541284e", + }, { + name: "random sampling #5", + in1: "ad82b8d1cc136e23e9fd77fe2c7db1fe5a2ecbfcbde59ab3529758334f862d28", + in2: "4d6a4e95d6d61f4f46b528bebe152d408fd741157a28f415639347a84f6f574b", + expected: "faed0767a2e98d7330b2a0bcea92df3eea060d12380e8ec8b62a9fdb9ef58473", + }, { + name: "random sampling #6", + in1: "f3f43a2540054a86e1df98547ec1c0e157b193e5350fb4a3c3ea214b228ac5e7", + in2: "25706572592690ea3ddc951a1b48b504a4c83dc253756e1b96d56fdfb3199522", + expected: "19649f97992bdb711fbc2d6e9a0a75e5fc79d1a7888522bf5abf912bd5a45eda", + }, { + name: "random sampling #7", + in1: "6915bb94eef13ff1bb9b2633d997e13b9b1157c713363cc0e891416d6734f5b8", + in2: "11f90d6ac6fe1c4e8900b1c85fb575c251ec31b9bc34b35ada0aea1c21eded22", + expected: "7b0ec8ffb5ef5c40449bd7fc394d56fdecfd8980cf6af01bc29c2b898922e2da", + }, { + name: "random sampling #8", + in1: "48b0c9eae622eed9335b747968544eb3e75cb2dc8128388f948aa30f88cabde4", + in2: "0989882b52f85f9d524a3a3061a0e01f46d597839d2ba637320f4b9510c8d2d5", + expected: "523a5216391b4e7685a5aea9c9f52ed32e324a601e53dec6c699eea4999390b9", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() - f2 := new(fieldVal).SetHex(test.in2).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Add(f2).Normalize() + for _, test := range tests { + // Parse test hex. + f1 := setHex(test.in1).Normalize() + f2 := setHex(test.in2).Normalize() + expected := setHex(test.expected).Normalize() + + // Ensure adding the two values with the result going to another + // variable produces the expected result. + result := new(FieldVal).Add2(f1, f2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Add #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + result, expected) continue } - } -} -// TestAdd2 ensures that adding two field values together via Add2 works as -// expected. -func TestAdd2(t *testing.T) { - tests := []struct { - in1 string // first hex encoded value - in2 string // second hex encoded value to add - expected string // expected hex encoded value - }{ - {"0", "1", "1"}, - {"1", "0", "1"}, - {"1", "1", "2"}, - // secp256k1 prime-1 + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1", "0"}, - // secp256k1 prime + 1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "1", "1"}, - // close but over the secp256k1 prime - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000", "f1ffff000", "1ffff3d1"}, - // Random samples. - { - "ad82b8d1cc136e23e9fd77fe2c7db1fe5a2ecbfcbde59ab3529758334f862d28", - "4d6a4e95d6d61f4f46b528bebe152d408fd741157a28f415639347a84f6f574b", - "faed0767a2e98d7330b2a0bcea92df3eea060d12380e8ec8b62a9fdb9ef58473", - }, - { - "f3f43a2540054a86e1df98547ec1c0e157b193e5350fb4a3c3ea214b228ac5e7", - "25706572592690ea3ddc951a1b48b504a4c83dc253756e1b96d56fdfb3199522", - "19649f97992bdb711fbc2d6e9a0a75e5fc79d1a7888522bf5abf912bd5a45eda", - }, - { - "6915bb94eef13ff1bb9b2633d997e13b9b1157c713363cc0e891416d6734f5b8", - "11f90d6ac6fe1c4e8900b1c85fb575c251ec31b9bc34b35ada0aea1c21eded22", - "7b0ec8ffb5ef5c40449bd7fc394d56fdecfd8980cf6af01bc29c2b898922e2da", - }, - { - "48b0c9eae622eed9335b747968544eb3e75cb2dc8128388f948aa30f88cabde4", - "0989882b52f85f9d524a3a3061a0e01f46d597839d2ba637320f4b9510c8d2d5", - "523a5216391b4e7685a5aea9c9f52ed32e324a601e53dec6c699eea4999390b9", - }, - } - - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() - f2 := new(fieldVal).SetHex(test.in2).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Add2(f, f2).Normalize() - if !result.Equals(expected) { - t.Errorf("fieldVal.Add2 #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + // Ensure adding the value to an existing field value produces the + // expected result. + f1.Add(f2).Normalize() + if !f1.Equals(expected) { + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + f1, expected) continue } } } -// TestMulInt ensures that adding an integer to field values via MulInt works as -// expected. -func TestMulInt(t *testing.T) { +// TestFieldMulInt ensures that multiplying an integer to field values via +// MulInt works as expected. +func TestFieldMulInt(t *testing.T) { tests := []struct { + name string // test description in1 string // hex encoded value - in2 uint // unsigned integer to multiply with value above + in2 uint8 // unsigned integer to multiply with value above expected string // expected hex encoded value - }{ - {"0", 0, "0"}, - {"1", 0, "0"}, - {"0", 1, "0"}, - {"1", 1, "1"}, - // secp256k1 prime-1 * 2 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - 2, - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", - }, - // secp256k1 prime * 3 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 3, "0"}, - // secp256k1 prime-1 * 8 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - 8, - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", - }, + }{{ + name: "zero * zero", + in1: "0", + in2: 0, + expected: "0", + }, { + name: "one * zero", + in1: "1", + in2: 0, + expected: "0", + }, { + name: "zero * one", + in1: "0", + in2: 1, + expected: "0", + }, { + name: "one * one", + in1: "1", + in2: 1, + expected: "1", + }, { + name: "secp256k1 prime-1 * 2", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: 2, + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + }, { + name: "secp256k1 prime * 3", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: 3, + expected: "0", + }, { + name: "secp256k1 prime-1 * 8", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: 8, + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", + }, { // Random samples for first value. The second value is limited // to 8 since that is the maximum int used in the elliptic curve // calculations. - { - "b75674dc9180d306c692163ac5e089f7cef166af99645c0c23568ab6d967288a", - 6, - "4c06bd2b6904f228a76c8560a3433bced9a8681d985a2848d407404d186b0280", - }, - { - "54873298ac2b5ba8591c125ae54931f5ea72040aee07b208d6135476fb5b9c0e", - 3, - "fd9597ca048212f90b543710afdb95e1bf560c20ca17161a8239fd64f212d42a", - }, - { - "7c30fbd363a74c17e1198f56b090b59bbb6c8755a74927a6cba7a54843506401", - 5, - "6cf4eb20f2447c77657fccb172d38c0aa91ea4ac446dc641fa463a6b5091fba7", - }, - { - "fb4529be3e027a3d1587d8a500b72f2d312e3577340ef5175f96d113be4c2ceb", - 8, - "da294df1f013d1e8ac3ec52805b979698971abb9a077a8bafcb688a4f261820f", - }, - } + name: "random sampling #1", + in1: "b75674dc9180d306c692163ac5e089f7cef166af99645c0c23568ab6d967288a", + in2: 6, + expected: "4c06bd2b6904f228a76c8560a3433bced9a8681d985a2848d407404d186b0280", + }, { + name: "random sampling #2", + in1: "54873298ac2b5ba8591c125ae54931f5ea72040aee07b208d6135476fb5b9c0e", + in2: 3, + expected: "fd9597ca048212f90b543710afdb95e1bf560c20ca17161a8239fd64f212d42a", + }, { + name: "random sampling #3", + in1: "7c30fbd363a74c17e1198f56b090b59bbb6c8755a74927a6cba7a54843506401", + in2: 5, + expected: "6cf4eb20f2447c77657fccb172d38c0aa91ea4ac446dc641fa463a6b5091fba7", + }, { + name: "random sampling #3", + in1: "fb4529be3e027a3d1587d8a500b72f2d312e3577340ef5175f96d113be4c2ceb", + in2: 8, + expected: "da294df1f013d1e8ac3ec52805b979698971abb9a077a8bafcb688a4f261820f", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() + for _, test := range tests { + f := setHex(test.in1).Normalize() + expected := setHex(test.expected).Normalize() result := f.MulInt(test.in2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.MulInt #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: wrong result -- got: %v -- want: %v", test.name, + result, expected) continue } } } -// TestMul ensures that multiplying two field valuess via Mul works as expected. -func TestMul(t *testing.T) { +// TestFieldMul ensures that multiplying two field values via Mul and Mul2 works +// as expected. +func TestFieldMul(t *testing.T) { tests := []struct { + name string // test description in1 string // first hex encoded value in2 string // second hex encoded value to multiply with expected string // expected hex encoded value - }{ - {"0", "0", "0"}, - {"1", "0", "0"}, - {"0", "1", "0"}, - {"1", "1", "1"}, - // slightly over prime - { - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1ffff", - "1000", - "1ffff3d1", - }, - // secp256k1 prime-1 * 2 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "2", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", - }, - // secp256k1 prime * 3 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "3", "0"}, - // secp256k1 prime-1 * 8 - { - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - "8", - "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", - }, - // Random samples. - { - "cfb81753d5ef499a98ecc04c62cb7768c2e4f1740032946db1c12e405248137e", - "58f355ad27b4d75fb7db0442452e732c436c1f7c5a7c4e214fa9cc031426a7d3", - "1018cd2d7c2535235b71e18db9cd98027386328d2fa6a14b36ec663c4c87282b", - }, - { - "26e9d61d1cdf3920e9928e85fa3df3e7556ef9ab1d14ec56d8b4fc8ed37235bf", - "2dfc4bbe537afee979c644f8c97b31e58be5296d6dbc460091eae630c98511cf", - "da85f48da2dc371e223a1ae63bd30b7e7ee45ae9b189ac43ff357e9ef8cf107a", - }, - { - "5db64ed5afb71646c8b231585d5b2bf7e628590154e0854c4c29920b999ff351", - "279cfae5eea5d09ade8e6a7409182f9de40981bc31c84c3d3dfe1d933f152e9a", - "2c78fbae91792dd0b157abe3054920049b1879a7cc9d98cfda927d83be411b37", - }, - { - "b66dfc1f96820b07d2bdbd559c19319a3a73c97ceb7b3d662f4fe75ecb6819e6", - "bf774aba43e3e49eb63a6e18037d1118152568f1a3ac4ec8b89aeb6ff8008ae1", - "c4f016558ca8e950c21c3f7fc15f640293a979c7b01754ee7f8b3340d4902ebb", - }, - } + }{{ + name: "zero * zero", + in1: "0", + in2: "0", + expected: "0", + }, { + name: "one * zero", + in1: "1", + in2: "0", + expected: "0", + }, { + name: "zero * one", + in1: "0", + in2: "1", + expected: "0", + }, { + name: "one * one", + in1: "1", + in2: "1", + expected: "1", + }, { + name: "slightly over prime", + in1: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1ffff", + in2: "1000", + expected: "1ffff3d1", + }, { + name: "secp256k1 prime-1 * 2", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: "2", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + }, { + name: "secp256k1 prime * 3", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + in2: "3", + expected: "0", + }, { + name: "secp256k1 prime * 3", + in1: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + in2: "8", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc27", + }, { + name: "random sampling #1", + in1: "cfb81753d5ef499a98ecc04c62cb7768c2e4f1740032946db1c12e405248137e", + in2: "58f355ad27b4d75fb7db0442452e732c436c1f7c5a7c4e214fa9cc031426a7d3", + expected: "1018cd2d7c2535235b71e18db9cd98027386328d2fa6a14b36ec663c4c87282b", + }, { + name: "random sampling #2", + in1: "26e9d61d1cdf3920e9928e85fa3df3e7556ef9ab1d14ec56d8b4fc8ed37235bf", + in2: "2dfc4bbe537afee979c644f8c97b31e58be5296d6dbc460091eae630c98511cf", + expected: "da85f48da2dc371e223a1ae63bd30b7e7ee45ae9b189ac43ff357e9ef8cf107a", + }, { + name: "random sampling #3", + in1: "5db64ed5afb71646c8b231585d5b2bf7e628590154e0854c4c29920b999ff351", + in2: "279cfae5eea5d09ade8e6a7409182f9de40981bc31c84c3d3dfe1d933f152e9a", + expected: "2c78fbae91792dd0b157abe3054920049b1879a7cc9d98cfda927d83be411b37", + }, { + name: "random sampling #4", + in1: "b66dfc1f96820b07d2bdbd559c19319a3a73c97ceb7b3d662f4fe75ecb6819e6", + in2: "bf774aba43e3e49eb63a6e18037d1118152568f1a3ac4ec8b89aeb6ff8008ae1", + expected: "c4f016558ca8e950c21c3f7fc15f640293a979c7b01754ee7f8b3340d4902ebb", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in1).Normalize() - f2 := new(fieldVal).SetHex(test.in2).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Mul(f2).Normalize() + for _, test := range tests { + f1 := setHex(test.in1).Normalize() + f2 := setHex(test.in2).Normalize() + expected := setHex(test.expected).Normalize() + + // Ensure multiplying the two values with the result going to another + // variable produces the expected result. + result := new(FieldVal).Mul2(f1, f2).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Mul #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + result, expected) + continue + } + + // Ensure multiplying the value to an existing field value produces the + // expected result. + f1.Mul(f2).Normalize() + if !f1.Equals(expected) { + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + f1, expected) continue } } } -// TestSquare ensures that squaring field values via Square works as expected. -func TestSquare(t *testing.T) { +// TestFieldSquare ensures that squaring field values via Square and SqualVal +// works as expected. +func TestFieldSquare(t *testing.T) { tests := []struct { + name string // test description in string // hex encoded value expected string // expected hex encoded value - }{ - // secp256k1 prime (aka 0) - {"0", "0"}, - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", "0"}, - {"0", "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"}, - // secp256k1 prime-1 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", "1"}, - // secp256k1 prime-2 - {"fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", "4"}, - // Random sampling - { - "b0ba920360ea8436a216128047aab9766d8faf468895eb5090fc8241ec758896", - "133896b0b69fda8ce9f648b9a3af38f345290c9eea3cbd35bafcadf7c34653d3", - }, - { - "c55d0d730b1d0285a1599995938b042a756e6e8857d390165ffab480af61cbd5", - "cd81758b3f5877cbe7e5b0a10cebfa73bcbf0957ca6453e63ee8954ab7780bee", - }, - { - "e89c1f9a70d93651a1ba4bca5b78658f00de65a66014a25544d3365b0ab82324", - "39ffc7a43e5dbef78fd5d0354fb82c6d34f5a08735e34df29da14665b43aa1f", - }, - { - "7dc26186079d22bcbe1614aa20ae627e62d72f9be7ad1e99cac0feb438956f05", - "bf86bcfc4edb3d81f916853adfda80c07c57745b008b60f560b1912f95bce8ae", - }, - } + }{{ + name: "zero", + in: "0", + expected: "0", + }, { + name: "secp256k1 prime (direct val in with 0 out)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0", + }, { + name: "secp256k1 prime (0 in with direct val out)", + in: "0", + expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + }, { + name: "secp256k1 prime - 1", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + expected: "1", + }, { + name: "secp256k1 prime - 2", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + expected: "4", + }, { + name: "random sampling #1", + in: "b0ba920360ea8436a216128047aab9766d8faf468895eb5090fc8241ec758896", + expected: "133896b0b69fda8ce9f648b9a3af38f345290c9eea3cbd35bafcadf7c34653d3", + }, { + name: "random sampling #2", + in: "c55d0d730b1d0285a1599995938b042a756e6e8857d390165ffab480af61cbd5", + expected: "cd81758b3f5877cbe7e5b0a10cebfa73bcbf0957ca6453e63ee8954ab7780bee", + }, { + name: "random sampling #3", + in: "e89c1f9a70d93651a1ba4bca5b78658f00de65a66014a25544d3365b0ab82324", + expected: "39ffc7a43e5dbef78fd5d0354fb82c6d34f5a08735e34df29da14665b43aa1f", + }, { + name: "random sampling #4", + in: "7dc26186079d22bcbe1614aa20ae627e62d72f9be7ad1e99cac0feb438956f05", + expected: "bf86bcfc4edb3d81f916853adfda80c07c57745b008b60f560b1912f95bce8ae", + }} - t.Logf("Running %d tests", len(tests)) - for i, test := range tests { - f := new(fieldVal).SetHex(test.in).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() - result := f.Square().Normalize() + for _, test := range tests { + f := setHex(test.in).Normalize() + expected := setHex(test.expected).Normalize() + + // Ensure squaring the value with the result going to another variable + // produces the expected result. + result := new(FieldVal).SquareVal(f).Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Square #%d wrong result\n"+ - "got: %v\nwant: %v", i, result, expected) + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + result, expected) + continue + } + + // Ensure self squaring an existing field value produces the expected + // result. + f.Square().Normalize() + if !f.Equals(expected) { + t.Errorf("%s: unexpected result\ngot: %v\nwant: %v", test.name, + f, expected) continue } } @@ -813,296 +846,127 @@ func TestInverse(t *testing.T) { t.Logf("Running %d tests", len(tests)) for i, test := range tests { - f := new(fieldVal).SetHex(test.in).Normalize() - expected := new(fieldVal).SetHex(test.expected).Normalize() + f := setHex(test.in).Normalize() + expected := setHex(test.expected).Normalize() result := f.Inverse().Normalize() if !result.Equals(expected) { - t.Errorf("fieldVal.Inverse #%d wrong result\n"+ + t.Errorf("FieldVal.Inverse #%d wrong result\n"+ "got: %v\nwant: %v", i, result, expected) continue } } } -// randFieldVal returns a random, normalized element in the field. -func randFieldVal(t *testing.T) fieldVal { - var b [32]byte - if _, err := rand.Read(b[:]); err != nil { - t.Fatalf("unable to create random element: %v", err) - } - - var x fieldVal - return *x.SetBytes(&b).Normalize() -} - -type sqrtTest struct { - name string - in string - expected string -} - -// TestSqrt asserts that a fieldVal properly computes the square root modulo the -// sep256k1 prime. -func TestSqrt(t *testing.T) { - var tests []sqrtTest - - // No valid root exists for the negative of a square. - for i := uint(9); i > 0; i-- { - var ( - x fieldVal - s fieldVal // x^2 mod p - n fieldVal // -x^2 mod p - ) - - x.SetInt(i) - s.SquareVal(&x).Normalize() - n.NegateVal(&s, 1).Normalize() - - tests = append(tests, sqrtTest{ - name: fmt.Sprintf("-%d", i), - in: fmt.Sprintf("%x", *n.Bytes()), - }) - } - - // A root should exist for true squares. - for i := uint(0); i < 10; i++ { - var ( - x fieldVal - s fieldVal // x^2 mod p - ) - - x.SetInt(i) - s.SquareVal(&x).Normalize() - - tests = append(tests, sqrtTest{ - name: fmt.Sprintf("%d", i), - in: fmt.Sprintf("%x", *s.Bytes()), - expected: fmt.Sprintf("%x", *x.Bytes()), - }) - } - - // Compute a non-square element, by negating if it has a root. - ns := randFieldVal(t) - if new(fieldVal).SqrtVal(&ns).Square().Equals(&ns) { - ns.Negate(1).Normalize() - } - - // For large random field values, test that: - // 1) its square has a valid root. - // 2) the negative of its square has no root. - // 3) the product of its square with a non-square has no root. - for i := 0; i < 10; i++ { - var ( - x fieldVal - s fieldVal // x^2 mod p - n fieldVal // -x^2 mod p - m fieldVal // ns*x^2 mod p - ) - - x = randFieldVal(t) - s.SquareVal(&x).Normalize() - n.NegateVal(&s, 1).Normalize() - m.Mul2(&s, &ns).Normalize() +// randFieldVal returns a field value created from a random value generated by +// the passed rng. +func randFieldVal(t *testing.T, rng *rand.Rand) *FieldVal { + t.Helper() - // A root should exist for true squares. - tests = append(tests, sqrtTest{ - name: fmt.Sprintf("%x", *s.Bytes()), - in: fmt.Sprintf("%x", *s.Bytes()), - expected: fmt.Sprintf("%x", *x.Bytes()), - }) - - // No valid root exists for the negative of a square. - tests = append(tests, sqrtTest{ - name: fmt.Sprintf("-%x", *s.Bytes()), - in: fmt.Sprintf("%x", *n.Bytes()), - }) - - // No root should be computed for product of a square and - // non-square. - tests = append(tests, sqrtTest{ - name: fmt.Sprintf("ns*%x", *s.Bytes()), - in: fmt.Sprintf("%x", *m.Bytes()), - }) + var buf [32]byte + if _, err := rng.Read(buf[:]); err != nil { + t.Fatalf("failed to read random: %v", err) } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - testSqrt(t, test) - }) - } + // Create and return both a big integer and a field value. + var fv FieldVal + fv.SetBytes(&buf) + return &fv } -func testSqrt(t *testing.T, test sqrtTest) { - var ( - f fieldVal - root fieldVal - rootNeg fieldVal - ) - - f.SetHex(test.in).Normalize() - - // Compute sqrt(f) and its negative. - root.SqrtVal(&f).Normalize() - rootNeg.NegateVal(&root, 1).Normalize() - - switch { - - // If we expect a square root, verify that either the computed square - // root is +/- the expected value. - case len(test.expected) > 0: - var expected fieldVal - expected.SetHex(test.expected).Normalize() - if !root.Equals(&expected) && !rootNeg.Equals(&expected) { - t.Fatalf("fieldVal.Sqrt incorrect root\n"+ - "got: %v\ngot_neg: %v\nwant: %v", - root, rootNeg, expected) - } - - // Otherwise, we expect this input not to have a square root. - default: - if root.Square().Equals(&f) || rootNeg.Square().Equals(&f) { - t.Fatalf("fieldVal.Sqrt root should not exist\n"+ - "got: %v\ngot_neg: %v", root, rootNeg) - } - } -} - -// TestFieldSetBytes ensures that setting a field value to a 256-bit big-endian -// unsigned integer via both the slice and array methods works as expected for -// edge cases. Random cases are tested via the various other tests. -func TestFieldSetBytes(t *testing.T) { +// TestFieldSquareRoot ensures that calculating the square root of field values +// via SquareRootVal works as expected for edge cases. +func TestFieldSquareRoot(t *testing.T) { tests := []struct { - name string // test description - in string // hex encoded test value - expected [10]uint32 // expected raw ints + name string // test description + in string // hex encoded value + valid bool // whether or not the value has a square root + want string // expected hex encoded value }{{ - name: "zero", - in: "00", - expected: [10]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + name: "secp256k1 prime (as 0 in and out)", + in: "0", + valid: true, + want: "0", }, { - name: "field prime", - in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, - 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, - }, + name: "secp256k1 prime (direct val with 0 out)", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + valid: true, + want: "0", }, { - name: "field prime - 1", - in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", - expected: [10]uint32{ - 0x03fffc2e, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, - 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, - }, + name: "secp256k1 prime (as 0 in direct val out)", + in: "0", + valid: true, + want: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", }, { - name: "field prime + 1 (overflow in word zero)", - in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc30", - expected: [10]uint32{ - 0x03fffc30, 0x03ffffbf, 0x03ffffff, 0x03ffffff, 0x03ffffff, - 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, - }, - }, { - name: "field prime first 32 bits", - in: "fffffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x00000003f, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, - }, { - name: "field prime word zero", - in: "03fffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, + name: "secp256k1 prime-1", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e", + valid: false, + want: "0000000000000000000000000000000000000000000000000000000000000001", }, { - name: "field prime first 64 bits", - in: "fffffffefffffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x03ffffbf, 0x00000fff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, + name: "secp256k1 prime-2", + in: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", + valid: false, + want: "210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f7", }, { - name: "field prime word zero and one", - in: "0ffffefffffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x03ffffbf, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, + name: "(secp256k1 prime-2)^2", + in: "0000000000000000000000000000000000000000000000000000000000000004", + valid: true, + want: "0000000000000000000000000000000000000000000000000000000000000002", }, { - name: "field prime first 96 bits", - in: "fffffffffffffffefffffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x0003ffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, + name: "value 1", + in: "0000000000000000000000000000000000000000000000000000000000000001", + valid: true, + want: "0000000000000000000000000000000000000000000000000000000000000001", }, { - name: "field prime word zero, one, and two", - in: "3ffffffffffefffffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x03ffffbf, 0x03ffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, + name: "value 2", + in: "0000000000000000000000000000000000000000000000000000000000000002", + valid: true, + want: "210c790573632359b1edb4302c117d8a132654692c3feeb7de3a86ac3f3b53f7", }, { - name: "overflow in word one (prime + 1<<26)", - in: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffff03fffc2f", - expected: [10]uint32{ - 0x03fffc2f, 0x03ffffc0, 0x03ffffff, 0x03ffffff, 0x03ffffff, - 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, - }, + name: "random sampling 1", + in: "16fb970147a9acc73654d4be233cc48b875ce20a2122d24f073d29bd28805aca", + valid: false, + want: "6a27dcfca440cf7930a967be533b9620e397f122787c53958aaa7da7ad3d89a4", }, { - name: "(field prime - 1) * 2 NOT mod P, truncated >32 bytes", - in: "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffff85c", - expected: [10]uint32{ - 0x01fffff8, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, - 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x00007fff, - }, + name: "square of random sampling 1", + in: "f4a8c3738ace0a1c3abf77737ae737f07687b5e24c07a643398298bd96893a18", + valid: true, + want: "e90468feb8565338c9ab2b41dcc33b7478a31df5dedd2db0f8c2d641d77fa165", }, { - name: "2^256 - 1", - in: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - expected: [10]uint32{ - 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, - 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x003fffff, - }, + name: "random sampling 2", + in: "69d1323ce9f1f7b3bd3c7320b0d6311408e30281e273e39a0d8c7ee1c8257919", + valid: true, + want: "61f4a7348274a52d75dfe176b8e3aaff61c1c833b6678260ba73def0fb2ad148", }, { - name: "alternating bits", - in: "a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5", - expected: [10]uint32{ - 0x01a5a5a5, 0x01696969, 0x025a5a5a, 0x02969696, 0x01a5a5a5, - 0x01696969, 0x025a5a5a, 0x02969696, 0x01a5a5a5, 0x00296969, - }, + name: "random sampling 3", + in: "e0debf988ae098ecda07d0b57713e97c6d213db19753e8c95aa12a2fc1cc5272", + valid: false, + want: "6e1cc9c311d33d901670135244f994b1ea39501f38002269b34ce231750cfbac", }, { - name: "alternating bits 2", - in: "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a", - expected: [10]uint32{ - 0x025a5a5a, 0x02969696, 0x01a5a5a5, 0x01696969, 0x025a5a5a, - 0x02969696, 0x01a5a5a5, 0x01696969, 0x025a5a5a, 0x00169696, - }, + name: "random sampling 4", + in: "dcd394f91f74c2ba16aad74a22bb0ed47fe857774b8f2d6c09e28bfb14642878", + valid: true, + want: "72b22fe6f173f8bcb21898806142ed4c05428601256eafce5d36c1b08fb82bab", }} for _, test := range tests { - inBytes := hexToBytes(test.in) - - // Ensure setting the bytes via the slice method works as expected. - var f fieldVal - f.SetByteSlice(inBytes) - if !reflect.DeepEqual(f.n, test.expected) { - t.Errorf("%s: unexpected result\ngot: %x\nwant: %x", test.name, f.n, - test.expected) + input := setHex(test.in).Normalize() + want := setHex(test.want).Normalize() + + // Calculate the square root and enusre the validity flag matches the + // expected value. + var result FieldVal + isValid := result.SquareRootVal(input) + if isValid != test.valid { + t.Errorf("%s: mismatched validity -- got %v, want %v", test.name, + isValid, test.valid) continue } - // Ensure setting the bytes via the array method works as expected. - var f2 fieldVal - var b32 [32]byte - truncatedInBytes := inBytes - if len(truncatedInBytes) > 32 { - truncatedInBytes = truncatedInBytes[:32] - } - copy(b32[32-len(truncatedInBytes):], truncatedInBytes) - f2.SetBytes(&b32) - if !reflect.DeepEqual(f2.n, test.expected) { - t.Errorf("%s: unexpected result\ngot: %x\nwant: %x", test.name, - f2.n, test.expected) + // Ensure the calculated result matches the expected value. + result.Normalize() + if !result.Equals(want) { + t.Errorf("%s: d wrong result\ngot: %v\nwant: %v", test.name, result, + want) continue } } diff --git a/btcec/genprecomps.go b/btcec/genprecomps.go deleted file mode 100644 index d4a9c1b830..0000000000 --- a/btcec/genprecomps.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -// This file is ignored during the regular build due to the following build tag. -// It is called by go generate and used to automatically generate pre-computed -// tables used to accelerate operations. -// +build ignore - -package main - -import ( - "bytes" - "compress/zlib" - "encoding/base64" - "fmt" - "log" - "os" - - "github.com/btcsuite/btcd/btcec" -) - -func main() { - fi, err := os.Create("secp256k1.go") - if err != nil { - log.Fatal(err) - } - defer fi.Close() - - // Compress the serialized byte points. - serialized := btcec.S256().SerializedBytePoints() - var compressed bytes.Buffer - w := zlib.NewWriter(&compressed) - if _, err := w.Write(serialized); err != nil { - fmt.Println(err) - os.Exit(1) - } - w.Close() - - // Encode the compressed byte points with base64. - encoded := make([]byte, base64.StdEncoding.EncodedLen(compressed.Len())) - base64.StdEncoding.Encode(encoded, compressed.Bytes()) - - fmt.Fprintln(fi, "// Copyright (c) 2015 The btcsuite developers") - fmt.Fprintln(fi, "// Use of this source code is governed by an ISC") - fmt.Fprintln(fi, "// license that can be found in the LICENSE file.") - fmt.Fprintln(fi) - fmt.Fprintln(fi, "package btcec") - fmt.Fprintln(fi) - fmt.Fprintln(fi, "// Auto-generated file (see genprecomps.go)") - fmt.Fprintln(fi, "// DO NOT EDIT") - fmt.Fprintln(fi) - fmt.Fprintf(fi, "var secp256k1BytePoints = %q\n", string(encoded)) - - a1, b1, a2, b2 := btcec.S256().EndomorphismVectors() - fmt.Println("The following values are the computed linearly " + - "independent vectors needed to make use of the secp256k1 " + - "endomorphism:") - fmt.Printf("a1: %x\n", a1) - fmt.Printf("b1: %x\n", b1) - fmt.Printf("a2: %x\n", a2) - fmt.Printf("b2: %x\n", b2) -} diff --git a/btcec/gensecp256k1.go b/btcec/gensecp256k1.go deleted file mode 100644 index 1928702da8..0000000000 --- a/btcec/gensecp256k1.go +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2014-2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -// This file is ignored during the regular build due to the following build tag. -// This build tag is set during go generate. -// +build gensecp256k1 - -package btcec - -// References: -// [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone) - -import ( - "encoding/binary" - "math/big" -) - -// secp256k1BytePoints are dummy points used so the code which generates the -// real values can compile. -var secp256k1BytePoints = "" - -// getDoublingPoints returns all the possible G^(2^i) for i in -// 0..n-1 where n is the curve's bit size (256 in the case of secp256k1) -// the coordinates are recorded as Jacobian coordinates. -func (curve *KoblitzCurve) getDoublingPoints() [][3]fieldVal { - doublingPoints := make([][3]fieldVal, curve.BitSize) - - // initialize px, py, pz to the Jacobian coordinates for the base point - px, py := curve.bigAffineToField(curve.Gx, curve.Gy) - pz := new(fieldVal).SetInt(1) - for i := 0; i < curve.BitSize; i++ { - doublingPoints[i] = [3]fieldVal{*px, *py, *pz} - // P = 2*P - curve.doubleJacobian(px, py, pz, px, py, pz) - } - return doublingPoints -} - -// SerializedBytePoints returns a serialized byte slice which contains all of -// the possible points per 8-bit window. This is used to when generating -// secp256k1.go. -func (curve *KoblitzCurve) SerializedBytePoints() []byte { - doublingPoints := curve.getDoublingPoints() - - // Segregate the bits into byte-sized windows - serialized := make([]byte, curve.byteSize*256*3*10*4) - offset := 0 - for byteNum := 0; byteNum < curve.byteSize; byteNum++ { - // Grab the 8 bits that make up this byte from doublingPoints. - startingBit := 8 * (curve.byteSize - byteNum - 1) - computingPoints := doublingPoints[startingBit : startingBit+8] - - // Compute all points in this window and serialize them. - for i := 0; i < 256; i++ { - px, py, pz := new(fieldVal), new(fieldVal), new(fieldVal) - for j := 0; j < 8; j++ { - if i>>uint(j)&1 == 1 { - curve.addJacobian(px, py, pz, &computingPoints[j][0], - &computingPoints[j][1], &computingPoints[j][2], px, py, pz) - } - } - for i := 0; i < 10; i++ { - binary.LittleEndian.PutUint32(serialized[offset:], px.n[i]) - offset += 4 - } - for i := 0; i < 10; i++ { - binary.LittleEndian.PutUint32(serialized[offset:], py.n[i]) - offset += 4 - } - for i := 0; i < 10; i++ { - binary.LittleEndian.PutUint32(serialized[offset:], pz.n[i]) - offset += 4 - } - } - } - - return serialized -} - -// sqrt returns the square root of the provided big integer using Newton's -// method. It's only compiled and used during generation of pre-computed -// values, so speed is not a huge concern. -func sqrt(n *big.Int) *big.Int { - // Initial guess = 2^(log_2(n)/2) - guess := big.NewInt(2) - guess.Exp(guess, big.NewInt(int64(n.BitLen()/2)), nil) - - // Now refine using Newton's method. - big2 := big.NewInt(2) - prevGuess := big.NewInt(0) - for { - prevGuess.Set(guess) - guess.Add(guess, new(big.Int).Div(n, guess)) - guess.Div(guess, big2) - if guess.Cmp(prevGuess) == 0 { - break - } - } - return guess -} - -// EndomorphismVectors runs the first 3 steps of algorithm 3.74 from [GECC] to -// generate the linearly independent vectors needed to generate a balanced -// length-two representation of a multiplier such that k = k1 + k2λ (mod N) and -// returns them. Since the values will always be the same given the fact that N -// and λ are fixed, the final results can be accelerated by storing the -// precomputed values with the curve. -func (curve *KoblitzCurve) EndomorphismVectors() (a1, b1, a2, b2 *big.Int) { - bigMinus1 := big.NewInt(-1) - - // This section uses an extended Euclidean algorithm to generate a - // sequence of equations: - // s[i] * N + t[i] * λ = r[i] - - nSqrt := sqrt(curve.N) - u, v := new(big.Int).Set(curve.N), new(big.Int).Set(curve.lambda) - x1, y1 := big.NewInt(1), big.NewInt(0) - x2, y2 := big.NewInt(0), big.NewInt(1) - q, r := new(big.Int), new(big.Int) - qu, qx1, qy1 := new(big.Int), new(big.Int), new(big.Int) - s, t := new(big.Int), new(big.Int) - ri, ti := new(big.Int), new(big.Int) - a1, b1, a2, b2 = new(big.Int), new(big.Int), new(big.Int), new(big.Int) - found, oneMore := false, false - for u.Sign() != 0 { - // q = v/u - q.Div(v, u) - - // r = v - q*u - qu.Mul(q, u) - r.Sub(v, qu) - - // s = x2 - q*x1 - qx1.Mul(q, x1) - s.Sub(x2, qx1) - - // t = y2 - q*y1 - qy1.Mul(q, y1) - t.Sub(y2, qy1) - - // v = u, u = r, x2 = x1, x1 = s, y2 = y1, y1 = t - v.Set(u) - u.Set(r) - x2.Set(x1) - x1.Set(s) - y2.Set(y1) - y1.Set(t) - - // As soon as the remainder is less than the sqrt of n, the - // values of a1 and b1 are known. - if !found && r.Cmp(nSqrt) < 0 { - // When this condition executes ri and ti represent the - // r[i] and t[i] values such that i is the greatest - // index for which r >= sqrt(n). Meanwhile, the current - // r and t values are r[i+1] and t[i+1], respectively. - - // a1 = r[i+1], b1 = -t[i+1] - a1.Set(r) - b1.Mul(t, bigMinus1) - found = true - oneMore = true - - // Skip to the next iteration so ri and ti are not - // modified. - continue - - } else if oneMore { - // When this condition executes ri and ti still - // represent the r[i] and t[i] values while the current - // r and t are r[i+2] and t[i+2], respectively. - - // sum1 = r[i]^2 + t[i]^2 - rSquared := new(big.Int).Mul(ri, ri) - tSquared := new(big.Int).Mul(ti, ti) - sum1 := new(big.Int).Add(rSquared, tSquared) - - // sum2 = r[i+2]^2 + t[i+2]^2 - r2Squared := new(big.Int).Mul(r, r) - t2Squared := new(big.Int).Mul(t, t) - sum2 := new(big.Int).Add(r2Squared, t2Squared) - - // if (r[i]^2 + t[i]^2) <= (r[i+2]^2 + t[i+2]^2) - if sum1.Cmp(sum2) <= 0 { - // a2 = r[i], b2 = -t[i] - a2.Set(ri) - b2.Mul(ti, bigMinus1) - } else { - // a2 = r[i+2], b2 = -t[i+2] - a2.Set(r) - b2.Mul(t, bigMinus1) - } - - // All done. - break - } - - ri.Set(r) - ti.Set(t) - } - - return a1, b1, a2, b2 -} diff --git a/btcec/go.mod b/btcec/go.mod new file mode 100644 index 0000000000..ce5eb3321e --- /dev/null +++ b/btcec/go.mod @@ -0,0 +1,9 @@ +module github.com/btcsuite/btcd/btcec/v2 + +go 1.17 + +require ( + github.com/btcsuite/btcd v0.22.0-beta + github.com/davecgh/go-spew v1.1.1 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 +) diff --git a/btcec/go.sum b/btcec/go.sum new file mode 100644 index 0000000000..a0f9c5b8fa --- /dev/null +++ b/btcec/go.sum @@ -0,0 +1,49 @@ +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcec/modnscalar.go b/btcec/modnscalar.go new file mode 100644 index 0000000000..eb1b8f05f4 --- /dev/null +++ b/btcec/modnscalar.go @@ -0,0 +1,42 @@ +package btcec + +import ( + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +// ModNScalar implements optimized 256-bit constant-time fixed-precision +// arithmetic over the secp256k1 group order. This means all arithmetic is +// performed modulo: +// +// 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 +// +// It only implements the arithmetic needed for elliptic curve operations, +// however, the operations that are not implemented can typically be worked +// around if absolutely needed. For example, subtraction can be performed by +// adding the negation. +// +// Should it be absolutely necessary, conversion to the standard library +// math/big.Int can be accomplished by using the Bytes method, slicing the +// resulting fixed-size array, and feeding it to big.Int.SetBytes. However, +// that should typically be avoided when possible as conversion to big.Ints +// requires allocations, is not constant time, and is slower when working modulo +// the group order. +type ModNScalar = secp.ModNScalar + +// NonceRFC6979 generates a nonce deterministically according to RFC 6979 using +// HMAC-SHA256 for the hashing function. It takes a 32-byte hash as an input +// and returns a 32-byte nonce to be used for deterministic signing. The extra +// and version arguments are optional, but allow additional data to be added to +// the input of the HMAC. When provided, the extra data must be 32-bytes and +// version must be 16 bytes or they will be ignored. +// +// Finally, the extraIterations parameter provides a method to produce a stream +// of deterministic nonces to ensure the signing code is able to produce a nonce +// that results in a valid signature in the extremely unlikely event the +// original nonce produced results in an invalid signature (e.g. R == 0). +// Signing code should start with 0 and increment it if necessary. +func NonceRFC6979(privKey []byte, hash []byte, extra []byte, version []byte, + extraIterations uint32) *ModNScalar { + + return secp.NonceRFC6979(privKey, hash, extra, version, extraIterations) +} diff --git a/btcec/precompute.go b/btcec/precompute.go deleted file mode 100644 index 034cd55332..0000000000 --- a/btcec/precompute.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package btcec - -import ( - "compress/zlib" - "encoding/base64" - "encoding/binary" - "io/ioutil" - "strings" -) - -//go:generate go run -tags gensecp256k1 genprecomps.go - -// loadS256BytePoints decompresses and deserializes the pre-computed byte points -// used to accelerate scalar base multiplication for the secp256k1 curve. This -// approach is used since it allows the compile to use significantly less ram -// and be performed much faster than it is with hard-coding the final in-memory -// data structure. At the same time, it is quite fast to generate the in-memory -// data structure at init time with this approach versus computing the table. -func loadS256BytePoints() error { - // There will be no byte points to load when generating them. - bp := secp256k1BytePoints - if len(bp) == 0 { - return nil - } - - // Decompress the pre-computed table used to accelerate scalar base - // multiplication. - decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(bp)) - r, err := zlib.NewReader(decoder) - if err != nil { - return err - } - serialized, err := ioutil.ReadAll(r) - if err != nil { - return err - } - - // Deserialize the precomputed byte points and set the curve to them. - offset := 0 - var bytePoints [32][256][3]fieldVal - for byteNum := 0; byteNum < 32; byteNum++ { - // All points in this window. - for i := 0; i < 256; i++ { - px := &bytePoints[byteNum][i][0] - py := &bytePoints[byteNum][i][1] - pz := &bytePoints[byteNum][i][2] - for i := 0; i < 10; i++ { - px.n[i] = binary.LittleEndian.Uint32(serialized[offset:]) - offset += 4 - } - for i := 0; i < 10; i++ { - py.n[i] = binary.LittleEndian.Uint32(serialized[offset:]) - offset += 4 - } - for i := 0; i < 10; i++ { - pz.n[i] = binary.LittleEndian.Uint32(serialized[offset:]) - offset += 4 - } - } - } - secp256k1.bytePoints = &bytePoints - return nil -} diff --git a/btcec/privkey.go b/btcec/privkey.go index 676a8c3fb0..6f13990b1f 100644 --- a/btcec/privkey.go +++ b/btcec/privkey.go @@ -5,69 +5,27 @@ package btcec import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "math/big" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) // PrivateKey wraps an ecdsa.PrivateKey as a convenience mainly for signing // things with the the private key without having to directly import the ecdsa // package. -type PrivateKey ecdsa.PrivateKey +type PrivateKey = secp.PrivateKey // PrivKeyFromBytes returns a private and public key for `curve' based on the // private key passed as an argument as a byte slice. -func PrivKeyFromBytes(curve elliptic.Curve, pk []byte) (*PrivateKey, - *PublicKey) { - x, y := curve.ScalarBaseMult(pk) +func PrivKeyFromBytes(pk []byte) (*PrivateKey, *PublicKey) { + privKey := secp.PrivKeyFromBytes(pk) - priv := &ecdsa.PrivateKey{ - PublicKey: ecdsa.PublicKey{ - Curve: curve, - X: x, - Y: y, - }, - D: new(big.Int).SetBytes(pk), - } - - return (*PrivateKey)(priv), (*PublicKey)(&priv.PublicKey) + return privKey, privKey.PubKey() } // NewPrivateKey is a wrapper for ecdsa.GenerateKey that returns a PrivateKey // instead of the normal ecdsa.PrivateKey. -func NewPrivateKey(curve elliptic.Curve) (*PrivateKey, error) { - key, err := ecdsa.GenerateKey(curve, rand.Reader) - if err != nil { - return nil, err - } - return (*PrivateKey)(key), nil -} - -// PubKey returns the PublicKey corresponding to this private key. -func (p *PrivateKey) PubKey() *PublicKey { - return (*PublicKey)(&p.PublicKey) -} - -// ToECDSA returns the private key as a *ecdsa.PrivateKey. -func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey { - return (*ecdsa.PrivateKey)(p) -} - -// Sign generates an ECDSA signature for the provided hash (which should be the result -// of hashing a larger message) using the private key. Produced signature -// is deterministic (same message and same key yield the same signature) and canonical -// in accordance with RFC6979 and BIP0062. -func (p *PrivateKey) Sign(hash []byte) (*Signature, error) { - return signRFC6979(p, hash) +func NewPrivateKey() (*PrivateKey, error) { + return secp.GeneratePrivateKey() } // PrivKeyBytesLen defines the length in bytes of a serialized private key. const PrivKeyBytesLen = 32 - -// Serialize returns the private key number d as a big-endian binary-encoded -// number, padded to a length of 32 bytes. -func (p *PrivateKey) Serialize() []byte { - b := make([]byte, 0, PrivKeyBytesLen) - return paddedAppend(PrivKeyBytesLen, b, p.ToECDSA().D.Bytes()) -} diff --git a/btcec/privkey_test.go b/btcec/privkey_test.go index a2918dc191..71a8bceaa1 100644 --- a/btcec/privkey_test.go +++ b/btcec/privkey_test.go @@ -26,20 +26,16 @@ func TestPrivKeys(t *testing.T) { } for _, test := range tests { - priv, pub := PrivKeyFromBytes(S256(), test.key) + priv, pub := PrivKeyFromBytes(test.key) - _, err := ParsePubKey(pub.SerializeUncompressed(), S256()) + _, err := ParsePubKey(pub.SerializeUncompressed()) if err != nil { t.Errorf("%s privkey: %v", test.name, err) continue } hash := []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9} - sig, err := priv.Sign(hash) - if err != nil { - t.Errorf("%s could not sign: %v", test.name, err) - continue - } + sig := Sign(priv, hash) if !sig.Verify(hash, pub) { t.Errorf("%s could not verify: %v", test.name, err) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index 3c9d5d02d2..7968ed042a 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -5,59 +5,14 @@ package btcec import ( - "crypto/ecdsa" - "errors" - "fmt" - "math/big" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) // These constants define the lengths of serialized public keys. const ( - PubKeyBytesLenCompressed = 33 - PubKeyBytesLenUncompressed = 65 - PubKeyBytesLenHybrid = 65 + PubKeyBytesLenCompressed = 33 ) -func isOdd(a *big.Int) bool { - return a.Bit(0) == 1 -} - -// decompressPoint decompresses a point on the secp256k1 curve given the X point and -// the solution to use. -func decompressPoint(curve *KoblitzCurve, bigX *big.Int, ybit bool) (*big.Int, error) { - var x fieldVal - x.SetByteSlice(bigX.Bytes()) - - // Compute x^3 + B mod p. - var x3 fieldVal - x3.SquareVal(&x).Mul(&x) - x3.Add(curve.fieldB).Normalize() - - // Now calculate sqrt mod p of x^3 + B - // This code used to do a full sqrt based on tonelli/shanks, - // but this was replaced by the algorithms referenced in - // https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294 - var y fieldVal - y.SqrtVal(&x3).Normalize() - if ybit != y.IsOdd() { - y.Negate(1).Normalize() - } - - // Check that y is a square root of x^3 + B. - var y2 fieldVal - y2.SquareVal(&y).Normalize() - if !y2.Equals(&x3) { - return nil, fmt.Errorf("invalid square root") - } - - // Verify that y-coord has expected parity. - if ybit != y.IsOdd() { - return nil, fmt.Errorf("ybit doesn't match oddness") - } - - return new(big.Int).SetBytes(y.Bytes()[:]), nil -} - const ( pubkeyCompressed byte = 0x2 // y_bit + x coord pubkeyUncompressed byte = 0x4 // x coord + y coord @@ -76,119 +31,21 @@ func IsCompressedPubKey(pubKey []byte) bool { // ParsePubKey parses a public key for a koblitz curve from a bytestring into a // ecdsa.Publickey, verifying that it is valid. It supports compressed, // uncompressed and hybrid signature formats. -func ParsePubKey(pubKeyStr []byte, curve *KoblitzCurve) (key *PublicKey, err error) { - pubkey := PublicKey{} - pubkey.Curve = curve - - if len(pubKeyStr) == 0 { - return nil, errors.New("pubkey string is empty") - } - - format := pubKeyStr[0] - ybit := (format & 0x1) == 0x1 - format &= ^byte(0x1) - - switch len(pubKeyStr) { - case PubKeyBytesLenUncompressed: - if format != pubkeyUncompressed && format != pubkeyHybrid { - return nil, fmt.Errorf("invalid magic in pubkey str: "+ - "%d", pubKeyStr[0]) - } - - pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33]) - pubkey.Y = new(big.Int).SetBytes(pubKeyStr[33:]) - // hybrid keys have extra information, make use of it. - if format == pubkeyHybrid && ybit != isOdd(pubkey.Y) { - return nil, fmt.Errorf("ybit doesn't match oddness") - } - - if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 { - return nil, fmt.Errorf("pubkey X parameter is >= to P") - } - if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 { - return nil, fmt.Errorf("pubkey Y parameter is >= to P") - } - if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) { - return nil, fmt.Errorf("pubkey isn't on secp256k1 curve") - } - - case PubKeyBytesLenCompressed: - // format is 0x2 | solution, - // solution determines which solution of the curve we use. - /// y^2 = x^3 + Curve.B - if format != pubkeyCompressed { - return nil, fmt.Errorf("invalid magic in compressed "+ - "pubkey string: %d", pubKeyStr[0]) - } - pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33]) - pubkey.Y, err = decompressPoint(curve, pubkey.X, ybit) - if err != nil { - return nil, err - } - - default: // wrong! - return nil, fmt.Errorf("invalid pub key length %d", - len(pubKeyStr)) - } - - return &pubkey, nil +func ParsePubKey(pubKeyStr []byte) (*PublicKey, error) { + return secp.ParsePubKey(pubKeyStr) } // PublicKey is an ecdsa.PublicKey with additional functions to // serialize in uncompressed, compressed, and hybrid formats. -type PublicKey ecdsa.PublicKey - -// ToECDSA returns the public key as a *ecdsa.PublicKey. -func (p *PublicKey) ToECDSA() *ecdsa.PublicKey { - return (*ecdsa.PublicKey)(p) -} - -// SerializeUncompressed serializes a public key in a 65-byte uncompressed -// format. -func (p *PublicKey) SerializeUncompressed() []byte { - b := make([]byte, 0, PubKeyBytesLenUncompressed) - b = append(b, pubkeyUncompressed) - b = paddedAppend(32, b, p.X.Bytes()) - return paddedAppend(32, b, p.Y.Bytes()) -} - -// SerializeCompressed serializes a public key in a 33-byte compressed format. -func (p *PublicKey) SerializeCompressed() []byte { - b := make([]byte, 0, PubKeyBytesLenCompressed) - format := pubkeyCompressed - if isOdd(p.Y) { - format |= 0x1 - } - b = append(b, format) - return paddedAppend(32, b, p.X.Bytes()) -} - -// SerializeHybrid serializes a public key in a 65-byte hybrid format. -func (p *PublicKey) SerializeHybrid() []byte { - b := make([]byte, 0, PubKeyBytesLenHybrid) - format := pubkeyHybrid - if isOdd(p.Y) { - format |= 0x1 - } - b = append(b, format) - b = paddedAppend(32, b, p.X.Bytes()) - return paddedAppend(32, b, p.Y.Bytes()) -} - -// IsEqual compares this PublicKey instance to the one passed, returning true if -// both PublicKeys are equivalent. A PublicKey is equivalent to another, if they -// both have the same X and Y coordinate. -func (p *PublicKey) IsEqual(otherPubKey *PublicKey) bool { - return p.X.Cmp(otherPubKey.X) == 0 && - p.Y.Cmp(otherPubKey.Y) == 0 -} - -// paddedAppend appends the src byte slice to dst, returning the new slice. -// If the length of the source is smaller than the passed size, leading zero -// bytes are appended to the dst slice before appending src. -func paddedAppend(size uint, dst, src []byte) []byte { - for i := 0; i < int(size)-len(src); i++ { - dst = append(dst, 0) - } - return append(dst, src...) +type PublicKey = secp.PublicKey + +// NewPublicKey instantiates a new public key with the given x and y +// coordinates. +// +// It should be noted that, unlike ParsePubKey, since this accepts arbitrary x +// and y coordinates, it allows creation of public keys that are not valid +// points on the secp256k1 curve. The IsOnCurve method of the returned instance +// can be used to determine validity. +func NewPublicKey(x, y *FieldVal) *PublicKey { + return secp.NewPublicKey(x, y) } diff --git a/btcec/pubkey_test.go b/btcec/pubkey_test.go index 68b61de10b..7ee7cd8044 100644 --- a/btcec/pubkey_test.go +++ b/btcec/pubkey_test.go @@ -216,7 +216,7 @@ var pubKeyTests = []pubKeyTest{ func TestPubKeys(t *testing.T) { for _, test := range pubKeyTests { - pk, err := ParsePubKey(test.key, S256()) + pk, err := ParsePubKey(test.key) if err != nil { if test.isValid { t.Errorf("%s pubkey failed when shouldn't %v", @@ -236,7 +236,7 @@ func TestPubKeys(t *testing.T) { case pubkeyCompressed: pkStr = pk.SerializeCompressed() case pubkeyHybrid: - pkStr = pk.SerializeHybrid() + pkStr = test.key } if !bytes.Equal(test.key, pkStr) { t.Errorf("%s pubkey: serialized keys do not match.", @@ -254,7 +254,6 @@ func TestPublicKeyIsEqual(t *testing.T) { 0x25, 0x21, 0x88, 0x7e, 0x97, 0x66, 0x90, 0xb6, 0xb4, 0x7f, 0x5b, 0x2a, 0x4b, 0x7d, 0x44, 0x8e, }, - S256(), ) if err != nil { t.Fatalf("failed to parse raw bytes for pubKey1: %v", err) @@ -266,7 +265,6 @@ func TestPublicKeyIsEqual(t *testing.T) { 0x2e, 0x9c, 0x51, 0x0f, 0x8e, 0xf5, 0x2b, 0xd0, 0x21, 0xa9, 0xa1, 0xf4, 0x80, 0x9d, 0x3b, 0x4d, }, - S256(), ) if err != nil { t.Fatalf("failed to parse raw bytes for pubKey2: %v", err) diff --git a/btcec/secp256k1.go b/btcec/secp256k1.go deleted file mode 100644 index 1b1b8179e1..0000000000 --- a/btcec/secp256k1.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2015 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package btcec - -// Auto-generated file (see genprecomps.go) -// DO NOT EDIT - -var secp256k1BytePoints = "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" diff --git a/btcec/signature.go b/btcec/signature.go index 8a8f8301b7..ddeb4b052f 100644 --- a/btcec/signature.go +++ b/btcec/signature.go @@ -5,15 +5,11 @@ package btcec import ( - "bytes" - "crypto/ecdsa" - "crypto/elliptic" - "crypto/hmac" - "crypto/sha256" "errors" "fmt" - "hash" "math/big" + + secp_ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" ) // Errors returned by canonicalPadding. @@ -23,9 +19,11 @@ var ( ) // Signature is a type representing an ecdsa signature. -type Signature struct { - R *big.Int - S *big.Int +type Signature = secp_ecdsa.Signature + +// NewSignature instantiates a new signature given some r and s values. +func NewSignature(r, s *ModNScalar) *Signature { + return secp_ecdsa.NewSignature(r, s) } var ( @@ -37,60 +35,27 @@ var ( oneInitializer = []byte{0x01} ) -// Serialize returns the ECDSA signature in the more strict DER format. Note -// that the serialized bytes returned do not include the appended hash type -// used in Bitcoin signature scripts. -// -// encoding/asn1 is broken so we hand roll this output: -// -// 0x30 0x02 r 0x02 s -func (sig *Signature) Serialize() []byte { - // low 'S' malleability breaker - sigS := sig.S - if sigS.Cmp(S256().halfOrder) == 1 { - sigS = new(big.Int).Sub(S256().N, sigS) - } - // Ensure the encoded bytes for the r and s values are canonical and - // thus suitable for DER encoding. - rb := canonicalizeInt(sig.R) - sb := canonicalizeInt(sigS) - - // total length of returned signature is 1 byte for each magic and - // length (6 total), plus lengths of r and s - length := 6 + len(rb) + len(sb) - b := make([]byte, length) - - b[0] = 0x30 - b[1] = byte(length - 2) - b[2] = 0x02 - b[3] = byte(len(rb)) - offset := copy(b[4:], rb) + 4 - b[offset] = 0x02 - b[offset+1] = byte(len(sb)) - copy(b[offset+2:], sb) - return b -} - -// Verify calls ecdsa.Verify to verify the signature of hash using the public -// key. It returns true if the signature is valid, false otherwise. -func (sig *Signature) Verify(hash []byte, pubKey *PublicKey) bool { - return ecdsa.Verify(pubKey.ToECDSA(), hash, sig.R, sig.S) -} - -// IsEqual compares this Signature instance to the one passed, returning true -// if both Signatures are equivalent. A signature is equivalent to another, if -// they both have the same scalar value for R and S. -func (sig *Signature) IsEqual(otherSig *Signature) bool { - return sig.R.Cmp(otherSig.R) == 0 && - sig.S.Cmp(otherSig.S) == 0 -} - // MinSigLen is the minimum length of a DER encoded signature and is when both R // and S are 1 byte each. // 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + const MinSigLen = 8 -func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) { +// canonicalPadding checks whether a big-endian encoded integer could +// possibly be misinterpreted as a negative number (even though OpenSSL +// treats all numbers as unsigned), or if there is any unnecessary +// leading zero padding. +func canonicalPadding(b []byte) error { + switch { + case b[0]&0x80 == 0x80: + return errNegativeValue + case len(b) > 1 && b[0] == 0x00 && b[1]&0x80 != 0x80: + return errExcessivelyPaddedValue + default: + return nil + } +} + +func parseSig(sigStr []byte, der bool) (*Signature, error) { // Originally this code used encoding/asn1 in order to parse the // signature, but a number of problems were found with this approach. // Despite the fact that signatures are stored as DER, the difference @@ -101,8 +66,6 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) // 0x30 <0x02> 0x2 // . - signature := &Signature{} - if len(sigStr) < MinSigLen { return nil, errors.New("malformed signature: too short") } @@ -150,7 +113,28 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) return nil, errors.New("signature R is excessively padded") } } - signature.R = new(big.Int).SetBytes(rBytes) + + // Strip leading zeroes from R. + for len(rBytes) > 0 && rBytes[0] == 0x00 { + rBytes = rBytes[1:] + } + + // R must be in the range [1, N-1]. Notice the check for the maximum number + // of bytes is required because SetByteSlice truncates as noted in its + // comment so it could otherwise fail to detect the overflow. + var r ModNScalar + if len(rBytes) > 32 { + str := "invalid signature: R is larger than 256 bits" + return nil, errors.New(str) + } + if overflow := r.SetByteSlice(rBytes); overflow { + str := "invalid signature: R >= group order" + return nil, errors.New(str) + } + if r.IsZero() { + str := "invalid signature: R is 0" + return nil, errors.New(str) + } index += rLen // 0x02. length already checked in previous if. if sigStr[index] != 0x02 { @@ -176,192 +160,51 @@ func parseSig(sigStr []byte, curve elliptic.Curve, der bool) (*Signature, error) return nil, errors.New("signature S is excessively padded") } } - signature.S = new(big.Int).SetBytes(sBytes) - index += sLen - // sanity check length parsing - if index != len(sigStr) { - return nil, fmt.Errorf("malformed signature: bad final length %v != %v", - index, len(sigStr)) + // Strip leading zeroes from S. + for len(sBytes) > 0 && sBytes[0] == 0x00 { + sBytes = sBytes[1:] } - // Verify also checks this, but we can be more sure that we parsed - // correctly if we verify here too. - // FWIW the ecdsa spec states that R and S must be | 1, N - 1 | - // but crypto/ecdsa only checks for Sign != 0. Mirror that. - if signature.R.Sign() != 1 { - return nil, errors.New("signature R isn't 1 or more") + // S must be in the range [1, N-1]. Notice the check for the maximum number + // of bytes is required because SetByteSlice truncates as noted in its + // comment so it could otherwise fail to detect the overflow. + var s ModNScalar + if len(sBytes) > 32 { + str := "invalid signature: S is larger than 256 bits" + return nil, errors.New(str) } - if signature.S.Sign() != 1 { - return nil, errors.New("signature S isn't 1 or more") + if overflow := s.SetByteSlice(sBytes); overflow { + str := "invalid signature: S >= group order" + return nil, errors.New(str) } - if signature.R.Cmp(curve.Params().N) >= 0 { - return nil, errors.New("signature R is >= curve.N") + if s.IsZero() { + str := "invalid signature: S is 0" + return nil, errors.New(str) } - if signature.S.Cmp(curve.Params().N) >= 0 { - return nil, errors.New("signature S is >= curve.N") + index += sLen + + // sanity check length parsing + if index != len(sigStr) { + return nil, fmt.Errorf("malformed signature: bad final length %v != %v", + index, len(sigStr)) } - return signature, nil + return NewSignature(&r, &s), nil } // ParseSignature parses a signature in BER format for the curve type `curve' // into a Signature type, perfoming some basic sanity checks. If parsing // according to the more strict DER format is needed, use ParseDERSignature. -func ParseSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) { - return parseSig(sigStr, curve, false) +func ParseSignature(sigStr []byte) (*Signature, error) { + return parseSig(sigStr, false) } // ParseDERSignature parses a signature in DER format for the curve type // `curve` into a Signature type. If parsing according to the less strict // BER format is needed, use ParseSignature. -func ParseDERSignature(sigStr []byte, curve elliptic.Curve) (*Signature, error) { - return parseSig(sigStr, curve, true) -} - -// canonicalizeInt returns the bytes for the passed big integer adjusted as -// necessary to ensure that a big-endian encoded integer can't possibly be -// misinterpreted as a negative number. This can happen when the most -// significant bit is set, so it is padded by a leading zero byte in this case. -// Also, the returned bytes will have at least a single byte when the passed -// value is 0. This is required for DER encoding. -func canonicalizeInt(val *big.Int) []byte { - b := val.Bytes() - if len(b) == 0 { - b = []byte{0x00} - } - if b[0]&0x80 != 0 { - paddedBytes := make([]byte, len(b)+1) - copy(paddedBytes[1:], b) - b = paddedBytes - } - return b -} - -// canonicalPadding checks whether a big-endian encoded integer could -// possibly be misinterpreted as a negative number (even though OpenSSL -// treats all numbers as unsigned), or if there is any unnecessary -// leading zero padding. -func canonicalPadding(b []byte) error { - switch { - case b[0]&0x80 == 0x80: - return errNegativeValue - case len(b) > 1 && b[0] == 0x00 && b[1]&0x80 != 0x80: - return errExcessivelyPaddedValue - default: - return nil - } -} - -// hashToInt converts a hash value to an integer. There is some disagreement -// about how this is done. [NSA] suggests that this is done in the obvious -// manner, but [SECG] truncates the hash to the bit-length of the curve order -// first. We follow [SECG] because that's what OpenSSL does. Additionally, -// OpenSSL right shifts excess bits from the number if the hash is too large -// and we mirror that too. -// This is borrowed from crypto/ecdsa. -func hashToInt(hash []byte, c elliptic.Curve) *big.Int { - orderBits := c.Params().N.BitLen() - orderBytes := (orderBits + 7) / 8 - if len(hash) > orderBytes { - hash = hash[:orderBytes] - } - - ret := new(big.Int).SetBytes(hash) - excess := len(hash)*8 - orderBits - if excess > 0 { - ret.Rsh(ret, uint(excess)) - } - return ret -} - -// recoverKeyFromSignature recovers a public key from the signature "sig" on the -// given message hash "msg". Based on the algorithm found in section 4.1.6 of -// SEC 1 Ver 2.0, page 47-48 (53 and 54 in the pdf). This performs the details -// in the inner loop in Step 1. The counter provided is actually the j parameter -// of the loop * 2 - on the first iteration of j we do the R case, else the -R -// case in step 1.6. This counter is used in the bitcoin compressed signature -// format and thus we match bitcoind's behaviour here. -func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte, - iter int, doChecks bool) (*PublicKey, error) { - // Parse and validate the R and S signature components. - // - // Fail if r and s are not in [1, N-1]. - if sig.R.Cmp(curve.Params().N) != -1 { - return nil, errors.New("signature R is >= curve order") - } - - if sig.R.Sign() == 0 { - return nil, errors.New("signature R is 0") - } - - if sig.S.Cmp(curve.Params().N) != -1 { - return nil, errors.New("signature S is >= curve order") - } - - if sig.S.Sign() == 0 { - return nil, errors.New("signature S is 0") - } - - // 1.1 x = (n * i) + r - Rx := new(big.Int).Mul(curve.Params().N, - new(big.Int).SetInt64(int64(iter/2))) - Rx.Add(Rx, sig.R) - if Rx.Cmp(curve.Params().P) != -1 { - return nil, errors.New("calculated Rx is larger than curve P") - } - - // convert 02 to point R. (step 1.2 and 1.3). If we are on an odd - // iteration then 1.6 will be done with -R, so we calculate the other - // term when uncompressing the point. - Ry, err := decompressPoint(curve, Rx, iter%2 == 1) - if err != nil { - return nil, err - } - - // 1.4 Check n*R is point at infinity - if doChecks { - nRx, nRy := curve.ScalarMult(Rx, Ry, curve.Params().N.Bytes()) - if nRx.Sign() != 0 || nRy.Sign() != 0 { - return nil, errors.New("n*R does not equal the point at infinity") - } - } - - // 1.5 calculate e from message using the same algorithm as ecdsa - // signature calculation. - e := hashToInt(msg, curve) - - // Step 1.6.1: - // We calculate the two terms sR and eG separately multiplied by the - // inverse of r (from the signature). We then add them to calculate - // Q = r^-1(sR-eG) - invr := new(big.Int).ModInverse(sig.R, curve.Params().N) - - // first term. - invrS := new(big.Int).Mul(invr, sig.S) - invrS.Mod(invrS, curve.Params().N) - sRx, sRy := curve.ScalarMult(Rx, Ry, invrS.Bytes()) - - // second term. - e.Neg(e) - e.Mod(e, curve.Params().N) - e.Mul(e, invr) - e.Mod(e, curve.Params().N) - minuseGx, minuseGy := curve.ScalarBaseMult(e.Bytes()) - - // TODO: this would be faster if we did a mult and add in one - // step to prevent the jacobian conversion back and forth. - Qx, Qy := curve.Add(sRx, sRy, minuseGx, minuseGy) - - if Qx.Sign() == 0 && Qy.Sign() == 0 { - return nil, errors.New("point (Qx, Qy) equals the point at infinity") - } - - return &PublicKey{ - Curve: curve, - X: Qx, - Y: Qy, - }, nil +func ParseDERSignature(sigStr []byte) (*Signature, error) { + return parseSig(sigStr, true) } // SignCompact produces a compact signature of the data in hash with the given @@ -371,193 +214,25 @@ func recoverKeyFromSignature(curve *KoblitzCurve, sig *Signature, msg []byte, // returned in the format: // <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R> // where the R and S parameters are padde up to the bitlengh of the curve. -func SignCompact(curve *KoblitzCurve, key *PrivateKey, - hash []byte, isCompressedKey bool) ([]byte, error) { - sig, err := key.Sign(hash) - if err != nil { - return nil, err - } +func SignCompact(key *PrivateKey, hash []byte, + isCompressedKey bool) ([]byte, error) { - // bitcoind checks the bit length of R and S here. The ecdsa signature - // algorithm returns R and S mod N therefore they will be the bitsize of - // the curve, and thus correctly sized. - for i := 0; i < (curve.H+1)*2; i++ { - pk, err := recoverKeyFromSignature(curve, sig, hash, i, true) - if err == nil && pk.X.Cmp(key.X) == 0 && pk.Y.Cmp(key.Y) == 0 { - result := make([]byte, 1, 2*curve.byteSize+1) - result[0] = 27 + byte(i) - if isCompressedKey { - result[0] += 4 - } - // Not sure this needs rounding but safer to do so. - curvelen := (curve.BitSize + 7) / 8 - - // Pad R and S to curvelen if needed. - bytelen := (sig.R.BitLen() + 7) / 8 - if bytelen < curvelen { - result = append(result, - make([]byte, curvelen-bytelen)...) - } - result = append(result, sig.R.Bytes()...) - - bytelen = (sig.S.BitLen() + 7) / 8 - if bytelen < curvelen { - result = append(result, - make([]byte, curvelen-bytelen)...) - } - result = append(result, sig.S.Bytes()...) - - return result, nil - } - } - - return nil, errors.New("no valid solution for pubkey found") + return secp_ecdsa.SignCompact(key, hash, isCompressedKey), nil } // RecoverCompact verifies the compact signature "signature" of "hash" for the // Koblitz curve in "curve". If the signature matches then the recovered public // key will be returned as well as a boolean if the original key was compressed // or not, else an error will be returned. -func RecoverCompact(curve *KoblitzCurve, signature, - hash []byte) (*PublicKey, bool, error) { - bitlen := (curve.BitSize + 7) / 8 - if len(signature) != 1+bitlen*2 { - return nil, false, errors.New("invalid compact signature size") - } - - iteration := int((signature[0] - 27) & ^byte(4)) - - // format is
- sig := &Signature{ - R: new(big.Int).SetBytes(signature[1 : bitlen+1]), - S: new(big.Int).SetBytes(signature[bitlen+1:]), - } - // The iteration used here was encoded - key, err := recoverKeyFromSignature(curve, sig, hash, iteration, false) - if err != nil { - return nil, false, err - } - - return key, ((signature[0] - 27) & 4) == 4, nil +func RecoverCompact(signature, hash []byte) (*PublicKey, bool, error) { + return secp_ecdsa.RecoverCompact(signature, hash) } -// signRFC6979 generates a deterministic ECDSA signature according to RFC 6979 and BIP 62. -func signRFC6979(privateKey *PrivateKey, hash []byte) (*Signature, error) { - - privkey := privateKey.ToECDSA() - N := S256().N - halfOrder := S256().halfOrder - k := nonceRFC6979(privkey.D, hash) - inv := new(big.Int).ModInverse(k, N) - r, _ := privkey.Curve.ScalarBaseMult(k.Bytes()) - r.Mod(r, N) - - if r.Sign() == 0 { - return nil, errors.New("calculated R is zero") - } - - e := hashToInt(hash, privkey.Curve) - s := new(big.Int).Mul(privkey.D, r) - s.Add(s, e) - s.Mul(s, inv) - s.Mod(s, N) - - if s.Cmp(halfOrder) == 1 { - s.Sub(N, s) - } - if s.Sign() == 0 { - return nil, errors.New("calculated S is zero") - } - return &Signature{R: r, S: s}, nil -} - -// nonceRFC6979 generates an ECDSA nonce (`k`) deterministically according to RFC 6979. -// It takes a 32-byte hash as an input and returns 32-byte nonce to be used in ECDSA algorithm. -func nonceRFC6979(privkey *big.Int, hash []byte) *big.Int { - - curve := S256() - q := curve.Params().N - x := privkey - alg := sha256.New - - qlen := q.BitLen() - holen := alg().Size() - rolen := (qlen + 7) >> 3 - bx := append(int2octets(x, rolen), bits2octets(hash, curve, rolen)...) - - // Step B - v := bytes.Repeat(oneInitializer, holen) - - // Step C (Go zeroes the all allocated memory) - k := make([]byte, holen) - - // Step D - k = mac(alg, k, append(append(v, 0x00), bx...)) - - // Step E - v = mac(alg, k, v) - - // Step F - k = mac(alg, k, append(append(v, 0x01), bx...)) - - // Step G - v = mac(alg, k, v) - - // Step H - for { - // Step H1 - var t []byte - - // Step H2 - for len(t)*8 < qlen { - v = mac(alg, k, v) - t = append(t, v...) - } - - // Step H3 - secret := hashToInt(t, curve) - if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 { - return secret - } - k = mac(alg, k, append(v, 0x00)) - v = mac(alg, k, v) - } -} - -// mac returns an HMAC of the given key and message. -func mac(alg func() hash.Hash, k, m []byte) []byte { - h := hmac.New(alg, k) - h.Write(m) - return h.Sum(nil) -} - -// https://tools.ietf.org/html/rfc6979#section-2.3.3 -func int2octets(v *big.Int, rolen int) []byte { - out := v.Bytes() - - // left pad with zeros if it's too short - if len(out) < rolen { - out2 := make([]byte, rolen) - copy(out2[rolen-len(out):], out) - return out2 - } - - // drop most significant bytes if it's too long - if len(out) > rolen { - out2 := make([]byte, rolen) - copy(out2, out[len(out)-rolen:]) - return out2 - } - - return out -} - -// https://tools.ietf.org/html/rfc6979#section-2.3.4 -func bits2octets(in []byte, curve elliptic.Curve, rolen int) []byte { - z1 := hashToInt(in, curve) - z2 := new(big.Int).Sub(z1, curve.Params().N) - if z2.Sign() < 0 { - return int2octets(z1, rolen) - } - return int2octets(z2, rolen) +// Sign generates an ECDSA signature over the secp256k1 curve for the provided +// hash (which should be the result of hashing a larger message) using the +// given private key. The produced signature is deterministic (same message and +// same key yield the same signature) and canonical in accordance with RFC6979 +// and BIP0062. +func Sign(key *PrivateKey, hash []byte) *Signature { + return secp_ecdsa.Sign(key, hash) } diff --git a/btcec/signature_test.go b/btcec/signature_test.go index b58d186775..74ea374784 100644 --- a/btcec/signature_test.go +++ b/btcec/signature_test.go @@ -10,7 +10,6 @@ import ( "crypto/sha256" "encoding/hex" "fmt" - "math/big" "reflect" "testing" ) @@ -337,9 +336,9 @@ func TestSignatures(t *testing.T) { for _, test := range signatureTests { var err error if test.der { - _, err = ParseDERSignature(test.sig, S256()) + _, err = ParseDERSignature(test.sig) } else { - _, err = ParseSignature(test.sig, S256()) + _, err = ParseSignature(test.sig) } if err != nil { if test.isValid { @@ -368,10 +367,10 @@ func TestSignatureSerialize(t *testing.T) { // 0437cd7f8525ceed2324359c2d0ba26006d92d85 { "valid 1 - r and s most significant bits are zero", - &Signature{ - R: fromHex("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"), - S: fromHex("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"), - }, + NewSignature( + hexToModNScalar("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"), + hexToModNScalar("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"), + ), []byte{ 0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, @@ -388,51 +387,51 @@ func TestSignatureSerialize(t *testing.T) { // cb00f8a0573b18faa8c4f467b049f5d202bf1101d9ef2633bc611be70376a4b4 { "valid 2 - r most significant bit is one", - &Signature{ - R: fromHex("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"), - S: fromHex("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"), - }, + NewSignature( + hexToModNScalar("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"), + hexToModNScalar("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"), + ), []byte{ - 0x30, 0x45, 0x02, 0x21, 0x00, 0x82, 0x23, 0x5e, + 0x30, 0x44, 0x02, 0x20, 0x00, 0x82, 0x23, 0x5e, 0x21, 0xa2, 0x30, 0x00, 0x22, 0x73, 0x8d, 0xab, 0xb8, 0xe1, 0xbb, 0xd9, 0xd1, 0x9c, 0xfb, 0x1e, 0x7a, 0xb8, 0xc3, 0x0a, 0x23, 0xb0, 0xaf, 0xbb, - 0x8d, 0x17, 0x8a, 0xbc, 0xf3, 0x02, 0x20, 0x24, - 0xbf, 0x68, 0xe2, 0x56, 0xc5, 0x34, 0xdd, 0xfa, - 0xf9, 0x66, 0xbf, 0x90, 0x8d, 0xeb, 0x94, 0x43, - 0x05, 0x59, 0x6f, 0x7b, 0xdc, 0xc3, 0x8d, 0x69, - 0xac, 0xad, 0x7f, 0x9c, 0x86, 0x87, 0x24, + 0x8d, 0x17, 0x8a, 0xbc, 0x02, 0x20, 0x24, 0xbf, + 0x68, 0xe2, 0x56, 0xc5, 0x34, 0xdd, 0xfa, 0xf9, + 0x66, 0xbf, 0x90, 0x8d, 0xeb, 0x94, 0x43, 0x05, + 0x59, 0x6f, 0x7b, 0xdc, 0xc3, 0x8d, 0x69, 0xac, + 0xad, 0x7f, 0x9c, 0x86, 0x87, 0x24, }, }, // signature from bitcoin blockchain tx // fda204502a3345e08afd6af27377c052e77f1fefeaeb31bdd45f1e1237ca5470 { "valid 3 - s most significant bit is one", - &Signature{ - R: fromHex("1cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71"), - S: new(big.Int).Add(fromHex("00c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"), S256().N), - }, + NewSignature( + hexToModNScalar("1cadddc2838598fee7dc35a12b340c6bde8b389f7bfd19a1252a17c4b5ed2d71"), + hexToModNScalar("c1a251bbecb14b058a8bd77f65de87e51c47e95904f4c0e9d52eddc21c1415ac"), + ), []byte{ - 0x30, 0x45, 0x02, 0x20, 0x1c, 0xad, 0xdd, 0xc2, + 0x30, 0x44, 0x2, 0x20, 0x1c, 0xad, 0xdd, 0xc2, 0x83, 0x85, 0x98, 0xfe, 0xe7, 0xdc, 0x35, 0xa1, - 0x2b, 0x34, 0x0c, 0x6b, 0xde, 0x8b, 0x38, 0x9f, + 0x2b, 0x34, 0xc, 0x6b, 0xde, 0x8b, 0x38, 0x9f, 0x7b, 0xfd, 0x19, 0xa1, 0x25, 0x2a, 0x17, 0xc4, - 0xb5, 0xed, 0x2d, 0x71, 0x02, 0x21, 0x00, 0xc1, - 0xa2, 0x51, 0xbb, 0xec, 0xb1, 0x4b, 0x05, 0x8a, - 0x8b, 0xd7, 0x7f, 0x65, 0xde, 0x87, 0xe5, 0x1c, - 0x47, 0xe9, 0x59, 0x04, 0xf4, 0xc0, 0xe9, 0xd5, - 0x2e, 0xdd, 0xc2, 0x1c, 0x14, 0x15, 0xac, + 0xb5, 0xed, 0x2d, 0x71, 0x2, 0x20, 0x3e, 0x5d, + 0xae, 0x44, 0x13, 0x4e, 0xb4, 0xfa, 0x75, 0x74, + 0x28, 0x80, 0x9a, 0x21, 0x78, 0x19, 0x9e, 0x66, + 0xf3, 0x8d, 0xaa, 0x53, 0xdf, 0x51, 0xea, 0xa3, + 0x80, 0xca, 0xb4, 0x22, 0x2b, 0x95, }, }, { "valid 4 - s is bigger than half order", - &Signature{ - R: fromHex("a196ed0e7ebcbe7b63fe1d8eecbdbde03a67ceba4fc8f6482bdcb9606a911404"), - S: fromHex("971729c7fa944b465b35250c6570a2f31acbb14b13d1565fab7330dcb2b3dfb1"), - }, + NewSignature( + hexToModNScalar("a196ed0e7ebcbe7b63fe1d8eecbdbde03a67ceba4fc8f6482bdcb9606a911404"), + hexToModNScalar("971729c7fa944b465b35250c6570a2f31acbb14b13d1565fab7330dcb2b3dfb1"), + ), []byte{ 0x30, 0x45, 0x02, 0x21, 0x00, 0xa1, 0x96, 0xed, - 0x0e, 0x7e, 0xbc, 0xbe, 0x7b, 0x63, 0xfe, 0x1d, + 0xe, 0x7e, 0xbc, 0xbe, 0x7b, 0x63, 0xfe, 0x1d, 0x8e, 0xec, 0xbd, 0xbd, 0xe0, 0x3a, 0x67, 0xce, 0xba, 0x4f, 0xc8, 0xf6, 0x48, 0x2b, 0xdc, 0xb9, 0x60, 0x6a, 0x91, 0x14, 0x04, 0x02, 0x20, 0x68, @@ -444,10 +443,7 @@ func TestSignatureSerialize(t *testing.T) { }, { "zero signature", - &Signature{ - R: big.NewInt(0), - S: big.NewInt(0), - }, + NewSignature(&ModNScalar{}, &ModNScalar{}), []byte{0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00}, }, } @@ -464,23 +460,24 @@ func TestSignatureSerialize(t *testing.T) { func testSignCompact(t *testing.T, tag string, curve *KoblitzCurve, data []byte, isCompressed bool) { - priv, _ := NewPrivateKey(curve) + priv, _ := NewPrivateKey() hashed := []byte("testing") - sig, err := SignCompact(curve, priv, hashed, isCompressed) + sig, err := SignCompact(priv, hashed, isCompressed) if err != nil { t.Errorf("%s: error signing: %s", tag, err) return } - pk, wasCompressed, err := RecoverCompact(curve, sig, hashed) + pk, wasCompressed, err := RecoverCompact(sig, hashed) if err != nil { t.Errorf("%s: error recovering: %s", tag, err) return } - if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 { + if pk.X().Cmp(priv.PubKey().X()) != 0 || pk.Y().Cmp(priv.PubKey().Y()) != 0 { t.Errorf("%s: recovered pubkey doesn't match original "+ - "(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y) + "(%v,%v) vs (%v,%v) ", tag, pk.X(), pk.Y(), + priv.PubKey().X(), priv.PubKey().Y()) return } if wasCompressed != isCompressed { @@ -497,14 +494,15 @@ func testSignCompact(t *testing.T, tag string, curve *KoblitzCurve, sig[0] += 4 } - pk, wasCompressed, err = RecoverCompact(curve, sig, hashed) + pk, wasCompressed, err = RecoverCompact(sig, hashed) if err != nil { t.Errorf("%s: error recovering (2): %s", tag, err) return } - if pk.X.Cmp(priv.X) != 0 || pk.Y.Cmp(priv.Y) != 0 { + if pk.X().Cmp(priv.PubKey().X()) != 0 || pk.Y().Cmp(priv.PubKey().Y()) != 0 { t.Errorf("%s: recovered pubkey (2) doesn't match original "+ - "(%v,%v) vs (%v,%v) ", tag, pk.X, pk.Y, priv.X, priv.Y) + "(%v,%v) vs (%v,%v) ", tag, pk.X(), pk.Y(), + priv.PubKey().X(), priv.PubKey().Y()) return } if wasCompressed == isCompressed { @@ -547,13 +545,13 @@ var recoveryTests = []struct { // Invalid curve point recovered. msg: "00c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c", sig: "0100b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f00b940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549", - err: fmt.Errorf("invalid square root"), + err: fmt.Errorf("signature is not for a valid curve point"), }, { // Point at infinity recovered msg: "6b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9", sig: "0079be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817986b8d2c81b11b2d699528dde488dbdf2f94293d0d33c32e347f255fa4a6c1f0a9", - err: fmt.Errorf("point (Qx, Qy) equals the point at infinity"), + err: fmt.Errorf("recovered pubkey is the point at infinity"), }, { // Low R and S values. @@ -567,7 +565,7 @@ var recoveryTests = []struct { // Test case contributed by Ethereum Swarm: GH-1651 msg: "3060d2c77c1e192d62ad712fb400e04e6f779914a6876328ff3b213fa85d2012", sig: "65000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037a3", - err: fmt.Errorf("signature R is 0"), + err: fmt.Errorf("invalid compact signature recovery code"), }, { // Zero R value @@ -581,7 +579,7 @@ var recoveryTests = []struct { // R = N (curve order of secp256k1) msg: "2bcebac60d8a78e520ae81c2ad586792df495ed429bd730dcd897b301932d054", sig: "65fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036414100000000000000000000000000000000000000000000000000000000000037a3", - err: fmt.Errorf("signature R is >= curve order"), + err: fmt.Errorf("invalid compact signature recovery code"), }, { // Zero S value @@ -605,7 +603,7 @@ func TestRecoverCompact(t *testing.T) { // Magic DER constant. sig[0] += 27 - pub, _, err := RecoverCompact(S256(), sig, msg) + pub, _, err := RecoverCompact(sig, msg) // Verify that returned error matches as expected. if !reflect.DeepEqual(test.err, err) { @@ -622,7 +620,7 @@ func TestRecoverCompact(t *testing.T) { } // Otherwise, ensure the correct public key was recovered. - exPub, _ := ParsePubKey(decodeHex(test.pub), S256()) + exPub, _ := ParsePubKey(decodeHex(test.pub)) if !exPub.IsEqual(pub) { t.Errorf("unexpected recovered public key #%d: "+ "want %v, got %v", i, exPub, pub) @@ -681,13 +679,13 @@ func TestRFC6979(t *testing.T) { } for i, test := range tests { - privKey, _ := PrivKeyFromBytes(S256(), decodeHex(test.key)) + privKey, _ := PrivKeyFromBytes(decodeHex(test.key)) hash := sha256.Sum256([]byte(test.msg)) // Ensure deterministically generated nonce is the expected value. - gotNonce := nonceRFC6979(privKey.D, hash[:]).Bytes() + gotNonce := NonceRFC6979(privKey.Serialize(), hash[:], nil, nil, 0).Bytes() wantNonce := decodeHex(test.nonce) - if !bytes.Equal(gotNonce, wantNonce) { + if !bytes.Equal(gotNonce[:], wantNonce) { t.Errorf("NonceRFC6979 #%d (%s): Nonce is incorrect: "+ "%x (expected %x)", i, test.msg, gotNonce, wantNonce) @@ -695,12 +693,8 @@ func TestRFC6979(t *testing.T) { } // Ensure deterministically generated signature is the expected value. - gotSig, err := privKey.Sign(hash[:]) - if err != nil { - t.Errorf("Sign #%d (%s): unexpected error: %v", i, - test.msg, err) - continue - } + gotSig := Sign(privKey, hash[:]) + gotSigBytes := gotSig.Serialize() wantSigBytes := decodeHex(test.signature) if !bytes.Equal(gotSigBytes, wantSigBytes) { @@ -713,14 +707,14 @@ func TestRFC6979(t *testing.T) { } func TestSignatureIsEqual(t *testing.T) { - sig1 := &Signature{ - R: fromHex("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"), - S: fromHex("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"), - } - sig2 := &Signature{ - R: fromHex("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"), - S: fromHex("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"), - } + sig1 := NewSignature( + hexToModNScalar("0082235e21a2300022738dabb8e1bbd9d19cfb1e7ab8c30a23b0afbb8d178abcf3"), + hexToModNScalar("24bf68e256c534ddfaf966bf908deb944305596f7bdcc38d69acad7f9c868724"), + ) + sig2 := NewSignature( + hexToModNScalar("4e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd41"), + hexToModNScalar("181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d09"), + ) if !sig1.IsEqual(sig1) { t.Fatalf("value of IsEqual is incorrect, %v is "+ From eee3c3b33760da307d3d9d77a8ed4c2778ea57eb Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 18 Nov 2021 18:43:53 -0800 Subject: [PATCH 0593/1056] multi: switch project over to using btcec/v2 --- .github/workflows/go.yml | 5 + .gitignore | 4 + Makefile | 7 +- blockchain/compress.go | 8 +- blockchain/fullblocktests/generate.go | 4 +- btcec/go.mod | 2 +- btcec/go.sum | 47 ++++++++-- btcutil/address.go | 15 +-- btcutil/address_test.go | 118 +----------------------- btcutil/go.mod | 4 + btcutil/go.sum | 48 +--------- btcutil/hdkeychain/extendedkey.go | 103 +++++++++++++++------ btcutil/hdkeychain/extendedkey_test.go | 11 ++- btcutil/internal_test.go | 4 +- btcutil/psbt/go.mod | 4 + btcutil/psbt/go.sum | 48 +--------- btcutil/psbt/partialsig.go | 6 +- btcutil/wif.go | 22 +---- btcutil/wif_test.go | 8 +- go.mod | 4 + go.sum | 4 + integration/csv_fork_test.go | 5 +- integration/rpcserver_test.go | 1 + integration/rpctest/memwallet.go | 11 ++- integration/rpctest/rpc_harness_test.go | 1 + mempool/mempool_test.go | 4 +- mempool/policy_test.go | 4 +- rpcserver.go | 6 +- txscript/engine.go | 2 +- txscript/example_test.go | 4 +- txscript/opcode.go | 16 ++-- txscript/pkscript.go | 2 +- txscript/sigcache.go | 2 +- txscript/sigcache_test.go | 31 ++++--- txscript/sign.go | 21 ++--- txscript/sign_test.go | 114 +++++++++-------------- 36 files changed, 286 insertions(+), 414 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index b015b3c175..aeca7e58be 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -43,6 +43,11 @@ jobs: with: path-to-profile: coverage.txt + - name: Send btcec + uses: shogo82148/actions-goveralls@v1 + with: + path-to-profile: btcec/coverage.txt + - name: Send btcutil coverage uses: shogo82148/actions-goveralls@v1 with: diff --git a/.gitignore b/.gitignore index c3effe5fc7..a92c3ab39d 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,7 @@ _testmain.go # Code coverage files profile.tmp profile.cov +coverage.txt +btcec/coverage.txt +btcutil/coverage.txt +btcutil/psbt/coverage.txt diff --git a/Makefile b/Makefile index 6dc6d9471b..dd34608df6 100644 --- a/Makefile +++ b/Makefile @@ -79,19 +79,22 @@ check: unit unit: @$(call print, "Running unit tests.") - $(GOTEST_DEV) ./... -test.timeout=20m + $(GOTEST) ./... -test.timeout=20m + cd btcec; $(GOTEST_DEV) ./... -test.timeout=20m cd btcutil; $(GOTEST_DEV) ./... -test.timeout=20m cd btcutil/psbt; $(GOTEST_DEV) ./... -test.timeout=20m unit-cover: $(GOACC_BIN) @$(call print, "Running unit coverage tests.") $(GOACC_BIN) ./... + cd btcec; $(GOACC_BIN) ./... cd btcutil; $(GOACC_BIN) ./... cd btcutil/psbt; $(GOACC_BIN) ./... unit-race: @$(call print, "Running unit race tests.") env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... + cd btcec; env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... cd btcutil; env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... cd btcutil/psbt; env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... @@ -111,7 +114,7 @@ lint: $(LINT_BIN) clean: @$(call print, "Cleaning source.$(NC)") - $(RM) coverage.txt btcutil/coverage.txt btcutil/psbt/coverage.txt + $(RM) coverage.txt btcec/coverage.txt btcutil/coverage.txt btcutil/psbt/coverage.txt .PHONY: all \ default \ diff --git a/blockchain/compress.go b/blockchain/compress.go index 611b9f0992..4495918558 100644 --- a/blockchain/compress.go +++ b/blockchain/compress.go @@ -5,7 +5,7 @@ package blockchain import ( - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/txscript" ) @@ -218,7 +218,7 @@ func isPubKey(script []byte) (bool, []byte) { // Ensure the public key is valid. serializedPubKey := script[1:34] - _, err := btcec.ParsePubKey(serializedPubKey, btcec.S256()) + _, err := btcec.ParsePubKey(serializedPubKey) if err == nil { return true, serializedPubKey } @@ -230,7 +230,7 @@ func isPubKey(script []byte) (bool, []byte) { // Ensure the public key is valid. serializedPubKey := script[1:66] - _, err := btcec.ParsePubKey(serializedPubKey, btcec.S256()) + _, err := btcec.ParsePubKey(serializedPubKey) if err == nil { return true, serializedPubKey } @@ -399,7 +399,7 @@ func decompressScript(compressedPkScript []byte) []byte { compressedKey := make([]byte, 33) compressedKey[0] = byte(encodedScriptSize - 2) copy(compressedKey[1:], compressedPkScript[1:]) - key, err := btcec.ParsePubKey(compressedKey, btcec.S256()) + key, err := btcec.ParsePubKey(compressedKey) if err != nil { return nil } diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 9555116842..964986dbcf 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -19,7 +19,7 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" @@ -198,7 +198,7 @@ type testGenerator struct { // makeTestGenerator returns a test generator instance initialized with the // genesis block as the tip. func makeTestGenerator(params *chaincfg.Params) (testGenerator, error) { - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), []byte{0x01}) + privKey, _ := btcec.PrivKeyFromBytes([]byte{0x01}) genesis := params.GenesisBlock genesisHash := genesis.BlockHash() return testGenerator{ diff --git a/btcec/go.mod b/btcec/go.mod index ce5eb3321e..8f110664c1 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -3,7 +3,7 @@ module github.com/btcsuite/btcd/btcec/v2 go 1.17 require ( - github.com/btcsuite/btcd v0.22.0-beta + github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 ) diff --git a/btcec/go.sum b/btcec/go.sum index a0f9c5b8fa..f70838a70e 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -1,10 +1,10 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c h1:lnAMg3ra/Gw4AkRMxrxYs8nrprWsHowg8H9zaYsJOo4= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= @@ -13,37 +13,72 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/address.go b/btcutil/address.go index 7f7ccbbd7b..d0367abfc8 100644 --- a/btcutil/address.go +++ b/btcutil/address.go @@ -11,10 +11,10 @@ import ( "fmt" "strings" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil/base58" "github.com/btcsuite/btcd/btcutil/bech32" + "github.com/btcsuite/btcd/chaincfg" "golang.org/x/crypto/ripemd160" ) @@ -417,10 +417,6 @@ const ( // PKFCompressed indicates the pay-to-pubkey address format is a // compressed public key. PKFCompressed - - // PKFHybrid indicates the pay-to-pubkey address format is a hybrid - // public key. - PKFHybrid ) // AddressPubKey is an Address for a pay-to-pubkey transaction. @@ -434,7 +430,7 @@ type AddressPubKey struct { // address. The serializedPubKey parameter must be a valid pubkey and can be // uncompressed, compressed, or hybrid. func NewAddressPubKey(serializedPubKey []byte, net *chaincfg.Params) (*AddressPubKey, error) { - pubKey, err := btcec.ParsePubKey(serializedPubKey, btcec.S256()) + pubKey, err := btcec.ParsePubKey(serializedPubKey) if err != nil { return nil, err } @@ -447,8 +443,6 @@ func NewAddressPubKey(serializedPubKey []byte, net *chaincfg.Params) (*AddressPu switch serializedPubKey[0] { case 0x02, 0x03: pkFormat = PKFCompressed - case 0x06, 0x07: - pkFormat = PKFHybrid } return &AddressPubKey{ @@ -469,9 +463,6 @@ func (a *AddressPubKey) serialize() []byte { case PKFCompressed: return a.pubKey.SerializeCompressed() - - case PKFHybrid: - return a.pubKey.SerializeHybrid() } } diff --git a/btcutil/address_test.go b/btcutil/address_test.go index 52472b7923..f5ae2ac0d5 100644 --- a/btcutil/address_test.go +++ b/btcutil/address_test.go @@ -12,9 +12,9 @@ import ( "strings" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "golang.org/x/crypto/ripemd160" ) @@ -338,64 +338,6 @@ func TestAddresses(t *testing.T) { }, net: &chaincfg.MainNetParams, }, - { - name: "mainnet p2pk hybrid (0x06)", - addr: "06192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4" + - "0d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453e", - encoded: "1Ja5rs7XBZnK88EuLVcFqYGMEbBitzchmX", - valid: true, - result: btcutil.TstAddressPubKey( - []byte{ - 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, - 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, - 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, - 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, - 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, - 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, - 0x44, 0xd3, 0x3f, 0x45, 0x3e}, - btcutil.PKFHybrid, chaincfg.MainNetParams.PubKeyHashAddrID), - f: func() (btcutil.Address, error) { - serializedPubKey := []byte{ - 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, - 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, - 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, - 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, - 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, - 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, - 0x44, 0xd3, 0x3f, 0x45, 0x3e} - return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) - }, - net: &chaincfg.MainNetParams, - }, - { - name: "mainnet p2pk hybrid (0x07)", - addr: "07b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65" + - "37a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b", - encoded: "1ExqMmf6yMxcBMzHjbj41wbqYuqoX6uBLG", - valid: true, - result: btcutil.TstAddressPubKey( - []byte{ - 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, - 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, - 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, - 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, - 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, - 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, - 0x1e, 0x09, 0x08, 0xef, 0x7b}, - btcutil.PKFHybrid, chaincfg.MainNetParams.PubKeyHashAddrID), - f: func() (btcutil.Address, error) { - serializedPubKey := []byte{ - 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, - 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, - 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, - 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, - 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, - 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, - 0x1e, 0x09, 0x08, 0xef, 0x7b} - return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) - }, - net: &chaincfg.MainNetParams, - }, { name: "testnet p2pk compressed (0x02)", addr: "02192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4", @@ -469,64 +411,6 @@ func TestAddresses(t *testing.T) { }, net: &chaincfg.TestNet3Params, }, - { - name: "testnet p2pk hybrid (0x06)", - addr: "06192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b" + - "40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453e", - encoded: "my639vCVzbDZuEiX44adfTUg6anRomZLEP", - valid: true, - result: btcutil.TstAddressPubKey( - []byte{ - 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, - 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, - 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, - 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, - 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, - 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, - 0x44, 0xd3, 0x3f, 0x45, 0x3e}, - btcutil.PKFHybrid, chaincfg.TestNet3Params.PubKeyHashAddrID), - f: func() (btcutil.Address, error) { - serializedPubKey := []byte{ - 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, - 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, - 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, - 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, - 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, - 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, - 0x44, 0xd3, 0x3f, 0x45, 0x3e} - return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) - }, - net: &chaincfg.TestNet3Params, - }, - { - name: "testnet p2pk hybrid (0x07)", - addr: "07b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e6" + - "537a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b", - encoded: "muUnepk5nPPrxUTuTAhRqrpAQuSWS5fVii", - valid: true, - result: btcutil.TstAddressPubKey( - []byte{ - 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, - 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, - 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, - 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, - 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, - 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, - 0x1e, 0x09, 0x08, 0xef, 0x7b}, - btcutil.PKFHybrid, chaincfg.TestNet3Params.PubKeyHashAddrID), - f: func() (btcutil.Address, error) { - serializedPubKey := []byte{ - 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, - 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, - 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, - 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, - 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, - 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, - 0x1e, 0x09, 0x08, 0xef, 0x7b} - return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) - }, - net: &chaincfg.TestNet3Params, - }, // Segwit address tests. { name: "segwit mainnet p2wpkh v0", diff --git a/btcutil/go.mod b/btcutil/go.mod index eaf71339e1..36d669b06e 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -5,9 +5,13 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c + github.com/btcsuite/btcd/btcec/v2 v2.0.0 github.com/davecgh/go-spew v1.1.1 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) +replace github.com/btcsuite/btcd/btcec/v2 => ../btcec + replace github.com/btcsuite/btcd => ../ diff --git a/btcutil/go.sum b/btcutil/go.sum index f4eb4bca26..ac96abce84 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -12,64 +12,24 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/hdkeychain/extendedkey.go b/btcutil/hdkeychain/extendedkey.go index 4145c5c23e..c44e6a18b4 100644 --- a/btcutil/hdkeychain/extendedkey.go +++ b/btcutil/hdkeychain/extendedkey.go @@ -18,11 +18,11 @@ import ( "fmt" "math/big" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/base58" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) const ( @@ -154,8 +154,7 @@ func (k *ExtendedKey) pubKeyBytes() []byte { // This is a private extended key, so calculate and memoize the public // key if needed. if len(k.pubKey) == 0 { - pkx, pky := btcec.S256().ScalarBaseMult(k.key) - pubKey := btcec.PublicKey{Curve: btcec.S256(), X: pkx, Y: pky} + _, pubKey := btcec.PrivKeyFromBytes(k.key) k.pubKey = pubKey.SerializeCompressed() } @@ -292,8 +291,8 @@ func (k *ExtendedKey) Derive(i uint32) (*ExtendedKey, error) { // chance (< 1 in 2^127) this condition will not hold, and in that case, // a child extended key can't be created for this index and the caller // should simply increment to the next index. - ilNum := new(big.Int).SetBytes(il) - if ilNum.Cmp(btcec.S256().N) >= 0 || ilNum.Sign() == 0 { + var ilNum btcec.ModNScalar + if overflow := ilNum.SetByteSlice(il); overflow { return nil, ErrInvalidChild } @@ -313,35 +312,66 @@ func (k *ExtendedKey) Derive(i uint32) (*ExtendedKey, error) { // derive the final child key. // // childKey = parse256(Il) + parenKey - keyNum := new(big.Int).SetBytes(k.key) - ilNum.Add(ilNum, keyNum) - ilNum.Mod(ilNum, btcec.S256().N) - childKey = ilNum.Bytes() + var keyNum btcec.ModNScalar + if overflow := keyNum.SetByteSlice(k.key); overflow { + return nil, ErrInvalidChild + } + + childKeyBytes := ilNum.Add(&keyNum).Bytes() + childKey = childKeyBytes[:] + + // Strip leading zeroes from childKey, to match the expectation + // as the old big.Int usage in this area of the codebase. + for len(childKey) > 0 && childKey[0] == 0x00 { + childKey = childKey[1:] + } + isPrivate = true } else { // Case #3. - // Calculate the corresponding intermediate public key for - // intermediate private key. - ilx, ily := btcec.S256().ScalarBaseMult(il) - if ilx.Sign() == 0 || ily.Sign() == 0 { + // Calculate the corresponding intermediate public key for thek + // intermediate private key: ilJ = ilScalar*G + var ( + ilScalar btcec.ModNScalar + ilJ btcec.JacobianPoint + ) + if overflow := ilScalar.SetByteSlice(il); overflow { + return nil, ErrInvalidChild + } + btcec.ScalarBaseMultNonConst(&ilScalar, &ilJ) + + if (ilJ.X.IsZero() && ilJ.Y.IsZero()) || ilJ.Z.IsZero() { return nil, ErrInvalidChild } // Convert the serialized compressed parent public key into X // and Y coordinates so it can be added to the intermediate // public key. - pubKey, err := btcec.ParsePubKey(k.key, btcec.S256()) + pubKey, err := btcec.ParsePubKey(k.key) if err != nil { return nil, err } + // Convert the public key to jacobian coordinates, as that's + // what our main add/double methods use. + var pubKeyJ btcec.JacobianPoint + pubKey.AsJacobian(&pubKeyJ) + // Add the intermediate public key to the parent public key to // derive the final child key. // // childKey = serP(point(parse256(Il)) + parentKey) - childX, childY := btcec.S256().Add(ilx, ily, pubKey.X, pubKey.Y) - pk := btcec.PublicKey{Curve: btcec.S256(), X: childX, Y: childY} - childKey = pk.SerializeCompressed() + var childKeyPubJ btcec.JacobianPoint + btcec.AddNonConst(&ilJ, &pubKeyJ, &childKeyPubJ) + + // Convert the new child public key back to affine coordinates + // so we can serialize it in compressed format. + childKeyPubJ.ToAffine() + childKeyPub := btcec.NewPublicKey( + &childKeyPubJ.X, &childKeyPubJ.Y, + ) + + childKey = childKeyPub.SerializeCompressed() } // The fingerprint of the parent for the derived child is the first 4 @@ -400,19 +430,36 @@ func (k *ExtendedKey) DeriveNonStandard(i uint32) (*ExtendedKey, error) { childKey = ilNum.Bytes() isPrivate = true } else { - ilx, ily := btcec.S256().ScalarBaseMult(il) - if ilx.Sign() == 0 || ily.Sign() == 0 { + var ( + ilScalar btcec.ModNScalar + ilJ btcec.JacobianPoint + ) + if overflow := ilScalar.SetByteSlice(il); overflow { + return nil, ErrInvalidChild + } + btcec.ScalarBaseMultNonConst(&ilScalar, &ilJ) + + if (ilJ.X.IsZero() && ilJ.Y.IsZero()) || ilJ.Z.IsZero() { return nil, ErrInvalidChild } - pubKey, err := btcec.ParsePubKey(k.key, btcec.S256()) + pubKey, err := btcec.ParsePubKey(k.key) if err != nil { return nil, err } - childX, childY := btcec.S256().Add(ilx, ily, pubKey.X, pubKey.Y) - pk := btcec.PublicKey{Curve: btcec.S256(), X: childX, Y: childY} - childKey = pk.SerializeCompressed() + var pubKeyJ btcec.JacobianPoint + pubKey.AsJacobian(&pubKeyJ) + + var childKeyPubJ btcec.JacobianPoint + btcec.AddNonConst(&ilJ, &pubKeyJ, &childKeyPubJ) + + childKeyPubJ.ToAffine() + childKeyPub := btcec.NewPublicKey( + &childKeyPubJ.X, &childKeyPubJ.Y, + ) + + childKey = childKeyPub.SerializeCompressed() } parentFP := btcutil.Hash160(k.pubKeyBytes())[:4] @@ -488,7 +535,7 @@ func (k *ExtendedKey) CloneWithVersion(version []byte) (*ExtendedKey, error) { // ECPubKey converts the extended key to a btcec public key and returns it. func (k *ExtendedKey) ECPubKey() (*btcec.PublicKey, error) { - return btcec.ParsePubKey(k.pubKeyBytes(), btcec.S256()) + return btcec.ParsePubKey(k.pubKeyBytes()) } // ECPrivKey converts the extended key to a btcec private key and returns it. @@ -500,7 +547,7 @@ func (k *ExtendedKey) ECPrivKey() (*btcec.PrivateKey, error) { return nil, ErrNotPrivExtKey } - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), k.key) + privKey, _ := btcec.PrivKeyFromBytes(k.key) return privKey, nil } @@ -674,7 +721,7 @@ func NewKeyFromString(key string) (*ExtendedKey, error) { } else { // Ensure the public key parses correctly and is actually on the // secp256k1 curve. - _, err := btcec.ParsePubKey(keyData, btcec.S256()) + _, err := btcec.ParsePubKey(keyData) if err != nil { return nil, err } diff --git a/btcutil/hdkeychain/extendedkey_test.go b/btcutil/hdkeychain/extendedkey_test.go index dd6deb514e..0721b92480 100644 --- a/btcutil/hdkeychain/extendedkey_test.go +++ b/btcutil/hdkeychain/extendedkey_test.go @@ -18,6 +18,7 @@ import ( "testing" "github.com/btcsuite/btcd/chaincfg" + secp_ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4" ) // TestBIP0032Vectors tests the vectors provided by [BIP32] to ensure the @@ -878,7 +879,7 @@ func TestErrors(t *testing.T) { { name: "pubkey not on curve", key: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ1hr9Rwbk95YadvBkQXxzHBSngB8ndpW6QH7zhhsXZ2jHyZqPjk", - err: errors.New("invalid square root"), + err: secp_ecdsa.ErrPubKeyNotOnCurve, }, { name: "unsupported version", @@ -891,7 +892,7 @@ func TestErrors(t *testing.T) { for i, test := range tests { extKey, err := NewKeyFromString(test.key) - if !reflect.DeepEqual(err, test.err) { + if !errors.Is(err, test.err) { t.Errorf("NewKeyFromString #%d (%s): mismatched error "+ "-- got: %v, want: %v", i, test.name, err, test.err) @@ -900,7 +901,7 @@ func TestErrors(t *testing.T) { if test.neuter { _, err := extKey.Neuter() - if !reflect.DeepEqual(err, test.neuterErr) { + if !errors.Is(err, test.neuterErr) { t.Errorf("Neuter #%d (%s): mismatched error "+ "-- got: %v, want: %v", i, test.name, err, test.neuterErr) @@ -972,9 +973,9 @@ func TestZero(t *testing.T) { return false } - wantErr = errors.New("pubkey string is empty") + wantErr = secp_ecdsa.ErrPubKeyInvalidLen _, err = key.ECPubKey() - if !reflect.DeepEqual(err, wantErr) { + if !errors.Is(err, wantErr) { t.Errorf("ECPubKey #%d (%s): mismatched error: want "+ "%v, got %v", i, testName, wantErr, err) return false diff --git a/btcutil/internal_test.go b/btcutil/internal_test.go index 6d1efa0199..211b6ae64b 100644 --- a/btcutil/internal_test.go +++ b/btcutil/internal_test.go @@ -12,7 +12,7 @@ interface. The functions are only exported while the tests are being run. package btcutil import ( - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil/base58" "github.com/btcsuite/btcd/btcutil/bech32" "golang.org/x/crypto/ripemd160" @@ -99,7 +99,7 @@ func TstAddressTaproot(version byte, program [32]byte, func TstAddressPubKey(serializedPubKey []byte, pubKeyFormat PubKeyFormat, netID byte) *AddressPubKey { - pubKey, _ := btcec.ParsePubKey(serializedPubKey, btcec.S256()) + pubKey, _ := btcec.ParsePubKey(serializedPubKey) return &AddressPubKey{ pubKeyFormat: pubKeyFormat, pubKey: pubKey, diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 485abcff67..fbd9f1b3c2 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -4,15 +4,19 @@ go 1.17 require ( github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c + github.com/btcsuite/btcd/btcec/v2 v2.0.0 github.com/btcsuite/btcd/btcutil v1.0.0 github.com/davecgh/go-spew v1.1.1 ) require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect ) +replace github.com/btcsuite/btcd/btcec/v2 => ../../btcec + replace github.com/btcsuite/btcd/btcutil => ../ replace github.com/btcsuite/btcd => ../.. diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index 921a146260..08c53e8b09 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -8,63 +8,23 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/psbt/partialsig.go b/btcutil/psbt/partialsig.go index e11bb80de7..26a6dc2d61 100644 --- a/btcutil/psbt/partialsig.go +++ b/btcutil/psbt/partialsig.go @@ -3,7 +3,7 @@ package psbt import ( "bytes" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" ) // PartialSig encapsulate a (BTC public key, ECDSA signature) @@ -30,7 +30,7 @@ func (s PartialSigSorter) Less(i, j int) bool { // validatePubkey checks if pubKey is *any* valid pubKey serialization in a // Bitcoin context (compressed/uncomp. OK). func validatePubkey(pubKey []byte) bool { - _, err := btcec.ParsePubKey(pubKey, btcec.S256()) + _, err := btcec.ParsePubKey(pubKey) return err == nil } @@ -38,7 +38,7 @@ func validatePubkey(pubKey []byte) bool { // ECDSA signature, including the sighash flag. It does *not* of course // validate the signature against any message or public key. func validateSignature(sig []byte) bool { - _, err := btcec.ParseDERSignature(sig, btcec.S256()) + _, err := btcec.ParseDERSignature(sig) return err == nil } diff --git a/btcutil/wif.go b/btcutil/wif.go index e727a0c44a..a28cc8ba8d 100644 --- a/btcutil/wif.go +++ b/btcutil/wif.go @@ -8,10 +8,10 @@ import ( "bytes" "errors" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil/base58" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/btcutil/base58" ) // ErrMalformedPrivateKey describes an error where a WIF-encoded private @@ -117,7 +117,7 @@ func DecodeWIF(wif string) (*WIF, error) { netID := decoded[0] privKeyBytes := decoded[1 : 1+btcec.PrivKeyBytesLen] - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) + privKey, _ := btcec.PrivKeyFromBytes(privKeyBytes) return &WIF{privKey, compress, netID}, nil } @@ -136,9 +136,7 @@ func (w *WIF) String() string { a := make([]byte, 0, encodeLen) a = append(a, w.netID) - // Pad and append bytes manually, instead of using Serialize, to - // avoid another call to make. - a = paddedAppend(btcec.PrivKeyBytesLen, a, w.PrivKey.D.Bytes()) + a = append(a, w.PrivKey.Serialize()...) if w.CompressPubKey { a = append(a, compressMagic) } @@ -151,19 +149,9 @@ func (w *WIF) String() string { // exported private key in either a compressed or uncompressed format. The // serialization format chosen depends on the value of w.CompressPubKey. func (w *WIF) SerializePubKey() []byte { - pk := (*btcec.PublicKey)(&w.PrivKey.PublicKey) + pk := w.PrivKey.PubKey() if w.CompressPubKey { return pk.SerializeCompressed() } return pk.SerializeUncompressed() } - -// paddedAppend appends the src byte slice to dst, returning the new slice. -// If the length of the source is smaller than the passed size, leading zero -// bytes are appended to the dst slice before appending src. -func paddedAppend(size uint, dst, src []byte) []byte { - for i := 0; i < int(size)-len(src); i++ { - dst = append(dst, 0) - } - return append(dst, src...) -} diff --git a/btcutil/wif_test.go b/btcutil/wif_test.go index 1c21b4871b..c255c1b54f 100644 --- a/btcutil/wif_test.go +++ b/btcutil/wif_test.go @@ -9,9 +9,9 @@ import ( "encoding/hex" "testing" - "github.com/btcsuite/btcd/btcec" - "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/btcec/v2" . "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" ) func TestEncodeDecodeWIF(t *testing.T) { @@ -67,7 +67,7 @@ func TestEncodeDecodeWIF(t *testing.T) { validCase := validCase t.Run(validCase.name, func(t *testing.T) { - priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), validCase.privateKey) + priv, _ := btcec.PrivKeyFromBytes(validCase.privateKey) wif, err := NewWIF(priv, validCase.net, validCase.compress) if err != nil { t.Fatalf("NewWIF failed: expected no error, got '%v'", err) @@ -145,7 +145,7 @@ func TestEncodeDecodeWIF(t *testing.T) { 0x60, 0x0b, 0x2f, 0xe5, 0x0b, 0x7c, 0xae, 0x11, 0xec, 0x86, 0xd3, 0xbf, 0x1f, 0xbe, 0x47, 0x1b, 0xe8, 0x98, 0x27, 0xe1, 0x9d, 0x72, 0xaa, 0x1d} - priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), privateKey) + priv, _ := btcec.PrivKeyFromBytes(privateKey) wif, err := NewWIF(priv, nil, true) diff --git a/go.mod b/go.mod index 2c2bb9229f..7ed1214d86 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/btcsuite/btcd require ( + github.com/btcsuite/btcd/btcec/v2 v2.0.0 github.com/btcsuite/btcd/btcutil v1.0.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd @@ -17,9 +18,12 @@ require ( require ( github.com/aead/siphash v1.0.1 // indirect github.com/btcsuite/snappy-go v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect ) replace github.com/btcsuite/btcd/btcutil => ./btcutil +replace github.com/btcsuite/btcd/btcec/v2 => ./btcec + go 1.17 diff --git a/go.sum b/go.sum index 3b35b00620..2645b3566c 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,10 @@ github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/integration/csv_fork_test.go b/integration/csv_fork_test.go index 5ffd5d5ab2..45ab8ad1aa 100644 --- a/integration/csv_fork_test.go +++ b/integration/csv_fork_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // This file is ignored during the regular tests due to the following build tag. +//go:build rpctest // +build rpctest package integration @@ -15,7 +16,7 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/integration/rpctest" @@ -35,7 +36,7 @@ func makeTestOutput(r *rpctest.Harness, t *testing.T, // Create a fresh key, then send some coins to an address spendable by // that key. - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { return nil, nil, nil, err } diff --git a/integration/rpcserver_test.go b/integration/rpcserver_test.go index 13325bc1d7..7e90a36b5c 100644 --- a/integration/rpcserver_test.go +++ b/integration/rpcserver_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // This file is ignored during the regular tests due to the following build tag. +//go:build rpctest // +build rpctest package integration diff --git a/integration/rpctest/memwallet.go b/integration/rpctest/memwallet.go index c94124d82c..d084e99feb 100644 --- a/integration/rpctest/memwallet.go +++ b/integration/rpctest/memwallet.go @@ -11,14 +11,14 @@ import ( "sync" "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/hdkeychain" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/btcutil/hdkeychain" ) var ( @@ -133,6 +133,7 @@ func newMemWallet(net *chaincfg.Params, harnessID uint32) (*memWallet, error) { if err != nil { return nil, err } + coinbaseAddr, err := keyToAddr(coinbaseKey, net) if err != nil { return nil, err @@ -514,11 +515,13 @@ func (m *memWallet) CreateTransaction(outputs []*wire.TxOut, return nil, err } - privKey, err := extendedKey.ECPrivKey() + privKeyOld, err := extendedKey.ECPrivKey() if err != nil { return nil, err } + privKey, _ := btcec.PrivKeyFromBytes(privKeyOld.Serialize()) + sigScript, err := txscript.SignatureScript(tx, i, utxo.pkScript, txscript.SigHashAll, privKey, true) if err != nil { diff --git a/integration/rpctest/rpc_harness_test.go b/integration/rpctest/rpc_harness_test.go index d1184eb6ba..baadd35f5e 100644 --- a/integration/rpctest/rpc_harness_test.go +++ b/integration/rpctest/rpc_harness_test.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. // This file is ignored during the regular tests due to the following build tag. +//go:build rpctest // +build rpctest package rpctest diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 96777b9758..8df587f8a5 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -13,7 +13,7 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" @@ -291,7 +291,7 @@ func newPoolHarness(chainParams *chaincfg.Params) (*poolHarness, []spendableOutp if err != nil { return nil, nil, err } - signKey, signPub := btcec.PrivKeyFromBytes(btcec.S256(), keyBytes) + signKey, signPub := btcec.PrivKeyFromBytes(keyBytes) // Generate associated pay-to-script-hash address and resulting payment // script. diff --git a/mempool/policy_test.go b/mempool/policy_test.go index a81f98ea83..5175b67999 100644 --- a/mempool/policy_test.go +++ b/mempool/policy_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" @@ -98,7 +98,7 @@ func TestCalcMinRequiredTxRelayFee(t *testing.T) { func TestCheckPkScriptStandard(t *testing.T) { var pubKeys [][]byte for i := 0; i < 4; i++ { - pk, err := btcec.NewPrivateKey(btcec.S256()) + pk, err := btcec.NewPrivateKey() if err != nil { t.Fatalf("TestCheckPkScriptStandard NewPrivateKey failed: %v", err) diff --git a/rpcserver.go b/rpcserver.go index e000af5a4f..b26074b33b 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -29,7 +29,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain/indexers" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" @@ -3520,7 +3520,7 @@ func handleSignMessageWithPrivKey(s *rpcServer, cmd interface{}, closeChan <-cha wire.WriteVarString(&buf, 0, c.Message) messageHash := chainhash.DoubleHashB(buf.Bytes()) - sig, err := btcec.SignCompact(btcec.S256(), wif.PrivKey, + sig, err := btcec.SignCompact(wif.PrivKey, messageHash, wif.CompressPubKey) if err != nil { return nil, &btcjson.RPCError{ @@ -3715,7 +3715,7 @@ func handleVerifyMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{ wire.WriteVarString(&buf, 0, messageSignatureHeader) wire.WriteVarString(&buf, 0, c.Message) expectedMessageHash := chainhash.DoubleHashB(buf.Bytes()) - pk, wasCompressed, err := btcec.RecoverCompact(btcec.S256(), sig, + pk, wasCompressed, err := btcec.RecoverCompact(sig, expectedMessageHash) if err != nil { // Mirror Bitcoin Core behavior, which treats error in diff --git a/txscript/engine.go b/txscript/engine.go index 0814e7eb96..1550579d28 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -12,7 +12,7 @@ import ( "math/big" "strings" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/wire" ) diff --git a/txscript/example_test.go b/txscript/example_test.go index 7983b08ff2..f3ff4b873c 100644 --- a/txscript/example_test.go +++ b/txscript/example_test.go @@ -9,7 +9,7 @@ import ( "encoding/hex" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" @@ -90,7 +90,7 @@ func ExampleSignTxOutput() { fmt.Println(err) return } - privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes) + privKey, pubKey := btcec.PrivKeyFromBytes(privKeyBytes) pubKeyHash := btcutil.Hash160(pubKey.SerializeCompressed()) addr, err := btcutil.NewAddressPubKeyHash(pubKeyHash, &chaincfg.MainNetParams) diff --git a/txscript/opcode.go b/txscript/opcode.go index 4c31be3f75..708bb2370b 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -15,7 +15,7 @@ import ( "golang.org/x/crypto/ripemd160" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) @@ -1929,7 +1929,7 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { hash = calcSignatureHash(subScript, hashType, &vm.tx, vm.txIdx) } - pubKey, err := btcec.ParsePubKey(pkBytes, btcec.S256()) + pubKey, err := btcec.ParsePubKey(pkBytes) if err != nil { vm.dstack.PushBool(false) return nil @@ -1939,9 +1939,9 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { if vm.hasFlag(ScriptVerifyStrictEncoding) || vm.hasFlag(ScriptVerifyDERSignatures) { - signature, err = btcec.ParseDERSignature(sigBytes, btcec.S256()) + signature, err = btcec.ParseDERSignature(sigBytes) } else { - signature, err = btcec.ParseSignature(sigBytes, btcec.S256()) + signature, err = btcec.ParseSignature(sigBytes) } if err != nil { vm.dstack.PushBool(false) @@ -2148,11 +2148,9 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { if vm.hasFlag(ScriptVerifyStrictEncoding) || vm.hasFlag(ScriptVerifyDERSignatures) { - parsedSig, err = btcec.ParseDERSignature(signature, - btcec.S256()) + parsedSig, err = btcec.ParseDERSignature(signature) } else { - parsedSig, err = btcec.ParseSignature(signature, - btcec.S256()) + parsedSig, err = btcec.ParseSignature(signature) } sigInfo.parsed = true if err != nil { @@ -2174,7 +2172,7 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { } // Parse the pubkey. - parsedPubKey, err := btcec.ParsePubKey(pubKey, btcec.S256()) + parsedPubKey, err := btcec.ParsePubKey(pubKey) if err != nil { continue } diff --git a/txscript/pkscript.go b/txscript/pkscript.go index f8aa783aef..c5dd2a12a2 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" diff --git a/txscript/sigcache.go b/txscript/sigcache.go index d9e4fa6ce1..959240c04d 100644 --- a/txscript/sigcache.go +++ b/txscript/sigcache.go @@ -7,7 +7,7 @@ package txscript import ( "sync" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" ) diff --git a/txscript/sigcache_test.go b/txscript/sigcache_test.go index 5413ea3b2c..f9e9f270ef 100644 --- a/txscript/sigcache_test.go +++ b/txscript/sigcache_test.go @@ -8,7 +8,7 @@ import ( "crypto/rand" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -16,7 +16,7 @@ import ( // public key and the public key. This function is used to generate randomized // test data. func genRandomSig() (*chainhash.Hash, *btcec.Signature, *btcec.PublicKey, error) { - privKey, err := btcec.NewPrivateKey(btcec.S256()) + privKey, err := btcec.NewPrivateKey() if err != nil { return nil, nil, nil, err } @@ -26,10 +26,7 @@ func genRandomSig() (*chainhash.Hash, *btcec.Signature, *btcec.PublicKey, error) return nil, nil, nil, err } - sig, err := privKey.Sign(msgHash[:]) - if err != nil { - return nil, nil, nil, err - } + sig := btcec.Sign(privKey, msgHash[:]) return &msgHash, sig, privKey.PubKey(), nil } @@ -49,8 +46,8 @@ func TestSigCacheAddExists(t *testing.T) { sigCache.Add(*msg1, sig1, key1) // The previously added triplet should now be found within the sigcache. - sig1Copy, _ := btcec.ParseSignature(sig1.Serialize(), btcec.S256()) - key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed(), btcec.S256()) + sig1Copy, _ := btcec.ParseSignature(sig1.Serialize()) + key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) if !sigCache.Exists(*msg1, sig1Copy, key1Copy) { t.Errorf("previously added item not found in signature cache") } @@ -73,8 +70,14 @@ func TestSigCacheAddEvictEntry(t *testing.T) { sigCache.Add(*msg, sig, key) - sigCopy, _ := btcec.ParseSignature(sig.Serialize(), btcec.S256()) - keyCopy, _ := btcec.ParsePubKey(key.SerializeCompressed(), btcec.S256()) + sigCopy, err := btcec.ParseSignature(sig.Serialize()) + if err != nil { + t.Fatalf("unable to parse sig: %v", err) + } + keyCopy, err := btcec.ParsePubKey(key.SerializeCompressed()) + if err != nil { + t.Fatalf("unable to parse key: %v", err) + } if !sigCache.Exists(*msg, sigCopy, keyCopy) { t.Errorf("previously added item not found in signature" + "cache") @@ -102,8 +105,8 @@ func TestSigCacheAddEvictEntry(t *testing.T) { } // The entry added above should be found within the sigcache. - sigNewCopy, _ := btcec.ParseSignature(sigNew.Serialize(), btcec.S256()) - keyNewCopy, _ := btcec.ParsePubKey(keyNew.SerializeCompressed(), btcec.S256()) + sigNewCopy, _ := btcec.ParseSignature(sigNew.Serialize()) + keyNewCopy, _ := btcec.ParsePubKey(keyNew.SerializeCompressed()) if !sigCache.Exists(*msgNew, sigNewCopy, keyNewCopy) { t.Fatalf("previously added item not found in signature cache") } @@ -125,8 +128,8 @@ func TestSigCacheAddMaxEntriesZeroOrNegative(t *testing.T) { sigCache.Add(*msg1, sig1, key1) // The generated triplet should not be found. - sig1Copy, _ := btcec.ParseSignature(sig1.Serialize(), btcec.S256()) - key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed(), btcec.S256()) + sig1Copy, _ := btcec.ParseSignature(sig1.Serialize()) + key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) if sigCache.Exists(*msg1, sig1Copy, key1Copy) { t.Errorf("previously added signature found in sigcache, but" + "shouldn't have been") diff --git a/txscript/sign.go b/txscript/sign.go index 84d8d1f3ea..e5335ce366 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -6,12 +6,11 @@ package txscript import ( "errors" - "fmt" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // RawTxInWitnessSignature returns the serialized ECDA signature for the input @@ -28,10 +27,7 @@ func RawTxInWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, return nil, err } - signature, err := key.Sign(hash) - if err != nil { - return nil, fmt.Errorf("cannot sign tx input: %s", err) - } + signature := btcec.Sign(key, hash) return append(signature.Serialize(), byte(hashType)), nil } @@ -51,7 +47,7 @@ func WitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64 return nil, err } - pk := (*btcec.PublicKey)(&privKey.PublicKey) + pk := privKey.PubKey() var pkData []byte if compress { pkData = pk.SerializeCompressed() @@ -73,10 +69,7 @@ func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, if err != nil { return nil, err } - signature, err := key.Sign(hash) - if err != nil { - return nil, fmt.Errorf("cannot sign tx input: %s", err) - } + signature := btcec.Sign(key, hash) return append(signature.Serialize(), byte(hashType)), nil } @@ -95,7 +88,7 @@ func SignatureScript(tx *wire.MsgTx, idx int, subscript []byte, hashType SigHash return nil, err } - pk := (*btcec.PublicKey)(&privKey.PublicKey) + pk := privKey.PubKey() var pkData []byte if compress { pkData = pk.SerializeCompressed() @@ -270,7 +263,7 @@ sigLoop: tSig := sig[:len(sig)-1] hashType := SigHashType(sig[len(sig)-1]) - pSig, err := btcec.ParseDERSignature(tSig, btcec.S256()) + pSig, err := btcec.ParseDERSignature(tSig) if err != nil { continue } diff --git a/txscript/sign_test.go b/txscript/sign_test.go index 47084f18bf..637ccef10d 100644 --- a/txscript/sign_test.go +++ b/txscript/sign_test.go @@ -9,7 +9,7 @@ import ( "fmt" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" @@ -143,15 +143,14 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -180,15 +179,14 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -241,15 +239,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -280,15 +277,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -342,15 +338,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -381,15 +376,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -442,15 +436,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -481,15 +474,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -543,15 +535,14 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -600,15 +591,14 @@ func TestSignTxOutput(t *testing.T) { for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -683,15 +673,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -740,15 +729,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { @@ -822,15 +810,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -879,15 +866,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeUncompressed() + pk := key.PubKey().SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -960,15 +946,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -1016,15 +1001,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key, err := btcec.NewPrivateKey(btcec.S256()) + key, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk := (*btcec.PublicKey)(&key.PublicKey). - SerializeCompressed() + pk := key.PubKey().SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { @@ -1097,15 +1081,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key1, err := btcec.NewPrivateKey(btcec.S256()) + key1, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk1 := (*btcec.PublicKey)(&key1.PublicKey). - SerializeCompressed() + pk1 := key1.PubKey().SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, &chaincfg.TestNet3Params) if err != nil { @@ -1114,15 +1097,14 @@ func TestSignTxOutput(t *testing.T) { break } - key2, err := btcec.NewPrivateKey(btcec.S256()) + key2, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } - pk2 := (*btcec.PublicKey)(&key2.PublicKey). - SerializeCompressed() + pk2 := key2.PubKey().SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, &chaincfg.TestNet3Params) if err != nil { @@ -1173,15 +1155,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key1, err := btcec.NewPrivateKey(btcec.S256()) + key1, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk1 := (*btcec.PublicKey)(&key1.PublicKey). - SerializeCompressed() + pk1 := key1.PubKey().SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, &chaincfg.TestNet3Params) if err != nil { @@ -1190,15 +1171,14 @@ func TestSignTxOutput(t *testing.T) { break } - key2, err := btcec.NewPrivateKey(btcec.S256()) + key2, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } - pk2 := (*btcec.PublicKey)(&key2.PublicKey). - SerializeCompressed() + pk2 := key2.PubKey().SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, &chaincfg.TestNet3Params) if err != nil { @@ -1279,15 +1259,14 @@ func TestSignTxOutput(t *testing.T) { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) - key1, err := btcec.NewPrivateKey(btcec.S256()) + key1, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } - pk1 := (*btcec.PublicKey)(&key1.PublicKey). - SerializeCompressed() + pk1 := key1.PubKey().SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, &chaincfg.TestNet3Params) if err != nil { @@ -1296,15 +1275,14 @@ func TestSignTxOutput(t *testing.T) { break } - key2, err := btcec.NewPrivateKey(btcec.S256()) + key2, err := btcec.NewPrivateKey() if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } - pk2 := (*btcec.PublicKey)(&key2.PublicKey). - SerializeCompressed() + pk2 := key2.PubKey().SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, &chaincfg.TestNet3Params) if err != nil { @@ -1635,7 +1613,7 @@ var sigScriptTests = []tstSigScript{ func TestSignatureScript(t *testing.T) { t.Parallel() - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyD) + privKey, _ := btcec.PrivKeyFromBytes(privKeyD) nexttest: for i := range sigScriptTests { From d2960c83ccf84e99be86df087a99bbc16e87dc18 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 11 Jan 2022 19:58:44 -0800 Subject: [PATCH 0594/1056] build: don't run the integration tests w/ -race --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dd34608df6..24667def7c 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ check: unit unit: @$(call print, "Running unit tests.") - $(GOTEST) ./... -test.timeout=20m + $(GOTEST_DEV) ./... -test.timeout=20m cd btcec; $(GOTEST_DEV) ./... -test.timeout=20m cd btcutil; $(GOTEST_DEV) ./... -test.timeout=20m cd btcutil/psbt; $(GOTEST_DEV) ./... -test.timeout=20m From 3ee1211e78ccfdd6ec085d1d38e5abf82bbeb1ab Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 2 Dec 2021 16:54:42 -0800 Subject: [PATCH 0595/1056] btcec/v2: retain copyright notices from decred developers for all files --- btcec/curve.go | 3 +++ btcec/error.go | 3 +++ btcec/modnscalar.go | 3 +++ 3 files changed, 9 insertions(+) diff --git a/btcec/curve.go b/btcec/curve.go index b86c591374..5224e35c8e 100644 --- a/btcec/curve.go +++ b/btcec/curve.go @@ -1,3 +1,6 @@ +// Copyright (c) 2015-2021 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers + package btcec import ( diff --git a/btcec/error.go b/btcec/error.go index 39c9172bc3..81ca2b044d 100644 --- a/btcec/error.go +++ b/btcec/error.go @@ -1,3 +1,6 @@ +// Copyright (c) 2013-2021 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers + package btcec import ( diff --git a/btcec/modnscalar.go b/btcec/modnscalar.go index eb1b8f05f4..b18b2c1d43 100644 --- a/btcec/modnscalar.go +++ b/btcec/modnscalar.go @@ -1,3 +1,6 @@ +// Copyright (c) 2013-2021 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers + package btcec import ( From b3d263e902e14e3491a8513cc8b0784597a61700 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 26 Jan 2022 16:31:54 -0800 Subject: [PATCH 0596/1056] build: use sed to remove v2 path from btcec/coverage.txt The `goveralls` tool we use to handle code coverage upload seems to not understand that a `v2 module can exist, without having a v2 file path on disk. We use a `sed` command to remove the `v2` module prefix so the tool can reach into the correct file to extract the source code. --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 24667def7c..2e967ba0f6 100644 --- a/Makefile +++ b/Makefile @@ -87,8 +87,13 @@ unit: unit-cover: $(GOACC_BIN) @$(call print, "Running unit coverage tests.") $(GOACC_BIN) ./... - cd btcec; $(GOACC_BIN) ./... + + # We need to remove the /v2 pathing from the module to have it work + # nicely with the CI tool we use to render live code coverage. + cd btcec; $(GOACC_BIN) ./...; sed -i.bak 's/v2\///g' coverage.txt + cd btcutil; $(GOACC_BIN) ./... + cd btcutil/psbt; $(GOACC_BIN) ./... unit-race: From eb61742c5dc54b2fe5fae0cbde814d2ddd6a59e5 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 2 Dec 2021 18:33:04 -0800 Subject: [PATCH 0597/1056] btcec/v2: create new ecdsa package In this commit, we create a new package to house the ECDSA-specific logic in the new `btcec/v2` pacakge. Thsi c hange is meant to mirror the structure of the `dcrec` package, as we'll soon slot in our own custom BIP-340 implementation. --- btcec/bench_test.go | 29 ---- btcec/btcec_test.go | 21 --- btcec/ecdsa/bench_test.go | 210 ++++++++++++++++++++++++++++ btcec/ecdsa/error.go | 18 +++ btcec/{ => ecdsa}/example_test.go | 7 +- btcec/{ => ecdsa}/signature.go | 16 ++- btcec/{ => ecdsa}/signature_test.go | 85 +++++++++-- btcec/go.mod | 6 + btcec/go.sum | 56 +------- btcec/privkey_test.go | 51 ------- btcutil/psbt/partialsig.go | 3 +- rpcserver.go | 6 +- txscript/opcode.go | 15 +- txscript/pkscript.go | 3 +- txscript/sigcache.go | 7 +- txscript/sigcache_test.go | 13 +- txscript/sign.go | 8 +- 17 files changed, 353 insertions(+), 201 deletions(-) create mode 100644 btcec/ecdsa/bench_test.go create mode 100644 btcec/ecdsa/error.go rename btcec/{ => ecdsa}/example_test.go (93%) rename btcec/{ => ecdsa}/signature.go (95%) rename btcec/{ => ecdsa}/signature_test.go (92%) delete mode 100644 btcec/privkey_test.go diff --git a/btcec/bench_test.go b/btcec/bench_test.go index 475a4afd6e..89e2bc2cce 100644 --- a/btcec/bench_test.go +++ b/btcec/bench_test.go @@ -164,35 +164,6 @@ func hexToModNScalar(s string) *ModNScalar { return &scalar } -// BenchmarkSigVerify benchmarks how long it takes the secp256k1 curve to -// verify signatures. -func BenchmarkSigVerify(b *testing.B) { - b.StopTimer() - // Randomly generated keypair. - // Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d - pubKey := NewPublicKey( - hexToFieldVal("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab"), - hexToFieldVal("ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52"), - ) - - // Double sha256 of []byte{0x01, 0x02, 0x03, 0x04} - msgHash := fromHex("8de472e2399610baaa7f84840547cd409434e31f5d3bd71e4d947f283874f9c0") - sig := NewSignature( - hexToModNScalar("fef45d2892953aa5bbcdb057b5e98b208f1617a7498af7eb765574e29b5d9c2c"), - hexToModNScalar("d47563f52aac6b04b55de236b7c515eb9311757db01e02cff079c3ca6efb063f"), - ) - - if !sig.Verify(msgHash.Bytes(), pubKey) { - b.Errorf("Signature failed to verify") - return - } - b.StartTimer() - - for i := 0; i < b.N; i++ { - sig.Verify(msgHash.Bytes(), pubKey) - } -} - // BenchmarkFieldNormalize benchmarks how long it takes the internal field // to perform normalization (which includes modular reduction). func BenchmarkFieldNormalize(b *testing.B) { diff --git a/btcec/btcec_test.go b/btcec/btcec_test.go index 5fdd638f22..3113a1b553 100644 --- a/btcec/btcec_test.go +++ b/btcec/btcec_test.go @@ -851,27 +851,6 @@ func TestKeyGeneration(t *testing.T) { testKeyGeneration(t, S256(), "S256") } -func testSignAndVerify(t *testing.T, c *KoblitzCurve, tag string) { - priv, _ := NewPrivateKey() - pub := priv.PubKey() - - hashed := []byte("testing") - sig := Sign(priv, hashed) - - if !sig.Verify(hashed, pub) { - t.Errorf("%s: Verify failed", tag) - } - - hashed[0] ^= 0xff - if sig.Verify(hashed, pub) { - t.Errorf("%s: Verify always works!", tag) - } -} - -func TestSignAndVerify(t *testing.T) { - testSignAndVerify(t, S256(), "S256") -} - // checkNAFEncoding returns an error if the provided positive and negative // portions of an overall NAF encoding do not adhere to the requirements or they // do not sum back to the provided original value. diff --git a/btcec/ecdsa/bench_test.go b/btcec/ecdsa/bench_test.go new file mode 100644 index 0000000000..3e27994cd4 --- /dev/null +++ b/btcec/ecdsa/bench_test.go @@ -0,0 +1,210 @@ +// Copyright 2013-2016 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package ecdsa + +import ( + "encoding/hex" + "math/big" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +// hexToBytes converts the passed hex string into bytes and will panic if there +// is an error. This is only provided for the hard-coded constants so errors in +// the source code can be detected. It will only (and must only) be called with +// hard-coded values. +func hexToBytes(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + return b +} + +// hexToModNScalar converts the passed hex string into a ModNScalar and will +// panic if there is an error. This is only provided for the hard-coded +// constants so errors in the source code can be detected. It will only (and +// must only) be called with hard-coded values. +func hexToModNScalar(s string) *btcec.ModNScalar { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + var scalar btcec.ModNScalar + if overflow := scalar.SetByteSlice(b); overflow { + panic("hex in source file overflows mod N scalar: " + s) + } + return &scalar +} + +// hexToFieldVal converts the passed hex string into a FieldVal and will panic +// if there is an error. This is only provided for the hard-coded constants so +// errors in the source code can be detected. It will only (and must only) be +// called with hard-coded values. +func hexToFieldVal(s string) *btcec.FieldVal { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + var f btcec.FieldVal + if overflow := f.SetByteSlice(b); overflow { + panic("hex in source file overflows mod P: " + s) + } + return &f +} + +// fromHex converts the passed hex string into a big integer pointer and will +// panic is there is an error. This is only provided for the hard-coded +// constants so errors in the source code can bet detected. It will only (and +// must only) be called for initialization purposes. +func fromHex(s string) *big.Int { + if s == "" { + return big.NewInt(0) + } + r, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("invalid hex in source file: " + s) + } + return r +} + +// BenchmarkSigVerify benchmarks how long it takes the secp256k1 curve to +// verify signatures. +func BenchmarkSigVerify(b *testing.B) { + b.StopTimer() + // Randomly generated keypair. + // Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d + pubKey := btcec.NewPublicKey( + hexToFieldVal("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab"), + hexToFieldVal("ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52"), + ) + + // Double sha256 of []byte{0x01, 0x02, 0x03, 0x04} + msgHash := fromHex("8de472e2399610baaa7f84840547cd409434e31f5d3bd71e4d947f283874f9c0") + sig := NewSignature( + hexToModNScalar("fef45d2892953aa5bbcdb057b5e98b208f1617a7498af7eb765574e29b5d9c2c"), + hexToModNScalar("d47563f52aac6b04b55de236b7c515eb9311757db01e02cff079c3ca6efb063f"), + ) + + if !sig.Verify(msgHash.Bytes(), pubKey) { + b.Errorf("Signature failed to verify") + return + } + b.StartTimer() + + for i := 0; i < b.N; i++ { + sig.Verify(msgHash.Bytes(), pubKey) + } +} + +// BenchmarkSign benchmarks how long it takes to sign a message. +func BenchmarkSign(b *testing.B) { + // Randomly generated keypair. + d := hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d") + privKey := secp256k1.NewPrivateKey(d) + + // blake256 of []byte{0x01, 0x02, 0x03, 0x04}. + msgHash := hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7") + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + Sign(privKey, msgHash) + } +} + +// BenchmarkSigSerialize benchmarks how long it takes to serialize a typical +// signature with the strict DER encoding. +func BenchmarkSigSerialize(b *testing.B) { + // Randomly generated keypair. + // Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d + // Signature for double sha256 of []byte{0x01, 0x02, 0x03, 0x04}. + sig := NewSignature( + hexToModNScalar("fef45d2892953aa5bbcdb057b5e98b208f1617a7498af7eb765574e29b5d9c2c"), + hexToModNScalar("d47563f52aac6b04b55de236b7c515eb9311757db01e02cff079c3ca6efb063f"), + ) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + sig.Serialize() + } +} + +// BenchmarkNonceRFC6979 benchmarks how long it takes to generate a +// deterministic nonce according to RFC6979. +func BenchmarkNonceRFC6979(b *testing.B) { + // Randomly generated keypair. + // Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d + // X: d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab + // Y: ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52 + privKeyStr := "9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d" + privKey := hexToBytes(privKeyStr) + + // BLAKE-256 of []byte{0x01, 0x02, 0x03, 0x04}. + msgHash := hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7") + + b.ReportAllocs() + b.ResetTimer() + var noElideNonce *secp256k1.ModNScalar + for i := 0; i < b.N; i++ { + noElideNonce = secp256k1.NonceRFC6979(privKey, msgHash, nil, nil, 0) + } + _ = noElideNonce +} + +// BenchmarkSignCompact benchmarks how long it takes to produce a compact +// signature for a message. +func BenchmarkSignCompact(b *testing.B) { + d := hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d") + privKey := secp256k1.NewPrivateKey(d) + + // blake256 of []byte{0x01, 0x02, 0x03, 0x04}. + msgHash := hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7") + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = SignCompact(privKey, msgHash, true) + } +} + +// BenchmarkSignCompact benchmarks how long it takes to recover a public key +// given a compact signature and message. +func BenchmarkRecoverCompact(b *testing.B) { + // Private key: 9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d + wantPubKey := secp256k1.NewPublicKey( + hexToFieldVal("d2e670a19c6d753d1a6d8b20bd045df8a08fb162cf508956c31268c6d81ffdab"), + hexToFieldVal("ab65528eefbb8057aa85d597258a3fbd481a24633bc9b47a9aa045c91371de52"), + ) + + compactSig := hexToBytes("205978b7896bc71676ba2e459882a8f52e1299449596c4f" + + "93c59bf1fbfa2f9d3b76ecd0c99406f61a6de2bb5a8937c061c176ecf381d0231e0d" + + "af73b922c8952c7") + + // blake256 of []byte{0x01, 0x02, 0x03, 0x04}. + msgHash := hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7") + + // Ensure a valid compact signature is being benchmarked. + pubKey, wasCompressed, err := RecoverCompact(compactSig, msgHash) + if err != nil { + b.Fatalf("unexpected err: %v", err) + } + if !wasCompressed { + b.Fatal("recover claims uncompressed pubkey") + } + if !pubKey.IsEqual(wantPubKey) { + b.Fatal("recover returned unexpected pubkey") + } + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _, _ = RecoverCompact(compactSig, msgHash) + } +} diff --git a/btcec/ecdsa/error.go b/btcec/ecdsa/error.go new file mode 100644 index 0000000000..a30d63b636 --- /dev/null +++ b/btcec/ecdsa/error.go @@ -0,0 +1,18 @@ +// Copyright (c) 2013-2021 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers + +package ecdsa + +import ( + secp_ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" +) + +// ErrorKind identifies a kind of error. It has full support for +// errors.Is and errors.As, so the caller can directly check against +// an error kind when determining the reason for an error. +type ErrorKind = secp_ecdsa.ErrorKind + +// Error identifies an error related to an ECDSA signature. It has full +// support for errors.Is and errors.As, so the caller can ascertain the +// specific reason for the error by checking the underlying error. +type Error = secp_ecdsa.ErrorKind diff --git a/btcec/example_test.go b/btcec/ecdsa/example_test.go similarity index 93% rename from btcec/example_test.go rename to btcec/ecdsa/example_test.go index b73f102c32..409a95bd23 100644 --- a/btcec/example_test.go +++ b/btcec/ecdsa/example_test.go @@ -2,13 +2,14 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcec_test +package ecdsa_test import ( "encoding/hex" "fmt" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -27,7 +28,7 @@ func Example_signMessage() { // Sign a message using the private key. message := "test message" messageHash := chainhash.DoubleHashB([]byte(message)) - signature := btcec.Sign(privKey, messageHash) + signature := ecdsa.Sign(privKey, messageHash) // Serialize and display the signature. fmt.Printf("Serialized Signature: %x\n", signature.Serialize()) @@ -67,7 +68,7 @@ func Example_verifySignature() { fmt.Println(err) return } - signature, err := btcec.ParseSignature(sigBytes) + signature, err := ecdsa.ParseSignature(sigBytes) if err != nil { fmt.Println(err) return diff --git a/btcec/signature.go b/btcec/ecdsa/signature.go similarity index 95% rename from btcec/signature.go rename to btcec/ecdsa/signature.go index ddeb4b052f..092e4ceb1c 100644 --- a/btcec/signature.go +++ b/btcec/ecdsa/signature.go @@ -1,14 +1,16 @@ // Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcec +package ecdsa import ( "errors" "fmt" "math/big" + "github.com/btcsuite/btcd/btcec/v2" secp_ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" ) @@ -22,7 +24,7 @@ var ( type Signature = secp_ecdsa.Signature // NewSignature instantiates a new signature given some r and s values. -func NewSignature(r, s *ModNScalar) *Signature { +func NewSignature(r, s *btcec.ModNScalar) *Signature { return secp_ecdsa.NewSignature(r, s) } @@ -122,7 +124,7 @@ func parseSig(sigStr []byte, der bool) (*Signature, error) { // R must be in the range [1, N-1]. Notice the check for the maximum number // of bytes is required because SetByteSlice truncates as noted in its // comment so it could otherwise fail to detect the overflow. - var r ModNScalar + var r btcec.ModNScalar if len(rBytes) > 32 { str := "invalid signature: R is larger than 256 bits" return nil, errors.New(str) @@ -169,7 +171,7 @@ func parseSig(sigStr []byte, der bool) (*Signature, error) { // S must be in the range [1, N-1]. Notice the check for the maximum number // of bytes is required because SetByteSlice truncates as noted in its // comment so it could otherwise fail to detect the overflow. - var s ModNScalar + var s btcec.ModNScalar if len(sBytes) > 32 { str := "invalid signature: S is larger than 256 bits" return nil, errors.New(str) @@ -214,7 +216,7 @@ func ParseDERSignature(sigStr []byte) (*Signature, error) { // returned in the format: // <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R> // where the R and S parameters are padde up to the bitlengh of the curve. -func SignCompact(key *PrivateKey, hash []byte, +func SignCompact(key *btcec.PrivateKey, hash []byte, isCompressedKey bool) ([]byte, error) { return secp_ecdsa.SignCompact(key, hash, isCompressedKey), nil @@ -224,7 +226,7 @@ func SignCompact(key *PrivateKey, hash []byte, // Koblitz curve in "curve". If the signature matches then the recovered public // key will be returned as well as a boolean if the original key was compressed // or not, else an error will be returned. -func RecoverCompact(signature, hash []byte) (*PublicKey, bool, error) { +func RecoverCompact(signature, hash []byte) (*btcec.PublicKey, bool, error) { return secp_ecdsa.RecoverCompact(signature, hash) } @@ -233,6 +235,6 @@ func RecoverCompact(signature, hash []byte) (*PublicKey, bool, error) { // given private key. The produced signature is deterministic (same message and // same key yield the same signature) and canonical in accordance with RFC6979 // and BIP0062. -func Sign(key *PrivateKey, hash []byte) *Signature { +func Sign(key *btcec.PrivateKey, hash []byte) *Signature { return secp_ecdsa.Sign(key, hash) } diff --git a/btcec/signature_test.go b/btcec/ecdsa/signature_test.go similarity index 92% rename from btcec/signature_test.go rename to btcec/ecdsa/signature_test.go index 74ea374784..d2eebdc788 100644 --- a/btcec/signature_test.go +++ b/btcec/ecdsa/signature_test.go @@ -1,8 +1,9 @@ // Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package btcec +package ecdsa import ( "bytes" @@ -12,6 +13,8 @@ import ( "fmt" "reflect" "testing" + + "github.com/btcsuite/btcd/btcec/v2" ) type signatureTest struct { @@ -344,9 +347,7 @@ func TestSignatures(t *testing.T) { if test.isValid { t.Errorf("%s signature failed when shouldn't %v", test.name, err) - } /* else { - t.Errorf("%s got error %v", test.name, err) - } */ + } continue } if !test.isValid { @@ -443,7 +444,7 @@ func TestSignatureSerialize(t *testing.T) { }, { "zero signature", - NewSignature(&ModNScalar{}, &ModNScalar{}), + NewSignature(&btcec.ModNScalar{}, &btcec.ModNScalar{}), []byte{0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00}, }, } @@ -458,9 +459,9 @@ func TestSignatureSerialize(t *testing.T) { } } -func testSignCompact(t *testing.T, tag string, curve *KoblitzCurve, +func testSignCompact(t *testing.T, tag string, curve *btcec.KoblitzCurve, data []byte, isCompressed bool) { - priv, _ := NewPrivateKey() + priv, _ := btcec.NewPrivateKey() hashed := []byte("testing") sig, err := SignCompact(priv, hashed, isCompressed) @@ -523,7 +524,7 @@ func TestSignCompact(t *testing.T) { continue } compressed := i%2 != 0 - testSignCompact(t, name, S256(), data, compressed) + testSignCompact(t, name, btcec.S256(), data, compressed) } } @@ -620,7 +621,7 @@ func TestRecoverCompact(t *testing.T) { } // Otherwise, ensure the correct public key was recovered. - exPub, _ := ParsePubKey(decodeHex(test.pub)) + exPub, _ := btcec.ParsePubKey(decodeHex(test.pub)) if !exPub.IsEqual(pub) { t.Errorf("unexpected recovered public key #%d: "+ "want %v, got %v", i, exPub, pub) @@ -679,11 +680,11 @@ func TestRFC6979(t *testing.T) { } for i, test := range tests { - privKey, _ := PrivKeyFromBytes(decodeHex(test.key)) + privKey, _ := btcec.PrivKeyFromBytes(decodeHex(test.key)) hash := sha256.Sum256([]byte(test.msg)) // Ensure deterministically generated nonce is the expected value. - gotNonce := NonceRFC6979(privKey.Serialize(), hash[:], nil, nil, 0).Bytes() + gotNonce := btcec.NonceRFC6979(privKey.Serialize(), hash[:], nil, nil, 0).Bytes() wantNonce := decodeHex(test.nonce) if !bytes.Equal(gotNonce[:], wantNonce) { t.Errorf("NonceRFC6979 #%d (%s): Nonce is incorrect: "+ @@ -726,3 +727,65 @@ func TestSignatureIsEqual(t *testing.T) { "equal to %v", sig1, sig2) } } + +func testSignAndVerify(t *testing.T, c *btcec.KoblitzCurve, tag string) { + priv, _ := btcec.NewPrivateKey() + pub := priv.PubKey() + + hashed := []byte("testing") + sig := Sign(priv, hashed) + + if !sig.Verify(hashed, pub) { + t.Errorf("%s: Verify failed", tag) + } + + hashed[0] ^= 0xff + if sig.Verify(hashed, pub) { + t.Errorf("%s: Verify always works!", tag) + } +} + +func TestSignAndVerify(t *testing.T) { + testSignAndVerify(t, btcec.S256(), "S256") +} + +func TestPrivKeys(t *testing.T) { + tests := []struct { + name string + key []byte + }{ + { + name: "check curve", + key: []byte{ + 0xea, 0xf0, 0x2c, 0xa3, 0x48, 0xc5, 0x24, 0xe6, + 0x39, 0x26, 0x55, 0xba, 0x4d, 0x29, 0x60, 0x3c, + 0xd1, 0xa7, 0x34, 0x7d, 0x9d, 0x65, 0xcf, 0xe9, + 0x3c, 0xe1, 0xeb, 0xff, 0xdc, 0xa2, 0x26, 0x94, + }, + }, + } + + for _, test := range tests { + priv, pub := btcec.PrivKeyFromBytes(test.key) + + _, err := btcec.ParsePubKey(pub.SerializeUncompressed()) + if err != nil { + t.Errorf("%s privkey: %v", test.name, err) + continue + } + + hash := []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9} + sig := Sign(priv, hash) + + if !sig.Verify(hash, pub) { + t.Errorf("%s could not verify: %v", test.name, err) + continue + } + + serializedKey := priv.Serialize() + if !bytes.Equal(serializedKey, test.key) { + t.Errorf("%s unexpected serialized bytes - got: %x, "+ + "want: %x", test.name, serializedKey, test.key) + } + } +} diff --git a/btcec/go.mod b/btcec/go.mod index 8f110664c1..53e4a1f5cb 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -7,3 +7,9 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 ) + +require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + +// We depend on chainhash as is, so we need to replace to use the version of +// chainhash included in the version of btcd we're building in. +replace github.com/btcsuite/btcd => ../ diff --git a/btcec/go.sum b/btcec/go.sum index f70838a70e..dcbbc98cc5 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -1,18 +1,12 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c h1:lnAMg3ra/Gw4AkRMxrxYs8nrprWsHowg8H9zaYsJOo4= -github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd/btcec/v2 v2.0.0/go.mod h1:vu+77Lro3alBlmsmlDnkZtgGiNo6OBwMHSb1XTGDwGo= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= @@ -20,65 +14,17 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcec/privkey_test.go b/btcec/privkey_test.go deleted file mode 100644 index 71a8bceaa1..0000000000 --- a/btcec/privkey_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2013-2016 The btcsuite developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. - -package btcec - -import ( - "bytes" - "testing" -) - -func TestPrivKeys(t *testing.T) { - tests := []struct { - name string - key []byte - }{ - { - name: "check curve", - key: []byte{ - 0xea, 0xf0, 0x2c, 0xa3, 0x48, 0xc5, 0x24, 0xe6, - 0x39, 0x26, 0x55, 0xba, 0x4d, 0x29, 0x60, 0x3c, - 0xd1, 0xa7, 0x34, 0x7d, 0x9d, 0x65, 0xcf, 0xe9, - 0x3c, 0xe1, 0xeb, 0xff, 0xdc, 0xa2, 0x26, 0x94, - }, - }, - } - - for _, test := range tests { - priv, pub := PrivKeyFromBytes(test.key) - - _, err := ParsePubKey(pub.SerializeUncompressed()) - if err != nil { - t.Errorf("%s privkey: %v", test.name, err) - continue - } - - hash := []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9} - sig := Sign(priv, hash) - - if !sig.Verify(hash, pub) { - t.Errorf("%s could not verify: %v", test.name, err) - continue - } - - serializedKey := priv.Serialize() - if !bytes.Equal(serializedKey, test.key) { - t.Errorf("%s unexpected serialized bytes - got: %x, "+ - "want: %x", test.name, serializedKey, test.key) - } - } -} diff --git a/btcutil/psbt/partialsig.go b/btcutil/psbt/partialsig.go index 26a6dc2d61..71cb63cdbf 100644 --- a/btcutil/psbt/partialsig.go +++ b/btcutil/psbt/partialsig.go @@ -4,6 +4,7 @@ import ( "bytes" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" ) // PartialSig encapsulate a (BTC public key, ECDSA signature) @@ -38,7 +39,7 @@ func validatePubkey(pubKey []byte) bool { // ECDSA signature, including the sighash flag. It does *not* of course // validate the signature against any message or public key. func validateSignature(sig []byte) bool { - _, err := btcec.ParseDERSignature(sig) + _, err := ecdsa.ParseDERSignature(sig) return err == nil } diff --git a/rpcserver.go b/rpcserver.go index b26074b33b..b8012b2b01 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -29,7 +29,7 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain/indexers" - "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" @@ -3520,7 +3520,7 @@ func handleSignMessageWithPrivKey(s *rpcServer, cmd interface{}, closeChan <-cha wire.WriteVarString(&buf, 0, c.Message) messageHash := chainhash.DoubleHashB(buf.Bytes()) - sig, err := btcec.SignCompact(wif.PrivKey, + sig, err := ecdsa.SignCompact(wif.PrivKey, messageHash, wif.CompressPubKey) if err != nil { return nil, &btcjson.RPCError{ @@ -3715,7 +3715,7 @@ func handleVerifyMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{ wire.WriteVarString(&buf, 0, messageSignatureHeader) wire.WriteVarString(&buf, 0, c.Message) expectedMessageHash := chainhash.DoubleHashB(buf.Bytes()) - pk, wasCompressed, err := btcec.RecoverCompact(sig, + pk, wasCompressed, err := ecdsa.RecoverCompact(sig, expectedMessageHash) if err != nil { // Mirror Bitcoin Core behavior, which treats error in diff --git a/txscript/opcode.go b/txscript/opcode.go index 708bb2370b..64e46fbf74 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -16,6 +16,7 @@ import ( "golang.org/x/crypto/ripemd160" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) @@ -1935,13 +1936,13 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { return nil } - var signature *btcec.Signature + var signature *ecdsa.Signature if vm.hasFlag(ScriptVerifyStrictEncoding) || vm.hasFlag(ScriptVerifyDERSignatures) { - signature, err = btcec.ParseDERSignature(sigBytes) + signature, err = ecdsa.ParseDERSignature(sigBytes) } else { - signature, err = btcec.ParseSignature(sigBytes) + signature, err = ecdsa.ParseSignature(sigBytes) } if err != nil { vm.dstack.PushBool(false) @@ -1989,7 +1990,7 @@ func opcodeCheckSigVerify(op *opcode, data []byte, vm *Engine) error { // the same signature multiple times when verifying a multisig. type parsedSigInfo struct { signature []byte - parsedSignature *btcec.Signature + parsedSignature *ecdsa.Signature parsed bool } @@ -2134,7 +2135,7 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { signature := rawSig[:len(rawSig)-1] // Only parse and check the signature encoding once. - var parsedSig *btcec.Signature + var parsedSig *ecdsa.Signature if !sigInfo.parsed { if err := vm.checkHashTypeEncoding(hashType); err != nil { return err @@ -2148,9 +2149,9 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { if vm.hasFlag(ScriptVerifyStrictEncoding) || vm.hasFlag(ScriptVerifyDERSignatures) { - parsedSig, err = btcec.ParseDERSignature(signature) + parsedSig, err = ecdsa.ParseDERSignature(signature) } else { - parsedSig, err = btcec.ParseSignature(signature) + parsedSig, err = ecdsa.ParseSignature(signature) } sigInfo.parsed = true if err != nil { diff --git a/txscript/pkscript.go b/txscript/pkscript.go index c5dd2a12a2..d89c244e41 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" @@ -20,7 +21,7 @@ const ( // Signature hash type (1 byte) // Public key length (1 byte) // Public key (33 byte) - minPubKeyHashSigScriptLen = 1 + btcec.MinSigLen + 1 + 1 + 33 + minPubKeyHashSigScriptLen = 1 + ecdsa.MinSigLen + 1 + 1 + 33 // maxPubKeyHashSigScriptLen is the maximum length of a signature script // that spends a P2PKH output. The length is composed of the following: diff --git a/txscript/sigcache.go b/txscript/sigcache.go index 959240c04d..fc9f627127 100644 --- a/txscript/sigcache.go +++ b/txscript/sigcache.go @@ -8,6 +8,7 @@ import ( "sync" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -18,7 +19,7 @@ import ( // match. In the occasion that two sigHashes collide, the newer sigHash will // simply overwrite the existing entry. type sigCacheEntry struct { - sig *btcec.Signature + sig *ecdsa.Signature pubKey *btcec.PublicKey } @@ -55,7 +56,7 @@ func NewSigCache(maxEntries uint) *SigCache { // // NOTE: This function is safe for concurrent access. Readers won't be blocked // unless there exists a writer, adding an entry to the SigCache. -func (s *SigCache) Exists(sigHash chainhash.Hash, sig *btcec.Signature, pubKey *btcec.PublicKey) bool { +func (s *SigCache) Exists(sigHash chainhash.Hash, sig *ecdsa.Signature, pubKey *btcec.PublicKey) bool { s.RLock() entry, ok := s.validSigs[sigHash] s.RUnlock() @@ -70,7 +71,7 @@ func (s *SigCache) Exists(sigHash chainhash.Hash, sig *btcec.Signature, pubKey * // // NOTE: This function is safe for concurrent access. Writers will block // simultaneous readers until function execution has concluded. -func (s *SigCache) Add(sigHash chainhash.Hash, sig *btcec.Signature, pubKey *btcec.PublicKey) { +func (s *SigCache) Add(sigHash chainhash.Hash, sig *ecdsa.Signature, pubKey *btcec.PublicKey) { s.Lock() defer s.Unlock() diff --git a/txscript/sigcache_test.go b/txscript/sigcache_test.go index f9e9f270ef..d0a3c4b973 100644 --- a/txscript/sigcache_test.go +++ b/txscript/sigcache_test.go @@ -9,13 +9,14 @@ import ( "testing" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg/chainhash" ) // genRandomSig returns a random message, a signature of the message under the // public key and the public key. This function is used to generate randomized // test data. -func genRandomSig() (*chainhash.Hash, *btcec.Signature, *btcec.PublicKey, error) { +func genRandomSig() (*chainhash.Hash, *ecdsa.Signature, *btcec.PublicKey, error) { privKey, err := btcec.NewPrivateKey() if err != nil { return nil, nil, nil, err @@ -26,7 +27,7 @@ func genRandomSig() (*chainhash.Hash, *btcec.Signature, *btcec.PublicKey, error) return nil, nil, nil, err } - sig := btcec.Sign(privKey, msgHash[:]) + sig := ecdsa.Sign(privKey, msgHash[:]) return &msgHash, sig, privKey.PubKey(), nil } @@ -46,7 +47,7 @@ func TestSigCacheAddExists(t *testing.T) { sigCache.Add(*msg1, sig1, key1) // The previously added triplet should now be found within the sigcache. - sig1Copy, _ := btcec.ParseSignature(sig1.Serialize()) + sig1Copy, _ := ecdsa.ParseSignature(sig1.Serialize()) key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) if !sigCache.Exists(*msg1, sig1Copy, key1Copy) { t.Errorf("previously added item not found in signature cache") @@ -70,7 +71,7 @@ func TestSigCacheAddEvictEntry(t *testing.T) { sigCache.Add(*msg, sig, key) - sigCopy, err := btcec.ParseSignature(sig.Serialize()) + sigCopy, err := ecdsa.ParseSignature(sig.Serialize()) if err != nil { t.Fatalf("unable to parse sig: %v", err) } @@ -105,7 +106,7 @@ func TestSigCacheAddEvictEntry(t *testing.T) { } // The entry added above should be found within the sigcache. - sigNewCopy, _ := btcec.ParseSignature(sigNew.Serialize()) + sigNewCopy, _ := ecdsa.ParseSignature(sigNew.Serialize()) keyNewCopy, _ := btcec.ParsePubKey(keyNew.SerializeCompressed()) if !sigCache.Exists(*msgNew, sigNewCopy, keyNewCopy) { t.Fatalf("previously added item not found in signature cache") @@ -128,7 +129,7 @@ func TestSigCacheAddMaxEntriesZeroOrNegative(t *testing.T) { sigCache.Add(*msg1, sig1, key1) // The generated triplet should not be found. - sig1Copy, _ := btcec.ParseSignature(sig1.Serialize()) + sig1Copy, _ := ecdsa.ParseSignature(sig1.Serialize()) key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) if sigCache.Exists(*msg1, sig1Copy, key1Copy) { t.Errorf("previously added signature found in sigcache, but" + diff --git a/txscript/sign.go b/txscript/sign.go index e5335ce366..f52214f371 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -7,6 +7,8 @@ package txscript import ( "errors" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" @@ -27,7 +29,7 @@ func RawTxInWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, return nil, err } - signature := btcec.Sign(key, hash) + signature := ecdsa.Sign(key, hash) return append(signature.Serialize(), byte(hashType)), nil } @@ -69,7 +71,7 @@ func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, if err != nil { return nil, err } - signature := btcec.Sign(key, hash) + signature := ecdsa.Sign(key, hash) return append(signature.Serialize(), byte(hashType)), nil } @@ -263,7 +265,7 @@ sigLoop: tSig := sig[:len(sig)-1] hashType := SigHashType(sig[len(sig)-1]) - pSig, err := btcec.ParseDERSignature(tSig) + pSig, err := ecdsa.ParseDERSignature(tSig) if err != nil { continue } From 3b3a6fc671b9e1cbc54d8c89aa7dfaf287fc7e75 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 4 Dec 2021 16:01:16 -0800 Subject: [PATCH 0598/1056] chaincfg: add BIP-340 tagged hash implementation In this commit, we add an implementation of the BIP-340 tagged hash scheme. This initial version can be optimized quite a bit, for example, we can hard code the output of frequently used `sha256(tag)` values and save two `sha256` invocations. --- chaincfg/chainhash/hash.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index 2b1cec022b..2859680fe8 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -6,6 +6,7 @@ package chainhash import ( + "crypto/sha256" "encoding/hex" "fmt" ) @@ -80,6 +81,32 @@ func NewHash(newHash []byte) (*Hash, error) { return &sh, err } +// TaggedHash implements the tagged hash scheme described in BIP-340. We use +// sha-256 to bind a message hash to a specific context using a tag: +// sha256(sha256(tag) || sha256(tag) || msg). +// +// TODO(roasbeef): add fast paths for common known tags +func TaggedHash(tag []byte, msgs ...[]byte) *Hash { + shaTag := sha256.Sum256(tag) + + // h = sha256(sha256(tag) || sha256(tag) || msg) + h := sha256.New() + h.Write(shaTag[:]) + h.Write(shaTag[:]) + + for _, msg := range msgs { + h.Write(msg) + } + + taggedHash := h.Sum(nil) + + // The function can't error out since the above hash is guaranteed to + // be 32 bytes. + hash, _ := NewHash(taggedHash) + + return hash +} + // NewHashFromStr creates a Hash from a hash string. The string should be // the hexadecimal string of a byte-reversed hash, but any missing characters // result in zero padding at the end of the Hash. From d6d38ad4aeff5af5e32dd0197b36809c957463a7 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 4 Dec 2021 16:03:12 -0800 Subject: [PATCH 0599/1056] btcec/v2/schnorr: add initial BIP-340 schnorr sig implementation In this commit, we add an initial implementation of BIP-340. Mirroring the recently added `ecsda` package, we create a new `schnorr` package with a unique `Signature` type and `ParsePubkey` function. The new `Signature` type implements the fixed-sized 64-byte signatures, and the `ParsePubkey` method only accepts pubkeys that are 32-bytes in length, with an implicit sign byte. The signing implementation by default, deviates from BIP-340 as it opts to use rfc6979 deterministic signatures by default, which means callers don't need to always pass in their own `auxNonce` randomness. A set of functional arguments allows callers to pass in their own value, which is the way all the included test vectors function. The other optional functional argument added is the `FastSign` option that allows callers to skip the final step of verifying each signature they generate. --- btcec/schnorr/error.go | 25 ++ btcec/schnorr/pubkey.go | 49 +++ btcec/schnorr/signature.go | 556 ++++++++++++++++++++++++++++++++ btcec/schnorr/signature_test.go | 256 +++++++++++++++ btcutil/go.sum | 17 - 5 files changed, 886 insertions(+), 17 deletions(-) create mode 100644 btcec/schnorr/error.go create mode 100644 btcec/schnorr/pubkey.go create mode 100644 btcec/schnorr/signature.go create mode 100644 btcec/schnorr/signature_test.go diff --git a/btcec/schnorr/error.go b/btcec/schnorr/error.go new file mode 100644 index 0000000000..4014339647 --- /dev/null +++ b/btcec/schnorr/error.go @@ -0,0 +1,25 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package schnorr + +import ( + ecdsa_schnorr "github.com/decred/dcrd/dcrec/secp256k1/v4/schnorr" +) + +// ErrorKind identifies a kind of error. It has full support for errors.Is +// and errors.As, so the caller can directly check against an error kind +// when determining the reason for an error. +type ErrorKind = ecdsa_schnorr.ErrorKind + +// Error identifies an error related to a schnorr signature. It has full +// support for errors.Is and errors.As, so the caller can ascertain the +// specific reason for the error by checking the underlying error. +type Error = ecdsa_schnorr.Error + +// signatureError creates an Error given a set of arguments. +func signatureError(kind ErrorKind, desc string) Error { + return Error{Err: kind, Description: desc} +} diff --git a/btcec/schnorr/pubkey.go b/btcec/schnorr/pubkey.go new file mode 100644 index 0000000000..f5d2ca4bd5 --- /dev/null +++ b/btcec/schnorr/pubkey.go @@ -0,0 +1,49 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package schnorr + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +// These constants define the lengths of serialized public keys. +const ( + PubKeyBytesLen = 32 +) + +// ParsePubKey parses a public key for a koblitz curve from a bytestring into a +// btcec.Publickey, verifying that it is valid. It only supports public keys in +// the BIP-340 32-byte format. +func ParsePubKey(pubKeyStr []byte) (*btcec.PublicKey, error) { + if pubKeyStr == nil { + err := fmt.Errorf("nil pubkey byte string") + return nil, err + } + if len(pubKeyStr) != PubKeyBytesLen { + err := fmt.Errorf("bad pubkey byte string size (want %v, have %v)", + PubKeyBytesLen, len(pubKeyStr)) + return nil, err + } + + // We'll manually prepend the compressed byte so we can re-use the + // existing pubkey parsing routine of the main btcec package. + var keyCompressed [btcec.PubKeyBytesLenCompressed]byte + keyCompressed[0] = secp.PubKeyFormatCompressedEven + copy(keyCompressed[1:], pubKeyStr) + + return btcec.ParsePubKey(keyCompressed[:]) +} + +// SerializePubKey serializes a public key as specified by BIP 340. Public keys +// in this format are 32 bytes in length, and are assumed to have an even y +// coordinate. +func SerializePubKey(pub *btcec.PublicKey) []byte { + pBytes := pub.SerializeCompressed() + return pBytes[1:] +} diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go new file mode 100644 index 0000000000..d6be341a8e --- /dev/null +++ b/btcec/schnorr/signature.go @@ -0,0 +1,556 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package schnorr + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/chaincfg/chainhash" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" + ecdsa_schnorr "github.com/decred/dcrd/dcrec/secp256k1/v4/schnorr" +) + +const ( + // SignatureSize is the size of an encoded Schnorr signature. + SignatureSize = 64 + + // scalarSize is the size of an encoded big endian scalar. + scalarSize = 32 +) + +var ( + tagHashAux = []byte("BIP0340/aux") + + tagHashNonce = []byte("BIP0340/nonce") + + tagHashChallenge = []byte("BIP0340/challenge") +) + +var ( + // rfc6979ExtraDataV0 is the extra data to feed to RFC6979 when + // generating the deterministic nonce for the BIP-340 scheme. This + // ensures the same nonce is not generated for the same message and key + // as for other signing algorithms such as ECDSA. + // + // It is equal to SHA-256([]byte("BIP-340")). + rfc6979ExtraDataV0 = [32]uint8{ + 0xa3, 0xeb, 0x4c, 0x18, 0x2f, 0xae, 0x7e, 0xf4, + 0xe8, 0x10, 0xc6, 0xee, 0x13, 0xb0, 0xe9, 0x26, + 0x68, 0x6d, 0x71, 0xe8, 0x7f, 0x39, 0x4f, 0x79, + 0x9c, 0x00, 0xa5, 0x21, 0x03, 0xcb, 0x4e, 0x17, + } +) + +// Signature is a type representing a Schnorr signature. +type Signature struct { + r btcec.FieldVal + s btcec.ModNScalar +} + +// NewSignature instantiates a new signature given some r and s values. +func NewSignature(r *btcec.FieldVal, s *btcec.ModNScalar) *Signature { + var sig Signature + sig.r.Set(r).Normalize() + sig.s.Set(s) + return &sig +} + +// Serialize returns the Schnorr signature in the more strict format. +// +// The signatures are encoded as +// sig[0:32] x coordinate of the point R, encoded as a big-endian uint256 +// sig[32:64] s, encoded also as big-endian uint256 +func (sig Signature) Serialize() []byte { + // Total length of returned signature is the length of r and s. + var b [SignatureSize]byte + sig.r.PutBytesUnchecked(b[0:32]) + sig.s.PutBytesUnchecked(b[32:64]) + return b[:] +} + +// ParseSignature parses a signature according to the BIP-340 specification and +// enforces the following additional restrictions specific to secp256k1: +// +// - The r component must be in the valid range for secp256k1 field elements +// - The s component must be in the valid range for secp256k1 scalars +func ParseSignature(sig []byte) (*Signature, error) { + // The signature must be the correct length. + sigLen := len(sig) + if sigLen < SignatureSize { + str := fmt.Sprintf("malformed signature: too short: %d < %d", sigLen, + SignatureSize) + return nil, signatureError(ecdsa_schnorr.ErrSigTooShort, str) + } + if sigLen > SignatureSize { + str := fmt.Sprintf("malformed signature: too long: %d > %d", sigLen, + SignatureSize) + return nil, signatureError(ecdsa_schnorr.ErrSigTooLong, str) + } + + // The signature is validly encoded at this point, however, enforce + // additional restrictions to ensure r is in the range [0, p-1], and s is in + // the range [0, n-1] since valid Schnorr signatures are required to be in + // that range per spec. + var r btcec.FieldVal + if overflow := r.SetByteSlice(sig[0:32]); overflow { + str := "invalid signature: r >= field prime" + return nil, signatureError(ecdsa_schnorr.ErrSigRTooBig, str) + } + var s btcec.ModNScalar + if overflow := s.SetByteSlice(sig[32:64]); overflow { + str := "invalid signature: s >= group order" + return nil, signatureError(ecdsa_schnorr.ErrSigSTooBig, str) + } + + // Return the signature. + return NewSignature(&r, &s), nil +} + +// IsEqual compares this Signature instance to the one passed, returning true +// if both Signatures are equivalent. A signature is equivalent to another, if +// they both have the same scalar value for R and S. +func (sig Signature) IsEqual(otherSig *Signature) bool { + return sig.r.Equals(&otherSig.r) && sig.s.Equals(&otherSig.s) +} + +// schnorrVerify attempt to verify the signature for the provided hash and +// secp256k1 public key and either returns nil if successful or a specific error +// indicating why it failed if not successful. +// +// This differs from the exported Verify method in that it returns a specific +// error to support better testing while the exported method simply returns a +// bool indicating success or failure. +func schnorrVerify(sig *Signature, hash []byte, pubKeyBytes []byte) error { + // The algorithm for producing a BIP-340 signature is described in + // README.md and is reproduced here for reference: + // + // 1. Fail if m is not 32 bytes + // 2. P = lift_x(int(pk)). + // 3. r = int(sig[0:32]); fail is r >= p. + // 4. s = int(sig[32:64]); fail if s >= n. + // 5. e = int(tagged_hash("BIP0340/challenge", bytes(r) || bytes(P) || M)) mod n. + // 6. R = s*G - e*P + // 7. Fail if is_infinite(R) + // 8. Fail if not hash_even_y(R) + // 9. Fail is x(R) != r. + // 10. Return success iff not failure occured before reachign this + // point. + + // Step 1. + // + // Fail if m is not 32 bytes + if len(hash) != scalarSize { + str := fmt.Sprintf("wrong size for message (got %v, want %v)", + len(hash), scalarSize) + return signatureError(ecdsa_schnorr.ErrInvalidHashLen, str) + } + + // Step 2. + // + // P = lift_x(int(pk)) + // + // Fail if P is not a point on the curve + pubKey, err := ParsePubKey(pubKeyBytes) + if err != nil { + return err + } + if !pubKey.IsOnCurve() { + str := "pubkey point is not on curve" + return signatureError(ecdsa_schnorr.ErrPubKeyNotOnCurve, str) + } + + // Step 3. + // + // Fail if r >= p + // + // Note this is already handled by the fact r is a field element. + + // Step 4. + // + // Fail if s >= n + // + // Note this is already handled by the fact s is a mod n scalar. + + // Step 5. + // + // e = int(tagged_hash("BIP0340/challenge", bytes(r) || bytes(P) || M)) mod n. + var rBytes [32]byte + sig.r.PutBytesUnchecked(rBytes[:]) + pBytes := SerializePubKey(pubKey) + + commitment := chainhash.TaggedHash( + tagHashChallenge, rBytes[:], pBytes, hash, + ) + + var e btcec.ModNScalar + if overflow := e.SetBytes((*[32]byte)(commitment)); overflow != 0 { + str := "hash of (r || P || m) too big" + return signatureError(ecdsa_schnorr.ErrSchnorrHashValue, str) + } + + // Negate e here so we can use AddNonConst below to subtract the s*G + // point from e*P. + e.Negate() + + // Step 6. + // + // R = s*G - e*P + var P, R, sG, eP btcec.JacobianPoint + pubKey.AsJacobian(&P) + btcec.ScalarBaseMultNonConst(&sig.s, &sG) + btcec.ScalarMultNonConst(&e, &P, &eP) + btcec.AddNonConst(&sG, &eP, &R) + + // Step 7. + // + // Fail if R is the point at infinity + if (R.X.IsZero() && R.Y.IsZero()) || R.Z.IsZero() { + str := "calculated R point is the point at infinity" + return signatureError(ecdsa_schnorr.ErrSigRNotOnCurve, str) + } + + // Step 8. + // + // Fail if R.y is odd + // + // Note that R must be in affine coordinates for this check. + R.ToAffine() + if R.Y.IsOdd() { + str := "calculated R y-value is odd" + return signatureError(ecdsa_schnorr.ErrSigRYIsOdd, str) + } + + // Step 9. + // + // Verified if R.x == r + // + // Note that R must be in affine coordinates for this check. + if !sig.r.Equals(&R.X) { + str := "calculated R point was not given R" + return signatureError(ecdsa_schnorr.ErrUnequalRValues, str) + } + + // Step 10. + // + // Return success iff not failure occured before reachign this + return nil +} + +// Verify returns whether or not the signature is valid for the provided hash +// and secp256k1 public key. +func (sig *Signature) Verify(hash []byte, pubKey *btcec.PublicKey) bool { + pubkeyBytes := SerializePubKey(pubKey) + return schnorrVerify(sig, hash, pubkeyBytes) == nil +} + +// zeroArray zeroes the memory of a scalar array. +func zeroArray(a *[scalarSize]byte) { + for i := 0; i < scalarSize; i++ { + a[i] = 0x00 + } +} + +// schnorrSign generates an BIP-340 signature over the secp256k1 curve for the +// provided hash (which should be the result of hashing a larger message) using +// the given nonce and private key. The produced signature is deterministic +// (same message, nonce, and key yield the same signature) and canonical. +// +// WARNING: The hash MUST be 32 bytes and both the nonce and private keys must +// NOT be 0. Since this is an internal use function, these preconditions MUST +// be satisified by the caller. +func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash []byte, + opts *signOptions) (*Signature, error) { + + // The algorithm for producing a BIP-340 signature is described in + // README.md and is reproduced here for reference: + // + // G = curve generator + // n = curve order + // d = private key + // m = message + // a = input randmoness + // r, s = signature + // + // 1. d' = int(d) + // 2. Fail if m is not 32 bytes + // 3. Fail if d = 0 or d >= n + // 4. P = d'*G + // 5. Negate d if P.y is odd + // 6. t = bytes(d) xor tagged_hash("BIP0340/aux", t || bytes(P) || m) + // 7. rand = tagged_hash("BIP0340/nonce", a) + // 8. k' = int(rand) mod n + // 9. Fail if k' = 0 + // 10. R = 'k*G + // 11. Negate k if R.y id odd + // 12. e = tagged_hash("BIP0340/challenge", bytes(R) || bytes(P) || m) mod n + // 13. sig = bytes(R) || bytes((k + e*d)) mod n + // 14. If Verify(bytes(P), m, sig) fails, abort. + // 15. return sig. + // + // Note that the set of functional options passed in may modify the + // above algorithm. Namely if CustomNonce is used, then steps 6-8 are + // replaced with a process that generates the nonce using rfc6679. If + // FastSign is passed, then we skip set 14. + + // NOTE: Steps 1-9 are performed by the caller. + + // + // Step 10. + // + // R = kG + var R btcec.JacobianPoint + k := *nonce + btcec.ScalarBaseMultNonConst(&k, &R) + + // Step 11. + // + // Negate nonce k if R.y is odd (R.y is the y coordinate of the point R) + // + // Note that R must be in affine coordinates for this check. + R.ToAffine() + if R.Y.IsOdd() { + k.Negate() + } + + // Step 12. + // + // e = tagged_hash("BIP0340/challenge", bytes(R) || bytes(P) || m) mod n + var rBytes [32]byte + r := &R.X + r.PutBytesUnchecked(rBytes[:]) + pBytes := SerializePubKey(pubKey) + + commitment := chainhash.TaggedHash( + tagHashChallenge, rBytes[:], pBytes, hash, + ) + + var e btcec.ModNScalar + if overflow := e.SetBytes((*[32]byte)(commitment)); overflow != 0 { + k.Zero() + str := "hash of (r || P || m) too big" + return nil, signatureError(ecdsa_schnorr.ErrSchnorrHashValue, str) + } + + // Step 13. + // + // s = k + e*d mod n + s := new(btcec.ModNScalar).Mul2(&e, privKey).Add(&k) + k.Zero() + + sig := NewSignature(r, s) + + // Step 14. + // + // If Verify(bytes(P), m, sig) fails, abort. + if !opts.fastSign { + if err := schnorrVerify(sig, hash, pBytes); err != nil { + return nil, err + } + } + + // Step 15. + // + // Return (r, s) + return sig, nil +} + +// SignOption is a functional option arguemnt that allows callers to modify the +// way we generate BIP-340 schnorr signatues. +type SignOption func(*signOptions) + +// signOptions houses the set of functional options that can be used to modify +// the method used to generate the BIP-340 signature. +type signOptions struct { + // fastSign determines if we'll skip the check at the end of the routine + // where we attempt to verify the produced signature. + fastSign bool + + // authNonce allows the user to pass in their own nonce information, which + // is useful for schemes like mu-sig. + authNonce *[32]byte +} + +// defaultSignOptions returns the default set of signing operations. +func defaultSignOptions() *signOptions { + return &signOptions{} +} + +// FastSign forces signing to skip the extra verification step at the end. +// Peformance sensitive applications may opt to use this option to speed up the +// signing operation. +func FastSign() SignOption { + return func(o *signOptions) { + o.fastSign = true + } +} + +// CustomNonce allows users to pass in a custom set of auxData that's used as +// input randomness to generate the nonce used during signing. Users may want +// to specify this custom value when using multi-signatures schemes such as +// Mu-Sig2. If this option isn't set, then rfc6979 will be used to generate the +// nonce material. +func CustomNonce(auxData [32]byte) SignOption { + return func(o *signOptions) { + o.authNonce = &auxData + } +} + +// Sign generates an BIP-340 signature over the secp256k1 curve for the +// provided hash (which should be the result of hashing a larger message) using +// the given private key. The produced signature is deterministic (same +// message and same key yield the same signature) and canonical. +// +// Note that the current signing implementation has a few remaining variable +// time aspects which make use of the private key and the generated nonce, +// which can expose the signer to constant time attacks. As a result, this +// function should not be used in situations where there is the possibility of +// someone having EM field/cache/etc access. +func Sign(privKey *btcec.PrivateKey, hash []byte, + signOpts ...SignOption) (*Signature, error) { + + // First, parse the set of optional signing options. + opts := defaultSignOptions() + for _, option := range signOpts { + option(opts) + } + + // The algorithm for producing a BIP-340 signature is described in + // README.md and is reproduced here for reference: + // + // G = curve generator + // n = curve order + // d = private key + // m = message + // a = input randmoness + // r, s = signature + // + // 1. d' = int(d) + // 2. Fail if m is not 32 bytes + // 3. Fail if d = 0 or d >= n + // 4. P = d'*G + // 5. Negate d if P.y is odd + // 6. t = bytes(d) xor tagged_hash("BIP0340/aux", t || bytes(P) || m) + // 7. rand = tagged_hash("BIP0340/nonce", a) + // 8. k' = int(rand) mod n + // 9. Fail if k' = 0 + // 10. R = 'k*G + // 11. Negate k if R.y id odd + // 12. e = tagged_hash("BIP0340/challenge", bytes(R) || bytes(P) || mod) mod n + // 13. sig = bytes(R) || bytes((k + e*d)) mod n + // 14. If Verify(bytes(P), m, sig) fails, abort. + // 15. return sig. + // + // Note that the set of functional options passed in may modify the + // above algorithm. Namely if CustomNonce is used, then steps 6-8 are + // replaced with a process that generates the nonce using rfc6679. If + // FastSign is passed, then we skip set 14. + + // Step 1. + // + // d' = int(d) + privKeyScalar := &privKey.Key + + // Step 2. + // + // Fail if m is not 32 bytes + if len(hash) != scalarSize { + str := fmt.Sprintf("wrong size for message hash (got %v, want %v)", + len(hash), scalarSize) + return nil, signatureError(ecdsa_schnorr.ErrInvalidHashLen, str) + } + + // Step 3. + // + // Fail if d = 0 or d >= n + if privKeyScalar.IsZero() { + str := "private key is zero" + return nil, signatureError(ecdsa_schnorr.ErrPrivateKeyIsZero, str) + } + + // Step 4. + // + // P = 'd*G + pub := privKey.PubKey() + + // Step 5. + // + // Negate d if P.y is odd. + pubKeyBytes := pub.SerializeCompressed() + if pubKeyBytes[0] == secp.PubKeyFormatCompressedOdd { + privKeyScalar.Negate() + } + + // At this point, we check to see if a CustomNonce has been passed in, + // and if so, then we'll deviate from the main routine here by + // generating the nonce value as specifid by BIP-0340. + if opts.authNonce != nil { + // Step 6. + // + // t = bytes(d) xor tagged_hash("BIP0340/aux", a) + privBytes := privKeyScalar.Bytes() + t := chainhash.TaggedHash(tagHashAux, (*opts.authNonce)[:]) + for i := 0; i < len(t); i++ { + t[i] ^= privBytes[i] + } + + // Step 7. + // + // rand = tagged_hash("BIP0340/nonce", t || bytes(P) || m) + // + // We snip off the first byte of the serialized pubkey, as we + // only need the x coordinate and not the market byte. + rand := chainhash.TaggedHash( + tagHashNonce, t[:], pubKeyBytes[1:], hash, + ) + + // Step 8. + // + // k'= int(rand) mod n + var kPrime btcec.ModNScalar + kPrime.SetBytes((*[32]byte)(rand)) + + // Step 9. + // + // Fail if k' = 0 + if kPrime.IsZero() { + str := fmt.Sprintf("generated nonce is zero") + return nil, signatureError(ecdsa_schnorr.ErrSchnorrHashValue, str) + } + + sig, err := schnorrSign(privKeyScalar, &kPrime, pub, hash, opts) + kPrime.Zero() + if err != nil { + return nil, err + } + + return sig, nil + } + + var privKeyBytes [scalarSize]byte + privKeyScalar.PutBytes(&privKeyBytes) + defer zeroArray(&privKeyBytes) + for iteration := uint32(0); ; iteration++ { + // Step 6-9. + // + // Use RFC6979 to generate a deterministic nonce k in [1, n-1] + // parameterized by the private key, message being signed, extra data + // that identifies the scheme, and an iteration count + k := btcec.NonceRFC6979( + privKeyBytes[:], hash, rfc6979ExtraDataV0[:], nil, iteration, + ) + + // Steps 10-15. + sig, err := schnorrSign(privKeyScalar, k, pub, hash, opts) + k.Zero() + if err != nil { + // Try again with a new nonce. + continue + } + + return sig, nil + } +} diff --git a/btcec/schnorr/signature_test.go b/btcec/schnorr/signature_test.go new file mode 100644 index 0000000000..b99614ff6c --- /dev/null +++ b/btcec/schnorr/signature_test.go @@ -0,0 +1,256 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package schnorr + +import ( + "encoding/hex" + "errors" + "strings" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + secp_ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4" + ecdsa_schnorr "github.com/decred/dcrd/dcrec/secp256k1/v4/schnorr" +) + +type bip340Test struct { + secretKey string + publicKey string + auxRand string + message string + signature string + verifyResult bool + validPubKey bool + expectErr error + rfc6979 bool +} + +var bip340TestVectors = []bip340Test{ + { + secretKey: "0000000000000000000000000000000000000000000000000000000000000003", + publicKey: "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + auxRand: "0000000000000000000000000000000000000000000000000000000000000000", + message: "0000000000000000000000000000000000000000000000000000000000000000", + signature: "04E7F9037658A92AFEB4F25BAE5339E3DDCA81A353493827D26F16D92308E49E2A25E92208678A2DF86970DA91B03A8AF8815A8A60498B358DAF560B347AA557", + verifyResult: true, + validPubKey: true, + rfc6979: true, + }, + { + secretKey: "0000000000000000000000000000000000000000000000000000000000000003", + publicKey: "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + auxRand: "0000000000000000000000000000000000000000000000000000000000000000", + message: "0000000000000000000000000000000000000000000000000000000000000000", + signature: "E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0", + verifyResult: true, + validPubKey: true, + }, + { + secretKey: "B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF", + publicKey: "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + auxRand: "0000000000000000000000000000000000000000000000000000000000000001", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A", + verifyResult: true, + validPubKey: true, + }, + { + secretKey: "C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9", + publicKey: "DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8", + auxRand: "C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906", + message: "7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C", + signature: "5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB745879A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7", + verifyResult: true, + validPubKey: true, + }, + { + secretKey: "0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710", + publicKey: "25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517", + auxRand: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + message: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + signature: "7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3", + verifyResult: true, + validPubKey: true, + }, + { + publicKey: "D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9", + message: "4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703", + signature: "00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB1548AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4", + verifyResult: true, + validPubKey: true, + }, + { + publicKey: "EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B", + verifyResult: false, + validPubKey: false, + expectErr: secp_ecdsa.ErrPubKeyNotOnCurve, + }, + { + publicKey: "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC27944640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2", + verifyResult: false, + validPubKey: true, + expectErr: ecdsa_schnorr.ErrSigRYIsOdd, + }, + { + publicKey: "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD", + verifyResult: false, + validPubKey: true, + expectErr: ecdsa_schnorr.ErrSigRYIsOdd, + }, + { + publicKey: "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6", + verifyResult: false, + validPubKey: true, + expectErr: ecdsa_schnorr.ErrUnequalRValues, + }, + { + publicKey: "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "0000000000000000000000000000000000000000000000000000000000000000123DDA8328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051", + verifyResult: false, + validPubKey: true, + expectErr: ecdsa_schnorr.ErrSigRNotOnCurve, + }, + { + publicKey: "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "00000000000000000000000000000000000000000000000000000000000000017615FBAF5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197", + verifyResult: false, + validPubKey: true, + expectErr: ecdsa_schnorr.ErrSigRNotOnCurve, + }, + { + publicKey: "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B", + verifyResult: false, + validPubKey: true, + expectErr: ecdsa_schnorr.ErrUnequalRValues, + }, + { + publicKey: "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30", + message: "243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", + signature: "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B", + verifyResult: false, + validPubKey: false, + expectErr: secp_ecdsa.ErrPubKeyXTooBig, + }, +} + +// decodeHex decodes the passed hex string and returns the resulting bytes. It +// panics if an error occurs. This is only used in the tests as a helper since +// the only way it can fail is if there is an error in the test source code. +func decodeHex(hexStr string) []byte { + b, err := hex.DecodeString(hexStr) + if err != nil { + panic("invalid hex string in test source: err " + err.Error() + + ", hex: " + hexStr) + } + + return b +} + +func TestSchnorrSign(t *testing.T) { + t.Parallel() + + for i, test := range bip340TestVectors { + if len(test.secretKey) == 0 { + continue + } + + d := decodeHex(test.secretKey) + privKey, _ := btcec.PrivKeyFromBytes(d) + + var auxBytes [32]byte + aux := decodeHex(test.auxRand) + copy(auxBytes[:], aux) + + msg := decodeHex(test.message) + + var signOpts []SignOption + if !test.rfc6979 { + signOpts = []SignOption{CustomNonce(auxBytes)} + } + + sig, err := Sign(privKey, msg, signOpts...) + if err != nil { + t.Fatalf("test #%v: sig generation failed: %v", i, err) + } + + if strings.ToUpper(hex.EncodeToString(sig.Serialize())) != test.signature { + t.Fatalf("test #%v: got signature %x : "+ + "want %s", i, sig.Serialize(), test.signature) + } + + pubKeyBytes := decodeHex(test.publicKey) + err = schnorrVerify(sig, msg, pubKeyBytes) + if err != nil { + t.Fail() + } + + verify := err == nil + if test.verifyResult != verify { + t.Fatalf("test #%v: verification mismatch: "+ + "expected %v, got %v", i, test.verifyResult, verify) + } + } +} + +func TestSchnorrVerify(t *testing.T) { + t.Parallel() + + for i, test := range bip340TestVectors { + + pubKeyBytes := decodeHex(test.publicKey) + + _, err := ParsePubKey(pubKeyBytes) + switch { + case !test.validPubKey && err != nil: + if !errors.Is(err, test.expectErr) { + t.Fatalf("test #%v: pubkey validation should "+ + "have failed, expected %v, got %v", i, + test.expectErr, err) + } + + continue + + case err != nil: + t.Fatalf("test #%v: unable to parse pubkey: %v", i, err) + } + + msg := decodeHex(test.message) + + sig, err := ParseSignature(decodeHex(test.signature)) + if err != nil { + t.Fatalf("unable to parse sig: %v", err) + } + + err = schnorrVerify(sig, msg, pubKeyBytes) + if err != nil && test.verifyResult { + t.Fatalf("test #%v: verification shouldn't have failed: %v", i, err) + } + + verify := err == nil + if test.verifyResult != verify { + t.Fatalf("test #%v: verificaiton mismatch: expected "+ + "%v, got %v", i, test.verifyResult, verify) + } + + if !test.verifyResult && test.expectErr != nil { + if !errors.Is(err, test.expectErr) { + t.Fatalf("test #%v: expect error %v : got %v", i, test.expectErr, err) + } + } + } +} diff --git a/btcutil/go.sum b/btcutil/go.sum index ac96abce84..e67b3253c3 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -16,20 +16,3 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 0bbc8310402a239b7e8adccce9950bafd095cb3e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 26 Jan 2022 17:26:25 -0800 Subject: [PATCH 0600/1056] build: run go mod tidy to refresh go.sum for btcutil --- btcutil/go.sum | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/btcutil/go.sum b/btcutil/go.sum index e67b3253c3..ac96abce84 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -16,3 +16,20 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 973fb3760099752cf242f1344036ceca7ba6131d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 31 Jan 2022 14:39:32 -0800 Subject: [PATCH 0601/1056] btcec/schnorr: add benchmarks for sign/verify Benchmarks run w/o fast sign (always verify after you generate a sig): ``` goos: darwin goarch: amd64 pkg: github.com/btcsuite/btcd/btcec/v2/schnorr cpu: VirtualApple @ 2.50GHz BenchmarkSigVerify-8 8000 152468 ns/op 960 B/op 16 allocs/op BenchmarkSign-8 4939 215489 ns/op 1408 B/op 27 allocs/op BenchmarkSignRfc6979-8 5106 217416 ns/op 2129 B/op 37 allocs/op PASS ok github.com/btcsuite/btcd/btcec/v2/schnorr 4.629s ``` Benchmarks w/ fast sign: ``` goos: darwin goarch: amd64 pkg: github.com/btcsuite/btcd/btcec/v2/schnorr cpu: VirtualApple @ 2.50GHz BenchmarkSigVerify-8 7982 142826 ns/op 960 B/op 16 allocs/op BenchmarkSign-8 18210 65908 ns/op 496 B/op 12 allocs/op BenchmarkSignRfc6979-8 16537 78161 ns/op 1216 B/op 22 allocs/op PASS ok github.com/btcsuite/btcd/btcec/v2/schnorr 5.418s ``` --- btcec/schnorr/bench_test.go | 169 ++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 btcec/schnorr/bench_test.go diff --git a/btcec/schnorr/bench_test.go b/btcec/schnorr/bench_test.go new file mode 100644 index 0000000000..4dadbb1fd6 --- /dev/null +++ b/btcec/schnorr/bench_test.go @@ -0,0 +1,169 @@ +// Copyright 2013-2016 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package schnorr + +import ( + "crypto/sha256" + "encoding/hex" + "math/big" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +// hexToBytes converts the passed hex string into bytes and will panic if there +// is an error. This is only provided for the hard-coded constants so errors in +// the source code can be detected. It will only (and must only) be called with +// hard-coded values. +func hexToBytes(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + return b +} + +// hexToModNScalar converts the passed hex string into a ModNScalar and will +// panic if there is an error. This is only provided for the hard-coded +// constants so errors in the source code can be detected. It will only (and +// must only) be called with hard-coded values. +func hexToModNScalar(s string) *btcec.ModNScalar { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + var scalar btcec.ModNScalar + if overflow := scalar.SetByteSlice(b); overflow { + panic("hex in source file overflows mod N scalar: " + s) + } + return &scalar +} + +// hexToFieldVal converts the passed hex string into a FieldVal and will panic +// if there is an error. This is only provided for the hard-coded constants so +// errors in the source code can be detected. It will only (and must only) be +// called with hard-coded values. +func hexToFieldVal(s string) *btcec.FieldVal { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + var f btcec.FieldVal + if overflow := f.SetByteSlice(b); overflow { + panic("hex in source file overflows mod P: " + s) + } + return &f +} + +// fromHex converts the passed hex string into a big integer pointer and will +// panic is there is an error. This is only provided for the hard-coded +// constants so errors in the source code can bet detected. It will only (and +// must only) be called for initialization purposes. +func fromHex(s string) *big.Int { + if s == "" { + return big.NewInt(0) + } + r, ok := new(big.Int).SetString(s, 16) + if !ok { + panic("invalid hex in source file: " + s) + } + return r +} + +var testOk bool + +// BenchmarkSigVerify benchmarks how long it takes the secp256k1 curve to +// verify signatures. +func BenchmarkSigVerify(b *testing.B) { + // Randomly generated keypair. + d := hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d") + + privKey := secp256k1.NewPrivateKey(d) + pubKey := privKey.PubKey() + + // Double sha256 of []byte{0x01, 0x02, 0x03, 0x04} + msgHash := sha256.Sum256([]byte("benchmark")) + sig, err := Sign(privKey, msgHash[:]) + if err != nil { + b.Fatalf("unable to sign: %v", err) + } + + if !sig.Verify(msgHash[:], pubKey) { + b.Errorf("Signature failed to verify") + return + } + + var ok bool + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + ok = sig.Verify(msgHash[:], pubKey) + } + + testOk = ok +} + +// Used to ensure the compiler doesn't optimize away the benchmark. +var ( + testSig *Signature + testErr error +) + +// BenchmarkSign benchmarks how long it takes to sign a message. +func BenchmarkSign(b *testing.B) { + // Randomly generated keypair. + d := hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d") + privKey := secp256k1.NewPrivateKey(d) + + // blake256 of []byte{0x01, 0x02, 0x03, 0x04}. + msgHash := hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7") + + var auxBytes [32]byte + copy(auxBytes[:], msgHash) + auxBytes[0] ^= 1 + + var ( + sig *Signature + err error + ) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + sig, err = Sign( + privKey, msgHash, CustomNonce(auxBytes), FastSign(), + ) + } + + testSig = sig + testErr = err +} + +// BenchmarkSignRfc6979 benchmarks how long it takes to sign a message. +func BenchmarkSignRfc6979(b *testing.B) { + // Randomly generated keypair. + d := hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d") + privKey := secp256k1.NewPrivateKey(d) + + // blake256 of []byte{0x01, 0x02, 0x03, 0x04}. + msgHash := hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7") + + var ( + sig *Signature + err error + ) + + b.ReportAllocs() + b.ResetTimer() + for i := 0; i < b.N; i++ { + sig, err = Sign(privKey, msgHash, FastSign()) + } + + testSig = sig + testErr = err +} From b7a4622a6b75b412be1e0acf72f2081eb4b19957 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 31 Jan 2022 14:54:12 -0800 Subject: [PATCH 0602/1056] btcec+chaincfg: use pre-computed tag hash values In this commit, we optimize our signature implementation slightly, by defining pre-computed sha256(tag) variables for the commonly used values. If a tag matches this, then we'll use that hash value to avoid an extra round of hashing. --- btcec/schnorr/signature.go | 18 ++++++------------ chaincfg/chainhash/hash.go | 28 +++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index d6be341a8e..ed4b9cb5bf 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -22,14 +22,6 @@ const ( scalarSize = 32 ) -var ( - tagHashAux = []byte("BIP0340/aux") - - tagHashNonce = []byte("BIP0340/nonce") - - tagHashChallenge = []byte("BIP0340/challenge") -) - var ( // rfc6979ExtraDataV0 is the extra data to feed to RFC6979 when // generating the deterministic nonce for the BIP-340 scheme. This @@ -183,7 +175,7 @@ func schnorrVerify(sig *Signature, hash []byte, pubKeyBytes []byte) error { pBytes := SerializePubKey(pubKey) commitment := chainhash.TaggedHash( - tagHashChallenge, rBytes[:], pBytes, hash, + chainhash.TagBIP0340Challenge, rBytes[:], pBytes, hash, ) var e btcec.ModNScalar @@ -325,7 +317,7 @@ func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash pBytes := SerializePubKey(pubKey) commitment := chainhash.TaggedHash( - tagHashChallenge, rBytes[:], pBytes, hash, + chainhash.TagBIP0340Challenge, rBytes[:], pBytes, hash, ) var e btcec.ModNScalar @@ -492,7 +484,9 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, // // t = bytes(d) xor tagged_hash("BIP0340/aux", a) privBytes := privKeyScalar.Bytes() - t := chainhash.TaggedHash(tagHashAux, (*opts.authNonce)[:]) + t := chainhash.TaggedHash( + chainhash.TagBIP0340Aux, (*opts.authNonce)[:], + ) for i := 0; i < len(t); i++ { t[i] ^= privBytes[i] } @@ -504,7 +498,7 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, // We snip off the first byte of the serialized pubkey, as we // only need the x coordinate and not the market byte. rand := chainhash.TaggedHash( - tagHashNonce, t[:], pubKeyBytes[1:], hash, + chainhash.TagBIP0340Nonce, t[:], pubKeyBytes[1:], hash, ) // Step 8. diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index 2859680fe8..b7a2d8a7f8 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -17,6 +17,25 @@ const HashSize = 32 // MaxHashStringSize is the maximum length of a Hash hash string. const MaxHashStringSize = HashSize * 2 +var ( + // TagBIP0340Challenge is the BIP-0340 tag for challenges. + TagBIP0340Challenge = []byte("BIP0340/challenge") + + // TagBIP0340Aux is the BIP-0340 tag for aux data. + TagBIP0340Aux = []byte("BIP0340/aux") + + // TagBIP0340Nonce is the BIP-0340 tag for nonces. + TagBIP0340Nonce = []byte("BIP0340/nonce") + + // precomputedTags is a map containing the SHA-256 hash of the BIP-0340 + // tags. + precomputedTags = map[string]Hash{ + string(TagBIP0340Challenge): sha256.Sum256(TagBIP0340Challenge), + string(TagBIP0340Aux): sha256.Sum256(TagBIP0340Aux), + string(TagBIP0340Nonce): sha256.Sum256(TagBIP0340Nonce), + } +) + // ErrHashStrSize describes an error that indicates the caller specified a hash // string that has too many characters. var ErrHashStrSize = fmt.Errorf("max hash string length is %v bytes", MaxHashStringSize) @@ -84,10 +103,13 @@ func NewHash(newHash []byte) (*Hash, error) { // TaggedHash implements the tagged hash scheme described in BIP-340. We use // sha-256 to bind a message hash to a specific context using a tag: // sha256(sha256(tag) || sha256(tag) || msg). -// -// TODO(roasbeef): add fast paths for common known tags func TaggedHash(tag []byte, msgs ...[]byte) *Hash { - shaTag := sha256.Sum256(tag) + // Check to see if we've already pre-computed the hash of the tag. If + // so then this'll save us an extra sha256 hash. + shaTag, ok := precomputedTags[string(tag)] + if !ok { + shaTag = sha256.Sum256(tag) + } // h = sha256(sha256(tag) || sha256(tag) || msg) h := sha256.New() From 0847f7a476df16757c4e35a45b966f89a8b9e2df Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 1 Feb 2022 12:51:19 -0800 Subject: [PATCH 0603/1056] build: update to btcec v2.1.0 This was the version tagged that created the new `ecdsa` and `schnorr` packages. Updating these pinned version lets importers properly use these packages and build. Things build as is since we use replace directive to point to the latest version _in the repo_ when we build. --- btcutil/go.mod | 2 +- btcutil/psbt/go.mod | 2 +- go.mod | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index 36d669b06e..d3e460e53d 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c - github.com/btcsuite/btcd/btcec/v2 v2.0.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.0 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index fbd9f1b3c2..7b07854505 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c - github.com/btcsuite/btcd/btcec/v2 v2.0.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.0 github.com/btcsuite/btcd/btcutil v1.0.0 github.com/davecgh/go-spew v1.1.1 ) diff --git a/go.mod b/go.mod index 7ed1214d86..cdd5a0d89f 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/btcsuite/btcd require ( - github.com/btcsuite/btcd/btcec/v2 v2.0.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.0 github.com/btcsuite/btcd/btcutil v1.0.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd From 342f4f8845c80c0d9e66b49aa824e6eefc46ad55 Mon Sep 17 00:00:00 2001 From: eugene Date: Fri, 4 Feb 2022 15:33:12 -0500 Subject: [PATCH 0604/1056] Revert "reduce redundant memory allocatio - resolves btcsuite/btcd#1699" This reverts commit 780cc0889fd2f326e4a2a9b513d8d30ff37e0cd2. --- connmgr/tor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connmgr/tor.go b/connmgr/tor.go index a2e512dba1..2b22ae51f2 100644 --- a/connmgr/tor.go +++ b/connmgr/tor.go @@ -76,7 +76,7 @@ func TorLookupIP(host, proxy string) ([]net.IP, error) { return nil, ErrTorUnrecognizedAuthMethod } - buf = make([]byte, 6+len(host)) + buf = make([]byte, 7+len(host)) buf[0] = 5 // protocol version buf[1] = '\xF0' // Tor Resolve buf[2] = 0 // reserved From 7572beb481dddd7f572c42e0305afcdc69af6d61 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 4 Feb 2022 15:44:53 -0800 Subject: [PATCH 0605/1056] build: retract bogus tags from btcd fork Fixes https://github.com/btcsuite/btcd/issues/1791. --- btcec/go.sum | 4 ++-- btcutil/go.sum | 2 +- btcutil/psbt/go.mod | 2 +- go.mod | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/btcec/go.sum b/btcec/go.sum index dcbbc98cc5..8ee9102772 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -1,6 +1,6 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd/btcec/v2 v2.0.0/go.mod h1:vu+77Lro3alBlmsmlDnkZtgGiNo6OBwMHSb1XTGDwGo= -github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= diff --git a/btcutil/go.sum b/btcutil/go.sum index ac96abce84..823b9bb378 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -1,6 +1,6 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 7b07854505..3897bf9916 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c github.com/btcsuite/btcd/btcec/v2 v2.1.0 - github.com/btcsuite/btcd/btcutil v1.0.0 + github.com/btcsuite/btcd/btcutil v1.1.0 github.com/davecgh/go-spew v1.1.1 ) diff --git a/go.mod b/go.mod index cdd5a0d89f..2b88125054 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/btcsuite/btcd require ( github.com/btcsuite/btcd/btcec/v2 v2.1.0 - github.com/btcsuite/btcd/btcutil v1.0.0 + github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/goleveldb v1.0.0 @@ -26,4 +26,36 @@ replace github.com/btcsuite/btcd/btcutil => ./btcutil replace github.com/btcsuite/btcd/btcec/v2 => ./btcec +// The retract statements below fixes an accidental push of the tags of a btcd +// fork. +retract ( + v0.18.1 + v0.18.0 + v0.17.1 + v0.17.0 + v0.16.5 + v0.16.4 + v0.16.3 + v0.16.2 + v0.16.1 + v0.16.0 + + v0.15.2 + v0.15.1 + v0.15.0 + + v0.14.7 + v0.14.6 + v0.14.6 + v0.14.5 + v0.14.4 + v0.14.3 + v0.14.2 + v0.14.1 + + v0.14.0 + v0.13.0-beta2 + v0.13.0-beta +) + go 1.17 From 2ce1c60ee4a1c9cd66022a3d85399408c24d92d7 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 22 Dec 2021 03:16:25 +0900 Subject: [PATCH 0606/1056] mempool/estimatefee: Fix negative index bug Fixes a negative index bug that makes the node crash on chain reorganizations. The bug is detailed in github.com/btcsuite/btcd/issues/1660. A better design than just skipping the transaction would make the fee estimator more accurate and that should implemented at a later date. --- mempool/estimatefee.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index f3a7cfe95b..a71ce42f12 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -275,7 +275,16 @@ func (ef *FeeEstimator) RegisterBlock(block *btcutil.Block) error { // This shouldn't happen but check just in case to avoid // an out-of-bounds array index later. - if blocksToConfirm >= estimateFeeDepth { + // + // Also check that blocksToConfirm is not negative as this causes + // the node to crash on reorgs. A tx that was observed at height X + // might be included in heights less than X because of chain reorgs. + // Refer to github.com/btcsuite/btcd/issues/1660 for more information. + // + // TODO(kcalvinalvin) a better design that doesn't just skip over the + // transaction would result in a more accurate fee estimator. Properly + // implement this later. + if blocksToConfirm >= estimateFeeDepth || blocksToConfirm < 0 { continue } From 1ec4a1e77ffb1c64fea6a87112ba58db9fda6cfe Mon Sep 17 00:00:00 2001 From: eugene Date: Thu, 3 Feb 2022 13:38:41 -0500 Subject: [PATCH 0607/1056] wire: netaddressv2 and tests --- wire/netaddressv2.go | 588 ++++++++++++++++++++++++++++++++++++++ wire/netaddressv2_test.go | 285 ++++++++++++++++++ 2 files changed, 873 insertions(+) create mode 100644 wire/netaddressv2.go create mode 100644 wire/netaddressv2_test.go diff --git a/wire/netaddressv2.go b/wire/netaddressv2.go new file mode 100644 index 0000000000..15f7916456 --- /dev/null +++ b/wire/netaddressv2.go @@ -0,0 +1,588 @@ +package wire + +import ( + "encoding/base32" + "encoding/binary" + "fmt" + "io" + "net" + "strings" + "time" + + "golang.org/x/crypto/sha3" +) + +const ( + // maxAddrV2Size is the maximum size an address may be in the addrv2 + // message. + maxAddrV2Size = 512 +) + +var ( + // ErrInvalidAddressSize is an error that means an incorrect address + // size was decoded for a networkID or that the address exceeded the + // maximum size for an unknown networkID. + ErrInvalidAddressSize = fmt.Errorf("invalid address size") + + // ErrSkippedNetworkID is returned when the cjdns, i2p, or unknown + // networks are encountered during decoding. btcd does not support i2p + // or cjdns addresses. In the case of an unknown networkID, this is so + // that a future BIP reserving a new networkID does not cause older + // addrv2-supporting btcd software to disconnect upon receiving the new + // addresses. This error can also be returned when an OnionCat-encoded + // torv2 address is received with the ipv6 networkID. This error + // signals to the caller to continue reading. + ErrSkippedNetworkID = fmt.Errorf("skipped networkID") +) + +// maxNetAddressV2Payload returns the max payload size for an address used in +// the addrv2 message. +func maxNetAddressV2Payload() uint32 { + // The timestamp takes up four bytes. + plen := uint32(4) + + // The ServiceFlag is a varint and its maximum size is 9 bytes. + plen += 9 + + // The netID is a single byte. + plen += 1 + + // The largest address is 512 bytes. Even though it will not be a valid + // address, we should read and ignore it. The preceeding varint to + // store 512 bytes is 3 bytes long. This gives us a total of 515 bytes. + plen += 515 + + // The port is 2 bytes. + plen += 2 + + return plen +} + +// isOnionCatTor returns whether a given ip address is actually an encoded tor +// v2 address. The wire package is unable to use the addrmgr's IsOnionCatTor as +// doing so would give an import cycle. +func isOnionCatTor(ip net.IP) bool { + onionCatNet := net.IPNet{ + IP: net.ParseIP("fd87:d87e:eb43::"), + Mask: net.CIDRMask(48, 128), + } + return onionCatNet.Contains(ip) +} + +// NetAddressV2 defines information about a peer on the network including the +// last time it was seen, the services it supports, its address, and port. This +// struct is used in the addrv2 message (MsgAddrV2) and can contain larger +// addresses, like Tor. Additionally, it can contain any NetAddress address. +type NetAddressV2 struct { + // Last time the address was seen. This is, unfortunately, encoded as a + // uint32 on the wire and therefore is limited to 2106. This field is + // not present in the bitcoin version message (MsgVersion) nor was it + // added until protocol version >= NetAddressTimeVersion. + Timestamp time.Time + + // Services is a bitfield which identifies the services supported by + // the address. This is encoded in CompactSize. + Services ServiceFlag + + // Addr is the network address of the peer. This is a variable-length + // address. Network() returns the BIP-155 networkID which is a uint8 + // encoded as a string. String() returns the address as a string. + Addr net.Addr + + // Port is the port of the address. This is 0 if the network doesn't + // use ports. + Port uint16 +} + +// HasService returns whether the specified service is supported by the +// address. +func (na *NetAddressV2) HasService(service ServiceFlag) bool { + return na.Services&service == service +} + +// AddService adds a service to the Services bitfield. +func (na *NetAddressV2) AddService(service ServiceFlag) { + na.Services |= service +} + +// ToLegacy attempts to convert a NetAddressV2 to a legacy NetAddress. This +// only works for ipv4, ipv6, or torv2 addresses as they can be encoded with +// the OnionCat encoding. If this method is called on a torv3 address, nil will +// be returned. +func (na *NetAddressV2) ToLegacy() *NetAddress { + legacyNa := &NetAddress{ + Timestamp: na.Timestamp, + Services: na.Services, + Port: na.Port, + } + + switch a := na.Addr.(type) { + case *ipv4Addr: + legacyNa.IP = a.addr[:] + case *ipv6Addr: + legacyNa.IP = a.addr[:] + case *torv2Addr: + legacyNa.IP = a.onionCatEncoding() + case *torv3Addr: + return nil + } + + return legacyNa +} + +// IsTorV3 returns a bool that signals to the caller whether or not this is a +// torv3 address. +func (na *NetAddressV2) IsTorV3() bool { + _, ok := na.Addr.(*torv3Addr) + return ok +} + +// TorV3Key returns the first byte of the v3 public key. This is used in the +// addrmgr to calculate a key from a network group. +func (na *NetAddressV2) TorV3Key() byte { + // This should never be called on a non-torv3 address. + addr, ok := na.Addr.(*torv3Addr) + if !ok { + panic("unexpected TorV3Key call on non-torv3 address") + } + + return addr.addr[0] +} + +// NetAddressV2FromBytes creates a NetAddressV2 from a byte slice. It will +// also handle a torv2 address using the OnionCat encoding. +func NetAddressV2FromBytes(timestamp time.Time, services ServiceFlag, + addrBytes []byte, port uint16) *NetAddressV2 { + + var netAddr net.Addr + switch len(addrBytes) { + case ipv4Size: + addr := &ipv4Addr{} + addr.netID = ipv4 + copy(addr.addr[:], addrBytes) + netAddr = addr + case ipv6Size: + if isOnionCatTor(addrBytes) { + addr := &torv2Addr{} + addr.netID = torv2 + copy(addr.addr[:], addrBytes[6:]) + netAddr = addr + break + } + + addr := &ipv6Addr{} + addr.netID = ipv6 + copy(addr.addr[:], addrBytes) + netAddr = addr + case torv2Size: + addr := &torv2Addr{} + addr.netID = torv2 + copy(addr.addr[:], addrBytes) + netAddr = addr + case TorV3Size: + addr := &torv3Addr{} + addr.netID = torv3 + copy(addr.addr[:], addrBytes) + netAddr = addr + } + + return &NetAddressV2{ + Timestamp: timestamp, + Services: services, + Addr: netAddr, + Port: port, + } +} + +// writeNetAddressV2 writes a NetAddressV2 to a writer. +func writeNetAddressV2(w io.Writer, pver uint32, na *NetAddressV2) error { + err := writeElement(w, uint32(na.Timestamp.Unix())) + if err != nil { + return err + } + + if err := WriteVarInt(w, pver, uint64(na.Services)); err != nil { + return err + } + + var ( + netID networkID + address []byte + ) + + switch a := na.Addr.(type) { + case *ipv4Addr: + netID = a.netID + address = a.addr[:] + case *ipv6Addr: + netID = a.netID + address = a.addr[:] + case *torv2Addr: + netID = a.netID + address = a.addr[:] + case *torv3Addr: + netID = a.netID + address = a.addr[:] + default: + // This should not occur. + return fmt.Errorf("unexpected address type") + } + + if err := writeElement(w, netID); err != nil { + return err + } + + addressSize := uint64(len(address)) + if err := WriteVarInt(w, pver, addressSize); err != nil { + return err + } + + if err := writeElement(w, address); err != nil { + return err + } + + return binary.Write(w, bigEndian, na.Port) +} + +// readNetAddressV2 reads a NetAddressV2 from a reader. This function has +// checks that the corresponding write function doesn't. This is because +// reading from the peer is untrusted whereas writing assumes we have already +// validated the NetAddressV2. +func readNetAddressV2(r io.Reader, pver uint32, na *NetAddressV2) error { + err := readElement(r, (*uint32Time)(&na.Timestamp)) + if err != nil { + return err + } + + // Services is encoded as a variable length integer in addrv2. + services, err := ReadVarInt(r, pver) + if err != nil { + return err + } + na.Services = ServiceFlag(services) + + var netID uint8 + if err := readElement(r, &netID); err != nil { + return err + } + + decodedSize, err := ReadVarInt(r, pver) + if err != nil { + return err + } + + if !isKnownNetworkID(netID) { + // In the case of an unknown networkID, we'll read the address + // size and error with ErrInvalidAddressSize if it's greater + // than maxAddrV2Size. If the address size is within the valid + // range, we'll just read and discard the address. In this + // case, ErrSkippedNetworkID will be returned to signal to the + // caller to continue reading. + if decodedSize > maxAddrV2Size { + return ErrInvalidAddressSize + } + + // The +2 is the port field. + discardedAddrPort := make([]byte, decodedSize+2) + if err := readElement(r, &discardedAddrPort); err != nil { + return err + } + + return ErrSkippedNetworkID + } + + // If the netID is an i2p or cjdns address, we'll advance the reader + // and return a special error to signal to the caller to not use the + // passed NetAddressV2 struct. Otherwise, we'll just read the address + // and port without returning an error. + switch networkID(netID) { + case ipv4: + addr := &ipv4Addr{} + addr.netID = ipv4 + if decodedSize != uint64(ipv4Size) { + return ErrInvalidAddressSize + } + + if err := readElement(r, &addr.addr); err != nil { + return err + } + + na.Port, err = binarySerializer.Uint16(r, bigEndian) + if err != nil { + return err + } + + na.Addr = addr + case ipv6: + addr := &ipv6Addr{} + addr.netID = ipv6 + if decodedSize != uint64(ipv6Size) { + return ErrInvalidAddressSize + } + + if err := readElement(r, &addr.addr); err != nil { + return err + } + + na.Port, err = binarySerializer.Uint16(r, bigEndian) + if err != nil { + return err + } + + na.Addr = addr + + // BIP-155 says to ignore OnionCat addresses in addrv2 + // messages. + if isOnionCatTor(addr.addr[:]) { + return ErrSkippedNetworkID + } + case torv2: + addr := &torv2Addr{} + addr.netID = torv2 + if decodedSize != uint64(torv2Size) { + return ErrInvalidAddressSize + } + + if err := readElement(r, &addr.addr); err != nil { + return err + } + + na.Port, err = binarySerializer.Uint16(r, bigEndian) + if err != nil { + return err + } + + na.Addr = addr + case torv3: + addr := &torv3Addr{} + addr.netID = torv3 + if decodedSize != uint64(TorV3Size) { + return ErrInvalidAddressSize + } + + if err := readElement(r, &addr.addr); err != nil { + return err + } + + na.Port, err = binarySerializer.Uint16(r, bigEndian) + if err != nil { + return err + } + + // BIP-155 does not specify to validate the public key here. + // bitcoind does not validate the ed25519 pubkey. + na.Addr = addr + case i2p: + addr := &i2pAddr{} + addr.netID = i2p + if decodedSize != uint64(i2pSize) { + return ErrInvalidAddressSize + } + + if err := readElement(r, &addr.addr); err != nil { + return err + } + + na.Port, err = binarySerializer.Uint16(r, bigEndian) + if err != nil { + return err + } + + return ErrSkippedNetworkID + case cjdns: + addr := &cjdnsAddr{} + addr.netID = cjdns + if decodedSize != uint64(cjdnsSize) { + return ErrInvalidAddressSize + } + + if err := readElement(r, &addr.addr); err != nil { + return err + } + + na.Port, err = binarySerializer.Uint16(r, bigEndian) + if err != nil { + return err + } + + return ErrSkippedNetworkID + } + + return nil +} + +// networkID represents the network that a given address is in. CJDNS and I2P +// addresses are not included. +type networkID uint8 + +const ( + // ipv4 means the following address is ipv4. + ipv4 networkID = iota + 1 + + // ipv6 means the following address is ipv6. + ipv6 + + // torv2 means the following address is a torv2 hidden service address. + torv2 + + // torv3 means the following address is a torv3 hidden service address. + torv3 + + // i2p means the following address is an i2p address. + i2p + + // cjdns means the following address is a cjdns address. + cjdns +) + +const ( + // ipv4Size is the size of an ipv4 address. + ipv4Size = 4 + + // ipv6Size is the size of an ipv6 address. + ipv6Size = 16 + + // torv2Size is the size of a torv2 address. + torv2Size = 10 + + // TorV3Size is the size of a torv3 address in bytes. + TorV3Size = 32 + + // i2pSize is the size of an i2p address. + i2pSize = 32 + + // cjdnsSize is the size of a cjdns address. + cjdnsSize = 16 +) + +const ( + // TorV2EncodedSize is the size of a torv2 address encoded in base32 + // with the ".onion" suffix. + TorV2EncodedSize = 22 + + // TorV3EncodedSize is the size of a torv3 address encoded in base32 + // with the ".onion" suffix. + TorV3EncodedSize = 62 +) + +// isKnownNetworkID returns true if the networkID is one listed above and false +// otherwise. +func isKnownNetworkID(netID uint8) bool { + return uint8(ipv4) <= netID && netID <= uint8(cjdns) +} + +type ipv4Addr struct { + addr [ipv4Size]byte + netID networkID +} + +// Part of the net.Addr interface. +func (a *ipv4Addr) String() string { + return net.IP(a.addr[:]).String() +} + +// Part of the net.Addr interface. +func (a *ipv4Addr) Network() string { + return string(a.netID) +} + +// Compile-time constraints to check that ipv4Addr meets the net.Addr +// interface. +var _ net.Addr = (*ipv4Addr)(nil) + +type ipv6Addr struct { + addr [ipv6Size]byte + netID networkID +} + +// Part of the net.Addr interface. +func (a *ipv6Addr) String() string { + return net.IP(a.addr[:]).String() +} + +// Part of the net.Addr interface. +func (a *ipv6Addr) Network() string { + return string(a.netID) +} + +// Compile-time constraints to check that ipv6Addr meets the net.Addr +// interface. +var _ net.Addr = (*ipv4Addr)(nil) + +type torv2Addr struct { + addr [torv2Size]byte + netID networkID +} + +// Part of the net.Addr interface. +func (a *torv2Addr) String() string { + base32Hash := base32.StdEncoding.EncodeToString(a.addr[:]) + return strings.ToLower(base32Hash) + ".onion" +} + +// Part of the net.Addr interface. +func (a *torv2Addr) Network() string { + return string(a.netID) +} + +// onionCatEncoding returns a torv2 address as an ipv6 address. +func (a *torv2Addr) onionCatEncoding() net.IP { + prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43} + return net.IP(append(prefix, a.addr[:]...)) +} + +// Compile-time constraints to check that torv2Addr meets the net.Addr +// interface. +var _ net.Addr = (*torv2Addr)(nil) + +type torv3Addr struct { + addr [TorV3Size]byte + netID networkID +} + +// Part of the net.Addr interface. +func (a *torv3Addr) String() string { + // BIP-155 describes the torv3 address format: + // onion_address = base32(PUBKEY | CHECKSUM | VERSION) + ".onion" + // CHECKSUM = H(".onion checksum" | PUBKEY | VERSION)[:2] + // PUBKEY = addr, which is the ed25519 pubkey of the hidden service. + // VERSION = '\x03' + // H() is the SHA3-256 cryptographic hash function. + + torV3Version := []byte("\x03") + checksumConst := []byte(".onion checksum") + + // Write never returns an error so there is no need to handle it. + h := sha3.New256() + h.Write(checksumConst) + h.Write(a.addr[:]) + h.Write(torV3Version) + truncatedChecksum := h.Sum(nil)[:2] + + var base32Input [35]byte + copy(base32Input[:32], a.addr[:]) + copy(base32Input[32:34], truncatedChecksum) + copy(base32Input[34:], torV3Version) + + base32Hash := base32.StdEncoding.EncodeToString(base32Input[:]) + return strings.ToLower(base32Hash) + ".onion" +} + +// Part of the net.Addr interface. +func (a *torv3Addr) Network() string { + return string(a.netID) +} + +// Compile-time constraints to check that torv3Addr meets the net.Addr +// interface. +var _ net.Addr = (*torv3Addr)(nil) + +type i2pAddr struct { + addr [i2pSize]byte + netID networkID +} + +type cjdnsAddr struct { + addr [cjdnsSize]byte + netID networkID +} diff --git a/wire/netaddressv2_test.go b/wire/netaddressv2_test.go new file mode 100644 index 0000000000..bd5084b009 --- /dev/null +++ b/wire/netaddressv2_test.go @@ -0,0 +1,285 @@ +package wire + +import ( + "bytes" + "io" + "testing" + "time" +) + +// TestNetAddressV2FromBytes tests that NetAddressV2FromBytes works as +// expected. +func TestNetAddressV2FromBytes(t *testing.T) { + tests := []struct { + addrBytes []byte + expectedString string + expectedNetwork string + }{ + // Ipv4 encoding + { + []byte{0x7f, 0x00, 0x00, 0x01}, + "127.0.0.1", + string(ipv4), + }, + + // Ipv6 encoding + { + []byte{ + 0x20, 0x01, 0x09, 0xe8, 0x26, 0x15, 0x73, 0x00, + 0x09, 0x54, 0x12, 0x63, 0xef, 0xc8, 0x2e, 0x34, + }, + "2001:9e8:2615:7300:954:1263:efc8:2e34", + string(ipv6), + }, + + // OnionCat encoding + { + []byte{ + 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43, 0xff, 0xfe, + 0xcc, 0x39, 0xa8, 0x73, 0x69, 0x15, 0xff, 0xff, + }, + "777myonionurl777.onion", + string(torv2), + }, + + // Torv2 encoding + { + []byte{ + 0xff, 0xfe, 0xcc, 0x39, 0xa8, 0x73, 0x69, 0x15, + 0xff, 0xff, + }, + "777myonionurl777.onion", + string(torv2), + }, + + // Torv3 encoding + { + []byte{ + 0xca, 0xd2, 0xd3, 0xc8, 0xdc, 0x9c, 0xc4, 0xd3, + 0x70, 0x33, 0x30, 0xc5, 0x23, 0xaf, 0x02, 0xed, + 0xc4, 0x9d, 0xf8, 0xc6, 0xb0, 0x4e, 0x74, 0x6d, + 0x3b, 0x51, 0x57, 0xa7, 0x15, 0xfe, 0x98, 0x35, + }, + "zljnhsg4ttcng4btgdcshlyc5xcj36ggwbhhi3j3kfl2ofp6ta26jlid.onion", + string(torv3), + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + na := NetAddressV2FromBytes(time.Time{}, 0, test.addrBytes, 0) + + if test.expectedNetwork != string(torv3) { + if na.ToLegacy() == nil { + t.Errorf("Test #%d has nil legacy encoding", i) + } + } else { + if !na.IsTorV3() { + t.Errorf("Test #%d is not torv3 address", i) + } + } + + if na.Addr.String() != test.expectedString { + t.Errorf("Test #%d did not match expected string", i) + } + + if na.Addr.Network() != test.expectedNetwork { + t.Errorf("Test #%d did not match expected network", i) + } + + var b bytes.Buffer + if err := writeNetAddressV2(&b, 0, na); err != nil { + t.Errorf("Test #%d failed writing address %v", i, err) + } + + // Assert that the written netID is equivalent to the above. + if string(b.Bytes()[5]) != test.expectedNetwork { + t.Errorf("Test #%d did not match expected network", i) + } + } +} + +// TestReadNetAddressV2 tests that readNetAddressV2 behaves as expected in +// different scenarios. +func TestReadNetAddressV2(t *testing.T) { + tests := []struct { + buf []byte + expectedNetwork string + expectedError error + }{ + // Invalid address size for unknown netID. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfd, 0xff, + 0xff, + }, + "", + ErrInvalidAddressSize, + }, + + // Valid address size for unknown netID. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x20, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x22, + 0x22, + }, + "", + ErrSkippedNetworkID, + }, + + // Invalid ipv4 size. + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05}, + "", + ErrInvalidAddressSize, + }, + + // Valid ipv4 encoding. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x7f, + 0x00, 0x00, 0x01, 0x22, 0x22, + }, + string(ipv4), + nil, + }, + + // Invalid ipv6 size. + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfc}, + "", + ErrInvalidAddressSize, + }, + + // OnionCat encoding is skipped. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xfd, + 0x87, 0xd8, 0x7e, 0xeb, 0x43, 0xff, 0xfe, 0xcc, + 0x39, 0xa8, 0x73, 0x69, 0x15, 0xff, 0xff, 0x22, + 0x22, + }, + "", + ErrSkippedNetworkID, + }, + + // Valid ipv6 encoding. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x22, + 0x22, + }, + string(ipv6), + nil, + }, + + // Invalid torv2 size. + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02}, + "", + ErrInvalidAddressSize, + }, + + // Valid torv2 encoding. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x22, 0x22, + }, + string(torv2), + nil, + }, + + // Invalid torv3 size. + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02}, + "", + ErrInvalidAddressSize, + }, + + // Valid torv3 encoding. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x20, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x22, + 0x22, + }, + string(torv3), + nil, + }, + + // Invalid i2p size. + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02}, + "", + ErrInvalidAddressSize, + }, + + // Valid i2p encoding. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x22, + 0x22, + }, + string(i2p), + ErrSkippedNetworkID, + }, + + // Invalid cjdns size. + { + []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02}, + "", + ErrInvalidAddressSize, + }, + + // Valid cjdns encoding. + { + []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, + 0x22, + }, + string(cjdns), + ErrSkippedNetworkID, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + r := bytes.NewReader(test.buf) + na := &NetAddressV2{} + + err := readNetAddressV2(r, 0, na) + if err != test.expectedError { + t.Errorf("Test #%d had unexpected error %v", i, err) + } else if err != nil { + continue + } + + // Trying to read more should give EOF. + var b [1]byte + if _, err := r.Read(b[:]); err != io.EOF { + t.Errorf("Test #%d did not cleanly finish reading", i) + } + + if na.Addr.Network() != test.expectedNetwork { + t.Errorf("Test #%d had unexpected network %v", i, + na.Addr.Network()) + } + } +} From 201c0836ec9a0ed3523a2eaee87a8370129702a1 Mon Sep 17 00:00:00 2001 From: eugene Date: Thu, 3 Feb 2022 14:02:46 -0500 Subject: [PATCH 0608/1056] multi: update addrmgr, server to use NetAddressV2 instead of legacy --- addrmgr/addrmanager.go | 182 +++++++++++++++++---------- addrmgr/addrmanager_internal_test.go | 32 +++-- addrmgr/addrmanager_test.go | 175 ++++++++++++++++++-------- addrmgr/internal_test.go | 2 +- addrmgr/knownaddress.go | 8 +- addrmgr/knownaddress_test.go | 18 +-- addrmgr/network.go | 55 +++++--- addrmgr/network_test.go | 12 +- connmgr/seed.go | 6 +- rpcadapters.go | 2 +- rpcserver.go | 4 +- server.go | 80 ++++++++---- 12 files changed, 381 insertions(+), 195 deletions(-) diff --git a/addrmgr/addrmanager.go b/addrmgr/addrmanager.go index 4c737b937e..bdfe9094ce 100644 --- a/addrmgr/addrmanager.go +++ b/addrmgr/addrmanager.go @@ -70,7 +70,7 @@ type serializedAddrManager struct { } type localAddress struct { - na *wire.NetAddress + na *wire.NetAddressV2 score AddressPriority } @@ -163,7 +163,7 @@ const ( // updateAddress is a helper function to either update an address already known // to the address manager, or to add the address if not already known. -func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddress) { +func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddressV2) { // Filter out non-routable addresses. Note that non-routable // also includes invalid and local addresses. if !IsRoutable(netAddr) { @@ -296,7 +296,7 @@ func (a *AddrManager) pickTried(bucket int) *list.Element { return oldestElem } -func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddress) int { +func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddressV2) int { // bitcoind: // doublesha256(key + sourcegroup + int64(doublesha256(key + group + sourcegroup))%bucket_per_source_group) % num_new_buckets @@ -318,7 +318,7 @@ func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddress) int { return int(binary.LittleEndian.Uint64(hash2) % newBucketCount) } -func (a *AddrManager) getTriedBucket(netAddr *wire.NetAddress) int { +func (a *AddrManager) getTriedBucket(netAddr *wire.NetAddressV2) int { // bitcoind hashes this as: // doublesha256(key + group + truncate_to_64bits(doublesha256(key)) % buckets_per_group) % num_buckets data1 := []byte{} @@ -550,7 +550,7 @@ func (a *AddrManager) deserializePeers(filePath string) error { // DeserializeNetAddress converts a given address string to a *wire.NetAddress. func (a *AddrManager) DeserializeNetAddress(addr string, - services wire.ServiceFlag) (*wire.NetAddress, error) { + services wire.ServiceFlag) (*wire.NetAddressV2, error) { host, portStr, err := net.SplitHostPort(addr) if err != nil { @@ -599,7 +599,7 @@ func (a *AddrManager) Stop() error { // AddAddresses adds new addresses to the address manager. It enforces a max // number of addresses and silently ignores duplicate addresses. It is // safe for concurrent access. -func (a *AddrManager) AddAddresses(addrs []*wire.NetAddress, srcAddr *wire.NetAddress) { +func (a *AddrManager) AddAddresses(addrs []*wire.NetAddressV2, srcAddr *wire.NetAddressV2) { a.mtx.Lock() defer a.mtx.Unlock() @@ -611,7 +611,7 @@ func (a *AddrManager) AddAddresses(addrs []*wire.NetAddress, srcAddr *wire.NetAd // AddAddress adds a new address to the address manager. It enforces a max // number of addresses and silently ignores duplicate addresses. It is // safe for concurrent access. -func (a *AddrManager) AddAddress(addr, srcAddr *wire.NetAddress) { +func (a *AddrManager) AddAddress(addr, srcAddr *wire.NetAddressV2) { a.mtx.Lock() defer a.mtx.Unlock() @@ -635,7 +635,7 @@ func (a *AddrManager) AddAddressByIP(addrIP string) error { if err != nil { return fmt.Errorf("invalid port %s: %v", portStr, err) } - na := wire.NewNetAddressIPPort(ip, uint16(port), 0) + na := wire.NetAddressV2FromBytes(time.Now(), 0, ip, uint16(port)) a.AddAddress(na, na) // XXX use correct src address return nil } @@ -664,7 +664,7 @@ func (a *AddrManager) NeedMoreAddresses() bool { // AddressCache returns the current address cache. It must be treated as // read-only (but since it is a copy now, this is not as dangerous). -func (a *AddrManager) AddressCache() []*wire.NetAddress { +func (a *AddrManager) AddressCache() []*wire.NetAddressV2 { allAddr := a.getAddresses() numAddresses := len(allAddr) * getAddrPercent / 100 @@ -686,7 +686,7 @@ func (a *AddrManager) AddressCache() []*wire.NetAddress { // getAddresses returns all of the addresses currently found within the // manager's address cache. -func (a *AddrManager) getAddresses() []*wire.NetAddress { +func (a *AddrManager) getAddresses() []*wire.NetAddressV2 { a.mtx.RLock() defer a.mtx.RUnlock() @@ -695,7 +695,7 @@ func (a *AddrManager) getAddresses() []*wire.NetAddress { return nil } - addrs := make([]*wire.NetAddress, 0, addrIndexLen) + addrs := make([]*wire.NetAddressV2, 0, addrIndexLen) for _, v := range a.addrIndex { addrs = append(addrs, v.na) } @@ -722,20 +722,43 @@ func (a *AddrManager) reset() { // HostToNetAddress returns a netaddress given a host address. If the address // is a Tor .onion address this will be taken care of. Else if the host is // not an IP address it will be resolved (via Tor if required). -func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.ServiceFlag) (*wire.NetAddress, error) { - // Tor address is 16 char base32 + ".onion" - var ip net.IP - if len(host) == 22 && host[16:] == ".onion" { +func (a *AddrManager) HostToNetAddress(host string, port uint16, + services wire.ServiceFlag) (*wire.NetAddressV2, error) { + + var ( + na *wire.NetAddressV2 + ip net.IP + ) + + // Tor v2 address is 16 char base32 + ".onion" + if len(host) == wire.TorV2EncodedSize && host[wire.TorV2EncodedSize-6:] == ".onion" { // go base32 encoding uses capitals (as does the rfc // but Tor and bitcoind tend to user lowercase, so we switch // case here. data, err := base32.StdEncoding.DecodeString( - strings.ToUpper(host[:16])) + strings.ToUpper(host[:wire.TorV2EncodedSize-6])) + if err != nil { + return nil, err + } + + na = wire.NetAddressV2FromBytes( + time.Now(), services, data, port, + ) + } else if len(host) == wire.TorV3EncodedSize && host[wire.TorV3EncodedSize-6:] == ".onion" { + // Tor v3 addresses are 56 base32 characters with the 6 byte + // onion suffix. + data, err := base32.StdEncoding.DecodeString( + strings.ToUpper(host[:wire.TorV3EncodedSize-6]), + ) if err != nil { return nil, err } - prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43} - ip = net.IP(append(prefix, data...)) + + // The first 32 bytes is the ed25519 public key and is enough + // to reconstruct the .onion address. + na = wire.NetAddressV2FromBytes( + time.Now(), services, data[:wire.TorV3Size], port, + ) } else if ip = net.ParseIP(host); ip == nil { ips, err := a.lookupFunc(host) if err != nil { @@ -745,30 +768,23 @@ func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.S return nil, fmt.Errorf("no addresses found for %s", host) } ip = ips[0] - } - - return wire.NewNetAddressIPPort(ip, port, services), nil -} -// ipString returns a string for the ip from the provided NetAddress. If the -// ip is in the range used for Tor addresses then it will be transformed into -// the relevant .onion address. -func ipString(na *wire.NetAddress) string { - if IsOnionCatTor(na) { - // We know now that na.IP is long enough. - base32 := base32.StdEncoding.EncodeToString(na.IP[6:]) - return strings.ToLower(base32) + ".onion" + na = wire.NetAddressV2FromBytes(time.Now(), services, ip, port) + } else { + // This is an non-nil IP address that was parsed in the else if + // above. + na = wire.NetAddressV2FromBytes(time.Now(), services, ip, port) } - return na.IP.String() + return na, nil } // NetAddressKey returns a string key in the form of ip:port for IPv4 addresses -// or [ip]:port for IPv6 addresses. -func NetAddressKey(na *wire.NetAddress) string { +// or [ip]:port for IPv6 addresses. It also handles onion v2 and v3 addresses. +func NetAddressKey(na *wire.NetAddressV2) string { port := strconv.FormatUint(uint64(na.Port), 10) - return net.JoinHostPort(ipString(na), port) + return net.JoinHostPort(na.Addr.String(), port) } // GetAddress returns a single address that should be routable. It picks a @@ -842,13 +858,13 @@ func (a *AddrManager) GetAddress() *KnownAddress { } } -func (a *AddrManager) find(addr *wire.NetAddress) *KnownAddress { +func (a *AddrManager) find(addr *wire.NetAddressV2) *KnownAddress { return a.addrIndex[NetAddressKey(addr)] } // Attempt increases the given address' attempt counter and updates // the last attempt time. -func (a *AddrManager) Attempt(addr *wire.NetAddress) { +func (a *AddrManager) Attempt(addr *wire.NetAddressV2) { a.mtx.Lock() defer a.mtx.Unlock() @@ -869,7 +885,7 @@ func (a *AddrManager) Attempt(addr *wire.NetAddress) { // Connected Marks the given address as currently connected and working at the // current time. The address must already be known to AddrManager else it will // be ignored. -func (a *AddrManager) Connected(addr *wire.NetAddress) { +func (a *AddrManager) Connected(addr *wire.NetAddressV2) { a.mtx.Lock() defer a.mtx.Unlock() @@ -894,7 +910,7 @@ func (a *AddrManager) Connected(addr *wire.NetAddress) { // Good marks the given address as good. To be called after a successful // connection and version exchange. If the address is unknown to the address // manager it will be ignored. -func (a *AddrManager) Good(addr *wire.NetAddress) { +func (a *AddrManager) Good(addr *wire.NetAddressV2) { a.mtx.Lock() defer a.mtx.Unlock() @@ -983,7 +999,7 @@ func (a *AddrManager) Good(addr *wire.NetAddress) { } // SetServices sets the services for the giiven address to the provided value. -func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFlag) { +func (a *AddrManager) SetServices(addr *wire.NetAddressV2, services wire.ServiceFlag) { a.mtx.Lock() defer a.mtx.Unlock() @@ -1005,9 +1021,11 @@ func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFl // AddLocalAddress adds na to the list of known local addresses to advertise // with the given priority. -func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPriority) error { +func (a *AddrManager) AddLocalAddress(na *wire.NetAddressV2, priority AddressPriority) error { if !IsRoutable(na) { - return fmt.Errorf("address %s is not routable", na.IP) + return fmt.Errorf( + "address %s is not routable", na.Addr.String(), + ) } a.lamtx.Lock() @@ -1030,7 +1048,7 @@ func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPrior // getReachabilityFrom returns the relative reachability of the provided local // address to the provided remote address. -func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int { +func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddressV2) int { const ( Unreachable = 0 Default = iota @@ -1045,36 +1063,66 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int { return Unreachable } - if IsOnionCatTor(remoteAddr) { - if IsOnionCatTor(localAddr) { + if remoteAddr.IsTorV3() { + if localAddr.IsTorV3() { return Private } - if IsRoutable(localAddr) && IsIPv4(localAddr) { + lna := localAddr.ToLegacy() + if IsOnionCatTor(lna) { + // Modern v3 clients should not be able to connect to + // deprecated v2 hidden services. + return Unreachable + } + + if IsRoutable(localAddr) && IsIPv4(lna) { return Ipv4 } return Default } - if IsRFC4380(remoteAddr) { + // We can't be sure if the remote party can actually connect to this + // address or not. + if localAddr.IsTorV3() { + return Default + } + + // Convert the V2 addresses into legacy to access the network + // functions. + remoteLna := remoteAddr.ToLegacy() + localLna := localAddr.ToLegacy() + + if IsOnionCatTor(remoteLna) { + if IsOnionCatTor(localLna) { + return Private + } + + if IsRoutable(localAddr) && IsIPv4(localLna) { + return Ipv4 + } + + return Default + } + + if IsRFC4380(remoteLna) { if !IsRoutable(localAddr) { return Default } - if IsRFC4380(localAddr) { + if IsRFC4380(localLna) { return Teredo } - if IsIPv4(localAddr) { + if IsIPv4(localLna) { return Ipv4 } return Ipv6Weak } - if IsIPv4(remoteAddr) { - if IsRoutable(localAddr) && IsIPv4(localAddr) { + if IsIPv4(remoteLna) { + if IsRoutable(localAddr) && IsIPv4(localLna) { return Ipv4 } return Unreachable @@ -1083,7 +1131,7 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int { /* ipv6 */ var tunnelled bool // Is our v6 is tunnelled? - if IsRFC3964(localAddr) || IsRFC6052(localAddr) || IsRFC6145(localAddr) { + if IsRFC3964(localLna) || IsRFC6052(localLna) || IsRFC6145(localLna) { tunnelled = true } @@ -1091,11 +1139,11 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int { return Default } - if IsRFC4380(localAddr) { + if IsRFC4380(localLna) { return Teredo } - if IsIPv4(localAddr) { + if IsIPv4(localLna) { return Ipv4 } @@ -1109,13 +1157,13 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int { // GetBestLocalAddress returns the most appropriate local address to use // for the given remote address. -func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.NetAddress { +func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddressV2) *wire.NetAddressV2 { a.lamtx.Lock() defer a.lamtx.Unlock() bestreach := 0 var bestscore AddressPriority - var bestAddress *wire.NetAddress + var bestAddress *wire.NetAddressV2 for _, la := range a.localAddresses { reach := getReachabilityFrom(la.na, remoteAddr) if reach > bestreach || @@ -1126,21 +1174,29 @@ func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.Net } } if bestAddress != nil { - log.Debugf("Suggesting address %s:%d for %s:%d", bestAddress.IP, - bestAddress.Port, remoteAddr.IP, remoteAddr.Port) + log.Debugf("Suggesting address %s:%d for %s:%d", + bestAddress.Addr.String(), bestAddress.Port, + remoteAddr.Addr.String(), remoteAddr.Port) } else { - log.Debugf("No worthy address for %s:%d", remoteAddr.IP, - remoteAddr.Port) + log.Debugf("No worthy address for %s:%d", + remoteAddr.Addr.String(), remoteAddr.Port) // Send something unroutable if nothing suitable. var ip net.IP - if !IsIPv4(remoteAddr) && !IsOnionCatTor(remoteAddr) { - ip = net.IPv6zero - } else { + if remoteAddr.IsTorV3() { ip = net.IPv4zero + } else { + remoteLna := remoteAddr.ToLegacy() + if !IsIPv4(remoteLna) && !IsOnionCatTor(remoteLna) { + ip = net.IPv6zero + } else { + ip = net.IPv4zero + } } services := wire.SFNodeNetwork | wire.SFNodeWitness | wire.SFNodeBloom - bestAddress = wire.NewNetAddressIPPort(ip, 0, services) + bestAddress = wire.NetAddressV2FromBytes( + time.Now(), services, ip, 0, + ) } return bestAddress diff --git a/addrmgr/addrmanager_internal_test.go b/addrmgr/addrmanager_internal_test.go index 1c19dceb18..1d13f78e6e 100644 --- a/addrmgr/addrmanager_internal_test.go +++ b/addrmgr/addrmanager_internal_test.go @@ -6,12 +6,14 @@ import ( "net" "os" "testing" + "time" "github.com/btcsuite/btcd/wire" ) -// randAddr generates a *wire.NetAddress backed by a random IPv4/IPv6 address. -func randAddr(t *testing.T) *wire.NetAddress { +// randAddr generates a *wire.NetAddressV2 backed by a random IPv4/IPv6 +// address. +func randAddr(t *testing.T) *wire.NetAddressV2 { t.Helper() ipv4 := rand.Intn(2) == 0 @@ -30,22 +32,26 @@ func randAddr(t *testing.T) *wire.NetAddress { ip = b[:] } - return &wire.NetAddress{ - Services: wire.ServiceFlag(rand.Uint64()), - IP: ip, - Port: uint16(rand.Uint32()), - } + services := wire.ServiceFlag(rand.Uint64()) + port := uint16(rand.Uint32()) + + return wire.NetAddressV2FromBytes( + time.Now(), services, ip, port, + ) } // assertAddr ensures that the two addresses match. The timestamp is not // checked as it does not affect uniquely identifying a specific address. -func assertAddr(t *testing.T, got, expected *wire.NetAddress) { +func assertAddr(t *testing.T, got, expected *wire.NetAddressV2) { if got.Services != expected.Services { t.Fatalf("expected address services %v, got %v", expected.Services, got.Services) } - if !got.IP.Equal(expected.IP) { - t.Fatalf("expected address IP %v, got %v", expected.IP, got.IP) + gotAddr := got.Addr.String() + expectedAddr := expected.Addr.String() + if gotAddr != expectedAddr { + t.Fatalf("expected address IP %v, got %v", expectedAddr, + gotAddr) } if got.Port != expected.Port { t.Fatalf("expected address port %d, got %d", expected.Port, @@ -56,7 +62,7 @@ func assertAddr(t *testing.T, got, expected *wire.NetAddress) { // assertAddrs ensures that the manager's address cache matches the given // expected addresses. func assertAddrs(t *testing.T, addrMgr *AddrManager, - expectedAddrs map[string]*wire.NetAddress) { + expectedAddrs map[string]*wire.NetAddressV2) { t.Helper() @@ -96,7 +102,7 @@ func TestAddrManagerSerialization(t *testing.T) { // We'll be adding 5 random addresses to the manager. const numAddrs = 5 - expectedAddrs := make(map[string]*wire.NetAddress, numAddrs) + expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs) for i := 0; i < numAddrs; i++ { addr := randAddr(t) expectedAddrs[NetAddressKey(addr)] = addr @@ -141,7 +147,7 @@ func TestAddrManagerV1ToV2(t *testing.T) { // each addresses' services will not be stored. const numAddrs = 5 - expectedAddrs := make(map[string]*wire.NetAddress, numAddrs) + expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs) for i := 0; i < numAddrs; i++ { addr := randAddr(t) expectedAddrs[NetAddressKey(addr)] = addr diff --git a/addrmgr/addrmanager_test.go b/addrmgr/addrmanager_test.go index 676913e21e..4afe5fd601 100644 --- a/addrmgr/addrmanager_test.go +++ b/addrmgr/addrmanager_test.go @@ -19,7 +19,7 @@ import ( // naTest is used to describe a test to be performed against the NetAddressKey // method. type naTest struct { - in wire.NetAddress + in wire.NetAddressV2 want string } @@ -93,8 +93,10 @@ func addNaTests() { func addNaTest(ip string, port uint16, want string) { nip := net.ParseIP(ip) - na := *wire.NewNetAddressIPPort(nip, port, wire.SFNodeNetwork) - test := naTest{na, want} + na := wire.NetAddressV2FromBytes( + time.Now(), wire.SFNodeNetwork, nip, port, + ) + test := naTest{*na, want} naTests = append(naTests, test) } @@ -157,37 +159,49 @@ func TestAddAddressByIP(t *testing.T) { func TestAddLocalAddress(t *testing.T) { var tests = []struct { - address wire.NetAddress + address wire.NetAddressV2 priority addrmgr.AddressPriority valid bool }{ { - wire.NetAddress{IP: net.ParseIP("192.168.0.100")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("192.168.0.100"), 0, + ), addrmgr.InterfacePrio, false, }, { - wire.NetAddress{IP: net.ParseIP("204.124.1.1")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("204.124.1.1"), 0, + ), addrmgr.InterfacePrio, true, }, { - wire.NetAddress{IP: net.ParseIP("204.124.1.1")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("204.124.1.1"), 0, + ), addrmgr.BoundPrio, true, }, { - wire.NetAddress{IP: net.ParseIP("::1")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("::1"), 0, + ), addrmgr.InterfacePrio, false, }, { - wire.NetAddress{IP: net.ParseIP("fe80::1")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("fe80::1"), 0, + ), addrmgr.InterfacePrio, false, }, { - wire.NetAddress{IP: net.ParseIP("2620:100::1")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("2620:100::1"), 0, + ), addrmgr.InterfacePrio, true, }, @@ -197,12 +211,12 @@ func TestAddLocalAddress(t *testing.T) { result := amgr.AddLocalAddress(&test.address, test.priority) if result == nil && !test.valid { t.Errorf("TestAddLocalAddress test #%d failed: %s should have "+ - "been accepted", x, test.address.IP) + "been accepted", x, test.address.Addr.String()) continue } if result != nil && test.valid { t.Errorf("TestAddLocalAddress test #%d failed: %s should not have "+ - "been accepted", x, test.address.IP) + "been accepted", x, test.address.Addr.String()) continue } } @@ -257,7 +271,7 @@ func TestNeedMoreAddresses(t *testing.T) { if !b { t.Errorf("Expected that we need more addresses") } - addrs := make([]*wire.NetAddress, addrsToAdd) + addrs := make([]*wire.NetAddressV2, addrsToAdd) var err error for i := 0; i < addrsToAdd; i++ { @@ -268,7 +282,9 @@ func TestNeedMoreAddresses(t *testing.T) { } } - srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0) + srcAddr := wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4(173, 144, 173, 111), 8333, + ) n.AddAddresses(addrs, srcAddr) numAddrs := n.NumAddresses() @@ -285,7 +301,7 @@ func TestNeedMoreAddresses(t *testing.T) { func TestGood(t *testing.T) { n := addrmgr.New("testgood", lookupFunc) addrsToAdd := 64 * 64 - addrs := make([]*wire.NetAddress, addrsToAdd) + addrs := make([]*wire.NetAddressV2, addrsToAdd) var err error for i := 0; i < addrsToAdd; i++ { @@ -296,7 +312,9 @@ func TestGood(t *testing.T) { } } - srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0) + srcAddr := wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4(173, 144, 173, 111), 8333, + ) n.AddAddresses(addrs, srcAddr) for _, addr := range addrs { @@ -331,8 +349,8 @@ func TestGetAddress(t *testing.T) { if ka == nil { t.Fatalf("Did not get an address where there is one in the pool") } - if ka.NetAddress().IP.String() != someIP { - t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP) + if ka.NetAddress().Addr.String() != someIP { + t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().Addr.String(), someIP) } // Mark this as a good address and get it @@ -341,8 +359,8 @@ func TestGetAddress(t *testing.T) { if ka == nil { t.Fatalf("Did not get an address where there is one in the pool") } - if ka.NetAddress().IP.String() != someIP { - t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP) + if ka.NetAddress().Addr.String() != someIP { + t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().Addr.String(), someIP) } numAddrs := n.NumAddresses() @@ -352,43 +370,83 @@ func TestGetAddress(t *testing.T) { } func TestGetBestLocalAddress(t *testing.T) { - localAddrs := []wire.NetAddress{ - {IP: net.ParseIP("192.168.0.100")}, - {IP: net.ParseIP("::1")}, - {IP: net.ParseIP("fe80::1")}, - {IP: net.ParseIP("2001:470::1")}, + localAddrs := []wire.NetAddressV2{ + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("192.168.0.100"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("::1"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("fe80::1"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("2001:470::1"), 0, + ), } var tests = []struct { - remoteAddr wire.NetAddress - want0 wire.NetAddress - want1 wire.NetAddress - want2 wire.NetAddress - want3 wire.NetAddress + remoteAddr wire.NetAddressV2 + want0 wire.NetAddressV2 + want1 wire.NetAddressV2 + want2 wire.NetAddressV2 + want3 wire.NetAddressV2 }{ { // Remote connection from public IPv4 - wire.NetAddress{IP: net.ParseIP("204.124.8.1")}, - wire.NetAddress{IP: net.IPv4zero}, - wire.NetAddress{IP: net.IPv4zero}, - wire.NetAddress{IP: net.ParseIP("204.124.8.100")}, - wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("204.124.8.1"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4zero, 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4zero, 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("204.124.8.100"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, + net.ParseIP("fd87:d87e:eb43:25::1"), 0, + ), }, { // Remote connection from private IPv4 - wire.NetAddress{IP: net.ParseIP("172.16.0.254")}, - wire.NetAddress{IP: net.IPv4zero}, - wire.NetAddress{IP: net.IPv4zero}, - wire.NetAddress{IP: net.IPv4zero}, - wire.NetAddress{IP: net.IPv4zero}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("172.16.0.254"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4zero, 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4zero, 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4zero, 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv4zero, 0, + ), }, { // Remote connection from public IPv6 - wire.NetAddress{IP: net.ParseIP("2602:100:abcd::102")}, - wire.NetAddress{IP: net.IPv6zero}, - wire.NetAddress{IP: net.ParseIP("2001:470::1")}, - wire.NetAddress{IP: net.ParseIP("2001:470::1")}, - wire.NetAddress{IP: net.ParseIP("2001:470::1")}, + *wire.NetAddressV2FromBytes( + time.Now(), 0, + net.ParseIP("2602:100:abcd::102"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.IPv6zero, 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("2001:470::1"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("2001:470::1"), 0, + ), + *wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("2001:470::1"), 0, + ), }, /* XXX { @@ -406,9 +464,12 @@ func TestGetBestLocalAddress(t *testing.T) { // Test against default when there's no address for x, test := range tests { got := amgr.GetBestLocalAddress(&test.remoteAddr) - if !test.want0.IP.Equal(got.IP) { + wantAddr := test.want0.Addr.String() + gotAddr := got.Addr.String() + if wantAddr != gotAddr { + remoteAddr := test.remoteAddr.Addr.String() t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s", - x, test.remoteAddr.IP, test.want1.IP, got.IP) + x, remoteAddr, wantAddr, gotAddr) continue } } @@ -420,23 +481,31 @@ func TestGetBestLocalAddress(t *testing.T) { // Test against want1 for x, test := range tests { got := amgr.GetBestLocalAddress(&test.remoteAddr) - if !test.want1.IP.Equal(got.IP) { + wantAddr := test.want1.Addr.String() + gotAddr := got.Addr.String() + if wantAddr != gotAddr { + remoteAddr := test.remoteAddr.Addr.String() t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s", - x, test.remoteAddr.IP, test.want1.IP, got.IP) + x, remoteAddr, wantAddr, gotAddr) continue } } // Add a public IP to the list of local addresses. - localAddr := wire.NetAddress{IP: net.ParseIP("204.124.8.100")} - amgr.AddLocalAddress(&localAddr, addrmgr.InterfacePrio) + localAddr := wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP("204.124.8.100"), 0, + ) + amgr.AddLocalAddress(localAddr, addrmgr.InterfacePrio) // Test against want2 for x, test := range tests { got := amgr.GetBestLocalAddress(&test.remoteAddr) - if !test.want2.IP.Equal(got.IP) { + wantAddr := test.want2.Addr.String() + gotAddr := got.Addr.String() + if wantAddr != gotAddr { + remoteAddr := test.remoteAddr.Addr.String() t.Errorf("TestGetBestLocalAddress test2 #%d failed for remote address %s: want %s got %s", - x, test.remoteAddr.IP, test.want2.IP, got.IP) + x, remoteAddr, wantAddr, gotAddr) continue } } diff --git a/addrmgr/internal_test.go b/addrmgr/internal_test.go index e50e923cf7..ab7644b6ca 100644 --- a/addrmgr/internal_test.go +++ b/addrmgr/internal_test.go @@ -18,7 +18,7 @@ func TstKnownAddressChance(ka *KnownAddress) float64 { return ka.chance() } -func TstNewKnownAddress(na *wire.NetAddress, attempts int, +func TstNewKnownAddress(na *wire.NetAddressV2, attempts int, lastattempt, lastsuccess time.Time, tried bool, refs int) *KnownAddress { return &KnownAddress{na: na, attempts: attempts, lastattempt: lastattempt, lastsuccess: lastsuccess, tried: tried, refs: refs} diff --git a/addrmgr/knownaddress.go b/addrmgr/knownaddress.go index 5a7674f45b..b045365508 100644 --- a/addrmgr/knownaddress.go +++ b/addrmgr/knownaddress.go @@ -15,8 +15,8 @@ import ( // to determine how viable an address is. type KnownAddress struct { mtx sync.RWMutex // na and lastattempt - na *wire.NetAddress - srcAddr *wire.NetAddress + na *wire.NetAddressV2 + srcAddr *wire.NetAddressV2 attempts int lastattempt time.Time lastsuccess time.Time @@ -24,9 +24,9 @@ type KnownAddress struct { refs int // reference count of new buckets } -// NetAddress returns the underlying wire.NetAddress associated with the +// NetAddress returns the underlying wire.NetAddressV2 associated with the // known address. -func (ka *KnownAddress) NetAddress() *wire.NetAddress { +func (ka *KnownAddress) NetAddress() *wire.NetAddressV2 { ka.mtx.RLock() defer ka.mtx.RUnlock() return ka.na diff --git a/addrmgr/knownaddress_test.go b/addrmgr/knownaddress_test.go index a289d5a386..b4a2650140 100644 --- a/addrmgr/knownaddress_test.go +++ b/addrmgr/knownaddress_test.go @@ -21,27 +21,27 @@ func TestChance(t *testing.T) { }{ { //Test normal case - addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)}, + addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)}, 0, time.Now().Add(-30*time.Minute), time.Now(), false, 0), 1.0, }, { //Test case in which lastseen < 0 - addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(20 * time.Second)}, + addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(20 * time.Second)}, 0, time.Now().Add(-30*time.Minute), time.Now(), false, 0), 1.0, }, { //Test case in which lastattempt < 0 - addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)}, + addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)}, 0, time.Now().Add(30*time.Minute), time.Now(), false, 0), 1.0 * .01, }, { //Test case in which lastattempt < ten minutes - addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)}, + addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)}, 0, time.Now().Add(-5*time.Minute), time.Now(), false, 0), 1.0 * .01, }, { //Test case with several failed attempts. - addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)}, + addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)}, 2, time.Now().Add(-30*time.Minute), time.Now(), false, 0), 1 / 1.5 / 1.5, }, @@ -65,10 +65,10 @@ func TestIsBad(t *testing.T) { hoursOld := now.Add(-5 * time.Hour) zeroTime := time.Time{} - futureNa := &wire.NetAddress{Timestamp: future} - minutesOldNa := &wire.NetAddress{Timestamp: minutesOld} - monthOldNa := &wire.NetAddress{Timestamp: monthOld} - currentNa := &wire.NetAddress{Timestamp: secondsOld} + futureNa := &wire.NetAddressV2{Timestamp: future} + minutesOldNa := &wire.NetAddressV2{Timestamp: minutesOld} + monthOldNa := &wire.NetAddressV2{Timestamp: monthOld} + currentNa := &wire.NetAddressV2{Timestamp: secondsOld} //Test addresses that have been tried in the last minute. if addrmgr.TstKnownAddressIsBad(addrmgr.TstNewKnownAddress(futureNa, 3, secondsOld, zeroTime, false, 0)) { diff --git a/addrmgr/network.go b/addrmgr/network.go index 51bfa3ed75..7f30901b21 100644 --- a/addrmgr/network.go +++ b/addrmgr/network.go @@ -222,11 +222,20 @@ func IsValid(na *wire.NetAddress) bool { // IsRoutable returns whether or not the passed address is routable over // the public internet. This is true as long as the address is valid and is not // in any reserved ranges. -func IsRoutable(na *wire.NetAddress) bool { - return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) || - IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) || - IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) || - IsLocal(na) || (IsRFC4193(na) && !IsOnionCatTor(na))) +func IsRoutable(na *wire.NetAddressV2) bool { + if na.IsTorV3() { + // na is a torv3 address, return true. + return true + } + + // Else na can be represented as a legacy NetAddress since i2p and + // cjdns are unsupported. + lna := na.ToLegacy() + return IsValid(lna) && !(IsRFC1918(lna) || IsRFC2544(lna) || + IsRFC3927(lna) || IsRFC4862(lna) || IsRFC3849(lna) || + IsRFC4843(lna) || IsRFC5737(lna) || IsRFC6598(lna) || + IsLocal(lna) || (IsRFC4193(lna) && + !IsOnionCatTor(lna))) } // GroupKey returns a string representing the network group an address is part @@ -234,48 +243,56 @@ func IsRoutable(na *wire.NetAddress) bool { // "local" for a local address, the string "tor:key" where key is the /4 of the // onion address for Tor address, and the string "unroutable" for an unroutable // address. -func GroupKey(na *wire.NetAddress) string { - if IsLocal(na) { +func GroupKey(na *wire.NetAddressV2) string { + if na.IsTorV3() { + // na is a torv3 address. Use the same network group keying as + // for torv2. + return fmt.Sprintf("tor:%d", na.TorV3Key()&((1<<4)-1)) + } + + lna := na.ToLegacy() + + if IsLocal(lna) { return "local" } if !IsRoutable(na) { return "unroutable" } - if IsIPv4(na) { - return na.IP.Mask(net.CIDRMask(16, 32)).String() + if IsIPv4(lna) { + return lna.IP.Mask(net.CIDRMask(16, 32)).String() } - if IsRFC6145(na) || IsRFC6052(na) { + if IsRFC6145(lna) || IsRFC6052(lna) { // last four bytes are the ip address - ip := na.IP[12:16] + ip := lna.IP[12:16] return ip.Mask(net.CIDRMask(16, 32)).String() } - if IsRFC3964(na) { - ip := na.IP[2:6] + if IsRFC3964(lna) { + ip := lna.IP[2:6] return ip.Mask(net.CIDRMask(16, 32)).String() } - if IsRFC4380(na) { + if IsRFC4380(lna) { // teredo tunnels have the last 4 bytes as the v4 address XOR // 0xff. ip := net.IP(make([]byte, 4)) - for i, byte := range na.IP[12:16] { + for i, byte := range lna.IP[12:16] { ip[i] = byte ^ 0xff } return ip.Mask(net.CIDRMask(16, 32)).String() } - if IsOnionCatTor(na) { + if IsOnionCatTor(lna) { // group is keyed off the first 4 bits of the actual onion key. - return fmt.Sprintf("tor:%d", na.IP[6]&((1<<4)-1)) + return fmt.Sprintf("tor:%d", lna.IP[6]&((1<<4)-1)) } // OK, so now we know ourselves to be a IPv6 address. // bitcoind uses /32 for everything, except for Hurricane Electric's // (he.net) IP range, which it uses /36 for. bits := 32 - if heNet.Contains(na.IP) { + if heNet.Contains(lna.IP) { bits = 36 } - return na.IP.Mask(net.CIDRMask(bits, 128)).String() + return lna.IP.Mask(net.CIDRMask(bits, 128)).String() } diff --git a/addrmgr/network_test.go b/addrmgr/network_test.go index 8af3369f56..f4bc5d88f7 100644 --- a/addrmgr/network_test.go +++ b/addrmgr/network_test.go @@ -7,6 +7,7 @@ package addrmgr_test import ( "net" "testing" + "time" "github.com/btcsuite/btcd/addrmgr" "github.com/btcsuite/btcd/wire" @@ -136,7 +137,10 @@ func TestIPTypes(t *testing.T) { t.Errorf("IsValid %s\n got: %v want: %v", test.in.IP, rv, test.valid) } - if rv := addrmgr.IsRoutable(&test.in); rv != test.routable { + currentNa := wire.NetAddressV2FromBytes( + time.Now(), test.in.Services, test.in.IP, test.in.Port, + ) + if rv := addrmgr.IsRoutable(currentNa); rv != test.routable { t.Errorf("IsRoutable %s\n got: %v want: %v", test.in.IP, rv, test.routable) } } @@ -192,8 +196,10 @@ func TestGroupKey(t *testing.T) { for i, test := range tests { nip := net.ParseIP(test.ip) - na := *wire.NewNetAddressIPPort(nip, 8333, wire.SFNodeNetwork) - if key := addrmgr.GroupKey(&na); key != test.expected { + na := wire.NetAddressV2FromBytes( + time.Now(), wire.SFNodeNetwork, nip, 8333, + ) + if key := addrmgr.GroupKey(na); key != test.expected { t.Errorf("TestGroupKey #%d (%s): unexpected group key "+ "- got '%s', want '%s'", i, test.name, key, test.expected) diff --git a/connmgr/seed.go b/connmgr/seed.go index 063b546ab8..4c26160d8f 100644 --- a/connmgr/seed.go +++ b/connmgr/seed.go @@ -24,7 +24,7 @@ const ( // OnSeed is the signature of the callback function which is invoked when DNS // seeding is succesfull. -type OnSeed func(addrs []*wire.NetAddress) +type OnSeed func(addrs []*wire.NetAddressV2) // LookupFunc is the signature of the DNS lookup function. type LookupFunc func(string) ([]net.IP, error) @@ -56,11 +56,11 @@ func SeedFromDNS(chainParams *chaincfg.Params, reqServices wire.ServiceFlag, if numPeers == 0 { return } - addresses := make([]*wire.NetAddress, len(seedpeers)) + addresses := make([]*wire.NetAddressV2, len(seedpeers)) // if this errors then we have *real* problems intPort, _ := strconv.Atoi(chainParams.DefaultPort) for i, peer := range seedpeers { - addresses[i] = wire.NewNetAddressTimestamp( + addresses[i] = wire.NetAddressV2FromBytes( // bitcoind seeds with addresses from // a time randomly selected between 3 // and 7 days ago. diff --git a/rpcadapters.go b/rpcadapters.go index 02d33710ac..487574a81c 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -228,7 +228,7 @@ func (cm *rpcConnManager) RelayTransactions(txns []*mempool.TxDesc) { // // This function is safe for concurrent access and is part of the // rpcserverConnManager interface implementation. -func (cm *rpcConnManager) NodeAddresses() []*wire.NetAddress { +func (cm *rpcConnManager) NodeAddresses() []*wire.NetAddressV2 { return cm.server.addrManager.AddressCache() } diff --git a/rpcserver.go b/rpcserver.go index b8012b2b01..4bbeb29ae9 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2518,7 +2518,7 @@ func handleGetNodeAddresses(s *rpcServer, cmd interface{}, closeChan <-chan stru address := &btcjson.GetNodeAddressesResult{ Time: node.Timestamp.Unix(), Services: uint64(node.Services), - Address: node.IP.String(), + Address: node.Addr.String(), Port: node.Port, } addresses = append(addresses, address) @@ -4524,7 +4524,7 @@ type rpcserverConnManager interface { // NodeAddresses returns an array consisting node addresses which can // potentially be used to find new nodes in the network. - NodeAddresses() []*wire.NetAddress + NodeAddresses() []*wire.NetAddressV2 } // rpcserverSyncManager represents a sync manager for use with the RPC server. diff --git a/server.go b/server.go index 45bfb17ee4..2b5cc0ff42 100644 --- a/server.go +++ b/server.go @@ -25,6 +25,8 @@ import ( "github.com/btcsuite/btcd/addrmgr" "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain/indexers" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/bloom" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/connmgr" @@ -36,8 +38,7 @@ import ( "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/btcutil/bloom" + "github.com/decred/dcrd/lru" ) const ( @@ -274,7 +275,7 @@ type serverPeer struct { isWhitelisted bool filter *bloom.Filter addressesMtx sync.RWMutex - knownAddresses map[string]struct{} + knownAddresses lru.Cache banScore connmgr.DynamicBanScore quit chan struct{} // The following chans are used to sync blockmanager and server. @@ -289,7 +290,7 @@ func newServerPeer(s *server, isPersistent bool) *serverPeer { server: s, persistent: isPersistent, filter: bloom.LoadFilter(nil), - knownAddresses: make(map[string]struct{}), + knownAddresses: lru.NewCache(5000), quit: make(chan struct{}), txProcessed: make(chan struct{}, 1), blockProcessed: make(chan struct{}, 1), @@ -305,18 +306,18 @@ func (sp *serverPeer) newestBlock() (*chainhash.Hash, int32, error) { // addKnownAddresses adds the given addresses to the set of known addresses to // the peer to prevent sending duplicate addresses. -func (sp *serverPeer) addKnownAddresses(addresses []*wire.NetAddress) { +func (sp *serverPeer) addKnownAddresses(addresses []*wire.NetAddressV2) { sp.addressesMtx.Lock() for _, na := range addresses { - sp.knownAddresses[addrmgr.NetAddressKey(na)] = struct{}{} + sp.knownAddresses.Add(addrmgr.NetAddressKey(na)) } sp.addressesMtx.Unlock() } // addressKnown true if the given address is already known to the peer. -func (sp *serverPeer) addressKnown(na *wire.NetAddress) bool { +func (sp *serverPeer) addressKnown(na *wire.NetAddressV2) bool { sp.addressesMtx.RLock() - _, exists := sp.knownAddresses[addrmgr.NetAddressKey(na)] + exists := sp.knownAddresses.Contains(addrmgr.NetAddressKey(na)) sp.addressesMtx.RUnlock() return exists } @@ -340,23 +341,45 @@ func (sp *serverPeer) relayTxDisabled() bool { return isDisabled } -// pushAddrMsg sends an addr message to the connected peer using the provided -// addresses. -func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddress) { - // Filter addresses already known to the peer. +// pushAddrMsg sends a legacy addr message to the connected peer using the +// provided addresses. +func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddressV2) { addrs := make([]*wire.NetAddress, 0, len(addresses)) for _, addr := range addresses { - if !sp.addressKnown(addr) { - addrs = append(addrs, addr) + // Filter addresses already known to the peer. + if sp.addressKnown(addr) { + continue + } + + // Must skip the V3 addresses for legacy ADDR messages. + if addr.IsTorV3() { + continue } + + // Convert the NetAddressV2 to a legacy address. + addrs = append(addrs, addr.ToLegacy()) } + known, err := sp.PushAddrMsg(addrs) if err != nil { - peerLog.Errorf("Can't push address message to %s: %v", sp.Peer, err) + peerLog.Errorf( + "Can't push address message to %s: %v", sp.Peer, err, + ) sp.Disconnect() return } - sp.addKnownAddresses(known) + + // Convert all of the known addresses to NetAddressV2 to add them to + // the set of known addresses. + knownAddrs := make([]*wire.NetAddressV2, 0, len(known)) + for _, knownAddr := range known { + currentKna := wire.NetAddressV2FromBytes( + knownAddr.Timestamp, knownAddr.Services, + knownAddr.IP, knownAddr.Port, + ) + knownAddrs = append(knownAddrs, currentKna) + } + sp.addKnownAddresses(knownAddrs) } // addBanScore increases the persistent and decaying ban score fields by the @@ -1272,6 +1295,7 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) { return } + addrs := make([]*wire.NetAddressV2, 0, len(msg.AddrList)) for _, na := range msg.AddrList { // Don't add more address if we're disconnecting. if !sp.Connected() { @@ -1286,8 +1310,14 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) { na.Timestamp = now.Add(-1 * time.Hour * 24 * 5) } - // Add address to known addresses for this peer. - sp.addKnownAddresses([]*wire.NetAddress{na}) + // Add address to known addresses for this peer. This is + // converted to NetAddressV2 since that's what the address + // manager uses. + currentNa := wire.NetAddressV2FromBytes( + na.Timestamp, na.Services, na.IP, na.Port, + ) + addrs = append(addrs, currentNa) + sp.addKnownAddresses([]*wire.NetAddressV2{currentNa}) } // Add addresses to server address manager. The address manager handles @@ -1295,7 +1325,7 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) { // addresses, and last seen updates. // XXX bitcoind gives a 2 hour time penalty here, do we want to do the // same? - sp.server.addrManager.AddAddresses(msg.AddrList, sp.NA()) + sp.server.addrManager.AddAddresses(addrs, sp.NA()) } // OnRead is invoked when a peer receives a message and it is used to update @@ -1700,7 +1730,7 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool { lna := s.addrManager.GetBestLocalAddress(sp.NA()) if addrmgr.IsRoutable(lna) { // Filter addresses the peer already knows about. - addresses := []*wire.NetAddress{lna} + addresses := []*wire.NetAddressV2{lna} sp.pushAddrMsg(addresses) } } @@ -2152,7 +2182,7 @@ func (s *server) peerHandler() { if !cfg.DisableDNSSeed { // Add peers discovered through DNS to the address manager. connmgr.SeedFromDNS(activeNetParams.Params, defaultRequiredServices, - btcdLookup, func(addrs []*wire.NetAddress) { + btcdLookup, func(addrs []*wire.NetAddressV2) { // Bitcoind uses a lookup of the dns seeder here. This // is rather strange since the values looked up by the // DNS seed lookups will vary quite a lot. @@ -2543,8 +2573,8 @@ out: srvrLog.Warnf("UPnP can't get external address: %v", err) continue out } - na := wire.NewNetAddressIPPort(externalip, uint16(listenPort), - s.services) + na := wire.NetAddressV2FromBytes(time.Now(), s.services, + externalip, uint16(listenPort)) err = s.addrManager.AddLocalAddress(na, addrmgr.UpnpPrio) if err != nil { // XXX DeletePortMapping? @@ -3117,7 +3147,9 @@ func addLocalAddress(addrMgr *addrmgr.AddrManager, addr string, services wire.Se continue } - netAddr := wire.NewNetAddressIPPort(ifaceIP, uint16(port), services) + netAddr := wire.NetAddressV2FromBytes( + time.Now(), services, ifaceIP, uint16(port), + ) addrMgr.AddLocalAddress(netAddr, addrmgr.BoundPrio) } } else { From cb6f21b598e90c8b1ea55e569b838797e9b37efe Mon Sep 17 00:00:00 2001 From: eugene Date: Thu, 3 Feb 2022 14:04:43 -0500 Subject: [PATCH 0609/1056] peer+wire: add addrv2 message, protocol negotiation --- peer/peer.go | 231 ++++++++++++++++++++++++++------ peer/peer_test.go | 290 ++++++++++++++++++++++++++++++++++++----- server.go | 68 ++++++++++ wire/message.go | 18 ++- wire/message_test.go | 4 +- wire/msgaddrv2.go | 102 +++++++++++++++ wire/msgaddrv2_test.go | 73 +++++++++++ wire/protocol.go | 9 +- 8 files changed, 714 insertions(+), 81 deletions(-) create mode 100644 wire/msgaddrv2.go create mode 100644 wire/msgaddrv2_test.go diff --git a/peer/peer.go b/peer/peer.go index a7b925802f..6d34c5f822 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -29,7 +29,7 @@ import ( const ( // MaxProtocolVersion is the max protocol version the peer supports. - MaxProtocolVersion = wire.FeeFilterVersion + MaxProtocolVersion = wire.AddrV2Version // DefaultTrickleInterval is the min time between attempts to send an // inv message to a peer. @@ -102,6 +102,9 @@ type MessageListeners struct { // OnAddr is invoked when a peer receives an addr bitcoin message. OnAddr func(p *Peer, msg *wire.MsgAddr) + // OnAddrV2 is invoked when a peer receives an addrv2 bitcoin message. + OnAddrV2 func(p *Peer, msg *wire.MsgAddrV2) + // OnPing is invoked when a peer receives a ping bitcoin message. OnPing func(p *Peer, msg *wire.MsgPing) @@ -197,6 +200,9 @@ type MessageListeners struct { // message. OnSendHeaders func(p *Peer, msg *wire.MsgSendHeaders) + // OnSendAddrV2 is invoked when a peer receives a sendaddrv2 message. + OnSendAddrV2 func(p *Peer, msg *wire.MsgSendAddrV2) + // OnRead is invoked when a peer receives a bitcoin message. It // consists of the number of bytes read, the message, and whether or not // an error in the read occurred. Typically, callers will opt to use @@ -399,7 +405,7 @@ type AddrFunc func(remoteAddr *wire.NetAddress) *wire.NetAddress // HostToNetAddrFunc is a func which takes a host, port, services and returns // the netaddress. type HostToNetAddrFunc func(host string, port uint16, - services wire.ServiceFlag) (*wire.NetAddress, error) + services wire.ServiceFlag) (*wire.NetAddressV2, error) // NOTE: The overall data flow of a peer is split into 3 goroutines. Inbound // messages are read via the inHandler goroutine and generally dispatched to @@ -445,7 +451,7 @@ type Peer struct { inbound bool flagsMtx sync.Mutex // protects the peer flags below - na *wire.NetAddress + na *wire.NetAddressV2 id int32 userAgent string services wire.ServiceFlag @@ -455,6 +461,7 @@ type Peer struct { sendHeadersPreferred bool // peer sent a sendheaders message verAckReceived bool witnessEnabled bool + sendAddrV2 bool wireEncoding wire.MessageEncoding @@ -585,7 +592,7 @@ func (p *Peer) ID() int32 { // NA returns the peer network address. // // This function is safe for concurrent access. -func (p *Peer) NA() *wire.NetAddress { +func (p *Peer) NA() *wire.NetAddressV2 { p.flagsMtx.Lock() na := p.na p.flagsMtx.Unlock() @@ -820,6 +827,16 @@ func (p *Peer) IsWitnessEnabled() bool { return witnessEnabled } +// WantsAddrV2 returns if the peer supports addrv2 messages instead of the +// legacy addr messages. +func (p *Peer) WantsAddrV2() bool { + p.flagsMtx.Lock() + wantsAddrV2 := p.sendAddrV2 + p.flagsMtx.Unlock() + + return wantsAddrV2 +} + // PushAddrMsg sends an addr message to the connected peer using the provided // addresses. This function is useful over manually sending the message via // QueueMessage since it automatically limits the addresses to the maximum @@ -856,6 +873,38 @@ func (p *Peer) PushAddrMsg(addresses []*wire.NetAddress) ([]*wire.NetAddress, er return msg.AddrList, nil } +// PushAddrV2Msg is used to push an addrv2 message to the remote peer. +// +// This function is safe for concurrent access. +func (p *Peer) PushAddrV2Msg(addrs []*wire.NetAddressV2) ( + []*wire.NetAddressV2, error) { + + count := len(addrs) + + // Nothing to send. + if count == 0 { + return nil, nil + } + + m := wire.NewMsgAddrV2() + m.AddrList = make([]*wire.NetAddressV2, count) + copy(m.AddrList, addrs) + + // Randomize the addresses sent if there are more than the maximum. + if count > wire.MaxV2AddrPerMsg { + rand.Shuffle(count, func(i, j int) { + m.AddrList[i] = m.AddrList[j] + m.AddrList[j] = m.AddrList[i] + }) + + // Truncate it to the maximum size. + m.AddrList = m.AddrList[:wire.MaxV2AddrPerMsg] + } + + p.QueueMessage(m, nil) + return m.AddrList, nil +} + // PushGetBlocksMsg sends a getblocks message for the provided block locator // and stop hash. It will ignore back-to-back duplicate requests. // @@ -1363,6 +1412,19 @@ out: continue } + // Since the protocol version is 70016 but we don't + // implement compact blocks, we have to ignore unknown + // messages after the version-verack handshake. This + // matches bitcoind's behavior and is necessary since + // compact blocks negotiation occurs after the + // handshake. + if err == wire.ErrUnknownMessage { + log.Debugf("Received unknown message from %s:"+ + " %v", p, err) + idleTimer.Reset(idleTimeout) + continue + } + // Only log the error and send reject message if the // local peer is not forcibly disconnecting and the // remote peer has not disconnected. @@ -1404,6 +1466,11 @@ out: ) break out + case *wire.MsgSendAddrV2: + // Disconnect if peer sends this after the handshake is + // completed. + break out + case *wire.MsgGetAddr: if p.cfg.Listeners.OnGetAddr != nil { p.cfg.Listeners.OnGetAddr(p, msg) @@ -1414,6 +1481,11 @@ out: p.cfg.Listeners.OnAddr(p, msg) } + case *wire.MsgAddrV2: + if p.cfg.Listeners.OnAddrV2 != nil { + p.cfg.Listeners.OnAddrV2(p, msg) + } + case *wire.MsgPing: p.handlePingMsg(msg) if p.cfg.Listeners.OnPing != nil { @@ -1986,29 +2058,8 @@ func (p *Peer) readRemoteVersionMsg() error { return nil } -// readRemoteVerAckMsg waits for the next message to arrive from the remote -// peer. If this message is not a verack message, then an error is returned. -// This method is to be used as part of the version negotiation upon a new -// connection. -func (p *Peer) readRemoteVerAckMsg() error { - // Read the next message from the wire. - remoteMsg, _, err := p.readMessage(wire.LatestEncoding) - if err != nil { - return err - } - - // It should be a verack message, otherwise send a reject message to the - // peer explaining why. - msg, ok := remoteMsg.(*wire.MsgVerAck) - if !ok { - reason := "a verack message must follow version" - rejectMsg := wire.NewMsgReject( - msg.Command(), wire.RejectMalformed, reason, - ) - _ = p.writeMessage(rejectMsg, wire.LatestEncoding) - return errors.New(reason) - } - +// processRemoteVerAckMsg takes the verack from the remote peer and handles it. +func (p *Peer) processRemoteVerAckMsg(msg *wire.MsgVerAck) { p.flagsMtx.Lock() p.verAckReceived = true p.flagsMtx.Unlock() @@ -2016,8 +2067,6 @@ func (p *Peer) readRemoteVerAckMsg() error { if p.cfg.Listeners.OnVerAck != nil { p.cfg.Listeners.OnVerAck(p, msg) } - - return nil } // localVersionMsg creates a version message that can be used to send to the @@ -2032,7 +2081,15 @@ func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { } } - theirNA := p.na + theirNA := p.na.ToLegacy() + + // If p.na is a torv3 hidden service address, we'll need to send over + // an empty NetAddress for their address. + if p.na.IsTorV3() { + theirNA = wire.NewNetAddressIPPort( + net.IP([]byte{0, 0, 0, 0}), p.na.Port, p.na.Services, + ) + } // If we are behind a proxy and the connection comes from the proxy then // we return an unroutable address as their address. This is to prevent @@ -2040,7 +2097,7 @@ func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) { if p.cfg.Proxy != "" { proxyaddress, _, err := net.SplitHostPort(p.cfg.Proxy) // invalid proxy means poorly configured, be on the safe side. - if err != nil || p.na.IP.String() == proxyaddress { + if err != nil || p.na.Addr.String() == proxyaddress { theirNA = wire.NewNetAddressIPPort(net.IP([]byte{0, 0, 0, 0}), 0, theirNA.Services) } @@ -2092,14 +2149,71 @@ func (p *Peer) writeLocalVersionMsg() error { return p.writeMessage(localVerMsg, wire.LatestEncoding) } +// writeSendAddrV2Msg writes our sendaddrv2 message to the remote peer if the +// peer supports protocol version 70016 and above. +func (p *Peer) writeSendAddrV2Msg(pver uint32) error { + if pver < wire.AddrV2Version { + return nil + } + + sendAddrMsg := wire.NewMsgSendAddrV2() + return p.writeMessage(sendAddrMsg, wire.LatestEncoding) +} + +// waitToFinishNegotiation waits until desired negotiation messages are +// received, recording the remote peer's preference for sendaddrv2 as an +// example. The list of negotiated features can be expanded in the future. If a +// verack is received, negotiation stops and the connection is live. +func (p *Peer) waitToFinishNegotiation(pver uint32) error { + // There are several possible messages that can be received here. We + // could immediately receive verack and be done with the handshake. We + // could receive sendaddrv2 and still have to wait for verack. Or we + // can receive unknown messages before and after sendaddrv2 and still + // have to wait for verack. + for { + remoteMsg, _, err := p.readMessage(wire.LatestEncoding) + if err == wire.ErrUnknownMessage { + continue + } else if err != nil { + return err + } + + switch m := remoteMsg.(type) { + case *wire.MsgSendAddrV2: + if pver >= wire.AddrV2Version { + p.flagsMtx.Lock() + p.sendAddrV2 = true + p.flagsMtx.Unlock() + + if p.cfg.Listeners.OnSendAddrV2 != nil { + p.cfg.Listeners.OnSendAddrV2(p, m) + } + } + case *wire.MsgVerAck: + // Receiving a verack means we are done with the + // handshake. + p.processRemoteVerAckMsg(m) + return nil + default: + // This is triggered if the peer sends, for example, a + // GETDATA message during this negotiation. + return wire.ErrInvalidHandshake + } + } +} + // negotiateInboundProtocol performs the negotiation protocol for an inbound // peer. The events should occur in the following order, otherwise an error is // returned: // // 1. Remote peer sends their version. // 2. We send our version. -// 3. We send our verack. -// 4. Remote peer sends their verack. +// 3. We send sendaddrv2 if their version is >= 70016. +// 4. We send our verack. +// 5. Wait until sendaddrv2 or verack is received. Unknown messages are +// skipped as it could be wtxidrelay or a different message in the future +// that btcd does not implement but bitcoind does. +// 6. If remote peer sent sendaddrv2 above, wait until receipt of verack. func (p *Peer) negotiateInboundProtocol() error { if err := p.readRemoteVersionMsg(); err != nil { return err @@ -2109,12 +2223,22 @@ func (p *Peer) negotiateInboundProtocol() error { return err } + var protoVersion uint32 + p.flagsMtx.Lock() + protoVersion = p.protocolVersion + p.flagsMtx.Unlock() + + if err := p.writeSendAddrV2Msg(protoVersion); err != nil { + return err + } + err := p.writeMessage(wire.NewMsgVerAck(), wire.LatestEncoding) if err != nil { return err } - return p.readRemoteVerAckMsg() + // Finish the negotiation by waiting for negotiable messages or verack. + return p.waitToFinishNegotiation(protoVersion) } // negotiateOutboundProtocol performs the negotiation protocol for an outbound @@ -2123,8 +2247,11 @@ func (p *Peer) negotiateInboundProtocol() error { // // 1. We send our version. // 2. Remote peer sends their version. -// 3. Remote peer sends their verack. +// 3. We send sendaddrv2 if their version is >= 70016. // 4. We send our verack. +// 5. We wait to receive sendaddrv2 or verack, skipping unknown messages as +// in the inbound case. +// 6. If sendaddrv2 was received, wait for receipt of verack. func (p *Peer) negotiateOutboundProtocol() error { if err := p.writeLocalVersionMsg(); err != nil { return err @@ -2134,11 +2261,22 @@ func (p *Peer) negotiateOutboundProtocol() error { return err } - if err := p.readRemoteVerAckMsg(); err != nil { + var protoVersion uint32 + p.flagsMtx.Lock() + protoVersion = p.protocolVersion + p.flagsMtx.Unlock() + + if err := p.writeSendAddrV2Msg(protoVersion); err != nil { + return err + } + + err := p.writeMessage(wire.NewMsgVerAck(), wire.LatestEncoding) + if err != nil { return err } - return p.writeMessage(wire.NewMsgVerAck(), wire.LatestEncoding) + // Finish the negotiation by waiting for negotiable messages or verack. + return p.waitToFinishNegotiation(protoVersion) } // start begins processing input and output messages. @@ -2201,7 +2339,12 @@ func (p *Peer) AssociateConnection(conn net.Conn) { p.Disconnect() return } - p.na = na + + // Convert the NetAddress created above into NetAddressV2. + currentNa := wire.NetAddressV2FromBytes( + na.Timestamp, na.Services, na.IP, na.Port, + ) + p.na = currentNa } go func() { @@ -2267,7 +2410,10 @@ func NewInboundPeer(cfg *Config) *Peer { return newPeerBase(cfg, true) } -// NewOutboundPeer returns a new outbound bitcoin peer. +// NewOutboundPeer returns a new outbound bitcoin peer. If the Config argument +// does not set HostToNetAddress, connecting to anything other than an ipv4 or +// ipv6 address will fail and may cause a nil-pointer-dereference. This +// includes hostnames and onion services. func NewOutboundPeer(cfg *Config, addr string) (*Peer, error) { p := newPeerBase(cfg, false) p.addr = addr @@ -2289,7 +2435,12 @@ func NewOutboundPeer(cfg *Config, addr string) (*Peer, error) { } p.na = na } else { - p.na = wire.NewNetAddressIPPort(net.ParseIP(host), uint16(port), 0) + // If host is an onion hidden service or a hostname, it is + // likely that a nil-pointer-dereference will occur. The caller + // should set HostToNetAddress if connecting to these. + p.na = wire.NetAddressV2FromBytes( + time.Now(), 0, net.ParseIP(host), uint16(port), + ) } return p, nil diff --git a/peer/peer_test.go b/peer/peer_test.go index dd7f36aa3a..9df90c233d 100644 --- a/peer/peer_test.go +++ b/peer/peer_test.go @@ -289,18 +289,16 @@ func TestPeerConnection(t *testing.T) { { "basic handshake", func() (*peer.Peer, *peer.Peer, error) { - inConn, outConn := pipe( - &conn{raddr: "10.0.0.1:8333"}, - &conn{raddr: "10.0.0.2:8333"}, - ) inPeer := peer.NewInboundPeer(peer1Cfg) - inPeer.AssociateConnection(inConn) - outPeer, err := peer.NewOutboundPeer(peer2Cfg, "10.0.0.2:8333") if err != nil { return nil, nil, err } - outPeer.AssociateConnection(outConn) + + err = setupPeerConnection(inPeer, outPeer) + if err != nil { + return nil, nil, err + } for i := 0; i < 4; i++ { select { @@ -315,18 +313,16 @@ func TestPeerConnection(t *testing.T) { { "socks proxy", func() (*peer.Peer, *peer.Peer, error) { - inConn, outConn := pipe( - &conn{raddr: "10.0.0.1:8333", proxy: true}, - &conn{raddr: "10.0.0.2:8333"}, - ) inPeer := peer.NewInboundPeer(peer1Cfg) - inPeer.AssociateConnection(inConn) - outPeer, err := peer.NewOutboundPeer(peer2Cfg, "10.0.0.2:8333") if err != nil { return nil, nil, err } - outPeer.AssociateConnection(outConn) + + err = setupPeerConnection(inPeer, outPeer) + if err != nil { + return nil, nil, err + } for i := 0; i < 4; i++ { select { @@ -359,7 +355,7 @@ func TestPeerConnection(t *testing.T) { // TestPeerListeners tests that the peer listeners are called as expected. func TestPeerListeners(t *testing.T) { verack := make(chan struct{}, 1) - ok := make(chan wire.Message, 20) + ok := make(chan wire.Message, 22) peerCfg := &peer.Config{ Listeners: peer.MessageListeners{ OnGetAddr: func(p *peer.Peer, msg *wire.MsgGetAddr) { @@ -447,6 +443,12 @@ func TestPeerListeners(t *testing.T) { OnSendHeaders: func(p *peer.Peer, msg *wire.MsgSendHeaders) { ok <- msg }, + OnSendAddrV2: func(p *peer.Peer, msg *wire.MsgSendAddrV2) { + ok <- msg + }, + OnAddrV2: func(p *peer.Peer, msg *wire.MsgAddrV2) { + ok <- msg + }, }, UserAgentName: "peer", UserAgentVersion: "1.0", @@ -456,12 +458,7 @@ func TestPeerListeners(t *testing.T) { TrickleInterval: time.Second * 10, AllowSelfConns: true, } - inConn, outConn := pipe( - &conn{raddr: "10.0.0.1:8333"}, - &conn{raddr: "10.0.0.2:8333"}, - ) inPeer := peer.NewInboundPeer(peerCfg) - inPeer.AssociateConnection(inConn) peerCfg.Listeners = peer.MessageListeners{ OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { @@ -473,7 +470,12 @@ func TestPeerListeners(t *testing.T) { t.Errorf("NewOutboundPeer: unexpected err %v\n", err) return } - outPeer.AssociateConnection(outConn) + + err = setupPeerConnection(inPeer, outPeer) + if err != nil { + t.Errorf("setupPeerConnection: failed: %v\n", err) + return + } for i := 0; i < 2; i++ { select { @@ -597,6 +599,14 @@ func TestPeerListeners(t *testing.T) { "OnSendHeaders", wire.NewMsgSendHeaders(), }, + { + "OnSendAddrV2", + wire.NewMsgSendAddrV2(), + }, + { + "OnAddrV2", + wire.NewMsgAddrV2(), + }, } t.Logf("Running %d tests", len(tests)) for _, test := range tests { @@ -881,17 +891,17 @@ func TestDuplicateVersionMsg(t *testing.T) { Services: 0, AllowSelfConns: true, } - inConn, outConn := pipe( - &conn{laddr: "10.0.0.1:9108", raddr: "10.0.0.2:9108"}, - &conn{laddr: "10.0.0.2:9108", raddr: "10.0.0.1:9108"}, - ) - outPeer, err := peer.NewOutboundPeer(peerCfg, inConn.laddr) + outPeer, err := peer.NewOutboundPeer(peerCfg, "10.0.0.2:8333") if err != nil { t.Fatalf("NewOutboundPeer: unexpected err: %v\n", err) } - outPeer.AssociateConnection(outConn) inPeer := peer.NewInboundPeer(peerCfg) - inPeer.AssociateConnection(inConn) + + err = setupPeerConnection(inPeer, outPeer) + if err != nil { + t.Fatalf("setupPeerConnection failed to connect: %v\n", err) + } + // Wait for the veracks from the initial protocol version negotiation. for i := 0; i < 2; i++ { select { @@ -947,17 +957,16 @@ func TestUpdateLastBlockHeight(t *testing.T) { remotePeerCfg.NewestBlock = func() (*chainhash.Hash, int32, error) { return &chainhash.Hash{}, remotePeerHeight, nil } - inConn, outConn := pipe( - &conn{laddr: "10.0.0.1:9108", raddr: "10.0.0.2:9108"}, - &conn{laddr: "10.0.0.2:9108", raddr: "10.0.0.1:9108"}, - ) - localPeer, err := peer.NewOutboundPeer(&peerCfg, inConn.laddr) + localPeer, err := peer.NewOutboundPeer(&peerCfg, "10.0.0.2:8333") if err != nil { t.Fatalf("NewOutboundPeer: unexpected err: %v\n", err) } - localPeer.AssociateConnection(outConn) inPeer := peer.NewInboundPeer(&remotePeerCfg) - inPeer.AssociateConnection(inConn) + + err = setupPeerConnection(inPeer, localPeer) + if err != nil { + t.Fatalf("setupPeerConnection failed to connect: %v\n", err) + } // Wait for the veracks from the initial protocol version negotiation. for i := 0; i < 2; i++ { @@ -989,3 +998,214 @@ func TestUpdateLastBlockHeight(t *testing.T) { remotePeerHeight+1) } } + +// setupPeerConnection initiates a tcp connection between two peers. +func setupPeerConnection(in, out *peer.Peer) error { + // listenFunc is a function closure that listens for a tcp connection. + // The tcp connection will be the one the inbound peer uses. This will + // be run as a goroutine. + listenFunc := func(l *net.TCPListener, errChan chan error, + listenChan chan struct{}) { + + listenChan <- struct{}{} + + conn, err := l.Accept() + if err != nil { + errChan <- err + return + } + + in.AssociateConnection(conn) + errChan <- nil + } + + // dialFunc is a function closure that initiates the tcp connection. + // The tcp connection will be the one the outbound peer uses. + dialFunc := func(addr *net.TCPAddr) error { + conn, err := net.Dial("tcp", addr.String()) + if err != nil { + return err + } + + out.AssociateConnection(conn) + return nil + } + + listenAddr := "localhost:0" + + addr, err := net.ResolveTCPAddr("tcp", listenAddr) + if err != nil { + return err + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return err + } + + errChan := make(chan error, 1) + listenChan := make(chan struct{}, 1) + + go listenFunc(l, errChan, listenChan) + <-listenChan + + if err := dialFunc(l.Addr().(*net.TCPAddr)); err != nil { + return err + } + + select { + case err = <-errChan: + return err + case <-time.After(time.Second * 2): + return errors.New("failed to create connection") + } +} + +// TestSendAddrV2Handshake tests that the version-verack handshake with the +// addition of the sendaddrv2 message works as expected. +func TestSendAddrV2Handshake(t *testing.T) { + verack := make(chan struct{}, 2) + sendaddr := make(chan struct{}, 2) + peer1Cfg := &peer.Config{ + Listeners: peer.MessageListeners{ + OnVerAck: func(p *peer.Peer, msg *wire.MsgVerAck) { + verack <- struct{}{} + }, + OnSendAddrV2: func(p *peer.Peer, + msg *wire.MsgSendAddrV2) { + + sendaddr <- struct{}{} + }, + }, + AllowSelfConns: true, + ChainParams: &chaincfg.MainNetParams, + } + + peer2Cfg := &peer.Config{ + Listeners: peer1Cfg.Listeners, + AllowSelfConns: true, + ChainParams: &chaincfg.MainNetParams, + } + + verackErr := errors.New("verack timeout") + + tests := []struct { + name string + expectsV2 bool + setup func() (*peer.Peer, *peer.Peer, error) + }{ + { + "successful sendaddrv2 handshake", + true, + func() (*peer.Peer, *peer.Peer, error) { + inPeer := peer.NewInboundPeer(peer1Cfg) + outPeer, err := peer.NewOutboundPeer( + peer2Cfg, "10.0.0.2:8333", + ) + if err != nil { + return nil, nil, err + } + + err = setupPeerConnection(inPeer, outPeer) + if err != nil { + return nil, nil, err + } + + for i := 0; i < 4; i++ { + select { + case <-sendaddr: + case <-verack: + case <-time.After(time.Second * 2): + return nil, nil, verackErr + } + } + + return inPeer, outPeer, nil + }, + }, + { + "handshake with legacy inbound peer", + false, + func() (*peer.Peer, *peer.Peer, error) { + legacyVersion := wire.AddrV2Version - 1 + peer1Cfg.ProtocolVersion = legacyVersion + inPeer := peer.NewInboundPeer(peer1Cfg) + outPeer, err := peer.NewOutboundPeer( + peer2Cfg, "10.0.0.2:8333", + ) + if err != nil { + return nil, nil, err + } + + err = setupPeerConnection(inPeer, outPeer) + if err != nil { + return nil, nil, err + } + + for i := 0; i < 2; i++ { + select { + case <-verack: + case <-time.After(time.Second * 2): + return nil, nil, verackErr + } + } + + return inPeer, outPeer, nil + }, + }, + { + "handshake with legacy outbound peer", + false, + func() (*peer.Peer, *peer.Peer, error) { + inPeer := peer.NewInboundPeer(peer1Cfg) + legacyVersion := wire.AddrV2Version - 1 + peer2Cfg.ProtocolVersion = legacyVersion + outPeer, err := peer.NewOutboundPeer( + peer2Cfg, "10.0.0.2:8333", + ) + if err != nil { + return nil, nil, err + } + + err = setupPeerConnection(inPeer, outPeer) + if err != nil { + return nil, nil, err + } + + for i := 0; i < 2; i++ { + select { + case <-verack: + case <-time.After(time.Second * 2): + return nil, nil, verackErr + } + } + + return inPeer, outPeer, nil + }, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + inPeer, outPeer, err := test.setup() + if err != nil { + t.Fatalf("TestSendAddrV2Handshake setup #%d: "+ + "unexpected err: %v", i, err) + } + + if inPeer.WantsAddrV2() != test.expectsV2 { + t.Fatalf("TestSendAddrV2Handshake #%d expected "+ + "wantsAddrV2 to be %v instead was %v", i, + test.expectsV2, inPeer.WantsAddrV2()) + } else if outPeer.WantsAddrV2() != test.expectsV2 { + t.Fatalf("TestSendAddrV2Handshake #%d expected "+ + "wantsAddrV2 to be %v instead was %v", i, + test.expectsV2, outPeer.WantsAddrV2()) + } + + inPeer.Disconnect() + outPeer.Disconnect() + inPeer.WaitForDisconnect() + outPeer.WaitForDisconnect() + } +} diff --git a/server.go b/server.go index 2b5cc0ff42..5cef434292 100644 --- a/server.go +++ b/server.go @@ -344,6 +344,34 @@ func (sp *serverPeer) relayTxDisabled() bool { // pushAddrMsg sends a legacy addr message to the connected peer using the // provided addresses. func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddressV2) { + if sp.WantsAddrV2() { + // If the peer supports addrv2, we'll be pushing an addrv2 + // message instead. The logic is otherwise identical to the + // addr case below. + addrs := make([]*wire.NetAddressV2, 0, len(addresses)) + for _, addr := range addresses { + // Filter addresses already known to the peer. + if sp.addressKnown(addr) { + continue + } + + addrs = append(addrs, addr) + } + + known, err := sp.PushAddrV2Msg(addrs) + if err != nil { + peerLog.Errorf("Can't push addrv2 message to %s: %v", + sp.Peer, err) + sp.Disconnect() + return + } + + // Add the final set of addresses sent to the set the peer + // knows of. + sp.addKnownAddresses(known) + return + } + addrs := make([]*wire.NetAddress, 0, len(addresses)) for _, addr := range addresses { // Filter addresses already known to the peer. @@ -1328,6 +1356,45 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) { sp.server.addrManager.AddAddresses(addrs, sp.NA()) } +// OnAddrV2 is invoked when a peer receives an addrv2 bitcoin message and is +// used to notify the server about advertised addresses. +func (sp *serverPeer) OnAddrV2(_ *peer.Peer, msg *wire.MsgAddrV2) { + // Ignore if simnet for the same reasons as the regular addr message. + if cfg.SimNet { + return + } + + // An empty AddrV2 message is invalid. + if len(msg.AddrList) == 0 { + peerLog.Errorf("Command [%s] from %s does not contain any "+ + "addresses", msg.Command(), sp.Peer) + sp.Disconnect() + return + } + + for _, na := range msg.AddrList { + // Don't add more to the set of known addresses if we're + // disconnecting. + if !sp.Connected() { + return + } + + // Set the timestamp to 5 days ago if the timestamp received is + // more than 10 minutes in the future so this address is one of + // the first to be removed. + now := time.Now() + if na.Timestamp.After(now.Add(time.Minute * 10)) { + na.Timestamp = now.Add(-1 * time.Hour * 24 * 5) + } + + // Add to the set of known addresses. + sp.addKnownAddresses([]*wire.NetAddressV2{na}) + } + + // Add the addresses to the addrmanager. + sp.server.addrManager.AddAddresses(msg.AddrList, sp.NA()) +} + // OnRead is invoked when a peer receives a message and it is used to update // the bytes received by the server. func (sp *serverPeer) OnRead(_ *peer.Peer, bytesRead int, msg wire.Message, err error) { @@ -2074,6 +2141,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config { OnFilterLoad: sp.OnFilterLoad, OnGetAddr: sp.OnGetAddr, OnAddr: sp.OnAddr, + OnAddrV2: sp.OnAddrV2, OnRead: sp.OnRead, OnWrite: sp.OnWrite, OnNotFound: sp.OnNotFound, diff --git a/wire/message.go b/wire/message.go index 6d3147a81d..1f412fa6fa 100644 --- a/wire/message.go +++ b/wire/message.go @@ -32,6 +32,7 @@ const ( CmdVerAck = "verack" CmdGetAddr = "getaddr" CmdAddr = "addr" + CmdAddrV2 = "addrv2" CmdGetBlocks = "getblocks" CmdInv = "inv" CmdGetData = "getdata" @@ -78,6 +79,13 @@ const ( // protocol. var LatestEncoding = WitnessEncoding +// ErrUnknownMessage is the error returned when decoding an unknown message. +var ErrUnknownMessage = fmt.Errorf("received unknown message") + +// ErrInvalidHandshake is the error returned when a peer sends us a known +// message that does not belong in the version-verack handshake. +var ErrInvalidHandshake = fmt.Errorf("invalid message during handshake") + // Message is an interface that describes a bitcoin message. A type that // implements Message has complete control over the representation of its data // and may therefore contain additional or fewer fields than those which @@ -109,6 +117,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdAddr: msg = &MsgAddr{} + case CmdAddrV2: + msg = &MsgAddrV2{} + case CmdGetBlocks: msg = &MsgGetBlocks{} @@ -185,7 +196,7 @@ func makeEmptyMessage(command string) (Message, error) { msg = &MsgCFCheckpt{} default: - return nil, fmt.Errorf("unhandled command [%s]", command) + return nil, ErrUnknownMessage } return msg, nil } @@ -378,9 +389,10 @@ func ReadMessageWithEncodingN(r io.Reader, pver uint32, btcnet BitcoinNet, // Create struct of appropriate message type based on the command. msg, err := makeEmptyMessage(command) if err != nil { + // makeEmptyMessage can only return ErrUnknownMessage and it is + // important that we bubble it up to the caller. discardInput(r, hdr.length) - return totalBytes, nil, nil, messageError("ReadMessage", - err.Error()) + return totalBytes, nil, nil, err } // Check for maximum length based on the message type as a malicious client diff --git a/wire/message_test.go b/wire/message_test.go index 3a422e66ba..7ba2e0639f 100644 --- a/wire/message_test.go +++ b/wire/message_test.go @@ -295,7 +295,7 @@ func TestReadMessageWireErrors(t *testing.T) { pver, btcnet, len(unsupportedCommandBytes), - &MessageError{}, + ErrUnknownMessage, 24, }, @@ -345,7 +345,7 @@ func TestReadMessageWireErrors(t *testing.T) { pver, btcnet, len(discardBytes), - &MessageError{}, + ErrUnknownMessage, 24, }, } diff --git a/wire/msgaddrv2.go b/wire/msgaddrv2.go new file mode 100644 index 0000000000..4db4a1334a --- /dev/null +++ b/wire/msgaddrv2.go @@ -0,0 +1,102 @@ +package wire + +import ( + "fmt" + "io" +) + +// MaxV2AddrPerMsg is the maximum number of version 2 addresses that will exist +// in a single addrv2 message (MsgAddrV2). +const MaxV2AddrPerMsg = 1000 + +// MsgAddrV2 implements the Message interface and represents a bitcoin addrv2 +// message that can support longer-length addresses like torv3, cjdns, and i2p. +// It is used to gossip addresses on the network. Each message is limited to +// MaxV2AddrPerMsg addresses. This is the same limit as MsgAddr. +type MsgAddrV2 struct { + AddrList []*NetAddressV2 +} + +// BtcDecode decodes r using the bitcoin protocol into a MsgAddrV2. +func (m *MsgAddrV2) BtcDecode(r io.Reader, pver uint32, + enc MessageEncoding) error { + + count, err := ReadVarInt(r, pver) + if err != nil { + return err + } + + // Limit to max addresses per message. + if count > MaxV2AddrPerMsg { + str := fmt.Sprintf("too many addresses for message [count %v,"+ + " max %v]", count, MaxV2AddrPerMsg) + return messageError("MsgAddrV2.BtcDecode", str) + } + + addrList := make([]NetAddressV2, count) + m.AddrList = make([]*NetAddressV2, 0, count) + for i := uint64(0); i < count; i++ { + na := &addrList[i] + err := readNetAddressV2(r, pver, na) + switch err { + case ErrSkippedNetworkID: + // This may be a network ID we don't know of, but is + // still valid. We can safely skip those. + continue + case ErrInvalidAddressSize: + // The encoding used by the peer does not follow + // BIP-155 and we should stop processing this message. + return err + } + + m.AddrList = append(m.AddrList, na) + } + + return nil +} + +// BtcEncode encodes the MsgAddrV2 into a writer w. +func (m *MsgAddrV2) BtcEncode(w io.Writer, pver uint32, + enc MessageEncoding) error { + + count := len(m.AddrList) + if count > MaxV2AddrPerMsg { + str := fmt.Sprintf("too many addresses for message [count %v,"+ + " max %v]", count, MaxV2AddrPerMsg) + return messageError("MsgAddrV2.BtcEncode", str) + } + + err := WriteVarInt(w, pver, uint64(count)) + if err != nil { + return err + } + + for _, na := range m.AddrList { + err = writeNetAddressV2(w, pver, na) + if err != nil { + return err + } + } + + return nil +} + +// Command returns the protocol command string for MsgAddrV2. +func (m *MsgAddrV2) Command() string { + return CmdAddrV2 +} + +// MaxPayloadLength returns the maximum length payload possible for MsgAddrV2. +func (m *MsgAddrV2) MaxPayloadLength(pver uint32) uint32 { + // The varint that can store the maximum number of addresses is 3 bytes + // long. The maximum payload is then 3 + 1000 * maxNetAddressV2Payload. + return 3 + (MaxV2AddrPerMsg * maxNetAddressV2Payload()) +} + +// NewMsgAddrV2 returns a new bitcoin addrv2 message that conforms to the +// Message interface. +func NewMsgAddrV2() *MsgAddrV2 { + return &MsgAddrV2{ + AddrList: make([]*NetAddressV2, 0, MaxV2AddrPerMsg), + } +} diff --git a/wire/msgaddrv2_test.go b/wire/msgaddrv2_test.go new file mode 100644 index 0000000000..213d699c96 --- /dev/null +++ b/wire/msgaddrv2_test.go @@ -0,0 +1,73 @@ +package wire + +import ( + "bytes" + "io" + "testing" +) + +// TestAddrV2Decode checks that decoding an addrv2 message off the wire behaves +// as expected. This means ignoring certain addresses, and failing in certain +// failure scenarios. +func TestAddrV2Decode(t *testing.T) { + tests := []struct { + buf []byte + expectedError bool + expectedAddrs int + }{ + // Exceeding max addresses. + { + []byte{0xfd, 0xff, 0xff}, + true, + 0, + }, + + // Invalid address size. + { + []byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05}, + true, + 0, + }, + + // One valid address and one skipped address + { + []byte{ + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, + 0x7f, 0x00, 0x00, 0x01, 0x22, 0x22, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x10, 0xfd, 0x87, 0xd8, + 0x7e, 0xeb, 0x43, 0xff, 0xfe, 0xcc, 0x39, 0xa8, + 0x73, 0x69, 0x15, 0xff, 0xff, 0x22, 0x22, + }, + false, + 1, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + r := bytes.NewReader(test.buf) + m := &MsgAddrV2{} + + err := m.BtcDecode(r, 0, LatestEncoding) + if test.expectedError { + if err == nil { + t.Errorf("Test #%d expected error", i) + } + + continue + } else if err != nil { + t.Errorf("Test #%d unexpected error %v", i, err) + } + + // Trying to read more should give EOF. + var b [1]byte + if _, err := r.Read(b[:]); err != io.EOF { + t.Errorf("Test #%d did not cleanly finish reading", i) + } + + if len(m.AddrList) != test.expectedAddrs { + t.Errorf("Test #%d expected %d addrs, instead of %d", + i, test.expectedAddrs, len(m.AddrList)) + } + } +} diff --git a/wire/protocol.go b/wire/protocol.go index 8cc9838a55..3b414ec3f1 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -13,7 +13,7 @@ import ( // XXX pedro: we will probably need to bump this. const ( // ProtocolVersion is the latest protocol version this package supports. - ProtocolVersion uint32 = 70013 + ProtocolVersion uint32 = 70016 // MultipleAddressVersion is the protocol version which added multiple // addresses per message (pver >= MultipleAddressVersion). @@ -51,6 +51,13 @@ const ( // FeeFilterVersion is the protocol version which added a new // feefilter message. FeeFilterVersion uint32 = 70013 + + // AddrV2Version is the protocol version which added two new messages. + // sendaddrv2 is sent during the version-verack handshake and signals + // support for sending and receiving the addrv2 message. In the future, + // new messages that occur during the version-verack handshake will not + // come with a protocol version bump. + AddrV2Version uint32 = 70016 ) // ServiceFlag identifies services supported by a bitcoin peer. From 87e3d7e2786b7c5af66b99cfde6be3e3e87035a5 Mon Sep 17 00:00:00 2001 From: Anup Chenthamarakshan Date: Tue, 7 Dec 2021 21:47:27 -0800 Subject: [PATCH 0610/1056] Replace github.com/btcsuite/goleveldb with github.com/syndtr/goleveldb --- btcec/go.sum | 51 +++++++++++++++++++++++++++--- btcutil/go.sum | 55 ++++++++++++++++++++++++++++----- btcutil/psbt/go.sum | 51 +++++++++++++++++++++++++++--- database/ffldb/db.go | 14 ++++----- database/ffldb/dbcache.go | 6 ++-- database/ffldb/ldbtreapiter.go | 4 +-- database/ffldb/whitebox_test.go | 4 +-- go.mod | 4 +-- go.sum | 6 ++-- 9 files changed, 160 insertions(+), 35 deletions(-) diff --git a/btcec/go.sum b/btcec/go.sum index 8ee9102772..3b9835fee9 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -3,8 +3,6 @@ github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v5 github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -14,17 +12,60 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/go.sum b/btcutil/go.sum index 823b9bb378..f6c63a9002 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -4,10 +4,6 @@ github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUB github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -17,19 +13,64 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index 08c53e8b09..876c6e94e4 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -2,8 +2,6 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -13,18 +11,61 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/database/ffldb/db.go b/database/ffldb/db.go index ee36b5b006..f571d3889b 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -19,13 +19,13 @@ import ( "github.com/btcsuite/btcd/database/internal/treap" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/goleveldb/leveldb" - "github.com/btcsuite/goleveldb/leveldb/comparer" - ldberrors "github.com/btcsuite/goleveldb/leveldb/errors" - "github.com/btcsuite/goleveldb/leveldb/filter" - "github.com/btcsuite/goleveldb/leveldb/iterator" - "github.com/btcsuite/goleveldb/leveldb/opt" - "github.com/btcsuite/goleveldb/leveldb/util" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/comparer" + ldberrors "github.com/syndtr/goleveldb/leveldb/errors" + "github.com/syndtr/goleveldb/leveldb/filter" + "github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/syndtr/goleveldb/leveldb/opt" + "github.com/syndtr/goleveldb/leveldb/util" ) const ( diff --git a/database/ffldb/dbcache.go b/database/ffldb/dbcache.go index a2346b58df..ec42ee969e 100644 --- a/database/ffldb/dbcache.go +++ b/database/ffldb/dbcache.go @@ -11,9 +11,9 @@ import ( "time" "github.com/btcsuite/btcd/database/internal/treap" - "github.com/btcsuite/goleveldb/leveldb" - "github.com/btcsuite/goleveldb/leveldb/iterator" - "github.com/btcsuite/goleveldb/leveldb/util" + "github.com/syndtr/goleveldb/leveldb" + "github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/syndtr/goleveldb/leveldb/util" ) const ( diff --git a/database/ffldb/ldbtreapiter.go b/database/ffldb/ldbtreapiter.go index b3d6b6bd58..10ce207c7f 100644 --- a/database/ffldb/ldbtreapiter.go +++ b/database/ffldb/ldbtreapiter.go @@ -6,8 +6,8 @@ package ffldb import ( "github.com/btcsuite/btcd/database/internal/treap" - "github.com/btcsuite/goleveldb/leveldb/iterator" - "github.com/btcsuite/goleveldb/leveldb/util" + "github.com/syndtr/goleveldb/leveldb/iterator" + "github.com/syndtr/goleveldb/leveldb/util" ) // ldbTreapIter wraps a treap iterator to provide the additional functionality diff --git a/database/ffldb/whitebox_test.go b/database/ffldb/whitebox_test.go index 1db69e4215..f2eae8ce09 100644 --- a/database/ffldb/whitebox_test.go +++ b/database/ffldb/whitebox_test.go @@ -21,8 +21,8 @@ import ( "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/goleveldb/leveldb" - ldberrors "github.com/btcsuite/goleveldb/leveldb/errors" + "github.com/syndtr/goleveldb/leveldb" + ldberrors "github.com/syndtr/goleveldb/leveldb/errors" ) var ( diff --git a/go.mod b/go.mod index 2b88125054..7158ca2477 100644 --- a/go.mod +++ b/go.mod @@ -5,20 +5,20 @@ require ( github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd - github.com/btcsuite/goleveldb v1.0.0 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 github.com/btcsuite/winsvc v1.0.0 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/lru v1.0.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 + github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) require ( github.com/aead/siphash v1.0.1 // indirect - github.com/btcsuite/snappy-go v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/golang/snappy v0.0.4 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect ) diff --git a/go.sum b/go.sum index 2645b3566c..ef7c066684 100644 --- a/go.sum +++ b/go.sum @@ -5,9 +5,7 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v1.0.0 h1:Tvd0BfvqX9o823q1j2UZ/epQo09eJh6dTcRp79ilIN4= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJGQE= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= @@ -31,6 +29,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -51,6 +51,8 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= From 7cc824e9b5768375d8d0770258f35bd67845698e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Sat, 12 Feb 2022 22:08:08 +0100 Subject: [PATCH 0611/1056] chainhash: make module --- chaincfg/chainhash/go.mod | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 chaincfg/chainhash/go.mod diff --git a/chaincfg/chainhash/go.mod b/chaincfg/chainhash/go.mod new file mode 100644 index 0000000000..1d865254dd --- /dev/null +++ b/chaincfg/chainhash/go.mod @@ -0,0 +1,3 @@ +module github.com/btcsuite/btcd/chaincfg/chainhash + +go 1.17 From 4ad74cd4c261ab6cbb81b9ee441fc5b0e83be58b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 8 Mar 2022 16:09:59 +0100 Subject: [PATCH 0612/1056] mod: use chaincfg/chainhash module --- btcec/go.mod | 6 +----- btcutil/go.mod | 1 + btcutil/psbt/go.mod | 1 + go.mod | 1 + 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/btcec/go.mod b/btcec/go.mod index 53e4a1f5cb..bc8cf721e3 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -3,13 +3,9 @@ module github.com/btcsuite/btcd/btcec/v2 go 1.17 require ( - github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 ) require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - -// We depend on chainhash as is, so we need to replace to use the version of -// chainhash included in the version of btcd we're building in. -replace github.com/btcsuite/btcd => ../ diff --git a/btcutil/go.mod b/btcutil/go.mod index d3e460e53d..50fe915db3 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -6,6 +6,7 @@ require ( github.com/aead/siphash v1.0.1 github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c github.com/btcsuite/btcd/btcec/v2 v2.1.0 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 3897bf9916..fbf3fe60f9 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -6,6 +6,7 @@ require ( github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c github.com/btcsuite/btcd/btcec/v2 v2.1.0 github.com/btcsuite/btcd/btcutil v1.1.0 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 github.com/davecgh/go-spew v1.1.1 ) diff --git a/go.mod b/go.mod index 7158ca2477..d0825bf986 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/btcsuite/btcd require ( github.com/btcsuite/btcd/btcec/v2 v2.1.0 github.com/btcsuite/btcd/btcutil v1.1.0 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 From 56dfa0f7e21b00b87d95bf3b28e490d4e57de292 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 8 Mar 2022 16:10:12 +0100 Subject: [PATCH 0613/1056] mod: add temporary replace --- btcec/go.mod | 5 +++++ btcutil/go.mod | 5 +++++ btcutil/psbt/go.mod | 5 +++++ go.mod | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/btcec/go.mod b/btcec/go.mod index bc8cf721e3..55485cabcc 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -9,3 +9,8 @@ require ( ) require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + +// We depend on chainhash as is, so we need to replace to use the version of +// chainhash included in the version of btcd we're building in. +// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. +replace github.com/btcsuite/btcd/chaincfg/chainhash => ../chaincfg/chainhash diff --git a/btcutil/go.mod b/btcutil/go.mod index 50fe915db3..142db484d5 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -16,3 +16,8 @@ require ( replace github.com/btcsuite/btcd/btcec/v2 => ../btcec replace github.com/btcsuite/btcd => ../ + +// We depend on chainhash as is, so we need to replace to use the version of +// chainhash included in the version of btcd we're building in. +// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. +replace github.com/btcsuite/btcd/chaincfg/chainhash => ../chaincfg/chainhash diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index fbf3fe60f9..bd209d071c 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -21,3 +21,8 @@ replace github.com/btcsuite/btcd/btcec/v2 => ../../btcec replace github.com/btcsuite/btcd/btcutil => ../ replace github.com/btcsuite/btcd => ../.. + +// We depend on chainhash as is, so we need to replace to use the version of +// chainhash included in the version of btcd we're building in. +// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. +replace github.com/btcsuite/btcd/chaincfg/chainhash => ../../chaincfg/chainhash diff --git a/go.mod b/go.mod index d0825bf986..a38e644d38 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,11 @@ replace github.com/btcsuite/btcd/btcutil => ./btcutil replace github.com/btcsuite/btcd/btcec/v2 => ./btcec +// We depend on chainhash as is, so we need to replace to use the version of +// chainhash included in the version of btcd we're building in. +// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. +replace github.com/btcsuite/btcd/chaincfg/chainhash => ./chaincfg/chainhash + // The retract statements below fixes an accidental push of the tags of a btcd // fork. retract ( From 46f5eec021208616a05691362458912caa2d16c1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 8 Mar 2022 16:15:14 +0100 Subject: [PATCH 0614/1056] mod: bump btcec/v2 module version --- btcutil/go.mod | 2 +- btcutil/psbt/go.mod | 2 +- go.mod | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index 142db484d5..b8de1c3ffd 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c - github.com/btcsuite/btcd/btcec/v2 v2.1.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.1 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index bd209d071c..ffd187018e 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c - github.com/btcsuite/btcd/btcec/v2 v2.1.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.1 github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 github.com/davecgh/go-spew v1.1.1 diff --git a/go.mod b/go.mod index a38e644d38..77d930dd14 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/btcsuite/btcd require ( - github.com/btcsuite/btcd/btcec/v2 v2.1.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.1 github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f From 999514c1fe1e3338c3f6f3597186726f7c08f343 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 8 Mar 2022 16:16:16 +0100 Subject: [PATCH 0615/1056] mod: add TODOs for removing local replaces --- btcutil/go.mod | 1 + btcutil/psbt/go.mod | 1 + go.mod | 1 + 3 files changed, 3 insertions(+) diff --git a/btcutil/go.mod b/btcutil/go.mod index b8de1c3ffd..e6451e4e7a 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -13,6 +13,7 @@ require ( golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) +// TODO(guggero): Remove this as soon as we have a tagged version of btcec/v2. replace github.com/btcsuite/btcd/btcec/v2 => ../btcec replace github.com/btcsuite/btcd => ../ diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index ffd187018e..7ae2dcb86d 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -16,6 +16,7 @@ require ( golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect ) +// TODO(guggero): Remove this as soon as we have a tagged version of btcec/v2. replace github.com/btcsuite/btcd/btcec/v2 => ../../btcec replace github.com/btcsuite/btcd/btcutil => ../ diff --git a/go.mod b/go.mod index 77d930dd14..e56d76e3e0 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( replace github.com/btcsuite/btcd/btcutil => ./btcutil +// TODO(guggero): Remove this as soon as we have a tagged version of btcec/v2. replace github.com/btcsuite/btcd/btcec/v2 => ./btcec // We depend on chainhash as is, so we need to replace to use the version of From 3baa09f33e3c2ab3e2323ad4d04cbbaf150a56af Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 9 Mar 2022 18:53:47 -0800 Subject: [PATCH 0616/1056] build: update to btcec/v2.1.1 and chaincfg/chainhash/v1.00 --- btcec/go.mod | 5 ---- btcec/go.sum | 67 ++------------------------------------------- btcutil/go.mod | 8 ------ btcutil/go.sum | 5 ++++ btcutil/psbt/go.mod | 8 ------ btcutil/psbt/go.sum | 4 +++ go.mod | 8 ------ go.sum | 4 +++ 8 files changed, 15 insertions(+), 94 deletions(-) diff --git a/btcec/go.mod b/btcec/go.mod index 55485cabcc..bc8cf721e3 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -9,8 +9,3 @@ require ( ) require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - -// We depend on chainhash as is, so we need to replace to use the version of -// chainhash included in the version of btcd we're building in. -// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. -replace github.com/btcsuite/btcd/chaincfg/chainhash => ../chaincfg/chainhash diff --git a/btcec/go.sum b/btcec/go.sum index 3b9835fee9..00af17624d 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -1,71 +1,8 @@ -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/btcutil/go.mod b/btcutil/go.mod index e6451e4e7a..ba110830fa 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -13,12 +13,4 @@ require ( golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) -// TODO(guggero): Remove this as soon as we have a tagged version of btcec/v2. -replace github.com/btcsuite/btcd/btcec/v2 => ../btcec - replace github.com/btcsuite/btcd => ../ - -// We depend on chainhash as is, so we need to replace to use the version of -// chainhash included in the version of btcd we're building in. -// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. -replace github.com/btcsuite/btcd/chaincfg/chainhash => ../chaincfg/chainhash diff --git a/btcutil/go.sum b/btcutil/go.sum index f6c63a9002..69c701ee18 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -1,6 +1,11 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.1 h1:xxivBG6pU3wwxx9qPNZP+2K0PXO9VmFLaSrwOFr24Hw= +github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 7ae2dcb86d..4aa9d394c5 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -16,14 +16,6 @@ require ( golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect ) -// TODO(guggero): Remove this as soon as we have a tagged version of btcec/v2. -replace github.com/btcsuite/btcd/btcec/v2 => ../../btcec - replace github.com/btcsuite/btcd/btcutil => ../ replace github.com/btcsuite/btcd => ../.. - -// We depend on chainhash as is, so we need to replace to use the version of -// chainhash included in the version of btcd we're building in. -// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. -replace github.com/btcsuite/btcd/chaincfg/chainhash => ../../chaincfg/chainhash diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index 876c6e94e4..40bb0c16ed 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -1,4 +1,8 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd/btcec/v2 v2.1.1 h1:xxivBG6pU3wwxx9qPNZP+2K0PXO9VmFLaSrwOFr24Hw= +github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/go.mod b/go.mod index e56d76e3e0..a006d957dc 100644 --- a/go.mod +++ b/go.mod @@ -25,14 +25,6 @@ require ( replace github.com/btcsuite/btcd/btcutil => ./btcutil -// TODO(guggero): Remove this as soon as we have a tagged version of btcec/v2. -replace github.com/btcsuite/btcd/btcec/v2 => ./btcec - -// We depend on chainhash as is, so we need to replace to use the version of -// chainhash included in the version of btcd we're building in. -// TODO(guggero): Remove this as soon as we have a tagged version of chainhash. -replace github.com/btcsuite/btcd/chaincfg/chainhash => ./chaincfg/chainhash - // The retract statements below fixes an accidental push of the tags of a btcd // fork. retract ( diff --git a/go.sum b/go.sum index ef7c066684..51aa052060 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,10 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd/btcec/v2 v2.1.1 h1:xxivBG6pU3wwxx9qPNZP+2K0PXO9VmFLaSrwOFr24Hw= +github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= From 10cff8777a4fcd7aa3b193f9f865786f0fd1259d Mon Sep 17 00:00:00 2001 From: vpereira01 <42812459+vpereira01@users.noreply.github.com> Date: Tue, 22 Feb 2022 14:59:23 +0000 Subject: [PATCH 0617/1056] Fixes coveralls coverage report With PR #1785 multiple coverage reports are sent to coveralls. This makes coveralls only consider the last report sent. This fix treat all reports has parallel reports so they can all be compiled later by coveralls. --- .github/workflows/go.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index aeca7e58be..c1625428d3 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -42,21 +42,34 @@ jobs: uses: shogo82148/actions-goveralls@v1 with: path-to-profile: coverage.txt + flag-name: btcd + parallel: true - name: Send btcec uses: shogo82148/actions-goveralls@v1 with: path-to-profile: btcec/coverage.txt + flag-name: btcec + parallel: true - name: Send btcutil coverage uses: shogo82148/actions-goveralls@v1 with: path-to-profile: btcutil/coverage.txt + flag-name: btcutil + parallel: true - name: Send btcutil coverage for psbt package uses: shogo82148/actions-goveralls@v1 with: path-to-profile: btcutil/psbt/coverage.txt + flag-name: btcutilpsbt + parallel: true + + - name: Notify coveralls all reports sent + uses: shogo82148/actions-goveralls@v1 + with: + parallel-finished: true test-race: name: Unit race From 6aac863a252ec9f4fe0fd492922b9006d795274a Mon Sep 17 00:00:00 2001 From: Marnix <93143998+MarnixCroes@users.noreply.github.com> Date: Wed, 9 Feb 2022 00:11:38 +0100 Subject: [PATCH 0618/1056] Update LICENSE Update LICENSE to 2022 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 53ba0c5608..23190babb7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ ISC License -Copyright (c) 2013-2017 The btcsuite developers +Copyright (c) 2013-2022 The btcsuite developers Copyright (c) 2015-2016 The Decred developers Permission to use, copy, modify, and distribute this software for any From bfd0f4a492d7d79030f884198dbabc54fd1592ed Mon Sep 17 00:00:00 2001 From: Brian Stafford Date: Mon, 1 Nov 2021 13:42:22 -0500 Subject: [PATCH 0619/1056] txscript: add taproot script type Add the WitnessV1TaprootTy script class and return it from GetScriptClass / typeOfScript. Bump the btcutil dep to leverage new taproot address type. --- txscript/pkscript.go | 11 +++- txscript/pkscript_test.go | 8 +-- txscript/script.go | 5 +- txscript/script_test.go | 3 +- txscript/standard.go | 132 ++++++++++++++++++++++++-------------- 5 files changed, 103 insertions(+), 56 deletions(-) diff --git a/txscript/pkscript.go b/txscript/pkscript.go index d89c244e41..4998f97b2f 100644 --- a/txscript/pkscript.go +++ b/txscript/pkscript.go @@ -7,9 +7,9 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "golang.org/x/crypto/ripemd160" ) @@ -48,6 +48,9 @@ const ( // witnessV0ScriptHashLen is the length of a P2WSH script. witnessV0ScriptHashLen = 34 + // witnessV1TaprootLen is the length of a P2TR script. + witnessV1TaprootLen = 34 + // maxLen is the maximum script length supported by ParsePkScript. maxLen = witnessV0ScriptHashLen ) @@ -100,7 +103,7 @@ func ParsePkScript(pkScript []byte) (PkScript, error) { func isSupportedScriptType(class ScriptClass) bool { switch class { case PubKeyHashTy, WitnessV0PubKeyHashTy, ScriptHashTy, - WitnessV0ScriptHashTy: + WitnessV0ScriptHashTy, WitnessV1TaprootTy: return true default: return false @@ -133,6 +136,10 @@ func (s PkScript) Script() []byte { script = make([]byte, witnessV0ScriptHashLen) copy(script, s.script[:witnessV0ScriptHashLen]) + case WitnessV1TaprootTy: + script = make([]byte, witnessV1TaprootLen) + copy(script, s.script[:witnessV1TaprootLen]) + default: // Unsupported script type. return nil diff --git a/txscript/pkscript_test.go b/txscript/pkscript_test.go index 49e2db8afa..c82ab04e62 100644 --- a/txscript/pkscript_test.go +++ b/txscript/pkscript_test.go @@ -429,12 +429,12 @@ func TestComputePkScript(t *testing.T) { } if pkScript.Class() != test.class { - t.Fatalf("expected pkScript of type %v, got %v", - test.class, pkScript.Class()) + t.Fatalf("%s: expected pkScript of type %v, got %v", + test.name, test.class, pkScript.Class()) } if !bytes.Equal(pkScript.Script(), test.pkScript) { - t.Fatalf("expected pkScript=%x, got pkScript=%x", - test.pkScript, pkScript.Script()) + t.Fatalf("%s: expected pkScript=%x, got pkScript=%x", + test.name, test.pkScript, pkScript.Script()) } }) } diff --git a/txscript/script.go b/txscript/script.go index 696bfe2d17..1c60b1c55d 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -651,7 +651,7 @@ func countSigOpsV0(script []byte, precise bool) int { // covering 1 through 16 pubkeys, which means this will count any // more than that value (e.g. 17, 18 19) as the maximum number of // allowed pubkeys. This is, unfortunately, now part of - // the Bitcion consensus rules, due to historical + // the Bitcoin consensus rules, due to historical // reasons. This could be made more correct with a new // script version, however, ideally all multisignaure // operations in new script versions should move to @@ -799,6 +799,9 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int { witnessScript := witness[len(witness)-1] return countSigOpsV0(witnessScript, true) } + case 1: + // https://github.com/bitcoin/bitcoin/blob/368831371d97a642beb54b5c4eb6eb0fedaa16b4/src/script/interpreter.cpp#L2090 + return 0 } return 0 diff --git a/txscript/script_test.go b/txscript/script_test.go index 86f94d84f4..a90e1940e5 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -173,6 +173,7 @@ func TestGetPreciseSigOps(t *testing.T) { // nested p2sh, and invalid variants are counted properly. func TestGetWitnessSigOpCount(t *testing.T) { t.Parallel() + tests := []struct { name string @@ -182,7 +183,7 @@ func TestGetWitnessSigOpCount(t *testing.T) { numSigOps int }{ - // A regualr p2wkh witness program. The output being spent + // A regular p2wkh witness program. The output being spent // should only have a single sig-op counted. { name: "p2wkh", diff --git a/txscript/standard.go b/txscript/standard.go index 343a9b2727..1488cd2853 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -7,9 +7,9 @@ package txscript import ( "fmt" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -58,6 +58,7 @@ const ( WitnessV0ScriptHashTy // Pay to witness script hash. MultiSigTy // Multi signature. NullDataTy // Empty data-only (provably prunable). + WitnessV1TaprootTy // Taproot output WitnessUnknownTy // Witness unknown ) @@ -72,6 +73,7 @@ var scriptClassToName = []string{ WitnessV0ScriptHashTy: "witness_v0_scripthash", MultiSigTy: "multisig", NullDataTy: "nulldata", + WitnessV1TaprootTy: "witness_v1_taproot", WitnessUnknownTy: "witness_unknown", } @@ -349,11 +351,11 @@ func IsMultisigSigScript(script []byte) bool { func extractWitnessPubKeyHash(script []byte) []byte { // A pay-to-witness-pubkey-hash script is of the form: // OP_0 OP_DATA_20 <20-byte-hash> - if len(script) == 22 && + if len(script) == witnessV0PubKeyHashLen && script[0] == OP_0 && script[1] == OP_DATA_20 { - return script[2:22] + return script[2:witnessV0PubKeyHashLen] } return nil @@ -365,13 +367,13 @@ func isWitnessPubKeyHashScript(script []byte) bool { return extractWitnessPubKeyHash(script) != nil } -// extractWitnessScriptHash extracts the witness script hash from the passed +// extractWitnessV0ScriptHash extracts the witness script hash from the passed // script if it is standard pay-to-witness-script-hash script. It will return // nil otherwise. -func extractWitnessScriptHash(script []byte) []byte { +func extractWitnessV0ScriptHash(script []byte) []byte { // A pay-to-witness-script-hash script is of the form: // OP_0 OP_DATA_32 <32-byte-hash> - if len(script) == 34 && + if len(script) == witnessV0ScriptHashLen && script[0] == OP_0 && script[1] == OP_DATA_32 { @@ -381,10 +383,26 @@ func extractWitnessScriptHash(script []byte) []byte { return nil } +// extractWitnessV1ScriptHash extracts the witness script hash from the passed +// script if it is standard pay-to-witness-script-hash script. It will return +// nil otherwise. +func extractWitnessV1ScriptHash(script []byte) []byte { + // A pay-to-witness-script-hash script is of the form: + // OP_1 OP_DATA_32 <32-byte-hash> + if len(script) == witnessV1TaprootLen && + script[0] == OP_1 && + script[1] == OP_DATA_32 { + + return script[2:34] + } + + return nil +} + // isWitnessScriptHashScript returns whether or not the passed script is a // standard pay-to-witness-script-hash script. func isWitnessScriptHashScript(script []byte) bool { - return extractWitnessScriptHash(script) != nil + return extractWitnessV0ScriptHash(script) != nil } // extractWitnessProgramInfo returns the version and program if the passed @@ -435,15 +453,28 @@ func extractWitnessProgramInfo(script []byte) (int, []byte, bool) { // smallest program is the witness version, followed by a data push of // 2 bytes. The largest allowed witness program has a data push of // 40-bytes. -// -// NOTE: This function is only valid for version 0 scripts. Since the function -// does not accept a script version, the results are undefined for other script -// versions. func isWitnessProgramScript(script []byte) bool { _, _, valid := extractWitnessProgramInfo(script) return valid } +// isWitnessTaprootScript returns true if the passed script is for a +// pay-to-witness-taproot output, false otherwise. +func isWitnessTaprootScript(script []byte) bool { + return extractWitnessV1ScriptHash(script) != nil +} + +// isAnnexedWitness returns true if the passed witness has a final push +// that is a witness annex. +func isAnnexedWitness(witness [][]byte) bool { + const OP_ANNEX = 0x50 + if len(witness) < 2 { + return false + } + lastElement := witness[len(witness)-1] + return len(lastElement) > 0 && lastElement[0] == OP_ANNEX +} + // isNullDataScript returns whether or not the passed script is a standard // null data script. // @@ -480,41 +511,49 @@ func isNullDataScript(scriptVersion uint16, script []byte) bool { } // scriptType returns the type of the script being inspected from the known -// standard types. -// -// NOTE: All scripts that are not version 0 are currently considered non -// standard. +// standard types. The version version should be 0 if the script is segwit v0 +// or prior, and 1 for segwit v1 (taproot) scripts. func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { - if scriptVersion != 0 { - return NonStandardTy - } - - switch { - case isPubKeyScript(script): - return PubKeyTy - case isPubKeyHashScript(script): - return PubKeyHashTy - case isScriptHashScript(script): - return ScriptHashTy - case isWitnessPubKeyHashScript(script): - return WitnessV0PubKeyHashTy - case isWitnessScriptHashScript(script): - return WitnessV0ScriptHashTy - case isMultisigScript(scriptVersion, script): - return MultiSigTy - case isNullDataScript(scriptVersion, script): - return NullDataTy - default: - return NonStandardTy + switch scriptVersion { + case 0: + switch { + case isPubKeyScript(script): + return PubKeyTy + case isPubKeyHashScript(script): + return PubKeyHashTy + case isScriptHashScript(script): + return ScriptHashTy + case isWitnessPubKeyHashScript(script): + return WitnessV0PubKeyHashTy + case isWitnessScriptHashScript(script): + return WitnessV0ScriptHashTy + case isMultisigScript(scriptVersion, script): + return MultiSigTy + case isNullDataScript(scriptVersion, script): + return NullDataTy + } + case 1: + switch { + case isWitnessTaprootScript(script): + return WitnessV1TaprootTy + } } + return NonStandardTy } // GetScriptClass returns the class of the script passed. // // NonStandardTy will be returned when the script does not parse. func GetScriptClass(script []byte) ScriptClass { - const scriptVersion = 0 - return typeOfScript(scriptVersion, script) + const scriptVersionSegWit = 0 + classSegWit := typeOfScript(scriptVersionSegWit, script) + + if classSegWit != NonStandardTy { + return classSegWit + } + + const scriptVersionTaproot = 1 + return typeOfScript(scriptVersionTaproot, script) } // NewScriptClass returns the ScriptClass corresponding to the string name @@ -561,6 +600,10 @@ func expectedInputs(script []byte, class ScriptClass) int { // Not including script. That is handled by the caller. return 1 + case WitnessV1TaprootTy: + // Not including script. That is handled by the caller. + return 1 + case MultiSigTy: // Standard multisig has a push a small number for the number // of sigs and number of keys. Check the first push instruction @@ -848,10 +891,6 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er // PushedData returns an array of byte slices containing any pushed data found // in the passed script. This includes OP_0, but not OP_1 - OP_16. -// -// NOTE: This function is only valid for version 0 scripts. Since the function -// does not accept a script version, the results are undefined for other script -// versions. func PushedData(script []byte) ([][]byte, error) { const scriptVersion = 0 @@ -900,11 +939,8 @@ func scriptHashToAddrs(hash []byte, params *chaincfg.Params) []btcutil.Address { // signatures associated with the passed PkScript. Note that it only works for // 'standard' transaction script types. Any data such as public keys which are // invalid are omitted from the results. -// -// NOTE: This function only attempts to identify version 0 scripts. The return -// value will indicate a nonstandard script type for other script versions along -// with an invalid script version error. -func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (ScriptClass, []btcutil.Address, int, error) { +func ExtractPkScriptAddrs(pkScript []byte, + chainParams *chaincfg.Params) (ScriptClass, []btcutil.Address, int, error) { // Check for pay-to-pubkey-hash script. if hash := extractPubKeyHash(pkScript); hash != nil { @@ -956,7 +992,7 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (Script return WitnessV0PubKeyHashTy, addrs, 1, nil } - if hash := extractWitnessScriptHash(pkScript); hash != nil { + if hash := extractWitnessV0ScriptHash(pkScript); hash != nil { var addrs []btcutil.Address addr, err := btcutil.NewAddressWitnessScriptHash(hash, chainParams) if err == nil { From 37964e550b4a143edb26411a15ed48f44ad8e285 Mon Sep 17 00:00:00 2001 From: Brian Stafford Date: Mon, 8 Nov 2021 08:25:44 -0600 Subject: [PATCH 0620/1056] txscript: add some txscript support for parsing taproot scripts --- txscript/standard.go | 9 +++++++++ txscript/standard_test.go | 28 +++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 1488cd2853..996177e34e 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -1001,6 +1001,15 @@ func ExtractPkScriptAddrs(pkScript []byte, return WitnessV0ScriptHashTy, addrs, 1, nil } + if hash := extractWitnessV1ScriptHash(pkScript); hash != nil { + var addrs []btcutil.Address + addr, err := btcutil.NewAddressTaproot(hash, chainParams) + if err == nil { + addrs = append(addrs, addr) + } + return WitnessV1TaprootTy, addrs, 1, nil + } + // If none of the above passed, then the address must be non-standard. return NonStandardTy, nil, 0, nil } diff --git a/txscript/standard_test.go b/txscript/standard_test.go index 809bf485d9..d7e209505c 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -11,9 +11,9 @@ import ( "reflect" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // mustParseShortForm parses the passed short form script and returns the @@ -71,6 +71,20 @@ func newAddressScriptHash(scriptHash []byte) btcutil.Address { return addr } +// newAddressTaproot returns a new btcutil.AddressTaproot from the +// provided hash. It panics if an error occurs. This is only used in the tests +// as a helper since the only way it can fail is if there is an error in the +// test source code. +func newAddressTaproot(scriptHash []byte) btcutil.Address { + addr, err := btcutil.NewAddressTaproot(scriptHash, + &chaincfg.MainNetParams) + if err != nil { + panic("invalid script hash in test source") + } + + return addr +} + // TestExtractPkScriptAddrs ensures that extracting the type, addresses, and // number of required signatures from PkScripts works as intended. func TestExtractPkScriptAddrs(t *testing.T) { @@ -311,8 +325,16 @@ func TestExtractPkScriptAddrs(t *testing.T) { reqSigs: 1, class: MultiSigTy, }, - // from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44 - // invalid public keys + { + name: "v1 p2tr witness-script-hash", + script: hexToBytes("51201a82f7457a9ba6ab1074e9f50" + + "053eefc637f8b046e389b636766bdc7d1f676f8"), + addrs: []btcutil.Address{newAddressTaproot( + hexToBytes("1a82f7457a9ba6ab1074e9f50053eefc6" + + "37f8b046e389b636766bdc7d1f676f8"))}, + reqSigs: 1, + class: WitnessV1TaprootTy, + }, { name: "1 of 3 multisig with invalid pubkeys 2", script: hexToBytes("514134633365633235396337346461636" + From 3ddf1b51a62f9d1f33ba90971b4c26750e6ac866 Mon Sep 17 00:00:00 2001 From: Brian Stafford Date: Mon, 22 Nov 2021 21:52:54 -0600 Subject: [PATCH 0621/1056] txscript: add taproot support to PayToAddrScript Add taproot address handling in PayToAddrScript. Adds a test and also some missing tests for p2wsh and p2wpkh addresses. --- txscript/standard.go | 12 +++++++++++ txscript/standard_test.go | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/txscript/standard.go b/txscript/standard.go index 996177e34e..4a3097a4d4 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -801,6 +801,12 @@ func payToWitnessScriptHashScript(scriptHash []byte) ([]byte, error) { return NewScriptBuilder().AddOp(OP_0).AddData(scriptHash).Script() } +// payToWitnessTaprootScript creates a new script to pay to a version 1 +// (taproot) witness program. The passed hash is expected to be valid. +func payToWitnessTaprootScript(scriptHash []byte) ([]byte, error) { + return NewScriptBuilder().AddOp(OP_1).AddData(scriptHash).Script() +} + // payToPubkeyScript creates a new script to pay a transaction output to a // public key. It is expected that the input is a valid pubkey. func payToPubKeyScript(serializedPubKey []byte) ([]byte, error) { @@ -847,6 +853,12 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) { nilAddrErrStr) } return payToWitnessScriptHashScript(addr.ScriptAddress()) + case *btcutil.AddressTaproot: + if addr == nil { + return nil, scriptError(ErrUnsupportedAddress, + nilAddrErrStr) + } + return payToWitnessTaprootScript(addr.ScriptAddress()) } str := fmt.Sprintf("unable to generate payment script for unsupported "+ diff --git a/txscript/standard_test.go b/txscript/standard_test.go index d7e209505c..283e2ccb7b 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -659,6 +659,27 @@ func TestPayToAddrScript(t *testing.T) { err) } + p2wsh, err := btcutil.NewAddressWitnessScriptHash(hexToBytes("e981bd992a43650657"+ + "d705ef7a30b2adc75a927ed42a4cf6b3da0f865a475fb4"), &chaincfg.MainNetParams) + if err != nil { + t.Fatalf("Unable to create p2wsh address: %v", + err) + } + + p2tr, err := btcutil.NewAddressTaproot(hexToBytes("3a8e170b546c3b122ab9c175e"+ + "ff36fb344db2684fe96497eb51b440e75232709"), &chaincfg.MainNetParams) + if err != nil { + t.Fatalf("Unable to create p2tr address: %v", + err) + } + + p2wpkh, err := btcutil.NewAddressWitnessPubKeyHash(hexToBytes("748e50366adb8"+ + "ae4b0255e406a28f99d24b73cbc"), &chaincfg.MainNetParams) + if err != nil { + t.Fatalf("Unable to create p2wpkh address: %v", + err) + } + // Errors used in the tests below defined here for convenience and to // keep the horizontal test size shorter. errUnsupportedAddress := scriptError(ErrUnsupportedAddress, "") @@ -705,11 +726,34 @@ func TestPayToAddrScript(t *testing.T) { "CHECKSIG", nil, }, + // pay-to-witness-script-hash address on mainnet. + { + p2wsh, + "OP_0 DATA_32 0xe981bd992a43650657d705ef7a30b2adc75a927ed" + + "42a4cf6b3da0f865a475fb4", + nil, + }, + // pay-to-taproot address on mainnet. + { + p2tr, + "OP_1 DATA_32 0x3a8e170b546c3b122ab9c175eff36fb344db2684" + + "fe96497eb51b440e75232709", + nil, + }, + // pay-to-witness-pubkey-hash address on mainnet. + { + p2wpkh, + "OP_0 DATA_20 0x748e50366adb8ae4b0255e406a28f99d24b73cbc", + nil, + }, // Supported address types with nil pointers. {(*btcutil.AddressPubKeyHash)(nil), "", errUnsupportedAddress}, {(*btcutil.AddressScriptHash)(nil), "", errUnsupportedAddress}, {(*btcutil.AddressPubKey)(nil), "", errUnsupportedAddress}, + {(*btcutil.AddressWitnessPubKeyHash)(nil), "", errUnsupportedAddress}, + {(*btcutil.AddressWitnessScriptHash)(nil), "", errUnsupportedAddress}, + {(*btcutil.AddressTaproot)(nil), "", errUnsupportedAddress}, // Unsupported address type. {&bogusAddress{}, "", errUnsupportedAddress}, From cfe801fe2e0930c1a8532ff6d126ec88ffd21be2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:10:36 -0800 Subject: [PATCH 0622/1056] txscript: move hash cache mid-state computation to hashcache.go file --- txscript/hashcache.go | 56 +++++++++++++++++++++++++++++++++++++++++++ txscript/script.go | 54 ----------------------------------------- 2 files changed, 56 insertions(+), 54 deletions(-) diff --git a/txscript/hashcache.go b/txscript/hashcache.go index f9c2caf76c..6db734992e 100644 --- a/txscript/hashcache.go +++ b/txscript/hashcache.go @@ -5,12 +5,68 @@ package txscript import ( + "bytes" + "encoding/binary" "sync" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) +// calcHashPrevOuts calculates a single hash of all the previous outputs +// (txid:index) referenced within the passed transaction. This calculated hash +// can be re-used when validating all inputs spending segwit outputs, with a +// signature hash type of SigHashAll. This allows validation to re-use previous +// hashing computation, reducing the complexity of validating SigHashAll inputs +// from O(N^2) to O(N). +func calcHashPrevOuts(tx *wire.MsgTx) chainhash.Hash { + var b bytes.Buffer + for _, in := range tx.TxIn { + // First write out the 32-byte transaction ID one of whose + // outputs are being referenced by this input. + b.Write(in.PreviousOutPoint.Hash[:]) + + // Next, we'll encode the index of the referenced output as a + // little endian integer. + var buf [4]byte + binary.LittleEndian.PutUint32(buf[:], in.PreviousOutPoint.Index) + b.Write(buf[:]) + } + + return chainhash.HashH(b.Bytes()) +} + +// calcHashSequence computes an aggregated hash of each of the sequence numbers +// within the inputs of the passed transaction. This single hash can be re-used +// when validating all inputs spending segwit outputs, which include signatures +// using the SigHashAll sighash type. This allows validation to re-use previous +// hashing computation, reducing the complexity of validating SigHashAll inputs +// from O(N^2) to O(N). +func calcHashSequence(tx *wire.MsgTx) chainhash.Hash { + var b bytes.Buffer + for _, in := range tx.TxIn { + var buf [4]byte + binary.LittleEndian.PutUint32(buf[:], in.Sequence) + b.Write(buf[:]) + } + + return chainhash.HashH(b.Bytes()) +} + +// calcHashOutputs computes a hash digest of all outputs created by the +// transaction encoded using the wire format. This single hash can be re-used +// when validating all inputs spending witness programs, which include +// signatures using the SigHashAll sighash type. This allows computation to be +// cached, reducing the total hashing complexity from O(N^2) to O(N). +func calcHashOutputs(tx *wire.MsgTx) chainhash.Hash { + var b bytes.Buffer + for _, out := range tx.TxOut { + wire.WriteTxOut(&b, 0, 0, out) + } + + return chainhash.HashH(b.Bytes()) +} + // TxSigHashes houses the partial set of sighashes introduced within BIP0143. // This partial set of sighashes may be re-used within each input across a // transaction when validating all inputs. As a result, validation complexity diff --git a/txscript/script.go b/txscript/script.go index 1c60b1c55d..233f62bd33 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -292,60 +292,6 @@ func removeOpcodeByData(script []byte, dataToRemove []byte) []byte { return result } -// calcHashPrevOuts calculates a single hash of all the previous outputs -// (txid:index) referenced within the passed transaction. This calculated hash -// can be re-used when validating all inputs spending segwit outputs, with a -// signature hash type of SigHashAll. This allows validation to re-use previous -// hashing computation, reducing the complexity of validating SigHashAll inputs -// from O(N^2) to O(N). -func calcHashPrevOuts(tx *wire.MsgTx) chainhash.Hash { - var b bytes.Buffer - for _, in := range tx.TxIn { - // First write out the 32-byte transaction ID one of whose - // outputs are being referenced by this input. - b.Write(in.PreviousOutPoint.Hash[:]) - - // Next, we'll encode the index of the referenced output as a - // little endian integer. - var buf [4]byte - binary.LittleEndian.PutUint32(buf[:], in.PreviousOutPoint.Index) - b.Write(buf[:]) - } - - return chainhash.DoubleHashH(b.Bytes()) -} - -// calcHashSequence computes an aggregated hash of each of the sequence numbers -// within the inputs of the passed transaction. This single hash can be re-used -// when validating all inputs spending segwit outputs, which include signatures -// using the SigHashAll sighash type. This allows validation to re-use previous -// hashing computation, reducing the complexity of validating SigHashAll inputs -// from O(N^2) to O(N). -func calcHashSequence(tx *wire.MsgTx) chainhash.Hash { - var b bytes.Buffer - for _, in := range tx.TxIn { - var buf [4]byte - binary.LittleEndian.PutUint32(buf[:], in.Sequence) - b.Write(buf[:]) - } - - return chainhash.DoubleHashH(b.Bytes()) -} - -// calcHashOutputs computes a hash digest of all outputs created by the -// transaction encoded using the wire format. This single hash can be re-used -// when validating all inputs spending witness programs, which include -// signatures using the SigHashAll sighash type. This allows computation to be -// cached, reducing the total hashing complexity from O(N^2) to O(N). -func calcHashOutputs(tx *wire.MsgTx) chainhash.Hash { - var b bytes.Buffer - for _, out := range tx.TxOut { - wire.WriteTxOut(&b, 0, 0, out) - } - - return chainhash.DoubleHashH(b.Bytes()) -} - // calcWitnessSignatureHashRaw computes the sighash digest of a transaction's // segwit input using the new, optimized digest calculation algorithm defined // in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. From 81a546bdedfdb6e5f6dded3ecde2fc9342b4a436 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:30:28 -0800 Subject: [PATCH 0623/1056] wire: export WriteOutPoint to public module --- wire/bench_test.go | 2 +- wire/msgtx.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index f6637d4210..c183df56e5 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -200,7 +200,7 @@ func BenchmarkWriteOutPoint(b *testing.B) { Index: 0, } for i := 0; i < b.N; i++ { - writeOutPoint(ioutil.Discard, 0, 0, op) + WriteOutPoint(ioutil.Discard, 0, 0, op) } } diff --git a/wire/msgtx.go b/wire/msgtx.go index 1e2f69fad4..6cd591e3be 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -930,9 +930,9 @@ func readOutPoint(r io.Reader, pver uint32, version int32, op *OutPoint) error { return err } -// writeOutPoint encodes op to the bitcoin protocol encoding for an OutPoint +// WriteOutPoint encodes op to the bitcoin protocol encoding for an OutPoint // to w. -func writeOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { +func WriteOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { _, err := w.Write(op.Hash[:]) if err != nil { return err @@ -992,7 +992,7 @@ func readTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { // writeTxIn encodes ti to the bitcoin protocol encoding for a transaction // input (TxIn) to w. func writeTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { - err := writeOutPoint(w, pver, version, &ti.PreviousOutPoint) + err := WriteOutPoint(w, pver, version, &ti.PreviousOutPoint) if err != nil { return err } From 30d93272a8e6056c58f54a1f1be7dde52697adb3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:22:49 -0800 Subject: [PATCH 0624/1056] txscript: add new IsPayToTaproot utility func --- txscript/script.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/txscript/script.go b/txscript/script.go index 233f62bd33..d6ae2f5e2f 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -90,6 +90,12 @@ func IsPayToWitnessPubKeyHash(script []byte) bool { return isWitnessPubKeyHashScript(script) } +// IsPayToTaproot returns true if if the passed script is a standard +// pay-to-taproot (PTTR) scripts, and false otherwise. +func IsPayToTaproot(script []byte) bool { + return isWitnessTaprootScript(script) +} + // IsWitnessProgram returns true if the passed script is a valid witness // program which is encoded according to the passed witness program version. A // witness program must be a small integer (from 0-16), followed by 2-40 bytes From 6ecc72e5e63dd148b7260bca351caf701558b62c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 20 Feb 2022 16:05:14 -0800 Subject: [PATCH 0625/1056] txscript: move sighash computations to new file --- txscript/script.go | 265 ----------------------------------------- txscript/sighash.go | 280 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+), 265 deletions(-) create mode 100644 txscript/sighash.go diff --git a/txscript/script.go b/txscript/script.go index d6ae2f5e2f..e2d708247c 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -7,12 +7,10 @@ package txscript import ( "bytes" - "encoding/binary" "fmt" "strings" "time" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) @@ -298,269 +296,6 @@ func removeOpcodeByData(script []byte, dataToRemove []byte) []byte { return result } -// calcWitnessSignatureHashRaw computes the sighash digest of a transaction's -// segwit input using the new, optimized digest calculation algorithm defined -// in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. -// This function makes use of pre-calculated sighash fragments stored within -// the passed HashCache to eliminate duplicate hashing computations when -// calculating the final digest, reducing the complexity from O(N^2) to O(N). -// Additionally, signatures now cover the input value of the referenced unspent -// output. This allows offline, or hardware wallets to compute the exact amount -// being spent, in addition to the final transaction fee. In the case the -// wallet if fed an invalid input amount, the real sighash will differ causing -// the produced signature to be invalid. -func calcWitnessSignatureHashRaw(scriptSig []byte, sigHashes *TxSigHashes, - hashType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { - - // As a sanity check, ensure the passed input index for the transaction - // is valid. - if idx > len(tx.TxIn)-1 { - return nil, fmt.Errorf("idx %d but %d txins", idx, len(tx.TxIn)) - } - - // We'll utilize this buffer throughout to incrementally calculate - // the signature hash for this transaction. - var sigHash bytes.Buffer - - // First write out, then encode the transaction's version number. - var bVersion [4]byte - binary.LittleEndian.PutUint32(bVersion[:], uint32(tx.Version)) - sigHash.Write(bVersion[:]) - - // Next write out the possibly pre-calculated hashes for the sequence - // numbers of all inputs, and the hashes of the previous outs for all - // outputs. - var zeroHash chainhash.Hash - - // If anyone can pay isn't active, then we can use the cached - // hashPrevOuts, otherwise we just write zeroes for the prev outs. - if hashType&SigHashAnyOneCanPay == 0 { - sigHash.Write(sigHashes.HashPrevOuts[:]) - } else { - sigHash.Write(zeroHash[:]) - } - - // If the sighash isn't anyone can pay, single, or none, the use the - // cached hash sequences, otherwise write all zeroes for the - // hashSequence. - if hashType&SigHashAnyOneCanPay == 0 && - hashType&sigHashMask != SigHashSingle && - hashType&sigHashMask != SigHashNone { - sigHash.Write(sigHashes.HashSequence[:]) - } else { - sigHash.Write(zeroHash[:]) - } - - txIn := tx.TxIn[idx] - - // Next, write the outpoint being spent. - sigHash.Write(txIn.PreviousOutPoint.Hash[:]) - var bIndex [4]byte - binary.LittleEndian.PutUint32(bIndex[:], txIn.PreviousOutPoint.Index) - sigHash.Write(bIndex[:]) - - if isWitnessPubKeyHashScript(scriptSig) { - // The script code for a p2wkh is a length prefix varint for - // the next 25 bytes, followed by a re-creation of the original - // p2pkh pk script. - sigHash.Write([]byte{0x19}) - sigHash.Write([]byte{OP_DUP}) - sigHash.Write([]byte{OP_HASH160}) - sigHash.Write([]byte{OP_DATA_20}) - sigHash.Write(extractWitnessPubKeyHash(scriptSig)) - sigHash.Write([]byte{OP_EQUALVERIFY}) - sigHash.Write([]byte{OP_CHECKSIG}) - } else { - // For p2wsh outputs, and future outputs, the script code is - // the original script, with all code separators removed, - // serialized with a var int length prefix. - wire.WriteVarBytes(&sigHash, 0, scriptSig) - } - - // Next, add the input amount, and sequence number of the input being - // signed. - var bAmount [8]byte - binary.LittleEndian.PutUint64(bAmount[:], uint64(amt)) - sigHash.Write(bAmount[:]) - var bSequence [4]byte - binary.LittleEndian.PutUint32(bSequence[:], txIn.Sequence) - sigHash.Write(bSequence[:]) - - // If the current signature mode isn't single, or none, then we can - // re-use the pre-generated hashoutputs sighash fragment. Otherwise, - // we'll serialize and add only the target output index to the signature - // pre-image. - if hashType&SigHashSingle != SigHashSingle && - hashType&SigHashNone != SigHashNone { - sigHash.Write(sigHashes.HashOutputs[:]) - } else if hashType&sigHashMask == SigHashSingle && idx < len(tx.TxOut) { - var b bytes.Buffer - wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx]) - sigHash.Write(chainhash.DoubleHashB(b.Bytes())) - } else { - sigHash.Write(zeroHash[:]) - } - - // Finally, write out the transaction's locktime, and the sig hash - // type. - var bLockTime [4]byte - binary.LittleEndian.PutUint32(bLockTime[:], tx.LockTime) - sigHash.Write(bLockTime[:]) - var bHashType [4]byte - binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType)) - sigHash.Write(bHashType[:]) - - return chainhash.DoubleHashB(sigHash.Bytes()), nil -} - -// CalcWitnessSigHash computes the sighash digest for the specified input of -// the target transaction observing the desired sig hash type. -func CalcWitnessSigHash(script []byte, sigHashes *TxSigHashes, hType SigHashType, - tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { - - const scriptVersion = 0 - if err := checkScriptParses(scriptVersion, script); err != nil { - return nil, err - } - - return calcWitnessSignatureHashRaw(script, sigHashes, hType, tx, idx, amt) -} - -// shallowCopyTx creates a shallow copy of the transaction for use when -// calculating the signature hash. It is used over the Copy method on the -// transaction itself since that is a deep copy and therefore does more work and -// allocates much more space than needed. -func shallowCopyTx(tx *wire.MsgTx) wire.MsgTx { - // As an additional memory optimization, use contiguous backing arrays - // for the copied inputs and outputs and point the final slice of - // pointers into the contiguous arrays. This avoids a lot of small - // allocations. - txCopy := wire.MsgTx{ - Version: tx.Version, - TxIn: make([]*wire.TxIn, len(tx.TxIn)), - TxOut: make([]*wire.TxOut, len(tx.TxOut)), - LockTime: tx.LockTime, - } - txIns := make([]wire.TxIn, len(tx.TxIn)) - for i, oldTxIn := range tx.TxIn { - txIns[i] = *oldTxIn - txCopy.TxIn[i] = &txIns[i] - } - txOuts := make([]wire.TxOut, len(tx.TxOut)) - for i, oldTxOut := range tx.TxOut { - txOuts[i] = *oldTxOut - txCopy.TxOut[i] = &txOuts[i] - } - return txCopy -} - -// CalcSignatureHash will, given a script and hash type for the current script -// engine instance, calculate the signature hash to be used for signing and -// verification. -// -// NOTE: This function is only valid for version 0 scripts. Since the function -// does not accept a script version, the results are undefined for other script -// versions. -func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) { - const scriptVersion = 0 - if err := checkScriptParses(scriptVersion, script); err != nil { - return nil, err - } - - return calcSignatureHash(script, hashType, tx, idx), nil -} - -// calcSignatureHash computes the signature hash for the specified input of the -// target transaction observing the desired signature hash type. -func calcSignatureHash(sigScript []byte, hashType SigHashType, tx *wire.MsgTx, idx int) []byte { - // The SigHashSingle signature type signs only the corresponding input - // and output (the output with the same index number as the input). - // - // Since transactions can have more inputs than outputs, this means it - // is improper to use SigHashSingle on input indices that don't have a - // corresponding output. - // - // A bug in the original Satoshi client implementation means specifying - // an index that is out of range results in a signature hash of 1 (as a - // uint256 little endian). The original intent appeared to be to - // indicate failure, but unfortunately, it was never checked and thus is - // treated as the actual signature hash. This buggy behavior is now - // part of the consensus and a hard fork would be required to fix it. - // - // Due to this, care must be taken by software that creates transactions - // which make use of SigHashSingle because it can lead to an extremely - // dangerous situation where the invalid inputs will end up signing a - // hash of 1. This in turn presents an opportunity for attackers to - // cleverly construct transactions which can steal those coins provided - // they can reuse signatures. - if hashType&sigHashMask == SigHashSingle && idx >= len(tx.TxOut) { - var hash chainhash.Hash - hash[0] = 0x01 - return hash[:] - } - - // Remove all instances of OP_CODESEPARATOR from the script. - sigScript = removeOpcodeRaw(sigScript, OP_CODESEPARATOR) - - // Make a shallow copy of the transaction, zeroing out the script for - // all inputs that are not currently being processed. - txCopy := shallowCopyTx(tx) - for i := range txCopy.TxIn { - if i == idx { - txCopy.TxIn[idx].SignatureScript = sigScript - } else { - txCopy.TxIn[i].SignatureScript = nil - } - } - - switch hashType & sigHashMask { - case SigHashNone: - txCopy.TxOut = txCopy.TxOut[0:0] // Empty slice. - for i := range txCopy.TxIn { - if i != idx { - txCopy.TxIn[i].Sequence = 0 - } - } - - case SigHashSingle: - // Resize output array to up to and including requested index. - txCopy.TxOut = txCopy.TxOut[:idx+1] - - // All but current output get zeroed out. - for i := 0; i < idx; i++ { - txCopy.TxOut[i].Value = -1 - txCopy.TxOut[i].PkScript = nil - } - - // Sequence on all other inputs is 0, too. - for i := range txCopy.TxIn { - if i != idx { - txCopy.TxIn[i].Sequence = 0 - } - } - - default: - // Consensus treats undefined hashtypes like normal SigHashAll - // for purposes of hash generation. - fallthrough - case SigHashOld: - fallthrough - case SigHashAll: - // Nothing special here. - } - if hashType&SigHashAnyOneCanPay != 0 { - txCopy.TxIn = txCopy.TxIn[idx : idx+1] - } - - // The final hash is the double sha256 of both the serialized modified - // transaction and the hash type (encoded as a 4-byte little-endian - // value) appended. - wbuf := bytes.NewBuffer(make([]byte, 0, txCopy.SerializeSizeStripped()+4)) - txCopy.SerializeNoWitness(wbuf) - binary.Write(wbuf, binary.LittleEndian, hashType) - return chainhash.DoubleHashB(wbuf.Bytes()) -} - // asSmallInt returns the passed opcode, which must be true according to // isSmallInt(), as an integer. func asSmallInt(op byte) int { diff --git a/txscript/sighash.go b/txscript/sighash.go new file mode 100644 index 0000000000..1cee804b96 --- /dev/null +++ b/txscript/sighash.go @@ -0,0 +1,280 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2019 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txscript + +import ( + "bytes" + "encoding/binary" + "fmt" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// shallowCopyTx creates a shallow copy of the transaction for use when +// calculating the signature hash. It is used over the Copy method on the +// transaction itself since that is a deep copy and therefore does more work and +// allocates much more space than needed. +func shallowCopyTx(tx *wire.MsgTx) wire.MsgTx { + // As an additional memory optimization, use contiguous backing arrays + // for the copied inputs and outputs and point the final slice of + // pointers into the contiguous arrays. This avoids a lot of small + // allocations. + txCopy := wire.MsgTx{ + Version: tx.Version, + TxIn: make([]*wire.TxIn, len(tx.TxIn)), + TxOut: make([]*wire.TxOut, len(tx.TxOut)), + LockTime: tx.LockTime, + } + txIns := make([]wire.TxIn, len(tx.TxIn)) + for i, oldTxIn := range tx.TxIn { + txIns[i] = *oldTxIn + txCopy.TxIn[i] = &txIns[i] + } + txOuts := make([]wire.TxOut, len(tx.TxOut)) + for i, oldTxOut := range tx.TxOut { + txOuts[i] = *oldTxOut + txCopy.TxOut[i] = &txOuts[i] + } + return txCopy +} + +// CalcSignatureHash will, given a script and hash type for the current script +// engine instance, calculate the signature hash to be used for signing and +// verification. +// +// NOTE: This function is only valid for version 0 scripts. Since the function +// does not accept a script version, the results are undefined for other script +// versions. +func CalcSignatureHash(script []byte, hashType SigHashType, tx *wire.MsgTx, idx int) ([]byte, error) { + const scriptVersion = 0 + if err := checkScriptParses(scriptVersion, script); err != nil { + return nil, err + } + + return calcSignatureHash(script, hashType, tx, idx), nil +} + +// calcSignatureHash computes the signature hash for the specified input of the +// target transaction observing the desired signature hash type. +func calcSignatureHash(sigScript []byte, hashType SigHashType, tx *wire.MsgTx, idx int) []byte { + // The SigHashSingle signature type signs only the corresponding input + // and output (the output with the same index number as the input). + // + // Since transactions can have more inputs than outputs, this means it + // is improper to use SigHashSingle on input indices that don't have a + // corresponding output. + // + // A bug in the original Satoshi client implementation means specifying + // an index that is out of range results in a signature hash of 1 (as a + // uint256 little endian). The original intent appeared to be to + // indicate failure, but unfortunately, it was never checked and thus is + // treated as the actual signature hash. This buggy behavior is now + // part of the consensus and a hard fork would be required to fix it. + // + // Due to this, care must be taken by software that creates transactions + // which make use of SigHashSingle because it can lead to an extremely + // dangerous situation where the invalid inputs will end up signing a + // hash of 1. This in turn presents an opportunity for attackers to + // cleverly construct transactions which can steal those coins provided + // they can reuse signatures. + if hashType&sigHashMask == SigHashSingle && idx >= len(tx.TxOut) { + var hash chainhash.Hash + hash[0] = 0x01 + return hash[:] + } + + // Remove all instances of OP_CODESEPARATOR from the script. + sigScript = removeOpcodeRaw(sigScript, OP_CODESEPARATOR) + + // Make a shallow copy of the transaction, zeroing out the script for + // all inputs that are not currently being processed. + txCopy := shallowCopyTx(tx) + for i := range txCopy.TxIn { + if i == idx { + txCopy.TxIn[idx].SignatureScript = sigScript + } else { + txCopy.TxIn[i].SignatureScript = nil + } + } + + switch hashType & sigHashMask { + case SigHashNone: + txCopy.TxOut = txCopy.TxOut[0:0] // Empty slice. + for i := range txCopy.TxIn { + if i != idx { + txCopy.TxIn[i].Sequence = 0 + } + } + + case SigHashSingle: + // Resize output array to up to and including requested index. + txCopy.TxOut = txCopy.TxOut[:idx+1] + + // All but current output get zeroed out. + for i := 0; i < idx; i++ { + txCopy.TxOut[i].Value = -1 + txCopy.TxOut[i].PkScript = nil + } + + // Sequence on all other inputs is 0, too. + for i := range txCopy.TxIn { + if i != idx { + txCopy.TxIn[i].Sequence = 0 + } + } + + default: + // Consensus treats undefined hashtypes like normal SigHashAll + // for purposes of hash generation. + fallthrough + case SigHashOld: + fallthrough + case SigHashAll: + // Nothing special here. + } + if hashType&SigHashAnyOneCanPay != 0 { + txCopy.TxIn = txCopy.TxIn[idx : idx+1] + } + + // The final hash is the double sha256 of both the serialized modified + // transaction and the hash type (encoded as a 4-byte little-endian + // value) appended. + wbuf := bytes.NewBuffer(make([]byte, 0, txCopy.SerializeSizeStripped()+4)) + txCopy.SerializeNoWitness(wbuf) + binary.Write(wbuf, binary.LittleEndian, hashType) + return chainhash.DoubleHashB(wbuf.Bytes()) +} + +// calcWitnessSignatureHashRaw computes the sighash digest of a transaction's +// segwit input using the new, optimized digest calculation algorithm defined +// in BIP0143: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki. +// This function makes use of pre-calculated sighash fragments stored within +// the passed HashCache to eliminate duplicate hashing computations when +// calculating the final digest, reducing the complexity from O(N^2) to O(N). +// Additionally, signatures now cover the input value of the referenced unspent +// output. This allows offline, or hardware wallets to compute the exact amount +// being spent, in addition to the final transaction fee. In the case the +// wallet if fed an invalid input amount, the real sighash will differ causing +// the produced signature to be invalid. +func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, + hashType SigHashType, tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { + + // As a sanity check, ensure the passed input index for the transaction + // is valid. + // + // TODO(roasbeef): check needs to be lifted elsewhere? + if idx > len(tx.TxIn)-1 { + return nil, fmt.Errorf("idx %d but %d txins", idx, len(tx.TxIn)) + } + + // We'll utilize this buffer throughout to incrementally calculate + // the signature hash for this transaction. + var sigHash bytes.Buffer + + // First write out, then encode the transaction's version number. + var bVersion [4]byte + binary.LittleEndian.PutUint32(bVersion[:], uint32(tx.Version)) + sigHash.Write(bVersion[:]) + + // Next write out the possibly pre-calculated hashes for the sequence + // numbers of all inputs, and the hashes of the previous outs for all + // outputs. + var zeroHash chainhash.Hash + + // If anyone can pay isn't active, then we can use the cached + // hashPrevOuts, otherwise we just write zeroes for the prev outs. + if hashType&SigHashAnyOneCanPay == 0 { + sigHash.Write(sigHashes.HashPrevOuts[:]) + } else { + sigHash.Write(zeroHash[:]) + } + + // If the sighash isn't anyone can pay, single, or none, the use the + // cached hash sequences, otherwise write all zeroes for the + // hashSequence. + if hashType&SigHashAnyOneCanPay == 0 && + hashType&sigHashMask != SigHashSingle && + hashType&sigHashMask != SigHashNone { + sigHash.Write(sigHashes.HashSequence[:]) + } else { + sigHash.Write(zeroHash[:]) + } + + txIn := tx.TxIn[idx] + + // Next, write the outpoint being spent. + sigHash.Write(txIn.PreviousOutPoint.Hash[:]) + var bIndex [4]byte + binary.LittleEndian.PutUint32(bIndex[:], txIn.PreviousOutPoint.Index) + sigHash.Write(bIndex[:]) + + if isWitnessPubKeyHashScript(subScript) { + // The script code for a p2wkh is a length prefix varint for + // the next 25 bytes, followed by a re-creation of the original + // p2pkh pk script. + sigHash.Write([]byte{0x19}) + sigHash.Write([]byte{OP_DUP}) + sigHash.Write([]byte{OP_HASH160}) + sigHash.Write([]byte{OP_DATA_20}) + sigHash.Write(extractWitnessPubKeyHash(subScript)) + sigHash.Write([]byte{OP_EQUALVERIFY}) + sigHash.Write([]byte{OP_CHECKSIG}) + } else { + // For p2wsh outputs, and future outputs, the script code is + // the original script, with all code separators removed, + // serialized with a var int length prefix. + wire.WriteVarBytes(&sigHash, 0, subScript) + } + + // Next, add the input amount, and sequence number of the input being + // signed. + var bAmount [8]byte + binary.LittleEndian.PutUint64(bAmount[:], uint64(amt)) + sigHash.Write(bAmount[:]) + var bSequence [4]byte + binary.LittleEndian.PutUint32(bSequence[:], txIn.Sequence) + sigHash.Write(bSequence[:]) + + // If the current signature mode isn't single, or none, then we can + // re-use the pre-generated hashoutputs sighash fragment. Otherwise, + // we'll serialize and add only the target output index to the signature + // pre-image. + if hashType&sigHashMask != SigHashSingle && + hashType&sigHashMask != SigHashNone { + sigHash.Write(sigHashes.HashOutputs[:]) + } else if hashType&sigHashMask == SigHashSingle && idx < len(tx.TxOut) { + var b bytes.Buffer + wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx]) + sigHash.Write(chainhash.DoubleHashB(b.Bytes())) + } else { + sigHash.Write(zeroHash[:]) + } + + // Finally, write out the transaction's locktime, and the sig hash + // type. + var bLockTime [4]byte + binary.LittleEndian.PutUint32(bLockTime[:], tx.LockTime) + sigHash.Write(bLockTime[:]) + var bHashType [4]byte + binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType)) + sigHash.Write(bHashType[:]) + + return chainhash.DoubleHashB(sigHash.Bytes()), nil +} + +// CalcWitnessSigHash computes the sighash digest for the specified input of +// the target transaction observing the desired sig hash type. +func CalcWitnessSigHash(script []byte, sigHashes *TxSigHashes, hType SigHashType, + tx *wire.MsgTx, idx int, amt int64) ([]byte, error) { + + const scriptVersion = 0 + if err := checkScriptParses(scriptVersion, script); err != nil { + return nil, err + } + + return calcWitnessSignatureHashRaw(script, sigHashes, hType, tx, idx, amt) +} From e781b66e2fb9a354a14bfa7fbdd44038450cc13f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:15:57 -0800 Subject: [PATCH 0626/1056] txscript: implement BIP 341+342 segwit v1 taproot+tapscript In this commit, we implement the new BIP 341+342 taproot sighash digest computation. The digest is similar, but re-orders some fragments and also starts to commit to the input values of all the transactions in the SIGHASH_ALL case. A new implicit sighash flag, SIGHASH_DEFAULT has been added that allows signatures to always be 64-bytes for the common case. The hashcache has been updated as well to store both the v0 and v1 mid state hashes. The v0 hashes are a double-sha of the contents, while the v1 hash is a single sha. As a result, if a transaction spends both v0 and v1 inputs, then we 're able to re-use all the intermediate hashes. As the sighash computation needs the input values and scripts, we create an abstraction: the PrevOutFetcher to give the caller flexibility w.r.t how this is done. We also create a `CannedPrevOutputFetcher` that holds the information in a map for a single input. A series of function options are also added to allow re-use of the same base sig hash calculation for both BIP 341 and 342. --- blockchain/scriptval.go | 18 +- blockchain/utxoviewpoint.go | 19 +- chaincfg/chainhash/hash.go | 5 + txscript/bench_test.go | 3 +- txscript/engine.go | 28 ++- txscript/engine_test.go | 6 +- txscript/example_test.go | 4 +- txscript/hashcache.go | 229 ++++++++++++++++++++++- txscript/hashcache_test.go | 46 +++-- txscript/opcode.go | 4 +- txscript/reference_test.go | 58 +++--- txscript/script.go | 23 +-- txscript/sigcache_test.go | 16 +- txscript/sighash.go | 354 +++++++++++++++++++++++++++++++++++- txscript/sign_test.go | 6 +- txscript/standard.go | 18 +- 16 files changed, 732 insertions(+), 105 deletions(-) diff --git a/blockchain/scriptval.go b/blockchain/scriptval.go index 8869e23f27..614e030c86 100644 --- a/blockchain/scriptval.go +++ b/blockchain/scriptval.go @@ -10,9 +10,9 @@ import ( "runtime" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // txValidateItem holds a transaction along with which input to validate. @@ -74,9 +74,11 @@ out: witness := txIn.Witness pkScript := utxo.PkScript() inputAmount := utxo.Amount() - vm, err := txscript.NewEngine(pkScript, txVI.tx.MsgTx(), - txVI.txInIndex, v.flags, v.sigCache, txVI.sigHashes, - inputAmount) + vm, err := txscript.NewEngine( + pkScript, txVI.tx.MsgTx(), txVI.txInIndex, + v.flags, v.sigCache, txVI.sigHashes, + inputAmount, v.utxoView, + ) if err != nil { str := fmt.Sprintf("failed to parse input "+ "%s:%d which references output %v - "+ @@ -201,7 +203,7 @@ func ValidateTransactionScripts(tx *btcutil.Tx, utxoView *UtxoViewpoint, // amongst all worker validation goroutines. if segwitActive && tx.MsgTx().HasWitness() && !hashCache.ContainsHashes(tx.Hash()) { - hashCache.AddSigHashes(tx.MsgTx()) + hashCache.AddSigHashes(tx.MsgTx(), utxoView) } var cachedHashes *txscript.TxSigHashes @@ -266,7 +268,7 @@ func checkBlockScripts(block *btcutil.Block, utxoView *UtxoViewpoint, if segwitActive && tx.HasWitness() && hashCache != nil && !hashCache.ContainsHashes(hash) { - hashCache.AddSigHashes(tx.MsgTx()) + hashCache.AddSigHashes(tx.MsgTx(), utxoView) } var cachedHashes *txscript.TxSigHashes @@ -274,7 +276,9 @@ func checkBlockScripts(block *btcutil.Block, utxoView *UtxoViewpoint, if hashCache != nil { cachedHashes, _ = hashCache.GetSigHashes(hash) } else { - cachedHashes = txscript.NewTxSigHashes(tx.MsgTx()) + cachedHashes = txscript.NewTxSigHashes( + tx.MsgTx(), utxoView, + ) } } diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 3398693225..3d1d513a3f 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -7,11 +7,11 @@ package blockchain import ( "fmt" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // txoFlags is a bitmask defining additional information and state for a @@ -159,6 +159,23 @@ func (view *UtxoViewpoint) LookupEntry(outpoint wire.OutPoint) *UtxoEntry { return view.entries[outpoint] } +// FetchPrevOutput fetches the previous output referenced by the passed +// outpoint. This is identical to the LookupEntry method, but it returns a +// wire.TxOut instead. +// +// NOTE: This is an implementation of the txscript.PrevOutputFetcher interface. +func (view *UtxoViewpoint) FetchPrevOutput(op wire.OutPoint) *wire.TxOut { + prevOut := view.entries[op] + if prevOut == nil { + return nil + } + + return &wire.TxOut{ + Value: prevOut.amount, + PkScript: prevOut.PkScript(), + } +} + // addTxOut adds the specified output to the view if it is not provably // unspendable. When the view already has an entry for the output, it will be // marked unspent. All fields will be updated for existing entries since it's diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index b7a2d8a7f8..1371e2fca7 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -27,12 +27,17 @@ var ( // TagBIP0340Nonce is the BIP-0340 tag for nonces. TagBIP0340Nonce = []byte("BIP0340/nonce") + // TagTapSighash is the tag used by BIP 341 to generate the sighash + // flags. + TagTapSighash = []byte("TapSighash") + // precomputedTags is a map containing the SHA-256 hash of the BIP-0340 // tags. precomputedTags = map[string]Hash{ string(TagBIP0340Challenge): sha256.Sum256(TagBIP0340Challenge), string(TagBIP0340Aux): sha256.Sum256(TagBIP0340Aux), string(TagBIP0340Nonce): sha256.Sum256(TagBIP0340Nonce), + string(TagTapSighash): sha256.Sum256(TagTapSighash), } ) diff --git a/txscript/bench_test.go b/txscript/bench_test.go index cac2920280..0d1aa91468 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -55,7 +55,8 @@ func BenchmarkCalcSigHash(b *testing.B) { // BenchmarkCalcWitnessSigHash benchmarks how long it takes to calculate the // witness signature hashes for all inputs of a transaction with many inputs. func BenchmarkCalcWitnessSigHash(b *testing.B) { - sigHashes := NewTxSigHashes(&manyInputsBenchTx) + prevOutFetcher := NewCannedPrevOutputFetcher(prevOutScript, 5) + sigHashes := NewTxSigHashes(&manyInputsBenchTx, prevOutFetcher) b.ResetTimer() b.ReportAllocs() diff --git a/txscript/engine.go b/txscript/engine.go index 1550579d28..b576165ee0 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -145,13 +145,14 @@ type Engine struct { // since transaction scripts are often executed more than once from various // contexts (e.g. new block templates, when transactions are first seen // prior to being mined, part of full block verification, etc). - flags ScriptFlags - tx wire.MsgTx - txIdx int - version uint16 - bip16 bool - sigCache *SigCache - hashCache *TxSigHashes + flags ScriptFlags + tx wire.MsgTx + txIdx int + version uint16 + bip16 bool + sigCache *SigCache + hashCache *TxSigHashes + prevOutFetcher PrevOutputFetcher // The following fields handle keeping track of the current execution state // of the engine. @@ -1117,7 +1118,9 @@ func (vm *Engine) SetAltStack(data [][]byte) { // transaction, and input index. The flags modify the behavior of the script // engine according to the description provided by each flag. func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags, - sigCache *SigCache, hashCache *TxSigHashes, inputAmount int64) (*Engine, error) { + sigCache *SigCache, hashCache *TxSigHashes, inputAmount int64, + prevOuts PrevOutputFetcher) (*Engine, error) { + const scriptVersion = 0 // The provided transaction input index must refer to a valid input. @@ -1147,8 +1150,13 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags // it possible to have a situation where P2SH would not be a soft fork // when it should be. The same goes for segwit which will pull in // additional scripts for execution from the witness stack. - vm := Engine{flags: flags, sigCache: sigCache, hashCache: hashCache, - inputAmount: inputAmount} + vm := Engine{ + flags: flags, + sigCache: sigCache, + hashCache: hashCache, + inputAmount: inputAmount, + prevOutFetcher: prevOuts, + } if vm.hasFlag(ScriptVerifyCleanStack) && (!vm.hasFlag(ScriptBip16) && !vm.hasFlag(ScriptVerifyWitness)) { return nil, scriptError(ErrInvalidFlags, diff --git a/txscript/engine_test.go b/txscript/engine_test.go index 5818080dfd..51a899be33 100644 --- a/txscript/engine_test.go +++ b/txscript/engine_test.go @@ -55,7 +55,7 @@ func TestBadPC(t *testing.T) { pkScript := mustParseShortForm("NOP") for _, test := range tests { - vm, err := NewEngine(pkScript, tx, 0, 0, nil, nil, -1) + vm, err := NewEngine(pkScript, tx, 0, 0, nil, nil, -1, nil) if err != nil { t.Errorf("Failed to create script: %v", err) } @@ -112,7 +112,7 @@ func TestCheckErrorCondition(t *testing.T) { pkScript := mustParseShortForm("NOP NOP NOP NOP NOP NOP NOP NOP NOP" + " NOP TRUE") - vm, err := NewEngine(pkScript, tx, 0, 0, nil, nil, 0) + vm, err := NewEngine(pkScript, tx, 0, 0, nil, nil, 0, nil) if err != nil { t.Errorf("failed to create script: %v", err) } @@ -188,7 +188,7 @@ func TestInvalidFlagCombinations(t *testing.T) { pkScript := []byte{OP_NOP} for i, test := range tests { - _, err := NewEngine(pkScript, tx, 0, test, nil, nil, -1) + _, err := NewEngine(pkScript, tx, 0, test, nil, nil, -1, nil) if !IsErrorCode(err, ErrInvalidFlags) { t.Fatalf("TestInvalidFlagCombinations #%d unexpected "+ "error: %v", i, err) diff --git a/txscript/example_test.go b/txscript/example_test.go index f3ff4b873c..b8c7104b5a 100644 --- a/txscript/example_test.go +++ b/txscript/example_test.go @@ -10,11 +10,11 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // This example demonstrates creating a script which pays to a bitcoin address. @@ -167,7 +167,7 @@ func ExampleSignTxOutput() { txscript.ScriptStrictMultiSig | txscript.ScriptDiscourageUpgradableNops vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0, - flags, nil, nil, -1) + flags, nil, nil, -1, nil) if err != nil { fmt.Println(err) return diff --git a/txscript/hashcache.go b/txscript/hashcache.go index 6db734992e..4a5f88fb24 100644 --- a/txscript/hashcache.go +++ b/txscript/hashcache.go @@ -7,6 +7,7 @@ package txscript import ( "bytes" "encoding/binary" + "math" "sync" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -67,24 +68,230 @@ func calcHashOutputs(tx *wire.MsgTx) chainhash.Hash { return chainhash.HashH(b.Bytes()) } +// PrevOutputFetcher is an interface used to supply the sighash cache with the +// previous output information needed to calculate the pre-computed sighash +// midstate for taproot transactions. +type PrevOutputFetcher interface { + // FetchPrevOutput attempts to fetch the previous output referenced by + // the passed outpoint. A nil value will be returned if the passed + // outpoint doesn't exist. + FetchPrevOutput(wire.OutPoint) *wire.TxOut +} + +// CannedPrevOutputFetcher is an implementation of PrevOutputFetcher that only +// is able to return information for a single previous output. +type CannedPrevOutputFetcher struct { + pkScript []byte + amt int64 +} + +// NewCannedPrevOutputFetcher returns an instance of a CannedPrevOutputFetcher +// that can only return the TxOut defined by the passed script and amount. +func NewCannedPrevOutputFetcher(script []byte, amt int64) *CannedPrevOutputFetcher { + return &CannedPrevOutputFetcher{ + pkScript: script, + amt: amt, + } +} + +// FetchPrevOutput attempts to fetch the previous output referenced by the +// passed outpoint. +// +// NOTE: This is a part of the PrevOutputFetcher interface. +func (c *CannedPrevOutputFetcher) FetchPrevOutput(wire.OutPoint) *wire.TxOut { + return &wire.TxOut{ + PkScript: c.pkScript, + Value: c.amt, + } +} + +// A compile-time assertion to ensure that CannedPrevOutputFetcher matches the +// PrevOutputFetcher interface. +var _ PrevOutputFetcher = (*CannedPrevOutputFetcher)(nil) + +// MultiPrevOutFetcher is a custom implementation of the PrevOutputFetcher +// backed by a key-value map of prevouts to outputs. +type MultiPrevOutFetcher struct { + prevOuts map[wire.OutPoint]*wire.TxOut +} + +// NewMultiPrevOutFetcher returns an instance of a PrevOutputFetcher that's +// backed by an optional map which is used as an input source. The +func NewMultiPrevOutFetcher(prevOuts map[wire.OutPoint]*wire.TxOut) *MultiPrevOutFetcher { + if prevOuts == nil { + prevOuts = make(map[wire.OutPoint]*wire.TxOut) + } + + return &MultiPrevOutFetcher{ + prevOuts: prevOuts, + } +} + +// FetchPrevOutput attempts to fetch the previous output referenced by the +// passed outpoint. +// +// NOTE: This is a part of the CannedPrevOutputFetcher interface. +func (m *MultiPrevOutFetcher) FetchPrevOutput(op wire.OutPoint) *wire.TxOut { + return m.prevOuts[op] +} + +// AddPrevOut adds a new prev out, tx out pair to the backing map. +func (m *MultiPrevOutFetcher) AddPrevOut(op wire.OutPoint, txOut *wire.TxOut) { + m.prevOuts[op] = txOut +} + +// Merge merges two instances of a MultiPrevOutFetcher into a single source. +func (m *MultiPrevOutFetcher) Merge(other *MultiPrevOutFetcher) { + for k, v := range other.prevOuts { + m.prevOuts[k] = v + } +} + +// A compile-time assertion to ensure that MultiPrevOutFetcher matches the +// PrevOutputFetcher interface. +var _ PrevOutputFetcher = (*MultiPrevOutFetcher)(nil) + +// calcHashInputAmounts computes a hash digest of the input amounts of all +// inputs referenced in the passed transaction. This hash pre computation is only +// used for validating taproot inputs. +func calcHashInputAmounts(tx *wire.MsgTx, inputFetcher PrevOutputFetcher) chainhash.Hash { + var b bytes.Buffer + for _, txIn := range tx.TxIn { + prevOut := inputFetcher.FetchPrevOutput(txIn.PreviousOutPoint) + + _ = binary.Write(&b, binary.LittleEndian, prevOut.Value) + } + + return chainhash.HashH(b.Bytes()) +} + +// calcHashInputAmts computes the hash digest of all the previous input scripts +// referenced by the passed transaction. This hash pre computation is only used +// for validating taproot inputs. +func calcHashInputScripts(tx *wire.MsgTx, inputFetcher PrevOutputFetcher) chainhash.Hash { + var b bytes.Buffer + for _, txIn := range tx.TxIn { + prevOut := inputFetcher.FetchPrevOutput(txIn.PreviousOutPoint) + + _ = wire.WriteVarBytes(&b, 0, prevOut.PkScript) + } + + return chainhash.HashH(b.Bytes()) +} + +// SegwitSigHashMidstate is the sighash midstate used in the base segwit +// sighash calculation as defined in BIP 143. +type SegwitSigHashMidstate struct { + HashPrevOutsV0 chainhash.Hash + HashSequenceV0 chainhash.Hash + HashOutputsV0 chainhash.Hash +} + +// TaprootSigHashMidState is the sighash midstate used to compute taproot and +// tapscript signatures as defined in BIP 341. +type TaprootSigHashMidState struct { + HashPrevOutsV1 chainhash.Hash + HashSequenceV1 chainhash.Hash + HashOutputsV1 chainhash.Hash + HashInputScriptsV1 chainhash.Hash + HashInputAmountsV1 chainhash.Hash +} + // TxSigHashes houses the partial set of sighashes introduced within BIP0143. // This partial set of sighashes may be re-used within each input across a // transaction when validating all inputs. As a result, validation complexity // for SigHashAll can be reduced by a polynomial factor. type TxSigHashes struct { - HashPrevOuts chainhash.Hash - HashSequence chainhash.Hash - HashOutputs chainhash.Hash + SegwitSigHashMidstate + + TaprootSigHashMidState } // NewTxSigHashes computes, and returns the cached sighashes of the given // transaction. -func NewTxSigHashes(tx *wire.MsgTx) *TxSigHashes { - return &TxSigHashes{ - HashPrevOuts: calcHashPrevOuts(tx), - HashSequence: calcHashSequence(tx), - HashOutputs: calcHashOutputs(tx), +func NewTxSigHashes(tx *wire.MsgTx, + inputFetcher PrevOutputFetcher) *TxSigHashes { + + var ( + sigHashes TxSigHashes + zeroHash chainhash.Hash + ) + + // Base segwit (witness version v0), and taproot (witness version v1) + // differ in how the set of pre-computed cached sighash midstate is + // computed. For taproot, the prevouts, sequence, and outputs are + // computed as normal, but a single sha256 hash invocation is used. In + // addition, the hashes of all the previous input amounts and scripts + // are included as well. + // + // Based on the above distinction, we'll run through all the referenced + // inputs to determine what we need to compute. + var hasV0Inputs, hasV1Inputs bool + for _, txIn := range tx.TxIn { + // If this is a coinbase input, then we know that we only need + // the v0 midstate (though it won't be used) in this instance. + outpoint := txIn.PreviousOutPoint + if outpoint.Index == math.MaxUint32 && outpoint.Hash == zeroHash { + hasV0Inputs = true + continue + } + + prevOut := inputFetcher.FetchPrevOutput(outpoint) + + // If this is spending a script that looks like a taproot output, + // then we'll need to pre-compute the extra taproot data. + if IsPayToTaproot(prevOut.PkScript) { + hasV1Inputs = true + } else { + // Otherwise, we'll assume we need the v0 sighash midstate. + hasV0Inputs = true + } + + // If the transaction has _both_ v0 and v1 inputs, then we can stop + // here. + if hasV0Inputs && hasV1Inputs { + break + } } + + // Now that we know which cached midstate we need to calculate, we can + // go ahead and do so. + // + // First, we can calculate the information that both segwit v0 and v1 + // need: the prevout, sequence and output hashes. For v1 the only + // difference is that this is a single instead of a double hash. + // + // Both v0 and v1 share this base data computed using a sha256 single + // hash. + sigHashes.HashPrevOutsV1 = calcHashPrevOuts(tx) + sigHashes.HashSequenceV1 = calcHashSequence(tx) + sigHashes.HashOutputsV1 = calcHashOutputs(tx) + + // The v0 data is the same as the v1 (newer data) but it uses a double + // hash instead. + if hasV0Inputs { + sigHashes.HashPrevOutsV0 = chainhash.HashH( + sigHashes.HashPrevOutsV1[:], + ) + sigHashes.HashSequenceV0 = chainhash.HashH( + sigHashes.HashSequenceV1[:], + ) + sigHashes.HashOutputsV0 = chainhash.HashH( + sigHashes.HashOutputsV1[:], + ) + } + + // Finally, we'll compute the taproot specific data if needed. + if hasV1Inputs { + sigHashes.HashInputAmountsV1 = calcHashInputAmounts( + tx, inputFetcher, + ) + sigHashes.HashInputScriptsV1 = calcHashInputScripts( + tx, inputFetcher, + ) + } + + return &sigHashes } // HashCache houses a set of partial sighashes keyed by txid. The set of partial @@ -108,9 +315,11 @@ func NewHashCache(maxSize uint) *HashCache { // AddSigHashes computes, then adds the partial sighashes for the passed // transaction. -func (h *HashCache) AddSigHashes(tx *wire.MsgTx) { +func (h *HashCache) AddSigHashes(tx *wire.MsgTx, + inputFetcher PrevOutputFetcher) { + h.Lock() - h.sigHashes[tx.TxHash()] = NewTxSigHashes(tx) + h.sigHashes[tx.TxHash()] = NewTxSigHashes(tx, inputFetcher) h.Unlock() } diff --git a/txscript/hashcache_test.go b/txscript/hashcache_test.go index cee59b9956..8d731820ec 100644 --- a/txscript/hashcache_test.go +++ b/txscript/hashcache_test.go @@ -18,10 +18,12 @@ func init() { } // genTestTx creates a random transaction for uses within test cases. -func genTestTx() (*wire.MsgTx, error) { +func genTestTx() (*wire.MsgTx, *MultiPrevOutFetcher, error) { tx := wire.NewMsgTx(2) tx.Version = rand.Int31() + prevOuts := NewMultiPrevOutFetcher(nil) + numTxins := 1 + rand.Intn(11) for i := 0; i < numTxins; i++ { randTxIn := wire.TxIn{ @@ -32,10 +34,14 @@ func genTestTx() (*wire.MsgTx, error) { } _, err := rand.Read(randTxIn.PreviousOutPoint.Hash[:]) if err != nil { - return nil, err + return nil, nil, err } tx.TxIn = append(tx.TxIn, &randTxIn) + + prevOuts.AddPrevOut( + randTxIn.PreviousOutPoint, &wire.TxOut{}, + ) } numTxouts := 1 + rand.Intn(11) @@ -45,12 +51,12 @@ func genTestTx() (*wire.MsgTx, error) { PkScript: make([]byte, rand.Intn(30)), } if _, err := rand.Read(randTxOut.PkScript); err != nil { - return nil, err + return nil, nil, err } tx.TxOut = append(tx.TxOut, &randTxOut) } - return tx, nil + return tx, prevOuts, nil } // TestHashCacheAddContainsHashes tests that after items have been added to the @@ -62,23 +68,29 @@ func TestHashCacheAddContainsHashes(t *testing.T) { cache := NewHashCache(10) - var err error + var ( + err error + randPrevOuts *MultiPrevOutFetcher + ) + prevOuts := NewMultiPrevOutFetcher(nil) // First, we'll generate 10 random transactions for use within our // tests. const numTxns = 10 txns := make([]*wire.MsgTx, numTxns) for i := 0; i < numTxns; i++ { - txns[i], err = genTestTx() + txns[i], randPrevOuts, err = genTestTx() if err != nil { t.Fatalf("unable to generate test tx: %v", err) } + + prevOuts.Merge(randPrevOuts) } // With the transactions generated, we'll add each of them to the hash // cache. for _, tx := range txns { - cache.AddSigHashes(tx) + cache.AddSigHashes(tx, prevOuts) } // Next, we'll ensure that each of the transactions inserted into the @@ -91,7 +103,7 @@ func TestHashCacheAddContainsHashes(t *testing.T) { } } - randTx, err := genTestTx() + randTx, _, err := genTestTx() if err != nil { t.Fatalf("unable to generate tx: %v", err) } @@ -115,14 +127,14 @@ func TestHashCacheAddGet(t *testing.T) { // To start, we'll generate a random transaction and compute the set of // sighashes for the transaction. - randTx, err := genTestTx() + randTx, prevOuts, err := genTestTx() if err != nil { t.Fatalf("unable to generate tx: %v", err) } - sigHashes := NewTxSigHashes(randTx) + sigHashes := NewTxSigHashes(randTx, prevOuts) // Next, add the transaction to the hash cache. - cache.AddSigHashes(randTx) + cache.AddSigHashes(randTx, prevOuts) // The transaction inserted into the cache above should be found. txid := randTx.TxHash() @@ -146,19 +158,25 @@ func TestHashCachePurge(t *testing.T) { cache := NewHashCache(10) - var err error + var ( + err error + randPrevOuts *MultiPrevOutFetcher + ) + prevOuts := NewMultiPrevOutFetcher(nil) // First we'll start by inserting numTxns transactions into the hash cache. const numTxns = 10 txns := make([]*wire.MsgTx, numTxns) for i := 0; i < numTxns; i++ { - txns[i], err = genTestTx() + txns[i], randPrevOuts, err = genTestTx() if err != nil { t.Fatalf("unable to generate test tx: %v", err) } + + prevOuts.Merge(randPrevOuts) } for _, tx := range txns { - cache.AddSigHashes(tx) + cache.AddSigHashes(tx, prevOuts) } // Once all the transactions have been inserted, we'll purge them from diff --git a/txscript/opcode.go b/txscript/opcode.go index 64e46fbf74..b315d03016 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1914,7 +1914,7 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { if vm.hashCache != nil { sigHashes = vm.hashCache } else { - sigHashes = NewTxSigHashes(&vm.tx) + sigHashes = NewTxSigHashes(&vm.tx, vm.prevOutFetcher) } hash, err = calcWitnessSignatureHashRaw(subScript, sigHashes, hashType, @@ -2185,7 +2185,7 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { if vm.hashCache != nil { sigHashes = vm.hashCache } else { - sigHashes = NewTxSigHashes(&vm.tx) + sigHashes = NewTxSigHashes(&vm.tx, vm.prevOutFetcher) } hash, err = calcWitnessSignatureHashRaw(script, sigHashes, hashType, diff --git a/txscript/reference_test.go b/txscript/reference_test.go index 3d4c591427..d1f516ee2d 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -15,9 +15,9 @@ import ( "strings" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // scriptTestName returns a descriptive test name for the given reference script @@ -441,10 +441,14 @@ func testScripts(t *testing.T, tests [][]interface{}, useSigCache bool) { // Generate a transaction pair such that one spends from the // other and the provided signature and public key scripts are // used, then create a new engine to execute the scripts. - tx := createSpendingTx(witness, scriptSig, scriptPubKey, - int64(inputAmt)) - vm, err := NewEngine(scriptPubKey, tx, 0, flags, sigCache, nil, - int64(inputAmt)) + tx := createSpendingTx( + witness, scriptSig, scriptPubKey, int64(inputAmt), + ) + prevOuts := NewCannedPrevOutputFetcher(scriptPubKey, int64(inputAmt)) + vm, err := NewEngine( + scriptPubKey, tx, 0, flags, sigCache, nil, + int64(inputAmt), prevOuts, + ) if err == nil { err = vm.Execute() } @@ -572,7 +576,7 @@ testloop: continue } - prevOuts := make(map[wire.OutPoint]scriptWithInputVal) + prevOutFetcher := NewMultiPrevOutFetcher(nil) for j, iinput := range inputs { input, ok := iinput.([]interface{}) if !ok { @@ -633,16 +637,18 @@ testloop: } } - v := scriptWithInputVal{ - inputVal: int64(inputValue), - pkScript: script, - } - prevOuts[*wire.NewOutPoint(prevhash, idx)] = v + op := wire.NewOutPoint(prevhash, idx) + prevOutFetcher.AddPrevOut(*op, &wire.TxOut{ + Value: int64(inputValue), + PkScript: script, + }) } for k, txin := range tx.MsgTx().TxIn { - prevOut, ok := prevOuts[txin.PreviousOutPoint] - if !ok { + prevOut := prevOutFetcher.FetchPrevOutput( + txin.PreviousOutPoint, + ) + if prevOut == nil { t.Errorf("bad test (missing %dth input) %d:%v", k, i, test) continue testloop @@ -650,8 +656,8 @@ testloop: // These are meant to fail, so as soon as the first // input fails the transaction has failed. (some of the // test txns have good inputs, too.. - vm, err := NewEngine(prevOut.pkScript, tx.MsgTx(), k, - flags, nil, nil, prevOut.inputVal) + vm, err := NewEngine(prevOut.PkScript, tx.MsgTx(), k, + flags, nil, nil, prevOut.Value, prevOutFetcher) if err != nil { continue testloop } @@ -727,7 +733,7 @@ testloop: continue } - prevOuts := make(map[wire.OutPoint]scriptWithInputVal) + prevOutFetcher := NewMultiPrevOutFetcher(nil) for j, iinput := range inputs { input, ok := iinput.([]interface{}) if !ok { @@ -788,22 +794,24 @@ testloop: } } - v := scriptWithInputVal{ - inputVal: int64(inputValue), - pkScript: script, - } - prevOuts[*wire.NewOutPoint(prevhash, idx)] = v + op := wire.NewOutPoint(prevhash, idx) + prevOutFetcher.AddPrevOut(*op, &wire.TxOut{ + Value: int64(inputValue), + PkScript: script, + }) } for k, txin := range tx.MsgTx().TxIn { - prevOut, ok := prevOuts[txin.PreviousOutPoint] - if !ok { + prevOut := prevOutFetcher.FetchPrevOutput( + txin.PreviousOutPoint, + ) + if prevOut == nil { t.Errorf("bad test (missing %dth input) %d:%v", k, i, test) continue testloop } - vm, err := NewEngine(prevOut.pkScript, tx.MsgTx(), k, - flags, nil, nil, prevOut.inputVal) + vm, err := NewEngine(prevOut.PkScript, tx.MsgTx(), k, + flags, nil, nil, prevOut.Value, prevOutFetcher) if err != nil { t.Errorf("test (%d:%v:%d) failed to create "+ "script: %v", i, test, k, err) diff --git a/txscript/script.go b/txscript/script.go index e2d708247c..7d169e633e 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -19,20 +19,17 @@ import ( // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. var Bip16Activation = time.Unix(1333238400, 0) -// SigHashType represents hash type bits at the end of a signature. -type SigHashType uint32 - -// Hash type bits from the end of a signature. const ( - SigHashOld SigHashType = 0x0 - SigHashAll SigHashType = 0x1 - SigHashNone SigHashType = 0x2 - SigHashSingle SigHashType = 0x3 - SigHashAnyOneCanPay SigHashType = 0x80 - - // sigHashMask defines the number of bits of the hash type which is used - // to identify which outputs are signed. - sigHashMask = 0x1f + // TaprootAnnexTag is the tag for an annex. This value is used to + // identify the annex during tapscript spends. If there're at least two + // elements in the taproot witness stack, and the first byte of the + // last element matches this tag, then we'll extract this as a distinct + // item. + TaprootAnnexTag = 0x50 + + // TaprootLeafMask is the mask applied to the control block to extract + // the leaf versions of the taproot script leaf being spent. + TaprootLeafMask = 0xfe ) // These are the constants specified for maximums in individual scripts. diff --git a/txscript/sigcache_test.go b/txscript/sigcache_test.go index d0a3c4b973..f83b8350b1 100644 --- a/txscript/sigcache_test.go +++ b/txscript/sigcache_test.go @@ -44,12 +44,12 @@ func TestSigCacheAddExists(t *testing.T) { } // Add the triplet to the signature cache. - sigCache.Add(*msg1, sig1, key1) + sigCache.Add(*msg1, sig1.Serialize(), key1.SerializeCompressed()) // The previously added triplet should now be found within the sigcache. sig1Copy, _ := ecdsa.ParseSignature(sig1.Serialize()) key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) - if !sigCache.Exists(*msg1, sig1Copy, key1Copy) { + if !sigCache.Exists(*msg1, sig1Copy.Serialize(), key1Copy.SerializeCompressed()) { t.Errorf("previously added item not found in signature cache") } } @@ -69,7 +69,7 @@ func TestSigCacheAddEvictEntry(t *testing.T) { t.Fatalf("unable to generate random signature test data") } - sigCache.Add(*msg, sig, key) + sigCache.Add(*msg, sig.Serialize(), key.SerializeCompressed()) sigCopy, err := ecdsa.ParseSignature(sig.Serialize()) if err != nil { @@ -79,7 +79,7 @@ func TestSigCacheAddEvictEntry(t *testing.T) { if err != nil { t.Fatalf("unable to parse key: %v", err) } - if !sigCache.Exists(*msg, sigCopy, keyCopy) { + if !sigCache.Exists(*msg, sigCopy.Serialize(), keyCopy.SerializeCompressed()) { t.Errorf("previously added item not found in signature" + "cache") } @@ -97,7 +97,7 @@ func TestSigCacheAddEvictEntry(t *testing.T) { if err != nil { t.Fatalf("unable to generate random signature test data") } - sigCache.Add(*msgNew, sigNew, keyNew) + sigCache.Add(*msgNew, sigNew.Serialize(), keyNew.SerializeCompressed()) // The sigcache should still have sigCache entries. if uint(len(sigCache.validSigs)) != sigCacheSize { @@ -108,7 +108,7 @@ func TestSigCacheAddEvictEntry(t *testing.T) { // The entry added above should be found within the sigcache. sigNewCopy, _ := ecdsa.ParseSignature(sigNew.Serialize()) keyNewCopy, _ := btcec.ParsePubKey(keyNew.SerializeCompressed()) - if !sigCache.Exists(*msgNew, sigNewCopy, keyNewCopy) { + if !sigCache.Exists(*msgNew, sigNewCopy.Serialize(), keyNewCopy.SerializeCompressed()) { t.Fatalf("previously added item not found in signature cache") } } @@ -126,12 +126,12 @@ func TestSigCacheAddMaxEntriesZeroOrNegative(t *testing.T) { } // Add the triplet to the signature cache. - sigCache.Add(*msg1, sig1, key1) + sigCache.Add(*msg1, sig1.Serialize(), key1.SerializeCompressed()) // The generated triplet should not be found. sig1Copy, _ := ecdsa.ParseSignature(sig1.Serialize()) key1Copy, _ := btcec.ParsePubKey(key1.SerializeCompressed()) - if sigCache.Exists(*msg1, sig1Copy, key1Copy) { + if sigCache.Exists(*msg1, sig1Copy.Serialize(), key1Copy.SerializeCompressed()) { t.Errorf("previously added signature found in sigcache, but" + "shouldn't have been") } diff --git a/txscript/sighash.go b/txscript/sighash.go index 1cee804b96..eaae070d5c 100644 --- a/txscript/sighash.go +++ b/txscript/sighash.go @@ -7,13 +7,39 @@ package txscript import ( "bytes" + "crypto/sha256" "encoding/binary" "fmt" + "io" + "math" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) +// SigHashType represents hash type bits at the end of a signature. +type SigHashType uint32 + +// Hash type bits from the end of a signature. +const ( + SigHashDefault SigHashType = 0x00 + SigHashOld SigHashType = 0x0 + SigHashAll SigHashType = 0x1 + SigHashNone SigHashType = 0x2 + SigHashSingle SigHashType = 0x3 + SigHashAnyOneCanPay SigHashType = 0x80 + + // sigHashMask defines the number of bits of the hash type which is used + // to identify which outputs are signed. + sigHashMask = 0x1f +) + +const ( + // blankCodeSepValue is the value of the code separator position in the + // tapscript sighash when no code separator was found in the script. + blankCodeSepValue = math.MaxUint32 +) + // shallowCopyTx creates a shallow copy of the transaction for use when // calculating the signature hash. It is used over the Copy method on the // transaction itself since that is a deep copy and therefore does more work and @@ -188,7 +214,7 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, // If anyone can pay isn't active, then we can use the cached // hashPrevOuts, otherwise we just write zeroes for the prev outs. if hashType&SigHashAnyOneCanPay == 0 { - sigHash.Write(sigHashes.HashPrevOuts[:]) + sigHash.Write(sigHashes.HashPrevOutsV0[:]) } else { sigHash.Write(zeroHash[:]) } @@ -199,7 +225,7 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, if hashType&SigHashAnyOneCanPay == 0 && hashType&sigHashMask != SigHashSingle && hashType&sigHashMask != SigHashNone { - sigHash.Write(sigHashes.HashSequence[:]) + sigHash.Write(sigHashes.HashSequenceV0[:]) } else { sigHash.Write(zeroHash[:]) } @@ -245,7 +271,7 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, // pre-image. if hashType&sigHashMask != SigHashSingle && hashType&sigHashMask != SigHashNone { - sigHash.Write(sigHashes.HashOutputs[:]) + sigHash.Write(sigHashes.HashOutputsV0[:]) } else if hashType&sigHashMask == SigHashSingle && idx < len(tx.TxOut) { var b bytes.Buffer wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx]) @@ -278,3 +304,325 @@ func CalcWitnessSigHash(script []byte, sigHashes *TxSigHashes, hType SigHashType return calcWitnessSignatureHashRaw(script, sigHashes, hType, tx, idx, amt) } + +// sigHashExtFlag represents the sig hash extension flag as defined in BIP 341. +// Extensions to the base sighash algorithm will be appended to the base +// sighash digest. +type sigHashExtFlag uint8 + +const ( + // baseSigHashExtFlag is the base extension flag. This adds no changes + // to the sighash digest message. This is used for segwit v1 spends, + // a.k.a the tapscript keyspend path. + baseSigHashExtFlag sigHashExtFlag = 0 + + // tapscriptSighashExtFlag is the extension flag defined by tapscript + // base leaf version spend define din BIP 342. This augments the base + // sighash by including the tapscript leaf hash, the key version, and + // the code separator position. + tapscriptSighashExtFlag sigHashExtFlag = 1 +) + +// taprootSigHashOptions houses a set of functional options that may optionally +// modify how the taproot/script sighash digest algorithm is implemented. +type taprootSigHashOptions struct { + // extFlag denotes the current message digest extension being used. For + // top-level script spends use a value of zero, while each tapscript + // version can define its own values as well. + extFlag sigHashExtFlag + + // annexHash is the sha256 hash of the annex with a compact size length + // prefix: sha256(sizeOf(annex) || annex). + annexHash []byte + + // tapLeafHash is the hash of the tapscript leaf as defined in BIP 341. + // This should be h_tapleaf(version || compactSizeOf(script) || script). + tapLeafHash []byte + + // keyVersion is the key version as defined in BIP 341. This is always + // 0x00 for all currently defined leaf versions. + keyVersion byte + + // codeSepPos is the op code position of the last code separator. This + // is used for the BIP 342 sighash message extension. + codeSepPos uint32 +} + +// writeDigestExtensions writes out the sighah mesage extensiosn defined by the +// current active sigHashExtFlags. +func (t *taprootSigHashOptions) writeDigestExtensions(w io.Writer) error { + switch t.extFlag { + // The base extension, used for tapscript keypath spends doesn't modify + // the digest at all. + case baseSigHashExtFlag: + return nil + + // The tapscript base leaf version extension adds the leaf hash, key + // version, and code separator position to the final digest. + case tapscriptSighashExtFlag: + if _, err := w.Write(t.tapLeafHash); err != nil { + return err + } + if _, err := w.Write([]byte{t.keyVersion}); err != nil { + return err + } + err := binary.Write(w, binary.LittleEndian, t.codeSepPos) + if err != nil { + return err + } + } + + return nil +} + +// defaultTaprootSighashOptions returns the set of default sighash options for +// taproot execution. +func defaultTaprootSighashOptions() *taprootSigHashOptions { + return &taprootSigHashOptions{} +} + +// TaprootSigHashOption defines a set of functional param options that can be +// used to modify the base sighash message with optional extensions. +type TaprootSigHashOption func(*taprootSigHashOptions) + +// WithAnnex is a functional option that allows the caller to specify the +// existence of an annex in the final witness stack for the taproot/tapscript +// spends. +func WithAnnex(annex []byte) TaprootSigHashOption { + return func(o *taprootSigHashOptions) { + // It's just a bytes.Buffer which never returns an error on + // write. + var b bytes.Buffer + _ = wire.WriteVarBytes(&b, 0, annex) + + o.annexHash = chainhash.HashB(b.Bytes()) + } +} + +// WithBaseTapscriptVersion is a functional option that specifies that the +// sighash digest should include the extra information included as part of the +// base tapscript version. +func WithBaseTapscriptVersion(codeSepPos uint32, + tapLeafHash []byte) TaprootSigHashOption { + + return func(o *taprootSigHashOptions) { + o.extFlag = tapscriptSighashExtFlag + o.tapLeafHash = tapLeafHash + o.keyVersion = 0 + o.codeSepPos = codeSepPos + } +} + +// isValidTaprootSigHash returns true if the passed sighash is a valid taproot +// sighash. +func isValidTaprootSigHash(hashType SigHashType) bool { + switch hashType { + case SigHashDefault, SigHashAll, SigHashNone, SigHashSingle: + fallthrough + case 0x81, 0x82, 0x83: + return true + + default: + return false + } +} + +// calcTaprootSignatureHashRaw computes the sighash as specified in BIP 143. +// If an invalid sighash type is passed in, an error is returned. +func calcTaprootSignatureHashRaw(sigHashes *TxSigHashes, hType SigHashType, + tx *wire.MsgTx, idx int, + prevOutFetcher PrevOutputFetcher, + sigHashOpts ...TaprootSigHashOption) ([]byte, error) { + + opts := defaultTaprootSighashOptions() + for _, sigHashOpt := range sigHashOpts { + sigHashOpt(opts) + } + + // If a valid sighash type isn't passed in, then we'll exit early. + if !isValidTaprootSigHash(hType) { + // TODO(roasbeef): use actual errr here + return nil, fmt.Errorf("invalid taproot sighash type: %v", hType) + } + + // As a sanity check, ensure the passed input index for the transaction + // is valid. + if idx > len(tx.TxIn)-1 { + return nil, fmt.Errorf("idx %d but %d txins", idx, len(tx.TxIn)) + } + + // We'll utilize this buffer throughout to incrementally calculate + // the signature hash for this transaction. + var sigMsg bytes.Buffer + + // The final sighash always has a value of 0x00 prepended to it, which + // is called the sighash epoch. + sigMsg.WriteByte(0x00) + + // First, we write the hash type encoded as a single byte. + if err := sigMsg.WriteByte(byte(hType)); err != nil { + return nil, err + } + + // Next we'll write out the transaction specific data which binds the + // outer context of the sighash. + err := binary.Write(&sigMsg, binary.LittleEndian, tx.Version) + if err != nil { + return nil, err + } + err = binary.Write(&sigMsg, binary.LittleEndian, tx.LockTime) + if err != nil { + return nil, err + } + + // If sighash isn't anyone can pay, then we'll include all the + // pre-computed midstate digests in the sighash. + if hType&SigHashAnyOneCanPay != SigHashAnyOneCanPay { + sigMsg.Write(sigHashes.HashPrevOutsV1[:]) + sigMsg.Write(sigHashes.HashInputAmountsV1[:]) + sigMsg.Write(sigHashes.HashInputScriptsV1[:]) + sigMsg.Write(sigHashes.HashSequenceV1[:]) + } + + // If this is sighash all, or its taproot alias (sighash default), + // then we'll also include the pre-computed digest of all the outputs + // of the transaction. + if hType&SigHashSingle != SigHashSingle && + hType&SigHashSingle != SigHashNone { + + sigMsg.Write(sigHashes.HashOutputsV1[:]) + } + + // Next, we'll write out the relevant information for this specific + // input. + // + // The spend type is computed as the (ext_flag*2) + annex_present. We + // use this to bind the extension flag (that BIP 342 uses), as well as + // the annex if its present. + input := tx.TxIn[idx] + witnessHasAnnex := opts.annexHash != nil + spendType := byte(opts.extFlag) * 2 + if witnessHasAnnex { + spendType += 1 + } + + if err := sigMsg.WriteByte(spendType); err != nil { + return nil, err + } + + // If anyone can pay is active, then we'll write out just the specific + // information about this input, given we skipped writing all the + // information of all the inputs above. + if hType&SigHashAnyOneCanPay == SigHashAnyOneCanPay { + // We'll start out with writing this input specific information by + // first writing the entire previous output. + err = wire.WriteOutPoint(&sigMsg, 0, 0, &input.PreviousOutPoint) + if err != nil { + return nil, err + } + + // Next, we'll write out the previous output (amt+script) being + // spent itself. + prevOut := prevOutFetcher.FetchPrevOutput(input.PreviousOutPoint) + if err := wire.WriteTxOut(&sigMsg, 0, 0, prevOut); err != nil { + return nil, err + } + + // Finally, we'll write out the input sequence itself. + err = binary.Write(&sigMsg, binary.LittleEndian, input.Sequence) + if err != nil { + return nil, err + } + } else { + err := binary.Write(&sigMsg, binary.LittleEndian, uint32(idx)) + if err != nil { + return nil, err + } + } + + // Now that we have the input specific information written, we'll + // include the anex, if we have it. + if witnessHasAnnex { + sigMsg.Write(opts.annexHash) + } + + // Finally, if this is sighash single, then we'll write out the + // information for this given output. + if hType&sigHashMask == SigHashSingle { + // If this output doesn't exist, then we'll return with an error + // here as this is an invalid sighash type for this input. + if idx >= len(tx.TxOut) { + // TODO(roasbeef): real error here + return nil, fmt.Errorf("invalid sighash type for input") + } + + // Now that we know this is a valid sighash input combination, + // we'll write out the information specific to this input. + // We'll write the wire serialization of the output and compute + // the sha256 in a single step. + shaWriter := sha256.New() + txOut := tx.TxOut[idx] + if err := wire.WriteTxOut(shaWriter, 0, 0, txOut); err != nil { + return nil, err + } + + // With the digest obtained, we'll write this out into our + // signature message. + if _, err := sigMsg.Write(shaWriter.Sum(nil)); err != nil { + return nil, err + } + } + + // Now that we've written out all the base information, we'll write any + // message extensions (if they exist). + if err := opts.writeDigestExtensions(&sigMsg); err != nil { + return nil, err + } + + // The final sighash is computed as: hash_TagSigHash(0x00 || sigMsg). + // We wrote the 0x00 above so we don't need to append here and incur + // extra allocations. + sigHash := chainhash.TaggedHash(chainhash.TagTapSighash, sigMsg.Bytes()) + return sigHash[:], nil +} + +// CalcTaprootSignatureHash computes the sighash digest of a transaction's +// taproot-spending input using the new sighash digest algorithm described in +// BIP 341. As the new digest algoriths may require the digest to commit to the +// entire prev output, a PrevOutputFetcher argument is required to obtain the +// needed information. The TxSigHashes pre-computed sighash midstate MUST be +// specified. +func CalcTaprootSignatureHash(sigHashes *TxSigHashes, hType SigHashType, + tx *wire.MsgTx, idx int, + prevOutFetcher PrevOutputFetcher) ([]byte, error) { + + return calcTaprootSignatureHashRaw( + sigHashes, hType, tx, idx, prevOutFetcher, + ) +} + +// CalcTaprootSignatureHash is similar to CalcTaprootSignatureHash but for +// _tapscript_ spends instead. A proper TapLeaf instance (the script leaf being +// signed) must be passed in. The functional options can be used to specify an +// annex if the signature was bound to that context. +// +// NOTE: This function is able to compute the sighash of scripts that contain a +// code separator if the caller passes in an instance of +// WithBaseTapscriptVersion with the valid position. +func CalcTapscriptSignaturehash(sigHashes *TxSigHashes, hType SigHashType, + tx *wire.MsgTx, idx int, prevOutFetcher PrevOutputFetcher, + tapLeaf TapLeaf, + sigHashOpts ...TaprootSigHashOption) ([]byte, error) { + + tapLeafHash := tapLeaf.TapHash() + + var opts []TaprootSigHashOption + opts = append( + opts, WithBaseTapscriptVersion(blankCodeSepValue, tapLeafHash[:]), + ) + opts = append(opts, sigHashOpts...) + + return calcTaprootSignatureHashRaw( + sigHashes, hType, tx, idx, prevOutFetcher, opts..., + ) +} diff --git a/txscript/sign_test.go b/txscript/sign_test.go index 637ccef10d..ae10ba17d8 100644 --- a/txscript/sign_test.go +++ b/txscript/sign_test.go @@ -10,10 +10,10 @@ import ( "testing" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) type addressToKey struct { @@ -56,7 +56,7 @@ func mkGetScript(scripts map[string][]byte) ScriptDB { func checkScripts(msg string, tx *wire.MsgTx, idx int, inputAmt int64, sigScript, pkScript []byte) error { tx.TxIn[idx].SignatureScript = sigScript vm, err := NewEngine(pkScript, tx, idx, - ScriptBip16|ScriptVerifyDERSignatures, nil, nil, inputAmt) + ScriptBip16|ScriptVerifyDERSignatures, nil, nil, inputAmt, nil) if err != nil { return fmt.Errorf("failed to make script engine for %s: %v", msg, err) @@ -1672,7 +1672,7 @@ nexttest: scriptFlags := ScriptBip16 | ScriptVerifyDERSignatures for j := range tx.TxIn { vm, err := NewEngine(sigScriptTests[i]. - inputs[j].txout.PkScript, tx, j, scriptFlags, nil, nil, 0) + inputs[j].txout.PkScript, tx, j, scriptFlags, nil, nil, 0, nil) if err != nil { t.Errorf("cannot create script vm for test %v: %v", sigScriptTests[i].name, err) diff --git a/txscript/standard.go b/txscript/standard.go index 4a3097a4d4..10689a9f72 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -466,13 +466,25 @@ func isWitnessTaprootScript(script []byte) bool { // isAnnexedWitness returns true if the passed witness has a final push // that is a witness annex. -func isAnnexedWitness(witness [][]byte) bool { - const OP_ANNEX = 0x50 +func isAnnexedWitness(witness wire.TxWitness) bool { if len(witness) < 2 { return false } + + lastElement := witness[len(witness)-1] + return len(lastElement) > 0 && lastElement[0] == TaprootAnnexTag +} + +// extractAnnex attempts to extract the annex from the passed witness. If the +// witness doesn't contain an annex, then an error is returned. +func extractAnnex(witness [][]byte) ([]byte, error) { + if !isAnnexedWitness(witness) { + // TODO(roasbeef): make into actual type + return nil, fmt.Errorf("no witness annex") + } + lastElement := witness[len(witness)-1] - return len(lastElement) > 0 && lastElement[0] == OP_ANNEX + return lastElement, nil } // isNullDataScript returns whether or not the passed script is a standard From 1cd509d9a5e1811b528fc1dee55e2c5794f1c7b0 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:30:02 -0800 Subject: [PATCH 0627/1056] txscript: update SigCache to cache both ECDSA and Schnorr signatures In this commit, we make the sigCache slightly more general in order to be able to cache both ECDSA and Schnorr signatures. The cache is now based off of byte slices (the values) rather than the direct objects. We rely on the fact that the sighash for ecdsa and the schnorr types are distinct, so we can keep using the same top-level sighash key. In the future with Go type params, we can use a type param here instead as they all have an `IsEqual` method. --- txscript/opcode.go | 8 ++++---- txscript/sigcache.go | 28 +++++++++++++++------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index b315d03016..922d073b00 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1954,9 +1954,9 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { var sigHash chainhash.Hash copy(sigHash[:], hash) - valid = vm.sigCache.Exists(sigHash, signature, pubKey) + valid = vm.sigCache.Exists(sigHash, sigBytes, pkBytes) if !valid && signature.Verify(hash, pubKey) { - vm.sigCache.Add(sigHash, signature, pubKey) + vm.sigCache.Add(sigHash, sigBytes, pkBytes) valid = true } } else { @@ -2202,9 +2202,9 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { var sigHash chainhash.Hash copy(sigHash[:], hash) - valid = vm.sigCache.Exists(sigHash, parsedSig, parsedPubKey) + valid = vm.sigCache.Exists(sigHash, signature, pubKey) if !valid && parsedSig.Verify(hash, parsedPubKey) { - vm.sigCache.Add(sigHash, parsedSig, parsedPubKey) + vm.sigCache.Add(sigHash, signature, pubKey) valid = true } } else { diff --git a/txscript/sigcache.go b/txscript/sigcache.go index fc9f627127..b7b1308968 100644 --- a/txscript/sigcache.go +++ b/txscript/sigcache.go @@ -5,10 +5,9 @@ package txscript import ( + "bytes" "sync" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -19,20 +18,23 @@ import ( // match. In the occasion that two sigHashes collide, the newer sigHash will // simply overwrite the existing entry. type sigCacheEntry struct { - sig *ecdsa.Signature - pubKey *btcec.PublicKey + sig []byte + pubKey []byte } -// SigCache implements an ECDSA signature verification cache with a randomized -// entry eviction policy. Only valid signatures will be added to the cache. The -// benefits of SigCache are two fold. Firstly, usage of SigCache mitigates a DoS -// attack wherein an attack causes a victim's client to hang due to worst-case -// behavior triggered while processing attacker crafted invalid transactions. A -// detailed description of the mitigated DoS attack can be found here: +// SigCache implements an Schnorr+ECDSA signature verification cache with a +// randomized entry eviction policy. Only valid signatures will be added to the +// cache. The benefits of SigCache are two fold. Firstly, usage of SigCache +// mitigates a DoS attack wherein an attack causes a victim's client to hang +// due to worst-case behavior triggered while processing attacker crafted +// invalid transactions. A detailed description of the mitigated DoS attack can +// be found here: // https://bitslog.wordpress.com/2013/01/23/fixed-bitcoin-vulnerability-explanation-why-the-signature-cache-is-a-dos-protection/. // Secondly, usage of the SigCache introduces a signature verification // optimization which speeds up the validation of transactions within a block, // if they've already been seen and verified within the mempool. +// +// TODO(roasbeef): use type params here after Go 1.18 type SigCache struct { sync.RWMutex validSigs map[chainhash.Hash]sigCacheEntry @@ -56,12 +58,12 @@ func NewSigCache(maxEntries uint) *SigCache { // // NOTE: This function is safe for concurrent access. Readers won't be blocked // unless there exists a writer, adding an entry to the SigCache. -func (s *SigCache) Exists(sigHash chainhash.Hash, sig *ecdsa.Signature, pubKey *btcec.PublicKey) bool { +func (s *SigCache) Exists(sigHash chainhash.Hash, sig []byte, pubKey []byte) bool { s.RLock() entry, ok := s.validSigs[sigHash] s.RUnlock() - return ok && entry.pubKey.IsEqual(pubKey) && entry.sig.IsEqual(sig) + return ok && bytes.Equal(entry.pubKey, pubKey) && bytes.Equal(entry.sig, sig) } // Add adds an entry for a signature over 'sigHash' under public key 'pubKey' @@ -71,7 +73,7 @@ func (s *SigCache) Exists(sigHash chainhash.Hash, sig *ecdsa.Signature, pubKey * // // NOTE: This function is safe for concurrent access. Writers will block // simultaneous readers until function execution has concluded. -func (s *SigCache) Add(sigHash chainhash.Hash, sig *ecdsa.Signature, pubKey *btcec.PublicKey) { +func (s *SigCache) Add(sigHash chainhash.Hash, sig []byte, pubKey []byte) { s.Lock() defer s.Unlock() From abeaf4e334311ff3687af358448370eb74ec235d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:19:53 -0800 Subject: [PATCH 0628/1056] txscript: introduce new signatureVerifier interface to abstract over schnorr/ecdsa In this commit, we add a new signatureVerifier interface that will allow us to consolidate a lot of code as we'll now have 4 distinct sig+sighash types to verify: 1. pre-segwit 2. segwit v0 3. segwit v1 (taproot key spend) 4. tapscript spends We'll need to be able to handle 3 of the cases for the modified OP_CHECKSIG operator. This new abstraction allows us to keep the implementation of the function somewhat succinct. In this commit we implement a verifier for #3 which is needed to verify the top-level taproot keyspend. We expose the verifier using a new VerifyTaprootKeySpend function. --- go.mod | 1 + txscript/engine.go | 42 ++++ txscript/sigvalidate.go | 480 ++++++++++++++++++++++++++++++++++++++++ txscript/taproot.go | 50 +++++ 4 files changed, 573 insertions(+) create mode 100644 txscript/sigvalidate.go create mode 100644 txscript/taproot.go diff --git a/go.mod b/go.mod index a006d957dc..6962080350 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( require ( github.com/aead/siphash v1.0.1 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect diff --git a/txscript/engine.go b/txscript/engine.go index b576165ee0..d9df0d99ab 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) @@ -117,6 +118,46 @@ const ( // halforder is used to tame ECDSA malleability (see BIP0062). var halfOrder = new(big.Int).Rsh(btcec.S256().N, 1) +// taprootExecutionCtx houses the special context-specific information we need +// to validate a taproot script spend. This includes the annex, the running sig +// op count tally, and other relevant information. +type taprootExecutionCtx struct { + annex []byte + + codeSepPos uint32 + + tapLeafHash chainhash.Hash + + sigOpsBudget uint32 +} + +// sigOpsDelta is both the starting budget for sig ops for tapscript +// verification, as well as the decrease in the total budget when we encounter +// a signature. +const sigOpsDelta = 50 + +// tallysigOp attempts to decrease the current sig ops budget by sigOpsDelta. +// An error is returned if after subtracting the delta, the budget is below +// zero. +func (t *taprootExecutionCtx) tallysigOp() error { + t.sigOpsBudget -= sigOpsDelta + + if t.sigOpsBudget == 0 { + return fmt.Errorf("max sig ops exceeded") + } + + return nil +} + +// newTaprootExecutionCtx returns a fresh instance of the taproot execution +// context. +func newTaprootExecutionCtx(inputWitnessSize uint32) *taprootExecutionCtx { + return &taprootExecutionCtx{ + codeSepPos: blankCodeSepValue, + sigOpsBudget: sigOpsDelta + inputWitnessSize, + } +} + // Engine is the virtual machine that executes scripts. type Engine struct { // The following fields are set when the engine is created and must not be @@ -201,6 +242,7 @@ type Engine struct { witnessVersion int witnessProgram []byte inputAmount int64 + taprootCtx *taprootExecutionCtx } // hasFlag returns whether the script engine instance has the passed flag set. diff --git a/txscript/sigvalidate.go b/txscript/sigvalidate.go new file mode 100644 index 0000000000..7f4b6f83a7 --- /dev/null +++ b/txscript/sigvalidate.go @@ -0,0 +1,480 @@ +// Copyright (c) 2013-2022 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txscript + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/ecdsa" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// signatureVerifier is an abstract interface that allows the op code execution +// to abstract over the _type_ of signature validation being executed. At this +// point in Bitcoin's history, there're four possible sig validation contexts: +// pre-segwit, segwit v0, segwit v1 (taproot key spend validation), and the +// base tapscript verification. +type signatureVerifier interface { + // Verify returns true if the signature verifier context deems the + // signature to be valid for the given context. + Verify() bool +} + +// baseSigVerifier is used to verify signatures for the _base_ system, meaning +// ECDSA signatures encoded in DER or BER encoding. +type baseSigVerifier struct { + vm *Engine + + pubKey *btcec.PublicKey + + sig *ecdsa.Signature + + fullSigBytes []byte + + sigBytes []byte + pkBytes []byte + + subScript []byte + + hashType SigHashType +} + +// parseBaseSigAndPubkey attempts to parse a signature and public key according +// to the base consensus rules, which expect an 33-byte public key and DER or +// BER encoded signature. +func parseBaseSigAndPubkey(pkBytes, fullSigBytes []byte, + vm *Engine) (*btcec.PublicKey, *ecdsa.Signature, SigHashType, error) { + + strictEncoding := vm.hasFlag(ScriptVerifyStrictEncoding) || + vm.hasFlag(ScriptVerifyDERSignatures) + + // Trim off hashtype from the signature string and check if the + // signature and pubkey conform to the strict encoding requirements + // depending on the flags. + // + // NOTE: When the strict encoding flags are set, any errors in the + // signature or public encoding here result in an immediate script error + // (and thus no result bool is pushed to the data stack). This differs + // from the logic below where any errors in parsing the signature is + // treated as the signature failure resulting in false being pushed to + // the data stack. This is required because the more general script + // validation consensus rules do not have the new strict encoding + // requirements enabled by the flags. + hashType := SigHashType(fullSigBytes[len(fullSigBytes)-1]) + sigBytes := fullSigBytes[:len(fullSigBytes)-1] + if err := vm.checkHashTypeEncoding(hashType); err != nil { + return nil, nil, 0, err + } + if err := vm.checkSignatureEncoding(sigBytes); err != nil { + return nil, nil, 0, err + } + if err := vm.checkPubKeyEncoding(pkBytes); err != nil { + return nil, nil, 0, err + } + + // First, parse the public key, which we expect to be in the proper + // encoding. + pubKey, err := btcec.ParsePubKey(pkBytes) + if err != nil { + return nil, nil, 0, err + } + + // Next, parse the signature which should be in DER or BER depending on + // the active script flags. + var signature *ecdsa.Signature + if strictEncoding { + signature, err = ecdsa.ParseDERSignature(sigBytes) + } else { + signature, err = ecdsa.ParseSignature(sigBytes) + } + if err != nil { + return nil, nil, 0, err + } + + return pubKey, signature, hashType, nil +} + +// newBaseSigVerifier returns a new instance of the base signature verifier. An +// error is returned if the signature, sighash, or public key aren't correctly +// encoded. +func newBaseSigVerifier(pkBytes, fullSigBytes []byte, + vm *Engine) (*baseSigVerifier, error) { + + pubKey, sig, hashType, err := parseBaseSigAndPubkey( + pkBytes, fullSigBytes, vm, + ) + if err != nil { + return nil, err + } + + // Get script starting from the most recent OP_CODESEPARATOR. + subScript := vm.subScript() + + return &baseSigVerifier{ + vm: vm, + pubKey: pubKey, + pkBytes: pkBytes, + sig: sig, + sigBytes: fullSigBytes[:len(fullSigBytes)-1], + subScript: subScript, + hashType: hashType, + fullSigBytes: fullSigBytes, + }, nil +} + +// verifySig attempts to verify the signature given the computed sighash. A nil +// error is returned if the signature is valid. +func (b *baseSigVerifier) verifySig(sigHash []byte) bool { + var valid bool + if b.vm.sigCache != nil { + var sigHashBytes chainhash.Hash + copy(sigHashBytes[:], sigHash[:]) + + valid = b.vm.sigCache.Exists(sigHashBytes, b.sigBytes, b.pkBytes) + if !valid && b.sig.Verify(sigHash, b.pubKey) { + b.vm.sigCache.Add(sigHashBytes, b.sigBytes, b.pkBytes) + valid = true + } + } else { + valid = b.sig.Verify(sigHash, b.pubKey) + } + + return valid +} + +// Verify returns true if the signature verifier context deems the signature to +// be valid for the given context. +// +// NOTE: This is part of the baseSigVerifier interface. +func (b *baseSigVerifier) Verify() bool { + // Remove the signature since there is no way for a signature + // to sign itself. + subScript := removeOpcodeByData(b.subScript, b.fullSigBytes) + + sigHash := calcSignatureHash( + subScript, b.hashType, &b.vm.tx, b.vm.txIdx, + ) + + return b.verifySig(sigHash) +} + +// A compile-time assertion to ensure baseSigVerifier implements the +// signatureVerifier interface. +var _ signatureVerifier = (*baseSigVerifier)(nil) + +// baseSegwitSigVerifier implements signature verification for segwit v0. The +// only difference between this and the baseSigVerifier is how the sighash is +// computed. +type baseSegwitSigVerifier struct { + *baseSigVerifier +} + +// newBaseSegwitSigVerifier returns a new instance of the base segwit verifier. +func newBaseSegwitSigVerifier(pkBytes, fullSigBytes []byte, + vm *Engine) (*baseSegwitSigVerifier, error) { + + sigVerifier, err := newBaseSigVerifier(pkBytes, fullSigBytes, vm) + if err != nil { + return nil, err + } + + return &baseSegwitSigVerifier{ + baseSigVerifier: sigVerifier, + }, nil +} + +// Verify returns true if the signature verifier context deems the signature to +// be valid for the given context. +// +// NOTE: This is part of the baseSigVerifier interface. +func (s *baseSegwitSigVerifier) Verify() bool { + var sigHashes *TxSigHashes + if s.vm.hashCache != nil { + sigHashes = s.vm.hashCache + } else { + sigHashes = NewTxSigHashes(&s.vm.tx, s.vm.prevOutFetcher) + } + + sigHash, err := calcWitnessSignatureHashRaw( + s.subScript, sigHashes, s.hashType, &s.vm.tx, s.vm.txIdx, + s.vm.inputAmount, + ) + if err != nil { + // TODO(roasbeef): this doesn't need to return an error, should + // instead be further up the stack? this only returns an error + // if the input index is greater than the number of inputs + return false + } + + return s.verifySig(sigHash) +} + +// A compile-time assertion to ensure baseSegwitSigVerifier implements the +// signatureVerifier interface. +var _ signatureVerifier = (*baseSegwitSigVerifier)(nil) + +// taprootSigVerifier verifies signatures according to the segwit v1 rules, +// which are described in BIP 341. +type taprootSigVerifier struct { + pubKey *btcec.PublicKey + pkBytes []byte + + fullSigBytes []byte + sig *schnorr.Signature + + hashType SigHashType + + sigCache *SigCache + hashCache *TxSigHashes + + tx *wire.MsgTx + + inputIndex int + + annex []byte + + prevOuts PrevOutputFetcher +} + +// parseTaprootSigAndPubKey attempts to parse the public key and signature for +// a taproot spend that may be a keyspend or script path spend. This function +// returns an error if the pubkey is invalid, or the sig is. +func parseTaprootSigAndPubKey(pkBytes, rawSig []byte, +) (*btcec.PublicKey, *schnorr.Signature, SigHashType, error) { + + // Now that we have the raw key, we'll parse it into a schnorr public + // key we can work with. + pubKey, err := schnorr.ParsePubKey(pkBytes) + if err != nil { + return nil, nil, 0, err + } + + // Next, we'll parse the signature, which may or may not be appended + // with the desired sighash flag. + var ( + sig *schnorr.Signature + sigHashType SigHashType + ) + switch { + // If the signature is exactly 64 bytes, then we know we're using the + // implicit SIGHASH_DEFAULT sighash type. + case len(rawSig) == schnorr.SignatureSize: + // First, parse out the signature which is just the raw sig itself. + sig, err = schnorr.ParseSignature(rawSig) + if err != nil { + return nil, nil, 0, err + } + + // If the sig is 64 bytes, then we'll assume that it's the + // default sighash type, which is actually an alias for + // SIGHASH_ALL. + sigHashType = SigHashDefault + + // Otherwise, if this is a signature, with a sighash looking byte + // appended that isn't all zero, then we'll extract the sighash from + // the end of the signature. + case len(rawSig) == schnorr.SignatureSize+1 && rawSig[64] != 0: + // Extract the sighash type, then snip off the last byte so we can + // parse the signature. + sigHashType = SigHashType(rawSig[schnorr.SignatureSize]) + + rawSig = rawSig[:schnorr.SignatureSize] + sig, err = schnorr.ParseSignature(rawSig) + if err != nil { + return nil, nil, 0, err + } + + // Otherwise, this is an invalid signature, so we need to bail out. + default: + // TODO(roasbeef): do proper error here + return nil, nil, 0, fmt.Errorf("invalid sig len: %v", len(rawSig)) + } + + return pubKey, sig, sigHashType, nil +} + +// newTaprootSigVerifier returns a new instance of a taproot sig verifier given +// the necessary contextual information. +func newTaprootSigVerifier(pkBytes []byte, fullSigBytes []byte, + tx *wire.MsgTx, inputIndex int, prevOuts PrevOutputFetcher, + sigCache *SigCache, hashCache *TxSigHashes, + annex []byte) (*taprootSigVerifier, error) { + + pubKey, sig, sigHashType, err := parseTaprootSigAndPubKey( + pkBytes, fullSigBytes, + ) + if err != nil { + return nil, err + } + + return &taprootSigVerifier{ + pubKey: pubKey, + pkBytes: pkBytes, + sig: sig, + fullSigBytes: fullSigBytes, + hashType: sigHashType, + tx: tx, + inputIndex: inputIndex, + prevOuts: prevOuts, + sigCache: sigCache, + hashCache: hashCache, + annex: annex, + }, nil +} + +// verifySig attempts to verify a BIP 340 signature using the internal public +// key and signature, and the passed sigHash as the message digest. +func (t *taprootSigVerifier) verifySig(sigHash []byte) bool { + // At this point, we can check to see if this signature is already + // included in the sigCcahe and is valid or not (if one was passed in). + cacheKey, _ := chainhash.NewHash(sigHash) + if t.sigCache != nil { + if t.sigCache.Exists(*cacheKey, t.fullSigBytes, t.pkBytes) { + return true + } + } + + // If we didn't find the entry in the cache, then we'll perform full + // verification as normal, adding the entry to the cache if it's found + // to be valid. + sigValid := t.sig.Verify(sigHash, t.pubKey) + if sigValid { + if t.sigCache != nil { + // The sig is valid, so we'll add it to the cache. + t.sigCache.Add(*cacheKey, t.fullSigBytes, t.pkBytes) + } + + return true + } + + // Otherwise the sig is invalid if we get to this point. + return false +} + +// Verify returns true if the signature verifier context deems the signature to +// be valid for the given context. +// +// NOTE: This is part of the baseSigVerifier interface. +func (t *taprootSigVerifier) Verify() bool { + var opts []TaprootSigHashOption + if t.annex != nil { + opts = append(opts, WithAnnex(t.annex)) + } + + // Before we attempt to verify the signature, we'll need to first + // compute the sighash based on the input and tx information. + sigHash, err := calcTaprootSignatureHashRaw( + t.hashCache, t.hashType, t.tx, t.inputIndex, t.prevOuts, + opts..., + ) + if err != nil { + // TODO(roasbeef): propagate the error here? + return false + } + + return t.verifySig(sigHash) +} + +// A compile-time assertion to ensure taprootSigVerifier implements the +// signatureVerifier interface. +var _ signatureVerifier = (*taprootSigVerifier)(nil) + +// baseTapscriptSigVerifier verifies a signature for an input spending a +// tapscript leaf from the prevoous output. +type baseTapscriptSigVerifier struct { + *taprootSigVerifier + + vm *Engine +} + +// newBaseTapscriptSigVerifier returns a new sig verifier for tapscript input +// spends. If the public key or signature aren't correctly formatted, an error +// is returned. +func newBaseTapscriptSigVerifier(pkBytes, rawSig []byte, + vm *Engine) (*baseTapscriptSigVerifier, error) { + + switch len(pkBytes) { + // If the public key is zero bytes, then this is invalid, and will fail + // immediately. + case 0: + // TODO(roasbeef): better erro + return nil, fmt.Errorf("pubkey is zero bytes") + + // If the public key is 32 byte as we expect, then we'll parse things + // as normal. + case 32: + baseTaprootVerifier, err := newTaprootSigVerifier( + pkBytes, rawSig, &vm.tx, vm.txIdx, vm.prevOutFetcher, + vm.sigCache, vm.hashCache, vm.taprootCtx.annex, + ) + if err != nil { + return nil, err + } + + return &baseTapscriptSigVerifier{ + taprootSigVerifier: baseTaprootVerifier, + vm: vm, + }, nil + + // Otherwise, we consider this to be an unknown public key, which means + // that we'll just assume the sig to be valid. + default: + // However, if the flag preventing usage of unknown key types + // is active, then we'll return that error. + if vm.hasFlag(ScriptVerifyDiscourageUpgradeablePubkeyType) { + str := fmt.Sprintf("puybkey of length %v was used", + len(pkBytes)) + return nil, scriptError( + ErrDiscourageUpgradeablePubKeyType, str, + ) + } + + return &baseTapscriptSigVerifier{ + taprootSigVerifier: &taprootSigVerifier{}, + }, nil + } +} + +// Verify returns true if the signature verifier context deems the signature to +// be valid for the given context. +// +// NOTE: This is part of the baseSigVerifier interface. +func (b *baseTapscriptSigVerifier) Verify() bool { + // If the public key is blank, then that means it wasn't 0 or 32 bytes, + // so we'll treat this as an unknown public key version and return + // true. + if b.pubKey == nil { + return true + } + + var opts []TaprootSigHashOption + opts = append(opts, WithBaseTapscriptVersion( + b.vm.taprootCtx.codeSepPos, b.vm.taprootCtx.tapLeafHash[:], + )) + + if b.vm.taprootCtx.annex != nil { + opts = append(opts, WithAnnex(b.vm.taprootCtx.annex)) + } + + // Otherwise, we'll compute the sighash using the tapscript message + // extensions and return the outcome. + sigHash, err := calcTaprootSignatureHashRaw( + b.hashCache, b.hashType, b.tx, b.inputIndex, b.prevOuts, + opts..., + ) + if err != nil { + // TODO(roasbeef): propagate the error here? + return false + } + + return b.verifySig(sigHash) +} + +// A compile-time assertion to ensure baseTapscriptSigVerifier implements the +// signatureVerifier interface. +var _ signatureVerifier = (*baseTapscriptSigVerifier)(nil) diff --git a/txscript/taproot.go b/txscript/taproot.go new file mode 100644 index 0000000000..c086cfbc54 --- /dev/null +++ b/txscript/taproot.go @@ -0,0 +1,50 @@ +package txscript + +import ( + "fmt" + + "github.com/btcsuite/btcd/wire" +) + +// VerifyTaprootKeySpend attempts to verify a top-level taproot key spend, +// returning a non-nil error if the passed signature is invalid. If a sigCache +// is passed in, then the sig cache will be consulted to skip full verification +// of a signature that has already been seen. Witness program here should be +// the 32-byte x-only schnorr output public key. +// +// NOTE: The TxSigHashes MUST be passed in and fully populated. +func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, + inputIndex int, prevOuts PrevOutputFetcher, hashCache *TxSigHashes, + sigCache *SigCache) error { + + // First, we'll need to extract the public key from the witness + // program. + rawKey := witnessProgram + + // Extract the annex if it exists, so we can compute the proper proper + // sighash below. + var annex []byte + witness := tx.TxIn[inputIndex].Witness + if isAnnexedWitness(witness) { + annex, _ = extractAnnex(witness) + } + + // Now that we have the public key, we can create a new top-level + // keyspend verifier that'll handle all the sighash and schnorr + // specifics for us. + keySpendVerifier, err := newTaprootSigVerifier( + rawKey, rawSig, tx, inputIndex, prevOuts, sigCache, + hashCache, annex, + ) + if err != nil { + return err + } + + valid := keySpendVerifier.Verify() + if valid { + return nil + } + + // TODO(roasbeef): add proper error + return fmt.Errorf("invalid sig") +} From 1ac34b75dc2c3eeba279452fb9cb9a3000150c94 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:34:19 -0800 Subject: [PATCH 0629/1056] txscript: use new signature verifiers for existing CHECKSIG ops In this commit, we use the recently added checksig verifiers to validate signatures for pre-segwit, and segwit v0 scripts. --- txscript/opcode.go | 110 +++++++++++++--------------------------- txscript/sigvalidate.go | 2 +- 2 files changed, 35 insertions(+), 77 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 922d073b00..b78516bc58 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -9,6 +9,7 @@ import ( "crypto/sha1" "crypto/sha256" "encoding/hex" + "errors" "fmt" "hash" "strings" @@ -1880,90 +1881,47 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { return nil } - // Trim off hashtype from the signature string and check if the - // signature and pubkey conform to the strict encoding requirements - // depending on the flags. - // - // NOTE: When the strict encoding flags are set, any errors in the - // signature or public encoding here result in an immediate script error - // (and thus no result bool is pushed to the data stack). This differs - // from the logic below where any errors in parsing the signature is - // treated as the signature failure resulting in false being pushed to - // the data stack. This is required because the more general script - // validation consensus rules do not have the new strict encoding - // requirements enabled by the flags. - hashType := SigHashType(fullSigBytes[len(fullSigBytes)-1]) - sigBytes := fullSigBytes[:len(fullSigBytes)-1] - if err := vm.checkHashTypeEncoding(hashType); err != nil { - return err - } - if err := vm.checkSignatureEncoding(sigBytes); err != nil { - return err - } - if err := vm.checkPubKeyEncoding(pkBytes); err != nil { - return err - } + var sigVerifier signatureVerifier + switch { + // If no witness program is active, then we're verifying under the + // base consensus rules. + case vm.witnessProgram == nil: + sigVerifier, err = newBaseSigVerifier( + pkBytes, fullSigBytes, vm, + ) + if err != nil { + var scriptErr Error + if errors.As(err, &scriptErr) { + return err + } - // Get script starting from the most recent OP_CODESEPARATOR. - subScript := vm.subScript() - - // Generate the signature hash based on the signature hash type. - var hash []byte - if vm.isWitnessVersionActive(0) { - var sigHashes *TxSigHashes - if vm.hashCache != nil { - sigHashes = vm.hashCache - } else { - sigHashes = NewTxSigHashes(&vm.tx, vm.prevOutFetcher) + vm.dstack.PushBool(false) + return nil } - hash, err = calcWitnessSignatureHashRaw(subScript, sigHashes, hashType, - &vm.tx, vm.txIdx, vm.inputAmount) + // If the base segwit version is active, then we'll create the verifier + // that factors in those new consensus rules. + case vm.isWitnessVersionActive(BaseSegwitWitnessVersion): + sigVerifier, err = newBaseSegwitSigVerifier( + pkBytes, fullSigBytes, vm, + ) if err != nil { - return err - } - } else { - // Remove the signature since there is no way for a signature - // to sign itself. - subScript = removeOpcodeByData(subScript, fullSigBytes) - - hash = calcSignatureHash(subScript, hashType, &vm.tx, vm.txIdx) - } - - pubKey, err := btcec.ParsePubKey(pkBytes) - if err != nil { - vm.dstack.PushBool(false) - return nil - } - - var signature *ecdsa.Signature - if vm.hasFlag(ScriptVerifyStrictEncoding) || - vm.hasFlag(ScriptVerifyDERSignatures) { - - signature, err = ecdsa.ParseDERSignature(sigBytes) - } else { - signature, err = ecdsa.ParseSignature(sigBytes) - } - if err != nil { - vm.dstack.PushBool(false) - return nil - } - - var valid bool - if vm.sigCache != nil { - var sigHash chainhash.Hash - copy(sigHash[:], hash) + var scriptErr Error + if errors.As(err, &scriptErr) { + return err + } - valid = vm.sigCache.Exists(sigHash, sigBytes, pkBytes) - if !valid && signature.Verify(hash, pubKey) { - vm.sigCache.Add(sigHash, sigBytes, pkBytes) - valid = true + vm.dstack.PushBool(false) + return nil } - } else { - valid = signature.Verify(hash, pubKey) } - if !valid && vm.hasFlag(ScriptVerifyNullFail) && len(sigBytes) > 0 { + // TODO(roasbeef): verify NULLFAIL semantics as relates to constructors + // above and empty sig vectors + valid := sigVerifier.Verify() + + switch { + case !valid && vm.hasFlag(ScriptVerifyNullFail) && len(fullSigBytes[1:]) > 0: str := "signature not empty on failed checksig" return scriptError(ErrNullFail, str) } diff --git a/txscript/sigvalidate.go b/txscript/sigvalidate.go index 7f4b6f83a7..8d5a8eb590 100644 --- a/txscript/sigvalidate.go +++ b/txscript/sigvalidate.go @@ -427,7 +427,7 @@ func newBaseTapscriptSigVerifier(pkBytes, rawSig []byte, // However, if the flag preventing usage of unknown key types // is active, then we'll return that error. if vm.hasFlag(ScriptVerifyDiscourageUpgradeablePubkeyType) { - str := fmt.Sprintf("puybkey of length %v was used", + str := fmt.Sprintf("pubkey of length %v was used", len(pkBytes)) return nil, scriptError( ErrDiscourageUpgradeablePubKeyType, str, From 938c1930dac92b32d00c0060760dd18dc0bafbfa Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:21:43 -0800 Subject: [PATCH 0630/1056] txscript: add new functions for signing a top-level taproot output In this commit, we add two new functions: one for signing a raw top-level taproot keyspend, and another for generating a valid witness for a keyspend. --- txscript/sign.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/txscript/sign.go b/txscript/sign.go index f52214f371..de829d7e28 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -7,10 +7,11 @@ package txscript import ( "errors" - "github.com/btcsuite/btcd/btcec/v2/ecdsa" - "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" + + "github.com/btcsuite/btcd/btcec/v2/ecdsa" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" ) @@ -62,6 +63,57 @@ func WitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64 return wire.TxWitness{sig, pkData}, nil } +// RawTxInWitnessSignature returns a valid schnorr signature required to +// perform a taproot key-spend of the specified input. An explicit sighash is +// always attached, which can be removed by a caller if they wish to +// implicitly use the "default" sighash with a 64-byte signature. +// +// TODO(roasbeef): also need a tapscript version of this as well +func RawTxInTaprootSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, + amt int64, pkScript []byte, hashType SigHashType, + key *btcec.PrivateKey) ([]byte, error) { + + // First, we'll start by compute the top-level taproot sighash. + sigHash, err := calcTaprootSignatureHashRaw( + sigHashes, hashType, tx, idx, + NewCannedPrevOutputFetcher(pkScript, amt), + ) + if err != nil { + return nil, err + } + + // With the sighash constructed, we can sign it with the specified + // private key. + signature, err := schnorr.Sign(key, sigHash) + if err != nil { + return nil, err + } + + // Finally, append the sighash type to the final sig. + return append(signature.Serialize(), byte(hashType)), nil +} + +// TaprootWitnessSignature returns a valid witness stack that can be used to +// spend the key-spend path of a taproot input as specified in BIP 342. +// +// TODO(roasbeef): add support for annex even tho it's non-standard? +func TaprootWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, + amt int64, pkScript []byte, hashType SigHashType, + key *btcec.PrivateKey) (wire.TxWitness, error) { + + sig, err := RawTxInTaprootSignature( + tx, sigHashes, idx, amt, pkScript, hashType, key, + ) + if err != nil { + return nil, err + } + + // The witness script to spend a taproot input using the key-spend path + // is just the signature itself, given the public key is + // embedded in the previous output script. + return wire.TxWitness{sig}, nil +} + // RawTxInSignature returns the serialized ECDSA signature for the input idx of // the given transaction, with hashType appended to it. func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, From 2ac743dc9fe14e4361c3175bc82d2dc302b57f59 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:28:30 -0800 Subject: [PATCH 0631/1056] txscript: add VM verification logic for top-level taproot keyspends In this commit, we add the initial verification logic for top-level taproot keyspends. Keyspends use the base BIP 341 sighash digest and don't require any tapscript level functionality for validation. --- txscript/engine.go | 153 +++++++++++++++++++++++++++++++++-------- txscript/error_test.go | 4 ++ 2 files changed, 129 insertions(+), 28 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index d9df0d99ab..972e639e3b 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -96,6 +96,10 @@ const ( // operation whose public key isn't serialized in a compressed format // non-standard. ScriptVerifyWitnessPubKeyType + + // ScriptVerifyTaproot defines whether or not to verify a transaction + // output using the new taproot validation rules. + ScriptVerifyTaproot ) const ( @@ -113,6 +117,21 @@ const ( // payToWitnessScriptHashDataSize is the size of the witness program's // data push for a pay-to-witness-script-hash output. payToWitnessScriptHashDataSize = 32 + + // payToTaprootDataSize is the size of the witness program push for + // taproot spends. This will be the serialized x-coordinate of the + // top-level taproot output public key. + payToTaprootDataSize = 32 +) + +const ( + // BaseSegwitWitnessVersion is the original witness version that defines + // the initial set of segwit validation logic. + BaseSegwitWitnessVersion = 0 + + // TaprootWitnessVersion is the witness version that defines the new + // taproot verification logic. + TaprootWitnessVersion = 1 ) // halforder is used to tame ECDSA malleability (see BIP0062). @@ -186,6 +205,13 @@ type Engine struct { // since transaction scripts are often executed more than once from various // contexts (e.g. new block templates, when transactions are first seen // prior to being mined, part of full block verification, etc). + // + // hashCache caches the midstate of segwit v0 and v1 sighashes to + // optimize worst-case hashing complexity. + // + // prevOutFetcher is used to look up all the previous output of + // taproot transactions, as that information is hashed into the + // sighash digest for such inputs. flags ScriptFlags tx wire.MsgTx txIdx int @@ -451,8 +477,12 @@ func (vm *Engine) isWitnessVersionActive(version uint) bool { // verifyWitnessProgram validates the stored witness program using the passed // witness as input. -func (vm *Engine) verifyWitnessProgram(witness [][]byte) error { - if vm.isWitnessVersionActive(0) { +func (vm *Engine) verifyWitnessProgram(witness wire.TxWitness) error { + switch { + + // We're attempting to verify a base (witness version 0) segwit output, + // so we'll be looking for either a p2wsh or a p2wkh spend. + case vm.isWitnessVersionActive(BaseSegwitWitnessVersion): switch len(vm.witnessProgram) { case payToWitnessPubKeyHashDataSize: // P2WKH // The witness stack should consist of exactly two @@ -531,30 +561,95 @@ func (vm *Engine) verifyWitnessProgram(witness [][]byte) error { len(vm.witnessProgram)) return scriptError(ErrWitnessProgramWrongLength, errStr) } - } else if vm.hasFlag(ScriptVerifyDiscourageUpgradeableWitnessProgram) { - errStr := fmt.Sprintf("new witness program versions "+ - "invalid: %v", vm.witnessProgram) - return scriptError(ErrDiscourageUpgradableWitnessProgram, errStr) - } else { - // If we encounter an unknown witness program version and we - // aren't discouraging future unknown witness based soft-forks, - // then we de-activate the segwit behavior within the VM for - // the remainder of execution. - vm.witnessProgram = nil - } - - if vm.isWitnessVersionActive(0) { - // All elements within the witness stack must not be greater - // than the maximum bytes which are allowed to be pushed onto - // the stack. - for _, witElement := range vm.GetStack() { - if len(witElement) > MaxScriptElementSize { - str := fmt.Sprintf("element size %d exceeds "+ - "max allowed size %d", len(witElement), - MaxScriptElementSize) - return scriptError(ErrElementTooBig, str) + + // We're attempting to to verify a taproot input, and the witness + // program data push is of the expected size, so we'll be looking for a + // normal key-path spend, or a merkle proof for a tapscript with + // execution afterwards. + case vm.isWitnessVersionActive(TaprootWitnessVersion) && + len(vm.witnessProgram) == payToTaprootDataSize && !vm.bip16: + + // If taproot isn't currently active, then we'll return a + // success here in place as we don't apply the new rules unless + // the flag flips, as governed by the version bits deployment. + if !vm.hasFlag(ScriptVerifyTaproot) { + return nil + } + + // If there're no stack elements at all, then this is an + // invalid spend. + if len(witness) == 0 { + return scriptError(ErrWitnessProgramEmpty, "witness "+ + "program empty passed empty witness") + } + + // At this point, we know taproot is active, so we'll populate + // the taproot execution context. + vm.taprootCtx = newTaprootExecutionCtx( + uint32(witness.SerializeSize()), + ) + + // If we can detect the annex, then drop that off the stack, + // we'll only need it to compute the sighash later. + if isAnnexedWitness(witness) { + // TODO(roasbeef): need the annex stored somewhere? + // * compute annex hash: sha(sizeAnnex || annex) + vm.taprootCtx.annex, _ = extractAnnex(witness) + + // Snip the annex off the end of the witness stack . + witness = witness[:len(witness)-1] + } + + // From here, we'll either be validating a normal key spend, or + // a spend from the tap script leaf using a committed leaf. + switch { + // If there's only a single element left on the stack (the + // signature), then we'll apply the normal top-level schnorr + // signature verification. + case len(witness) == 1: + // As we only have a single element left (after maybe + // removing the annex), we'll do normal taproot + // keyspend validation. + rawSig := witness[0] + err := VerifyTaprootKeySpend( + vm.witnessProgram, rawSig, &vm.tx, vm.txIdx, + vm.prevOutFetcher, vm.hashCache, vm.sigCache, + ) + if err != nil { + // TODO(roasbeef): proper error + return err } + + case vm.hasFlag(ScriptVerifyDiscourageUpgradeableWitnessProgram): + errStr := fmt.Sprintf("new witness program versions "+ + "invalid: %v", vm.witnessProgram) + return scriptError(ErrDiscourageUpgradableWitnessProgram, errStr) + + default: + // If we encounter an unknown witness program version and we + // aren't discouraging future unknown witness based soft-forks, + // then we de-activate the segwit behavior within the VM for + // the remainder of execution. + vm.witnessProgram = nil } + + // TODO(roasbeef): other sanity checks here + switch { + case vm.isWitnessVersionActive(BaseSegwitWitnessVersion): + // All elements within the witness stack must not be greater + // than the maximum bytes which are allowed to be pushed onto + // the stack. + for _, witElement := range vm.GetStack() { + if len(witElement) > MaxScriptElementSize { + str := fmt.Sprintf("element size %d exceeds "+ + "max allowed size %d", len(witElement), + MaxScriptElementSize) + return scriptError(ErrElementTooBig, str) + } + } + } + + return nil } return nil @@ -639,7 +734,8 @@ func (vm *Engine) CheckErrorCondition(finalScript bool) error { // If we're in version zero witness execution mode, and this was the // final script, then the stack MUST be clean in order to maintain // compatibility with BIP16. - if finalScript && vm.isWitnessVersionActive(0) && vm.dstack.Depth() != 1 { + if finalScript && vm.isWitnessVersionActive(BaseSegwitWitnessVersion) && + vm.dstack.Depth() != 1 { return scriptError(ErrEvalFalse, "witness program must "+ "have clean stack") } @@ -891,7 +987,8 @@ func isStrictPubKeyEncoding(pubKey []byte) bool { // the strict encoding requirements if enabled. func (vm *Engine) checkPubKeyEncoding(pubKey []byte) error { if vm.hasFlag(ScriptVerifyWitnessPubKeyType) && - vm.isWitnessVersionActive(0) && !btcec.IsCompressedPubKey(pubKey) { + vm.isWitnessVersionActive(BaseSegwitWitnessVersion) && + !btcec.IsCompressedPubKey(pubKey) { str := "only compressed keys are accepted post-segwit" return scriptError(ErrWitnessPubKeyType, str) @@ -1161,7 +1258,7 @@ func (vm *Engine) SetAltStack(data [][]byte) { // engine according to the description provided by each flag. func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags, sigCache *SigCache, hashCache *TxSigHashes, inputAmount int64, - prevOuts PrevOutputFetcher) (*Engine, error) { + prevOutFetcher PrevOutputFetcher) (*Engine, error) { const scriptVersion = 0 @@ -1197,7 +1294,7 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags sigCache: sigCache, hashCache: hashCache, inputAmount: inputAmount, - prevOutFetcher: prevOuts, + prevOutFetcher: prevOutFetcher, } if vm.hasFlag(ScriptVerifyCleanStack) && (!vm.hasFlag(ScriptBip16) && !vm.hasFlag(ScriptVerifyWitness)) { diff --git a/txscript/error_test.go b/txscript/error_test.go index abfa156577..8a9cef0926 100644 --- a/txscript/error_test.go +++ b/txscript/error_test.go @@ -81,7 +81,11 @@ func TestErrorCodeStringer(t *testing.T) { {ErrWitnessUnexpected, "ErrWitnessUnexpected"}, {ErrMinimalIf, "ErrMinimalIf"}, {ErrWitnessPubKeyType, "ErrWitnessPubKeyType"}, + {ErrDiscourageOpSuccess, "ErrDiscourageOpSuccess"}, + {ErrDiscourageUpgradeableTaprootVersion, "ErrDiscourageUpgradeableTaprootVersion"}, + {ErrTapscriptCheckMultisig, "ErrTapscriptCheckMultisig"}, {ErrDiscourageUpgradableWitnessProgram, "ErrDiscourageUpgradableWitnessProgram"}, + {ErrDiscourageUpgradeablePubKeyType, "ErrDiscourageUpgradeablePubKeyType"}, {0xffff, "Unknown ErrorCode (65535)"}, } From a7c3db40af2e65a445c359f85de62113092c5f70 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:31:16 -0800 Subject: [PATCH 0632/1056] txscript: use keyBytes instead of ScriptHash for segwit utilities --- txscript/standard.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/txscript/standard.go b/txscript/standard.go index 10689a9f72..53f9f4ebbb 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -383,10 +383,9 @@ func extractWitnessV0ScriptHash(script []byte) []byte { return nil } -// extractWitnessV1ScriptHash extracts the witness script hash from the passed -// script if it is standard pay-to-witness-script-hash script. It will return -// nil otherwise. -func extractWitnessV1ScriptHash(script []byte) []byte { +// extractWitnessV1KeyBytes extracts the raw public key bytes script if it is +// standard pay-to-witness-script-hash v1 script. It will return nil otherwise. +func extractWitnessV1KeyBytes(script []byte) []byte { // A pay-to-witness-script-hash script is of the form: // OP_1 OP_DATA_32 <32-byte-hash> if len(script) == witnessV1TaprootLen && @@ -461,7 +460,7 @@ func isWitnessProgramScript(script []byte) bool { // isWitnessTaprootScript returns true if the passed script is for a // pay-to-witness-taproot output, false otherwise. func isWitnessTaprootScript(script []byte) bool { - return extractWitnessV1ScriptHash(script) != nil + return extractWitnessV1KeyBytes(script) != nil } // isAnnexedWitness returns true if the passed witness has a final push @@ -504,7 +503,7 @@ func isNullDataScript(scriptVersion uint16, script []byte) bool { // Thus, it can either be a single OP_RETURN or an OP_RETURN followed by a // data push up to MaxDataCarrierSize bytes. - // The script can't possibly be a a null data script if it doesn't start + // The script can't possibly be a null data script if it doesn't start // with OP_RETURN. Fail fast to avoid more work below. if len(script) < 1 || script[0] != OP_RETURN { return false @@ -527,7 +526,7 @@ func isNullDataScript(scriptVersion uint16, script []byte) bool { // or prior, and 1 for segwit v1 (taproot) scripts. func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { switch scriptVersion { - case 0: + case BaseSegwitWitnessVersion: switch { case isPubKeyScript(script): return PubKeyTy @@ -544,12 +543,13 @@ func typeOfScript(scriptVersion uint16, script []byte) ScriptClass { case isNullDataScript(scriptVersion, script): return NullDataTy } - case 1: + case TaprootWitnessVersion: switch { case isWitnessTaprootScript(script): return WitnessV1TaprootTy } } + return NonStandardTy } @@ -815,8 +815,8 @@ func payToWitnessScriptHashScript(scriptHash []byte) ([]byte, error) { // payToWitnessTaprootScript creates a new script to pay to a version 1 // (taproot) witness program. The passed hash is expected to be valid. -func payToWitnessTaprootScript(scriptHash []byte) ([]byte, error) { - return NewScriptBuilder().AddOp(OP_1).AddData(scriptHash).Script() +func payToWitnessTaprootScript(rawKey []byte) ([]byte, error) { + return NewScriptBuilder().AddOp(OP_1).AddData(rawKey).Script() } // payToPubkeyScript creates a new script to pay a transaction output to a @@ -1025,9 +1025,9 @@ func ExtractPkScriptAddrs(pkScript []byte, return WitnessV0ScriptHashTy, addrs, 1, nil } - if hash := extractWitnessV1ScriptHash(pkScript); hash != nil { + if rawKey := extractWitnessV1KeyBytes(pkScript); rawKey != nil { var addrs []btcutil.Address - addr, err := btcutil.NewAddressTaproot(hash, chainParams) + addr, err := btcutil.NewAddressTaproot(rawKey, chainParams) if err == nil { addrs = append(addrs, addr) } From 11dd8207409b4a0df4404f28b48ccc8a048ae3c8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:32:35 -0800 Subject: [PATCH 0633/1056] txscript: add new ScriptHasOpSuccess utility method We'll use this to examine if a script has any OP_SUCCESS op codes during pre-processing before we attempt full tapscript execution. --- txscript/opcode.go | 93 ++++++++++++++++++++++++++++++++++++++++++++++ txscript/script.go | 18 +++++++++ 2 files changed, 111 insertions(+) diff --git a/txscript/opcode.go b/txscript/opcode.go index b78516bc58..516fba164b 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -613,6 +613,99 @@ var opcodeOnelineRepls = map[string]string{ "OP_16": "16", } +// successOpcodes tracks the set of op codes that are to be interpreted as op +// codes that cause execution to automatically succeed. This map is used to +// quickly look up the op codes during script pre-processing. +var successOpcodes = map[byte]struct{}{ + OP_RESERVED: {}, // 80 + OP_VER: {}, // 98 + OP_CAT: {}, // 126 + OP_SUBSTR: {}, // 127 + OP_LEFT: {}, // 128 + OP_RIGHT: {}, // 129 + OP_INVERT: {}, // 131 + OP_AND: {}, // 132 + OP_OR: {}, // 133 + OP_XOR: {}, // 134 + OP_RESERVED1: {}, // 137 + OP_RESERVED2: {}, // 138 + OP_2MUL: {}, // 141 + OP_2DIV: {}, // 142 + OP_MUL: {}, // 149 + OP_DIV: {}, // 150 + OP_MOD: {}, // 151 + OP_LSHIFT: {}, // 152 + OP_RSHIFT: {}, // 153 + OP_UNKNOWN187: {}, // 187 + OP_UNKNOWN188: {}, // 188 + OP_UNKNOWN189: {}, // 189 + OP_UNKNOWN190: {}, // 190 + OP_UNKNOWN191: {}, // 191 + OP_UNKNOWN192: {}, // 192 + OP_UNKNOWN193: {}, // 193 + OP_UNKNOWN194: {}, // 194 + OP_UNKNOWN195: {}, // 195 + OP_UNKNOWN196: {}, // 196 + OP_UNKNOWN197: {}, // 197 + OP_UNKNOWN198: {}, // 198 + OP_UNKNOWN199: {}, // 199 + OP_UNKNOWN200: {}, // 200 + OP_UNKNOWN201: {}, // 201 + OP_UNKNOWN202: {}, // 202 + OP_UNKNOWN203: {}, // 203 + OP_UNKNOWN204: {}, // 204 + OP_UNKNOWN205: {}, // 205 + OP_UNKNOWN206: {}, // 206 + OP_UNKNOWN207: {}, // 207 + OP_UNKNOWN208: {}, // 208 + OP_UNKNOWN209: {}, // 209 + OP_UNKNOWN210: {}, // 210 + OP_UNKNOWN211: {}, // 211 + OP_UNKNOWN212: {}, // 212 + OP_UNKNOWN213: {}, // 213 + OP_UNKNOWN214: {}, // 214 + OP_UNKNOWN215: {}, // 215 + OP_UNKNOWN216: {}, // 216 + OP_UNKNOWN217: {}, // 217 + OP_UNKNOWN218: {}, // 218 + OP_UNKNOWN219: {}, // 219 + OP_UNKNOWN220: {}, // 220 + OP_UNKNOWN221: {}, // 221 + OP_UNKNOWN222: {}, // 222 + OP_UNKNOWN223: {}, // 223 + OP_UNKNOWN224: {}, // 224 + OP_UNKNOWN225: {}, // 225 + OP_UNKNOWN226: {}, // 226 + OP_UNKNOWN227: {}, // 227 + OP_UNKNOWN228: {}, // 228 + OP_UNKNOWN229: {}, // 229 + OP_UNKNOWN230: {}, // 230 + OP_UNKNOWN231: {}, // 231 + OP_UNKNOWN232: {}, // 232 + OP_UNKNOWN233: {}, // 233 + OP_UNKNOWN234: {}, // 234 + OP_UNKNOWN235: {}, // 235 + OP_UNKNOWN236: {}, // 236 + OP_UNKNOWN237: {}, // 237 + OP_UNKNOWN238: {}, // 238 + OP_UNKNOWN239: {}, // 239 + OP_UNKNOWN240: {}, // 240 + OP_UNKNOWN241: {}, // 241 + OP_UNKNOWN242: {}, // 242 + OP_UNKNOWN243: {}, // 243 + OP_UNKNOWN244: {}, // 244 + OP_UNKNOWN245: {}, // 245 + OP_UNKNOWN246: {}, // 246 + OP_UNKNOWN247: {}, // 247 + OP_UNKNOWN248: {}, // 248 + OP_UNKNOWN249: {}, // 249 + OP_SMALLINTEGER: {}, // 250 + OP_PUBKEYS: {}, // 251 + OP_UNKNOWN252: {}, // 252 + OP_PUBKEYHASH: {}, // 253 + OP_PUBKEY: {}, // 254 +} + // disasmOpcode writes a human-readable disassembly of the provided opcode and // data into the provided buffer. The compact flag indicates the disassembly // should print a more compact representation of data-carrying and small integer diff --git a/txscript/script.go b/txscript/script.go index 7d169e633e..4a04c434c2 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -522,3 +522,21 @@ func IsUnspendable(pkScript []byte) bool { const scriptVersion = 0 return checkScriptParses(scriptVersion, pkScript) != nil } + +// ScriptHasOpSuccess returns true if any op codes in the script contain an +// OP_SUCCESS op code. +func ScriptHasOpSuccess(witnessScript []byte) bool { + // First, create a new script tokenizer so we can run through all the + // elements. + tokenizer := MakeScriptTokenizer(0, witnessScript) + + // Run through all the op codes, returning true if we find anything + // that is marked as a new op success. + for tokenizer.Next() { + if _, ok := successOpcodes[tokenizer.Opcode()]; ok { + return true + } + } + + return false +} From 5c4a29b9d19e1483bb810134713a7ad6f431436d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:39:55 -0800 Subject: [PATCH 0634/1056] txscript: introduce new ControlBlock struct along w/ parsing routine In this commit, we add a new struct to represent the ControlBlock structure used to feed in the tapscript leaf inclusion proof into the witness tack. The `ParseControlBlock` parses a would-be control block and returns an error if it's incorrectly formatted. --- txscript/script.go | 3 +- txscript/taproot.go | 152 +++++++++++++++++++++++++++++++++++++++ txscript/taproot_test.go | 133 ++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 txscript/taproot_test.go diff --git a/txscript/script.go b/txscript/script.go index 4a04c434c2..aa9645e9b2 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -28,7 +28,8 @@ const ( TaprootAnnexTag = 0x50 // TaprootLeafMask is the mask applied to the control block to extract - // the leaf versions of the taproot script leaf being spent. + // the leaf version and parity of the y-coordinate of the output key if + // the taproot script leaf being spent. TaprootLeafMask = 0xfe ) diff --git a/txscript/taproot.go b/txscript/taproot.go index c086cfbc54..37f4aa882d 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -1,11 +1,53 @@ +// Copyright (c) 2013-2022 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + package txscript import ( + "bytes" "fmt" + secp "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/wire" ) +// TapscriptLeafVersion represents the various possible versions of a tapscript +// leaf version. Leaf versions are used to define, or introduce new script +// semantics, under the base taproot execution model. +// +// TODO(roasbeef): add validation here as well re proper prefix, etc? +type TapscriptLeafVersion uint8 + +const ( + // BaseLeafVersion is the base tapscript leaf version. The semantics of + // this version are defined in BIP 342. + BaseLeafVersion TapscriptLeafVersion = 0xc0 +) + +const ( + // ControlBlockBaseSize is the base size of a control block. This + // includes the initial byte for the leaf version, and then serialized + // schnorr public key. + ControlBlockBaseSize = 33 + + // ControlBlockNodeSize is the size of a given merkle branch hash in + // the control block. + ControlBlockNodeSize = 32 + + // ControlBlockMaxNodeCount is the max number of nodes that can be + // included in a control block. This value represents a merkle tree of + // depth 2^128. + ControlBlockMaxNodeCount = 128 + + // ControlBlockMaxSize is the max possible size of a control block. + // This simulates revealing a leaf from the largest possible tapscript + // tree. + ControlBlockMaxSize = ControlBlockBaseSize + (ControlBlockNodeSize * + ControlBlockMaxNodeCount) +) + // VerifyTaprootKeySpend attempts to verify a top-level taproot key spend, // returning a non-nil error if the passed signature is invalid. If a sigCache // is passed in, then the sig cache will be consulted to skip full verification @@ -48,3 +90,113 @@ func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, // TODO(roasbeef): add proper error return fmt.Errorf("invalid sig") } + +// ControlBlock houses the structured witness input for a taproot spend. This +// includes the internal taproot key, the leaf version, and finally a nearly +// complete merkle inclusion proof for the main taproot commitment. +type ControlBlock struct { + // InternalKey is the internal public key in the taproot commitment. + InternalKey *secp.PublicKey + + // OutputKeyYIsOdd denotes if the y coordinate of the output key (the + // key placed in the actual taproot output is odd. + OutputKeyYIsOdd bool + + // LeafVersion is the specified leaf version of the tapscript leaf that + // the InclusionProof below is based off of. + LeafVersion TapscriptLeafVersion + + // InclusionProof is a series of merkle branches that when hashed + // pairwise, starting with the revealed script, will yield the taproot + // commitment root. + InclusionProof []byte +} + +// ToBytes returns the control block in a format suitable for using as part of +// a witness spending a tapscript output. +func (c *ControlBlock) ToBytes() ([]byte, error) { + var b bytes.Buffer + + // The first byte of the control block is the leaf version byte XOR'd with + // the parity of the y coordinate of the public key. + yParity := byte(0) + if c.OutputKeyYIsOdd { + yParity = 1 + } + + // The first byte is a combination of the leaf version, using the lowest + // bit to encode the single bit that denotes if the yo coordinate if odd or + // even. + leafVersionAndParity := byte(c.LeafVersion) | yParity + if err := b.WriteByte(leafVersionAndParity); err != nil { + return nil, err + } + + // Next, we encode the raw 32 byte schnorr public key + if _, err := b.Write(schnorr.SerializePubKey(c.InternalKey)); err != nil { + return nil, err + } + + // Finally, we'll write out the inclusion proof as is, without any length + // prefix. + if _, err := b.Write(c.InclusionProof); err != nil { + return nil, err + } + + return b.Bytes(), nil +} + +// ParseControlBlock attempts to parse the raw bytes of a control block. An +// error is returned if the control block isn't well formed, or can't be +// parsed. +func ParseControlBlock(ctrlBlock []byte) (*ControlBlock, error) { + // The control block minimally must contain 33 bytes (for the leaf + // version and internal key) along with at least a single value + // comprising the merkle proof. If not, then it's invalid. + switch { + // The control block must minimally have 33 bytes for the internal + // public key and script leaf version. + case len(ctrlBlock) < ControlBlockBaseSize: + return nil, fmt.Errorf("invalid control block size") + + // The control block can't be larger than a proof for the largest + // possible tapscript merkle tree with 2^128 leaves. + case len(ctrlBlock) > ControlBlockMaxSize: + return nil, fmt.Errorf("invalid max block size") + + // Ignoring the fixed sized portion, we expect the total number of + // remaining bytes to be a multiple of the node size, which is 32 + // bytes. + case (len(ctrlBlock)-ControlBlockBaseSize)%ControlBlockNodeSize != 0: + return nil, fmt.Errorf("invalid max block size") + } + + // With the basic sanity checking complete, we can now parse the + // control block. + leafVersion := TapscriptLeafVersion(ctrlBlock[0] & TaprootLeafMask) + + // Extract the parity of the y coordinate of the internal key. + var yIsOdd bool + if ctrlBlock[0]&0x01 == 0x01 { + yIsOdd = true + } + + // Next, we'll parse the public key, which is the 32 bytes following + // the leaf version. + rawKey := ctrlBlock[1:33] + pubKey, err := schnorr.ParsePubKey(rawKey) + if err != nil { + return nil, err + } + + // The rest of the bytes are the control block itself, which encodes a + // merkle proof of inclusion. + proofBytes := ctrlBlock[33:] + + return &ControlBlock{ + InternalKey: pubKey, + OutputKeyYIsOdd: yIsOdd, + LeafVersion: leafVersion, + InclusionProof: proofBytes, + }, nil +} diff --git a/txscript/taproot_test.go b/txscript/taproot_test.go new file mode 100644 index 0000000000..fd5ec217d0 --- /dev/null +++ b/txscript/taproot_test.go @@ -0,0 +1,133 @@ +// Copyright (c) 2013-2022 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txscript + +import ( + "bytes" + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/btcec/v2/schnorr" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +var ( + testPubBytes, _ = hex.DecodeString("F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9") +) + +// TestControlBlockParsing tests that we're able to generate and parse a valid +// control block. +func TestControlBlockParsing(t *testing.T) { + t.Parallel() + + var testCases = []struct { + controlBlockGen func() []byte + valid bool + }{ + // An invalid control block, it's only 5 bytes and needs to be + // at least 33 bytes. + { + controlBlockGen: func() []byte { + return bytes.Repeat([]byte{0x00}, 5) + }, + valid: false, + }, + + // An invalid control block, it's greater than the largest + // accepted control block. + { + controlBlockGen: func() []byte { + return bytes.Repeat([]byte{0x00}, ControlBlockMaxSize+1) + }, + valid: false, + }, + + // An invalid control block, it isn't a multiple of 32 bytes + // enough though it has a valid starting byte length. + { + controlBlockGen: func() []byte { + return bytes.Repeat([]byte{0x00}, ControlBlockBaseSize+34) + }, + valid: false, + }, + + // A valid control block, of the largest possible size. + { + controlBlockGen: func() []byte { + privKey, _ := btcec.NewPrivateKey() + pubKey := privKey.PubKey() + + yIsOdd := (pubKey.SerializeCompressed()[0] == + secp.PubKeyFormatCompressedOdd) + + ctrl := ControlBlock{ + InternalKey: pubKey, + OutputKeyYIsOdd: yIsOdd, + LeafVersion: BaseLeafVersion, + InclusionProof: bytes.Repeat( + []byte{0x00}, + ControlBlockMaxSize-ControlBlockBaseSize, + ), + } + + ctrlBytes, _ := ctrl.ToBytes() + return ctrlBytes + }, + valid: true, + }, + + // A valid control block, only has a single element in the + // proof as the tree only has a single element. + { + controlBlockGen: func() []byte { + privKey, _ := btcec.NewPrivateKey() + pubKey := privKey.PubKey() + + yIsOdd := (pubKey.SerializeCompressed()[0] == + secp.PubKeyFormatCompressedOdd) + + ctrl := ControlBlock{ + InternalKey: pubKey, + OutputKeyYIsOdd: yIsOdd, + LeafVersion: BaseLeafVersion, + InclusionProof: bytes.Repeat( + []byte{0x00}, ControlBlockNodeSize, + ), + } + + ctrlBytes, _ := ctrl.ToBytes() + return ctrlBytes + }, + valid: true, + }, + } + for i, testCase := range testCases { + ctrlBlockBytes := testCase.controlBlockGen() + + ctrlBlock, err := ParseControlBlock(ctrlBlockBytes) + switch { + case testCase.valid && err != nil: + t.Fatalf("#%v: unable to parse valid control block: %v", i, err) + + case !testCase.valid && err == nil: + t.Fatalf("#%v: invalid control block should have failed: %v", i, err) + } + + if !testCase.valid { + continue + } + + // If we serialize the control block, we should get the exact same + // set of bytes as the input. + ctrlBytes, err := ctrlBlock.ToBytes() + if err != nil { + t.Fatalf("#%v: unable to encode bytes: %v", i, err) + } + if !bytes.Equal(ctrlBytes, ctrlBlockBytes) { + t.Fatalf("#%v: encoding mismatch: expected %x, "+ + "got %x", i, ctrlBlockBytes, ctrlBytes) + } + } +} From 37f8c8ba0acaab2720766d510d8a9ae7c077ae82 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 17:42:41 -0800 Subject: [PATCH 0635/1056] txscript: add VerifyTaprootLeafCommitment function In this commit, we add a new function to verify the taproot merkle commitment of a given tapscript leaf. Along the way we add some helper functions which can be used to construct a taproot output given the raw script root. --- chaincfg/chainhash/hash.go | 16 +++ txscript/taproot.go | 248 +++++++++++++++++++++++++++++++++++++ 2 files changed, 264 insertions(+) diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index 1371e2fca7..764ec3c40a 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -31,6 +31,19 @@ var ( // flags. TagTapSighash = []byte("TapSighash") + // TagTagTapLeaf is the message tag prefix used to compute the hash + // digest of a tapscript leaf. + TagTapLeaf = []byte("TapLeaf") + + // TagTapBranch is the message tag prefix used to compute the + // hash digest of two tap leaves into a taproot branch node. + TagTapBranch = []byte("TapBranch") + + // TagTapTweak is the message tag prefix used to compute the hash tweak + // used to enable a public key to commit to the taproot branch root + // for the witness program. + TagTapTweak = []byte("TapTweak") + // precomputedTags is a map containing the SHA-256 hash of the BIP-0340 // tags. precomputedTags = map[string]Hash{ @@ -38,6 +51,9 @@ var ( string(TagBIP0340Aux): sha256.Sum256(TagBIP0340Aux), string(TagBIP0340Nonce): sha256.Sum256(TagBIP0340Nonce), string(TagTapSighash): sha256.Sum256(TagTapSighash), + string(TagTapLeaf): sha256.Sum256(TagTapLeaf), + string(TagTapBranch): sha256.Sum256(TagTapBranch), + string(TagTapTweak): sha256.Sum256(TagTapTweak), } ) diff --git a/txscript/taproot.go b/txscript/taproot.go index 37f4aa882d..4f132e4082 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -8,8 +8,10 @@ import ( "bytes" "fmt" + "github.com/btcsuite/btcd/btcec/v2" secp "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) @@ -146,6 +148,33 @@ func (c *ControlBlock) ToBytes() ([]byte, error) { return b.Bytes(), nil } +// RootHash calculates the root hash of a tapscript given the revealed script. +func (c *ControlBlock) RootHash(revealedScript []byte) []byte { + // We'll start by creating a new tapleaf from the revealed script, + // this'll serve as the initial hash we'll use to incrementally + // reconstruct the merkle root using the control block elements. + merkleAccumulator := NewTapLeaf(c.LeafVersion, revealedScript).TapHash() + + // Now that we have our initial hash, we'll parse the control block one + // node at a time to build up our merkle accumulator into the taproot + // commitment. + // + // The control block is a series of nodes that serve as an inclusion + // proof as we can start hashing with our leaf, with each internal + // branch, until we reach the root. + numNodes := len(c.InclusionProof) / ControlBlockNodeSize + for nodeOffset := 0; nodeOffset < numNodes; nodeOffset++ { + // Extract the new node using our index to serve as a 32-byte + // offset. + leafOffset := 32 * nodeOffset + nextNode := c.InclusionProof[leafOffset : leafOffset+32] + + merkleAccumulator = tapBranchHash(merkleAccumulator[:], nextNode) + } + + return merkleAccumulator[:] +} + // ParseControlBlock attempts to parse the raw bytes of a control block. An // error is returned if the control block isn't well formed, or can't be // parsed. @@ -200,3 +229,222 @@ func ParseControlBlock(ctrlBlock []byte) (*ControlBlock, error) { InclusionProof: proofBytes, }, nil } + +// ComputeTaprootOutputKey calculates a top-level taproot output key given an +// internal key, and tapscript merkle root. The final key is derived as: +// taprootKey = internalKey + (h_tapTweak(internalKey || merkleRoot)*G). +func ComputeTaprootOutputKey(pubKey *btcec.PublicKey, + scriptRoot []byte) *btcec.PublicKey { + + // This routine only operates on x-only public keys where the public + // key always has an even y coordinate, so we'll re-parse it as such. + internalKey, _ := schnorr.ParsePubKey(schnorr.SerializePubKey(pubKey)) + + // First, we'll compute the tap tweak hash that commits to the internal + // key and the merkle script root. + tapTweakHash := chainhash.TaggedHash( + chainhash.TagTapTweak, schnorr.SerializePubKey(internalKey), + scriptRoot, + ) + + // With the tap tweek computed, we'll need to convert the merkle root + // into something in the domain we can manipulate: a scalar value mod + // N. + var tweakScalar btcec.ModNScalar + tweakScalar.SetBytes((*[32]byte)(tapTweakHash)) + + // Next, we'll need to convert the internal key to jacobian coordinates + // as the routines we need only operate on this type. + var internalPoint btcec.JacobianPoint + internalKey.AsJacobian(&internalPoint) + + // With our intermediate data obtained, we'll now compute: + // + // taprootKey = internalPoint + (tapTweak*G). + var tPoint, taprootKey btcec.JacobianPoint + btcec.ScalarBaseMultNonConst(&tweakScalar, &tPoint) + btcec.AddNonConst(&internalPoint, &tPoint, &taprootKey) + + // Finally, we'll convert the key back to affine coordinates so we can + // return the format of public key we usually use. + taprootKey.ToAffine() + + return btcec.NewPublicKey(&taprootKey.X, &taprootKey.Y) +} + +// VerifyTaprootLeafCommitment attempts to verify a taproot commitment of the +// revealed script within the taprootWitnessProgram (a schnorr public key) +// given the required information included in the control block. An error is +// returned if the reconstructed taproot commitment (a function of the merkle +// root and the internal key) doesn't match the passed witness program. +func VerifyTaprootLeafCommitment(controlBlock *ControlBlock, + taprootWitnessProgram []byte, revealedScript []byte) error { + + // First, we'll calculate the root hash from the given proof and + // revealed script. + rootHash := controlBlock.RootHash(revealedScript) + + // Next, we'll construct the final commitment (creating the external or + // taproot output key) as a function of this commitment and the + // included internal key: taprootKey = internalKey + (tPoint*G). + taprootKey := ComputeTaprootOutputKey( + controlBlock.InternalKey, rootHash, + ) + + // If we convert the taproot key to a witness program (we just need to + // serialize the public key), then it should exactly match the witness + // program passed in. + expectedWitnessProgram := schnorr.SerializePubKey(taprootKey) + if !bytes.Equal(expectedWitnessProgram, taprootWitnessProgram) { + return fmt.Errorf("invalid witness commitment") + } + + // Otherwise, if we reach here, the commitment opening is valid and + // execution can continue. + return nil +} + +// TapNode represents an abstract node in a tapscript merkle tree. A node is +// either a branch or a leaf. +type TapNode interface { + // TapHash returns the hash of the node. This will either be a tagged + // hash derived from a branch, or a leaf. + TapHash() chainhash.Hash + + // Left returns the left node. If this is a leaf node, this may be nil. + Left() TapNode + + // Right returns the right node. If this is a leaf node, this may be + // nil. + Right() TapNode +} + +// TapLeaf represents a leaf in a tapscript tree. A leaf has two components: +// the leaf version, and the script associated with that leaf version. +type TapLeaf struct { + // LeafVersion is the leaf version of this leaf. + LeafVersion TapscriptLeafVersion + + // Script is the script to be validated based on the specified leaf + // version. + Script []byte +} + +// Left rights the left node for this leaf. As this is a leaf the left node is +// nil. +func (t TapLeaf) Left() TapNode { + return nil +} + +// Right rights the right node for this leaf. As this is a leaf the right node +// is nil. +func (t TapLeaf) Right() TapNode { + return nil +} + +// NewBaseTapLeaf returns a new TapLeaf for the specified script, using the +// current base leaf version (BIP 342). +func NewBaseTapLeaf(script []byte) TapLeaf { + return TapLeaf{ + Script: script, + LeafVersion: BaseLeafVersion, + } +} + +// NewTapLeaf returns a new TapLeaf with the given leaf version and script to +// be committed to. +func NewTapLeaf(leafVersion TapscriptLeafVersion, script []byte) TapLeaf { + return TapLeaf{ + LeafVersion: leafVersion, + Script: script, + } +} + +// TapHash returns the hash digest of the target taproot script leaf. The +// digest is computed as: h_tapleaf(leafVersion || compactSizeof(script) || +// script). +func (t TapLeaf) TapHash() chainhash.Hash { + // The leaf encoding is: leafVersion || compactSizeof(script) || + // script, where compactSizeof returns the compact size needed to + // encode the value. + var leafEncoding bytes.Buffer + + _ = leafEncoding.WriteByte(byte(t.LeafVersion)) + _ = wire.WriteVarBytes(&leafEncoding, 0, t.Script) + + return *chainhash.TaggedHash(chainhash.TagTapLeaf, leafEncoding.Bytes()) +} + +// TapBranch represents an internal branch in the tapscript tree. The left or +// right nodes may either be another branch, leaves, or a combination of both. +type TapBranch struct { + // leftNode is the left node, this cannot be nil. + leftNode TapNode + + // rightNode is the right node, this cannot be nil. + rightNode TapNode +} + +// NewTapBranch creates a new internal branch from a left and right node. +func NewTapBranch(l, r TapNode) TapBranch { + + return TapBranch{ + leftNode: l, + rightNode: r, + } +} + +// Left is the left node of the branch, this might be a leaf or another +// branch. +func (t TapBranch) Left() TapNode { + return t.leftNode +} + +// Right is the right node of a branch, this might be a leaf or another branch. +func (t TapBranch) Right() TapNode { + return t.rightNode +} + +// TapHash returns the hash digest of the taproot internal branch given a left +// and right node. The final hash digest is: h_tapbranch(leftNode || +// rightNode), where leftNode is the lexicographically smaller of the two nodes. +func (t TapBranch) TapHash() chainhash.Hash { + leftHash := t.leftNode.TapHash() + rightHash := t.rightNode.TapHash() + return tapBranchHash(leftHash[:], rightHash[:]) +} + +// tapBranchHash takes the raw tap hashes of the right and left nodes and +// hashes them into a branch. See The TapBranch method for the specifics. +func tapBranchHash(l, r []byte) chainhash.Hash { + if bytes.Compare(l[:], r[:]) > 0 { + l = r + r = l + } + + return *chainhash.TaggedHash( + chainhash.TagTapBranch, l[:], r[:], + ) +} + +// TapscriptProof is a proof of inclusion that a given leaf (a script and leaf +// version) is included within a top-level taproot output commitment. +type TapscriptProof struct { + // TapLeaf is the leaf that we want to prove inclusion for. + TapLeaf + + // InclusionProof is the tail end of the control block that contains + // the series of hashes (the sibling hashes up the tree), that when + // hashed together allow us to re-derive the top level taproot output. + InclusionProof []byte +} + +// ToControlBlock maps the tapscript proof into a fully valid control block +// that can be used as a witness item for a tapscript spend. +func (t *TapscriptProof) ToControlBlock(internalKey *btcec.PublicKey) ControlBlock { + return ControlBlock{ + InternalKey: internalKey, + LeafVersion: t.TapLeaf.LeafVersion, + InclusionProof: t.InclusionProof, + } +} From 6fc4199ee479a1ca313a8c2ec5f071c755461277 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:14:49 -0800 Subject: [PATCH 0636/1056] txscript: add new RawTxInTapscriptSignature to generate tapsript sigs In this commit, we add a new function `RawTxInTapscriptSignature` that will be used to generate signatures in the _tapscript_ context. Note that this differs from top-level taproot as a distinct sighash is used, and we _always_ accept a root hash to perform the proper tweak. --- btcec/privkey.go | 6 ++ btcutil/go.sum | 8 +++ btcutil/psbt/go.mod | 1 + btcutil/psbt/go.sum | 8 +++ go.mod | 5 +- go.sum | 9 +++ txscript/sign.go | 82 +++++++++++++++++++++++---- txscript/taproot.go | 51 +++++++++++++++++ txscript/taproot_test.go | 116 ++++++++++++++++++++++++++++++++++++++- 9 files changed, 272 insertions(+), 14 deletions(-) diff --git a/btcec/privkey.go b/btcec/privkey.go index 6f13990b1f..4efa806c5f 100644 --- a/btcec/privkey.go +++ b/btcec/privkey.go @@ -27,5 +27,11 @@ func NewPrivateKey() (*PrivateKey, error) { return secp.GeneratePrivateKey() } +// PrivKeyFromScalar instantiates a new private key from a scalar encoded as a +// big integer. +func PrivKeyFromScalar(key *ModNScalar) *PrivateKey { + return &PrivateKey{Key: *key} +} + // PrivKeyBytesLen defines the length in bytes of a serialized private key. const PrivKeyBytesLen = 32 diff --git a/btcutil/go.sum b/btcutil/go.sum index 69c701ee18..8617dd8351 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -11,6 +11,7 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufo github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= @@ -43,6 +44,11 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -79,3 +85,5 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 4aa9d394c5..059bdab55c 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -12,6 +12,7 @@ require ( require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect ) diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index 40bb0c16ed..3056278f02 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -8,6 +8,7 @@ github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufo github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= @@ -38,6 +39,11 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= @@ -73,3 +79,5 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.mod b/go.mod index 6962080350..732ed420c8 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,11 @@ require ( github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 github.com/btcsuite/winsvc v1.0.0 github.com/davecgh/go-spew v1.1.1 + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/decred/dcrd/lru v1.0.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 + github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) @@ -19,9 +21,10 @@ require ( require ( github.com/aead/siphash v1.0.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) replace github.com/btcsuite/btcd/btcutil => ./btcutil diff --git a/go.sum b/go.sum index 51aa052060..604e50543e 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3 github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= @@ -55,6 +56,11 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -91,6 +97,7 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -99,3 +106,5 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/txscript/sign.go b/txscript/sign.go index de829d7e28..fc89312f20 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -63,14 +63,12 @@ func WitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64 return wire.TxWitness{sig, pkData}, nil } -// RawTxInWitnessSignature returns a valid schnorr signature required to -// perform a taproot key-spend of the specified input. An explicit sighash is -// always attached, which can be removed by a caller if they wish to -// implicitly use the "default" sighash with a 64-byte signature. -// -// TODO(roasbeef): also need a tapscript version of this as well +// RawTxInTaprootSignature returns a valid schnorr signature required to +// perform a taproot key-spend of the specified input. If SigHashDefault was +// specified, then the returned signature is 64-byte in length, as it omits the +// additional byte to denote the sighash type. func RawTxInTaprootSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, - amt int64, pkScript []byte, hashType SigHashType, + amt int64, pkScript []byte, tapScriptRootHash []byte, hashType SigHashType, key *btcec.PrivateKey) ([]byte, error) { // First, we'll start by compute the top-level taproot sighash. @@ -82,27 +80,48 @@ func RawTxInTaprootSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, return nil, err } + // Before we sign the sighash, we'll need to apply the taptweak to the + // private key based on the tapScriptRootHash. + privKeyTweak := TweakTaprootPrivKey(key, tapScriptRootHash) + // With the sighash constructed, we can sign it with the specified // private key. - signature, err := schnorr.Sign(key, sigHash) + signature, err := schnorr.Sign(privKeyTweak, sigHash) if err != nil { return nil, err } - // Finally, append the sighash type to the final sig. - return append(signature.Serialize(), byte(hashType)), nil + sig := signature.Serialize() + + // If this is sighash default, then we can just return the signature + // directly. + if hashType&SigHashDefault == SigHashDefault { + return sig, nil + } + + // Otherwise, append the sighash type to the final sig. + return append(sig, byte(hashType)), nil } // TaprootWitnessSignature returns a valid witness stack that can be used to -// spend the key-spend path of a taproot input as specified in BIP 342. +// spend the key-spend path of a taproot input as specified in BIP 342 and BIP +// 86. This method assumes that the public key included in pkScript was +// generated using ComputeTaprootKeyNoScript that commits to a fake root +// tapscript hash. If not, then RawTxInTaprootSignature should be used with the +// actual committed contents. // // TODO(roasbeef): add support for annex even tho it's non-standard? func TaprootWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, amt int64, pkScript []byte, hashType SigHashType, key *btcec.PrivateKey) (wire.TxWitness, error) { + // As we're assuming this was a BIP 86 key, we use an empty root hash + // which means output key commits to just the public key. + fakeTapscriptRootHash := []byte{} + sig, err := RawTxInTaprootSignature( - tx, sigHashes, idx, amt, pkScript, hashType, key, + tx, sigHashes, idx, amt, pkScript, fakeTapscriptRootHash, + hashType, key, ) if err != nil { return nil, err @@ -114,6 +133,45 @@ func TaprootWitnessSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, return wire.TxWitness{sig}, nil } +// RawTxInTapscriptSignature computes a raw schnorr signature for a signature +// generated from a tapscript leaf. This differs from the +// RawTxInTaprootSignature which is used to generate signatures for top-level +// taproot key spends. +// +// TODO(roasbeef): actually add code-sep to interface? not really used +// anywhere.... +func RawTxInTapscriptSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, + amt int64, pkScript []byte, tapLeaf TapLeaf, hashType SigHashType, + privKey *btcec.PrivateKey) ([]byte, error) { + + // First, we'll start by compute the top-level taproot sighash. + tapLeafHash := tapLeaf.TapHash() + sigHash, err := calcTaprootSignatureHashRaw( + sigHashes, hashType, tx, idx, + NewCannedPrevOutputFetcher(pkScript, amt), + WithBaseTapscriptVersion(blankCodeSepValue, tapLeafHash[:]), + ) + if err != nil { + return nil, err + } + + // With the sighash constructed, we can sign it with the specified + // private key. + signature, err := schnorr.Sign(privKey, sigHash) + if err != nil { + return nil, err + } + + // Finally, append the sighash type to the final sig if it's not the + // default sighash value (in which case appending it is disallowed). + if hashType != SigHashDefault { + return append(signature.Serialize(), byte(hashType)), nil + } + + // The default sighash case where we'll return _just_ the signature. + return signature.Serialize(), nil +} + // RawTxInSignature returns the serialized ECDSA signature for the input idx of // the given transaction, with hashType appended to it. func RawTxInSignature(tx *wire.MsgTx, idx int, subScript []byte, diff --git a/txscript/taproot.go b/txscript/taproot.go index 4f132e4082..5bd7aef619 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -96,6 +96,9 @@ func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, // ControlBlock houses the structured witness input for a taproot spend. This // includes the internal taproot key, the leaf version, and finally a nearly // complete merkle inclusion proof for the main taproot commitment. +// +// TODO(roasbeef): method to serialize control block that commits to even +// y-bit, which pops up everywhere even tho 32 byte keys type ControlBlock struct { // InternalKey is the internal public key in the taproot commitment. InternalKey *secp.PublicKey @@ -272,6 +275,54 @@ func ComputeTaprootOutputKey(pubKey *btcec.PublicKey, return btcec.NewPublicKey(&taprootKey.X, &taprootKey.Y) } +// ComputeTaprootKeyNoScript calculates the top-level taproot output key given +// an internal key, and a desire that the only way an output can be spent is +// with the keyspend path. This is useful for normal wallet operations that +// don't need any other additional spending conditions. +func ComputeTaprootKeyNoScript(internalKey *btcec.PublicKey) *btcec.PublicKey { + // We'll compute a custom tap tweak hash that just commits to the key, + // rather than an actual root hash. + fakeScriptroot := []byte{} + + return ComputeTaprootOutputKey(internalKey, fakeScriptroot) +} + +// TweakTaprootPrivKey applies the same operation as ComputeTaprootOutputKey, +// but on the private key instead. The final key is derived as: privKey + +// h_tapTweak(internalKey || merkleRoot) % N, where N is the order of the +// secp256k1 curve, and merkleRoot is the root hash of the tapscript tree. +func TweakTaprootPrivKey(privKey *btcec.PrivateKey, + scriptRoot []byte) *btcec.PrivateKey { + + // If the corresponding public key has an odd y coordinate, then we'll + // negate the private key as specified in BIP 341. + privKeyScalar := &privKey.Key + pubKeyBytes := privKey.PubKey().SerializeCompressed() + if pubKeyBytes[0] == btcec.PubKeyFormatCompressedOdd { + privKeyScalar.Negate() + } + + // Next, we'll compute the tap tweak hash that commits to the internal + // key and the merkle script root. We'll snip off the extra parity byte + // from the compressed serialization and use that directly. + schnorrKeyBytes := pubKeyBytes[1:] + tapTweakHash := chainhash.TaggedHash( + chainhash.TagTapTweak, schnorrKeyBytes, scriptRoot, + ) + + // Map the private key to a ModNScalar which is needed to perform + // operation mod the curve order. + var tweakScalar btcec.ModNScalar + tweakScalar.SetBytes((*[32]byte)(tapTweakHash)) + + // Now that we have the private key in its may negated form, we'll add + // the script root as a tweak. As we're using a ModNScalar all + // operations are already normalized mod the curve order. + privTweak := privKeyScalar.Add(&tweakScalar) + + return btcec.PrivKeyFromScalar(privTweak) +} + // VerifyTaprootLeafCommitment attempts to verify a taproot commitment of the // revealed script within the taprootWitnessProgram (a schnorr public key) // given the required information included in the control block. An error is diff --git a/txscript/taproot_test.go b/txscript/taproot_test.go index fd5ec217d0..2a458551cc 100644 --- a/txscript/taproot_test.go +++ b/txscript/taproot_test.go @@ -8,13 +8,40 @@ import ( "bytes" "encoding/hex" "testing" + "testing/quick" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/hdkeychain" + "github.com/btcsuite/btcd/chaincfg" secp "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/stretchr/testify/require" ) var ( - testPubBytes, _ = hex.DecodeString("F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9") + testPubBytes, _ = hex.DecodeString("F9308A019258C31049344F85F89D5229B" + + "531C845836F99B08601F113BCE036F9") + + // rootKey is the test root key defined in the test vectors: + // https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki + rootKey, _ = hdkeychain.NewKeyFromString( + "xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLi" + + "sriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu", + ) + + // accountPath is the base path for BIP86 (m/86'/0'/0'). + accountPath = []uint32{ + 86 + hdkeychain.HardenedKeyStart, hdkeychain.HardenedKeyStart, + hdkeychain.HardenedKeyStart, + } + expectedExternalAddresses = []string{ + "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr", + "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh", + } + expectedInternalAddresses = []string{ + "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7", + } ) // TestControlBlockParsing tests that we're able to generate and parse a valid @@ -131,3 +158,90 @@ func TestControlBlockParsing(t *testing.T) { } } } + +// TestTaprootScriptSpendTweak tests that for any 32-byte hypothetical script +// root, the resulting tweaked public key is the same as tweaking the private +// key, then generating a public key from that. This test a quickcheck test to +// assert the following invariant: +// +// * taproot_tweak_pubkey(pubkey_gen(seckey), h)[1] == +// pubkey_gen(taproot_tweak_seckey(seckey, h)) +func TestTaprootScriptSpendTweak(t *testing.T) { + t.Parallel() + + // Assert that if we use this x value as the hash of the script root, + // then if we generate a tweaked public key, it's the same key as if we + // used that key to generate the tweaked + // private key, and then generated the public key from that. + f := func(x [32]byte) bool { + privKey, err := btcec.NewPrivateKey() + if err != nil { + return false + } + + // Generate the tweaked public key using the x value as the + // script root. + tweakedPub := ComputeTaprootOutputKey(privKey.PubKey(), x[:]) + + // Now we'll generate the corresponding tweaked private key. + tweakedPriv := TweakTaprootPrivKey(privKey, x[:]) + + // The public key for this private key should be the same as + // the tweaked public key we generate above. + return tweakedPub.IsEqual(tweakedPriv.PubKey()) && + bytes.Equal( + schnorr.SerializePubKey(tweakedPub), + schnorr.SerializePubKey(tweakedPriv.PubKey()), + ) + } + + if err := quick.Check(f, nil); err != nil { + t.Fatalf("tweaked public/private key mapping is "+ + "incorrect: %v", err) + } + +} + +// TestTaprootConstructKeyPath tests the key spend only taproot construction. +func TestTaprootConstructKeyPath(t *testing.T) { + checkPath := func(branch uint32, expectedAddresses []string) { + path, err := derivePath(rootKey, append(accountPath, branch)) + require.NoError(t, err) + + for index, expectedAddr := range expectedAddresses { + extendedKey, err := path.Derive(uint32(index)) + require.NoError(t, err) + + pubKey, err := extendedKey.ECPubKey() + require.NoError(t, err) + + tapKey := ComputeTaprootKeyNoScript(pubKey) + + addr, err := btcutil.NewAddressTaproot( + schnorr.SerializePubKey(tapKey), + &chaincfg.MainNetParams, + ) + require.NoError(t, err) + + require.Equal(t, expectedAddr, addr.String()) + } + } + checkPath(0, expectedExternalAddresses) + checkPath(1, expectedInternalAddresses) +} + +func derivePath(key *hdkeychain.ExtendedKey, path []uint32) ( + *hdkeychain.ExtendedKey, error) { + + var ( + currentKey = key + err error + ) + for _, pathPart := range path { + currentKey, err = currentKey.Derive(pathPart) + if err != nil { + return nil, err + } + } + return currentKey, nil +} From 17e46094944733feeb38b7571d2a22b6d4e0ca03 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:16:09 -0800 Subject: [PATCH 0637/1056] txscript: add AssembleTaprootScriptTree func for creating input witnesses In this commit, we add a new AssembleTaprootScriptTree function that given a list of tapscript leaves, generates a valid tapscript root, along with the auxiliary proof data needed to spend each output. --- txscript/taproot.go | 282 +++++++++++++++++++++++++++++++++++++-- txscript/taproot_test.go | 116 ++++++++++++++++ 2 files changed, 390 insertions(+), 8 deletions(-) diff --git a/txscript/taproot.go b/txscript/taproot.go index 5bd7aef619..f07e4d015a 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -9,10 +9,10 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec/v2" - secp "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) // TapscriptLeafVersion represents the various possible versions of a tapscript @@ -101,7 +101,7 @@ func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, // y-bit, which pops up everywhere even tho 32 byte keys type ControlBlock struct { // InternalKey is the internal public key in the taproot commitment. - InternalKey *secp.PublicKey + InternalKey *btcec.PublicKey // OutputKeyYIsOdd denotes if the y coordinate of the output key (the // key placed in the actual taproot output is odd. @@ -298,7 +298,7 @@ func TweakTaprootPrivKey(privKey *btcec.PrivateKey, // negate the private key as specified in BIP 341. privKeyScalar := &privKey.Key pubKeyBytes := privKey.PubKey().SerializeCompressed() - if pubKeyBytes[0] == btcec.PubKeyFormatCompressedOdd { + if pubKeyBytes[0] == secp.PubKeyFormatCompressedOdd { privKeyScalar.Negate() } @@ -350,6 +350,14 @@ func VerifyTaprootLeafCommitment(controlBlock *ControlBlock, return fmt.Errorf("invalid witness commitment") } + // Finally, we'll verify that the parity of the y coordinate of the + // public key we've derived matches the control block. + derivedYIsOdd := (taprootKey.SerializeCompressed()[0] == + secp.PubKeyFormatCompressedOdd) + if controlBlock.OutputKeyYIsOdd != derivedYIsOdd { + return fmt.Errorf("invalid witness commitment") + } + // Otherwise, if we reach here, the commitment opening is valid and // execution can continue. return nil @@ -415,6 +423,9 @@ func NewTapLeaf(leafVersion TapscriptLeafVersion, script []byte) TapLeaf { // digest is computed as: h_tapleaf(leafVersion || compactSizeof(script) || // script). func (t TapLeaf) TapHash() chainhash.Hash { + // TODO(roasbeef): cache these and the branch due to the recursive + // call, so memoize + // The leaf encoding is: leafVersion || compactSizeof(script) || // script, where compactSizeof returns the compact size needed to // encode the value. @@ -469,8 +480,7 @@ func (t TapBranch) TapHash() chainhash.Hash { // hashes them into a branch. See The TapBranch method for the specifics. func tapBranchHash(l, r []byte) chainhash.Hash { if bytes.Compare(l[:], r[:]) > 0 { - l = r - r = l + l, r = r, l } return *chainhash.TaggedHash( @@ -484,6 +494,10 @@ type TapscriptProof struct { // TapLeaf is the leaf that we want to prove inclusion for. TapLeaf + // RootNode is the root of the tapscript tree, this will be used to + // compute what the final output key looks like. + RootNode TapNode + // InclusionProof is the tail end of the control block that contains // the series of hashes (the sibling hashes up the tree), that when // hashed together allow us to re-derive the top level taproot output. @@ -493,9 +507,261 @@ type TapscriptProof struct { // ToControlBlock maps the tapscript proof into a fully valid control block // that can be used as a witness item for a tapscript spend. func (t *TapscriptProof) ToControlBlock(internalKey *btcec.PublicKey) ControlBlock { + // Compute the total level output commitment based on the populated + // root node. + rootHash := t.RootNode.TapHash() + taprootKey := ComputeTaprootOutputKey( + internalKey, rootHash[:], + ) + + // With the commitment computed we can obtain the bit that denotes if + // the resulting key has an odd y coordinate or not. + var outputKeyYIsOdd bool + if taprootKey.SerializeCompressed()[0] == + secp.PubKeyFormatCompressedOdd { + + outputKeyYIsOdd = true + } + return ControlBlock{ - InternalKey: internalKey, - LeafVersion: t.TapLeaf.LeafVersion, - InclusionProof: t.InclusionProof, + InternalKey: internalKey, + OutputKeyYIsOdd: outputKeyYIsOdd, + LeafVersion: t.TapLeaf.LeafVersion, + InclusionProof: t.InclusionProof, + } +} + +// IndexedTapScriptTree reprints a fully contracted tapscript tree. The +// RootNode can be used to traverse down the full tree. In addition, complete +// inclusion proofs for each leaf are included as well, with an index into the +// slice of proof based on the tap leaf hash of a given leaf. +type IndexedTapScriptTree struct { + // RootNode is the root of the tapscript tree. RootNode.TapHash() can + // be used to extract the hash needed to derive the taptweak committed + // to in the taproot output. + RootNode TapNode + + // LeafMerkleProofs is a slice that houses the series of merkle + // inclusion proofs for each leaf based on the input order of the + // leaves. + LeafMerkleProofs []TapscriptProof + + // LeafProofIndex maps the TapHash() of a given leaf node to the index + // within the LeafMerkleProofs array above. This can be used to + // retrieve the inclusion proof for a given script when constructing + // the witness stack and control block for spending a tapscript path. + LeafProofIndex map[chainhash.Hash]int +} + +// NewIndexedTapScriptTree creates a new empty tapscript tree that has enough +// space to hold information for the specified amount of leaves. +func NewIndexedTapScriptTree(numLeaves int) *IndexedTapScriptTree { + return &IndexedTapScriptTree{ + LeafMerkleProofs: make([]TapscriptProof, numLeaves), + LeafProofIndex: make(map[chainhash.Hash]int, numLeaves), + } +} + +// hashTapNodes takes a left and right now, and returns the left and right tap +// hashes, along with the new combined node. If both nodes are nil, nil +// pointers are returned. If the right now is nil, then the left node is passed +// in, which effectively will "lift" the node up in the tree as long as it +// doesn't have any siblings. +func hashTapNodes(left, right TapNode) (*chainhash.Hash, *chainhash.Hash, TapNode) { + switch { + // If there's no left child, then this is a "nil" portion of the array + // tree, so well thread thru nil. + case left == nil: + return nil, nil, nil + + // If there's no right child, then this is a single node that'll be + // passed all the way up the tree as it has no children. + case right == nil: + return nil, nil, left } + + // The result of hashing two nodes will always be a branch, so we start + // with that. + leftHash := left.TapHash() + rightHash := right.TapHash() + + return &leftHash, &rightHash, NewTapBranch(left, right) +} + +// leafDescendants is a recursive algorithm that returns all the leaf nodes +// that are a decedents of this tree. This is used to collect the series of +// nodes we need to extend the inclusion proof of each time we go up in the +// tree. +func leafDescendants(node TapNode) []TapNode { + // A leaf node has no decedents, so we just return it directly. + if node.Left() == nil && node.Right() == nil { + return []TapNode{node} + } + + // Otherwise, get the descendants of the left and right sub-trees to + // return. + leftLeaves := leafDescendants(node.Left()) + rightLeaves := leafDescendants(node.Right()) + + return append(leftLeaves, rightLeaves...) +} + +// AssembleTaprootScriptTree constructs a new fully indexed tapscript tree +// given a series of leaf nodes. A combination of a recursive data structure, +// and an array-based representation are used to both generate the tree and +// also accumulate all the necessary inclusion proofs in the same path. See the +// comment of blockchain.BuildMerkleTreeStore for further details. +func AssembleTaprootScriptTree(leaves ...TapLeaf) *IndexedTapScriptTree { + // If there's only a single leaf, then that becomes our root. + if len(leaves) == 1 { + // A lone leaf has no additional inclusion proof, as a verifier + // will just hash the leaf as the sole branch. + leaf := leaves[0] + return &IndexedTapScriptTree{ + RootNode: leaf, + LeafProofIndex: map[chainhash.Hash]int{ + leaf.TapHash(): 0, + }, + LeafMerkleProofs: []TapscriptProof{ + { + TapLeaf: leaf, + RootNode: leaf, + InclusionProof: nil, + }, + }, + } + } + + // We'll start out by populating the leaf index which maps a leave's + // taphash to its index within the tree. + scriptTree := NewIndexedTapScriptTree(len(leaves)) + for i, leaf := range leaves { + leafHash := leaf.TapHash() + scriptTree.LeafProofIndex[leafHash] = i + } + + var branches []TapBranch + for i := 0; i < len(leaves); i += 2 { + // If there's only a single leaf left, then we'll merge this + // with the last branch we have. + if i == len(leaves)-1 { + branchToMerge := branches[len(branches)-1] + leaf := leaves[i] + newBranch := NewTapBranch(branchToMerge, leaf) + + branches[len(branches)-1] = newBranch + + // The leaf includes the existing branch within its + // inclusion proof. + branchHash := branchToMerge.TapHash() + + scriptTree.LeafMerkleProofs[i].TapLeaf = leaf + scriptTree.LeafMerkleProofs[i].InclusionProof = append( + scriptTree.LeafMerkleProofs[i].InclusionProof, + branchHash[:]..., + ) + + // We'll also add this right hash to the inclusion of + // the left and right nodes of the branch. + lastLeafHash := leaf.TapHash() + + leftLeafHash := branchToMerge.Left().TapHash() + leftLeafIndex := scriptTree.LeafProofIndex[leftLeafHash] + scriptTree.LeafMerkleProofs[leftLeafIndex].InclusionProof = append( + scriptTree.LeafMerkleProofs[leftLeafIndex].InclusionProof, + lastLeafHash[:]..., + ) + + rightLeafHash := branchToMerge.Right().TapHash() + rightLeafIndex := scriptTree.LeafProofIndex[rightLeafHash] + scriptTree.LeafMerkleProofs[rightLeafIndex].InclusionProof = append( + scriptTree.LeafMerkleProofs[rightLeafIndex].InclusionProof, + lastLeafHash[:]..., + ) + + continue + } + + // While we still have leaves left, we'll combine two of them + // into a new branch node. + left, right := leaves[i], leaves[i+1] + nextBranch := NewTapBranch(left, right) + branches = append(branches, nextBranch) + + // The left node will use the right node as part of its + // inclusion proof, and vice versa. + leftHash := left.TapHash() + rightHash := right.TapHash() + + scriptTree.LeafMerkleProofs[i].TapLeaf = left + scriptTree.LeafMerkleProofs[i].InclusionProof = append( + scriptTree.LeafMerkleProofs[i].InclusionProof, + rightHash[:]..., + ) + + scriptTree.LeafMerkleProofs[i+1].TapLeaf = right + scriptTree.LeafMerkleProofs[i+1].InclusionProof = append( + scriptTree.LeafMerkleProofs[i+1].InclusionProof, + leftHash[:]..., + ) + } + + // In this second phase, we'll merge all the leaf branches we have one + // by one until we have our final root. + var rootNode TapNode + for len(branches) != 0 { + // When we only have a single branch left, then that becomes + // our root. + if len(branches) == 1 { + rootNode = branches[0] + break + } + + left, right := branches[0], branches[1] + + newBranch := NewTapBranch(left, right) + + branches = branches[2:] + + branches = append(branches, newBranch) + + // Accumulate the sibling hash of this new branch for all the + // leaves that are its children. + leftLeafDescendants := leafDescendants(left) + rightLeafDescendants := leafDescendants(right) + + leftHash, rightHash := left.TapHash(), right.TapHash() + + // For each left hash that's a leaf descendants, well add the + // right sibling as that sibling is needed to construct the new + // internal branch we just created. We also do the same for the + // siblings of the right node. + for _, leftLeaf := range leftLeafDescendants { + leafHash := leftLeaf.TapHash() + leafIndex := scriptTree.LeafProofIndex[leafHash] + + scriptTree.LeafMerkleProofs[leafIndex].InclusionProof = append( + scriptTree.LeafMerkleProofs[leafIndex].InclusionProof, + rightHash[:]..., + ) + } + for _, rightLeaf := range rightLeafDescendants { + leafHash := rightLeaf.TapHash() + leafIndex := scriptTree.LeafProofIndex[leafHash] + + scriptTree.LeafMerkleProofs[leafIndex].InclusionProof = append( + scriptTree.LeafMerkleProofs[leafIndex].InclusionProof, + leftHash[:]..., + ) + } + } + + // Populate the top level root node pointer, as well as the pointer in + // each proof. + scriptTree.RootNode = rootNode + for i := range scriptTree.LeafMerkleProofs { + scriptTree.LeafMerkleProofs[i].RootNode = rootNode + } + + return scriptTree } diff --git a/txscript/taproot_test.go b/txscript/taproot_test.go index 2a458551cc..178405b526 100644 --- a/txscript/taproot_test.go +++ b/txscript/taproot_test.go @@ -7,6 +7,8 @@ package txscript import ( "bytes" "encoding/hex" + "fmt" + prand "math/rand" "testing" "testing/quick" @@ -245,3 +247,117 @@ func derivePath(key *hdkeychain.ExtendedKey, path []uint32) ( } return currentKey, nil } + +// TestTapscriptCommitmentVerification that given a valid control block, proof +// we're able to both generate and validate validate script tree leaf inclusion +// proofs. +func TestTapscriptCommitmentVerification(t *testing.T) { + t.Parallel() + + // make from 0 to 1 leaf + // ensure verifies properly + testCases := []struct { + numLeaves int + + valid bool + + treeMutateFunc func(*IndexedTapScriptTree) + + ctrlBlockMutateFunc func(*ControlBlock) + }{ + // A valid merkle proof of a single leaf. + { + numLeaves: 1, + valid: true, + }, + + // A valid series of merkle proofs with an odd number of leaves. + { + numLeaves: 3, + valid: true, + }, + + // A valid series of merkle proofs with an even number of leaves. + { + numLeaves: 4, + valid: true, + }, + + // An invalid merkle proof, we modify the last byte of one of + // the leaves. + { + numLeaves: 4, + valid: false, + treeMutateFunc: func(t *IndexedTapScriptTree) { + for _, leafProof := range t.LeafMerkleProofs { + leafProof.InclusionProof[0] ^= 1 + } + }, + }, + + { + // An invalid series of proofs, we modify the control + // block to not match the parity of the final output + // key commitment. + numLeaves: 2, + valid: false, + ctrlBlockMutateFunc: func(c *ControlBlock) { + c.OutputKeyYIsOdd = !c.OutputKeyYIsOdd + }, + }, + } + for _, testCase := range testCases { + testName := fmt.Sprintf("num_leaves=%v, valid=%v, treeMutate=%v, "+ + "ctrlBlockMutate=%v", testCase.numLeaves, testCase.valid, + testCase.treeMutateFunc == nil, testCase.ctrlBlockMutateFunc == nil) + + t.Run(testName, func(t *testing.T) { + tapScriptLeaves := make([]TapLeaf, testCase.numLeaves) + for i := 0; i < len(tapScriptLeaves); i++ { + numLeafBytes := prand.Intn(1000) + scriptBytes := make([]byte, numLeafBytes) + if _, err := prand.Read(scriptBytes[:]); err != nil { + t.Fatalf("unable to read rand bytes: %v", err) + } + tapScriptLeaves[i] = NewBaseTapLeaf(scriptBytes) + } + + scriptTree := AssembleTaprootScriptTree(tapScriptLeaves...) + + if testCase.treeMutateFunc != nil { + testCase.treeMutateFunc(scriptTree) + } + + internalKey, _ := btcec.NewPrivateKey() + + rootHash := scriptTree.RootNode.TapHash() + outputKey := ComputeTaprootOutputKey( + internalKey.PubKey(), rootHash[:], + ) + + for _, leafProof := range scriptTree.LeafMerkleProofs { + ctrlBlock := leafProof.ToControlBlock( + internalKey.PubKey(), + ) + + if testCase.ctrlBlockMutateFunc != nil { + testCase.ctrlBlockMutateFunc(&ctrlBlock) + } + + err := VerifyTaprootLeafCommitment( + &ctrlBlock, schnorr.SerializePubKey(outputKey), + leafProof.TapLeaf.Script, + ) + valid := err == nil + + if valid != testCase.valid { + t.Fatalf("test case mismatch: expected "+ + "valid=%v, got valid=%v", testCase.valid, + valid) + } + } + + // TODO(roasbeef): index correctness + }) + } +} From c1eb15044e76f4ce7618ff71c807920b6727730e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:17:11 -0800 Subject: [PATCH 0638/1056] txscript: implement script path verification In this commit, we use the recently added control block and script tree verification+generation routines to implement full script path verification within the VM. This includes verifying the script reveal commitment, and recursing one layer deeper to execute the revealed witness script as specified by BIP 342. --- txscript/engine.go | 191 +++++++++++++++++++++++++++++++++++-------- txscript/error.go | 158 ++++++++++++++++++++--------------- txscript/standard.go | 6 +- 3 files changed, 256 insertions(+), 99 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 972e639e3b..3c8f207636 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -100,6 +100,20 @@ const ( // ScriptVerifyTaproot defines whether or not to verify a transaction // output using the new taproot validation rules. ScriptVerifyTaproot + + // ScriptVerifyDiscourageUpgradeableWitnessProgram defines whether or + // not to consider any new/unknown taproot leaf versions as + // non-standard. + ScriptVerifyDiscourageUpgradeableTaprootVersion + + // ScriptVerifyDiscourageOpSuccess defines whether or not to consider + // usage of OP_SUCCESS op codes during tapscript execution as + // non-standard. + ScriptVerifyDiscourageOpSuccess + + // ScriptVerifyDiscourageUpgradeablePubkeyType defines if unknown + // public key versions (during tapscript execution) is non-standard. + ScriptVerifyDiscourageUpgradeablePubkeyType ) const ( @@ -147,7 +161,9 @@ type taprootExecutionCtx struct { tapLeafHash chainhash.Hash - sigOpsBudget uint32 + sigOpsBudget int32 + + mustSucceed bool } // sigOpsDelta is both the starting budget for sig ops for tapscript @@ -161,7 +177,7 @@ const sigOpsDelta = 50 func (t *taprootExecutionCtx) tallysigOp() error { t.sigOpsBudget -= sigOpsDelta - if t.sigOpsBudget == 0 { + if t.sigOpsBudget < 0 { return fmt.Errorf("max sig ops exceeded") } @@ -170,7 +186,7 @@ func (t *taprootExecutionCtx) tallysigOp() error { // newTaprootExecutionCtx returns a fresh instance of the taproot execution // context. -func newTaprootExecutionCtx(inputWitnessSize uint32) *taprootExecutionCtx { +func newTaprootExecutionCtx(inputWitnessSize int32) *taprootExecutionCtx { return &taprootExecutionCtx{ codeSepPos: blankCodeSepValue, sigOpsBudget: sigOpsDelta + inputWitnessSize, @@ -424,7 +440,7 @@ func (vm *Engine) executeOpcode(op *opcode, data []byte) error { } // Note that this includes OP_RESERVED which counts as a push operation. - if op.value > OP_16 { + if vm.taprootCtx == nil && op.value > OP_16 { vm.numOps++ if vm.numOps > MaxOpsPerScript { str := fmt.Sprintf("exceeded max operation limit of %d", @@ -586,17 +602,15 @@ func (vm *Engine) verifyWitnessProgram(witness wire.TxWitness) error { // At this point, we know taproot is active, so we'll populate // the taproot execution context. vm.taprootCtx = newTaprootExecutionCtx( - uint32(witness.SerializeSize()), + int32(witness.SerializeSize()), ) // If we can detect the annex, then drop that off the stack, // we'll only need it to compute the sighash later. if isAnnexedWitness(witness) { - // TODO(roasbeef): need the annex stored somewhere? - // * compute annex hash: sha(sizeAnnex || annex) vm.taprootCtx.annex, _ = extractAnnex(witness) - // Snip the annex off the end of the witness stack . + // Snip the annex off the end of the witness stack. witness = witness[:len(witness)-1] } @@ -620,32 +634,137 @@ func (vm *Engine) verifyWitnessProgram(witness wire.TxWitness) error { return err } - case vm.hasFlag(ScriptVerifyDiscourageUpgradeableWitnessProgram): - errStr := fmt.Sprintf("new witness program versions "+ - "invalid: %v", vm.witnessProgram) - return scriptError(ErrDiscourageUpgradableWitnessProgram, errStr) + // TODO(roasbeef): or remove the other items from the stack? + vm.taprootCtx.mustSucceed = true + return nil + // Otherwise, we need to attempt full tapscript leaf + // verification in place. default: - // If we encounter an unknown witness program version and we - // aren't discouraging future unknown witness based soft-forks, - // then we de-activate the segwit behavior within the VM for - // the remainder of execution. - vm.witnessProgram = nil - } + // First, attempt to parse the control block, if this + // isn't formatted properly, then we'll end execution + // right here. + controlBlock, err := ParseControlBlock( + witness[len(witness)-1], + ) + if err != nil { + return err + } - // TODO(roasbeef): other sanity checks here - switch { - case vm.isWitnessVersionActive(BaseSegwitWitnessVersion): - // All elements within the witness stack must not be greater - // than the maximum bytes which are allowed to be pushed onto - // the stack. - for _, witElement := range vm.GetStack() { - if len(witElement) > MaxScriptElementSize { - str := fmt.Sprintf("element size %d exceeds "+ - "max allowed size %d", len(witElement), - MaxScriptElementSize) - return scriptError(ErrElementTooBig, str) + // Now that we know the control block is valid, we'll + // verify the top-level taproot commitment, which + // proves that the specified script was committed to in + // the merkle tree. + witnessScript := witness[len(witness)-2] + err = VerifyTaprootLeafCommitment( + controlBlock, vm.witnessProgram, witnessScript, + ) + if err != nil { + return err + } + + // Now that we know the commitment is valid, we'll + // check to see if OP_SUCCESS op codes are found in the + // script. If so, then we'll return here early as we + // skip proper validation. + if ScriptHasOpSuccess(witnessScript) { + // An op success op code has been found, however if + // the policy flag forbidding them is active, then + // we'll return an error. + if vm.hasFlag(ScriptVerifyDiscourageOpSuccess) { + errStr := fmt.Sprintf("script contains " + + "OP_SUCCESS op code") + return scriptError(ErrDiscourageOpSuccess, errStr) } + + // Otherwise, the script passes scott free. + vm.taprootCtx.mustSucceed = true + return nil + } + + // Before we proceed with normal execution, check the + // leaf version of the script, as if the policy flag is + // active, then we should only allow the base leaf + // version. + if controlBlock.LeafVersion != BaseLeafVersion { + switch { + case vm.hasFlag(ScriptVerifyDiscourageUpgradeableTaprootVersion): + errStr := fmt.Sprintf("tapscript is attempting "+ + "to use version: %v", controlBlock.LeafVersion) + return scriptError( + ErrDiscourageUpgradeableTaprootVersion, errStr, + ) + default: + // If the policy flag isn't active, + // then execution succeeds here as we + // don't know the rules of the future + // leaf versions. + vm.taprootCtx.mustSucceed = true + return nil + } + } + + // Now that we know we don't have any op success + // fields, ensure that the script parses properly. + // + // TODO(roasbeef): combine w/ the above? + err = checkScriptParses(vm.version, witnessScript) + if err != nil { + return err + } + + // Now that we know the script parses, and we have a + // valid leaf version, we'll save the tapscript hash of + // the leaf, as we need that for signature validation + // later. + vm.taprootCtx.tapLeafHash = NewBaseTapLeaf( + witnessScript, + ).TapHash() + + // Otherwise, we'll now "recurse" one level deeper, and + // set the remaining witness (leaving off the annex and + // the witness script) as the execution stack, and + // enter further execution. + vm.scripts = append(vm.scripts, witnessScript) + vm.SetStack(witness[:len(witness)-2]) + } + + case vm.hasFlag(ScriptVerifyDiscourageUpgradeableWitnessProgram): + errStr := fmt.Sprintf("new witness program versions "+ + "invalid: %v", vm.witnessProgram) + + return scriptError(ErrDiscourageUpgradableWitnessProgram, errStr) + default: + // If we encounter an unknown witness program version and we + // aren't discouraging future unknown witness based soft-forks, + // then we de-activate the segwit behavior within the VM for + // the remainder of execution. + vm.witnessProgram = nil + } + + // TODO(roasbeef): other sanity checks here + switch { + + // In addition to the normal script element size limits, taproot also + // enforces a limit on the max _starting_ stack size. + case vm.isWitnessVersionActive(TaprootWitnessVersion): + if vm.dstack.Depth() > MaxStackSize { + str := fmt.Sprintf("tapscript stack size %d > max allowed %d", + vm.dstack.Depth(), MaxStackSize) + return scriptError(ErrStackOverflow, str) + } + + fallthrough + case vm.isWitnessVersionActive(BaseSegwitWitnessVersion): + // All elements within the witness stack must not be greater + // than the maximum bytes which are allowed to be pushed onto + // the stack. + for _, witElement := range vm.GetStack() { + if len(witElement) > MaxScriptElementSize { + str := fmt.Sprintf("element size %d exceeds "+ + "max allowed size %d", len(witElement), + MaxScriptElementSize) + return scriptError(ErrElementTooBig, str) } } @@ -724,6 +843,10 @@ func (vm *Engine) DisasmScript(idx int) (string, error) { // successful, leaving a a true boolean on the stack. An error otherwise, // including if the script has not finished. func (vm *Engine) CheckErrorCondition(finalScript bool) error { + if vm.taprootCtx != nil && vm.taprootCtx.mustSucceed { + return nil + } + // Check execution is actually done by ensuring the script index is after // the final script in the array script. if vm.scriptIdx < len(vm.scripts) { @@ -743,8 +866,8 @@ func (vm *Engine) CheckErrorCondition(finalScript bool) error { // The final script must end with exactly one data stack item when the // verify clean stack flag is set. Otherwise, there must be at least one // data stack item in order to interpret it as a boolean. - if finalScript && vm.hasFlag(ScriptVerifyCleanStack) && - vm.dstack.Depth() != 1 { + cleanStackActive := vm.hasFlag(ScriptVerifyCleanStack) || vm.taprootCtx != nil + if finalScript && cleanStackActive && vm.dstack.Depth() != 1 { str := fmt.Sprintf("stack must contain exactly one item (contains %d)", vm.dstack.Depth()) @@ -1398,7 +1521,9 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags if witProgram != nil { var err error - vm.witnessVersion, vm.witnessProgram, err = ExtractWitnessProgramInfo(witProgram) + vm.witnessVersion, vm.witnessProgram, err = ExtractWitnessProgramInfo( + witProgram, + ) if err != nil { return nil, err } diff --git a/txscript/error.go b/txscript/error.go index f42b893ea4..9170895425 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -343,6 +343,30 @@ const ( // serialized in a compressed format. ErrWitnessPubKeyType + // ---------------------------- + // Failures related to taproot. + // ---------------------------- + + // ErrDiscourageOpSuccess is returned if + // ScriptVerifyDiscourageOpSuccess is active, and a OP_SUCCESS op code + // is encountered during tapscript validation. + ErrDiscourageOpSuccess + + // ErrDiscourageUpgradeableTaprootVersion is returned if + // ScriptVerifyDiscourageUpgradeableTaprootVersion is active and a leaf + // version encountered isn't the base leaf version. + ErrDiscourageUpgradeableTaprootVersion + + // ErrTapscriptCheckMultisig is returned if a script attempts to use + // OP_CHECKMULTISIGVERIFY or OP_CHECKMULTISIG during tapscript + // execution. + ErrTapscriptCheckMultisig + + // ErrDiscourageUpgradeableTaprootVersion is returned if during + // tapscript execution, we encoutner a public key that isn't 0 or 32 + // bytes. + ErrDiscourageUpgradeablePubKeyType + // numErrorCodes is the maximum error code number used in tests. This // entry MUST be the last entry in the enum. numErrorCodes @@ -350,71 +374,75 @@ const ( // Map of ErrorCode values back to their constant names for pretty printing. var errorCodeStrings = map[ErrorCode]string{ - ErrInternal: "ErrInternal", - ErrInvalidFlags: "ErrInvalidFlags", - ErrInvalidIndex: "ErrInvalidIndex", - ErrUnsupportedAddress: "ErrUnsupportedAddress", - ErrNotMultisigScript: "ErrNotMultisigScript", - ErrTooManyRequiredSigs: "ErrTooManyRequiredSigs", - ErrTooMuchNullData: "ErrTooMuchNullData", - ErrUnsupportedScriptVersion: "ErrUnsupportedScriptVersion", - ErrEarlyReturn: "ErrEarlyReturn", - ErrEmptyStack: "ErrEmptyStack", - ErrEvalFalse: "ErrEvalFalse", - ErrScriptUnfinished: "ErrScriptUnfinished", - ErrInvalidProgramCounter: "ErrInvalidProgramCounter", - ErrScriptTooBig: "ErrScriptTooBig", - ErrElementTooBig: "ErrElementTooBig", - ErrTooManyOperations: "ErrTooManyOperations", - ErrStackOverflow: "ErrStackOverflow", - ErrInvalidPubKeyCount: "ErrInvalidPubKeyCount", - ErrInvalidSignatureCount: "ErrInvalidSignatureCount", - ErrNumberTooBig: "ErrNumberTooBig", - ErrVerify: "ErrVerify", - ErrEqualVerify: "ErrEqualVerify", - ErrNumEqualVerify: "ErrNumEqualVerify", - ErrCheckSigVerify: "ErrCheckSigVerify", - ErrCheckMultiSigVerify: "ErrCheckMultiSigVerify", - ErrDisabledOpcode: "ErrDisabledOpcode", - ErrReservedOpcode: "ErrReservedOpcode", - ErrMalformedPush: "ErrMalformedPush", - ErrInvalidStackOperation: "ErrInvalidStackOperation", - ErrUnbalancedConditional: "ErrUnbalancedConditional", - ErrMinimalData: "ErrMinimalData", - ErrInvalidSigHashType: "ErrInvalidSigHashType", - ErrSigTooShort: "ErrSigTooShort", - ErrSigTooLong: "ErrSigTooLong", - ErrSigInvalidSeqID: "ErrSigInvalidSeqID", - ErrSigInvalidDataLen: "ErrSigInvalidDataLen", - ErrSigMissingSTypeID: "ErrSigMissingSTypeID", - ErrSigMissingSLen: "ErrSigMissingSLen", - ErrSigInvalidSLen: "ErrSigInvalidSLen", - ErrSigInvalidRIntID: "ErrSigInvalidRIntID", - ErrSigZeroRLen: "ErrSigZeroRLen", - ErrSigNegativeR: "ErrSigNegativeR", - ErrSigTooMuchRPadding: "ErrSigTooMuchRPadding", - ErrSigInvalidSIntID: "ErrSigInvalidSIntID", - ErrSigZeroSLen: "ErrSigZeroSLen", - ErrSigNegativeS: "ErrSigNegativeS", - ErrSigTooMuchSPadding: "ErrSigTooMuchSPadding", - ErrSigHighS: "ErrSigHighS", - ErrNotPushOnly: "ErrNotPushOnly", - ErrSigNullDummy: "ErrSigNullDummy", - ErrPubKeyType: "ErrPubKeyType", - ErrCleanStack: "ErrCleanStack", - ErrNullFail: "ErrNullFail", - ErrDiscourageUpgradableNOPs: "ErrDiscourageUpgradableNOPs", - ErrNegativeLockTime: "ErrNegativeLockTime", - ErrUnsatisfiedLockTime: "ErrUnsatisfiedLockTime", - ErrWitnessProgramEmpty: "ErrWitnessProgramEmpty", - ErrWitnessProgramMismatch: "ErrWitnessProgramMismatch", - ErrWitnessProgramWrongLength: "ErrWitnessProgramWrongLength", - ErrWitnessMalleated: "ErrWitnessMalleated", - ErrWitnessMalleatedP2SH: "ErrWitnessMalleatedP2SH", - ErrWitnessUnexpected: "ErrWitnessUnexpected", - ErrMinimalIf: "ErrMinimalIf", - ErrWitnessPubKeyType: "ErrWitnessPubKeyType", - ErrDiscourageUpgradableWitnessProgram: "ErrDiscourageUpgradableWitnessProgram", + ErrInternal: "ErrInternal", + ErrInvalidFlags: "ErrInvalidFlags", + ErrInvalidIndex: "ErrInvalidIndex", + ErrUnsupportedAddress: "ErrUnsupportedAddress", + ErrNotMultisigScript: "ErrNotMultisigScript", + ErrTooManyRequiredSigs: "ErrTooManyRequiredSigs", + ErrTooMuchNullData: "ErrTooMuchNullData", + ErrUnsupportedScriptVersion: "ErrUnsupportedScriptVersion", + ErrEarlyReturn: "ErrEarlyReturn", + ErrEmptyStack: "ErrEmptyStack", + ErrEvalFalse: "ErrEvalFalse", + ErrScriptUnfinished: "ErrScriptUnfinished", + ErrInvalidProgramCounter: "ErrInvalidProgramCounter", + ErrScriptTooBig: "ErrScriptTooBig", + ErrElementTooBig: "ErrElementTooBig", + ErrTooManyOperations: "ErrTooManyOperations", + ErrStackOverflow: "ErrStackOverflow", + ErrInvalidPubKeyCount: "ErrInvalidPubKeyCount", + ErrInvalidSignatureCount: "ErrInvalidSignatureCount", + ErrNumberTooBig: "ErrNumberTooBig", + ErrVerify: "ErrVerify", + ErrEqualVerify: "ErrEqualVerify", + ErrNumEqualVerify: "ErrNumEqualVerify", + ErrCheckSigVerify: "ErrCheckSigVerify", + ErrCheckMultiSigVerify: "ErrCheckMultiSigVerify", + ErrDisabledOpcode: "ErrDisabledOpcode", + ErrReservedOpcode: "ErrReservedOpcode", + ErrMalformedPush: "ErrMalformedPush", + ErrInvalidStackOperation: "ErrInvalidStackOperation", + ErrUnbalancedConditional: "ErrUnbalancedConditional", + ErrMinimalData: "ErrMinimalData", + ErrInvalidSigHashType: "ErrInvalidSigHashType", + ErrSigTooShort: "ErrSigTooShort", + ErrSigTooLong: "ErrSigTooLong", + ErrSigInvalidSeqID: "ErrSigInvalidSeqID", + ErrSigInvalidDataLen: "ErrSigInvalidDataLen", + ErrSigMissingSTypeID: "ErrSigMissingSTypeID", + ErrSigMissingSLen: "ErrSigMissingSLen", + ErrSigInvalidSLen: "ErrSigInvalidSLen", + ErrSigInvalidRIntID: "ErrSigInvalidRIntID", + ErrSigZeroRLen: "ErrSigZeroRLen", + ErrSigNegativeR: "ErrSigNegativeR", + ErrSigTooMuchRPadding: "ErrSigTooMuchRPadding", + ErrSigInvalidSIntID: "ErrSigInvalidSIntID", + ErrSigZeroSLen: "ErrSigZeroSLen", + ErrSigNegativeS: "ErrSigNegativeS", + ErrSigTooMuchSPadding: "ErrSigTooMuchSPadding", + ErrSigHighS: "ErrSigHighS", + ErrNotPushOnly: "ErrNotPushOnly", + ErrSigNullDummy: "ErrSigNullDummy", + ErrPubKeyType: "ErrPubKeyType", + ErrCleanStack: "ErrCleanStack", + ErrNullFail: "ErrNullFail", + ErrDiscourageUpgradableNOPs: "ErrDiscourageUpgradableNOPs", + ErrNegativeLockTime: "ErrNegativeLockTime", + ErrUnsatisfiedLockTime: "ErrUnsatisfiedLockTime", + ErrWitnessProgramEmpty: "ErrWitnessProgramEmpty", + ErrWitnessProgramMismatch: "ErrWitnessProgramMismatch", + ErrWitnessProgramWrongLength: "ErrWitnessProgramWrongLength", + ErrWitnessMalleated: "ErrWitnessMalleated", + ErrWitnessMalleatedP2SH: "ErrWitnessMalleatedP2SH", + ErrWitnessUnexpected: "ErrWitnessUnexpected", + ErrMinimalIf: "ErrMinimalIf", + ErrWitnessPubKeyType: "ErrWitnessPubKeyType", + ErrDiscourageUpgradableWitnessProgram: "ErrDiscourageUpgradableWitnessProgram", + ErrDiscourageOpSuccess: "ErrDiscourageOpSuccess", + ErrDiscourageUpgradeableTaprootVersion: "ErrDiscourageUpgradeableTaprootVersion", + ErrTapscriptCheckMultisig: "ErrTapscriptCheckMultisig", + ErrDiscourageUpgradeablePubKeyType: "ErrDiscourageUpgradeablePubKeyType", } // String returns the ErrorCode as a human-readable name. diff --git a/txscript/standard.go b/txscript/standard.go index 53f9f4ebbb..2ad658304b 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -42,7 +42,11 @@ const ( ScriptVerifyWitness | ScriptVerifyDiscourageUpgradeableWitnessProgram | ScriptVerifyMinimalIf | - ScriptVerifyWitnessPubKeyType + ScriptVerifyWitnessPubKeyType | + ScriptVerifyTaproot | + ScriptVerifyDiscourageUpgradeableTaprootVersion | + ScriptVerifyDiscourageOpSuccess | + ScriptVerifyDiscourageUpgradeablePubkeyType ) // ScriptClass is an enumeration for the list of standard types of script. From a7a8ad7d3791f116736866e7dabbd301cd330023 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:21:23 -0800 Subject: [PATCH 0639/1056] txscript: disable OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY for tapscript --- txscript/opcode.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 516fba164b..bb8cb43717 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -2065,6 +2065,14 @@ type parsedSigInfo struct { // Stack transformation: // [... dummy [sig ...] numsigs [pubkey ...] numpubkeys] -> [... bool] func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { + // If we're doing tapscript execution, then this op code is disabled. + if vm.taprootCtx != nil { + str := fmt.Sprintf("OP_CHECKMULTISIG and " + + "OP_CHECKMULTISIGVERIFY are disabled during " + + "tapscript execution") + return scriptError(ErrTapscriptCheckMultisig, str) + } + numKeys, err := vm.dstack.PopInt() if err != nil { return err @@ -2236,7 +2244,9 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { if vm.hashCache != nil { sigHashes = vm.hashCache } else { - sigHashes = NewTxSigHashes(&vm.tx, vm.prevOutFetcher) + sigHashes = NewTxSigHashes( + &vm.tx, vm.prevOutFetcher, + ) } hash, err = calcWitnessSignatureHashRaw(script, sigHashes, hashType, From 3c6be738ed7a2de7e619d81f0d462efbc41a435c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:21:59 -0800 Subject: [PATCH 0640/1056] txscript: always enforce MINIMAL_IF during tapscript execution --- txscript/opcode.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index bb8cb43717..4d775cc818 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -839,15 +839,27 @@ func opcodeNop(op *opcode, data []byte, vm *Engine) error { // the stack will be popped and interpreted as a boolean. func popIfBool(vm *Engine) (bool, error) { // When not in witness execution mode, not executing a v0 witness - // program, or the minimal if flag isn't set pop the top stack item as - // a normal bool. - if !vm.isWitnessVersionActive(0) || !vm.hasFlag(ScriptVerifyMinimalIf) { + // program, or not doing tapscript execution, or the minimal if flag + // isn't set pop the top stack item as a normal bool. + switch { + // Minimal if is always on for taproot execution. + case vm.isWitnessVersionActive(TaprootWitnessVersion): + break + + // If this isn't the base segwit version, then we'll coerce the stack + // element as a bool as normal. + case !vm.isWitnessVersionActive(BaseSegwitWitnessVersion): + fallthrough + + // If the minimal if flag isn't set, then we don't need any extra + // checks here. + case !vm.hasFlag(ScriptVerifyMinimalIf): return vm.dstack.PopBool() } - // At this point, a v0 witness program is being executed and the minimal - // if flag is set, so enforce additional constraints on the top stack - // item. + // At this point, a v0 or v1 witness program is being executed and the + // minimal if flag is set, so enforce additional constraints on the top + // stack item. so, err := vm.dstack.PopByteArray() if err != nil { return false, err From a4beed9f7245d71fd1aaf218fbbe341d6702f903 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:22:54 -0800 Subject: [PATCH 0641/1056] txscript: add new OpcodePosition method to tokenizer to save code sep position We'll need this to properly generate the sighash during tapscript validation later --- txscript/opcode.go | 5 +++++ txscript/tokenizer.go | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 4d775cc818..1a4a5335d4 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1950,6 +1950,11 @@ func opcodeHash256(op *opcode, data []byte, vm *Engine) error { // This opcode does not change the contents of the data stack. func opcodeCodeSeparator(op *opcode, data []byte, vm *Engine) error { vm.lastCodeSep = int(vm.tokenizer.ByteIndex()) + + if vm.taprootCtx != nil { + vm.taprootCtx.codeSepPos = uint32(vm.tokenizer.OpcodePosition()) + } + return nil } diff --git a/txscript/tokenizer.go b/txscript/tokenizer.go index 72e00f07e2..4c7c883a27 100644 --- a/txscript/tokenizer.go +++ b/txscript/tokenizer.go @@ -29,12 +29,13 @@ func init() { // The ByteIndex function may be used to obtain the tokenizer's current offset // into the raw script. type ScriptTokenizer struct { - script []byte - version uint16 - offset int32 - op *opcode - data []byte - err error + script []byte + version uint16 + offset int32 + opcodePos int32 + op *opcode + data []byte + err error } // Done returns true when either all opcodes have been exhausted or a parse @@ -64,6 +65,12 @@ func (t *ScriptTokenizer) Next() bool { return false } + // Increment the op code position each time we attempt to parse the + // next op code. Note that since the starting value is -1 (no op codes + // parsed), by incrementing here, we start at 0, then 1, and so on for + // the other op codes. + t.opcodePos++ + op := &opcodeArrayRef[t.script[t.offset]] switch { // No additional data. Note that some of the opcodes, notably OP_1NEGATE, @@ -152,6 +159,16 @@ func (t *ScriptTokenizer) ByteIndex() int32 { return t.offset } +// OpcodePosition returns the current op code counter. Unlike the ByteIndex +// above (referred to as the program counter or pc at times), this is +// incremented with each node op code, and isn't incremented more than once for +// push datas. +// +// NOTE: If no op codes have been parsed, this returns -1. +func (t *ScriptTokenizer) OpcodePosition() int32 { + return t.opcodePos +} + // Opcode returns the current opcode associated with the tokenizer. func (t *ScriptTokenizer) Opcode() byte { return t.op.value @@ -182,5 +199,11 @@ func MakeScriptTokenizer(scriptVersion uint16, script []byte) ScriptTokenizer { err = scriptError(ErrUnsupportedScriptVersion, str) } - return ScriptTokenizer{version: scriptVersion, script: script, err: err} + return ScriptTokenizer{ + version: scriptVersion, + script: script, + err: err, + // We use a value of negative 1 here so the first op code has a value of 0. + opcodePos: -1, + } } From 3ce6130ee4b5335da700652da696eb22149f3a27 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:27:00 -0800 Subject: [PATCH 0642/1056] txscript: implement OP_CHECKSIG semantics for tapscript validation In this commit, we implement the new checksig semantics as part of tapscript validation. Namely: * OP_CHECKSIGVERIFY no longer pops the OP_TRUE off the stack (TODO(roasbeef): verify)) * the new sig ops semantics are added where each sig deducts 50 from a starting budget of 50+the weight of the witness * NULLFAIL is always enforced, meaning invalid sigs MUST be an empty sig array --- txscript/opcode.go | 57 ++++++++++++++++++++++++++++++++++++++++++---- txscript/script.go | 8 ++++--- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 1a4a5335d4..7475e3dda5 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1986,7 +1986,10 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { // The signature actually needs needs to be longer than this, but at // least 1 byte is needed for the hash type below. The full length is // checked depending on the script flags and upon parsing the signature. - if len(fullSigBytes) < 1 { + // + // This only applies if tapscript verification isn't active, as this + // check is done within the sighash itself. + if vm.taprootCtx == nil && len(fullSigBytes) < 1 { vm.dstack.PushBool(false) return nil } @@ -2024,14 +2027,60 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { vm.dstack.PushBool(false) return nil } + + // Otherwise, this is routine tapscript execution. + case vm.taprootCtx != nil: + // Account for changes in the sig ops budget after this + // execution, but only for non-empty signatures. + if len(fullSigBytes) > 0 { + if err := vm.taprootCtx.tallysigOp(); err != nil { + return err + } + } + + // Empty public keys immeidately cause execution to fail. + if len(pkBytes) == 0 { + return fmt.Errorf("nil pub key") + } + + // If this is tapscript execution, and the signature was + // actually an empty vector, then we push on an empty vector + // and continue execution from ther, but only if the pubkey + // isn't empty. + if len(fullSigBytes) == 0 { + vm.dstack.PushByteArray([]byte{}) + return nil + } + + // If the constructor fails immediately, then it's because + // the public key size is zero, so we'll fail all script + // execution. + sigVerifier, err = newBaseTapscriptSigVerifier( + pkBytes, fullSigBytes, vm, + ) + if err != nil { + return err + } + + default: + // We skip segwit v1 in isolation here, as the v1 rules aren't + // used in script execution (for sig verification) and are only + // part of the top-level key-spend verification which we + // already skipped. + // + // In other words, this path shouldn't ever be reached + // + // TODO(roasbeef): return an error? } - // TODO(roasbeef): verify NULLFAIL semantics as relates to constructors - // above and empty sig vectors valid := sigVerifier.Verify() switch { - case !valid && vm.hasFlag(ScriptVerifyNullFail) && len(fullSigBytes[1:]) > 0: + // For tapscript, and prior execution with null fail active, if the + // signature is invalid, then this MUST be an empty signature. + case !valid && vm.taprootCtx != nil && len(fullSigBytes) != 0: + fallthrough + case !valid && vm.hasFlag(ScriptVerifyNullFail) && len(fullSigBytes) > 0: str := "signature not empty on failed checksig" return scriptError(ErrNullFail, str) } diff --git a/txscript/script.go b/txscript/script.go index aa9645e9b2..602c1fced1 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -474,7 +474,7 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int { } switch witnessVersion { - case 0: + case BaseSegwitWitnessVersion: switch { case len(witnessProgram) == payToWitnessPubKeyHashDataSize: return 1 @@ -484,8 +484,10 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int { witnessScript := witness[len(witness)-1] return countSigOpsV0(witnessScript, true) } - case 1: - // https://github.com/bitcoin/bitcoin/blob/368831371d97a642beb54b5c4eb6eb0fedaa16b4/src/script/interpreter.cpp#L2090 + + // Taproot signature operations don't count towards the block-wide sig + // op limit, instead a distinct weight-based accounting method is used. + case TaprootWitnessVersion: return 0 } From 5f8660e5c37e744fa9f8b9fae7df2a9e0b60c199 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 6 Jan 2022 18:28:11 -0800 Subject: [PATCH 0643/1056] txscript: implement OP_CHECKSIGADD In this commit, we implement OP_CHECKSIGADD which replaces OP_CHECKMULTISIG* in the tapscript execution environment. --- txscript/opcode.go | 84 ++++++++++++++++++++++++++++++++++++++++- txscript/opcode_test.go | 12 ++++-- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 7475e3dda5..9819ee6510 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -227,7 +227,7 @@ const ( OP_NOP8 = 0xb7 // 183 OP_NOP9 = 0xb8 // 184 OP_NOP10 = 0xb9 // 185 - OP_UNKNOWN186 = 0xba // 186 + OP_CHECKSIGADD = 0xba // 186 OP_UNKNOWN187 = 0xbb // 187 OP_UNKNOWN188 = 0xbc // 188 OP_UNKNOWN189 = 0xbd // 189 @@ -501,6 +501,7 @@ var opcodeArray = [256]opcode{ OP_CHECKSIGVERIFY: {OP_CHECKSIGVERIFY, "OP_CHECKSIGVERIFY", 1, opcodeCheckSigVerify}, OP_CHECKMULTISIG: {OP_CHECKMULTISIG, "OP_CHECKMULTISIG", 1, opcodeCheckMultiSig}, OP_CHECKMULTISIGVERIFY: {OP_CHECKMULTISIGVERIFY, "OP_CHECKMULTISIGVERIFY", 1, opcodeCheckMultiSigVerify}, + OP_CHECKSIGADD: {OP_CHECKSIGADD, "OP_CHECKSIGADD", 1, opcodeCheckSigAdd}, // Reserved opcodes. OP_NOP1: {OP_NOP1, "OP_NOP1", 1, opcodeNop}, @@ -513,7 +514,6 @@ var opcodeArray = [256]opcode{ OP_NOP10: {OP_NOP10, "OP_NOP10", 1, opcodeNop}, // Undefined opcodes. - OP_UNKNOWN186: {OP_UNKNOWN186, "OP_UNKNOWN186", 1, opcodeInvalid}, OP_UNKNOWN187: {OP_UNKNOWN187, "OP_UNKNOWN187", 1, opcodeInvalid}, OP_UNKNOWN188: {OP_UNKNOWN188, "OP_UNKNOWN188", 1, opcodeInvalid}, OP_UNKNOWN189: {OP_UNKNOWN189, "OP_UNKNOWN189", 1, opcodeInvalid}, @@ -2102,6 +2102,86 @@ func opcodeCheckSigVerify(op *opcode, data []byte, vm *Engine) error { return err } +// opcodeCheckSigAdd implements the OP_CHECKSIGADD operation defined in BIP +// 342. This is a replacement for OP_CHECKMULTISIGVERIFY and OP_CHECKMULTISIG +// that lends better to batch sig validation, as well as a possible future of +// signature aggregation across inputs. +// +// The op code takes a public key, an integer (N) and a signature, and returns +// N if the signature was the empty vector, and n+1 otherwise. +// +// Stack transformation: [... pubkey n signature] -> [... n | n+1 ] -> [...] +func opcodeCheckSigAdd(op *opcode, data []byte, vm *Engine) error { + // This op code can only be used if tapsript execution is active. + // Before the soft fork, this opcode was marked as an invalid reserved + // op code. + if vm.taprootCtx == nil { + str := fmt.Sprintf("attempt to execute invalid opcode %s", op.name) + return scriptError(ErrReservedOpcode, str) + } + + // Pop the signature, integer n, and public key off the stack. + pubKeyBytes, err := vm.dstack.PopByteArray() + if err != nil { + return err + } + accumulatorInt, err := vm.dstack.PopInt() + if err != nil { + return err + } + sigBytes, err := vm.dstack.PopByteArray() + if err != nil { + return err + } + + // Only non-empty signatures count towards the total tapscript sig op + // limit. + if len(sigBytes) != 0 { + // Account for changes in the sig ops budget after this execution. + if err := vm.taprootCtx.tallysigOp(); err != nil { + return err + } + } + + // Empty public keys immeidately cause execution to fail. + if len(pubKeyBytes) == 0 { + return fmt.Errorf("nil pubkey") + } + + // If the signature is empty, then we'll just push the value N back + // onto the stack and continue from here. + if len(sigBytes) == 0 { + vm.dstack.PushInt(accumulatorInt) + return nil + } + + // Otherwise, we'll attempt to validate the signature as normal. + // + // If the constructor fails immediately, then it's because the public + // key size is zero, so we'll fail all script execution. + sigVerifier, err := newBaseTapscriptSigVerifier( + pubKeyBytes, sigBytes, vm, + ) + if err != nil { + return err + } + + valid := sigVerifier.Verify() + + // If the signature is invalid, this we fail execution, as it should + // have been an empty signature. + if !valid { + str := "signature not empty on failed checksig" + return scriptError(ErrNullFail, str) + } + + // Otherwise, we increment the accumulatorInt by one, and push that + // back onto the stack. + vm.dstack.PushInt(accumulatorInt + 1) + + return nil +} + // parsedSigInfo houses a raw signature along with its parsed form and a flag // for whether or not it has already been parsed. It is used to prevent parsing // the same signature multiple times when verifying a multisig. diff --git a/txscript/opcode_test.go b/txscript/opcode_test.go index 91263c21b1..15c62907aa 100644 --- a/txscript/opcode_test.go +++ b/txscript/opcode_test.go @@ -77,7 +77,7 @@ func TestOpcodeDisasm(t *testing.T) { 0xae: "OP_CHECKMULTISIG", 0xaf: "OP_CHECKMULTISIGVERIFY", 0xfa: "OP_SMALLINTEGER", 0xfb: "OP_PUBKEYS", 0xfd: "OP_PUBKEYHASH", 0xfe: "OP_PUBKEY", - 0xff: "OP_INVALIDOPCODE", + 0xff: "OP_INVALIDOPCODE", 0xba: "OP_CHECKSIGADD", } for opcodeVal, expectedStr := range expectedStrings { var data []byte @@ -123,7 +123,7 @@ func TestOpcodeDisasm(t *testing.T) { } // OP_UNKNOWN#. - case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc: + case opcodeVal >= 0xbb && opcodeVal <= 0xf9 || opcodeVal == 0xfc: expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) } @@ -191,7 +191,13 @@ func TestOpcodeDisasm(t *testing.T) { // OP_UNKNOWN#. case opcodeVal >= 0xba && opcodeVal <= 0xf9 || opcodeVal == 0xfc: - expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) + switch opcodeVal { + // OP_UNKNOWN186 a.k.a 0xba is now OP_CHECKSIGADD. + case 0xba: + expectedStr = "OP_CHECKSIGADD" + default: + expectedStr = "OP_UNKNOWN" + strconv.Itoa(opcodeVal) + } } var buf strings.Builder From 79c314d5035aa8e6e8df19d8284780615dc6da0e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 20 Feb 2022 14:55:32 -0800 Subject: [PATCH 0644/1056] txscript: add taproot JSON success/fail reference tests In this commit, we add a total of 2760 taproot reference tests generated by the bitcoind functional tests located at: https://github.com/bitcoin/bitcoin/blob/master/test/functional/feature_taproot.py. The tests aren't deterministic (fresh private keys are generated), so we time we go to update the set of tests, we'll end up with fresh hashes (the file name is the sha1 of the raw json test) and tests. --- .../003af31dd0b5a50c2723531e8ca22ae8ca6e7089 | 1 + .../005e61a50014d33f7309097490534db3c0dc65fe | 1 + .../007f313a1a53428b7fc9eaf54c5d51be20e10567 | 1 + .../00850c1cc564bd0dcbb02c3398f9fc8e0219a317 | 1 + .../0089a0f18b0647cf2bfae0c93e9ae39b345d1611 | 1 + .../00b6fe5a14ee4fb3bb65e0aa28e70cb57f0cd0b0 | 1 + .../00cd1f1ac746e81ae27bfe1e9a383975d0bba949 | 1 + .../00d07d91c86c11dbbd14f4edf55c1f496ffaf010 | 1 + .../00dc037c98e799a31facfab68fce3187ad7a0f68 | 1 + .../00e2723c3cce5d6fa2b7db987e5fbc1d75297650 | 1 + .../00eb1a2b8aed4a406ee59371fa0a50e6679857c1 | 1 + .../0108a92da87f766ee005ac0bb220f78b50d04101 | 1 + .../010cc78772e75503cf488b6267f5891e1495c962 | 1 + .../014aca010656e76077fe517e999ea589e88307d7 | 1 + .../01686c55b9d9f3d0c2d9dc8c0911de32df21a864 | 1 + .../016e25aa492396c1f2937c07dac87f3bce812041 | 1 + .../017f425514c38506670a6136985cf2f693c1851b | 1 + .../0181b63b032265ff6a54d3acaf33d2efc67028ca | 1 + .../018284c1e780a7aacea0d945603d5f06254c5cfe | 1 + .../01ca217ccf1ea0e39003e90d0d3573454b370bd0 | 1 + .../01cc26fa177761f2440d4f78790adfdcb27c9321 | 1 + .../0224ee3efd6d6c2e6024db65267c008a3786f0b2 | 1 + .../0234f23ded5600eb13895b83e3d3208daa621654 | 1 + .../026745c2e6a71ca361cb3f37fe3f4e9c3029688e | 1 + .../026f12b427239f4351f951644afdf9e483ddc4bd | 1 + .../0274119160b74eb12e8b0ea869012528e5c8c64a | 1 + .../02a2d45e622dec5a4342e4be185659da883e8d6d | 1 + .../02bb3113c2f000ec71e0cac539468d820cfa2df6 | 1 + .../02c77525ae2279633746cc24153272f0cbebb2cf | 1 + .../02d1c1fa4446780154693993cbb3b3357d7dc38f | 1 + .../02f4d455a5e5230510c642f46a00e2819cbd49fa | 1 + .../02fcf2313f765802ff09c238af833842580fe461 | 1 + .../0313e7c2127076391d6fd9696d30081eb2c9bfb5 | 1 + .../0325cc06523d6b80529e7b67ea669a8cacc195a1 | 1 + .../032b54a2e80454a2b7039f32a4974095c2f018b0 | 1 + .../035336c778f096bfe56ccd9c44ca36a275649299 | 1 + .../038d58e7a5bd8cd3c42dbd68c099f5900b90ceef | 1 + .../03ac2fb4ae30f213cec9edbaf2796b086134d050 | 1 + .../03b65143f1009a2a8a2f6b758fd8559f040d207c | 1 + .../03bc1ab1714e0ffffffd3593268beb217c603b54 | 1 + .../03bf93a96878a9f8ab6cdeabb7da6656971299e2 | 1 + .../03ec899fb91c58bbb5676ebce177b0b63fa704a1 | 1 + .../03edb43f652ba7e0ad56e117bab26ed1b3cc0b66 | 1 + .../0401cdbd85422acd1857a2cf6024ba4b7b5d909e | 1 + .../040d05cbd66190be71c513b0ebd00bbc34debe8b | 1 + .../04369027c0cf8f61083f8faeaf5d15a4bba2cb26 | 1 + .../043ee2fa352668d08af2912ea4c7dc868039dd7c | 1 + .../046dee126274f9efbec0b1803cf0483b40e0bc0a | 1 + .../047736248915b6ec7bb882618f4c6428dc10bc32 | 1 + .../0496f56b7283138d77bd26aa97936a80588bc908 | 1 + .../04a0415662e8fe755a1cad7e31e996b0f9553a15 | 1 + .../04a9e5bdcdafa1f723281d72593020692f3b5004 | 1 + .../04bb5c8ad218b2ea6cbabde04b776a727cb804d3 | 1 + .../04c14170bf3650e0dee112ba4b888f2e76fc3b69 | 1 + .../04f498a7f3cfb530edcae02afc0d1476b8fbcd8a | 1 + .../0526255fad6bcad83e0f38f3e175d8b55d0113d3 | 1 + .../0530510aa69fa36a6377468b144a6daefe9e0779 | 1 + .../05645a121a9dee2f1e618d22d9c0e11f1729c008 | 1 + .../05723fdb3ecd4a3d4acc01d8ce541e74f11ba38f | 1 + .../0576b0175f23da9546b0ed7d213c1bdf55941dcd | 1 + .../05a7b91a73da2203e485ff51426532165c688040 | 1 + .../05d3a449ff645092d95ff6fa07d433d341861837 | 1 + .../05e7d1f74a0f0d69935dcee5b60fd0b08ff396cf | 1 + .../05f2dfea38b07d623e2947cc2c7963f25a45e24e | 1 + .../05ff688173b90131ed218e693cd3e0735c88955a | 1 + .../060f27e89600b0edaefb344b00420aa71360fd11 | 1 + .../0621f65ed4f98e0fc3ba2caa915de84ac2773b64 | 1 + .../064cb40080f9955f34713af8c9ccd370c7ce8d39 | 1 + .../064f3862567d3645a67ad42e8f1234919491ef00 | 1 + .../06689eea577fd577cf0ed48baa3396126bb6f1b5 | 1 + .../0672af82ea3c78b3ade4b7424ecf5c00466fba2e | 1 + .../06882dd6d50dc8061c56b887fa16764a4db5cc51 | 1 + .../06aa8b12e6ae5c391fb3d92c4050218d552b6923 | 1 + .../06b7ea9f43da11b479b267aca3bdd7cf6fb9cfa7 | 1 + .../06e74af8b10a6ab9ce11036f2747f8034ec3febf | 1 + .../06f54531f7cc822f36462b303f5eed8313ca07f5 | 1 + .../07249b6446b452a9005766194cb824b77c6ed600 | 1 + .../0725dac7b6c36d404b706902e2a350065ba66fbd | 1 + .../073b21ccb622912fef49f0555d5ed7b6ea85ad7e | 1 + .../07904e76401a888153be57bdc173982a4396aea3 | 1 + .../079662a69dfd16ca9215a4e0c822fc44641e72ed | 1 + .../07991f2bbd7bbe3fad499b0c428f795590321613 | 1 + .../07a56716b603afd041d05639404b37744bc2b83c | 1 + .../07aa3010d9cc23f67f6962a7c18f7dedccd7855b | 1 + .../07ae5671fc31d245f515f5c967b4e7cfed38567b | 1 + .../07b8ee857d10f18474e7471c3c27d10be12c5f25 | 1 + .../07cbbc0e4129794730bb9bb49d334b497f11b422 | 1 + .../07d68512aa206614c478ec869a8b7d4f7c32333b | 1 + .../07ff10e93b7bf06e8da854a647ad08d5bc902326 | 1 + .../08106eb8543994958b201f3ce5f42dbbf19adf37 | 1 + .../081a75fb52ef536975050ff3192f6c516b3b557a | 1 + .../08421b069ef3b27abeb764e8412aa879c8bfb0cd | 1 + .../08630f23c6a755790aea6ed91128183d6ddc8291 | 1 + .../086661b19fe6034d3748295413e2b4d4251157aa | 1 + .../08a0635b26ef56d2f6ddd4c31295a8bbde840584 | 1 + .../08a19ba6422f65b65cacb3f20b5507bca39fffc3 | 1 + .../08b5c0ff184e15e9c21e4949e2382b9a71623d3c | 1 + .../08b74fd5e5bdcfc0a22933abb14c20399138f612 | 1 + .../08cb0cb08cfb93d7ca744dbf018072b119fbc650 | 1 + .../08cefa50635850a5a6caa88ddae4d4e4c5178f8b | 1 + .../0918ed067691e99a0ac65b680c99b8a0bd6d2dc2 | 1 + .../0920b0864e2f856ec01587533e768fdc9f982a59 | 1 + .../092dfb3e8b68e6142fcb0a354c4d02c23428b870 | 1 + .../09342cfa6e3461e698ef1f6aceb83fd4a3ccbf35 | 1 + .../0942d800ed811d505130b0e5cca50e722fc4f19b | 1 + .../095bca4fc65d75681b759e14d34e7a5987625ab4 | 1 + .../097dbe987c217c3d9b230bc0e634a9e3f0bab2fd | 1 + .../09b3e7123f40c4ddb240073a912a440a18168c13 | 1 + .../09c225b7d61512e189a466c46243a4511b6eae8d | 1 + .../09cd349f59ff286840fb04789da01062c5d83ba2 | 1 + .../09d7f478f35e48679ca5a97a08febfa49d510081 | 1 + .../0a3e2dd5f11a2182d7b86b927a600bde565229a8 | 1 + .../0a9a9a6e04b0e55c5a90ca23c2586a07ae1fc542 | 1 + .../0aaeeea67c9e79315c703c56429535fd670ef5aa | 1 + .../0abded429f191b0375a464688f06bd465af7c644 | 1 + .../0abdf3a09f88ee47573f9509a323dfd8af89e021 | 1 + .../0ad139668541c092541da58168e6488a1191ff58 | 1 + .../0b0a37b5c9ef3c034545cbefc3e8de97c8b5ea05 | 1 + .../0b0f9ae5467a2c8d14e86527b264cacbf4871500 | 1 + .../0b37dc29cfcef1377a94a17297a0525504b5a9d2 | 1 + .../0b7236484ffa4dee58a006bc3b9e51c30e5cc903 | 1 + .../0b727481698d5b6e33b991da896215f0527335a6 | 1 + .../0b931370dfff16b9e6d9a7a333e61cabe23290eb | 1 + .../0bc98deaaa9007629b3338d906d73f87abce0b62 | 1 + .../0bf313616424ee4fc95cf71286563567fc87c472 | 1 + .../0bfc8b69a3702ac6986ce61b00e837a148e7d0eb | 1 + .../0c00a8351b02f2185ea30aa4052174b38417e0ff | 1 + .../0c02f78d8dd01b33e94abaa865ee6a9792f4ccfa | 1 + .../0c043c49e6d5aafcf072e6be1be89160111fcb16 | 1 + .../0c10be31ac329baf66d4d083563e6a9c3ab9ee59 | 1 + .../0c12817899b35dadda1aee2d0a376b1e6fca73d8 | 1 + .../0c2099a1366325dfb20d310e00b1c1554e93defd | 1 + .../0c4d9a60206c9ad9b61b6120b3b5495408989e96 | 1 + .../0c6dc14de0b80f72306e015b7560fef8a12f722c | 1 + .../0c860ba9e47e23ac7ceaaa948e710e0253317ad1 | 1 + .../0c90542e3f64cf4c09f66ad39471bbed839d46af | 1 + .../0c91906e6830ed3ad8eba843f2cd7c66205a7981 | 1 + .../0cbaaae8f169bef4c71cd090d475e96cc8277741 | 1 + .../0cfce5f569e35c19633d12676981cda0b47a34b9 | 1 + .../0d1dfc0136b588b721884040ebf5911514ebb74f | 1 + .../0d25d4167a2171b28beda354bc7a6b814d718e10 | 1 + .../0d265e43ba90ce1827ee538563c6a293b0b03ff8 | 1 + .../0d3ce2afc206b93ee7c40177e168a295fc3e5ce0 | 1 + .../0d4d3db873cac71185de9e2fa4462b2f3ba96462 | 1 + .../0d5ecc8d0c063c2641c3a8e7adff9ecb0323914a | 1 + .../0d65edb0c2f57a76df2b15cd2c722b18edffbacc | 1 + .../0d687e26341ba489f3d7be5d0b46f4beacaf8358 | 1 + .../0d6ac2e508ad66fe5e2ceb784535d11ee75cbe2f | 1 + .../0d75732bc24cbac5dc017bb967142c5648d55bfd | 1 + .../0d89c8dca6b7a1af5614348af7dd5ae2f65190bf | 1 + .../0dd2ab05d7639afe71f965b79bd7092a935732e5 | 1 + .../0debebb3108bcd03c6d5ce9c5c2ce1a64f8da172 | 1 + .../0e03e6819458e3a55e6655f8ac2fb5cb9b28406b | 1 + .../0e1d5cb6786009b8f3825aeb3f4c7eecc240bf0b | 1 + .../0e1f79030f3681187ce4b16bf43133d56c470a63 | 1 + .../0e229a80fe4e2619a4b272d19ce5815986d08fa2 | 1 + .../0e27294bb1dafe333a689bcad39dff7fb6f9cddf | 1 + .../0e28329dee72cdf3ca474e54b4eae5fb8c42ce45 | 1 + .../0e292d3b3af29268349fe695e0f7ad74c422612d | 1 + .../0e41c7f53cff3726f8dbca36445f5bb99cc7515f | 1 + .../0e73fd872d8f71896397723287ddf1497ea61297 | 1 + .../0ea17004d718ec4b5b84011a18828cf136f86973 | 1 + .../0ea4e4491ee2abc4ea52e48ba33eeccf62d5f85d | 1 + .../0ea84a4a5eee9c0cfe8bd52347d11c08b97d6640 | 1 + .../0eb26606cb3895e3e7c3160a2acb1dd55cfde903 | 1 + .../0ec71de4446b68520af7b2f5cb5495f2f7d56bbc | 1 + .../0ecc927da181cd3e4cf9d00b158c6acd0700b7c0 | 1 + .../0ef9e684b87a52e1d2ec2b274d91ca104093f268 | 1 + .../0f0de5c345a12934d91427634192d4040e5bd1fe | 1 + .../0f1aee7720bb0ab848210f3e547b18c4431e3651 | 1 + .../0f2ec0ef703ae34c9801d778277b221e6ec19ba7 | 1 + .../0f51e2a5ab57413a930a436edf258d17d6ae7de2 | 1 + .../0f7b105b71e9cb68726584b4fa24c0ebd801c4ca | 1 + .../0fa616a640ec4b881c4c4ea08e1a39f481403fe6 | 1 + .../0fabe142a692b593ed073f5db1ef2aca01dbd689 | 1 + .../1000a469dfca1be2144a6563e3bc8e3f5ceb2448 | 1 + .../1007d21149445ee61da9ad4413d7acefa9ede7e3 | 1 + .../100be162498b413ca391dea2387d07097432e64b | 1 + .../101afec325ccd0ecfd32b22bcb5ddb64cbc1c497 | 1 + .../102f84dec76aa32c7c32a67b8398d3433fd9c124 | 1 + .../10549677366e93a6b247cf85ef6b109794e927a0 | 1 + .../10624dd984bc11b57e154d0125049824624ef4b9 | 1 + .../106f9a1f4925d539eab0171af97bfe996099ad01 | 1 + .../107e2cdcdfabb3aca2ab5aa2fd3c97288ca30c94 | 1 + .../109b57979771e9a623eab0dbd365a6eb604e4d39 | 1 + .../10a884685231a301c2628f0607b449081b250ab5 | 1 + .../10e147455c54d7bb8f4395e8f52666ee498a10a3 | 1 + .../10e2ba2a40c7f4b5bbe26a0ae7a814ef9883672e | 1 + .../10fefd7899096dc27cf05039ac9a172231d52173 | 1 + .../1113b16ac0b3e4b76353eb896e7272061f03ff8c | 1 + .../1131434b4bb6f2acbd59abb881c239975a1116af | 1 + .../117e130d533574c601aab37e70b93bae134a6527 | 1 + .../1184f4a41ef45af98fbb77736bcca10e157c347c | 1 + .../118b63929e90757c8ca1ec818ecf53f8b71c70fb | 1 + .../11b1f9db49bba588d8f418e89843ef901274fe93 | 1 + .../11e26aa15592a14b6f7dc59ed4225b0ceeca2418 | 1 + .../11ef5be6a614ca068f2c89bc602378f8ce71d763 | 1 + .../121e9e0d61998a2f829c791e9f23a065b8ce683d | 1 + .../122e57288341172f17f63e1689fc9a205e9e5905 | 1 + .../1260bed4953f82e80f379c79bc4484db28c58d8a | 1 + .../126e5c88c57ce073bc1e63e4306d21823db4b99a | 1 + .../12bcaf48556b4780abcb73c4f32bd274ea7861bb | 1 + .../12e033c1a8f3298a775b13078a77bc8befe4567c | 1 + .../12e5f4d526a722bc9b8f2af83ae028c8ee6b9027 | 1 + .../12fada550b4d90c67f307a0d563ae38283c008fa | 1 + .../13080e256b05f38789902f0dbbc437401d15a3f2 | 1 + .../1318e44a20cde77432578f5126e255855a0f8104 | 1 + .../131ec09b5ca700e6a035eb50138f6a7f62fe3f91 | 1 + .../1337852e30e2d514c14e8123b84fadb9d4aa882f | 1 + .../136bc03e80bca2dc5f71c4fdf91e7d690eac78e2 | 1 + .../1390c111cc1ca46caab6bdee16d74dd49519fb4f | 1 + .../1395575564b7da66e3b458131eaed79bc605b605 | 1 + .../13c9792e4f626e8f900acfa50cf122a5f5f15030 | 1 + .../13d37de420974d4290a6029f20175feb02e1106e | 1 + .../13d9b1cfc7b7864ec3f85c71a1046df30cc17b62 | 1 + .../13ecc0464cacec7245082422e8f3212d959e0fa9 | 1 + .../14450718a3a9e2266004b863df27746606f071ae | 1 + .../146b0be5a219a70b803fc5f82ded6f34e4cf7a6e | 1 + .../1477a76ad0e64b74908b0f8a89549c7cf7190288 | 1 + .../1493716a3ca7c3194959cd177b8dd531b04b0b9f | 1 + .../149679a6778ca49110eaeac21b33cd449242eb91 | 1 + .../149bceae555709818ddc8eb34d3cf4b508780b88 | 1 + .../14a9e9b7200758410bd419f2b0954ec253e17889 | 1 + .../14b46e9b808aa20b426e21803aebd6efffef133f | 1 + .../14b583f6a2bb67ac548a6daf674748880c14916c | 1 + .../14bac90ea6a6692cf7202b96a1c18e47f81a055a | 1 + .../14d0d7bc3443d31977bc6035b1a9bce2c6dc9114 | 1 + .../14d9a8a4291206e2c4d73120dc485bd077e5f66d | 1 + .../14ffecf99f50d1adde6ff14120965c878f744781 | 1 + .../15032320c16e26b0069cf1571846247d073f2efe | 1 + .../150b2d12becd542c0352fdc80bbd85c2901d8228 | 1 + .../152491c8478252c98640ae41d5813cd6cc4800a4 | 1 + .../1532d9cb1517dd25a5c8a93eb64d3962a52cf4cd | 1 + .../154147c0c82e41a7cfdb7b8295df125020cd7113 | 1 + .../154b30ae55351cbd129d9b1b6a6311572840bb26 | 1 + .../15541041a721e558c8cfa7f4ee5f4d09fa6c9065 | 1 + .../157183c1796c9575b6c576a29c98f58fbd42356c | 1 + .../1571fe984911dc73398ce28defbf71e715958a81 | 1 + .../157aebc161b66c638243c0a814262c48979b21de | 1 + .../15b38d795c9bb9ef573b4d2b1ec4af8fc0cd8fb6 | 1 + .../15bed2762ca16694fce3754fdcb0fe404484b18c | 1 + .../15d389f49e1f412ed725252d3ee81230a2e81cd0 | 1 + .../15fcafcc7469d59709774013df0fd9633e820008 | 1 + .../16128f27ae921b87284e0eab75845884e009c865 | 1 + .../1630122f5bef1592ca6b6280297bd620d8ce0ab9 | 1 + .../164113b42e586e2e8ce7bb6fccef9f52a5136708 | 1 + .../164178c636e1e1ccfbe67f53e9209ff1c0e8584a | 1 + .../16431b60ce2185dc8a3e19f1b9325a1078131515 | 1 + .../1658b5c8f7c6d3672d694462a7f53ad3f3596d38 | 1 + .../166cd55c33178000f9e3e3b366ace5266964a5c3 | 1 + .../167a4033a1f4c30b87898758c3868c1025df1694 | 1 + .../167fe32905b764460a1199e4a4ab3d84ef186e2e | 1 + .../1680d648bb0d496b0b5cdc71bd31f42d092b5e31 | 1 + .../168c2988106ea01a8121eba649b024715de5122f | 1 + .../16acfa58909fa72c2eecfaacc8866e7dd1f42fda | 1 + .../16b2bf568fa5aa6e4b5de39fd290f6de49b091ec | 1 + .../16c6bf5c5a6caf8746580f9e01ec4e218a4c0e39 | 1 + .../16ecdda3d618db946d6033f96c780764642e0471 | 1 + .../16f6f25ce07eadca0f3c82818b8910b5006b6aa5 | 1 + .../1715e26f824103c322e360c6d3c237781724ca4e | 1 + .../172062063b7ae63dcffacdd6b98414054d06633e | 1 + .../172b85f2524cbd3f0ca1a41380566b1648c8c405 | 1 + .../172ff5cf4d0d01f9ac160be767a1b233dea05ffa | 1 + .../17405fca2ae8f08cec8849c6a750217abef9ff89 | 1 + .../177f3355a5b98fe40607bd5da8383d7129c515d5 | 1 + .../177f56a1fdc5cc3198a785f6f5e7a55d8c324f16 | 1 + .../179b29b5e6ade731ba119866f25b6743232bd3ec | 1 + .../17b2c3c5c8f5c6d4e3b517021c8e26c982fc552f | 1 + .../17cd80eebaac8182716c6996ad037efac35af699 | 1 + .../17fccd13627419da75dd075f405d0c40a09c652d | 1 + .../184dbb048070da2a1db945f29853600246189da2 | 1 + .../186d4e3b056dbde38d01af9a2095f2b550b930bb | 1 + .../1870a7b0cbdbdbcb7e9f1d248928fe0dca885fbe | 1 + .../1878d0c6c90056867949699c2702dab1671a5739 | 1 + .../187dc420ad18b5fb75f0f40dcfa22e824b23bbd4 | 1 + .../18822bf70764f3c01f808cd81031bdaa811edcaa | 1 + .../189034044dacfcbaac5a98bbd0a33a369683d2d8 | 1 + .../1891c772f3ce8c760b0cf1b52164fe1d2e4ce605 | 1 + .../1894c4ad4a51725e14a4b3ca4124be935f442f98 | 1 + .../1899c6c029807a2b6fb9c8709343768c03f3405b | 1 + .../18ae04d1c49da35415f8e30e1757321ada62e83c | 1 + .../18cd769c18f505e8bc05856ed71e114b5bd9a022 | 1 + .../19056ae532d1819a4355eff6310ab655a5030df5 | 1 + .../190cfc23dd00d10a83315e6bc368d40445cd322f | 1 + .../190dca39f195f8973c60e414fa6fa6aacd3d9290 | 1 + .../191602968fa2af7edef6e40a0c4e4b9e4ef4cd75 | 1 + .../194da7e8add6b9a1ecf41a75f040b4611f016a09 | 1 + .../1969e36c75fe223b6de50a2e92c6ce56dd4915a3 | 1 + .../1970570c77db050bc51d853165e59487dd05c1a7 | 1 + .../197071c336e5f96eeccaa2d253d5c00e0ac7febc | 1 + .../197a3fa4a03436efcb2a86e1f8cbb45de1371615 | 1 + .../19928329d12601dfd9c4a12541e9799fefb5439e | 1 + .../19a982b7ff350572fab07d8c7397bd3e8f2cc04b | 1 + .../19b94494f911d6c8dffa42a0570e686d8d385d0e | 1 + .../19ce749d29e4620af1b8364a70b233842f7e9d56 | 1 + .../1a199a3cd2f3a67e25e36bd4711b535ae3d24e31 | 1 + .../1a3a8c18a8e82421d33989ed4d05f5485999b0db | 1 + .../1a83bda864530d8086caf59fe1272ad5768d34c7 | 1 + .../1a9368b5d21e42219df4751485b7f522507fdefa | 1 + .../1ab6d3c20509931b1abf61a6b45d8069679b66fe | 1 + .../1af45f5f9b4d38fa9b4e939f3e3622bcdf2d29d6 | 1 + .../1afbe3f769c38b8e8b6210ef4c1e57bc6cfd7f8d | 1 + .../1b13c8bd9a345bdcf71eaa1078ef4cb752b3da96 | 1 + .../1b2543854748d5b37077ed3e53a36309f5330a50 | 1 + .../1b3c874362224cdb658666354aa6fb9efff9b371 | 1 + .../1b4bc136aef0b80666d85ce3d93b7996d0ce7ab5 | 1 + .../1b5a41cda693f9d63f77b9b053dbac3106aea789 | 1 + .../1b68c33f2aa26138257e984d7c57524a609332e4 | 1 + .../1b79cd4b2e7a4b311359e56e468853036d3681d5 | 1 + .../1b8f51ede6850bb667b5fd80d78e02cd4832d753 | 1 + .../1bbde099bad78eb5021b57eaf4e9fecec63162ce | 1 + .../1bc3e95ef1ef57164dee0340314916513b071491 | 1 + .../1bc5747eb674dd470ce9e8f236e8c461bd9f5491 | 1 + .../1bc76532e1949261ee2079d9ce81e5bd2ee2c56a | 1 + .../1bfe6046e6cdc344b877ad37196692f2724dfb96 | 1 + .../1c0b90070d5af0e0da662d27418affd7255bb328 | 1 + .../1c1b10df48009861e679c78f57233fcbab1c9c74 | 1 + .../1c1c68f02884233862b5ace3f063b648ef1a8f5b | 1 + .../1c2a334bb5693def73177ba056d467309d1a592a | 1 + .../1c34962adc291e2c8bf6dae66b8fb9c765b86439 | 1 + .../1c385e281c4e1f86fe4c3b41f133fe0f1ad20791 | 1 + .../1c561097325c97828153532b8c7b95b14e46dff4 | 1 + .../1c7cf3e3c8d41ca4743e00d88ec0434c6f31d4c9 | 1 + .../1c903f96be3cd8956476fb915624fb89666a187c | 1 + .../1c929a0b875b383b7f3db0d168424cf2ba6d3cd5 | 1 + .../1c974326af0bc49a9f389a9c91eda58bdb47ef17 | 1 + .../1caae5c5cd8d5b5cbaed34c3bffbfa19df6aa109 | 1 + .../1cb39f47f10b248d485afd4c83fa450fe4dcf928 | 1 + .../1cc704edb370c2b52aa731bd30ea881ee0b2eb53 | 1 + .../1cf397672140f803d1c48c64b7a9b55ed395d983 | 1 + .../1d396736b3bc9203fa55467a0775f7a058a44b05 | 1 + .../1d4be0ac5b202d439cadb143602ea3459a3eea33 | 1 + .../1d66bb4f8ee00895bb9533eb0329de6d26b4e395 | 1 + .../1d6b45d432e1a9f7bcf2692c87fd3865d9e96451 | 1 + .../1d6c3731bc1125e0c52a0356e80d994f891c5e9c | 1 + .../1d83703eed5baa3599b3562c9ea6f395f0ecacbd | 1 + .../1da56d6e6d60e92c14472e47b665a85be68598f1 | 1 + .../1dd5926d9df81e85da3075d37f0702718c88900e | 1 + .../1ddf875ca22b308639d7b1cab6ee74ea77bc6bce | 1 + .../1de45c6257377171ec1383ff685db7ce8e13d8c4 | 1 + .../1de7bbede303fc60efdde225de97fe6e4cfb88ef | 1 + .../1df8c615c5b7d5080d1019801137bdc97c72d639 | 1 + .../1e2b8ba68f2655f0f5159ba8ee446f920bd6f384 | 1 + .../1e2f14f392e271b5a594679f83b4847d83b8109a | 1 + .../1e2fa5e498506cf0c5adee563fba8cdb0900cb86 | 1 + .../1e32a9cc12b73e8a61aaf4c846d1cd0ffa78bf93 | 1 + .../1e5a2d83584c4f1ccd8746aa4cc87f3b5c520e63 | 1 + .../1e754a40c050fe3c356b0e253ed22633f2c5edb5 | 1 + .../1e841722ec03b5be4c1001e90d8019bf9e01d892 | 1 + .../1ea62bf92cf8078007e5cd279d0ac921980c1395 | 1 + .../1ec26ee9e524029b8cf64e318125007a12c085d1 | 1 + .../1eed48f62357914c0650cba567a06e37071db51e | 1 + .../1f06a021e51a7104e4b8be0ce9c51232c8fd6c77 | 1 + .../1f21715d338b4550c3e7e74321d26de8853626f0 | 1 + .../1f33b328ec921a865dddc299139161f27b477147 | 1 + .../1f59389661d72064b929ee2bac0a3f2782c99fb1 | 1 + .../1f7d7d9cf1ac6252c762a06bdb35e619ce77741d | 1 + .../1fa141a9352d1d89d10a4d09abf044c9506a4bac | 1 + .../1fa4445b8704e72f4df267622d688919d1c6a44e | 1 + .../1fbfc728d51680fcfeadde2a9e6fa7d1ac3996ec | 1 + .../1fcd778862db2069278171a2ee940bf756a2bdab | 1 + .../1fcd7eddbae73818ef08042df1c443c53fab0c49 | 1 + .../1fd0cbef8f091c8edefa214a32625302e2f3a6d8 | 1 + .../1fe16cf825c0f639b3abd120fa85f9a344d3e514 | 1 + .../1fe6f643a391a7f73e3577d1f4e57935064e1c84 | 1 + .../1fe7d8f0f7839c475eb9dbd113d0ac120b1301fa | 1 + .../1ff8cc1006122254a00dc42299f828366e65b691 | 1 + .../202c9cc0aac7d6c5172f0818c8d0d3405649d29b | 1 + .../20372276860410d8622c60d5ec72e5716e313dfc | 1 + .../203cda36559f2e342d3921d1f1f5ab05e330fe7f | 1 + .../2068fcad81b42ac14a337456c1c0e850bc5567e8 | 1 + .../2071f151f52b689e1e3c9f2b0372a3c1ca4c6dc9 | 1 + .../2089f610f91855cc26e8760f3910284181dc1b86 | 1 + .../209d75465a4314536f2bbabf6ada3622bec989d5 | 1 + .../20cd1af7438c223f49d33ed3693631c63f6c3234 | 1 + .../21227867cfe4806f692be272ca5b865dcecc1894 | 1 + .../213cd49c2b13fe3ee6d2220f5f96b63c748d1add | 1 + .../2152488b729a3937e9f4e83bbefbb36d961013ca | 1 + .../215ddb94c508c11099b9268dbf4ce0d7f7d18977 | 1 + .../21a38194825eb39a4a0ae99128be4409c90d420d | 1 + .../21a967d5a754fe4909db382de1d7debbb040d069 | 1 + .../21b086a0fcb5394bca5e13730e9801a167031fd3 | 1 + .../21b915be35d2383f8baacd2d513b5cdd06836ebd | 1 + .../21c64c51dc34976712f8356ed25d28cb2506a3bd | 1 + .../21cd99bcb03828e0395286a09e866684d6c569f0 | 1 + .../21f06e9520e734ab7974353357c55b81e5ee87a9 | 1 + .../22089449f264bdccac5901669554a20c01c7632d | 1 + .../223d492bc034d65fae5c76008697dc6455711a0b | 1 + .../227dc7dc4b5fedba0f90b82d69d0f8f6785c49f3 | 1 + .../228fadb4fab77130e6a42578be8c100758962a74 | 1 + .../229254c58edf03c88b0434f339de04542e82f168 | 1 + .../229a032ed00e20e08e27892cc81b53b28e1d245d | 1 + .../22a01d7a209edd8694bd9edb1c95de74dbed6fc4 | 1 + .../22b9de25667093d760c9e17c5477dead3043b33e | 1 + .../23157f2fc305799762478817c79fe62d896edd22 | 1 + .../2334138f3c633d853dbab847307d9950c227ac09 | 1 + .../2341c37b333e27f887345a539b3a46aa15fe6738 | 1 + .../234eb0340c07ea7d86dcfac62e971eae6dbc359d | 1 + .../2363727c5d55ff4d6eaaf41f33d420d94aa0259e | 1 + .../2364ebc1025f0c764130435a3da1d5febf1ac0a5 | 1 + .../23873275d271cfb7c8271e4058054ab8102b18bd | 1 + .../23ce0a835c3fef13acabbe51379451af1bad4377 | 1 + .../23ee2abacaf9004b59fb4b0c0bf4fb0518c0b719 | 1 + .../24189b1ed398f5834d414ec0517d0e4ec49e5123 | 1 + .../2447d402d9160d103faa8fce8f16b8201a516a4c | 1 + .../244d1fe0151e8979539727b36d9efd4236889b85 | 1 + .../24b9d083b99a1fda505df14b9b98cadbf34618a3 | 1 + .../24bbb3bb32575090a29c31c6d367e46898dc602a | 1 + .../24d0fbfa8bd2c68fd6ee1e4839bb0d5bb73ef21a | 1 + .../24e2153d05b71ded99689e64661aa90af06300e2 | 1 + .../24f5f696fe56cb9b25c9d12a9606b6d6f531d6db | 1 + .../24f8bbbbf4e945080301e930844b08d263783100 | 1 + .../250db3e160a3b1e5fb27d5880463b82d2da450a9 | 1 + .../253542d32b85965ac57232e3741542be2aa8d091 | 1 + .../25452194c45988fdb9442f977481e8fb95b4ad75 | 1 + .../2546c1139a14d6b2b3d6b9918c96de6e589fbf07 | 1 + .../255e0819d8c9639459a4e49579fbd923cdf9240e | 1 + .../25608654bdece6361519480d9115afff3312cb31 | 1 + .../25bdf9d085288589dbb23f1fc7d98f7783cb09fe | 1 + .../25e7910e53d821321fab3c8bb9db847f37fff616 | 1 + .../25f13dc685e40d3fb22819356cbba4a5a6789e15 | 1 + .../25fd25289846f102771af05c1445e63acb583b93 | 1 + .../2619632226257817c56eb288a9d2075e56dd0e34 | 1 + .../26300a1704f502625832730a36d0088f21a46e2f | 1 + .../265d0640e2752abb03fbe0a1b150f575f8469aa5 | 1 + .../2669c9c65bf3af74d4482204c70ea69545d8babf | 1 + .../266c1691a90b2a342849d25e3704659308c45951 | 1 + .../2670c894e879a8499f50e08ae018e501b6693152 | 1 + .../2692015cba943bdfa1b324204d53284234754d15 | 1 + .../26fbe1c5bd294a3fc35af2e36f46c951b25e5cc3 | 1 + .../2721ca2fc08ca7ae38cc809a3799bf618ce5a75d | 1 + .../2756fd453011fa7471613114061631b066029dc5 | 1 + .../278eb959a30cf3ec8163a007eb3f89ef107765ea | 1 + .../27ab4c447f840d27a13d145eb27c80db511a400a | 1 + .../27aff0ad61d128505e22df766c0492e316fbd9a9 | 1 + .../27b9b3e3bde2958e048cee68f2493d41648987d3 | 1 + .../27be24f0f9eb749b51dc6e83c6ab5c8637349a25 | 1 + .../27d37797fa4bb9c3bba68f9967eab892fec70642 | 1 + .../27f1dbe3a65014c59ae266af3346177a5a57d4e5 | 1 + .../2807a46ba9b453c2f9e4af2406b26ed38137b216 | 1 + .../280d6a9607ad78d3eb40f04e5b5a76c6f8eb4c02 | 1 + .../28259bbbf78c881c7400ac4602722df51776ffe0 | 1 + .../284cac89d0553dfdc596ce4bfc4251fd2115cb15 | 1 + .../2872201824aca727042b22cae049102582283dd9 | 1 + .../288e61a59fe0099d03730d5c9d59712f743123a2 | 1 + .../28a21b4f4afeb9c978b1290c620548f1f33e127e | 1 + .../28b1a2ce5cf374a3ce64a6c7853fdbb6a15d1e25 | 1 + .../28f223ee6f9c2562b1e382ea899bc7f88e63490e | 1 + .../28f4e044d59009036250527f061daea52c6b5917 | 1 + .../290325a794a4307e35ab570d847c9854f6d63001 | 1 + .../290a1cf15d24d80b8dba0ba4397f5a7eb13382d0 | 1 + .../29186f53cff8c33b62ccd1cec92b4c6b02c8c2c8 | 1 + .../29306f00a438f213a01ebd7a7b0d04ae25d239ad | 1 + .../297a3281b6d5be24c14d7ff51f2fbfe46ed86f1a | 1 + .../297a666c7fc982a83775114d7c6821fb42031e06 | 1 + .../299581f978295f5b97afd9102abe9746f3633e76 | 1 + .../29cceb8deed87738d060e1bd5338ab0536f8d2a6 | 1 + .../29ce41699e783cf1ab6b5b84bcc1f8da679ce8cd | 1 + .../29d289d23bf6e34dbfac501041222a1978cc95d2 | 1 + .../29dc54df002663eb3874c3fb7d3952e70b1d1779 | 1 + .../29dd1cab8fbe87bf2eba3c671a6054c32e47ee9f | 1 + .../29ec9ea0cab2025b952a31c864a85546c8a8f032 | 1 + .../29ef22549cd23bb217da411a3ca72d83c71150d6 | 1 + .../29f6acfc391f9db2fecb96ea0a708da396ed202e | 1 + .../2a46178ff8d5794433a794e9fe86b9b5fc268cc7 | 1 + .../2a479685fd7da722bb6722ebc37d68cccb881ee6 | 1 + .../2a4e458a761d418129aa4d22bbbd076927fcef77 | 1 + .../2a4e61567a20b2e90af1a0fb476b1ba0154b0a8c | 1 + .../2a7da9157e1527a2190bce26d0a1303d7f239f9f | 1 + .../2aa0596f17f2698bdfd51894a7dc1e1241cd3ae9 | 1 + .../2aa48f72c81f73267919baef97d2c186ffc36882 | 1 + .../2aa72eaeb2dee91742e3412f9e1ec464ecc22161 | 1 + .../2ab67ca0e8401c63810a011ea1b9b40ef8573922 | 1 + .../2ae84cabbb3a18b00167af69886696809a07a86a | 1 + .../2aef8c06dd7c0aa09e6494194a3b812e4b7b2221 | 1 + .../2b1075a4c09b4d3aa3be48cb1ce2571ab06a86a7 | 1 + .../2b168b93f7f916976567d85cf8e7ca0d6dbbf32e | 1 + .../2b229e9febea1749971fa08007b52b574b3046fb | 1 + .../2b4be33fed42ff17f8c6910629b0e2183d109eb9 | 1 + .../2b609a197a87b5e2d1507c9acbaf2e2ab79ce53a | 1 + .../2b9f2b2856d6b4e70d3b3d8e2d4ffcc6048847d9 | 1 + .../2ba9b396adf10109648ab2f9856ca66b6fc5b688 | 1 + .../2baded8ac492d5bbd1dcece9f3d4a2f0458c778d | 1 + .../2bde7ad09804a986048db6aa7983bf552f327e9d | 1 + .../2be1d596003c42e91c2a03626c93ce8259dc64ad | 1 + .../2bed09f85647ccc7b26bbdedb9cbf18167240799 | 1 + .../2c2132ba18413a6ac05a486fd72669aa4293e784 | 1 + .../2c24b83fa75f9fc91269d9be43a5c14f9a0c8adb | 1 + .../2c2615f5ff25527bb1609bacc940eda0c32b8d28 | 1 + .../2c2686017a35729961e5b4064e6ea9b58c073505 | 1 + .../2c28303252e327e51e1e99036e9c4fcc97b10d8e | 1 + .../2c3a119d1d9da7d4fe68883d95e8f11060a9def5 | 1 + .../2c3a775a5deae4555f3af3537c8a4195c6e5354f | 1 + .../2c62f7a3d90b30d6f1b1804f6bf0a916d3305efc | 1 + .../2c67e0be52a7389f103f44944fe8d8913c973b48 | 1 + .../2c7c5497a7e7f81979773204f099b9f23323698e | 1 + .../2cc2506d179d284634729bf9fbd8c05239f90ca9 | 1 + .../2ccd61243d6bba96a68b774617b9d76c97662ff0 | 1 + .../2cd0311c121154bc8385767e5893c92ee5aa2c05 | 1 + .../2d240420d7f8e429cb31120c7bf532805423084e | 1 + .../2d2a878308fd10775f477107b478ca6993799763 | 1 + .../2d50c7d765d0137b5bc9bd78ac8e39437d22fc0f | 1 + .../2d562228e60c1a1e62b21379cc97a7cf96852b48 | 1 + .../2dafca8d1802bbb6ce3ae1196aa647ee3c9e418e | 1 + .../2db945824c150b91aa78265f9e3701bd991fcf10 | 1 + .../2dc10a9c76952430b8601993c330b88bd0e19cb0 | 1 + .../2dc5b1536be7b443c27e763739595c42dc34998e | 1 + .../2dc9f8f8cf217ccac41228917cb739aee23f3b55 | 1 + .../2dcae1af8317442bc492bd0899984f32bf30396d | 1 + .../2dd9b9584d97aeda14030c0cb94034e5a64e1e33 | 1 + .../2de7782cb97bcd10b69053268684420a0022efd6 | 1 + .../2df7793cf7520895ea4121850c34c16bd1874c22 | 1 + .../2e15993224f1d73378824cbd1780f6d25e85740a | 1 + .../2e2b8acfc93c65c04508d0730229d6beb1760346 | 1 + .../2e4630df1ac360494322a4300b3a916bf4a7aa42 | 1 + .../2e9a37abf29713e5bf564831df0206b134ed9e23 | 1 + .../2ecab25cfb72ae137a881589719a53343a030263 | 1 + .../2eccff6ea763376046948b3876b0d9b3e8b28c87 | 1 + .../2ef7e082ae22ffb03fec01772b442b4b8d19cf06 | 1 + .../2f1b30aed18276568d11bfeb997aac3246d57017 | 1 + .../2f63727a65eb7f7437ab5c39d3f16671518719e6 | 1 + .../2f6a3e29b8be29ea5949fb1b5a71679b5cadc8d8 | 1 + .../2f718ebe5d9460ba98f7815e59bfffe1cd1f3bc6 | 1 + .../2f92c5daf5b1fc8c65563916bd77ad58dc8ffdab | 1 + .../2fc6756b64916b520df4a5d7eed9bc7c1ee85753 | 1 + .../2fe9ee314e024619b228c81cae27f4bd50141a36 | 1 + .../30060e7ffc388552b8bae73eb28705b637f7685a | 1 + .../3012845a3aa7dc757cc4778e5334769c9239ab60 | 1 + .../3015e994a3e16567397bea00a92ff97eb53971e6 | 1 + .../3031aef9ccb0cb566246e72e7f976a7cf00b9898 | 1 + .../305b7d52e8b2e5b62f366d1fe9aca1b4c31a2e51 | 1 + .../30733f314d77a04fcfb55b009f72a5a1a94cc1e5 | 1 + .../312a2eaf5a3bbccf69b97e292f665b53846038f5 | 1 + .../3177278ccbc91f49567f80c0b575882edaf4556b | 1 + .../31a7241822ef819833b51d86a78d83bbb4d58136 | 1 + .../31b4933ee39bc4133c6a36b1e309775c87a96c23 | 1 + .../31bf684d25c7125e85ce524a607eb2a52cb7bdca | 1 + .../31c15818563bf9247178dcf6aa28b033af2bb447 | 1 + .../31c6f3973f706c7761a06718934fbee33a007e9d | 1 + .../31c88595514658ef1b8ff73277244b8f007c505d | 1 + .../31d4c861644fc9edae1f7e2e4f31aa06c7517889 | 1 + .../31f076334b0a05c6d42d3ee64880af4288a1a071 | 1 + .../31f2c4c02978ae42e16425ad8313162bbbba6fc1 | 1 + .../322e55f03866ad2580881660af953e8169abf66a | 1 + .../32465695f8a85d30402f9b194bdf25dd6e21729d | 1 + .../3296dbebd697c68468c1215ff252b1da046d3d4c | 1 + .../32aba46093e0c1405d3a8229f68cefd6de6d9767 | 1 + .../32abfd2efb454436ddc75cd07a406d88aabceb2a | 1 + .../32ba176293211377a9ca30f7b1742a3102758b7a | 1 + .../32bcf37b6b3d15680600c81db467e1dfff6ce375 | 1 + .../333dafc1d96971e2ccab51c8ee0d9e479decf78b | 1 + .../334e3a237339fce576119749a9aa81f3d65211cd | 1 + .../3352986afb9bc33fc67eaf72f47be64e3c6ccba3 | 1 + .../335b7a860725ca4f2c467a8b034060d0ce6b3bb4 | 1 + .../33848da9a02cc62be9f5a84c5ce6e33bb6aa8a29 | 1 + .../33aa1588445e9cbbedd1d4a629780bcc8b4a8e9d | 1 + .../33aa91e75b0cc39daae8eb7a1f0889075a667617 | 1 + .../33d0d39d6ce6ced2a0a8dc5d8c47e5f5098d7aaf | 1 + .../33efade4e6970da9cea78a726935e5443e0d1ba3 | 1 + .../33fe1028443f16cce6d9858c8501dfb0a7ae5816 | 1 + .../33ff2ff9d9aabf2865009fc3701058f954184c4a | 1 + .../3400d35bd94547fb613f1aa5cd2073fdca146533 | 1 + .../34038f296d87d228ac46a39bb072cc03e4e585bb | 1 + .../34264b99b16c56793e013d7d2ac3dc83c0c07da6 | 1 + .../342a92cea02c320154d0894d36811870581b660e | 1 + .../346b40c03454e4740323b5b0422908722f9a4ed8 | 1 + .../348d5c1f7c9f5084425a506f649c65b2f31946a0 | 1 + .../349341420dbe9b22120760aa5b91a9099c7cdcea | 1 + .../349bf68e15d8f14b4a471b7ab402784c1077db21 | 1 + .../349dc9e7f879b45a530ea9ac4a5ee92a83b80b64 | 1 + .../34dee51305402e7e6b502025f00f29abbde3cb18 | 1 + .../34e0f433a921b809a71c9924e9c0956dc34bc220 | 1 + .../34ebf584d708a418710a1466a3dbc67b82146196 | 1 + .../34ed3c4ed5af89953d2e81d21f7c1e45d2c7dc87 | 1 + .../34fe51570c93ab7b56e8955a00795a7af3eb88c3 | 1 + .../350219ab2d9d1993c2e0ad903f92eaaf6318f133 | 1 + .../351979da8be9a1fded3861db5068a083d50516e7 | 1 + .../35210e4f9eb6f063e680746037b199244fe0997c | 1 + .../3569acb6b68f7aed0054e44b1fa854e2ef33b96d | 1 + .../3572c1cebe263656185dea9403422e9884954499 | 1 + .../3574aa7865915325c364ab1364ae532d35ec2952 | 1 + .../357c3aca3897a104f6b209ff00a90eb8f93c11e9 | 1 + .../357f1e298d27372ed2fdb360e6ecf4b4f93bf38f | 1 + .../3585f3da19dc73f07d513f4d5e06b3af35381aab | 1 + .../35995d78575bb81724c123126ae84f04c1ef1324 | 1 + .../36107f7e7692414cd4ae5e7ee06a1e46821b107a | 1 + .../361314e0baab060ff8fb2888efad4f841ee2e65d | 1 + .../361c2bf607441dd9ae1d9e592d08aff1c4423aec | 1 + .../361e67ace54dd8058e82517e87d5a294ff0e2430 | 1 + .../36225523764ce0fcf4a54ecc157c7a9ee0ca5e1c | 1 + .../363516e81c7327e6e8535e74da1cf78a4a939bf2 | 1 + .../363d3439b183bb0f2c6a0d1238057e9beb398f18 | 1 + .../36415fab25c89139e82b030657b2f8d9f5d9bfc4 | 1 + .../36608fb81d55d07d46c2f7849cd926ee3b2544c0 | 1 + .../367c9b1f3074839cbe7794421f5a5a30b5392887 | 1 + .../368c81b84650d4644c983e3209d93ebe140d375a | 1 + .../36918d3941b615417b367e0dda84482198335469 | 1 + .../36a94d7bc5dc9af664df029d9cacb70d1662178f | 1 + .../36bc60267ff97612610797a43fa5e7b371687229 | 1 + .../36bd6cf68074e03b5642284ce7d493af28e048a2 | 1 + .../36c7fd31d411d45f3d03143f9a36158791a29660 | 1 + .../36cefffcad6493e933315f78db381ff7ecc43bfd | 1 + .../36db1eaf5e186f36042dd8afeeebfabe675c620a | 1 + .../36e7b1c9920f0e9a7c1c52c380c61f6b44246ce8 | 1 + .../370f93aec0042473af8eda625b8e55afa266cf0a | 1 + .../3711e5aa1c94f1b0f835504e4dc9cfac933f247d | 1 + .../37178f03fde09a06a32ec4e778874ec6ff11c8c3 | 1 + .../3722cdc62a8920daf88999d381d42a7424417843 | 1 + .../3745a800a4b496404473a26dd593f84588194471 | 1 + .../374e3814357798251b0430dc4cfb9f212c1dddd3 | 1 + .../375599a0689231a316462d64f42ec6b33ccca33e | 1 + .../3771c3d9e542f846b3c206c6719246bde5cb472d | 1 + .../3774905200290499adbbac9b674c43b82c3af04d | 1 + .../379b89135a99972794096065de8e1072473b7cdf | 1 + .../37a26cf98e0cb201f2e241d6a41e267821078fc2 | 1 + .../37cfd491e753f20291c4606a4bb007cf1aa69eaa | 1 + .../37fdd34d221df947a4dc6a40f91fe044f88c8ca2 | 1 + .../381cf7c5a9c44f989bb97ebca54137b24a0c5102 | 1 + .../381d7b2c554124f48f833d5bb44cb65d6a4e69ae | 1 + .../3849d609dcd2299e85caef8d7aaf0dc4cbda60ea | 1 + .../385fb0d2eeda5f4790eeab09a29ec612150cd115 | 1 + .../3862864a68546884d4ae2ef7644d75b814fd279e | 1 + .../38633120561625bae7ecb1c951acd585717ee56e | 1 + .../387db60867784e48a23882557f34fd3e8df5fe60 | 1 + .../38a77bbe28f3ce750b32c16df488eb5970d28d51 | 1 + .../38b2b86e0814487d32eb0a49aaa091c527c67a39 | 1 + .../38b7d993272a54c03a7adb7a046e8485546ebd0a | 1 + .../38bce0395152e8d2a60a95b4642bf3700934e4e9 | 1 + .../38cd5b3045252d1ad4ff3cad40d838874891506c | 1 + .../38cf290b09eac905ac4bdc5ffd7fbeb55b28d0b1 | 1 + .../38fa5cb2147069b9e33e21d621935d45486c5345 | 1 + .../39016f47ee6449811c8a18548ba14d36d60f1a15 | 1 + .../39095ad3e086951d38e9de71ed6390bf4a910ada | 1 + .../391ae71a3b29dc703963bfe3a4d96555cac94848 | 1 + .../391b89f7a6069cedebf4da40cbd2e894c4e4e161 | 1 + .../39261d0b29bcefd21020cd2c24c872c070c66ae7 | 1 + .../39427d9b3326e6d242f88c30c5337e28e60ba2cc | 1 + .../395284f8211e771929c6abd17a1e39b471bad2ac | 1 + .../39702f9a29cc5985ccdbae18da3583e3a98271be | 1 + .../39a530e81b2ae6640a22eade59df3f302ebb0806 | 1 + .../39c2d78974b78a945ee5325ec03d2a9842678371 | 1 + .../39c6fd26ec7474a9addfe549df2cb8ee610ecb51 | 1 + .../3a48de373b5922e0287dcbaa10361aa1464b3eff | 1 + .../3a4b7a4a72ab611ede23f7e04e2c7e0300d1c7b6 | 1 + .../3a5d1711382ce031d27b85c9d0db96a8d322c0a5 | 1 + .../3a8258d488d60df9cd2d2e0f3fbfda5aa2916b1a | 1 + .../3ad5eb51c8c2ea66907d5c7b40ef6cccaee711ce | 1 + .../3b055324162a840bb031e742e417383a3c2b9fff | 1 + .../3b6174c02c9421bd7512cb0b507ee81cbe621e8f | 1 + .../3b756b29419004b37c85b3e93c13d3f231e1eb67 | 1 + .../3b7aa5f0f9d0fc31f7be3558e9eae22f13652d33 | 1 + .../3b964cb9d3464c3949a2e8a0f9edb54a4a9ce6c7 | 1 + .../3ba14a20059a5c8f8e184fb6d08736296adf21fd | 1 + .../3ba4a606e430170b23a098c2ac6ee7213be618ca | 1 + .../3baa61730ba406d7fad296d7df24a9629ae0240c | 1 + .../3bacefe15c3e633f44d830137c6fe22c074b155d | 1 + .../3bc46b0f49e132b39a7468c0eeae4f18c15a9e46 | 1 + .../3bd1e196feb0c029ad908a2c989b46a4c75e87e4 | 1 + .../3c0a722d83c61bffb4712e8bdb67f68d6757d30e | 1 + .../3c11357c518486213b14a41e23ce85acfc7225b9 | 1 + .../3c20247465b4757bf0758627c8b5e4839dd819cc | 1 + .../3c4f81b3cab5b54ca2ec122fa809fca650b47db6 | 1 + .../3c695558731a219357e99fced06f0c24b38b6c11 | 1 + .../3c6b79f35456c42d2578553948e940b494865ac5 | 1 + .../3c78b5bf3e8a594974afba095afac84660219f6c | 1 + .../3c986463576a17cc12996a738a2cc479d1198df8 | 1 + .../3cb4479d7f4d2911b165d8e388cda3c7da36bd62 | 1 + .../3cb7605604a629153b71183c4083311f53f6fee1 | 1 + .../3cd91b4c3a1d21d1c90b1e6542ae78fd35091778 | 1 + .../3d4082e12a369fee00a97f5ee6a3b72ea6f15238 | 1 + .../3d4137ffad2b1c85003d032d19a2150f4b6517c9 | 1 + .../3d65682b1f434030f11d6815360c3d269d231474 | 1 + .../3d6fb8e46d4f9e03d6de0e295ec2e0e50df1aa5f | 1 + .../3d75756c8dd79c4efe056dd5435cfb6a2457207c | 1 + .../3da479f176b53c08e1248502a5bc75aed6c71746 | 1 + .../3db85c10d9886a1d664d6d3db26ae7961d66a4be | 1 + .../3dc41a3a65eecfb088cf236466ab9fb737a19b57 | 1 + .../3dcd87542c1fe27ba922187001739130ac6c6c5c | 1 + .../3dd2c473cd54ea601b15cc9840f01e6cec72fbd3 | 1 + .../3e0593c1054f6598bbf8297623874e58ed4f2f9e | 1 + .../3e1e6aa2f96548cfbcb05311c5d24990bb96a8ef | 1 + .../3e2370ff2103895a7c13f394468b1d7588a525a0 | 1 + .../3e30536558f547b9ad4f09f367634b969078f719 | 1 + .../3ea9b3574203d1cc954fbb5b93f7588b765a4d0f | 1 + .../3eabc6ab34a7c9a974850c1dd22c428aa05b1b1a | 1 + .../3eb9a6cfe1aa2c1c02424702999504c5b096248f | 1 + .../3ebde48f5439e084e28144fd489296408e0dac44 | 1 + .../3ef5bed9863d50fbfa4dee5c776d36177e888adb | 1 + .../3efcb90f4a83944731d1cbf69fcde8147549f8ff | 1 + .../3f08853267dab46c6370068cbb68b228923ff0b3 | 1 + .../3f1549e9384322e64380cd38621193a46900a116 | 1 + .../3f1d506b154892f06d439bb90ba5202e723507eb | 1 + .../3f512330103073dbd4f58e82fee2f316a4b0c171 | 1 + .../3f513698f389965cd3f800cde5d06d6742166c96 | 1 + .../3f6985d5b0c8658ee84900aef20ad6b450f6f3e9 | 1 + .../3f6a1b44037f9a0ecf95cd3d23ce8bde0b02ff8e | 1 + .../3f6da0ebdeff4ba77b33c2c2d3b962e7dc353570 | 1 + .../3f7737e152b00480f6b1e13136938142db63c3bb | 1 + .../3f7dd25efaad7cb28967f110fe74e5e38a763ca8 | 1 + .../3f827b95772a69cca7924e0a2e6ed2cef8755536 | 1 + .../3f86932b9bd5a8f673b4dd4243ebb78bef50c888 | 1 + .../3f8e06a01cdada6071275fb451a2ba624eecf6b8 | 1 + .../3f9e6c510733a54871b5b12db956530901898fe5 | 1 + .../3faa53c6eda1becad9cec3442b7069bc2083f057 | 1 + .../3fed18356adbd733c605b538f4fbe6434ecad6df | 1 + .../4017ac5f35612181926802d0cfd9e7f6a5aed8a7 | 1 + .../40198d56b45470dd3064ec201e05ca4e3cdca930 | 1 + .../405cc03a69b95e49ca66bdd71055159a13f437eb | 1 + .../405ecda072acc56c38f0eae072ad858ec1097d36 | 1 + .../40637530cf642a13aaddd88b9e805ab9eed711f1 | 1 + .../40815dacf70ec14f7b8a062c9faaf258058731fe | 1 + .../4088fa75fe995a05522f18f9b0e6945552611611 | 1 + .../40c7820188392556b1df313d7fe8ad00eac4965f | 1 + .../40cdd6d34a71ec60c962c3ce8c6408731acebed3 | 1 + .../410f4c522606d7e3dd362eafa5a5ab9d9811a338 | 1 + .../41114b51cf4fbb2b1beee4e0cc3047fcddd88c2e | 1 + .../416cc4828a6c9b5f1667ac7ad0d2684eb23cac38 | 1 + .../4184d22015b6c9b7656f411782a4484efd87060b | 1 + .../4186f82b0ef77212271ae59a07d75a5f370f8add | 1 + .../4194caf8692db4d7109076c5dece284d07e06cbf | 1 + .../41a24f98a0882fe70484f5006c4b6b9a37bc85f0 | 1 + .../41bb837acd47aa639c62f7986ff46af86a6c36d1 | 1 + .../420a24fcbd56a2a2791e7238666b8aa34e2ccf16 | 1 + .../42c6d3a78f584cc355a0bac6f309e105089332b8 | 1 + .../42da32b7dda49d356987402249a3bb67a0b53529 | 1 + .../42e412a1e895536ef1264d7ee08902b8e37a53a0 | 1 + .../42eddccf89cbef79a5adffb7eb5ea1523de5b3b7 | 1 + .../42f1cfaa89e0e558cc339a4adfc253b4108d5843 | 1 + .../43532b914ad45faf56c91ef34b9b696012326b2d | 1 + .../43a09bc93d6d45b6cef903b1341a287624b825ca | 1 + .../43a12820d4dfa937dfdbaa0843372e901ec73944 | 1 + .../43b19c13ed8e58e70071e063750e8fca7a9f05e0 | 1 + .../43bfb11c19ea9173f4b0185fbc6a622fd0787c68 | 1 + .../43d1fadc7620820efcc941a68f7696480649c13d | 1 + .../43dae97b688afba43b6d88389a78b979f1181c34 | 1 + .../43eea0f55cf11052527d14c3cf0f96e55882c4d5 | 1 + .../43f8e70fd6ed448f6cd62609f6e4a9d03a0e083a | 1 + .../4407ad4a37ac5667b725ef07db2b1b0ebbe6db1e | 1 + .../4422ccfb3a652df26350f5fd43cab32b4a6db9bc | 1 + .../443de93ae646f545525c4a8177964caee78a499e | 1 + .../444bdbc8e2a3f36427b9ee3bb33b639f3d06010d | 1 + .../44513b5ccd5d2993d98b0f606e24c3363080118d | 1 + .../447e0a4f2c9391201bd7abdb3935d959277ac93d | 1 + .../4493e5053e8c93d7133c12033db30ab0fad02eea | 1 + .../44b2a5681330965efa5dadccd65e4296cb9bb54c | 1 + .../44bf61ffe86491dc47531baea9f4722fed205885 | 1 + .../44c41d5a9ee6d3836c4cd959feb9946950a93097 | 1 + .../44d03ac572cc57f5a15470cd97f15bcb5b9aae1e | 1 + .../44d081e51884f8d702e4373433bcf56a8a7ad583 | 1 + .../44d277dff113e85feb1b0da733079ba007e9ce3c | 1 + .../44f204855343e69fdcf5529e0a6cb7ea5dee9741 | 1 + .../452689d60be7f0c8bbd02b65a8c9841ac076b913 | 1 + .../456d04cce86b68e35302afe4c3345e7531aa7304 | 1 + .../457a9522f60a63cad613ce6f45ab52147b5a1871 | 1 + .../45afd60d642320c756621d0d193cd27de023f243 | 1 + .../45b86557bbe4fb210901de818886b7536f396562 | 1 + .../45babb1803fdc9834a37bce496e989425e2fe9b9 | 1 + .../45c14cf9149717468bed37e1e419020555c5f927 | 1 + .../45c97ab53324162e66ed1d4c64371055d966b691 | 1 + .../461af17d337077781b7e49d203e17cf7cdd7781b | 1 + .../464a9d31b63ef5f4fe0f193acff3f7a8251adb7f | 1 + .../4656d9b9e1003224e094622d9723247d8e53ca72 | 1 + .../467ac05fa481edab9bf207738a0fdf308bb097c5 | 1 + .../469213f3d0a4e2171977ef67184aa5af2a7d259a | 1 + .../46a14a2d2ab594d5d1917b16120cf28258bcd02b | 1 + .../46b30a46669909d38ddfd379180d9b9e4b032d30 | 1 + .../46bf3a742f868512007f33d6092b25ad9851abc5 | 1 + .../46faed608cd8553355e705736f5883a865bdd1c0 | 1 + .../476140a4869c363ff59de15ca0b3dddb33ee16ea | 1 + .../47678ed5dae9d91220f82b512192c03161458d96 | 1 + .../476e1eb3a45bcd3c87728f4a5f152341fc41c6d6 | 1 + .../4775847b1966e3acdf5bf21407d223d54512c0aa | 1 + .../477812c3aa633968c3f508ea4a64f6240b7c1282 | 1 + .../4786bab5e3fdd53811fa094d64658a869323943d | 1 + .../47975b43d53b5ddfe8aebbb719cb70af90f9ca56 | 1 + .../479ddb4cda1c95a66132ba2891f8deed16e1e31a | 1 + .../47c96a95d6bd928e3390068b3c94db28d219e9c7 | 1 + .../47d2125494edd0e8f737339160fc2c2bbff13239 | 1 + .../47d754aabbae7b0b019240479e872ec641a71606 | 1 + .../47f82c71674923da07b7c082409faecaa9d932d1 | 1 + .../4849670c7437aabe38ac365b533b2cae10e1c316 | 1 + .../4877a47b68dcd97455dcb8cd52e27309ec642b93 | 1 + .../487deb88a57dc3cabdf497fe30220136e593d23d | 1 + .../48a74bc4e405cef7fd774039eb79bdfaeafeea6b | 1 + .../48aba9a0a8d38583f02db4ffbfe46b11affd2459 | 1 + .../48ba4204d31335006c77c0a0c393c5424c5c89fd | 1 + .../48bb02ef59af281b015aba26344a918d3e949c98 | 1 + .../4907d4a7edab4d2d57ded00e95a654d47f9d823b | 1 + .../491492c2f48c07bca9ef88c9fd36bbd272563b73 | 1 + .../494a7c765d815e6adc6d4e66a57225322bccde6b | 1 + .../496ed2b73e932787fe91d418b240c466ab6a4075 | 1 + .../496f687a93323cea34ef1249059c862f9397c645 | 1 + .../499184ec78a677697ab3ce5b0a87dfbb5ecce65e | 1 + .../499f8c99044f5a7eb9940853f276e5ed7a9894f3 | 1 + .../4a015d179a6415548a65aa75d68b1927fe2b0738 | 1 + .../4a46cdc5c3a288a4eead1245fd3b0bfea974ea21 | 1 + .../4a729815cf7a0f3947cdf502e425da1b2392d6b8 | 1 + .../4a7e2f54a225b7edfc7761d52940b39a3702b9d8 | 1 + .../4a8d82dfb1750aa99deb48b58f8c91a30cc703b0 | 1 + .../4ab1d0f5d83d7343f225dc40c2a3a9940dbe3f7c | 1 + .../4ab5fb6756c937560dc91ad579231800bcb605f0 | 1 + .../4ab75e6d0cbfec5617026ca0e5622cb4be8d69ea | 1 + .../4aef881f37b09a5f41876628452dac08c70a5c3e | 1 + .../4af1e59e48ecbb8bcf5f8c2a739ffe2d47054b4a | 1 + .../4b22e5ee8f595d1440ed41006d8e611da06d0c13 | 1 + .../4b537d79f1a6255185126b99325e3917dfdc7885 | 1 + .../4b57985dbb3b797fd0788cfb9513abc07ddad003 | 1 + .../4b72ce01f999a32aedc950dd1804a8795ff98723 | 1 + .../4b7e7a47d519d00fb5bb9332b6fb49586a4134f8 | 1 + .../4b8ea927af2611b4cf7fbab90c9f8ffb8bea3ab2 | 1 + .../4ba2921581f7a3560b6ec87297653fb165ccf969 | 1 + .../4ba8a95b0f39aae1daf6e664542420657da72fa0 | 1 + .../4be8d76134fd3aa72fd3ecc702e88a4530fcab53 | 1 + .../4c0186fb62257335535a95ddfc34807b1f836154 | 1 + .../4c0a1b11b6e6b7691c115aa09cd92e8ee09a5076 | 1 + .../4c117e356638d628e5b841bc413e67c8bbf10384 | 1 + .../4c2d2d7bdc708a582093d11d189f7addae41c5b4 | 1 + .../4c66ad58c30b6404b73490df6a7aabdb4eb995b2 | 1 + .../4c749139f91d4268578b998b4fc4742cfa968495 | 1 + .../4c9126df811790be522891686bd1fcd0a7fae560 | 1 + .../4cafaf85ab316a592878f9e83a2be01cfcdf738f | 1 + .../4cb7d23ad1e01a5e42d3c8d927936db03801ab95 | 1 + .../4cff2a8e93a415e0cd8f16313427db2dceea582a | 1 + .../4d21f89d57587583f18ad029ffd268e08c6deaed | 1 + .../4d2c30084bbdec620ff06379849a52ea2e10b97f | 1 + .../4d72ed31959a5c8b48c6c9de682cb5364bf0cafe | 1 + .../4d9a093d9de04fcd9c74eeb3fb252b4f762f048e | 1 + .../4db56aa4ef26d2fbb9c74967c01012f86fb5c60e | 1 + .../4dd64e2309c3e9efee2d5404d847b644329d1f7f | 1 + .../4df3d74d147d4bb7144799be7f96196f44def06d | 1 + .../4e1c650230dc5d5f622303dbdb697b39acc5953d | 1 + .../4e27213b2fb3cbd2c324c9d967eb6837151c512b | 1 + .../4e442bf704b5166ed40da217a4f0a6103e117487 | 1 + .../4e6bb871c5b2e524530d3675221cf34b2e598538 | 1 + .../4e7f6d1d5ff623f2b978feb61b0905320a14cea2 | 1 + .../4e8673f1a272e7a4846b2b13fd4d6d699de0dd4d | 1 + .../4e8dce29e5e8dce89954f8535e95a66c4dec52d0 | 1 + .../4e98f79b12c1bcc786816c990038e187b1881a2b | 1 + .../4ebc10c30a1a1250dc40fd49051eb8cadd3eb677 | 1 + .../4ed19b212daaac7d9ddf8fbed04bd645b3540c87 | 1 + .../4ed948d6df09636962a55dc16fa8141b57caf0a8 | 1 + .../4f01eb0e5c5b453e93d7259acca78110e06e0cdc | 1 + .../4f043f492b006187a12d4a27a2fb711e089c21cb | 1 + .../4f31274445bc35aaf35c1fc3838142b83f4e4dbb | 1 + .../4f3b0d3de5e5a892c662d05f7df9b836b5083f4e | 1 + .../4f3eb1205832e452025bc7463ab84f005ccd56a6 | 1 + .../4f444cefd89a49cf66c69836b968e18c893e6243 | 1 + .../4f4de778bdec3be4e7cc1f875680330eb9edda65 | 1 + .../4f54816eeaa1958560b3411df01fd36e2cc3cf78 | 1 + .../4f5d2d6eb42d852d85a2d40419830ff372017208 | 1 + .../4f692f08e2284094269303792599c3ca996925a1 | 1 + .../4f967edf0f22d51ce89c007d5351844488bfc1d4 | 1 + .../4f9df26c7948631ce06cb7292bcc481337bff811 | 1 + .../4faee5238fb7a4ab5d716bcfb441ef4b0ab3f888 | 1 + .../4fc70db2882c50f92cbf554605f20aa8afdc9e7b | 1 + .../4fd09ff1c3fd39676f5029f8a82082c4a788cbe7 | 1 + .../4fd67112498e9041d549dca8902b4b18f4151e0a | 1 + .../4fdbb01ee1c89fea2c908ade5230cbf49b493184 | 1 + .../4fe78456cf82ee1f4f6bf880baf672a53376c62d | 1 + .../4fe9d51c1a4a51db63ace4b7593bf4d0179da70e | 1 + .../5008a5b791ae73ec29ac0e451b2193e921d7d91e | 1 + .../50197b1f963b6c70cf02494a68b83252169b58f8 | 1 + .../501c6aa901d9b79489250b1e7c008dad90b998ba | 1 + .../501cdfc8b8bfd47787c30328084cb44010d48a2a | 1 + .../5020bfad68bbf3d62a9901f11d582b9367ff01a8 | 1 + .../5027b63206364f920f33ae41d244998d60e6d000 | 1 + .../502ba5490df10d7b64842c917be0cc8dce168153 | 1 + .../5040561743c74062906a64802db725e7cb87b572 | 1 + .../5047a7a4c5f22dc492d73a6de284a0603fc06171 | 1 + .../50701ea0af2da8b084ea4a3566db2cedf8dcc2b9 | 1 + .../50765c36b2c5b67d14ed6d3f1006bcac492b9d7e | 1 + .../50ade4cb2bfd78d63959c0c196702463020ec1a7 | 1 + .../50e97f4dc4e78ccd7491b23a05fec77e705d6d17 | 1 + .../512819dc5f866c4c52a96393d1dc161a298b58cf | 1 + .../5134a98d252e038c84c184e2a60b3ab15541c32f | 1 + .../513b5b1cd7ae4a18b0684e98b8bea2445f0f267c | 1 + .../5145a2f823d50829addf9a923816226e49b73772 | 1 + .../51585e660838f7655a9d3f8e62673ed896abc1b1 | 1 + .../5159ef1765261a6a8967fe22b91be23bc4f7c672 | 1 + .../516e8f247c632cc97a34b088b9b9c5522f6b4b7b | 1 + .../51902d7c0dc3e60282faf7c3bed70ad3588b79cc | 1 + .../51cb6bd8e208996ef5816ab2e4a5f0a4392acd9f | 1 + .../51d22c9e318035b292b06c7e92cff7a7dcd2ef46 | 1 + .../51df77e1f5047cc73d62f6a82b06c76b2f2dfcf2 | 1 + .../51f4a12afbc5c09d84488a09c1ec4fad2f8ad55b | 1 + .../5201220ebf5a752ed230ba1c4660d6768ea0ab37 | 1 + .../52406f743dd8cf468c8739e0e49a5e8c2abe890d | 1 + .../524a8fbae511284a4b3feffd7e69391eebfe5fe3 | 1 + .../525afb4266fbfcb9a9457044ffa429e6345aca74 | 1 + .../526b41de4d7b2b6cca5b8cca2aff4e05e1edd180 | 1 + .../528808e08755d1c4badf200ea1e46b471e697367 | 1 + .../5292dd4bbfc4ed134ecca359a50042487bdab8de | 1 + .../529e15d7495022b3928ad252f217ff7066f4a8c4 | 1 + .../529e417f9521111e7e2b214bbe3a009fb241e0e3 | 1 + .../52a46ce5d115709464d927bd868cb66e64d5d890 | 1 + .../52b71f15e64724663db04868b953a0dd6f8ab01a | 1 + .../52c7e56d194272214280372b7dbacf979b86a714 | 1 + .../52da571031bbcc150454dd6be63a21c6a2dca5e5 | 1 + .../53045f62216e6dd1d7b2d1c05dbda813f59f4d38 | 1 + .../53090ff0e10b029e37a0eab690a757a5f4c346ea | 1 + .../530e0b9098674994a45495cf1eb8c3fd36b04ef3 | 1 + .../53123aee1da68a8b9619edd5140ab5c6aae10886 | 1 + .../53234e0beefd772757294c48658a6fb1b632e5f3 | 1 + .../5349c13d7b8dd8f692718b4ef221a21825fb04f3 | 1 + .../5366b2cab843c6f4979214e27b561d35321bd2a6 | 1 + .../5379718fd6733c3194547aea3041303f46159862 | 1 + .../5394689c5e237d677fa75daa48d897e73a858ecf | 1 + .../539798847b99eee00985bc1951275a98b55dd7fd | 1 + .../53a808e42f754a6b97d63d9648f1e9a70ef36421 | 1 + .../53c007e4c811059c16e10ba22c2b8c0f4ce3d99d | 1 + .../53c3edf3601218d001c1e5074a2e608ca903fa25 | 1 + .../53c8c5901bf8077df2161336a0fc9a5f774e1a5d | 1 + .../53d0cafdef4e74e058c9073bbd755b723f71207d | 1 + .../53dc16200f550b0ebabb6c5c132ae4191e1a1482 | 1 + .../53f7ba7985ea8688080ed30b57d08c4ab91d4a7c | 1 + .../53fd1406ce1667cf7d7de3b444b90660d76871fb | 1 + .../540c6dd899720dbbc04e0f316f56549b4c1ea925 | 1 + .../542c02db48e5517905eab16fd96de2d76702fe3a | 1 + .../54305f14909100e1757674ae16a759d855c4a647 | 1 + .../5445a326ed6ffd6f95dc9cb3c9514a0e53f4868a | 1 + .../545537c377201418fedef933281d2dcbea90a159 | 1 + .../547539d40d65ab39026f065bc9152d96c7c4ad43 | 1 + .../54ab5c42625d4869197c04f218c443750527c92e | 1 + .../54b4f9842dadbaeb2ac90b0f6d8177f76ce3f9a1 | 1 + .../54b9966d625700d7ab8b6fb6e1c3e019b5a09f6c | 1 + .../54bb653bb1662d8b2730bde1e4a255606fea193d | 1 + .../54c4a1f796d9ff3acf74d30faba1654e46cb8e87 | 1 + .../54db865605c4886df424d455f6674d7c9f904922 | 1 + .../54eef01ce1e7ec1e6b58bb1a7e192b0e5d3a98e8 | 1 + .../54fe044e4c6d4dfed594e15518f9550df3910bc9 | 1 + .../55222bbf499234ced0243f0c54a06a8e01ee78e8 | 1 + .../55296a40c4a4eec0b8b959e6e4af29fbf647774b | 1 + .../554254ae450e17abd46d3c290600e3620f888246 | 1 + .../554ee85d50ac67df97fb01a2eb533f4a62a41c9f | 1 + .../555fcf75ef7ac731ace1cd81886b6cc1b013e911 | 1 + .../555fe6827560beb47e96016c2aae78850a4e345c | 1 + .../556a65730f4092db6fd77c12b631d10117d47033 | 1 + .../556db9cb87763f9c127e87edfb88a8e8443c00d6 | 1 + .../5581fa4307ec84b987cdfaee72db964e4a304876 | 1 + .../55944a2b94a2ca58cff331e3ef254a2869f5fb50 | 1 + .../55b0896604f6a6b38c17cf95f8c053e19d26090c | 1 + .../55c61e7a6bf6a7b27176d90e85c792e38fa47d95 | 1 + .../55c9ce0b7ccbe8ff676abebe7761bee66f38e3bc | 1 + .../55cabf94b48b77fc7b0a87efd62377c6a44cfd3d | 1 + .../55db8d546fc7e337dd899c328c82a60b6102a7b5 | 1 + .../55f99e2d68ee85b75133f78cb948a5b7466cb4ea | 1 + .../55faab0c69903138a86beca8e6ebc3e7a2010e0b | 1 + .../55fc38b7d593fc118d407fcbd2ed49e3ea890734 | 1 + .../56397a2ccd392deb6d3ed52e0a065fdde579e9d6 | 1 + .../56567e4be5618770bb97f61b1487c7d47cf8192c | 1 + .../5658a8d8fb388e7c7e5f7c7fc8630d3de961b676 | 1 + .../5687a5e9c47486c4d2f24f74e09c95a9b9139145 | 1 + .../56c988fc520dc9a5bafa28ad83eb0e972fd70567 | 1 + .../56cc448ba82bed7220a831c4b05eabed0406386b | 1 + .../56ed4007baeecebd4a8905063055ace47704a0dc | 1 + .../56ff467c9c6b5e3079baa559955ba107d89d77fc | 1 + .../570fb69de8afa341b54dd79455b6d21085c0334f | 1 + .../570fc65b0c81c1473fc82b8545f5ae6efeb839ff | 1 + .../57267f8aca1eeab5fdc28ec5f2cdbd6ce0d150ae | 1 + .../572c410d27df3156ea85e726a966af51c9cadf8f | 1 + .../576476370370b5501ea6a61ac033110ea83ed7c6 | 1 + .../57731bef67046b96aa1a3f92ffbb41851e7b3353 | 1 + .../5777068b6f7170fa6a505e9144aa3f6fc8625b74 | 1 + .../578701a27b2e9321384f3e516f48fe5d2ebfad6d | 1 + .../57ba07044f687929674d01d0c501e408072f02f8 | 1 + .../57e2edb6bce9815f7e92a1cacf2c42a1d8a5ed21 | 1 + .../580742d9b18b0603cb29360f8e7cbfef479c00c6 | 1 + .../5876822a1e4504b3dcd7a3ddd10ca0dafc4c9ce7 | 1 + .../58d98ae03e7b63b61749dae272899a7f41a89c30 | 1 + .../58dd5844bf68fb5f47e929bf24c7d8dc2cab5791 | 1 + .../58e9cc8b18e2ee0f4ef6cfa6222d9ba9c4e6999e | 1 + .../58f607b447f90cc1f1f8626ebec53c5173658a3b | 1 + .../58fb9dddb99befb27e93f61cc7346e2e320d4124 | 1 + .../5901e4b94bc2da63a3099505728106aad680aaf1 | 1 + .../59170b1799ffe9d1e085f2b8c38cf655ca14f1bb | 1 + .../592e17797674340048f2ec49023bde0febe810f4 | 1 + .../5930d2e1ddc70c728b1f219bfa14e4053fe56dbc | 1 + .../59357c2c93a40183682393a898e6b58d6e81cb14 | 1 + .../5951e8f0a0cafab1db40426b854148481b762ce2 | 1 + .../595901e13730319ffed24982bd4ea8c12e89bc96 | 1 + .../597a6a03965d41f1179d6a45268ac32531a9c209 | 1 + .../5981777edd562076958d2a1e4c80225a425eb08e | 1 + .../598b73c14cf25c235e0cc5c5a3bf6a5add3b0b66 | 1 + .../5991f803b4df614fde19c2f5742b860c1a14d33c | 1 + .../59a01c32eca07dea482bf25537b7d52b7bc5aaca | 1 + .../59aa7a8b1146af0061b9b9478ffb499b5e7f3229 | 1 + .../59b9a0e1dfe394504f08eae69abd47bfab092572 | 1 + .../5a198317abb136510b17c59de5eaa7c880152f8b | 1 + .../5a53b6c3fb03892958b022df8a6e0a4cd3d8e51c | 1 + .../5a5abab97631cffda0f11fd3ecd87d86dc325f8f | 1 + .../5a5d03ff40bbb94cac9b06c3d47e693d8db5af67 | 1 + .../5a5efe209bb7d1e1b0085b1515836fcb2144c5f7 | 1 + .../5a81cfc3ec9bfa6d49dcb19b411b6a4b6043df15 | 1 + .../5a9d9ae70e2df49baefc66227ea1c1604902038d | 1 + .../5a9f746ca2d826a621e61152c995893027ae3dff | 1 + .../5b000b738705bfd4a6198d22129f7e9f2ccf1708 | 1 + .../5b08bfcfc4f7317c5e45fbc3a683064ae85a3794 | 1 + .../5b33a7895ef81de11965a513bcadc8ee53993d21 | 1 + .../5b718764a0b56ae1705be7dcf35a2c639fbee6f4 | 1 + .../5b72a3d1797578b12f235ecdfb8305d928514960 | 1 + .../5b831888d2299bcbbe9bb60f6812a461f2da8720 | 1 + .../5b89dad22b6b9ad7d97be2de400eaaa8ab2a03e9 | 1 + .../5b9296392fbbb89f20c46a8276795c3b237a921b | 1 + .../5b9476567b263e9cd4c8455b1383c48f559cdd5c | 1 + .../5b95416a6aeb72fb134a6149c2103c7b4b8af54a | 1 + .../5bc0284515461bcb5e3ebafccc633649bb1ec2fd | 1 + .../5bdb30e6f918889383a02c0269f0e346fb129035 | 1 + .../5be7de136c7e263729c299d1617ae86dd468f91d | 1 + .../5c2aec0e280cc6dccb0aa9c3d4c5354a71c3d8e8 | 1 + .../5c2cccde1ba71ca24440e1be3fe94d8b2abc9ba0 | 1 + .../5c414ad191f1a4f17701285f026d3be386795f46 | 1 + .../5c4b2bd5199eaae65eb1b50ff2282715f285525d | 1 + .../5c4e02eac5ec6bfd2aacdf25eb5606e7f1f8d245 | 1 + .../5c58efa0b606fd3a9f5c4149f78312e37884f070 | 1 + .../5c7526188d4edba67f479317b2da9ebd815e25d8 | 1 + .../5c82173fb5f60e67f6c570773d0e7ca501b2ef2a | 1 + .../5cb8c6d32062773a2963b39820bf5c9c9d4d14f4 | 1 + .../5ccd74670aa8f9270b7b6d1ec35f26366e24af92 | 1 + .../5ccf6b63be9a26dc12ed0d8d9fcf8f9bd4d32aae | 1 + .../5cd441bea952394300fbb2b175630e939f70734a | 1 + .../5cd9d11e72f21213a0cd5e3b000d85ffc71a267a | 1 + .../5cf79ca7fb6c27351843e8929c62c99f6d116b3e | 1 + .../5d460d2d593010e8b116c549316144cec213da3d | 1 + .../5d547488bdc33c4ba9f4eb64d9e510fe10c43b64 | 1 + .../5d5955b5c12cb917cf3b4b20cef145f61555cebb | 1 + .../5d5d395b7d0d39e7e061299a0ac6d887b277e7f6 | 1 + .../5d67205500c9fd9a4b6a49b76f5ba2c4bc80f718 | 1 + .../5d979fc0c97f4b30b22b3b449446ef2dad2f94fd | 1 + .../5da06db4c347f603cf5309c3456c26cc7ff974ad | 1 + .../5dccc42ff618aec2747273439401c4901ac182b8 | 1 + .../5e1b24b8be80cb985494cc5e6aad6e0169f302a9 | 1 + .../5e29c824e31a38432a78e51cb6163effbc1b7632 | 1 + .../5e5cf1d19425ce321d71cf332626bab6bf9e5c44 | 1 + .../5e7998196110af78479912905025c638163deb00 | 1 + .../5ec7eb46ae8e0891018b9848bc2341e3ef6ee62c | 1 + .../5ef0bcd2fc8dc128e8583e90e1d3848ad698670d | 1 + .../5f065a6b9d7bf300aef6fc736b6256c582fa075b | 1 + .../5f06fb75a8156e71669ca65d0d928c7effc223ff | 1 + .../5f148693c5a6505500494101603fb4754464594f | 1 + .../5f1c481f15b7e89e16871d58cd5784dc2fbfc8f0 | 1 + .../5f33c80c85ea079ca0e803f9157053bb5cc26ce9 | 1 + .../5f49d9e42303e9fd5d3b3beb8b4f91d1d295e920 | 1 + .../5f617801a71e54b50b37fa8715f4acb9c710bc1d | 1 + .../5fae0f3d4ccf63a68fa6fc6ed2f605c153bc568e | 1 + .../5fd0ea816791d944d140a7f5a132e628c4df41cf | 1 + .../5fd72300746767ed3942898b20e747b5e468bf3f | 1 + .../600a49efd1ef275dd0d15886970d34f50ceb2cb5 | 1 + .../600aee354a6065175892343ec14dc1eced5c33d7 | 1 + .../60157ba4a7cd240aad985554d23dafcb6b99be47 | 1 + .../601bf2a7aa8b6c3a9adef4933fc515d494f4a95c | 1 + .../6030146df9ff31d1d977c2672cfc3792ad81865d | 1 + .../60350336430acbd30d2f4a7afd671e1a676249b8 | 1 + .../604aa389e1cdb7844558781a66e69bb80e5f7ed4 | 1 + .../6070c8050e46e845c5170ec25daefa937dbbdd11 | 1 + .../608151513d665821b3914810e70e9c1f957da187 | 1 + .../60a40b71e2980d806f6e3f1f604e1c25d8d684a9 | 1 + .../60c433ddebf0bd6ec3f44d608946aed9e843587f | 1 + .../616a7fdb9927448c5c9e34f94d4f6d784f55ccf8 | 1 + .../617d47ec32a898ac6e2b5bdd9b8e643408054596 | 1 + .../61ac7af8ebd0ac559618d67f23d159b57dce5577 | 1 + .../61ad3f5b692481700ab46b1c77ecf7e1590f4f72 | 1 + .../61ad53ecbb9e93b9d193624ee3222dd39af8c8a4 | 1 + .../61af1bfa70f27db871da9994cee2a1fa6dbfe915 | 1 + .../61cb3c37ef29bf5abdbf60157dd9334ea8578716 | 1 + .../61cca434775b13627deda2ffc7b421cc834c16ee | 1 + .../61cd2f257a7e5a750b8f03f5aac0ffb2badc3aef | 1 + .../61dfcc18f9bbed9da1c93970d11da1509777d17c | 1 + .../622454dc9deabc8438f95f3e6280211c37369c04 | 1 + .../626dec99c8f47a95e864b2a31b4ca6b916ee594c | 1 + .../629399f535a4b780a7126fd274938c9e1bdd9b94 | 1 + .../629683fa749137e2dfd6e82633d304ea6c124ce3 | 1 + .../62c572a03d69a6b40d25947abae19bf6ce5eb385 | 1 + .../62d04745f9fcb76848b12153a162a268f14abeca | 1 + .../62f4696a4d80fd4c0dc13ef75f8bacef6743b8d7 | 1 + .../62f8cb127c31b1882150c0c8effbd39c09119e5f | 1 + .../630f756a29287a797ffb5586566bc1d25758573d | 1 + .../63167cb8ba3874badf57f0e855e7f02478cfd49f | 1 + .../6316bbbc6a41808b00262eab5f5262fcfa97066b | 1 + .../63254af008fbdb6301cc07058a867abb97610c66 | 1 + .../633faf2de8dd00d4d8b3bbdda4d9f2125613a89d | 1 + .../63428d34338ada0748fdd95dc5f6db204de7543a | 1 + .../634458fa7be2820b5e56c8ae2c193b953af0ad40 | 1 + .../6360d46053a73eb3d4ae1cc875f022d5d461f571 | 1 + .../636131ac174bfe63b118e739bb030a2fae2ae0ed | 1 + .../6391af63a3bab91b1f963e133bbb54d1ec7814cb | 1 + .../639afaf27cd09001a498697b15842c3394f9535d | 1 + .../63b0cec5acbe499ece5bd821c8af36dd0de95819 | 1 + .../63b754b26183ec079fd02af865aea1d5c49d93cb | 1 + .../63c6cb5ef992299a9604582c39c7f956c65860b3 | 1 + .../63c8bbd564a4a1648edf9f05d80a6b089c40883c | 1 + .../63cc94dee9c6256ddfe004eb9fcabb932627fcce | 1 + .../63e781018cd701d6d445dc7c4ea28f9a53de825f | 1 + .../642e1fbd4f64d1ba035193a0100aefc8d436121a | 1 + .../642f40f85c3e92c672ec038a2e238351c6c24178 | 1 + .../643386ed0f556a2227416f5b32e310b70a2cf743 | 1 + .../643f751fa11ea6d366ace6319feda720f2e8accd | 1 + .../64537ec43a7b2b59f2b936c7247b94e44e1bb551 | 1 + .../648fef1a9a568a6e98c2cb836193a18ec11b60ce | 1 + .../64b6416da57fa74cb892f8728aac8bc6064ac5dc | 1 + .../64c1ab90001da13422d892838a22208f71109eb2 | 1 + .../64c86a5fba96a19af3d7f98cb11533d79ff4433f | 1 + .../64c9c1019b362e31675420967685e3e5e1d92f06 | 1 + .../64e713b456a3f23cd86eeb23d796639b7c85d2b6 | 1 + .../650b0fcd68979a929ceb682e9024fb7beb57c2b1 | 1 + .../652f7178db85a30195aec38e5bed56f8d492b18c | 1 + .../6536f2a8bf497dc4fb07e6344571b041ddf3e9ce | 1 + .../6552bfcd6579a934948b7068b4c551a0117ad0f9 | 1 + .../657e868eb96e89c02af5430fd6fd6b371011ad19 | 1 + .../65883b58c6b3dd90d25b39f5ccc47be52f17c9fc | 1 + .../658ae5cbb0d9d2acbdf007a1d56b7a8d343343c5 | 1 + .../659a2dd2fa1b9d801f3241e5ff84637ce06ccb77 | 1 + .../65a933e1d1978ba3bd2f831c22458a755de9ba53 | 1 + .../65b54fb91b4a1cb8c833485f4d132f6e676256e0 | 1 + .../65b5fce87c9d43529bc25317899f3d88952342f0 | 1 + .../65e72ac1ffd20fc948eb9fd0715334a200044fb6 | 1 + .../65f7ef2d10a182c5af3e4c60b4f23f13770b1d2f | 1 + .../660b8322660c10bb3072efbf02a01b028869f3ed | 1 + .../660ef1c053328676703178f6c1f1a9eab0eba34d | 1 + .../66252c3d296124f1a894a2bef80eb0b8d2780c58 | 1 + .../6652466b4852d5b5fdaaa69e10880f1a3b76c3fa | 1 + .../665eb41953197df4c60f261f2844052bbd0c48b6 | 1 + .../66726b80715835e1ff8fad96f3c76a0309586a88 | 1 + .../6699c94d11593280e700614b550ad835b0025476 | 1 + .../669ff69c2c67c7765c32e86e0eda8fcf04bcdbdd | 1 + .../66bbe506485ecc1f5f29905e93bbc326b119a9db | 1 + .../66cb36473c4a75d094b0c109710f2456a52e3ac0 | 1 + .../66e881b64f9e9007cc27f9ae6ea1d9c09b7ff1dd | 1 + .../66fd2e2f42f7b15c03f46c8f5852fc2b2a1288d4 | 1 + .../6723a627907cb1d91034b75d6a69d055a9d2a9b2 | 1 + .../674c86a431b193721af73dfdf07aeef65a7ef508 | 1 + .../674e2feab074ca0240a6ca55826b14e434793461 | 1 + .../6766fbe9f961609fc3c2e2dbb922ddf1dc771d96 | 1 + .../677c2fb0bd66dbf157aed281b05b92ad2c197c37 | 1 + .../6790425ac6ab89b1bf9e69e61d0a23def2470c84 | 1 + .../679748203674073239d2e5a0f7f9da26bc60feb9 | 1 + .../67cfc5cf8010d9b1c152301eae06d149589112ba | 1 + .../67f26334e58a0356529496d89738359b7a8dd136 | 1 + .../68052b4483af39b51b45980874124e3793c72420 | 1 + .../680f37fd69b7d65b2bea1f6968d0d19d60d93bb6 | 1 + .../682b9ef29382e2d77b5242e0860693527c825702 | 1 + .../68560332b36281ab2ef6e177361019a087666119 | 1 + .../685bad2808b9ebb6dd3bebf554aba2916e169a21 | 1 + .../685c94cdfdc42c71493f0fbf86f6cc75a2bfe7f5 | 1 + .../6864a32b8e40345c0b76999afe5f1c070d474908 | 1 + .../6864d1927bc63a92a60460a41b2a104d48d49e0a | 1 + .../687590a8d9eb9f62d77022572d103d4c5adc9867 | 1 + .../687648741dc59ceab592c14d35fa96ac27ef98d1 | 1 + .../6890f89ae85a96d458a2e92ae84db78ff5a3d8e4 | 1 + .../6893c34edde19b9be594417a3321f7522c83713a | 1 + .../68ae4d6748f33706497031526da5fa76f0c923a1 | 1 + .../68b62ec5b8680759a52e8934526dbf400162c104 | 1 + .../68c6c0d42504385245c61282657b3afb267a068a | 1 + .../68ebe4901e5b73c0d6c376b14ab93cb27b6b9b29 | 1 + .../68f2022142d8ce6c1188c67a635ce455d70e8668 | 1 + .../68f3ade32553e6641d33ffec7c4bbbe70c966a75 | 1 + .../692178574c30ecc0fe297e53225c7fe6b7047923 | 1 + .../692a5e26fd84eb7c487336a8ad5a27bbf550d3e5 | 1 + .../693b4e80b442d5871a480b72fc7f154489eada7b | 1 + .../693f1072f030299b192b97d19cba8ff9e045ceba | 1 + .../696eb3cf37f866313a3dbf40b4af77d45f827d98 | 1 + .../69763ca3d19be4c3d360ac96f990730c211450f4 | 1 + .../6977dc4cb03457ddcfe3fb5e4ebd32c7a60a4f4e | 1 + .../697a7f07151aad714b88aad13a439841eb1d849b | 1 + .../69c1c268224ffcce5d6dc13b49962a3c8887c2ba | 1 + .../69d24f5639ca8a5eaf58924722cc313b9936c330 | 1 + .../69f36a1e1c567e1d5e44edc58c355abb92e23f68 | 1 + .../6a35130e1e9674f6d1c241fd478fe85332fbdbb1 | 1 + .../6a37620db708370995281cf6c46512cd60efeda8 | 1 + .../6a8e8effd233033afabfdaf9d971d772b2bf9ecd | 1 + .../6abb0ece7e16ec849987f8c8acf3aee7013ec5de | 1 + .../6addba1d7123769bf9727a6a4106110126f36086 | 1 + .../6aff050ffc62f58100aca0e5b1839f097fe65155 | 1 + .../6aff0519662314531494b8b3319e2768ebd40a35 | 1 + .../6b14353e2b7d7788062623a8ab274c36f8e8bf3b | 1 + .../6b611309b991acee95b55b4b19539f65ceccf76b | 1 + .../6b861044122a6b081803e3a99f47b40277743d06 | 1 + .../6b8790739dcd1f8d3ef41a03c6508717d78feb52 | 1 + .../6ba407f0a422507bed18c1d5b52f1f550c278fcb | 1 + .../6bc93c9d2144506aeb9dbbe41a5b4a095f8fe9cb | 1 + .../6bde125fedeb05208eb8991bab6ad0713a60d9e4 | 1 + .../6be0d8042ea3f474de849bc8205c65b017a3d587 | 1 + .../6c1bef32f6ca0cfaee1705746902336e4fd67e96 | 1 + .../6c3db2c6ab0b6b80838387b923869561f9e1cf11 | 1 + .../6c7e6cdda9913347f0ba8eed8f914941cec5b2c1 | 1 + .../6c8a1b2ea553e6dfa5f653afeeb135465732aa6e | 1 + .../6c8acc451d0c73e74ad6918585d0c8776498affd | 1 + .../6ca4ca112dc6f3b82a4ee1dcb539f5412b61802e | 1 + .../6ca7072324326a43f42b641dd4cc2d785bfbb7d6 | 1 + .../6cbefe4b22649c02c818e52d3142c768ae99b9eb | 1 + .../6cdb87bebca9057c621affd2eddfbe726630b1c6 | 1 + .../6ceffd0098b1fadf6f95341e39b6b1486b6e2dab | 1 + .../6d1ad01f9d4765e28554608aaaaf7f86d7fee48a | 1 + .../6d2c53b612c9e3931c251808123e215918c34b60 | 1 + .../6d6cb592531f25b7c0a1a607342e2c3dcf35ac1f | 1 + .../6d776b8dcea06b627feb06e8e07e6455f48086d2 | 1 + .../6d807824d43b2e677fee210fcdda1e52cabbbbc5 | 1 + .../6d874714ddd3706018c9051c55abbcf1210b4643 | 1 + .../6d9b8efdf33eb396820e03892263d3b784e5dcf5 | 1 + .../6de00eee762e4ed839eb40fe1f0e25de0071e584 | 1 + .../6e0058983c03e5e6a363e64deb28a252b20617c1 | 1 + .../6e20107c698b7f36b9163a7db7382e068caca218 | 1 + .../6e41239fdb2bae4970f0a9787e683e94dcfb1760 | 1 + .../6e59dc43f59b064311d89a689dd58f9a905d10e3 | 1 + .../6e85ec4ec7f9980d8de6d6892d1415072155eb5f | 1 + .../6e99af85369d8643f1c91d6e46c038af402d368c | 1 + .../6eb985be69c6686dbcfaa0cfeba04cbc68dd5298 | 1 + .../6f3e92cd7c0bd1c759a5d1ec589fa593028c2f27 | 1 + .../6f52449eba2cea1fa19799e7de8f931e69c70cdb | 1 + .../6f56fca6cc1c01fee921e3ebec30d918b7e84af1 | 1 + .../6f6d754696a56d367c058bd6cef710ac92a36c4d | 1 + .../6f7390dad86b309a8464acc781b7a22cdc6164de | 1 + .../6f775290762b949c8416b8db72a80fd4f625aeeb | 1 + .../6f8393bbb9d02857705efc61028b43ee819ae6ef | 1 + .../6f8e2a9cd5725921d637323d42b65faaa53b2d0c | 1 + .../6f9c6ccc8504bc417cff64152e5d55f2da6384f6 | 1 + .../6fae620fa980b4c2193b8d1ca489fecb771da643 | 1 + .../6fd7c011c1e087678c2fc502f6049d5a1610b285 | 1 + .../6fda74aa278e18be569d89d76d2b7d189719fc9b | 1 + .../6fe4cc6bb00f0db22fe4cf7e68170752bf9e1f7d | 1 + .../6ff3146da9ac0acb6f0c208976dc39290b684b16 | 1 + .../6ffb4a945d04f8b031049d6b6fa49f15f19568e5 | 1 + .../70103c6bfa6033fc750d73a791d50375a1b86fea | 1 + .../70294d4a0a0438dea998f982369933dacc66aacd | 1 + .../708f0996354e7df20b2aef4b10bc9586dcaa5db0 | 1 + .../70c7802de56e11939701cba269f74c5c54434e61 | 1 + .../70cd3f4760a280eac2806e6373034a5e750cb013 | 1 + .../70e123fe2099ae69883a84234ee7d2c67ffae902 | 1 + .../70f98e7683065de833f78e968b12a17560c6d145 | 1 + .../7125c24e3079aa7ecd8a075096657aa41cbf32aa | 1 + .../712c593d655c49212ff38704eff4d5d68d14506d | 1 + .../713565a78c4f0eefe92a042e831427511dd4f5b9 | 1 + .../715cf3f1edec8508d34687cba9eb9735c4113fc8 | 1 + .../716e9a2309a2d14f0b54d759df166270321962ca | 1 + .../71807ffa82a2c8190651c69c857cb71bcb08e301 | 1 + .../71a2de6544779c774612b1f87277375ae9792a62 | 1 + .../71d2976410e52b3891d47b0bf5daf36223655072 | 1 + .../71d3d5be815413f81a15e1f21d82fa46ce4eeab9 | 1 + .../71ea7e6e573f89e2a23138bfbd547d888bdb7c55 | 1 + .../71f13e97734a6166d08d71982621f3785ea5ae3d | 1 + .../7217d80b5053a43d6fb6822470d12e76b42b2764 | 1 + .../7222bfdff7231c2aa5afe88a9b8860e057c947b7 | 1 + .../722914ef8c3dfacc1243877cf6bc0be5cc3eb6c2 | 1 + .../7275e47aff6a2c0f8bacb56d065aaba591e02a30 | 1 + .../72790cb9d6895411ac13e44b9be62c5cb05584e7 | 1 + .../7282e73fa9d18fc99fa2f10c51211fe1079693fe | 1 + .../72893e972bd42b8697f75e7ac80c8885bf7c3a45 | 1 + .../728c6175ed68889cfe3f359471f509fd1da1623a | 1 + .../729abe2b4cc9df53668a78ea8236ae421f3b5173 | 1 + .../729bc90d92d1235d6d3bc4c56bfc5a7cb1532e39 | 1 + .../72a19edf12311bc49d7e72f4ce0d25f68b5ba472 | 1 + .../72b351e21f164a536ef913cda1b95716c0de23ce | 1 + .../72b831f893332ad3733b0af04ea0e76cac65b5dc | 1 + .../72bd024e4b285894458f234b460fcaf90e8445cb | 1 + .../72de723051c80828a6318b2251cdaf29db2600f1 | 1 + .../72e0280dc174679a75da3799cbb41ffe349f9f46 | 1 + .../72f423c06f55b024fcd60e3acd20f596205615ab | 1 + .../73319dedec7db18100aca1acbdf582d38ed80c64 | 1 + .../733a381bc9e56cec2e4a856413e56d0bb7972662 | 1 + .../734891576e6360feb0a79e5f6326f4a0f3310853 | 1 + .../73617507f1dbe680e93caaef1d078ac92ad846ba | 1 + .../739b15f40bb87a9e4f1a8399ce654d068bd0d30b | 1 + .../739c724fbc1d946d981066a3f82cfb09a034ba1f | 1 + .../73a2aaa511c3c79634f98183fed1aa515112c30c | 1 + .../73ee1a7d0acd1f7e6a29e2cc9de52adf757c34f3 | 1 + .../74033d1959e62921897648eae99b7576a518dcbb | 1 + .../74068e2edea30ca07fc3d6536b7beb1e73610c5e | 1 + .../74077dff1318da9fbe3c8ecbcf570fa2b161a310 | 1 + .../742166e63d37f163f9bfa53c3d1ca1c432028519 | 1 + .../742c9cda5fd595f2f4acc988670128b67aa2cce0 | 1 + .../743bd395e890e120441210e9d92579d0c7fd94d9 | 1 + .../74433925d2da6bb3c3edcc954a98eca9eeb57abd | 1 + .../746569f919dd66a45ca13b1e18824a0afdb22d9e | 1 + .../74685cb831119333da8b5a7c83e055eedbef944e | 1 + .../7482f850ee397dd25bd1687e64b7eea626e9c608 | 1 + .../748b5f0d6e2f9fa4665f7445654524ae50ffc8ad | 1 + .../748ece6f6568749de6856f4e101f00d04a22d979 | 1 + .../74965c4ae1074a7c5d80f0889dda62db64f0d7d3 | 1 + .../74b0040c6bed65b152921df24d1d78125695306f | 1 + .../74ba2f22626f43b6a2563b0cb35c620433682d40 | 1 + .../74dba0abfcd70931e9e189f44c9fe76cb1cdbb0a | 1 + .../74e0dd99e051486e796a28c6482f0b52f0af67a1 | 1 + .../75255d425818aa4e45fa7a8ce30896b30e5f57bf | 1 + .../75362838d1ed152f60dc3cb74924d167c1b0fd2b | 1 + .../7559c841c04c474bc9ff45fe8504abb5d4e8f57d | 1 + .../757adad4f7dd459070f4f1b1f4f4f2374a57ec6c | 1 + .../75ed237efa308c478c8ee1faa516c94e45f17495 | 1 + .../75f1856401af3c6957b627bba156ed076e49ef5a | 1 + .../762487d62765bf58b6c712ce69edfc2a9d91f23c | 1 + .../767dc9730435e95ff0446a5e08a10843c28b5e4d | 1 + .../76967f9679742d07c45801b75cdb5ec88f3ea2e6 | 1 + .../7697ccd8a0cbc267875cf87e7ce982f8dbffa82b | 1 + .../769cf64713d5676b0d7823f406502b750f29f48a | 1 + .../76adb95f40dd46b0cd442f82b7eb70ed237f1676 | 1 + .../76ba7be2b975f49a68b47d255757883a4fe65358 | 1 + .../76bc86d13bce32da92769372e37076c675520959 | 1 + .../76c17c551bd5e5ae2efbb26f2e05d12c9c8181b3 | 1 + .../76c565f5646ff08d8c740ffe4cf133d9c8a3fe65 | 1 + .../76f5c55837a53eb0781baf11e0de07184a6d08ee | 1 + .../76f83799d26fbfe8607158f4718d6f5cfdc8621b | 1 + .../7705fd1f70110abbefb84b8bb3679338dc85008b | 1 + .../7722142222386c62ee3cf0d244202e77b759f34b | 1 + .../77258dc253bbfcab9ac3a990bda4f20592f9c651 | 1 + .../7726ec0c41e3e97e7d617065e6504efb8f024cd4 | 1 + .../773d0e073333f130bcff75d37d1111faaebee058 | 1 + .../774784914f2077e1681344cb01340a934be26ba4 | 1 + .../77907cfa0df9ad35b28a28dc974519599031d5b7 | 1 + .../77a416c6802644089ebc937712578c64cd114e2e | 1 + .../77b1d215fef8b044b5354a64c3541f96a5eed3ef | 1 + .../77bc35d370a04908ca4a6126a011623e2b09442d | 1 + .../77d0cc6e1223f82ea66b45b7eefc97601034b9bb | 1 + .../77faf5783504d2bd51c625bcecb48b8f87e8e165 | 1 + .../78251c5d9b329e36203639010c03798c0e1dcf20 | 1 + .../78536c856a97d639ec3c9e87656c03a486180cb2 | 1 + .../78a8516593c8bad79e4092b1b3fc0a850a266c4e | 1 + .../78a85c295a5f5c62f56d7eba74225f31406a0b51 | 1 + .../78aa0f27c839d5f0b6120545131237373c9ae941 | 1 + .../78bb53d71409ce127d2a0ea2bb3fe8ab857c3db0 | 1 + .../78f579fb1bbed4948a321bcad1a70116b995076e | 1 + .../7929ee70089306f9173670db39ef247d71e6d01c | 1 + .../79348dfc973141bd7bee5f470ac28ffd56e6591c | 1 + .../794d2929ccd4a9f38151fa274b7bba0a898aa30c | 1 + .../79693f140367ae963c396d7952f2b07e3e603755 | 1 + .../7988534604fb11aa559428f200cd7631d266dcdc | 1 + .../7993ab06fc93824943100f468b83a388dc8396fc | 1 + .../79a78205700940deac5a3af06b37f7a837ba5d0c | 1 + .../79dcbe312ec0cae55271acea3fbcad77eb51a258 | 1 + .../79ed5f67b23082b621f1d3d307cbb3833df70b36 | 1 + .../79ee5f66d93ee0d29f8b42ccf65fc760525867d6 | 1 + .../7a043102c33d83ed36e9879386a6e618668535d9 | 1 + .../7a111af866866f2de4ef478fd546fb1c0fc25d0a | 1 + .../7a1820d857c8a49a2db73ca33ae771ff2942dccf | 1 + .../7a490995df2d5f17d023de70297a3ccd20b7e9f0 | 1 + .../7a4a6b8236fc89f7d9e11728eab5f34c87b831ca | 1 + .../7a59b37e047189062f0abaf0d629290ecfb35f75 | 1 + .../7a69a216cc5a6c99a19546872d16973b864b8ec6 | 1 + .../7a6afdaaff4560a33eba5ebd9df662b110b72dc2 | 1 + .../7a87119e2369843226572e9e9603e14022ad565d | 1 + .../7aa3606e89e98945870fd6072bc248da2ac00194 | 1 + .../7ab6a9ca3af298309556e392c5a2145121ecad20 | 1 + .../7ac66a26b371216e55464bd620f00f9b3cabf539 | 1 + .../7adcfb6ec993d4f55872e19410191727163f6958 | 1 + .../7ae9dff22041f4c1fe093655030d83341a775789 | 1 + .../7b1eb9664a41baa7f5e742f91eba9581bd509407 | 1 + .../7b242c6392ed925c411f5a03c01a5b224498873d | 1 + .../7b302c63a0c095634d5b99d885e31d50d348915f | 1 + .../7b385bf3549519df825d01ede2e8d9864af0d4f1 | 1 + .../7b8328e1cf64ee86aed185c42ef2d58842a86505 | 1 + .../7b9f95b7241f7c9902e959452e13b67e26806ad6 | 1 + .../7ba72ec40b0c475f5d75c1845b6a75ce8fa2c003 | 1 + .../7bcb414301b9d095183f9b852a0c948309483542 | 1 + .../7bd191b72e7ea5e8407c5a81557fb3489574834c | 1 + .../7c0066094d3af7d6ae9649b1e0d8c4f65d29d5b7 | 1 + .../7c3defc5ef17cddbacd31b76689e0f6d0737ac57 | 1 + .../7c7017c2b46f27580791e590ff2536195830225d | 1 + .../7c7b7ccbaea2f13ad6524f8a286a5a8e5de67e21 | 1 + .../7c81f44f5bced662dae488456a190a2b5b68c852 | 1 + .../7cc6f39aa5cdd7a9af8b06f6627638b3bb770f40 | 1 + .../7cfcff79af9057d0133f2b5da206b608722bd025 | 1 + .../7d568d459cf98a02f42d26cf7a40def28f45c07c | 1 + .../7d77c20b635f8d363cafef80ce333359495fddeb | 1 + .../7dbdb91634696f23cadac0af049ca2841cbf75df | 1 + .../7dca132115921f6d0134e317bc0c5b2e5b97934d | 1 + .../7dd14622cf7fe1695e710f01b45d90250043dea6 | 1 + .../7ddf0e4fc007dcceddccc60c7634ce32af1c1782 | 1 + .../7de80c1c4a6415b28404560b4e476f7ff798b292 | 1 + .../7e165223d7af3c0a9b55423a23a84315b3549c34 | 1 + .../7e2b8b5d88ab86a02660c9f930b1dc7bc915500f | 1 + .../7e2f0de68af4544f103e74bd384b74b2e2f85241 | 1 + .../7e4029c06ed03535d5f51420d860c7da16cc155e | 1 + .../7e70e8a2a78ad2b7e350dc4a07651a5bf027cb57 | 1 + .../7e874b33beab6c09e8cdbcdcf34c226d959f53a7 | 1 + .../7e926dc258ef73747c6dee6961a01976f75e194f | 1 + .../7e952aa0d4d919ea11291440bf1f5548858938d6 | 1 + .../7e95b122591089fda778a2dbd434c55672c92346 | 1 + .../7eaf9980118567289bdc91759abbffb031b64227 | 1 + .../7eca413996ccecf266e5bf306d63db50903b1ec0 | 1 + .../7eeec8eac2847cfc829b4f04a7732871fa5b33bb | 1 + .../7f31dda7857641eb43ac8f245109af960b934c86 | 1 + .../7f36ff093686c198384796967779e512b39b0067 | 1 + .../7f37fc6f46dfd2056c23dce7388e996b2e007166 | 1 + .../7f5fb097a29a27b116140b9366006e578d1139ce | 1 + .../7f6b5c7e454d101b3d586c7653b251e1aaa8404d | 1 + .../7f76a08aef5329137e1c80a8f4fc7245375849d9 | 1 + .../7f7be6c8663be7951320cb6c651781e5583ed65e | 1 + .../7f8f81d1bf5547aca3adaba322cccf59977c80b0 | 1 + .../7f9d1a52ba029c7f6e88ff84575df1fcb1075619 | 1 + .../7fc1bf414713fa9f80c252358021f9f97b15c792 | 1 + .../7fdcc6c41ae23f27834e5e1303ac7e3a7a01c43f | 1 + .../801315c10fe0fcc26c0c57bc8f631cd93596168d | 1 + .../80333b40950b8f22b44ba7c383dc625b1b094df3 | 1 + .../80376b2b822b9baaef72428ca022d2e8ad5fab95 | 1 + .../803cd5f12d095d218780ad627b0b82b0bab86370 | 1 + .../8046cd7645e89a0fda7d8f8378e8425fefabb6e8 | 1 + .../804b90af698434a3596956677aba5a5f73dbaed0 | 1 + .../808bb1522f5aa5de2dee150c5fe9b2240c76f14e | 1 + .../809f182745ce2d04f2ed1126bbd41c71d290955e | 1 + .../80b5c3a4f3efc732cfad5a798289e246619f8977 | 1 + .../80b9b953d5d211827d5046ddef05778d9e6fe889 | 1 + .../80ce5e7fb2b5a1cf0cf9bb4b9a786e4bf6735056 | 1 + .../80d98df3c15079be160fd7897dc74ef9a9b4774b | 1 + .../80dfc8a9fc0fe40ea7577dfd42a34b367905756e | 1 + .../80ed8061d1dc94f53f2e897f7421f7e7109037ef | 1 + .../8114bd4cff1787b06e5836915e62486478f693d1 | 1 + .../8114ee0d2c07fd933798fcf7febf9e08b6cf1043 | 1 + .../813b01314937089f22d1d64ac7030c5da92ac36d | 1 + .../814755d13f451119bbd6e341778fcca05d023f99 | 1 + .../8152fa388ef907459fca58c6382e7cf481e8b03f | 1 + .../816316a3b73af9b70141fff8b2deda8269d38d34 | 1 + .../81639ecf4a65a0d2972d186cbca46aa48c408a2b | 1 + .../817d2dc89f753f1b403cbbdd6c078eeee50563d1 | 1 + .../81873f88c2fbdb0a58e15e3492b63cb1eeebd61d | 1 + .../818a1e4250991ce3f414e0f7215308cf2f23f7fd | 1 + .../82050e725b7ee8e6090dcb98775499dc19017c4d | 1 + .../826b8362320fe6f06ab5a2f4b4fbf5c94448170f | 1 + .../8283d17b50ed5619f147c5b35a8f94626b7d5b26 | 1 + .../829c3ad6c8ab04d87634c91b6fcd79faa92656fb | 1 + .../82a84993b98a8fb62799914dc21be4be700e7b5d | 1 + .../82e6db8a76fd387b0eb64cb1d7bf968ef761fb96 | 1 + .../82ec131b824b4c3f3757e1edd238735d0656fc37 | 1 + .../8336cc9fb782ee91ec2fca64631271cf0078de20 | 1 + .../833a14196d27bc959251f1d19b9e4e6829d267d5 | 1 + .../8366f34c8cc56c4971befa8d4905f0f436bf6cda | 1 + .../8393e8cc899fa71d1c638c5cb8eea55c40342700 | 1 + .../83945bfa970aa433de420b7ac4f4efcc297ec972 | 1 + .../83970d72a6907256d4feab8e061182642c3d4b24 | 1 + .../83b00e365af084f70ba64981a783c5ec81c0e650 | 1 + .../8434ef7375003e0e049d9248cca04a7d89a51736 | 1 + .../8442ffd276255dd9c5995c977f30f700234f866f | 1 + .../8462f1863bdba9f38df24dbeb39d9be31a8b3d93 | 1 + .../8478b1cc13202df27bd080e55410e541629423e8 | 1 + .../847ca904186295e8fd47a4e29885615907cb992e | 1 + .../847d38e6322523b12583cde1ac03aa9cb6c11494 | 1 + .../8485b7daa7b9582b7257e4ad6aa767ad9b2c7173 | 1 + .../848ef68b2028c2d1d2c774427baef8811e6973c6 | 1 + .../84b78b9ad073a948405f0b7ab62f9f69118ba8f0 | 1 + .../84c54f3da6a5e6fab8e1f0e9e437a602b838b808 | 1 + .../84d1cf1063766590aee538d2b55b7bd3698c0de7 | 1 + .../84dce9fa92c533d455e0c1f97179960220f0a855 | 1 + .../84f74ecd7dcd980cbe8f5c5df3e9de9eb9e2198b | 1 + .../855137df77e723cfc86499f4fdb99f284ce7dfb2 | 1 + .../857a099c2b46ccc02b866b3d0c0eb37858af7f6b | 1 + .../857c4d2b4cbe976e614059e4d9eeb613c69a523b | 1 + .../858fcb46fd11dfff505511ab32c43de93cb923ab | 1 + .../8592c80000cf304bf52753ab309ceb04e2652ec5 | 1 + .../859bf525139277f5088a3ce814f120ba25928ba7 | 1 + .../85c3b1c5bc8469eb9f51ee2b19c514d2dcc9d4e5 | 1 + .../85c9ddc38fbb85bd175bf3ac00a626752b964461 | 1 + .../85cd37fe2c7301fdbdedfe4eee2559a27232c9e1 | 1 + .../85db7ff2b922cfebbf367553f67005a39f7c7481 | 1 + .../85f392952d2f71a976ea2c35e174e534ade34805 | 1 + .../863c74afe345aa2460edf06abd9aa101ade521bf | 1 + .../8641c37d6051843e6ca2af00b13ec220650722d5 | 1 + .../86808a5b2f495881fed3418379a96faec86f72a3 | 1 + .../869a1712bd79edfc9d95461a25217f1b4b203e29 | 1 + .../869e9e9fd462fca683f8b432da94616198c8eb41 | 1 + .../86e9313b4a88cc4785b502796f36bd97f1174856 | 1 + .../871647145b6c79309648164fe2e9294d7ba23b0b | 1 + .../871b6052e7f9a98779e47518bd5f8bf607a0e268 | 1 + .../87360adcbd85bcb0816fa5f993fc9a5e14182074 | 1 + .../874116a3fba0e5b88378c9825e5b2cd8fe9707c6 | 1 + .../874498dbd2d21fb6b01edf60814088feb89dc02e | 1 + .../874b8f129a3df7a4c057a29c6d71bfa99137ed88 | 1 + .../874c302461e364f71a8f6570728f98611a5c96ce | 1 + .../8753f414b84b9ccd0c62553961f88f7c0264c379 | 1 + .../8768655b2d8b6e0cca092c104735354aee0c9b0a | 1 + .../87d794de1dead52b89760fa5e136596c5b59bc40 | 1 + .../87dcc971a3beea2e91a4d7e9643a5539ff94d52f | 1 + .../87e1e382d129600c7e7f842f983fa6e87de06c9c | 1 + .../87f0c2e540270b3692ef13bc2b91234c893bea37 | 1 + .../87f8602bd7dcfb5af1052f424e7403550ff631de | 1 + .../87ffa0846cd9a6bebb41a9d3d719ba376c69285f | 1 + .../880f03671efb6dcc3f3fdaae9491625f46f6e4ac | 1 + .../8829fdc647553393e0d223a098067bdf44dd2c3e | 1 + .../882c32949367f4f504b543399fa13b4f4118344d | 1 + .../884b9c73958e305260b7aa5b9969660166f550c3 | 1 + .../885db56c9eb82324c5a0f7e7aebd3d215505a5d3 | 1 + .../88684adb319365b522f644e785033cac77380e06 | 1 + .../88797c1357072ec5f6d7a77f8f554fdf14935742 | 1 + .../88d3c033edc04d341651610ce654caab89f0c589 | 1 + .../88e2041ce84c5a5fd2b056669856844691b520a5 | 1 + .../88e2266275388545e1f8f54b8fdbe89bbac43274 | 1 + .../88ec99f421c2381e497fe2fc13b4f6dd8e8786d1 | 1 + .../88f24d3d0ee361f07b6a968b39726f1326ec9166 | 1 + .../89063488083093835287b1f9c18b2a7944664176 | 1 + .../892cc3023c1245c75dd88475a0e49fe4d5063dd9 | 1 + .../8951f7b39335a2e501908ed76548372ea5979b19 | 1 + .../895da8e67657010ab55eddf2b5e50156498f59c1 | 1 + .../89843a3d7b0d8895dac3541e10e30e0400dc0f5e | 1 + .../899da8e446fd56d043e8d9fbd5821c09500c8654 | 1 + .../89c130024a3230c8800c10efba7110244146ea67 | 1 + .../89d3b93983fbc2ea121d1407d7944b74f44c67ae | 1 + .../89db7a1ad6220b1635de9734c32a76ab69bb70e3 | 1 + .../89df1562d15e81161f4c47827c0802d44a116dcd | 1 + .../89e008ea516ef46108ee4b85055e4cba034e75c2 | 1 + .../89fa19afc7b932f3749a095009d1bf1c6162c607 | 1 + .../8a0a41ec1bffbaf105b7b5b3784d680d00446960 | 1 + .../8a0ad7fc3cf79a721233622b6ae7a4bfc52c228a | 1 + .../8a2775fc1b4fdf627698087dbc89fc1a3b0943be | 1 + .../8a289fe11f09a8013015d4bdd383c4d26de1f483 | 1 + .../8a29d68c4034560207bd08a36c47e26953bebe3f | 1 + .../8a3477e0575b2a93269f750c0395201cd0f19a37 | 1 + .../8a3c9306c70ceb610d6f1f738df6679eabff4238 | 1 + .../8a52da0771f3d868955501e901d2540538f4d521 | 1 + .../8a7bd56f4854fd39ca2b9dac03cf4e4f92a1b93d | 1 + .../8a8928f98f7dd800744cfcdbefeff96b97543b76 | 1 + .../8a95cc474b746e69625f0fe8c262c07a37a82a7d | 1 + .../8ab6f611cd721ca128cb8f5ea3078c1b431d5704 | 1 + .../8abdd04f7c724f0a762d03fb6fb80e698280ae9c | 1 + .../8b08333db48411d829619458a66585a39efcbb11 | 1 + .../8b2cadafb5c90652623fe20f1da4fa65454b1764 | 1 + .../8b379a5db43a90e8d77da62355f3ac86f95b1422 | 1 + .../8b436810adfe76e9f0a84f1a2382284cefc4128a | 1 + .../8b4a8862bbb6306cc7b4473bba476bcaf6383aee | 1 + .../8b5c3d67f71726b53372b58a37b41fce4a30a5ac | 1 + .../8b5c7dbd04ac3065bf6c8164f3068ebc910ddc30 | 1 + .../8b714927de7515d6467407861bea2d1b6816f769 | 1 + .../8b7781da37cae546b0800cc96db74dfb1988fa5d | 1 + .../8b8235aeb63d5111ff81b6406893e2c114f3d163 | 1 + .../8b926866858180ba6c9e1a87ace930fdf129b59b | 1 + .../8b9de640b20beae0f41a3d88dacf8e7c8c00e4a9 | 1 + .../8babec8da5a26469095793b097811d07f256a5e9 | 1 + .../8c4cbb21d02e5d466fb2539022255760626149f2 | 1 + .../8c504464b5b4239a47fd8d4b185c3e0e1b6c1af0 | 1 + .../8c716ab740c917b4df170efbc22b4e47873d8e3d | 1 + .../8c7dc16b0e4c9ef242cc7ca7264ea3a4cb62a9bd | 1 + .../8c87d28e9f82d8cb2da362853cbfd7f6ed73becd | 1 + .../8cac7b8d77d23a0085a03a673ee2021520fbabea | 1 + .../8cd544fbd46d49e76648955888fc3047bf5e24bc | 1 + .../8cde25f4590bc7a0cb88896228ad8d28ecb9641a | 1 + .../8cf7c389a03e6d9d8cdd4dc0ee8615f54cccd395 | 1 + .../8cfbcd30e59e458884ca65687215ef8a39fa420b | 1 + .../8d2e1d4e20c8a37b8483b0636a53106414b2e098 | 1 + .../8d84c17e2d2a5f1b483ec417d4084cff8a83bd8b | 1 + .../8dad5eca9780e98722de60bdf4209e99730b7ce0 | 1 + .../8db878b9f4d8758552ba375e70b1c319d8ca0248 | 1 + .../8dceab2924460f1a418835afa3ff5d4bde00914a | 1 + .../8dd1413b2a30d480170c4918b00b9b7abe7ae2c6 | 1 + .../8de4d54ede6f78c61866173f8b1096d7f5e3f478 | 1 + .../8e0a71d16611cdac906bb4dece9fbf87d1a0fc8b | 1 + .../8e1a1f4379046e33058d6b3df5184a181b98a2b5 | 1 + .../8e38afa0e7c920bbb4aec155f70d1940028204ee | 1 + .../8ea1e2b4445b668065a333641c17f3c6038f2f27 | 1 + .../8eb143cfc057b1ffa8e90069a1d1ff91a90ac794 | 1 + .../8ebc6173196e2c3ad4ea6d665b4893fd67690d70 | 1 + .../8ee6b6a7957bf8ed03aa4b95dbc232e5ba56ead5 | 1 + .../8ef96afc00349b4248ec31f4755d1020b7fdda03 | 1 + .../8f07475a5f9d43a948b3b96452aea50918e4b9b7 | 1 + .../8f0862b153c849b8d035fa189f7ec654f8b3e862 | 1 + .../8f0aa9d861c14d5c32d60092ba04c2253666c4c5 | 1 + .../8f4ba01ca74a466747b89a116a26047e58536ef9 | 1 + .../8f56d7ddb9c736b9c89113453c379ec0a21341f9 | 1 + .../8f7ed4f89eb5a042d9a19a78e61c47e5c984a9fa | 1 + .../8f94c8c6a37bcc91d7a39416023f9d78ff08129a | 1 + .../8fc0dcb82f3f88e6c20e123adddbce9afa79dd7e | 1 + .../901261518c53841cdeb55041f748183f25fbdb6f | 1 + .../9014cd1a175ea66532264c818ac4692ed805357f | 1 + .../902fc67f6a0dd7c17809ac0002972da218f32b8c | 1 + .../90439abb1bce7df95926ac69fbe35e9a75849704 | 1 + .../906de10a0641d6cd4c0dd422fe885c2f9691128a | 1 + .../9076f59736d1a417df0e4e53465ba7f80da49859 | 1 + .../909f04b9af20cf2cb275ec1cf722f9a40b234fdf | 1 + .../90b75e22907115340a987929a776f6f3bea1d9b5 | 1 + .../90cddd59c8cf3bcac6b2fb6df29c9362c3a69855 | 1 + .../90e012902ea03831fe652fb98c2f284c57217115 | 1 + .../910480b0cfba5cfd886687f687f8a73d081c0b15 | 1 + .../9143eec00e7c0dcba52a44c54c7fea4ca90ac9db | 1 + .../914d626c074a269b3a9d1451d77761c9b6e8db28 | 1 + .../91b3598a2ceedd0e45722fd9287672a13bf221e1 | 1 + .../91deadec3dc6c425ddc903b195066184526341bb | 1 + .../91eb11de4a9b1c364da7e342da879d0915930da6 | 1 + .../91ed8c8f6952e9dfd27a3d45454432bd4886c8d1 | 1 + .../91f11c0a3851e5a1b473cfd412ff28fcd7903c39 | 1 + .../91f5456cb58ea9371b0fc9864e05767c7a8ee7e4 | 1 + .../921d11cbd9a6ba01c1bbfcc40c1205f6ef275acb | 1 + .../9238fc472251c9a3c817ab6cc5ea4e97c3d05410 | 1 + .../9250a8a685e1f24b96edf202f1204a332bcb0ba3 | 1 + .../9266cfa0d3adb02eaa15bc09db296fa853d6deed | 1 + .../92848420c5779bd1c6d954bfc933383296c73c07 | 1 + .../92886f1a44cabcf2e2c4dcef68ee37caa458c47b | 1 + .../9289711f9cf1406a577387a27b8bd4930e29fd38 | 1 + .../92bddaa4b62dfceaf980ba7a89bb0cc57e8fc52c | 1 + .../92c132ca1fe8044c1317c18feaca645a54713ffb | 1 + .../92e0a98f523af81899be75f9371608fd9948b337 | 1 + .../9309be25161f4e02117ef32870ded9650d0e4f7a | 1 + .../930d453e2c53ce2b64bd0f4b950552f988bdbc20 | 1 + .../934c8ad33d4e9c5c13372bc93bf26cf3107839a5 | 1 + .../935a6ed5b994d0bfdaf42bf6dd6fef4ccdbfee4a | 1 + .../935dfd118a575d599a75b00db37955c92ef6471b | 1 + .../936af0357943e249bd7e428753fc79b7870c4f96 | 1 + .../937fe4be2d5689c59d7c617e65996d41cfafdef5 | 1 + .../938f94084baf3b93faae268cc5e094df56f01f7a | 1 + .../939a2a924292c7f549cc8f8be939826a3de6b820 | 1 + .../93aa13626c3895c12d82d3763e8e916a16a4fd52 | 1 + .../93c0123f1118e26a15aba5739d9f8db784f21efa | 1 + .../93c6f793e89f2bbe200dcd083729e8e2af40c2f2 | 1 + .../93c799f74d4e3a3b8dafa975cb2453af687a8872 | 1 + .../93cedb385de6371ec85a3086d53c93ba0e1c6926 | 1 + .../93d43e9d7f08eba5daa4d394a95703498c7e2139 | 1 + .../93db6d7b5e262a03c9f6ccf71ef4e8de7acf6fb6 | 1 + .../940254cd6f8f945bc5f1edcef83ba2afc7edfdef | 1 + .../94136714739c4978945621f669ecaf025dff07f8 | 1 + .../942302c74767926cf73be9bc6753fc422157855d | 1 + .../94232b6796277453192019999be8b0fce849e3c3 | 1 + .../944304c86610b738afbff55026632249b735f401 | 1 + .../9447c6b9ffec17e55cc04961dec9cc9affec21dc | 1 + .../94862fb03e48c18301c8d883c0b89da06351e369 | 1 + .../948c81d5b83d1cdb3423d9e81a61becd8bf2a7bf | 1 + .../9499a40681e896adc4c45047502a358ed7cf1237 | 1 + .../94a9f7a609640945c820b281c9b05d992b0ac4c2 | 1 + .../94f8b89ee92aa4c7d64eb59fa7c8811ee71c5de1 | 1 + .../9506e2eb82ae6c5a245403a82c8c36c49e7dd19a | 1 + .../9512c13d6e0d292adb68e6b0ed8f466ba396e30a | 1 + .../95285e78757c883cf8644bfcd7749e4b08cb59c4 | 1 + .../9528c094e6823258fc43686ee4fdc5d619021a94 | 1 + .../95418ddbd4a17ea011fd39c57c1e4389b711dd7e | 1 + .../954e0aead2f1448d168416547f795dc8baa7eb10 | 1 + .../958966b97201943c2831502b3f5bbcccc2d1b2f3 | 1 + .../95957430f0fd0b98963bf7080efffaa2efc45563 | 1 + .../959b1c7bccd9efde5105f9deaa24262e6171f127 | 1 + .../959ef5c1dfba6621fcd8365261b27885ba0eedfb | 1 + .../95a04b0c50967b773d91751126d1ffe273287347 | 1 + .../95afe9b1e8db35a5924aabbffc0a617e6862a1d3 | 1 + .../95b65f78191ad63ba2149f216ad4b1f3a404ee82 | 1 + .../95bc7b2db1ac665317576e24031e551189f4efe7 | 1 + .../95da825d4132e9de80a280c89ba82724643b74f2 | 1 + .../95e7d15b24fad0c2e4780004a45b735813a6d457 | 1 + .../96089d3e37c85cc3e1727b58cbcd209157529a71 | 1 + .../96197c6b417cdc946b9a34b57ac7c50feea0ada4 | 1 + .../962bb09ab095bcd35f7f34055ed0fa8ae434af02 | 1 + .../962d79802cab79d4bd0c5d840a5f94281465c290 | 1 + .../966f41ea0609c64925ecaee5ba1af166ae43fdda | 1 + .../96735cbde31cd1fbca452de029d3f77a7072dd87 | 1 + .../967784fbda80e2586d2566b1d20422c209de8e3a | 1 + .../968b512c074558ddde3b21c60e2886fd579c950b | 1 + .../96a0422936b6ca5c4077e1e8fceea23c5dd146fe | 1 + .../96aac36c65d79125e3ee07ec601f71c0c09b0cb2 | 1 + .../96c1bbeb23affbc8ce9c5703062a448e21a42eeb | 1 + .../96f5f4a5b64b8e8462a72eb1d259066fce9fbe2f | 1 + .../9700352a9f17c39165256df2f2f7e4fa2ec9de61 | 1 + .../9749e874bbbae2a0dce118ef7501ad135ea6cddc | 1 + .../975509735c405d7f26b8bd4c00a32158c4f2911b | 1 + .../976fab0e9af7ab44ebc738f13b377d23ab763465 | 1 + .../97703896dfbc748c76753b9dc807252baa7d17ab | 1 + .../978c3a312999502111000de7dfe47b35516164f4 | 1 + .../97aba204ef02b37a3627221d61d8e55c8a4e1c89 | 1 + .../97cc85297ae928c35b606a80f058ab18ea5187d1 | 1 + .../97f61b6d98c9ffe5ca701f864969608db86c81fe | 1 + .../982a43466eb400711eaa92486fd3a9b22d4ed22c | 1 + .../984d407c9a0781d661b22c64ad915a555d3bf64d | 1 + .../98500d46f789f6e67f2c3e2f6af290db2fc124cd | 1 + .../9886f8415dd6095f89ff7e519af7516c9b7dc352 | 1 + .../98bd202ec6667081b4a70e2f6b929af634ac6d68 | 1 + .../98c6e09cd9cdc3967e01f4842102de38d4cda1a9 | 1 + .../98c83bcdb5956bb94639dc29099871c76564d6bf | 1 + .../98d122b2f88e6c5326c77b7a643d054909d0e33a | 1 + .../98d39d50572a07ce2b34b997b11f0801efe034d0 | 1 + .../98e6557609649d2edfa5303dc85da6929b3e46cb | 1 + .../990480b357aeb905cfea6ff646718d101978e980 | 1 + .../990924cc189ea41b110bc4dd575460c49374f23d | 1 + .../99621f82461534b8907da50ed4c7020620244c46 | 1 + .../996fd99ab96f9643d5e5713a831995b17e7a3d6a | 1 + .../99d1d11e7c7797862b2f093aecd2482708213a46 | 1 + .../99dec7b1a061c754594c315d70173856ee38ca53 | 1 + .../99e6e3dc68bf0e9973d9cda82f1300e98c4d58a0 | 1 + .../99e8319b516c140aa7badd1e9ef03d1ff1c3bee0 | 1 + .../9a11c2fda7b9c43e2b7720bd72c00e2503c9dd88 | 1 + .../9a309f12e7243094d23099f5433d19602252797b | 1 + .../9a89b6f3139174829b27ab6ead21acbf001ee2be | 1 + .../9abdf13e2635797e12d342e2dfb31a9c80d0edd9 | 1 + .../9adf5a63b8158c84d6bc327d0b1ac1b5964a3ac4 | 1 + .../9ae58507a65058e0fe31de871c7a34bab5415ae9 | 1 + .../9aece0f0260af3664b7ed391226bcf127e9fd163 | 1 + .../9af8af68c2f18bca7d94dd8b48ce8692c89ffb04 | 1 + .../9afe6dae1af7cdc07ef615de0c3d2ebdd4f68c15 | 1 + .../9b42d222b18945ea05823e8a6dbcb0d54a364700 | 1 + .../9b4d35c34d31ab2b9e6a0becef710c9b00ec976c | 1 + .../9b51c6d0b56ce78a3dd7924a0c74626beea4b529 | 1 + .../9b62911307d4c57e65b67719613737ad5d45433f | 1 + .../9ba6a6cf62c5826ffc6fcd084371c29d51f194c7 | 1 + .../9baed9539fb0ad3446fb36b9804e562244aec18f | 1 + .../9bb0ba96392a718e713162631e2036c2a0708ce2 | 1 + .../9bb98651acde18815c952146548c472023a22072 | 1 + .../9bbe3f1ede4caaf74b619e6e82cb6b6f779f366d | 1 + .../9beb9170ecc8bc4e97002efea295cafc58d55688 | 1 + .../9c1a6591aef6efd4346aa9f750f87940a9783107 | 1 + .../9c3a7896381a924c326a82a884be65e632a9f190 | 1 + .../9ce105ac118fb5187b993ba8e83d9b199dc86fe9 | 1 + .../9ce973c4df052f54b32f61eb27b74cff377e6752 | 1 + .../9cf29382585d7d87b68e19e5244cd47ddedf35c0 | 1 + .../9cffb02f79fc72e41c0ac0b800b862fb39b0a7fd | 1 + .../9d13b7a6b273e9242c1092d047290e60291087da | 1 + .../9d2325335a737991316f3231a676fb415c357be8 | 1 + .../9d3dab224014b620dde2b56cee3fec23463cb909 | 1 + .../9d6211da7d3f0bda14d5067af27a1abd46dd187d | 1 + .../9d6647e7af1e10de1b3c608d829400e5663b3d7e | 1 + .../9d86f6cf43b5947de7d50f80fec0483a9072ee0a | 1 + .../9d8bf71616bca5ac31e24117c80dad52352d5c2a | 1 + .../9da24604599fa08b01181b48265429ebf1cb213a | 1 + .../9db297bad5b8a7a06f76713a5b05cdf2148f3b19 | 1 + .../9dc1141da1d44addec511e26f89d5046f97da2c6 | 1 + .../9de0c2afad49fa532a8fea5e4dad68a5f1ab8a22 | 1 + .../9de4c3db0a099c27c523988b4b750ce3ee2c0ffc | 1 + .../9e080c9060b0017ebfc6f81bd854014a8fc88ee8 | 1 + .../9e0885e261051e23c61d7b6859e9c25f16f9aa73 | 1 + .../9e533595a0cd03757f4ce00ca1a54a38453f6274 | 1 + .../9e7cd3ed8c99ea2f99c6c55da41e1a2e4c56fb9b | 1 + .../9e94137b564120169fc22f85678cc20df3a1128c | 1 + .../9ea50ae0758462d0e77fe1397a5af6f83ad15f39 | 1 + .../9eafe1e70dda380dee958b8ae1138ab758f76857 | 1 + .../9ee645ca92c85ae4515e7e01d35579bbc6cb046f | 1 + .../9efceb8b8d6841f20ca0f194b19427087f5a97ea | 1 + .../9f0427c58e85128c73cd97a9ba41519871d70331 | 1 + .../9f07a530e3bc65a6d0a8da0a8ad697b5dc9ab202 | 1 + .../9f0aaa42e73656b0fce8443aea84266d564470e9 | 1 + .../9f1fe443098130f838ce7d5c1460cdc0f13bb12e | 1 + .../9f282d2e013696b3d63d9269bf869f906bd8cef4 | 1 + .../9f78e819952e56d7b1961320d611fdc489b34e51 | 1 + .../9f9bfc59905231b990a2d55faaa21a4cf26c8781 | 1 + .../9fd2c2accbc395448a7b5d7d8bcafd190ce329a7 | 1 + .../9fda11dcb9654da892e82b6566c4aeab962c8278 | 1 + .../9fe5d577717a9a11e4740f29f231fa15b9f4d01c | 1 + .../a01b0232919914b0a33ff87262f8ba59543b0ab6 | 1 + .../a027f0c1c564bf78407eed47f2a9f03c60eadc02 | 1 + .../a0482c5ebc234aebacf836bed890b373827b5958 | 1 + .../a04e38678141417445359665f17e2c444cc55835 | 1 + .../a05131b921bd9d6b4ea47f249e51ee98efc05f54 | 1 + .../a080874cf108744cedfbb712de9629eed229ec49 | 1 + .../a086f46eaeca09d3649d592dc5a55044d8de1f41 | 1 + .../a0951cc6042b25d64914d945c4e3758a0407ea87 | 1 + .../a0c092d70e81d7131ac1cb03d9ac8db9d2c0709b | 1 + .../a0d64b88f7e1a35f28c08292725d25214520f7a6 | 1 + .../a1258cbda9cc624bb9f238882cc84253a1dc87c2 | 1 + .../a1430a0798548b8c620d89157e6f2a54d9f94f2e | 1 + .../a16835f468084695f51026fc26ce3f842fc97714 | 1 + .../a17272e8d29e6c955e3b27761ff0e3908e202ff1 | 1 + .../a175484c1508738494b7c85ab928bb65c4a07f42 | 1 + .../a17a5140033f84e309aac8415b2a580b4050203c | 1 + .../a1b572d1fe5a9c9111033297ae5ff70014c256ce | 1 + .../a1e666afd74df95cb5c06318730dff9116d6a22f | 1 + .../a1e97b7bd972796aecfd4b83180776a015f64a8e | 1 + .../a2124d0d2b17ee1f1e0998338eea25cffadf437c | 1 + .../a2135bcd7d491b07a72fbd501a3b0be1b9f3bdc2 | 1 + .../a21f2d7b6393cda8bcff8df7034062e8925f6377 | 1 + .../a2452fe77f45ef6a612ce676a6ad9d9002b9331e | 1 + .../a25b4431040ecd4aca97dad2844cf0080a40800b | 1 + .../a26f67d81684b9007a2109269de4afe49d23f938 | 1 + .../a293d31bc0cff7b14f873a325579ef283c8e2068 | 1 + .../a2a3d1e6a386b04424a390d174bdd394f0b88602 | 1 + .../a2ad73830bfcdf027adbf16721e9d3b54303b060 | 1 + .../a2c43c8aa3d41b7eab2ae20fb1f9e973802d902e | 1 + .../a2c7ad1b00fd60ced001c83967d4fb945e86a28a | 1 + .../a2ccb0337cf44bc0b3562bbf7dcdd792989d5faa | 1 + .../a2f70a0c20b111ca1ab34de6f2319109527a564e | 1 + .../a32041608e8afe0ca18b503f0e9c30cd1480f6e2 | 1 + .../a32cec9ef7fd885815ad4d76f8a45026473405b3 | 1 + .../a34ff67c5e9162f46fa22c082d21a7ac7a23c3a9 | 1 + .../a3770de2569e6bc576e5a3947ac08e8bbe24cb5b | 1 + .../a3823af6285ec27ac5824bddb591a1f209bc4018 | 1 + .../a38819d7d0147d7cfd3e537fe3756def5a12274d | 1 + .../a3ad36fa2c2c376afbf409d8fb83e076d6d87bac | 1 + .../a3af8000afdeacd1c3d6137959029e3b260c72ad | 1 + .../a3b21dcd0e4adb6a0ef920d74555d2f699917d39 | 1 + .../a3ce74eabac11a8d8a11955afa3ad09d86b22961 | 1 + .../a3d08eda208b96260cb5b47c1478e155264ff8c1 | 1 + .../a3e5f143cabf7cdb1f6111fd744b4230796b6064 | 1 + .../a42eb9002c5144273a55bdd736db4fde19aee488 | 1 + .../a446bc4e40187735edce2ecd8fcd0e7ed43952ee | 1 + .../a45d7d60a1eef620afd536f4d69cd4196a0fa6e8 | 1 + .../a460475c32082067af4eb3aca7203a69381aec6f | 1 + .../a47eeeeb9c724e0247b882207d4598df2b1f9db0 | 1 + .../a4b22b3869f32433a3caeafcc3e2dd92c010757d | 1 + .../a4b538f21947ef1c76087aab101911f7a2cd4ab0 | 1 + .../a4bb5997e547796263c8fda8ffb4c87967e2ea43 | 1 + .../a4c0daa47b25c77cdc37c485b2ddaf4db6edaac6 | 1 + .../a4d7bdb95ff0421ff9f027700815f81ebac50d03 | 1 + .../a4e49ce4052c6a3e72232ff2f764b972159ce65e | 1 + .../a4e87c35b253e9246a0bd98cbe936ecccbf2d89a | 1 + .../a4e89f79f42904ee1b600ddd79f2d3e27c855da0 | 1 + .../a4f449044130b59be750db18b3dd9cfd3bae5588 | 1 + .../a4f68b87043e04396cfebc9287c9d7280448eacb | 1 + .../a4faeb187eb7094b39e0f0699026cacbbb9d2ea7 | 1 + .../a4fb1b9f52700ffd6bf24f06e73666810b0e3260 | 1 + .../a506dd32985fc68730bdda9ec17bd68456455ba2 | 1 + .../a51dfad994645830ec06457aa99a3680c881234f | 1 + .../a52cb7e463be1bd639929b2d3988c313fb4189b5 | 1 + .../a545cc27e2d474a7a7b7ae974d6c61935d3bdfb6 | 1 + .../a547e004e80194fef36be8b3932bb2a42502c7b9 | 1 + .../a54e57e8c7e474bf56e54f46813916ef373a9d88 | 1 + .../a56763f3af3e1d367ff0097d69c129ed4bae7f00 | 1 + .../a5706ef86f9f5e79c7eb3a0ed8168f28bdc25f87 | 1 + .../a574eeebf64538810c2a45c5864f3209361e1c96 | 1 + .../a59cd78a997d502a498c2b597cda9c8cb9b435e4 | 1 + .../a5aaae5e5cc3955871ba97a7c41d307fef2b72eb | 1 + .../a5ace5adf4a44f04399e15b18f44e6a83e13b549 | 1 + .../a5b907c867904b2e2631128c5f637988bef1282b | 1 + .../a5c7d3a86b0f7fd48476aea167e188ad2e930dac | 1 + .../a5ccdd516198da910321185e29de6f20d9be2985 | 1 + .../a5d4903bde9105b510f48ef3783702f402c38289 | 1 + .../a5f0f80d6202449807c3c23b59496812943f4d12 | 1 + .../a610da0c9997c31b63719e6fe71e9b82d48595ec | 1 + .../a63c8dad9a5b7049824ad507266f11ef32fef7c3 | 1 + .../a65e2a892ee1771cf4861f2c1bc2d5f505645c14 | 1 + .../a66d01f6351976b51603542719f7e00648878dc0 | 1 + .../a686f07063eda38bb50a12b8bff95eb203e492e2 | 1 + .../a6932b59aafceeb75607a7b5c0b5d93b3f2e17dc | 1 + .../a6b7a9259b013c7a8613e1a5291dff6a4c46e85d | 1 + .../a6ba23753e57cd1a1f2d7e37472e4679a0f113a7 | 1 + .../a6c5d8b49fda54f8534027bba1269af6af46da1f | 1 + .../a6ccf2fabae7c6419459beefef87fd1e78fb2d4f | 1 + .../a6f23c5bb6dad507a24fea1ceecc0df2a026481c | 1 + .../a708a2f8ec818a38ec29e17b587179a32b43d704 | 1 + .../a70da8709e12ffb27292ce7290967a40c89cf126 | 1 + .../a72f0993c4460fa269fecd7c19909f1a8f319d4a | 1 + .../a732f61f7a104110a42397e2f2bcff054f17f50d | 1 + .../a736014c5e879818948ab14c8851770efe5d5fbb | 1 + .../a73a44e1dbbda1a5482aab336034e0f3b2631b86 | 1 + .../a742d0a1cc22ae97a4d67dae7649bce1710b89db | 1 + .../a758aa7b471d865a094148a124f948d84c1137bd | 1 + .../a76b07ca76b8129996817bda9c15cfe6c801c496 | 1 + .../a777b3aa2b4eb6ca1a87d04550c620145fe1fd1d | 1 + .../a78c1ce484d2b06f18054390abe8ba3738befc47 | 1 + .../a7ca771886a4f3f8ef1274e272ed3b75f1c52957 | 1 + .../a7d8752018d8cded7995daa9e4cd387a0f75eafc | 1 + .../a7edc21f3d053cf490a4f0032887dd77602ce962 | 1 + .../a80117d2623452c4c4d047ad5ffdcd2cfd707957 | 1 + .../a814c0230632e5c08f097102f2033615293348b7 | 1 + .../a83603464a89b1ff53b86c47af7c54b0f8a72405 | 1 + .../a858130542274ac050eecd7df40f62a22f2af3e5 | 1 + .../a87851edeb5a5db0f65fd04d5730500bf77c3e76 | 1 + .../a8a3b52078ade562edb5a7dc6ab61ce4b3cca2ab | 1 + .../a8b03c8e24ef968616c561f18edd3944caccbc5f | 1 + .../a8b6c76ee96d3aab811609a8979cfcc67cff79c6 | 1 + .../a8cd8ebe1c92a5ce01cb9d553c32988d450e82c9 | 1 + .../a8f6f74ddb0e0e8e8361ea297e0abac830cc1dfd | 1 + .../a912b73ec5ce6f1628bcb8d8e2dca4f96fb71c5a | 1 + .../a91984528078da07c39af230d966ecfa33124d9d | 1 + .../a98e2c1c0077687fbc9166f61a386e4a7023ae4f | 1 + .../a99032acc713604176f8d95263865e2c6dd015fe | 1 + .../a9b04af95ae95e9a60941ab351fb387c007938a2 | 1 + .../a9b58c8a3ebf4f2c3c8af6242b20c43aa733d6c5 | 1 + .../a9b81c4e5e52ddeed6c3bb9ecb2f67d7e056eb1f | 1 + .../aa0024897deb20273f4fad0f856967621953d402 | 1 + .../aa0d4dde043c88d76ca0b51949f90e102187198f | 1 + .../aa17922f64ff7cd6d4aeb56bfab8af47218a86d1 | 1 + .../aa376ce844fe5f3d69f1047c99cbef99e732dbdd | 1 + .../aa471973e1dc517ae959d5706167622da05bab46 | 1 + .../aa56f625476b200e65ada22557c871b0993ff86e | 1 + .../aa76c2e6c5a061d0580802966b8efb8804164d68 | 1 + .../aa8eac8fb7ebd4e613d8bdbce660665b3f45fa66 | 1 + .../aaa6693d92f9027513267fd416bd6201171873ac | 1 + .../aab859864bc25e0a7b430273941b291f2b765ba7 | 1 + .../ab1a9283d7a85a42aff52d1937193ca27a794187 | 1 + .../ab3899ee5c2ed560ae6beb77e71e4950fc17aab3 | 1 + .../ab3bd8d93632f274ea33e6bac92fec9215c4f20f | 1 + .../ab3f300e2417c10f0eedeee88f719e82892e53a2 | 1 + .../ab5267db0c03e93e08f51b597821900db93ae75c | 1 + .../ab8bd300852ee0d05f0c8d476f4205347466c6e3 | 1 + .../ab8ffe370320d075a8c7b9daefaf545d29b7ac1b | 1 + .../ab9b4c72f3a16b2e16d40652ec33ca2a8ee4d3ef | 1 + .../ab9c711cf8bbafb6cdfd30f945bfcb03cf0272b6 | 1 + .../ac0b35cbd93f63ed7452d6acebde72ca9fcc3d81 | 1 + .../ac2088d883a0a84ac9d499824adcbd32f90b53c8 | 1 + .../ac3cd67c26d777875eeebe2e90c716e8bd592ff4 | 1 + .../ac93b3ca2d9c1ec6e07725af461ea07bb19c4dee | 1 + .../acef576be556d6720814253fa450ffd2684c3c7b | 1 + .../acf314897698e9e208634f10df880184d9a7754d | 1 + .../ad1589197b44cb0c659b26869de6c66b103e9682 | 1 + .../ad16650f9e472fb459eb487a9f883c894760b565 | 1 + .../ad382a856cee976ed155aa5fae9828cd059ccb26 | 1 + .../ad4069abc0712cf1f3c8508b699379282bbf556a | 1 + .../ad58a3216af0b6f002972233963f6be39c7aee60 | 1 + .../ad67e4cfbdacd913d6561d8fe08f456a4341a88b | 1 + .../ad705acdd20e8da3a2171681cbf04df9fa98a3f7 | 1 + .../ad8af6e7441c7a1e3628b69f1ca22b74068a2278 | 1 + .../ad9cdf2ad4d35e3f1e5279c581d0394ae2aa6972 | 1 + .../ada6178e8321efd51626a855bc6e5557d68ca3fa | 1 + .../add98ecf3dbbc875a84ca24db0f18c054af38335 | 1 + .../ade2c248d7512985cd0840191f643e986e49db2e | 1 + .../aded7ddfdd7ffa25f49bad4502033ca4a8591786 | 1 + .../adf617416382c5deb595144ff94dce09117c3181 | 1 + .../adfe9ae4df4e249a66eb91fd2f8b26ee063e6f76 | 1 + .../ae32aa63248b35fca6503c67fb4fd2acf15a98ad | 1 + .../ae87ecd86f7053ab8d71a8f1fc84c2d2c62b472b | 1 + .../ae887143b966f102e6e5967f76ea3c041af92e65 | 1 + .../aea2776fad1a4341ceaff3aa6cf21d9c37587a96 | 1 + .../aeabf0753dee7e4de87a4ffe6e1414931333b32a | 1 + .../aeaf78544ff09661df34acf0ab140ca8f6834d93 | 1 + .../aeb2510aa3d77a9c6dcf533982e3925d74a03591 | 1 + .../af3246dfb5ebe1bed3d537e239a99af7422239e7 | 1 + .../af39e152ec29cf6ef9124bc09c621887cea05402 | 1 + .../af4d15714a467c338537aaa00108e2bee33e8426 | 1 + .../af58cb52355f4201682a37056445b679070634b3 | 1 + .../af5fe2e1f2c809eb47dbe26c8a45e6a55718cce6 | 1 + .../af7648fbe02efa3d9188b9b61ce6422012612477 | 1 + .../afa5c3718b0a518cee419488c60f2f2741ba28ff | 1 + .../afb161887b4215368f593a2d8d8b6bc32170698d | 1 + .../afb93dea86c318802ea31536847bc3786c8bb47c | 1 + .../afcc94478400491055613ccd42f75d4fa9c1ceab | 1 + .../afea0adf1a155b6acd7f6a1aac9dcfd781f953f1 | 1 + .../b0225ebc20fa76a5b5efb83881756503681565fa | 1 + .../b02921b398ef06202f6f3b3f652c3c8f10888607 | 1 + .../b068dde987664207f704c5b73a6444bd16d46da8 | 1 + .../b06a48e5c2bc5a6b1fc1fec7273e5642a15c8c13 | 1 + .../b075dfb300337efeb5bdabad39fff800ee516fa3 | 1 + .../b085cb29b4ab162f71d870e1b8f890fd0cf23cd6 | 1 + .../b08ac583665d8a49691a3a09c1d5cc1ee3b8a416 | 1 + .../b0a4831326c413d2804c49788050b9f91a6403f7 | 1 + .../b0ad1929e6a50924bb0dc2de48e23ed645f857f7 | 1 + .../b0c00b0f653fb7d6d9c6d10a355b006e90bfdefd | 1 + .../b0c6d5f594246c874ab683269116303a280482fe | 1 + .../b0c73ceab30b62cfa56f40cdfd49c1ce58f55a01 | 1 + .../b0d9006bd4700ed6403142773e914c7bb257d345 | 1 + .../b0e3df60a56490ae4dccf3851d020b40b21b8b7b | 1 + .../b0ec063bde9113e41cd5590763cc5a80a27e57df | 1 + .../b105a50748888b6356015fc47a88bc2be5715d6d | 1 + .../b14851f777181f4d6991a19eb5faf986f6c5d922 | 1 + .../b16c3acf4e0fdb0086f5e645c0abf5248401f236 | 1 + .../b1776090f6173a9a430ec315e3ed5aabd24b1b72 | 1 + .../b1a7636cf60adfde2e1358221f019b1e6b4155d6 | 1 + .../b1ad5a93a73ac48400168c0d0d6867c722e2ee94 | 1 + .../b1b4eed63248ce097e83d9f1723c6762b7de9c27 | 1 + .../b1bf9f8b4545db1b4c96961e0e20f15216c0e8b5 | 1 + .../b1c08a839cd0acb873c5f79044f09ba166bfa26d | 1 + .../b1d288dfd536ad13a01041e19c9c11fead33ff91 | 1 + .../b1e426a1d9ca218fe8dfbd94e4f84deb69cf3add | 1 + .../b21f2a634774a50314c4e0ef19018373cfff5761 | 1 + .../b25b243c1918bd286e71165a606917ad6566dcb9 | 1 + .../b279bf9258b4c48220f05e2e891b91c7b13e0572 | 1 + .../b2bf386739903299a1cce995ba58544747eee3f9 | 1 + .../b34497bedf19b0567d48c3bb9d3c6c6b7285bf56 | 1 + .../b354cb571d5964e5709107acf8b69b7a52691648 | 1 + .../b3621ec700f1905ab8a89bd0dc990c56dc5b2619 | 1 + .../b36fa07023f7e2c301fca71c92d63d4b9d3dbfe8 | 1 + .../b3acffc7854d876acec4be4e8f02c5785c9786cc | 1 + .../b3b35af21b57765c4439d83505e2c122bcd9d159 | 1 + .../b3e2b23acbebfcbc2e5f4e54d4fd7005740cae7f | 1 + .../b3f7745d61088bde2d2244a961085a6e8ca22a22 | 1 + .../b3fb8896212c7278ddd055ebe8806a9aadfbdbf4 | 1 + .../b42a78220d5bf6c02b4d64f379b4963da854ecf8 | 1 + .../b471b7933c10f89f075ebd244fc7dce18cc064ec | 1 + .../b4881b1ab0b628b8e08950b8799b2a7b2f90f6bb | 1 + .../b4b0e6e8de840a729657842fc3f326a51926695a | 1 + .../b4c0e993f516711b0d2941c1993f065eee0512a5 | 1 + .../b4d27baa0c7f4d587689db8a9529b71fa55341ec | 1 + .../b535e18acfb42d8eca463e3d005649eeec97a029 | 1 + .../b537477b73545075fe86dcab51eee08a1eff1f93 | 1 + .../b545791a846adc504218666c3218bfaa83bc90d2 | 1 + .../b56d0867bbc5b009c7f592e99f5d598f728cda80 | 1 + .../b571a84a7a61d25a217f263add5e84836c981aad | 1 + .../b592aa01c9d16fda0673296c91e16d85378ef308 | 1 + .../b594302e03843a9f9c9551e5065d334f5788b18f | 1 + .../b5c23ef36f914bfe6734a376e3ff23afa4056cdf | 1 + .../b5f858c267b5596e80a4ca9e1d9d9fc97493a161 | 1 + .../b5f894878cea25475b042e2e6dccf49267130d0f | 1 + .../b605240fb46dc5b5a62d8e4fe44362074c17cd79 | 1 + .../b62a40520073f939f2c0c9f173f5df055dbcfe5e | 1 + .../b646f8b3b9e38907889dca9d182ffcb148c5eb86 | 1 + .../b64c6d5ba93dfc04d7a168f3316abb231668ca1a | 1 + .../b66c4be98c84d4c925dd2af48a775cc657d0344d | 1 + .../b6737bb08c29b827385850c321cf5d8413acfef6 | 1 + .../b67e4f02f0ff506105dfa4a0171d89ceb6d26cfa | 1 + .../b68b738158b1aed99780946dcf5925a67eb68cca | 1 + .../b6df4711f8c031a1f3fc609594a2746d2d4e3d62 | 1 + .../b6e1970eedbfd9c6a474d94f15274687adf86c2e | 1 + .../b71c95db43c402381d9a9673ab063f0735eb1d31 | 1 + .../b71ebb4f48a1c213c17c8b1e9166cc38b072dc9d | 1 + .../b72daece9e0661e0bd4c8a41d26c73ba8eef4882 | 1 + .../b795709244b876a1f75a1d801c74732832748ebb | 1 + .../b7a501079daff65d0e768364b11ab44c69980aa7 | 1 + .../b7b1691a7efc0fca08ac5b931ccb3dbf5aa891d8 | 1 + .../b7cc907a8b0d3c3e1994be68a40873b4e99a5f78 | 1 + .../b8079c5bdcff63a0f477e2f79dd8aaf4928abda7 | 1 + .../b809617c671f07711eb77d11353900df3a1020b0 | 1 + .../b83c1c0b8c3121745e8e5a5de023dfb379736329 | 1 + .../b83df399d9754f536f1c099dfad005119a65be7a | 1 + .../b83ffefda146d967a06f51678c18eff540980695 | 1 + .../b84cd36f16a07a3e7153b397d87779a08b904316 | 1 + .../b8500830a3e73890fbb7f1b5e546f8dd9a851acb | 1 + .../b8684e0746d02b30dd7444f365d9552810403e85 | 1 + .../b8a16da4c5a5e56d3c75e8933ac8d444b9d06ecc | 1 + .../b8a400a5412cc152b17a2cda851c5874dd5ead2d | 1 + .../b8a97f2ecce17499487b6afbfd74dcdb69711ff3 | 1 + .../b8b534195cd5db1dd0cc83d99d7face7ebae029d | 1 + .../b8ba77481215495fefc3d9c89e8e4251b1514f9b | 1 + .../b8c25103015cf79375d6f576186c9bf014842e27 | 1 + .../b8c863f970b2f3c39e353171b5902be0355002ed | 1 + .../b8daa1c785e390cba67ca10da7ee578c00efb805 | 1 + .../b90034052330d016cb6261caaff33ff9b2007d1d | 1 + .../b953ae08ca074cfcfeda2be630b7eabb0a0feef0 | 1 + .../b95d3cec25b96ed5bf972cb98ca8c6476eac7630 | 1 + .../b95e31c70d4e1c7f52eb020450f422dc69f2b3f1 | 1 + .../b960c57badc5a9291e8064176397f05700f998c2 | 1 + .../b98b3ae70f7b3075d295829a4a779d63ac54efc1 | 1 + .../b9c4f033e767c62469be7d0c9837ff7976269c03 | 1 + .../ba1c9764d8c0c80309b24333c675854c1e92edf6 | 1 + .../ba1e6bbaa2a233a2a9e108339e2a03d15db6c21a | 1 + .../ba213f9e83bc18ee5d889ce921f71786661cdb49 | 1 + .../ba60320519e241dc303d027571c1b6b6677274ef | 1 + .../ba66a56ebc2679a2d9e33cd52effe2bf5657ba63 | 1 + .../ba71d7ae4697eea6a410b7c4d7d542ded867b329 | 1 + .../ba830627ab470b34e7d889cad07110a91669d64b | 1 + .../ba88104330b37c0458b14c5d53739d04527f803a | 1 + .../baa4d60cb12ba51a47909ac8227ee6df6d0dc0b2 | 1 + .../baa96c5298845a9d61eb221acb395d2256d66ee5 | 1 + .../baa9d2ad62a330c543ec07ad2137ad8de21565a1 | 1 + .../bab370c81fa011cfbd5f4933e8e203b69b4613b9 | 1 + .../bae295c693b97cb9ce1c49550985444f7083bf7d | 1 + .../baf106403ddec9a4e35d93e4d7e9c8858a1db975 | 1 + .../baf7af0bebc3219aa43e93f239abf44c3c75cc84 | 1 + .../bb00878c7c40b024bd20fd9e026f76cc0f01bda7 | 1 + .../bb06616585d2cf60ef82187fc0334f6ddea3aafc | 1 + .../bb0848b612e67f32638209d33374606f9f878516 | 1 + .../bb213f4cc6adea71bcd254acd7a66de7a21a8fb5 | 1 + .../bb4c46289dbd303f6704b3a08d9e02f4c48b84e6 | 1 + .../bb4cc97eb2c8303964e3730c003f85cb88a0211d | 1 + .../bb7141b532ed1aa0b98bd58bc84ec2e08f2e47c0 | 1 + .../bb7fc95bb6e35ae77514934a3e4ffa53a6516e13 | 1 + .../bb85f9b909ffd0ec974d57b8e96a0afe8031c95f | 1 + .../bbb302be328567aed2f8a9548699284ede429dc6 | 1 + .../bbc60e9c8fe20335286b1b4c11f2554bf44bde1c | 1 + .../bbd6a4aa19b13347c78851a8c39dc87ba2c6cc26 | 1 + .../bc18a41aa534670b3eb06ea552eeaa43a8bf670b | 1 + .../bc44929f9083ce895cef6e68e78c51d907624850 | 1 + .../bc61d16fcfe7499f1dda3e1aebd61701783f32bb | 1 + .../bc63fef6a6e1da11f5ad9cdc8c82557d301f7f93 | 1 + .../bc94c09d187af83d11bc158ffad91041ae1cccf5 | 1 + .../bcd93267863bf6c12c490fdca519c9a6fb257676 | 1 + .../bcdee1bf1b6f002a01bcb15b07e1ceef6be9c962 | 1 + .../bcfbb863f9751dbc9e52565fa18f52d7cfc28dc0 | 1 + .../bd06f79eb234682d1b026c5b614cea268261d69b | 1 + .../bd10e29dccdef5c1bc2693b295ca9c3ee1a5e9fb | 1 + .../bd4570befca425281b554426e78e723b29b91aeb | 1 + .../bd4b0d5ede1b9b28ba821e22b21d2e67eb35fb46 | 1 + .../bd5b6bd1cba3b3c9511abe6e7ba85869cc7271a8 | 1 + .../bd647eceba7eb445528903854da69225eb46a33b | 1 + .../bd806dc6dd950acd2fb4799772f9284b52b3eefd | 1 + .../bd90aa727c6f46c0b214029c4cc55665db207ed4 | 1 + .../bdb75495237a21c1632a1d8002a2de43c75cbece | 1 + .../be342f285479f59388d4ad299b262298ea0a194a | 1 + .../be4056e6d4621f67f649cc023b36d0616763fb74 | 1 + .../be5fa21ede21c3ae07d18916186307eb0dbd0b20 | 1 + .../be6dd32445672ad01a41728099573f056d19f11b | 1 + .../beaac08761cf0537284bd2fb73e52c21bf944e0e | 1 + .../bebcb9f288f4fe614ba1fcc940d72dd3a2e9182c | 1 + .../bf0031c6d9edfce82c4f7c49f277cbf11c628084 | 1 + .../bf1ad139661581e23e01c40061ebbcbdbce507e7 | 1 + .../bf2b441671494bdd813cbde459c3f201b5dc132d | 1 + .../bf34c8983707b06356e258d949ea5d5b386f793c | 1 + .../bf699d29a3431d6314083edeeb34fd0d30d0e88a | 1 + .../bf79de65a5198ccae719f56cd87e06ebfa963388 | 1 + .../bf8f7dfface9a3a19ae105b018ef9c8464a7766a | 1 + .../bff5be66a4aacf336f6a1a8aabdf35a37bd49c75 | 1 + .../c0039aba73061b1e9d1b5673c11d9a6fec6c2d2b | 1 + .../c0201387de1a365edea3ae462c8e87757ac56e21 | 1 + .../c0264fc040cf13b7e91a6413eb4b7c76c194b45c | 1 + .../c02fa738eb666819f177a296b855df242f3744a5 | 1 + .../c04290c4f9037a6b82b7d2392c6c80c1ae11f80c | 1 + .../c066693ba1a2191967ded9338dab201a79f31370 | 1 + .../c06e8cd4278bfe18806835f29e8892fe38588b77 | 1 + .../c09fc10086b95973815a1c9f85b9e89af0b68a27 | 1 + .../c0c65b781da778eab58a96c85067f90b2d4d1f4c | 1 + .../c0d2b1edf6f56cba1a8e2d0b100cb918fd7f803d | 1 + .../c0d30a73338909cf56a6d97fed0221e78bb7731d | 1 + .../c0ea13628224c7cfa08a24dfe6cac5360c02d61f | 1 + .../c0f5b91a651c2d181d2e204758d6556b2d362c11 | 1 + .../c128857e0f643e229c430eb8ef7d3f5aaad861fb | 1 + .../c12b71a60e309ebef55284d493cfd3665116ac35 | 1 + .../c146489c520399688a56c27fa5210f00c10e9e5b | 1 + .../c180a8fea16357ccb1c9e9a5b1fcde5e0137ba39 | 1 + .../c195e2cf967dde5160c0de3b6a514dbb2ff8485c | 1 + .../c19c13729ac0ec5c7e396da5494a3f513d31d8e8 | 1 + .../c1b84b02f4cf106428923ebb095dd6888ae0ac50 | 1 + .../c1bff9e88ae4e9b8bfd1976fa22c1802e6db3962 | 1 + .../c1e5922d5f60798c78f4d0d669795bdad1a0801b | 1 + .../c1eeed88c600ab669ef89bb18d5ef6a6830d4f0e | 1 + .../c21065afa4b19740633e3c552a080169d12b4afb | 1 + .../c2268af10452034a5d5f9268c6f6797ab805a459 | 1 + .../c22963b5f52cca482bd79213fd1c9fd9819b85dc | 1 + .../c23bb15b95f0283493b5e9660535131e08c4b442 | 1 + .../c23dc3dee1bab058e9dda39e357268464aff6993 | 1 + .../c259be6e071636a46f638dc71fbf337480a65d62 | 1 + .../c2606a81031cc7d45d665ff29e83009cdaeb09b4 | 1 + .../c2615fefcd8c48ae15d7cdf715cb7cbe15365bb4 | 1 + .../c274fc041bc18ec36b6fc361335ee8c903ba6539 | 1 + .../c2b521f99f9142ffd0f06f35fdbf0a1e6db3b411 | 1 + .../c2bc316e1620048c72dc6375bd6c4de0d175594b | 1 + .../c2ccbe9e06e6c7ce6e43c0b381322fc7dc10a2c2 | 1 + .../c2cdbf0cad554855e5a2c77ade2426042fd077d0 | 1 + .../c2fc3139b18939587fa9376d426b5ed6e5a7d384 | 1 + .../c30440e2e36842767c6880d3419ffd67d8fc65e5 | 1 + .../c30828b92e910f121013ae0e7e80f112ff29c40a | 1 + .../c30e1db5cebdf16c793ac3774df5940ba0cbd27f | 1 + .../c34e8364c057d48255c31d4626eee97cb90971f7 | 1 + .../c34ea38700b3874b1fc56b98fba764e26e442bbf | 1 + .../c36f9ecac75a1f8369062bd659d7be8116d9426f | 1 + .../c3759872dcc57d4041c64cfe3164f0beae9647dd | 1 + .../c37b0f05074e165869fb4e36093d5d05e7f5cd58 | 1 + .../c38df517f192e8ee8b749587f2286408e1add7af | 1 + .../c3a855f0999c9f0c734c21ec479b4a2de052c197 | 1 + .../c3ca44e765c59aef19ebc14444cb23801ff338d4 | 1 + .../c3f3469ae6022ba9a824d15d3e5c6966ecd2729f | 1 + .../c42ba6332f5103b6c07a6d7b7c7a96e1345fcad3 | 1 + .../c4499beb83fe2bbc215490890a252106247a0d03 | 1 + .../c46f7002e386e4c4fd5c63195b15a2720dc604c6 | 1 + .../c4b2c2074e18699523a8e60939dabe323e8cfcc8 | 1 + .../c4c19d4cee5d79334aa9c0ff61f19d321cc3941e | 1 + .../c4e28343af816c29311d37b8559a05b14d797dd9 | 1 + .../c5c550da4ca7e932cdd65a9656f2f7c611148d24 | 1 + .../c62a6dec1ec0c7508b82a35dfbcc1d66455eb241 | 1 + .../c62d08fa40199eb68353dc3045f6c961f21f080c | 1 + .../c63b3815a0dae098fa0dce37acfd79f213436d49 | 1 + .../c63fa7c5e9f3cfa3be54296de8fcb8c5bae42ab6 | 1 + .../c66c43a4b77a41b0bcafd8714216e0e515ea32c1 | 1 + .../c671d0d61110d22335aeeff604afc7a78832a1f0 | 1 + .../c684723b339ed9a247b5fe843d2111fcb009cbf2 | 1 + .../c6911c815fc4eb1fdd0b9ab9cd09d3f6af2c6188 | 1 + .../c69155ad942486c3313ec96fba99eb4b629b0b7e | 1 + .../c694a3b9670b92c47faef2482e1c373a96c84b7b | 1 + .../c6a2dc24e570bc2a810731231121944aa2c4a595 | 1 + .../c6fa56d9a3cfa039c883bb5289ea577b65e788ce | 1 + .../c709197b022538558c64745e06cce6340703a73d | 1 + .../c70d23ebccdc1ea73e6448b1df58f62d71582adf | 1 + .../c71d9516b42225f3514b4d1df627c022e4817ee0 | 1 + .../c7252d6f48851dc47f8c3177537e12abe69a084c | 1 + .../c75d0a897f9c6981d81da8b49be331ba03439313 | 1 + .../c761e8c4c51ea45aa6c56b949fdc22e5d4c60cf1 | 1 + .../c763c8080d8e8e78651eaf9140b7aa3fef1d52d4 | 1 + .../c77f06b7f82e62ac50865f5ee4163ae369969020 | 1 + .../c785d388c9a15886ab980f88b666d4945c7ee4a6 | 1 + .../c79333ec6723390b7f1563f388c7a50d86f860b2 | 1 + .../c7946ca286a4c1e04861f5fe7ff7982618728e8f | 1 + .../c7a2d84c0203fa2c48f932ed3cdb57e9bc3d4cd3 | 1 + .../c7aa7f6d958c6e29a221a767f1d7b3c103fe86b2 | 1 + .../c7b48c2518d6d2a2a5acd628f2fb397cad2ac0ea | 1 + .../c814f8c932eb8ff0b1b54d8a85929406a22a72f6 | 1 + .../c8172ac90dca46ddecfcb6abf992c70d492bdaf0 | 1 + .../c8203a41b6f45793c2150ed5554ab5bf5c7eae94 | 1 + .../c82943e824916226a82dbcda450c1cf3f21df1da | 1 + .../c83f86babe52fc934414d829d4969407bdaa8de9 | 1 + .../c85880f71216bacfb5f45a917040c76a5b933f5e | 1 + .../c85ec330c8ffb17623ec929fd4a198c3b768811a | 1 + .../c86c77b200bac67eba1a81988b36e0764528deef | 1 + .../c8e586d3f61c1ad22568794bbfcb69f57cb8b000 | 1 + .../c8ef39151618f6cc8716604cb9c29f93559b5a3d | 1 + .../c908a5304c6a71d150881ee923df19a58e37c8e9 | 1 + .../c91a0b63271792838de6f8620c116c19028be7d3 | 1 + .../c92d0b7830a59c91b7478b9bc6537abc9104ab24 | 1 + .../c94bf93a205b5120777d3d7dedacadaf6c732df5 | 1 + .../c95a348b7638eb340903fe3cc3532859ffe5403f | 1 + .../c965920ad9808bd3f6a009ce5335213895163c4a | 1 + .../c968d693525b4f56eb70b070dbf41555841fa170 | 1 + .../c97c22cac658b5a97d90aab28ef2a0126a80ce6e | 1 + .../c9810cb06137edb22aba29ce495e0f5e87073b06 | 1 + .../c9888f4ae613d1778de5399e9c17e6e517df9292 | 1 + .../c9a84f25b1d55cfc33df56ee356e86772a479352 | 1 + .../c9addf4f9fd1a956c97c9babd5981d0c8295e152 | 1 + .../c9b398e28803f0f2e675448f50d7f4d8c39e8991 | 1 + .../c9d4c34b8cbf8c16d5b1e01af0f0541cdd36456b | 1 + .../c9dd51e291d1902fcc5389ef9f70290ea166e35b | 1 + .../c9ed258ea27321037ce42d665a00191863c1ddce | 1 + .../c9f4f38c06357e5794c082ee3a691a02193ff1e2 | 1 + .../c9ff164d902f41698dc1714ef130057761a13f8c | 1 + .../ca067c02b5a5e0209c277a0cea71db50a16d380f | 1 + .../ca0a2329b586ff39d07383acaecfac1982afe0df | 1 + .../ca10907ed5b956b8d7c600609307e951fa48d8e6 | 1 + .../ca10ab334b15fc1a219962a002ba20266142420e | 1 + .../ca3a2137d38c1e9a98dd585fbb1e5e6483a855d0 | 1 + .../ca4f72eced8e3ace4cb06faea7d35e7831c1e5ce | 1 + .../ca4f932e8cc3a4b016fedf455e955c89cd7237bf | 1 + .../ca67aeff72a1ca354129ea9f32b49e63219b5d98 | 1 + .../ca8e90d773aaf3a6cc447fa963353434f82c0e50 | 1 + .../ca8ead844b2d1ee6d2526ed1a548996bc943ea68 | 1 + .../ca9fc42da81222da6dec277f6346109bf564fefb | 1 + .../cab98434bc48379e0a365fff01d6b79bf577457a | 1 + .../cab9a4b9aa0799313bf8c71e90011d910fd2eca4 | 1 + .../cabd7d24e6498c820ccd2a79a03cc481607909e5 | 1 + .../cafd0a9a6dab6200dcb88ecbf7e265de1ad5d317 | 1 + .../cb181959ea829e3c8e81c95a1bbce81b35f8d2fd | 1 + .../cb1b57e08db865390f1b4cf22118530463b721aa | 1 + .../cb5cd2d881a8e8202863c29e2d692b6245167dd1 | 1 + .../cb7c58b77b079764dd1fdd95626fced2ad539c7c | 1 + .../cbdd9f9ee3d06ce2cdfe2000194d0fa14bb03cb0 | 1 + .../cbe16c2c588c6bc7000fbb04188632167236d008 | 1 + .../cbfe3b47d8728af1b60451af99e980f90dc89668 | 1 + .../cc06cd6c0a43860436758eaf21a715c3ecebb6f4 | 1 + .../cc13210738ed00cc6f24c6bdcc72bc63f13783e2 | 1 + .../cc3fcfad22ff1374fc57610045f054311fc92f6d | 1 + .../ccb6fc2bd7df140d0acaa9fa4f6c64be65339a60 | 1 + .../cd083f5472e5c5b1f0a2910e5400ed9fb0e38379 | 1 + .../cd2bb450b14d6d4aeb2383f17d0b52532a6d60bc | 1 + .../cd2f80cd83fdc9c096ed0c6e1e02112a0e62dd16 | 1 + .../cd4a620abc44efff9ec16d12232d21d35383be02 | 1 + .../cd536df731fdebe8bbafa86ebef1f6c819648a78 | 1 + .../cd553bbac6c8bd33ad432ca2077facbf41604f68 | 1 + .../cd8b40b4ffe13dc923550924d4133d5ac918ecc4 | 1 + .../cd8ca448ef6a3c3fa7536eee563579389b399c7f | 1 + .../cd935e81f7b958dc94cbb682f2c926e1e63fc213 | 1 + .../cd9562d304291faf33b2752268819af3d9fdd593 | 1 + .../cda64a68115a3ca8971a2747b360b387fbe1d1ec | 1 + .../cdaa800ed715e873d65a75ff494c085689777769 | 1 + .../cdae175fecf9783890ad4364fcdb7e9a26312c86 | 1 + .../cdbb9c9c88d727637e88c5e5f34b796e03a77c9a | 1 + .../cdd70dfc5c39ec02e5e48d747003dccc345d9c35 | 1 + .../ce08102de2f440a689645ebc57829a604424b751 | 1 + .../ce29a0262edb0e4c4a3905e19cb08c9a4e8318ba | 1 + .../ce4f3f6725a58e41e3545de8f93475f0f9402a52 | 1 + .../ce5a6e30faecc2d2f249b1bb1b0a21cbffc46674 | 1 + .../ce5c007dab411a6a225c1b09181578eaf6edf364 | 1 + .../cea069b190b73ea7c41e48275d6d0841d7fdd8f3 | 1 + .../cec62d6028ecb0885e4adbb89b0c33222ed71d55 | 1 + .../cedf97481d67a8a89199abfe8c15570cd253967d | 1 + .../cef118940d5799540be8721e2453120639fbe14e | 1 + .../cef395bb5063aba1aeaafde86a8bfd4c3ae80b8f | 1 + .../cf1726d92ba0a57e5cb508f7f38cf8c30c31572a | 1 + .../cf19361572439227ba12b4d90a84b45c9c77a6dd | 1 + .../cf1b9fbc48a705e782d90e0caefa83731663957e | 1 + .../cf3ddc0d11192bb67b1d1a9c46dba9cb99e1ab37 | 1 + .../cf87f1c7fe8d84db93cab39e5ec4fc004b0daf45 | 1 + .../cf99a5aabda5c420d162ea57e1d44c83b4a5f444 | 1 + .../d01804b3f650a230ba4caf6f35710074094ef4bc | 1 + .../d018c44a4a260f0faa1c368b22e6fd2da47b4279 | 1 + .../d023d686290f14c19a40f74a18a2c183ac38c02f | 1 + .../d07029fee875ecd9778957b1eb1b6ed3ba90c94a | 1 + .../d076c78276e47d5f2551df88390966202a644ad4 | 1 + .../d0a5a7631c5914f69f44abe8d926e7ec265b3853 | 1 + .../d0b362a6e10e2e3ca3df573c3918408d11230109 | 1 + .../d0c14f7b59f5b7c5e2348a842c4f17589992edef | 1 + .../d0d80b81785e11a47eb4778cde0392ceee57d442 | 1 + .../d10cc817535fbf7ed3ccccfffd59542e31fd811c | 1 + .../d120192543d7524d72dbae6640c1fd01b655ba8b | 1 + .../d13e9dcbf612e2b605c913bf461a40c14c78981c | 1 + .../d145e690ead8e8b91dcf655a058473fba40e05c4 | 1 + .../d1624ab2e4dceb28dc1e7d8f042d85271b474f44 | 1 + .../d17443611cb2c74ecfda516700477ecdd4ccd1e8 | 1 + .../d17802655b5504bb0405ee7934ae6e14c9c2f6af | 1 + .../d17b2da02d1d622d7b71dade71d9adc392999c5b | 1 + .../d17e92c55da82ddc95d75ddd15779fff2868ff46 | 1 + .../d209841a9bb6b9ed3a4954465f454a0d304ef888 | 1 + .../d263cabcd95f3dae465820283cf9b428e89c02f6 | 1 + .../d27d3711e16baa8c89ff9c90b6ed0622ca86ff8e | 1 + .../d2957d9af2c85119d0e66bf643c7eb85bda86170 | 1 + .../d2c7c0da2861f14114f11766107a7b8aa6efd73b | 1 + .../d2d896106278d4a3d97f13f67d9366baca387121 | 1 + .../d2e69860ee1527c081669b81f428a0dee46fe218 | 1 + .../d2f56cc722b3fc0ac3792e7c09a53592a22039af | 1 + .../d2f8f204891c46f5ba28af13b77da60a054ed30f | 1 + .../d33cb0c2e7c01d420f375159f3d266e71d9c3bcf | 1 + .../d34c8b66d9e51e1f51b9432c19d0d95ce51aa297 | 1 + .../d35d96943b798f0362dee33b1c9dd9f5ce520bf7 | 1 + .../d386337a1d0705a7cc519dc2e044e51c1831c3f8 | 1 + .../d3918bf85a56fd7561082f401a5ebd4a0d642f87 | 1 + .../d3abb997507d97ede96a2ca419dd8554e22db558 | 1 + .../d3ad578f5f3076aa52c4e35e8a0002582433fef9 | 1 + .../d3ae88e79c1801c2da2ca48244ec5455bb3abe76 | 1 + .../d3d3e2a151a062b9f319dd5ba2d382d38c8c95d4 | 1 + .../d3e5ffbc18b1ff4b1db6426ef3962f8c9cf5cdf0 | 1 + .../d411fdd25ef73e64648572aee57803f358cf4bb2 | 1 + .../d4208a5824d1318820b3784412f424db595f35ae | 1 + .../d42eec126dd7b1e4c2c574ddba68f4d0228c3d09 | 1 + .../d48d445fdf8825eb982e112320fe51da22271d30 | 1 + .../d49f2424f7e47981e92cdca8a120fad3b5b46351 | 1 + .../d4a61c1883d529642358ce1ad476eae28f347140 | 1 + .../d4b2d30318741bf9642c79ca255322762ff5a669 | 1 + .../d4bdc84c656fc906c865b5369626edd1bc0d575d | 1 + .../d4bfa057df6de164cf5907d1054f7b8f37dc55ca | 1 + .../d4d9f5cbd1cf9b75c9821d5d4746491e46efecb0 | 1 + .../d4eb08a9f93ac1b16665f4266fcd570b760e0b41 | 1 + .../d4f11edc0601915ee85baffdd4721b1d1b3b60d0 | 1 + .../d4f65e281be1feebd4750e113b05138a9c44f486 | 1 + .../d5048f880c8259302815a101c17c687a6ddbb1d7 | 1 + .../d52e561715cddf6ccf811873e1d9570a5b25b677 | 1 + .../d5466e451d61467e6bd45f66d7608457be8a656f | 1 + .../d54c6961bb95000149d7cffd738f1f34eaf1d825 | 1 + .../d54fe454199d96dd8e1ab2d0069417d2b9be7cf7 | 1 + .../d573fa9122441a358ecf4c86ea6af4d26e08d93a | 1 + .../d5892cc02088b2b7e11febc39b2d7cd9ed96fec6 | 1 + .../d58b0cd6e4cd0f7d08d8c5cd8f64fb89bc6c77b3 | 1 + .../d5ad81a47205ca9893336dfcc66e370ee84776ce | 1 + .../d5f073d2ccb1d4bc1f4bb2d64971cda535f3abc4 | 1 + .../d60ddd04ef59ce7655ce0640bb9f05a050c50572 | 1 + .../d6114c41966cf276af2ac91a43b0dcfdde3ff6ec | 1 + .../d64045b67fe7d9bbac6b1955c9709dc8f62c2574 | 1 + .../d65a0ff7ac01950da5c822d87cd1f1b94663c71f | 1 + .../d66bdc15b3bc47537708b688679685d7823933ec | 1 + .../d6a9e0d913d7e024afc093007237124f4a34364c | 1 + .../d6bb41e59dad21fc3ff2d5bb0c784b27307ee4d3 | 1 + .../d6e668abcd05531d83ec0bdff606bec2368882a8 | 1 + .../d6e9b28f9645fdf80b2547f4a875bc298680a83f | 1 + .../d70c950a9b6157fdddbd8eb01fed07f12638844f | 1 + .../d71a3d01673ec097d7272cd0fcf4fc12f19a90e8 | 1 + .../d72363609fde245d8d04d59c1d9e2386e97f61ec | 1 + .../d73e808e6fe07bbd4cac3998bbd227cb333f3860 | 1 + .../d7435dd29bb609d8a757deda3c46bae9522fafb0 | 1 + .../d747c65611d3195e76faeea3dbaca70f0255d690 | 1 + .../d7482427db68b72ab957e74167dbc8c28842b070 | 1 + .../d7491a450345ac8fd8bd2da583d6974224917a83 | 1 + .../d750ca1379d7933d2b0750e621fad549663516ca | 1 + .../d762cef9eb8735ca5282dea549336970c32f0470 | 1 + .../d784977d5fa21c31f0f510f5a1e2d50f7815c63e | 1 + .../d78a59aa9fae45d7cbfb5d42a6d57744818f4f3c | 1 + .../d78b2cc4912fce258a371b34976f623504f00bf5 | 1 + .../d796184dcd2791587af889f67ff0bd146da22bf6 | 1 + .../d7a0524afa7b58f919577fc272101adacde12154 | 1 + .../d7ae7546c73cd724ed329a7e111b1874f3fad3a3 | 1 + .../d7c12a570bce792607b3d5f23fc34ef6392109de | 1 + .../d7d1782dc0b7c5e12cccab548a33619bf58a1db8 | 1 + .../d7ed3928aecf2d3acbca2fb8d2ee7775f7f52ccf | 1 + .../d7f54f75c60667b7fd883f34d666d917d0b88809 | 1 + .../d80fa30ad1a0824f0da7b212e606ac5496c0715c | 1 + .../d86ea65d288be1fd03e9e19e503b17612c637374 | 1 + .../d8ac2a246d17295baa73602fa55f5ef1d6edd095 | 1 + .../d8d54db51b8f8299982f8136c6058c9e8063811b | 1 + .../d8def6ae46c2ae1d19b457603e2015ddad467ad3 | 1 + .../d8df811ed2f11c79fe945f4943ea3299a251ecb0 | 1 + .../d8e4caa314d508c3062410f0d680eb589488140f | 1 + .../d8f77e44fa8aab802aa9131ae9f319611a054835 | 1 + .../d915944728f949574638f5527cabdee757340ecc | 1 + .../d92c58e19437f5a57d606edb988ebe5449b4db1d | 1 + .../d93387aa595f09f4e40642c715176275012422f9 | 1 + .../d93dd1d6d2d9b39d77cd72571effaec51dad73cf | 1 + .../d9462d451520aea896848f14167cad63f8eb631b | 1 + .../d9632d4e4f8d7cc9db523291bb7442332d7c588c | 1 + .../d96eb1935933e5d8a16bab96d06d05f8b1ab6619 | 1 + .../d9721f612be2c4596ef2507879885c69a5e6e58d | 1 + .../d975fa857300c644b1b8b86b9e5579116325e3b6 | 1 + .../d97fad7ecab4d8f234efc71d9e0019d3cd6866be | 1 + .../d9d8525ff675d165e7bd245edb10bef8ffbabf37 | 1 + .../da15d30445dcabf73491b38ff9b7fd6ebf09fabb | 1 + .../da20174fe1299204fdf8cca351a424cf681308a2 | 1 + .../da3eafaf969feb19889dd744b3407db1aa866e06 | 1 + .../da802c4897e37a5e51f367edd23444c11faa33aa | 1 + .../da8a14b376513348d7ee34b10ff6883f15cc6fd5 | 1 + .../da91d607fd954405726ab36fa5677e8163634ff7 | 1 + .../daad29bf36401da76f1b83f5cd1cc0335bf5c14f | 1 + .../dacc869b2d12c823c9a4bb00e5edcd51d35c5978 | 1 + .../dacf3352a5bdd39737fb53affdf284ce61f4e97e | 1 + .../dadf4bbba1d78a438712afd4e84df10275987f0a | 1 + .../daf266d227dfb92686b3d8cb80cb4d2c4e849468 | 1 + .../dafea52d56a314eff0b38df4ddd35be40d4f6d24 | 1 + .../db01c81c34e5e86ae44bef70289a143173916fb4 | 1 + .../db06c61fa468b40855c83db915cf67df55dddeb9 | 1 + .../db191d70ebee38a520718fe3a295896a1840f111 | 1 + .../db2f754795e1478498a59b3071a7852a32a70b8e | 1 + .../db41febcaac001cb453d4a2ca2a285784d5a9cd8 | 1 + .../db5b9f12551bfc0e07e9c89d6d5971df6e4eea17 | 1 + .../db715816bbafa4a288124a98d0cb4df6a364cb3e | 1 + .../db81d6ad0913097959d953bb6c2e7d576f846a11 | 1 + .../db9eba0b2b563ba067b7fd8e8ee5ddad9b770dce | 1 + .../dba31a12d1adba28878c2a0b52b782a5c72d9972 | 1 + .../dbef858a545baf2d110f1d0e917e4ad258acf993 | 1 + .../dc01bbbcdac6b5bb939e4be9ca56e5b8c3d165af | 1 + .../dc0806f74a893b88a54642a35cd820535fde3ed1 | 1 + .../dc161355dcd6047181d0cf4e25b6a5525f6fe50e | 1 + .../dc3539d6d3a6a1eaf48ce5185a088eb43b9e383e | 1 + .../dc480267e0ef9ce538b42b77872f2b3532c35322 | 1 + .../dc57d8ffab2a6632708a04cb288629b09aa5c82e | 1 + .../dc593bc1e5ac44230400eae2d39c99148ad34e4b | 1 + .../dc6dcb26e66c42982855aa1a52a31fd33b250e19 | 1 + .../dc9395f17d85f800578e0d6e8bf89ad9746befb7 | 1 + .../dc9899ac6fe73116d5e9f16eb5d414386eaf20b6 | 1 + .../dc99d264d246e0de31744757d56e34f81e69221e | 1 + .../dca299a0e651d9aa555003ff4a5031f3fccf9743 | 1 + .../dcaa02212efb1b1d7b35ccd1cd382be6b3e66e71 | 1 + .../dcbd31842dac9e7cdaf7ca65e510582bfd1d1a9b | 1 + .../dccaf2fc47adc1a3b05f03d5fac2a95f989db10c | 1 + .../dccd7c4272928f022003ea9c7aaa12dcc004a54c | 1 + .../dcd041ba07357566b4ee1ed3cbca6574c6154f10 | 1 + .../dcf7577a80ecef6f3ca732dc2e3adaa48e682fdb | 1 + .../dd000d20a2f313c18520373a1f18e05ed9a150e2 | 1 + .../dd0b6ef4b264cf0858480a3460b856a1c8f6dc1d | 1 + .../dd51571565035f293d86c40ad779317f87aedf8a | 1 + .../dd6e129061e453f9a72be030e9baeee3e56fcf0f | 1 + .../dd8c174c7b3d3ef26b6db13442b39a50c7f55222 | 1 + .../dda325195c906944f23de872fa78b2af88631c09 | 1 + .../ddaf37dc11a8574b722f076f36e746bc7c60e215 | 1 + .../ddd4994f43b538ffca8eb9b28ca5fb499238d0b9 | 1 + .../dde699e331a7df59bcdada620624b5ba61dc5dd0 | 1 + .../ddebb704471c13ddfaf31413aae6c013515a3717 | 1 + .../ddedd372fed9df45da4d1a59cf4f5cb35009e49f | 1 + .../ddf80ae28fa37fbe9cd6a838ae2c428932ef3961 | 1 + .../de08cbb895403680951a2ebc90561ac53b1a1f4e | 1 + .../de2a5caabe3e3b0b1b01533e95ed8f482c6ba0fc | 1 + .../de4f89a55a6d907d16952ca4e4166a5979c39c8b | 1 + .../de5a7c1447572e08c6b28e753fe662ac083fd6d1 | 1 + .../de5adc575b18b1c34a68e95cecf166f402e523ff | 1 + .../de5af33427175b7548895fa5441e430afe11d1d5 | 1 + .../de6875a737b7c8020f44b1c99b70c4853e661ecf | 1 + .../de6cf2f6180404aa31b1db7d09cf2baddd601d44 | 1 + .../de8a035daf19e89e29ba0bbdd71dffd1f9cadc5c | 1 + .../dea753eea55e305608844a4f00655549302ce7dd | 1 + .../decd88daf9600a38bc143777492f37dad4565eaf | 1 + .../ded66ffb0cbf19f233f516bd3c63fe712650ef33 | 1 + .../ded72412b30434c168fa06e48b7e054269d006c0 | 1 + .../dedc75c0c2ee756e9070605ce546167cacfbcaca | 1 + .../dee101172e339916048ad363fb6995306d7dd142 | 1 + .../def37ff0a6957f0a571488b66a768f20f7079048 | 1 + .../def74495863bbdf9d1af666161152708f2ba582d | 1 + .../df029e9ebb9e83aace8f0071d2840c27c3ceda07 | 1 + .../df085e9114f63f74c86f24312e70f7b5318ad9fc | 1 + .../df12a4966bab2fafa4ffe3a2ffbbbe8d697046c2 | 1 + .../df16a0297efbbe308fa83a0f3e6ad417689b028b | 1 + .../df865486869273fb5f7adede25fcadcb18ce2221 | 1 + .../df8de808e45c8839831abd0deb0cabf9143753a4 | 1 + .../df8e03791d82b6610c2c15664032e32589ea35a8 | 1 + .../dfa3c5fef1b463d98f523033ec70daf8d4bf8803 | 1 + .../dfb36ff8904f4e8107d8ba666de3e5f94f741bfe | 1 + .../dfca4159ab78bba17ae0d77f088b5aaeb3144266 | 1 + .../dfe3a4307a38993f68b0c2518ea2e3e590b0c9d1 | 1 + .../e0128963856adfa8520b26e571a93610b5355887 | 1 + .../e03443f852b194c164bc4732fb9c5cc86effe4f6 | 1 + .../e0588caa737bfbd960ff3fd219ca062193aa6bf0 | 1 + .../e0aaba61fbc722b30669314cc389d44b8f989110 | 1 + .../e0bbbcbab18f481daf5b315491e268254f4983fb | 1 + .../e0da4e0fe645f0a953ac5735fde4706cca9e1197 | 1 + .../e0ebae4900e11a9672f2ae78e61178aa6247650c | 1 + .../e1087672834b43c44e37cba854b5b9c9f7179a84 | 1 + .../e10bddf4873386e1fe3f6dc0f2b20f5c151c89e1 | 1 + .../e11d98e0003ce918a6fad19f550ea0702a879911 | 1 + .../e1326c178bf8e7b80cda8ea9f9dd86938329c849 | 1 + .../e147111796d5b53a6bf6dc9458c50027b4d09f87 | 1 + .../e14960a185290ebe95ae6279b9e869e837251710 | 1 + .../e170c4afc7cf3aa9e0e5c2670686778994fa4f11 | 1 + .../e184bc711398d7c0c1fa6934192fda6c555a1cb3 | 1 + .../e1b11848fd01dfa0ba32bf126463d9d364ab4313 | 1 + .../e1ba585df080f7b1a7f8f2c7db5dd610f19174de | 1 + .../e1d952db862331ca79b0a9c72c162374fb1857d7 | 1 + .../e1e49dcfb28496b89f4ea5ce3dc0d76d880076e4 | 1 + .../e1f0807d7b3a4bba613963e80beb7c74850d5c28 | 1 + .../e22480aebb82f3343403252198ba68a247b6d046 | 1 + .../e24851678d123d31e1507cb51348f5b1dc101d4c | 1 + .../e2496a88dd988d4f3ef82308c3cca33a874d45aa | 1 + .../e255d1877a2010d7fcfc04ed18a7a010df14a2c0 | 1 + .../e25fb2f6402ada66247ba900b01f074eb85ba330 | 1 + .../e279990fd5d183e1d8b4f404ff9bb849d49c365a | 1 + .../e2d5ca40d2c53fc997406f6b09aab24c3df0d72c | 1 + .../e2eeef8ece1fd34ca3dc565f6c64e1e27ffe4394 | 1 + .../e3196566970071a5ddde94e45545b255dbb827b6 | 1 + .../e31f0de61f44c1cdc4d261d497cf718662ce97d4 | 1 + .../e3201e6cef5abb4e32884e254d83db6c48c0c98e | 1 + .../e3588db1c621c20dd15839f0a47a91d2b3a7c779 | 1 + .../e35adac42c2fa3fac81b5b56415001d9ef213aa9 | 1 + .../e36c31c772e822a277d29a41f45a505e97121618 | 1 + .../e37bd80d8483f80595f8de680651a88967e6b765 | 1 + .../e385046269e21e18e9615b10675db2b779814ea6 | 1 + .../e3cb84cf87cf0a5a0e394a62331f15e54cde54f5 | 1 + .../e3e431ac9b495d6b12f584909dd0891e732ef378 | 1 + .../e3e86951be6edc4911741f8779b8b81f8e19669e | 1 + .../e3ee89b296eda3cdf6b73af88989c9879d826a5c | 1 + .../e43e0f4dd6d04ff5cb7feb566ac7effde65eabaf | 1 + .../e4400ed471cfae79f01e699c1535a927cd7db111 | 1 + .../e4403314230ec5266c263c14b3167d0495467abb | 1 + .../e4476c9611f68d7aed1329b54ac787a7dc19d3c1 | 1 + .../e4549906b6821c9cfd2bdad13fcedc9f2ce44c8f | 1 + .../e46150bc653c31e407e6428aa1a6ebf50bf84aea | 1 + .../e4a1dbfb8711c43befec064b8fd396058b0c54af | 1 + .../e4ac1ef7380b8d2111b6763169a1743b27f8990e | 1 + .../e4be0b4404267bdc3cff4674612fa0aafae17da8 | 1 + .../e4ed5b23d5de1068cbbde995bd4acee64e91aa7e | 1 + .../e4f857e19db4cfd96f2d5054dbf40b5a9e492dff | 1 + .../e4f9951077eb874d4585b5156eb27d51d2efbfd3 | 1 + .../e50744f139df817035a18b49f300ba44cb0343d3 | 1 + .../e50e205a1d18fcdba7e8e5fcee9033cc4707f9c7 | 1 + .../e52cfe3453de9b1d75444df456949cb75040b8b6 | 1 + .../e531badf585946f2d8e4ca711ad08bfab23b255d | 1 + .../e556fbc1cbc098965abc9f19de4e699a65701b97 | 1 + .../e5a06372794c8a0907ebcab73767cf918aac39aa | 1 + .../e5c2adb3e9fbf1cd914078ec2a63b5eb9a6e3abe | 1 + .../e5d4d4aeaf98b811a93af7c9329c6daf9589e991 | 1 + .../e5d756b155e51281410e56562a664673b0c34fcd | 1 + .../e60ac2a186190f5f41d0f98adb9107b436491c32 | 1 + .../e617e275740cca2c1002733c0b62505410149814 | 1 + .../e62e88a5e5a9d90dbb6072f7ccea09b105b0f310 | 1 + .../e638e75f42344b0c3f6564246955fb5d040cf293 | 1 + .../e649d79b9010e5f76ed8c6e317e55e0e91802bac | 1 + .../e660a993ca6c73039fade4ba3407920ada89923e | 1 + .../e66bd9898efc98f464bdb5ece0b4f62d602dc737 | 1 + .../e677ad001a80f4218fcb1f38a8705f1d1caeb999 | 1 + .../e68c741fb9f3bd4beb774a6295165f0719b15942 | 1 + .../e69ec7f55ad3c08cfcb37946cda5c9e8bd2f23d4 | 1 + .../e69f704fabb54c278ef86ba0a840cc8b462fd273 | 1 + .../e6a0539a6bf9730e9f7197aac29cee83936137c2 | 1 + .../e6beac0076a3f98639e16833588cb1f7c3630b56 | 1 + .../e6c4139fc79b0036b50c35d40646356790b47698 | 1 + .../e6d6a1ae86f60f1e63f309397a0008e6d4943d50 | 1 + .../e6f3612a73d29882780cefe3d036f68100cf0c7b | 1 + .../e721205c821d1cfd009e603052b5cee6c677c52a | 1 + .../e72d5da834d577e08d8919888da3491b1cfc2395 | 1 + .../e73715f248773b481cfeb2552aceaf18e4b03797 | 1 + .../e7865be06886b6e888fd9d883d55c5faee586ef4 | 1 + .../e7a375809c225d5450a212abb59a2046d1b5e007 | 1 + .../e7c4905ac16a9774e7e810abf68b112d641b2d9e | 1 + .../e7c5c79c85fb153f7749dd5dcfa97ac1401ef95c | 1 + .../e7ccede981bb4c65fa47e7fa310a9348a7109ba3 | 1 + .../e7d9419f6cc1411629e9a09076e350aef3f0adbb | 1 + .../e7e9f1bdab686670c7fd4b590aaad6feacbbeb73 | 1 + .../e7fc7fe2e56e39aff52a6c1a3f3ddb20c48651d6 | 1 + .../e81dc94c8743dc71b11667a65c76c5ef0e8eaef8 | 1 + .../e81ee8a9a2165602a74cee1bdc447e2da39ab762 | 1 + .../e84308cd3dc05d65738bf940c73e11c1342f53dd | 1 + .../e8597fda210c9006c4eb35f55099dd53f0804f47 | 1 + .../e85ebbbabefe13b277bdb7bb290e81d48aaae843 | 1 + .../e87e2014a5a0695a3cdffdfe859201eb8beb9fb0 | 1 + .../e8ac301abd5dee5dd4ef8cb0670844bca13f0323 | 1 + .../e8de8be751822aa2e8bcf086b89ae6ca68052255 | 1 + .../e91b8692e5e50d7452d085b3580b9cdd1676e122 | 1 + .../e93758815f2e92fcae33eeb424961ee124cec2c7 | 1 + .../e9501001531cf5569b3b23daa63df0825b2e06f3 | 1 + .../e98353914c5de48ee650dfff9741c1285bf29368 | 1 + .../e9a85210b1a1018e7666d51f88430bb5d8bfdb3e | 1 + .../e9b76d10a6eebe9f37aaf17e3c71921c02524b86 | 1 + .../e9bf6e5a4cbd00e35ecd77dc39c1f9264b9f4dc1 | 1 + .../e9c730fdf2c5807b82dd1e4d042e404651d4c118 | 1 + .../e9d4196818fdc0fa92415cb4a2aff1b96c783b8b | 1 + .../e9dbacbd2e05c550b025911cfa3ca5803dae805e | 1 + .../e9ddf35ff01ae9bc71730f02a17a6079411fde98 | 1 + .../ea1fa2cb1864ebe376683d33d94b64f0f54a43dd | 1 + .../ea224ce2e986d690db2a198af3f98a8408cdb30e | 1 + .../ea3247c42e38f93b6d8af0e43d7f34cc4bc25070 | 1 + .../ea3a67eab454450f7603fe0cd98a27c731eb5d00 | 1 + .../ea3f5822d3ff42dc536ca2f868583167e04fcb24 | 1 + .../ea9383c734b03a942fd3c33b4cd6172b0c606aeb | 1 + .../eaa2ec29b35602bac1202162cc43997d10f21ed3 | 1 + .../eaa7b118760debbe1d5a3d4a62d81d966ab89097 | 1 + .../eab77792be235dec9f3313676498d907e560b5cc | 1 + .../eae489d9b326b6e764166ddf53140f5ddb3b425c | 1 + .../eae7770e2a494f15bf0e76460740c8d2e1cbd22e | 1 + .../eaee09f4a0e178165105cf2ccf81513fc80541b9 | 1 + .../eaee80bfbe65037b08eeecc39e40e2b8276a958d | 1 + .../eb0e20fe944dc77d38b2fc2582d02c80d3d9628f | 1 + .../eb372b84ca640e23188861d0efa04be45ee5f243 | 1 + .../eba9b48ee4b2ed1d213ff803ba46409241800f53 | 1 + .../ebaab3cbf799854c56be5ea1c8570b79e12530d3 | 1 + .../ec0558d3bd9826dcf5a547231702b26bb029d5b3 | 1 + .../ec11e48dae90b65ac226a309a6ab974cfc87474a | 1 + .../ec236a1ba693a15d7cd145cb072b03a9edafd25d | 1 + .../ec2d9171350303a508d3a35306e1da95e2d45a8c | 1 + .../ec3dc1b7325240192c1e37e75c29831fa68e98d4 | 1 + .../ec4c99541792d43b2c11d31a995e9d4e6494735e | 1 + .../ec5f10d715ff4121c9af8001b65d91bde62f884b | 1 + .../ec7ac5952f631f170c9cf5ab7afb10a2800e3be7 | 1 + .../ecc052cec3d69b0b941945fcfee7fcca160fee0f | 1 + .../ed414b2d37754fddb26883baa6399318c130524f | 1 + .../ed5648d424b5a21a684d02bc55bdcfab06ec276e | 1 + .../edb0a385324372442f7d831b7fa747c2a2ba5d40 | 1 + .../ede245d24c4ccbe651f556667d1de8b18984e6bf | 1 + .../edf48d71ea536f47f2ebae0ef4c1a54805cfd2bf | 1 + .../ee216fd86ba1f2f2eecc6892dba069f1fa7e2566 | 1 + .../ee227dd2c697b5ad500c732edea24bd9f2ec08a7 | 1 + .../ee39d37f93b56b4c318cb83ca60e411ee5c1abbb | 1 + .../ee4391649d8b6cf1ed2a18eef419b54a19d2f481 | 1 + .../ee4b75d279f94af5208664797cc453ca45044806 | 1 + .../ee537050d4b74465e99c77d79aec50879344edb4 | 1 + .../ee666d81fc0411dbdbf38406d49ba05685bee495 | 1 + .../ee92d4d96303e7296f561d5b3efe262b3993bc85 | 1 + .../eeb6e1a4eebe04ce7814c38efaf8b5b7e910296f | 1 + .../eef8d1a1e8c3a9566015b3ae089052a50d3c3ddb | 1 + .../ef1b9627be8307d947f73d84910a2d343187898a | 1 + .../ef34d2a06ed043b1d7aa5c55d07e649a98e022d0 | 1 + .../ef5018ccc4d868e150c22f85faea02a352f124d9 | 1 + .../ef588660a2f4df9f52c4f476036ae92b435dd8be | 1 + .../ef7b84160b7025ab4d29b8bb32de27500874c4e0 | 1 + .../efab9adce18cdbdd285db520ec08c755b0916a2f | 1 + .../efb25951d890dbd071c4a3811042fdb8e0bc4326 | 1 + .../efb757b9644c060f72a7441ae9f0dbb05935ddee | 1 + .../efbdf30300adcc55d7c50d4ec76a75496d6d7b7d | 1 + .../efc4b323ebe3c0b9e2f2fd7168ab4437570a54e8 | 1 + .../efce2a5687afc47a9a7951b0d14a86559eccd8af | 1 + .../f00c95582e31d9827eabb236ee8b4b776907a667 | 1 + .../f015ec4058e4e7ae0d1a64823882e2e3fe9f8bbd | 1 + .../f04d521c21ed8372ae0bcf98ee15b6ca83c85bc2 | 1 + .../f052250556f0a305782ffc367c106bf8213e5199 | 1 + .../f0b8804a6b3fa0ab08fb2e07758480377e212f0b | 1 + .../f0f31b265d33a5adb67af2f1fec8248f8855469e | 1 + .../f111543d0f442f268353dbbbf00ebe24c21f930e | 1 + .../f1439b2e5f242df93c3d5fd61e367f850098495b | 1 + .../f150268fcc20d8c1e1607d773fe9c2af148e9e8e | 1 + .../f1728d0e4771e35b1cb1998adc82e22eb67a65c9 | 1 + .../f172e0269b4ce4678ade6f0ac95a9448d2453792 | 1 + .../f17ba688055f4e28c6c763a1a67b55ffd27ab22b | 1 + .../f18786606f38657d15f1d007fa2934ea6034a605 | 1 + .../f1ab87a390b003a1f262909e41e5d3853c0dee70 | 1 + .../f1ac308d98f3a982e3c86ebf022541b3c7a53857 | 1 + .../f1b42b68e02cd3503158c2cedbad9f43b4a782fc | 1 + .../f1b9e75c583d069af4d354379ec7cbf02e95c41d | 1 + .../f1cfa6ecbcc68ba081804e6b531a970f6cc70cee | 1 + .../f1d42d84bf3c0ea75c9ac6babfdb06afac572bfa | 1 + .../f1e479e1e2ba063168c4201bc568c60b601c98f8 | 1 + .../f20f49c8c8a09c2b68a66d3640886588c1e95299 | 1 + .../f281cfc9b564fceae1f18905886e1a2ea6a79f8f | 1 + .../f29cde4e4d18f502a83e953d7e6aafc162b49fb0 | 1 + .../f2a7b6785e4184b100bb118d537c3e1fe7deed13 | 1 + .../f2aed5fc63d1322cbfa59dc10fc63c5c13905bad | 1 + .../f2b01b12b747c63ff84c1d178f5cd881a09d61d3 | 1 + .../f2cf8fc04a84276827038c4814930bd1166dcb83 | 1 + .../f306f010650c1ce3662a988f2d5c8848a114b742 | 1 + .../f311f3194f27d91bd26c7ac20214d331ade7f1c9 | 1 + .../f32541dee791305368453ac147924b5c2d9dfff7 | 1 + .../f34aa9739565ceed4d2a67fa8e24e1cffda032d0 | 1 + .../f36797074db1a3316cf9f79b8cedbea196a94883 | 1 + .../f3a1124f0e210f773fcb446a4c6325838f796dcd | 1 + .../f3abe34a0b2b561230223ebd55fa58c1abfa4752 | 1 + .../f3aefeaaf417737c9b08ddb588ac8f34f1bfd7c0 | 1 + .../f3b9a054bd33583afbecffad0407dcd117b60cb8 | 1 + .../f3c37d9c9bc7bbacd5acc05ecfa2dd6b3e4079be | 1 + .../f3dbd1cd81a692630c41a036e51a108069161d76 | 1 + .../f41b245dc4b63227dcd52bf8df204c69ef2c632d | 1 + .../f43a467e1ed501e4fae97b23c7ac5f51943b4a60 | 1 + .../f4466a6264c406cffaf61cd062c6954b8145b827 | 1 + .../f45bfc326aa2978cf872bbd25ac92e74c51b222c | 1 + .../f4604f24ef1262cff35502c140d3a3ab09e62650 | 1 + .../f47e1dd86121d4d47b5e315b8bc8f941d5c890ba | 1 + .../f49204f8e85d64be3490b7843476939194bca10c | 1 + .../f4cc235e3a3e0f11b34f866c952d52ba470ce96c | 1 + .../f4e60bca3a955a55d00e4186db841023ceef4e20 | 1 + .../f50995c18b1bea7d6e8f78c8db8139687517a781 | 1 + .../f50bbc9cda906042a1e0c756df37b20c36a36df6 | 1 + .../f54e6bed090f658f483733605be1def47c4a00f1 | 1 + .../f5584e332423dfd006828addcbd73f040328b087 | 1 + .../f558bde45b06e08703659c22eb17a9b25f4941d1 | 1 + .../f560ba3291103bb7f5cc015586c6946d5f9e8857 | 1 + .../f58c6d8117f18e36e7e31efdf23c18aea2a31b7c | 1 + .../f5a0c3cda376e7bd8f7a27caa053bef8617f451b | 1 + .../f5a0cbe081c8037a7f36d438e758b6bcd92abcbc | 1 + .../f5a7ff2dc8ee9ec1ef36b73c60de71d7978d3d27 | 1 + .../f5b5807a9afa7c7b8351abe9a32cdd85d696c15e | 1 + .../f5bbca8f5a7339d3dab2b5f758f426cdb744dd6d | 1 + .../f5bcbe0530388a9d1b0ddeb9fd52bbf9553589c1 | 1 + .../f5d29c01f03e55e2269af62ed6364a98353003af | 1 + .../f5d9f6f2aa6f7e44a24ecb63e2ccbe34ba6eecfe | 1 + .../f5f01b555c46d9d86c043b50cdf0dc05ea4c3d08 | 1 + .../f5f4bc663f8ff671a51d503c89c7a5659c0c37ab | 1 + .../f614cb3aadb14fc4cea6a3fa949cf1c4a5aa490a | 1 + .../f62efd7cbffa78cde24f12d7daf90b120c6b3e5f | 1 + .../f6389882692a6a18e427b73ca3a0a34f645e476b | 1 + .../f63afc3910d5b449d7d26586af8681218677fd6d | 1 + .../f64c19e45d11b07f585d65dd6f72bcd502d95a0a | 1 + .../f6514adef6dcf766ba7179320ec6c88126688614 | 1 + .../f6765d4b30feb17d15d4bd81601ea5788d8d26ed | 1 + .../f678ee4a403b466dde13be7e941db7ff7684a932 | 1 + .../f67b572dbad35568f4ec9ba53cafa2997991340e | 1 + .../f6840c641bb58cad923fc4f9c092164413ff4ce6 | 1 + .../f6907b785c509927b03981052c87de1c9ae5f772 | 1 + .../f69458974b285f9c2ac48a1bd10b3dff2d042a8d | 1 + .../f6a06f14f3641278ceae3733db1a7eff71fb3629 | 1 + .../f6c823a2b3203faddc06a15a61e6f0e3f3e7fe8e | 1 + .../f6d3771166a0c4e00527b2be21466030fb499521 | 1 + .../f6d618ef7f588f9fc237b18f4ad42a84337ec67e | 1 + .../f6e85bce5c033f269bbb51eb480ff58e9d814ed5 | 1 + .../f6f146c32b1b724af896fdd11df580e1dc8f0e35 | 1 + .../f70b704bb277d70481b756371e4d92b9dadb2d85 | 1 + .../f747e1181b2e9303715bc0aea1cfca3babf00705 | 1 + .../f75c71bf10464658e79f72142b2c327cd6ca3347 | 1 + .../f77abd655150de8bda3b775fd291d5b2bf27a1e6 | 1 + .../f77e7d751660a7149e80488c8245aeb9be6eeb1d | 1 + .../f796e5b0c5ce67017c553a21907fd6a51a1058eb | 1 + .../f798f952feda25e6fc4b37a429dc368f73d0d158 | 1 + .../f7a5375d5d273e7eda804ac9335745a3fcc568ae | 1 + .../f7ab44a4e73a9b24bfff6a263c608abce5696639 | 1 + .../f7b76430a96ffa6355eaf12167d0ef405e2669d8 | 1 + .../f7bc805d350c55cd8e24def5b79ca3b2fe88ae80 | 1 + .../f7c02de0b4f89c043a3ebcb28bcb0e1396fe0e23 | 1 + .../f7c0db2c2ed3c1e6f19acace4e10c0a99df88018 | 1 + .../f7dad92963bb917f67c0a5d9a11c7a623157603e | 1 + .../f7e399c76d4ec4bad55a5e054f90aaefbbefd54a | 1 + .../f7eb97d1c42b9d53be75b54f5a30490ace43fa77 | 1 + .../f7f77a67d9bea0dcf7942ed62f29985930122ff0 | 1 + .../f803ece8ba109526994448413d0b5389e89fec0b | 1 + .../f808813d157995b8d10c3cffd1f2616528fdad1f | 1 + .../f8136e4e492396052082b2d3eb7f45ce735b580e | 1 + .../f82150120ceb9a7b6d24c8144a2fc40fca6c7ded | 1 + .../f846835025106a0f7d7d18630b87f4321e626835 | 1 + .../f84d4edb22fee2109b5e00fd5ac471e49c15e25c | 1 + .../f86da2aa3ec8718d5308b84e38864225dfeb6819 | 1 + .../f880da185f238333598d20ee2e139229db739f94 | 1 + .../f881895a273c1bb8b76313a9f0ff65520ad27975 | 1 + .../f8835febdb55dca918a36795f2203f4ee4a6b841 | 1 + .../f8930f55c55efa927ccec4a3a273d7af679fe190 | 1 + .../f8d8d11d95153ea9449df09e90a108d0d46dd36a | 1 + .../f8e2668d6408cd99bb9b4144dccc869b5b5c3995 | 1 + .../f8f8928329f1f5ae3c966fb5ec2113e076eafcfe | 1 + .../f8f9451ddef15046ebb34b8ada8344e100e77c6b | 1 + .../f90c809fa2d5593e55f0033ebff4eb6de3bf7a4d | 1 + .../f92ae6d39d23d890f0a4bbb1700628cf97bfd5a6 | 1 + .../f92ff19d417dd30243bf0048d8947d33b4bf7064 | 1 + .../f950057a3fe68206273e224b1a0c92d75bf4cffd | 1 + .../f9527f53e0c01295c939d322769c4900690eac47 | 1 + .../f953c76798af4534303b789774638f6750bf064f | 1 + .../f95a0a2fc49acea853b2fa634e154189153c8e19 | 1 + .../f9ae968bede9072e9913f275110691863b21d704 | 1 + .../f9e9604adf8a8fa70a8a2d8699243ba825c4c268 | 1 + .../f9f75f9ba55d66c16536a85bc2406112ffaef2ff | 1 + .../f9fc9e2a4f2af623fc883937402f30bb39d7194c | 1 + .../f9fe421cb9a3952dc45c8d26a7ddd2f53b952533 | 1 + .../fa167d1943fe2df543ef85cf25a11984cbd5a5a2 | 1 + .../fa18264203439b69d71bc0bf47eb42c09a0276b5 | 1 + .../fa2f957cce50a9e152ca7a429346901042de9fc5 | 1 + .../fa49e364b5b789a639515d469e423d52b4437393 | 1 + .../fa4c5cdf26645ea0534a498e6eed0980cfb7a7c8 | 1 + .../fa597ee663f096b76cd93b293bc4d7f7aaefc262 | 1 + .../fa5f468e5077c7552905d4b235d938ba656a8956 | 1 + .../fa6ab5df5a5d808c4d736244d69510fa6e17f904 | 1 + .../fa7d0a81564418a5df2eae24548c51be6486a4aa | 1 + .../fa862d772ea0c551e8a2b2e955c3a314343a9249 | 1 + .../fa8814b8ee8c8c0b59933c5df3e62bc70882f43c | 1 + .../fa90b9f27b4ef61835f27c23a72f15ab0bc2f8d4 | 1 + .../fab23300d1e8e0ac77217a22517738b6de5afead | 1 + .../fac25d9ab05e1c85b45aa41798674daebf462237 | 1 + .../fad3ceab7d42e3ad2e07e8e88420e42ecf4dd0b8 | 1 + .../fae57409d88f4b4a8521c3bbd0560991c2a8986b | 1 + .../fb0c60f40b98f2127746a9a359165bc8d41dcb8c | 1 + .../fb18611c9ee4a416896469762bdeb28572310087 | 1 + .../fb193ee81245f14d9b19cacbf56cbcb01dec02be | 1 + .../fb3a40b01dd182dc32fd94d86be6aeec9cfda7dc | 1 + .../fb3feed4650211ed4fd84c29e022288219979e4a | 1 + .../fb47b82833fbb82a6a9844bcfa75012bfc49c9cf | 1 + .../fb56305966435f548db004e141dd614dcb71150d | 1 + .../fb6bbbb8192f592ebde7d1bb37924cade63c96c8 | 1 + .../fb803c7f3034af611f6dd19c6cd55245f319dd86 | 1 + .../fb84f0eaf5bbab71df0de66b8e502f2e52604fac | 1 + .../fb964d7fe5e195fa98766d8c4058c8258646e95a | 1 + .../fb9e6ec52fad74ca4a775818f110ba219adaadbb | 1 + .../fba8bb171f6333a2f8f8099ed7061ca7507012bc | 1 + .../fbae541afc8fd2842b660a15ba61db2dbd26dca5 | 1 + .../fbd1df6484bc96485135c2b29c3b125355c62848 | 1 + .../fbeb89304a55a7ab8a338b807ad02b8dd2ab9c28 | 1 + .../fc1908d2145aa6f1cf830f6aeb9bf24470454805 | 1 + .../fc6ad6441d0d3ba1260efa94e68b4af0576bf63f | 1 + .../fc6e7fbd1048ad4d4f9eadb18d79a7ddaddee244 | 1 + .../fc72b1ff88ff0bb9a8e7a27d860b1e727bc825b0 | 1 + .../fc833899bb452572fe6f3e84efd6737cca4eb786 | 1 + .../fc9c2ac36745e20f981008bf5f85f146b9c9dbb1 | 1 + .../fcc3f72c08a026d3c0f4cc50227793a26fc3efeb | 1 + .../fcd03d953e3452f116e4035d2029de953e62334d | 1 + .../fcd91aa7ad2c0011f8f2516f5687f9e91aa76b71 | 1 + .../fcda2ec36cb7652d368098a0c2ac64665164601f | 1 + .../fd03276208dbd6219a958f47d888d22fa303e89e | 1 + .../fd14286e8c496b3f62dea79de42d57a7b02b22fc | 1 + .../fd1a057fd69f2113eeeafc133d9d51c7cded9125 | 1 + .../fd1c6cdb67bcc23e0920c0b2724591695d7e88b1 | 1 + .../fd1d4fb758440d51c0db63f8a401ad4f7dd1ba6d | 1 + .../fd1f6bb68c1a0317e7fb3e9c65ce2b765717f38f | 1 + .../fd275d920066468018b3ec78708e01bbf4634f89 | 1 + .../fd30d1fabe3c70d63ebf6eb08fcc889f2062dd96 | 1 + .../fd4b486776c7fc4e964a57db37f46b6fb893446f | 1 + .../fde4e348195fef4158d57bce09b8132261e53404 | 1 + .../fe3a254545ba65877f7f12c1957e6983a9540725 | 1 + .../fe4991f96a4078203ed82f3dc9d57b0f5c8d7c31 | 1 + .../fe5a94896e814e80a5d4f0d17825ea303d136807 | 1 + .../fe754dfb4207b538736ac33f4d6d3a8b39ed7eb8 | 1 + .../fe8a403b551fce23551c1a364c5d7a9bdf4082b4 | 1 + .../fead4cb9efe769ed34fc79a6f7f7c301fa44b950 | 1 + .../fec0428a7d5b4dd2f894abbef22a4fd55b125e79 | 1 + .../fed7b4e8b0ffa8ba7ee920409e365993f8f23423 | 1 + .../ff02cab52406b52d736534063539b815a83e9ec9 | 1 + .../ff0c9a3fa047cac34488cf6902e39ceb0b31a1f2 | 1 + .../ff0ecc250f060fadb2dfbc788f027f6c46ef6c40 | 1 + .../ff269c4192d92ee1330ca6cb368ffaf3dec65d44 | 1 + .../ffba9a51f35e6cfeb9726e3eb3551989a55a2ab6 | 1 + .../ffbfc4371313a95615a944ca1fb473bf2569d7aa | 1 + .../ffc6076c34629ad5d440389f97bac8efcd2db5b7 | 1 + txscript/reference_test.go | 190 ++++++++++++++++++ wire/bench_test.go | 2 +- wire/msgtx.go | 6 +- 2763 files changed, 2954 insertions(+), 4 deletions(-) create mode 100644 txscript/data/taproot-ref/003af31dd0b5a50c2723531e8ca22ae8ca6e7089 create mode 100644 txscript/data/taproot-ref/005e61a50014d33f7309097490534db3c0dc65fe create mode 100644 txscript/data/taproot-ref/007f313a1a53428b7fc9eaf54c5d51be20e10567 create mode 100644 txscript/data/taproot-ref/00850c1cc564bd0dcbb02c3398f9fc8e0219a317 create mode 100644 txscript/data/taproot-ref/0089a0f18b0647cf2bfae0c93e9ae39b345d1611 create mode 100644 txscript/data/taproot-ref/00b6fe5a14ee4fb3bb65e0aa28e70cb57f0cd0b0 create mode 100644 txscript/data/taproot-ref/00cd1f1ac746e81ae27bfe1e9a383975d0bba949 create mode 100644 txscript/data/taproot-ref/00d07d91c86c11dbbd14f4edf55c1f496ffaf010 create mode 100644 txscript/data/taproot-ref/00dc037c98e799a31facfab68fce3187ad7a0f68 create mode 100644 txscript/data/taproot-ref/00e2723c3cce5d6fa2b7db987e5fbc1d75297650 create mode 100644 txscript/data/taproot-ref/00eb1a2b8aed4a406ee59371fa0a50e6679857c1 create mode 100644 txscript/data/taproot-ref/0108a92da87f766ee005ac0bb220f78b50d04101 create mode 100644 txscript/data/taproot-ref/010cc78772e75503cf488b6267f5891e1495c962 create mode 100644 txscript/data/taproot-ref/014aca010656e76077fe517e999ea589e88307d7 create mode 100644 txscript/data/taproot-ref/01686c55b9d9f3d0c2d9dc8c0911de32df21a864 create mode 100644 txscript/data/taproot-ref/016e25aa492396c1f2937c07dac87f3bce812041 create mode 100644 txscript/data/taproot-ref/017f425514c38506670a6136985cf2f693c1851b create mode 100644 txscript/data/taproot-ref/0181b63b032265ff6a54d3acaf33d2efc67028ca create mode 100644 txscript/data/taproot-ref/018284c1e780a7aacea0d945603d5f06254c5cfe create mode 100644 txscript/data/taproot-ref/01ca217ccf1ea0e39003e90d0d3573454b370bd0 create mode 100644 txscript/data/taproot-ref/01cc26fa177761f2440d4f78790adfdcb27c9321 create mode 100644 txscript/data/taproot-ref/0224ee3efd6d6c2e6024db65267c008a3786f0b2 create mode 100644 txscript/data/taproot-ref/0234f23ded5600eb13895b83e3d3208daa621654 create mode 100644 txscript/data/taproot-ref/026745c2e6a71ca361cb3f37fe3f4e9c3029688e create mode 100644 txscript/data/taproot-ref/026f12b427239f4351f951644afdf9e483ddc4bd create mode 100644 txscript/data/taproot-ref/0274119160b74eb12e8b0ea869012528e5c8c64a create mode 100644 txscript/data/taproot-ref/02a2d45e622dec5a4342e4be185659da883e8d6d create mode 100644 txscript/data/taproot-ref/02bb3113c2f000ec71e0cac539468d820cfa2df6 create mode 100644 txscript/data/taproot-ref/02c77525ae2279633746cc24153272f0cbebb2cf create mode 100644 txscript/data/taproot-ref/02d1c1fa4446780154693993cbb3b3357d7dc38f create mode 100644 txscript/data/taproot-ref/02f4d455a5e5230510c642f46a00e2819cbd49fa create mode 100644 txscript/data/taproot-ref/02fcf2313f765802ff09c238af833842580fe461 create mode 100644 txscript/data/taproot-ref/0313e7c2127076391d6fd9696d30081eb2c9bfb5 create mode 100644 txscript/data/taproot-ref/0325cc06523d6b80529e7b67ea669a8cacc195a1 create mode 100644 txscript/data/taproot-ref/032b54a2e80454a2b7039f32a4974095c2f018b0 create mode 100644 txscript/data/taproot-ref/035336c778f096bfe56ccd9c44ca36a275649299 create mode 100644 txscript/data/taproot-ref/038d58e7a5bd8cd3c42dbd68c099f5900b90ceef create mode 100644 txscript/data/taproot-ref/03ac2fb4ae30f213cec9edbaf2796b086134d050 create mode 100644 txscript/data/taproot-ref/03b65143f1009a2a8a2f6b758fd8559f040d207c create mode 100644 txscript/data/taproot-ref/03bc1ab1714e0ffffffd3593268beb217c603b54 create mode 100644 txscript/data/taproot-ref/03bf93a96878a9f8ab6cdeabb7da6656971299e2 create mode 100644 txscript/data/taproot-ref/03ec899fb91c58bbb5676ebce177b0b63fa704a1 create mode 100644 txscript/data/taproot-ref/03edb43f652ba7e0ad56e117bab26ed1b3cc0b66 create mode 100644 txscript/data/taproot-ref/0401cdbd85422acd1857a2cf6024ba4b7b5d909e create mode 100644 txscript/data/taproot-ref/040d05cbd66190be71c513b0ebd00bbc34debe8b create mode 100644 txscript/data/taproot-ref/04369027c0cf8f61083f8faeaf5d15a4bba2cb26 create mode 100644 txscript/data/taproot-ref/043ee2fa352668d08af2912ea4c7dc868039dd7c create mode 100644 txscript/data/taproot-ref/046dee126274f9efbec0b1803cf0483b40e0bc0a create mode 100644 txscript/data/taproot-ref/047736248915b6ec7bb882618f4c6428dc10bc32 create mode 100644 txscript/data/taproot-ref/0496f56b7283138d77bd26aa97936a80588bc908 create mode 100644 txscript/data/taproot-ref/04a0415662e8fe755a1cad7e31e996b0f9553a15 create mode 100644 txscript/data/taproot-ref/04a9e5bdcdafa1f723281d72593020692f3b5004 create mode 100644 txscript/data/taproot-ref/04bb5c8ad218b2ea6cbabde04b776a727cb804d3 create mode 100644 txscript/data/taproot-ref/04c14170bf3650e0dee112ba4b888f2e76fc3b69 create mode 100644 txscript/data/taproot-ref/04f498a7f3cfb530edcae02afc0d1476b8fbcd8a create mode 100644 txscript/data/taproot-ref/0526255fad6bcad83e0f38f3e175d8b55d0113d3 create mode 100644 txscript/data/taproot-ref/0530510aa69fa36a6377468b144a6daefe9e0779 create mode 100644 txscript/data/taproot-ref/05645a121a9dee2f1e618d22d9c0e11f1729c008 create mode 100644 txscript/data/taproot-ref/05723fdb3ecd4a3d4acc01d8ce541e74f11ba38f create mode 100644 txscript/data/taproot-ref/0576b0175f23da9546b0ed7d213c1bdf55941dcd create mode 100644 txscript/data/taproot-ref/05a7b91a73da2203e485ff51426532165c688040 create mode 100644 txscript/data/taproot-ref/05d3a449ff645092d95ff6fa07d433d341861837 create mode 100644 txscript/data/taproot-ref/05e7d1f74a0f0d69935dcee5b60fd0b08ff396cf create mode 100644 txscript/data/taproot-ref/05f2dfea38b07d623e2947cc2c7963f25a45e24e create mode 100644 txscript/data/taproot-ref/05ff688173b90131ed218e693cd3e0735c88955a create mode 100644 txscript/data/taproot-ref/060f27e89600b0edaefb344b00420aa71360fd11 create mode 100644 txscript/data/taproot-ref/0621f65ed4f98e0fc3ba2caa915de84ac2773b64 create mode 100644 txscript/data/taproot-ref/064cb40080f9955f34713af8c9ccd370c7ce8d39 create mode 100644 txscript/data/taproot-ref/064f3862567d3645a67ad42e8f1234919491ef00 create mode 100644 txscript/data/taproot-ref/06689eea577fd577cf0ed48baa3396126bb6f1b5 create mode 100644 txscript/data/taproot-ref/0672af82ea3c78b3ade4b7424ecf5c00466fba2e create mode 100644 txscript/data/taproot-ref/06882dd6d50dc8061c56b887fa16764a4db5cc51 create mode 100644 txscript/data/taproot-ref/06aa8b12e6ae5c391fb3d92c4050218d552b6923 create mode 100644 txscript/data/taproot-ref/06b7ea9f43da11b479b267aca3bdd7cf6fb9cfa7 create mode 100644 txscript/data/taproot-ref/06e74af8b10a6ab9ce11036f2747f8034ec3febf create mode 100644 txscript/data/taproot-ref/06f54531f7cc822f36462b303f5eed8313ca07f5 create mode 100644 txscript/data/taproot-ref/07249b6446b452a9005766194cb824b77c6ed600 create mode 100644 txscript/data/taproot-ref/0725dac7b6c36d404b706902e2a350065ba66fbd create mode 100644 txscript/data/taproot-ref/073b21ccb622912fef49f0555d5ed7b6ea85ad7e create mode 100644 txscript/data/taproot-ref/07904e76401a888153be57bdc173982a4396aea3 create mode 100644 txscript/data/taproot-ref/079662a69dfd16ca9215a4e0c822fc44641e72ed create mode 100644 txscript/data/taproot-ref/07991f2bbd7bbe3fad499b0c428f795590321613 create mode 100644 txscript/data/taproot-ref/07a56716b603afd041d05639404b37744bc2b83c create mode 100644 txscript/data/taproot-ref/07aa3010d9cc23f67f6962a7c18f7dedccd7855b create mode 100644 txscript/data/taproot-ref/07ae5671fc31d245f515f5c967b4e7cfed38567b create mode 100644 txscript/data/taproot-ref/07b8ee857d10f18474e7471c3c27d10be12c5f25 create mode 100644 txscript/data/taproot-ref/07cbbc0e4129794730bb9bb49d334b497f11b422 create mode 100644 txscript/data/taproot-ref/07d68512aa206614c478ec869a8b7d4f7c32333b create mode 100644 txscript/data/taproot-ref/07ff10e93b7bf06e8da854a647ad08d5bc902326 create mode 100644 txscript/data/taproot-ref/08106eb8543994958b201f3ce5f42dbbf19adf37 create mode 100644 txscript/data/taproot-ref/081a75fb52ef536975050ff3192f6c516b3b557a create mode 100644 txscript/data/taproot-ref/08421b069ef3b27abeb764e8412aa879c8bfb0cd create mode 100644 txscript/data/taproot-ref/08630f23c6a755790aea6ed91128183d6ddc8291 create mode 100644 txscript/data/taproot-ref/086661b19fe6034d3748295413e2b4d4251157aa create mode 100644 txscript/data/taproot-ref/08a0635b26ef56d2f6ddd4c31295a8bbde840584 create mode 100644 txscript/data/taproot-ref/08a19ba6422f65b65cacb3f20b5507bca39fffc3 create mode 100644 txscript/data/taproot-ref/08b5c0ff184e15e9c21e4949e2382b9a71623d3c create mode 100644 txscript/data/taproot-ref/08b74fd5e5bdcfc0a22933abb14c20399138f612 create mode 100644 txscript/data/taproot-ref/08cb0cb08cfb93d7ca744dbf018072b119fbc650 create mode 100644 txscript/data/taproot-ref/08cefa50635850a5a6caa88ddae4d4e4c5178f8b create mode 100644 txscript/data/taproot-ref/0918ed067691e99a0ac65b680c99b8a0bd6d2dc2 create mode 100644 txscript/data/taproot-ref/0920b0864e2f856ec01587533e768fdc9f982a59 create mode 100644 txscript/data/taproot-ref/092dfb3e8b68e6142fcb0a354c4d02c23428b870 create mode 100644 txscript/data/taproot-ref/09342cfa6e3461e698ef1f6aceb83fd4a3ccbf35 create mode 100644 txscript/data/taproot-ref/0942d800ed811d505130b0e5cca50e722fc4f19b create mode 100644 txscript/data/taproot-ref/095bca4fc65d75681b759e14d34e7a5987625ab4 create mode 100644 txscript/data/taproot-ref/097dbe987c217c3d9b230bc0e634a9e3f0bab2fd create mode 100644 txscript/data/taproot-ref/09b3e7123f40c4ddb240073a912a440a18168c13 create mode 100644 txscript/data/taproot-ref/09c225b7d61512e189a466c46243a4511b6eae8d create mode 100644 txscript/data/taproot-ref/09cd349f59ff286840fb04789da01062c5d83ba2 create mode 100644 txscript/data/taproot-ref/09d7f478f35e48679ca5a97a08febfa49d510081 create mode 100644 txscript/data/taproot-ref/0a3e2dd5f11a2182d7b86b927a600bde565229a8 create mode 100644 txscript/data/taproot-ref/0a9a9a6e04b0e55c5a90ca23c2586a07ae1fc542 create mode 100644 txscript/data/taproot-ref/0aaeeea67c9e79315c703c56429535fd670ef5aa create mode 100644 txscript/data/taproot-ref/0abded429f191b0375a464688f06bd465af7c644 create mode 100644 txscript/data/taproot-ref/0abdf3a09f88ee47573f9509a323dfd8af89e021 create mode 100644 txscript/data/taproot-ref/0ad139668541c092541da58168e6488a1191ff58 create mode 100644 txscript/data/taproot-ref/0b0a37b5c9ef3c034545cbefc3e8de97c8b5ea05 create mode 100644 txscript/data/taproot-ref/0b0f9ae5467a2c8d14e86527b264cacbf4871500 create mode 100644 txscript/data/taproot-ref/0b37dc29cfcef1377a94a17297a0525504b5a9d2 create mode 100644 txscript/data/taproot-ref/0b7236484ffa4dee58a006bc3b9e51c30e5cc903 create mode 100644 txscript/data/taproot-ref/0b727481698d5b6e33b991da896215f0527335a6 create mode 100644 txscript/data/taproot-ref/0b931370dfff16b9e6d9a7a333e61cabe23290eb create mode 100644 txscript/data/taproot-ref/0bc98deaaa9007629b3338d906d73f87abce0b62 create mode 100644 txscript/data/taproot-ref/0bf313616424ee4fc95cf71286563567fc87c472 create mode 100644 txscript/data/taproot-ref/0bfc8b69a3702ac6986ce61b00e837a148e7d0eb create mode 100644 txscript/data/taproot-ref/0c00a8351b02f2185ea30aa4052174b38417e0ff create mode 100644 txscript/data/taproot-ref/0c02f78d8dd01b33e94abaa865ee6a9792f4ccfa create mode 100644 txscript/data/taproot-ref/0c043c49e6d5aafcf072e6be1be89160111fcb16 create mode 100644 txscript/data/taproot-ref/0c10be31ac329baf66d4d083563e6a9c3ab9ee59 create mode 100644 txscript/data/taproot-ref/0c12817899b35dadda1aee2d0a376b1e6fca73d8 create mode 100644 txscript/data/taproot-ref/0c2099a1366325dfb20d310e00b1c1554e93defd create mode 100644 txscript/data/taproot-ref/0c4d9a60206c9ad9b61b6120b3b5495408989e96 create mode 100644 txscript/data/taproot-ref/0c6dc14de0b80f72306e015b7560fef8a12f722c create mode 100644 txscript/data/taproot-ref/0c860ba9e47e23ac7ceaaa948e710e0253317ad1 create mode 100644 txscript/data/taproot-ref/0c90542e3f64cf4c09f66ad39471bbed839d46af create mode 100644 txscript/data/taproot-ref/0c91906e6830ed3ad8eba843f2cd7c66205a7981 create mode 100644 txscript/data/taproot-ref/0cbaaae8f169bef4c71cd090d475e96cc8277741 create mode 100644 txscript/data/taproot-ref/0cfce5f569e35c19633d12676981cda0b47a34b9 create mode 100644 txscript/data/taproot-ref/0d1dfc0136b588b721884040ebf5911514ebb74f create mode 100644 txscript/data/taproot-ref/0d25d4167a2171b28beda354bc7a6b814d718e10 create mode 100644 txscript/data/taproot-ref/0d265e43ba90ce1827ee538563c6a293b0b03ff8 create mode 100644 txscript/data/taproot-ref/0d3ce2afc206b93ee7c40177e168a295fc3e5ce0 create mode 100644 txscript/data/taproot-ref/0d4d3db873cac71185de9e2fa4462b2f3ba96462 create mode 100644 txscript/data/taproot-ref/0d5ecc8d0c063c2641c3a8e7adff9ecb0323914a create mode 100644 txscript/data/taproot-ref/0d65edb0c2f57a76df2b15cd2c722b18edffbacc create mode 100644 txscript/data/taproot-ref/0d687e26341ba489f3d7be5d0b46f4beacaf8358 create mode 100644 txscript/data/taproot-ref/0d6ac2e508ad66fe5e2ceb784535d11ee75cbe2f create mode 100644 txscript/data/taproot-ref/0d75732bc24cbac5dc017bb967142c5648d55bfd create mode 100644 txscript/data/taproot-ref/0d89c8dca6b7a1af5614348af7dd5ae2f65190bf create mode 100644 txscript/data/taproot-ref/0dd2ab05d7639afe71f965b79bd7092a935732e5 create mode 100644 txscript/data/taproot-ref/0debebb3108bcd03c6d5ce9c5c2ce1a64f8da172 create mode 100644 txscript/data/taproot-ref/0e03e6819458e3a55e6655f8ac2fb5cb9b28406b create mode 100644 txscript/data/taproot-ref/0e1d5cb6786009b8f3825aeb3f4c7eecc240bf0b create mode 100644 txscript/data/taproot-ref/0e1f79030f3681187ce4b16bf43133d56c470a63 create mode 100644 txscript/data/taproot-ref/0e229a80fe4e2619a4b272d19ce5815986d08fa2 create mode 100644 txscript/data/taproot-ref/0e27294bb1dafe333a689bcad39dff7fb6f9cddf create mode 100644 txscript/data/taproot-ref/0e28329dee72cdf3ca474e54b4eae5fb8c42ce45 create mode 100644 txscript/data/taproot-ref/0e292d3b3af29268349fe695e0f7ad74c422612d create mode 100644 txscript/data/taproot-ref/0e41c7f53cff3726f8dbca36445f5bb99cc7515f create mode 100644 txscript/data/taproot-ref/0e73fd872d8f71896397723287ddf1497ea61297 create mode 100644 txscript/data/taproot-ref/0ea17004d718ec4b5b84011a18828cf136f86973 create mode 100644 txscript/data/taproot-ref/0ea4e4491ee2abc4ea52e48ba33eeccf62d5f85d create mode 100644 txscript/data/taproot-ref/0ea84a4a5eee9c0cfe8bd52347d11c08b97d6640 create mode 100644 txscript/data/taproot-ref/0eb26606cb3895e3e7c3160a2acb1dd55cfde903 create mode 100644 txscript/data/taproot-ref/0ec71de4446b68520af7b2f5cb5495f2f7d56bbc create mode 100644 txscript/data/taproot-ref/0ecc927da181cd3e4cf9d00b158c6acd0700b7c0 create mode 100644 txscript/data/taproot-ref/0ef9e684b87a52e1d2ec2b274d91ca104093f268 create mode 100644 txscript/data/taproot-ref/0f0de5c345a12934d91427634192d4040e5bd1fe create mode 100644 txscript/data/taproot-ref/0f1aee7720bb0ab848210f3e547b18c4431e3651 create mode 100644 txscript/data/taproot-ref/0f2ec0ef703ae34c9801d778277b221e6ec19ba7 create mode 100644 txscript/data/taproot-ref/0f51e2a5ab57413a930a436edf258d17d6ae7de2 create mode 100644 txscript/data/taproot-ref/0f7b105b71e9cb68726584b4fa24c0ebd801c4ca create mode 100644 txscript/data/taproot-ref/0fa616a640ec4b881c4c4ea08e1a39f481403fe6 create mode 100644 txscript/data/taproot-ref/0fabe142a692b593ed073f5db1ef2aca01dbd689 create mode 100644 txscript/data/taproot-ref/1000a469dfca1be2144a6563e3bc8e3f5ceb2448 create mode 100644 txscript/data/taproot-ref/1007d21149445ee61da9ad4413d7acefa9ede7e3 create mode 100644 txscript/data/taproot-ref/100be162498b413ca391dea2387d07097432e64b create mode 100644 txscript/data/taproot-ref/101afec325ccd0ecfd32b22bcb5ddb64cbc1c497 create mode 100644 txscript/data/taproot-ref/102f84dec76aa32c7c32a67b8398d3433fd9c124 create mode 100644 txscript/data/taproot-ref/10549677366e93a6b247cf85ef6b109794e927a0 create mode 100644 txscript/data/taproot-ref/10624dd984bc11b57e154d0125049824624ef4b9 create mode 100644 txscript/data/taproot-ref/106f9a1f4925d539eab0171af97bfe996099ad01 create mode 100644 txscript/data/taproot-ref/107e2cdcdfabb3aca2ab5aa2fd3c97288ca30c94 create mode 100644 txscript/data/taproot-ref/109b57979771e9a623eab0dbd365a6eb604e4d39 create mode 100644 txscript/data/taproot-ref/10a884685231a301c2628f0607b449081b250ab5 create mode 100644 txscript/data/taproot-ref/10e147455c54d7bb8f4395e8f52666ee498a10a3 create mode 100644 txscript/data/taproot-ref/10e2ba2a40c7f4b5bbe26a0ae7a814ef9883672e create mode 100644 txscript/data/taproot-ref/10fefd7899096dc27cf05039ac9a172231d52173 create mode 100644 txscript/data/taproot-ref/1113b16ac0b3e4b76353eb896e7272061f03ff8c create mode 100644 txscript/data/taproot-ref/1131434b4bb6f2acbd59abb881c239975a1116af create mode 100644 txscript/data/taproot-ref/117e130d533574c601aab37e70b93bae134a6527 create mode 100644 txscript/data/taproot-ref/1184f4a41ef45af98fbb77736bcca10e157c347c create mode 100644 txscript/data/taproot-ref/118b63929e90757c8ca1ec818ecf53f8b71c70fb create mode 100644 txscript/data/taproot-ref/11b1f9db49bba588d8f418e89843ef901274fe93 create mode 100644 txscript/data/taproot-ref/11e26aa15592a14b6f7dc59ed4225b0ceeca2418 create mode 100644 txscript/data/taproot-ref/11ef5be6a614ca068f2c89bc602378f8ce71d763 create mode 100644 txscript/data/taproot-ref/121e9e0d61998a2f829c791e9f23a065b8ce683d create mode 100644 txscript/data/taproot-ref/122e57288341172f17f63e1689fc9a205e9e5905 create mode 100644 txscript/data/taproot-ref/1260bed4953f82e80f379c79bc4484db28c58d8a create mode 100644 txscript/data/taproot-ref/126e5c88c57ce073bc1e63e4306d21823db4b99a create mode 100644 txscript/data/taproot-ref/12bcaf48556b4780abcb73c4f32bd274ea7861bb create mode 100644 txscript/data/taproot-ref/12e033c1a8f3298a775b13078a77bc8befe4567c create mode 100644 txscript/data/taproot-ref/12e5f4d526a722bc9b8f2af83ae028c8ee6b9027 create mode 100644 txscript/data/taproot-ref/12fada550b4d90c67f307a0d563ae38283c008fa create mode 100644 txscript/data/taproot-ref/13080e256b05f38789902f0dbbc437401d15a3f2 create mode 100644 txscript/data/taproot-ref/1318e44a20cde77432578f5126e255855a0f8104 create mode 100644 txscript/data/taproot-ref/131ec09b5ca700e6a035eb50138f6a7f62fe3f91 create mode 100644 txscript/data/taproot-ref/1337852e30e2d514c14e8123b84fadb9d4aa882f create mode 100644 txscript/data/taproot-ref/136bc03e80bca2dc5f71c4fdf91e7d690eac78e2 create mode 100644 txscript/data/taproot-ref/1390c111cc1ca46caab6bdee16d74dd49519fb4f create mode 100644 txscript/data/taproot-ref/1395575564b7da66e3b458131eaed79bc605b605 create mode 100644 txscript/data/taproot-ref/13c9792e4f626e8f900acfa50cf122a5f5f15030 create mode 100644 txscript/data/taproot-ref/13d37de420974d4290a6029f20175feb02e1106e create mode 100644 txscript/data/taproot-ref/13d9b1cfc7b7864ec3f85c71a1046df30cc17b62 create mode 100644 txscript/data/taproot-ref/13ecc0464cacec7245082422e8f3212d959e0fa9 create mode 100644 txscript/data/taproot-ref/14450718a3a9e2266004b863df27746606f071ae create mode 100644 txscript/data/taproot-ref/146b0be5a219a70b803fc5f82ded6f34e4cf7a6e create mode 100644 txscript/data/taproot-ref/1477a76ad0e64b74908b0f8a89549c7cf7190288 create mode 100644 txscript/data/taproot-ref/1493716a3ca7c3194959cd177b8dd531b04b0b9f create mode 100644 txscript/data/taproot-ref/149679a6778ca49110eaeac21b33cd449242eb91 create mode 100644 txscript/data/taproot-ref/149bceae555709818ddc8eb34d3cf4b508780b88 create mode 100644 txscript/data/taproot-ref/14a9e9b7200758410bd419f2b0954ec253e17889 create mode 100644 txscript/data/taproot-ref/14b46e9b808aa20b426e21803aebd6efffef133f create mode 100644 txscript/data/taproot-ref/14b583f6a2bb67ac548a6daf674748880c14916c create mode 100644 txscript/data/taproot-ref/14bac90ea6a6692cf7202b96a1c18e47f81a055a create mode 100644 txscript/data/taproot-ref/14d0d7bc3443d31977bc6035b1a9bce2c6dc9114 create mode 100644 txscript/data/taproot-ref/14d9a8a4291206e2c4d73120dc485bd077e5f66d create mode 100644 txscript/data/taproot-ref/14ffecf99f50d1adde6ff14120965c878f744781 create mode 100644 txscript/data/taproot-ref/15032320c16e26b0069cf1571846247d073f2efe create mode 100644 txscript/data/taproot-ref/150b2d12becd542c0352fdc80bbd85c2901d8228 create mode 100644 txscript/data/taproot-ref/152491c8478252c98640ae41d5813cd6cc4800a4 create mode 100644 txscript/data/taproot-ref/1532d9cb1517dd25a5c8a93eb64d3962a52cf4cd create mode 100644 txscript/data/taproot-ref/154147c0c82e41a7cfdb7b8295df125020cd7113 create mode 100644 txscript/data/taproot-ref/154b30ae55351cbd129d9b1b6a6311572840bb26 create mode 100644 txscript/data/taproot-ref/15541041a721e558c8cfa7f4ee5f4d09fa6c9065 create mode 100644 txscript/data/taproot-ref/157183c1796c9575b6c576a29c98f58fbd42356c create mode 100644 txscript/data/taproot-ref/1571fe984911dc73398ce28defbf71e715958a81 create mode 100644 txscript/data/taproot-ref/157aebc161b66c638243c0a814262c48979b21de create mode 100644 txscript/data/taproot-ref/15b38d795c9bb9ef573b4d2b1ec4af8fc0cd8fb6 create mode 100644 txscript/data/taproot-ref/15bed2762ca16694fce3754fdcb0fe404484b18c create mode 100644 txscript/data/taproot-ref/15d389f49e1f412ed725252d3ee81230a2e81cd0 create mode 100644 txscript/data/taproot-ref/15fcafcc7469d59709774013df0fd9633e820008 create mode 100644 txscript/data/taproot-ref/16128f27ae921b87284e0eab75845884e009c865 create mode 100644 txscript/data/taproot-ref/1630122f5bef1592ca6b6280297bd620d8ce0ab9 create mode 100644 txscript/data/taproot-ref/164113b42e586e2e8ce7bb6fccef9f52a5136708 create mode 100644 txscript/data/taproot-ref/164178c636e1e1ccfbe67f53e9209ff1c0e8584a create mode 100644 txscript/data/taproot-ref/16431b60ce2185dc8a3e19f1b9325a1078131515 create mode 100644 txscript/data/taproot-ref/1658b5c8f7c6d3672d694462a7f53ad3f3596d38 create mode 100644 txscript/data/taproot-ref/166cd55c33178000f9e3e3b366ace5266964a5c3 create mode 100644 txscript/data/taproot-ref/167a4033a1f4c30b87898758c3868c1025df1694 create mode 100644 txscript/data/taproot-ref/167fe32905b764460a1199e4a4ab3d84ef186e2e create mode 100644 txscript/data/taproot-ref/1680d648bb0d496b0b5cdc71bd31f42d092b5e31 create mode 100644 txscript/data/taproot-ref/168c2988106ea01a8121eba649b024715de5122f create mode 100644 txscript/data/taproot-ref/16acfa58909fa72c2eecfaacc8866e7dd1f42fda create mode 100644 txscript/data/taproot-ref/16b2bf568fa5aa6e4b5de39fd290f6de49b091ec create mode 100644 txscript/data/taproot-ref/16c6bf5c5a6caf8746580f9e01ec4e218a4c0e39 create mode 100644 txscript/data/taproot-ref/16ecdda3d618db946d6033f96c780764642e0471 create mode 100644 txscript/data/taproot-ref/16f6f25ce07eadca0f3c82818b8910b5006b6aa5 create mode 100644 txscript/data/taproot-ref/1715e26f824103c322e360c6d3c237781724ca4e create mode 100644 txscript/data/taproot-ref/172062063b7ae63dcffacdd6b98414054d06633e create mode 100644 txscript/data/taproot-ref/172b85f2524cbd3f0ca1a41380566b1648c8c405 create mode 100644 txscript/data/taproot-ref/172ff5cf4d0d01f9ac160be767a1b233dea05ffa create mode 100644 txscript/data/taproot-ref/17405fca2ae8f08cec8849c6a750217abef9ff89 create mode 100644 txscript/data/taproot-ref/177f3355a5b98fe40607bd5da8383d7129c515d5 create mode 100644 txscript/data/taproot-ref/177f56a1fdc5cc3198a785f6f5e7a55d8c324f16 create mode 100644 txscript/data/taproot-ref/179b29b5e6ade731ba119866f25b6743232bd3ec create mode 100644 txscript/data/taproot-ref/17b2c3c5c8f5c6d4e3b517021c8e26c982fc552f create mode 100644 txscript/data/taproot-ref/17cd80eebaac8182716c6996ad037efac35af699 create mode 100644 txscript/data/taproot-ref/17fccd13627419da75dd075f405d0c40a09c652d create mode 100644 txscript/data/taproot-ref/184dbb048070da2a1db945f29853600246189da2 create mode 100644 txscript/data/taproot-ref/186d4e3b056dbde38d01af9a2095f2b550b930bb create mode 100644 txscript/data/taproot-ref/1870a7b0cbdbdbcb7e9f1d248928fe0dca885fbe create mode 100644 txscript/data/taproot-ref/1878d0c6c90056867949699c2702dab1671a5739 create mode 100644 txscript/data/taproot-ref/187dc420ad18b5fb75f0f40dcfa22e824b23bbd4 create mode 100644 txscript/data/taproot-ref/18822bf70764f3c01f808cd81031bdaa811edcaa create mode 100644 txscript/data/taproot-ref/189034044dacfcbaac5a98bbd0a33a369683d2d8 create mode 100644 txscript/data/taproot-ref/1891c772f3ce8c760b0cf1b52164fe1d2e4ce605 create mode 100644 txscript/data/taproot-ref/1894c4ad4a51725e14a4b3ca4124be935f442f98 create mode 100644 txscript/data/taproot-ref/1899c6c029807a2b6fb9c8709343768c03f3405b create mode 100644 txscript/data/taproot-ref/18ae04d1c49da35415f8e30e1757321ada62e83c create mode 100644 txscript/data/taproot-ref/18cd769c18f505e8bc05856ed71e114b5bd9a022 create mode 100644 txscript/data/taproot-ref/19056ae532d1819a4355eff6310ab655a5030df5 create mode 100644 txscript/data/taproot-ref/190cfc23dd00d10a83315e6bc368d40445cd322f create mode 100644 txscript/data/taproot-ref/190dca39f195f8973c60e414fa6fa6aacd3d9290 create mode 100644 txscript/data/taproot-ref/191602968fa2af7edef6e40a0c4e4b9e4ef4cd75 create mode 100644 txscript/data/taproot-ref/194da7e8add6b9a1ecf41a75f040b4611f016a09 create mode 100644 txscript/data/taproot-ref/1969e36c75fe223b6de50a2e92c6ce56dd4915a3 create mode 100644 txscript/data/taproot-ref/1970570c77db050bc51d853165e59487dd05c1a7 create mode 100644 txscript/data/taproot-ref/197071c336e5f96eeccaa2d253d5c00e0ac7febc create mode 100644 txscript/data/taproot-ref/197a3fa4a03436efcb2a86e1f8cbb45de1371615 create mode 100644 txscript/data/taproot-ref/19928329d12601dfd9c4a12541e9799fefb5439e create mode 100644 txscript/data/taproot-ref/19a982b7ff350572fab07d8c7397bd3e8f2cc04b create mode 100644 txscript/data/taproot-ref/19b94494f911d6c8dffa42a0570e686d8d385d0e create mode 100644 txscript/data/taproot-ref/19ce749d29e4620af1b8364a70b233842f7e9d56 create mode 100644 txscript/data/taproot-ref/1a199a3cd2f3a67e25e36bd4711b535ae3d24e31 create mode 100644 txscript/data/taproot-ref/1a3a8c18a8e82421d33989ed4d05f5485999b0db create mode 100644 txscript/data/taproot-ref/1a83bda864530d8086caf59fe1272ad5768d34c7 create mode 100644 txscript/data/taproot-ref/1a9368b5d21e42219df4751485b7f522507fdefa create mode 100644 txscript/data/taproot-ref/1ab6d3c20509931b1abf61a6b45d8069679b66fe create mode 100644 txscript/data/taproot-ref/1af45f5f9b4d38fa9b4e939f3e3622bcdf2d29d6 create mode 100644 txscript/data/taproot-ref/1afbe3f769c38b8e8b6210ef4c1e57bc6cfd7f8d create mode 100644 txscript/data/taproot-ref/1b13c8bd9a345bdcf71eaa1078ef4cb752b3da96 create mode 100644 txscript/data/taproot-ref/1b2543854748d5b37077ed3e53a36309f5330a50 create mode 100644 txscript/data/taproot-ref/1b3c874362224cdb658666354aa6fb9efff9b371 create mode 100644 txscript/data/taproot-ref/1b4bc136aef0b80666d85ce3d93b7996d0ce7ab5 create mode 100644 txscript/data/taproot-ref/1b5a41cda693f9d63f77b9b053dbac3106aea789 create mode 100644 txscript/data/taproot-ref/1b68c33f2aa26138257e984d7c57524a609332e4 create mode 100644 txscript/data/taproot-ref/1b79cd4b2e7a4b311359e56e468853036d3681d5 create mode 100644 txscript/data/taproot-ref/1b8f51ede6850bb667b5fd80d78e02cd4832d753 create mode 100644 txscript/data/taproot-ref/1bbde099bad78eb5021b57eaf4e9fecec63162ce create mode 100644 txscript/data/taproot-ref/1bc3e95ef1ef57164dee0340314916513b071491 create mode 100644 txscript/data/taproot-ref/1bc5747eb674dd470ce9e8f236e8c461bd9f5491 create mode 100644 txscript/data/taproot-ref/1bc76532e1949261ee2079d9ce81e5bd2ee2c56a create mode 100644 txscript/data/taproot-ref/1bfe6046e6cdc344b877ad37196692f2724dfb96 create mode 100644 txscript/data/taproot-ref/1c0b90070d5af0e0da662d27418affd7255bb328 create mode 100644 txscript/data/taproot-ref/1c1b10df48009861e679c78f57233fcbab1c9c74 create mode 100644 txscript/data/taproot-ref/1c1c68f02884233862b5ace3f063b648ef1a8f5b create mode 100644 txscript/data/taproot-ref/1c2a334bb5693def73177ba056d467309d1a592a create mode 100644 txscript/data/taproot-ref/1c34962adc291e2c8bf6dae66b8fb9c765b86439 create mode 100644 txscript/data/taproot-ref/1c385e281c4e1f86fe4c3b41f133fe0f1ad20791 create mode 100644 txscript/data/taproot-ref/1c561097325c97828153532b8c7b95b14e46dff4 create mode 100644 txscript/data/taproot-ref/1c7cf3e3c8d41ca4743e00d88ec0434c6f31d4c9 create mode 100644 txscript/data/taproot-ref/1c903f96be3cd8956476fb915624fb89666a187c create mode 100644 txscript/data/taproot-ref/1c929a0b875b383b7f3db0d168424cf2ba6d3cd5 create mode 100644 txscript/data/taproot-ref/1c974326af0bc49a9f389a9c91eda58bdb47ef17 create mode 100644 txscript/data/taproot-ref/1caae5c5cd8d5b5cbaed34c3bffbfa19df6aa109 create mode 100644 txscript/data/taproot-ref/1cb39f47f10b248d485afd4c83fa450fe4dcf928 create mode 100644 txscript/data/taproot-ref/1cc704edb370c2b52aa731bd30ea881ee0b2eb53 create mode 100644 txscript/data/taproot-ref/1cf397672140f803d1c48c64b7a9b55ed395d983 create mode 100644 txscript/data/taproot-ref/1d396736b3bc9203fa55467a0775f7a058a44b05 create mode 100644 txscript/data/taproot-ref/1d4be0ac5b202d439cadb143602ea3459a3eea33 create mode 100644 txscript/data/taproot-ref/1d66bb4f8ee00895bb9533eb0329de6d26b4e395 create mode 100644 txscript/data/taproot-ref/1d6b45d432e1a9f7bcf2692c87fd3865d9e96451 create mode 100644 txscript/data/taproot-ref/1d6c3731bc1125e0c52a0356e80d994f891c5e9c create mode 100644 txscript/data/taproot-ref/1d83703eed5baa3599b3562c9ea6f395f0ecacbd create mode 100644 txscript/data/taproot-ref/1da56d6e6d60e92c14472e47b665a85be68598f1 create mode 100644 txscript/data/taproot-ref/1dd5926d9df81e85da3075d37f0702718c88900e create mode 100644 txscript/data/taproot-ref/1ddf875ca22b308639d7b1cab6ee74ea77bc6bce create mode 100644 txscript/data/taproot-ref/1de45c6257377171ec1383ff685db7ce8e13d8c4 create mode 100644 txscript/data/taproot-ref/1de7bbede303fc60efdde225de97fe6e4cfb88ef create mode 100644 txscript/data/taproot-ref/1df8c615c5b7d5080d1019801137bdc97c72d639 create mode 100644 txscript/data/taproot-ref/1e2b8ba68f2655f0f5159ba8ee446f920bd6f384 create mode 100644 txscript/data/taproot-ref/1e2f14f392e271b5a594679f83b4847d83b8109a create mode 100644 txscript/data/taproot-ref/1e2fa5e498506cf0c5adee563fba8cdb0900cb86 create mode 100644 txscript/data/taproot-ref/1e32a9cc12b73e8a61aaf4c846d1cd0ffa78bf93 create mode 100644 txscript/data/taproot-ref/1e5a2d83584c4f1ccd8746aa4cc87f3b5c520e63 create mode 100644 txscript/data/taproot-ref/1e754a40c050fe3c356b0e253ed22633f2c5edb5 create mode 100644 txscript/data/taproot-ref/1e841722ec03b5be4c1001e90d8019bf9e01d892 create mode 100644 txscript/data/taproot-ref/1ea62bf92cf8078007e5cd279d0ac921980c1395 create mode 100644 txscript/data/taproot-ref/1ec26ee9e524029b8cf64e318125007a12c085d1 create mode 100644 txscript/data/taproot-ref/1eed48f62357914c0650cba567a06e37071db51e create mode 100644 txscript/data/taproot-ref/1f06a021e51a7104e4b8be0ce9c51232c8fd6c77 create mode 100644 txscript/data/taproot-ref/1f21715d338b4550c3e7e74321d26de8853626f0 create mode 100644 txscript/data/taproot-ref/1f33b328ec921a865dddc299139161f27b477147 create mode 100644 txscript/data/taproot-ref/1f59389661d72064b929ee2bac0a3f2782c99fb1 create mode 100644 txscript/data/taproot-ref/1f7d7d9cf1ac6252c762a06bdb35e619ce77741d create mode 100644 txscript/data/taproot-ref/1fa141a9352d1d89d10a4d09abf044c9506a4bac create mode 100644 txscript/data/taproot-ref/1fa4445b8704e72f4df267622d688919d1c6a44e create mode 100644 txscript/data/taproot-ref/1fbfc728d51680fcfeadde2a9e6fa7d1ac3996ec create mode 100644 txscript/data/taproot-ref/1fcd778862db2069278171a2ee940bf756a2bdab create mode 100644 txscript/data/taproot-ref/1fcd7eddbae73818ef08042df1c443c53fab0c49 create mode 100644 txscript/data/taproot-ref/1fd0cbef8f091c8edefa214a32625302e2f3a6d8 create mode 100644 txscript/data/taproot-ref/1fe16cf825c0f639b3abd120fa85f9a344d3e514 create mode 100644 txscript/data/taproot-ref/1fe6f643a391a7f73e3577d1f4e57935064e1c84 create mode 100644 txscript/data/taproot-ref/1fe7d8f0f7839c475eb9dbd113d0ac120b1301fa create mode 100644 txscript/data/taproot-ref/1ff8cc1006122254a00dc42299f828366e65b691 create mode 100644 txscript/data/taproot-ref/202c9cc0aac7d6c5172f0818c8d0d3405649d29b create mode 100644 txscript/data/taproot-ref/20372276860410d8622c60d5ec72e5716e313dfc create mode 100644 txscript/data/taproot-ref/203cda36559f2e342d3921d1f1f5ab05e330fe7f create mode 100644 txscript/data/taproot-ref/2068fcad81b42ac14a337456c1c0e850bc5567e8 create mode 100644 txscript/data/taproot-ref/2071f151f52b689e1e3c9f2b0372a3c1ca4c6dc9 create mode 100644 txscript/data/taproot-ref/2089f610f91855cc26e8760f3910284181dc1b86 create mode 100644 txscript/data/taproot-ref/209d75465a4314536f2bbabf6ada3622bec989d5 create mode 100644 txscript/data/taproot-ref/20cd1af7438c223f49d33ed3693631c63f6c3234 create mode 100644 txscript/data/taproot-ref/21227867cfe4806f692be272ca5b865dcecc1894 create mode 100644 txscript/data/taproot-ref/213cd49c2b13fe3ee6d2220f5f96b63c748d1add create mode 100644 txscript/data/taproot-ref/2152488b729a3937e9f4e83bbefbb36d961013ca create mode 100644 txscript/data/taproot-ref/215ddb94c508c11099b9268dbf4ce0d7f7d18977 create mode 100644 txscript/data/taproot-ref/21a38194825eb39a4a0ae99128be4409c90d420d create mode 100644 txscript/data/taproot-ref/21a967d5a754fe4909db382de1d7debbb040d069 create mode 100644 txscript/data/taproot-ref/21b086a0fcb5394bca5e13730e9801a167031fd3 create mode 100644 txscript/data/taproot-ref/21b915be35d2383f8baacd2d513b5cdd06836ebd create mode 100644 txscript/data/taproot-ref/21c64c51dc34976712f8356ed25d28cb2506a3bd create mode 100644 txscript/data/taproot-ref/21cd99bcb03828e0395286a09e866684d6c569f0 create mode 100644 txscript/data/taproot-ref/21f06e9520e734ab7974353357c55b81e5ee87a9 create mode 100644 txscript/data/taproot-ref/22089449f264bdccac5901669554a20c01c7632d create mode 100644 txscript/data/taproot-ref/223d492bc034d65fae5c76008697dc6455711a0b create mode 100644 txscript/data/taproot-ref/227dc7dc4b5fedba0f90b82d69d0f8f6785c49f3 create mode 100644 txscript/data/taproot-ref/228fadb4fab77130e6a42578be8c100758962a74 create mode 100644 txscript/data/taproot-ref/229254c58edf03c88b0434f339de04542e82f168 create mode 100644 txscript/data/taproot-ref/229a032ed00e20e08e27892cc81b53b28e1d245d create mode 100644 txscript/data/taproot-ref/22a01d7a209edd8694bd9edb1c95de74dbed6fc4 create mode 100644 txscript/data/taproot-ref/22b9de25667093d760c9e17c5477dead3043b33e create mode 100644 txscript/data/taproot-ref/23157f2fc305799762478817c79fe62d896edd22 create mode 100644 txscript/data/taproot-ref/2334138f3c633d853dbab847307d9950c227ac09 create mode 100644 txscript/data/taproot-ref/2341c37b333e27f887345a539b3a46aa15fe6738 create mode 100644 txscript/data/taproot-ref/234eb0340c07ea7d86dcfac62e971eae6dbc359d create mode 100644 txscript/data/taproot-ref/2363727c5d55ff4d6eaaf41f33d420d94aa0259e create mode 100644 txscript/data/taproot-ref/2364ebc1025f0c764130435a3da1d5febf1ac0a5 create mode 100644 txscript/data/taproot-ref/23873275d271cfb7c8271e4058054ab8102b18bd create mode 100644 txscript/data/taproot-ref/23ce0a835c3fef13acabbe51379451af1bad4377 create mode 100644 txscript/data/taproot-ref/23ee2abacaf9004b59fb4b0c0bf4fb0518c0b719 create mode 100644 txscript/data/taproot-ref/24189b1ed398f5834d414ec0517d0e4ec49e5123 create mode 100644 txscript/data/taproot-ref/2447d402d9160d103faa8fce8f16b8201a516a4c create mode 100644 txscript/data/taproot-ref/244d1fe0151e8979539727b36d9efd4236889b85 create mode 100644 txscript/data/taproot-ref/24b9d083b99a1fda505df14b9b98cadbf34618a3 create mode 100644 txscript/data/taproot-ref/24bbb3bb32575090a29c31c6d367e46898dc602a create mode 100644 txscript/data/taproot-ref/24d0fbfa8bd2c68fd6ee1e4839bb0d5bb73ef21a create mode 100644 txscript/data/taproot-ref/24e2153d05b71ded99689e64661aa90af06300e2 create mode 100644 txscript/data/taproot-ref/24f5f696fe56cb9b25c9d12a9606b6d6f531d6db create mode 100644 txscript/data/taproot-ref/24f8bbbbf4e945080301e930844b08d263783100 create mode 100644 txscript/data/taproot-ref/250db3e160a3b1e5fb27d5880463b82d2da450a9 create mode 100644 txscript/data/taproot-ref/253542d32b85965ac57232e3741542be2aa8d091 create mode 100644 txscript/data/taproot-ref/25452194c45988fdb9442f977481e8fb95b4ad75 create mode 100644 txscript/data/taproot-ref/2546c1139a14d6b2b3d6b9918c96de6e589fbf07 create mode 100644 txscript/data/taproot-ref/255e0819d8c9639459a4e49579fbd923cdf9240e create mode 100644 txscript/data/taproot-ref/25608654bdece6361519480d9115afff3312cb31 create mode 100644 txscript/data/taproot-ref/25bdf9d085288589dbb23f1fc7d98f7783cb09fe create mode 100644 txscript/data/taproot-ref/25e7910e53d821321fab3c8bb9db847f37fff616 create mode 100644 txscript/data/taproot-ref/25f13dc685e40d3fb22819356cbba4a5a6789e15 create mode 100644 txscript/data/taproot-ref/25fd25289846f102771af05c1445e63acb583b93 create mode 100644 txscript/data/taproot-ref/2619632226257817c56eb288a9d2075e56dd0e34 create mode 100644 txscript/data/taproot-ref/26300a1704f502625832730a36d0088f21a46e2f create mode 100644 txscript/data/taproot-ref/265d0640e2752abb03fbe0a1b150f575f8469aa5 create mode 100644 txscript/data/taproot-ref/2669c9c65bf3af74d4482204c70ea69545d8babf create mode 100644 txscript/data/taproot-ref/266c1691a90b2a342849d25e3704659308c45951 create mode 100644 txscript/data/taproot-ref/2670c894e879a8499f50e08ae018e501b6693152 create mode 100644 txscript/data/taproot-ref/2692015cba943bdfa1b324204d53284234754d15 create mode 100644 txscript/data/taproot-ref/26fbe1c5bd294a3fc35af2e36f46c951b25e5cc3 create mode 100644 txscript/data/taproot-ref/2721ca2fc08ca7ae38cc809a3799bf618ce5a75d create mode 100644 txscript/data/taproot-ref/2756fd453011fa7471613114061631b066029dc5 create mode 100644 txscript/data/taproot-ref/278eb959a30cf3ec8163a007eb3f89ef107765ea create mode 100644 txscript/data/taproot-ref/27ab4c447f840d27a13d145eb27c80db511a400a create mode 100644 txscript/data/taproot-ref/27aff0ad61d128505e22df766c0492e316fbd9a9 create mode 100644 txscript/data/taproot-ref/27b9b3e3bde2958e048cee68f2493d41648987d3 create mode 100644 txscript/data/taproot-ref/27be24f0f9eb749b51dc6e83c6ab5c8637349a25 create mode 100644 txscript/data/taproot-ref/27d37797fa4bb9c3bba68f9967eab892fec70642 create mode 100644 txscript/data/taproot-ref/27f1dbe3a65014c59ae266af3346177a5a57d4e5 create mode 100644 txscript/data/taproot-ref/2807a46ba9b453c2f9e4af2406b26ed38137b216 create mode 100644 txscript/data/taproot-ref/280d6a9607ad78d3eb40f04e5b5a76c6f8eb4c02 create mode 100644 txscript/data/taproot-ref/28259bbbf78c881c7400ac4602722df51776ffe0 create mode 100644 txscript/data/taproot-ref/284cac89d0553dfdc596ce4bfc4251fd2115cb15 create mode 100644 txscript/data/taproot-ref/2872201824aca727042b22cae049102582283dd9 create mode 100644 txscript/data/taproot-ref/288e61a59fe0099d03730d5c9d59712f743123a2 create mode 100644 txscript/data/taproot-ref/28a21b4f4afeb9c978b1290c620548f1f33e127e create mode 100644 txscript/data/taproot-ref/28b1a2ce5cf374a3ce64a6c7853fdbb6a15d1e25 create mode 100644 txscript/data/taproot-ref/28f223ee6f9c2562b1e382ea899bc7f88e63490e create mode 100644 txscript/data/taproot-ref/28f4e044d59009036250527f061daea52c6b5917 create mode 100644 txscript/data/taproot-ref/290325a794a4307e35ab570d847c9854f6d63001 create mode 100644 txscript/data/taproot-ref/290a1cf15d24d80b8dba0ba4397f5a7eb13382d0 create mode 100644 txscript/data/taproot-ref/29186f53cff8c33b62ccd1cec92b4c6b02c8c2c8 create mode 100644 txscript/data/taproot-ref/29306f00a438f213a01ebd7a7b0d04ae25d239ad create mode 100644 txscript/data/taproot-ref/297a3281b6d5be24c14d7ff51f2fbfe46ed86f1a create mode 100644 txscript/data/taproot-ref/297a666c7fc982a83775114d7c6821fb42031e06 create mode 100644 txscript/data/taproot-ref/299581f978295f5b97afd9102abe9746f3633e76 create mode 100644 txscript/data/taproot-ref/29cceb8deed87738d060e1bd5338ab0536f8d2a6 create mode 100644 txscript/data/taproot-ref/29ce41699e783cf1ab6b5b84bcc1f8da679ce8cd create mode 100644 txscript/data/taproot-ref/29d289d23bf6e34dbfac501041222a1978cc95d2 create mode 100644 txscript/data/taproot-ref/29dc54df002663eb3874c3fb7d3952e70b1d1779 create mode 100644 txscript/data/taproot-ref/29dd1cab8fbe87bf2eba3c671a6054c32e47ee9f create mode 100644 txscript/data/taproot-ref/29ec9ea0cab2025b952a31c864a85546c8a8f032 create mode 100644 txscript/data/taproot-ref/29ef22549cd23bb217da411a3ca72d83c71150d6 create mode 100644 txscript/data/taproot-ref/29f6acfc391f9db2fecb96ea0a708da396ed202e create mode 100644 txscript/data/taproot-ref/2a46178ff8d5794433a794e9fe86b9b5fc268cc7 create mode 100644 txscript/data/taproot-ref/2a479685fd7da722bb6722ebc37d68cccb881ee6 create mode 100644 txscript/data/taproot-ref/2a4e458a761d418129aa4d22bbbd076927fcef77 create mode 100644 txscript/data/taproot-ref/2a4e61567a20b2e90af1a0fb476b1ba0154b0a8c create mode 100644 txscript/data/taproot-ref/2a7da9157e1527a2190bce26d0a1303d7f239f9f create mode 100644 txscript/data/taproot-ref/2aa0596f17f2698bdfd51894a7dc1e1241cd3ae9 create mode 100644 txscript/data/taproot-ref/2aa48f72c81f73267919baef97d2c186ffc36882 create mode 100644 txscript/data/taproot-ref/2aa72eaeb2dee91742e3412f9e1ec464ecc22161 create mode 100644 txscript/data/taproot-ref/2ab67ca0e8401c63810a011ea1b9b40ef8573922 create mode 100644 txscript/data/taproot-ref/2ae84cabbb3a18b00167af69886696809a07a86a create mode 100644 txscript/data/taproot-ref/2aef8c06dd7c0aa09e6494194a3b812e4b7b2221 create mode 100644 txscript/data/taproot-ref/2b1075a4c09b4d3aa3be48cb1ce2571ab06a86a7 create mode 100644 txscript/data/taproot-ref/2b168b93f7f916976567d85cf8e7ca0d6dbbf32e create mode 100644 txscript/data/taproot-ref/2b229e9febea1749971fa08007b52b574b3046fb create mode 100644 txscript/data/taproot-ref/2b4be33fed42ff17f8c6910629b0e2183d109eb9 create mode 100644 txscript/data/taproot-ref/2b609a197a87b5e2d1507c9acbaf2e2ab79ce53a create mode 100644 txscript/data/taproot-ref/2b9f2b2856d6b4e70d3b3d8e2d4ffcc6048847d9 create mode 100644 txscript/data/taproot-ref/2ba9b396adf10109648ab2f9856ca66b6fc5b688 create mode 100644 txscript/data/taproot-ref/2baded8ac492d5bbd1dcece9f3d4a2f0458c778d create mode 100644 txscript/data/taproot-ref/2bde7ad09804a986048db6aa7983bf552f327e9d create mode 100644 txscript/data/taproot-ref/2be1d596003c42e91c2a03626c93ce8259dc64ad create mode 100644 txscript/data/taproot-ref/2bed09f85647ccc7b26bbdedb9cbf18167240799 create mode 100644 txscript/data/taproot-ref/2c2132ba18413a6ac05a486fd72669aa4293e784 create mode 100644 txscript/data/taproot-ref/2c24b83fa75f9fc91269d9be43a5c14f9a0c8adb create mode 100644 txscript/data/taproot-ref/2c2615f5ff25527bb1609bacc940eda0c32b8d28 create mode 100644 txscript/data/taproot-ref/2c2686017a35729961e5b4064e6ea9b58c073505 create mode 100644 txscript/data/taproot-ref/2c28303252e327e51e1e99036e9c4fcc97b10d8e create mode 100644 txscript/data/taproot-ref/2c3a119d1d9da7d4fe68883d95e8f11060a9def5 create mode 100644 txscript/data/taproot-ref/2c3a775a5deae4555f3af3537c8a4195c6e5354f create mode 100644 txscript/data/taproot-ref/2c62f7a3d90b30d6f1b1804f6bf0a916d3305efc create mode 100644 txscript/data/taproot-ref/2c67e0be52a7389f103f44944fe8d8913c973b48 create mode 100644 txscript/data/taproot-ref/2c7c5497a7e7f81979773204f099b9f23323698e create mode 100644 txscript/data/taproot-ref/2cc2506d179d284634729bf9fbd8c05239f90ca9 create mode 100644 txscript/data/taproot-ref/2ccd61243d6bba96a68b774617b9d76c97662ff0 create mode 100644 txscript/data/taproot-ref/2cd0311c121154bc8385767e5893c92ee5aa2c05 create mode 100644 txscript/data/taproot-ref/2d240420d7f8e429cb31120c7bf532805423084e create mode 100644 txscript/data/taproot-ref/2d2a878308fd10775f477107b478ca6993799763 create mode 100644 txscript/data/taproot-ref/2d50c7d765d0137b5bc9bd78ac8e39437d22fc0f create mode 100644 txscript/data/taproot-ref/2d562228e60c1a1e62b21379cc97a7cf96852b48 create mode 100644 txscript/data/taproot-ref/2dafca8d1802bbb6ce3ae1196aa647ee3c9e418e create mode 100644 txscript/data/taproot-ref/2db945824c150b91aa78265f9e3701bd991fcf10 create mode 100644 txscript/data/taproot-ref/2dc10a9c76952430b8601993c330b88bd0e19cb0 create mode 100644 txscript/data/taproot-ref/2dc5b1536be7b443c27e763739595c42dc34998e create mode 100644 txscript/data/taproot-ref/2dc9f8f8cf217ccac41228917cb739aee23f3b55 create mode 100644 txscript/data/taproot-ref/2dcae1af8317442bc492bd0899984f32bf30396d create mode 100644 txscript/data/taproot-ref/2dd9b9584d97aeda14030c0cb94034e5a64e1e33 create mode 100644 txscript/data/taproot-ref/2de7782cb97bcd10b69053268684420a0022efd6 create mode 100644 txscript/data/taproot-ref/2df7793cf7520895ea4121850c34c16bd1874c22 create mode 100644 txscript/data/taproot-ref/2e15993224f1d73378824cbd1780f6d25e85740a create mode 100644 txscript/data/taproot-ref/2e2b8acfc93c65c04508d0730229d6beb1760346 create mode 100644 txscript/data/taproot-ref/2e4630df1ac360494322a4300b3a916bf4a7aa42 create mode 100644 txscript/data/taproot-ref/2e9a37abf29713e5bf564831df0206b134ed9e23 create mode 100644 txscript/data/taproot-ref/2ecab25cfb72ae137a881589719a53343a030263 create mode 100644 txscript/data/taproot-ref/2eccff6ea763376046948b3876b0d9b3e8b28c87 create mode 100644 txscript/data/taproot-ref/2ef7e082ae22ffb03fec01772b442b4b8d19cf06 create mode 100644 txscript/data/taproot-ref/2f1b30aed18276568d11bfeb997aac3246d57017 create mode 100644 txscript/data/taproot-ref/2f63727a65eb7f7437ab5c39d3f16671518719e6 create mode 100644 txscript/data/taproot-ref/2f6a3e29b8be29ea5949fb1b5a71679b5cadc8d8 create mode 100644 txscript/data/taproot-ref/2f718ebe5d9460ba98f7815e59bfffe1cd1f3bc6 create mode 100644 txscript/data/taproot-ref/2f92c5daf5b1fc8c65563916bd77ad58dc8ffdab create mode 100644 txscript/data/taproot-ref/2fc6756b64916b520df4a5d7eed9bc7c1ee85753 create mode 100644 txscript/data/taproot-ref/2fe9ee314e024619b228c81cae27f4bd50141a36 create mode 100644 txscript/data/taproot-ref/30060e7ffc388552b8bae73eb28705b637f7685a create mode 100644 txscript/data/taproot-ref/3012845a3aa7dc757cc4778e5334769c9239ab60 create mode 100644 txscript/data/taproot-ref/3015e994a3e16567397bea00a92ff97eb53971e6 create mode 100644 txscript/data/taproot-ref/3031aef9ccb0cb566246e72e7f976a7cf00b9898 create mode 100644 txscript/data/taproot-ref/305b7d52e8b2e5b62f366d1fe9aca1b4c31a2e51 create mode 100644 txscript/data/taproot-ref/30733f314d77a04fcfb55b009f72a5a1a94cc1e5 create mode 100644 txscript/data/taproot-ref/312a2eaf5a3bbccf69b97e292f665b53846038f5 create mode 100644 txscript/data/taproot-ref/3177278ccbc91f49567f80c0b575882edaf4556b create mode 100644 txscript/data/taproot-ref/31a7241822ef819833b51d86a78d83bbb4d58136 create mode 100644 txscript/data/taproot-ref/31b4933ee39bc4133c6a36b1e309775c87a96c23 create mode 100644 txscript/data/taproot-ref/31bf684d25c7125e85ce524a607eb2a52cb7bdca create mode 100644 txscript/data/taproot-ref/31c15818563bf9247178dcf6aa28b033af2bb447 create mode 100644 txscript/data/taproot-ref/31c6f3973f706c7761a06718934fbee33a007e9d create mode 100644 txscript/data/taproot-ref/31c88595514658ef1b8ff73277244b8f007c505d create mode 100644 txscript/data/taproot-ref/31d4c861644fc9edae1f7e2e4f31aa06c7517889 create mode 100644 txscript/data/taproot-ref/31f076334b0a05c6d42d3ee64880af4288a1a071 create mode 100644 txscript/data/taproot-ref/31f2c4c02978ae42e16425ad8313162bbbba6fc1 create mode 100644 txscript/data/taproot-ref/322e55f03866ad2580881660af953e8169abf66a create mode 100644 txscript/data/taproot-ref/32465695f8a85d30402f9b194bdf25dd6e21729d create mode 100644 txscript/data/taproot-ref/3296dbebd697c68468c1215ff252b1da046d3d4c create mode 100644 txscript/data/taproot-ref/32aba46093e0c1405d3a8229f68cefd6de6d9767 create mode 100644 txscript/data/taproot-ref/32abfd2efb454436ddc75cd07a406d88aabceb2a create mode 100644 txscript/data/taproot-ref/32ba176293211377a9ca30f7b1742a3102758b7a create mode 100644 txscript/data/taproot-ref/32bcf37b6b3d15680600c81db467e1dfff6ce375 create mode 100644 txscript/data/taproot-ref/333dafc1d96971e2ccab51c8ee0d9e479decf78b create mode 100644 txscript/data/taproot-ref/334e3a237339fce576119749a9aa81f3d65211cd create mode 100644 txscript/data/taproot-ref/3352986afb9bc33fc67eaf72f47be64e3c6ccba3 create mode 100644 txscript/data/taproot-ref/335b7a860725ca4f2c467a8b034060d0ce6b3bb4 create mode 100644 txscript/data/taproot-ref/33848da9a02cc62be9f5a84c5ce6e33bb6aa8a29 create mode 100644 txscript/data/taproot-ref/33aa1588445e9cbbedd1d4a629780bcc8b4a8e9d create mode 100644 txscript/data/taproot-ref/33aa91e75b0cc39daae8eb7a1f0889075a667617 create mode 100644 txscript/data/taproot-ref/33d0d39d6ce6ced2a0a8dc5d8c47e5f5098d7aaf create mode 100644 txscript/data/taproot-ref/33efade4e6970da9cea78a726935e5443e0d1ba3 create mode 100644 txscript/data/taproot-ref/33fe1028443f16cce6d9858c8501dfb0a7ae5816 create mode 100644 txscript/data/taproot-ref/33ff2ff9d9aabf2865009fc3701058f954184c4a create mode 100644 txscript/data/taproot-ref/3400d35bd94547fb613f1aa5cd2073fdca146533 create mode 100644 txscript/data/taproot-ref/34038f296d87d228ac46a39bb072cc03e4e585bb create mode 100644 txscript/data/taproot-ref/34264b99b16c56793e013d7d2ac3dc83c0c07da6 create mode 100644 txscript/data/taproot-ref/342a92cea02c320154d0894d36811870581b660e create mode 100644 txscript/data/taproot-ref/346b40c03454e4740323b5b0422908722f9a4ed8 create mode 100644 txscript/data/taproot-ref/348d5c1f7c9f5084425a506f649c65b2f31946a0 create mode 100644 txscript/data/taproot-ref/349341420dbe9b22120760aa5b91a9099c7cdcea create mode 100644 txscript/data/taproot-ref/349bf68e15d8f14b4a471b7ab402784c1077db21 create mode 100644 txscript/data/taproot-ref/349dc9e7f879b45a530ea9ac4a5ee92a83b80b64 create mode 100644 txscript/data/taproot-ref/34dee51305402e7e6b502025f00f29abbde3cb18 create mode 100644 txscript/data/taproot-ref/34e0f433a921b809a71c9924e9c0956dc34bc220 create mode 100644 txscript/data/taproot-ref/34ebf584d708a418710a1466a3dbc67b82146196 create mode 100644 txscript/data/taproot-ref/34ed3c4ed5af89953d2e81d21f7c1e45d2c7dc87 create mode 100644 txscript/data/taproot-ref/34fe51570c93ab7b56e8955a00795a7af3eb88c3 create mode 100644 txscript/data/taproot-ref/350219ab2d9d1993c2e0ad903f92eaaf6318f133 create mode 100644 txscript/data/taproot-ref/351979da8be9a1fded3861db5068a083d50516e7 create mode 100644 txscript/data/taproot-ref/35210e4f9eb6f063e680746037b199244fe0997c create mode 100644 txscript/data/taproot-ref/3569acb6b68f7aed0054e44b1fa854e2ef33b96d create mode 100644 txscript/data/taproot-ref/3572c1cebe263656185dea9403422e9884954499 create mode 100644 txscript/data/taproot-ref/3574aa7865915325c364ab1364ae532d35ec2952 create mode 100644 txscript/data/taproot-ref/357c3aca3897a104f6b209ff00a90eb8f93c11e9 create mode 100644 txscript/data/taproot-ref/357f1e298d27372ed2fdb360e6ecf4b4f93bf38f create mode 100644 txscript/data/taproot-ref/3585f3da19dc73f07d513f4d5e06b3af35381aab create mode 100644 txscript/data/taproot-ref/35995d78575bb81724c123126ae84f04c1ef1324 create mode 100644 txscript/data/taproot-ref/36107f7e7692414cd4ae5e7ee06a1e46821b107a create mode 100644 txscript/data/taproot-ref/361314e0baab060ff8fb2888efad4f841ee2e65d create mode 100644 txscript/data/taproot-ref/361c2bf607441dd9ae1d9e592d08aff1c4423aec create mode 100644 txscript/data/taproot-ref/361e67ace54dd8058e82517e87d5a294ff0e2430 create mode 100644 txscript/data/taproot-ref/36225523764ce0fcf4a54ecc157c7a9ee0ca5e1c create mode 100644 txscript/data/taproot-ref/363516e81c7327e6e8535e74da1cf78a4a939bf2 create mode 100644 txscript/data/taproot-ref/363d3439b183bb0f2c6a0d1238057e9beb398f18 create mode 100644 txscript/data/taproot-ref/36415fab25c89139e82b030657b2f8d9f5d9bfc4 create mode 100644 txscript/data/taproot-ref/36608fb81d55d07d46c2f7849cd926ee3b2544c0 create mode 100644 txscript/data/taproot-ref/367c9b1f3074839cbe7794421f5a5a30b5392887 create mode 100644 txscript/data/taproot-ref/368c81b84650d4644c983e3209d93ebe140d375a create mode 100644 txscript/data/taproot-ref/36918d3941b615417b367e0dda84482198335469 create mode 100644 txscript/data/taproot-ref/36a94d7bc5dc9af664df029d9cacb70d1662178f create mode 100644 txscript/data/taproot-ref/36bc60267ff97612610797a43fa5e7b371687229 create mode 100644 txscript/data/taproot-ref/36bd6cf68074e03b5642284ce7d493af28e048a2 create mode 100644 txscript/data/taproot-ref/36c7fd31d411d45f3d03143f9a36158791a29660 create mode 100644 txscript/data/taproot-ref/36cefffcad6493e933315f78db381ff7ecc43bfd create mode 100644 txscript/data/taproot-ref/36db1eaf5e186f36042dd8afeeebfabe675c620a create mode 100644 txscript/data/taproot-ref/36e7b1c9920f0e9a7c1c52c380c61f6b44246ce8 create mode 100644 txscript/data/taproot-ref/370f93aec0042473af8eda625b8e55afa266cf0a create mode 100644 txscript/data/taproot-ref/3711e5aa1c94f1b0f835504e4dc9cfac933f247d create mode 100644 txscript/data/taproot-ref/37178f03fde09a06a32ec4e778874ec6ff11c8c3 create mode 100644 txscript/data/taproot-ref/3722cdc62a8920daf88999d381d42a7424417843 create mode 100644 txscript/data/taproot-ref/3745a800a4b496404473a26dd593f84588194471 create mode 100644 txscript/data/taproot-ref/374e3814357798251b0430dc4cfb9f212c1dddd3 create mode 100644 txscript/data/taproot-ref/375599a0689231a316462d64f42ec6b33ccca33e create mode 100644 txscript/data/taproot-ref/3771c3d9e542f846b3c206c6719246bde5cb472d create mode 100644 txscript/data/taproot-ref/3774905200290499adbbac9b674c43b82c3af04d create mode 100644 txscript/data/taproot-ref/379b89135a99972794096065de8e1072473b7cdf create mode 100644 txscript/data/taproot-ref/37a26cf98e0cb201f2e241d6a41e267821078fc2 create mode 100644 txscript/data/taproot-ref/37cfd491e753f20291c4606a4bb007cf1aa69eaa create mode 100644 txscript/data/taproot-ref/37fdd34d221df947a4dc6a40f91fe044f88c8ca2 create mode 100644 txscript/data/taproot-ref/381cf7c5a9c44f989bb97ebca54137b24a0c5102 create mode 100644 txscript/data/taproot-ref/381d7b2c554124f48f833d5bb44cb65d6a4e69ae create mode 100644 txscript/data/taproot-ref/3849d609dcd2299e85caef8d7aaf0dc4cbda60ea create mode 100644 txscript/data/taproot-ref/385fb0d2eeda5f4790eeab09a29ec612150cd115 create mode 100644 txscript/data/taproot-ref/3862864a68546884d4ae2ef7644d75b814fd279e create mode 100644 txscript/data/taproot-ref/38633120561625bae7ecb1c951acd585717ee56e create mode 100644 txscript/data/taproot-ref/387db60867784e48a23882557f34fd3e8df5fe60 create mode 100644 txscript/data/taproot-ref/38a77bbe28f3ce750b32c16df488eb5970d28d51 create mode 100644 txscript/data/taproot-ref/38b2b86e0814487d32eb0a49aaa091c527c67a39 create mode 100644 txscript/data/taproot-ref/38b7d993272a54c03a7adb7a046e8485546ebd0a create mode 100644 txscript/data/taproot-ref/38bce0395152e8d2a60a95b4642bf3700934e4e9 create mode 100644 txscript/data/taproot-ref/38cd5b3045252d1ad4ff3cad40d838874891506c create mode 100644 txscript/data/taproot-ref/38cf290b09eac905ac4bdc5ffd7fbeb55b28d0b1 create mode 100644 txscript/data/taproot-ref/38fa5cb2147069b9e33e21d621935d45486c5345 create mode 100644 txscript/data/taproot-ref/39016f47ee6449811c8a18548ba14d36d60f1a15 create mode 100644 txscript/data/taproot-ref/39095ad3e086951d38e9de71ed6390bf4a910ada create mode 100644 txscript/data/taproot-ref/391ae71a3b29dc703963bfe3a4d96555cac94848 create mode 100644 txscript/data/taproot-ref/391b89f7a6069cedebf4da40cbd2e894c4e4e161 create mode 100644 txscript/data/taproot-ref/39261d0b29bcefd21020cd2c24c872c070c66ae7 create mode 100644 txscript/data/taproot-ref/39427d9b3326e6d242f88c30c5337e28e60ba2cc create mode 100644 txscript/data/taproot-ref/395284f8211e771929c6abd17a1e39b471bad2ac create mode 100644 txscript/data/taproot-ref/39702f9a29cc5985ccdbae18da3583e3a98271be create mode 100644 txscript/data/taproot-ref/39a530e81b2ae6640a22eade59df3f302ebb0806 create mode 100644 txscript/data/taproot-ref/39c2d78974b78a945ee5325ec03d2a9842678371 create mode 100644 txscript/data/taproot-ref/39c6fd26ec7474a9addfe549df2cb8ee610ecb51 create mode 100644 txscript/data/taproot-ref/3a48de373b5922e0287dcbaa10361aa1464b3eff create mode 100644 txscript/data/taproot-ref/3a4b7a4a72ab611ede23f7e04e2c7e0300d1c7b6 create mode 100644 txscript/data/taproot-ref/3a5d1711382ce031d27b85c9d0db96a8d322c0a5 create mode 100644 txscript/data/taproot-ref/3a8258d488d60df9cd2d2e0f3fbfda5aa2916b1a create mode 100644 txscript/data/taproot-ref/3ad5eb51c8c2ea66907d5c7b40ef6cccaee711ce create mode 100644 txscript/data/taproot-ref/3b055324162a840bb031e742e417383a3c2b9fff create mode 100644 txscript/data/taproot-ref/3b6174c02c9421bd7512cb0b507ee81cbe621e8f create mode 100644 txscript/data/taproot-ref/3b756b29419004b37c85b3e93c13d3f231e1eb67 create mode 100644 txscript/data/taproot-ref/3b7aa5f0f9d0fc31f7be3558e9eae22f13652d33 create mode 100644 txscript/data/taproot-ref/3b964cb9d3464c3949a2e8a0f9edb54a4a9ce6c7 create mode 100644 txscript/data/taproot-ref/3ba14a20059a5c8f8e184fb6d08736296adf21fd create mode 100644 txscript/data/taproot-ref/3ba4a606e430170b23a098c2ac6ee7213be618ca create mode 100644 txscript/data/taproot-ref/3baa61730ba406d7fad296d7df24a9629ae0240c create mode 100644 txscript/data/taproot-ref/3bacefe15c3e633f44d830137c6fe22c074b155d create mode 100644 txscript/data/taproot-ref/3bc46b0f49e132b39a7468c0eeae4f18c15a9e46 create mode 100644 txscript/data/taproot-ref/3bd1e196feb0c029ad908a2c989b46a4c75e87e4 create mode 100644 txscript/data/taproot-ref/3c0a722d83c61bffb4712e8bdb67f68d6757d30e create mode 100644 txscript/data/taproot-ref/3c11357c518486213b14a41e23ce85acfc7225b9 create mode 100644 txscript/data/taproot-ref/3c20247465b4757bf0758627c8b5e4839dd819cc create mode 100644 txscript/data/taproot-ref/3c4f81b3cab5b54ca2ec122fa809fca650b47db6 create mode 100644 txscript/data/taproot-ref/3c695558731a219357e99fced06f0c24b38b6c11 create mode 100644 txscript/data/taproot-ref/3c6b79f35456c42d2578553948e940b494865ac5 create mode 100644 txscript/data/taproot-ref/3c78b5bf3e8a594974afba095afac84660219f6c create mode 100644 txscript/data/taproot-ref/3c986463576a17cc12996a738a2cc479d1198df8 create mode 100644 txscript/data/taproot-ref/3cb4479d7f4d2911b165d8e388cda3c7da36bd62 create mode 100644 txscript/data/taproot-ref/3cb7605604a629153b71183c4083311f53f6fee1 create mode 100644 txscript/data/taproot-ref/3cd91b4c3a1d21d1c90b1e6542ae78fd35091778 create mode 100644 txscript/data/taproot-ref/3d4082e12a369fee00a97f5ee6a3b72ea6f15238 create mode 100644 txscript/data/taproot-ref/3d4137ffad2b1c85003d032d19a2150f4b6517c9 create mode 100644 txscript/data/taproot-ref/3d65682b1f434030f11d6815360c3d269d231474 create mode 100644 txscript/data/taproot-ref/3d6fb8e46d4f9e03d6de0e295ec2e0e50df1aa5f create mode 100644 txscript/data/taproot-ref/3d75756c8dd79c4efe056dd5435cfb6a2457207c create mode 100644 txscript/data/taproot-ref/3da479f176b53c08e1248502a5bc75aed6c71746 create mode 100644 txscript/data/taproot-ref/3db85c10d9886a1d664d6d3db26ae7961d66a4be create mode 100644 txscript/data/taproot-ref/3dc41a3a65eecfb088cf236466ab9fb737a19b57 create mode 100644 txscript/data/taproot-ref/3dcd87542c1fe27ba922187001739130ac6c6c5c create mode 100644 txscript/data/taproot-ref/3dd2c473cd54ea601b15cc9840f01e6cec72fbd3 create mode 100644 txscript/data/taproot-ref/3e0593c1054f6598bbf8297623874e58ed4f2f9e create mode 100644 txscript/data/taproot-ref/3e1e6aa2f96548cfbcb05311c5d24990bb96a8ef create mode 100644 txscript/data/taproot-ref/3e2370ff2103895a7c13f394468b1d7588a525a0 create mode 100644 txscript/data/taproot-ref/3e30536558f547b9ad4f09f367634b969078f719 create mode 100644 txscript/data/taproot-ref/3ea9b3574203d1cc954fbb5b93f7588b765a4d0f create mode 100644 txscript/data/taproot-ref/3eabc6ab34a7c9a974850c1dd22c428aa05b1b1a create mode 100644 txscript/data/taproot-ref/3eb9a6cfe1aa2c1c02424702999504c5b096248f create mode 100644 txscript/data/taproot-ref/3ebde48f5439e084e28144fd489296408e0dac44 create mode 100644 txscript/data/taproot-ref/3ef5bed9863d50fbfa4dee5c776d36177e888adb create mode 100644 txscript/data/taproot-ref/3efcb90f4a83944731d1cbf69fcde8147549f8ff create mode 100644 txscript/data/taproot-ref/3f08853267dab46c6370068cbb68b228923ff0b3 create mode 100644 txscript/data/taproot-ref/3f1549e9384322e64380cd38621193a46900a116 create mode 100644 txscript/data/taproot-ref/3f1d506b154892f06d439bb90ba5202e723507eb create mode 100644 txscript/data/taproot-ref/3f512330103073dbd4f58e82fee2f316a4b0c171 create mode 100644 txscript/data/taproot-ref/3f513698f389965cd3f800cde5d06d6742166c96 create mode 100644 txscript/data/taproot-ref/3f6985d5b0c8658ee84900aef20ad6b450f6f3e9 create mode 100644 txscript/data/taproot-ref/3f6a1b44037f9a0ecf95cd3d23ce8bde0b02ff8e create mode 100644 txscript/data/taproot-ref/3f6da0ebdeff4ba77b33c2c2d3b962e7dc353570 create mode 100644 txscript/data/taproot-ref/3f7737e152b00480f6b1e13136938142db63c3bb create mode 100644 txscript/data/taproot-ref/3f7dd25efaad7cb28967f110fe74e5e38a763ca8 create mode 100644 txscript/data/taproot-ref/3f827b95772a69cca7924e0a2e6ed2cef8755536 create mode 100644 txscript/data/taproot-ref/3f86932b9bd5a8f673b4dd4243ebb78bef50c888 create mode 100644 txscript/data/taproot-ref/3f8e06a01cdada6071275fb451a2ba624eecf6b8 create mode 100644 txscript/data/taproot-ref/3f9e6c510733a54871b5b12db956530901898fe5 create mode 100644 txscript/data/taproot-ref/3faa53c6eda1becad9cec3442b7069bc2083f057 create mode 100644 txscript/data/taproot-ref/3fed18356adbd733c605b538f4fbe6434ecad6df create mode 100644 txscript/data/taproot-ref/4017ac5f35612181926802d0cfd9e7f6a5aed8a7 create mode 100644 txscript/data/taproot-ref/40198d56b45470dd3064ec201e05ca4e3cdca930 create mode 100644 txscript/data/taproot-ref/405cc03a69b95e49ca66bdd71055159a13f437eb create mode 100644 txscript/data/taproot-ref/405ecda072acc56c38f0eae072ad858ec1097d36 create mode 100644 txscript/data/taproot-ref/40637530cf642a13aaddd88b9e805ab9eed711f1 create mode 100644 txscript/data/taproot-ref/40815dacf70ec14f7b8a062c9faaf258058731fe create mode 100644 txscript/data/taproot-ref/4088fa75fe995a05522f18f9b0e6945552611611 create mode 100644 txscript/data/taproot-ref/40c7820188392556b1df313d7fe8ad00eac4965f create mode 100644 txscript/data/taproot-ref/40cdd6d34a71ec60c962c3ce8c6408731acebed3 create mode 100644 txscript/data/taproot-ref/410f4c522606d7e3dd362eafa5a5ab9d9811a338 create mode 100644 txscript/data/taproot-ref/41114b51cf4fbb2b1beee4e0cc3047fcddd88c2e create mode 100644 txscript/data/taproot-ref/416cc4828a6c9b5f1667ac7ad0d2684eb23cac38 create mode 100644 txscript/data/taproot-ref/4184d22015b6c9b7656f411782a4484efd87060b create mode 100644 txscript/data/taproot-ref/4186f82b0ef77212271ae59a07d75a5f370f8add create mode 100644 txscript/data/taproot-ref/4194caf8692db4d7109076c5dece284d07e06cbf create mode 100644 txscript/data/taproot-ref/41a24f98a0882fe70484f5006c4b6b9a37bc85f0 create mode 100644 txscript/data/taproot-ref/41bb837acd47aa639c62f7986ff46af86a6c36d1 create mode 100644 txscript/data/taproot-ref/420a24fcbd56a2a2791e7238666b8aa34e2ccf16 create mode 100644 txscript/data/taproot-ref/42c6d3a78f584cc355a0bac6f309e105089332b8 create mode 100644 txscript/data/taproot-ref/42da32b7dda49d356987402249a3bb67a0b53529 create mode 100644 txscript/data/taproot-ref/42e412a1e895536ef1264d7ee08902b8e37a53a0 create mode 100644 txscript/data/taproot-ref/42eddccf89cbef79a5adffb7eb5ea1523de5b3b7 create mode 100644 txscript/data/taproot-ref/42f1cfaa89e0e558cc339a4adfc253b4108d5843 create mode 100644 txscript/data/taproot-ref/43532b914ad45faf56c91ef34b9b696012326b2d create mode 100644 txscript/data/taproot-ref/43a09bc93d6d45b6cef903b1341a287624b825ca create mode 100644 txscript/data/taproot-ref/43a12820d4dfa937dfdbaa0843372e901ec73944 create mode 100644 txscript/data/taproot-ref/43b19c13ed8e58e70071e063750e8fca7a9f05e0 create mode 100644 txscript/data/taproot-ref/43bfb11c19ea9173f4b0185fbc6a622fd0787c68 create mode 100644 txscript/data/taproot-ref/43d1fadc7620820efcc941a68f7696480649c13d create mode 100644 txscript/data/taproot-ref/43dae97b688afba43b6d88389a78b979f1181c34 create mode 100644 txscript/data/taproot-ref/43eea0f55cf11052527d14c3cf0f96e55882c4d5 create mode 100644 txscript/data/taproot-ref/43f8e70fd6ed448f6cd62609f6e4a9d03a0e083a create mode 100644 txscript/data/taproot-ref/4407ad4a37ac5667b725ef07db2b1b0ebbe6db1e create mode 100644 txscript/data/taproot-ref/4422ccfb3a652df26350f5fd43cab32b4a6db9bc create mode 100644 txscript/data/taproot-ref/443de93ae646f545525c4a8177964caee78a499e create mode 100644 txscript/data/taproot-ref/444bdbc8e2a3f36427b9ee3bb33b639f3d06010d create mode 100644 txscript/data/taproot-ref/44513b5ccd5d2993d98b0f606e24c3363080118d create mode 100644 txscript/data/taproot-ref/447e0a4f2c9391201bd7abdb3935d959277ac93d create mode 100644 txscript/data/taproot-ref/4493e5053e8c93d7133c12033db30ab0fad02eea create mode 100644 txscript/data/taproot-ref/44b2a5681330965efa5dadccd65e4296cb9bb54c create mode 100644 txscript/data/taproot-ref/44bf61ffe86491dc47531baea9f4722fed205885 create mode 100644 txscript/data/taproot-ref/44c41d5a9ee6d3836c4cd959feb9946950a93097 create mode 100644 txscript/data/taproot-ref/44d03ac572cc57f5a15470cd97f15bcb5b9aae1e create mode 100644 txscript/data/taproot-ref/44d081e51884f8d702e4373433bcf56a8a7ad583 create mode 100644 txscript/data/taproot-ref/44d277dff113e85feb1b0da733079ba007e9ce3c create mode 100644 txscript/data/taproot-ref/44f204855343e69fdcf5529e0a6cb7ea5dee9741 create mode 100644 txscript/data/taproot-ref/452689d60be7f0c8bbd02b65a8c9841ac076b913 create mode 100644 txscript/data/taproot-ref/456d04cce86b68e35302afe4c3345e7531aa7304 create mode 100644 txscript/data/taproot-ref/457a9522f60a63cad613ce6f45ab52147b5a1871 create mode 100644 txscript/data/taproot-ref/45afd60d642320c756621d0d193cd27de023f243 create mode 100644 txscript/data/taproot-ref/45b86557bbe4fb210901de818886b7536f396562 create mode 100644 txscript/data/taproot-ref/45babb1803fdc9834a37bce496e989425e2fe9b9 create mode 100644 txscript/data/taproot-ref/45c14cf9149717468bed37e1e419020555c5f927 create mode 100644 txscript/data/taproot-ref/45c97ab53324162e66ed1d4c64371055d966b691 create mode 100644 txscript/data/taproot-ref/461af17d337077781b7e49d203e17cf7cdd7781b create mode 100644 txscript/data/taproot-ref/464a9d31b63ef5f4fe0f193acff3f7a8251adb7f create mode 100644 txscript/data/taproot-ref/4656d9b9e1003224e094622d9723247d8e53ca72 create mode 100644 txscript/data/taproot-ref/467ac05fa481edab9bf207738a0fdf308bb097c5 create mode 100644 txscript/data/taproot-ref/469213f3d0a4e2171977ef67184aa5af2a7d259a create mode 100644 txscript/data/taproot-ref/46a14a2d2ab594d5d1917b16120cf28258bcd02b create mode 100644 txscript/data/taproot-ref/46b30a46669909d38ddfd379180d9b9e4b032d30 create mode 100644 txscript/data/taproot-ref/46bf3a742f868512007f33d6092b25ad9851abc5 create mode 100644 txscript/data/taproot-ref/46faed608cd8553355e705736f5883a865bdd1c0 create mode 100644 txscript/data/taproot-ref/476140a4869c363ff59de15ca0b3dddb33ee16ea create mode 100644 txscript/data/taproot-ref/47678ed5dae9d91220f82b512192c03161458d96 create mode 100644 txscript/data/taproot-ref/476e1eb3a45bcd3c87728f4a5f152341fc41c6d6 create mode 100644 txscript/data/taproot-ref/4775847b1966e3acdf5bf21407d223d54512c0aa create mode 100644 txscript/data/taproot-ref/477812c3aa633968c3f508ea4a64f6240b7c1282 create mode 100644 txscript/data/taproot-ref/4786bab5e3fdd53811fa094d64658a869323943d create mode 100644 txscript/data/taproot-ref/47975b43d53b5ddfe8aebbb719cb70af90f9ca56 create mode 100644 txscript/data/taproot-ref/479ddb4cda1c95a66132ba2891f8deed16e1e31a create mode 100644 txscript/data/taproot-ref/47c96a95d6bd928e3390068b3c94db28d219e9c7 create mode 100644 txscript/data/taproot-ref/47d2125494edd0e8f737339160fc2c2bbff13239 create mode 100644 txscript/data/taproot-ref/47d754aabbae7b0b019240479e872ec641a71606 create mode 100644 txscript/data/taproot-ref/47f82c71674923da07b7c082409faecaa9d932d1 create mode 100644 txscript/data/taproot-ref/4849670c7437aabe38ac365b533b2cae10e1c316 create mode 100644 txscript/data/taproot-ref/4877a47b68dcd97455dcb8cd52e27309ec642b93 create mode 100644 txscript/data/taproot-ref/487deb88a57dc3cabdf497fe30220136e593d23d create mode 100644 txscript/data/taproot-ref/48a74bc4e405cef7fd774039eb79bdfaeafeea6b create mode 100644 txscript/data/taproot-ref/48aba9a0a8d38583f02db4ffbfe46b11affd2459 create mode 100644 txscript/data/taproot-ref/48ba4204d31335006c77c0a0c393c5424c5c89fd create mode 100644 txscript/data/taproot-ref/48bb02ef59af281b015aba26344a918d3e949c98 create mode 100644 txscript/data/taproot-ref/4907d4a7edab4d2d57ded00e95a654d47f9d823b create mode 100644 txscript/data/taproot-ref/491492c2f48c07bca9ef88c9fd36bbd272563b73 create mode 100644 txscript/data/taproot-ref/494a7c765d815e6adc6d4e66a57225322bccde6b create mode 100644 txscript/data/taproot-ref/496ed2b73e932787fe91d418b240c466ab6a4075 create mode 100644 txscript/data/taproot-ref/496f687a93323cea34ef1249059c862f9397c645 create mode 100644 txscript/data/taproot-ref/499184ec78a677697ab3ce5b0a87dfbb5ecce65e create mode 100644 txscript/data/taproot-ref/499f8c99044f5a7eb9940853f276e5ed7a9894f3 create mode 100644 txscript/data/taproot-ref/4a015d179a6415548a65aa75d68b1927fe2b0738 create mode 100644 txscript/data/taproot-ref/4a46cdc5c3a288a4eead1245fd3b0bfea974ea21 create mode 100644 txscript/data/taproot-ref/4a729815cf7a0f3947cdf502e425da1b2392d6b8 create mode 100644 txscript/data/taproot-ref/4a7e2f54a225b7edfc7761d52940b39a3702b9d8 create mode 100644 txscript/data/taproot-ref/4a8d82dfb1750aa99deb48b58f8c91a30cc703b0 create mode 100644 txscript/data/taproot-ref/4ab1d0f5d83d7343f225dc40c2a3a9940dbe3f7c create mode 100644 txscript/data/taproot-ref/4ab5fb6756c937560dc91ad579231800bcb605f0 create mode 100644 txscript/data/taproot-ref/4ab75e6d0cbfec5617026ca0e5622cb4be8d69ea create mode 100644 txscript/data/taproot-ref/4aef881f37b09a5f41876628452dac08c70a5c3e create mode 100644 txscript/data/taproot-ref/4af1e59e48ecbb8bcf5f8c2a739ffe2d47054b4a create mode 100644 txscript/data/taproot-ref/4b22e5ee8f595d1440ed41006d8e611da06d0c13 create mode 100644 txscript/data/taproot-ref/4b537d79f1a6255185126b99325e3917dfdc7885 create mode 100644 txscript/data/taproot-ref/4b57985dbb3b797fd0788cfb9513abc07ddad003 create mode 100644 txscript/data/taproot-ref/4b72ce01f999a32aedc950dd1804a8795ff98723 create mode 100644 txscript/data/taproot-ref/4b7e7a47d519d00fb5bb9332b6fb49586a4134f8 create mode 100644 txscript/data/taproot-ref/4b8ea927af2611b4cf7fbab90c9f8ffb8bea3ab2 create mode 100644 txscript/data/taproot-ref/4ba2921581f7a3560b6ec87297653fb165ccf969 create mode 100644 txscript/data/taproot-ref/4ba8a95b0f39aae1daf6e664542420657da72fa0 create mode 100644 txscript/data/taproot-ref/4be8d76134fd3aa72fd3ecc702e88a4530fcab53 create mode 100644 txscript/data/taproot-ref/4c0186fb62257335535a95ddfc34807b1f836154 create mode 100644 txscript/data/taproot-ref/4c0a1b11b6e6b7691c115aa09cd92e8ee09a5076 create mode 100644 txscript/data/taproot-ref/4c117e356638d628e5b841bc413e67c8bbf10384 create mode 100644 txscript/data/taproot-ref/4c2d2d7bdc708a582093d11d189f7addae41c5b4 create mode 100644 txscript/data/taproot-ref/4c66ad58c30b6404b73490df6a7aabdb4eb995b2 create mode 100644 txscript/data/taproot-ref/4c749139f91d4268578b998b4fc4742cfa968495 create mode 100644 txscript/data/taproot-ref/4c9126df811790be522891686bd1fcd0a7fae560 create mode 100644 txscript/data/taproot-ref/4cafaf85ab316a592878f9e83a2be01cfcdf738f create mode 100644 txscript/data/taproot-ref/4cb7d23ad1e01a5e42d3c8d927936db03801ab95 create mode 100644 txscript/data/taproot-ref/4cff2a8e93a415e0cd8f16313427db2dceea582a create mode 100644 txscript/data/taproot-ref/4d21f89d57587583f18ad029ffd268e08c6deaed create mode 100644 txscript/data/taproot-ref/4d2c30084bbdec620ff06379849a52ea2e10b97f create mode 100644 txscript/data/taproot-ref/4d72ed31959a5c8b48c6c9de682cb5364bf0cafe create mode 100644 txscript/data/taproot-ref/4d9a093d9de04fcd9c74eeb3fb252b4f762f048e create mode 100644 txscript/data/taproot-ref/4db56aa4ef26d2fbb9c74967c01012f86fb5c60e create mode 100644 txscript/data/taproot-ref/4dd64e2309c3e9efee2d5404d847b644329d1f7f create mode 100644 txscript/data/taproot-ref/4df3d74d147d4bb7144799be7f96196f44def06d create mode 100644 txscript/data/taproot-ref/4e1c650230dc5d5f622303dbdb697b39acc5953d create mode 100644 txscript/data/taproot-ref/4e27213b2fb3cbd2c324c9d967eb6837151c512b create mode 100644 txscript/data/taproot-ref/4e442bf704b5166ed40da217a4f0a6103e117487 create mode 100644 txscript/data/taproot-ref/4e6bb871c5b2e524530d3675221cf34b2e598538 create mode 100644 txscript/data/taproot-ref/4e7f6d1d5ff623f2b978feb61b0905320a14cea2 create mode 100644 txscript/data/taproot-ref/4e8673f1a272e7a4846b2b13fd4d6d699de0dd4d create mode 100644 txscript/data/taproot-ref/4e8dce29e5e8dce89954f8535e95a66c4dec52d0 create mode 100644 txscript/data/taproot-ref/4e98f79b12c1bcc786816c990038e187b1881a2b create mode 100644 txscript/data/taproot-ref/4ebc10c30a1a1250dc40fd49051eb8cadd3eb677 create mode 100644 txscript/data/taproot-ref/4ed19b212daaac7d9ddf8fbed04bd645b3540c87 create mode 100644 txscript/data/taproot-ref/4ed948d6df09636962a55dc16fa8141b57caf0a8 create mode 100644 txscript/data/taproot-ref/4f01eb0e5c5b453e93d7259acca78110e06e0cdc create mode 100644 txscript/data/taproot-ref/4f043f492b006187a12d4a27a2fb711e089c21cb create mode 100644 txscript/data/taproot-ref/4f31274445bc35aaf35c1fc3838142b83f4e4dbb create mode 100644 txscript/data/taproot-ref/4f3b0d3de5e5a892c662d05f7df9b836b5083f4e create mode 100644 txscript/data/taproot-ref/4f3eb1205832e452025bc7463ab84f005ccd56a6 create mode 100644 txscript/data/taproot-ref/4f444cefd89a49cf66c69836b968e18c893e6243 create mode 100644 txscript/data/taproot-ref/4f4de778bdec3be4e7cc1f875680330eb9edda65 create mode 100644 txscript/data/taproot-ref/4f54816eeaa1958560b3411df01fd36e2cc3cf78 create mode 100644 txscript/data/taproot-ref/4f5d2d6eb42d852d85a2d40419830ff372017208 create mode 100644 txscript/data/taproot-ref/4f692f08e2284094269303792599c3ca996925a1 create mode 100644 txscript/data/taproot-ref/4f967edf0f22d51ce89c007d5351844488bfc1d4 create mode 100644 txscript/data/taproot-ref/4f9df26c7948631ce06cb7292bcc481337bff811 create mode 100644 txscript/data/taproot-ref/4faee5238fb7a4ab5d716bcfb441ef4b0ab3f888 create mode 100644 txscript/data/taproot-ref/4fc70db2882c50f92cbf554605f20aa8afdc9e7b create mode 100644 txscript/data/taproot-ref/4fd09ff1c3fd39676f5029f8a82082c4a788cbe7 create mode 100644 txscript/data/taproot-ref/4fd67112498e9041d549dca8902b4b18f4151e0a create mode 100644 txscript/data/taproot-ref/4fdbb01ee1c89fea2c908ade5230cbf49b493184 create mode 100644 txscript/data/taproot-ref/4fe78456cf82ee1f4f6bf880baf672a53376c62d create mode 100644 txscript/data/taproot-ref/4fe9d51c1a4a51db63ace4b7593bf4d0179da70e create mode 100644 txscript/data/taproot-ref/5008a5b791ae73ec29ac0e451b2193e921d7d91e create mode 100644 txscript/data/taproot-ref/50197b1f963b6c70cf02494a68b83252169b58f8 create mode 100644 txscript/data/taproot-ref/501c6aa901d9b79489250b1e7c008dad90b998ba create mode 100644 txscript/data/taproot-ref/501cdfc8b8bfd47787c30328084cb44010d48a2a create mode 100644 txscript/data/taproot-ref/5020bfad68bbf3d62a9901f11d582b9367ff01a8 create mode 100644 txscript/data/taproot-ref/5027b63206364f920f33ae41d244998d60e6d000 create mode 100644 txscript/data/taproot-ref/502ba5490df10d7b64842c917be0cc8dce168153 create mode 100644 txscript/data/taproot-ref/5040561743c74062906a64802db725e7cb87b572 create mode 100644 txscript/data/taproot-ref/5047a7a4c5f22dc492d73a6de284a0603fc06171 create mode 100644 txscript/data/taproot-ref/50701ea0af2da8b084ea4a3566db2cedf8dcc2b9 create mode 100644 txscript/data/taproot-ref/50765c36b2c5b67d14ed6d3f1006bcac492b9d7e create mode 100644 txscript/data/taproot-ref/50ade4cb2bfd78d63959c0c196702463020ec1a7 create mode 100644 txscript/data/taproot-ref/50e97f4dc4e78ccd7491b23a05fec77e705d6d17 create mode 100644 txscript/data/taproot-ref/512819dc5f866c4c52a96393d1dc161a298b58cf create mode 100644 txscript/data/taproot-ref/5134a98d252e038c84c184e2a60b3ab15541c32f create mode 100644 txscript/data/taproot-ref/513b5b1cd7ae4a18b0684e98b8bea2445f0f267c create mode 100644 txscript/data/taproot-ref/5145a2f823d50829addf9a923816226e49b73772 create mode 100644 txscript/data/taproot-ref/51585e660838f7655a9d3f8e62673ed896abc1b1 create mode 100644 txscript/data/taproot-ref/5159ef1765261a6a8967fe22b91be23bc4f7c672 create mode 100644 txscript/data/taproot-ref/516e8f247c632cc97a34b088b9b9c5522f6b4b7b create mode 100644 txscript/data/taproot-ref/51902d7c0dc3e60282faf7c3bed70ad3588b79cc create mode 100644 txscript/data/taproot-ref/51cb6bd8e208996ef5816ab2e4a5f0a4392acd9f create mode 100644 txscript/data/taproot-ref/51d22c9e318035b292b06c7e92cff7a7dcd2ef46 create mode 100644 txscript/data/taproot-ref/51df77e1f5047cc73d62f6a82b06c76b2f2dfcf2 create mode 100644 txscript/data/taproot-ref/51f4a12afbc5c09d84488a09c1ec4fad2f8ad55b create mode 100644 txscript/data/taproot-ref/5201220ebf5a752ed230ba1c4660d6768ea0ab37 create mode 100644 txscript/data/taproot-ref/52406f743dd8cf468c8739e0e49a5e8c2abe890d create mode 100644 txscript/data/taproot-ref/524a8fbae511284a4b3feffd7e69391eebfe5fe3 create mode 100644 txscript/data/taproot-ref/525afb4266fbfcb9a9457044ffa429e6345aca74 create mode 100644 txscript/data/taproot-ref/526b41de4d7b2b6cca5b8cca2aff4e05e1edd180 create mode 100644 txscript/data/taproot-ref/528808e08755d1c4badf200ea1e46b471e697367 create mode 100644 txscript/data/taproot-ref/5292dd4bbfc4ed134ecca359a50042487bdab8de create mode 100644 txscript/data/taproot-ref/529e15d7495022b3928ad252f217ff7066f4a8c4 create mode 100644 txscript/data/taproot-ref/529e417f9521111e7e2b214bbe3a009fb241e0e3 create mode 100644 txscript/data/taproot-ref/52a46ce5d115709464d927bd868cb66e64d5d890 create mode 100644 txscript/data/taproot-ref/52b71f15e64724663db04868b953a0dd6f8ab01a create mode 100644 txscript/data/taproot-ref/52c7e56d194272214280372b7dbacf979b86a714 create mode 100644 txscript/data/taproot-ref/52da571031bbcc150454dd6be63a21c6a2dca5e5 create mode 100644 txscript/data/taproot-ref/53045f62216e6dd1d7b2d1c05dbda813f59f4d38 create mode 100644 txscript/data/taproot-ref/53090ff0e10b029e37a0eab690a757a5f4c346ea create mode 100644 txscript/data/taproot-ref/530e0b9098674994a45495cf1eb8c3fd36b04ef3 create mode 100644 txscript/data/taproot-ref/53123aee1da68a8b9619edd5140ab5c6aae10886 create mode 100644 txscript/data/taproot-ref/53234e0beefd772757294c48658a6fb1b632e5f3 create mode 100644 txscript/data/taproot-ref/5349c13d7b8dd8f692718b4ef221a21825fb04f3 create mode 100644 txscript/data/taproot-ref/5366b2cab843c6f4979214e27b561d35321bd2a6 create mode 100644 txscript/data/taproot-ref/5379718fd6733c3194547aea3041303f46159862 create mode 100644 txscript/data/taproot-ref/5394689c5e237d677fa75daa48d897e73a858ecf create mode 100644 txscript/data/taproot-ref/539798847b99eee00985bc1951275a98b55dd7fd create mode 100644 txscript/data/taproot-ref/53a808e42f754a6b97d63d9648f1e9a70ef36421 create mode 100644 txscript/data/taproot-ref/53c007e4c811059c16e10ba22c2b8c0f4ce3d99d create mode 100644 txscript/data/taproot-ref/53c3edf3601218d001c1e5074a2e608ca903fa25 create mode 100644 txscript/data/taproot-ref/53c8c5901bf8077df2161336a0fc9a5f774e1a5d create mode 100644 txscript/data/taproot-ref/53d0cafdef4e74e058c9073bbd755b723f71207d create mode 100644 txscript/data/taproot-ref/53dc16200f550b0ebabb6c5c132ae4191e1a1482 create mode 100644 txscript/data/taproot-ref/53f7ba7985ea8688080ed30b57d08c4ab91d4a7c create mode 100644 txscript/data/taproot-ref/53fd1406ce1667cf7d7de3b444b90660d76871fb create mode 100644 txscript/data/taproot-ref/540c6dd899720dbbc04e0f316f56549b4c1ea925 create mode 100644 txscript/data/taproot-ref/542c02db48e5517905eab16fd96de2d76702fe3a create mode 100644 txscript/data/taproot-ref/54305f14909100e1757674ae16a759d855c4a647 create mode 100644 txscript/data/taproot-ref/5445a326ed6ffd6f95dc9cb3c9514a0e53f4868a create mode 100644 txscript/data/taproot-ref/545537c377201418fedef933281d2dcbea90a159 create mode 100644 txscript/data/taproot-ref/547539d40d65ab39026f065bc9152d96c7c4ad43 create mode 100644 txscript/data/taproot-ref/54ab5c42625d4869197c04f218c443750527c92e create mode 100644 txscript/data/taproot-ref/54b4f9842dadbaeb2ac90b0f6d8177f76ce3f9a1 create mode 100644 txscript/data/taproot-ref/54b9966d625700d7ab8b6fb6e1c3e019b5a09f6c create mode 100644 txscript/data/taproot-ref/54bb653bb1662d8b2730bde1e4a255606fea193d create mode 100644 txscript/data/taproot-ref/54c4a1f796d9ff3acf74d30faba1654e46cb8e87 create mode 100644 txscript/data/taproot-ref/54db865605c4886df424d455f6674d7c9f904922 create mode 100644 txscript/data/taproot-ref/54eef01ce1e7ec1e6b58bb1a7e192b0e5d3a98e8 create mode 100644 txscript/data/taproot-ref/54fe044e4c6d4dfed594e15518f9550df3910bc9 create mode 100644 txscript/data/taproot-ref/55222bbf499234ced0243f0c54a06a8e01ee78e8 create mode 100644 txscript/data/taproot-ref/55296a40c4a4eec0b8b959e6e4af29fbf647774b create mode 100644 txscript/data/taproot-ref/554254ae450e17abd46d3c290600e3620f888246 create mode 100644 txscript/data/taproot-ref/554ee85d50ac67df97fb01a2eb533f4a62a41c9f create mode 100644 txscript/data/taproot-ref/555fcf75ef7ac731ace1cd81886b6cc1b013e911 create mode 100644 txscript/data/taproot-ref/555fe6827560beb47e96016c2aae78850a4e345c create mode 100644 txscript/data/taproot-ref/556a65730f4092db6fd77c12b631d10117d47033 create mode 100644 txscript/data/taproot-ref/556db9cb87763f9c127e87edfb88a8e8443c00d6 create mode 100644 txscript/data/taproot-ref/5581fa4307ec84b987cdfaee72db964e4a304876 create mode 100644 txscript/data/taproot-ref/55944a2b94a2ca58cff331e3ef254a2869f5fb50 create mode 100644 txscript/data/taproot-ref/55b0896604f6a6b38c17cf95f8c053e19d26090c create mode 100644 txscript/data/taproot-ref/55c61e7a6bf6a7b27176d90e85c792e38fa47d95 create mode 100644 txscript/data/taproot-ref/55c9ce0b7ccbe8ff676abebe7761bee66f38e3bc create mode 100644 txscript/data/taproot-ref/55cabf94b48b77fc7b0a87efd62377c6a44cfd3d create mode 100644 txscript/data/taproot-ref/55db8d546fc7e337dd899c328c82a60b6102a7b5 create mode 100644 txscript/data/taproot-ref/55f99e2d68ee85b75133f78cb948a5b7466cb4ea create mode 100644 txscript/data/taproot-ref/55faab0c69903138a86beca8e6ebc3e7a2010e0b create mode 100644 txscript/data/taproot-ref/55fc38b7d593fc118d407fcbd2ed49e3ea890734 create mode 100644 txscript/data/taproot-ref/56397a2ccd392deb6d3ed52e0a065fdde579e9d6 create mode 100644 txscript/data/taproot-ref/56567e4be5618770bb97f61b1487c7d47cf8192c create mode 100644 txscript/data/taproot-ref/5658a8d8fb388e7c7e5f7c7fc8630d3de961b676 create mode 100644 txscript/data/taproot-ref/5687a5e9c47486c4d2f24f74e09c95a9b9139145 create mode 100644 txscript/data/taproot-ref/56c988fc520dc9a5bafa28ad83eb0e972fd70567 create mode 100644 txscript/data/taproot-ref/56cc448ba82bed7220a831c4b05eabed0406386b create mode 100644 txscript/data/taproot-ref/56ed4007baeecebd4a8905063055ace47704a0dc create mode 100644 txscript/data/taproot-ref/56ff467c9c6b5e3079baa559955ba107d89d77fc create mode 100644 txscript/data/taproot-ref/570fb69de8afa341b54dd79455b6d21085c0334f create mode 100644 txscript/data/taproot-ref/570fc65b0c81c1473fc82b8545f5ae6efeb839ff create mode 100644 txscript/data/taproot-ref/57267f8aca1eeab5fdc28ec5f2cdbd6ce0d150ae create mode 100644 txscript/data/taproot-ref/572c410d27df3156ea85e726a966af51c9cadf8f create mode 100644 txscript/data/taproot-ref/576476370370b5501ea6a61ac033110ea83ed7c6 create mode 100644 txscript/data/taproot-ref/57731bef67046b96aa1a3f92ffbb41851e7b3353 create mode 100644 txscript/data/taproot-ref/5777068b6f7170fa6a505e9144aa3f6fc8625b74 create mode 100644 txscript/data/taproot-ref/578701a27b2e9321384f3e516f48fe5d2ebfad6d create mode 100644 txscript/data/taproot-ref/57ba07044f687929674d01d0c501e408072f02f8 create mode 100644 txscript/data/taproot-ref/57e2edb6bce9815f7e92a1cacf2c42a1d8a5ed21 create mode 100644 txscript/data/taproot-ref/580742d9b18b0603cb29360f8e7cbfef479c00c6 create mode 100644 txscript/data/taproot-ref/5876822a1e4504b3dcd7a3ddd10ca0dafc4c9ce7 create mode 100644 txscript/data/taproot-ref/58d98ae03e7b63b61749dae272899a7f41a89c30 create mode 100644 txscript/data/taproot-ref/58dd5844bf68fb5f47e929bf24c7d8dc2cab5791 create mode 100644 txscript/data/taproot-ref/58e9cc8b18e2ee0f4ef6cfa6222d9ba9c4e6999e create mode 100644 txscript/data/taproot-ref/58f607b447f90cc1f1f8626ebec53c5173658a3b create mode 100644 txscript/data/taproot-ref/58fb9dddb99befb27e93f61cc7346e2e320d4124 create mode 100644 txscript/data/taproot-ref/5901e4b94bc2da63a3099505728106aad680aaf1 create mode 100644 txscript/data/taproot-ref/59170b1799ffe9d1e085f2b8c38cf655ca14f1bb create mode 100644 txscript/data/taproot-ref/592e17797674340048f2ec49023bde0febe810f4 create mode 100644 txscript/data/taproot-ref/5930d2e1ddc70c728b1f219bfa14e4053fe56dbc create mode 100644 txscript/data/taproot-ref/59357c2c93a40183682393a898e6b58d6e81cb14 create mode 100644 txscript/data/taproot-ref/5951e8f0a0cafab1db40426b854148481b762ce2 create mode 100644 txscript/data/taproot-ref/595901e13730319ffed24982bd4ea8c12e89bc96 create mode 100644 txscript/data/taproot-ref/597a6a03965d41f1179d6a45268ac32531a9c209 create mode 100644 txscript/data/taproot-ref/5981777edd562076958d2a1e4c80225a425eb08e create mode 100644 txscript/data/taproot-ref/598b73c14cf25c235e0cc5c5a3bf6a5add3b0b66 create mode 100644 txscript/data/taproot-ref/5991f803b4df614fde19c2f5742b860c1a14d33c create mode 100644 txscript/data/taproot-ref/59a01c32eca07dea482bf25537b7d52b7bc5aaca create mode 100644 txscript/data/taproot-ref/59aa7a8b1146af0061b9b9478ffb499b5e7f3229 create mode 100644 txscript/data/taproot-ref/59b9a0e1dfe394504f08eae69abd47bfab092572 create mode 100644 txscript/data/taproot-ref/5a198317abb136510b17c59de5eaa7c880152f8b create mode 100644 txscript/data/taproot-ref/5a53b6c3fb03892958b022df8a6e0a4cd3d8e51c create mode 100644 txscript/data/taproot-ref/5a5abab97631cffda0f11fd3ecd87d86dc325f8f create mode 100644 txscript/data/taproot-ref/5a5d03ff40bbb94cac9b06c3d47e693d8db5af67 create mode 100644 txscript/data/taproot-ref/5a5efe209bb7d1e1b0085b1515836fcb2144c5f7 create mode 100644 txscript/data/taproot-ref/5a81cfc3ec9bfa6d49dcb19b411b6a4b6043df15 create mode 100644 txscript/data/taproot-ref/5a9d9ae70e2df49baefc66227ea1c1604902038d create mode 100644 txscript/data/taproot-ref/5a9f746ca2d826a621e61152c995893027ae3dff create mode 100644 txscript/data/taproot-ref/5b000b738705bfd4a6198d22129f7e9f2ccf1708 create mode 100644 txscript/data/taproot-ref/5b08bfcfc4f7317c5e45fbc3a683064ae85a3794 create mode 100644 txscript/data/taproot-ref/5b33a7895ef81de11965a513bcadc8ee53993d21 create mode 100644 txscript/data/taproot-ref/5b718764a0b56ae1705be7dcf35a2c639fbee6f4 create mode 100644 txscript/data/taproot-ref/5b72a3d1797578b12f235ecdfb8305d928514960 create mode 100644 txscript/data/taproot-ref/5b831888d2299bcbbe9bb60f6812a461f2da8720 create mode 100644 txscript/data/taproot-ref/5b89dad22b6b9ad7d97be2de400eaaa8ab2a03e9 create mode 100644 txscript/data/taproot-ref/5b9296392fbbb89f20c46a8276795c3b237a921b create mode 100644 txscript/data/taproot-ref/5b9476567b263e9cd4c8455b1383c48f559cdd5c create mode 100644 txscript/data/taproot-ref/5b95416a6aeb72fb134a6149c2103c7b4b8af54a create mode 100644 txscript/data/taproot-ref/5bc0284515461bcb5e3ebafccc633649bb1ec2fd create mode 100644 txscript/data/taproot-ref/5bdb30e6f918889383a02c0269f0e346fb129035 create mode 100644 txscript/data/taproot-ref/5be7de136c7e263729c299d1617ae86dd468f91d create mode 100644 txscript/data/taproot-ref/5c2aec0e280cc6dccb0aa9c3d4c5354a71c3d8e8 create mode 100644 txscript/data/taproot-ref/5c2cccde1ba71ca24440e1be3fe94d8b2abc9ba0 create mode 100644 txscript/data/taproot-ref/5c414ad191f1a4f17701285f026d3be386795f46 create mode 100644 txscript/data/taproot-ref/5c4b2bd5199eaae65eb1b50ff2282715f285525d create mode 100644 txscript/data/taproot-ref/5c4e02eac5ec6bfd2aacdf25eb5606e7f1f8d245 create mode 100644 txscript/data/taproot-ref/5c58efa0b606fd3a9f5c4149f78312e37884f070 create mode 100644 txscript/data/taproot-ref/5c7526188d4edba67f479317b2da9ebd815e25d8 create mode 100644 txscript/data/taproot-ref/5c82173fb5f60e67f6c570773d0e7ca501b2ef2a create mode 100644 txscript/data/taproot-ref/5cb8c6d32062773a2963b39820bf5c9c9d4d14f4 create mode 100644 txscript/data/taproot-ref/5ccd74670aa8f9270b7b6d1ec35f26366e24af92 create mode 100644 txscript/data/taproot-ref/5ccf6b63be9a26dc12ed0d8d9fcf8f9bd4d32aae create mode 100644 txscript/data/taproot-ref/5cd441bea952394300fbb2b175630e939f70734a create mode 100644 txscript/data/taproot-ref/5cd9d11e72f21213a0cd5e3b000d85ffc71a267a create mode 100644 txscript/data/taproot-ref/5cf79ca7fb6c27351843e8929c62c99f6d116b3e create mode 100644 txscript/data/taproot-ref/5d460d2d593010e8b116c549316144cec213da3d create mode 100644 txscript/data/taproot-ref/5d547488bdc33c4ba9f4eb64d9e510fe10c43b64 create mode 100644 txscript/data/taproot-ref/5d5955b5c12cb917cf3b4b20cef145f61555cebb create mode 100644 txscript/data/taproot-ref/5d5d395b7d0d39e7e061299a0ac6d887b277e7f6 create mode 100644 txscript/data/taproot-ref/5d67205500c9fd9a4b6a49b76f5ba2c4bc80f718 create mode 100644 txscript/data/taproot-ref/5d979fc0c97f4b30b22b3b449446ef2dad2f94fd create mode 100644 txscript/data/taproot-ref/5da06db4c347f603cf5309c3456c26cc7ff974ad create mode 100644 txscript/data/taproot-ref/5dccc42ff618aec2747273439401c4901ac182b8 create mode 100644 txscript/data/taproot-ref/5e1b24b8be80cb985494cc5e6aad6e0169f302a9 create mode 100644 txscript/data/taproot-ref/5e29c824e31a38432a78e51cb6163effbc1b7632 create mode 100644 txscript/data/taproot-ref/5e5cf1d19425ce321d71cf332626bab6bf9e5c44 create mode 100644 txscript/data/taproot-ref/5e7998196110af78479912905025c638163deb00 create mode 100644 txscript/data/taproot-ref/5ec7eb46ae8e0891018b9848bc2341e3ef6ee62c create mode 100644 txscript/data/taproot-ref/5ef0bcd2fc8dc128e8583e90e1d3848ad698670d create mode 100644 txscript/data/taproot-ref/5f065a6b9d7bf300aef6fc736b6256c582fa075b create mode 100644 txscript/data/taproot-ref/5f06fb75a8156e71669ca65d0d928c7effc223ff create mode 100644 txscript/data/taproot-ref/5f148693c5a6505500494101603fb4754464594f create mode 100644 txscript/data/taproot-ref/5f1c481f15b7e89e16871d58cd5784dc2fbfc8f0 create mode 100644 txscript/data/taproot-ref/5f33c80c85ea079ca0e803f9157053bb5cc26ce9 create mode 100644 txscript/data/taproot-ref/5f49d9e42303e9fd5d3b3beb8b4f91d1d295e920 create mode 100644 txscript/data/taproot-ref/5f617801a71e54b50b37fa8715f4acb9c710bc1d create mode 100644 txscript/data/taproot-ref/5fae0f3d4ccf63a68fa6fc6ed2f605c153bc568e create mode 100644 txscript/data/taproot-ref/5fd0ea816791d944d140a7f5a132e628c4df41cf create mode 100644 txscript/data/taproot-ref/5fd72300746767ed3942898b20e747b5e468bf3f create mode 100644 txscript/data/taproot-ref/600a49efd1ef275dd0d15886970d34f50ceb2cb5 create mode 100644 txscript/data/taproot-ref/600aee354a6065175892343ec14dc1eced5c33d7 create mode 100644 txscript/data/taproot-ref/60157ba4a7cd240aad985554d23dafcb6b99be47 create mode 100644 txscript/data/taproot-ref/601bf2a7aa8b6c3a9adef4933fc515d494f4a95c create mode 100644 txscript/data/taproot-ref/6030146df9ff31d1d977c2672cfc3792ad81865d create mode 100644 txscript/data/taproot-ref/60350336430acbd30d2f4a7afd671e1a676249b8 create mode 100644 txscript/data/taproot-ref/604aa389e1cdb7844558781a66e69bb80e5f7ed4 create mode 100644 txscript/data/taproot-ref/6070c8050e46e845c5170ec25daefa937dbbdd11 create mode 100644 txscript/data/taproot-ref/608151513d665821b3914810e70e9c1f957da187 create mode 100644 txscript/data/taproot-ref/60a40b71e2980d806f6e3f1f604e1c25d8d684a9 create mode 100644 txscript/data/taproot-ref/60c433ddebf0bd6ec3f44d608946aed9e843587f create mode 100644 txscript/data/taproot-ref/616a7fdb9927448c5c9e34f94d4f6d784f55ccf8 create mode 100644 txscript/data/taproot-ref/617d47ec32a898ac6e2b5bdd9b8e643408054596 create mode 100644 txscript/data/taproot-ref/61ac7af8ebd0ac559618d67f23d159b57dce5577 create mode 100644 txscript/data/taproot-ref/61ad3f5b692481700ab46b1c77ecf7e1590f4f72 create mode 100644 txscript/data/taproot-ref/61ad53ecbb9e93b9d193624ee3222dd39af8c8a4 create mode 100644 txscript/data/taproot-ref/61af1bfa70f27db871da9994cee2a1fa6dbfe915 create mode 100644 txscript/data/taproot-ref/61cb3c37ef29bf5abdbf60157dd9334ea8578716 create mode 100644 txscript/data/taproot-ref/61cca434775b13627deda2ffc7b421cc834c16ee create mode 100644 txscript/data/taproot-ref/61cd2f257a7e5a750b8f03f5aac0ffb2badc3aef create mode 100644 txscript/data/taproot-ref/61dfcc18f9bbed9da1c93970d11da1509777d17c create mode 100644 txscript/data/taproot-ref/622454dc9deabc8438f95f3e6280211c37369c04 create mode 100644 txscript/data/taproot-ref/626dec99c8f47a95e864b2a31b4ca6b916ee594c create mode 100644 txscript/data/taproot-ref/629399f535a4b780a7126fd274938c9e1bdd9b94 create mode 100644 txscript/data/taproot-ref/629683fa749137e2dfd6e82633d304ea6c124ce3 create mode 100644 txscript/data/taproot-ref/62c572a03d69a6b40d25947abae19bf6ce5eb385 create mode 100644 txscript/data/taproot-ref/62d04745f9fcb76848b12153a162a268f14abeca create mode 100644 txscript/data/taproot-ref/62f4696a4d80fd4c0dc13ef75f8bacef6743b8d7 create mode 100644 txscript/data/taproot-ref/62f8cb127c31b1882150c0c8effbd39c09119e5f create mode 100644 txscript/data/taproot-ref/630f756a29287a797ffb5586566bc1d25758573d create mode 100644 txscript/data/taproot-ref/63167cb8ba3874badf57f0e855e7f02478cfd49f create mode 100644 txscript/data/taproot-ref/6316bbbc6a41808b00262eab5f5262fcfa97066b create mode 100644 txscript/data/taproot-ref/63254af008fbdb6301cc07058a867abb97610c66 create mode 100644 txscript/data/taproot-ref/633faf2de8dd00d4d8b3bbdda4d9f2125613a89d create mode 100644 txscript/data/taproot-ref/63428d34338ada0748fdd95dc5f6db204de7543a create mode 100644 txscript/data/taproot-ref/634458fa7be2820b5e56c8ae2c193b953af0ad40 create mode 100644 txscript/data/taproot-ref/6360d46053a73eb3d4ae1cc875f022d5d461f571 create mode 100644 txscript/data/taproot-ref/636131ac174bfe63b118e739bb030a2fae2ae0ed create mode 100644 txscript/data/taproot-ref/6391af63a3bab91b1f963e133bbb54d1ec7814cb create mode 100644 txscript/data/taproot-ref/639afaf27cd09001a498697b15842c3394f9535d create mode 100644 txscript/data/taproot-ref/63b0cec5acbe499ece5bd821c8af36dd0de95819 create mode 100644 txscript/data/taproot-ref/63b754b26183ec079fd02af865aea1d5c49d93cb create mode 100644 txscript/data/taproot-ref/63c6cb5ef992299a9604582c39c7f956c65860b3 create mode 100644 txscript/data/taproot-ref/63c8bbd564a4a1648edf9f05d80a6b089c40883c create mode 100644 txscript/data/taproot-ref/63cc94dee9c6256ddfe004eb9fcabb932627fcce create mode 100644 txscript/data/taproot-ref/63e781018cd701d6d445dc7c4ea28f9a53de825f create mode 100644 txscript/data/taproot-ref/642e1fbd4f64d1ba035193a0100aefc8d436121a create mode 100644 txscript/data/taproot-ref/642f40f85c3e92c672ec038a2e238351c6c24178 create mode 100644 txscript/data/taproot-ref/643386ed0f556a2227416f5b32e310b70a2cf743 create mode 100644 txscript/data/taproot-ref/643f751fa11ea6d366ace6319feda720f2e8accd create mode 100644 txscript/data/taproot-ref/64537ec43a7b2b59f2b936c7247b94e44e1bb551 create mode 100644 txscript/data/taproot-ref/648fef1a9a568a6e98c2cb836193a18ec11b60ce create mode 100644 txscript/data/taproot-ref/64b6416da57fa74cb892f8728aac8bc6064ac5dc create mode 100644 txscript/data/taproot-ref/64c1ab90001da13422d892838a22208f71109eb2 create mode 100644 txscript/data/taproot-ref/64c86a5fba96a19af3d7f98cb11533d79ff4433f create mode 100644 txscript/data/taproot-ref/64c9c1019b362e31675420967685e3e5e1d92f06 create mode 100644 txscript/data/taproot-ref/64e713b456a3f23cd86eeb23d796639b7c85d2b6 create mode 100644 txscript/data/taproot-ref/650b0fcd68979a929ceb682e9024fb7beb57c2b1 create mode 100644 txscript/data/taproot-ref/652f7178db85a30195aec38e5bed56f8d492b18c create mode 100644 txscript/data/taproot-ref/6536f2a8bf497dc4fb07e6344571b041ddf3e9ce create mode 100644 txscript/data/taproot-ref/6552bfcd6579a934948b7068b4c551a0117ad0f9 create mode 100644 txscript/data/taproot-ref/657e868eb96e89c02af5430fd6fd6b371011ad19 create mode 100644 txscript/data/taproot-ref/65883b58c6b3dd90d25b39f5ccc47be52f17c9fc create mode 100644 txscript/data/taproot-ref/658ae5cbb0d9d2acbdf007a1d56b7a8d343343c5 create mode 100644 txscript/data/taproot-ref/659a2dd2fa1b9d801f3241e5ff84637ce06ccb77 create mode 100644 txscript/data/taproot-ref/65a933e1d1978ba3bd2f831c22458a755de9ba53 create mode 100644 txscript/data/taproot-ref/65b54fb91b4a1cb8c833485f4d132f6e676256e0 create mode 100644 txscript/data/taproot-ref/65b5fce87c9d43529bc25317899f3d88952342f0 create mode 100644 txscript/data/taproot-ref/65e72ac1ffd20fc948eb9fd0715334a200044fb6 create mode 100644 txscript/data/taproot-ref/65f7ef2d10a182c5af3e4c60b4f23f13770b1d2f create mode 100644 txscript/data/taproot-ref/660b8322660c10bb3072efbf02a01b028869f3ed create mode 100644 txscript/data/taproot-ref/660ef1c053328676703178f6c1f1a9eab0eba34d create mode 100644 txscript/data/taproot-ref/66252c3d296124f1a894a2bef80eb0b8d2780c58 create mode 100644 txscript/data/taproot-ref/6652466b4852d5b5fdaaa69e10880f1a3b76c3fa create mode 100644 txscript/data/taproot-ref/665eb41953197df4c60f261f2844052bbd0c48b6 create mode 100644 txscript/data/taproot-ref/66726b80715835e1ff8fad96f3c76a0309586a88 create mode 100644 txscript/data/taproot-ref/6699c94d11593280e700614b550ad835b0025476 create mode 100644 txscript/data/taproot-ref/669ff69c2c67c7765c32e86e0eda8fcf04bcdbdd create mode 100644 txscript/data/taproot-ref/66bbe506485ecc1f5f29905e93bbc326b119a9db create mode 100644 txscript/data/taproot-ref/66cb36473c4a75d094b0c109710f2456a52e3ac0 create mode 100644 txscript/data/taproot-ref/66e881b64f9e9007cc27f9ae6ea1d9c09b7ff1dd create mode 100644 txscript/data/taproot-ref/66fd2e2f42f7b15c03f46c8f5852fc2b2a1288d4 create mode 100644 txscript/data/taproot-ref/6723a627907cb1d91034b75d6a69d055a9d2a9b2 create mode 100644 txscript/data/taproot-ref/674c86a431b193721af73dfdf07aeef65a7ef508 create mode 100644 txscript/data/taproot-ref/674e2feab074ca0240a6ca55826b14e434793461 create mode 100644 txscript/data/taproot-ref/6766fbe9f961609fc3c2e2dbb922ddf1dc771d96 create mode 100644 txscript/data/taproot-ref/677c2fb0bd66dbf157aed281b05b92ad2c197c37 create mode 100644 txscript/data/taproot-ref/6790425ac6ab89b1bf9e69e61d0a23def2470c84 create mode 100644 txscript/data/taproot-ref/679748203674073239d2e5a0f7f9da26bc60feb9 create mode 100644 txscript/data/taproot-ref/67cfc5cf8010d9b1c152301eae06d149589112ba create mode 100644 txscript/data/taproot-ref/67f26334e58a0356529496d89738359b7a8dd136 create mode 100644 txscript/data/taproot-ref/68052b4483af39b51b45980874124e3793c72420 create mode 100644 txscript/data/taproot-ref/680f37fd69b7d65b2bea1f6968d0d19d60d93bb6 create mode 100644 txscript/data/taproot-ref/682b9ef29382e2d77b5242e0860693527c825702 create mode 100644 txscript/data/taproot-ref/68560332b36281ab2ef6e177361019a087666119 create mode 100644 txscript/data/taproot-ref/685bad2808b9ebb6dd3bebf554aba2916e169a21 create mode 100644 txscript/data/taproot-ref/685c94cdfdc42c71493f0fbf86f6cc75a2bfe7f5 create mode 100644 txscript/data/taproot-ref/6864a32b8e40345c0b76999afe5f1c070d474908 create mode 100644 txscript/data/taproot-ref/6864d1927bc63a92a60460a41b2a104d48d49e0a create mode 100644 txscript/data/taproot-ref/687590a8d9eb9f62d77022572d103d4c5adc9867 create mode 100644 txscript/data/taproot-ref/687648741dc59ceab592c14d35fa96ac27ef98d1 create mode 100644 txscript/data/taproot-ref/6890f89ae85a96d458a2e92ae84db78ff5a3d8e4 create mode 100644 txscript/data/taproot-ref/6893c34edde19b9be594417a3321f7522c83713a create mode 100644 txscript/data/taproot-ref/68ae4d6748f33706497031526da5fa76f0c923a1 create mode 100644 txscript/data/taproot-ref/68b62ec5b8680759a52e8934526dbf400162c104 create mode 100644 txscript/data/taproot-ref/68c6c0d42504385245c61282657b3afb267a068a create mode 100644 txscript/data/taproot-ref/68ebe4901e5b73c0d6c376b14ab93cb27b6b9b29 create mode 100644 txscript/data/taproot-ref/68f2022142d8ce6c1188c67a635ce455d70e8668 create mode 100644 txscript/data/taproot-ref/68f3ade32553e6641d33ffec7c4bbbe70c966a75 create mode 100644 txscript/data/taproot-ref/692178574c30ecc0fe297e53225c7fe6b7047923 create mode 100644 txscript/data/taproot-ref/692a5e26fd84eb7c487336a8ad5a27bbf550d3e5 create mode 100644 txscript/data/taproot-ref/693b4e80b442d5871a480b72fc7f154489eada7b create mode 100644 txscript/data/taproot-ref/693f1072f030299b192b97d19cba8ff9e045ceba create mode 100644 txscript/data/taproot-ref/696eb3cf37f866313a3dbf40b4af77d45f827d98 create mode 100644 txscript/data/taproot-ref/69763ca3d19be4c3d360ac96f990730c211450f4 create mode 100644 txscript/data/taproot-ref/6977dc4cb03457ddcfe3fb5e4ebd32c7a60a4f4e create mode 100644 txscript/data/taproot-ref/697a7f07151aad714b88aad13a439841eb1d849b create mode 100644 txscript/data/taproot-ref/69c1c268224ffcce5d6dc13b49962a3c8887c2ba create mode 100644 txscript/data/taproot-ref/69d24f5639ca8a5eaf58924722cc313b9936c330 create mode 100644 txscript/data/taproot-ref/69f36a1e1c567e1d5e44edc58c355abb92e23f68 create mode 100644 txscript/data/taproot-ref/6a35130e1e9674f6d1c241fd478fe85332fbdbb1 create mode 100644 txscript/data/taproot-ref/6a37620db708370995281cf6c46512cd60efeda8 create mode 100644 txscript/data/taproot-ref/6a8e8effd233033afabfdaf9d971d772b2bf9ecd create mode 100644 txscript/data/taproot-ref/6abb0ece7e16ec849987f8c8acf3aee7013ec5de create mode 100644 txscript/data/taproot-ref/6addba1d7123769bf9727a6a4106110126f36086 create mode 100644 txscript/data/taproot-ref/6aff050ffc62f58100aca0e5b1839f097fe65155 create mode 100644 txscript/data/taproot-ref/6aff0519662314531494b8b3319e2768ebd40a35 create mode 100644 txscript/data/taproot-ref/6b14353e2b7d7788062623a8ab274c36f8e8bf3b create mode 100644 txscript/data/taproot-ref/6b611309b991acee95b55b4b19539f65ceccf76b create mode 100644 txscript/data/taproot-ref/6b861044122a6b081803e3a99f47b40277743d06 create mode 100644 txscript/data/taproot-ref/6b8790739dcd1f8d3ef41a03c6508717d78feb52 create mode 100644 txscript/data/taproot-ref/6ba407f0a422507bed18c1d5b52f1f550c278fcb create mode 100644 txscript/data/taproot-ref/6bc93c9d2144506aeb9dbbe41a5b4a095f8fe9cb create mode 100644 txscript/data/taproot-ref/6bde125fedeb05208eb8991bab6ad0713a60d9e4 create mode 100644 txscript/data/taproot-ref/6be0d8042ea3f474de849bc8205c65b017a3d587 create mode 100644 txscript/data/taproot-ref/6c1bef32f6ca0cfaee1705746902336e4fd67e96 create mode 100644 txscript/data/taproot-ref/6c3db2c6ab0b6b80838387b923869561f9e1cf11 create mode 100644 txscript/data/taproot-ref/6c7e6cdda9913347f0ba8eed8f914941cec5b2c1 create mode 100644 txscript/data/taproot-ref/6c8a1b2ea553e6dfa5f653afeeb135465732aa6e create mode 100644 txscript/data/taproot-ref/6c8acc451d0c73e74ad6918585d0c8776498affd create mode 100644 txscript/data/taproot-ref/6ca4ca112dc6f3b82a4ee1dcb539f5412b61802e create mode 100644 txscript/data/taproot-ref/6ca7072324326a43f42b641dd4cc2d785bfbb7d6 create mode 100644 txscript/data/taproot-ref/6cbefe4b22649c02c818e52d3142c768ae99b9eb create mode 100644 txscript/data/taproot-ref/6cdb87bebca9057c621affd2eddfbe726630b1c6 create mode 100644 txscript/data/taproot-ref/6ceffd0098b1fadf6f95341e39b6b1486b6e2dab create mode 100644 txscript/data/taproot-ref/6d1ad01f9d4765e28554608aaaaf7f86d7fee48a create mode 100644 txscript/data/taproot-ref/6d2c53b612c9e3931c251808123e215918c34b60 create mode 100644 txscript/data/taproot-ref/6d6cb592531f25b7c0a1a607342e2c3dcf35ac1f create mode 100644 txscript/data/taproot-ref/6d776b8dcea06b627feb06e8e07e6455f48086d2 create mode 100644 txscript/data/taproot-ref/6d807824d43b2e677fee210fcdda1e52cabbbbc5 create mode 100644 txscript/data/taproot-ref/6d874714ddd3706018c9051c55abbcf1210b4643 create mode 100644 txscript/data/taproot-ref/6d9b8efdf33eb396820e03892263d3b784e5dcf5 create mode 100644 txscript/data/taproot-ref/6de00eee762e4ed839eb40fe1f0e25de0071e584 create mode 100644 txscript/data/taproot-ref/6e0058983c03e5e6a363e64deb28a252b20617c1 create mode 100644 txscript/data/taproot-ref/6e20107c698b7f36b9163a7db7382e068caca218 create mode 100644 txscript/data/taproot-ref/6e41239fdb2bae4970f0a9787e683e94dcfb1760 create mode 100644 txscript/data/taproot-ref/6e59dc43f59b064311d89a689dd58f9a905d10e3 create mode 100644 txscript/data/taproot-ref/6e85ec4ec7f9980d8de6d6892d1415072155eb5f create mode 100644 txscript/data/taproot-ref/6e99af85369d8643f1c91d6e46c038af402d368c create mode 100644 txscript/data/taproot-ref/6eb985be69c6686dbcfaa0cfeba04cbc68dd5298 create mode 100644 txscript/data/taproot-ref/6f3e92cd7c0bd1c759a5d1ec589fa593028c2f27 create mode 100644 txscript/data/taproot-ref/6f52449eba2cea1fa19799e7de8f931e69c70cdb create mode 100644 txscript/data/taproot-ref/6f56fca6cc1c01fee921e3ebec30d918b7e84af1 create mode 100644 txscript/data/taproot-ref/6f6d754696a56d367c058bd6cef710ac92a36c4d create mode 100644 txscript/data/taproot-ref/6f7390dad86b309a8464acc781b7a22cdc6164de create mode 100644 txscript/data/taproot-ref/6f775290762b949c8416b8db72a80fd4f625aeeb create mode 100644 txscript/data/taproot-ref/6f8393bbb9d02857705efc61028b43ee819ae6ef create mode 100644 txscript/data/taproot-ref/6f8e2a9cd5725921d637323d42b65faaa53b2d0c create mode 100644 txscript/data/taproot-ref/6f9c6ccc8504bc417cff64152e5d55f2da6384f6 create mode 100644 txscript/data/taproot-ref/6fae620fa980b4c2193b8d1ca489fecb771da643 create mode 100644 txscript/data/taproot-ref/6fd7c011c1e087678c2fc502f6049d5a1610b285 create mode 100644 txscript/data/taproot-ref/6fda74aa278e18be569d89d76d2b7d189719fc9b create mode 100644 txscript/data/taproot-ref/6fe4cc6bb00f0db22fe4cf7e68170752bf9e1f7d create mode 100644 txscript/data/taproot-ref/6ff3146da9ac0acb6f0c208976dc39290b684b16 create mode 100644 txscript/data/taproot-ref/6ffb4a945d04f8b031049d6b6fa49f15f19568e5 create mode 100644 txscript/data/taproot-ref/70103c6bfa6033fc750d73a791d50375a1b86fea create mode 100644 txscript/data/taproot-ref/70294d4a0a0438dea998f982369933dacc66aacd create mode 100644 txscript/data/taproot-ref/708f0996354e7df20b2aef4b10bc9586dcaa5db0 create mode 100644 txscript/data/taproot-ref/70c7802de56e11939701cba269f74c5c54434e61 create mode 100644 txscript/data/taproot-ref/70cd3f4760a280eac2806e6373034a5e750cb013 create mode 100644 txscript/data/taproot-ref/70e123fe2099ae69883a84234ee7d2c67ffae902 create mode 100644 txscript/data/taproot-ref/70f98e7683065de833f78e968b12a17560c6d145 create mode 100644 txscript/data/taproot-ref/7125c24e3079aa7ecd8a075096657aa41cbf32aa create mode 100644 txscript/data/taproot-ref/712c593d655c49212ff38704eff4d5d68d14506d create mode 100644 txscript/data/taproot-ref/713565a78c4f0eefe92a042e831427511dd4f5b9 create mode 100644 txscript/data/taproot-ref/715cf3f1edec8508d34687cba9eb9735c4113fc8 create mode 100644 txscript/data/taproot-ref/716e9a2309a2d14f0b54d759df166270321962ca create mode 100644 txscript/data/taproot-ref/71807ffa82a2c8190651c69c857cb71bcb08e301 create mode 100644 txscript/data/taproot-ref/71a2de6544779c774612b1f87277375ae9792a62 create mode 100644 txscript/data/taproot-ref/71d2976410e52b3891d47b0bf5daf36223655072 create mode 100644 txscript/data/taproot-ref/71d3d5be815413f81a15e1f21d82fa46ce4eeab9 create mode 100644 txscript/data/taproot-ref/71ea7e6e573f89e2a23138bfbd547d888bdb7c55 create mode 100644 txscript/data/taproot-ref/71f13e97734a6166d08d71982621f3785ea5ae3d create mode 100644 txscript/data/taproot-ref/7217d80b5053a43d6fb6822470d12e76b42b2764 create mode 100644 txscript/data/taproot-ref/7222bfdff7231c2aa5afe88a9b8860e057c947b7 create mode 100644 txscript/data/taproot-ref/722914ef8c3dfacc1243877cf6bc0be5cc3eb6c2 create mode 100644 txscript/data/taproot-ref/7275e47aff6a2c0f8bacb56d065aaba591e02a30 create mode 100644 txscript/data/taproot-ref/72790cb9d6895411ac13e44b9be62c5cb05584e7 create mode 100644 txscript/data/taproot-ref/7282e73fa9d18fc99fa2f10c51211fe1079693fe create mode 100644 txscript/data/taproot-ref/72893e972bd42b8697f75e7ac80c8885bf7c3a45 create mode 100644 txscript/data/taproot-ref/728c6175ed68889cfe3f359471f509fd1da1623a create mode 100644 txscript/data/taproot-ref/729abe2b4cc9df53668a78ea8236ae421f3b5173 create mode 100644 txscript/data/taproot-ref/729bc90d92d1235d6d3bc4c56bfc5a7cb1532e39 create mode 100644 txscript/data/taproot-ref/72a19edf12311bc49d7e72f4ce0d25f68b5ba472 create mode 100644 txscript/data/taproot-ref/72b351e21f164a536ef913cda1b95716c0de23ce create mode 100644 txscript/data/taproot-ref/72b831f893332ad3733b0af04ea0e76cac65b5dc create mode 100644 txscript/data/taproot-ref/72bd024e4b285894458f234b460fcaf90e8445cb create mode 100644 txscript/data/taproot-ref/72de723051c80828a6318b2251cdaf29db2600f1 create mode 100644 txscript/data/taproot-ref/72e0280dc174679a75da3799cbb41ffe349f9f46 create mode 100644 txscript/data/taproot-ref/72f423c06f55b024fcd60e3acd20f596205615ab create mode 100644 txscript/data/taproot-ref/73319dedec7db18100aca1acbdf582d38ed80c64 create mode 100644 txscript/data/taproot-ref/733a381bc9e56cec2e4a856413e56d0bb7972662 create mode 100644 txscript/data/taproot-ref/734891576e6360feb0a79e5f6326f4a0f3310853 create mode 100644 txscript/data/taproot-ref/73617507f1dbe680e93caaef1d078ac92ad846ba create mode 100644 txscript/data/taproot-ref/739b15f40bb87a9e4f1a8399ce654d068bd0d30b create mode 100644 txscript/data/taproot-ref/739c724fbc1d946d981066a3f82cfb09a034ba1f create mode 100644 txscript/data/taproot-ref/73a2aaa511c3c79634f98183fed1aa515112c30c create mode 100644 txscript/data/taproot-ref/73ee1a7d0acd1f7e6a29e2cc9de52adf757c34f3 create mode 100644 txscript/data/taproot-ref/74033d1959e62921897648eae99b7576a518dcbb create mode 100644 txscript/data/taproot-ref/74068e2edea30ca07fc3d6536b7beb1e73610c5e create mode 100644 txscript/data/taproot-ref/74077dff1318da9fbe3c8ecbcf570fa2b161a310 create mode 100644 txscript/data/taproot-ref/742166e63d37f163f9bfa53c3d1ca1c432028519 create mode 100644 txscript/data/taproot-ref/742c9cda5fd595f2f4acc988670128b67aa2cce0 create mode 100644 txscript/data/taproot-ref/743bd395e890e120441210e9d92579d0c7fd94d9 create mode 100644 txscript/data/taproot-ref/74433925d2da6bb3c3edcc954a98eca9eeb57abd create mode 100644 txscript/data/taproot-ref/746569f919dd66a45ca13b1e18824a0afdb22d9e create mode 100644 txscript/data/taproot-ref/74685cb831119333da8b5a7c83e055eedbef944e create mode 100644 txscript/data/taproot-ref/7482f850ee397dd25bd1687e64b7eea626e9c608 create mode 100644 txscript/data/taproot-ref/748b5f0d6e2f9fa4665f7445654524ae50ffc8ad create mode 100644 txscript/data/taproot-ref/748ece6f6568749de6856f4e101f00d04a22d979 create mode 100644 txscript/data/taproot-ref/74965c4ae1074a7c5d80f0889dda62db64f0d7d3 create mode 100644 txscript/data/taproot-ref/74b0040c6bed65b152921df24d1d78125695306f create mode 100644 txscript/data/taproot-ref/74ba2f22626f43b6a2563b0cb35c620433682d40 create mode 100644 txscript/data/taproot-ref/74dba0abfcd70931e9e189f44c9fe76cb1cdbb0a create mode 100644 txscript/data/taproot-ref/74e0dd99e051486e796a28c6482f0b52f0af67a1 create mode 100644 txscript/data/taproot-ref/75255d425818aa4e45fa7a8ce30896b30e5f57bf create mode 100644 txscript/data/taproot-ref/75362838d1ed152f60dc3cb74924d167c1b0fd2b create mode 100644 txscript/data/taproot-ref/7559c841c04c474bc9ff45fe8504abb5d4e8f57d create mode 100644 txscript/data/taproot-ref/757adad4f7dd459070f4f1b1f4f4f2374a57ec6c create mode 100644 txscript/data/taproot-ref/75ed237efa308c478c8ee1faa516c94e45f17495 create mode 100644 txscript/data/taproot-ref/75f1856401af3c6957b627bba156ed076e49ef5a create mode 100644 txscript/data/taproot-ref/762487d62765bf58b6c712ce69edfc2a9d91f23c create mode 100644 txscript/data/taproot-ref/767dc9730435e95ff0446a5e08a10843c28b5e4d create mode 100644 txscript/data/taproot-ref/76967f9679742d07c45801b75cdb5ec88f3ea2e6 create mode 100644 txscript/data/taproot-ref/7697ccd8a0cbc267875cf87e7ce982f8dbffa82b create mode 100644 txscript/data/taproot-ref/769cf64713d5676b0d7823f406502b750f29f48a create mode 100644 txscript/data/taproot-ref/76adb95f40dd46b0cd442f82b7eb70ed237f1676 create mode 100644 txscript/data/taproot-ref/76ba7be2b975f49a68b47d255757883a4fe65358 create mode 100644 txscript/data/taproot-ref/76bc86d13bce32da92769372e37076c675520959 create mode 100644 txscript/data/taproot-ref/76c17c551bd5e5ae2efbb26f2e05d12c9c8181b3 create mode 100644 txscript/data/taproot-ref/76c565f5646ff08d8c740ffe4cf133d9c8a3fe65 create mode 100644 txscript/data/taproot-ref/76f5c55837a53eb0781baf11e0de07184a6d08ee create mode 100644 txscript/data/taproot-ref/76f83799d26fbfe8607158f4718d6f5cfdc8621b create mode 100644 txscript/data/taproot-ref/7705fd1f70110abbefb84b8bb3679338dc85008b create mode 100644 txscript/data/taproot-ref/7722142222386c62ee3cf0d244202e77b759f34b create mode 100644 txscript/data/taproot-ref/77258dc253bbfcab9ac3a990bda4f20592f9c651 create mode 100644 txscript/data/taproot-ref/7726ec0c41e3e97e7d617065e6504efb8f024cd4 create mode 100644 txscript/data/taproot-ref/773d0e073333f130bcff75d37d1111faaebee058 create mode 100644 txscript/data/taproot-ref/774784914f2077e1681344cb01340a934be26ba4 create mode 100644 txscript/data/taproot-ref/77907cfa0df9ad35b28a28dc974519599031d5b7 create mode 100644 txscript/data/taproot-ref/77a416c6802644089ebc937712578c64cd114e2e create mode 100644 txscript/data/taproot-ref/77b1d215fef8b044b5354a64c3541f96a5eed3ef create mode 100644 txscript/data/taproot-ref/77bc35d370a04908ca4a6126a011623e2b09442d create mode 100644 txscript/data/taproot-ref/77d0cc6e1223f82ea66b45b7eefc97601034b9bb create mode 100644 txscript/data/taproot-ref/77faf5783504d2bd51c625bcecb48b8f87e8e165 create mode 100644 txscript/data/taproot-ref/78251c5d9b329e36203639010c03798c0e1dcf20 create mode 100644 txscript/data/taproot-ref/78536c856a97d639ec3c9e87656c03a486180cb2 create mode 100644 txscript/data/taproot-ref/78a8516593c8bad79e4092b1b3fc0a850a266c4e create mode 100644 txscript/data/taproot-ref/78a85c295a5f5c62f56d7eba74225f31406a0b51 create mode 100644 txscript/data/taproot-ref/78aa0f27c839d5f0b6120545131237373c9ae941 create mode 100644 txscript/data/taproot-ref/78bb53d71409ce127d2a0ea2bb3fe8ab857c3db0 create mode 100644 txscript/data/taproot-ref/78f579fb1bbed4948a321bcad1a70116b995076e create mode 100644 txscript/data/taproot-ref/7929ee70089306f9173670db39ef247d71e6d01c create mode 100644 txscript/data/taproot-ref/79348dfc973141bd7bee5f470ac28ffd56e6591c create mode 100644 txscript/data/taproot-ref/794d2929ccd4a9f38151fa274b7bba0a898aa30c create mode 100644 txscript/data/taproot-ref/79693f140367ae963c396d7952f2b07e3e603755 create mode 100644 txscript/data/taproot-ref/7988534604fb11aa559428f200cd7631d266dcdc create mode 100644 txscript/data/taproot-ref/7993ab06fc93824943100f468b83a388dc8396fc create mode 100644 txscript/data/taproot-ref/79a78205700940deac5a3af06b37f7a837ba5d0c create mode 100644 txscript/data/taproot-ref/79dcbe312ec0cae55271acea3fbcad77eb51a258 create mode 100644 txscript/data/taproot-ref/79ed5f67b23082b621f1d3d307cbb3833df70b36 create mode 100644 txscript/data/taproot-ref/79ee5f66d93ee0d29f8b42ccf65fc760525867d6 create mode 100644 txscript/data/taproot-ref/7a043102c33d83ed36e9879386a6e618668535d9 create mode 100644 txscript/data/taproot-ref/7a111af866866f2de4ef478fd546fb1c0fc25d0a create mode 100644 txscript/data/taproot-ref/7a1820d857c8a49a2db73ca33ae771ff2942dccf create mode 100644 txscript/data/taproot-ref/7a490995df2d5f17d023de70297a3ccd20b7e9f0 create mode 100644 txscript/data/taproot-ref/7a4a6b8236fc89f7d9e11728eab5f34c87b831ca create mode 100644 txscript/data/taproot-ref/7a59b37e047189062f0abaf0d629290ecfb35f75 create mode 100644 txscript/data/taproot-ref/7a69a216cc5a6c99a19546872d16973b864b8ec6 create mode 100644 txscript/data/taproot-ref/7a6afdaaff4560a33eba5ebd9df662b110b72dc2 create mode 100644 txscript/data/taproot-ref/7a87119e2369843226572e9e9603e14022ad565d create mode 100644 txscript/data/taproot-ref/7aa3606e89e98945870fd6072bc248da2ac00194 create mode 100644 txscript/data/taproot-ref/7ab6a9ca3af298309556e392c5a2145121ecad20 create mode 100644 txscript/data/taproot-ref/7ac66a26b371216e55464bd620f00f9b3cabf539 create mode 100644 txscript/data/taproot-ref/7adcfb6ec993d4f55872e19410191727163f6958 create mode 100644 txscript/data/taproot-ref/7ae9dff22041f4c1fe093655030d83341a775789 create mode 100644 txscript/data/taproot-ref/7b1eb9664a41baa7f5e742f91eba9581bd509407 create mode 100644 txscript/data/taproot-ref/7b242c6392ed925c411f5a03c01a5b224498873d create mode 100644 txscript/data/taproot-ref/7b302c63a0c095634d5b99d885e31d50d348915f create mode 100644 txscript/data/taproot-ref/7b385bf3549519df825d01ede2e8d9864af0d4f1 create mode 100644 txscript/data/taproot-ref/7b8328e1cf64ee86aed185c42ef2d58842a86505 create mode 100644 txscript/data/taproot-ref/7b9f95b7241f7c9902e959452e13b67e26806ad6 create mode 100644 txscript/data/taproot-ref/7ba72ec40b0c475f5d75c1845b6a75ce8fa2c003 create mode 100644 txscript/data/taproot-ref/7bcb414301b9d095183f9b852a0c948309483542 create mode 100644 txscript/data/taproot-ref/7bd191b72e7ea5e8407c5a81557fb3489574834c create mode 100644 txscript/data/taproot-ref/7c0066094d3af7d6ae9649b1e0d8c4f65d29d5b7 create mode 100644 txscript/data/taproot-ref/7c3defc5ef17cddbacd31b76689e0f6d0737ac57 create mode 100644 txscript/data/taproot-ref/7c7017c2b46f27580791e590ff2536195830225d create mode 100644 txscript/data/taproot-ref/7c7b7ccbaea2f13ad6524f8a286a5a8e5de67e21 create mode 100644 txscript/data/taproot-ref/7c81f44f5bced662dae488456a190a2b5b68c852 create mode 100644 txscript/data/taproot-ref/7cc6f39aa5cdd7a9af8b06f6627638b3bb770f40 create mode 100644 txscript/data/taproot-ref/7cfcff79af9057d0133f2b5da206b608722bd025 create mode 100644 txscript/data/taproot-ref/7d568d459cf98a02f42d26cf7a40def28f45c07c create mode 100644 txscript/data/taproot-ref/7d77c20b635f8d363cafef80ce333359495fddeb create mode 100644 txscript/data/taproot-ref/7dbdb91634696f23cadac0af049ca2841cbf75df create mode 100644 txscript/data/taproot-ref/7dca132115921f6d0134e317bc0c5b2e5b97934d create mode 100644 txscript/data/taproot-ref/7dd14622cf7fe1695e710f01b45d90250043dea6 create mode 100644 txscript/data/taproot-ref/7ddf0e4fc007dcceddccc60c7634ce32af1c1782 create mode 100644 txscript/data/taproot-ref/7de80c1c4a6415b28404560b4e476f7ff798b292 create mode 100644 txscript/data/taproot-ref/7e165223d7af3c0a9b55423a23a84315b3549c34 create mode 100644 txscript/data/taproot-ref/7e2b8b5d88ab86a02660c9f930b1dc7bc915500f create mode 100644 txscript/data/taproot-ref/7e2f0de68af4544f103e74bd384b74b2e2f85241 create mode 100644 txscript/data/taproot-ref/7e4029c06ed03535d5f51420d860c7da16cc155e create mode 100644 txscript/data/taproot-ref/7e70e8a2a78ad2b7e350dc4a07651a5bf027cb57 create mode 100644 txscript/data/taproot-ref/7e874b33beab6c09e8cdbcdcf34c226d959f53a7 create mode 100644 txscript/data/taproot-ref/7e926dc258ef73747c6dee6961a01976f75e194f create mode 100644 txscript/data/taproot-ref/7e952aa0d4d919ea11291440bf1f5548858938d6 create mode 100644 txscript/data/taproot-ref/7e95b122591089fda778a2dbd434c55672c92346 create mode 100644 txscript/data/taproot-ref/7eaf9980118567289bdc91759abbffb031b64227 create mode 100644 txscript/data/taproot-ref/7eca413996ccecf266e5bf306d63db50903b1ec0 create mode 100644 txscript/data/taproot-ref/7eeec8eac2847cfc829b4f04a7732871fa5b33bb create mode 100644 txscript/data/taproot-ref/7f31dda7857641eb43ac8f245109af960b934c86 create mode 100644 txscript/data/taproot-ref/7f36ff093686c198384796967779e512b39b0067 create mode 100644 txscript/data/taproot-ref/7f37fc6f46dfd2056c23dce7388e996b2e007166 create mode 100644 txscript/data/taproot-ref/7f5fb097a29a27b116140b9366006e578d1139ce create mode 100644 txscript/data/taproot-ref/7f6b5c7e454d101b3d586c7653b251e1aaa8404d create mode 100644 txscript/data/taproot-ref/7f76a08aef5329137e1c80a8f4fc7245375849d9 create mode 100644 txscript/data/taproot-ref/7f7be6c8663be7951320cb6c651781e5583ed65e create mode 100644 txscript/data/taproot-ref/7f8f81d1bf5547aca3adaba322cccf59977c80b0 create mode 100644 txscript/data/taproot-ref/7f9d1a52ba029c7f6e88ff84575df1fcb1075619 create mode 100644 txscript/data/taproot-ref/7fc1bf414713fa9f80c252358021f9f97b15c792 create mode 100644 txscript/data/taproot-ref/7fdcc6c41ae23f27834e5e1303ac7e3a7a01c43f create mode 100644 txscript/data/taproot-ref/801315c10fe0fcc26c0c57bc8f631cd93596168d create mode 100644 txscript/data/taproot-ref/80333b40950b8f22b44ba7c383dc625b1b094df3 create mode 100644 txscript/data/taproot-ref/80376b2b822b9baaef72428ca022d2e8ad5fab95 create mode 100644 txscript/data/taproot-ref/803cd5f12d095d218780ad627b0b82b0bab86370 create mode 100644 txscript/data/taproot-ref/8046cd7645e89a0fda7d8f8378e8425fefabb6e8 create mode 100644 txscript/data/taproot-ref/804b90af698434a3596956677aba5a5f73dbaed0 create mode 100644 txscript/data/taproot-ref/808bb1522f5aa5de2dee150c5fe9b2240c76f14e create mode 100644 txscript/data/taproot-ref/809f182745ce2d04f2ed1126bbd41c71d290955e create mode 100644 txscript/data/taproot-ref/80b5c3a4f3efc732cfad5a798289e246619f8977 create mode 100644 txscript/data/taproot-ref/80b9b953d5d211827d5046ddef05778d9e6fe889 create mode 100644 txscript/data/taproot-ref/80ce5e7fb2b5a1cf0cf9bb4b9a786e4bf6735056 create mode 100644 txscript/data/taproot-ref/80d98df3c15079be160fd7897dc74ef9a9b4774b create mode 100644 txscript/data/taproot-ref/80dfc8a9fc0fe40ea7577dfd42a34b367905756e create mode 100644 txscript/data/taproot-ref/80ed8061d1dc94f53f2e897f7421f7e7109037ef create mode 100644 txscript/data/taproot-ref/8114bd4cff1787b06e5836915e62486478f693d1 create mode 100644 txscript/data/taproot-ref/8114ee0d2c07fd933798fcf7febf9e08b6cf1043 create mode 100644 txscript/data/taproot-ref/813b01314937089f22d1d64ac7030c5da92ac36d create mode 100644 txscript/data/taproot-ref/814755d13f451119bbd6e341778fcca05d023f99 create mode 100644 txscript/data/taproot-ref/8152fa388ef907459fca58c6382e7cf481e8b03f create mode 100644 txscript/data/taproot-ref/816316a3b73af9b70141fff8b2deda8269d38d34 create mode 100644 txscript/data/taproot-ref/81639ecf4a65a0d2972d186cbca46aa48c408a2b create mode 100644 txscript/data/taproot-ref/817d2dc89f753f1b403cbbdd6c078eeee50563d1 create mode 100644 txscript/data/taproot-ref/81873f88c2fbdb0a58e15e3492b63cb1eeebd61d create mode 100644 txscript/data/taproot-ref/818a1e4250991ce3f414e0f7215308cf2f23f7fd create mode 100644 txscript/data/taproot-ref/82050e725b7ee8e6090dcb98775499dc19017c4d create mode 100644 txscript/data/taproot-ref/826b8362320fe6f06ab5a2f4b4fbf5c94448170f create mode 100644 txscript/data/taproot-ref/8283d17b50ed5619f147c5b35a8f94626b7d5b26 create mode 100644 txscript/data/taproot-ref/829c3ad6c8ab04d87634c91b6fcd79faa92656fb create mode 100644 txscript/data/taproot-ref/82a84993b98a8fb62799914dc21be4be700e7b5d create mode 100644 txscript/data/taproot-ref/82e6db8a76fd387b0eb64cb1d7bf968ef761fb96 create mode 100644 txscript/data/taproot-ref/82ec131b824b4c3f3757e1edd238735d0656fc37 create mode 100644 txscript/data/taproot-ref/8336cc9fb782ee91ec2fca64631271cf0078de20 create mode 100644 txscript/data/taproot-ref/833a14196d27bc959251f1d19b9e4e6829d267d5 create mode 100644 txscript/data/taproot-ref/8366f34c8cc56c4971befa8d4905f0f436bf6cda create mode 100644 txscript/data/taproot-ref/8393e8cc899fa71d1c638c5cb8eea55c40342700 create mode 100644 txscript/data/taproot-ref/83945bfa970aa433de420b7ac4f4efcc297ec972 create mode 100644 txscript/data/taproot-ref/83970d72a6907256d4feab8e061182642c3d4b24 create mode 100644 txscript/data/taproot-ref/83b00e365af084f70ba64981a783c5ec81c0e650 create mode 100644 txscript/data/taproot-ref/8434ef7375003e0e049d9248cca04a7d89a51736 create mode 100644 txscript/data/taproot-ref/8442ffd276255dd9c5995c977f30f700234f866f create mode 100644 txscript/data/taproot-ref/8462f1863bdba9f38df24dbeb39d9be31a8b3d93 create mode 100644 txscript/data/taproot-ref/8478b1cc13202df27bd080e55410e541629423e8 create mode 100644 txscript/data/taproot-ref/847ca904186295e8fd47a4e29885615907cb992e create mode 100644 txscript/data/taproot-ref/847d38e6322523b12583cde1ac03aa9cb6c11494 create mode 100644 txscript/data/taproot-ref/8485b7daa7b9582b7257e4ad6aa767ad9b2c7173 create mode 100644 txscript/data/taproot-ref/848ef68b2028c2d1d2c774427baef8811e6973c6 create mode 100644 txscript/data/taproot-ref/84b78b9ad073a948405f0b7ab62f9f69118ba8f0 create mode 100644 txscript/data/taproot-ref/84c54f3da6a5e6fab8e1f0e9e437a602b838b808 create mode 100644 txscript/data/taproot-ref/84d1cf1063766590aee538d2b55b7bd3698c0de7 create mode 100644 txscript/data/taproot-ref/84dce9fa92c533d455e0c1f97179960220f0a855 create mode 100644 txscript/data/taproot-ref/84f74ecd7dcd980cbe8f5c5df3e9de9eb9e2198b create mode 100644 txscript/data/taproot-ref/855137df77e723cfc86499f4fdb99f284ce7dfb2 create mode 100644 txscript/data/taproot-ref/857a099c2b46ccc02b866b3d0c0eb37858af7f6b create mode 100644 txscript/data/taproot-ref/857c4d2b4cbe976e614059e4d9eeb613c69a523b create mode 100644 txscript/data/taproot-ref/858fcb46fd11dfff505511ab32c43de93cb923ab create mode 100644 txscript/data/taproot-ref/8592c80000cf304bf52753ab309ceb04e2652ec5 create mode 100644 txscript/data/taproot-ref/859bf525139277f5088a3ce814f120ba25928ba7 create mode 100644 txscript/data/taproot-ref/85c3b1c5bc8469eb9f51ee2b19c514d2dcc9d4e5 create mode 100644 txscript/data/taproot-ref/85c9ddc38fbb85bd175bf3ac00a626752b964461 create mode 100644 txscript/data/taproot-ref/85cd37fe2c7301fdbdedfe4eee2559a27232c9e1 create mode 100644 txscript/data/taproot-ref/85db7ff2b922cfebbf367553f67005a39f7c7481 create mode 100644 txscript/data/taproot-ref/85f392952d2f71a976ea2c35e174e534ade34805 create mode 100644 txscript/data/taproot-ref/863c74afe345aa2460edf06abd9aa101ade521bf create mode 100644 txscript/data/taproot-ref/8641c37d6051843e6ca2af00b13ec220650722d5 create mode 100644 txscript/data/taproot-ref/86808a5b2f495881fed3418379a96faec86f72a3 create mode 100644 txscript/data/taproot-ref/869a1712bd79edfc9d95461a25217f1b4b203e29 create mode 100644 txscript/data/taproot-ref/869e9e9fd462fca683f8b432da94616198c8eb41 create mode 100644 txscript/data/taproot-ref/86e9313b4a88cc4785b502796f36bd97f1174856 create mode 100644 txscript/data/taproot-ref/871647145b6c79309648164fe2e9294d7ba23b0b create mode 100644 txscript/data/taproot-ref/871b6052e7f9a98779e47518bd5f8bf607a0e268 create mode 100644 txscript/data/taproot-ref/87360adcbd85bcb0816fa5f993fc9a5e14182074 create mode 100644 txscript/data/taproot-ref/874116a3fba0e5b88378c9825e5b2cd8fe9707c6 create mode 100644 txscript/data/taproot-ref/874498dbd2d21fb6b01edf60814088feb89dc02e create mode 100644 txscript/data/taproot-ref/874b8f129a3df7a4c057a29c6d71bfa99137ed88 create mode 100644 txscript/data/taproot-ref/874c302461e364f71a8f6570728f98611a5c96ce create mode 100644 txscript/data/taproot-ref/8753f414b84b9ccd0c62553961f88f7c0264c379 create mode 100644 txscript/data/taproot-ref/8768655b2d8b6e0cca092c104735354aee0c9b0a create mode 100644 txscript/data/taproot-ref/87d794de1dead52b89760fa5e136596c5b59bc40 create mode 100644 txscript/data/taproot-ref/87dcc971a3beea2e91a4d7e9643a5539ff94d52f create mode 100644 txscript/data/taproot-ref/87e1e382d129600c7e7f842f983fa6e87de06c9c create mode 100644 txscript/data/taproot-ref/87f0c2e540270b3692ef13bc2b91234c893bea37 create mode 100644 txscript/data/taproot-ref/87f8602bd7dcfb5af1052f424e7403550ff631de create mode 100644 txscript/data/taproot-ref/87ffa0846cd9a6bebb41a9d3d719ba376c69285f create mode 100644 txscript/data/taproot-ref/880f03671efb6dcc3f3fdaae9491625f46f6e4ac create mode 100644 txscript/data/taproot-ref/8829fdc647553393e0d223a098067bdf44dd2c3e create mode 100644 txscript/data/taproot-ref/882c32949367f4f504b543399fa13b4f4118344d create mode 100644 txscript/data/taproot-ref/884b9c73958e305260b7aa5b9969660166f550c3 create mode 100644 txscript/data/taproot-ref/885db56c9eb82324c5a0f7e7aebd3d215505a5d3 create mode 100644 txscript/data/taproot-ref/88684adb319365b522f644e785033cac77380e06 create mode 100644 txscript/data/taproot-ref/88797c1357072ec5f6d7a77f8f554fdf14935742 create mode 100644 txscript/data/taproot-ref/88d3c033edc04d341651610ce654caab89f0c589 create mode 100644 txscript/data/taproot-ref/88e2041ce84c5a5fd2b056669856844691b520a5 create mode 100644 txscript/data/taproot-ref/88e2266275388545e1f8f54b8fdbe89bbac43274 create mode 100644 txscript/data/taproot-ref/88ec99f421c2381e497fe2fc13b4f6dd8e8786d1 create mode 100644 txscript/data/taproot-ref/88f24d3d0ee361f07b6a968b39726f1326ec9166 create mode 100644 txscript/data/taproot-ref/89063488083093835287b1f9c18b2a7944664176 create mode 100644 txscript/data/taproot-ref/892cc3023c1245c75dd88475a0e49fe4d5063dd9 create mode 100644 txscript/data/taproot-ref/8951f7b39335a2e501908ed76548372ea5979b19 create mode 100644 txscript/data/taproot-ref/895da8e67657010ab55eddf2b5e50156498f59c1 create mode 100644 txscript/data/taproot-ref/89843a3d7b0d8895dac3541e10e30e0400dc0f5e create mode 100644 txscript/data/taproot-ref/899da8e446fd56d043e8d9fbd5821c09500c8654 create mode 100644 txscript/data/taproot-ref/89c130024a3230c8800c10efba7110244146ea67 create mode 100644 txscript/data/taproot-ref/89d3b93983fbc2ea121d1407d7944b74f44c67ae create mode 100644 txscript/data/taproot-ref/89db7a1ad6220b1635de9734c32a76ab69bb70e3 create mode 100644 txscript/data/taproot-ref/89df1562d15e81161f4c47827c0802d44a116dcd create mode 100644 txscript/data/taproot-ref/89e008ea516ef46108ee4b85055e4cba034e75c2 create mode 100644 txscript/data/taproot-ref/89fa19afc7b932f3749a095009d1bf1c6162c607 create mode 100644 txscript/data/taproot-ref/8a0a41ec1bffbaf105b7b5b3784d680d00446960 create mode 100644 txscript/data/taproot-ref/8a0ad7fc3cf79a721233622b6ae7a4bfc52c228a create mode 100644 txscript/data/taproot-ref/8a2775fc1b4fdf627698087dbc89fc1a3b0943be create mode 100644 txscript/data/taproot-ref/8a289fe11f09a8013015d4bdd383c4d26de1f483 create mode 100644 txscript/data/taproot-ref/8a29d68c4034560207bd08a36c47e26953bebe3f create mode 100644 txscript/data/taproot-ref/8a3477e0575b2a93269f750c0395201cd0f19a37 create mode 100644 txscript/data/taproot-ref/8a3c9306c70ceb610d6f1f738df6679eabff4238 create mode 100644 txscript/data/taproot-ref/8a52da0771f3d868955501e901d2540538f4d521 create mode 100644 txscript/data/taproot-ref/8a7bd56f4854fd39ca2b9dac03cf4e4f92a1b93d create mode 100644 txscript/data/taproot-ref/8a8928f98f7dd800744cfcdbefeff96b97543b76 create mode 100644 txscript/data/taproot-ref/8a95cc474b746e69625f0fe8c262c07a37a82a7d create mode 100644 txscript/data/taproot-ref/8ab6f611cd721ca128cb8f5ea3078c1b431d5704 create mode 100644 txscript/data/taproot-ref/8abdd04f7c724f0a762d03fb6fb80e698280ae9c create mode 100644 txscript/data/taproot-ref/8b08333db48411d829619458a66585a39efcbb11 create mode 100644 txscript/data/taproot-ref/8b2cadafb5c90652623fe20f1da4fa65454b1764 create mode 100644 txscript/data/taproot-ref/8b379a5db43a90e8d77da62355f3ac86f95b1422 create mode 100644 txscript/data/taproot-ref/8b436810adfe76e9f0a84f1a2382284cefc4128a create mode 100644 txscript/data/taproot-ref/8b4a8862bbb6306cc7b4473bba476bcaf6383aee create mode 100644 txscript/data/taproot-ref/8b5c3d67f71726b53372b58a37b41fce4a30a5ac create mode 100644 txscript/data/taproot-ref/8b5c7dbd04ac3065bf6c8164f3068ebc910ddc30 create mode 100644 txscript/data/taproot-ref/8b714927de7515d6467407861bea2d1b6816f769 create mode 100644 txscript/data/taproot-ref/8b7781da37cae546b0800cc96db74dfb1988fa5d create mode 100644 txscript/data/taproot-ref/8b8235aeb63d5111ff81b6406893e2c114f3d163 create mode 100644 txscript/data/taproot-ref/8b926866858180ba6c9e1a87ace930fdf129b59b create mode 100644 txscript/data/taproot-ref/8b9de640b20beae0f41a3d88dacf8e7c8c00e4a9 create mode 100644 txscript/data/taproot-ref/8babec8da5a26469095793b097811d07f256a5e9 create mode 100644 txscript/data/taproot-ref/8c4cbb21d02e5d466fb2539022255760626149f2 create mode 100644 txscript/data/taproot-ref/8c504464b5b4239a47fd8d4b185c3e0e1b6c1af0 create mode 100644 txscript/data/taproot-ref/8c716ab740c917b4df170efbc22b4e47873d8e3d create mode 100644 txscript/data/taproot-ref/8c7dc16b0e4c9ef242cc7ca7264ea3a4cb62a9bd create mode 100644 txscript/data/taproot-ref/8c87d28e9f82d8cb2da362853cbfd7f6ed73becd create mode 100644 txscript/data/taproot-ref/8cac7b8d77d23a0085a03a673ee2021520fbabea create mode 100644 txscript/data/taproot-ref/8cd544fbd46d49e76648955888fc3047bf5e24bc create mode 100644 txscript/data/taproot-ref/8cde25f4590bc7a0cb88896228ad8d28ecb9641a create mode 100644 txscript/data/taproot-ref/8cf7c389a03e6d9d8cdd4dc0ee8615f54cccd395 create mode 100644 txscript/data/taproot-ref/8cfbcd30e59e458884ca65687215ef8a39fa420b create mode 100644 txscript/data/taproot-ref/8d2e1d4e20c8a37b8483b0636a53106414b2e098 create mode 100644 txscript/data/taproot-ref/8d84c17e2d2a5f1b483ec417d4084cff8a83bd8b create mode 100644 txscript/data/taproot-ref/8dad5eca9780e98722de60bdf4209e99730b7ce0 create mode 100644 txscript/data/taproot-ref/8db878b9f4d8758552ba375e70b1c319d8ca0248 create mode 100644 txscript/data/taproot-ref/8dceab2924460f1a418835afa3ff5d4bde00914a create mode 100644 txscript/data/taproot-ref/8dd1413b2a30d480170c4918b00b9b7abe7ae2c6 create mode 100644 txscript/data/taproot-ref/8de4d54ede6f78c61866173f8b1096d7f5e3f478 create mode 100644 txscript/data/taproot-ref/8e0a71d16611cdac906bb4dece9fbf87d1a0fc8b create mode 100644 txscript/data/taproot-ref/8e1a1f4379046e33058d6b3df5184a181b98a2b5 create mode 100644 txscript/data/taproot-ref/8e38afa0e7c920bbb4aec155f70d1940028204ee create mode 100644 txscript/data/taproot-ref/8ea1e2b4445b668065a333641c17f3c6038f2f27 create mode 100644 txscript/data/taproot-ref/8eb143cfc057b1ffa8e90069a1d1ff91a90ac794 create mode 100644 txscript/data/taproot-ref/8ebc6173196e2c3ad4ea6d665b4893fd67690d70 create mode 100644 txscript/data/taproot-ref/8ee6b6a7957bf8ed03aa4b95dbc232e5ba56ead5 create mode 100644 txscript/data/taproot-ref/8ef96afc00349b4248ec31f4755d1020b7fdda03 create mode 100644 txscript/data/taproot-ref/8f07475a5f9d43a948b3b96452aea50918e4b9b7 create mode 100644 txscript/data/taproot-ref/8f0862b153c849b8d035fa189f7ec654f8b3e862 create mode 100644 txscript/data/taproot-ref/8f0aa9d861c14d5c32d60092ba04c2253666c4c5 create mode 100644 txscript/data/taproot-ref/8f4ba01ca74a466747b89a116a26047e58536ef9 create mode 100644 txscript/data/taproot-ref/8f56d7ddb9c736b9c89113453c379ec0a21341f9 create mode 100644 txscript/data/taproot-ref/8f7ed4f89eb5a042d9a19a78e61c47e5c984a9fa create mode 100644 txscript/data/taproot-ref/8f94c8c6a37bcc91d7a39416023f9d78ff08129a create mode 100644 txscript/data/taproot-ref/8fc0dcb82f3f88e6c20e123adddbce9afa79dd7e create mode 100644 txscript/data/taproot-ref/901261518c53841cdeb55041f748183f25fbdb6f create mode 100644 txscript/data/taproot-ref/9014cd1a175ea66532264c818ac4692ed805357f create mode 100644 txscript/data/taproot-ref/902fc67f6a0dd7c17809ac0002972da218f32b8c create mode 100644 txscript/data/taproot-ref/90439abb1bce7df95926ac69fbe35e9a75849704 create mode 100644 txscript/data/taproot-ref/906de10a0641d6cd4c0dd422fe885c2f9691128a create mode 100644 txscript/data/taproot-ref/9076f59736d1a417df0e4e53465ba7f80da49859 create mode 100644 txscript/data/taproot-ref/909f04b9af20cf2cb275ec1cf722f9a40b234fdf create mode 100644 txscript/data/taproot-ref/90b75e22907115340a987929a776f6f3bea1d9b5 create mode 100644 txscript/data/taproot-ref/90cddd59c8cf3bcac6b2fb6df29c9362c3a69855 create mode 100644 txscript/data/taproot-ref/90e012902ea03831fe652fb98c2f284c57217115 create mode 100644 txscript/data/taproot-ref/910480b0cfba5cfd886687f687f8a73d081c0b15 create mode 100644 txscript/data/taproot-ref/9143eec00e7c0dcba52a44c54c7fea4ca90ac9db create mode 100644 txscript/data/taproot-ref/914d626c074a269b3a9d1451d77761c9b6e8db28 create mode 100644 txscript/data/taproot-ref/91b3598a2ceedd0e45722fd9287672a13bf221e1 create mode 100644 txscript/data/taproot-ref/91deadec3dc6c425ddc903b195066184526341bb create mode 100644 txscript/data/taproot-ref/91eb11de4a9b1c364da7e342da879d0915930da6 create mode 100644 txscript/data/taproot-ref/91ed8c8f6952e9dfd27a3d45454432bd4886c8d1 create mode 100644 txscript/data/taproot-ref/91f11c0a3851e5a1b473cfd412ff28fcd7903c39 create mode 100644 txscript/data/taproot-ref/91f5456cb58ea9371b0fc9864e05767c7a8ee7e4 create mode 100644 txscript/data/taproot-ref/921d11cbd9a6ba01c1bbfcc40c1205f6ef275acb create mode 100644 txscript/data/taproot-ref/9238fc472251c9a3c817ab6cc5ea4e97c3d05410 create mode 100644 txscript/data/taproot-ref/9250a8a685e1f24b96edf202f1204a332bcb0ba3 create mode 100644 txscript/data/taproot-ref/9266cfa0d3adb02eaa15bc09db296fa853d6deed create mode 100644 txscript/data/taproot-ref/92848420c5779bd1c6d954bfc933383296c73c07 create mode 100644 txscript/data/taproot-ref/92886f1a44cabcf2e2c4dcef68ee37caa458c47b create mode 100644 txscript/data/taproot-ref/9289711f9cf1406a577387a27b8bd4930e29fd38 create mode 100644 txscript/data/taproot-ref/92bddaa4b62dfceaf980ba7a89bb0cc57e8fc52c create mode 100644 txscript/data/taproot-ref/92c132ca1fe8044c1317c18feaca645a54713ffb create mode 100644 txscript/data/taproot-ref/92e0a98f523af81899be75f9371608fd9948b337 create mode 100644 txscript/data/taproot-ref/9309be25161f4e02117ef32870ded9650d0e4f7a create mode 100644 txscript/data/taproot-ref/930d453e2c53ce2b64bd0f4b950552f988bdbc20 create mode 100644 txscript/data/taproot-ref/934c8ad33d4e9c5c13372bc93bf26cf3107839a5 create mode 100644 txscript/data/taproot-ref/935a6ed5b994d0bfdaf42bf6dd6fef4ccdbfee4a create mode 100644 txscript/data/taproot-ref/935dfd118a575d599a75b00db37955c92ef6471b create mode 100644 txscript/data/taproot-ref/936af0357943e249bd7e428753fc79b7870c4f96 create mode 100644 txscript/data/taproot-ref/937fe4be2d5689c59d7c617e65996d41cfafdef5 create mode 100644 txscript/data/taproot-ref/938f94084baf3b93faae268cc5e094df56f01f7a create mode 100644 txscript/data/taproot-ref/939a2a924292c7f549cc8f8be939826a3de6b820 create mode 100644 txscript/data/taproot-ref/93aa13626c3895c12d82d3763e8e916a16a4fd52 create mode 100644 txscript/data/taproot-ref/93c0123f1118e26a15aba5739d9f8db784f21efa create mode 100644 txscript/data/taproot-ref/93c6f793e89f2bbe200dcd083729e8e2af40c2f2 create mode 100644 txscript/data/taproot-ref/93c799f74d4e3a3b8dafa975cb2453af687a8872 create mode 100644 txscript/data/taproot-ref/93cedb385de6371ec85a3086d53c93ba0e1c6926 create mode 100644 txscript/data/taproot-ref/93d43e9d7f08eba5daa4d394a95703498c7e2139 create mode 100644 txscript/data/taproot-ref/93db6d7b5e262a03c9f6ccf71ef4e8de7acf6fb6 create mode 100644 txscript/data/taproot-ref/940254cd6f8f945bc5f1edcef83ba2afc7edfdef create mode 100644 txscript/data/taproot-ref/94136714739c4978945621f669ecaf025dff07f8 create mode 100644 txscript/data/taproot-ref/942302c74767926cf73be9bc6753fc422157855d create mode 100644 txscript/data/taproot-ref/94232b6796277453192019999be8b0fce849e3c3 create mode 100644 txscript/data/taproot-ref/944304c86610b738afbff55026632249b735f401 create mode 100644 txscript/data/taproot-ref/9447c6b9ffec17e55cc04961dec9cc9affec21dc create mode 100644 txscript/data/taproot-ref/94862fb03e48c18301c8d883c0b89da06351e369 create mode 100644 txscript/data/taproot-ref/948c81d5b83d1cdb3423d9e81a61becd8bf2a7bf create mode 100644 txscript/data/taproot-ref/9499a40681e896adc4c45047502a358ed7cf1237 create mode 100644 txscript/data/taproot-ref/94a9f7a609640945c820b281c9b05d992b0ac4c2 create mode 100644 txscript/data/taproot-ref/94f8b89ee92aa4c7d64eb59fa7c8811ee71c5de1 create mode 100644 txscript/data/taproot-ref/9506e2eb82ae6c5a245403a82c8c36c49e7dd19a create mode 100644 txscript/data/taproot-ref/9512c13d6e0d292adb68e6b0ed8f466ba396e30a create mode 100644 txscript/data/taproot-ref/95285e78757c883cf8644bfcd7749e4b08cb59c4 create mode 100644 txscript/data/taproot-ref/9528c094e6823258fc43686ee4fdc5d619021a94 create mode 100644 txscript/data/taproot-ref/95418ddbd4a17ea011fd39c57c1e4389b711dd7e create mode 100644 txscript/data/taproot-ref/954e0aead2f1448d168416547f795dc8baa7eb10 create mode 100644 txscript/data/taproot-ref/958966b97201943c2831502b3f5bbcccc2d1b2f3 create mode 100644 txscript/data/taproot-ref/95957430f0fd0b98963bf7080efffaa2efc45563 create mode 100644 txscript/data/taproot-ref/959b1c7bccd9efde5105f9deaa24262e6171f127 create mode 100644 txscript/data/taproot-ref/959ef5c1dfba6621fcd8365261b27885ba0eedfb create mode 100644 txscript/data/taproot-ref/95a04b0c50967b773d91751126d1ffe273287347 create mode 100644 txscript/data/taproot-ref/95afe9b1e8db35a5924aabbffc0a617e6862a1d3 create mode 100644 txscript/data/taproot-ref/95b65f78191ad63ba2149f216ad4b1f3a404ee82 create mode 100644 txscript/data/taproot-ref/95bc7b2db1ac665317576e24031e551189f4efe7 create mode 100644 txscript/data/taproot-ref/95da825d4132e9de80a280c89ba82724643b74f2 create mode 100644 txscript/data/taproot-ref/95e7d15b24fad0c2e4780004a45b735813a6d457 create mode 100644 txscript/data/taproot-ref/96089d3e37c85cc3e1727b58cbcd209157529a71 create mode 100644 txscript/data/taproot-ref/96197c6b417cdc946b9a34b57ac7c50feea0ada4 create mode 100644 txscript/data/taproot-ref/962bb09ab095bcd35f7f34055ed0fa8ae434af02 create mode 100644 txscript/data/taproot-ref/962d79802cab79d4bd0c5d840a5f94281465c290 create mode 100644 txscript/data/taproot-ref/966f41ea0609c64925ecaee5ba1af166ae43fdda create mode 100644 txscript/data/taproot-ref/96735cbde31cd1fbca452de029d3f77a7072dd87 create mode 100644 txscript/data/taproot-ref/967784fbda80e2586d2566b1d20422c209de8e3a create mode 100644 txscript/data/taproot-ref/968b512c074558ddde3b21c60e2886fd579c950b create mode 100644 txscript/data/taproot-ref/96a0422936b6ca5c4077e1e8fceea23c5dd146fe create mode 100644 txscript/data/taproot-ref/96aac36c65d79125e3ee07ec601f71c0c09b0cb2 create mode 100644 txscript/data/taproot-ref/96c1bbeb23affbc8ce9c5703062a448e21a42eeb create mode 100644 txscript/data/taproot-ref/96f5f4a5b64b8e8462a72eb1d259066fce9fbe2f create mode 100644 txscript/data/taproot-ref/9700352a9f17c39165256df2f2f7e4fa2ec9de61 create mode 100644 txscript/data/taproot-ref/9749e874bbbae2a0dce118ef7501ad135ea6cddc create mode 100644 txscript/data/taproot-ref/975509735c405d7f26b8bd4c00a32158c4f2911b create mode 100644 txscript/data/taproot-ref/976fab0e9af7ab44ebc738f13b377d23ab763465 create mode 100644 txscript/data/taproot-ref/97703896dfbc748c76753b9dc807252baa7d17ab create mode 100644 txscript/data/taproot-ref/978c3a312999502111000de7dfe47b35516164f4 create mode 100644 txscript/data/taproot-ref/97aba204ef02b37a3627221d61d8e55c8a4e1c89 create mode 100644 txscript/data/taproot-ref/97cc85297ae928c35b606a80f058ab18ea5187d1 create mode 100644 txscript/data/taproot-ref/97f61b6d98c9ffe5ca701f864969608db86c81fe create mode 100644 txscript/data/taproot-ref/982a43466eb400711eaa92486fd3a9b22d4ed22c create mode 100644 txscript/data/taproot-ref/984d407c9a0781d661b22c64ad915a555d3bf64d create mode 100644 txscript/data/taproot-ref/98500d46f789f6e67f2c3e2f6af290db2fc124cd create mode 100644 txscript/data/taproot-ref/9886f8415dd6095f89ff7e519af7516c9b7dc352 create mode 100644 txscript/data/taproot-ref/98bd202ec6667081b4a70e2f6b929af634ac6d68 create mode 100644 txscript/data/taproot-ref/98c6e09cd9cdc3967e01f4842102de38d4cda1a9 create mode 100644 txscript/data/taproot-ref/98c83bcdb5956bb94639dc29099871c76564d6bf create mode 100644 txscript/data/taproot-ref/98d122b2f88e6c5326c77b7a643d054909d0e33a create mode 100644 txscript/data/taproot-ref/98d39d50572a07ce2b34b997b11f0801efe034d0 create mode 100644 txscript/data/taproot-ref/98e6557609649d2edfa5303dc85da6929b3e46cb create mode 100644 txscript/data/taproot-ref/990480b357aeb905cfea6ff646718d101978e980 create mode 100644 txscript/data/taproot-ref/990924cc189ea41b110bc4dd575460c49374f23d create mode 100644 txscript/data/taproot-ref/99621f82461534b8907da50ed4c7020620244c46 create mode 100644 txscript/data/taproot-ref/996fd99ab96f9643d5e5713a831995b17e7a3d6a create mode 100644 txscript/data/taproot-ref/99d1d11e7c7797862b2f093aecd2482708213a46 create mode 100644 txscript/data/taproot-ref/99dec7b1a061c754594c315d70173856ee38ca53 create mode 100644 txscript/data/taproot-ref/99e6e3dc68bf0e9973d9cda82f1300e98c4d58a0 create mode 100644 txscript/data/taproot-ref/99e8319b516c140aa7badd1e9ef03d1ff1c3bee0 create mode 100644 txscript/data/taproot-ref/9a11c2fda7b9c43e2b7720bd72c00e2503c9dd88 create mode 100644 txscript/data/taproot-ref/9a309f12e7243094d23099f5433d19602252797b create mode 100644 txscript/data/taproot-ref/9a89b6f3139174829b27ab6ead21acbf001ee2be create mode 100644 txscript/data/taproot-ref/9abdf13e2635797e12d342e2dfb31a9c80d0edd9 create mode 100644 txscript/data/taproot-ref/9adf5a63b8158c84d6bc327d0b1ac1b5964a3ac4 create mode 100644 txscript/data/taproot-ref/9ae58507a65058e0fe31de871c7a34bab5415ae9 create mode 100644 txscript/data/taproot-ref/9aece0f0260af3664b7ed391226bcf127e9fd163 create mode 100644 txscript/data/taproot-ref/9af8af68c2f18bca7d94dd8b48ce8692c89ffb04 create mode 100644 txscript/data/taproot-ref/9afe6dae1af7cdc07ef615de0c3d2ebdd4f68c15 create mode 100644 txscript/data/taproot-ref/9b42d222b18945ea05823e8a6dbcb0d54a364700 create mode 100644 txscript/data/taproot-ref/9b4d35c34d31ab2b9e6a0becef710c9b00ec976c create mode 100644 txscript/data/taproot-ref/9b51c6d0b56ce78a3dd7924a0c74626beea4b529 create mode 100644 txscript/data/taproot-ref/9b62911307d4c57e65b67719613737ad5d45433f create mode 100644 txscript/data/taproot-ref/9ba6a6cf62c5826ffc6fcd084371c29d51f194c7 create mode 100644 txscript/data/taproot-ref/9baed9539fb0ad3446fb36b9804e562244aec18f create mode 100644 txscript/data/taproot-ref/9bb0ba96392a718e713162631e2036c2a0708ce2 create mode 100644 txscript/data/taproot-ref/9bb98651acde18815c952146548c472023a22072 create mode 100644 txscript/data/taproot-ref/9bbe3f1ede4caaf74b619e6e82cb6b6f779f366d create mode 100644 txscript/data/taproot-ref/9beb9170ecc8bc4e97002efea295cafc58d55688 create mode 100644 txscript/data/taproot-ref/9c1a6591aef6efd4346aa9f750f87940a9783107 create mode 100644 txscript/data/taproot-ref/9c3a7896381a924c326a82a884be65e632a9f190 create mode 100644 txscript/data/taproot-ref/9ce105ac118fb5187b993ba8e83d9b199dc86fe9 create mode 100644 txscript/data/taproot-ref/9ce973c4df052f54b32f61eb27b74cff377e6752 create mode 100644 txscript/data/taproot-ref/9cf29382585d7d87b68e19e5244cd47ddedf35c0 create mode 100644 txscript/data/taproot-ref/9cffb02f79fc72e41c0ac0b800b862fb39b0a7fd create mode 100644 txscript/data/taproot-ref/9d13b7a6b273e9242c1092d047290e60291087da create mode 100644 txscript/data/taproot-ref/9d2325335a737991316f3231a676fb415c357be8 create mode 100644 txscript/data/taproot-ref/9d3dab224014b620dde2b56cee3fec23463cb909 create mode 100644 txscript/data/taproot-ref/9d6211da7d3f0bda14d5067af27a1abd46dd187d create mode 100644 txscript/data/taproot-ref/9d6647e7af1e10de1b3c608d829400e5663b3d7e create mode 100644 txscript/data/taproot-ref/9d86f6cf43b5947de7d50f80fec0483a9072ee0a create mode 100644 txscript/data/taproot-ref/9d8bf71616bca5ac31e24117c80dad52352d5c2a create mode 100644 txscript/data/taproot-ref/9da24604599fa08b01181b48265429ebf1cb213a create mode 100644 txscript/data/taproot-ref/9db297bad5b8a7a06f76713a5b05cdf2148f3b19 create mode 100644 txscript/data/taproot-ref/9dc1141da1d44addec511e26f89d5046f97da2c6 create mode 100644 txscript/data/taproot-ref/9de0c2afad49fa532a8fea5e4dad68a5f1ab8a22 create mode 100644 txscript/data/taproot-ref/9de4c3db0a099c27c523988b4b750ce3ee2c0ffc create mode 100644 txscript/data/taproot-ref/9e080c9060b0017ebfc6f81bd854014a8fc88ee8 create mode 100644 txscript/data/taproot-ref/9e0885e261051e23c61d7b6859e9c25f16f9aa73 create mode 100644 txscript/data/taproot-ref/9e533595a0cd03757f4ce00ca1a54a38453f6274 create mode 100644 txscript/data/taproot-ref/9e7cd3ed8c99ea2f99c6c55da41e1a2e4c56fb9b create mode 100644 txscript/data/taproot-ref/9e94137b564120169fc22f85678cc20df3a1128c create mode 100644 txscript/data/taproot-ref/9ea50ae0758462d0e77fe1397a5af6f83ad15f39 create mode 100644 txscript/data/taproot-ref/9eafe1e70dda380dee958b8ae1138ab758f76857 create mode 100644 txscript/data/taproot-ref/9ee645ca92c85ae4515e7e01d35579bbc6cb046f create mode 100644 txscript/data/taproot-ref/9efceb8b8d6841f20ca0f194b19427087f5a97ea create mode 100644 txscript/data/taproot-ref/9f0427c58e85128c73cd97a9ba41519871d70331 create mode 100644 txscript/data/taproot-ref/9f07a530e3bc65a6d0a8da0a8ad697b5dc9ab202 create mode 100644 txscript/data/taproot-ref/9f0aaa42e73656b0fce8443aea84266d564470e9 create mode 100644 txscript/data/taproot-ref/9f1fe443098130f838ce7d5c1460cdc0f13bb12e create mode 100644 txscript/data/taproot-ref/9f282d2e013696b3d63d9269bf869f906bd8cef4 create mode 100644 txscript/data/taproot-ref/9f78e819952e56d7b1961320d611fdc489b34e51 create mode 100644 txscript/data/taproot-ref/9f9bfc59905231b990a2d55faaa21a4cf26c8781 create mode 100644 txscript/data/taproot-ref/9fd2c2accbc395448a7b5d7d8bcafd190ce329a7 create mode 100644 txscript/data/taproot-ref/9fda11dcb9654da892e82b6566c4aeab962c8278 create mode 100644 txscript/data/taproot-ref/9fe5d577717a9a11e4740f29f231fa15b9f4d01c create mode 100644 txscript/data/taproot-ref/a01b0232919914b0a33ff87262f8ba59543b0ab6 create mode 100644 txscript/data/taproot-ref/a027f0c1c564bf78407eed47f2a9f03c60eadc02 create mode 100644 txscript/data/taproot-ref/a0482c5ebc234aebacf836bed890b373827b5958 create mode 100644 txscript/data/taproot-ref/a04e38678141417445359665f17e2c444cc55835 create mode 100644 txscript/data/taproot-ref/a05131b921bd9d6b4ea47f249e51ee98efc05f54 create mode 100644 txscript/data/taproot-ref/a080874cf108744cedfbb712de9629eed229ec49 create mode 100644 txscript/data/taproot-ref/a086f46eaeca09d3649d592dc5a55044d8de1f41 create mode 100644 txscript/data/taproot-ref/a0951cc6042b25d64914d945c4e3758a0407ea87 create mode 100644 txscript/data/taproot-ref/a0c092d70e81d7131ac1cb03d9ac8db9d2c0709b create mode 100644 txscript/data/taproot-ref/a0d64b88f7e1a35f28c08292725d25214520f7a6 create mode 100644 txscript/data/taproot-ref/a1258cbda9cc624bb9f238882cc84253a1dc87c2 create mode 100644 txscript/data/taproot-ref/a1430a0798548b8c620d89157e6f2a54d9f94f2e create mode 100644 txscript/data/taproot-ref/a16835f468084695f51026fc26ce3f842fc97714 create mode 100644 txscript/data/taproot-ref/a17272e8d29e6c955e3b27761ff0e3908e202ff1 create mode 100644 txscript/data/taproot-ref/a175484c1508738494b7c85ab928bb65c4a07f42 create mode 100644 txscript/data/taproot-ref/a17a5140033f84e309aac8415b2a580b4050203c create mode 100644 txscript/data/taproot-ref/a1b572d1fe5a9c9111033297ae5ff70014c256ce create mode 100644 txscript/data/taproot-ref/a1e666afd74df95cb5c06318730dff9116d6a22f create mode 100644 txscript/data/taproot-ref/a1e97b7bd972796aecfd4b83180776a015f64a8e create mode 100644 txscript/data/taproot-ref/a2124d0d2b17ee1f1e0998338eea25cffadf437c create mode 100644 txscript/data/taproot-ref/a2135bcd7d491b07a72fbd501a3b0be1b9f3bdc2 create mode 100644 txscript/data/taproot-ref/a21f2d7b6393cda8bcff8df7034062e8925f6377 create mode 100644 txscript/data/taproot-ref/a2452fe77f45ef6a612ce676a6ad9d9002b9331e create mode 100644 txscript/data/taproot-ref/a25b4431040ecd4aca97dad2844cf0080a40800b create mode 100644 txscript/data/taproot-ref/a26f67d81684b9007a2109269de4afe49d23f938 create mode 100644 txscript/data/taproot-ref/a293d31bc0cff7b14f873a325579ef283c8e2068 create mode 100644 txscript/data/taproot-ref/a2a3d1e6a386b04424a390d174bdd394f0b88602 create mode 100644 txscript/data/taproot-ref/a2ad73830bfcdf027adbf16721e9d3b54303b060 create mode 100644 txscript/data/taproot-ref/a2c43c8aa3d41b7eab2ae20fb1f9e973802d902e create mode 100644 txscript/data/taproot-ref/a2c7ad1b00fd60ced001c83967d4fb945e86a28a create mode 100644 txscript/data/taproot-ref/a2ccb0337cf44bc0b3562bbf7dcdd792989d5faa create mode 100644 txscript/data/taproot-ref/a2f70a0c20b111ca1ab34de6f2319109527a564e create mode 100644 txscript/data/taproot-ref/a32041608e8afe0ca18b503f0e9c30cd1480f6e2 create mode 100644 txscript/data/taproot-ref/a32cec9ef7fd885815ad4d76f8a45026473405b3 create mode 100644 txscript/data/taproot-ref/a34ff67c5e9162f46fa22c082d21a7ac7a23c3a9 create mode 100644 txscript/data/taproot-ref/a3770de2569e6bc576e5a3947ac08e8bbe24cb5b create mode 100644 txscript/data/taproot-ref/a3823af6285ec27ac5824bddb591a1f209bc4018 create mode 100644 txscript/data/taproot-ref/a38819d7d0147d7cfd3e537fe3756def5a12274d create mode 100644 txscript/data/taproot-ref/a3ad36fa2c2c376afbf409d8fb83e076d6d87bac create mode 100644 txscript/data/taproot-ref/a3af8000afdeacd1c3d6137959029e3b260c72ad create mode 100644 txscript/data/taproot-ref/a3b21dcd0e4adb6a0ef920d74555d2f699917d39 create mode 100644 txscript/data/taproot-ref/a3ce74eabac11a8d8a11955afa3ad09d86b22961 create mode 100644 txscript/data/taproot-ref/a3d08eda208b96260cb5b47c1478e155264ff8c1 create mode 100644 txscript/data/taproot-ref/a3e5f143cabf7cdb1f6111fd744b4230796b6064 create mode 100644 txscript/data/taproot-ref/a42eb9002c5144273a55bdd736db4fde19aee488 create mode 100644 txscript/data/taproot-ref/a446bc4e40187735edce2ecd8fcd0e7ed43952ee create mode 100644 txscript/data/taproot-ref/a45d7d60a1eef620afd536f4d69cd4196a0fa6e8 create mode 100644 txscript/data/taproot-ref/a460475c32082067af4eb3aca7203a69381aec6f create mode 100644 txscript/data/taproot-ref/a47eeeeb9c724e0247b882207d4598df2b1f9db0 create mode 100644 txscript/data/taproot-ref/a4b22b3869f32433a3caeafcc3e2dd92c010757d create mode 100644 txscript/data/taproot-ref/a4b538f21947ef1c76087aab101911f7a2cd4ab0 create mode 100644 txscript/data/taproot-ref/a4bb5997e547796263c8fda8ffb4c87967e2ea43 create mode 100644 txscript/data/taproot-ref/a4c0daa47b25c77cdc37c485b2ddaf4db6edaac6 create mode 100644 txscript/data/taproot-ref/a4d7bdb95ff0421ff9f027700815f81ebac50d03 create mode 100644 txscript/data/taproot-ref/a4e49ce4052c6a3e72232ff2f764b972159ce65e create mode 100644 txscript/data/taproot-ref/a4e87c35b253e9246a0bd98cbe936ecccbf2d89a create mode 100644 txscript/data/taproot-ref/a4e89f79f42904ee1b600ddd79f2d3e27c855da0 create mode 100644 txscript/data/taproot-ref/a4f449044130b59be750db18b3dd9cfd3bae5588 create mode 100644 txscript/data/taproot-ref/a4f68b87043e04396cfebc9287c9d7280448eacb create mode 100644 txscript/data/taproot-ref/a4faeb187eb7094b39e0f0699026cacbbb9d2ea7 create mode 100644 txscript/data/taproot-ref/a4fb1b9f52700ffd6bf24f06e73666810b0e3260 create mode 100644 txscript/data/taproot-ref/a506dd32985fc68730bdda9ec17bd68456455ba2 create mode 100644 txscript/data/taproot-ref/a51dfad994645830ec06457aa99a3680c881234f create mode 100644 txscript/data/taproot-ref/a52cb7e463be1bd639929b2d3988c313fb4189b5 create mode 100644 txscript/data/taproot-ref/a545cc27e2d474a7a7b7ae974d6c61935d3bdfb6 create mode 100644 txscript/data/taproot-ref/a547e004e80194fef36be8b3932bb2a42502c7b9 create mode 100644 txscript/data/taproot-ref/a54e57e8c7e474bf56e54f46813916ef373a9d88 create mode 100644 txscript/data/taproot-ref/a56763f3af3e1d367ff0097d69c129ed4bae7f00 create mode 100644 txscript/data/taproot-ref/a5706ef86f9f5e79c7eb3a0ed8168f28bdc25f87 create mode 100644 txscript/data/taproot-ref/a574eeebf64538810c2a45c5864f3209361e1c96 create mode 100644 txscript/data/taproot-ref/a59cd78a997d502a498c2b597cda9c8cb9b435e4 create mode 100644 txscript/data/taproot-ref/a5aaae5e5cc3955871ba97a7c41d307fef2b72eb create mode 100644 txscript/data/taproot-ref/a5ace5adf4a44f04399e15b18f44e6a83e13b549 create mode 100644 txscript/data/taproot-ref/a5b907c867904b2e2631128c5f637988bef1282b create mode 100644 txscript/data/taproot-ref/a5c7d3a86b0f7fd48476aea167e188ad2e930dac create mode 100644 txscript/data/taproot-ref/a5ccdd516198da910321185e29de6f20d9be2985 create mode 100644 txscript/data/taproot-ref/a5d4903bde9105b510f48ef3783702f402c38289 create mode 100644 txscript/data/taproot-ref/a5f0f80d6202449807c3c23b59496812943f4d12 create mode 100644 txscript/data/taproot-ref/a610da0c9997c31b63719e6fe71e9b82d48595ec create mode 100644 txscript/data/taproot-ref/a63c8dad9a5b7049824ad507266f11ef32fef7c3 create mode 100644 txscript/data/taproot-ref/a65e2a892ee1771cf4861f2c1bc2d5f505645c14 create mode 100644 txscript/data/taproot-ref/a66d01f6351976b51603542719f7e00648878dc0 create mode 100644 txscript/data/taproot-ref/a686f07063eda38bb50a12b8bff95eb203e492e2 create mode 100644 txscript/data/taproot-ref/a6932b59aafceeb75607a7b5c0b5d93b3f2e17dc create mode 100644 txscript/data/taproot-ref/a6b7a9259b013c7a8613e1a5291dff6a4c46e85d create mode 100644 txscript/data/taproot-ref/a6ba23753e57cd1a1f2d7e37472e4679a0f113a7 create mode 100644 txscript/data/taproot-ref/a6c5d8b49fda54f8534027bba1269af6af46da1f create mode 100644 txscript/data/taproot-ref/a6ccf2fabae7c6419459beefef87fd1e78fb2d4f create mode 100644 txscript/data/taproot-ref/a6f23c5bb6dad507a24fea1ceecc0df2a026481c create mode 100644 txscript/data/taproot-ref/a708a2f8ec818a38ec29e17b587179a32b43d704 create mode 100644 txscript/data/taproot-ref/a70da8709e12ffb27292ce7290967a40c89cf126 create mode 100644 txscript/data/taproot-ref/a72f0993c4460fa269fecd7c19909f1a8f319d4a create mode 100644 txscript/data/taproot-ref/a732f61f7a104110a42397e2f2bcff054f17f50d create mode 100644 txscript/data/taproot-ref/a736014c5e879818948ab14c8851770efe5d5fbb create mode 100644 txscript/data/taproot-ref/a73a44e1dbbda1a5482aab336034e0f3b2631b86 create mode 100644 txscript/data/taproot-ref/a742d0a1cc22ae97a4d67dae7649bce1710b89db create mode 100644 txscript/data/taproot-ref/a758aa7b471d865a094148a124f948d84c1137bd create mode 100644 txscript/data/taproot-ref/a76b07ca76b8129996817bda9c15cfe6c801c496 create mode 100644 txscript/data/taproot-ref/a777b3aa2b4eb6ca1a87d04550c620145fe1fd1d create mode 100644 txscript/data/taproot-ref/a78c1ce484d2b06f18054390abe8ba3738befc47 create mode 100644 txscript/data/taproot-ref/a7ca771886a4f3f8ef1274e272ed3b75f1c52957 create mode 100644 txscript/data/taproot-ref/a7d8752018d8cded7995daa9e4cd387a0f75eafc create mode 100644 txscript/data/taproot-ref/a7edc21f3d053cf490a4f0032887dd77602ce962 create mode 100644 txscript/data/taproot-ref/a80117d2623452c4c4d047ad5ffdcd2cfd707957 create mode 100644 txscript/data/taproot-ref/a814c0230632e5c08f097102f2033615293348b7 create mode 100644 txscript/data/taproot-ref/a83603464a89b1ff53b86c47af7c54b0f8a72405 create mode 100644 txscript/data/taproot-ref/a858130542274ac050eecd7df40f62a22f2af3e5 create mode 100644 txscript/data/taproot-ref/a87851edeb5a5db0f65fd04d5730500bf77c3e76 create mode 100644 txscript/data/taproot-ref/a8a3b52078ade562edb5a7dc6ab61ce4b3cca2ab create mode 100644 txscript/data/taproot-ref/a8b03c8e24ef968616c561f18edd3944caccbc5f create mode 100644 txscript/data/taproot-ref/a8b6c76ee96d3aab811609a8979cfcc67cff79c6 create mode 100644 txscript/data/taproot-ref/a8cd8ebe1c92a5ce01cb9d553c32988d450e82c9 create mode 100644 txscript/data/taproot-ref/a8f6f74ddb0e0e8e8361ea297e0abac830cc1dfd create mode 100644 txscript/data/taproot-ref/a912b73ec5ce6f1628bcb8d8e2dca4f96fb71c5a create mode 100644 txscript/data/taproot-ref/a91984528078da07c39af230d966ecfa33124d9d create mode 100644 txscript/data/taproot-ref/a98e2c1c0077687fbc9166f61a386e4a7023ae4f create mode 100644 txscript/data/taproot-ref/a99032acc713604176f8d95263865e2c6dd015fe create mode 100644 txscript/data/taproot-ref/a9b04af95ae95e9a60941ab351fb387c007938a2 create mode 100644 txscript/data/taproot-ref/a9b58c8a3ebf4f2c3c8af6242b20c43aa733d6c5 create mode 100644 txscript/data/taproot-ref/a9b81c4e5e52ddeed6c3bb9ecb2f67d7e056eb1f create mode 100644 txscript/data/taproot-ref/aa0024897deb20273f4fad0f856967621953d402 create mode 100644 txscript/data/taproot-ref/aa0d4dde043c88d76ca0b51949f90e102187198f create mode 100644 txscript/data/taproot-ref/aa17922f64ff7cd6d4aeb56bfab8af47218a86d1 create mode 100644 txscript/data/taproot-ref/aa376ce844fe5f3d69f1047c99cbef99e732dbdd create mode 100644 txscript/data/taproot-ref/aa471973e1dc517ae959d5706167622da05bab46 create mode 100644 txscript/data/taproot-ref/aa56f625476b200e65ada22557c871b0993ff86e create mode 100644 txscript/data/taproot-ref/aa76c2e6c5a061d0580802966b8efb8804164d68 create mode 100644 txscript/data/taproot-ref/aa8eac8fb7ebd4e613d8bdbce660665b3f45fa66 create mode 100644 txscript/data/taproot-ref/aaa6693d92f9027513267fd416bd6201171873ac create mode 100644 txscript/data/taproot-ref/aab859864bc25e0a7b430273941b291f2b765ba7 create mode 100644 txscript/data/taproot-ref/ab1a9283d7a85a42aff52d1937193ca27a794187 create mode 100644 txscript/data/taproot-ref/ab3899ee5c2ed560ae6beb77e71e4950fc17aab3 create mode 100644 txscript/data/taproot-ref/ab3bd8d93632f274ea33e6bac92fec9215c4f20f create mode 100644 txscript/data/taproot-ref/ab3f300e2417c10f0eedeee88f719e82892e53a2 create mode 100644 txscript/data/taproot-ref/ab5267db0c03e93e08f51b597821900db93ae75c create mode 100644 txscript/data/taproot-ref/ab8bd300852ee0d05f0c8d476f4205347466c6e3 create mode 100644 txscript/data/taproot-ref/ab8ffe370320d075a8c7b9daefaf545d29b7ac1b create mode 100644 txscript/data/taproot-ref/ab9b4c72f3a16b2e16d40652ec33ca2a8ee4d3ef create mode 100644 txscript/data/taproot-ref/ab9c711cf8bbafb6cdfd30f945bfcb03cf0272b6 create mode 100644 txscript/data/taproot-ref/ac0b35cbd93f63ed7452d6acebde72ca9fcc3d81 create mode 100644 txscript/data/taproot-ref/ac2088d883a0a84ac9d499824adcbd32f90b53c8 create mode 100644 txscript/data/taproot-ref/ac3cd67c26d777875eeebe2e90c716e8bd592ff4 create mode 100644 txscript/data/taproot-ref/ac93b3ca2d9c1ec6e07725af461ea07bb19c4dee create mode 100644 txscript/data/taproot-ref/acef576be556d6720814253fa450ffd2684c3c7b create mode 100644 txscript/data/taproot-ref/acf314897698e9e208634f10df880184d9a7754d create mode 100644 txscript/data/taproot-ref/ad1589197b44cb0c659b26869de6c66b103e9682 create mode 100644 txscript/data/taproot-ref/ad16650f9e472fb459eb487a9f883c894760b565 create mode 100644 txscript/data/taproot-ref/ad382a856cee976ed155aa5fae9828cd059ccb26 create mode 100644 txscript/data/taproot-ref/ad4069abc0712cf1f3c8508b699379282bbf556a create mode 100644 txscript/data/taproot-ref/ad58a3216af0b6f002972233963f6be39c7aee60 create mode 100644 txscript/data/taproot-ref/ad67e4cfbdacd913d6561d8fe08f456a4341a88b create mode 100644 txscript/data/taproot-ref/ad705acdd20e8da3a2171681cbf04df9fa98a3f7 create mode 100644 txscript/data/taproot-ref/ad8af6e7441c7a1e3628b69f1ca22b74068a2278 create mode 100644 txscript/data/taproot-ref/ad9cdf2ad4d35e3f1e5279c581d0394ae2aa6972 create mode 100644 txscript/data/taproot-ref/ada6178e8321efd51626a855bc6e5557d68ca3fa create mode 100644 txscript/data/taproot-ref/add98ecf3dbbc875a84ca24db0f18c054af38335 create mode 100644 txscript/data/taproot-ref/ade2c248d7512985cd0840191f643e986e49db2e create mode 100644 txscript/data/taproot-ref/aded7ddfdd7ffa25f49bad4502033ca4a8591786 create mode 100644 txscript/data/taproot-ref/adf617416382c5deb595144ff94dce09117c3181 create mode 100644 txscript/data/taproot-ref/adfe9ae4df4e249a66eb91fd2f8b26ee063e6f76 create mode 100644 txscript/data/taproot-ref/ae32aa63248b35fca6503c67fb4fd2acf15a98ad create mode 100644 txscript/data/taproot-ref/ae87ecd86f7053ab8d71a8f1fc84c2d2c62b472b create mode 100644 txscript/data/taproot-ref/ae887143b966f102e6e5967f76ea3c041af92e65 create mode 100644 txscript/data/taproot-ref/aea2776fad1a4341ceaff3aa6cf21d9c37587a96 create mode 100644 txscript/data/taproot-ref/aeabf0753dee7e4de87a4ffe6e1414931333b32a create mode 100644 txscript/data/taproot-ref/aeaf78544ff09661df34acf0ab140ca8f6834d93 create mode 100644 txscript/data/taproot-ref/aeb2510aa3d77a9c6dcf533982e3925d74a03591 create mode 100644 txscript/data/taproot-ref/af3246dfb5ebe1bed3d537e239a99af7422239e7 create mode 100644 txscript/data/taproot-ref/af39e152ec29cf6ef9124bc09c621887cea05402 create mode 100644 txscript/data/taproot-ref/af4d15714a467c338537aaa00108e2bee33e8426 create mode 100644 txscript/data/taproot-ref/af58cb52355f4201682a37056445b679070634b3 create mode 100644 txscript/data/taproot-ref/af5fe2e1f2c809eb47dbe26c8a45e6a55718cce6 create mode 100644 txscript/data/taproot-ref/af7648fbe02efa3d9188b9b61ce6422012612477 create mode 100644 txscript/data/taproot-ref/afa5c3718b0a518cee419488c60f2f2741ba28ff create mode 100644 txscript/data/taproot-ref/afb161887b4215368f593a2d8d8b6bc32170698d create mode 100644 txscript/data/taproot-ref/afb93dea86c318802ea31536847bc3786c8bb47c create mode 100644 txscript/data/taproot-ref/afcc94478400491055613ccd42f75d4fa9c1ceab create mode 100644 txscript/data/taproot-ref/afea0adf1a155b6acd7f6a1aac9dcfd781f953f1 create mode 100644 txscript/data/taproot-ref/b0225ebc20fa76a5b5efb83881756503681565fa create mode 100644 txscript/data/taproot-ref/b02921b398ef06202f6f3b3f652c3c8f10888607 create mode 100644 txscript/data/taproot-ref/b068dde987664207f704c5b73a6444bd16d46da8 create mode 100644 txscript/data/taproot-ref/b06a48e5c2bc5a6b1fc1fec7273e5642a15c8c13 create mode 100644 txscript/data/taproot-ref/b075dfb300337efeb5bdabad39fff800ee516fa3 create mode 100644 txscript/data/taproot-ref/b085cb29b4ab162f71d870e1b8f890fd0cf23cd6 create mode 100644 txscript/data/taproot-ref/b08ac583665d8a49691a3a09c1d5cc1ee3b8a416 create mode 100644 txscript/data/taproot-ref/b0a4831326c413d2804c49788050b9f91a6403f7 create mode 100644 txscript/data/taproot-ref/b0ad1929e6a50924bb0dc2de48e23ed645f857f7 create mode 100644 txscript/data/taproot-ref/b0c00b0f653fb7d6d9c6d10a355b006e90bfdefd create mode 100644 txscript/data/taproot-ref/b0c6d5f594246c874ab683269116303a280482fe create mode 100644 txscript/data/taproot-ref/b0c73ceab30b62cfa56f40cdfd49c1ce58f55a01 create mode 100644 txscript/data/taproot-ref/b0d9006bd4700ed6403142773e914c7bb257d345 create mode 100644 txscript/data/taproot-ref/b0e3df60a56490ae4dccf3851d020b40b21b8b7b create mode 100644 txscript/data/taproot-ref/b0ec063bde9113e41cd5590763cc5a80a27e57df create mode 100644 txscript/data/taproot-ref/b105a50748888b6356015fc47a88bc2be5715d6d create mode 100644 txscript/data/taproot-ref/b14851f777181f4d6991a19eb5faf986f6c5d922 create mode 100644 txscript/data/taproot-ref/b16c3acf4e0fdb0086f5e645c0abf5248401f236 create mode 100644 txscript/data/taproot-ref/b1776090f6173a9a430ec315e3ed5aabd24b1b72 create mode 100644 txscript/data/taproot-ref/b1a7636cf60adfde2e1358221f019b1e6b4155d6 create mode 100644 txscript/data/taproot-ref/b1ad5a93a73ac48400168c0d0d6867c722e2ee94 create mode 100644 txscript/data/taproot-ref/b1b4eed63248ce097e83d9f1723c6762b7de9c27 create mode 100644 txscript/data/taproot-ref/b1bf9f8b4545db1b4c96961e0e20f15216c0e8b5 create mode 100644 txscript/data/taproot-ref/b1c08a839cd0acb873c5f79044f09ba166bfa26d create mode 100644 txscript/data/taproot-ref/b1d288dfd536ad13a01041e19c9c11fead33ff91 create mode 100644 txscript/data/taproot-ref/b1e426a1d9ca218fe8dfbd94e4f84deb69cf3add create mode 100644 txscript/data/taproot-ref/b21f2a634774a50314c4e0ef19018373cfff5761 create mode 100644 txscript/data/taproot-ref/b25b243c1918bd286e71165a606917ad6566dcb9 create mode 100644 txscript/data/taproot-ref/b279bf9258b4c48220f05e2e891b91c7b13e0572 create mode 100644 txscript/data/taproot-ref/b2bf386739903299a1cce995ba58544747eee3f9 create mode 100644 txscript/data/taproot-ref/b34497bedf19b0567d48c3bb9d3c6c6b7285bf56 create mode 100644 txscript/data/taproot-ref/b354cb571d5964e5709107acf8b69b7a52691648 create mode 100644 txscript/data/taproot-ref/b3621ec700f1905ab8a89bd0dc990c56dc5b2619 create mode 100644 txscript/data/taproot-ref/b36fa07023f7e2c301fca71c92d63d4b9d3dbfe8 create mode 100644 txscript/data/taproot-ref/b3acffc7854d876acec4be4e8f02c5785c9786cc create mode 100644 txscript/data/taproot-ref/b3b35af21b57765c4439d83505e2c122bcd9d159 create mode 100644 txscript/data/taproot-ref/b3e2b23acbebfcbc2e5f4e54d4fd7005740cae7f create mode 100644 txscript/data/taproot-ref/b3f7745d61088bde2d2244a961085a6e8ca22a22 create mode 100644 txscript/data/taproot-ref/b3fb8896212c7278ddd055ebe8806a9aadfbdbf4 create mode 100644 txscript/data/taproot-ref/b42a78220d5bf6c02b4d64f379b4963da854ecf8 create mode 100644 txscript/data/taproot-ref/b471b7933c10f89f075ebd244fc7dce18cc064ec create mode 100644 txscript/data/taproot-ref/b4881b1ab0b628b8e08950b8799b2a7b2f90f6bb create mode 100644 txscript/data/taproot-ref/b4b0e6e8de840a729657842fc3f326a51926695a create mode 100644 txscript/data/taproot-ref/b4c0e993f516711b0d2941c1993f065eee0512a5 create mode 100644 txscript/data/taproot-ref/b4d27baa0c7f4d587689db8a9529b71fa55341ec create mode 100644 txscript/data/taproot-ref/b535e18acfb42d8eca463e3d005649eeec97a029 create mode 100644 txscript/data/taproot-ref/b537477b73545075fe86dcab51eee08a1eff1f93 create mode 100644 txscript/data/taproot-ref/b545791a846adc504218666c3218bfaa83bc90d2 create mode 100644 txscript/data/taproot-ref/b56d0867bbc5b009c7f592e99f5d598f728cda80 create mode 100644 txscript/data/taproot-ref/b571a84a7a61d25a217f263add5e84836c981aad create mode 100644 txscript/data/taproot-ref/b592aa01c9d16fda0673296c91e16d85378ef308 create mode 100644 txscript/data/taproot-ref/b594302e03843a9f9c9551e5065d334f5788b18f create mode 100644 txscript/data/taproot-ref/b5c23ef36f914bfe6734a376e3ff23afa4056cdf create mode 100644 txscript/data/taproot-ref/b5f858c267b5596e80a4ca9e1d9d9fc97493a161 create mode 100644 txscript/data/taproot-ref/b5f894878cea25475b042e2e6dccf49267130d0f create mode 100644 txscript/data/taproot-ref/b605240fb46dc5b5a62d8e4fe44362074c17cd79 create mode 100644 txscript/data/taproot-ref/b62a40520073f939f2c0c9f173f5df055dbcfe5e create mode 100644 txscript/data/taproot-ref/b646f8b3b9e38907889dca9d182ffcb148c5eb86 create mode 100644 txscript/data/taproot-ref/b64c6d5ba93dfc04d7a168f3316abb231668ca1a create mode 100644 txscript/data/taproot-ref/b66c4be98c84d4c925dd2af48a775cc657d0344d create mode 100644 txscript/data/taproot-ref/b6737bb08c29b827385850c321cf5d8413acfef6 create mode 100644 txscript/data/taproot-ref/b67e4f02f0ff506105dfa4a0171d89ceb6d26cfa create mode 100644 txscript/data/taproot-ref/b68b738158b1aed99780946dcf5925a67eb68cca create mode 100644 txscript/data/taproot-ref/b6df4711f8c031a1f3fc609594a2746d2d4e3d62 create mode 100644 txscript/data/taproot-ref/b6e1970eedbfd9c6a474d94f15274687adf86c2e create mode 100644 txscript/data/taproot-ref/b71c95db43c402381d9a9673ab063f0735eb1d31 create mode 100644 txscript/data/taproot-ref/b71ebb4f48a1c213c17c8b1e9166cc38b072dc9d create mode 100644 txscript/data/taproot-ref/b72daece9e0661e0bd4c8a41d26c73ba8eef4882 create mode 100644 txscript/data/taproot-ref/b795709244b876a1f75a1d801c74732832748ebb create mode 100644 txscript/data/taproot-ref/b7a501079daff65d0e768364b11ab44c69980aa7 create mode 100644 txscript/data/taproot-ref/b7b1691a7efc0fca08ac5b931ccb3dbf5aa891d8 create mode 100644 txscript/data/taproot-ref/b7cc907a8b0d3c3e1994be68a40873b4e99a5f78 create mode 100644 txscript/data/taproot-ref/b8079c5bdcff63a0f477e2f79dd8aaf4928abda7 create mode 100644 txscript/data/taproot-ref/b809617c671f07711eb77d11353900df3a1020b0 create mode 100644 txscript/data/taproot-ref/b83c1c0b8c3121745e8e5a5de023dfb379736329 create mode 100644 txscript/data/taproot-ref/b83df399d9754f536f1c099dfad005119a65be7a create mode 100644 txscript/data/taproot-ref/b83ffefda146d967a06f51678c18eff540980695 create mode 100644 txscript/data/taproot-ref/b84cd36f16a07a3e7153b397d87779a08b904316 create mode 100644 txscript/data/taproot-ref/b8500830a3e73890fbb7f1b5e546f8dd9a851acb create mode 100644 txscript/data/taproot-ref/b8684e0746d02b30dd7444f365d9552810403e85 create mode 100644 txscript/data/taproot-ref/b8a16da4c5a5e56d3c75e8933ac8d444b9d06ecc create mode 100644 txscript/data/taproot-ref/b8a400a5412cc152b17a2cda851c5874dd5ead2d create mode 100644 txscript/data/taproot-ref/b8a97f2ecce17499487b6afbfd74dcdb69711ff3 create mode 100644 txscript/data/taproot-ref/b8b534195cd5db1dd0cc83d99d7face7ebae029d create mode 100644 txscript/data/taproot-ref/b8ba77481215495fefc3d9c89e8e4251b1514f9b create mode 100644 txscript/data/taproot-ref/b8c25103015cf79375d6f576186c9bf014842e27 create mode 100644 txscript/data/taproot-ref/b8c863f970b2f3c39e353171b5902be0355002ed create mode 100644 txscript/data/taproot-ref/b8daa1c785e390cba67ca10da7ee578c00efb805 create mode 100644 txscript/data/taproot-ref/b90034052330d016cb6261caaff33ff9b2007d1d create mode 100644 txscript/data/taproot-ref/b953ae08ca074cfcfeda2be630b7eabb0a0feef0 create mode 100644 txscript/data/taproot-ref/b95d3cec25b96ed5bf972cb98ca8c6476eac7630 create mode 100644 txscript/data/taproot-ref/b95e31c70d4e1c7f52eb020450f422dc69f2b3f1 create mode 100644 txscript/data/taproot-ref/b960c57badc5a9291e8064176397f05700f998c2 create mode 100644 txscript/data/taproot-ref/b98b3ae70f7b3075d295829a4a779d63ac54efc1 create mode 100644 txscript/data/taproot-ref/b9c4f033e767c62469be7d0c9837ff7976269c03 create mode 100644 txscript/data/taproot-ref/ba1c9764d8c0c80309b24333c675854c1e92edf6 create mode 100644 txscript/data/taproot-ref/ba1e6bbaa2a233a2a9e108339e2a03d15db6c21a create mode 100644 txscript/data/taproot-ref/ba213f9e83bc18ee5d889ce921f71786661cdb49 create mode 100644 txscript/data/taproot-ref/ba60320519e241dc303d027571c1b6b6677274ef create mode 100644 txscript/data/taproot-ref/ba66a56ebc2679a2d9e33cd52effe2bf5657ba63 create mode 100644 txscript/data/taproot-ref/ba71d7ae4697eea6a410b7c4d7d542ded867b329 create mode 100644 txscript/data/taproot-ref/ba830627ab470b34e7d889cad07110a91669d64b create mode 100644 txscript/data/taproot-ref/ba88104330b37c0458b14c5d53739d04527f803a create mode 100644 txscript/data/taproot-ref/baa4d60cb12ba51a47909ac8227ee6df6d0dc0b2 create mode 100644 txscript/data/taproot-ref/baa96c5298845a9d61eb221acb395d2256d66ee5 create mode 100644 txscript/data/taproot-ref/baa9d2ad62a330c543ec07ad2137ad8de21565a1 create mode 100644 txscript/data/taproot-ref/bab370c81fa011cfbd5f4933e8e203b69b4613b9 create mode 100644 txscript/data/taproot-ref/bae295c693b97cb9ce1c49550985444f7083bf7d create mode 100644 txscript/data/taproot-ref/baf106403ddec9a4e35d93e4d7e9c8858a1db975 create mode 100644 txscript/data/taproot-ref/baf7af0bebc3219aa43e93f239abf44c3c75cc84 create mode 100644 txscript/data/taproot-ref/bb00878c7c40b024bd20fd9e026f76cc0f01bda7 create mode 100644 txscript/data/taproot-ref/bb06616585d2cf60ef82187fc0334f6ddea3aafc create mode 100644 txscript/data/taproot-ref/bb0848b612e67f32638209d33374606f9f878516 create mode 100644 txscript/data/taproot-ref/bb213f4cc6adea71bcd254acd7a66de7a21a8fb5 create mode 100644 txscript/data/taproot-ref/bb4c46289dbd303f6704b3a08d9e02f4c48b84e6 create mode 100644 txscript/data/taproot-ref/bb4cc97eb2c8303964e3730c003f85cb88a0211d create mode 100644 txscript/data/taproot-ref/bb7141b532ed1aa0b98bd58bc84ec2e08f2e47c0 create mode 100644 txscript/data/taproot-ref/bb7fc95bb6e35ae77514934a3e4ffa53a6516e13 create mode 100644 txscript/data/taproot-ref/bb85f9b909ffd0ec974d57b8e96a0afe8031c95f create mode 100644 txscript/data/taproot-ref/bbb302be328567aed2f8a9548699284ede429dc6 create mode 100644 txscript/data/taproot-ref/bbc60e9c8fe20335286b1b4c11f2554bf44bde1c create mode 100644 txscript/data/taproot-ref/bbd6a4aa19b13347c78851a8c39dc87ba2c6cc26 create mode 100644 txscript/data/taproot-ref/bc18a41aa534670b3eb06ea552eeaa43a8bf670b create mode 100644 txscript/data/taproot-ref/bc44929f9083ce895cef6e68e78c51d907624850 create mode 100644 txscript/data/taproot-ref/bc61d16fcfe7499f1dda3e1aebd61701783f32bb create mode 100644 txscript/data/taproot-ref/bc63fef6a6e1da11f5ad9cdc8c82557d301f7f93 create mode 100644 txscript/data/taproot-ref/bc94c09d187af83d11bc158ffad91041ae1cccf5 create mode 100644 txscript/data/taproot-ref/bcd93267863bf6c12c490fdca519c9a6fb257676 create mode 100644 txscript/data/taproot-ref/bcdee1bf1b6f002a01bcb15b07e1ceef6be9c962 create mode 100644 txscript/data/taproot-ref/bcfbb863f9751dbc9e52565fa18f52d7cfc28dc0 create mode 100644 txscript/data/taproot-ref/bd06f79eb234682d1b026c5b614cea268261d69b create mode 100644 txscript/data/taproot-ref/bd10e29dccdef5c1bc2693b295ca9c3ee1a5e9fb create mode 100644 txscript/data/taproot-ref/bd4570befca425281b554426e78e723b29b91aeb create mode 100644 txscript/data/taproot-ref/bd4b0d5ede1b9b28ba821e22b21d2e67eb35fb46 create mode 100644 txscript/data/taproot-ref/bd5b6bd1cba3b3c9511abe6e7ba85869cc7271a8 create mode 100644 txscript/data/taproot-ref/bd647eceba7eb445528903854da69225eb46a33b create mode 100644 txscript/data/taproot-ref/bd806dc6dd950acd2fb4799772f9284b52b3eefd create mode 100644 txscript/data/taproot-ref/bd90aa727c6f46c0b214029c4cc55665db207ed4 create mode 100644 txscript/data/taproot-ref/bdb75495237a21c1632a1d8002a2de43c75cbece create mode 100644 txscript/data/taproot-ref/be342f285479f59388d4ad299b262298ea0a194a create mode 100644 txscript/data/taproot-ref/be4056e6d4621f67f649cc023b36d0616763fb74 create mode 100644 txscript/data/taproot-ref/be5fa21ede21c3ae07d18916186307eb0dbd0b20 create mode 100644 txscript/data/taproot-ref/be6dd32445672ad01a41728099573f056d19f11b create mode 100644 txscript/data/taproot-ref/beaac08761cf0537284bd2fb73e52c21bf944e0e create mode 100644 txscript/data/taproot-ref/bebcb9f288f4fe614ba1fcc940d72dd3a2e9182c create mode 100644 txscript/data/taproot-ref/bf0031c6d9edfce82c4f7c49f277cbf11c628084 create mode 100644 txscript/data/taproot-ref/bf1ad139661581e23e01c40061ebbcbdbce507e7 create mode 100644 txscript/data/taproot-ref/bf2b441671494bdd813cbde459c3f201b5dc132d create mode 100644 txscript/data/taproot-ref/bf34c8983707b06356e258d949ea5d5b386f793c create mode 100644 txscript/data/taproot-ref/bf699d29a3431d6314083edeeb34fd0d30d0e88a create mode 100644 txscript/data/taproot-ref/bf79de65a5198ccae719f56cd87e06ebfa963388 create mode 100644 txscript/data/taproot-ref/bf8f7dfface9a3a19ae105b018ef9c8464a7766a create mode 100644 txscript/data/taproot-ref/bff5be66a4aacf336f6a1a8aabdf35a37bd49c75 create mode 100644 txscript/data/taproot-ref/c0039aba73061b1e9d1b5673c11d9a6fec6c2d2b create mode 100644 txscript/data/taproot-ref/c0201387de1a365edea3ae462c8e87757ac56e21 create mode 100644 txscript/data/taproot-ref/c0264fc040cf13b7e91a6413eb4b7c76c194b45c create mode 100644 txscript/data/taproot-ref/c02fa738eb666819f177a296b855df242f3744a5 create mode 100644 txscript/data/taproot-ref/c04290c4f9037a6b82b7d2392c6c80c1ae11f80c create mode 100644 txscript/data/taproot-ref/c066693ba1a2191967ded9338dab201a79f31370 create mode 100644 txscript/data/taproot-ref/c06e8cd4278bfe18806835f29e8892fe38588b77 create mode 100644 txscript/data/taproot-ref/c09fc10086b95973815a1c9f85b9e89af0b68a27 create mode 100644 txscript/data/taproot-ref/c0c65b781da778eab58a96c85067f90b2d4d1f4c create mode 100644 txscript/data/taproot-ref/c0d2b1edf6f56cba1a8e2d0b100cb918fd7f803d create mode 100644 txscript/data/taproot-ref/c0d30a73338909cf56a6d97fed0221e78bb7731d create mode 100644 txscript/data/taproot-ref/c0ea13628224c7cfa08a24dfe6cac5360c02d61f create mode 100644 txscript/data/taproot-ref/c0f5b91a651c2d181d2e204758d6556b2d362c11 create mode 100644 txscript/data/taproot-ref/c128857e0f643e229c430eb8ef7d3f5aaad861fb create mode 100644 txscript/data/taproot-ref/c12b71a60e309ebef55284d493cfd3665116ac35 create mode 100644 txscript/data/taproot-ref/c146489c520399688a56c27fa5210f00c10e9e5b create mode 100644 txscript/data/taproot-ref/c180a8fea16357ccb1c9e9a5b1fcde5e0137ba39 create mode 100644 txscript/data/taproot-ref/c195e2cf967dde5160c0de3b6a514dbb2ff8485c create mode 100644 txscript/data/taproot-ref/c19c13729ac0ec5c7e396da5494a3f513d31d8e8 create mode 100644 txscript/data/taproot-ref/c1b84b02f4cf106428923ebb095dd6888ae0ac50 create mode 100644 txscript/data/taproot-ref/c1bff9e88ae4e9b8bfd1976fa22c1802e6db3962 create mode 100644 txscript/data/taproot-ref/c1e5922d5f60798c78f4d0d669795bdad1a0801b create mode 100644 txscript/data/taproot-ref/c1eeed88c600ab669ef89bb18d5ef6a6830d4f0e create mode 100644 txscript/data/taproot-ref/c21065afa4b19740633e3c552a080169d12b4afb create mode 100644 txscript/data/taproot-ref/c2268af10452034a5d5f9268c6f6797ab805a459 create mode 100644 txscript/data/taproot-ref/c22963b5f52cca482bd79213fd1c9fd9819b85dc create mode 100644 txscript/data/taproot-ref/c23bb15b95f0283493b5e9660535131e08c4b442 create mode 100644 txscript/data/taproot-ref/c23dc3dee1bab058e9dda39e357268464aff6993 create mode 100644 txscript/data/taproot-ref/c259be6e071636a46f638dc71fbf337480a65d62 create mode 100644 txscript/data/taproot-ref/c2606a81031cc7d45d665ff29e83009cdaeb09b4 create mode 100644 txscript/data/taproot-ref/c2615fefcd8c48ae15d7cdf715cb7cbe15365bb4 create mode 100644 txscript/data/taproot-ref/c274fc041bc18ec36b6fc361335ee8c903ba6539 create mode 100644 txscript/data/taproot-ref/c2b521f99f9142ffd0f06f35fdbf0a1e6db3b411 create mode 100644 txscript/data/taproot-ref/c2bc316e1620048c72dc6375bd6c4de0d175594b create mode 100644 txscript/data/taproot-ref/c2ccbe9e06e6c7ce6e43c0b381322fc7dc10a2c2 create mode 100644 txscript/data/taproot-ref/c2cdbf0cad554855e5a2c77ade2426042fd077d0 create mode 100644 txscript/data/taproot-ref/c2fc3139b18939587fa9376d426b5ed6e5a7d384 create mode 100644 txscript/data/taproot-ref/c30440e2e36842767c6880d3419ffd67d8fc65e5 create mode 100644 txscript/data/taproot-ref/c30828b92e910f121013ae0e7e80f112ff29c40a create mode 100644 txscript/data/taproot-ref/c30e1db5cebdf16c793ac3774df5940ba0cbd27f create mode 100644 txscript/data/taproot-ref/c34e8364c057d48255c31d4626eee97cb90971f7 create mode 100644 txscript/data/taproot-ref/c34ea38700b3874b1fc56b98fba764e26e442bbf create mode 100644 txscript/data/taproot-ref/c36f9ecac75a1f8369062bd659d7be8116d9426f create mode 100644 txscript/data/taproot-ref/c3759872dcc57d4041c64cfe3164f0beae9647dd create mode 100644 txscript/data/taproot-ref/c37b0f05074e165869fb4e36093d5d05e7f5cd58 create mode 100644 txscript/data/taproot-ref/c38df517f192e8ee8b749587f2286408e1add7af create mode 100644 txscript/data/taproot-ref/c3a855f0999c9f0c734c21ec479b4a2de052c197 create mode 100644 txscript/data/taproot-ref/c3ca44e765c59aef19ebc14444cb23801ff338d4 create mode 100644 txscript/data/taproot-ref/c3f3469ae6022ba9a824d15d3e5c6966ecd2729f create mode 100644 txscript/data/taproot-ref/c42ba6332f5103b6c07a6d7b7c7a96e1345fcad3 create mode 100644 txscript/data/taproot-ref/c4499beb83fe2bbc215490890a252106247a0d03 create mode 100644 txscript/data/taproot-ref/c46f7002e386e4c4fd5c63195b15a2720dc604c6 create mode 100644 txscript/data/taproot-ref/c4b2c2074e18699523a8e60939dabe323e8cfcc8 create mode 100644 txscript/data/taproot-ref/c4c19d4cee5d79334aa9c0ff61f19d321cc3941e create mode 100644 txscript/data/taproot-ref/c4e28343af816c29311d37b8559a05b14d797dd9 create mode 100644 txscript/data/taproot-ref/c5c550da4ca7e932cdd65a9656f2f7c611148d24 create mode 100644 txscript/data/taproot-ref/c62a6dec1ec0c7508b82a35dfbcc1d66455eb241 create mode 100644 txscript/data/taproot-ref/c62d08fa40199eb68353dc3045f6c961f21f080c create mode 100644 txscript/data/taproot-ref/c63b3815a0dae098fa0dce37acfd79f213436d49 create mode 100644 txscript/data/taproot-ref/c63fa7c5e9f3cfa3be54296de8fcb8c5bae42ab6 create mode 100644 txscript/data/taproot-ref/c66c43a4b77a41b0bcafd8714216e0e515ea32c1 create mode 100644 txscript/data/taproot-ref/c671d0d61110d22335aeeff604afc7a78832a1f0 create mode 100644 txscript/data/taproot-ref/c684723b339ed9a247b5fe843d2111fcb009cbf2 create mode 100644 txscript/data/taproot-ref/c6911c815fc4eb1fdd0b9ab9cd09d3f6af2c6188 create mode 100644 txscript/data/taproot-ref/c69155ad942486c3313ec96fba99eb4b629b0b7e create mode 100644 txscript/data/taproot-ref/c694a3b9670b92c47faef2482e1c373a96c84b7b create mode 100644 txscript/data/taproot-ref/c6a2dc24e570bc2a810731231121944aa2c4a595 create mode 100644 txscript/data/taproot-ref/c6fa56d9a3cfa039c883bb5289ea577b65e788ce create mode 100644 txscript/data/taproot-ref/c709197b022538558c64745e06cce6340703a73d create mode 100644 txscript/data/taproot-ref/c70d23ebccdc1ea73e6448b1df58f62d71582adf create mode 100644 txscript/data/taproot-ref/c71d9516b42225f3514b4d1df627c022e4817ee0 create mode 100644 txscript/data/taproot-ref/c7252d6f48851dc47f8c3177537e12abe69a084c create mode 100644 txscript/data/taproot-ref/c75d0a897f9c6981d81da8b49be331ba03439313 create mode 100644 txscript/data/taproot-ref/c761e8c4c51ea45aa6c56b949fdc22e5d4c60cf1 create mode 100644 txscript/data/taproot-ref/c763c8080d8e8e78651eaf9140b7aa3fef1d52d4 create mode 100644 txscript/data/taproot-ref/c77f06b7f82e62ac50865f5ee4163ae369969020 create mode 100644 txscript/data/taproot-ref/c785d388c9a15886ab980f88b666d4945c7ee4a6 create mode 100644 txscript/data/taproot-ref/c79333ec6723390b7f1563f388c7a50d86f860b2 create mode 100644 txscript/data/taproot-ref/c7946ca286a4c1e04861f5fe7ff7982618728e8f create mode 100644 txscript/data/taproot-ref/c7a2d84c0203fa2c48f932ed3cdb57e9bc3d4cd3 create mode 100644 txscript/data/taproot-ref/c7aa7f6d958c6e29a221a767f1d7b3c103fe86b2 create mode 100644 txscript/data/taproot-ref/c7b48c2518d6d2a2a5acd628f2fb397cad2ac0ea create mode 100644 txscript/data/taproot-ref/c814f8c932eb8ff0b1b54d8a85929406a22a72f6 create mode 100644 txscript/data/taproot-ref/c8172ac90dca46ddecfcb6abf992c70d492bdaf0 create mode 100644 txscript/data/taproot-ref/c8203a41b6f45793c2150ed5554ab5bf5c7eae94 create mode 100644 txscript/data/taproot-ref/c82943e824916226a82dbcda450c1cf3f21df1da create mode 100644 txscript/data/taproot-ref/c83f86babe52fc934414d829d4969407bdaa8de9 create mode 100644 txscript/data/taproot-ref/c85880f71216bacfb5f45a917040c76a5b933f5e create mode 100644 txscript/data/taproot-ref/c85ec330c8ffb17623ec929fd4a198c3b768811a create mode 100644 txscript/data/taproot-ref/c86c77b200bac67eba1a81988b36e0764528deef create mode 100644 txscript/data/taproot-ref/c8e586d3f61c1ad22568794bbfcb69f57cb8b000 create mode 100644 txscript/data/taproot-ref/c8ef39151618f6cc8716604cb9c29f93559b5a3d create mode 100644 txscript/data/taproot-ref/c908a5304c6a71d150881ee923df19a58e37c8e9 create mode 100644 txscript/data/taproot-ref/c91a0b63271792838de6f8620c116c19028be7d3 create mode 100644 txscript/data/taproot-ref/c92d0b7830a59c91b7478b9bc6537abc9104ab24 create mode 100644 txscript/data/taproot-ref/c94bf93a205b5120777d3d7dedacadaf6c732df5 create mode 100644 txscript/data/taproot-ref/c95a348b7638eb340903fe3cc3532859ffe5403f create mode 100644 txscript/data/taproot-ref/c965920ad9808bd3f6a009ce5335213895163c4a create mode 100644 txscript/data/taproot-ref/c968d693525b4f56eb70b070dbf41555841fa170 create mode 100644 txscript/data/taproot-ref/c97c22cac658b5a97d90aab28ef2a0126a80ce6e create mode 100644 txscript/data/taproot-ref/c9810cb06137edb22aba29ce495e0f5e87073b06 create mode 100644 txscript/data/taproot-ref/c9888f4ae613d1778de5399e9c17e6e517df9292 create mode 100644 txscript/data/taproot-ref/c9a84f25b1d55cfc33df56ee356e86772a479352 create mode 100644 txscript/data/taproot-ref/c9addf4f9fd1a956c97c9babd5981d0c8295e152 create mode 100644 txscript/data/taproot-ref/c9b398e28803f0f2e675448f50d7f4d8c39e8991 create mode 100644 txscript/data/taproot-ref/c9d4c34b8cbf8c16d5b1e01af0f0541cdd36456b create mode 100644 txscript/data/taproot-ref/c9dd51e291d1902fcc5389ef9f70290ea166e35b create mode 100644 txscript/data/taproot-ref/c9ed258ea27321037ce42d665a00191863c1ddce create mode 100644 txscript/data/taproot-ref/c9f4f38c06357e5794c082ee3a691a02193ff1e2 create mode 100644 txscript/data/taproot-ref/c9ff164d902f41698dc1714ef130057761a13f8c create mode 100644 txscript/data/taproot-ref/ca067c02b5a5e0209c277a0cea71db50a16d380f create mode 100644 txscript/data/taproot-ref/ca0a2329b586ff39d07383acaecfac1982afe0df create mode 100644 txscript/data/taproot-ref/ca10907ed5b956b8d7c600609307e951fa48d8e6 create mode 100644 txscript/data/taproot-ref/ca10ab334b15fc1a219962a002ba20266142420e create mode 100644 txscript/data/taproot-ref/ca3a2137d38c1e9a98dd585fbb1e5e6483a855d0 create mode 100644 txscript/data/taproot-ref/ca4f72eced8e3ace4cb06faea7d35e7831c1e5ce create mode 100644 txscript/data/taproot-ref/ca4f932e8cc3a4b016fedf455e955c89cd7237bf create mode 100644 txscript/data/taproot-ref/ca67aeff72a1ca354129ea9f32b49e63219b5d98 create mode 100644 txscript/data/taproot-ref/ca8e90d773aaf3a6cc447fa963353434f82c0e50 create mode 100644 txscript/data/taproot-ref/ca8ead844b2d1ee6d2526ed1a548996bc943ea68 create mode 100644 txscript/data/taproot-ref/ca9fc42da81222da6dec277f6346109bf564fefb create mode 100644 txscript/data/taproot-ref/cab98434bc48379e0a365fff01d6b79bf577457a create mode 100644 txscript/data/taproot-ref/cab9a4b9aa0799313bf8c71e90011d910fd2eca4 create mode 100644 txscript/data/taproot-ref/cabd7d24e6498c820ccd2a79a03cc481607909e5 create mode 100644 txscript/data/taproot-ref/cafd0a9a6dab6200dcb88ecbf7e265de1ad5d317 create mode 100644 txscript/data/taproot-ref/cb181959ea829e3c8e81c95a1bbce81b35f8d2fd create mode 100644 txscript/data/taproot-ref/cb1b57e08db865390f1b4cf22118530463b721aa create mode 100644 txscript/data/taproot-ref/cb5cd2d881a8e8202863c29e2d692b6245167dd1 create mode 100644 txscript/data/taproot-ref/cb7c58b77b079764dd1fdd95626fced2ad539c7c create mode 100644 txscript/data/taproot-ref/cbdd9f9ee3d06ce2cdfe2000194d0fa14bb03cb0 create mode 100644 txscript/data/taproot-ref/cbe16c2c588c6bc7000fbb04188632167236d008 create mode 100644 txscript/data/taproot-ref/cbfe3b47d8728af1b60451af99e980f90dc89668 create mode 100644 txscript/data/taproot-ref/cc06cd6c0a43860436758eaf21a715c3ecebb6f4 create mode 100644 txscript/data/taproot-ref/cc13210738ed00cc6f24c6bdcc72bc63f13783e2 create mode 100644 txscript/data/taproot-ref/cc3fcfad22ff1374fc57610045f054311fc92f6d create mode 100644 txscript/data/taproot-ref/ccb6fc2bd7df140d0acaa9fa4f6c64be65339a60 create mode 100644 txscript/data/taproot-ref/cd083f5472e5c5b1f0a2910e5400ed9fb0e38379 create mode 100644 txscript/data/taproot-ref/cd2bb450b14d6d4aeb2383f17d0b52532a6d60bc create mode 100644 txscript/data/taproot-ref/cd2f80cd83fdc9c096ed0c6e1e02112a0e62dd16 create mode 100644 txscript/data/taproot-ref/cd4a620abc44efff9ec16d12232d21d35383be02 create mode 100644 txscript/data/taproot-ref/cd536df731fdebe8bbafa86ebef1f6c819648a78 create mode 100644 txscript/data/taproot-ref/cd553bbac6c8bd33ad432ca2077facbf41604f68 create mode 100644 txscript/data/taproot-ref/cd8b40b4ffe13dc923550924d4133d5ac918ecc4 create mode 100644 txscript/data/taproot-ref/cd8ca448ef6a3c3fa7536eee563579389b399c7f create mode 100644 txscript/data/taproot-ref/cd935e81f7b958dc94cbb682f2c926e1e63fc213 create mode 100644 txscript/data/taproot-ref/cd9562d304291faf33b2752268819af3d9fdd593 create mode 100644 txscript/data/taproot-ref/cda64a68115a3ca8971a2747b360b387fbe1d1ec create mode 100644 txscript/data/taproot-ref/cdaa800ed715e873d65a75ff494c085689777769 create mode 100644 txscript/data/taproot-ref/cdae175fecf9783890ad4364fcdb7e9a26312c86 create mode 100644 txscript/data/taproot-ref/cdbb9c9c88d727637e88c5e5f34b796e03a77c9a create mode 100644 txscript/data/taproot-ref/cdd70dfc5c39ec02e5e48d747003dccc345d9c35 create mode 100644 txscript/data/taproot-ref/ce08102de2f440a689645ebc57829a604424b751 create mode 100644 txscript/data/taproot-ref/ce29a0262edb0e4c4a3905e19cb08c9a4e8318ba create mode 100644 txscript/data/taproot-ref/ce4f3f6725a58e41e3545de8f93475f0f9402a52 create mode 100644 txscript/data/taproot-ref/ce5a6e30faecc2d2f249b1bb1b0a21cbffc46674 create mode 100644 txscript/data/taproot-ref/ce5c007dab411a6a225c1b09181578eaf6edf364 create mode 100644 txscript/data/taproot-ref/cea069b190b73ea7c41e48275d6d0841d7fdd8f3 create mode 100644 txscript/data/taproot-ref/cec62d6028ecb0885e4adbb89b0c33222ed71d55 create mode 100644 txscript/data/taproot-ref/cedf97481d67a8a89199abfe8c15570cd253967d create mode 100644 txscript/data/taproot-ref/cef118940d5799540be8721e2453120639fbe14e create mode 100644 txscript/data/taproot-ref/cef395bb5063aba1aeaafde86a8bfd4c3ae80b8f create mode 100644 txscript/data/taproot-ref/cf1726d92ba0a57e5cb508f7f38cf8c30c31572a create mode 100644 txscript/data/taproot-ref/cf19361572439227ba12b4d90a84b45c9c77a6dd create mode 100644 txscript/data/taproot-ref/cf1b9fbc48a705e782d90e0caefa83731663957e create mode 100644 txscript/data/taproot-ref/cf3ddc0d11192bb67b1d1a9c46dba9cb99e1ab37 create mode 100644 txscript/data/taproot-ref/cf87f1c7fe8d84db93cab39e5ec4fc004b0daf45 create mode 100644 txscript/data/taproot-ref/cf99a5aabda5c420d162ea57e1d44c83b4a5f444 create mode 100644 txscript/data/taproot-ref/d01804b3f650a230ba4caf6f35710074094ef4bc create mode 100644 txscript/data/taproot-ref/d018c44a4a260f0faa1c368b22e6fd2da47b4279 create mode 100644 txscript/data/taproot-ref/d023d686290f14c19a40f74a18a2c183ac38c02f create mode 100644 txscript/data/taproot-ref/d07029fee875ecd9778957b1eb1b6ed3ba90c94a create mode 100644 txscript/data/taproot-ref/d076c78276e47d5f2551df88390966202a644ad4 create mode 100644 txscript/data/taproot-ref/d0a5a7631c5914f69f44abe8d926e7ec265b3853 create mode 100644 txscript/data/taproot-ref/d0b362a6e10e2e3ca3df573c3918408d11230109 create mode 100644 txscript/data/taproot-ref/d0c14f7b59f5b7c5e2348a842c4f17589992edef create mode 100644 txscript/data/taproot-ref/d0d80b81785e11a47eb4778cde0392ceee57d442 create mode 100644 txscript/data/taproot-ref/d10cc817535fbf7ed3ccccfffd59542e31fd811c create mode 100644 txscript/data/taproot-ref/d120192543d7524d72dbae6640c1fd01b655ba8b create mode 100644 txscript/data/taproot-ref/d13e9dcbf612e2b605c913bf461a40c14c78981c create mode 100644 txscript/data/taproot-ref/d145e690ead8e8b91dcf655a058473fba40e05c4 create mode 100644 txscript/data/taproot-ref/d1624ab2e4dceb28dc1e7d8f042d85271b474f44 create mode 100644 txscript/data/taproot-ref/d17443611cb2c74ecfda516700477ecdd4ccd1e8 create mode 100644 txscript/data/taproot-ref/d17802655b5504bb0405ee7934ae6e14c9c2f6af create mode 100644 txscript/data/taproot-ref/d17b2da02d1d622d7b71dade71d9adc392999c5b create mode 100644 txscript/data/taproot-ref/d17e92c55da82ddc95d75ddd15779fff2868ff46 create mode 100644 txscript/data/taproot-ref/d209841a9bb6b9ed3a4954465f454a0d304ef888 create mode 100644 txscript/data/taproot-ref/d263cabcd95f3dae465820283cf9b428e89c02f6 create mode 100644 txscript/data/taproot-ref/d27d3711e16baa8c89ff9c90b6ed0622ca86ff8e create mode 100644 txscript/data/taproot-ref/d2957d9af2c85119d0e66bf643c7eb85bda86170 create mode 100644 txscript/data/taproot-ref/d2c7c0da2861f14114f11766107a7b8aa6efd73b create mode 100644 txscript/data/taproot-ref/d2d896106278d4a3d97f13f67d9366baca387121 create mode 100644 txscript/data/taproot-ref/d2e69860ee1527c081669b81f428a0dee46fe218 create mode 100644 txscript/data/taproot-ref/d2f56cc722b3fc0ac3792e7c09a53592a22039af create mode 100644 txscript/data/taproot-ref/d2f8f204891c46f5ba28af13b77da60a054ed30f create mode 100644 txscript/data/taproot-ref/d33cb0c2e7c01d420f375159f3d266e71d9c3bcf create mode 100644 txscript/data/taproot-ref/d34c8b66d9e51e1f51b9432c19d0d95ce51aa297 create mode 100644 txscript/data/taproot-ref/d35d96943b798f0362dee33b1c9dd9f5ce520bf7 create mode 100644 txscript/data/taproot-ref/d386337a1d0705a7cc519dc2e044e51c1831c3f8 create mode 100644 txscript/data/taproot-ref/d3918bf85a56fd7561082f401a5ebd4a0d642f87 create mode 100644 txscript/data/taproot-ref/d3abb997507d97ede96a2ca419dd8554e22db558 create mode 100644 txscript/data/taproot-ref/d3ad578f5f3076aa52c4e35e8a0002582433fef9 create mode 100644 txscript/data/taproot-ref/d3ae88e79c1801c2da2ca48244ec5455bb3abe76 create mode 100644 txscript/data/taproot-ref/d3d3e2a151a062b9f319dd5ba2d382d38c8c95d4 create mode 100644 txscript/data/taproot-ref/d3e5ffbc18b1ff4b1db6426ef3962f8c9cf5cdf0 create mode 100644 txscript/data/taproot-ref/d411fdd25ef73e64648572aee57803f358cf4bb2 create mode 100644 txscript/data/taproot-ref/d4208a5824d1318820b3784412f424db595f35ae create mode 100644 txscript/data/taproot-ref/d42eec126dd7b1e4c2c574ddba68f4d0228c3d09 create mode 100644 txscript/data/taproot-ref/d48d445fdf8825eb982e112320fe51da22271d30 create mode 100644 txscript/data/taproot-ref/d49f2424f7e47981e92cdca8a120fad3b5b46351 create mode 100644 txscript/data/taproot-ref/d4a61c1883d529642358ce1ad476eae28f347140 create mode 100644 txscript/data/taproot-ref/d4b2d30318741bf9642c79ca255322762ff5a669 create mode 100644 txscript/data/taproot-ref/d4bdc84c656fc906c865b5369626edd1bc0d575d create mode 100644 txscript/data/taproot-ref/d4bfa057df6de164cf5907d1054f7b8f37dc55ca create mode 100644 txscript/data/taproot-ref/d4d9f5cbd1cf9b75c9821d5d4746491e46efecb0 create mode 100644 txscript/data/taproot-ref/d4eb08a9f93ac1b16665f4266fcd570b760e0b41 create mode 100644 txscript/data/taproot-ref/d4f11edc0601915ee85baffdd4721b1d1b3b60d0 create mode 100644 txscript/data/taproot-ref/d4f65e281be1feebd4750e113b05138a9c44f486 create mode 100644 txscript/data/taproot-ref/d5048f880c8259302815a101c17c687a6ddbb1d7 create mode 100644 txscript/data/taproot-ref/d52e561715cddf6ccf811873e1d9570a5b25b677 create mode 100644 txscript/data/taproot-ref/d5466e451d61467e6bd45f66d7608457be8a656f create mode 100644 txscript/data/taproot-ref/d54c6961bb95000149d7cffd738f1f34eaf1d825 create mode 100644 txscript/data/taproot-ref/d54fe454199d96dd8e1ab2d0069417d2b9be7cf7 create mode 100644 txscript/data/taproot-ref/d573fa9122441a358ecf4c86ea6af4d26e08d93a create mode 100644 txscript/data/taproot-ref/d5892cc02088b2b7e11febc39b2d7cd9ed96fec6 create mode 100644 txscript/data/taproot-ref/d58b0cd6e4cd0f7d08d8c5cd8f64fb89bc6c77b3 create mode 100644 txscript/data/taproot-ref/d5ad81a47205ca9893336dfcc66e370ee84776ce create mode 100644 txscript/data/taproot-ref/d5f073d2ccb1d4bc1f4bb2d64971cda535f3abc4 create mode 100644 txscript/data/taproot-ref/d60ddd04ef59ce7655ce0640bb9f05a050c50572 create mode 100644 txscript/data/taproot-ref/d6114c41966cf276af2ac91a43b0dcfdde3ff6ec create mode 100644 txscript/data/taproot-ref/d64045b67fe7d9bbac6b1955c9709dc8f62c2574 create mode 100644 txscript/data/taproot-ref/d65a0ff7ac01950da5c822d87cd1f1b94663c71f create mode 100644 txscript/data/taproot-ref/d66bdc15b3bc47537708b688679685d7823933ec create mode 100644 txscript/data/taproot-ref/d6a9e0d913d7e024afc093007237124f4a34364c create mode 100644 txscript/data/taproot-ref/d6bb41e59dad21fc3ff2d5bb0c784b27307ee4d3 create mode 100644 txscript/data/taproot-ref/d6e668abcd05531d83ec0bdff606bec2368882a8 create mode 100644 txscript/data/taproot-ref/d6e9b28f9645fdf80b2547f4a875bc298680a83f create mode 100644 txscript/data/taproot-ref/d70c950a9b6157fdddbd8eb01fed07f12638844f create mode 100644 txscript/data/taproot-ref/d71a3d01673ec097d7272cd0fcf4fc12f19a90e8 create mode 100644 txscript/data/taproot-ref/d72363609fde245d8d04d59c1d9e2386e97f61ec create mode 100644 txscript/data/taproot-ref/d73e808e6fe07bbd4cac3998bbd227cb333f3860 create mode 100644 txscript/data/taproot-ref/d7435dd29bb609d8a757deda3c46bae9522fafb0 create mode 100644 txscript/data/taproot-ref/d747c65611d3195e76faeea3dbaca70f0255d690 create mode 100644 txscript/data/taproot-ref/d7482427db68b72ab957e74167dbc8c28842b070 create mode 100644 txscript/data/taproot-ref/d7491a450345ac8fd8bd2da583d6974224917a83 create mode 100644 txscript/data/taproot-ref/d750ca1379d7933d2b0750e621fad549663516ca create mode 100644 txscript/data/taproot-ref/d762cef9eb8735ca5282dea549336970c32f0470 create mode 100644 txscript/data/taproot-ref/d784977d5fa21c31f0f510f5a1e2d50f7815c63e create mode 100644 txscript/data/taproot-ref/d78a59aa9fae45d7cbfb5d42a6d57744818f4f3c create mode 100644 txscript/data/taproot-ref/d78b2cc4912fce258a371b34976f623504f00bf5 create mode 100644 txscript/data/taproot-ref/d796184dcd2791587af889f67ff0bd146da22bf6 create mode 100644 txscript/data/taproot-ref/d7a0524afa7b58f919577fc272101adacde12154 create mode 100644 txscript/data/taproot-ref/d7ae7546c73cd724ed329a7e111b1874f3fad3a3 create mode 100644 txscript/data/taproot-ref/d7c12a570bce792607b3d5f23fc34ef6392109de create mode 100644 txscript/data/taproot-ref/d7d1782dc0b7c5e12cccab548a33619bf58a1db8 create mode 100644 txscript/data/taproot-ref/d7ed3928aecf2d3acbca2fb8d2ee7775f7f52ccf create mode 100644 txscript/data/taproot-ref/d7f54f75c60667b7fd883f34d666d917d0b88809 create mode 100644 txscript/data/taproot-ref/d80fa30ad1a0824f0da7b212e606ac5496c0715c create mode 100644 txscript/data/taproot-ref/d86ea65d288be1fd03e9e19e503b17612c637374 create mode 100644 txscript/data/taproot-ref/d8ac2a246d17295baa73602fa55f5ef1d6edd095 create mode 100644 txscript/data/taproot-ref/d8d54db51b8f8299982f8136c6058c9e8063811b create mode 100644 txscript/data/taproot-ref/d8def6ae46c2ae1d19b457603e2015ddad467ad3 create mode 100644 txscript/data/taproot-ref/d8df811ed2f11c79fe945f4943ea3299a251ecb0 create mode 100644 txscript/data/taproot-ref/d8e4caa314d508c3062410f0d680eb589488140f create mode 100644 txscript/data/taproot-ref/d8f77e44fa8aab802aa9131ae9f319611a054835 create mode 100644 txscript/data/taproot-ref/d915944728f949574638f5527cabdee757340ecc create mode 100644 txscript/data/taproot-ref/d92c58e19437f5a57d606edb988ebe5449b4db1d create mode 100644 txscript/data/taproot-ref/d93387aa595f09f4e40642c715176275012422f9 create mode 100644 txscript/data/taproot-ref/d93dd1d6d2d9b39d77cd72571effaec51dad73cf create mode 100644 txscript/data/taproot-ref/d9462d451520aea896848f14167cad63f8eb631b create mode 100644 txscript/data/taproot-ref/d9632d4e4f8d7cc9db523291bb7442332d7c588c create mode 100644 txscript/data/taproot-ref/d96eb1935933e5d8a16bab96d06d05f8b1ab6619 create mode 100644 txscript/data/taproot-ref/d9721f612be2c4596ef2507879885c69a5e6e58d create mode 100644 txscript/data/taproot-ref/d975fa857300c644b1b8b86b9e5579116325e3b6 create mode 100644 txscript/data/taproot-ref/d97fad7ecab4d8f234efc71d9e0019d3cd6866be create mode 100644 txscript/data/taproot-ref/d9d8525ff675d165e7bd245edb10bef8ffbabf37 create mode 100644 txscript/data/taproot-ref/da15d30445dcabf73491b38ff9b7fd6ebf09fabb create mode 100644 txscript/data/taproot-ref/da20174fe1299204fdf8cca351a424cf681308a2 create mode 100644 txscript/data/taproot-ref/da3eafaf969feb19889dd744b3407db1aa866e06 create mode 100644 txscript/data/taproot-ref/da802c4897e37a5e51f367edd23444c11faa33aa create mode 100644 txscript/data/taproot-ref/da8a14b376513348d7ee34b10ff6883f15cc6fd5 create mode 100644 txscript/data/taproot-ref/da91d607fd954405726ab36fa5677e8163634ff7 create mode 100644 txscript/data/taproot-ref/daad29bf36401da76f1b83f5cd1cc0335bf5c14f create mode 100644 txscript/data/taproot-ref/dacc869b2d12c823c9a4bb00e5edcd51d35c5978 create mode 100644 txscript/data/taproot-ref/dacf3352a5bdd39737fb53affdf284ce61f4e97e create mode 100644 txscript/data/taproot-ref/dadf4bbba1d78a438712afd4e84df10275987f0a create mode 100644 txscript/data/taproot-ref/daf266d227dfb92686b3d8cb80cb4d2c4e849468 create mode 100644 txscript/data/taproot-ref/dafea52d56a314eff0b38df4ddd35be40d4f6d24 create mode 100644 txscript/data/taproot-ref/db01c81c34e5e86ae44bef70289a143173916fb4 create mode 100644 txscript/data/taproot-ref/db06c61fa468b40855c83db915cf67df55dddeb9 create mode 100644 txscript/data/taproot-ref/db191d70ebee38a520718fe3a295896a1840f111 create mode 100644 txscript/data/taproot-ref/db2f754795e1478498a59b3071a7852a32a70b8e create mode 100644 txscript/data/taproot-ref/db41febcaac001cb453d4a2ca2a285784d5a9cd8 create mode 100644 txscript/data/taproot-ref/db5b9f12551bfc0e07e9c89d6d5971df6e4eea17 create mode 100644 txscript/data/taproot-ref/db715816bbafa4a288124a98d0cb4df6a364cb3e create mode 100644 txscript/data/taproot-ref/db81d6ad0913097959d953bb6c2e7d576f846a11 create mode 100644 txscript/data/taproot-ref/db9eba0b2b563ba067b7fd8e8ee5ddad9b770dce create mode 100644 txscript/data/taproot-ref/dba31a12d1adba28878c2a0b52b782a5c72d9972 create mode 100644 txscript/data/taproot-ref/dbef858a545baf2d110f1d0e917e4ad258acf993 create mode 100644 txscript/data/taproot-ref/dc01bbbcdac6b5bb939e4be9ca56e5b8c3d165af create mode 100644 txscript/data/taproot-ref/dc0806f74a893b88a54642a35cd820535fde3ed1 create mode 100644 txscript/data/taproot-ref/dc161355dcd6047181d0cf4e25b6a5525f6fe50e create mode 100644 txscript/data/taproot-ref/dc3539d6d3a6a1eaf48ce5185a088eb43b9e383e create mode 100644 txscript/data/taproot-ref/dc480267e0ef9ce538b42b77872f2b3532c35322 create mode 100644 txscript/data/taproot-ref/dc57d8ffab2a6632708a04cb288629b09aa5c82e create mode 100644 txscript/data/taproot-ref/dc593bc1e5ac44230400eae2d39c99148ad34e4b create mode 100644 txscript/data/taproot-ref/dc6dcb26e66c42982855aa1a52a31fd33b250e19 create mode 100644 txscript/data/taproot-ref/dc9395f17d85f800578e0d6e8bf89ad9746befb7 create mode 100644 txscript/data/taproot-ref/dc9899ac6fe73116d5e9f16eb5d414386eaf20b6 create mode 100644 txscript/data/taproot-ref/dc99d264d246e0de31744757d56e34f81e69221e create mode 100644 txscript/data/taproot-ref/dca299a0e651d9aa555003ff4a5031f3fccf9743 create mode 100644 txscript/data/taproot-ref/dcaa02212efb1b1d7b35ccd1cd382be6b3e66e71 create mode 100644 txscript/data/taproot-ref/dcbd31842dac9e7cdaf7ca65e510582bfd1d1a9b create mode 100644 txscript/data/taproot-ref/dccaf2fc47adc1a3b05f03d5fac2a95f989db10c create mode 100644 txscript/data/taproot-ref/dccd7c4272928f022003ea9c7aaa12dcc004a54c create mode 100644 txscript/data/taproot-ref/dcd041ba07357566b4ee1ed3cbca6574c6154f10 create mode 100644 txscript/data/taproot-ref/dcf7577a80ecef6f3ca732dc2e3adaa48e682fdb create mode 100644 txscript/data/taproot-ref/dd000d20a2f313c18520373a1f18e05ed9a150e2 create mode 100644 txscript/data/taproot-ref/dd0b6ef4b264cf0858480a3460b856a1c8f6dc1d create mode 100644 txscript/data/taproot-ref/dd51571565035f293d86c40ad779317f87aedf8a create mode 100644 txscript/data/taproot-ref/dd6e129061e453f9a72be030e9baeee3e56fcf0f create mode 100644 txscript/data/taproot-ref/dd8c174c7b3d3ef26b6db13442b39a50c7f55222 create mode 100644 txscript/data/taproot-ref/dda325195c906944f23de872fa78b2af88631c09 create mode 100644 txscript/data/taproot-ref/ddaf37dc11a8574b722f076f36e746bc7c60e215 create mode 100644 txscript/data/taproot-ref/ddd4994f43b538ffca8eb9b28ca5fb499238d0b9 create mode 100644 txscript/data/taproot-ref/dde699e331a7df59bcdada620624b5ba61dc5dd0 create mode 100644 txscript/data/taproot-ref/ddebb704471c13ddfaf31413aae6c013515a3717 create mode 100644 txscript/data/taproot-ref/ddedd372fed9df45da4d1a59cf4f5cb35009e49f create mode 100644 txscript/data/taproot-ref/ddf80ae28fa37fbe9cd6a838ae2c428932ef3961 create mode 100644 txscript/data/taproot-ref/de08cbb895403680951a2ebc90561ac53b1a1f4e create mode 100644 txscript/data/taproot-ref/de2a5caabe3e3b0b1b01533e95ed8f482c6ba0fc create mode 100644 txscript/data/taproot-ref/de4f89a55a6d907d16952ca4e4166a5979c39c8b create mode 100644 txscript/data/taproot-ref/de5a7c1447572e08c6b28e753fe662ac083fd6d1 create mode 100644 txscript/data/taproot-ref/de5adc575b18b1c34a68e95cecf166f402e523ff create mode 100644 txscript/data/taproot-ref/de5af33427175b7548895fa5441e430afe11d1d5 create mode 100644 txscript/data/taproot-ref/de6875a737b7c8020f44b1c99b70c4853e661ecf create mode 100644 txscript/data/taproot-ref/de6cf2f6180404aa31b1db7d09cf2baddd601d44 create mode 100644 txscript/data/taproot-ref/de8a035daf19e89e29ba0bbdd71dffd1f9cadc5c create mode 100644 txscript/data/taproot-ref/dea753eea55e305608844a4f00655549302ce7dd create mode 100644 txscript/data/taproot-ref/decd88daf9600a38bc143777492f37dad4565eaf create mode 100644 txscript/data/taproot-ref/ded66ffb0cbf19f233f516bd3c63fe712650ef33 create mode 100644 txscript/data/taproot-ref/ded72412b30434c168fa06e48b7e054269d006c0 create mode 100644 txscript/data/taproot-ref/dedc75c0c2ee756e9070605ce546167cacfbcaca create mode 100644 txscript/data/taproot-ref/dee101172e339916048ad363fb6995306d7dd142 create mode 100644 txscript/data/taproot-ref/def37ff0a6957f0a571488b66a768f20f7079048 create mode 100644 txscript/data/taproot-ref/def74495863bbdf9d1af666161152708f2ba582d create mode 100644 txscript/data/taproot-ref/df029e9ebb9e83aace8f0071d2840c27c3ceda07 create mode 100644 txscript/data/taproot-ref/df085e9114f63f74c86f24312e70f7b5318ad9fc create mode 100644 txscript/data/taproot-ref/df12a4966bab2fafa4ffe3a2ffbbbe8d697046c2 create mode 100644 txscript/data/taproot-ref/df16a0297efbbe308fa83a0f3e6ad417689b028b create mode 100644 txscript/data/taproot-ref/df865486869273fb5f7adede25fcadcb18ce2221 create mode 100644 txscript/data/taproot-ref/df8de808e45c8839831abd0deb0cabf9143753a4 create mode 100644 txscript/data/taproot-ref/df8e03791d82b6610c2c15664032e32589ea35a8 create mode 100644 txscript/data/taproot-ref/dfa3c5fef1b463d98f523033ec70daf8d4bf8803 create mode 100644 txscript/data/taproot-ref/dfb36ff8904f4e8107d8ba666de3e5f94f741bfe create mode 100644 txscript/data/taproot-ref/dfca4159ab78bba17ae0d77f088b5aaeb3144266 create mode 100644 txscript/data/taproot-ref/dfe3a4307a38993f68b0c2518ea2e3e590b0c9d1 create mode 100644 txscript/data/taproot-ref/e0128963856adfa8520b26e571a93610b5355887 create mode 100644 txscript/data/taproot-ref/e03443f852b194c164bc4732fb9c5cc86effe4f6 create mode 100644 txscript/data/taproot-ref/e0588caa737bfbd960ff3fd219ca062193aa6bf0 create mode 100644 txscript/data/taproot-ref/e0aaba61fbc722b30669314cc389d44b8f989110 create mode 100644 txscript/data/taproot-ref/e0bbbcbab18f481daf5b315491e268254f4983fb create mode 100644 txscript/data/taproot-ref/e0da4e0fe645f0a953ac5735fde4706cca9e1197 create mode 100644 txscript/data/taproot-ref/e0ebae4900e11a9672f2ae78e61178aa6247650c create mode 100644 txscript/data/taproot-ref/e1087672834b43c44e37cba854b5b9c9f7179a84 create mode 100644 txscript/data/taproot-ref/e10bddf4873386e1fe3f6dc0f2b20f5c151c89e1 create mode 100644 txscript/data/taproot-ref/e11d98e0003ce918a6fad19f550ea0702a879911 create mode 100644 txscript/data/taproot-ref/e1326c178bf8e7b80cda8ea9f9dd86938329c849 create mode 100644 txscript/data/taproot-ref/e147111796d5b53a6bf6dc9458c50027b4d09f87 create mode 100644 txscript/data/taproot-ref/e14960a185290ebe95ae6279b9e869e837251710 create mode 100644 txscript/data/taproot-ref/e170c4afc7cf3aa9e0e5c2670686778994fa4f11 create mode 100644 txscript/data/taproot-ref/e184bc711398d7c0c1fa6934192fda6c555a1cb3 create mode 100644 txscript/data/taproot-ref/e1b11848fd01dfa0ba32bf126463d9d364ab4313 create mode 100644 txscript/data/taproot-ref/e1ba585df080f7b1a7f8f2c7db5dd610f19174de create mode 100644 txscript/data/taproot-ref/e1d952db862331ca79b0a9c72c162374fb1857d7 create mode 100644 txscript/data/taproot-ref/e1e49dcfb28496b89f4ea5ce3dc0d76d880076e4 create mode 100644 txscript/data/taproot-ref/e1f0807d7b3a4bba613963e80beb7c74850d5c28 create mode 100644 txscript/data/taproot-ref/e22480aebb82f3343403252198ba68a247b6d046 create mode 100644 txscript/data/taproot-ref/e24851678d123d31e1507cb51348f5b1dc101d4c create mode 100644 txscript/data/taproot-ref/e2496a88dd988d4f3ef82308c3cca33a874d45aa create mode 100644 txscript/data/taproot-ref/e255d1877a2010d7fcfc04ed18a7a010df14a2c0 create mode 100644 txscript/data/taproot-ref/e25fb2f6402ada66247ba900b01f074eb85ba330 create mode 100644 txscript/data/taproot-ref/e279990fd5d183e1d8b4f404ff9bb849d49c365a create mode 100644 txscript/data/taproot-ref/e2d5ca40d2c53fc997406f6b09aab24c3df0d72c create mode 100644 txscript/data/taproot-ref/e2eeef8ece1fd34ca3dc565f6c64e1e27ffe4394 create mode 100644 txscript/data/taproot-ref/e3196566970071a5ddde94e45545b255dbb827b6 create mode 100644 txscript/data/taproot-ref/e31f0de61f44c1cdc4d261d497cf718662ce97d4 create mode 100644 txscript/data/taproot-ref/e3201e6cef5abb4e32884e254d83db6c48c0c98e create mode 100644 txscript/data/taproot-ref/e3588db1c621c20dd15839f0a47a91d2b3a7c779 create mode 100644 txscript/data/taproot-ref/e35adac42c2fa3fac81b5b56415001d9ef213aa9 create mode 100644 txscript/data/taproot-ref/e36c31c772e822a277d29a41f45a505e97121618 create mode 100644 txscript/data/taproot-ref/e37bd80d8483f80595f8de680651a88967e6b765 create mode 100644 txscript/data/taproot-ref/e385046269e21e18e9615b10675db2b779814ea6 create mode 100644 txscript/data/taproot-ref/e3cb84cf87cf0a5a0e394a62331f15e54cde54f5 create mode 100644 txscript/data/taproot-ref/e3e431ac9b495d6b12f584909dd0891e732ef378 create mode 100644 txscript/data/taproot-ref/e3e86951be6edc4911741f8779b8b81f8e19669e create mode 100644 txscript/data/taproot-ref/e3ee89b296eda3cdf6b73af88989c9879d826a5c create mode 100644 txscript/data/taproot-ref/e43e0f4dd6d04ff5cb7feb566ac7effde65eabaf create mode 100644 txscript/data/taproot-ref/e4400ed471cfae79f01e699c1535a927cd7db111 create mode 100644 txscript/data/taproot-ref/e4403314230ec5266c263c14b3167d0495467abb create mode 100644 txscript/data/taproot-ref/e4476c9611f68d7aed1329b54ac787a7dc19d3c1 create mode 100644 txscript/data/taproot-ref/e4549906b6821c9cfd2bdad13fcedc9f2ce44c8f create mode 100644 txscript/data/taproot-ref/e46150bc653c31e407e6428aa1a6ebf50bf84aea create mode 100644 txscript/data/taproot-ref/e4a1dbfb8711c43befec064b8fd396058b0c54af create mode 100644 txscript/data/taproot-ref/e4ac1ef7380b8d2111b6763169a1743b27f8990e create mode 100644 txscript/data/taproot-ref/e4be0b4404267bdc3cff4674612fa0aafae17da8 create mode 100644 txscript/data/taproot-ref/e4ed5b23d5de1068cbbde995bd4acee64e91aa7e create mode 100644 txscript/data/taproot-ref/e4f857e19db4cfd96f2d5054dbf40b5a9e492dff create mode 100644 txscript/data/taproot-ref/e4f9951077eb874d4585b5156eb27d51d2efbfd3 create mode 100644 txscript/data/taproot-ref/e50744f139df817035a18b49f300ba44cb0343d3 create mode 100644 txscript/data/taproot-ref/e50e205a1d18fcdba7e8e5fcee9033cc4707f9c7 create mode 100644 txscript/data/taproot-ref/e52cfe3453de9b1d75444df456949cb75040b8b6 create mode 100644 txscript/data/taproot-ref/e531badf585946f2d8e4ca711ad08bfab23b255d create mode 100644 txscript/data/taproot-ref/e556fbc1cbc098965abc9f19de4e699a65701b97 create mode 100644 txscript/data/taproot-ref/e5a06372794c8a0907ebcab73767cf918aac39aa create mode 100644 txscript/data/taproot-ref/e5c2adb3e9fbf1cd914078ec2a63b5eb9a6e3abe create mode 100644 txscript/data/taproot-ref/e5d4d4aeaf98b811a93af7c9329c6daf9589e991 create mode 100644 txscript/data/taproot-ref/e5d756b155e51281410e56562a664673b0c34fcd create mode 100644 txscript/data/taproot-ref/e60ac2a186190f5f41d0f98adb9107b436491c32 create mode 100644 txscript/data/taproot-ref/e617e275740cca2c1002733c0b62505410149814 create mode 100644 txscript/data/taproot-ref/e62e88a5e5a9d90dbb6072f7ccea09b105b0f310 create mode 100644 txscript/data/taproot-ref/e638e75f42344b0c3f6564246955fb5d040cf293 create mode 100644 txscript/data/taproot-ref/e649d79b9010e5f76ed8c6e317e55e0e91802bac create mode 100644 txscript/data/taproot-ref/e660a993ca6c73039fade4ba3407920ada89923e create mode 100644 txscript/data/taproot-ref/e66bd9898efc98f464bdb5ece0b4f62d602dc737 create mode 100644 txscript/data/taproot-ref/e677ad001a80f4218fcb1f38a8705f1d1caeb999 create mode 100644 txscript/data/taproot-ref/e68c741fb9f3bd4beb774a6295165f0719b15942 create mode 100644 txscript/data/taproot-ref/e69ec7f55ad3c08cfcb37946cda5c9e8bd2f23d4 create mode 100644 txscript/data/taproot-ref/e69f704fabb54c278ef86ba0a840cc8b462fd273 create mode 100644 txscript/data/taproot-ref/e6a0539a6bf9730e9f7197aac29cee83936137c2 create mode 100644 txscript/data/taproot-ref/e6beac0076a3f98639e16833588cb1f7c3630b56 create mode 100644 txscript/data/taproot-ref/e6c4139fc79b0036b50c35d40646356790b47698 create mode 100644 txscript/data/taproot-ref/e6d6a1ae86f60f1e63f309397a0008e6d4943d50 create mode 100644 txscript/data/taproot-ref/e6f3612a73d29882780cefe3d036f68100cf0c7b create mode 100644 txscript/data/taproot-ref/e721205c821d1cfd009e603052b5cee6c677c52a create mode 100644 txscript/data/taproot-ref/e72d5da834d577e08d8919888da3491b1cfc2395 create mode 100644 txscript/data/taproot-ref/e73715f248773b481cfeb2552aceaf18e4b03797 create mode 100644 txscript/data/taproot-ref/e7865be06886b6e888fd9d883d55c5faee586ef4 create mode 100644 txscript/data/taproot-ref/e7a375809c225d5450a212abb59a2046d1b5e007 create mode 100644 txscript/data/taproot-ref/e7c4905ac16a9774e7e810abf68b112d641b2d9e create mode 100644 txscript/data/taproot-ref/e7c5c79c85fb153f7749dd5dcfa97ac1401ef95c create mode 100644 txscript/data/taproot-ref/e7ccede981bb4c65fa47e7fa310a9348a7109ba3 create mode 100644 txscript/data/taproot-ref/e7d9419f6cc1411629e9a09076e350aef3f0adbb create mode 100644 txscript/data/taproot-ref/e7e9f1bdab686670c7fd4b590aaad6feacbbeb73 create mode 100644 txscript/data/taproot-ref/e7fc7fe2e56e39aff52a6c1a3f3ddb20c48651d6 create mode 100644 txscript/data/taproot-ref/e81dc94c8743dc71b11667a65c76c5ef0e8eaef8 create mode 100644 txscript/data/taproot-ref/e81ee8a9a2165602a74cee1bdc447e2da39ab762 create mode 100644 txscript/data/taproot-ref/e84308cd3dc05d65738bf940c73e11c1342f53dd create mode 100644 txscript/data/taproot-ref/e8597fda210c9006c4eb35f55099dd53f0804f47 create mode 100644 txscript/data/taproot-ref/e85ebbbabefe13b277bdb7bb290e81d48aaae843 create mode 100644 txscript/data/taproot-ref/e87e2014a5a0695a3cdffdfe859201eb8beb9fb0 create mode 100644 txscript/data/taproot-ref/e8ac301abd5dee5dd4ef8cb0670844bca13f0323 create mode 100644 txscript/data/taproot-ref/e8de8be751822aa2e8bcf086b89ae6ca68052255 create mode 100644 txscript/data/taproot-ref/e91b8692e5e50d7452d085b3580b9cdd1676e122 create mode 100644 txscript/data/taproot-ref/e93758815f2e92fcae33eeb424961ee124cec2c7 create mode 100644 txscript/data/taproot-ref/e9501001531cf5569b3b23daa63df0825b2e06f3 create mode 100644 txscript/data/taproot-ref/e98353914c5de48ee650dfff9741c1285bf29368 create mode 100644 txscript/data/taproot-ref/e9a85210b1a1018e7666d51f88430bb5d8bfdb3e create mode 100644 txscript/data/taproot-ref/e9b76d10a6eebe9f37aaf17e3c71921c02524b86 create mode 100644 txscript/data/taproot-ref/e9bf6e5a4cbd00e35ecd77dc39c1f9264b9f4dc1 create mode 100644 txscript/data/taproot-ref/e9c730fdf2c5807b82dd1e4d042e404651d4c118 create mode 100644 txscript/data/taproot-ref/e9d4196818fdc0fa92415cb4a2aff1b96c783b8b create mode 100644 txscript/data/taproot-ref/e9dbacbd2e05c550b025911cfa3ca5803dae805e create mode 100644 txscript/data/taproot-ref/e9ddf35ff01ae9bc71730f02a17a6079411fde98 create mode 100644 txscript/data/taproot-ref/ea1fa2cb1864ebe376683d33d94b64f0f54a43dd create mode 100644 txscript/data/taproot-ref/ea224ce2e986d690db2a198af3f98a8408cdb30e create mode 100644 txscript/data/taproot-ref/ea3247c42e38f93b6d8af0e43d7f34cc4bc25070 create mode 100644 txscript/data/taproot-ref/ea3a67eab454450f7603fe0cd98a27c731eb5d00 create mode 100644 txscript/data/taproot-ref/ea3f5822d3ff42dc536ca2f868583167e04fcb24 create mode 100644 txscript/data/taproot-ref/ea9383c734b03a942fd3c33b4cd6172b0c606aeb create mode 100644 txscript/data/taproot-ref/eaa2ec29b35602bac1202162cc43997d10f21ed3 create mode 100644 txscript/data/taproot-ref/eaa7b118760debbe1d5a3d4a62d81d966ab89097 create mode 100644 txscript/data/taproot-ref/eab77792be235dec9f3313676498d907e560b5cc create mode 100644 txscript/data/taproot-ref/eae489d9b326b6e764166ddf53140f5ddb3b425c create mode 100644 txscript/data/taproot-ref/eae7770e2a494f15bf0e76460740c8d2e1cbd22e create mode 100644 txscript/data/taproot-ref/eaee09f4a0e178165105cf2ccf81513fc80541b9 create mode 100644 txscript/data/taproot-ref/eaee80bfbe65037b08eeecc39e40e2b8276a958d create mode 100644 txscript/data/taproot-ref/eb0e20fe944dc77d38b2fc2582d02c80d3d9628f create mode 100644 txscript/data/taproot-ref/eb372b84ca640e23188861d0efa04be45ee5f243 create mode 100644 txscript/data/taproot-ref/eba9b48ee4b2ed1d213ff803ba46409241800f53 create mode 100644 txscript/data/taproot-ref/ebaab3cbf799854c56be5ea1c8570b79e12530d3 create mode 100644 txscript/data/taproot-ref/ec0558d3bd9826dcf5a547231702b26bb029d5b3 create mode 100644 txscript/data/taproot-ref/ec11e48dae90b65ac226a309a6ab974cfc87474a create mode 100644 txscript/data/taproot-ref/ec236a1ba693a15d7cd145cb072b03a9edafd25d create mode 100644 txscript/data/taproot-ref/ec2d9171350303a508d3a35306e1da95e2d45a8c create mode 100644 txscript/data/taproot-ref/ec3dc1b7325240192c1e37e75c29831fa68e98d4 create mode 100644 txscript/data/taproot-ref/ec4c99541792d43b2c11d31a995e9d4e6494735e create mode 100644 txscript/data/taproot-ref/ec5f10d715ff4121c9af8001b65d91bde62f884b create mode 100644 txscript/data/taproot-ref/ec7ac5952f631f170c9cf5ab7afb10a2800e3be7 create mode 100644 txscript/data/taproot-ref/ecc052cec3d69b0b941945fcfee7fcca160fee0f create mode 100644 txscript/data/taproot-ref/ed414b2d37754fddb26883baa6399318c130524f create mode 100644 txscript/data/taproot-ref/ed5648d424b5a21a684d02bc55bdcfab06ec276e create mode 100644 txscript/data/taproot-ref/edb0a385324372442f7d831b7fa747c2a2ba5d40 create mode 100644 txscript/data/taproot-ref/ede245d24c4ccbe651f556667d1de8b18984e6bf create mode 100644 txscript/data/taproot-ref/edf48d71ea536f47f2ebae0ef4c1a54805cfd2bf create mode 100644 txscript/data/taproot-ref/ee216fd86ba1f2f2eecc6892dba069f1fa7e2566 create mode 100644 txscript/data/taproot-ref/ee227dd2c697b5ad500c732edea24bd9f2ec08a7 create mode 100644 txscript/data/taproot-ref/ee39d37f93b56b4c318cb83ca60e411ee5c1abbb create mode 100644 txscript/data/taproot-ref/ee4391649d8b6cf1ed2a18eef419b54a19d2f481 create mode 100644 txscript/data/taproot-ref/ee4b75d279f94af5208664797cc453ca45044806 create mode 100644 txscript/data/taproot-ref/ee537050d4b74465e99c77d79aec50879344edb4 create mode 100644 txscript/data/taproot-ref/ee666d81fc0411dbdbf38406d49ba05685bee495 create mode 100644 txscript/data/taproot-ref/ee92d4d96303e7296f561d5b3efe262b3993bc85 create mode 100644 txscript/data/taproot-ref/eeb6e1a4eebe04ce7814c38efaf8b5b7e910296f create mode 100644 txscript/data/taproot-ref/eef8d1a1e8c3a9566015b3ae089052a50d3c3ddb create mode 100644 txscript/data/taproot-ref/ef1b9627be8307d947f73d84910a2d343187898a create mode 100644 txscript/data/taproot-ref/ef34d2a06ed043b1d7aa5c55d07e649a98e022d0 create mode 100644 txscript/data/taproot-ref/ef5018ccc4d868e150c22f85faea02a352f124d9 create mode 100644 txscript/data/taproot-ref/ef588660a2f4df9f52c4f476036ae92b435dd8be create mode 100644 txscript/data/taproot-ref/ef7b84160b7025ab4d29b8bb32de27500874c4e0 create mode 100644 txscript/data/taproot-ref/efab9adce18cdbdd285db520ec08c755b0916a2f create mode 100644 txscript/data/taproot-ref/efb25951d890dbd071c4a3811042fdb8e0bc4326 create mode 100644 txscript/data/taproot-ref/efb757b9644c060f72a7441ae9f0dbb05935ddee create mode 100644 txscript/data/taproot-ref/efbdf30300adcc55d7c50d4ec76a75496d6d7b7d create mode 100644 txscript/data/taproot-ref/efc4b323ebe3c0b9e2f2fd7168ab4437570a54e8 create mode 100644 txscript/data/taproot-ref/efce2a5687afc47a9a7951b0d14a86559eccd8af create mode 100644 txscript/data/taproot-ref/f00c95582e31d9827eabb236ee8b4b776907a667 create mode 100644 txscript/data/taproot-ref/f015ec4058e4e7ae0d1a64823882e2e3fe9f8bbd create mode 100644 txscript/data/taproot-ref/f04d521c21ed8372ae0bcf98ee15b6ca83c85bc2 create mode 100644 txscript/data/taproot-ref/f052250556f0a305782ffc367c106bf8213e5199 create mode 100644 txscript/data/taproot-ref/f0b8804a6b3fa0ab08fb2e07758480377e212f0b create mode 100644 txscript/data/taproot-ref/f0f31b265d33a5adb67af2f1fec8248f8855469e create mode 100644 txscript/data/taproot-ref/f111543d0f442f268353dbbbf00ebe24c21f930e create mode 100644 txscript/data/taproot-ref/f1439b2e5f242df93c3d5fd61e367f850098495b create mode 100644 txscript/data/taproot-ref/f150268fcc20d8c1e1607d773fe9c2af148e9e8e create mode 100644 txscript/data/taproot-ref/f1728d0e4771e35b1cb1998adc82e22eb67a65c9 create mode 100644 txscript/data/taproot-ref/f172e0269b4ce4678ade6f0ac95a9448d2453792 create mode 100644 txscript/data/taproot-ref/f17ba688055f4e28c6c763a1a67b55ffd27ab22b create mode 100644 txscript/data/taproot-ref/f18786606f38657d15f1d007fa2934ea6034a605 create mode 100644 txscript/data/taproot-ref/f1ab87a390b003a1f262909e41e5d3853c0dee70 create mode 100644 txscript/data/taproot-ref/f1ac308d98f3a982e3c86ebf022541b3c7a53857 create mode 100644 txscript/data/taproot-ref/f1b42b68e02cd3503158c2cedbad9f43b4a782fc create mode 100644 txscript/data/taproot-ref/f1b9e75c583d069af4d354379ec7cbf02e95c41d create mode 100644 txscript/data/taproot-ref/f1cfa6ecbcc68ba081804e6b531a970f6cc70cee create mode 100644 txscript/data/taproot-ref/f1d42d84bf3c0ea75c9ac6babfdb06afac572bfa create mode 100644 txscript/data/taproot-ref/f1e479e1e2ba063168c4201bc568c60b601c98f8 create mode 100644 txscript/data/taproot-ref/f20f49c8c8a09c2b68a66d3640886588c1e95299 create mode 100644 txscript/data/taproot-ref/f281cfc9b564fceae1f18905886e1a2ea6a79f8f create mode 100644 txscript/data/taproot-ref/f29cde4e4d18f502a83e953d7e6aafc162b49fb0 create mode 100644 txscript/data/taproot-ref/f2a7b6785e4184b100bb118d537c3e1fe7deed13 create mode 100644 txscript/data/taproot-ref/f2aed5fc63d1322cbfa59dc10fc63c5c13905bad create mode 100644 txscript/data/taproot-ref/f2b01b12b747c63ff84c1d178f5cd881a09d61d3 create mode 100644 txscript/data/taproot-ref/f2cf8fc04a84276827038c4814930bd1166dcb83 create mode 100644 txscript/data/taproot-ref/f306f010650c1ce3662a988f2d5c8848a114b742 create mode 100644 txscript/data/taproot-ref/f311f3194f27d91bd26c7ac20214d331ade7f1c9 create mode 100644 txscript/data/taproot-ref/f32541dee791305368453ac147924b5c2d9dfff7 create mode 100644 txscript/data/taproot-ref/f34aa9739565ceed4d2a67fa8e24e1cffda032d0 create mode 100644 txscript/data/taproot-ref/f36797074db1a3316cf9f79b8cedbea196a94883 create mode 100644 txscript/data/taproot-ref/f3a1124f0e210f773fcb446a4c6325838f796dcd create mode 100644 txscript/data/taproot-ref/f3abe34a0b2b561230223ebd55fa58c1abfa4752 create mode 100644 txscript/data/taproot-ref/f3aefeaaf417737c9b08ddb588ac8f34f1bfd7c0 create mode 100644 txscript/data/taproot-ref/f3b9a054bd33583afbecffad0407dcd117b60cb8 create mode 100644 txscript/data/taproot-ref/f3c37d9c9bc7bbacd5acc05ecfa2dd6b3e4079be create mode 100644 txscript/data/taproot-ref/f3dbd1cd81a692630c41a036e51a108069161d76 create mode 100644 txscript/data/taproot-ref/f41b245dc4b63227dcd52bf8df204c69ef2c632d create mode 100644 txscript/data/taproot-ref/f43a467e1ed501e4fae97b23c7ac5f51943b4a60 create mode 100644 txscript/data/taproot-ref/f4466a6264c406cffaf61cd062c6954b8145b827 create mode 100644 txscript/data/taproot-ref/f45bfc326aa2978cf872bbd25ac92e74c51b222c create mode 100644 txscript/data/taproot-ref/f4604f24ef1262cff35502c140d3a3ab09e62650 create mode 100644 txscript/data/taproot-ref/f47e1dd86121d4d47b5e315b8bc8f941d5c890ba create mode 100644 txscript/data/taproot-ref/f49204f8e85d64be3490b7843476939194bca10c create mode 100644 txscript/data/taproot-ref/f4cc235e3a3e0f11b34f866c952d52ba470ce96c create mode 100644 txscript/data/taproot-ref/f4e60bca3a955a55d00e4186db841023ceef4e20 create mode 100644 txscript/data/taproot-ref/f50995c18b1bea7d6e8f78c8db8139687517a781 create mode 100644 txscript/data/taproot-ref/f50bbc9cda906042a1e0c756df37b20c36a36df6 create mode 100644 txscript/data/taproot-ref/f54e6bed090f658f483733605be1def47c4a00f1 create mode 100644 txscript/data/taproot-ref/f5584e332423dfd006828addcbd73f040328b087 create mode 100644 txscript/data/taproot-ref/f558bde45b06e08703659c22eb17a9b25f4941d1 create mode 100644 txscript/data/taproot-ref/f560ba3291103bb7f5cc015586c6946d5f9e8857 create mode 100644 txscript/data/taproot-ref/f58c6d8117f18e36e7e31efdf23c18aea2a31b7c create mode 100644 txscript/data/taproot-ref/f5a0c3cda376e7bd8f7a27caa053bef8617f451b create mode 100644 txscript/data/taproot-ref/f5a0cbe081c8037a7f36d438e758b6bcd92abcbc create mode 100644 txscript/data/taproot-ref/f5a7ff2dc8ee9ec1ef36b73c60de71d7978d3d27 create mode 100644 txscript/data/taproot-ref/f5b5807a9afa7c7b8351abe9a32cdd85d696c15e create mode 100644 txscript/data/taproot-ref/f5bbca8f5a7339d3dab2b5f758f426cdb744dd6d create mode 100644 txscript/data/taproot-ref/f5bcbe0530388a9d1b0ddeb9fd52bbf9553589c1 create mode 100644 txscript/data/taproot-ref/f5d29c01f03e55e2269af62ed6364a98353003af create mode 100644 txscript/data/taproot-ref/f5d9f6f2aa6f7e44a24ecb63e2ccbe34ba6eecfe create mode 100644 txscript/data/taproot-ref/f5f01b555c46d9d86c043b50cdf0dc05ea4c3d08 create mode 100644 txscript/data/taproot-ref/f5f4bc663f8ff671a51d503c89c7a5659c0c37ab create mode 100644 txscript/data/taproot-ref/f614cb3aadb14fc4cea6a3fa949cf1c4a5aa490a create mode 100644 txscript/data/taproot-ref/f62efd7cbffa78cde24f12d7daf90b120c6b3e5f create mode 100644 txscript/data/taproot-ref/f6389882692a6a18e427b73ca3a0a34f645e476b create mode 100644 txscript/data/taproot-ref/f63afc3910d5b449d7d26586af8681218677fd6d create mode 100644 txscript/data/taproot-ref/f64c19e45d11b07f585d65dd6f72bcd502d95a0a create mode 100644 txscript/data/taproot-ref/f6514adef6dcf766ba7179320ec6c88126688614 create mode 100644 txscript/data/taproot-ref/f6765d4b30feb17d15d4bd81601ea5788d8d26ed create mode 100644 txscript/data/taproot-ref/f678ee4a403b466dde13be7e941db7ff7684a932 create mode 100644 txscript/data/taproot-ref/f67b572dbad35568f4ec9ba53cafa2997991340e create mode 100644 txscript/data/taproot-ref/f6840c641bb58cad923fc4f9c092164413ff4ce6 create mode 100644 txscript/data/taproot-ref/f6907b785c509927b03981052c87de1c9ae5f772 create mode 100644 txscript/data/taproot-ref/f69458974b285f9c2ac48a1bd10b3dff2d042a8d create mode 100644 txscript/data/taproot-ref/f6a06f14f3641278ceae3733db1a7eff71fb3629 create mode 100644 txscript/data/taproot-ref/f6c823a2b3203faddc06a15a61e6f0e3f3e7fe8e create mode 100644 txscript/data/taproot-ref/f6d3771166a0c4e00527b2be21466030fb499521 create mode 100644 txscript/data/taproot-ref/f6d618ef7f588f9fc237b18f4ad42a84337ec67e create mode 100644 txscript/data/taproot-ref/f6e85bce5c033f269bbb51eb480ff58e9d814ed5 create mode 100644 txscript/data/taproot-ref/f6f146c32b1b724af896fdd11df580e1dc8f0e35 create mode 100644 txscript/data/taproot-ref/f70b704bb277d70481b756371e4d92b9dadb2d85 create mode 100644 txscript/data/taproot-ref/f747e1181b2e9303715bc0aea1cfca3babf00705 create mode 100644 txscript/data/taproot-ref/f75c71bf10464658e79f72142b2c327cd6ca3347 create mode 100644 txscript/data/taproot-ref/f77abd655150de8bda3b775fd291d5b2bf27a1e6 create mode 100644 txscript/data/taproot-ref/f77e7d751660a7149e80488c8245aeb9be6eeb1d create mode 100644 txscript/data/taproot-ref/f796e5b0c5ce67017c553a21907fd6a51a1058eb create mode 100644 txscript/data/taproot-ref/f798f952feda25e6fc4b37a429dc368f73d0d158 create mode 100644 txscript/data/taproot-ref/f7a5375d5d273e7eda804ac9335745a3fcc568ae create mode 100644 txscript/data/taproot-ref/f7ab44a4e73a9b24bfff6a263c608abce5696639 create mode 100644 txscript/data/taproot-ref/f7b76430a96ffa6355eaf12167d0ef405e2669d8 create mode 100644 txscript/data/taproot-ref/f7bc805d350c55cd8e24def5b79ca3b2fe88ae80 create mode 100644 txscript/data/taproot-ref/f7c02de0b4f89c043a3ebcb28bcb0e1396fe0e23 create mode 100644 txscript/data/taproot-ref/f7c0db2c2ed3c1e6f19acace4e10c0a99df88018 create mode 100644 txscript/data/taproot-ref/f7dad92963bb917f67c0a5d9a11c7a623157603e create mode 100644 txscript/data/taproot-ref/f7e399c76d4ec4bad55a5e054f90aaefbbefd54a create mode 100644 txscript/data/taproot-ref/f7eb97d1c42b9d53be75b54f5a30490ace43fa77 create mode 100644 txscript/data/taproot-ref/f7f77a67d9bea0dcf7942ed62f29985930122ff0 create mode 100644 txscript/data/taproot-ref/f803ece8ba109526994448413d0b5389e89fec0b create mode 100644 txscript/data/taproot-ref/f808813d157995b8d10c3cffd1f2616528fdad1f create mode 100644 txscript/data/taproot-ref/f8136e4e492396052082b2d3eb7f45ce735b580e create mode 100644 txscript/data/taproot-ref/f82150120ceb9a7b6d24c8144a2fc40fca6c7ded create mode 100644 txscript/data/taproot-ref/f846835025106a0f7d7d18630b87f4321e626835 create mode 100644 txscript/data/taproot-ref/f84d4edb22fee2109b5e00fd5ac471e49c15e25c create mode 100644 txscript/data/taproot-ref/f86da2aa3ec8718d5308b84e38864225dfeb6819 create mode 100644 txscript/data/taproot-ref/f880da185f238333598d20ee2e139229db739f94 create mode 100644 txscript/data/taproot-ref/f881895a273c1bb8b76313a9f0ff65520ad27975 create mode 100644 txscript/data/taproot-ref/f8835febdb55dca918a36795f2203f4ee4a6b841 create mode 100644 txscript/data/taproot-ref/f8930f55c55efa927ccec4a3a273d7af679fe190 create mode 100644 txscript/data/taproot-ref/f8d8d11d95153ea9449df09e90a108d0d46dd36a create mode 100644 txscript/data/taproot-ref/f8e2668d6408cd99bb9b4144dccc869b5b5c3995 create mode 100644 txscript/data/taproot-ref/f8f8928329f1f5ae3c966fb5ec2113e076eafcfe create mode 100644 txscript/data/taproot-ref/f8f9451ddef15046ebb34b8ada8344e100e77c6b create mode 100644 txscript/data/taproot-ref/f90c809fa2d5593e55f0033ebff4eb6de3bf7a4d create mode 100644 txscript/data/taproot-ref/f92ae6d39d23d890f0a4bbb1700628cf97bfd5a6 create mode 100644 txscript/data/taproot-ref/f92ff19d417dd30243bf0048d8947d33b4bf7064 create mode 100644 txscript/data/taproot-ref/f950057a3fe68206273e224b1a0c92d75bf4cffd create mode 100644 txscript/data/taproot-ref/f9527f53e0c01295c939d322769c4900690eac47 create mode 100644 txscript/data/taproot-ref/f953c76798af4534303b789774638f6750bf064f create mode 100644 txscript/data/taproot-ref/f95a0a2fc49acea853b2fa634e154189153c8e19 create mode 100644 txscript/data/taproot-ref/f9ae968bede9072e9913f275110691863b21d704 create mode 100644 txscript/data/taproot-ref/f9e9604adf8a8fa70a8a2d8699243ba825c4c268 create mode 100644 txscript/data/taproot-ref/f9f75f9ba55d66c16536a85bc2406112ffaef2ff create mode 100644 txscript/data/taproot-ref/f9fc9e2a4f2af623fc883937402f30bb39d7194c create mode 100644 txscript/data/taproot-ref/f9fe421cb9a3952dc45c8d26a7ddd2f53b952533 create mode 100644 txscript/data/taproot-ref/fa167d1943fe2df543ef85cf25a11984cbd5a5a2 create mode 100644 txscript/data/taproot-ref/fa18264203439b69d71bc0bf47eb42c09a0276b5 create mode 100644 txscript/data/taproot-ref/fa2f957cce50a9e152ca7a429346901042de9fc5 create mode 100644 txscript/data/taproot-ref/fa49e364b5b789a639515d469e423d52b4437393 create mode 100644 txscript/data/taproot-ref/fa4c5cdf26645ea0534a498e6eed0980cfb7a7c8 create mode 100644 txscript/data/taproot-ref/fa597ee663f096b76cd93b293bc4d7f7aaefc262 create mode 100644 txscript/data/taproot-ref/fa5f468e5077c7552905d4b235d938ba656a8956 create mode 100644 txscript/data/taproot-ref/fa6ab5df5a5d808c4d736244d69510fa6e17f904 create mode 100644 txscript/data/taproot-ref/fa7d0a81564418a5df2eae24548c51be6486a4aa create mode 100644 txscript/data/taproot-ref/fa862d772ea0c551e8a2b2e955c3a314343a9249 create mode 100644 txscript/data/taproot-ref/fa8814b8ee8c8c0b59933c5df3e62bc70882f43c create mode 100644 txscript/data/taproot-ref/fa90b9f27b4ef61835f27c23a72f15ab0bc2f8d4 create mode 100644 txscript/data/taproot-ref/fab23300d1e8e0ac77217a22517738b6de5afead create mode 100644 txscript/data/taproot-ref/fac25d9ab05e1c85b45aa41798674daebf462237 create mode 100644 txscript/data/taproot-ref/fad3ceab7d42e3ad2e07e8e88420e42ecf4dd0b8 create mode 100644 txscript/data/taproot-ref/fae57409d88f4b4a8521c3bbd0560991c2a8986b create mode 100644 txscript/data/taproot-ref/fb0c60f40b98f2127746a9a359165bc8d41dcb8c create mode 100644 txscript/data/taproot-ref/fb18611c9ee4a416896469762bdeb28572310087 create mode 100644 txscript/data/taproot-ref/fb193ee81245f14d9b19cacbf56cbcb01dec02be create mode 100644 txscript/data/taproot-ref/fb3a40b01dd182dc32fd94d86be6aeec9cfda7dc create mode 100644 txscript/data/taproot-ref/fb3feed4650211ed4fd84c29e022288219979e4a create mode 100644 txscript/data/taproot-ref/fb47b82833fbb82a6a9844bcfa75012bfc49c9cf create mode 100644 txscript/data/taproot-ref/fb56305966435f548db004e141dd614dcb71150d create mode 100644 txscript/data/taproot-ref/fb6bbbb8192f592ebde7d1bb37924cade63c96c8 create mode 100644 txscript/data/taproot-ref/fb803c7f3034af611f6dd19c6cd55245f319dd86 create mode 100644 txscript/data/taproot-ref/fb84f0eaf5bbab71df0de66b8e502f2e52604fac create mode 100644 txscript/data/taproot-ref/fb964d7fe5e195fa98766d8c4058c8258646e95a create mode 100644 txscript/data/taproot-ref/fb9e6ec52fad74ca4a775818f110ba219adaadbb create mode 100644 txscript/data/taproot-ref/fba8bb171f6333a2f8f8099ed7061ca7507012bc create mode 100644 txscript/data/taproot-ref/fbae541afc8fd2842b660a15ba61db2dbd26dca5 create mode 100644 txscript/data/taproot-ref/fbd1df6484bc96485135c2b29c3b125355c62848 create mode 100644 txscript/data/taproot-ref/fbeb89304a55a7ab8a338b807ad02b8dd2ab9c28 create mode 100644 txscript/data/taproot-ref/fc1908d2145aa6f1cf830f6aeb9bf24470454805 create mode 100644 txscript/data/taproot-ref/fc6ad6441d0d3ba1260efa94e68b4af0576bf63f create mode 100644 txscript/data/taproot-ref/fc6e7fbd1048ad4d4f9eadb18d79a7ddaddee244 create mode 100644 txscript/data/taproot-ref/fc72b1ff88ff0bb9a8e7a27d860b1e727bc825b0 create mode 100644 txscript/data/taproot-ref/fc833899bb452572fe6f3e84efd6737cca4eb786 create mode 100644 txscript/data/taproot-ref/fc9c2ac36745e20f981008bf5f85f146b9c9dbb1 create mode 100644 txscript/data/taproot-ref/fcc3f72c08a026d3c0f4cc50227793a26fc3efeb create mode 100644 txscript/data/taproot-ref/fcd03d953e3452f116e4035d2029de953e62334d create mode 100644 txscript/data/taproot-ref/fcd91aa7ad2c0011f8f2516f5687f9e91aa76b71 create mode 100644 txscript/data/taproot-ref/fcda2ec36cb7652d368098a0c2ac64665164601f create mode 100644 txscript/data/taproot-ref/fd03276208dbd6219a958f47d888d22fa303e89e create mode 100644 txscript/data/taproot-ref/fd14286e8c496b3f62dea79de42d57a7b02b22fc create mode 100644 txscript/data/taproot-ref/fd1a057fd69f2113eeeafc133d9d51c7cded9125 create mode 100644 txscript/data/taproot-ref/fd1c6cdb67bcc23e0920c0b2724591695d7e88b1 create mode 100644 txscript/data/taproot-ref/fd1d4fb758440d51c0db63f8a401ad4f7dd1ba6d create mode 100644 txscript/data/taproot-ref/fd1f6bb68c1a0317e7fb3e9c65ce2b765717f38f create mode 100644 txscript/data/taproot-ref/fd275d920066468018b3ec78708e01bbf4634f89 create mode 100644 txscript/data/taproot-ref/fd30d1fabe3c70d63ebf6eb08fcc889f2062dd96 create mode 100644 txscript/data/taproot-ref/fd4b486776c7fc4e964a57db37f46b6fb893446f create mode 100644 txscript/data/taproot-ref/fde4e348195fef4158d57bce09b8132261e53404 create mode 100644 txscript/data/taproot-ref/fe3a254545ba65877f7f12c1957e6983a9540725 create mode 100644 txscript/data/taproot-ref/fe4991f96a4078203ed82f3dc9d57b0f5c8d7c31 create mode 100644 txscript/data/taproot-ref/fe5a94896e814e80a5d4f0d17825ea303d136807 create mode 100644 txscript/data/taproot-ref/fe754dfb4207b538736ac33f4d6d3a8b39ed7eb8 create mode 100644 txscript/data/taproot-ref/fe8a403b551fce23551c1a364c5d7a9bdf4082b4 create mode 100644 txscript/data/taproot-ref/fead4cb9efe769ed34fc79a6f7f7c301fa44b950 create mode 100644 txscript/data/taproot-ref/fec0428a7d5b4dd2f894abbef22a4fd55b125e79 create mode 100644 txscript/data/taproot-ref/fed7b4e8b0ffa8ba7ee920409e365993f8f23423 create mode 100644 txscript/data/taproot-ref/ff02cab52406b52d736534063539b815a83e9ec9 create mode 100644 txscript/data/taproot-ref/ff0c9a3fa047cac34488cf6902e39ceb0b31a1f2 create mode 100644 txscript/data/taproot-ref/ff0ecc250f060fadb2dfbc788f027f6c46ef6c40 create mode 100644 txscript/data/taproot-ref/ff269c4192d92ee1330ca6cb368ffaf3dec65d44 create mode 100644 txscript/data/taproot-ref/ffba9a51f35e6cfeb9726e3eb3551989a55a2ab6 create mode 100644 txscript/data/taproot-ref/ffbfc4371313a95615a944ca1fb473bf2569d7aa create mode 100644 txscript/data/taproot-ref/ffc6076c34629ad5d440389f97bac8efcd2db5b7 diff --git a/txscript/data/taproot-ref/003af31dd0b5a50c2723531e8ca22ae8ca6e7089 b/txscript/data/taproot-ref/003af31dd0b5a50c2723531e8ca22ae8ca6e7089 new file mode 100644 index 0000000000..eaf08ab3d2 --- /dev/null +++ b/txscript/data/taproot-ref/003af31dd0b5a50c2723531e8ca22ae8ca6e7089 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff2000000001c75619cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4900000000cff75994dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b07010000003c029216047236f3000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8784d7ee4b", "prevouts": ["ac7783000000000017a91408247b8d3db4e641d0be1ff23f14280256870a5187", "06404d000000000017a914b60a534933f6e50f3846e396b9868efc9e681f4187", "4408250000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["b51b9ccaaea9fd42c652f402c720f9204800e00b2f8ae4766b7fcfa164231fc81d8a8900ca86e7a871b94e86ceded7cff43db52b7ae760520079a117b3a2a562", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/005e61a50014d33f7309097490534db3c0dc65fe b/txscript/data/taproot-ref/005e61a50014d33f7309097490534db3c0dc65fe new file mode 100644 index 0000000000..8fcc5b4a8f --- /dev/null +++ b/txscript/data/taproot-ref/005e61a50014d33f7309097490534db3c0dc65fe @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708900000000676b3469dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2101000000e54ad34c04af0b30000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6f000000", "prevouts": ["d015120000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "65ee200000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d14c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4595f1c75585029ef5fafe40c7b455be7b6317879deb123e683907f6588babc52172c8da9bdd43b70cbab8912ef1aa7926e5ad7e47a4f7b71ac936200cc947dd0f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93657385cfb449c384dd2171856b934522ab5b17115bbddd9e3700a77caba093451595f1c75585029ef5fafe40c7b455be7b6317879deb123e683907f6588babc52172c8da9bdd43b70cbab8912ef1aa7926e5ad7e47a4f7b71ac936200cc947dd0f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}}, diff --git a/txscript/data/taproot-ref/007f313a1a53428b7fc9eaf54c5d51be20e10567 b/txscript/data/taproot-ref/007f313a1a53428b7fc9eaf54c5d51be20e10567 new file mode 100644 index 0000000000..450f5ca486 --- /dev/null +++ b/txscript/data/taproot-ref/007f313a1a53428b7fc9eaf54c5d51be20e10567 @@ -0,0 +1 @@ +{"tx": "52c12c3202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7d0100000055114ebadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd000000000a78541e802e64d970000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898705010000", "prevouts": ["7bdf770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bd21210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_66", "final": true, "success": {"scriptSig": "", "witness": ["2873c80a655850b5bd310a9138328c6fb8f178aecd4dcc016b1823c70f5f02815d8459ecfb1535ba7bf4d426415fa68706072eddc5d75fef76e4fda1f5471aa502", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0d0c8b2aca5e7e7a075e04f6084617cef72dd5f6b2783aba1f9c36cfda42550581d4ebde5a11d7298919cb5c9142b366abb51f60f87ea0e7bbec8cacb393de1466", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/00850c1cc564bd0dcbb02c3398f9fc8e0219a317 b/txscript/data/taproot-ref/00850c1cc564bd0dcbb02c3398f9fc8e0219a317 new file mode 100644 index 0000000000..4bd862308b --- /dev/null +++ b/txscript/data/taproot-ref/00850c1cc564bd0dcbb02c3398f9fc8e0219a317 @@ -0,0 +1 @@ +{"tx": "1bbfd49402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd3010000009d9e899b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a701000000e3abf6f202e8b091000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487859f2c25", "prevouts": ["b31c5d00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970", "5ffc3600000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "417d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936571460ba76479f128232c1e7f3cb97430b20436d33add020c19a42e032587e00ebfb5abead622ee588f8a14df4b864e849bfb1ffa426a7f0fc441a7ea7f9f3e8819e00a9246c8c145cff8a91ff4546d478c6c8e3d7b4e3f7e61102a4388494af"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d0254c28ec270bdf41d4337856af66ad3dc8a43a5d3e633735369ec57cf2fec9da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e53f01d9cbc4ce44e53bf46e342c1ac713c14ac9ff1cc3e88a31c5570fba253bd819e00a9246c8c145cff8a91ff4546d478c6c8e3d7b4e3f7e61102a4388494af"]}}, diff --git a/txscript/data/taproot-ref/0089a0f18b0647cf2bfae0c93e9ae39b345d1611 b/txscript/data/taproot-ref/0089a0f18b0647cf2bfae0c93e9ae39b345d1611 new file mode 100644 index 0000000000..15ad8f6e7c --- /dev/null +++ b/txscript/data/taproot-ref/0089a0f18b0647cf2bfae0c93e9ae39b345d1611 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702601000000580e63a5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5101000000d93ed2df03842435000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac1f000000", "prevouts": ["d487110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "eaea250000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_13", "final": true, "success": {"scriptSig": "", "witness": ["a563b69b91fd5fbe809f3b3a2b7353746f928a30dbfbc8f9ef9328112b7381a6d9b12f9857e1231a5c4b1f16b62d8893c252e110cfb4d46e597de5a8da01753301", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["80ad3c0a699a9ba01ad512740ee0bd865d10f471c737d33e38b443e3e4c72bc9a8df15660ab01897c052d8cf1ce2b7d78c5084b05ac163da8e251bfcd7e5990e13", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/00b6fe5a14ee4fb3bb65e0aa28e70cb57f0cd0b0 b/txscript/data/taproot-ref/00b6fe5a14ee4fb3bb65e0aa28e70cb57f0cd0b0 new file mode 100644 index 0000000000..38da643ee8 --- /dev/null +++ b/txscript/data/taproot-ref/00b6fe5a14ee4fb3bb65e0aa28e70cb57f0cd0b0 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4e01000000192acd32dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbd000000000851923c0387ee7a00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a632000000", "prevouts": ["a0f6280000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "d6ad540000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "4a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364758c64267c751cdb3a7d0ad4e97f82b7320c0de5dc96a77478bcc9a1aac62dfb1956d2c402f72d86d9128969f4c9ed8db93dfb826b4075483e7d557b0e234b512efaba1d06903f148d2465ca4e4c6639d336576fa6993c6ca48823372648a44"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e696e0a39b8006d5c38246735bc900624bc412e796f8d634640137370e1472505749e2a390543356cdb3691ba8d54627dfb45f7f1132e94c1a4e909f84f1614c2"]}}, diff --git a/txscript/data/taproot-ref/00cd1f1ac746e81ae27bfe1e9a383975d0bba949 b/txscript/data/taproot-ref/00cd1f1ac746e81ae27bfe1e9a383975d0bba949 new file mode 100644 index 0000000000..11e29497db --- /dev/null +++ b/txscript/data/taproot-ref/00cd1f1ac746e81ae27bfe1e9a383975d0bba949 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4eb01000000db6b973760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706401000000f98306f1010fe10c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a648000000", "prevouts": ["3f4243000000000017a91448274ba0d73ec00ce63e7922c9d87a48fd0c670f87", "04e712000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2251202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["151ed1a80e83ef2261d0a7c9cf17ed67c9b014c7f910704afdb6093f8b026fb75e65866fd39c79345c43e8ad7b7e53a111c9dd225afc4285c89b88021c930daf"]}}, diff --git a/txscript/data/taproot-ref/00d07d91c86c11dbbd14f4edf55c1f496ffaf010 b/txscript/data/taproot-ref/00d07d91c86c11dbbd14f4edf55c1f496ffaf010 new file mode 100644 index 0000000000..0ff6096c63 --- /dev/null +++ b/txscript/data/taproot-ref/00d07d91c86c11dbbd14f4edf55c1f496ffaf010 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1602000000be453d33dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4c000000008b83fd6a01858b58000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748705000000", "prevouts": ["e5325d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0268220000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_44", "final": true, "success": {"scriptSig": "", "witness": ["5bfb6605b25e0f6ea070cfddf827a224bc97bcd06c1acfc9328820914bba2d40ff72c23c0a0ac77abd8935b0bdcfc2e6255fad23b88836e5bff973e3748ddfb901", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0b0f6c4a9358db9fd237d6fa5af7f7285f4a369c3840533a090b1f5a8b1af295dc7ac91983312a9135f919ca281fd49d2623c2d21edec613e3f28e455bd072f644", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/00dc037c98e799a31facfab68fce3187ad7a0f68 b/txscript/data/taproot-ref/00dc037c98e799a31facfab68fce3187ad7a0f68 new file mode 100644 index 0000000000..aec63fb04c --- /dev/null +++ b/txscript/data/taproot-ref/00dc037c98e799a31facfab68fce3187ad7a0f68 @@ -0,0 +1 @@ +{"tx": "e4ec8ca402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0801000000348e6ddadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b190100000032c930c80498cd6f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8700000000", "prevouts": ["3514520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "71481f00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_9a", "final": true, "success": {"scriptSig": "", "witness": ["475a10bbf8ea5fc324ca213076229310193f2c0dd1dccf1ddd0de8d7ddbbc4c079edce55ab860161adf2a15e2a9c25e0a9d6f720ca0a39fcb8cdb66791f51fbd83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0833d13eb5c92b0f6cce1e5f769d946aa53bcbca9c443ee94dc4c3499027323b06d0d7dd0f6c2b2fbb3a37c0e034e083ae7cdf86975eb2eba1078a7ade4558849a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/00e2723c3cce5d6fa2b7db987e5fbc1d75297650 b/txscript/data/taproot-ref/00e2723c3cce5d6fa2b7db987e5fbc1d75297650 new file mode 100644 index 0000000000..82055ad5cf --- /dev/null +++ b/txscript/data/taproot-ref/00e2723c3cce5d6fa2b7db987e5fbc1d75297650 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cde010000000845aabfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9300000000e34899db029dd8b10000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87a5030000", "prevouts": ["4f865d000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "302c5600000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "0f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f550d8843d52ee2b366c31e2565bf158a1473c8f129a11bc7b0dcff887ae948c29bd03bbcbebf503f24139d653052e63a9a9f3faf73bed4a74eee576514948d11491142a38ebb10a24e36aadbe0cf227dedfd0966bcf56b2aea8b33dc3fd67f"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a041bf56b75b4d6888b8caace1d183294aa04f1728740594947390d0dd0c8936f8d113c18817a044fae8525416b35b4656d6d7185568187de608cafb5211e2f68491001e36edf91058819766439c3f31bd198abbe3d2204f458ac7743e1d61ccf16a5e3db9e2b81c974405e52c4661efcc91a529144e47e78be5814d4a09901"]}}, diff --git a/txscript/data/taproot-ref/00eb1a2b8aed4a406ee59371fa0a50e6679857c1 b/txscript/data/taproot-ref/00eb1a2b8aed4a406ee59371fa0a50e6679857c1 new file mode 100644 index 0000000000..234afd5dc5 --- /dev/null +++ b/txscript/data/taproot-ref/00eb1a2b8aed4a406ee59371fa0a50e6679857c1 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a101000000803b90c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b990100000075a93d6802b1c933000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc772010000", "prevouts": ["139c1100000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "5f092400000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f54c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bdcbe75f074483e48d717af2cfa8ab1bbef1c35fc84f016c108dd10256d535ae10b3b87e8b9d8544644738d4851bae032b2bf37d3a4aa6541b936ff18c715610c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}, "failure": {"scriptSig": "", "witness": ["4c52f5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e13fb7770917eb0311339f7797b42ae31badf39be5fac652227efb4e28a80f4e35f46b3ac3e0eb552c07a1c6336d6a3e2704f93e82a6d5b4a7907113e7cf17bb16c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}}, diff --git a/txscript/data/taproot-ref/0108a92da87f766ee005ac0bb220f78b50d04101 b/txscript/data/taproot-ref/0108a92da87f766ee005ac0bb220f78b50d04101 new file mode 100644 index 0000000000..e64a0e24e8 --- /dev/null +++ b/txscript/data/taproot-ref/0108a92da87f766ee005ac0bb220f78b50d04101 @@ -0,0 +1 @@ +{"tx": "bbfdf13103dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba801000000044ebdc3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba3010000006ee87db8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0700000000b29ebcbf04633b6a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc791357b23", "prevouts": ["55991f0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "bf142400000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335", "5a22280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "e27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ddc5ef0753cfbbae9ae95a5d7a8057a0f244ed9534f11134802dcf3d6e001e11de3dcad145b88b360fb9f51ed5363f34910a171e61f360dd6bdf047d4a1b93cb212021a26ea5e00fb993aa3d0fc1bd1e431f365db69035b8e4625845fc9b697c"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0bc8e394a89b61e744ca0843579507fbd14c939f32cc2eb6ce7075b90210fcdaec7827d9bc9e4e8e39cc141cf7690ea6843d6b50eda1fc8d5571fb149b2aabab"]}}, diff --git a/txscript/data/taproot-ref/010cc78772e75503cf488b6267f5891e1495c962 b/txscript/data/taproot-ref/010cc78772e75503cf488b6267f5891e1495c962 new file mode 100644 index 0000000000..362af976ba --- /dev/null +++ b/txscript/data/taproot-ref/010cc78772e75503cf488b6267f5891e1495c962 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d01000000a146999d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40b00000000f9d200c960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706c00000000e4a24ae5038de26200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79693145c58", "prevouts": ["a3d2230000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30", "ba3a3200000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "f60b0f00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "9f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e7391eb2542a03443f1c351bcd0fdf78b6f5cd40e118bcfcda3d325918034371ee453f7f7ccbda5a0ba96115b963083e4b2e9e93a3abf82e4dae88dd7e6a6b566f3617d560800e971f99646d89bd2028caf0c6d02b6f505a11fcad3ec349c801"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d16427f90468029d5a6f19bd59ef88b2d31e42e78c5014d25692e36886ec4dd7da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e93df6a2e62376e6a3587300ef2d1a395dd90428413a52508272625b5a1a189adb591a16be56540de55d9fbfa115de937b3aca1e4dd0f5a93f17ebd2ebda95183"]}}, diff --git a/txscript/data/taproot-ref/014aca010656e76077fe517e999ea589e88307d7 b/txscript/data/taproot-ref/014aca010656e76077fe517e999ea589e88307d7 new file mode 100644 index 0000000000..93180f93c1 --- /dev/null +++ b/txscript/data/taproot-ref/014aca010656e76077fe517e999ea589e88307d7 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c483010000004b90d992bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf690100000046acbee704b8599500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487b8040000", "prevouts": ["a0413100000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "cd9e650000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e16b70d0ea7480f8ba050345bd8e4e7681bbd8db77ef27050d0a3831748599db67afcaf82673e7b509fa61dcb6f9390da3a7ce1e18401449d1277235bd9d9c04d9a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367f568ee3b696c54dce29559b372086a9ebba75be3e39bc103cd26c12b6b516bb29caa746058fefa69912501c9b6f792a531f2cb30638f1f343d3625f0a93b066f288028cdab461d62f9273620b97315e6e9af9458f777a616c1bade2d3f6a89e"]}}, diff --git a/txscript/data/taproot-ref/01686c55b9d9f3d0c2d9dc8c0911de32df21a864 b/txscript/data/taproot-ref/01686c55b9d9f3d0c2d9dc8c0911de32df21a864 new file mode 100644 index 0000000000..73f11b2c0f --- /dev/null +++ b/txscript/data/taproot-ref/01686c55b9d9f3d0c2d9dc8c0911de32df21a864 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b990000000015e6e6d3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3c010000008991028ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6901000000414a92e6031b996c00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acd3000000", "prevouts": ["7bf1270000000000225f202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "1007280000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f", "867e1e0000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["4339b5a2bb43edb5ec6015e78422673e93a5f940eb73c4bbc50742946ab32e5eed427b14f6d879458116ab1efc635aea8826b9cc83bdff544ff6844fcdf7a496"]}}, diff --git a/txscript/data/taproot-ref/016e25aa492396c1f2937c07dac87f3bce812041 b/txscript/data/taproot-ref/016e25aa492396c1f2937c07dac87f3bce812041 new file mode 100644 index 0000000000..6b0171f499 --- /dev/null +++ b/txscript/data/taproot-ref/016e25aa492396c1f2937c07dac87f3bce812041 @@ -0,0 +1 @@ +{"tx": "238858b702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bca00000000c2cbecccdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce60000000068a68ee4039e927a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acdf40ad44", "prevouts": ["b94a230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "97ef580000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_98", "final": true, "success": {"scriptSig": "", "witness": ["9cf987916c9fc945259df0324a762cd2e10f8cd101b6a6731ab1a8454c54928099a075b1fe092c6ccf2d557f89cfc68ab6f2edf800e60adf72513c4d0fcea5b182", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ca2685331a6191a0114eeabe6ebde5470bce9115c812319aff0b13492676a85fbdda8915dfe9c0f7fd1042634f5acab35eae1255f45d79581ac08d887d49f1d198", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/017f425514c38506670a6136985cf2f693c1851b b/txscript/data/taproot-ref/017f425514c38506670a6136985cf2f693c1851b new file mode 100644 index 0000000000..494859bfb4 --- /dev/null +++ b/txscript/data/taproot-ref/017f425514c38506670a6136985cf2f693c1851b @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd100000000e6d2f9d0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1801000000ccd8cab80133f516000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487bf169b47", "prevouts": ["492721000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "7355690000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4a3ea69b746c966c84daf122809976a6bce8b1d887b17a6e963c4c690b8a790e73a6c94bbfbe0c8d8162307ea587875a7b29cdfde589bfdf70042a40a3445f95ec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5174c6ee35a9af327fa74c94c4ba87a09a7dd613a1ede58e30654f1c4a24a66737074cc5cf84a1d913e1f5647d3427cc0d6d469f0e5b86c78a49890e87126542fa0e1c61743bed8ba943c0dc40e80402f7423773c7111097ca9c5a140b1b3c94b9"]}}, diff --git a/txscript/data/taproot-ref/0181b63b032265ff6a54d3acaf33d2efc67028ca b/txscript/data/taproot-ref/0181b63b032265ff6a54d3acaf33d2efc67028ca new file mode 100644 index 0000000000..21fac55f4a --- /dev/null +++ b/txscript/data/taproot-ref/0181b63b032265ff6a54d3acaf33d2efc67028ca @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9d0100000067e4a0f360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d0000000088944686bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9001000000dc741ab4037f16ee00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb3af1b32", "prevouts": ["de725e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c5840f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ebe5810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/branched_codesep/left", "success": {"scriptSig": "", "witness": ["03020d3eaa8a72b1aa47728a04d43184a271547970e0ea8816d304ece0a04935f83be78ff4d36c71649a3d01c467534678e5554b87828c0df7b8553b79a0fd1381", "01", "4cfe26427fc7901b4262f3d916bc0dd8633c30e5af8ceea1dcacd253c102db78cd839b841955f61e94bf7285a2d0e43879ae3b488b8a01e39fb2cd2bafad8fa0106bbb3fade1a7f218e6696679e4d9a0064d7cfa56e38fbce9d589ae3f102c474c244515d6deda3c971875a105d875417da42bab76fa2a27b69ca61e195bbd59e9cd2768feb7ca6768e59331499fe3edd07b3541fad96c6dd5163816913f7c6f555b72f3810c341f5ef952f6cca9fcec7a4eedbd279af7c38d57c9fb075a83b87ca30e3f546f1d56461fddbec204d0d88a9eacf4b14d4a45fdd445f343e09b7eafa0d24b8c53bef7fbf18b28e1f65ddcba4f4f353831e32a3a7c6483034fcf747563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cbbc2d3d740d8643b25368816a3e2bcc8f965749028964b311d1dfcdbc4a53b754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50ac042ba05ad11f932cebeef8b239400bced5"]}, "failure": {"scriptSig": "", "witness": ["c45c79578af8a27f61c2d67ef3a94395648362bde9177391f52f91fe074803e52cd63f6b917d076cea51d4d03ebc29ab73387d1e16560332c56db68c745725c382", "01", "4cfe26427fc7901b4262f3d916bc0dd8633c30e5af8ceea1dcacd253c102db78cd839b841955f61e94bf7285a2d0e43879ae3b488b8a01e39fb2cd2bafad8fa0106bbb3fade1a7f218e6696679e4d9a0064d7cfa56e38fbce9d589ae3f102c474c244515d6deda3c971875a105d875417da42bab76fa2a27b69ca61e195bbd59e9cd2768feb7ca6768e59331499fe3edd07b3541fad96c6dd5163816913f7c6f555b72f3810c341f5ef952f6cca9fcec7a4eedbd279af7c38d57c9fb075a83b87ca30e3f546f1d56461fddbec204d0d88a9eacf4b14d4a45fdd445f343e09b7eafa0d24b8c53bef7fbf18b28e1f65ddcba4f4f353831e32a3a7c6483034fcf747563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cbbc2d3d740d8643b25368816a3e2bcc8f965749028964b311d1dfcdbc4a53b754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50d10d0bd8e3f1cabc6112980cb297bc5c41ed353de56009a1391b18b49f72e57ea91e7772386659b2a4c3f11548cde49c39c8275d3e5e59aa74c00cf8002df9e4d1e0d017c5d08f6eea24e5e837fbc26ad1d9f018e16a6a200b04b73f8b977242e7867c772a6cdf6ecc62cc889f620f5961cb819733f362e9f3843051663078870142a2f60447911e62d53a997fcbadc873a10f2a62b9e03947d26fa0c80062a2402c593629a27df803fa5eb4420421dc7032cbfc83a2a885d2f9149c6d584890fbcc57d4"]}}, diff --git a/txscript/data/taproot-ref/018284c1e780a7aacea0d945603d5f06254c5cfe b/txscript/data/taproot-ref/018284c1e780a7aacea0d945603d5f06254c5cfe new file mode 100644 index 0000000000..7c47ababc1 --- /dev/null +++ b/txscript/data/taproot-ref/018284c1e780a7aacea0d945603d5f06254c5cfe @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4001000000f6f17dea60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701902000000d12b24b1025b3564000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787911ee449", "prevouts": ["6b4456000000000017a914269f407e1403e9e55237bbaed7146c0fbc0fe6c987", "b6a71000000000002251201649567eb00a0fbdde29b894a99c9dfb586a4dcbbedf9e66ed23f8b13544bc3c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["5ae1bb6d9c8227fbe6b4f51287715bd0ff67feca8c40c7f44c5caca4677c8833055e478a619d43466cfb90a3160e1d49cfdc3f8c47c1f376bbf11ef74df018bb", "57ae0c5d033c3b21f5ebbe4a9047ea95419ead2af2a6ab25dcd715c5310690bb7fda15f9857fcd552c25974bd2792de4cb0aa1b66902d14953b5d41a065662ffc394024c185878238d98e243889f2bb95d2381d0e48a334ac1c1ae39167ebfe8f7b8aca2d943e01b79a4dd2d6cad180b7a584ace48d190da3782d603dfed577899a8f93ffd4cb4dcc38169072001ef8b79cd9803ff44e6b3e9bfa9e69bebc8d4fc2278bb58bc6a8c9483c89451663773e061df8745b7f6bacd602dea", "750442c4413200636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e29b18e54b9e1140aa1e11582f537a5ad3999c59a23047ddb57b3ac70c6daa05e44613a52a3af8356590bcff88b520703b7800fd287a336b2c3b3df06aec1ba9093f9e168a9296464b0cb8d60d5ea228bedf288217508cefa0369dc5c09770c1a08ab1be49aaefe730fc3dc02c42930c0ef8d37e9882b09d910b42fee25cd5fcc0cf11274eb3c1f88f775243e4d6b7852ff5a273b2933877e6c1f7f93705c2aa981d0e7f742d746b7b35b8a606b51debac815e203fd3b195b7554ab4dd3e9960942c624b73feb775cec5155a8259c6a62089426b0a8276f3af6eb31eb7743e2916513b07703f9d17167c9a959fdcd0cae179c2a3beb8eef73f49d54b9a683df90beb45228ea759f56bf279a6490d7939871db834fb4f71e2aa134a1c515491012185bf093501bdd1ed26d6794459dbb074ec632f7aad5abd92cfa2d667f36fb90233ecf9ffa0f1acc87455a974903469689da98c448f59a9ac115d8a0a5e218cc5ddf73967c25d95b1a647dccb6326d59dd55f8c8bb43924508a446b4890ecb4b7105310775c9c23ab9453a8724b9db8f4ec3b9da541bc40cf7e139eb84e5d2fbb2342d4572e5d6890d142c455ebe5eb04d0452cec2b30553d1cf714e9a287b4373837d2f1b875554d0595a98820079f4b0810a322d17e2a11eeafa4b7c79f17560e63654d209cbb282493fdeb1f4fd223e4a735dc90e38c877737eb9ef3abe1000000000000000000000000000000000000000000000000000000000000000061c871e70c7d4119fcc7ed12b89136e223c6aeaedb3ee335a6c3ef523524be01f25f280d9de364a1f86f02d0f520b6ad08e77e2e7ae01f13d6ad0e760a943bb0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc61eebd30f27142c50fdbb2a7fc273ea1dba69879a36d68d4e9f1496b4d827338b6efad5c0e7d0410f01e02028258169b8d6d7aeeae7274b642867424d4b8d268a5848489679402225b8ca9ff91c8268b46b210266c603aa5d18faf745d4953e41819b819a4f7d67493609222558d2580faa86888b1068105b2577fc735b8b9bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7dcdb5fac8897ab4258bb5e4224576578d9ffef55b02135098c3cf86c079d2acffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb403c85095c5b43a22db076a9577c2e678350dc158d7b91b84a0357cfb68a9b0000000000000000000000000000000000000000000000000000000000000000f29e2f89cf5449492c51956aea99da5af19562992d468947751936b5bccda618ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffab71f6c1d2a905b87ebb27f5fe751c43ab49e1570717c20682fbcb99025351aa00000000000000000000000000000000000000000000000000000000000000003d0ddfb5150cfc195901d331dd25bd3476a7af9b8b9e6c9e53d87a75da617b6effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92b8781761d78d0c2f5ba45ae8e15f96df6914fe95abd57a9c482f07edc7ce6097b7339ed5484fecc4dd609e9431b94a2f55e3cd239cfef1a13b364840ebde28ec7676f80ffb285e6042eb11f3c2e99c48fede5c1ce543f213a13c5e4d04aef40ddb431655269f3d4a88d1f6b6d97f6e62b3726cce6024f57f88488d94f7521180868c0cbf3aa76f710ce164d71916e53281f525d1fbdf049d02c0121eaf1562ede19158fed9dcd017254ea525197fd0f2dd3d737176d7b1c48a24e5e26c8c3500000000000000000000000000000000000000000000000000000000000000004782489e614f0f46202bb2e0be9435ee2cdca64edfb612d743543120b98c7fa500000000000000000000000000000000000000000000000000000000000000009a1c7798415af6cb071c401a749655078551865e4039d0835863429ae207b46af38b9a4f08346b5ed47e670ebd05a75aaa9a8faf04abb1f32afe720cd57ab205ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["5ae1bb6d9c8227fbe6b4f51287715bd0ff67feca8c40c7f44c5caca4677c8833055e478a619d43466cfb90a3160e1d49cfdc3f8c47c1f376bbf11ef74df018bb", "72e820bf3407ba443a74c04332d7d8aa71f92299ebd2c8df3c9ff04a356e751a6a4ab8c8c911933a611da9814253d961bf871a77516840f16e6da31fdcb16382520d4fc3554da48c5915ce04dc75f739309344353bd2b8e0bb4978d849383d0eaa9b97e2edb9705e26b98025d9d7c818b4e746f75ed7c8ccbc28dbeb49ab055c9c5d2f73afe916079c96b35e817528562e84602864d870dd1f0b8bd03561335c3b485178b2a0c34cdf1d198e88764d9c19db4db948dc41bc74c510", "750442c4413200636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e29b18e54b9e1140aa1e11582f537a5ad3999c59a23047ddb57b3ac70c6daa05e44613a52a3af8356590bcff88b520703b7800fd287a336b2c3b3df06aec1ba9093f9e168a9296464b0cb8d60d5ea228bedf288217508cefa0369dc5c09770c1a08ab1be49aaefe730fc3dc02c42930c0ef8d37e9882b09d910b42fee25cd5fcc0cf11274eb3c1f88f775243e4d6b7852ff5a273b2933877e6c1f7f93705c2aa981d0e7f742d746b7b35b8a606b51debac815e203fd3b195b7554ab4dd3e9960942c624b73feb775cec5155a8259c6a62089426b0a8276f3af6eb31eb7743e2916513b07703f9d17167c9a959fdcd0cae179c2a3beb8eef73f49d54b9a683df90beb45228ea759f56bf279a6490d7939871db834fb4f71e2aa134a1c515491012185bf093501bdd1ed26d6794459dbb074ec632f7aad5abd92cfa2d667f36fb90233ecf9ffa0f1acc87455a974903469689da98c448f59a9ac115d8a0a5e218cc5ddf73967c25d95b1a647dccb6326d59dd55f8c8bb43924508a446b4890ecb4b7105310775c9c23ab9453a8724b9db8f4ec3b9da541bc40cf7e139eb84e5d2fbb2342d4572e5d6890d142c455ebe5eb04d0452cec2b30553d1cf714e9a287b4373837d2f1b875554d0595a98820079f4b0810a322d17e2a11eeafa4b7c79f17560e63654d209cbb282493fdeb1f4fd223e4a735dc90e38c877737eb9ef3abe1000000000000000000000000000000000000000000000000000000000000000061c871e70c7d4119fcc7ed12b89136e223c6aeaedb3ee335a6c3ef523524be01f25f280d9de364a1f86f02d0f520b6ad08e77e2e7ae01f13d6ad0e760a943bb0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc61eebd30f27142c50fdbb2a7fc273ea1dba69879a36d68d4e9f1496b4d827338b6efad5c0e7d0410f01e02028258169b8d6d7aeeae7274b642867424d4b8d268a5848489679402225b8ca9ff91c8268b46b210266c603aa5d18faf745d4953e41819b819a4f7d67493609222558d2580faa86888b1068105b2577fc735b8b9bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7dcdb5fac8897ab4258bb5e4224576578d9ffef55b02135098c3cf86c079d2acffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdb403c85095c5b43a22db076a9577c2e678350dc158d7b91b84a0357cfb68a9b0000000000000000000000000000000000000000000000000000000000000000f29e2f89cf5449492c51956aea99da5af19562992d468947751936b5bccda618ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffab71f6c1d2a905b87ebb27f5fe751c43ab49e1570717c20682fbcb99025351aa00000000000000000000000000000000000000000000000000000000000000003d0ddfb5150cfc195901d331dd25bd3476a7af9b8b9e6c9e53d87a75da617b6effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92b8781761d78d0c2f5ba45ae8e15f96df6914fe95abd57a9c482f07edc7ce6097b7339ed5484fecc4dd609e9431b94a2f55e3cd239cfef1a13b364840ebde28ec7676f80ffb285e6042eb11f3c2e99c48fede5c1ce543f213a13c5e4d04aef40ddb431655269f3d4a88d1f6b6d97f6e62b3726cce6024f57f88488d94f7521180868c0cbf3aa76f710ce164d71916e53281f525d1fbdf049d02c0121eaf1562ede19158fed9dcd017254ea525197fd0f2dd3d737176d7b1c48a24e5e26c8c3500000000000000000000000000000000000000000000000000000000000000004782489e614f0f46202bb2e0be9435ee2cdca64edfb612d743543120b98c7fa500000000000000000000000000000000000000000000000000000000000000009a1c7798415af6cb071c401a749655078551865e4039d0835863429ae207b46af38b9a4f08346b5ed47e670ebd05a75aaa9a8faf04abb1f32afe720cd57ab205ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/01ca217ccf1ea0e39003e90d0d3573454b370bd0 b/txscript/data/taproot-ref/01ca217ccf1ea0e39003e90d0d3573454b370bd0 new file mode 100644 index 0000000000..6ecf0f0f58 --- /dev/null +++ b/txscript/data/taproot-ref/01ca217ccf1ea0e39003e90d0d3573454b370bd0 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700a02000000307a10d802eece0b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df9797223689874f040000", "prevouts": ["83d00e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "success": {"scriptSig": "", "witness": ["dbcb129ebf4f1e8201527e18f1d2be57cecffd27cf05ac2766de001634d77f1ab28efeeca801991ab3f57bba5e5dafbe42ccb0de07ef2a2a2e2e8180178b23f003", "508321106f9aff90ba27dc13d2ef81cc94ec2f8f1ea854ca3e0ce292ddcbf4d61e2320f8ce08a36e0b4d4037a452252b79ea015cca303607d8de1470da0b0507b6c9817fd30b6678079111ab7673f017f0cd07f5291141bb36d639d9bd932f1853f6dacc8a6f3f34a35d2cfb85ba80aea6b542981232e8c2ea969a99809e00fb4dfbbb46b84275821dfa0c46bef0f8542b045f39bfeec1dee1488dce01d411708e73d8566d2887099ec45ec09aaca37d1d4fc453492b958a8397e8668a88043529c055b0dc38b5bfa62c49"]}, "failure": {"scriptSig": "", "witness": ["05aa27047b2f5b25aee0ab27c860c2847dfda7f80ba6b6335f03222edaf26fc88f38915a90f7c50376cb46722d3b6eeac031b52111e2b514ad898c559fa535b803", "507d1eae983c3f45190305daa1e0543f00973fd14afca63300647162eea1905d22eeb0656c87b86cc89edb03876003d2359b1a3a96780f610cec16e0cba0b5f21bfa17fa6fef53047de15ea66457bcb475ff3156ea9912c196e1ef411a389889f417652637e2cf7424b9d83ce7b5ec1636b52f50dcf4a77c2a4009445ca5037a2f88ef33699080afa1b0a0324539b3ce8d66014d844af632178356297de11e28af3b45021c445ab85c19b8a219d8ca81a28192929ed9066bd918a24a3159e968db76156238ac94a589d46a40bff32c6ce8b7b1cae6dec43530ed2daccc8b14142e84196bb4019c98be9b4c"]}}, diff --git a/txscript/data/taproot-ref/01cc26fa177761f2440d4f78790adfdcb27c9321 b/txscript/data/taproot-ref/01cc26fa177761f2440d4f78790adfdcb27c9321 new file mode 100644 index 0000000000..97800509c7 --- /dev/null +++ b/txscript/data/taproot-ref/01cc26fa177761f2440d4f78790adfdcb27c9321 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f3000000008d771f89dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd500000000c1cefaf2042f856000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf2b3e221", "prevouts": ["23500f0000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43", "c97753000000000017a914e014b0ed75ce4306970c9f63e88b08a5a7bb4d0f87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2358212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["05d85d20fc108d588ad29a582be7d3cb74c0b8f2f2ac241d5a1d6881c63326d6299dc8a12f3fba6e77ea7c4b4af004240d4160ea55c6b0cf9eef3588f712700e", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/0224ee3efd6d6c2e6024db65267c008a3786f0b2 b/txscript/data/taproot-ref/0224ee3efd6d6c2e6024db65267c008a3786f0b2 new file mode 100644 index 0000000000..62d981e46c --- /dev/null +++ b/txscript/data/taproot-ref/0224ee3efd6d6c2e6024db65267c008a3786f0b2 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2c00000000a3ce2e21dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1702000000adcbac73bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b02000000deea024702e1a1c8000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ace21d5c2a", "prevouts": ["e96d23000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "ffd225000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "485c8200000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "cc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360f3116d13ffcf1555cb4ae301ccf73da17002937b6b410b37f9321c49918b540474a999e2826f1f27f01ebf91ad073bfebeca039a55919a1ef327838bd290026ec1da8cea892037e805a477afbb54b1f5ec380954f076c0bcd3c4e3d4797a8d6"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4a945d156e5e86160b430602b16befc6691bb081598fdd6a533cf4573a883d745716b950e27a233a501a90011450809f321d0f7541cd1975fe5718ce8e53406ec1da8cea892037e805a477afbb54b1f5ec380954f076c0bcd3c4e3d4797a8d6"]}}, diff --git a/txscript/data/taproot-ref/0234f23ded5600eb13895b83e3d3208daa621654 b/txscript/data/taproot-ref/0234f23ded5600eb13895b83e3d3208daa621654 new file mode 100644 index 0000000000..1ef4cf7df4 --- /dev/null +++ b/txscript/data/taproot-ref/0234f23ded5600eb13895b83e3d3208daa621654 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4020200000098371f3adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbc01000000059cb1e5044b7b7900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6f4010000", "prevouts": ["a15f32000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "55b04800000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09024f8005087f643e5e326d0fbdb76b9716a98de1150ee25e33b0a11f2f828a5a6ee42441089319f5f7a30f66ae6fe290d924631c0a560e4058cf4cc9365809804ec3203b232bcba98a3677a89bf235a32006a46bceec4815b6a9ad678feaabffc7593aabaaab9ee4166fa2b634131708ae1928fb89743f5cdcac27c76e4e7c1fa351ff9c686d0f9044f68a77f85149944b62dd18b89687aa0a4e52c7f4867097735cd0479406d25087d7cb32168f66fdfba982bbb5f84d89e0e32821a5a30d8df65275b11e1d6ed0d3c31fb4003297b20778f87b1b2bdbfbc8fa36e6273aa4d965aca16bb8dee9c0fec56d17555d88e5d2271c2777b0e3109f4af0050ee1e28432f4b8391d0d414850c09821fd82cee61d206611be218ce229dd4ef6555351a22361273030ee5cd632d845d287a777d1bb8264283a6325643bc524ab6ceb4a7bcfcfdb0ab93165fbd0b5345e6ee7743c545ad5f162f551ea74eae6b6a060525d3f7060e6183c9c9c2e2e235bccb9a497600e9861785de111578e38b29a87c81b4327cd64235e5f770df3cc9072bb075148a264eedc3717e7510982b44a56dc3501d8e9aa3ae1342c7cccc052cdd901a5183aa4b1a4af097b1b216966bf0f4d663aa21af6e02046ec2466db326245e3fc6e692610e3f3eaed6e7823de6225edae0921164233fdb0532af729b79a85c26df585aeaa3e2eb91845c53cce8fbf7e8227537c1d77f676f4009a75c8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ab352ee2a6a8e236a875eeadb35b814571c290bf5fc32e6cf848a4bdb48a3dff6032c3262f8d7c29daaf8f9846bf0ed9dbcc4a0f9aeeb7c8ab8b4ceb985f45a6c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}, "failure": {"scriptSig": "", "witness": ["4d0902d4079ee5c5ab78967a4de070dcd8917cefcd564da8e2c7b418a7caf1b2a764c993a93077fcf699ee51efcfe06d7d67cf66b058ee19619d948d70f9179a9d209f4fec62c9d7afd685c60061eaf8f3b301baeea8e441796f349ded20653cac996257a65805c024857ce2e6829217dcb1b8cc02c33b1172d9bde101537cf37789ed3fce9c9c67937e9099e366b695b08d4bd5ea93c82ac95922774432237ec82ce62560b9f64e5f8e7e3ef72f2abefb77123c445668a3e336b8a0141174782f7b07194af9718fd1f7bce221ec724cbe7fe43c07a62c367e17022e9e75ee0d25957d6b5ff85b829affe8942632b08597639dc7ad979b058a5be6d59d719fa451cdc66bcc185aebdd38a642bf8500496cc3f433c126106011e79a89440dedf4188b7597794e56bd15344508b9afe32d87449f13052266938bc272af6c01ab3279b41804d94c4f7fd90ae81358adc04b2b90e5bb8681bdb55022afa39c906afe8dd8e19cb03c6cfbee7a72a60c77afbda33dfce0f64926c17d97366b25d2242e009f9856e2173d2ec7fcc199534fd42779dd87eaef5d10739543f59560863d577025650d4c9cb385fa2aec0b92ec1300c00f2d3fc375e0b2f52006639c6fcf0107f07817735aadc7dcf70a5cf5747b6b94b91e7ac27d33d663f4dcb618099e9ed133b9980fb86b8f7e92696598ffcf39baa97736d189eacaec042b2b884f975f4d0b7a4ab82d08cfdcca21b77561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93644a2c580f02407949e8c9479d2e11f86ba508deab24abeabd93013277c882be620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b553f13873b7614c747e02d52f281322dd98cc8d4ce789920cf593b75c6f05693959a095ba405700a8bdcb88c47f737d45523ad768f5b3698c80add34f2e764b"]}}, diff --git a/txscript/data/taproot-ref/026745c2e6a71ca361cb3f37fe3f4e9c3029688e b/txscript/data/taproot-ref/026745c2e6a71ca361cb3f37fe3f4e9c3029688e new file mode 100644 index 0000000000..e9ec465dea --- /dev/null +++ b/txscript/data/taproot-ref/026745c2e6a71ca361cb3f37fe3f4e9c3029688e @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e40100000087e476028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47200000000408ded1d02f5c75f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987a7000000", "prevouts": ["6082310000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "792e310000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae7", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cbe80ed66a202568e8406ce6daea5cbc02fcaace10fdce03f37cb2cd6261bd65d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c61a1ab416979399a3dea56cc9db65331fc4d8e9e627e6b90ed3a4ebdc2f66c36df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936372e7144be8e6568f861dea45248ebea76fa61ab8bc1a80418220e511074ae7fc61a1ab416979399a3dea56cc9db65331fc4d8e9e627e6b90ed3a4ebdc2f66c36df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}}, diff --git a/txscript/data/taproot-ref/026f12b427239f4351f951644afdf9e483ddc4bd b/txscript/data/taproot-ref/026f12b427239f4351f951644afdf9e483ddc4bd new file mode 100644 index 0000000000..272ffdd8c3 --- /dev/null +++ b/txscript/data/taproot-ref/026f12b427239f4351f951644afdf9e483ddc4bd @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3901000000294d73f38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f000000000428d778904fbaeb6000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796f7b3ae3c", "prevouts": ["d7b8770000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "2ac54100000000002251202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "167d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cd8a296a36cabb0bc76215e2b1961ccf6987911bdf985895069abdd55ec163ba2d231140cd01d0310e585ecf2f38aee8d36f3a935cf5b06765b4319c9202713151e3355b9fad1d20bddcd1a8531bcd58c93c4d9ee4159d68db4e08ecdffbe17e"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9208e9eee32827fa4e54b07d43c20a1066def6db0c0487e58a7d5647a1ab7f13f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828719dd3b5606bc946287d150a5ecd03b0f8e892d08bbecd28ea2e3769111c28051e3355b9fad1d20bddcd1a8531bcd58c93c4d9ee4159d68db4e08ecdffbe17e"]}}, diff --git a/txscript/data/taproot-ref/0274119160b74eb12e8b0ea869012528e5c8c64a b/txscript/data/taproot-ref/0274119160b74eb12e8b0ea869012528e5c8c64a new file mode 100644 index 0000000000..b302485b25 --- /dev/null +++ b/txscript/data/taproot-ref/0274119160b74eb12e8b0ea869012528e5c8c64a @@ -0,0 +1 @@ +{"tx": "077b85b802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5d0000000030a7fabf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700b00000000c47e39a703584e3500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc1d010000", "prevouts": ["75172800000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "a8e50e0000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "147d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ab0e9d9a4858a0e69605fe9c5a42d739fbe26fa79650e7074f462b02645f7ea7d9d0ef68974064b15682d7a9aede6e3fda6769a3db9d22f26322e1baaf4532e568dbaf979cca58396dcf271ee6fc736edd00965a3b0ecce9c87347ff88ab08a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab120007c9d6e5438fb32187fc2295f6e0f6d7a9b61cc04930744a089d58d965ad1099cc9bb3a5e2066786e30d0fff4359b3ce527e140b44a0b5c89c6b4383919a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100efb63111b06c7a0ce3f44d9f6906db8fc60057b72694cfd58ed25db88d188e5fc"]}}, diff --git a/txscript/data/taproot-ref/02a2d45e622dec5a4342e4be185659da883e8d6d b/txscript/data/taproot-ref/02a2d45e622dec5a4342e4be185659da883e8d6d new file mode 100644 index 0000000000..dba669f6ba --- /dev/null +++ b/txscript/data/taproot-ref/02a2d45e622dec5a4342e4be185659da883e8d6d @@ -0,0 +1 @@ +{"tx": "66f38c2001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc900000000cda530e803fabc1e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987c8b2f34b", "prevouts": ["3f79210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_5f", "final": true, "success": {"scriptSig": "", "witness": ["9b8c21d8992b703916296f8328c308107fba6a58f4e0c0f3e932ed3869f68918d9de62a3d80e883258011295585bcd3b408a88afe0820ece1a5a9c909e3e9896"]}, "failure": {"scriptSig": "", "witness": ["36e15b42d7f927df7fc4d1976cfb3636ac0b5c7abb195d36a610b4e4c325881285d2d94ce9e47dbe0fc6d149e4773a4754f2d73d8f25603b7c00053ad3e8cdff5f"]}}, diff --git a/txscript/data/taproot-ref/02bb3113c2f000ec71e0cac539468d820cfa2df6 b/txscript/data/taproot-ref/02bb3113c2f000ec71e0cac539468d820cfa2df6 new file mode 100644 index 0000000000..2d3e48e4b6 --- /dev/null +++ b/txscript/data/taproot-ref/02bb3113c2f000ec71e0cac539468d820cfa2df6 @@ -0,0 +1 @@ +{"tx": "e051097e028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45500000000dc24bba48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4730000000064d00afb0499a17b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e789010000", "prevouts": ["24093e0000000000225120c7cc4d9ecf94fd1d6052a234c093a72236440d0ef34d0ac6810605a4931ceb69", "e12440000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667eba4a75e30ef7cf22fbfc1113fbdf039a8bb23353b5bb581506d48372cca6d"]}, "failure": {"scriptSig": "", "witness": ["6a16616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/02c77525ae2279633746cc24153272f0cbebb2cf b/txscript/data/taproot-ref/02c77525ae2279633746cc24153272f0cbebb2cf new file mode 100644 index 0000000000..1c7f7e01ac --- /dev/null +++ b/txscript/data/taproot-ref/02c77525ae2279633746cc24153272f0cbebb2cf @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0200000000cc03c0d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c680000000072bf48db039442c600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acc4ec2f20", "prevouts": ["e2656b00000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "65ce5c000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09026bfcc84a20f1dde059eafec76ab3f132b4b97d116fd9c0ecd94fbd5ae160ffca578916630bf7b2ab99380a452ca6feb2c2a0b74569e52a4d3a741119b2769860d266e4be108ab87c5254bea9009479393393b21aeb61546527ce496910bf201a0e418ae95e6bf137eafcad3e06e3c3cf2da59cb3096b9593f6eadb3b7c08bb7a9564002be14a472ba273ade254fc9855f999cdc687f04b32e05795f6d4e705b09fa265f601fc7474c7ab54b7f6966f0b86c34ba81e97cdeae52ccf504dc5dc6e0613f5cbee2cc97ab674d0db7139dfeeec8d26ced7395a13d2d1f0750b17726b2f8b24c9df13b3ec48eba42c2dd48851d08533568756c6bfdf3ea159dca5913e942f75b0e3f8cb35c883ef7da55fc6a84fb28412d58ea3f5e6b77a8895e735465e1f197aa298b03767a80f0f22a8246b6b0c56f78a79a90dd2b310c6049a358e838ab4b02686ccdbac0681739a2e67300ad3d27987e77fad413d0aafbec20332be693871db55788ca49a14ee37761ab5130731a3beeaa7d359d0adffe0c311a366cfc4830192e84e3f7ee79ce185c5b0e6a68a450b31277b074004f9d05a66feb0fbbf240ba7dd661dfa3356101f91b9b55f9f3ace5feab889659ace9879342c33cc2891ef6ecf1acbe8efa220bdf40a7fe1f43b4d3894122ebef09098a68bd08eb7c0d4b64e71c21712a66b85b9acb52f01ae85984b714ba7004df34aeee3a74afacda297895bce4c75", "347d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d221413d2c4dda6e421754723c8a1cc16da4dea4f461b707f2ddf3ed15b4d514c5a4ec1ad3c05e8d6cb6e5418cc65ab3865118805b06cbf11da98fae87c97132e97124583e57aeab90707503ff0d8dae530166a9193c4517699e1743b45d7c12"]}, "failure": {"scriptSig": "", "witness": ["4d0902db52af405d1c8b0c28b352ede8be9b8a16826899c0bd8773adeb0f0685770f5182bc9b6603ae215ecf1adcc69cf908a68654448d70df7c4e7a6ed92b7a0eeeaaa77c27314daebb270f7ee97bccad49bb2112bac50fb88ca5cb4a0138ecf4f5bac2915cd1face16d5f78c1691417f0da99ade26f9cf7bd760e014c3af369c9a8127acd92dc553ed12b4a7a86e53283730aa5e6a7c27d4d6a0af547c47f625192d6d2cb3d32cea2b611ddb90a90c520fd0fcc2c6b21d73bf9f37caf92deb1be44ba462133ec09ffd7603ae4e40463d2a5cd19683d0e5c50f097ad25785e36806e893ec6b069aa1951c7cd970bcbaee5274efd8b7dc12880d0c228115d12eae2ecdb692de46623e91cd25d0aa6e28b8e72ea2248875505e23582c3614decaf3e0ba31d77ef5ab788adddd53b5baec31a3039727cf15baff9647049a5a192c51879b06fea6506addbb9cb991811b5f7003dc12d1100863c262a97f4463f041bfa9ef95f675711baa0381427ebf1be8ec381d9795ae1bbbfcdf85d2424d8a13e9b0560dbddbb362e07edba65334773ae3bca405a2a630ab41ca253a14843bc0730b459fddeddb484bcec67e7e757283cb631b7657e493daad69218a921b4612c7665cc376a79de26956488d467707e7e937b0f7208b7555dfee6f3288ae902fd9e6dd1db8dafd5046950d755d877bdc6589d6dc1b39d0cb638cb060d32719f28698db6c05b813dca43e87fa75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a750add471e9b5b51db6817cb10861abf00379c9e2c8d017af134b88039c39e3ca882fe3c585d1ac8aa5218112791e3065e91b4e1e0362790dbd367cd44cec36e97124583e57aeab90707503ff0d8dae530166a9193c4517699e1743b45d7c12"]}}, diff --git a/txscript/data/taproot-ref/02d1c1fa4446780154693993cbb3b3357d7dc38f b/txscript/data/taproot-ref/02d1c1fa4446780154693993cbb3b3357d7dc38f new file mode 100644 index 0000000000..ab23669fe3 --- /dev/null +++ b/txscript/data/taproot-ref/02d1c1fa4446780154693993cbb3b3357d7dc38f @@ -0,0 +1 @@ +{"tx": "67740b64038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48b00000000cbcacdbcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a010000009adeb4bedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd9010000005dd15aca02d7dc9800000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac56737540", "prevouts": ["ff1f310000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "d85b480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6f8f21000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00636268", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08265d6469ded31e8361d538153e3993104db0c9d480dfc3dcfe9dd6d2fbda5f8f6abc42ab3738335b78a2a7135de763706b017ef32cb75bc24ca1210f74f6e5b7b3fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365f7d2d3ff74ecf468292bf32d6ccf054ad7a3b1b44c07da8896c3351da300a8722ebb88c16ebf61dfdf766657f947c6b679bf36be3a1118c2e7b2b24c8fd5c2a5a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}}, diff --git a/txscript/data/taproot-ref/02f4d455a5e5230510c642f46a00e2819cbd49fa b/txscript/data/taproot-ref/02f4d455a5e5230510c642f46a00e2819cbd49fa new file mode 100644 index 0000000000..56995d0123 --- /dev/null +++ b/txscript/data/taproot-ref/02f4d455a5e5230510c642f46a00e2819cbd49fa @@ -0,0 +1 @@ +{"tx": "9701b121028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40902000000f80e52cc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fb00000000f5b250cc04079570000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961fe84c52", "prevouts": ["510837000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9", "0f433b000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09023353eb347d0d2153cd9bad2bd6904e61e7a55a0ab586d7c450417662391636a0d8868ed4fbf3e9f91e6d8b61f972f36f717dca183f648d96b57203ce4f9a2447d44c50c07276d3258977e8fce61f3ce1866d6ce748292380b2be241d4666ca0701410030bedda775b8505d6fe3ce6103288ffede28435eda29614bc189eacf2b17e96eccbc91c782fe66abb968f821d41f680b1dcf007deab123c0422477dee740e7719be7520a18d5b2a118453f846ffb35edb6f22f8f90e01ac68f37c461199f2036e548700bfa8041467ce1fb87f186d0469d658b211595ddce86d95ce929fa4cead051baeeb283bdbfdbab4fbecb6decbb8f40c0f09e69538a5ee16b4a805a285ac0292c49a1594c5ff7629bb603404e50a414b36eb6d23a85a725c00cf51c06b19a1fe943c522c05fed7864534e39bf322f94d4540aa5d731f35a7fe13a024f65a64ad603e2362523066b6bf57e474edb7cd5911a446b1391e6946012143658109491c7736e3e837c3052082a63b335826ad2cab87d68c9cda512c97e6083cb5057ee85cbbc6fd838dc7628e4c69c8277fea144a5f7b0c04e629c77832ab6f89b713b3e04986008a5ebd0001d38b265f8156e9d230acae56a5ac9cc065be2a6efdda57c6c65d3e46f1d756e592a6aed34dd0306dffa384d971a1a23a5e59542cb6303d3415518ecc881582fbaf7593679be5725466f1096f8e20733bd8fae7cd8e11fecdb853875e8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363edf250f59c4f8d5411dc2db66583927bca5ee5d6634a7a83199202757115d4a886d39c7fd191823f2d71d70dbb2b614916cf5220a36a0556ea0e320955e8896770b862ef93acb6091cb4ff8ef135b3065b278142aa4adab757f952a626e2b26c80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}, "failure": {"scriptSig": "", "witness": ["4d09023aeeb10473b6ce93a4415b162ddf8725baea19dc6056c93ebe4665e2b752558a90c2a8179abf63ec0dd2e727a2c7bcdc698ad44a00a85b76ffdb17804ca07919ab22ec6b01e86f6b2e68ecdb567d6c64d18b221084bc29fa1523242ec9453fb58c3fa579e374550650afb81bddbb35dc6702afb0114ba4f2e487a724e83edabfd4587af283918dcadbe2bca16e8eeb8702cfb1dd9a0bfcd697e7668439e459b6bb5ac9b75df68bb4f685b7f87d931dcf760ad8e8ea7b12e13b4cd41e195c51b1b4cf73c68acc17b6093292eee19997bfd701408e0305b9906dea47b79ecfc9bbaf723585f4288a90fe1ccefd8d41b19ba1acd7b9652b71dd8a10d0c87a6b40fbcacfa1b068c16973109aa391e249fa775ac5b2bfc626ab7f9df87decbca832fed887de5ddbd2d903b2889dadfbaaf7e7e5335b00bb1f41525efc2a502b84c3efa4f7d2cd209027a41d038efe432df72f1f5069a6dbb03cb5cfc596fff10f043ff09b2ca87e36abb87a172cb503a14a06d50b76a1e9ba66d3288413f96f6a7e37bf9188e92434d803f7aa7106bf238d81fea1b81b03685597f2591a175f5be89149ff0923a78741b5227d7b654c3726573b4243beb0e9b31842c83fabd310cd034bc1bfbc46eb21027b51b7e1e7b4d1b810066ffa8ffad253dca43894077404c79da411e7a9358a9805f43ed674860519e567adc09c4c5d9b710d3a4a5b60208277480fe28da2994f8d7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e13f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f61f73219d91856056394a010eb6c8ee7f13c9683181be224f0fcf47ad20d61b9aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}}, diff --git a/txscript/data/taproot-ref/02fcf2313f765802ff09c238af833842580fe461 b/txscript/data/taproot-ref/02fcf2313f765802ff09c238af833842580fe461 new file mode 100644 index 0000000000..6102e8de21 --- /dev/null +++ b/txscript/data/taproot-ref/02fcf2313f765802ff09c238af833842580fe461 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf29000000001bb3f48cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff001000000b58b7f9404b14deb000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aced020000", "prevouts": ["68347b0000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "aedc7200000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d268", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936845af1e352b99ba1b82573d5ecb8b40522cefe3709b796d40d93abe1531690682bdb5955fa247e32681f749888c9d4f86e5604dd03da59f821ad9d541fb8adcb845c4b1f0ef9796b099f7837236ca3239de7da07050a4e4f568f49f6a65718f105f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d519d9c6e51540aa9a09fa82ae61189b3f4badb16bfd2877ff7bde730e5687247de05f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}}, diff --git a/txscript/data/taproot-ref/0313e7c2127076391d6fd9696d30081eb2c9bfb5 b/txscript/data/taproot-ref/0313e7c2127076391d6fd9696d30081eb2c9bfb5 new file mode 100644 index 0000000000..cc4d082743 --- /dev/null +++ b/txscript/data/taproot-ref/0313e7c2127076391d6fd9696d30081eb2c9bfb5 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8d01000000117807cebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0d01000000ea8fb1ec02e7b0ce0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898749102860", "prevouts": ["7bdc65000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "e5246b00000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["504c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f933d08853672a2275403f631a185860433b7a30f3dde2a4cbab45ca4cd5b5bf04d1c6645dfa5bcea0755bc1d945f129b754bcfdfa4df703b30809220c35586032cb43424d7ca27a7abc5fd0c2fa249f92b1e992144deb3864a86d466f79c2cceedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b2c979e5280cffc0fe517d7f3a0a759f39d4606868e0106565d6533994a6841faa718416d21ef008df2257ef512539448f5ca520db3fa3c7b8aa919421e6092eedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}}, diff --git a/txscript/data/taproot-ref/0325cc06523d6b80529e7b67ea669a8cacc195a1 b/txscript/data/taproot-ref/0325cc06523d6b80529e7b67ea669a8cacc195a1 new file mode 100644 index 0000000000..61ee6af9e1 --- /dev/null +++ b/txscript/data/taproot-ref/0325cc06523d6b80529e7b67ea669a8cacc195a1 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127033010000009cf2b10cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2201000000378971070259bd8600000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47876dd8b95c", "prevouts": ["f1be110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3569770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_75", "final": true, "success": {"scriptSig": "", "witness": ["ee04256d62ea675e3aa806a3452a6a010138f4d64e4e42228095623c25357d90954435ec1693c98fd76fa1597cca47b0f5708950e92c2894573ea12dc3fc37fc01"]}, "failure": {"scriptSig": "", "witness": ["b02f7b3c1cf4e1d8184f9fe58b46a5189033cddbdc79c54483675266f497dd9fa7e37697d3c2c9b2cac7ac228296b5f7acc853fd7a3ff60a4d5ca5bf9f196e7475"]}}, diff --git a/txscript/data/taproot-ref/032b54a2e80454a2b7039f32a4974095c2f018b0 b/txscript/data/taproot-ref/032b54a2e80454a2b7039f32a4974095c2f018b0 new file mode 100644 index 0000000000..ad357c0be3 --- /dev/null +++ b/txscript/data/taproot-ref/032b54a2e80454a2b7039f32a4974095c2f018b0 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d8010000000971c6928bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45001000000c3f02c01025ddd7800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac80ae104b", "prevouts": ["f8213e0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "65c23d0000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "4730440220686bb6e46dea578147f27aafedff0c993acd44d4f80a84a57edc035af04d10f202203d2a6da29cf4f18ad64214ecc843c48b120136beb06dc90d4182d08e52df82ff01", "witness": []}, "failure": {"scriptSig": "473044022013a6d2168ed4fa68061b08e3b2d68bc5d2e6671577c6d25201c6e3948901456f022002dbad69f47e00723719f64cc25082628a1b8bb8baac82dc589debdb8563b07a01", "witness": []}}, diff --git a/txscript/data/taproot-ref/035336c778f096bfe56ccd9c44ca36a275649299 b/txscript/data/taproot-ref/035336c778f096bfe56ccd9c44ca36a275649299 new file mode 100644 index 0000000000..2cdcfe037c --- /dev/null +++ b/txscript/data/taproot-ref/035336c778f096bfe56ccd9c44ca36a275649299 @@ -0,0 +1 @@ +{"tx": "e2951d0503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2900000000faacbcb9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1601000000b69418878bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4eb000000002de75a95023fb57d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689870b6d6e3c", "prevouts": ["4a82260000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258", "6f1924000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "0ab0340000000000225b202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["c65f891f63a4162edc2f85da4a692c563eee896098c5d267f1e194a520bc037cd66194e6887748b9e1e8fa07d0598fbf835e584ebf9a684f336d03b628e6e3a7"]}}, diff --git a/txscript/data/taproot-ref/038d58e7a5bd8cd3c42dbd68c099f5900b90ceef b/txscript/data/taproot-ref/038d58e7a5bd8cd3c42dbd68c099f5900b90ceef new file mode 100644 index 0000000000..6872d0160a --- /dev/null +++ b/txscript/data/taproot-ref/038d58e7a5bd8cd3c42dbd68c099f5900b90ceef @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ec01000000cb4377a0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffe010000004024cc68026864b900000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdd020000", "prevouts": ["64e73a000000000017a9140917710a6236c7a08b54f54b004ee705f2913e3087", "d82a810000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dba6d090ce6eeca8f19bee4c4b18bd87e742c613226dbb66d44b3d8c22cd4f417d143406647e47f2aa45aee5a8d37fbb079fe3a633dc3f79123da3b3ed47a821a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93645b70697259a6092735a83fd9185b271706fbd91da528cf82e26060ba02f7d12c3950c17255228812280bec2d0cca04b586565374a97ee6c913745c9c1a159600ce9ba0618adb3ee44483a22999a54a4e1710b9846377d8164aaa29371d79f22a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}}, diff --git a/txscript/data/taproot-ref/03ac2fb4ae30f213cec9edbaf2796b086134d050 b/txscript/data/taproot-ref/03ac2fb4ae30f213cec9edbaf2796b086134d050 new file mode 100644 index 0000000000..05750fd724 --- /dev/null +++ b/txscript/data/taproot-ref/03ac2fb4ae30f213cec9edbaf2796b086134d050 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdc01000000f1553faf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41f020000004d967d93dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b20000000009c7a29f501e4bd6e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac9946af3a", "prevouts": ["8fa24e0000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "07ca3b000000000017a914a7d99db8790799e567017bcc9951f7f968dba70f87", "48721e000000000017a914a1b035f555fd87548264c3580a1f62a42acf027e87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902507dceead97f0d39a0479a7449706ea67130065d5b4100aa056b2ec143dce6731bc857eb628da5d6582597ddd0e45ae4b471849db6e9fb3fe1c3682931873323072350cbb62ff65b67c7ecbb06c15cdbaeaf0e9def442c347be5dd7e2a51a96bba938c6c5f9828102ecd35e365e31e1896d945d7b5bf9fa72fc0fef606246e9826e4f611711aa8fcc664d39d556ea91357e5f61f71b4f541550316fab12d018f8a95bfa43156a3b003fa3283f38e89ef9a79b2308933df81d7f3459609dade69e500c90936678b2039f062a86f19196dd7aaa97aa0e7034e4ef1536690ca67356e9ccd071e82b0ccfc50f3ca3503ceec63ae1e674235edd969349a3c60afb544d75801343e5d870cf694cb9d7dce70cc797748b53657e8d8f6d3f3cdcc24f8e4f0f2efb941eee7906e5cee872f9bea68f28f99c45cbe0589e562d80ed16b80343cef4805754b5fd76e527c7fb0b749083094168ee72a1ec8922696977d6256aad60a908c0a28ac7f4e8a1d82d9a23354cd49eb6bdd210921cf0783d918a27f42977cbdd5b183f7e8bed8dac11fb3e55c940b5888725c69d8b38b194fd86345595aea7e8170ad3efd72f93e154a40266741bda110d4c389670e62c93a09fece71f5e58dacbf6bcc4eeffedabed92c760e618b69487805fbbcc7a499e4209660ceb82abd20ec9da6e429b43b26faf5ffe5cc752c7286c9aae9b615e0d0034b82519b8dc02af3837b39dc75", "6b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361b101d42e37cf345b14a494ee8db2f6d3825916e42c7a162e255fc6a9b93086c8a154b22b0f2e2bdd7f3b34b8feaf196c14822a5749c8a329692c0e12e8447d605976fe26432a41f3547171b2b9abb696d7de0172bd15211267873326056804912e839b87dc613c826a9c62085431a96f79b8782d4b0fe31dfc75aede09e250a"]}, "failure": {"scriptSig": "", "witness": ["4d0902f62d6b759218d83ab882995d625bf8f2485500966d8bf7856c73cd7d17260caf3da5b7c179032e276a4c2fe6ce6584905c5ee04745a81948f2941bb47d2871fd9eda7ad0fe926bccb818a72d505fa1abae02704f5f734dd0499733aa6a7c8545e06e965af935139702d192ecd586e7ba622fe22314477744538df2decb01028bb15b569d0879012033e02e21e7e999ac2e04ed009bab93eb9359adfae1a5e15dac151db6dea7e7bbb928c4347cba6e488420e9c2bd509b7cd2475a2b39d0b2c2eb87035c474b50edc8e029569990fed0d8029fcb39d89eaa472eafa35987b0e6c819859c3e740cb4d0df76adeb4159c987f96b2fa15cb77d01925b162cf2cf2bb60bb171f6e34601b0ae797b31d14afa7927fa551a461169c7a37429ce51dbfbcaafb572092c25f1f1bcd224e71b5816c7ec9763d5749ec50850d8078cdce5a4611876e702688765b29c58e5de0c229bac703d81576b1c41660ed6a1edc885384aa2a134c60855f617f89668d55780e576d9cdc705f25edc7834aa8c52f2115c10d76bfd6ece6602f42b7d5009b84ef0962d9de477eae8ddd8af32fe3baa60df582008facf3a3544de7b75e39f06b1af4aa009b67af22feab39cf6bdb1124ef0421cf0607be403b0e40fb602738d79c9016df609dadba5fc348920fdf82db61e236f7a27fa44ffb0f5d04fb6d365395cd2e26f3b79826269bef056ad37dd258f1789c799426cb5595c75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bb9f94af104a116bd67f5cc9bb9b862a518db3d2599f39de780392b0d5a72c30f14541946e1cf92393992e5ef2191ac72b106fd890d94444e74600720cd636c212e839b87dc613c826a9c62085431a96f79b8782d4b0fe31dfc75aede09e250a"]}}, diff --git a/txscript/data/taproot-ref/03b65143f1009a2a8a2f6b758fd8559f040d207c b/txscript/data/taproot-ref/03b65143f1009a2a8a2f6b758fd8559f040d207c new file mode 100644 index 0000000000..09028f3668 --- /dev/null +++ b/txscript/data/taproot-ref/03b65143f1009a2a8a2f6b758fd8559f040d207c @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf750100000056603c16bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf44000000000058d92c0486a2f60000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac1d010000", "prevouts": ["928a81000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "d39f770000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/padlongcontrol", "final": true, "success": {"scriptSig": "", "witness": ["fa77708f4f753ee0939477dd14179863ddef3bc880a8f335609fa93296fd108a0d05c747a90440216c01770041164364c719afd343ff34b1dba534c01de436f0", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}, "failure": {"scriptSig": "", "witness": ["fa77708f4f753ee0939477dd14179863ddef3bc880a8f335609fa93296fd108a0d05c747a90440216c01770041164364c719afd343ff34b1dba534c01de436f0", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcbca2cf1b4d989a3e309c3"]}}, diff --git a/txscript/data/taproot-ref/03bc1ab1714e0ffffffd3593268beb217c603b54 b/txscript/data/taproot-ref/03bc1ab1714e0ffffffd3593268beb217c603b54 new file mode 100644 index 0000000000..5de4da5cc7 --- /dev/null +++ b/txscript/data/taproot-ref/03bc1ab1714e0ffffffd3593268beb217c603b54 @@ -0,0 +1 @@ +{"tx": "077b85b802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5d0000000030a7fabf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700b00000000c47e39a703584e3500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc1d010000", "prevouts": ["75172800000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "a8e50e0000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090265347be1f1cccbaf5df8907cf7dacd344a716612ebc3cb560fc5c971b8c4c1031327ed44e3d3db8f2a6c3fa7270047ca3e0fb8d3181c0f79483f072706d0c1ed34821282d5ff88375dba3137ab8841a0dcc90314420a19cdb52d3ce9cf73065cf4917d1073712c952299eeb71fecc1ef61d7da57057864573e01ca802e5d5ab8aae93dc35d9e8865c313150e2dbe88ba61a1d49d0aa623ca1d9a40f9fe3c1dc3f9d07911f8bebdcb2a0dc458a05c6d7bcd2c58a30c779bef355529fa16afe3e822ca3e6b9e978a21e798ec4255b7fbf11e4fbe3be6c34d949f08b2e629ed6212d72a7def2f86d00c076678bc3d49fc6c022b9622330ee270195e2c7b2fe11492aa747c6995f535ed973446db7a8d6947a9f02f7d9311820c3ad3a28d3d1bee8b25af08b7b64b8e553430ef573bbd9542c028e9d5d17194fe70357372435a2d27ade8f0fef1fdc8e86e659fa05bfd406a01435f35ec82e372f414e608e7a6b9cdd7c617ac87d05d86791a5779959df85ba78b4fd440889c1d2aaf56cb9db10c8740a3b8625ed018c987cb05b11e4b4304d6172c7aea876226c8e5ffd46bce0200c02623fbeca2ab5dbc44b08145a1668b8cdebdbeb4fc6083e476546179aefc3098c637ee22a98cd34dddfa67e79737c477c778de7010259df66973f6e51b5e65182646affb23e028a8a929cc46e8dbe17f370f65e55700afd68267ab51212657715324cd07fb7ef5c375", "e67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa85f665641dd2adac3083650f9d93a4e0ff6d52a887a3a3677c2728d09852a8a99d11a7792f25f0da70e8485da42647201d1062d1bd001b767f1b05dec6877400"]}, "failure": {"scriptSig": "", "witness": ["4d09022d82118ada44e3fea673624994afc66bad92397c8b136ccdac6bbdc56245db6a43c1f85fcff07b09fe732657f9e6a700c2f0491035e688b8789978f8c08201b9eaef24419981e8dbc0dad5d1fb73cb4cd43f691d7781c628d06e6fc434b2d59f000ec963a0478d2d2f27ddd1ab0b1370fe98be1e28381ea5a5f7c21b10a5191d5e54512973697271df47434f8a034f8bc984e2d3c0ec64fdca0d1960685bcfab9bb57863cf91c2f2748946ac3862999b77b8a3e37c35addedfd103b1fbbe48b21f2de8440d5d4c1922ddb3a1194567266c8ce4fc59acce9fc99d1b50f4fc2eb1c5c4f875cc7e8b7ecf924d54fb6770105316c6ba5eca48bb8be92903c3aeebe6635663362a4d1efe4ebe7159fad8571fda3cf01bcfd9c89a92e1de286f60b04e2bb86c6f94d5546f457da3700faedef2c8a2568676f74022fac45dd67951020779c297c8c4533fc822a130c5ac4b459fb22560bb4d2a26ca04a20e818e41bf245195ef501a21341af2c79ee9423e280138bcb1a05a18bf7c26f47a8ed113b5ed97b44874431d6abcf48bfc3a947df90b6f1fee7d1d62defb32ab68b54dfb35d8af8db95b614560d99bdff7d12226a0c95ef60fc119cff197c61dfa41f4ade49148a997ad68c352bcda141e3b6271b092d93ec0bd148922a274a2bed64a7b8710bd40c7b8c03e213ecc97b991eae66d902e06fa67d27de2eae4e373a5167505d9e6f7339ba641bac3c475", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac9ea19512c809756aa5c58e4cd3562935caab0c2ca4eda8db33914ce4decb3cfe9d11a7792f25f0da70e8485da42647201d1062d1bd001b767f1b05dec6877400"]}}, diff --git a/txscript/data/taproot-ref/03bf93a96878a9f8ab6cdeabb7da6656971299e2 b/txscript/data/taproot-ref/03bf93a96878a9f8ab6cdeabb7da6656971299e2 new file mode 100644 index 0000000000..dcf4d9ae01 --- /dev/null +++ b/txscript/data/taproot-ref/03bf93a96878a9f8ab6cdeabb7da6656971299e2 @@ -0,0 +1 @@ +{"tx": "47c0016f0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700301000000248adfaddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca601000000923ad6d7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb500000000bc64099104f8507b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72f050000", "prevouts": ["71151300000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "c3c7480000000000235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "db32210000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ee", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f25297efdbed2aa8c1ec8b5437cb1f621645355ab4fec48723d1bef81dab8b605e01deb44bf60eeaa09a037ba0d53221083944f657819e2d2b55bb732cda3dfdd207214d6df2d18dfa237afd6016520e9e6ed6636ebebd182087bb183877c35439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d519b8dfaa69151d05ccddc10c8c1e468eb7b78f9ad17f99ee1b916fd61bdfbcfce40899fd8696dac9e3afc960f0a100b615a3c324ed3a125e98af98336f748ba56"]}}, diff --git a/txscript/data/taproot-ref/03ec899fb91c58bbb5676ebce177b0b63fa704a1 b/txscript/data/taproot-ref/03ec899fb91c58bbb5676ebce177b0b63fa704a1 new file mode 100644 index 0000000000..ac493c1f1d --- /dev/null +++ b/txscript/data/taproot-ref/03ec899fb91c58bbb5676ebce177b0b63fa704a1 @@ -0,0 +1 @@ +{"tx": "fb2bc47d028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43301000000be89569360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b101000000f904b380013e3908000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8790010000", "prevouts": ["4291310000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "39b01100000000002360212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["0c77e9f90c808108c29bf4f0eee7fe28be0cf50bb14d1f2d61baf0ea4772c38e7db30e1b807fd143bd3ee6cdbe06c2af20de4ad634330073b3d1149b4aaea84d", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/03edb43f652ba7e0ad56e117bab26ed1b3cc0b66 b/txscript/data/taproot-ref/03edb43f652ba7e0ad56e117bab26ed1b3cc0b66 new file mode 100644 index 0000000000..7e2a16594d --- /dev/null +++ b/txscript/data/taproot-ref/03edb43f652ba7e0ad56e117bab26ed1b3cc0b66 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb001000000037ef9808bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48201000000c798b1410490418700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd3010000", "prevouts": ["2c324c0000000000225120bf14cc6d2f64add112964063c7917cbfbca584b2015bb2b877e08d516634d692", "d1193d000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3045022100edfe03812173e4c65957e82650a060bccbc61c5acd076fb840b5006e26588f9602206e45846d2e23ee3be178578b2ca3a7dbfe49e2c59dbee2c9670a03a1fa7ea87803", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3044022075a06455df7b20225492f9e3a6b68b36c199ee9f47dffe33de5d5184e03d7bda022070cb646fd931c2a6e62e27739f564e67eb5ad82b5d332ee1dc706246d6e4284103", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/0401cdbd85422acd1857a2cf6024ba4b7b5d909e b/txscript/data/taproot-ref/0401cdbd85422acd1857a2cf6024ba4b7b5d909e new file mode 100644 index 0000000000..6f80ba9dfb --- /dev/null +++ b/txscript/data/taproot-ref/0401cdbd85422acd1857a2cf6024ba4b7b5d909e @@ -0,0 +1 @@ +{"tx": "55f3a2c603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5b010000003b874fecdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0b01000000e740bcee8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4580100000096508f98011c849e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac56000000", "prevouts": ["4ff72300000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "9d0f53000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0", "b9943e0000000000225120beebf2e29d62b55aba368e7e892512e69e2ef37d942bd7f6bc768a8958380305"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902186868f5a49aba39336c7fac1fccedd9e432f0b9208b9bd2ee9e0d09e6a93c86743368b82265f4a755e42a71776eef04a7f548cdbace159dd5156fe1f0e436baee748c28de426195b330bb0f57f5063b78d02d48131f65ca2ff5df87d41ba016df5cc54ee19410223521f4cfe48699df0fc934b0ead5a57b2accd4984f49b69d1c8506e2867dc9409c6fd8737f53343668a26debd293e65e04f0ed187b745da016b3477c5965683e03b3780db59a6945f22d122bf20d5ffef5bc24974cfeef66e01fa2d6bf5b9360f125fac8fe200344c1f684aad16f00c9126997ea9cbd72e33c7e712cbde801d47a634c7df00706652cdf4683099aadd1af94e4ff71495914ad7ce3a43855f379dda6ba5eee3fd85eab78de66f2ddd02b249f1a7ba655b874d736218cc7f5ead91222e183623d860f1e0170d3b442d08ebf67e2663b9f847deb78b435204059b09237df46056ea2b1b6703b83b7e03abbc1ef56c15b46c81b4f1afd2d12275de54381ce1efd2428da6ac745794dcc4cd76ab9fb1ae39a8b5b74e7c10b6fcd9fceeed2550fb50eacbf3152992d8cd0d799fb345f3c4164dcdf7c2435e3f4af5bed9394b273a31d63665d42e5a50d07ce849b94dd48a7e9df822ed193a46fd455a7869aadbbcdb03c49008672d15da2b9243346cd5b379feb2de18c774b6142374d3bb8f4592a3b0b45b06aae1de7d3737b78f4765ca1f846573d7273b4d81fba51e175", "a77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082146d6305f54208d13896b102f4aea30badeaee99896cb007ba6ff00553e24c3b2915fd873a4966f8e9b4a3b328eef3933245a1c852c287990317c3760d8289da96773453f0744a158be0509abdec64f05b1db7ccf03251d8359952271b442a24"]}, "failure": {"scriptSig": "", "witness": ["4d0902adba052ef3b7f1f9c73d7fb2caf16d7e56b2a8bb485272f0b81fdcc4a2489707719be15d2eae049fcff8ed09471a560c4b1faa7c5397212214c7d202c003f5d69a4c9fb2f2fafa2142a3e2304471509d9630047a556c4c43170770c360f017fe932fffec7047d0cd013b465ec747e570437acdbf472c9dd837808488f1ef1c917c9a46bcc7f276cbd732e2aea11c8e9c6e2ec769bffe42289a89da5e7a87aafece139edb0a6671f674a786e4bd1667b2325499a20b87efb5165378522107c7d57c465c120bf358b23aabaedc396007606e3d425d2cc33cca71fee916265a302dcd391736163a0e6f08464e6007ff1b217b64a2c127f450e75f7dcfd2f43de96f03d390986a5d6a52cc6e315a6a5fcf9b6e22d54c5b93a81fdf34c4f01073eb97b702188dd17715ca673b79d05ea524f4addb1e07fd906359fe869399c8e682c3cd355ed94c418b72b2d7ec4ac09a4e84b193e031a5782174e6357e4384783f6a926f2f57ee4d50b0f251a857b195cf47aaf0358e3ad921de76b524e36cc3d277b599bfcd8537fa0a282024c591fb23de6f92764f8e690d1ac37adf47c8e8f7a43103390fc49d97117bb83e4ad50d3209d12afcf15acc6b1c1dd088ef4790e5a1b10b337499858d51832c1c300f202d6e19c91bd54b87beca78e8f29e10c7355774453bc5a9182449ff53d972e8a9c6c3add5cad9bb28dcd10808877aecd62cdeb565bef8e250df241e75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ed1a62e8154f816026f7403b3a9565755790b01b86635a59f42302343c6f3dd69619a83ee22e28c5507e71eab09869c4e19cd00c1b769e62c37a8de310ec2a6696773453f0744a158be0509abdec64f05b1db7ccf03251d8359952271b442a24"]}}, diff --git a/txscript/data/taproot-ref/040d05cbd66190be71c513b0ebd00bbc34debe8b b/txscript/data/taproot-ref/040d05cbd66190be71c513b0ebd00bbc34debe8b new file mode 100644 index 0000000000..64a3bf86df --- /dev/null +++ b/txscript/data/taproot-ref/040d05cbd66190be71c513b0ebd00bbc34debe8b @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4d0100000097b2f1d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff300000000335a90e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43900000000f069d69701a1ee2600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aceb020000", "prevouts": ["98775d0000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf", "e37b73000000000017a9148462ed29696925d7688e1db8e76ef9e6667f05b287", "74ed3100000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21551f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["599545692eed16acc6ed23622eadfbf98699e55a84d0ec9431e80c8c0c234e9837aae449445814abe7cd48a61719937fb7c323ee98203f0e903c941edc17b58e"]}}, diff --git a/txscript/data/taproot-ref/04369027c0cf8f61083f8faeaf5d15a4bba2cb26 b/txscript/data/taproot-ref/04369027c0cf8f61083f8faeaf5d15a4bba2cb26 new file mode 100644 index 0000000000..265febe0c9 --- /dev/null +++ b/txscript/data/taproot-ref/04369027c0cf8f61083f8faeaf5d15a4bba2cb26 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c424000000004c7ffa9e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270120000000067fecfca02e2db4a00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc71c501441", "prevouts": ["8aeb3c000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "adf20f0000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["30450221008e7924b940b4ee77a40d8c9c071e4dbb61736bd178eb2019aa5d0c9ba76a022b022015f77f2b5791496908100fc43681d4d366f8af4630d9c2efdd48a4a16987fab681", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["304402205a4634d78cd7d210cf1551300af2cd466b9ed3b18ff568e6bafe3bcfb25a38ae0220055ac9545dd9559aaf2f619e6bb3f785fac840c1065df3742022a2a7f23e406881", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/043ee2fa352668d08af2912ea4c7dc868039dd7c b/txscript/data/taproot-ref/043ee2fa352668d08af2912ea4c7dc868039dd7c new file mode 100644 index 0000000000..2bf293fde0 --- /dev/null +++ b/txscript/data/taproot-ref/043ee2fa352668d08af2912ea4c7dc868039dd7c @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c26010000008481b789dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6a000000000539fbbf038fa4a4000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487c283824c", "prevouts": ["38d65900000000002251201902cefa81d0b0fe2050344a0485b195b36f31ece5900d0426a9de0fd01dcd1a", "f9154d00000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f650677a85498c606c782b8f888c9310727e5031ed3d767ec20b675f0ef8f617"]}, "failure": {"scriptSig": "", "witness": ["6a1e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/046dee126274f9efbec0b1803cf0483b40e0bc0a b/txscript/data/taproot-ref/046dee126274f9efbec0b1803cf0483b40e0bc0a new file mode 100644 index 0000000000..ee85517757 --- /dev/null +++ b/txscript/data/taproot-ref/046dee126274f9efbec0b1803cf0483b40e0bc0a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3c0000000017ddeeecdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfb0100000096479ad303c0b99c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac86e9c54b", "prevouts": ["6d6a48000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "fe56570000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_0", "final": true, "success": {"scriptSig": "", "witness": ["93765305a3fae08d9a1b1d28b4b2065aa3d6f1031fd31a5e3b926f65d534a5dce6eeb59b0d59e42719939f6e7d4ce9883d9276137c979d255bd3c1c6af7c6335"]}, "failure": {"scriptSig": "", "witness": ["babdec7f600efe50933dfc100c4e0d503430f6be4a7858f1996d6ed735afcd79769e2e7aaf9b694a12c1d47f0f6d7fb8673f6b9301634aed5143e8167a04b877"]}}, diff --git a/txscript/data/taproot-ref/047736248915b6ec7bb882618f4c6428dc10bc32 b/txscript/data/taproot-ref/047736248915b6ec7bb882618f4c6428dc10bc32 new file mode 100644 index 0000000000..3588f604aa --- /dev/null +++ b/txscript/data/taproot-ref/047736248915b6ec7bb882618f4c6428dc10bc32 @@ -0,0 +1 @@ +{"tx": "2718af9003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbe01000000e5a9b0d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7701000000d487d4b6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7c01000000a122a7d901541e3f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e1010000", "prevouts": ["436e760000000000225120cd69e6502803f0acddd51df30ad464e69e95dcae732a2073690eba6ce00d0199", "a2f375000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "0988520000000000225120a98c6fc01fa4c9d83199250e6e76cd0e9fc22cdfbaba8827d6d131a9d8267c4e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646cb5e8c66a9ebf72f7ffb8f0d067589f8122f5d919b65c933101887d7d058af"]}, "failure": {"scriptSig": "", "witness": ["6ab0616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/0496f56b7283138d77bd26aa97936a80588bc908 b/txscript/data/taproot-ref/0496f56b7283138d77bd26aa97936a80588bc908 new file mode 100644 index 0000000000..c5a2a858b2 --- /dev/null +++ b/txscript/data/taproot-ref/0496f56b7283138d77bd26aa97936a80588bc908 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3c0000000017ddeeecdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfb0100000096479ad303c0b99c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac86e9c54b", "prevouts": ["6d6a48000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "fe56570000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f268", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045726f0db9cf92b82453fc0fb8c6e624f8035b680f8d4bf4414d1abd8846bea56401b5a419c18d23e8c03ade77009761f1ea37c255231895048329572c11717ad56187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f36ca7668fa45ed948b1c8d1bea39db523e0bba5358b896321d776a78fadcd6f726f0db9cf92b82453fc0fb8c6e624f8035b680f8d4bf4414d1abd8846bea56401b5a419c18d23e8c03ade77009761f1ea37c255231895048329572c11717ad56187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}}, diff --git a/txscript/data/taproot-ref/04a0415662e8fe755a1cad7e31e996b0f9553a15 b/txscript/data/taproot-ref/04a0415662e8fe755a1cad7e31e996b0f9553a15 new file mode 100644 index 0000000000..cf0b4cf93d --- /dev/null +++ b/txscript/data/taproot-ref/04a0415662e8fe755a1cad7e31e996b0f9553a15 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf7010000007a32a641bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff50000000030c813b30337aecb00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7aa000000", "prevouts": ["f054530000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb", "d4857a000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "be7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd522f1cef67c43cc160020062cdc11d631b4f6eefdd5e68f18dfd86aed0bbdde4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8c20793b34d3eca391845c9ee05577f0fe1c8a49b621d2ce1a9da4783f236266e6f69f1f3a976918b4a05b157c0a8e21d478cce8b5d78fdf690138c8d187dd5c9"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb7c20d175283666615e94eef717cc04c54a6d9612bfb359a13b4f03ea50e15671092566d000aee18de877d7d37a6499dcaa40717b87fb42c4af8a156e9c8751ba72dfb389a6a0bb3f8b3aa7842bba2225719f72a11deb6eb959f4e6afb1e08b911ebac8c921821ba74d98d656401ec4b56b2bfe8f672693a939227457b8b1a2"]}}, diff --git a/txscript/data/taproot-ref/04a9e5bdcdafa1f723281d72593020692f3b5004 b/txscript/data/taproot-ref/04a9e5bdcdafa1f723281d72593020692f3b5004 new file mode 100644 index 0000000000..8cc7a9f11a --- /dev/null +++ b/txscript/data/taproot-ref/04a9e5bdcdafa1f723281d72593020692f3b5004 @@ -0,0 +1 @@ +{"tx": "08ffb27f01bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfab00000000334465f70206687300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acabd39529", "prevouts": ["532a750000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e768", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93664ec3f6c98a66c6847beb09afa70d74962ff9c9e8b80ab563ab503c0812acea03f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826cbd7cfc5d340306ce0f8e37fe1bfa8aba9fd4064e6187eeb928db0d0bdab726391a14412c925771c32fa4c7776d5872be2a56fee9c5a8de868e7e6e5a4c84da"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ee9caaa52dbb5b2356b97143365eda72b121d3e2ab2e725af8b99797f1a4e7c0809bd2604b63a9913b428e9bd239a7888c90ad67a336710c360335112147f5da391a14412c925771c32fa4c7776d5872be2a56fee9c5a8de868e7e6e5a4c84da"]}}, diff --git a/txscript/data/taproot-ref/04bb5c8ad218b2ea6cbabde04b776a727cb804d3 b/txscript/data/taproot-ref/04bb5c8ad218b2ea6cbabde04b776a727cb804d3 new file mode 100644 index 0000000000..8396e69665 --- /dev/null +++ b/txscript/data/taproot-ref/04bb5c8ad218b2ea6cbabde04b776a727cb804d3 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba101000000a9a32afc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ce00000000d3ee6bbadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf600000000f28de0af0335865a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb813d458", "prevouts": ["5519240000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "15bb0f000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "0239280000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "483045022100a6c5a91a092958f8894c0f8d9978c5eb068bfda5fcfc24b850b97988f146ae8702200e9256ebbaf450ddfe88150fa324f2c18b284c0de17870691d27f3aac83b120e932102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "473044022028aa0294c582a0e055ce32f145b187a3e18bd48f37a8a76895a79872fa675e7b02205553461a848c955cc16628c50c7bc5fb21e3701f48d09f1f307e591abba1ffd5932102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/04c14170bf3650e0dee112ba4b888f2e76fc3b69 b/txscript/data/taproot-ref/04c14170bf3650e0dee112ba4b888f2e76fc3b69 new file mode 100644 index 0000000000..9aba5801b7 --- /dev/null +++ b/txscript/data/taproot-ref/04c14170bf3650e0dee112ba4b888f2e76fc3b69 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2e000000004f19aad78bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a9000000008152fdb1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8b01000000bc4390e0033a13a400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d3c8e225", "prevouts": ["20dc4d0000000000225120ec87a05d11c16a148e05f58a688dc5bed4b2941085b66901aaa75337acfb52a4", "f0dc3300000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "0f0a25000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ba7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93679583417cf0de5689111c04e71e0d01ec961f10ecfecded2a9e36ca9bac8c22da47630aaed9dd66550bfcb0f3b3ec2bd830a8a42bcee9dbdef471b4e5cf2e89f5668d978bcc8d3ac0b8aded42d2a4a1c5e69a5396581e310868cb48ff813edbf"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670c450feb28eb0f8b74116aafe4d624d4bc8d2ad8551ccd2959f6334db4959b5a0ef97ab7ee9fc1eac24be41bfdadcbb7c9625a4e882ca5abbd81147d09c0527a47630aaed9dd66550bfcb0f3b3ec2bd830a8a42bcee9dbdef471b4e5cf2e89f5668d978bcc8d3ac0b8aded42d2a4a1c5e69a5396581e310868cb48ff813edbf"]}}, diff --git a/txscript/data/taproot-ref/04f498a7f3cfb530edcae02afc0d1476b8fbcd8a b/txscript/data/taproot-ref/04f498a7f3cfb530edcae02afc0d1476b8fbcd8a new file mode 100644 index 0000000000..585ac71e87 --- /dev/null +++ b/txscript/data/taproot-ref/04f498a7f3cfb530edcae02afc0d1476b8fbcd8a @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704a00000000197308bfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8000000000a81903c801c1d73a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796b73c7c53", "prevouts": ["6d9e100000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde", "456f820000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "067d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652d640cff0c4ca0b51ec04f00e7d6ca5ab56cb8e34eb7266cfd1f29ce54ee2fa85587f46271ff71c1a8d3d9e62b351dc1e7761b3de349b9de66c491fc83cbc116ed3422fe95872366e2174646ef4116c9fafb56aaaad9ae25dbd472ec9cd0fc1c48ffafb7a4cf249a6909d8fbff6ddfd3f500331ce755bc2f73b79afc0800987"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e2edee9d6f4a8cbfbb4a0af0dddab94d753895c3cdd7995db9d6f3e266cdd0bebd1973e93f7ad3f562801731a237f358bfce42fb636b2a0dab3a823989e87b4ae"]}}, diff --git a/txscript/data/taproot-ref/0526255fad6bcad83e0f38f3e175d8b55d0113d3 b/txscript/data/taproot-ref/0526255fad6bcad83e0f38f3e175d8b55d0113d3 new file mode 100644 index 0000000000..9d246ed0d2 --- /dev/null +++ b/txscript/data/taproot-ref/0526255fad6bcad83e0f38f3e175d8b55d0113d3 @@ -0,0 +1 @@ +{"tx": "78fb85ab02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7e01000000c5e6ddac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708e0100000019cdf7a804af2e3400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acb51aa824", "prevouts": ["0c31250000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f", "2b311100000000002259202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "947d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360bd0ac8016dcf75d48c3ac69d2580b72b0ba7cd77592bc6631039a54a132ee505432af4ca45b9bbe99b3e8be0ff589ddab81e08d94f2d38bc0283112328f69fdfe847a112bc0d43d64007e06b59459a0c0ad8818c3210afd17f00e931ed6a3b8"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936301899a4270bb6916b9141aa84e043e27ca85cd4d827e482e33ee8eaa8161c9e7085091e7b587d9e3d903161356c0634077d7e43e5aac1c0c25d5c3c805eac670235be472b05f11e998cd7dc8896eb16b23bac01933cdabddca8bd45937e3454"]}}, diff --git a/txscript/data/taproot-ref/0530510aa69fa36a6377468b144a6daefe9e0779 b/txscript/data/taproot-ref/0530510aa69fa36a6377468b144a6daefe9e0779 new file mode 100644 index 0000000000..d2c1de4e1e --- /dev/null +++ b/txscript/data/taproot-ref/0530510aa69fa36a6377468b144a6daefe9e0779 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0202000000b786b0918bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a20000000008aab3a404e02093000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47878a82972a", "prevouts": ["2360560000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "88d43e0000000000225120032ba6f397146bf93cda2585b16902a48899558623e6c842c83c4de6509e8b52"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c5b305c186e9c550c1f891932feea0e9cd4c7688ca45dc8e9b187d3246f8c99e"]}, "failure": {"scriptSig": "", "witness": ["6a0b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/05645a121a9dee2f1e618d22d9c0e11f1729c008 b/txscript/data/taproot-ref/05645a121a9dee2f1e618d22d9c0e11f1729c008 new file mode 100644 index 0000000000..f1f41ef7d3 --- /dev/null +++ b/txscript/data/taproot-ref/05645a121a9dee2f1e618d22d9c0e11f1729c008 @@ -0,0 +1 @@ +{"tx": "17f2605402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc60100000098f115be60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270230100000050702df8027ffe3200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48752b40928", "prevouts": ["5c6025000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "9a19100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f8", "final": true, "success": {"scriptSig": "", "witness": ["acce478862100e38361491bd945e99d878d7c209ca2466b06a8958a76f6f4fc2b10ee9cff032553be630ebad7b867179e1f6765748c8f3045c0e7ce6b430e4cc83"]}, "failure": {"scriptSig": "", "witness": ["b2db7022dfe0f5d2d2ddaa02534f2faa1e42c0d851740edc1a40039c8d7bc312761b2c9da391696f41f6f8352d39353ee94c4ad3768f79b09c5ba0a9d2d57957f8"]}}, diff --git a/txscript/data/taproot-ref/05723fdb3ecd4a3d4acc01d8ce541e74f11ba38f b/txscript/data/taproot-ref/05723fdb3ecd4a3d4acc01d8ce541e74f11ba38f new file mode 100644 index 0000000000..4ec79bdfbb --- /dev/null +++ b/txscript/data/taproot-ref/05723fdb3ecd4a3d4acc01d8ce541e74f11ba38f @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703f0000000024d521f4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbc01000000e8ed3cd4048e26370000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac76000000", "prevouts": ["ec7f110000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "7866270000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936266992371c49134ecc3cd22e54af8ffd5ffa261d20c402b4c0da0de3b849e1f1f98bea6a80fea94b985145b0732d825e6fbd27add9cac654f3749fb201eaf5c0cdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1770c141d000b7389bcb028eba0df2d51be96e98815503d59ed22f20e414bb1bdd3571a06a1d33120289e06483b2785a7356eedf367170ec7792d3587508789d4da9670c383f4b71f5a22d48df0589bd68dfe195935a65f1aeaa80f10f8ca6973"]}}, diff --git a/txscript/data/taproot-ref/0576b0175f23da9546b0ed7d213c1bdf55941dcd b/txscript/data/taproot-ref/0576b0175f23da9546b0ed7d213c1bdf55941dcd new file mode 100644 index 0000000000..0956dd6b79 --- /dev/null +++ b/txscript/data/taproot-ref/0576b0175f23da9546b0ed7d213c1bdf55941dcd @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49c01000000fc23b6c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b040100000067f7ca9b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f0010000009dd718dd01c92f7a00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac43010000", "prevouts": ["ad873700000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "baf1220000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf", "f44440000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a58b6826c45b958e6a43801c4f9a11218097d5d18de4cdf93890daaefc8ad62d7d143406647e47f2aa45aee5a8d37fbb079fe3a633dc3f79123da3b3ed47a821a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bf5896ca46bce08ea2cd3a2aa0391d54c59b6987085b2861de9c65df3f5b29ee99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45e04c998862288954a26ee7ce146837a88020619bd4ef6b5d2b0b49b83f7fafffc7f9c78871d6a598c7c7c3f4c8210a5c47caa8abf9700608b6e75845c74a6c5"]}}, diff --git a/txscript/data/taproot-ref/05a7b91a73da2203e485ff51426532165c688040 b/txscript/data/taproot-ref/05a7b91a73da2203e485ff51426532165c688040 new file mode 100644 index 0000000000..6a991f080c --- /dev/null +++ b/txscript/data/taproot-ref/05a7b91a73da2203e485ff51426532165c688040 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca2010000006f1d02720215695200000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796208d153c", "prevouts": ["a0f7530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c3", "final": true, "success": {"scriptSig": "", "witness": ["1576b15728f36c1aaa93f11db6c9bdc1b071cf0560a8d9fa87cd8ad0bfceb02e1ae7c6d34166db4273141aa4413f2c7a966cb7a906ea6844dcbe0d5888e6ab2d03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7a62ff08fdfe196332f5092e6d2a3ea47973d5284e5574bbc9aa3222143f62d0cc6f31eee34f662763ee3028d1dbce5ad51b1989d5040835f378384609b58c89c3", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/05d3a449ff645092d95ff6fa07d433d341861837 b/txscript/data/taproot-ref/05d3a449ff645092d95ff6fa07d433d341861837 new file mode 100644 index 0000000000..f123133d0a --- /dev/null +++ b/txscript/data/taproot-ref/05d3a449ff645092d95ff6fa07d433d341861837 @@ -0,0 +1 @@ +{"tx": "4a4547c3028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46301000000d1c47481dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b90010000006136b0e302a00c5b0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898718b3c029", "prevouts": ["4bef3800000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "d1392400000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "473044022054554f319c3795aa4a008926b3d564d699315ae2fe362eb1ab83128392896be70220144c04d7f15e0d82069520d1c36f0bd5f7ed8c2d42d2386749f3f3b264a7aa45024104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "483045022100e8b5c8e27b4d3120a70ae403b885a224bfe2bb31f385665cc08f7bb87bdc096a02201c6fe2cfd3d16d4eacd377af6ce78d7746e1b2a9e95b6ed78d4d70328af19507024104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/05e7d1f74a0f0d69935dcee5b60fd0b08ff396cf b/txscript/data/taproot-ref/05e7d1f74a0f0d69935dcee5b60fd0b08ff396cf new file mode 100644 index 0000000000..507d1510b3 --- /dev/null +++ b/txscript/data/taproot-ref/05e7d1f74a0f0d69935dcee5b60fd0b08ff396cf @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4db00000000fb0b3489dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bff01000000ea7ff3a203f9225a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc75f7548", "prevouts": ["524935000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "93f3260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_90", "final": true, "success": {"scriptSig": "", "witness": ["7337baf5e1481f981491127edfa649a51943c66757f9f029ef9bcb15bab0f31f4fd8cc4d5f96191468c3d7b011083c36dd742fbc4c4a7e5a2a901f64cc0f152001", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["abba4f3beb209d4dc153b59c58acee686622d181b79b538386b806c18685e4031c1909f4685c873c0a726923429d12c2b2343def9e628420dcf2cec6298b55d090", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/05f2dfea38b07d623e2947cc2c7963f25a45e24e b/txscript/data/taproot-ref/05f2dfea38b07d623e2947cc2c7963f25a45e24e new file mode 100644 index 0000000000..6d58ff300c --- /dev/null +++ b/txscript/data/taproot-ref/05f2dfea38b07d623e2947cc2c7963f25a45e24e @@ -0,0 +1 @@ +{"tx": "bbfdf13103dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba801000000044ebdc3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba3010000006ee87db8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0700000000b29ebcbf04633b6a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc791357b23", "prevouts": ["55991f0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "bf142400000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335", "5a22280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_4", "final": true, "success": {"scriptSig": "", "witness": ["d7a4de15e00961d988e4ac3f11e36dead0af966fcc97ce922dc435dd9573b8def6cf418e70726de23090f91a058eb36d779521aab880d3bc49245bb5b989e7bc03"]}, "failure": {"scriptSig": "", "witness": ["4250137e209af13e73d9d4b423b7459d0bcf20813e4d75427dcdda2bc89e28ef152d866c961e2771fe8dc9ef92c9d3bceb55908dae0976b510dcbd2d1397d53a04"]}}, diff --git a/txscript/data/taproot-ref/05ff688173b90131ed218e693cd3e0735c88955a b/txscript/data/taproot-ref/05ff688173b90131ed218e693cd3e0735c88955a new file mode 100644 index 0000000000..dfffe09aff --- /dev/null +++ b/txscript/data/taproot-ref/05ff688173b90131ed218e693cd3e0735c88955a @@ -0,0 +1 @@ +{"tx": "0200000001a86a862f8a1bc1808f7ba2abcc71e2c0ff30c2c698fc832f6545a8dcb978b6cb0100000000d612f0b5043c3da44010000000160014ca9858c362545bc83a3b93e73b12b27a9b3ca003580200000000000017a914ca5375a68588393c82c00f5d2ab21f91e99aa5ce8758020000000000001600143f886f8feaf75ad7bedd5713d4d148e7c97c11345802000000000000160014bf1a19526352877c6b170dd8786dc91b1610ae1ca7010000", "prevouts": ["bc9aa6401000000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_invalidcb", "success": {"scriptSig": "", "witness": ["3450353dceeead4aeffc66c2623942031803cc26b4417f85fee94662355c0cc06ade70ade320622ef9465ab480f3fbe3614e16d5bcdf8e49a8dd4d2a6abbe867", "20cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3ac", "c0cb0ba18c127bd01c924f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f312f383ce02997bd7885b2023ff24b4d79c49e77348af650460f5903df7baafc9"]}}, diff --git a/txscript/data/taproot-ref/060f27e89600b0edaefb344b00420aa71360fd11 b/txscript/data/taproot-ref/060f27e89600b0edaefb344b00420aa71360fd11 new file mode 100644 index 0000000000..7a3ee038a4 --- /dev/null +++ b/txscript/data/taproot-ref/060f27e89600b0edaefb344b00420aa71360fd11 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb9000000001e948b94dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b63010000003a5b129a014d5c680000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc10000000", "prevouts": ["2162530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "da65220000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_92", "final": true, "success": {"scriptSig": "", "witness": ["a9f6700bd6df58bceaa4597de51e0fa2e1e6a82d27393f0ace9053aa9fd3f367376a5715a22c87cb958d3163bdff15193be416b68feca647a8cdd056dedb9f3101"]}, "failure": {"scriptSig": "", "witness": ["84d14dc499dc1e3eabcc5034d1fe1b9e102d6c36c6410edc2abe97c85167b0a06e34f8ae3bbceddead34c1b1821a96c80dda92a87e155f7ec2be54f487e1067592"]}}, diff --git a/txscript/data/taproot-ref/0621f65ed4f98e0fc3ba2caa915de84ac2773b64 b/txscript/data/taproot-ref/0621f65ed4f98e0fc3ba2caa915de84ac2773b64 new file mode 100644 index 0000000000..691fa91c97 --- /dev/null +++ b/txscript/data/taproot-ref/0621f65ed4f98e0fc3ba2caa915de84ac2773b64 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709b000000007f3424108bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4af010000004517a8d7048319420000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875f000000", "prevouts": ["e4820e0000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "3867350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_29", "final": true, "success": {"scriptSig": "", "witness": ["beddc99585101211d166f1161dec6948a6f5976e2d29d9b7eb5347db8a42ef66cd4be058672497360f1216eb4f078d697ec07da884dcbf6710355643ac872b3181", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["072a0633145d14fe087930b8e08bd67bbcb251ab0e53472d7c1d78373cadfb352712f1cf65e74305237d9b02e9528ecd95aac0b757eb00d8d3b15ff66cab8a1729", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/064cb40080f9955f34713af8c9ccd370c7ce8d39 b/txscript/data/taproot-ref/064cb40080f9955f34713af8c9ccd370c7ce8d39 new file mode 100644 index 0000000000..62a14bc6ef --- /dev/null +++ b/txscript/data/taproot-ref/064cb40080f9955f34713af8c9ccd370c7ce8d39 @@ -0,0 +1 @@ +{"tx": "997c8d6803dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb000000000b13b4e848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fc010000003b13f7f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf4010000001bbc0c8c04cff9dc00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870cba8322", "prevouts": ["4d2151000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec", "2a41350000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "170c590000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "597d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee343ebd89880aabef0f18c5bef462b16920a32508939784a2317d7ebda32c7f1d0160c53d01d80ab4be204ae4e021ad6f56ad3990ac4b37baa4678d530d3ba4ecd61c62feef9509bc7b3762bc81079411fa6867ea4986820580c60fa1e8298e9"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369246ff60def872dcd9425d4b182836bb1c9ba5ca30c9708f02d69701de6960d646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faa393999847c63b69274661db27cd2e7bb4343911a06570db858c301dc754c7eb4be962498b383c32e8a84fa570ade752f3a2216469b10dbfd65078bd8e1b5998"]}}, diff --git a/txscript/data/taproot-ref/064f3862567d3645a67ad42e8f1234919491ef00 b/txscript/data/taproot-ref/064f3862567d3645a67ad42e8f1234919491ef00 new file mode 100644 index 0000000000..00a11318b0 --- /dev/null +++ b/txscript/data/taproot-ref/064f3862567d3645a67ad42e8f1234919491ef00 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfda00000000be838db68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e80100000074bdb79c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b0000000006cc0e3ed03fdbde60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a613ede228", "prevouts": ["566f7f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5c51330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0198350000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a83", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936648b8fdbc24ddaf6fda4be3c15bd53c3c8af4eb62251b7ead54781f83ba5fc3b8ed6c904d531fc0d19ced9482d4cbb64035dc55104164ba190923612d3f9e9a82b9d1447cbfb5d72d5da72ac5ad193469eaa6b44c038aa23e2a9d2dd480586adaf3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da4a1468d71fb79ddca97f2d0be02d5c32dc1eb93332690a2fd408e08d38e5e68f4301bf594f01c0bdeaf5c3d617f0344f5f915f3ffa16d6ac31751e310f3332b0bdfd7fd43775a37ae3e20c8f8514aca25517db969733cf8d9f690f9b6d8ea23f980255362d30444bd4a09dfd60422f4fe5b70b7cde78729ca8cd52cb50aace"]}}, diff --git a/txscript/data/taproot-ref/06689eea577fd577cf0ed48baa3396126bb6f1b5 b/txscript/data/taproot-ref/06689eea577fd577cf0ed48baa3396126bb6f1b5 new file mode 100644 index 0000000000..a7d59e0283 --- /dev/null +++ b/txscript/data/taproot-ref/06689eea577fd577cf0ed48baa3396126bb6f1b5 @@ -0,0 +1 @@ +{"tx": "36cdf06c018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ee01000000c0f713de01703f22000000000017a914719f78084af863e000acd618ba76df97972236898778000000", "prevouts": ["1847330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_23", "final": true, "success": {"scriptSig": "", "witness": ["11c8d2d2d77f80429dd899f88143ae6f988f00b7c9efe7d938d51fa2547f2c50debc9a4745150d77db2e9e0c24d8fd0057ddf5543e537bb0384616efd364915201", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["78ac00751bd1251df05faadc67c597881293ee1ecabd0418f41c375db6ed526487e20a8c65cb0156e7b83cf4086ca18dd83083b0f74fe6e580d8143b7859d8e923", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/0672af82ea3c78b3ade4b7424ecf5c00466fba2e b/txscript/data/taproot-ref/0672af82ea3c78b3ade4b7424ecf5c00466fba2e new file mode 100644 index 0000000000..88b19804f0 --- /dev/null +++ b/txscript/data/taproot-ref/0672af82ea3c78b3ade4b7424ecf5c00466fba2e @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc10100000045d79042bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf650000000093c03899033fb4c3000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac0a030000", "prevouts": ["9f9c520000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "0ae7730000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f74c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e6bf3ef0c52029538d60b405bd64e2cc9734303fd934f9ee1f37723dcf17f67fbe0beccf8b53a38f7a20d51eb008bdc60f78fac094fdd23935202ece673d8622376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}, "failure": {"scriptSig": "", "witness": ["4c52f7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1dec24bcd5a84e558ba1632e81361cbfb2715ab9fa3d579aef34157cfe08620975813d9fe920e311eca68d9da8ac683d4c5ffd57c03f9174ce1b6c58fb2e14cca376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}}, diff --git a/txscript/data/taproot-ref/06882dd6d50dc8061c56b887fa16764a4db5cc51 b/txscript/data/taproot-ref/06882dd6d50dc8061c56b887fa16764a4db5cc51 new file mode 100644 index 0000000000..b7224ac412 --- /dev/null +++ b/txscript/data/taproot-ref/06882dd6d50dc8061c56b887fa16764a4db5cc51 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca401000000a89fb6d18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d9010000001d4379cf0321668a00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689870d020000", "prevouts": ["d6ca500000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "40f93b0000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dab42da502f2250da43a527a2c86d70ef22e86fb8286b7cba8088edd55a95ebde8db2f81248ad9ed5128a6abc5bb92ba3aeb558dfcb95d0b55c9fe030b8e1ae1c9fc6c767d5aa72b6a61d813f4dedd67fc97d91e71acf86e276ab6f41d1da0fa8c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bab5c143898502b1abd6718354496239c5165981c0d5d614586abbdfb87575999aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4e05de1aec4dcfd94364dc697d2506f2d3dcb95f0b1cd2734b3ed6d289f30b19a3cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}}, diff --git a/txscript/data/taproot-ref/06aa8b12e6ae5c391fb3d92c4050218d552b6923 b/txscript/data/taproot-ref/06aa8b12e6ae5c391fb3d92c4050218d552b6923 new file mode 100644 index 0000000000..9d86883916 --- /dev/null +++ b/txscript/data/taproot-ref/06aa8b12e6ae5c391fb3d92c4050218d552b6923 @@ -0,0 +1 @@ +{"tx": "97afbbe90160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270aa010000007d516c87016e320700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acbc030000", "prevouts": ["432b100000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["bf4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cddd07b9b59a457ac18abed7266986241d091147981a1ef9d43f6473969f25041ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045911e2ebc11e8ff6aef3c08be5d8086fd4b944e3e1f7063038c1b6dadb4d48ab0219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c00247f9d8df68482c9cba9042da753e4cb10c5fb7c4ff28bbbb197976934ac148ad690b4db681210d49373d4012b83591ebe1050d9c81702caad07f4cd5bb9faa736b6bec5c04b20c5b38998d4f897a7594adad2cf377758bae1284900c20e3219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}}, diff --git a/txscript/data/taproot-ref/06b7ea9f43da11b479b267aca3bdd7cf6fb9cfa7 b/txscript/data/taproot-ref/06b7ea9f43da11b479b267aca3bdd7cf6fb9cfa7 new file mode 100644 index 0000000000..792330930d --- /dev/null +++ b/txscript/data/taproot-ref/06b7ea9f43da11b479b267aca3bdd7cf6fb9cfa7 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c8000000008115ba958bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c485010000004a1f0fbd0350b06200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7624b9d51", "prevouts": ["7b22320000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30", "9234320000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c268", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b9602a0fa147d5a6995f53504151ef0f1c99d37971b01cb6c21f8bc7a527e93d60a46f1edbb097ed18057c0e42fb935953c4336ec9d443d16e55ae39a225d9f2f0288dcf8f2e1e03125ab45cd0efca3a23715e7661e5c17627e98d50057f87374b5cd80fb8cd7c947a98554a389db356265b198fc72df311d010d98c3d6e3928"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d5c78237289a8636bb429226e0de9c7befeb1ddb6aefa0b188bf3d9b51e606da144e2b32fb029cde325456c88021dd04a80b93e0665f7e39c1e8a56bfdcaf4a64b5cd80fb8cd7c947a98554a389db356265b198fc72df311d010d98c3d6e3928"]}}, diff --git a/txscript/data/taproot-ref/06e74af8b10a6ab9ce11036f2747f8034ec3febf b/txscript/data/taproot-ref/06e74af8b10a6ab9ce11036f2747f8034ec3febf new file mode 100644 index 0000000000..2ec861e71d --- /dev/null +++ b/txscript/data/taproot-ref/06e74af8b10a6ab9ce11036f2747f8034ec3febf @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7900000000f330f40adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b590100000008d985f0031e937400000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac2cb95a1f", "prevouts": ["9343500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a6ef260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_be", "final": true, "success": {"scriptSig": "", "witness": ["efda24429d139dd7964b3f3923dfff8c4e7934d53387dfa110b912083d14f9ea5ef852d3ccf60772a205f9e5f658eb3aa52b90cfeb83fac4c71db46599a6608e81"]}, "failure": {"scriptSig": "", "witness": ["bbcd15b5296d5628463756efc7405c482007a0ecf43b2a5b1b60c1f31447b8812a767d8c06fadb8014d21ebdc22a32ba279b328020eab220e95008123bab3ef2be"]}}, diff --git a/txscript/data/taproot-ref/06f54531f7cc822f36462b303f5eed8313ca07f5 b/txscript/data/taproot-ref/06f54531f7cc822f36462b303f5eed8313ca07f5 new file mode 100644 index 0000000000..ab89b0da26 --- /dev/null +++ b/txscript/data/taproot-ref/06f54531f7cc822f36462b303f5eed8313ca07f5 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be500000000e3fccd6e0404431f0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acba000000", "prevouts": ["a4fb2100000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "", "witness": ["304402207247050860ceb4e196d3b1f5c057e6ddd839afbacb556d7f7098e299fc8c78ea022017e3c0252268a13b78d7351d3d3ec355c8f6620cc53dfffb6ae119361e21450c02", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["304402203bd0af9847bf68ab8778f9160de97b5e9caaf7e8e5b866e72bb6c3dff5c3bc3d022079f5d9271d0a58ca69a9dadaafc365350b753d7bb69345d335e17ee20768a88a02", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/07249b6446b452a9005766194cb824b77c6ed600 b/txscript/data/taproot-ref/07249b6446b452a9005766194cb824b77c6ed600 new file mode 100644 index 0000000000..52abb33067 --- /dev/null +++ b/txscript/data/taproot-ref/07249b6446b452a9005766194cb824b77c6ed600 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d8010000000971c6928bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45001000000c3f02c01025ddd7800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac80ae104b", "prevouts": ["f8213e0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "65c23d0000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "2f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e478f34169e056cf51b9394d2ada3735c0a63dc9f48f236da8ac021a74c045d29ed6bb91bf977e9e370b444e9d5512cd4ec7f3694a9311c01272a4c1a167cd930"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360eb2d35c2916f6ee10417bbe503f487f009b40ae689b59f28732d8e6ab85ee945f3be5f8f698e83d3665b890524642b89b7b05493241beec338309aba778c454d8fcf0fa02e125fe1892f3caadd01fd66f2ae3104b90b9e35e4c43083bce335e4e9031d393e93ec4f3e9da8fc51e83b82f31256dd96ef4af94581a47eb5c67bc"]}}, diff --git a/txscript/data/taproot-ref/0725dac7b6c36d404b706902e2a350065ba66fbd b/txscript/data/taproot-ref/0725dac7b6c36d404b706902e2a350065ba66fbd new file mode 100644 index 0000000000..d04851e82e --- /dev/null +++ b/txscript/data/taproot-ref/0725dac7b6c36d404b706902e2a350065ba66fbd @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c489000000005bca01bcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba70100000054f58ac701aac509000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487adb94525", "prevouts": ["3bde380000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c", "b5601e0000000000225120dfb9bbe67fbb4eb318568f7b177f9ecde078527d023b90a4ec13e543e4037efe"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360f84a3d63b5b1872a1abd5454056145b48969a3f6a653dce575a0a82ad7f58cb"]}, "failure": {"scriptSig": "", "witness": ["6a5d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/073b21ccb622912fef49f0555d5ed7b6ea85ad7e b/txscript/data/taproot-ref/073b21ccb622912fef49f0555d5ed7b6ea85ad7e new file mode 100644 index 0000000000..3794884c29 --- /dev/null +++ b/txscript/data/taproot-ref/073b21ccb622912fef49f0555d5ed7b6ea85ad7e @@ -0,0 +1 @@ +{"tx": "56711c2a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b55010000007a913ec4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccb01000000598666940321156700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac6c010000", "prevouts": ["f4382000000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e", "6595480000000000235a212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51419220fa8a7a918b3857a082d32be9fa2ecc61d36b58eead0239ee9c5d9d4afcd5a470b8497850c3a230fee464eb343180400453804118582df887251250b2f1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ef65a7bc88e8caa9953fbbe68415f348dc7b3deedacdb598041f1438fea667b18959ac4fa8a57d164b76708dc6f63c2efb2484bc5a77a391ceb66b2f5ad6b35f745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}}, diff --git a/txscript/data/taproot-ref/07904e76401a888153be57bdc173982a4396aea3 b/txscript/data/taproot-ref/07904e76401a888153be57bdc173982a4396aea3 new file mode 100644 index 0000000000..2eb4cf819b --- /dev/null +++ b/txscript/data/taproot-ref/07904e76401a888153be57bdc173982a4396aea3 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0502000000d16cb6e660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127073000000003ed0908104709196000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdfd17120", "prevouts": ["10ea8600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190", "a4a0110000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936725108a440ed4012535da7c85222e4fd4d60d8ac1b151397c12e7bd31b62cd6b31a3099151dd9022c8ab6721206c57c00ed937e9f62099522c543aef8c2ea8dec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08274c6ee35a9af327fa74c94c4ba87a09a7dd613a1ede58e30654f1c4a24a66737074cc5cf84a1d913e1f5647d3427cc0d6d469f0e5b86c78a49890e87126542fa0e1c61743bed8ba943c0dc40e80402f7423773c7111097ca9c5a140b1b3c94b9"]}}, diff --git a/txscript/data/taproot-ref/079662a69dfd16ca9215a4e0c822fc44641e72ed b/txscript/data/taproot-ref/079662a69dfd16ca9215a4e0c822fc44641e72ed new file mode 100644 index 0000000000..9571e14fdf --- /dev/null +++ b/txscript/data/taproot-ref/079662a69dfd16ca9215a4e0c822fc44641e72ed @@ -0,0 +1 @@ +{"tx": "c99d682202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5e010000002c0ba2bebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf67000000009fdb47ec02affe8e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79659a35950", "prevouts": ["2cbd26000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4", "dbd56900000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "e47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89220988768fa939e91d6ac18545dc908ae35e0fbdf4f2079456a337e4567f1e2befe4cc2cebe7bba8b4a4f82666342333b91a450af49acc0f1954b5763bfc142"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93627a793cd26d083ba6aa51290dd61966260e2cea77d3c953e5a10e1c750a41acd9220988768fa939e91d6ac18545dc908ae35e0fbdf4f2079456a337e4567f1e2befe4cc2cebe7bba8b4a4f82666342333b91a450af49acc0f1954b5763bfc142"]}}, diff --git a/txscript/data/taproot-ref/07991f2bbd7bbe3fad499b0c428f795590321613 b/txscript/data/taproot-ref/07991f2bbd7bbe3fad499b0c428f795590321613 new file mode 100644 index 0000000000..fc283766f5 --- /dev/null +++ b/txscript/data/taproot-ref/07991f2bbd7bbe3fad499b0c428f795590321613 @@ -0,0 +1 @@ +{"tx": "8e8e60c302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3d00000000e9ad4fc0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfe00000000630dd0fc01f5cf80000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478754000000", "prevouts": ["9422520000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb", "671c5000000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "737d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e85062220981136031499d54282dd1dc217e6360b68c94112219f47c832c6b09fa8cadcf9bcd23f9249fd09eb8b2b9ca63044a0ccef58f4cae9402f6ead4c2071"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa1755d4e71afcc10f3d2573fa2263bf007b883f1245d387f3f26fe0befbe96d0f3ec5aec6a85c1ca54f3417a27e00c281f3765ee450a46261b59de169989c9a702c501a2f323d94577f3c4b353be8e702d3f9991edd341efb02c3132264010bb33a63f37675deadbbcd666ca6b38ad7090050f3dcc6bba45985e955ec185c53"]}}, diff --git a/txscript/data/taproot-ref/07a56716b603afd041d05639404b37744bc2b83c b/txscript/data/taproot-ref/07a56716b603afd041d05639404b37744bc2b83c new file mode 100644 index 0000000000..9009b5fc3a --- /dev/null +++ b/txscript/data/taproot-ref/07a56716b603afd041d05639404b37744bc2b83c @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1f00000000624a02eb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127095010000009ed305a30279d36200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac70030000", "prevouts": ["fa02520000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "73761200000000002251202ea95065368f678e25a669a7906e1051ddb7c321fda55e7bd6b39829f3117b75"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["cb4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936140d663498a4274ecf7f45240089a1df766efe22ae76bf8a987a78cbf23a246a1937db199a07e1996385ab03857d8e2ee63e136796e4b408281aef544a937c0c73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}, "failure": {"scriptSig": "", "witness": ["4c52cb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93604078a57b801774f1511fcfcd4e29746b07fc4b44c1e1428c3fe5e43ff6be5a920e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e191fd70f8e44f42202023c580ea06f1578af3f03a2439147535e7b1f16736e0d18859d05a814eb862cab9a6acf3b7acf0881c47896b22b56466b77992f62c0511"]}}, diff --git a/txscript/data/taproot-ref/07aa3010d9cc23f67f6962a7c18f7dedccd7855b b/txscript/data/taproot-ref/07aa3010d9cc23f67f6962a7c18f7dedccd7855b new file mode 100644 index 0000000000..f498a1cd93 --- /dev/null +++ b/txscript/data/taproot-ref/07aa3010d9cc23f67f6962a7c18f7dedccd7855b @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd801000000872a088c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c418010000008af1d13301eb745300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3d95c32e", "prevouts": ["a1705a0000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "2fb636000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "897d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa58e965213f8dbdd3ccbab86b6d585f0f8e78abed831015bbc989f3cab476ce59ac632f1e88e109b3d5485dae08acb0148fc939094c3a94300b3efbd66c89bc20"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e8e7fff1bca432c9ba96d0556d2ed7bd47849d71950e18b52879751e42d3038d46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa58e965213f8dbdd3ccbab86b6d585f0f8e78abed831015bbc989f3cab476ce59ac632f1e88e109b3d5485dae08acb0148fc939094c3a94300b3efbd66c89bc20"]}}, diff --git a/txscript/data/taproot-ref/07ae5671fc31d245f515f5c967b4e7cfed38567b b/txscript/data/taproot-ref/07ae5671fc31d245f515f5c967b4e7cfed38567b new file mode 100644 index 0000000000..518c54a60a --- /dev/null +++ b/txscript/data/taproot-ref/07ae5671fc31d245f515f5c967b4e7cfed38567b @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702d00000000d650368ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8701000000b6f15db004cee659000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7efa05528", "prevouts": ["f62210000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "f6ee4b000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c068", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663c49f3bc9f550c63855e2d5fc0a261957d370018a90e39a0a9924b5c04b4f32f827dd3f971806aab342b51fb6c2519c5b3aa410ee2eacb06207a66da829722129de37322ddf566a2356077a247b666bf816d75bd62d8842c555909c8a1545e03de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d753e4c48a29c49a51002f402079443dae545bd96b00a3a5880d5a88ed66a5a500c8753d4e6010499b58065b36892efcd9281a64e85ebf7c5dcb8f6f4baee16c3de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}}, diff --git a/txscript/data/taproot-ref/07b8ee857d10f18474e7471c3c27d10be12c5f25 b/txscript/data/taproot-ref/07b8ee857d10f18474e7471c3c27d10be12c5f25 new file mode 100644 index 0000000000..3a26949920 --- /dev/null +++ b/txscript/data/taproot-ref/07b8ee857d10f18474e7471c3c27d10be12c5f25 @@ -0,0 +1 @@ +{"tx": "02a25573038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44300000000a45df2cd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d7000000004530aec2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c62000000009004818202ae91bf0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478724ab1f33", "prevouts": ["520e3100000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4", "942a410000000000225120327dc9effbe915b227349282cadfcd45dc438d4f1c3ec72713111ad7587a718c", "f2415000000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366db23d78c6adee92f78ed0a395ed560dcca3b184d0294b17d87d5ff6314e6d5c"]}, "failure": {"scriptSig": "", "witness": ["6a25616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/07cbbc0e4129794730bb9bb49d334b497f11b422 b/txscript/data/taproot-ref/07cbbc0e4129794730bb9bb49d334b497f11b422 new file mode 100644 index 0000000000..aa5d85eff2 --- /dev/null +++ b/txscript/data/taproot-ref/07cbbc0e4129794730bb9bb49d334b497f11b422 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6000000000f1c183f860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b201000000b9cf07d303a0995a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca2e5a443", "prevouts": ["478e4c0000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2", "d047100000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "717d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa135cf860bbff3a99fb4ec2fdf299b3a63be6e4cd6baa7eae64af9a923e2398def4fdc20f1f5535ceda7aadddab857a143114b7886b058839365016ac02e93c97"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365ed3e5978e160b34ed2da7d8b0e41bdf70d28308fbcd927b9d3a78fa41469786135cf860bbff3a99fb4ec2fdf299b3a63be6e4cd6baa7eae64af9a923e2398def4fdc20f1f5535ceda7aadddab857a143114b7886b058839365016ac02e93c97"]}}, diff --git a/txscript/data/taproot-ref/07d68512aa206614c478ec869a8b7d4f7c32333b b/txscript/data/taproot-ref/07d68512aa206614c478ec869a8b7d4f7c32333b new file mode 100644 index 0000000000..b42fd97f50 --- /dev/null +++ b/txscript/data/taproot-ref/07d68512aa206614c478ec869a8b7d4f7c32333b @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700100000000d4506fd8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0100000000c19213868bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4df01000000e0a85df0028455cb00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acece8b33d", "prevouts": ["2e421200000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "1de97d000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "8ed73d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936070bb467edca609e1a3246a8ba31e6266509d0d4e74e5fb2a32359b5f156527204d1c6645dfa5bcea0755bc1d945f129b754bcfdfa4df703b30809220c35586032cb43424d7ca27a7abc5fd0c2fa249f92b1e992144deb3864a86d466f79c2cceedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93672fb7b0b8b9d34fd164052a9d1d97e8f2f76026babd1f73e719809b132cf1e5b464f19ce228e2f316c50129d6edd6267acdc0242055b306d7ddf31bf4be6326132cb43424d7ca27a7abc5fd0c2fa249f92b1e992144deb3864a86d466f79c2cceedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}}, diff --git a/txscript/data/taproot-ref/07ff10e93b7bf06e8da854a647ad08d5bc902326 b/txscript/data/taproot-ref/07ff10e93b7bf06e8da854a647ad08d5bc902326 new file mode 100644 index 0000000000..ee691893a0 --- /dev/null +++ b/txscript/data/taproot-ref/07ff10e93b7bf06e8da854a647ad08d5bc902326 @@ -0,0 +1 @@ +{"tx": "a890ed2e028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dc000000001f541de760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700601000000ecb8d1e201aa403a00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac99020000", "prevouts": ["ec3b3f00000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "f06c110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_9b", "final": true, "success": {"scriptSig": "", "witness": ["4a759f3cd1e4a0694f3ecab49b9fb8b1105aa45bd3fedfc0e466ee468604f08d6b0f0b51c255b1478f34acd7e9282b818c5005828be1d56dd641bb72d72b465681"]}, "failure": {"scriptSig": "", "witness": ["1604cbbabe361b73faaf2ef6187ff51b79098bf820c004152c14e1af0d6048e47c451ccefee48a1cc76d0116eb1185a950a8565ff37f7ad81c1e66d36fc41d709a"]}}, diff --git a/txscript/data/taproot-ref/08106eb8543994958b201f3ce5f42dbbf19adf37 b/txscript/data/taproot-ref/08106eb8543994958b201f3ce5f42dbbf19adf37 new file mode 100644 index 0000000000..6b8508a59b --- /dev/null +++ b/txscript/data/taproot-ref/08106eb8543994958b201f3ce5f42dbbf19adf37 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7001000000fe2a26babcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaa000000006e3943b604070dc800000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987fc927851", "prevouts": ["7fcc4b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "59217f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_96", "final": true, "success": {"scriptSig": "", "witness": ["cec646cc69f13f2bbcac7aaed897dcd0b3d9585a286fcad369bc4b434669e2be41856dc069c2169609f3dcb3898a0a75d5b40a27f2f623f8b09d4eaa8f4fcf4803"]}, "failure": {"scriptSig": "", "witness": ["b03291d79fd59944fa0c87ffeb37f8e2a795a1d103f274afe4db0745384bd147f0c8ebef1091d6d71a5f59c5c636dfe2b42c55bd290809e2a3575216122904b096"]}}, diff --git a/txscript/data/taproot-ref/081a75fb52ef536975050ff3192f6c516b3b557a b/txscript/data/taproot-ref/081a75fb52ef536975050ff3192f6c516b3b557a new file mode 100644 index 0000000000..fccaca4682 --- /dev/null +++ b/txscript/data/taproot-ref/081a75fb52ef536975050ff3192f6c516b3b557a @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8d000000009628e1ab8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f10100000041654ba460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c200000000352cd7d102283e7a00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7eca46228", "prevouts": ["be4828000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "99de42000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "344811000000000017a914d574841bde7bf0817694c799002118e85acf040e87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["db4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361eadd57732c956dfe38750ac99bf9f6a185a50e2b535aa6e427b8b7d9ced3e4c3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082a04823906532712c3d4cb334ae6c7c41a1294a824a25b5277d43f47953a1da33e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}, "failure": {"scriptSig": "", "witness": ["4c52db", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fdf92fb2c16504bc9198e70ee5e2872df4025bad8bb2a722e84a5b213bdb644c99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ba0f4accdd80d494e1b95824e4feb55c95caee559d90e25fbf6396e2b6be61303dda2dfca806ccc9c3ad62846e64b9ac16121de5d926db5bebf2e82f8dec8d2a"]}}, diff --git a/txscript/data/taproot-ref/08421b069ef3b27abeb764e8412aa879c8bfb0cd b/txscript/data/taproot-ref/08421b069ef3b27abeb764e8412aa879c8bfb0cd new file mode 100644 index 0000000000..0c597ae556 --- /dev/null +++ b/txscript/data/taproot-ref/08421b069ef3b27abeb764e8412aa879c8bfb0cd @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700c000000003eac70b460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707f00000000d49919bd011e8c0700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac99020000", "prevouts": ["e78610000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7", "39a5100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "267d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2135dfff529a8c82f4e399fa9509c5b3ed194ad634f2dd2a3feda036a1773d4612b49f68f31842330decdce79aecc48c70a85ed65081abd3cb605a7bb4f89ac9cd4c02f64c49cc162ff9325daec6263c98ea78a2c5346e44c6d55d79722c7edb"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361698797c10f7187c2383d0e226dcd2087587d02c12a3e721aa4a470e9466395a9ed12ee2db6918b2bff03768a1c947d0f4fb00a38b9989b1add1650628df27e9913d4be53f363cb6dc14d29c1d7e4819045cdc001ac228b3b700074691e2599d91e402d116972020cc4db8f7e1431e7a7416668817d422dd270400f40dd8d238"]}}, diff --git a/txscript/data/taproot-ref/08630f23c6a755790aea6ed91128183d6ddc8291 b/txscript/data/taproot-ref/08630f23c6a755790aea6ed91128183d6ddc8291 new file mode 100644 index 0000000000..1e7082bf95 --- /dev/null +++ b/txscript/data/taproot-ref/08630f23c6a755790aea6ed91128183d6ddc8291 @@ -0,0 +1 @@ +{"tx": "67740b64038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48b00000000cbcacdbcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a010000009adeb4bedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd9010000005dd15aca02d7dc9800000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac56737540", "prevouts": ["ff1f310000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "d85b480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6f8f21000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_3a", "final": true, "success": {"scriptSig": "", "witness": ["1baf12dd595451dc6e061dc85971849281a59ce923b4dd9e5c71906b5f1aab7ae1ad709d24f63537e368ad07b86fdf8747a3adcef89d5d0ebc19d640d885305383", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["56f2474ee41a5df06a56fb69998211768db21c5418bbb1df3b9baa95b084a65402d9195bb969be51016361e8d7bd3a5a148737533394790b737722145711ba8f3a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/086661b19fe6034d3748295413e2b4d4251157aa b/txscript/data/taproot-ref/086661b19fe6034d3748295413e2b4d4251157aa new file mode 100644 index 0000000000..076bd01525 --- /dev/null +++ b/txscript/data/taproot-ref/086661b19fe6034d3748295413e2b4d4251157aa @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e601000000f77c8100bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf780100000075a884cc0355c5ac00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd9000000", "prevouts": ["6fdb3400000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "f282790000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_83", "success": {"scriptSig": "", "witness": ["f34b66da181de5b1e7cc51a57058c475f7ad24e1d1bb4467c6db55c2faee0bd10e8195367e7f72d51559b0aee8c60eef65d3e1ad6fc11f0df622b437a999653a83", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50d31224d31895d5f93214e389286652f6716bf1e190d51c9b23c1b205b5ba743072b263b80f96f7d373613400c7547c85c9a6c31c55cebcafc8a8c9dd42f67ab9f66679e23e5d1aeca7d76d761fe889aad74eaab38bd9ac5093e43d732ef19131a45721770a4c6fa3892249946f81f8a22ec2b808bf909e9901e6eede46863cd8b1b6893ef793c36e5dfa85d62fef0fbefebd0bad4f9a865cc0"]}, "failure": {"scriptSig": "", "witness": ["2580f77d8bfc0fa5330d36a68d182c3d90a9cb020ddb046a9ceb3486c59bacfd142ec9637a3c90b908fa4fe710e4a1cf75cc11f03547b8f74e130e1c1726e5a783", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "5057a54fbd5d4b07929441b26b64d130112c537fa56ea4ac84c490dc2f4d68a42c3570b5f36314017256e821f3bc76214ef0b973ba2d3f3a3a66e88df751"]}}, diff --git a/txscript/data/taproot-ref/08a0635b26ef56d2f6ddd4c31295a8bbde840584 b/txscript/data/taproot-ref/08a0635b26ef56d2f6ddd4c31295a8bbde840584 new file mode 100644 index 0000000000..41b857f62a --- /dev/null +++ b/txscript/data/taproot-ref/08a0635b26ef56d2f6ddd4c31295a8bbde840584 @@ -0,0 +1 @@ +{"tx": "4cb277ca02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbc01000000987c9ec48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48a00000000ab7f4a8301368b720000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7960c7c812e", "prevouts": ["9c487c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7b65400000000000215a1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["f8715e58be64394a10159f3d1c9c715912297ee6d2210f80979aa46ef71fd8cbac68d41553095afec7b14a4e3f5cc081463aef8d2ce3d98c0e772eae2ab24088", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/08a19ba6422f65b65cacb3f20b5507bca39fffc3 b/txscript/data/taproot-ref/08a19ba6422f65b65cacb3f20b5507bca39fffc3 new file mode 100644 index 0000000000..8fbf37ea38 --- /dev/null +++ b/txscript/data/taproot-ref/08a19ba6422f65b65cacb3f20b5507bca39fffc3 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe800000000f78152b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3501000000776103a803669483000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58000000", "prevouts": ["8c6f65000000000017a9148bc1125bf4e3450c593a5be1ae9a05461832d39a87", "f6cb200000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "8d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829640e65f27972e690b56e28a8f49ec76fed3450565b59143bd547c42619e148d8047789ecbd47ea83af97bdb87f8422a4707031714ddb05eaa38b24e158a7c35"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360a8a801582dd903a75de5904df4445cb714185a34938b03fb7716e9516670c429640e65f27972e690b56e28a8f49ec76fed3450565b59143bd547c42619e148d8047789ecbd47ea83af97bdb87f8422a4707031714ddb05eaa38b24e158a7c35"]}}, diff --git a/txscript/data/taproot-ref/08b5c0ff184e15e9c21e4949e2382b9a71623d3c b/txscript/data/taproot-ref/08b5c0ff184e15e9c21e4949e2382b9a71623d3c new file mode 100644 index 0000000000..9f6d938400 --- /dev/null +++ b/txscript/data/taproot-ref/08b5c0ff184e15e9c21e4949e2382b9a71623d3c @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfac010000005fbc51e78bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ff01000000a025c78004003eb7000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acfa151a24", "prevouts": ["c84d7d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e9ba3b0000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "bf", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db7a6a7e9e2eb861c5b236223f8a0e993b636b19808476c0a20268bf09779a38cc596949c599e703b9191d3ba022749fca5ec33c3492eb5532759cd445d2634b82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365bf71cf7816bf4c839ad04f64c439f60ca1e0c1202f6058d0897192eaa874d9b285ab48eb468144e5e6aa7ce6d4aa75a792c11a68b383289399495d27c15055ecc596949c599e703b9191d3ba022749fca5ec33c3492eb5532759cd445d2634b82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}}, diff --git a/txscript/data/taproot-ref/08b74fd5e5bdcfc0a22933abb14c20399138f612 b/txscript/data/taproot-ref/08b74fd5e5bdcfc0a22933abb14c20399138f612 new file mode 100644 index 0000000000..4c6a4e16da --- /dev/null +++ b/txscript/data/taproot-ref/08b74fd5e5bdcfc0a22933abb14c20399138f612 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf21000000004676830d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41702000000bbb7591260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707600000000094760f703733ebe000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc56f0646", "prevouts": ["044877000000000017a914b1a54d09172ecbb89289f2a670acc3fe14ced9ee87", "4656390000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "ea96100000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_3", "final": true, "success": {"scriptSig": "", "witness": ["d7b6456f201cf74ae23f528fa19076a87cd6787b60d78d7f8cae6ede245595824cce38957e3567f0634717543ddf7bae1e1d4620d2ac610a556e520ac5bfe7c303"]}, "failure": {"scriptSig": "", "witness": ["bc8faa4589338734df135c0ca3414dc0a62163edfc2c51b5f64898a53408c21f74f08cc0e3bf557b67b5f4a11806ccb8b0a65312491d3a627c9569459a9e998d03"]}}, diff --git a/txscript/data/taproot-ref/08cb0cb08cfb93d7ca744dbf018072b119fbc650 b/txscript/data/taproot-ref/08cb0cb08cfb93d7ca744dbf018072b119fbc650 new file mode 100644 index 0000000000..b5ed6a435f --- /dev/null +++ b/txscript/data/taproot-ref/08cb0cb08cfb93d7ca744dbf018072b119fbc650 @@ -0,0 +1 @@ +{"tx": "14fa46cf02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4801000000d70bd4f0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c64010000005783b2cd023169cc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac6b25ab25", "prevouts": ["0c20700000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a57e5e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_2d", "final": true, "success": {"scriptSig": "", "witness": ["7e300717a60ac55fdac518e5d9429f32257a2306c8a1ffdd0330ee8746e70be3277f2adc0f58c46255c40342ea996d06c4bed5d4b5334976cbf2177a1ee4e39d01"]}, "failure": {"scriptSig": "", "witness": ["69677d02c38b008c37dd52c9cd225831df3d9dbadac2bde0735c2f75b27472a945948273eeb2bfd7fb1d854347e7e8750e9cdd3fdd330c1687ff9f0a80e783de2d"]}}, diff --git a/txscript/data/taproot-ref/08cefa50635850a5a6caa88ddae4d4e4c5178f8b b/txscript/data/taproot-ref/08cefa50635850a5a6caa88ddae4d4e4c5178f8b new file mode 100644 index 0000000000..eac052aee6 --- /dev/null +++ b/txscript/data/taproot-ref/08cefa50635850a5a6caa88ddae4d4e4c5178f8b @@ -0,0 +1 @@ +{"tx": "1b7091bf0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705001000000fb6c19bdbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf80010000000a4e7ece028b5f8400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7e7000000", "prevouts": ["8822100000000000235f212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "1dd2760000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["57e0667e28ec049022631f787411974501133ec1fc2911cec719d1de6efc6db1783e2089ab96f7027a37435dd54893aec2a1ee758153f939cfc2a7f48b78fc99"]}}, diff --git a/txscript/data/taproot-ref/0918ed067691e99a0ac65b680c99b8a0bd6d2dc2 b/txscript/data/taproot-ref/0918ed067691e99a0ac65b680c99b8a0bd6d2dc2 new file mode 100644 index 0000000000..3216df945a --- /dev/null +++ b/txscript/data/taproot-ref/0918ed067691e99a0ac65b680c99b8a0bd6d2dc2 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd50000000053f403cadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8c0000000080e6db55bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b010000007bfc680003fe5216010000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc79aa1c358", "prevouts": ["f266720000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "bdf22300000000002251203d5ffb7cd06f5c84b56ec9f73ff7cc3a22b38565d229330748f260d30800c008", "acc68100000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004536ccddef3149683af65c31c85a3c06583d8e56fa5e9b8809ad6476a55251e65fad1faed220136b938a4936a71b98f5f9e86de449242d6a82efdf7a3adba2ae62745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}, "failure": {"scriptSig": "", "witness": ["4c52d4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936455dd346a6e8884f0fb95ea8c71bd7948dbe722bf7c03e38225b2fa9604e199b70b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d8657208959ac4fa8a57d164b76708dc6f63c2efb2484bc5a77a391ceb66b2f5ad6b35f745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}}, diff --git a/txscript/data/taproot-ref/0920b0864e2f856ec01587533e768fdc9f982a59 b/txscript/data/taproot-ref/0920b0864e2f856ec01587533e768fdc9f982a59 new file mode 100644 index 0000000000..007405290b --- /dev/null +++ b/txscript/data/taproot-ref/0920b0864e2f856ec01587533e768fdc9f982a59 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e5010000000f6b49bbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf66010000005e3d45c0020d06a1000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acc2a8f43a", "prevouts": ["777a3800000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc", "e9266a00000000001652142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["2be378d8e07bb734176317b5e7115c5678dbc8a9b591e95bec222e3bd303eed6c64f6ca230a44c3e80ea20e10c772c1b3b65825a41f508baf4cad948bfee4af4"]}}, diff --git a/txscript/data/taproot-ref/092dfb3e8b68e6142fcb0a354c4d02c23428b870 b/txscript/data/taproot-ref/092dfb3e8b68e6142fcb0a354c4d02c23428b870 new file mode 100644 index 0000000000..c9932fc68e --- /dev/null +++ b/txscript/data/taproot-ref/092dfb3e8b68e6142fcb0a354c4d02c23428b870 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2600000000d7f2c4e302b2435a000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7f7030000", "prevouts": ["74175d000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "483045022100b90463b19720a17907e34d06465ad5f60baab23b489b42b0e5f2e1256377f21402205e684ce7490e311ff071e05b8eb208c04be3b4bb035199ced6f6668f6a953f7b2f4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "4730440220412a88fe97f96fe569517b3cabd861be17ea143bf28c30205a0c192a25d8703c022006e1ae891ea74bb35556d88cde9be264e7722e342bfdb5678019d09783d737692f4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/09342cfa6e3461e698ef1f6aceb83fd4a3ccbf35 b/txscript/data/taproot-ref/09342cfa6e3461e698ef1f6aceb83fd4a3ccbf35 new file mode 100644 index 0000000000..97f9ffee2f --- /dev/null +++ b/txscript/data/taproot-ref/09342cfa6e3461e698ef1f6aceb83fd4a3ccbf35 @@ -0,0 +1 @@ +{"tx": "02000000012e09ffdbb2069feade9688806d408b21e4e24b0581b653f6a686a5bf690596fa0000000000436cd2f903305b7ed20f0000001600143f886f8feaf75ad7bedd5713d4d148e7c97c1134580200000000000017a914dfd1018683cfaa440400f061c02b281ec7e8e2d887580200000000000017a91402e53bc18808b3955166f5113b83b265fa421e998736050000", "prevouts": ["12fd7fd20f00000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/keypath_valid", "success": {"scriptSig": "", "witness": ["8736d0e96fabfd24bd45fbc3771242ddb5fa61dc00c00bfac51f0a981912f1b36c103fd984b420028aae849ab44624cb8301d97984442513133cafef4151d6c5"]}}, diff --git a/txscript/data/taproot-ref/0942d800ed811d505130b0e5cca50e722fc4f19b b/txscript/data/taproot-ref/0942d800ed811d505130b0e5cca50e722fc4f19b new file mode 100644 index 0000000000..496e6fde2e --- /dev/null +++ b/txscript/data/taproot-ref/0942d800ed811d505130b0e5cca50e722fc4f19b @@ -0,0 +1 @@ +{"tx": "2a4ba92a0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270680100000050b312a0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6d01000000f7b1108603868a800000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c6020000", "prevouts": ["7995100000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "cdad7100000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000095", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367cbe056fd5524803d39d9d872de87d596ee1d58542b57a2a09fc467d443df29299aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4c1a4178950446608ddf8409535ad79bdd567504e9e3f05b7b17ad70ac9eb9eeed4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c88cdf200e9cb41c74ff1734a224bd622bb601baa19704ac4140592d266c2a7878d069a3e06f8a8ee706e51fefe68609e4a48214bf7e1dad1e46f763a0ae6da54d6fbd68a9aac62cc0fc4848936fa6d465cb32a19d5a751074f74d9c4f7fb368ab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}}, diff --git a/txscript/data/taproot-ref/095bca4fc65d75681b759e14d34e7a5987625ab4 b/txscript/data/taproot-ref/095bca4fc65d75681b759e14d34e7a5987625ab4 new file mode 100644 index 0000000000..3847ca753e --- /dev/null +++ b/txscript/data/taproot-ref/095bca4fc65d75681b759e14d34e7a5987625ab4 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b74000000004fcd769dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9d0100000099219efd01df608a000000000017a914719f78084af863e000acd618ba76df97972236898710000000", "prevouts": ["b816270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5df17c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_5c", "final": true, "success": {"scriptSig": "", "witness": ["47c95e08771f68bb9e4dd1c5cf0be918327f9cedca27ad3ce00ec22c227394ed60b479071b0570e9dc435e6f0d60f84d5beab93fcb4cc18d0c72711ab2a094d382"]}, "failure": {"scriptSig": "", "witness": ["f15e080b96ee4f6a5117d8ced8ef43e304e35c5361937fb427282ddb0df9f539c8acec89cd4740689854b69148286c50ed776429aaa0fc8c4620fcf04e23ed865c"]}}, diff --git a/txscript/data/taproot-ref/097dbe987c217c3d9b230bc0e634a9e3f0bab2fd b/txscript/data/taproot-ref/097dbe987c217c3d9b230bc0e634a9e3f0bab2fd new file mode 100644 index 0000000000..562926b350 --- /dev/null +++ b/txscript/data/taproot-ref/097dbe987c217c3d9b230bc0e634a9e3f0bab2fd @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cac00000000e581b6e704f4065500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48779000000", "prevouts": ["32dd5600000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "187d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eaad0670a1a2805483e1b6119aead8e5c4f5e2d65383350292f138c62bc77d51b80858ffdbef3a81ff8eaeb69bf692b0617d2bdcb9145576d5843e6d9e5e1cb0c"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93658baf989b33fdf7a985d181ac7c72c0e79727fa5bf7d6725e5e076c24bcc85c5aad0670a1a2805483e1b6119aead8e5c4f5e2d65383350292f138c62bc77d51b80858ffdbef3a81ff8eaeb69bf692b0617d2bdcb9145576d5843e6d9e5e1cb0c"]}}, diff --git a/txscript/data/taproot-ref/09b3e7123f40c4ddb240073a912a440a18168c13 b/txscript/data/taproot-ref/09b3e7123f40c4ddb240073a912a440a18168c13 new file mode 100644 index 0000000000..0926934e6e --- /dev/null +++ b/txscript/data/taproot-ref/09b3e7123f40c4ddb240073a912a440a18168c13 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1101000000a081b3de60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127053000000000c7b5fdbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc5000000006f40e899046516ab000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c6030000", "prevouts": ["bf8d4a000000000022512074a4c3567b4c4ece2d1ea256a6bf2f85bf4dc051497bd8ce7ed8816e2d4c108a", "befc0f0000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "19b35200000000001653142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["5dcfa6aa91ce6da49a5c1dc23d4fb246deb6a5a93a275f981169ecd31cdf0e4a4e034b8f7a5c641927ca17720284b3f5e34aea6d9c96f79c6745e63a6fc75369"]}}, diff --git a/txscript/data/taproot-ref/09c225b7d61512e189a466c46243a4511b6eae8d b/txscript/data/taproot-ref/09c225b7d61512e189a466c46243a4511b6eae8d new file mode 100644 index 0000000000..382e1c2c3f --- /dev/null +++ b/txscript/data/taproot-ref/09c225b7d61512e189a466c46243a4511b6eae8d @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6c01000000b9a21ffd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127021020000007ef33ff3034d9e330000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748708010000", "prevouts": ["63bb250000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "75911000000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a922ac303092a6cb80a96afd5c7c243ba2385da8ab4baf3331612d0b9d31d6a7777e5a97eed984c98f8bc097a5ecd26814ddecb354a6d174fd826a31e179fc1bc382eac721f5d77f3709779bcbce4280b42008010e70d0a562a81fa2c4c1b7f7fd5b6fb9181510151652fd5eb41d40f94ed6292d29cb5ce365c2b2d5850a9d03d394d510ef0b1c601e81a235ab43c62f13399d7091a1d57334da623f787f533ebb7fbbf6a5f765e9f04e174764a619fe4ea8fca4ef5e0cb0b0c4f29d680fb28ed99b4258b91f82e5a2d3d59be20d98ab0c1338c62b36ea4038535b61d4d2d177b086aefcb77dfd85712b1617b9c7b1d65cb75d2ca349b739fed1d2abc6ce3bc714c4c1021e3b25fea1c3d07e02d5f12534f4e91cae5160c28094d8c7246fe7c6cf7639eaf5c65825e5da682018cdc3a24414aa77a36768f52e0cf192476ba0c879393c2d1b17cd8b2c32990c74201177ed022f6a9af26b2354fad690e9b23e2a0452dfbcfbed25660fd4e3d3e0c3fd9a9f60aac3b30d60b5ff1bda95d6b792e78fab815a5d25254cb36cbbe93df4ecd777f365b19320f34c1ca884c8c2a8493458a49b851efe928bacc9aaf1b5bf1eb83458a09cfbac7639295f1edf9c7387050c73bc4444bf11964b34a07b30dafa5fb861f7a61c485e83c0dcb6f6799efb743f91f8eafd31e3607a01df8ddc07f645ecf372e81d02bca2cab5a564ed6dca8b1723168fa0df1743c875e3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900451741062de046b8f3bdf7ef41b5db27631c489deab6fd85436806296af4173e7e74166a9b0f1c55c1671126e5eb7d3b70cf827ee1dc762db7ef6404d6cf84ba0da54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}, "failure": {"scriptSig": "", "witness": ["4d090268c590697e1ff9c25d1423bbc25d5b0159c38c30fb65a06cbefed7e0f0791e50aac7b5fc03b5cc8975d160d3594d272235a6fc4521f0f426f479e061e99ffb0caeb42a71b452dcc75b1e8e4f7595a597321e15216349e58c0c79569b8308944cab79ba12ad5355a6e4a0b9ba7f6be89db13cfac2687bdf0507f9bca7395d557c7b437b6be9902e38b4060006fb8219d474e923bb36808c9bc270f037b776888cc8ea3ca7f9b92400a362441778f9e1c8a13c53450a996c6f2e78e5307eca335f33b12e1b0f000de1401cd7f1eb3ad1e988f4db7917af6ad83ad232e9baeec51d4f306a1c4a32023d1570bc8f5e952a2f45211252950663565feda7336528943fcf4a8a7a23ddceae03d91048bfab3bcc4450f9c7cf7318fbe8e29c970938530bc4b80c36570982b27d0055a59311bb49894b286f753ac93681a4c663bfd8cf2b72c0fd2bb68098a8467508dd4220bd75eb2fb67d9399b2c277d936a43b910905fd7444adafd95ed169ca118b00b380a4ad13f663f49d4dc7dfe2b09f56069731ec1749fd2e246a3752d5d27defbab850abb6a5a158044428224d8314aacb93d68e71f4fa4823514537be93d1a65b22f066d2bdb188308cba8a6d04e76b51c0e0731a9f0687e03dfddcd0b0063f41e25fe4c6320ffc2ce7565386c9dea17b6e2257e3224bf000fe59e6e8a35a0cf3847f033b57faaa3def005bb597bf0569bb7a473885f1d912b07e3c7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362dd9a6a816a27714ed943cc25e1a1e39dd34d5569d3490ab6023dfe42a6cba430277e21fac1036469cce09bee47dd6f35fd38d265061a05632a5c9d8280907c6449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}}, diff --git a/txscript/data/taproot-ref/09cd349f59ff286840fb04789da01062c5d83ba2 b/txscript/data/taproot-ref/09cd349f59ff286840fb04789da01062c5d83ba2 new file mode 100644 index 0000000000..a10c6ac99c --- /dev/null +++ b/txscript/data/taproot-ref/09cd349f59ff286840fb04789da01062c5d83ba2 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbd000000008b1e38c6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6100000000422eee7f02753dcc00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac466b3933", "prevouts": ["6b948300000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "7a884a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "fa7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ab5229b48fb31f4aebc56e2dee567bf7ba352c6c3615b44a029752a401ad5af48c1a9074fcf4072701b6c332871422b1ccd41e69925b4b38aff436cff44d889284b3c1002850d4c89a68130d64a5a5ee29d0b1bb458f5120fd1f649ff1c37e66ac496a48f5e08c9a0063585476106fe61a3ff4222f4c7aaafd1f65bf01170e2"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936048c253878ae3aaf7983b8b419d3ff5fe49de177c40f616b90817e056f3cc67b06f1c7e5fb59ec6be7dc8dd9b5e5a9bf4b5e4bf2d4887cde3c9822cca7ddc75b6ac496a48f5e08c9a0063585476106fe61a3ff4222f4c7aaafd1f65bf01170e2"]}}, diff --git a/txscript/data/taproot-ref/09d7f478f35e48679ca5a97a08febfa49d510081 b/txscript/data/taproot-ref/09d7f478f35e48679ca5a97a08febfa49d510081 new file mode 100644 index 0000000000..913235d8f5 --- /dev/null +++ b/txscript/data/taproot-ref/09d7f478f35e48679ca5a97a08febfa49d510081 @@ -0,0 +1 @@ +{"tx": "3995509b02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c05020000006f476edcbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8f000000009096b4e5019114a90000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000", "prevouts": ["0e825f000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "336a680000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_8c", "final": true, "success": {"scriptSig": "", "witness": ["b2dd830aa16a9fd3b8a6d567462260d9063a4956bfcb1980cb68c50acaa289321d9d3311794ff9e589a3352d47652e16e9a2675b0d2d6e41b4e9b235f2c152f582", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1707541a32c6ceffb3038cc9bdbb74596608920000379ed6a93c3ffa61ee638ed6d043198826f277e11431cd2d2fafcd80a191656fc8057f0a7ef98c189cea168c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/0a3e2dd5f11a2182d7b86b927a600bde565229a8 b/txscript/data/taproot-ref/0a3e2dd5f11a2182d7b86b927a600bde565229a8 new file mode 100644 index 0000000000..ee526003ae --- /dev/null +++ b/txscript/data/taproot-ref/0a3e2dd5f11a2182d7b86b927a600bde565229a8 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46b000000000540a8d7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd30000000018732d9204c7b2b20000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5c000000", "prevouts": ["9d083200000000002251202ae35af575feea0dc18681bbd0ec0494b44b5926493fa5426b4858bf97ae878d", "4972830000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_42", "final": true, "success": {"scriptSig": "", "witness": ["8d8c44f14f15a7529f6ebd2573e08047a72348b7133320ea9b5d59bcae5d14810c7d770be878812fbb9c49135ba1ee6658ccf1105a661e74458a2e50ebb2d3b083", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["79db11fe61cced14eef34b841c4b89bdbd475ee0a749a817f406b3acccf937cba5b5568c9a20514887def0d5422a639187d1feca6f1182ca445a9e3d3d547a3842", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/0a9a9a6e04b0e55c5a90ca23c2586a07ae1fc542 b/txscript/data/taproot-ref/0a9a9a6e04b0e55c5a90ca23c2586a07ae1fc542 new file mode 100644 index 0000000000..30dd35e2bd --- /dev/null +++ b/txscript/data/taproot-ref/0a9a9a6e04b0e55c5a90ca23c2586a07ae1fc542 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6f01000000928f47ca60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c1010000000276321b048f28600000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc1683433c", "prevouts": ["d36254000000000022512055d32a9b44ee6fb3a2a0e7e2d6444c6afa4ce43aaa0c5357064383c70ed0d31b", "3f930e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_6f", "final": true, "success": {"scriptSig": "", "witness": ["b9dfa6e4602a68a3e727e8b6324c65adf31bfb0e849554f32e1be32860dd177e4feee48b1caad022448907a02332badc78c44661afc503291886d71fe448dc3f"]}, "failure": {"scriptSig": "", "witness": ["58f5560fab5895e3dd35ac7aa23d8113b7de0cb2df256b3a4900aa5264e93995bc5e4a3c7ea6f86156bf998769485bdbb30fd2725359835bf7a6be8336454d8d6f"]}}, diff --git a/txscript/data/taproot-ref/0aaeeea67c9e79315c703c56429535fd670ef5aa b/txscript/data/taproot-ref/0aaeeea67c9e79315c703c56429535fd670ef5aa new file mode 100644 index 0000000000..8189e96bb6 --- /dev/null +++ b/txscript/data/taproot-ref/0aaeeea67c9e79315c703c56429535fd670ef5aa @@ -0,0 +1 @@ +{"tx": "564957d90260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702a000000004dcc25e160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b100000000af182efc0194a10e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac93b72d3e", "prevouts": ["5f160f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cdd10e00000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100c370e2d294552c952dc54982c7ae7b7a1cb9feb56ee6637a5d18bd4bd3464cdb022040d6bf05500243fb6f1587b4aecdcd16bc12175e906527753b114b2b09e2d5bb81", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["3045022100cdc6ed9006971e967d7e22567ae7c9a89e580bc255cc7964cff1711f982d907d02200ed8f2b2d8efce97aef9c01a0e687c51fdeb267560b261f1893b6f9094ab89bf81", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/0abded429f191b0375a464688f06bd465af7c644 b/txscript/data/taproot-ref/0abded429f191b0375a464688f06bd465af7c644 new file mode 100644 index 0000000000..ef58b6d79b --- /dev/null +++ b/txscript/data/taproot-ref/0abded429f191b0375a464688f06bd465af7c644 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd20000000060f33779dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b70000000001ed470278bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ab00000000c60fe4de03dd71ba000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987a6000000", "prevouts": ["e3725e000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "5044260000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "2a20380000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000097", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692bf74884f2cec72519997a0395ff7ca30fc290a0cf462789b3d1378cedb3028ff42e4d873fbb915aa5b42e254ee79c6fd372778836ebbd6336959492b60478df213b900f5cb66b025bdcf0538d69427e8f93cfc9741b2125e61cf9215fad53f373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51064e90022f018e8cc473163b262248813e3dc7e43f487ab53623d6c75190b10b282285524a15c732567d099967405d35f7136f74f48f011bc4ab279ad8d14f14"]}}, diff --git a/txscript/data/taproot-ref/0abdf3a09f88ee47573f9509a323dfd8af89e021 b/txscript/data/taproot-ref/0abdf3a09f88ee47573f9509a323dfd8af89e021 new file mode 100644 index 0000000000..98eab7adea --- /dev/null +++ b/txscript/data/taproot-ref/0abdf3a09f88ee47573f9509a323dfd8af89e021 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b48010000003a3e7a78dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbe010000003e008dd90464f34700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875b04d52d", "prevouts": ["f08027000000000022512090f7a6000b5d616b8fab8dbf93f0441952f14900faa8700280033be77a40eb2f", "ef642300000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360089274d47cee2433e5e796e01aa5462b16341b60f863914d1ab1664c5146ca6"]}, "failure": {"scriptSig": "", "witness": ["6a54616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/0ad139668541c092541da58168e6488a1191ff58 b/txscript/data/taproot-ref/0ad139668541c092541da58168e6488a1191ff58 new file mode 100644 index 0000000000..bb511e42bf --- /dev/null +++ b/txscript/data/taproot-ref/0ad139668541c092541da58168e6488a1191ff58 @@ -0,0 +1 @@ +{"tx": "065bd6d102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4500000000c1b6cdc160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270180100000068d0aff1028cb48f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69a350326", "prevouts": ["373e83000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "e4e50e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b6", "final": true, "success": {"scriptSig": "", "witness": ["123416c4147c380e906aad495a06009aca12b8565d91b82769dab30b07b158043193ba7b36e47cc6017d2cc0c14454b0717af19d028c93d14a229a0ada13d5dc83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["281271137238ad2d3648e7b2f38adf379f9a8348bb23f2e000a68e8eb60bb1f9c60c6fc56b7bcef23fb9a90a32ed376974f9ed75e88119cda3209e35b1001e46b6", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/0b0a37b5c9ef3c034545cbefc3e8de97c8b5ea05 b/txscript/data/taproot-ref/0b0a37b5c9ef3c034545cbefc3e8de97c8b5ea05 new file mode 100644 index 0000000000..b22508b1d1 --- /dev/null +++ b/txscript/data/taproot-ref/0b0a37b5c9ef3c034545cbefc3e8de97c8b5ea05 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb501000000739790e5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc401000000d48d3cbfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c06010000008bfda2e203856df3000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6a988fe22", "prevouts": ["3bb34f00000000002251201aa53d82b3e96e8e01ae5203880cf5cebef0e054596b6f65010b7ca42a314e33", "5cd8500000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "7f6954000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d34c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08279688f26c44e4c38ecd8996ded351dfac291f6a9fe2ce500158a378a1caa9ee2234a5a049dfcee5b69ebdb7c70e6242c675d1abc9cd58c84d7f9a8e8e1277a43a4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361dc8d6179080437d4f90682873ed4bbb3e32e9d0e3b60c87db9e5499f1f336eb272895df1c355058834787a12b20ffb756990efd77bd7ff75ef6e99c81f77af73e02ad6eabd24d4d247e98c297de2a9d81d67e55d72d4ddf06c8e9a23565ad8a003e045cb689fe4fc6de332c618eb0cdce02c2dd8aae7c6dd6f70bdbaede2814"]}}, diff --git a/txscript/data/taproot-ref/0b0f9ae5467a2c8d14e86527b264cacbf4871500 b/txscript/data/taproot-ref/0b0f9ae5467a2c8d14e86527b264cacbf4871500 new file mode 100644 index 0000000000..40c9dc4243 --- /dev/null +++ b/txscript/data/taproot-ref/0b0f9ae5467a2c8d14e86527b264cacbf4871500 @@ -0,0 +1 @@ +{"tx": "6f7d0d91028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45d0100000075023faa8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e9000000009cb7bebe0114cd4600000000001600149d38710eb90e420b159c7a9263994c88e6810bc722010000", "prevouts": ["db1f410000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "a72f42000000000022512012d5e5f1356f7dd71d8fd34dd655f0d6117e8d6eac3bda425a0cfaea0a76750b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369c9aed3dfd11ab0e78bf87ef3bf296269dc4b0f7712140386d6980992bab4b45"]}, "failure": {"scriptSig": "", "witness": ["6ab3616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/0b37dc29cfcef1377a94a17297a0525504b5a9d2 b/txscript/data/taproot-ref/0b37dc29cfcef1377a94a17297a0525504b5a9d2 new file mode 100644 index 0000000000..3d0eddfa12 --- /dev/null +++ b/txscript/data/taproot-ref/0b37dc29cfcef1377a94a17297a0525504b5a9d2 @@ -0,0 +1 @@ +{"tx": "f0b08b4f02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cae01000000806254d3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1e020000004cedc9fb03ed11cc000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7962c010000", "prevouts": ["d7c14f0000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0", "2f8c7e0000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "9d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e5cb645b004d221127868eb317b35b9739fc590ddfdd834a11f89e113e113367cae2f7927e5cc4d53e0e18212acda8d85e01e1da74473232947322e5e96654c18"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ebf8cf3051908396d96a16e21f9fb14717dee7b5dfac112f56d0746b9362fe4375cb645b004d221127868eb317b35b9739fc590ddfdd834a11f89e113e113367cae2f7927e5cc4d53e0e18212acda8d85e01e1da74473232947322e5e96654c18"]}}, diff --git a/txscript/data/taproot-ref/0b7236484ffa4dee58a006bc3b9e51c30e5cc903 b/txscript/data/taproot-ref/0b7236484ffa4dee58a006bc3b9e51c30e5cc903 new file mode 100644 index 0000000000..70cb074d96 --- /dev/null +++ b/txscript/data/taproot-ref/0b7236484ffa4dee58a006bc3b9e51c30e5cc903 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703300000000690e42c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42102000000816bc2b260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f701000000b4d361eb03c83c6000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcad010000", "prevouts": ["3f56100000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "e9274300000000002251201d9d7b8068d804e3524a88462f1a480f3f4200cc7b90f0ee3c3216cc2f53f488", "35100f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "success": {"scriptSig": "", "witness": ["c3bdcbe1e2eff48c1048119be70323e738c75dd92578275c35365df43298c550b2dda6b6b2b09bd7632c973116077c46a123119dd6e043a0a058b1f87f78ebce", "6c4b52258ba4ef018a012f1db18fb5ea51005404280abbe8a32968c2ea51d3a32020031152cf733f2339e64b25fdbf77a33f9b8badd61eaaa8119b677964c4ad3cbd8dda42dab5e7295cfe65d7144ee8d59407a370bf23ee01dfda5df2d8f85d909a0a8e1b7745cd9d262d7e0252b9946f82bcc303562f54da29200f73d62faac9b2d00f15e99d676cd1f41bcfc5d52eb9307c894b898cdfca520665", "7529dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32506ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368c6f1ab0f60b6d27d4740b7424952ec5e9b4e6c3a2634fa4afdbe60332efe621ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000007b784d38a23b40086bfd8c053fb648544285a5c3cbd31b2ca243e62da1e820f4d41d47364315281464bb2bc7e133a14da7f761774864f1526404216e30be056404fb8040571c8f889efdf519c29ee8c0a22a7589e5342bca315d8ad264c09d6181feb0b0d6f40f12ef28a31a1b280bca1a116bc974608e4ae0f1bcecebf03cba00000000000000000000000000000000000000000000000000000000000000007a3f7f1ab29d05ddd347dcc7928b7367ebc1a4a1546562a00473f7a3c6cbcf0d9cca28d02b3bdd251e8552d7a0e9bb8c63d0967d76f6715e9dbcbc94651ddcb8ee680609b7aff51c1d9aa75ba6b47d666e0e92bc9a9ecc88a92a0e7a60ebd9bb00000000000000000000000000000000000000000000000000000000000000000df841a0ef8b8bf0fa3a48e28b09185afcffbe67dfc208294fa46558aaea9415c9df80e4514be4fbb7dba4245959f5be6017d29074c75e2c025d0e2c8f61cd95f8addca2ed8f6529a558a9e3e01e14c00915d486cd0ce24bbb8280d9a2eeea26ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6822ed0c934c780077812a8ec4675344f31d0a1f886d4fca11f71b2ca8ffcc8effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffceee2ef00c3d39f074722549e72a39677df22e78e46c2dd38db485fa08abbdda1dfcbe42a832838b98369f674b9bf3dab730221099e42598963bb1e0a9d40262ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000986680564d03774fa0facae89091f858d1d206ac28b6442ee070bf6debcfce9ee963c61d1ba7029aafb57abcfc927e0e76cf93ff7e4bdf08fa3af38940687ec6e6015be418b3b5609201008328468dbec4d16a3ec5e289fb31b9a775a88752932c4f85be333f315015496ef30778a90f2134bd87da0b96578b16fc6d615b3165c03ae9316f70f8f50e03e4c06f46bc55efad0bb3f658852384a046dbf03e93c591ae2675a823ff8de9db76fbd74c25c4e47124311c1654e04acc45adcd3bc2614472c0326c6920b128a30a578c540b1cacfef48f13a605e93cef8903921f66d7e1001240797f76542ccc4aabd7691b1ee1b4ef21ba5e005380b8fb1fd83103ca4100379d987e2db9374b325e0b2892820f7d08d1d9003f65e8c1ae4d916fb24569c5c7ec9f5a881a9544e2ef1ca88d8200ec3a90a62c9dafefc9ac3208a6269e323c5129a1675cddc59abf4ded8cdbe6b8aff4d9e31c8f684cca885464705324fd838fc5cb3489ce7914e1d1331abf3fe7d5c7473c146dbb911f0ae07f59172cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f5d3fb6127668f215b35bd94a716148714d264d9f7708148d25263d273655262b49dfa124fc488476ac7626decbd7a81b514bb187f144a81d3367ea5957474992128d9f9761238fec5926078ca9b3c7ef3fc7beca4b235226aec32709e100929027c07512a6b66469b7e23bf7c50a5dcdef7b1cd0447a1120e120cabd0301557707a40774284bc5a91b179523bdc301a1f9a4b134e0331ee2981ba97b0220c2f10c5e5b67d2ea7a8766da934bc52528f141bc45f12c2e8511208a0675192b6e340899eb1ebe25dcf532599528649fe7631e08c2ce875b5ecaa85015253d44500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27a5f874f01ba2df25b9511937f5c10357cbc3e6e2951c9caddfad0dc241792800000000000000000000000000000000000000000000000000000000000000005eef2440bb5a7cf4aa324e6fc40dac1c0182f24c80a5c50562ea024c388931840000000000000000000000000000000000000000000000000000000000000000280e73ce9d3d72fcca33d93965c67a6cdd83c054d246b63c29943fd2a9e19b09b4f4e017fabf8fc9c60acbbd0c1b2eb6870fabf36ad94ab2bfce6642becf84d084e13e8ab30ce81e1bb15a0e1f5ef6389cc07dc736259391d6561a2d1a6b63404ff00ed246db6aabe5a34518eb4889d9746b8cf0b6f10fb7b680b1bcfb37287bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff055bf56685ee9d33b04a565cd01cb749eecf681703e571753a2fd5b22428b617bc3b2028f448e7c6fb7c22a9da463f596c6ae2e7669db52a643f05a5976b2bc7e96479f87b60ec38e71f5d4045f98ddb819af129b686fa6572dd44cf13a26b3effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04277e44a2347fc589673a4e101d4e013919d466cc2f9bcdc39282a85bb1af3b6431f6ac3f92296b33895064cffb34d6b60018b1d6685ebf84eac8699265b25c8b369c92418c14fd791117af0af3fc64fe9d0cbc6e5e843bbd2390cb0ca02e4aa26345d5eb934add1898678e0d0b4081797b53ec31da25a14fd8b510975dbecd24b915103d0b4a531b061c9eec6327f7f05aaf1e3a89a2adcac086f27946cbbaa6895484aab65e0743a3cc784df53820909e89b476f8f3a85f6ad3713308f35f2cfba897bf57159d95ccd5f2cec2c594d28258370c0303f640d8fccd39ab063e93a44a62fd53d3731ffad2fa26c2ce73e0b36b3bd7ef4fd5a3cd4c69b35680159205e1be6536802c983896b3dbd280b06ecb74db1f5d2baf7320094bda793815e4888c2ada5b687bd36343aee249fd77b989aeaca24c227b661bdf9919065a8f836041c27ccf576251836af5bd9c4d806dd1165f181f422fe7b4c2d9f10a5e4059b4b5b3464a70695e6004bb5787d12c865e1da166bdada7f1d1d10b3070095ad5af93cca42812d207e2fdb48159701b1bb0d5c8c8e9210201242a69a2d4cd51ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff125da1aad2c202d21a32b894e3857da7ad2189b92cb138de5b6153d142aa257a22ae748312c68ec7b05d89fe5087425449a1a155675fdb83a63f66694ea52bebfc90693be6fc486612871f3dd6f8840f974a3ee1922c6a48f3db1c3cb643a6c5df2c37540a97e6aa1dc6dc2dd7e7edb85dd5054d81a1c8352e9ad78dbfa251910000000000000000000000000000000000000000000000000000000000000000089d59173070797e1b39b3c6f38ae7b617efc5c3e535584906eac6067af77dec06333f9ef7783bacfc4a0598596da0415a64d1b1d460970a14f994c49cad20cbf94a26d777e3f8395245d7e45d69a7b24add08058f9afb66e0b72b2e844295452179af02a00d22a0716bb98d17b1f581846be6977b94adf16d34c58a460c9d90bc66952187cbe572574d5fa7fa37948e674c3e12fc0f56259f41d53d70870d1dbe87ef145a49b30cf99cd5c12f5a63181ce2d0922a48bfe122c173e2db2cd86279727aaf8e7d1abdd10d982bb935ae0d282f4d24f255880eeb7b4f6556ea10acd4be89eefafa9548d8cb15e567afd7e9e326516f2446055635c5785a047dfdb900000000000000000000000000000000000000000000000000000000000000009d47d33a5dcbc6bc50dde0ab6e957b0102659febd9b30c4e8ed5ad7bb42705bf4bbae6057afb128115fd12c8a0dd5c67fe9a016ce6b155b77b6efee28f99975abe22cd3c492cd082d1a84ca8041f3032b68e143b8b9ddfa1a4cebe7f2a0d896a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aab68dcb9ba5edb99dc0517a9d37ac3076680f101ced4036d50cdedca6e0877827c27d16f862a82a428bb0b917d69dbd78889f1ae7ed0e594f256ef4dd479a12abd741f4708efe323f9e966c96caed925e1df30bd844885b2c3d806e5ffc10239a13faf0d6e56d28a23f9ba1c3387da4bf6746ada8253a9d6151df5afc000fa77b6494acc6e4d9aca8357cd000055100454321aa8e821258e9a1fa2960ee17369590f39e8ef5ebbaf9f91dfee92fa1b301db1dc60a7a1ac91927f60508c423e586cb40cb20a4a0626533d56de0654e1664972d7151ac8d8c45ced1506b3b346a0f4f2e58b9d1eaad28153d39573ed50df12b59f5ba7c7d420ccb80227634d6e319fd65d1e7a090f83adb53bc53675c3d4ba2f1c5448737c58a088c16d078aa4f11780ce817ee436fa8709654ceb1c8ce1c5c30cd69176c52903e6c3dd897061263355d6173acff5b589da6745f344aa150b9f389de40f7400804dcd7854a30effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20cd59322096216580c07d7431e7af7bb4d2841ee7d7c4baa62b1da2319b92b4647602476d791a2d2d5abc6749f6d39198577c033841894cc538a7aeac19f336ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18dd9c054d018cb9e0a206e26446c6a13c5f0d8f9edcd56d5e402c5e99852ce609ff0d0bb4243e2a4d92d91a75c6db1152fb70760fa5c459ccb964b8599aee06861524c109334956d92b085d4d08da511f01b056feb57f71ca31257e7b596f7ddd434a83ea2c94897d047a1e0441c0c7210e06b7bf406ebe45ad1b5dac562e01598333715708e7e879880cd37b489c40373a9cb8fbcf74b53c7113aa62a4b9761938bf78928c88e2e9005ceb2136af4b8a299f1f8687a3c503b54853231beeed1ca9fa27ee78aef8ab74aec366a7ddc5c4aad3a38681a7b57665aaa99f0e20d40000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03d954b5fb6eb9295ae6377a00573071aee29ac5bfc401a20de905bc07c7069803355c54e8ed96b7552b2f89f26b961f92e9063bcd5d151aac93adcb5c84604ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}, "failure": {"scriptSig": "", "witness": ["c3bdcbe1e2eff48c1048119be70323e738c75dd92578275c35365df43298c550b2dda6b6b2b09bd7632c973116077c46a123119dd6e043a0a058b1f87f78ebce", "89cd78a9a24ab161bdfb8555cd6bdcd8547095eadcf6d7f9a872e85ce0e7a153e7ca5269b3e885c337c715754e10c296e55165af6321fc25d9db26911daafe5034f4c469bc49e66357902f484a4dfd6e7e9a188afab10fd9e58ae1701e494e138b4bc4620b8901b58171541767e6edfc214471825ebef0ff58339ee66bc5eb869f20f5d613f6ebeecbadbcfa86ab66d5e5e6276e2e719b37849342", "7529dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32506ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368c6f1ab0f60b6d27d4740b7424952ec5e9b4e6c3a2634fa4afdbe60332efe621ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000007b784d38a23b40086bfd8c053fb648544285a5c3cbd31b2ca243e62da1e820f4d41d47364315281464bb2bc7e133a14da7f761774864f1526404216e30be056404fb8040571c8f889efdf519c29ee8c0a22a7589e5342bca315d8ad264c09d6181feb0b0d6f40f12ef28a31a1b280bca1a116bc974608e4ae0f1bcecebf03cba00000000000000000000000000000000000000000000000000000000000000007a3f7f1ab29d05ddd347dcc7928b7367ebc1a4a1546562a00473f7a3c6cbcf0d9cca28d02b3bdd251e8552d7a0e9bb8c63d0967d76f6715e9dbcbc94651ddcb8ee680609b7aff51c1d9aa75ba6b47d666e0e92bc9a9ecc88a92a0e7a60ebd9bb00000000000000000000000000000000000000000000000000000000000000000df841a0ef8b8bf0fa3a48e28b09185afcffbe67dfc208294fa46558aaea9415c9df80e4514be4fbb7dba4245959f5be6017d29074c75e2c025d0e2c8f61cd95f8addca2ed8f6529a558a9e3e01e14c00915d486cd0ce24bbb8280d9a2eeea26ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6822ed0c934c780077812a8ec4675344f31d0a1f886d4fca11f71b2ca8ffcc8effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffceee2ef00c3d39f074722549e72a39677df22e78e46c2dd38db485fa08abbdda1dfcbe42a832838b98369f674b9bf3dab730221099e42598963bb1e0a9d40262ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000986680564d03774fa0facae89091f858d1d206ac28b6442ee070bf6debcfce9ee963c61d1ba7029aafb57abcfc927e0e76cf93ff7e4bdf08fa3af38940687ec6e6015be418b3b5609201008328468dbec4d16a3ec5e289fb31b9a775a88752932c4f85be333f315015496ef30778a90f2134bd87da0b96578b16fc6d615b3165c03ae9316f70f8f50e03e4c06f46bc55efad0bb3f658852384a046dbf03e93c591ae2675a823ff8de9db76fbd74c25c4e47124311c1654e04acc45adcd3bc2614472c0326c6920b128a30a578c540b1cacfef48f13a605e93cef8903921f66d7e1001240797f76542ccc4aabd7691b1ee1b4ef21ba5e005380b8fb1fd83103ca4100379d987e2db9374b325e0b2892820f7d08d1d9003f65e8c1ae4d916fb24569c5c7ec9f5a881a9544e2ef1ca88d8200ec3a90a62c9dafefc9ac3208a6269e323c5129a1675cddc59abf4ded8cdbe6b8aff4d9e31c8f684cca885464705324fd838fc5cb3489ce7914e1d1331abf3fe7d5c7473c146dbb911f0ae07f59172cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f5d3fb6127668f215b35bd94a716148714d264d9f7708148d25263d273655262b49dfa124fc488476ac7626decbd7a81b514bb187f144a81d3367ea5957474992128d9f9761238fec5926078ca9b3c7ef3fc7beca4b235226aec32709e100929027c07512a6b66469b7e23bf7c50a5dcdef7b1cd0447a1120e120cabd0301557707a40774284bc5a91b179523bdc301a1f9a4b134e0331ee2981ba97b0220c2f10c5e5b67d2ea7a8766da934bc52528f141bc45f12c2e8511208a0675192b6e340899eb1ebe25dcf532599528649fe7631e08c2ce875b5ecaa85015253d44500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27a5f874f01ba2df25b9511937f5c10357cbc3e6e2951c9caddfad0dc241792800000000000000000000000000000000000000000000000000000000000000005eef2440bb5a7cf4aa324e6fc40dac1c0182f24c80a5c50562ea024c388931840000000000000000000000000000000000000000000000000000000000000000280e73ce9d3d72fcca33d93965c67a6cdd83c054d246b63c29943fd2a9e19b09b4f4e017fabf8fc9c60acbbd0c1b2eb6870fabf36ad94ab2bfce6642becf84d084e13e8ab30ce81e1bb15a0e1f5ef6389cc07dc736259391d6561a2d1a6b63404ff00ed246db6aabe5a34518eb4889d9746b8cf0b6f10fb7b680b1bcfb37287bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff055bf56685ee9d33b04a565cd01cb749eecf681703e571753a2fd5b22428b617bc3b2028f448e7c6fb7c22a9da463f596c6ae2e7669db52a643f05a5976b2bc7e96479f87b60ec38e71f5d4045f98ddb819af129b686fa6572dd44cf13a26b3effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04277e44a2347fc589673a4e101d4e013919d466cc2f9bcdc39282a85bb1af3b6431f6ac3f92296b33895064cffb34d6b60018b1d6685ebf84eac8699265b25c8b369c92418c14fd791117af0af3fc64fe9d0cbc6e5e843bbd2390cb0ca02e4aa26345d5eb934add1898678e0d0b4081797b53ec31da25a14fd8b510975dbecd24b915103d0b4a531b061c9eec6327f7f05aaf1e3a89a2adcac086f27946cbbaa6895484aab65e0743a3cc784df53820909e89b476f8f3a85f6ad3713308f35f2cfba897bf57159d95ccd5f2cec2c594d28258370c0303f640d8fccd39ab063e93a44a62fd53d3731ffad2fa26c2ce73e0b36b3bd7ef4fd5a3cd4c69b35680159205e1be6536802c983896b3dbd280b06ecb74db1f5d2baf7320094bda793815e4888c2ada5b687bd36343aee249fd77b989aeaca24c227b661bdf9919065a8f836041c27ccf576251836af5bd9c4d806dd1165f181f422fe7b4c2d9f10a5e4059b4b5b3464a70695e6004bb5787d12c865e1da166bdada7f1d1d10b3070095ad5af93cca42812d207e2fdb48159701b1bb0d5c8c8e9210201242a69a2d4cd51ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff125da1aad2c202d21a32b894e3857da7ad2189b92cb138de5b6153d142aa257a22ae748312c68ec7b05d89fe5087425449a1a155675fdb83a63f66694ea52bebfc90693be6fc486612871f3dd6f8840f974a3ee1922c6a48f3db1c3cb643a6c5df2c37540a97e6aa1dc6dc2dd7e7edb85dd5054d81a1c8352e9ad78dbfa251910000000000000000000000000000000000000000000000000000000000000000089d59173070797e1b39b3c6f38ae7b617efc5c3e535584906eac6067af77dec06333f9ef7783bacfc4a0598596da0415a64d1b1d460970a14f994c49cad20cbf94a26d777e3f8395245d7e45d69a7b24add08058f9afb66e0b72b2e844295452179af02a00d22a0716bb98d17b1f581846be6977b94adf16d34c58a460c9d90bc66952187cbe572574d5fa7fa37948e674c3e12fc0f56259f41d53d70870d1dbe87ef145a49b30cf99cd5c12f5a63181ce2d0922a48bfe122c173e2db2cd86279727aaf8e7d1abdd10d982bb935ae0d282f4d24f255880eeb7b4f6556ea10acd4be89eefafa9548d8cb15e567afd7e9e326516f2446055635c5785a047dfdb900000000000000000000000000000000000000000000000000000000000000009d47d33a5dcbc6bc50dde0ab6e957b0102659febd9b30c4e8ed5ad7bb42705bf4bbae6057afb128115fd12c8a0dd5c67fe9a016ce6b155b77b6efee28f99975abe22cd3c492cd082d1a84ca8041f3032b68e143b8b9ddfa1a4cebe7f2a0d896a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000aab68dcb9ba5edb99dc0517a9d37ac3076680f101ced4036d50cdedca6e0877827c27d16f862a82a428bb0b917d69dbd78889f1ae7ed0e594f256ef4dd479a12abd741f4708efe323f9e966c96caed925e1df30bd844885b2c3d806e5ffc10239a13faf0d6e56d28a23f9ba1c3387da4bf6746ada8253a9d6151df5afc000fa77b6494acc6e4d9aca8357cd000055100454321aa8e821258e9a1fa2960ee17369590f39e8ef5ebbaf9f91dfee92fa1b301db1dc60a7a1ac91927f60508c423e586cb40cb20a4a0626533d56de0654e1664972d7151ac8d8c45ced1506b3b346a0f4f2e58b9d1eaad28153d39573ed50df12b59f5ba7c7d420ccb80227634d6e319fd65d1e7a090f83adb53bc53675c3d4ba2f1c5448737c58a088c16d078aa4f11780ce817ee436fa8709654ceb1c8ce1c5c30cd69176c52903e6c3dd897061263355d6173acff5b589da6745f344aa150b9f389de40f7400804dcd7854a30effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20cd59322096216580c07d7431e7af7bb4d2841ee7d7c4baa62b1da2319b92b4647602476d791a2d2d5abc6749f6d39198577c033841894cc538a7aeac19f336ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18dd9c054d018cb9e0a206e26446c6a13c5f0d8f9edcd56d5e402c5e99852ce609ff0d0bb4243e2a4d92d91a75c6db1152fb70760fa5c459ccb964b8599aee06861524c109334956d92b085d4d08da511f01b056feb57f71ca31257e7b596f7ddd434a83ea2c94897d047a1e0441c0c7210e06b7bf406ebe45ad1b5dac562e01598333715708e7e879880cd37b489c40373a9cb8fbcf74b53c7113aa62a4b9761938bf78928c88e2e9005ceb2136af4b8a299f1f8687a3c503b54853231beeed1ca9fa27ee78aef8ab74aec366a7ddc5c4aad3a38681a7b57665aaa99f0e20d40000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd03d954b5fb6eb9295ae6377a00573071aee29ac5bfc401a20de905bc07c7069803355c54e8ed96b7552b2f89f26b961f92e9063bcd5d151aac93adcb5c84604ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}}, diff --git a/txscript/data/taproot-ref/0b727481698d5b6e33b991da896215f0527335a6 b/txscript/data/taproot-ref/0b727481698d5b6e33b991da896215f0527335a6 new file mode 100644 index 0000000000..b8d96b9f42 --- /dev/null +++ b/txscript/data/taproot-ref/0b727481698d5b6e33b991da896215f0527335a6 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43c0100000095415d86dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6b00000000d4fe448802e1715d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2708ec21", "prevouts": ["fc1c370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6fad28000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "final": true, "success": {"scriptSig": "", "witness": ["33aef750cbca2ae70fa4e61a360cc74cdc5845f7220478c5ae24ba9e7d58d7c3a64c1537ec8bf5da3564fbe092ed4323ceb447b28be659e0f810ae1a8d43d4a283"]}, "failure": {"scriptSig": "", "witness": ["7e73988dc4ea242eb936f608260ffc3407d458b61f57777a861d37f87d509ab7a0e2e1f452b647e6c5abb4e1c564d5d3641f6751b2c287deabd310b62320e2bd83"]}}, diff --git a/txscript/data/taproot-ref/0b931370dfff16b9e6d9a7a333e61cabe23290eb b/txscript/data/taproot-ref/0b931370dfff16b9e6d9a7a333e61cabe23290eb new file mode 100644 index 0000000000..271338e77b --- /dev/null +++ b/txscript/data/taproot-ref/0b931370dfff16b9e6d9a7a333e61cabe23290eb @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd800000000a44e63dd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bd00000000160a5735025a6d7a000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787fd27fe2e", "prevouts": ["f38748000000000017a914b0716f1bec91d4758ee97d9063c9da884dd2ba5287", "ebc33300000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "165a142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["34f6449f6b7994f1e4e3219f28990cedb1f93d63779bea56e3a89b87d7096db705989fd4d740a69b9a1c7711ed50e63e8519ba2af37c4169369cebc001f3bc62", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/0bc98deaaa9007629b3338d906d73f87abce0b62 b/txscript/data/taproot-ref/0bc98deaaa9007629b3338d906d73f87abce0b62 new file mode 100644 index 0000000000..7440b574ec --- /dev/null +++ b/txscript/data/taproot-ref/0bc98deaaa9007629b3338d906d73f87abce0b62 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709e0000000047e9de70bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf36000000000931f20a02e0517500000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc22fbf46", "prevouts": ["e25a0f000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787", "c8216800000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100e41de8ee7baef7958dfed81c9982dcd8eeb37dcf13eac0d81f9d7273de1797f60220664d2178b377acf8205a7f9822f533751109e595a719e8852a63ee20397e93b483", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100e661b3b0b5ddae11ce0764751e22e523fb243c6337d707e4f0d75865a39dd56b02206892d0fc8790325387265ed6c293867991ab8edd6ce3d1a4b6d09bdd2de9af3783", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/0bf313616424ee4fc95cf71286563567fc87c472 b/txscript/data/taproot-ref/0bf313616424ee4fc95cf71286563567fc87c472 new file mode 100644 index 0000000000..787bbe2b0d --- /dev/null +++ b/txscript/data/taproot-ref/0bf313616424ee4fc95cf71286563567fc87c472 @@ -0,0 +1 @@ +{"tx": "85ad78690260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701102000000aa846bd8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bce00000000353636d60413b23000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870a020000", "prevouts": ["b39f0e00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8", "28aa2300000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "c57d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e80f62f511a5f57d359682e9bf2433f4757cbd4acbee5d7e6d55377acbc6e694247b7f3ebdceab6737726d3802236d8368ee483fc4ea684d1523b8c26fc56452a37def1cc2232d9b1ca5244635fcf6779cb15e82fb856baa2ca11d8fd1da35295f"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936969f17f40163001b57522e1bfe2b5fe7c0c4e62446f9d2c84d4738fa96391d180f62f511a5f57d359682e9bf2433f4757cbd4acbee5d7e6d55377acbc6e694247b7f3ebdceab6737726d3802236d8368ee483fc4ea684d1523b8c26fc56452a37def1cc2232d9b1ca5244635fcf6779cb15e82fb856baa2ca11d8fd1da35295f"]}}, diff --git a/txscript/data/taproot-ref/0bfc8b69a3702ac6986ce61b00e837a148e7d0eb b/txscript/data/taproot-ref/0bfc8b69a3702ac6986ce61b00e837a148e7d0eb new file mode 100644 index 0000000000..29eecf9491 --- /dev/null +++ b/txscript/data/taproot-ref/0bfc8b69a3702ac6986ce61b00e837a148e7d0eb @@ -0,0 +1 @@ +{"tx": "1af00c3402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd0000000006c00f6ad60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705401000000ca7050f7032c0a5f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796a3093b4e", "prevouts": ["bd14510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "81c20f0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_9d", "final": true, "success": {"scriptSig": "", "witness": ["e8b301698cc8fe10b9fbe252e7025e9d5fae59b7c9332f8094b1fb5439874ddcfcb7e04c95749504a7a69af462581849c82c2fb91813911755ad8a69171bed9e82"]}, "failure": {"scriptSig": "", "witness": ["66d5a75332f4785db4ee435536e7d33848897633b18efac07ce703c2389d3229093cbc9316acd88ce6f4fbaaef4bf20208fac4dc3fc52874598fb6312bb841ba9d"]}}, diff --git a/txscript/data/taproot-ref/0c00a8351b02f2185ea30aa4052174b38417e0ff b/txscript/data/taproot-ref/0c00a8351b02f2185ea30aa4052174b38417e0ff new file mode 100644 index 0000000000..763d275aa8 --- /dev/null +++ b/txscript/data/taproot-ref/0c00a8351b02f2185ea30aa4052174b38417e0ff @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cf010000002d86ee8cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba5000000005702dfc60407903000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a627000000", "prevouts": ["e2b60f000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "91282300000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09022b246878ccfab611754d6f0642f8b2cb1743063978de071b35b7d288c79916a2736cc63b07a7a2a623acfab6f6ce99322b728dd44be021e2a05dfb22735ee0db9a0b70734036bbae9f90c9c020ccb4cfec0cdfb447931a5bb6cf69a54b661ddd5a8a8eb5b10c22718fbb64c69fd23c8198bfee2a421f9fbc353e319404dcab1183126d0898eb2e878a22f820faf6b02afa4c6aa6fe27eb87ca09de15a4eb3478653fd9637a31a0789434009a5d941dce685d6bbefefc6ed96ab72a2f939056ef452d6fa2f0aee639a4e12fb8703ad7c4c99db7fda84e84b4db551f1b4d679effb3fee16e090d7bc0b866e427e6046d0d057a378c7c898655df882c5eaaab5a59d76105e4db7cb76f5dd40da1505350d1cbc02c3d968c5c0d63e44bcc1bd30313f8668001a4d781890cc43f89e40f4c01f3df0c06e241ac05a748112d53767656678aece90969fef87e164368b2a02c44d3e4cf70b791e89c1e287dc003bdd572cae39bdef823a3da7582de538e3588fae69c9f46cbaf707dec9e6894c59176bc4a191dfd8a0b183f3eea93e158cc9f4ebb2fbab1087b1bb4631fdaf784fbadda48c584a417a2406f1fb2d0fd4280b67535663fd16e801468f8d79c68f25a3034ad2b446c0fa3c1a75c029c023fe03b3024d0a56235dd82dce941fefc81de07c0f875c8a59fc3c2b08b0841fdd86126678193c958181b601f2a1e88a1db0f88ab1065fc26082a366c1a75", "447d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ec655510ef0d78e24844d6e76597a80e81981a8d7f61dd7bc99fd53b1a11d65f7b6e2c095a2b9a1b3d0ba71ae2a36fa91117ca9fadc253f03c0f98f0de350244f357c04ffd5ab4b0848fd0bc62a9916d6f879ccec8b8201b6b82c9f83bee932"]}, "failure": {"scriptSig": "", "witness": ["4d0902d1c3622916b19f90dff3fd08a32465ce6057e3e59a06f4f9bff5830bb2204f732fb5d7bff9f5f6c3bc34b05a8b0674276f6d9910c78549a811c9c1d89842450dcbefb5d20bab5322d4474366a7293452bb3e277818a640d21da6725fb83aa6178d9358d5b7eb8da717809359fc8b381c54fdb83c35317d3f431e71803ec40173c4772358e35f45b9a73194308d79fe4f8c1ffc2e1ec676218a1952ea879da4da627bfd40c547983ee773305840fb91010378336d9bf23d7aa56cd919071db2954f59be64ceb03c20b4fddd8d7c81fa7651a0e91e146dbb85ced0f938a7ef5a55a512540e93e43d9c4aea55f04f9e4ceb3760cd4139c0bbd603ee6d1ccef5bae116d8d7fda24639efaad8a10e8f22ba59837ef3fc532ccc0c8fcfc5993ccdf681bc7c6f51b74f1eadebb63bd985cff13ee775278dc5642155e018c74b197a64931642d0212f588ca0959ba21fe82c439023ed1f9f6e57c4ab4636e37bde1ae08b5c862699ea27bb1c6ea362c7fd3a8b58ccd6c6af15b9d7433f07d4ee36824b0f844f20f531353d39022ca8bc7ca6236eb8d1bc6f9cb3dd9ec058ff9a4c64573517d919ea871e3623e082accb43f52b68323aaecb3e6f9bf019e3873a0032d7cc09c84efd42675bbd1d7a0b5ee6a02c39d0455434a9a84697f566eaffac800788ee96014070564542f0e257b979630aa897fa25fb4567592bca45eacb5514439e89d4d823ce952e776275", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936443b7e89d84dba416b5c010b3eec3635a6b8b3ffa01e53435da8d448fb39e6ccda290f4428e3e675f4a51c1ca36b5af7f0162ea7962d369252b53cfa5e2a91134f357c04ffd5ab4b0848fd0bc62a9916d6f879ccec8b8201b6b82c9f83bee932"]}}, diff --git a/txscript/data/taproot-ref/0c02f78d8dd01b33e94abaa865ee6a9792f4ccfa b/txscript/data/taproot-ref/0c02f78d8dd01b33e94abaa865ee6a9792f4ccfa new file mode 100644 index 0000000000..780bd6066a --- /dev/null +++ b/txscript/data/taproot-ref/0c02f78d8dd01b33e94abaa865ee6a9792f4ccfa @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb501000000739790e5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc401000000d48d3cbfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c06010000008bfda2e203856df3000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6a988fe22", "prevouts": ["3bb34f00000000002251201aa53d82b3e96e8e01ae5203880cf5cebef0e054596b6f65010b7ca42a314e33", "5cd8500000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "7f6954000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936207372de628be21b0016a4467a52ed3274bee00d5b175bb5f0264e63299a675141d10d6c1f57e693407bbcd98ddd5bf64931b5565c89b36e50f161e759967c3e172c8da9bdd43b70cbab8912ef1aa7926e5ad7e47a4f7b71ac936200cc947dd0f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936557fb8112a3a220373d52cc4c89c6517a2e1720c5885e0e17f2a0be351c36a81ba89d18ed67dd3d5d559101471702e4f2e7d1e8ead8a22feb9e78f041b8f409f5c55ad82284641cab824687b45d4293ada5fb8cbfc4ac19bcb5188e4cd0a7708cf37d2bf9ac9d65f4f9542d60f6497573c04b4d7313f44a5c611386102890a1c"]}}, diff --git a/txscript/data/taproot-ref/0c043c49e6d5aafcf072e6be1be89160111fcb16 b/txscript/data/taproot-ref/0c043c49e6d5aafcf072e6be1be89160111fcb16 new file mode 100644 index 0000000000..92a42f04c2 --- /dev/null +++ b/txscript/data/taproot-ref/0c043c49e6d5aafcf072e6be1be89160111fcb16 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47e0100000034d6f85adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8200000000012c3b33dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d000000008f19ffce02f518ac000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987d0010000", "prevouts": ["baec39000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "d7d2500000000000225120b982c4866c93df3772712b36d4336b477e2dfe66f304c80c21f6bc33f20b8495", "8ecf23000000000017a91418261fd2fa0b0480c86b918607add1dde9f7026a87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93645312a56de4d39a275ea41c23c7e6772b7c82cab6a1b0100cced3b0664f6f1e8"]}, "failure": {"scriptSig": "", "witness": ["6a0f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/0c10be31ac329baf66d4d083563e6a9c3ab9ee59 b/txscript/data/taproot-ref/0c10be31ac329baf66d4d083563e6a9c3ab9ee59 new file mode 100644 index 0000000000..074624754f --- /dev/null +++ b/txscript/data/taproot-ref/0c10be31ac329baf66d4d083563e6a9c3ab9ee59 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba000000000a4dea4a4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c51010000001e406ea960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e01000000c86dabae0117a21000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac57020000", "prevouts": ["0ca3270000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "d08c4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "08ab110000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "8b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362494f98453d8de8230306fae5264b7e20094fd005457c4d9c992af615d79de60493e40fcef10fde3df13bbd1c2551f58461e5d74b1e1953624615bb6f8ad2778f2e441b555c43a724b579c479d380c278f8ccac4217fbfdcb96526a1dcd96287"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa726c3b29d073c2dbcf72056f4f7511ea796d648b755097daf6738edf6332d6d84d7dc2c55a7521ecc297ff7217b922438f95dd9c29c118a2bf5c9e2c8f8c84f32a50ac17afa49989b8cd5fe09550e31f987b9afab4d6ff7fb0ac42074cc4b38f"]}}, diff --git a/txscript/data/taproot-ref/0c12817899b35dadda1aee2d0a376b1e6fca73d8 b/txscript/data/taproot-ref/0c12817899b35dadda1aee2d0a376b1e6fca73d8 new file mode 100644 index 0000000000..15ab7ad434 --- /dev/null +++ b/txscript/data/taproot-ref/0c12817899b35dadda1aee2d0a376b1e6fca73d8 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a010000006c9b93db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d601000000fcf1a38ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b33010000009c6a06b504e4ebae00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987182a0b5d", "prevouts": ["29c3530000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "0ffb35000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "bcdb2600000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "cf", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365e0e9a175fda05a064c52eebe8eea391232a608d343baa66a1ca563d1b6babca6a7a52674f359a7dbed67a49e09732132053a9cde77eaa564fdce3cafe7738b9f4a62e14d7fc4acbfb0196ec29a60565ac2b3043dda4cedec8cb1ff291b90d41"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ba852db044cc7b3c6c227af3aa09dc9e9bae5367030e3f2be29afb15f97933d48121d7901a27ea565e1cb6f91818c43a3dc8f46dc56db80c8bd3776430739107a653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}}, diff --git a/txscript/data/taproot-ref/0c2099a1366325dfb20d310e00b1c1554e93defd b/txscript/data/taproot-ref/0c2099a1366325dfb20d310e00b1c1554e93defd new file mode 100644 index 0000000000..864867d2c4 --- /dev/null +++ b/txscript/data/taproot-ref/0c2099a1366325dfb20d310e00b1c1554e93defd @@ -0,0 +1 @@ +{"tx": "1b2bfb8902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b780100000008eb22ab8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42600000000c4deaba3015955540000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc74506636", "prevouts": ["1b791f00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "c7163f0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "747d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c1c1cec2ec4a702b027c32afe8f050a7abd6c53cc1a056033971ea23441aa0d3133f027656d2d9f64ade865091a06c0b2adab14558eca27c91472397a1e3806e077aea6ccf316b47e40a0e3636c5ad4f7738b9bfce630d4a478a0dbfcb51ed93"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e86e257627f53ae21a01782ee3e7d4da03b01bc19a25fdaba4c8a32b8ecf0a2d91bf4492fa00dc56072e72009d776219274bea6eb51adb458249eab71940c27cb4bfbb1ef2412aee06f4b75b9e20a72d4d9707545a4ae77abc538f76b00105406a"]}}, diff --git a/txscript/data/taproot-ref/0c4d9a60206c9ad9b61b6120b3b5495408989e96 b/txscript/data/taproot-ref/0c4d9a60206c9ad9b61b6120b3b5495408989e96 new file mode 100644 index 0000000000..7772d1dea4 --- /dev/null +++ b/txscript/data/taproot-ref/0c4d9a60206c9ad9b61b6120b3b5495408989e96 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9d00000000e8af27168bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41900000000f499c33c02627c86000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac0e38aa56", "prevouts": ["e39f5100000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "229f370000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f568", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c90e280e1421574cb54e7318c63431e4a1edfed926b25be9229483f2d9c0035299ead232f95c20736c4ca28d40406922684ff7a84c70e432a4f6a4d4d1893c4694e361b142bccbbefeea6ac26126d4f4fbb610699e3a27d96f99d1b67de22f2f"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb44041dd00c04bb207a9f54805a750c9f5dad18a896c6f9e3a7e4fce73f8863b3a94e361b142bccbbefeea6ac26126d4f4fbb610699e3a27d96f99d1b67de22f2f"]}}, diff --git a/txscript/data/taproot-ref/0c6dc14de0b80f72306e015b7560fef8a12f722c b/txscript/data/taproot-ref/0c6dc14de0b80f72306e015b7560fef8a12f722c new file mode 100644 index 0000000000..ba1412348e --- /dev/null +++ b/txscript/data/taproot-ref/0c6dc14de0b80f72306e015b7560fef8a12f722c @@ -0,0 +1 @@ +{"tx": "9a9e95db02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7c01000000d1dd92ed60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b200000000832b678a025db336000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdfa28c60", "prevouts": ["c1f3270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a348100000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "d67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667d27b234150b851a84a9914325267995d8047a4d411fd05a1678f70c40cfe2ef0c0cd32dca2782b49e872f77a6f41a631e1b6bec2669bf2370bfbcbf3d4a769630d95c26588949f1b3ae4e4e429080b434b995fa18047406852c727cd9e6feb"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e14394dbc4504b599527b31ae07292f4c811cc2f9bd5ea2479c58248999356efb1986d7e8e27273be987a3f59c249d736830c7b6f9b487df38f4ee68bd2c5d06630d95c26588949f1b3ae4e4e429080b434b995fa18047406852c727cd9e6feb"]}}, diff --git a/txscript/data/taproot-ref/0c860ba9e47e23ac7ceaaa948e710e0253317ad1 b/txscript/data/taproot-ref/0c860ba9e47e23ac7ceaaa948e710e0253317ad1 new file mode 100644 index 0000000000..f98ba148b8 --- /dev/null +++ b/txscript/data/taproot-ref/0c860ba9e47e23ac7ceaaa948e710e0253317ad1 @@ -0,0 +1 @@ +{"tx": "b96146fd0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270aa00000000012841abbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffa010000002b0920930287757400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac12010000", "prevouts": ["3995120000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "1686640000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c64c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456a39aac74ee3f63949b9c215c515b0db1b113f4639b3fb19cd99ba22ff01310c728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}, "failure": {"scriptSig": "", "witness": ["4c52c6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936818d75448986f133fc28c6b1d0348e731f044a1050c9b39e3bfbc63da577cd23d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514a68ec639edecebbcc441a95b015cfc7d67c6cfab51cac7643a880d3dd4163fb31e5a3cd6e337eb252bd8d7a8d95e14a531fbfbee4d245debca50b247e512ad1"]}}, diff --git a/txscript/data/taproot-ref/0c90542e3f64cf4c09f66ad39471bbed839d46af b/txscript/data/taproot-ref/0c90542e3f64cf4c09f66ad39471bbed839d46af new file mode 100644 index 0000000000..fa9020fb16 --- /dev/null +++ b/txscript/data/taproot-ref/0c90542e3f64cf4c09f66ad39471bbed839d46af @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b00010000006626179d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dd000000002f9f28d801c65c470000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e70cd67b4d", "prevouts": ["308e200000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "e53e310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f868", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e485f1c41272271fc4c80a4e35cc3d5c00c2bf0a9cdab1f013c35398e076f7021ef28805a30acff873fd9260c6b3bfee2b626467fb0ce04f716d513a8a4b08b6f288028cdab461d62f9273620b97315e6e9af9458f777a616c1bade2d3f6a89e"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dafdffa5bee5fc279ded3bd906723ad31de263059c45567130a0992fb7d0cdbd7103c9e8ba836cb8a4e14cf2cfa4f8a9b341b4f4aa6fb02102628b5e7003f327891e44dcd1430a53a9228b1d4df01e5c5d5af3846f876ba8dd78ee7e669e7153a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}}, diff --git a/txscript/data/taproot-ref/0c91906e6830ed3ad8eba843f2cd7c66205a7981 b/txscript/data/taproot-ref/0c91906e6830ed3ad8eba843f2cd7c66205a7981 new file mode 100644 index 0000000000..40e670861b --- /dev/null +++ b/txscript/data/taproot-ref/0c91906e6830ed3ad8eba843f2cd7c66205a7981 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa701000000f7176d97dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce401000000c70bcbe401c58e01000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ef01641e", "prevouts": ["75707700000000002251202eded5f58e3549770351ff682af5b38d1de1354573522cd8f1060c49001c6d0d", "9d5b480000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_keypath", "final": true, "success": {"scriptSig": "", "witness": ["16160f61bd77a762ef82e4095012cf3118ba7418d282fe9279dfb2ae4f7d693c7ea94e29333a27523c9a3f18ee8ffaac7d31e8b48f3bbd61926b9626b107df7a"]}, "failure": {"scriptSig": "", "witness": ["16160f61bd77a762ef82e4095012cf3118ba7418d282fe9279dfb2ae4f7d693c7ea94e29333a27523c9a3f18ee8ffaac7d31e8b48f3bbd61926b9626b107df"]}}, diff --git a/txscript/data/taproot-ref/0cbaaae8f169bef4c71cd090d475e96cc8277741 b/txscript/data/taproot-ref/0cbaaae8f169bef4c71cd090d475e96cc8277741 new file mode 100644 index 0000000000..b8ba35eb8d --- /dev/null +++ b/txscript/data/taproot-ref/0cbaaae8f169bef4c71cd090d475e96cc8277741 @@ -0,0 +1 @@ +{"tx": "e1a1f69c02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0100000000f91c71a18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e201000000d7f6cca303f3e29600000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac8b000000", "prevouts": ["b9075d0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "61e43c0000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902e8a82e148e674b2da678756ef7fb3acef7ecdd154992e611b612eb1b2efb3449ec1b6a8174731a6ba3035ed06be8afe3ad4b039a6672ae22c4dbf7617b657e942c89a5194237c2876f0381c2093ce5c84b28cbbf2d88dd8c9038b546232e5aaf505c62194008985a89505cad0a266920a70240182ce14ea47ed784ef3891c68e165a5775cd18a8b1d026edc92e0a6cf58342f06caf5fc8715d42278c86a19f3e39e8e3a656dbc7d3264018a1def62fd260c09823b98ba7aa4e8567076651f6dbccebe5977814d9cbbf01140db39bf4e8aa41bed8665129ee1747003ab3a39f100fe9f9d37bc6e267b1222119bc13ef2acb57ddc9141cdf61b82f7ccb22fd1bdb9df397ca497e35a2acf590d6e7c674c7a72ae700496f096a3b106a9476b6ea98c6654bed94bfeb5c5d40b03026a2d0cad6bcf4744c55b2c80807f71b482d931c31f18ecc0d8d8f938652c343644908705107365043ff7468c39e3698b917e27fb105b6bc860d5c7b3b3ffcf8ff27d85a2acfeaaad608711a640a8758365786ff811f14c7f1fd0d0decb048993991248fb14f95798a302e2f7813bdf53cf82642c98139ace206ad5d3a50655487312cb5002fb5370a9dd7098d850e4d92bca151d8d0a56adb316f1ca237c94dfc5ff5faf3eb1b883ed6d003e04aebf430d79a2e94c46699c7156ab4111d765567ecf018e327c64e2ed97165d0637c3f1a40bf07753ee8265c7d0108c875e2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a469bfc8de16b0968070038325e6b76e7740524a1c4ae3d3f158ce1e63cb3bfd7c6ac6071aeb5642f86cbd8c403a36f49b1ae971c310fa0b2c6d23cdcc52f9ae3b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["4d0902225586b6f5d6e8a902e3ce91f256d235da38e7af3589b6ca4267db6a9170910ae185b2288cb83df651604ee1c06cbe9441d9db43e9eeef8366211f1ce6118b1860ddeed47d85513c0869b7314dfae66b9b3bf8c56b89495bc0edaa2d2f870ad00810d0d8cb8d83936fbcb629bfdbd4f8f8873e7cfd9b8909ab4649b3a93ec0238431593fa55e651fc2761590e52a7cef87d85df33c77e90e17134def3174737627a06de1598c60c2d883191aa38f06a432634e67c61f82a64364d630a906fb7f4ad51b7d4d318a363d4db840aba1d3c4db976be94a5a2c14d06f96c17cff6dac09de4fa8833bd7daf42a9938ec99dd14448cd736ea953d494fc6afa3eecf6d480f03e9fa62c785f10189b8a1c2062a5fd3ed1eb4adc01faa2fa96835ddefd92877dc23bd33cf2515d42a0973c017dddfa1adc52e8ef4fbdafd8002ea281876092dc60340423567c4d57c8a4233f0181119be5660629949b951511b208cd490f1a8ab965a14639b5831ef164f091e608c30bbbd1193742fc04f2c6201dec6d3c928bf4fed3d2f0daaa308e11c92cb0a09e622302f625d828ffd47b6df1214f6f56fae3bfe22b9c1a688816baa12ae2056baa1b470e951118338061135a876b8bb739a8b938bfb57cd7bbcac51b8c3fef9088526db58eb21c49eb3e0f32ed0fb85acf5b877010f2809c83f31c280ba0a5a9a7ad8bc57be5ba11b4aef41afb988a7de5d2c8d40267bc4d77561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045b0bd2b339cdab1cb752df7db1bf10e0fcc4b57fed7d380ff50ba3a0b4b018724b77966166a359aa5541e77c34a58fd9dcb7d88ef6e7e0cd0e140e1adf959d28b"]}}, diff --git a/txscript/data/taproot-ref/0cfce5f569e35c19633d12676981cda0b47a34b9 b/txscript/data/taproot-ref/0cfce5f569e35c19633d12676981cda0b47a34b9 new file mode 100644 index 0000000000..b297114606 --- /dev/null +++ b/txscript/data/taproot-ref/0cfce5f569e35c19633d12676981cda0b47a34b9 @@ -0,0 +1 @@ +{"tx": "2cc56a15038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49a00000000ec9501e6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7b0000000043261ee960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e100000000823f43cc013ca96b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487b5010000", "prevouts": ["c1243f0000000000225120036cd49b0a5a8928de04f8e04bd3da02711fbb4d9053aeba12a20cf11cba05b5", "bb6f4700000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "cd9e10000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "6f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361835f9abe9a741de0e36f4900df38cc6cd8be0480d341e9b7353c9d58c608762796126e2d69a152489172163b4bb3b76a5285668b37fe09a10764d2324ee4a01a6ef766bda57b4717926485a86d332fc460fd2733e6a54825f17015621dd4290"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936702c3c7c1f1da03c8b27f2bc575737070d61786cccc09f33c0640d21457e29b546c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa250e9882e2e133b56af40caa5e77ecf964d6e28c7a51ea626a8db4d1e1f7bbb4a3f8f9fe88f0f431b5ffad473abfcf1c4b340e1c7daa1232bf4c86f035b8cc51"]}}, diff --git a/txscript/data/taproot-ref/0d1dfc0136b588b721884040ebf5911514ebb74f b/txscript/data/taproot-ref/0d1dfc0136b588b721884040ebf5911514ebb74f new file mode 100644 index 0000000000..2c8b7541f8 --- /dev/null +++ b/txscript/data/taproot-ref/0d1dfc0136b588b721884040ebf5911514ebb74f @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270250100000036c4ee558bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4510100000070e54af860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ac000000007953921f012baf0200000000001600149d38710eb90e420b159c7a9263994c88e6810bc727afb653", "prevouts": ["de1d1200000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "bbba3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "781d120000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e8", "final": true, "success": {"scriptSig": "", "witness": ["8b12312a5336aadb74e8201a2892680091c451ad34555b44330dcecafd075fca2da0d6a1cd039c82ea25ec0a66e7321a99d0d437c100510dc0d7465a3513524281"]}, "failure": {"scriptSig": "", "witness": ["9b7c20852b9e943c263b2e5c0e100b643ee71ef8ff2416512705ff4ad0dfecc3b9c439cb01f62ad0920375dfe13d746068a161571a51eb3bf0b41782813854bde8"]}}, diff --git a/txscript/data/taproot-ref/0d25d4167a2171b28beda354bc7a6b814d718e10 b/txscript/data/taproot-ref/0d25d4167a2171b28beda354bc7a6b814d718e10 new file mode 100644 index 0000000000..2f008d6447 --- /dev/null +++ b/txscript/data/taproot-ref/0d25d4167a2171b28beda354bc7a6b814d718e10 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc900000000f2275ef2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caf01000000fc57e8f90367dc99000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acba7c1440", "prevouts": ["6647510000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "52934b000000000017a91418261fd2fa0b0480c86b918607add1dde9f7026a87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "6c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a238d55badf8acf8a76486c1c58a90ba61d2c17882158465b124e563f4a2674d94fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e872a8a6de95a80dc4a6e95ba0e12854eab511c8acfff04c6cfab0ff55ad6b178"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab66e6e50f0e23344b2fb4fbd1c94b97eff6a18e7892810f712f9b1a97473dfd5b22591e944b414d99fe534a482351afe29b8e90b07993fb7f3f85b72380ca5294fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e872a8a6de95a80dc4a6e95ba0e12854eab511c8acfff04c6cfab0ff55ad6b178"]}}, diff --git a/txscript/data/taproot-ref/0d265e43ba90ce1827ee538563c6a293b0b03ff8 b/txscript/data/taproot-ref/0d265e43ba90ce1827ee538563c6a293b0b03ff8 new file mode 100644 index 0000000000..38276c6310 --- /dev/null +++ b/txscript/data/taproot-ref/0d265e43ba90ce1827ee538563c6a293b0b03ff8 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2a0000000037452ca28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ca000000003ed3dc9a0168c22d0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca639323d", "prevouts": ["1e6c240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "06ca36000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/minimalnotif", "final": true, "success": {"scriptSig": "", "witness": ["6cc2577c611c83d4bf802fbc3817b2e24f285d3c2b707bf9a36769626d6d62cceebf765a634aeb628f611fb164807f6a3f075f63f717fe5f32193ffcd2ea0dc5", "01", "646a6720871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5e13cad19c924f09e742cf01d7e012810213f06b075da864011776c4e0e33ce5afd4f5a80fdb0e775e9347ffe0d8d06d20821e8392839b829c29e03cf24dd39e09e6d21873535d25ffee6834466c284ff42ef82d8fa2fdd706d38dd213905035c198717912f4b406e8d3b313d97c1127d1135c371a850790824e04061625b9d13fad9f6d66cfea14ccee2f27c94687462e60c93097e3ddae516a269438c7ee5497178e22127db6c7f8f175fff2d2055fc4c08a025732ff7ea1096ec159efbddc6f248e0af5869f80622f637a3edafb79d72487846d4b0589ad8df1e49d86b58ae982564b911df2d2fca61beb75f1ecc1a3526592822acf1cb81afd4e2a93f13b7dbd0c12ffd99a2b3242b359ecbd2060409f001c89f4f8371cd210f37fc35c4b1df78360227d44f218f9c188c83f404e81070c2440736b5601340b7fe06d3b1bec47189a7be4ffc0056c3ee876b2f14785a511ffb40f655d5a8b5fa356d4081558c155b0d7e8c00e6282b2c83a0b7370731ce99ff8996d6837e990d84e1874f60a177a028d5b32d1137467ad00d3419299404906e230dd6a3cb22ab6dff4f06738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["6cc2577c611c83d4bf802fbc3817b2e24f285d3c2b707bf9a36769626d6d62cceebf765a634aeb628f611fb164807f6a3f075f63f717fe5f32193ffcd2ea0dc5", "03", "646a6720871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5e13cad19c924f09e742cf01d7e012810213f06b075da864011776c4e0e33ce5afd4f5a80fdb0e775e9347ffe0d8d06d20821e8392839b829c29e03cf24dd39e09e6d21873535d25ffee6834466c284ff42ef82d8fa2fdd706d38dd213905035c198717912f4b406e8d3b313d97c1127d1135c371a850790824e04061625b9d13fad9f6d66cfea14ccee2f27c94687462e60c93097e3ddae516a269438c7ee5497178e22127db6c7f8f175fff2d2055fc4c08a025732ff7ea1096ec159efbddc6f248e0af5869f80622f637a3edafb79d72487846d4b0589ad8df1e49d86b58ae982564b911df2d2fca61beb75f1ecc1a3526592822acf1cb81afd4e2a93f13b7dbd0c12ffd99a2b3242b359ecbd2060409f001c89f4f8371cd210f37fc35c4b1df78360227d44f218f9c188c83f404e81070c2440736b5601340b7fe06d3b1bec47189a7be4ffc0056c3ee876b2f14785a511ffb40f655d5a8b5fa356d4081558c155b0d7e8c00e6282b2c83a0b7370731ce99ff8996d6837e990d84e1874f60a177a028d5b32d1137467ad00d3419299404906e230dd6a3cb22ab6dff4f06738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/0d3ce2afc206b93ee7c40177e168a295fc3e5ce0 b/txscript/data/taproot-ref/0d3ce2afc206b93ee7c40177e168a295fc3e5ce0 new file mode 100644 index 0000000000..8f9a68b225 --- /dev/null +++ b/txscript/data/taproot-ref/0d3ce2afc206b93ee7c40177e168a295fc3e5ce0 @@ -0,0 +1 @@ +{"tx": "4e4d1dfb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a100000000b81df2cbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcc01000000b1bc72eb0373d0a700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df979722368987c51ca14c", "prevouts": ["558933000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "ccf77600000000002251209d7a18923cf92d77a70864db68b8be9c97fe6f327eec6aa2ee3bdf40725ab507"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "677d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a77b70c46c994a01ec5a816124f61e0f5d1b89a7d1384137283c1b5de2b508b62e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdbceae773fe677547a5f8be2986f5e4c7dc436c0d3f0e1e86711aa468c8778215"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8687eac120734a03ae4c27d3bf57e4c4c383799b8e878ebb1c20141d650e89e9fbceae773fe677547a5f8be2986f5e4c7dc436c0d3f0e1e86711aa468c8778215"]}}, diff --git a/txscript/data/taproot-ref/0d4d3db873cac71185de9e2fa4462b2f3ba96462 b/txscript/data/taproot-ref/0d4d3db873cac71185de9e2fa4462b2f3ba96462 new file mode 100644 index 0000000000..03f0df434c --- /dev/null +++ b/txscript/data/taproot-ref/0d4d3db873cac71185de9e2fa4462b2f3ba96462 @@ -0,0 +1 @@ +{"tx": "64f4e4390360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707701000000fb3218d8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ced0100000081e9f5b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcc010000006137ffcd047b7d89000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6034d4655", "prevouts": ["3d9412000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "be405700000000002251208ab07249a1fdfb04b130308cc651220c9430f0ee7d7b49fe0191e15183fe6b9a", "277321000000000021571f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363885a0e92cd4b057c16daea5a7b83b3e63537af4017f46a840615a8d8f567c1a"]}, "failure": {"scriptSig": "", "witness": ["6a0a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/0d5ecc8d0c063c2641c3a8e7adff9ecb0323914a b/txscript/data/taproot-ref/0d5ecc8d0c063c2641c3a8e7adff9ecb0323914a new file mode 100644 index 0000000000..2deb0bdc81 --- /dev/null +++ b/txscript/data/taproot-ref/0d5ecc8d0c063c2641c3a8e7adff9ecb0323914a @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff6010000004f498f07dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c860100000008441211dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7700000000fe3bde330149db9a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9fec5531", "prevouts": ["f6da7500000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "dde94700000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "c6d94e000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3043021f0da3297ff19fb04fa25e2c5bf6bc43816cb2b39db34d5f6754ce62b442aa9d02201b5faaf44a89577cbf13388fb8b09930622afaa54109768373b23b0d57bd6e3283", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3045022100961fb8ba71e716ed2972f15218c42ccc4efab8bc86f2fd593fe50a367952c1a502201b7c7cfb759576779c636d74992adea9355ca1646d860f7bddc563ef13f1f0b683", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/0d65edb0c2f57a76df2b15cd2c722b18edffbacc b/txscript/data/taproot-ref/0d65edb0c2f57a76df2b15cd2c722b18edffbacc new file mode 100644 index 0000000000..d768c0c125 --- /dev/null +++ b/txscript/data/taproot-ref/0d65edb0c2f57a76df2b15cd2c722b18edffbacc @@ -0,0 +1 @@ +{"tx": "01000000012e09ffdbb2069feade9688806d408b21e4e24b0581b653f6a686a5bf690596fa01000000008f67898d033cb5fd8a1800000017a9143fd5279308772d81081a68d882f81a7ac08fe1d98758020000000000001976a914d2eef9cb56b74880f063df7305ec01f0b8fc540888ac580200000000000017a914dfd1018683cfaa440400f061c02b281ec7e8e2d88771c9694b", "prevouts": ["3083ff8a1800000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid_unkleaf", "success": {"scriptSig": "", "witness": ["5685a450002b7722b67ce499747bfa853d11943563381312add9b974d99f5729b4e2bf51310826d839a461cf795eefc85bf51bec70a9d1e523ea6b733713db5e", "20cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3ac", "c2cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3cbfc5d7464d6f9932fdfbdb59ed04135d3da1fd24a1d97149f3f9fe8acd746e901c94ae67cd857f8f23543b618b38154b6c0432568bb8cf7638fb55d4cc0a24e"]}}, diff --git a/txscript/data/taproot-ref/0d687e26341ba489f3d7be5d0b46f4beacaf8358 b/txscript/data/taproot-ref/0d687e26341ba489f3d7be5d0b46f4beacaf8358 new file mode 100644 index 0000000000..0bef61a9c4 --- /dev/null +++ b/txscript/data/taproot-ref/0d687e26341ba489f3d7be5d0b46f4beacaf8358 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4da000000006af8c3e060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270870100000017873a89035f27450000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcfe030000", "prevouts": ["2887390000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "a9700e000000000017a914381003aa1ce42a7df73f2dd1e6e78ae0a36c6b1c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2172fc08f39dec38a16acdaea6f2fb40d915f4bcb39aadc0ac96def6ea8d2de907407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6d5e8883e00432528415be42327fc5a4a6375200eeb9467b263c8c2a6402f75ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2172fc08f39dec38a16acdaea6f2fb40d915f4bcb39aadc0ac96def6ea8d2de907407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}}, diff --git a/txscript/data/taproot-ref/0d6ac2e508ad66fe5e2ceb784535d11ee75cbe2f b/txscript/data/taproot-ref/0d6ac2e508ad66fe5e2ceb784535d11ee75cbe2f new file mode 100644 index 0000000000..f609b11eb0 --- /dev/null +++ b/txscript/data/taproot-ref/0d6ac2e508ad66fe5e2ceb784535d11ee75cbe2f @@ -0,0 +1 @@ +{"tx": "7aa1c49802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf23000000009585a1b7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b88000000003b0b69d601c2a39000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3b797542", "prevouts": ["9ed88400000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "440b1f000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93623ae85726644c2de015503b238f6d2ff3873dd043771b87773ddc298654b0280d81cfe71594e1389c7dbef12605d87c33af6e429193e755ec800f4a6d58e14260941252319b1d0989c3ca3905f2d65278f17fb3ebe6fd71301329f8e450b42a05a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b1651a3fc1c4e1b7c3cd67236d38206903995e4c6229f7d3322c375e330dd9b093e484a9e3a7c57c3845514d142b984218effb649d9e5eb3f309ab706810aa991d26af6ddceab3892536958f1ea20dd7b885ab499207106c7decaa6511a0e4c5a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}}, diff --git a/txscript/data/taproot-ref/0d75732bc24cbac5dc017bb967142c5648d55bfd b/txscript/data/taproot-ref/0d75732bc24cbac5dc017bb967142c5648d55bfd new file mode 100644 index 0000000000..2e9f2346e4 --- /dev/null +++ b/txscript/data/taproot-ref/0d75732bc24cbac5dc017bb967142c5648d55bfd @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf201000000ce5eda9bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2f010000005618a396bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0701000000427c408b01084841000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487d4145d56", "prevouts": ["24fb4c0000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "4f8a7600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "3763820000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/invalid_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}, "failure": {"scriptSig": "", "witness": ["611b77aec8c3a0a873ddffa29ff90e034dd6060c5f5aaf0c8a2dee2209879a02adbccd1d3853d9a166e6c32990b621b313362b69b5974a03ac89b352ee5e433b", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}}, diff --git a/txscript/data/taproot-ref/0d89c8dca6b7a1af5614348af7dd5ae2f65190bf b/txscript/data/taproot-ref/0d89c8dca6b7a1af5614348af7dd5ae2f65190bf new file mode 100644 index 0000000000..869f0699df --- /dev/null +++ b/txscript/data/taproot-ref/0d89c8dca6b7a1af5614348af7dd5ae2f65190bf @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf79000000003b14d3dbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2401000000537929c80432a09e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48751010000", "prevouts": ["a0c57b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f4c4240000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a99", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d85ffea93b39ff48f026a1de615f9bd5d9d5cb27805fa051e581b49afd71e8d341e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361e4dce6bac278c1b1e733e5c8ab81364e97dbfa61cc5cc43bccc0065b9d2eca6379b42341ec85aaea9ba53764a308ad79e21ba1c6bfeef93296a10f4c0e568eb3c50effc4608d2c714b1f589c510b82e2cb4bd2fb333954004903b4f08f38a79"]}}, diff --git a/txscript/data/taproot-ref/0dd2ab05d7639afe71f965b79bd7092a935732e5 b/txscript/data/taproot-ref/0dd2ab05d7639afe71f965b79bd7092a935732e5 new file mode 100644 index 0000000000..7d5dabba42 --- /dev/null +++ b/txscript/data/taproot-ref/0dd2ab05d7639afe71f965b79bd7092a935732e5 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41c0200000090748d82dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cec00000000327a6adb04bd048500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cf0c1a4c", "prevouts": ["d0a93c0000000000225120dc347dac30d55fcefc955ccbc6791a94d629e3a9213464313d15e8052cd76ad1", "f6434b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ee", "final": true, "success": {"scriptSig": "", "witness": ["a297b3345456c0e79f1ac7e940ae7b2031b4ffacddd92dcbc50b725a662e8018501ad94d516d521a69b48b21b0d3dcef7b7f042e2ff9b11f9548f65e98be96da02"]}, "failure": {"scriptSig": "", "witness": ["8c51135843b35986295761edd343c47c0c8f69f566dfc1e7ec19370a20421908d9e647a48691add825a30a57d53ddf5a8c4fb3964ff6196f0084454dc04a58e9ee"]}}, diff --git a/txscript/data/taproot-ref/0debebb3108bcd03c6d5ce9c5c2ce1a64f8da172 b/txscript/data/taproot-ref/0debebb3108bcd03c6d5ce9c5c2ce1a64f8da172 new file mode 100644 index 0000000000..e3a7e09f52 --- /dev/null +++ b/txscript/data/taproot-ref/0debebb3108bcd03c6d5ce9c5c2ce1a64f8da172 @@ -0,0 +1 @@ +{"tx": "b200976d01bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8e010000009fb86ac8037b817200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33fc3f5d", "prevouts": ["a7b074000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["97", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369753cb1a5a2e209ace27a7eb8605f5f7017a5ce229afe5de89ccd0b48219a4f45a7303e26d6b86d2a780c30dbeb7ba87c6a0494b901c3875fb9ca7f2f12bb2fd373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362b9f3130479ebcff49fd970febd3f22cafd2118ccf82fa26a081c98b144e890c088456232115bcc24dec0b5a24cea45f7d15fc3427ff6cd91fcf5dc3f7efaf083288455e3867d2ff7594cc417650f42f79f93c98aaa5c5ef25eb3554c8bf2ec6282285524a15c732567d099967405d35f7136f74f48f011bc4ab279ad8d14f14"]}}, diff --git a/txscript/data/taproot-ref/0e03e6819458e3a55e6655f8ac2fb5cb9b28406b b/txscript/data/taproot-ref/0e03e6819458e3a55e6655f8ac2fb5cb9b28406b new file mode 100644 index 0000000000..f280959b03 --- /dev/null +++ b/txscript/data/taproot-ref/0e03e6819458e3a55e6655f8ac2fb5cb9b28406b @@ -0,0 +1 @@ +{"tx": "0aaa8a4802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c72000000002635b9ba60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701802000000ce18a8af021b536e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac0651971f", "prevouts": ["36135f0000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a", "19de1100000000002251207ea7068de42e8dd8ec2d889eabca72799b94dd329861089e307e247da6412b8e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "837d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e87e533ff75a4d67e066dc739e50d12e058e790be330db290aa1a5b4fb647c89858163db171dbfcbf374971659a5a65d0378eae0ee15db360ca8cf80a8c2e13046"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365b8d95c6db891b4b73acf316d977e35c7b522b3e596d08ccbc7a995da83161483f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08209d3f278379d69ec93b9031f683f10c8ab57e2d08c050c4811cb81bd332eb9e3ff15e37d03bf407745d47da370f693bba1bd1439d95d9059575aa23ebc3ce6e3"]}}, diff --git a/txscript/data/taproot-ref/0e1d5cb6786009b8f3825aeb3f4c7eecc240bf0b b/txscript/data/taproot-ref/0e1d5cb6786009b8f3825aeb3f4c7eecc240bf0b new file mode 100644 index 0000000000..737110fbb3 --- /dev/null +++ b/txscript/data/taproot-ref/0e1d5cb6786009b8f3825aeb3f4c7eecc240bf0b @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1e000000007f87f9d660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bb01000000b381a6b20118072100000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac24010000", "prevouts": ["ef6d640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "076c110000000000235a212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["43859efd869b15d8b33f3c634b4e96d875595f9690bd5803c48fae26bbf1f097fa69dd48f8f59d02a7e642043bbe44a539d068d0e3f79843bd4aa4ac91433b86", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/0e1f79030f3681187ce4b16bf43133d56c470a63 b/txscript/data/taproot-ref/0e1f79030f3681187ce4b16bf43133d56c470a63 new file mode 100644 index 0000000000..eb5a1edf0c --- /dev/null +++ b/txscript/data/taproot-ref/0e1f79030f3681187ce4b16bf43133d56c470a63 @@ -0,0 +1 @@ +{"tx": "6fe1dd5a02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c070000000006cfdada8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48600000000e8441bcf03113b90000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cf000000", "prevouts": ["bdc05b000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "6a7436000000000017a91486e5fab3386e07350db4c59e442dbaac96c1816287"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "235a212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["472e4d32f1c25c84db688dbda40fa933bf8472109f2303175068888ae7b2dbace4d10bc6468c490dc7c2935c1a01af39812db491416acc58a4809fc899dfa862"]}}, diff --git a/txscript/data/taproot-ref/0e229a80fe4e2619a4b272d19ce5815986d08fa2 b/txscript/data/taproot-ref/0e229a80fe4e2619a4b272d19ce5815986d08fa2 new file mode 100644 index 0000000000..a9dc66846c --- /dev/null +++ b/txscript/data/taproot-ref/0e229a80fe4e2619a4b272d19ce5815986d08fa2 @@ -0,0 +1 @@ +{"tx": "0f80966902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0e00000000ea3117d060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708f00000000ee3251bc0203da6600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc722010000", "prevouts": ["a96a590000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3efa0e000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_66", "final": true, "success": {"scriptSig": "", "witness": ["bc6e0c791c7513090a5f4e337e6e2c521f16dde08d35c7a410615e8fc0936afc9dd68bf98dac81565c3776a26a4ad2f09022b9d9fe5b3290db73f67ddb89c01083"]}, "failure": {"scriptSig": "", "witness": ["ba2408cd81a669ba47141a8e5dfc436b0f542877da45e559ca29b444e5eb9eb23815b7e4d96999bef8bb447fc0cf6c0bd6e670d024436c27f4437f8094b3aada66"]}}, diff --git a/txscript/data/taproot-ref/0e27294bb1dafe333a689bcad39dff7fb6f9cddf b/txscript/data/taproot-ref/0e27294bb1dafe333a689bcad39dff7fb6f9cddf new file mode 100644 index 0000000000..5491b4cb65 --- /dev/null +++ b/txscript/data/taproot-ref/0e27294bb1dafe333a689bcad39dff7fb6f9cddf @@ -0,0 +1 @@ +{"tx": "57cf5f4502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf6010000006a9486e760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702d0100000035f118d4039b315b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac7d735b5b", "prevouts": ["8eae4b0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "768f11000000000017a914b403773244c403f76163005c780d53872622b52c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["e0fe281e14a8a8cd59a07d5c0ece3e4836edc64880ae9350f56ba15bc232fa9257b1d4f98bd0336f690615600dfc64bc5919d993ef03289dbc3944f754036e7000", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/0e28329dee72cdf3ca474e54b4eae5fb8c42ce45 b/txscript/data/taproot-ref/0e28329dee72cdf3ca474e54b4eae5fb8c42ce45 new file mode 100644 index 0000000000..c4cbac2023 --- /dev/null +++ b/txscript/data/taproot-ref/0e28329dee72cdf3ca474e54b4eae5fb8c42ce45 @@ -0,0 +1 @@ +{"tx": "c4706a100260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f700000000efbe80c4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcf0100000062bb14f502b16d800000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898726000000", "prevouts": ["9d9a100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "012f720000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "287d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e780a528759e22c32b672b3582ec3b98210a6d7cdb045b8c2f36dc39043db702a61bc10490c3b13d9c4f63caefcea4aba06d3a92ca8668ebd56c703a638058ee7"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ae0185d73b30cde4b6f847d95b0ec77b009b44599f3d33d8be12ed96fb030558462eebfc32d9e48af9ce92e50735d36faef083a1171bd1899835a9be2fa30ea55b4ae3ee914d52223472aa57f653ca8073aef0e7910b2553778e1ae03228475361bc10490c3b13d9c4f63caefcea4aba06d3a92ca8668ebd56c703a638058ee7"]}}, diff --git a/txscript/data/taproot-ref/0e292d3b3af29268349fe695e0f7ad74c422612d b/txscript/data/taproot-ref/0e292d3b3af29268349fe695e0f7ad74c422612d new file mode 100644 index 0000000000..41c1c68e88 --- /dev/null +++ b/txscript/data/taproot-ref/0e292d3b3af29268349fe695e0f7ad74c422612d @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127008000000009184f39cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8b00000000b18bd5d28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43300000000963b85dc031aab6f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7697ea15d", "prevouts": ["9e2f0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3c0a27000000000017a91486e5fab3386e07350db4c59e442dbaac96c1816287", "7c613b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c6", "final": true, "success": {"scriptSig": "", "witness": ["f5664d07dfa6f7a84016bb2df0387801d3a8d30dd7f4b641105f06ab04c2d69986c4d0e6085db919fb36100d3d67ad8c46c007f37046634b145e8d33568ae8c3", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a22fd97ec717ce4684ca78b6efc91ea96808bdf3854146a3a69c6f26dc3ac74345926d557f0d40fc61bc3da466d3bb2945d464df51b1b21e1dc83b9e10927f4bc6", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/0e41c7f53cff3726f8dbca36445f5bb99cc7515f b/txscript/data/taproot-ref/0e41c7f53cff3726f8dbca36445f5bb99cc7515f new file mode 100644 index 0000000000..70d1462b50 --- /dev/null +++ b/txscript/data/taproot-ref/0e41c7f53cff3726f8dbca36445f5bb99cc7515f @@ -0,0 +1 @@ +{"tx": "48b53c3102dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c390000000029ddda8dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd6010000002acd50fb0243a8c5000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc70404943d", "prevouts": ["84ac53000000000022512027986c975f6014bd54fa55f3e483bd83d3384004828bdd3e489d9b175e79ead5", "ae1574000000000017a91498e55eac47e04767f832d50008ff18559102c9e787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21601f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["516609a38ddfe1d98bbaad43bd619e65b73a163a7a9467bad83936a63ee4fc84d6d53ec50ce63dd171c906b33b9d4e41feea1e386ea2c3c1853f8f736bd03010"]}}, diff --git a/txscript/data/taproot-ref/0e73fd872d8f71896397723287ddf1497ea61297 b/txscript/data/taproot-ref/0e73fd872d8f71896397723287ddf1497ea61297 new file mode 100644 index 0000000000..09422c637d --- /dev/null +++ b/txscript/data/taproot-ref/0e73fd872d8f71896397723287ddf1497ea61297 @@ -0,0 +1 @@ +{"tx": "4de70a2202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1402000000fa3ce6a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf401000000b6192cae031df747000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374872a010000", "prevouts": ["52c025000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "e47b24000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090202cab6ff434e1d5b531b7202a554db72d8e3a67b117026249d92b7f971b77531e5440a1d94bd95bf355f7480cc535932d63a68eca87816757587158a417ec9e2d1c5bfc9f7dce2efe4090f1cf58d93c68becd06ac3221cb3dcdd419ac707037f85fcedfbfb8c3f44e847e751d244732dbd2304e4b232e5a8d8cc6a4fd4a9f418c2bc2e991b82f503077342da58cfe34cc3269e36fb4cb2c239a2a390d21323498c58a3280380e3944222ccd55a0c94dc57fd41b1a2655180e655615a684ab78bacb6318a43cf5377004bff7fd42bc6655b9ba7e53d0eba72c1bfec28a45a0ad1d971868761d057246ce4b852620c0ec16db0a8c62fe4b561236e64b72285b88e754c655d465d3b2d7261874ffc761f74e2e5a8c7ccd94decbec81a746d50d138dc66cfa8c4ede8df437da98a94de362b49874eb3acb1566effbda20bc545ef9c961d27219ca49813cdad47f82892b9060bac47e0b9df85f89df4230e3b4a9a4d5aeb61c791049334bca917d67b7299eb61f80f607212b731adba0e1db180cb0a05cce3d4a88913612caef50e3b4bb7c1e4b1e124eededd1f978cb6217f45992de079c39f331f51fe9b0ebce3a1a9d84b8aee0f2e3c4c09d1ccb1c4f2a5439b0227639daa1b36ba0694185e07e546f43a0a382dba25df1aebc79326fbd342f9cdefc85b8f1689c9dfe48b1d140e18d16c945cabdcbe344e485fd14394882638e7b61685fff9d41cf87d75db", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb4607ba7298d17f73d24d5d86c1d3d0fb9db652f9c069df5b4a0333ad80d0a33f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082a04823906532712c3d4cb334ae6c7c41a1294a824a25b5277d43f47953a1da33e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}, "failure": {"scriptSig": "", "witness": ["4d09022a97838beabfc8d8978d228f37f06ee48d7614432cb1aa6a915f2bbabb2507f4d8cbf9003ca4a7a110c3ae6b1eeec5f23799dcca73efe08d64f2d976ae0a25db8a8d57a4b605304789807495b4d9fa8c8ef385c52e15dc66f6f22bc05d03313724fc0248cde0b0371edda8bbb3ecdc7cb4042f615648f3bf996bc2da2a795baf2598056feafc1e82d4e374a06a5a18742585ea84f3ed67e1692585a5869ec471e93e715b56e07f93522c4da6e114d7cb38776f2190b1fbe6fc6a5e6a57c52ceaa42a3fab239c4e66ab7910c3d0e5d3ee28b0ceba338b48cdee99fd605171eee11872db14cda1636269e494ef17056919731ccb9b517b4ebb2f79c73ca718b6f91691ce7b5210e5f6913019d9bfdf70b374815352b8072cc40fc0208df93fa41013c2ebdb8225df7926cb2b1af08fbb5c1585914d131a1fcbe4ad644b8504881c787b0a74eb18bbed16193053a0604260a681d4cef558954b82163c8482e6cf11525d3eff08c2b4460cbe091cbcb040039dd79fcd1d426739f3bafe25d75e1f2a2ca5b631ca311053108a36114c753f5285ff0cb036042c302d4fb5a20744760692aaf12f17cd6fce337d63a28bd143cd8c9fda6ebfd2f77235acd89c4485b948cda114869460cec264596a4e11da85fb24e230f2650686711884e2b373199b1bf7f15ac24d5f198ff3b03079b7fc764ab868440c0680b6ec3d170b571da64adcc0b079ab4d051a46cd7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a7d2c4cebd38f1f6f3fa3eb99e7c82e9a917412571f2b1af1e1c6189830d7fa4e3966518140ddfb4b2a9d93e012e33d80f6a3bf7f24f1b44efe84ec3ac236f0e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}}, diff --git a/txscript/data/taproot-ref/0ea17004d718ec4b5b84011a18828cf136f86973 b/txscript/data/taproot-ref/0ea17004d718ec4b5b84011a18828cf136f86973 new file mode 100644 index 0000000000..571ee5df22 --- /dev/null +++ b/txscript/data/taproot-ref/0ea17004d718ec4b5b84011a18828cf136f86973 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f00000000aee490c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4b000000005f173cce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703801000000fe1cc3f8014c7b3000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac9c041628", "prevouts": ["5139310000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "560c2100000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "d2ad11000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["3045022100d7a113b9360aea818c00e3f6a1e2913059efbc3218bfe687f4a214df3a18930a02203a87c5b812f3b0777f570378af8adf62a33bf2edd57185ecbcb01dc0aa75a2b902", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["3044022057e577dda9df8746b2428cee605f12b38c5300e902b467e9309a3cbf451456a602200dad23743fdbf1bfd8678000ac822d41d43b62f0e0e609490aa48288275b50b002", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/0ea4e4491ee2abc4ea52e48ba33eeccf62d5f85d b/txscript/data/taproot-ref/0ea4e4491ee2abc4ea52e48ba33eeccf62d5f85d new file mode 100644 index 0000000000..b3795a1179 --- /dev/null +++ b/txscript/data/taproot-ref/0ea4e4491ee2abc4ea52e48ba33eeccf62d5f85d @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0a0200000089a51db2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6301000000b13edf8504c9d17400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac29b2eb20", "prevouts": ["4612240000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258", "7a71520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "3d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa671c5f6e3fdb2cca9ff2c8978272a7c72309b5e793932f9bb10a0961dd619da6701c89cbc41056f58ce11974b5756eca381e306e17d72fcef5e58c3aca02cf1415eb41ce20b61903eca7e2f7903a7c5f76d50ccbb22a22a302188dbad2e46b28"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367a4323bca4261be341492d2c8aaea5b9c8cd338f75ff3ca656464aeff6e26a7ada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eef9a48fcabec25982850a496e19df71982d596f167265e15d1ec282fb30074b91cb891527dccd7fe22077390053ac1c45ab6e7110116df1a30c9559411f432f5"]}}, diff --git a/txscript/data/taproot-ref/0ea84a4a5eee9c0cfe8bd52347d11c08b97d6640 b/txscript/data/taproot-ref/0ea84a4a5eee9c0cfe8bd52347d11c08b97d6640 new file mode 100644 index 0000000000..0c6787580e --- /dev/null +++ b/txscript/data/taproot-ref/0ea84a4a5eee9c0cfe8bd52347d11c08b97d6640 @@ -0,0 +1 @@ +{"tx": "2c58931d0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270220000000000450dd28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4010200000073486ed00336a552000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc44000000", "prevouts": ["63ed11000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "bbea420000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100922f35dcf07596b5a8df94f8153105be4bc76f6039de12c8071849f9b7ab840c02200e5cf5a15ef2aae75a2ce5f3efce5414b44f85b5c513af68710c2d18c3a8e151832102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "47304402205d40dda17032ebffbe930ec4c8b5deffa2919db868c55604902ab66cbfa9784c02205e22995e1bfdda2e9fefa19c8a07d449f43b75dadbf83e5f22a5af64fd8779e5832102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/0eb26606cb3895e3e7c3160a2acb1dd55cfde903 b/txscript/data/taproot-ref/0eb26606cb3895e3e7c3160a2acb1dd55cfde903 new file mode 100644 index 0000000000..34fccaf088 --- /dev/null +++ b/txscript/data/taproot-ref/0eb26606cb3895e3e7c3160a2acb1dd55cfde903 @@ -0,0 +1 @@ +{"tx": "a9916a060160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127020010000002766d9ce0413900f0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca973fc43", "prevouts": ["5518120000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "be7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eab0507b9227b06ce0689f3875ade4de998c1d9b3bd044e9f3b63e2ed7f9e05ff6f69f1f3a976918b4a05b157c0a8e21d478cce8b5d78fdf690138c8d187dd5c9"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8c2ac45274f354a7fa6bf45f239b04832d37283b3079f2371915482a2c13848c20793b34d3eca391845c9ee05577f0fe1c8a49b621d2ce1a9da4783f236266e6f69f1f3a976918b4a05b157c0a8e21d478cce8b5d78fdf690138c8d187dd5c9"]}}, diff --git a/txscript/data/taproot-ref/0ec71de4446b68520af7b2f5cb5495f2f7d56bbc b/txscript/data/taproot-ref/0ec71de4446b68520af7b2f5cb5495f2f7d56bbc new file mode 100644 index 0000000000..bb81e5e3d6 --- /dev/null +++ b/txscript/data/taproot-ref/0ec71de4446b68520af7b2f5cb5495f2f7d56bbc @@ -0,0 +1 @@ +{"tx": "b925e88602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2a01000000148d50bc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700e02000000c93381a40114a80a00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac61010000", "prevouts": ["4a2c2400000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8", "368a10000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "997d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e874e6e02235f222bedd00290eb9daa035321655bcf09c112e5b4a77998f5c860a0e580b14ffff5bbee812c9f6e3af6b100c6b4cffaf41971c257964f1fb14f6f9"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368884d2a2b97e27dc9a8d5c4c13a1ad4f8dd33ff04d22905d87b0003d1fc0339de4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e874e6e02235f222bedd00290eb9daa035321655bcf09c112e5b4a77998f5c860a0e580b14ffff5bbee812c9f6e3af6b100c6b4cffaf41971c257964f1fb14f6f9"]}}, diff --git a/txscript/data/taproot-ref/0ecc927da181cd3e4cf9d00b158c6acd0700b7c0 b/txscript/data/taproot-ref/0ecc927da181cd3e4cf9d00b158c6acd0700b7c0 new file mode 100644 index 0000000000..430c29484b --- /dev/null +++ b/txscript/data/taproot-ref/0ecc927da181cd3e4cf9d00b158c6acd0700b7c0 @@ -0,0 +1 @@ +{"tx": "f33c648a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1801000000efe045ba8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a4000000002db817c60273f54f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca3000000", "prevouts": ["3d7d1e000000000021511f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "c54b3300000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09024308dd64e7eeaf9ca2934bb2edc0405828ab2e3c96947aea1a656e1d8ccb8eccccb8a8478785121172cd86cc106b63be1cfa178a8853bb8900b66e1cbed5790925fe42025a2bc1e46e614b26f0e50c25f0bbd4621e97613e00340903a590162b9c6da461c5538244177a8f655a4532d13dfc6e7a7cf457c68a5b8beb96687d9f405dd123bc73dfc9accb748851c6d2e0fe7f7c94cd4f921b7b85876f5dc8bf5d804b43c41980b250fb21314454dd0912e643f5b9f38d9297c518625c78498a62571115265f05ff8dff13a154eb1cfbd8c9aa3159515b16f0eac381d36648eb3b8c37f06925cfc6d005869b5d2a0d70e8d7b80fefab7f1c9f8abfc4f311dbcb1de21f92e97bc157d3c47981bc84dc58cc2e44a78ceba1e1c2a27ccd116a80c1c3cb3a0706c1d1ae044966792b9ba6a12cbce633d9275abf86eb4f03e3dada0e396ddabe7a48c1dac4e83b8e43da7fd1f938f13a44b4f5d56f5c03536dcb33c1fb7f08e72e070d6c39c0ef54b922f830ebb90131659084e648be2881569105b238863c742db2647996fa247f87db1ea2bbe81f20c08666333c7e3cfff05a10e3e0ad72071a7302d77499346ce53c8e8f5c608fc97b39e83b31b8f2606372113c31f9c444dd73862900a33917a9b2c54965064e22d751da0c44acc6f8be5bc0ffa3947a6b61e53d3a8756da5e27f39590647b7e5b6f0a5d6c6d2f1388ccb1e6615020c3ce8e147a7cd83475", "967d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bf86d7708a8015fd8c392d5dfda539be3c55b3d42b83ba5bec57bef080407e280ad15d5ff3e747c4643a2e7779e2cae74c1db700bc0de7d47935e7ffa6ea968f"]}, "failure": {"scriptSig": "", "witness": ["4d090220e2abbf680f2ed9ebb9358138d93a8f99cea634015714200ffad0a07283553e012b8ea97ea8f366753988f2d122da3a47fbfa14bf4db54f3ae1081b0e01eb500b86ec085c81b6acf27a05639f352cd928e9918cd40b0aacca273f35e95f9fcdf08f1cef2ef3685010affbb8705aeb6f567ed5da99d80a0d8ec66007855f79e07c9bed840a56359fbc6bf42c1c8189a3fbb02d24c4e3f75535209e1c600f1e8247a0804edda81a3441a07566a3dbed889d45e09d8a09008af47bfe7362bb3b751d9238b44e2b7dc3bcfc23c4092f0e9c5bb3836547cd3a3f53226dedf032d3af18f132b684c3fd0bceab36dcfb608d51e0170c3b00804972a8c59e90b2c80024d975eaadc5d55290089649e1760c3485769cb8693aa6c5a5db88ce8a151aa22962e3a50d465858137719df4cbab33993637ac1706a6dfdd40ccdaa9960118af4369d769dd7452fd281faa7d213d6b9c83175e5dfb9d68cc8644a0b43877c57eea6d2a6e3842bba47c60ca184c886fc752b41694d164b569b434788490ad7ec2100345df48c7643d4e60c7c4b9dacce0088850eb3bc54c1e469c767ba932789c00d7c0b081c2e8dfbe70bd4232fee055b594a9a25f369ea5186508489792c2026fca6e5ada25413ca0ff273108d5eb71a7c025703bde96ed4678e87e1c4a507b4171acd5548a32fbda2f76fd88ac4b78c9b5780ad42a9ee7fdeb86f3af12446f579ba472a47a416dc4275", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360a229273ee78a689305c88529da0b62b319efef7a9724ef9ac9c424c39c39693dfa3c45458ee21e782394432ca1779912e92f35e0ff52c3985a5265a8dee58b3654e31a1d81b19a8c2670362b3a1330b2f2d66c8db1c8314023a61983d2ff610"]}}, diff --git a/txscript/data/taproot-ref/0ef9e684b87a52e1d2ec2b274d91ca104093f268 b/txscript/data/taproot-ref/0ef9e684b87a52e1d2ec2b274d91ca104093f268 new file mode 100644 index 0000000000..dcd4e9ebd5 --- /dev/null +++ b/txscript/data/taproot-ref/0ef9e684b87a52e1d2ec2b274d91ca104093f268 @@ -0,0 +1 @@ +{"tx": "2922ebe703dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb9010000005c19b4fedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b13020000001998e48adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b010100000093d904b504fad96600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac67c6fe2b", "prevouts": ["deda1f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5841230000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "70472500000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_34", "final": true, "success": {"scriptSig": "", "witness": ["1bb7d8ac82792da18cf7b6fc941ae456d366e3b2e5dc80016affdc81639cb19dd353b28add3538645bbf1a95b668d8ccc2021328e7f3352bbb809a04320deeb281"]}, "failure": {"scriptSig": "", "witness": ["35be4efe08071f56f077d44e7e833ed7b38d1d25f107b68e9a061be4f948dce90dea7af84b9ea48a0bf9e685757c428191e8a9f4605c75808ae0a12b0f40bdf234"]}}, diff --git a/txscript/data/taproot-ref/0f0de5c345a12934d91427634192d4040e5bd1fe b/txscript/data/taproot-ref/0f0de5c345a12934d91427634192d4040e5bd1fe new file mode 100644 index 0000000000..69572735c6 --- /dev/null +++ b/txscript/data/taproot-ref/0f0de5c345a12934d91427634192d4040e5bd1fe @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4070200000035c405e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca301000000f48bf49ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b52000000003a56f2d902d8daa3000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac6c000000", "prevouts": ["5bc8310000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "a32d5400000000001652142540f27e90740933c99d4f17ab2dfc6c82951cfb", "05a12000000000002251202b18b828586b5828635076972ee0bba96c3f290312125c393cc54d832abc1349"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["26c43c1b8ec990445982be5e9b8915828484df8c50e041436cb711d37db150faee76fee8fbf9d59dbbc90642b9a5292906c32de278fa80e07c68cfa3d832e0bd", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/0f1aee7720bb0ab848210f3e547b18c4431e3651 b/txscript/data/taproot-ref/0f1aee7720bb0ab848210f3e547b18c4431e3651 new file mode 100644 index 0000000000..99741e9791 --- /dev/null +++ b/txscript/data/taproot-ref/0f1aee7720bb0ab848210f3e547b18c4431e3651 @@ -0,0 +1 @@ +{"tx": "4b419ba103bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe30000000088c28bd08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cb00000000ab5264a260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709f010000009807c48504d038ca0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d33e7c40", "prevouts": ["2bbf7d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "af753c00000000002251204b9049d3a4bee03b6d234dd4c8f499fa4ef0a49d04247a5113735801c2defee0", "5551120000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_69", "final": true, "success": {"scriptSig": "", "witness": ["8229af1d9e1a0356663f422ec8b816037cd086555f2f4fb97efe1b321c781b101a39c08fc602478e583b8da8bad33fb23e76e4f57506b5cdc1dfca0537390508"]}, "failure": {"scriptSig": "", "witness": ["ac613cf8dd46d046fe317410f8017a6d0e7ffa027284d45d3c31e6a4fe4f9787d47fe2423fc2096b31d864e4656611df0282c756101e505ba3401772217b467169"]}}, diff --git a/txscript/data/taproot-ref/0f2ec0ef703ae34c9801d778277b221e6ec19ba7 b/txscript/data/taproot-ref/0f2ec0ef703ae34c9801d778277b221e6ec19ba7 new file mode 100644 index 0000000000..be7db07bff --- /dev/null +++ b/txscript/data/taproot-ref/0f2ec0ef703ae34c9801d778277b221e6ec19ba7 @@ -0,0 +1 @@ +{"tx": "0100000003d15657a619affff084fc6b1bc2cdf5e85e399bb207d84ace710aa8effb82232f0000000000378eeb7906f5bd527bde63f7c45daff54c390a64a59dabeafc8078a9bd0a050f54db6b44010000000038906fb3492909e056fa5c0ef2af542be68aba07da39583e95b43e24484150891b1d5323000000000077e0c98802d0235951380000001600146d764276c66fec1127e5074db5bff3aa6c52553358020000000000001976a914b2c48f336848c91e9c274b4615a238e127bb7e2d88ac40000000", "prevouts": ["24977ad110000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "1ad1d66814000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "14cf091713000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid_opsuccess", "success": {"scriptSig": "", "witness": ["699fdb6b143012370d036103fdbcee3723efc7a11d8bb794ffa0cd69264b4b8cbd2b943139985650e3b05e6c591a1acdc72c62e1074032538cd74455bfede244", "20159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717ac00635068", "c0159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f7173cf6535970adc1aa2e2cd04b60847ed9656d715af72d750ffdba18631024451b7902b78fc59ae74800241e9b7a2e0578a35ace37791478c3e04a51e81e708c61"]}}, diff --git a/txscript/data/taproot-ref/0f51e2a5ab57413a930a436edf258d17d6ae7de2 b/txscript/data/taproot-ref/0f51e2a5ab57413a930a436edf258d17d6ae7de2 new file mode 100644 index 0000000000..6e9ffe8b4b --- /dev/null +++ b/txscript/data/taproot-ref/0f51e2a5ab57413a930a436edf258d17d6ae7de2 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c8000000008115ba958bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c485010000004a1f0fbd0350b06200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7624b9d51", "prevouts": ["7b22320000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30", "9234320000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100cc917317757baebac9ac7ea2b4437c4f196381721810a37e5cb17506c1efe01e0220054caeb99365885257fddacda5176a180e4a80aca61a86710c6f9bd528d34dda02", "witness": []}, "failure": {"scriptSig": "473044022038dad12902e5b503b0ebd814cd812e3d4287088d17f0c282c80175915bab241c022071526b902f0a1d8b81ca20efc0cec65f1abbf6fc811eb55c8589312bc4f8239f02", "witness": []}}, diff --git a/txscript/data/taproot-ref/0f7b105b71e9cb68726584b4fa24c0ebd801c4ca b/txscript/data/taproot-ref/0f7b105b71e9cb68726584b4fa24c0ebd801c4ca new file mode 100644 index 0000000000..7fbafa06ab --- /dev/null +++ b/txscript/data/taproot-ref/0f7b105b71e9cb68726584b4fa24c0ebd801c4ca @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41e00000000689473618bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e500000000333fa0f201c56120000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d2000000", "prevouts": ["c2e73700000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1", "5e323600000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6acc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362039563b955d2dbb4039cf2ce233b67393a3c90b1c8e11b9e093e855d67171ef5f8b38696f7f521c781f821b55aa4ff86c04fbebd102ad129a9d47907becd36b4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e183e343f15a28f9ad1157957559cb0b6b8ddccd5d64405c8ba15aa31cdad4142c00ae7d77688765097c61dd6dc7203a99b1de19633b0fe895af4a245d0fe1ab9735478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}}, diff --git a/txscript/data/taproot-ref/0fa616a640ec4b881c4c4ea08e1a39f481403fe6 b/txscript/data/taproot-ref/0fa616a640ec4b881c4c4ea08e1a39f481403fe6 new file mode 100644 index 0000000000..90edea9fc4 --- /dev/null +++ b/txscript/data/taproot-ref/0fa616a640ec4b881c4c4ea08e1a39f481403fe6 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704a00000000197308bfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8000000000a81903c801c1d73a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796b73c7c53", "prevouts": ["6d9e100000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde", "456f820000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "477d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936079db4e6166f733d5f26884094154d18acad271c7897e45716ba972f6c28bc89ff81b1159cd56b1887f265c0d653f3c782f8c9b1bd8992faa992c6296a364de747adf318628644459e7d8d4ba81b7833f70746497cdf0fced2937ab961dc2be46657009e9173c5ef8826379cea4b8c999e3ae37a5805e4cc6da117a3d2ee0eec"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d573dcae6844503e10ad73cd9b71da3919fcdf6472c18e1c41584f6b5b237bc2dbbe6d997bdcd7c7603d7696a19dfa7a137162827825260b73e89d3e21fe597dfd9e929a06047270fff43ba4c6b47136464c62381aba7ed74ab98bc69d199aa4"]}}, diff --git a/txscript/data/taproot-ref/0fabe142a692b593ed073f5db1ef2aca01dbd689 b/txscript/data/taproot-ref/0fabe142a692b593ed073f5db1ef2aca01dbd689 new file mode 100644 index 0000000000..3b94f71d52 --- /dev/null +++ b/txscript/data/taproot-ref/0fabe142a692b593ed073f5db1ef2aca01dbd689 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa00100000085aa13c060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e70100000090538ffa0198587a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964401975a", "prevouts": ["395b84000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "69b7100000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09024a923d3cf89646fe239b6e78edc49ef372a465916a2802bc58363bed0bfb6af97295a944a06831ba07e48ce1fdbbe0c3fbe99f7cd010612193e4aee7cc1adf8f102b8550e11c14561e13f825081218bf0d03e00bd0a88f84efd874a6831c94b90a1f62a1e15bcd144de1fd5d6d25f7eac390835b46ee3efc5e9de2ad4f7a4f5034f57994963b0f95029c14433ed728a3ce0ab2657e3277371413650b08c3a15db7f54c6507457c2704eb74c1925bf51305ce25e707275d73dbd10fc4e583190ebaf994f8b7a73219d2ab05a67fd3b8d76f41d650bbfd3d6a7cd469e1a7ddfd4a6c4ecf884dcb45517fba401be9194a716009a83b0cee92ad5238e5715277582389729a17782ee77aae8e0c88d8a265851ca33cc5e655aa4c06adc294fab4b94cd4c8b5f1470fe6177b7ad941326c4e5ffdb4a5f6c0d0d2e8c4ca36e68be3ae46249ea4a80c21115bf6263c0237ca832eff837f94d7c3a929e863ad157af581bb59e68b2938b7536075b807f3a13a4ddc01433d31258a2a173899ce082f9e616a379ec14bd54b7efd1901da4eb72db6834f635f1936e9ae40d240648784108435103849e1d5e0fea2952714daceb3f6bc3f77d34b70907c2ca67a344e5ee0ce35d5f3af7873d3f11601edaf4718af4da9c4e2ba5128d41b75acc1e289b0d5d96f9f76ecb30075debeeaa16c48d38dcf4744e855a95eb9431aafdbbb0a259f3b0baa4fcfa84c8140034375", "9d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361e133a480e620191da8aaca6530685b5d8d82e919edeb5352d49c034c0d561ba8024f0f821479c34a3d08a46a80a2c380535e71b033b1c786baa16eef71e1977ae2f7927e5cc4d53e0e18212acda8d85e01e1da74473232947322e5e96654c18"]}, "failure": {"scriptSig": "", "witness": ["4d090243a349217aa263976d92dce8f5610a6ec4a5e47bd02dab69919d176fd8ee4b03d4dfc4d258d1dc62344e1d0612e750a676ea8359aff9abb7bc9692cdb2b5b33833e3ffa4fdc4036c5cef11a9df1952086df6c8e4d3af51b6b3d3059ad9edaa34cb17f8cb8cc9feba574ebdb2a527b1c9a3f3f2aa44716424a80d4a25cb866a05d9759adf56a1cb93e88fb82a8ebad11a5525079f88a427760443f7d942441b816a482d7ce8fb7b9869594c1db3a8d3fd874b9ba32dad414870072b12155f3837908faa0dabaca85c3e46e0b28fb705aada228c84f18bf414e237637ff8cdd2c26647471b63501e899b8a65fd128ad0479042b9c1bdcaf70f6d0f8b7d92e490d0a48e4d2ce423cd79365f8cfec8e86425ba6bb4c90a0537aa16d26b48c53144e37c92657d46a797b7ae74578a05bd61616bed287e036cc0747c2b4320017c7099aae6a723dc5efb658e0e1a231812f452702ee0b062913a80bad5aed663b50e5a6458f6533593d8c7176d2a0cb7f280dd02f8a8a677932c12fe7e3cdf09f8ef12a1291a9d1dd27f0a59c5b9d0f99fe907f78a9673b9be0003ef1d90bd954db72d67cc0999a25c624f4c977a4f89656831748b08ccaa1b3a694022982709502393410fdd293c0dd73da16d6808e7a0e646c2be031483d000f19807c8b1b2edfdf8e1756c433da925e0d1dcd9f548bc8923b00b549760f0dd5fda53ff3245e86ba2548368aeed566a37fd75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c801b4c4a2960858f413ab5d98ddadc6ffe3ff6a6f0ddc4e13767870b9a730796b892175c0861377cad04fa4faba87807216c52ab5a24eadee36522f056d83a72756956c694637235f847009e8e23b8c05283b4a047903b3fbdb647ae4209c1"]}}, diff --git a/txscript/data/taproot-ref/1000a469dfca1be2144a6563e3bc8e3f5ceb2448 b/txscript/data/taproot-ref/1000a469dfca1be2144a6563e3bc8e3f5ceb2448 new file mode 100644 index 0000000000..f7a957ef64 --- /dev/null +++ b/txscript/data/taproot-ref/1000a469dfca1be2144a6563e3bc8e3f5ceb2448 @@ -0,0 +1 @@ +{"tx": "a1212fcc028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f50000000035a475f48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c476000000007698abaf02c9fa77000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478702030000", "prevouts": ["bdc53c000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e", "d6083e00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["8e4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb46e8601d3af4b3a958df52448c90f2764dee9285ef639d0a94e9c0ff98d78680d8d550033184c6424688af85d43f5bf525b7f6d8111e731f6e2359cae2801b117ed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}, "failure": {"scriptSig": "", "witness": ["4c528e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93698751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d5099eb053c54d8f72c6d7331f9a1bb3bf1b628df692ad9b7eecd4e01f4a47bb5aed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}}, diff --git a/txscript/data/taproot-ref/1007d21149445ee61da9ad4413d7acefa9ede7e3 b/txscript/data/taproot-ref/1007d21149445ee61da9ad4413d7acefa9ede7e3 new file mode 100644 index 0000000000..7e31154211 --- /dev/null +++ b/txscript/data/taproot-ref/1007d21149445ee61da9ad4413d7acefa9ede7e3 @@ -0,0 +1 @@ +{"tx": "7cd259480160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ca00000000e0fec3de04d7741000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87aa000000", "prevouts": ["722c13000000000017a91448964eab407ad5d6e123f59d9280ca7998f71bce87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2351212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["9c54e3358dc40fff5b6eaab0a7356c6e097a91d7d87aadd4a30d61eb9667964d011eafb4a8a5867f537a947468abeb8c238a1a7c6b9953215dcf3ff5b714520d", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/100be162498b413ca391dea2387d07097432e64b b/txscript/data/taproot-ref/100be162498b413ca391dea2387d07097432e64b new file mode 100644 index 0000000000..8a672d5931 --- /dev/null +++ b/txscript/data/taproot-ref/100be162498b413ca391dea2387d07097432e64b @@ -0,0 +1 @@ +{"tx": "e82fd79b028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40002000000f2fd11988bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4740000000030e1c39504a9a063000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac9333884e", "prevouts": ["093f3300000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "1a28320000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "d97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363255b317c7de6e9ae6bb70a9fb776c4c6a00d056fb5cee6a264a49253b234c169208680e05d04c3942bb784f68e647b385a50066aeeb87d1b11822ef550a3a38682a6e83df749f265180f93fd54e474915a8abfc6fef0a760c06d61a0bf42967"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361d56eca119efe8600c7ddbecaafaac765d2e5fc0abc9d3eeeeb65fccd7070d9846c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2d5942624d66fc39e30c2a996d85a0dad9a6418b79db996452744438b84f9614682a6e83df749f265180f93fd54e474915a8abfc6fef0a760c06d61a0bf42967"]}}, diff --git a/txscript/data/taproot-ref/101afec325ccd0ecfd32b22bcb5ddb64cbc1c497 b/txscript/data/taproot-ref/101afec325ccd0ecfd32b22bcb5ddb64cbc1c497 new file mode 100644 index 0000000000..4154debf42 --- /dev/null +++ b/txscript/data/taproot-ref/101afec325ccd0ecfd32b22bcb5ddb64cbc1c497 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf070000000062aabd978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f10000000022d1bc9003560c960000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb3c81660", "prevouts": ["78b26200000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "1625360000000000235d212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["e92d8101c980eff4377e6d8955a6be6eb9c513a73b76b0c2865d9217ecc002952e790d9c1b6d4873f01b62966c2e29a6c5c67d56950c0adb21878e7ce72b19ad", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/102f84dec76aa32c7c32a67b8398d3433fd9c124 b/txscript/data/taproot-ref/102f84dec76aa32c7c32a67b8398d3433fd9c124 new file mode 100644 index 0000000000..f53c7f0056 --- /dev/null +++ b/txscript/data/taproot-ref/102f84dec76aa32c7c32a67b8398d3433fd9c124 @@ -0,0 +1 @@ +{"tx": "2a4ba92a0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270680100000050b312a0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6d01000000f7b1108603868a800000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c6020000", "prevouts": ["7995100000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "cdad7100000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "807d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac32beddb8df376ed0f15f8ca557ca4fa4dab9ea34398a6bb2b3d4cd5dda00bcea090cbfbdc5dfcad7ff4463f3cf2898b3c754f5d70a369d7bdece79053e0da647"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ebc7c443b27f0c4bcb1a4d24531c68d10c673cef24ac139c6bf3ae7480664417e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e83f9b6f826008f58b0a2f0424fb9eb1e858fa037e128d89da74120b3f1d2e75bf3dbbf3726cbcb24bd9ee344fc88539efd23f46f5d6cac68dd1bf47840d55ab8c"]}}, diff --git a/txscript/data/taproot-ref/10549677366e93a6b247cf85ef6b109794e927a0 b/txscript/data/taproot-ref/10549677366e93a6b247cf85ef6b109794e927a0 new file mode 100644 index 0000000000..630d8b7620 --- /dev/null +++ b/txscript/data/taproot-ref/10549677366e93a6b247cf85ef6b109794e927a0 @@ -0,0 +1 @@ +{"tx": "f0b08b4f02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cae01000000806254d3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1e020000004cedc9fb03ed11cc000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7962c010000", "prevouts": ["d7c14f0000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0", "2f8c7e0000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "4e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa024d2ced480b827388702026dedb2056611ff82f89a108072a2691dd6856cb09a4a8046f0466b39966676954eca5d67ee52b1615e6fe46612ea9ab4edfa131fb"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369dbcd1ddf7df12d2fbe56f12d93a74f67dca3a0fa03128d33a048f2d963a2099024d2ced480b827388702026dedb2056611ff82f89a108072a2691dd6856cb09a4a8046f0466b39966676954eca5d67ee52b1615e6fe46612ea9ab4edfa131fb"]}}, diff --git a/txscript/data/taproot-ref/10624dd984bc11b57e154d0125049824624ef4b9 b/txscript/data/taproot-ref/10624dd984bc11b57e154d0125049824624ef4b9 new file mode 100644 index 0000000000..0e0b8dcc6f --- /dev/null +++ b/txscript/data/taproot-ref/10624dd984bc11b57e154d0125049824624ef4b9 @@ -0,0 +1 @@ +{"tx": "3980379002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7f00000000bdb16596dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc001000000f9f628ff01158fbf000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a68a000000", "prevouts": ["b65179000000000017a914f955a33e905fb6c7b7e694c8cef25993577deafb87", "68725e0000000000235b212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21581f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["26814cdf6b8010156c55e773cbb30eb356c9f94852cfb3d3454e0b3c12c52fe7e73c81b9d90ce86a4c7b3fab2d18d4a3c833fe4e9f0f47ab9f6ad8468b7663cd", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/106f9a1f4925d539eab0171af97bfe996099ad01 b/txscript/data/taproot-ref/106f9a1f4925d539eab0171af97bfe996099ad01 new file mode 100644 index 0000000000..35f6b5b8c0 --- /dev/null +++ b/txscript/data/taproot-ref/106f9a1f4925d539eab0171af97bfe996099ad01 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c330100000072fc8e80dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c83000000003e0d57f5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1d01000000594c5146046d9223010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79661010000", "prevouts": ["bb6c5900000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d", "aa9357000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "edbe740000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045da069eb8d814e8e6c846f6346fa512368611d0ddd5fc662af48af9436c51fa006032c3262f8d7c29daaf8f9846bf0ed9dbcc4a0f9aeeb7c8ab8b4ceb985f45a6c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936555a30cab9babe93a50caa7d6258c00dbdef6dc9d9a8b2d0ae40520e9152db0899aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb470901b40dea8c7a5ffa56ebe32dcbb2bdc70f6165f45007f6a309c26f1d76d473959a095ba405700a8bdcb88c47f737d45523ad768f5b3698c80add34f2e764b"]}}, diff --git a/txscript/data/taproot-ref/107e2cdcdfabb3aca2ab5aa2fd3c97288ca30c94 b/txscript/data/taproot-ref/107e2cdcdfabb3aca2ab5aa2fd3c97288ca30c94 new file mode 100644 index 0000000000..e6a4cd767a --- /dev/null +++ b/txscript/data/taproot-ref/107e2cdcdfabb3aca2ab5aa2fd3c97288ca30c94 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127014010000007885ab88bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3501000000d8098c37dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0800000000ce51b63e0198b6c300000000001600149d38710eb90e420b159c7a9263994c88e6810bc7bf71183c", "prevouts": ["2537120000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e", "5971770000000000215d1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "58b05a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "777d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936317c62222341529afe8f077c28135e4216d182041ddde4bb210fc7dce870fc693c7477a635aa10de5895d22b0b13d3a2307950c6447747564098b225c8ebc094ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457e2aee6c91b47bf7b7aff3c5d3800b2287c2f5852e09bca12781ffc191c1d4f04"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fafa584ded413e2880e88fe5cf9cb62118b35d382d99cebe394016833778f1470de2aee6c91b47bf7b7aff3c5d3800b2287c2f5852e09bca12781ffc191c1d4f04"]}}, diff --git a/txscript/data/taproot-ref/109b57979771e9a623eab0dbd365a6eb604e4d39 b/txscript/data/taproot-ref/109b57979771e9a623eab0dbd365a6eb604e4d39 new file mode 100644 index 0000000000..0f768930ac --- /dev/null +++ b/txscript/data/taproot-ref/109b57979771e9a623eab0dbd365a6eb604e4d39 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b08000000005eac31d2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5f00000000e9c12dda030e24a300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487c5010000", "prevouts": ["bb4c220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5a55830000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_38", "final": true, "success": {"scriptSig": "", "witness": ["318843384a5fd6307421fe114c473c43c927ce9a7e92c77cbd360837d2f3ce568afd9cf540777bf5b7a44f588aebc1fd32897f817bc396db13d556190e34d87981", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0edceeef26ec81812148b0a5c98897bc906ca52cb5da5f40f802de1d1f5cb9bcac8f269da3b88c9a56b9472733d3b2ca5646c3be46707330bb3a069ba4ccbb7238", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/10a884685231a301c2628f0607b449081b250ab5 b/txscript/data/taproot-ref/10a884685231a301c2628f0607b449081b250ab5 new file mode 100644 index 0000000000..d1305a389a --- /dev/null +++ b/txscript/data/taproot-ref/10a884685231a301c2628f0607b449081b250ab5 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700c000000003eac70b460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707f00000000d49919bd011e8c0700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac99020000", "prevouts": ["e78610000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7", "39a5100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype1to0_scriptpath", "final": true, "success": {"scriptSig": "", "witness": ["4825723baafebd7062b84c3074b58adf3e370d04d93a9cab253810e9c2d90b3c8e12793d4c452331bf9c3961cfbe7230c2fe2c591fdeb87458a1f185e0756f0001", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["4825723baafebd7062b84c3074b58adf3e370d04d93a9cab253810e9c2d90b3c8e12793d4c452331bf9c3961cfbe7230c2fe2c591fdeb87458a1f185e0756f00", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/10e147455c54d7bb8f4395e8f52666ee498a10a3 b/txscript/data/taproot-ref/10e147455c54d7bb8f4395e8f52666ee498a10a3 new file mode 100644 index 0000000000..0af3879521 --- /dev/null +++ b/txscript/data/taproot-ref/10e147455c54d7bb8f4395e8f52666ee498a10a3 @@ -0,0 +1 @@ +{"tx": "b5d5ba7e02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be900000000704da091dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b970100000044b31bb50347704b0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796a3010000", "prevouts": ["2c7d240000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "12a5280000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f84c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bb84f5f1451210ceb72432b3e6d63235af9ffb877329c35283c8b2d18797507891e44dcd1430a53a9228b1d4df01e5c5d5af3846f876ba8dd78ee7e669e7153a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}, "failure": {"scriptSig": "", "witness": ["4c52f8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f5ae99bcfb285d164f9370410e936aae64489acadcf2521c7c395e9f790ed55435701ef224ad20174d0190f97f9f6d3f23a41bbc27fc82fd96c9e1fc2f7b2cb81ef28805a30acff873fd9260c6b3bfee2b626467fb0ce04f716d513a8a4b08b6f288028cdab461d62f9273620b97315e6e9af9458f777a616c1bade2d3f6a89e"]}}, diff --git a/txscript/data/taproot-ref/10e2ba2a40c7f4b5bbe26a0ae7a814ef9883672e b/txscript/data/taproot-ref/10e2ba2a40c7f4b5bbe26a0ae7a814ef9883672e new file mode 100644 index 0000000000..c45e5dbb12 --- /dev/null +++ b/txscript/data/taproot-ref/10e2ba2a40c7f4b5bbe26a0ae7a814ef9883672e @@ -0,0 +1 @@ +{"tx": "2c58931d0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270220000000000450dd28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4010200000073486ed00336a552000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc44000000", "prevouts": ["63ed11000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "bbea420000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f4", "final": true, "success": {"scriptSig": "", "witness": ["c18996a50a9ede14356673d49ccc2fbaf76d0bb2740f796e6e0626b92728f0a6acba91321f22429f5166252b8ecdd37ebf5230ac334fffe2d27b205e38471db883", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f24b2db5f83e6a23473c07573e33803dd9ea06c07c971dd5d2949f3f18e48b3d139020e8677fb0b2c3ed9f2283489d6584e2e5a478534918409b6edaf64a344df4", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/10fefd7899096dc27cf05039ac9a172231d52173 b/txscript/data/taproot-ref/10fefd7899096dc27cf05039ac9a172231d52173 new file mode 100644 index 0000000000..4d4058831f --- /dev/null +++ b/txscript/data/taproot-ref/10fefd7899096dc27cf05039ac9a172231d52173 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c00020000002b7885eb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e50100000052310cfd02d0af62000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac12010000", "prevouts": ["b53f550000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247", "eed40f0000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d15d544d61c31b4fed0aeefc13ec08cc85209c6d5b38125e07f8d6b119aad417a9cc7cf8942e20871e843abc4d08f3260aa34782de145843bab753526013ba9d6000ff4712f1551ed36f1c3a3b6b2b237c7925585bb72d1991c7487de12aa2045f2292fc61c89b5afbed6a11237ad29f6db36f760dfecf42096516463315ad69079cae38d857203628e5a2bbc04266f26710157112a01495eba3346e4dca46eab56e48272ccb02bc5f30d335eea1fcd2ce2954c430ce26d0530bfbdfca8bea0066f7c58eb63705984a6916db34ad728d972bf125bd95938c8af9b5fabd6def1d8ab325b69740128eb3db07bd331f7d3cb448727709870987c37dd1f722dc9061745e4c806a33be348e794440fd3214fc5625237efade29e0df41582d5f717de1f0392fd754d6c44ea7aa742041ce538ea82b74ed172d374f7be3c97b212ec2e2a2efdf2e2ccbd2797caccda97a55be1113bf5ba63e96174064cefa2e162cbe7d427a7b04b910361b84159e0e2080ed07660e49a4adac55ec179557db0db7bbbc49a1ae4324f4e54905ced6895d3245bc90ca20f510f04d4553d24c2276adc93290d06fed4cd5f6ae28ee091b43848791fccbc29ccf1355625374adc3f39018e2520bee94d08d27418a60b2155d59446061e6d1a412e6346638bec392684228908903ee901845d34414c98436faafc0191f30c0e38a346b324bd79e30839b3e58c04c6a56f7ab065b0e75", "8d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa6c417b1d65e26db5cf9371b0ce7a9c3a110335bcae099de9d0155d4e514bb408a37683ca92a47492765ed69e840601310475c5f70013240e7a67747a5da918187472d664747fea006dedee35c74318028ad9a0ae37c154fe8226ccc2af402983"]}, "failure": {"scriptSig": "", "witness": ["4d09021008d23baf9c904d7e1664b68b2a7d53743b9f098060a028684222e1959810f5360f94181368887278c7a4f8fe66e11b90514e89ed7c586a382abe671ea4e34ca1f7f9e99472e21a7c2cbe1a304d3eb8f66c7130d96c1ce1690551d02563bd28745a187b35914b1f8ad6886f82cba13088c9a596c46a73a83f1e83aa46ccc16e55c186dac0864dee058e37a897f2b890de699dce56bf0238e584eea74960443880ca083c3d02267b814b267f1e6b39efd0b8f4ea719c9d8afff3be37b6ddc31b349a4e9c3eb6f4f82fef4a0a3e93c7e651c65545af17d888def481cd7dde9489fb1e12402f875b5bd463127d58478f9fea8722486a848df31352f808d67eb3b7b879757a0d73e7996a11623d6ba5f20509c743e039e5e8e269c4db86a817bf90790c1105f969dfb044b1b786e033e64ad98798295e4987559b40ee48f88aa3fdcf5150ea11c1ea98627a42d5a80f3c80cd832eb3eefae58019d1844c36af6fbd56983e1168fd397fa93be636ff78e14fc83cd6b8b77d03ab86d7761b901eac2f89bab527b678f6a22f62d5aa725ef28c3b5756ed2dff0e3d1d8e711c1d8aef312abd0c2a87322ce433ee160f966a86d5f49d43e492e8b8de32a3d86944df8ad654c9d2e75cbff386d53dd5417259a072c0452a0590841491a28ea2fbffbff6924bdef73ab12dff424ee121fdd885c317d64c13a76cc7c2d7e10c3107df7ad7f0a713454575834eacfb75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e80492d17ab4c59254bcdea8b81e7721fca5f8758b8cd0b322bd5a652bd9dfe7967472d664747fea006dedee35c74318028ad9a0ae37c154fe8226ccc2af402983"]}}, diff --git a/txscript/data/taproot-ref/1113b16ac0b3e4b76353eb896e7272061f03ff8c b/txscript/data/taproot-ref/1113b16ac0b3e4b76353eb896e7272061f03ff8c new file mode 100644 index 0000000000..d263ca3a1a --- /dev/null +++ b/txscript/data/taproot-ref/1113b16ac0b3e4b76353eb896e7272061f03ff8c @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1601000000ce4364e8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe400000000a9dbb2eb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46000000000b49550d804b90201010000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc60416b55", "prevouts": ["b6636600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "becd650000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029", "4eaa370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_27", "final": true, "success": {"scriptSig": "", "witness": ["77a42b33d07826192717f841bbb97d4a3aee00c2e26de594b231dd079f86cb7e7b37c49ff2c6e52df896e11bcb6e3559510c46e5c113f9b83d10d4df08ea67e502", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["e42c5ca8cdf8f2ebc0c45de9d8184c5d872850a6a0cc84e9fc6bbd851a651cf4e37e151424d736cf656b11151a72c82fad84c292047afb49f01677a137d334f627", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/1131434b4bb6f2acbd59abb881c239975a1116af b/txscript/data/taproot-ref/1131434b4bb6f2acbd59abb881c239975a1116af new file mode 100644 index 0000000000..4d01af4871 --- /dev/null +++ b/txscript/data/taproot-ref/1131434b4bb6f2acbd59abb881c239975a1116af @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca1010000002f81b9ab60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c9010000000f201065042881640000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8764000000", "prevouts": ["a46f5700000000002251207c84ae2d9063cc63412a30e00823aa01b05bc54bcf6d9936dc1c650bbdc9e98b", "d71a0f0000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb2ec5b5f80be5ffc851a24e9e2606734899b00ea08cfb8b544162f48ce08ae2064fb6de85916ce1333b57715a419fbbb7fd448155796c8af09a2e4a2bc14d947"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8531e2fd89fa5f39409e38f05906a9d1ca5d490c9939b0e896f59f0755d169eb2ec5b5f80be5ffc851a24e9e2606734899b00ea08cfb8b544162f48ce08ae2064fb6de85916ce1333b57715a419fbbb7fd448155796c8af09a2e4a2bc14d947"]}}, diff --git a/txscript/data/taproot-ref/117e130d533574c601aab37e70b93bae134a6527 b/txscript/data/taproot-ref/117e130d533574c601aab37e70b93bae134a6527 new file mode 100644 index 0000000000..4e7e796fb8 --- /dev/null +++ b/txscript/data/taproot-ref/117e130d533574c601aab37e70b93bae134a6527 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9b01000000744771be8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40100000000c8bd0fb801d2b675000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c37dd022", "prevouts": ["f61b7b000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "8dc2360000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "677d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688382350e48c4cf8321145c516ef78ca067967743c135ad2d056468d55d14eb52bba6f8d4f5daf96bc6060ee089cc6dcbd533ad30ddd55009697a11ce72a351d2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdbceae773fe677547a5f8be2986f5e4c7dc436c0d3f0e1e86711aa468c8778215"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cdc40148670f97d658d45aac2004072c8bcd1ff901e6e1bec20ff924a01653ad5ea7fd6123a97de30c69bfce8661bc08bde914a895a50530d51ffe984d9d20eafa195b9f6f39c732eb35859a6bf094cf148e251ed4d8a79570f47a225cba2c42"]}}, diff --git a/txscript/data/taproot-ref/1184f4a41ef45af98fbb77736bcca10e157c347c b/txscript/data/taproot-ref/1184f4a41ef45af98fbb77736bcca10e157c347c new file mode 100644 index 0000000000..9348b20f38 --- /dev/null +++ b/txscript/data/taproot-ref/1184f4a41ef45af98fbb77736bcca10e157c347c @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf280000000029e4a59edceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd60000000005371cd401525245000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48722d99d32", "prevouts": ["4f2071000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407", "990126000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6afc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dc78fa2606fd84cafa3e9f2d8805c3b820cb57841f4a0769a1e9f387ba6d96c239c06a64e39d88ea3d05132fdd32c8e90a6b90ff74e726fde2d8f99de3a7b89959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93669c989d0e3cd6f361274bcf4d5c8319fbc2250da7e1afff7d5a216e9b52c6b5ce96c6534a767436613e49f724d4ec24036cb4bdca8403821be2a67ec4c00c0e3731d32c4c28957ee8de75561afe63689e2428997edbca796d37c8feacf80dd0b4e0df2464f99a35d5bc9fbf69ae3045675e957332f77327dfd622124d00cb4df"]}}, diff --git a/txscript/data/taproot-ref/118b63929e90757c8ca1ec818ecf53f8b71c70fb b/txscript/data/taproot-ref/118b63929e90757c8ca1ec818ecf53f8b71c70fb new file mode 100644 index 0000000000..514932c227 --- /dev/null +++ b/txscript/data/taproot-ref/118b63929e90757c8ca1ec818ecf53f8b71c70fb @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41700000000818fa90adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0101000000f46e8321024948840000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e784621a3f", "prevouts": ["e47a390000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278", "b2b14d000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e15f20acab37c5a5cb044828a71c51f411f3799e0c9201344692cb6121a679af6a96525fdd0eb5f3c5c39bf5b04d78b37703e3d3b538b36e17fa0ddbdeb236a5daa4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa108807fd1da60fca18a375aa3fa2202a3eae5e0bf99a9374f58816bea445c879688f26c44e4c38ecd8996ded351dfac291f6a9fe2ce500158a378a1caa9ee2234a5a049dfcee5b69ebdb7c70e6242c675d1abc9cd58c84d7f9a8e8e1277a43a4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}}, diff --git a/txscript/data/taproot-ref/11b1f9db49bba588d8f418e89843ef901274fe93 b/txscript/data/taproot-ref/11b1f9db49bba588d8f418e89843ef901274fe93 new file mode 100644 index 0000000000..e4388e0a64 --- /dev/null +++ b/txscript/data/taproot-ref/11b1f9db49bba588d8f418e89843ef901274fe93 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702800000000800da0c18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b4000000004386efe703b659440000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1bd3c834", "prevouts": ["d1a1100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "46513600000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f7", "final": true, "success": {"scriptSig": "", "witness": ["e0f26ec8b7c33a1f3eb4d65181d089d5db4d2bda9d68ac0f17dc311aa5c956daf559749149d33519ec46e33695dce9a9766132a6e0dcb49d3966c6f0b0f6a82282"]}, "failure": {"scriptSig": "", "witness": ["597962e8961e4e72ba14b26e40d5d6c71d81563d7a041f081065262e729fa2db2ea36f6eb4c88882bdadb41f87129215cb9081fa2b807a209689ac7a5932b910f7"]}}, diff --git a/txscript/data/taproot-ref/11e26aa15592a14b6f7dc59ed4225b0ceeca2418 b/txscript/data/taproot-ref/11e26aa15592a14b6f7dc59ed4225b0ceeca2418 new file mode 100644 index 0000000000..bff3ac7f39 --- /dev/null +++ b/txscript/data/taproot-ref/11e26aa15592a14b6f7dc59ed4225b0ceeca2418 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705400000000d43674c0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0201000000aeba28e203296f2f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df97972236898731a52e29", "prevouts": ["cb58100000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "f13f2100000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e74c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e907011b224c3ef86d2f36e7d89b63e177b85cadcf6e2dbac0680b671e6366dad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b292a4f502e305109d81040f98432632ff806e9beae33e8faa7e022234476532106df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}, "failure": {"scriptSig": "", "witness": ["4c52e7", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a046b214117572ccd993880051dc23b22a6e41bbc520e5dd4f1b896f3a7710a73f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826cbd7cfc5d340306ce0f8e37fe1bfa8aba9fd4064e6187eeb928db0d0bdab726391a14412c925771c32fa4c7776d5872be2a56fee9c5a8de868e7e6e5a4c84da"]}}, diff --git a/txscript/data/taproot-ref/11ef5be6a614ca068f2c89bc602378f8ce71d763 b/txscript/data/taproot-ref/11ef5be6a614ca068f2c89bc602378f8ce71d763 new file mode 100644 index 0000000000..0d47ab71ce --- /dev/null +++ b/txscript/data/taproot-ref/11ef5be6a614ca068f2c89bc602378f8ce71d763 @@ -0,0 +1 @@ +{"tx": "7f7876df028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4830000000034c2a7f160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270da00000000bd4927c901e6090f0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb48a7a2d", "prevouts": ["7e07350000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb", "36b70f00000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f49738aff57e0a6b8995805d8d75c600ca2593a4bb41e712efc7b944ce86ac09656c167d78024cf9ac8ab753e035ddcfbd9ff3ce8d671a87b961f7dc5c285e19485290b5b24e8c4be158b28d7aa15f62440c20797f0ff9046b08dd5d16dde3f1e33f80b1056bdf2c24e0af1480ff60c2334c347ba12327dd1882336b0f4c053429fb79e32ecfbbf5bd1c1696eb5b1bcb10f531e388c1102ea723b9fbf0c99b20c2cc384f00694f2ca582ed6f519d67422787b3478b24421a6c0f267a915ffae17fcb29d5f40f8f366b918f03c7489cab980b6881ad92df9455e0b0b3b7134cc68c03c16e996ec63f484ec764477f627458d6ecb044b54bf51eec799b6c77c73f13ef126dc2f76fb12aea072623700f9e4c4acfc1ba88cd859a6adea32c0206345ce2bc3e2f6840b9682f8d28d6f6798b009b713b500f916d557bb00d0bad132f3c24c8cc2d69a4ced7956b8847e7224495190407a0a25d7dd56b175dbff8c05bdc1fd6a26ed7cd5fd0fa447ea059246968f013d778895114414babd34440d8bc5b07a91b47f59910240896b68e6976eb8879ca698c202197d7ccb29fb40602c1731dd97d43c9aed2b6aec38fafe90d690c8f656767ae40840ed35e6ffac5978ddf72d7546486a5c310c35d3ffed087d9795b44d20a84b8ac805f55945438a98a38a9550fda80bad11962c36fdea2b4c92fb7d155a866150210dd8ea50e5d3ad8c757bb6e242d7c541d75", "d47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facc94371513ed03fc9b5b146a2753e7b1ecbc6d9bbcb6df59d8f1ce2dd42b56b227fe8633af3ad90c30a4ff6253cd799a6a417bd03591c5308acef4cef6c60fd438c2fd1368e2cc97a2933efae2d13561032948a77b2cd5d87b5e0b8010cd9f32"]}, "failure": {"scriptSig": "", "witness": ["4d09023e40994aa88661520fa6e599727d1ab9e832bb0b282abd1124ea17548d548844dd0634b83b5c8c0db635ed35de4f8a83dec08f2d50958f7753e5c769656025d49febf8568d3d7733f172e292b4c9cce87312e2b499b97b8e1c483e0a54fbc8580f5579d12c2790eb2cb1e473e03812639f15bcf56c7befbcf7d064c31896dc7624e81d3e15d5a9b820e26272e6b9a4c878916877386a2c2b3038939053644ffff156945ea7b218ebfeaa10e232e794f7f5fe244287ac427142a748325bb069b1c5ba6aeb061e841fd02ff9ae34e35f14c6a681ec9350b40a7f255b5909d5f1bfa95e94005fe04206798223cc28b0904cd761ea42a2291e5ed447800161c48db345957c7ddd0bf5460837be67bdf4bcf24941097e599cc8da062dfcab3cf264e95748c71b390d2e473317b2cd6b3a1505419611bf4416e769fb19c2d8050c9f0bc2bc3d9620e861c2f1849b4a4eea4ba8bf9d2dd2b1f7cb1ec26c3f88046a9a3573881044695f06ab7e154e7184b9c4408f8f1d13190da516bb6a6bfb5f0e0275cdfbde8395b311a64112aedd23024e8106419d161efca56dbfdcd511c202341687438187bdc3561b6a845e09e329d9b14fb9f607b488b4faa0b40c56f7aed547dada4f0286692f3c41c13d3c6345e80287b5c56b5d2640d62e0abceedbb16304f22d7c5ab0c75961b177f1af3f91392e1f43fe9190085d9f4dffe6772a2d9317e41fcdfa139c662e8875", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369694bafde2e274b368d6d3b86a79da485f5d9deaac6205f36033c146f59aef9927fe8633af3ad90c30a4ff6253cd799a6a417bd03591c5308acef4cef6c60fd438c2fd1368e2cc97a2933efae2d13561032948a77b2cd5d87b5e0b8010cd9f32"]}}, diff --git a/txscript/data/taproot-ref/121e9e0d61998a2f829c791e9f23a065b8ce683d b/txscript/data/taproot-ref/121e9e0d61998a2f829c791e9f23a065b8ce683d new file mode 100644 index 0000000000..70294a0dfd --- /dev/null +++ b/txscript/data/taproot-ref/121e9e0d61998a2f829c791e9f23a065b8ce683d @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff8000000001375d4d460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f101000000e076448004e67f8600000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acb4030000", "prevouts": ["620f7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4e3c0f00000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_14", "final": true, "success": {"scriptSig": "", "witness": ["472efdcc4bcabdde7d5b4f147cd6bcc16505dd0aa41a77d4e90a49fdb8bf011aa2ec2b3576c822a55290d1e7e10e5e51c44f083844c5561f44ca3ed214581ab782"]}, "failure": {"scriptSig": "", "witness": ["ee16f338ced795c4bb32d7c6c443d28feb43c1533d667ed29d2e35200acc18ce1c507a11412a4707654ae549de36ad18f218626cf6de269ea510911bd0018e6114"]}}, diff --git a/txscript/data/taproot-ref/122e57288341172f17f63e1689fc9a205e9e5905 b/txscript/data/taproot-ref/122e57288341172f17f63e1689fc9a205e9e5905 new file mode 100644 index 0000000000..0c9c9bf972 --- /dev/null +++ b/txscript/data/taproot-ref/122e57288341172f17f63e1689fc9a205e9e5905 @@ -0,0 +1 @@ +{"tx": "db212fd101bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8f01000000d3e8b7d40278c269000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a665fff835", "prevouts": ["396a6b0000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a5119591238be1dbb96dac89a2a1f4200bdf9ca9ffe70af608a628a478a97cfd82e1f304fd5cbcea150151ab9467ed7486524704f6f52be5784e497cf75255948f2d3b38adb8d43e963794c7c849e38b96159d46161410258dff8455721475eda4a439cf7360b606ade423dedbcf68e000a449a5c29ca30f8214e663b5d8814555c4f61973560e1f9ca1364800e359bb1eb1bab74f0d94c9cb3357557af24515d54d1d44a4bfef2597e8260d3b7ea6caaeb30d79fdf50379e989ed159a35d661fa3c2033d1640b03e018857a4e8c9c17ef041f9d177edc87ed86b4bbe57513723ad8952b174a25cd1553e775e2ca21c74adfca8ea192ecef0f9a746e7faaaa2649138c9d9907b0f99f890a0610afc95b283692c4b843558a929b80072136c64b58b8e3576e409cc4398b453b1136ce9a90a80dbfb98b113fd3c22202ed94f701259742caf849a945675ebeecc125cb16f935ce68800a6ca2599208899d72d23829c6c0cb5c991d6500e86e8102378e6849f3f98e77a9d29415896cf2dcf894d9f6adb07406cf4856d17152d55bbea73ac6090dfbaef00f59de3b952aa625c133e7294acfb968b34e5fb795d6e3b979eee0b3a1ef3aa158cfda9b676686457ea4b75c3e7477666392d2f159c406fb7baad0fed77a59cbb6aa31d751ed1b75fd3e447e2fd066e986ae57b6ee84d6d67eddbceb1d5182d30e4a7cd131d9aa5176688a5395e5984c10f87a75", "597d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93640c4fde89207c6347043abb6407e1fad26c074a321948ed0af8764114916a85f613bea5824cd1812f2095288c03f032c5bbbfbbcd6a739f4744a40299340ab834be962498b383c32e8a84fa570ade752f3a2216469b10dbfd65078bd8e1b5998"]}, "failure": {"scriptSig": "", "witness": ["4d0902761724686fbb95927291d5f9a02b864b6c6593ee844395c7ba318c8b6d9d880156ab95e1a1a00d9238abfe4a8cb2bcdb1262d6dff2fcf789b8714ca19637a47eff2438b5d7e3dd42ea7785ef92052ee84b532dd19cd59beb11fc7ce95afaa108fc8844378309d8ec3850160b8065c05218aac6ae82f4279f64b45e9d5c2879874eb9e1c75ea61dada5dea106ccac88dd96afd7ff4376b128097e29b6104521914654eec1f73479ad069b1b99075a0a99c1d5bc06478500328bfa6841a6eb43909316e4dfa0628f5151fa33a9bebeddb31b3d2a1cbcfdc5618e4db77fe6b4cc3e155769e1579c1679b3b8b059999769f6e3c89bfe76968b9ad46f90e4a9921bb2363c027b324f1b1b65d2341a718e791c7917c253d4530e8aeabc3f35409b4d5678170e79d373b80a28b7246bc14c4f89004116298f5e61530ed617728d80d96ec01a7f5fb066bb7fccb516922b255cb8079856c8b5aaadc6351361a7a436ed4d350b961c66647fd37582ee5608aa7108f5b3d4b0420cfe663e262066818e7787de72dfaba5f710db7717e07691be14e835eb8b6b398d06077f2ee8b77ee994f955d67cfc8a2a8fe5c907730eeed4f898442d39c49aa4bc1e40979d22a3bffd0d6ec7af5e74f0e0c695665c12151623f8b2adad509b4bb91bfd101526905c8e506f38a03eb28fdb2f9b1770e7ce1972571f7eb4a4817890c35c48d1126b47bb342361804f5917c5d27875", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b93df312d52b8f2dd4a25d0e8ed5a68dc4d03b1b80fcd966f75d6d56b0f35fc7d0160c53d01d80ab4be204ae4e021ad6f56ad3990ac4b37baa4678d530d3ba4ecd61c62feef9509bc7b3762bc81079411fa6867ea4986820580c60fa1e8298e9"]}}, diff --git a/txscript/data/taproot-ref/1260bed4953f82e80f379c79bc4484db28c58d8a b/txscript/data/taproot-ref/1260bed4953f82e80f379c79bc4484db28c58d8a new file mode 100644 index 0000000000..5b1effd2dc --- /dev/null +++ b/txscript/data/taproot-ref/1260bed4953f82e80f379c79bc4484db28c58d8a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6f00000000469d4db760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ca010000008269a1ba0146b74100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5d010000", "prevouts": ["31f95a000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "7c1d0e0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063eb68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045c5036d5496e9f4f5147754f04cc929214b621a1df3bcbd671a812d74f0d7877d399891b33f3277cd8a2b8473e2e6079de1e6f51840c7864da48d9f2287dbe494cf9ce2244c675144b577c27c052f9ebd481172245e28e9502c6c6e8f12c64fa6"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f8e29bc07f5e449d4f156ba38c490a95b3b86c2d169e953b485a0043ccbd92b2c5036d5496e9f4f5147754f04cc929214b621a1df3bcbd671a812d74f0d7877d399891b33f3277cd8a2b8473e2e6079de1e6f51840c7864da48d9f2287dbe494cf9ce2244c675144b577c27c052f9ebd481172245e28e9502c6c6e8f12c64fa6"]}}, diff --git a/txscript/data/taproot-ref/126e5c88c57ce073bc1e63e4306d21823db4b99a b/txscript/data/taproot-ref/126e5c88c57ce073bc1e63e4306d21823db4b99a new file mode 100644 index 0000000000..231b157283 --- /dev/null +++ b/txscript/data/taproot-ref/126e5c88c57ce073bc1e63e4306d21823db4b99a @@ -0,0 +1 @@ +{"tx": "23fdaf0a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b660000000016a519fbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3a00000000879540b203c8c28f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df9797223689877e1bf628", "prevouts": ["a61d230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "95886f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_86", "final": true, "success": {"scriptSig": "", "witness": ["28e62fc2ee5d4d1c39dc02111f43286367debb2554174bfd295225e9c3e08a4ec3623d598784eb10b211e396e5f04b1a9903b6ce2185645362e1af4671d0be1583", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7e87ed8e897adef2508c81f8ca58d8f76435c1e213a052aeb6b1a81f403f49b99c27c41cfaa65b658a0432946c13cda274c0d0cceb793dd7a398116acd02e49586", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/12bcaf48556b4780abcb73c4f32bd274ea7861bb b/txscript/data/taproot-ref/12bcaf48556b4780abcb73c4f32bd274ea7861bb new file mode 100644 index 0000000000..39b891d115 --- /dev/null +++ b/txscript/data/taproot-ref/12bcaf48556b4780abcb73c4f32bd274ea7861bb @@ -0,0 +1 @@ +{"tx": "a77294ea028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ae0000000081d69fbb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a501000000e28dd3c903cee874000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961f030000", "prevouts": ["b5783700000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "506d3f0000000000225120fd767bc2bb07e4ca9357cd933b3dc41f590c00db442e0ea12a871bb96cd7e63e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["0eee1782b97d831fe5b635a1d15fba66455951c9e7db31fa98c9a13621beacba406ba378d6d72b358340d9691f1b28696a0ae33905c482e473c4b1aaf6c6ea06", "ce474e327dba7b16a19e7f022304063ae63fed1e6fefcbf342ebb202d69441094ef7adf62c1e8e206792e6f2d75db8e4a5e27795fe78e1a6bbfc8f1fc54b52e45a93787a4293df74d65e962b279ec3b8281f4e3b5da43f78bd71d08c57d231cd7e7311be70d7f92036117575b8b34b8fb4aab7c36590ea9614cf3747ca2857ac3167ea725e92eea21ca8c0027522ceb76a40b877f027b9", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ce99e795792a3b123372692f0c3a2a4c93a6e7d2ec701c9eb9ecdbc27fb0b173956ce300fd1e9317d4788f7559d429e7197ed501cac5b77a30e2e44415254b09724fef99a662e9e1211e563429ab274b90431e7afb6bd5e6bc1fc2f69ae8c56eaac2348dc1bc3cc94ec8cf7de9027247edb1bc76738ded447663208a650b6368000000000000000000000000000000000000000000000000000000000000000070c7c5c179be9d813c0cf052f58ede075dd69e9389addace305677f5b30b36513d6d2aa7d7ef2bac0796a7f067802cc09013c9938e1092ff0cff91b377243fbd10b4abd4c7bc52f818dfae0a3b844a8169fc36593cb4fcd8517ef1dc3172b6a5ddcc86569d849eb34dda562dde11802e394bfc7a773028432e86ce627b92820281a83512c0859f3be040e42fb163f3e39752589ee9236f7fe48d580e8d192204efecc98d6ac5fe619cd8ad0cbe0fc4dc0e56bbc9f1ae493e2910f90cfe3f8d98c0ad375b221c85e52d567a24f734560dd280e896030e1b12e2400dc1fee7915e8ed1d36077cda215168c9d84d4c8153e60def32a01852c2c26735e2dd6f3bf0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000adff78ea746c92e4190d0870f7ebd1ce03f586d4871d15117601f3e4ffd74e3f0000000000000000000000000000000000000000000000000000000000000000c73e27c47df88642197488deecd32c4116ec1c1d8f7f333dbfd9c2669a73986156cc523ac66dbc0b610fc7bcef654b2627e947586d674f84449c8f337d5ee34ec0c43b4d2f4ecdf09f2d97bff72819c23fa178f90987fe0676fb36370e93c8f2b09b5e3ac0ac3ea7e49f1a022bda0c0d6baafa3ce41cb6a8b1b060d6fccc723934f5021c5ec5c2dfa5528ffc937480d61e05927f2e2520ee5ca048e551cfda9579584991385068c9da37431443a24de399dc09d0d76e537682de413315c926d246c5023730ea0c4860c7fd0014d26a2a4ed97903e64a01c4f630caf802221c5cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea796666a94a0c67f21efdd73ba3292e39c52318c76f9b210f748a7ed00446b1ad7e67a428810fd1e33ed1839251e4aab947571ee6f49aa48e2a150e16ebbf6d0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff67d462f37a9d770a4f8ead434365d5046e2ebb8297f0e853bb3bb0beb201cb0e0000000000000000000000000000000000000000000000000000000000000000decda19431cc4754921f93ac4190ac4ee76e9e4de08e021654cef7b7cce8daf2194f1fc6826df2785bea12215cfa124ed99c3d934ad9a4b7d77d8cf7bbf940cbea4d65835e1293eb408359245301ef20afbd6a540f0b0920173d6e05e146359affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20ded9e62f73615653886d425b45e946d4462aa27e02a509d5c5386b0847b555ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3613c27ce8e2c5209a8d43492d3af6271b81ad026e26a522c8ec55518cf8687240ae14aaec29caac32227e58bcab2d1598fa149b910a9cd0a488190cb981085bb8391a784c88eac8b12b46312a4f74f8c3ceb9e8b881c6aacb015bde35d07c8d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fe8da1f9d88e3062da0007ac52479c42f9a5b81ee1f2fd810d585d00cf6556ef38749dc81a5ff71c3c675c9caa96943d99af744bc309f76bd49a9cee4995b8f02e65eb31a4a70aae63ccbd0f7b7f8d6a912f87fcf44e5ad58c9f9589edc62ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffba18c4c3a42e636a8443264b2e6e8eab468027391f7c4b9e7814f828d2391fecf1b384450b1ee2de452b1834a32af2090cef8402a93122d7f1b093456d6ff73a1ad4cbdfe487f1c681c3fb37cbd28c5d811bb5ced4213cdb2e14cfe902a2e7800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5d4b29dee92766f94f831433289b3ef66829d09ba2abe29cd9a06ec326bbfa7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02ee16e1355c0cf7be210e658ce6ebd74ea4af503edae2f334b59c65a762af46797cf1ddedf299ee15e627789c8dc1c08423ed2b98ff96415c83a376c871549c93bafc7946aed19c633190ed64207ac84d8e29bc97db4f5d723f15cd6e45186bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff57d7ae1df51adb96c454d716899a926b68d13c9968645cc89d3cb5f86cb7ad0f42b60ac760679b729b7d4b807b11893438bb59579294c12a8dc02797d45a86e3669345e25ad0e64f6155549f56506e4cc950539005f9f87d1c54cf5858b7288eb00ef26aa80f15e9be38c53671b5884efe77fb24e73815fb48dc37aca10e832edbbb914d4e8641c5c7026c2d11a50a72fe5431742d7a3c08cdcc47856b2757d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff089d41b55aed0337173ee62811a8094c029970d0623ac4ed1e8153a4606a47b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17e1bb55ab6f71c880fccb048eacb4d10a8cc3d4b56471a43dd63f692c3ed4f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff881c26ae3d6c9437c747bdfc8b1384db985615fba23944a17c5f1c09d1bbbf2bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd215a4d83cae44eb84014910ddc131b8a9a891f567d5930a222ed5e2d147ae23b841e46bcb54bdfac481b6520812fa0fbefe5f0ba840599d459e472faafaa792dfbc529aaaa39fa38c21ffd97070982f76989e44b1fe6ba3ebc515e22769fe6e740e3e0bc9e28d77576468dc11ac305ba8bcc3fea44f9ac8926b8095a1b35c400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8dd6f353ed25b9760df5d18dfabde5abc637fbdf4b4fbc8f271e941c2111fec5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff024345a9a2629ffa5c80af68be2abe39baa7565e3101dc49714683273bf926cf0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7239678bdab2834bc126c9af902186f0e1beeeeb1b13c60bfa4c0ce8245e7321b8b07ab64ae13c1f260f34217a5ab4d79e56b6b01cf58746b43fa9b756e64b8c000000000000000000000000000000000000000000000000000000000000000037af4931d2296edff9601a2574d241f9a94a0211e878244c322743f1cbef996432c4641166bdf22da19cb0a5f3c90108b3a825bb829d765c4647706a0215e3ec0000000000000000000000000000000000000000000000000000000000000000624dd1a53cd497e05917360cd8d4944ea710ee7ceb01c82f93be995f0c987354ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99860e967739a24f87874bed00b417705d9da1c1609106d5c8ce02eea1c0e5625c230f2a4335148a105219d3a1945b3b4e00df0452882ef5100bf23f22ebd5a40b6185328e20211949fe04cdeeede68f0c4d45644a13cdb74cf2444d0be0f5e0bead34447df0fb6000892f14786ce165149060ca0648385bbedcf24b398c6148f8314fa195f351df9e4f10dbb0d36560f3e37896f00dc6ae4995b4456de943ed00000000000000000000000000000000000000000000000000000000000000008ad7f587d130728e281e6557dc582636c00bd0f410b4db21930e82d84617c0e1745226160b9794b3d0ee89d473050505ea3a87e59d8cfe3609beeaaf85747b396de35437058f4dda156063a419fca8b483b352b8816a9eb40fbcaa5d4e5b4a0bcafeae664288c1883780d2eb572e811b3948af113aa57e256e0b645e2643348a209e3471a8178ef49be358ba1a1b821a696d354e8019437766cdb980d8a577bbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008424e83a7bce5e70a44f2dc898fa43c2fb1b1f65ed16dfcc1047c83c5e4d856a145ea7b13e44b74135c6d7a0612617c38da6647d97f7e6c74be49ccd9fac8976918ba41213fb71b7844b1b6669ac9d2553545279c18ba96d1f161295c3dfe580b13665b2d82f719efce463a0dd962d16995092329b8065c7948b3ed93df1a2bde63e6804c4a650fa562053414457f5e53dd60051e198a0612b24997f8ba9241a60100ffb7196defe5eb222672be5d06a0a24a9ee6b3e0d68b6d9b57e2cf4bf7d6d10c2901d0948927be1b43cbb38ce0e2e75a59c484e6a051bb4d06cc350d9a7df24c911b0c686b13da4842e3f1791c591e6e7c5d495c106ab721c1eb10df6fa983cb7e31745de028fadef0320dc751c0b07bec602f522cff0b9737a536fefeff7d8b5e85792031ad2a46f9efbd5838ffc3330a511f129987b211bd6f48ea186"]}, "failure": {"scriptSig": "", "witness": ["0eee1782b97d831fe5b635a1d15fba66455951c9e7db31fa98c9a13621beacba406ba378d6d72b358340d9691f1b28696a0ae33905c482e473c4b1aaf6c6ea06", "063f8403c9a8ee48c87b859e858579b6c39196751715df2fd4594b214d28918766fa70ec1fc897502f41ce11673996aab1105ecdd3baff21871dbb807e140759099f15a3ec7e37999fa31fcd7ad12a14d4b09e141e51ef66775529dbbe1d7494d01e48ec3a9eb57e7228479c787f99c396afb3f87b95b23f0ae2633b2d88e83a4cf588d6ce6299773e351c05d19d605ab16b9fea15c9", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ce99e795792a3b123372692f0c3a2a4c93a6e7d2ec701c9eb9ecdbc27fb0b173956ce300fd1e9317d4788f7559d429e7197ed501cac5b77a30e2e44415254b09724fef99a662e9e1211e563429ab274b90431e7afb6bd5e6bc1fc2f69ae8c56eaac2348dc1bc3cc94ec8cf7de9027247edb1bc76738ded447663208a650b6368000000000000000000000000000000000000000000000000000000000000000070c7c5c179be9d813c0cf052f58ede075dd69e9389addace305677f5b30b36513d6d2aa7d7ef2bac0796a7f067802cc09013c9938e1092ff0cff91b377243fbd10b4abd4c7bc52f818dfae0a3b844a8169fc36593cb4fcd8517ef1dc3172b6a5ddcc86569d849eb34dda562dde11802e394bfc7a773028432e86ce627b92820281a83512c0859f3be040e42fb163f3e39752589ee9236f7fe48d580e8d192204efecc98d6ac5fe619cd8ad0cbe0fc4dc0e56bbc9f1ae493e2910f90cfe3f8d98c0ad375b221c85e52d567a24f734560dd280e896030e1b12e2400dc1fee7915e8ed1d36077cda215168c9d84d4c8153e60def32a01852c2c26735e2dd6f3bf0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000adff78ea746c92e4190d0870f7ebd1ce03f586d4871d15117601f3e4ffd74e3f0000000000000000000000000000000000000000000000000000000000000000c73e27c47df88642197488deecd32c4116ec1c1d8f7f333dbfd9c2669a73986156cc523ac66dbc0b610fc7bcef654b2627e947586d674f84449c8f337d5ee34ec0c43b4d2f4ecdf09f2d97bff72819c23fa178f90987fe0676fb36370e93c8f2b09b5e3ac0ac3ea7e49f1a022bda0c0d6baafa3ce41cb6a8b1b060d6fccc723934f5021c5ec5c2dfa5528ffc937480d61e05927f2e2520ee5ca048e551cfda9579584991385068c9da37431443a24de399dc09d0d76e537682de413315c926d246c5023730ea0c4860c7fd0014d26a2a4ed97903e64a01c4f630caf802221c5cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea796666a94a0c67f21efdd73ba3292e39c52318c76f9b210f748a7ed00446b1ad7e67a428810fd1e33ed1839251e4aab947571ee6f49aa48e2a150e16ebbf6d0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff67d462f37a9d770a4f8ead434365d5046e2ebb8297f0e853bb3bb0beb201cb0e0000000000000000000000000000000000000000000000000000000000000000decda19431cc4754921f93ac4190ac4ee76e9e4de08e021654cef7b7cce8daf2194f1fc6826df2785bea12215cfa124ed99c3d934ad9a4b7d77d8cf7bbf940cbea4d65835e1293eb408359245301ef20afbd6a540f0b0920173d6e05e146359affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20ded9e62f73615653886d425b45e946d4462aa27e02a509d5c5386b0847b555ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3613c27ce8e2c5209a8d43492d3af6271b81ad026e26a522c8ec55518cf8687240ae14aaec29caac32227e58bcab2d1598fa149b910a9cd0a488190cb981085bb8391a784c88eac8b12b46312a4f74f8c3ceb9e8b881c6aacb015bde35d07c8d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fe8da1f9d88e3062da0007ac52479c42f9a5b81ee1f2fd810d585d00cf6556ef38749dc81a5ff71c3c675c9caa96943d99af744bc309f76bd49a9cee4995b8f02e65eb31a4a70aae63ccbd0f7b7f8d6a912f87fcf44e5ad58c9f9589edc62ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffba18c4c3a42e636a8443264b2e6e8eab468027391f7c4b9e7814f828d2391fecf1b384450b1ee2de452b1834a32af2090cef8402a93122d7f1b093456d6ff73a1ad4cbdfe487f1c681c3fb37cbd28c5d811bb5ced4213cdb2e14cfe902a2e7800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5d4b29dee92766f94f831433289b3ef66829d09ba2abe29cd9a06ec326bbfa7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff02ee16e1355c0cf7be210e658ce6ebd74ea4af503edae2f334b59c65a762af46797cf1ddedf299ee15e627789c8dc1c08423ed2b98ff96415c83a376c871549c93bafc7946aed19c633190ed64207ac84d8e29bc97db4f5d723f15cd6e45186bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff57d7ae1df51adb96c454d716899a926b68d13c9968645cc89d3cb5f86cb7ad0f42b60ac760679b729b7d4b807b11893438bb59579294c12a8dc02797d45a86e3669345e25ad0e64f6155549f56506e4cc950539005f9f87d1c54cf5858b7288eb00ef26aa80f15e9be38c53671b5884efe77fb24e73815fb48dc37aca10e832edbbb914d4e8641c5c7026c2d11a50a72fe5431742d7a3c08cdcc47856b2757d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff089d41b55aed0337173ee62811a8094c029970d0623ac4ed1e8153a4606a47b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff17e1bb55ab6f71c880fccb048eacb4d10a8cc3d4b56471a43dd63f692c3ed4f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff881c26ae3d6c9437c747bdfc8b1384db985615fba23944a17c5f1c09d1bbbf2bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd215a4d83cae44eb84014910ddc131b8a9a891f567d5930a222ed5e2d147ae23b841e46bcb54bdfac481b6520812fa0fbefe5f0ba840599d459e472faafaa792dfbc529aaaa39fa38c21ffd97070982f76989e44b1fe6ba3ebc515e22769fe6e740e3e0bc9e28d77576468dc11ac305ba8bcc3fea44f9ac8926b8095a1b35c400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8dd6f353ed25b9760df5d18dfabde5abc637fbdf4b4fbc8f271e941c2111fec5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff024345a9a2629ffa5c80af68be2abe39baa7565e3101dc49714683273bf926cf0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7239678bdab2834bc126c9af902186f0e1beeeeb1b13c60bfa4c0ce8245e7321b8b07ab64ae13c1f260f34217a5ab4d79e56b6b01cf58746b43fa9b756e64b8c000000000000000000000000000000000000000000000000000000000000000037af4931d2296edff9601a2574d241f9a94a0211e878244c322743f1cbef996432c4641166bdf22da19cb0a5f3c90108b3a825bb829d765c4647706a0215e3ec0000000000000000000000000000000000000000000000000000000000000000624dd1a53cd497e05917360cd8d4944ea710ee7ceb01c82f93be995f0c987354ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99860e967739a24f87874bed00b417705d9da1c1609106d5c8ce02eea1c0e5625c230f2a4335148a105219d3a1945b3b4e00df0452882ef5100bf23f22ebd5a40b6185328e20211949fe04cdeeede68f0c4d45644a13cdb74cf2444d0be0f5e0bead34447df0fb6000892f14786ce165149060ca0648385bbedcf24b398c6148f8314fa195f351df9e4f10dbb0d36560f3e37896f00dc6ae4995b4456de943ed00000000000000000000000000000000000000000000000000000000000000008ad7f587d130728e281e6557dc582636c00bd0f410b4db21930e82d84617c0e1745226160b9794b3d0ee89d473050505ea3a87e59d8cfe3609beeaaf85747b396de35437058f4dda156063a419fca8b483b352b8816a9eb40fbcaa5d4e5b4a0bcafeae664288c1883780d2eb572e811b3948af113aa57e256e0b645e2643348a209e3471a8178ef49be358ba1a1b821a696d354e8019437766cdb980d8a577bbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008424e83a7bce5e70a44f2dc898fa43c2fb1b1f65ed16dfcc1047c83c5e4d856a145ea7b13e44b74135c6d7a0612617c38da6647d97f7e6c74be49ccd9fac8976918ba41213fb71b7844b1b6669ac9d2553545279c18ba96d1f161295c3dfe580b13665b2d82f719efce463a0dd962d16995092329b8065c7948b3ed93df1a2bde63e6804c4a650fa562053414457f5e53dd60051e198a0612b24997f8ba9241a60100ffb7196defe5eb222672be5d06a0a24a9ee6b3e0d68b6d9b57e2cf4bf7d6d10c2901d0948927be1b43cbb38ce0e2e75a59c484e6a051bb4d06cc350d9a7df24c911b0c686b13da4842e3f1791c591e6e7c5d495c106ab721c1eb10df6fa983cb7e31745de028fadef0320dc751c0b07bec602f522cff0b9737a536fefeff7d8b5e85792031ad2a46f9efbd5838ffc3330a511f129987b211bd6f48ea186"]}}, diff --git a/txscript/data/taproot-ref/12e033c1a8f3298a775b13078a77bc8befe4567c b/txscript/data/taproot-ref/12e033c1a8f3298a775b13078a77bc8befe4567c new file mode 100644 index 0000000000..0b54fc4f66 --- /dev/null +++ b/txscript/data/taproot-ref/12e033c1a8f3298a775b13078a77bc8befe4567c @@ -0,0 +1 @@ +{"tx": "57cf5f4502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf6010000006a9486e760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702d0100000035f118d4039b315b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac7d735b5b", "prevouts": ["8eae4b0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "768f11000000000017a914b403773244c403f76163005c780d53872622b52c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1659142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["cb500f865cff9b4b2ebc3aa367a9c52d5827d857d852a907cc04180190a0d79e91125f2fc2eca2ab8f50e4b956da9be68cdf7040582f103d0ac8e9fdc10423c1", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/12e5f4d526a722bc9b8f2af83ae028c8ee6b9027 b/txscript/data/taproot-ref/12e5f4d526a722bc9b8f2af83ae028c8ee6b9027 new file mode 100644 index 0000000000..f8d73c4a94 --- /dev/null +++ b/txscript/data/taproot-ref/12e5f4d526a722bc9b8f2af83ae028c8ee6b9027 @@ -0,0 +1 @@ +{"tx": "8ab8cf8c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be401000000e633f1b18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b800000000e45ce987016a015900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac56b72021", "prevouts": ["64751e000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e", "23a9400000000000225120c1102a8f1f1acb509ea40275c13487a0c613f8d79621443165b53e6eaf1338d7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["8e4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb46e8601d3af4b3a958df52448c90f2764dee9285ef639d0a94e9c0ff98d78680d8d550033184c6424688af85d43f5bf525b7f6d8111e731f6e2359cae2801b117ed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e0ce34fb0c991ad9d4eca1e4cfc93a976f01940b6dde3760a5561afff4e34d676e8601d3af4b3a958df52448c90f2764dee9285ef639d0a94e9c0ff98d78680d8d550033184c6424688af85d43f5bf525b7f6d8111e731f6e2359cae2801b117ed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}}, diff --git a/txscript/data/taproot-ref/12fada550b4d90c67f307a0d563ae38283c008fa b/txscript/data/taproot-ref/12fada550b4d90c67f307a0d563ae38283c008fa new file mode 100644 index 0000000000..b786902562 --- /dev/null +++ b/txscript/data/taproot-ref/12fada550b4d90c67f307a0d563ae38283c008fa @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf610000000058cecab6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c12020000005cf0669103c7c9af000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e736847739", "prevouts": ["b31f680000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "09424900000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "627d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e1c3079426a5b5f1fe415ca1dc9a375fc9bf135fffa940368a3174df14ecf01db815577f72abc2219d93608f0bf386debaad95a87d0f429ecb808b0f22f69367f"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364044acc6a70fa5b9cf91df37d1a559deb3c0d78b0a462f26dc9347473fa4c4821c3079426a5b5f1fe415ca1dc9a375fc9bf135fffa940368a3174df14ecf01db815577f72abc2219d93608f0bf386debaad95a87d0f429ecb808b0f22f69367f"]}}, diff --git a/txscript/data/taproot-ref/13080e256b05f38789902f0dbbc437401d15a3f2 b/txscript/data/taproot-ref/13080e256b05f38789902f0dbbc437401d15a3f2 new file mode 100644 index 0000000000..85c78d6751 --- /dev/null +++ b/txscript/data/taproot-ref/13080e256b05f38789902f0dbbc437401d15a3f2 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf29000000001bb3f48cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff001000000b58b7f9404b14deb000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aced020000", "prevouts": ["68347b0000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "aedc7200000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac9", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663fad082b3d4bc896bd1c7eabf214d4027c747e30ed7127fc38c25827593872689fc6d70c1c4e15dab7d2fdd5db26cf688ca78f103ab970182d2c6706fc8281bcc9238bf2d7dc0bcf11838c34785251ea2fa5f3bb034bc98e2e8efb0909b7dbc17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e10b2b16248e513241b83875342c0ccd59e2b6d40dffb5019b56610da5b5de422d74e6cd8e612cb42cda5f7f42dc10fbfe42e4e0a9faed92158fa7e41e5f92051e17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}}, diff --git a/txscript/data/taproot-ref/1318e44a20cde77432578f5126e255855a0f8104 b/txscript/data/taproot-ref/1318e44a20cde77432578f5126e255855a0f8104 new file mode 100644 index 0000000000..2f1f78b2c3 --- /dev/null +++ b/txscript/data/taproot-ref/1318e44a20cde77432578f5126e255855a0f8104 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e9010000001dec1589bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf260000000053ee53c504472cad00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac11ed5824", "prevouts": ["65a33900000000002251202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "ee537600000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "a87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8159738ff2c4f90cd16c07bb852218b8a19eccf086ed61d505eed94e2770983c2cd165f299bdaaa06ccf8947d9b12e815a5b39fc50068532880492a3446c423d89e26d26d9f798657ab1642d8194f1f5dc9158412142f65824f82701f20125ac7"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360696a8ad49f6bde3bd1da86a2495044ebc8bdff93c87d1dc4e64279442168fbe337e31cedb20dd0ec36f43f7131008eded9387a241f89ca892d220549655a6e95def3d75afa0626f5ab572f3c9ae49b6567bf85ec43d0b3933062a3ad8b1e492"]}}, diff --git a/txscript/data/taproot-ref/131ec09b5ca700e6a035eb50138f6a7f62fe3f91 b/txscript/data/taproot-ref/131ec09b5ca700e6a035eb50138f6a7f62fe3f91 new file mode 100644 index 0000000000..0052738dff --- /dev/null +++ b/txscript/data/taproot-ref/131ec09b5ca700e6a035eb50138f6a7f62fe3f91 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc101000000c198db84bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcb0000000017fde2f5039f7f8c00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8716010000", "prevouts": ["56ff250000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "2f89680000000000165a142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["22fd611b311bceb680b02d3c506b7a6490d3073e0978b21351e00df8c57b607f8ce0221a5601fa732041c9a4b1b47ca62499157edd71151ba4088699092959b6"]}}, diff --git a/txscript/data/taproot-ref/1337852e30e2d514c14e8123b84fadb9d4aa882f b/txscript/data/taproot-ref/1337852e30e2d514c14e8123b84fadb9d4aa882f new file mode 100644 index 0000000000..053bef4cb7 --- /dev/null +++ b/txscript/data/taproot-ref/1337852e30e2d514c14e8123b84fadb9d4aa882f @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bba01000000a2f78b97dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b82000000003a48009dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5301000000e7fb77e004cb3fcd00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7f2000000", "prevouts": ["d4b42600000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "69c2270000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "926981000000000017a914971b3e5f9ac480bdcebf6ea71a9fc7de0ab164e287"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e7", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93668ce749c68de633516e195736934f8a88269848cb24cae075fce4521e857a6cdd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c61a1ab416979399a3dea56cc9db65331fc4d8e9e627e6b90ed3a4ebdc2f66c36df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936feb3983b18e4525f0a8518cd3710c3b144f3f0d5edea574e13e05d297dfd94906cbd7cfc5d340306ce0f8e37fe1bfa8aba9fd4064e6187eeb928db0d0bdab726391a14412c925771c32fa4c7776d5872be2a56fee9c5a8de868e7e6e5a4c84da"]}}, diff --git a/txscript/data/taproot-ref/136bc03e80bca2dc5f71c4fdf91e7d690eac78e2 b/txscript/data/taproot-ref/136bc03e80bca2dc5f71c4fdf91e7d690eac78e2 new file mode 100644 index 0000000000..f75db0e5fc --- /dev/null +++ b/txscript/data/taproot-ref/136bc03e80bca2dc5f71c4fdf91e7d690eac78e2 @@ -0,0 +1 @@ +{"tx": "02000000031980a99ad1eac101c8fe3dd9b7c19f4e81dda5a690601a9eedc2ce713d9132e5000000000007acc88a492909e056fa5c0ef2af542be68aba07da39583e95b43e24484150891b1d532301000000001ad6d4dc1980a99ad1eac101c8fe3dd9b7c19f4e81dda5a690601a9eedc2ce713d9132e5010000000079e1bbdd02ac0b058b320000001600146d764276c66fec1127e5074db5bff3aa6c52553358020000000000001976a9147d8c30278dcbf5bd88310a3c91abbeb33651906c88acd137773e", "prevouts": ["7371c1150f000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "b7e4d4f711000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "6689717d11000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid", "success": {"scriptSig": "", "witness": ["0e0f08267df2ceaffdfeb1cade96dcfe41721caf22f0bb89fad8d7f363b2e9a52928486dd44f7b980ec67683caf4fb4e836db5f68fc7414f46fb53169174b4c2", "20159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717ac", "c0159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717a00074c7e8df7fd91f9df9f350398e675f9ead7758f02aef75359e3279a8e0e7"]}}, diff --git a/txscript/data/taproot-ref/1390c111cc1ca46caab6bdee16d74dd49519fb4f b/txscript/data/taproot-ref/1390c111cc1ca46caab6bdee16d74dd49519fb4f new file mode 100644 index 0000000000..8607105458 --- /dev/null +++ b/txscript/data/taproot-ref/1390c111cc1ca46caab6bdee16d74dd49519fb4f @@ -0,0 +1 @@ +{"tx": "db5803d80260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e101000000d732cef260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d301000000446240800499271f000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac2c32be27", "prevouts": ["b1ce1000000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "4fef0f0000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45e04c998862288954a26ee7ce146837a88020619bd4ef6b5d2b0b49b83f7fafffc7f9c78871d6a598c7c7c3f4c8210a5c47caa8abf9700608b6e75845c74a6c5"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea2949503db9bf5110d001b5fe31844dc42c6d6df34bdb7dd462bab705d6d86ea58b6826c45b958e6a43801c4f9a11218097d5d18de4cdf93890daaefc8ad62d7d143406647e47f2aa45aee5a8d37fbb079fe3a633dc3f79123da3b3ed47a821a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}}, diff --git a/txscript/data/taproot-ref/1395575564b7da66e3b458131eaed79bc605b605 b/txscript/data/taproot-ref/1395575564b7da66e3b458131eaed79bc605b605 new file mode 100644 index 0000000000..2eb50cd182 --- /dev/null +++ b/txscript/data/taproot-ref/1395575564b7da66e3b458131eaed79bc605b605 @@ -0,0 +1 @@ +{"tx": "fdc7ce4202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0900000000f49ff5b1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbb01000000249669d202c284cc000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e77d020000", "prevouts": ["f3566600000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "cd22690000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090274e9a197dffeab560f6d764160863bd948582bbbe73ce689c2fe924ce23f82a1d8037221258644efdd306d84eea245809cfbfa3d4ec384202f58ec72347e66345c91b30aa391f1f834df7940f6d9b56538f48a4be708aa59603fa8a49d785dbb65e69e75a0c1d7e9bcc4f98c22d87dc47d310d9407d50dd50de93b1de00a25177adc8853c01370e2c5b6d63d8d683145516bced6d17963bf18bffb621791c742784a397ab8ea9c0403b2ef6cd682331f4190e20687f5c49e3bdb6173f0e4cbd900991ec91d23319dcfd82f73226f6378fc5566fc61f9389034354b44c9bd4fa51dca410a0b0cefb28877432b5f7c8bf5f61f8eef57c550d4db2743bfa3fcd2b56d563ee4d11618802db67891ddfd3c0412436d3b1c63daf95dce4c16779f271831df892a04b911a54905b7b3baae7324c5a73f3d3cc12449f40ad9d359e82a67f95fd8eaea473efd1612ae33e383b268e73e631c92d217b32a42ff4e20f8d0407a77bc91badb9d7b54c63de0be89648adfbb793ce1da94f21b862b3ece8fe000c41595f7aebb049d6ec7fe0444a289a77e55baab9bb29c680581bfae20bc9e51bf8b8e1de14e1bb260805f1aa99d60aa8bb5da698a3e7ef28890140bc9d47a58c5c4e539c1d3ef7b73167c963bd0bbbc565b92ba3bb904a39cf425e3bc9f57d2201eef5ee9e73dbe5e9d272a328fc13856a9a51ed9fb86a5937451e0b31672a1978e8d3f677e276995757f", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d0abc6c99cdb1b2d92cc3611af9751bdc3c9fe9addf653926779bc3342f99dfdd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51d82f8c55e99af1bc6044802eb870171f459184b3c99e354e12eac4f204be9c37cf5fd42f9969f7f2472ed1fa62ffa49909a09466cf06ef7c57cb1be351156c54"]}, "failure": {"scriptSig": "", "witness": ["4d090233a526de0f8ac4aa3fa3ccef384d54a17b4b15234b92ab8724d6f68bc591e2c9bb0a88a7f4bbf7d0e1dafd8c1987ab1854abb1752239cdfb383966c02e6d3d81c9970759b59b2976e026bb9c9ac779fcfd5c58e91ae463bf867a1b6e88ebebc06ac3e1ddf878a16ebe4849dc3cedf716670fb602abcf458ae3d7053316a8b156627250b5bb6a01faa6ac51c538dd4d0d342b329e4add88456551b48e5be04dee9973b0b15eeee8f184c367b808f486755c92bb6568fa43db56d206c553d84b081d60c4742529039bdb73167c9493a80e860b9ecf71fa908cd3277e8d1f15b3cd325c7e827aba540c067ebedf36d7bbf7278df90eb5f0dd2d2e5f2a63dee773565ec329ea4e2c4a8915ceaf298fa8b416c4c3f337cb96a4870558991255bccb4148c38a296225c0159726043c89de079fc8b4c8dd9205d60342540c3d57c391ff1630c4a267f108e35565f762ba6310a9c4f225bb884242c3d82eca4763764c04da1ae7fd9ffe8c058e7edd29648d1c9bebb2359d7474c116b9dac03481c589ac7fd54699a1afb575661cffa385a6e9c78563c4d18fcfd852662340697abfaa340e948d5905289cce6fc54db5cea6b1dccf9eca35708a812a4f28368265f47c2f439a03c267b7df015a558e1d82da98a06289a915a5b05e44233a3a16b84072cd93bc52eab1f13828aeebc268c2e80ee9f675c77c364f310cb2ed8a2fa10f9be56ed93dd3603d2102607561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720480120d5a477c096fbef97d1ee2aeb957fc425ff8aedf322b93097b3a97db744cf5fd42f9969f7f2472ed1fa62ffa49909a09466cf06ef7c57cb1be351156c54"]}}, diff --git a/txscript/data/taproot-ref/13c9792e4f626e8f900acfa50cf122a5f5f15030 b/txscript/data/taproot-ref/13c9792e4f626e8f900acfa50cf122a5f5f15030 new file mode 100644 index 0000000000..738fc02e48 --- /dev/null +++ b/txscript/data/taproot-ref/13c9792e4f626e8f900acfa50cf122a5f5f15030 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7d00000000bdb388de8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42302000000684f888f0147fd2300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5ac08453", "prevouts": ["109027000000000017a91468f63610c45a6790781558e4d5ce83e16e8f3f3b87", "d6aa3a000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2352212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["0a4840b5169b4280cbc2bc61182b91f2558a29f20b31871018012c08fcff664659201014f10cc1f79d371fc6ddf3ab6aff415211de5436aa097fc50eb3f1dbe5", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/13d37de420974d4290a6029f20175feb02e1106e b/txscript/data/taproot-ref/13d37de420974d4290a6029f20175feb02e1106e new file mode 100644 index 0000000000..a9c1730f7c --- /dev/null +++ b/txscript/data/taproot-ref/13d37de420974d4290a6029f20175feb02e1106e @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1501000000e3ee7de3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c32010000003f2fec4a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b8010000006499adc6032e11bf00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc77d690e25", "prevouts": ["38975c0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f", "cb9154000000000022512096d49a663447a0304343e0ca844d9bda5a7da8dbda233b650dfa03e219f7bd31", "eee1100000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063ea68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93648734efffc6fccdfa671b85960f6a2915d6c681467297c41489a3521a420b294a2d42db82fd8c87bf94597052443343fe22a3a138f6b0aee44f71ff1c976f3ab32777cb2583add22ba560e78ee9942bfe3080d15b9172e7f2c8ac5adf5c65a1c36f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb1d5ef1e00fa5f70010a57f200748b29ecde733e01f3ca7c1bafa26b207d579538b2525e5ad3e6ab2346b1907a9f51d3650fdbb6911031be2b995911891caa483976a7e8bc20bfa4c53f64ff2df47d867849c8cbf6df51014735817968d498535c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}}, diff --git a/txscript/data/taproot-ref/13d9b1cfc7b7864ec3f85c71a1046df30cc17b62 b/txscript/data/taproot-ref/13d9b1cfc7b7864ec3f85c71a1046df30cc17b62 new file mode 100644 index 0000000000..008fb53104 --- /dev/null +++ b/txscript/data/taproot-ref/13d9b1cfc7b7864ec3f85c71a1046df30cc17b62 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9801000000acfffbeb02e4216d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac90020000", "prevouts": ["5c146f000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/unkpk/checksigadd", "success": {"scriptSig": "", "witness": ["cbe468d342d05067cf759e7786fa7d773f6336a46b8c391ba4988671fed73eba50cb6bf0ff1ce15f7af17ef4cdf4f7e5263990e8e8643b4fbdc8a7adff46e33e", "0051ba", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93629231b61c6552c60ab78187651c3584908ae1e5e6e6a28ea4234170b970c6fec00265579c9ab465d5922d1fe7ccd2a380d6e9c28a567fff5af501862d4fc50743de45c89862fb0bacbcd023499749ca2835a6e0cc10c045df6197f376a1b3da887ace9cacfd100dcef177ae09ce8bb2caf65c00693dfb1e2f65365235a56a522d6b917ab95e1fd9fa58eb1ad6ac180fd5b6f88d1a1a8ec6fad554fcfbece624ac8cd84c5af0b4719e62f8d2013ce0d4d13327c4e6fe65e29938735fc43debe5986c28c228ef1888dee344e41f26af0a1b5fd5ac36fb1e0b8256949ea91a65877ae71cede4162d7d56c21d6566ef88bfb31ac917ecb9cdbd205e92e106d62fabc32a651adc155e6b8aef622a203b8c3224e433a61efe40438a1ee3abe76600fe6967dbbb0216d0210891492746b07a592ae85bb43ae3347ec0e25bfb45e954be856f68441022cd3a444817edbae2583eb76683b8480293994d059289218f0d4a79d976568d9e92c4f00b9c8d7cf447c76042a3234918f31ddf63c43fdd94d6a32c000fafc31f95a626ff6b47272847de898d0fe9392d6cb40a47f54dc91f8f8111360dc44ae3d69de3386cee559eb49e6c76a737e105f9117431d64c73a13a31f98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["fd432c6b683e9b89ce010ba01631811316960fd946a28e9042feb1be6d99aa0b333b6d3e8a176dc16310d717ed191409e423131e93227765e76ed44af30ca557", "5400ba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368cc4d632c25fb1473ebc2c4691dff712f1529879b16cf6e01c3498b371ad5643f043ba3d030a3b9cb1de0a60e5c22d352c9a6b0167bb0429c65653ad93c6b5ad75df7d692cfa002fbaff39a633e2a3d0c51d8dadcd4fcf0c857fbd83ad169fef2faba22bfc7a47f9e635144f510dd0bf27279d7f381c4c7abb10bfa7caa6f45212b1384dfb83dad558f50952f8dc7a4c93fc05bc0bf8f252596f3f99dcc4aa25ab6fe4c1776346de255528baa11f4624c0da11cd67d3944bc9e3c23527f253a174940966dd57e339c9cd051354c05cad3fffcfa87d89865f388df6a9793fb850795b387e411ef7ecd738a90c270a9e8b41d104f0901d65be980e017742035d2ed5a15550423aeac2e288a32ca51234efdd8592bd1b66a7f846be8561b7af73c90baa320cf1711a17ed2a311e1783897c17c40a4468373563049ba8a82c1cbe704bb8d89f21761581480cc9fb789613a87d31235185f9da4b4384725e898ebf0d2c5eddaeb8557ce0f7cc7880e698091ab104cabb34aeeeb5d0f57ea86d1ebc555dfde575d48d1eaafa8343c63d6f5425984d2425aca274be02e47a5142e089ba2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/13ecc0464cacec7245082422e8f3212d959e0fa9 b/txscript/data/taproot-ref/13ecc0464cacec7245082422e8f3212d959e0fa9 new file mode 100644 index 0000000000..b014c5e6c6 --- /dev/null +++ b/txscript/data/taproot-ref/13ecc0464cacec7245082422e8f3212d959e0fa9 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0d00000000f0d0e5afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb5010000001fc1f48c03cccb44000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acfc000000", "prevouts": ["f2bb1e00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "59da280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_7f", "final": true, "success": {"scriptSig": "", "witness": ["e44b59fa69e292937d8450cf79b089361836967397d8a696e30cbe1cf896268bf7e0704f77bde10b992b87a8fb5c570fff52fcbb465352faaa49e954f03e28d983"]}, "failure": {"scriptSig": "", "witness": ["0ff7815b0b176697d6d7cebe201eaab1db60b0a4c521fb67becdc3dab42147ef948c5bb528e3a81bff4f7c9d102135a9003002a21d1cae0eed13adbf356c63db7f"]}}, diff --git a/txscript/data/taproot-ref/14450718a3a9e2266004b863df27746606f071ae b/txscript/data/taproot-ref/14450718a3a9e2266004b863df27746606f071ae new file mode 100644 index 0000000000..009937b569 --- /dev/null +++ b/txscript/data/taproot-ref/14450718a3a9e2266004b863df27746606f071ae @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc501000000731a1b27027c5774000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748751ef9a5d", "prevouts": ["c30d76000000000022512047adffb94737afedfc89d87094a195f595690331a7dc68829e77727baf25a9ad"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360793597254158918e3369507f2d6fdbef17d18b1028bbb0719450ded0f42c58f"]}, "failure": {"scriptSig": "", "witness": ["6a52616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/146b0be5a219a70b803fc5f82ded6f34e4cf7a6e b/txscript/data/taproot-ref/146b0be5a219a70b803fc5f82ded6f34e4cf7a6e new file mode 100644 index 0000000000..a5ebe4e192 --- /dev/null +++ b/txscript/data/taproot-ref/146b0be5a219a70b803fc5f82ded6f34e4cf7a6e @@ -0,0 +1 @@ +{"tx": "f66b5ce4038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c465000000005be9d6eedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc300000000394663ffdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c08020000000e1b4af6047d16af000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a62067231f", "prevouts": ["3e80410000000000225120783dfb3310d474c767ef9239befe26bff1665135289516e5417abb1737338f98", "172323000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "8d5d4c000000000017a9141757f4686f091b43a46fa47e92d07c87fc7a205e87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "165f142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["63b2ebbc764413c404afcf95e5f700ede4e39144ace8feaf943a413b057ec4448b8eb76fd6be2329a202b567268662569010b636e4fef4c7429523b227dbb93b"]}}, diff --git a/txscript/data/taproot-ref/1477a76ad0e64b74908b0f8a89549c7cf7190288 b/txscript/data/taproot-ref/1477a76ad0e64b74908b0f8a89549c7cf7190288 new file mode 100644 index 0000000000..7486404c5c --- /dev/null +++ b/txscript/data/taproot-ref/1477a76ad0e64b74908b0f8a89549c7cf7190288 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c130200000021444841dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3a0100000069712e0e01f62b6b000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787a59c0849", "prevouts": ["bf775c00000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f", "e8922000000000002260202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["3a3c590ec08cdb332be8e81f48a4b67e15e9fa330c9c6e57183c9027fa4272edc0c23e4668924216c7e09268bbbdc2dcf74344cc96681f2268e9affdffe701a0"]}}, diff --git a/txscript/data/taproot-ref/1493716a3ca7c3194959cd177b8dd531b04b0b9f b/txscript/data/taproot-ref/1493716a3ca7c3194959cd177b8dd531b04b0b9f new file mode 100644 index 0000000000..4dde4a4337 --- /dev/null +++ b/txscript/data/taproot-ref/1493716a3ca7c3194959cd177b8dd531b04b0b9f @@ -0,0 +1 @@ +{"tx": "06cb7a96028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42e01000000df4b95b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3200000000adddb4a50374fb5d000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acea040000", "prevouts": ["f3563e00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc", "fd30210000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "067d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823f226bc542f166b7ab1884d7601266c0b79ac59ceed404fe5ce2372ecd38c8cf9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ed1973e93f7ad3f562801731a237f358bfce42fb636b2a0dab3a823989e87b4ae"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93662b4c4e03f8bbc4e0fa6de616a7b17503976357af82c5e4ff1a693444fc6910b3f226bc542f166b7ab1884d7601266c0b79ac59ceed404fe5ce2372ecd38c8cf9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ed1973e93f7ad3f562801731a237f358bfce42fb636b2a0dab3a823989e87b4ae"]}}, diff --git a/txscript/data/taproot-ref/149679a6778ca49110eaeac21b33cd449242eb91 b/txscript/data/taproot-ref/149679a6778ca49110eaeac21b33cd449242eb91 new file mode 100644 index 0000000000..328132de03 --- /dev/null +++ b/txscript/data/taproot-ref/149679a6778ca49110eaeac21b33cd449242eb91 @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127086000000003a2fcd2c0453f10f000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7b2000000", "prevouts": ["43bf110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_58", "final": true, "success": {"scriptSig": "", "witness": ["ec39ab289167b4733f108acbf62f1118bd04b5979a66afb0f3c68018d0ce9a502d9f5c7c3300c72e2a8602ddd053040e72ebca258e951c089842e4eda60c5a0783", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["54ead5030a14a9f3d394b7d5b28710aef56bdd7a3d8cec3c3d55009ff788bc433728ebd60a03a77b475bed70a84da7938510401f95cb61c258545b30ca02cf3358", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/149bceae555709818ddc8eb34d3cf4b508780b88 b/txscript/data/taproot-ref/149bceae555709818ddc8eb34d3cf4b508780b88 new file mode 100644 index 0000000000..c45245eb7f --- /dev/null +++ b/txscript/data/taproot-ref/149bceae555709818ddc8eb34d3cf4b508780b88 @@ -0,0 +1 @@ +{"tx": "85ad78690260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701102000000aa846bd8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bce00000000353636d60413b23000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870a020000", "prevouts": ["b39f0e00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8", "28aa2300000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c2c55a726534a8d0321aea5300ccc37acb5b1fc81b19755e9d039e159ccc6bbd6e55e6cc099b3fd5cca65d40087200ff064f8f598dc371f61f8d957b472ffb5414746b6cdbbdbe747c087a2d99e7432ddfa1db1d7a6445e7dea3810e7475536557a61376c510bdd1fc860151a3b261939fa407ec1a2d0490cf2efc4278abc783"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f12e5bdadb74bb113beeaaa5995d4ebaa92337455ee51746db1fb6fe7db125e52d50ee9aa3de1fe988255b0d8b9f34dc2cecc4a96432b9f704e90359a06b468476e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}}, diff --git a/txscript/data/taproot-ref/14a9e9b7200758410bd419f2b0954ec253e17889 b/txscript/data/taproot-ref/14a9e9b7200758410bd419f2b0954ec253e17889 new file mode 100644 index 0000000000..f6b3df58c0 --- /dev/null +++ b/txscript/data/taproot-ref/14a9e9b7200758410bd419f2b0954ec253e17889 @@ -0,0 +1 @@ +{"tx": "0572398202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b01020000000b604692dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcb00000000fbc4aeb20342553b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7fc57fd5c", "prevouts": ["c5281f0000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "26c71e00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "de7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936de23aba2d7dfc49771c3511939fd66882f5955aeb1ffd7f3f853dee6c699f10346c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa827b55d11351c6fed41de6d200bca95500243dcc7874125f5161f5be208848f0ac1d0874bb493d5b277fe586a1908760dedf191b70e37bd9b06448d9d8257f0a"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93603f6319fbb8104be3478515f2930ba3b255e646dae280e79434cdb319e4e3729856e164d8f95680a310901239278cf924747110c023e5c9b2077227ee61e12b7ac1d0874bb493d5b277fe586a1908760dedf191b70e37bd9b06448d9d8257f0a"]}}, diff --git a/txscript/data/taproot-ref/14b46e9b808aa20b426e21803aebd6efffef133f b/txscript/data/taproot-ref/14b46e9b808aa20b426e21803aebd6efffef133f new file mode 100644 index 0000000000..2761fc6d4a --- /dev/null +++ b/txscript/data/taproot-ref/14b46e9b808aa20b426e21803aebd6efffef133f @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8100000000cd228e8dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa4000000004c9db3ce04ea51bf000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a60d000000", "prevouts": ["11384c0000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "6aa37400000000001659142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["9a1626105ce106bafb1b13e47bcbc07de6a37e6f07b467c39d053d20253c064f39d7f135eaeb21eb50f1b7ae032cd0a1a96a4593bcba4e4f277fe871479c0a10"]}}, diff --git a/txscript/data/taproot-ref/14b583f6a2bb67ac548a6daf674748880c14916c b/txscript/data/taproot-ref/14b583f6a2bb67ac548a6daf674748880c14916c new file mode 100644 index 0000000000..a79f5974d6 --- /dev/null +++ b/txscript/data/taproot-ref/14b583f6a2bb67ac548a6daf674748880c14916c @@ -0,0 +1 @@ +{"tx": "b039045e018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c4000000000d55d5b4022f9b3900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acd328ce2e", "prevouts": ["44fe3b0000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "6b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366cf9eaec23fdd8ffc56eaf5457c71c87e3a4d680a728575e9c60ac5881aecf96f14541946e1cf92393992e5ef2191ac72b106fd890d94444e74600720cd636c212e839b87dc613c826a9c62085431a96f79b8782d4b0fe31dfc75aede09e250a"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f4575c9148ab8fb2f0e3b60c30486bc2998c5a9fcff153a4260746061263c245b36a70886d9e3726a9aa8a2b94454683b5181a970edd894e0d0cd75aad09f75436b2"]}}, diff --git a/txscript/data/taproot-ref/14bac90ea6a6692cf7202b96a1c18e47f81a055a b/txscript/data/taproot-ref/14bac90ea6a6692cf7202b96a1c18e47f81a055a new file mode 100644 index 0000000000..d64044cbaf --- /dev/null +++ b/txscript/data/taproot-ref/14bac90ea6a6692cf7202b96a1c18e47f81a055a @@ -0,0 +1 @@ +{"tx": "22713f2202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca30000000021b16c8a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4940100000024a82fcd0387598700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487a073772b", "prevouts": ["af76570000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a", "b7733100000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c5", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360437fc07f82a1b970ec5a575c32125a1db89269ab6bba98a0a02cfac89dc7ad84b23f991898c0f7e80b32f00b838c1f1514616fab2a47083539335b67c2689fcce4d7767c8a9637a0804b073b1eb172c67de67ce152ade33f2591a85dfee2e5a"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369f15a01ba92850ae0934bcdc7ad7dd0ec30771ae29a80b5a37ba0c6579d57abb111302735ec636dd6cd82402c946e3c4544cb7cccda2620354a4b8fa269f342b5075e3d7a2801b75eefdf65cb630fc6bd09768ae07eb1bf67760ac5f1c253b1300a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}}, diff --git a/txscript/data/taproot-ref/14d0d7bc3443d31977bc6035b1a9bce2c6dc9114 b/txscript/data/taproot-ref/14d0d7bc3443d31977bc6035b1a9bce2c6dc9114 new file mode 100644 index 0000000000..449e3c23fe --- /dev/null +++ b/txscript/data/taproot-ref/14d0d7bc3443d31977bc6035b1a9bce2c6dc9114 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc301000000859e9063bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdc01000000d82019748bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c431000000003461614d047e0708010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e9103047", "prevouts": ["f007760000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "93d9610000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "f14b320000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090265dfb469bf381a99034f00c2313db7a9ea8487be485aea065b6a22bb58b09c0d5309145f4ee680d85c19e99edb3f45e1f4bed9589c94883deadebd3a5daa3b8b6b4e28040ecbb0f1f121ba924bcb343c975ac122db37e623c930d91f4611296f0d201fb314d2b988a760eb7983ff6c302b73ede91fba1ce9829c15726910d3398e0f2e6b8e941b96a59951882799189e17ea65da922a16a1e0c153363ee1304828977812013fdb0fa2a9f711e37a8ffe32974de487717c696e5409fda07631e9536ee88b3c1b5263411360122a1747650520be59c8303de25e875bfcc7d90de78b5a729fab6117ee447d5f4785ab39c4184226cbdcc52fd5fad14ef2806e855e6f52eb453acfb02841f5dde4ac674ccf6590592a420ca4368949665494cab71da2bebfb0bd7fc432ee49d355d76fdd59da5d39d12f995804d7b2caf0ccd4b41a51b940085554ee8f1938c72af163288fefdcbc0541b0e06a912bc152fc945a2278103e7dc7625c3c588b46410224860881b4c5af2fe857791103e89a10cc73081a38a97bd449892f664a86ba2d59ccf39ffb0524a8d6dbee8a8a8221ffd29fadb356de9375f79fc28eed914f2cddca1a333a15f6a93c85855011e515d5ec749790f0a9ddd983b2182dcda8297c95feb0a7ee5cb64a430d7bd637681e27086f27da38718e9dd9cb6ac1e44607b35a9d04f31ca79be71e5e0ea78913b464a6f3d3f2607cad3eb019dc1375", "0c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828d88e70532c494439586c1157b8a644f11fc532506ec8f5af612c230a11997e628257bae22e6d8aedb31b43cfe467850e731fb88c1221782039a4c16ef44c35617d0d4fc7404dd8984f6a1705481d95654b515a34c586c99c11bfe20e9503459"]}, "failure": {"scriptSig": "", "witness": ["4d090231d27d278dca35e9f72199a0cfa3d8906195b95239ac69a44d4ee627e4148a24c63a3d20f2970e9501a90323e490c366a1b9ee5d7dc6dc89151c8ce8bf3d1ed4cd968718cd918890b942be0f3d5c3e25796f3cc8886c795f90b69d871180fd431d85d43644d5a8e0d1b6093cbd0da3f3961c77c36d753936506381ab188f84a9537fc2aa603b49110d4c455f25e02d3653c2f3e9ee3ab7c037de21ce7f9f11fe1be9f53e454e691d23d5c3ab8d01017bc55b2b33e5105a55872bcc01a6a1891c08ffd418619a06320902816fe0d47e05628b6a5d930660dd7d78273cec77407af6668773aad18cdab903311d102a66f8db7c1d920e13c438ef6d38b9d8e46f115510bca1098e93a4cf32297b9262c4cf00342ae63bd0c75563e31717c11fe94430d5cd76ef126a5ded19ae495f33e348623f49c88c2399688c36adfb47c7ce0b1cc1305efa202815302ebd4164d28e1f551aaba5bc389ab20e84b37960c47da88f1d82f0526cd6e8978d3bf45bc5840ba13e6b5b21110c325ac0b0426a211f504a568f5b3b63c9d0b24fa92e1de500c99b29a1e05bece91487858990493b47c488106d06813911dbf993bf5c05d8f9ece975160ebe2183dddf8372d911dbfb10607c912fcf83a467def7048c911819030bd29dab21b76d8a6ea7daf07f289192e7f92218e2edf2e9af2a098f48000b3b2c7a08050cf78f63f6179e1694d9ed201e4d1cebee4245108375", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a98df32f973e5ecb9021ae265faceadfc19a0621ba8bbdbaed0b61c2d0622269da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e5111e542fd849c49f4d44aada2d8e1aab946c793c1d334242f5a6d1a51a6de2d5b0de380cf0ebf0fa9d17e1d1edb87a374b64935c1c67f0c5024fcc072643681"]}}, diff --git a/txscript/data/taproot-ref/14d9a8a4291206e2c4d73120dc485bd077e5f66d b/txscript/data/taproot-ref/14d9a8a4291206e2c4d73120dc485bd077e5f66d new file mode 100644 index 0000000000..fcb097f6e1 --- /dev/null +++ b/txscript/data/taproot-ref/14d9a8a4291206e2c4d73120dc485bd077e5f66d @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c00000000addaa5ecdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0b01000000d5f25f580315f46d00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acf284905e", "prevouts": ["41ae4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "91ef230000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_25", "final": true, "success": {"scriptSig": "", "witness": ["dc2a706a4a0aa1f32af552a7b5304f12a3813a7f904ccc019d6dcaf3c7fada431badbdd671c254b846fa339901440edf6b43e99ee23e4db215bcfe128019867b83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7f8032755532062218442e9b19b7dd6d4fa75c1a71b6e058621507722689c3e5b6a42b7e42a91de94f0940d8e3efe7b702c8a4ae7747e272f2e6cc7ba0e58c3525", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/14ffecf99f50d1adde6ff14120965c878f744781 b/txscript/data/taproot-ref/14ffecf99f50d1adde6ff14120965c878f744781 new file mode 100644 index 0000000000..c80be6fb54 --- /dev/null +++ b/txscript/data/taproot-ref/14ffecf99f50d1adde6ff14120965c878f744781 @@ -0,0 +1 @@ +{"tx": "1440bee6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44000000000a895e88fbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf52000000000366cbad01bc8c1b00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac83030000", "prevouts": ["a0853e00000000002252202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "44c57f0000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a62", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936adba0e1bc195d38fce49fa646b6129b089e3124fdc2016a828a489528ffec7b5c3a658b9783cc0a28fcc02932d4b85eca4f49aba0b4fac0b36a7e3a0001ff4113fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4acac51423d2718039d2d4f4b1ede307d37862410d7af1d01b9eb1511bc3dae1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004522ebb88c16ebf61dfdf766657f947c6b679bf36be3a1118c2e7b2b24c8fd5c2a5a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}}, diff --git a/txscript/data/taproot-ref/15032320c16e26b0069cf1571846247d073f2efe b/txscript/data/taproot-ref/15032320c16e26b0069cf1571846247d073f2efe new file mode 100644 index 0000000000..5f94bd2804 --- /dev/null +++ b/txscript/data/taproot-ref/15032320c16e26b0069cf1571846247d073f2efe @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1402000000ff7187b9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8600000000e2bd2fabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b54000000005614c499012d9a5900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388aca876a75f", "prevouts": ["cc547700000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "b4db27000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "aafc28000000000022512008ff927e8178e20f38298d934a97845982dc7c5901b7d815cf7926413ad6b4c2"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f328d66b083ab2a9c43e5cc215aeb4ee10a12698c3df0ddf89a122fccd78eacd"]}, "failure": {"scriptSig": "", "witness": ["6a90616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/150b2d12becd542c0352fdc80bbd85c2901d8228 b/txscript/data/taproot-ref/150b2d12becd542c0352fdc80bbd85c2901d8228 new file mode 100644 index 0000000000..9394805535 --- /dev/null +++ b/txscript/data/taproot-ref/150b2d12becd542c0352fdc80bbd85c2901d8228 @@ -0,0 +1 @@ +{"tx": "32bd0f0b03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7301000000a2d6c9c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a100000000c06b56c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127000020000006321a4850146cb4d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709ff9333", "prevouts": ["03b67e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "f22b120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "802711000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "success": {"scriptSig": "", "witness": ["9e7a5db4c19c933d8a1c668f5df19fbea4c8449ec42c618226deb5cdbf56601e0590821fae8c6467f18c74a86f3b381d09c2623874937be21ed1151241df34d882", "50664439600155fd4b4c213b5426df46fbba2237183c4c5ab72ab97ac7f95840fc9d7fea4f2bd65d35215ea52b50e717aa96ae22b868d3fb618165042c193ff8803fc7ed900f0a84f257ddea319b01ea30c0387869daa1df78d31771e6bda749f30d1aa832611bbdd6058e6787bc429325c2f1a08d12889954736cc348db08694352730bf7581d4d4f066490c3ea8b33db8a00f5e53df4dec53719d4f108d44ea435c66df718a1762c240482f62de9093a14bdf2ed1c1ab6d5f8d9bbb6dc90b1b0d66449f73ffe99c5d5a260e202819614dc6a80ac3738"]}, "failure": {"scriptSig": "", "witness": ["e05cd2880a9cda10a00c04f98f7f4d9743c62524bf765b17c6a37698f9e3b74550d3b29bb8ae6b73bdcb58d1be8c51b9413246e1ba613d872a327a7c438b7d1f82", "50e765dd9670a5d889e2ef65331812b31f7b301662cc7be2fb94631a232f39a72d5df054fd5fa2510b825fb2052cb9ca4881b80269621671baf39e962d989c58cba068b76c7a81a0859e1439a1bf5de050f5f7f4accb61"]}}, diff --git a/txscript/data/taproot-ref/152491c8478252c98640ae41d5813cd6cc4800a4 b/txscript/data/taproot-ref/152491c8478252c98640ae41d5813cd6cc4800a4 new file mode 100644 index 0000000000..626399597a --- /dev/null +++ b/txscript/data/taproot-ref/152491c8478252c98640ae41d5813cd6cc4800a4 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be001000000a799f40abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4f010000001e21c462bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9a0000000077dd0fb3022989fd0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a611000000", "prevouts": ["025a1f00000000002251203d94c30f7ef8b0d9d4c7a773497c0af2bbd0a232f6e89c19e65bba66d7e2056b", "c0e969000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "f4dd760000000000225120ff67dbe5f480d52a3db68ddc8756a5701c353a5e478c53504b3368e48f095423"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["4c2811373219b4fe0d51b3636adf30c65e37103a291cad7ced9974fc1ed02719b3c730180f343426fa077c7b021ccf8f14d8e18de65258ee9a2cbecab092d49f", "20c361c307b1347c3dbd192b8365ea0856258daea3babb4e0b6cf1473be162b5c249f6a8283ba675e35f5789e589d63f47ad7f6f0d5b741fd2303d960bd2679f492610c0226661ca3b4fa3a985162b4ede7ee3adaf664778a9a77400b693ab17ece76d7805307589a2826dd9d544f88265663f9df8f3526d82ca0f6be0ceaac07f", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694623ddbddbeff0d470051de72b352c3379666f2e7a0c2d38368d4b52ca36d470000000000000000000000000000000000000000000000000000000000000000da4811e2aacb3c84826462416084743ed6dd43bb284051c03dfdddfd63c540104f14b640f086882c47bced18d592421bbd1a13d929376bd98932a8e6f7af0432ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcf51df56b95b936c41835af32e23ec4c37bba09ad354e25a296cf8a2656a50f670993ecbbcf0bc159ec158eab8996524b2d584952c62e23e4e36e6cecb65ecae016910cb2eee6c42404feb46b882062426af39f8f178be9c4f5a5d922c0d788600000000000000000000000000000000000000000000000000000000000000006527910f019c3fcf564669fbb4de551caf24033b91e6e20341a2ad1e19e794975ab79dfa7cf5db7145e5d4b1cf65a62da6f4820b5bb8836c7352aa412d89bbf9cffa665729358e66ee7974075bdc3f023da28c8170769389bd77fd3350573099ad9e4f4a509b1727e57bb4cdfbbc9cdc5e25d1c80d3c0e1c0472b5a012f1c5ac8fdb0ed751460f87321e7eb2778f208b22cc62c5a3333033aabc48d6a4234408555e4ea92c158eabbc383be2138719c205f2e564d5513c602afa90d5d21a64ed07c9bb2cdb84cb55454f658761c235886584f469cb5db1c8f126bb07e52d94fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2b9a385067d1ff76e66456d18758d7252474300231654393e962574dfcb3e02900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6d0207243d3a5e1d40b65a3e00ac09ee4fb9ac90d65b0d48611dc50693aa349554b1a5dfec8ab3dd9cbb3b7c3bce73eeb64d657f9b0edbf4cf233f96ccdd20da897b378d7e7abeea00daa9a8458336b67244f9b33bbdcaedf4e545a463a31220000000000000000000000000000000000000000000000000000000000000000f1923ab9b1427d72e7269c361060aee9e259b71dd54306873c6a83db8917af370000000000000000000000000000000000000000000000000000000000000000dfacecc67e0994959ed18f085c4d51a50d8c63c6ae33e37cdfd0aaa3916a01ffd906df940b0788d9298f45a851e28993d905f4f44e71f23447a8eb291b08da0b13ac2ecd7c087e789b7aec612185da482c4154291c9750ddb61eae66b7a3b84d3637d419470f6e827829fb96ca2244aea96c187addf1800b3a1c93168b7f7352114f215a8f004336333296195e14e4cf4d41b60e61102a4922a0753f47792f52707b26b61c29f13b51ee900bc00311c92ba01cb9fbc8146f086b212616b917eac92168c5b925cb38cf692d2ad85d4a48328295d9a986cf2ed298979ec2d77165b8693445bfd3789f047078d3089189a42154d3c6d025ccca8059fe44b852d46c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026779a7dcd99df21ca785abdb33aa8dcefe047efeecf6776220d361c8db1926d0000000000000000000000000000000000000000000000000000000000000000610c1eb08b2962ddd01d2c8466ebebdc574b186c623b686c6d7d8a5bdb0b6407000000000000000000000000000000000000000000000000000000000000000006c96b0efe981974fe03ce5c459e755d2b9bf6c03ac4be4b9a79954a9bae8bf0dacd581c50f6afba108c6f63783079ff6f9aa98726d907938892631d548282ec0000000000000000000000000000000000000000000000000000000000000000da4bda93fc5768f467514d10b3e0847704a6ab251f1eed02771e37529e138c835224c8e6add6fbfd06d3f86feef55029733513ed47533dab7044333377279f0d813863f5fae4e2e3c999407371460a52d5509a286bfc3367bd768b89ee842fb9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90fa64bd3bee3a05ed5ae22173e7f969667bbe2e1864238b8969d4822a247470472b397fe976f850c4dab4af7a4fe2260bcf80cf77b002706e4fcd222e448e087b98b20d1cd8f5dc8697f8d25ccffa3f7e6106e17b2cfb546ba60b050f05ee34014daf9b7831c6b6aef9dc084c1cbc9e70624e236891a8079a08acb3c4b3733bf8cad34ee169bc56f17c0da902a29574d2874ce1479b25f0a13a55943edf23aea89cf5d84c7cb0a591b3d8c719e5d151096bda56f2b15d1b162f87e1ace3d942fc1aecb5da843cc093ab6bd2197970e55555844fd2778e623b202ac79a197297d7743666a6a236c6f008d32f55f7580c26c63af20514bb21225a25cad5bec6653de563560779ec83e2d18d669241ea80197c1becd5af2a19f55c752356ad7d41e57397ff916836f106d1077c50c353a77cff266c1ca61c192f719e62d11d26f61ca4b7357879edbce8f21690ebb8d359e46d22056ddbcaf4b85fb534a26b924bcd5eff56081dfd8b71d373a31bc6d37ec91f93c78486cd6dab9c5b709f0ed53dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8201962e9051459e1b14ad2163ca08d4980ccfdb063b840b38d00c267fdb51affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6992696ad57ce4955c69e5322b474dc52d445da18f197a3fe875df06f3965f467fede0c9619ced497685906b3e6a271af70afe7b1cf2e6a96572f45027424d2b7f424b07e7f08053d8bd3c2fa343a8a423b1a8bd414efdae03adb9c9c7a43af234068674a7a0acc2028341b92d85529616dfe6deac9718e05acc43bac4285f4c95a57aa0bbb142f8691107c5b257f93ae851f054af2edde97fbdc1b6b815f9f000c6412c25377ad82d391822896adc0e03a8aeeace06fa19c32673ba251f28bdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000e4e023bba57072ac921c95300dadef54579723e7d5494fb3cc674e6254aeb46c9d2cc27b9990c26cf55efc8ffb9b295f2e8e771e8f9b9ab66912cc17580edf6d6d9453ed2eaf6a1a94cebc2bd1601c37a141e4baf35b921b1e6a913421b4fb0adea8f5c19fcd235104ae63cc3721a3af04ffd5215ee0f537d6e835030e3c23ad7ab66b33c5fe4136214d2bbf5dff01dffa449a654c8334af799255d0b56ad3c2602a5826bd2d8331651edb05faad28b95f192954389b092c31fc14dcfe55efb7a42bc77d761e80540cee7f3e755be577d16f3061ed7066d55cbfc7731bf317348b006355c1e9b833782ee3fcb0c105d32de7ce461f093b18ac2469170b0f3163eb0b29ffabfadc4548a488bc6f7351730422069f075c89041ebf8c1a1263411b0000000000000000000000000000000000000000000000000000000000000000fb6017f23840baff3a911350961bbcf46bce41f99ddd15430e5c42bf750a2ea0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3fa33345aa47618e8fe0368be3040c4a53021f4e4eec186f77f9be22b921ff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27070a474e9083bdc6c46593942c11e5941cdd9cb4e0966459aebd77f49a25a5cb404b950305fc3997cf6d7a66804eb33ac708af7c6a5a8afeccd5684498634f49687bb3048bb5756478596a0156d73f72c5cb10b759d6682bf8bf1f1e3a5dce00000000000000000000000000000000000000000000000000000000000000009c20b15f7caac69d8ae700c0e6af6bf4ca64bc1ae695e675ad11a51c3616721ee217543ddb8a58dfd3951d4195b5bf71009a22e4e62eece10fcfdeae1f7808c2cacd00f6e8492212f03ff48ef3c9688d972b72bc418b4432ad7f873bbf2cca0a", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["4c2811373219b4fe0d51b3636adf30c65e37103a291cad7ced9974fc1ed02719b3c730180f343426fa077c7b021ccf8f14d8e18de65258ee9a2cbecab092d49f", "4ec6a99aa59703f81a8c4122a6d5f47117d14935de6551dce6dae5f38bc09de31b90fa725205863e73f0a1f4b42fd279200807e4805c684f9fe65924195f7b0a4e0aadb5c30a09167fe379c2ae362369169498258b791a07386c916db47672377a1237ce7ace8e8a8a7155bb79c3c040d4ae7cb0f9627cfa93d6f2fcd35bf4c8", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694623ddbddbeff0d470051de72b352c3379666f2e7a0c2d38368d4b52ca36d470000000000000000000000000000000000000000000000000000000000000000da4811e2aacb3c84826462416084743ed6dd43bb284051c03dfdddfd63c540104f14b640f086882c47bced18d592421bbd1a13d929376bd98932a8e6f7af0432ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcf51df56b95b936c41835af32e23ec4c37bba09ad354e25a296cf8a2656a50f670993ecbbcf0bc159ec158eab8996524b2d584952c62e23e4e36e6cecb65ecae016910cb2eee6c42404feb46b882062426af39f8f178be9c4f5a5d922c0d788600000000000000000000000000000000000000000000000000000000000000006527910f019c3fcf564669fbb4de551caf24033b91e6e20341a2ad1e19e794975ab79dfa7cf5db7145e5d4b1cf65a62da6f4820b5bb8836c7352aa412d89bbf9cffa665729358e66ee7974075bdc3f023da28c8170769389bd77fd3350573099ad9e4f4a509b1727e57bb4cdfbbc9cdc5e25d1c80d3c0e1c0472b5a012f1c5ac8fdb0ed751460f87321e7eb2778f208b22cc62c5a3333033aabc48d6a4234408555e4ea92c158eabbc383be2138719c205f2e564d5513c602afa90d5d21a64ed07c9bb2cdb84cb55454f658761c235886584f469cb5db1c8f126bb07e52d94fcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2b9a385067d1ff76e66456d18758d7252474300231654393e962574dfcb3e02900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6d0207243d3a5e1d40b65a3e00ac09ee4fb9ac90d65b0d48611dc50693aa349554b1a5dfec8ab3dd9cbb3b7c3bce73eeb64d657f9b0edbf4cf233f96ccdd20da897b378d7e7abeea00daa9a8458336b67244f9b33bbdcaedf4e545a463a31220000000000000000000000000000000000000000000000000000000000000000f1923ab9b1427d72e7269c361060aee9e259b71dd54306873c6a83db8917af370000000000000000000000000000000000000000000000000000000000000000dfacecc67e0994959ed18f085c4d51a50d8c63c6ae33e37cdfd0aaa3916a01ffd906df940b0788d9298f45a851e28993d905f4f44e71f23447a8eb291b08da0b13ac2ecd7c087e789b7aec612185da482c4154291c9750ddb61eae66b7a3b84d3637d419470f6e827829fb96ca2244aea96c187addf1800b3a1c93168b7f7352114f215a8f004336333296195e14e4cf4d41b60e61102a4922a0753f47792f52707b26b61c29f13b51ee900bc00311c92ba01cb9fbc8146f086b212616b917eac92168c5b925cb38cf692d2ad85d4a48328295d9a986cf2ed298979ec2d77165b8693445bfd3789f047078d3089189a42154d3c6d025ccca8059fe44b852d46c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000026779a7dcd99df21ca785abdb33aa8dcefe047efeecf6776220d361c8db1926d0000000000000000000000000000000000000000000000000000000000000000610c1eb08b2962ddd01d2c8466ebebdc574b186c623b686c6d7d8a5bdb0b6407000000000000000000000000000000000000000000000000000000000000000006c96b0efe981974fe03ce5c459e755d2b9bf6c03ac4be4b9a79954a9bae8bf0dacd581c50f6afba108c6f63783079ff6f9aa98726d907938892631d548282ec0000000000000000000000000000000000000000000000000000000000000000da4bda93fc5768f467514d10b3e0847704a6ab251f1eed02771e37529e138c835224c8e6add6fbfd06d3f86feef55029733513ed47533dab7044333377279f0d813863f5fae4e2e3c999407371460a52d5509a286bfc3367bd768b89ee842fb9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90fa64bd3bee3a05ed5ae22173e7f969667bbe2e1864238b8969d4822a247470472b397fe976f850c4dab4af7a4fe2260bcf80cf77b002706e4fcd222e448e087b98b20d1cd8f5dc8697f8d25ccffa3f7e6106e17b2cfb546ba60b050f05ee34014daf9b7831c6b6aef9dc084c1cbc9e70624e236891a8079a08acb3c4b3733bf8cad34ee169bc56f17c0da902a29574d2874ce1479b25f0a13a55943edf23aea89cf5d84c7cb0a591b3d8c719e5d151096bda56f2b15d1b162f87e1ace3d942fc1aecb5da843cc093ab6bd2197970e55555844fd2778e623b202ac79a197297d7743666a6a236c6f008d32f55f7580c26c63af20514bb21225a25cad5bec6653de563560779ec83e2d18d669241ea80197c1becd5af2a19f55c752356ad7d41e57397ff916836f106d1077c50c353a77cff266c1ca61c192f719e62d11d26f61ca4b7357879edbce8f21690ebb8d359e46d22056ddbcaf4b85fb534a26b924bcd5eff56081dfd8b71d373a31bc6d37ec91f93c78486cd6dab9c5b709f0ed53dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8201962e9051459e1b14ad2163ca08d4980ccfdb063b840b38d00c267fdb51affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6992696ad57ce4955c69e5322b474dc52d445da18f197a3fe875df06f3965f467fede0c9619ced497685906b3e6a271af70afe7b1cf2e6a96572f45027424d2b7f424b07e7f08053d8bd3c2fa343a8a423b1a8bd414efdae03adb9c9c7a43af234068674a7a0acc2028341b92d85529616dfe6deac9718e05acc43bac4285f4c95a57aa0bbb142f8691107c5b257f93ae851f054af2edde97fbdc1b6b815f9f000c6412c25377ad82d391822896adc0e03a8aeeace06fa19c32673ba251f28bdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000e4e023bba57072ac921c95300dadef54579723e7d5494fb3cc674e6254aeb46c9d2cc27b9990c26cf55efc8ffb9b295f2e8e771e8f9b9ab66912cc17580edf6d6d9453ed2eaf6a1a94cebc2bd1601c37a141e4baf35b921b1e6a913421b4fb0adea8f5c19fcd235104ae63cc3721a3af04ffd5215ee0f537d6e835030e3c23ad7ab66b33c5fe4136214d2bbf5dff01dffa449a654c8334af799255d0b56ad3c2602a5826bd2d8331651edb05faad28b95f192954389b092c31fc14dcfe55efb7a42bc77d761e80540cee7f3e755be577d16f3061ed7066d55cbfc7731bf317348b006355c1e9b833782ee3fcb0c105d32de7ce461f093b18ac2469170b0f3163eb0b29ffabfadc4548a488bc6f7351730422069f075c89041ebf8c1a1263411b0000000000000000000000000000000000000000000000000000000000000000fb6017f23840baff3a911350961bbcf46bce41f99ddd15430e5c42bf750a2ea0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3fa33345aa47618e8fe0368be3040c4a53021f4e4eec186f77f9be22b921ff03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27070a474e9083bdc6c46593942c11e5941cdd9cb4e0966459aebd77f49a25a5cb404b950305fc3997cf6d7a66804eb33ac708af7c6a5a8afeccd5684498634f49687bb3048bb5756478596a0156d73f72c5cb10b759d6682bf8bf1f1e3a5dce00000000000000000000000000000000000000000000000000000000000000009c20b15f7caac69d8ae700c0e6af6bf4ca64bc1ae695e675ad11a51c3616721ee217543ddb8a58dfd3951d4195b5bf71009a22e4e62eece10fcfdeae1f7808c2cacd00f6e8492212f03ff48ef3c9688d972b72bc418b4432ad7f873bbf2cca0a", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/1532d9cb1517dd25a5c8a93eb64d3962a52cf4cd b/txscript/data/taproot-ref/1532d9cb1517dd25a5c8a93eb64d3962a52cf4cd new file mode 100644 index 0000000000..4248146231 --- /dev/null +++ b/txscript/data/taproot-ref/1532d9cb1517dd25a5c8a93eb64d3962a52cf4cd @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4e000000008f41f4e3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b450000000076427492dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cff00000000c272c0da025f6a97000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acbf96ea1e", "prevouts": ["4be92800000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "7fc7250000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "79b64a00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6aca", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6f432293da1a11df20de0df2cdfe573cc92222e6714a6159f8978c317656a2558c38514ede62462d8dcaca890d92a506794ae643449cc5c1c2c2667ece3d2dbdc18898993c284d2f731b7495cb62c60e8571430965d040562487638e1f1fd248a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369d53ff9cdbd05c7b14874b5d383777a8a4f6c1559bc54c1161d63ac106a237bcc1012b923c15ff4ca5711684c82f77f7d0ace9e417918255ff860668826001128a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}}, diff --git a/txscript/data/taproot-ref/154147c0c82e41a7cfdb7b8295df125020cd7113 b/txscript/data/taproot-ref/154147c0c82e41a7cfdb7b8295df125020cd7113 new file mode 100644 index 0000000000..8a37e0a942 --- /dev/null +++ b/txscript/data/taproot-ref/154147c0c82e41a7cfdb7b8295df125020cd7113 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bc00000000045d0f63dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0301000000dc9d369c018f9e5b000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787a2000000", "prevouts": ["fc803f0000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "8d43260000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "d47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e1d15be41604f0459412a6d9aa888e4d019cca614dbd3b30e8d19f8f49981c6d3eef830f28a0ecbd34c70640f7829eb7d86b0cf2da24853f16b74ab53bbfd728ea84370bdaf8fbfa2c728119f306db95ff534e2e627fabf0c000f69380d4e93e"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93669e6d8ef22861e07fee4583a5ab47fb4893c942079130ef347ee1cbb0ba45047b93338c7d107e01cff6d052285c57a3fa3547f5f14e99776c0371239cd8619173eef830f28a0ecbd34c70640f7829eb7d86b0cf2da24853f16b74ab53bbfd728ea84370bdaf8fbfa2c728119f306db95ff534e2e627fabf0c000f69380d4e93e"]}}, diff --git a/txscript/data/taproot-ref/154b30ae55351cbd129d9b1b6a6311572840bb26 b/txscript/data/taproot-ref/154b30ae55351cbd129d9b1b6a6311572840bb26 new file mode 100644 index 0000000000..2f5aee4c43 --- /dev/null +++ b/txscript/data/taproot-ref/154b30ae55351cbd129d9b1b6a6311572840bb26 @@ -0,0 +1 @@ +{"tx": "b516eae002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3801000000c3f7c6c8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8800000000587ace9a0352bb73000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4872f7d0b24", "prevouts": ["9917220000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "91ee530000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "fb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936832cdd808d94d07e5d991a3d0c5a8b4a06c9fcd7df1eeedb760eeb7a3be6ddfe43d925f8e6664e67417d113cf51c5b4c3126025efa5f83bf5b16dba6746279b738273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d466d9f82b2327fc04ce4429e47540ca0f52fd08e57643f6e07da44ee4246ab9eee8539df42e1fa2e5e9e7b75fbe1b52db879ec8a622b496736c99966ce19d0038273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}}, diff --git a/txscript/data/taproot-ref/15541041a721e558c8cfa7f4ee5f4d09fa6c9065 b/txscript/data/taproot-ref/15541041a721e558c8cfa7f4ee5f4d09fa6c9065 new file mode 100644 index 0000000000..370a64de46 --- /dev/null +++ b/txscript/data/taproot-ref/15541041a721e558c8cfa7f4ee5f4d09fa6c9065 @@ -0,0 +1 @@ +{"tx": "e61fc582038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45601000000c4e2b5b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2001000000c5b7f7db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41a020000002528aeb801fdae1700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7c4010000", "prevouts": ["f0893300000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970", "8b96760000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f", "5e9f320000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_8d", "final": true, "success": {"scriptSig": "", "witness": ["1b6c242c01c1110e3cb320bbad176adc2fa5b1b01e493aa2200b28f5419ca02a8f8fb950dbe0ccc6de76af5df3cc4ccfdade86acafaca80d8cabe28bb476b73182"]}, "failure": {"scriptSig": "", "witness": ["383ec8f0dd004aebdd2ad05a5a87c334f6d1b2c1398272c26fc9893a4317acba84cf4ed11aebe339d3567509a40e076d0644b5ba82904b643cfc1d6dba72a84e8d"]}}, diff --git a/txscript/data/taproot-ref/157183c1796c9575b6c576a29c98f58fbd42356c b/txscript/data/taproot-ref/157183c1796c9575b6c576a29c98f58fbd42356c new file mode 100644 index 0000000000..80171c7c0d --- /dev/null +++ b/txscript/data/taproot-ref/157183c1796c9575b6c576a29c98f58fbd42356c @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc900000000f2275ef2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caf01000000fc57e8f90367dc99000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acba7c1440", "prevouts": ["6647510000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "52934b000000000017a91418261fd2fa0b0480c86b918607add1dde9f7026a87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2255202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["759bd5b16f8435ff1e784f79b0f1bd4de1590a1e54f0536d6d84bab4e8c903d81915781366fe51dfe410e656b2d5f3f89e7374de4e49700275cd296eadcc2b08"]}}, diff --git a/txscript/data/taproot-ref/1571fe984911dc73398ce28defbf71e715958a81 b/txscript/data/taproot-ref/1571fe984911dc73398ce28defbf71e715958a81 new file mode 100644 index 0000000000..f60986cd7f --- /dev/null +++ b/txscript/data/taproot-ref/1571fe984911dc73398ce28defbf71e715958a81 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704501000000ee4d8a848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40b01000000f0d42d8a0429894a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8749000000", "prevouts": ["30ce120000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "725c3a00000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cebe1805b4dd002a9656fd180b0893baf3654597c23b46cc67f3675a294fa085bbd17872a9d61e54e96dfef681da77b5399be78aec05b527019b8e812e967c33a95f177959a3d24a94a797d1e607e5550897d4e95d12a52323e6e8eeeab3383c"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e145a42fba29499bdd7f6ed301115275954ea9ec94acc2dc80e39b9e79b601e9aa172fc08f39dec38a16acdaea6f2fb40d915f4bcb39aadc0ac96def6ea8d2de907407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}}, diff --git a/txscript/data/taproot-ref/157aebc161b66c638243c0a814262c48979b21de b/txscript/data/taproot-ref/157aebc161b66c638243c0a814262c48979b21de new file mode 100644 index 0000000000..e2249034f9 --- /dev/null +++ b/txscript/data/taproot-ref/157aebc161b66c638243c0a814262c48979b21de @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45400000000990ad9cb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709601000000ca2459ba01210a0d00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acae847024", "prevouts": ["dd2d390000000000225120ed1497f510b05298f56dedfdf59bdab87baceded2037e3bc9fe47e7002bf81b0", "480f100000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "success": {"scriptSig": "", "witness": ["9c6d465f3859fe9151e890fc05920f5f0e2268355917987ee9ea7e79de43c463a7d888255b7132ae4dfbe3dc0bc72a101332801010f29430e3cc148bdebbd360", "2cae544d1f08c0bf45a6668f8e81e77ed8830fc5fff4a9b50d724022cab5690ee80b421eec511dd5e61010c90a857ef50df533c2f596e0", "750442c441326ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f2f760e336cd45075e8c240a289642762d43a502d352eb6f26856b9069ecbd6f0000000000000000000000000000000000000000000000000000000000000000a24976a108ec6afa239bf6529f53a4dd717eb168e3f5be864cac330810dbf6e1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92823c675e1a2f7520b6491ff52c17828c7ea50107a5ef1b6f881be6d9db820d", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["9c6d465f3859fe9151e890fc05920f5f0e2268355917987ee9ea7e79de43c463a7d888255b7132ae4dfbe3dc0bc72a101332801010f29430e3cc148bdebbd360", "4c8b30f49759382a62c79ad4ccc192fdd531d8ebd07da1d328f8dd1d6c551bed44f783ee28e0b6171a7c8a3d5af5de84f4452a1c1a0b", "750442c441326ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f2f760e336cd45075e8c240a289642762d43a502d352eb6f26856b9069ecbd6f0000000000000000000000000000000000000000000000000000000000000000a24976a108ec6afa239bf6529f53a4dd717eb168e3f5be864cac330810dbf6e1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92823c675e1a2f7520b6491ff52c17828c7ea50107a5ef1b6f881be6d9db820d", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/15b38d795c9bb9ef573b4d2b1ec4af8fc0cd8fb6 b/txscript/data/taproot-ref/15b38d795c9bb9ef573b4d2b1ec4af8fc0cd8fb6 new file mode 100644 index 0000000000..1dede99c1b --- /dev/null +++ b/txscript/data/taproot-ref/15b38d795c9bb9ef573b4d2b1ec4af8fc0cd8fb6 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccb000000001cfe6dddbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2c01000000c20cd2c40255c4c200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f877b000000", "prevouts": ["92f156000000000022512081f4094833c2bd1c8ccd20bca7d3b4bfd2d5ed628270e66be4011ac690e88295", "1a336e00000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["fd6b1d3683d073e61bf14c61589314e5217a28e37f79fb5ef1a559a7d092686e004fa5230305827d654a6dced83870b0cf28098e9e15ffa32763cfbc1704645a01", "9e692d60bd8d606571937bca6efc4424", "750023fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774daac916923fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da6eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360ee8ce1cc6402c664160e2673cd562c284ffe5a9d51d880e57aa7962acbdbaf6b82212375b3163165baf07a41081950e4a930d2d89c0b0e74343bf419d7d9a90faafca2a8a8f6c7d119832e5d564b4d4833a04a2fd7939d6b3f4f9113808a30946961be48dc97c5faed1227dd301bbed3c226f8bae5b9850ca0fec70938223991b8afbaa887ecd89c28162c904940f3bbdde1337cbf5cfaa29807f434f2a3cc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d991af31a7907ca623e7471472ba05dbdd7634b91e6dd5935b4cc093a81d13387ed1870f3f061cbc24b9576b62dd0a98734759b8e527cbb595f7f3b08e524f7fe4a16c690034d7855c91554dcb96a2d8d2a2769ebe672069a66f653ae4f76ca5d1bdeaec1d93e893b58df5440bac7d0034a93260341cba7c7e17ebd8142671cb618f3f7bd41dc0483f53576fb62c4a4ddf9fa643706403a7e80d2f52c16dfdb68e3b24e18d54ce3bc3f592380d81db6ff0b093303657b7c0217cea14ff19e7f2e577d56b1accd67f73c6a86371f866e23145b60ccc40343af6f38672031b483ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2568d751d8590666015ff790e5e46158bf7fb84480770b17f668e3d6b7108183960f233300d7460f72e9a93ec8ad82180f3479fd15aabb50f8199b7d58c03fd3b3e75a587ddd19655282f16a554597180217d56817cc2503f7772ca013c120c21f4bd07fed00ed63729e02e7a1dd956b0eaca9b45943eeed833f94fd8f9710697657d3dac22b45d9cf80f7698315130eae1662959abdbea7354a1bd55123ab178482c0fb29f4f03e22c5b87e2db34d4e9f152679680ecb88ef3772497d38e6c0e6b8521209d2c8c0b03daced85104381e7697c97be8a424e952346cc7b054a7506cdc72be568f2422212b9e88e6e7c5973a824be4b31a2aa17f52cf6ee495ab32bd2168a51c3a5b05d231b27d2fc6aad802bd77e8edb4ab219ffd6c1df66eda881590b753ce02dbc56d81978897e889e0cba287be84214a041ca7dff0b7997e36a7c2f4c46e7fc4cb5aeb93f28d687ac8c86ed0ed5b09a88d63ea4cef16c59a8000000000000000000000000000000000000000000000000000000000000000006f72b5a2d4bdcea0bd126246ad2d2477c17dea0bb0dc556b640d1aef1e676602492c3d88c830d609a707645ba9640d7d565bcd5aff69b0b6a3dcf2c5eec35c00000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf07e91c9da68d5d703d6e06c45282b0f3ddc059316166f8f9f7a179e25da51a49b0aad9ca9b82f64d83f38eca581ca38d1bb6f9f662829251e69bcf2f3e43145cc59dce48bf6b3d4072f2995aa52ff4488befc6866bd69943917bcd43579ea6ef216ce10035f9b72fff15c20113b0ce4b3064454680131c4e5eb9070cf67937416232689e5c807105b6f37cd192baeff0dd09e185b66338c5899223e92518c1000000000000000000000000000000000000000000000000000000000000000054f70ea626b1f3b00f2b177ed980cf6737c1fb222bf27803957141c673a197e344d81986af3e4fe232fb4cefb56d334dfa7cae09fa5f359cd5171bb54aebf2cdfae0afa293d38f6a60784231cd5c836df1ada5a03252d281528b3313c4ff44d1d2dbbcaadf18dceca71cebcaeb5d4d43c614022a3d5d97cfd78e94525aaa28347593bb42a8d7441c9a11bfa0bd2870f8ce06dda840c0fbf2f7106003cdac424d128c3dcdcdeb73a001958145f157af99ece9fa64aa5d571d87cbcb3025cbdc2f3a17c1097a4681b6ff92ec7197ec6db2514a2d22ee0344df673393be06893b4a00000000000000000000000000000000000000000000000000000000000000004d1c42436eec7dc83920ffb5afcab7d6e9de90f2dcc8d1b70444ba211de242c772e76cd39c87b212680a2ea640588ca6ebb9f1c2dc7ace27890693efa7e1437d77ebc8d0be0253abcc19620a9228e0fc39bff25095f2fcdade5349194d8b5c0aaec7e7dbf321ef772ac6b953fc7fd1b760cede71a36ed1f9f778d1d9d96cf2698141d7f62311cf943699d3bd66f6ef4202a3e3593a0b06e4e10ee1a1036fae949fbf725310621fe2bc1160d6b73acd12af1c9032b22d0c8271f1e608339aa4b2000000000000000000000000000000000000000000000000000000000000000093ab9d3ba174288d6d9576c25bf2eab745d2d2cfce294d070cc8bf0772a9cb52ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a29a7cd992657590929a06c0f1e0810cbbcd6e04dd22a270182707c31a68aa7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["fd6b1d3683d073e61bf14c61589314e5217a28e37f79fb5ef1a559a7d092686e004fa5230305827d654a6dced83870b0cf28098e9e15ffa32763cfbc1704645a01", "50827f0bdf447b9c8f9d0eaee88b8d", "750023fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774daac916923fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da6eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360ee8ce1cc6402c664160e2673cd562c284ffe5a9d51d880e57aa7962acbdbaf6b82212375b3163165baf07a41081950e4a930d2d89c0b0e74343bf419d7d9a90faafca2a8a8f6c7d119832e5d564b4d4833a04a2fd7939d6b3f4f9113808a30946961be48dc97c5faed1227dd301bbed3c226f8bae5b9850ca0fec70938223991b8afbaa887ecd89c28162c904940f3bbdde1337cbf5cfaa29807f434f2a3cc2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d991af31a7907ca623e7471472ba05dbdd7634b91e6dd5935b4cc093a81d13387ed1870f3f061cbc24b9576b62dd0a98734759b8e527cbb595f7f3b08e524f7fe4a16c690034d7855c91554dcb96a2d8d2a2769ebe672069a66f653ae4f76ca5d1bdeaec1d93e893b58df5440bac7d0034a93260341cba7c7e17ebd8142671cb618f3f7bd41dc0483f53576fb62c4a4ddf9fa643706403a7e80d2f52c16dfdb68e3b24e18d54ce3bc3f592380d81db6ff0b093303657b7c0217cea14ff19e7f2e577d56b1accd67f73c6a86371f866e23145b60ccc40343af6f38672031b483ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2568d751d8590666015ff790e5e46158bf7fb84480770b17f668e3d6b7108183960f233300d7460f72e9a93ec8ad82180f3479fd15aabb50f8199b7d58c03fd3b3e75a587ddd19655282f16a554597180217d56817cc2503f7772ca013c120c21f4bd07fed00ed63729e02e7a1dd956b0eaca9b45943eeed833f94fd8f9710697657d3dac22b45d9cf80f7698315130eae1662959abdbea7354a1bd55123ab178482c0fb29f4f03e22c5b87e2db34d4e9f152679680ecb88ef3772497d38e6c0e6b8521209d2c8c0b03daced85104381e7697c97be8a424e952346cc7b054a7506cdc72be568f2422212b9e88e6e7c5973a824be4b31a2aa17f52cf6ee495ab32bd2168a51c3a5b05d231b27d2fc6aad802bd77e8edb4ab219ffd6c1df66eda881590b753ce02dbc56d81978897e889e0cba287be84214a041ca7dff0b7997e36a7c2f4c46e7fc4cb5aeb93f28d687ac8c86ed0ed5b09a88d63ea4cef16c59a8000000000000000000000000000000000000000000000000000000000000000006f72b5a2d4bdcea0bd126246ad2d2477c17dea0bb0dc556b640d1aef1e676602492c3d88c830d609a707645ba9640d7d565bcd5aff69b0b6a3dcf2c5eec35c00000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf07e91c9da68d5d703d6e06c45282b0f3ddc059316166f8f9f7a179e25da51a49b0aad9ca9b82f64d83f38eca581ca38d1bb6f9f662829251e69bcf2f3e43145cc59dce48bf6b3d4072f2995aa52ff4488befc6866bd69943917bcd43579ea6ef216ce10035f9b72fff15c20113b0ce4b3064454680131c4e5eb9070cf67937416232689e5c807105b6f37cd192baeff0dd09e185b66338c5899223e92518c1000000000000000000000000000000000000000000000000000000000000000054f70ea626b1f3b00f2b177ed980cf6737c1fb222bf27803957141c673a197e344d81986af3e4fe232fb4cefb56d334dfa7cae09fa5f359cd5171bb54aebf2cdfae0afa293d38f6a60784231cd5c836df1ada5a03252d281528b3313c4ff44d1d2dbbcaadf18dceca71cebcaeb5d4d43c614022a3d5d97cfd78e94525aaa28347593bb42a8d7441c9a11bfa0bd2870f8ce06dda840c0fbf2f7106003cdac424d128c3dcdcdeb73a001958145f157af99ece9fa64aa5d571d87cbcb3025cbdc2f3a17c1097a4681b6ff92ec7197ec6db2514a2d22ee0344df673393be06893b4a00000000000000000000000000000000000000000000000000000000000000004d1c42436eec7dc83920ffb5afcab7d6e9de90f2dcc8d1b70444ba211de242c772e76cd39c87b212680a2ea640588ca6ebb9f1c2dc7ace27890693efa7e1437d77ebc8d0be0253abcc19620a9228e0fc39bff25095f2fcdade5349194d8b5c0aaec7e7dbf321ef772ac6b953fc7fd1b760cede71a36ed1f9f778d1d9d96cf2698141d7f62311cf943699d3bd66f6ef4202a3e3593a0b06e4e10ee1a1036fae949fbf725310621fe2bc1160d6b73acd12af1c9032b22d0c8271f1e608339aa4b2000000000000000000000000000000000000000000000000000000000000000093ab9d3ba174288d6d9576c25bf2eab745d2d2cfce294d070cc8bf0772a9cb52ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a29a7cd992657590929a06c0f1e0810cbbcd6e04dd22a270182707c31a68aa7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/15bed2762ca16694fce3754fdcb0fe404484b18c b/txscript/data/taproot-ref/15bed2762ca16694fce3754fdcb0fe404484b18c new file mode 100644 index 0000000000..2bc9b9f928 --- /dev/null +++ b/txscript/data/taproot-ref/15bed2762ca16694fce3754fdcb0fe404484b18c @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705c00000000fc3ba74b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270360100000034bc366cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfa0100000055a193d8039f024700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca335554b", "prevouts": ["c58a11000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "75690f000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "91f92800000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00637e68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456a1ef8f97f9d432891c11b27eeccc6d565069ea6fda1d19446b03f857ca9b7d00cbb6a1bc9c683a9249ad6bea98cd3b225511a23bd3763b6594afd12d3e036b5faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367379cfff3878adda0b859082d5b21f59c33b10ed69d43cb7d8098f3dbbb31e416a1ef8f97f9d432891c11b27eeccc6d565069ea6fda1d19446b03f857ca9b7d00cbb6a1bc9c683a9249ad6bea98cd3b225511a23bd3763b6594afd12d3e036b5faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}}, diff --git a/txscript/data/taproot-ref/15d389f49e1f412ed725252d3ee81230a2e81cd0 b/txscript/data/taproot-ref/15d389f49e1f412ed725252d3ee81230a2e81cd0 new file mode 100644 index 0000000000..ee828641b2 --- /dev/null +++ b/txscript/data/taproot-ref/15d389f49e1f412ed725252d3ee81230a2e81cd0 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4f01000000b02ea1ac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e30100000099b12a1b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703401000000cc4e3d950314417100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc757020000", "prevouts": ["0fb65300000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "2ac5100000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "03740f0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cd949ca4fda7b418d269ac7332cfe3b3c4d272913f478425fae381281da8c46e49153cc622aa353482ad0128e41c922a496803621b9ad28f713d97cdce77464b2c78e40500fa05b550b7f6357dbf83024c41a574f6a1706762c104fa8aec3fcb"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a30bb99d7d9a0fac0fcd125fc81d59b23ab8775c400f56b8708f446f264d38aca51646124a2b4386d840e205fec55c7cefbdbe9c75e9c45dd558741f313d2d0ee0d9bed60e53dfa6fe8b58229f37daf0597893c765c7b30814eb9e16fca89b86"]}}, diff --git a/txscript/data/taproot-ref/15fcafcc7469d59709774013df0fd9633e820008 b/txscript/data/taproot-ref/15fcafcc7469d59709774013df0fd9633e820008 new file mode 100644 index 0000000000..fb5d98321d --- /dev/null +++ b/txscript/data/taproot-ref/15fcafcc7469d59709774013df0fd9633e820008 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47d01000000bf12ba80dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e020000007eaf3ef5041e8d5500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79693000000", "prevouts": ["fd043300000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "0f3225000000000017a914a5f28fe5532719f979169bfa3a31d5746f69452187"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2357212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["b8be758fe2d28e7fbfa6f2359efe0fbfe093c11e11aa89a0f25e978fccaabc764e37fb378db09249e7a5fd824831cb3af1a1074bb5d25e5c7d8aa5c537fe4a1a"]}}, diff --git a/txscript/data/taproot-ref/16128f27ae921b87284e0eab75845884e009c865 b/txscript/data/taproot-ref/16128f27ae921b87284e0eab75845884e009c865 new file mode 100644 index 0000000000..a23292e43b --- /dev/null +++ b/txscript/data/taproot-ref/16128f27ae921b87284e0eab75845884e009c865 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a1010000009c56d373dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbc00000000662fdb6e03de2e7d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd858f22c", "prevouts": ["c78532000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "4d314c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ae", "final": true, "success": {"scriptSig": "", "witness": ["4d0be36ed8dae05f9cda4607148e82c789c4d9e36be70fa625603182279d00e95f660cfff7d4bde847544ea1944c79df8edf67aceb90d0d743ed452510da9bf601"]}, "failure": {"scriptSig": "", "witness": ["1bfd93a70888881a409f12eb9c833a9f696bd4f8c7fec00becc36b0f24dc97c628121b7932065253e71c59618770790c1493f723e0c45479bc432b7c55d54cddae"]}}, diff --git a/txscript/data/taproot-ref/1630122f5bef1592ca6b6280297bd620d8ce0ab9 b/txscript/data/taproot-ref/1630122f5bef1592ca6b6280297bd620d8ce0ab9 new file mode 100644 index 0000000000..494eb3382d --- /dev/null +++ b/txscript/data/taproot-ref/1630122f5bef1592ca6b6280297bd620d8ce0ab9 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4901000000049cf49e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b801000000bc4daa160275809a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e754000000", "prevouts": ["0c3a6400000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "53e838000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_1", "final": true, "success": {"scriptSig": "", "witness": ["bfa2103ccccf1488b36a28aa4957dfd6becf11a8a0469d582e7c98bc6255926c5affaaa2f1dddc4c29a1c8e96b141211a3426a1da8693f2e73f2f57fa23d7bde01"]}, "failure": {"scriptSig": "", "witness": ["4a12e80c94c0ac0584a8eade86f52726f4706abdad42a39268d30b05aa4afaf7ae8c296a8b72e703572ff1e16d3e8fd31c8e6575a53a0f960c28fe83961fc5b801"]}}, diff --git a/txscript/data/taproot-ref/164113b42e586e2e8ce7bb6fccef9f52a5136708 b/txscript/data/taproot-ref/164113b42e586e2e8ce7bb6fccef9f52a5136708 new file mode 100644 index 0000000000..048b62ee11 --- /dev/null +++ b/txscript/data/taproot-ref/164113b42e586e2e8ce7bb6fccef9f52a5136708 @@ -0,0 +1 @@ +{"tx": "84a1e22002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6700000000d31a558abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3e00000000a47f97e303c77edb00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7b8821e39", "prevouts": ["fe68600000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "69857d00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_dc", "final": true, "success": {"scriptSig": "", "witness": ["1b2c8969f6db96d01c364f245eef671b80073c13aedb6987de3b77d5659cc81e1eba9eb682616a1b7fb85def99082375b2adae70132ce84c20c34e4e398238bd03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["d4f296ae3ee1ec947be95c69e6dcbd5f2fb38a277f1329b990a8243c12d9248c745d0c45d0e4a26e6361a8fa896064068d8826c0cafb491a88197cd8bb96630bdc", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/164178c636e1e1ccfbe67f53e9209ff1c0e8584a b/txscript/data/taproot-ref/164178c636e1e1ccfbe67f53e9209ff1c0e8584a new file mode 100644 index 0000000000..c631010b0a --- /dev/null +++ b/txscript/data/taproot-ref/164178c636e1e1ccfbe67f53e9209ff1c0e8584a @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ed01000000980d4ec98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40a02000000fb01bfe604d937760000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48738fdec36", "prevouts": ["e7e9370000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "685f4000000000002354212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["3d601f5f6580ecb01eec7c5ead52441fe44b531ab6ae99d3e697404822425e8759146b1c6992eab52d5279feeba4f7cfe79e2d5a51c026de49302c2f6e01d653", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/16431b60ce2185dc8a3e19f1b9325a1078131515 b/txscript/data/taproot-ref/16431b60ce2185dc8a3e19f1b9325a1078131515 new file mode 100644 index 0000000000..c21cfe87ee --- /dev/null +++ b/txscript/data/taproot-ref/16431b60ce2185dc8a3e19f1b9325a1078131515 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d02000000cf6fd6acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdd00000000770059ed60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270030000000080b8e2a304c1997600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5997e11d", "prevouts": ["a72f0e000000000017a91481d4142ddc5ce7a3de4047bd48b623419b5bc45e87", "8cd95a0000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247", "ae2e0f000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "3f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369aba35d3104e600974e554b9cb99049f7aee0f23ae7c74d9fbe3a88b265c838bd728e192bc5f69ac80b4a6e0537a86a2095372e08a2c76143a8a8a3d0ed1b85bc06da1f6599d7e514a71ffa8a2afff73792fcf1df1b953d2196d009aa835a52703985aa46dcbff8b0495de750bd1afe74a661312f7eddf1146199ee1ea8c08aa"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3d62cda1d889ee05ca59ece4e76d2fa27c0bab47b49d4f70b1e2cb0efe9a711fea811edfde1d836b623c2094badb4ab8bc7795b2b49da5506600222f32ea3fbd"]}}, diff --git a/txscript/data/taproot-ref/1658b5c8f7c6d3672d694462a7f53ad3f3596d38 b/txscript/data/taproot-ref/1658b5c8f7c6d3672d694462a7f53ad3f3596d38 new file mode 100644 index 0000000000..759d76b03d --- /dev/null +++ b/txscript/data/taproot-ref/1658b5c8f7c6d3672d694462a7f53ad3f3596d38 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bec00000000078c47fcbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd5010000001a65b428042cf0a00000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478710020000", "prevouts": ["f72520000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d", "497283000000000017a914269f407e1403e9e55237bbaed7146c0fbc0fe6c987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090275fab9b7195359f7514f30a6475ced76a2aa48da224e6237aa6415c08b28ce5e2fb5859531f43cfbe5564e6677e4945d72bd57a5e391af4eb6b1cc214c3271c6417d1d31156fed8d5608caa4648ae84a369204011aeeb2fdc9a5dd3f501fea490089091faa2601c5fcc1fa05ad0a29fb85a040cc521706b51dfb7fd76f0cb39f0a1a60056079346d67ebfe3325da3b47c20c4c59a349ed192aed4fb7397861e496c7ea413bd961a51830f27bf1c4b270849600f15e878c851bf189d07c56a94d55adcd5e2d6ea8f74fb78f340e9e0a5985fe0396ada1e0903fcd250bfe577bfa194a7bc57eb0e332f33e183489fe985c15a08ba86f40922c19d60319a0529c25943af902e84066b079ea7f1bac331bb5cfb96a8996275c2d6a5cd63e1b04770c81e6887465149f28096b78f61423a5b1e2ee3930f3b2d667fb10f8153d48fd30587c880b7afe5160d4dda45b45d5a388eb3534c827de64b3fa31562a3447950ccd10c5357b76b045e4c8dbff3f4dd42998ef4d1733c25c6acba72107c8f401fcfadb6bbc838342d0556f95fd322b1640256f30753e8f4c4cc4846de415637d5da505100c7f9699ae46c4a3738c3bfa51374e10e2457097a6d9c98ccdf2d40ad57b412c493c48a8afbfe059c7001884b5cc0911e32c601c9a5d078609dd54fd6554aec2459ffe08b2c4265dc63898b68d2467d190eda1f56cb13cab10e10f6edacac0f68425e8ca3b0b75", "ef7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367cbfda17c38fed6334a2908ab805e5d14fa71acd028483d3725fa56b0d725d21eda91d0eecd1ce224dc9f5ac46de57cb81ed44d1050e451131a9df60f58ad735b030008666d4260a12bee868d13ea953ce9c9319f2222d8e8469ea0b912b8ceb"]}, "failure": {"scriptSig": "", "witness": ["4d09022074db48bb9c1f5d88eb3fb771aa8b9567d69e345485ed7d6eed5a405fd4ef514a48923e11cc30d8ea7b6e3670bdfac73b61fb2edb8619603c65920bd0e3368fed8707f68eebe3cadf5b8b830c92f16ea3a535499c31ff7c72292394c77cfe9046310dfa27b589342be471c337d9040f9b20d15171324efbb16e69ad8b1fc08947f991fae6eaf0d61bc0dd75be08fa3e87ef168f9212dcab43cf566416951f4d2bd3a097fcee8a50e1471a01e68dde48a1773fb112b49596adba32732d3c108f20d937146661d7a64e5a770d8676d6e83718653efc899ac583e52b8168af1471480eb4334c6cfa62f853b409fe0f0b18da29256b97d99f84101c0d3168efbce42178734dde7c0c1a1382dff8895a7e3d25dfabf7cc75d69f6044434f8acd327ec5c5645e51a22d15e9b0ece5bf66f96f9af7c4161e6fd4e5b87a7c15e8f1d9292224dad6ad431d7b261ae1e55a60493c0d3acc36c2dced84343019332d9433bd3c018c0348f922cb75912179eef737c08b033b24d4a26fcb10c8de4fb856a52072ea1343d6225d750d1f237b99519b9ec04193a6e3d57cb825db2b0bcedafe6caabbd505cef725f622c74a065006471f433695404b3bbc058e91403a01a7539497d851f98882c53b320d7586031d4689f4e42a3b506ad6abc8911551a612df4482ea5f6b19c1685f84a0eb61771be9a4134baea5e129ba3089f02c23f2b296e91cf738bb5ae4edb91f75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936361ae9315a4f56942059dce8d08baef7ceb9eca078b725cd2c8eec46152008c6eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac8ef60344f111a9c34d055af59cfd42b130acbf4987ee3354719b7c9974e4d449"]}}, diff --git a/txscript/data/taproot-ref/166cd55c33178000f9e3e3b366ace5266964a5c3 b/txscript/data/taproot-ref/166cd55c33178000f9e3e3b366ace5266964a5c3 new file mode 100644 index 0000000000..1db82cae40 --- /dev/null +++ b/txscript/data/taproot-ref/166cd55c33178000f9e3e3b366ace5266964a5c3 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd90100000012f00060dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3c010000008347e7830238aeb10000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748761030000", "prevouts": ["c79c6b00000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e", "dd9f470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_19", "final": true, "success": {"scriptSig": "", "witness": ["2d46ac609b4e1622bd501ff9596c14c9ed0624310f50cc9f3936270dfa548d2c7adf11af4d0eaa4fa4a21739ee0c77dcb014bac0a87346a140d6d018c16fef2682", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ed9ac15921dc6266095a75e80b82ee38ba7a3a2095b816b01f629e5343326880f41a48ba16e00bb810ffac1915d0948a5187cfe9e58e1c162a25bf944d18c7b019", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/167a4033a1f4c30b87898758c3868c1025df1694 b/txscript/data/taproot-ref/167a4033a1f4c30b87898758c3868c1025df1694 new file mode 100644 index 0000000000..f5a51116dc --- /dev/null +++ b/txscript/data/taproot-ref/167a4033a1f4c30b87898758c3868c1025df1694 @@ -0,0 +1 @@ +{"tx": "7b13900c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b76010000009ad734fedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4b01000000c5b820b103cef56b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e745000000", "prevouts": ["0177270000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "43f5460000000000165e142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["205b562ceece4892dab2aaa5b4dd4c3220d2e3d2ed8890be47773502094f216601464380447c2983866fc6c4301cef32ad64a9c377f25b1fcd583377c253b449"]}}, diff --git a/txscript/data/taproot-ref/167fe32905b764460a1199e4a4ab3d84ef186e2e b/txscript/data/taproot-ref/167fe32905b764460a1199e4a4ab3d84ef186e2e new file mode 100644 index 0000000000..668df5ea03 --- /dev/null +++ b/txscript/data/taproot-ref/167fe32905b764460a1199e4a4ab3d84ef186e2e @@ -0,0 +1 @@ +{"tx": "b809cec502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4d00000000826028da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708200000000d8400db60264ac6e00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acd4000000", "prevouts": ["3910600000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "4937100000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "777d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364d6f52c65af8984250618465516d171424b5f4605f7d510d2b5bd71719fa37153c7477a635aa10de5895d22b0b13d3a2307950c6447747564098b225c8ebc094ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457e2aee6c91b47bf7b7aff3c5d3800b2287c2f5852e09bca12781ffc191c1d4f04"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a983e3c65cf55188846777a92d5d2662905d67f05c2a27733140ae1b500402ced76a514a469a046f8a639d1762af89c30ccdce4827317950871fa39f73bf898af03474d1f6825ec143575bd2e16c5d5a5b633189d07c1a3af4de94c30aa06021"]}}, diff --git a/txscript/data/taproot-ref/1680d648bb0d496b0b5cdc71bd31f42d092b5e31 b/txscript/data/taproot-ref/1680d648bb0d496b0b5cdc71bd31f42d092b5e31 new file mode 100644 index 0000000000..34e7274011 --- /dev/null +++ b/txscript/data/taproot-ref/1680d648bb0d496b0b5cdc71bd31f42d092b5e31 @@ -0,0 +1 @@ +{"tx": "c3554c7202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0e0100000076c92ed6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcd0100000015e8f9ac0162f93d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac8ebf4b29", "prevouts": ["f7b753000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "2b9321000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090275f8ad32fc82d87f629fce56667f924fd59b23f1967f238b19edd0de3dc262a2ba6ac97c8c761e2a93deed9e676697909ef70de8ba836e6449a000fba219de20afeaab20c73245fe3055fa64bc4fee3604f5f05ad56da1e1b108a15805af6f8f27f91e39312227267431aecd4fb6e5c2cafddf5b0c8065b776f39edcb8ac72a3152f42211527ea426f02486046c4b0748b050651cc2205b0453c70007fc57de292a4c6d42240db36bfd29137b8a8a5ecb1994e50e61d323a4b7255a79b953ba88704d163621dc282c662cb720bf11f25b43c9f29f89d31a6cb87ae73bfbe6f96baf6a4496e8b4df69cef594efc9edac9f2729848b95e87a1b07e01f50e5543100d5d4a91d16d87bb307bce6c891545bf46ec5839c67edfbf43730f71e9f2fb137bab9645cf2b9e539da74cd4da03a12d46a7666c42a824cdfa8b369e614b2595601329fc2c7ab87aec9986bd28ad09e387cb467250a3e02227479062d5c27510fddf0a9fcd204c69c198a5133a59810e8ba7edb973d2845973ae43cc55e7afce144f216680214d5be0e5de4dee5add6a0b5c3e0bd060103e53a0695d7b1b29b4a6723d75207a5018952ce1df6aa0b77687682bfaed4af04bc1ef8702b36e2ff1165b8f85b9eb65e8854bca27702ca2c1237cf5c15c89d91cbfa4432424a44180edced6fa479c99ea9b2f4e066bb31dddea90abf115d7634021447d6eb560adce000045cadce7343a3975eb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ed6552aba169725607bb1130dbc4a5e66e4116f82e73ca53fd59d9f0c82562e31292070a98a4b0647c95affa8e1bd4aa189d67ab6e78b6f1cfbf1b9e41a8f8bf399891b33f3277cd8a2b8473e2e6079de1e6f51840c7864da48d9f2287dbe494cf9ce2244c675144b577c27c052f9ebd481172245e28e9502c6c6e8f12c64fa6"]}, "failure": {"scriptSig": "", "witness": ["4d09027274a01e8ad4da83e3fa778a82a2fb92f044ca92c005899e5679ca074a7909a5213a09e1f09efdd4148f37b007c5b2de2fed89f964df70cddf15fec39c1202cb72ab4a624e1bf918dc4cf60fddfdc17dea6b91422e27b54f7bbc1415f92c7f7952e51ca712b812813c52257e17f2e3e8e17ac2ccaba45612e43d5724e90e5e9c168ed72f2b3a8f7c341d7e5acd656986e7f60fc91ae5e180d018b178c0ee3a839020a1a0ea0671949dda3470a9006eb88cbc46b1d88244b93edd34afd2a1803990f19cd5cc197146c7de90144e0260a020d48466de1127f723f6f51aee38941e3167ebea6ab4d0c4416d25cb90d0aca2d42aea46c4ebce4e841625afd0212456f23730832011c3b8840838bfd609dcfbbaf025b0227079bb3141f67fe01614bf7d90d213149010626650c37e06d5fb3d13122160b7c4d276fbfb7476e7cc53c211a6605efbd92f062b62441ab9197fc93adb8a5009633880438a446e10a69bac0478db09e4cc1782fb4a35c3ecab86ecaaea47b913bf5a64647e06550eb43d1cc114ed3d2860e77ceebda45fac1ce02051c92932f827c804bc016352f64c7d37d0847a539065414f92b9796e5991f7eba30d7c0287f8b7f30e1df9ada3f4ef7f58d82d83808fed14dd9c3b4ec9cf31d0433f98ff05e6b4d68a9054e764e6de4cc3028aa8f57118a687a767d06a7c05997cc7845afcaab0622737aaab3feedfdb891e771bedaf0a89f57561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369886f85ebb300297009aa959255e1f8e976b091c7e06b33477ed400c40a83b4c14f0d108097d00934ef2973385fcf188ce2945eb833bd9e90fcb9cf025505833cf9ce2244c675144b577c27c052f9ebd481172245e28e9502c6c6e8f12c64fa6"]}}, diff --git a/txscript/data/taproot-ref/168c2988106ea01a8121eba649b024715de5122f b/txscript/data/taproot-ref/168c2988106ea01a8121eba649b024715de5122f new file mode 100644 index 0000000000..e9333099c0 --- /dev/null +++ b/txscript/data/taproot-ref/168c2988106ea01a8121eba649b024715de5122f @@ -0,0 +1 @@ +{"tx": "ab01e604018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49e000000002f2cd5fb03a4a13a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796a481275b", "prevouts": ["f5363d000000000017a914f7f3eae48087a4952a984cf9c1f2f12f8785754687"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2253202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["c2cd116515da87b99de2601d6f479891cd5d8247cff7df2366f63237c6a7fe39aec53d853fdcde99e72311c5be6ba75778f6e11065c44bce3ac9a74220eb997b"]}}, diff --git a/txscript/data/taproot-ref/16acfa58909fa72c2eecfaacc8866e7dd1f42fda b/txscript/data/taproot-ref/16acfa58909fa72c2eecfaacc8866e7dd1f42fda new file mode 100644 index 0000000000..23278d20aa --- /dev/null +++ b/txscript/data/taproot-ref/16acfa58909fa72c2eecfaacc8866e7dd1f42fda @@ -0,0 +1 @@ +{"tx": "0a05db0e028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4230100000039d351eb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707f010000009a75c1ee016fad22000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cdd4d843", "prevouts": ["852c310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2f131200000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_7a", "final": true, "success": {"scriptSig": "", "witness": ["96bf9b8dd7c3e25dae24535d68b03d7034cf2ae0bfb0c257d2306316d6d4de59d533c636b33ffbc710228439042268a9d0147c4b0296c1ea63893508425691aa01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["112329f32b8d24769485befb9431172c5e520686e872a4f5554d429e43f687f2358fcbb14f2cb2b9f6c0df35c92d6fb2b81031df59c54bafef0b80337a361d667a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/16b2bf568fa5aa6e4b5de39fd290f6de49b091ec b/txscript/data/taproot-ref/16b2bf568fa5aa6e4b5de39fd290f6de49b091ec new file mode 100644 index 0000000000..ea0bdc6896 --- /dev/null +++ b/txscript/data/taproot-ref/16b2bf568fa5aa6e4b5de39fd290f6de49b091ec @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f800000000fdb29b5b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705101000000f4984f1f04d30d4500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ba000000", "prevouts": ["a949370000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "4e5a0f0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "f07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3e6b1501de3c77a58ed25563289f7380fad902eb870a0fdd7293169316d7b75ff88c7bee1bb9c109f1c6365501285b6447b8ae029d34f47d1dd1efc50e8947b4"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb5208f8b948433da6baa451dcc6971038720543971a17923638ed54c8a85897df7eb609cf6b5925737ad21e523a1c8cc87f95ebe19353e64c9623e085aa5557f88c7bee1bb9c109f1c6365501285b6447b8ae029d34f47d1dd1efc50e8947b4"]}}, diff --git a/txscript/data/taproot-ref/16c6bf5c5a6caf8746580f9e01ec4e218a4c0e39 b/txscript/data/taproot-ref/16c6bf5c5a6caf8746580f9e01ec4e218a4c0e39 new file mode 100644 index 0000000000..ad0d94abf8 --- /dev/null +++ b/txscript/data/taproot-ref/16c6bf5c5a6caf8746580f9e01ec4e218a4c0e39 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b07020000007adfb0878bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41d01000000b3b8bc9e0240305d00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f874d000000", "prevouts": ["43942700000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "1845380000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_6a", "final": true, "success": {"scriptSig": "", "witness": ["2ffc5dbd47ddd5c2f8e370e4599bb5f24a60695d816beda2c13da6cb5016ff2a7008a3c80b599761254448f3da8822bc7282217e3d6e33adc7c68e4f1bec3b3503"]}, "failure": {"scriptSig": "", "witness": ["29482721dc7ac275df8f85c07a78144d243d30cdce18b8d78005ba830e06d6909ba2db0e2c09583cc26b65cb8aeb9fdb063081867a42b45023689e2426b6ab4b6a"]}}, diff --git a/txscript/data/taproot-ref/16ecdda3d618db946d6033f96c780764642e0471 b/txscript/data/taproot-ref/16ecdda3d618db946d6033f96c780764642e0471 new file mode 100644 index 0000000000..2aed1c5ac8 --- /dev/null +++ b/txscript/data/taproot-ref/16ecdda3d618db946d6033f96c780764642e0471 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707301000000b075f9f160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703a000000004772b9bc03c6971e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac66000000", "prevouts": ["0d7e0f000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "2ae0110000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09022074c1af01a4ab4ee37a577ed2238c8787f0cab6a4bada6f5d2e8e612647c21be6d26696ae79098d80e3f1284580385e0c77a330ff679475d29e10503a4f582147e76794e5a5f855160fc67104736bd34e91bb7e6c6949893d5ba0002ecd78680aedf2bd03daf8238d8742f68cc3475a5b6fe9f667d7fb1e92772fdafff7fe3fefc6c657041d58a4bf9732adc627f7924e13306cde51ea9050b91361d526e1b349e6c362cb9fd1d3e8f11814738a554bd4c4775b06ee086b411aceb72e4cbad1a238e26b4b27e8827dd23f7601e92d11582c34218f30564f0b923e0c4abc70f31b588636015af7f9b899e40f92dea322adc746b0d60b4a0df5c03b9c61c75c844f2e9c8f35e576f4aa897a082c9a6042f78e5d0e5cb2ee6aecdbf1cac2a20bbbfc303525c7309eed6cfc78eb7b44f83536221b7fb45bba92eff5d30e01549ef42a01c468b988ecf776de5c2497f28486c8a4be1cec44f6a3a7f6ff4110fb26761b8d38f638df69dfa24f9ea03d8910402bc726b84d1c1b24d2458c96e56006e7bbd7df1df5b0c655e9f01a2394d4bb361836783c36db19f9433788878880703a72d7512926040a2e570c03e88eda6dd187a0435d175a7763f2c94abdbb82619077a0f1d3611681986def2171430c3885917235fac9b821f1d527749ce43f04efa241f727ebe23c58b5c5e756391e6850e48eb59306ef01633f1a74c80ea603c66bd45bf15fa317810775", "717d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936acd583c45d21b204d1804bedee0b0f3c4b80b4344b7f9b78d7e17b5495d745d61e193f5d3ae2ada43ea9223ce508afaffd6393e3458e5d7b2b04f710aee774aaf4fdc20f1f5535ceda7aadddab857a143114b7886b058839365016ac02e93c97"]}, "failure": {"scriptSig": "", "witness": ["4d090275347463f525937e1d40acb4526ae2a606ce4c9ea532e96a08565c5600ba4579e2fae43aec021284ed8df594a5061daa3c984e6ced12570eecb593b21e72e5017dd990c7b1e785872731ace7dcd25d5a409b394badca2fb3e089bd5cbdf5bcbe6538a61152cc0a6692c57c66e71203974426396dbd05597b65e1efdf4835c687edd32019d365cccaef873ce0343172655e841c550e32db2bc1b83abc4cc36ad1edb93a48df3850953383a83a8dfa5e6c17e119a672100be9c49f33ed270023b11f17b5dc70819e544bb68716cc880bcd5e06986669c43a02161ae0594427d1de18dc54eec708cd782eb28a214c1be61bd4b2505d9173ac5cb87934ffcac3a192177bb7659faace9ee3de2d917e59bdb8f845d82e0968b2b0ad14131f4a7f09e6aa98c340995adf8179b4406025acd4d6c788c3c63715271fd2d99898621b07dd8a59f71ed3f931b49c7d84580934da53b637b1ba3b40e3181c7676d52eb9b77a88392e7b2a7aee7360098bd1d64003d72e74c537466548dada818b8d83117e5bab73563e54c3441c8c872cf2671a919e2345ccca71d293ad60b0a6a6927ca9303071581793294793b35acc4f5fc8897a8d67f8202d87e152ffada3674e4c1a565f195f1a80264d3e5773b1df3400c7be59af8c34e4d73074932895fe4213db361754ed666ce91f068701d739b84918bc33eaeec6f2d4c2e4c2fef7b59c74eda5864dfca3d89e58fe3575", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e47c0542868f8d04f04b11c7797ac2650c695e4f1f1a83ba9fe9a249175e916721e193f5d3ae2ada43ea9223ce508afaffd6393e3458e5d7b2b04f710aee774aaf4fdc20f1f5535ceda7aadddab857a143114b7886b058839365016ac02e93c97"]}}, diff --git a/txscript/data/taproot-ref/16f6f25ce07eadca0f3c82818b8910b5006b6aa5 b/txscript/data/taproot-ref/16f6f25ce07eadca0f3c82818b8910b5006b6aa5 new file mode 100644 index 0000000000..5fac9b9aca --- /dev/null +++ b/txscript/data/taproot-ref/16f6f25ce07eadca0f3c82818b8910b5006b6aa5 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3e01000000cfab0487bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6c000000006aa54fd6047c69d500000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc797000000", "prevouts": ["a7a25a0000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "970b7d00000000002251203792436bc7394fc8cacb2bd2cdac9c86871063933d86113811cf92ac8fb26226"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93640873c0ba6ee1189c8eb3d7712690e4c72ee5324e9b4123eca76344463b203ae"]}, "failure": {"scriptSig": "", "witness": ["6a3d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/1715e26f824103c322e360c6d3c237781724ca4e b/txscript/data/taproot-ref/1715e26f824103c322e360c6d3c237781724ca4e new file mode 100644 index 0000000000..65c29eb0d7 --- /dev/null +++ b/txscript/data/taproot-ref/1715e26f824103c322e360c6d3c237781724ca4e @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c81010000006dbe9804bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6101000000606c4766027ae7c2000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487afaba04e", "prevouts": ["7ea54c0000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "8668780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a", "final": true, "success": {"scriptSig": "", "witness": ["9f4d601ee4c95b404904b3634f10340ed5cc2d5217b8d4c8b61fcd07ea2a2ec0be945eeca3e8dd20201edae5e8e4ad5353419b0e7283a9ddefa3c9cb6197aeb683", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ef45f34e72a351230a4b75d54f81f0a013881cbce07c34da05fcb83150234cce6a5602d5b63ed6c66a0b376d84a4189e90f866b71a967a0a415ad11e045bff6b0a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/172062063b7ae63dcffacdd6b98414054d06633e b/txscript/data/taproot-ref/172062063b7ae63dcffacdd6b98414054d06633e new file mode 100644 index 0000000000..bccb6f98ee --- /dev/null +++ b/txscript/data/taproot-ref/172062063b7ae63dcffacdd6b98414054d06633e @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0b00000000841f9a698bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d301000000542e177d01f3141c0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce455ed3d", "prevouts": ["95cc5a000000000022512089cd9bcf9fe9207377d5b979d86bcf752d8d9dc577da80e024c55776b1ac583b", "47af310000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "success": {"scriptSig": "", "witness": ["bbc60f5d705ad205271ae418fa66f0d3c7e753d4ff180d61427337fd992e014cc7b932cd72f78749602d019232db381de632db37e63bb6c98c7b099f8d01bf85", "839267d6df0912e5b51f34023acbc7ee499792bf670136104fbdebede46c7bdc92b506accde64fbf85b129d12d39e3b68c5742e49fa574c78df828c285caa75dd5adc196e2aaf19535c8b6ff81359797258a81b5441686e4ff9cf2a3bffe6b356d5973c329e3b83aeda7c597a0007b98f9799f6d38d9235b387a427d7f8907f586e581c18cc2783ad9ca95c6efccd9d61cb7ef1e9a7798300d02e0de99c01a", "4cdc5c946e76fa3b8cbba9df2747f00e36922870e04a1d7b73d0d7be7b66ebcf9b7fb48e2c19122178c23c497bdb9e81cca0c8f506c2948de839eb8fd4937fad193a715e0199efa3630d411a86fa04d93b9cdc76493ff3a76194563f4aae77307242bfa399fd6b916ad0cbb23b9c3aef3075068fc66b5f186c14f15e2b1af53afcc633f3857186145b9927a02e1cbacadd099a1a2f58b9d79fe00a0785a531dffcc2a09bbb3a90e22aad7f41f330f16ba557b99d8f6467b650041d69428816875a721eea04addb2cdbd6bd61250600108a3ae9bb21643cd6c4e7ffd0d4e36d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000032d2efdbe161f98c288eaa7fde4bf4fcea321901811a63e066302ce97599a1f9c1aedc962753057dd58085b3b42211bdffaf8bfc7fd34f8a41eb79c9c1d3ae83ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000001f858f5656212125faa6eca732f451d22c3247528ede16e402131fa27291047000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008dbb21eaff952aee1413b27d6544f80001b0348805f17871125c31f0c83693bc4e6c0135b1e281dab29c4cad425a9053dd2519a7dd2c8c13a888f296e54cd0ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43d6bea0072195b361f058c9a7e17831c3c4d4453374f6b3ef9c08e136a3e1ca6c188788cd0ca725f0a3156c1ead00eb9238ea1aafbb39b34d4e0f0fc4c4d3209a54439c8f1b29dec753bac498ba1ac20b83434e06482602f7e0a989f99d6ea963b5c5d77f2175ebd3570a0ccf057ddc65fe30c62b6f1c9c0c34e0a08a62021ed917fd46971d6070abb03d15af5991be56e08a425e0cd9e813f7e96ba49012b3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1d726dc89cf4e5c9124bf8711bdc2e07a8daf774ae4012b22539b71c07ef212f9c938a7204c78c9670b3b453158ffa99b869b633379d29fb1aacca0628e5a9d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff58db95f3737e2b8a5a30ff49853ad0936e6c131757bdbaefc3e366453323513f16250042be117da29fef9ef7f439bba7edf9e777b14ed019706f4bc72caed468eac762bd0d93a5dcd4b44b8868b4a20da2906f9229d66631d05efecd463868703475f6ccfcdb564a8516f725723827aabdc7c0b6441aeac1b9b1e3f1d8e9fe3c9661d942f27eab2399848d83364321d832fe274ea51d21fd6e96ff381d5f86c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb284df40cb00a2b517a661340b2d63e0d02f2c780340b8dc5d2617845680c33cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["bbc60f5d705ad205271ae418fa66f0d3c7e753d4ff180d61427337fd992e014cc7b932cd72f78749602d019232db381de632db37e63bb6c98c7b099f8d01bf85", "aaf117669031bf027b0d859b5cb34b284214e9b533bf4c22bcf4714af431f6efd11d5abef709464a6006c1cdc0bdea111ebd46a80ee2b6b214456c169e345e24660acf2db097f7b3574995385abe6c0e91938c6c43e3987e44aa5a4712258025d7593a00ffe4f95a099481d0de95ffa700ba12cc5b135241c8c565ba00e070e878885ac95ee15046a2ba96122e503729a488d066782be6c30cb52105201e", "4cdc5c946e76fa3b8cbba9df2747f00e36922870e04a1d7b73d0d7be7b66ebcf9b7fb48e2c19122178c23c497bdb9e81cca0c8f506c2948de839eb8fd4937fad193a715e0199efa3630d411a86fa04d93b9cdc76493ff3a76194563f4aae77307242bfa399fd6b916ad0cbb23b9c3aef3075068fc66b5f186c14f15e2b1af53afcc633f3857186145b9927a02e1cbacadd099a1a2f58b9d79fe00a0785a531dffcc2a09bbb3a90e22aad7f41f330f16ba557b99d8f6467b650041d69428816875a721eea04addb2cdbd6bd61250600108a3ae9bb21643cd6c4e7ffd0d4e36d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000032d2efdbe161f98c288eaa7fde4bf4fcea321901811a63e066302ce97599a1f9c1aedc962753057dd58085b3b42211bdffaf8bfc7fd34f8a41eb79c9c1d3ae83ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000001f858f5656212125faa6eca732f451d22c3247528ede16e402131fa27291047000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008dbb21eaff952aee1413b27d6544f80001b0348805f17871125c31f0c83693bc4e6c0135b1e281dab29c4cad425a9053dd2519a7dd2c8c13a888f296e54cd0ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43d6bea0072195b361f058c9a7e17831c3c4d4453374f6b3ef9c08e136a3e1ca6c188788cd0ca725f0a3156c1ead00eb9238ea1aafbb39b34d4e0f0fc4c4d3209a54439c8f1b29dec753bac498ba1ac20b83434e06482602f7e0a989f99d6ea963b5c5d77f2175ebd3570a0ccf057ddc65fe30c62b6f1c9c0c34e0a08a62021ed917fd46971d6070abb03d15af5991be56e08a425e0cd9e813f7e96ba49012b3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1d726dc89cf4e5c9124bf8711bdc2e07a8daf774ae4012b22539b71c07ef212f9c938a7204c78c9670b3b453158ffa99b869b633379d29fb1aacca0628e5a9d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff58db95f3737e2b8a5a30ff49853ad0936e6c131757bdbaefc3e366453323513f16250042be117da29fef9ef7f439bba7edf9e777b14ed019706f4bc72caed468eac762bd0d93a5dcd4b44b8868b4a20da2906f9229d66631d05efecd463868703475f6ccfcdb564a8516f725723827aabdc7c0b6441aeac1b9b1e3f1d8e9fe3c9661d942f27eab2399848d83364321d832fe274ea51d21fd6e96ff381d5f86c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb284df40cb00a2b517a661340b2d63e0d02f2c780340b8dc5d2617845680c33cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/172b85f2524cbd3f0ca1a41380566b1648c8c405 b/txscript/data/taproot-ref/172b85f2524cbd3f0ca1a41380566b1648c8c405 new file mode 100644 index 0000000000..3d9005f03d --- /dev/null +++ b/txscript/data/taproot-ref/172b85f2524cbd3f0ca1a41380566b1648c8c405 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bae010000006b85b084dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1c020000003e333c8a0305983e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7beb20230", "prevouts": ["9b361f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "07072100000000002251205109082c92be6cdaf88bccd1fbf3eb83cfab83a783afec3533a63ba21c303957"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a2", "final": true, "success": {"scriptSig": "", "witness": ["76c983c00fb22e9436e98f72d0759ce06226d6b3f4dcfc7c6e430b8a74e4af893c54f63c8731a08f6ef2a870d0226e0c0f6279a4d5565680728a94115c32713a81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["333565cb2306881e71591235c965c1c30f9a392877cedcc6b965f45028b69f512c8bf3d472ddc724ada5df5256200327507374cc5e35026256abd4c9a053bdbea2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/172ff5cf4d0d01f9ac160be767a1b233dea05ffa b/txscript/data/taproot-ref/172ff5cf4d0d01f9ac160be767a1b233dea05ffa new file mode 100644 index 0000000000..9a0c0e1d10 --- /dev/null +++ b/txscript/data/taproot-ref/172ff5cf4d0d01f9ac160be767a1b233dea05ffa @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4660000000079caaceddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9400000000319a8008014ac71c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a631000000", "prevouts": ["e90e370000000000225e202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "72f2250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["f0cef00457cf698bf2d34dd5b5a0ded84464a8bcf9886cccb35a292ef580e492c3abd449cb085d9914f672edae5d0c926025942789a99731e7c216170ad41de7"]}}, diff --git a/txscript/data/taproot-ref/17405fca2ae8f08cec8849c6a750217abef9ff89 b/txscript/data/taproot-ref/17405fca2ae8f08cec8849c6a750217abef9ff89 new file mode 100644 index 0000000000..374642adb8 --- /dev/null +++ b/txscript/data/taproot-ref/17405fca2ae8f08cec8849c6a750217abef9ff89 @@ -0,0 +1 @@ +{"tx": "1856b3df02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4e01000000bd0fc0dd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b0010000008f497eb404b1cd82000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c40df233", "prevouts": ["dc4e490000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453", "11a53b00000000002255202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["bf", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db7a6a7e9e2eb861c5b236223f8a0e993b636b19808476c0a20268bf09779a38cc596949c599e703b9191d3ba022749fca5ec33c3492eb5532759cd445d2634b82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365bf71cf7816bf4c839ad04f64c439f60ca1e0c1202f6058d0897192eaa874d9b285ab48eb468144e5e6aa7ce6d4aa75a792c11a68b383289399495d27c15055ecc596949c599e703b9191d3ba022749fca5ec33c3492eb5532759cd445d2634b82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}}, diff --git a/txscript/data/taproot-ref/177f3355a5b98fe40607bd5da8383d7129c515d5 b/txscript/data/taproot-ref/177f3355a5b98fe40607bd5da8383d7129c515d5 new file mode 100644 index 0000000000..7bff305791 --- /dev/null +++ b/txscript/data/taproot-ref/177f3355a5b98fe40607bd5da8383d7129c515d5 @@ -0,0 +1 @@ +{"tx": "acbf9f810260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cc000000000eb572d4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b920100000084c9bc8602e0ab2e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acb0633037", "prevouts": ["2dff0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f34f210000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "3d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93643fc02d791da942af66dbc7ed13bfb20fc5039325710c1116f758577e095b78a701c89cbc41056f58ce11974b5756eca381e306e17d72fcef5e58c3aca02cf1415eb41ce20b61903eca7e2f7903a7c5f76d50ccbb22a22a302188dbad2e46b28"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b508c965bf67778dcb8a54be530beda3976f1f18c717ffc195c744ea9b09aadb671c5f6e3fdb2cca9ff2c8978272a7c72309b5e793932f9bb10a0961dd619da6701c89cbc41056f58ce11974b5756eca381e306e17d72fcef5e58c3aca02cf1415eb41ce20b61903eca7e2f7903a7c5f76d50ccbb22a22a302188dbad2e46b28"]}}, diff --git a/txscript/data/taproot-ref/177f56a1fdc5cc3198a785f6f5e7a55d8c324f16 b/txscript/data/taproot-ref/177f56a1fdc5cc3198a785f6f5e7a55d8c324f16 new file mode 100644 index 0000000000..50ab04dcae --- /dev/null +++ b/txscript/data/taproot-ref/177f56a1fdc5cc3198a785f6f5e7a55d8c324f16 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf430100000019be6fb160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704300000000dcce808e041afa810000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8795000000", "prevouts": ["d9ef740000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "78f40e000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c04c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688fc8f615032475bb12c71b7eb73effb9d0886ca0e0e26ca1dee2899bd81981c1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004500c8753d4e6010499b58065b36892efcd9281a64e85ebf7c5dcb8f6f4baee16c3de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a3f25e8770efb05111073ed80fe6014ab4fd3382442a3e29d1922781189381cde2b448ed3f1969af8fffbdb3b73bd72fedaa98057d5c8b58a84426194002c6e029de37322ddf566a2356077a247b666bf816d75bd62d8842c555909c8a1545e03de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}}, diff --git a/txscript/data/taproot-ref/179b29b5e6ade731ba119866f25b6743232bd3ec b/txscript/data/taproot-ref/179b29b5e6ade731ba119866f25b6743232bd3ec new file mode 100644 index 0000000000..4ea5a07259 --- /dev/null +++ b/txscript/data/taproot-ref/179b29b5e6ade731ba119866f25b6743232bd3ec @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0401000000bebd38a7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbe01000000ba854d0e04f3d9d10000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e790000000", "prevouts": ["474f840000000000225120ea467ace5d4e72e4b47248d08b4c7e21d4858a06bc17e94ab3d6153139c60e1f", "ee48500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936816733c26ff73b2a499b6ca717ce0a086eff22a381422ce1dc07285d274c2f8b"]}, "failure": {"scriptSig": "", "witness": ["6a6b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/17b2c3c5c8f5c6d4e3b517021c8e26c982fc552f b/txscript/data/taproot-ref/17b2c3c5c8f5c6d4e3b517021c8e26c982fc552f new file mode 100644 index 0000000000..1074793d49 --- /dev/null +++ b/txscript/data/taproot-ref/17b2c3c5c8f5c6d4e3b517021c8e26c982fc552f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9500000000d03e1c89bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd101000000992df1f804e162e200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac708d0a37", "prevouts": ["a310810000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba", "b1dc620000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_7c", "final": true, "success": {"scriptSig": "", "witness": ["7fa5da3cd9b4d580444f4654d625dc1b8b9856d7348e7e31b609a33cf89f84997a0e5d95530f5de272f3f2c7cb6605e824b2c0d015c0ba50a451cd12f1f49cd803", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["eab441492422849d56f4622cfcbd0126a9feddfeb2046e6bb576c24bd65113ab7a06955661f92abbad08389afc44b4b36273f587af7a6389364a61dae9318cee7c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/17cd80eebaac8182716c6996ad037efac35af699 b/txscript/data/taproot-ref/17cd80eebaac8182716c6996ad037efac35af699 new file mode 100644 index 0000000000..9180d55bed --- /dev/null +++ b/txscript/data/taproot-ref/17cd80eebaac8182716c6996ad037efac35af699 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8c01000000dffcc7d7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfce0000000016cac3e60495eabf000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8729020000", "prevouts": ["937b5c00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "5f7e650000000000225120e1a0c74a8d16f26f13c9c4b6f4a1ceec6071856e9cbd0cceab614068d31377db"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "47304402203d3811030c08e0a632f8b0fc87b891d3763cbf3a20328a2e256ae000909e68a4022018c009878d1833d1390094c1fddfdfbaa956aebec306538c237df1f506124494cf00", "witness": []}, "failure": {"scriptSig": "483045022100a89bdbdcde6c63d7d2a6f29815a2ce2cb4a871c74e636e4791d23b2230e1b645022058f7a4c5a43c0a9ef1cf8800f89fd301f19d03ee803bd530d1324799078acca2cf0101", "witness": []}}, diff --git a/txscript/data/taproot-ref/17fccd13627419da75dd075f405d0c40a09c652d b/txscript/data/taproot-ref/17fccd13627419da75dd075f405d0c40a09c652d new file mode 100644 index 0000000000..7c99074b2a --- /dev/null +++ b/txscript/data/taproot-ref/17fccd13627419da75dd075f405d0c40a09c652d @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1a00000000fcf1cbccdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca4000000005c8d71ea02dd33db00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69c733a34", "prevouts": ["bd928000000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "adff5c000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "b67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3bc00f369fc994f47536ced64d5e4f722a68c2ed1128957c24de4b5158af0ec621d9a3f11774810afeba87c9188100d693899e640a37210c96e3be6a00ac01d4"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e848df663f65f0e27b2d1567423d7462b229bee90dcacba8c1bf1c1a66aca7f6821d9a3f11774810afeba87c9188100d693899e640a37210c96e3be6a00ac01d4"]}}, diff --git a/txscript/data/taproot-ref/184dbb048070da2a1db945f29853600246189da2 b/txscript/data/taproot-ref/184dbb048070da2a1db945f29853600246189da2 new file mode 100644 index 0000000000..c0f14f40ce --- /dev/null +++ b/txscript/data/taproot-ref/184dbb048070da2a1db945f29853600246189da2 @@ -0,0 +1 @@ +{"tx": "6a7bc0ae03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2d010000005909f2bfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc501000000c4642ca8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b22020000008a37259c02ef808b00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4c7b8943", "prevouts": ["697b510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a86c1f0000000000165b142540f27e90740933c99d4f17ab2dfc6c82951cfb", "e3fe1c0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_7b", "final": true, "success": {"scriptSig": "", "witness": ["6d1784fdb02f794281d08e5a2eadccab5b1087b0a7be24f1c3db188a916719147f28cb172383aadfcbb53a554bd17ead768a785ba87b98aac13881819252009c"]}, "failure": {"scriptSig": "", "witness": ["63f65fe0609276b08be634be8b183957880282d8dcc77e30b7193ee9f23ae9ff3f153cffe505e3f46fbc60837bfd76db11d9445ea7ab7c6f569cb8bc77587b377b"]}}, diff --git a/txscript/data/taproot-ref/186d4e3b056dbde38d01af9a2095f2b550b930bb b/txscript/data/taproot-ref/186d4e3b056dbde38d01af9a2095f2b550b930bb new file mode 100644 index 0000000000..31ac84481f --- /dev/null +++ b/txscript/data/taproot-ref/186d4e3b056dbde38d01af9a2095f2b550b930bb @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf10010000001f3f7932dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3401000000f67932efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2102000000826b9d0304a1acf2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688accafa8b37", "prevouts": ["0a62760000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "ff685e0000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5", "64a1200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_47", "final": true, "success": {"scriptSig": "", "witness": ["4f15da331ebc736f43a26b66b6f0d3dfe612edb6c9048c30f1a4a1a64824b2d84888175d8752df80ad37d67ac18d69a38fd7f8c8b9594de5aff947d1e54007af82"]}, "failure": {"scriptSig": "", "witness": ["ec08c97c7428798b25dcda478f9ec80f14cfe5dcee6e99e556f5247195d0274819d59fe7bab5878e2cbffac9f6f3eed3257d9f9ddf2005fb0c6bf1a7b42b422247"]}}, diff --git a/txscript/data/taproot-ref/1870a7b0cbdbdbcb7e9f1d248928fe0dca885fbe b/txscript/data/taproot-ref/1870a7b0cbdbdbcb7e9f1d248928fe0dca885fbe new file mode 100644 index 0000000000..b868a45959 --- /dev/null +++ b/txscript/data/taproot-ref/1870a7b0cbdbdbcb7e9f1d248928fe0dca885fbe @@ -0,0 +1 @@ +{"tx": "48b53c3102dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c390000000029ddda8dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd6010000002acd50fb0243a8c5000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc70404943d", "prevouts": ["84ac53000000000022512027986c975f6014bd54fa55f3e483bd83d3384004828bdd3e489d9b175e79ead5", "ae1574000000000017a91498e55eac47e04767f832d50008ff18559102c9e787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["3f87d679e4e87922a0eee489ec20a705e9e568dc388bcf757e70cac8d09ecc13b34cfbd387b92a08c4d8d1292f488d73a430928e4a49f7eafeab4d76b68e33aa01", "15fe4dba251774e95533d9bc102ed0609a97c946219a1cf03e6fb6112d76020a0c78efaf1d33b244cf21fe90e9fa03a6d0a855dd44da2f8be864e216495dc5495453566b4f6b5fc57cd7f7e0a312e93a2bced2a69847fc45feebe7b7dd5c8ae7dd689286589ebbd15ed9a4417c5fb5df2294d4272c81ade188ed5be3cf0a45f63329fa10da2f0482c4272083ad489dbf160399317c92da90a61ec5c218078d652c45f0a6ce", "75005a3535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a2ba5a883535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a26e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936411aaccaa2f00a161189dce43a9cea795f36d9d70d3e1cdfaad5740f706f3bc685a95c0e3a9be06cf58146b3bc5fb1546d7d0e3556502e189d50862181eabedb441369121629d451605e60faa82fb2587a97364c24cffc54a5e52e827c54e449ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000344c3dd851e2ea42f02204f30463dee20c8e4ec50417a06167139b8316877a824c5b466720024622ac5259cd26bec0d05da102db22ba7095575a2ab0833c096ee80c64f88c70fa9c5a569bf63c9b21d14468486491ad016b49487ac210783ef738a473e1ce637153c37c66e2de294c34f551d3bff138f1251d2e0a7f4443f8c56f461f998bb42f4b3acc72e9e53e57f8ec81f342eb5545af3272b690b5de07643a69d446fb5445fb7c454993ad958ec703cba86021ad80fd977d224cf36b429e850602eccaa779cc00b8e901390d0a3f36f43e636d45368154c7ae46fb231fb7000000000000000000000000000000000000000000000000000000000000000028045a5222f219de8ce4ec64d59ec454de0c807af9d7cac8453ec4ba2c236bd4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbb9da65bdf156bf72fd39d7f8e5752fca9a112277c8bb84a4f0c27644715f865b557a5191e283f21ba9e21731cfae2cce5fd3871db1cab1b923c6441195a6489a1301aa0ebfabd684fa6000ff7d506040276a9f980293b4f5e1c25cabca2dc3da0e48c71b991503486333f3fb9d1d772ac0a752ba97864b4c8f30a08d1b9986cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa6f7dc171b51f4e47daaf698237e670b847083a87634e77718e24b4a1464ae516fedb2e1e9eed857bc9e29f3169583d6da8d59e2ecf81763b37dc26cc9770bca31fb6945707df739a4b83934d90a1dda4122bfc99d5290237e4cf99ee4802f6aa07f773beac71a24828b1c2bcde88987adc1134896e30412787c35d1333060376aff0ea89d2fe3642e776371bed5c0828903ae0efa314eefdba81558a852d8b1363f3636a73ee0d5967e2666ae2d9417538c99a277c2f2399c9ca2da076db766399f07a4ba9b4e291ce4ebb45247e0879b10d6b0a19344e65ad4b68475184fc6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1184700b38805717162fd8eb98570728e94e1d69bf2f17a904264923904b5e23b257b4f4aa591205239b696237fb3d9a1787aa2d972c47529486b9a47b76136c6ccf73a78b3c04938de1da676befeb8c12e0346b7baad6f7781b6de83876fce1c06e304006c7f5f29425bed8b063420f0fe2bac560eeec08cc5e418e103a5d4a682425880f6f7aa6c4f19abdd0aaa24988645d00ffbb813497720be270d2fa65ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc04f72245113b62716050c7417eb81c66dd8b1460d05627d683c3c3a50a2ee3b5ace784a5112f602ba4d0d55c8d47b9f58ff462a0a0d0f1bdb3e111bbfbc42fc85215ebb23a45fb555483827840ba84619b643c8c951ee3948f03bfa66dda1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f89a0621c6a1237d5e0083f81f775598a85a3ea54c279faaefbf20811c74ceea5d237ac4a5690206981b4ede23e91cb3e799c38126fbb04c4951bbcd72153ce4"]}, "failure": {"scriptSig": "", "witness": ["3f87d679e4e87922a0eee489ec20a705e9e568dc388bcf757e70cac8d09ecc13b34cfbd387b92a08c4d8d1292f488d73a430928e4a49f7eafeab4d76b68e33aa01", "d53139ecbcd5420e03cb5a1f62a039f4613fab6145a39447d28c04ed572eb947c298e0d9527b927af004c454ed9092be4cb71da7a0f5f170107c45764c2a8a9e9b30c4583c48e7d1f54a1b1bfe2f7365faa467dbb9ff03c32cfe99284219a26e53765b32161fd856e2f8b1ebe52296add06888d17b4565e0b5d7af781156c923d4c3b1ec6c0c5f8975fda0810a06148160f6f4c12ea90581c7ca937aa1421cb7c94d66f7", "75005a3535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a2ba5a883535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a26e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936411aaccaa2f00a161189dce43a9cea795f36d9d70d3e1cdfaad5740f706f3bc685a95c0e3a9be06cf58146b3bc5fb1546d7d0e3556502e189d50862181eabedb441369121629d451605e60faa82fb2587a97364c24cffc54a5e52e827c54e449ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000344c3dd851e2ea42f02204f30463dee20c8e4ec50417a06167139b8316877a824c5b466720024622ac5259cd26bec0d05da102db22ba7095575a2ab0833c096ee80c64f88c70fa9c5a569bf63c9b21d14468486491ad016b49487ac210783ef738a473e1ce637153c37c66e2de294c34f551d3bff138f1251d2e0a7f4443f8c56f461f998bb42f4b3acc72e9e53e57f8ec81f342eb5545af3272b690b5de07643a69d446fb5445fb7c454993ad958ec703cba86021ad80fd977d224cf36b429e850602eccaa779cc00b8e901390d0a3f36f43e636d45368154c7ae46fb231fb7000000000000000000000000000000000000000000000000000000000000000028045a5222f219de8ce4ec64d59ec454de0c807af9d7cac8453ec4ba2c236bd4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbb9da65bdf156bf72fd39d7f8e5752fca9a112277c8bb84a4f0c27644715f865b557a5191e283f21ba9e21731cfae2cce5fd3871db1cab1b923c6441195a6489a1301aa0ebfabd684fa6000ff7d506040276a9f980293b4f5e1c25cabca2dc3da0e48c71b991503486333f3fb9d1d772ac0a752ba97864b4c8f30a08d1b9986cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa6f7dc171b51f4e47daaf698237e670b847083a87634e77718e24b4a1464ae516fedb2e1e9eed857bc9e29f3169583d6da8d59e2ecf81763b37dc26cc9770bca31fb6945707df739a4b83934d90a1dda4122bfc99d5290237e4cf99ee4802f6aa07f773beac71a24828b1c2bcde88987adc1134896e30412787c35d1333060376aff0ea89d2fe3642e776371bed5c0828903ae0efa314eefdba81558a852d8b1363f3636a73ee0d5967e2666ae2d9417538c99a277c2f2399c9ca2da076db766399f07a4ba9b4e291ce4ebb45247e0879b10d6b0a19344e65ad4b68475184fc6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1184700b38805717162fd8eb98570728e94e1d69bf2f17a904264923904b5e23b257b4f4aa591205239b696237fb3d9a1787aa2d972c47529486b9a47b76136c6ccf73a78b3c04938de1da676befeb8c12e0346b7baad6f7781b6de83876fce1c06e304006c7f5f29425bed8b063420f0fe2bac560eeec08cc5e418e103a5d4a682425880f6f7aa6c4f19abdd0aaa24988645d00ffbb813497720be270d2fa65ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcc04f72245113b62716050c7417eb81c66dd8b1460d05627d683c3c3a50a2ee3b5ace784a5112f602ba4d0d55c8d47b9f58ff462a0a0d0f1bdb3e111bbfbc42fc85215ebb23a45fb555483827840ba84619b643c8c951ee3948f03bfa66dda1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f89a0621c6a1237d5e0083f81f775598a85a3ea54c279faaefbf20811c74ceea5d237ac4a5690206981b4ede23e91cb3e799c38126fbb04c4951bbcd72153ce4"]}}, diff --git a/txscript/data/taproot-ref/1878d0c6c90056867949699c2702dab1671a5739 b/txscript/data/taproot-ref/1878d0c6c90056867949699c2702dab1671a5739 new file mode 100644 index 0000000000..7ce1093e34 --- /dev/null +++ b/txscript/data/taproot-ref/1878d0c6c90056867949699c2702dab1671a5739 @@ -0,0 +1 @@ +{"tx": "83cc59aa02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bca010000003af476dbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc6000000006aef47a201686f3a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac94020000", "prevouts": ["5b6a1e000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "26871f0000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_81", "success": {"scriptSig": "", "witness": ["410a83dce0fc1f4b869e6ebad4e96ff5ac038efae48abdd4cd1994cb17db7fd9bac8a598e83f75fed7e9ee950253d942154f170267123240e9fa4e1a842beb9c81", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50f58c"]}, "failure": {"scriptSig": "", "witness": ["c927375cdecaaaf14e52c715c3a41f3b247660f79b6056fbedbc19d4a9bf647b1637af0ae2d7c36993b6e16338c0df4186c54449bc3ae2912851b1889c01bc6881", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50c8a20490796da18231bd891dfc9ee9fd3dd67e5b30c1a68a6cee31aaa1336563c6ca3d54708b8c2b37edfd5202d99de398f9334228717506d47758da2096d2044c83f25dc7e9130a265932f539855bc55287cd589137c651df4fb02a89d8efcb8dfeb713325eca5030f8fd265bcccf417534c9b9798622d197d365a1399abdff9b863e58d4a947646aab8a203622c4b0de25b3350549c5a7c4b10510109688e65ed8759dd8c4d93ab0abb7c5f86c136630abcfac7f01ddd48edf843ab9d39cb1ea46cee32b93334e12ac9ca566197b98deb2"]}}, diff --git a/txscript/data/taproot-ref/187dc420ad18b5fb75f0f40dcfa22e824b23bbd4 b/txscript/data/taproot-ref/187dc420ad18b5fb75f0f40dcfa22e824b23bbd4 new file mode 100644 index 0000000000..7b405070ad --- /dev/null +++ b/txscript/data/taproot-ref/187dc420ad18b5fb75f0f40dcfa22e824b23bbd4 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be301000000fb36def3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb301000000e6af33afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0c00000000754fa2b201d3161100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac7fabae57", "prevouts": ["c6bf250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b787490000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "1205240000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "167d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936394c54942360201b0e5a9c52bdb8553d3b85213f639fc7674feca5a4529f4e0b46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa654bbf7a6388e898988522fa7e5d2ba9e6951646cde29fc617f56e0c3d8e4d50afd13a3b2c4c421c5355668ae9e4eec8bcb7618363c6e35efd204a43726d22d6"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6552d9f0078438d40136d7ff6a38e228e91ae2f5adfdceb2d12241afedfa4e08719dd3b5606bc946287d150a5ecd03b0f8e892d08bbecd28ea2e3769111c28051e3355b9fad1d20bddcd1a8531bcd58c93c4d9ee4159d68db4e08ecdffbe17e"]}}, diff --git a/txscript/data/taproot-ref/18822bf70764f3c01f808cd81031bdaa811edcaa b/txscript/data/taproot-ref/18822bf70764f3c01f808cd81031bdaa811edcaa new file mode 100644 index 0000000000..3a2cba2fbd --- /dev/null +++ b/txscript/data/taproot-ref/18822bf70764f3c01f808cd81031bdaa811edcaa @@ -0,0 +1 @@ +{"tx": "cc2a29fc03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8901000000c830c9abbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff100000000746406a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9601000000bd8ec8fe0286b12d0100000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cc349424", "prevouts": ["6a2b66000000000017a91408247b8d3db4e641d0be1ff23f14280256870a5187", "2f55760000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0074530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1655142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["af342baa3fbdeba74159cdc207a6d6446da28746af0ac0b6527095a2a1df2747abdeb989e446aa880398dc744c8055cd2f37976c5b7311f4c6e1a3923216225f", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/189034044dacfcbaac5a98bbd0a33a369683d2d8 b/txscript/data/taproot-ref/189034044dacfcbaac5a98bbd0a33a369683d2d8 new file mode 100644 index 0000000000..3830f52e2b --- /dev/null +++ b/txscript/data/taproot-ref/189034044dacfcbaac5a98bbd0a33a369683d2d8 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a300000000afc78ee1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8a01000000bb1633dc0151876500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac867f065b", "prevouts": ["ddbc100000000000225120ce3551521fa9f590f4e3a432d6c546446f0d4fa78e73ac01749e3c952a57623c", "8fb85a000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902e89ef9cd6a14ce137a122e44e8f156230f0fb36a7fe792c664bf4e947afd0d0d697dc42b4471ab4b348f61a8519e7390605ae60b23b14c83a0c81e8115296ac5a9daa7733b3a0feca8343c80a0c3c55f8d113c6a90832209384961aee83e5fb322f0c412ae0e480a0e0707a55e4833d5281a6bfaea7c3a8d9b18cf36ce87fa1e76f9a5770098d2852721ceda1096a092df80654ee99377cfa92b424ce5599d0d022227cd4614fd76dbd6efd459f367214a3a2f308eee0a22a6e43c41e4660239b960204c9abe9ba77eb55dc371c7036b245a9820d0f70682a2e60dc8feb8ec9c2a0bde27353ded2adb1ce2c4644b5a013c9e428b2f4335af9efcc4599029d88c8292161d7eb7a367ec859fdf8e801e8083fcd9b15d821f023eb2bb5d01305a17d85e88d8b147012ffa1ff2582a65fed1793686d8c1b1afa8124161d33e42b897519a76fa1093abe812c7e07daf6e205bd6a41b53dd0612bbf1e860c5383ffa04fde77d9cc56ff7b817061652f8956980c8a60cb14d6d80134d0314a69a646d065f8c540b2c1c5a928f11f24eb7dc9d501e0082bcf5c77f09c27b2f0dc4e98f18c8fc9203088ed95b3ef15dccfcc0099acd050b21e95f2cadccb7506a30d01d8ecb1ad72de8513c9947a1908609df03d7509f01011b85d5f3d033203b8e0add3a1d42dca2feb1b8cad341805d8272faaf7b9f788fe592f0dae7e5ff72970453bee2e027a13736e8ab3275c0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936276d389ce3a0d147c1239f614bede42df56e685272932fdf5fddf7ce36575c5f1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004500c8753d4e6010499b58065b36892efcd9281a64e85ebf7c5dcb8f6f4baee16c3de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}, "failure": {"scriptSig": "", "witness": ["4d0902b01c77afa7c0b5bbb9b76851dd5b0c4c1291b498150c85d5e77a5760c3c53238768a50eb44fe420f0b709e8cb838731e8abacd0742575f54ef20bd961caa30534f889de0e3322cde7b11b680bb1790cdc3ea2af04982d59d205a600f9d1d9840b7a5024b903073603cdab268a22c15c0afa3a3346364622c843f653ec944cb0f0be9a87541087e0cbbdb2c3fd8ddbc0ca3cdfec638a3a2c4b7ce3c0d1c17259719b7fd78f7b60be45e8942c155728b6f17c028130029eeae1e396b4198b8ed01b16ecdda8c8440aae1795da4f24a39d60bd80fc514504bea4ab1006537aeea72a3c7fe70640c96c3544dc04ec86cce64e29e8bc31783d3dde3b50669aaa1f69140045d8403e6f20860dbb3437be037484e7e7f80c071bea3989fb569489b122a37c12dd34042b81eed66a9cf5f4ce551570c4fa0eb4df0252ec9eaee5bebc884c3450ba26cf52a27e06e9f074edc1eea8f9ad734806a1ea0ad3790abbfc6e50a0262054c73cd894b8f9e608f8e354d14d86f713a2d53e9672074471d9a271cd9fc14530b764937e144e4ec7a0480276c1f49d63cf9a968d7034f12ff75f4926d1ac2701a2eb8cdcf7134c8bf554729efd1c66bbf0a1e95ab0fd5d961386b0e12ef7813f5e9f9c62d3705cd23bccd9c150506e717ef3847316d8f6b73b11d52030d798e14177092cfc2c7f1bf6749d8241110b42bd5462a881b26a3463a1ef7c83668f9d76c9d7e0f977561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e99c9f88738a88b3aa0a4c3963e818c9517aa5d4efdacba58fe8702f7dee8816fd75cc9ac1e6f185878d252db6c7bbd874f5ae03fa9961d4f4a0208503b0750f17ad4bbf375bb62f626ec8048d4347cc1eef977780228a6d2fc47294088d561"]}}, diff --git a/txscript/data/taproot-ref/1891c772f3ce8c760b0cf1b52164fe1d2e4ce605 b/txscript/data/taproot-ref/1891c772f3ce8c760b0cf1b52164fe1d2e4ce605 new file mode 100644 index 0000000000..a1dadfd94e --- /dev/null +++ b/txscript/data/taproot-ref/1891c772f3ce8c760b0cf1b52164fe1d2e4ce605 @@ -0,0 +1 @@ +{"tx": "db2f843102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1c0200000066a63388dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1f01000000bf6ffcb001a26d3d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71019ae4b", "prevouts": ["a799760000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "62b4510000000000225120db9ddec7a132eff6af262a32a64079b83118332a0594bc0106395f5efc921419"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ff9558f81ce3a2dd7306f2c5fb453fea421a50752f6b7d85ff2868f6db9902d"]}, "failure": {"scriptSig": "", "witness": ["6a11616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/1894c4ad4a51725e14a4b3ca4124be935f442f98 b/txscript/data/taproot-ref/1894c4ad4a51725e14a4b3ca4124be935f442f98 new file mode 100644 index 0000000000..1624b4f5e3 --- /dev/null +++ b/txscript/data/taproot-ref/1894c4ad4a51725e14a4b3ca4124be935f442f98 @@ -0,0 +1 @@ +{"tx": "861c712d018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fc000000005f5df3da046a193e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acb2ca1426", "prevouts": ["23a04000000000001660142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["782efbd86b045ff3423e869c9ff729134d2e2d6d42e34893fc9b54481a272a287e205fb3b5b7bb34ba9e49ffb3340109bc34e99ed3b092d8aecdf643e6de7a31"]}}, diff --git a/txscript/data/taproot-ref/1899c6c029807a2b6fb9c8709343768c03f3405b b/txscript/data/taproot-ref/1899c6c029807a2b6fb9c8709343768c03f3405b new file mode 100644 index 0000000000..4b343aed22 --- /dev/null +++ b/txscript/data/taproot-ref/1899c6c029807a2b6fb9c8709343768c03f3405b @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc9010000008569c1c7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b05010000000d6c2cfa0347939200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc5000000", "prevouts": ["5b906d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d95e270000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e3", "final": true, "success": {"scriptSig": "", "witness": ["7132d2bf84d4c67ce4b2b563bbeb1047587933e3d039c6fce4c818c47f967e8d4fffa2803b3b989fb1e8ba8e6499a92cb8944ffa0facf983d1fb0bd7a3408a0302", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["69c2e1924b1024f6abd8959b5bd5ec07801f72f9f880c60cf36d8c841d967b2fd8dcf8e6f4df839bebe8b1620915a04ec5b60674a1bf2c783ac8dbdad2ec303ce3", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/18ae04d1c49da35415f8e30e1757321ada62e83c b/txscript/data/taproot-ref/18ae04d1c49da35415f8e30e1757321ada62e83c new file mode 100644 index 0000000000..c5e1dc4929 --- /dev/null +++ b/txscript/data/taproot-ref/18ae04d1c49da35415f8e30e1757321ada62e83c @@ -0,0 +1 @@ +{"tx": "e0ed141303dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b93000000001fcf05f6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7a0100000091bd69b9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc8000000009a4857d5047746c200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487bf000000", "prevouts": ["bec22800000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989", "73802000000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "8c967a00000000002251208560e60ff9f5f50e17abe0faa94b8704db3bcecc7cb6f74a11a752b4bbc814f5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["fa4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6765b3a9293f3bfd6c3b684051ad5b8ba6e731c254b25e3cb8e354d60cbb2971a4e7a29e9a68a1d6e5ccf500c3bde1b862f2704e441e939992f2bf5a528056a3bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}, "failure": {"scriptSig": "", "witness": ["4c52fa", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08226ad4257a22b62302a767a5b8896008d1af7055b6fcc30f1a04cbcad06de5cf2f8b8afd7beb88d43ca6c6d2d58dc9425172bd95ccf582b2eeeba83616a9d27d33bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}}, diff --git a/txscript/data/taproot-ref/18cd769c18f505e8bc05856ed71e114b5bd9a022 b/txscript/data/taproot-ref/18cd769c18f505e8bc05856ed71e114b5bd9a022 new file mode 100644 index 0000000000..77e100191b --- /dev/null +++ b/txscript/data/taproot-ref/18cd769c18f505e8bc05856ed71e114b5bd9a022 @@ -0,0 +1 @@ +{"tx": "8a55f3a20260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127021000000004a3d07fb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40e01000000ff9e6bf701948e070000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7fb010000", "prevouts": ["7a301000000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "1e2442000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "e67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d518f5fcc4dcd317f656293c43c0e8e59e06b99ff36e809cba7caf0d79972dd48256d6f90d235a6ba3188b640209fb1b87a6d8106344fff793e748ee999a397d93d03784866e2fdd94d7d1b7c12b1f0da96746c05c19b8696f0ac6a701ba8135"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee92d7728fe824bb86fbd19678fc348031552299afe2faac0cf612835804e2a859ea19512c809756aa5c58e4cd3562935caab0c2ca4eda8db33914ce4decb3cfe9d11a7792f25f0da70e8485da42647201d1062d1bd001b767f1b05dec6877400"]}}, diff --git a/txscript/data/taproot-ref/19056ae532d1819a4355eff6310ab655a5030df5 b/txscript/data/taproot-ref/19056ae532d1819a4355eff6310ab655a5030df5 new file mode 100644 index 0000000000..3ffb9d5167 --- /dev/null +++ b/txscript/data/taproot-ref/19056ae532d1819a4355eff6310ab655a5030df5 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfc01000000e1fb988b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4080000000022028f9adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bea01000000a94b1fb4012f9338000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748777000000", "prevouts": ["30532100000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "b5243b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9a341f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_fb", "final": true, "success": {"scriptSig": "", "witness": ["a98fb395b3493eb836bf41a5bd15b15209c6528c74263544e6dc96725d7a28e1c7073a7c1a6a9d9ed2651cb1f2b5c7b9712769b98bdfa4efb2162bf9fd3d6adb81"]}, "failure": {"scriptSig": "", "witness": ["88b69aaef809e7d03af8417a443da1bf0f7d36da0ae334b0d1b5ab96d960d3fcbcd630dbb9ab3ac6788a73002f8c5a40c64356a9154f83a07c3dbefb07e0d41cfa"]}}, diff --git a/txscript/data/taproot-ref/190cfc23dd00d10a83315e6bc368d40445cd322f b/txscript/data/taproot-ref/190cfc23dd00d10a83315e6bc368d40445cd322f new file mode 100644 index 0000000000..e531d9ae9d --- /dev/null +++ b/txscript/data/taproot-ref/190cfc23dd00d10a83315e6bc368d40445cd322f @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf81010000007d91abc060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700400000000377d028060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270550100000075c420dc03d8f996000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876c030000", "prevouts": ["daf6740000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "cd0112000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47", "923912000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09028598895956c3c54d60141d7dccd3ece136a9ae92e7de806483a046ec5e34a65d7fd4877d911c0a50224968dbcc146ac94bacdbe51c9b3a7dcbe60eb8cc167df34d4dd397489a39ac5c97ea7af8c1225cc8b2653926d9c1fd285d498d62fd162b8c59de799db2895b669387dbfee379a1209b1984b7596b30f05498b9bb919fac74acbf96a1a2ea5709cabf24c0e60a289e62a824c7a5aab185ca8a28a8706ca2b26237be1bc60e08d1d11d299e800c971ed2ee84f4867e7f9fa64afbdd1a4eeb3ca60b1c5e6fc9eb790c541f494938d512ba82982d4d52b70d02bc039ca381afb245f90148055275b38158ec782c20bd308f1dd35b4a3a2826c2daf93e9726ecfe43b13e4c67ecf8a129dfb73d1b94bcbeca814e579540af62b78627c06ce53aa6fe82b4e10b640193214ccbb63f2d3399884216e1cf3164d4e06962f26e279d05f7e91a13d3d5a7d0aead0c0741be2779a2b7f04e403c17572e56721877d58676133a5169b4b6f8b450d22d77566a6d0803f42541ee336606b9c09aceb61b85e001c979ce04470415900db581b190f0f772c500964d7b6b4460db86430dbc3f5bcf69ac09a50dbb03c7be7db156e32bbc4cbef91148fc0a0efb5ac44abffb400aa1afbcf0235208347deb7205e40dbcbdcdeacb0520531ed6c6e96348b641df1252b29e3ab1055a94de18d2da7b8023e4961b0d913857410f2d91d5559c2cd5d46520acb2c30d4a6c75d1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e2640f3481b4b8be81ba7985476c68570d9a370e915b621c48db5cd673c6aa535c55ad82284641cab824687b45d4293ada5fb8cbfc4ac19bcb5188e4cd0a7708cf37d2bf9ac9d65f4f9542d60f6497573c04b4d7313f44a5c611386102890a1c"]}, "failure": {"scriptSig": "", "witness": ["4d09024e585a70f6e68623563a521d3ab6d70962de4d06af5ae6286b424445e12893c78ab47c79061d477e81483f9868d4b19902c6af29bb24f8ed5fa6472812109e5c5864796d7e384064a8385264d27c4264fc974cb1ba069899917903c5b6a0d13380042c8af67b33f897a141c6a1edb55701e4d043383f844503bf003d2613c6ec35467b64579c80e51550306db99f472c9613b613aa374cdd7702f49d45ba89dee8a87d6629e4ef7193bf9cc9bcda479effa6426c14dd013a04188fb73c589c9190113d9188da7697b8290b27850f64a3bfc3e18afb14804c69280a3a0f384712279a5ae70bf59fcf17f47e31292632676c9daa3e985917adcdf7ae096398e2782d0a4370c9451a421b192ae396bed9e1c01b1e82eba6624337316c5fa35a955b0b0be26755cb8d76a3076c9ab235a2729324c658f42a3ed1a81b5263ef058800d48843469ebe01658e24b75353e695d79386994b540eb5e3777acd10fecb066b946ce01d4960215f029fc2f5bf320731144c1aeef2ab2d0e53f5e169686f399dfd1947dab539a0664c291d6876d8cce162fe1c5f908ce4954dfe336ee45f80321687aeb9a947ab8ed79fbf91bfd38c60b553dac29401a510e8869df0a9376764699ad7072b4f52c92977044210ae44f2b2eb928611c6187e1b04d595b19f187b4bdce2ecffd6dedd1fbb649a3a89b87522ebfff3df6aef88c74bb80909946eed489c7c7aa8bc3cc0ca7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5172402ee5f7d01023de35bf8c020790747879409f1771ca1b4a9af174b095ec7ee5aa467dfe2257bccb94fb5bf6723e840de90a3890266560a9e3d72c84089f55cf37d2bf9ac9d65f4f9542d60f6497573c04b4d7313f44a5c611386102890a1c"]}}, diff --git a/txscript/data/taproot-ref/190dca39f195f8973c60e414fa6fa6aacd3d9290 b/txscript/data/taproot-ref/190dca39f195f8973c60e414fa6fa6aacd3d9290 new file mode 100644 index 0000000000..cde8bd0028 --- /dev/null +++ b/txscript/data/taproot-ref/190dca39f195f8973c60e414fa6fa6aacd3d9290 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ed0000000047b48efbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf38010000006d3fa388017bcc44000000000017a914719f78084af863e000acd618ba76df97972236898720010000", "prevouts": ["ee9241000000000017a914a4e57198280c195671631f8b9014214c2f083b3c87", "da80710000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e148eb929e36bf5d0ae927afe6ca96e40c19e477115e42779571d6d91d45ed5d842c4c20f1fedac94edf4ee37dcf580edabb0aa4839378386ec3447d53f529f2ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936724f9d0df23615753016e7eb8d62571c0b8a17dd151f7df09f79bc44b2e134251de3578bd50e4aef3f42172206e28aaa53f32c3941b8b4ddcf806814652917426187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}}, diff --git a/txscript/data/taproot-ref/191602968fa2af7edef6e40a0c4e4b9e4ef4cd75 b/txscript/data/taproot-ref/191602968fa2af7edef6e40a0c4e4b9e4ef4cd75 new file mode 100644 index 0000000000..80c4c5afdf --- /dev/null +++ b/txscript/data/taproot-ref/191602968fa2af7edef6e40a0c4e4b9e4ef4cd75 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6401000000c77854c802ab2882000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7e82ebc5d", "prevouts": ["d461840000000000225120d88cb7f53f02fa1c481625f74693a34411b6fbcd1738e3c4eddc22f3e1da8f8b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936276cdcf8aa7f00f9cb895dc6486b366e3db7f84b06171b90b5a70246671bc599"]}, "failure": {"scriptSig": "", "witness": ["6a48616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/194da7e8add6b9a1ecf41a75f040b4611f016a09 b/txscript/data/taproot-ref/194da7e8add6b9a1ecf41a75f040b4611f016a09 new file mode 100644 index 0000000000..d2153823b7 --- /dev/null +++ b/txscript/data/taproot-ref/194da7e8add6b9a1ecf41a75f040b4611f016a09 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a101000000803b90c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b990100000075a93d6802b1c933000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc772010000", "prevouts": ["139c1100000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "5f092400000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09028648441159ad2b9d233f800939add1a514c20ed91caa7d2e987b386d685e1d731b58440102d73d177d22f69af5cedb0c49176ceb18d6cf779c1791a5356643889976479b3f3c1c5ed6c0961d6e45617e1a5df3fc53f4ea77bc230facf738c0674f96c5190d6e8cef9371621cb7c4ce9655b947b129caba27823efaa16e54b2c9fda2dee8dd1e168c3fb1a71430207b808b2d987ff11a7bb1eb7aa232887be85514f5742376ac568d7081339fc11fb4756aa3f0d09cd3ca4c6bdbd075b11ac307d49ce466991a48d73cbb7bd03ab1a6f6f6c0e443c7d45c28b6853595f95f9a96113f600e4696ccd06f73e49f563ef52150c7097fc3dcb09164707ae72cfb212ef2a5ede2992dc7fec07184cfa207b3abe85efc42350540a9e0e1f5a0357705e204e188b2cfd081eb9dad8338c823cc5a6de4ea06c79235feb3502e97d463fd2bc558f78c4b9338e537ccb3b4991b809f1b07c3e6017ef9d5f4111e765bc8ec4a8ce81078f71dc56afabf8f6152034824d09c621bcc60c9e4fa2762cb67486e7d149e357d6eaf7a3efdfce693548b3348d318db5c541e0a5d8b546bad75c15334c5f00e89e15f899002fbc5818a9309dea1d7f0db786cab72b6da3bc3139e0135cf7b726f76ef0bdff0d74a4d4ce9ca29669feb3eadf3f7cef5fe7396b0afc3230b9091e235da3a9118008f4a96c11f39851d5a477cffecbfdddbab8f542ab7d8ea787880c52e6b4fb675", "737d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820f3ec5aec6a85c1ca54f3417a27e00c281f3765ee450a46261b59de169989c9a702c501a2f323d94577f3c4b353be8e702d3f9991edd341efb02c3132264010bb33a63f37675deadbbcd666ca6b38ad7090050f3dcc6bba45985e955ec185c53"]}, "failure": {"scriptSig": "", "witness": ["4d0902f8efa2bec798ba64b03a5a73e1ee4e926bf8834987fb701b1bc07641eb1d04ef82a3c3570314e1c487e3eaf7b61b9f5d1e54f66bb2f64071a4f81bffe22ecf61f3f4ad28ed5f3b19b8b5fa19149e35bfff473490f5a2ff09837295014e3b5992155349b58f6ae6ab9a3af1900e52295358d36f12e5f9b56c8dfa5b240ef0ad8a9103962c35efacbeddd5b0ff277c1f2090177411a5906c1f3831782c9a9da9f731f43f6955a8401de9fa99e1c10e6c2fa0dc1954dd6ccf16eb5d6f3fc841d9765d116462af996cc93a11f0428d4bb7fcdb283545cea5b671243313d97bf972cde25871fc92c077407e977135a83531cf74b26615fd61f6c82b1ddc3b16b0ab3309e20bfff864e24e38d1fda3c251233990a5379e82c6b9a48e3b97a2f0bc0262697979971378a5a83708db3ff1cbcec8d6d39a4068510eb7266d9a23a97a1b66e131127191691a2a81008d71ba85351e8cc6656a41d3033dda07e9c51b8641b047bdf8901a31b13211fa4a142f54d6c9ba7c1862ad8d7ace338e8a6a9a8640701cc50deacf8a62ca1d4ec9f096d8abffc79169cf7ddf4c733b93488de08dce3bc7e5c30ab1312d89eef609c3f5d037a0f3b0d14eb0cdf2352d490724c7846ad55856d161afe93de2b67ea373f02daec657ae20704960b9c1e5f6293961892567257f93007cf8085c87c7b092e1e093b3f994d31fc1772384e0439101a9a50842c10e4d1853d3ebadfb75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936349dae1e17845f77bdf4fa0e5359f29aefe32d3d88495b84e8b0fa7ed04ef515be4f7cbc7087a9eecd21f8f9de83a71ce09520dfa28ecbf12e6edbc22e0d0c39a8cadcf9bcd23f9249fd09eb8b2b9ca63044a0ccef58f4cae9402f6ead4c2071"]}}, diff --git a/txscript/data/taproot-ref/1969e36c75fe223b6de50a2e92c6ce56dd4915a3 b/txscript/data/taproot-ref/1969e36c75fe223b6de50a2e92c6ce56dd4915a3 new file mode 100644 index 0000000000..fb87e2a509 --- /dev/null +++ b/txscript/data/taproot-ref/1969e36c75fe223b6de50a2e92c6ce56dd4915a3 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1402000000d73d2e948bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4200200000097ebd4f30302dd930000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ad30a625", "prevouts": ["a81f570000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "e9523f000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "1d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dd31519ef42d9a07de8d84f40740dcd35a5a7ec542cf980ef798e38719a42baac92cd4ecb05acffc69b3cce67f0fe15bd50aa9f87096dacf733b4583e5e3d147ea37f54c31b0dcd6e392a972a33f542af4c40de53091de86bbd5587895c52a53"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368c90fc6b4e29557b0ab9f594980af38df75bea42e763db152d9bd27c49e84296422ef55f7568e8dc283b8fa041d75ce76b297151a0e1c7ebf12f48a20b112ecb6879334807fc224780ba3e72651a115d27f4d0acc1c4b651ff2820865c4364ddea37f54c31b0dcd6e392a972a33f542af4c40de53091de86bbd5587895c52a53"]}}, diff --git a/txscript/data/taproot-ref/1970570c77db050bc51d853165e59487dd05c1a7 b/txscript/data/taproot-ref/1970570c77db050bc51d853165e59487dd05c1a7 new file mode 100644 index 0000000000..1a466951ab --- /dev/null +++ b/txscript/data/taproot-ref/1970570c77db050bc51d853165e59487dd05c1a7 @@ -0,0 +1 @@ +{"tx": "b940699f0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706e00000000caa6f69504ef1c1000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388accd7d3e34", "prevouts": ["b6ba120000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c94c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900453bd2bf476d5c79b80d1dc385df1320868058b4af6871225604d123c25805c1374cc0fc2e3b1a564cf058e89401e888e3d8222f635de2bcbc595bfcbb872403dfb24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}, "failure": {"scriptSig": "", "witness": ["4c52c9", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369456184d2f43385344915638f6d037a1adead7f216e201cdee489bfb57cf83ac4cc0fc2e3b1a564cf058e89401e888e3d8222f635de2bcbc595bfcbb872403dfb24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}}, diff --git a/txscript/data/taproot-ref/197071c336e5f96eeccaa2d253d5c00e0ac7febc b/txscript/data/taproot-ref/197071c336e5f96eeccaa2d253d5c00e0ac7febc new file mode 100644 index 0000000000..a4849b2ca5 --- /dev/null +++ b/txscript/data/taproot-ref/197071c336e5f96eeccaa2d253d5c00e0ac7febc @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45301000000f58a3dee8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44100000000b63cad77dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bef0100000079a1743d0344399800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df979722368987ea000000", "prevouts": ["8b783e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "624c37000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "3919240000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d84c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93602817a41c51ca033292e6ad0865adf1b315ae27488bc31b0f8fb3dd6e91881b7d7b73fe79aa50781a03db77b9e22252058e372f5a0275feae864cfaf4c2a217ec513aca5799d408eee0c275015e54cf6f255f9c56741048ad8672ad33d4825d8e26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93676a870c8d6d66d1892dece22bb0edd2c674ad3f2fe5a056bace5d4c57bd527fd06f18ba19de64c771db55f5af06ee3412ffaea1fa921290752d742eff6a1e67f7007ac6d9f1365651a4d55e6df0dcb109d268cc6c386b355a4997173bc95c886"]}}, diff --git a/txscript/data/taproot-ref/197a3fa4a03436efcb2a86e1f8cbb45de1371615 b/txscript/data/taproot-ref/197a3fa4a03436efcb2a86e1f8cbb45de1371615 new file mode 100644 index 0000000000..041446560b --- /dev/null +++ b/txscript/data/taproot-ref/197a3fa4a03436efcb2a86e1f8cbb45de1371615 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2a01000000f6816db38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c467000000004c8c3ed5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa300000000092b0a9b015b3c530000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7962ad43c56", "prevouts": ["4e8f5e00000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "562e3e00000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "81d36500000000002251206ee7f50dd8b37aeb440050df10921bea288340730b764e02d5c3920c65efa447"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93600d8a7d3ba54fbb1fccfd13258af4c0990ddaba061aa27cca5baff13fc191a16"]}, "failure": {"scriptSig": "", "witness": ["6aa0616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/19928329d12601dfd9c4a12541e9799fefb5439e b/txscript/data/taproot-ref/19928329d12601dfd9c4a12541e9799fefb5439e new file mode 100644 index 0000000000..29eb76aa9f --- /dev/null +++ b/txscript/data/taproot-ref/19928329d12601dfd9c4a12541e9799fefb5439e @@ -0,0 +1 @@ +{"tx": "0572398202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b01020000000b604692dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcb00000000fbc4aeb20342553b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7fc57fd5c", "prevouts": ["c5281f0000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "26c71e00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "f87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac319c7218672eb959ddbc260878b465d5507ea31f17efd143d8fbc0323ae2c89a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e5422b6de6500db2bf907e4c5314ebb405475f57406f25afe5ac62a92a9e6c58b"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa9b3730ae0e9b8e06af6fa3903dd842ff49b91f4387036eb6432f756cbb46a1de5422b6de6500db2bf907e4c5314ebb405475f57406f25afe5ac62a92a9e6c58b"]}}, diff --git a/txscript/data/taproot-ref/19a982b7ff350572fab07d8c7397bd3e8f2cc04b b/txscript/data/taproot-ref/19a982b7ff350572fab07d8c7397bd3e8f2cc04b new file mode 100644 index 0000000000..395d25b59b --- /dev/null +++ b/txscript/data/taproot-ref/19a982b7ff350572fab07d8c7397bd3e8f2cc04b @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1f0100000024be6dac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708101000000ce3435b90165bf2400000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4f45d043", "prevouts": ["f8be21000000000017a9141582f8bc3490e924b143f387e99eced40303eaed87", "53cf10000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2355212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["39c95c28eef2d86ff7f805a2e33b30e4b9f33c8c4109928d9a3ac762aad41698a79804c1f7bf30b80dea6d323e1a673df445e3797ec0186de2c1c550eef58e3d"]}}, diff --git a/txscript/data/taproot-ref/19b94494f911d6c8dffa42a0570e686d8d385d0e b/txscript/data/taproot-ref/19b94494f911d6c8dffa42a0570e686d8d385d0e new file mode 100644 index 0000000000..d25218a771 --- /dev/null +++ b/txscript/data/taproot-ref/19b94494f911d6c8dffa42a0570e686d8d385d0e @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4c00000000274f8de6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdf01000000f39357ce027462a30000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e718a8883b", "prevouts": ["c63d4b0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "7dc45a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c3", "final": true, "success": {"scriptSig": "", "witness": ["c1db5d29b3f8836f14c4e1bc3d0c1622dc9224e69e259628e048e23338b334879f8c549e4afa5134d71135b32178095dc092369d1573aca294815119234e7eff83"]}, "failure": {"scriptSig": "", "witness": ["29682f6d3d2cfb2d0ef2a264d5b95c3751b14f71a85f980f49a3ff199d52927a34ec170f44e72cc36a16246d37edc0939f1c1263a63e5b122fa94b7eddfdf41bc3"]}}, diff --git a/txscript/data/taproot-ref/19ce749d29e4620af1b8364a70b233842f7e9d56 b/txscript/data/taproot-ref/19ce749d29e4620af1b8364a70b233842f7e9d56 new file mode 100644 index 0000000000..6851ae6d5a --- /dev/null +++ b/txscript/data/taproot-ref/19ce749d29e4620af1b8364a70b233842f7e9d56 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41d00000000c6f337eebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1f0000000004cc6ffa02a323b300000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987074dfa5f", "prevouts": ["ec8d3f00000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "768e7600000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["7e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e19aed6a34821d65edf69e9d12354a87f406d02be059705f92363392a057792142e401215e29d5d13de3b6ed62165bc3378402ce71158bd1208562fc299f33fc22fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a0d0ac5788f723aceb0a237bb228183ae381a676877b38e9861fc4f2162de386b9b4175db22b4058fbb32c1c98b401bd6f80a734567664ffaf4b869d5cecb8c8be9bce0da1a8e0eb2f55600b1edecb05394963f1d059e6505f0ccee9d28b62f6faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}}, diff --git a/txscript/data/taproot-ref/1a199a3cd2f3a67e25e36bd4711b535ae3d24e31 b/txscript/data/taproot-ref/1a199a3cd2f3a67e25e36bd4711b535ae3d24e31 new file mode 100644 index 0000000000..32bf96a299 --- /dev/null +++ b/txscript/data/taproot-ref/1a199a3cd2f3a67e25e36bd4711b535ae3d24e31 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c200200000056d3cc57dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf501000000a74f649460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270020200000040bd4f300326debf000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac82010000", "prevouts": ["1dfc5f000000000017a91480e36171416c0f598c1c20ba17ab3a3cf10a438e87", "34075000000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "95c61200000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c868", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb470901b40dea8c7a5ffa56ebe32dcbb2bdc70f6165f45007f6a309c26f1d76d473959a095ba405700a8bdcb88c47f737d45523ad768f5b3698c80add34f2e764b"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367895634d85db6d6be3323c51ec5b22c423c1332565debeb0f270092a59401143da069eb8d814e8e6c846f6346fa512368611d0ddd5fc662af48af9436c51fa006032c3262f8d7c29daaf8f9846bf0ed9dbcc4a0f9aeeb7c8ab8b4ceb985f45a6c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}}, diff --git a/txscript/data/taproot-ref/1a3a8c18a8e82421d33989ed4d05f5485999b0db b/txscript/data/taproot-ref/1a3a8c18a8e82421d33989ed4d05f5485999b0db new file mode 100644 index 0000000000..afb3cd14d2 --- /dev/null +++ b/txscript/data/taproot-ref/1a3a8c18a8e82421d33989ed4d05f5485999b0db @@ -0,0 +1 @@ +{"tx": "5ba8d15b028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b100000000a28f43ffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4301000000f4d3acf404f3d25800000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87e490d753", "prevouts": ["4153340000000000225120dc3b17a9e97101dd89a6713513f87d72e341f4413af90c87ebb03089172b5d03", "e38a27000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367e327090cd1d58a7bb1c01ec2add8b9e55662aa07a105e387969c68210862490"]}, "failure": {"scriptSig": "", "witness": ["6a68616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/1a83bda864530d8086caf59fe1272ad5768d34c7 b/txscript/data/taproot-ref/1a83bda864530d8086caf59fe1272ad5768d34c7 new file mode 100644 index 0000000000..10f6c6c24c --- /dev/null +++ b/txscript/data/taproot-ref/1a83bda864530d8086caf59fe1272ad5768d34c7 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c496000000000fcc65bbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfef010000009a2231fa0450179e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870d661d36", "prevouts": ["4a9e3b000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "4982650000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "4730440220551b4fac1e931eb4709bd1c9ca34de6fb6d354f2ec95f9b5ef3f19c6f20ad5b50220408f74615a963ab5cca0811ceed7b591b242d5f6c2b7706b363b88e2d2c8b36082", "witness": []}, "failure": {"scriptSig": "47304402203266799c0aebd4129cfc3391cdf081f407db3cf6c5ae353980cd281c1260041f02200a82cd1c0863b4a2e66029e3418e566a916d04ea0c87c504d1356a72bbf958cd82", "witness": []}}, diff --git a/txscript/data/taproot-ref/1a9368b5d21e42219df4751485b7f522507fdefa b/txscript/data/taproot-ref/1a9368b5d21e42219df4751485b7f522507fdefa new file mode 100644 index 0000000000..b4e7b51baa --- /dev/null +++ b/txscript/data/taproot-ref/1a9368b5d21e42219df4751485b7f522507fdefa @@ -0,0 +1 @@ +{"tx": "73092d65038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46c000000004658eea8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa401000000a7b39fe5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c450100000060837bf002397b12010000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a60fdfb23c", "prevouts": ["afe43a0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "7ec5840000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee20550000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_6c", "final": true, "success": {"scriptSig": "", "witness": ["e857d2f90a5bc7133586841afde07b1a8a3a411030decc4660825e63f7bdba2ffbe49542633f455dd76988ed20b444f8fc57752c36a192f59b5d41ac601bb60681", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ddf64ec469cf84face0bced4771ee35e04faf554c70568f2de03eb420512c85d2e63950c2e2eb0d7a6bf730c367908d900afb6b3a94fccf5d131cae1f7d985926c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/1ab6d3c20509931b1abf61a6b45d8069679b66fe b/txscript/data/taproot-ref/1ab6d3c20509931b1abf61a6b45d8069679b66fe new file mode 100644 index 0000000000..1c3208db6d --- /dev/null +++ b/txscript/data/taproot-ref/1ab6d3c20509931b1abf61a6b45d8069679b66fe @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708300000000a2259fc7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8100000000c6f72fe102884f91000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c8010000", "prevouts": ["1fea110000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6", "6e5c82000000000017a914927d550e2674fb9e1f6ae1260d00989fc596dd7f87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090274fa3d8b77f1bffd12d3bbf2b314c93c392949ea529f39c5e3c345c5ff1112b6dfff2435d46796fc34bbdb9748d6736c775b452b064088344aabdea0cec8220b3764b5e34edb61e8405fcad227877826186b0f73ed74abc7405251b6d62ccd0ed2879c1b5aa1d93a3746b70ee16ab3bcab6442e45b3737d2220b4b2a5527573e1fa70d3cd4f839af1c54bd1f315a2e73ea46d58fbcd75ede8678b6fcb2131e036c8dd6c3f17268e6e23701026672e35d450313a4f00f0e6426683b345211bbdae5d4049b90b52eacd11729b6f977029129657df3b1af967d3330d782834afd8ffb8d4ed35f3ab33a8a606a2c3e6369546d25c83523ebc19a8ea2b53375d5d46f5bd51aff5f7de980568a079e8e461bea7f561c8ab39327e32c6405e851a8f525de98119126d2370eeabe7cc093ae031c60b16c86869916be9ffb2b27bd565f73468d134b358fc7717c32777fa07652d585fa096bae11c0121fa1a5ced8339b0c094f605740b0f7090b3af7bb4b4f96e4ef01aefda18ef330b370f32b2323b752df75923f2dfd9759798a9750a0502df4bf8953baf334d862edbfa492de1913dd126f9ed89f82d7b40e0ca3e4acd3ebb779247e8ce4fe06ae94c3a556110605cded8dc3506ca1bb98d7ca853856189069e6d1d818dc3cfd8bd18ba08fe8b7b9c9cdbb05bd9ae2c3e77de0e9a6b311e0175dc92631ae429c457e580463836ffe9e2ec233477aae46085d75", "2f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faa9cca9c712bd5dbc651b74ba1f32b079db60a81520e454f56bdbd9ff2bb730ac4a68514c5be2766b31ac79cb27b74c816d51537da76cf4fa244470107a7172f8ed6bb91bf977e9e370b444e9d5512cd4ec7f3694a9311c01272a4c1a167cd930"]}, "failure": {"scriptSig": "", "witness": ["4d09021511def2d2d06019a62a38430800e7d0b9c29ab11904b26a197189f78c6a7e53c20b713823cee88abc75c1b34db860499af0cf4954de25cccdee355137e49030c67bcbc204bfabafb47b93c03a353f3e0fe516b5e28386149ef94f0bb8051dcb31d6614a94f5227592cc93756115cb908152ebb46dfa9f80796f344908a760fca9995210b89ddb932c11569d3d509abcf7bec4ee2c224267d82a768837b9a559c2c13ee9e83a088d5547f50970cac6029c0b52970c6602e17b5483a6399d0c0ecfc3fab1bd43b5c1084bc8503e403b43dd70533d2b055b85ea3b51c3da0d6d958c0ea6438095e66200a0692c8586da0db6b084933f2388e8d0693521b957da46646acf53f917bd1376bb7585bd3893e5b6262b002483122892c53dfb5c59f5141d6811cc913b6f38df2380a81978785149d036dec7612602c4bb6a29937d1d21d13c161fd1a5a1036272834f9b89cea5a912b9978a848288f6d4d72f0e488a3e8063589e3f4eb49369c72b62a42742ffdb440cd12591ea2164684e2d91c5a9922ea55b156a0acce65905032a2b0dff9d8c495347eec48bbb08cb6b066e8de6e51febbc34bfbc923a5a73857d59d1392f492217faa9561b3b883068cf13b80468b5318dff5ba2266680746f499f4be31e07d43813462b9ce55f09aec147354c53ca7b47b5c421ec1e2b83982ecc6b73f1c96122e9ea2a52dda230b4bcf9c2a088c7d4e23fc553304d0e75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369dff55cf6ae51df43fe52c7d0d4fdbe30fa92730d4eceb3c6abd9d09fcc7ef40d8fcf0fa02e125fe1892f3caadd01fd66f2ae3104b90b9e35e4c43083bce335e4e9031d393e93ec4f3e9da8fc51e83b82f31256dd96ef4af94581a47eb5c67bc"]}}, diff --git a/txscript/data/taproot-ref/1af45f5f9b4d38fa9b4e939f3e3622bcdf2d29d6 b/txscript/data/taproot-ref/1af45f5f9b4d38fa9b4e939f3e3622bcdf2d29d6 new file mode 100644 index 0000000000..cabb17b0cc --- /dev/null +++ b/txscript/data/taproot-ref/1af45f5f9b4d38fa9b4e939f3e3622bcdf2d29d6 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6900000000d4abccebbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb700000000bd7983dd023b8a89000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47874aafe95d", "prevouts": ["0bac2800000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428", "09de63000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "5a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936648f7288da451c6edcb2ab904ab412d7719851ebe4c732831d3fb8a1e081c682db79ef349d3e4f05529a42271c6cf93f8e06fd8991a688edddf7288612a03eef8b5457f6f65490151d40d3d05d55f9c92d8dec73c7aa55a79aa7c51354918829c531ca70e78518003474f611c07657b0808402a053b744a80e6cf25146bdf24b"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367960d7b37dd1361aee34510e77acb4d27ddca17648a17e28475032538c1eb500da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb4949da8d2968254411aebae49708200d0b19b59a844616925b107b397a8b89bee9c212f1ab0dfa1a42522b9ca3467b009d36f3b841f39cdc4da4a0520ce4fa4"]}}, diff --git a/txscript/data/taproot-ref/1afbe3f769c38b8e8b6210ef4c1e57bc6cfd7f8d b/txscript/data/taproot-ref/1afbe3f769c38b8e8b6210ef4c1e57bc6cfd7f8d new file mode 100644 index 0000000000..5af698c92a --- /dev/null +++ b/txscript/data/taproot-ref/1afbe3f769c38b8e8b6210ef4c1e57bc6cfd7f8d @@ -0,0 +1 @@ +{"tx": "7b8f2880028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46300000000896a89f660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c3000000008f1288ee01e55143000000000017a914719f78084af863e000acd618ba76df97972236898700000000", "prevouts": ["2c12410000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "797d0f0000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d5012e137fad837f2a561bcd1c9c1f808d9fbccd84ec6909847f68cc5e99fd83680ad4b39187ba2201bd43281cb490806f8c92f3a923381fbf08f71aacda6b45a8d82ce18bd234c1584c4c622342218adb669c8aa790fa32167112ba5ab09537f29ca2a45ef7c036783e7f019aef8c33828dfc20d8195f846b202f5060bd6054c5e9d880afa10b507a611a7cecba0751355e204d7d64cdc65781a30fb764faf16916952ba4bce2ff36064afed8298aede0bfa088d5cd87b98bd86e0d202351a708c54794ccb84200dd55c18b7917646b7f907583615335daf060c73e014afbcd85269a32091ca1a0e619f6cb46502b0617eb208183082b6d5eadd4338e4b10dbb97d8cc4aefd2bbff4ac5774aa7982bc9c37e7f08e57211b2703c97bb67d987aa84ab88925ee8582ab7c5b84ad64822574e5eab73dbea6612084108aad55bf4bed6d6aa2b9e066146b19db11511d4ad8ae5515bddc907180c169281dbc52835b6456a98e3de1086bb652e5971f79fa145d699f0d3f075f058767839d4bc421ea4bff2666e4184e2ba3b40841d4d84ef7df51a9df4d23a49c5c067c7b5ad797adc191b33a6991643a5484210c304c9a55f50151dc5816624ea9a8a448bca698b23c50db5b86b03db533335bf6d0647eae4c039e05f016cc8805dfa15fd010ed2e5f65c5f9ea1e732051d65371f5df0cfe5590cd124d77011f963477e438344a6835e0693fb3d083133775ee", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361e1b8a1feee59cf22177304d96071e13d70dea9b08ecfc21a58c9f3d5fdb3c7559932febacadcdac9e119439ee6db08dc69c3a75ae91b384d859ac01e20a421c0028cdc19f89baf6c362287c7c7841c4536091540a9bd978c440258b5fe7844c439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}, "failure": {"scriptSig": "", "witness": ["4d0902ba928d55b192a89bed5e70305a953fb31aed39dbda4d92b7501ca560e75875af4bc1f1cad845cf132d229040f255300d2d92e14e3baf0ca7261028b28525afe557310a4513d6c035826c20ec28ca25d69ffa1fd69324d4f053f46569665001d152a86f5c779661d2e74ca20fb6e60a619dafc445b735fa1c209fdb999454b255e7338a078bd425f1a6523435b24b9d50a0aa221f873dce6e8454ce85e7a4c7c4a92f4dc2ada819992e0f98779276a4b4b18905de8c0ecefa5f445f95814da46bd30037eb8f3ea3e78d8e9da0c92b63198f7826e92c90fa61d7a1d35a87e720d7997cb9b4ed894e84aebd87e54082fb470c490f2bb353a4aa926a15e076e29dcbc8da4a63d5078659ad263302326525911d848b77ad4d35a0c0bc025f37fc5c40b2c06786c14c1682dbe8cff62d3b7b5543e21bb1ba2bf1ac089e1c37fa443d282576ab7b9d37aab9b2161b7491a07923b254494da284488e5302406f7be9ba60234d3c6eccf289416dbdf2cdf17410edcdb2234ba003a985d992ee9e00069bbd1b93fd5fa1b44208d6af7067bf5666e4a570d1b0ac682a5972c84111619a307622e8b2d38e24d42548d3cd47f53b553e62a46efbf4dcd30317c65b834f5ae6474bbe4945a3a66ac34fa4c628bf983ec8e68ccfae08d228f6416737264838eb602652e918ea718b2f4166aa1c1a411f3ed31630ce2345a89f52a363578694ed34220f4f00128197eb077561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364853829b144d1f1df74c8f7a51e60c1d5006a46e3272d2845a586cb2514e9cb959932febacadcdac9e119439ee6db08dc69c3a75ae91b384d859ac01e20a421c0028cdc19f89baf6c362287c7c7841c4536091540a9bd978c440258b5fe7844c439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}}, diff --git a/txscript/data/taproot-ref/1b13c8bd9a345bdcf71eaa1078ef4cb752b3da96 b/txscript/data/taproot-ref/1b13c8bd9a345bdcf71eaa1078ef4cb752b3da96 new file mode 100644 index 0000000000..73287f07aa --- /dev/null +++ b/txscript/data/taproot-ref/1b13c8bd9a345bdcf71eaa1078ef4cb752b3da96 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be9010000003b4ab8d18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49301000000992f62bfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c36000000004f65d726032c18a700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5f079022", "prevouts": ["617c220000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029", "dc55330000000000225120884291612dcc22b2c0e2cf19d55719f5f9dfe9624bd12dad94712b18ad4d330a", "c6da520000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e74c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e907011b224c3ef86d2f36e7d89b63e177b85cadcf6e2dbac0680b671e6366dad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b292a4f502e305109d81040f98432632ff806e9beae33e8faa7e022234476532106df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1dbfe159b7f074423d2fa61e8a9b5231056855b78cb68876c387837662b8c070f92a4f502e305109d81040f98432632ff806e9beae33e8faa7e022234476532106df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}}, diff --git a/txscript/data/taproot-ref/1b2543854748d5b37077ed3e53a36309f5330a50 b/txscript/data/taproot-ref/1b2543854748d5b37077ed3e53a36309f5330a50 new file mode 100644 index 0000000000..db350c295b --- /dev/null +++ b/txscript/data/taproot-ref/1b2543854748d5b37077ed3e53a36309f5330a50 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8801000000c8c8d8b88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ad010000004c9346de03c1f76000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc731010000", "prevouts": ["4b5d270000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "c51a3c000000000017a9146f2d26adc5ad58653becfc45ce03a0b1167b1b7e87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "cf7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea56bafcb4adbf2751227cb38af2ee857892c1346189758b7796ca4cc3d2e44b46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdd6c4167c25132c432c9175336dcf34ec1853eafcfbd891c58e0cd045b8bc4542"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e82a853d9097b45eb0aab266931969d1621607f85e2073f603093b953a54be8539d6c4167c25132c432c9175336dcf34ec1853eafcfbd891c58e0cd045b8bc4542"]}}, diff --git a/txscript/data/taproot-ref/1b3c874362224cdb658666354aa6fb9efff9b371 b/txscript/data/taproot-ref/1b3c874362224cdb658666354aa6fb9efff9b371 new file mode 100644 index 0000000000..b868ee7a8b --- /dev/null +++ b/txscript/data/taproot-ref/1b3c874362224cdb658666354aa6fb9efff9b371 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4300000000d2837e2e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c484010000003ef0486f03696259000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8761727c27", "prevouts": ["e16b230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "43df37000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/input81limit", "success": {"scriptSig": "", "witness": ["8c51fd3dadf2084c515868c0183c3a4fe1f7af7f1d72b3c5bea38d36b25fead31cebb4337cf0fcc96b784a4673ebda7bc5dc62d4fb2a1f019523632a7f8fd337", "6ee6f7f05b6d3e67725ae7b81d24ee0c606bf1ee08210f6d61e0980224e8f31ef531b411854cb17b4d129f949891c8c09237a72dfd743ca002b8ac24f2b8e9e64ac37c2055b4b66dc9fc7ab00faa0994de", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93633f145906eb3b0b9144503b7e952fa7ac030804bf21818b76946b0617a1dc901d4021eb67a5422f2c264ab2e161e443ad68483a924a10f3067064f47bfc1aa823d0cff3dcc0a2d4e46fc30f48a30ceeaa99fba3feb9f110c8632a3b2fa3f4f4f8fbdead7f8de6a8aad36d37b0d589bc9244c1684fd5ac3294cec67c7c6e587a6904ede5a53833ce5d447360be78b94add963f9070eac219e9b04ee2bdd400ddd04364ae3f3c0d48023a93d8481ba8ff7adab87d79476f69028f3fb22b08d057964bbb3ea34308947c748760264ee9e03eb1f98d2b66028dab654f580a418be99661f479a6b0f557293064f4a690bd09af98d8bd3a778ce8944b23259946622ee8f58700e34290ee018923271c5b5338c26b1c5ef6f25154ea2cb21c87cb2bddad45cd3b88d2dbb65b62cf977bb614d0efb5c9353a8b35cfa01122561253231744c2c32064ddb3ff0f538be34c536787771f8aa5aec123a81e8014a979ffa6906075479528a5b4db5d683c0884af4c8976d652dd9505f85dd291fe0843ffd0ff27865ba15c8822e63cb0be5982c1ef15a41fad555080e76aad0b72a8aa15726acd51679a62f62b306cf011a5d1358e6ba8e189d7358bc43376d46dcace83895e75b2934214492b999e4970e4990c42fb0eac353aa09117e3e38145bdbc22646e577b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/1b4bc136aef0b80666d85ce3d93b7996d0ce7ab5 b/txscript/data/taproot-ref/1b4bc136aef0b80666d85ce3d93b7996d0ce7ab5 new file mode 100644 index 0000000000..3e241af168 --- /dev/null +++ b/txscript/data/taproot-ref/1b4bc136aef0b80666d85ce3d93b7996d0ce7ab5 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9a00000000410c554104488323000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76e000000", "prevouts": ["74fb25000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "a77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8344d9400294a0bc4ed438b22b08ab3b11b45ca3db5baf8ab71a53149f22b235b11a008161139ac7a92b00665158d25501a881aeebdfdbf881ee45b85e0726c11"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b1e774f32bdb28c76107d540bfb745497eaaa89f3b38b8eaacc646c85ab728e2344d9400294a0bc4ed438b22b08ab3b11b45ca3db5baf8ab71a53149f22b235b11a008161139ac7a92b00665158d25501a881aeebdfdbf881ee45b85e0726c11"]}}, diff --git a/txscript/data/taproot-ref/1b5a41cda693f9d63f77b9b053dbac3106aea789 b/txscript/data/taproot-ref/1b5a41cda693f9d63f77b9b053dbac3106aea789 new file mode 100644 index 0000000000..053549e43f --- /dev/null +++ b/txscript/data/taproot-ref/1b5a41cda693f9d63f77b9b053dbac3106aea789 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd90100000012f00060dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3c010000008347e7830238aeb10000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748761030000", "prevouts": ["c79c6b00000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e", "dd9f470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004536ccddef3149683af65c31c85a3c06583d8e56fa5e9b8809ad6476a55251e65fad1faed220136b938a4936a71b98f5f9e86de449242d6a82efdf7a3adba2ae62745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ef65a7bc88e8caa9953fbbe68415f348dc7b3deedacdb598041f1438fea667b18959ac4fa8a57d164b76708dc6f63c2efb2484bc5a77a391ceb66b2f5ad6b35f745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}}, diff --git a/txscript/data/taproot-ref/1b68c33f2aa26138257e984d7c57524a609332e4 b/txscript/data/taproot-ref/1b68c33f2aa26138257e984d7c57524a609332e4 new file mode 100644 index 0000000000..b87afbcd3b --- /dev/null +++ b/txscript/data/taproot-ref/1b68c33f2aa26138257e984d7c57524a609332e4 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd401000000a64a7c9bdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2f00000000f9b73b8e0300959b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a695000000", "prevouts": ["8f217a00000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "ed1f240000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "2f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cb0eee81661f2fefaf772a8bdabbcbada52a1b0c3a58f1bcc7f9bb01897d4d674e9031d393e93ec4f3e9da8fc51e83b82f31256dd96ef4af94581a47eb5c67bc"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ca2ffab0cf338eb106c1ce200445cc90ecf54781f497edfad4f32965f124fa8cb0eee81661f2fefaf772a8bdabbcbada52a1b0c3a58f1bcc7f9bb01897d4d674e9031d393e93ec4f3e9da8fc51e83b82f31256dd96ef4af94581a47eb5c67bc"]}}, diff --git a/txscript/data/taproot-ref/1b79cd4b2e7a4b311359e56e468853036d3681d5 b/txscript/data/taproot-ref/1b79cd4b2e7a4b311359e56e468853036d3681d5 new file mode 100644 index 0000000000..c2c0f4f6ac --- /dev/null +++ b/txscript/data/taproot-ref/1b79cd4b2e7a4b311359e56e468853036d3681d5 @@ -0,0 +1 @@ +{"tx": "d1497db003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5a010000000ac409eddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1802000000b7a057afbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff7000000007c740f92045d5fac0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce5030000", "prevouts": ["d1a0230000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e", "d84b2000000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1", "d77c6b0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c54c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694642e1d6a26a11a0c6e91919f09b278112d3d9e7557d10f9f51d88907efe7b71ca095b957df84f3ee7611aa117e5662ab64755743d6d9c5cff6305984f4054c5075e3d7a2801b75eefdf65cb630fc6bd09768ae07eb1bf67760ac5f1c253b1300a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}, "failure": {"scriptSig": "", "witness": ["4c52c5", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365ecb95e6307dce8c007c72a55b7b5c6feb3e69a9f251aeba09cf2903e8de24a91ca095b957df84f3ee7611aa117e5662ab64755743d6d9c5cff6305984f4054c5075e3d7a2801b75eefdf65cb630fc6bd09768ae07eb1bf67760ac5f1c253b1300a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}}, diff --git a/txscript/data/taproot-ref/1b8f51ede6850bb667b5fd80d78e02cd4832d753 b/txscript/data/taproot-ref/1b8f51ede6850bb667b5fd80d78e02cd4832d753 new file mode 100644 index 0000000000..5bebc8d355 --- /dev/null +++ b/txscript/data/taproot-ref/1b8f51ede6850bb667b5fd80d78e02cd4832d753 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701f010000008a70cce402a20b0e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc11e4753b", "prevouts": ["b2a6100000000000165c142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["cfc26d33c3f5da3eceabd09c022c5e779e8b65893679a04f00096c9348e616a10ce548f5d5717b699b60e94ae7675c4d43a7be8f45ccddc700a88556b6026cea", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/1bbde099bad78eb5021b57eaf4e9fecec63162ce b/txscript/data/taproot-ref/1bbde099bad78eb5021b57eaf4e9fecec63162ce new file mode 100644 index 0000000000..ed5f465430 --- /dev/null +++ b/txscript/data/taproot-ref/1bbde099bad78eb5021b57eaf4e9fecec63162ce @@ -0,0 +1 @@ +{"tx": "a8b92e5502bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7c01000000345ea6848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40901000000fc4b1ed502e2dfa00000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac69b80e4e", "prevouts": ["8402640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7c773f000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["be", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93659372e262d5a0f9ef536aae388303ac1332900989a5444d826ec2580d67fc3a21a521886ab29756862a71c0453b77f880429f1d68b1fae0f34d555c1e4747b3e7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a5bb2be9c002390585aecd6a44dd843628783a58b1ff5512778ad80556de83f015cb0c87b91becc5e8e88545f518ccd4dd82a3936db012f0c0e2ff8a479534101a521886ab29756862a71c0453b77f880429f1d68b1fae0f34d555c1e4747b3e7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}}, diff --git a/txscript/data/taproot-ref/1bc3e95ef1ef57164dee0340314916513b071491 b/txscript/data/taproot-ref/1bc3e95ef1ef57164dee0340314916513b071491 new file mode 100644 index 0000000000..00e84e6d1a --- /dev/null +++ b/txscript/data/taproot-ref/1bc3e95ef1ef57164dee0340314916513b071491 @@ -0,0 +1 @@ +{"tx": "044da27e03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdc000000001a07b0b4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9501000000bff781dddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bee00000000ac3a7bb4026db9df0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67e030000", "prevouts": ["ca4f73000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "2fbf4b00000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "e43e22000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "a87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa5bae7514f70ba44e8d531d880798aa096a25d03d605b2e6afaf4f02fcbbf71905def3d75afa0626f5ab572f3c9ae49b6567bf85ec43d0b3933062a3ad8b1e492"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e0f273cf51817af2ba6be97d0b489c0ff94fb9e2107188f41c15a52934d07d725bae7514f70ba44e8d531d880798aa096a25d03d605b2e6afaf4f02fcbbf71905def3d75afa0626f5ab572f3c9ae49b6567bf85ec43d0b3933062a3ad8b1e492"]}}, diff --git a/txscript/data/taproot-ref/1bc5747eb674dd470ce9e8f236e8c461bd9f5491 b/txscript/data/taproot-ref/1bc5747eb674dd470ce9e8f236e8c461bd9f5491 new file mode 100644 index 0000000000..3bce49e476 --- /dev/null +++ b/txscript/data/taproot-ref/1bc5747eb674dd470ce9e8f236e8c461bd9f5491 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270df010000000d2d46bf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704500000000609e4da760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a601000000c24588ea01641b0d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87260bfd52", "prevouts": ["9707110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bde20e000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "f260120000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c6", "final": true, "success": {"scriptSig": "", "witness": ["ddaf1bb74989869b37d16c28f9b40779f55f7f5218aa7f4c0685073d12b99c91b034097dfb03d30811fafd407578b0e2574a239ae4e5611106dc92d5d83046b902"]}, "failure": {"scriptSig": "", "witness": ["04ac942e3e881e0770c43d7aabd4619c2f8fd9930302edb64765b30443e9ebd2d75201cd83ae2f622a4bdfbde08a1f357a601a2c866e2459b1d9be20fddf56fcc6"]}}, diff --git a/txscript/data/taproot-ref/1bc76532e1949261ee2079d9ce81e5bd2ee2c56a b/txscript/data/taproot-ref/1bc76532e1949261ee2079d9ce81e5bd2ee2c56a new file mode 100644 index 0000000000..0bbffe8138 --- /dev/null +++ b/txscript/data/taproot-ref/1bc76532e1949261ee2079d9ce81e5bd2ee2c56a @@ -0,0 +1 @@ +{"tx": "a83fcb2f01dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0c02000000300def9a03348f220000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72c010000", "prevouts": ["6614250000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902987bbdb96815479e252b855f04fd09b10903650e7f2b4711d67c5f3d52c6e112abcbb9aeda19ca443637f8af4be0bd588f2bf3d3451c2290f18e2b98fbb0207b0d4cafd72c318d0207acf78da1a6b850968d0dfa2c2ba264ae4d1d9335888894578835dbe8bc0aaa2fa616bcfdd2645e34058e523dbe20cac0296caf6e7669742880805ebcb4988448776844570656fa42a56e438869fb28e2d41bf1491fbbfd0962f8f9293fc970bc61456b63a6f71a95a009b7d04258a2cd7429524c40c0384a8e7e83a46c2cb28470bec8edc59729a2a6666c3a6934fae3a662ee3d744ac831a565d3a637f74561b395b9faf3958422791928ceb370b5d133620de5210bd5d59feb4f4277f33ee4642c3a78927c2dadcd7cc9dd64426e9120bf52716d945aa8ef41165ff702aad7667419322d892d7b31a6580ccdd70cb103e0ef4c627100342d0e968fe4597b6beca749a94923f0b4ccb73d0b9054029a8c64f92138ca07beecc730e33a8db9798c826d2a3322d65d197faa43725fdb5e2eb17aa768ffc466cd96b0ddb7e5e02beb4081648afed31d7307add3aee1e91aadfdec50e0e024752ae7cce334cbbc4c44166fa0717d413fc4705e235f59639466fdb00441ba6b59feb969c484b89a245a896b5954f88cc871642f836c1723f711a1919c52f63bd88823727e359bcf81b7c73fe5fdf1f99a4e89d38f22694ef46fbd6445e90a0d8e0e8e427c62fd0da775c5", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1111302735ec636dd6cd82402c946e3c4544cb7cccda2620354a4b8fa269f342b5075e3d7a2801b75eefdf65cb630fc6bd09768ae07eb1bf67760ac5f1c253b1300a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}, "failure": {"scriptSig": "", "witness": ["4d090230ecb3e7cdd1f21ad4866d4b17edb63a2ea54323396ecb9ff29801f7f34cb7fa443c0c5adc090368e9434746ff002e4730351d45e72964762c78d3b03d40d713422223d4857688b9eabc0573719f932518b9e2f2b1beced10da4150cee0049de8254fd03309f9f04d1ff7c1f15c215facb0ec1d51116610a83e9b80d38e9cd917261cd5f6a9d6c2dce17ddc268e07b893564a1ad65dad766465c3055c54c0138cc517808e412c08ef38e6d42dfed56e7dc797f815f14654cf5283883d85c362fd911e5a314097bf785665888e831fe68ca5f22b7497881bb7c9dc33082812cf8162c824ad085bc858b2a1be43091ccab22c989f43ecbb7d152f3365c25a3ee6d12a89609f429b4feebcd549c37b1a13408043428ef2b856fd48ad02fff8e35084046064413e5a44ad3e8e36045f8859e898f5d84f3919c005592aeef473692552a000b94619545fbac00dce04a4c9aacc0fcf54927117b05b84beb4e37f0622317bbd91338eacbcfb5d954866a93931514a051e009cd9c0c6b5e5d08f35365cd88c6fc4aba03331c91bded729f8aeed05c5f32bde8921947844e5d7499238c0ce305d5d0bedf4c53b18d52c1d0cdc51d0650459bc9bd71d7b19cde9ab53084f2e95d489dfd79abaeb4b0a7746f187015067e8576b25ddb0a6f68897529f6842e33b3c7ed7c0b3e276cb43052005d3944a68bc64483610d73d6fd521caa1e40cd730429897b1c0517847561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a660eca3fa0edb42c0ab30ffe3daaf6f1f409e953104f48559c2b804c71af6a81ce4d7767c8a9637a0804b073b1eb172c67de67ce152ade33f2591a85dfee2e5a"]}}, diff --git a/txscript/data/taproot-ref/1bfe6046e6cdc344b877ad37196692f2724dfb96 b/txscript/data/taproot-ref/1bfe6046e6cdc344b877ad37196692f2724dfb96 new file mode 100644 index 0000000000..dc67403009 --- /dev/null +++ b/txscript/data/taproot-ref/1bfe6046e6cdc344b877ad37196692f2724dfb96 @@ -0,0 +1 @@ +{"tx": "3f83490e02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf29010000004679f882dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7001000000ded352b204041c8c00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487ae53ff24", "prevouts": ["18d9660000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "dbd8260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_csa", "final": true, "success": {"scriptSig": "", "witness": ["2b44eb7cd66327d88d4548755f38c44c35018f8a857e6c90843b6b9b76e558f77a9de1d26d4076b0f124c9291ad326ee84d275d24343dbe3e3d6b0385bee9ebd", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439befee6fda3cb49175c9fcdc99039bdef34bed6f8c885214259c1ab60f6e0548afc8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["2b44eb7cd66327d88d4548755f38c44c35018f8a857e6c90843b6b9b76e558f77a9de1d26d4076b0f124c9291ad326ee84d275d24343dbe3e3d6b0385bee9ebd00", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439befee6fda3cb49175c9fcdc99039bdef34bed6f8c885214259c1ab60f6e0548afc8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/1c0b90070d5af0e0da662d27418affd7255bb328 b/txscript/data/taproot-ref/1c0b90070d5af0e0da662d27418affd7255bb328 new file mode 100644 index 0000000000..eb5ea2e6dc --- /dev/null +++ b/txscript/data/taproot-ref/1c0b90070d5af0e0da662d27418affd7255bb328 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf300000000050a1b45adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2002000000d5142d75026c9a980000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac27030000", "prevouts": ["3ca17900000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "03c62100000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "327d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93664a7611b628410c237d06316ee04957fbdc9ecb6c280085c3b6be5718c5572e78ce3cfcf38b656b5bd992972d83f897c8aa5da1de7c0e12ea4c0aa09cdb3dc1d2e4cd18b5d1ec472eec5a95c6c9d67ba3848eb933b0b41a8c6d3176a27b07997"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93613098bd67eb0d948d9da1baef2a1e373b21f0d2c05e2b432c8a43efdf85d0ad308902a07d3a610262cf0bf6826274beb2bca0848f03750f1d66d9fdb1ecc982925d31a4d328a06fbd663a9de03f4f743ae6731d946a7b64875ecbfa9fe5ecb492e4cd18b5d1ec472eec5a95c6c9d67ba3848eb933b0b41a8c6d3176a27b07997"]}}, diff --git a/txscript/data/taproot-ref/1c1b10df48009861e679c78f57233fcbab1c9c74 b/txscript/data/taproot-ref/1c1b10df48009861e679c78f57233fcbab1c9c74 new file mode 100644 index 0000000000..4e9462c12b --- /dev/null +++ b/txscript/data/taproot-ref/1c1b10df48009861e679c78f57233fcbab1c9c74 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4c00000000274f8de6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdf01000000f39357ce027462a30000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e718a8883b", "prevouts": ["c63d4b0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "7dc45a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "1a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa8e84781bad1ba81b7ce5b7be6cf9bec34b59091704d19096b61e5a37e7aa266c56798b11c96dafc2935d577afad31a6537ce4b1a48ff27833822cff5fe95a51e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ae37181c42054bd3d996a0cb9fcac8a434e22d455bb156486fd105951d5862240401d3043d3e54134521a2f6b274f3ac0e46a5b9a6f95ac49ca3a75270b4793801cbe9d84ce1e82e006940c90d66235295537a514918e448d1b01c99be1031af2727a08c83da142d000f7f66d34a23554b296f940ffe81022e50f50dcfdd8b9"]}}, diff --git a/txscript/data/taproot-ref/1c1c68f02884233862b5ace3f063b648ef1a8f5b b/txscript/data/taproot-ref/1c1c68f02884233862b5ace3f063b648ef1a8f5b new file mode 100644 index 0000000000..6a30370636 --- /dev/null +++ b/txscript/data/taproot-ref/1c1c68f02884233862b5ace3f063b648ef1a8f5b @@ -0,0 +1 @@ +{"tx": "2cdaf2c70260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127012010000003b999eed60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705901000000d23472a40318961e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5f000000", "prevouts": ["05ce0e0000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "bd5f1100000000001651142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063ec68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367a5b4453de5c6ff322ea1de12551f31e7d4d3d0aa0fae2cde1b898bb69f40e54afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173adddfc46016955cd26bcdfd077adbba0d60eefd6e0317def1b858595de21efb103b719bf4b6df334f4ad3966afd516fb2a8d294cb4fface4e4609ab1c9f988c5a"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d686773729ee45a24450fddb7da6d0266ea60d425b2bcaf3694e59ee80e6a1a3dddfc46016955cd26bcdfd077adbba0d60eefd6e0317def1b858595de21efb103b719bf4b6df334f4ad3966afd516fb2a8d294cb4fface4e4609ab1c9f988c5a"]}}, diff --git a/txscript/data/taproot-ref/1c2a334bb5693def73177ba056d467309d1a592a b/txscript/data/taproot-ref/1c2a334bb5693def73177ba056d467309d1a592a new file mode 100644 index 0000000000..0ea800b7f3 --- /dev/null +++ b/txscript/data/taproot-ref/1c2a334bb5693def73177ba056d467309d1a592a @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bed010000004b8c4692dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc00000000064d1b7e701d6ec0500000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5d040000", "prevouts": ["d41126000000000017a914927d550e2674fb9e1f6ae1260d00989fc596dd7f87", "690e290000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2254202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["3986be8a270ddfe32e2009bc7115200b5e1f0a0ebc807f85a6a2f555df4aca454525ee4dda5aaac495658d27b678d55652a1f2ea60fad74816052599f8b8c92c", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/1c34962adc291e2c8bf6dae66b8fb9c765b86439 b/txscript/data/taproot-ref/1c34962adc291e2c8bf6dae66b8fb9c765b86439 new file mode 100644 index 0000000000..5c7a1f8153 --- /dev/null +++ b/txscript/data/taproot-ref/1c34962adc291e2c8bf6dae66b8fb9c765b86439 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dd0100000032bd211460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ae01000000ce12f710049bb81c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac34000000", "prevouts": ["bfb20e000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "9019100000000000165b142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["b0a0c8f5ff054a8c0b66272c21f09d79645ec52eba52e10be1a70c9dce1379227bf4a7668378a0efe2e4ca5c312fb651a52cedfa4773ff4ab97e186205b0a85b", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/1c385e281c4e1f86fe4c3b41f133fe0f1ad20791 b/txscript/data/taproot-ref/1c385e281c4e1f86fe4c3b41f133fe0f1ad20791 new file mode 100644 index 0000000000..2dbcc4f58a --- /dev/null +++ b/txscript/data/taproot-ref/1c385e281c4e1f86fe4c3b41f133fe0f1ad20791 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41202000000c2df2cc2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3e0000000000c889220437d98f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a63a584d51", "prevouts": ["d5a340000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "1f1a5200000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "437d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362c503a4390cea1e1efd273895e3e36c6de149914d80a97a30106137d896fa43dd9a73345c989c90f21221bc9fa2fdbe5d62b34ad323157a62317cd84046f2af72db79fc77699d349d3583c063c1ca5cb78d93faef419ab336fa45db1a25ff641"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a84e311995f98367a2a93ed7b61478a76d5defba7ed050312f02844091a9eaa94274b5900613cb2e14ccbb49f92be42e903262ce34f92c4d0a103e0ecbbdfe862db79fc77699d349d3583c063c1ca5cb78d93faef419ab336fa45db1a25ff641"]}}, diff --git a/txscript/data/taproot-ref/1c561097325c97828153532b8c7b95b14e46dff4 b/txscript/data/taproot-ref/1c561097325c97828153532b8c7b95b14e46dff4 new file mode 100644 index 0000000000..a3ea13d95b --- /dev/null +++ b/txscript/data/taproot-ref/1c561097325c97828153532b8c7b95b14e46dff4 @@ -0,0 +1 @@ +{"tx": "feb46ba5038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45901000000d71bd59f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4be010000004e14988560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a7010000008348decf04584a79000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987a5c20248", "prevouts": ["41353600000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac", "744c360000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "28650e00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ca", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f99c996d59a69d75c183cc1e3ba6b17987582b2274e87a7d50251745c93805cc8eba4e75ed92f6e82baf0cd6101dcd67879c020ab703e3dac001fd69a24240ecc7034c4ece6ceffdf067bd97d8bd2a80e986f14e8b5dca33ff1523eba7a77d63"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93609ecd9cca2f2b8950833b6aa956617a5b43d405ddabf2f82896509604dfe978d1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045be01dd809c80d07fbb65649666935b9712ecafc77e536b2a27c3cd6425d00c1ec7034c4ece6ceffdf067bd97d8bd2a80e986f14e8b5dca33ff1523eba7a77d63"]}}, diff --git a/txscript/data/taproot-ref/1c7cf3e3c8d41ca4743e00d88ec0434c6f31d4c9 b/txscript/data/taproot-ref/1c7cf3e3c8d41ca4743e00d88ec0434c6f31d4c9 new file mode 100644 index 0000000000..cdfbda7df1 --- /dev/null +++ b/txscript/data/taproot-ref/1c7cf3e3c8d41ca4743e00d88ec0434c6f31d4c9 @@ -0,0 +1 @@ +{"tx": "d3ff18670260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127077000000001de5cfb8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6200000000bb5121f804c76831000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac74020000", "prevouts": ["23940f0000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "a9962300000000002251208cf8a45f10f972ce0940452c1be98364c363db2f13613d49d474bd7709bf6664"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "8d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367fb9aaabde077b4a96633c8c7d2d9c056a2c65d4be6dfdaa3c1c9735c6591c4fb838daaa44e784827b3ea8aea20503468fe81f3acdd576e27ac09ae12d8ed7c28047789ecbd47ea83af97bdb87f8422a4707031714ddb05eaa38b24e158a7c35"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e88f7cf44737276fc9e0e4313f71ddb6257126d0499b1311bfe4a854929366560492d17ab4c59254bcdea8b81e7721fca5f8758b8cd0b322bd5a652bd9dfe7967472d664747fea006dedee35c74318028ad9a0ae37c154fe8226ccc2af402983"]}}, diff --git a/txscript/data/taproot-ref/1c903f96be3cd8956476fb915624fb89666a187c b/txscript/data/taproot-ref/1c903f96be3cd8956476fb915624fb89666a187c new file mode 100644 index 0000000000..ff2891fc54 --- /dev/null +++ b/txscript/data/taproot-ref/1c903f96be3cd8956476fb915624fb89666a187c @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706a00000000ba3847fa01d7b9020000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc15020000", "prevouts": ["0d141000000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09024c60c07685b0417c278706be8b20403d535e08fe96e8a49143174c62f87a0fff247b9625014ff97b39045d5791a8f071f7024979d335a05e843ef427d5ebbcca3188050a4668a361e040eb89629cb77b168ad9c46a13427b3f8fe1d7eb4417f132cfa94b84ad4a52d7ab1988879ebef37da6ba67866597973f51d8e05964ceed321323d3e0d857e1421627bb575713d9661841e83b89e0429e271dce0b57061c3ab2e6bec506520c94d2a556c2708c62a9ebd3625214a74277dcfce157927e4c25fc8ca86168dfb495b394b2b6eccbabca296655ec91060cb415658e39313e3c6e570a9bca1127647e20fe0f7246b5fb464e899e6b9f9ebd66b42a2ab5cb9ca2cd20ae9ce19aa5e82991df186a89e579d2282453b43051bd855825191665358fabda6d3dacc64f96f1c1fbc9401da10693286fc252e472ce5338aca9b47feb7f7dae56c04a978ee4fb3a571b777906b70f519cf31098b8759ba4239f77e06153fe967cc9a95c9107d23d07f36396496cb33d224cc86f56b8d0b4a090561c5b6c40d54f23f80105b81824524a1c52ac2e6537501ecae2b61711ba647136d08a54660268bded7c90f9d473a2f000a41e25fac686223bde9debd54b9ebe372edbd8824ff04a4dc126ea7762bb58442cf782ace01c0ca01813e9c71072966f5190164e4103b82aaac539d4d5585d9327850fa7655e7c7a7bef797ec07b6e4d734904b64d7a27ae3363fb0575", "107d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e32fffbf821c428499cff2b0139c90d93037c61d12af2692624d5246efcf2a3a14520b5ceb13d27db1b37ec8ee9ee9482aafd08fc62c5401b1fb7c7b4ff374c3d"]}, "failure": {"scriptSig": "", "witness": ["4d0902aee04339b9490235fa263c8a9d1929a73a22b6665a877f21940e3037e1cb39e76f25ff54c1e217fb5156da8edea597654d2abbe5203007c27276cb78e6786973e1b2f302aa78b0eb3f10ceca4490d6b24a240fcc959704fd574daad1e2604c3aea31cbdf80f3bf38c3ddbc630610dde249dbd182a005648ed105ba802d39b9164ed0a2d19c61a8cee5b4616345b5316703d09221a554f3d1172ab8fd61abe4f46758155f9ccb90695869bc7569e6c25d278b6288e7c1b8a9537d72349fd41041fa2413ebd82723766ff7ebf178afe3a00419d139ec6abc5d8262a6ca8a22ed3539097a0fde7bcb6b37885ce7931e5ba848a1657c6d7f8dec7a214b102bd908dd6a3c57490400f06425cbeb9efbd32af16954ae48b83af314671a0d08c76af69e0eabd9ed703ec91cbd9b8b9a68b6f6dd3fbcd1909b223cb8c50d0a2d1e58423294789f50bdabc07290db9286f9e531d4ed59f42f92bc3d0b767ec2b44815f8756ac222cce21792012882139ea843745b12ba9ff77392617c5bca01d69af30d98d617d40800915bc8a33a53d224ad2da62d578252c629eb705695549e56cbec550a1f2d62f18520496b4f0ffaad2cc085f31b7af0590e2adea835c5e3936a54bff6069a9c03fbcc6f5e5ccbbfa9f4fc2ec5ebba4c5ab56bca459a2ac55bac312a2de82b17a125c95cf4c29c539d5b2414158dc6c0d77833feb713ed9c0994373e19f0139957cd577c6175", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93634545fb38decb633cf6ae769fdef4bf71c30e4ea3f5ff3ea24d94195fdedff4709630471a62c8657382c38b342878f0042beb3ba209e0ca1417f9db2e3d45f6dbd940ade039b405c8439b762bfbc73f9441ef227e6f687b6d94ebcbac32155c7"]}}, diff --git a/txscript/data/taproot-ref/1c929a0b875b383b7f3db0d168424cf2ba6d3cd5 b/txscript/data/taproot-ref/1c929a0b875b383b7f3db0d168424cf2ba6d3cd5 new file mode 100644 index 0000000000..fff0191bec --- /dev/null +++ b/txscript/data/taproot-ref/1c929a0b875b383b7f3db0d168424cf2ba6d3cd5 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702e01000000a82179bedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf101000000b57106c802fe846b000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac32000000", "prevouts": ["b7550f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "45bd5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_7c", "final": true, "success": {"scriptSig": "", "witness": ["50bf221dcc4228142ec7f1b58cdf0cbc075daf28ee8a07041cd6f07a20d05696ebca6a7a8d0ffaf9a2449b39c7b38eb29c2c3f0e5c2d039ba51a0b3c92ae7b6501"]}, "failure": {"scriptSig": "", "witness": ["a740c0e16ff18e887707249969575eeffbfa21e71f98fa097001567a45a8504b2913294a49fc25a3cc72a55cec35d5af3147f630280a7b14c6fa3aa9f47b0a7e7c"]}}, diff --git a/txscript/data/taproot-ref/1c974326af0bc49a9f389a9c91eda58bdb47ef17 b/txscript/data/taproot-ref/1c974326af0bc49a9f389a9c91eda58bdb47ef17 new file mode 100644 index 0000000000..b63ae9d4b5 --- /dev/null +++ b/txscript/data/taproot-ref/1c974326af0bc49a9f389a9c91eda58bdb47ef17 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40502000000389ef4cfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cee01000000e0711392020eb285000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e55e102f", "prevouts": ["67343e0000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "df294a00000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/merklelimit", "final": true, "success": {"scriptSig": "", "witness": ["fc777bfd39e7a40f276038dc2bc4c815879daf9a58586353d6f3f85ee628a1c2dd5353de835c4020bd07ff63da79a03d921019893ee36314ae0ef668da1c456f", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}, "failure": {"scriptSig": "", "witness": ["fc777bfd39e7a40f276038dc2bc4c815879daf9a58586353d6f3f85ee628a1c2dd5353de835c4020bd07ff63da79a03d921019893ee36314ae0ef668da1c456f", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93672ab2582871329e6d2ee7428615b3ca131667fbf9a036ced2b197b0b63c7847f72ab2582871329e6d2ee7428615b3ca131677fbf9a036ced2b197b0b63c7847fbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}}, diff --git a/txscript/data/taproot-ref/1caae5c5cd8d5b5cbaed34c3bffbfa19df6aa109 b/txscript/data/taproot-ref/1caae5c5cd8d5b5cbaed34c3bffbfa19df6aa109 new file mode 100644 index 0000000000..260ddd1de8 --- /dev/null +++ b/txscript/data/taproot-ref/1caae5c5cd8d5b5cbaed34c3bffbfa19df6aa109 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8600000000ce2f9983dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4601000000204160840467558b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ba17e93a", "prevouts": ["35af690000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43", "468324000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402207686e00c97162febf58805365e573e1fd0aed87eed6e265268aded331b55b05102202b76a217a8ebe51fd962739ea9065c67a104185abf22b4e7538217e7cb81072f81", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["3045022100dd3abd03be5be846e41d4fc544313f60598ebef60284bf3b954428f6868e187502206732f3dcff5b38dbdccc1f609c0510d3e9b4387b3d5dec49d1f2efa96f61c3b981", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/1cb39f47f10b248d485afd4c83fa450fe4dcf928 b/txscript/data/taproot-ref/1cb39f47f10b248d485afd4c83fa450fe4dcf928 new file mode 100644 index 0000000000..6364359fd1 --- /dev/null +++ b/txscript/data/taproot-ref/1cb39f47f10b248d485afd4c83fa450fe4dcf928 @@ -0,0 +1 @@ +{"tx": "67740b64038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48b00000000cbcacdbcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a010000009adeb4bedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd9010000005dd15aca02d7dc9800000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac56737540", "prevouts": ["ff1f310000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "d85b480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6f8f21000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "897d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ab344e4b6d97d5a92cc1b05df0fe09e2cd2d4682c3139258fed99670b6ab8d41726cb8b9ef30538f8a1a93f31e75c47dd280be49ef0cf0ee8d9ed88fe0918226c56da6b4a79dd49e001229b88fb5122d120ac43d63d1be0cdb38b208b21132e"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d4b8046dad04a3772f9ccea4aa6561ffa13699a4d5ce62fc25982fe6640a947d25e476051edc329ceb3a02f4bde28569ef4d6846a9140276d24ddc98c1f436ac1726cb8b9ef30538f8a1a93f31e75c47dd280be49ef0cf0ee8d9ed88fe0918226c56da6b4a79dd49e001229b88fb5122d120ac43d63d1be0cdb38b208b21132e"]}}, diff --git a/txscript/data/taproot-ref/1cc704edb370c2b52aa731bd30ea881ee0b2eb53 b/txscript/data/taproot-ref/1cc704edb370c2b52aa731bd30ea881ee0b2eb53 new file mode 100644 index 0000000000..30a44c6ddf --- /dev/null +++ b/txscript/data/taproot-ref/1cc704edb370c2b52aa731bd30ea881ee0b2eb53 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce501000000881946a160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270870000000050efa3a7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb100000000ea994684043ae79000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487046fe641", "prevouts": ["b8fc5900000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5", "d298100000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "290d290000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "697d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facb7a7ab5fd71851d574a9c26887a3027e1173994a10fb9074a9680b95d402bf38dbbed29828226c3a1e74b431b518dca4e99f1ee054f76cd9b7bd5529b5cc8688de3449b5e2c621283b68ab187cecafc7aa77a8721601b5317d3484f84536019"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366514e2792df6cd73727562f46c93cd47aa533cf6032189900e3e0a43e73e7f3e7bbe6274b0dcd2777fc9b1075bd65318fdd52335751f1d5034a6ddc9c2a447578de3449b5e2c621283b68ab187cecafc7aa77a8721601b5317d3484f84536019"]}}, diff --git a/txscript/data/taproot-ref/1cf397672140f803d1c48c64b7a9b55ed395d983 b/txscript/data/taproot-ref/1cf397672140f803d1c48c64b7a9b55ed395d983 new file mode 100644 index 0000000000..02ddacd6eb --- /dev/null +++ b/txscript/data/taproot-ref/1cf397672140f803d1c48c64b7a9b55ed395d983 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4680100000014cd4d66dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5b01000000d231e7ff03efb58d0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc27030000", "prevouts": ["9db93700000000001654142540f27e90740933c99d4f17ab2dfc6c82951cfb", "7b045800000000002358212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["11f1c55903856f2490e230698c97a7170a192ec750008f08d002d35e89a335566076759e504b9c5780d7077cd426e1639c3e0d113dec6a9a678118987f1e4af0", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/1d396736b3bc9203fa55467a0775f7a058a44b05 b/txscript/data/taproot-ref/1d396736b3bc9203fa55467a0775f7a058a44b05 new file mode 100644 index 0000000000..4dc763423c --- /dev/null +++ b/txscript/data/taproot-ref/1d396736b3bc9203fa55467a0775f7a058a44b05 @@ -0,0 +1 @@ +{"tx": "7b8f2880028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46300000000896a89f660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c3000000008f1288ee01e55143000000000017a914719f78084af863e000acd618ba76df97972236898700000000", "prevouts": ["2c12410000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "797d0f0000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "b87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8d64c15a931058236adef8a4965d2af6c40e751c52c93bf72b53dfa72cc6c024bd12296fcc73680f3617d8f33f0de746e19dcfecb08411ea531ade48d4ab609a0"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e5c7be958f18497b82a5f310769c8b8ace0436200d1bb32be05dbac5afb51b7c71ca511921a6acb6b52511c7e467c1fdb04a1d5dae2a81dbcc486709376a8609dd12296fcc73680f3617d8f33f0de746e19dcfecb08411ea531ade48d4ab609a0"]}}, diff --git a/txscript/data/taproot-ref/1d4be0ac5b202d439cadb143602ea3459a3eea33 b/txscript/data/taproot-ref/1d4be0ac5b202d439cadb143602ea3459a3eea33 new file mode 100644 index 0000000000..ddf70daa85 --- /dev/null +++ b/txscript/data/taproot-ref/1d4be0ac5b202d439cadb143602ea3459a3eea33 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41c0200000090748d82dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cec00000000327a6adb04bd048500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cf0c1a4c", "prevouts": ["d0a93c0000000000225120dc347dac30d55fcefc955ccbc6791a94d629e3a9213464313d15e8052cd76ad1", "f6434b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe79816e53960984aa9f9324f7580bf1e252717c8ddcb06f3034ba39587c992e"]}, "failure": {"scriptSig": "", "witness": ["6a12616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/1d66bb4f8ee00895bb9533eb0329de6d26b4e395 b/txscript/data/taproot-ref/1d66bb4f8ee00895bb9533eb0329de6d26b4e395 new file mode 100644 index 0000000000..b08117d061 --- /dev/null +++ b/txscript/data/taproot-ref/1d66bb4f8ee00895bb9533eb0329de6d26b4e395 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdb000000005eaf85bf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e0010000001162e7efbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9701000000c3c69fd004347af5000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac82745761", "prevouts": ["612151000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "c6b8340000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "f439720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["984c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c161624a971c36aa6290c86687ec80062b931dc8c82c07703e18fb2ec2014c60afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a4b5563559956b4521d685614895115ff3b761ab3fb4dd1d8def3bf310bb092b594c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900451f4c7988b5621a2b4ceb0e4a0295b5522bdaf57a14af19f5e9873d8ccb0a4f054b5563559956b4521d685614895115ff3b761ab3fb4dd1d8def3bf310bb092b594c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}}, diff --git a/txscript/data/taproot-ref/1d6b45d432e1a9f7bcf2692c87fd3865d9e96451 b/txscript/data/taproot-ref/1d6b45d432e1a9f7bcf2692c87fd3865d9e96451 new file mode 100644 index 0000000000..68c145e6cb --- /dev/null +++ b/txscript/data/taproot-ref/1d6b45d432e1a9f7bcf2692c87fd3865d9e96451 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8e010000009d47f8c3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9c00000000643f149804cd20a300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac550ddd44", "prevouts": ["3958230000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "01bd8200000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360a008098802adc05b7660f80fc20c7ba5a23d2bd0801d1158072548832fd78b18080c17c1a9ba5ea8a3780f9d0897aa41ac6e03bb9fc27a0b4027847c33ef9f08f84e1cc8430872045fc695723e7e8ea88aa60745b893850b41017408051d8396d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663f772b330758ff91816ad5871b5e8f137c7278d3b68f945670a0b97a4fd348222ac0f20434af06d5694002e66a328e774b08c17356336e0bf0019524f47df1a7470af5f469e43c444817efa23ad8740a4ec3822d36804e7973b39d521bdef59faeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}}, diff --git a/txscript/data/taproot-ref/1d6c3731bc1125e0c52a0356e80d994f891c5e9c b/txscript/data/taproot-ref/1d6c3731bc1125e0c52a0356e80d994f891c5e9c new file mode 100644 index 0000000000..15552ad006 --- /dev/null +++ b/txscript/data/taproot-ref/1d6c3731bc1125e0c52a0356e80d994f891c5e9c @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c730000000007e7cb39bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4a000000006802958d0482acd60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac15766851", "prevouts": ["4500580000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c9af80000000000017a914b0b53ba433a336ced94ed75e23248458a1c69fab87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2252202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["5d0bd60061e5efbf062c0c572eb308a43704db88b96943fbda77dd4f9d1d97cd33c696ac36c089951dd2bd32b0933da4706cec06b97a5a9a290e728b1afd0703"]}}, diff --git a/txscript/data/taproot-ref/1d83703eed5baa3599b3562c9ea6f395f0ecacbd b/txscript/data/taproot-ref/1d83703eed5baa3599b3562c9ea6f395f0ecacbd new file mode 100644 index 0000000000..3f81e4f9c0 --- /dev/null +++ b/txscript/data/taproot-ref/1d83703eed5baa3599b3562c9ea6f395f0ecacbd @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5000000000b2eddc38bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9b000000005a19fb67020823d500000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac37a54057", "prevouts": ["fe80540000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1a6f820000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e", "final": true, "success": {"scriptSig": "", "witness": ["1d898af12645329314121988bca247d8058a4a07668854d1230edffc57c9ba153634f60451d8f2b1f3f326922d9964c54beb0784c374ce67c2d8a6f96d7a887801"]}, "failure": {"scriptSig": "", "witness": ["4713e0a951a41221f90b51516adb5e13c07d104f62e82e715156c4a99939e7193e3b1866035c75fc75d48daa703bd35f5b8f1b1d7c9f36c95edd2417efeed91d0e"]}}, diff --git a/txscript/data/taproot-ref/1da56d6e6d60e92c14472e47b665a85be68598f1 b/txscript/data/taproot-ref/1da56d6e6d60e92c14472e47b665a85be68598f1 new file mode 100644 index 0000000000..4a9e24b7d9 --- /dev/null +++ b/txscript/data/taproot-ref/1da56d6e6d60e92c14472e47b665a85be68598f1 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ad00000000d70bf3c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b08010000005adde9fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b60100000078ddf57604cdc96f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787521e713c", "prevouts": ["6eb8120000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "686e1f0000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "02ce3f0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100cd39a39352e610354339855f7764070783c64dfb51e94ccb5402fe45ffee70ec02206e2aea3ec7777536a73cb5a604c1f87435c64d05251a235d5ce15597cd31471903", "witness": []}, "failure": {"scriptSig": "483045022100da7de1c027823bb7ee1d3365ef19a3d48ae72ec52baccfafbc1af3e92d68185e0220684939173578d11d459d1ebe2ed19ca2978f160209de889bbe65336d97fd158603", "witness": []}}, diff --git a/txscript/data/taproot-ref/1dd5926d9df81e85da3075d37f0702718c88900e b/txscript/data/taproot-ref/1dd5926d9df81e85da3075d37f0702718c88900e new file mode 100644 index 0000000000..43be68e12c --- /dev/null +++ b/txscript/data/taproot-ref/1dd5926d9df81e85da3075d37f0702718c88900e @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bba01000000a2f78b97dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b82000000003a48009dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5301000000e7fb77e004cb3fcd00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7f2000000", "prevouts": ["d4b42600000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "69c2270000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "926981000000000017a914971b3e5f9ac480bdcebf6ea71a9fc7de0ab164e287"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21541f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["4292cca86b1b659a1536c0809dbe9ee735a3f3c75c7923f1b1fd213cb26875c533456f950943e6d6c95370ff3a62d8986998da89659d83be93e072de654bc626"]}}, diff --git a/txscript/data/taproot-ref/1ddf875ca22b308639d7b1cab6ee74ea77bc6bce b/txscript/data/taproot-ref/1ddf875ca22b308639d7b1cab6ee74ea77bc6bce new file mode 100644 index 0000000000..9ea6467c2e --- /dev/null +++ b/txscript/data/taproot-ref/1ddf875ca22b308639d7b1cab6ee74ea77bc6bce @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4100000000ade270268bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e300000000586a0d6902a64ca4000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c5010000", "prevouts": ["d61a740000000000225120e5be1c56293dbf2401662c2d3a0e5c3ad348f091e23d387b2bf628c220dc03c1", "b02c32000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369b94a607fdb4e67654022166c29e3d68c7d66d8db4d337314bdf481760aeb4b9"]}, "failure": {"scriptSig": "", "witness": ["6ab1616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/1de45c6257377171ec1383ff685db7ce8e13d8c4 b/txscript/data/taproot-ref/1de45c6257377171ec1383ff685db7ce8e13d8c4 new file mode 100644 index 0000000000..f1a04212b2 --- /dev/null +++ b/txscript/data/taproot-ref/1de45c6257377171ec1383ff685db7ce8e13d8c4 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1200000000f79331a1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1c00000000af1cfe2a0186b90c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d3d29e43", "prevouts": ["46751e0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "1b83220000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09027e716760078390cdadb0e9260390b88e80098d43502e4672c8fac6d770c8eb42cdb4854a650bfc14629fc38122eec2f3eb0012876861157c780db41969bb8f6b00fcfab393b5fe72d0f5db254f39db30728c397871ba12dc2cf76c7cd347947e8b48262a0e6b8078edab1955a623071b4f180ac3e1f04d87fd76bd4d79f5f93118738002cba5b78eef52e27f5fd2bda939fe8261439196a789e418b27fb34308e10a82cd6eb2b9e7d4ccef6b277d420ea6830678268b09fd16f5a1890b8942d3791129c5848e9d4513307b8bacb61c30ef96cfe16799e3042a7d2cfc649143b610c95191d4de8f8b76b0581ccb7ee1d8af237153d5b128af150dd9593ed0c577a7c7f8fb7a8868504e3a5db5686ac7b94db04c2a72ad39c5822b4665fede0eed0e3ca09030bf676a99f14643e4fbd9dcab698378213e18cf9abf28b5b3abc3eebc5cf297760c79a6e07fdbfc12aea095543c246e48a50437e0e7774d4c30e8719304a58dab234a958bccc260cd66204eefecf2c9e0290b3974c5b4abff01040350c2a8e5514505296d6b1170d404a5493ac59a19408ef6b0c87865c3464ac95015b7fffab5e2433770ec5366510d466d255f3b5cb95f86122e4ac03b18acd584bc34690620e29ccaaf29351d152f2965996f184202c3282f11a6792e352777491fe6d01c36c3d606b7d5281f03ec344779b8dda4ecaaf468ad641dc55f002c0a44fb20b87bf012a56375dd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361dd1f325c7599a78d92b2d23b27ca74bab0f6f46d0fa61f693735ede031c6bf898751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d5c12d2886f924517b8c41f4755cb69ff55f68e740076f0e346dfe7ab1da23e202491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}, "failure": {"scriptSig": "", "witness": ["4d09028a5657ad0cef0fc2f60c361e3773fe48ca7c066bc0041df797f0c742dc8240da2b4a183b579a2615e3c6f32b650b7021161c2cd68b4b140d52a28f1f327d402865b29ec18d2ac856309782eaf390d19167c42dea8e75b0b423e58eb647481d0010515dba3334450c6f72c1932d37ffc239dcc1c55e72cc12947cfa10bf4eb3f73eee6574eb2e606c0b10a1db3726b8d8879f49f6d84870bc7aeeb389f59bbec5d4669b681fd7aa50b25a514e4ec63cf770e661f610279419ae35717412f5f6d7147dfcde9c04872bdf2bb9ec152e612340a0aa94b7faf636214c12084ce492cac3bd2b11e9685535ea207b8083450a8033211f54b676c167711bf6d267c45bf8716c7362a48aa74b21e6d2f097d1616d2c620345918267866b01224a288e0d13ea22883476de7b07a3fc091a8c4d5ca61b3a4272d582b0ba217597c987d043c17bcdb5e461c27f821988095ac1f9be21c229517a9eca4483ce3f0154fbf8e48903d53310948c5b975c6280c1123ae25946bf9fca2b249adfe9e685811b945a42035ee762bfcb4cab1aa383c4ec40b91f47c578f4313f922f01422cd61d301b9d08bb8aae7634bc891eb853f7caa7b967b813fea7311ffb0b4a94b2c28ea88be4d3f2cc3871f620fb394f201d75300b5b61839f8590da79ce80e0dc34e8704bf41c9ddc443333b65ed6a2eaf55174212f29d65f4634a54ecee6d2cab1cf0b07fad1d935aaf793c466687561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d058489ac116bc6dd9b95d4e3df35f96fc6c43c4fbdbaf0f126d19fb49e472fe6ff37e966b1384c4d5bfa916e4482452180179a80b37f756d07f3e2976ea2d444f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}}, diff --git a/txscript/data/taproot-ref/1de7bbede303fc60efdde225de97fe6e4cfb88ef b/txscript/data/taproot-ref/1de7bbede303fc60efdde225de97fe6e4cfb88ef new file mode 100644 index 0000000000..b184d42bcd --- /dev/null +++ b/txscript/data/taproot-ref/1de7bbede303fc60efdde225de97fe6e4cfb88ef @@ -0,0 +1 @@ +{"tx": "bfc6bdac0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705d01000000a466cbd7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4901000000510497b3033a5032000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8700643d2b", "prevouts": ["e9d1120000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4", "0ded210000000000225120803c4cefbfa0d88ba71bbfceadb0978872c77a948bd70ce562f9334bcd1dc6dd"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["0d8b3925a29252d5928eb1425abd42dca2f5f952fe4141bae1f69fc4e09910beef62953a7e1af241cd45ce1784c7bca02b687638ae539b8d5b981a59835debaf01", "855f152b8fe068340becfc15f1bfcbf7fd1d10ed67b0ef10db1641a82f5c73a95e3ffc225e28d9e339e24311efa6177664a6dfe14d34ae2022a0e8f14c1c150488d9f68f35e6c5e66a6410fc18eb", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a9c58bd41b8fc2379fbb89e979f65b4422719c0e5523b14d43ef7b58bc771b6141a604de8df597194a64a0393f98cc7dcb73e0445b1fdb8f7c5b9743dca7dd300000000000000000000000000000000000000000000000000000000000000009c334e28a41046a614ceb75041aaa8c50b3d2a63c6e199d1a52e17618ee578baf20b1a94752e5511701c811d8863fd07baa3bc138935a9aa0da4c40ccd50dd3affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33513086926ca65d1bcc0ed5fd54f0689e45ea12db577c49ddbeb7fb43895dc05fe8fc5bb3a8eb867f16081e9ff7aab4d1710b464ae04eacbcadea3e96deaa6db251d6000ac52413b8fcfff7ee8cf2a0e783127d3174d4b0c3d18b89562425fe50dc011f7abe9c52b51148917e176632021610f66786cf7eb22e578e382f5d8d23fd60d9f80ffd76c86606ccc070913271e3ae9763ecec8920c600546263f1dcb5d780805fbb369415a2df853983e46d2bbb7de6af62bdcc1630a3ef74128fab29321d4e4e64e89faf895fce335166a483ad5ec640d21f3dc9aeddbf4c594ddeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc129f5a01833e6f687b8d7acb7a198db8c9c6219d9d9e3bb04eea564e9722b2bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5376d1fd9eb5bc7ed5f740970802297606290f8f37c225c2d56c45dfd2e6b2216e069c73ce93231aeeb36f8ec19c13d481d4f01d9a4d1da23ff324a7a0570fe5cc68a4a01876e525de7e7cb051ba59788552a64f2653fba1ab2a5862c0786ba94a406f5d2c9bf7176b77884a7beef7c28d71927f64fa010208f90a29e6799245ba64a3b0e8a7a4761d9d26d99b9a31edd5b957f99544d69c34a1f500fbcccfd6683087cfbe73f76bd4afc2ba12238ceeed9d84dd753404b6da4208c999aa5cd70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff489008f17c7972c9361baeda34a36d693684286c266b690add962b31e70e04f88683fce20851725ae0c5e6b4e234a0ba7f9ce1f4f167ad2a67459773200d227ceb346fa033c86bca2ab196f3d9a277ff388c861d6eb62922f27c51ccb8a9515ac9233b1e9b73ff54d05436db65ee331970b47db36b384177a6176e14616acad5c397125a5fd584d44faf56567216dec2289faf20a81dd2d3c462bd2d16d3b6a3b0067d58d044ddad4bc6ba80633bfa6aa3c1007d2d9f72e9a975c5f3b715c0baa9ac4db0116efdd97b24b49f296c9041697ac511d91986401bdd1ddddaf461dde57dedd0587e36469271958e71ff56af782b2dd92340df151716636c42b8eefb799c3c66c1c579c0f0f16cbea9c8bb5478e0bc79b0c66714798e9a9f95a3480cbf25c48716c0c7c3adfaf1388e411ab300f1a46e9600b2871d546ceb556d8f82ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb65226b1358c415f1ffc2f1e836aad1406ad36617332fd7bd26e688618d9d1200000000000000000000000000000000000000000000000000000000000000004f6b4fcd8ed4389c0c016bcfc73e722ff2c65d6bbb7995453a88f1b68a0776d30000000000000000000000000000000000000000000000000000000000000000425c88510c0fa6d7bbbe212f5347cae05e80400212515cb35fb6c60db3dd1fc8ea7f5252bf9ed9ae8b70f35a93b421ef96a8a90684e016695af5f35f1be840966ed52a2f8d8268f293b666f6f7d5aa84a6aac3b3b1b80087b14bbfcc13b0333ca86f15b40294dede979afc3e173c68d45e38f7197a4cec150a9d4e5cbe441d66000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f421c128db20477f4d8b18e4af2cfffb92d01f8bd46fd88e4ce69d41252731e0d0e50c2c3729f7be46608d0334d5cd7dacbe28801502d31a3b18bc7c1a1e65fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6f642cd6eb08ba7b702c471f5f14c176fba15056ed0fbc4bf77626d64ac3df7cd152295262efbdc1502c9f6d815a04a67eb1cd0393bb4c5f67e1287543a990d8a549c25773a3b30a38f5bf32ca94b5a26c2eb1c78756bfb210a8b3751f46341c2d7a7bb1792b15814c782f6ab02c7a34c534ec00563f34ec1822221a0ee6b7df46404cd4305a0820cdc24ad9783542060f3c033aa489f191cfd014fd227a056a34d0d157a1b71afe486f707ea2d249ca1058b7d3a7b6425c4d2393611ad1d713029e075b5bca6f59c6777db817e96677c5e3626cb35248a4dc2f5d905f7071839ff0b8c72b268e09099c620c2f720b27733db3810b619bec5dcdc11edc7a0ae7867d4da97da20fe8559412ba979c238f4dabef763b01c01eb4750d03490c5bb97c130b7b13378352f912eb3b93a5d722c0a912b8600898fd38202e24ea55152eeb00ce84d720d311b5627fab1f4fab7f524bbc51b1a164b81164d54c8f59d6a868df0eeca945bba6643b776bc7f907f2d9b76186b6876b3bd714c0720ca7d9f7ffe4bc49df7e9fcc86a3e3effd7827b57255624f65787cbb010d4d23c23b0a47e306b1f0458efb8eab487be7e5493f2c193660054babf701fcba9537466a092a38187bdfdb079bb9d7bd4be10adaf2b07ce9c9b807da99a11642831849b4c8f0", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["0d8b3925a29252d5928eb1425abd42dca2f5f952fe4141bae1f69fc4e09910beef62953a7e1af241cd45ce1784c7bca02b687638ae539b8d5b981a59835debaf01", "3cbb21efe1567520b2461b1a88d0d35f17e40fdf502df93155271bd61c475f8402b18eb1e289b75652078d6547c204b016796896ff9a184553e4426fed5aeb508eb5d016b3f0dbe04cc6b9a871", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a9c58bd41b8fc2379fbb89e979f65b4422719c0e5523b14d43ef7b58bc771b6141a604de8df597194a64a0393f98cc7dcb73e0445b1fdb8f7c5b9743dca7dd300000000000000000000000000000000000000000000000000000000000000009c334e28a41046a614ceb75041aaa8c50b3d2a63c6e199d1a52e17618ee578baf20b1a94752e5511701c811d8863fd07baa3bc138935a9aa0da4c40ccd50dd3affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33513086926ca65d1bcc0ed5fd54f0689e45ea12db577c49ddbeb7fb43895dc05fe8fc5bb3a8eb867f16081e9ff7aab4d1710b464ae04eacbcadea3e96deaa6db251d6000ac52413b8fcfff7ee8cf2a0e783127d3174d4b0c3d18b89562425fe50dc011f7abe9c52b51148917e176632021610f66786cf7eb22e578e382f5d8d23fd60d9f80ffd76c86606ccc070913271e3ae9763ecec8920c600546263f1dcb5d780805fbb369415a2df853983e46d2bbb7de6af62bdcc1630a3ef74128fab29321d4e4e64e89faf895fce335166a483ad5ec640d21f3dc9aeddbf4c594ddeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc129f5a01833e6f687b8d7acb7a198db8c9c6219d9d9e3bb04eea564e9722b2bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5376d1fd9eb5bc7ed5f740970802297606290f8f37c225c2d56c45dfd2e6b2216e069c73ce93231aeeb36f8ec19c13d481d4f01d9a4d1da23ff324a7a0570fe5cc68a4a01876e525de7e7cb051ba59788552a64f2653fba1ab2a5862c0786ba94a406f5d2c9bf7176b77884a7beef7c28d71927f64fa010208f90a29e6799245ba64a3b0e8a7a4761d9d26d99b9a31edd5b957f99544d69c34a1f500fbcccfd6683087cfbe73f76bd4afc2ba12238ceeed9d84dd753404b6da4208c999aa5cd70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff489008f17c7972c9361baeda34a36d693684286c266b690add962b31e70e04f88683fce20851725ae0c5e6b4e234a0ba7f9ce1f4f167ad2a67459773200d227ceb346fa033c86bca2ab196f3d9a277ff388c861d6eb62922f27c51ccb8a9515ac9233b1e9b73ff54d05436db65ee331970b47db36b384177a6176e14616acad5c397125a5fd584d44faf56567216dec2289faf20a81dd2d3c462bd2d16d3b6a3b0067d58d044ddad4bc6ba80633bfa6aa3c1007d2d9f72e9a975c5f3b715c0baa9ac4db0116efdd97b24b49f296c9041697ac511d91986401bdd1ddddaf461dde57dedd0587e36469271958e71ff56af782b2dd92340df151716636c42b8eefb799c3c66c1c579c0f0f16cbea9c8bb5478e0bc79b0c66714798e9a9f95a3480cbf25c48716c0c7c3adfaf1388e411ab300f1a46e9600b2871d546ceb556d8f82ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb65226b1358c415f1ffc2f1e836aad1406ad36617332fd7bd26e688618d9d1200000000000000000000000000000000000000000000000000000000000000004f6b4fcd8ed4389c0c016bcfc73e722ff2c65d6bbb7995453a88f1b68a0776d30000000000000000000000000000000000000000000000000000000000000000425c88510c0fa6d7bbbe212f5347cae05e80400212515cb35fb6c60db3dd1fc8ea7f5252bf9ed9ae8b70f35a93b421ef96a8a90684e016695af5f35f1be840966ed52a2f8d8268f293b666f6f7d5aa84a6aac3b3b1b80087b14bbfcc13b0333ca86f15b40294dede979afc3e173c68d45e38f7197a4cec150a9d4e5cbe441d66000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005f421c128db20477f4d8b18e4af2cfffb92d01f8bd46fd88e4ce69d41252731e0d0e50c2c3729f7be46608d0334d5cd7dacbe28801502d31a3b18bc7c1a1e65fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6f642cd6eb08ba7b702c471f5f14c176fba15056ed0fbc4bf77626d64ac3df7cd152295262efbdc1502c9f6d815a04a67eb1cd0393bb4c5f67e1287543a990d8a549c25773a3b30a38f5bf32ca94b5a26c2eb1c78756bfb210a8b3751f46341c2d7a7bb1792b15814c782f6ab02c7a34c534ec00563f34ec1822221a0ee6b7df46404cd4305a0820cdc24ad9783542060f3c033aa489f191cfd014fd227a056a34d0d157a1b71afe486f707ea2d249ca1058b7d3a7b6425c4d2393611ad1d713029e075b5bca6f59c6777db817e96677c5e3626cb35248a4dc2f5d905f7071839ff0b8c72b268e09099c620c2f720b27733db3810b619bec5dcdc11edc7a0ae7867d4da97da20fe8559412ba979c238f4dabef763b01c01eb4750d03490c5bb97c130b7b13378352f912eb3b93a5d722c0a912b8600898fd38202e24ea55152eeb00ce84d720d311b5627fab1f4fab7f524bbc51b1a164b81164d54c8f59d6a868df0eeca945bba6643b776bc7f907f2d9b76186b6876b3bd714c0720ca7d9f7ffe4bc49df7e9fcc86a3e3effd7827b57255624f65787cbb010d4d23c23b0a47e306b1f0458efb8eab487be7e5493f2c193660054babf701fcba9537466a092a38187bdfdb079bb9d7bd4be10adaf2b07ce9c9b807da99a11642831849b4c8f0", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/1df8c615c5b7d5080d1019801137bdc97c72d639 b/txscript/data/taproot-ref/1df8c615c5b7d5080d1019801137bdc97c72d639 new file mode 100644 index 0000000000..2e44f05393 --- /dev/null +++ b/txscript/data/taproot-ref/1df8c615c5b7d5080d1019801137bdc97c72d639 @@ -0,0 +1 @@ +{"tx": "1a1da20f038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c496010000003477079360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127029010000000b0db5c160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700e010000000bfac8b303bf195b000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487198ac73f", "prevouts": ["ed513c00000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "fd2d11000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9", "5ac90f000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "4830450221008c530efe6c078e627fc8e56d518195b4a6cdc486b85831ae546c4d935b8db6a8022008d2f9353e940029a8a96fd8568578bfc9dd8abeec91d81cbb6f4b0b79ccc62602004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "483045022100a090d756e9f1ed649b6ef69b8d83da87c604ea10e700ad0bd9547163faa215fe02201be9fd953ca42c83e176a0121cb17c70887afeff4b550e2c6aec0df9331e64c80201014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/1e2b8ba68f2655f0f5159ba8ee446f920bd6f384 b/txscript/data/taproot-ref/1e2b8ba68f2655f0f5159ba8ee446f920bd6f384 new file mode 100644 index 0000000000..ab0d401bca --- /dev/null +++ b/txscript/data/taproot-ref/1e2b8ba68f2655f0f5159ba8ee446f920bd6f384 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6900000000070fc07ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf680000000062cb832204efafcf000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2c000000", "prevouts": ["0697650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "24df6b000000000017a9149d4bcb1ed806c9beed692a78614f8b90a68c708187"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_50", "final": true, "success": {"scriptSig": "", "witness": ["ef1c081533d72348c49b6dced51bf3dbe9f33e3a18e76bea3a51e8e9558f908ea49b2cbbabf6cae85ac397dba0cdb9971da85a595f57d236e6bc533d6fc7783f83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1c068c111f27015bcdc64135671066e2c873572f3dedb5187b98592e47212079a9e22be2dec9dd33300968d016a93d51d6d0074216113a69215de44ee33f0fb550", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/1e2f14f392e271b5a594679f83b4847d83b8109a b/txscript/data/taproot-ref/1e2f14f392e271b5a594679f83b4847d83b8109a new file mode 100644 index 0000000000..d6c765871f --- /dev/null +++ b/txscript/data/taproot-ref/1e2f14f392e271b5a594679f83b4847d83b8109a @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41d00000000c6f337eebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1f0000000004cc6ffa02a323b300000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987074dfa5f", "prevouts": ["ec8d3f00000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "768e7600000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090289df5dfe666d2cc917e1f55821de1ab143027be0f2ab94845395685182a511a4fbd06f6550babaa8e15cbd24d6090a762ac41e8fd6777ee121423f4ab9fadd448061d721e9614ef46665752ccae11ba8fb8b3e0e8635278d6d1a41575350502d3532aced57cc6793ba7b319de455086c750edec36be168460493ce8ab3b4959284f08f22e5455741738407ea852b845c813effc44941197c00d9cbae33c2a21790845a760592fc96200e7b9f4615e4f65431e19915a5bf9c397b116ce39cba73edd44e22dbc743352ac7715af58be0791ff7ca80f9745a5ed24d555dde57515806c23d55582ec53a78cf66ae28835200ddbefe49c6638d6e4ac21951af73e631a24b39dc18f31e4e2f1d9641591faec6e4fb5235020cc2020437a11110d38a1f5c64cb25df9fa762cceedab2a362acda54590d2a7b85a288d58282b238a225ae1007afdf53e71da548897ec153586a02273985403754dd9b138834e14ef64fb64cf735a2a0a17854149e7187c00cd216f40a40b7712f585792053349e23fed08c9e0a7d4c9a772ba16396a8be3d9d93ed09296f0e7e5246f224c75e33a0133b5d42eeaba07f288a367dfbcca385b7ef9d4e7ff9e1d0398d7a543691261affa79c5b18867b36c9df9a813aa07fa3e5b8a6cebbc5e1b7caf968837198d1d6563b94c42464bea000a1eb4b8ac9f1585a8adf23ab097311917b61d777514e51709c46abde176591b5f1f3775", "387d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db3476583035a6d1b88195251aaba7e67b83c65ae24581826bcc4112443d611c9b60e5914c50703ee8fed26b085ec7bf74c965cec3b126e70865dabf0c3179e2a12168afdb4ef286e7748ddb08cf408d85b089f504486378d2bfb535c0d2875b"]}, "failure": {"scriptSig": "", "witness": ["4d0902033937b9697af058a166983e989845de94fd06d6c9d4e471685d7514abe06a1f7b44e0e957743d407ea3b60fce90065c8a69f67553571af6e56d23ebac3029343636cac22ff003874c61d825dd304a5b4eb7b01eecc990cb7d6c7e557a028700944f802fa0925ca5fde07f62cfe3a4103407279040fa481a3f7a8a7624b1467461abe9d43be8e2c5b350a094a2e21135a130be57e1b8d0d0165844055a60a68cd4ee92988958cfb233f39a1bc19ce82db3886b7472b5343eba62d15cb40cac2848da8082b76e09355473a7f986257ad0f6aa09cdebc338b874688b9e123d1eca488fa7a21bc2f1b277af53a467efda2440e583114274926d5a534c08a32652f9e752cafac51892ef0dfa4f03fd75bd9681254cd5d2fa7109b78b3cf876db2b014129cfd6d4233f265ad45e8a9da8a3f10c76f877bdebe043d1950124bcefc63a3533481808ed912ed38e0eb7f1d1ff1b7c1feaea1a6dc09cb7a6b287cf2cbb2d43d5cd702c17d493be3e007a0c8c727ae57bc7e743d62a018985e2b0102cdfd50e4a6641993b6406da5b3bb3b55cd017731a74ea96e041a25b66a48cac438174f9ba6704bdcac41446e98f9e81fc9473d27a18e6149fe63b187e814b0d14cb104c8d6f0a0b468371e8af6ca385b46067668053107ff1429326fe98adad3b6cb9dfd822ad3162ab16909d987a0ef69448dcfdc5ec6bebfc02e4e9ad4776d41987b031bc5d4a361a1fec75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365bdf44d130d48ddf5aa080cbaba430c6470780414dc9784f104c605fab81d466c542915153386019108494d00e6bbd0a8a4ab824ea9158d8694b82aeea9ace0ff7118923d14a9704f5c6065ead9bf1df659362e443facca38f7fc54a29b18e2b8fa601fcc68a78472d280e0a6f10ace0c22dad9ad93c154f995d1132d7b2f793"]}}, diff --git a/txscript/data/taproot-ref/1e2fa5e498506cf0c5adee563fba8cdb0900cb86 b/txscript/data/taproot-ref/1e2fa5e498506cf0c5adee563fba8cdb0900cb86 new file mode 100644 index 0000000000..197f029eff --- /dev/null +++ b/txscript/data/taproot-ref/1e2fa5e498506cf0c5adee563fba8cdb0900cb86 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9a01000000b5f930dadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8d000000005ea06fac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127044000000007a558cdd0125890e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b1000000", "prevouts": ["5c0c570000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "7bdd4c0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "fc3d0e0000000000225a202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902311e76f30cd86bd8a8820920af5ab36e6884f47add64465d23defc7cb327af1f69d1d0ca4e9b1e2368af7128794c2cf73ffc8f78cb9d12fa45d3ba838ad135a44c6344ff062aea4403e91b8bf9c615f45dc7a2dc87ab8d0e7538eb20d569bfdac14d72c4f9cc555556c04aefb1d04182b2ef05520cf474f7a8f0443ec286dadf8c1833eaa6f1ff5b8dc0c2b202311f4725f8f06c9394d33b2a9cf82d17a5cba6675aa8561fbd22086737ab6306291c2e0b7531ba268c30ca69b2bdc1cae06655dacd427cc8c8919249e0c33338c45ff004126d0b2b782ab1af2d0e82085d2a1688cbd6fa966627fc2283108c48ee1ed1a777ccbf2723701701f01bed96a5906857e08695a7fc4150eef75ccb1f7df5c7dd8802fd40e09e9006bafc2d44d3d06842700bfa95863e667a6b6856e614dcc829b1690bd5d5593a7349f906065d8f85ec4d23d0fa8fcc6fa46519163627f8da5c94ec01d4deb6cc1e8e823cae233776bdf47108d142b0b9ff2856a4eac6ed2916ccb09db4cd6ca6415a052feb625494bb1eabcfc555bbad3a01e43a17581ea500c397249b14e542efcd04e394569f2e3f4b8faad28e28598f384b917433ccb9cc3ac1842c07abceea267b86c33eff30a2184f8c8ff2876b8a785ebbb4b461eec6afb1c22083f65f7dd384f53f8c3b7c4490caff14b1eded19d8e967b77744633b9d9e70c927ef17bf841447113603cd34c41105d4e9bc342f75ef", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5170b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720cc28207c7af5a37f80d9c7bda068b6f89abe5b5cf72eaf80ed3e31c2f1c9dfaa6c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}, "failure": {"scriptSig": "", "witness": ["4d0902352373deff6fc3da049f4124623a135a6453146cbaac9b4da0cbaebef15e339213472c31bccb69db3d201c31f28b91cd1878f7d76f2339edc48b0c8588a521d2fb4ecbb2d4374c8dc404eb072a9b46a0506a9827d98ae409f590aaa2d98edca01188e76b3450037b3518144475ddeaabbd04467d32371dbe579a9422d9896732c308e9659717f2b58abebe12250105b35b1dd56bfa3b8fc42cfabb343a38e934c80cfb66f8b4886b15e372a9999ec4afdcc9326b89e77a26aa4dc046020061882aed4623aac49d20d08a8ac8b8823c223e9ed68f5014179a9cb112cea8b255d6fe471f1127f28a269b9d40b14dd9862782329fb6d7bdc259d3cc5cf980c842551965a28ec33f715af105bbea7c19ed33f5b335927676a0a59d57577c256f4d5ddb1659e9c52d496d5686f08fb18a4a83f7aea273851751af42f1756bab592bc2ff33014dffe01b70cba23b501fd86c083ffc6fc0a7c92477642a62576b273613835ab50d243e82cbacbfe88b017813779804d62bd346faa016e60923ca626517c56d2ba0092c0e4db8dc7c4dc4fa3d13685585fad0d374677eb6cd708dddcfe9c7407f19ea2a0be5f4859a40b7352c6d4fc63a929b1ee055aac4ccb160dd3645ad39a5925978e94a7ad2a630f45e6b298804423f5a2b3470856d5ac98fd7ab1d0fc664fa92ad180898fb2f5d92395cc7fe1b9f5b0c8196b4bce59ec33537a524cb88a75337c60f8f8c7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e190840bd75c8ee6dcc19a553b4e3bda7516a8577ecf1c365a05a7b0ad0f101a1c215b4c606cdda8e0cd0631e1e6566a3457cf9b2eb8ccfe9cc1918e65b703d3f7cd241e6bbc5ebedd8f50ae206f1f82a1e41ff5c139455a0ddb0d368f52a47602"]}}, diff --git a/txscript/data/taproot-ref/1e32a9cc12b73e8a61aaf4c846d1cd0ffa78bf93 b/txscript/data/taproot-ref/1e32a9cc12b73e8a61aaf4c846d1cd0ffa78bf93 new file mode 100644 index 0000000000..ec0507ef06 --- /dev/null +++ b/txscript/data/taproot-ref/1e32a9cc12b73e8a61aaf4c846d1cd0ffa78bf93 @@ -0,0 +1 @@ +{"tx": "e4ba8c7202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c69000000005862f3e0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcd00000000a6beadbc02bf667500000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d7010000", "prevouts": ["d38156000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "608c210000000000225120242fbb4e68c81dfdc905839a5aa96f20c82583acd27e1bde1e06ec2a83f43f26"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/oldpk/checksig", "success": {"scriptSig": "", "witness": ["b00c0ad3306860ca44abb8145f06a470bab5db8e74e2ee20685f616131eec486251f6e958508eb5630b3319ddb7a045d8393e63e7135ef2702230a82aac89c89", "2103871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368f39a0868157845cb7ad47461625d394fa6e029b849baf79f532c059eb0c90de3e8a461a0f368c4eaf94de3746540889bc99fb0c1f5702a0984aea55c9bba1eb22670c87c91ee1fda6f8c1b2dbad04ae44c07618f7e68a5991e1d29a00ee01dec96075c0438de6f0216cdd72c8aa39ebb45de420e1f8e51b4e4692bf34a2e56f8158c8b95398c311670004bd9a4afbeae52e97235779550b29728e38cbd58716465db9b66632241155b259b456613f75f4b6110df8d845f1977a6a00467ac0fb2de7e81d2fc1490aa9ea09216c54370d636a110d3f6d009a2836912482a02ec1416c54da450879e4fe6a281fd904df5a47457cf3faf8fff1fc7cefa1429c1f837cce0c16b4ac2bc0a56a4da93975e15b81bed03d043eda7c9ddac9d51a909cf984b496ca51f1d59b029869e88466a950803e0b1fd0201aa98a66ad53a0d4a0c956f68441022cd3a444817edbae2583eb76683b8480293994d059289218f0d4a79d976568d9e92c4f00b9c8d7cf447c76042a3234918f31ddf63c43fdd94d6a32c000fafc31f95a626ff6b47272847de898d0fe9392d6cb40a47f54dc91f8f8111360dc44ae3d69de3386cee559eb49e6c76a737e105f9117431d64c73a13a31f98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["6f0391293f93ead6b26939209e234eabb3081854bffef81e74c6ba479b736d0c96a9bbe884e5e6c9c8798b5176a6b0410879165953057fe295a782c7faf2fa0b", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cd2d09394ee01f4cbf453b8e43120c6bca0157ff833036c4a91161ae8d6db3dd3595e47f783dea9cd898c640c1ccf4b7d0ff5bfa4236f535dc6b4728299c1d69fb9e9eefbd8dee3e5857c0a5c3742d0e58764b1e6eec73b89290af63b7ef8123f752582a11afed87b1aeeab00a91ac5167325e0fc3825def3a8307d2082c1acae8c13f957496bd85a8bfb196b41115877f1c292877d449cb5d56eb109a1f8e695176267bbd1b7867e2eebc439e9f1978d6a17134b75a8bbf0107687388ddeb5ca20cf31e30816ef7bffd0e43d4efa6c46d11185474d89ac75f693a7c477baa289311c864108ea260dd739a7c927abea94bbd3ef2fa436b5348a12a03476bb9e451f31f95136dbefe9a42f2bb6868f993acae25cfce8fc0d73b984508d267a487b041864f4ad19f6b2782b89895068e96969bc0c0cb50b64c3b84612df4c73208c4bcf6cb070e67449ea1a036232a8155856b27be4c634558db013e06b79c26858824757e3ab18b9476867ac69e63e36877af9fee4aeb519472ff5a504bc7e1bb8a70b57e599289922abee7f7cb3f5c4b4e0126255c9af59ddd6c8d572a0551d9a0b10fc29ed9ec9ba811a78159d56d191855f20d80384a7f598d54defaeda75074e07476023602dfde1c8d0d124f96edbab4af8198f97e6bceba6cad7de517a8f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/1e5a2d83584c4f1ccd8746aa4cc87f3b5c520e63 b/txscript/data/taproot-ref/1e5a2d83584c4f1ccd8746aa4cc87f3b5c520e63 new file mode 100644 index 0000000000..36fb354dcd --- /dev/null +++ b/txscript/data/taproot-ref/1e5a2d83584c4f1ccd8746aa4cc87f3b5c520e63 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6c01000000caf387b6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0701000000d913f3dbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf000000000d47bb5d904ec5a0d010000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acef05f434", "prevouts": ["5591730000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "a0b64e0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "88954d00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["624c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f393068994750671244e9a386d61bbc7bdd03428d67a6b3b3603ff438afc80a6abc42ab3738335b78a2a7135de763706b017ef32cb75bc24ca1210f74f6e5b7b3fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}, "failure": {"scriptSig": "", "witness": ["4c5262", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93623b186fa626e8512a5fc76cda23f4a60fbbad4c2c958c923f9740c685dc8fa339b124451a95f66d328740c8f74b6bc79ec66573930240463dbcd03d8389735ccc3a658b9783cc0a28fcc02932d4b85eca4f49aba0b4fac0b36a7e3a0001ff4113fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}}, diff --git a/txscript/data/taproot-ref/1e754a40c050fe3c356b0e253ed22633f2c5edb5 b/txscript/data/taproot-ref/1e754a40c050fe3c356b0e253ed22633f2c5edb5 new file mode 100644 index 0000000000..f34de6f459 --- /dev/null +++ b/txscript/data/taproot-ref/1e754a40c050fe3c356b0e253ed22633f2c5edb5 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e800000000a2a1cdefdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf5010000003ccba3d9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5100000000276aa1a901227028000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787240e3c58", "prevouts": ["3b470f0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "fb0b200000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "0b2527000000000022512067225551b50f550878fba08cb06856b99d76e57e98d7477f94810d7b1bff9dd2"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dc50a39cdaeebb2a650cca1339da469af920634404b8985ff645e07812e34845"]}, "failure": {"scriptSig": "", "witness": ["6a10616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/1e841722ec03b5be4c1001e90d8019bf9e01d892 b/txscript/data/taproot-ref/1e841722ec03b5be4c1001e90d8019bf9e01d892 new file mode 100644 index 0000000000..5e8df13016 --- /dev/null +++ b/txscript/data/taproot-ref/1e841722ec03b5be4c1001e90d8019bf9e01d892 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703100000000aae7c1ca60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127001010000004823318f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270060200000039d291e50304902e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e70b3b865a", "prevouts": ["076b0e00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "6753100000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "176f12000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "b17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa6d4441481b861885f5ed94900bbd5862c55ac99196b75719f05c0af3923d20525bc912f5bf4aa2c9ddbc9747d59c78f40d0a0aa0a8a4f22dc70e3f9cdb9b6ae3"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d5f4fd4f38de76daa30397659fc5eb995186dee5e848d8b406f0f064ef43f0c2e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8d9568d9f877f6ca0cee9df3d4970d26d0e286b65747316dde3c995de6e71d9f55bc912f5bf4aa2c9ddbc9747d59c78f40d0a0aa0a8a4f22dc70e3f9cdb9b6ae3"]}}, diff --git a/txscript/data/taproot-ref/1ea62bf92cf8078007e5cd279d0ac921980c1395 b/txscript/data/taproot-ref/1ea62bf92cf8078007e5cd279d0ac921980c1395 new file mode 100644 index 0000000000..dd0138915a --- /dev/null +++ b/txscript/data/taproot-ref/1ea62bf92cf8078007e5cd279d0ac921980c1395 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3501000000d42eb6c660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ff01000000c3ef7ad960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270af010000003e9053a503f715690000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7a21d363b", "prevouts": ["1cfc47000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "edf4120000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "94c6100000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5120e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e18e3807b59d4390aa508570eca32c61fc450dce8c5cf98deda801e2e8c3fb4b07491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ed9bc7b6602c1c15305ed2f4c8ec9cbeff7f3a1ef2517417313cc014db5fff98e3807b59d4390aa508570eca32c61fc450dce8c5cf98deda801e2e8c3fb4b07491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}}, diff --git a/txscript/data/taproot-ref/1ec26ee9e524029b8cf64e318125007a12c085d1 b/txscript/data/taproot-ref/1ec26ee9e524029b8cf64e318125007a12c085d1 new file mode 100644 index 0000000000..8d4839b481 --- /dev/null +++ b/txscript/data/taproot-ref/1ec26ee9e524029b8cf64e318125007a12c085d1 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fe0000000085a123a1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb8010000002f037acc0296cc62000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf7000000", "prevouts": ["d9ef3d00000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d", "f66a270000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c84c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93666ea2a418f0de61648f1846bcf7f8f7eac0e21721710bf1aae8a61bff50d06c920e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b553f13873b7614c747e02d52f281322dd98cc8d4ce789920cf593b75c6f05693959a095ba405700a8bdcb88c47f737d45523ad768f5b3698c80add34f2e764b"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360379d19db0294afbd483f2a5266502c79758d505384d45d9b44125b08f0b0e3c70901b40dea8c7a5ffa56ebe32dcbb2bdc70f6165f45007f6a309c26f1d76d473959a095ba405700a8bdcb88c47f737d45523ad768f5b3698c80add34f2e764b"]}}, diff --git a/txscript/data/taproot-ref/1eed48f62357914c0650cba567a06e37071db51e b/txscript/data/taproot-ref/1eed48f62357914c0650cba567a06e37071db51e new file mode 100644 index 0000000000..81afb50d68 --- /dev/null +++ b/txscript/data/taproot-ref/1eed48f62357914c0650cba567a06e37071db51e @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e000000009ccca0ec8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44301000000298165898bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e700000000f154399c02849c8e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966d030000", "prevouts": ["a9371f000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "49f43300000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85", "fb803d00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "107d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936acc696796e153717ed5a6a385f9de8b7611279c250cec566122acf9b81ca854846c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada7506a3091a1e28dfc5b9aac4646748f840add9c91a317c4120c5f1dff96d2e4520b5ceb13d27db1b37ec8ee9ee9482aafd08fc62c5401b1fb7c7b4ff374c3d"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630300b02e92706ec4fd7f3b61fec60afc7cf4f75cde7fe0ccf1bedc3ed3184dadad4d220d15ec254ba214a445cc73922794d5f92559e27b8850a422e98de131f09630471a62c8657382c38b342878f0042beb3ba209e0ca1417f9db2e3d45f6dbd940ade039b405c8439b762bfbc73f9441ef227e6f687b6d94ebcbac32155c7"]}}, diff --git a/txscript/data/taproot-ref/1f06a021e51a7104e4b8be0ce9c51232c8fd6c77 b/txscript/data/taproot-ref/1f06a021e51a7104e4b8be0ce9c51232c8fd6c77 new file mode 100644 index 0000000000..e95663aaf2 --- /dev/null +++ b/txscript/data/taproot-ref/1f06a021e51a7104e4b8be0ce9c51232c8fd6c77 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e601000000f77c8100bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf780100000075a884cc0355c5ac00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd9000000", "prevouts": ["6fdb3400000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "f282790000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "557d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936140d24f18a3c79287a65dbdab01f63e645309929f2cbe7a876d35f25767643489c6f5bbec45690fe95363697d7c9a9077046b35079592ab1dc3c0638990956b6a4c5d50721208c85113b157b4dd4688510f63bd33d4c90ece0d9e0afcb8224b1"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936410b6b76a639e4f4cca477601870e8f5c1a65fec44bb24e64b1e09572c2ddbf52a116e3d98c0753c1b4fce835beb402fe845fa277dc01c5b4ae7ac2a0861d05e2d0ae3a8a51f8512ed3183c6b189898e3d13807be8720838a97bd7135cdf46e7da77d1c2cfbe9569ee5db2c51580a9857624040db9177af617be0771cc5b8a1b"]}}, diff --git a/txscript/data/taproot-ref/1f21715d338b4550c3e7e74321d26de8853626f0 b/txscript/data/taproot-ref/1f21715d338b4550c3e7e74321d26de8853626f0 new file mode 100644 index 0000000000..4b688fcf3d --- /dev/null +++ b/txscript/data/taproot-ref/1f21715d338b4550c3e7e74321d26de8853626f0 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c33000000003fb3db2960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708000000000f56cb0cedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5600000000b56ec84c033b18af0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac87d19161", "prevouts": ["5469470000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "ad4f1100000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "392e580000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "84", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b09f12ec1a5fa4aa343993f316f0126821d68bdf7911bc110cb6f7136d98f163462b9d29a734e556c6b2d2347029c074a964aefd93d416389a14ef3ddb3da113c419005ce053ef5676128682d79317eecff4f27ad8f3a341c1729484208650bf5e521f6248097fdc64ff5a0a6cea9e07e7c649e93dab8ac6058acbfaf1ad70aa"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694086fc36ff4db5fca7b596fd90c3389887398c2c7f02b2c132cac3937a1991e1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900459910ef1376b2f57d6157bb9e8c31b4bd4b9d07432c4b683bf27102948dfaafec7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}}, diff --git a/txscript/data/taproot-ref/1f33b328ec921a865dddc299139161f27b477147 b/txscript/data/taproot-ref/1f33b328ec921a865dddc299139161f27b477147 new file mode 100644 index 0000000000..037da6c355 --- /dev/null +++ b/txscript/data/taproot-ref/1f33b328ec921a865dddc299139161f27b477147 @@ -0,0 +1 @@ +{"tx": "997c8d6803dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb000000000b13b4e848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fc010000003b13f7f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf4010000001bbc0c8c04cff9dc00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870cba8322", "prevouts": ["4d2151000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec", "2a41350000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "170c590000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_cd", "final": true, "success": {"scriptSig": "", "witness": ["7c020ccdd67522f4954f025bc3c4029bf6164a536a8eaf2fab9499cb2b9b3cc802e223354bbfea41e635ead55aa4dc3b26215de122527204b933e47ffa7e833902"]}, "failure": {"scriptSig": "", "witness": ["3a28164e5b3e874a2836cbef678b40dcc4dc2781d1a67213d7539de84f36581be89fb9bb78c03bbfb4c487c0b5efbb095eb70616f6f5b0a7512dfd5f99d9c262cd"]}}, diff --git a/txscript/data/taproot-ref/1f59389661d72064b929ee2bac0a3f2782c99fb1 b/txscript/data/taproot-ref/1f59389661d72064b929ee2bac0a3f2782c99fb1 new file mode 100644 index 0000000000..7ff86cc2ef --- /dev/null +++ b/txscript/data/taproot-ref/1f59389661d72064b929ee2bac0a3f2782c99fb1 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703e00000000c3348ab560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707c000000000d6403d70465f522000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67f64dc44", "prevouts": ["2d431200000000002251204e94ede8d65c6640c4e6b607af4038eeb61cf5c03f43315636aeaf4bbf4b4fcd", "482b130000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "success": {"scriptSig": "", "witness": ["e2a5abd0faf03d04bc444eee9e8c8eec00144ae37a2d3b9401bad6291682e856fefb6736fb76aa669edc33000bec526f257566c9295c3a2653f86a32461895a1", "efe555c8f4b6a3941cb6dce8d7c8400922fbfc61c5fdb2d0cde49084cd3996329d7ba79e95a91d2cd4dc65cd1b2a6eed8ab75d777d997e4ba77b10357d95d6274a0a9c248234c476c9e29d0509742cc1df33adfc6bd8ba12bdb0550ba0479f5666a7a08b8be84adc934b049530fcf55089d12c2b99fb8a5dc9e3214aff70a6dbc18e0e520de477bfa4910cdcb7f9fe675163492c24b5ae253b1d143f22ce8a4ec08aa32edb96843be21139399feaab4242cd48505626f7084f692a1bdf71a4801e2203457fe527f73440e21e25b2a1c07772c579a116193a3836aa4a41ccf58af4eda33071239c", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff10ff8ff84e2c74b185c3719598e68da490345cea6c4dad36e38092287b147b2bf95c996c233af882906f9dbac1ade951ffbcfbc851784c4426c4244530b53a718781d128360fcf147d876726c34cbb43628eaf8cca219716c2c6c399cebcf5a"]}, "failure": {"scriptSig": "", "witness": ["e2a5abd0faf03d04bc444eee9e8c8eec00144ae37a2d3b9401bad6291682e856fefb6736fb76aa669edc33000bec526f257566c9295c3a2653f86a32461895a1", "04b0c465f4deb7c2f40c81ef09ae86a825a63529d20e6890ccf84f57486afd6dfbe76d6b705ef0446b5da688955e1cc8051702612f445b32e916714da815ba236228459751a0cf9bf26bfc36d1d08531523acc683c8cbbe60c0d0c85e7b63d17de5ed6ecc10b6a23383fac06e92146a36874a968904478e6b02ae0eba2219444017be61918e25839a19230c345d0785bf0fb6ee2bb82813e632c3fbc336524883520a8f08c4591dfaae7a2cf78c8c543ad22e8772707ad7ebaff1c34f8cabcdadc193f1cece0af97125c97b0c4500f9200b9a0f623ba61bf84b957013ea601359c7e2c7df8d1", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff10ff8ff84e2c74b185c3719598e68da490345cea6c4dad36e38092287b147b2bf95c996c233af882906f9dbac1ade951ffbcfbc851784c4426c4244530b53a718781d128360fcf147d876726c34cbb43628eaf8cca219716c2c6c399cebcf5a"]}}, diff --git a/txscript/data/taproot-ref/1f7d7d9cf1ac6252c762a06bdb35e619ce77741d b/txscript/data/taproot-ref/1f7d7d9cf1ac6252c762a06bdb35e619ce77741d new file mode 100644 index 0000000000..99468b392d --- /dev/null +++ b/txscript/data/taproot-ref/1f7d7d9cf1ac6252c762a06bdb35e619ce77741d @@ -0,0 +1 @@ +{"tx": "d950a147028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4710100000088ae7b8cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd2000000002feaa9920273d1630000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75c917233", "prevouts": ["201d410000000000225120682cff718d7cbe051bd5beaa1ff36d3547b88d6d4bf403f10c1645a08d942ef8", "4ae5240000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d54c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365edec6927239e37481c871e98a308ae148761fbd82cda43b44eea2241bece5c01ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045135ed0e678ad02d8eb601751aa1b9acf14c9c27e67d62b009394546cc2bb02284b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}, "failure": {"scriptSig": "", "witness": ["4c52d5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e134849a28cba9aacf50a598dea57ce3ca224575357c4c8c887db8ba6ff2354671f69ea04c091b2bc3b7c7ae53ee1804d998a6447fcbbef49abb62b7a394c4c123854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}}, diff --git a/txscript/data/taproot-ref/1fa141a9352d1d89d10a4d09abf044c9506a4bac b/txscript/data/taproot-ref/1fa141a9352d1d89d10a4d09abf044c9506a4bac new file mode 100644 index 0000000000..931559227a --- /dev/null +++ b/txscript/data/taproot-ref/1fa141a9352d1d89d10a4d09abf044c9506a4bac @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1502000000ee042eca031c9649000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487a36b7049", "prevouts": ["35654b000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "657d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936642c359003ab8821594404f608687349fe596e5e62fafd127e5735207b1f199b7fdb01d6ca2155f5be7a678ca6a1e1d0c436995e81f878ed9c74997cf4fccddd302781454c6297f6b8a579760f4d591c0acf84ff9d038b064bbab8a5d53835db"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93611b7e6af417d224a1457ec19c3d9b3480cff6eb3dd58882614542c648c838a9319acac53f630ad836c1252ba923d9d3235c3c343fcfee9c8733d292c93bc64142bc2c7d802e8c870cc0fefcfae9d23d316cca1682651be3bf62b663d5ddaa443"]}}, diff --git a/txscript/data/taproot-ref/1fa4445b8704e72f4df267622d688919d1c6a44e b/txscript/data/taproot-ref/1fa4445b8704e72f4df267622d688919d1c6a44e new file mode 100644 index 0000000000..e11461913f --- /dev/null +++ b/txscript/data/taproot-ref/1fa4445b8704e72f4df267622d688919d1c6a44e @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc9010000008d41693360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fe01000000b3acba1101460a090000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc89e64f5d", "prevouts": ["b00c260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "90ae0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_99", "final": true, "success": {"scriptSig": "", "witness": ["28408300b104b8144353cde3903f49e2dc94ca991cdd9211ea108b6b85afee6d4520bdaeaad36e1a05f2e13b2c24571febdee963fe2d391eab38ceb154be36a303", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a4af46dbdcdb7f5b33f16bd681462da43c41d651e2257d815d6c3620f02498b5047564ecbf2a9f08156125db0bcd62f6cc00466a392449fe6001d7a8369cc37d99", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/1fbfc728d51680fcfeadde2a9e6fa7d1ac3996ec b/txscript/data/taproot-ref/1fbfc728d51680fcfeadde2a9e6fa7d1ac3996ec new file mode 100644 index 0000000000..58200b24c3 --- /dev/null +++ b/txscript/data/taproot-ref/1fbfc728d51680fcfeadde2a9e6fa7d1ac3996ec @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be3000000005ebff876040f9920000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acf3030000", "prevouts": ["f5702300000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936070bb467edca609e1a3246a8ba31e6266509d0d4e74e5fb2a32359b5f156527204d1c6645dfa5bcea0755bc1d945f129b754bcfdfa4df703b30809220c35586032cb43424d7ca27a7abc5fd0c2fa249f92b1e992144deb3864a86d466f79c2cceedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93672fb7b0b8b9d34fd164052a9d1d97e8f2f76026babd1f73e719809b132cf1e5b464f19ce228e2f316c50129d6edd6267acdc0242055b306d7ddf31bf4be6326132cb43424d7ca27a7abc5fd0c2fa249f92b1e992144deb3864a86d466f79c2cceedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}}, diff --git a/txscript/data/taproot-ref/1fcd778862db2069278171a2ee940bf756a2bdab b/txscript/data/taproot-ref/1fcd778862db2069278171a2ee940bf756a2bdab new file mode 100644 index 0000000000..96c4534cc7 --- /dev/null +++ b/txscript/data/taproot-ref/1fcd778862db2069278171a2ee940bf756a2bdab @@ -0,0 +1 @@ +{"tx": "766d60d703bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1201000000da307bb5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0000000000def8accadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba10000000099eb13d001d42a740000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72a040000", "prevouts": ["f9057b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6272570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b92221000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f0", "final": true, "success": {"scriptSig": "", "witness": ["89bffb1a58ab6675b495f7914fd34c4f41c87b8e25f1179000b0f67220300bf45c525d2f486e738658fcfcff09c3835ffc31aa30192f76deab72fc61f4423ce2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["e167ccec3dea0b6f348da1b70a3c5228d3fd0fa9e38d384d0e75a377cd793c649ee920d7728ab8433d98912fa5b462d21647f06116d294702f86739ff9265cf8f0", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/1fcd7eddbae73818ef08042df1c443c53fab0c49 b/txscript/data/taproot-ref/1fcd7eddbae73818ef08042df1c443c53fab0c49 new file mode 100644 index 0000000000..58f72ae674 --- /dev/null +++ b/txscript/data/taproot-ref/1fcd7eddbae73818ef08042df1c443c53fab0c49 @@ -0,0 +1 @@ +{"tx": "d9cbeb5702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b06010000007bcede8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706901000000a3cb8e8102bd1e2b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acf751961f", "prevouts": ["eec71e0000000000225120761ee5da1a196558fc88c883f4c68738765f8bbbf6c28fcf877f70c5de6e3c55", "e7850e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f467d3b2e53c0044d956650f0b6dad5c85ca4976a3e1b41bee60729426076047"]}, "failure": {"scriptSig": "", "witness": ["6a23616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/1fd0cbef8f091c8edefa214a32625302e2f3a6d8 b/txscript/data/taproot-ref/1fd0cbef8f091c8edefa214a32625302e2f3a6d8 new file mode 100644 index 0000000000..833a3659c9 --- /dev/null +++ b/txscript/data/taproot-ref/1fd0cbef8f091c8edefa214a32625302e2f3a6d8 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf81010000007d91abc060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700400000000377d028060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270550100000075c420dc03d8f996000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876c030000", "prevouts": ["daf6740000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "cd0112000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47", "923912000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f068", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364a1e8360ef905c29a22b948ad2d88d5f8aceb0a77bd56e2a8ea8c44b68d550acef05bece11fc4259c24dede9b1787a65bcee91937b36a28d108e88384141e6c4419704ddfd13dc63b1b4156372563d65f148a89e112fdd9cbf47f8afee5da0a9"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d1c86e323c4ea98d64ced2095cdf418b8da11459ca8cc7d768d85c68c22e03bad7df43f1383df9f0df0a1e0ce133acd14e2258cbe9a702da78bb61f4d1a9bc80eb43d08761fb76661299d0344fd2d8bfc7de5e7c6dc622156e95971f4b8396db5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}}, diff --git a/txscript/data/taproot-ref/1fe16cf825c0f639b3abd120fa85f9a344d3e514 b/txscript/data/taproot-ref/1fe16cf825c0f639b3abd120fa85f9a344d3e514 new file mode 100644 index 0000000000..6f776356b2 --- /dev/null +++ b/txscript/data/taproot-ref/1fe16cf825c0f639b3abd120fa85f9a344d3e514 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ed0000000005c790a2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6c0100000018167116dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9f00000000e046d60303b5e5830000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e74d241b32", "prevouts": ["69900f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ae0c58000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "92f41e000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_23", "final": true, "success": {"scriptSig": "", "witness": ["6afc5bf813b1756f0a1d5c1f332c15e7a736be9fffc76358a6a1ea00c2e16626e8ba688042cf4ef627e6717c631b6cc0260f4b21e7292ab41747c7fd2aa61ed181"]}, "failure": {"scriptSig": "", "witness": ["ae0e98a4fdc95b2953b8e4f09c33b6c0af467c60b4e3f1ddecbd956fa505b1846c57bf267784e943b3c3bbb4786a139fb1362a4deb1f46e2e9fa5161f87fde4323"]}}, diff --git a/txscript/data/taproot-ref/1fe6f643a391a7f73e3577d1f4e57935064e1c84 b/txscript/data/taproot-ref/1fe6f643a391a7f73e3577d1f4e57935064e1c84 new file mode 100644 index 0000000000..54e363d3cd --- /dev/null +++ b/txscript/data/taproot-ref/1fe6f643a391a7f73e3577d1f4e57935064e1c84 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe2010000006a60a6e6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc700000000333905ed029b4e95000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748789e0cf22", "prevouts": ["f9d2760000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2", "ac4c2100000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["844c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51120199479ee6d2d4c88363683365d3fc0e890ec8511afbf0335c75bda2c0295827135a2a7712dc4ffb0f490ef0a9e18994dae8053f69b06dfd6a349e2375b7df7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a081beaa6ca8e8a38428233ed41ed0af84f710aa288efb4d17e1b0b9546cb4415f8a538f68d5e42651660e8feb349dcf42bebc9266cba18280404d93052698127135a2a7712dc4ffb0f490ef0a9e18994dae8053f69b06dfd6a349e2375b7df7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}}, diff --git a/txscript/data/taproot-ref/1fe7d8f0f7839c475eb9dbd113d0ac120b1301fa b/txscript/data/taproot-ref/1fe7d8f0f7839c475eb9dbd113d0ac120b1301fa new file mode 100644 index 0000000000..c86dfc2c47 --- /dev/null +++ b/txscript/data/taproot-ref/1fe7d8f0f7839c475eb9dbd113d0ac120b1301fa @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2e0000000021998959dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd701000000289af2e28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49001000000cc78bb2b01117a7000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acc484a04d", "prevouts": ["5bd120000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "0a98200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b4ba39000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09029140b18755d55c9ee068ed4156548f810024a038b43525e32e1b421b547d3d4d8bcdd02ab45a5caf22e9992a32cb479fa0992e8222a33e19beba472aaec531b9e8eae3539feb433fdad8fff4f38e7a14b61f65bf1ee5cea54d6bb990dd8688d44b68d23b3dac549fef4bd8cf52bcf6eeb68596b99db64a25ca9550afccb9fcd10e7e6b139a5521d766f52112e64e6094e2461ee8bdf8614eb0828c34a0f5f6ae4e104acc5964a18d6bf872be09546b62831ae744b664c9755eb63321ad5c8cc6a35608884cc0e48904351a50485ae61b7f5460ecf5916aff0f78970a7667099ded8d90e3b986e0354c66787005512c85961fa016593663f6c08f7f4f9984f13de311e7997bae76112f6947058e9501cc03d88fc2210cb34aaa83bf85c3b8cfd7d3fee9153c4e90952644210576fd3af97327926a1851af63122e616444a3a623dafc0141a48813f658f12364f19a54f7e086013768a1ebf7532f3151062f25e34e24d54db1ecb3e64a063b1fe91eda41e1693b9e33b226ac01b1c848a4c80eb20b87d2ed69c00f6e0acb7209561acbf2785afdfa068f66c1d576d3f4250e4b29228edddfc88ed76935b6c10732c3b31d206d156835fc6809159670e9e7e18690c8f35b190dee2bf3ca79afc227b98ef960ac5a45fea9325acd0924aa3de3853ab5b97332845113275b7482a72c1967786c243c34897b07964e7f33949d73065a3a8f57b7c0a463a8e775", "bd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364ce5ebf1d1f724a0dbfc9e1d58a876a2ee5271b366a0d0a4478f52badb0e07b5f248cd26a95289b2c5b6dcbde70ff737dd7b8c2860adf4f4d2fc326868c95410d797dd6acf95c24b81e793c9c81b0ab80d381fe8deb935e4a90684c96acd4587"]}, "failure": {"scriptSig": "", "witness": ["4d090216fc59cf9c1b85b35eb2d3760023cade92b0fd92fe309d5bec453763aba2842b3833b7bddec0144ab6ee045eb22cb2dd078e044b8390da1f71678b836b46376905a32870b36d3caa39f497053c65c648de50b8d9f05f0c54d7a4b74b4f76421b99468ece4e5602e290d2bb921317383feccf40b3ecf50f68ba847e0c4c7ecceb2597bde0a0d12fdcd341bcf553527238c23a884684380eb69004b089bfd64945b1f1877b099e2fc6a8d32e75852660e55153d2116f552255cbb04efc7d55de0d58e13f4dd742c003f25351caafb0c613cf9f3def818321f557ff5290135c8966b135c1420f943264afa808d903b9cb9a8bf2a165b656bfb6805e396d865c466f71bc35f63b3194d8c332bd4d2d80d73a6cb1715b7d36e13c283ebece3b1438339f5794c3537135ccfa10ef888505fad21a69cffdb45fe7d44220b3e8054ebe63219f7a29755e44be9655bf119c72edb93e7057d05ecae0c68a9edd706d908ce5a4a4cf792262bbb27169bf2ca90df7679623c618eff8e4f4033f536546306e9426636017c83116d9a9a57b9f7c873b8c1f6a0deda762bc91b280e7bedc5713189ce0ec0fae8704721144a709cc06d0e4c5710c04db69346f9c60c331678a39177a530ff10e8a6cc0bfb544fe5154ed4c3b10bc3b909d176aa629a70c17bb209d23446812c1836735f7671884e5e0df1c31bc8a53354d2e1a207a6830df90f92a37ec2769c0dd01e70f75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed4c17033a0423a3758914e896a84d75b6af3e7ce95cad06f99098a3cc7df4a1ef248cd26a95289b2c5b6dcbde70ff737dd7b8c2860adf4f4d2fc326868c95410d797dd6acf95c24b81e793c9c81b0ab80d381fe8deb935e4a90684c96acd4587"]}}, diff --git a/txscript/data/taproot-ref/1ff8cc1006122254a00dc42299f828366e65b691 b/txscript/data/taproot-ref/1ff8cc1006122254a00dc42299f828366e65b691 new file mode 100644 index 0000000000..123d9fb491 --- /dev/null +++ b/txscript/data/taproot-ref/1ff8cc1006122254a00dc42299f828366e65b691 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a700000000d7649d888bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41b020000005bb521d202828c7d0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ef020000", "prevouts": ["68bc400000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "10fa3e0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93619c25e57f1f989d83744c87da06b614bf52628c742756c46ef690ad2ebeffa6f0b87aa3d77021654e9bdded249075f42755a492250fa9a6a44787c57353d93e356798b11c96dafc2935d577afad31a6537ce4b1a48ff27833822cff5fe95a51e"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ebd27c35238d7f43d4f7bfdb39568ec119b9aba2b203a7d851ca1c3c89dc41c13ff5c5d6186003b3e6d49f1c6ac4dc5a625cd45316b0701f0e70ab94b228af6df2727a08c83da142d000f7f66d34a23554b296f940ffe81022e50f50dcfdd8b9"]}}, diff --git a/txscript/data/taproot-ref/202c9cc0aac7d6c5172f0818c8d0d3405649d29b b/txscript/data/taproot-ref/202c9cc0aac7d6c5172f0818c8d0d3405649d29b new file mode 100644 index 0000000000..1d8138be85 --- /dev/null +++ b/txscript/data/taproot-ref/202c9cc0aac7d6c5172f0818c8d0d3405649d29b @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701b000000000f33c6c8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8c0100000053d675bb027de5770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a63f6b2736", "prevouts": ["a2ef0f00000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9", "b26b6a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "d07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa74714e58ef013156220aa32c916bb7c1f2fb2617e3ecaa27044ebfec042fafbaa211c16676cbc388c1faf2d1545933d22071968ce5ea9e4d8ac4039e171efe917420b3503815f4c7b180839898c4c4aff0ab6ef4d8b082708dba105a321f7428"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c91ffd9bdd7718e2534d84740feff12c3e278aec2a2c7640f784ff2523f8588c15c449093bd19eda03bff23881ea6078d018b9cd0ffff6e12447ca822e876d277e36b196311c1a9d305bc653889017f46f4c4934a1587d131a83127df4466fae"]}}, diff --git a/txscript/data/taproot-ref/20372276860410d8622c60d5ec72e5716e313dfc b/txscript/data/taproot-ref/20372276860410d8622c60d5ec72e5716e313dfc new file mode 100644 index 0000000000..f8a58979d4 --- /dev/null +++ b/txscript/data/taproot-ref/20372276860410d8622c60d5ec72e5716e313dfc @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c493000000004619122f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705600000000f0a051aedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdb000000009966758c01ba080700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac63030000", "prevouts": ["901e38000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "2cff0f00000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f", "676a26000000000017a9144c4b1fc943f04d775886b4f6d3c3c73bf7d3118c87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21511f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["9c977cda999fb777401bb707089a400841e57a42d76a033be16e75d27051f5c0063eb91f26417ebbd83af79a57d1d2b8494303e3208c77ad3e4964f1472679cc"]}}, diff --git a/txscript/data/taproot-ref/203cda36559f2e342d3921d1f1f5ab05e330fe7f b/txscript/data/taproot-ref/203cda36559f2e342d3921d1f1f5ab05e330fe7f new file mode 100644 index 0000000000..a37d295b54 --- /dev/null +++ b/txscript/data/taproot-ref/203cda36559f2e342d3921d1f1f5ab05e330fe7f @@ -0,0 +1 @@ +{"tx": "e3469bbe0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706700000000c719f5ba60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709f000000002924d0bd01b5301900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac88030000", "prevouts": ["17b91100000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81", "09fa0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_de", "final": true, "success": {"scriptSig": "", "witness": ["05219fd19c255dd62c22f1d23054b50d11994ed452ab688d5f39c135657686601b112e74d10d9c769c9b3ef2147401bbd1148060ee8b535520d53c4b7c914d6f02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a25754a5be8d5603ff76d699fd962222fd7a6446bc364ebb4483ca18a9554e2e115fda02da9cf38c92f08bc0c56b58969dd9c08c98ef401a14d52946bf47d3e0de", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2068fcad81b42ac14a337456c1c0e850bc5567e8 b/txscript/data/taproot-ref/2068fcad81b42ac14a337456c1c0e850bc5567e8 new file mode 100644 index 0000000000..15fabae3ae --- /dev/null +++ b/txscript/data/taproot-ref/2068fcad81b42ac14a337456c1c0e850bc5567e8 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270900000000030ccb953bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf360100000044aec6de01f70b180000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc12a84e37", "prevouts": ["90430e00000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327", "f73e8200000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "447d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457430173849036d038bb15ccd29e38ea974083458e0cf50b14971883c73e09395afa4004b2cd3f2b5519985ef4ce40029d6249627881f39179d9882ffc68f5bb6a"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa08f12ff2db60e07951e3ece83f8d4c41d9b16f9cd93bc43e76ab3ca16313aee1430173849036d038bb15ccd29e38ea974083458e0cf50b14971883c73e09395afa4004b2cd3f2b5519985ef4ce40029d6249627881f39179d9882ffc68f5bb6a"]}}, diff --git a/txscript/data/taproot-ref/2071f151f52b689e1e3c9f2b0372a3c1ca4c6dc9 b/txscript/data/taproot-ref/2071f151f52b689e1e3c9f2b0372a3c1ca4c6dc9 new file mode 100644 index 0000000000..79fc6cbeeb --- /dev/null +++ b/txscript/data/taproot-ref/2071f151f52b689e1e3c9f2b0372a3c1ca4c6dc9 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700f010000007bc29c6cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb900000000665aacda033f912f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e74a010000", "prevouts": ["0b3c100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0862220000000000225120e57fe1708102910b1e8fab470345c0402aba6cb96c683e4f102534396b5c1780"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a8", "final": true, "success": {"scriptSig": "", "witness": ["39eb969c427e032bfbff293814fbd33417be2d8872751fca57e881e37ccf77c2afe50a43cf336625c50cf055e199c0befd766b9c963ecd0d90fa714712896466", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["fbeb611f19a3b68d8630ffca6fa6062eb074a92e44f854d10cac4defdc78f08dd6f9392c7c86d3391a6e4aa741bc3c1922c9b47f080461e88188e7a2727b3ab9a8", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2089f610f91855cc26e8760f3910284181dc1b86 b/txscript/data/taproot-ref/2089f610f91855cc26e8760f3910284181dc1b86 new file mode 100644 index 0000000000..73089eb69c --- /dev/null +++ b/txscript/data/taproot-ref/2089f610f91855cc26e8760f3910284181dc1b86 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bec010000001d0a2dc2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf00100000010fb28d503d0fc6b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac4d020000", "prevouts": ["5d3d220000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "c7244c00000000002252202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["5a7d220a2162de9dd36b932eec5d84328f53e5a1c5d11922d11565b47cf408654d661e58f11589da695ccac5165f97e5a2cbf83dcedf2fc5f6b321061f22fdd2", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/209d75465a4314536f2bbabf6ada3622bec989d5 b/txscript/data/taproot-ref/209d75465a4314536f2bbabf6ada3622bec989d5 new file mode 100644 index 0000000000..3e4ad6f66f --- /dev/null +++ b/txscript/data/taproot-ref/209d75465a4314536f2bbabf6ada3622bec989d5 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2e0000000021998959dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd701000000289af2e28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49001000000cc78bb2b01117a7000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acc484a04d", "prevouts": ["5bd120000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "0a98200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b4ba39000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_0", "success": {"scriptSig": "", "witness": ["959d8b004aec9b6c8b35fc30afa6e1c9c64bbaed1b82210e78e3d772f6bce5777f786bddc06f222a037ebd4777fac8bfd2fe22eb950019490f44d22f2f1858f6", "502480a9a1c656a9f5f7746327f1502e9badebe19941d325bffa0b69ca20d42cbba39f6119d85cf48f64651b58f4d172892b615337e5ae1b79b1b075c2c0c6c8fcd824e506c15518a093d3784485f840af3db7c2d6fe64bf0eefbac6760ea866c11bdd38b3b91ad1c92cfa912ce2ea64ad0b8836d6ef9d47df36fb8712a9aadb5b7ebe77916014813c9ba3bfde6e9ca00b747088dc55e836e0a6bb1e817fb5c01a05277b205e73e57ea5eeb53244ee64cf4a15ce1fe1648bae74835f4eac17961062a29c29a5b041873e01f34160e5594a8e88782e07cbe71fc0da7b880cf5bc9923ee"]}, "failure": {"scriptSig": "", "witness": ["9ed7c8a586213bebaf0e2e191ab6016cef1f18afd56c1cb8be6387fa7814968f1f46bf2d1dd870c953c60a9e0e8b6ddf070aac51ccc0e5a19d6ded1c7b664d7e", "5030e2de755082f6ef0c8db5c1dbb514ed01771dc2fd8356d180d58d8f2b57a03ce1efc7b26ac693ba7844888338cf23f16d34d00d4aeef7f7afce215b518a1df9581a38a199eeb8cba7b1ca06"]}}, diff --git a/txscript/data/taproot-ref/20cd1af7438c223f49d33ed3693631c63f6c3234 b/txscript/data/taproot-ref/20cd1af7438c223f49d33ed3693631c63f6c3234 new file mode 100644 index 0000000000..c69ca4201e --- /dev/null +++ b/txscript/data/taproot-ref/20cd1af7438c223f49d33ed3693631c63f6c3234 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be701000000e408386d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46a010000004e24027602e24e58000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48790000000", "prevouts": ["6c72270000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "f5703200000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e10a12ee33fd4d96023e4b035134b5e2e7438605ed0c658788ecc1f80acf96e3cde17cc42fca95eeef15c2a149426edd48c8eb93e73982ab4fa8378007bf5ef888ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366cd1429f940fd1b5efd0dd192a5378c597739e1b4337081e905f661f126e379f0a12ee33fd4d96023e4b035134b5e2e7438605ed0c658788ecc1f80acf96e3cde17cc42fca95eeef15c2a149426edd48c8eb93e73982ab4fa8378007bf5ef888ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}}, diff --git a/txscript/data/taproot-ref/21227867cfe4806f692be272ca5b865dcecc1894 b/txscript/data/taproot-ref/21227867cfe4806f692be272ca5b865dcecc1894 new file mode 100644 index 0000000000..4093df4333 --- /dev/null +++ b/txscript/data/taproot-ref/21227867cfe4806f692be272ca5b865dcecc1894 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9600000000634b90858bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48800000000344f78fb01beec02000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6c14e4b3b", "prevouts": ["520829000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4", "bada40000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ef7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aa6323c0295bc5775a3404b3aacf7082420dcfdcb982829d77fe55ccdd4d869082a8da46561b857dd56ed73270ec2a55b69a5f7c1db8df98b88468b2be2ca2b7eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac8ef60344f111a9c34d055af59cfd42b130acbf4987ee3354719b7c9974e4d449"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb1d33bd2ec2ef2b80e561b3c30cfb99b356a60261a599d7e1f2ff199de481a6e8ef60344f111a9c34d055af59cfd42b130acbf4987ee3354719b7c9974e4d449"]}}, diff --git a/txscript/data/taproot-ref/213cd49c2b13fe3ee6d2220f5f96b63c748d1add b/txscript/data/taproot-ref/213cd49c2b13fe3ee6d2220f5f96b63c748d1add new file mode 100644 index 0000000000..8fdaab8ee3 --- /dev/null +++ b/txscript/data/taproot-ref/213cd49c2b13fe3ee6d2220f5f96b63c748d1add @@ -0,0 +1 @@ +{"tx": "7f672b810260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704600000000d96525f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce000000000157fcba20390206e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a66a020000", "prevouts": ["5d7811000000000017a914b0716f1bec91d4758ee97d9063c9da884dd2ba5287", "32655f0000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "165a142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["ba35ab6dc7bb7f42a551063c6f63d18d00b0b1d45576ad66786938447dd71941b9813b8443228b535069a06c4cfdc57a0feba8067a80f5fe7fe50c644e535d95"]}}, diff --git a/txscript/data/taproot-ref/2152488b729a3937e9f4e83bbefbb36d961013ca b/txscript/data/taproot-ref/2152488b729a3937e9f4e83bbefbb36d961013ca new file mode 100644 index 0000000000..1e43c5bc85 --- /dev/null +++ b/txscript/data/taproot-ref/2152488b729a3937e9f4e83bbefbb36d961013ca @@ -0,0 +1 @@ +{"tx": "359093cd0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ec010000002e50bda803557e0e0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac8e757553", "prevouts": ["12bf10000000000017a914b403773244c403f76163005c780d53872622b52c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1659142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["c5792a58b67d9ab4f85de726ace781508f45a14949e4f0df33d83e835148398cdc86083f6b2c243dda9b6806313f8618e121ee99d8ee5211a7eebd12017dc9ee"]}}, diff --git a/txscript/data/taproot-ref/215ddb94c508c11099b9268dbf4ce0d7f7d18977 b/txscript/data/taproot-ref/215ddb94c508c11099b9268dbf4ce0d7f7d18977 new file mode 100644 index 0000000000..b5aed78888 --- /dev/null +++ b/txscript/data/taproot-ref/215ddb94c508c11099b9268dbf4ce0d7f7d18977 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b48010000003a3e7a78dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbe010000003e008dd90464f34700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875b04d52d", "prevouts": ["f08027000000000022512090f7a6000b5d616b8fab8dbf93f0441952f14900faa8700280033be77a40eb2f", "ef642300000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "47304402201204ff9c9eae38bf2b33b671b2d640c822740371a4b2d5bfda1999c4a15cd2840220195e1c96d8ab5bdaeafbdf2d336be51203f4cd8df2284b786386af6fab34d84eb24104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "4730440220165b901dc777d7422d0882af9833e6a8b0b63640e6633b39d05373f6e1e6ebb80220535b568652daa99cbc006f31d9d4e7aafbe9057a5f8ff93d450a0682f03bc0beb24104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/21a38194825eb39a4a0ae99128be4409c90d420d b/txscript/data/taproot-ref/21a38194825eb39a4a0ae99128be4409c90d420d new file mode 100644 index 0000000000..da4b788125 --- /dev/null +++ b/txscript/data/taproot-ref/21a38194825eb39a4a0ae99128be4409c90d420d @@ -0,0 +1 @@ +{"tx": "d7f96b1903dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca701000000c90fb0fadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0602000000fe78deebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b92000000002e15949302b1769a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1a020000", "prevouts": ["3eea5800000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "d5e41f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "688424000000000017a91495eb8fe3d959e08a2cc279c1b4ede1921d14a93b87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}, "failure": {"scriptSig": "", "witness": ["d3252c4a759ac11949cf9159136b9e06c6295f8939b74bcafcdf3cbef48f320cccb2b22c406a6837310819a4d6b01f220aa934a7832d57d4607faa31a591894400", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}}, diff --git a/txscript/data/taproot-ref/21a967d5a754fe4909db382de1d7debbb040d069 b/txscript/data/taproot-ref/21a967d5a754fe4909db382de1d7debbb040d069 new file mode 100644 index 0000000000..9b53093709 --- /dev/null +++ b/txscript/data/taproot-ref/21a967d5a754fe4909db382de1d7debbb040d069 @@ -0,0 +1 @@ +{"tx": "020000000206f5bd527bde63f7c45daff54c390a64a59dabeafc8078a9bd0a050f54db6b44000000000096e4218fd15657a619affff084fc6b1bc2cdf5e85e399bb207d84ace710aa8effb82232f0100000000d0187eb30492422a51220000001600146d764276c66fec1127e5074db5bff3aa6c5255335802000000000000160014a4c1279efe108bfac1a01a2fe5d5c45b8fa18363580200000000000017a9143f5d8a006e43f5509420a4ea1e0b36ae11579f4487580200000000000017a9143f5d8a006e43f5509420a4ea1e0b36ae11579f4487a529293a", "prevouts": ["22cbf72c10000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "ddc7342412000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_invalidsig", "success": {"scriptSig": "", "witness": ["5e6cd8509542b63d2537a5bac669c0e311e78bff90c017c9c820e0c8da249779835917527ca01331a4054ec1b7b321c9234dfc8ce009f572033573a3c0091b52", "20159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717ac", "c0159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717a00074c7e8df7fd91f9df9f350398e675f9ead7758f02aef75359e3279a8e0e7"]}}, diff --git a/txscript/data/taproot-ref/21b086a0fcb5394bca5e13730e9801a167031fd3 b/txscript/data/taproot-ref/21b086a0fcb5394bca5e13730e9801a167031fd3 new file mode 100644 index 0000000000..80609d3d7c --- /dev/null +++ b/txscript/data/taproot-ref/21b086a0fcb5394bca5e13730e9801a167031fd3 @@ -0,0 +1 @@ +{"tx": "6a76990802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd8000000001d4b6c88dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4a000000002f820b8201e0103a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac02034d61", "prevouts": ["b82721000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838", "cf8a1f000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936685ceb4100efa5e54cc068990ea9a5bf606617cab6629ff60e87e062a72f36c14639ba4332756735e08e9dd0c9395e600a8a67669bda3acb22644b013566df80a9fad2668c863ea9bd6dd9197c1c49c61c2b9d7888bac8bf6fef03fc3ace0a5a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ef01d0d256ad0d229e53661481dce388404558ec2529e0bc1d85e0261a585159aa9fad2668c863ea9bd6dd9197c1c49c61c2b9d7888bac8bf6fef03fc3ace0a5a"]}}, diff --git a/txscript/data/taproot-ref/21b915be35d2383f8baacd2d513b5cdd06836ebd b/txscript/data/taproot-ref/21b915be35d2383f8baacd2d513b5cdd06836ebd new file mode 100644 index 0000000000..77c5881552 --- /dev/null +++ b/txscript/data/taproot-ref/21b915be35d2383f8baacd2d513b5cdd06836ebd @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47801000000d864d64160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706300000000b0448b2f01b9302e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8754010000", "prevouts": ["fb623f0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "33201100000000002256202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f5847d0622df121483b1ed7ca0bdae80206069e1f4810c687064ab59362fa9d59ff12214a208d620ece111200c1b5ab8b29e152a7c0e0e9f34d3dc0633f30eeeec1657f77102ce9c66c2655bb8b142b23ef3aa1d02b33f9da92a5485665189a305894ba7e52c3f59ebde71110e6c07aa3bee1c306f778690742fc0d2666be22433877eb8dadfe7392b904a66d6e5a0fdf6abcec13bfa32b12428fc721b4899425361151473b05c7435b71805c313c77f99fc2e625caddf9eba38b41961d9aac8887fca6a04088dabcc5bb229da55269438cc8cae8510ef86756104a5abcd4b04dc97aff4f977878d8d6dbd4e93781623986ea337f11083eabe3f4041a0bbc18f9202cfac5543a23481545870df93629f7408aa1adf0febc0b154d0e5458d38ac59a8e755fc574e37d5e31620e2e2b509f7500305e244bd9f769f6b55faf0e0541eda6c68ee6cd2f7ecd2986ff4286473e6f519c61771ec01bbecedc12119c173e0a70dd0e4b6e7f33a1dd09bd27ddb591ca0742272179dd3f928b20f87b1056bf95665bda75eed1248735141aa1357ec21922c018c0b65411252c61729c121e65f0889c8c550b605cc3aa364e9044eb48cee5e7a0251145439477b569e393506edac5c52814f53f7c10d91e526ad89a90f900f839e3a03b158cde00fce30f3bc219665407756206e9201e137acbd1e3dc0e4838adff3f0e3ea88ef86a5f118450b2bfbe112db310fe075", "697d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e945c33b167c9a8798707088659264fefaebd6f00f5f412ec268481dd4d0e7e4494dcbc06ccecaf65037be0509f5fea40d87445fa254b78f124a4b8c5e16963b53b3c2b944ff5e8034ac7518513c5ca10ab4eec025a723136fa482de383e24ff1"]}, "failure": {"scriptSig": "", "witness": ["4d090265099e99201f0ae5ecc7e7150bc7097c376c0da0d359efeeba78eb50d06cb3e3367eb394c456161ff97f0b821c36a335ec772ca86c113a7c1af68e7a5e99811a8045986fc060eaaaf362f85b288c4c2bec1148741ef27504b8168d3e4aee1112cdb5676de582c59200b6279650e63a3e02989f56406065f0798d6e251207e044ce7af6e7259e449c26bc45322b9a9f1a9cec73cc7929f8b6c28aa9b1292a68d222203aa61155a0494f55f7c7262ef8bc61ded342356d7150c6e927f0879dd22baa293eaa0ac1b609b4ccd9369fb906529933c2692b893c0162d4e22870566ddae7f50f09d10f26e3c59ec538e8233d67a72495c9ad2d2360486a205bcbbf9130cb5a551393ac1418596b0fce84d3f2c92bc2b27de57e805c786e78f0bd64623a7780472348003affc7f78fa1f17fdbe6a7e160a2aec3e418a42c146b3e336a158e2590f456d0a1616f40882ee6a2fbb55905a3dbd484204253f8a6663db27cded6ba4a5be14daaa009136ab5061dc57a28e79cc41ff0271be7052513cad6685217d61c76d7ebc05efed1ad376add0ccc97858bffe745a60bdf61f14fc68d9ee473378f960a9df286fbedaf16b03855f5c861b6dd7beddb599188d5551329ef082c329861e86c4c99eab7b7bc07d1393dadc65e7ab4b967ef6c8e919cfae6f96df3d1c54bf5c6c91f9a8f1243ac80cecb7497cb646e4057dafd6d18ffa3b366fe1ccf1a798e2383d24375", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bbba8c45aec20ec89a583a695eb75c8b6b0a9fdfefa2bfeb5c3f7ebac004de28dbbed29828226c3a1e74b431b518dca4e99f1ee054f76cd9b7bd5529b5cc8688de3449b5e2c621283b68ab187cecafc7aa77a8721601b5317d3484f84536019"]}}, diff --git a/txscript/data/taproot-ref/21c64c51dc34976712f8356ed25d28cb2506a3bd b/txscript/data/taproot-ref/21c64c51dc34976712f8356ed25d28cb2506a3bd new file mode 100644 index 0000000000..b6b5f3f6a5 --- /dev/null +++ b/txscript/data/taproot-ref/21c64c51dc34976712f8356ed25d28cb2506a3bd @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44900000000f5f5607edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2400000000a5a0567a0347928500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a66dc2b32a", "prevouts": ["ddf93a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "57904c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c2", "final": true, "success": {"scriptSig": "", "witness": ["8a0085756ab64896d6da8cf6a231042de33fdcb2378af0685f003628646c246d1b4d9c69e97ffc9be71d61dfc961a77aa1232e56195baf91e9eaabd8ac13ddc201", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["38ec05dc82f628ae4093c6109d9ce790cb7d07b666f44f3137a0bd8df91f8f9dc99ab062ca4df414763477ebec5c02b4c1c024d3fe8b08c3d45551577986dd50c2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/21cd99bcb03828e0395286a09e866684d6c569f0 b/txscript/data/taproot-ref/21cd99bcb03828e0395286a09e866684d6c569f0 new file mode 100644 index 0000000000..8646650ab3 --- /dev/null +++ b/txscript/data/taproot-ref/21cd99bcb03828e0395286a09e866684d6c569f0 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f00000000aee490c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4b000000005f173cce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703801000000fe1cc3f8014c7b3000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac9c041628", "prevouts": ["5139310000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "560c2100000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "d2ad11000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "907d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ed16c11561cb4e52cbc61ad76d34e49a6feea77f682efcf50ee22f89bd1fa0f0da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457ba4f11ff80ca9181e3d85997fa959accb8f97af45a52bfd0df916797673441f5"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa51b810e60c043042e0bb2eafa8cecc8c22fa830d489bdf7de51e14fd273b03e0ba4f11ff80ca9181e3d85997fa959accb8f97af45a52bfd0df916797673441f5"]}}, diff --git a/txscript/data/taproot-ref/21f06e9520e734ab7974353357c55b81e5ee87a9 b/txscript/data/taproot-ref/21f06e9520e734ab7974353357c55b81e5ee87a9 new file mode 100644 index 0000000000..73071f9a8f --- /dev/null +++ b/txscript/data/taproot-ref/21f06e9520e734ab7974353357c55b81e5ee87a9 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bac00000000a4c899b2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3301000000510c59fc02e5e69f00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac52020000", "prevouts": ["13cf270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "33bc7a0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e6", "final": true, "success": {"scriptSig": "", "witness": ["e20d99c9b7cc55693d7fcddbdb74b2e4b44d7d73e01a3007f31a7a6b2383aabcdff58c6e37c26938cee76279e85ff2a382f0f91502495007badbb777fab8df4b"]}, "failure": {"scriptSig": "", "witness": ["e783476659ca403a70e474208bc6081d34140b640add30584d711f8c051b60ba83098caf714b69bfe84538f54302e3ce3a7a6c0dcd3786fb8ec791d43c7c287fe6"]}}, diff --git a/txscript/data/taproot-ref/22089449f264bdccac5901669554a20c01c7632d b/txscript/data/taproot-ref/22089449f264bdccac5901669554a20c01c7632d new file mode 100644 index 0000000000..a35414d8bb --- /dev/null +++ b/txscript/data/taproot-ref/22089449f264bdccac5901669554a20c01c7632d @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bea00000000ee0a502560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fd00000000d7a42f82dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b80010000009c57242704fe4b5500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48746e08936", "prevouts": ["2584250000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "ec9f120000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "64811f00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/negflag", "final": true, "success": {"scriptSig": "", "witness": ["7340617ced9340b45760ceb890528fe2485469f12da62bf2170dd2f0de96785c1664b40e8e69c903cb0ceede49127d69deb93704d5e9f4845c384cf5ed9e29c7", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}, "failure": {"scriptSig": "", "witness": ["7340617ced9340b45760ceb890528fe2485469f12da62bf2170dd2f0de96785c1664b40e8e69c903cb0ceede49127d69deb93704d5e9f4845c384cf5ed9e29c7", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}}, diff --git a/txscript/data/taproot-ref/223d492bc034d65fae5c76008697dc6455711a0b b/txscript/data/taproot-ref/223d492bc034d65fae5c76008697dc6455711a0b new file mode 100644 index 0000000000..212942e1c8 --- /dev/null +++ b/txscript/data/taproot-ref/223d492bc034d65fae5c76008697dc6455711a0b @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff50100000056f5479204060a8500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e798000000", "prevouts": ["fcad860000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_5b", "final": true, "success": {"scriptSig": "", "witness": ["bda58126d802fc8724e1125ad89e081814d63df7516d10412d5dab66c1e01d3d190f47091320c87d1a69cb736db34bf7d9abd284a594ff6df2b6d116cb5c3e9901", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3ea3be366a45078cc28f71c16628b06f52c8f5f7deac2ad51f942f6bdad7fcf05430857a5d49feed4260131087e8631ac9af928fbd39b17e15c2ae4f01a5bdaf5b", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/227dc7dc4b5fedba0f90b82d69d0f8f6785c49f3 b/txscript/data/taproot-ref/227dc7dc4b5fedba0f90b82d69d0f8f6785c49f3 new file mode 100644 index 0000000000..0e0d7231ed --- /dev/null +++ b/txscript/data/taproot-ref/227dc7dc4b5fedba0f90b82d69d0f8f6785c49f3 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a300000000afc78ee1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8a01000000bb1633dc0151876500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac867f065b", "prevouts": ["ddbc100000000000225120ce3551521fa9f590f4e3a432d6c546446f0d4fa78e73ac01749e3c952a57623c", "8fb85a000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "final": true, "success": {"scriptSig": "", "witness": ["053e1b8e538c3bc309321ac2217c841e880cb5a81e463cb0273e3eb9d8ff51171a2a986efb4e5d8578424799da33525b1c775752a17602e0c96412e87012a8f301", "187ab5e105b5f66858c5", "4cdc9e50942076c092b25970e2ec1edf7d22f4e8b7d3fec3736a17277eb80fe9326cf18522ad1022328e18c1a14493249583ab862b6578e409ed7ca2edcdb1f3aa054abaa04cc51fae6e33cbf17eb5794fd525f3ef28f01bc15e20750d9ce510485df67443c4925a72e921f620bc7c94dd404f4bfe95fba127119cc784608713b24adec77630aa324369a14a2f16b637bf12180bfbdc8d48692a188aa0563671a10863392b672220a5b12fd3a0f5e7bfa50715370de8fe624a2232cce49783144e169e5f73429de7aa4a634058f95da223f9240494b2fe9ea62072cee4c76d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361592bcadc6b0173f44371808ef35839d7baf56fff8f47332472589970ebf0574a56703c807c846ee6abb2e7a8564bac5205dd4eabfb1e9d7f613523c0bbf3fac983123818ea2fb30d9c84b0712135e951ac6fcaf39fdf102e51ec0569ab5991acc2e87e6786e427484b7a25eca77971dac858d288ad2240853937e399511e1ac4814eb3006873c92f651a031d457533ec016334f911cc3244fdb7b55a1bf193c8d7fcaa8a3f248af81478f78c2ae2d84a51a55c107f63091e371c961c44fa973ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc22b5950015ca6bf902ab72aa161ffddb8987823fcc69a35030cb97d9616cfff6331bf3ecd5cecfb7e4dc2b7d61da5af4e5c887b1feb7d18aee6a7d1cd1096818b16ba2eef987ab89b69f32dbaaa9ec389f135c69edb6a4ec37f19740b7f2030fd5d4501928cec0bfd3602ed3e76d8155ec353f26584e3e4366c38f97c64459a00000000000000000000000000000000000000000000000000000000000000000d19e8ba886ddbbc76dafe91b8a3f02f3529cb5ab44e9f64b8ac5357a77f29094c224d123975e63ce69d08583f98430dee35d861114d22679af6131d9293c61b079e2fa6fab44cc7b4c6168b32516e0f04cc913a7bafd309decf260e3dec9ec9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23c22efba2313404e5904d2fb71b613b37bd41e7dcbb9c2b8be01d05d7a0187f14cb4cb66f826648695fdcb338c2aa262eb871a8c6cd9390c57bbc2ad6593fb3474d25704f9cafc09d6d8453426c7549d5e3004778d9b3968bd3b952c67c78aece7d952da9d14678ebdac73a5c8d5e14d2cf7ad3db2da6307947f0654078ec9fe05bfe0e9604d5022b4976402c46e4791b3c24cc77cdcaa415e28c2d609e771a94d6fdebc6f5faf2a0846ba52c6690c8a7073b213b6876428e0ce15616fd0ae963c0b2339f89cf0c1a47a819d2b9486acee87704ed5fa88be0ebb48e216088e500000000000000000000000000000000000000000000000000000000000000000893f14fcf5d631ca4274979ce31cb9c09423de1cb28e151fdb6568c6c55c988cc59b8e0defd2e76923fd0c02612e4a457ad43e8a186a5bbf1a8a2e635dd74c84f51f3ecd679b6c3af4c536805ad1cba391d88688d829113e460024821dd540fd4e7c034159daba82f364a02678622ec5af6cfeb13e31db96cdbd07f4e158d44c1f6f49e31c03579db62e751ad67ad23ccb8b225365890d25961d69fd722782b012bc98deb593730ee305162ddc176ce1055da8028d8a2ee84d3c5c2c016e610d4ae09ac0895b0e73024df773b4bc8f1fa77f269019c47251e1c591ed460b2286cc58e13e322ea39b4ff78f82227af8337dbb5c72b03e1c7618e558f55a9075fc8c68fd921bcbef3dd6b532ca14b0fd895fc7a323b38714abeec35945cabd814000000000000000000000000000000000000000000000000000000000000000074504a206801529e97cac9bcfbf0e79c56e7bcf3bdd57da720ac7abf661cb56b989feea5982311a81e317d99b193bafbe53278f14d7b4be0dd3d3284c0e978d6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000034ad4366c2133fe7305e82f00e8e91cb8b9791a3213d6a5d8bd78689c95b2e2200000000000000000000000000000000000000000000000000000000000000001ede38e04bd71b3ac73e836ccc88072a7a4af163764f3793deb8c7d98cc2f928362f49f48aa2225e55227b3d7ad92193a33b686884306da89b4eaa021b4b7daf0000000000000000000000000000000000000000000000000000000000000000084d5d7678a3ed0fcf0ae03f659b2fa1dcbcbe078bb81640a9785c7ba1c58b4557b5a17667a4d546babc00b67679095d6e28454babbf94f34b1b0c124a0604d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27f3c98e8455f02dc20fea8d531a5a4c9e725776b18a66babc2cd47d77c913a3bd2cdad93c71d5ea44101b85685b0084504e664db3a94d92d59fa39ce6a85b0654dd810de0659ebab0f273f152d7bd84250193e07888cd2fa42003624114a381ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000003066daf29525c49d87e5cf6049bb14ef6673f0322201ef9693ab06c4026439d68e8ab8978a96a938148e40440241df287b5f0d5a15cdfeb4e7519593faefb3c45118e72a7730c34cfd24b4adda3b16ab4022e80da0f9444d347922a0b3227d9c000000000000000000000000000000000000000000000000000000000000000044e7c902a1c8fbe84ba609f269cf831ccdb662782f4e70276f4e3b821fd5df5a43acde8c0352fc0aaaae2e02aa01128217fe38f9f6ffda05ac9924746330e0915201a810491ac6470d9eda9794c3d356bdabf10b53d6b81280412c9ea0a70cf3545d56b60a3fd73014bba9fbefcb041aa62d02ac0505ff63888fbe19ad0c9763c69febdb8e0ed135a6949314778b5867f1ed499dd589b0465ae2227c2c373c1bf7b52c16ec7a6a4c7a53b73dc546c6ca5a1e63511fe79bc58b510572ae439831ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8d4608c9c942491a3856d1af5e4ca48a237017c60814331617bdad2705666b325c968575eebb5df14f4b7c35f6a1cdc55e757cf91ede928ce5cbb13b86bc4856ff46359e7411918ed4c675ebb7fc831e8a5add7dc1eb9b3cb2635fa2785f3f880000000000000000000000000000000000000000000000000000000000000000cfdd7a337e747cbf1f441415e766197b1fe31e560f2bec1e61d1a024a657e69b9576076a6c1d6b47dca9816a842858332bcd978d0a69f25c2b051cf9b9feb0dba2f0b7a047dc92e8f11b6a9b77015bee15ee6ea71a811ecc6babaa90fc9464a82bd9c105c600a394f153addc1db5fa33c17990cddb9634cd24788d0a3b13612dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe55f438864ef2a33dcd1ca3767364691085985ef8f411f2902a38068b23af8d50000000000000000000000000000000000000000000000000000000000000000946911e0389d4b583b97ca3d7b2c423ae4a3d6c9fafd58cc8bff8456f17d236b2e53bf69fb1c97e7c7836556c6667046e21cf6785ecd43cfba50274e6df29381"]}, "failure": {"scriptSig": "", "witness": ["053e1b8e538c3bc309321ac2217c841e880cb5a81e463cb0273e3eb9d8ff51171a2a986efb4e5d8578424799da33525b1c775752a17602e0c96412e87012a8f301", "525d710a6fed5fb107", "4cdc9e50942076c092b25970e2ec1edf7d22f4e8b7d3fec3736a17277eb80fe9326cf18522ad1022328e18c1a14493249583ab862b6578e409ed7ca2edcdb1f3aa054abaa04cc51fae6e33cbf17eb5794fd525f3ef28f01bc15e20750d9ce510485df67443c4925a72e921f620bc7c94dd404f4bfe95fba127119cc784608713b24adec77630aa324369a14a2f16b637bf12180bfbdc8d48692a188aa0563671a10863392b672220a5b12fd3a0f5e7bfa50715370de8fe624a2232cce49783144e169e5f73429de7aa4a634058f95da223f9240494b2fe9ea62072cee4c76d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361592bcadc6b0173f44371808ef35839d7baf56fff8f47332472589970ebf0574a56703c807c846ee6abb2e7a8564bac5205dd4eabfb1e9d7f613523c0bbf3fac983123818ea2fb30d9c84b0712135e951ac6fcaf39fdf102e51ec0569ab5991acc2e87e6786e427484b7a25eca77971dac858d288ad2240853937e399511e1ac4814eb3006873c92f651a031d457533ec016334f911cc3244fdb7b55a1bf193c8d7fcaa8a3f248af81478f78c2ae2d84a51a55c107f63091e371c961c44fa973ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc22b5950015ca6bf902ab72aa161ffddb8987823fcc69a35030cb97d9616cfff6331bf3ecd5cecfb7e4dc2b7d61da5af4e5c887b1feb7d18aee6a7d1cd1096818b16ba2eef987ab89b69f32dbaaa9ec389f135c69edb6a4ec37f19740b7f2030fd5d4501928cec0bfd3602ed3e76d8155ec353f26584e3e4366c38f97c64459a00000000000000000000000000000000000000000000000000000000000000000d19e8ba886ddbbc76dafe91b8a3f02f3529cb5ab44e9f64b8ac5357a77f29094c224d123975e63ce69d08583f98430dee35d861114d22679af6131d9293c61b079e2fa6fab44cc7b4c6168b32516e0f04cc913a7bafd309decf260e3dec9ec9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff23c22efba2313404e5904d2fb71b613b37bd41e7dcbb9c2b8be01d05d7a0187f14cb4cb66f826648695fdcb338c2aa262eb871a8c6cd9390c57bbc2ad6593fb3474d25704f9cafc09d6d8453426c7549d5e3004778d9b3968bd3b952c67c78aece7d952da9d14678ebdac73a5c8d5e14d2cf7ad3db2da6307947f0654078ec9fe05bfe0e9604d5022b4976402c46e4791b3c24cc77cdcaa415e28c2d609e771a94d6fdebc6f5faf2a0846ba52c6690c8a7073b213b6876428e0ce15616fd0ae963c0b2339f89cf0c1a47a819d2b9486acee87704ed5fa88be0ebb48e216088e500000000000000000000000000000000000000000000000000000000000000000893f14fcf5d631ca4274979ce31cb9c09423de1cb28e151fdb6568c6c55c988cc59b8e0defd2e76923fd0c02612e4a457ad43e8a186a5bbf1a8a2e635dd74c84f51f3ecd679b6c3af4c536805ad1cba391d88688d829113e460024821dd540fd4e7c034159daba82f364a02678622ec5af6cfeb13e31db96cdbd07f4e158d44c1f6f49e31c03579db62e751ad67ad23ccb8b225365890d25961d69fd722782b012bc98deb593730ee305162ddc176ce1055da8028d8a2ee84d3c5c2c016e610d4ae09ac0895b0e73024df773b4bc8f1fa77f269019c47251e1c591ed460b2286cc58e13e322ea39b4ff78f82227af8337dbb5c72b03e1c7618e558f55a9075fc8c68fd921bcbef3dd6b532ca14b0fd895fc7a323b38714abeec35945cabd814000000000000000000000000000000000000000000000000000000000000000074504a206801529e97cac9bcfbf0e79c56e7bcf3bdd57da720ac7abf661cb56b989feea5982311a81e317d99b193bafbe53278f14d7b4be0dd3d3284c0e978d6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000034ad4366c2133fe7305e82f00e8e91cb8b9791a3213d6a5d8bd78689c95b2e2200000000000000000000000000000000000000000000000000000000000000001ede38e04bd71b3ac73e836ccc88072a7a4af163764f3793deb8c7d98cc2f928362f49f48aa2225e55227b3d7ad92193a33b686884306da89b4eaa021b4b7daf0000000000000000000000000000000000000000000000000000000000000000084d5d7678a3ed0fcf0ae03f659b2fa1dcbcbe078bb81640a9785c7ba1c58b4557b5a17667a4d546babc00b67679095d6e28454babbf94f34b1b0c124a0604d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff27f3c98e8455f02dc20fea8d531a5a4c9e725776b18a66babc2cd47d77c913a3bd2cdad93c71d5ea44101b85685b0084504e664db3a94d92d59fa39ce6a85b0654dd810de0659ebab0f273f152d7bd84250193e07888cd2fa42003624114a381ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000003066daf29525c49d87e5cf6049bb14ef6673f0322201ef9693ab06c4026439d68e8ab8978a96a938148e40440241df287b5f0d5a15cdfeb4e7519593faefb3c45118e72a7730c34cfd24b4adda3b16ab4022e80da0f9444d347922a0b3227d9c000000000000000000000000000000000000000000000000000000000000000044e7c902a1c8fbe84ba609f269cf831ccdb662782f4e70276f4e3b821fd5df5a43acde8c0352fc0aaaae2e02aa01128217fe38f9f6ffda05ac9924746330e0915201a810491ac6470d9eda9794c3d356bdabf10b53d6b81280412c9ea0a70cf3545d56b60a3fd73014bba9fbefcb041aa62d02ac0505ff63888fbe19ad0c9763c69febdb8e0ed135a6949314778b5867f1ed499dd589b0465ae2227c2c373c1bf7b52c16ec7a6a4c7a53b73dc546c6ca5a1e63511fe79bc58b510572ae439831ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8d4608c9c942491a3856d1af5e4ca48a237017c60814331617bdad2705666b325c968575eebb5df14f4b7c35f6a1cdc55e757cf91ede928ce5cbb13b86bc4856ff46359e7411918ed4c675ebb7fc831e8a5add7dc1eb9b3cb2635fa2785f3f880000000000000000000000000000000000000000000000000000000000000000cfdd7a337e747cbf1f441415e766197b1fe31e560f2bec1e61d1a024a657e69b9576076a6c1d6b47dca9816a842858332bcd978d0a69f25c2b051cf9b9feb0dba2f0b7a047dc92e8f11b6a9b77015bee15ee6ea71a811ecc6babaa90fc9464a82bd9c105c600a394f153addc1db5fa33c17990cddb9634cd24788d0a3b13612dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe55f438864ef2a33dcd1ca3767364691085985ef8f411f2902a38068b23af8d50000000000000000000000000000000000000000000000000000000000000000946911e0389d4b583b97ca3d7b2c423ae4a3d6c9fafd58cc8bff8456f17d236b2e53bf69fb1c97e7c7836556c6667046e21cf6785ecd43cfba50274e6df29381"]}}, diff --git a/txscript/data/taproot-ref/228fadb4fab77130e6a42578be8c100758962a74 b/txscript/data/taproot-ref/228fadb4fab77130e6a42578be8c100758962a74 new file mode 100644 index 0000000000..3ce1537232 --- /dev/null +++ b/txscript/data/taproot-ref/228fadb4fab77130e6a42578be8c100758962a74 @@ -0,0 +1 @@ +{"tx": "2922ebe703dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb9010000005c19b4fedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b13020000001998e48adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b010100000093d904b504fad96600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac67c6fe2b", "prevouts": ["deda1f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5841230000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "70472500000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93666a124118b98944227ac8799c33055b94d7e7018f02deaa87dcf78fe58f5e6601ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045bd4c1b076909910aa73b6afb36aebfd26014933f900bad794466c6fcd625cde53ff737734404bbc9015f34371be38b9f5376f1a60720e7cf7da81354011ad4f7"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360294c57366dead3fd876fc32af42a2fa764f9bd5b32489219346221a609003451f8d24c2756f16b9efc524121d49339a04fd56a536f956352850ed4d5018a4abf7205f064a536655663faab66bf2e716758d251376e4a55710082b6d7272244791bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}}, diff --git a/txscript/data/taproot-ref/229254c58edf03c88b0434f339de04542e82f168 b/txscript/data/taproot-ref/229254c58edf03c88b0434f339de04542e82f168 new file mode 100644 index 0000000000..00b0996cf4 --- /dev/null +++ b/txscript/data/taproot-ref/229254c58edf03c88b0434f339de04542e82f168 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c850000000050957517dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce601000000ac49e6a1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5101000000703ea34b033cef1101000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a641020000", "prevouts": ["59c348000000000017a914ff6a0b1cf86e786bc6de2387f1927f71fd08cd0c87", "fabd5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a3736d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "165d142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["792e781772198103647e5cfac1dc4091877ebb5077e791a2c12f8df0eedd0aea9926b2690076ed08e99357dbf7eeab06cd4b6b474fe179a0f91e8bfb1576a070", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/229a032ed00e20e08e27892cc81b53b28e1d245d b/txscript/data/taproot-ref/229a032ed00e20e08e27892cc81b53b28e1d245d new file mode 100644 index 0000000000..f7b973b7db --- /dev/null +++ b/txscript/data/taproot-ref/229a032ed00e20e08e27892cc81b53b28e1d245d @@ -0,0 +1 @@ +{"tx": "e804ef7102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe80100000034edbacedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd1010000006fa7aca801349d22000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787f2e54f5a", "prevouts": ["e25f660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "146920000000000017a9148fdfffe253d045df4a2985902e5465482e50374187"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_25", "final": true, "success": {"scriptSig": "", "witness": ["e61ba9755f060034285cef78e42a9461431cd3560d8e35b815f0c4939697db5c13d18cd88f908990704eb5289b22675d16eef3222c96d9b83050c4ce96a926a082"]}, "failure": {"scriptSig": "", "witness": ["eeb72d40ee7892901389368277850a2863b21496aae1e44ccc936d22b3b8944c3571313c4eab0a9282c069cb0bf5d539802145bf2def115727c7ecd26e041e0c25"]}}, diff --git a/txscript/data/taproot-ref/22a01d7a209edd8694bd9edb1c95de74dbed6fc4 b/txscript/data/taproot-ref/22a01d7a209edd8694bd9edb1c95de74dbed6fc4 new file mode 100644 index 0000000000..d35b577ae8 --- /dev/null +++ b/txscript/data/taproot-ref/22a01d7a209edd8694bd9edb1c95de74dbed6fc4 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6000000000f1c183f860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b201000000b9cf07d303a0995a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca2e5a443", "prevouts": ["478e4c0000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2", "d047100000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "217d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b125012b8c96659eb5051cffa1e2d8709a673f9f71e7e6dba2a97721853c7b7f5bb5ed745f7425de3873ba37c460c85acd2f4f50490d9d3680fc958bb85bfda6f488f9b2dd04714e2920653c1afab7d010d81355bbe53edbfcaebea15ff1da48"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936292ff1b7e178d7e9da4854c31b4400aae8a94314f1c0979690521ac9be0bd43e4f67f6e69cf51b25bdfcad90ab02b519823ccb2f4612df68d1a9a4df99984c88f488f9b2dd04714e2920653c1afab7d010d81355bbe53edbfcaebea15ff1da48"]}}, diff --git a/txscript/data/taproot-ref/22b9de25667093d760c9e17c5477dead3043b33e b/txscript/data/taproot-ref/22b9de25667093d760c9e17c5477dead3043b33e new file mode 100644 index 0000000000..ee62b083fc --- /dev/null +++ b/txscript/data/taproot-ref/22b9de25667093d760c9e17c5477dead3043b33e @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706f00000000c32c43f2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf320100000028b9c79a0196fd4300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac7d040000", "prevouts": ["bd700f0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "b5d872000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "747d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f13115bd78303830deef59a17ab37bfed179177a6532f4fa9f0a1bd0d59f4dc133f027656d2d9f64ade865091a06c0b2adab14558eca27c91472397a1e3806e077aea6ccf316b47e40a0e3636c5ad4f7738b9bfce630d4a478a0dbfcb51ed93"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93600cb8eb27b118577da6335628c0c478e07c27a1a525520767178318f599b32b5ff7c473e619e0ca75adf5145a8683277729cbfddbd5802fec00494435aa4942fbfbb1ef2412aee06f4b75b9e20a72d4d9707545a4ae77abc538f76b00105406a"]}}, diff --git a/txscript/data/taproot-ref/23157f2fc305799762478817c79fe62d896edd22 b/txscript/data/taproot-ref/23157f2fc305799762478817c79fe62d896edd22 new file mode 100644 index 0000000000..c212d60d5e --- /dev/null +++ b/txscript/data/taproot-ref/23157f2fc305799762478817c79fe62d896edd22 @@ -0,0 +1 @@ +{"tx": "ac7f65d102dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c010000004de5a7fabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9200000000f76d37d202d679b6000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e1000000", "prevouts": ["25c3510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "397a660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_71", "final": true, "success": {"scriptSig": "", "witness": ["a456c59e98366ae7ff61f61a89cdffdbd005e7e3bc4fbd099197f1a081976d965bcc584c7e7a29ad6a2625259dae4bfc998dea467e2805617b1632f00c73082082", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ba94e56ba101c1b723b2cd8c1fa8a54c5ae79d7cf1a2439c7af948e861f382e2419747a3b57d514515985d0f717045304887d07439977e31e73fc86ee4a63aed71", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2334138f3c633d853dbab847307d9950c227ac09 b/txscript/data/taproot-ref/2334138f3c633d853dbab847307d9950c227ac09 new file mode 100644 index 0000000000..ba5f4405c8 --- /dev/null +++ b/txscript/data/taproot-ref/2334138f3c633d853dbab847307d9950c227ac09 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706f01000000230ae7af60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d600000000224fd88202d97b1f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a626000000", "prevouts": ["621d120000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "78ea0f000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a97", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936320fe3e7102342eb9f8810633fbe90b9d113dd72dc4507b687ff513a291f00e9bbdd0eb743f16fddaffdc87a703f35bd0417e0996b155e435c0add546ea723b55a7303e26d6b86d2a780c30dbeb7ba87c6a0494b901c3875fb9ca7f2f12bb2fd373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2064e90022f018e8cc473163b262248813e3dc7e43f487ab53623d6c75190b10b282285524a15c732567d099967405d35f7136f74f48f011bc4ab279ad8d14f14"]}}, diff --git a/txscript/data/taproot-ref/2341c37b333e27f887345a539b3a46aa15fe6738 b/txscript/data/taproot-ref/2341c37b333e27f887345a539b3a46aa15fe6738 new file mode 100644 index 0000000000..1ab8045a19 --- /dev/null +++ b/txscript/data/taproot-ref/2341c37b333e27f887345a539b3a46aa15fe6738 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fb010000003f2b16d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb10100000040c4b8b401a85c0700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac817e0b21", "prevouts": ["29c23b0000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588", "3cf4590000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac5", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b7edbaf46c0268ae1918128a2d0d299a3d54c113a31bc8611ce7c78042257f253f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826c8f4b27179de8a3c9fbcc0ecf825a44b7564122e0508108d3381c6acb047da700a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ca963a534af16cff2b21484c634d90c5e0c00f8b3fd57582cf68a2a29eca46015f1aeabcd45f20884fa261b27121b1c083fa5a2716bfd01069fab98e18c3b0e4b23f991898c0f7e80b32f00b838c1f1514616fab2a47083539335b67c2689fcce4d7767c8a9637a0804b073b1eb172c67de67ce152ade33f2591a85dfee2e5a"]}}, diff --git a/txscript/data/taproot-ref/234eb0340c07ea7d86dcfac62e971eae6dbc359d b/txscript/data/taproot-ref/234eb0340c07ea7d86dcfac62e971eae6dbc359d new file mode 100644 index 0000000000..8942582b03 --- /dev/null +++ b/txscript/data/taproot-ref/234eb0340c07ea7d86dcfac62e971eae6dbc359d @@ -0,0 +1 @@ +{"tx": "71a4ed46028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44b01000000ec698ea18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47501000000cce1158c0485037000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac31010000", "prevouts": ["8ce9360000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5f533b00000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6aed", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7af4cfe0f99cca6fd42b4bad50f9f41e4667d74ccb507e77633a831529259e37eb7d8a059ff700a84b94cf01bc4b173d99041796f2088e1a59df5cc5c18f54d86475c33b310e45b92339559838140b9b3f3d62b1cf111e129ddf9f566de62eb71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368171ab9422ce0db519e36e4df069c3183058a2adc3cc0dfd4bb4c05bde2a2f30c9b0690fa0521f4fddf88c65f69e0716898ebb5a52dcb1ee37dd2f34a8a99dbd71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}}, diff --git a/txscript/data/taproot-ref/2363727c5d55ff4d6eaaf41f33d420d94aa0259e b/txscript/data/taproot-ref/2363727c5d55ff4d6eaaf41f33d420d94aa0259e new file mode 100644 index 0000000000..73b3a87eba --- /dev/null +++ b/txscript/data/taproot-ref/2363727c5d55ff4d6eaaf41f33d420d94aa0259e @@ -0,0 +1 @@ +{"tx": "9141e8fb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c431010000009eecc698dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6a00000000ac6348d004e56f6200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca6173146", "prevouts": ["83e83d00000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "f83727000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d7a19d3d760a1d5b978f5f8613b1d81f8c804efc212bcdee817dc6857aacc54dc4ac7686e1050a7898ca46832dc0b13c656b8aa5296dcb10451fe0686117a525ba8b1d0413a3689afa6e2d3b5e2c7645358d98c43f6c96a422c82685ea6ebed243c7016fa806ba9399c8748af43c67a9931dd4be53300ce189c0addca0147628838b9e44c160d655842f291bfb9229f8c849f630e82253daba9d615aabeb90a2ceb5e9fe548869c37c426773c51df4089cc45f472c69d3ae172a3e96766e4056d2bdd2c883828986bbbf628f78aa9193925784cd080760db15db2d7ddcf232709c468cfdf7f2279136b433104d8a23a726f2e024007ad37bae5a90d61502cabcbacc92aac1e945356c7b905510a04afd1a64056f3ac117e963500e1cf8388dd97fa005b259f8db467372ce304ac59e5233b4cac90f1a410f1b0baa0d30fe804dba19e1ff4cf9f2b46ecf12e1835c88830dc7e5aebb781a630d83beb145a08231e9564a4938cd0864f24f088881405eee602fafd96a120b2fea89c09290402625ed0448801b41bc85baa36810c816cec4ecccc1b9f7044128c1c6ab50ea6dfa8eb8352d6ae2b3a1b8c907ce62a51c3f29ea6ebfe3efa32fe0565bc9b1d09816c004080d40fc21f62bf917edab68690ef37e27bf9a10ee365f1758b8a71b90d6034749ed1d48f90fce1f6045794a00ab8a72f6c49d7fe4b976e89d16e4c3db3a5e39b0e9f5f9688fecfe75e0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456b8fb8a6613bd9c6482328b74d7fce63938f8fb7ab14fbe335c660b528e72f6791d26af6ddceab3892536958f1ea20dd7b885ab499207106c7decaa6511a0e4c5a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}, "failure": {"scriptSig": "", "witness": ["4d09020b84cf359cb0adde03512043954d24058956b42b615de75e6ddcec21df184bbee6c863bc11286694c694fa0a8fb65ffd60304f9f96b4544c14b4163f76923b3773fa746611c4d6ed29af4f8586bab6bfd704aa6fce0c4c201525bcd9e901377bef2915acaaf853e616153933c684a493de9d51d53070dd21d318657b6e654313159eaac3addf54c3f0a1814ec5482b7a7fa7b1f238805a7aaa66e0bf60414823d4b4e7d0fe091a60c1cd66dcfddebe80247654548220e63422fc7f0dc44e3cae708fe297fe5bfe97ecc73c25866c039cbd034bc54b6f60057139722de21b9c669e553c41f949c90e247c81b99aa5657e59d4b37d8b1a659de394957c8314b75bbdd9897bacd2807566073306ddefbb9cc32b0e37b155bdbfe4661ecebdc1825c519c8891a70bdbde9adba7b0cb294a33e87063f83f2e68eedb711f05ef97b8f54fda4d774496bd20773ee5d2d30bdd1031e531c17af6d13ea321a25817cd36a054b8a2b70189f8d25e3b9f1c23f6f745888ecd6ce590cf1170bda83381f7f34bf8baaf0721660aeda86a6726110b58991b0b6b81fd646b1ed5ff8fe10d040116b3727c80c013cf3daa792d1f5b73607be9bc040cfc6fdaac30395ba9914c3a94410af93ca306ba3e225e37b7cf9f8efe90fb68caa92732ff00d975d833066968d7a6b23c164b93fdc84a95083d1f1c7bea248b3b703b2fcbe6c78e51a9380ffe2a722004d92283e08d7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bdcf8e50873998a844faba380504aa6a4d6e9de9af7f46f4843b96a4d07d0a1c0941252319b1d0989c3ca3905f2d65278f17fb3ebe6fd71301329f8e450b42a05a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}}, diff --git a/txscript/data/taproot-ref/2364ebc1025f0c764130435a3da1d5febf1ac0a5 b/txscript/data/taproot-ref/2364ebc1025f0c764130435a3da1d5febf1ac0a5 new file mode 100644 index 0000000000..31a232032f --- /dev/null +++ b/txscript/data/taproot-ref/2364ebc1025f0c764130435a3da1d5febf1ac0a5 @@ -0,0 +1 @@ +{"tx": "1440bee6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44000000000a895e88fbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf52000000000366cbad01bc8c1b00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac83030000", "prevouts": ["a0853e00000000002252202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "44c57f0000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["9bde27e94522f6809244df9ebd77fd059392ef6e9929729db2a23e7f354cec06728b50c787bb54d821f0f6b64f38a80b0d65b35c5124dc4dc8d03381ba66de4e"]}}, diff --git a/txscript/data/taproot-ref/23873275d271cfb7c8271e4058054ab8102b18bd b/txscript/data/taproot-ref/23873275d271cfb7c8271e4058054ab8102b18bd new file mode 100644 index 0000000000..732a4424d5 --- /dev/null +++ b/txscript/data/taproot-ref/23873275d271cfb7c8271e4058054ab8102b18bd @@ -0,0 +1 @@ +{"tx": "57a8be88028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4360000000053d6dc89dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c050100000069ebfe9f022b60820000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65c37ec52", "prevouts": ["657a3100000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7", "1017530000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "b37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b1edffd5a893e5df644ec9dcdc719e8bca2e1f26d5763c3eeb38ec8c4740357935a4766d58ec26ce2b4efcbf65574b66558d9985cca85178600ded982bb1eb8a33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a368ced990ebadb111ebc3982eac7e308f07f99a9264ca6c949f56162916d7884"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93657cfe4e05c2801526133fbc39f19ebc94f094228af725e239c5bbdc23ebbaf663f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ebec8f444f9538a00b5e533aa370349d7181cba703021b72fe611d481b359a8e62055c347ba5402321504576f6c37d0c6cb1d044ee75df535bc9eec0560634a7"]}}, diff --git a/txscript/data/taproot-ref/23ce0a835c3fef13acabbe51379451af1bad4377 b/txscript/data/taproot-ref/23ce0a835c3fef13acabbe51379451af1bad4377 new file mode 100644 index 0000000000..9848cc7afa --- /dev/null +++ b/txscript/data/taproot-ref/23ce0a835c3fef13acabbe51379451af1bad4377 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcf010000008c867549bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe200000000ef2a1b630206169c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71bbb9c40", "prevouts": ["35f922000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "d5937b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["ce4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb2c5514a992c22e53e3a04f6b085a9b65917ab3f28cc532348e66ade0afda2c959bd9b34bb85690c892593228383c48f2c7a3855b4947a3dd1708d13c567655d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}, "failure": {"scriptSig": "", "witness": ["4c52ce", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366e56b48b572a1cc7c2f3559a9632e4e2bdf1e7b793f9a11573ce0ed706b87c990ea67bdb3398814286540937ec364df004af879f987225ad05d036a51e8223e6d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}}, diff --git a/txscript/data/taproot-ref/23ee2abacaf9004b59fb4b0c0bf4fb0518c0b719 b/txscript/data/taproot-ref/23ee2abacaf9004b59fb4b0c0bf4fb0518c0b719 new file mode 100644 index 0000000000..c7400ea1c9 --- /dev/null +++ b/txscript/data/taproot-ref/23ee2abacaf9004b59fb4b0c0bf4fb0518c0b719 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccf010000000c1a2eeadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce100000000a5df58b402ee86b5000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac3e5be55b", "prevouts": ["6a2c5a00000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "604f5e0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000df", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d781ab0fc22299030d8088d2502bf7faafb676f2c6fd3570596726d37b72f1ea18b5f2fef84521b683d8aac742b48aa2197bd0282730b1a4f3a8fad5441e2c71c315aec02adde316e700f87e7c47f474d1ec7cdd06b196ee567d81a15967a13360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369f2178c5a62b4c30d4502e396e591afca727ab38280213cf79bd50a97c5a07b199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45385991a3000310359e2a9adae84589f286ca8f4d4476598a0e772bdb8ecbe6352ff338358c59a252efd0a17af70f1cdfe194eb24c5d50483b26343bf89011bf"]}}, diff --git a/txscript/data/taproot-ref/24189b1ed398f5834d414ec0517d0e4ec49e5123 b/txscript/data/taproot-ref/24189b1ed398f5834d414ec0517d0e4ec49e5123 new file mode 100644 index 0000000000..ae0404cd4a --- /dev/null +++ b/txscript/data/taproot-ref/24189b1ed398f5834d414ec0517d0e4ec49e5123 @@ -0,0 +1 @@ +{"tx": "dc9f3d8802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf46010000009ae647c88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44901000000ed7e76b5043306b500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8725000000", "prevouts": ["89a97b000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "5f003b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_67", "final": true, "success": {"scriptSig": "", "witness": ["863013d4da2ddb0a46deb8b892d3eb016fcbdea9c696bce69f15e1aa6fbd98006a72109f81297ab644f1d0e9894e63500c4af91b399c39921c7388e960e2b31203", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f672b112d731d76e4b4d22617715711ee17afbc16e51f1f3aef845b1fce57650326a639e81e3acf410e5daa35ff55e6f422cf1db39b4e8021456d3e1120ce5b667", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2447d402d9160d103faa8fce8f16b8201a516a4c b/txscript/data/taproot-ref/2447d402d9160d103faa8fce8f16b8201a516a4c new file mode 100644 index 0000000000..cb47cbe4ac --- /dev/null +++ b/txscript/data/taproot-ref/2447d402d9160d103faa8fce8f16b8201a516a4c @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1601000000ce4364e8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe400000000a9dbb2eb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46000000000b49550d804b90201010000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc60416b55", "prevouts": ["b6636600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "becd650000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029", "4eaa370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_keypath", "final": true, "success": {"scriptSig": "", "witness": ["abc52c9b6e558009b409314e7eac5967890b3ab0fbd19460eceb0e93b7565442ece6be3ecead53f592645f60ef462641aede6a98a50fa514baff89d7bcc0e83d"]}, "failure": {"scriptSig": "", "witness": ["abc52c9b6e558009b409314e7eac5967890b3ab0fbd19460eceb0e93b7565442ece6be3ecead53f592645f60ef462641aede6a98a50fa514baff89d7bcc0e83d00"]}}, diff --git a/txscript/data/taproot-ref/244d1fe0151e8979539727b36d9efd4236889b85 b/txscript/data/taproot-ref/244d1fe0151e8979539727b36d9efd4236889b85 new file mode 100644 index 0000000000..13dae4f720 --- /dev/null +++ b/txscript/data/taproot-ref/244d1fe0151e8979539727b36d9efd4236889b85 @@ -0,0 +1 @@ +{"tx": "1d7233850360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708c010000004c7f1e8bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf76000000001971cdc460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706001000000c78a86e4027ef68b0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f877bbf5d2b", "prevouts": ["4e1e0e0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "19636d0000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "a6081300000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ab7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ce8c86c7323be371b6600ab2618f7270fcde0f103b94fe3f1289a4691bdc2f0b588819b06684552554786b2b49e7cd3d9dcfc0725dc4b3b93f8768a6a84fb31b7c07bb1aa10d02d314eb70c923196d0e49e71087637e2d5a1d7fe44c2440c398"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e894b0c937046f490030e0d20905ef6ea85b70027c49d9391eab6e36e103b9e792f3dd0bfdeb3f64daf38e1101738c14790d5f1c68393c583b55b6fea5718d19818cb303569f28fbe8acbcc2d27d183e3a68170f5392df28f40a03efea695d856e"]}}, diff --git a/txscript/data/taproot-ref/24b9d083b99a1fda505df14b9b98cadbf34618a3 b/txscript/data/taproot-ref/24b9d083b99a1fda505df14b9b98cadbf34618a3 new file mode 100644 index 0000000000..be23af65df --- /dev/null +++ b/txscript/data/taproot-ref/24b9d083b99a1fda505df14b9b98cadbf34618a3 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfda00000000be838db68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e80100000074bdb79c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b0000000006cc0e3ed03fdbde60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a613ede228", "prevouts": ["566f7f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5c51330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0198350000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a", "final": true, "success": {"scriptSig": "", "witness": ["ab6f2a367aaa484bda76cf2cb22c487a3174d962013372eb1507ff843e34eadf29fef3f39b6974c382e939309acc68924a9d49e2d55515bb0ab5ec4e15f3dbcc02"]}, "failure": {"scriptSig": "", "witness": ["9d6fe25fcb93992f8d739c892ae3ce58646a41defc8dbe43097bd1a8969882bf972ba62b773fb797f35d670c68b25bfd115b0dbb0e0499496478bf62bc2d21260a"]}}, diff --git a/txscript/data/taproot-ref/24bbb3bb32575090a29c31c6d367e46898dc602a b/txscript/data/taproot-ref/24bbb3bb32575090a29c31c6d367e46898dc602a new file mode 100644 index 0000000000..0394110baa --- /dev/null +++ b/txscript/data/taproot-ref/24bbb3bb32575090a29c31c6d367e46898dc602a @@ -0,0 +1 @@ +{"tx": "1bbfd49402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd3010000009d9e899b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a701000000e3abf6f202e8b091000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487859f2c25", "prevouts": ["b31c5d00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970", "5ffc3600000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "e47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366bc9e6400471d4508039602a6371cc2fb521d342dad10229cb10d12c2b95e76f158e114954b29a1fe443083941979d23a0210cc324956afb3dcce424fb4eceefbefe4cc2cebe7bba8b4a4f82666342333b91a450af49acc0f1954b5763bfc142"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa0d58db0463b9d01080baa2617114f2c0459e5723b09a0137090d28117705b675ea7c8dd4a05a6083e4a7ce3fc20cde94d430ec03cbfbe8017e9dc8ef3bce99a9"]}}, diff --git a/txscript/data/taproot-ref/24d0fbfa8bd2c68fd6ee1e4839bb0d5bb73ef21a b/txscript/data/taproot-ref/24d0fbfa8bd2c68fd6ee1e4839bb0d5bb73ef21a new file mode 100644 index 0000000000..14b2198114 --- /dev/null +++ b/txscript/data/taproot-ref/24d0fbfa8bd2c68fd6ee1e4839bb0d5bb73ef21a @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706c01000000ba310ba08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41100000000bb14c6b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b42010000002e7adaf704ccf9680000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987d84ad23d", "prevouts": ["3b2c110000000000225120e0fbe9053c6d2a439b1df3d9c89ed0e68b8279a92dae6907e23437dbb3b4029a", "a9cc330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6891260000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_7", "final": true, "success": {"scriptSig": "", "witness": ["6a566cccf8d556b725767057e9855e9c75da02cd5ecac659c8e7aa317cb7ce19154c5e66479190706580cf8ccffb3ee9b3d34c0414cbd4c9d7993d7c9982c86202"]}, "failure": {"scriptSig": "", "witness": ["33a3ba65412efccc995c72a550fc3d0ee02d63309953043a9b3a7625796dc71d3f0f5dfce2bffcb90843143fcd5e266635675865d9e12e227ec0ece6e3dd8e4107"]}}, diff --git a/txscript/data/taproot-ref/24e2153d05b71ded99689e64661aa90af06300e2 b/txscript/data/taproot-ref/24e2153d05b71ded99689e64661aa90af06300e2 new file mode 100644 index 0000000000..45d78cfb92 --- /dev/null +++ b/txscript/data/taproot-ref/24e2153d05b71ded99689e64661aa90af06300e2 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127031010000004cc7cda5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2c00000000af66aafd030a6e79000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87dec2e433", "prevouts": ["a3ab120000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "b7c06900000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ae7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fab92d0c8bb72b9935581697fe84ef0173536b04207acfd5de8a2df8889a2a895490189ee9b6b94816743a58868693b6f0ba58cb07e4c6d5ed2ce590077e887d5b"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364894fe7b01477097453262073e919cd09e7fe7002637f313a53b18e1ba28b741b509ab67bbf3c81955fa9e200008a666546f84b8be37a00b57f87c80ceedbec790189ee9b6b94816743a58868693b6f0ba58cb07e4c6d5ed2ce590077e887d5b"]}}, diff --git a/txscript/data/taproot-ref/24f5f696fe56cb9b25c9d12a9606b6d6f531d6db b/txscript/data/taproot-ref/24f5f696fe56cb9b25c9d12a9606b6d6f531d6db new file mode 100644 index 0000000000..5344352c0e --- /dev/null +++ b/txscript/data/taproot-ref/24f5f696fe56cb9b25c9d12a9606b6d6f531d6db @@ -0,0 +1 @@ +{"tx": "67281e5e02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfea000000004aacbe908bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42200000000a23368a302d754a3000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898740461b2f", "prevouts": ["a9f1670000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "032d3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_6a", "final": true, "success": {"scriptSig": "", "witness": ["e00afe554272977ab3f2b49abae534781583d7ad56333709f506f3374d33eef12f64831a0760bbf6ebe943861d12fb4782cd4be5c2ffed0f4ef6cf62ae98112b83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a2aa46f3072abcf280b77d2244b9bc38a46f398b11ef902183651c3e5164c5ad7ec3f3f84a32670ef00ac3ff6d05778f256807269c913366abd1839ac88817dd6a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/24f8bbbbf4e945080301e930844b08d263783100 b/txscript/data/taproot-ref/24f8bbbbf4e945080301e930844b08d263783100 new file mode 100644 index 0000000000..e95f60e31b --- /dev/null +++ b/txscript/data/taproot-ref/24f8bbbbf4e945080301e930844b08d263783100 @@ -0,0 +1 @@ +{"tx": "edcfcdd702d9befb1e9c529d7d9073823d42f590d5d83a9ae9e8205a58b2deac400aa179de0000000000aed2b9bbd9befb1e9c529d7d9073823d42f590d5d83a9ae9e8205a58b2deac400aa179de0100000000c9ef9ecf037bb08b0f2100000017a91417076ced824a76f7f00aa0b9ce412f8713d9a8a68758020000000000001976a914798a0f34de6d8f95c4b7ca7c79a0cd208c63fb0888ac580200000000000017a9146e2b0fcc2c4086d85becf46dae6d7af8c0bb07518738d6ea54", "prevouts": ["d453c1ad13000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "8032cc610d000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/keypath_valid", "success": {"scriptSig": "", "witness": ["b0e70b088525ec9342c39ffbeda6de86c95b6f4e996aa4d1877d6528a735d6f56f6c5047e4ad727e6c8147f22df9423a81218a920b673bdb6b66ee9f457dcac4"]}}, diff --git a/txscript/data/taproot-ref/250db3e160a3b1e5fb27d5880463b82d2da450a9 b/txscript/data/taproot-ref/250db3e160a3b1e5fb27d5880463b82d2da450a9 new file mode 100644 index 0000000000..817a031b56 --- /dev/null +++ b/txscript/data/taproot-ref/250db3e160a3b1e5fb27d5880463b82d2da450a9 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2601000000813b7ae6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc100000000e9fc16df02e0e58e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac31c5cb4e", "prevouts": ["c5496a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c351270000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b6ca9bd00465ce94790b3b7a982cef870607517f3d3166496de7dbf5954c12613b218f74fbd0c55276c685331fdb0afd974d82655877a178fabd8a81865588a6da74b77cec5b7fe449456850d166470def075aebaeccf9499b10505089f5a1cfc7acfc3c61e892a316f931a7e8a743174c6f9d4dde170747ae9fbe17ddeb8e226e47d3da47b9a193dc9a7264e112daacb6f035e28c5102c6322c133c5f5d0b1bb197927209056cbf10e65ed20ee2eea49bbabece407e63d9389b55497709689b44fad0ea8d4fee74cfee5740c541ca49e9673207ed1c91a62bd89cece466f5041baa53f4877b4cfc8ac12aaed89add43ccfcd8614fb3448e11119743c06c2c27fdf88097760c4c7fb482ff62ff52f95440b228504b9369885666588b5aa959d63642f6a47526912090d7eecbe4577ba7566ab1db067ad735b38ccdb03512eb6a8fa7442aaadacbdd3f6a5d23d69b9f0af76d5a288097f92b1d4bc459202435466efdfabe45bb529d952e000da4af29575a01d1caa8864ee77d8dd70f110ff0caee764a67658d9b9d0b8a44122ce224b2625c2c7ca1a2824d78fdfa1b07881176fc1c37a8847e7d8ccd5738fbf671df2af66a030bee73931c9e2657ab6c06fa189af7a1adbdab9b9aeab90c85d457d6edd2238c1aee017c00eaab0ff850925e168cda5fbf9482886ac931bd6a5c74241ccf19c6c7404ebf7e3f8f51cba95a9e4d2d8e39fd5eb5bf195475c4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93640426f7abc0edfa3e5837ac88df8e230a9790a46604f0df0976590e171fcb82c1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045161570c3f10a90b75a16babedba4ef90c71a7e82b9436df981e4930578e77912a95f177959a3d24a94a797d1e607e5550897d4e95d12a52323e6e8eeeab3383c"]}, "failure": {"scriptSig": "", "witness": ["4d09026d3cc0d5b63b2610fac20b94fbcb41610aeec5956b511addfa87dbcdbaefc7eebe8947f2684977c8e598abdf9a0f776e51be058cb66ea05fe55aedcba2f9e576121e73dd9202aaf615367a08a46de36784d8eaad291b896b7ac5dfe654c93fbceb111f336f78dab89e5146430f3543b046820131318492ab4520f545a20f62b25828cab0aa3cc5dcbca3f3d0d454bd57823890a8e73ec4e0fb3393f34b42e22c782d8e5221d30282e3d0c91b60449f3e8b9304fd8e6547f2b239385ceb9b2631ac2e7d8b00c2d99f588ca876d9e405d017c9f3c3f9a8806bc7258f3bca0c7f2a8e1216042e649b8965bcf7fb01c9aa5db3c5aa942a9cd51e977281b3d747d72e783091cef5ef104751e70a066df14e1d03fde151b640efaaf6d606696b9f9034fdbda7d2e26ecc6d3075bf45695e6693f762752c121af7b799022db8e5ec0fea45c6b2fcd1b678c87f9861e7b0b3f86af0397c4cbc42780ab6873797831077171be6e0e71121e699eb94c06fc2ee4c8b27161d529d9c8fbbb1060fc15a6c6cd2215cdbb88e560ad167b99b03b058db52d78b14b1b51b7588c126ed7babea7e89aeafc539d5d3dc0f5612e50e31d95f3b6ffcd9b583167a929c32a15a50b1311f572261c5793a0e734b245611cbc636fd664507535e33c1b3352d13c0d0a011bda9d54974c888386e5f4eb02d1c213c20dcb0ec07b731ca05b715335c8bf12fa6aabd0d23e3401e39777561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c204e79a2ed843ca0f497febf0944f07030a971653548149129593a3acd07f1fd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5174048a48c6eb42f280da39a6557d46ee4318cb4e3319043ed115bdbceba7fd7e7407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}}, diff --git a/txscript/data/taproot-ref/253542d32b85965ac57232e3741542be2aa8d091 b/txscript/data/taproot-ref/253542d32b85965ac57232e3741542be2aa8d091 new file mode 100644 index 0000000000..67ec90cfd9 --- /dev/null +++ b/txscript/data/taproot-ref/253542d32b85965ac57232e3741542be2aa8d091 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d1000000007867cfcbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf47000000009ee3dbbf01c2b77700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6c0d4c1e", "prevouts": ["55523c00000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "ad3d770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["864c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4a89eab7efa8b8df17a82e815a072b99e340ac1768e499ee92fb25d88959474e250636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}, "failure": {"scriptSig": "", "witness": ["4c5286", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93696d81c4fed743e71eb520662c2db8c0fc2de5c834e975d368200854a3f19047c9a49af0eb7097a2b25f70d75fc7fd7c267678862dc5ecafe442b2ce2fa2401f5a112aec6b4b8b5b1ca7f36a9e0521bdf2c7802df3cadcb1e8aa67d830b4a0d3fd33ab5c29645e0220ea4ffd8cb7e67404885cb8b0cf94872336c7b06d59c3124"]}}, diff --git a/txscript/data/taproot-ref/25452194c45988fdb9442f977481e8fb95b4ad75 b/txscript/data/taproot-ref/25452194c45988fdb9442f977481e8fb95b4ad75 new file mode 100644 index 0000000000..5990ece591 --- /dev/null +++ b/txscript/data/taproot-ref/25452194c45988fdb9442f977481e8fb95b4ad75 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700700000000cf91ab8ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1e010000002e60e4f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43f0000000034add3ce038151bc00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79695b58e1e", "prevouts": ["055d0e00000000002251203236882dfaab6a61030776953d98ee1af902cb36dd280fe66ad8ee191278ec27", "e3536f00000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "e1fd400000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_7b", "final": true, "success": {"scriptSig": "", "witness": ["00559de3606cd6fb38dfa5bd6a0cece71320a2d5799b2f8df76ece1731b38d5e67ae7ee68f9c2efc1f9dccbede1c3586122debda6c390f1351aeb6c0784f554e02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3562b94c856a14147b325fb36410535b2d563f5b4302b04b7a68817b6d461b2274adc80d114388f32f51cbedde6e71d4859959baca2c45bbddc735229bdc8b1e7b", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2546c1139a14d6b2b3d6b9918c96de6e589fbf07 b/txscript/data/taproot-ref/2546c1139a14d6b2b3d6b9918c96de6e589fbf07 new file mode 100644 index 0000000000..1506c6a40e --- /dev/null +++ b/txscript/data/taproot-ref/2546c1139a14d6b2b3d6b9918c96de6e589fbf07 @@ -0,0 +1 @@ +{"tx": "7c7bc09502dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4a010000005814a0c1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf72010000002a1554c90484e08300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7fc000000", "prevouts": ["d98421000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87", "3e4f650000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["3044022007a486a869114165d5fc919c2eeec61779fc7b02a178f36b22edc5cb6a9ece2f022006e6213f5635c03fd8510cffe1da06601b5f4300c850699773a64590442945635f", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["3045022100cea15e514cdb25add06b3fbd62c250979141615cf92db862a8914169378ade5d02206ab02b7dbaf2f7ba0a077b95ae41e194116ac2c134be22be0ffbb84159d39ed85f", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/255e0819d8c9639459a4e49579fbd923cdf9240e b/txscript/data/taproot-ref/255e0819d8c9639459a4e49579fbd923cdf9240e new file mode 100644 index 0000000000..30f8010742 --- /dev/null +++ b/txscript/data/taproot-ref/255e0819d8c9639459a4e49579fbd923cdf9240e @@ -0,0 +1 @@ +{"tx": "5212986602bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe100000000b6aa49efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcb01000000fd92fc8b04ca0fa200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acecbfb437", "prevouts": ["7f66820000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1060210000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["814c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93649f82d663a1e447420f2cf05179af13964281439b8b427a6cb4b09af5b0cc191d3571a06a1d33120289e06483b2785a7356eedf367170ec7792d3587508789d4da9670c383f4b71f5a22d48df0589bd68dfe195935a65f1aeaa80f10f8ca6973"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d2fc2950fe45156b8c56aeb245dc43c1c6a55e17e72ce5d38a429da4652849019c228cb7ae814d70beabdb725e2cb3ba4f8af3a16648b1300fc97d27ac433c5da9670c383f4b71f5a22d48df0589bd68dfe195935a65f1aeaa80f10f8ca6973"]}}, diff --git a/txscript/data/taproot-ref/25608654bdece6361519480d9115afff3312cb31 b/txscript/data/taproot-ref/25608654bdece6361519480d9115afff3312cb31 new file mode 100644 index 0000000000..bf4780184b --- /dev/null +++ b/txscript/data/taproot-ref/25608654bdece6361519480d9115afff3312cb31 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5e00000000bb4e8ee2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8501000000acba6b03047a1da200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac91030000", "prevouts": ["a3a5820000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "952e220000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_bf", "final": true, "success": {"scriptSig": "", "witness": ["f593154ba8af9b372c525572230278b9c19b2a48dbd79fc5dc97da5541c23ce446f3ce84a544c17463a78167268231f7a3954f38be52d4629d08ead3369482fb83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["dedf1a77c9358f8385d28ea34d869318f7ad41ab42642f269cce982fec028412edb4234c53457221ec57aac1a2883eeb37b2ef75eb7b4a7141237ff2e293ec8fbf", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/25bdf9d085288589dbb23f1fc7d98f7783cb09fe b/txscript/data/taproot-ref/25bdf9d085288589dbb23f1fc7d98f7783cb09fe new file mode 100644 index 0000000000..3b442d6db1 --- /dev/null +++ b/txscript/data/taproot-ref/25bdf9d085288589dbb23f1fc7d98f7783cb09fe @@ -0,0 +1 @@ +{"tx": "82e7331e018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f6000000005e138bb703b93e37000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487db020000", "prevouts": ["49d039000000000017a91482be44661ef9d172a86ea47619409ff206130f7487"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2256202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["6ddce3068c94bded449e8fc546ab815d4baf7ae5981f67b59a6a85fc59ba731d1e5f4c659e5d88afefc4bc08228f2f291644dfd3a99a48b60452f4416eedf576"]}}, diff --git a/txscript/data/taproot-ref/25e7910e53d821321fab3c8bb9db847f37fff616 b/txscript/data/taproot-ref/25e7910e53d821321fab3c8bb9db847f37fff616 new file mode 100644 index 0000000000..23a6ca6a7d --- /dev/null +++ b/txscript/data/taproot-ref/25e7910e53d821321fab3c8bb9db847f37fff616 @@ -0,0 +1 @@ +{"tx": "6f7d0d91028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45d0100000075023faa8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e9000000009cb7bebe0114cd4600000000001600149d38710eb90e420b159c7a9263994c88e6810bc722010000", "prevouts": ["db1f410000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "a72f42000000000022512012d5e5f1356f7dd71d8fd34dd655f0d6117e8d6eac3bda425a0cfaea0a76750b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902474f16723479a702a9dd4086a6d913f04c60f046a28d4c3bdef03770d37766806130148165a399b8398f1a7a6101dced6c179bb01a4f58171a3cba1be405f3a4d6e4d8915b513563548274b2350913689a2b297bd7fb11c436ac69da8b7dc4e71c6d4956b2311aecb026f17411b65d6693f46e2f2cb4d9adc69ca99be0ced3e6ddb431514a79ff28635bff881dc5d7f0997c15764471eaa977e515916f501a35b6f85748b3821c1f18e0dd7cefb1455cdff896a1884d916e645c5a61ec830590af1a715d3653178f3d9f4784ee3080b83e4d9ac7c3a5285b1810bdf9c9641904258f5c2e5a810c831e3ded934f04c6dae31a4513e05ce52f75339f0bf2a9d8370395dc56c695b4e94e35703d06c2b89e79e18b6b7b1a5d29c6764f85c76d71c5f75514fcad37adc8f88b724532f65eb5d94402c31bf5217b1ee3fae3a1cc724e889c3bdb0f4973d23b1b023badf2786ad5f8514fdc9c901faa73face5ca598e7c70e64a38547e50fdffd7e67612061c7dc8c8c442c7dacd71b0961aeace9aa18b4c3d9750fd3b07b6b82b03abcc7e486c33345b8d11de7dfea74b29c0e0e5c379a5a69a80fd4e081df770950757e6f3adad7f637eea9e39a8b6d3f14973443ec2a78bd46959ebbf5f86b8774319f94349779d879b54120ec4e95040120837343d6958b3fc81fe9752c28b02d1bfa7c575be75c3b69f8e72552f140154a3fa2ed87cf9c0784316d013f758d", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e1ff68bf827032ff32c71cc2cc31eb8f40be3e575e2b9e5ebb1de96bc2fc57fb6a7569334f57ff848fadca8fed75a3aad007c69b24557dd271b830b96d574d63f2f7628d981d9c0428415dafbd1cc169dd3ce50060f3002d6f03fa895459568af43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}, "failure": {"scriptSig": "", "witness": ["4d09022f5a3443246efea87c796510050d88cf4e3457f805df227ef0f78f28e0783d00488533cf9debf1b6fbcdac460fcd69643214a3c1065dc5c6775a77c9d91f10479c2c465fffc8b82b3c658eb8289dfb776218fd29e1299865e770952f0b6ba7fc28da221ba35699be6f01dd6b4e07e335abff4a640b5ea9bdd08d07aa5dba50010c194d02ea6aa3c393aed2b51aafb7e7ffa26cbc23836ba1d7986eb90456a905dee34fa3195e04ed92a5e2a64dde4a2580ae0a71b94a2dd247cb63db853bb88d64dea5ddaffd9a0cfb57322e76f6fb12b4239eac0b2408dd779a90255ec907eb7c27664ce924c6a6920d6c793a65ae2d0d12f4b5a7b51db9cc92798737643f63fa7bd1ccb64a737d749068fa91fb7de636e1cb3086d6865d538f2cee23bd9dcbbc4dd7b05d582f75a54b58a751cb45358bb07449bf60035f3d913d5e31074139a57acfcced21d25eac61e76c5e9a586804f18b12f4d60629809c43396cd345106c971019b88f5c485a7d84d057e3c5f64ef1057d0389cb598151d4b8577774844dc0a4cdc5c1fa841f9f41fdf9557e59cf3f274f02a2b16b2411ed9e1882ea17cab93c44850f7a768512a7212a1679bd8066716d98b61e046d9997c602805698256778c56d3866b4cf166673f5ee8ca2820a58ea7d5068101a053ac1af88127f59b58bdbb2b5125aec4c27da2d1eb65e05c00109a36fd167a8e09a6b9e7c944af4a82ec2070aeecbad7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368c644295f81108e0be886f59870f13809827e9d797ba4690398470dbc4c919c19886f85ebb300297009aa959255e1f8e976b091c7e06b33477ed400c40a83b4c185c953dbf0a33402e724bbb72e47d874a897a0941d53d9706dc82e2e14efc19f43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}}, diff --git a/txscript/data/taproot-ref/25f13dc685e40d3fb22819356cbba4a5a6789e15 b/txscript/data/taproot-ref/25f13dc685e40d3fb22819356cbba4a5a6789e15 new file mode 100644 index 0000000000..b23e75abfd --- /dev/null +++ b/txscript/data/taproot-ref/25f13dc685e40d3fb22819356cbba4a5a6789e15 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4b010000006599e3b460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e9010000002319b8e0033a632e000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a3600632", "prevouts": ["b22e1f00000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7", "0de6100000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b6726ecd04cb905c4ce1620edede51b486a0bd5e02be9efb7864f9dd4803dfc8a154b22b0f2e2bdd7f3b34b8feaf196c14822a5749c8a329692c0e12e8447d605976fe26432a41f3547171b2b9abb696d7de0172bd15211267873326056804912e839b87dc613c826a9c62085431a96f79b8782d4b0fe31dfc75aede09e250a"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363993fbb03bcf38c66ad1844758b0c7119cbc650054de9c9a3fd376fb91c92df78a2960a95becb1bbbe0636e0493c58f712af9b8da417013d797bf12c130ac56070886d9e3726a9aa8a2b94454683b5181a970edd894e0d0cd75aad09f75436b2"]}}, diff --git a/txscript/data/taproot-ref/25fd25289846f102771af05c1445e63acb583b93 b/txscript/data/taproot-ref/25fd25289846f102771af05c1445e63acb583b93 new file mode 100644 index 0000000000..7db41a27f9 --- /dev/null +++ b/txscript/data/taproot-ref/25fd25289846f102771af05c1445e63acb583b93 @@ -0,0 +1 @@ +{"tx": "abcdc84802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2300000000aef782f1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7f000000006a9856a70490143e0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df97972236898704010000", "prevouts": ["dd33220000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "a0951e000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "8f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936963dc86bc71687ecacc1e5b8f2c4145fceca424a4eb02fbe2bf7a8e8f9bd1024e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e81f261744aaaab7b61bfd8b873ce05c274059b1d1cb072d2d2c67e8900f407405dd5f972b05e2f18c3e7c797b604beeb8879a3af7f1e10968a0ac8aaf9d489fe7"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa458187dbd74455692a21727c8254a8cae6fcc3fc3c7e883861248db6e64d9919f8fae370a255a677f2f729010dbb329fa966ed9a0dd82e5083dd7ea90426dc47"]}}, diff --git a/txscript/data/taproot-ref/2619632226257817c56eb288a9d2075e56dd0e34 b/txscript/data/taproot-ref/2619632226257817c56eb288a9d2075e56dd0e34 new file mode 100644 index 0000000000..85608e340d --- /dev/null +++ b/txscript/data/taproot-ref/2619632226257817c56eb288a9d2075e56dd0e34 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4df00000000d95f0a96dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8f010000003207e989016e8a0d000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d3010000", "prevouts": ["4a6b3a0000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde", "6934240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "477d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8af5253a3ae898682e613588786a672ae77746787ad628dd74364be19bb5242936657009e9173c5ef8826379cea4b8c999e3ae37a5805e4cc6da117a3d2ee0eec"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93624f7d08525b5d52815de985e807035e6f0110330bf2d62b1ce3b9c92499c7c7ca24674935b347637fb115fbceef28e6d08e5e47afc6eaa336546ee2e891e964bfd9e929a06047270fff43ba4c6b47136464c62381aba7ed74ab98bc69d199aa4"]}}, diff --git a/txscript/data/taproot-ref/26300a1704f502625832730a36d0088f21a46e2f b/txscript/data/taproot-ref/26300a1704f502625832730a36d0088f21a46e2f new file mode 100644 index 0000000000..cc845a15a8 --- /dev/null +++ b/txscript/data/taproot-ref/26300a1704f502625832730a36d0088f21a46e2f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf19000000009d3e6ea68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44800000000855c81ec04bce4aa000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478709000000", "prevouts": ["c8fd7a00000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9", "b6d4320000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "d07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362b8a3482aa7cb17cad77f3537e7f0fb67661c6720f234fbfa8fc690463546899da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e15c449093bd19eda03bff23881ea6078d018b9cd0ffff6e12447ca822e876d277e36b196311c1a9d305bc653889017f46f4c4934a1587d131a83127df4466fae"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360723cf45802ddf87c5577cf46e20a53b28825f20a581d36a06d1de070a7e046a1c85c730685924be02f7d46bcb10c9c474c6189388cc381e7f7055dcad1cfa477e36b196311c1a9d305bc653889017f46f4c4934a1587d131a83127df4466fae"]}}, diff --git a/txscript/data/taproot-ref/265d0640e2752abb03fbe0a1b150f575f8469aa5 b/txscript/data/taproot-ref/265d0640e2752abb03fbe0a1b150f575f8469aa5 new file mode 100644 index 0000000000..3dc46a2320 --- /dev/null +++ b/txscript/data/taproot-ref/265d0640e2752abb03fbe0a1b150f575f8469aa5 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270190000000065a894b4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bed00000000c5e85eed04a6fd3100000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787cd030000", "prevouts": ["661a0f0000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6", "f080250000000000225120ed31d524ef6bc5b71a68a40bfd6359c52f177bae49683ad83ab62d1806c34929"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e85f3be5f8f698e83d3665b890524642b89b7b05493241beec338309aba778c454d8fcf0fa02e125fe1892f3caadd01fd66f2ae3104b90b9e35e4c43083bce335e4e9031d393e93ec4f3e9da8fc51e83b82f31256dd96ef4af94581a47eb5c67bc"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ce38f36f588003ae3435f4b7a2e1027d2d00dc9eb0fa8adac7713a480749442478f34169e056cf51b9394d2ada3735c0a63dc9f48f236da8ac021a74c045d29ed6bb91bf977e9e370b444e9d5512cd4ec7f3694a9311c01272a4c1a167cd930"]}}, diff --git a/txscript/data/taproot-ref/2669c9c65bf3af74d4482204c70ea69545d8babf b/txscript/data/taproot-ref/2669c9c65bf3af74d4482204c70ea69545d8babf new file mode 100644 index 0000000000..ae60c4eafc --- /dev/null +++ b/txscript/data/taproot-ref/2669c9c65bf3af74d4482204c70ea69545d8babf @@ -0,0 +1 @@ +{"tx": "f919006c02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf62000000009ccc4ad2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0800000000c2f31cf701a3813c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487d9fcb420", "prevouts": ["8e88720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "735d69000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "final": true, "success": {"scriptSig": "", "witness": ["cd134634a4384f5c6c32353fe0e3d4d3d31c5b176345ebc07f2d6b30b01669e93bd94fe207a6f5e1de2dfe583fffba5c4cdfadc0fe688e34f59c67edd84c81e402"]}, "failure": {"scriptSig": "", "witness": ["34f4a8bcf08a0c7499841efc7edf06fb25520b9fa9dfc2cbdfe0b4a9c488742f71d24044f0729ee618ebdb316ef7c67370cec6e754683a0379cf2a680317120d02"]}}, diff --git a/txscript/data/taproot-ref/266c1691a90b2a342849d25e3704659308c45951 b/txscript/data/taproot-ref/266c1691a90b2a342849d25e3704659308c45951 new file mode 100644 index 0000000000..b432d29dc6 --- /dev/null +++ b/txscript/data/taproot-ref/266c1691a90b2a342849d25e3704659308c45951 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706a010000003d8886bbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf770000000088db63dd03e1877e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478742010000", "prevouts": ["ee0f13000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "54426d000000000017a914f5a65ca4534ef3ca5833434c0dd44a3e128f499587"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2259202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["427dc8da4ffa5ecc822b1cf3bae38ff8a32e3788355b9ea21ba5f58b5e2eb6f6a70fdb814bdc4801d45574dfc9679198c5d5228957fe3481a577a9cd3a280d28"]}}, diff --git a/txscript/data/taproot-ref/2670c894e879a8499f50e08ae018e501b6693152 b/txscript/data/taproot-ref/2670c894e879a8499f50e08ae018e501b6693152 new file mode 100644 index 0000000000..4e8725e3ad --- /dev/null +++ b/txscript/data/taproot-ref/2670c894e879a8499f50e08ae018e501b6693152 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5500000000e17386c6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbf01000000655e64b60215bcbb000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48731792f38", "prevouts": ["e16e49000000000017a914e18c03fb168c1c1b3408ffb477de8ff77b0fbd9587", "c198740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["32ff6e2411fdf496fa6bfc80d7fdcd16b6c28f11fd1090550cd0f96c6c0ae439a7569296b8018165923a6c60a08873efaa1e0d3579a9e43aaa530e4da034901d"]}}, diff --git a/txscript/data/taproot-ref/2692015cba943bdfa1b324204d53284234754d15 b/txscript/data/taproot-ref/2692015cba943bdfa1b324204d53284234754d15 new file mode 100644 index 0000000000..eb55c85f58 --- /dev/null +++ b/txscript/data/taproot-ref/2692015cba943bdfa1b324204d53284234754d15 @@ -0,0 +1 @@ +{"tx": "71b5e2d803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba401000000be38a9c2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9b010000003949d5b6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba2010000007c0e80f601ed1c22000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787e6a4735d", "prevouts": ["4a3f2100000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "f873240000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "4005270000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "e67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d518f5fcc4dcd317f656293c43c0e8e59e06b99ff36e809cba7caf0d79972dd48256d6f90d235a6ba3188b640209fb1b87a6d8106344fff793e748ee999a397d93d03784866e2fdd94d7d1b7c12b1f0da96746c05c19b8696f0ac6a701ba8135"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee92d7728fe824bb86fbd19678fc348031552299afe2faac0cf612835804e2a859ea19512c809756aa5c58e4cd3562935caab0c2ca4eda8db33914ce4decb3cfe9d11a7792f25f0da70e8485da42647201d1062d1bd001b767f1b05dec6877400"]}}, diff --git a/txscript/data/taproot-ref/26fbe1c5bd294a3fc35af2e36f46c951b25e5cc3 b/txscript/data/taproot-ref/26fbe1c5bd294a3fc35af2e36f46c951b25e5cc3 new file mode 100644 index 0000000000..7723b42208 --- /dev/null +++ b/txscript/data/taproot-ref/26fbe1c5bd294a3fc35af2e36f46c951b25e5cc3 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d900000000dd8001afdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c19000000007ff930cf04916466000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8749030000", "prevouts": ["a68d110000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "567c56000000000022512077fcdfa5b83233990258cd0e78144655048956ba28606e7ed979bb07d82944e6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670f2b09ce069cb1d2f19757a518c7d2541e6ab5f0b990938e6d2f93119732f11"]}, "failure": {"scriptSig": "", "witness": ["6a70616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/2721ca2fc08ca7ae38cc809a3799bf618ce5a75d b/txscript/data/taproot-ref/2721ca2fc08ca7ae38cc809a3799bf618ce5a75d new file mode 100644 index 0000000000..f37d736596 --- /dev/null +++ b/txscript/data/taproot-ref/2721ca2fc08ca7ae38cc809a3799bf618ce5a75d @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703200000000ac43b0a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2801000000ab411cb402bca15a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963af0dd3e", "prevouts": ["d08e120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "319b4a000000000017a9141d8eff3030620b266a8bb5e50900ecd7b2ab72da87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_22", "final": true, "success": {"scriptSig": "", "witness": ["1d30e194b4df56e01a172013a81217111f42aae7e242ef28ac1e86f071b2f101b3cfe1acb5c3bbe18090905b5d0418b1630f46afd2b9d4e64cc490ca5599f68301"]}, "failure": {"scriptSig": "", "witness": ["f0785c48c61905e841e84567b2ceb69b42c2bae46fc17cec918a2dfc700a36687ca07a9bc318dfc810379f1ecd9754a11e2e20d2aa8abfffe44f36042c9563e322"]}}, diff --git a/txscript/data/taproot-ref/2756fd453011fa7471613114061631b066029dc5 b/txscript/data/taproot-ref/2756fd453011fa7471613114061631b066029dc5 new file mode 100644 index 0000000000..5b123f1ec9 --- /dev/null +++ b/txscript/data/taproot-ref/2756fd453011fa7471613114061631b066029dc5 @@ -0,0 +1 @@ +{"tx": "7aa1c49802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf23000000009585a1b7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b88000000003b0b69d601c2a39000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3b797542", "prevouts": ["9ed88400000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "440b1f000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "7f", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db342938b39be9e12773a9624b573dbb1df9d93500dc93058087a84b4280ff8e70f73741da43ca43557c58f6aa15023f4cf70566ac935702465d6fb0f93d4429f8d5397512e216c7ab52609f0ab27ccbbfd2b7e561d7599ada55e292956af911ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb44a1c4274957806206aadadfd15cabecf517c42c49a66a44e84081097b7475aac480120d5a477c096fbef97d1ee2aeb957fc425ff8aedf322b93097b3a97db744cf5fd42f9969f7f2472ed1fa62ffa49909a09466cf06ef7c57cb1be351156c54"]}}, diff --git a/txscript/data/taproot-ref/278eb959a30cf3ec8163a007eb3f89ef107765ea b/txscript/data/taproot-ref/278eb959a30cf3ec8163a007eb3f89ef107765ea new file mode 100644 index 0000000000..2b0a707660 --- /dev/null +++ b/txscript/data/taproot-ref/278eb959a30cf3ec8163a007eb3f89ef107765ea @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270230000000056475b9ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca0010000002f35f8e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8900000000ccb14bf503f56ee6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898746a49225", "prevouts": ["6ab20e0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "e73c5e000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "aea27b00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100ada79d62fa15f9115d82840b8691c32a9675d1153431a30d84c575b27f655ff5022037daf47feead7f6bf130cf9b11c67c0ddd821710093bfe758b63d51759b1e2b882", "witness": []}, "failure": {"scriptSig": "473044022055e9d1d50eba789b485e7be1d8723ea09824cb56ff53c14b2dee44d74e7ec379022070fc42377626267d182fdb531525ef651da68d02a997ed5f6da35f9751d958db82", "witness": []}}, diff --git a/txscript/data/taproot-ref/27ab4c447f840d27a13d145eb27c80db511a400a b/txscript/data/taproot-ref/27ab4c447f840d27a13d145eb27c80db511a400a new file mode 100644 index 0000000000..9ffd8dd8fe --- /dev/null +++ b/txscript/data/taproot-ref/27ab4c447f840d27a13d145eb27c80db511a400a @@ -0,0 +1 @@ +{"tx": "aceead2a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b940100000081d662d860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270db0000000091e8ebe1033d623500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acb2000000", "prevouts": ["f89c280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "688a0e00000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ff", "final": true, "success": {"scriptSig": "", "witness": ["9e14bb8d59f2cdaa26d8446bafdb8ad8e26ae889daa3c5b6be4daf7a5c66b12ffefcc72a251df6530db46cfb3872d1a655816c7e4d0baa30c7a2d8557b82375f83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3a2b267d257536b91fa1ea735b5cafcc7a828875c141be7ffa30f52e08c3eca7fdedf355b3d272cc504879d9dcdcbe4df548b291235c0737fc48beb180a84b71ff", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/27aff0ad61d128505e22df766c0492e316fbd9a9 b/txscript/data/taproot-ref/27aff0ad61d128505e22df766c0492e316fbd9a9 new file mode 100644 index 0000000000..4870a8b4d7 --- /dev/null +++ b/txscript/data/taproot-ref/27aff0ad61d128505e22df766c0492e316fbd9a9 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708f010000007d6193fc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f6010000004a71e3b960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705c01000000093cd1cd02363e64000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87f047c423", "prevouts": ["df2c110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4a5e4300000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "818712000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e26684d91d6a25611b98f9525cf8030045f0e379e1e6360450dcf32f11d35fa349c2fd9879a2ee2ae7d76224c991edc718b1729f7f1922f570a67a21926d2cc48d"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93600db14dabffde4eadee715a8622cdc410adca6ffbf626fcd1e3a6b0b6e154d3c99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4faa718416d21ef008df2257ef512539448f5ca520db3fa3c7b8aa919421e6092eedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}}, diff --git a/txscript/data/taproot-ref/27b9b3e3bde2958e048cee68f2493d41648987d3 b/txscript/data/taproot-ref/27b9b3e3bde2958e048cee68f2493d41648987d3 new file mode 100644 index 0000000000..a837dc5f23 --- /dev/null +++ b/txscript/data/taproot-ref/27b9b3e3bde2958e048cee68f2493d41648987d3 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba0010000003f954bf360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706501000000f7025ddc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ec00000000d17f70eb03851b6d000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3a773856", "prevouts": ["90ed1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6154110000000000225120685f1f4d981f8d279e9288f3fac3f130840e4486d97e094876558f7ee35a7d24", "1f353f000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_70", "final": true, "success": {"scriptSig": "", "witness": ["4dda5727b9cd37b5c14c9a77d8af9d109ec06230eb6cd58d9f51bbe0feeb0ed852e20570d011a45d84becb8e6cf238140c68a811fd7571bed3a847994bd2e09f03"]}, "failure": {"scriptSig": "", "witness": ["498ee427afbf3f1d086ac1eeb701926ab18225d1677e7bc7ed55b83c072d4f6517b884c5050b13dbefac8a91c54a49bec9d0e094ebcf4868148dc71241d79f4f70"]}}, diff --git a/txscript/data/taproot-ref/27be24f0f9eb749b51dc6e83c6ab5c8637349a25 b/txscript/data/taproot-ref/27be24f0f9eb749b51dc6e83c6ab5c8637349a25 new file mode 100644 index 0000000000..48c4f9bc07 --- /dev/null +++ b/txscript/data/taproot-ref/27be24f0f9eb749b51dc6e83c6ab5c8637349a25 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc7010000003a0d4fc5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1700000000c98173e6018bbc4f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87921bfa49", "prevouts": ["658421000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "ad0a4c00000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "897d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa58e965213f8dbdd3ccbab86b6d585f0f8e78abed831015bbc989f3cab476ce59ac632f1e88e109b3d5485dae08acb0148fc939094c3a94300b3efbd66c89bc20"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e8e7fff1bca432c9ba96d0556d2ed7bd47849d71950e18b52879751e42d3038d46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa58e965213f8dbdd3ccbab86b6d585f0f8e78abed831015bbc989f3cab476ce59ac632f1e88e109b3d5485dae08acb0148fc939094c3a94300b3efbd66c89bc20"]}}, diff --git a/txscript/data/taproot-ref/27d37797fa4bb9c3bba68f9967eab892fec70642 b/txscript/data/taproot-ref/27d37797fa4bb9c3bba68f9967eab892fec70642 new file mode 100644 index 0000000000..752c5b79c6 --- /dev/null +++ b/txscript/data/taproot-ref/27d37797fa4bb9c3bba68f9967eab892fec70642 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0202000000b786b0918bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a20000000008aab3a404e02093000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47878a82972a", "prevouts": ["2360560000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "88d43e0000000000225120032ba6f397146bf93cda2585b16902a48899558623e6c842c83c4de6509e8b52"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638068", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045f29e1e33c93035514fb0dd85894dc242cac3fcef5d3781aac1ff5cb7ed66668ed2fecf8564d6a652bf0232997fa790ca314d73b111c417284694cd1738ccb12191585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a13e25e6d35815262cd49d2dcc0fd0de63cfe51aa238dc2e6ca3c341dac8fec3f29e1e33c93035514fb0dd85894dc242cac3fcef5d3781aac1ff5cb7ed66668ed2fecf8564d6a652bf0232997fa790ca314d73b111c417284694cd1738ccb12191585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}}, diff --git a/txscript/data/taproot-ref/27f1dbe3a65014c59ae266af3346177a5a57d4e5 b/txscript/data/taproot-ref/27f1dbe3a65014c59ae266af3346177a5a57d4e5 new file mode 100644 index 0000000000..e8f9b5a3b2 --- /dev/null +++ b/txscript/data/taproot-ref/27f1dbe3a65014c59ae266af3346177a5a57d4e5 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ef000000008cdb3d2f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4740100000070de6b5704c11e770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7d5000000", "prevouts": ["21b33d00000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "6ab93b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b3", "final": true, "success": {"scriptSig": "", "witness": ["cbac7272a76e134786c66591596a58a32a0e363a6c6d1dff45def2968dcb61b0d39730d5d0392d53f294f0a45acd9374d448934224a8fb142935427831900fc302"]}, "failure": {"scriptSig": "", "witness": ["c765d437cdac54a1521f4c8960c1afd35707362404339f96252de68961be4c3227f95a2ea6a636e381b263f3c90908a09a7d653e583805de653055e5c68776e2b3"]}}, diff --git a/txscript/data/taproot-ref/2807a46ba9b453c2f9e4af2406b26ed38137b216 b/txscript/data/taproot-ref/2807a46ba9b453c2f9e4af2406b26ed38137b216 new file mode 100644 index 0000000000..d265fdb633 --- /dev/null +++ b/txscript/data/taproot-ref/2807a46ba9b453c2f9e4af2406b26ed38137b216 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c370000000026ad1f6dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbf00000000f2e52467039292ce00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac85020000", "prevouts": ["88de5c0000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "035a730000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["ee4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ba746a1e3af4c529d3cdba1b4e6cf9b58f2b1e1d981455be45b81cc2f039993b0f3b0db014ceaa26ae02ffb8f31853eb721e6357de034fb71f3898341a9ea5240028cdc19f89baf6c362287c7c7841c4536091540a9bd978c440258b5fe7844c439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}, "failure": {"scriptSig": "", "witness": ["4c52ee", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab3d7a13ff99e8e18dacbbc4ceeaa4446ab48fce45aaf041cd197f8d702987f5dd207214d6df2d18dfa237afd6016520e9e6ed6636ebebd182087bb183877c35439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}}, diff --git a/txscript/data/taproot-ref/280d6a9607ad78d3eb40f04e5b5a76c6f8eb4c02 b/txscript/data/taproot-ref/280d6a9607ad78d3eb40f04e5b5a76c6f8eb4c02 new file mode 100644 index 0000000000..9d36b79afd --- /dev/null +++ b/txscript/data/taproot-ref/280d6a9607ad78d3eb40f04e5b5a76c6f8eb4c02 @@ -0,0 +1 @@ +{"tx": "0affb4e102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb601000000148475f38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42101000000c9d6518c023f499c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf4e9e538", "prevouts": ["110a680000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5f3e3700000000002358212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["e4fd4aa8ed373d196ab6e9a0ba8935c0d889eadfc5126511718e0b222975eb97e2f882010153a250c4f4b2ac4fd2d10797cfae46c68a67bcccc6a7fa91e2636c"]}}, diff --git a/txscript/data/taproot-ref/28259bbbf78c881c7400ac4602722df51776ffe0 b/txscript/data/taproot-ref/28259bbbf78c881c7400ac4602722df51776ffe0 new file mode 100644 index 0000000000..b4dceadcd7 --- /dev/null +++ b/txscript/data/taproot-ref/28259bbbf78c881c7400ac4602722df51776ffe0 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c57000000006bfe37f5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd9000000002b9ed0c5018f7108000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478720040000", "prevouts": ["571d530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a4e51e0000000000215c1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["dbb4ed59e14362647749d55139746050f452d9ecc6c022c09328971453f73ac09c4dcc8d420a62aaf6b133b2cdf953aa3df1b048687bbad72fa841068b20765c"]}}, diff --git a/txscript/data/taproot-ref/284cac89d0553dfdc596ce4bfc4251fd2115cb15 b/txscript/data/taproot-ref/284cac89d0553dfdc596ce4bfc4251fd2115cb15 new file mode 100644 index 0000000000..a35278c2f7 --- /dev/null +++ b/txscript/data/taproot-ref/284cac89d0553dfdc596ce4bfc4251fd2115cb15 @@ -0,0 +1 @@ +{"tx": "c78d28c0028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b900000000714907ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709c00000000d69c6cbb04d88644000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689876b010000", "prevouts": ["d6823600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "c2831000000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93648f8d343e45b2a3fbb17d68cee821227f9a1b53be93535e58c68639dc86e84fc4b6f5261b409d682c30910e7df322d9859114aeb60c7168b8885bdaa0165cc6510b3b87e8b9d8544644738d4851bae032b2bf37d3a4aa6541b936ff18c715610c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7e8952e748deb89d7f1315439c5970ec42920b4cab4cfb00d3d1dcb758e23bdbdcbe75f074483e48d717af2cfa8ab1bbef1c35fc84f016c108dd10256d535ae10b3b87e8b9d8544644738d4851bae032b2bf37d3a4aa6541b936ff18c715610c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}}, diff --git a/txscript/data/taproot-ref/2872201824aca727042b22cae049102582283dd9 b/txscript/data/taproot-ref/2872201824aca727042b22cae049102582283dd9 new file mode 100644 index 0000000000..80388620a3 --- /dev/null +++ b/txscript/data/taproot-ref/2872201824aca727042b22cae049102582283dd9 @@ -0,0 +1 @@ +{"tx": "a5db689303dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8e00000000ee83d8e88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49d010000003a8b0fcadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6e01000000d40773fa021b25830000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ace0020000", "prevouts": ["24a5260000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8", "e8e73c0000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "4909220000000000225120acc511cd55079365da76d18a33af3ae7411f3879a9caec918e9264c8959f5dac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "017d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93680d50eb913f48c4bd7a21deaca51149041449e391631c234baaeef92aa25ad44d7f8ee1a917297df4869582a1b348cabbff1db4a1952fbd39d89a346cd02d0a88810a2a55ef559e3dd2f859359930339f67e2de31eeac841179b888fd41fd8a3"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4e5ee47dc19cce5f5bcfbe17d15c6a925997647a0a2c3c32d22380bb5e59a56e05873438be84f92d1402d5d55e9fb409fe52800aaeb5db180b239b834bc1ca2"]}}, diff --git a/txscript/data/taproot-ref/288e61a59fe0099d03730d5c9d59712f743123a2 b/txscript/data/taproot-ref/288e61a59fe0099d03730d5c9d59712f743123a2 new file mode 100644 index 0000000000..03a751dda7 --- /dev/null +++ b/txscript/data/taproot-ref/288e61a59fe0099d03730d5c9d59712f743123a2 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b90000000044735f0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a5000000005a25110d02bd811f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8714020000", "prevouts": ["8cf00e000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "bb0213000000000017a914381003aa1ce42a7df73f2dd1e6e78ae0a36c6b1c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082093e484a9e3a7c57c3845514d142b984218effb649d9e5eb3f309ab706810aa991d26af6ddceab3892536958f1ea20dd7b885ab499207106c7decaa6511a0e4c5a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93644f2e60a682fd302b1c3c798b38ae6e5157f4f93288539ff9c08590bf0a0b2aad300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5112303efa97a8ef6ff3cee2bba9a63ee7e38a3d19e4db44f275f3f55c4e39991f7cc0cd924d9aecb0bc2fcf01621d0e73a88693291594fa52fe0219caeccfa5b3"]}}, diff --git a/txscript/data/taproot-ref/28a21b4f4afeb9c978b1290c620548f1f33e127e b/txscript/data/taproot-ref/28a21b4f4afeb9c978b1290c620548f1f33e127e new file mode 100644 index 0000000000..2a92a95b29 --- /dev/null +++ b/txscript/data/taproot-ref/28a21b4f4afeb9c978b1290c620548f1f33e127e @@ -0,0 +1 @@ +{"tx": "f919006c02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf62000000009ccc4ad2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0800000000c2f31cf701a3813c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487d9fcb420", "prevouts": ["8e88720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "735d69000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f", "final": true, "success": {"scriptSig": "", "witness": ["0ef016eaa849eeae9a07777b6688a6da7982dcb02ef9b98bbfabfa68721fa22f79a121b00be8e65588652fa6f7a396e04dd6496767c76640ec8817c0fa0c20c382", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1a286ae53a16e195ffe38b0b70f03e31f7b8293a664a7f566b1547c94a9f631b521b544aafdba8dafec5583da9e032adbf676a1373c2e8967b03f911f63da1d90f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/28b1a2ce5cf374a3ce64a6c7853fdbb6a15d1e25 b/txscript/data/taproot-ref/28b1a2ce5cf374a3ce64a6c7853fdbb6a15d1e25 new file mode 100644 index 0000000000..5da1ca6b7d --- /dev/null +++ b/txscript/data/taproot-ref/28b1a2ce5cf374a3ce64a6c7853fdbb6a15d1e25 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ca010000006bee4fa801e60a040000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcdb000000", "prevouts": ["74673b00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "317d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e14e57181048ac96cb53327a8f686080e72dc312071604fe817a5f66426afc20b12f65ebf74c8b951b09da599ea3d6f486010b8cccb0a2142ec39aae62c1ca3e7"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363c68f787ab385ea36bbb3a618645cecd085be4294b842aea644329206b21f53e4187c77ca06c68e3a239e6fea37385de49c0e93bf09ae3a990bb588f1e26193612f65ebf74c8b951b09da599ea3d6f486010b8cccb0a2142ec39aae62c1ca3e7"]}}, diff --git a/txscript/data/taproot-ref/28f223ee6f9c2562b1e382ea899bc7f88e63490e b/txscript/data/taproot-ref/28f223ee6f9c2562b1e382ea899bc7f88e63490e new file mode 100644 index 0000000000..80f0489777 --- /dev/null +++ b/txscript/data/taproot-ref/28f223ee6f9c2562b1e382ea899bc7f88e63490e @@ -0,0 +1 @@ +{"tx": "5f9251c902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf800000000bc13d3a860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705b01000000331e88c204b46b2e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48766d85037", "prevouts": ["0f9b210000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "89ee0e000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000db", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f48f2841dab59f80ad6998fa3cd0986050b454c28fbbaecb941d0e8795529b49f09ad02cb012ed2091760f4e9ad26775ad10447e2b9e598a8be746abc4727fb4e3966518140ddfb4b2a9d93e012e33d80f6a3bf7f24f1b44efe84ec3ac236f0e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b7f6b7f6faf43deefc8dfb90058dbe61b727862c364ff314077bff4a6c878d2754e6d4b188f4ba3829c97f16419e7d7896d7c05fe6215d1417ce194d9971cb9e3dda2dfca806ccc9c3ad62846e64b9ac16121de5d926db5bebf2e82f8dec8d2a"]}}, diff --git a/txscript/data/taproot-ref/28f4e044d59009036250527f061daea52c6b5917 b/txscript/data/taproot-ref/28f4e044d59009036250527f061daea52c6b5917 new file mode 100644 index 0000000000..a42de1a793 --- /dev/null +++ b/txscript/data/taproot-ref/28f4e044d59009036250527f061daea52c6b5917 @@ -0,0 +1 @@ +{"tx": "9ca1b5ad038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46400000000a64e37f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e001000000fa4a59c660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703701000000d0973dde03647656000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd90b845f", "prevouts": ["ae4139000000000021511f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "4d750e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7465110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_3f", "final": true, "success": {"scriptSig": "", "witness": ["5cb3501b241eea500dedaaf16734b6243eb53e4ff4acd4e81ea8ca35c0ac1aeca287614ea75026f7ac7b806cc7d6a09e211fc149fbbac303a5f4075fb083314a83"]}, "failure": {"scriptSig": "", "witness": ["444c64a22e1610258cdaf53ec7625f2df5c6d8af447b82d0ae63d8c323b1b69bd2ef597e20675587e40d925dbb230b98ac201588e7bdb1749777c2be392eb9273f"]}}, diff --git a/txscript/data/taproot-ref/290325a794a4307e35ab570d847c9854f6d63001 b/txscript/data/taproot-ref/290325a794a4307e35ab570d847c9854f6d63001 new file mode 100644 index 0000000000..52ca5a6a7e --- /dev/null +++ b/txscript/data/taproot-ref/290325a794a4307e35ab570d847c9854f6d63001 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4da000000006af8c3e060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270870100000017873a89035f27450000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcfe030000", "prevouts": ["2887390000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "a9700e000000000017a914381003aa1ce42a7df73f2dd1e6e78ae0a36c6b1c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1654142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["8df426347ce7aa183839cbace2dc0aa6559f8e0884b104badaa8f337f90ca4beec5468c71dac3655f4facf4e9a257dfd14f021ca3a5866be730454807685f9a7"]}}, diff --git a/txscript/data/taproot-ref/290a1cf15d24d80b8dba0ba4397f5a7eb13382d0 b/txscript/data/taproot-ref/290a1cf15d24d80b8dba0ba4397f5a7eb13382d0 new file mode 100644 index 0000000000..8aa08cd2a8 --- /dev/null +++ b/txscript/data/taproot-ref/290a1cf15d24d80b8dba0ba4397f5a7eb13382d0 @@ -0,0 +1 @@ +{"tx": "865915d603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4200000000458456e0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9d00000000e0cafcf560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707a000000000805b2d203a5255300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4a000000", "prevouts": ["ed2920000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "3f51250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e9fa0f0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_8f", "final": true, "success": {"scriptSig": "", "witness": ["c38095a8e2603d473d663749cd03aa5edc0c9224eb38c6efdf8e4872b14c37516b08471a575cbb113ca5a41ef9cc12294e3e3b7205928f3dd873b17f19b7195102"]}, "failure": {"scriptSig": "", "witness": ["2429f911d27d6e99d9a0ad91ba066dbe28df85ac96882efa0d3a30838ab045992494697bb2bee74d1b2a81a1b08bf2bbfe4f959cab3777a4f9be5d0caf1cd7178f"]}}, diff --git a/txscript/data/taproot-ref/29186f53cff8c33b62ccd1cec92b4c6b02c8c2c8 b/txscript/data/taproot-ref/29186f53cff8c33b62ccd1cec92b4c6b02c8c2c8 new file mode 100644 index 0000000000..07e8bfa0c3 --- /dev/null +++ b/txscript/data/taproot-ref/29186f53cff8c33b62ccd1cec92b4c6b02c8c2c8 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd50000000053f403cadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8c0000000080e6db55bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b010000007bfc680003fe5216010000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc79aa1c358", "prevouts": ["f266720000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "bdf22300000000002251203d5ffb7cd06f5c84b56ec9f73ff7cc3a22b38565d229330748f260d30800c008", "acc68100000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["5dda6d72098986d04518a24d2521425ba6d77b741f2dc69adc71135d06cc897697b9b998281b4aeb839e0b3bda61f16f4b4c505b81706352bfcf18ea801720f301", "d4705b44acd3ec855c255a6dea384759d5063f3b2150dcf17db724df5cc6c9ccf15141f6e0a22c20c664f8ffdba93d8cf8d7770627985b510c66e9fa8c8deb3eea72d0c2e68e0ae503100e608310eeb77614bd31c2bb8390da18cd2eba1826c76ccf37918cda2d4beab01e20cc53dd18b7c5c206e7000a2501a84ef69dbfadd649ef0b0f51327f03f95df877a83b465d50f7c7770cd0aa2ae57d2d1c3323c10d812b8f4b251eb50757bfd05a1f6fbdd7afe6df7d159fa9b5e01e96f262be4e", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667032e69e21d42781246748391369dbfbe9c2f737a3aa9dd562e73f34721d9f90000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d5e180c56c0451524ee8a3ecc1896e768f754c20286ce8750e284a151907e0f0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff367c934a4e22854ce1859ec32a8b50a173f3d6bf46b91a4e515153e2740f32abd6cfa89ab6efc047f82cae49d2c7e996032853be69261c62e58dcb3c658578fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff814c28f1277924f496f70c6329e6fac80f720e95be11054f2510a4a0e768693e83d0eb0ae905db2b3320532e634fa29e4cb94c4e96928e7deef2f119e52df0a57f6c93a7ffdece33021c7cf7b3d765e1a46296764dc9ba04c599279cb672c479a9925177f77555e7c2464536907aa0652b5d6df5d5805f83e664fcbfa72aba2e31a87647ccae878b37dd674f479be3918775c0a8d0e7cff5e8e41ff5b753198d82594cdf62acb0b1c218457e155e8393989ec96832f8688a1ce662bd91ab362dd146f03dd1d4451010a28a928a5862d9891081ff8346d0be05e585bfa5838048ba9bc477dc9106d83ec59206cfed5e9d001dedc4689f82ab32943944509c6cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8385d325695f4e3dfcf4fd74b8e11ce36b58c36dfbda4f78bef707e7e6e0e55fe75eb3a08875f4fd6054ac3ea535866fe12d75d68f862b514e5b6562b23a066269bb6bd3e6d3a52d1c8e3e2bcb300f97d2d958553c34bf19db98fd0ca15b5717b6b24aabb1a6d761815d5a2aeecfd76e00b319e79a0c094cef081f9597096109e5ee9a49f7c4bd48672eaa3c559c197f42203c0c3f747ec67dcfbbb39a6d8b99964ab793c369c83bebbd6d9ab04fdc20eee4d5b564c2ae0bba8012a506ef0a7359659d7950fbbb61bd5b15b30b553b03295ce3b4802c9bb96c67be53661d1033e4baf755d6772763fb9f00f49b3eca6fed6a61db392a1cddebc28a3a29f183b5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4feef60d9a51c95da5f947be6b14a11753c50b6f77c9fde2091b1bf69e7c89499d68da6005d030d02de924b098b912ad8d4407e957916ab58085fa0f0d0bfeb8951440b49f3c0312875a0ed1424d9783139c27b389bce64d8a3fb48826e2facec7c7861ea5509d55dbd2a306764de3d574389ebbb8f3e3a19ec9b86e8101f24b8f8a8d7993ab1b2960566540f39a5e7bbcc8050a68a1ea4a040b0c4e3338a1aac3e8a55a88cf2022e5ec967e99b3491010878a865097750ecc03b9b368467a9cb4c3dd8e9c84081d062d9a493ebde728b0ac140b9fccb94c86ec4ba4332f2eb02198aa9806157c25250e42ff5d040a6d4f93bbbec7b3c533e20f11c6371e4c2a1f64f518b1b16f67fc9af158746931699464c7b709b3f73e234e08a9dd7e782e91c2a1f51d6419311604a1b9af882f49a3e8dd7fcf7e2e88012a16afb55252145ac98b6c2ac10b0bc5f7aaa9934ddfc8ae746072955b5002ae01ddd5f27234c1bf3eb2e5e40ef2a0e2adfd9017cf0a0fad99e659c388d03a9f190db9ae00d51a1857dc312bba1d96a12c87e389ff1d540dea0ddf9f6d2c084c61f1c6411227f18bc930a253a4738929c6fda8d38bcc04911604a72857b6546104eeed291de3f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2339a9818586aeec15c1a33bca4fb74aa5070ce4d351acd4558314783398588623ab4d91c02012cfd3d16762d052e3bea25e0cc4afc61fa618dd7cfee3ef7f900000000000000000000000000000000000000000000000000000000000000007a2932450e8563f21a614cde78869ae4cd0c6c11ad100954ae5d68f257e8b3b2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff29d8f8674248f31ed7eb0e93b8e631d9885381e2eadb6ce29220939193b75c0988d3775f3bba68dbea3679f79f8ef5fc82934acb8388249daa7b82818290f7c00000000000000000000000000000000000000000000000000000000000000000835024320f109a04b39cabc114a7a14246a4335cf860393ca76de3de8cb2cc21056ed338d9bd88ccf476c043068bb7b27c2ee4048ce332a2ee2e697a706c199322ed959329c9e61e24e6adc1397e7f8616eab4013de5770430e05f7955c4b311ec03396403dfbb50cd13942b9a633bb11eeaeed80a65541dd3027f2c096f7b367029d052419f5ea265a8bf7f0ea7065e38016694cd20167eb6c0ae40bf29d3f924b0cdb8ac8dd8b4bf7f7cb3db25c2070bb177dc59eb684faca6f13d48dba1c6"]}, "failure": {"scriptSig": "", "witness": ["5dda6d72098986d04518a24d2521425ba6d77b741f2dc69adc71135d06cc897697b9b998281b4aeb839e0b3bda61f16f4b4c505b81706352bfcf18ea801720f301", "56920577caf00f768afcb45739f46879113eee1f0a6f3e7844dd095da5a9cc28ee594e99904294de13fe35c3da526aec2e214127254baa70de8ec484d38bd9310353b90db40cb2f5523616acaeb81608c86c2e5124973bfc2f5d874fca2f205bbd5e6b56262f469cbd0d649c7db5480c26d62e4283c4b69cda3d13e0a6682e27a41b76876805c3e57480c13c2e99b5bedcbdc14650ebde1310b871da3f71a2da75a7a276ee372826f949916dcdf5e507ead814255ad09bb648b2566951cc", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667032e69e21d42781246748391369dbfbe9c2f737a3aa9dd562e73f34721d9f90000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d5e180c56c0451524ee8a3ecc1896e768f754c20286ce8750e284a151907e0f0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff367c934a4e22854ce1859ec32a8b50a173f3d6bf46b91a4e515153e2740f32abd6cfa89ab6efc047f82cae49d2c7e996032853be69261c62e58dcb3c658578fbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff814c28f1277924f496f70c6329e6fac80f720e95be11054f2510a4a0e768693e83d0eb0ae905db2b3320532e634fa29e4cb94c4e96928e7deef2f119e52df0a57f6c93a7ffdece33021c7cf7b3d765e1a46296764dc9ba04c599279cb672c479a9925177f77555e7c2464536907aa0652b5d6df5d5805f83e664fcbfa72aba2e31a87647ccae878b37dd674f479be3918775c0a8d0e7cff5e8e41ff5b753198d82594cdf62acb0b1c218457e155e8393989ec96832f8688a1ce662bd91ab362dd146f03dd1d4451010a28a928a5862d9891081ff8346d0be05e585bfa5838048ba9bc477dc9106d83ec59206cfed5e9d001dedc4689f82ab32943944509c6cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8385d325695f4e3dfcf4fd74b8e11ce36b58c36dfbda4f78bef707e7e6e0e55fe75eb3a08875f4fd6054ac3ea535866fe12d75d68f862b514e5b6562b23a066269bb6bd3e6d3a52d1c8e3e2bcb300f97d2d958553c34bf19db98fd0ca15b5717b6b24aabb1a6d761815d5a2aeecfd76e00b319e79a0c094cef081f9597096109e5ee9a49f7c4bd48672eaa3c559c197f42203c0c3f747ec67dcfbbb39a6d8b99964ab793c369c83bebbd6d9ab04fdc20eee4d5b564c2ae0bba8012a506ef0a7359659d7950fbbb61bd5b15b30b553b03295ce3b4802c9bb96c67be53661d1033e4baf755d6772763fb9f00f49b3eca6fed6a61db392a1cddebc28a3a29f183b5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4feef60d9a51c95da5f947be6b14a11753c50b6f77c9fde2091b1bf69e7c89499d68da6005d030d02de924b098b912ad8d4407e957916ab58085fa0f0d0bfeb8951440b49f3c0312875a0ed1424d9783139c27b389bce64d8a3fb48826e2facec7c7861ea5509d55dbd2a306764de3d574389ebbb8f3e3a19ec9b86e8101f24b8f8a8d7993ab1b2960566540f39a5e7bbcc8050a68a1ea4a040b0c4e3338a1aac3e8a55a88cf2022e5ec967e99b3491010878a865097750ecc03b9b368467a9cb4c3dd8e9c84081d062d9a493ebde728b0ac140b9fccb94c86ec4ba4332f2eb02198aa9806157c25250e42ff5d040a6d4f93bbbec7b3c533e20f11c6371e4c2a1f64f518b1b16f67fc9af158746931699464c7b709b3f73e234e08a9dd7e782e91c2a1f51d6419311604a1b9af882f49a3e8dd7fcf7e2e88012a16afb55252145ac98b6c2ac10b0bc5f7aaa9934ddfc8ae746072955b5002ae01ddd5f27234c1bf3eb2e5e40ef2a0e2adfd9017cf0a0fad99e659c388d03a9f190db9ae00d51a1857dc312bba1d96a12c87e389ff1d540dea0ddf9f6d2c084c61f1c6411227f18bc930a253a4738929c6fda8d38bcc04911604a72857b6546104eeed291de3f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2339a9818586aeec15c1a33bca4fb74aa5070ce4d351acd4558314783398588623ab4d91c02012cfd3d16762d052e3bea25e0cc4afc61fa618dd7cfee3ef7f900000000000000000000000000000000000000000000000000000000000000007a2932450e8563f21a614cde78869ae4cd0c6c11ad100954ae5d68f257e8b3b2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff29d8f8674248f31ed7eb0e93b8e631d9885381e2eadb6ce29220939193b75c0988d3775f3bba68dbea3679f79f8ef5fc82934acb8388249daa7b82818290f7c00000000000000000000000000000000000000000000000000000000000000000835024320f109a04b39cabc114a7a14246a4335cf860393ca76de3de8cb2cc21056ed338d9bd88ccf476c043068bb7b27c2ee4048ce332a2ee2e697a706c199322ed959329c9e61e24e6adc1397e7f8616eab4013de5770430e05f7955c4b311ec03396403dfbb50cd13942b9a633bb11eeaeed80a65541dd3027f2c096f7b367029d052419f5ea265a8bf7f0ea7065e38016694cd20167eb6c0ae40bf29d3f924b0cdb8ac8dd8b4bf7f7cb3db25c2070bb177dc59eb684faca6f13d48dba1c6"]}}, diff --git a/txscript/data/taproot-ref/29306f00a438f213a01ebd7a7b0d04ae25d239ad b/txscript/data/taproot-ref/29306f00a438f213a01ebd7a7b0d04ae25d239ad new file mode 100644 index 0000000000..f6ae4c2184 --- /dev/null +++ b/txscript/data/taproot-ref/29306f00a438f213a01ebd7a7b0d04ae25d239ad @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701f02000000c88992c38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c471000000002bee261f02805a46000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e745311638", "prevouts": ["43bd130000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247", "ae50340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_98", "final": true, "success": {"scriptSig": "", "witness": ["3567c39e4922965c877ce5437585a0ce586f4770215af4d36adeaba189e176f44ea5a7cf38a87191f77162d333e4ade4b1e9267c2a86383e03be70d105b8195a01"]}, "failure": {"scriptSig": "", "witness": ["6c885cd3c57f8434439fbd898a5883458c3cd7878d2f4ac4cc926e993f8af32b44fab4a8359649a55ed7656c35ee56ad23c9e923f34f7a6ce852c11488740de998"]}}, diff --git a/txscript/data/taproot-ref/297a3281b6d5be24c14d7ff51f2fbfe46ed86f1a b/txscript/data/taproot-ref/297a3281b6d5be24c14d7ff51f2fbfe46ed86f1a new file mode 100644 index 0000000000..8bd660aefb --- /dev/null +++ b/txscript/data/taproot-ref/297a3281b6d5be24c14d7ff51f2fbfe46ed86f1a @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d401000000e688dcea8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ff00000000123c9dc8046d667b000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac3fb5d441", "prevouts": ["915f410000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50", "defc3b0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["834c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bf852205919db101e7100c264881cf502d3d2e764ba6b83faae2c86d526b113f2b9d1447cbfb5d72d5da72ac5ad193469eaa6b44c038aa23e2a9d2dd480586adaf3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c18461976e62a50a1c995a04d8b83eea654c194a7ebc4bf0616751df5ce2576839b32d44b6ff86c799acdff23ced11a294722ef2b8af6951bf8429e3bda52b31af3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}}, diff --git a/txscript/data/taproot-ref/297a666c7fc982a83775114d7c6821fb42031e06 b/txscript/data/taproot-ref/297a666c7fc982a83775114d7c6821fb42031e06 new file mode 100644 index 0000000000..1175057818 --- /dev/null +++ b/txscript/data/taproot-ref/297a666c7fc982a83775114d7c6821fb42031e06 @@ -0,0 +1 @@ +{"tx": "dd0484290260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127004020000003a1f3dc18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b2010000009ee9318602534e47000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c9000000", "prevouts": ["e68d100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f4e6380000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["cb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652247e5dd926380ab694d48c4d41b564ea6c104d6001198f68608a68dc76789170b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720d6d723e038e6335a667e0268d00f4826306437ee84552cc7f8172181160444ef73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4f551d5f9df51039c21b920ecc011c032a9913b031d76462e802a27cbd0d0ed8dd6d723e038e6335a667e0268d00f4826306437ee84552cc7f8172181160444ef73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}}, diff --git a/txscript/data/taproot-ref/299581f978295f5b97afd9102abe9746f3633e76 b/txscript/data/taproot-ref/299581f978295f5b97afd9102abe9746f3633e76 new file mode 100644 index 0000000000..68ce7e99e3 --- /dev/null +++ b/txscript/data/taproot-ref/299581f978295f5b97afd9102abe9746f3633e76 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700f010000007bc29c6cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb900000000665aacda033f912f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e74a010000", "prevouts": ["0b3c100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0862220000000000225120e57fe1708102910b1e8fab470345c0402aba6cb96c683e4f102534396b5c1780"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936545c476ac6dd89960a95424e037fc45720028d28300f66c18e5d73f49140b067"]}, "failure": {"scriptSig": "", "witness": ["6a1a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/29cceb8deed87738d060e1bd5338ab0536f8d2a6 b/txscript/data/taproot-ref/29cceb8deed87738d060e1bd5338ab0536f8d2a6 new file mode 100644 index 0000000000..4e74847390 --- /dev/null +++ b/txscript/data/taproot-ref/29cceb8deed87738d060e1bd5338ab0536f8d2a6 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0a000000000dcc735dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaa0100000058f69bca01f683110000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7af77dd40", "prevouts": ["61a26c0000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e", "cdb27100000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "777d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936317c62222341529afe8f077c28135e4216d182041ddde4bb210fc7dce870fc693c7477a635aa10de5895d22b0b13d3a2307950c6447747564098b225c8ebc094ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457e2aee6c91b47bf7b7aff3c5d3800b2287c2f5852e09bca12781ffc191c1d4f04"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fafa584ded413e2880e88fe5cf9cb62118b35d382d99cebe394016833778f1470de2aee6c91b47bf7b7aff3c5d3800b2287c2f5852e09bca12781ffc191c1d4f04"]}}, diff --git a/txscript/data/taproot-ref/29ce41699e783cf1ab6b5b84bcc1f8da679ce8cd b/txscript/data/taproot-ref/29ce41699e783cf1ab6b5b84bcc1f8da679ce8cd new file mode 100644 index 0000000000..b596df54d9 --- /dev/null +++ b/txscript/data/taproot-ref/29ce41699e783cf1ab6b5b84bcc1f8da679ce8cd @@ -0,0 +1 @@ +{"tx": "0fe2948902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be6010000006a51eadd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c4000000007dccafb10437fd2d000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964bd1f750", "prevouts": ["e56f1e000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529", "981f110000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "f77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee1b135a17580d142a9191c3b85b2fd298f3e09062f6f11151feab86e1334277f9411b885fbcd56b4d2cd2e695cafde2fa2de7097172cb34b20e1fb870aea9a6a"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93614bc388ca930cddc1c81a27ee7343eb0c7b6fd8e7416418176eb400a30a42e0c75fbdc6cf2e777e050e79c533e418db275d42efba7f8dbffba71190cfdc033660f5943df1a7722c938328966c7e5ac747f85bf050d43cd9195f6df88860ae066"]}}, diff --git a/txscript/data/taproot-ref/29d289d23bf6e34dbfac501041222a1978cc95d2 b/txscript/data/taproot-ref/29d289d23bf6e34dbfac501041222a1978cc95d2 new file mode 100644 index 0000000000..8cc5ec0c62 --- /dev/null +++ b/txscript/data/taproot-ref/29d289d23bf6e34dbfac501041222a1978cc95d2 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdd01000000023cc89c033c5726000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a64636e056", "prevouts": ["f79d280000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b8d8025076b24c8a40f76c002001c237b48dcd5ca95a82c0e5e41f0b66f8d235805006cc51063e7185e527fb59c761b5074d10ceb82e6a0b7e047e6dfb68ed645d4f3cf5225bc2e73bca160ca9ad46c357c6d2e1ae176a3211e20e5b1ebd28f9886e04e2e32fa7ad4455724eeab1facbc4974330c42667012f8319582ec02529573cb21a631ca15bb4e9a11f0b33c4fac3f5c23956ccf4c137f9ab5ffb9c788bc2584230d40c4440e5afaa58dc239280e60c7fff9f1e0e04362675d60552e9fd6171c0119c067a199095fa5ffce19230fbfd4bc55a74e9bf9bc95fe7811bcbc5baee5ebef1a5a189e407f78eda078eb3c14e4eefcdb328ff92c0594f07c2be48fc17d7ec39d2654d0e2b7e05ab9abdc96c7cdc9024fc06253d2049207bdd1b75933b1538b7c3d8785dc862cc0e283b57cde1ea32c67de21488473295624630fb3a68ad2053e7ae8e85b08513b274ed188fe50aeb9ad7327ba8d0f053ed46817f1f9547718020eef34d55f693c49717af4420d33dc7b0405e06ecd96c307a0ed6560f14673495fc50c6819ebd0d0663f4e4d84c96aa5a4332bcfedf5010c1705d19d26532e4b5fd8adc36d22acd1b73c0ec3d909abb8b2271349cc48c1fc370d3fb18a660fdb680e4421bcc846aeab0213ee6a3b124a047f1a214390493644e6fe9aa7e1d465407604bed45d57a9165f155cf48144eef19f36baa291368ad974e9702b1e961f52bbc8775bf", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb448ad690b4db681210d49373d4012b83591ebe1050d9c81702caad07f4cd5bb9faa736b6bec5c04b20c5b38998d4f897a7594adad2cf377758bae1284900c20e3219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}, "failure": {"scriptSig": "", "witness": ["4d09020e105272e2585e738c768fc20f5d968658bfc397956b671146f4b7795091d902cdc73036841d91a7cf5e5873c97979a7604ca82151d8fc6926a1a7a195f0f3abb3b2b673e9bb7b1c27205eb5a62c7ff9f3744e015650d5d1573c7f521675eb4cb11118a04049e2bf69f5ecf5177f67c3260ace9d3caa675e79da97e0afb04a43e777c245d6fda66c2c63651be6f6757fa8c5dd9441c0ad8db19122f1a0541bb96efa637dad6a22226131a026fa4d6e3b3658fc77f3fc8c3bbfa22940d7e17397e1b0a69fdef34d6b2c0e6e44ab56212b0aa7a5c0263655e43dd86951fea2a604af949af140737a269420350c88075b01bb8fd2c28304fa7c6c37676e60fb89b050f25a7527982eef96665354af9a29733e62a7f756e962e888241f2f63a2de5b04d387dc8a75437b4afb6db301508836125156078ce820574769c5145be3b6161ab298bccddb039f032fba6d7b1137567645870af19e57ead4acf8b9845deb241e61fbad9a3b315415b5e59aecefa9ac0a25a33f2010a607b9d62d5982bacec40d7bfb7033b2943478ce7df0d10f8c57f2b751750d85fa2650ced72cb501c23ef3e3f6adc2180541621111ee26010aa9156c841a3cd9126612663d1cfe2f476414940aca7659c332768f7bb2e92f093659532cbaf81fcc449fdb013abeb368745c23e262a7d2e99c057b5eccc8ba5cb0eae27005fc84a41b3af3a5c0988977e1a11b0360e9aeed1bb37561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082285ab48eb468144e5e6aa7ce6d4aa75a792c11a68b383289399495d27c15055ecc596949c599e703b9191d3ba022749fca5ec33c3492eb5532759cd445d2634b82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}}, diff --git a/txscript/data/taproot-ref/29dc54df002663eb3874c3fb7d3952e70b1d1779 b/txscript/data/taproot-ref/29dc54df002663eb3874c3fb7d3952e70b1d1779 new file mode 100644 index 0000000000..42b46b7c1f --- /dev/null +++ b/txscript/data/taproot-ref/29dc54df002663eb3874c3fb7d3952e70b1d1779 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c100000000dd110ca0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caf00000000071f80f3030b996000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac9d000000", "prevouts": ["b4170f000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "b5bd530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d511915e430f0db2345814ef782ce895d8c23952d8feef260d8eb90daec0803de3eef05bece11fc4259c24dede9b1787a65bcee91937b36a28d108e88384141e6c4419704ddfd13dc63b1b4156372563d65f148a89e112fdd9cbf47f8afee5da0a9"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4baf3800ace8e6c95c7e7a9d035d879049832cd6be429795a36cd3109eecab56cf0292c5c10d160f8e0745cc9e7b1222beed517475d04a852f0f3c02abb361f19b5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}}, diff --git a/txscript/data/taproot-ref/29dd1cab8fbe87bf2eba3c671a6054c32e47ee9f b/txscript/data/taproot-ref/29dd1cab8fbe87bf2eba3c671a6054c32e47ee9f new file mode 100644 index 0000000000..a6d0f7c78f --- /dev/null +++ b/txscript/data/taproot-ref/29dd1cab8fbe87bf2eba3c671a6054c32e47ee9f @@ -0,0 +1 @@ +{"tx": "a804d40e02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b96010000007c2543a7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfb00000000e7fe5fb603e9bb46000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79609000000", "prevouts": ["332f26000000000017a9144370350f30aa8f875e3d2a13be81f25f19bf1a6387", "6b2623000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "027d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8c6a1fb55f16de67c2a92ad96c93aeea32aba2f93d3355ba34bd608160e8b6bc30e32049d91f42cbcb04955cd98e985d287b85d3c77c1154d8406ae5e2d81b7b1"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e27fd3105da1a30ac5d519a74d6ce1b9e57e0f98575d55e76aa178b4a6feecbec6a1fb55f16de67c2a92ad96c93aeea32aba2f93d3355ba34bd608160e8b6bc30e32049d91f42cbcb04955cd98e985d287b85d3c77c1154d8406ae5e2d81b7b1"]}}, diff --git a/txscript/data/taproot-ref/29ec9ea0cab2025b952a31c864a85546c8a8f032 b/txscript/data/taproot-ref/29ec9ea0cab2025b952a31c864a85546c8a8f032 new file mode 100644 index 0000000000..2ee60e2e69 --- /dev/null +++ b/txscript/data/taproot-ref/29ec9ea0cab2025b952a31c864a85546c8a8f032 @@ -0,0 +1 @@ +{"tx": "82be370701dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7100000000e2dd84d901c0404a000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4877c000000", "prevouts": ["190c530000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c65d6d28abe4427a28718cc9defbf81c26729a2e7a56ee27b8dc889a3e93ef624f81831abc7030d30d94d76608ced7887e45146dfb5c6f498f7413d0801b8ec7370771bc09cab9990a137eb2bb36c383505d4d9622e2608e50044675509ef423478c66cad98a0e432fbf5ebaf8edad64c7e69aef4b0ecb2d91224350ecd4ca2b12fa4f30cd813b1727916698f3a36b99f57249def877c8eb26ffaa2e89ef37ba2d5eae3d4087861a32c2301fcc6526a832631ce74afcb19abe25323e02ce5bcf918938c9260f6cc78f08ccfda91b4edae9e87478fa98959668c188503e739c9250e4fe01f646976a21a8bdeb603de9327a271009c25302ec16a9075b01fb10e3c14e7f9e84c21f0e572d8c0baf5de5badfc858b8d4031a2ed56d0e574b2ae632fa6db275d93e24f7ea1bfc3fd107842c07aeb28e3a11f378b0f058396df45c6d195813457aeaec14ec5f4c34324291fdd81c184c7fa09b70ec6032af1d30edfb986b15f46ba49e847ef142ec8f050c2602e4a5399c960ee556315266d4e3af38da742f2c000c141291d643c3b0c48fe4641ff8ade4a0e89a1ef3388de0d26bbf9e1857b21a56ba99a394f1a8a2f2193511174ba1881308dd9fc7cada8576072c967d068357203d288819ed68c2385cd9f3e83e32c7bdf3a3eb1d1ed4374b6902b39c851708e748952e6040f6f797375ac5df8f0429223f2716feead55539fd605b07dfdf619cd4b11b75", "eb7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f6502ed723c13c5ddcf31911de71be6f76e583532ccf009c50f97b41c4fddfbb84ce21fa65bd655e7fa8dd3695f51b098b96b5173f87464f2936878bf520f49fc2ce937a5de573933a673baa3adefc0607b7a8b345eb0a9388ff089ef522bdd2"]}, "failure": {"scriptSig": "", "witness": ["4d090299e6ec5cb8d4658f0cf258626bd3d34f4f03b0abbdcdc7114723e8143cb357be842a82f438db98212eee111068e7ac218cac2006e89d62c921b70d38f5a6c5a84d288723d59e4fb8a9e7761d40a6f381739d5b2db8cb1179eb492c2823da5e6712d85632f20d262a17dd659182b9cbbe44c1955da4988c678837160fb8f12f5e341acacd54c50ce56bbea55f20904ec6b672862a854cf6197e8635c7502fe8845708ea12c2d69486fc75d74c6b11898557737115c73f82ebaeda00d243bc745e092c42bcc8fca35a81178923732e7f0a5a21a593f3cc5d376148d143bba4d4938592e1927e279fcb6f6ee2676e668f2f33557976f2438ef61f5b826606519377503e9f1ce443ae1fa81026017c6711d9832256587148be270d272918533f06e0dfdbf98eb7c93d8722db3624222412d424f4635f7ea35663bb7926a17d303b78da410c0c39da5b7e069de4be5d776b5463306373a94dfd8dd027623dbee561e0e34e3d300387c2ff95cddda6478e14ec65b10f3c87452bf7361245a1987203ef362a0ee362e7b1127bc44fa5f8921cd034d4db2f4b1394df6875536f7ebfd73e6e17174703c039eec3a68e93ec983dd1a9a86eca4343153c1d4cdb18e858015c3109731f21970526e1a50ce941409f7ff6120bb1fbe60d12aea1707e5b1bacb17cd17a3259611e4149ecea670cc95b65c000c67d602c808491998a35743bd6746d3404f6a2e1251dd975", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823f13c9f2c0ba7c3724f3080ca99cfd230291165bf004db5bbadb2403d0b759af84ce21fa65bd655e7fa8dd3695f51b098b96b5173f87464f2936878bf520f49fc2ce937a5de573933a673baa3adefc0607b7a8b345eb0a9388ff089ef522bdd2"]}}, diff --git a/txscript/data/taproot-ref/29ef22549cd23bb217da411a3ca72d83c71150d6 b/txscript/data/taproot-ref/29ef22549cd23bb217da411a3ca72d83c71150d6 new file mode 100644 index 0000000000..7a18f810d9 --- /dev/null +++ b/txscript/data/taproot-ref/29ef22549cd23bb217da411a3ca72d83c71150d6 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d900000000dd8001afdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c19000000007ff930cf04916466000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8749030000", "prevouts": ["a68d110000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "567c56000000000022512077fcdfa5b83233990258cd0e78144655048956ba28606e7ed979bb07d82944e6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "367d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a25034f4670dba2bfd8b532fe5e2c4399b1757245b955e89574c41111a3f13a78448a7537869648343bbbdc00eb4ac0785a5f2aec0111e81b0d25ebde82a92a"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93618278c07a795a465b0e01ec560e597d9dfa9576d66260ea15112d4b854280992e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a25034f4670dba2bfd8b532fe5e2c4399b1757245b955e89574c41111a3f13a78448a7537869648343bbbdc00eb4ac0785a5f2aec0111e81b0d25ebde82a92a"]}}, diff --git a/txscript/data/taproot-ref/29f6acfc391f9db2fecb96ea0a708da396ed202e b/txscript/data/taproot-ref/29f6acfc391f9db2fecb96ea0a708da396ed202e new file mode 100644 index 0000000000..233061cf01 --- /dev/null +++ b/txscript/data/taproot-ref/29f6acfc391f9db2fecb96ea0a708da396ed202e @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0302000000e24818d4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9000000000f9f348ce017c48060000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961c030000", "prevouts": ["dec2220000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9", "964c5600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93626c391d5e47230d4b4e419da58037ce9505b07d9e5ed3742aee4172be09b65ae536798c57c197a746bb2ed7f28bea5bf32719d74447f5bf93d90a00b781807a2845c4b1f0ef9796b099f7837236ca3239de7da07050a4e4f568f49f6a65718f105f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d1b360dbc2a68556ffe995fa73d9491f5c7d1d4795c1bc7f06a4bb01cde3d3510ec8a0a1d660d587d93edd278a1416bd3a7fb5c67f78681973183382c988e9bb422e3784e386a40d51dfdc8b2696050c6780884f0aa6a0f3f5d0b1b514784d82ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}}, diff --git a/txscript/data/taproot-ref/2a46178ff8d5794433a794e9fe86b9b5fc268cc7 b/txscript/data/taproot-ref/2a46178ff8d5794433a794e9fe86b9b5fc268cc7 new file mode 100644 index 0000000000..f70fa1228e --- /dev/null +++ b/txscript/data/taproot-ref/2a46178ff8d5794433a794e9fe86b9b5fc268cc7 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cba0000000025e7d69ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5201000000d3af49b860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701202000000fc825ac201084a89000000000017a914719f78084af863e000acd618ba76df979722368987398c0a2f", "prevouts": ["33da480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "65a5590000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "064711000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09028c268e4ecec76aa2f59fd94a68acfe2af67776f00ab61b86e7926b8144e5460e352e8be1a3e826c1de3684dde036bb7fe3ee1d1abed079fa22ad91325d6d250c4071cbbb929bb77ca91eaf03eca18757f412a11ca98c105429b92b01fa2edbf45df934cc0c392ab33e5de08a07d445b2960976e3a612969189fa73381c74b61595c73fdd90a17bbd5d3ad2dfa07331dd78d654069faee70b8f3d0027dd4bda0d25036fa6bd5a31714afc0b876a1484fc0ac1d172488b41385d371429232fd1ca521709e8798d2c8f4632fc0d0991c6601844fa80fdeb0f863d6c8d9e23acea27e4f6e79b1544860e70a1ab109defe1e5d885efba13babf997cfdbbba70e9b43cfd08bb67231cf0f73194c8956eb4836c70499e8f1e1414fbebdd36991ddab518b704a5323fb24bd8cb5dede640dfb43823bfc370ffdc8f8bf9015213367aaf83febc6255cfd65db07e9ae40a72c52cf098a6e39210868f7f112753e19ac1fbf7ae587e08feacee253b364bd8597808e61fdfc766b043a7e5f2660e450d86b6881052c2d6b715def1b3878c16593a3c15f394a666ee03d0f523dd35b8d22d2b882eca659cb3c0a4c1aae1bb05e5963263e1f8431a80722ab1b5a578fabb97d5a4e0b2acc386e1e0ce43bcd17e4027df76691ea1672d466792ec4c0b69529a066b0fa276db15c6f54c2b2bb080efe801aa96151ea9f70473b6b921d902a8ffc8cc73c320a72e2575d93775ec", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367c63ad976486975ed2446585f6ed9ba3fac098da722e4eeebc45988370da4d7fb68406090ec9503da6e41d61411400226504a16a75c985e068fea4ead469507b3b719bf4b6df334f4ad3966afd516fb2a8d294cb4fface4e4609ab1c9f988c5a"]}, "failure": {"scriptSig": "", "witness": ["4d0902d69785071bec72fafe99f102795213c00b384192ae090803f8625c94283c751d50e410062e3117ae2a30ea04b068e7a9d50fb1654db4f7e36a29ee771593efc943b1505a983a6911158499b20c80f50b23983cb242319cf04df8ef13675414c5b15d36795a77d8092b2456ed9ea851470470d8e6dc233b0d7cbe947e92c0713de76718482c411885db43fce7d5ea387f08a3b2f2374af87ee9f49aa887b8bd4e8ea23fcac6638de92fb44c0ed4028e2603390f96262272b8b30d9e0de8a06c111f4e5b5ccb7737c28de9ce83c990b0bae5f8febc8dcaaa664cf3f697c7d912d80b67704f66298cc9cad54c6de90bcebeec5857385f3635af969080018e4fe81c5e47a880ba6e8ba152f9cda6943504eb5df2477038a99165eff24f84cde01173de56907890aab88f8f2a68c3836362f7a252961cabcd26e0096e9d8285f030828eea7ce529e58b6c218a48af9781d86beacba5f9200384e6b50283459c52853b6d1c76986d5294d354bc1379f9a31668ec33d9451a3e2c918e8706bc694ed0df8a419b1ffce6ce3bdb9cb11c537ab37697b1f6edb3cc6512a11839fffb283210c1e6b7f154a60c8b82a31f855ec217b79b96543a47b3d07ee439c2a1c8e3f358db506434a6a8b53b76b7f2e089f140d0ef49f0bec3214ef2f90151a52675127f263af3271e8b42983ef9731e5b6e5a99bf38be069813665bfaa75355f6bf6392b387aa9af1f6223ec27561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dab3c70c06b6d40db1cad4929dc14312cad177937e3c271bc65c4be8c12a381eafd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173adddfc46016955cd26bcdfd077adbba0d60eefd6e0317def1b858595de21efb103b719bf4b6df334f4ad3966afd516fb2a8d294cb4fface4e4609ab1c9f988c5a"]}}, diff --git a/txscript/data/taproot-ref/2a479685fd7da722bb6722ebc37d68cccb881ee6 b/txscript/data/taproot-ref/2a479685fd7da722bb6722ebc37d68cccb881ee6 new file mode 100644 index 0000000000..c8451400b8 --- /dev/null +++ b/txscript/data/taproot-ref/2a479685fd7da722bb6722ebc37d68cccb881ee6 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd401000000c607a19edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc70000000014b61f7a0255067f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc783000000", "prevouts": ["a10d260000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "1c935b00000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "967d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fab066835f4c858657284bc4f27395efb05761f76f20d1739098d7bca44617346d654e31a1d81b19a8c2670362b3a1330b2f2d66c8db1c8314023a61983d2ff610"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea99249230f034edd8755346ac09fca5c6ef71b313e66a1d1ca3f34bf2000d9789b1afbd82754ccbdb229e33ad6472305abc54dae2fa9ac3a68b58b93ca8c8390ad15d5ff3e747c4643a2e7779e2cae74c1db700bc0de7d47935e7ffa6ea968f"]}}, diff --git a/txscript/data/taproot-ref/2a4e458a761d418129aa4d22bbbd076927fcef77 b/txscript/data/taproot-ref/2a4e458a761d418129aa4d22bbbd076927fcef77 new file mode 100644 index 0000000000..675eeb107f --- /dev/null +++ b/txscript/data/taproot-ref/2a4e458a761d418129aa4d22bbbd076927fcef77 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703f0000000024d521f4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbc01000000e8ed3cd4048e26370000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac76000000", "prevouts": ["ec7f110000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "7866270000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936442ef3e08d4cc76e1b58466903dde6bc7d9143fa5154c6795334e9e845b214803f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08233479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a4bb2c7d85af23cd06361a8d9967d47c0827d7b479cd52e2216fb2d12a2ff38bc"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a680f8e17236a8fbc1196317399c346aeca722ffefcaac5ef62e17ac4625d25b4bb2c7d85af23cd06361a8d9967d47c0827d7b479cd52e2216fb2d12a2ff38bc"]}}, diff --git a/txscript/data/taproot-ref/2a4e61567a20b2e90af1a0fb476b1ba0154b0a8c b/txscript/data/taproot-ref/2a4e61567a20b2e90af1a0fb476b1ba0154b0a8c new file mode 100644 index 0000000000..c39491fc74 --- /dev/null +++ b/txscript/data/taproot-ref/2a4e61567a20b2e90af1a0fb476b1ba0154b0a8c @@ -0,0 +1 @@ +{"tx": "1a1da20f038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c496010000003477079360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127029010000000b0db5c160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700e010000000bfac8b303bf195b000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487198ac73f", "prevouts": ["ed513c00000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "fd2d11000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9", "5ac90f000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362cc5df8a4115da779f8a758b20ada553e9e091a2311498f2aa3552034f30084e276a8166e5256dc9010e53101dfdb6dbd4fafdb1e785ffcbffe7e4bfe923fbf99aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d3d1c8f95326a5f9176c86e1c30427cdf7afee7eae03ceb2fdd83531b682283cf61f73219d91856056394a010eb6c8ee7f13c9683181be224f0fcf47ad20d61b9aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}}, diff --git a/txscript/data/taproot-ref/2a7da9157e1527a2190bce26d0a1303d7f239f9f b/txscript/data/taproot-ref/2a7da9157e1527a2190bce26d0a1303d7f239f9f new file mode 100644 index 0000000000..0e1076cc3b --- /dev/null +++ b/txscript/data/taproot-ref/2a7da9157e1527a2190bce26d0a1303d7f239f9f @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdd0000000084353b078bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a0000000004495027302e6bfa3000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e791e25a5a", "prevouts": ["3415660000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "d8bb3f00000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "eb7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d30f73147a154a3628d0970c0221a8932217afeee5ae5f898a11b906e2468131e58e476735d98d5a1185fd7ff42bb7b31cec58182079010d151d415fc7d6c3e4c2ce937a5de573933a673baa3adefc0607b7a8b345eb0a9388ff089ef522bdd2"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e2b3f5d542005946f2ec6051f133431d1ec5375b61ea1504919b9de7f1f58f14cd47700b8e47119238508fabe2c12c2c2868bd36dd1a15df7cf7a783bdc7d4f633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a9e937f21fcad1bfe108fe60be9a324a720a35d98355df5fe53ca48d5593a6c6b"]}}, diff --git a/txscript/data/taproot-ref/2aa0596f17f2698bdfd51894a7dc1e1241cd3ae9 b/txscript/data/taproot-ref/2aa0596f17f2698bdfd51894a7dc1e1241cd3ae9 new file mode 100644 index 0000000000..da1a1f5ea0 --- /dev/null +++ b/txscript/data/taproot-ref/2aa0596f17f2698bdfd51894a7dc1e1241cd3ae9 @@ -0,0 +1 @@ +{"tx": "78a4f8c4018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b7000000009a731cbd039e5f3a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487fb267745", "prevouts": ["b4f53c0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa5d6d6d3f2cd85347736e7cd11e639ac781ae37e103c2c2842f248c73b61e825b0a9249c0485c0b349be2068ea39eda6d50f7b6c474a6d5eb714296c91a9f24b9"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bb23dba8f127cc5caa444c657f3417e5706f46d2cbe11427067fdee54552685ddaba019801d089772adec5c5b59e5bcfed03a63e4fac904ae7f3c905b717bc6fd7bec169038f6fbc2f311373c62d75738dee89ed934d1dccaea4579b1c053aa90a9249c0485c0b349be2068ea39eda6d50f7b6c474a6d5eb714296c91a9f24b9"]}}, diff --git a/txscript/data/taproot-ref/2aa48f72c81f73267919baef97d2c186ffc36882 b/txscript/data/taproot-ref/2aa48f72c81f73267919baef97d2c186ffc36882 new file mode 100644 index 0000000000..c817c695cf --- /dev/null +++ b/txscript/data/taproot-ref/2aa48f72c81f73267919baef97d2c186ffc36882 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701c0200000078a4abf760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e80100000013f5b7250110821b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac9f000000", "prevouts": ["51e6120000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "458a110000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["cd4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5148aa6a6dbcb4c7060082480e3e536b464146150e8b2e96d2b5eabf2aaf1fe24e9f4d7ab890a2001a7be6cb25cf630fcd24657943ff80a7c5a11988ecbf9e80e4620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}, "failure": {"scriptSig": "", "witness": ["4c52cd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93683f2a03e8c381f92f3124ed7c392785374a020be92a8046eb2be30094f713c068fd238d2decf6f7142c55252dfef824eea080278838d8f4f1f0f617cfe47b5d91029910a453e765cd82c29c3b576a90579a453f3a941b6b6175fa922e9a13196"]}}, diff --git a/txscript/data/taproot-ref/2aa72eaeb2dee91742e3412f9e1ec464ecc22161 b/txscript/data/taproot-ref/2aa72eaeb2dee91742e3412f9e1ec464ecc22161 new file mode 100644 index 0000000000..ccc1614482 --- /dev/null +++ b/txscript/data/taproot-ref/2aa72eaeb2dee91742e3412f9e1ec464ecc22161 @@ -0,0 +1 @@ +{"tx": "896c810602bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfee01000000fadb3ee3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfee00000000d2cc268d0308cbd900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df979722368987e4000000", "prevouts": ["7dd76b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f3956f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath", "success": {"scriptSig": "", "witness": ["1fded07e14633319b5e5d364a93e0d1d69618a0bc3e97963976ead7850c805c8e98a23b613814cad05b5405372152115490f3de9a5ae05045b4bd15a8f95266b02", "50cdc53a7cb9cd5ee51d6149aecf9513ff5e0ff90b593e41157ee379098b30950d6383f4062f0c953e39bda615242fd08cfe63e1d438b500933bf1f372f8c65613b2d5114825223618514f73aca0f1e0771ae72e00606e445891296845e1dfe150e541ad046eaf767190486fa4b72a399279d95827284367003507c9d75fc300289ac1f466a89d36755e1600e9f1331399a86e3d6614880bc5639e5c5752f982fe8c321f227fe925a9a03dfc15769c4b914ec30a565872e626afd7a688f04d2188aa718ad9cb9c9cfc68ef59d95f"]}, "failure": {"scriptSig": "", "witness": ["cae0502574ebeeba586e579f5ff580377e691cd75fec571595fbcb717e287961abed55f6b0c7837de54539d85ca391adfd315d4cec3b7d7d78d13ba6e8acd9ef03", "50940335d2bed26fbd5ad4cd2bb4582c647d766eed8bd1ac46942ac25feae77c8d59fd8552f74acc58d02bf139ffd091c977ea845e402a2da1f9e4282183afb49883c37ee77529e224c823cb6f04e16f085c302d16ec88556dd1311f768ceb00fc42f2406ee9d4252e4cdb3835ac88e84fa802fb74639fe01457d17cf4c9655f74b9bd1614010e34f8fe015aa768c73a3db3dda5cbe0dee792f2d25f0cccc7d7a2d08c9c1c8b2639a85d81abb4960393b06fe8570a029d9a2a97eccde684e094b74461cbb6abd5db5491d8ac878e7ee7301352517a6d016050c52a2f00aa37beaa"]}}, diff --git a/txscript/data/taproot-ref/2ab67ca0e8401c63810a011ea1b9b40ef8573922 b/txscript/data/taproot-ref/2ab67ca0e8401c63810a011ea1b9b40ef8573922 new file mode 100644 index 0000000000..6f368cdd67 --- /dev/null +++ b/txscript/data/taproot-ref/2ab67ca0e8401c63810a011ea1b9b40ef8573922 @@ -0,0 +1 @@ +{"tx": "65bd5fe701dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf50000000060d4819d03436a2600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac2ce15b2c", "prevouts": ["4c042800000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "d07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dae8e61e5a93854f939bc67e0ec3e122a7138bc48d6cec8581769a140f30e791a211c16676cbc388c1faf2d1545933d22071968ce5ea9e4d8ac4039e171efe917420b3503815f4c7b180839898c4c4aff0ab6ef4d8b082708dba105a321f7428"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fbb2c95f519f2e9e9c845032cdd61b2be56a03c746f0eb1686ad2cec90f6300d74714e58ef013156220aa32c916bb7c1f2fb2617e3ecaa27044ebfec042fafbaa211c16676cbc388c1faf2d1545933d22071968ce5ea9e4d8ac4039e171efe917420b3503815f4c7b180839898c4c4aff0ab6ef4d8b082708dba105a321f7428"]}}, diff --git a/txscript/data/taproot-ref/2ae84cabbb3a18b00167af69886696809a07a86a b/txscript/data/taproot-ref/2ae84cabbb3a18b00167af69886696809a07a86a new file mode 100644 index 0000000000..94d27922a3 --- /dev/null +++ b/txscript/data/taproot-ref/2ae84cabbb3a18b00167af69886696809a07a86a @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702d00000000d650368ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8701000000b6f15db004cee659000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7efa05528", "prevouts": ["f62210000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "f6ee4b000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100f2e79a51fe00c6e6e503785aafc61c471d8b3f3710ce2822fc6b94dad79bb5f20220612a7f3657447392d93d9efd88c018f24279f3576e48a6d63825d2f80156217203434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "47304402205ec6f37e7965778b6138431b2edef66705a66cdf19c15dc917aa27fb8647c52302206fb657046bca821f61f76c1b0e05a68cce9aa61015ce60e471454091f26a4edc03434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/2aef8c06dd7c0aa09e6494194a3b812e4b7b2221 b/txscript/data/taproot-ref/2aef8c06dd7c0aa09e6494194a3b812e4b7b2221 new file mode 100644 index 0000000000..d85f5bad47 --- /dev/null +++ b/txscript/data/taproot-ref/2aef8c06dd7c0aa09e6494194a3b812e4b7b2221 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709d00000000dd342c8a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127014000000002d192c0760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d00100000015c28620013a9a03000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a600000000", "prevouts": ["6c730f0000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "a76f0e0000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76", "ef970e0000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "597d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee343ebd89880aabef0f18c5bef462b16920a32508939784a2317d7ebda32c7f1d0160c53d01d80ab4be204ae4e021ad6f56ad3990ac4b37baa4678d530d3ba4ecd61c62feef9509bc7b3762bc81079411fa6867ea4986820580c60fa1e8298e9"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369246ff60def872dcd9425d4b182836bb1c9ba5ca30c9708f02d69701de6960d646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faa393999847c63b69274661db27cd2e7bb4343911a06570db858c301dc754c7eb4be962498b383c32e8a84fa570ade752f3a2216469b10dbfd65078bd8e1b5998"]}}, diff --git a/txscript/data/taproot-ref/2b1075a4c09b4d3aa3be48cb1ce2571ab06a86a7 b/txscript/data/taproot-ref/2b1075a4c09b4d3aa3be48cb1ce2571ab06a86a7 new file mode 100644 index 0000000000..29ba3bec72 --- /dev/null +++ b/txscript/data/taproot-ref/2b1075a4c09b4d3aa3be48cb1ce2571ab06a86a7 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9c0000000073b9617bdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caa00000000e018eef0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf8000000009055c6ed02596ab6000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8cf5391e", "prevouts": ["56552100000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "682a4e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d136490000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_61", "final": true, "success": {"scriptSig": "", "witness": ["4c0a794abbe885190796db3840260cf4307843554ceecab68b87ff3376813c3ed29dfb4d8f3bbaa85ab8d257d0d203ff2340ed1b96a5935dfe667da753300b4b03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8193c1f31ca8063a843028b265a92d103a0bc55d579077a38dfa4c0f0cf1f578f8aa4ae59b252cb1ad77cb9fd776daefa1da376451b1ac32e0f9e42b0381767861", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2b168b93f7f916976567d85cf8e7ca0d6dbbf32e b/txscript/data/taproot-ref/2b168b93f7f916976567d85cf8e7ca0d6dbbf32e new file mode 100644 index 0000000000..d6df95f8b1 --- /dev/null +++ b/txscript/data/taproot-ref/2b168b93f7f916976567d85cf8e7ca0d6dbbf32e @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9000000000e38806fadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b27000000003c867fec04b7aea000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987b2879b25", "prevouts": ["4d15810000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "1f522100000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "8d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361cedd4ebc3a8843023445addfc64093d9c0a992ca250059238cd67fb8e6a944bb838daaa44e784827b3ea8aea20503468fe81f3acdd576e27ac09ae12d8ed7c28047789ecbd47ea83af97bdb87f8422a4707031714ddb05eaa38b24e158a7c35"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368e1f303af422a99e386a37c6ae9ac8e059bcc48394b77a776eee18f539e12c166c417b1d65e26db5cf9371b0ce7a9c3a110335bcae099de9d0155d4e514bb408a37683ca92a47492765ed69e840601310475c5f70013240e7a67747a5da918187472d664747fea006dedee35c74318028ad9a0ae37c154fe8226ccc2af402983"]}}, diff --git a/txscript/data/taproot-ref/2b229e9febea1749971fa08007b52b574b3046fb b/txscript/data/taproot-ref/2b229e9febea1749971fa08007b52b574b3046fb new file mode 100644 index 0000000000..d1840f1a19 --- /dev/null +++ b/txscript/data/taproot-ref/2b229e9febea1749971fa08007b52b574b3046fb @@ -0,0 +1 @@ +{"tx": "b354418b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2b01000000785719ab60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d801000000a030ebbf032d37300000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac35050000", "prevouts": ["1c06210000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "72e9100000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "bd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d6822c3ab459532077d5f4bfcf7544c522d220251729d5888eecbf9f185531198751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d50e634e19498d3396bfa452af2ece499faa564dc4b58fae514f4ede8dd179fb909e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900450cffa7efd13876b56a4fb6d16fe87f2b3bb25d39f5e6fb1dfb5ce04c0283c8690e634e19498d3396bfa452af2ece499faa564dc4b58fae514f4ede8dd179fb909e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}}, diff --git a/txscript/data/taproot-ref/2b4be33fed42ff17f8c6910629b0e2183d109eb9 b/txscript/data/taproot-ref/2b4be33fed42ff17f8c6910629b0e2183d109eb9 new file mode 100644 index 0000000000..4f3d1e8146 --- /dev/null +++ b/txscript/data/taproot-ref/2b4be33fed42ff17f8c6910629b0e2183d109eb9 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4280000000012c312408bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44b00000000ca4d1b9204be1e7100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc70b020000", "prevouts": ["7eca39000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "85e938000000000021551f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "cc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa45716b950e27a233a501a90011450809f321d0f7541cd1975fe5718ce8e53406ec1da8cea892037e805a477afbb54b1f5ec380954f076c0bcd3c4e3d4797a8d6"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eaf68f276ddb4c0fc7f0310a620a2f1f9fe6c0e4e29d0e280a559099e56625bc6391effb841e4c3f4ca92b599bc572f2bc6440711e20bdc5ba4fc353379105b198f95dbc4edc81931664a748b39a9978dd32dedaf5c850114f6bd2f5098c050fb"]}}, diff --git a/txscript/data/taproot-ref/2b609a197a87b5e2d1507c9acbaf2e2ab79ce53a b/txscript/data/taproot-ref/2b609a197a87b5e2d1507c9acbaf2e2ab79ce53a new file mode 100644 index 0000000000..d7284a7544 --- /dev/null +++ b/txscript/data/taproot-ref/2b609a197a87b5e2d1507c9acbaf2e2ab79ce53a @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1302000000a081f487dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0500000000e4f110110337dcab000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48777000000", "prevouts": ["c78166000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "7f1348000000000017a914971b3e5f9ac480bdcebf6ea71a9fc7de0ab164e287"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21541f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["b0fcfc88cfb5d6a8f5cdc0ea287840d7aff9a8756f3059ef4a2b2630a9ee69c301f524b2bfe20e440501edac14efe3fe089e837b1fa49d825701efc63522b590", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/2b9f2b2856d6b4e70d3b3d8e2d4ffcc6048847d9 b/txscript/data/taproot-ref/2b9f2b2856d6b4e70d3b3d8e2d4ffcc6048847d9 new file mode 100644 index 0000000000..26fc1b507d --- /dev/null +++ b/txscript/data/taproot-ref/2b9f2b2856d6b4e70d3b3d8e2d4ffcc6048847d9 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3200000000bfb51208dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf700000000ddd630b103d1d6aa00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796cb000000", "prevouts": ["b68d4f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ec455e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_4f", "final": true, "success": {"scriptSig": "", "witness": ["4d328c9fca94688e44f3ddc20a53f0782d432f5cf25486d998b1cd1777ee872169d8df25e6fd5c14c88ac72c6c6c4384aa0bee3bd35f74575a1dde6873a78db081"]}, "failure": {"scriptSig": "", "witness": ["22fc99a53b24832447d4a86902b8a2f9a1d3bb32f9b7a4adaa99b60efdd44c439d94e5f10eada4241a36f9194669561144e77084cb56b63f2eff81c6f07fdd3d4f"]}}, diff --git a/txscript/data/taproot-ref/2ba9b396adf10109648ab2f9856ca66b6fc5b688 b/txscript/data/taproot-ref/2ba9b396adf10109648ab2f9856ca66b6fc5b688 new file mode 100644 index 0000000000..73c1fafb9b --- /dev/null +++ b/txscript/data/taproot-ref/2ba9b396adf10109648ab2f9856ca66b6fc5b688 @@ -0,0 +1 @@ +{"tx": "40d9dd910260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cc0100000012faedd7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3e01000000bdce0ea40285d78d00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487a77b7a2b", "prevouts": ["2dc31200000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "55a47c0000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09029cb4a54efcccea4dafaff73436fc60ee5b4b7435fc92eace37e5c5d2ee723e22f662c2e24427d387f25549d5a36980f4f0ac3f27f8f2210c4cbd92b2a3c693999292caaf533ec3aaf0bc7aa832e780ac41ff1f43d04ccb54342f2db52d90376dedb1682ba31f74cf78d1cf9fad9cdf023e0ffa92e0686adfeb4db0dc1e7f636971b2c8118a9b9177c527ba2420defafc162961f80533f3f38adaca3ba60ee6c01709c86f494d3082e52d35d8e3018b78548654d946c8a300b0023e987133e797a631a95885cc9c1966311c5318bc004d36273bed5a357b25ffcd15a6df9f79ef7e7497fe1299e2dd62ea89215b08d627edb1b2761bd4a7067765924405ec97be826e95a22a6d5341ff4b35ff845743e464f1b0388f36ce1b6485a4a72d97dd6d40de394a2173d3d3cfb9dd880c28745a4bcf04f47325955464882da740f2b078cfdb5fae6cce7ed3e28ad13ce77a757b24abfcd6be705603db6ae6b5ceaba91eefb4e803147c4915e35d5a2b545491043a8a283e680b7ad0d99db1ccf96827b588d9a0101b2a4942f01dda330054b3501e056a6378680a74d250c382d7327993aee995c814fbabbb3ab551a00c1e920faba4d69b1db802c848f93bf97e767f5f0c9ec52dd16e94ceda4aeb8c9d14cb717ff421956750123fdbe84f0927adb67c2cb611d5f935cab2df633acb65efc48e137d807969785e903cc0e7cd395f9f84e33d0cf2068310cc5375f5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a4535f2a8b8103329caa1c08a23a51463ce03272f6b2653fcde7985b43626f34b6f5261b409d682c30910e7df322d9859114aeb60c7168b8885bdaa0165cc6510b3b87e8b9d8544644738d4851bae032b2bf37d3a4aa6541b936ff18c715610c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}, "failure": {"scriptSig": "", "witness": ["4d09027370d73d83f0ee286bcdf47d56a638fc2a96fee834f9f3930dcc5b67dcbb7abe7689a28ed15513d1b733a5ed1a38f7699db25858938a56a8abcda8b82a7072385ffeaea4df29e6ccf07fb82ccece359b4b2b9b56a819a977eb7885c60c9ebd03b954938195567f5abe2173261c40f69e31d2478fbcdb45c33df599636505b989d2b3806618b3f359f7d3ade30b78c5671098c4c6456dbf0701f97ac56d02d178d00b5302f7f426a2121c57733a8dc29f0e25bfa4461ea481ab71e85d8ca493d6646a4a752554ac802931e8a783a66e08c3b217d71a7ed95ce86a75b28c57e8fac0a50fa3c45940a472027657fea7e2d7737e8bba3a6d5a396d0f0063be766e3ce553d434787fd2ac1a3499b2387af32fe57830ffdde282f9c011cca75df0c16405e9bcdac75810eed9c2ff8f708196394957d584bac8668727c6608a553a0519aa643eed2d750c0c63df091ea36f92b6ff05ad4cf3a87e2f2daf3607b222e9fa190b67606b998c6d949a66b862a2b7c7c24c3344b52162527d5fc330d81901a70a788174db795f7e11894f3c4cb0c90519666698c1e431e8fbb95f55bcd468fd63e5a513ad4ed4b5147b1e4962aae44bf5703a17d39453596402efdedf3782280eabad201e66bceed466e1b5aaca1c5a72b2a1164f954858686f72b89520da5b83dbaf9184dfe8f3170cf8387d07afab8f279a8379a66b5eea8ed2b3c6bc13f3d326165f21939707207561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363e6166208d8c263b9a4a34aa528e018584d0355a882520645d2ec0d7435d6daaf46b3ac3e0eb552c07a1c6336d6a3e2704f93e82a6d5b4a7907113e7cf17bb16c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}}, diff --git a/txscript/data/taproot-ref/2baded8ac492d5bbd1dcece9f3d4a2f0458c778d b/txscript/data/taproot-ref/2baded8ac492d5bbd1dcece9f3d4a2f0458c778d new file mode 100644 index 0000000000..1028e0f060 --- /dev/null +++ b/txscript/data/taproot-ref/2baded8ac492d5bbd1dcece9f3d4a2f0458c778d @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf801000000af3ec0830480c1240000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac7df1c63e", "prevouts": ["ea9c27000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ba7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa8eec2374ba6ebc72bec4e80a7a4eb00aacc51a24e1026152998b46c213b611dafed5a24f2185242e3d6c1310740c566533f3942992fafe5f5be2785933680ed6"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d28ed9315b482680e4fce28b95ffa4f42337dfc620d9f0292f84b82b6bf4e2a98eec2374ba6ebc72bec4e80a7a4eb00aacc51a24e1026152998b46c213b611dafed5a24f2185242e3d6c1310740c566533f3942992fafe5f5be2785933680ed6"]}}, diff --git a/txscript/data/taproot-ref/2bde7ad09804a986048db6aa7983bf552f327e9d b/txscript/data/taproot-ref/2bde7ad09804a986048db6aa7983bf552f327e9d new file mode 100644 index 0000000000..a48387adeb --- /dev/null +++ b/txscript/data/taproot-ref/2bde7ad09804a986048db6aa7983bf552f327e9d @@ -0,0 +1 @@ +{"tx": "90a986b40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127057010000006a8f8b938bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e400000000e9d5c1d403674e480000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7e6010000", "prevouts": ["90c70e000000000017a914aa4a4e70b11f4eec4760f77206dc93b02350fcff87", "88c33b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1656142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["57e53e386b4787443e31509bfee6c0b1bb2cdecda0239fc8d71217960b529cb82c40e0e35928e60c70c32e01eb2177e27f526e4e86f94bffea45ea362be4c589"]}}, diff --git a/txscript/data/taproot-ref/2be1d596003c42e91c2a03626c93ce8259dc64ad b/txscript/data/taproot-ref/2be1d596003c42e91c2a03626c93ce8259dc64ad new file mode 100644 index 0000000000..ef15331e03 --- /dev/null +++ b/txscript/data/taproot-ref/2be1d596003c42e91c2a03626c93ce8259dc64ad @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b050000000039ccbcc40458951f0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d9030000", "prevouts": ["a854210000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/bitflipmerkle", "final": true, "success": {"scriptSig": "", "witness": ["983e46c7721e340f16f66741f7f5b66ac0ff2e0a1a718853752a0be0a9ec8418b77190f9661c12602673bb39ed0efe1b2647f1d67218a87164b3d360b67f1711", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}, "failure": {"scriptSig": "", "witness": ["983e46c7721e340f16f66741f7f5b66ac0ff2e0a1a718853752a0be0a9ec8418b77190f9661c12602673bb39ed0efe1b2647f1d67218a87164b3d360b67f1711", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddfffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}}, diff --git a/txscript/data/taproot-ref/2bed09f85647ccc7b26bbdedb9cbf18167240799 b/txscript/data/taproot-ref/2bed09f85647ccc7b26bbdedb9cbf18167240799 new file mode 100644 index 0000000000..e183e25b46 --- /dev/null +++ b/txscript/data/taproot-ref/2bed09f85647ccc7b26bbdedb9cbf18167240799 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c75010000007ef937a6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3f01000000d149970e0413abc500000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc8beed50", "prevouts": ["16f4570000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491", "264f700000000000225120af2bbad466c5a636acfebdcec0f137a30a8da1196ff11e44fb40b3a109be056a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902236e2f5f81dae367b3a32efd6df987735531d7a249a36ab57ab1942d2ce2a573b4369058c3a3e021c84082d30e443bf2688653932ae4df20c0f670f595f339bb8180e48106b379adcfec74ba8d4ad1838fe190ce0737da53bd97fcaefd31bfba66ee1295721f198bee5c592951c9e8a531371a55bc321fb847788eadbc2d005029b63c313c1aee1d4297e5bd46ef695c9522ef339c80a5118beb0805834e7f5d16cbc3a65671bb3c71007cce88ddfd6330c113b71c2fe5d3139bcb93bb77e2029b2a476686573c42313b160d5615aa71d5f015753e73e495d22b83ec41014ca5e0c58c94ec79325fd022ce445543850f9f4a12e0a89fc7e7a84e6af93fdce279149322b65da69fdf21846ccf0b35a1527e96fdf8b1a6af144e0d41decb434c80243af46f5c54e7d977528abc9efb1ed94b77daf70cd8dfcc44aeb0f6ba88167d69922afd2a082f50ee7eee80d7c8b56f7c4b8fec1685be3b10887cee1b3a15f237cd7fcaab7663ca30b0016a20e6fbf01a4be2a7125e179d607093607a85d18a938c79e802f9ce5415693e493c1238d12aaaaa4ecc6c44608fd4d45ce35fba7c92ac5abaa71b6d5047e8ddff403b9fd5a3000420b6b357402cfdddf668da8e9e34fdf30eea73acd6038b1268768645a4be94b993a436021923648b58967d311cb8083d91eb05c5b89f027a07d7b7816193082816a1fdc6a8afe060dbf58a4ab2d3436f58c2b998160e75", "ca7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360e3072da704737c92e6792de46398d398bda5c7ff39800a3d9751e7fa2331627d8a21256d264232ee00f93dc1ddd051bb1479704967786b363cfaf3cd40418b0ce21dc20c2e8df5336572f81421322a354c6d32fb525b1159d1e49b1e9404bf5"]}, "failure": {"scriptSig": "", "witness": ["4d0902bcfc97d52a3c0f965091d2cacb7a585d7ac9a9cae9eff3f1790cd8ad05798f6de8d03d290a527b84bdca5fe6986ecdbb7201485bca1b0400fd1395aacf9835f064b0a83507546adb84d6b11ba769402a81435b13ce4501b0fa96536282f5925ab3ff03af6d0e24c3583047b751e34b364f26869405ecb1e0d4bfc5111a53de2ec6f06665f3b6d9da38ac5341ee6c1c75b0adb7357e1ee21ef26f69831f2f91cfc48ef7d16f84362f9f584cabc7d752e69f6ce47ce542ed3247e4d166afe039d1a43b69be51219e81024b9ff04d6961b98e696121c64cf0cb438ef7d5b08c3bf2147431db5763ed35b9fde768a90013100abb6cb16a652ef5732a37d883130a91f42323825d7993f5b6c10a7eaf8a8c955c43acae39fbcd300292d1f41a29de29b265adf9662e62ab971d2507e3bffbba40421ae5347b67201e0ec4dd05623b04e88d74cd45f42413a3137b3908f4e9fd2d1d8de9774bd1431d72de1bcb10ac5a1ad5c766ccd68959a19c1e2d83d4c05fc304f2cd59f29ba6128d5a3357947a2629d8f325790cf36c54074ab867a40f6d669aa5f68afb6e290f047a35c9b7fe52449d636db47cf18c0ecd80637cb8fa9f0031e8b8d1b3607d85d9c71ca9581798c6aa7e3a0e7c814d4e3b73241b7e432040373db8984c3a2790016f2e851b22cf1c42226f9cade6d98424b0798933fbebda7ca71b8e6246e42a966a4d09e6897a2387b9a12b0e493fc175", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e3449c69d4dd26d8f08d0fe98a8e8c1c38138c07c2a650710c465fa6c38a97e3ce21dc20c2e8df5336572f81421322a354c6d32fb525b1159d1e49b1e9404bf5"]}}, diff --git a/txscript/data/taproot-ref/2c2132ba18413a6ac05a486fd72669aa4293e784 b/txscript/data/taproot-ref/2c2132ba18413a6ac05a486fd72669aa4293e784 new file mode 100644 index 0000000000..4f47b8deb9 --- /dev/null +++ b/txscript/data/taproot-ref/2c2132ba18413a6ac05a486fd72669aa4293e784 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c75010000007ef937a6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3f01000000d149970e0413abc500000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc8beed50", "prevouts": ["16f4570000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491", "264f700000000000225120af2bbad466c5a636acfebdcec0f137a30a8da1196ff11e44fb40b3a109be056a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d62e2c11d390d4993697686d5fe9ff5088ad345993c774ed79e9cd5d83468e5b"]}, "failure": {"scriptSig": "", "witness": ["6a2e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/2c24b83fa75f9fc91269d9be43a5c14f9a0c8adb b/txscript/data/taproot-ref/2c24b83fa75f9fc91269d9be43a5c14f9a0c8adb new file mode 100644 index 0000000000..9342ddadb4 --- /dev/null +++ b/txscript/data/taproot-ref/2c24b83fa75f9fc91269d9be43a5c14f9a0c8adb @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1300000000eb0c7ff9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9f01000000c78597bfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a020000000af4cdaf04a802d1000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76dfb7e54", "prevouts": ["501121000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "7beb5e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bbba52000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "2b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936135ad0cd7c9b6311df988de8317b2c783507c964445beca4d69314b6889edfdc527b3d6e358222ba6f0d0e44427df3c74648eb5abf60e34311dababed48c5c2bd74d03d2cf0ae79996d1bf896237ca201e78f1b4c5ece550af4c0e01e9fa9886"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a543900b336a3c008870ed4aa640473f983a69734480d339364ae43ad1d21b16885bea8937005622f3eb8b2c440108feebbdb5f3ff09e0402c722754cbcd9b2d195038de5261112827291f7af9c58b034003ed818b7e5ec0d4ccdf81f6c2ea4d"]}}, diff --git a/txscript/data/taproot-ref/2c2615f5ff25527bb1609bacc940eda0c32b8d28 b/txscript/data/taproot-ref/2c2615f5ff25527bb1609bacc940eda0c32b8d28 new file mode 100644 index 0000000000..558c40c7dd --- /dev/null +++ b/txscript/data/taproot-ref/2c2615f5ff25527bb1609bacc940eda0c32b8d28 @@ -0,0 +1 @@ +{"tx": "8e8e60c302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3d00000000e9ad4fc0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfe00000000630dd0fc01f5cf80000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478754000000", "prevouts": ["9422520000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb", "671c5000000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "be7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ca40252659daaf7bd0a99f0cd5df95fe9267f5bca7d63ff15beca83667156d23e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8c20793b34d3eca391845c9ee05577f0fe1c8a49b621d2ce1a9da4783f236266e6f69f1f3a976918b4a05b157c0a8e21d478cce8b5d78fdf690138c8d187dd5c9"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93689a733077e07d558d32e9359f72d96d0e65552d1fc5bec129f6b14519670c299ab0507b9227b06ce0689f3875ade4de998c1d9b3bd044e9f3b63e2ed7f9e05ff6f69f1f3a976918b4a05b157c0a8e21d478cce8b5d78fdf690138c8d187dd5c9"]}}, diff --git a/txscript/data/taproot-ref/2c2686017a35729961e5b4064e6ea9b58c073505 b/txscript/data/taproot-ref/2c2686017a35729961e5b4064e6ea9b58c073505 new file mode 100644 index 0000000000..ecd5c5b2b9 --- /dev/null +++ b/txscript/data/taproot-ref/2c2686017a35729961e5b4064e6ea9b58c073505 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ed0000000005c790a2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6c0100000018167116dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9f00000000e046d60303b5e5830000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e74d241b32", "prevouts": ["69900f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ae0c58000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "92f41e000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5112303efa97a8ef6ff3cee2bba9a63ee7e38a3d19e4db44f275f3f55c4e39991f7cc0cd924d9aecb0bc2fcf01621d0e73a88693291594fa52fe0219caeccfa5b3"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a798727fda10d0036e92c2807d287b376d106d60a47a638b2ffa4bc96415976a12303efa97a8ef6ff3cee2bba9a63ee7e38a3d19e4db44f275f3f55c4e39991f7cc0cd924d9aecb0bc2fcf01621d0e73a88693291594fa52fe0219caeccfa5b3"]}}, diff --git a/txscript/data/taproot-ref/2c28303252e327e51e1e99036e9c4fcc97b10d8e b/txscript/data/taproot-ref/2c28303252e327e51e1e99036e9c4fcc97b10d8e new file mode 100644 index 0000000000..1d0201bee4 --- /dev/null +++ b/txscript/data/taproot-ref/2c28303252e327e51e1e99036e9c4fcc97b10d8e @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c452010000004e24b6b360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127082010000008e6c8db2045a9741000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898755010000", "prevouts": ["2c1f340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c8200f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_8e", "final": true, "success": {"scriptSig": "", "witness": ["2a9fa7f94fb4eed58add5335b59b833f5d23368510bd8a0bad2d767a2071b5b850ff0d7a306f2e990e23ee425f618eeddd804dd8e7123627f7e262936133501b02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["4e9dad7f641f850229ab9805daceb057af75c9b7ea11e99ed179c6dd05da65dfbf5fef79d9abc6bf6de2eed4bb0219cdb88706a421c586b9138f50733f22173e8e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2c3a119d1d9da7d4fe68883d95e8f11060a9def5 b/txscript/data/taproot-ref/2c3a119d1d9da7d4fe68883d95e8f11060a9def5 new file mode 100644 index 0000000000..668f392e6e --- /dev/null +++ b/txscript/data/taproot-ref/2c3a119d1d9da7d4fe68883d95e8f11060a9def5 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707301000000b075f9f160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703a000000004772b9bc03c6971e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac66000000", "prevouts": ["0d7e0f000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "2ae0110000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "success": {"scriptSig": "", "witness": ["a4d66911b9fab85fa454ff79e7aacdb46a0cfb135b676c3088d4188b6d8eedfd4b6a7e5d091228483a946f396a7eb7a52e036fab36c42ea72842463904828f6983", "50c1e8ebef0ff5a53599a24f57ac480c27d919b1eb13fd98fac93df728ce6b0b78ce1d3365a0bc169463accb988a490f1076f186525a9fd9c3c8b2a4027b15574d015bf2d1ef1fca000ea1d8be5fa4ad17"]}, "failure": {"scriptSig": "", "witness": ["3be1d19392a4847afe2c1fd0d8c7ed5c91bf42072f6fd73e7cec54601dbad6a8751360f195d58870f0f11dd3530853fa10c72e7be83aad2c8583195fd6c8488483", "505377d055a183100a91b0a0c5ec8601ecc394fa006c26ff0fabf901f319a509e70088370c5136e74d81642146967476ea381f32dc3660ddc4c405213d85046b528bdda31c2075e07de31ded85a571a766bfe188929118b572791b993ec7840972d0e06863cc88fe3393c6101be1ca11f7942045bfce40112b02ae69d0a618a34b8a7a8baa220588bf8567a0141996f444c061c197f06603749a2e67e719b7dc92e50370bfc8c37f81f165f737dc3c58733d158520166cdfa15e640f4f00f219"]}}, diff --git a/txscript/data/taproot-ref/2c3a775a5deae4555f3af3537c8a4195c6e5354f b/txscript/data/taproot-ref/2c3a775a5deae4555f3af3537c8a4195c6e5354f new file mode 100644 index 0000000000..257a136d12 --- /dev/null +++ b/txscript/data/taproot-ref/2c3a775a5deae4555f3af3537c8a4195c6e5354f @@ -0,0 +1 @@ +{"tx": "32bd0f0b03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7301000000a2d6c9c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a100000000c06b56c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127000020000006321a4850146cb4d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709ff9333", "prevouts": ["03b67e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "f22b120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "802711000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b9", "final": true, "success": {"scriptSig": "", "witness": ["bac03280310edab32e47ad2149e69de400c7ffe6e28a636181118f38390d7a787f2ae43f65710514538b1fdd779c58769ede109ff1d79db0bf4471ecf111209002", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a297df114f37f55d9b4ed1e3f63bad63d671d4b9b23c07be7af6a916ec99158de750669f9737e120809497c4ce13d79fc1981426b808fb763aa2343f19304573b9", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2c62f7a3d90b30d6f1b1804f6bf0a916d3305efc b/txscript/data/taproot-ref/2c62f7a3d90b30d6f1b1804f6bf0a916d3305efc new file mode 100644 index 0000000000..c23dfa5770 --- /dev/null +++ b/txscript/data/taproot-ref/2c62f7a3d90b30d6f1b1804f6bf0a916d3305efc @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6101000000fa271d9660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270790100000078cbba8d03582c3100000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1c000000", "prevouts": ["2453230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b6c010000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_48", "final": true, "success": {"scriptSig": "", "witness": ["4a56d64489dfcb24ad51a498b7f548027600e170d67317acec759b0f03422d8e5ab3460d69c19f6be0eb559f50974c028601689fb5b5f6237363d47ef5b8e24c02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0db5ebafb35dd767eccccbd366467749618c34c6f5fb7912f66b22577b8d93dd653e03e8d68f6ab4c010e6bef0a6ce86255f8fb46088e55052313894091886f148", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2c67e0be52a7389f103f44944fe8d8913c973b48 b/txscript/data/taproot-ref/2c67e0be52a7389f103f44944fe8d8913c973b48 new file mode 100644 index 0000000000..e6b4b6cd47 --- /dev/null +++ b/txscript/data/taproot-ref/2c67e0be52a7389f103f44944fe8d8913c973b48 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708300000000a2259fc7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8100000000c6f72fe102884f91000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c8010000", "prevouts": ["1fea110000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6", "6e5c82000000000017a914927d550e2674fb9e1f6ae1260d00989fc596dd7f87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2254202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["aea28210ccbc6063f5354013cd50857fba6fd49a8749ad2a4148746ed6bdc422ec0cce14f7f2b83e3d27a6a13354cc60d006a9039e074d670657ae6edb93d62f"]}}, diff --git a/txscript/data/taproot-ref/2c7c5497a7e7f81979773204f099b9f23323698e b/txscript/data/taproot-ref/2c7c5497a7e7f81979773204f099b9f23323698e new file mode 100644 index 0000000000..9270b63c9d --- /dev/null +++ b/txscript/data/taproot-ref/2c7c5497a7e7f81979773204f099b9f23323698e @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccd00000000f9b351b001d812490000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e79e000000", "prevouts": ["d5225900000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045721cddf589dd211ac28650b11a57c9c7761090d2defca181b3dbd9260ba7b6b1d191de94316b2d555b882a7ea052cdcffb2858bcf3e9dcd4db66bb89a9914d760d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936140d466410f93f506cb3577f700de6259d226f314801f04d6da966bcb64c10bef2809a2eb594a6d82ed798bedf8d6754ddd1a8a74001a2f8f1c3cb07bb651864f3b3fb8d5121830dc5ea13d084a01bce62f4c2426ea7fcb92dda33a6ec3d9661"]}}, diff --git a/txscript/data/taproot-ref/2cc2506d179d284634729bf9fbd8c05239f90ca9 b/txscript/data/taproot-ref/2cc2506d179d284634729bf9fbd8c05239f90ca9 new file mode 100644 index 0000000000..26492ea6b4 --- /dev/null +++ b/txscript/data/taproot-ref/2cc2506d179d284634729bf9fbd8c05239f90ca9 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4c00000000fad9e7660375706800000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478780000000", "prevouts": ["785f6b00000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f94c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c138752b88f442304cd570a99b7416851da048b7f1df3ec1a880a296df45b544a4dd4bfc6549e8d5e198b0f1e67d147f6db02444245a6cb27bc19444f2462468d332399bdd0fdb741da8d579adddb10dac50c4b595c0031ea1e156729d78e3487d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369f418ddb17834b13bad2d7867a7cd562666631728cf586feeab904af49e7e90debe99bd20db478a4ea38512f1221f176d7e5053d85ce724541b970d7e312b589d332399bdd0fdb741da8d579adddb10dac50c4b595c0031ea1e156729d78e3487d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}}, diff --git a/txscript/data/taproot-ref/2ccd61243d6bba96a68b774617b9d76c97662ff0 b/txscript/data/taproot-ref/2ccd61243d6bba96a68b774617b9d76c97662ff0 new file mode 100644 index 0000000000..67575aaa40 --- /dev/null +++ b/txscript/data/taproot-ref/2ccd61243d6bba96a68b774617b9d76c97662ff0 @@ -0,0 +1 @@ +{"tx": "a890ed2e028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dc000000001f541de760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700601000000ecb8d1e201aa403a00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac99020000", "prevouts": ["ec3b3f00000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "f06c110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638668", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365fab757434963be9e6b2bc0ce3358798181954c3af1778da49ffe7612886fff5056f60ea686d79cfa4fb79f197b2e905ac857a983be4a5a41a4873e865aa950715c685a6e20a464c0638846c4feb0cc1ab19a0a1d3cef03660e119c827d202a5d33ab5c29645e0220ea4ffd8cb7e67404885cb8b0cf94872336c7b06d59c3124"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d516619599a2832199ea7520e829579ac708ea18d94219cc28453716c125c7ffbf6b4167115de6998fecfb714975bc270adc7a6998f06c7ef8576e15f157ca8963750636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}}, diff --git a/txscript/data/taproot-ref/2cd0311c121154bc8385767e5893c92ee5aa2c05 b/txscript/data/taproot-ref/2cd0311c121154bc8385767e5893c92ee5aa2c05 new file mode 100644 index 0000000000..9f86b197bd --- /dev/null +++ b/txscript/data/taproot-ref/2cd0311c121154bc8385767e5893c92ee5aa2c05 @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270410000000011ab04a302b6940f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc40030000", "prevouts": ["5d78120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_38", "final": true, "success": {"scriptSig": "", "witness": ["671024994d289f8082e67b82ad6c507ae04d157119b587baff5ad260381797efb62a929e26d45f8965e5bd110b3aef395b702fd402ff517d175be30d7cf3f09a03"]}, "failure": {"scriptSig": "", "witness": ["4c81a578377825b6b347ac5c4623fe99cbf806ead287d9bec6c7a24728a2018bb0e54cb299c047d9ce95db7071e4a3f6f99fed67291398ceae513120af070ec438"]}}, diff --git a/txscript/data/taproot-ref/2d240420d7f8e429cb31120c7bf532805423084e b/txscript/data/taproot-ref/2d240420d7f8e429cb31120c7bf532805423084e new file mode 100644 index 0000000000..b61b027911 --- /dev/null +++ b/txscript/data/taproot-ref/2d240420d7f8e429cb31120c7bf532805423084e @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127031010000004cc7cda5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2c00000000af66aafd030a6e79000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87dec2e433", "prevouts": ["a3ab120000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "b7c06900000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["30440220424a1fcedac58fbab208e7872625898eec1b477b391478d49822257108be639c02203b1888636d3f82bc77e92d9d245acfe2715ca7c9e4963a7d15acae979b7adf7dfe", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["3045022100e974a892ae164d3255e966f24d7157c9f6e5773a9f2534152153e64bb12fea0102200186a3dfc8c364a7ae72712fa808647039f4e9fc39c07bb3d89c13f0d62ea0abfe", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/2d2a878308fd10775f477107b478ca6993799763 b/txscript/data/taproot-ref/2d2a878308fd10775f477107b478ca6993799763 new file mode 100644 index 0000000000..b00755ae9a --- /dev/null +++ b/txscript/data/taproot-ref/2d2a878308fd10775f477107b478ca6993799763 @@ -0,0 +1 @@ +{"tx": "8d072cdd028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c408020000006c4d0c91dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be800000000b35dfbaf0267815900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6e14cf126", "prevouts": ["7b9236000000000022512085b1b5643880360a93ad399dd8d1aa945ccf0115d9a41dc926feca691d280be1", "8981250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93622caa5a4728c320064920d38fb193ace693a56e97bbcb89e0763e5547ea42b91"]}, "failure": {"scriptSig": "", "witness": ["6a08616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/2d50c7d765d0137b5bc9bd78ac8e39437d22fc0f b/txscript/data/taproot-ref/2d50c7d765d0137b5bc9bd78ac8e39437d22fc0f new file mode 100644 index 0000000000..f7d123ca18 --- /dev/null +++ b/txscript/data/taproot-ref/2d50c7d765d0137b5bc9bd78ac8e39437d22fc0f @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbd00000000d61de46603ff1b2000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc754000000", "prevouts": ["31c0210000000000225b202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["74d06513e254771c994c8eff3a704430ab64d6b1094937fe3e9f90083eb5ef5c0cbbfd8214affb01532e5b00db6afc887d4f96e2c8d8ab269cd12eac425d2b8a", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/2d562228e60c1a1e62b21379cc97a7cf96852b48 b/txscript/data/taproot-ref/2d562228e60c1a1e62b21379cc97a7cf96852b48 new file mode 100644 index 0000000000..06fd0e1d6b --- /dev/null +++ b/txscript/data/taproot-ref/2d562228e60c1a1e62b21379cc97a7cf96852b48 @@ -0,0 +1 @@ +{"tx": "0adb3c5a0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c30100000007c9f6ac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704a01000000e25f26870387721e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2a817952", "prevouts": ["569012000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679", "59830e000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "7e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369989da34048f0fc009025cddcce64a25b2539e47e8d6db7b5752e0bbf5ec5785da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed3fb5b8f7b3afa290146b30788656a8f4c2497a65b1555cd50f1d702ddc8a1f8f2e4a14a40b0acbe20218e44481fe6660f01d2e0cf04e3bc8d4452bacd1080d1"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fab95efb91d04564594d9dcf752eb8fd975bf01996a0bb9f9eb7163324924bcd44fa5d068ae686a8bb1ac9947127542ac866077ad522de57cab26ce701d52bc951"]}}, diff --git a/txscript/data/taproot-ref/2dafca8d1802bbb6ce3ae1196aa647ee3c9e418e b/txscript/data/taproot-ref/2dafca8d1802bbb6ce3ae1196aa647ee3c9e418e new file mode 100644 index 0000000000..5f2635c88c --- /dev/null +++ b/txscript/data/taproot-ref/2dafca8d1802bbb6ce3ae1196aa647ee3c9e418e @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5c00000000bbab6ce0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb500000000c4ee82fc03fcbb79000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f878865e72f", "prevouts": ["34dc260000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "8bab550000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["30440220737d2e648a5be65074da66d545eadd11f9ddf1d199ca3ab7cc78cfecc3e18dcc02207f2c8d36c2e65fc7a9934bd579e42176065193e8b901b8209c216c7ae7b8985f82", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["3044022065c9c653026db1153cdd8ae6e83aef8a48d7d558f87f475465c26ace6cfe4dc402205731f6814f4a56cf57cd6107ebc60af4a92a74876a32064ee6a8c15e206008c482", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/2db945824c150b91aa78265f9e3701bd991fcf10 b/txscript/data/taproot-ref/2db945824c150b91aa78265f9e3701bd991fcf10 new file mode 100644 index 0000000000..9a24cebf0f --- /dev/null +++ b/txscript/data/taproot-ref/2db945824c150b91aa78265f9e3701bd991fcf10 @@ -0,0 +1 @@ +{"tx": "e2951d0503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2900000000faacbcb9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1601000000b69418878bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4eb000000002de75a95023fb57d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689870b6d6e3c", "prevouts": ["4a82260000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258", "6f1924000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "0ab0340000000000225b202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b904af0aedf319833b6f0b5cc7decb0889776f3b77dd0bee536a968c107450583dc089f03a34f9a466f96706ee05a2c65539647f5e0522a7c1eb730770b2f3bea809c0c19ecf10fa30a127aa36fa908ad7150633bdc76f444042c61340bbce98f283db07d21eb3646864d591d62d7ea89cd4fe5c53d9cac758325c23478cd23cb96479f190182bfd291c39676b63b25ab7189f37c57b6aa43a9787a8349f43ae6af10354e7c7683ba590f944c3f093f860075a196bf752044b2b9e871432bed800b030b09424cb74a4c11ead0a02665a359a06a427191c45484eea8acd392b190ffbb0b67847bf9a36a335ac89a394d88743908daed17785255b26220769bada28c31d2f9f02a4c9b4a00cb3902bcf1cc4f329ddf7b755fb48424ac9e2b15423725fe4392aee827301d3bc45b505bc283104c722e19161595876ffdebcb027e30bd4617df89096bce9d7b78b1451ac28e0b27e029178010867b2da170d39427ff5093c317c8272b429ac5aafa9a052804a61485d365db36ed4e6843a72703898607188976e5c86ffa3d89b4bf040fd3cc53d0f80542bb58ebc484bbdc68885b83eeed607504fcb8e701a3f5d54dd575762b414a2a420b081fc8f60a8b7badc2e7063460be2968cecce24ba321cc219799ea24f62415cf33a6ef1cf4a78606e7fb7f506279b41e02ccbdd054737dca131891bfb6465063f4695a16e5e9dfe559a5b91a3ae9bab51173175", "3d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362b5dec934ccf641c1f3f5519568e5c1c1326bd2715cafe0a6e7ee716dc27c9f14ed4022c883bcffdd4981a43d80a989f638bed5cb710560195e12f06d5f3803c1cb891527dccd7fe22077390053ac1c45ab6e7110116df1a30c9559411f432f5"]}, "failure": {"scriptSig": "", "witness": ["4d0902257170955c47916501f1e60c211483835e75c9607c71846fde55f94f7aa07a0af2cb6418c4e1c2412127f30be270998c93e9590de3c36cac97d677a256b24bcc76b77d943717e4a234ec25292d21dd067dba9e06830f0368f151558d05d5d07e012f91f50149ac649c461743569c40ce9333fe03c4493f78cf0979447849a721f1def33ce6a24d9cbb3ad9cf6e909243572f75b01621e405f251adc94b7dc03d07bc5d94aa409b639ec1a77bf4fca14d3549c531d7eb2449a0520f30ecd38ce52ab978f0402be6e8892482df4274d4d7f0ea0143d29895bc7fd257e62fb7af1d5a2e928f4c6bdf0e192d3b4a285b5ac0089875c94f83aaf2513e3eb15e4c5fae4ec1caa74bfaf5ac4795cf54d655f358d4011f9e68e232e813a4df6489cfc2ce3020464d8c4c0579852ac2529b3623fd1c11ae5178e665382fae66fa7ad93f6eb7443ede6bf926783c8eef39f9495b71a096271b5ce0efd4a7f703a9716827d1217fe9784f1dfc83e52c30c326a3a22d8ec9878b4b51ccfa03958203245afed879db89040dcbb997c948e771f16d17ca798e3e158638132ad6fe035a478231903687b0f2c05f10b447a4b4336a280e48c0ad415fcba55fe7ef100c2ac1da92cee102ed2f2e03a1d01c5a5e5a3696693b8b64bf395d8a75555cd58a353ba21948541ce5427ac4945a027563d24d51dce47446ab54ee30bf25b2854f8eca966297b3c822432b73abc45675", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eef9a48fcabec25982850a496e19df71982d596f167265e15d1ec282fb30074b91cb891527dccd7fe22077390053ac1c45ab6e7110116df1a30c9559411f432f5"]}}, diff --git a/txscript/data/taproot-ref/2dc10a9c76952430b8601993c330b88bd0e19cb0 b/txscript/data/taproot-ref/2dc10a9c76952430b8601993c330b88bd0e19cb0 new file mode 100644 index 0000000000..82cc79da4e --- /dev/null +++ b/txscript/data/taproot-ref/2dc10a9c76952430b8601993c330b88bd0e19cb0 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45400000000990ad9cb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709601000000ca2459ba01210a0d00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acae847024", "prevouts": ["dd2d390000000000225120ed1497f510b05298f56dedfdf59bdab87baceded2037e3bc9fe47e7002bf81b0", "480f100000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d666a87a34bdde03248c8aac3a2f3cbb5c6322b1c912a69a1720e7f08fbef08803216184eec05d23f2cf8f11e8132d22e55250b1dd0dd930eed2463a640b4cb3935b24f2dda21bd71b290b36c23a236e30959133139fae36c8c319dfa56ccb90b4f923087529860f60db50a941e0648505ee9229884c11d173fccdaea036b5dba14a392c1fd4395ff1b7822f28ce9a0004528e2fa8ae1dccb1bd625bb1fcfc692e0aa9a022e68826a2877d11dac2e04126f6e07e45bd216ee7ab06a4968c00d89b79a7d694735f4cabb34156980ee79b7aac581cf7775adc112e870cb17fdee261bee9f4bd5b18fa95aa09d60e495a365c9508df1a56f37976c686f96663e0230d8b361d5e30f297cbe821243044a694958a536cd18156076f3622111985cf0a3139f617cb31d4579ae1895b63f089440e77a065a8ec026200c06767f6abb6f469bd20680cb27d39f75fb37f4825620229d9293004f8bd9ca6dc114006363919ba331314771512786f7741367e58d06b74a75d04ce197f6fd9c2847636622112bb1a45221a9a0522bb592c94847b18761c41e2b846be6cc8f45bb8995138e65f85dbc5b0bfc7f32edb83097f4a210f09cda4264ce9f7ee4ee22f69b0bc375ca731222673b6e920f960bdca744e509f5d5954465de105977324203a3e262c0fa535aec5147081fa05fc6fc3b6a117c5369818034468c9580a1f568c01c1b21d9d2bcf4569fe463f603375", "7b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffc23cd491e8fcb233d9013136f75dc1e8b804157adf3d15ad0ad23d368e24bf2affe3792374ee751e9779d236e331236b2211c0285bb070b7e5d58aad1c033f64fb6de85916ce1333b57715a419fbbb7fd448155796c8af09a2e4a2bc14d947"]}, "failure": {"scriptSig": "", "witness": ["4d09020d89e0fae9357fdf89b3639a88a65e941d8855eec7ce68e6f13a6a6b5ba7abe824e47f9cf11e1dbd0db57166425eff3ef578e9d73568bd184640c4b591b9868a60e084744e7779b6f7ed248ff685354f7a6fa7e14e3da359ff41a86336d03e9c099b997d1b730bb33294a22b3a195f8aea033d9bc2379a715bde9caeb673718125e9d4d4414cecec1512cabc9cfb91f0b2dc8a05af0d20c29414ca1c038cf78b8e4aa4acfc6d684bed98bf6b681fb6b7df97d391cb17b74973cac63d5bc86bc87f9d430a2edaa5b85e433b89c896b996947815129981a5aff7151ea9f31cb8c9fcf95da2582aa3fe946e980cf8a244f2ad099e966e49e3b8244780b5ef903b7c607cc2ffb736f8d564e668a7980dc19204e424e745cfdd1efd399904892b0a6be52037ff7f6e76fa8d8c7205e6bee9803a215355cd4fde78aad7d52c69434936dac65bd6bd9db59f771ad152530fc9d46a3b2e763bee19b8d3107c2d45860838c11535d77df67292c9824f5522e05a7110767a2958a7cc3ebe595fcbd74ec86be2b8c4bbdf5bb6e961d601c2c23b209754997b2cb59035a9f784a7ca23feca6f227e72a4053b48320e047a819e418a25e269d2e8b14a993ccfb54d8fbecda59635bd327a3b21448c5d75da091427fee5410852eff893bd94ff535963246cdfbbae3891e3675cef51b3bc6440cd3cd3486e3dea650cb3712fccc780e7dac268f9a2244c828fae1383d775", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082565447efa486312fa493bc3efa8d0ca00e2c766484411258b08f0fec6b85156cd34322f35809060e9857f404c38bdcaf402c3d07c78e42a3b4d1eaa304dca88a"]}}, diff --git a/txscript/data/taproot-ref/2dc5b1536be7b443c27e763739595c42dc34998e b/txscript/data/taproot-ref/2dc5b1536be7b443c27e763739595c42dc34998e new file mode 100644 index 0000000000..9f9cf3127c --- /dev/null +++ b/txscript/data/taproot-ref/2dc5b1536be7b443c27e763739595c42dc34998e @@ -0,0 +1 @@ +{"tx": "b183537402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b730000000029171eb98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40a010000006f30ebce04500f4f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374879e627060", "prevouts": ["76491f00000000002251200e94bfc4da0ec878710fc6e63dfa8cf2888c96cc8603d6f04301c7800d453852", "9dc6310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364f1066f55fda12d1d5279f6f8609595c415a02645efcaf2b4e451b7cd978e9be"]}, "failure": {"scriptSig": "", "witness": ["6a60616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/2dc9f8f8cf217ccac41228917cb739aee23f3b55 b/txscript/data/taproot-ref/2dc9f8f8cf217ccac41228917cb739aee23f3b55 new file mode 100644 index 0000000000..20a3ad0318 --- /dev/null +++ b/txscript/data/taproot-ref/2dc9f8f8cf217ccac41228917cb739aee23f3b55 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c415020000008b24badfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0400000000376ef8070205c49700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689878c020000", "prevouts": ["92b3310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "adb367000000000017a914856f7c6a5a6a1ac0e553b769a4c35bcb9fb6f50287"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_fd", "final": true, "success": {"scriptSig": "", "witness": ["697477b6f9d7c74b509fb25aa4948561024137bf5c2dd8edf46921020f4f122a9bec8324cefbd879df5bf6225ecd05d3d86f6f42bb1afff2496a0395467ee504"]}, "failure": {"scriptSig": "", "witness": ["48f3d197c6e9af9cacf64915a2f18cc6c0838397d1f75de62dd956b4e5212be98be8b375a488565b5860f3f0bbf77f9d9eb6760a40ffb52d46a798d994eab796fd"]}}, diff --git a/txscript/data/taproot-ref/2dcae1af8317442bc492bd0899984f32bf30396d b/txscript/data/taproot-ref/2dcae1af8317442bc492bd0899984f32bf30396d new file mode 100644 index 0000000000..ebd72fa4d9 --- /dev/null +++ b/txscript/data/taproot-ref/2dcae1af8317442bc492bd0899984f32bf30396d @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd901000000f31c8ecadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6f00000000c116dbd404db3d7a000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5d010000", "prevouts": ["1ef55c00000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "0fff1f0000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "137d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e86a37fd9f079711aee2dd395c4f9bf6b9cf1f54b1a82846abc908addbbb61fc725d0346f0de7f7080f7758bd86c81c482f81ad0c7703311f4b65ab9d7b77c9f00"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ebd41cd46598692ca564feb702471a27c2b329b731a2dc6dbcecd3c4d6afe3efd7c43b740c0608ac721897ca7a4b0bbd2ef7e62418d1fc20274bd386c7c0d4d7e"]}}, diff --git a/txscript/data/taproot-ref/2dd9b9584d97aeda14030c0cb94034e5a64e1e33 b/txscript/data/taproot-ref/2dd9b9584d97aeda14030c0cb94034e5a64e1e33 new file mode 100644 index 0000000000..e497a8c7b1 --- /dev/null +++ b/txscript/data/taproot-ref/2dd9b9584d97aeda14030c0cb94034e5a64e1e33 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ae0100000008a2ec32dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9c00000000ab39da2d03d6d489000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc742d7ef21", "prevouts": ["0d91320000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6cac590000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_aa", "final": true, "success": {"scriptSig": "", "witness": ["2fe77d385cee1e8ea67bcd1a4ab9a7a56a6fd393937cd299ed84fc6ff756a1df9a87d024d0f2673e09d267c99b2631e47bf3c52436e2f7dd15473b628f861f4702"]}, "failure": {"scriptSig": "", "witness": ["171b6ee5693612f96b8971c02837bcd7990bdac55d1268294b28e40192fd4aac74c35bfb700be0dd9b7481d55e639c3f7b0c8e807fadae98b63b8642b4d0166aaa"]}}, diff --git a/txscript/data/taproot-ref/2de7782cb97bcd10b69053268684420a0022efd6 b/txscript/data/taproot-ref/2de7782cb97bcd10b69053268684420a0022efd6 new file mode 100644 index 0000000000..c737c19443 --- /dev/null +++ b/txscript/data/taproot-ref/2de7782cb97bcd10b69053268684420a0022efd6 @@ -0,0 +1 @@ +{"tx": "35c5f7e30260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270220200000096b2ecaf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44c00000000bf5276d503061a48000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987c030cb56", "prevouts": ["02ee0d0000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde", "ee013c0000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "f77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a71884cd53fc7dd87aebc20425da51a5c294f1bede93b7a913770a59279767c4e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e80a4dc25bef94d3da1f821dff96c297a1e496d55e040bded104527be104f359289411b885fbcd56b4d2cd2e695cafde2fa2de7097172cb34b20e1fb870aea9a6a"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f5209053a0e3543f016bdabf2a9b449e56532ff027210dc00b302557bc408c98e1b135a17580d142a9191c3b85b2fd298f3e09062f6f11151feab86e1334277f9411b885fbcd56b4d2cd2e695cafde2fa2de7097172cb34b20e1fb870aea9a6a"]}}, diff --git a/txscript/data/taproot-ref/2df7793cf7520895ea4121850c34c16bd1874c22 b/txscript/data/taproot-ref/2df7793cf7520895ea4121850c34c16bd1874c22 new file mode 100644 index 0000000000..a87a7c0c9d --- /dev/null +++ b/txscript/data/taproot-ref/2df7793cf7520895ea4121850c34c16bd1874c22 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf48000000009d982271dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c76010000002843b97c03ee7dca0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787fd93ba45", "prevouts": ["a3c46e00000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "81d15d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d04c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b81ff7cc7637e0c05982e17a8e208328988859d4b2b7eb979a1983188becada13f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823bd101e45a609d3b8e0b3b6f0b7594624f7e9102ef5d5dd3027418de40ebb2180d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb3c724dd5710b1380b446d964c3207575a75cdfc2d4e5f005be07d8e30cc140daaf72f6551695de9dd2e4eae28f07b41c9ec36110061b2152d7ab3729ab44bcf81a0ae7b640e88bbe84e7c412f47337f1d12d37f95b062c539998fd28213cbdf3b3fb8d5121830dc5ea13d084a01bce62f4c2426ea7fcb92dda33a6ec3d9661"]}}, diff --git a/txscript/data/taproot-ref/2e15993224f1d73378824cbd1780f6d25e85740a b/txscript/data/taproot-ref/2e15993224f1d73378824cbd1780f6d25e85740a new file mode 100644 index 0000000000..a859b7f136 --- /dev/null +++ b/txscript/data/taproot-ref/2e15993224f1d73378824cbd1780f6d25e85740a @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270910100000002ee48babcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6301000000681f3bd404a77680000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac689bb04d", "prevouts": ["d5e912000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "11686f0000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ca7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea15911bfc306ad37f0e70507a95a4a7045d4c5bf0ca1619bed3f37a14eb6407e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8bfe61acb5630f372e1ed5eec342882068788aa3656bac92c2951e857c300141b065bfcb7199ff8296c5f7d41f3b2c6067d88c0a33f2878328c609d56cc191f12"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367e39eda6846be57e551a440b61577244ebba110fe39aa4de9a3aa77d57736b5ebfe61acb5630f372e1ed5eec342882068788aa3656bac92c2951e857c300141b065bfcb7199ff8296c5f7d41f3b2c6067d88c0a33f2878328c609d56cc191f12"]}}, diff --git a/txscript/data/taproot-ref/2e2b8acfc93c65c04508d0730229d6beb1760346 b/txscript/data/taproot-ref/2e2b8acfc93c65c04508d0730229d6beb1760346 new file mode 100644 index 0000000000..7a2d7e9804 --- /dev/null +++ b/txscript/data/taproot-ref/2e2b8acfc93c65c04508d0730229d6beb1760346 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2101000000cfe0b1b560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701701000000d6dee7570105fc0400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4c000000", "prevouts": ["48997400000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945", "60ea120000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_mis_83", "success": {"scriptSig": "", "witness": ["a9a463c57f5b1cc5842c32f6861eeb98c56b3095b2197f0179969ef076ab25d20d39b7716feadb72ac981c7987e20c4b8515b4f9c3b8c492e0c03343b569cc2e82", "507a06e1db1b486066c7a31bb8825a8d4302e904a212edeb9483bce2e1e7bfc2face2c9d48f67629594d3117b8c3ef6e71a386fe8f45378203b251d4b128acaa7269"]}, "failure": {"scriptSig": "", "witness": ["0ee1f68bef8ea48719567c7dcbd082a7445c6f33d6c6725bc7925ef66844f13a78baabac3df01b4ec85b8869e341ff558eb711e6d5e59ce798f12427fa89a4bf83", "500b8bdb554277b253a33974533211c9bdbdb494be9869b397c3e49b32982d90b8842ab8908c5724d99cabe2863b00f227b79ff5c83dadb7293a20c7a4be1ebf6cd569b24f9fcebb6937179e2487c7eca78ff87249"]}}, diff --git a/txscript/data/taproot-ref/2e4630df1ac360494322a4300b3a916bf4a7aa42 b/txscript/data/taproot-ref/2e4630df1ac360494322a4300b3a916bf4a7aa42 new file mode 100644 index 0000000000..6f9444ca20 --- /dev/null +++ b/txscript/data/taproot-ref/2e4630df1ac360494322a4300b3a916bf4a7aa42 @@ -0,0 +1 @@ +{"tx": "9e51fc1b02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf32000000004143349fdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4beb000000009abff0ed03c1d68f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ace21a0c39", "prevouts": ["01b468000000000017a914a8c07d8aa161ec0fed82ac1dc93d81dd0a92012687", "54c72800000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cf", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630ff43b1b4fa7d17657f9cc2ec27f32679adb7cdeffb13176335679db5b5919f3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828121d7901a27ea565e1cb6f91818c43a3dc8f46dc56db80c8bd3776430739107a653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514d5a9b7fc917253ce709706ec0b90ac12c0f363dbc177a85b066bc4407805851ecf70b79dd1be85a38988f8929e7263abb01bba95965800009381ed351eddb0fa653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}}, diff --git a/txscript/data/taproot-ref/2e9a37abf29713e5bf564831df0206b134ed9e23 b/txscript/data/taproot-ref/2e9a37abf29713e5bf564831df0206b134ed9e23 new file mode 100644 index 0000000000..14a284e595 --- /dev/null +++ b/txscript/data/taproot-ref/2e9a37abf29713e5bf564831df0206b134ed9e23 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf60010000006c56fddcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf700000000cc52dde28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41200000000d0282f1d047d49ca00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d8000000", "prevouts": ["a7a86f000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "7af02500000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "2e6e3600000000002251200fe4658e0dbf66b6be10f530376fb0e6dfa185e9d7f38ef5d5af1eba17e45594"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b7ad5dba2f6f9458c267035de2d7bf503510508c8170fbdcaea0beece8a3bb23282b7b94ff2692e877eeaa3eafb165130cb72cfea221dc1c58e730ef74fd0fac2d03c13d57b4ce5b0f7ea75927e23ce55c81390c8691b340cca438ac913c93305ebfc1bf0ab184275a47986721d9e8f84e432fcfaa66fc390cc40b5c0290fe4b0c7cfde660d1ee135ba38c440afe4643c43e3d8b4d68ba8040e98073deae341927ebf2266d75261f6214a86770d368c621acbc65bb9a2c7d63609caf35c0ecec934b8a35d972d4eb890c97d9efb764cc68c53e650a3ef109e3716255ed3e0d3ba7aef3ed87e4d27263b62c9061817da64c850af1dfae274cc53511cab2acef4af2b814d26bd325950368d51e19e7ac1c1a2110f7b50316de62e60f5e0ced7a359552e8c90be6246b22132cf033941b5944e52fc7e7aa25bdbabb21948e91ee116fd488fbb7229962ed3e168f23612ef3436cc4c9bd0a5c4d7183d64660df68686f73cd6cf451a862d2c3e833b18d4727df04ee7ab75e62480db84d78a8f5679747e362e4fdff8760ed0d4e03a4383f57d8c88f2964bdf81d017cb6f18be3d7a4b4066719346642082479181c32c448e66a1890e57cf84b0113f5e80de7777280948712cbb01a1df40acca696cd7148190f34cb2fa319793f9c7086b04f8a5be3a02023d4a2928785d933b30c7a160b32310b76a06b255ef4c835996c1cf58a4f7950a8e742049b63d275", "fa7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936871d09367f73210ada4ae17c4e696152b1b26636a23a3c040181dad738cb50193f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ef1076b289256cd19daa60d704e81db3a39e457bb71d9d0e29c4cb2075820e5e1"]}, "failure": {"scriptSig": "", "witness": ["4d0902c4718fa1742f630e1346c8971a97dc28b4cce6fa6cfbae37f39d896e5b06392b510889602d9f3fbe754f3e9d9d1ba4e3f541ad98094691579a8a5d9664d69b1c9c35b2fdabf844c85a1121ef42824f7777bb6b72e47bf0cf97f434d6785dd7e8adb346d0b105209d30cbe127d649011a9ade0103a12da678b54f64b6f0594a3f837c450ffef8f55166ed79348879022fbc2d61b4f2f00095f7a8bfc6a3b283fed52a77d149151c58b6a0b1ab76c118da14bcb10aede9ebdf7fdc6402feb70ac33bb898ac02a3d16497f1296a55da1869548de7a289ee324d21ae208e00cb80f1cffa358190b15800ccbe6806b56530bff303c2990d2cda159b647132c0439bffda5a392b87844d9e911d6a5f83b3ed6fad30e74a263271f07d2c1c6b2691559d7293172b4d43e9162c6b8d8f5868aed99cc7b7c81a78903215779b9fab998bf5675d133b4be726476089f5aa330e4f253db7656b13f58a050cfa5f752f31832abf50c75911b6ede542f22232a351d9416169451df509d7f19ec9225d3fffeb2759eae5ab270110fee0b16f994fdf531f2dec50a73775eadd449b2307f2748d1b9ea07092c437684160b82cb848bcf342067aafc9ca65257dc0ba1e2f7ba302f2aae965b572a53677671866a5aee0dff7ce69e8d4182b9d78007d2c815a29321521020242f6c8f96f2a0d3504a49780db73a422e3fe68b69f76af454f4c0fa3c4bcec9210d88b59dabe75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369137576d67431f087aec678a5b0872b87ad128bcec3b357baf1a434a8a1f59b5284b3c1002850d4c89a68130d64a5a5ee29d0b1bb458f5120fd1f649ff1c37e66ac496a48f5e08c9a0063585476106fe61a3ff4222f4c7aaafd1f65bf01170e2"]}}, diff --git a/txscript/data/taproot-ref/2ecab25cfb72ae137a881589719a53343a030263 b/txscript/data/taproot-ref/2ecab25cfb72ae137a881589719a53343a030263 new file mode 100644 index 0000000000..22b20c5053 --- /dev/null +++ b/txscript/data/taproot-ref/2ecab25cfb72ae137a881589719a53343a030263 @@ -0,0 +1 @@ +{"tx": "956ac78c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd3010000000bede5d6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbd01000000dd0c1e9303c6f18f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79631010000", "prevouts": ["3db3220000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8", "db25700000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["0b28dc1a1ed9c237cc12bd76b0de2c6d3a65d4aa2db7a6dee9d7bb55a8f05853c18259cbf31a19f2a6e9653cd9f674322322eb2f4e78dff407e40bb84c9928", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/2eccff6ea763376046948b3876b0d9b3e8b28c87 b/txscript/data/taproot-ref/2eccff6ea763376046948b3876b0d9b3e8b28c87 new file mode 100644 index 0000000000..b81150e70d --- /dev/null +++ b/txscript/data/taproot-ref/2eccff6ea763376046948b3876b0d9b3e8b28c87 @@ -0,0 +1 @@ +{"tx": "cc6f3def0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a90100000072a16fcbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1d02000000bff28abf0409d36200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ace2040000", "prevouts": ["38281000000000002251203e6b8aa12170bf3e8ad7f10d608d1ed027d7fee17123c5116152c821758451f4", "bc035500000000002251202f329ebb629b1bb09406fd99900762644c979122f44ddf705116f636c54af1f8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "success": {"scriptSig": "", "witness": ["b169c11161be2668a4898276e1674688a27c346bb637a43c4603cd94a1675fbeb0f4e4a049f072db99a8129c20c7ecb362d04a1f7f31ef2c875354c24c669dd801", "4f11cb54cd4363330221a5476e74c99e78c313b7e57ea6a0a1a013458a6017055bf2fb8346e050982ff6bf4e87eee951d27544f6d9bbbd37797efe7145a70c1734571bb22d9dfa6283c74a63267c132bad", "753535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a25163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360000000000000000000000000000000000000000000000000000000000000000c464465aab929372e8a3272aaa968cbe1bc1afb1960d855f2fe679d588a02434856b36bfd7f7855bb64dbf9aa668b0b855833757a9d963e8997fdb5f4e4240cb4447818055f223605d46ae0697f5dd051ef4973d44405ad46cb7216702b7ff39fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff31269ab2f4c1c53405a20186a186d3b8959a3926b34b7f6cc4c21ab859b1ef6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}, "failure": {"scriptSig": "", "witness": ["b169c11161be2668a4898276e1674688a27c346bb637a43c4603cd94a1675fbeb0f4e4a049f072db99a8129c20c7ecb362d04a1f7f31ef2c875354c24c669dd801", "3ff764577193cecedc2471709b069b3d901771a4bbb5117747b819cbd4ae05a8325788723d9289f513cf115e00228431a78d3bd32b6087d0f419353d04936992d9d02a23a2ae49e10d78ec481bb26731", "753535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a25163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360000000000000000000000000000000000000000000000000000000000000000c464465aab929372e8a3272aaa968cbe1bc1afb1960d855f2fe679d588a02434856b36bfd7f7855bb64dbf9aa668b0b855833757a9d963e8997fdb5f4e4240cb4447818055f223605d46ae0697f5dd051ef4973d44405ad46cb7216702b7ff39fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff31269ab2f4c1c53405a20186a186d3b8959a3926b34b7f6cc4c21ab859b1ef6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}}, diff --git a/txscript/data/taproot-ref/2ef7e082ae22ffb03fec01772b442b4b8d19cf06 b/txscript/data/taproot-ref/2ef7e082ae22ffb03fec01772b442b4b8d19cf06 new file mode 100644 index 0000000000..9b1c2870af --- /dev/null +++ b/txscript/data/taproot-ref/2ef7e082ae22ffb03fec01772b442b4b8d19cf06 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709100000000dc1650da8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49c000000002a8e0ff10207f94a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac4c010000", "prevouts": ["a0e70f000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "e1773d000000000022512015f6c01f4cbfbd03849fbcce8a636b49e5c18ed85b3712a10e7757f33687c2ef"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["510c1e0f8d8b217fd756cabc05215322aa202163430f2f8105d26396dee19e42d90269035be717393da60ef10270371fdf81a676ad2565380f0b3ac4743a35e5", "6d0445e6ed41c5c1da464b7f69f42c82e904b2019baf9b4c51e22d2598834b0281e418155c336f14c44c8f3e610bbe1694afd26681dcf4c5ed133bc33b9bdf33ec046859ff8bb26d477103dfc106611656ac4e7934ccb0ef45234d9ee840aade4ecf20774557cdbcb815f8fe171f1aa45cf7f3118ec3ba95860df8e3edc54b6e62af3c455379037a790ad462353c453dc44683bbf866ab7544fd983e306393e04dee9f47fded02dee1385ba9fb748aa071a845afba4227a84f1968a87152456f36acfa0f139e15a069702ee81086", "75005a0442c44132ba5a880442c441326e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b906ec0996a27a0975ca1985c3441f930e18c0e7161e7296b2172ba13341a453ed9bde459cc607f90434bb166d3ec7e209748081df0503bf0c893b2c05cc89025a4dc0c0ac06154f9e7687d9626a71c4113e7b04462405ea5030300b68649b1f0000000000000000000000000000000000000000000000000000000000000000059c97f71763205d37447d77b9481b0229f316e3ea169182bf6c4442799784c7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff47cf94f4ef9a81243015778337beed47d770b1752496c8cb43e14c8f5618d03d2bc023c1a5426b30f2d3ff8ee18cc79337bfe63f8c21b48063f56145891f3fca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c375f9cc4863b77509f570dca37c6f1b0d5780650bc90808dfd966172f0aee314f5e7eb28e29b8f9711d97c5f67205dd5fe5bbccf6c4613c0584d22b427a8640aabee78f518d567a56310fd35e88b053b233b8d53d9a84463c19e404bb93219402edceef2e1cfabda82014c15520265730051f3e196742b5d6f980876f86c9e0ae5e6d1fd7a8aed8617495055bd2756aae86b051d9a7e64aac892410fec9828e7797c85ea40021e6370c6b1247ad96c868ecdfa3b3a09bd1641a75386973b59341bdebd50e1f93218ba374debfaa394f619fcf8ae3e41d68756f77be2b559bc94441bba5950973255a390573b21bbe00a5674bb0e3d894bcaefb4c3f152b2726163d788cc5b2733f8152907944d51204b8abdbe76babf05a395a66a40853220ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90c813b07f3f1e589da2b64465f5fb1c84207d13e616b780826015634f93fc1e419707835256302027c307839e60ddd33a9e3793eceb5c69ca5de22c3ec7bf1616277b9d794c4da0026826782b9260bc2c5379ad6ca693f2d617d559d14a26d6999f00734e9389dca8a9e0ac79833afd33dbd044f69b9b2f9756073ca40fc68adb4bde35283173c269b9673926dfd4351a41d94bedfe523aa26cf069308f577bb0c4f4abba38873964205ff1d891dc324d4591b57c4a9c340da8bc3d8c44bf70f0044922f9c552d236346e932fecdb9abc09fcca6459ee447e7305a9424a0b2ba5760cebbc9e519407c295cf85190c31a45326db562081ca53d2fae07679ee6b5eef6b6ff377c7de10ce1ba4352a612be67f4659b90e3742fedec162eb88f44d0e123e8578004adb49aa2263493fdbd7312ffdb6a7fbd1359c2f7d39be43ed28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000004d631c01803798834ea281dc818038ced54754a8b054812e7806a5fb63db7938ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff79b1fadf47789fa69b12fa81337fb4b9dd503dce04e753e29a3d7206030d04525f492a57ccc8ad78d7af544768e6566d73c807bdaada390521b09849d35ea4065b273116f990e14ba6fac0a194be232846a2032257ef8650eba772493728d326ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6ac316cdba4b9d7b340a3e93390a9e51ec7177f56555b1d4dc81944c73c8ecce1ae75ef58286acd8a78947a6fafa96fc79935ac52bcd399d90cbecb897dc7b6f7042d8ac5bd990f5d2df14977d954252a3f4f4425ce1bc99b5d9265d4efbd9d0b8257ed0e3f30076c4b54ba89d76d013d6d5236b4d69415aa5e149fd07f4f00d73350118db15fd4ff62db868637c7de74e18c9aefd9ba6de3c725b3cc59f7697156f40401f7899f325f6dc9468a0d060e00633a197fb96df82f14008184a5d4588bdc717d62e02543ce2019c521db22f153f5b8841108263722c7519285dbbc4cd02a9c11907ffcb18eb5f628354a8c9af9826c0db1fd222186714cae1cc253b875c7b0575481d1a3e533be752b0daf9f6833f7692903e4fc2a5739b84cc02900000000000000000000000000000000000000000000000000000000000000000e01323f29c7b82c367139190b7256078a65437ac9c1e5b9be7c8757a8d44b35842149120a20b2140e28a58f57441ba66e856a33970815631a877f98eabd3eba62c8a64e994be5ad8cc3e9cf8b9d462624da81e70b2f4fd1530d4696cc35acaac703f40116c3b2be49cbe8ade195aa4cc6acceefdc8f2f440ff172be1cd11cb5af24b2ad4e0822adb5846ad68af15b9564ad0aa903f9c68df6b404fffd75b778c8c29a418bc316fd8ec552fed778cdb4e130d22016e0f635fc1e2574b4a968ecda5b3470ee859244ce0038d539bcf90d82d1b7197cea53d7cd98927fe6f8606ad13b28a1ccaaf76512e5c97384d28634a5b8e07fc6fc88fdc219c7c092086e85c00000000000000000000000000000000000000000000000000000000000000004bb364304e2c3099a14595ae3783d99484f261cdfe8ac1c9c9dd8b044bf5af1d52b7ec58a6a31e86ae468579508ef8fafa8494ffb501d58ff7ba5c1a78aca03dcbd9580c456a23201881183c7e6b1555cadf3970d6fff3c1cfc0b0595db6de43e2c17952118e3c3246fe40c3b1763b09f2edeb999caa3d3ece77a6d4f55a212ed5628b648990c536feec6bf6a8f73e0b15722078452bdd040303a20a2c811a70fe48df9f8a53f3566aea507ede96dfd2625a6ec6324867decb474a58b9c3ee75bef0b20a924b0cd13fbb6994ea19b989a9f39e3df3da9d8c872b89c3ae5d361dab4a16d574dc9db1845ed073394ce0cb48b070edfe6dbe86bbb4ddde28d5cc9fe4992cb7cc97f08d79e521194394e42f8abbeedb693f4f361c7db176a82f9afdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9657e34068c80a6680e7119262cf52ba3dc579df242c970b0bd27f0a8a0ffda44d0c46c25e493f8fce00c2f165dfdfd6cf7d0a4c376edb382cd9c314f462c2be026ab7db6da46baab1e5bb55f3fae0a9dd11ee926938172a8ff968bef78ffabd0d8e26e0f044d259b44f24cca1c65b6706f084accd8a9ebcc99640c4f7d08729ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5ea263b7d84a27d6fed4a9d6fe8b2108bfec7a471bf77ab3aee6e1979a7d8feef8ef1e99aa602ab3d345c641a79704c3af9569ae0f70a112968822bcc00b328b296e20f25e5000731149e4732b9fa9925eabf3bebfa1d94ed859a8ab12380abb81d80235fe722b9bcc985edd64c98dcad858552092ba23674447e5001870af92c670689bc281bd20293ff9cc8b810cf4b9c20e94c1271e53591283558093c90bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5a376bb2b88ab92a85b954d3d7d3b304933692d788a3dafeb6c4ecc3c561e1f5cee81e4fdef3be738e703a40bfd998df6e9bc90f5e8940a45aedf471a2e40c34f6d6b80393fd2bdb9ac4ec136c87a91e993dd01d266f1d2bf55075e4786afd4eb57cbebb951f85cf2941f373516ba8a56866cfd4d747642622e6a41612781a81bfa9a3064581607042502d5c27f480e6d9b42e285c2f88a5b0977aab1964f19bbde0c206cb8ecb6ca3cb7bb40d78d37c0768b67bf8776de7d3afadca0b1f407a941185a32b56822e84ef9f50d906dc4ce70c6dd202ed2bfc6b1e5f4d0e932a442f2fbacb2a630fb5a9638cc3fe2d350f3675a96fbd38cef95881f33ca1655a188ac3ac1622a9e48c57a993a505d716d5cf4f1250ede35bd9116bbf6afb568baa557f3f4e91b0c33878ec28338679e25b262ce969651876ca1a2237735e408d47", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["510c1e0f8d8b217fd756cabc05215322aa202163430f2f8105d26396dee19e42d90269035be717393da60ef10270371fdf81a676ad2565380f0b3ac4743a35e5", "7a07b376cf5ef72cc8df6adb062da0eb0c3ab296cca12d495b3ebd443ce82bdd1f1a7a2a4b5fc72ec2bef62e1a636cb1b35f1b8de7d15eb7207cb6b4efbf4610f3f54b151d24d008cad4ee2b3fc2f61b4d20458bd4e08fa1f6c76f3a1e469dfbab887ae1aad4218e171619eedb4fef67a549828c5abfb1da5cb121d9704b12628867ed6578519321f2a883f87ea3440377f8fdfad4036e0c6af352612a29c42de115f6909791caa5e9d6388922a224777fc47ce672e8021a7656ca7d1bbb69a65d6108f794d91c633741e6bec9", "75005a0442c44132ba5a880442c441326e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b906ec0996a27a0975ca1985c3441f930e18c0e7161e7296b2172ba13341a453ed9bde459cc607f90434bb166d3ec7e209748081df0503bf0c893b2c05cc89025a4dc0c0ac06154f9e7687d9626a71c4113e7b04462405ea5030300b68649b1f0000000000000000000000000000000000000000000000000000000000000000059c97f71763205d37447d77b9481b0229f316e3ea169182bf6c4442799784c7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff47cf94f4ef9a81243015778337beed47d770b1752496c8cb43e14c8f5618d03d2bc023c1a5426b30f2d3ff8ee18cc79337bfe63f8c21b48063f56145891f3fca000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c375f9cc4863b77509f570dca37c6f1b0d5780650bc90808dfd966172f0aee314f5e7eb28e29b8f9711d97c5f67205dd5fe5bbccf6c4613c0584d22b427a8640aabee78f518d567a56310fd35e88b053b233b8d53d9a84463c19e404bb93219402edceef2e1cfabda82014c15520265730051f3e196742b5d6f980876f86c9e0ae5e6d1fd7a8aed8617495055bd2756aae86b051d9a7e64aac892410fec9828e7797c85ea40021e6370c6b1247ad96c868ecdfa3b3a09bd1641a75386973b59341bdebd50e1f93218ba374debfaa394f619fcf8ae3e41d68756f77be2b559bc94441bba5950973255a390573b21bbe00a5674bb0e3d894bcaefb4c3f152b2726163d788cc5b2733f8152907944d51204b8abdbe76babf05a395a66a40853220ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90c813b07f3f1e589da2b64465f5fb1c84207d13e616b780826015634f93fc1e419707835256302027c307839e60ddd33a9e3793eceb5c69ca5de22c3ec7bf1616277b9d794c4da0026826782b9260bc2c5379ad6ca693f2d617d559d14a26d6999f00734e9389dca8a9e0ac79833afd33dbd044f69b9b2f9756073ca40fc68adb4bde35283173c269b9673926dfd4351a41d94bedfe523aa26cf069308f577bb0c4f4abba38873964205ff1d891dc324d4591b57c4a9c340da8bc3d8c44bf70f0044922f9c552d236346e932fecdb9abc09fcca6459ee447e7305a9424a0b2ba5760cebbc9e519407c295cf85190c31a45326db562081ca53d2fae07679ee6b5eef6b6ff377c7de10ce1ba4352a612be67f4659b90e3742fedec162eb88f44d0e123e8578004adb49aa2263493fdbd7312ffdb6a7fbd1359c2f7d39be43ed28000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000004d631c01803798834ea281dc818038ced54754a8b054812e7806a5fb63db7938ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff79b1fadf47789fa69b12fa81337fb4b9dd503dce04e753e29a3d7206030d04525f492a57ccc8ad78d7af544768e6566d73c807bdaada390521b09849d35ea4065b273116f990e14ba6fac0a194be232846a2032257ef8650eba772493728d326ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6ac316cdba4b9d7b340a3e93390a9e51ec7177f56555b1d4dc81944c73c8ecce1ae75ef58286acd8a78947a6fafa96fc79935ac52bcd399d90cbecb897dc7b6f7042d8ac5bd990f5d2df14977d954252a3f4f4425ce1bc99b5d9265d4efbd9d0b8257ed0e3f30076c4b54ba89d76d013d6d5236b4d69415aa5e149fd07f4f00d73350118db15fd4ff62db868637c7de74e18c9aefd9ba6de3c725b3cc59f7697156f40401f7899f325f6dc9468a0d060e00633a197fb96df82f14008184a5d4588bdc717d62e02543ce2019c521db22f153f5b8841108263722c7519285dbbc4cd02a9c11907ffcb18eb5f628354a8c9af9826c0db1fd222186714cae1cc253b875c7b0575481d1a3e533be752b0daf9f6833f7692903e4fc2a5739b84cc02900000000000000000000000000000000000000000000000000000000000000000e01323f29c7b82c367139190b7256078a65437ac9c1e5b9be7c8757a8d44b35842149120a20b2140e28a58f57441ba66e856a33970815631a877f98eabd3eba62c8a64e994be5ad8cc3e9cf8b9d462624da81e70b2f4fd1530d4696cc35acaac703f40116c3b2be49cbe8ade195aa4cc6acceefdc8f2f440ff172be1cd11cb5af24b2ad4e0822adb5846ad68af15b9564ad0aa903f9c68df6b404fffd75b778c8c29a418bc316fd8ec552fed778cdb4e130d22016e0f635fc1e2574b4a968ecda5b3470ee859244ce0038d539bcf90d82d1b7197cea53d7cd98927fe6f8606ad13b28a1ccaaf76512e5c97384d28634a5b8e07fc6fc88fdc219c7c092086e85c00000000000000000000000000000000000000000000000000000000000000004bb364304e2c3099a14595ae3783d99484f261cdfe8ac1c9c9dd8b044bf5af1d52b7ec58a6a31e86ae468579508ef8fafa8494ffb501d58ff7ba5c1a78aca03dcbd9580c456a23201881183c7e6b1555cadf3970d6fff3c1cfc0b0595db6de43e2c17952118e3c3246fe40c3b1763b09f2edeb999caa3d3ece77a6d4f55a212ed5628b648990c536feec6bf6a8f73e0b15722078452bdd040303a20a2c811a70fe48df9f8a53f3566aea507ede96dfd2625a6ec6324867decb474a58b9c3ee75bef0b20a924b0cd13fbb6994ea19b989a9f39e3df3da9d8c872b89c3ae5d361dab4a16d574dc9db1845ed073394ce0cb48b070edfe6dbe86bbb4ddde28d5cc9fe4992cb7cc97f08d79e521194394e42f8abbeedb693f4f361c7db176a82f9afdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9657e34068c80a6680e7119262cf52ba3dc579df242c970b0bd27f0a8a0ffda44d0c46c25e493f8fce00c2f165dfdfd6cf7d0a4c376edb382cd9c314f462c2be026ab7db6da46baab1e5bb55f3fae0a9dd11ee926938172a8ff968bef78ffabd0d8e26e0f044d259b44f24cca1c65b6706f084accd8a9ebcc99640c4f7d08729ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5ea263b7d84a27d6fed4a9d6fe8b2108bfec7a471bf77ab3aee6e1979a7d8feef8ef1e99aa602ab3d345c641a79704c3af9569ae0f70a112968822bcc00b328b296e20f25e5000731149e4732b9fa9925eabf3bebfa1d94ed859a8ab12380abb81d80235fe722b9bcc985edd64c98dcad858552092ba23674447e5001870af92c670689bc281bd20293ff9cc8b810cf4b9c20e94c1271e53591283558093c90bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5a376bb2b88ab92a85b954d3d7d3b304933692d788a3dafeb6c4ecc3c561e1f5cee81e4fdef3be738e703a40bfd998df6e9bc90f5e8940a45aedf471a2e40c34f6d6b80393fd2bdb9ac4ec136c87a91e993dd01d266f1d2bf55075e4786afd4eb57cbebb951f85cf2941f373516ba8a56866cfd4d747642622e6a41612781a81bfa9a3064581607042502d5c27f480e6d9b42e285c2f88a5b0977aab1964f19bbde0c206cb8ecb6ca3cb7bb40d78d37c0768b67bf8776de7d3afadca0b1f407a941185a32b56822e84ef9f50d906dc4ce70c6dd202ed2bfc6b1e5f4d0e932a442f2fbacb2a630fb5a9638cc3fe2d350f3675a96fbd38cef95881f33ca1655a188ac3ac1622a9e48c57a993a505d716d5cf4f1250ede35bd9116bbf6afb568baa557f3f4e91b0c33878ec28338679e25b262ce969651876ca1a2237735e408d47", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/2f1b30aed18276568d11bfeb997aac3246d57017 b/txscript/data/taproot-ref/2f1b30aed18276568d11bfeb997aac3246d57017 new file mode 100644 index 0000000000..805e36395b --- /dev/null +++ b/txscript/data/taproot-ref/2f1b30aed18276568d11bfeb997aac3246d57017 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41102000000869367a3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cef010000005d951084021acb7a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2b040000", "prevouts": ["86fc330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8835490000000000225120f42b54ceee5422b98931ba4e4259b1fe0b973d9efeacc7f6f710ee118b027bcc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_5d", "final": true, "success": {"scriptSig": "", "witness": ["ef072dc73a2a7c85a106da40cf4350988ada5473f81d7603594996251a4416008427c03b27db4546a392e75922a74ff451367c038407efd2a1783038d4cb36db82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f2f50a5f3eb4ce4a02b45f364fd2b28078d73058b45b484461b8197429502f51979e7a9bcf9871a1ab468ce8e6583e66729b4b4414bb01229a845f3fbcab6a965d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/2f63727a65eb7f7437ab5c39d3f16671518719e6 b/txscript/data/taproot-ref/2f63727a65eb7f7437ab5c39d3f16671518719e6 new file mode 100644 index 0000000000..8bdc5b930d --- /dev/null +++ b/txscript/data/taproot-ref/2f63727a65eb7f7437ab5c39d3f16671518719e6 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b12020000006f9651d88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42401000000bdfd4f8d034fab5c00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ae07c92f", "prevouts": ["8131230000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d", "82de3b000000000017a914f7f3eae48087a4952a984cf9c1f2f12f8785754687"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2253202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["b076743f1b381298fdeedecca24325f7eaa6406b4cc4a9bfb03a0e98be4f2a0fc74c1ea328c89447c37cad026f943ca4e340bb957d3da66003882909baa9a2a3", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/2f6a3e29b8be29ea5949fb1b5a71679b5cadc8d8 b/txscript/data/taproot-ref/2f6a3e29b8be29ea5949fb1b5a71679b5cadc8d8 new file mode 100644 index 0000000000..e74fc756e9 --- /dev/null +++ b/txscript/data/taproot-ref/2f6a3e29b8be29ea5949fb1b5a71679b5cadc8d8 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2100000000d30a43ec0156331c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75c010000", "prevouts": ["bc6f2600000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["cf", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365e0e9a175fda05a064c52eebe8eea391232a608d343baa66a1ca563d1b6babca6a7a52674f359a7dbed67a49e09732132053a9cde77eaa564fdce3cafe7738b9f4a62e14d7fc4acbfb0196ec29a60565ac2b3043dda4cedec8cb1ff291b90d41"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ba852db044cc7b3c6c227af3aa09dc9e9bae5367030e3f2be29afb15f97933d48121d7901a27ea565e1cb6f91818c43a3dc8f46dc56db80c8bd3776430739107a653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}}, diff --git a/txscript/data/taproot-ref/2f718ebe5d9460ba98f7815e59bfffe1cd1f3bc6 b/txscript/data/taproot-ref/2f718ebe5d9460ba98f7815e59bfffe1cd1f3bc6 new file mode 100644 index 0000000000..feae496f4d --- /dev/null +++ b/txscript/data/taproot-ref/2f718ebe5d9460ba98f7815e59bfffe1cd1f3bc6 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4baa01000000f77c2d26bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0c010000004f4f1f22031457a20000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f870d020000", "prevouts": ["3c312800000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "f4397c000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100feac6a621889f11528fe75f4f1ed3bddc4a3405cafd8e83304097686bb18065a02200f488a566cdf0c26008250132586eb44338afedd92e69b3bed54f457082215e783", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["3045022100b64aa1eab2e13c30e201a02745d52123ef5e8190d2fa4aab4cd2164cbbd39b3a02200e621b908bedf7c40b1d3b4dacfcf51a36685bcb35b59a13dd6babca9985bad083", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/2f92c5daf5b1fc8c65563916bd77ad58dc8ffdab b/txscript/data/taproot-ref/2f92c5daf5b1fc8c65563916bd77ad58dc8ffdab new file mode 100644 index 0000000000..60379ef0fb --- /dev/null +++ b/txscript/data/taproot-ref/2f92c5daf5b1fc8c65563916bd77ad58dc8ffdab @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cea00000000937427d7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5000000000476245d802ecc273000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689870d97cc2d", "prevouts": ["dbfa5400000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "704f21000000000021601f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["b70ef45802c64d612d4f6b57535e50f9dace6e6750abf4373a4664a19d391d8100d29199118100e3759d96e740f519cfa6949b6b04e1bcc8910c672cb0c9dae9", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/2fc6756b64916b520df4a5d7eed9bc7c1ee85753 b/txscript/data/taproot-ref/2fc6756b64916b520df4a5d7eed9bc7c1ee85753 new file mode 100644 index 0000000000..5bca4401bd --- /dev/null +++ b/txscript/data/taproot-ref/2fc6756b64916b520df4a5d7eed9bc7c1ee85753 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d00100000061bcd71c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46200000000492c8d5abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfde0000000026f8a34302b303e60000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87ab000000", "prevouts": ["6f8234000000000021551f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "b983310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c2d5810000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "a37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365aa5ec3a6d8c57772d2eb4e1b20d5e63ae42b9b99b4ff5e41cdc072aa2de00e7fd3695492b964dfcc45d3a474d456ab4db8430bda5885b2eccf08499e11263dad2054b94cb6efba565738f5dbf6ee5a67458962b65d77e1cf5e0d2c1c00b2210"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e2798fbbca1809bcbebf31f88b6105e51fb6f911c134cbc99a44881a528cc9462f8f33b00019c5a92b78a4d0765b6724114f5676deb8014962e3b41b4c6baea3fd3695492b964dfcc45d3a474d456ab4db8430bda5885b2eccf08499e11263dad2054b94cb6efba565738f5dbf6ee5a67458962b65d77e1cf5e0d2c1c00b2210"]}}, diff --git a/txscript/data/taproot-ref/2fe9ee314e024619b228c81cae27f4bd50141a36 b/txscript/data/taproot-ref/2fe9ee314e024619b228c81cae27f4bd50141a36 new file mode 100644 index 0000000000..65bd8737d1 --- /dev/null +++ b/txscript/data/taproot-ref/2fe9ee314e024619b228c81cae27f4bd50141a36 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a400000000bf14df5cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c000000002070b123bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd800000000fbff2f2002a8abd800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac05ebd32a", "prevouts": ["79d30e00000000002253202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "5ed7480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "853c8300000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "", "witness": ["3045022100ca4097ba1ea29a4ee74a221595b6449bedb0d92abba7f8b35c74513cf44e1c2a02204f902eff652022536de3e104a7dc21c344778ad6467186ea9eefb567c7c7e89c79", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["3045022100fda831829ec294c3db692d9ced24cf52132b6b02cffd3ce55a28a4e4b80cf34802207626f16e69deb1ad1817bb0ff356ba239b98c4b2d09fc099556a48e95bceae8579", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/30060e7ffc388552b8bae73eb28705b637f7685a b/txscript/data/taproot-ref/30060e7ffc388552b8bae73eb28705b637f7685a new file mode 100644 index 0000000000..b30890200c --- /dev/null +++ b/txscript/data/taproot-ref/30060e7ffc388552b8bae73eb28705b637f7685a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4f00000000aace61d9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4101000000718e46cd01acf570000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e4000000", "prevouts": ["a9c1470000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6", "1a5c710000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090201db07837861b034233f77b3111e4d0454df87e2a2ff67ed85311b71b4f71ea984ee7706783d1d8d901af96336562e8d9b681366f75181d5b5bf5c203b439bfb74691dcd2a3d862aef8ed868371cb201121c920928376a9c354e2164985dad9849282ad32fde8e834e8c0c85492fe0deb0e7f2169ec2f85c6d1bf5cdb80a4b58840f28885f5c76e6f722a85d7140cbdaa3e1bc80d8e92b5143fbce25d74f701388c01a3c150e337cec29f3a5da355215983936b2fdd1455c0a1386d6986d1d7d18d693b6e11da7b611b0ab4b29da5754091eb40f7ff0ee22228eea77a94b059e16e9b8bf1a8eed0acadc92f96e2e1dfe4e7d03b67dd0395550a02a74dfa2d0ad8ea3a1cce721cb512bc800cd4b3faae00ed5d644fc9a5f24194461db2726e8dbae3b8a4841b4b57177c0d020e8d80d5f7037a7e8131d829c473db5fd9661dd1b324f4586f385d8e5436a0eea158b3ec52b488b0ef6124eca6362a614ad4aabe08205e40023becb41201eabaf64a22a43f5852d49acab49037919da7cb246ad532bce07c2f5d9cb3db3fca631f5a47a1bb3deb6f20c979d8fd09d90fe1224b44cbfbef283968d9741dfee1e94abf7a91269f12153db64d4a52f9fc78f181ed31d472f3c4a5b066eb730503906bf339dd1b1a8ff8a0c9422d622ac14655cdd5e838696a3437b56aa1b4c7ecc259f8ed6b7bd7ffd6e7e1bda92f8d7a9bec94c12e25929a0f4e083687d3875", "4a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a5f53a99550b57470dcc4d4233d312935e71f0fec8998bf9150bf0a5d1b49a4615c38a9f4b3c26d8dcb1a4c3fc9e68202e120a4fd7f06c3d33071ff6316723f12efaba1d06903f148d2465ca4e4c6639d336576fa6993c6ca48823372648a44"]}, "failure": {"scriptSig": "", "witness": ["4d09020117eafd078d9fdeaf63cb3c5977ab805a9f300e7ccb7d9e91108c18403445bd9b2108817b65d5a42e26389c75ad57668db05f829fc02daf8ec0d29b43a1de7d5036efb52c810bfa4e4bdc426e4e6c588e21ede5fde6f02bbe46f4843ecc5e61278695182541d856245fa73740b4a9766cd7f1f4dd5a9f68de74961e162c9a7d22366abfeda5fefa1e12fcbb6df4d02d38ba18fe8f065e2c87c5ff8662d12fe973366a03ebffdc472935cbc4c3995b0ad24b4ebe994a165aa62051e01d9823ac27c5e9b15f8f84e42fb45cd8b410dac23725a24a1d098537f081f4b105505850f8a0682dde64bbb4f2929814a1a4dbaad8e421d073a6a993a28cf27ef01f9b6c4bc705f5202cb6903d70c49f41b920178a4860cd1f9ffa7c5795de2648d218ebaf2adf2bc9d61d3a9e50345521bbf48d4fd735498cb06b7aaf2f9ea8dd410187653cef74f53582679eeb953c5e4df4c8dd7327b9ea1a0227bcba1532c3ae35a31b86a93017ba63200e30bf7b1969ed2b1e23759ae8ae4661d748137e5ffd796b0f0121ff9d8e106f6d5329ae8596596a21bda2d0b2a231096c26bd9648dd2c4694f514ec13cbbc7a4577726ca5d281301185a94aab801ac722f1df73cc8d9153c1866114b94e31e919d23ab8c496700ad76587a92d0b4da562849b7a6e5eca4ea48fbebd061fec5f4745b27baa51a76187bf7863a0b7887b713c57ad51403b81881582a36727b6f85975", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93649ae925491555535d3452d6a0c9675b1c4c853a5ac96d8d917c8f686b1ab70deb1956d2c402f72d86d9128969f4c9ed8db93dfb826b4075483e7d557b0e234b512efaba1d06903f148d2465ca4e4c6639d336576fa6993c6ca48823372648a44"]}}, diff --git a/txscript/data/taproot-ref/3012845a3aa7dc757cc4778e5334769c9239ab60 b/txscript/data/taproot-ref/3012845a3aa7dc757cc4778e5334769c9239ab60 new file mode 100644 index 0000000000..0beaa68704 --- /dev/null +++ b/txscript/data/taproot-ref/3012845a3aa7dc757cc4778e5334769c9239ab60 @@ -0,0 +1 @@ +{"tx": "50f7ec8e0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706701000000a45b1eefbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb501000000d4e342ea0211518b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7bfe0a757", "prevouts": ["10c212000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "41977b0000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063ce68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a6a38b8d39a057b5d03cc3fb1c5a8fc6fbbf2afa69d215fd7d0ba06cabd825c0959bd9b34bb85690c892593228383c48f2c7a3855b4947a3dd1708d13c567655d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368cdeb0de8daf44e986d19e114a7b8ed70d46e74ed21bd6c6e785c2a6747f82dd5067193501824fc7e1f7f904c1e32fba78339d7701e72316b16feebc15a414abab692e734634bfaf43d653c1e6f6d8e8d14797d8e4fda7a04cf5eec270202b46d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}}, diff --git a/txscript/data/taproot-ref/3015e994a3e16567397bea00a92ff97eb53971e6 b/txscript/data/taproot-ref/3015e994a3e16567397bea00a92ff97eb53971e6 new file mode 100644 index 0000000000..b1eae3b0e6 --- /dev/null +++ b/txscript/data/taproot-ref/3015e994a3e16567397bea00a92ff97eb53971e6 @@ -0,0 +1 @@ +{"tx": "dac681e501dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c250100000096d7d29903b4354e000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4766ee20", "prevouts": ["555d500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_6b", "final": true, "success": {"scriptSig": "", "witness": ["60e41b643c1c904eb42c536554f629a5a90730108f3c3f64603aa691fe7e5970c00935965378e91a47e2c720dc2d3595da65f1f42a9a0462503c0ff9dcdb25d702"]}, "failure": {"scriptSig": "", "witness": ["49a0de936e7821d3f58fe5e59c6ce0da34ed62280bcddafe5a9927c420bebd82d83dcb74aec03bac7391e2554da15a352cc0c2cf9ee6d51d1cb07c41844493d36b"]}}, diff --git a/txscript/data/taproot-ref/3031aef9ccb0cb566246e72e7f976a7cf00b9898 b/txscript/data/taproot-ref/3031aef9ccb0cb566246e72e7f976a7cf00b9898 new file mode 100644 index 0000000000..7d73329764 --- /dev/null +++ b/txscript/data/taproot-ref/3031aef9ccb0cb566246e72e7f976a7cf00b9898 @@ -0,0 +1 @@ +{"tx": "dfd2e9c702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3201000000e75193c860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c6000000003e731e9f04828f2e00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7eae9964a", "prevouts": ["f48f21000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "b6d40f0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "5e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bc10050415f3a7eb0f871e59844dac39a9eb46351c529a41184ff4a5bf872c5d7bec169038f6fbc2f311373c62d75738dee89ed934d1dccaea4579b1c053aa90a9249c0485c0b349be2068ea39eda6d50f7b6c474a6d5eb714296c91a9f24b9"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369fb909a8cefef27cda8d32206876bbd59a602541b1ac02e9aca8fefecae353d965cca6be1d3cc9714f9205dc72257def63c8e50f66dbe399f94c25bd2c6a85f30c8cbc16505271ed8ce1a03d67d2c4a35529bcf4a25ace24696315022c27c9cf"]}}, diff --git a/txscript/data/taproot-ref/305b7d52e8b2e5b62f366d1fe9aca1b4c31a2e51 b/txscript/data/taproot-ref/305b7d52e8b2e5b62f366d1fe9aca1b4c31a2e51 new file mode 100644 index 0000000000..f85b1bdac5 --- /dev/null +++ b/txscript/data/taproot-ref/305b7d52e8b2e5b62f366d1fe9aca1b4c31a2e51 @@ -0,0 +1 @@ +{"tx": "b4abf2a802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4baf00000000b44aa8a6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7a00000000201254d604ccd0a80000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a64c020000", "prevouts": ["87bb2600000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "998a840000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090205b8b6acf2a1736dbbaad48ee9d1f6f76f614fe334d2d4879607993100e97cebf90f59892e8df71e7d72827181b3718731fe8058f38f7664fabc855eb51aba6033d063f287d5e4c5795ac8bec57a4beecca7a88847dc99b5c7eaefa8d86be802e14836dd6187494d9d13a61270da2c2383c6a220b70dcce96f0b1ba7459e000fdbba556000c7959d9e25920717d1c39ac30a566db08dcf50a07bc4de8e0524f1a2a6b70fd03e10cb93afd59ee586f5e6efaf5337ba0ca58312824fd43a122ba9070fe087d868f453c6eb0a7ed7c4e5577fdef88af88fa979e473b449d92ae10268368688e754135412dc955f350514dfac3bcdc1126aa2363d8cae0e47f64bee1fa0712f8690d4728c733c85f5ecab2cf9a24eaa28c419cbc1765f948b59e92e7ab0bef423c49e113c534f8da1fb40544142f0ec513a15df5eed3378adfd6d490daecde5a624de508575880aea484ef4b5d8285a1f7ae764d201a4774acb96b96725e9859bfc095d89bafaab1189529362c2d7dd8059773d475f3e716733522911c7cb1f2fdb0cebbeb3d092b1aace46c3f0e98c4477faa239288141db3403ee4773583f0b87f64fc948345ff73c7a471ef5875bf5fe56f172d8c24beb3e29fd0d141256023bcf7cfa2e9ec870b56018ba2f8abf16c603c42491aa870dc2b7ffc3b58af172b7a9ae7e9d822dc05e310b666926b4b35ea7e2fc5d5fae2323fdf10ff759e5beaef0cade75", "487d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8fbef2b09bb3fcc5f7a097fe825ffcbc345a4a7607f02adcd9241733378f6a21f7da89940c9c2be3d3cb1ea9fc374137a74dc3bafe909c68993f298761996d666"]}, "failure": {"scriptSig": "", "witness": ["4d0902e08d56acc221f3c5abd5a672ced6a3b82aca76c67152e71330aa040b6999e65de00b8354a22a07efc36182e2584ce94cad2b7ccae8baf249ae1513e5462eca0736e74e77a052e819f3d5af896d9d50a1fd44ed94bd223b9049c0226b80887cd71331be18a236d77a14e55e5a98ac2467dd4f7f7b7ed938b47193b21fad48c479dd40447a3d304afa0e5c628a2e1b7823a0b4ff442c663583edeb1936652db22a04b18e29ee5bc2cc55f47485a530a7c0a6588c4d0e6ef380f39832a7c1a8525b322784ccf11452ae91acc5d2ac27c4ac6e308a1b31139cc3cf64546aeb61b6fcb1e4b3907d0fef12dc7370f33523ea4392a3731b5861d8efbbd7b4015d3fbd06bb5ee79df526d0c0e9de9dc93183fc6f7971abe2005ecbe6c69e3640920c6a7f56921335ebd25f8bed69d285611b4c818ef3ff48645dbbe1206040e556ec60813a4bca11431e39e00cd6df4a9db07bbd5d949aa4cacbdbf4f8aa5b87a5674882efa72c5c7275c488425b9223900fecf5898853c227fa7842fa929c9190bcf71a4da602eef272702ff34ab9ba2b11d48c2f31241718f2a55a8ca4cb3b862f3019d0972d31c4b501ba29bffb7de4fa5674ba56abad00192d6371d727c1396a5a352a87f4facc462f7ef79705e2c97aceb3f2c04726793897d4a531de7cc40b8545ed67bb1e63a4cb79da4a5f24a891a3afdcb4d508d4907d795210c6f881cf463c00f10e2ea87aed248275", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365c9fca99784b9d41e6f6eaa8a610ad45ac066af872a8b7bf7b421736c80a55bc4d178bbecd44a62a975bb89c44ce69c4bec935ce63261f4a792ecb896593fa3c40210bd7db211b82a407c19f9567cde5a01f8f2a3c3dc032c7ac21169de78447"]}}, diff --git a/txscript/data/taproot-ref/30733f314d77a04fcfb55b009f72a5a1a94cc1e5 b/txscript/data/taproot-ref/30733f314d77a04fcfb55b009f72a5a1a94cc1e5 new file mode 100644 index 0000000000..bd15176363 --- /dev/null +++ b/txscript/data/taproot-ref/30733f314d77a04fcfb55b009f72a5a1a94cc1e5 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c63000000002fad8be6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9201000000a4949ed304f066a70000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcffb82f2d", "prevouts": ["8fae510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5ed3570000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_63", "final": true, "success": {"scriptSig": "", "witness": ["37a9f9ce33791d68a4f828b52443efbb4a63f8857a585ab57799e1527fdcd431fe22aa36e7b3e099442517ae27200a83146a9ac43d41e3ec1ae4504404a3e1bc82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3a76cf09e0dd45dab9531549c859b67bd303eff4b7dd8f85ccf423d229bc1fa7efa2893ff8279b61d97e4e52182b1514d693e262cb63d90faa6e0aa2ae0266bf63", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/312a2eaf5a3bbccf69b97e292f665b53846038f5 b/txscript/data/taproot-ref/312a2eaf5a3bbccf69b97e292f665b53846038f5 new file mode 100644 index 0000000000..25701c4baa --- /dev/null +++ b/txscript/data/taproot-ref/312a2eaf5a3bbccf69b97e292f665b53846038f5 @@ -0,0 +1 @@ +{"tx": "f558c58603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b980000000056c18ef4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2401000000aee696e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42a01000000869aac980117bc3d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdb518220", "prevouts": ["e140210000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "49c88100000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "8e2839000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09029e9fbc43986dfc06ccc27dfc5fea2ca7339b8830f043004f6b89771c0e3fb83d714645fe4d0076702e2b41f08e672c2bf2d40ffe582975e9ed403094effb4aa62e9f4d8cfdf881ec3f2f25df5231caae77cc45f9aabf37281f5c758d8a79245c576453ea78b3a33116a93e1ebc767d0eaa013836d990a609315eacbf6fbe2738aa274af49863273ab305af6a7caf0d58ff24f5074cdc9a0e68dca18706e888c9a10cee3c859bf6767e782eded343112fdb0e4dc6bfe618197a7f0f8bb5658a33abfa6e130432ae67a77cf91f67c9e22538ff726837d818c202fdf8f2fa7cd17e6b80a5595595aac6ca3dda8875128b259deb1f22831f2238091755bbc3246622e6c4d18312e6aae1efd43e1b26f5659f8f174278ea5ce142043fd9b96003e97784a75891a525a4727ef854d59e6cbc00f2d624b7bdc544562f0e42ebc21ebe19725cedbf9e5034cf63fcebd1297e848c7a225695595fe4234961c5936bb65075e7d5a0db3b9337f6d2992ae5b9edc06420d7ca69f68ee7f424745e3a5b95b00ed46c572a9bf0769ed97aa7ec98af2e16bda3e766755dc257a1af915dfcc21402e376d4ecd669c9410f38835a6a3db4ee71aa883deac397bff34c1d09eec4fc1521ed20cf7f7edcdda358d8af15dde8b084ea6ca3f00dfa98f0528549046df091c79d408718a3ccff84d82ca47adfc3a370307c81fde6241ae6a3b314d4cf2c1d9c74d603426c2154a875", "b67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694c0b340583cf13ebe9076e32fe1c03226eaf53cf87bb1d5bdb546787d6812ebca37f8027c2c0b0d436eabba5be8b19fe8a47d5b17abeebfa31c0139f25f704791244d1d955381053a5c36db6928ef13bb9242569ee84b58d7018329936aac78"]}, "failure": {"scriptSig": "", "witness": ["4d09025bf364e9f43484dd5a74e4ee67d8772984549b328dfd37f43cc117b8aa5e8a8a26e43d8b717e7f8ab5985e199c23f11fa41a2ee586133c16a39708d7d863a58a8df54313fc601dff1ef9f32acb35bcec5ba7868cf873e2a9bba9bc970ba3eb4bb571935990924e4040da54c51ea142be5722214f596bd1b51b98d586af75d0dec46d22bbb19272c5fd2f11204d8204a46690eb76019def8b28f08930e6fc6bce5d28af6a74b9492283f3f7958dc5facdd9fd227106ca3dc5cbbdb10083d2fe279815fa066c71498c9d67f4b83ad5069fe1fa818d7a6efd08ea872a95f99a445df7bcb582f0ae58cecc03ff3ebb0e02af229913603b3a451fd7223607fa7bd1fbc52fb75deb9272e474fa8a65d793f9001dfef5e5f0a889051cd357c2d3a1e99f33a4bad065ec3f64fe394d184d816d7c29d9474c78dd47850bcd6327d11acebcb610b2f0d40ffda2b796b6f7fead3070a46680b682e5f7dd03b6dd877a780a30f6be66a379e9e2c233f69d7db4ae3882de3299e2348e4ffb1fe2d88d36d056c096ab5ae85dcbc6651ed3aecd739e0fef5f321592fdabe1c3382da805036909a27f0d721c579bc2bfeefb4e8ea75179be1ef630202972fa11bef077b0712c013d6759354c062748cd35b559cd427759f93d5314c186c0c6a38a112c1b10b53503d4be85272eda3884d96284208d7e96db5f9e1e32470435db03ea42ca031eb545cab114bc871e38092075", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb561c4b1d6688f5bfb11d0986684152459867eeebbedce173d7984e1f333e22781c07d8975c94d77b7f566737b45f640ec74b2b98cad100fb0cff19b6594ed691244d1d955381053a5c36db6928ef13bb9242569ee84b58d7018329936aac78"]}}, diff --git a/txscript/data/taproot-ref/3177278ccbc91f49567f80c0b575882edaf4556b b/txscript/data/taproot-ref/3177278ccbc91f49567f80c0b575882edaf4556b new file mode 100644 index 0000000000..4fff2660b4 --- /dev/null +++ b/txscript/data/taproot-ref/3177278ccbc91f49567f80c0b575882edaf4556b @@ -0,0 +1 @@ +{"tx": "5e99ba8803bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7500000000df8a91a8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3f000000005c7bc9e9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0d02000000a28c08c40314b9e600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75c6ed459", "prevouts": ["48417900000000002258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "685e2300000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "f0a04c0000000000235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["18d74be7b73f4c5ca81e26253f5de705a40a19125516b355c897d2050126cfa62a6728c742eeb80723bd09ddfcc22739bb29d0052bbf4cfd8e4118fed4398e29", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/31a7241822ef819833b51d86a78d83bbb4d58136 b/txscript/data/taproot-ref/31a7241822ef819833b51d86a78d83bbb4d58136 new file mode 100644 index 0000000000..9e62c70afc --- /dev/null +++ b/txscript/data/taproot-ref/31a7241822ef819833b51d86a78d83bbb4d58136 @@ -0,0 +1 @@ +{"tx": "0f23d10e02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0602000000ff1278f3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2d010000005422bc8b0191e85c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4878f7b482f", "prevouts": ["ab6a490000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "388f1e000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "a77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936efbd2f9b1cd4fbec58efe0420f12191abaa855d6729399166c4c2475d9d665e59619a83ee22e28c5507e71eab09869c4e19cd00c1b769e62c37a8de310ec2a6696773453f0744a158be0509abdec64f05b1db7ccf03251d8359952271b442a24"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93625bfac2bef47395f58f992c21945b8909d7652ef3a3903d04cb677a2ce7470d8389e677eaf5eeea89a70f01c0aa3bc14cf3320f4b6dd8cc61f33138af3398b5b11a008161139ac7a92b00665158d25501a881aeebdfdbf881ee45b85e0726c11"]}}, diff --git a/txscript/data/taproot-ref/31b4933ee39bc4133c6a36b1e309775c87a96c23 b/txscript/data/taproot-ref/31b4933ee39bc4133c6a36b1e309775c87a96c23 new file mode 100644 index 0000000000..d501475d3e --- /dev/null +++ b/txscript/data/taproot-ref/31b4933ee39bc4133c6a36b1e309775c87a96c23 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707800000000d472c2ff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47e00000000b22608f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbb000000007c5fb0ca0254669200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8e01af3b", "prevouts": ["ab600e0000000000225120a2c28b736583e5896e4a53bfde129100bff930ada42454ee2f7bef5a60a371d8", "deef37000000000017a914c7d65cb5025eac8b5bf295baac9287994ab34b9b87", "28374e00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "225b202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["c16d2e3e06340d2f877b0eab8731a0be75cd78a304909212b58f76d0de579180d29fc64d6e108c74bbbb3f670903bc091152728424957cc505fd618c0e673814"]}}, diff --git a/txscript/data/taproot-ref/31bf684d25c7125e85ce524a607eb2a52cb7bdca b/txscript/data/taproot-ref/31bf684d25c7125e85ce524a607eb2a52cb7bdca new file mode 100644 index 0000000000..9cc0e3fd89 --- /dev/null +++ b/txscript/data/taproot-ref/31bf684d25c7125e85ce524a607eb2a52cb7bdca @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c9010000000264f714bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf53000000001434957104c9c89e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79635000000", "prevouts": ["8db2310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3ae16f000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "027d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936420b598f8858794c178995f11a8e34655a29ef30c99d23407a26d0a64bc31f191a39935f0afddba064f6b0bc8589127966a984604296ac06f9873b8ee7d7aea369828280661f54bb25ef200c9d39138c753346ae1cc558703fbc48b26980763768cf2d3d0be95621d7446294d89d9a2894510d2dfb4e1a33e7316a17e39cfc99"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936228879bafec8e1069b4e024c9320127e455344299f19b4d97495a4e33db3a44844c267ebca37631eb8e8b6e08a101702978fd7f172e21a8d6d6b527626f4402168cf2d3d0be95621d7446294d89d9a2894510d2dfb4e1a33e7316a17e39cfc99"]}}, diff --git a/txscript/data/taproot-ref/31c15818563bf9247178dcf6aa28b033af2bb447 b/txscript/data/taproot-ref/31c15818563bf9247178dcf6aa28b033af2bb447 new file mode 100644 index 0000000000..c2daef5041 --- /dev/null +++ b/txscript/data/taproot-ref/31c15818563bf9247178dcf6aa28b033af2bb447 @@ -0,0 +1 @@ +{"tx": "0d8311b402bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd701000000fe04979960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700a00000000da955a9d01905b3a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a636020000", "prevouts": ["df00720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "73d312000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "3b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a1daf2fbdc5eba8a219f1f8635fe45cf0e30925345452464a53096773d109ba7ef84fce916674b46359d0327d7b56c183d26d6053da1b16053a1f90da8a1d4e"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369517bd2ec6e222f593b12487f5a7b1eaee696b6e0fbcce419bd0b390383a361246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fafc7fa9328de6285e10958c6b3d6f5d3c073b4c582e31cb42904dcf82d4bed78a29f15cefa9911251712bcf83078e1db490f7db40c14a26e0e577f39f7cfaf11f"]}}, diff --git a/txscript/data/taproot-ref/31c6f3973f706c7761a06718934fbee33a007e9d b/txscript/data/taproot-ref/31c6f3973f706c7761a06718934fbee33a007e9d new file mode 100644 index 0000000000..b23f74107f --- /dev/null +++ b/txscript/data/taproot-ref/31c6f3973f706c7761a06718934fbee33a007e9d @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1502000000692e59dbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdf00000000d423c2f302fde5ca0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac6ee00e50", "prevouts": ["0990850000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "90e7470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_45", "final": true, "success": {"scriptSig": "", "witness": ["b34ea06aceecce83e03cb040193d99209bd9d53d028494754984fdbad06f23e930f5e7dc05fa644db9d6062a4abed83386d095739cb342c46619ef7019bab09a03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["fb3fc49762e161cba1c9a95533e76d002d6bfea2c76f997b653f0c2f111f78d3859425789d2f093914bf43aac3d34f3cfbd3161d2895dad5f509ade10153007445", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/31c88595514658ef1b8ff73277244b8f007c505d b/txscript/data/taproot-ref/31c88595514658ef1b8ff73277244b8f007c505d new file mode 100644 index 0000000000..8b9b85c412 --- /dev/null +++ b/txscript/data/taproot-ref/31c88595514658ef1b8ff73277244b8f007c505d @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f601000000901c05e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9900000000916fb3af02ceaf58000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a622010000", "prevouts": ["07680e00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "90344d0000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/invalid_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["f1ee54e6c0c32e3731dab52392c8fe3fb26537d5c72a5a909de0f1aaa6def308dd5ee83fd14aded0294cda3bad5f00bca2aea2f5acf38cf8cc73db14726666bb", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/31d4c861644fc9edae1f7e2e4f31aa06c7517889 b/txscript/data/taproot-ref/31d4c861644fc9edae1f7e2e4f31aa06c7517889 new file mode 100644 index 0000000000..e17f2aa5cf --- /dev/null +++ b/txscript/data/taproot-ref/31d4c861644fc9edae1f7e2e4f31aa06c7517889 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2e000000004f19aad78bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a9000000008152fdb1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8b01000000bc4390e0033a13a400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d3c8e225", "prevouts": ["20dc4d0000000000225120ec87a05d11c16a148e05f58a688dc5bed4b2941085b66901aaa75337acfb52a4", "f0dc3300000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "0f0a25000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f54c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bdcbe75f074483e48d717af2cfa8ab1bbef1c35fc84f016c108dd10256d535ae10b3b87e8b9d8544644738d4851bae032b2bf37d3a4aa6541b936ff18c715610c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec34041dd00c04bb207a9f54805a750c9f5dad18a896c6f9e3a7e4fce73f8863b3a94e361b142bccbbefeea6ac26126d4f4fbb610699e3a27d96f99d1b67de22f2f"]}}, diff --git a/txscript/data/taproot-ref/31f076334b0a05c6d42d3ee64880af4288a1a071 b/txscript/data/taproot-ref/31f076334b0a05c6d42d3ee64880af4288a1a071 new file mode 100644 index 0000000000..99e139be80 --- /dev/null +++ b/txscript/data/taproot-ref/31f076334b0a05c6d42d3ee64880af4288a1a071 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf60010000006c56fddcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf700000000cc52dde28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41200000000d0282f1d047d49ca00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d8000000", "prevouts": ["a7a86f000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "7af02500000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "2e6e3600000000002251200fe4658e0dbf66b6be10f530376fb0e6dfa185e9d7f38ef5d5af1eba17e45594"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902be1fdb15007c7b079b1fcba37239218d2a0c30bac088eb1bc95a350527d03c30e825e686599f11585d24459989a12b2deb3942948cb4b8f9cda5b0a791d3ed03b4bdfcfd361b094f8caec2142892666ce4b2b488cc016d1fe8c1a607d1af467bafe0dcd94063da1e485b4ce943fa3daab9ffa7ed4765ea8840071d5bd38fca49594ad9b532a51ab448ebb3f19688136f5a74b9eb5f59e2ea931d4a0583f350c50c626903e11087bb74f76859a15cf934c6c46f1fd04a5269bbac98bc751549c470b8f72621925e01ef3f3220b2e7a1a2480279f7b56ab2e0cce2ec534b20cad50ddd20ac47f4b91a5f727622c3ca4d4406214b0c4239f05a9d851a31b5d80e0a8f37b083c19c9ca9f83eee836ccb8592d08ba17d6c822d29e760506b91e769bd74ae989ff28aee9723e60e2c6e9ce1f7ff8654293fc51d7412b103a9ca611de8473caae5a362a95d2047752a598d6b45a3c9717a5693a49d8d752c993a6f755428cc77636e306b2553db19379595174e12ea6c936c8016b3861ba6fd4ea933239b733720e249a6053a9ea4d6852e5561729da7538d4a937673716f95fc2be78e5874aff68e9afba308f6423c5aae7c8e2b45661e26fa14d36cf918ef1379c2cb61d329ce1adc9f94562b71c56bc461eb732e5ebcf8083caed20fd7c73d699480b430c173415f692464e7a1c6a8468a89f7d6313dfa82a6a35ac98892a86aff146044328cec2c15097175", "657d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e874d92406f86dee9f8c04bb958856db6cfc0bb7ea92d17397457214a16beb1de2302781454c6297f6b8a579760f4d591c0acf84ff9d038b064bbab8a5d53835db"]}, "failure": {"scriptSig": "", "witness": ["4d090226f850f7916ae805cfd01da3d88ba7199d161feb700e32a1e50021c6003ca27dc720ec4b6f7479434a54f67001de9d4fe624d2cc701234506a3aeab9ffc936897e4b0276a74a482fcadd75f8b0ba5a6115f4acb1d5803b741035c7916e7587c77409522bd0d4987b273d05f6e3d08d281f0c7909b73087769b28231eaa345b901a6b7b43c0547f07df9e089ff1f953ed0bce399c502ec492ffbb6e0a358e549783d8a46223fd1d70dc57bfadae07294e70978d5e5a4aadc6e5859f115f49a5cb21c5b5836748c1a4d5082bc5775f51701daa63a0f8e1753bbc1dd4a97c53cc1a286488205dbb620869a256f9b961ee0a21fb38a71816805d48ec695126afdcd2239296bff27447a2eede5770873acbccb8cc6fbf51dde9b65691a5052f518f84188382e676c04bfa05ff578a9de1191b8405d2597acfad0d5b4479707a936431265c14211a1ba593034235eb24c82b840b4fe131f19fae3ce3fc4d40183db076c935c1486a850bc64994ea20edaa605f56222165541624237602f667f9d254ae7daa69cbae4cdb10a5dec08d4c9cb72166d8e7770d5691ceb6e42ba4f83d9c07d09c271681af9956814c23cdd3ee14b1e4bdc835a6975f65e98041c920a61c1e0209e0d0a57847f2d2414b4c1785037dc9afee306dfb2f63a72f42dc21aa940bb43c09090ce6bf6f144876b9070d5c81d66876524c1052ad44ce1aaa29a5dd8b282a56607cabea3dbc75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e38fd10ac28b4a0ae18793cce60e7e7ebbedf1e3488ce0551c956bc9cf517ba032bc2c7d802e8c870cc0fefcfae9d23d316cca1682651be3bf62b663d5ddaa443"]}}, diff --git a/txscript/data/taproot-ref/31f2c4c02978ae42e16425ad8313162bbbba6fc1 b/txscript/data/taproot-ref/31f2c4c02978ae42e16425ad8313162bbbba6fc1 new file mode 100644 index 0000000000..540cdd4834 --- /dev/null +++ b/txscript/data/taproot-ref/31f2c4c02978ae42e16425ad8313162bbbba6fc1 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1b020000001b786e618bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ea01000000fb510c0860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700f020000007a80c8d8019ead11000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d2de3b4b", "prevouts": ["ab2348000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "bb733b0000000000225120c52c9d5db69f3d85ee35b65e5555252fc0470ab9a3dcbb72267f75438b29b283", "885a110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_18", "final": true, "success": {"scriptSig": "", "witness": ["3bb82bc9855bff63b0806c30243ab6fe6426048089fa359853a43727833a71eb8712e3f23c61d5782e5762c682b7d2d1b04e38eea97d8a5f947b34b3833f7d9e01"]}, "failure": {"scriptSig": "", "witness": ["d03348852a55ecc7dc459389116e8735107f690dbaf8c2ea77bb4f79999764cc561318fa63ba00c1fe8c4e700c4aabed736d29a2f98fbbcb5ef197bb2bca048b18"]}}, diff --git a/txscript/data/taproot-ref/322e55f03866ad2580881660af953e8169abf66a b/txscript/data/taproot-ref/322e55f03866ad2580881660af953e8169abf66a new file mode 100644 index 0000000000..d0234e0b2f --- /dev/null +++ b/txscript/data/taproot-ref/322e55f03866ad2580881660af953e8169abf66a @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cca01000000beed76a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfa01000000006e98b98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b701000000b215db96035f51d900000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7f08c9e1f", "prevouts": ["f6c5510000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "2aaa4900000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "ab2940000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "success": {"scriptSig": "", "witness": ["84ca13405546924e6c9fb74dca48f76bd877f7208e82a83f2d23f23e1ae0d8b1c15b7c59a5c02eaf1fb15469bcab66cbba1ccb96702af7e47dc9b055183e59f202", "50066a082476af20f64504b01d23ca398afc25473f9061260e2559285294e81f4623d810a196f11f5a4ac85f7bb0c40855b443fd323fbfafc83ff838a6e618ad2316f92962a697139191dfedb3f1f475a75b58bf545bd9ad6c2e183ad7f5b35c0d8aeb66806582f8a9375c2d46327142d816ff6faa4621eb8fddd96c19d2eb4d3adfc7c20e5106beb9bf106a8461e04bda524b17bc460c606628137fcfb4dc50a1acdde2219f744447b0096d70cce90d25c417b2888425252a0697421bb4c0af15121e2aac2eb597937a0c9cd3b00e6d527c17d31b8b045b77707b19cfc280e289"]}, "failure": {"scriptSig": "", "witness": ["d8c1fb3ee3067ac98df69fb8275cee5c1944a25abfcd509b44b5e0a9e35f47b1deccb1990859aefcabaeac82a3444d0059e71df69fc0a777100ce79221bb83e002", "503fd27fbd47b778410f167be796854ac258f606f5dd6bf4056e43ee08d466c389f40d33521f277645062a807748d8f42e7d064a6e61c9ec028ac755c835f719449be2febf6c70fc4534350b6eed3cdd399d05d7b9fbda5a6a153a20c2d799851c3e25287efec944a976d46b44a2d904422fe38304cf0d800d4c116f194c8c0507373ebd7eab9149c97d0120480b170fe80abaf915f541bbc584bffb5e25187874a9952ebb646df548a0c5dc7ce5a0ef2aa6"]}}, diff --git a/txscript/data/taproot-ref/32465695f8a85d30402f9b194bdf25dd6e21729d b/txscript/data/taproot-ref/32465695f8a85d30402f9b194bdf25dd6e21729d new file mode 100644 index 0000000000..0711e49f54 --- /dev/null +++ b/txscript/data/taproot-ref/32465695f8a85d30402f9b194bdf25dd6e21729d @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48f01000000072c8a9abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4e0100000043944632025c9eb500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1c4cd623", "prevouts": ["881937000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "7fda8000000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "797d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368e9ed2886e7908e27181476c22eef50b42616dd4d44ef70273b9f072453f43980793fbcba16d5416bd6f0933503ffe6704f239223875a49be11ed5869ee331b55be39dc57762be2d9b1a04aa5b570805d23104bfe4fa54c392bda5d51f7f4540"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa0b1051acd7c1b2d32995b3df0c6921af5f8ed3327e7e16cb8a5e0bd007230af127aec9530f4cf05d3554e63105b96634da39f3c52c35c251ce860693e97320b3"]}}, diff --git a/txscript/data/taproot-ref/3296dbebd697c68468c1215ff252b1da046d3d4c b/txscript/data/taproot-ref/3296dbebd697c68468c1215ff252b1da046d3d4c new file mode 100644 index 0000000000..32d72891b7 --- /dev/null +++ b/txscript/data/taproot-ref/3296dbebd697c68468c1215ff252b1da046d3d4c @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4e000000008f41f4e3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b450000000076427492dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cff00000000c272c0da025f6a97000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acbf96ea1e", "prevouts": ["4be92800000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "7fc7250000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "79b64a00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000085", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb43f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d4e60e987dc96ee5dbea4bc309cd424f3f3a0504752ed5a5936e8ec363297933734b3a7050eee065844830ad8d45a710891f78004f5e7f35b8fd72bf3ee94449"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641544759b35923e828b4a61445a8ec3755fffb3583722c19659f8e8298b40b1ac80cdf889f2095af4d324c92b00d2a9db5fcc0724b0f6f8ee9ebbd204938760cb2a240b376911c9876b3695f79f395ec3f2d97b1695e5c0e7f397f1ed982e79a1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}}, diff --git a/txscript/data/taproot-ref/32aba46093e0c1405d3a8229f68cefd6de6d9767 b/txscript/data/taproot-ref/32aba46093e0c1405d3a8229f68cefd6de6d9767 new file mode 100644 index 0000000000..42b9887ae1 --- /dev/null +++ b/txscript/data/taproot-ref/32aba46093e0c1405d3a8229f68cefd6de6d9767 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b07020000007adfb0878bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41d01000000b3b8bc9e0240305d00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f874d000000", "prevouts": ["43942700000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "1845380000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_cs", "final": true, "success": {"scriptSig": "", "witness": ["a57f02d016c39779e9ce1f4f3c48385533efe663709d72051b46f19328fc7ccce9f41e98fb5d98c2eada9a462c855f527a2d7e06a95441495a4b4cbf57f45d17", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b7922a9ef31868fd0bdd2720bc44a83a05911c979e226e14df12e43105fabe25154b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["a57f02d016c39779e9ce1f4f3c48385533efe663709d72051b46f19328fc7ccce9f41e98fb5d98c2eada9a462c855f527a2d7e06a95441495a4b4cbf57f45d", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b7922a9ef31868fd0bdd2720bc44a83a05911c979e226e14df12e43105fabe25154b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/32abfd2efb454436ddc75cd07a406d88aabceb2a b/txscript/data/taproot-ref/32abfd2efb454436ddc75cd07a406d88aabceb2a new file mode 100644 index 0000000000..f44dc6ef3d --- /dev/null +++ b/txscript/data/taproot-ref/32abfd2efb454436ddc75cd07a406d88aabceb2a @@ -0,0 +1 @@ +{"tx": "398e50c902bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8e000000003f6e1e85dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2f010000002f7459e501c7546300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac9689c95b", "prevouts": ["219d790000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "768d250000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a782270f3344e4a0806c19029d04ad520705ab352d941cef93688ee397cbe2ba37683ca92a47492765ed69e840601310475c5f70013240e7a67747a5da918187472d664747fea006dedee35c74318028ad9a0ae37c154fe8226ccc2af402983"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361387569eff5c8fdfbb47201101452628117e65be58c01e3fcd7a4762d833e9a33f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829640e65f27972e690b56e28a8f49ec76fed3450565b59143bd547c42619e148d8047789ecbd47ea83af97bdb87f8422a4707031714ddb05eaa38b24e158a7c35"]}}, diff --git a/txscript/data/taproot-ref/32ba176293211377a9ca30f7b1742a3102758b7a b/txscript/data/taproot-ref/32ba176293211377a9ca30f7b1742a3102758b7a new file mode 100644 index 0000000000..bb158831a1 --- /dev/null +++ b/txscript/data/taproot-ref/32ba176293211377a9ca30f7b1742a3102758b7a @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709400000000b5af37dfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdd010000009d67e5be0212197900000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac7c000000", "prevouts": ["48250f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6c8d6c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c9", "final": true, "success": {"scriptSig": "", "witness": ["130caf75742f8ae965a7d7e33c499d6bc2c28d159e9a4caaf044f94090728b88dbe0ed3d8cf70c6dac63890dd2fb23b6609ab4e55cb3e5ccf9dc54088421c40283", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["6a6ba0a6bca5ae864aac839be28c034df4c7ee67b75988f87ac47ec326a0a1a0980f34b312b04fd328f4d5ecc453ba46a5380409a1c72dc3195b3af264aa6276c9", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/32bcf37b6b3d15680600c81db467e1dfff6ce375 b/txscript/data/taproot-ref/32bcf37b6b3d15680600c81db467e1dfff6ce375 new file mode 100644 index 0000000000..7719391b27 --- /dev/null +++ b/txscript/data/taproot-ref/32bcf37b6b3d15680600c81db467e1dfff6ce375 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4baa00000000d7f864f704dddc25000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1302564d", "prevouts": ["b5bc270000000000225120d61496029c5d349efd8924002b7ff235d477ef1351b040da94f6febcd1852b9b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f33cb046b8eba7745a43a31b99cce8060d29a3cf40684a8ccadf7d90acba647f"]}, "failure": {"scriptSig": "", "witness": ["6a05616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/333dafc1d96971e2ccab51c8ee0d9e479decf78b b/txscript/data/taproot-ref/333dafc1d96971e2ccab51c8ee0d9e479decf78b new file mode 100644 index 0000000000..b2096c853d --- /dev/null +++ b/txscript/data/taproot-ref/333dafc1d96971e2ccab51c8ee0d9e479decf78b @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1102000000ac4cac65dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b710100000030a16be304f0b149000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374871ce85d41", "prevouts": ["40ac2300000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb", "0f2a280000000000225d202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["e7e1aae90aceb2e99a7b56eacd7f6d43c8002a6ca89f9e3208f45316cc2cb09dfd5df45bcde2574b895b928b7d66d079e6641938e46fd0b8a63fb5163ce25e4c"]}}, diff --git a/txscript/data/taproot-ref/334e3a237339fce576119749a9aa81f3d65211cd b/txscript/data/taproot-ref/334e3a237339fce576119749a9aa81f3d65211cd new file mode 100644 index 0000000000..76de4ebba0 --- /dev/null +++ b/txscript/data/taproot-ref/334e3a237339fce576119749a9aa81f3d65211cd @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a010000006c9b93db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d601000000fcf1a38ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b33010000009c6a06b504e4ebae00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987182a0b5d", "prevouts": ["29c3530000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "0ffb35000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "bcdb2600000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "a17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93654d5e9f128d5d45e2b514bc7d0582e1e8810c31523e6a7d498e7ed4fcc964510a4fb15e70bbc27f4f9ee6ce894c5f8660c4bc0a21501abf5c583e18e279746b733479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae668dba12609f1dce2a1e29faaa62ff248d54f408b31ef31944f67a579d4fbb4"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692ed1d8a723f26614ad38a5a6bbff83804b2df3c5c12fea7853938e6cfd441ba04a5fb755beb1eb88fd06fac279ccb2aada241654186a69e6e0c04e3255c18f895176026b3e005afce4c10b5e59a002659822bde369bd64201565ae4c88fc95c"]}}, diff --git a/txscript/data/taproot-ref/3352986afb9bc33fc67eaf72f47be64e3c6ccba3 b/txscript/data/taproot-ref/3352986afb9bc33fc67eaf72f47be64e3c6ccba3 new file mode 100644 index 0000000000..7852e9bba2 --- /dev/null +++ b/txscript/data/taproot-ref/3352986afb9bc33fc67eaf72f47be64e3c6ccba3 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270910100000002ee48babcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6301000000681f3bd404a77680000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac689bb04d", "prevouts": ["d5e912000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "11686f0000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["be4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4c9baaf460c9b08d8af0a53251cd8db921d22667fbf74eb915957e4e9d1c209d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51f60e2d3154f769650886384bb096233f0069490aec77c98efe910f3ad816f81d7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}, "failure": {"scriptSig": "", "witness": ["4c52be", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e118b1142f6c6f685b07aa6aec8ab7e3e6024758bf09974a9b2a7615fb4927a0f7d3726db1c97dedfc82502578948b1d779eb886e6296c36bf50b8d2fe25c32b8a344cebdb8ecd56ef01fad0911d9d88482970ec36d3a04b84eda7f5b5c68ec938"]}}, diff --git a/txscript/data/taproot-ref/335b7a860725ca4f2c467a8b034060d0ce6b3bb4 b/txscript/data/taproot-ref/335b7a860725ca4f2c467a8b034060d0ce6b3bb4 new file mode 100644 index 0000000000..f76e5c642b --- /dev/null +++ b/txscript/data/taproot-ref/335b7a860725ca4f2c467a8b034060d0ce6b3bb4 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cad010000006f1f83aa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702302000000807b5d64015f1d3700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1d010000", "prevouts": ["3a024d0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "f1401400000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["964c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456bbb2d2aacfa419948546f2c8aa96b4ab4a80289c3c8034e795f45f733cf7ae0b35fa22f4b25dbc3a6b67e691e1ba7f45df255baed4abd058cf23fbf36a7f21681a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1ba1d7044f76185c852e3494a6fce96de1fdde778c7130ed924b07f57193456c18c78e356042728a8dc5293f4719d9544479381d7bc53161d8023b722566e5250874a9774daa89f30be275a1ff5113653dfa1548b9628ff9725cf694401ebdfe4"]}}, diff --git a/txscript/data/taproot-ref/33848da9a02cc62be9f5a84c5ce6e33bb6aa8a29 b/txscript/data/taproot-ref/33848da9a02cc62be9f5a84c5ce6e33bb6aa8a29 new file mode 100644 index 0000000000..b0c8739451 --- /dev/null +++ b/txscript/data/taproot-ref/33848da9a02cc62be9f5a84c5ce6e33bb6aa8a29 @@ -0,0 +1 @@ +{"tx": "c37ec3c302dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbf01000000556bab88bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc10100000073720da201fb286d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdac25b29", "prevouts": ["55e22000000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "e2aa6a00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "fd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa4304fc86dd976b0937fa56c41f386d806abfef37789b2eae5a350cc5f24e0b07f4148296d57de26c46202ca6ca2132af69ac5e2240f6410455c1127b810a8937"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c1b9bacdca57d9824556224747bb261aea2ae7ed0ce11a73241cde6387669db02c6cefb1e181eefac563b15a866f5ecfc3c81e54821b9e81f79abce745f7d95962d72dd1cd8804fbc0be1dcf6a22214dbfb5210e6cde6f2a41edfb954edd50fb"]}}, diff --git a/txscript/data/taproot-ref/33aa1588445e9cbbedd1d4a629780bcc8b4a8e9d b/txscript/data/taproot-ref/33aa1588445e9cbbedd1d4a629780bcc8b4a8e9d new file mode 100644 index 0000000000..e618184668 --- /dev/null +++ b/txscript/data/taproot-ref/33aa1588445e9cbbedd1d4a629780bcc8b4a8e9d @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d70000000095241478dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7c0000000022e144c003cb9d2d0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7c0000000", "prevouts": ["839b0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b091210000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "2c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a969cf06ec193d0358c31c8afad5bbcd547aa0657673b5bb10a44e38c372c44cda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef5981cd58c469d4842aa56f101a76a4447dba55ab7a128197943d7701f95f2823b7ec1fb3aca1c665feb629f75b86bc6796ed5eb830658d68574ea157b89fde9"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667e3c1aa8bd39d6182a2299f940d076e52caf4ade4a085ff8961d11623e68188872b08559f184ac3ac9956d54e492d7f98285a254bf010e00b63b6bbe75054353b7ec1fb3aca1c665feb629f75b86bc6796ed5eb830658d68574ea157b89fde9"]}}, diff --git a/txscript/data/taproot-ref/33aa91e75b0cc39daae8eb7a1f0889075a667617 b/txscript/data/taproot-ref/33aa91e75b0cc39daae8eb7a1f0889075a667617 new file mode 100644 index 0000000000..cac670e260 --- /dev/null +++ b/txscript/data/taproot-ref/33aa91e75b0cc39daae8eb7a1f0889075a667617 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7000000000a124ab458bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4260100000088e9d0d702bff683000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874b010000", "prevouts": ["493c4e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d06538000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ace", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828def8465bc2f3cbc3837b9c231547f51d7c9e247c478e05a849822285048dd5e0ea67bdb3398814286540937ec364df004af879f987225ad05d036a51e8223e6d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c90a0cbd53f67dc3e255e72ef3008af6a84b6163b55755c05c159eced1c9429125e7936dacf44c2cc5542287b329619dfaa06ef235a847d66c9c2df863225da6d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}}, diff --git a/txscript/data/taproot-ref/33d0d39d6ce6ced2a0a8dc5d8c47e5f5098d7aaf b/txscript/data/taproot-ref/33d0d39d6ce6ced2a0a8dc5d8c47e5f5098d7aaf new file mode 100644 index 0000000000..e0f5963cf7 --- /dev/null +++ b/txscript/data/taproot-ref/33d0d39d6ce6ced2a0a8dc5d8c47e5f5098d7aaf @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6f010000000801f9338bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44e00000000cafb6acc04e6afa2000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac06010000", "prevouts": ["8cea640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "606d400000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a5", "final": true, "success": {"scriptSig": "", "witness": ["344e52e99b8621c7551bc3af9c82142e9503431eb3e7e9a005b520c2d0c32ded2346ee64a63e101d224fed8af6f5e5b8ceca4f99fdaeea8a586ca29820309da601"]}, "failure": {"scriptSig": "", "witness": ["c1c7b8e70017ef7a6e69330630f8e1e0cf604cfdbc220833df0657bf4dbf7f23b2fcc00879bc9246d15046067af1493a3ccdb7c714b02f344235fce1c36f1d1da5"]}}, diff --git a/txscript/data/taproot-ref/33efade4e6970da9cea78a726935e5443e0d1ba3 b/txscript/data/taproot-ref/33efade4e6970da9cea78a726935e5443e0d1ba3 new file mode 100644 index 0000000000..96ad668194 --- /dev/null +++ b/txscript/data/taproot-ref/33efade4e6970da9cea78a726935e5443e0d1ba3 @@ -0,0 +1 @@ +{"tx": "e8d0e7300260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127071000000007a5fcead60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705801000000c2c69bd103096b2000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487b8556127", "prevouts": ["487a12000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "e3b0100000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "867d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e97a330f28472054f17ba9fa881f8fc7a87b4cb8666ce3273442871f099d80d74fc7631352e9fb39bf71f46c116b968047934be68cc4b25c7eb80a8b2383cf163ac108bed01ff7a3c4482bdb9637a0c08eda3eca9d378124f08be0fd1593c53eb98f84b0d7d6fcb38bca0562970da4fa4ac9189daad947902c07179846baca90"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da88b8ff2a82ba0fa3daef634fc59634370b0e98c0a294a285f81b50f56bd3b735e7075953fd5a7e7406fd0d1347280992625a2d2de29c104ee1b42e523bd7beccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f4576b069f256e7b53185a64c953a8831f99a2248244dec917c9fc219bffc52b204f"]}}, diff --git a/txscript/data/taproot-ref/33fe1028443f16cce6d9858c8501dfb0a7ae5816 b/txscript/data/taproot-ref/33fe1028443f16cce6d9858c8501dfb0a7ae5816 new file mode 100644 index 0000000000..9724e40c82 --- /dev/null +++ b/txscript/data/taproot-ref/33fe1028443f16cce6d9858c8501dfb0a7ae5816 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7f00000000ec0883ebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf400000000af6e853204717b76000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487e7000000", "prevouts": ["408f560000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "d3d9220000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d968", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004520e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d13faaaba0b83fb431d1a23feb7d5de22e491a7fb36e5108ab00e1ac0e7366690e1c61743bed8ba943c0dc40e80402f7423773c7111097ca9c5a140b1b3c94b9"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363cf7d6c7dbe5925b37da22fc3f9b29f912bd281d5a092b1ed7e24ae2c32a8d7520e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d13faaaba0b83fb431d1a23feb7d5de22e491a7fb36e5108ab00e1ac0e7366690e1c61743bed8ba943c0dc40e80402f7423773c7111097ca9c5a140b1b3c94b9"]}}, diff --git a/txscript/data/taproot-ref/33ff2ff9d9aabf2865009fc3701058f954184c4a b/txscript/data/taproot-ref/33ff2ff9d9aabf2865009fc3701058f954184c4a new file mode 100644 index 0000000000..75468e408d --- /dev/null +++ b/txscript/data/taproot-ref/33ff2ff9d9aabf2865009fc3701058f954184c4a @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c290000000006481d8560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e0200000026bb47f7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5601000000f8a95f8803a645cd00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79665a0ac45", "prevouts": ["bc855900000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "782b1000000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7", "077c65000000000022512007a606ac1d369bdfe9b32b88a4b0d4c507785f2481b337f6b3340196eed3e896"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d79df6a78da0f5e7e8abe67a937df0199bc2719081f435200b4d9406e022e7e11ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045a58cdb730d5140e8751cef937639de4f5fbc77d98986906c68a7616d2fa212f87d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365fb6cdab2e5dc224d99eb40cef967cec823dec47795ecc7beb7ac0a6ad6c13edbb0de8cab6875867027c85350e6845db37b89c1faa2a12b075d8db116249f7bd2367bb7d11bbe7d9666c447942212a409021a53e3151df7f84d090727acdc4c9"]}}, diff --git a/txscript/data/taproot-ref/3400d35bd94547fb613f1aa5cd2073fdca146533 b/txscript/data/taproot-ref/3400d35bd94547fb613f1aa5cd2073fdca146533 new file mode 100644 index 0000000000..23af9070bd --- /dev/null +++ b/txscript/data/taproot-ref/3400d35bd94547fb613f1aa5cd2073fdca146533 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2e01000000c5dd29acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca2000000009f8c9bfd026dc5c20000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3aba894c", "prevouts": ["ee7c6700000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552", "cd325d00000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "e47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cfe8c2630d2e6dab45dee7e1e2c518d990c791dc0a4f80f5d66c62d1beb467aa455476c3fa5bfea733d4af800001099064b64c061f8e2c0be311cfe06abfabc5158e114954b29a1fe443083941979d23a0210cc324956afb3dcce424fb4eceefbefe4cc2cebe7bba8b4a4f82666342333b91a450af49acc0f1954b5763bfc142"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c0476de9e93667ef708e6684295477581821e44eb6d19385f240ec9b8d96232c13278694ce96e600b1b1379af0dda4dcee22bd0822513808885cb6e68b7803daccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457ea7c8dd4a05a6083e4a7ce3fc20cde94d430ec03cbfbe8017e9dc8ef3bce99a9"]}}, diff --git a/txscript/data/taproot-ref/34038f296d87d228ac46a39bb072cc03e4e585bb b/txscript/data/taproot-ref/34038f296d87d228ac46a39bb072cc03e4e585bb new file mode 100644 index 0000000000..0b1480f4e5 --- /dev/null +++ b/txscript/data/taproot-ref/34038f296d87d228ac46a39bb072cc03e4e585bb @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca1010000002f81b9ab60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c9010000000f201065042881640000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8764000000", "prevouts": ["a46f5700000000002251207c84ae2d9063cc63412a30e00823aa01b05bc54bcf6d9936dc1c650bbdc9e98b", "d71a0f0000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/trunc1shortcontrol", "final": true, "success": {"scriptSig": "", "witness": ["f133e35be334aa55fd1a4020103c95306ba81793663788cc311ca541d9085f594f3c22c0a650975083c14ce3a50ce7df37c835d59be900ba7eeab95ea31598da", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20"]}, "failure": {"scriptSig": "", "witness": ["f133e35be334aa55fd1a4020103c95306ba81793663788cc311ca541d9085f594f3c22c0a650975083c14ce3a50ce7df37c835d59be900ba7eeab95ea31598da", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", ""]}}, diff --git a/txscript/data/taproot-ref/34264b99b16c56793e013d7d2ac3dc83c0c07da6 b/txscript/data/taproot-ref/34264b99b16c56793e013d7d2ac3dc83c0c07da6 new file mode 100644 index 0000000000..9ee263c252 --- /dev/null +++ b/txscript/data/taproot-ref/34264b99b16c56793e013d7d2ac3dc83c0c07da6 @@ -0,0 +1 @@ +{"tx": "db1a6b1b02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc300000000730c61b260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127017000000003c7d6ccc044728720000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac09020000", "prevouts": ["5f59630000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "986311000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "867d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e35e7075953fd5a7e7406fd0d1347280992625a2d2de29c104ee1b42e523bd7beccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f4576b069f256e7b53185a64c953a8831f99a2248244dec917c9fc219bffc52b204f"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823f28332fff4e521a34f62a6094c9ca083df763bc212ee1a103146f1ea11bafd96b069f256e7b53185a64c953a8831f99a2248244dec917c9fc219bffc52b204f"]}}, diff --git a/txscript/data/taproot-ref/342a92cea02c320154d0894d36811870581b660e b/txscript/data/taproot-ref/342a92cea02c320154d0894d36811870581b660e new file mode 100644 index 0000000000..7b629c51e0 --- /dev/null +++ b/txscript/data/taproot-ref/342a92cea02c320154d0894d36811870581b660e @@ -0,0 +1 @@ +{"tx": "4f48ddde0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704f00000000ab8735e8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1702000000c289f8a9017946670000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7cf020000", "prevouts": ["0633100000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17", "bd2f790000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "7c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93618bfa1a0310c6e7995d51524289b510664f003b8075315c96b030a9e98a309f23f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08208eae3f5bf5f4c26def68bde658fd1412dc2dfb494d39d6b1bd4ba6a274f177d9a711983bc616996e2ac47b27808b31a9b7e87f7ce1f3571999dd3a2a57f1080"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93671c1d10f8373edc2c4abf147e4b905e718eb9e3a7a7d82e3fbe9489fbd4d31fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8742f7aec0ae53a52a244a2c0c214837ef2ff67b990e770e70b44d703b0bde01fd5e8f79d631fbf207b458b911c1cf4efab0aea5316113aa9c93bea92caa9fc9"]}}, diff --git a/txscript/data/taproot-ref/346b40c03454e4740323b5b0422908722f9a4ed8 b/txscript/data/taproot-ref/346b40c03454e4740323b5b0422908722f9a4ed8 new file mode 100644 index 0000000000..6b364e1e90 --- /dev/null +++ b/txscript/data/taproot-ref/346b40c03454e4740323b5b0422908722f9a4ed8 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b820100000031e5a6bd03e4231f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48727000000", "prevouts": ["3cf2210000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09029799e9d74897279c0afb8c38d5d3c16e364d203dacd3b9fd2ad8aa0c72b731c7e4fcd79c21bcdb17fbf7bd2112c9d486e90a022725fc9f30344ef75a1b6dd33cb5f2111f382512a428b9f0fb7bc037e4a0f29c9d98c64cdd64685e3853ebad79eed2c24e82fc94a901215a7b5eb7242c0d0932a071d8da5b20486970826ac1abbab96b40b667a0b4ae4414c7c90787ddcde93816e7197135b1d0a2337416f3885412c406b29b892f0c1ab57e8cf18db0788f91e464eb3cfec3da5c6e4539f0ef7880e0f1e26dbc5df4b551b09137d16286ce162e356a631e48945957b196ddcaf053cc16daeff06dc24759765904c36b55bbf3007146ee520e6706cd5b2646b96c4e73bc3627802a1f28bd4d51f16c04b21dc0b1bdcbd4b89ee8169fbe86500f2705652fbc77ba0090f1fbe2eb5ea4e731ad74636ac8fc4a8a0642489201874b5653f5a8d5e036142ccfd96ea5eabd0440feb5070a81bfca23bdd5b90f85fd374f99dc5bc1e117affe5743e897cbbe8c3ec27b5252c3adad2374aec2ef39f8f11c7040b779c4e551a5445bbca7441a68c0a4d3fcbc5a5db86fe37275eb260d3de6b600937bb0e7fd37d289f337dd2aa4b5e96fe22604d0d353db52f9d394c38ac9a0d4d457cf10d09d54e51b88a55bed3a6b98a1a4bab32dcd1760a8b682a7b9b19c91ac135f5d5b4d0cf0efac5830df35e1bedbf0ef463a1ee09fb66c51d318f3bdb96e67872e266e75", "c37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361a3ba70448446526157b81f30e62eedc08a9d1c5eab7e26d94d9d479cca132acce42d201fd753cc19d7433434234602e4af838ce265353441a761579b9ecb89c78d53ca9a9f93e78db88a883cc9c42dbf55ad09041fa37b21a93adcd191d7180"]}, "failure": {"scriptSig": "", "witness": ["4d09026c74214fedb3c7322ab8deb285da3f4eaf36590572a02a0471ac6700c60b4fbba804cef111caa1d135cfed8192f8a3a9c71335e677dafaa6a1454fa01cc882e4e703966f63ff6944157619abf269bba16dd6853a4c28f5639e4cec96a21e15efef9558a84fbe42d4529630c9dd9fbee8b70c99b88b4db03ebe42f9d640252333ad746d0e195badca5f265af64caeba3fbbf3bf0c79c4691660e077dac6b7d9f8dabd1d4d69bdf211b2f688d55b4bd84a062ad63011e13857facb392df8b004adc222e718c60c385d14c61bb7d58d8ff202545288c7819800d45f480e117495143021017900e671d3e7acf12dfc0852513d3d1ff0d6bbeac4302245c9b993020e9a058b930a328896f712a8b0ce68bb9aba288225bde049fc0c9a97a1577d338682662fd7f335e6bd59bc9754fe14c236ba0427ddf200fe5fc0c2957e692acc71bfc07419a16a9a99cac0e59e9576b387ca11a96fe8586832654eb833cfeda083ccbee194e981378b8acaa6623ffdd1d4618276cf90f1b923900ca8b13f0bfdf4187a6c15ffb5a1ba7f95d006c7bc2779d348b00ed719f489acc459abe1f37b357c1d45fb353bdfd88cda73b10577cad0407ad1d82c8a3da825d62b22ad4793e96227eeb0e078825b8148df33233240a025080bddbdbedabc5d7611a12a0d93784898d5b9eb433d4ff5fed3fc00d1f14fd630022e23f79d7d2c332b3272a3dd79d8d67deb39ded4605b75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082638c14f042a58a31b61c3859e3b726944cfc511dd17ecaa68ed5dba7522a36ac78d53ca9a9f93e78db88a883cc9c42dbf55ad09041fa37b21a93adcd191d7180"]}}, diff --git a/txscript/data/taproot-ref/348d5c1f7c9f5084425a506f649c65b2f31946a0 b/txscript/data/taproot-ref/348d5c1f7c9f5084425a506f649c65b2f31946a0 new file mode 100644 index 0000000000..eb6f95fb83 --- /dev/null +++ b/txscript/data/taproot-ref/348d5c1f7c9f5084425a506f649c65b2f31946a0 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9600000000431e98c960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127048000000008ede57ff04e6946e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987ddbdc542", "prevouts": ["320f5d00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "6a0f130000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "cf7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea56bafcb4adbf2751227cb38af2ee857892c1346189758b7796ca4cc3d2e44b46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdd6c4167c25132c432c9175336dcf34ec1853eafcfbd891c58e0cd045b8bc4542"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e82a853d9097b45eb0aab266931969d1621607f85e2073f603093b953a54be8539d6c4167c25132c432c9175336dcf34ec1853eafcfbd891c58e0cd045b8bc4542"]}}, diff --git a/txscript/data/taproot-ref/349341420dbe9b22120760aa5b91a9099c7cdcea b/txscript/data/taproot-ref/349341420dbe9b22120760aa5b91a9099c7cdcea new file mode 100644 index 0000000000..8844ff3ce1 --- /dev/null +++ b/txscript/data/taproot-ref/349341420dbe9b22120760aa5b91a9099c7cdcea @@ -0,0 +1 @@ +{"tx": "bfc6bdac0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705d01000000a466cbd7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4901000000510497b3033a5032000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8700643d2b", "prevouts": ["e9d1120000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4", "0ded210000000000225120803c4cefbfa0d88ba71bbfceadb0978872c77a948bd70ce562f9334bcd1dc6dd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "137d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4c49796db8bc731ce4ba3cbbdd752e7baa135113f8e0f4a7981e8466556ff5d9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e7c43b740c0608ac721897ca7a4b0bbd2ef7e62418d1fc20274bd386c7c0d4d7e"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368bd2abfcc71c7b73097e9a5763f21997ccd1bd8d9582aa36e06c3dbfb6e67c306a37fd9f079711aee2dd395c4f9bf6b9cf1f54b1a82846abc908addbbb61fc725d0346f0de7f7080f7758bd86c81c482f81ad0c7703311f4b65ab9d7b77c9f00"]}}, diff --git a/txscript/data/taproot-ref/349bf68e15d8f14b4a471b7ab402784c1077db21 b/txscript/data/taproot-ref/349bf68e15d8f14b4a471b7ab402784c1077db21 new file mode 100644 index 0000000000..5911f4a461 --- /dev/null +++ b/txscript/data/taproot-ref/349bf68e15d8f14b4a471b7ab402784c1077db21 @@ -0,0 +1 @@ +{"tx": "398e50c902bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8e000000003f6e1e85dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2f010000002f7459e501c7546300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac9689c95b", "prevouts": ["219d790000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "768d250000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09021510852cddac042e61fc3d11e3311df0733ceaf7eb5c20e6d6190f0679d34e8954349e8fca335ea52133f96e208119c5e773ae431a3fc66d668e6987b684fd85d0341e4ac362efd11da618f0ae4a33f61fbccc73a20750a8898bd18ec36d338fc66d1ca186284c0197ff435c1031efb775f5a149c7fe43090f7c57f2bc8287da6efacb67c76d53c573dbcf1eeb190f8862e27a79d2b20f0cf19722fc7b69fcfebbd6b568f7acc9729802ebdf3c09a32fb9da6babfd4f3814e0724a4614a38b68655210d07b58fae306538a7fbdfaa451280288d2b70f2e57864eaf9fda5b7842b8af7ced1545fa1f4d83e67b299231aecaa1885d3e2e278a988f2a10a052c79d6a5ee19b2108611dedfcdde3bab2859d085ae90fd92f369c96245476bed223f9e9d2f2f6625a510b1ae39c50160cad32f9eca9e2f98ebc780bbb38c292f4f0103f706d680d6d3368330dc82a4fc4e5ce7f21722c8b6269627b79675c38ef4cbc015c3245431252b00af0217e18dba78dfe4bceff542753c64810f03efd6e14d95edf35d88d5433e130bf6087cb55b368361289bc2c70c1e87076b72e11375b5c6dd6de25eff532ea47b708cedf5946556379bb60cd88ef3b345f636814e497c2eb53d2b4295c79b1927576ddddf4a39644addce18e177fe6b59f0b214e6f0e3e19f1bee634922c4b00cd19c4b4aae9732184295de06813084d294b205e3166b52049f35cca15ddf21a75", "217d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08256da9396880b08a11a17662bac4a7b382e749572eea29fa5ac5793c70e2d18ea5bb5ed745f7425de3873ba37c460c85acd2f4f50490d9d3680fc958bb85bfda6f488f9b2dd04714e2920653c1afab7d010d81355bbe53edbfcaebea15ff1da48"]}, "failure": {"scriptSig": "", "witness": ["4d09021c456d981e5c3b017b4453317e1084985c411e0374eebcd13639455a4bd4cb054b1fffc89b944c9abebb8ad086bbdb188d6b122ad0597a0e23561ba43687f52aa25252aa0bf87be1540ffed38500ab81ea44feeca7797f3b22d47bad9e0a1253a46208e0bc5937b5161b8fe85f8691648422f371aca8153460b32460ea179e8fe6a31a08ff7cab8bda7bf491b53c2c6261ad74511579a5fd97c2eebf92acb284206d872345b1cf850b562f2873a1e6e71df99dd6cb996d939affd6c950c7c5d40ea76e2e2a36b9c71d8ecf5424817aed0efe02c0767705d86521bed0ca3fc24609682970a23517a769f8bbe6f078252ccaf5ff2d7fddca1f86b93450b99ac8fb727523de11eb977069480646fc92cb59a1ef5ea39a6137ea8bf9937afa3bdcbd365350c295aa2276927c2741b41c50948c03e60adfd3683dc74a3238b9977e1ca638fdcb04d92fd5aefce0bab9822498dc4088b74b506d624f476c1818f7d54e2d5665daf9d63cb5ae1d4413bbb029c2e111dca3b7338582219a404d1780fa92e3d0f3e22e4945181679f60ce7812123463c5eb11a8c055bda24fb9d5938e1302adf1066cdfa68db38f1f1ec8a5c8b683d2ae16c23347b50e0f792427a2583c5ed6358250293e5d36632585a202d3f476e76855560844a3010891e72402f9ca7c1ef8dae3a3d8aaf20f4cc47830fd0a6bcd9adcbab196fbabb30c439eef6208a55497785591b3170b375", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8dc39cab162b5ecfeb387365be0497ecf3ceb69817352d9280526c0f75de7c14184bdfafc9427bbc75e549436fc0749ee4f6acf063a9661c81b3024fc653ae79a"]}}, diff --git a/txscript/data/taproot-ref/349dc9e7f879b45a530ea9ac4a5ee92a83b80b64 b/txscript/data/taproot-ref/349dc9e7f879b45a530ea9ac4a5ee92a83b80b64 new file mode 100644 index 0000000000..91adde0e48 --- /dev/null +++ b/txscript/data/taproot-ref/349dc9e7f879b45a530ea9ac4a5ee92a83b80b64 @@ -0,0 +1 @@ +{"tx": "2b7a7ca6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4700100000089a957d260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707900000000d42a2be001ef6b390000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79653020000", "prevouts": ["076c330000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "f6b10f00000000002251204c956d2ed9840e95134d355554a887a299d70036ebf1550bbadc52fbd9ddc36f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365c2c02039e1e8eda45733cfa19a15344bb0ca6a0e9236d9dcb31644a405809ec"]}, "failure": {"scriptSig": "", "witness": ["6a9d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/34dee51305402e7e6b502025f00f29abbde3cb18 b/txscript/data/taproot-ref/34dee51305402e7e6b502025f00f29abbde3cb18 new file mode 100644 index 0000000000..de99f8861d --- /dev/null +++ b/txscript/data/taproot-ref/34dee51305402e7e6b502025f00f29abbde3cb18 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca0000000001422ed9c02a9f24a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac7edaba35", "prevouts": ["61b24d0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902475f66f483f4c6e7b20e1b16a1d2064a82f252c8117a7ca458b3ff3d51aab9be705f73aae5be6e70f0fe05ccba31ff8a440307e6f18cc7081041ed4b81abaaf1a12e6b5fa427aee1c1ecc074d19b1fbb031d6280e42657dc0eb83d1fa21a9b432991b5f7d1d471ca28ae773dd19b2e218f21a8a3adf4f0ece04226e48d01ec4d26f078b46ff5719a16237517bbf35b5a164097fe733d5973f5e1a9a91424755d4ea17d6bd2459ccdf52a5468bf1cbf5b3413c1f799cb59f731a66229a06c1cdeee53af08bdd3e641d204a229c2f1dd4dbc1aabd7b460a1b157695cfde157aeaf1887362baa734e82bf73642c3c6c57fb07da34ee35ba51795053309e41014fe6eff5906741fa51dbe6fd47e6436935c0e956dfb5cd52f04259ec76b737f1e8cad11ae0d1279268650e3e4ab23a148c79b3423eac5119a34d42b716aa32db32f8aabfa156b6a7946ba3c65515e13fd06a871a851278855da192cb5cae8dcffd76f8d6504390a9b08593c5ef7b4a79d6e5f9063a92ec78cd43c6cd36d2cba6dbe43c02e94b956f291ce0159448aaa20be2d8d40761017078558278e02bf074c2e224832557286fb997596f529dd80c0ff86c45ed6fb5fe866f5ee66260777e6326dc6e90b2e750214233f385affd17e4f8ef63a4c4e227a8a060d621db34ab81036acb37d0abb6dc7a3ae97a6b337eb802d0f4285f3bcbb9329a9702e94dab04299e94845aec0a563ff17583", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08299aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb439b32d44b6ff86c799acdff23ced11a294722ef2b8af6951bf8429e3bda52b31af3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}, "failure": {"scriptSig": "", "witness": ["4d0902c579f8af5ad6cf79aeed517ec77400fa5ae2353ecb0ec200b08c233d23b36901469edd1eee449acc62eefec3271e63f3758c66545059a6b2cf6ff59dcf97e1776ba998c71a2be633fad8275f7f05694a7f90d660a61bd8302561dd5d9fd4b6da5405fb4f4733cbf76ec120c93e00c13d269d1a47937797f44a8a93d86aeae0bbfbbf66468b3ec9cc6d91fe321bebc96f40009dc71fa4485e4f8ded6c631e4f0f289c478dc04b620b5ec72cb2ea20b13503aa4e150f93fb8381d404e3d41977049aee2fb4f3c49dcc572f1eb640b83e7b82385622db518b185a05a8f4fd37efea2b3271e2dbbf6140ae97baac4cc04a632e51834806b3f3768d340ae0d7408298d695318e4e435d90d1af5b103836513906dbd072c9dd943944c25330aa6d591ed8bfd881d245770eadd8f0eccc6dbc01099d4801848fa6e09eb0cff638384541b01b55299b4f83fc09e13b97e3f8dc6192f7bb1130099a2cb7a69fda912108bf8a91c675cf99b1c768f69a4bc30b141da96a396f38c2652690909941f3f4e1d54991b865afe0709db772ed53f8e74057dbb71c2cfd12d2840b11e44fdc74bc276db2a6c7d5c2b74554450ad9291e12c513b758e3e41a7a768e6098a9841cf61a4a3676df32a0d122a55c5f5f0c46cfc4b25d68942c303dc1bdd2a2ee4ed5026bfe694d39847b0779496ad07751c1fccad377bc18f661e3786ce1813c8aec4e1225aa6ea88244b415af7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d518f4301bf594f01c0bdeaf5c3d617f0344f5f915f3ffa16d6ac31751e310f3332b0bdfd7fd43775a37ae3e20c8f8514aca25517db969733cf8d9f690f9b6d8ea23f980255362d30444bd4a09dfd60422f4fe5b70b7cde78729ca8cd52cb50aace"]}}, diff --git a/txscript/data/taproot-ref/34e0f433a921b809a71c9924e9c0956dc34bc220 b/txscript/data/taproot-ref/34e0f433a921b809a71c9924e9c0956dc34bc220 new file mode 100644 index 0000000000..c77a992921 --- /dev/null +++ b/txscript/data/taproot-ref/34e0f433a921b809a71c9924e9c0956dc34bc220 @@ -0,0 +1 @@ +{"tx": "4b61cf630260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270550000000048887186bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1902000000afa4fda102cbb3790000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8728747447", "prevouts": ["5c850e000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838", "74946d0000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d94c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363223f590d275dbf98f3959a26c5345f553357b5bd8a825b42274d58542b11fc5131be74f8e69d59b35718025ad78971477354696379895e31ee13c64e6c94e9a3a6c94bbfbe0c8d8162307ea587875a7b29cdfde589bfdf70042a40a3445f95ec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}, "failure": {"scriptSig": "", "witness": ["4c52d9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f2df3669f0ebd61b1abc5e44d231fc82a1446c69bb597cf670e574f96771c819131be74f8e69d59b35718025ad78971477354696379895e31ee13c64e6c94e9a3a6c94bbfbe0c8d8162307ea587875a7b29cdfde589bfdf70042a40a3445f95ec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}}, diff --git a/txscript/data/taproot-ref/34ebf584d708a418710a1466a3dbc67b82146196 b/txscript/data/taproot-ref/34ebf584d708a418710a1466a3dbc67b82146196 new file mode 100644 index 0000000000..9a55c5f761 --- /dev/null +++ b/txscript/data/taproot-ref/34ebf584d708a418710a1466a3dbc67b82146196 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1000000000e348ed568bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44e01000000d194e30f035234630000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709ed1724", "prevouts": ["119624000000000022512048dae93b9a8752a11e2bf9d811f71f83e914d496dade834e573813f3fedfdad6", "607441000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ce60b07daa005e7e961b1cd1197a880b0926a9defc492f43af4f596fa4d95286ebf10485a7565da4888b0296454aba30a39a8416dd3eaaebe7fea4a18750e931ca477f7eac6c013e182e33a949b526b028f901138401b50189d2a4f50cede7d4a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b205b49dca00d66246302f0b0e6aac7e300ad432a7c010b19b7b2f949f7f012a70b4d2addc31b8421907b0cff80194a5513593e3802bd921239c9c6063ea806bb655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}}, diff --git a/txscript/data/taproot-ref/34ed3c4ed5af89953d2e81d21f7c1e45d2c7dc87 b/txscript/data/taproot-ref/34ed3c4ed5af89953d2e81d21f7c1e45d2c7dc87 new file mode 100644 index 0000000000..99738d0603 --- /dev/null +++ b/txscript/data/taproot-ref/34ed3c4ed5af89953d2e81d21f7c1e45d2c7dc87 @@ -0,0 +1 @@ +{"tx": "e3469bbe0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706700000000c719f5ba60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709f000000002924d0bd01b5301900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac88030000", "prevouts": ["17b91100000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81", "09fa0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902e1118f7cca20da1def9023630ce16f7f5835312be8eda360288bfea17af2b584c5a23e00a9a7dc2f353ba7896709dce82fc16191727b3183f782d36735c96099fe64b50e43d59716fcc3be7bbe76dd3ffd7b0c48a52f5c0065c51f7798af8586ae4d7b94e431407c6b932957460eeee4db73e5697831eef08d4f1c36482c0a73a1c1c7db964d2cd7ae17cde2b332730f90fe27c014cd537d33df94f2efe0792be51a2e13404233f292d33f559f283a1fb45c05d9be9c0733d3f93a3afc8519aa4891fd45fa45710583e767aaca334942360bc823166e2d7bd1f7530b639b6405dfef02e05314c9ef5f74d0d6366228a109c3c87e1633456efd01d544bc972af7b44f12ec87ae432486f66f46cfac9e0643fc4119fba979519851fbb256dc52d8e21cdae6a7955be486547c097041e2096f43818dffb0537ae1286a8c19b65dc777407f853d6ff9296a920deec6ab9bab6cb8818a144597b0a5667d2562f81a9bfb6afd454c0c4934557edda2945543fb9aba37a87fbd38ce2f39689b7476595afb012ddf72298d9e8d7d157a25c9fb1b49a00cd3177dd4c61da1097588a69a464c517b1154f12b35e50848eff7e37e88103a076e5e132736e422ed915aef44a07ed0de6627a7ba5792df9cf79b300b8b7e3aa439e839c2d99ddecc9bec47c8c33a9aed652d5a60e14695ebe74cd093fa15fab53bfbac61d4f32be775f298d610e8030d84c23ba6e8de7596", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b28c78e356042728a8dc5293f4719d9544479381d7bc53161d8023b722566e5250874a9774daa89f30be275a1ff5113653dfa1548b9628ff9725cf694401ebdfe4"]}, "failure": {"scriptSig": "", "witness": ["4d090208e2fff581ba5a50b839a109a158f1ae9d512e8b8b5141a4d95106120a8a86d5bec55e773653bbcc8f0f7e0557f9b3ac7f0c8c187908d8a9dba5c3fb734073a30e8d8f527aa72ef8511b79ded506b5deb47352adb253a20fa8f286640a39ee2be0f79c9600f0efc763a1a815adbb227812c2ffd46cad34a865714dc5c07d86a0d54e7600e0902552780d4424de339261b55188228557b692619b645486beb36322fb32c3c7fd431bd41309f5f4f7caba891b1b50671f24ee6751cadb0c749a43e23556e634e8a66907523b220127214718be0f0eb003b05a277a35cc26c2fc284c71a2f938c866f3b3e79c5ddb4d2ed1fb2e13076181367db83194072bd57c9b59a465e00023e5a4181a5bdc61fa69009f198b6adcdc6aaa2b30469c453f9ef5eaf5a63ae0ef2bf1b2d3c68ebaa80238764b6fd117b90b3f9d961d38d670eeebfe4a13f7e03ac64bbcc9a77b30c94416bd9b073e8c50ea87b5b6e373772acea1566d3b3c5ea5b962d223c3b7e2e4aaa16c9ad32ea14f6f4209d8eab409766bf1c5d1c9144a49e319263a1a0785d9b5526ce4c073561f604a4894f6bab7d2069166ea7cd73d2ce5c187fe5f2528cda247e341c3d15978a9954b2da9bd74bc0ad5a2511e7d86c41efb5b7c2ab404fcad2073cec1fba48d8f2bffe3f2d05d519fa964bce785d18c47b961972bc1afb784a3509f2cbedb256e3a73c089e5df3555408e543b1dd309dcbb867561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821bdee2e16a63898e861f6346f98a8f5f2a90fe2be47e52912f18205e56fa5c07b35fa22f4b25dbc3a6b67e691e1ba7f45df255baed4abd058cf23fbf36a7f21681a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}}, diff --git a/txscript/data/taproot-ref/34fe51570c93ab7b56e8955a00795a7af3eb88c3 b/txscript/data/taproot-ref/34fe51570c93ab7b56e8955a00795a7af3eb88c3 new file mode 100644 index 0000000000..7ebc19955f --- /dev/null +++ b/txscript/data/taproot-ref/34fe51570c93ab7b56e8955a00795a7af3eb88c3 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2301000000aad2904b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a6000000003d041d050193d671000000000017a914719f78084af863e000acd618ba76df979722368987d0c74728", "prevouts": ["5b7f6c0000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "663a0f000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "a47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93662a72c7361d2eba7ec3a19fe348f0f06b8ad5a36127d626cba43309febe57ca2d5e071d65b1ff2cbb44adb2a0836dee99e48dd3c256c0643eaf2d4db2ac89d0f9da521cfc521edd35405d6ff7b10120e980b699014de05f8e600b437ffa9c347"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa1a56f6cf7d9f4db4b4e32634d67c1bdca6b80e06b787823c0e4d06c57c1163a2ec4f69e5cd9a0f0c1fda8eb2f54297e33bc5edab35b299e65e2653a923d6ca55"]}}, diff --git a/txscript/data/taproot-ref/350219ab2d9d1993c2e0ad903f92eaaf6318f133 b/txscript/data/taproot-ref/350219ab2d9d1993c2e0ad903f92eaaf6318f133 new file mode 100644 index 0000000000..b00ce11752 --- /dev/null +++ b/txscript/data/taproot-ref/350219ab2d9d1993c2e0ad903f92eaaf6318f133 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b85000000009369fd8bdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce3000000008641938a0366ee8000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce86e6736", "prevouts": ["6ac7250000000000225120c1ae6350d5e25c8637e3643ccad16ae3a3009b1bad8c1dbb165abd62db3354a2", "98df5d0000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364dc685ecbd8fbb467f50be3541444cace52e2a96f82f6e3a97ffe7c20b40a1e235701ef224ad20174d0190f97f9f6d3f23a41bbc27fc82fd96c9e1fc2f7b2cb81ef28805a30acff873fd9260c6b3bfee2b626467fb0ce04f716d513a8a4b08b6f288028cdab461d62f9273620b97315e6e9af9458f777a616c1bade2d3f6a89e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f183944a14618fc7fe9ceade0f58e43a19d3c3b179ea6c43c29616413b6971c1fd87b85adb72b018dc8118730af51fe2e1fc2345a45c291032ad5ea0f36db09afcaf82673e7b509fa61dcb6f9390da3a7ce1e18401449d1277235bd9d9c04d9a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}}, diff --git a/txscript/data/taproot-ref/351979da8be9a1fded3861db5068a083d50516e7 b/txscript/data/taproot-ref/351979da8be9a1fded3861db5068a083d50516e7 new file mode 100644 index 0000000000..020198bceb --- /dev/null +++ b/txscript/data/taproot-ref/351979da8be9a1fded3861db5068a083d50516e7 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270780100000092a442168bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40500000000ac1f958adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2b000000009c4898ea02e6d16d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875a481120", "prevouts": ["2b3f120000000000225120c10f9a5287d6d37684b1ac107332d66417d952fdf60fb9cd3e9fa5de48c339b4", "fcef35000000000022512070bce5a25570b494d89a85af7ba09d895150a56587b7f7acec0c02ca42514b39", "91f927000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93642a698c787d1b847cde6e98849bca61e9a55d0a1c0c2fad329979ba621c74795"]}, "failure": {"scriptSig": "", "witness": ["6a44616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/35210e4f9eb6f063e680746037b199244fe0997c b/txscript/data/taproot-ref/35210e4f9eb6f063e680746037b199244fe0997c new file mode 100644 index 0000000000..2b863dc5fb --- /dev/null +++ b/txscript/data/taproot-ref/35210e4f9eb6f063e680746037b199244fe0997c @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e00000000082a1fedbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b040000000078251ec4037e9167000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac33248d4d", "prevouts": ["aec841000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "e5c4280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_31", "final": true, "success": {"scriptSig": "", "witness": ["a158bebfa7f7e39bb3bd9f2c9bcec51c834aa081291ebf0fbd28b4cd7fe4042fd70875e62105e87be40abc44c6f11600c4be1ff516e1b55e28cc2c81f9951be883", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["dc1f40d2c785e4e5e2450796e46fff01d27991a54698f5782ce784108eb1c5995e082e94bbed1262006a52eae43a8836c65a0c8c1ed15a944cb9ce5050fe8eae31", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/3569acb6b68f7aed0054e44b1fa854e2ef33b96d b/txscript/data/taproot-ref/3569acb6b68f7aed0054e44b1fa854e2ef33b96d new file mode 100644 index 0000000000..a0746f4585 --- /dev/null +++ b/txscript/data/taproot-ref/3569acb6b68f7aed0054e44b1fa854e2ef33b96d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4e00000000a4ee171060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708b0100000082b99690015cef6a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc8000000", "prevouts": ["f6f17d00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc", "84ac1100000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "317d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936baa8b3b4b8a0b13d474f8e303d1fb88b1f31b08e2de6caa1fb01bb3d4c0176023f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08228c5b97b98364e562d83f29d0f7226f72eeb298058e828607471d679ccabea05a4517c545b323e839a783e2c84e61e1f1046ec65ac2c085bba4fcd3b8ecf0c89"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936848a98c8453c3accedd5d6c98b5c0c5ec67507e057504b5eef02067a388f801228c5b97b98364e562d83f29d0f7226f72eeb298058e828607471d679ccabea05a4517c545b323e839a783e2c84e61e1f1046ec65ac2c085bba4fcd3b8ecf0c89"]}}, diff --git a/txscript/data/taproot-ref/3572c1cebe263656185dea9403422e9884954499 b/txscript/data/taproot-ref/3572c1cebe263656185dea9403422e9884954499 new file mode 100644 index 0000000000..85998c60a0 --- /dev/null +++ b/txscript/data/taproot-ref/3572c1cebe263656185dea9403422e9884954499 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba800000000d44957fc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127059000000009e3999d502b1992d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ace6010000", "prevouts": ["9ad1210000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "92710e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["814c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93649f82d663a1e447420f2cf05179af13964281439b8b427a6cb4b09af5b0cc191d3571a06a1d33120289e06483b2785a7356eedf367170ec7792d3587508789d4da9670c383f4b71f5a22d48df0589bd68dfe195935a65f1aeaa80f10f8ca6973"]}, "failure": {"scriptSig": "", "witness": ["4c5281", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366acb6639dc224661965f1c40d35e3666caeb8dba1d8ba77ab5b688daa06db8e499aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb419c228cb7ae814d70beabdb725e2cb3ba4f8af3a16648b1300fc97d27ac433c5da9670c383f4b71f5a22d48df0589bd68dfe195935a65f1aeaa80f10f8ca6973"]}}, diff --git a/txscript/data/taproot-ref/3574aa7865915325c364ab1364ae532d35ec2952 b/txscript/data/taproot-ref/3574aa7865915325c364ab1364ae532d35ec2952 new file mode 100644 index 0000000000..43a5092d62 --- /dev/null +++ b/txscript/data/taproot-ref/3574aa7865915325c364ab1364ae532d35ec2952 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f601000000901c05e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9900000000916fb3af02ceaf58000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a622010000", "prevouts": ["07680e00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "90344d0000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e868e9a99c27257089f8586472cc94222e874ab5c5b462fc98ac1b045b7a37dce65323990ac9ba96640afb66df99f25054f5788ad16157a03b33c6c26a70bd925e21136d3d9ecdf371b2101a7e86edb56e15b10ef185a8506988239bb2b5a4c43e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a48ad409340116ac239d5c746dae159519851dfc1ab3c3ad2152d495f5f1663b52e804f6a261e09ec86c0fb6e6ff5b26564af7d86f56b1539029a07a3794a04021136d3d9ecdf371b2101a7e86edb56e15b10ef185a8506988239bb2b5a4c43e"]}}, diff --git a/txscript/data/taproot-ref/357c3aca3897a104f6b209ff00a90eb8f93c11e9 b/txscript/data/taproot-ref/357c3aca3897a104f6b209ff00a90eb8f93c11e9 new file mode 100644 index 0000000000..abbc024db0 --- /dev/null +++ b/txscript/data/taproot-ref/357c3aca3897a104f6b209ff00a90eb8f93c11e9 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe101000000a64555a502d9916e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e74d1fe352", "prevouts": ["a550700000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a2964428c5627bca847605afc80c1617e4aeb928b4472ea19d347e6adf351dd82af60a6b1ce41c85915f4ec0899b6d6f1cca85ed4f86462d464658804bb71b3aea89f0fbfd9dd813268d111dcf81525d56b9783f0f98125d92d41e0fef09748813099d5e1d6a1ba1decf29eb688da21dc9d8f2c43b15e6199aa8fdcb835c5d013c3f13ba0d2d2f679a59679c3f4e557898e02e9b4640171ddb37a28c20a2d3f299647e3e99a9d82a3e4571ea170ccff2b5ae28b402531a470c9ba2e2f8cb91cb3cac4c3f939ab8bb450f63f4214684ebca04065a69d63da74880d4c482873322a12e073835179fe80d1d481ba4fa541e5ded02eaaf75bdc032dc4a39584fa3d7cae88d29bdc72627ebacb9a3a1a370e60549108e373be901ee4937394990431f9776fb597d72e3b1496aa7d124535fed9eb9ec83b411a60dc970eb8328d9a87626967c21f1ce316d5d7616306c899e91e8a63a79cf6689506895bd41428005561ffe726c9f3aeded4f91f7f99bbebb81d93eb1648cad1949731d9db76ef0d77838941151d4539edfaceac81dba7d39a20975c58775fea38fd52b219475a923a18da65fd0d805a5c96ece838500d5f987cbe1d9568079589dec9632deb75affd0d4afee73f71787065b1e3f4f5301a418b90f4bb0787b94e54e54e68746bd1851e638fa1cf691d53017a976db98982361716cdeaf67ee2bd89276446a851a136f92f0d66d90533eb98b75", "da7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fabb1bf216bf716c84a1c7f4bdf291db4b4c93f804d437ac6faff07f214860f972566ba3404d3656bfd0df4a55f82c254cdba579fd51be164a5cd21fa2faf92a44"]}, "failure": {"scriptSig": "", "witness": ["4d0902a7f4d0ae60acc87b60720ef208df3f6881c53b5b422ec367d4193d1a9af76b29d2ca7f2ecd176f59a79329a7e0aa40ebc4f4103eaf89d8e3ec96cde7c400212b07fb2a449f35e6f15c2aacc9e33bd2112e6ab98ec76dd1993b76bc932da5a093a64c84fad222d73b29f67c86003da9a9fdffc4a52403e2dad01fc3e590d3c438e6ebbab48d2ae356c0b8ff11278c8440fd5d9dcc4806e14526848b1abba4b7e6a88f5eca475b3349560b54ed0b2b7926341e5ab86248a3d94cc27292473b85cceb17a27410c30802de7e0505232f0c474a976d6897c96e88b8959e8bb9a8e66672ca4a5902d55011ffd3bbb5cca1f5da1eea9a30a97723bf78a37be3fe3fd6669903e1f2b29b7b1f85d38c5a6f5a6513860d2d4cd3cc9a9b68d2c04881b5d13505e9eca66a752990cacffb536c49ee32745cbec92fee57e0c481c66e1ad1b2ff16ae7c8b8c748bff30e0b916749de47c50b6eebac7632340a986c0ab2073919132b3126c4df6588a46b79d1ae0cc73ae2f423bc123e4f0ba8c33113196e39bf00803ea0eefe5f269741fcb84d3b9abf0478e34109cbb792f1267de62d68656448e9841f99a94a5f0135185ae67a830ba0b3e5fb620c145b930e51467fd29485e3547fb2df0d9b15d6b91b8112d18c6eda105f61c207bfe80881de30906598e40ad121088843e1e6f9d7f774852a94be5035bbb0d30be8f054791dddbb71de9dec85639c7e5ecea38d775", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93619e18d071110c5abaa139a6d0bdd1af7c8aedfa20831714d5471a7b6fe83dab09a29f5cb7818ea23e4b491695dace811707e8772e99626d3237c076ba9a076d6566ba3404d3656bfd0df4a55f82c254cdba579fd51be164a5cd21fa2faf92a44"]}}, diff --git a/txscript/data/taproot-ref/357f1e298d27372ed2fdb360e6ecf4b4f93bf38f b/txscript/data/taproot-ref/357f1e298d27372ed2fdb360e6ecf4b4f93bf38f new file mode 100644 index 0000000000..b40f9aa55d --- /dev/null +++ b/txscript/data/taproot-ref/357f1e298d27372ed2fdb360e6ecf4b4f93bf38f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffb000000003c3851e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2b01000000a55d69fe016a56890000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796cd000000", "prevouts": ["ae147e0000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "731e4d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["de", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f9ea8f2e65eb73025cf4611eb81b9bc973c238c936328a8046b3068be11236b1823ff0d5c6a769fa09e08a59a2485b611e1511239bba2f80aba2b92be945f1b811034f174cb7bd77652d345f06878a8d4eb3ae1b92590cd10e2563bf228d2d6bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb423dda11617dc042479e1d576056805c31872018ddbd603e5e1ceb926e90a3395bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}}, diff --git a/txscript/data/taproot-ref/3585f3da19dc73f07d513f4d5e06b3af35381aab b/txscript/data/taproot-ref/3585f3da19dc73f07d513f4d5e06b3af35381aab new file mode 100644 index 0000000000..f05923ee72 --- /dev/null +++ b/txscript/data/taproot-ref/3585f3da19dc73f07d513f4d5e06b3af35381aab @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705400000000d43674c0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0201000000aeba28e203296f2f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df97972236898731a52e29", "prevouts": ["cb58100000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "f13f2100000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "b67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368f91b6c4c13aa4ec71d33e29eeb31c6a6eee39b0d151b2bf968ac977aa50b78419cfe9d552d59ccbadc4f3846c4b5c3686f3389826ed032a892d1ca338e6ba63ca37f8027c2c0b0d436eabba5be8b19fe8a47d5b17abeebfa31c0139f25f704791244d1d955381053a5c36db6928ef13bb9242569ee84b58d7018329936aac78"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b4dd63163ec3072393586c7919962509f9d5e063bf86457cbccc929d8e7b42d23bc00f369fc994f47536ced64d5e4f722a68c2ed1128957c24de4b5158af0ec621d9a3f11774810afeba87c9188100d693899e640a37210c96e3be6a00ac01d4"]}}, diff --git a/txscript/data/taproot-ref/35995d78575bb81724c123126ae84f04c1ef1324 b/txscript/data/taproot-ref/35995d78575bb81724c123126ae84f04c1ef1324 new file mode 100644 index 0000000000..7af830af2f --- /dev/null +++ b/txscript/data/taproot-ref/35995d78575bb81724c123126ae84f04c1ef1324 @@ -0,0 +1 @@ +{"tx": "561ea52603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6001000000363305b7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd501000000b8f01b8d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c442010000002b7372e904bd41b000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748703000000", "prevouts": ["f0d7250000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "3f614c00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "cdc840000000000017a9148462ed29696925d7688e1db8e76ef9e6667f05b287"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21551f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["80972288adc6d7cba75001f1141141eb3686c9d3391523c89ec8a5d51191b31f7ec18951bd568e4fbba5d6e4cc84462a06b1aeaca08f8e5c0bdb85d868bea8bd", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/36107f7e7692414cd4ae5e7ee06a1e46821b107a b/txscript/data/taproot-ref/36107f7e7692414cd4ae5e7ee06a1e46821b107a new file mode 100644 index 0000000000..e196f02b75 --- /dev/null +++ b/txscript/data/taproot-ref/36107f7e7692414cd4ae5e7ee06a1e46821b107a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3001000000a624d4cc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700802000000f83632e9019e1b0000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac56000000", "prevouts": ["d9161f000000000017a914e18c03fb168c1c1b3408ffb477de8ff77b0fbd9587", "c0db110000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["e04c767dfd5b7d04a7575a895a890a96fec52479db16d1360413e16345dd2561ec60f703c0d427d470048b256f382fe9264326d51f90733814b5cb3a78703739", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/361314e0baab060ff8fb2888efad4f841ee2e65d b/txscript/data/taproot-ref/361314e0baab060ff8fb2888efad4f841ee2e65d new file mode 100644 index 0000000000..37a39c7ee1 --- /dev/null +++ b/txscript/data/taproot-ref/361314e0baab060ff8fb2888efad4f841ee2e65d @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127090010000005ac683e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c380000000038d3a0f20107b609000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87cd821a49", "prevouts": ["b65e0f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "d17c4d000000000017a914a68ade9e67dbb5e8acf044461cfd5bd8dcf592c387"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1652142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["1c57dc5cae11418538bd0d2602bc9033ee944789925249b9dc13189e5fdda2d00395bf36c138544c40aeded5fd16f11830dfa8931a56fcf656d1480713061d0b", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/361c2bf607441dd9ae1d9e592d08aff1c4423aec b/txscript/data/taproot-ref/361c2bf607441dd9ae1d9e592d08aff1c4423aec new file mode 100644 index 0000000000..2e28eeedfe --- /dev/null +++ b/txscript/data/taproot-ref/361c2bf607441dd9ae1d9e592d08aff1c4423aec @@ -0,0 +1 @@ +{"tx": "a812a8340260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127011000000001b84d5c560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b90100000047458cbf0119a31f00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acba000000", "prevouts": ["7909120000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "c8670f00000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "697d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89363a1a9e3455d5e541eede6f35654fff6287ec2d2087da21729e13d6d7b575f3b3c2b944ff5e8034ac7518513c5ca10ab4eec025a723136fa482de383e24ff1"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936af22b4901457eb456597ad7be41b200460b2a53b5535b5af1e9b3a1b5edde2e99363a1a9e3455d5e541eede6f35654fff6287ec2d2087da21729e13d6d7b575f3b3c2b944ff5e8034ac7518513c5ca10ab4eec025a723136fa482de383e24ff1"]}}, diff --git a/txscript/data/taproot-ref/361e67ace54dd8058e82517e87d5a294ff0e2430 b/txscript/data/taproot-ref/361e67ace54dd8058e82517e87d5a294ff0e2430 new file mode 100644 index 0000000000..d5a9c31ad3 --- /dev/null +++ b/txscript/data/taproot-ref/361e67ace54dd8058e82517e87d5a294ff0e2430 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8e010000009d47f8c3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9c00000000643f149804cd20a300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac550ddd44", "prevouts": ["3958230000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "01bd8200000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["8d4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368b6d963912b4b21c343ab35d829758acd38b20aa323c58d3577851a32d8d38189886f85ebb300297009aa959255e1f8e976b091c7e06b33477ed400c40a83b4c185c953dbf0a33402e724bbb72e47d874a897a0941d53d9706dc82e2e14efc19f43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5188d314ba4ab03912e470cb461a645c9914779a4907e0bafc42fbc04fe8b44a37185c953dbf0a33402e724bbb72e47d874a897a0941d53d9706dc82e2e14efc19f43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}}, diff --git a/txscript/data/taproot-ref/36225523764ce0fcf4a54ecc157c7a9ee0ca5e1c b/txscript/data/taproot-ref/36225523764ce0fcf4a54ecc157c7a9ee0ca5e1c new file mode 100644 index 0000000000..d2802f6feb --- /dev/null +++ b/txscript/data/taproot-ref/36225523764ce0fcf4a54ecc157c7a9ee0ca5e1c @@ -0,0 +1 @@ +{"tx": "bc407aaf03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6600000000004780dadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9500000000b762a584bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfec00000000c46558bd01b5e525000000000017a914719f78084af863e000acd618ba76df97972236898718b7f726", "prevouts": ["d3706e00000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "a20f210000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "60e3700000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6afb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4006cb24f353cfca0d245645f6b16ad599c212098eee86bd01fc37c5c4a863127c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b29f7cabfb957bba526a47fc91b61b10aee27eddba24db724dc3d01c8c4f31434c1cf5ffa00c6c7050afc353617823cd679ab4db6c6aacae1c16f62a2980653852b51aac478484d8a075e848b67a41ce9b347e1249fa49816f898b909a6d4bd5c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}}, diff --git a/txscript/data/taproot-ref/363516e81c7327e6e8535e74da1cf78a4a939bf2 b/txscript/data/taproot-ref/363516e81c7327e6e8535e74da1cf78a4a939bf2 new file mode 100644 index 0000000000..7ca225962d --- /dev/null +++ b/txscript/data/taproot-ref/363516e81c7327e6e8535e74da1cf78a4a939bf2 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1101000000c10c2513dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4a000000001013795b0240fdcd000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac35020000", "prevouts": ["660a7d0000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "ea8852000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "final": true, "success": {"scriptSig": "", "witness": ["d728ffd3b4e5ee0b6ce4d3eadd407ec13a93466db8301b27f68be80942b82a09ec004eb01a79e36188d5e309ab6f1597fc4d1a9e686b0cc6c52861d6c281ccca82"]}, "failure": {"scriptSig": "", "witness": ["0a2eee076946409f4b97aa446498e63db0bfbc131467921e8e2eec44a70ec8a3b539782dd8d7da4b23add8948b476438234ac66ae752aad19f5b9d8bb103609482"]}}, diff --git a/txscript/data/taproot-ref/363d3439b183bb0f2c6a0d1238057e9beb398f18 b/txscript/data/taproot-ref/363d3439b183bb0f2c6a0d1238057e9beb398f18 new file mode 100644 index 0000000000..242632cee6 --- /dev/null +++ b/txscript/data/taproot-ref/363d3439b183bb0f2c6a0d1238057e9beb398f18 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c415020000008b24badfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0400000000376ef8070205c49700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689878c020000", "prevouts": ["92b3310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "adb367000000000017a914856f7c6a5a6a1ac0e553b769a4c35bcb9fb6f50287"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2353212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["5ec4552ffa2184dada89e5707a20eba875f5638aad7b361827fb125646ac0df368e7301ab8264c017a2e8be4bb09a7bd7f9d1d0a3a74617310f6cbbe76ce09e7", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/36415fab25c89139e82b030657b2f8d9f5d9bfc4 b/txscript/data/taproot-ref/36415fab25c89139e82b030657b2f8d9f5d9bfc4 new file mode 100644 index 0000000000..e972f9d8f8 --- /dev/null +++ b/txscript/data/taproot-ref/36415fab25c89139e82b030657b2f8d9f5d9bfc4 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127016010000005a40fda98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cb010000005cc4a369dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cab000000003c7930a40216509d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac25272e3f", "prevouts": ["2ae70e00000000002251204929a185ed20b7f7e86ae8920b068b5e7d5df0975bee6bbfbcd97b6bb81e709d", "b3c23b0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65", "8b34540000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "7b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bf376daee13dd63a085ad58e4a789e980aa4a44dc2b29700e972d7f3e78897bcd15ee116aef2a5177f7228fbf74f7a33b70e884325424982f9125cdefb107591d34322f35809060e9857f404c38bdcaf402c3d07c78e42a3b4d1eaa304dca88a"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93627167632271a67f79806a6d1eb3003f6a6b2caa9b61c2ff1392a9bd62be206b9e069ba5eeb0bec6bb336aeedfc480da3e66ab61ed5906063fe5b68f45dcb12952affe3792374ee751e9779d236e331236b2211c0285bb070b7e5d58aad1c033f64fb6de85916ce1333b57715a419fbbb7fd448155796c8af09a2e4a2bc14d947"]}}, diff --git a/txscript/data/taproot-ref/36608fb81d55d07d46c2f7849cd926ee3b2544c0 b/txscript/data/taproot-ref/36608fb81d55d07d46c2f7849cd926ee3b2544c0 new file mode 100644 index 0000000000..91f52c327c --- /dev/null +++ b/txscript/data/taproot-ref/36608fb81d55d07d46c2f7849cd926ee3b2544c0 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4baa01000000f77c2d26bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0c010000004f4f1f22031457a20000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f870d020000", "prevouts": ["3c312800000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "f4397c000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100d9aad57a3b6ffbe01e5aa610c80a31dac0435ed9ab6bc77300028978a0dfe9ab0220693cfd0fb01370af7d07b4fecc8b192e1a2216e94d42da27db6649c7fb4d3f4101434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "483045022100d2bf2bba76cc40c83e4fa88a78cca0a51d823926708c32ceef76f50f0480e74202200846b9fbbed97d2ae1c9ccb73e86cb58120d894da0f2c2486b67b3bb842a071f01434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/367c9b1f3074839cbe7794421f5a5a30b5392887 b/txscript/data/taproot-ref/367c9b1f3074839cbe7794421f5a5a30b5392887 new file mode 100644 index 0000000000..8f97f56573 --- /dev/null +++ b/txscript/data/taproot-ref/367c9b1f3074839cbe7794421f5a5a30b5392887 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c36010000009d36b71e047ee44d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88accceeb831", "prevouts": ["4bfe4f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b7", "final": true, "success": {"scriptSig": "", "witness": ["a4063c93b08049b6f9535c3fe361cbe0ba81ccf1de814e064ae40969d880a544336437e95c43e1308a425be13c2eefcb039e905154e344d7a65a50cf1defd24d03"]}, "failure": {"scriptSig": "", "witness": ["788a54b3f2fdc816b53744391b0112b0dd7da2e0905556986fec63395814c0b5ca80404ed642a2a031dcd2230f2d0b26dfcf9b3fd6ccf8f655c623f047ad96a1b7"]}}, diff --git a/txscript/data/taproot-ref/368c81b84650d4644c983e3209d93ebe140d375a b/txscript/data/taproot-ref/368c81b84650d4644c983e3209d93ebe140d375a new file mode 100644 index 0000000000..3b52341fa9 --- /dev/null +++ b/txscript/data/taproot-ref/368c81b84650d4644c983e3209d93ebe140d375a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caa0100000063e069f98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49701000000410c148c017dbf160000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e712fb6959", "prevouts": ["8d71480000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "40c43200000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ab7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936868a8b5d4fa4ebb812e9187140be33b96106da21b05039089cc432e85b6849d0588819b06684552554786b2b49e7cd3d9dcfc0725dc4b3b93f8768a6a84fb31b7c07bb1aa10d02d314eb70c923196d0e49e71087637e2d5a1d7fe44c2440c398"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93686c31dcf8859245bfdb2cad1cc94d16ee0f95fa651e4b9f3d702e098ccaa2b3aa05ea26d8201abb1a5c146c7fb3e541bebd813f78d5cb214a01f0b6fbe6f45888cb303569f28fbe8acbcc2d27d183e3a68170f5392df28f40a03efea695d856e"]}}, diff --git a/txscript/data/taproot-ref/36918d3941b615417b367e0dda84482198335469 b/txscript/data/taproot-ref/36918d3941b615417b367e0dda84482198335469 new file mode 100644 index 0000000000..2f5e0f791c --- /dev/null +++ b/txscript/data/taproot-ref/36918d3941b615417b367e0dda84482198335469 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b12020000006f9651d88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42401000000bdfd4f8d034fab5c00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ae07c92f", "prevouts": ["8131230000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d", "82de3b000000000017a914f7f3eae48087a4952a984cf9c1f2f12f8785754687"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "9a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93610630b77bb4590cf218c5051e5309756c31e53d1c2931037bcb12349387772a4703c0353c01e1109d81375c08919405978bc042794caf82a403da05ca89d0cdeef17902325999cb16876d9e124f321b7a2400c6233e0b61b95917979ea167214"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bf17dfde2600b0767befdacfef733adf21854ac1d2a618729f77c0302a39a08774224dbe9932044562df2f9dbf2ed3a87afba7bd9cf6855f9f40e4c24add8036ef17902325999cb16876d9e124f321b7a2400c6233e0b61b95917979ea167214"]}}, diff --git a/txscript/data/taproot-ref/36a94d7bc5dc9af664df029d9cacb70d1662178f b/txscript/data/taproot-ref/36a94d7bc5dc9af664df029d9cacb70d1662178f new file mode 100644 index 0000000000..d8a986b607 --- /dev/null +++ b/txscript/data/taproot-ref/36a94d7bc5dc9af664df029d9cacb70d1662178f @@ -0,0 +1 @@ +{"tx": "e40f700a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5d01000000e6a4029260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708d00000000b040e98602ca483700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72b040000", "prevouts": ["7b45280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2d0d120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_60", "final": true, "success": {"scriptSig": "", "witness": ["be007a4e43895b378db7bcd4461d8c69ace0ce7fd51d0cfdbdacc69ac4e742321e220ae6597c6a425a15f621abb7aad75636ce79d1d8a63a3446f3f8fb921e6881"]}, "failure": {"scriptSig": "", "witness": ["a9574ec4f482f856bf12b749da5c724444abe5e5e99aa9fbf424151d0089dac86fb575cc267a9769644acf5ec84080d9c5d6f56687885a6548bf37baa825ca3160"]}}, diff --git a/txscript/data/taproot-ref/36bc60267ff97612610797a43fa5e7b371687229 b/txscript/data/taproot-ref/36bc60267ff97612610797a43fa5e7b371687229 new file mode 100644 index 0000000000..bb1c215eda --- /dev/null +++ b/txscript/data/taproot-ref/36bc60267ff97612610797a43fa5e7b371687229 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e00000000082a1fedbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b040000000078251ec4037e9167000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac33248d4d", "prevouts": ["aec841000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "e5c4280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "867d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936926f2b50f3fbd9ffe22dc41af4426bcb82a03b8aad9cfd0cba46d108de7a4ac73ac108bed01ff7a3c4482bdb9637a0c08eda3eca9d378124f08be0fd1593c53eb98f84b0d7d6fcb38bca0562970da4fa4ac9189daad947902c07179846baca90"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f28332fff4e521a34f62a6094c9ca083df763bc212ee1a103146f1ea11bafd96b069f256e7b53185a64c953a8831f99a2248244dec917c9fc219bffc52b204f"]}}, diff --git a/txscript/data/taproot-ref/36bd6cf68074e03b5642284ce7d493af28e048a2 b/txscript/data/taproot-ref/36bd6cf68074e03b5642284ce7d493af28e048a2 new file mode 100644 index 0000000000..c966424c68 --- /dev/null +++ b/txscript/data/taproot-ref/36bd6cf68074e03b5642284ce7d493af28e048a2 @@ -0,0 +1 @@ +{"tx": "4013c48c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6201000000bf7eceeedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca901000000a70f748001caf00c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac9a82d82a", "prevouts": ["164228000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "eaa954000000000017a91439ec132e1466f40f0086baa7ac253013e83c7dc387"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffaf172eeb05afc6853709009cf0d3b6d15c8aef7da615bde3873221decaaac449f82d663a1e447420f2cf05179af13964281439b8b427a6cb4b09af5b0cc1910a67b80b81ed02a57999348bdd390384d424a2522cd0278ffab5313e035bd402791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045360c8600b70daaa5cf8f525cd2d4abcf69506a056a119fd926e23bd8684708da0a67b80b81ed02a57999348bdd390384d424a2522cd0278ffab5313e035bd402791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}}, diff --git a/txscript/data/taproot-ref/36c7fd31d411d45f3d03143f9a36158791a29660 b/txscript/data/taproot-ref/36c7fd31d411d45f3d03143f9a36158791a29660 new file mode 100644 index 0000000000..29aaaff465 --- /dev/null +++ b/txscript/data/taproot-ref/36c7fd31d411d45f3d03143f9a36158791a29660 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2c01000000a1ebc3e504f5da1e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac66000000", "prevouts": ["3858210000000000225e202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["b118a16a7c37649018445f821f07443fcc9bed7e28a4df387e18cbfe4f1ec41ba81f27a4055bdc437628c8c6f9c25381e0f582bf5b351b1c66d6d310404a4c07", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/36cefffcad6493e933315f78db381ff7ecc43bfd b/txscript/data/taproot-ref/36cefffcad6493e933315f78db381ff7ecc43bfd new file mode 100644 index 0000000000..97c8f3e02d --- /dev/null +++ b/txscript/data/taproot-ref/36cefffcad6493e933315f78db381ff7ecc43bfd @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6d00000000c3f473d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf60000000080c431b7017add220000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796f31d0d46", "prevouts": ["61587600000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "76ed4f0000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "fd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e850656d0bdb94b88d381f7a82b87984f770e250bf999894456706d2524183d15d62d72dd1cd8804fbc0be1dcf6a22214dbfb5210e6cde6f2a41edfb954edd50fb"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93648de95c4bfc2b10e0b5b509c1c28dbcea1b51ec6e9d986bf948a619cc01a5e2a50656d0bdb94b88d381f7a82b87984f770e250bf999894456706d2524183d15d62d72dd1cd8804fbc0be1dcf6a22214dbfb5210e6cde6f2a41edfb954edd50fb"]}}, diff --git a/txscript/data/taproot-ref/36db1eaf5e186f36042dd8afeeebfabe675c620a b/txscript/data/taproot-ref/36db1eaf5e186f36042dd8afeeebfabe675c620a new file mode 100644 index 0000000000..10b5c0eb08 --- /dev/null +++ b/txscript/data/taproot-ref/36db1eaf5e186f36042dd8afeeebfabe675c620a @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5f00000000392891fa03dd4e1c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48725e0654e", "prevouts": ["98d21e000000000021571f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["bc14b9cc54dcd0d113ada2eefbf6fabd4511fcba5923dff3c44b88c1b06bddf574cd80d1110e2cbd1bc459f4f3b0bf4b81ba3001b188d703c2400398343c347b"]}}, diff --git a/txscript/data/taproot-ref/36e7b1c9920f0e9a7c1c52c380c61f6b44246ce8 b/txscript/data/taproot-ref/36e7b1c9920f0e9a7c1c52c380c61f6b44246ce8 new file mode 100644 index 0000000000..5d71076be2 --- /dev/null +++ b/txscript/data/taproot-ref/36e7b1c9920f0e9a7c1c52c380c61f6b44246ce8 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce501000000881946a160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270870000000050efa3a7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb100000000ea994684043ae79000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487046fe641", "prevouts": ["b8fc5900000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5", "d298100000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "290d290000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "e07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366a34314d49dd780a407fa75b4326be002152b42e0347e780a2c6960ad067bedf3bc00f369fc994f47536ced64d5e4f722a68c2ed1128957c24de4b5158af0ec63ccd0bea79832f66dcec0cbfd0592e3eb2d999b46ac697170d667eb8939a9687"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd73d9d375b530aa22fee240902ecc7793689bdebd58e9771ff3d6e92b1aa7f5c13ccd0bea79832f66dcec0cbfd0592e3eb2d999b46ac697170d667eb8939a9687"]}}, diff --git a/txscript/data/taproot-ref/370f93aec0042473af8eda625b8e55afa266cf0a b/txscript/data/taproot-ref/370f93aec0042473af8eda625b8e55afa266cf0a new file mode 100644 index 0000000000..94f421d402 --- /dev/null +++ b/txscript/data/taproot-ref/370f93aec0042473af8eda625b8e55afa266cf0a @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d4010000004448e7b2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7e0100000089d641a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a0000000083a09fad0354caca000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acfa030000", "prevouts": ["5e70100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8e686e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d1414e00000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_79", "final": true, "success": {"scriptSig": "", "witness": ["68e2f257581e84c6f9db8e854b0819e47d32393ab66b3d2e241d05dfe5644d274f787cc0b514c60657514693aea2da275941b2656801468ae0f76b282fca837502", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["6cdf3a7f7d2142f98f64f3a1e1a2e2392a4b7314983aab1a2c95ea317742c0333168797dfb82249cc68846b2b8a2bba88de4e932a5a60ebac9d459ced3c8dcd679", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/3711e5aa1c94f1b0f835504e4dc9cfac933f247d b/txscript/data/taproot-ref/3711e5aa1c94f1b0f835504e4dc9cfac933f247d new file mode 100644 index 0000000000..f95ed901a0 --- /dev/null +++ b/txscript/data/taproot-ref/3711e5aa1c94f1b0f835504e4dc9cfac933f247d @@ -0,0 +1 @@ +{"tx": "7f02f66c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701001000000807656f68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43a000000004a3e6fa701c6143f00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd3010000", "prevouts": ["bc16110000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "a79a400000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090238aac846cef107dcfe5b06d54f7a835f803b8f46e9bbfd86772e71fca902bbaef77735fe5859ac6121d74cfb39179104ecceab851f1b7aac77d10ec2c713982da98749799b0a605fa46aeff5b6cf7705a70ba64133eaf44a2723dcb162d2c8a6bd696af167c2a62fad5c89d3f27ee0b5a5ac111549d7a09c84e7ec84a6e0dc828bacef37a198c4f10b47b0be848d318b02aecbc2a49ddb9063a855e1a8d04101eae0154d5d57af82f22bb1ea2ee1b98131867e796552145f42cd26018f13eadd2c8e0785663de4caa6f8f7a956712cceb704f4b39d5621bbde0c85e1b6e56b96c826e0b5f5d6303cb9c5e9918551913bd26ecd7b77d119d5985655ced9cd8abc8f7d2b7162eb8dbdb504c3afe009ce8e010fa2bb58d136094f1a955968db6f563c8587d8d1eedd183918a6fa2e0b45b2076d3eaecf49ceead718f6315c2f9177ff62f9488478da13d6ab1eca9ee10dc36b875b807aab1b8086aa564a39e2447b233133bfc8438da324c38c252f2656951623ef0d96cd8c3e71f7b5df7816c96ed987dca87c955a1ab9da9b45208e24f9d422141b194af646606209b0a7cac9b3e640760ce4cfc6cd40b0245825cd73e47028eaa55953680728c6be7395ea409248d069170a6106da7351f3dc37c3ce475d0365b380e0d6f50aae1f37324b5fd3e500766961a3e487db20a19844639df06065c9c22bee111599978607db5aee0b84bc90f821f7eec7157585", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93655a6e6bedacbdfd967c24f4020a4dae166c9c259a03b3ae16ac1a87dc32929381ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045952384bfcd198c969b60204543b8b578741ae3068409132e955e5c7af181f3d3734b3a7050eee065844830ad8d45a710891f78004f5e7f35b8fd72bf3ee94449"]}, "failure": {"scriptSig": "", "witness": ["4d09020a3ca49792f29cf339b8b3a8faaf531d4c2380b2466dee6102aff920557b65a1adcf05f51430b694be7045ece13921851be291038fac1ae725fae16218a8395489b659901af584ccd3fae26b52119d7395fd03b9573f21de0e4ab692fc935defdd8a8b510ecf405dc4112101ebad92cbdf603c211fd95cd9f12c1237228a37236a414f62204aa9125fead9116dbfed6f162712f9a2af18c9331ece4814db23f9c0fcc717581e62650dbb8dd85c8fa667416ab73f932a83d22cbcb9abdb2a49c84fb41ca764f1fb89628c3b7e82a39df6a12b9fbbfee836cd66fd1111323afb155ca7a625bb59cd3c0386c9bbb0d1431b24281500b89b0192240b61188c052a84265904815ac5447b7a56d368da651ebd6d0fe8ee39c4c655b2a997071befc5282c806e9fe3abcf8066692b8fcba4e12d3ddaf40ec146855c29d86ce1c765348f8d95969f28c9a312b44c61ca29d7ba97aee06d4bbb74d3539441417b29ff9e4d965003d1ec5118f2cfca86726fa8b0cb4eda5d730b9633a5c5e822749832699ae95892bab2cc6d7ee570c6963c1b04e776db2b1bb6ba1a71336df225e58de6efbb786989bf34ce30b5ac8340e521cae7c1f43d638ecea3d3d4de6ec90107f844919c4103f486be7ccda29866e4537e62656b18b1345f91d2708d158f0d7165a26a9913874570728d95c087b072e1b936743b0c85c1be53de3a0051c0404bb813c6f638cb56a42af77a7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cc8c0c7594f9800c68bdab4939f24615b278fe3bf8441cb0c501e2d28dbdb31cd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51f1361648aec2fada6693d9b39e398a39a20a7ec02f5f37d94bd6d3a28893e48e1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}}, diff --git a/txscript/data/taproot-ref/37178f03fde09a06a32ec4e778874ec6ff11c8c3 b/txscript/data/taproot-ref/37178f03fde09a06a32ec4e778874ec6ff11c8c3 new file mode 100644 index 0000000000..bd489d4d0c --- /dev/null +++ b/txscript/data/taproot-ref/37178f03fde09a06a32ec4e778874ec6ff11c8c3 @@ -0,0 +1 @@ +{"tx": "56711c2a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b55010000007a913ec4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccb01000000598666940321156700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac6c010000", "prevouts": ["f4382000000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e", "6595480000000000235a212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["11a3d09719fcca2565f6327fcabf0ca212fe094dce436586689b4974f57f1617ccb5deae62d77f37fa23314a360daed67993799d4f7c07e68efe09d1c52fd2e1"]}}, diff --git a/txscript/data/taproot-ref/3722cdc62a8920daf88999d381d42a7424417843 b/txscript/data/taproot-ref/3722cdc62a8920daf88999d381d42a7424417843 new file mode 100644 index 0000000000..49207e2a8f --- /dev/null +++ b/txscript/data/taproot-ref/3722cdc62a8920daf88999d381d42a7424417843 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c98010000002f66bab2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9901000000f66711d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf84000000001a4b64da03373c3901000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac8e020000", "prevouts": ["d1295e000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "7c9879000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "e9a063000000000021541f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["8ebebe2a7fa1a40637b1d39a565324cbb6d10bee6139bb959795df334617057c6e72ecd601dc2b3ffb697171f3f7e380b907435292fd3efe07d08431bd0845e6"]}}, diff --git a/txscript/data/taproot-ref/3745a800a4b496404473a26dd593f84588194471 b/txscript/data/taproot-ref/3745a800a4b496404473a26dd593f84588194471 new file mode 100644 index 0000000000..2d944437c1 --- /dev/null +++ b/txscript/data/taproot-ref/3745a800a4b496404473a26dd593f84588194471 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e00000000c57d4392bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4d0000000052ad4c7c030fba7b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8b92b750", "prevouts": ["9f611200000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5", "65ea6b00000000002251208b7fe9d4f09d2d8e7a4070c707b9c580ba6935dccb7bf02b3c8420577f22e1d4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900453e4c13dfee647a17f9595e8b3c65969e7c880cfffed6449fdebc16325bda3bb094cc415af9f84001a6feea45646803cad285186914838c4558edfc97d3166e78fd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361516cb28afaea3109ac1b2a6be9ee9c1349c985ebc1f094f91933a3c30e1118979a506f75037c50a9ea9c509d8c41e46c95fdf651773b41e5feb3da8f515025ffd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}}, diff --git a/txscript/data/taproot-ref/374e3814357798251b0430dc4cfb9f212c1dddd3 b/txscript/data/taproot-ref/374e3814357798251b0430dc4cfb9f212c1dddd3 new file mode 100644 index 0000000000..f78da89652 --- /dev/null +++ b/txscript/data/taproot-ref/374e3814357798251b0430dc4cfb9f212c1dddd3 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706c01000000ba310ba08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41100000000bb14c6b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b42010000002e7adaf704ccf9680000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987d84ad23d", "prevouts": ["3b2c110000000000225120e0fbe9053c6d2a439b1df3d9c89ed0e68b8279a92dae6907e23437dbb3b4029a", "a9cc330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6891260000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "success": {"scriptSig": "", "witness": ["bf547b49954bc50d0726baffe4902a07de414bdee0da2e167e9afad61312c1f45a986e2212a999b32a35e1e8cf7353b8c6d8e90b0efdebf9415893ea2f7ff7ed01", "057e4421e4452c4b7f376dcb03157853348c23cf7b32b1c447a60346de45229034e56168d2cc2d47a1162cda1c03108db0730de5b058866954418c066bf059c81a5ba2479a9eb079ad0038f0350648", "753535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a26ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93603873753c288255b908fdaadf531bc1d68ff88416a14514d21f880f381496ce6109f3f9fed7a7850479575fe09819c514312532a101591e70b3ca7a41015d315abb6d11f6afe1d94d9d9f8c365772775719ce7effb301ae3ad4c4b3953942c9a173da251af8551a60e870972ffb93c31d944da40128e84f75b2100254c09f1b4de06e3cd6f3b0b209a8fe563fc0d7d5531bbe10145b72019ee6951325ead69740e6aa5d2a3313b034bf7c50dc92f197b6f924bf5d188e80f7e83cc6b1df9a9200000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92bc58659211a4beadd8fa11a9845ff332b73538a93df84322b83e2be6806aec4a61dabd15e7c32b6ea531d34a692667bed8d7204672e2f2f1175218c050f78a3171dc5c5350b795a66ce38c1722adcba1fc40ef925faf53527faa391efe98bb3a827d6aae010ac333a59a738f4411490fa0ed048e3c7afb8a22b835690661deffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc817f1a371e950a12722586a5229873fcf0aed07489c9e7da60a05e7299def8194ed79115f02ce018b07d4bed9adffd7b00af1ea21eb1006ef232ab168648ba44c4c1787758d755a6445f19dd41348f06ed1b0f8a96cc9a729e5fe6ebc20288a3a2bdda781484822fd984a6a476ae7a39923a558edeba7b039c0d3c8536b086e0000000000000000000000000000000000000000000000000000000000000000976851de7870b0dd0dfc5cf582c477ae966ecdcae30037866fd3d0fd03f206e173dc23d909d6175f94b12ab45f393f9fe7a6f3281c8997a9ae1bd4f7db60083c4eb455c7273b5f737b59d0edaf7c9e9cb4a21445e45d447adb0b9139880e08bdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ae5a10d69adbf68cf45d94a7b63f55ee963a9d6bb6dfbb0ee85755a753bde2b5d299b1ba4ccae6aeec9e68e19e2fe8f4070fba2d6c319364523390600be50900718f0e3bc67fdfe6ca4a65a01208d4725c4d9dc6e4c76e45eafc218680aeb39f2e83e2744d4c42c6dc631532134ce32363bdcfad46e7021c6ab562ad02e139f383757a2116a3f40f905ccca878b1151065c4304d44d7214775e69609d520ca72461690e1391a8c20a93f0aa34b30976882eb1aa32ab6d73c80d9cec2dc39c1aa55fda5fd77e4d7054b3d01ddc184a8a78b5d438cb71b048410f6673f5ed219fbdbb454d8a8c8facc9f3d363959565a3c3ca6c0952d6b13e55d66c0853030d9dbecbdded1aa2df877d9cfa28926ae570873cb1f411227d40f07bdd07803ea1b289167b641608c5b160857f960f8f014662a6455b25d4e20b21aee6545b5dacfcf1cdb5a27ec69ca29264ca65fb287c293e794fec15ec0cebf88e6eb59f062821"]}, "failure": {"scriptSig": "", "witness": ["bf547b49954bc50d0726baffe4902a07de414bdee0da2e167e9afad61312c1f45a986e2212a999b32a35e1e8cf7353b8c6d8e90b0efdebf9415893ea2f7ff7ed01", "3436c6e08ef4187db8091d942d4aac3619e3793a65bf66e411cfedf9b9dd145df699e5f536a0ddf39c4a754d3c5a74c5db6445381f4ef02842e426775f7fadb1f6d8e807ac8595c61760d5055d2c", "753535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a26ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93603873753c288255b908fdaadf531bc1d68ff88416a14514d21f880f381496ce6109f3f9fed7a7850479575fe09819c514312532a101591e70b3ca7a41015d315abb6d11f6afe1d94d9d9f8c365772775719ce7effb301ae3ad4c4b3953942c9a173da251af8551a60e870972ffb93c31d944da40128e84f75b2100254c09f1b4de06e3cd6f3b0b209a8fe563fc0d7d5531bbe10145b72019ee6951325ead69740e6aa5d2a3313b034bf7c50dc92f197b6f924bf5d188e80f7e83cc6b1df9a9200000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff92bc58659211a4beadd8fa11a9845ff332b73538a93df84322b83e2be6806aec4a61dabd15e7c32b6ea531d34a692667bed8d7204672e2f2f1175218c050f78a3171dc5c5350b795a66ce38c1722adcba1fc40ef925faf53527faa391efe98bb3a827d6aae010ac333a59a738f4411490fa0ed048e3c7afb8a22b835690661deffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc817f1a371e950a12722586a5229873fcf0aed07489c9e7da60a05e7299def8194ed79115f02ce018b07d4bed9adffd7b00af1ea21eb1006ef232ab168648ba44c4c1787758d755a6445f19dd41348f06ed1b0f8a96cc9a729e5fe6ebc20288a3a2bdda781484822fd984a6a476ae7a39923a558edeba7b039c0d3c8536b086e0000000000000000000000000000000000000000000000000000000000000000976851de7870b0dd0dfc5cf582c477ae966ecdcae30037866fd3d0fd03f206e173dc23d909d6175f94b12ab45f393f9fe7a6f3281c8997a9ae1bd4f7db60083c4eb455c7273b5f737b59d0edaf7c9e9cb4a21445e45d447adb0b9139880e08bdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ae5a10d69adbf68cf45d94a7b63f55ee963a9d6bb6dfbb0ee85755a753bde2b5d299b1ba4ccae6aeec9e68e19e2fe8f4070fba2d6c319364523390600be50900718f0e3bc67fdfe6ca4a65a01208d4725c4d9dc6e4c76e45eafc218680aeb39f2e83e2744d4c42c6dc631532134ce32363bdcfad46e7021c6ab562ad02e139f383757a2116a3f40f905ccca878b1151065c4304d44d7214775e69609d520ca72461690e1391a8c20a93f0aa34b30976882eb1aa32ab6d73c80d9cec2dc39c1aa55fda5fd77e4d7054b3d01ddc184a8a78b5d438cb71b048410f6673f5ed219fbdbb454d8a8c8facc9f3d363959565a3c3ca6c0952d6b13e55d66c0853030d9dbecbdded1aa2df877d9cfa28926ae570873cb1f411227d40f07bdd07803ea1b289167b641608c5b160857f960f8f014662a6455b25d4e20b21aee6545b5dacfcf1cdb5a27ec69ca29264ca65fb287c293e794fec15ec0cebf88e6eb59f062821"]}}, diff --git a/txscript/data/taproot-ref/375599a0689231a316462d64f42ec6b33ccca33e b/txscript/data/taproot-ref/375599a0689231a316462d64f42ec6b33ccca33e new file mode 100644 index 0000000000..dec48caa1d --- /dev/null +++ b/txscript/data/taproot-ref/375599a0689231a316462d64f42ec6b33ccca33e @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be50100000063a870e860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705a01000000ecf01f0a0126bd150000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c32f391f", "prevouts": ["821b2600000000002355212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "050211000000000017a914a4e57198280c195671631f8b9014214c2f083b3c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2260202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["55db540a25196391be2d65ae0003c1f649c60f07711f400f13c53bae7ea5ef0981d564739cece5df3646e9f1aa33842655e984da96aac911801425ddaf0cec6b"]}}, diff --git a/txscript/data/taproot-ref/3771c3d9e542f846b3c206c6719246bde5cb472d b/txscript/data/taproot-ref/3771c3d9e542f846b3c206c6719246bde5cb472d new file mode 100644 index 0000000000..075a5ca9cd --- /dev/null +++ b/txscript/data/taproot-ref/3771c3d9e542f846b3c206c6719246bde5cb472d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf49000000007d987b7260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270eb000000000aaa262202847d7500000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac22010000", "prevouts": ["8e0b6800000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "b7e20f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4eae6bd6f52ba0e132a99199dd52ce9219533a45594ec0ae315984b9ce8f4516684d91d6a25611b98f9525cf8030045f0e379e1e6360450dcf32f11d35fa349c2fd9879a2ee2ae7d76224c991edc718b1729f7f1922f570a67a21926d2cc48d"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f46ef7c73612c270119b2372d340af405f58d8345e16456a531c474619d8ce41fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e26684d91d6a25611b98f9525cf8030045f0e379e1e6360450dcf32f11d35fa349c2fd9879a2ee2ae7d76224c991edc718b1729f7f1922f570a67a21926d2cc48d"]}}, diff --git a/txscript/data/taproot-ref/3774905200290499adbbac9b674c43b82c3af04d b/txscript/data/taproot-ref/3774905200290499adbbac9b674c43b82c3af04d new file mode 100644 index 0000000000..0828d764d5 --- /dev/null +++ b/txscript/data/taproot-ref/3774905200290499adbbac9b674c43b82c3af04d @@ -0,0 +1 @@ +{"tx": "5fbef0bf0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e4010000002fbbd3ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702400000000b17fc38b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4020000000022f32a9201149c1700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6691b05e", "prevouts": ["0bd8110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "02e3120000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2", "37553d00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b1", "final": true, "success": {"scriptSig": "", "witness": ["2ce88883ae23b521d480265d741aa13b4b99b2c417116be02119435a96e0d178b86c39ed0c550f3362b4ad4212bef0b2e0c1f06cbea9c9c12ce924a65e25aa4881"]}, "failure": {"scriptSig": "", "witness": ["62b0ad91da6bc00cc47a6a7b5e44ba05b57d486d00ea2523ca960328e47b22c8706f48ee3dd242341ba5c1c899ee487160feab52e87fa32c3f8a03dfb40e4735b1"]}}, diff --git a/txscript/data/taproot-ref/379b89135a99972794096065de8e1072473b7cdf b/txscript/data/taproot-ref/379b89135a99972794096065de8e1072473b7cdf new file mode 100644 index 0000000000..a84e2012e2 --- /dev/null +++ b/txscript/data/taproot-ref/379b89135a99972794096065de8e1072473b7cdf @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b700000000eb5b4d300435280d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac97030000", "prevouts": ["5624100000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6acb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5112ea1c769bf4ed96f58121c83502481562485a40fea0bf2693d01f3a88662b8b1937db199a07e1996385ab03857d8e2ee63e136796e4b408281aef544a937c0c73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93671214783dac4295bfd807e673d52a384d4e362b63aa9a14af3c4920cb220748712ea1c769bf4ed96f58121c83502481562485a40fea0bf2693d01f3a88662b8b1937db199a07e1996385ab03857d8e2ee63e136796e4b408281aef544a937c0c73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}}, diff --git a/txscript/data/taproot-ref/37a26cf98e0cb201f2e241d6a41e267821078fc2 b/txscript/data/taproot-ref/37a26cf98e0cb201f2e241d6a41e267821078fc2 new file mode 100644 index 0000000000..0693a054ca --- /dev/null +++ b/txscript/data/taproot-ref/37a26cf98e0cb201f2e241d6a41e267821078fc2 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6a01000000d4b6778c01ea400700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac3942b943", "prevouts": ["a87e280000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "d67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb1986d7e8e27273be987a3f59c249d736830c7b6f9b487df38f4ee68bd2c5d06630d95c26588949f1b3ae4e4e429080b434b995fa18047406852c727cd9e6feb"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630ca117f3a3f5d0edabc733225eb4a624a098c8f44ec26e7a92d0c8239372396e4fd5de156dec52418d0df8cecdd3495838e4d1d1b80598a34f381ec5024e2c9bd0211bc754da142cb3564162304068e34e33074851a6380a45a2a3191e3f102"]}}, diff --git a/txscript/data/taproot-ref/37cfd491e753f20291c4606a4bb007cf1aa69eaa b/txscript/data/taproot-ref/37cfd491e753f20291c4606a4bb007cf1aa69eaa new file mode 100644 index 0000000000..d1ca25762b --- /dev/null +++ b/txscript/data/taproot-ref/37cfd491e753f20291c4606a4bb007cf1aa69eaa @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e02000000912e21dfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9a0100000031b47cf98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4980000000092ee46990448da0101000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd8010000", "prevouts": ["ac7a4e00000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "3b7a79000000000022512065eb0ad8f24d6d8eb63c7f85eaa52926e45dd0588dc97971df796ca5c67918e7", "18b33b0000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ff7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f59f882dcce043ab5273f79d0d152c35fae0f251a6812c7f2d3daa07c20029a516c082ffd0388de178727289f9edc245ed8244bc4e4186d1c7a66ea621fec0ad"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362bd3a471ee044d9d1aa58d9f4f966cc5745c7ac5592ed682143181a0f47efc0bcba978c9f8bb8ad08bb333d68e8bfcd03859985a79755d391cef5d6f406deb57187b9e30f7e626b28b6dbe2d7b101f74e326290698090dbb0a7eb7a50daae87a"]}}, diff --git a/txscript/data/taproot-ref/37fdd34d221df947a4dc6a40f91fe044f88c8ca2 b/txscript/data/taproot-ref/37fdd34d221df947a4dc6a40f91fe044f88c8ca2 new file mode 100644 index 0000000000..5ec5b0a458 --- /dev/null +++ b/txscript/data/taproot-ref/37fdd34d221df947a4dc6a40f91fe044f88c8ca2 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c5000000006242d66edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd601000000ddd1212b04e58899000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb2000000", "prevouts": ["26f83d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "36595e000000000017a914856f7c6a5a6a1ac0e553b769a4c35bcb9fb6f50287"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2353212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["20b89804e90837e9dae02d7437fa3f983016fe8a2e1e34e1bf5c5f8b58315efec2c51214a9a3dd71eb0d1b24b1cbd3564045a6b128679dd391a8647ac3469548"]}}, diff --git a/txscript/data/taproot-ref/381cf7c5a9c44f989bb97ebca54137b24a0c5102 b/txscript/data/taproot-ref/381cf7c5a9c44f989bb97ebca54137b24a0c5102 new file mode 100644 index 0000000000..8edba384b4 --- /dev/null +++ b/txscript/data/taproot-ref/381cf7c5a9c44f989bb97ebca54137b24a0c5102 @@ -0,0 +1 @@ +{"tx": "64c16f4c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700900000000414b74a060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700d010000005c64f2b20470e81c00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc733000000", "prevouts": ["d259100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "40f50e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_54", "final": true, "success": {"scriptSig": "", "witness": ["5439d7332f467f04095a4ce246f4a56e02d8d830afe42a61b7b5b06e6b2f4bc600fec9385c9ad471c115b070607e613deee2c0592220f954a84827b42f8904c2"]}, "failure": {"scriptSig": "", "witness": ["b940d74f3172475f5b8173d396b319e2f9d669d27321a5873b5b33d83561112ea32d3f55495b78d3e199ea220e88e46d7583d4888bc892e09ed4d3fa000d976e54"]}}, diff --git a/txscript/data/taproot-ref/381d7b2c554124f48f833d5bb44cb65d6a4e69ae b/txscript/data/taproot-ref/381d7b2c554124f48f833d5bb44cb65d6a4e69ae new file mode 100644 index 0000000000..e27f0ff083 --- /dev/null +++ b/txscript/data/taproot-ref/381d7b2c554124f48f833d5bb44cb65d6a4e69ae @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfad00000000a2a222a28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40602000000952b84bebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0c000000007b93a1dc01c8cd08010000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487078ca733", "prevouts": ["be076700000000002251206e4088e3ab3053e34fa9f42678349f51acfd745de3b6b8ba599a97db56ef8c25", "59dc4000000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "0d6b780000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "067d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93637a925bc8f704cad671189518c9abd151e4193d3e419ccb499565ec7319392f89a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ed1973e93f7ad3f562801731a237f358bfce42fb636b2a0dab3a823989e87b4ae"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2edee9d6f4a8cbfbb4a0af0dddab94d753895c3cdd7995db9d6f3e266cdd0bebd1973e93f7ad3f562801731a237f358bfce42fb636b2a0dab3a823989e87b4ae"]}}, diff --git a/txscript/data/taproot-ref/3849d609dcd2299e85caef8d7aaf0dc4cbda60ea b/txscript/data/taproot-ref/3849d609dcd2299e85caef8d7aaf0dc4cbda60ea new file mode 100644 index 0000000000..20122c8f56 --- /dev/null +++ b/txscript/data/taproot-ref/3849d609dcd2299e85caef8d7aaf0dc4cbda60ea @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f00000000aee490c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4b000000005f173cce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703801000000fe1cc3f8014c7b3000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac9c041628", "prevouts": ["5139310000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "560c2100000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "d2ad11000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "557d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b85439bc36c09324b2f69ee8bbc5e2d848c6dcad09b29c0021348708068368e9c6f5bbec45690fe95363697d7c9a9077046b35079592ab1dc3c0638990956b6a4c5d50721208c85113b157b4dd4688510f63bd33d4c90ece0d9e0afcb8224b1"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93651741a4e3e2a3e44a80e6912aaf8177301e30f939f3b8b538bb3a1c1c4af3209283c6292a6ae3f7cd2fa90a42d11f5a54bea63a95cab37375097c35ac3f3911dda77d1c2cfbe9569ee5db2c51580a9857624040db9177af617be0771cc5b8a1b"]}}, diff --git a/txscript/data/taproot-ref/385fb0d2eeda5f4790eeab09a29ec612150cd115 b/txscript/data/taproot-ref/385fb0d2eeda5f4790eeab09a29ec612150cd115 new file mode 100644 index 0000000000..b21488bc59 --- /dev/null +++ b/txscript/data/taproot-ref/385fb0d2eeda5f4790eeab09a29ec612150cd115 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c00000000addaa5ecdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0b01000000d5f25f580315f46d00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acf284905e", "prevouts": ["41ae4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "91ef230000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93686e10009f826ae98be2091575903ddf7d5bec40ff77526fea2822b8bcaa021aa41d10d6c1f57e693407bbcd98ddd5bf64931b5565c89b36e50f161e759967c3e172c8da9bdd43b70cbab8912ef1aa7926e5ad7e47a4f7b71ac936200cc947dd0f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082716f66701312fe6b613a3a288c903128f650d73beac5c480044fdeaa8466574a9dac82751ef42f4155e8d0286eb609cd4bc8c8b3be93c107754fe282612bb362f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}}, diff --git a/txscript/data/taproot-ref/3862864a68546884d4ae2ef7644d75b814fd279e b/txscript/data/taproot-ref/3862864a68546884d4ae2ef7644d75b814fd279e new file mode 100644 index 0000000000..e50cd5f941 --- /dev/null +++ b/txscript/data/taproot-ref/3862864a68546884d4ae2ef7644d75b814fd279e @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6d01000000b06dc58edceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4c010000002a7e2e9adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc90100000011c898bc0363a0a1000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a663000000", "prevouts": ["3c7c220000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "23ef240000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "d7255d000000000017a91498e55eac47e04767f832d50008ff18559102c9e787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364e1c80865788996a05c5a9f6b0900b0096f6056de983ef887886ef5950a10b0c0d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3ab0398bc4828dee75def1007ce877d708ab4ca86c9734bfab291d4bd05bae3eec1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4aede7f6feac32430a03a6fb4ca18c03b66145006034584e3a19904465ea1e66424cf807c4b041deab506320299ff116921971164ef72b2742896e58a89a98f91cdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}}, diff --git a/txscript/data/taproot-ref/38633120561625bae7ecb1c951acd585717ee56e b/txscript/data/taproot-ref/38633120561625bae7ecb1c951acd585717ee56e new file mode 100644 index 0000000000..fb38df49b9 --- /dev/null +++ b/txscript/data/taproot-ref/38633120561625bae7ecb1c951acd585717ee56e @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b440100000090a859b3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf91010000003771e53e030b83950000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d8030000", "prevouts": ["0817280000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "86656f0000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "", "witness": ["3044022034335162d737f158c7b3c25f5b5563228f612a7993a0bb0106e6c330fe32e537022004e8ceea10ee54e560a6c6f44459a98742d29a9cae1e7046d27a56836e997aed01", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["3045022100e78e92208d7cc2b5a9773c800e825f7ffc0f76077497e7bce6d279d89f75387a022018496549e67be8c0892bc711eeaf089a7166ee2caf0684f3a72e59f09c76403f01", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/387db60867784e48a23882557f34fd3e8df5fe60 b/txscript/data/taproot-ref/387db60867784e48a23882557f34fd3e8df5fe60 new file mode 100644 index 0000000000..7c63bc136c --- /dev/null +++ b/txscript/data/taproot-ref/387db60867784e48a23882557f34fd3e8df5fe60 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b340000000077941edf0434921d000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d3ec1d3f", "prevouts": ["8d7b1f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_1b", "final": true, "success": {"scriptSig": "", "witness": ["c5faeb9a347692f3a996631d94d3dd98f32295ddb59104cb542ed4f87b30b9a9d759815bef1affdb5bd2c312d659ac5eeb1fc69ea98787477d5ec772de0a113481"]}, "failure": {"scriptSig": "", "witness": ["e36505a5b181292a8650bca5ea7be6bee32cd9a15ad053212d1dee15c825ea1736a5dce27ff6ef989e028d31bd4b2ca27d54484fc7537c0446c34acb9cba871f1b"]}}, diff --git a/txscript/data/taproot-ref/38a77bbe28f3ce750b32c16df488eb5970d28d51 b/txscript/data/taproot-ref/38a77bbe28f3ce750b32c16df488eb5970d28d51 new file mode 100644 index 0000000000..9292e39dc9 --- /dev/null +++ b/txscript/data/taproot-ref/38a77bbe28f3ce750b32c16df488eb5970d28d51 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ae0000000047920cabdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5301000000a1ccabe104ac0f5b0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9e8d6f25", "prevouts": ["14790f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "910b4e00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_fe", "final": true, "success": {"scriptSig": "", "witness": ["8ba0e90615127c5d9ea667a5ba5c26b9f66f237978ad352924773ce4f1ebfe070d43b0ca019fbad9466159f4ecd21cdbd58cebb97d1f64945fdcf2350be04d8d83"]}, "failure": {"scriptSig": "", "witness": ["9bdb91e89dcbfb39b42a321d60edbb8319f12d05f9faa426ff7badfde3ba30977fcb1128f80e3fd4e90d401861bc4b6c4c85aae92226ba310d49fd85261a7f61fe"]}}, diff --git a/txscript/data/taproot-ref/38b2b86e0814487d32eb0a49aaa091c527c67a39 b/txscript/data/taproot-ref/38b2b86e0814487d32eb0a49aaa091c527c67a39 new file mode 100644 index 0000000000..1d26b0957c --- /dev/null +++ b/txscript/data/taproot-ref/38b2b86e0814487d32eb0a49aaa091c527c67a39 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf0000000009f8bce5d04818f1d000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df9797223689872aed5655", "prevouts": ["f2921f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d8", "final": true, "success": {"scriptSig": "", "witness": ["2aa16639104c78cee7439634edac568733e8bb275edc2ebfc43f6585b5b909bb413c02e57c3b029edb3eeddffbc9426a31f9b0c92cb8db331fd35df209edb1d7"]}, "failure": {"scriptSig": "", "witness": ["c68a740536f42dd9506b682c99896b8c2c5b85fe2341890dc9ebd9a6fe897378677f0c4e15efeb53375353f8a1d9c6583bd18c6d7fba3d92b7deaeaff5faf680d8"]}}, diff --git a/txscript/data/taproot-ref/38b7d993272a54c03a7adb7a046e8485546ebd0a b/txscript/data/taproot-ref/38b7d993272a54c03a7adb7a046e8485546ebd0a new file mode 100644 index 0000000000..c82f36382e --- /dev/null +++ b/txscript/data/taproot-ref/38b7d993272a54c03a7adb7a046e8485546ebd0a @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43b00000000ae08b4eadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c51000000007a44b5c0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b640100000061c4ffd403bdd4b60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac57010000", "prevouts": ["f0d03b00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "96d759000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "3c68230000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a8d", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9b0461d232ca8cbb85f9cff4edce544795cd9e38a4d0e90220b3cc21716164820e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b25240bc46c035392207c1076e816011b96fc57f286e81391f52d072a1ebea8b62cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb488d314ba4ab03912e470cb461a645c9914779a4907e0bafc42fbc04fe8b44a37185c953dbf0a33402e724bbb72e47d874a897a0941d53d9706dc82e2e14efc19f43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}}, diff --git a/txscript/data/taproot-ref/38bce0395152e8d2a60a95b4642bf3700934e4e9 b/txscript/data/taproot-ref/38bce0395152e8d2a60a95b4642bf3700934e4e9 new file mode 100644 index 0000000000..5a34ec9f72 --- /dev/null +++ b/txscript/data/taproot-ref/38bce0395152e8d2a60a95b4642bf3700934e4e9 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f80100000079124b848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4320000000067ebebe7049dfa440000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a666010000", "prevouts": ["2ceb110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9c753500000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ed", "final": true, "success": {"scriptSig": "", "witness": ["9274ac3e0212f0c0646326e538e9bb9746925b878e92d6ef93ceffc41a6bd160763e2f55764446188879bfeb643cc0328d99caf8fa2e628b62fec59f99c8fedb03"]}, "failure": {"scriptSig": "", "witness": ["f3d479d4e56ad59dec938dc0253f1dd338753b740fd1f9c836f4fe34b86139c9a255aa3f21ba6fc48bf682df4af4f2e0926dfa53c82f038fcbe6eec1c6560afded"]}}, diff --git a/txscript/data/taproot-ref/38cd5b3045252d1ad4ff3cad40d838874891506c b/txscript/data/taproot-ref/38cd5b3045252d1ad4ff3cad40d838874891506c new file mode 100644 index 0000000000..09e7bbca09 --- /dev/null +++ b/txscript/data/taproot-ref/38cd5b3045252d1ad4ff3cad40d838874891506c @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705e000000007f3b89fe60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127009020000009be7daae0426b41e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7968bbbee5c", "prevouts": ["67bf12000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "58640e00000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "4730440220543ded75984f10631c547153e668339318316b46a6acdc95b72565db39cba06102207bd76bd6095de8a6d7d49abc9874100ad9c264dab5e542aff87f9fea8824389f822102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "4830450221008e236e8514424afbf80254518324c97bec4a1c1d931f1983b1db672606f3981002207ea1ba5c64fd50d1b4e97d729fe5a0cf08253ea0f7c2480ccb11ca60ae682bd0822102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/38cf290b09eac905ac4bdc5ffd7fbeb55b28d0b1 b/txscript/data/taproot-ref/38cf290b09eac905ac4bdc5ffd7fbeb55b28d0b1 new file mode 100644 index 0000000000..0944278103 --- /dev/null +++ b/txscript/data/taproot-ref/38cf290b09eac905ac4bdc5ffd7fbeb55b28d0b1 @@ -0,0 +1 @@ +{"tx": "a804d40e02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b96010000007c2543a7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfb00000000e7fe5fb603e9bb46000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79609000000", "prevouts": ["332f26000000000017a9144370350f30aa8f875e3d2a13be81f25f19bf1a6387", "6b2623000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "165b142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["ec464e0adc042aec0c2faacbf02be14e36edde4da057690d617cb47dc12d8b7ba4531947887a1c1a8f04971eb2b5b269db89a657828cdc1823307d26652693f4"]}}, diff --git a/txscript/data/taproot-ref/38fa5cb2147069b9e33e21d621935d45486c5345 b/txscript/data/taproot-ref/38fa5cb2147069b9e33e21d621935d45486c5345 new file mode 100644 index 0000000000..bb86d6d625 --- /dev/null +++ b/txscript/data/taproot-ref/38fa5cb2147069b9e33e21d621935d45486c5345 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9b01000000744771be8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40100000000c8bd0fb801d2b675000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c37dd022", "prevouts": ["f61b7b000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "8dc2360000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_24", "final": true, "success": {"scriptSig": "", "witness": ["199a4a926b83803513647ea69935f13837f11bc1a627235ff4df4609f3bc7b25187093e20c26621b83142edcad4473094b6bc3e7e566975c20b7b09cf23ce4ec02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["11857143302617a4e0e926197b5d993695d4ab736d03ce678f550cceabd099a4fa044e495fc36a0ae89b476a2668705dddcd95435b05dcf9ab2175d4dbcdf04424", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/39016f47ee6449811c8a18548ba14d36d60f1a15 b/txscript/data/taproot-ref/39016f47ee6449811c8a18548ba14d36d60f1a15 new file mode 100644 index 0000000000..52b537f7e7 --- /dev/null +++ b/txscript/data/taproot-ref/39016f47ee6449811c8a18548ba14d36d60f1a15 @@ -0,0 +1 @@ +{"tx": "85324522028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47f01000000b61021addff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4e000000006b4b3e8303a56079000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7cfcfce3d", "prevouts": ["153b330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9946480000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d9", "final": true, "success": {"scriptSig": "", "witness": ["b58ef2299b49b53498f3dfb343bb0147fdfdb16bd8f72099145e74a58299f7f28aa78acd40e2ca3fd7752d6b8a4c6837804f400f27b31cf02f81d77c1c3c70f403", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["12c9d1142090c955e04a1e837957073fbf4a1b811b4103f6875742b7efe793ff244c751da96c6c4d7db0561c824a216d184a26c0bb4fefadcc05b2f04a36b64dd9", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/39095ad3e086951d38e9de71ed6390bf4a910ada b/txscript/data/taproot-ref/39095ad3e086951d38e9de71ed6390bf4a910ada new file mode 100644 index 0000000000..90b86a12c5 --- /dev/null +++ b/txscript/data/taproot-ref/39095ad3e086951d38e9de71ed6390bf4a910ada @@ -0,0 +1 @@ +{"tx": "5212986602bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe100000000b6aa49efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcb01000000fd92fc8b04ca0fa200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acecbfb437", "prevouts": ["7f66820000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1060210000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_4c", "final": true, "success": {"scriptSig": "", "witness": ["918b36466f94075e9be07c490788ab309ab2b31ef7692a2579398980edfd07c42cd18bef348f9a554c12fd8e2d95aa197d4f226a507c5b41d47af8db260ba326", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["dbdfca1c96978198be6393361c25561d12cc32b2eb3a2f69da676369f104f6281a43643b74dac99c0c8cbe3d234acea9d21fb67d650d6c7f60e1935f3e614f1b4c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/391ae71a3b29dc703963bfe3a4d96555cac94848 b/txscript/data/taproot-ref/391ae71a3b29dc703963bfe3a4d96555cac94848 new file mode 100644 index 0000000000..d2706c775d --- /dev/null +++ b/txscript/data/taproot-ref/391ae71a3b29dc703963bfe3a4d96555cac94848 @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf00010000008635effe02de03710000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6bc000000", "prevouts": ["aaf4720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_47", "final": true, "success": {"scriptSig": "", "witness": ["2c2708559a3eac7d1c852c6d9edb35e6f356e28a50abd47bd49df6cf6c68173b278c2db69fb0762f2a08749e634024f08a177f02bed811f322990e047717359602", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["27b04ec8efc1299e07da1299a63a337d4e94af12e6c97e5b067c59f88a71fdcaf411c75619806c1ac7f4dc2ed22095c97ae4424c1db8510efe547a7464349b5647", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/391b89f7a6069cedebf4da40cbd2e894c4e4e161 b/txscript/data/taproot-ref/391b89f7a6069cedebf4da40cbd2e894c4e4e161 new file mode 100644 index 0000000000..45e87bdb4f --- /dev/null +++ b/txscript/data/taproot-ref/391b89f7a6069cedebf4da40cbd2e894c4e4e161 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf330000000056a475b2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cba01000000746cca94dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cca00000000ed67c018043edd1c0100000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88accb010000", "prevouts": ["e2be7c000000000017a91441ce0eb0e6e5800ced23a872818e5aaa63be0d5b87", "3be74d00000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "38fe530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d3", "final": true, "success": {"scriptSig": "", "witness": ["d04ffb72469ddc66ae082eddc4392c14d71e085d8ae83352f9c37ef680d0d7c04a059b4b5d64a85511f4633d52ad3ff4e608962a6bfe962b3f7514aa8dc5540382", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["fa6dc37c2d78322782f92650882c7402e3ac4056be9adf851c3adb5a3e1c7dccecf623a09bd1c2efef20793d0691a8f0e18d079d014130018b741a7e715d062ed3", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/39261d0b29bcefd21020cd2c24c872c070c66ae7 b/txscript/data/taproot-ref/39261d0b29bcefd21020cd2c24c872c070c66ae7 new file mode 100644 index 0000000000..9fa795266a --- /dev/null +++ b/txscript/data/taproot-ref/39261d0b29bcefd21020cd2c24c872c070c66ae7 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c730000000007e7cb39bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4a000000006802958d0482acd60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac15766851", "prevouts": ["4500580000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c9af80000000000017a914b0b53ba433a336ced94ed75e23248458a1c69fab87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_4e", "final": true, "success": {"scriptSig": "", "witness": ["76b51f7d8850e815a2f29a132d69601c7c9ed5b7a71560008d7edb776cf04d05d5d11d79e9e5c1c0255a60a72f9770f3ecc3f21e1f38d199448c97228703abf602"]}, "failure": {"scriptSig": "", "witness": ["813e1ebf75e3a78dbe6c55892a1191280240a6f802a60f2b538e5c5cbe99b3890572000bdbb583b8cf2831fe4476599330ed9294ce42cdf139b46c28ae9b166e4e"]}}, diff --git a/txscript/data/taproot-ref/39427d9b3326e6d242f88c30c5337e28e60ba2cc b/txscript/data/taproot-ref/39427d9b3326e6d242f88c30c5337e28e60ba2cc new file mode 100644 index 0000000000..d15630d58f --- /dev/null +++ b/txscript/data/taproot-ref/39427d9b3326e6d242f88c30c5337e28e60ba2cc @@ -0,0 +1 @@ +{"tx": "ae141b9f03dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bab000000003d92aca3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0d00000000851034978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c445010000004f05579f031209c70000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e741700146", "prevouts": ["27c222000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e", "30c5690000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "23df3c00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a8e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ec5722d02b8b9029442961cc3fd9a7a94721ebefae4f707bcb621aeba142f8aeb7a2231cf916c441aa882850e5209a465c1bf953237149df21eb7dcd7136fa198d550033184c6424688af85d43f5bf525b7f6d8111e731f6e2359cae2801b117ed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1e707b6995f8993c03f45183b0bc1e0ebe72a0445f3f0cf57f2d95712f279e1c2be0cdb6e99edcfec16766ec5847d1f54ccd051e23ee2b2272cffaae333295d1b30b2981ae69232c3f6c5ff759e9ad4102f31f3fc5e7a3a4ffd34dce2e2e06026"]}}, diff --git a/txscript/data/taproot-ref/395284f8211e771929c6abd17a1e39b471bad2ac b/txscript/data/taproot-ref/395284f8211e771929c6abd17a1e39b471bad2ac new file mode 100644 index 0000000000..9d70f625e7 --- /dev/null +++ b/txscript/data/taproot-ref/395284f8211e771929c6abd17a1e39b471bad2ac @@ -0,0 +1 @@ +{"tx": "543aa354028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44a0000000011a31ca4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7401000000580331d803fd42a9000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acad535e40", "prevouts": ["137f32000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "1a62790000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "d47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b93338c7d107e01cff6d052285c57a3fa3547f5f14e99776c0371239cd8619173eef830f28a0ecbd34c70640f7829eb7d86b0cf2da24853f16b74ab53bbfd728ea84370bdaf8fbfa2c728119f306db95ff534e2e627fabf0c000f69380d4e93e"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e3e1af50e9fddc5b40f5692067c8c7b9556942ec16723cf5c6b37b54adcf255bb970f6251c63bb7d52d2f522a2f2041b3457429d11106abd9da97a7fab7a15d238c2fd1368e2cc97a2933efae2d13561032948a77b2cd5d87b5e0b8010cd9f32"]}}, diff --git a/txscript/data/taproot-ref/39702f9a29cc5985ccdbae18da3583e3a98271be b/txscript/data/taproot-ref/39702f9a29cc5985ccdbae18da3583e3a98271be new file mode 100644 index 0000000000..9c28e84b09 --- /dev/null +++ b/txscript/data/taproot-ref/39702f9a29cc5985ccdbae18da3583e3a98271be @@ -0,0 +1 @@ +{"tx": "c9c8ae8802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1d00000000fad144c4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9c0100000062d84ea8013cd619000000000017a914719f78084af863e000acd618ba76df979722368987428c8e4e", "prevouts": ["70f55500000000002251202411d699451e61c2ae1e9b07727f82864d3d401db7c2ec25b77e3a65ecc346bb", "fe6e240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ca", "final": true, "success": {"scriptSig": "", "witness": ["ccfa4da731767429392a91fd269dc432b468f89fc9b4b5543afb9aa8ec596ddf03a339bad380617e4c1befad93475d6c0938813865aa4ad6657fb60c902cfedb81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["768dbee09895e6c1d0577e8be1f8677fcbfa1129e799134e2bac6ccaaae02573c177af4a7c3eed92dbc70bd8e2f072c0da227d768dd37b26c1c7bdf7365b1e05ca", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/39a530e81b2ae6640a22eade59df3f302ebb0806 b/txscript/data/taproot-ref/39a530e81b2ae6640a22eade59df3f302ebb0806 new file mode 100644 index 0000000000..b77f132f87 --- /dev/null +++ b/txscript/data/taproot-ref/39a530e81b2ae6640a22eade59df3f302ebb0806 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa90100000010059b838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4580000000033dc898602dc7baa000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac08020000", "prevouts": ["31d1760000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "c135360000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100b718c2791c2badb2b8e183fafda2cbec3d198dcdf6b6a67e53351bbb2646fee4022049a083af5b7cbde125b03df2f12afb821cb9d9650fdecc4e618e91bcd88bf75302", "witness": []}, "failure": {"scriptSig": "4830450221009742d27580e3aec93fcaca396886a5dae6b834799f783836a6905f8403e21a1a02201de072fc6889deb35d5720dc03f976a8430e57bd09c40b1f8c2db48e836dacf002", "witness": []}}, diff --git a/txscript/data/taproot-ref/39c2d78974b78a945ee5325ec03d2a9842678371 b/txscript/data/taproot-ref/39c2d78974b78a945ee5325ec03d2a9842678371 new file mode 100644 index 0000000000..d1c39e687f --- /dev/null +++ b/txscript/data/taproot-ref/39c2d78974b78a945ee5325ec03d2a9842678371 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccc00000000943576cf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41600000000780387a8028e4e9c000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac10010000", "prevouts": ["a4b05e00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67", "293a3f0000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936043ca414401d02c8bceed194a0f5859ab7579e0546fec32e9f1c40942706c7e55813d9fe920e311eca68d9da8ac683d4c5ffd57c03f9174ce1b6c58fb2e14cca376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d3c7e324ed429231bc80df899753efc8e6aec2cfa09e5404b20e527324b481ee2c6725dd4617fe2c0113ef50b93a252f15ac43c20ed2eeb851ef9070637abf4dac8db205c7d3bb0390b2e22910f5d1cbad00807eee3325f4c4e7f4412ed3064a1c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}}, diff --git a/txscript/data/taproot-ref/39c6fd26ec7474a9addfe549df2cb8ee610ecb51 b/txscript/data/taproot-ref/39c6fd26ec7474a9addfe549df2cb8ee610ecb51 new file mode 100644 index 0000000000..3c42d7ced6 --- /dev/null +++ b/txscript/data/taproot-ref/39c6fd26ec7474a9addfe549df2cb8ee610ecb51 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2d0100000067095e1ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b00000000b27fd181049eb8c90000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df9797223689876a020000", "prevouts": ["9d75660000000000225120de7c17758b854fc68d3061dec4ffef020214eb4d128d0a0aa1b6bff82dc51d5a", "f6a1650000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["da4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d5de9338381cd304b2738c8b1f6fa31d15bcfc9fae7d40af04401c68f4d5de3473df9812949ea11fa7cd8f7a31f5257bc4998fae53c5743d03c7cfeceae664b355d713f01682c54eefc137cacda341f8a928ca67657dd1895f9a847e54f584f6ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367f6a5a2baa8cd252fc4ab850ea9e4cb81c048efc06f172ee1268b682f3ed0b1b1dc38fa67d6e370c9f405c2af01822f370dc317d6e78d2f71aa14f0ce4de56d6ee4d75780d36bffae9b56136e6d27c02b8d233efdc800bb260bfbba6a6f94b87"]}}, diff --git a/txscript/data/taproot-ref/3a48de373b5922e0287dcbaa10361aa1464b3eff b/txscript/data/taproot-ref/3a48de373b5922e0287dcbaa10361aa1464b3eff new file mode 100644 index 0000000000..58f6b2c3dc --- /dev/null +++ b/txscript/data/taproot-ref/3a48de373b5922e0287dcbaa10361aa1464b3eff @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c43010000003f472588bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4501000000d3e842e9032ea2ca000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac62000000", "prevouts": ["20175100000000001659142540f27e90740933c99d4f17ab2dfc6c82951cfb", "d2437c000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["91828a2f001425c1625387988a444090750bf791918c2207b1a3dea73b12df8da6bb09bc2dde7a967fde5f43a9deee757818cef0ebf7bcebdcb8a1fff3bcdb39", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/3a4b7a4a72ab611ede23f7e04e2c7e0300d1c7b6 b/txscript/data/taproot-ref/3a4b7a4a72ab611ede23f7e04e2c7e0300d1c7b6 new file mode 100644 index 0000000000..3918d4814d --- /dev/null +++ b/txscript/data/taproot-ref/3a4b7a4a72ab611ede23f7e04e2c7e0300d1c7b6 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8f01000000e85c06ea03f6e652000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4871011e341", "prevouts": ["4422550000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c94c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900453bd2bf476d5c79b80d1dc385df1320868058b4af6871225604d123c25805c1374cc0fc2e3b1a564cf058e89401e888e3d8222f635de2bcbc595bfcbb872403dfb24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d3c147557fd4654830368843709159d459528293d28ab2736e9587eb54fea08bf48725aff660a72fd31f8e9799fbe605d57d774c031cecd8b6989780acb581b6b24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}}, diff --git a/txscript/data/taproot-ref/3a5d1711382ce031d27b85c9d0db96a8d322c0a5 b/txscript/data/taproot-ref/3a5d1711382ce031d27b85c9d0db96a8d322c0a5 new file mode 100644 index 0000000000..f575eb2b8e --- /dev/null +++ b/txscript/data/taproot-ref/3a5d1711382ce031d27b85c9d0db96a8d322c0a5 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe601000000c65799e260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ba00000000d4786d82dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8f00000000fcfa74ef02a77fbf00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d5000000", "prevouts": ["6bf861000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407", "d5740e0000000000225120f53d4d34de47a5fffffaf2fc2c78ea776a7cd8d2ae45e19539d143c70b3fc5d0", "5eaf510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c0248df00e7a4dc0c1a55899dad6646a67c262377c42a818f3ac26470e7b94e3"]}, "failure": {"scriptSig": "", "witness": ["6a56616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/3a8258d488d60df9cd2d2e0f3fbfda5aa2916b1a b/txscript/data/taproot-ref/3a8258d488d60df9cd2d2e0f3fbfda5aa2916b1a new file mode 100644 index 0000000000..fc1733d229 --- /dev/null +++ b/txscript/data/taproot-ref/3a8258d488d60df9cd2d2e0f3fbfda5aa2916b1a @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708900000000676b3469dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2101000000e54ad34c04af0b30000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6f000000", "prevouts": ["d015120000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "65ee200000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6afe", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694e0e7acaac641668fc05305801328759974c78d394b9aa0618ae365ee981a7dd800fc56907ebb8e18291aa6f74a5d7a46b4d60066ab44c243b43072452172e3365bb68c3eae5e6cd9b20289e581f52d4e8c0cb4ba58bcd8be9e67bc80fb920a1e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900455ba7b576a8dda08f1b482f8c289e95e9d52783e5c439690d7dbc8078ddf6e59ab44d8b0f62b2d27de7be259100200d6da1e5303b29f3eaa1b6a4eeb0c96a42f364ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}}, diff --git a/txscript/data/taproot-ref/3ad5eb51c8c2ea66907d5c7b40ef6cccaee711ce b/txscript/data/taproot-ref/3ad5eb51c8c2ea66907d5c7b40ef6cccaee711ce new file mode 100644 index 0000000000..126238e9d5 --- /dev/null +++ b/txscript/data/taproot-ref/3ad5eb51c8c2ea66907d5c7b40ef6cccaee711ce @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d401000000e688dcea8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ff00000000123c9dc8046d667b000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac3fb5d441", "prevouts": ["915f410000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50", "defc3b0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c6c67fc5db5a48a2d95838acbbf8c02666a57f9afa4a196d8a1c4266fd607a20516db74e79dae20b980131c66ab5c6b1103d5696c84aae822ea57ed7abba6df9c47c79f10eddb86c5430be5b12cd56fd72ed72b8e9fd97b27cb9d8794e4fe0ff0c9ad624fa170605f055a7e7fbd776e840af1d4eec99d8c4672f60d35ac95da2343630e58d0e49d036a3d4c9d64dc660614aa3786242cd0abe4e5b8c5de301bd99af384c5ecc823153c1606e81b61c7d31027375ed835726d4c754f4ffcf383b11d28fe5eaef856dca99fb118187042ca7f59e0195b603d887a814e7bedca5ddecdcef5ab57af375b6f50579acc4d0b5927db9b61a1f2c7d3fbde6d583d9677c339bbacbef59193105c5306550def281332bab47830626009563cb60164a1f5f71405bf8de6d69dd3349b1e4d7c5f9f162eb1de22307ecb9a39d5ba7ce03abfc178600a9275ad26a1ce43ddf70f6da741beb70154bec478a630e3c5e76560c66628d099c709af5e18677bd39bac44d435b0a8a3dc23bf7542271b963a0c934f56870afc62d4cc92eacd9f302dbe974b221d5a70b3d3158bbd7533f1063e6c96aff5e83c814e1bc9fa53e7ff85ee81ffd84deac9a05cb7be108ae7e61fe2ca80bb1e7f8e13bbc94e06cbf11f9621cc7fe532bcb12673a0ef50e147d8612e8048e30a420f6ba5b2225b033f2823300c438ea2e79a21c0ebbeb537507d49edd356511829fafeea17b33ee75", "227d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9f2d7c582f83634cd135c0c41a92af063e6e0eba35e5b92273f4e04c23802be6b7b535eacb46044525b0033e262a0686af8b44a8254e1701bb4a9d0d605b263fcb15428af69077ee4e47ddc8bd2adcf7d97a29fc56c75a24a213a103a1e3586"]}, "failure": {"scriptSig": "", "witness": ["4d090203c94a49e5650f882b71a8b54b11d86841939712125f5b05d3ccdfee26b4c27dfb753ce79127dc1aa67b20a61753c5d52b70dc756138f22fa2e7c075e1bd43f023265deaf540ffb5051b07d4ce8197af06649cf1e587fe9fef4b0e2b60714f687de029f6a678c3645702d03d3649f313600f50d46809233fa1950d9a22f2a73182ee6969a65c23d509792933339081d2fc9e9ac858c28f6bb7b36a2c9f92289df76ce76dc13974c0cf9e3d3c10ee65f5f703a3517e9f4af94d0693aefd00ca3b5c69db4ddeaf232b25a0ca0d8f89cf8a7b4620eb8de35f631631b46e2947478bf1e9ec9c69c20868a2d0010b829df85848e5e0689d7b6146b4b376ab3233fb4ccf256ac705544c3d3e5823b817a4844cbf1233173e4d3e06d1af5714b473494e14188ec6a22c616f10a8f070c55416f55769638cb897345e0f963bc52f77a49e9109ce25da5950362f948f64b751f0ba748558b53ec42ba631aa20d09fd1b7774930e868ada2139848b649923bc857c292c6764e78ad14a8888c3f450940e009dac1f7bf7baf0358b02ffd4322a11d1ba5a41ff46f1bb8e8e17dccf878cb3cf49246b21c42b74a609ad4fcddc0d8303c4bd22b2b08be732a51bf172c708584b24fe6066519efce8319555bffe443454fa1dc682c4b027d7cc110f2da20fd768757ba6724945cdf5832b30383f6f7586bb8c84f12d160041a3e218770d950a5b8f4e2f3c8afe1cf467f75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef76c402a4bd1fd97ec7cb0657ebc265c6b14283a23241722901633641a1252aadc4c18ce03381be5d83370dbaee0482c0440aa7aa94902a00244e0237bd29478fcb15428af69077ee4e47ddc8bd2adcf7d97a29fc56c75a24a213a103a1e3586"]}}, diff --git a/txscript/data/taproot-ref/3b055324162a840bb031e742e417383a3c2b9fff b/txscript/data/taproot-ref/3b055324162a840bb031e742e417383a3c2b9fff new file mode 100644 index 0000000000..93cdaa7eed --- /dev/null +++ b/txscript/data/taproot-ref/3b055324162a840bb031e742e417383a3c2b9fff @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a020000005f503664bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3a01000000af22f6838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45a01000000ec72071c0131d9410000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc7bf29061", "prevouts": ["8127570000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "5719770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4e193e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_67", "final": true, "success": {"scriptSig": "", "witness": ["9b79da4e610ea8d97803a99b4865bb086bfedb92db6d09a9c17507146a4095ea4be7ae4ba991c21a7701da4148762a0c34b23eaf38228ee9c4dbeac1a8374ad1"]}, "failure": {"scriptSig": "", "witness": ["214fcd315f91e6ecf985f4bd4dfe6fe5eeb75f82a37b5908f0238cc3ab1326017c5088c1ed806fd8247045efe366dcfb875eb8b7f12ff9e544fc6f8881d5885766"]}}, diff --git a/txscript/data/taproot-ref/3b6174c02c9421bd7512cb0b507ee81cbe621e8f b/txscript/data/taproot-ref/3b6174c02c9421bd7512cb0b507ee81cbe621e8f new file mode 100644 index 0000000000..2e1c5de204 --- /dev/null +++ b/txscript/data/taproot-ref/3b6174c02c9421bd7512cb0b507ee81cbe621e8f @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4601000000944c61c260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706800000000ba4a2dc30216b76a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966b000000", "prevouts": ["4bc55b000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "f1b4100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ab", "final": true, "success": {"scriptSig": "", "witness": ["8f7f754dc6d102ee359d2cd6eeb3c0a87f330a5d54e15e8e1d57cdcf2ae84b1321af4ab4a8771d0340f6a82423a8186482766759fb25271e9d15a509286ecfd3"]}, "failure": {"scriptSig": "", "witness": ["117aca326b17db0c910fa1c611ffe06726f46fdfcecdc130f573a4dc6990bc236c5d6f5b988da6e5da986029bd2211364b5e7db13a52af6ffa0b47a25d846529ab"]}}, diff --git a/txscript/data/taproot-ref/3b756b29419004b37c85b3e93c13d3f231e1eb67 b/txscript/data/taproot-ref/3b756b29419004b37c85b3e93c13d3f231e1eb67 new file mode 100644 index 0000000000..b1825443a4 --- /dev/null +++ b/txscript/data/taproot-ref/3b756b29419004b37c85b3e93c13d3f231e1eb67 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2c00000000a3ce2e21dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1702000000adcbac73bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b02000000deea024702e1a1c8000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ace21d5c2a", "prevouts": ["e96d23000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "ffd225000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "485c8200000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902cb78b3bdac8d11567c7dc6f2aa5b2ee71076ef2ddffba413e3ce848eb15618be522f737adc97fc90ba295e0727aa88e1696aa25671ff17692233f63ca1df4954b728825a6a0ce2da4774799ca8e2a5dcbafc3ac771c1a956234aafdbfceee834d356c2f129777a4398e354cf4e31c481ef8fe637971a2fbcc949eeb8e6bb4054d2c7c78d8f375b3e539ce67675343b80b177108de78dba18782b2225da8a599234e06c0a162419e01e0b04b7480db0fe96a523c1a7677d2aa2e544249157ca7b75fc4841a7ee073863a521315caf74241fcd3c7ed1dceaa89d8328f24f55aed57a85f7f2c94a5867cae4edcfe458e1ce3a1a9ada3dda198ffb11b8b231d6f129c5adef4bda7ee47edff05d26f21d7888f8a2c0fa3286dae7d20daa15b6573940cd0f7ec62ef6287760afe4131e32d00ef38757a9f8aae4fa78aef59b818633b428a82c29d4f2bd40d3a0b5780786fd644a0effd1a28a4067713b2fad3d6635187e1a3e7b27c7eeb6bea9b8d73810fbd9c60dd461cd792614569beb5440f193bd3de674d02b9674fb2ff8c12d114cda3b5b360967434a8c2d81cfadd021c8ee7a35fd27941c5c6b03088420cb4d79741b6e9d1e37967a35a3ef7106f6e3775b9b8ba4f4c1b111e20a914c7aba4caf80eeda8caac5378bff69c39479dffad6cb116db676b30cd78a4bfc0c3548ea30b0dca1b0f394d7ccd553d352b3436f5ae477dd6dcaabe34ca4848b75", "3b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f43516c2d68d132fac7bd8c90b108bd3a48adfbd6b0c62f8ced1a9f682d0b8d524213bc04a867e2e908d02e9cd05b1befa37bc2f591ad783cb0f6fd2a1a72397ef84fce916674b46359d0327d7b56c183d26d6053da1b16053a1f90da8a1d4e"]}, "failure": {"scriptSig": "", "witness": ["4d0902507d1ceddc54b77c465a747597375db581a193b47764273510b80b36a7d6b18cb8fae32f1b611da2a4d4fc716c2f2b1024b3534450a8b2033dc1f6c08e8e5f2fa1f867559fc5604a866e21e85d11f46cc874debb7bc0ab48788e81ea25c19aa1034e212616aa348429ed7d5c2a85027b60368bf4aa1010037d08acdd2071a02762db4a2c019e3ce2c444039915f71af5832530c89dc55334bebf3659e295f49889a58d0382fa4d969ab6588c28e5ed12747fe878c0e91d02ec9042549f2d5fdb9216cbcbbe39be42189c4f8ff854f28574191c172d47f025c83a9e463e5f59c27e30c6cf5ccf7c8be09beb6126c7b1ebed962bb9154f0e64760cfb2f5aec68e925c2fdb43c437615d5bbd083098715c448a0e9c11050a2824d3b464baaf48dc4efc7a79aab863283e98d66269c36b08a336eadbb2fd82e22b3be9c00c2f12116d9f565892b62d574a69307d52705f3c11f83cf174aee88a5dc24bf1b4903665683b3eed24068c03d7c38c75d3b933b15cea550701bc0202aaf4f3d93c3627c2ff31646694f90621b7a4932e076fdec416016b4491337e88233473e85877447a28cb9ae08bab119595d96e46686e37ddcadb60f74c9f6a52cc2015adefd7b294def59f55b0d1e27466c7a51d5cd75acfad7a0200f3d0ca23aeec056695d89da655d2f68ff2bfc5ca99de03433ee37496b3fb70e15d23fa599993fbe4043c42e03765c790578746abd8275", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed450a1526d7659d1d0ab8a304ec78556741ee62c830e21f1e920b63ff49823b3524213bc04a867e2e908d02e9cd05b1befa37bc2f591ad783cb0f6fd2a1a72397ef84fce916674b46359d0327d7b56c183d26d6053da1b16053a1f90da8a1d4e"]}}, diff --git a/txscript/data/taproot-ref/3b7aa5f0f9d0fc31f7be3558e9eae22f13652d33 b/txscript/data/taproot-ref/3b7aa5f0f9d0fc31f7be3558e9eae22f13652d33 new file mode 100644 index 0000000000..ab7b2eb779 --- /dev/null +++ b/txscript/data/taproot-ref/3b7aa5f0f9d0fc31f7be3558e9eae22f13652d33 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf56000000009d725befbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa600000000046d18dc04521cf200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acbc0a924b", "prevouts": ["e40573000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "c8ad800000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sig/key", "final": true, "success": {"scriptSig": "", "witness": ["bb2af8593bbcfac406e26202e5f13648fa5e664193a79fce786c89934a4c57c1aa81bbf0e1355adf76a445594d00db8c548820da4260010ea7dd5015aa3fe9f5"]}, "failure": {"scriptSig": "", "witness": ["ab142f24726777850cb9f9bd64c555e3fa49510332c574858d5c2186037810a7088199fd5a1b8cb033a262c4ab06d4a52cf54091cecb548a2ef5340170706d13"]}}, diff --git a/txscript/data/taproot-ref/3b964cb9d3464c3949a2e8a0f9edb54a4a9ce6c7 b/txscript/data/taproot-ref/3b964cb9d3464c3949a2e8a0f9edb54a4a9ce6c7 new file mode 100644 index 0000000000..1add070180 --- /dev/null +++ b/txscript/data/taproot-ref/3b964cb9d3464c3949a2e8a0f9edb54a4a9ce6c7 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1102000000e34a2009dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bde0100000060eae28fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c540000000002789cfd01dce73200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acae030000", "prevouts": ["6cbd6c000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "4c421e000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "b0574a0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6aea", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93622f1de47b063444ad2876036dacec053228c21a48fe4326b3b842e08dd2b252da2d42db82fd8c87bf94597052443343fe22a3a138f6b0aee44f71ff1c976f3ab32777cb2583add22ba560e78ee9942bfe3080d15b9172e7f2c8ac5adf5c65a1c36f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e170b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720f322cf06423056ff4efb147ba4330d28398a4f05a11ad98b1121aa54f60b594336f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}}, diff --git a/txscript/data/taproot-ref/3ba14a20059a5c8f8e184fb6d08736296adf21fd b/txscript/data/taproot-ref/3ba14a20059a5c8f8e184fb6d08736296adf21fd new file mode 100644 index 0000000000..6066bc14a6 --- /dev/null +++ b/txscript/data/taproot-ref/3ba14a20059a5c8f8e184fb6d08736296adf21fd @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb80100000095c037858bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4770000000021da5818dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce800000000a4b8f83f04b7dcdd00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c45bb44b", "prevouts": ["724b5b0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "d90c3500000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb", "294550000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e84c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93616f8948a019ae5ead2cd9d851c765ad0220b162570156f4a7dc6af8fd2e75e36f4bc19c05a4ad9ae05992168d490013403fc5515955a55899592aa66a61db799770b862ef93acb6091cb4ff8ef135b3065b278142aa4adab757f952a626e2b26c80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}, "failure": {"scriptSig": "", "witness": ["4c52e8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d39fd96f2153f8e279dd396423519f362f93616cb37cbc9b2f05e3e7bc75ada5276a8166e5256dc9010e53101dfdb6dbd4fafdb1e785ffcbffe7e4bfe923fbf99aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}}, diff --git a/txscript/data/taproot-ref/3ba4a606e430170b23a098c2ac6ee7213be618ca b/txscript/data/taproot-ref/3ba4a606e430170b23a098c2ac6ee7213be618ca new file mode 100644 index 0000000000..5ba12bd382 --- /dev/null +++ b/txscript/data/taproot-ref/3ba4a606e430170b23a098c2ac6ee7213be618ca @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccb000000001cfe6dddbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2c01000000c20cd2c40255c4c200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f877b000000", "prevouts": ["92f156000000000022512081f4094833c2bd1c8ccd20bca7d3b4bfd2d5ed628270e66be4011ac690e88295", "1a336e00000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "", "witness": ["304402206a130ea11521b20ceda33cfa589ae04f345a08c6f65264c643fd01917a53be5802206540524df34d1fb00190aba6674a1a63d89f4df10acd60eaba389de4d70adbbe81", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["3045022100e27839681f2e9abdb3566e2438767fa2c262e72a9cfa3b4e0d6b7ee7db147168022016fc9cdc28115d8737fe15fadf6be7f0c0ef5ded8d52bf5edb83bfc385a3377b81", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/3baa61730ba406d7fad296d7df24a9629ae0240c b/txscript/data/taproot-ref/3baa61730ba406d7fad296d7df24a9629ae0240c new file mode 100644 index 0000000000..4c2f11a981 --- /dev/null +++ b/txscript/data/taproot-ref/3baa61730ba406d7fad296d7df24a9629ae0240c @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4a0100000084436a61bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc500000000b28535d6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd2010000007e9916a503f4c94f01000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e77c000000", "prevouts": ["f56e7400000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "259f7f0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "acbf5e0000000000215c1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "dd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2823dff2991922f121728685824385d20f53064595141c17e375e09b6c17310e1f075c573bc42ff1b5fdcad1a87ebee849fc17bcfc5c414a2a4f901b5a19cd44f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d5adfb4b655ff7e7194216f0c9ec7a59b69961b08133bf278a8ed5672f2f6a4fc12d2886f924517b8c41f4755cb69ff55f68e740076f0e346dfe7ab1da23e202491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}}, diff --git a/txscript/data/taproot-ref/3bacefe15c3e633f44d830137c6fe22c074b155d b/txscript/data/taproot-ref/3bacefe15c3e633f44d830137c6fe22c074b155d new file mode 100644 index 0000000000..54e819f0dc --- /dev/null +++ b/txscript/data/taproot-ref/3bacefe15c3e633f44d830137c6fe22c074b155d @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c910000000057056869dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c47010000003cf378558bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44d010000006ea78b090428b4f3000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac70000000", "prevouts": ["9f7a60000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "8619550000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "478f400000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "597d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8e1a055bce30035b144601862be42e0b1f1d387c5344cafae4ff25a0d1808b56acd61c62feef9509bc7b3762bc81079411fa6867ea4986820580c60fa1e8298e9"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c551dd4dd159c7937eee09518212705b0904c5c3555f506114395535a1fb444ba393999847c63b69274661db27cd2e7bb4343911a06570db858c301dc754c7eb4be962498b383c32e8a84fa570ade752f3a2216469b10dbfd65078bd8e1b5998"]}}, diff --git a/txscript/data/taproot-ref/3bc46b0f49e132b39a7468c0eeae4f18c15a9e46 b/txscript/data/taproot-ref/3bc46b0f49e132b39a7468c0eeae4f18c15a9e46 new file mode 100644 index 0000000000..a3dc70266f --- /dev/null +++ b/txscript/data/taproot-ref/3bc46b0f49e132b39a7468c0eeae4f18c15a9e46 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdd0000000084353b078bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a0000000004495027302e6bfa3000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e791e25a5a", "prevouts": ["3415660000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "d8bb3f00000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "e07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dc752bbc00728dc9fc97a524e5c00d8fa73d20f44eeac2a564eeea9db1553afc3bc00f369fc994f47536ced64d5e4f722a68c2ed1128957c24de4b5158af0ec63ccd0bea79832f66dcec0cbfd0592e3eb2d999b46ac697170d667eb8939a9687"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e73d9d375b530aa22fee240902ecc7793689bdebd58e9771ff3d6e92b1aa7f5c13ccd0bea79832f66dcec0cbfd0592e3eb2d999b46ac697170d667eb8939a9687"]}}, diff --git a/txscript/data/taproot-ref/3bd1e196feb0c029ad908a2c989b46a4c75e87e4 b/txscript/data/taproot-ref/3bd1e196feb0c029ad908a2c989b46a4c75e87e4 new file mode 100644 index 0000000000..06fbebb7b7 --- /dev/null +++ b/txscript/data/taproot-ref/3bd1e196feb0c029ad908a2c989b46a4c75e87e4 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfac0000000017ce8cabdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5f01000000fb96d0ee013f6e34000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787bcab301f", "prevouts": ["18dd840000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4a3e5a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_87", "final": true, "success": {"scriptSig": "", "witness": ["8891ec441a8fed191cbe43605957eddbf420cccbfd1a991a80ba020b1199fc3c50f148118f94a379b38fa564bedc3193b03a93ad0a9baaedeeb8de153de85b7101"]}, "failure": {"scriptSig": "", "witness": ["5cb37f0a3ebda88880990442443905e0ae293ec30e39a0582b10dcc0d4def3c817d2a14a40048b38392f18f6a57b8fdef983215a7ef3b299be90ca0aa87b884e86"]}}, diff --git a/txscript/data/taproot-ref/3c0a722d83c61bffb4712e8bdb67f68d6757d30e b/txscript/data/taproot-ref/3c0a722d83c61bffb4712e8bdb67f68d6757d30e new file mode 100644 index 0000000000..abb9f1e1f6 --- /dev/null +++ b/txscript/data/taproot-ref/3c0a722d83c61bffb4712e8bdb67f68d6757d30e @@ -0,0 +1 @@ +{"tx": "36449a2c02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0f0100000000b960bcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3700000000576d43be01f4b34c00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac83000000", "prevouts": ["5386840000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8", "e6232600000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "997d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93659100ab1d99009eaf631522d0390412a62a32905c7f687f8ed538c1d75c8e249e3e7df71444e7cc76d8e211582e4acb0f4a71a503115fbd605db9d475b3b0609413afa0de0ff2ef52577d4c80443f6003c675907986908c28bc93ded208ca160"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93617fe6272c5fffac4ddc4c47d3a6fc8218dc4d9298ec687e863b37acdb8199f2e2e3b986c0375fedeed2562a6fa36a7b38b0ca47fc0125e42be2f4bc52e49716a3d673df10a8cc98fc65477367c7f3bb838b82569297570384f0d4df8cd49e6dd413afa0de0ff2ef52577d4c80443f6003c675907986908c28bc93ded208ca160"]}}, diff --git a/txscript/data/taproot-ref/3c11357c518486213b14a41e23ce85acfc7225b9 b/txscript/data/taproot-ref/3c11357c518486213b14a41e23ce85acfc7225b9 new file mode 100644 index 0000000000..e561ce8498 --- /dev/null +++ b/txscript/data/taproot-ref/3c11357c518486213b14a41e23ce85acfc7225b9 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a400000000bf14df5cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c000000002070b123bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd800000000fbff2f2002a8abd800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac05ebd32a", "prevouts": ["79d30e00000000002253202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "5ed7480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "853c8300000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["c18461cc346aa094096b342c10a66208d719576ebcac841c65ce6ba4e93f60ab55a13d8fcaac985f6aa013828744cdde4f51fcfd86f8c5dd481210b20804d5e2"]}}, diff --git a/txscript/data/taproot-ref/3c20247465b4757bf0758627c8b5e4839dd819cc b/txscript/data/taproot-ref/3c20247465b4757bf0758627c8b5e4839dd819cc new file mode 100644 index 0000000000..8bfeffd16e --- /dev/null +++ b/txscript/data/taproot-ref/3c20247465b4757bf0758627c8b5e4839dd819cc @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f900000000bceb13d28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dd010000007fcb8fed015e995a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9009232e", "prevouts": ["e33d3a00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "3bff3b00000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f968", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363479168552e0c3d7df5f44dbbb743296079984d081213225c4f28f061a2ab719a4dd4bfc6549e8d5e198b0f1e67d147f6db02444245a6cb27bc19444f2462468d332399bdd0fdb741da8d579adddb10dac50c4b595c0031ea1e156729d78e3487d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c5d39e9862e20f53a0e43cd42e822dc4fc6d6c3f6bbd1afa8e6a99e8abcb2192a58cdb730d5140e8751cef937639de4f5fbc77d98986906c68a7616d2fa212f87d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}}, diff --git a/txscript/data/taproot-ref/3c4f81b3cab5b54ca2ec122fa809fca650b47db6 b/txscript/data/taproot-ref/3c4f81b3cab5b54ca2ec122fa809fca650b47db6 new file mode 100644 index 0000000000..0c50b1adaf --- /dev/null +++ b/txscript/data/taproot-ref/3c4f81b3cab5b54ca2ec122fa809fca650b47db6 @@ -0,0 +1 @@ +{"tx": "d105fdc102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0301000000971ac2e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41b00000000099cdcd0044657a70000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79617aa1023", "prevouts": ["43046f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c8213a0000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090283a58b717bb09720c20d04b00847c5f2d0892ee1723208bf1c79cf95ad0fa074694042e6c4aecc8374c42f095cce586dea00c533525f82657cf57ea5944adfd927a660bf5bccf0a4ecf50680e29027294904791c8337089da38b64a4339bb54733b31e31f6b6a1c5be8bd3aae3aeef05a60814ead4c36a1bfa349b3095bc210d133446f83bb20ab0178fc796e3756cbaa257970ad6cf9939d572f227f6d66bf0a1b5a37a89f394a5431b5130ffaac17fbf8cb66f89dda17854f181796192e1503948bbd5b4589e4200bada6a99a67d26076d4c4ccac6c42963e9d738c05cce90e6b3796466220a85a11e420eaaa232c9a56e8b63514cfd49815d20f60faef72294dc85098d4563bc46d9ab322ba218d7e21293c44e143070606895228830c145b2970cd15ed172e83ffe27baa71808cb69ba4244988ce9f40728eab596c350481c8cf4c2fc40b3fcb6143a9f0d36895465496b76c3bf9a926a8c1ca7918554a3c104df9900ce9b93c0937df733c5e8712f6310708adbee79b3059ceb9be16d6a53fd82f30529e839e7f31dac797a4379bbb2afb5d994b77cd671c900688e42b05768229a531c909d26c0c0262b9c0ae2b0f31bdd3f0b8f221a9bdd64df8f99672734b47c6f6943d0f79885a55845febc6b149f526b63143bda37c542aa5256571601a0ecab128b84b582047edae7c8470d4552db589d926dfb5badd136a25cbb3976d6d878b368491b75", "a47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e298b057fcdff1fd9eedffab28c4b84177a993dd4b4edb713a819d49be9f33539a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100eec4f69e5cd9a0f0c1fda8eb2f54297e33bc5edab35b299e65e2653a923d6ca55"]}, "failure": {"scriptSig": "", "witness": ["4d0902b52f8fbb9de22c73b9ed1544813d415a787c2c5484a574fe3a4b3fb45b25cdefdc05d19065d57f8bac97ce3b21f37f1fa319394199461af2223057dcce1ddde5ecd47592ec6309721c864cad28933d42ae2f1fb48b649869b27575dc811dc7e18d0ece4115a24cd4b750a86441b1cb96ca61f5c6ea311be9d2d64bfc44ed9cd3abb5ed0d1a3d89a165876e302f484d6a85cc7e642a4aab569bdf090bb07f12f8c9db042c4fa5bb350ae1729e3b6b560d46ee37b20e4da5bc3ed7d0eff21f6a2cd6afea1192dde618fd1ea197b4493a513f09535ccb65a85d8f05795827cd7bde7eb93e6972269b72231c041294d7f17489847ed56c50427429d98eeeb47b3a2612060c0520c74cc73b7e808296c0c0cff51cf41901e13e0439c7df2b5998a6d3fc0434bce18ca6fefb16306a7ea0e9fadeff0a55980ae595853ad8ca181354f990f0f9f451d46225c62237537bd9582c13d3e672a1701b844b2fb1a910a89ef4d18c68196f60c3ddb8bd673fa35a38a0b484fffb1659928dfdb71178faa029c7119ad1d1ac76713976583edee3312e95f89949141bc9486c06c407c774c7320a54671a76980e81318258760d8d6ecfc179dc1c2e0808d4ec7209d5bdb243eaead5322b7bf3e85dc9091d448eead5e1de5218fb84e649eb188fcf462b9461443563b821affd1bd4405cf5abcd139a6c623649509ddb2918e04252637fad9c2181e61a5f847b81f571f075", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e6f2ceb64e65b7fe0ee2bcc907e6bb6457910dcb8068df083547398b80574b4f873bed7b94a92ccdf1432eab063a27f935bef099df6a1cbcf6734b218f2b6aa9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100eec4f69e5cd9a0f0c1fda8eb2f54297e33bc5edab35b299e65e2653a923d6ca55"]}}, diff --git a/txscript/data/taproot-ref/3c695558731a219357e99fced06f0c24b38b6c11 b/txscript/data/taproot-ref/3c695558731a219357e99fced06f0c24b38b6c11 new file mode 100644 index 0000000000..19d87aac45 --- /dev/null +++ b/txscript/data/taproot-ref/3c695558731a219357e99fced06f0c24b38b6c11 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e9010000001dec1589bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf260000000053ee53c504472cad00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac11ed5824", "prevouts": ["65a33900000000002251202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "ee537600000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "final": true, "success": {"scriptSig": "", "witness": ["88d65c168f8a0920214e83e6f345f559981529a1045602dbf8c6ca6b1fa3b5e90f59a018b3bb9d11709625a0997bdc1f558ffcb6f94ee82b58849a1287e5a68b", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}, "failure": {"scriptSig": "", "witness": ["39f4cbfd76887c4a92dca98894059cbc1979e2173137cbb57b75fe307704ee3411b9a854c4ffc10440b9df9b4cc6f1b0442da56d252efe435fd50c8a887ee622", "6a", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2072ab2582871329e6d2ee7428615b3ca131677fbf9a036ced2b197b0b63c7847f"]}}, diff --git a/txscript/data/taproot-ref/3c6b79f35456c42d2578553948e940b494865ac5 b/txscript/data/taproot-ref/3c6b79f35456c42d2578553948e940b494865ac5 new file mode 100644 index 0000000000..a52847e944 --- /dev/null +++ b/txscript/data/taproot-ref/3c6b79f35456c42d2578553948e940b494865ac5 @@ -0,0 +1 @@ +{"tx": "5d45ca5a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3100000000f9556abb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bb00000000953fe6a9045d685e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8eb7014c", "prevouts": ["0290260000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e", "4f64390000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "0c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7110d101968a4b58b88744c41dbbb4e2ad9f7c85e8f992915dc83ff5cca0b4028257bae22e6d8aedb31b43cfe467850e731fb88c1221782039a4c16ef44c35617d0d4fc7404dd8984f6a1705481d95654b515a34c586c99c11bfe20e9503459"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fad8b86df4811d5d33605da5981d7f94c5d3490296d8615b43f813528d1a3f165ada3d451ef6042e8b6b9e1a05667773e16935ec77c1049456c2d3709876bb0617d0d4fc7404dd8984f6a1705481d95654b515a34c586c99c11bfe20e9503459"]}}, diff --git a/txscript/data/taproot-ref/3c78b5bf3e8a594974afba095afac84660219f6c b/txscript/data/taproot-ref/3c78b5bf3e8a594974afba095afac84660219f6c new file mode 100644 index 0000000000..4b674f4acd --- /dev/null +++ b/txscript/data/taproot-ref/3c78b5bf3e8a594974afba095afac84660219f6c @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c370000000026ad1f6dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbf00000000f2e52467039292ce00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac85020000", "prevouts": ["88de5c0000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "035a730000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6add", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936737f38b389e91945a59e7d1a54cc6743fa202767b45d1f6a954572f10f069a57b6537362191d9a5e0aa3a730b93b6f98a99ef63ed893bef4b9dfa7e3451eaf360e1f075c573bc42ff1b5fdcad1a87ebee849fc17bcfc5c414a2a4f901b5a19cd44f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936077cc45fdbcc3c6a197d438d850d88fa7818ff45d2680821c93c0ab1e64d7a1e20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e18e3807b59d4390aa508570eca32c61fc450dce8c5cf98deda801e2e8c3fb4b07491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}}, diff --git a/txscript/data/taproot-ref/3c986463576a17cc12996a738a2cc479d1198df8 b/txscript/data/taproot-ref/3c986463576a17cc12996a738a2cc479d1198df8 new file mode 100644 index 0000000000..1a78176a5c --- /dev/null +++ b/txscript/data/taproot-ref/3c986463576a17cc12996a738a2cc479d1198df8 @@ -0,0 +1 @@ +{"tx": "6640765702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5f0100000029d0c5b9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1e020000000a5e90fd0143ee2a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7ea02a33c", "prevouts": ["6120210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0999250000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "e97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362896a049359ddc96fc816a03690dd361f765cb7441c784067b848ad4ad8c32711a6bebb6dd497db999161621b23fc9287dcbaa466f13da5d035327b94edd053dbd7d7e2e0b29bfb283546875adbaa200efb560b624d50a8165ce6ae8ed501592"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936615da7ac8d078e5fc7f4690fc2127ba40f0f97cc070ade5b3a7919783d91ef3fda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0edd1eeef23b4191adb89e631380cd7acdd7acf00b470d5a9d9dc70e20df3f09bd7d7e2e0b29bfb283546875adbaa200efb560b624d50a8165ce6ae8ed501592"]}}, diff --git a/txscript/data/taproot-ref/3cb4479d7f4d2911b165d8e388cda3c7da36bd62 b/txscript/data/taproot-ref/3cb4479d7f4d2911b165d8e388cda3c7da36bd62 new file mode 100644 index 0000000000..f98d9831fa --- /dev/null +++ b/txscript/data/taproot-ref/3cb4479d7f4d2911b165d8e388cda3c7da36bd62 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ce000000004bd0f99e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270610000000097c65b8d01828a39000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47877a0b633c", "prevouts": ["06f4350000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "30571100000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902014e396e8146f3a3431562dd8f595ab074d6ec1d0d8287250ce946d6635b51732c0f9843d6bf8496532fc900dca4083dca6658d29c7851d1956b5e6dd23a3e0109cc34f511f59b7fce9d624b5ea3c3619e737bbf1dc6ba5a96c115b9d985ca16fc3021cf94c9168b0ff065ecd3fcca362aa72ee0828a5e816698ff4f54dea9e31ec98c9eb353cf8cb45d446278b35da3b70365a505dd1022f5d97572ffea03a986a7446cd33866256e06329c9f24e90f74962fe8488c893d564e3656a706f0d71584df1e676aa4280878f331a1ee40babc890ac22b01cd3ab5a3f2fac547c3ade431dde9520d483adf2c507b670bf4c3ae302ff2f2bcf5f67057c1dfe00c6c9ac143682031f8f330fd2cd11b5d02335bd79aae17c5bb42dd5ee6339aa970a2227258d3e77b617fe787aebd5ba159abbfad24de598593354ba2e889efd80101e45b2ae4aec4c4554ac153c6f6aa9e5e4e724e6b582eb3b525eef679a8a1e95513d6737c119fe33abe1c335ad3b7c7e8621047f8359fd79d789ce0362df3e573770e8e942eed9bac29a7ec4e9e08677f275a0d9fcd62fc8dcb3377067448a1d830fc16464538c6ace04f56bb514dd8b2eddc72e09876fe26f6f38103edd3244918cc58c76e35174c47cb8052858ec3d0cba8d20992312a4bf1f03dac9b7a5b4e503b77fb0992b4aec7a046f8a8a42d4fbcbb18844d90a463ada1871824792fecfa3365712cf8ab09e56475", "b47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db0523871f2cd538158ede77b2d54a3b132610dca27e4b1b70c1c98b9153bdc120cb1d3ba38961d99eb4dd4ca5f4423fa7ecc992e517adf4bcc7891fe49c1f0e90a6d927376acace3683bbc4ff9f5d15a4c9ee2ad4271a1fb38c29668c3ce61898ae4fb28ba039f9030001532aa52d54afebb8b1d186c7283d6707334cdf0cf3"]}, "failure": {"scriptSig": "", "witness": ["4d09024398a6799cc67492d8b06aa782f94519ea08f290828c71f6303a4d3376590129dac016694a5bb4fbd631420992ba42145f5fa1bb598cb3dde7011a51e3ce752187b464c878fd7a4ac072baf97592a69aa23590d8778acd8ac35aef8c6e19e3f81122b9926cc8c2f095e8746b507c7cf037ec42517540a65c528862d5df38be27b23f56aafa804a806cabe281b0323ad167a30945ac1929eb9c62a49a6729656a2f011a23f80e386f836c4a3438df5aa85ae8954a369192086238b3700c5e384f7de5b4ec5c11b5e868839df7b5650efc9d07480d41889da51ad7bbac1f40ccfa2a5bfed3e8c6364a9990154419a927d246b7a6d965cbf164bda614e2ef79b51b25e0b6433c89c208db07caee28aab62032d0eadf7acf748da7d0c57cd05cc7f34d83ad53604a31b1142251f53ccdd78552cfdc12740a27d2971895d16a50a536b1a15ae155da18614728e557d6ce39d0583a2e170d020319533a179033b26d1bb6b2e4ca8ad0cffc08c75a584c050499292b8b46657026239d133e669fcb0f6555a093ee8f3d852b89f33688993acb0fc18b0415f645c080dabd98155667f64ec5e63bf847fe488ee836270d9906bea9d05d0c824c5757f4d860a56a6f89b4525d2666b964a72df964b860abd1afbf84b43a9c9238927007ebfaa7f7e3c4ee7ea7931d73188a98b75a7cca86762277c0acd5ae1f0855dcab8107be4b6deaa8245c6c90b1fa425e050175", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363397305a46d15a1fbd1718c65c5b71233ce63301ff33254e27be79b1faf0455420cb1d3ba38961d99eb4dd4ca5f4423fa7ecc992e517adf4bcc7891fe49c1f0e90a6d927376acace3683bbc4ff9f5d15a4c9ee2ad4271a1fb38c29668c3ce61898ae4fb28ba039f9030001532aa52d54afebb8b1d186c7283d6707334cdf0cf3"]}}, diff --git a/txscript/data/taproot-ref/3cb7605604a629153b71183c4083311f53f6fee1 b/txscript/data/taproot-ref/3cb7605604a629153b71183c4083311f53f6fee1 new file mode 100644 index 0000000000..cf45280cdb --- /dev/null +++ b/txscript/data/taproot-ref/3cb7605604a629153b71183c4083311f53f6fee1 @@ -0,0 +1 @@ +{"tx": "2168928d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b680100000082a688d3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0600000000b79a99bf04f55a8e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ace8020000", "prevouts": ["0ab323000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "5cb06c00000000002353212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["30440220487d2d101ed150b62a24d7d92cfaf315ff929e30c8260139b5399f4cb0af74b602205eb352da3f71fe94ceda84c40c7d13af0053ac9a15a068b01b571f3585dbd04a59", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["30440220487e8ce3df65516fdd3d0efe2c5d41647a023ace5fe6bfda4987ef87b33806160220575ee889d7357643247894ce013d47555819059d4de0449041182149df31807b59", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/3cd91b4c3a1d21d1c90b1e6542ae78fd35091778 b/txscript/data/taproot-ref/3cd91b4c3a1d21d1c90b1e6542ae78fd35091778 new file mode 100644 index 0000000000..e7cf511211 --- /dev/null +++ b/txscript/data/taproot-ref/3cd91b4c3a1d21d1c90b1e6542ae78fd35091778 @@ -0,0 +1 @@ +{"tx": "778899b603dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c95000000007c54b39660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fa00000000b5fe039b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a8010000002867b9b101c0ee1900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2bb98647", "prevouts": ["325f4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1bc120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "09e33d000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b", "final": true, "success": {"scriptSig": "", "witness": ["38e7db28381c7f870e8f3ea9691ce2d38b31ff5050529ee2b45b9759224fe85f970c45de2c0d5885323318ce7ccbbef71b2993cb1589e8784f16bbf0cfae4a7381", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["bde7f721c522a28fc221518a19b4513e461cdf6e46bae113944acc8fd055dc77e37e75dd6c52c9bba0967fa57bb408d14a4c97f19b6f5de4dabdbe835a78ace40a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/3d4082e12a369fee00a97f5ee6a3b72ea6f15238 b/txscript/data/taproot-ref/3d4082e12a369fee00a97f5ee6a3b72ea6f15238 new file mode 100644 index 0000000000..fb5ecb0d99 --- /dev/null +++ b/txscript/data/taproot-ref/3d4082e12a369fee00a97f5ee6a3b72ea6f15238 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9400000000c44b13eadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0401000000a6db52abdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c54010000002c43129203bb4104010000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6b86cdd5a", "prevouts": ["b93560000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0", "27ca5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "17f34800000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/leafver", "success": {"scriptSig": "", "witness": ["b1d9a37f61f7c7a4c82bf219436c4f1927e6f76722701677d56a29acfd127e0e3ec0ccd33568526ed29e04a28bde190ad28971e0d1b6d595d41d375d411bea4a01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "500715dd98e8041b179cfb07"]}, "failure": {"scriptSig": "", "witness": ["1c7b30a5fd81a190827244ddb13b0f4ad8d3404e9741bac8d15529fca5cfcb7f11ce707b81d4da50f8023c7eaa6296aad320c7b6b4a053426540971565c1869183", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "508116c23b6787b2098b11682c9e8d20d9827696375b938baf0cffbfc4ce2cd059e2021f4d191b54cc75d49b52dd9406e95240b59332b6c16a74218182a06f7860c023aaa6dc5890e4ba1af1b997377a356d263d187885556f5d918b985e226740b3451d49c771216044a4a0ff2165554ad703ed3c401d2744234cf4d2f9a2760551"]}}, diff --git a/txscript/data/taproot-ref/3d4137ffad2b1c85003d032d19a2150f4b6517c9 b/txscript/data/taproot-ref/3d4137ffad2b1c85003d032d19a2150f4b6517c9 new file mode 100644 index 0000000000..308fb8c73a --- /dev/null +++ b/txscript/data/taproot-ref/3d4137ffad2b1c85003d032d19a2150f4b6517c9 @@ -0,0 +1 @@ +{"tx": "c830ab1802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c16000000003360f5e8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c650100000012a15abe03ce9c99000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb5020000", "prevouts": ["be9747000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "7bc35300000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826047efe14993a8a73b9baf7cd14f960037ac1d53bb1921fe06fa7eee8637040814a663af4c315d4c0e419951403071b67d2106b9ce8bb6d7e6c872100135a32b791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b9fcf0a7c92dd23244df9580e55d15e57255b9f51d71ced09e9b8172bc04386f6047efe14993a8a73b9baf7cd14f960037ac1d53bb1921fe06fa7eee8637040814a663af4c315d4c0e419951403071b67d2106b9ce8bb6d7e6c872100135a32b791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}}, diff --git a/txscript/data/taproot-ref/3d65682b1f434030f11d6815360c3d269d231474 b/txscript/data/taproot-ref/3d65682b1f434030f11d6815360c3d269d231474 new file mode 100644 index 0000000000..08f6f6d62f --- /dev/null +++ b/txscript/data/taproot-ref/3d65682b1f434030f11d6815360c3d269d231474 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3e000000004eecdbfd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40400000000dc744fac8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48801000000149ea6b603d7969a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88aca8a50227", "prevouts": ["6f9121000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "11d139000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "5094410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "657d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa19acac53f630ad836c1252ba923d9d3235c3c343fcfee9c8733d292c93bc64142bc2c7d802e8c870cc0fefcfae9d23d316cca1682651be3bf62b663d5ddaa443"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363d30055f1b2452a1671c6e1eba433b096afb8e3d3c5ba62baf7090afff22fc4e74d92406f86dee9f8c04bb958856db6cfc0bb7ea92d17397457214a16beb1de2302781454c6297f6b8a579760f4d591c0acf84ff9d038b064bbab8a5d53835db"]}}, diff --git a/txscript/data/taproot-ref/3d6fb8e46d4f9e03d6de0e295ec2e0e50df1aa5f b/txscript/data/taproot-ref/3d6fb8e46d4f9e03d6de0e295ec2e0e50df1aa5f new file mode 100644 index 0000000000..1df0cee865 --- /dev/null +++ b/txscript/data/taproot-ref/3d6fb8e46d4f9e03d6de0e295ec2e0e50df1aa5f @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42d01000000bdb630c88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cd000000003ebb08c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f400000000c26dee9901a9b60e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374879a000000", "prevouts": ["804a37000000000021561f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "47ba3c0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "dfe4400000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["be422925792e3ada801d54172a3f99503d375b2a7cbec506e7880aeea8a8340bd54c174c2df59760be6047ed0571ab8346cc9029b75c8f79bf2766c41724817e"]}}, diff --git a/txscript/data/taproot-ref/3d75756c8dd79c4efe056dd5435cfb6a2457207c b/txscript/data/taproot-ref/3d75756c8dd79c4efe056dd5435cfb6a2457207c new file mode 100644 index 0000000000..40fd73ab84 --- /dev/null +++ b/txscript/data/taproot-ref/3d75756c8dd79c4efe056dd5435cfb6a2457207c @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd100000000ec47e22bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfae01000000926ff007049a1bec000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac12020000", "prevouts": ["942b7c0000000000225120cebe24bd65f3df56aab440a71cbc9879a1b3f80f985a5dd97b0c93b61f81cd49", "6cee72000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["edfcdfbea3c23f3bc1b87a0fd8f36757ab9564c40868070b71e554f8dc9078d3ffdfa0dceee87a0780f180410e674c5db6c3fe142f05f91227a8a0889696a3d701", "d28b204afc5398e160cbfc089192d27fc37dd6d8d3dbc4d7f744d17909f23444246ea1af7d8b725890a1852f7ca0ebf6dbc0e050545f3910c5f8f8e34d82a6d0110fda7adaebc667887af53ae9c9008d66a94f06be60efeaf1e5cb2a0ceff56cc8a4a5037beda28f6fe6f92d4deac48aeb00e163832b5b9032ed05f1dea398c0aff5daf1fe2e2341c0d0b025e6b6caa31f019c1e1cf0f0c9a461d30fe2ed90a9b3ba541d8f09c3af97f025464fb0bd", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f9c5d7eb03b7f54c91714f607bb106c5a9d67c7c5b975a10fc82efdaa356df65eddbb0afdf37ab261319ce7a8e479c320dc2477983d69b93935705b3f3620fb8ac68ace3853064e722e1b1afd151878c5865be09478b565571c169dd243fb993bad14950d771775f4676bac3906f4b088a0db4dc3dc7eefd6e7ad257912098000000000000000000000000000000000000000000000000000000000000000007772bf51064c90c0e58f48f9db455f9e50b8d8b08ce5800938a6261ec8209eae90b7b6e61126f6d3790e89865ab4119d57119006a85e75cb22756b96079fe197478217f5739698d82667998ebd36e9a2911eebce53cafd314027d12f6f7d6fb34e19f2960ef96b8d186a912da3a133529bf4f01072411fbb38048cc022ea939683a92d5e9be0215a4c7bafb7df24f1deddf8e3e70654a2a0c11526f54ecb2bded6906ecbd007b6adcd2d3a9c180f477d4f1c53a85a3c2f4d888450ce3bd3af660000000000000000000000000000000000000000000000000000000000000000b08832c8ada8bd9ba25a569edcea6d0b0273a8aa79360f1e19c2d1a818c8ca09ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe65874829a6fca96a658b69cd99e9a6ca9e70e2ea5a3c85673e85a85bc71fae6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ff857e1fd6562469c8364952c860f1e45b452f421582252bca13798aa371f62853e97ade0634f6e230ff512547d39d8acef1caaf72f24acf577c27424c68925ee0a5ae304c259c27aadd9bc76d24195f749514a131e48c16792d10e8c2a8e485343f3af3562acf496328ab7e97fc4676c110ae7813eb9b70720dd24cd33338a0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4369e24008103d8c9e6c573f0264e51327bda5fd52ee79f9386fa14dc4c224b742ad2539f6c1874c2ef824f3863f2a8f8052c33072d847547bcd0f5e72f332f500000000000000000000000000000000000000000000000000000000000000007a045ba295822f4cf3608dedf74c453dbad7c9617bc8ece1adec3b86c5403c12642807f1f220d8f386d1ab0609e9a99cf8f1d43c97626e5962d2cc1a0b5af4eafb4e59df34d3d625e91de9c6d25c50026a81b8c20f7cf02fc47355ab870c527d1ba446c59d7334926c5d1dbe2f8a1e1913480ff52db2a0bbdfa86f9ec4580f3c99914b59be4c93f5567d5f33492a01cc2b8e4fed7ae5ce0fe2280a98bda1468d1a906c9c42c9bfaa0d1fc5f6cd71c6c6b161419255acddc046e94fcb824ffcc5d0e462527e0dfdf1dfec4afe30cebf6e6d88ff045127ceeaf75e2bc4049d4fce45158bf70b8138e021f56c9cbb83cba475f04a8a436b707cf9aed9b3a37ca431aecb41c179c688a28bc4eb67bf14294077467cd7feb09b627db9cfc2bf1ffa03816beeec1135ad37064f945160b3191972d8052c36f1397e9bf72ad4098dcfca5a4fe73ce09fb577a9d78c681f878a257248613d22d56c913109f02554ec7b5fa924f2dbb97153499dbb253aa235f5bf5053126d36e5138c04d9d0195b1b36fd00000000000000000000000000000000000000000000000000000000000000009700eae923f62337efa128c93ca75ddf6d9923f84eb457d4bd4625ee87aa667300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dfc98418a242151286df9f103cc91b4737daf3474bb060ca60897a5071c5cb13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0700c3b3d3a3c9ed6f7f9c9b876d19986dec133fe4e23093a3e3ac2321f772c01dbeb5fc721e190f39925e73434c74a8a5fe462047b1e2dfed09c47bb4a116e0000000000000000000000000000000000000000000000000000000000000000531965327d21e27d9d2b918afcab2f3209c8d7dc10cee9e8f37b414c6327057f0000000000000000000000000000000000000000000000000000000000000000a57a09473d1dae69a4cf8423571bb06b901f37253cdaa6e948f92e824fe53774ce748e9f089ba7d5836bd2cb3dd575489d6e593416b7cc9b5925f90571782dfc0000000000000000000000000000000000000000000000000000000000000000795be99b998bb12ec6379cb80d2a5ba5e9fb78303d4d1c6dbe7b097eb266d2a98cf72ef937dfa60258e4433686f6afa93de6212056f4657dbfee7f338fc9277fa6889804ee8b98431d81a65f360f220263348e9c001e9c0a2104450849d5944bed1c9d5b7e3dccdf65674148f2eb44cecbae02a19bddedb6c57fdd48b539e9c8e2e8f6e0f6662045e628a81353e9d0de000a43d6896b152f026b7fc2fc4fef146db315e33d1b3bfaf53bdd19b81a22db5819c2ef1c9bb9cffed167dd590e576415829a408737b4fcf5f6c2ddae5d97ce9f8a129a6a2603b93744fe70a217be14ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99475c4fafedbb1ecb857f13fffc28b7f316b28c0fc88efc47b1cc4e52b8f0b26e6ee6234bbaa24d441ddcf185f186d6a8adbaee2f84527033438a9a89d859b3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb565c8b6ca6fd3f80259dbc88568e44ffc1f0fdd139e5452c4506a5ab6a46818431d69bae4bbdebefe763d5cfb2404b1ba08fb0428c117caea304db70aee0c6d3b1e5943c2d0fb5b0cd32b50ff77324af6345e448e419c8e2aea7711f11fdb632ee771d395c186394417563da56bec3dca90ba3be085367b0664e7ef134bb2ad9702c541b0c4cc1fb44e45c9d1245c0a21ef808528820ba1b80892058b0c05579a12a9e32c3ad6af2463d5d03488875345078119f402d9e1d4c88e4dcd27513377695598d5238e4177608ead4d851e782c309dfffb316f240d019c5b19569bc16749d5177783ad509f99ee914289e4866ecf7ee28223cb85890dbefdc5bf75a67489ca239183c005d36675edc774692901f6229f73ceb4db07d7299ce374ae51e21e7d6da88b73aa8cc1f232b4adb5f5621c8007d07edf771fcd7dbceee497667bb079e3fc189baabe10c78292d9f9bb6273b63109c3083d411bedb78c3226bd0000000000000000000000000000000000000000000000000000000000000000ce47725597941674b7e8bd1ee969309592499f4f1ee4ac83d38834649a3c6523a932e52a4f963c304d828b42c0de38ed5d4fa7c89a2bddf97b64ad966c7b79dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb342ab9a519cdc07dd77b174acc17830f0ea8dfbab2073f15594f414b05c68e7df9ba1e754cc5c999baaa94b7d26f795d4153a238f2e329ea6da26f92df720c25147814778cb006069dd170d3611147781245cf5c03c564e714f81285a1ce6c4018d9e395df31e06a57c07065d5f8cb987b113ed9be344488c59eed27496792cfac4c01f702a704d993876bf616a89cab8911488be9eaeb3b8556b604297a75001c3c1288e65afaeccf1a83f1ac1b7744393b51fcc27297ab5cbdfff743d34a800000000000000000000000000000000000000000000000000000000000000008041f55c0bdc07af5d6c2c0ec4afd20fd042e64663daa99d6a3352ce0c7bf7cad397a496cfcf53857a5e0b8d861b2a23f67be93be84641615b5d82f4ba00d212690eaa87a6b8641686c102382ec3de9005ba359ee5914fbfac245ce48dd1b7b9e8837718c6763acec811ddaac0f572a99f876f557dbb40c0333903d0bb680659f403b5f131380e8dac882fcfee1480b4efc4e6475db1da71ddeb21f8abce3710be65713c1bf91fb6a50ee126da21bb6248d2897c1517325914ff59c2fb012cbb45f9bdac925ed4392fd350ccfeebcc481c08a911f558310acd7a9408c71ed063a541a121265934e85e47f10f377e07340bc406366247b3fd64fa61d13f5bc928fc32675e9e9148915a547e615c77048610f34a8a2944aca1c93b0e7e340298494ed729477b414a782b459dc5b91ddb3f22e5caf167d2ee39edfaeb7333db0898877ca6ccb4a88afa0e4c80140254b39c7dec208b865d962a7422468658cdacc472afcbed6a9d193e85f96d5273c5bb6c090f57d1a2c71c83d6db99bb64d6620f0000000000000000000000000000000000000000000000000000000000000000d5b6e753cb106da3c716a35df2d8dee3e417541b97f8f62bf1fe16a0a6fd319c9ead626369bd6d5f8484ff3da8a9b5c89c18b2d2d268e456150fb20549334cb8296673afbc702ea89fcf861b76b66b8746885fbf3668e09533eae1ed62fdec1179372bc439fe3e8ff996941583cdd821fa061b44ae3381420f4d5973f6a1c537e30df0147a77e13e708e03b38df52f197e2443ea7f7d686a34a47aa52642dc47ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2ea7b694001f5f3d230108f2e954385b3964629545cf5ffb1c89f944aae7b97f0000000000000000000000000000000000000000000000000000000000000000ea3c55499635864516e47c9569140163ec17b994aed30db17408e09a0f05fe2c7f270490ccecaa24cd2f3a34592ac8eb88835240957395e87c881f69826bcf642a78d7bbb6057f8839d6b39afa757e8d08156e2b63ec70d0ba55a8312a8f1989", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["edfcdfbea3c23f3bc1b87a0fd8f36757ab9564c40868070b71e554f8dc9078d3ffdfa0dceee87a0780f180410e674c5db6c3fe142f05f91227a8a0889696a3d701", "6d1918b7181d68101b4626a6d6d42553e1ee298c0b5fbf25bfb05227c2d9a8a1faa81168b16ab8e2885fa3dab118c996164ef710bfa88cca1d09347c5683d360f59dc24a012f5abedcba8459d7fed5f145a63bb583b1c0a0932b95f9120bd8a3d0b9c2ac6f0f58af28d43a3a662c00bbf2cc84d17a3074149592c9909f721278df120872cf3d0ff9a3ca48a660201bba384678216494f660c98272b9570335f1ac1a167c479b5d1213841267eeae", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f9c5d7eb03b7f54c91714f607bb106c5a9d67c7c5b975a10fc82efdaa356df65eddbb0afdf37ab261319ce7a8e479c320dc2477983d69b93935705b3f3620fb8ac68ace3853064e722e1b1afd151878c5865be09478b565571c169dd243fb993bad14950d771775f4676bac3906f4b088a0db4dc3dc7eefd6e7ad257912098000000000000000000000000000000000000000000000000000000000000000007772bf51064c90c0e58f48f9db455f9e50b8d8b08ce5800938a6261ec8209eae90b7b6e61126f6d3790e89865ab4119d57119006a85e75cb22756b96079fe197478217f5739698d82667998ebd36e9a2911eebce53cafd314027d12f6f7d6fb34e19f2960ef96b8d186a912da3a133529bf4f01072411fbb38048cc022ea939683a92d5e9be0215a4c7bafb7df24f1deddf8e3e70654a2a0c11526f54ecb2bded6906ecbd007b6adcd2d3a9c180f477d4f1c53a85a3c2f4d888450ce3bd3af660000000000000000000000000000000000000000000000000000000000000000b08832c8ada8bd9ba25a569edcea6d0b0273a8aa79360f1e19c2d1a818c8ca09ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe65874829a6fca96a658b69cd99e9a6ca9e70e2ea5a3c85673e85a85bc71fae6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002ff857e1fd6562469c8364952c860f1e45b452f421582252bca13798aa371f62853e97ade0634f6e230ff512547d39d8acef1caaf72f24acf577c27424c68925ee0a5ae304c259c27aadd9bc76d24195f749514a131e48c16792d10e8c2a8e485343f3af3562acf496328ab7e97fc4676c110ae7813eb9b70720dd24cd33338a0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4369e24008103d8c9e6c573f0264e51327bda5fd52ee79f9386fa14dc4c224b742ad2539f6c1874c2ef824f3863f2a8f8052c33072d847547bcd0f5e72f332f500000000000000000000000000000000000000000000000000000000000000007a045ba295822f4cf3608dedf74c453dbad7c9617bc8ece1adec3b86c5403c12642807f1f220d8f386d1ab0609e9a99cf8f1d43c97626e5962d2cc1a0b5af4eafb4e59df34d3d625e91de9c6d25c50026a81b8c20f7cf02fc47355ab870c527d1ba446c59d7334926c5d1dbe2f8a1e1913480ff52db2a0bbdfa86f9ec4580f3c99914b59be4c93f5567d5f33492a01cc2b8e4fed7ae5ce0fe2280a98bda1468d1a906c9c42c9bfaa0d1fc5f6cd71c6c6b161419255acddc046e94fcb824ffcc5d0e462527e0dfdf1dfec4afe30cebf6e6d88ff045127ceeaf75e2bc4049d4fce45158bf70b8138e021f56c9cbb83cba475f04a8a436b707cf9aed9b3a37ca431aecb41c179c688a28bc4eb67bf14294077467cd7feb09b627db9cfc2bf1ffa03816beeec1135ad37064f945160b3191972d8052c36f1397e9bf72ad4098dcfca5a4fe73ce09fb577a9d78c681f878a257248613d22d56c913109f02554ec7b5fa924f2dbb97153499dbb253aa235f5bf5053126d36e5138c04d9d0195b1b36fd00000000000000000000000000000000000000000000000000000000000000009700eae923f62337efa128c93ca75ddf6d9923f84eb457d4bd4625ee87aa667300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dfc98418a242151286df9f103cc91b4737daf3474bb060ca60897a5071c5cb13ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0700c3b3d3a3c9ed6f7f9c9b876d19986dec133fe4e23093a3e3ac2321f772c01dbeb5fc721e190f39925e73434c74a8a5fe462047b1e2dfed09c47bb4a116e0000000000000000000000000000000000000000000000000000000000000000531965327d21e27d9d2b918afcab2f3209c8d7dc10cee9e8f37b414c6327057f0000000000000000000000000000000000000000000000000000000000000000a57a09473d1dae69a4cf8423571bb06b901f37253cdaa6e948f92e824fe53774ce748e9f089ba7d5836bd2cb3dd575489d6e593416b7cc9b5925f90571782dfc0000000000000000000000000000000000000000000000000000000000000000795be99b998bb12ec6379cb80d2a5ba5e9fb78303d4d1c6dbe7b097eb266d2a98cf72ef937dfa60258e4433686f6afa93de6212056f4657dbfee7f338fc9277fa6889804ee8b98431d81a65f360f220263348e9c001e9c0a2104450849d5944bed1c9d5b7e3dccdf65674148f2eb44cecbae02a19bddedb6c57fdd48b539e9c8e2e8f6e0f6662045e628a81353e9d0de000a43d6896b152f026b7fc2fc4fef146db315e33d1b3bfaf53bdd19b81a22db5819c2ef1c9bb9cffed167dd590e576415829a408737b4fcf5f6c2ddae5d97ce9f8a129a6a2603b93744fe70a217be14ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff99475c4fafedbb1ecb857f13fffc28b7f316b28c0fc88efc47b1cc4e52b8f0b26e6ee6234bbaa24d441ddcf185f186d6a8adbaee2f84527033438a9a89d859b3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb565c8b6ca6fd3f80259dbc88568e44ffc1f0fdd139e5452c4506a5ab6a46818431d69bae4bbdebefe763d5cfb2404b1ba08fb0428c117caea304db70aee0c6d3b1e5943c2d0fb5b0cd32b50ff77324af6345e448e419c8e2aea7711f11fdb632ee771d395c186394417563da56bec3dca90ba3be085367b0664e7ef134bb2ad9702c541b0c4cc1fb44e45c9d1245c0a21ef808528820ba1b80892058b0c05579a12a9e32c3ad6af2463d5d03488875345078119f402d9e1d4c88e4dcd27513377695598d5238e4177608ead4d851e782c309dfffb316f240d019c5b19569bc16749d5177783ad509f99ee914289e4866ecf7ee28223cb85890dbefdc5bf75a67489ca239183c005d36675edc774692901f6229f73ceb4db07d7299ce374ae51e21e7d6da88b73aa8cc1f232b4adb5f5621c8007d07edf771fcd7dbceee497667bb079e3fc189baabe10c78292d9f9bb6273b63109c3083d411bedb78c3226bd0000000000000000000000000000000000000000000000000000000000000000ce47725597941674b7e8bd1ee969309592499f4f1ee4ac83d38834649a3c6523a932e52a4f963c304d828b42c0de38ed5d4fa7c89a2bddf97b64ad966c7b79dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb342ab9a519cdc07dd77b174acc17830f0ea8dfbab2073f15594f414b05c68e7df9ba1e754cc5c999baaa94b7d26f795d4153a238f2e329ea6da26f92df720c25147814778cb006069dd170d3611147781245cf5c03c564e714f81285a1ce6c4018d9e395df31e06a57c07065d5f8cb987b113ed9be344488c59eed27496792cfac4c01f702a704d993876bf616a89cab8911488be9eaeb3b8556b604297a75001c3c1288e65afaeccf1a83f1ac1b7744393b51fcc27297ab5cbdfff743d34a800000000000000000000000000000000000000000000000000000000000000008041f55c0bdc07af5d6c2c0ec4afd20fd042e64663daa99d6a3352ce0c7bf7cad397a496cfcf53857a5e0b8d861b2a23f67be93be84641615b5d82f4ba00d212690eaa87a6b8641686c102382ec3de9005ba359ee5914fbfac245ce48dd1b7b9e8837718c6763acec811ddaac0f572a99f876f557dbb40c0333903d0bb680659f403b5f131380e8dac882fcfee1480b4efc4e6475db1da71ddeb21f8abce3710be65713c1bf91fb6a50ee126da21bb6248d2897c1517325914ff59c2fb012cbb45f9bdac925ed4392fd350ccfeebcc481c08a911f558310acd7a9408c71ed063a541a121265934e85e47f10f377e07340bc406366247b3fd64fa61d13f5bc928fc32675e9e9148915a547e615c77048610f34a8a2944aca1c93b0e7e340298494ed729477b414a782b459dc5b91ddb3f22e5caf167d2ee39edfaeb7333db0898877ca6ccb4a88afa0e4c80140254b39c7dec208b865d962a7422468658cdacc472afcbed6a9d193e85f96d5273c5bb6c090f57d1a2c71c83d6db99bb64d6620f0000000000000000000000000000000000000000000000000000000000000000d5b6e753cb106da3c716a35df2d8dee3e417541b97f8f62bf1fe16a0a6fd319c9ead626369bd6d5f8484ff3da8a9b5c89c18b2d2d268e456150fb20549334cb8296673afbc702ea89fcf861b76b66b8746885fbf3668e09533eae1ed62fdec1179372bc439fe3e8ff996941583cdd821fa061b44ae3381420f4d5973f6a1c537e30df0147a77e13e708e03b38df52f197e2443ea7f7d686a34a47aa52642dc47ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2ea7b694001f5f3d230108f2e954385b3964629545cf5ffb1c89f944aae7b97f0000000000000000000000000000000000000000000000000000000000000000ea3c55499635864516e47c9569140163ec17b994aed30db17408e09a0f05fe2c7f270490ccecaa24cd2f3a34592ac8eb88835240957395e87c881f69826bcf642a78d7bbb6057f8839d6b39afa757e8d08156e2b63ec70d0ba55a8312a8f1989", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/3da479f176b53c08e1248502a5bc75aed6c71746 b/txscript/data/taproot-ref/3da479f176b53c08e1248502a5bc75aed6c71746 new file mode 100644 index 0000000000..194bd264e6 --- /dev/null +++ b/txscript/data/taproot-ref/3da479f176b53c08e1248502a5bc75aed6c71746 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cab01000000c52c83f28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41902000000b66db99f0378a38d0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f874b030000", "prevouts": ["b33c4b00000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "74f3430000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d4", "final": true, "success": {"scriptSig": "", "witness": ["cc046d3ffc5e59b0b8de740e0d2de28228302d766dedccc174d524acdcc2ed89c895cb81a637b1f4fe04aa7e54cb8c1ee76ef66a352e363340888b71a94fbabe01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["12ecb9562664fc9fe8e7241ab3dcbd019ec2b56bd1e66261b7dd25629447514533420a00ba1cffae854a80eeec73b6f6d25c5e947862ff61b205e20db15e19a9d4", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/3db85c10d9886a1d664d6d3db26ae7961d66a4be b/txscript/data/taproot-ref/3db85c10d9886a1d664d6d3db26ae7961d66a4be new file mode 100644 index 0000000000..dea220436f --- /dev/null +++ b/txscript/data/taproot-ref/3db85c10d9886a1d664d6d3db26ae7961d66a4be @@ -0,0 +1 @@ +{"tx": "5c3eff1d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4f0100000047cb658a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b400000000b06c21f90234212f000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac25020000", "prevouts": ["6abb1f00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970", "fd3b120000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "417d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936625394cd07ac5332e9837d3d183b906354a4c6266a0b69bd6286a70cd041b76b45bbf2815375aaeee056e6b05e441f58ef8c911146e9d15e94b57fcda7a8d0b76831d286b681d36077bb0670e25d1d3b2bbe36e9d696c3276746d4ede397eb7d"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369e909eda73886f3ec8a47c266112c6e5fc7df5ec0f1bcf543e7d218ae8f9d61153f01d9cbc4ce44e53bf46e342c1ac713c14ac9ff1cc3e88a31c5570fba253bd819e00a9246c8c145cff8a91ff4546d478c6c8e3d7b4e3f7e61102a4388494af"]}}, diff --git a/txscript/data/taproot-ref/3dc41a3a65eecfb088cf236466ab9fb737a19b57 b/txscript/data/taproot-ref/3dc41a3a65eecfb088cf236466ab9fb737a19b57 new file mode 100644 index 0000000000..6d3e2513a3 --- /dev/null +++ b/txscript/data/taproot-ref/3dc41a3a65eecfb088cf236466ab9fb737a19b57 @@ -0,0 +1 @@ +{"tx": "23fdaf0a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b660000000016a519fbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3a00000000879540b203c8c28f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df9797223689877e1bf628", "prevouts": ["a61d230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "95886f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a5", "final": true, "success": {"scriptSig": "", "witness": ["5257acb12077e4a0cfdd11bb36bea1087fff8792c76a2bb7358071fdc265f3bb9aa43c86a11475e75689650c685417cc22040689941255f306e9a043e3585a8b82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["e70b535da6eb381f0563046cfc53c3c41e92dda54620396a8308c80a3e02443618e41919c1224794946240f717b0c81f81ccd67d4658e5ff6a05a150bf8a2367a5", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/3dcd87542c1fe27ba922187001739130ac6c6c5c b/txscript/data/taproot-ref/3dcd87542c1fe27ba922187001739130ac6c6c5c new file mode 100644 index 0000000000..f4098da273 --- /dev/null +++ b/txscript/data/taproot-ref/3dcd87542c1fe27ba922187001739130ac6c6c5c @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40001000000879be48fbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9600000000f30fa8d6019bf8a2000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e62e0b28", "prevouts": ["7d1a3c0000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "7f417a00000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "327d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8dc5eed1d7503ecfab0ed4d46e7cc50ff1de729365d43675c7ebcad838ce58c01620e954adb3b90d8c3597d54022d70f5af7b761a66be618c54dd56feea2be872"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93640ff68d439a51ee107fd83731a2288fde4c117a4005465377136bc1a4823e224dc5eed1d7503ecfab0ed4d46e7cc50ff1de729365d43675c7ebcad838ce58c01620e954adb3b90d8c3597d54022d70f5af7b761a66be618c54dd56feea2be872"]}}, diff --git a/txscript/data/taproot-ref/3dd2c473cd54ea601b15cc9840f01e6cec72fbd3 b/txscript/data/taproot-ref/3dd2c473cd54ea601b15cc9840f01e6cec72fbd3 new file mode 100644 index 0000000000..f9fee2ebf8 --- /dev/null +++ b/txscript/data/taproot-ref/3dd2c473cd54ea601b15cc9840f01e6cec72fbd3 @@ -0,0 +1 @@ +{"tx": "32a22d0702dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2500000000efb94c898bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46401000000695cd28101bdee5300000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acab3f1920", "prevouts": ["d04b53000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679", "5d2f4200000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b6808ca78b661bce204a3b17b7f3e8f2aa2063dcccc4cffe698227ae90135b9096aecf1c37a7131f7d59a248f44ceb50bce2e40baf9d4d5e1aeebfecd7c68de1c3935167daf605213b52b271f9e6a53725a69c71e98809d589a82fdf67815380f2724b50b68b4936fb2f7b513f82364d9dd2ccf414deca202e2eef9374045dea4b83545d5f0f8d552e1465fb40c88d4cd8c293fb2145dab48252f4df6a68a0342ca8463c38a1f1604f2a32f235f9fbd94c74b95e11ee52278594a144f8dd90888cd13eb642c3c10d17c6ac9b63886e361011ebd5915c34590f564d77fc3a7c15aca11359fae5b5630d0a75d10fc7715c6dc8773980cc9eb22c905d79cf9d58dd2b1184204353f56a4e46d09f63c64be304dd5693cd9aa08b2609b52ee309f40e65c7c49603b1a5c41273233928c568fa04cf2a35bd8b9fe7de9956e394c4a5b2899a477c8f71ea808155321e54be8eec7d2bb9ca55b9b68942a4a3a79e5f292d3c3a9cf243ab0b5d734ac1d0932ca89ab10c3c71f836f660ed23967efacc8420f9263f7a8dabb7e729d7ff900df6e19e463515b0c89fd48d00593fc1c733040e3bf33d09cbab71b555a8572c90b8b25961fcda27b78b609916445e5d8c0328e6f12679e309c48037ad4add4c871b5375afd3931f8f35e578756078ca47cdb79b78d966d308d23ccadc276bb7badbd4baaefd740dd04639a5bc24e6c73b23001bb64e7ed46dc98bfb9b75", "6f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4adc39ce81a6fea632ecf565fa45d7a7ca50aa2e3b548038c9066d72b539243596a6ef766bda57b4717926485a86d332fc460fd2733e6a54825f17015621dd4290"]}, "failure": {"scriptSig": "", "witness": ["4d090238b87369689df0d41cdac31b08995a5b5ce07b2f2182732f8a5ee13a8c46780a7c85e5c7dd9f03be4c603203eabb84a2ee8e277b2d1b214e1ab9c98ed1805c66ba91dd012c4b8201d2e8ce2a5798f2d88943fe0259141034a54590ee09c88fe1d7bc4dbd9fa306acef3a2cdb0bb049d37f94c42479e25a1ae0312dc68ef252f9eefaef6dc28107237690377498009a80915c5cb21c99330db43ee2d97b8c6d0d301e216db4ddd6a28602dc6e089eaae0ddd58d51cae74b1857d8a3acccf4a582e9db8824b23b412c96b228064952e1533cb9cfc85aa762a16439a9c5e8d8f4ce402316ebe911ab27241842dc750722ceb80260614ea65468508327e49c43cfd9a00569d1bfbbf457beba5e1ca922857ecb06e1d3fce829ee0a17f0759b212f1d747ded1588f92d9c4260cab743db6e3c39a225a552b3d7bb9d38f5d8f0a78f7eea7b3264cfdbe23ae86267349c9ba2d8dadb6422ecaf55f067d68034f0c2ef11a777fc32f817dad4917b435eb31731585dbadd9fff7d3561e197954accd4f7596b6f92e9e4a5331dc36cc554051aaeb4cdb7e0072217b9e87c96aa556ca317b0be58298baf2d898648417d8c5497fa22883b89d7a05d9e6cea31c148abe45ae93cd53cebbb6687826b8537fadef6ea42f09ef179e0b8c5b6aeb115fc6db5fbb590348674e614e791df6c325267d3a3852f04f6c094d916c80e7dc0b15cad867325f5c4830a2a6f1a8175", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ff7b311773aae467fec7730c03ca925f7d90d2d8851bbd9c3c07340c4c785e894cd3bb01e072d01d43d3082324ff6e625f5d569cbe89802b785fdd288bfd31c9a3f8f9fe88f0f431b5ffad473abfcf1c4b340e1c7daa1232bf4c86f035b8cc51"]}}, diff --git a/txscript/data/taproot-ref/3e0593c1054f6598bbf8297623874e58ed4f2f9e b/txscript/data/taproot-ref/3e0593c1054f6598bbf8297623874e58ed4f2f9e new file mode 100644 index 0000000000..1ab86aa7d2 --- /dev/null +++ b/txscript/data/taproot-ref/3e0593c1054f6598bbf8297623874e58ed4f2f9e @@ -0,0 +1 @@ +{"tx": "671d5a89028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46a000000006a1175f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41701000000b71cd6f70163c15100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac85010000", "prevouts": ["96443e00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "82ac3200000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "537d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee1ea8876939edcfa4030d01bff156fecefc420cd1c8fec8a2f14f09f14c187072e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fde150f8c7b4812d3362c6afa34922f3b5cc4b63cc9e98285537a088f4a7fe3bee"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d603694b1746abcdb32c29db50a1413ae8228bd62a4d8e06b3ca802f4bdf7f4d1d38f649aceaf83ba76018e55a1207707882be6904852f7ab0998fc8ad53a321d892d02e0db2d70aca72db86bdb1e35d04291625c81ec0b3d884b10be9f787fb"]}}, diff --git a/txscript/data/taproot-ref/3e1e6aa2f96548cfbcb05311c5d24990bb96a8ef b/txscript/data/taproot-ref/3e1e6aa2f96548cfbcb05311c5d24990bb96a8ef new file mode 100644 index 0000000000..36c671927c --- /dev/null +++ b/txscript/data/taproot-ref/3e1e6aa2f96548cfbcb05311c5d24990bb96a8ef @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff6010000004f498f07dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c860100000008441211dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7700000000fe3bde330149db9a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9fec5531", "prevouts": ["f6da7500000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "dde94700000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "c6d94e000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "9f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e93df6a2e62376e6a3587300ef2d1a395dd90428413a52508272625b5a1a189adb591a16be56540de55d9fbfa115de937b3aca1e4dd0f5a93f17ebd2ebda95183"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936327099b01b253298afa4f7cd9d288beb4aefe51868cce630b6f9dfce458fab5ee7391eb2542a03443f1c351bcd0fdf78b6f5cd40e118bcfcda3d325918034371ee453f7f7ccbda5a0ba96115b963083e4b2e9e93a3abf82e4dae88dd7e6a6b566f3617d560800e971f99646d89bd2028caf0c6d02b6f505a11fcad3ec349c801"]}}, diff --git a/txscript/data/taproot-ref/3e2370ff2103895a7c13f394468b1d7588a525a0 b/txscript/data/taproot-ref/3e2370ff2103895a7c13f394468b1d7588a525a0 new file mode 100644 index 0000000000..b374aa29a3 --- /dev/null +++ b/txscript/data/taproot-ref/3e2370ff2103895a7c13f394468b1d7588a525a0 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffa0000000003a2aaccdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6d000000009d67e03e033aa3a6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75b000000", "prevouts": ["4d2c850000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "6dfe2200000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09026bef139b8b79d9b15d958cbdc1f728486a1718f73e2355a089963e4abef9c0d503b1eeaab8cca325bf1cc68a7cb2c9007b6e3cdf7d90d077d3fdb5dea4014f92c79b5a7809b8bf0f99b1c26cafc5078f267efab1ac6360594a44d476debf7308e42d1fcd5422450c9582cea176c964e3dd81e6efa117624eec6a270289e54b52dc6dbcb1c1871cf31a3b082e5c263e32fe9abf6eb6dcc57b3a03bab8f0d9c10ddb444809c38e9008d328f48fe4a1789cc60ec6c29b11aefcd608361ac35c552d3d916f33e9f4cf10f781192c36d64c7c8a418e532ac353cfe8a4def250752ad04df9ea2656ef4c8cdacdb759c4affa372e05b789d209feec746223df4f9a426315f6cad337e1813a18d09c2554dd0a5ad63a9c523fff216b13d2f500acbfc4ad0de8f33624c87459f7fd881637d005f8d29cbfc6cc173e2db998d71e68f64a9c8c7b89c0f08fd72c86760ed05ccab90116ae3a35ed863898d491f7871a4d38f8db75efd3a04d2270c597ebce0db412c0a3cd3bca56d8f30254acb56bdb6ef26b29f2fcf25b953ffd201f32c68a7f183012522e61cedd35bd8231329b3dec0e1594bb77b39126b0acf16a6f636d9ddfc6fc2c28b3e5702f8cc6a2118acc3eead4eba8cb88cd566ec2e671b9ca1dcd533518eb6176ef3783690962ddeec7fbd68a36f9bc9e98a0787c05b5e506be860c242e07017f3244b62afc92f110fe3d8b3682a25f0a3f6b41736375d6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93605b68b7555431fb9df93ab122414b31e5279de2800baba6f217865faa01584b0c99cdefdc3473a619e12778c4cd588646c716d59e86e999fbd28728a66c3e7c6a7d0a3f3648f0d829df7cabdb8f0af96ecc09ebc190c461c6b5fbdc9f87abaf73acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}, "failure": {"scriptSig": "", "witness": ["4d09027fc358edd531085246ad04f485140848bbb9d22877da445cfc3ad769c9d8ee95e64f53eeca28db66fa027b0591e1c3ca61fe25c696897b3964e955bac48c6ad49a19c71aba49915e98f8e3d906c60e21726f79f81006f14b4852622007fab3ab7ad95d41188a1083ef45b64036be273829094a699ddb4e6d3ab1b90c7d1a91f20673fd72c8c3e1b8f51075efcb46386ffe516586ffe0ee295a40301bf816158d2289f3923f64efdf7a42cb069314c20dae4a200585ce8ff36fdaad7751a7ba1fee7ed082f64002900517df0f74f769fd79b9d0cf27381262cada3d0072c7b42b3580d1b544716ad0b0770e6b91e7aa5103d872efc3c375f5efb59e11dc1893d474d5f8c3ddb0b2982249603425c4f6a3145f12b3de2f2e6d0fed88b1f5c1bfb5d1d17ba34eb6e31ab53b9b06d7d8c6be8da8a181e88ed63ec1b6e0c9b8be43e2b0d5f3ebded902e468e02baca64940cd8a540c713e3fc113f5a7723762d5b534d63716178b90887e65557be9ce5c60d50bb9eb694f139049c6a6598fcc791528bdc63b58ddda9fcf95d8ec03f3b6da6f71238a7298ac7760832d2607be7da01b0a10f3e8fe9ed179e5b2ec31d04248c819ff1e94c2d5900e068dca4bb28d9405d578337cb16703ba3c9ec801fd37f9d2a85c8d199979152f454fcc08d585e96f86e8f2ba82697e954f51b1cb1aa01c801b46f4a2d96faea8b733ace2efa2f842cd69e486688e90a0907561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ca585b58cbea5a7207e2f9700bf95d02dcde0e3417cbd056c4efa914a582a327ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b22a5aef24b6a1c01bacd2a24a37cefc04a347b590d10f3bd98469f969c355217b0dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}}, diff --git a/txscript/data/taproot-ref/3e30536558f547b9ad4f09f367634b969078f719 b/txscript/data/taproot-ref/3e30536558f547b9ad4f09f367634b969078f719 new file mode 100644 index 0000000000..470b674571 --- /dev/null +++ b/txscript/data/taproot-ref/3e30536558f547b9ad4f09f367634b969078f719 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc200000000f7b7a2a260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700e00000000e4710aa80255ee7400000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca0000000", "prevouts": ["07906300000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428", "db0f130000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "577d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936959ca2c498f0f62da8da99e7dd3b27b348a55d74011ce858dd89c431589d8b6e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828cd69c149de1c0fd775c23d200817106db3811e77c5a94d49bd03e58d7bcfa223a8385792857b3824bc259fd95f469eb32c57805e5f383de6590f06749d208e6"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362130eabd9bb65b7301a0825f895bcb2d1ad88ce8047b79faf2c001ef0627842a1c685f9e7861cf217f0c3f090528b45399014026e5720182b0faf436212c9d85a66706abdbe591f97764059d8785051c12d40b9c9543fb83334d204ae23d8b59"]}}, diff --git a/txscript/data/taproot-ref/3ea9b3574203d1cc954fbb5b93f7588b765a4d0f b/txscript/data/taproot-ref/3ea9b3574203d1cc954fbb5b93f7588b765a4d0f new file mode 100644 index 0000000000..f0543fbfdf --- /dev/null +++ b/txscript/data/taproot-ref/3ea9b3574203d1cc954fbb5b93f7588b765a4d0f @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ec000000003f55e4d0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4d01000000793d45fa02b27535000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a15b323f", "prevouts": ["522912000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "43a8250000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "907d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8693163a47c3dba2861e33fa837573abaf06e3047dcd3f7c322d2576c3cfe3d489f4b63c6df7ef43e2db8ec562e1d1dc49232dee39216a09a14bc3b6a66d1e38f07d6dd053b835b300872a79bbaa392d17bbe19548a92a63c5948e9fc7e63dbc8"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08251b810e60c043042e0bb2eafa8cecc8c22fa830d489bdf7de51e14fd273b03e0ba4f11ff80ca9181e3d85997fa959accb8f97af45a52bfd0df916797673441f5"]}}, diff --git a/txscript/data/taproot-ref/3eabc6ab34a7c9a974850c1dd22c428aa05b1b1a b/txscript/data/taproot-ref/3eabc6ab34a7c9a974850c1dd22c428aa05b1b1a new file mode 100644 index 0000000000..bdfbd4b9da --- /dev/null +++ b/txscript/data/taproot-ref/3eabc6ab34a7c9a974850c1dd22c428aa05b1b1a @@ -0,0 +1 @@ +{"tx": "c500bd8803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6b010000005ed744c48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49501000000484908fc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43b01000000f2652ed601e58f2a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7f5010000", "prevouts": ["d29a240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d2823f0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "17283b0000000000225120f103da370e61120ffbfed9be73547691440e55c4664603c27eb9ef615a7ccbdc"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93677e41dab50557b5b20871f2553a2bc1c7b9ddf7d5b647a2744f571de9caa26f1"]}, "failure": {"scriptSig": "", "witness": ["6a57616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/3eb9a6cfe1aa2c1c02424702999504c5b096248f b/txscript/data/taproot-ref/3eb9a6cfe1aa2c1c02424702999504c5b096248f new file mode 100644 index 0000000000..b71c1b1198 --- /dev/null +++ b/txscript/data/taproot-ref/3eb9a6cfe1aa2c1c02424702999504c5b096248f @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127016010000005a40fda98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cb010000005cc4a369dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cab000000003c7930a40216509d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac25272e3f", "prevouts": ["2ae70e00000000002251204929a185ed20b7f7e86ae8920b068b5e7d5df0975bee6bbfbcd97b6bb81e709d", "b3c23b0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65", "8b34540000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cf152d63f1051f9385c5addf6d53db16062c84e9870929489e0718e5f0e91bd5"]}, "failure": {"scriptSig": "", "witness": ["6a01616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/3ebde48f5439e084e28144fd489296408e0dac44 b/txscript/data/taproot-ref/3ebde48f5439e084e28144fd489296408e0dac44 new file mode 100644 index 0000000000..a3628f3d92 --- /dev/null +++ b/txscript/data/taproot-ref/3ebde48f5439e084e28144fd489296408e0dac44 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c493000000004619122f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705600000000f0a051aedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdb000000009966758c01ba080700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac63030000", "prevouts": ["901e38000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "2cff0f00000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f", "676a26000000000017a9144c4b1fc943f04d775886b4f6d3c3c73bf7d3118c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6abc", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dae56aa441f4258abe9bcb76736e618cba7a98e5acbee529967b1ef4b09363f599aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d5154a115ce154f943bf3cf8f46c74cde664956f57cd29b00bedec3f53c1a73157ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd8f5962b372cb4e7f2fb078cf6d27c268bbba1ff2abc83942f0aa063fc70b686a0ed0b6cdb130b03f26b8a245e72d5247ee3941518d7e9956496f6ce27b97d7150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}}, diff --git a/txscript/data/taproot-ref/3ef5bed9863d50fbfa4dee5c776d36177e888adb b/txscript/data/taproot-ref/3ef5bed9863d50fbfa4dee5c776d36177e888adb new file mode 100644 index 0000000000..759cfffc22 --- /dev/null +++ b/txscript/data/taproot-ref/3ef5bed9863d50fbfa4dee5c776d36177e888adb @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc001000000cc3e5864bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf850100000023fe971b01f0091c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6c780bb21", "prevouts": ["5d6e220000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156", "f656660000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e14c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366ed0e779cc15e2a03d2e3d97c8cf6c7506658d81da92e90af03d7b12593133764b04f8f54a0a76ae0e4c7aeaaef28ce29fe1b2cd8b193a4d28e758ec231d2b883bd198ccbfa9c702c0592bb8c84a948c36ef9eddfd1aec8278a333dab45811656e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365bd9e6af64badc3bab736f59ea7db24f388eb048beb664b97cc6c7235b822e2c1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045f693e8696ee404d8be98a67cec2febef1e0f75b013501a27963a3fb4300a4da26e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}}, diff --git a/txscript/data/taproot-ref/3efcb90f4a83944731d1cbf69fcde8147549f8ff b/txscript/data/taproot-ref/3efcb90f4a83944731d1cbf69fcde8147549f8ff new file mode 100644 index 0000000000..04972702d8 --- /dev/null +++ b/txscript/data/taproot-ref/3efcb90f4a83944731d1cbf69fcde8147549f8ff @@ -0,0 +1 @@ +{"tx": "fca5d31203bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb801000000d35e6ddfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4001000000e5f842af8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49500000000cbb138bd029ea525010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b6000000", "prevouts": ["208c780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "859d6f00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "eaec3f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100817ec35acda74ca63193961fbfe82d53b1e97ee57ddcedd61b88c3e49cd38570022025b39d8bee72e545be9bdaa5255eccc67036b5aa1f5c0417168f798dd7e15e3e012102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "4830450221008202765397f684b91dbc2d69586666f6c5f1f0012eb1dcc5235401e6bc3818a302201970e0bdfcc3817f49d88aeb11c4317a096229ed3911f7d9d1eb55fe179e99de012102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/3f08853267dab46c6370068cbb68b228923ff0b3 b/txscript/data/taproot-ref/3f08853267dab46c6370068cbb68b228923ff0b3 new file mode 100644 index 0000000000..966f7327fc --- /dev/null +++ b/txscript/data/taproot-ref/3f08853267dab46c6370068cbb68b228923ff0b3 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c601000000236a23f860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127010020000006b91e6da01a7a13100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3e000000", "prevouts": ["83e233000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787", "2cb5100000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["304402200218967cc003c22e4af7b2444fe390eaf3c6457bb906b8a209a59be641896c3702205b4b4ab9d6b72bc0b58a7a3fccd57cba4bf5597292f8e85dd97285406b239b3681", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3044022015ee4b743fb8a158aad5b103be8d9913d0514f9bdfed33d482ba580d2b60a2ad022059a6dcff80e0a020e01b2dd65b7b2b5871d1f4648b20673721cc9956c8a4edef81", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/3f1549e9384322e64380cd38621193a46900a116 b/txscript/data/taproot-ref/3f1549e9384322e64380cd38621193a46900a116 new file mode 100644 index 0000000000..33c2bfaff3 --- /dev/null +++ b/txscript/data/taproot-ref/3f1549e9384322e64380cd38621193a46900a116 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfe010000000fe2765760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ea00000000cfd16a8c01ff36080000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796ba030000", "prevouts": ["92fd270000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "b4031300000000002251206c786b308a9c6a675d6ba645c0b3fdb6ef76f1ce96e6f31b784e53054a24ec87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "a47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630a51e3ee68449166d2da506d8de0f0b7ef39424ebe5f034d615a238e9b2a225f873bed7b94a92ccdf1432eab063a27f935bef099df6a1cbcf6734b218f2b6aa9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100eec4f69e5cd9a0f0c1fda8eb2f54297e33bc5edab35b299e65e2653a923d6ca55"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8df22966d6a6c55ca54713f7180fb521ad1601010bda1f1af87739ba1b0e44e80ea84c8431ee0615517346b97932410ca977012a316263f78a9edf0a452e478a09da521cfc521edd35405d6ff7b10120e980b699014de05f8e600b437ffa9c347"]}}, diff --git a/txscript/data/taproot-ref/3f1d506b154892f06d439bb90ba5202e723507eb b/txscript/data/taproot-ref/3f1d506b154892f06d439bb90ba5202e723507eb new file mode 100644 index 0000000000..4998b86d0d --- /dev/null +++ b/txscript/data/taproot-ref/3f1d506b154892f06d439bb90ba5202e723507eb @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c130200000021444841dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3a0100000069712e0e01f62b6b000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787a59c0849", "prevouts": ["bf775c00000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f", "e8922000000000002260202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "187d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93606a629bc116268be1a17da3f53dc5135cb0ba720860d61650af2ab2ef2f0d65c919a726f5226a1e5e752df6df7fd59ca609863b1a6d095747bbc103e423fb93280858ffdbef3a81ff8eaeb69bf692b0617d2bdcb9145576d5843e6d9e5e1cb0c"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364394e80ff16ebdd0b8084d2a2ac0d9fd937ef7443fa96a9eeb67a82d8ebac460b6019e279bd309d4b7ea698da82947cdf92f55834d49ec05c8520ba423c90b8e919a726f5226a1e5e752df6df7fd59ca609863b1a6d095747bbc103e423fb93280858ffdbef3a81ff8eaeb69bf692b0617d2bdcb9145576d5843e6d9e5e1cb0c"]}}, diff --git a/txscript/data/taproot-ref/3f512330103073dbd4f58e82fee2f316a4b0c171 b/txscript/data/taproot-ref/3f512330103073dbd4f58e82fee2f316a4b0c171 new file mode 100644 index 0000000000..cdcfa60652 --- /dev/null +++ b/txscript/data/taproot-ref/3f512330103073dbd4f58e82fee2f316a4b0c171 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4f01000000b02ea1ac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e30100000099b12a1b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703401000000cc4e3d950314417100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc757020000", "prevouts": ["0fb65300000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "2ac5100000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "03740f0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f98b4fa7d70ccacaf149110d37e14afa465a4cce5ea58b45c718aa129bf119442eae45bdbc332bf5a978667243b49c9b979fe92ee1d9ed3823912cc17c63e45aa06b7dbf505033281bc2802f60ea73c6b6bc1ec4f50a830b90bf520018ab39223a7745587804ad8af30810436e9dbff8c3bc66323fb3ea116bdb1b433155b8cfafc20e31cb64906476b2a49674dcc56dc839ba3ad707cca79aadbf462217ddc44c41ac963fb5f1bdb0606d2b6ed11195b99988395877046c99550680e0a941e5e450695eb554e43952678f73e19842e91c51732f2d32592245befb41a7a633df89e310fc546102273713727bc77812093d115b4bd3c7cf5ed4c5f32271b3ea9048d6897ff72cc6d2aba20069ee681b7d46efa95eb60872f3b25eb768042251766e9498d9ffec2ef72ca2be3485cef961547f4ed4f3e82a48dd8f9539ab7efd9dd442e303fafe3bc0f871260ccf1b86851b9d36408f254a47713818c8bd1276285efa3bd8c6702c2a71d0f23cf1a40253feb86e037fc80c875b7b85d2d40808f04dd8e71a76cf127a75a898378bf3c29b120dc4cfaffc8ac9943ad1a7da34523adc8e2d4f3fe5888ece2e6cd48deadd6d46b4dd99f11e7cd0bc9ae3f5f1e0f89302c3408f24d23d8baad092e0ccd4837752a31a3a924d62fd3e2af9c5e12a1f7ae611a0f59670322afe19b2786e4010a9f0a2c29302b14e006f4d1ced3d16a49ef31b30e97ab16fb25875", "ab7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366fa2c694f390b743554f08be0c7f2328ba8b079239bffe76afe54da1858b8f590144ecbe7fb1e6c18f5b14cfe26e6e35ca66fe7cdb676ad740673ee849f6d44e7c07bb1aa10d02d314eb70c923196d0e49e71087637e2d5a1d7fe44c2440c398"]}, "failure": {"scriptSig": "", "witness": ["4d0902c3c94536c8f4da8e5efc8cc87881a5bebb7ed90a9f2d9c743344c030e370532771538f4e57e2d07a516488e39af25bb3da3817bfe5ba4e2f14338112ff799177b19c6f4d69232d1f310a3af5ddf4ff5206eadaeb6fcce8b84fefae069efe5af5703a7409d69a44056ed0e7b8e986e6e40cd1f77c415ad7cd7c37117d0ca07a392435a4a204222a4dba5929e800d317d04272d16ed139a337879c2294e886132c361082ea278181be93b8fc048cba67e2d295a51a26790b207b3a73aa3b1bc9dda9fa49aa3d0b131080f38342311c3f5480d3a361bd37f10e82453ea2875e79426d3780cced736ba8f9a09a951fe7e1b83df0f10e19a297456677c3ecb1d5c861b324d9ba2ae9b2c912b0c589ddb26ace771915921eec798420b874594b9ed9885dd63ffa3ec327b4263cac5fec7ed49c66a747efddc70fb09d3116f942f71cacda11a41a50c61d51ef97cb49d214d7de0940482bb090bdae946ecf56783b0693f953cc7ddcb9d716a89823e48c5d53256811c81a6749e79a3605bba2e9a47e0e41be9cfef7d3fa0de904e1964ee823cfba8b1092030ea6cdc12c0f3e26d85ae27ac8fe24c0d175bf4961faa95bd4395675727fc84629284866fd7e266446908522d69d97b7e425df6f99eb6334ae5f76a3a8d9d32f7d2d0ca62238376341edfecbe37c2eca14c74c404974bf387632efec9f1f0fba009055e8a5ddc3e811eef63506d274592bb2f4ae75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6ef3dd0bfdeb3f64daf38e1101738c14790d5f1c68393c583b55b6fea5718d19818cb303569f28fbe8acbcc2d27d183e3a68170f5392df28f40a03efea695d856e"]}}, diff --git a/txscript/data/taproot-ref/3f513698f389965cd3f800cde5d06d6742166c96 b/txscript/data/taproot-ref/3f513698f389965cd3f800cde5d06d6742166c96 new file mode 100644 index 0000000000..9d168e517c --- /dev/null +++ b/txscript/data/taproot-ref/3f513698f389965cd3f800cde5d06d6742166c96 @@ -0,0 +1 @@ +{"tx": "2c3a87c40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ab010000002b52538260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707e00000000bdae3c9301fb521000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72c010000", "prevouts": ["b42f100000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "cc000f0000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f34c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364b47e9b9572a2fdbea0003eeba5c6c5df8476b78e561177a43bb360ce14ca93ec9fc6c767d5aa72b6a61d813f4dedd67fc97d91e71acf86e276ab6f41d1da0fa8c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ff3c01f4eb155968cc3221659e149da2e0b6684938cae443a11b820562bc19a4e05de1aec4dcfd94364dc697d2506f2d3dcb95f0b1cd2734b3ed6d289f30b19a3cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}}, diff --git a/txscript/data/taproot-ref/3f6985d5b0c8658ee84900aef20ad6b450f6f3e9 b/txscript/data/taproot-ref/3f6985d5b0c8658ee84900aef20ad6b450f6f3e9 new file mode 100644 index 0000000000..f5ea419704 --- /dev/null +++ b/txscript/data/taproot-ref/3f6985d5b0c8658ee84900aef20ad6b450f6f3e9 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707800000000d472c2ff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47e00000000b22608f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbb000000007c5fb0ca0254669200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8e01af3b", "prevouts": ["ab600e0000000000225120a2c28b736583e5896e4a53bfde129100bff930ada42454ee2f7bef5a60a371d8", "deef37000000000017a914c7d65cb5025eac8b5bf295baac9287994ab34b9b87", "28374e00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93696c243d178212e8777fbc993402db4381baa5ece36ceffefb611138a29c3f415"]}, "failure": {"scriptSig": "", "witness": ["6ab9616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/3f6a1b44037f9a0ecf95cd3d23ce8bde0b02ff8e b/txscript/data/taproot-ref/3f6a1b44037f9a0ecf95cd3d23ce8bde0b02ff8e new file mode 100644 index 0000000000..b5ca9dc471 --- /dev/null +++ b/txscript/data/taproot-ref/3f6a1b44037f9a0ecf95cd3d23ce8bde0b02ff8e @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca801000000af0593dadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1e000000003ce8e7810303907300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b3a96d28", "prevouts": ["2743510000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "27ec2400000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "", "witness": ["3045022100a6d030e6236df5287e6444afbc3138d4def56ce2acbb80c3a7930eda90da5bf0022054202da46b6bf32176850e1a63cd3aa7ceee558ff527fb963fa1bf405e240f8983", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["30440220422fabd2f6b6feff4c2386182e09add737f0f5870e761c08d4dcdc3ef78c38ef02202f180c439dd9b7c92a996dc1a0f19ba231e1bb84372db366d9ac04ec7daabff783", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/3f6da0ebdeff4ba77b33c2c2d3b962e7dc353570 b/txscript/data/taproot-ref/3f6da0ebdeff4ba77b33c2c2d3b962e7dc353570 new file mode 100644 index 0000000000..87eb0841f9 --- /dev/null +++ b/txscript/data/taproot-ref/3f6da0ebdeff4ba77b33c2c2d3b962e7dc353570 @@ -0,0 +1 @@ +{"tx": "f43d36db02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1700000000fe6134a060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270be010000003e5d2c98033b5d8b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac2b000000", "prevouts": ["170b7f00000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989", "32960e00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "47304402201b1b051e73431f017ee5f51654862cc3e77a553eb2632799f978414d05093b0e0220051a3de18d2bf627cd036e6489216ae87038231777b1f90cd3756bc15f259b918300", "witness": []}, "failure": {"scriptSig": "47304402203638dadfbc3ffec5bbc6c80b9eede4b8e941cec5b12f91faa3aa5bfc6cdfbc1502200f50849d3234ac799332b6f6c6fd30725a31746076feb16d59a5b8bce7a95a47830101", "witness": []}}, diff --git a/txscript/data/taproot-ref/3f7737e152b00480f6b1e13136938142db63c3bb b/txscript/data/taproot-ref/3f7737e152b00480f6b1e13136938142db63c3bb new file mode 100644 index 0000000000..e4cf9270ab --- /dev/null +++ b/txscript/data/taproot-ref/3f7737e152b00480f6b1e13136938142db63c3bb @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270170200000079ce70c5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf31000000004c1ea1b001a9b353000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748760020000", "prevouts": ["7ff80e0000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "541766000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09020da30906dc4223c30c356b2e1a26c196af1d396fd7f5ebf060b38fde6f589fe587db80d1f7df68dda19e57c8fe86c4ae7defdfdae761407a694e4eb28a17be01de68a7c1e36dfc1fac4670abed59fef0ad6dad16cfc9918a428398fd591c027e08daa77779fa82ac171630b23fe1f5fb25b52fcbce65ff3b2b2587958c31fa4b387e1193adfeeabf919e081d91104acefa870421240fe460f763962d61d30ece56c3a01ce5ad7de454a166229d011f3550cb0f30e9d3847b5d190b147274603bbdb78cd0fa81f3d9834734eaefe30c6570790c6081839ea1401c4057648ba81b2d8b53fd3c79867422f854d803ca2f357a8a0f75424e7814d445d63d6e4d622e5210f0052e70d2800e2f8e5b2fbdffe8b324ddb15833ed9cf2c27914e3d9706208e25faf90c078e5cf9233393ba92b92be10e63dfbaaf45dc5876b53c1c9778cf7b44783d736667fd219fa87fa6372da3afac3bf18596f01d8745fa34fd0a6eb5c1a758802845e391573c6f76891ba2cf433e0bc2aa2578d4e8d5af5cc538621dd2c08b2c224de89cab8aa12f2b832c8bc92a63d91aca8cbfaead4331ae09286c83e6fc0ef357ec64edf280f39db9cfb9421f4848373717957a01fea3e57b26f13fe300ff07df9cb7dfa4ba786c3f03b35af174b3a8fc9e76e5445af96a02a35b322692b06010a1b70a40a0c953c1cb442fb589645c4d74554c742cc18bcbfb0a16beb29f1be429ae675d9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f2e968ff58e95ba8bfb88f713127f2c0a83030ac0ad8720c76044b40e2e6afdce051b2f792b2f00393c750e2f5c1724429883d9e1fb30c50e31a79f17241e62331a3099151dd9022c8ab6721206c57c00ed937e9f62099522c543aef8c2ea8dec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}, "failure": {"scriptSig": "", "witness": ["4d090268aa11dd125163f48e7c3bc11c91e0bd82a3a578c8bcfd9f5b6cc5257c749c59b1d4cb1e4aeb7b01ecda1692fbb464e18a29b2147c9b2d21b6c71c5249e286ed856e078000325efd1bc6b68d2d171d4d200e79b776ae802d55bc20a99acac99171b584bd56eefce23864306dcc7029f2f8666e8b98ff7a4135d8aa6bd5be32b7491bfd15149a818c90ce3452f2caf1a665902d9651b56d33ce3a7f60fd28a2f474348a9fafd3b2a96109cde6441c11dc2a9e33211a62a122174d40aea7390ffab5a03623ec681c6adb5bb0121c558e3c4484384fa58703844e42ae81981bbc1b142e5809b7021e6a1233e4733ba72f89c38cff6db5c321c6e4b773845d8eb31192a0fbc554c89b6a3b3d5ff22ea9c10d01099cefc100d7dfe1d146c16d99a69a4830b2ee11e561490fc6c8b85c31d8c05b3b97d86e9555a4d2325ac8fed45e2b80ddfa03bd10cc44f584e85043ac2070a88f27d5cd36d0cfcbe46c9509e55d1ec7068c26b2171000f22aeb3dfe10e2e8eaa063b27cc940afe0d8412a9feebeb0cb16f56e76dda69dc0fdc50976b0e9094f55a6c8b83d238ea44a457f43b06c5777867df76e7b67c79e1f1ae3b4c82efbcbf5f42105af61942b789b968c2116b62bc049575b1b05e3d9b0f44eda5c601d6a498eb154235615b9c31084c2f5517c42d12a13d88a60d9d4d4c5ff0b4ca726aa894326cbc315c7926f7973aecdbd0cd3e3ead0c86b8a46447561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365bd9a855ff120153a9708859ceaae16898e3111e3492b3f2130b56cfe36cb4d3e051b2f792b2f00393c750e2f5c1724429883d9e1fb30c50e31a79f17241e62331a3099151dd9022c8ab6721206c57c00ed937e9f62099522c543aef8c2ea8dec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}}, diff --git a/txscript/data/taproot-ref/3f7dd25efaad7cb28967f110fe74e5e38a763ca8 b/txscript/data/taproot-ref/3f7dd25efaad7cb28967f110fe74e5e38a763ca8 new file mode 100644 index 0000000000..be11bc8813 --- /dev/null +++ b/txscript/data/taproot-ref/3f7dd25efaad7cb28967f110fe74e5e38a763ca8 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46d00000000e4e24797bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd0010000006cf86596dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbe0000000039bf39d9014d7b6700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5e010000", "prevouts": ["b9ba3900000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "cd767b00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "7a8f2100000000002357212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["894c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d26d1004a8019ef2e1188b07306b9375b4b58b003610908a9f3451755ce03441ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454b1cf341ebb9351320fe3e143ffa2dad1c15696d7ac983fbe7e302fe7a073e7ecf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51d8b8b59ec9330d10cfd242c1699350bed4f76e625017108107d5490f0b0ac19bcb3e0a345cce78c1fe891e9b22b966ce84a8b12623d949f63d5e15e148dd67959d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}}, diff --git a/txscript/data/taproot-ref/3f827b95772a69cca7924e0a2e6ed2cef8755536 b/txscript/data/taproot-ref/3f827b95772a69cca7924e0a2e6ed2cef8755536 new file mode 100644 index 0000000000..e04b1f74a1 --- /dev/null +++ b/txscript/data/taproot-ref/3f827b95772a69cca7924e0a2e6ed2cef8755536 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be50100000063a870e860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705a01000000ecf01f0a0126bd150000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c32f391f", "prevouts": ["821b2600000000002355212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "050211000000000017a914a4e57198280c195671631f8b9014214c2f083b3c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["8f1ded8b1cd3477bc520967937fd94eb82f6b542ee85528386023e89fb107d527ab78a30ef63c3319ebabb576fd3449b575a4676437710f9914ebc505dc74930", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/3f86932b9bd5a8f673b4dd4243ebb78bef50c888 b/txscript/data/taproot-ref/3f86932b9bd5a8f673b4dd4243ebb78bef50c888 new file mode 100644 index 0000000000..bb7b44a992 --- /dev/null +++ b/txscript/data/taproot-ref/3f86932b9bd5a8f673b4dd4243ebb78bef50c888 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f200000000d11a06a1038d133200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374871d010000", "prevouts": ["a7d134000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063fd68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fdd74ee01a272cd292d2b3c7cac8438ee48f053af121a9be8314077ca1dd604920e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1e0a7be32fdcca7a506e9ce249f658cc089bc7a3d23614d55e872a83e7956fea4416efa3a61de7db58e4e5b27e55eab88df01883130071a88e8c07ccbf4e37c61"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51cf0ef20a11005175256561cf2f67252fad6f828fd45e261da47aa072728c1e1d416efa3a61de7db58e4e5b27e55eab88df01883130071a88e8c07ccbf4e37c61"]}}, diff --git a/txscript/data/taproot-ref/3f8e06a01cdada6071275fb451a2ba624eecf6b8 b/txscript/data/taproot-ref/3f8e06a01cdada6071275fb451a2ba624eecf6b8 new file mode 100644 index 0000000000..20023d86da --- /dev/null +++ b/txscript/data/taproot-ref/3f8e06a01cdada6071275fb451a2ba624eecf6b8 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf59010000001611e3da8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4100200000040147ee90150805700000000001976a914c629d61df58baceae110d15eb5b55e144268615388acc4030000", "prevouts": ["854e6f0000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "53a039000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4bb0b9e3baaec320f7de46eda77f4fdd2cda08039a1867e75a703bfdee0f4ff6d1cafc3da456d473afb79353f7068dc1822b24dbf9d7eaef6a0c8c9b611b05e979feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b6ddcef20c10c61d9e21e2293389fb4d83401974c63955ae345dea7dfe41530ea78a04935edfb84e1b4b71380d58e01ed379cbb21cec8f8440ec0fbfce597ab8cd941a6bc152cbea0496b075d4b2611b435301778200e60e8b4147cd93749673"]}}, diff --git a/txscript/data/taproot-ref/3f9e6c510733a54871b5b12db956530901898fe5 b/txscript/data/taproot-ref/3f9e6c510733a54871b5b12db956530901898fe5 new file mode 100644 index 0000000000..dae878e0dd --- /dev/null +++ b/txscript/data/taproot-ref/3f9e6c510733a54871b5b12db956530901898fe5 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702601000000580e63a5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5101000000d93ed2df03842435000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac1f000000", "prevouts": ["d487110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "eaea250000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "477d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8af5253a3ae898682e613588786a672ae77746787ad628dd74364be19bb5242936657009e9173c5ef8826379cea4b8c999e3ae37a5805e4cc6da117a3d2ee0eec"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93624f7d08525b5d52815de985e807035e6f0110330bf2d62b1ce3b9c92499c7c7ca24674935b347637fb115fbceef28e6d08e5e47afc6eaa336546ee2e891e964bfd9e929a06047270fff43ba4c6b47136464c62381aba7ed74ab98bc69d199aa4"]}}, diff --git a/txscript/data/taproot-ref/3faa53c6eda1becad9cec3442b7069bc2083f057 b/txscript/data/taproot-ref/3faa53c6eda1becad9cec3442b7069bc2083f057 new file mode 100644 index 0000000000..a3e9573439 --- /dev/null +++ b/txscript/data/taproot-ref/3faa53c6eda1becad9cec3442b7069bc2083f057 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2c010000006700468d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701b02000000de835db602815d6100000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6f3010000", "prevouts": ["61ec530000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "4ef50f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c0", "final": true, "success": {"scriptSig": "", "witness": ["c6c72c36e1b7b923a19dd384dae60627dfcdae430b0916158757f7c29ec316c5885a62a834d4db79520422d1ac58f56d8e747f3b96d9fe570f63081dfe6c6a4903", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1d214d6efc01024016deff46b5272504c03a8c3c1fe6c5320f7c4f805d13562ce163e560a75928452e9e532913d0dbdd8c2aeb3892889ece2ba25fdc97da0ae4c0", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/3fed18356adbd733c605b538f4fbe6434ecad6df b/txscript/data/taproot-ref/3fed18356adbd733c605b538f4fbe6434ecad6df new file mode 100644 index 0000000000..d084673be7 --- /dev/null +++ b/txscript/data/taproot-ref/3fed18356adbd733c605b538f4fbe6434ecad6df @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e900000000852477de60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704301000000434e8635dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bab01000000ef552e5e0380634000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875e020000", "prevouts": ["f4eb1000000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8", "4b251000000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "e5f4200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "437d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f74173222da8f55f8c3eb790aea6942ff700236cf5dc88f69953ed52b194a9a0d9a73345c989c90f21221bc9fa2fdbe5d62b34ad323157a62317cd84046f2af72db79fc77699d349d3583c063c1ca5cb78d93faef419ab336fa45db1a25ff641"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936532662ef0d829b3b02e134f996fb7ab3a2665cf7ae2b3d0e4b000d9e17d468433f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824274b5900613cb2e14ccbb49f92be42e903262ce34f92c4d0a103e0ecbbdfe862db79fc77699d349d3583c063c1ca5cb78d93faef419ab336fa45db1a25ff641"]}}, diff --git a/txscript/data/taproot-ref/4017ac5f35612181926802d0cfd9e7f6a5aed8a7 b/txscript/data/taproot-ref/4017ac5f35612181926802d0cfd9e7f6a5aed8a7 new file mode 100644 index 0000000000..fbf4ce8806 --- /dev/null +++ b/txscript/data/taproot-ref/4017ac5f35612181926802d0cfd9e7f6a5aed8a7 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf300000000050a1b45adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2002000000d5142d75026c9a980000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac27030000", "prevouts": ["3ca17900000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "03c62100000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["7f4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b6d9476ecc09d849d3c16682d4a6fd2c22d5514554f5544b52408747bbaff174e17cc42fca95eeef15c2a149426edd48c8eb93e73982ab4fa8378007bf5ef888ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824a1c4274957806206aadadfd15cabecf517c42c49a66a44e84081097b7475aac480120d5a477c096fbef97d1ee2aeb957fc425ff8aedf322b93097b3a97db744cf5fd42f9969f7f2472ed1fa62ffa49909a09466cf06ef7c57cb1be351156c54"]}}, diff --git a/txscript/data/taproot-ref/40198d56b45470dd3064ec201e05ca4e3cdca930 b/txscript/data/taproot-ref/40198d56b45470dd3064ec201e05ca4e3cdca930 new file mode 100644 index 0000000000..fc7ceb79bd --- /dev/null +++ b/txscript/data/taproot-ref/40198d56b45470dd3064ec201e05ca4e3cdca930 @@ -0,0 +1 @@ +{"tx": "db1a6b1b02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc300000000730c61b260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127017000000003c7d6ccc044728720000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac09020000", "prevouts": ["5f59630000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "986311000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e148d44b3b8b580a9f727722e46acefe6d67c1e6b80ead7c236fb066c3dd6b0bfbdede6356752267b6a4958657c43b99b93cfd40f762fcdaad4937ef48d6413f31b5843f54915b2c97abdf26ed2d562b36c2375ce95d63af6aa508e6368a687449"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a576d03eca93f143feb7e152136a467cbd42f46620dff7de4663782cb270610348d44b3b8b580a9f727722e46acefe6d67c1e6b80ead7c236fb066c3dd6b0bfbdede6356752267b6a4958657c43b99b93cfd40f762fcdaad4937ef48d6413f31b5843f54915b2c97abdf26ed2d562b36c2375ce95d63af6aa508e6368a687449"]}}, diff --git a/txscript/data/taproot-ref/405cc03a69b95e49ca66bdd71055159a13f437eb b/txscript/data/taproot-ref/405cc03a69b95e49ca66bdd71055159a13f437eb new file mode 100644 index 0000000000..e1452dafba --- /dev/null +++ b/txscript/data/taproot-ref/405cc03a69b95e49ca66bdd71055159a13f437eb @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3101000000baf8229cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8700000000f34c48e804c866e000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6bd667b36", "prevouts": ["9873650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ffb47d00000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_bf", "final": true, "success": {"scriptSig": "", "witness": ["d10005f5b799760d6db41be0413cfafa254653405363deb3b3a14f8189a21ef604ee04cee3d85eb8c78772aa62bec509e3843b5b2b165f2688903e173de565b382"]}, "failure": {"scriptSig": "", "witness": ["ea71e794c0856062d55971af785ba96a89374e7fcf007bacd1d0ba6298e94f17e25fa3c93eba4ec23be2d8c9813808de14046230563f43d64726eee6055c49e0bf"]}}, diff --git a/txscript/data/taproot-ref/405ecda072acc56c38f0eae072ad858ec1097d36 b/txscript/data/taproot-ref/405ecda072acc56c38f0eae072ad858ec1097d36 new file mode 100644 index 0000000000..72dd93ba74 --- /dev/null +++ b/txscript/data/taproot-ref/405ecda072acc56c38f0eae072ad858ec1097d36 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1800000000666e3e46dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf200000000f1d81ac101a24f220000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7fa698e43", "prevouts": ["befa55000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "f7b3550000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "8f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c1a7bd15ecdb2694ff0f0300be9147ec1d2e75e3b8043d2543f57834df42dd6da79f40e3d51694d686dc3a1ae4413ff10533c43d32121e1e1cac9518583e4de2dd5f972b05e2f18c3e7c797b604beeb8879a3af7f1e10968a0ac8aaf9d489fe7"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936df7ba38e6eab303ff43446256dc29f9eb9d122fbc3cb1286684b6b478f0d16a61f261744aaaab7b61bfd8b873ce05c274059b1d1cb072d2d2c67e8900f407405dd5f972b05e2f18c3e7c797b604beeb8879a3af7f1e10968a0ac8aaf9d489fe7"]}}, diff --git a/txscript/data/taproot-ref/40637530cf642a13aaddd88b9e805ab9eed711f1 b/txscript/data/taproot-ref/40637530cf642a13aaddd88b9e805ab9eed711f1 new file mode 100644 index 0000000000..9acff81639 --- /dev/null +++ b/txscript/data/taproot-ref/40637530cf642a13aaddd88b9e805ab9eed711f1 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4100000000ade270268bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e300000000586a0d6902a64ca4000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c5010000", "prevouts": ["d61a740000000000225120e5be1c56293dbf2401662c2d3a0e5c3ad348f091e23d387b2bf628c220dc03c1", "b02c32000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["304402207a350c25d0826856f93150b389d40f87965b91b00344eaf7eb19aab90f15a5ce022008560bc36a0fbbd7668f9a0803968c795c4340bd971436e82e7840676c3d6fbc83", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["3045022100f48533e761e43d0e20046043f1bb776bd6dbbbef4cbd83a29940511d1b6a83ea02203abc4cf86259af1158580eee83eb73412b4ff2880a7f198acccb39ca67163e3a83", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/40815dacf70ec14f7b8a062c9faaf258058731fe b/txscript/data/taproot-ref/40815dacf70ec14f7b8a062c9faaf258058731fe new file mode 100644 index 0000000000..aac3f4487e --- /dev/null +++ b/txscript/data/taproot-ref/40815dacf70ec14f7b8a062c9faaf258058731fe @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce2000000001a4c53f502057f530000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac79511752", "prevouts": ["fd145500000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "047d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84030e911897c6e4798122efc4265e48d96402783f565c89ff2a62155c020859d8460181b685601280cbfaae0e90478ea5ae6fea73a2d03f5a79a14a3e0c6d503"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93665f2789c044d6944fb0be746f461fd1d8ebe7179986f1cc1563b6f682e3c1e51e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84030e911897c6e4798122efc4265e48d96402783f565c89ff2a62155c020859d8460181b685601280cbfaae0e90478ea5ae6fea73a2d03f5a79a14a3e0c6d503"]}}, diff --git a/txscript/data/taproot-ref/4088fa75fe995a05522f18f9b0e6945552611611 b/txscript/data/taproot-ref/4088fa75fe995a05522f18f9b0e6945552611611 new file mode 100644 index 0000000000..14b733fbee --- /dev/null +++ b/txscript/data/taproot-ref/4088fa75fe995a05522f18f9b0e6945552611611 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706600000000263fbb6adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1a00000000cebe71a7030bb62e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d5afd460", "prevouts": ["9659110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bd0c1f00000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646243844b2829720c8a21875c1e5ebb7b78aaf54c61f95ffa067870b404aebceb3b80bda1b133ebf5523b41a15c88aa3d5202619e06dcb6a8f4a5442678614e2fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368e895c8970650c6085b3331045ea781cb4c0c0a78535361d77c53655614766db9aed6a34821d65edf69e9d12354a87f406d02be059705f92363392a057792142e401215e29d5d13de3b6ed62165bc3378402ce71158bd1208562fc299f33fc22fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}}, diff --git a/txscript/data/taproot-ref/40c7820188392556b1df313d7fe8ad00eac4965f b/txscript/data/taproot-ref/40c7820188392556b1df313d7fe8ad00eac4965f new file mode 100644 index 0000000000..18d1c7f8d0 --- /dev/null +++ b/txscript/data/taproot-ref/40c7820188392556b1df313d7fe8ad00eac4965f @@ -0,0 +1 @@ +{"tx": "4a229c5502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc200000000278d4f8dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9301000000fe6f74e00168477700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac24030000", "prevouts": ["784b60000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec", "40117a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "bd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082956f78f875a4cff3dc955be6c960f7b458e90648c2291f520c96d2b85cf15d2941cfbdca9cced9a9297ecbc29dffc929789a1848311039b5a24b338cddf0aa70"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641dd31aa852e6f71aedc584ccf1bdf704b326c74e68fda16d455fddcb9868622956f78f875a4cff3dc955be6c960f7b458e90648c2291f520c96d2b85cf15d2941cfbdca9cced9a9297ecbc29dffc929789a1848311039b5a24b338cddf0aa70"]}}, diff --git a/txscript/data/taproot-ref/40cdd6d34a71ec60c962c3ce8c6408731acebed3 b/txscript/data/taproot-ref/40cdd6d34a71ec60c962c3ce8c6408731acebed3 new file mode 100644 index 0000000000..97d5810e3b --- /dev/null +++ b/txscript/data/taproot-ref/40cdd6d34a71ec60c962c3ce8c6408731acebed3 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708a000000006cad66f9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf50000000010b9b10002826d6b0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca5000000", "prevouts": ["c136110000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "bf2e5c000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["cd4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5148aa6a6dbcb4c7060082480e3e536b464146150e8b2e96d2b5eabf2aaf1fe24e9f4d7ab890a2001a7be6cb25cf630fcd24657943ff80a7c5a11988ecbf9e80e4620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f454233ea8ba792ff851233df40d07d043b6f28307e4b5e8da83231ec75b1673f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820aae41afa256ed506dae95e698e8dcc0fa26e2618e50e74a83d05bcf51ab890d620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}}, diff --git a/txscript/data/taproot-ref/410f4c522606d7e3dd362eafa5a5ab9d9811a338 b/txscript/data/taproot-ref/410f4c522606d7e3dd362eafa5a5ab9d9811a338 new file mode 100644 index 0000000000..0755696578 --- /dev/null +++ b/txscript/data/taproot-ref/410f4c522606d7e3dd362eafa5a5ab9d9811a338 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2a01000000f6816db38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c467000000004c8c3ed5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa300000000092b0a9b015b3c530000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7962ad43c56", "prevouts": ["4e8f5e00000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "562e3e00000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "81d36500000000002251206ee7f50dd8b37aeb440050df10921bea288340730b764e02d5c3920c65efa447"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "", "witness": ["3045022100e6f32e5b47ffd07975ddddc3ed46ce9308d56bce465f2695c2182b84eca5b58e02204d0396a8b1af0de29eb1a068b196d61e713686feb1e31f473d0a53665d041a9c02", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["3044022001ca27f7fe0468534cf19539a3552f08da74acb2427cbc10521b29b1cf6e8bc502206c077774878a2580a86ccf18828dae2fc0cc9a89f2026b13d7c0deb1bcff15f102", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/41114b51cf4fbb2b1beee4e0cc3047fcddd88c2e b/txscript/data/taproot-ref/41114b51cf4fbb2b1beee4e0cc3047fcddd88c2e new file mode 100644 index 0000000000..47376885c0 --- /dev/null +++ b/txscript/data/taproot-ref/41114b51cf4fbb2b1beee4e0cc3047fcddd88c2e @@ -0,0 +1 @@ +{"tx": "bfeaf70b038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41d02000000f8f102f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270de010000002f563892dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2d00000000c1b137a404a710660000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac34000000", "prevouts": ["f4c73700000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "a13c0e0000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "0f2d22000000000022512022abfe1c27b62198bb616e4483022cc980778bee956a61d21a3456cf5e2e41f8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "367d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93610840586922c5e53ad9a63266eaa24e185b5e485f667ba0f3e18873b1df80384d4d2cf0b4a04f3dfea651ef6d0b2c4d5fffa0a14be5e227661027bf8174dd263cddd84017ed719a58f336e1892f80afe07727626533c4c78318e44c39862ffd3"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936898ebd438ad33d3fdb6724497cc3faaa24f87c16c7508697e3bc38420604e532b94a5b3352296838f351f650ec3ca72e25dc2a412f5bb92aac76541fe277cb7178448a7537869648343bbbdc00eb4ac0785a5f2aec0111e81b0d25ebde82a92a"]}}, diff --git a/txscript/data/taproot-ref/416cc4828a6c9b5f1667ac7ad0d2684eb23cac38 b/txscript/data/taproot-ref/416cc4828a6c9b5f1667ac7ad0d2684eb23cac38 new file mode 100644 index 0000000000..979e43619b --- /dev/null +++ b/txscript/data/taproot-ref/416cc4828a6c9b5f1667ac7ad0d2684eb23cac38 @@ -0,0 +1 @@ +{"tx": "d07c79b8038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41f0100000018502eebdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9a000000002d3f28d1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c170100000063ffc498030747e700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47874de2e530", "prevouts": ["a595390000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "51a15800000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "dec15700000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["894c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d26d1004a8019ef2e1188b07306b9375b4b58b003610908a9f3451755ce03441ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454b1cf341ebb9351320fe3e143ffa2dad1c15696d7ac983fbe7e302fe7a073e7ecf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}, "failure": {"scriptSig": "", "witness": ["4c5289", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93653442b71edc232265c61904a981e049b0ac07d3398e540c73595bf275af3e5a4bd8f71710e2f4773b226617f0b144a9d046788db13e8347a383f909c13421323cf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}}, diff --git a/txscript/data/taproot-ref/4184d22015b6c9b7656f411782a4484efd87060b b/txscript/data/taproot-ref/4184d22015b6c9b7656f411782a4484efd87060b new file mode 100644 index 0000000000..d32af2588b --- /dev/null +++ b/txscript/data/taproot-ref/4184d22015b6c9b7656f411782a4484efd87060b @@ -0,0 +1 @@ +{"tx": "14fa46cf02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4801000000d70bd4f0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c64010000005783b2cd023169cc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac6b25ab25", "prevouts": ["0c20700000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a57e5e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_53", "final": true, "success": {"scriptSig": "", "witness": ["a42c53fdf9f147990456e9027106f116b1fc8a253ba540763629b00db180057ccf534e0e745dc4e6c2b6b9eff978c43bb2f0f03f249aab6bce94a2457150fe4982", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5bda1280c946d68d6d4f69e81e61b4b6ee4cf2f7b31b7026f7f31db7af35c26ca7b2173339444bd8bb5235cdd690516a66893441460ecca848461c0c4486193e53", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/4186f82b0ef77212271ae59a07d75a5f370f8add b/txscript/data/taproot-ref/4186f82b0ef77212271ae59a07d75a5f370f8add new file mode 100644 index 0000000000..e10973959e --- /dev/null +++ b/txscript/data/taproot-ref/4186f82b0ef77212271ae59a07d75a5f370f8add @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701f02000000c88992c38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c471000000002bee261f02805a46000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e745311638", "prevouts": ["43bd130000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247", "ae50340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a95b51142906d61fff9b6eb19048f2d78beaeff0d809d50241b6dbf74fcc47950fc871d26555c201dd33550300448d4ae64e8667b7b3a5ff0d1457418fd85d97d231b10243e4e269236a618881f024b863ef2cf3de7e16691a59c4df3ad0ff8945b1cd0e9c9eb09b3e99ba2bf4b5bfd19b37e1db85fe20bde69649f3393dcdb499e3e973007cce8228168676134670d0baff825958c666e75c0cd396ba06e797334dda1764c3bff0081b1c1cf24ee069df2bec5d18d164ac2a6ac88c5f6895b9ab4639719d231b433427cc65e8e6b995184940f4ee67db13c86e23de7f882018c70c39edf813811d7daf5e937c4e903792e3bc08adcd4fc29f253b9cde001958746d321d48e3fef7562dd8c8a3ac864dac2d432c424d8ea7119dcb85c5dfc935777d015910e546ce8e9848abc35d583c07b8315bb8a76146797304a1148f4bb8b50968d698ce1d0418e6c736c63324f80a9f6370519a5db88f2f10e6d4acef75dace76a9dcd0e15a1890fdccde6a074e6c5ddc92c08eb9b13a9c74ceb69afb0a637ba9470fe37ea11f85520a810f4b6374e705a54707e8c81830f5a044ad849a488d8a427c4ee1951de23f092ca4742a34955297212e6fc0f37660fcb97c598eab9282c2f8829fc7e047ee3cc93fb86333a7f0009eb5bb1c468de6148c3b7d91783b4eeda3d47e74fd604178d7cef6f2c473826ab5148ddbc73364a006ca3589188d71467c8055be2f75", "847d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d67be0b3ed085d8229f99ec7120ac293144efe6be4aade727ce45146ba4b7b4fda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e9f6b3154707dfd0cc47160c458b5d6bbad5dbae79d1b1aff02b8c8f076d5395a9f31796df107fae040796e44aea27c7a7d41418cdc7206378fd34089f9daf951"]}, "failure": {"scriptSig": "", "witness": ["4d09021295e9ea5c3ed71a319ca66f39cfb76fbea35e76d485921c2ef0ea8f0ad5a6043a3bdf0cb1ae4e4864c117597b63ea6cae6f8647c25ab11d2f5e9ce0ae7f47b823c91a19ae552fc9732686d9a2ec73150a993eff0473f96f650dcd3e1f6b6e5271d4e1e3dffed73c51842ef9024a9800f692a08dd4a713ceedb0806e71dc5002cd1dbae7fdbb1e60ed3841db20e1d87535054c949c109ef68f84064f9948548dbe4b31257d230c91157157ae52eda33b8c1cd325897bed3e31ff1ca53c6b68c9d6f95e72db39537acbc5f3438e58ec75d2521915103541a0f42a85460ea1819e120a4352f877cdceb7b424c74df422f9dd8725aaf6dd3abb1ba57db2ac1eb76ad6ab222fff67c578cd3a6a010252713fa0096ad49e62007faa12bc68946234297dba040157e648e1afa77c88043ef0c7e4703b4cc4a9f2049318f7d0e7a342d8f02f40a57845778386c52a6c398a0491c0d2f6f52486dc36058a0ddf0b81def12b9866bad19e800439fd8c48283c84ea0ce66c90959b16670822cec55eb16257888441f266f48356bab6883e55140556907eb0b98985602b74d07896c9e187cc3ec206ad403bee59eef2ba6196210e471747aa0b96991aaacd5dd7ec232d8f8ebefea9a86bf118dc3ee3acd1c8cc4d9a291af29ba5f794284ef9be82fb329454e7076556d14b6a180e2ccfb04f5201e7e8510a649db36d8af96268c4fbd60528b82f9683e1720aafa775", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361950e9cd3056fae57f4e29cba5f1c37ec5e51ffeed67571dacdd2332e5e5df68cc3b36ccc81fe4912a925ea2b1eb99a41bced4468215b0c94e7bf4feca6759c79f31796df107fae040796e44aea27c7a7d41418cdc7206378fd34089f9daf951"]}}, diff --git a/txscript/data/taproot-ref/4194caf8692db4d7109076c5dece284d07e06cbf b/txscript/data/taproot-ref/4194caf8692db4d7109076c5dece284d07e06cbf new file mode 100644 index 0000000000..8cfe708bcb --- /dev/null +++ b/txscript/data/taproot-ref/4194caf8692db4d7109076c5dece284d07e06cbf @@ -0,0 +1 @@ +{"tx": "9a15a34503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6700000000b98902bb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47301000000b91d6fd260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703d00000000c51f3a80025f6e7000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964c000000", "prevouts": ["e6fe26000000000017a9141582f8bc3490e924b143f387e99eced40303eaed87", "fca73d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "973b0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_6e", "final": true, "success": {"scriptSig": "", "witness": ["dfa56b053bc5d80a69aef617f2475e8e09f446e7efc5ee7bd1a231c3a4a64e3d765727f42b37a9f7104332797ee53db8dbed629d668d59f05832417e9faa288c02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c8e6efa90e1fecb749468c4e12dabd2f1ac0ea03c231a8145cdafdee296c24a6f7970a06c21ff5ef9d4da8e5354acfb3c34b52c991228d4a6e6f1a4a1b68c7996e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/41a24f98a0882fe70484f5006c4b6b9a37bc85f0 b/txscript/data/taproot-ref/41a24f98a0882fe70484f5006c4b6b9a37bc85f0 new file mode 100644 index 0000000000..d7a8f4f5ec --- /dev/null +++ b/txscript/data/taproot-ref/41a24f98a0882fe70484f5006c4b6b9a37bc85f0 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7000000000ec9b048ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7301000000231716990186d7ae0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e776040000", "prevouts": ["2956780000000000225120e126375bd164d085eaf078f7c968ba0351125367548e57f6cc6688a24dc88c09", "3cd947000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "347d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faa00efe7e15c1e643e9e1cfaff50670e7cac10128754f4af7dc416953d80cca2b070c3fd2cc03cfe72ec91581f9e22200fa4c4f6deb8dafcd335310e90efb11e5"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366956433f4fb745717b89f2dabf7821b404dd73db8a334af9b6b63fb319135fc93ac03c85a7bde4aa83325c4e9fa3803d6178be55885bf5b72d341e036ded0599070c3fd2cc03cfe72ec91581f9e22200fa4c4f6deb8dafcd335310e90efb11e5"]}}, diff --git a/txscript/data/taproot-ref/41bb837acd47aa639c62f7986ff46af86a6c36d1 b/txscript/data/taproot-ref/41bb837acd47aa639c62f7986ff46af86a6c36d1 new file mode 100644 index 0000000000..b71e0d57a4 --- /dev/null +++ b/txscript/data/taproot-ref/41bb837acd47aa639c62f7986ff46af86a6c36d1 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49000000000575c18d0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6e000000009b12d9b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6201000000323bd29c036d5608010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6ca6eb94e", "prevouts": ["b77b360000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17", "a9315e00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "7c80750000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "7c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364a60ea8a26b95179b8a81cf8791033c1de4a7f8dcf3286d999b7c941f2edf7811202adea3ba63b8efb220ed0b92cf765f01931ebb31f4963f663d14c15b1e6099a711983bc616996e2ac47b27808b31a9b7e87f7ce1f3571999dd3a2a57f1080"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699b107a70635ffc73d55a58255f55b6e906e17a6659bcc3b92a6a185be68db381941f75e5ef6b91990230755a95e91c03e6de7762e861be9dda5623c3157397ffd5e8f79d631fbf207b458b911c1cf4efab0aea5316113aa9c93bea92caa9fc9"]}}, diff --git a/txscript/data/taproot-ref/420a24fcbd56a2a2791e7238666b8aa34e2ccf16 b/txscript/data/taproot-ref/420a24fcbd56a2a2791e7238666b8aa34e2ccf16 new file mode 100644 index 0000000000..88fac822b4 --- /dev/null +++ b/txscript/data/taproot-ref/420a24fcbd56a2a2791e7238666b8aa34e2ccf16 @@ -0,0 +1 @@ +{"tx": "2072d98802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1502000000525dbd8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704d00000000be747faf02cbaf2c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71c86fa53", "prevouts": ["2ae61d00000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "45be1100000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["864c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4a89eab7efa8b8df17a82e815a072b99e340ac1768e499ee92fb25d88959474e250636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93611dc1db4058b7df57233984f644c48dd57428e5644aa1c5e18e4c2c7e9844a80a89eab7efa8b8df17a82e815a072b99e340ac1768e499ee92fb25d88959474e250636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}}, diff --git a/txscript/data/taproot-ref/42c6d3a78f584cc355a0bac6f309e105089332b8 b/txscript/data/taproot-ref/42c6d3a78f584cc355a0bac6f309e105089332b8 new file mode 100644 index 0000000000..70fd9efec8 --- /dev/null +++ b/txscript/data/taproot-ref/42c6d3a78f584cc355a0bac6f309e105089332b8 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5400000000ddaec8968bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d5010000003ef568afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4900000000daee1d6e0386b1db0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac56000000", "prevouts": ["92bf790000000000235b212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "309640000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "c96623000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["7c3697d5de3aa481d64fd5f75484d4994cbea6af6a5e3d8391bc5c52fb3307999ad91102540ca3f8757641bfc1d36dd8faf913d9874937fc17baf6ab4db99eba"]}}, diff --git a/txscript/data/taproot-ref/42da32b7dda49d356987402249a3bb67a0b53529 b/txscript/data/taproot-ref/42da32b7dda49d356987402249a3bb67a0b53529 new file mode 100644 index 0000000000..d7174ecceb --- /dev/null +++ b/txscript/data/taproot-ref/42da32b7dda49d356987402249a3bb67a0b53529 @@ -0,0 +1 @@ +{"tx": "22713f2202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca30000000021b16c8a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4940100000024a82fcd0387598700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487a073772b", "prevouts": ["af76570000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a", "b7733100000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ed7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a7e5e7dcc199a2f568fd88e83eadcc582fbeb8fc2cdeb8c853fb2288d51fac1b4d19f2c0f6744ba7ac1f5ff1e4bbd0a31d1cdb1f5d58d1dbc476492d0098121b5"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e1749aa0b5d70f518b926cb476468410836d749f7ea53df886cb06228889683d97e5e7dcc199a2f568fd88e83eadcc582fbeb8fc2cdeb8c853fb2288d51fac1b4d19f2c0f6744ba7ac1f5ff1e4bbd0a31d1cdb1f5d58d1dbc476492d0098121b5"]}}, diff --git a/txscript/data/taproot-ref/42e412a1e895536ef1264d7ee08902b8e37a53a0 b/txscript/data/taproot-ref/42e412a1e895536ef1264d7ee08902b8e37a53a0 new file mode 100644 index 0000000000..793ac24cd1 --- /dev/null +++ b/txscript/data/taproot-ref/42e412a1e895536ef1264d7ee08902b8e37a53a0 @@ -0,0 +1 @@ +{"tx": "0996bdbc02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4201000000c4343cea8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46c010000005a7cd0e60191ac45000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48701283e59", "prevouts": ["1283730000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f", "21743a000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "657d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d46ed5c88be999b027defe78826bdf9f79fd708eb8b2e1895cb28c5d0d8f8cf07a9921914746f344d752c7034b32810721c9853c38c376ca018a4c3c5bab65757fdb01d6ca2155f5be7a678ca6a1e1d0c436995e81f878ed9c74997cf4fccddd302781454c6297f6b8a579760f4d591c0acf84ff9d038b064bbab8a5d53835db"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c56699834a23a35d7a8a8e446f06483c0f6f4014465e54b19938cdc9d35914e3da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e38fd10ac28b4a0ae18793cce60e7e7ebbedf1e3488ce0551c956bc9cf517ba032bc2c7d802e8c870cc0fefcfae9d23d316cca1682651be3bf62b663d5ddaa443"]}}, diff --git a/txscript/data/taproot-ref/42eddccf89cbef79a5adffb7eb5ea1523de5b3b7 b/txscript/data/taproot-ref/42eddccf89cbef79a5adffb7eb5ea1523de5b3b7 new file mode 100644 index 0000000000..6cef0448e5 --- /dev/null +++ b/txscript/data/taproot-ref/42eddccf89cbef79a5adffb7eb5ea1523de5b3b7 @@ -0,0 +1 @@ +{"tx": "3229dd7102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfca00000000dbcb3ddb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704b01000000c5a717a901a974190000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963a010000", "prevouts": ["a632640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ed0d13000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "4830450221009754527738b581abc4f8608a913b98b874c4626f53374f198140d73fe623e4b102206aca3fabafc73b33ab683eb12e436b9835fa0788572f815a6f7bf4c3201c654602434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "483045022100e6b5f7be8ae69f76d84286005a58fcbfaa1ea530557e240582c3f4ecc4d65abe02203e1e941e8f87f8354381d67578c031d30a398c6f94b29aac09adbb7af5522a1402434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/42f1cfaa89e0e558cc339a4adfc253b4108d5843 b/txscript/data/taproot-ref/42f1cfaa89e0e558cc339a4adfc253b4108d5843 new file mode 100644 index 0000000000..f0a74b0a54 --- /dev/null +++ b/txscript/data/taproot-ref/42f1cfaa89e0e558cc339a4adfc253b4108d5843 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701c0200000078a4abf760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e80100000013f5b7250110821b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac9f000000", "prevouts": ["51e6120000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "458a110000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4a3ea69b746c966c84daf122809976a6bce8b1d887b17a6e963c4c690b8a790e73a6c94bbfbe0c8d8162307ea587875a7b29cdfde589bfdf70042a40a3445f95ec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5174c6ee35a9af327fa74c94c4ba87a09a7dd613a1ede58e30654f1c4a24a66737074cc5cf84a1d913e1f5647d3427cc0d6d469f0e5b86c78a49890e87126542fa0e1c61743bed8ba943c0dc40e80402f7423773c7111097ca9c5a140b1b3c94b9"]}}, diff --git a/txscript/data/taproot-ref/43532b914ad45faf56c91ef34b9b696012326b2d b/txscript/data/taproot-ref/43532b914ad45faf56c91ef34b9b696012326b2d new file mode 100644 index 0000000000..6f7a81536c --- /dev/null +++ b/txscript/data/taproot-ref/43532b914ad45faf56c91ef34b9b696012326b2d @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c290000000006481d8560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e0200000026bb47f7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5601000000f8a95f8803a645cd00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79665a0ac45", "prevouts": ["bc855900000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "782b1000000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7", "077c65000000000022512007a606ac1d369bdfe9b32b88a4b0d4c507785f2481b337f6b3340196eed3e896"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "f47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa056823e3960e672c2faac6672d149a4ac5db30e5c30fec842c5078845a2fea890bfc944cea42013591059ba9f4ec0a95c62699d2133b38017223ef90bcb8e42b4a87a36ff2ed7228bcfc2438815b30cc1c98339504e1b834e10aaf4a034051"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682115a2dfa9b95e696b2e1876a43d90a8957d7c1a0aa8ff9ef276528e0707301bf93feda87a2a10f8ccaf134f5ef6c2a0b95d03f8827da72e1e875b6e78a8a5e876f4540117e7e2fda63f7a015ec774d613b8932caa4388fa9ce7145d42cc7f6"]}}, diff --git a/txscript/data/taproot-ref/43a09bc93d6d45b6cef903b1341a287624b825ca b/txscript/data/taproot-ref/43a09bc93d6d45b6cef903b1341a287624b825ca new file mode 100644 index 0000000000..326f94ea60 --- /dev/null +++ b/txscript/data/taproot-ref/43a09bc93d6d45b6cef903b1341a287624b825ca @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb201000000cefb2422bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfba01000000810ff78403a63af100000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac7eeaf121", "prevouts": ["54e3820000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6", "8c2470000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "4a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936153aa193df228982a93d719b91a9ccdb5e9bf3da7f02bfb3b6c406cdd69a7eb4615c38a9f4b3c26d8dcb1a4c3fc9e68202e120a4fd7f06c3d33071ff6316723f12efaba1d06903f148d2465ca4e4c6639d336576fa6993c6ca48823372648a44"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652be2b7d343b6ff8f1db316ffadb0e63f1ae900c6a55aa5e53be2b7079034d4d9a5f53a99550b57470dcc4d4233d312935e71f0fec8998bf9150bf0a5d1b49a4615c38a9f4b3c26d8dcb1a4c3fc9e68202e120a4fd7f06c3d33071ff6316723f12efaba1d06903f148d2465ca4e4c6639d336576fa6993c6ca48823372648a44"]}}, diff --git a/txscript/data/taproot-ref/43a12820d4dfa937dfdbaa0843372e901ec73944 b/txscript/data/taproot-ref/43a12820d4dfa937dfdbaa0843372e901ec73944 new file mode 100644 index 0000000000..d0921be676 --- /dev/null +++ b/txscript/data/taproot-ref/43a12820d4dfa937dfdbaa0843372e901ec73944 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8000000000896880f4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2302000000409c9b9802fd1ba200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdfcb3a45", "prevouts": ["2ca35d000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d", "3634470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ef7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aa6323c0295bc5775a3404b3aacf7082420dcfdcb982829d77fe55ccdd4d869082a8da46561b857dd56ed73270ec2a55b69a5f7c1db8df98b88468b2be2ca2b7eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac8ef60344f111a9c34d055af59cfd42b130acbf4987ee3354719b7c9974e4d449"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb1d33bd2ec2ef2b80e561b3c30cfb99b356a60261a599d7e1f2ff199de481a6e8ef60344f111a9c34d055af59cfd42b130acbf4987ee3354719b7c9974e4d449"]}}, diff --git a/txscript/data/taproot-ref/43b19c13ed8e58e70071e063750e8fca7a9f05e0 b/txscript/data/taproot-ref/43b19c13ed8e58e70071e063750e8fca7a9f05e0 new file mode 100644 index 0000000000..0b9186989b --- /dev/null +++ b/txscript/data/taproot-ref/43b19c13ed8e58e70071e063750e8fca7a9f05e0 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f80100000079124b848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4320000000067ebebe7049dfa440000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a666010000", "prevouts": ["2ceb110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9c753500000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_csa", "final": true, "success": {"scriptSig": "", "witness": ["c5a268386538f5dcdc6b32fd437e7aa0f1ee1100b7fb5ecfc40d276cb9007ba505c108bc9acfdbd25afecb6ff023b17e11b1564ef22b16a4136dc00086742954", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef32555276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}, "failure": {"scriptSig": "", "witness": ["", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef32555276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}}, diff --git a/txscript/data/taproot-ref/43bfb11c19ea9173f4b0185fbc6a622fd0787c68 b/txscript/data/taproot-ref/43bfb11c19ea9173f4b0185fbc6a622fd0787c68 new file mode 100644 index 0000000000..4965614181 --- /dev/null +++ b/txscript/data/taproot-ref/43bfb11c19ea9173f4b0185fbc6a622fd0787c68 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fc01000000fc7cc7ccbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfed0000000086d73080029a989400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748768010000", "prevouts": ["e92f130000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "09138300000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51419220fa8a7a918b3857a082d32be9fa2ecc61d36b58eead0239ee9c5d9d4afcd5a470b8497850c3a230fee464eb343180400453804118582df887251250b2f1"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ef65a7bc88e8caa9953fbbe68415f348dc7b3deedacdb598041f1438fea667b18959ac4fa8a57d164b76708dc6f63c2efb2484bc5a77a391ceb66b2f5ad6b35f745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}}, diff --git a/txscript/data/taproot-ref/43d1fadc7620820efcc941a68f7696480649c13d b/txscript/data/taproot-ref/43d1fadc7620820efcc941a68f7696480649c13d new file mode 100644 index 0000000000..672d74c9f9 --- /dev/null +++ b/txscript/data/taproot-ref/43d1fadc7620820efcc941a68f7696480649c13d @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127052000000000b665d8edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c200000000084914c6603c36969000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7a37d794a", "prevouts": ["2f9e0e00000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d", "ceb65d0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "e47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366bc9e6400471d4508039602a6371cc2fb521d342dad10229cb10d12c2b95e76f158e114954b29a1fe443083941979d23a0210cc324956afb3dcce424fb4eceefbefe4cc2cebe7bba8b4a4f82666342333b91a450af49acc0f1954b5763bfc142"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa0d58db0463b9d01080baa2617114f2c0459e5723b09a0137090d28117705b675ea7c8dd4a05a6083e4a7ce3fc20cde94d430ec03cbfbe8017e9dc8ef3bce99a9"]}}, diff --git a/txscript/data/taproot-ref/43dae97b688afba43b6d88389a78b979f1181c34 b/txscript/data/taproot-ref/43dae97b688afba43b6d88389a78b979f1181c34 new file mode 100644 index 0000000000..881c1c22c4 --- /dev/null +++ b/txscript/data/taproot-ref/43dae97b688afba43b6d88389a78b979f1181c34 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8301000000820c50a18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48c0100000021f32087dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbf01000000a91f7be901ef40c600000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acac07da2f", "prevouts": ["4cf95b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f456400000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "d4ce59000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c9", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936643cf28b3f57e3e135ddaf8a1f03437647ba3161555e3c3b2dda50db56032ea077878475803065420b5149b394b9f2a263406aa3a3cf62bdb9b13e67809a83ebcc9238bf2d7dc0bcf11838c34785251ea2fa5f3bb034bc98e2e8efb0909b7dbc17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d3c147557fd4654830368843709159d459528293d28ab2736e9587eb54fea08bf48725aff660a72fd31f8e9799fbe605d57d774c031cecd8b6989780acb581b6b24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}}, diff --git a/txscript/data/taproot-ref/43eea0f55cf11052527d14c3cf0f96e55882c4d5 b/txscript/data/taproot-ref/43eea0f55cf11052527d14c3cf0f96e55882c4d5 new file mode 100644 index 0000000000..931e6ff59b --- /dev/null +++ b/txscript/data/taproot-ref/43eea0f55cf11052527d14c3cf0f96e55882c4d5 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0802000000f4ac4498dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c370100000052b315f604819bde000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac2c000000", "prevouts": ["1d9887000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987", "206059000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100adc3d98ee8e5c1787d2b85ce1fcd1e29a503d298d390f63e89972f1760dbdbfc02201b1f6a00bb9a7de1c0b4a3ea0441662cd0dbbfeabac21ac68d8821da5c2f7c1f024104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "483045022100bc7217801168eddf5a58a3cfdda97c542a04cdeb3abf6d377edd9649a977664b022075af2dc74696f76798c77103126ab30dce3626b501c2e4213e1bc19da6b1d404024104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/43f8e70fd6ed448f6cd62609f6e4a9d03a0e083a b/txscript/data/taproot-ref/43f8e70fd6ed448f6cd62609f6e4a9d03a0e083a new file mode 100644 index 0000000000..c36f2aee1e --- /dev/null +++ b/txscript/data/taproot-ref/43f8e70fd6ed448f6cd62609f6e4a9d03a0e083a @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706201000000f53fbee960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127004010000008b79075601f01c0f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac54000000", "prevouts": ["cf231300000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9", "bfe7110000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_mis_83", "success": {"scriptSig": "", "witness": ["626a18a6eec2972850c19be268a6a52e86ce74e005009e75ca6e65c08b5cc41eac5c023a6102bad84750eb48fc3a79616a6684cfbd93d151b77a18eaadee0dcc01", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50db6d8b93e424a50fb110d4d237683ac07e6c07da9335a8132d3538472fc0a13fdd63a4f7258a359a055f2ed67b177d56cc00fceafd6c0f973773ba6c49bdb0aa3b"]}, "failure": {"scriptSig": "", "witness": ["3532dd22bf65057d8863cfd93b0944cf39b5bf0e2f42d8725589592fb56bb7c3abe7515ed71127424fea7de0caefbadd41cadd3540b967c06d2b813cd375f81f83", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50cd54dddf5c435e73def586bd9097cdf835f7188234e6520787964681739d4478193466ac3f5ebdbb9c4b535b3350feda5611f645"]}}, diff --git a/txscript/data/taproot-ref/4407ad4a37ac5667b725ef07db2b1b0ebbe6db1e b/txscript/data/taproot-ref/4407ad4a37ac5667b725ef07db2b1b0ebbe6db1e new file mode 100644 index 0000000000..7edd8ba2e7 --- /dev/null +++ b/txscript/data/taproot-ref/4407ad4a37ac5667b725ef07db2b1b0ebbe6db1e @@ -0,0 +1 @@ +{"tx": "706e0a0002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd70100000024a962a960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b600000000b076b3840399c468000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2b971d54", "prevouts": ["cf2e5b000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "ad3810000000000017a914613e66961ccf40c7c83ed07cc80b2528cfe51edb87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "bc", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900459312a224ee6564b861c658371f7a6f0026ad2c58d86ce869dc9b432e830a527104966f092bf1e4b4348fca11e7254311373308f7fc15e3d44d6a2afffa343c9657ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b04dbe1d7a597ef7e58582d6b28f055a2f440add2d85f9dd7bf5919989399b7220e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e14a8563068286881d42b1c4901d93a483973910fd5653bf7ebbf040741f7cd837150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}}, diff --git a/txscript/data/taproot-ref/4422ccfb3a652df26350f5fd43cab32b4a6db9bc b/txscript/data/taproot-ref/4422ccfb3a652df26350f5fd43cab32b4a6db9bc new file mode 100644 index 0000000000..e440c986c1 --- /dev/null +++ b/txscript/data/taproot-ref/4422ccfb3a652df26350f5fd43cab32b4a6db9bc @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0601000000cd66d1bebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf64000000002ad67cc0048a99e0000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac56000000", "prevouts": ["9ca76c0000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "71787600000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "85", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1c80cdf889f2095af4d324c92b00d2a9db5fcc0724b0f6f8ee9ebbd204938760cb2a240b376911c9876b3695f79f395ec3f2d97b1695e5c0e7f397f1ed982e79a1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364b0900bf42a492e6d84803f411d6b7283b14689911cd75fb3ce169ea1a2bbfe0d4e60e987dc96ee5dbea4bc309cd424f3f3a0504752ed5a5936e8ec363297933734b3a7050eee065844830ad8d45a710891f78004f5e7f35b8fd72bf3ee94449"]}}, diff --git a/txscript/data/taproot-ref/443de93ae646f545525c4a8177964caee78a499e b/txscript/data/taproot-ref/443de93ae646f545525c4a8177964caee78a499e new file mode 100644 index 0000000000..ce9a947405 --- /dev/null +++ b/txscript/data/taproot-ref/443de93ae646f545525c4a8177964caee78a499e @@ -0,0 +1 @@ +{"tx": "1fa8cf3401dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5701000000ac034f8802b8c04b0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac3f558d5e", "prevouts": ["83824d00000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ed", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08220e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e179a506f75037c50a9ea9c509d8c41e46c95fdf651773b41e5feb3da8f515025ffd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364239bb564bb88fab9cc8a68fc985ce74d0a60efaac94a2193d617d4650dce2ca20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e179a506f75037c50a9ea9c509d8c41e46c95fdf651773b41e5feb3da8f515025ffd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}}, diff --git a/txscript/data/taproot-ref/444bdbc8e2a3f36427b9ee3bb33b639f3d06010d b/txscript/data/taproot-ref/444bdbc8e2a3f36427b9ee3bb33b639f3d06010d new file mode 100644 index 0000000000..8cd0f9fa23 --- /dev/null +++ b/txscript/data/taproot-ref/444bdbc8e2a3f36427b9ee3bb33b639f3d06010d @@ -0,0 +1 @@ +{"tx": "4296b05c0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d701000000192c02da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703800000000b70f74e6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c010200000054072fbe0445ff6e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e4cb024e", "prevouts": ["0526100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "099f120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "39c14e0000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype0_byte_keypath", "final": true, "success": {"scriptSig": "", "witness": ["da1ab9c302402e20432a4594d9fa7f497ccad03de081d4a84d17f40df1570448874889de2f0b8df815ff234416b9b1192d30e9e894a6aa52d0bde4a7a13bb3e7"]}, "failure": {"scriptSig": "", "witness": ["da1ab9c302402e20432a4594d9fa7f497ccad03de081d4a84d17f40df1570448874889de2f0b8df815ff234416b9b1192d30e9e894a6aa52d0bde4a7a13bb3e700"]}}, diff --git a/txscript/data/taproot-ref/44513b5ccd5d2993d98b0f606e24c3363080118d b/txscript/data/taproot-ref/44513b5ccd5d2993d98b0f606e24c3363080118d new file mode 100644 index 0000000000..74f75afd57 --- /dev/null +++ b/txscript/data/taproot-ref/44513b5ccd5d2993d98b0f606e24c3363080118d @@ -0,0 +1 @@ +{"tx": "363a05540260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700f00000000e95226b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b34010000005888338d017b9b0b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac4fb5bd44", "prevouts": ["c009130000000000225120440c37f254c07fa4cc41897f3d6c7e819f00ad5f6c5ca97225bb132b6849e94a", "0cbb220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a5cb231d20a79dea39c1cf40c1bbfc5417f53129f0b8bc111b3a1988e404cce5"]}, "failure": {"scriptSig": "", "witness": ["6a18616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/447e0a4f2c9391201bd7abdb3935d959277ac93d b/txscript/data/taproot-ref/447e0a4f2c9391201bd7abdb3935d959277ac93d new file mode 100644 index 0000000000..d363e035e6 --- /dev/null +++ b/txscript/data/taproot-ref/447e0a4f2c9391201bd7abdb3935d959277ac93d @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ee010000002a96f3a28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f4010000000cf823d504af574a00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fced92f55c", "prevouts": ["dae111000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "57623a0000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/inputmaxlimit", "success": {"scriptSig": "", "witness": ["4ea734ebfed9e69b2eeabc3c8a8761f0d2f4dcfdebb9b46aa28d0ca18ac4b29ca59e5a06042fd767120cdbdc4e7a8693b6dc0641a9c42c3c2731660eeb65b67c", "ed6c5c68dc20c4d81e1a9fd4f9a1cea561e6ce4dec463534c9f79be0649c9a14df0481b53baacd38acc07370660cb0ea06bad30ce9c81e3b6982f71742eb0bd16c73134323b6182c28c7cfa4b5d12aa1f1eee3575b62951c78426cde80eee3b1ead621334e200b7705d1db822abb4e8ad641f7a9629e50a120ceee9728ea567175ef04a6e1ffcf03230c9c83f73d3c0afb317bac9b3186dd9fa61ece7d173f6fec4173243c4054f05a9c45710b9d23c31e252369b2e8dfa9b2c526f0fd6d4ed9552d8df2fddde0f539084cadc5eddd5586a40b37a9db1f93e20c82ef5fa0b9291fb75deddd312f29336718aab29d0fabdd12f3e194cc8fa6c7e4cad213e4d0fb992568206ab873bdb40fae9f7d67742eaaf2c6efcb4fccbcf1b5e81c64e41c04ebf631366b669f629adb57c24378754ef7d5ae1eeedc9a4498eca87e1a1dbb78b16c0247a05da6804dcddfca27b44f897f24394e44a18cd30fcc59587236d2a8f696d2e2a62176200c3b33ce2d07a9b0c47e025df6319a3c0b0de94b5c85bcfb96b599217f8c4842c1f26838bad5d96b0fc60a357b24c6e35fe07dba659eed38928e5df01e33cf75d6f34c730440719a97dc95593d31bf6c970d7dd3380d07da9f9daae0a1621c36bfd51dfec939aca5054dd5c13f78a309aad147e1e1b0dc22896b3f0cf905f6a992958dd77aa2e8279a8b516b3e76f566f72fd4144aa59133c9666e409bc99fa3", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93633f145906eb3b0b9144503b7e952fa7ac030804bf21818b76946b0617a1dc901d4021eb67a5422f2c264ab2e161e443ad68483a924a10f3067064f47bfc1aa823d0cff3dcc0a2d4e46fc30f48a30ceeaa99fba3feb9f110c8632a3b2fa3f4f4f8fbdead7f8de6a8aad36d37b0d589bc9244c1684fd5ac3294cec67c7c6e587a6904ede5a53833ce5d447360be78b94add963f9070eac219e9b04ee2bdd400ddd04364ae3f3c0d48023a93d8481ba8ff7adab87d79476f69028f3fb22b08d057964bbb3ea34308947c748760264ee9e03eb1f98d2b66028dab654f580a418be99661f479a6b0f557293064f4a690bd09af98d8bd3a778ce8944b23259946622ee8f58700e34290ee018923271c5b5338c26b1c5ef6f25154ea2cb21c87cb2bddad45cd3b88d2dbb65b62cf977bb614d0efb5c9353a8b35cfa01122561253231744c2c32064ddb3ff0f538be34c536787771f8aa5aec123a81e8014a979ffa6906075479528a5b4db5d683c0884af4c8976d652dd9505f85dd291fe0843ffd0ff27865ba15c8822e63cb0be5982c1ef15a41fad555080e76aad0b72a8aa15726acd51679a62f62b306cf011a5d1358e6ba8e189d7358bc43376d46dcace83895e75b2934214492b999e4970e4990c42fb0eac353aa09117e3e38145bdbc22646e577b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["4ea734ebfed9e69b2eeabc3c8a8761f0d2f4dcfdebb9b46aa28d0ca18ac4b29ca59e5a06042fd767120cdbdc4e7a8693b6dc0641a9c42c3c2731660eeb65b67c", "9522d307fd40d9be4d4da051ae6910c605180d33f1668ebe958499d5bb8aed34219f719d4498b6375b4d334d66be19c5d26b8210eb751bbb87ede327c69546f4a21dc527aa6d682777c3ce17d0038712b8ad3be26d8f457357b203712a559ccc869d2069cd3e6656d0b631bd15ddde355cc941c79588655b4ecb28d931ad72c2f24dd0bdf93d07c1df0f9c6a5d30613a2d3e30ea5bc367b15539870364eda18ef77b5af3a6aee8ac4a78bbfd581cc8673293945993260ddd9a3c7f238f80de87fd7df5e4a2ce8c292d296c9680b44457ec8fcd7e299b19318d7e17a0f233bb64475751f0f46e46abf37bfd6b213ff556bb885fb08e99a92235668e3e8983daca3efef2f18660eecf9102d8e54a40dde7f8106e25bc9bf46dc549842c6d88fee2c1baa3affbc0d30e8285b8fb474718ba4480eae8fdf4f704df7e1d4d9558ec09e534e2499f64ad12855cd4362b72d7a3552f3d2319df4e2782220654aae7a12ce6e81b8b1b6fc751ad61e60a26dbe6949e1827fa35068b754729a01ecd041771fdfab7c97b51ff5e8768e9b4bc41afcba0f5fcd5817a24110c0447e5e5564af9f032ecf15207d1643a04d8e65b50abd42280fd47593c69ef6489cdb399a8afd44a827bdf173b1ffe8bd57dfb4e7be65aebf2ba543d12629d1475b024713f6f18bba3efe2ae7c2f6efb3418162414164ec7a6876d68a934ac7c5709447412724313e5f8651e8dd36b73", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93633f145906eb3b0b9144503b7e952fa7ac030804bf21818b76946b0617a1dc901d4021eb67a5422f2c264ab2e161e443ad68483a924a10f3067064f47bfc1aa823d0cff3dcc0a2d4e46fc30f48a30ceeaa99fba3feb9f110c8632a3b2fa3f4f4f8fbdead7f8de6a8aad36d37b0d589bc9244c1684fd5ac3294cec67c7c6e587a6904ede5a53833ce5d447360be78b94add963f9070eac219e9b04ee2bdd400ddd04364ae3f3c0d48023a93d8481ba8ff7adab87d79476f69028f3fb22b08d057964bbb3ea34308947c748760264ee9e03eb1f98d2b66028dab654f580a418be99661f479a6b0f557293064f4a690bd09af98d8bd3a778ce8944b23259946622ee8f58700e34290ee018923271c5b5338c26b1c5ef6f25154ea2cb21c87cb2bddad45cd3b88d2dbb65b62cf977bb614d0efb5c9353a8b35cfa01122561253231744c2c32064ddb3ff0f538be34c536787771f8aa5aec123a81e8014a979ffa6906075479528a5b4db5d683c0884af4c8976d652dd9505f85dd291fe0843ffd0ff27865ba15c8822e63cb0be5982c1ef15a41fad555080e76aad0b72a8aa15726acd51679a62f62b306cf011a5d1358e6ba8e189d7358bc43376d46dcace83895e75b2934214492b999e4970e4990c42fb0eac353aa09117e3e38145bdbc22646e577b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/4493e5053e8c93d7133c12033db30ab0fad02eea b/txscript/data/taproot-ref/4493e5053e8c93d7133c12033db30ab0fad02eea new file mode 100644 index 0000000000..513ba502b5 --- /dev/null +++ b/txscript/data/taproot-ref/4493e5053e8c93d7133c12033db30ab0fad02eea @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd901000000f31c8ecadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6f00000000c116dbd404db3d7a000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5d010000", "prevouts": ["1ef55c00000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "0fff1f0000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "0b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ddf344411e2a803e2f014fc4dbbd34487be175b3b72a6822dae0235404bef0ad6eee185c5450ca8ff820874ed786a77ca41a0ece110e4e1e272b53628d0f659ee0d9bed60e53dfa6fe8b58229f37daf0597893c765c7b30814eb9e16fca89b86"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a7a0146d222f7b4b0baec19231a96a69115ffe6b14d39b17208bbfe466e36783da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ea51646124a2b4386d840e205fec55c7cefbdbe9c75e9c45dd558741f313d2d0ee0d9bed60e53dfa6fe8b58229f37daf0597893c765c7b30814eb9e16fca89b86"]}}, diff --git a/txscript/data/taproot-ref/44b2a5681330965efa5dadccd65e4296cb9bb54c b/txscript/data/taproot-ref/44b2a5681330965efa5dadccd65e4296cb9bb54c new file mode 100644 index 0000000000..9c74042b93 --- /dev/null +++ b/txscript/data/taproot-ref/44b2a5681330965efa5dadccd65e4296cb9bb54c @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1302000000a081f487dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0500000000e4f110110337dcab000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48777000000", "prevouts": ["c78166000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "7f1348000000000017a914971b3e5f9ac480bdcebf6ea71a9fc7de0ab164e287"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/emptysigs/checksig", "final": true, "success": {"scriptSig": "", "witness": ["", "36228bbe2462ebf9b44d5743a161bb8b43dec7d353201064a04696e3c5074c9f7e1a0cb72ee02e5eeaa1de3f2b7657cbfdc9ee34efa9d9859d04c40a6b4ac1df", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac91", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b87c3d13bda4bc96912d9e1d3614b88ea00288653983e5946dd79f95cad56850892bd312bf555f4ddaee895b667ff52e0154e570fb3b21fb70ce55962eaacfa82b8a8694f12869a73a7c9258692c0a516e36ca599c5440cd48185ae688899f972334d1082e7cf9fba1fb8bfc554039e0d30e1d717d7bd10b1687557faeaf94ec531fe2ceb6eb6fc38e892c8463543d75fb6857ed3555003db7d30631ee24ce556745e6d5f13398b82293345b14639057cfe7c9133f3a817857bdff96787ef39c49602cf62409ee25e64fef6eaf4f70b438998ea376bf89aac812460edc6098d5da36431739388703f162bfd6be43cc18929921c1c825eeda473da76ec1d4f9fb59fb388f102ea0ad67c71defac059c7c8b93c58afe1a654026c6fac78536b8b1901243e25851de0d6781e7f528327af4772fe14b340f1eedd75761d4eaa742157b0a6f9680ce7f5ca5bec9338fe334e6832114c99db2b4b78f7605856e14f0f922c7dab2635ca4d983bce69908efc2d6c8e3a4e02d107fe54b591d6c8cbc0ea2e862ced977f81641729beff04e69bc449bbaee4ae229138f125e8f575c30a32bf5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["", "a7f2f47ede28e2e8ce69a17fc3a01f3298b85f5485f6bebfde16c89eec7adf4f6458a7a46922f2fa766f1dc473c0616e81c3b9adc97dfe98f3e8662e0fe06ee1", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad00ac91", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361a911a84ebfe90f85cb95d912de296e406a83e6bb64e40cd5d5446ea831b1e6ec0a0aad722561a657b32c771837934bb172c5e60445fda6f61f0549ad59d168a4a21c5ad207b7d947881fce7c77c2c558bf7d85da25db7933f453b6e11590535e632f05d2f265193b9649a5ef1618ecbe44f766924f0669492df39f8d13b141c3c5693f833d18242b72bcb57e7e060bce728ee6c12c1b8c82231a7efa18d9c9385b2a4b14339866bbd34bafab4a7cc7e6dc675bec351f64691ae0675794190c7171848de06ef9560cb93bd963649849e184ccf9b661423d2aef42d152a6744ce6c2706eb27a56bd81931fb0b15ae24da807c7aa33efa89f4760659c3931e68d37676dbcd6ad8e64a0f0b6ff3a833ffebef72be2857da7c20fbbefad3c0710755dd17badd9d086330be6b0297d0fd804a34aeab6728d2070e6393f90b7e2f24c098ac1853f441446cce5c977f35bdabac1c454ad75f42d53ffaa130b2c28a234a15ef11190bc97bcc8d0e99d5656d0891e3984baf383c021195a3f4accb96a873fe0d5c32a15e7fe92b17b2b8c3b841359f1b14625d34ce4c46a1c898e5b74301d7a21d399a47140b6711788aa4ac5bd9e63ac239ed45da28e932ea3acd6bd9f7f5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/44bf61ffe86491dc47531baea9f4722fed205885 b/txscript/data/taproot-ref/44bf61ffe86491dc47531baea9f4722fed205885 new file mode 100644 index 0000000000..517d32b420 --- /dev/null +++ b/txscript/data/taproot-ref/44bf61ffe86491dc47531baea9f4722fed205885 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2301000000aad2904b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a6000000003d041d050193d671000000000017a914719f78084af863e000acd618ba76df979722368987d0c74728", "prevouts": ["5b7f6c0000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "663a0f000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["304402206fa6f76e7f571b86a43f0ae206bd48cdd783d877db586d4f37fb4760e5c4980a0220618ca643df307b2f1380f43e2bf1a6765f434929345aa169aeb602cf4651a2e301", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["304402206ce32e5c2078e6996c69dc4263d8d2e08152b7fe43f583f89aaf4640cef0af5302206e2886860b00947eb4547ae247456ad24509c864d70af1623552bf48faa9629a01", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/44c41d5a9ee6d3836c4cd959feb9946950a93097 b/txscript/data/taproot-ref/44c41d5a9ee6d3836c4cd959feb9946950a93097 new file mode 100644 index 0000000000..8b550ad076 --- /dev/null +++ b/txscript/data/taproot-ref/44c41d5a9ee6d3836c4cd959feb9946950a93097 @@ -0,0 +1 @@ +{"tx": "2164258c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c801000000643e6ce4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1b010000002e5c44cd0201878c000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65633f05d", "prevouts": ["e17b11000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "ecc07d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e144d0ff37a890039c0ba21f76704f7cfad8b9e86a035546ebb7c5a6ad2c2135a28cfae4f24e00136258a4229df9ce1533cc743f70cc4e5c0214ad74c09f63cc0b9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bd5fb013d649a0b113a2236243da0be0326b44fd96f8b22737f30239849c7b4bc63b209b29a3611ab6267155884a7f894b498570c9db6a86ba3046458c9f77af637f7085334bd6ace67733ad5f759fad65febfe656f63b2b30abaed1d2ea29dc9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}}, diff --git a/txscript/data/taproot-ref/44d03ac572cc57f5a15470cd97f15bcb5b9aae1e b/txscript/data/taproot-ref/44d03ac572cc57f5a15470cd97f15bcb5b9aae1e new file mode 100644 index 0000000000..0c11333727 --- /dev/null +++ b/txscript/data/taproot-ref/44d03ac572cc57f5a15470cd97f15bcb5b9aae1e @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5c0100000075641680bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8a0000000017e471b5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf300000000ac1340c303f3d21d01000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79694c84f5d", "prevouts": ["ad2d7f0000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "7d0e7e0000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6", "9da622000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/disabled_checkmultisigverify", "final": true, "success": {"scriptSig": "", "witness": ["9a2f7f0b58db0a89e0561ded91d28df1269c2b5f285435e6da4020731219553731994f4e17695e91b6a424f2ba383093cac617f6c1f2c1e622d8d6d129e78aeb", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d2db232a58a684473efffe5f8be15c17374986169cf18c1adb110b544d48679b6f3543d66dd2934a4b4b5b83f3181725b5ccb68f1096ac62351c7c97bd1fb9501b8110e709da1864e3fbcb3b5249515c34bb807e7a52bfe6718950e769cad388c56ff404b78dc0a0b90d50115d89846b94a2b0a1f0895318a364e3dc179dd61f9b1e0d638a311a5be1486a7a4c42f89ed43ffd1d5b18820f631006aab35c0b2a02b593180c53027b35b862cc29f04a25efce114c7682377a83dbcf64f6fe42598064c72ae707f2b03b7d69f3c0306a0bb5edc9aa2d90aecbb96bd412d5b1ee8f00d68262204427d46410b755bc31a6012df0b06b921e6cd021b936d3d4c99eead90212921e1142bda8cb81c5ff3145b34391c40797432570ad9a88a0958a1b955fe09784706370c5f6fd13c48513ab6cc16af1e04504ea44462b93ae24aca3b2228a833ef2c51accd6ee09327b5cb9ad2975d597ee135bfef0964473e20f824ec199d2a72d3d5f5ff6ee974913584144656ddfc893ea617971c4925fe8b7e1c4f556906203221bddfee6deb7780e80a3769637a05bcf2efe708f1aaa4a6ffdc17363486d1e033637af9f6d28292a4f4527a2090bfcb5efca2ed9c0d63c01e16c98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["be73b35f48d93be86cfc0cf74d6d137772570bcd0a4f9d668ba07dbbd44f07e00e58c348cdaa53a47740620b9ad3de92bc80674de5efd8f33a2f0de0021553f1", "007c5120871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051af51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936163a2cc881d2817d2aebbfe172137e370cba72169135b49668e6c780f04e982af52d98203d7275fad400ed3b197c4c0e8622d77cbcb79cf7a2a00d2fc972bf5088fbdd48b7d094f4d49d8b1839b74dcc4dbc013e4a19a5571fcb3060ef9d19df09c62f41d049064138a9903b85876dd9717333b851facc249a6324496924ccd19bda959ee64a0e521086eadef560e007b812ea93c38fe6696cd23c9dbfec9561aa0b9584501d37df2cd6ca13872aa7d8e15f2d972cdc457728ab40ef8953a50d3001935f957d09ca50115598022aa673264713d6b6dab663f57d1ec4e21ca3f1bdd904199a671bb3071cf8c371a0277045925ae6969a91e37c13fd037f6d30f33fa29f5bf4150ae3c3f10f01b96905a4bda7f9c787f1e1f29b743fd45b74a0ded3f6d02e18608fcc5d3e47e21e030a7d2d6f4e266ec508f5b1b295a661225ac65f234c9d20f0c91cddcc015657641c02499e0969ed1c799bb7545acf49ce097d4bb8d89f21761581480cc9fb789613a87d31235185f9da4b4384725e898ebf0d2c5eddaeb8557ce0f7cc7880e698091ab104cabb34aeeeb5d0f57ea86d1ebc555dfde575d48d1eaafa8343c63d6f5425984d2425aca274be02e47a5142e089ba2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/44d081e51884f8d702e4373433bcf56a8a7ad583 b/txscript/data/taproot-ref/44d081e51884f8d702e4373433bcf56a8a7ad583 new file mode 100644 index 0000000000..5f905c01d6 --- /dev/null +++ b/txscript/data/taproot-ref/44d081e51884f8d702e4373433bcf56a8a7ad583 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd801000000e90e4673dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c17020000001ba48a0c0414137a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdbfcc93d", "prevouts": ["a9982800000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "c1345400000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902154269b2599e692e7e67455049f2a70cb852434fc1ab386df0f0e61f2e1fda7986033017a4113acd645d6fa3ff6f32f674dea0d97b1bee2d66bf2327ee1824c826b5212e5cf384eb0bd49c7175a7a4eac52c621a6d38fb842b40a6637fc1462170ecb40a604235e08652c2f4cb86773f405d84ddd92920485d8ba82ce2a2a8a0757df116d1e5dca6a64c4d59eb3081db86e2923a3458f00c9f5d5594cc4ffa6a358d5a4269845c3b36db8b044f2e33e52d567a39dc38efe3bc680fa9bb3d87077be5b3c71a06658795e499dba6f12260724b0e9f705236404d579065ed0e9c6adb4797ebe32688107f544bfc814561216dbdf7c679c1174d3048794b4cda9bf1a6dd7a43a44fe0f31b648af40eaa3e1f65f5bcd3fa20611d5ea5133271a1badc9e2621c4f7990cd54294eb375f77a6a6503b4d0944b9fac940cae17108a6de2ab9bda6023521ebd6e2734e4a6d932de7dfe21b1db6afa0074f3567ae0cb58144da4ad0bf76278a6a92f3e9be26ce18124b1a9e2fbf77c260bbd1b4d2a06bcced79478b2cace2232dbf4d130305d06242f702481f722cdd4765188dbfcf5110877db2b4a9934de0b6e1e788d68ee70adda3f9e8715a35725f99dc496c51ff6478ac3e60ae6f7763f26b0a011023d429220839400165ea82b02e138b0290038e39b46a53a632dac987fa0456355d524f41e1087a6852e10a72cca4151873f2b7a59932da8b975e8060fe75", "087d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8b5a7915446f123db4170aa52497de96e23eeb94b1c6e08805331c597130f97392ef61cba24ca089522adfb015944d93e6e298b3bdb8572d6b7e61874c3a207520a79ac573d08fada6e0a495a70546abebfe2eb256837e38d30334686ccae33"]}, "failure": {"scriptSig": "", "witness": ["4d090204e3625c781a3e70b2a310117b40d85d0e9bffcf3d61259962771f28d027f66362e244aee2c8d21aa0ac0987257de1036d92e23a5192bdb47b193286bb782146767394732dc303be0db1c7d25c3287f7c5ed49c4a3f2bab8e2d57bf07bc244b23abe30083d7e1f37433849d25464b3b5b744eccb0e8845f0ce82fb69e1a4b29026ab3ac1a59211f76b5c9254e441110d2fa814f7f61fd549b55ace752bc9c8be5e532fe394027b79d2349cfb1bd2adc6142769bd0494fbf48e5f07411123e0e58f410b653728553e502123eb35bc452e5eed2848b3a27f05be581a23acbea610e1b695feccababd08747aae78b03d75282bbf6f7f604e32599191f64d5c7fff6a907d053f9b7a9c10dcd2d5d4c26218eb756b64f2c0732033a3b9f94eed61df904e512080e7baa5e5e9781f8749407823b9526cc6ce63ddbdd3425e840a597087d3c0e82ad5e75c5d3cdf97604135c8b1dd0802ec73f982aa6207610d6bf21dbd9d0a95a35552430112b6e151f5e416b7e7be52291ca5d100e5105470a1241aca7eca11b74057789b38fab803477a113480e47f5a9a73f6638ddcfcb184fd36c0abf5302a1234d30a2b14cc844003debc8475770016ac37119a5e89af4fdc24e9b17d40d008a5be1f29a9e156a3be25517a3747a08d15a5e71c55a1d7265c204708df349d11119244284b379e64f5edf55d9c5ca2811a702323ff35fee4ecc248b262e827d8a00627a75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ebc0204111bf7e5d13e3ecd3b1c8f71c6ecf5827e1a757374a2d5a102d95777fd392ef61cba24ca089522adfb015944d93e6e298b3bdb8572d6b7e61874c3a207520a79ac573d08fada6e0a495a70546abebfe2eb256837e38d30334686ccae33"]}}, diff --git a/txscript/data/taproot-ref/44d277dff113e85feb1b0da733079ba007e9ce3c b/txscript/data/taproot-ref/44d277dff113e85feb1b0da733079ba007e9ce3c new file mode 100644 index 0000000000..1fa6a3904d --- /dev/null +++ b/txscript/data/taproot-ref/44d277dff113e85feb1b0da733079ba007e9ce3c @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c489000000005bca01bcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba70100000054f58ac701aac509000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487adb94525", "prevouts": ["3bde380000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c", "b5601e0000000000225120dfb9bbe67fbb4eb318568f7b177f9ecde078527d023b90a4ec13e543e4037efe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "f77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee1b135a17580d142a9191c3b85b2fd298f3e09062f6f11151feab86e1334277f9411b885fbcd56b4d2cd2e695cafde2fa2de7097172cb34b20e1fb870aea9a6a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93614bc388ca930cddc1c81a27ee7343eb0c7b6fd8e7416418176eb400a30a42e0c75fbdc6cf2e777e050e79c533e418db275d42efba7f8dbffba71190cfdc033660f5943df1a7722c938328966c7e5ac747f85bf050d43cd9195f6df88860ae066"]}}, diff --git a/txscript/data/taproot-ref/44f204855343e69fdcf5529e0a6cb7ea5dee9741 b/txscript/data/taproot-ref/44f204855343e69fdcf5529e0a6cb7ea5dee9741 new file mode 100644 index 0000000000..aff72888e5 --- /dev/null +++ b/txscript/data/taproot-ref/44f204855343e69fdcf5529e0a6cb7ea5dee9741 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49801000000f2d4614a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270130200000074abd946dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9f0000000045a6249304c5089b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acf499373c", "prevouts": ["31f4380000000000225120d7db2432b77440d39106fdcd5c35c463320f36611b8bc46e3633cb3a8d85086a", "83da110000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4", "30d0520000000000225120c3b9d8e50d42de1212377aa9427da72fe17222669efe5204fac1f05c34f6e65b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367962369c05be87b1a218c7edfefd1f740a3e06cdf8be2eccb1098b418ade5b5c"]}, "failure": {"scriptSig": "", "witness": ["6a88616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/452689d60be7f0c8bbd02b65a8c9841ac076b913 b/txscript/data/taproot-ref/452689d60be7f0c8bbd02b65a8c9841ac076b913 new file mode 100644 index 0000000000..aaf663ce09 --- /dev/null +++ b/txscript/data/taproot-ref/452689d60be7f0c8bbd02b65a8c9841ac076b913 @@ -0,0 +1 @@ +{"tx": "3969ed4802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7b0100000059dcb48ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4101000000052af5c1039b12b0000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acdb000000", "prevouts": ["a65d5b0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "6f45560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c2008843b41165efefa966ef86e5b17069112b4e8811936aac919af7c5cbfc0d863909619a9e5e3690b76be6b1d45a6f641895d036112b103d4a996c01584c34e2dd9164a263db053f999206ee7487ce868bb2edfcde9013ab8828341c83c1860ff9b2b65556c799caacb19ce7174550227ecda758458da932d0e28874d59dbf539e83f0021a1a7375fe3c6a9002e3118d86ec55884c001bd301c3d0640515a62d38b6388937e66e425417d7b1268e89e8f731508ed3b090b9de7d63503eeab79dfd2c9b9acd8446b8c7aca6888a4c3a75dcab570a0b8d5727c9513354522d6b5c2023d0e3d37a341987b71832a732c508924bd4cfe79e3561a5f6b7a6abbe9363d2a71ae58029ef1fbd00680c24e9517ef155cd72f728c2947ea2827403c3cca6a355993bb92d68b49226734d45854f1da196f489fcbe62de470f15ac1f37d969606c93dfcddd44bb850f4a47cf71544452081e2e184dee5f4a8636c24c800177fec87385add0f8f4ee3e5d5ba4ab562118af504ee97dd57732c0ec5e31972c869eeb6ffb7e3dbdcfd96528cdf8def3734b837b295f6c77887eddeccad8b2022215c07cdae9702d2246fa159483674c798d5394dd79633030de667839a72c9cb5eb3773f907acf000256cb7cdabf05e131ffeb16a9e490bca644f46a06e7f100905bed108a2bba43d702900ae46f0145bddeac952a85f4accb3b2d2643ae0a0c84d7bb392a8fc8c9675", "1a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8febf22132d9643e24ed9082227473dd30d4d39a0b990b222eadb4d87d4a2f8740b87aa3d77021654e9bdded249075f42755a492250fa9a6a44787c57353d93e356798b11c96dafc2935d577afad31a6537ce4b1a48ff27833822cff5fe95a51e"]}, "failure": {"scriptSig": "", "witness": ["4d0902b112b41944d8bd451ca6f3c4409a4448e82c100cb323999c9a9d7a5655e4ba06c52cfc49e90b3ac8054f4fb5a96bc92dd92f0bf377f0b2d221a10e0c78e7e0cf9c80713a75f1b7a66a506f1fb57e8471d263ca0cd6c052c5ce2d61f79503dcb1df6c9db66f71bdc182aafb5c9d4509461bcf23ba1d455ffa3cf473a61126819ef40002bbf682eff05e7799664e696fa123f7f1dc0b947d1caf4710c976656abe5f300dba88b76e6c9c02c37754dbebf5acbe50e495c5b275d2290051867bf0cdd8077b8fd3bad713be2d7db19e637f2eaf2e1943c1bad05e8399c8a82b2c2f28e12c8adb8719d0546bacb395d9674b872e4d1ccaecc0044d6fd2724c434ad345c9a4f496d7869c0adc35703b2bc3a7fb193e0e4c4f5297774840c5f7e238bf0b1f1a865a2acdea462ccd2988a3de72fe284ba74e371ecea2ff194b2f0b8f1490f8ea080d1a211ae006dddd8141c6f7c9d4d8dd88b039b823ad3248d6ad903b9859aa91b38459a5421956077025656dad3a8f328a837f9df63bc60e4d4bec481292c263798be4574565971f098f876c25eefa45f8f361449d43c0ca65e4a06dfd8cf16dd9533f919599b45300f89c92f9d21345dee13de8223a167de041716be99d9076c66c916fb4f9867ac0a96f1a37493c7c707d21384d0aea007de708e890945d6cd23d0326c041f54d9251605c6fb0fb985529f995a3e109fa54845a17999c1cf3ea4e9ea8bcfc75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3ff5c5d6186003b3e6d49f1c6ac4dc5a625cd45316b0701f0e70ab94b228af6df2727a08c83da142d000f7f66d34a23554b296f940ffe81022e50f50dcfdd8b9"]}}, diff --git a/txscript/data/taproot-ref/456d04cce86b68e35302afe4c3345e7531aa7304 b/txscript/data/taproot-ref/456d04cce86b68e35302afe4c3345e7531aa7304 new file mode 100644 index 0000000000..8e34a756f4 --- /dev/null +++ b/txscript/data/taproot-ref/456d04cce86b68e35302afe4c3345e7531aa7304 @@ -0,0 +1 @@ +{"tx": "5c3eff1d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4f0100000047cb658a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b400000000b06c21f90234212f000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac25020000", "prevouts": ["6abb1f00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970", "fd3b120000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09020a9ed6d0162fdc26a45d63ed84b116e59a5362606f5cd32f4fba084b119446c61d24a4a6d1bafe9b46a76a819927a541c99244a840cace3799afa924a348bbf31d303441b9e968c652d5dd0ed337604ec9bce7ef399c6ca38b45e324cb2b7fdb7ea38da7c59b4c210db0addbb1d4f040a4f5a9167081a91e95ae73f514e22fc5f170e66853b80373ca579ba03365a963ae357aa6facb72ff9a4958fbc63f40e04108b6069677614e99cfc4b1d6afa7b4f26b5aeeefe828f81571b16586ccf589eed7aebfd560c893971fca999b0e4024848aca661aa8002aefd678f3b668facbd7950facf098772c3579adef2e84eaac7fcfc34f558387d1343b57b66b89dd664d96ea9e56e7e69801c996d550fb5357a41dc4e9a3a6dfa56e76b607204ee34b4004c9feec2b53e8bfe30b9285ba2212545fb006b2e1ef0850097d902ef8e277807ddeb23c4c97a35ade7ba9910e801b174d3c6c5f5deabe73aa24bdd6f8070ecc63e3a40b2ede659bcc5ce00caa70e44481665c925583467c190f857d742fa8e3b1bad3133dcd1a2f5b460567377eaa7f5f5b431c6153c23b3b00936a425af67e60cd68c30bfa740356284d8f65f3c95b2ff5186e0718beebbc5cfa6bbd2aad45393e7918205f86fcc3d521e3dc430d76c548b1e134492af5aeb72fbc3a69382361a551ab370e01a71424ffbd2fcebdfc8b1928b8112249b3b3bfb9f5dde4baba70a687ef880e33457599", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51379b42341ec85aaea9ba53764a308ad79e21ba1c6bfeef93296a10f4c0e568eb3c50effc4608d2c714b1f589c510b82e2cb4bd2fb333954004903b4f08f38a79"]}, "failure": {"scriptSig": "", "witness": ["4d0902fc7ba2315efad43456443393f9eee65bfe67ead2686f2acbc59651624b753dae58d2b67bf211311d334a34761c9bd63dec663422fbb8c61f01c005f56c5e29efbb290b3b9ca5eb659c66c002ef42f452a0979ea19f3c2d11d8f023c151ff33cd338143a85fe818a812b13468ace78761bb990a13b8a4652a7c0be267747717d6f66c5ec05ea122aac2c4cfe8d1e36b277b388fe02d22e9882c3ece3dbe62c9231648e26ee5136a4672eccc74e7f29e9b9fe2c750c6593e8e5dfb08923bcc0ee47cf691c67cfc9273158d772fe6315785d28346e4b0118710fa3032fccd25cfa0a6a00b0e027ccceda6c8b1c72bc17b492d5dfc8f1c00c078359b65292d757ec6584f106800624b055c26e68fcbe76df8ccbfd3227a284f1cf99131edf1acc38f9f5b9a8b275c8bdfafe77634fd3ba2e59d482f06169cc091af4e82e700fad7fb66684c024ec55f8a35c909e336fcbc795c6ce6460444909fd0190b7e43507f88450b4cce6efc7ca9f0f027271cbd1812a40f1f7e320c84eed0fda2e26ac5d9524d0ac8b479ee89984fef260f3bfd1bd2ddb1cb4e59afabd34b7e58009248815d72a9553355b568faf0963a7c385c20f22b1f9da858636c938f6a99cfd4651ae70b711eba68e7b284977d631e98edcabbba860c28a652c267125675ebfe411f0af4e15bf8ef29fb0d3d2a695b60dce8d386ecff512402497845c3030b530a831d664be9ab0798e71ed77561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f4927cf48427f778f6164e8488ebda7b6882b6008ccde3c7191d70c6abcfa8cdcf0c734edfbcac159d7813ef9562f4df1a796390e1a91bb6f745d3b9c841d624c8fbf2363a77354fc9c61d01c3ea3e8806c47304e5a0571bc5a832b63c4c4c93c50effc4608d2c714b1f589c510b82e2cb4bd2fb333954004903b4f08f38a79"]}}, diff --git a/txscript/data/taproot-ref/457a9522f60a63cad613ce6f45ab52147b5a1871 b/txscript/data/taproot-ref/457a9522f60a63cad613ce6f45ab52147b5a1871 new file mode 100644 index 0000000000..1e69470fa1 --- /dev/null +++ b/txscript/data/taproot-ref/457a9522f60a63cad613ce6f45ab52147b5a1871 @@ -0,0 +1 @@ +{"tx": "0f80966902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0e00000000ea3117d060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708f00000000ee3251bc0203da6600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc722010000", "prevouts": ["a96a590000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3efa0e000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "dc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e87ec7f48ddb853ff8ec7c3ca68869c312ba33903dcdb15647a5295c052617846c86395c8bc923896e22972506a7f348d4e1ec7a5bf3aa363c117ffaeeeab3b8c4ad29df8a0e62e4f40897f8996914b12118c918ca2851b639742aeab01f587290"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fac1c00ca223002bbb4a77b296f490434ed2387551884308e16e8dfcb52ea12e9f3bfe8b0458382ba4f4ce4b13b8b707c198a710172b0004e49e202e4d70abaa7b"]}}, diff --git a/txscript/data/taproot-ref/45afd60d642320c756621d0d193cd27de023f243 b/txscript/data/taproot-ref/45afd60d642320c756621d0d193cd27de023f243 new file mode 100644 index 0000000000..0896b460b5 --- /dev/null +++ b/txscript/data/taproot-ref/45afd60d642320c756621d0d193cd27de023f243 @@ -0,0 +1 @@ +{"tx": "5bee4af203bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2200000000c005eba660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ed0100000060fdda93bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf65010000000bf347b903f07aea000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689872898922a", "prevouts": ["c7c87a0000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "d53a0f00000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "1e11630000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902ea30927e3351644c00e8bb9074d5f41820840987fa10657656c3ebbbf4a3ebb7c56246497e5735e52993543a5d89ab846dde66278d9ca099ae882db2da31b924fd2ed0fdceeb1c915ddc0246d99df59eede8544da09c20791208d8e9ecd6d46314991226ba8ccff2dd20f656026969338807e0899fe6d7b9edf6f49864e8a117b27ec025baa7c6a1dd154aa465369c3107e309ba0816c29e84a9ecddcb7bb2a7b1f2445e3230ddb8bdebfa4dc7fc1b70e31a9dd3b5aa063859970c42b1f55c3d3b4e9036ad3d62c50258da97b21415ab24fec02aa04f50c8f97dd8cf895482dff8478fef82195378d4154eaa26c8a77c4f2f4bdc801bf8743dbb97fd881f27b5434156e01060031fd1b94b3156379deee84bb8df2b8a8b2901d6174b259e72c6ed446915499ded265eb8035739a04158d7a8ced365b182b3ce80584ac3f4a907ce89d4620d84adb82c840b0c147d8da988cb882f6bb8fa49f048f35c2e3c88718e26b400feb458bda5793ff9b00036565d411b23be3ed84653ff5ff456dc82f271ba350867992674e76a6cf9e360538453157d00a1294a067c69f1d10acad95cf1f67f2ebaa58fa4e4ba002d862fe8a9b2af4b93e97d3338b556aae79a29e3a91c5ca2f99424b2137276b9dd49ba3b92f09f26262b5e29637ada7d1818b3de799e41d4dd052adfb4cdd89992e8d24b208a27f68e275d2b215dfb4dc1c5c90ef64ee0ab7d52589d0a2c75e6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb42f8e5029e924e7d935b65d329b99c619ed2851847f9f95e76ebd19c6b8448036f7205f064a536655663faab66bf2e716758d251376e4a55710082b6d7272244791bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}, "failure": {"scriptSig": "", "witness": ["4d0902091f234eccbbe679615d46a2a9889ab42a8c486ef6b0fb5066bd6792308d0242e247f4facf7248fe098628de1eb6c66b62104cf36216eea85acb3c0ed207f367515b19b6610ecddd1fc17e5cc21c9e753c2a422d1ca6545868270e7afd0c535936329513cbf0431ae42283f388d0c6cb8d4b03604318f066f7bc4e2c0329da075c6170363047da9328c1d87a095e33fd5e4d8607a607f943714bd888223391dc149735064cc3cd57292cbe9c01043c9c58d32427535deee94c01c6e8e0ac46b15ab4a641a86f88e2e6437e0ade6292037c0ac12e165bb208e592f0054b960c411e2e19c63f04bab79b5aba7fbd768f0ef2a6e9684a6b578aec52ffec2b104ad58403fe3cf9accf0be89c6879748d5c04adc986673ba8bdb3038cf00f0b5becc2870178991082c669049fd50fa5e9cabd137d6880e93bb6845e7a7f243d4baa6825a83e573fd8aa53f951fc6c536c415678d97201cf70d958ed41b0a5f1c2006f927365907cf31e64556a2f73c8f9c86a6a7101f8e231e5adffd657be1538497c37c04e4b2da53d877f3c70697e1a11177f3975bc5bb731d241c3ce1d60c66224716039b14d74eb4d79179c90777fbadc711d1fd4334005d9a979ca5957424407b950a2b8d00dc735387cbfd8ee1ca657615f2240c47caf35b292f76e4c9d5446905e07338196f5235c5c3eab5bf448adc14f3a9237d7b207bfb761408a1427a36f85cee5bd2eff0e7d7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936920eba80c2f9213151a31ef0a132999efa50e46ccfec391e06fd49d7fb9341681ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045bd4c1b076909910aa73b6afb36aebfd26014933f900bad794466c6fcd625cde53ff737734404bbc9015f34371be38b9f5376f1a60720e7cf7da81354011ad4f7"]}}, diff --git a/txscript/data/taproot-ref/45b86557bbe4fb210901de818886b7536f396562 b/txscript/data/taproot-ref/45b86557bbe4fb210901de818886b7536f396562 new file mode 100644 index 0000000000..ede9019c39 --- /dev/null +++ b/txscript/data/taproot-ref/45b86557bbe4fb210901de818886b7536f396562 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbf000000007c50ca91bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf94000000002da740f8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0101000000229667af01daee3f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963a040000", "prevouts": ["27a64c000000000017a9146db815d9819f256ca5d1e70b15558a98689cc52e87", "24147c000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "aff2740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1660142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["cc47afc87fe7e8d7b05810557d398c7c6f0e422d590854faf4d3aea996538b47150c40e9edfa5851e1f642438811c8380333a2d98b1d78fa264d476dd3011794"]}}, diff --git a/txscript/data/taproot-ref/45babb1803fdc9834a37bce496e989425e2fe9b9 b/txscript/data/taproot-ref/45babb1803fdc9834a37bce496e989425e2fe9b9 new file mode 100644 index 0000000000..de0447226d --- /dev/null +++ b/txscript/data/taproot-ref/45babb1803fdc9834a37bce496e989425e2fe9b9 @@ -0,0 +1 @@ +{"tx": "9264652d0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703400000000317b18b403a20d10000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd5000000", "prevouts": ["dc5a1200000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "fa7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692144fa78a37f9d4158f2341b3f64ea9d93b698f8b61fb7d7e21bdfd4d5c0b363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ef1076b289256cd19daa60d704e81db3a39e457bb71d9d0e29c4cb2075820e5e1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c5b5d638e62e1ee83083719c01950228b7d23e6528a32df7f751a90376aaaf3e9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ef1076b289256cd19daa60d704e81db3a39e457bb71d9d0e29c4cb2075820e5e1"]}}, diff --git a/txscript/data/taproot-ref/45c14cf9149717468bed37e1e419020555c5f927 b/txscript/data/taproot-ref/45c14cf9149717468bed37e1e419020555c5f927 new file mode 100644 index 0000000000..f9d5f8b399 --- /dev/null +++ b/txscript/data/taproot-ref/45c14cf9149717468bed37e1e419020555c5f927 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270db010000002e0520a960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bc00000000add0448a04b7351e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac07010000", "prevouts": ["c18f0e00000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "51ca1100000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["fa", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bbf1d1d3d3f3a5ef5765b8348d5c92141ed2621e0ac73cf7baa1850fff99acc06081f43f8c34257025162ccf1daca48ae61c99356c3eb24d5601d3c52dd9de2a6f5053dc49cb92d20c30fe5ab09c589302aa9886b9c794d18405aff33121a169"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a1d35e36d71f4211ee8dcb476ced8f16f1af9e215de664588adfe8e8df5b115526ad4257a22b62302a767a5b8896008d1af7055b6fcc30f1a04cbcad06de5cf2f8b8afd7beb88d43ca6c6d2d58dc9425172bd95ccf582b2eeeba83616a9d27d33bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}}, diff --git a/txscript/data/taproot-ref/45c97ab53324162e66ed1d4c64371055d966b691 b/txscript/data/taproot-ref/45c97ab53324162e66ed1d4c64371055d966b691 new file mode 100644 index 0000000000..0b32c6da20 --- /dev/null +++ b/txscript/data/taproot-ref/45c97ab53324162e66ed1d4c64371055d966b691 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba101000000a9a32afc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ce00000000d3ee6bbadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf600000000f28de0af0335865a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb813d458", "prevouts": ["5519240000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "15bb0f000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "0239280000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "d47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8b970f6251c63bb7d52d2f522a2f2041b3457429d11106abd9da97a7fab7a15d238c2fd1368e2cc97a2933efae2d13561032948a77b2cd5d87b5e0b8010cd9f32"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dcde3d867c97d7a18e651bca5f63606f08ff12019e315b301fde84bc4d24cd8ff9197423ce94fe6d3a105485c3c73b77ffad3b95ed69b8a8a6b271b9e98a9e69ea84370bdaf8fbfa2c728119f306db95ff534e2e627fabf0c000f69380d4e93e"]}}, diff --git a/txscript/data/taproot-ref/461af17d337077781b7e49d203e17cf7cdd7781b b/txscript/data/taproot-ref/461af17d337077781b7e49d203e17cf7cdd7781b new file mode 100644 index 0000000000..3b973c0ee9 --- /dev/null +++ b/txscript/data/taproot-ref/461af17d337077781b7e49d203e17cf7cdd7781b @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb700000000d737d52860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d300000000aa1153480339fd2f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796741c1828", "prevouts": ["d3ed200000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "6e931100000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363e76fda838f76382ae0d0bdb253de0cdef8bb5a3eb9bc3b2e59c371abae55d530d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3f2a2968b4ea0558d79f1ec3cd2b8a530982c6b5ad0be17180e93d11bc09903133cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361cc0b7b7d6ad7930d95e3200c68d1443ca9c709d86c4485118a6574c598e644fc145688b3898d8a1374847539a36067c996b07f78d82debe95e7e288000a7bb1b9cd72275efe6b477d9cf0b54cc21959221ed58300fa90def59e56d53bf5ae178c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}}, diff --git a/txscript/data/taproot-ref/464a9d31b63ef5f4fe0f193acff3f7a8251adb7f b/txscript/data/taproot-ref/464a9d31b63ef5f4fe0f193acff3f7a8251adb7f new file mode 100644 index 0000000000..29647b92c9 --- /dev/null +++ b/txscript/data/taproot-ref/464a9d31b63ef5f4fe0f193acff3f7a8251adb7f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa00100000085aa13c060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e70100000090538ffa0198587a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964401975a", "prevouts": ["395b84000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "69b7100000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["ce", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900455067193501824fc7e1f7f904c1e32fba78339d7701e72316b16feebc15a414abab692e734634bfaf43d653c1e6f6d8e8d14797d8e4fda7a04cf5eec270202b46d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367d1fd0be73b6182e4cd51ed7a2b120ef2cd5ccabb8492e6bf7f26137f064f14b8def8465bc2f3cbc3837b9c231547f51d7c9e247c478e05a849822285048dd5e0ea67bdb3398814286540937ec364df004af879f987225ad05d036a51e8223e6d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}}, diff --git a/txscript/data/taproot-ref/4656d9b9e1003224e094622d9723247d8e53ca72 b/txscript/data/taproot-ref/4656d9b9e1003224e094622d9723247d8e53ca72 new file mode 100644 index 0000000000..07c24b4fa8 --- /dev/null +++ b/txscript/data/taproot-ref/4656d9b9e1003224e094622d9723247d8e53ca72 @@ -0,0 +1 @@ +{"tx": "1f1a48c703dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9b00000000fdf160f9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c03010000009968b6f760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270150000000060f62d8a013c37600000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc85000000", "prevouts": ["5a1a200000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "f39b5b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b0fe12000000000017a914b0b53ba433a336ced94ed75e23248458a1c69fab87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2252202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["fba8faafcf8b7630fd262a54ff27f6dd7ae88c99224d5ec07684f74d9e49fe888c0efe36ef2e1d2bb45d110e5dc454e7826a5f40f50f158e6b10389b75e0f6de", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/467ac05fa481edab9bf207738a0fdf308bb097c5 b/txscript/data/taproot-ref/467ac05fa481edab9bf207738a0fdf308bb097c5 new file mode 100644 index 0000000000..98cf273400 --- /dev/null +++ b/txscript/data/taproot-ref/467ac05fa481edab9bf207738a0fdf308bb097c5 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45f00000000788b972abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf02020000008b773e1560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702b00000000fdffac0001b6184e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8721010000", "prevouts": ["39113f0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "8f097000000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e", "d0ef0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_4a", "final": true, "success": {"scriptSig": "", "witness": ["afca39b475d08f31f02c6438e4e3ef89f87a5d88b9653c638a2dd902b3ddad93515dd0ef8705f3130f913d7cfcccae267ca87bd72b40796166c52b630fc70bd402"]}, "failure": {"scriptSig": "", "witness": ["a00c7c0b622457becddef0664e7b133699f813a54c5a66c7778b4e3f0e704406820e9a11a2feb0a7449e51fdcd2844b9526915df881fcab0a0396128617bbf374a"]}}, diff --git a/txscript/data/taproot-ref/469213f3d0a4e2171977ef67184aa5af2a7d259a b/txscript/data/taproot-ref/469213f3d0a4e2171977ef67184aa5af2a7d259a new file mode 100644 index 0000000000..dd6f0e1fd0 --- /dev/null +++ b/txscript/data/taproot-ref/469213f3d0a4e2171977ef67184aa5af2a7d259a @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0d02000000419a5faf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45e010000005e59f2d60130516600000000001600149d38710eb90e420b159c7a9263994c88e6810bc72b000000", "prevouts": ["73ad7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "046131000000000022512094bfa417ff7fec0e1f7b84edca83ca6ff73ff5ab901944aa69a26f9bdb9b300a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_43", "final": true, "success": {"scriptSig": "", "witness": ["d4634c590066bea2959548add44f4ae748221bf303a7f07f4745efb4e1955ee42f2e834c20834610c24d9cdf32adc32a97088f33fd3f4edd9148eec585314ade"]}, "failure": {"scriptSig": "", "witness": ["88728b962159bffed4371671c2d066c044a618f74c657c6b8c85726f35e276f432f9b08211f4ba207b8133b661c5b702ae66c53347109789524bc954f8592ae343"]}}, diff --git a/txscript/data/taproot-ref/46a14a2d2ab594d5d1917b16120cf28258bcd02b b/txscript/data/taproot-ref/46a14a2d2ab594d5d1917b16120cf28258bcd02b new file mode 100644 index 0000000000..4febc8f985 --- /dev/null +++ b/txscript/data/taproot-ref/46a14a2d2ab594d5d1917b16120cf28258bcd02b @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf59010000001611e3da8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4100200000040147ee90150805700000000001976a914c629d61df58baceae110d15eb5b55e144268615388acc4030000", "prevouts": ["854e6f0000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "53a039000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638568", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360696f5b4f1dd7045c4bac67803efea85e4be4911fdec759a69cd2bdfd360ad05717b4e30a5884e3e55754911c167a338fe4fe766d1d9ad9fb23fde5d0da8b2aeb2a240b376911c9876b3695f79f395ec3f2d97b1695e5c0e7f397f1ed982e79a1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366fd39b63ba8e52e90fd8a07b9cb05832c173e8838fd172658667cf8878374d8c952384bfcd198c969b60204543b8b578741ae3068409132e955e5c7af181f3d3734b3a7050eee065844830ad8d45a710891f78004f5e7f35b8fd72bf3ee94449"]}}, diff --git a/txscript/data/taproot-ref/46b30a46669909d38ddfd379180d9b9e4b032d30 b/txscript/data/taproot-ref/46b30a46669909d38ddfd379180d9b9e4b032d30 new file mode 100644 index 0000000000..9636a99fb3 --- /dev/null +++ b/txscript/data/taproot-ref/46b30a46669909d38ddfd379180d9b9e4b032d30 @@ -0,0 +1 @@ +{"tx": "b516eae002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3801000000c3f7c6c8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8800000000587ace9a0352bb73000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4872f7d0b24", "prevouts": ["9917220000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "91ee530000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e7", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368f5cdfcf40d08d1ee6c8b33ae5ec5247fdb56b1282308d0d349b07692bd5bf381ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045809bd2604b63a9913b428e9bd239a7888c90ad67a336710c360335112147f5da391a14412c925771c32fa4c7776d5872be2a56fee9c5a8de868e7e6e5a4c84da"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4dbfe159b7f074423d2fa61e8a9b5231056855b78cb68876c387837662b8c070f92a4f502e305109d81040f98432632ff806e9beae33e8faa7e022234476532106df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}}, diff --git a/txscript/data/taproot-ref/46bf3a742f868512007f33d6092b25ad9851abc5 b/txscript/data/taproot-ref/46bf3a742f868512007f33d6092b25ad9851abc5 new file mode 100644 index 0000000000..d38e69d741 --- /dev/null +++ b/txscript/data/taproot-ref/46bf3a742f868512007f33d6092b25ad9851abc5 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9c0100000086f844cdbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf57010000000f4c07bd014c2ab2000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48780020000", "prevouts": ["ab6b560000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc", "09216e0000000000225120460dfd59ffac97f33cb704e62d40a80655c52408ecad6b881ea54a9bb408923f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090247300d269ff90ed5a8fc056a9f4039ace7956bd2266496c395b3f3bf081860e552a40053b948e6efbdbba3519c987fd8b22f029a3c6ed021aecfc84090657657308dfc28c4e589a5690b2a59259903a1d31f3df33c5a0b0c4f01fd370a439453e105749b95ff347b880234267c6b3f0e5e51e77e73a3b6a4750307b0258ab93cc3e20bf6a4a8e2517dd738b729836a4597f6467f665562c9d287f1d34c013038cac1c435d768fd42150a3a691acf2429439f47c3f3ae261a0340895635c2984af00cbff42e287276f7dee31d6da2db71ee5b8f8a921f2d63f749a41d1d99cbcc03e5ecf1b38f095daaf28d144ae432343e55692abd16b01457c5f3eb27fe7bef3817b71d6d3aaa575d5183fe3d85b886966b183bb59162e55060dc25b85ba8ab98b3b36fb62c960ce82cab0d6e66e4dc5a2051249fd7aa153a0945c2574a772cfd85bfa78ca18b594948c391d4b1d72ea544875fc54fddc81a66cff18f5992aa23493d78edb4d229bf84ef70e3f262f5eaa66e6b48045931bdb0136115ab78ebb65f9add46efa738eef38c0178a52f386cfd733dcb92b606be4d38b051d77136651f4740024bde98733a46153c83ef1bce9c42c9c0389a4ece0109e5aba1eebbccf4ee8eaaaa0ceeb05f08012b322ce8536dbc3261806d7b4b5ce8ac40ee87df3184ee1f4e9fb6b37a38ecf1627d9cb494d9077d4448b8c23f2dcd4f7a031b73eaaa6b14ae2c0790cd75", "d67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c254a8ac6899858608f160ab69db89bb24ee8208e13d5ff22518d57ffad270f18a47f828b5683f18d8d2a0301cf32ab60b8042f73dfba3f43f347d91ef120fb4bd0211bc754da142cb3564162304068e34e33074851a6380a45a2a3191e3f102"]}, "failure": {"scriptSig": "", "witness": ["4d09021df5defed6b9f3a531496d7ef3200d910bd8f37c98089593d53cc00aaf846087b410b368f872fec06c4fd320cadef3f0c360361fb8818058d67b2732ee6c0e9fc00620a25bcd84be486f363566796320a62b31cbbecef30406a07c134f320b997a64d98b2b24d418a3d6a6042bc7e916f3d7a7dfdb84c867f7b30e5f35337ff6f8f33453eb4aec5605b47157fe0dfc4ce3873ba6319249c04fc558f04a57dca2c0bd2948b68f2c76dcccc261adc60c77815d7f3852b5a642deb5b650ea487c8cec1a8184e1773a6e5a6be17fbfdae06f442263328bccbe1aa37f4620c4533c1c9d2548c639c2209ddc2da85d985063b304e83d97a1f38319dd37d2906ee4c46d159ee253e59f45e69a6ec34d739e141c939036ab8f2f049342f5a34e69a2a3afc0e2b767dd70bb119499639f356e64ce4a9bf10a0765b35ef1165d3f364e50df6d75a87ab3987708f1c3133957bcd0bb552427c0b1f1d352bb7f728f30ae5fbdf41bdf7ea0646087a1f576ed884ced0e3863582203ad85f357d8f227c39b13d607c43037d77e8f1b21356238f8e515470b78821c9550c5f453483e1ad75d799da93e6e9865fec07314f67cb51787c5b86de39718271ea8dd5b44a18703dafe8c8d1d36039351c90bcf7adbb1b1c804f334d708eb35f889da72fdc94b3938c414c9011870ca102d6c8c8bf4fa7a3c2a05f38f19168a124086d7fada507279699a48d38aa8a60b147bd175", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faeebb44c2a26e7d04d06be9441726cfca165ed247b802be55a42fd4c1a57db75ef0c0cd32dca2782b49e872f77a6f41a631e1b6bec2669bf2370bfbcbf3d4a769630d95c26588949f1b3ae4e4e429080b434b995fa18047406852c727cd9e6feb"]}}, diff --git a/txscript/data/taproot-ref/46faed608cd8553355e705736f5883a865bdd1c0 b/txscript/data/taproot-ref/46faed608cd8553355e705736f5883a865bdd1c0 new file mode 100644 index 0000000000..cfa591e1e1 --- /dev/null +++ b/txscript/data/taproot-ref/46faed608cd8553355e705736f5883a865bdd1c0 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46d010000007fc9e944dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd50100000032d28935bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9401000000353048d30172b24c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ee4b014d", "prevouts": ["17883d0000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "4e40240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c40a6f000000000022512026ecbdce513e5cfeb779eb6a118aa90fae67510c7ee9bff64af6ca27f9068c2e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["994c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367643e13e483d98b5cb4a2dd9b2a8baf365ffe94859ab503c911dc21978e6d7804c8fbf2363a77354fc9c61d01c3ea3e8806c47304e5a0571bc5a832b63c4c4c93c50effc4608d2c714b1f589c510b82e2cb4bd2fb333954004903b4f08f38a79"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b39e544a8e3d2b207cd38626a9bebd6ccb5f06d994574d73902ada6a510f1a46d85ffea93b39ff48f026a1de615f9bd5d9d5cb27805fa051e581b49afd71e8d341e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}}, diff --git a/txscript/data/taproot-ref/476140a4869c363ff59de15ca0b3dddb33ee16ea b/txscript/data/taproot-ref/476140a4869c363ff59de15ca0b3dddb33ee16ea new file mode 100644 index 0000000000..43553778eb --- /dev/null +++ b/txscript/data/taproot-ref/476140a4869c363ff59de15ca0b3dddb33ee16ea @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cce00000000e19e8a348bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ef0100000011e89353dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c02000000b3dc5d44043c69d900000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac92010000", "prevouts": ["d9e6520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8f6b320000000000225120d70bb5030b4517d64d2a3c38713515b320a06334d0ff9db76c903984d8e384a2", "bcc555000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "success": {"scriptSig": "", "witness": ["7d160ece680f4a8418caf812fb42769b5e408a02105b9a68896ca83a3171b8a53cf93c9ad110707d9e14d443259d5d290d65209d9000c9004312c9d2450a212f01", "0932f4f5d101937a49b2930a1d013cdc91254422cbfcf6f75303c2819f807770914d758b7a9656f312141aa9194210761099ab021ccc7330a2cc83259482407f1684db0a0b3a460b0f3633fcb20f3250353255562bd39c9ac2ddec7ed3ccf2bc2b80f07306", "7523fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661c8486f195c1a3ef65b05b37e21a103ce642eeb740a8caa78a5c1ae370e33e4badc187240961080422bf8276f0a29eb125316a15ec8974d553de5fce36f3bec253415b71957175c16169c49198cd3f0a862455b885e0e35e372fdad520e05c077c3f65b74130262b35e7ddcb26a78aed79f034d7bd147773940bee02cf44653904a03ada378a2a6776c9b245e4a0092001043bfbe5bfd30e518ea25f18ac33ff7f4e9e15e76c636b150da06993b5f6de96a2e1fc090f2c7907997e1d5fa996a51f24777e7b300f38d6ac44a3faf36c476f4e61fd05c7a39a19b078a2b755ce8afa3e5e87451f40747520aa94b1c95a6038cd1e021072105441c983913767b9a3bb2766bcac675bef0bca1c7bda289c172bc7a7a61650a894ef287625c85677a18f2a30f20b7667ceea24effea42161391d26cf59961eaec6d3852f2dd899663ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb475c2965818d83b7e67d20b694a799e76d91799e7c9d242e585855f03d1b3f3a317c237fbae01a7712c5ce36aae4d53315cb1f6d58a4d4a7268d3ee086533d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffead926b6aaa264f5eef0c2799d712a273681ef3c5162836847eab383546f5ad83da61e004ebac3f4f176fc2fc0c028c8cba9c118abc2ca84e97e1628f00a76f88a9fe018c5a0f50159624ac39dd70cb9487a42ea86e1ab8f7384ea643dd37714827b4b176729dbc4c206dacf4816a37404955c1bd1de44b38c66210020711ff4624343830e54cfb3610465196c2c7499f5c337c03ec74f3acea427504fd7e8a8b0ee0c43bd6793d1598918c2dac05c9908803c7b523bcfd439579d1dafa142fd5f51dacee2a17a5dc8efba06eff0416613cb73850b2889c267f9ef13f780748642ec6bae520583dade36096f88449a4e0166653db943e03b0cab3a9847762884ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff860e33487a6aa09e54aa4f342cc7a411a8ef7f6afa6f34d822f4dd0f7e6978c7fa71a1d448e576f7bc8eb2a93f77db90f74289c7b16bb694e2f60c2ae7af96efa4e741f628ff10a1d626052c5b96dd204f2eeee4144e384fcb0f1909b6f642fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9dc24862adb5cce7096a62db5f314c590b5340a9a69760d3ba528c6f4861b35301a20d17517777d4ce8a96339de05cdff73e4c7918682ead0cdd9afedbe6df38ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff28c226ed3ff213133af90d017729877c6ca93ea3d2f4c4ef04cc926a7d2c9dce6b90123d0c13965cbc94a8640b832dc9ecf220d399fcdf833ee978188a0e35e1922ea0efc49e9c9ea2964f58b8825b7edcafeaaa29a53efc52db0e01650091a9e8587a191ca71cf2c3286ee45fb294be949e05e0ace18dd6f0b004f85420edd1eb26af0a5fdc50853c20222041699340e30804b62ed136f631ab79b2ca6e2399c93b9c6ae7b93ec96914f7845b510e34d6deca37679658371c2ed877f0bbff67ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146423451ed710d7875e782a5aab0af9c9ea2f5be99c037f7f68c80f19bd6a4d9b48ed8147bf711ea1497e58e2b87e37ccd0c69af656d39595032a9358ea9167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcb410f2dc5ef8ff73a6320dfac7906626a65cafedcd6208c29103b800d8169ec0efa0ee3964ad3fb78afcd63d08e12dd4923aa3b8b702f7d4d59f7f16172d2ab0000000000000000000000000000000000000000000000000000000000000000fbef2d3df302890842449802b25db8f790749e3fa39301a71efca2eaa0ffe0d20bc08cdace3b2cb38cae679a43fef7183c04d1da78593e91545bd1516babf780e4a1283f5fbe1e73fe0c924d0e63b8250355f37bdbdc68bb59d43746a54e18a3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff593d259514a1eea6eb45841da20e8538cda29e9c068cf2bbf9f6928942e8acd1e03e21750eb40ccf85663c686bf9c9f5a7b8c00c308b081883cc8b3e5a2fc573b30e90f2428c17ee7c54b30800f70536049cfcf3ff7a371d55cbd3255898b068787f39dfcfb5de7a52763752d75e73ec9f49d5be2c6c6b313e13f7c716a4a1f114e6c43d920687090561e291bcc0a781bbe20849c55303416cd89bfb48b24ebcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b1268a56dd0c7e5973326b41543a37308d8a4e6341fa595bc8ff6281316871878caa4516115d1b43b10e9f59762ef9f6c0c07dc30d0d01d50ccf4804af19ccd4fe104c9600bab531746e5efef35e26b6c138b46f2d68f01da70c1a65c0344d224b5e9006c7d5087bed656d559dbf12820bde2f21c6f6add8b4da618eaef8e090716b0ecd7aa43e45edf6bf8005307b8ee94c9d0ea4d0a4c67c652e5cf415cf40ae826539b2dbd0c39086794802b427f7e40aa1846b5973570f402c043dfa2b1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94eb16e8928ef2c98a9739e333343d1c8f559841efe8379299e82c553ccc6ec926f39dc306592ea8ae4de8ce433a4c25f4deeda2fcbd2c2b45b7c0a29f35ab7600000000000000000000000000000000000000000000000000000000000000007359ed95dcb850fc1d84b29b77a5df73488d568934f5d8a345296334750d6de3c2e5e21ba55fb31bb677804e259424c38866491a0dda2e316d998c1bd68a82c8cf37fd5412e92947c5bdf1989938f20fe49730eed2b693c9aa6a330546bda40400000000000000000000000000000000000000000000000000000000000000000f5bab539dd4dd5a555188568ac4b1cbdde0e4123d7d118d3c31408a3a7ad3b6e7cfaddae4283aa121d19689597dd5ed0256579d7ab8a9fe416aa1f15cdfa00e", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["7d160ece680f4a8418caf812fb42769b5e408a02105b9a68896ca83a3171b8a53cf93c9ad110707d9e14d443259d5d290d65209d9000c9004312c9d2450a212f01", "f92790b4ebd08bef1de8e1d9a8afdd70938b7507ec1beb7c02216dec03e01d1d912b194ffb1fbe579ccf9980c1f9ac8d570eebe418c98a5037d8b0884595507328c5bbdea1015b055b74a4618fcb3e0f1cca81132b9f120f67a23c51161b186a7630baa6", "7523fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661c8486f195c1a3ef65b05b37e21a103ce642eeb740a8caa78a5c1ae370e33e4badc187240961080422bf8276f0a29eb125316a15ec8974d553de5fce36f3bec253415b71957175c16169c49198cd3f0a862455b885e0e35e372fdad520e05c077c3f65b74130262b35e7ddcb26a78aed79f034d7bd147773940bee02cf44653904a03ada378a2a6776c9b245e4a0092001043bfbe5bfd30e518ea25f18ac33ff7f4e9e15e76c636b150da06993b5f6de96a2e1fc090f2c7907997e1d5fa996a51f24777e7b300f38d6ac44a3faf36c476f4e61fd05c7a39a19b078a2b755ce8afa3e5e87451f40747520aa94b1c95a6038cd1e021072105441c983913767b9a3bb2766bcac675bef0bca1c7bda289c172bc7a7a61650a894ef287625c85677a18f2a30f20b7667ceea24effea42161391d26cf59961eaec6d3852f2dd899663ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb475c2965818d83b7e67d20b694a799e76d91799e7c9d242e585855f03d1b3f3a317c237fbae01a7712c5ce36aae4d53315cb1f6d58a4d4a7268d3ee086533d8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffead926b6aaa264f5eef0c2799d712a273681ef3c5162836847eab383546f5ad83da61e004ebac3f4f176fc2fc0c028c8cba9c118abc2ca84e97e1628f00a76f88a9fe018c5a0f50159624ac39dd70cb9487a42ea86e1ab8f7384ea643dd37714827b4b176729dbc4c206dacf4816a37404955c1bd1de44b38c66210020711ff4624343830e54cfb3610465196c2c7499f5c337c03ec74f3acea427504fd7e8a8b0ee0c43bd6793d1598918c2dac05c9908803c7b523bcfd439579d1dafa142fd5f51dacee2a17a5dc8efba06eff0416613cb73850b2889c267f9ef13f780748642ec6bae520583dade36096f88449a4e0166653db943e03b0cab3a9847762884ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff860e33487a6aa09e54aa4f342cc7a411a8ef7f6afa6f34d822f4dd0f7e6978c7fa71a1d448e576f7bc8eb2a93f77db90f74289c7b16bb694e2f60c2ae7af96efa4e741f628ff10a1d626052c5b96dd204f2eeee4144e384fcb0f1909b6f642fdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9dc24862adb5cce7096a62db5f314c590b5340a9a69760d3ba528c6f4861b35301a20d17517777d4ce8a96339de05cdff73e4c7918682ead0cdd9afedbe6df38ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff28c226ed3ff213133af90d017729877c6ca93ea3d2f4c4ef04cc926a7d2c9dce6b90123d0c13965cbc94a8640b832dc9ecf220d399fcdf833ee978188a0e35e1922ea0efc49e9c9ea2964f58b8825b7edcafeaaa29a53efc52db0e01650091a9e8587a191ca71cf2c3286ee45fb294be949e05e0ace18dd6f0b004f85420edd1eb26af0a5fdc50853c20222041699340e30804b62ed136f631ab79b2ca6e2399c93b9c6ae7b93ec96914f7845b510e34d6deca37679658371c2ed877f0bbff67ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146423451ed710d7875e782a5aab0af9c9ea2f5be99c037f7f68c80f19bd6a4d9b48ed8147bf711ea1497e58e2b87e37ccd0c69af656d39595032a9358ea9167ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcb410f2dc5ef8ff73a6320dfac7906626a65cafedcd6208c29103b800d8169ec0efa0ee3964ad3fb78afcd63d08e12dd4923aa3b8b702f7d4d59f7f16172d2ab0000000000000000000000000000000000000000000000000000000000000000fbef2d3df302890842449802b25db8f790749e3fa39301a71efca2eaa0ffe0d20bc08cdace3b2cb38cae679a43fef7183c04d1da78593e91545bd1516babf780e4a1283f5fbe1e73fe0c924d0e63b8250355f37bdbdc68bb59d43746a54e18a3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff593d259514a1eea6eb45841da20e8538cda29e9c068cf2bbf9f6928942e8acd1e03e21750eb40ccf85663c686bf9c9f5a7b8c00c308b081883cc8b3e5a2fc573b30e90f2428c17ee7c54b30800f70536049cfcf3ff7a371d55cbd3255898b068787f39dfcfb5de7a52763752d75e73ec9f49d5be2c6c6b313e13f7c716a4a1f114e6c43d920687090561e291bcc0a781bbe20849c55303416cd89bfb48b24ebcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b1268a56dd0c7e5973326b41543a37308d8a4e6341fa595bc8ff6281316871878caa4516115d1b43b10e9f59762ef9f6c0c07dc30d0d01d50ccf4804af19ccd4fe104c9600bab531746e5efef35e26b6c138b46f2d68f01da70c1a65c0344d224b5e9006c7d5087bed656d559dbf12820bde2f21c6f6add8b4da618eaef8e090716b0ecd7aa43e45edf6bf8005307b8ee94c9d0ea4d0a4c67c652e5cf415cf40ae826539b2dbd0c39086794802b427f7e40aa1846b5973570f402c043dfa2b1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94eb16e8928ef2c98a9739e333343d1c8f559841efe8379299e82c553ccc6ec926f39dc306592ea8ae4de8ce433a4c25f4deeda2fcbd2c2b45b7c0a29f35ab7600000000000000000000000000000000000000000000000000000000000000007359ed95dcb850fc1d84b29b77a5df73488d568934f5d8a345296334750d6de3c2e5e21ba55fb31bb677804e259424c38866491a0dda2e316d998c1bd68a82c8cf37fd5412e92947c5bdf1989938f20fe49730eed2b693c9aa6a330546bda40400000000000000000000000000000000000000000000000000000000000000000f5bab539dd4dd5a555188568ac4b1cbdde0e4123d7d118d3c31408a3a7ad3b6e7cfaddae4283aa121d19689597dd5ed0256579d7ab8a9fe416aa1f15cdfa00e", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/47678ed5dae9d91220f82b512192c03161458d96 b/txscript/data/taproot-ref/47678ed5dae9d91220f82b512192c03161458d96 new file mode 100644 index 0000000000..6b53460080 --- /dev/null +++ b/txscript/data/taproot-ref/47678ed5dae9d91220f82b512192c03161458d96 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0302000000e24818d4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9000000000f9f348ce017c48060000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961c030000", "prevouts": ["dec2220000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9", "964c5600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b21cd3eccb1078808f504a0ae9d7c98d8587addb87e97e44101fed206146f041397c930f8b1a350a59ca429b0fd379960979d81cfde5ec584df3b9ebc58890893eea997a0110941a5969b29cda4ab73ccfa6f2fd6e912ed2c1a2d2967497c6fa4915d9725d4d8db5018b5c71ac226416665c86e6e588f7af4bc1f346c66c53c2f2e96c2af1abecd7ec70592c666b70af2736296507164e3a59e0554b9ed47a8b14c678ca98cb4ff6e74801a9057f9ef2aa64047316f13310422c564811bc57ca090c9e7f51fa6e58cf7c2ab965cf4deb74ef5b8f205e30158c7918625b9e004e0a6d7afe29e77c8a5b7d39dc48c521b3c2e0e56a90a7290f68a7a8e9cd2259f6af255e941ddf060cb57c34d3f8692d1eb2d40822c90b741229cb84deb42ac72d6164d94a5a5bc6b42dde89904edbd913771c68e817d4bd13ce172171d532edb3927a967249675621a2ba38d32d4c71218fe8f7eeaa4a486963b0f6be94b9df3082a5bff5da77ea999c39f1886fbe83b65c3c294bd84d923931966794f0ed4c8eb2275e760f51748790687e4eddd8f48fdb5bf4b387de57a7f0ae2bdc5ffd7161bdc8337bb78f423569f0fb3898d21833e02384be4ac11a8f8ff0457ab59b60b870d015fbfe17bf01c6d26bd54a822ddb3265199a0e19ecfe8c163206e432e92c1b6b16b633663741e6c9c7e93c7ec5e072d717e28fdf36b6c22688a4692cc3086ce41309523f20962775f2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936855634eaecdc9d9ac50e15cf1cceda1e94c28cba9dcd92e65bcab0ee1c3b94463493aeab6959567855d46871d1975f827c269435f7c9757b13dbaeb906d5d20b01b5a419c18d23e8c03ade77009761f1ea37c255231895048329572c11717ad56187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}, "failure": {"scriptSig": "", "witness": ["4d0902ec2584955cfcc968f1671bc170893f3f1d670ae5f3bace663ba6a17899595941ff280165f60d561d360401efc472f2dd97f8b59e3b00925e42a1abec8e328ae896f35511e1dc83b8186dba62a5df93c4c5793fcb840e7eb24f0baa740fb35e170fb4c400ee08ac5023a913d1b21796d5dd74de8da6ba15f022a7400394750208cd8c7b49645be052dc0ea47498fb67d3ad7ac2b813992b7760a9a93a6863f807aaf4686f7ca4bde93d6f05940f17586d42cc57a7b1d40702115b04335b56e2aca100b328fd6c49b3db208564066ea7143a53bb9a9eee9780ba43ade0b77cc90cedb39c7a9152fa082ea04e62812bec435ea21455b5a02994b3c281bd79529203a4984ec581ac07c954af11c32a28638ffdfdbc4d21e47af66c0ed217dc1089dd667d864339d10e8b4bb0998c928aafcd6d05549a54cd2699fa2f3b254f4f3f502d2f6a25988e244b0df660f8c726d582d28db295aeceb753da2bacdb958651029b46541aaa6e3cf630ea2371e737a7ed998b2457e8bd85dfaedfe0e675e846a47cf7006b66fb69d528c238838faa2e33eb6d712447da34883ba0d7c3f2ad6f87f86b0b181bc5026a6af6191d084e31a457bb14df8c523a614b36cbdfcb2ce044c2760b12638c3059c857db01d0d374c8d6ab6b2be6ea793e93e0fa3b64f718a8c79065a8e65f3856efe264c04c3af5ec294f09e96cf02d52dea1df8d613eae2f6fd023376961b36d707561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d513f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821de3578bd50e4aef3f42172206e28aaa53f32c3941b8b4ddcf806814652917426187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}}, diff --git a/txscript/data/taproot-ref/476e1eb3a45bcd3c87728f4a5f152341fc41c6d6 b/txscript/data/taproot-ref/476e1eb3a45bcd3c87728f4a5f152341fc41c6d6 new file mode 100644 index 0000000000..853e3d3b93 --- /dev/null +++ b/txscript/data/taproot-ref/476e1eb3a45bcd3c87728f4a5f152341fc41c6d6 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9c0000000073b9617bdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caa00000000e018eef0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf8000000009055c6ed02596ab6000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8cf5391e", "prevouts": ["56552100000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "682a4e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d136490000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "557d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e283c6292a6ae3f7cd2fa90a42d11f5a54bea63a95cab37375097c35ac3f3911dda77d1c2cfbe9569ee5db2c51580a9857624040db9177af617be0771cc5b8a1b"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8cf2f607c60f6c156b7df40b9550df6641a796550f01570d3040f84cea15217bcf33eaf0e0e2046a2b327db0183a88d397c5be0a86c812e98815a20f9da9843a2a4c5d50721208c85113b157b4dd4688510f63bd33d4c90ece0d9e0afcb8224b1"]}}, diff --git a/txscript/data/taproot-ref/4775847b1966e3acdf5bf21407d223d54512c0aa b/txscript/data/taproot-ref/4775847b1966e3acdf5bf21407d223d54512c0aa new file mode 100644 index 0000000000..4d2c63df87 --- /dev/null +++ b/txscript/data/taproot-ref/4775847b1966e3acdf5bf21407d223d54512c0aa @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4600000000ece899acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6b00000000d1ceccb003347ea4000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e754000000", "prevouts": ["de454a00000000001655142540f27e90740933c99d4f17ab2dfc6c82951cfb", "7c0a5c0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "5e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71edaba019801d089772adec5c5b59e5bcfed03a63e4fac904ae7f3c905b717bc6fd7bec169038f6fbc2f311373c62d75738dee89ed934d1dccaea4579b1c053aa90a9249c0485c0b349be2068ea39eda6d50f7b6c474a6d5eb714296c91a9f24b9"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe3a991642405641833a7e7ab1d7538152ae68165bb1749fa1b8edad905e55795d6d6d3f2cd85347736e7cd11e639ac781ae37e103c2c2842f248c73b61e825b0a9249c0485c0b349be2068ea39eda6d50f7b6c474a6d5eb714296c91a9f24b9"]}}, diff --git a/txscript/data/taproot-ref/477812c3aa633968c3f508ea4a64f6240b7c1282 b/txscript/data/taproot-ref/477812c3aa633968c3f508ea4a64f6240b7c1282 new file mode 100644 index 0000000000..29034688fd --- /dev/null +++ b/txscript/data/taproot-ref/477812c3aa633968c3f508ea4a64f6240b7c1282 @@ -0,0 +1 @@ +{"tx": "716b8db702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc4000000001e7a2ac28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40b02000000e32d47c101a5858400000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac93010000", "prevouts": ["3afa6c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e140320000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ca7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8f1383fd7477c38c90a6990274ce9dd13fa2e04ff8b9e6fd75bbda71e156ecd1d8a21256d264232ee00f93dc1ddd051bb1479704967786b363cfaf3cd40418b0ce21dc20c2e8df5336572f81421322a354c6d32fb525b1159d1e49b1e9404bf5"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93662cf871ef72e744ac21df2ae1dca341db6636f118cea74203d61b4d210926c308f1383fd7477c38c90a6990274ce9dd13fa2e04ff8b9e6fd75bbda71e156ecd1d8a21256d264232ee00f93dc1ddd051bb1479704967786b363cfaf3cd40418b0ce21dc20c2e8df5336572f81421322a354c6d32fb525b1159d1e49b1e9404bf5"]}}, diff --git a/txscript/data/taproot-ref/4786bab5e3fdd53811fa094d64658a869323943d b/txscript/data/taproot-ref/4786bab5e3fdd53811fa094d64658a869323943d new file mode 100644 index 0000000000..cb78875080 --- /dev/null +++ b/txscript/data/taproot-ref/4786bab5e3fdd53811fa094d64658a869323943d @@ -0,0 +1 @@ +{"tx": "c78d28c0028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b900000000714907ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709c00000000d69c6cbb04d88644000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689876b010000", "prevouts": ["d6823600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "c2831000000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_csv", "final": true, "success": {"scriptSig": "", "witness": ["77f5d13a5f86ca1707350746753a8d93371add02ed5bf24e662743beeccff85eb72191882226016ef4e4657bffb5f8029792835bf3f531e5956c876c2cab7c92", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313ddd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["77f5d13a5f86ca1707350746753a8d93371add02ed5bf24e662743beeccff85eb72191882226016ef4e4657bffb5f8029792835bf3f531e5956c876c2cab7c9200", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313ddd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/47975b43d53b5ddfe8aebbb719cb70af90f9ca56 b/txscript/data/taproot-ref/47975b43d53b5ddfe8aebbb719cb70af90f9ca56 new file mode 100644 index 0000000000..4e8395b7bc --- /dev/null +++ b/txscript/data/taproot-ref/47975b43d53b5ddfe8aebbb719cb70af90f9ca56 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40300000000adc681c160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b301000000dee1962b01d87c34000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478764020000", "prevouts": ["f8753600000000001656142540f27e90740933c99d4f17ab2dfc6c82951cfb", "65390f00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["7978dde698ec2ffcbe18d31e2b3e1930a62fb25b10c61fab7b5bcb7c9958caaf1005dae1442a6f45bfa98dbdd682397b3b8b78c167932e94f80d4e7c40292eaa"]}}, diff --git a/txscript/data/taproot-ref/479ddb4cda1c95a66132ba2891f8deed16e1e31a b/txscript/data/taproot-ref/479ddb4cda1c95a66132ba2891f8deed16e1e31a new file mode 100644 index 0000000000..2c614098d7 --- /dev/null +++ b/txscript/data/taproot-ref/479ddb4cda1c95a66132ba2891f8deed16e1e31a @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4de0100000044be49a801b7d116000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8701a0b651", "prevouts": ["e7be3100000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "387d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d03a0e2dd976c032df5ba11c8ac0ec783bfd7377fb7304a38f58a019219dc2e3f7118923d14a9704f5c6065ead9bf1df659362e443facca38f7fc54a29b18e2b8fa601fcc68a78472d280e0a6f10ace0c22dad9ad93c154f995d1132d7b2f793"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8f5321bd3c280560a6e93f009006b65547a58d72ede42c89f2f760c3bf47a1d1aa12168afdb4ef286e7748ddb08cf408d85b089f504486378d2bfb535c0d2875b"]}}, diff --git a/txscript/data/taproot-ref/47c96a95d6bd928e3390068b3c94db28d219e9c7 b/txscript/data/taproot-ref/47c96a95d6bd928e3390068b3c94db28d219e9c7 new file mode 100644 index 0000000000..9802830672 --- /dev/null +++ b/txscript/data/taproot-ref/47c96a95d6bd928e3390068b3c94db28d219e9c7 @@ -0,0 +1 @@ +{"tx": "6ce4a80902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0600000000fb9a44d08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4aa00000000cd2115bb0257a88400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc0a7ea020", "prevouts": ["59204b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7ea13b000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "fc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cb6beef37ee5dce9a0d87dd9110e965067099d7e22847272a5a9481e46004ae8aceb16be1ebf4fc69deaf064fc7bf5d7ff2149818b5ba4c28c799d30ad567cc959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8f9b91a8bd77dea62c47e49d062c2fcfe01875e2df978edbcee5db59c7daa26cb6beef37ee5dce9a0d87dd9110e965067099d7e22847272a5a9481e46004ae8aceb16be1ebf4fc69deaf064fc7bf5d7ff2149818b5ba4c28c799d30ad567cc959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}}, diff --git a/txscript/data/taproot-ref/47d2125494edd0e8f737339160fc2c2bbff13239 b/txscript/data/taproot-ref/47d2125494edd0e8f737339160fc2c2bbff13239 new file mode 100644 index 0000000000..34b3c91a89 --- /dev/null +++ b/txscript/data/taproot-ref/47d2125494edd0e8f737339160fc2c2bbff13239 @@ -0,0 +1 @@ +{"tx": "d181cd7103bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1f02000000538bccd660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704f0100000003fd78e5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf30010000001a08da8c020568e0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ace80c3a31", "prevouts": ["725f600000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "3713110000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "e23c710000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f5", "final": true, "success": {"scriptSig": "", "witness": ["29b2c78e49ab0e4c1da797ce959ff3729c64b8780327e6e38b44b6fafc92fa2e3343e9dd1bf22830387165b20494522eb04cf25cc768a27b069e4593777de80902"]}, "failure": {"scriptSig": "", "witness": ["b32297a833b7f3df8b1030409a31e3422bf382c6aafe4b596b6b507193f0d6a68b61f60e8ea53cdd4794ae56970ba9298884aa1fe55dc5c25ef7536b39dda4a0f5"]}}, diff --git a/txscript/data/taproot-ref/47d754aabbae7b0b019240479e872ec641a71606 b/txscript/data/taproot-ref/47d754aabbae7b0b019240479e872ec641a71606 new file mode 100644 index 0000000000..497b442656 --- /dev/null +++ b/txscript/data/taproot-ref/47d754aabbae7b0b019240479e872ec641a71606 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ac010000004cc6bcc202066b37000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478736000000", "prevouts": ["8be139000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "8f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936963dc86bc71687ecacc1e5b8f2c4145fceca424a4eb02fbe2bf7a8e8f9bd1024e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e81f261744aaaab7b61bfd8b873ce05c274059b1d1cb072d2d2c67e8900f407405dd5f972b05e2f18c3e7c797b604beeb8879a3af7f1e10968a0ac8aaf9d489fe7"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa458187dbd74455692a21727c8254a8cae6fcc3fc3c7e883861248db6e64d9919f8fae370a255a677f2f729010dbb329fa966ed9a0dd82e5083dd7ea90426dc47"]}}, diff --git a/txscript/data/taproot-ref/47f82c71674923da07b7c082409faecaa9d932d1 b/txscript/data/taproot-ref/47f82c71674923da07b7c082409faecaa9d932d1 new file mode 100644 index 0000000000..475b9e4d36 --- /dev/null +++ b/txscript/data/taproot-ref/47f82c71674923da07b7c082409faecaa9d932d1 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1f0100000024be6dac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708101000000ce3435b90165bf2400000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4f45d043", "prevouts": ["f8be21000000000017a9141582f8bc3490e924b143f387e99eced40303eaed87", "53cf10000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["db", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936158dbdd04fc8b1597704d885de388d9e8396e20d8d1d942e0680de9f689953519f09ad02cb012ed2091760f4e9ad26775ad10447e2b9e598a8be746abc4727fb4e3966518140ddfb4b2a9d93e012e33d80f6a3bf7f24f1b44efe84ec3ac236f0e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93674592b4fb9d11d06e04aedf373a859381c5b821797864f536763c5371283881ca04823906532712c3d4cb334ae6c7c41a1294a824a25b5277d43f47953a1da33e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}}, diff --git a/txscript/data/taproot-ref/4849670c7437aabe38ac365b533b2cae10e1c316 b/txscript/data/taproot-ref/4849670c7437aabe38ac365b533b2cae10e1c316 new file mode 100644 index 0000000000..9558fdbf7c --- /dev/null +++ b/txscript/data/taproot-ref/4849670c7437aabe38ac365b533b2cae10e1c316 @@ -0,0 +1 @@ +{"tx": "fb2bc47d028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43301000000be89569360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b101000000f904b380013e3908000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8790010000", "prevouts": ["4291310000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "39b01100000000002360212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "f37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8196b2ad6d6b5bc7837f2ee6018d0c442079551bc2d8b1220df512cb455d716d94fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6ed93ab99c02c1580916967b23bff6c51eda165404bd9578af086db7302f1c7275"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c7f90985649f4f780ddde68fefeeb82111abffafbe26556b8bb88918199344b8196b2ad6d6b5bc7837f2ee6018d0c442079551bc2d8b1220df512cb455d716d94fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6ed93ab99c02c1580916967b23bff6c51eda165404bd9578af086db7302f1c7275"]}}, diff --git a/txscript/data/taproot-ref/4877a47b68dcd97455dcb8cd52e27309ec642b93 b/txscript/data/taproot-ref/4877a47b68dcd97455dcb8cd52e27309ec642b93 new file mode 100644 index 0000000000..412ddb3f9d --- /dev/null +++ b/txscript/data/taproot-ref/4877a47b68dcd97455dcb8cd52e27309ec642b93 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c13010000000be331e3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6a00000000b0cea3c303fd75cf00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb3030000", "prevouts": ["6a5f51000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "eae27f000000000017a91448964eab407ad5d6e123f59d9280ca7998f71bce87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["fd4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365f3e79e727db2ce69498c039b8b655f97a15b215378db35ebb03872d036f84823effc93d9a59775ec6af4eadc6f66e855123af6e736654ec63572366f38b17272c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}, "failure": {"scriptSig": "", "witness": ["4c52fd", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a87f953251f51e981abdf2d54ebf7b5574cc2fb47742874145712c569ad8b62fd9f77cfc3030f4fa2d9551f14353e565e33cb9a72a19e79fd0e4930553ab0cc3a3aa70c847d82166fa4c32b27cb78dba1a5c77b2d4b8269442df723c9129fb762c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}}, diff --git a/txscript/data/taproot-ref/487deb88a57dc3cabdf497fe30220136e593d23d b/txscript/data/taproot-ref/487deb88a57dc3cabdf497fe30220136e593d23d new file mode 100644 index 0000000000..fa349fe0ee --- /dev/null +++ b/txscript/data/taproot-ref/487deb88a57dc3cabdf497fe30220136e593d23d @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c45000000002883818660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d100000000f7bd9f9f0118376100000000001600149d38710eb90e420b159c7a9263994c88e6810bc75b020000", "prevouts": ["6076550000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "c041120000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "477d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361659200379fe61c8b5eb790a44eee46ca3c7c7a86d8d14f6da8b993c764b3aaf47adf318628644459e7d8d4ba81b7833f70746497cdf0fced2937ab961dc2be46657009e9173c5ef8826379cea4b8c999e3ae37a5805e4cc6da117a3d2ee0eec"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d5c45d46d04b15e6ce2ec10bbcc0e8edf35633863cef84b3ede2af6eac197731af5253a3ae898682e613588786a672ae77746787ad628dd74364be19bb5242936657009e9173c5ef8826379cea4b8c999e3ae37a5805e4cc6da117a3d2ee0eec"]}}, diff --git a/txscript/data/taproot-ref/48a74bc4e405cef7fd774039eb79bdfaeafeea6b b/txscript/data/taproot-ref/48a74bc4e405cef7fd774039eb79bdfaeafeea6b new file mode 100644 index 0000000000..bd63f5364c --- /dev/null +++ b/txscript/data/taproot-ref/48a74bc4e405cef7fd774039eb79bdfaeafeea6b @@ -0,0 +1 @@ +{"tx": "2fa783c901dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf7010000002889a1aa03e5041f0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796bc000000", "prevouts": ["fe29210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e5", "final": true, "success": {"scriptSig": "", "witness": ["0df3e4ccb04abe113a16997829890435cf4080e0da36fe75ff9e8c9a2098101b3318f60a1e36abe4c4f9cafd095f3f3c083f506b7bad766eadcd21d9fdf63e2081"]}, "failure": {"scriptSig": "", "witness": ["0d9c9acbf56db53388b66c59513222528675d5d7d81475c655877fd04fe00675bc89543f2d1aeb04da715be1ee6c7d5de4b4ef67e3521322647de18fe29dbfb1e5"]}}, diff --git a/txscript/data/taproot-ref/48aba9a0a8d38583f02db4ffbfe46b11affd2459 b/txscript/data/taproot-ref/48aba9a0a8d38583f02db4ffbfe46b11affd2459 new file mode 100644 index 0000000000..c9ad3fa116 --- /dev/null +++ b/txscript/data/taproot-ref/48aba9a0a8d38583f02db4ffbfe46b11affd2459 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cde000000009f5d27808bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d201000000283e3bd98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42700000000da52b0940417c3c800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e52a3644", "prevouts": ["6fb15200000000001653142540f27e90740933c99d4f17ab2dfc6c82951cfb", "55f23f000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87", "a8d8370000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["09538187137f32ace2930d2911fe4e69cb81e2d6cf9d93ba927edd3d795fd0bc31fb8767ac49f0dc96b05675635124546f959376cf867517b6eb37681f27883c", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/48ba4204d31335006c77c0a0c393c5424c5c89fd b/txscript/data/taproot-ref/48ba4204d31335006c77c0a0c393c5424c5c89fd new file mode 100644 index 0000000000..c9c9d9066f --- /dev/null +++ b/txscript/data/taproot-ref/48ba4204d31335006c77c0a0c393c5424c5c89fd @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1a00000000fcf1cbccdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca4000000005c8d71ea02dd33db00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69c733a34", "prevouts": ["bd928000000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "adff5c000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "4730440220446c1176deb9a74e6522ef0c3260bef36aa5b8b9df80bb648482b35f4fe4ea2a02207f75fd0de7e84b77cab8c275e6d4a00f68e108ef84d2e194961c45e5f118a6f901004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "473044022004dcccbf9b8dbbf6870669aa306086fa649fec5b0f66a16d000084501e14ee6f022043eb9c6c2c26cfef35efd30a0e0da2e86a46c67114375e111fe17d0baac21e9d0101014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/48bb02ef59af281b015aba26344a918d3e949c98 b/txscript/data/taproot-ref/48bb02ef59af281b015aba26344a918d3e949c98 new file mode 100644 index 0000000000..e4b70c3a1b --- /dev/null +++ b/txscript/data/taproot-ref/48bb02ef59af281b015aba26344a918d3e949c98 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd401000000c607a19edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc70000000014b61f7a0255067f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc783000000", "prevouts": ["a10d260000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "1c935b00000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100d9cc1260c7352652a2effe8a3455a2a83f456ff83dca9efd3f638a0da6683fa0022009ccaa4281d1ed02854c7dda662a6a3cea157e67f3d452d5d30e4fceb000b7aa81", "witness": []}, "failure": {"scriptSig": "473044022073f273b579378c36efe55e9015e3b7a6154e8fc038472f618ca4214e178e8e6802205d004726202f168eb0fc2fea1d2f6dc130e459280d6067589fae6b2d0b4e262b81", "witness": []}}, diff --git a/txscript/data/taproot-ref/4907d4a7edab4d2d57ded00e95a654d47f9d823b b/txscript/data/taproot-ref/4907d4a7edab4d2d57ded00e95a654d47f9d823b new file mode 100644 index 0000000000..f258ac7b8e --- /dev/null +++ b/txscript/data/taproot-ref/4907d4a7edab4d2d57ded00e95a654d47f9d823b @@ -0,0 +1 @@ +{"tx": "c5f01f0f028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d50000000053b9fe8c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ea00000000961af2b201963241000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a653040000", "prevouts": ["1b69330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5a393e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_9d", "final": true, "success": {"scriptSig": "", "witness": ["02e5d1da73ca87ac166454b9542ee7450b2e2f0adc84a09e0b7b670942a86cffabf3a960bcdca481a8ec476265849fa865daefed46452eb7ee3605aa1c6c12df81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["769d0599c3383468ea37dac9ec9ab3ceb4d0b3594a956c65fc845ff1b0de01f5ed8c3d56f73f891524663cefbf18b67f2b6fd279c13072d787630c34541e25e79d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/491492c2f48c07bca9ef88c9fd36bbd272563b73 b/txscript/data/taproot-ref/491492c2f48c07bca9ef88c9fd36bbd272563b73 new file mode 100644 index 0000000000..3d24de41cb --- /dev/null +++ b/txscript/data/taproot-ref/491492c2f48c07bca9ef88c9fd36bbd272563b73 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2800000000ffe4807d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705201000000dbb069df02474e31000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7bdf76d22", "prevouts": ["1acc2000000000002351212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "f970120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_46", "final": true, "success": {"scriptSig": "", "witness": ["c8a6fe54273bf9a667aa0a75d690f199de72bc771fad53250c17629e9888a392d668f25c37a353140bbe462503f85899f1e6b9f38a472e10d13e052f75864e10", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["36d2fa472f06d1d67c5bf8516403f19c64bb670885d335265607ee55d098d2575ab678a0fae7eb1b5ea75de3340079099e92b633bef7b66392b6ba4fafdb9e6b46", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/494a7c765d815e6adc6d4e66a57225322bccde6b b/txscript/data/taproot-ref/494a7c765d815e6adc6d4e66a57225322bccde6b new file mode 100644 index 0000000000..b8281d9662 --- /dev/null +++ b/txscript/data/taproot-ref/494a7c765d815e6adc6d4e66a57225322bccde6b @@ -0,0 +1 @@ +{"tx": "3df0c2550260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704d010000006102a8938bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41302000000e3c820940116cc37000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478714020000", "prevouts": ["5eaf0e0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "39193c00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["ca4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb460e4b742334a3ba05c34377629280dcb4ee1c5981341754674382732961bb035dc18898993c284d2f731b7495cb62c60e8571430965d040562487638e1f1fd248a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}, "failure": {"scriptSig": "", "witness": ["4c52ca", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f6cae3bfd98fc5a984de3df319deccf414966302f09ea14347630e5855742cc8eba4e75ed92f6e82baf0cd6101dcd67879c020ab703e3dac001fd69a24240ecc7034c4ece6ceffdf067bd97d8bd2a80e986f14e8b5dca33ff1523eba7a77d63"]}}, diff --git a/txscript/data/taproot-ref/496ed2b73e932787fe91d418b240c466ab6a4075 b/txscript/data/taproot-ref/496ed2b73e932787fe91d418b240c466ab6a4075 new file mode 100644 index 0000000000..66c38cd5e8 --- /dev/null +++ b/txscript/data/taproot-ref/496ed2b73e932787fe91d418b240c466ab6a4075 @@ -0,0 +1 @@ +{"tx": "15915fbf0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709900000000fb88b9dc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47d000000000fa7e7b903fc313e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875b000000", "prevouts": ["55970f0000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "ca62310000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93621b43ffe028ee9d7bfea2cc09a76d3908c6fc6c62f09d6722d68ca530544f92fb79b88164a8f67b1298a482dda9483af1363bdf02371c7e121a2c285843f3f1e449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ee5a0294560109b8131d2c42cefe472f9b95bf0b422f14b3dda035051434b22e7387e8fdb6e1953b8492ce494f93b549856be52be3e0b2251aade3a72c8c2c0db79b88164a8f67b1298a482dda9483af1363bdf02371c7e121a2c285843f3f1e449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}}, diff --git a/txscript/data/taproot-ref/496f687a93323cea34ef1249059c862f9397c645 b/txscript/data/taproot-ref/496f687a93323cea34ef1249059c862f9397c645 new file mode 100644 index 0000000000..30fa462a0a --- /dev/null +++ b/txscript/data/taproot-ref/496f687a93323cea34ef1249059c862f9397c645 @@ -0,0 +1 @@ +{"tx": "c830ab1802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c16000000003360f5e8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c650100000012a15abe03ce9c99000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb5020000", "prevouts": ["be9747000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "7bc35300000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360f369a784a8897def013640f6b83ddd8e7b013fb685e4cb805a2938f63414ccb99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45d26c3c7079b274e62542512e39807ee92511541c708e3b51bc61366b8def992ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93649f82d663a1e447420f2cf05179af13964281439b8b427a6cb4b09af5b0cc1919d9c6e51540aa9a09fa82ae61189b3f4badb16bfd2877ff7bde730e5687247de05f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}}, diff --git a/txscript/data/taproot-ref/499184ec78a677697ab3ce5b0a87dfbb5ecce65e b/txscript/data/taproot-ref/499184ec78a677697ab3ce5b0a87dfbb5ecce65e new file mode 100644 index 0000000000..6c60efcdef --- /dev/null +++ b/txscript/data/taproot-ref/499184ec78a677697ab3ce5b0a87dfbb5ecce65e @@ -0,0 +1 @@ +{"tx": "ea9513f50360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e500000000325a22e960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127099010000008f727e8160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b0010000007ad921c20200f131000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e789000000", "prevouts": ["e680120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "519e10000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "67ba1000000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_bd", "final": true, "success": {"scriptSig": "", "witness": ["be991662c79405c44c84daf3d0637966754207abe3b78e1e951955a225853c8254ab8f912032fa2fc2eecef1cc456b3d627d082a97b8a31438045ae7e4c4fa6301"]}, "failure": {"scriptSig": "", "witness": ["3324cbbfdf7f4456c9a027d935076ad0f74d7b6d947a7fd7868e9e81f1eafa0f7e13a3a1b8d399354f048c99db1b699f360cf927d62226504785d303869b6e9dbd"]}}, diff --git a/txscript/data/taproot-ref/499f8c99044f5a7eb9940853f276e5ed7a9894f3 b/txscript/data/taproot-ref/499f8c99044f5a7eb9940853f276e5ed7a9894f3 new file mode 100644 index 0000000000..8a99b6a902 --- /dev/null +++ b/txscript/data/taproot-ref/499f8c99044f5a7eb9940853f276e5ed7a9894f3 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700100000000d4506fd8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0100000000c19213868bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4df01000000e0a85df0028455cb00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acece8b33d", "prevouts": ["2e421200000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "1de97d000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "8ed73d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_5e", "final": true, "success": {"scriptSig": "", "witness": ["d2e866302eeed47d01f0d71c41372587d156c5717f40b41c9d0ccce3a2a242efce91c199d20a8de8244a25d3351c04f395104d6e6ff5e8180e5e98c8f1b624a482", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["78c695559095f0aeff271e86a5569ca642207a7289216004d23149426003338b4ff248ea940076ffa758606d04ffb6f7268a8c94d2cbbfcf718594472b1d3ae55e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/4a015d179a6415548a65aa75d68b1927fe2b0738 b/txscript/data/taproot-ref/4a015d179a6415548a65aa75d68b1927fe2b0738 new file mode 100644 index 0000000000..17a31f804a --- /dev/null +++ b/txscript/data/taproot-ref/4a015d179a6415548a65aa75d68b1927fe2b0738 @@ -0,0 +1 @@ +{"tx": "a54aff3a03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf37010000008bb7459d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702700000000a6f955b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b590000000057ec95af02d213ac00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689873f816d5e", "prevouts": ["87ab7b0000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50", "d308130000000000225120efe1fa8c8643b06748235620ecfbc876727366244fc928e9c2000087b14324f1", "17ff1e00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93645c60550b35bd9d705a4e6aa4d32c67750084623e9a280cf31189ad299fac6e7"]}, "failure": {"scriptSig": "", "witness": ["6a17616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/4a46cdc5c3a288a4eead1245fd3b0bfea974ea21 b/txscript/data/taproot-ref/4a46cdc5c3a288a4eead1245fd3b0bfea974ea21 new file mode 100644 index 0000000000..b8d72a7c64 --- /dev/null +++ b/txscript/data/taproot-ref/4a46cdc5c3a288a4eead1245fd3b0bfea974ea21 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707800000000d472c2ff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47e00000000b22608f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbb000000007c5fb0ca0254669200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8e01af3b", "prevouts": ["ab600e0000000000225120a2c28b736583e5896e4a53bfde129100bff930ada42454ee2f7bef5a60a371d8", "deef37000000000017a914c7d65cb5025eac8b5bf295baac9287994ab34b9b87", "28374e00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360df6be8a46bd533a7a93e37944fe1fe70edab0d92eef636eb3f909ab0fae0ce898751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d56e427c91532996b84ed2c37f8a26be8637de11530a49bfc255181ba6103e3464915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93669ad745ec8c5686e271a78eda1c132d24041cdcc23e8fee83101a0367275b2af99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4572db529171a47fc33c2e4ee960be7fb9400c27bdb6fae7dcdae272f7c7daab09b045cee6f1e54629d213b8dbfcd9de8aba2dd7f34fe21c75d81b8576e463c6b"]}}, diff --git a/txscript/data/taproot-ref/4a729815cf7a0f3947cdf502e425da1b2392d6b8 b/txscript/data/taproot-ref/4a729815cf7a0f3947cdf502e425da1b2392d6b8 new file mode 100644 index 0000000000..4cf36facdc --- /dev/null +++ b/txscript/data/taproot-ref/4a729815cf7a0f3947cdf502e425da1b2392d6b8 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c98010000002f66bab2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9901000000f66711d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf84000000001a4b64da03373c3901000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac8e020000", "prevouts": ["d1295e000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "7c9879000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "e9a063000000000021541f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "3b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fafc7fa9328de6285e10958c6b3d6f5d3c073b4c582e31cb42904dcf82d4bed78a29f15cefa9911251712bcf83078e1db490f7db40c14a26e0e577f39f7cfaf11f"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93695b1ebd19a72b38f1278a5ef71d649a792e7e469dc9bf05369ce582ee090883f9a1daf2fbdc5eba8a219f1f8635fe45cf0e30925345452464a53096773d109ba7ef84fce916674b46359d0327d7b56c183d26d6053da1b16053a1f90da8a1d4e"]}}, diff --git a/txscript/data/taproot-ref/4a7e2f54a225b7edfc7761d52940b39a3702b9d8 b/txscript/data/taproot-ref/4a7e2f54a225b7edfc7761d52940b39a3702b9d8 new file mode 100644 index 0000000000..4fadaf8d51 --- /dev/null +++ b/txscript/data/taproot-ref/4a7e2f54a225b7edfc7761d52940b39a3702b9d8 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7501000000e6d878d9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3f01000000a46d7fa2018ab5160000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7e2c51b57", "prevouts": ["edec250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "902024000000000022512068a70acb8902a9bd7a8a0bf24e1b522fed50855c0b1040069930cd3d961acf32"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_5d", "final": true, "success": {"scriptSig": "", "witness": ["70374e2003fcb3638b453dafe36f1386d0a1b71f9bab5e82cd7cfc7925c159be17ce35bccf4191fedbcd84c08eed2681804fb8a09d742d11de2ff214f7860ba102"]}, "failure": {"scriptSig": "", "witness": ["e1192e7df04cc54143c59d2e435000fd068852d9f7b6b45c9577117068119ea02e0e1d8e2566b8e0a0e52db261f0cb485d08fc222b1ac08d8b067a91f4a9e5f65d"]}}, diff --git a/txscript/data/taproot-ref/4a8d82dfb1750aa99deb48b58f8c91a30cc703b0 b/txscript/data/taproot-ref/4a8d82dfb1750aa99deb48b58f8c91a30cc703b0 new file mode 100644 index 0000000000..e4193f2e91 --- /dev/null +++ b/txscript/data/taproot-ref/4a8d82dfb1750aa99deb48b58f8c91a30cc703b0 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700001000000f3c0e6a660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707d0100000038f3cdae03080d1e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc63000000", "prevouts": ["aeae0e00000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "dbf0110000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f368", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363c3687187a66b80fafb5b0277cf05dfcb566c0733f5897c37ccf352960211e89b9cd72275efe6b477d9cf0b54cc21959221ed58300fa90def59e56d53bf5ae178c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51a6e9c603f7f99515daebfc2839154302ca67407333b540c062b355b85f19a07ff2a2968b4ea0558d79f1ec3cd2b8a530982c6b5ad0be17180e93d11bc09903133cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}}, diff --git a/txscript/data/taproot-ref/4ab1d0f5d83d7343f225dc40c2a3a9940dbe3f7c b/txscript/data/taproot-ref/4ab1d0f5d83d7343f225dc40c2a3a9940dbe3f7c new file mode 100644 index 0000000000..78c166592f --- /dev/null +++ b/txscript/data/taproot-ref/4ab1d0f5d83d7343f225dc40c2a3a9940dbe3f7c @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c413000000006d7c0687bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0c02000000532d33930418b6b700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc996e2420", "prevouts": ["69f4340000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76", "b9e8840000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["da4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d5de9338381cd304b2738c8b1f6fa31d15bcfc9fae7d40af04401c68f4d5de3473df9812949ea11fa7cd8f7a31f5257bc4998fae53c5743d03c7cfeceae664b355d713f01682c54eefc137cacda341f8a928ca67657dd1895f9a847e54f584f6ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}, "failure": {"scriptSig": "", "witness": ["4c52da", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004544455204ada9566561196f14caee307d16123ffe4b49d60aeadbae3e053e0a80355d713f01682c54eefc137cacda341f8a928ca67657dd1895f9a847e54f584f6ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}}, diff --git a/txscript/data/taproot-ref/4ab5fb6756c937560dc91ad579231800bcb605f0 b/txscript/data/taproot-ref/4ab5fb6756c937560dc91ad579231800bcb605f0 new file mode 100644 index 0000000000..f87110beae --- /dev/null +++ b/txscript/data/taproot-ref/4ab5fb6756c937560dc91ad579231800bcb605f0 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4600000000ece899acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6b00000000d1ceccb003347ea4000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e754000000", "prevouts": ["de454a00000000001655142540f27e90740933c99d4f17ab2dfc6c82951cfb", "7c0a5c0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["5a0974d832729731c41798c33c7a1c0300be4dff93f440d652a3257fbb5da0e4e77fd5c4c8be4c487baeaf32f951980eb2ab4372177d3bd01d49de2560a2e8b7"]}}, diff --git a/txscript/data/taproot-ref/4ab75e6d0cbfec5617026ca0e5622cb4be8d69ea b/txscript/data/taproot-ref/4ab75e6d0cbfec5617026ca0e5622cb4be8d69ea new file mode 100644 index 0000000000..f1832e1f94 --- /dev/null +++ b/txscript/data/taproot-ref/4ab75e6d0cbfec5617026ca0e5622cb4be8d69ea @@ -0,0 +1 @@ +{"tx": "d2c4031102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe40100000010467ce9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9901000000770146d6038921dd000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac0b000000", "prevouts": ["11f6810000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842", "b9f75c00000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090263ae34b455e59724eb6ef57cb0e0123d910934fea3aa0270c9aa1b955a5eb73c6c8a169af2b4646004f9e69faf0e3f03f3151659b6d62a8435c55dab98c6ab3fd86fd69a2c9c4a5fb16dabce31351840564b2becc9f94c7c594240c37f787a1dae71bc58f1349ce3f460f2d1f507caffbca0bc680eb90552b2d0bb87d8f7117759f8c427c6a3a29b7e241b5f53f84a08036e15db3b5ed6c5da0990475968169b6e02036bdff3a4f8300b7d9b259f39a19b554fb2e009ea4cfd28b2fc02b563676510c3e6be086962d3940fea09719b9b655196c6bb5ebe208a8b02c2ffb8c596d7f5755b5ff4f417a32a2348323eb2032d1e08c954808ce80acaff7ae0f7829a13ec60a31a1ddfab6ab817ae6f8ed42f8b2d0262152aceb218b16f795c1473de264a50c12c48c36e7c49527616e71d5cbf6cdd88c881523a403425f1a44a1aa97e7b4fc58b0135cb52452803453c243d89934e02b8dfe9ea01387a7c6d0dd0fbd96c5c2dfc358f911cc5336b4de088ac0325f6f4fcf2d4fa9f9fd40318a642f3d154b2754ff200ce1943395e8dedb1b21af62e0e69f647691ae305bc2a2be53bd175361a8451596ca5b3b73e07b06cf6d3a59cf935afbba4134e4af8a75dcfad9a97fe611d303612a0f76439285b7903ea30dd16f1c53e98513c0aad1ed98e167726e37dbc4a173386642dc265a3ee677051f6028e9fce64ae14a1e5c5f03894080ee7352d72ec477475", "b87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bc4cb601b2ff3e4c8eb7bf71eef003c1241e07142df84ef0b259f821b2a43f68ab6940ee0f3b13da6463e2f516d6c168d9c5d733b385f1180629b82031abf4ccad8c3985a8e2539d42260561cfa7167d8724d0e4cbcfaa47665e96933724a3d86960f5e71abb11fb1594f725adbdd26a9f61c928558a58ca58d11d05eb565d16"]}, "failure": {"scriptSig": "", "witness": ["4d090299d45006867b98eec01e1bfa2ead1933035d70a408fbebc560c94fdbed6390098932fc1a21be0ee96c3dd621378d91ae870f2de932098d60568ed8cc613e2cbe3d9925a67ab7686157f2138fc18a286211c949e6024ef952d533a19af2b09b823679c96550c845a56e52d75c6556994db6589e9bfa0b259aae06437f510049489e528ddbd35e36fd1cdabca57af51e350c3a5d9c71bf30ae28ca04f0004bf4170b613428a653a26551337bfba63f98e387b59b513b407f4fb6ecc3a86f97f16439ed22a2fe8eac7a8262325ca83bc07efb982c7308508c13d96fba61a65fd0d1c56a69bc21faff7c695d03b03b77f0e1ab6fc4ee0cd892735f0ceabd4d99a7b78ea803b0a3595c912598b738456bd953d3c546ebef357b50b933d1f58af1f46330419637e710d6c3ebbb64bf3eb9abfeefc1b81b85466d4c1139e845d84bf0dfbc933fecc7a933038bd6b9307ab44993d5696b7f7d07e0504cc63535f6fa13905cc67a1cba58a4ef23b0bf13fc0bf1e9095c2c1c16b7ee013fffecdbf3537702a566b575cd164d76786b72e7c31200b105c12ef52e90a04e58e36d681282de2b43f3b7db892c7e3941a890a33520283f27c5f2aed23babac38c5bace95ff98f3636204016a3e36e0efad68a4fc00a94833bf6d693d71d34855b1c135e16f9548c7f9e33d6cbcac9bff8cf88643d01815cc6402bf1d5443aa9ecb6f32be71b3290c3c35b786342199f875", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365e2e8335e76e899befc23e40fb6f9c6307bfd84edbd8f2adc0fb5ac8d6288970ad8c3985a8e2539d42260561cfa7167d8724d0e4cbcfaa47665e96933724a3d86960f5e71abb11fb1594f725adbdd26a9f61c928558a58ca58d11d05eb565d16"]}}, diff --git a/txscript/data/taproot-ref/4aef881f37b09a5f41876628452dac08c70a5c3e b/txscript/data/taproot-ref/4aef881f37b09a5f41876628452dac08c70a5c3e new file mode 100644 index 0000000000..c923fe2198 --- /dev/null +++ b/txscript/data/taproot-ref/4aef881f37b09a5f41876628452dac08c70a5c3e @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1402000000ff7187b9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8600000000e2bd2fabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b54000000005614c499012d9a5900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388aca876a75f", "prevouts": ["cc547700000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "b4db27000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "aafc28000000000022512008ff927e8178e20f38298d934a97845982dc7c5901b7d815cf7926413ad6b4c2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "557d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2a116e3d98c0753c1b4fce835beb402fe845fa277dc01c5b4ae7ac2a0861d05e2d0ae3a8a51f8512ed3183c6b189898e3d13807be8720838a97bd7135cdf46e7da77d1c2cfbe9569ee5db2c51580a9857624040db9177af617be0771cc5b8a1b"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cf2f607c60f6c156b7df40b9550df6641a796550f01570d3040f84cea15217bcf33eaf0e0e2046a2b327db0183a88d397c5be0a86c812e98815a20f9da9843a2a4c5d50721208c85113b157b4dd4688510f63bd33d4c90ece0d9e0afcb8224b1"]}}, diff --git a/txscript/data/taproot-ref/4af1e59e48ecbb8bcf5f8c2a739ffe2d47054b4a b/txscript/data/taproot-ref/4af1e59e48ecbb8bcf5f8c2a739ffe2d47054b4a new file mode 100644 index 0000000000..4f74d2b5ff --- /dev/null +++ b/txscript/data/taproot-ref/4af1e59e48ecbb8bcf5f8c2a739ffe2d47054b4a @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5d000000006fb370c1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa501000000e51bbcae03ddc2c000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc7ee3e34d", "prevouts": ["52205d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6c5565000000000017a914ca8d66b8079fd8386ff3ae1d10b869f5605e693b87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a9", "final": true, "success": {"scriptSig": "", "witness": ["f2c034aae270d3ab92348aec07cc220b325344dd915672c5c288a0d3fd433fbecfac0da44c094be3e305e1c1ea78680b37dde07a3c9b401d91d05f8e63ad03d203", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["cb41401717f090464cf6d9fab9b14c5004c8dace3497baaf46531a844a764a3cfdc5cf3d2e7f2a77e7bb300ac4a24ec23b38fc06598f259be7ec15ece228a8c5a9", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/4b22e5ee8f595d1440ed41006d8e611da06d0c13 b/txscript/data/taproot-ref/4b22e5ee8f595d1440ed41006d8e611da06d0c13 new file mode 100644 index 0000000000..e53d188397 --- /dev/null +++ b/txscript/data/taproot-ref/4b22e5ee8f595d1440ed41006d8e611da06d0c13 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708100000000b5ce03e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6f0000000017b9b5cd04deb385000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87ead3593a", "prevouts": ["0888110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1a5f760000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a81", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364125f1cbae1c36a714ee021fd4164bcdcce073dab8e1136386d2993f5734f22399aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb419c228cb7ae814d70beabdb725e2cb3ba4f8af3a16648b1300fc97d27ac433c5da9670c383f4b71f5a22d48df0589bd68dfe195935a65f1aeaa80f10f8ca6973"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d650279aec7c7c5fe6d77189aeacda2bfbbc50f6f488fcb7bb6e3e093d2538718137b75632fc8469b6d274d74e13d397486217d72038875bba282e5d91314c39823c6bcc0c06b1ccedd8f3302fb965778bf11fdbd4830d29cbc62f32a77240ccdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}}, diff --git a/txscript/data/taproot-ref/4b537d79f1a6255185126b99325e3917dfdc7885 b/txscript/data/taproot-ref/4b537d79f1a6255185126b99325e3917dfdc7885 new file mode 100644 index 0000000000..22dd3277fd --- /dev/null +++ b/txscript/data/taproot-ref/4b537d79f1a6255185126b99325e3917dfdc7885 @@ -0,0 +1 @@ +{"tx": "0996bdbc02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4201000000c4343cea8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46c010000005a7cd0e60191ac45000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48701283e59", "prevouts": ["1283730000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f", "21743a000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "947d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa7085091e7b587d9e3d903161356c0634077d7e43e5aac1c0c25d5c3c805eac670235be472b05f11e998cd7dc8896eb16b23bac01933cdabddca8bd45937e3454"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936417d2d865202d20eebfd4aacf46381b0ece3fddc39ce14b62446cc40f8d1090e3ee723c85209fe64e13625f9e221aa1a5a0132ad156eaddb44490f9df3bced660235be472b05f11e998cd7dc8896eb16b23bac01933cdabddca8bd45937e3454"]}}, diff --git a/txscript/data/taproot-ref/4b57985dbb3b797fd0788cfb9513abc07ddad003 b/txscript/data/taproot-ref/4b57985dbb3b797fd0788cfb9513abc07ddad003 new file mode 100644 index 0000000000..096d5f5f0e --- /dev/null +++ b/txscript/data/taproot-ref/4b57985dbb3b797fd0788cfb9513abc07ddad003 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4a0100000084436a61bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc500000000b28535d6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd2010000007e9916a503f4c94f01000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e77c000000", "prevouts": ["f56e7400000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "259f7f0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "acbf5e0000000000215c1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["426430db3dc77ef08364b380c829f036f13d04383c75a0522b3440f4853d948e3eede99181d53675ad93374bc8c69a4162a18d7ebf7f1080a8b3d21b8a55195a", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/4b72ce01f999a32aedc950dd1804a8795ff98723 b/txscript/data/taproot-ref/4b72ce01f999a32aedc950dd1804a8795ff98723 new file mode 100644 index 0000000000..39982e1a6c --- /dev/null +++ b/txscript/data/taproot-ref/4b72ce01f999a32aedc950dd1804a8795ff98723 @@ -0,0 +1 @@ +{"tx": "47c0016f0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700301000000248adfaddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca601000000923ad6d7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb500000000bc64099104f8507b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72f050000", "prevouts": ["71151300000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "c3c7480000000000235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "db32210000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902718b1505bf73d8addb5f3c865c6ff14615556e200844aa8308c1fb610a0c09142a1ab31a38b5db43c100771565e3933f6bc6c3b7ee47f119f8dfdc0bf349552c3df18ee788d4eb0366bb8254555092289bcb8383cff15dcbc97d4e655719d5d8952e5ea5d42a45b5ae81820df54447b50423b6e1f71de4c7de9318720d6d85cb8cb4503a13ad35b58dd441107fff3eb51aea69a6699ce7c8793e8a16912e28bdc9a45cebef1a767c12163278116c0a956fdd4794da6a0915390afb0c91360614a389ab80b877d87a70c92fc526e0a6b191a3d0c83e74d4846e8102f06ebfa69f3fbd49be938a387433d000e3fc1385c06bd14ad69b6d29f60d2e8c190972e0fd39858fc7b097ed0efcdab96d17f8aef43660c9630e596f781826060c8f5342fbd810e176b5513fb77f63ffd1e2b050a19f81043394bb613299cbdc59e8f8cd86da92bb529fadb64e0bc9807c58ca4cde44f8d709d3b7b751060dd59c9ba279c224e9082123109741413277a4f7d1ce9aa184c51e35b3966352616ab9bfd3e9b064a81949a1391c2703b86069bb8171280269146e3eff413ab96c9c2d9b74bff2f5f9facf5e325286511c7eda3aa28f1652598597160c203edc65a110d1d23608603ff6307e3aa5724a6122a28cee8de245cb6aaf1fe476cdf64538950301b638886d511ec3e69da6898e5b615c0e30108fd83b4705441f68c5ad2ee33b50166ec7b6f0d987f6014f8f75fa", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e15d4b392b2e4c368022144328e009ed21ebc6df76a38c37cd5c7ada1ffb4033c71a4e7a29e9a68a1d6e5ccf500c3bde1b862f2704e441e939992f2bf5a528056a3bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}, "failure": {"scriptSig": "", "witness": ["4d09024a1d8b6f52c9bf374a22198b10c849f2de4d02124a70757da8118207f01855e57d43b5c69ea657cbf97743e20d0c7e15a72d102f193347c99ce69cd2e3b2b62d7f9524084ef1474ccc699b24a570f67ed33e6238f845c1a79bba1d55cf052dbdb18c6f776cb53faff034a7437dadbbb3d439344767afb2ca48aadb91892c791c7fdbf2a6d4012136d89179c6ff414a6a25e70568f904a527a2baafe467da4baae935ea62b03a492362877bf05f31a444c10ec34b665e3fa6591c4d7ce2b5df836da341bb9aa43fc680439dcef77420745e1eaca54bbd7d27784e28eee7880c77ab194ee4cd940901043daaf9df337a114efc4bd9989c0ee1979b5a8da4e84f0d9b7d457ca971693bad96ffc69ae3928920fd49d93f2686f5a46ae61d8cedc35e57f38f15d35657a8ab2c0af8f4da24faeaa47ade426fac41208de9cea4404ab8001e9cdd54ad7dceae4dd26efea0ecaf8242fcc549d514c99372feffa7805a49afd9447bb2f8ab0658f15f43bac176dae56a7e083fbbe2c77e2d26a3f8dc77a58ed0f70e3d965fa14824856e219e2aff02d967f999d7447e57780bbc4fd4e96032d903bebd5a807a3500a043ff6edead27d70a316dbb6d5f6f439f3e45935f39e56ac5391fab364d9109dbd88c6a0e466dbf08a5a1f416eb5ac7b7050ca7398ab259ec417cd8a2eff19076c0b8a54166e51852738ce5b9ce31df6e9a045eab0178ca9005bde051257b7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368e1d4621f5a2467af09fb339d917c3eaebf29ad88777f17d5401e6cf398d8d98319d91594da7fa35d5ac76c3396b108bc28aa6233c389d8680e4f0461963fe656f5053dc49cb92d20c30fe5ab09c589302aa9886b9c794d18405aff33121a169"]}}, diff --git a/txscript/data/taproot-ref/4b7e7a47d519d00fb5bb9332b6fb49586a4134f8 b/txscript/data/taproot-ref/4b7e7a47d519d00fb5bb9332b6fb49586a4134f8 new file mode 100644 index 0000000000..462f1a05c5 --- /dev/null +++ b/txscript/data/taproot-ref/4b7e7a47d519d00fb5bb9332b6fb49586a4134f8 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c452000000003b7dd6d08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41501000000cf2ca79e04c0e7650000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e702dfca59", "prevouts": ["4fb5330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9b2335000000000017a914a7d99db8790799e567017bcc9951f7f968dba70f87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2356212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["690731b1a0b6814b8fc7d32847d22e69a3fe5726ee1041af6d03555929f7f434924ac9287832f7b0151492da04fc8589593afba56b6c174e03cfc7bb8bb9d9a9"]}}, diff --git a/txscript/data/taproot-ref/4b8ea927af2611b4cf7fbab90c9f8ffb8bea3ab2 b/txscript/data/taproot-ref/4b8ea927af2611b4cf7fbab90c9f8ffb8bea3ab2 new file mode 100644 index 0000000000..3956ee7c2a --- /dev/null +++ b/txscript/data/taproot-ref/4b8ea927af2611b4cf7fbab90c9f8ffb8bea3ab2 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfff0100000064056d8d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700201000000167321d8034e0186000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb31b4546", "prevouts": ["9f5278000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "368c0f00000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/emptypk/checksigadd", "final": true, "success": {"scriptSig": "", "witness": ["9ea638a16318d7aead6b38111127507d170b8970edc6285e6b801a42574414a6873ddd68e7e040865548fef0018fda27e5d67a008c68fad6228db4087899f32b", "5420871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a034685013eb12d0936a5af43ae0e5638d7148ca8da311dd51cf2e290b05ed820ba5102bbf7fbeec60e292aba2a12d06acbee3d1ff3068be768a5f8ab1c15c8b5f95428243b01e6b613d868e39a3cd6f8053f3b8a58a5b42db19ed132d0fdc37ab205f68d8ec55f68ec14e7908e46173699cdebd091fbaa00eafb7815b9069cba262853dbe467a837dbe26fc7f3ad7cd7a62e462e47b7e1bb60054913e91ba6c655d89a1acb7a851de7428c381ead1ba6d1d417e8b953e51f7c670e3863576c3b88611529e8d8ac178c50676d0c91193955b6fb062740847f08c84da5efc29fd5abdcdd61aefa92e26b138e07522d025d19d1fad7762f9c1f70685829a115613fda528b23fc9436db397402f0e7a3d49cf7a01c31cfb831fc26b2262ab8efbabef6fb95525f08c0ad7b451d163f6e35eb4e415957ac629ef0511fe91c7e5e389d906758caa877012f69cc4f32b8c78b5f62c54ebb03c94d75afc9f0e4835f9336f422423aeb19ed8c37b62b0dd1dc6be563591d9481677ce9900692950fc288a25dd19e02d4685ba017b89767b5c8376f6b66370e3202d9e807c9c5b06b99c098acfa6a9da80a755a207eb5a3ad02b1a2cff248af93ddec122a727b43b9e8dbb8b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["cc9b62c485dc8c1de4ab827a7aa0545e4fbca86323408d5d7aaf066258f4c086044ae1d26566d10568834c6a36cb6134e0c545be7b3cd0970608b0b6326c8f2c", "5400ba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368cc4d632c25fb1473ebc2c4691dff712f1529879b16cf6e01c3498b371ad5643f043ba3d030a3b9cb1de0a60e5c22d352c9a6b0167bb0429c65653ad93c6b5ad75df7d692cfa002fbaff39a633e2a3d0c51d8dadcd4fcf0c857fbd83ad169fef2faba22bfc7a47f9e635144f510dd0bf27279d7f381c4c7abb10bfa7caa6f45212b1384dfb83dad558f50952f8dc7a4c93fc05bc0bf8f252596f3f99dcc4aa25ab6fe4c1776346de255528baa11f4624c0da11cd67d3944bc9e3c23527f253a174940966dd57e339c9cd051354c05cad3fffcfa87d89865f388df6a9793fb850795b387e411ef7ecd738a90c270a9e8b41d104f0901d65be980e017742035d2ed5a15550423aeac2e288a32ca51234efdd8592bd1b66a7f846be8561b7af73c90baa320cf1711a17ed2a311e1783897c17c40a4468373563049ba8a82c1cbe704bb8d89f21761581480cc9fb789613a87d31235185f9da4b4384725e898ebf0d2c5eddaeb8557ce0f7cc7880e698091ab104cabb34aeeeb5d0f57ea86d1ebc555dfde575d48d1eaafa8343c63d6f5425984d2425aca274be02e47a5142e089ba2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/4ba2921581f7a3560b6ec87297653fb165ccf969 b/txscript/data/taproot-ref/4ba2921581f7a3560b6ec87297653fb165ccf969 new file mode 100644 index 0000000000..b10866a716 --- /dev/null +++ b/txscript/data/taproot-ref/4ba2921581f7a3560b6ec87297653fb165ccf969 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf55000000004245bcb4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b17000000009c83f3e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3a01000000932991810400c0e700000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac6fe3af24", "prevouts": ["3f1c6e00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67", "ceaf1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "75615d00000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["cf4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936576dcfbd45e3fc8427f121d4200b68bae14bb12011fb1b2bbae78ffacf19fef2e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0decf70b79dd1be85a38988f8929e7263abb01bba95965800009381ed351eddb0fa653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670be4a0ca57acda4948961859806a1e82ea139c65a64667406163012635ee571197eab9a6b3049015e2aeaa64734336ddd9b9acdec5b1d6588bac0b5808dea8f5f88ccdecf77b0d26ba8d6f3209049de9d03155be73752c3625590c2269e1c4cf4a62e14d7fc4acbfb0196ec29a60565ac2b3043dda4cedec8cb1ff291b90d41"]}}, diff --git a/txscript/data/taproot-ref/4ba8a95b0f39aae1daf6e664542420657da72fa0 b/txscript/data/taproot-ref/4ba8a95b0f39aae1daf6e664542420657da72fa0 new file mode 100644 index 0000000000..4cc0bf36c1 --- /dev/null +++ b/txscript/data/taproot-ref/4ba8a95b0f39aae1daf6e664542420657da72fa0 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1b0000000022e6d7a8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc401000000b2de69fa047e0aa800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acb1040000", "prevouts": ["39ea810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2995280000000000225120fd40216dd29fb2eecdff7e4128bba3cfbee632fa2e745a84c0cfcf3475ca43df"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362fa354647588dfee660039a90ed403daafd6a7b1cbb30bd112b49394f93378d2"]}, "failure": {"scriptSig": "", "witness": ["6a1d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/4be8d76134fd3aa72fd3ecc702e88a4530fcab53 b/txscript/data/taproot-ref/4be8d76134fd3aa72fd3ecc702e88a4530fcab53 new file mode 100644 index 0000000000..385a6f3ba8 --- /dev/null +++ b/txscript/data/taproot-ref/4be8d76134fd3aa72fd3ecc702e88a4530fcab53 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff901000000939dafac8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47c01000000d2c3b2ffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2801000000052131c304cb62b800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c6010000", "prevouts": ["1f9b64000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7", "1e9b35000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "49a720000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1c75ad5b0c19c64f5d3a7fdf07b71b1a8f8b99e999958fe2a8fbfcbf733553f9475ca33d7e1e5f2997f74dd285eec8a0e5cba5080c4482d5b595e9662ee4b93be0a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367d0d894f81359a419367fc8ac631148e3eadd39a7159e1d5f784b52cce329de7bc80a3081e946651089c17942e2d2b7e0a2ba8b51162f8e9c4f29cb18d1603310a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}}, diff --git a/txscript/data/taproot-ref/4c0186fb62257335535a95ddfc34807b1f836154 b/txscript/data/taproot-ref/4c0186fb62257335535a95ddfc34807b1f836154 new file mode 100644 index 0000000000..1844d88e0d --- /dev/null +++ b/txscript/data/taproot-ref/4c0186fb62257335535a95ddfc34807b1f836154 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9f01000000d913cab760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127007010000005f0436fa04d7bb8800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac46000000", "prevouts": ["c4ba7b00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "ef5f0f000000000017a914b1a54d09172ecbb89289f2a670acc3fe14ced9ee87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21531f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["315c9a851d47e522491de1c1ba5d5322a5df750b02611d4cb50ed7000beb732301bc0bc1e59598d7fec28d19249cd55c8f6b8b2ee5a8a9abc8e53766e9e84962"]}}, diff --git a/txscript/data/taproot-ref/4c0a1b11b6e6b7691c115aa09cd92e8ee09a5076 b/txscript/data/taproot-ref/4c0a1b11b6e6b7691c115aa09cd92e8ee09a5076 new file mode 100644 index 0000000000..97921b1dc0 --- /dev/null +++ b/txscript/data/taproot-ref/4c0a1b11b6e6b7691c115aa09cd92e8ee09a5076 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dd0100000032bd211460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ae01000000ce12f710049bb81c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac34000000", "prevouts": ["bfb20e000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "9019100000000000165b142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a80286c58cbba2a57fb9b12a69a1841fc8a004e55302942795623103064cf9df0bdc2cfb102452c2a967c53504e9f9addd5f12bd635e8916083c12ec4bd01272c5eaa403f04c1051faebec20966ebe5a50352787073e7fb641e803eb34274f377517bafc24f597fa892a812af569f52d348c8d80cfa868d4eda235b04a983d3adfa470b7205d09bc3586dd6ee4d40e7bd04bded8747cad31bd2e83b1a28fd9453bf701c8b8dc5805234951ce989e309297c94893a9e6acd795c98ad6e618f844ff340e799251d0ed815a57e791c4643e3037c7ffc984a6ba839546f9d1e388d7eab0b0c88a5cf0804c7edc55e13a3add41ed3295857559e43910b7b1ca971061d4dcbf865e1736e4c57eea3bf11c89053e17121a2586624f736cc1bcaf54b293a15eee0e8e0994fb1f5513ef9448ce4c50fac6b384486a6794ad8b8ff952d36f46de70cf2811766de3a0b9b05e346714593ef1c11080a2606c90f1f82dd5103aa4dae7cc403a77b1342f9fb737615956d0edd03b686cf26d81292f46d485ead33774ed1f56c1a3a09729aa1a942588061f4287ee08b8d1a8b7ac13a130f5ab519b9787c2a0685743af16dc0d05b19bfb1cf08084ac1b6586279b9a47d25497ae77a4fa7c14ed55d27a2707fead97c4536754ba7b7b625726c8876a060181ce44591099fcd240d9fc022e90310827e64b4101e2e06676a3f0c9d7123f13232cdefb7701f761df0a8d0d75", "797d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8b1663b8b45656caee420ee834d80103f5ad80f9c4de199ff6879db0155217f4eccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f45727aec9530f4cf05d3554e63105b96634da39f3c52c35c251ce860693e97320b3"]}, "failure": {"scriptSig": "", "witness": ["4d090212f43ba80991e1c133077a9dbcef510636b40dc18c86830747725cb0f2fcdb6e39f6900e2e51c8f2e03a61c54e1307649458fd09074d5a564fa734d82876731e7fb23a07745f07cc8ccd22f79496f687fbc56738125a1c260908da013cd7aa69dd5fd80561ecd5caf4b99246b80d46c615200c400ca0d15e4a20fadd25e484c9cff13cca6f77f839e42931f32d371be0cb298f6e4a98ff9cc387695e8933bac89a59e1695cb219c12a6aff5b097d6f6dc9c2984d3ffc72a9ccd4acbd93d66c6ca9153f8d352f84715e5fb38c697cfcb9a1d77209d4162483182159b37a4fc48c147bf352c3f72cb13027495d899fff5e91113ac9b92ac95fbbc308c18b77ea646750735016c7c657aa27c01716570c5a37df176b4ae105ffaefb3a12744c966ddf459af3dae74364cea80b6bc31d42e3c534e5eee5f2e96563f576b59c13d0e2c3daf7babd412918e035fa4d2c7b05d69789897fce70b35a3cb0cc40f14869c4a691572397b8203b47d859356b266bce4ba19ddca7f9ba1de207e0d19b89f9ccb119f91f98553139b7e5f974002107d648f12ddc662208884ac6fad53940289be8b236e62c5200c54a1592c568e61f98e4f202b58574524f23b13c57451a0af784f0ec06933be63fbc48e718912186a5402fcc375dec7670382924dc2ff493e26c50b2dd32522ee89a2d596e30013d3cb1812ecef3192d5daeeb136ab59614722b82a5e98d0974219275", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e6301af72c0f0fcbfc62431a82320b93fda30ebabe1c669499e3cf52b4dc2b40fe711fb6ebac21c15598dc6feca0613664d86278cc532834585097123290bb3d45be39dc57762be2d9b1a04aa5b570805d23104bfe4fa54c392bda5d51f7f4540"]}}, diff --git a/txscript/data/taproot-ref/4c117e356638d628e5b841bc413e67c8bbf10384 b/txscript/data/taproot-ref/4c117e356638d628e5b841bc413e67c8bbf10384 new file mode 100644 index 0000000000..06c16b9e20 --- /dev/null +++ b/txscript/data/taproot-ref/4c117e356638d628e5b841bc413e67c8bbf10384 @@ -0,0 +1 @@ +{"tx": "0a67d5d202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf03020000001e51faa7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7e0100000001bfdca8034512b7000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac9d83214c", "prevouts": ["bb446500000000002251209884719338e1397826c7fc76b57dc9070e1ae6721fe0f4052d3f32cbc4476e6a", "857d5300000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "fd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d55b1ed4b01a6cd7629ecd20d44fed4dc17055f878d3dfd1e02408408b3c8ea2ebdb1eebdcbd8002197b9f44a9e59d0e9024523da319a2f3d109fa4e426d654ff4148296d57de26c46202ca6ca2132af69ac5e2240f6410455c1127b810a8937"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93622db97bf80631dfdf531579b6ec0d52fa26ef63a3bea7b809a4ece9c352aba3e4304fc86dd976b0937fa56c41f386d806abfef37789b2eae5a350cc5f24e0b07f4148296d57de26c46202ca6ca2132af69ac5e2240f6410455c1127b810a8937"]}}, diff --git a/txscript/data/taproot-ref/4c2d2d7bdc708a582093d11d189f7addae41c5b4 b/txscript/data/taproot-ref/4c2d2d7bdc708a582093d11d189f7addae41c5b4 new file mode 100644 index 0000000000..803f2fd44b --- /dev/null +++ b/txscript/data/taproot-ref/4c2d2d7bdc708a582093d11d189f7addae41c5b4 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdb00000000b104fec5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b15000000008f74357a0431b5990000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987d7010000", "prevouts": ["94b37700000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "04d82400000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}, "failure": {"scriptSig": "", "witness": ["c43931c0252ef35eed0164ab7b1b9c14130759b9113fce27ace9dfe7a45f145b3707d661b15108aed4b252dfdc2d8a8aaa002440096f77bed5f253495387a1", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}}, diff --git a/txscript/data/taproot-ref/4c66ad58c30b6404b73490df6a7aabdb4eb995b2 b/txscript/data/taproot-ref/4c66ad58c30b6404b73490df6a7aabdb4eb995b2 new file mode 100644 index 0000000000..fa690cb3af --- /dev/null +++ b/txscript/data/taproot-ref/4c66ad58c30b6404b73490df6a7aabdb4eb995b2 @@ -0,0 +1 @@ +{"tx": "c07ee00c0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270200200000062d802d1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cef00000000fd6645bddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3b01000000fb6fb2d2013a6d4300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac24ec9a3a", "prevouts": ["db2511000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "86f3560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "946057000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "c77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936791463836b54b358dc53f27671fdab223563276614e8972ade3f121fa536a5dd4639ba4332756735e08e9dd0c9395e600a8a67669bda3acb22644b013566df80a9fad2668c863ea9bd6dd9197c1c49c61c2b9d7888bac8bf6fef03fc3ace0a5a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f01d0d256ad0d229e53661481dce388404558ec2529e0bc1d85e0261a585159aa9fad2668c863ea9bd6dd9197c1c49c61c2b9d7888bac8bf6fef03fc3ace0a5a"]}}, diff --git a/txscript/data/taproot-ref/4c749139f91d4268578b998b4fc4742cfa968495 b/txscript/data/taproot-ref/4c749139f91d4268578b998b4fc4742cfa968495 new file mode 100644 index 0000000000..6c9297402f --- /dev/null +++ b/txscript/data/taproot-ref/4c749139f91d4268578b998b4fc4742cfa968495 @@ -0,0 +1 @@ +{"tx": "ac7f65d102dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c010000004de5a7fabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9200000000f76d37d202d679b6000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e1000000", "prevouts": ["25c3510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "397a660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b6", "final": true, "success": {"scriptSig": "", "witness": ["1aeb72305fff2e0596cac4c211ee8a821cc9e9d71be1d3e091c05f335b51c6933ff8e974f70e13dff4fb48ea6bed4b2b8da1d7a4e34aa22a4cd7df27a413254201"]}, "failure": {"scriptSig": "", "witness": ["f5fc6f58d98f38f1438f26533faca52aee64f9dc25c7246f0356a0f71e8507d031fa6930653073620664d566bdcc9e1226aee7680aec3399c5e61583fe04eb63b6"]}}, diff --git a/txscript/data/taproot-ref/4c9126df811790be522891686bd1fcd0a7fae560 b/txscript/data/taproot-ref/4c9126df811790be522891686bd1fcd0a7fae560 new file mode 100644 index 0000000000..bc673e28c5 --- /dev/null +++ b/txscript/data/taproot-ref/4c9126df811790be522891686bd1fcd0a7fae560 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf21000000004676830d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41702000000bbb7591260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707600000000094760f703733ebe000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc56f0646", "prevouts": ["044877000000000017a914b1a54d09172ecbb89289f2a670acc3fe14ced9ee87", "4656390000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "ea96100000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21531f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["48d22355c0de34fddfd11fb995a3e98c48a4574f5b1786c3527932b6c943da9e5fa6a02efc762df0cbab1d862eeb67ba867934720ad7c1e8aac69368b5386c27", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/4cafaf85ab316a592878f9e83a2be01cfcdf738f b/txscript/data/taproot-ref/4cafaf85ab316a592878f9e83a2be01cfcdf738f new file mode 100644 index 0000000000..84a80b3025 --- /dev/null +++ b/txscript/data/taproot-ref/4cafaf85ab316a592878f9e83a2be01cfcdf738f @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1602000000242acf68dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be400000000ae8b607802db5a4a00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac46000000", "prevouts": ["b1e125000000000021591f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "55a626000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["2a8b80e8a4f54d2267cf3d402978e8bdf420668ca259624885a6428db47c5d9e5f34f52c8c25435eb0d65ca1a580061a460ead8a38f69365bc452750d37d7f62", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/4cb7d23ad1e01a5e42d3c8d927936db03801ab95 b/txscript/data/taproot-ref/4cb7d23ad1e01a5e42d3c8d927936db03801ab95 new file mode 100644 index 0000000000..e464d39cf4 --- /dev/null +++ b/txscript/data/taproot-ref/4cb7d23ad1e01a5e42d3c8d927936db03801ab95 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5701000000bcb31209dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7301000000fa266ec5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd8010000005d4ca570010206ad000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d3a8b624", "prevouts": ["82e721000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "d0211f000000000017a914a5f28fe5532719f979169bfa3a31d5746f69452187", "fa38720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100a57375666e23f9777bb1d7f3053dd358a692ac519c36aeec52e51d1ef300e36b022015cc2cdf6d01de7cea07529bb7f0cc6fec832768b289795ee9747b70bbb4121981434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "47304402206b71489933a9cc6a40bc17e90a96b73f46c16d8021b1ab4f9882bf81fe40fe4d02201fa2f81e6e0021d2e593dff95c23ede143a9c4f78121af3328ebcf6783ff5e5f81434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/4cff2a8e93a415e0cd8f16313427db2dceea582a b/txscript/data/taproot-ref/4cff2a8e93a415e0cd8f16313427db2dceea582a new file mode 100644 index 0000000000..93fd5161c9 --- /dev/null +++ b/txscript/data/taproot-ref/4cff2a8e93a415e0cd8f16313427db2dceea582a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b23010000000184e7e38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b501000000906251e203788259000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2c010000", "prevouts": ["41e7200000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842", "14703b0000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "b87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac1ca511921a6acb6b52511c7e467c1fdb04a1d5dae2a81dbcc486709376a8609dd12296fcc73680f3617d8f33f0de746e19dcfecb08411ea531ade48d4ab609a0"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0825c7be958f18497b82a5f310769c8b8ace0436200d1bb32be05dbac5afb51b7c71ca511921a6acb6b52511c7e467c1fdb04a1d5dae2a81dbcc486709376a8609dd12296fcc73680f3617d8f33f0de746e19dcfecb08411ea531ade48d4ab609a0"]}}, diff --git a/txscript/data/taproot-ref/4d21f89d57587583f18ad029ffd268e08c6deaed b/txscript/data/taproot-ref/4d21f89d57587583f18ad029ffd268e08c6deaed new file mode 100644 index 0000000000..b4c2bac9b5 --- /dev/null +++ b/txscript/data/taproot-ref/4d21f89d57587583f18ad029ffd268e08c6deaed @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c61010000001257accddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c650000000012c97ec6018f237b000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374870b5af43b", "prevouts": ["bc124f0000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "a21c580000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a6ec201a93e79c82aebcb32c5742cba4049490cef67cba707365d2e1379631f73bd198ccbfa9c702c0592bb8c84a948c36ef9eddfd1aec8278a333dab45811656e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f96bfa32a795a0be15451bd7a8acafde79cf5d8ce79cbaf82150de20d1f80e0d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d513070c0d29d47e9fe7be7df27becdaf45cc7da31561e827162b16aa01fe84c4a24f44ecb3bab6b962a7ffa14a2ce082ec551943f33ce508b63a8ee30ee5e49264"]}}, diff --git a/txscript/data/taproot-ref/4d2c30084bbdec620ff06379849a52ea2e10b97f b/txscript/data/taproot-ref/4d2c30084bbdec620ff06379849a52ea2e10b97f new file mode 100644 index 0000000000..44e6f05ce1 --- /dev/null +++ b/txscript/data/taproot-ref/4d2c30084bbdec620ff06379849a52ea2e10b97f @@ -0,0 +1 @@ +{"tx": "db04e35402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b79000000000f3aa8f7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6a0100000042e6cff403695068000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d4ac9f56", "prevouts": ["937e200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74a7490000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a2", "final": true, "success": {"scriptSig": "", "witness": ["e9d0ce2741ebf8f3365d05aa4452a7f36e1f34b95fff8a910b459f6a4f00933320a44ec1e9a54516e8862067cd9d0bbf47891320902bf028edb43cdad41927eb"]}, "failure": {"scriptSig": "", "witness": ["6ad6c352c9c549a40d14ec920f77606e7cf01369ac3fce749645bb8f742c344f5e858a5fe628d07a77597fc4aa1abecc0baa5ea13e608d4f1add8d07ae2e578ba2"]}}, diff --git a/txscript/data/taproot-ref/4d72ed31959a5c8b48c6c9de682cb5364bf0cafe b/txscript/data/taproot-ref/4d72ed31959a5c8b48c6c9de682cb5364bf0cafe new file mode 100644 index 0000000000..b22610d639 --- /dev/null +++ b/txscript/data/taproot-ref/4d72ed31959a5c8b48c6c9de682cb5364bf0cafe @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44f01000000e8d79ef28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4aa01000000a7c6011a025172760000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df9797223689874bb33631", "prevouts": ["98d7380000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "af6e4000000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936de087c66081fda9663069b4c8b042046f39088626172b4c1411a7271e0f70433938b5973806e5396d9f6a2ad240022103fc2376d5af9a7129252a47c1a6405aad5a470b8497850c3a230fee464eb343180400453804118582df887251250b2f1"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e54b6b787f97e01f22483fa030d88163bddd8804c4bcb1ddbba44b373e5312dad300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51419220fa8a7a918b3857a082d32be9fa2ecc61d36b58eead0239ee9c5d9d4afcd5a470b8497850c3a230fee464eb343180400453804118582df887251250b2f1"]}}, diff --git a/txscript/data/taproot-ref/4d9a093d9de04fcd9c74eeb3fb252b4f762f048e b/txscript/data/taproot-ref/4d9a093d9de04fcd9c74eeb3fb252b4f762f048e new file mode 100644 index 0000000000..06233c8185 --- /dev/null +++ b/txscript/data/taproot-ref/4d9a093d9de04fcd9c74eeb3fb252b4f762f048e @@ -0,0 +1 @@ +{"tx": "a115863c038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48b0100000096e9c4c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49901000000144124f9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf9010000004abe32e30189092c000000000017a914719f78084af863e000acd618ba76df979722368987dc000000", "prevouts": ["e7c0370000000000225120975437f6ff12fc45d8ef3d74f3d05cfb35811edf79338d42e1008b4e2cf45094", "6ef4350000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f", "c869260000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ba4ba1186fc601afa0c557314117fee5cddffb95af3ab27f978a84c6b0c32f2"]}, "failure": {"scriptSig": "", "witness": ["6a94616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/4db56aa4ef26d2fbb9c74967c01012f86fb5c60e b/txscript/data/taproot-ref/4db56aa4ef26d2fbb9c74967c01012f86fb5c60e new file mode 100644 index 0000000000..2e6b189edc --- /dev/null +++ b/txscript/data/taproot-ref/4db56aa4ef26d2fbb9c74967c01012f86fb5c60e @@ -0,0 +1 @@ +{"tx": "20bdf86d02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5a01000000abe94496bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb8000000008c6483c501f95a620000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc21cc5822", "prevouts": ["e9f97b00000000001655142540f27e90740933c99d4f17ab2dfc6c82951cfb", "a723680000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["7dad6448b4411583ad8d2c2bf818b3c92438e9340c508ee2c4cae7d32a0e655689d8b77e92372bd5c63edbeb50f1ebe16a828c5f28f4cb0b53df526722b611b7", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/4dd64e2309c3e9efee2d5404d847b644329d1f7f b/txscript/data/taproot-ref/4dd64e2309c3e9efee2d5404d847b644329d1f7f new file mode 100644 index 0000000000..904770064d --- /dev/null +++ b/txscript/data/taproot-ref/4dd64e2309c3e9efee2d5404d847b644329d1f7f @@ -0,0 +1 @@ +{"tx": "0100000003d15657a619affff084fc6b1bc2cdf5e85e399bb207d84ace710aa8effb82232f0000000000378eeb7906f5bd527bde63f7c45daff54c390a64a59dabeafc8078a9bd0a050f54db6b44010000000038906fb3492909e056fa5c0ef2af542be68aba07da39583e95b43e24484150891b1d5323000000000077e0c98802d0235951380000001600146d764276c66fec1127e5074db5bff3aa6c52553358020000000000001976a914b2c48f336848c91e9c274b4615a238e127bb7e2d88ac40000000", "prevouts": ["24977ad110000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "1ad1d66814000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "14cf091713000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid_opsuccess", "success": {"scriptSig": "", "witness": ["5569b5a8669183bbf7a49db9dd9ffb9c4281fda50653a980819e4ca26d199e2f6977de349db0282af31ca1fbe0902025ac9066a24a01a62c320d2d6560605f63", "20159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717ac00635068", "c0159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f7173cf6535970adc1aa2e2cd04b60847ed9656d715af72d750ffdba18631024451b7902b78fc59ae74800241e9b7a2e0578a35ace37791478c3e04a51e81e708c61"]}}, diff --git a/txscript/data/taproot-ref/4df3d74d147d4bb7144799be7f96196f44def06d b/txscript/data/taproot-ref/4df3d74d147d4bb7144799be7f96196f44def06d new file mode 100644 index 0000000000..70818cc375 --- /dev/null +++ b/txscript/data/taproot-ref/4df3d74d147d4bb7144799be7f96196f44def06d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf12020000006d57da0d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40d02000000dae2d1f001858c5300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acca000000", "prevouts": ["52eb790000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "240d3b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "1d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea5e09f506d3786832e30b2bdef7e552adbbac598072ee50ea4bccda1394a3023f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08233479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a4bb2c7d85af23cd06361a8d9967d47c0827d7b479cd52e2216fb2d12a2ff38bc"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fc4cca0131d18d8150e9d666d72698d77b9db3880415ba5ae0e811c11ff8a05c33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a4bb2c7d85af23cd06361a8d9967d47c0827d7b479cd52e2216fb2d12a2ff38bc"]}}, diff --git a/txscript/data/taproot-ref/4e1c650230dc5d5f622303dbdb697b39acc5953d b/txscript/data/taproot-ref/4e1c650230dc5d5f622303dbdb697b39acc5953d new file mode 100644 index 0000000000..c8bc483eaf --- /dev/null +++ b/txscript/data/taproot-ref/4e1c650230dc5d5f622303dbdb697b39acc5953d @@ -0,0 +1 @@ +{"tx": "fbe4c329028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42000000000fb3c3896bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5a000000001dda1dea04b72eb200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac2d040000", "prevouts": ["268a3c0000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8", "fd69770000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08252e804f6a261e09ec86c0fb6e6ff5b26564af7d86f56b1539029a07a3794a04021136d3d9ecdf371b2101a7e86edb56e15b10ef185a8506988239bb2b5a4c43e"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936816862a3ca4ec462993bd240f6039fb5376ac85de732ed6933e2ec585e28dd4d65775dfb1ab8912d99abba269b246de78dce1dfa6fdc8b38f44f7be80bcbeb76c308d8e78b0cea59e70bbcac5990a047bb63a968328232757672e5e931dda055"]}}, diff --git a/txscript/data/taproot-ref/4e27213b2fb3cbd2c324c9d967eb6837151c512b b/txscript/data/taproot-ref/4e27213b2fb3cbd2c324c9d967eb6837151c512b new file mode 100644 index 0000000000..9f69ce501b --- /dev/null +++ b/txscript/data/taproot-ref/4e27213b2fb3cbd2c324c9d967eb6837151c512b @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c45000000002883818660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d100000000f7bd9f9f0118376100000000001600149d38710eb90e420b159c7a9263994c88e6810bc75b020000", "prevouts": ["6076550000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "c041120000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a5f69c5070a670eb4b1f18f2f2ca5111ff00de063a8ffe58727e3dfcc80e4d9921c3bad5225c42c0ecc3da53f98a2c7daf8df9f7b3fb65f74896047d7f1e7bb5619e0bcd71f4d839b5949e01b74e3a38882aeab134d3b043f234bd7c0fb20bd7e397323ba0ced905103554894c438cd3b300a3fd351248bccbe1a84f8e76aa771c90181ab4c7713e81fb73a7f6ea8e1be0dc1257b5b7e392d3d36ac1bebb5778a901db1343b1ab2b6aa3e9287e3e6b4afddec10c20b8032e07812f5cb31d663fe6a7e59820141d992fa653719eae90a72afdd7426e658ffbe75681c3a3601869d7fa15429aec39266115688f130faeb52c86ae4c11fae9e745d70675e434b674ed9ac2b7326ff6fbde3e563764c83495a8878f07eadbd17805479d1f3a0895e0f2fb85995f99ea079949c655955d35c5f8d4ac8ff249ba904b36a2af40c20bb69b18a4705c50ee94c429fee1d48abb6f9c2ebe6c92b329104284b1fde0c19d135cd0748a00a40a256a1fa9a442a27e900c52ee9c9364038779817a8b89a819a3092af96b419d543c9fc125220e8f574c3ee34bfb1a38d5908a735a456ec9b8c8b0319d2483b66e6f6535b39d6de47960fc1c1526ff5086d599cc5f1c33d157f50bade7baadf51f1eb23a046c47edaf735ba7ee786dca7b1febb5289cde4c6828636211b4924d4ca4072e136744ee10ab633925a22bb2d83ea2e050cdf9142161570b68639d0b6e0bb275", "167d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e93bd46d889920012fd3d654be778806775b1e6ea0b6836161b66543651907968afd13a3b2c4c421c5355668ae9e4eec8bcb7618363c6e35efd204a43726d22d6"]}, "failure": {"scriptSig": "", "witness": ["4d09027c896ed8d46430539ee5555fce2a157a6485859d27de823cf638edb528d3c516cf8bb2daa98e673b6c0c05bdf1a7848a11480f1b7d4385b31f8a268c061ccf50973260095546c2b3bb54b46b44a9f4ebee2504d8ebb2d8e96ecbda2cdca07a30dc9eb7d3c0d6ba5938bbb4d99d19f1e90fc53f77e11bc53c0bc63f64e207bd4f9725bb7af6944d50cbd4707f47f63f99ba045d9e361487ce7d93546646d4a1c83e1aaa4b074683d3cb846e92984dad986f4e7f525e04d84ed01cba48956e1cd8d1dfd686094981750ef846363864e34be8db27965df475178304405cdef9e71b42a30022859e5f98588d73e209ad43196ec31c46232d6c660523b54481c38937099fb046938913a034979bfc758fb81a2e2e29b5710b8964a9aff79e28f455cc58a988cb32767812bf19400fa13a26823ab838a418f1bd8d5068a4fd6d2c9a09ec2fb8edad228ac4685861de436efe4666e6b7bd2957e7701f727a994091500de471d99f70b7225ea1142b982be70140aae8e1321b31f10133dee142cbfbdc1b76160bbca1379db44b6d7cc503f3380808a4444f3bec4145d5dec38305ddee294c540bd404bbb35d501782ba646700f2e3c348c4bba2e93ad1fe51901fc6bccbfd0d8206a632fe12a14f0a4f5db42a042b48fea00608a0fb5c9a70cecdfad7e80209b0c5906dda82369f1dcf521147f0d57664337a11371e7f6fcb0764a7e694c8f4271ffa301d004b75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ccc651badf627d83c4536dc19a84e418ac77e4d8a40e4afa91bb66f57df18612d231140cd01d0310e585ecf2f38aee8d36f3a935cf5b06765b4319c9202713151e3355b9fad1d20bddcd1a8531bcd58c93c4d9ee4159d68db4e08ecdffbe17e"]}}, diff --git a/txscript/data/taproot-ref/4e442bf704b5166ed40da217a4f0a6103e117487 b/txscript/data/taproot-ref/4e442bf704b5166ed40da217a4f0a6103e117487 new file mode 100644 index 0000000000..72cea4bfce --- /dev/null +++ b/txscript/data/taproot-ref/4e442bf704b5166ed40da217a4f0a6103e117487 @@ -0,0 +1 @@ +{"tx": "ddda8eb9018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41e0100000049486be003053e3000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7968e65065b", "prevouts": ["d021330000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "4e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366eda255a985f9018ece0f2cdeb0e084c59fd6623beb306595ce95e3d71dbb86b9d8abe9ca6155576d0a7d6ce7b2728ac84476385b9c54c38b8a9cbf195895186ab153920b849b6028620ffd2b7e486a6f5e2411aa058dab621c72a45f67f5d8e"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f5f9e17620b9e5ee117d28ecc81f7c66357561166fee94fa9f70f6d3f1a5605d1fd3f29d710dd7ef94713df6d8e3b931ee02ef1dd830d0dcb285a37875735c080d03cc4210f6c8d536ca11754de7a86c068de81055f4750ba9e0b801f8560f6a4a8046f0466b39966676954eca5d67ee52b1615e6fe46612ea9ab4edfa131fb"]}}, diff --git a/txscript/data/taproot-ref/4e6bb871c5b2e524530d3675221cf34b2e598538 b/txscript/data/taproot-ref/4e6bb871c5b2e524530d3675221cf34b2e598538 new file mode 100644 index 0000000000..425a343d13 --- /dev/null +++ b/txscript/data/taproot-ref/4e6bb871c5b2e524530d3675221cf34b2e598538 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fe01000000955e53b2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4701000000658363c5011e667c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e705870958", "prevouts": ["b6c04200000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "09067000000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "4c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082126001c6c44c6d65a09c6d1b267ed4323a5b88ec68ff3dda19058d2d3d94a32d819d45740b1e9d6e416a8a4978331345395bf058ef0b936b66c7755017d83c65"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d840fd1b4336118158b49a207c7c1265147fcdb5164c3ca7c69b8b407af04dfd126001c6c44c6d65a09c6d1b267ed4323a5b88ec68ff3dda19058d2d3d94a32d819d45740b1e9d6e416a8a4978331345395bf058ef0b936b66c7755017d83c65"]}}, diff --git a/txscript/data/taproot-ref/4e7f6d1d5ff623f2b978feb61b0905320a14cea2 b/txscript/data/taproot-ref/4e7f6d1d5ff623f2b978feb61b0905320a14cea2 new file mode 100644 index 0000000000..b91cd108e5 --- /dev/null +++ b/txscript/data/taproot-ref/4e7f6d1d5ff623f2b978feb61b0905320a14cea2 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b200000000ea14fb878bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d000000000294766f002728a7600000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87bc010000", "prevouts": ["72c13d0000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f", "12c53a0000000000225120a7af56c53f6997dc9f888a8c6887a5f8ee9cb96a9d70fc301f3f9e386ed85991"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b4c2acc3f3dd22048883df4c6ef8926d4d7a863cb2abccf3932c00a61d7b20b7"]}, "failure": {"scriptSig": "", "witness": ["6a91616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/4e8673f1a272e7a4846b2b13fd4d6d699de0dd4d b/txscript/data/taproot-ref/4e8673f1a272e7a4846b2b13fd4d6d699de0dd4d new file mode 100644 index 0000000000..c8ea1a7199 --- /dev/null +++ b/txscript/data/taproot-ref/4e8673f1a272e7a4846b2b13fd4d6d699de0dd4d @@ -0,0 +1 @@ +{"tx": "9323717b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9f01000000a919a7ebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b380000000000b460fd01079d2e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6da000000", "prevouts": ["4a23220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "54912800000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b5", "final": true, "success": {"scriptSig": "", "witness": ["be514faad4f3c1d5b1c84ce536f35155e145ae5f45a7dc398aa182c4bbd1c6d6c992b79c2a13682f1442ef3230131f2c5bb67c9ccf42e2373e3d8b88ae45381e81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a636eea579fa3a3a3025ff72706dfff0b95d87a7bf40f0a5b3553671ed021b993faf2a1f7b44b0e8d1174841469e2134d1eb94fec8caa47c7874d235aecf5f57b5", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/4e8dce29e5e8dce89954f8535e95a66c4dec52d0 b/txscript/data/taproot-ref/4e8dce29e5e8dce89954f8535e95a66c4dec52d0 new file mode 100644 index 0000000000..8c7c374a7a --- /dev/null +++ b/txscript/data/taproot-ref/4e8dce29e5e8dce89954f8535e95a66c4dec52d0 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b76000000005231fa1703f1e32600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487b1392128", "prevouts": ["0e6b280000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "287d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e780a528759e22c32b672b3582ec3b98210a6d7cdb045b8c2f36dc39043db702a61bc10490c3b13d9c4f63caefcea4aba06d3a92ca8668ebd56c703a638058ee7"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ae0185d73b30cde4b6f847d95b0ec77b009b44599f3d33d8be12ed96fb030558462eebfc32d9e48af9ce92e50735d36faef083a1171bd1899835a9be2fa30ea55b4ae3ee914d52223472aa57f653ca8073aef0e7910b2553778e1ae03228475361bc10490c3b13d9c4f63caefcea4aba06d3a92ca8668ebd56c703a638058ee7"]}}, diff --git a/txscript/data/taproot-ref/4e98f79b12c1bcc786816c990038e187b1881a2b b/txscript/data/taproot-ref/4e98f79b12c1bcc786816c990038e187b1881a2b new file mode 100644 index 0000000000..5d9fb5e50e --- /dev/null +++ b/txscript/data/taproot-ref/4e98f79b12c1bcc786816c990038e187b1881a2b @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8101000000d15525dcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cac01000000f2c7c6da0498846a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acbf000000", "prevouts": ["b8cd240000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "6979470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f3", "final": true, "success": {"scriptSig": "", "witness": ["43867394a86759c616af12ad200d02086bbc5efacd7ec261476e75ba65ef99ce80bb987008bd7224c30a4eb00c40c5f9873ec3bf1c0140ca25aaf45edd96285b02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0fba4f1802ebb4446ea3bad58a8f7ef7b26b00af5348d8340103a6716dd120247aed3651d2b9a2b56eee0bd252c1bbbc0abbabae4094dca6d97c11c7b2ad0e82f3", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/4ebc10c30a1a1250dc40fd49051eb8cadd3eb677 b/txscript/data/taproot-ref/4ebc10c30a1a1250dc40fd49051eb8cadd3eb677 new file mode 100644 index 0000000000..51745e8e2b --- /dev/null +++ b/txscript/data/taproot-ref/4ebc10c30a1a1250dc40fd49051eb8cadd3eb677 @@ -0,0 +1 @@ +{"tx": "20bdf86d02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5a01000000abe94496bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb8000000008c6483c501f95a620000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc21cc5822", "prevouts": ["e9f97b00000000001655142540f27e90740933c99d4f17ab2dfc6c82951cfb", "a723680000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a3", "final": true, "success": {"scriptSig": "", "witness": ["9ce4dce770b5f580ab75751e45f91d42e90da09af3e13660dabd5c89e4365a5a8028d4418ac3810f295fe076998c8e86ebad13e00b0db526b76016058196cb6501", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["795ed4081216e0d2fc5dbc1c7e6cd5bdee1cf80bee75bbfe6f4ce03134550c43e1202e0a8a37e2f11b47ecacc9271059cb348399c9f33b7ea7e45a19d7cb3c78a2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/4ed19b212daaac7d9ddf8fbed04bd645b3540c87 b/txscript/data/taproot-ref/4ed19b212daaac7d9ddf8fbed04bd645b3540c87 new file mode 100644 index 0000000000..d78c1439ca --- /dev/null +++ b/txscript/data/taproot-ref/4ed19b212daaac7d9ddf8fbed04bd645b3540c87 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7400000000ed794b8ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2200000000422cea9001bc295b00000000001976a914c629d61df58baceae110d15eb5b55e144268615388acaf970346", "prevouts": ["1f3653000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87", "fdbc5a0000000000225120469ff3412c89f5805e53fbb9303c790a98dd32093d40e3b7dfe22bb05f85f37f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402205545430d2c1b412c1571a70f3df83420460c789d74754b91f8be4d1658788fa302202fe34318176878e9e7d56b3588928cc6d3eeb377221fb50d42b15df5ac062c0983", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402206455b13bba26b5ac6066c6a833d34727b3376fbdd36252d4566faf1b19f61f4902206b6b0e4c73215086cd19bbc0cbb69e4c3000ebeed73ba47a14b98c621da7a67883", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/4ed948d6df09636962a55dc16fa8141b57caf0a8 b/txscript/data/taproot-ref/4ed948d6df09636962a55dc16fa8141b57caf0a8 new file mode 100644 index 0000000000..66a58eead5 --- /dev/null +++ b/txscript/data/taproot-ref/4ed948d6df09636962a55dc16fa8141b57caf0a8 @@ -0,0 +1 @@ +{"tx": "af5f933c02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2d00000000e528e6848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c439010000007ad0089d046ddda8000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac76000000", "prevouts": ["1a906b0000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "abfc3f0000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["fe4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93679936465fe465f0d401827e55c2317c08ad696e5227da5899b92494a3d57c5ba365bb68c3eae5e6cd9b20289e581f52d4e8c0cb4ba58bcd8be9e67bc80fb920a1e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}, "failure": {"scriptSig": "", "witness": ["4c52fe", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3b44d8b0f62b2d27de7be259100200d6da1e5303b29f3eaa1b6a4eeb0c96a42f364ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}}, diff --git a/txscript/data/taproot-ref/4f01eb0e5c5b453e93d7259acca78110e06e0cdc b/txscript/data/taproot-ref/4f01eb0e5c5b453e93d7259acca78110e06e0cdc new file mode 100644 index 0000000000..e66d3f60da --- /dev/null +++ b/txscript/data/taproot-ref/4f01eb0e5c5b453e93d7259acca78110e06e0cdc @@ -0,0 +1 @@ +{"tx": "53f634e403bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8d00000000fb2721ebdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c86000000001da8c8acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5c000000003f491bb602892f0601000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7ad000000", "prevouts": ["2902640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e4a94f0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "e76455000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_1", "final": true, "success": {"scriptSig": "", "witness": ["83612559b0673fa4042d1e6bdb6d5f9b8451f0132ad5913994aa6774bab5bfb6490f9ae076c61e175b90db6e63400952c4150dc28fcf447661e34f82a44167ff01", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["4721cf3ab5cef3685ef13017a460e4d543b1d0d35ed7859204130c9c34254d2a9082b9c7393d2ba311d336b187de688d7e9bb6c3efd30ac3254d88839136a77901", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/4f043f492b006187a12d4a27a2fb711e089c21cb b/txscript/data/taproot-ref/4f043f492b006187a12d4a27a2fb711e089c21cb new file mode 100644 index 0000000000..a546c9dabc --- /dev/null +++ b/txscript/data/taproot-ref/4f043f492b006187a12d4a27a2fb711e089c21cb @@ -0,0 +1 @@ +{"tx": "ce36f33a02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce1010000007e650397dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfb00000000bd1a57b903916ea10000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374872b040000", "prevouts": ["e45c4e000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529", "90e355000000000022512009252952876a5c13cea12f753600009323d5e64530eb665ff4d131016b9c0911"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900458f435ba6abdf70be4dec7b2a0789d26eb9361219ce4916c9f3e2c2146b2213509dff863108f68b54d204f4b43b2fddebfd69630b8c1a20ba8be96c4e7e2557a5003e045cb689fe4fc6de332c618eb0cdce02c2dd8aae7c6dd6f70bdbaede2814"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363af132e2ca2e1ee00faae667175800cc2b7e8c9bbfff591958a2cb32b4e92f5d4c57128c8a67973c5c0637342f282ffab122f5a34eae9e616b37e48a600a7a243e02ad6eabd24d4d247e98c297de2a9d81d67e55d72d4ddf06c8e9a23565ad8a003e045cb689fe4fc6de332c618eb0cdce02c2dd8aae7c6dd6f70bdbaede2814"]}}, diff --git a/txscript/data/taproot-ref/4f31274445bc35aaf35c1fc3838142b83f4e4dbb b/txscript/data/taproot-ref/4f31274445bc35aaf35c1fc3838142b83f4e4dbb new file mode 100644 index 0000000000..8b695c0346 --- /dev/null +++ b/txscript/data/taproot-ref/4f31274445bc35aaf35c1fc3838142b83f4e4dbb @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3800000000d4d32d95dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb4010000008376eebf04e5a4bd000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac14000000", "prevouts": ["7e08700000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "c0bc4f0000000000165d142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["f9b86e355753a0f7d1178f44a1088ef38025cd452017401a4b3fce94aaa7151fd173eef0f43ce56565e4f7a6a39231826f79f45a6667b46547c758980615ab85", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/4f3b0d3de5e5a892c662d05f7df9b836b5083f4e b/txscript/data/taproot-ref/4f3b0d3de5e5a892c662d05f7df9b836b5083f4e new file mode 100644 index 0000000000..c5ef65d1d6 --- /dev/null +++ b/txscript/data/taproot-ref/4f3b0d3de5e5a892c662d05f7df9b836b5083f4e @@ -0,0 +1 @@ +{"tx": "2c3a87c40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ab010000002b52538260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707e00000000bdae3c9301fb521000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72c010000", "prevouts": ["b42f100000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "cc000f0000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "b87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8d64c15a931058236adef8a4965d2af6c40e751c52c93bf72b53dfa72cc6c024bd12296fcc73680f3617d8f33f0de746e19dcfecb08411ea531ade48d4ab609a0"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e5c7be958f18497b82a5f310769c8b8ace0436200d1bb32be05dbac5afb51b7c71ca511921a6acb6b52511c7e467c1fdb04a1d5dae2a81dbcc486709376a8609dd12296fcc73680f3617d8f33f0de746e19dcfecb08411ea531ade48d4ab609a0"]}}, diff --git a/txscript/data/taproot-ref/4f3eb1205832e452025bc7463ab84f005ccd56a6 b/txscript/data/taproot-ref/4f3eb1205832e452025bc7463ab84f005ccd56a6 new file mode 100644 index 0000000000..9bfaad59ec --- /dev/null +++ b/txscript/data/taproot-ref/4f3eb1205832e452025bc7463ab84f005ccd56a6 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127027010000000982f9e7020d680f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc1077a92a", "prevouts": ["160f12000000000022512088dde8afd13f0194fca36526be3687127f2e7cf17d2220794be262690544ab16"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cf710f3f6686759e0a7b7ec2e518295fe9deeba1571514a4091d7bbee9df99b8"]}, "failure": {"scriptSig": "", "witness": ["6ab6616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/4f444cefd89a49cf66c69836b968e18c893e6243 b/txscript/data/taproot-ref/4f444cefd89a49cf66c69836b968e18c893e6243 new file mode 100644 index 0000000000..90c15c92fc --- /dev/null +++ b/txscript/data/taproot-ref/4f444cefd89a49cf66c69836b968e18c893e6243 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c750000000034d93ff2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb10000000088399385027739dc0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac02010000", "prevouts": ["d9be5a0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a", "22ee83000000000017a914c7d65cb5025eac8b5bf295baac9287994ab34b9b87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "225b202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["c6a3f8462131ece7a4ac60951c40c9603b0811c484aa5c62e77f857913a067d7812a85f46e165f2f418a62fd4027001f434c3bf0800a2aa3069e845da792ca4f", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/4f4de778bdec3be4e7cc1f875680330eb9edda65 b/txscript/data/taproot-ref/4f4de778bdec3be4e7cc1f875680330eb9edda65 new file mode 100644 index 0000000000..23ea469845 --- /dev/null +++ b/txscript/data/taproot-ref/4f4de778bdec3be4e7cc1f875680330eb9edda65 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21010000000ae3668c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127048010000008de810588bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40d00000000fa4dd06f0403f6a000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870d92972e", "prevouts": ["96975b000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "3597120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cab1350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype0to1_scriptpath", "final": true, "success": {"scriptSig": "", "witness": ["2001921562bcace39e2b7522191d9d46e9564579cb9c9f7f10823e4b0c0914cebde959a558bbea6bfb69bc26dc8e041042c0546784c77c9a3639b8653838d338", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["2001921562bcace39e2b7522191d9d46e9564579cb9c9f7f10823e4b0c0914cebde959a558bbea6bfb69bc26dc8e041042c0546784c77c9a3639b8653838d33801", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/4f54816eeaa1958560b3411df01fd36e2cc3cf78 b/txscript/data/taproot-ref/4f54816eeaa1958560b3411df01fd36e2cc3cf78 new file mode 100644 index 0000000000..bd9cd98da1 --- /dev/null +++ b/txscript/data/taproot-ref/4f54816eeaa1958560b3411df01fd36e2cc3cf78 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c02000000d71284f38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a6000000003d5157d4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8501000000f9d154d30318e4eb000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33000000", "prevouts": ["bfc05d00000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428", "4d2b37000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "cbce580000000000225120aa00b33df18083b0bc269fd07ade71d6a19be5cfe3bbc4e226f77b4058e47cd7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["eb4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360c54e1ada67eb35c9fc75440012c0966dedc9197e6aa1f92cced4ba861a6e0736873018117c319506164013bcdec2d285df0b840d64f5a35ebdb06eb3e2afdaba9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}, "failure": {"scriptSig": "", "witness": ["4c52eb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f7503786cb7ee92eae5d70fa92690036da7bdf6692c5c1fbcf5def7599471201292070a98a4b0647c95affa8e1bd4aa189d67ab6e78b6f1cfbf1b9e41a8f8bf399891b33f3277cd8a2b8473e2e6079de1e6f51840c7864da48d9f2287dbe494cf9ce2244c675144b577c27c052f9ebd481172245e28e9502c6c6e8f12c64fa6"]}}, diff --git a/txscript/data/taproot-ref/4f5d2d6eb42d852d85a2d40419830ff372017208 b/txscript/data/taproot-ref/4f5d2d6eb42d852d85a2d40419830ff372017208 new file mode 100644 index 0000000000..98690482f9 --- /dev/null +++ b/txscript/data/taproot-ref/4f5d2d6eb42d852d85a2d40419830ff372017208 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe2010000006a60a6e6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc700000000333905ed029b4e95000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748789e0cf22", "prevouts": ["f9d2760000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2", "ac4c2100000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "717d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820b90ee144c073a081d1ef827361e7936248dbf88e4cb0dcdac45f51ff02f5de2667dde4f09f14471eadd81946489c41cf4fd01382a4947d773f1f2d4d0db4c57"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936934e71b25832c3b522010201f0ea45f4c2c0f78477650c948e369f9a59638b5a47c0542868f8d04f04b11c7797ac2650c695e4f1f1a83ba9fe9a249175e916721e193f5d3ae2ada43ea9223ce508afaffd6393e3458e5d7b2b04f710aee774aaf4fdc20f1f5535ceda7aadddab857a143114b7886b058839365016ac02e93c97"]}}, diff --git a/txscript/data/taproot-ref/4f692f08e2284094269303792599c3ca996925a1 b/txscript/data/taproot-ref/4f692f08e2284094269303792599c3ca996925a1 new file mode 100644 index 0000000000..3f6ae1623a --- /dev/null +++ b/txscript/data/taproot-ref/4f692f08e2284094269303792599c3ca996925a1 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41b01000000b82575a3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6501000000474aeda00135f745000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47876fa28731", "prevouts": ["0e6e320000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "0ef12100000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "0b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93684c23a4f834a7effc42b1c4f88dcc82246b0d4e764e461eb4f4db8348ecfb3306eee185c5450ca8ff820874ed786a77ca41a0ece110e4e1e272b53628d0f659ee0d9bed60e53dfa6fe8b58229f37daf0597893c765c7b30814eb9e16fca89b86"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef92671edfc08b1595b62488145cc68a42644b51379cbb9ed71181eed5e56f97e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8784d9e7ee919b8817f3904ff7d27b5c3a4ce3798ed5b994b75288b8e9341d9b42c78e40500fa05b550b7f6357dbf83024c41a574f6a1706762c104fa8aec3fcb"]}}, diff --git a/txscript/data/taproot-ref/4f967edf0f22d51ce89c007d5351844488bfc1d4 b/txscript/data/taproot-ref/4f967edf0f22d51ce89c007d5351844488bfc1d4 new file mode 100644 index 0000000000..9a3d3e2dca --- /dev/null +++ b/txscript/data/taproot-ref/4f967edf0f22d51ce89c007d5351844488bfc1d4 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c438000000001ea2ccb8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf180200000014118e3a013b6381000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748747a2fb1d", "prevouts": ["0dfa40000000000017a914f0ed99a28545ab2ceacee60b5537a9e5c34fcd5187", "67f27700000000002251202b6311c61a2a508a144ec510c52a71fff5d62c4fa86296d42faefa4fd619b162"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "215b1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["09e9fcaea32a4aa595828226e2229902d1d88d4c7faad932d9658fba57fc06a73098bd9f61f3b0a752472bed18c70cb645844935573e9647fad8ed6d42a89396"]}}, diff --git a/txscript/data/taproot-ref/4f9df26c7948631ce06cb7292bcc481337bff811 b/txscript/data/taproot-ref/4f9df26c7948631ce06cb7292bcc481337bff811 new file mode 100644 index 0000000000..e0f02f5435 --- /dev/null +++ b/txscript/data/taproot-ref/4f9df26c7948631ce06cb7292bcc481337bff811 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0f00000000fea24c75bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0402000000ffd0d85002b76feb0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72e261f40", "prevouts": ["aca878000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "3ab5750000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "473044022004040759a1961cfa82671ebd824d6cb4d62cfcc34da58a47674854aa3f3b49bf0220408c7f4d185c9fb520fbad8f1fc2fac04fdb40f0cb2bb22146d386ea7a8b553f16232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "483045022100ebeece7e8de8b04f144fb82fe9c6faea740fd4e5fd4091b93d66424b005e6788022035b3bfdbb28d5ee1576ae08be40fa2dc83ef49f24fd7e33f9a83014f2b6bafc016232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/4faee5238fb7a4ab5d716bcfb441ef4b0ab3f888 b/txscript/data/taproot-ref/4faee5238fb7a4ab5d716bcfb441ef4b0ab3f888 new file mode 100644 index 0000000000..e7c858cbed --- /dev/null +++ b/txscript/data/taproot-ref/4faee5238fb7a4ab5d716bcfb441ef4b0ab3f888 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2d0100000067095e1ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b00000000b27fd181049eb8c90000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df9797223689876a020000", "prevouts": ["9d75660000000000225120de7c17758b854fc68d3061dec4ffef020214eb4d128d0a0aa1b6bff82dc51d5a", "f6a1650000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f35a9e9183b809919681c9ebf7f5998e5393f3a0b75bd60b721d49b380be8117"]}, "failure": {"scriptSig": "", "witness": ["6aaa616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/4fc70db2882c50f92cbf554605f20aa8afdc9e7b b/txscript/data/taproot-ref/4fc70db2882c50f92cbf554605f20aa8afdc9e7b new file mode 100644 index 0000000000..281e866530 --- /dev/null +++ b/txscript/data/taproot-ref/4fc70db2882c50f92cbf554605f20aa8afdc9e7b @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c02000000d71284f38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a6000000003d5157d4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8501000000f9d154d30318e4eb000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33000000", "prevouts": ["bfc05d00000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428", "4d2b37000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "cbce580000000000225120aa00b33df18083b0bc269fd07ade71d6a19be5cfe3bbc4e226f77b4058e47cd7"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692171dcce0f83dbc374f842d6c29c40444bab2dbb43dfc5467e2257ffee5e878"]}, "failure": {"scriptSig": "", "witness": ["6a77616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/4fd09ff1c3fd39676f5029f8a82082c4a788cbe7 b/txscript/data/taproot-ref/4fd09ff1c3fd39676f5029f8a82082c4a788cbe7 new file mode 100644 index 0000000000..8b7e398b1d --- /dev/null +++ b/txscript/data/taproot-ref/4fd09ff1c3fd39676f5029f8a82082c4a788cbe7 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d901000000d5ab22dfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf98000000009e40c06902500e8f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796b4d1895d", "prevouts": ["8fbe0f00000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8", "f80a8200000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "997d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb3e0f47209c8bd03f9c1f4c84e35056958ab5882c2791c6ae554831739033813d673df10a8cc98fc65477367c7f3bb838b82569297570384f0d4df8cd49e6dd413afa0de0ff2ef52577d4c80443f6003c675907986908c28bc93ded208ca160"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cdd31c127df2ea056bd7aeefd91119cf1ab5be9ea7b27ebeefbd713a415465b774e6e02235f222bedd00290eb9daa035321655bcf09c112e5b4a77998f5c860a0e580b14ffff5bbee812c9f6e3af6b100c6b4cffaf41971c257964f1fb14f6f9"]}}, diff --git a/txscript/data/taproot-ref/4fd67112498e9041d549dca8902b4b18f4151e0a b/txscript/data/taproot-ref/4fd67112498e9041d549dca8902b4b18f4151e0a new file mode 100644 index 0000000000..72d2d88ba8 --- /dev/null +++ b/txscript/data/taproot-ref/4fd67112498e9041d549dca8902b4b18f4151e0a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7e00000000208666d98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cf01000000b7b13eed03661d95000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acaf000000", "prevouts": ["96b259000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "a73e3d0000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000da", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aa25749a9d031bca906e25f3e351ca93a9a7d139f4eba150a9b4242be9856031d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5148d61d9b48b1fd3c9dcc7ce9fbab23c91d7bbaaf6610449bdfa8b9a4fdaeae22ee4d75780d36bffae9b56136e6d27c02b8d233efdc800bb260bfbba6a6f94b87"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08216c8ab92abfbe4bc2686b5b42764123e12e1b7fae7b64d8b1bf7005c7df7fa0a3ad7647dae649c97c815eebecc244cfd5d14ac6da92e0e18049c71625e2af9496ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}}, diff --git a/txscript/data/taproot-ref/4fdbb01ee1c89fea2c908ade5230cbf49b493184 b/txscript/data/taproot-ref/4fdbb01ee1c89fea2c908ade5230cbf49b493184 new file mode 100644 index 0000000000..a6d5d22e02 --- /dev/null +++ b/txscript/data/taproot-ref/4fdbb01ee1c89fea2c908ade5230cbf49b493184 @@ -0,0 +1 @@ +{"tx": "02000000017cacf58c1885ec7a53b7658a58e4f1dee7e8d7a954fb736b3a502279c0be18ef0100000000ddf8e0e404c5a5538b160000001976a91472fb0c729bce8fb851f92a5ad48d3d4231beda4988ac5802000000000000160014f2ca549f2f8613e81a7cb48fd110f37b7fb1529a580200000000000017a914ca5375a68588393c82c00f5d2ab21f91e99aa5ce8758020000000000001976a914a875a4732dcf342e2587f26f2b7b2ea4a2fd587488ac10010000", "prevouts": ["979f558b1600000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_invalidsig", "success": {"scriptSig": "", "witness": ["cde641a27c5267172f2757bdf093f55c990d9cef17568a37276c373b3597303004035690bf6772d6c9ff5401569850db8553020c011ff0530e988a693d5fea34", "20cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3ac", "c0cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f312f383ce02997bd7885b2023ff24b4d79c49e77348af650460f5903df7baafc9"]}}, diff --git a/txscript/data/taproot-ref/4fe78456cf82ee1f4f6bf880baf672a53376c62d b/txscript/data/taproot-ref/4fe78456cf82ee1f4f6bf880baf672a53376c62d new file mode 100644 index 0000000000..599a15b6ed --- /dev/null +++ b/txscript/data/taproot-ref/4fe78456cf82ee1f4f6bf880baf672a53376c62d @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45600000000205bddf760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700d00000000c8f1b58b0186fc1f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478744990c28", "prevouts": ["28b5380000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "36b6110000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090216c5c5bb97a54d41103c735c2b8c4a1a5c1039b3ad59da9dca82283fd083a7fd49f1598556e1afeaedbcd178daa05bb8ae60e78836b958581f7926b5c8623020d28ab9b179756e1536af0a4d93bb032b7ac64f81d807513c95471d2d2e8a73f0e5d7443d044b32bbfdd5a2329e73f35c3bcc60628fde61058ed3fff8a5556f8c5a3cc9a46004ca4a796c4e948f8e6f75e0715f49cf23e8ce4d0c92953fa6c2751530d24f44d4e5be183fca935312dab312448cd532f70bc4933caa524b30b317e15c818c9092052611ca51cbcb3e2efe25c2c330023a91d576b3bf35d26b94dad64886a0eb0fb9d4b56aedeca9e087037c5e74b3e1fcde03b0121a9fcb4ea41890efeaa41642118552ef6d5ebc3bff9c87c057882d23518fbe2b92c1b96c67bb29524bf13740a5a8382f668c5da6dc44e943235d2abb047923ae340c0249e612f649801bc971101f02c6b2cc6834bf79961b156e6564b132e0663cab7faffb55de954ca33cafdc1d1f9538b05b1d4983c0d2e7a64407486fa2449d74bd759df93b900fab2e244d563ebca286781f3c284f6d22815aa116514be590bd371626307fef8356068a58bf347a73b9260ddffb7fb726343d8b156e16729296004e5f08d9042b1dd5ba348847e649b7eb9ca7fb69217987db5b254d25197a9e1f51c15d78b760bd506c2ea5c242bf12ba2d73e491c814a6be544a73de8b25a6a31a8340176eb69bf0013cd09c75", "d27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661b2c7f111ba6ec1e70ffb2e90369bb1194c2022d0cf3fc398f654044cd38fea9a9c5d9290705897ef911507dd26b72756738dae23c9379fd676f365e52e00fbc5e1171eec0a28263e9818d2dbd976f4b8066e50dd8906a411b6a9dd47f52980e39f192d4dec24b48e9231a08b7d2e64fac2040aad69c16c1d9eedfe5fb62ebc"]}, "failure": {"scriptSig": "", "witness": ["4d09022f0997b23c3f9db654af0f95d661e3cad62b9ef2fe8e535048f918b94d767055604f13b5163000c19fd8df4b61012b40a425fec229f2e296106ed26a01296d5602d9d242f0dbdeafedfce29e753d580f7512631c167fc145887edc6276d626c50acd008c695efb4805293aca2665c1776f26835ac8a631f9b13b78726a8d29207ec8e768f6e0d0c6a55263d0c24a7d59393b4278e89ede22d5a12fa17daa8e0474a80b6b3014b2e49d0873ae3c86dcf34452e29244734fbdbcc0392127e9ae59e8ade19f9493e67c6ce59d58d9d45231bf4079341aa3e8a584d2498c6b9058e483a2b5f5ec9ef32215ba72ccbd029cbfe85d16229800ba810ab4da8dd3689b489aed0d7915fdaf8ba542188c2d606e3419b57d111b4a13600968f6c4fae8cb19edb97f05a901cc53ae57840679d099613c0629fdf9b9b9584bc7d13408270114ce46c12c4068028a10fd23dd7b856e72cf3594e00be636546c202e215c7ca18ba7e37fd35d3e456e06f2cf335ea2632c1f0eb4973ecef6ce50254addb814893b36489abf8d1b283d2d2bc4b3e89fd1af20f554d788727b09e190d29d6bd444e0d450b571612db7b5cd8859c338cab823bf9ef1ad02a08baf0b4698541944cfba0180e2b7b43cdc007409def61174877ce6426b3959b441f6d35ab4f58aaee3ec633f83fd20708c8d9632dec5edc836e5e145e358ce4902bdbfcf21d481d0a5db7c060ba1be69734fec75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd98210eae0fa98a1319e0f8d015acee739784c329755eb742bbe2450ea9c34cc5e1171eec0a28263e9818d2dbd976f4b8066e50dd8906a411b6a9dd47f52980e39f192d4dec24b48e9231a08b7d2e64fac2040aad69c16c1d9eedfe5fb62ebc"]}}, diff --git a/txscript/data/taproot-ref/4fe9d51c1a4a51db63ace4b7593bf4d0179da70e b/txscript/data/taproot-ref/4fe9d51c1a4a51db63ace4b7593bf4d0179da70e new file mode 100644 index 0000000000..44177aa804 --- /dev/null +++ b/txscript/data/taproot-ref/4fe9d51c1a4a51db63ace4b7593bf4d0179da70e @@ -0,0 +1 @@ +{"tx": "706e0a0002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd70100000024a962a960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b600000000b076b3840399c468000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2b971d54", "prevouts": ["cf2e5b000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "ad3810000000000017a914613e66961ccf40c7c83ed07cc80b2528cfe51edb87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["ffb7fe6f8c670a9fbcab42d8e49650ec5cbcc1fd92640bbcdbb19aec61302f2984e22b033cc8bec4b2e1308769422d14f23b55d485fd17856aeab0601a169b81"]}}, diff --git a/txscript/data/taproot-ref/5008a5b791ae73ec29ac0e451b2193e921d7d91e b/txscript/data/taproot-ref/5008a5b791ae73ec29ac0e451b2193e921d7d91e new file mode 100644 index 0000000000..7b1ab24d8e --- /dev/null +++ b/txscript/data/taproot-ref/5008a5b791ae73ec29ac0e451b2193e921d7d91e @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0502000000d16cb6e660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127073000000003ed0908104709196000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdfd17120", "prevouts": ["10ea8600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190", "a4a0110000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d24c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820ec8a0a1d660d587d93edd278a1416bd3a7fb5c67f78681973183382c988e9bb422e3784e386a40d51dfdc8b2696050c6780884f0aa6a0f3f5d0b1b514784d82ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}, "failure": {"scriptSig": "", "witness": ["4c52d2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ec61f623cabc1c59ae609038607190a38cf6222717d18f4a17cbb39cf7dbe2c9422e3784e386a40d51dfdc8b2696050c6780884f0aa6a0f3f5d0b1b514784d82ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}}, diff --git a/txscript/data/taproot-ref/50197b1f963b6c70cf02494a68b83252169b58f8 b/txscript/data/taproot-ref/50197b1f963b6c70cf02494a68b83252169b58f8 new file mode 100644 index 0000000000..303a1e2d59 --- /dev/null +++ b/txscript/data/taproot-ref/50197b1f963b6c70cf02494a68b83252169b58f8 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf430100000019be6fb160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704300000000dcce808e041afa810000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8795000000", "prevouts": ["d9ef740000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "78f40e000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a95", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a0f07cd9257033b6e222f9f09c7a2afab52c7da4cd2bd631f821ab1682d301643f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082adc7c8b3bda8f17728820267d55a41d559bf30f92e294931cb4fa644579829c4d4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93690a135c86aa9942f4732601386d1d91f18d87aa0ae76f08bfff5f90e314904dfaab45d9ee0154589058109bae8be3e72a724d93a0656d7cd013110f238c03b0975c046d699a38e7801f010fab6b697cc237a48311758c02bc29e281a6d7a682eab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}}, diff --git a/txscript/data/taproot-ref/501c6aa901d9b79489250b1e7c008dad90b998ba b/txscript/data/taproot-ref/501c6aa901d9b79489250b1e7c008dad90b998ba new file mode 100644 index 0000000000..884e172cf7 --- /dev/null +++ b/txscript/data/taproot-ref/501c6aa901d9b79489250b1e7c008dad90b998ba @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dd00000000e98bdfcfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8a010000001e3b31c4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf10000000006ffb29ef043b09130100000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd0000000", "prevouts": ["f1ac0e000000000017a914ff6a0b1cf86e786bc6de2387f1927f71fd08cd0c87", "cda7830000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c", "20568200000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "f77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa0bef6e20d4c5455f6a7eb766c9d2ecc1d4fc5a0b2a6436d41d520177b8d84d9981b72a8cc1600d8047fe8b56626831fcb5b55f7ee61ebb9b8b91fcb4b55947dd0f5943df1a7722c938328966c7e5ac747f85bf050d43cd9195f6df88860ae066"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e91206a13dce830cde2206e5f739521922f5dc18cf67a0e14634d1bdd9ebb3ed0a4dc25bef94d3da1f821dff96c297a1e496d55e040bded104527be104f359289411b885fbcd56b4d2cd2e695cafde2fa2de7097172cb34b20e1fb870aea9a6a"]}}, diff --git a/txscript/data/taproot-ref/501cdfc8b8bfd47787c30328084cb44010d48a2a b/txscript/data/taproot-ref/501cdfc8b8bfd47787c30328084cb44010d48a2a new file mode 100644 index 0000000000..503ec4421b --- /dev/null +++ b/txscript/data/taproot-ref/501cdfc8b8bfd47787c30328084cb44010d48a2a @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cc00000000b8f83b5e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b000000000ea20edd1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7b010000009599d10e01c5f72d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac71030000", "prevouts": ["f6d641000000000017a9141757f4686f091b43a46fa47e92d07c87fc7a205e87", "5b42100000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "0c43250000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363e76fda838f76382ae0d0bdb253de0cdef8bb5a3eb9bc3b2e59c371abae55d530d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3f2a2968b4ea0558d79f1ec3cd2b8a530982c6b5ad0be17180e93d11bc09903133cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361cc0b7b7d6ad7930d95e3200c68d1443ca9c709d86c4485118a6574c598e644fc145688b3898d8a1374847539a36067c996b07f78d82debe95e7e288000a7bb1b9cd72275efe6b477d9cf0b54cc21959221ed58300fa90def59e56d53bf5ae178c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}}, diff --git a/txscript/data/taproot-ref/5020bfad68bbf3d62a9901f11d582b9367ff01a8 b/txscript/data/taproot-ref/5020bfad68bbf3d62a9901f11d582b9367ff01a8 new file mode 100644 index 0000000000..723b1424de --- /dev/null +++ b/txscript/data/taproot-ref/5020bfad68bbf3d62a9901f11d582b9367ff01a8 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700d020000005955ac21bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1301000000b41584b4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b35000000009f42a30602486899000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c5b9435a", "prevouts": ["ac30110000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "f49e6700000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "7202230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_1d", "final": true, "success": {"scriptSig": "", "witness": ["bb5b83d7d8938ca101024dc3e7460b6b1181f2d63478fab90f85e9763ca6f94243fe0321568a8e77cc7d797b417e5d00c6a6a4da33bb69f7f3b7df3a62424e8a02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3e194e73315fb57b606937e0f2f037069d1004c6b7a4798eda6feb39a435a8c6e650b12b0eca569d65c1f1d0a6aff5a015f67430fbb6be3f7e95ab1ca5ff912d1d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5027b63206364f920f33ae41d244998d60e6d000 b/txscript/data/taproot-ref/5027b63206364f920f33ae41d244998d60e6d000 new file mode 100644 index 0000000000..a6950c87e5 --- /dev/null +++ b/txscript/data/taproot-ref/5027b63206364f920f33ae41d244998d60e6d000 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fd010000003193dfcfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b54010000005b35cfa901599734000000000017a914719f78084af863e000acd618ba76df979722368987f8010000", "prevouts": ["5c99400000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bf2620000000000017a9147e06846ce22cd5e23f7e03391c0538498e0e18ed87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_62", "final": true, "success": {"scriptSig": "", "witness": ["99d2157465caae90d91f9016d5319752015f5e5653b5fff8f3f4fe00ad496903b44e66b985d91d189da0e1d7a5766ce18069f9e1aa97f57ae6d7a0acbeef2c1a03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["325df9e2e4adeda8388b98b8d4aaf9125f309fce49bac19d1a494a9c2e0604c2cf80bbefdcfd15f56e262db17e839ad9a3ac959f8ba9119877c1ece2c5990b8862", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/502ba5490df10d7b64842c917be0cc8dce168153 b/txscript/data/taproot-ref/502ba5490df10d7b64842c917be0cc8dce168153 new file mode 100644 index 0000000000..8fc1f3f436 --- /dev/null +++ b/txscript/data/taproot-ref/502ba5490df10d7b64842c917be0cc8dce168153 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127011010000009512ffec60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dc000000001b1f74a901fa2f0300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac929f8435", "prevouts": ["9a331000000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5", "e0c2100000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "e07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac7aee4b44d5965a2155fdfc505fe91ce63bf32d9f7dea97d151efeddbb77a8d8e461ced71aca9bcca55b69078fb4637b626cf10c8373b915aa1b57bf9dc2b76cfc84644ef9fcb418936abdde9e6d46d404f44a19de7b4f5c4865233c46051e9a410273431f29264d27122ed0946ba884bbeaa1cf1ddeb7776ccdcb7bb2f1db0"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e73d9d375b530aa22fee240902ecc7793689bdebd58e9771ff3d6e92b1aa7f5c13ccd0bea79832f66dcec0cbfd0592e3eb2d999b46ac697170d667eb8939a9687"]}}, diff --git a/txscript/data/taproot-ref/5040561743c74062906a64802db725e7cb87b572 b/txscript/data/taproot-ref/5040561743c74062906a64802db725e7cb87b572 new file mode 100644 index 0000000000..c387e5c53f --- /dev/null +++ b/txscript/data/taproot-ref/5040561743c74062906a64802db725e7cb87b572 @@ -0,0 +1 @@ +{"tx": "3df0c2550260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704d010000006102a8938bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41302000000e3c820940116cc37000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478714020000", "prevouts": ["5eaf0e0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "39193c00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["ef4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fbdd38c28c61f1b7a6e8ceb22fbafcfb9b20df7a8d7411fb9f5b9067992d68d9921261d9825d6464319e11fb6c7a9f7c01f613629293fb1fa80574c155a587736c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}, "failure": {"scriptSig": "", "witness": ["4c52ef", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364d02a6944b3295a9081531191f8339678ef18bd6d1d93e67f7e41417715ae2b61aac465e0caf83cc75bfd3b0ee046dffa2f2de04035b6590b107e2b54cd5d5d2cd241e6bbc5ebedd8f50ae206f1f82a1e41ff5c139455a0ddb0d368f52a47602"]}}, diff --git a/txscript/data/taproot-ref/5047a7a4c5f22dc492d73a6de284a0603fc06171 b/txscript/data/taproot-ref/5047a7a4c5f22dc492d73a6de284a0603fc06171 new file mode 100644 index 0000000000..2ef8897f19 --- /dev/null +++ b/txscript/data/taproot-ref/5047a7a4c5f22dc492d73a6de284a0603fc06171 @@ -0,0 +1 @@ +{"tx": "d505974903dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7d010000009a3a5dc3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b710000000071f6369760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f501000000c7d508ab0473fc5900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487b6000000", "prevouts": ["a02e250000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "b3ca250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d95a110000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "947d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b94af649fd7e9693ff473420f733b57f9fdcc5cab1f492263ad73d963d21a7732e00206903aca02b9ef6b315776a46e2bb12ad4a7f610ddc80848357a2bf29da5432af4ca45b9bbe99b3e8be0ff589ddab81e08d94f2d38bc0283112328f69fdfe847a112bc0d43d64007e06b59459a0c0ad8818c3210afd17f00e931ed6a3b8"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ae0d38dbae0af5265a3cb082a237627ff1f83d25afb725954790e6416ead5eeb9828c38da3f3e346edf59d2f92319d23f93cd7e709e1c3907c38a06ec412d61efe847a112bc0d43d64007e06b59459a0c0ad8818c3210afd17f00e931ed6a3b8"]}}, diff --git a/txscript/data/taproot-ref/50701ea0af2da8b084ea4a3566db2cedf8dcc2b9 b/txscript/data/taproot-ref/50701ea0af2da8b084ea4a3566db2cedf8dcc2b9 new file mode 100644 index 0000000000..7c60673b1f --- /dev/null +++ b/txscript/data/taproot-ref/50701ea0af2da8b084ea4a3566db2cedf8dcc2b9 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0f020000000b347dcbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9800000000d4e7428104d53da800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79686010000", "prevouts": ["17065400000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f", "71505600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93626c391d5e47230d4b4e419da58037ce9505b07d9e5ed3742aee4172be09b65ae536798c57c197a746bb2ed7f28bea5bf32719d74447f5bf93d90a00b781807a2845c4b1f0ef9796b099f7837236ca3239de7da07050a4e4f568f49f6a65718f105f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d1b360dbc2a68556ffe995fa73d9491f5c7d1d4795c1bc7f06a4bb01cde3d3510ec8a0a1d660d587d93edd278a1416bd3a7fb5c67f78681973183382c988e9bb422e3784e386a40d51dfdc8b2696050c6780884f0aa6a0f3f5d0b1b514784d82ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}}, diff --git a/txscript/data/taproot-ref/50765c36b2c5b67d14ed6d3f1006bcac492b9d7e b/txscript/data/taproot-ref/50765c36b2c5b67d14ed6d3f1006bcac492b9d7e new file mode 100644 index 0000000000..9ed3f96c2b --- /dev/null +++ b/txscript/data/taproot-ref/50765c36b2c5b67d14ed6d3f1006bcac492b9d7e @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48a01000000668a29f1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3d00000000680a248b0199335c00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acd1918f56", "prevouts": ["64343f0000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "251a20000000000017a91454957ff2b5c5fa7ace3c6fb485b914ecf6ce0c8c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "0c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c2538f548eb9d319d165a467796d1e60ec6673916444f0d66e1a9edbb7d8ec4eda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e5111e542fd849c49f4d44aada2d8e1aab946c793c1d334242f5a6d1a51a6de2d5b0de380cf0ebf0fa9d17e1d1edb87a374b64935c1c67f0c5024fcc072643681"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f347fc09b13f9ab949e4d0dd849e76d18bd9ee465aaa47c5e053192723bafcd48d88e70532c494439586c1157b8a644f11fc532506ec8f5af612c230a11997e628257bae22e6d8aedb31b43cfe467850e731fb88c1221782039a4c16ef44c35617d0d4fc7404dd8984f6a1705481d95654b515a34c586c99c11bfe20e9503459"]}}, diff --git a/txscript/data/taproot-ref/50ade4cb2bfd78d63959c0c196702463020ec1a7 b/txscript/data/taproot-ref/50ade4cb2bfd78d63959c0c196702463020ec1a7 new file mode 100644 index 0000000000..af8042efb6 --- /dev/null +++ b/txscript/data/taproot-ref/50ade4cb2bfd78d63959c0c196702463020ec1a7 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdb00000000b104fec5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b15000000008f74357a0431b5990000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987d7010000", "prevouts": ["94b37700000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "04d82400000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "b17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa6d4441481b861885f5ed94900bbd5862c55ac99196b75719f05c0af3923d20525bc912f5bf4aa2c9ddbc9747d59c78f40d0a0aa0a8a4f22dc70e3f9cdb9b6ae3"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d5f4fd4f38de76daa30397659fc5eb995186dee5e848d8b406f0f064ef43f0c2e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8d9568d9f877f6ca0cee9df3d4970d26d0e286b65747316dde3c995de6e71d9f55bc912f5bf4aa2c9ddbc9747d59c78f40d0a0aa0a8a4f22dc70e3f9cdb9b6ae3"]}}, diff --git a/txscript/data/taproot-ref/50e97f4dc4e78ccd7491b23a05fec77e705d6d17 b/txscript/data/taproot-ref/50e97f4dc4e78ccd7491b23a05fec77e705d6d17 new file mode 100644 index 0000000000..0075b80b95 --- /dev/null +++ b/txscript/data/taproot-ref/50e97f4dc4e78ccd7491b23a05fec77e705d6d17 @@ -0,0 +1 @@ +{"tx": "143da98402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b440000000025c5a983dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1f0000000038ac8a9d039d224200000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e764451426", "prevouts": ["d3781e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "694a250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e", "final": true, "success": {"scriptSig": "", "witness": ["d9124b8647f3acb4689e4700a9599fc0bc513599668e1920e4bedc7a4ff8f237ae15e32d93778e93fd3702c8a475b974d8f95a6315ce7ebf3560de909a35e99082", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8bd90ef2e9c46dc6d962f61e4765ad430e6f14b7b174c413922efcb80f5e8681c3c222ce2224b789f04f2877a611ed2346d135007c05c7dd22fd824b1b114a770e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/512819dc5f866c4c52a96393d1dc161a298b58cf b/txscript/data/taproot-ref/512819dc5f866c4c52a96393d1dc161a298b58cf new file mode 100644 index 0000000000..b44cbca146 --- /dev/null +++ b/txscript/data/taproot-ref/512819dc5f866c4c52a96393d1dc161a298b58cf @@ -0,0 +1 @@ +{"tx": "d7f96b1903dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca701000000c90fb0fadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0602000000fe78deebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b92000000002e15949302b1769a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1a020000", "prevouts": ["3eea5800000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "d5e41f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "688424000000000017a91495eb8fe3d959e08a2cc279c1b4ede1921d14a93b87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_2c", "final": true, "success": {"scriptSig": "", "witness": ["cbdcc544b9cf6555405ea1e773a70c6cf70cc997c3adb4cad23abe14380c7065cfe563076597f09919dccc545a384d03421a884e097eddf324fa435083df25f782"]}, "failure": {"scriptSig": "", "witness": ["c95a185454bf06e40c9ca70a66723bf19eac83a2702717f5e64ff49f8c6c02914718103f316dc3dd282963d07b03b238afa922488820fd0e9b43336597df8d632c"]}}, diff --git a/txscript/data/taproot-ref/5134a98d252e038c84c184e2a60b3ab15541c32f b/txscript/data/taproot-ref/5134a98d252e038c84c184e2a60b3ab15541c32f new file mode 100644 index 0000000000..7afd4a0ac6 --- /dev/null +++ b/txscript/data/taproot-ref/5134a98d252e038c84c184e2a60b3ab15541c32f @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3f01000000b8a74f8a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44f00000000e90788d160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702a01000000ca5a428f0116f30700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ace4010000", "prevouts": ["45214700000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "d6963e0000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5", "aee20e0000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09026c8996ae41319caadcbf48a28b57f224cbd38d446d2467b4a10a4b0772f7b34cb5e4f581c04147436f22e81793836a4632580b362f43b531602850ea052da4516bbc5b4f689c052ca256fa308c869af00a681823df8b45438e870cc66642b39cf8963eb626019fb6362815b92a6c335fb3af15c99c909ba32496f22bdacd2af9983f09cdaa709d996c9aab70503a7ac17a428f90418959f654ccaa293e6e0d70bc6b79219070e0d959c0bf219fb2fc5685336f84b9c76e05066c772c5dfeabf42601130fe4ef32979200eb886b2912e323b8f9229a755156af3fe5f200f4c3dd56a26be458f4b0c313577ce4cf3569efe2062ea1c631913605e3eb3f6d1828b31cf3f01252528f464d272cee8be990696d0c267b10a584d422c42e6f230f9eb455a52ee05482dcde698772592f09dd7c2dcda5f143e36f0d0687a76248919418e65e9962ab66b988ba9364c5c0891a9ba251e4779d6d05314430a01e053b39d3098861dad21e45895e10d219e9ab0501f2e5e4dd26b2b80386031ee82d7b363788074d2c1e9ebaea1fdbcfa1eb6be6abccdca9a147b7e3848ddc4a257d74d354e8aa3360d31bad3513a9d7c2a6000227a2a51d6cf80ab5bca05425230f58c62a330f855f9e560cbd47112959af75204f852b5f2cd5053d18fcd9b96fad35e4dfdf90a9c5bdeb385f9693da7cefe5d96af6993fd23124b9992091710223e05fd52182a6b27a87c8c5b775", "7c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936440c08ad087e39b430304a4ad762f31ceefbef677acccb5a06e2c9abe9dfa4ef3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08208eae3f5bf5f4c26def68bde658fd1412dc2dfb494d39d6b1bd4ba6a274f177d9a711983bc616996e2ac47b27808b31a9b7e87f7ce1f3571999dd3a2a57f1080"]}, "failure": {"scriptSig": "", "witness": ["4d090215af9e4ab190a1dd0b82fd3a290972aa8d406638237717238d40dd22a33723616a87d580c4a856b5f3d2f2657cc1eeadf3e132f5a8733eb7e12b634d0be39b8cbee99af01aed909876a8defa580bdcab1525d41566c292ac583a885b3a10562aaf61abd5fd99e39e5e1509abef35bf9ab0ff05bdbb0120192245721deca95d3af3c7b1bd628c76e4235016af31c82d99ddf82a8f7bde46e5e8689741ff9a80fe085a56f7b5f7817de216133608ded926c44d8465c3d620b8a00d7a18d5da15e03e5b1760860b879ff57e2103f2a110a854150e6a4e454bc1c59453f02d8c5e8253a51ad005c9e73b26d21cd9d38253ddb6beae80317906cafda541cc9336b5d703c2e9d09fe7aa61dec161d987d181ed76742c396ec4e659c308e4abebddd471a16457f86eeb5e073da108b7e8b5f01be0327dd4597ef190daa232f5121b522cf7de7f4f6a34c32d99dcd829592d300fd2084025ae410cd05e54a446e42518954eb86a7c93ec9da7c67300ff14618b26bfae89383cc73694075c2ad53722193f6af5d59bbc294c1e5fd7f7e08edeae6dda6ad158f434377609b51bfb40d38af4b4e8f2dfe951fb625cf6c9211f1d24d83bc023b7bd7d79093c0828da1ab323da5bba9d86810e8bb155c66029796b904697ab5cf8eb471feaa183ce54dee4cb50cdb0e528c096ac37a3f644e5a9f91ade7ed4074c7f91972028f2116f4e9149f34a5a4cee2ed4508db875", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8742f7aec0ae53a52a244a2c0c214837ef2ff67b990e770e70b44d703b0bde01fd5e8f79d631fbf207b458b911c1cf4efab0aea5316113aa9c93bea92caa9fc9"]}}, diff --git a/txscript/data/taproot-ref/513b5b1cd7ae4a18b0684e98b8bea2445f0f267c b/txscript/data/taproot-ref/513b5b1cd7ae4a18b0684e98b8bea2445f0f267c new file mode 100644 index 0000000000..c2a74190ab --- /dev/null +++ b/txscript/data/taproot-ref/513b5b1cd7ae4a18b0684e98b8bea2445f0f267c @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2501000000fa3516db03e85f7400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a662e5a438", "prevouts": ["8685760000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["994c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367643e13e483d98b5cb4a2dd9b2a8baf365ffe94859ab503c911dc21978e6d7804c8fbf2363a77354fc9c61d01c3ea3e8806c47304e5a0571bc5a832b63c4c4c93c50effc4608d2c714b1f589c510b82e2cb4bd2fb333954004903b4f08f38a79"]}, "failure": {"scriptSig": "", "witness": ["4c5299", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef799b79a3787fcc1cc2e029bc49329c320df8be6585c07b1b866b22fbf64c2a637edb6ad97271a1ba84afbf70caa284b53510d77fb53cff70120791d9457d51af95302e7a08635545e6c64d05a20a7ff60718981ac8a997d809f6391d7b2d9241e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}}, diff --git a/txscript/data/taproot-ref/5145a2f823d50829addf9a923816226e49b73772 b/txscript/data/taproot-ref/5145a2f823d50829addf9a923816226e49b73772 new file mode 100644 index 0000000000..42253b3061 --- /dev/null +++ b/txscript/data/taproot-ref/5145a2f823d50829addf9a923816226e49b73772 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c580000000089646dbadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc10000000056ed9eb1035d779e000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc30010000", "prevouts": ["bfdd4a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a25e550000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c", "final": true, "success": {"scriptSig": "", "witness": ["829634fbe591f16cc6652c86a67cba77a6b184985d1af18139166edc4fe590f08ce8ca6b7a8e41c9c90cd53b49e3f4221044575e26fd3499e0041cf69294cc1281"]}, "failure": {"scriptSig": "", "witness": ["a6e2cdb8dbcb055cb8bff5523e2705900c6693f892078f35d623f2a922127af8a66e1a509f22b0d361382ddf77ba710aacf970ff0370f20686f2079438612c150c"]}}, diff --git a/txscript/data/taproot-ref/51585e660838f7655a9d3f8e62673ed896abc1b1 b/txscript/data/taproot-ref/51585e660838f7655a9d3f8e62673ed896abc1b1 new file mode 100644 index 0000000000..3d245907f0 --- /dev/null +++ b/txscript/data/taproot-ref/51585e660838f7655a9d3f8e62673ed896abc1b1 @@ -0,0 +1 @@ +{"tx": "19d3c01403bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb400000000d4d080ff60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700b01000000657831fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49400000000aa2e2a9604f321bf00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f871a000000", "prevouts": ["0c0877000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "894f0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "be6b3c0000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_39", "final": true, "success": {"scriptSig": "", "witness": ["ce90b7e1e1b3078f39a5ee0bf2f6f28ef7457299f4626e2a7bc3c62da383f0a494e07a07419603a3f64d2356bfe887519595ad6c6a5e755b648e07ddc82bbfea02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["00f14fca2bd71090c6f6e22b63b497a7f033b83ada84d3cd30bbca9a6897cbb84013d7d24b2b57e6bc9bc842fa74d0c110081ef00b2c69b7d93b5b0b5d3f232d39", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5159ef1765261a6a8967fe22b91be23bc4f7c672 b/txscript/data/taproot-ref/5159ef1765261a6a8967fe22b91be23bc4f7c672 new file mode 100644 index 0000000000..1e236dcb3b --- /dev/null +++ b/txscript/data/taproot-ref/5159ef1765261a6a8967fe22b91be23bc4f7c672 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c98010000002f66bab2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9901000000f66711d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf84000000001a4b64da03373c3901000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac8e020000", "prevouts": ["d1295e000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "7c9879000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "e9a063000000000021541f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00639868", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6acbc7404f4a64833bba86ae12a250fbd4270c03a4df3211800a65b426343c7b806b7a00459a4c1bc30a7ac808d25283aa8d21c996014515e9974f153b7e8517bb22a9d6ce3a4416076bcdc0e15ff24e2eba93ece471e96a0af39f5a01dd3ec6e2c0067d6235544c969c57bb6383bc4dfe8083fe3443e336f29d85bd1c9f087"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41f4c7988b5621a2b4ceb0e4a0295b5522bdaf57a14af19f5e9873d8ccb0a4f054b5563559956b4521d685614895115ff3b761ab3fb4dd1d8def3bf310bb092b594c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}}, diff --git a/txscript/data/taproot-ref/516e8f247c632cc97a34b088b9b9c5522f6b4b7b b/txscript/data/taproot-ref/516e8f247c632cc97a34b088b9b9c5522f6b4b7b new file mode 100644 index 0000000000..ed4fb6213e --- /dev/null +++ b/txscript/data/taproot-ref/516e8f247c632cc97a34b088b9b9c5522f6b4b7b @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8a0000000030d2549004c35d4e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875add8536", "prevouts": ["5912510000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f74c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e6bf3ef0c52029538d60b405bd64e2cc9734303fd934f9ee1f37723dcf17f67fbe0beccf8b53a38f7a20d51eb008bdc60f78fac094fdd23935202ece673d8622376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900455438ad321f710317d8f3678f772f8337c845de7a4601c479cd7219e318503b74fdf1522df456d7fbfe0d29a7744cbe637017dd01cd6de5bb6b2c07ed06f430b01c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}}, diff --git a/txscript/data/taproot-ref/51902d7c0dc3e60282faf7c3bed70ad3588b79cc b/txscript/data/taproot-ref/51902d7c0dc3e60282faf7c3bed70ad3588b79cc new file mode 100644 index 0000000000..b4e821a92d --- /dev/null +++ b/txscript/data/taproot-ref/51902d7c0dc3e60282faf7c3bed70ad3588b79cc @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cce00000000e19e8a348bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ef0100000011e89353dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c02000000b3dc5d44043c69d900000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac92010000", "prevouts": ["d9e6520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8f6b320000000000225120d70bb5030b4517d64d2a3c38713515b320a06334d0ff9db76c903984d8e384a2", "bcc555000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cc9987f9f1a0b217068c5915d51afe3a2b0e8487705cf8822368d5c636743cdbfb640520cc13bd7f4751eea589bfdaf463667e9e3eebb3331ccb48f0e9ad4c4d3f52a2844c5f7874c7d430ecd2ddfcfe713e30c56da5784f950db6acb8f092a"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1360c8600b70daaa5cf8f525cd2d4abcf69506a056a119fd926e23bd8684708da0a67b80b81ed02a57999348bdd390384d424a2522cd0278ffab5313e035bd402791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}}, diff --git a/txscript/data/taproot-ref/51cb6bd8e208996ef5816ab2e4a5f0a4392acd9f b/txscript/data/taproot-ref/51cb6bd8e208996ef5816ab2e4a5f0a4392acd9f new file mode 100644 index 0000000000..5428630041 --- /dev/null +++ b/txscript/data/taproot-ref/51cb6bd8e208996ef5816ab2e4a5f0a4392acd9f @@ -0,0 +1 @@ +{"tx": "a54aff3a03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf37010000008bb7459d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702700000000a6f955b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b590000000057ec95af02d213ac00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689873f816d5e", "prevouts": ["87ab7b0000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50", "d308130000000000225120efe1fa8c8643b06748235620ecfbc876727366244fc928e9c2000087b14324f1", "17ff1e00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368191df1e8a6412a9133547ec8d3321f9af52362f72a65d356b4413964c57ce831e80b1f8b709fd7e9f8915460d72d278aa0d12452680dedc295e1cc62d069d9c5f8b38696f7f521c781f821b55aa4ff86c04fbebd102ad129a9d47907becd36b4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5183e343f15a28f9ad1157957559cb0b6b8ddccd5d64405c8ba15aa31cdad4142c00ae7d77688765097c61dd6dc7203a99b1de19633b0fe895af4a245d0fe1ab9735478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}}, diff --git a/txscript/data/taproot-ref/51d22c9e318035b292b06c7e92cff7a7dcd2ef46 b/txscript/data/taproot-ref/51d22c9e318035b292b06c7e92cff7a7dcd2ef46 new file mode 100644 index 0000000000..ba600f1a7f --- /dev/null +++ b/txscript/data/taproot-ref/51d22c9e318035b292b06c7e92cff7a7dcd2ef46 @@ -0,0 +1 @@ +{"tx": "faa2764402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c11020000009f2c27d5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b77000000005ce06ec703e2aa73000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6fb35962b", "prevouts": ["7b284e0000000000225120e0ca4cb327604d8bb54d855256413a632bce5e2185126ca2f73680d7829d5a91", "ad77280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_1e", "final": true, "success": {"scriptSig": "", "witness": ["97f4f2cfd939ddd0434001233b05794237a4d684cdb12fb123f26584e9bed16d1659f6fa989a7665f51ec2dcea27584c6e7f3f67c3d02d5db126b8be3a69a4a703"]}, "failure": {"scriptSig": "", "witness": ["e3e0778281cb047d0c31055580c8b439d833aef9225ffc93a89ae1e045ae7fdd93c88b9ea86cfc0fa20f20d804ed853db1bc2a8c6e93371f82db4262f6d895531e"]}}, diff --git a/txscript/data/taproot-ref/51df77e1f5047cc73d62f6a82b06c76b2f2dfcf2 b/txscript/data/taproot-ref/51df77e1f5047cc73d62f6a82b06c76b2f2dfcf2 new file mode 100644 index 0000000000..c447a5881e --- /dev/null +++ b/txscript/data/taproot-ref/51df77e1f5047cc73d62f6a82b06c76b2f2dfcf2 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c78000000003e1cfcb0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c87000000004eb3e1eebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf930000000022a849d80147e877000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487a8000000", "prevouts": ["f2d35400000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "17484f00000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4", "72f17a0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "087d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa55b45b3af2af0c7a238665fed9a70950b75abf30a3f75b50a7b1cc61308c32d3371e41a07562523a12648be26bdba66be78ce7e249298c356e66cf29847872e0"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08281f944ef569cf36d808a56aaa75ca2fdbdf4182c26b1d87989a6b5ad676759bc691c2a9908d9e7287fb91837cd9c32b2a21ac331bb306f4648aa27bb40422e45371e41a07562523a12648be26bdba66be78ce7e249298c356e66cf29847872e0"]}}, diff --git a/txscript/data/taproot-ref/51f4a12afbc5c09d84488a09c1ec4fad2f8ad55b b/txscript/data/taproot-ref/51f4a12afbc5c09d84488a09c1ec4fad2f8ad55b new file mode 100644 index 0000000000..2ee0582420 --- /dev/null +++ b/txscript/data/taproot-ref/51f4a12afbc5c09d84488a09c1ec4fad2f8ad55b @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9400000000c44b13eadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0401000000a6db52abdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c54010000002c43129203bb4104010000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6b86cdd5a", "prevouts": ["b93560000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0", "27ca5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "17f34800000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_csv", "final": true, "success": {"scriptSig": "", "witness": ["39d172cedc87521fd3bd91d949348abc24a61074248eae2c541efab24fe7ab4ba11e64d0aba143b7b86543d0ef485368b7b3a002a8bd5f98bfb00c4620bf61f7", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313ddd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["39d172cedc87521fd3bd91d949348abc24a61074248eae2c541efab24fe7ab4ba11e64d0aba143b7b86543d0ef485368b7b3a002a8bd5f98bfb00c4620bf61", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313ddd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/5201220ebf5a752ed230ba1c4660d6768ea0ab37 b/txscript/data/taproot-ref/5201220ebf5a752ed230ba1c4660d6768ea0ab37 new file mode 100644 index 0000000000..8f2917f7ef --- /dev/null +++ b/txscript/data/taproot-ref/5201220ebf5a752ed230ba1c4660d6768ea0ab37 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1f00000000624a02eb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127095010000009ed305a30279d36200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac70030000", "prevouts": ["fa02520000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "73761200000000002251202ea95065368f678e25a669a7906e1051ddb7c321fda55e7bd6b39829f3117b75"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93605468d6fa5e4634f58d2d208976b5aab4a73e083c36d6c2e411848e44297e02d"]}, "failure": {"scriptSig": "", "witness": ["6a3a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/52406f743dd8cf468c8739e0e49a5e8c2abe890d b/txscript/data/taproot-ref/52406f743dd8cf468c8739e0e49a5e8c2abe890d new file mode 100644 index 0000000000..dd10e3ac3c --- /dev/null +++ b/txscript/data/taproot-ref/52406f743dd8cf468c8739e0e49a5e8c2abe890d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6900000000070fc07ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf680000000062cb832204efafcf000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2c000000", "prevouts": ["0697650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "24df6b000000000017a9149d4bcb1ed806c9beed692a78614f8b90a68c708187"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21571f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["522e46c0721863b9e3cb7bde3b95912a12c893d3166766d12d02c50c88cf2c328c62350de66dd9e6ea9d65b61b1b69b771583fb4afa450d9a9c5b28b82bd164a", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/524a8fbae511284a4b3feffd7e69391eebfe5fe3 b/txscript/data/taproot-ref/524a8fbae511284a4b3feffd7e69391eebfe5fe3 new file mode 100644 index 0000000000..4b495282c5 --- /dev/null +++ b/txscript/data/taproot-ref/524a8fbae511284a4b3feffd7e69391eebfe5fe3 @@ -0,0 +1 @@ +{"tx": "2922ebe703dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb9010000005c19b4fedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b13020000001998e48adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b010100000093d904b504fad96600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac67c6fe2b", "prevouts": ["deda1f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5841230000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "70472500000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6aee", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f6f920dc9dcb98ba04cff112f583969b4fa240bedf781759d6b6e0f2e74eb7fa05e01deb44bf60eeaa09a037ba0d53221083944f657819e2d2b55bb732cda3dfdd207214d6df2d18dfa237afd6016520e9e6ed6636ebebd182087bb183877c35439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d8657209b8dfaa69151d05ccddc10c8c1e468eb7b78f9ad17f99ee1b916fd61bdfbcfce40899fd8696dac9e3afc960f0a100b615a3c324ed3a125e98af98336f748ba56"]}}, diff --git a/txscript/data/taproot-ref/525afb4266fbfcb9a9457044ffa429e6345aca74 b/txscript/data/taproot-ref/525afb4266fbfcb9a9457044ffa429e6345aca74 new file mode 100644 index 0000000000..bd2e90190c --- /dev/null +++ b/txscript/data/taproot-ref/525afb4266fbfcb9a9457044ffa429e6345aca74 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4a0100000084436a61bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc500000000b28535d6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd2010000007e9916a503f4c94f01000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e77c000000", "prevouts": ["f56e7400000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "259f7f0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "acbf5e0000000000215c1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["8a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4572db529171a47fc33c2e4ee960be7fb9400c27bdb6fae7dcdae272f7c7daab09b045cee6f1e54629d213b8dbfcd9de8aba2dd7f34fe21c75d81b8576e463c6b"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045141ceaec0b62943b85ddb54ef2037615ee2bfdc3c88602ea27aeaa6ef1c2e0ef6e427c91532996b84ed2c37f8a26be8637de11530a49bfc255181ba6103e3464915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}}, diff --git a/txscript/data/taproot-ref/526b41de4d7b2b6cca5b8cca2aff4e05e1edd180 b/txscript/data/taproot-ref/526b41de4d7b2b6cca5b8cca2aff4e05e1edd180 new file mode 100644 index 0000000000..f26bd58a60 --- /dev/null +++ b/txscript/data/taproot-ref/526b41de4d7b2b6cca5b8cca2aff4e05e1edd180 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cb00000000e2137298bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4b010000003490f9c1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5901000000e9b952fd0237c4c2000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898757020000", "prevouts": ["30081100000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335", "bc186b00000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "22bd48000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "e27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b1d764645ac829a889ede7ad8db127382a24af0c39e10b540dba9512d84645b5eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7acec7827d9bc9e4e8e39cc141cf7690ea6843d6b50eda1fc8d5571fb149b2aabab"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367c93f7c29ee74358d9798874b9f1b1bb2a78bb36471717798dde9f0a020d10aae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8512c582a906b097cf6fdaec64d2651566eff10d9e5eded90f3aff95e690654e4212021a26ea5e00fb993aa3d0fc1bd1e431f365db69035b8e4625845fc9b697c"]}}, diff --git a/txscript/data/taproot-ref/528808e08755d1c4badf200ea1e46b471e697367 b/txscript/data/taproot-ref/528808e08755d1c4badf200ea1e46b471e697367 new file mode 100644 index 0000000000..f524f43a63 --- /dev/null +++ b/txscript/data/taproot-ref/528808e08755d1c4badf200ea1e46b471e697367 @@ -0,0 +1 @@ +{"tx": "ec6f545702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9e00000000a8a25b8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705000000000f22c0df9034f438b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d3020000", "prevouts": ["85f87b0000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "97f8100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_56", "final": true, "success": {"scriptSig": "", "witness": ["4df118ebbf8fce9da1d6256db5a49c86b2be621827c36591ba5dbb47b8b72795d0d5ce31638322488a9e35909f70df7b8caba4d07418e26742c5863e90ac10d601"]}, "failure": {"scriptSig": "", "witness": ["943060a8657df6697aa72fd099b4c197987b2896f09ff25bac8696a619a8ac4034766042a89d3e7aac55734e897069c03558557deaa09c5fc15a85ed42d6f02556"]}}, diff --git a/txscript/data/taproot-ref/5292dd4bbfc4ed134ecca359a50042487bdab8de b/txscript/data/taproot-ref/5292dd4bbfc4ed134ecca359a50042487bdab8de new file mode 100644 index 0000000000..2449e979bb --- /dev/null +++ b/txscript/data/taproot-ref/5292dd4bbfc4ed134ecca359a50042487bdab8de @@ -0,0 +1 @@ +{"tx": "d97d1cfb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46601000000d2c0dabe60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703900000000021a8ba701f3112f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964a030000", "prevouts": ["4aa7410000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "15ab0f000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "99", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364d586cb5de2dd3058dd7e227544d59b90431907c0aee9f3c45dbe5cd5ada47d3637edb6ad97271a1ba84afbf70caa284b53510d77fb53cff70120791d9457d51af95302e7a08635545e6c64d05a20a7ff60718981ac8a997d809f6391d7b2d9241e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4db2b7303d128165c3aee76333e625284db46e202d1b30be35d2598f7d6b886c0b317c85b837bc971133c463a5a02b3e438f62c623f33a660d87550a4209620af95302e7a08635545e6c64d05a20a7ff60718981ac8a997d809f6391d7b2d9241e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}}, diff --git a/txscript/data/taproot-ref/529e15d7495022b3928ad252f217ff7066f4a8c4 b/txscript/data/taproot-ref/529e15d7495022b3928ad252f217ff7066f4a8c4 new file mode 100644 index 0000000000..0cb8d34b7b --- /dev/null +++ b/txscript/data/taproot-ref/529e15d7495022b3928ad252f217ff7066f4a8c4 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c409000000009364ac4260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ac01000000ed34be6e039fbf50000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709310e52", "prevouts": ["e41f420000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f4301000000000002251205fbb8ac28e580fb39d87ab9ecacdc52316773607abc8ac10a5707b0a5a311000"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["5a0ba866675f7dcdd69fa812d8bc0b7100417c09ed26f11d1fb1ccfed13bb8753885813c383a73f49a51bcc12c9a797e6834d60a411e3a3610bc9402a8c57bb401", "3fa4524396f75e78ea91e3f7665db7f8cf5e898b2c61d61c31c5785ccce34b72d1b26bee966617925934b5d796b60c04fdc6c69f7f1b4cb888ff0a89c3b3371f2ebd1303f3f2bd8a9f20fc3d45bc87817b1212b702c8f759e11e1ae29c98f921debd49d34f6fb4c98830602b73d94de9275c5973b3c64af620cc48aaa400ab8bf5f11e7aa5c75f9f4c9975", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ffe2f9e7651e9c582230805dea6ab3f770391f72340882880a9a66d58587497760d14537d26c6420044fa8ebd38475257ff2b21d84f4b8d09ede551234536ca57d36b4a575814cf54685ac704a7dcbc10721e1ec740698e9dcfb57c35e77ff55a5c396eed87ff772ce52825cdc495e9c04fb7ca8a067211a005b28f4578544029f842240c645949adcd0f10466b378902fb744c393ba4780cc2212b976ce07bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73c091b0614ef7942ac3712e9340eee8de2b5d5360d8f858faae197db1531a93d6188a98edee7ef4d72517cf453882e06807799415dfcb5fc26feb6712d5c215a9b05904167f78bd9da3adac10f2f4122c09e9f54abea648caad3c3b7e1f8aa100000000000000000000000000000000000000000000000000000000000000000d342f30abe252a2fc4ad53d00a9b547116ed2eac0fecb6536d542fb489aeb9a54016aeba8dd7ac26ace25c63f13a80d6dec050bffdddb0ac77cece5e83ecd21"]}, "failure": {"scriptSig": "", "witness": ["5a0ba866675f7dcdd69fa812d8bc0b7100417c09ed26f11d1fb1ccfed13bb8753885813c383a73f49a51bcc12c9a797e6834d60a411e3a3610bc9402a8c57bb401", "f0957755a9ca78dacae97c846fb0e3cf28c9561039ebc678c0c906641e97e75658c56d147d7ba53e6b7836bd7a3ce46a440103d137bbd3cd04574d165af7bd6d0ee056a29418370dab98207c63413ab8ef2e8c3afb82fb86dcf40bc3d65927b34aed6b5f5e5c18e715f2bb01de0606a5f6aa23b5bdadb6093a54952f989b844035f3d480247fd9413a39", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ffe2f9e7651e9c582230805dea6ab3f770391f72340882880a9a66d58587497760d14537d26c6420044fa8ebd38475257ff2b21d84f4b8d09ede551234536ca57d36b4a575814cf54685ac704a7dcbc10721e1ec740698e9dcfb57c35e77ff55a5c396eed87ff772ce52825cdc495e9c04fb7ca8a067211a005b28f4578544029f842240c645949adcd0f10466b378902fb744c393ba4780cc2212b976ce07bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73c091b0614ef7942ac3712e9340eee8de2b5d5360d8f858faae197db1531a93d6188a98edee7ef4d72517cf453882e06807799415dfcb5fc26feb6712d5c215a9b05904167f78bd9da3adac10f2f4122c09e9f54abea648caad3c3b7e1f8aa100000000000000000000000000000000000000000000000000000000000000000d342f30abe252a2fc4ad53d00a9b547116ed2eac0fecb6536d542fb489aeb9a54016aeba8dd7ac26ace25c63f13a80d6dec050bffdddb0ac77cece5e83ecd21"]}}, diff --git a/txscript/data/taproot-ref/529e417f9521111e7e2b214bbe3a009fb241e0e3 b/txscript/data/taproot-ref/529e417f9521111e7e2b214bbe3a009fb241e0e3 new file mode 100644 index 0000000000..a5f84064e5 --- /dev/null +++ b/txscript/data/taproot-ref/529e417f9521111e7e2b214bbe3a009fb241e0e3 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4b00000000f912b3eedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5001000000e0efbb9d02305ac300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e775040000", "prevouts": ["b6b17500000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "bb5450000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f64c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e88526c13eb9f3ceda07aab2d6470ded7d71666b865703d69a451a4808570d93ab836f202d3609bf617cb7b4b7700532182ae3d2e1a09e3b3f38346196fd93b669cfd1883d9d94906422bb83623918edcd109683f826bcbf676882b31fdcf44192fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}, "failure": {"scriptSig": "", "witness": ["4c52f6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936061ea1cc303ae48ba58384e29824bd453e270f0d0a8b7b8fddbb1c01a6802b543f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bc80a3081e946651089c17942e2d2b7e0a2ba8b51162f8e9c4f29cb18d1603310a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}}, diff --git a/txscript/data/taproot-ref/52a46ce5d115709464d927bd868cb66e64d5d890 b/txscript/data/taproot-ref/52a46ce5d115709464d927bd868cb66e64d5d890 new file mode 100644 index 0000000000..07d5ec4882 --- /dev/null +++ b/txscript/data/taproot-ref/52a46ce5d115709464d927bd868cb66e64d5d890 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cb01000000cd9868e9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2b00000000cd3ed02203b4d76700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc734010000", "prevouts": ["3a08110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ba875900000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_9a", "final": true, "success": {"scriptSig": "", "witness": ["bd641174c8c9d5a320e5848603ee4e052442f7f72c6f46d5ed22e6d04533eaf85a42c05a9c170a3878c85512200e1192bf09ffcf7342394b41a1531d5a22520682"]}, "failure": {"scriptSig": "", "witness": ["a34328a2f6bae8f0c91edda5b2a87d6da408b1ab8ad1df672aee3e117bb732e8f30fb29a0509c41ca5b824d31b06f63143b7edf0be8f5317169ca7602f9e795e9a"]}}, diff --git a/txscript/data/taproot-ref/52b71f15e64724663db04868b953a0dd6f8ab01a b/txscript/data/taproot-ref/52b71f15e64724663db04868b953a0dd6f8ab01a new file mode 100644 index 0000000000..3269065b13 --- /dev/null +++ b/txscript/data/taproot-ref/52b71f15e64724663db04868b953a0dd6f8ab01a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce90000000060bcc3aadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8b01000000049096870147a1430000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d32e1233", "prevouts": ["141a590000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "33cf5e0000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "62", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8b553b0a6fa8101b21fae89df5dd09b18d30a3ef06025a3f9cb6b07028f8b60ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2a28c39ce330a19a0d6c22ddc640bc3609271e6194de475fecd1ad84a88d361935a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93608efc3524da3cce9064a39cd829c421044a59a48c5000df9ec45b645663b2d3865d6469ded31e8361d538153e3993104db0c9d480dfc3dcfe9dd6d2fbda5f8f6abc42ab3738335b78a2a7135de763706b017ef32cb75bc24ca1210f74f6e5b7b3fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}}, diff --git a/txscript/data/taproot-ref/52c7e56d194272214280372b7dbacf979b86a714 b/txscript/data/taproot-ref/52c7e56d194272214280372b7dbacf979b86a714 new file mode 100644 index 0000000000..971719a72d --- /dev/null +++ b/txscript/data/taproot-ref/52c7e56d194272214280372b7dbacf979b86a714 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8b000000008783f9a3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf850000000061d3980c048f94c6000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7f11eac39", "prevouts": ["ed4553000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "e55075000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["eb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936548e02ba2703ccddc552600e93f0a288f5116c529acb2e0434ef3486de3078ba3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821e09e6d24dde1e7a9afb38743b4c2dd55dbb58a3a1803a82bc7b3a42584fec8fa9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b965c838716597843dddd943276d0695a7197e96f70841ed980463eb99376fe31e09e6d24dde1e7a9afb38743b4c2dd55dbb58a3a1803a82bc7b3a42584fec8fa9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}}, diff --git a/txscript/data/taproot-ref/52da571031bbcc150454dd6be63a21c6a2dca5e5 b/txscript/data/taproot-ref/52da571031bbcc150454dd6be63a21c6a2dca5e5 new file mode 100644 index 0000000000..e277a30d5f --- /dev/null +++ b/txscript/data/taproot-ref/52da571031bbcc150454dd6be63a21c6a2dca5e5 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0e02000000dfbf3a19bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa10100000034a2a0af02fe7ad10000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487dac0f83c", "prevouts": ["fef26900000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "568269000000000022512030fd389dfc6b7dc5f4caf58ddf04b54dbb338c7b69e334c29cccf1a655d02655"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "8a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4572db529171a47fc33c2e4ee960be7fb9400c27bdb6fae7dcdae272f7c7daab09b045cee6f1e54629d213b8dbfcd9de8aba2dd7f34fe21c75d81b8576e463c6b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045141ceaec0b62943b85ddb54ef2037615ee2bfdc3c88602ea27aeaa6ef1c2e0ef6e427c91532996b84ed2c37f8a26be8637de11530a49bfc255181ba6103e3464915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}}, diff --git a/txscript/data/taproot-ref/53045f62216e6dd1d7b2d1c05dbda813f59f4d38 b/txscript/data/taproot-ref/53045f62216e6dd1d7b2d1c05dbda813f59f4d38 new file mode 100644 index 0000000000..129001df8f --- /dev/null +++ b/txscript/data/taproot-ref/53045f62216e6dd1d7b2d1c05dbda813f59f4d38 @@ -0,0 +1 @@ +{"tx": "cc2a29fc03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8901000000c830c9abbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff100000000746406a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9601000000bd8ec8fe0286b12d0100000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cc349424", "prevouts": ["6a2b66000000000017a91408247b8d3db4e641d0be1ff23f14280256870a5187", "2f55760000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0074530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_9", "final": true, "success": {"scriptSig": "", "witness": ["6c638ac7586e761b5544b7fa32d337502bf5593dcba4a8c48c81cfc9ae0af979c571e472a0bd876885ff99d9b93c69ba5829a01b2d479f6b665ec66aaca1efc083"]}, "failure": {"scriptSig": "", "witness": ["108737c5062c0a93d00afc4fc86c180d11ead1f580c3f58c6a58fb53d3daa06c94ecf752a742bda7ce980b1ba1a4a6fe745a367d21bc92075562df5e2671b9ee09"]}}, diff --git a/txscript/data/taproot-ref/53090ff0e10b029e37a0eab690a757a5f4c346ea b/txscript/data/taproot-ref/53090ff0e10b029e37a0eab690a757a5f4c346ea new file mode 100644 index 0000000000..9b9924c338 --- /dev/null +++ b/txscript/data/taproot-ref/53090ff0e10b029e37a0eab690a757a5f4c346ea @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701c01000000ec402aaadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0c01000000553296460139f8080000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79629030000", "prevouts": ["dd961000000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7", "f5212600000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "f47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa44a76e856afdfa077951e950d1b00a9b743b1044161111d30eb56bfa7ddab902890bfc944cea42013591059ba9f4ec0a95c62699d2133b38017223ef90bcb8e42b4a87a36ff2ed7228bcfc2438815b30cc1c98339504e1b834e10aaf4a034051"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936132265c4b43f7fbce1d2c14e001e4966ccfecb1b0069f6ee6ebbb69457f7bb48760cc2203422c55a835172c125a7e245d244f5477158f1701a7cdf5578cf79bddefbee90a18838bf61213a4f1f5f31a75e180b842cfb60d5f81d26cbd38f8652876f4540117e7e2fda63f7a015ec774d613b8932caa4388fa9ce7145d42cc7f6"]}}, diff --git a/txscript/data/taproot-ref/530e0b9098674994a45495cf1eb8c3fd36b04ef3 b/txscript/data/taproot-ref/530e0b9098674994a45495cf1eb8c3fd36b04ef3 new file mode 100644 index 0000000000..b2635d0e08 --- /dev/null +++ b/txscript/data/taproot-ref/530e0b9098674994a45495cf1eb8c3fd36b04ef3 @@ -0,0 +1 @@ +{"tx": "3c688b8f028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c501000000794a30f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c30100000090cacde503a0306f00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a61e4ba658", "prevouts": ["83f8390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8c143700000000002357212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["e9440ccff55d93379936d095be283dffe5541de496e585ee7250bbcaa943ffab41aba468e5c0aecd6a12d830b424289f15b0a5564fdc86e42e7f72d95df28f99", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/53123aee1da68a8b9619edd5140ab5c6aae10886 b/txscript/data/taproot-ref/53123aee1da68a8b9619edd5140ab5c6aae10886 new file mode 100644 index 0000000000..0c3ba945e8 --- /dev/null +++ b/txscript/data/taproot-ref/53123aee1da68a8b9619edd5140ab5c6aae10886 @@ -0,0 +1 @@ +{"tx": "861025b202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9b0100000044a148f28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a001000000788338a8029f0189000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acafa0f542", "prevouts": ["2c4f500000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e", "af973b0000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "7b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8e069ba5eeb0bec6bb336aeedfc480da3e66ab61ed5906063fe5b68f45dcb12952affe3792374ee751e9779d236e331236b2211c0285bb070b7e5d58aad1c033f64fb6de85916ce1333b57715a419fbbb7fd448155796c8af09a2e4a2bc14d947"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367588a9e23979d821fd29244dca8e20c36f5fbf7a2828b65ef7678089e87c8fd3565447efa486312fa493bc3efa8d0ca00e2c766484411258b08f0fec6b85156cd34322f35809060e9857f404c38bdcaf402c3d07c78e42a3b4d1eaa304dca88a"]}}, diff --git a/txscript/data/taproot-ref/53234e0beefd772757294c48658a6fb1b632e5f3 b/txscript/data/taproot-ref/53234e0beefd772757294c48658a6fb1b632e5f3 new file mode 100644 index 0000000000..517f71508f --- /dev/null +++ b/txscript/data/taproot-ref/53234e0beefd772757294c48658a6fb1b632e5f3 @@ -0,0 +1 @@ +{"tx": "d3ff18670260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127077000000001de5cfb8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6200000000bb5121f804c76831000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac74020000", "prevouts": ["23940f0000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "a9962300000000002251208cf8a45f10f972ce0940452c1be98364c363db2f13613d49d474bd7709bf6664"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe92aff70a2e8e2a4f34a913b99612468a41e0f8ecaff9a729a173d11013c27e"]}, "failure": {"scriptSig": "", "witness": ["6a4f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/5349c13d7b8dd8f692718b4ef221a21825fb04f3 b/txscript/data/taproot-ref/5349c13d7b8dd8f692718b4ef221a21825fb04f3 new file mode 100644 index 0000000000..d7e0aa66a5 --- /dev/null +++ b/txscript/data/taproot-ref/5349c13d7b8dd8f692718b4ef221a21825fb04f3 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b100100000018a6bf8ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc8010000001c25910902ab3e8900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875502f91e", "prevouts": ["12271f0000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "ba146c0000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "227d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93669991cc2f674abc382d5045b0eb857568d5c7aee4d0cb1a298fb8e785822f7d86b7b535eacb46044525b0033e262a0686af8b44a8254e1701bb4a9d0d605b263fcb15428af69077ee4e47ddc8bd2adcf7d97a29fc56c75a24a213a103a1e3586"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f4576a45def9951625cf02c88598f8616d12bef3cc01ed824d79a70edf31b7fbe0e1a4a9bce64ad1fc5af22ad5621933415c83e23766bbab20239912b691ace9dee2"]}}, diff --git a/txscript/data/taproot-ref/5366b2cab843c6f4979214e27b561d35321bd2a6 b/txscript/data/taproot-ref/5366b2cab843c6f4979214e27b561d35321bd2a6 new file mode 100644 index 0000000000..01862ae476 --- /dev/null +++ b/txscript/data/taproot-ref/5366b2cab843c6f4979214e27b561d35321bd2a6 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43b00000000ae08b4eadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c51000000007a44b5c0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b640100000061c4ffd403bdd4b60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac57010000", "prevouts": ["f0d03b00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "96d759000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "3c68230000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "de7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8856e164d8f95680a310901239278cf924747110c023e5c9b2077227ee61e12b7ac1d0874bb493d5b277fe586a1908760dedf191b70e37bd9b06448d9d8257f0a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93622949a7a9280df6a303321d653363fb1d0908af0005974b2d136602a67fd77b5827b55d11351c6fed41de6d200bca95500243dcc7874125f5161f5be208848f0ac1d0874bb493d5b277fe586a1908760dedf191b70e37bd9b06448d9d8257f0a"]}}, diff --git a/txscript/data/taproot-ref/5379718fd6733c3194547aea3041303f46159862 b/txscript/data/taproot-ref/5379718fd6733c3194547aea3041303f46159862 new file mode 100644 index 0000000000..1623271144 --- /dev/null +++ b/txscript/data/taproot-ref/5379718fd6733c3194547aea3041303f46159862 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0401000000bebd38a7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbe01000000ba854d0e04f3d9d10000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e790000000", "prevouts": ["474f840000000000225120ea467ace5d4e72e4b47248d08b4c7e21d4858a06bc17e94ab3d6153139c60e1f", "ee48500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_99", "final": true, "success": {"scriptSig": "", "witness": ["2217ca85f3cb5cf73759214cefb7c16ca214c69645df3c0601a0e6f2c28b28230e42ed2eeb67f3d0fdfe39b2b9daae238c68b07a4b11981d704ee41b0c35679683"]}, "failure": {"scriptSig": "", "witness": ["f7350416c0ec992dc10bab3387eefc5b0af7bef73c8dfa126aff9945e90642259910a0ca9c08f119ea96fb174da4381f41f15c63d5be20303b6efe53b3e78b6599"]}}, diff --git a/txscript/data/taproot-ref/5394689c5e237d677fa75daa48d897e73a858ecf b/txscript/data/taproot-ref/5394689c5e237d677fa75daa48d897e73a858ecf new file mode 100644 index 0000000000..c036804c3a --- /dev/null +++ b/txscript/data/taproot-ref/5394689c5e237d677fa75daa48d897e73a858ecf @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b600000000e9c7f4e6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcc00000000ae03d8a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b63000000004e7e6ee9020bc17c00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acc8010000", "prevouts": ["529f330000000000225120973a94e36a4a923b8d161b8fe153210f91b56b5e4fa7540d30da78859ffb8897", "1b20280000000000225120035d0d8894332b18eeb5087880b9b7fe7a878dc0e9a501d9b85908b60f4f194b", "d2c2230000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93687582901ac4ef6d8d45b4369f7aae1f1005d5e2602d38dd61436b2bc7435277b"]}, "failure": {"scriptSig": "", "witness": ["6a51616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/539798847b99eee00985bc1951275a98b55dd7fd b/txscript/data/taproot-ref/539798847b99eee00985bc1951275a98b55dd7fd new file mode 100644 index 0000000000..24e2adb643 --- /dev/null +++ b/txscript/data/taproot-ref/539798847b99eee00985bc1951275a98b55dd7fd @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700100000000d4506fd8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0100000000c19213868bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4df01000000e0a85df0028455cb00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acece8b33d", "prevouts": ["2e421200000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "1de97d000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "8ed73d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a98", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a9afd50783ddcef84deb29fa414f257c4b095e802047876f95e359846f2205c3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082241df2003654f0fe7fc4600eb797dff990a6f251f130f49fda58fcd5b0cbb08c94c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bc9bcf9ff3721a7f1ef5fd55aac47b8aba67e27589b60c20b5d7827ca859f31020e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1390e5640971602922d6b073671c4e08980ecd1f17d1da07e150f68606efdd1f96e2c0067d6235544c969c57bb6383bc4dfe8083fe3443e336f29d85bd1c9f087"]}}, diff --git a/txscript/data/taproot-ref/53a808e42f754a6b97d63d9648f1e9a70ef36421 b/txscript/data/taproot-ref/53a808e42f754a6b97d63d9648f1e9a70ef36421 new file mode 100644 index 0000000000..ddd672514e --- /dev/null +++ b/txscript/data/taproot-ref/53a808e42f754a6b97d63d9648f1e9a70ef36421 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703a0100000094624dca8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ba000000007ee534a402fc76420000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac6f5cb72e", "prevouts": ["1ba20e000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a", "c868360000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["854c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a8a30cc5f8be195df182d3a0e5016923565d012c99df51a6809fe7dcf26e6445717b4e30a5884e3e55754911c167a338fe4fe766d1d9ad9fb23fde5d0da8b2aeb2a240b376911c9876b3695f79f395ec3f2d97b1695e5c0e7f397f1ed982e79a1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f59837e6bc6752c676e29f45f07d44939857c9cc64ab4a8a9eb8303db51aabd13f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d4e60e987dc96ee5dbea4bc309cd424f3f3a0504752ed5a5936e8ec363297933734b3a7050eee065844830ad8d45a710891f78004f5e7f35b8fd72bf3ee94449"]}}, diff --git a/txscript/data/taproot-ref/53c007e4c811059c16e10ba22c2b8c0f4ce3d99d b/txscript/data/taproot-ref/53c007e4c811059c16e10ba22c2b8c0f4ce3d99d new file mode 100644 index 0000000000..306d3c2c8f --- /dev/null +++ b/txscript/data/taproot-ref/53c007e4c811059c16e10ba22c2b8c0f4ce3d99d @@ -0,0 +1 @@ +{"tx": "9141e8fb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c431010000009eecc698dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6a00000000ac6348d004e56f6200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca6173146", "prevouts": ["83e83d00000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "f83727000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "047d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93640482c4914218b901d904c5b510a4de9c03c595a6755b9edceca77409a5698b30d3ad511cf44769b6705694216a5b431b28318b130ebf832e7f6887216fa315d1a343680beaae3fbea53ecc49afe7cbe880992a117d636f336d7d159be7b446d"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936518a056f01b645db024b67c94355cf052bf827de3bece4ad5970bab770c22e93b6863138d45c5b9211ebf4039595f6572b1b39ac7fa7faf75aa7045d3f3541879de556ac6994112f2dbe51e2f18419f84f5e3afde46d5119f13558b672a3f6371a343680beaae3fbea53ecc49afe7cbe880992a117d636f336d7d159be7b446d"]}}, diff --git a/txscript/data/taproot-ref/53c3edf3601218d001c1e5074a2e608ca903fa25 b/txscript/data/taproot-ref/53c3edf3601218d001c1e5074a2e608ca903fa25 new file mode 100644 index 0000000000..3e1aa777ba --- /dev/null +++ b/txscript/data/taproot-ref/53c3edf3601218d001c1e5074a2e608ca903fa25 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701b000000000f33c6c8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8c0100000053d675bb027de5770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a63f6b2736", "prevouts": ["a2ef0f00000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9", "b26b6a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d1", "final": true, "success": {"scriptSig": "", "witness": ["2c734fe30938a19b22485defb62be791440be6d0aa599f5238ee0714ad4c25d82e1d8e254d9aea29b44addffe7aa101149b6b19e0f9b404f25c58aacefca61b603"]}, "failure": {"scriptSig": "", "witness": ["8e21721e91f7e17c912c1a6b87a900441dbd454d64ec58af73ec487ae16932560e3b85baf59e3bf28f84eca67a04f2e7ed9724fe715b715da2a6834998082b69d1"]}}, diff --git a/txscript/data/taproot-ref/53c8c5901bf8077df2161336a0fc9a5f774e1a5d b/txscript/data/taproot-ref/53c8c5901bf8077df2161336a0fc9a5f774e1a5d new file mode 100644 index 0000000000..0bf7d3e195 --- /dev/null +++ b/txscript/data/taproot-ref/53c8c5901bf8077df2161336a0fc9a5f774e1a5d @@ -0,0 +1 @@ +{"tx": "b063326b03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfd00000000d54304dcbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe900000000f78d71fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707000000000eeb7db83038ea0cc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689870b010000", "prevouts": ["daa652000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "f0016e0000000000225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "33870e000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "47304402206106ae63e7694ce86de3b32116175b3dc9faea35b32d1297ccc318332809ed5102203dbea36aa72c14dd19fba22971c865a95fd3e274968beaed784b73840b9007bc014104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "47304402201f971571ea8ee83397460eddb6fe47273155118e0dcffcb2ac0c493ca72511630220230d82887541d8d43784a193f9709e4eddd44afee0282c75a80948a3ff860e2d014104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/53d0cafdef4e74e058c9073bbd755b723f71207d b/txscript/data/taproot-ref/53d0cafdef4e74e058c9073bbd755b723f71207d new file mode 100644 index 0000000000..b5c6ec7fe0 --- /dev/null +++ b/txscript/data/taproot-ref/53d0cafdef4e74e058c9073bbd755b723f71207d @@ -0,0 +1 @@ +{"tx": "9cb7d226028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e800000000505ce1bc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43601000000043fdc9a0412077300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689879f020000", "prevouts": ["728d4000000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85", "e467340000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "107d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4ece29f6647eca10734c36d2b2a9c99580ea1b3b4606d409e3d27a25628f10946c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada7506a3091a1e28dfc5b9aac4646748f840add9c91a317c4120c5f1dff96d2e4520b5ceb13d27db1b37ec8ee9ee9482aafd08fc62c5401b1fb7c7b4ff374c3d"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f97335490236408107edf93c51ed34034fbbb8ad4f6b9a196e596f5650c1ecaf6665110f53a885bff43176a7d7b6b195840e7c84801cde818ee8fcc4f3857331bd940ade039b405c8439b762bfbc73f9441ef227e6f687b6d94ebcbac32155c7"]}}, diff --git a/txscript/data/taproot-ref/53dc16200f550b0ebabb6c5c132ae4191e1a1482 b/txscript/data/taproot-ref/53dc16200f550b0ebabb6c5c132ae4191e1a1482 new file mode 100644 index 0000000000..8a69945160 --- /dev/null +++ b/txscript/data/taproot-ref/53dc16200f550b0ebabb6c5c132ae4191e1a1482 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2c00000000e3fc62ca04a5c95c000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47878d000000", "prevouts": ["47075f0000000000225120c766455b5ae5e195764c9b332b78d097f842c4b058ff2966094b650eeeeb1f7a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cdb3d0d78ae173e351549f9bef2b17f5d16e4902f43c7279aa4f3f7b9b217ed3"]}, "failure": {"scriptSig": "", "witness": ["6a8f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/53f7ba7985ea8688080ed30b57d08c4ab91d4a7c b/txscript/data/taproot-ref/53f7ba7985ea8688080ed30b57d08c4ab91d4a7c new file mode 100644 index 0000000000..2a4d01a3cc --- /dev/null +++ b/txscript/data/taproot-ref/53f7ba7985ea8688080ed30b57d08c4ab91d4a7c @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0d01000000ccfbefbebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6000000000dc712be3025d9193000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5db0833e", "prevouts": ["4dd627000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "bd686e00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902aa32a49d685c694a272f72af2e558f9c5538a9ac8f1b7f5a8de0f1ce728a6552e4d50d90fe5723fc14a93f913e086bfa9675243b06d15ff82075b4785f46584b26563a65a96d8125fb3d6a37aef446fad780e6b10ee13d2692aeddbaeee69b4a58d9ea2b1192558e96f1722db664a9694058b8074bb7b214ef49c14c8f2349c4a51677831922b369cd4fa85ee3b792072df2f58ef05c09a24dd75d1f16a0c26bfc9800b7da89b2d9e90d05369a24743b85b7df678b4073c29ef53c7576f7b55e4e39f25a168b626e1a65ad0020c8a531b2c9f4b685ef34cd98d4daec49a9f70645b11e9c11e6ef6da14cff63968ec749a04c42808935188f30288800bbf67494cf36e5ad7d5ccd783f6f3681acbce1df0088012c244db592e364b29cc64dd4814db3aa42547bfe54d4c9c8c0a147d7999faa859105ba6bb4a2b0ff86c65dba6c8e359a72e86497a5c5cab851c083300b89dfc6a83e2199521b21d3c28dbfa37445defcb54f7d11e95dacad6694a67d88eea7cf169c6349b9b0ac7c634d71d9622acab9feeb08fdcc7b9d3077181406335ccaeba3200ad471231e04a2c2c6f195b9f845e5d2fce5f6a98641775b799f10fd8a222192005b8903844a36385fdba2c45abf26282a73c874b7f95cd5c610ff428c74cf0ba581303a0e2e29c92234d2a92940581e0b09a00aaf5f1337c9900c3d5f6e618842fb92d1c8885ff91d0e9c259ebe7d6a951edc2675", "907d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c374609570e32d34f993f11726b30429119b9dbd5f99ae31546f61854bcb05d1da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457ba4f11ff80ca9181e3d85997fa959accb8f97af45a52bfd0df916797673441f5"]}, "failure": {"scriptSig": "", "witness": ["4d0902795f5688fa8fa175c26bf326176d3c3339cd166d316d195ecb6bb0a3e465173821c668bdf363e3f2ce214b4798fd9bb5f05f5517f90d85d5fcc96d64ec37c8e360b0bee774514c24efc0855969a5f67df85e1bb21416b809672f1c4862b3d7ab2b8505d1e003ed4ae978d4536dd8a7252d4011d9bb9c442fe8b2a58a6b322af56badd671cef730ca8cba6910face9e6c3cd211a45384a7dda3e159898f0d3450aa092b79c31ee0f945fbc35fc842ba0ed0745cc7d2e6fb6c07b5eab3756c0a6cde0010f7ffa1f7fc3f8310f560ba69c0fba8a07e930d61ed5b47a6980858616a2444dc2d2808544533fb5b133e4b82f4878adbe78eebc99ea3654fb959be3e34b7891ce4f8c9faeb240d1f4d3c49c6cb125fc241c7075e68f76899ad637e2cbd4c7f3dcd6bfef69b19ffdb5277bb9062d75163e60fe4fd6e9b881f29aa75d30d7e45986ae30048e56cd8864963c94666ee7055332bf7dd43e02bc17d14fcf5c204a8b4fb6f1c83d0a3bd76a5239e4d1def2d36da063ef7e1bbded2297b71ea86bbd85d91f5afa9c434ec399b53e68c641db4fd3fde374601b70617d4209dc708edbf3196b7b9715b1796864179b71f1a215682f3e13a2da21176653a2f291e2b9f355a1d5b5bb1f54affb65fc0b47140036caec75846ca3aff2caa5478676cea70264e8468601cda7537983a09a4e747ab5cb5bbb1010267935d4c14aaf47cbf226aa061d4ba55d92c75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b538c086097dec7fff9cc2378d2245032c34a28bbf51320358cadf5b13a0d77c9f4b63c6df7ef43e2db8ec562e1d1dc49232dee39216a09a14bc3b6a66d1e38f07d6dd053b835b300872a79bbaa392d17bbe19548a92a63c5948e9fc7e63dbc8"]}}, diff --git a/txscript/data/taproot-ref/53fd1406ce1667cf7d7de3b444b90660d76871fb b/txscript/data/taproot-ref/53fd1406ce1667cf7d7de3b444b90660d76871fb new file mode 100644 index 0000000000..6a49d49007 --- /dev/null +++ b/txscript/data/taproot-ref/53fd1406ce1667cf7d7de3b444b90660d76871fb @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49c01000000fc23b6c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b040100000067f7ca9b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f0010000009dd718dd01c92f7a00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac43010000", "prevouts": ["ad873700000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "baf1220000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf", "f44440000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100e0a4d654bfb90b42ed8396f0b19a2923f65d70cdf9c17ad803a3e941babeeb9102203a20448663651d81d3f84b8cabb42872fa4c94ecb561b8d41240ec72610d456509", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["304402204dd268c7a63c16ab7f732046be3f0b6281949f30e8cdd322802c13809098811102201194a869e05bf7524d2e23d0815ec8c76c3963e40afd85dbac18decbc786757b09", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/540c6dd899720dbbc04e0f316f56549b4c1ea925 b/txscript/data/taproot-ref/540c6dd899720dbbc04e0f316f56549b4c1ea925 new file mode 100644 index 0000000000..ca473460d7 --- /dev/null +++ b/txscript/data/taproot-ref/540c6dd899720dbbc04e0f316f56549b4c1ea925 @@ -0,0 +1 @@ +{"tx": "c500bd8803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6b010000005ed744c48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49501000000484908fc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43b01000000f2652ed601e58f2a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7f5010000", "prevouts": ["d29a240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d2823f0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "17283b0000000000225120f103da370e61120ffbfed9be73547691440e55c4664603c27eb9ef615a7ccbdc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "1a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93610b0866e686ab02e02c75976444f2845fd6cde7bfef10e820cc3554ce683941d801cbe9d84ce1e82e006940c90d66235295537a514918e448d1b01c99be1031af2727a08c83da142d000f7f66d34a23554b296f940ffe81022e50f50dcfdd8b9"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93604a96bcdb01a6195bb6a7c9814761d079ee609b3dd4c3742d889e5f8a10b718d8e84781bad1ba81b7ce5b7be6cf9bec34b59091704d19096b61e5a37e7aa266c56798b11c96dafc2935d577afad31a6537ce4b1a48ff27833822cff5fe95a51e"]}}, diff --git a/txscript/data/taproot-ref/542c02db48e5517905eab16fd96de2d76702fe3a b/txscript/data/taproot-ref/542c02db48e5517905eab16fd96de2d76702fe3a new file mode 100644 index 0000000000..b5460e15d3 --- /dev/null +++ b/txscript/data/taproot-ref/542c02db48e5517905eab16fd96de2d76702fe3a @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1701000000233e40828bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c407000000004acef7c7044c5ca200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72614dd3a", "prevouts": ["a8956b0000000000225a202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "ca23390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["b83a6cc838fe4ff92a9af858d2efde524ed333cea01ebbc4b7f4773fab924030cf11433ef5c5edaafe13139710b3980b471a60ecd69fa7ace7bec388560a62f3"]}}, diff --git a/txscript/data/taproot-ref/54305f14909100e1757674ae16a759d855c4a647 b/txscript/data/taproot-ref/54305f14909100e1757674ae16a759d855c4a647 new file mode 100644 index 0000000000..6353dc4bb0 --- /dev/null +++ b/txscript/data/taproot-ref/54305f14909100e1757674ae16a759d855c4a647 @@ -0,0 +1 @@ +{"tx": "c7be2d510260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f2000000007a27fcd68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d300000000f23e2aa40213964400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898778fe3e3b", "prevouts": ["d736110000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5", "8239350000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "4e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8d1fd3f29d710dd7ef94713df6d8e3b931ee02ef1dd830d0dcb285a37875735c080d03cc4210f6c8d536ca11754de7a86c068de81055f4750ba9e0b801f8560f6a4a8046f0466b39966676954eca5d67ee52b1615e6fe46612ea9ab4edfa131fb"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365455e544596f3c60eab5a6f875fbfa3721cb31fe6673b63508e23ee0c4afbad49fcb6847defd4ab5435e313e937417091a847a9b6ba01e1bd1b0fdc0d1cd93789d8abe9ca6155576d0a7d6ce7b2728ac84476385b9c54c38b8a9cbf195895186ab153920b849b6028620ffd2b7e486a6f5e2411aa058dab621c72a45f67f5d8e"]}}, diff --git a/txscript/data/taproot-ref/5445a326ed6ffd6f95dc9cb3c9514a0e53f4868a b/txscript/data/taproot-ref/5445a326ed6ffd6f95dc9cb3c9514a0e53f4868a new file mode 100644 index 0000000000..b0eed9f1e9 --- /dev/null +++ b/txscript/data/taproot-ref/5445a326ed6ffd6f95dc9cb3c9514a0e53f4868a @@ -0,0 +1 @@ +{"tx": "b183537402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b730000000029171eb98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40a010000006f30ebce04500f4f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374879e627060", "prevouts": ["76491f00000000002251200e94bfc4da0ec878710fc6e63dfa8cf2888c96cc8603d6f04301c7800d453852", "9dc6310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e0", "final": true, "success": {"scriptSig": "", "witness": ["69afd9f2ddf550f3dd28592c7380f6c43b680e7036a7e1325978b3dda47c48a9fc9cc357a211b8a77a00c9aab0f07118928ec2ebd9374228306de27069bd85ab03"]}, "failure": {"scriptSig": "", "witness": ["fe7e2ce76ac9de3d83c57f6b8ffe06733f41ab6ba2920b76dc2b58409a3f33df5b3c3855ba7e35dd51bb495d54e8c4e7d48aacd1b8c6ae9156e40513ebb7b1e0e0"]}}, diff --git a/txscript/data/taproot-ref/545537c377201418fedef933281d2dcbea90a159 b/txscript/data/taproot-ref/545537c377201418fedef933281d2dcbea90a159 new file mode 100644 index 0000000000..d2438b6bdd --- /dev/null +++ b/txscript/data/taproot-ref/545537c377201418fedef933281d2dcbea90a159 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc6010000004f2f5a8ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf201000000518448d70270749900000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c5000000", "prevouts": ["81447d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e7081f000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "483045022100ca3fb19553c8baf1e000b5f9d1dc48f89e80310337390a5c8ac284f198bfb4ea022039aad2d42b72abd50815651f388ddfcf8665c85b154fbf5af5a0733c7ac9c64283004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "483045022100cf545cf82bbadd5f2ce6a14fe973403c54b610283ad94017a534545ac22651f3022078a099f994710d330f10db2334471551190563fd7bd9e2b9b8393931ca2c68ba8301014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/547539d40d65ab39026f065bc9152d96c7c4ad43 b/txscript/data/taproot-ref/547539d40d65ab39026f065bc9152d96c7c4ad43 new file mode 100644 index 0000000000..4f4d3485a2 --- /dev/null +++ b/txscript/data/taproot-ref/547539d40d65ab39026f065bc9152d96c7c4ad43 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1f01000000f063541e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bf010000003a54a79804b961930000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7969a010000", "prevouts": ["f0058500000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "6a541100000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936773136ea4d9f4c1bceb0dcfda29bf9f5f26c6bb27d9ca969f75ef19eed55ea123f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08225f2fc2293577bab1371dd996050d2a4e8a01eb34ee2db6c09974277461b3e6691bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f5e72664d40ec18feba23359c060b0289d5f21df5bacfea8d53f38e9c21f97b575d1df7a3e4c47ed4bae99c3344f7d42d0c4d3b112e8138771efc2bc74e29dd3ff737734404bbc9015f34371be38b9f5376f1a60720e7cf7da81354011ad4f7"]}}, diff --git a/txscript/data/taproot-ref/54ab5c42625d4869197c04f218c443750527c92e b/txscript/data/taproot-ref/54ab5c42625d4869197c04f218c443750527c92e new file mode 100644 index 0000000000..844de985f3 --- /dev/null +++ b/txscript/data/taproot-ref/54ab5c42625d4869197c04f218c443750527c92e @@ -0,0 +1 @@ +{"tx": "103e89be02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b830000000082ed4bd360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709600000000ede849cf0184480a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e70c17ce26", "prevouts": ["149c1f000000000017a914bf07e8218e5a3c93fa381357100b6dba1ff2a91287", "e7361200000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2354212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["f76e93c925e04e4c813605eae544eec8140e2351cd3f147a2f144173f57b90bf742eb4d523deb2161014d82e5c33c9681a1814e02147707e45695d7109d47601"]}}, diff --git a/txscript/data/taproot-ref/54b4f9842dadbaeb2ac90b0f6d8177f76ce3f9a1 b/txscript/data/taproot-ref/54b4f9842dadbaeb2ac90b0f6d8177f76ce3f9a1 new file mode 100644 index 0000000000..77f29ea688 --- /dev/null +++ b/txscript/data/taproot-ref/54b4f9842dadbaeb2ac90b0f6d8177f76ce3f9a1 @@ -0,0 +1 @@ +{"tx": "1a7ddf0002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1600000000f71b52aabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbb00000000a38578fe04d6958f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fccc000000", "prevouts": ["8900200000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "aa79720000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902388f390252817a200d6a40b588cfd04424d7c863834fdadf2a5db7f53d0c9dca8714303aea8393b95fb4f03ff7c6d8bd81a114e707235dd037520ca8be53b9fc3949a8a200c185a2ab0073e0132e629141577b84b734599034766f2bd19d19705f25dcfab7104448de0500ef7cb84860dda1b8f6d15bd93e83a23a206ec45dd013b1642c17ad3751e6dc8e6e72c20796033afff3200a40597292fbed0a7ca63c06636903a9bd8737354dd3a35ce5824a7d6409d43abd04d1a292be47a547a74f23540d7e7c315e59c7a1dd490565bca6bb8b89d01e5eccbbcbfc10b93d31ab705752a449b1f493bcdae4f9a494b781096876ccaad39c83330c07ed7217b81aa6d91d214f1dfd4dbea38292dccaa6034bc1dea4d0c58a3ab7d77734f3d1e7301ae0ff77b861f5f5e8c51a09656046e0c111c0d2d2b5062aface8dfa1191588d67d6990a6e2a3783328cf505ce47c443a415ef150f8b5448a66ad70e80120186d54b7d940dee872a677a7ce666e0b2c45c6cbeb76248639ca4eca5e7dd731eb542ba030fd6ae3bde665869e37a99d02ccb6b74d59a678dae7a95456654125ee24086dcaae272e76e75cb985f53cdc6c1143b5e18bafbb6eb09d44fa24cf97381a83c321856199f66ddf6c4fa4c4d9ef99b29bcb1ea83398ee8837cd56a969288cd21821e4cf91b22396ec02366273df529efa96eb5ad833b06903f0dd5c0a90691fc28a7df4b74d5aef475", "017d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad606e86ced54a653210e8da1037051c2b45f06b64d9f9b7dc936ee1cca52c733f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828874369940c44314cd428c72b977b6d1fa375b1e54ddd71363c505e3530065c38810a2a55ef559e3dd2f859359930339f67e2de31eeac841179b888fd41fd8a3"]}, "failure": {"scriptSig": "", "witness": ["4d09022d34c754e8621d84f7dc68399121c706d613dc2e9eff25991ab6830780143a43b36aad5ded905e3f3d9a7a80a5cfbdc8432f2e27b8b61adc8ff9026ac400580c62d0dc3f9603273adc4c50a26528a996fb7f50bef113005bb18a1c01e37f633e3ecb79f9a967672d37c616eeea812b04e498b569686dc40ee2434c42588d5eb9ac0750207f0bca4aa6fd92c179c6787658f75de6c5269d0984b0852945fe02fbde9d0436e8dfed7cc5309f95959d5243eb38a380a11907f31410c482e45f643dd664872732407a32a3dadd0586a8608d6bb7735c7356377b5221827c80c69cad2b1398174ca99c3f1a484a29f44e8a1b8547540ef2e65cb54a09d22c95fee64949a3185aa597378fd1a508b75736df72d2627f2002ec15a4cc107440ba80ebaf40966ee924391f7b776e003a444820bdd3f318034bad7b6665612f96e2f06b39858bbfeeb5ae83c3434f53f48bd65421ef2685bb5b164cf18c1dc21e1f33e64e7ffccb416ceee437ea50c7b59c8b64d0334415a78218dcda72f6711bb631b383c971c3c75e86f8d63171f7a939b17949a189a96d8cf6d1dc4652d85fd22b935edb6c8706c8b8ff56fdb3a3ee87c09f826d9eee80e5a2fa4a84287619dc0224b3346c6c2350e8b85d4c779a3bd398fff33dc8c3a093edf4736cd8315aa88a66dd47006b31affd5361fa5b30db1879c7a2a2367bddec86fa4dad85cd26f0091f856c0d38bde4f051fcbf75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361cd8248981863bf5208678f4a8be84ce1e7bd946743b34df66b16d7c3eaa91323f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828874369940c44314cd428c72b977b6d1fa375b1e54ddd71363c505e3530065c38810a2a55ef559e3dd2f859359930339f67e2de31eeac841179b888fd41fd8a3"]}}, diff --git a/txscript/data/taproot-ref/54b9966d625700d7ab8b6fb6e1c3e019b5a09f6c b/txscript/data/taproot-ref/54b9966d625700d7ab8b6fb6e1c3e019b5a09f6c new file mode 100644 index 0000000000..3c21d678d6 --- /dev/null +++ b/txscript/data/taproot-ref/54b9966d625700d7ab8b6fb6e1c3e019b5a09f6c @@ -0,0 +1 @@ +{"tx": "db5803d80260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e101000000d732cef260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d301000000446240800499271f000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac2c32be27", "prevouts": ["b1ce1000000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "4fef0f0000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}, "failure": {"scriptSig": "", "witness": ["b1f8db07571db89d159078fb87ed3ecf6e2f05159390af1113a68eb7e26caf0e06184d946290dda3ef2a7026fa03675e437c", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a25721145276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}}, diff --git a/txscript/data/taproot-ref/54bb653bb1662d8b2730bde1e4a255606fea193d b/txscript/data/taproot-ref/54bb653bb1662d8b2730bde1e4a255606fea193d new file mode 100644 index 0000000000..c42d67cf53 --- /dev/null +++ b/txscript/data/taproot-ref/54bb653bb1662d8b2730bde1e4a255606fea193d @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270350000000098af0dd360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701f00000000ce699485013f66180000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e77b030000", "prevouts": ["54ae1000000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "fe110f00000000002253202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["7e4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4efe8c29822d261ccff72913d153de8b886275dc8d15210ffbb43fd45d8b4e8e401215e29d5d13de3b6ed62165bc3378402ce71158bd1208562fc299f33fc22fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bdda9588126290ab75e3f97a29526139f210dcc234ab0ba271134ea4893d76ef82f3f1132320d0959751765567119a0f105dea34ff98e3a4034ab732ff09dfdbb3b80bda1b133ebf5523b41a15c88aa3d5202619e06dcb6a8f4a5442678614e2fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}}, diff --git a/txscript/data/taproot-ref/54c4a1f796d9ff3acf74d30faba1654e46cb8e87 b/txscript/data/taproot-ref/54c4a1f796d9ff3acf74d30faba1654e46cb8e87 new file mode 100644 index 0000000000..5e4ed8e100 --- /dev/null +++ b/txscript/data/taproot-ref/54c4a1f796d9ff3acf74d30faba1654e46cb8e87 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6c01000000caf387b6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0701000000d913f3dbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf000000000d47bb5d904ec5a0d010000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acef05f434", "prevouts": ["5591730000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "a0b64e0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "88954d00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368982585ef19be154a5d0887475e9222bb71fccbba422f418bf7ba462437a3b52233ca416c78a4619c687785de007f14a4879f9c7a0556256e1b46b2a7e5a39b3c2782374d67da9500785d400f7ef10ae84f146bbb568355094c68456b68f7a283b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0e6ddebd74405781922a3c06ec9e019fa66c9803c79b531f33e986452ce61d5d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51ab4aa5d5e3dbd00e7a6b81724e903c1ca482dc7bc8339f552afc52b4f38fc6a5b77966166a359aa5541e77c34a58fd9dcb7d88ef6e7e0cd0e140e1adf959d28b"]}}, diff --git a/txscript/data/taproot-ref/54db865605c4886df424d455f6674d7c9f904922 b/txscript/data/taproot-ref/54db865605c4886df424d455f6674d7c9f904922 new file mode 100644 index 0000000000..80da63bd96 --- /dev/null +++ b/txscript/data/taproot-ref/54db865605c4886df424d455f6674d7c9f904922 @@ -0,0 +1 @@ +{"tx": "4a229c5502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc200000000278d4f8dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9301000000fe6f74e00168477700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac24030000", "prevouts": ["784b60000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec", "40117a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/codesep_pk", "success": {"scriptSig": "", "witness": ["86b2803b04d84f0eb0060af0d56d7c94695f84ce42b701b577ff1355e93ec5b1f2364568ac950202219443dbed6f24cf5dc3d6753b4891db677aea328f69552b81", "ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b48512f8e6e82cca8f3eef972de21f1531c72d4d209707723bcdf2a49924bb9a", "50f3dc1e441fa570b2c205a4cbcd4936eb67a7d6a442efb819ff13ce3318b08c793621b40d973b62bb102fafa78f3d776ee86a9ae954d2894c881fb3607da72be48b173d4b31b54bcd9d3453cda3"]}, "failure": {"scriptSig": "", "witness": ["96e2526a50b6f736a62bb7e8af12381ad71571cde2da557b0011f006bf8fa823f96e9a5622a8100b6cfe6a068fb058a3b56f1f0dc0dbe256526e4061b54c3c1e81", "ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b48512f8e6e82cca8f3eef972de21f1531c72d4d209707723bcdf2a49924bb9a", "507412f72ab3d1c93d00e1664a84df69b93d8b3be23e71a919109a94bb98bf61eff93b4ae554c792f895f382099c31873c4c9d7666117b297303093b28c62cd83f299395514c19ebf1ae7e752082d59df36745ec5821b35b9e7b902584b4d7c2993aed093739984da7ece808984b829a0f708fc04a0f2d496d6b14c48aff278db51a819c0001f5c25bcff36fa15a499fe739ab20bfa3dce95bc60fdc0a778d154449"]}}, diff --git a/txscript/data/taproot-ref/54eef01ce1e7ec1e6b58bb1a7e192b0e5d3a98e8 b/txscript/data/taproot-ref/54eef01ce1e7ec1e6b58bb1a7e192b0e5d3a98e8 new file mode 100644 index 0000000000..12e3406c9a --- /dev/null +++ b/txscript/data/taproot-ref/54eef01ce1e7ec1e6b58bb1a7e192b0e5d3a98e8 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9000000000e38806fadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b27000000003c867fec04b7aea000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987b2879b25", "prevouts": ["4d15810000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "1f522100000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "087d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cb173d9968a47ba6c5c74f630df9011e2eaca208cfb301cadfc15d58ec381f47a9c5848e7797e88ab157cf3f92cb1e084ad7139395a6330a6d0efe4ec0158f0520a79ac573d08fada6e0a495a70546abebfe2eb256837e38d30334686ccae33"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e881f944ef569cf36d808a56aaa75ca2fdbdf4182c26b1d87989a6b5ad676759bc691c2a9908d9e7287fb91837cd9c32b2a21ac331bb306f4648aa27bb40422e45371e41a07562523a12648be26bdba66be78ce7e249298c356e66cf29847872e0"]}}, diff --git a/txscript/data/taproot-ref/54fe044e4c6d4dfed594e15518f9550df3910bc9 b/txscript/data/taproot-ref/54fe044e4c6d4dfed594e15518f9550df3910bc9 new file mode 100644 index 0000000000..7c04fa42f6 --- /dev/null +++ b/txscript/data/taproot-ref/54fe044e4c6d4dfed594e15518f9550df3910bc9 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49d0000000063080aaebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa801000000660303ee60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ba01000000be4370b5010fb78c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7d8000000", "prevouts": ["c21240000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "da9f8400000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "a0b10f00000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "557d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e283c6292a6ae3f7cd2fa90a42d11f5a54bea63a95cab37375097c35ac3f3911dda77d1c2cfbe9569ee5db2c51580a9857624040db9177af617be0771cc5b8a1b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8cf2f607c60f6c156b7df40b9550df6641a796550f01570d3040f84cea15217bcf33eaf0e0e2046a2b327db0183a88d397c5be0a86c812e98815a20f9da9843a2a4c5d50721208c85113b157b4dd4688510f63bd33d4c90ece0d9e0afcb8224b1"]}}, diff --git a/txscript/data/taproot-ref/55222bbf499234ced0243f0c54a06a8e01ee78e8 b/txscript/data/taproot-ref/55222bbf499234ced0243f0c54a06a8e01ee78e8 new file mode 100644 index 0000000000..78052ff481 --- /dev/null +++ b/txscript/data/taproot-ref/55222bbf499234ced0243f0c54a06a8e01ee78e8 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd60000000099b168e7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb2000000007a2554fd01db7f7600000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac30020000", "prevouts": ["05864a0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "291c560000000000225120327f04e65f02f8e03ce78ab2157c33b783b64287146459b669c40017b50fedbf"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e24c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93605be3ea16000e1e5d0cd0f286bdd228006eef88980c7cd756b0c9f357e0882437c6ac6071aeb5642f86cbd8c403a36f49b1ae971c310fa0b2c6d23cdcc52f9ae3b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c8536a7660b750cdfc13bd850c6f9f37445f5bbdab2263015cd8e07ff5f1c21f1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045b0bd2b339cdab1cb752df7db1bf10e0fcc4b57fed7d380ff50ba3a0b4b018724b77966166a359aa5541e77c34a58fd9dcb7d88ef6e7e0cd0e140e1adf959d28b"]}}, diff --git a/txscript/data/taproot-ref/55296a40c4a4eec0b8b959e6e4af29fbf647774b b/txscript/data/taproot-ref/55296a40c4a4eec0b8b959e6e4af29fbf647774b new file mode 100644 index 0000000000..45f702eed2 --- /dev/null +++ b/txscript/data/taproot-ref/55296a40c4a4eec0b8b959e6e4af29fbf647774b @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0901000000304617538bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41901000000d85fa7830225df550000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ace8000000", "prevouts": ["d42d200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "517537000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["30440220114488f8f5c7e9e144d29160202126703340e984a92b22cccd20706b0142ee8d022021ffa4d7437815ac5986054c7ec78518ff5ff7c6eca09782bba6fc69c443718503", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["30440220344a4119ee7599c9e9aeae585b1cad52c732c9eaa20dea4990ec34e8fd2939a102205d792198fa4ebef703067516c2b289ac552a5ef9aaa6868e237a0f5d959695b703", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/554254ae450e17abd46d3c290600e3620f888246 b/txscript/data/taproot-ref/554254ae450e17abd46d3c290600e3620f888246 new file mode 100644 index 0000000000..8c72e6faf2 --- /dev/null +++ b/txscript/data/taproot-ref/554254ae450e17abd46d3c290600e3620f888246 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41c00000000082f34b00462563f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8740972a26", "prevouts": ["732642000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09026ec1278f9175ea9964c62306ee2f96c56f3c68684d05706764e8959eac1b5c94278d497170172440f5b7d26901090663278279b1e81477650ef80cfa97271f3eb85b519bc44e0226f23d1d2a79836aa3f792eb7eb50e3c5d7a4cea0803d0635243a29f5b99a6d7a4daaf80317951520f213c8d090ff6a0e4e2ae7e95faca525d97ec42bd9de4027d1ae98cdba59971af909df2814bbc9fb58f4d717017ac6035eaac3ccdc2de8862fa6f7b2b1982105bed692dac05c49675343e18bac994f810665c87ce9f9e2788d6a54d5c94f6736ce00793dcceb718ee8d31e0a380f49129f62a0a8f895d2cbb38203224906587a7dede5edb4f4880ff642c2591bea0e90ff8d795de06e51e618d53b4c7c9c89d3f657533aad57390e8f4989e489b23c6f3621969f1f48155cdaa19b36f668bff036b894e944af6d381d52ee8e1439c86b9d1f7974a51bc084c30f3190264aada52154c85f4b8fc0b2b4eebd391a32350af604a788ea95062f8da07e4790fa52a2988586b964afac0ba57e5dcb529e1ea5409da8396df60271667f9c619ef715c570c743b3b85c9d41ac098d83b64c079740bbc5f1c085567ef6ffaed37b24922dd5134c63adb756ee4a1c1993f7d905790c5a809c75467b6b8999fffd208583bcef1a41ff4f241cb30cf4f3ca6c747f4cd1cd5ce87951b8b464f95eb95f62373b9f3eb7c4caa93b2c7687c81f3aaf36a4147d8af5fc41bb7a89175ce", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366964dc31804cc2f0bf098e3336240100d67f6f4f6698d2be2bda5f0de8a283d2a253f0d292bf616dfa5076ba7d0aea90d79076a752abe834699a79484c5e1632ab692e734634bfaf43d653c1e6f6d8e8d14797d8e4fda7a04cf5eec270202b46d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}, "failure": {"scriptSig": "", "witness": ["4d09028c2a3a94e400901a5d9568cbf428fb68b23dbd7bb7ae669cf90c06fcf43682d9e6846744ef634dc0aeb164dbda0eeef5a484a5eb0aba51c09f0dcc226b33f8285139e6958a372be06c0492260bfe3651eb86b2005fa4497a0a4658a0b25677304c3d0a348113392614ca63edc0f58a2982b29bfb23963681d029cbc73fc67cba91fcde9a7ebd424c061d732ad09ee638ddc22dc71ea4b756dc8ab0e0cbe7ba38649f84fc1afe16ab82d22dc4f59447c1ecc816e98516bec89b4b901b12913e2950c1fca82aa9d9639eb061264b731898032c2e57e2a6f89c199e5ba052e5d28d5a3fd2744baa6e9e53687a3aff6827b164695374932f4ef6b2347a34e7353e036cbb225353729997abb8eddc8246b149ae8b2c40a9b99396cec58a22d94f5408ea31e71d0b8680c02833404b7b1531c2475f33d852c5907a03a6df1b89cce8fbaf50a7a7728fbf820858c4f84bdb4e548a66e1a8aec0bd91f872ff5058d13f3754bf87507415e241cc322836baffd447c619d2fbdef394f0dd53de6af9a03f4b3f34a2b0bdf3f3d4cea8b920ae29895946b592876e8d7bf60d672a64c188575d5c420b502c7d1b5bcd756b4c8621951c28065c897aa8f4ceb70292c3db5fea94a3502b53ae587c16cff828d826e341ca5cb446d783c23bfd68835e158ff7addfac61df8b7bc154842033a2c6d5209105d96009c813e4a97c6e99c0b480505387e3793ea6093038b69d7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a9519128ceaa4d58cf3fb9f4d9c0523c691437b9e7fff300bc110a05f7f4d056a253f0d292bf616dfa5076ba7d0aea90d79076a752abe834699a79484c5e1632ab692e734634bfaf43d653c1e6f6d8e8d14797d8e4fda7a04cf5eec270202b46d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}}, diff --git a/txscript/data/taproot-ref/554ee85d50ac67df97fb01a2eb533f4a62a41c9f b/txscript/data/taproot-ref/554ee85d50ac67df97fb01a2eb533f4a62a41c9f new file mode 100644 index 0000000000..0159376fe8 --- /dev/null +++ b/txscript/data/taproot-ref/554ee85d50ac67df97fb01a2eb533f4a62a41c9f @@ -0,0 +1 @@ +{"tx": "1856b3df02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4e01000000bd0fc0dd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b0010000008f497eb404b1cd82000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c40df233", "prevouts": ["dc4e490000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453", "11a53b00000000002255202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["e5978118d5ab7952e4e6e4d5a8c98c5e9f64c85c89fdf7e3707edd32a9535f8ce29fc39d031b595a30ca3ad31811cebf67b7a27203d8b37a4c7ce5a7310277e5", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/555fcf75ef7ac731ace1cd81886b6cc1b013e911 b/txscript/data/taproot-ref/555fcf75ef7ac731ace1cd81886b6cc1b013e911 new file mode 100644 index 0000000000..4ae6dfbd41 --- /dev/null +++ b/txscript/data/taproot-ref/555fcf75ef7ac731ace1cd81886b6cc1b013e911 @@ -0,0 +1 @@ +{"tx": "35c5f7e30260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270220200000096b2ecaf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44c00000000bf5276d503061a48000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987c030cb56", "prevouts": ["02ee0d0000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde", "ee013c0000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09026973b5783f65fbdfbbb97c1e803fb4c9de0c7d1238f104174b03dcc9d587b2b9c7a82559d322149f38f17069afe237e939823f7faa63468e2fb6755a0f0b5067ced966a74f0d3ff0a8a381cc0535ec87eb62aec54d1d08568aea1a998ed54a699132e4cf163174a04f14bd280b10424ce95a02d106929bfb8fdde7a32350ccef8fc012c01e324d8834ff8988dd9e961973f66d0b3e6ece3151a74db71e4b406a4d9bd45cf7ee5c48004657fbb603b5f186643b9397739dea5870434c69a3a493795b619b5b89d74ac57db568992f7d1602f2c27c8dfc5466c7f15d04743ed9a153062c93039010ec75696ba888bd1752c31b842b4d96b0a868190e201bbd6b49d96a958e176f694d9dbecfefbfccb04f16b4e4459912ff369eee76e2d0ab2b4aa2cb9ceed00ee07d05dc1585556ea17d3aaa3b438e6cafdc28ae56db03a406ffd750acc125ed3f24b90d842e808439f4b60941a7d2125a81ec4ef78a7268f8b9ca6ce0ea9179ffd152bd48e8da676f9adeb3eb9b1fb7642fd37122da0e08f13317dcea0a0e3fba7019e29a821b49e39d29ce012b796648d42235bc1929e8172317bff6b2689e8937cecd2652a12bfb2e63192ac9014d9402cb7d18fac115019a543b759fd356b05a86517812e2c4ae4767c73844b1806d4d1e3fa2a4d97c3b1a356ead13e3f969fad22e951f8ad8d072a820d8ec5dae79a4b2926100c405a455481f2fb7348a65eda875", "477d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082a24674935b347637fb115fbceef28e6d08e5e47afc6eaa336546ee2e891e964bfd9e929a06047270fff43ba4c6b47136464c62381aba7ed74ab98bc69d199aa4"]}, "failure": {"scriptSig": "", "witness": ["4d0902a994f7cab56864b639d7532171fa7080452b27cc8e4b12c31b45397a6308c0f57382b72241ded327b4632b43f8273d85ed97108114527bbbe415ba0f43d03d38d27d899995919882cb51bc8776324deaa71ff4dcdf96920bb2d7144dbed4f89ecab199dd4b45f01847e18aeceb6769111cd83d93d08dbbf50a23010d21dd752d04ec47a002034ffc182d0b35cefe21873e8f0deacdee0e5e657a4c2c9e1001e31fb951d9e97d18090521ca92652320640bede5c8a221378d55f11611752a778860aa7e3c63a59557b215364415af71d7df84fe7a89917c52af5ea0dd579936fea81f1d0f22e7454aab7401132a5bcde5e26647201d92336f2bc6679a4d7dbf1f58bbb7773d7312f5b173e77b6c3382d8f62fc893466309baf14b8dd04f8dd6300fc213476f98c4b8dbc872395792ffe774e158a6e8ed74bba26b7710ecb2cb352993bf272018b05fb0b9aa7711a8c2452563bcbb1a23ecb614327a28ddbe85ec18189b62d977384f33a2184146f7c498e98e473d2f8bac35455d6cef9db022edc7eaa9be12223f1ec26ba88ff210c26b49d27e73bbbdfbc4bf09196f45904fbe71d1c2378533cc9e9f742b54f16c0152a9cbbc131f359e0456ba056ef192b47ef428af365e825b0bbf3f9bc63acf3f48328a80679c972e1487d7bb561ce6052136a63fc7d90562089b1785c8165f81567c0a365229737245aa03d8c663aa0ba438817bcc7766d3bced75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0d94273a00f5b73468b8b6c7a839b831dc0df283de3dbe2175dff60161da024ff81b1159cd56b1887f265c0d653f3c782f8c9b1bd8992faa992c6296a364de747adf318628644459e7d8d4ba81b7833f70746497cdf0fced2937ab961dc2be46657009e9173c5ef8826379cea4b8c999e3ae37a5805e4cc6da117a3d2ee0eec"]}}, diff --git a/txscript/data/taproot-ref/555fe6827560beb47e96016c2aae78850a4e345c b/txscript/data/taproot-ref/555fe6827560beb47e96016c2aae78850a4e345c new file mode 100644 index 0000000000..bb2494742a --- /dev/null +++ b/txscript/data/taproot-ref/555fe6827560beb47e96016c2aae78850a4e345c @@ -0,0 +1 @@ +{"tx": "26bea3fc01dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c970100000075c2f08501cec6000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7bc98653d", "prevouts": ["57144c000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "final": true, "success": {"scriptSig": "", "witness": ["2eaa8d5c089018ad5270968232d49205851ae61fce62758bd75b66eb5f615fa421a3365c10fe5f11234c962ded42d732ce69c3aa764a03d4d87b859c333e8a4102"]}, "failure": {"scriptSig": "", "witness": ["ab684fe283f2e3a6ba9ca683327d7f1dc3759c793bdf64459499ca596375323b89b4fe5ae5af3e190f35d63c5129b5192c5c417a5c6e1bae88139c0ceaab809202"]}}, diff --git a/txscript/data/taproot-ref/556a65730f4092db6fd77c12b631d10117d47033 b/txscript/data/taproot-ref/556a65730f4092db6fd77c12b631d10117d47033 new file mode 100644 index 0000000000..4e00d85626 --- /dev/null +++ b/txscript/data/taproot-ref/556a65730f4092db6fd77c12b631d10117d47033 @@ -0,0 +1 @@ +{"tx": "28a354820260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ff00000000be3b46b4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1a020000000e78c7d001ff502400000000001600149d38710eb90e420b159c7a9263994c88e6810bc79c000000", "prevouts": ["1ea6100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9e2f22000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["eb4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360c54e1ada67eb35c9fc75440012c0966dedc9197e6aa1f92cced4ba861a6e0736873018117c319506164013bcdec2d285df0b840d64f5a35ebdb06eb3e2afdaba9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51434501c222c2b9303845523b2a5615208b9d5e9b8dddf3d495d8511b54149dc414f0d108097d00934ef2973385fcf188ce2945eb833bd9e90fcb9cf025505833cf9ce2244c675144b577c27c052f9ebd481172245e28e9502c6c6e8f12c64fa6"]}}, diff --git a/txscript/data/taproot-ref/556db9cb87763f9c127e87edfb88a8e8443c00d6 b/txscript/data/taproot-ref/556db9cb87763f9c127e87edfb88a8e8443c00d6 new file mode 100644 index 0000000000..ef6f0a1137 --- /dev/null +++ b/txscript/data/taproot-ref/556db9cb87763f9c127e87edfb88a8e8443c00d6 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf48000000009d982271dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c76010000002843b97c03ee7dca0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787fd93ba45", "prevouts": ["a3c46e00000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "81d15d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b7", "final": true, "success": {"scriptSig": "", "witness": ["05f60808292ccef731638e9b9747c64e9435dbc9ba39b0e398d17e49dbebf458eee028085fff295713a4ce747ef3d6634c6a1108001022d25cb6881cfa3bff3681", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b7e65707080c7e7248f0619dda3bad03e440bb6597604bc9ba48730a7bea7f137df02784b49116fd665559aca61deb00c6e519c846f32d4dd1be10d8064350d2b7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5581fa4307ec84b987cdfaee72db964e4a304876 b/txscript/data/taproot-ref/5581fa4307ec84b987cdfaee72db964e4a304876 new file mode 100644 index 0000000000..2f5fe72de9 --- /dev/null +++ b/txscript/data/taproot-ref/5581fa4307ec84b987cdfaee72db964e4a304876 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47b000000002870fb82024be0380000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478780db7c61", "prevouts": ["c82a3b00000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["7f", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db342938b39be9e12773a9624b573dbb1df9d93500dc93058087a84b4280ff8e70f73741da43ca43557c58f6aa15023f4cf70566ac935702465d6fb0f93d4429f8d5397512e216c7ab52609f0ab27ccbbfd2b7e561d7599ada55e292956af911ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb44a1c4274957806206aadadfd15cabecf517c42c49a66a44e84081097b7475aac480120d5a477c096fbef97d1ee2aeb957fc425ff8aedf322b93097b3a97db744cf5fd42f9969f7f2472ed1fa62ffa49909a09466cf06ef7c57cb1be351156c54"]}}, diff --git a/txscript/data/taproot-ref/55944a2b94a2ca58cff331e3ef254a2869f5fb50 b/txscript/data/taproot-ref/55944a2b94a2ca58cff331e3ef254a2869f5fb50 new file mode 100644 index 0000000000..da041cb683 --- /dev/null +++ b/txscript/data/taproot-ref/55944a2b94a2ca58cff331e3ef254a2869f5fb50 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6701000000a473d9cfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cda0000000076ecb2df043144cd0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7edb0fd40", "prevouts": ["2b0574000000000017a9146f2d26adc5ad58653becfc45ce03a0b1167b1b7e87", "56ed5a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_32", "final": true, "success": {"scriptSig": "", "witness": ["0d0ab90d46e1643d1ec1fea1cadfb2cc8056cf235a7fe16e181860d7c2c2dd9bfba013dd7d8e1c981f5634e3824897f3a18707edfb4b969727b09a6ae64c731e"]}, "failure": {"scriptSig": "", "witness": ["a7cf9360233f1ea7d86199a6314b754746092474f24a0872e6ad147b010ab9a589c1835806f024834f0f92703a0ac9d6fd46ece753742dddc5994b5d66046cc232"]}}, diff --git a/txscript/data/taproot-ref/55b0896604f6a6b38c17cf95f8c053e19d26090c b/txscript/data/taproot-ref/55b0896604f6a6b38c17cf95f8c053e19d26090c new file mode 100644 index 0000000000..8aa0ec19e4 --- /dev/null +++ b/txscript/data/taproot-ref/55b0896604f6a6b38c17cf95f8c053e19d26090c @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4b010000006599e3b460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e9010000002319b8e0033a632e000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a3600632", "prevouts": ["b22e1f00000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7", "0de6100000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "b37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936903d2a659aad03c667a6b873e21cea168414c29d3474a9880634e3e12e550e8c33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a368ced990ebadb111ebc3982eac7e308f07f99a9264ca6c949f56162916d7884"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93613226b488a95574c43053209c9e6fe8a3ea8bc7dade3cccc06ee2b8f5d857db7ebec8f444f9538a00b5e533aa370349d7181cba703021b72fe611d481b359a8e62055c347ba5402321504576f6c37d0c6cb1d044ee75df535bc9eec0560634a7"]}}, diff --git a/txscript/data/taproot-ref/55c61e7a6bf6a7b27176d90e85c792e38fa47d95 b/txscript/data/taproot-ref/55c61e7a6bf6a7b27176d90e85c792e38fa47d95 new file mode 100644 index 0000000000..bad4053857 --- /dev/null +++ b/txscript/data/taproot-ref/55c61e7a6bf6a7b27176d90e85c792e38fa47d95 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c890100000045a341c4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfd010000000a8f2aea0184814a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e742cdbc45", "prevouts": ["97085a00000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a", "44315d000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "627d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457a979a031634820b293704e38f33c20e5acd9cb2a8735bda71fecc5f77708044027529efe07ed3ec82dce77345a5c0eb368b138839946732056b6a908dbf5f05c"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b02092f1126067d557fddf65a3b2c06c88f3692f671d91058df5d5c8f702785989c476762c97a1f480fe93da3602a750f62c0ee9bbab5a4ae1c7a4219e84dbc327529efe07ed3ec82dce77345a5c0eb368b138839946732056b6a908dbf5f05c"]}}, diff --git a/txscript/data/taproot-ref/55c9ce0b7ccbe8ff676abebe7761bee66f38e3bc b/txscript/data/taproot-ref/55c9ce0b7ccbe8ff676abebe7761bee66f38e3bc new file mode 100644 index 0000000000..c3babe95c7 --- /dev/null +++ b/txscript/data/taproot-ref/55c9ce0b7ccbe8ff676abebe7761bee66f38e3bc @@ -0,0 +1 @@ +{"tx": "17d518f302dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5800000000e32f0abb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48400000000644a2ed2022f4f5700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc20000000", "prevouts": ["c7ec230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b9703500000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f0", "final": true, "success": {"scriptSig": "", "witness": ["5d8de6d1280b5ba87a728e458102f7fec26e020d165021a26baf894cd1424d2bd56e5d09829f99a16dc6a7595e066c8cf463c0d412ff743f029baef8c146a30381"]}, "failure": {"scriptSig": "", "witness": ["48b8dbb88cb5aae0fe5e459a51a3b95dfe7e8cde85b9216a0ea4179884fe651e485ffb8a79463a62a77755ccb5b66f5c38a60dd7564181ca048303089316f134f0"]}}, diff --git a/txscript/data/taproot-ref/55cabf94b48b77fc7b0a87efd62377c6a44cfd3d b/txscript/data/taproot-ref/55cabf94b48b77fc7b0a87efd62377c6a44cfd3d new file mode 100644 index 0000000000..4542cd02b5 --- /dev/null +++ b/txscript/data/taproot-ref/55cabf94b48b77fc7b0a87efd62377c6a44cfd3d @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca500000000141df85c01b8e702000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48727030000", "prevouts": ["6eeb510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_45", "final": true, "success": {"scriptSig": "", "witness": ["b73e5396a76e0c5e3fc6e042edaa12f5a8a8be428d19c023c1afa7b5c9d55f14e0276261e40dd940704155e3015fb3ba68c2f62369c387a53e54c4875f79bb2901"]}, "failure": {"scriptSig": "", "witness": ["792486511c28a806d5c3b5d66dbc15d733e09e541e899e41fa1a7d986e85fe3ec8150262372dc884c8e357af5444fc592b1886497edb697e77b0ee53e892d53b45"]}}, diff --git a/txscript/data/taproot-ref/55db8d546fc7e337dd899c328c82a60b6102a7b5 b/txscript/data/taproot-ref/55db8d546fc7e337dd899c328c82a60b6102a7b5 new file mode 100644 index 0000000000..723b25901e --- /dev/null +++ b/txscript/data/taproot-ref/55db8d546fc7e337dd899c328c82a60b6102a7b5 @@ -0,0 +1 @@ +{"tx": "3f83490e02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf29010000004679f882dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7001000000ded352b204041c8c00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487ae53ff24", "prevouts": ["18d9660000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "dbd8260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f3", "final": true, "success": {"scriptSig": "", "witness": ["48de2e16b4bcaf95bd071a9832c7ce33fee167fcd6292e5eb8c6155a84a992ed9a88955a56979512b2ff872c353f5f3503e5954e524a2442f7b2db2e1cfb3cca"]}, "failure": {"scriptSig": "", "witness": ["61d9ec5c3d0de53d1eb1d56733a4abd08e9a31f376436e54b83b5a0cec7eaa03bd94cb128f620fd8cc43e0d9359d8d68f9e7bee462abb2999d6467e21fc806f9f3"]}}, diff --git a/txscript/data/taproot-ref/55f99e2d68ee85b75133f78cb948a5b7466cb4ea b/txscript/data/taproot-ref/55f99e2d68ee85b75133f78cb948a5b7466cb4ea new file mode 100644 index 0000000000..3de6eb57cd --- /dev/null +++ b/txscript/data/taproot-ref/55f99e2d68ee85b75133f78cb948a5b7466cb4ea @@ -0,0 +1 @@ +{"tx": "b07ccdb3028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40e02000000ac2245c68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48c0000000092334be801f08a5b000000000017a914719f78084af863e000acd618ba76df979722368987818e012b", "prevouts": ["35c53600000000001658142540f27e90740933c99d4f17ab2dfc6c82951cfb", "1c5737000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e868", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361b3d4b3c1d12642e7710cbf88d90f6ee341056f129c03c206ce123214db4cfdc886d39c7fd191823f2d71d70dbb2b614916cf5220a36a0556ea0e320955e8896770b862ef93acb6091cb4ff8ef135b3065b278142aa4adab757f952a626e2b26c80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93621ca571378a3ebc1b3d88db0fcc1864f60e2af1eb346e9dd3894589a6bf4e26ad39fd96f2153f8e279dd396423519f362f93616cb37cbc9b2f05e3e7bc75ada5276a8166e5256dc9010e53101dfdb6dbd4fafdb1e785ffcbffe7e4bfe923fbf99aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}}, diff --git a/txscript/data/taproot-ref/55faab0c69903138a86beca8e6ebc3e7a2010e0b b/txscript/data/taproot-ref/55faab0c69903138a86beca8e6ebc3e7a2010e0b new file mode 100644 index 0000000000..ec143a72a4 --- /dev/null +++ b/txscript/data/taproot-ref/55faab0c69903138a86beca8e6ebc3e7a2010e0b @@ -0,0 +1 @@ +{"tx": "85324522028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47f01000000b61021addff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4e000000006b4b3e8303a56079000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7cfcfce3d", "prevouts": ["153b330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9946480000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00639968", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082c0b317c85b837bc971133c463a5a02b3e438f62c623f33a660d87550a4209620af95302e7a08635545e6c64d05a20a7ff60718981ac8a997d809f6391d7b2d9241e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bda2b2a0c2215fd01cbae6f9632c297c3acc6ad2e282578e936cd31657d5fa84d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51379b42341ec85aaea9ba53764a308ad79e21ba1c6bfeef93296a10f4c0e568eb3c50effc4608d2c714b1f589c510b82e2cb4bd2fb333954004903b4f08f38a79"]}}, diff --git a/txscript/data/taproot-ref/55fc38b7d593fc118d407fcbd2ed49e3ea890734 b/txscript/data/taproot-ref/55fc38b7d593fc118d407fcbd2ed49e3ea890734 new file mode 100644 index 0000000000..068cc4d799 --- /dev/null +++ b/txscript/data/taproot-ref/55fc38b7d593fc118d407fcbd2ed49e3ea890734 @@ -0,0 +1 @@ +{"tx": "bf8398af01dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0300000000c148ada60492d14700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478711010000", "prevouts": ["cb8e4900000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09028cea88127acc9c3f2a83d257282d4867ac82e62fdd8fc2f26c7f55dde4b46178da6f9b7eeea9ed1a4075a058f3396c3c513042dccf6736926551eb4ec3cee4dd100810d8ef6d792acc5011fd662d8bc2f0fe53886c81144927f8192ed8de3b9abef690be184e86fb019e00f9a8bd5bca1553246e19f4ed6af61e58dbcc8447e7117521241c6c5cf4bb5d6edccf9e2bad1d3551b8d0f89e232a4ee684f80d27f58d173257551c40097c8b0bf7b307b58387fea6cc3365425788c6ff8ec43da3840fa9b2c2c534adb81c40df06ae5aa41c006ec9484d40801d6ffe871d2c95328f9cacfed0bd223f3118e6edd9d182aa038e1ca5f1dcf40ef73008d2fcb80064c56beea0991ea0bd8dc9c64040cabeba9fa63f3596ed60725d5083b15cf5ee10b4a75882777cd4af71795ac7a31563a091f242378afac315b06e421c31775fc30fddfa14a4ce0c16e968bd83d0c96e30071c4aa1c2a3e38fa9a42bd5a4de7e8780e29632699712ca95ae0d4ccd77963378046eea4e57d6e6b72cdbb4028fa07eb69fc662eb13855b2a2c969678c7caf78e69da9e996717decac9b6883e0d619b56ef3fa13fd82f42337e8acee185a31aa77903502eeda6c407874e9c6f8d5a3c62b75be4d57ce3b884924ac9787b18b9a6b0bb89d323c8092846413f09ae47dfc53a11b403a406c01e068b7e5d611430998b35e802ba1b42fb60f8f5fd0a3d95e4b6b28e173199cd0dbc75", "e27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366faa7d7d2440a55ec7d139a8964ddbb0355a79c57a8fc16181baf4c33ea43944de3dcad145b88b360fb9f51ed5363f34910a171e61f360dd6bdf047d4a1b93cb212021a26ea5e00fb993aa3d0fc1bd1e431f365db69035b8e4625845fc9b697c"]}, "failure": {"scriptSig": "", "witness": ["4d09025c589ef9398582c77991c45f56b5efc2fde50176ec588911636689f5d35522a0cb2104aad106d95202f371942be228197ef76d1b1ac32326f46caeea72b112cc7951803ebf5c711f2b7ae2dc3afb9db78a0742bb94326e2d74fd1b486d2cc60985f58f08420f0bc817014f7efb29c855f866bba320faea04a141a1e6337f1e58ad3253f466636a6e676f3dee84dcdcdfdb7bbd3d58be695e00961a8278a0f90383022396612925667479b4f45afc334a7a779461532a0c18bbe56bfbf6bdfd8da8aa2c3dd2a110e309a82aa347fc265ac0eee3216dd5ddfb255aacdd718685792db52995836f972461388537361de78848a9233bd94fb3f80c0197c2d2766c5aa1ef8894b3dc7a646a92e213af4431636394334e808e06b32886a68d7c2883a14eabd698a6efeb114766ba8d80d4bc1b2155135926ae23177afde428ec673e88fea8d1ae48d9cf68d97e649090a0d6e577357d0f859095304d0c49afa3288ee6148e6c0578f9d2949bdf72495eddadb407c26724ec5c9738e5bb9f6dd39da44f65068ea14592ed127304fdb0ff9c840d16252b9ac72433271f8a7e06d63524e54136b2f11556b7c3f019ab813eac9962a12b7cd305d650221b0a8dfc2c8fb195e66a8a79d1229f31d7e233debe0a284d2ae4cf26b45cd262870d9ef6487961639ea15bad889d136b10cd8c1ee5090f3f2f7a35ecef5c9377cd66ed751a8b12cd20678db29f7c9d1d1d75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694061612a85b22860c670ea907f0f210751112fdd19efc00b4f6773b6f7a9cd1d6719dae808d80c72548faab257df36cf98b115c53ace18df08612b967e5347aeebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7acec7827d9bc9e4e8e39cc141cf7690ea6843d6b50eda1fc8d5571fb149b2aabab"]}}, diff --git a/txscript/data/taproot-ref/56397a2ccd392deb6d3ed52e0a065fdde579e9d6 b/txscript/data/taproot-ref/56397a2ccd392deb6d3ed52e0a065fdde579e9d6 new file mode 100644 index 0000000000..2d9973ff88 --- /dev/null +++ b/txscript/data/taproot-ref/56397a2ccd392deb6d3ed52e0a065fdde579e9d6 @@ -0,0 +1 @@ +{"tx": "69e9ad9d02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6600000000c9d7deda60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f001000000c805afc401196533000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f871b91163a", "prevouts": ["17806000000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "eed7110000000000225120934cc30b71223b04aa2af20106e445bb93ef4a67adba137dbea8fd26e6a0b3fd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063fa68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb462b588f53b8753752456cb241f753d144ff0679dfcac60637407bf69aac4dc17f8b8afd7beb88d43ca6c6d2d58dc9425172bd95ccf582b2eeeba83616a9d27d33bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363d196519084bd9e912011a72f2be62635ef4baff1f9b0d2c0319da63472fdda3b9350299288462116e81ad139d1cf2552ad17a94ea609f697964ec86e4a0e9d9319d91594da7fa35d5ac76c3396b108bc28aa6233c389d8680e4f0461963fe656f5053dc49cb92d20c30fe5ab09c589302aa9886b9c794d18405aff33121a169"]}}, diff --git a/txscript/data/taproot-ref/56567e4be5618770bb97f61b1487c7d47cf8192c b/txscript/data/taproot-ref/56567e4be5618770bb97f61b1487c7d47cf8192c new file mode 100644 index 0000000000..a870acd8ed --- /dev/null +++ b/txscript/data/taproot-ref/56567e4be5618770bb97f61b1487c7d47cf8192c @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45b010000002378e255bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2701000000bcdd8d74044f8ea9000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478740000000", "prevouts": ["780d3e000000000017a91481d4142ddc5ce7a3de4047bd48b623419b5bc45e87", "ab0c6d0000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8dc8c5662064e2d9613ba0f54feafa13b4a8d810a28ca520b1cd1b9628c3c1add15eb41ce20b61903eca7e2f7903a7c5f76d50ccbb22a22a302188dbad2e46b28"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c1510f921748ad83649efcc17e75d7082e73dd380974088ab927571dfaea01cef9a48fcabec25982850a496e19df71982d596f167265e15d1ec282fb30074b91cb891527dccd7fe22077390053ac1c45ab6e7110116df1a30c9559411f432f5"]}}, diff --git a/txscript/data/taproot-ref/5658a8d8fb388e7c7e5f7c7fc8630d3de961b676 b/txscript/data/taproot-ref/5658a8d8fb388e7c7e5f7c7fc8630d3de961b676 new file mode 100644 index 0000000000..5405105a71 --- /dev/null +++ b/txscript/data/taproot-ref/5658a8d8fb388e7c7e5f7c7fc8630d3de961b676 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc4010000002b6191afdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21020000009884a17cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1c000000007c4b09c60226af4401000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd3000000", "prevouts": ["c299750000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "05cc5a000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "080976000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["30450221009ae58dd691f67621cb44ce3cf3e790a1490280b8d2f21b65954650b7e6ed671602201d17c98e967b79705ef30c47f115bf0d25c4d5c5e493aa026fdb46ca4725b76681", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["3045022100bf491b28ced4492824c5b34d7c4ea5a41dad5c9b629e549488b7dc11502ecad102207e6a2993212e567a96be68ba1a262b405cd70a2986eee40edd63104cb1339b8781", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/5687a5e9c47486c4d2f24f74e09c95a9b9139145 b/txscript/data/taproot-ref/5687a5e9c47486c4d2f24f74e09c95a9b9139145 new file mode 100644 index 0000000000..77e0f671f5 --- /dev/null +++ b/txscript/data/taproot-ref/5687a5e9c47486c4d2f24f74e09c95a9b9139145 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0201000000a5902247dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b260000000016a000b7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0100000000de383c3702a0e7a50000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4879304df5c", "prevouts": ["f2295f0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544", "0b62230000000000235f212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "bbe224000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["b8812ae4910f95e260c84c81cda42194f3c09e2266ea82252a16054e3bbcb7d4240112039594c42e43c0670591365309d35ebe3c03b5fc9f3695067e9afe9545", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/56c988fc520dc9a5bafa28ad83eb0e972fd70567 b/txscript/data/taproot-ref/56c988fc520dc9a5bafa28ad83eb0e972fd70567 new file mode 100644 index 0000000000..9fd3c8b0a0 --- /dev/null +++ b/txscript/data/taproot-ref/56c988fc520dc9a5bafa28ad83eb0e972fd70567 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bec010000001d0a2dc2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf00100000010fb28d503d0fc6b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac4d020000", "prevouts": ["5d3d220000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "c7244c00000000002252202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/bitflippubkey", "final": true, "success": {"scriptSig": "", "witness": ["a95f4b2151ef091df4c7d19cb4998a3268094cd7f4dbd6d056fa9164170de7c051d60afdd8a370783bed723d081aadd37629557316957f8141a2102bb99624b8", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}, "failure": {"scriptSig": "", "witness": ["a95f4b2151ef091df4c7d19cb4998a3268094cd7f4dbd6d056fa9164170de7c051d60afdd8a370783bed723d081aadd37629557316957f8141a2102bb99624b8", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5962d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}}, diff --git a/txscript/data/taproot-ref/56cc448ba82bed7220a831c4b05eabed0406386b b/txscript/data/taproot-ref/56cc448ba82bed7220a831c4b05eabed0406386b new file mode 100644 index 0000000000..95e88576a2 --- /dev/null +++ b/txscript/data/taproot-ref/56cc448ba82bed7220a831c4b05eabed0406386b @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2000000000868a0dee04630f6000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48766030000", "prevouts": ["93c66200000000002351212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["738bdbe9cd1a5424b7d83bd7a5e298273445228a286a1ad1a0ab62ab3a890fc0260cccb593eaa605fc1be61b5642b639897bc50cbbf04051dd29a71273e862b6", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/56ed4007baeecebd4a8905063055ace47704a0dc b/txscript/data/taproot-ref/56ed4007baeecebd4a8905063055ace47704a0dc new file mode 100644 index 0000000000..a8f7b72011 --- /dev/null +++ b/txscript/data/taproot-ref/56ed4007baeecebd4a8905063055ace47704a0dc @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f02000000edc4c2a1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7d00000000b6e37ef8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b970000000032ac10e903965dd000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c020353f", "prevouts": ["db0b40000000000017a9147e06846ce22cd5e23f7e03391c0538498e0e18ed87", "234c6c00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "693f260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_8a", "final": true, "success": {"scriptSig": "", "witness": ["214ddaacf7c31cec6634b8d1be5bd63b8250f22ff1390f4c27302b3f77601c3840fec9785a32a74e006b3d902e6b237129e8fcc6fca01f4f93d0805bf659293402", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a52ae61876ee07852f630d8c736bb794b957e000bf42ae6d711136e967f78160e04a61022330c6b25b68162d5ab0e7f8874955632d96ec784dfeec31fde965868a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/56ff467c9c6b5e3079baa559955ba107d89d77fc b/txscript/data/taproot-ref/56ff467c9c6b5e3079baa559955ba107d89d77fc new file mode 100644 index 0000000000..42ae461223 --- /dev/null +++ b/txscript/data/taproot-ref/56ff467c9c6b5e3079baa559955ba107d89d77fc @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d00100000061bcd71c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46200000000492c8d5abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfde0000000026f8a34302b303e60000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87ab000000", "prevouts": ["6f8234000000000021551f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "b983310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c2d5810000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e5", "final": true, "success": {"scriptSig": "", "witness": ["206fbc11d8471d1c21e61bb46107d8d1f4cf55982ff22f820131fb7f947746579cadb292d2426d0726e5451f0e79d620529e7eeee66f9b910df7ab2139b62c2f83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["67e0abac7e67c6ac12d86c06d9d916cfbbfaa3dc1220a5d266fb61dc7404582397859450a4aa65dddfc91ec49b34c57641f6c54a31e407eb362c6bbbd0a53315e5", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/570fb69de8afa341b54dd79455b6d21085c0334f b/txscript/data/taproot-ref/570fb69de8afa341b54dd79455b6d21085c0334f new file mode 100644 index 0000000000..8b848f797e --- /dev/null +++ b/txscript/data/taproot-ref/570fb69de8afa341b54dd79455b6d21085c0334f @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41102000000869367a3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cef010000005d951084021acb7a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2b040000", "prevouts": ["86fc330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8835490000000000225120f42b54ceee5422b98931ba4e4259b1fe0b973d9efeacc7f6f710ee118b027bcc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db6f858bcb140df281d7bcf64cb458d8641f6a6ea76b9d437d19719ea520e9d2"]}, "failure": {"scriptSig": "", "witness": ["6a65616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/570fc65b0c81c1473fc82b8545f5ae6efeb839ff b/txscript/data/taproot-ref/570fc65b0c81c1473fc82b8545f5ae6efeb839ff new file mode 100644 index 0000000000..9cdff3eeb8 --- /dev/null +++ b/txscript/data/taproot-ref/570fc65b0c81c1473fc82b8545f5ae6efeb839ff @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c900000000e4d8689fdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2601000000013a04e50458d53300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac3703122b", "prevouts": ["ff541200000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "f15c240000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d74c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366581f7b0ca6f1aed206970c0804a234f1a44041591cfc91f27f0238489d6aa9aaffae472ebffc4152ddce3f20794b01737e96becc2bb4a1a296a47c8ec0d29af569af0f9e86656db21fe5e74d4bdcdfc2cda5437bccaf9e3d568ba1282fc608d76e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f0f1548d1d073f6e5b14220ad2361e8ef5d38bb11452790f522d55796a8a82b3d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514c1a4ef98c473095d2df256e4c96a081ff076f8ed25b9a6c5f4dacfc5de1b1d157a61376c510bdd1fc860151a3b261939fa407ec1a2d0490cf2efc4278abc783"]}}, diff --git a/txscript/data/taproot-ref/57267f8aca1eeab5fdc28ec5f2cdbd6ce0d150ae b/txscript/data/taproot-ref/57267f8aca1eeab5fdc28ec5f2cdbd6ce0d150ae new file mode 100644 index 0000000000..fde1d631ce --- /dev/null +++ b/txscript/data/taproot-ref/57267f8aca1eeab5fdc28ec5f2cdbd6ce0d150ae @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9301000000b42ed6a28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d90000000081fe60ac049d5a9100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac47d04324", "prevouts": ["749a5a000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e", "d2c139000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100f3c2b9d005defc4d295be85b11319da089ffa512fcf591f4803c2232dddaa1330220615e3f019f504d42bf605cacf388b06c77d9f78ac76dd3299e3e0aa2724ec5d782", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["304402202d315cbd08a6bde5a6c500c965930630db122bbae9679d6d35450b128490a32c02202891c280ebda5a3fa930a72ea6ca1f940fc1c59cd690b89523cffce410bddd0a82", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/572c410d27df3156ea85e726a966af51c9cadf8f b/txscript/data/taproot-ref/572c410d27df3156ea85e726a966af51c9cadf8f new file mode 100644 index 0000000000..7f9042b2a0 --- /dev/null +++ b/txscript/data/taproot-ref/572c410d27df3156ea85e726a966af51c9cadf8f @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccd01000000309951c10172eb4000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7ca010000", "prevouts": ["0b135b000000000017a91468f63610c45a6790781558e4d5ce83e16e8f3f3b87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2352212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["0eb4b3e6ef96cf190e4d3359e19dad29fc52872294cbd7ae7630dd5a95d2abfdb7b008f9acdbba52783b9bc8c4a580b3e3e16f383c551b11d02a41f07a84aa76"]}}, diff --git a/txscript/data/taproot-ref/576476370370b5501ea6a61ac033110ea83ed7c6 b/txscript/data/taproot-ref/576476370370b5501ea6a61ac033110ea83ed7c6 new file mode 100644 index 0000000000..61cd4f07dd --- /dev/null +++ b/txscript/data/taproot-ref/576476370370b5501ea6a61ac033110ea83ed7c6 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe701000000566f672760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706e01000000333580ee0250697b00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb141a65f", "prevouts": ["7df96d000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "c049100000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cebe1805b4dd002a9656fd180b0893baf3654597c23b46cc67f3675a294fa085bbd17872a9d61e54e96dfef681da77b5399be78aec05b527019b8e812e967c33a95f177959a3d24a94a797d1e607e5550897d4e95d12a52323e6e8eeeab3383c"]}, "failure": {"scriptSig": "", "witness": ["4c52c4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9cbacfb9ac71e83a18047da934e295451257fe751eace0e6de3d0887f96ea29ca92fb159a7f16850def0f13a878cd04653ddced5aa57281dcbf7f9041e8663ebbd17872a9d61e54e96dfef681da77b5399be78aec05b527019b8e812e967c33a95f177959a3d24a94a797d1e607e5550897d4e95d12a52323e6e8eeeab3383c"]}}, diff --git a/txscript/data/taproot-ref/57731bef67046b96aa1a3f92ffbb41851e7b3353 b/txscript/data/taproot-ref/57731bef67046b96aa1a3f92ffbb41851e7b3353 new file mode 100644 index 0000000000..20ebae181a --- /dev/null +++ b/txscript/data/taproot-ref/57731bef67046b96aa1a3f92ffbb41851e7b3353 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c850000000050957517dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce601000000ac49e6a1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5101000000703ea34b033cef1101000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a641020000", "prevouts": ["59c348000000000017a914ff6a0b1cf86e786bc6de2387f1927f71fd08cd0c87", "fabd5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a3736d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_2a", "final": true, "success": {"scriptSig": "", "witness": ["962e277db60afc12b4bb4a72a705ce113f7bec80cbda252c3139ef94efa698dbe8d022a82d8b47ac21e1750b158786f802e4ab047f0c7940f0aadc541c95d8eb03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["e4fb10238c3981b649883f9f2e22b27fc6470b306ad69b2f4b82b7ec4f763c1c731063b92a47e8fca85eea1b938bfdb8857d6bbefedeadeda7aa3805531a34572a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5777068b6f7170fa6a505e9144aa3f6fc8625b74 b/txscript/data/taproot-ref/5777068b6f7170fa6a505e9144aa3f6fc8625b74 new file mode 100644 index 0000000000..19e3c122bb --- /dev/null +++ b/txscript/data/taproot-ref/5777068b6f7170fa6a505e9144aa3f6fc8625b74 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cba0000000025e7d69ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5201000000d3af49b860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701202000000fc825ac201084a89000000000017a914719f78084af863e000acd618ba76df979722368987398c0a2f", "prevouts": ["33da480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "65a5590000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "064711000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367952003d040c7265d30648e0fedf45af2112bf795f8359b3d6f1b95f924fe55e4f4a9cbf846248908cc3621c28de38a375d9ce3ef1fd8ded826daa29f51353851cafc3da456d473afb79353f7068dc1822b24dbf9d7eaef6a0c8c9b611b05e979feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b6ddcef20c10c61d9e21e2293389fb4d83401974c63955ae345dea7dfe41530ea78a04935edfb84e1b4b71380d58e01ed379cbb21cec8f8440ec0fbfce597ab8cd941a6bc152cbea0496b075d4b2611b435301778200e60e8b4147cd93749673"]}}, diff --git a/txscript/data/taproot-ref/578701a27b2e9321384f3e516f48fe5d2ebfad6d b/txscript/data/taproot-ref/578701a27b2e9321384f3e516f48fe5d2ebfad6d new file mode 100644 index 0000000000..be5941d138 --- /dev/null +++ b/txscript/data/taproot-ref/578701a27b2e9321384f3e516f48fe5d2ebfad6d @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2a01000000f6816db38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c467000000004c8c3ed5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa300000000092b0a9b015b3c530000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7962ad43c56", "prevouts": ["4e8f5e00000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "562e3e00000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "81d36500000000002251206ee7f50dd8b37aeb440050df10921bea288340730b764e02d5c3920c65efa447"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09028896e117af595dd9705c395be3304524f3326fb3478abb985ccccc07e8370b2e9c7e98ad8a1878c633df96638442506ae5a3eea8e092312b13480b01c654c634759653fe89282cf2b362f01b518c6fb6c1de8551ed14cb660924801ae88516a329320a5e18d8db90a660e2d775f9053c47d70815280ce3b323f09130b3a73597be2688fdac0a090647991836c98a037df01d7111fcdc2ce22b558df5cc89b339d18fc20a091dd22154159983edcd75e7a42a9b9e62f5cfa1050782a6766a4cceb16ab80fb42980559573d70c369471e307053340470e8c8c0055eb17c5617663687241fa9babe46a2865462f480c713e147302df7c28f551209bf926ce44b94054d2dbd11aa3ad8fdeda79b22fd2e8bf3e93de154fcfe21d20ca722d0aa58abfc596f5f11456ec9ac8f43b1453ff5091a32ba5fcdc218193a21eee610e998595426b582c8e94419de2792645568a5e80ba2294ed6bfafe10010919f9a75aa6093a1c3e467ed96a15c10c8a5bc6041d637d135249e664a077a73ef48fc61e8807d3276695576958046ce3d102482bb310a86886b42e0bf3b77aa9ad211c4f12e44437b152d30bf9930c2a7dc2ee2914f28865f1e811de1caa10c047f2fd5b0bdf2347fe086177c342b78cd1cffd36cffe9e10bcc0f5a3e6d60745b0f18d647843dc8161ab35d9eafb19babce364a41081b0c25a5267e79fc3f52598302d81df81853cfc46e37458596a75", "047d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3af26a389e120e94680e27477caee46163f2ffed4e6499d7dcb61a15b1d76a7c8460181b685601280cbfaae0e90478ea5ae6fea73a2d03f5a79a14a3e0c6d503"]}, "failure": {"scriptSig": "", "witness": ["4d0902ef9653cd2c33b2efda403841c7fb73246623be34cb46bd0aaced5451f10c6fbe9d50dd7277c2b035e2430dcda8810b0e8584ad371be4ebe16d6f002310bbebe35dbd251f91d17738ec0385d7dc4142edf110374e4434eed04175a82b399a61fe4fd84868f26a4a555c4a850da174f16a36ffcb3631da7a6aa146287e4504ec22f5518f4415f35cfa3338a5e9aea294bf7f1803433042442d5e9fe904f77a6027dfb02fdefeed29c12d5f71fa089a144aab28e710cc7a9a069d0528dd4df4291c63b1c77d16a6eeba92bfc6e73fe3713be4b38a268e38b55c6df93b02bd46f46146361e2db556a3d63530d87d38c5b517a78324133e226909a0e891811576e119301efaee047375cc6194560406e3a406ff43e4d36a277302ed308fd4dc9e8bb6d6736d632decf24ab5459404dd34cd67d356dcf5fa84c0ae2d18cc0bd54be2c1462ed825a51501f26276d1f5116bc838b15692bd42770430aeb126a35e7ad8e9b526e43b7c3d672bcac4b0cd8d4e2df4e0f4218a9b37d45804cda80d200e82ae81836957da821cef7a25c0701d97500bc42888ee8e67b1f186fca6734e3460c51c0c2a57ec5fb2508c7899fdfa0088b60dbd4905e6582bae7514231ef7ddb9edc161599a7bd72bc55d434b2944612f1cdaa47d57e8d9ef192f547d7b7cdb2afdb321f940f3d1d2ca41b4c9ea284806874a039fee9d7e5083986d301c8177d13b9320477bd4cdb0214775", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93616320590b22355b457fc3fa4c4fda2fbc5888b55a29cd6e30112b029eeab3dad9de556ac6994112f2dbe51e2f18419f84f5e3afde46d5119f13558b672a3f6371a343680beaae3fbea53ecc49afe7cbe880992a117d636f336d7d159be7b446d"]}}, diff --git a/txscript/data/taproot-ref/57ba07044f687929674d01d0c501e408072f02f8 b/txscript/data/taproot-ref/57ba07044f687929674d01d0c501e408072f02f8 new file mode 100644 index 0000000000..413e588377 --- /dev/null +++ b/txscript/data/taproot-ref/57ba07044f687929674d01d0c501e408072f02f8 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd800000000a44e63dd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bd00000000160a5735025a6d7a000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787fd27fe2e", "prevouts": ["f38748000000000017a914b0716f1bec91d4758ee97d9063c9da884dd2ba5287", "ebc33300000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "967d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e889b1afbd82754ccbdb229e33ad6472305abc54dae2fa9ac3a68b58b93ca8c8390ad15d5ff3e747c4643a2e7779e2cae74c1db700bc0de7d47935e7ffa6ea968f"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936393d3666f153f5444bbde9f12a33ca18bffeb96af6c3b3812e1be180585532ecbf86d7708a8015fd8c392d5dfda539be3c55b3d42b83ba5bec57bef080407e280ad15d5ff3e747c4643a2e7779e2cae74c1db700bc0de7d47935e7ffa6ea968f"]}}, diff --git a/txscript/data/taproot-ref/57e2edb6bce9815f7e92a1cacf2c42a1d8a5ed21 b/txscript/data/taproot-ref/57e2edb6bce9815f7e92a1cacf2c42a1d8a5ed21 new file mode 100644 index 0000000000..ab0a09d92c --- /dev/null +++ b/txscript/data/taproot-ref/57e2edb6bce9815f7e92a1cacf2c42a1d8a5ed21 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c1010000006ac7384fbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1100000000d73802e703a25eb7000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787b7000000", "prevouts": ["edca3c000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a", "b02b7d0000000000225120dbe65d5ea7d032bcaa5c118e4e1c91ea90d9063ab0b7377212d71cac34e27d50"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "247d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936274b6042ebb9d5348c83f5ca8de85b1be0d48f115321b174dec002a2085b4af312b5d836754160f4cb099c4d8b267e29847dad01b12a09dec3875f376ae126ea3506420e788c3ffd3d8d88ddb9154e82106737a8dd2b5d0940daf68f275cd0d7"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936195e60e91131137c7fc5ada885ec733e6b607a015084b0ea1ecbb763e672f30dbda2774425301130c379b9a863bac2b926fc4ec0dd6af03d15dab43b60e3a64c440784f6f41cc1ae323b623cf5dcb000da45020704fab66b6b5f2ff7d67a93a3"]}}, diff --git a/txscript/data/taproot-ref/580742d9b18b0603cb29360f8e7cbfef479c00c6 b/txscript/data/taproot-ref/580742d9b18b0603cb29360f8e7cbfef479c00c6 new file mode 100644 index 0000000000..9cb967cdf1 --- /dev/null +++ b/txscript/data/taproot-ref/580742d9b18b0603cb29360f8e7cbfef479c00c6 @@ -0,0 +1 @@ +{"tx": "2cdaf2c70260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127012010000003b999eed60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705901000000d23472a40318961e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5f000000", "prevouts": ["05ce0e0000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "bd5f1100000000001651142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["3577a9f5e5afd7dec8794ec90f5b30191dc3d1d03aff482e4b3dd0ad46069d3c1df5ffe05a93b0914354000c5013e139352c853c670c19dfdbe29a79b6a88351", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/5876822a1e4504b3dcd7a3ddd10ca0dafc4c9ce7 b/txscript/data/taproot-ref/5876822a1e4504b3dcd7a3ddd10ca0dafc4c9ce7 new file mode 100644 index 0000000000..37b0b70e6d --- /dev/null +++ b/txscript/data/taproot-ref/5876822a1e4504b3dcd7a3ddd10ca0dafc4c9ce7 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8d000000009628e1ab8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f10100000041654ba460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c200000000352cd7d102283e7a00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7eca46228", "prevouts": ["be4828000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "99de42000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "344811000000000017a914d574841bde7bf0817694c799002118e85acf040e87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_83", "final": true, "success": {"scriptSig": "", "witness": ["67b122669ea9d7a03ac499c300412e9a4808c17efdf9b008efa5cae7ffb3525adfe5f7840f42178b593fba90e1011296da951f40f07e6762457d4c69363de8f883"]}, "failure": {"scriptSig": "", "witness": ["0e27f11d7f93665a2300ffb2feac5bf9c0d8119a059919ac703db6df7ba006cf0adebe580bbc4318c6ccc92082edb6d8c928d4d1b4cae47a46e2abbbfe78479283"]}}, diff --git a/txscript/data/taproot-ref/58d98ae03e7b63b61749dae272899a7f41a89c30 b/txscript/data/taproot-ref/58d98ae03e7b63b61749dae272899a7f41a89c30 new file mode 100644 index 0000000000..77b1651781 --- /dev/null +++ b/txscript/data/taproot-ref/58d98ae03e7b63b61749dae272899a7f41a89c30 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf160200000050c0ec8560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705d000000008597bb100331928b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc94010000", "prevouts": ["f8447f00000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7", "18440f0000000000225120d1655db6fcb356decaccee2a8cc0c67c6e760726bed93f7ed1bf145bc7c6bd94"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902492faceabd608f860a47f22399d1864fe7d0d4ce3321cb876e2535b169e40c0f6893bce11d6feae29f33aeb33f16fb8a0c72d668d8817fbdf1339dd2b775ac0732f396358fe4d6117ebd38e068a3bb65c59175080482645e3daf525dd6af113075391da98059e95a23b704408ce4d3f781f311b82e669e9cfe3e07b3d8cd80c701be93d88f40bf336f2cac12691c3bdeac7e4337ce5a2eb3b8643ca096ac1835b1a06eef09b5aa00529246d5bb4ef7a170e9b32f1aee537b504d852f2df25efec7ff5dd543575b31e6d79f037adcc552536a9c122672dcd3cb3904a011a28cfefbe750bd7464748a217129cdd431d407d7333dc7dbac08daa00e073faa1cbe500a0a814fbc4f7812b8b22d58b6d133844717a4044bb8b1d950b40c34c9c095a290524c523c574957c878618e80fd77d4763771faf38b5fa5aae8e5ed1e2842915151d5b96d411dc06cf7a012af2af502020d5e42a5005cfaa26d21b8b6755b9e2a5d4215b4ded5ccc91869a3390c16bc736e283037c0d06f7a1f71a55f886ec679b2aeb88140d6ecd79865cc22865cc45e3ac021878ea9f32594a144219dfb8df3e9f4492c64daea879dbc9abfda230b1b1d02e64e516c30f6eacb0c15f35fb352adf9518c85371123fb8be9e5331b07ec4477f28cc743ff4a32a9b286a8bc5f6208cf77aed995197030de4740419f634268bc877a418ab0b9f20631daca7e06470c65a3868885809375", "b37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ebec8f444f9538a00b5e533aa370349d7181cba703021b72fe611d481b359a8e62055c347ba5402321504576f6c37d0c6cb1d044ee75df535bc9eec0560634a7"]}, "failure": {"scriptSig": "", "witness": ["4d090272468123f56270b4333f287cd1502515beab062f9e033575e93fcb2d4c5b2b60531b61e57d70d57171d03defe8b2385399ada175c6d235b79d6cc8281ed2116cdfb08261cc187de7185b5d6fae37c62585797544cc4e34d6945f5d04a3a9823960c6b55ea761237e10ccdeba6999731c218c5028dc51ee059acf495f31357d1f3a73058d87cbf6a2232d0b942f9b34388893dfcdaa1d38dc42a32c3c39d2443d8f5f7bac4ba8c3513115c73139bff8b02e8ff2e836b26b99312b4c689ae5d6872d6f8618c2d75a16b4b58d9292ddb7d6628bc5fedfab017ba5d03a8ea167f23e4b46c959282578ce472326f36b43a369294daeff4773aa42af1b2e54d07b438923d393d2c31146450f3634a211c9d8b4d1e8f52739d21e05ccc0b068d2182aea690bc46548dd0af9353e4f26fb7a1d839073cd66cabb352d9e5e40f035a99c0d6404bf430eebd59b900ea55a759bf7fb049f0c4845918710474168fa34e7f3f0239d6cae820434cc3377ca9bc5b199c9e149c37c89db262f7659f06dae8d9b26554f2c1b0bc51512411be4834599b825877108d495e4c640082f81f3b77c5fe68e1503b8ce987349d22f49613d934a02c06cfc98ebafb4d06854e87c7c28f3ee72b600c20f16c059fe266a349799ac0ff277743c3b4dd184d0f408e7a97881800e8667b6be3d218bc305a2e05f9eacbbf1b280e9088fe5c3d3f317727e332051083d4259ad2e0420f975", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936497c7e978e1ad8a50d6711ca68bc31cb28123919e82fa890ac36ad6e92fae3cd95b7d6bda25431cc8e02e54f2e1c95b50d23fb11d52c977ad7d2dfd588f90c1962055c347ba5402321504576f6c37d0c6cb1d044ee75df535bc9eec0560634a7"]}}, diff --git a/txscript/data/taproot-ref/58dd5844bf68fb5f47e929bf24c7d8dc2cab5791 b/txscript/data/taproot-ref/58dd5844bf68fb5f47e929bf24c7d8dc2cab5791 new file mode 100644 index 0000000000..28bc3d1f69 --- /dev/null +++ b/txscript/data/taproot-ref/58dd5844bf68fb5f47e929bf24c7d8dc2cab5791 @@ -0,0 +1 @@ +{"tx": "561ea52603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6001000000363305b7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd501000000b8f01b8d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c442010000002b7372e904bd41b000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748703000000", "prevouts": ["f0d7250000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "3f614c00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "cdc840000000000017a9148462ed29696925d7688e1db8e76ef9e6667f05b287"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d74c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366581f7b0ca6f1aed206970c0804a234f1a44041591cfc91f27f0238489d6aa9aaffae472ebffc4152ddce3f20794b01737e96becc2bb4a1a296a47c8ec0d29af569af0f9e86656db21fe5e74d4bdcdfc2cda5437bccaf9e3d568ba1282fc608d76e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}, "failure": {"scriptSig": "", "witness": ["4c52d7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369fb2550e1ed51643baef309f81b6f22207378bdcce142874e2eadbef60c073106e55e6cc099b3fd5cca65d40087200ff064f8f598dc371f61f8d957b472ffb5414746b6cdbbdbe747c087a2d99e7432ddfa1db1d7a6445e7dea3810e7475536557a61376c510bdd1fc860151a3b261939fa407ec1a2d0490cf2efc4278abc783"]}}, diff --git a/txscript/data/taproot-ref/58e9cc8b18e2ee0f4ef6cfa6222d9ba9c4e6999e b/txscript/data/taproot-ref/58e9cc8b18e2ee0f4ef6cfa6222d9ba9c4e6999e new file mode 100644 index 0000000000..4b176e65eb --- /dev/null +++ b/txscript/data/taproot-ref/58e9cc8b18e2ee0f4ef6cfa6222d9ba9c4e6999e @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f801000000038e6fa4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c00010000005e6f05c7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6c00000000737b03c302ffe3c000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac65fd242d", "prevouts": ["a82c3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d5b75e0000000000225120733adac9df449b2595d1b217303cc00a8e3c5ae4d51e5f74120e9d2d90d81fcc", "1b492600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936399ceda524fd992fa8b819159764767086827a3dfffa524bc5c8b2e9b363d21d"]}, "failure": {"scriptSig": "", "witness": ["6a29616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/58f607b447f90cc1f1f8626ebec53c5173658a3b b/txscript/data/taproot-ref/58f607b447f90cc1f1f8626ebec53c5173658a3b new file mode 100644 index 0000000000..3a1fadbafa --- /dev/null +++ b/txscript/data/taproot-ref/58f607b447f90cc1f1f8626ebec53c5173658a3b @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706d010000001db75c8f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e70100000040edebc3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf710000000010bd48dc0265f7b6000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc3fbaa343", "prevouts": ["9930120000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156", "dded350000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "1558710000000000225120ba259941c99089f87a1bc06d64ef249f01ab7891d30169746f94b5a6d9357ae2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d6ac5d894ed28d75919bd671c475effc497e0fec610bb120a5968a6df92db1bec343041e033fdd8af2791d16d4589ccf5e4c305832c3fe2d018b69b91776d5506ed2b07bc22bef869f4f341e995eaf352a79c5308dc80f6bc11fe0290b3c756c33a13fab4d30d9e0f2ffeeb52ba377416ce2a4b6cb1da7c5d6782dc58c5c0fe4b0392c86968b3d41e618e714536594016ffeb97e7a3cd0e245e50d4a83cc7ab7c7de629459f517413aa269570dfe96d60a8549a65ff365354db55a744afc461058622ad905639c87dc671ba58c4dc142ae356b1ad1d31968f8b5572d0de8d96171fdaab97030d7f1e106882f7bc902bf546464513c0ec819378d0ed0cd402f69808df7a2a762240b0921a5a6568df602b9db9b7f4a6233d93c467b205dab9a65a4fc43397d707c4553478fa797b584eaf9e599f2fcd26b85f932323f9956ee4a83e4b54a9e9c213ebe43a07e7d17edd7b6a73f403cfbbfbaead28edcd230967e9c36e6aa8d407b46a9f98e6f4bd6fd3ef5d951d4611fb718c339de9bf2b24cdcd9ab34d3080d4dee7565a582e299dd929cbe9427556e09f7289449be9fb1b12ffa5f1cb2ce5b3e2a838c6cad91c9f8d1868810f1b30972c1a9309fecbc430d5dcb35763b3a531b5ee3807fd5f2c9f5dc3d928c87c3e9469468cbcd9012fe3571124fa773bbabc2ebe2c79912803928b8ac265541bb67d9aa3c372780e40d4e53046e5728836e876a1d75e1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c3ebc90e5160821628d2c57ea2f64a4b98877001fa79d5fa719df35ccb90b6abbde4683e2f88a3942929fc88a4cafb8eec09785ff7c9f0b883255a650cf557ca66ee26669afb6dac63e75f53b4cae6cf36ae7535fe99100c6f349ffc46155d224f44ecb3bab6b962a7ffa14a2ce082ec551943f33ce508b63a8ee30ee5e49264"]}, "failure": {"scriptSig": "", "witness": ["4d090210bd435cbb1095a0ddfe7f366a184eb919bc03ec09d806934b20371460792c481b9e3624e1a14ed647b3c91f038dfe216992b567551b0ea0ae5c5413abcae573bd17fb973caf63fbdd2150881e49ca546b2952049a8c51ffa82e10f3c7de1e97f3fc9804b120e948635395fd5ff49876cc1d68987c9fe54a00ade931e4df10da96e2dfffebfaf434bda1ae88197b849d01af37a6468dafa477cbe2d84d81277e1bb9f76292c88cf7d6bd2dcb695f132837adea0a4bcb73e0b664fa7f81d33413b01da5692d24126a4db72185b0abbd9e569ba29be720203bb9f8d22b257cd6fd4b730f8b8b4590d38fdba766eca943bcbfa4ea0436dd0ff16251f17c5b00ff06f754ed5d609fdbfb745574f501bd1db5a42c2d62249de0d91349d8543bcd1c55614ed9748aa3e45fd46ec63eea7d154ae39e269f327b2c73229eaef5fe05875bb6fd8b2cca373df01ea817840d196defd912b3dac69106fe6fdf5a5e66803325142433c7d536e22c2585bbb913a3306c88b0c961105dce7e703902a59352eb28a6eaf8e247b4b2047ddb93fd95d0f197f66a67b591657f14fdd82bcac761485ae0859dba8c6c1d4245251461a8edca37987037897e5096e8f2bbbaa43a8c1b63ac8774f91fbaeb2117441230df32b46db6dbcbceb8fc2a0fb89d382dff6c8df7d17cc5f6d21a9e8f03ec8a9baa83102c93a7cd267e0b976d8e7d703fae183b831a5ba3d7fac85484ba7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d513070c0d29d47e9fe7be7df27becdaf45cc7da31561e827162b16aa01fe84c4a24f44ecb3bab6b962a7ffa14a2ce082ec551943f33ce508b63a8ee30ee5e49264"]}}, diff --git a/txscript/data/taproot-ref/58fb9dddb99befb27e93f61cc7346e2e320d4124 b/txscript/data/taproot-ref/58fb9dddb99befb27e93f61cc7346e2e320d4124 new file mode 100644 index 0000000000..59bd96f0c7 --- /dev/null +++ b/txscript/data/taproot-ref/58fb9dddb99befb27e93f61cc7346e2e320d4124 @@ -0,0 +1 @@ +{"tx": "363a05540260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700f00000000e95226b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b34010000005888338d017b9b0b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac4fb5bd44", "prevouts": ["c009130000000000225120440c37f254c07fa4cc41897f3d6c7e819f00ad5f6c5ca97225bb132b6849e94a", "0cbb220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_70", "final": true, "success": {"scriptSig": "", "witness": ["98ce72c2934e1dff341aa1715387831de345d4bb16004b8f58780e1c404c68d720614c644cb9bafe0d29812957cc389f434fc2a7b5e39c68cacfd7bea0bc993f01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["12ecb843497bd08656e85718be0e8f7172b533757165b010ac4a58b46c16fb40e87ae4d8decd61bcf02f3e0f247e4238ef3c725fa7c65c09f9ebedb75d1425a670", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5901e4b94bc2da63a3099505728106aad680aaf1 b/txscript/data/taproot-ref/5901e4b94bc2da63a3099505728106aad680aaf1 new file mode 100644 index 0000000000..1095acdd75 --- /dev/null +++ b/txscript/data/taproot-ref/5901e4b94bc2da63a3099505728106aad680aaf1 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3901000000d158bef104baa42200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df97972236898740000000", "prevouts": ["1790240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_78", "final": true, "success": {"scriptSig": "", "witness": ["7bfff1571b28d2b1951c409f8261b3c759aac2ad0dde259adef342b4a52fdec847942edecd7da47bd8dc8cd3a1ee8d61725ec929f78657ef41778ca50610e8b002", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["fe18afdc833986a8455155c2ef5458da646bcaa72aa7042cbdad9e8385ed0c6677318fbed10a32082e9c9ea26fa0c909a58ab0aa459e3e3eba9d79fa43c8f31178", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/59170b1799ffe9d1e085f2b8c38cf655ca14f1bb b/txscript/data/taproot-ref/59170b1799ffe9d1e085f2b8c38cf655ca14f1bb new file mode 100644 index 0000000000..0a95bb3cb1 --- /dev/null +++ b/txscript/data/taproot-ref/59170b1799ffe9d1e085f2b8c38cf655ca14f1bb @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702f0100000063a3e9c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700502000000f4bedc840447552100000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acae030000", "prevouts": ["fef7110000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8", "2a3712000000000022512077461b0e3955cce0a8e05b12e20464a062d47e96c909cad0353185349b78401d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93696a694b26b6349dc8b1d316bba0314d4d3dc947d10f5241ff95786180ff398b9e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da733fe71e3ce0c37752cc3ed22f63651cf62c657cae6a4db35497744053504dcc62bd398c27c2bcf203967681d855a98ab83c6f29a4f091e05b1c584209e732"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d966958a6a534cbe77cd310764ead8a0428b575df096895d63298a54d270e70ef5981cd58c469d4842aa56f101a76a4447dba55ab7a128197943d7701f95f2823b7ec1fb3aca1c665feb629f75b86bc6796ed5eb830658d68574ea157b89fde9"]}}, diff --git a/txscript/data/taproot-ref/592e17797674340048f2ec49023bde0febe810f4 b/txscript/data/taproot-ref/592e17797674340048f2ec49023bde0febe810f4 new file mode 100644 index 0000000000..5d31ba9900 --- /dev/null +++ b/txscript/data/taproot-ref/592e17797674340048f2ec49023bde0febe810f4 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c0100000093647caebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd200000000897280c9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf63000000009dfb36d60406682001000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388accbd14a30", "prevouts": ["e211480000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "22e868000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "cd58720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "897d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e0000de5fc6567ef06db1dece55569d9fe4e9fbe0d833ab67420ad09244343ad18ef0696df011c2e84d95b8f4877f40057090cebf81e873c0600d23ea60362df6c56da6b4a79dd49e001229b88fb5122d120ac43d63d1be0cdb38b208b21132e"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c13e8217f4df24b7ed05cd750bc2df5f0081699b55d294026679edf52b865a2d9facf4edbbf526ff5eeb12780b24daca1831089abc7bf461f974d05d276c4783ac632f1e88e109b3d5485dae08acb0148fc939094c3a94300b3efbd66c89bc20"]}}, diff --git a/txscript/data/taproot-ref/5930d2e1ddc70c728b1f219bfa14e4053fe56dbc b/txscript/data/taproot-ref/5930d2e1ddc70c728b1f219bfa14e4053fe56dbc new file mode 100644 index 0000000000..1fbd24aef3 --- /dev/null +++ b/txscript/data/taproot-ref/5930d2e1ddc70c728b1f219bfa14e4053fe56dbc @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cb00000000e2137298bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4b010000003490f9c1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5901000000e9b952fd0237c4c2000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898757020000", "prevouts": ["30081100000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335", "bc186b00000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "22bd48000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "087d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cb173d9968a47ba6c5c74f630df9011e2eaca208cfb301cadfc15d58ec381f47a9c5848e7797e88ab157cf3f92cb1e084ad7139395a6330a6d0efe4ec0158f0520a79ac573d08fada6e0a495a70546abebfe2eb256837e38d30334686ccae33"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e881f944ef569cf36d808a56aaa75ca2fdbdf4182c26b1d87989a6b5ad676759bc691c2a9908d9e7287fb91837cd9c32b2a21ac331bb306f4648aa27bb40422e45371e41a07562523a12648be26bdba66be78ce7e249298c356e66cf29847872e0"]}}, diff --git a/txscript/data/taproot-ref/59357c2c93a40183682393a898e6b58d6e81cb14 b/txscript/data/taproot-ref/59357c2c93a40183682393a898e6b58d6e81cb14 new file mode 100644 index 0000000000..20f47da858 --- /dev/null +++ b/txscript/data/taproot-ref/59357c2c93a40183682393a898e6b58d6e81cb14 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7a0100000095d9f0a38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4af00000000ea0b84ea030401b30000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1bbc2046", "prevouts": ["1ff07f0000000000225120aee326bed25c38bbd2065ec54ba80d7933aa4c88bcaacc9a661dae671bd05d2c", "3a2a350000000000225120cf1cdbebd76187b7cc76a29147a6cff8f4ffead99137b52e0c175bb15fb623b3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93632b3ef9681fb815518e003feddc929afb08e1672963f3eb536a9a38227c931cd"]}, "failure": {"scriptSig": "", "witness": ["6a4b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/5951e8f0a0cafab1db40426b854148481b762ce2 b/txscript/data/taproot-ref/5951e8f0a0cafab1db40426b854148481b762ce2 new file mode 100644 index 0000000000..f3069965c6 --- /dev/null +++ b/txscript/data/taproot-ref/5951e8f0a0cafab1db40426b854148481b762ce2 @@ -0,0 +1 @@ +{"tx": "c07ee00c0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270200200000062d802d1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cef00000000fd6645bddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3b01000000fb6fb2d2013a6d4300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac24ec9a3a", "prevouts": ["db2511000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "86f3560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "946057000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "7e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93601763a9a2ad9de81aacd638dcfd4fda3d0aea4cfecb2218c942c0044c1357ce3e4e9bfb46536bdbe14fd1969523d98350611f9c0fc6236e31514e2d43f59e146f2e4a14a40b0acbe20218e44481fe6660f01d2e0cf04e3bc8d4452bacd1080d1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e846c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fab95efb91d04564594d9dcf752eb8fd975bf01996a0bb9f9eb7163324924bcd44fa5d068ae686a8bb1ac9947127542ac866077ad522de57cab26ce701d52bc951"]}}, diff --git a/txscript/data/taproot-ref/595901e13730319ffed24982bd4ea8c12e89bc96 b/txscript/data/taproot-ref/595901e13730319ffed24982bd4ea8c12e89bc96 new file mode 100644 index 0000000000..c67f036e2f --- /dev/null +++ b/txscript/data/taproot-ref/595901e13730319ffed24982bd4ea8c12e89bc96 @@ -0,0 +1 @@ +{"tx": "6b2f1e3902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2700000000e8905cd3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba9010000008c35e8f9017e2c3400000000001600149d38710eb90e420b159c7a9263994c88e6810bc7445d4235", "prevouts": ["09254d000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "36be28000000000022512081b6fde8d6a32bf994f385f13e2db06adc6a69d3d570a785570e2b0fcec09f40"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936923488173528c4b9dde2293d2d6ae310180a9f48368b5c2aaa9bb790d91e7493"]}, "failure": {"scriptSig": "", "witness": ["6a20616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/597a6a03965d41f1179d6a45268ac32531a9c209 b/txscript/data/taproot-ref/597a6a03965d41f1179d6a45268ac32531a9c209 new file mode 100644 index 0000000000..01096d88f5 --- /dev/null +++ b/txscript/data/taproot-ref/597a6a03965d41f1179d6a45268ac32531a9c209 @@ -0,0 +1 @@ +{"tx": "5546a66c038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d400000000b5d77298dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b120100000066b879f3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfda010000004fcfbcc7041d3ac4000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf2010000", "prevouts": ["968f3a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ebe5240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d3e1660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f7", "final": true, "success": {"scriptSig": "", "witness": ["71388e85bc88682be2696b60a83459f4edd22d13a9bcb2f7a3ecaeeeaf7553b645508f8b3a36244108136f54e480b2fab00c85c3e21442fe475bd0201ad56f8d02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["348b3f4edf4fe977b6ad2261589d623c52430caf094f898fcd8e7e1874a979e49e4fc6b5e1cda0e5f957f89e2a1bb92c958d91aa030ac3df64cedc3867979f38f7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5981777edd562076958d2a1e4c80225a425eb08e b/txscript/data/taproot-ref/5981777edd562076958d2a1e4c80225a425eb08e new file mode 100644 index 0000000000..ed1fbea985 --- /dev/null +++ b/txscript/data/taproot-ref/5981777edd562076958d2a1e4c80225a425eb08e @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2e01000000c5dd29acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca2000000009f8c9bfd026dc5c20000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3aba894c", "prevouts": ["ee7c6700000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552", "cd325d00000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "537d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361e9dee4062f54961d8ab1adbb5855faf1c96da96092bd787cd156b5117b50716aee97a7dfb8acbc78fdce4694f8ba1e1e3bf612a81f34559c93e6dfd336d600fd892d02e0db2d70aca72db86bdb1e35d04291625c81ec0b3d884b10be9f787fb"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367092fdad059f732c7ea7ebad169b970067d4e4ac878b6bbd4d3081f11431e8f3e1ea8876939edcfa4030d01bff156fecefc420cd1c8fec8a2f14f09f14c187072e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fde150f8c7b4812d3362c6afa34922f3b5cc4b63cc9e98285537a088f4a7fe3bee"]}}, diff --git a/txscript/data/taproot-ref/598b73c14cf25c235e0cc5c5a3bf6a5add3b0b66 b/txscript/data/taproot-ref/598b73c14cf25c235e0cc5c5a3bf6a5add3b0b66 new file mode 100644 index 0000000000..a81af9b446 --- /dev/null +++ b/txscript/data/taproot-ref/598b73c14cf25c235e0cc5c5a3bf6a5add3b0b66 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffa0000000003a2aaccdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6d000000009d67e03e033aa3a6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75b000000", "prevouts": ["4d2c850000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "6dfe2200000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["804c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef50ce65e1ce97b405f0b78362b0983814277331f92d6e6fe48e5fe1e54fcd63d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b44d35a0b3fc5d8cdca17f6fd766b3b7f076a7a891ad519d38c56688c70ff9dbd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cbb3471782f6552fa4d140adb875524e3bffe9f0a11868cc08e8f15e249039b3e222414f291e7c8e231e07541c9ce63e3a938f40bc45d6936d3328c3939c0fbc26dfe099323fd489e28deb26e949bd9371fd3334eb17fb18f59b980c6dd72afd91585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}}, diff --git a/txscript/data/taproot-ref/5991f803b4df614fde19c2f5742b860c1a14d33c b/txscript/data/taproot-ref/5991f803b4df614fde19c2f5742b860c1a14d33c new file mode 100644 index 0000000000..12863e5db2 --- /dev/null +++ b/txscript/data/taproot-ref/5991f803b4df614fde19c2f5742b860c1a14d33c @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd3000000009fe7febfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b86010000005573ef0e03daf96e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787dcce0e48", "prevouts": ["492f4f00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "2c5e220000000000225120d0cab111a0a7736e4b6d77027eed86efb57774f05b322cfbf052f28c507b8b1c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["4a016cdd855ac098bbc95cb5c41d1c400c9a3c5eb2432ae891f1d0d87d9ad820c401cf59134e62152b6b5ed584501ea2e92ee734c561224a3a2d3e787c23e7c3", "8ee6b4", "7529dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b325000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f00eb87a4692b27acc4891d8d3e3cdaac6444510f2bb10f8271fef4ca4ad1c0fe23310ec75f77fca2c744850a143acb95dbca139f1193d320ccff9ac1780fb1200000000000000000000000000000000000000000000000000000000000000008cc5e62b22fc06ef194978040fbbf674b0e75abfea73fecf2b459c58ae47ad882a91134608b03876227b33925d69e197a18014be235f82e13f964d7e3ee38004c0291c475bee6e13b50480160389a299a4b8bfa7b163538b8d8229b0930e2e95d5f24a89f7554a816325f89504348a7d04aecf72acb7b3161cb42fa26a77326da2b24b755b3ef6773bc8621c5ba012fe8e00c045c6e2f4bb3ebb2f332ada06e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff988bdef943b15b140cdff7ec7804e0bb3df71f763a819e6085ab4a023dfd820948788096dca9fcae82406e083f7a5bedb7db7513a0157bb52bb26f5c29a9516bfb98336861334fb562d365d25a0295c02465abf4545073426ad34a74496923045bf3818d0d3e4c68b13105477d601411785766c22f357699c168d77ad7c8093345c7c6f664b265eb35797bac4e334f98b09f0ed0be5ad6a1be3ebf075cdb341c13eb9944afc357320db238b1601374cb5a7380109c721b09169a336fe81b19f65d395042b8d29122c2810648100d566e2be256d187c66113e3d167df245a4a80ca22df8ea9052a2067a5cbbd192ddd984a0553182843c9e58b5df2dee7f0e3ab69df084681e31896355d4ff4ddb8f66ca0776fd972ceb5b66681b6af4464e832a851a610b136b9d645a3aa7782aac993cb67f0aefce6ca930d24c633dc85b548c64429ca549dbc28b231a4785cac759b2e8f7f18cd068976879f23d2b39b902e480a98b31bc5fe0133271354570993f2261dbaac4ca480005e892c8b3fcad779a93c262a615e37fdaedb6906e28e4e46a511c8bb1abeadafe21ad4734af8de8cb842ca308a2f241ccc07a2c270e302afb6961b621c803a1e05a1dd5089f5568a924ee539b7ecad14df25c5c2d532eed053407eb2e5fcbb67f619bf374b9fe9a9b6ca5ea3a401b564c26b8ec057bfd5764fe1713031627bfaa66d5bac9eb4b50be22518d97c445c2666c3aae84fdc5fe5fd9d61b7fa8e1a9dab09103a97263c0a4753a77f450cb32ddd91f90c6be53fc26cee49206499a19a91266328d53c306ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff561e43e3a89a40edb4478e82f6a8df4d738ae87432ef72cb3eb5a3c401f8b967"]}, "failure": {"scriptSig": "", "witness": ["4a016cdd855ac098bbc95cb5c41d1c400c9a3c5eb2432ae891f1d0d87d9ad820c401cf59134e62152b6b5ed584501ea2e92ee734c561224a3a2d3e787c23e7c3", "598f", "7529dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b325000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f00eb87a4692b27acc4891d8d3e3cdaac6444510f2bb10f8271fef4ca4ad1c0fe23310ec75f77fca2c744850a143acb95dbca139f1193d320ccff9ac1780fb1200000000000000000000000000000000000000000000000000000000000000008cc5e62b22fc06ef194978040fbbf674b0e75abfea73fecf2b459c58ae47ad882a91134608b03876227b33925d69e197a18014be235f82e13f964d7e3ee38004c0291c475bee6e13b50480160389a299a4b8bfa7b163538b8d8229b0930e2e95d5f24a89f7554a816325f89504348a7d04aecf72acb7b3161cb42fa26a77326da2b24b755b3ef6773bc8621c5ba012fe8e00c045c6e2f4bb3ebb2f332ada06e0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff988bdef943b15b140cdff7ec7804e0bb3df71f763a819e6085ab4a023dfd820948788096dca9fcae82406e083f7a5bedb7db7513a0157bb52bb26f5c29a9516bfb98336861334fb562d365d25a0295c02465abf4545073426ad34a74496923045bf3818d0d3e4c68b13105477d601411785766c22f357699c168d77ad7c8093345c7c6f664b265eb35797bac4e334f98b09f0ed0be5ad6a1be3ebf075cdb341c13eb9944afc357320db238b1601374cb5a7380109c721b09169a336fe81b19f65d395042b8d29122c2810648100d566e2be256d187c66113e3d167df245a4a80ca22df8ea9052a2067a5cbbd192ddd984a0553182843c9e58b5df2dee7f0e3ab69df084681e31896355d4ff4ddb8f66ca0776fd972ceb5b66681b6af4464e832a851a610b136b9d645a3aa7782aac993cb67f0aefce6ca930d24c633dc85b548c64429ca549dbc28b231a4785cac759b2e8f7f18cd068976879f23d2b39b902e480a98b31bc5fe0133271354570993f2261dbaac4ca480005e892c8b3fcad779a93c262a615e37fdaedb6906e28e4e46a511c8bb1abeadafe21ad4734af8de8cb842ca308a2f241ccc07a2c270e302afb6961b621c803a1e05a1dd5089f5568a924ee539b7ecad14df25c5c2d532eed053407eb2e5fcbb67f619bf374b9fe9a9b6ca5ea3a401b564c26b8ec057bfd5764fe1713031627bfaa66d5bac9eb4b50be22518d97c445c2666c3aae84fdc5fe5fd9d61b7fa8e1a9dab09103a97263c0a4753a77f450cb32ddd91f90c6be53fc26cee49206499a19a91266328d53c306ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff561e43e3a89a40edb4478e82f6a8df4d738ae87432ef72cb3eb5a3c401f8b967"]}}, diff --git a/txscript/data/taproot-ref/59a01c32eca07dea482bf25537b7d52b7bc5aaca b/txscript/data/taproot-ref/59a01c32eca07dea482bf25537b7d52b7bc5aaca new file mode 100644 index 0000000000..e31e1e5ea9 --- /dev/null +++ b/txscript/data/taproot-ref/59a01c32eca07dea482bf25537b7d52b7bc5aaca @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc4010000002b6191afdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21020000009884a17cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1c000000007c4b09c60226af4401000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd3000000", "prevouts": ["c299750000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "05cc5a000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "080976000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045591d3592ddb0f56a18929886f1890713028f922113494349427ddaa1ea39184e02b5f712fb146ffe69ff220cec8aeafe04d8a9d43d299b22043a34551aa1e56e09208a3d5cb0b20fec302022af702ea090b934668d0752a16a75cba2aae8c677"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360de7d78f78fcc1ab87c0aa695c1bfde682cf6b1e0f8cbb7a903d4a6ffdb03c46aac1f02719ff09c82d93c60ae8b21e31f1ec3fca4030b09dbe2604c5a66091c209208a3d5cb0b20fec302022af702ea090b934668d0752a16a75cba2aae8c677"]}}, diff --git a/txscript/data/taproot-ref/59aa7a8b1146af0061b9b9478ffb499b5e7f3229 b/txscript/data/taproot-ref/59aa7a8b1146af0061b9b9478ffb499b5e7f3229 new file mode 100644 index 0000000000..ec5fe8b440 --- /dev/null +++ b/txscript/data/taproot-ref/59aa7a8b1146af0061b9b9478ffb499b5e7f3229 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b85000000009369fd8bdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce3000000008641938a0366ee8000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce86e6736", "prevouts": ["6ac7250000000000225120c1ae6350d5e25c8637e3643ccad16ae3a3009b1bad8c1dbb165abd62db3354a2", "98df5d0000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369dff3719d80ed973188b1e18c406e7a882a557b83701af7fafb01b5e6c08518b"]}, "failure": {"scriptSig": "", "witness": ["6a9a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/59b9a0e1dfe394504f08eae69abd47bfab092572 b/txscript/data/taproot-ref/59b9a0e1dfe394504f08eae69abd47bfab092572 new file mode 100644 index 0000000000..7091d116f7 --- /dev/null +++ b/txscript/data/taproot-ref/59b9a0e1dfe394504f08eae69abd47bfab092572 @@ -0,0 +1 @@ +{"tx": "23ccb2ba038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d2000000000276dbdddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc201000000bff559ce8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49b010000003499f1aa02d96dc3000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac8a010000", "prevouts": ["334c420000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b5fe4b00000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "3fdb36000000000017a914aa4a4e70b11f4eec4760f77206dc93b02350fcff87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1656142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["76090b842d03017fcc3a54ee33291ec26151f7678de4792da9eb6ba5c5f8bc12f1cf6dc101a14ea93f5577908ded8f80c9b53785a1a89a38f47e6522c1e3fb4e", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/5a198317abb136510b17c59de5eaa7c880152f8b b/txscript/data/taproot-ref/5a198317abb136510b17c59de5eaa7c880152f8b new file mode 100644 index 0000000000..a7279a2145 --- /dev/null +++ b/txscript/data/taproot-ref/5a198317abb136510b17c59de5eaa7c880152f8b @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702e01000000a82179bedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf101000000b57106c802fe846b000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac32000000", "prevouts": ["b7550f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "45bd5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ef", "final": true, "success": {"scriptSig": "", "witness": ["f5259f26a46925063bfd0d33a1df0e884a946857efddf2d6a9b96ce25ab7160a9523c6d19b3fc533bc8a54a4f5bdb9de32e49a8ba0107501c976db88b488480302", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8f38202eb656ce07410e142d99a545511f1c2a6922f58ab00095360d409862b6258b14dee274181e99091174ec7f3f7cf5d404c0de070af16f0f8a3d2bff5f01ef", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5a53b6c3fb03892958b022df8a6e0a4cd3d8e51c b/txscript/data/taproot-ref/5a53b6c3fb03892958b022df8a6e0a4cd3d8e51c new file mode 100644 index 0000000000..8bb0020292 --- /dev/null +++ b/txscript/data/taproot-ref/5a53b6c3fb03892958b022df8a6e0a4cd3d8e51c @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb1010000006efd7897bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdf0100000078ee6cd803e00dd4000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc55030000", "prevouts": ["00c563000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "dc71720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/pk_codesep", "success": {"scriptSig": "", "witness": ["781cce034e47e081dfc6aee6d7a23af9df7a9c128799aadddf5edc10761334b8ff406be65cd8e25817cdab42a4e765a199b157d68aab2a3b46a7d6b50d7b0dce03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50fc41f5a2bd1748e2a7f00451b8b318fed29b9a"]}, "failure": {"scriptSig": "", "witness": ["910fdc32fa386f26136e3f934cd48eb062be1b19c61cf0b2aacd04de1f93386836cd074b132c8d9c7e8745393b31bd0ede6ae53f2fe21030ee8428b5acb36d3682", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50255c0fb59c91025ae877168f6f73e3860bb0f9863f2740801075fd4141576e5c3b6cbb8ae7252a1aefd0"]}}, diff --git a/txscript/data/taproot-ref/5a5abab97631cffda0f11fd3ecd87d86dc325f8f b/txscript/data/taproot-ref/5a5abab97631cffda0f11fd3ecd87d86dc325f8f new file mode 100644 index 0000000000..cc5ca6fe83 --- /dev/null +++ b/txscript/data/taproot-ref/5a5abab97631cffda0f11fd3ecd87d86dc325f8f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf79000000003b14d3dbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2401000000537929c80432a09e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48751010000", "prevouts": ["a0c57b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f4c4240000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_fa", "final": true, "success": {"scriptSig": "", "witness": ["e097ccb88c98bc5b320412d3824c0b7ebbd66b9acc8fa4536ade9d90a7db4875dec758916018f082985fff817c38bc79b6e5b92489c7fcb97f2c823d75a94bb182", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a7e58588e9e3f011a7aeec751f61cf2c36a22221a66678d803d2e6698db1696540e8ab9735b5d69e5690e6d1902590d02801aeaaad47db75fce701a887ec0676fa", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5a5d03ff40bbb94cac9b06c3d47e693d8db5af67 b/txscript/data/taproot-ref/5a5d03ff40bbb94cac9b06c3d47e693d8db5af67 new file mode 100644 index 0000000000..5ca23af06b --- /dev/null +++ b/txscript/data/taproot-ref/5a5d03ff40bbb94cac9b06c3d47e693d8db5af67 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb1010000006efd7897bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdf0100000078ee6cd803e00dd4000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc55030000", "prevouts": ["00c563000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "dc71720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "677d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a77b70c46c994a01ec5a816124f61e0f5d1b89a7d1384137283c1b5de2b508b62e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdbceae773fe677547a5f8be2986f5e4c7dc436c0d3f0e1e86711aa468c8778215"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8687eac120734a03ae4c27d3bf57e4c4c383799b8e878ebb1c20141d650e89e9fbceae773fe677547a5f8be2986f5e4c7dc436c0d3f0e1e86711aa468c8778215"]}}, diff --git a/txscript/data/taproot-ref/5a5efe209bb7d1e1b0085b1515836fcb2144c5f7 b/txscript/data/taproot-ref/5a5efe209bb7d1e1b0085b1515836fcb2144c5f7 new file mode 100644 index 0000000000..f25be87c57 --- /dev/null +++ b/txscript/data/taproot-ref/5a5efe209bb7d1e1b0085b1515836fcb2144c5f7 @@ -0,0 +1 @@ +{"tx": "e804ef7102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe80100000034edbacedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd1010000006fa7aca801349d22000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787f2e54f5a", "prevouts": ["e25f660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "146920000000000017a9148fdfffe253d045df4a2985902e5465482e50374187"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2360212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["3201faf0f008f4b991bde7c4e5a8e0151e32e6e436f2cdf4795a2128a90e73dcc7985f3467b350aefdb57ee932643e64353e10f0a4d7bf4c1a9cf1a394ee51f0"]}}, diff --git a/txscript/data/taproot-ref/5a81cfc3ec9bfa6d49dcb19b411b6a4b6043df15 b/txscript/data/taproot-ref/5a81cfc3ec9bfa6d49dcb19b411b6a4b6043df15 new file mode 100644 index 0000000000..3f738f36e5 --- /dev/null +++ b/txscript/data/taproot-ref/5a81cfc3ec9bfa6d49dcb19b411b6a4b6043df15 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705100000000fbf40f81dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be10100000028107fd004ce692f000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aceb524132", "prevouts": ["aafc0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "43d42100000000002255202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d3", "final": true, "success": {"scriptSig": "", "witness": ["63d7996c18222f1ff524042a5ddc4d277e17160cf398b4e9cedd99e2deb94b85dc7e7f89e866cf02d3ce88f082436eb3e543efe13992fdecb0da627e90d6d7e781"]}, "failure": {"scriptSig": "", "witness": ["ec45c4f58ae924054bcc114730678dd60e16539ae1c4966704cb386cc7e49b09b4cb6e333de6680a8ad78f495fd3c92e8689e64d7d1accf809150b74c9745ff3d3"]}}, diff --git a/txscript/data/taproot-ref/5a9d9ae70e2df49baefc66227ea1c1604902038d b/txscript/data/taproot-ref/5a9d9ae70e2df49baefc66227ea1c1604902038d new file mode 100644 index 0000000000..deb05b109f --- /dev/null +++ b/txscript/data/taproot-ref/5a9d9ae70e2df49baefc66227ea1c1604902038d @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270570000000087ad7513011c180500000000001600149d38710eb90e420b159c7a9263994c88e6810bc762000000", "prevouts": ["5fc60e000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "a17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93654d5e9f128d5d45e2b514bc7d0582e1e8810c31523e6a7d498e7ed4fcc964510a4fb15e70bbc27f4f9ee6ce894c5f8660c4bc0a21501abf5c583e18e279746b733479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae668dba12609f1dce2a1e29faaa62ff248d54f408b31ef31944f67a579d4fbb4"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692ed1d8a723f26614ad38a5a6bbff83804b2df3c5c12fea7853938e6cfd441ba04a5fb755beb1eb88fd06fac279ccb2aada241654186a69e6e0c04e3255c18f895176026b3e005afce4c10b5e59a002659822bde369bd64201565ae4c88fc95c"]}}, diff --git a/txscript/data/taproot-ref/5a9f746ca2d826a621e61152c995893027ae3dff b/txscript/data/taproot-ref/5a9f746ca2d826a621e61152c995893027ae3dff new file mode 100644 index 0000000000..b43be10c85 --- /dev/null +++ b/txscript/data/taproot-ref/5a9f746ca2d826a621e61152c995893027ae3dff @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc001000000cc3e5864bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf850100000023fe971b01f0091c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6c780bb21", "prevouts": ["5d6e220000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156", "f656660000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "e97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e88b8d8a8d8c003fabb93595bfceed403f9a1266ee95e7fa8447cccdf398ce498db8321554bafe286e6661652cf416d3db0b455024b23404eea069d656c79e4f25"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e84a72ef51eb7f1fd93b7716e160b4419190ea5192ffe31c8263ef308a11abcda602e473c0179dfd44294f4ddb50d827cec9d4b4e0c6eae7f68c0301f0fdfe7e6b9e5e4bd2cefcda110a5bf613694738c198174b403d264db4691720c8f18fc7b8321554bafe286e6661652cf416d3db0b455024b23404eea069d656c79e4f25"]}}, diff --git a/txscript/data/taproot-ref/5b000b738705bfd4a6198d22129f7e9f2ccf1708 b/txscript/data/taproot-ref/5b000b738705bfd4a6198d22129f7e9f2ccf1708 new file mode 100644 index 0000000000..31c5c70678 --- /dev/null +++ b/txscript/data/taproot-ref/5b000b738705bfd4a6198d22129f7e9f2ccf1708 @@ -0,0 +1 @@ +{"tx": "63a8de0b0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270400000000003003e95dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6000000000987504ec042540390000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478761b26b4c", "prevouts": ["d92113000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "f77028000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000be", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93627167bdf7dd6f113555fa8f4b26cff315296a536038735c5506a84f918c8c5ad61eb6e6fd21ad84d93c7a0474b2daf5b011002cbe34781a2a14a95ac7c4e00ae344cebdb8ecd56ef01fad0911d9d88482970ec36d3a04b84eda7f5b5c68ec938"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e44a95c71cca5173fb3cb918c324a06ae35450e2cf1a92910826d87005746c9018b1142f6c6f685b07aa6aec8ab7e3e6024758bf09974a9b2a7615fb4927a0f7d3726db1c97dedfc82502578948b1d779eb886e6296c36bf50b8d2fe25c32b8a344cebdb8ecd56ef01fad0911d9d88482970ec36d3a04b84eda7f5b5c68ec938"]}}, diff --git a/txscript/data/taproot-ref/5b08bfcfc4f7317c5e45fbc3a683064ae85a3794 b/txscript/data/taproot-ref/5b08bfcfc4f7317c5e45fbc3a683064ae85a3794 new file mode 100644 index 0000000000..723fb63b2d --- /dev/null +++ b/txscript/data/taproot-ref/5b08bfcfc4f7317c5e45fbc3a683064ae85a3794 @@ -0,0 +1 @@ +{"tx": "ec6f545702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9e00000000a8a25b8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705000000000f22c0df9034f438b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d3020000", "prevouts": ["85f87b0000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "97f8100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ac7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e5a9aa32e218bbd7702dd80b5ebdf509d58cd1514da294d038190654a927a1119f9ef29ad3e74b34f129235a64deb65fb580c2718ff9462ea3ca43b3a4f56170fc485b911b91245b46c320351c8e1d13bb30ee22c3f953d2224593bd4b5088ca"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93658c6fb8444bf3f1c71dc62d586de8f6b9f63c49598648e9eb416ba7b8eeb55d0f6e1ab16ab4bc20af15f35a7f6b67f82a67b85511624b76e02698979773111889f9ef29ad3e74b34f129235a64deb65fb580c2718ff9462ea3ca43b3a4f56170fc485b911b91245b46c320351c8e1d13bb30ee22c3f953d2224593bd4b5088ca"]}}, diff --git a/txscript/data/taproot-ref/5b33a7895ef81de11965a513bcadc8ee53993d21 b/txscript/data/taproot-ref/5b33a7895ef81de11965a513bcadc8ee53993d21 new file mode 100644 index 0000000000..21f7e199df --- /dev/null +++ b/txscript/data/taproot-ref/5b33a7895ef81de11965a513bcadc8ee53993d21 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf601000000eb15c2fddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7701000000ce8ae4fd044f5f4e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a64ae04558", "prevouts": ["5f3d280000000000225120768c54f13dde172f25cce5a33aed38e02f08031f35d73759f73c7d1a105e2823", "abac270000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a1e25a5a51de273a99a983b8dab5f9a449011b840b2876cc59d12f2fdfbcf4b4"]}, "failure": {"scriptSig": "", "witness": ["6a82616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/5b718764a0b56ae1705be7dcf35a2c639fbee6f4 b/txscript/data/taproot-ref/5b718764a0b56ae1705be7dcf35a2c639fbee6f4 new file mode 100644 index 0000000000..50829aa842 --- /dev/null +++ b/txscript/data/taproot-ref/5b718764a0b56ae1705be7dcf35a2c639fbee6f4 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1102000000e34a2009dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bde0100000060eae28fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c540000000002789cfd01dce73200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acae030000", "prevouts": ["6cbd6c000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "4c421e000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "b0574a0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4e2b448ed3f1969af8fffbdb3b73bd72fedaa98057d5c8b58a84426194002c6e029de37322ddf566a2356077a247b666bf816d75bd62d8842c555909c8a1545e03de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a6a8932227d021db8093e005e96d1e8927d5db9b23e7e4b1a24529d381170a492555fb599a2fbb7b206b08358b85e40a527ad21aa064f750df81600ff72cf4ef17ad4bbf375bb62f626ec8048d4347cc1eef977780228a6d2fc47294088d561"]}}, diff --git a/txscript/data/taproot-ref/5b72a3d1797578b12f235ecdfb8305d928514960 b/txscript/data/taproot-ref/5b72a3d1797578b12f235ecdfb8305d928514960 new file mode 100644 index 0000000000..a9ae70055d --- /dev/null +++ b/txscript/data/taproot-ref/5b72a3d1797578b12f235ecdfb8305d928514960 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42201000000a7edade360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702e00000000e8af8ed604cd3f4100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388aca7030000", "prevouts": ["d6d3320000000000225120bb5a47f5af791bd0da95f040450c31e81733ad36d8a4b487e3e6f1ab189dc604", "3056100000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["0dd15b60a933bc801626bd96989888c3ef766d4707939fd2fabe3dbe586b1cc2095a90a93de6471623acf924489310ea05bf81e35893164f663c55c0b5346f1a00", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/5b831888d2299bcbbe9bb60f6812a461f2da8720 b/txscript/data/taproot-ref/5b831888d2299bcbbe9bb60f6812a461f2da8720 new file mode 100644 index 0000000000..67bad7f940 --- /dev/null +++ b/txscript/data/taproot-ref/5b831888d2299bcbbe9bb60f6812a461f2da8720 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b23010000000184e7e38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b501000000906251e203788259000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2c010000", "prevouts": ["41e7200000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842", "14703b0000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "f37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936111cdf76836f174788069938d43a1f118e1d6048d7db416209f274b647d1178e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cfa000ce8b9790c39a5d5a4e1f475bb1ef714fb8e08d79945cb39f042227236d80eaa4a5149b34d26f0437dfc3cc15f8b829f232fb4e000d97f0d76bcdb6c884"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ad006099a5afd91da2bb050912b31486a1a5f178aed6fde7a35ffc349c590e4cfa000ce8b9790c39a5d5a4e1f475bb1ef714fb8e08d79945cb39f042227236d80eaa4a5149b34d26f0437dfc3cc15f8b829f232fb4e000d97f0d76bcdb6c884"]}}, diff --git a/txscript/data/taproot-ref/5b89dad22b6b9ad7d97be2de400eaaa8ab2a03e9 b/txscript/data/taproot-ref/5b89dad22b6b9ad7d97be2de400eaaa8ab2a03e9 new file mode 100644 index 0000000000..bb55fa5245 --- /dev/null +++ b/txscript/data/taproot-ref/5b89dad22b6b9ad7d97be2de400eaaa8ab2a03e9 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c440010000008819fbb38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49f0000000080656b9904c66868000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c7030000", "prevouts": ["455135000000000022512089bb171a5e185cc37daf7aa0871afa228227b6abbb83e8d3d329212a244ac814", "ebad34000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c0e369f272f9685ae2ab5cbec56c7922838a13e1e8a56851740c1aaff5717a80"]}, "failure": {"scriptSig": "", "witness": ["6a32616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/5b9296392fbbb89f20c46a8276795c3b237a921b b/txscript/data/taproot-ref/5b9296392fbbb89f20c46a8276795c3b237a921b new file mode 100644 index 0000000000..e7f99697cd --- /dev/null +++ b/txscript/data/taproot-ref/5b9296392fbbb89f20c46a8276795c3b237a921b @@ -0,0 +1 @@ +{"tx": "72ce730f02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbb01000000937aa8c7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd400000000e0a2bed102189b98000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787660da74c", "prevouts": ["89f4240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e849750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_27", "final": true, "success": {"scriptSig": "", "witness": ["685d25c1d2d17a914657bc9226bff699b0619edc946287c76d4e764d6e6522577217f42b52e8ea935a9fd4a8788a3e34d0a574570859d949cc06e893b3a91f0c03"]}, "failure": {"scriptSig": "", "witness": ["8b3d69c2884b0c8fefa4fd2ea1b2b2577a56b255e688a760517e88ce944ecd9b496b514563a8e8ac308b2777f14057cddee4d74e2a637c9ac7f68636a256ad2027"]}}, diff --git a/txscript/data/taproot-ref/5b9476567b263e9cd4c8455b1383c48f559cdd5c b/txscript/data/taproot-ref/5b9476567b263e9cd4c8455b1383c48f559cdd5c new file mode 100644 index 0000000000..6d4d006d03 --- /dev/null +++ b/txscript/data/taproot-ref/5b9476567b263e9cd4c8455b1383c48f559cdd5c @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1800000000666e3e46dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf200000000f1d81ac101a24f220000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7fa698e43", "prevouts": ["befa55000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "f7b3550000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366710f0898dc1486fa1452d6452d8e08d4e319f7bf9099dce0673c5abdae87e6f493e40fcef10fde3df13bbd1c2551f58461e5d74b1e1953624615bb6f8ad2778f2e441b555c43a724b579c479d380c278f8ccac4217fbfdcb96526a1dcd96287"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e8cc06f1f6f7ed6c588d622e74b9585b43038ad82cf2101cca86064972a6f81086a27b1635c4d20405f5eb1d8e1a675f8ac3bff005ffde1fde7fd53008c3096ff2e441b555c43a724b579c479d380c278f8ccac4217fbfdcb96526a1dcd96287"]}}, diff --git a/txscript/data/taproot-ref/5b95416a6aeb72fb134a6149c2103c7b4b8af54a b/txscript/data/taproot-ref/5b95416a6aeb72fb134a6149c2103c7b4b8af54a new file mode 100644 index 0000000000..8bbdcc78f1 --- /dev/null +++ b/txscript/data/taproot-ref/5b95416a6aeb72fb134a6149c2103c7b4b8af54a @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4201000000b563db75dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc301000000f098e3a68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c467010000003d1d4d040391f7a8000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72db95c2a", "prevouts": ["4e8e4900000000001657142540f27e90740933c99d4f17ab2dfc6c82951cfb", "f6a2260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1053b0000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "837d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c30d5e9bc30c4c4af9e4eb5b310ad22b2e60a98f718761077afb06a77f13bd7efcc3b58fc7cb9ae8c07f6b17b965d49129a74935af1e9f3c9d7206d9e0977573ff15e37d03bf407745d47da370f693bba1bd1439d95d9059575aa23ebc3ce6e3"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364e4b21485a97c5fd22d086acea81de731dd57bf1980b68bf0a0105c8b4b984177e533ff75a4d67e066dc739e50d12e058e790be330db290aa1a5b4fb647c89858163db171dbfcbf374971659a5a65d0378eae0ee15db360ca8cf80a8c2e13046"]}}, diff --git a/txscript/data/taproot-ref/5bc0284515461bcb5e3ebafccc633649bb1ec2fd b/txscript/data/taproot-ref/5bc0284515461bcb5e3ebafccc633649bb1ec2fd new file mode 100644 index 0000000000..a1a73cafea --- /dev/null +++ b/txscript/data/taproot-ref/5bc0284515461bcb5e3ebafccc633649bb1ec2fd @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704b000000000a65acfd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c465010000008cdf959c01c1fe0600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5e000000", "prevouts": ["d88a0f0000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f", "d44c330000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "147d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c26aa6cc7dbd51dcffea9f3cd500823e5cbc45e46e2b002a2a7ff91e8ab38dae3488b030fbb16fa8d50c4f1f044e6df81cbeac111f0be15e3f466e559374b3e5568dbaf979cca58396dcf271ee6fc736edd00965a3b0ecce9c87347ff88ab08a"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa7a317a052512b66d9c0a593db192e28ab9b1379143982fc432aa6f278435f8ccfb63111b06c7a0ce3f44d9f6906db8fc60057b72694cfd58ed25db88d188e5fc"]}}, diff --git a/txscript/data/taproot-ref/5bdb30e6f918889383a02c0269f0e346fb129035 b/txscript/data/taproot-ref/5bdb30e6f918889383a02c0269f0e346fb129035 new file mode 100644 index 0000000000..bc810eb2f6 --- /dev/null +++ b/txscript/data/taproot-ref/5bdb30e6f918889383a02c0269f0e346fb129035 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49801000000f2d4614a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270130200000074abd946dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9f0000000045a6249304c5089b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acf499373c", "prevouts": ["31f4380000000000225120d7db2432b77440d39106fdcd5c35c463320f36611b8bc46e3633cb3a8d85086a", "83da110000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4", "30d0520000000000225120c3b9d8e50d42de1212377aa9427da72fe17222669efe5204fac1f05c34f6e65b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09026fecdd4402cc53c7d16d3e939e8e3afcc9d3c59ded67f392425c6737bfa97e5ded722b8cf7d50550b459a9f46d0520b6a5540ce67caf543c0c5f28ee0a0c0f8990e36f730660a7d90aba2720fdc1d390985ec097cea1203b5fb3f9ff4ff0990e4e3c8b9608baae79d5695715f40811a721d607df2a0e7346194293135dc41d9ca6e5079ade54bd6f16c6f60a4c5d75968a3483399ffa1a09d5363025dbf97f57eeddb2ce4b991b5dff568b0e6058364884221a253c2c097b55ab5e57d75ab407ae4feb54c291dbc62df4419e053848666785366a2620d4b8141bca0e858de1d05dc6790ce0996d80b065f4fb5ca44a4eae36d7814700b20f2e2506a3993cf50a250944f44336d4efba1ad82cef4c31596942f3a83b0950f25e87408eb84c208d109a219a67fd5e92bbe75c9f21dce76ef84e9966e021722d28071ca0c5af4db33d603c2ad5bddb7b0951a805699f51b502461b24e5f5fbde7b9fb69ff0f27910dae63dc2be0e38aa2d0ccf6940dc7a636e2bbf85721b58017178bee6ec54f79894726e40825bc8a1d23d10e2390c09058116a6e7bfff9f7489b9069182496c3676b1bd369433435d35c2ee5111a8d0fba6a44dca4564f023a98d485193742c184a0261cc74d72801ce3b3d2cf17ad17375fac0a8c7903b995f93fbda44012a60d9d9c2430153344cb12346ae7a56fa33240f44c3373990981fd210a322ef5a84d141551864d24af56a75", "137d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361426daa4bbe5d8fcab9dd1197b7c9101d6becf10f586c66a38819853ce8b40c391993dcc568707dee1346cf3396ea5c7390afa7d45c5790b2352813dde91dd339a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e7c43b740c0608ac721897ca7a4b0bbd2ef7e62418d1fc20274bd386c7c0d4d7e"]}, "failure": {"scriptSig": "", "witness": ["4d0902158bc98498b37b7647654b0d28d7cb79dfd2016d7902738862e6eeb27c65385701547fc2025bb2be0d0fecf8794c1bba6442eebe3302b4c194dfbdbaba68bda53ea0984be5fd27a0571abd5c6bbe3dd7ff12cef3a4483863d788ff17f80e157301ac1772fedb30e5b20557b972e82e4216140ba93c5e896e862cacc79048077e4be5e880602f63ce49fdc5ab08b8ec5f119fb6cf7898d35eeb1802ee91a5b5015b8f6c6c6030da2164f0a82bdd6a67452ec8d27a88ea9cbec836c6c5b39f9cdebc6ff7fb84b08fd829886c027cd2884536f304c678b7e78827ee5b08f7d50c14490f80226e6bb504714ce85e5d6c7c342d3d263f08ec44baec748dcd8c6e6271cea772250c349fb10278f0a3eeab533d18fda98636c366cf058a612f3cb91279f3caa47cf7795c7b69f78dd8f2fb0a6aea9b6a8cdbc3a6d3fca5d20edfa01aec5077b30a387edf43b8abdf66e359c374dc96a42dcc5130c869580ddfddcc770ab46b13c77097a82fd43701c9577280825ccdb7f0c60d41ec362af39513977c1a3a0fe42c5f67f6d66b66dad330839d93fb66768397b607979d7e1295e76531598c2382393024cbc9c3285350d2379bd53b469ef774b01334be69acf57262c78d27090ddd5e641566438d79614418183e61a4e63fab91ceb2dac3fa9a1d94d83b9e4b7a7651d84d9317cb5fdf61dac9dc68b387890414970fc2bc68afb4b304bb5f74eaab0b92ebda3275", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b8824ca039286516426034e909501685a57dd231358ae092197a767d6d59583991993dcc568707dee1346cf3396ea5c7390afa7d45c5790b2352813dde91dd339a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e7c43b740c0608ac721897ca7a4b0bbd2ef7e62418d1fc20274bd386c7c0d4d7e"]}}, diff --git a/txscript/data/taproot-ref/5be7de136c7e263729c299d1617ae86dd468f91d b/txscript/data/taproot-ref/5be7de136c7e263729c299d1617ae86dd468f91d new file mode 100644 index 0000000000..109f1b0a8d --- /dev/null +++ b/txscript/data/taproot-ref/5be7de136c7e263729c299d1617ae86dd468f91d @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45700000000d443c5cb01040627000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870d90964b", "prevouts": ["b9ec3f00000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902be062cab72511239868c05d22706a5695f0e63841129712bf325d765dad23339b1a9810a58bf2c9bd69e3761daa1f83981df227a9b233d6d1102f6aa8b54a300185d607c6dc16ad92b87f1a440576ab30b3a7e7599aeb921a150f19eeae0c8f92937364734250b68e274993c387a8eb3e92b56ee12746286e20c96fe1743c62679cbb3e7648cb745b0366fa76cc938a1d82d56b483ffd0cd64a15eabfa5f9717ff3c0c168522dc81a5f1c4d6d336674deeb6139fd58bb477c8b329d335f2b5f35de0080e9fd3a5b912b190d328ef3c0f50738e71ef987e55880095366ea2e9701a1aef098439cf686caf4e3f51368166dc9761524256ef031d7398d141c709b8e9ec25870a6e3481a5b996d80017bce46db728198cfd180f9cce9181d17e9754a573dd439c580de353261f5e71796fb0c053ca3191e1d2fbc5fd168d42ca3111ac2bc5ca9112acdc48b7593a3abd4ae7d12cc9b62e82cb2e403687bd35f2908f8e60fa61e08f2170a39a40fdffa559a06ad5ccdf97e1b2cd4ed89a2cb1c1fcce13ba213fc8eb435e9e567b3d54b311e59afe7f7386b389adf5f922d6e0f2010b74ae79bb5dc32d63664a2d28d5acc3e5962c795881dec8f503b8aeaf51eb5a29ff33ed4a7dd7ba0d4ca856750084802e22696e6a25128fae9cfb04eff6f56afa0e1d1c1c8b849dca2dd886ed865a36652e4299ddd98cb679c21bc9a5a15f363a7a9bbf0308397238c1757e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d511f4adb00685858cbe7bcb6f491f781bc30000d79c976ba3736fd7b7a39329ee30cbb6a1bc9c683a9249ad6bea98cd3b225511a23bd3763b6594afd12d3e036b5faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}, "failure": {"scriptSig": "", "witness": ["4d090282cdcffc3f05c6977b0cd02c835b7eeab7a0f62e169621aa36f5740268d0acfa82f8e80f2f456c7093814f254fbc07e36c04447b10c6b6f48572a05c5fc6d6ced81e61fe075de523f0deb627041f03443884c4bd7b8c85ff128c899f9ecb39847bb9a971d498839358ec9f808e104be0de57640d5d02030948739e99eeb8e139b7832e3d20c939361c349a917c2135102087af2f628046463e0630cfd7e18cf19800164a0e06f4eff7f9c55dfcb441d1039163e518d83b182027b33eba77922f6c2afd463bc48e0c95691f185615860292902fcd23210c63f79b888c9a0180ca52f71874af6ad65bad70c71ee19984c9bec8f745c2a10ff8d0244b22ecbc5f5c1c2750464c14b0a9a39299b76d3a76c520b7c81e6f5b6b104260b65e7440f9a69ba1285e089174e371793af1c20ce0e191d28573eaa3c6508d16232357e637f1dee44caf389e65f336eda982d5a986432081392f9ac8ee4c6732420de1a2bdc9f75ec283a057c52a830ba3f10d243995f23137f9ffe7db82b424f46794efbe9d5cd32d5629716b9be1070af9dfc5d3e4cc99757dbea41189f4bf34c999440caf58538c5f1108f95c4d81e71e43ed22e5122b4a401bc5a16ff6e04853da0e49827ceac8d29f412176bdd5150faa16e11563e1253f59686181380f19ba3052901117082d629889ae4d5a6212ea7b7bec696a7f4f704504836dda729243ed307748a3aed8bc3042eca8917561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b9b4175db22b4058fbb32c1c98b401bd6f80a734567664ffaf4b869d5cecb8c8be9bce0da1a8e0eb2f55600b1edecb05394963f1d059e6505f0ccee9d28b62f6faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}}, diff --git a/txscript/data/taproot-ref/5c2aec0e280cc6dccb0aa9c3d4c5354a71c3d8e8 b/txscript/data/taproot-ref/5c2aec0e280cc6dccb0aa9c3d4c5354a71c3d8e8 new file mode 100644 index 0000000000..a5bde1d40b --- /dev/null +++ b/txscript/data/taproot-ref/5c2aec0e280cc6dccb0aa9c3d4c5354a71c3d8e8 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48a01000000668a29f1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3d00000000680a248b0199335c00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acd1918f56", "prevouts": ["64343f0000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "251a20000000000017a91454957ff2b5c5fa7ace3c6fb485b914ecf6ce0c8c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1658142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["7698efe28cd54922ea5e6da351039d28e1396fc2b3f262ce287a666ab6bad6f86ddc89802934ad992a50fcc287f7b187b9bf6084e175b85c15f2928f55af056a"]}}, diff --git a/txscript/data/taproot-ref/5c2cccde1ba71ca24440e1be3fe94d8b2abc9ba0 b/txscript/data/taproot-ref/5c2cccde1ba71ca24440e1be3fe94d8b2abc9ba0 new file mode 100644 index 0000000000..58de42aca8 --- /dev/null +++ b/txscript/data/taproot-ref/5c2cccde1ba71ca24440e1be3fe94d8b2abc9ba0 @@ -0,0 +1 @@ +{"tx": "b07ccdb3028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40e02000000ac2245c68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48c0000000092334be801f08a5b000000000017a914719f78084af863e000acd618ba76df979722368987818e012b", "prevouts": ["35c53600000000001658142540f27e90740933c99d4f17ab2dfc6c82951cfb", "1c5737000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["8767dc918e57c70b298c1e561d76c5e65deefece0466c1b170a15e69fa408a920e2b04e96f142cc6b66e76d5b89c9b25ae8fbe00cff03bbe00e52c31d1dfc2fd", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/5c414ad191f1a4f17701285f026d3be386795f46 b/txscript/data/taproot-ref/5c414ad191f1a4f17701285f026d3be386795f46 new file mode 100644 index 0000000000..a794fef6c5 --- /dev/null +++ b/txscript/data/taproot-ref/5c414ad191f1a4f17701285f026d3be386795f46 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb80100000095c037858bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4770000000021da5818dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce800000000a4b8f83f04b7dcdd00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c45bb44b", "prevouts": ["724b5b0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "d90c3500000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb", "294550000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "697d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b581e7745017096cad4c25a994b7b5383cb3ce53d5d9c99862d5778426da160494dcbc06ccecaf65037be0509f5fea40d87445fa254b78f124a4b8c5e16963b53b3c2b944ff5e8034ac7518513c5ca10ab4eec025a723136fa482de383e24ff1"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f50b5b5da10eb7d793ae86878c22918a1efc57934013172b8e322c1c64be3917945c33b167c9a8798707088659264fefaebd6f00f5f412ec268481dd4d0e7e4494dcbc06ccecaf65037be0509f5fea40d87445fa254b78f124a4b8c5e16963b53b3c2b944ff5e8034ac7518513c5ca10ab4eec025a723136fa482de383e24ff1"]}}, diff --git a/txscript/data/taproot-ref/5c4b2bd5199eaae65eb1b50ff2282715f285525d b/txscript/data/taproot-ref/5c4b2bd5199eaae65eb1b50ff2282715f285525d new file mode 100644 index 0000000000..0a10994ca1 --- /dev/null +++ b/txscript/data/taproot-ref/5c4b2bd5199eaae65eb1b50ff2282715f285525d @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c100000000dd110ca0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caf00000000071f80f3030b996000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac9d000000", "prevouts": ["b4170f000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "b5bd530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e1", "final": true, "success": {"scriptSig": "", "witness": ["2ff700f146833e50bf28334e5610247af6f4b97b05b9a0f0f79314c30ec3dbb53cf80d6a86a136445362be1371ac101792618ef950a8b828a1a79a3f9d08df9e02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8c2014f4da6230928cd9e7530606b065a82c4f8acb61cf3deec20497ad64645c1f39debe8750c4e6b7f811cf7ec1dc660416613234a87093140313ec80dfd197e1", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5c4e02eac5ec6bfd2aacdf25eb5606e7f1f8d245 b/txscript/data/taproot-ref/5c4e02eac5ec6bfd2aacdf25eb5606e7f1f8d245 new file mode 100644 index 0000000000..d5278a3d1d --- /dev/null +++ b/txscript/data/taproot-ref/5c4e02eac5ec6bfd2aacdf25eb5606e7f1f8d245 @@ -0,0 +1 @@ +{"tx": "d3c407fd02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf59000000008d3110a5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce7010000001d03cbb703ec85ba00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc53000000", "prevouts": ["c7df65000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "38585600000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100851e49b2e0a4973a6592637503937aaf2597822f72b7aa9873f81ec9ee3328d0022031d016a543c18c5389e366497d5e3c54b26e19434909d55de0ccb8f81b7cebcb83232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "473044022042cc82fb21e88a2ff8018f737d29058c0b0fde64c9e250f39f6efd3b4d21e33f02207d4262b4fa35aa8f608ba21c41583224d1f47160484c0dd731258526e71bbf6d83232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/5c58efa0b606fd3a9f5c4149f78312e37884f070 b/txscript/data/taproot-ref/5c58efa0b606fd3a9f5c4149f78312e37884f070 new file mode 100644 index 0000000000..5838f8e974 --- /dev/null +++ b/txscript/data/taproot-ref/5c58efa0b606fd3a9f5c4149f78312e37884f070 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1e000000007f87f9d660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bb01000000b381a6b20118072100000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac24010000", "prevouts": ["ef6d640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "076c110000000000235a212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_15", "final": true, "success": {"scriptSig": "", "witness": ["90aea01f2cc4cf5f9a75da5cf2a9c5a7fc3db62029872ee27f99e04c9003cbc137f8d0a8279114a4ab44e670db2c6ac13b3ac8d854a728f8d3863e6f1dbdfdcb"]}, "failure": {"scriptSig": "", "witness": ["ad198d9bf156fff4f37ed51c0e9b879bf2428f2658985b472707f7b6ce48d5de7677fe72cd05041414d28580686ba9e6083a804540325d847a3af0c54b681cfc15"]}}, diff --git a/txscript/data/taproot-ref/5c7526188d4edba67f479317b2da9ebd815e25d8 b/txscript/data/taproot-ref/5c7526188d4edba67f479317b2da9ebd815e25d8 new file mode 100644 index 0000000000..4090f4b31a --- /dev/null +++ b/txscript/data/taproot-ref/5c7526188d4edba67f479317b2da9ebd815e25d8 @@ -0,0 +1 @@ +{"tx": "0aaa8a4802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c72000000002635b9ba60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701802000000ce18a8af021b536e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac0651971f", "prevouts": ["36135f0000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a", "19de1100000000002251207ea7068de42e8dd8ec2d889eabca72799b94dd329861089e307e247da6412b8e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93618290ef83a776d63c84ec09e6a4fe5a6d7e5ff269dcf5fcfd50fd6b72ce0989f"]}, "failure": {"scriptSig": "", "witness": ["6a79616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/5c82173fb5f60e67f6c570773d0e7ca501b2ef2a b/txscript/data/taproot-ref/5c82173fb5f60e67f6c570773d0e7ca501b2ef2a new file mode 100644 index 0000000000..8ae9bc13ea --- /dev/null +++ b/txscript/data/taproot-ref/5c82173fb5f60e67f6c570773d0e7ca501b2ef2a @@ -0,0 +1 @@ +{"tx": "ad9cd02d0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270920000000053c5d9ebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b30000000008440aebf0409af2f00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487cb000000", "prevouts": ["15f4120000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491", "d2071f0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["95", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045cf76285204aedeb2e654c32bdcb90a470f0de651bfbe7b8c0c018e8a9ed468384d6fbd68a9aac62cc0fc4848936fa6d465cb32a19d5a751074f74d9c4f7fb368ab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e461b72f89a2c16bf6a5015001c0ff63d37cf9f24e8cabb5685a98f400e46d3aadc7c8b3bda8f17728820267d55a41d559bf30f92e294931cb4fa644579829c4d4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}}, diff --git a/txscript/data/taproot-ref/5cb8c6d32062773a2963b39820bf5c9c9d4d14f4 b/txscript/data/taproot-ref/5cb8c6d32062773a2963b39820bf5c9c9d4d14f4 new file mode 100644 index 0000000000..0753b7868a --- /dev/null +++ b/txscript/data/taproot-ref/5cb8c6d32062773a2963b39820bf5c9c9d4d14f4 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb201000000cefb2422bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfba01000000810ff78403a63af100000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac7eeaf121", "prevouts": ["54e3820000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6", "8c2470000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/minimalif", "final": true, "success": {"scriptSig": "", "witness": ["9b978a2871d60b5b8a11ae11e1772b43cce1611b53a5a2c808afd6c82be7a7e300cbd348c33dcc6f0762a107aab5305527f30be20afd52ffb31283fbbe819149", "01", "6320871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac676a68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692f0de23ee769069055d0d6d05652e1367445947e897223d0b74ba21bedb5258c23c60128fd3e7af8adaf4abc6718bf379ce4956c06c6d05419568a3b7fbb4becdfa5022fbf9ae5dfa56f4098acf4285bbe92d9aeb187fa2d4d396f6e0eee31df9d9ff7331949f40b876b1f64f1a10013ac65e222e2c8b225fa80db88dddb53aa6a2d9e7459765b4c09c28753bc2ff55d05ebac69a2359cac2688619c9c27618eeb68ce69b97818447ab7b9a4ba90bb798d21d9027f4de024baf5f3b5f4da875d446577c2ae0ff5873a151ab353523af1af4fb00651b9bde1c1989520e7d338bffb609e59d45c7d1e0be4118ae582299f3fc1b7f496d16d6ab2d0d6e0f7a455128ce34dda559eb1787d0c8deddf8f5f19f9fd4c2ccb2eb142b7063fdfa79ad71051bfd8661ff100df5daaf9353084b6d3751b20c475840529a2a7efac33ff2efdbb6b7c86f986531e7bd2af85df536ab9da539cb9ad98883aa4960532e755ead635b927ce0af32fb24943035d26d0ea88bbdc698d8d4264beb9c7e8103a368881360dc44ae3d69de3386cee559eb49e6c76a737e105f9117431d64c73a13a31f98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["9b978a2871d60b5b8a11ae11e1772b43cce1611b53a5a2c808afd6c82be7a7e300cbd348c33dcc6f0762a107aab5305527f30be20afd52ffb31283fbbe819149", "02", "6320871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac676a68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692f0de23ee769069055d0d6d05652e1367445947e897223d0b74ba21bedb5258c23c60128fd3e7af8adaf4abc6718bf379ce4956c06c6d05419568a3b7fbb4becdfa5022fbf9ae5dfa56f4098acf4285bbe92d9aeb187fa2d4d396f6e0eee31df9d9ff7331949f40b876b1f64f1a10013ac65e222e2c8b225fa80db88dddb53aa6a2d9e7459765b4c09c28753bc2ff55d05ebac69a2359cac2688619c9c27618eeb68ce69b97818447ab7b9a4ba90bb798d21d9027f4de024baf5f3b5f4da875d446577c2ae0ff5873a151ab353523af1af4fb00651b9bde1c1989520e7d338bffb609e59d45c7d1e0be4118ae582299f3fc1b7f496d16d6ab2d0d6e0f7a455128ce34dda559eb1787d0c8deddf8f5f19f9fd4c2ccb2eb142b7063fdfa79ad71051bfd8661ff100df5daaf9353084b6d3751b20c475840529a2a7efac33ff2efdbb6b7c86f986531e7bd2af85df536ab9da539cb9ad98883aa4960532e755ead635b927ce0af32fb24943035d26d0ea88bbdc698d8d4264beb9c7e8103a368881360dc44ae3d69de3386cee559eb49e6c76a737e105f9117431d64c73a13a31f98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/5ccd74670aa8f9270b7b6d1ec35f26366e24af92 b/txscript/data/taproot-ref/5ccd74670aa8f9270b7b6d1ec35f26366e24af92 new file mode 100644 index 0000000000..b125013e11 --- /dev/null +++ b/txscript/data/taproot-ref/5ccd74670aa8f9270b7b6d1ec35f26366e24af92 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fe01000000955e53b2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4701000000658363c5011e667c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e705870958", "prevouts": ["b6c04200000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "09067000000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c84c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93666ea2a418f0de61648f1846bcf7f8f7eac0e21721710bf1aae8a61bff50d06c920e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b553f13873b7614c747e02d52f281322dd98cc8d4ce789920cf593b75c6f05693959a095ba405700a8bdcb88c47f737d45523ad768f5b3698c80add34f2e764b"]}, "failure": {"scriptSig": "", "witness": ["4c52c8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cd4dbe16911bf8042e53b5984ba25563e24e4d01fb5e320bf03d1b64849c9db7460b19c0accce5a24a056b98cce949d671afb14dd91d0cbdd469fc3f22c90b1553249301ac20ee33639c015b4a618b106ac87c8ade2ff7aca8998bda2366a260c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}}, diff --git a/txscript/data/taproot-ref/5ccf6b63be9a26dc12ed0d8d9fcf8f9bd4d32aae b/txscript/data/taproot-ref/5ccf6b63be9a26dc12ed0d8d9fcf8f9bd4d32aae new file mode 100644 index 0000000000..a9982488f5 --- /dev/null +++ b/txscript/data/taproot-ref/5ccf6b63be9a26dc12ed0d8d9fcf8f9bd4d32aae @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c900000000e4d8689fdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2601000000013a04e50458d53300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac3703122b", "prevouts": ["ff541200000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "f15c240000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "847d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faff78d21b135ee37de5fb006beb46b85f4aedf8bacb6598da1f15171cdf92c209c568c76d6b344a062dd798f6575db1f1731d6a7ca3f2682e7e1b801cd94d3826"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c194e7775fd7c80d883f2d740f9e56e49ab9a06d8b2a8d7428d3ae945cc345b376735f386d1a4700f0e60fd19c47be953169b4ae01039887cebf253884ac2528c568c76d6b344a062dd798f6575db1f1731d6a7ca3f2682e7e1b801cd94d3826"]}}, diff --git a/txscript/data/taproot-ref/5cd441bea952394300fbb2b175630e939f70734a b/txscript/data/taproot-ref/5cd441bea952394300fbb2b175630e939f70734a new file mode 100644 index 0000000000..02afb63633 --- /dev/null +++ b/txscript/data/taproot-ref/5cd441bea952394300fbb2b175630e939f70734a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c63000000002fad8be6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9201000000a4949ed304f066a70000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcffb82f2d", "prevouts": ["8fae510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5ed3570000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "", "witness": ["30440220525a7845ce4b2f5390c5b7c8b9c0e78d50a7d94af7d53bf7f1af09b52160a11e02205d5573f2e64a87e919a821d051f32c0e44ce7b75eb0c647b09203872003b0abb81", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["3045022100e965a7e9c14fd31cabcb120624d120d334fd2f3e2eea64998f23d3e0f42f94d6022044703cdd9b3d1c0fa60e96ae026d437c6919a9c6124b6aa4ae6d598a303c8d3281", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/5cd9d11e72f21213a0cd5e3b000d85ffc71a267a b/txscript/data/taproot-ref/5cd9d11e72f21213a0cd5e3b000d85ffc71a267a new file mode 100644 index 0000000000..25ecaa257a --- /dev/null +++ b/txscript/data/taproot-ref/5cd9d11e72f21213a0cd5e3b000d85ffc71a267a @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c100000000e823d301dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc801000000d7978e97044cfd5d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac13000000", "prevouts": ["01ee380000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65", "2cfe260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c4", "final": true, "success": {"scriptSig": "", "witness": ["c1622e178ad7a6967ba48e5b0af3b29d709f4d9267a4fbe7a3f46b215849cc8f5651ceac82571931259ff1713ee50f720a1b1dfa57174be82f41a594e668597001", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["92133e4dc13ef643b6e4566c20e64b0cc9ad2c295b12314562b4b6538f708259e0f475f2d753002b57461f2bcd4d3799a9f0a237820010316e4fdbe9c8dcb8e5c4", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5cf79ca7fb6c27351843e8929c62c99f6d116b3e b/txscript/data/taproot-ref/5cf79ca7fb6c27351843e8929c62c99f6d116b3e new file mode 100644 index 0000000000..0cfab35907 --- /dev/null +++ b/txscript/data/taproot-ref/5cf79ca7fb6c27351843e8929c62c99f6d116b3e @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7e00000000208666d98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cf01000000b7b13eed03661d95000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acaf000000", "prevouts": ["96b259000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "a73e3d0000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89e517178a4498250bd09ce9aecd8afa5f6f049a9750e0fcac48ec3d6edc1b53ae8f45a3ac55dff4b7d62b0bc42204f13e92c55212ff162d480a58edc7717abc8"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368cdf980c8580c893c053e8f36fc601f79605cfc76c6b11fd2e35e7b5e626ae0524e037abdf69c22f44b0c591ad93651f749184eaa819a8a63a5d4092bdddfb78f243c72f4e074898aab8058b3c73fee97ec3b9723e213834a8398e97170c1356"]}}, diff --git a/txscript/data/taproot-ref/5d460d2d593010e8b116c549316144cec213da3d b/txscript/data/taproot-ref/5d460d2d593010e8b116c549316144cec213da3d new file mode 100644 index 0000000000..b3f530004a --- /dev/null +++ b/txscript/data/taproot-ref/5d460d2d593010e8b116c549316144cec213da3d @@ -0,0 +1 @@ +{"tx": "716b8db702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc4000000001e7a2ac28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40b02000000e32d47c101a5858400000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac93010000", "prevouts": ["3afa6c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e140320000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_59", "final": true, "success": {"scriptSig": "", "witness": ["2be37752447d6d3e61d976dcf448cedd3898004706b07bdf763c3498f8f1eabaffca0230eb3385451772fb25bfc84b34af12626e5c57f422a290b3163278c8ca02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ff05145a9ee0ec2d634ba7cb1b257143a03a283099a9f46575731511ec4d29e376b63bc24295183e376b83c8f422d3bbadfbc8f87530bc51352c30d068b606a259", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5d547488bdc33c4ba9f4eb64d9e510fe10c43b64 b/txscript/data/taproot-ref/5d547488bdc33c4ba9f4eb64d9e510fe10c43b64 new file mode 100644 index 0000000000..585afc76b1 --- /dev/null +++ b/txscript/data/taproot-ref/5d547488bdc33c4ba9f4eb64d9e510fe10c43b64 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706101000000587c2fe78bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c428010000007d05a6b102dfca430000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac31718742", "prevouts": ["d4c011000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "f5ed340000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/checksigaddresults", "final": true, "success": {"scriptSig": "", "witness": ["8dd4b96b4c1e16293541ea54ec6b33c8fe9a736c9f4696ca6656bde5a56404787c01f9fdfc65d8b8d90299e328e7a8496f72ae9827624ab8f344210387948ebc", "01b820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba01b787", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a4ab26b19b12dd5ed84675a14c998105d6f885db851af25affc21adf58dee419d170c934e59191828af4b443d621af5306292ce84d9ec7d56e4d5e95f4a2b883b6fd696714014486fd7f93eb277485a7e6b2ad9076f6f17fc1c22a649c512cece24022bfb434738800d6aeadbb65c0b5f1c54fd97b098ababd1df24d7362e80f41af64fbf9620aa43b24a95927199d6cd96f713b6c21c4241494f6ef0a4794b137108eeeef0d1cdb0bf8b9c7668f98c08793001c20de814582aa46fe17366f71bdfc32c1e1c145969abcbef65c26a893c9816b7a71a91b71dcfe4a49fffd792905e89fbc0a67267d9092cb76689d3f43e2e6846ec5193713df91969e861cb60c31b4d84c9ed58356d00f548e6c0b7494dab0ae598e30a63a373db1671630b0e008f7f368b69fdb42cf55796ee854208b1524a7b7ad1fac452c6296b4ad4fb087b0a6f9680ce7f5ca5bec9338fe334e6832114c99db2b4b78f7605856e14f0f922c7dab2635ca4d983bce69908efc2d6c8e3a4e02d107fe54b591d6c8cbc0ea2e862ced977f81641729beff04e69bc449bbaee4ae229138f125e8f575c30a32bf5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["2aefe7af812ccdcfd31cc887cf61877f9006edaf7684a4ce32c2629479aa31cce8b8b9af7f42bf706093e8fda891a7f683bf43ed7a22b722824351e67798ff31", "05000000800020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ca373a9284d9516d65ca57d42aeefe677abc27971d99a0e576ea3e033f0e37e18e226a88f8de1ffdbf8653e5e5c99d8ed6854f82ec6180716e498db4090bc6632eca1c10f6e29adacebae9c18d35728cfda46eaa96261d129acdc4b9e453cdf8e00a42427634156bf48aae55d12e65b2b6cdc4abb92f4ff102785641e1ad0d5b12d8443b4b548fc10604f059128cc28d89f7aec36eeec0a36f070495d2024be6b4d9c782523004c55b59cdfe76d2b17eaca8dbca1786e586c09b966ccead252fef997c426d9e949c5a3515b5e0042d45e4be44351c6f149d4fc020759a6f4b0d67374e7caf20322e7084d9546ded12af1d1c5a4e1ba9f0c95d59cab087df6e422f503472e6304a227f15c06c4bf90b77a0576afae68bfe51800240c398f7b74c3dfc6c9c46ba420c22a4b23a6e73e8909bd27f9a6cc2eba3b71442d590039c84de8a0e517ca4f4c263b0ab1b11f7cea6a468382fed8b4a21a3e6c2259e4be3735e9e781db25a304cb2b703fb372b5fb8e69d12880f4d83920da47a594e16bf0d7b8ad7363e0a6ef78402a031bc0a044f5a7e6c01a5c111176c74efd8c6d7787a57b391dd67ba025b9a60505ecd7fa3b5ed0808730285af9f495e709e1f92ab88b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/5d5955b5c12cb917cf3b4b20cef145f61555cebb b/txscript/data/taproot-ref/5d5955b5c12cb917cf3b4b20cef145f61555cebb new file mode 100644 index 0000000000..bf74245f6b --- /dev/null +++ b/txscript/data/taproot-ref/5d5955b5c12cb917cf3b4b20cef145f61555cebb @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c890100000045a341c4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfd010000000a8f2aea0184814a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e742cdbc45", "prevouts": ["97085a00000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a", "44315d000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["304402203a89f73cc889ae00a7a48cabffdb45543b73bb22e77523cd9d61e5ef9aa5aac402204c6faa9abca40836d371f2854dd6e0a6b4d7964d9d309e212607488b480a3b2d5f", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["304402207ca44b668c8c91a37d7b5be371dd0ed908d5974cfded513072e97cc55b15d0700220773f9e8c44b697a34f30aa0bd2270f130932ff5a63995200cdaba8bbdd7a910b5f", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/5d5d395b7d0d39e7e061299a0ac6d887b277e7f6 b/txscript/data/taproot-ref/5d5d395b7d0d39e7e061299a0ac6d887b277e7f6 new file mode 100644 index 0000000000..fe4c561513 --- /dev/null +++ b/txscript/data/taproot-ref/5d5d395b7d0d39e7e061299a0ac6d887b277e7f6 @@ -0,0 +1 @@ +{"tx": "bf72937702dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c91010000006ea375f4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd700000000a67e3fba04f02f8000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7afb7485f", "prevouts": ["158b5f000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "80a3220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_51", "final": true, "success": {"scriptSig": "", "witness": ["d53cb2aa996dfed6f2b90f6d1a3cd65f1f2cef383e2d9afcc9f36bda76fb7b12b810ddc1e47108eac36467f0f2bd088272242fc3442ec836c51623ac223f5114"]}, "failure": {"scriptSig": "", "witness": ["75c3dacada1a0aa2159dffb05ed62dfc83c7beed10f32d3730c2b4fff673935afa789a917e95169b6e082cf4a51e2986cf01ff022521149c24caecfc2b592eba51"]}}, diff --git a/txscript/data/taproot-ref/5d67205500c9fd9a4b6a49b76f5ba2c4bc80f718 b/txscript/data/taproot-ref/5d67205500c9fd9a4b6a49b76f5ba2c4bc80f718 new file mode 100644 index 0000000000..b7a9185fcc --- /dev/null +++ b/txscript/data/taproot-ref/5d67205500c9fd9a4b6a49b76f5ba2c4bc80f718 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0b020000000f6e3dab048ef750000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc7a814257", "prevouts": ["7cc753000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09029b250e9ddb4ef1d24523febd77857ce81814cae8c8a7688cb148874e1f1699616564df763ad6557f93a8243f6be9c3bae5eba87a9b1292c300e8180356d7f29e9fa7a022617ad7b782f04210523d7fbf71ad169d3372aebb443456e9630dc3b7fcfc44ea2e3f15419526b0a3a4f4ef10fcd3f4f5a9aa832e56eae1d76e6b6abba102b770c03f482fb69852509b7a45fbf3ec4e804048039872102450eeaafb9462de68efdbe65b6a5909ffab38f456c099cd94d5140e9e854f6004df2d6322f8f56f6be1c098204aa9464ecec7065bf74d89b9fec7116415bf3ea6dfb479474eb476f42743ec93fb34eb28f79020408b3f8723752b4b96b5b6808f17f803e4242a933f7a1432f6eb7d20fc2428c7ef9fb8aca69ebe66333ed68624d8757bffb4d3b70dea1544542640721ab736947f6a6c717f4a6a995dc385f658aff44b23f3a8a9214a2777dbbfc1cd761f281918ab94bef657db1db91f25f7c1b05880a9ff9c7ebdcb9616ccec23ba242fe3234bd2ab2fc3ecb4393f19b1d690dfcfb151fcf4c92a1ccea68b040c9eaef504eda43ecd157e02d309f378fea2f71a336b6704d5a0824f321c8ad90f6a81c6ff5fd53acd2f574c38f82535ceaa092867eb369e3aa874a13e1a6c6f26c397fa6cccf855002b3ebd05cb6aa4ec96c27d63f395643250d44712c71d4772d64a35a35087a68859a234e5e86180ea36d4a78f9cb3a10b23f656e7c041912175bc", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c671f46b5c4a8a91a91b52498ec1d50afa67569c2c9995041aa6fde798981e9899aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d5154a115ce154f943bf3cf8f46c74cde664956f57cd29b00bedec3f53c1a73157ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}, "failure": {"scriptSig": "", "witness": ["4d0902ff4628ba536955c325b011147fc1714a37f65ab397f7f99f0f14ace75448fd053fb38b0ca943cc4114eec77cc69c05760f01c70e1b9d5495b22ccdc96178f0b85e74c60078796421d1b77b50690deb93942db077130c3b47abc608e2d4c9c85ea2fb95e45183804e1893012c7f7e596047985120b977a82e6ef674a119cf06fb5198fa0e9330ec0d890651d2ce528cfec82d1549726a7a9c6da625bbe28ebdc708f5b98248534132faec965e5c6e7016b07b233cd94316cb788bf2fb74548d4c1b2e574636f8b171a29f898bff3134bcd4e4aeaa939111122f26ba9d829816f9333dc417574e74ce938da9f2cf2d1867a30afb6c6f1a1ebda548215189d43b3938b8fadb88e87e2f5d181c13b7a4488182983f0b695a9cb40113dfc996e57b6018ed4040bbdf6cb7be2d8d05f438a3b10d08b6e882e330977774b9447934727e5b5bf03540680fccb597f108f6e4340365bbb2df0a862bea9ee4286ac6bc3da1ef46f60318be286e333f0c1e44da18034dfda0fbf640a9ff6f3a063ae301d8b44eeaf2b43eb89b05c53eeff7b438f251f3b98d623f0f553aeac70e5480b83986a3cf6ba27679462f67083451d924ae1bc672e1aba419c8ab576cb3bff9a7a25aeb103121f0bf771b209daa74659c937cb4427b7faa8e39c7dbdd0c34a0000b90582fd0928d598e9a02ad80e2efb867ef12d921cb33de772ea35f249cb8155c70c73a889bded48133f07561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93617f3d357d262a0ace1eb8ae0982017753a860c00b575d1442d59c97716b7cc976628fbf290b9055f1812e9325160cdda478fd06188bac581533b5ab5319162eb04966f092bf1e4b4348fca11e7254311373308f7fc15e3d44d6a2afffa343c9657ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}}, diff --git a/txscript/data/taproot-ref/5d979fc0c97f4b30b22b3b449446ef2dad2f94fd b/txscript/data/taproot-ref/5d979fc0c97f4b30b22b3b449446ef2dad2f94fd new file mode 100644 index 0000000000..c7cccd89bd --- /dev/null +++ b/txscript/data/taproot-ref/5d979fc0c97f4b30b22b3b449446ef2dad2f94fd @@ -0,0 +1 @@ +{"tx": "3266ab6701bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0a02000000e846028402651c7300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac25010000", "prevouts": ["1195750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_33", "final": true, "success": {"scriptSig": "", "witness": ["f3646360c3bcb95287fb9ad8eb9c3e93ef3264837f7e1fb204524db415b6331de3502c29ba57470dc285c872fda22ebb207c509de013d6ee82de550bc7d76e4201", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f136f633413d0715a2d15cc0725683fe4e2735a7e56624cd1862384ecdd22f7a8054412af2ba6c3c43735223ab0254b075d8645762d536ebbb5e4bde77ce07d733", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5da06db4c347f603cf5309c3456c26cc7ff974ad b/txscript/data/taproot-ref/5da06db4c347f603cf5309c3456c26cc7ff974ad new file mode 100644 index 0000000000..4d72f3d8f1 --- /dev/null +++ b/txscript/data/taproot-ref/5da06db4c347f603cf5309c3456c26cc7ff974ad @@ -0,0 +1 @@ +{"tx": "b76923990260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270be000000001e0361fa8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40c02000000c541bcca04e7f550000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987fe5af33a", "prevouts": ["2373110000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "71844100000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063cd68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c9423051280ab0ba07278ceefb01ed123f8b9963758d62a87c192126ecaf00f1e22a66b502779d6b233f9a5a075cab3b2a5d3e595dfdfe607248b2d2d8734c7b9f4d7ab890a2001a7be6cb25cf630fcd24657943ff80a7c5a11988ecbf9e80e4620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936498acf89780080a2cd57bc0c10dce52b06266470b3eb2ef99b486159ea0e945d20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e11863a41bc3dc2a7aa524e62e66740ce82713c2a995d68e9803c1affe373c89601029910a453e765cd82c29c3b576a90579a453f3a941b6b6175fa922e9a13196"]}}, diff --git a/txscript/data/taproot-ref/5dccc42ff618aec2747273439401c4901ac182b8 b/txscript/data/taproot-ref/5dccc42ff618aec2747273439401c4901ac182b8 new file mode 100644 index 0000000000..ce174cbfe6 --- /dev/null +++ b/txscript/data/taproot-ref/5dccc42ff618aec2747273439401c4901ac182b8 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703200000000ac43b0a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2801000000ab411cb402bca15a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963af0dd3e", "prevouts": ["d08e120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "319b4a000000000017a9141d8eff3030620b266a8bb5e50900ecd7b2ab72da87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21561f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["974d25958931043c6b7cc3344c248be7a6ed9e6277f40fb672a1e4edd83a2bdff2a10e66e172c91858921ab17edcd9b8c1dc8a065c4bf5c8b78ffd8da66e47a6"]}}, diff --git a/txscript/data/taproot-ref/5e1b24b8be80cb985494cc5e6aad6e0169f302a9 b/txscript/data/taproot-ref/5e1b24b8be80cb985494cc5e6aad6e0169f302a9 new file mode 100644 index 0000000000..615c886ba0 --- /dev/null +++ b/txscript/data/taproot-ref/5e1b24b8be80cb985494cc5e6aad6e0169f302a9 @@ -0,0 +1 @@ +{"tx": "760cfce6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41e020000008082e1c6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1a010000009b10e7d2012db07a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478726010000", "prevouts": ["2967330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5d51770000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_cf", "final": true, "success": {"scriptSig": "", "witness": ["e4f84cbed1be1e786bb3b34e98127de2b0a6a7259622d003b8fce943f9b980b6af53025d56fbb380e3fa14b2ee267aa278a8af8ab16b81a9fddf10118423228a83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["dd21672b844dc5eef5313357d3ea45619805fc089aa275e3f4ebe4be556d468facd4bff2d5e9e5bf65ab7e678d041b43511869966773f5f1034f39c0c36890a9cf", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5e29c824e31a38432a78e51cb6163effbc1b7632 b/txscript/data/taproot-ref/5e29c824e31a38432a78e51cb6163effbc1b7632 new file mode 100644 index 0000000000..524836d159 --- /dev/null +++ b/txscript/data/taproot-ref/5e29c824e31a38432a78e51cb6163effbc1b7632 @@ -0,0 +1 @@ +{"tx": "324e93d202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9a010000002b5640d48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fd00000000938fb6ab03c0a05f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca2c5a437", "prevouts": ["7def240000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "57833c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c4", "final": true, "success": {"scriptSig": "", "witness": ["9600600e60ef1b30bff3a4e3b3a114d858e47100a069961c8c27151805892c80a161aeb9bde24150e004968b5d9c7660c24390db520b0990fa4379e4abc4a7eb03"]}, "failure": {"scriptSig": "", "witness": ["4813c8774af586abad439797395c106945eab2540f56d547976d0055ed4118881540eeec74cc6112ec540faf8eedca83afb82fe880ff5179c4d46dbdaf2f5ed0c4"]}}, diff --git a/txscript/data/taproot-ref/5e5cf1d19425ce321d71cf332626bab6bf9e5c44 b/txscript/data/taproot-ref/5e5cf1d19425ce321d71cf332626bab6bf9e5c44 new file mode 100644 index 0000000000..5340436649 --- /dev/null +++ b/txscript/data/taproot-ref/5e5cf1d19425ce321d71cf332626bab6bf9e5c44 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf92010000002d7002b0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb100000000c01dcced048b91e100000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79628eed841", "prevouts": ["b3f9850000000000235e212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "aa485e0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["b4f086362b79d90b8b59621bf6f80fc3c9e75f17a9109a8b9b2a68fc59cb536dafce45d091db8e55c50b7793462c89389e9b46a622028e2bbd3eff32815638f7"]}}, diff --git a/txscript/data/taproot-ref/5e7998196110af78479912905025c638163deb00 b/txscript/data/taproot-ref/5e7998196110af78479912905025c638163deb00 new file mode 100644 index 0000000000..075753dd4b --- /dev/null +++ b/txscript/data/taproot-ref/5e7998196110af78479912905025c638163deb00 @@ -0,0 +1 @@ +{"tx": "97ca34d70260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127044010000004c539de760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f0000000002921dd9f0244a22100000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48781000000", "prevouts": ["264b120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4732120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_41", "final": true, "success": {"scriptSig": "", "witness": ["de8089d8b74361b02bf2ec25842ca3a735e650a4ff654f87d7495dc0acb6f37b95b4faffd1186a23dcb3876e30f8d0b9d117f0d1d100223564dc2023bf0c6a2083"]}, "failure": {"scriptSig": "", "witness": ["3ae6dfca518aac9fdd2913ad68ff7c8b33b1f65ec7113cc40129c1725712e791c1ffc54da9a0724758798822f1a0e1aaca6389d0d41ea32ea9ce6ee2de5cfb3241"]}}, diff --git a/txscript/data/taproot-ref/5ec7eb46ae8e0891018b9848bc2341e3ef6ee62c b/txscript/data/taproot-ref/5ec7eb46ae8e0891018b9848bc2341e3ef6ee62c new file mode 100644 index 0000000000..c03c641ed3 --- /dev/null +++ b/txscript/data/taproot-ref/5ec7eb46ae8e0891018b9848bc2341e3ef6ee62c @@ -0,0 +1 @@ +{"tx": "f72903db0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708a01000000c27adeb40243be100000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48716030000", "prevouts": ["d4a0120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_37", "final": true, "success": {"scriptSig": "", "witness": ["a1a7efcbefdd3d042f1fe407442b72f7e36b1ba5a5eea8d82963b30e441d87f6eea093896f80738800382daf3a5a54da32c954b3d732d5b24fd22de8db29be8e82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7415f6159d193def5f543889775938ecda7491c83f1f4b5ebb21553fb0bed3f6ec0523428996d3b31a9a25fb058a2c45c2c13e5b014a06a66b58e7217a78554637", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5ef0bcd2fc8dc128e8583e90e1d3848ad698670d b/txscript/data/taproot-ref/5ef0bcd2fc8dc128e8583e90e1d3848ad698670d new file mode 100644 index 0000000000..19dbf9fa65 --- /dev/null +++ b/txscript/data/taproot-ref/5ef0bcd2fc8dc128e8583e90e1d3848ad698670d @@ -0,0 +1 @@ +{"tx": "971ef45d02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0e01000000bea1139a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127071010000003f3d64ce026c8d91000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6b0faa40", "prevouts": ["a3c78400000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "88c10e0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_csa", "final": true, "success": {"scriptSig": "", "witness": ["acda7a718582f92aee3759ab0b33eb532ace3f5e408f31b9ece6b7d48686d7c5d3694eda712aaf3aa86498832245544cac0f51bfaf3623b0f726f95b97c2895d", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439befee6fda3cb49175c9fcdc99039bdef34bed6f8c885214259c1ab60f6e0548afc8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439befee6fda3cb49175c9fcdc99039bdef34bed6f8c885214259c1ab60f6e0548afc8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/5f065a6b9d7bf300aef6fc736b6256c582fa075b b/txscript/data/taproot-ref/5f065a6b9d7bf300aef6fc736b6256c582fa075b new file mode 100644 index 0000000000..76fd668984 --- /dev/null +++ b/txscript/data/taproot-ref/5f065a6b9d7bf300aef6fc736b6256c582fa075b @@ -0,0 +1 @@ +{"tx": "7647552a02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfc01000000b71eb1cb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c489010000005bb7d7a804ae458a00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4dab3f4e", "prevouts": ["3c0e530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "85f03900000000002251201e1e43c91fff99f096580082345e8b6c592108fedec9f6a82472097138f3a147"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["542000d72ec43c4f8d706ce1405158876fe0de3e7b672a19800145de6bf211becb9ee8ff74f3ccabc3ffa061d019bf7e00828f5a4e0d54c62b8ad390217c598b", "b71a53f8d1ce3b1b4918fa70f5b7ae6e88675e644e955503751636355bb9e28ee41c315ba7b125074f36f2745c88cd10418f6867c98da30c0bc2c8cf74fcc3d4d9342f70d157a2506b0ecbfdecacac3a8e6e6e60a9c49491d4320e3f9494242fcda484aa13d6139ff187ce1d7bd0349b1fa3c89637198b10818fa758fc4f6f174adba206a83d88306e24aaced754ba733b4349c06e795366e8c94cadda1ed111c952f951047587aca4b64c5ed44d93378c1b972bfbb37c8a14d0e638c47c8f47d4deada61affc61872941d8ad3d1cc3193b645df427e43ef70a781fee7680575", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365c2ab5ec9fa482b6934284b5609962a0afc3aae20b96a93e54b5fc5dc02f16c60000000000000000000000000000000000000000000000000000000000000000467ba320cf76754858afbd0a410437dd45fec020789ba961ea4172c517f33629e5858531762eb6a698a1e3be7c8affa2992e03597c26e89af62e5a147b5ef486cb7eacdc29d885253cb6dc773ea1c82343fe772a2223138d156f7d07bac5cf2770ed531f6f86030bc09c893afdee98e07365ae576d295e36fde41ff5fa3efa73ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe93c61bf449d1ca5ba09a216d6cd0cac8515bdb9901cd5b78b17567dfed89ad71ee7dfe112bf56e87fe8d7e87f6c04ca1d0de94fff41d1c5e23f1527525e2e2231d4b39d818b1eb61c090a0ee418dff9e2ab8f7a724a413571adfa69b3fb6e40aaaad9320e8f9ad462969b6aa096cd4095dd78ac9a586a2c43a4d0876e9081bee56ebd7b46142dca84cdce3bb7157d0682fad18c765ce07405ecf3278c3ef0aee210a26d72fe0be22d4a0f76a2de486244f2b71417194e5440b7574ebd70d0efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff020115476634b435782333af72ce400dbbdbacdea010bae619d3dbfa76cff88845c471c71870b81acbbb00b4afa4261a91d2a541cc33e35a5f0a79b9c45e3b760000000000000000000000000000000000000000000000000000000000000000a6c1b5866a6d69c6209ad23ef71d6a06094f27450e1b4e032183c409cbb411e78b4a687419f9c4ef9df5c78d65c634c1e27a28ac08f97d687d614b1828bc435c3907dd78ede7d267aaf41d3510632656f8817d048302547a9688ad7c4850539077b7573ecb3d28f5f5b092f4974a8043fef0520670f1c6a3ef58c60a72df8807000000000000000000000000000000000000000000000000000000000000000008837b8b6a3f8983afd89ec084ee3e9ee9c1e23306ccc468a29823f68a71d2c885a4620b4bb81d39d439aebd435b049188fd502d91eb02a197736995b7b681a9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b75fe9679abb4f3ef6c76f8204890d129fe5f8aacd42bf21d24036a60f4b7214e53f9f90c04a88857c4eefd545fa9220383d972e755ca1c092ba94faaf2036e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6ad5cb5c118b7b710a1d7e63045925c542f6c28041121c1f15f1b2d1e7ed743009a6e94f0c3e4bb5520dc8daaa5e4d45e49ef5a62610f471a6d59f01fee05586c53db31f55a06b0dbeb3ecd8b904c596f7f14c356da40f7b46e2c5f3f20ab04fa0a89b0ea28fb713dd005dcf9defc6ded1c1666aee548e7719fe58f4594edf5affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000544b68a665ca4c315187b7d594a11b6095fc679da480ae7c2a5a79b875ddd5e40000000000000000000000000000000000000000000000000000000000000000a2edc52c483d392e19d27b3682e0539df72431c834a1cf493299c3bc2c48e9d5645d79752f33e13ddc7686e3b5bcb624380465814527ab1a8a96f5edd2255ae8c4dced00ac498230e0697e32927170e9b4e2e460d9a8cfe2477e3d1603bb7adbcfef4409233e1d32a0678b176021a8eebb825448e83c35c00f41a3dc14c0fc9e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c2ca47032e82458967123977e9bbed6a974abadd1477333c3cace184e3ac852aec05e2c2462d28b65e08830ee24c33e9659ca7649cc7e79f7d009dacd063380000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa22633b7b435bab136304e1af1fbdc5025b34d24306502d9d142511426e1cca7d3a4a8ee12f2776b9d9222e28d95839c9488639527171b1579145e96bb8bb4872b0935d8ed445848c17b7eae038d9b187cfb460a451b51d2f8bcef01ae97203d0000000000000000000000000000000000000000000000000000000000000000ce277f6aa795245afec21418da718cccde79d6abe906cb7fd0b0b9e7d8bcfee9af00a4b73dea1d7180fc16801899cf312761d03578288f429bf672eecd27857b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7ecc9a2324d4a2e5f2e11299983b026d7107849329dfdac1e2b04885277af1af59be8d4963d61780ff8301985f114a5168d163ba5c0f47cb07f42e77fb5a451704709ed649af2eaaf8a76d81c4e1f2bc9b359aad877a7d544f0da198be4189714a5388f9f8ebee45eb1ad56d0c75f3306214615107988ef5d09f5ed14fa037f76c154f01491897fd49a3f9e1730953cd1e02c1faaa441ac9918c78602713c67ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb92f5d52ff7399a99a72f1736f293950fb057b616bade753d632dc65769a006f", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["542000d72ec43c4f8d706ce1405158876fe0de3e7b672a19800145de6bf211becb9ee8ff74f3ccabc3ffa061d019bf7e00828f5a4e0d54c62b8ad390217c598b", "92f8830adfc90b83d616588b760ee454e07a997960c3f507ac8cfb561e60a218569cfb6c25d11bf935fbd489d8a30b5188ac545841d55f826061c35eb74c0cc1d0800bee575bb2c68143ec3d847f845893b2608e87a1f06d041f1ac0f7787782b53690f9e08e9e3b5d7343e94512cf0efb5a95eaf5205f932e3f9408c266c1617b39aeaefe69d71a5f5cbbbbd01403829decadd0da22097a1d2606ae88a5ed90a18470a1293776271be35d2ca14f7da0d4b9f0eee98a15f1243a834e68237f7427c4e5859b4777d4646ed8489daf898a03dca6063d273e5c1e8c516cf6148b", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365c2ab5ec9fa482b6934284b5609962a0afc3aae20b96a93e54b5fc5dc02f16c60000000000000000000000000000000000000000000000000000000000000000467ba320cf76754858afbd0a410437dd45fec020789ba961ea4172c517f33629e5858531762eb6a698a1e3be7c8affa2992e03597c26e89af62e5a147b5ef486cb7eacdc29d885253cb6dc773ea1c82343fe772a2223138d156f7d07bac5cf2770ed531f6f86030bc09c893afdee98e07365ae576d295e36fde41ff5fa3efa73ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe93c61bf449d1ca5ba09a216d6cd0cac8515bdb9901cd5b78b17567dfed89ad71ee7dfe112bf56e87fe8d7e87f6c04ca1d0de94fff41d1c5e23f1527525e2e2231d4b39d818b1eb61c090a0ee418dff9e2ab8f7a724a413571adfa69b3fb6e40aaaad9320e8f9ad462969b6aa096cd4095dd78ac9a586a2c43a4d0876e9081bee56ebd7b46142dca84cdce3bb7157d0682fad18c765ce07405ecf3278c3ef0aee210a26d72fe0be22d4a0f76a2de486244f2b71417194e5440b7574ebd70d0efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff020115476634b435782333af72ce400dbbdbacdea010bae619d3dbfa76cff88845c471c71870b81acbbb00b4afa4261a91d2a541cc33e35a5f0a79b9c45e3b760000000000000000000000000000000000000000000000000000000000000000a6c1b5866a6d69c6209ad23ef71d6a06094f27450e1b4e032183c409cbb411e78b4a687419f9c4ef9df5c78d65c634c1e27a28ac08f97d687d614b1828bc435c3907dd78ede7d267aaf41d3510632656f8817d048302547a9688ad7c4850539077b7573ecb3d28f5f5b092f4974a8043fef0520670f1c6a3ef58c60a72df8807000000000000000000000000000000000000000000000000000000000000000008837b8b6a3f8983afd89ec084ee3e9ee9c1e23306ccc468a29823f68a71d2c885a4620b4bb81d39d439aebd435b049188fd502d91eb02a197736995b7b681a9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b75fe9679abb4f3ef6c76f8204890d129fe5f8aacd42bf21d24036a60f4b7214e53f9f90c04a88857c4eefd545fa9220383d972e755ca1c092ba94faaf2036e7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6ad5cb5c118b7b710a1d7e63045925c542f6c28041121c1f15f1b2d1e7ed743009a6e94f0c3e4bb5520dc8daaa5e4d45e49ef5a62610f471a6d59f01fee05586c53db31f55a06b0dbeb3ecd8b904c596f7f14c356da40f7b46e2c5f3f20ab04fa0a89b0ea28fb713dd005dcf9defc6ded1c1666aee548e7719fe58f4594edf5affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000544b68a665ca4c315187b7d594a11b6095fc679da480ae7c2a5a79b875ddd5e40000000000000000000000000000000000000000000000000000000000000000a2edc52c483d392e19d27b3682e0539df72431c834a1cf493299c3bc2c48e9d5645d79752f33e13ddc7686e3b5bcb624380465814527ab1a8a96f5edd2255ae8c4dced00ac498230e0697e32927170e9b4e2e460d9a8cfe2477e3d1603bb7adbcfef4409233e1d32a0678b176021a8eebb825448e83c35c00f41a3dc14c0fc9e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060c2ca47032e82458967123977e9bbed6a974abadd1477333c3cace184e3ac852aec05e2c2462d28b65e08830ee24c33e9659ca7649cc7e79f7d009dacd063380000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa22633b7b435bab136304e1af1fbdc5025b34d24306502d9d142511426e1cca7d3a4a8ee12f2776b9d9222e28d95839c9488639527171b1579145e96bb8bb4872b0935d8ed445848c17b7eae038d9b187cfb460a451b51d2f8bcef01ae97203d0000000000000000000000000000000000000000000000000000000000000000ce277f6aa795245afec21418da718cccde79d6abe906cb7fd0b0b9e7d8bcfee9af00a4b73dea1d7180fc16801899cf312761d03578288f429bf672eecd27857b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7ecc9a2324d4a2e5f2e11299983b026d7107849329dfdac1e2b04885277af1af59be8d4963d61780ff8301985f114a5168d163ba5c0f47cb07f42e77fb5a451704709ed649af2eaaf8a76d81c4e1f2bc9b359aad877a7d544f0da198be4189714a5388f9f8ebee45eb1ad56d0c75f3306214615107988ef5d09f5ed14fa037f76c154f01491897fd49a3f9e1730953cd1e02c1faaa441ac9918c78602713c67ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb92f5d52ff7399a99a72f1736f293950fb057b616bade753d632dc65769a006f", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/5f06fb75a8156e71669ca65d0d928c7effc223ff b/txscript/data/taproot-ref/5f06fb75a8156e71669ca65d0d928c7effc223ff new file mode 100644 index 0000000000..e818902f36 --- /dev/null +++ b/txscript/data/taproot-ref/5f06fb75a8156e71669ca65d0d928c7effc223ff @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4f01000000b02ea1ac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e30100000099b12a1b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703401000000cc4e3d950314417100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc757020000", "prevouts": ["0fb65300000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "2ac5100000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "03740f0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082280ecd46f67705e4464578fc0c4eafd6d20a38d5c68152a49fc5d0c6b2a7c87ed2fecf8564d6a652bf0232997fa790ca314d73b111c417284694cd1738ccb12191585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b632d9cf4e2aaebce128d72748304c39681d2bcdf15a688dfe7a1c2c48044586014c92f678e181bf1dc3c918b3709f7d7746b7ca1ad43207ed3c2b1249c00bdd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}}, diff --git a/txscript/data/taproot-ref/5f148693c5a6505500494101603fb4754464594f b/txscript/data/taproot-ref/5f148693c5a6505500494101603fb4754464594f new file mode 100644 index 0000000000..c0032ea05d --- /dev/null +++ b/txscript/data/taproot-ref/5f148693c5a6505500494101603fb4754464594f @@ -0,0 +1 @@ +{"tx": "66a8b84102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf440100000027cdb0cb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a301000000fbab0fe603154c8c000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc74dc3dd23", "prevouts": ["ff977d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8a63100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ef", "final": true, "success": {"scriptSig": "", "witness": ["9ab776834a7d51ff312a4d6538c2e273e8258cba8948a2e491d03eb95a2e5696b4578bdfc01b3ae2f4f313ac488b24d452da79dbb68b097c1b254d88a033ec8d01"]}, "failure": {"scriptSig": "", "witness": ["c6b7be766cff0bf9186ccc6e28d137811fea7b8074fa9ce3940ed235a2e65715b3af32dcb22e427036f1d2021bb516b1e7fea029f3d9eaf66497bac166a54bb0ef"]}}, diff --git a/txscript/data/taproot-ref/5f1c481f15b7e89e16871d58cd5784dc2fbfc8f0 b/txscript/data/taproot-ref/5f1c481f15b7e89e16871d58cd5784dc2fbfc8f0 new file mode 100644 index 0000000000..cce94cbf34 --- /dev/null +++ b/txscript/data/taproot-ref/5f1c481f15b7e89e16871d58cd5784dc2fbfc8f0 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7500000000bed07dca04c0871d00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898783aa7c29", "prevouts": ["d12c200000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["85", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1c80cdf889f2095af4d324c92b00d2a9db5fcc0724b0f6f8ee9ebbd204938760cb2a240b376911c9876b3695f79f395ec3f2d97b1695e5c0e7f397f1ed982e79a1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364b0900bf42a492e6d84803f411d6b7283b14689911cd75fb3ce169ea1a2bbfe0d4e60e987dc96ee5dbea4bc309cd424f3f3a0504752ed5a5936e8ec363297933734b3a7050eee065844830ad8d45a710891f78004f5e7f35b8fd72bf3ee94449"]}}, diff --git a/txscript/data/taproot-ref/5f33c80c85ea079ca0e803f9157053bb5cc26ce9 b/txscript/data/taproot-ref/5f33c80c85ea079ca0e803f9157053bb5cc26ce9 new file mode 100644 index 0000000000..9dd828755f --- /dev/null +++ b/txscript/data/taproot-ref/5f33c80c85ea079ca0e803f9157053bb5cc26ce9 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc9010000008569c1c7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b05010000000d6c2cfa0347939200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc5000000", "prevouts": ["5b906d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d95e270000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "017d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a70d9b275504125857cbaafe4a923049b33c80b4c83ac6cdbd36bca05abf17733479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae05873438be84f92d1402d5d55e9fb409fe52800aaeb5db180b239b834bc1ca2"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361819509e9671e02e7a4d8cb2e99fbc3fdcbb7d0847ecf4f66821ff751ef18b028874369940c44314cd428c72b977b6d1fa375b1e54ddd71363c505e3530065c38810a2a55ef559e3dd2f859359930339f67e2de31eeac841179b888fd41fd8a3"]}}, diff --git a/txscript/data/taproot-ref/5f49d9e42303e9fd5d3b3beb8b4f91d1d295e920 b/txscript/data/taproot-ref/5f49d9e42303e9fd5d3b3beb8b4f91d1d295e920 new file mode 100644 index 0000000000..fb702c57e8 --- /dev/null +++ b/txscript/data/taproot-ref/5f49d9e42303e9fd5d3b3beb8b4f91d1d295e920 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c78000000003e1cfcb0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c87000000004eb3e1eebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf930000000022a849d80147e877000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487a8000000", "prevouts": ["f2d35400000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "17484f00000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4", "72f17a0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d68bf7c140feaf8e4f60b8776bc2d1d8905ca34f4654213318f309611a791fb5a1ee4fc8dc3f50b1a7d3e5d21efc1fec664b6d43331f1543a08d774de08283d74b746d331d5c95ed01a802968db1eb0c81e0732cc306eb144cf9060c14b04a5c6a5e5061b73680a999fed0246f6cab8aa050c65d8ca054cbec9889d7184164e16fc8892d53c526e2d0319777ed8f82fb8165f3d4ef862eaa293789e9fa0908c057319c87d954e6274cb12c64f00e91cdc8f5145243a0189bfee992b27429d95021f953f23aeab4c6e7e7987c77378352a21d8b7fe4ebe28d113d8f7e0f662bd4bd4573b6e75c03493e72f22e525b5033e36f9c4e9b6e34a4c0342e539bfaa96c938c2477057ba1fccef550bf7f8d85f3f4eec2b7fc624e88884ad3bf1c32e839de0614b2cb30e81003c0620d9ac091d97c199bcaaa3c38faf2fb1cf1464e18eda2f4fcd7ae55c45a0d3cf2347cf9fd80afa78361c367fb700e17e7868e08757da8dcf9050b185e927d5c0cb7c9a80188884d03049231303cd03c23d9d6275abfe63eb720a423bf8926cd28ac0d416ffb7a866676825b560af653dd9a61be9389e375e1b9b0a117135099ecd9c11e0afaf647e1b9e90de8dd4f67b34a0823b913c66b98b2baff077dda4e21518a2317d1eb7274d9bc1fbded3844b9307ea03a8884d734ff9557ec92d29a1c157bf85c7e83dc0581a144a1e291e275ff5717a529f75ce3ca14b5c75f7275df", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045473717a4c1e901899f4f84b73650625e3fd5128aa3394961893ec6e831ca5ba551d880cc047c10a424f65fe9dd9096492f3efd8e08517d04362957faed36c3f852ff338358c59a252efd0a17af70f1cdfe194eb24c5d50483b26343bf89011bf"]}, "failure": {"scriptSig": "", "witness": ["4d090280dbce27bc6df840e8a2111bfbc544aa69a9062ac998d1aea9b5c19e4508542441b53073dac68032c2a7786a5fccdddc19a01fccd9c88dd0de26ecae8602b82ea65b88253f8f6103c1a1ad55cc629437d04b4ee6d3ccc0e33e3431927b45af53af61ee0593c59b469d553c6c4f550ecf021e07dbcf3981fe0d9a061583f90d6c00dfb5f3fd29fe895d9930c531bc2c5c24544e64b11f0f491320e2f80838a30268e491138071a849afb18322f676d06504ff1ac62d213ebf0330b754f0d96832509dbc5dd00dc9c5285eed78d78758d5033c95b8f38247af94cf64e855deb83e0d0e4a8461d9ac07de149feb3db55d0948f53120f3f454ec6b88f719e54c620163f49efd08813adf2d1fd450e57cb87d19d9c63852ce1c36d7f7eff5e089156971df45ea075b61f2792356059913df7f090cfa0dc801332be78b3ff8efde723f409a80c0f0b54b522b02cca7bd99642adc50ee3f9e1eea08938504b23cb8307a6dc7cf021b031dc32f6937082584aee4d7afcacd01a1479c0d89359b90a63886187849ede948546f367a85041b1546a118a7614488f915247616eef412263d436303c4228e2fea141a71ae0ad128f7d79b5f6c94e7941ee003e3ef6c0a9fb671fa79a6ff9e57143ee18e5bf70d107727b313561d7015477816b92bc41718fd89d5fb18667ef5edfcd3d391eea8791b0d1cfe8e8b7f665914ea119a2197e13fe3d0415ebdd2fbbf32f17561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45385991a3000310359e2a9adae84589f286ca8f4d4476598a0e772bdb8ecbe6352ff338358c59a252efd0a17af70f1cdfe194eb24c5d50483b26343bf89011bf"]}}, diff --git a/txscript/data/taproot-ref/5f617801a71e54b50b37fa8715f4acb9c710bc1d b/txscript/data/taproot-ref/5f617801a71e54b50b37fa8715f4acb9c710bc1d new file mode 100644 index 0000000000..3be642437c --- /dev/null +++ b/txscript/data/taproot-ref/5f617801a71e54b50b37fa8715f4acb9c710bc1d @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffb000000003c3851e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2b01000000a55d69fe016a56890000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796cd000000", "prevouts": ["ae147e0000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "731e4d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b", "final": true, "success": {"scriptSig": "", "witness": ["86c6eec7193da1b5455bcf273a3a16114ee645411225a833cdd0a32e9dfd78b089bbf36f4e9af0c6d026973e0f1887dd6d29e2337079ae5afb26e1cfcefc1b3f81"]}, "failure": {"scriptSig": "", "witness": ["dfe32bb06ebc64fcd737b27bc8bef0840e3dc7794ab25058705659308f1453cc9be602519eb3ae6bfe877b8f16dd08e96b708997382d53b2a6903546206a00010a"]}}, diff --git a/txscript/data/taproot-ref/5fae0f3d4ccf63a68fa6fc6ed2f605c153bc568e b/txscript/data/taproot-ref/5fae0f3d4ccf63a68fa6fc6ed2f605c153bc568e new file mode 100644 index 0000000000..5de7ba5a9b --- /dev/null +++ b/txscript/data/taproot-ref/5fae0f3d4ccf63a68fa6fc6ed2f605c153bc568e @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1602000000be453d33dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4c000000008b83fd6a01858b58000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748705000000", "prevouts": ["e5325d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0268220000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_mis_3", "final": true, "success": {"scriptSig": "", "witness": ["c677708e3196e905a65db1e859f10031e4e09b6ae41585884462f5e1196b3148d3fd4d0603e1d5a2a1d70f3f444fe2e1b8bc569009a5a4539dcfc4a21d3d47cb01", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["ba8509c370606f9c579eb466d05a04f13d5db0021bb6e138c306fe8a542cb505acb5b46ba209ff8c47b727d8e35a4de76702e00bdfc0d66fa3199164a105412e03", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/5fd0ea816791d944d140a7f5a132e628c4df41cf b/txscript/data/taproot-ref/5fd0ea816791d944d140a7f5a132e628c4df41cf new file mode 100644 index 0000000000..7530c47da4 --- /dev/null +++ b/txscript/data/taproot-ref/5fd0ea816791d944d140a7f5a132e628c4df41cf @@ -0,0 +1 @@ +{"tx": "58bcc4a301dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbd01000000dd85e9b602df8448000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac46000000", "prevouts": ["aa2e4a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_43", "final": true, "success": {"scriptSig": "", "witness": ["87d077961f8f2397c36aa4a99b46e0dbeaecdd032434c973d6f45c84a2691ed9c40af7f80d79d4cd13dcdbfc7290bd83538f2c1b89d8c6e68db84e3cb3ab03ab", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b91ae0ef9e93bebeb3288bf7e2817763246cb75874fc608094a8f55cf2a1db8b6dd8ea87a26aecb9b3b7df2299d0d8576b1ffe6c8dafabb79c2f688d6f89a4d543", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/5fd72300746767ed3942898b20e747b5e468bf3f b/txscript/data/taproot-ref/5fd72300746767ed3942898b20e747b5e468bf3f new file mode 100644 index 0000000000..31dc81be4d --- /dev/null +++ b/txscript/data/taproot-ref/5fd72300746767ed3942898b20e747b5e468bf3f @@ -0,0 +1 @@ +{"tx": "af047eec0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708d0100000035cba8a8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0500000000056a088502900d7b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca77d2341", "prevouts": ["67e6110000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "63c76b00000000002354212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["4734f7eefaabd240db74a20e895a323978e3541c66ea1e8b55f9b9cc3a956339431fb1d9ecf8acdc726ab83cdcc6c9a89a2e9a0edc755bacfdaf9d5d6db5d5c7"]}}, diff --git a/txscript/data/taproot-ref/600a49efd1ef275dd0d15886970d34f50ceb2cb5 b/txscript/data/taproot-ref/600a49efd1ef275dd0d15886970d34f50ceb2cb5 new file mode 100644 index 0000000000..b3b1e32745 --- /dev/null +++ b/txscript/data/taproot-ref/600a49efd1ef275dd0d15886970d34f50ceb2cb5 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127093010000002d19d9aadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba200000000c727f6d70274d23500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748705010000", "prevouts": ["f447110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3830270000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6abf", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d517a865b9233942981930f9f8afabfa67810a1f554556b3d8041274c095c748aa3aa736b6bec5c04b20c5b38998d4f897a7594adad2cf377758bae1284900c20e3219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93664b0019b93cb5fba4dac055f468adb936a6222806f746f4014a8a3f37639abc27a865b9233942981930f9f8afabfa67810a1f554556b3d8041274c095c748aa3aa736b6bec5c04b20c5b38998d4f897a7594adad2cf377758bae1284900c20e3219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}}, diff --git a/txscript/data/taproot-ref/600aee354a6065175892343ec14dc1eced5c33d7 b/txscript/data/taproot-ref/600aee354a6065175892343ec14dc1eced5c33d7 new file mode 100644 index 0000000000..4dd9b5542c --- /dev/null +++ b/txscript/data/taproot-ref/600aee354a6065175892343ec14dc1eced5c33d7 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d02000000cf6fd6acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdd00000000770059ed60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270030000000080b8e2a304c1997600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5997e11d", "prevouts": ["a72f0e000000000017a91481d4142ddc5ce7a3de4047bd48b623419b5bc45e87", "8cd95a0000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247", "ae2e0f000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "847d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faff78d21b135ee37de5fb006beb46b85f4aedf8bacb6598da1f15171cdf92c209c568c76d6b344a062dd798f6575db1f1731d6a7ca3f2682e7e1b801cd94d3826"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c194e7775fd7c80d883f2d740f9e56e49ab9a06d8b2a8d7428d3ae945cc345b376735f386d1a4700f0e60fd19c47be953169b4ae01039887cebf253884ac2528c568c76d6b344a062dd798f6575db1f1731d6a7ca3f2682e7e1b801cd94d3826"]}}, diff --git a/txscript/data/taproot-ref/60157ba4a7cd240aad985554d23dafcb6b99be47 b/txscript/data/taproot-ref/60157ba4a7cd240aad985554d23dafcb6b99be47 new file mode 100644 index 0000000000..ec1a64cf66 --- /dev/null +++ b/txscript/data/taproot-ref/60157ba4a7cd240aad985554d23dafcb6b99be47 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1a02000000688f084d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c2010000009ef8d859045db7a1000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acc63ed24d", "prevouts": ["8f31660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8f393d00000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_5a", "final": true, "success": {"scriptSig": "", "witness": ["0c322227924edb56429524d47975bec9661feced637da9488d938c579ed9d9f3f751e937ca88e77c996154191cd340a0ecff2647e9cef67303b4811bff21d623", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b72cd534632bcb423fd826395cb0170679cb69c34af86263d9fc29e106097cd0a2f0c7fe295147621a9d101cca84e4241d59b622c6d10e1a9651f22f5f58f3905a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/601bf2a7aa8b6c3a9adef4933fc515d494f4a95c b/txscript/data/taproot-ref/601bf2a7aa8b6c3a9adef4933fc515d494f4a95c new file mode 100644 index 0000000000..d8b6c58c63 --- /dev/null +++ b/txscript/data/taproot-ref/601bf2a7aa8b6c3a9adef4933fc515d494f4a95c @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47801000000d864d64160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706300000000b0448b2f01b9302e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8754010000", "prevouts": ["fb623f0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "33201100000000002256202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["7e6eff66ddca203267f8079794c4aa5cc3e46d949ac5d785b162a8c7acf888f7b978e1f3a0accdf966e42dfe4dd7cc59d4d6da856cd372a1bbf908a6bfdb3ed1", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/6030146df9ff31d1d977c2672cfc3792ad81865d b/txscript/data/taproot-ref/6030146df9ff31d1d977c2672cfc3792ad81865d new file mode 100644 index 0000000000..5db2bf3f4c --- /dev/null +++ b/txscript/data/taproot-ref/6030146df9ff31d1d977c2672cfc3792ad81865d @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4d0100000097b2f1d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff300000000335a90e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43900000000f069d69701a1ee2600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aceb020000", "prevouts": ["98775d0000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf", "e37b73000000000017a9148462ed29696925d7688e1db8e76ef9e6667f05b287", "74ed3100000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902cebb14ae0976d2a761e7312a258e5691aade4f58cee01a039414a95b2ad9366950f9d22dc2d56986735460027f83409b3d76a03ebb5acf5951b743755e38ef6f856d3330744f493bdbc242a87021e9eee73d256fd114103c90a47cdd9169889ca6d88850e3dc228fdec261be836ca0eca2a63643b5463fe3eca82100fb05a89c6fc7153b0691ed830eebaf4c4a5add6478f5c67a5b0352cea3f315e19bb0caab04878d1c87ad73229e35b16846e1541a378fa47c0136713b96c664e203b7f39736d6752340971b166baea7b7a1b64739802b3228e211a750a2ba6e46037db35828b8be5cfe71d75c54b2c1f4ca5890edcb193ff2f89e1a92b277d6180525e680f649fa1b6a7fb04c09ed5f1ded674c69a1a1f660ac2665092ac9cf44d1a0d83c14cc196b95fd27db03a317cd1ab19247e5ced20bcd1b658cfc6c134aa1094b6f5b311dac11c1ab606eff1a70a5041365e9822b572ecb58bb02d17b726875af11ecb742107be3ca7ad4f59b7b71fb9065334ad509ee37c9400abf4eae3a8ad0384fa350635f2eedff03e71bae11111a7d2495f629ffb888512a01963550bbc0350b863f413c96fac5aa4ac395495c30dfcb75ec7d3eea1bc672a38bacd23419a71fb38a1b2347b459e03ddccd0e32cc810313ff42e5768bbbbbf5a8faf88ec0876e4b67e7f7aa643271374a65005f04598c97dee9fd0968fcfe6371f59b631b2d81d16d8fced4a39d4d75e9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082c3950c17255228812280bec2d0cca04b586565374a97ee6c913745c9c1a159600ce9ba0618adb3ee44483a22999a54a4e1710b9846377d8164aaa29371d79f22a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}, "failure": {"scriptSig": "", "witness": ["4d090222a6561a0e906e5cde7507b9e35dda6a2608ec0600c213a66226848db87593fafa194a6a01d862b3e29dbeb40f502a22cafe5bcf5842c552f3aaeafc056d6113c418c285a38d4a625f94f981ad119b0f627e5418c08b471676dd18d7102d2330cc780645a7b0e4e7480172f20641ade124179be416c856f3ee7ffcc1c0f7f66a665ed3b779b9aa02c7df92c9eb3af8b2beb601e42b7cc9a8f696c1a81ea97e23451699214834b98f2b66ad6310664c466276408f754928ccf0fa72ff59193dc6ed0282290fc25205ad57bb0a9415559d0299bfe17b029a6cdb4bca0dd3ed14ec30187c90b4a883d7218bd0b996ff3e60ca83aab6d3279953a9137ddbb6038748f9bb2a83a7c39f18fff94eb2fa5d23a1b6c6db163943ee8fd4dffa4526326a6adf04530e299dfc99683d22677a00251842b6d798ba0fb88826a35f2fc72d04fa40303b66ca2e1c12f8ce6b1a27c9134d6e07a404caa0857a57aa76391558fb9fbb0c98c6df61aa4fa8aa0615e38591470cb0f60317fd74b6b754648f71e599e621438aa654b2bb937b649be08fae10bf953aa791f5a0b6aac76c9e80c61fb1d64948528d9fcae33b277e0506eed1c0785b7577688393914e39ca2cbf39e08c0b77d716db3266a9f902ab20488c091c0300a12e18b9f4f65f81483941ea1bca66c23307f14dad070e3bcefe2cf9da69a00229faff2aec5ccfd76009b3018b45249c00f5d20eb5840a647561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d60d23b5fa12cba50628f4886671306729110bc543fd454bef1f18df07be9211fcbd8218c9dac71a3535cf40d08210778548ef11a7c40c018c5ea1885d9980740ce9ba0618adb3ee44483a22999a54a4e1710b9846377d8164aaa29371d79f22a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}}, diff --git a/txscript/data/taproot-ref/60350336430acbd30d2f4a7afd671e1a676249b8 b/txscript/data/taproot-ref/60350336430acbd30d2f4a7afd671e1a676249b8 new file mode 100644 index 0000000000..68ecbcf327 --- /dev/null +++ b/txscript/data/taproot-ref/60350336430acbd30d2f4a7afd671e1a676249b8 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42d01000000bdb630c88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cd000000003ebb08c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f400000000c26dee9901a9b60e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374879a000000", "prevouts": ["804a37000000000021561f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "47ba3c0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "dfe4400000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "f07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363b039c0e9d8bf6e88a427a2ddf5980e431ac842cc97f6c7b94ab341d52b6d0fdbec2e27f579b173781717090b44a070e7a8880532a05b17dc998986213b0a92d21741bf2762a3041d275698fd56a81520b6404e88c31ed080bdecc36c09cb10e"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652dd3253268b521b8234f9a6c7de3fba7d5f203b8100eaddd2fc9e08d24fa7c435987c1d75c441670cebdf615816c6f42e3d99515a7a7b9841c20e75c916465ebec2e27f579b173781717090b44a070e7a8880532a05b17dc998986213b0a92d21741bf2762a3041d275698fd56a81520b6404e88c31ed080bdecc36c09cb10e"]}}, diff --git a/txscript/data/taproot-ref/604aa389e1cdb7844558781a66e69bb80e5f7ed4 b/txscript/data/taproot-ref/604aa389e1cdb7844558781a66e69bb80e5f7ed4 new file mode 100644 index 0000000000..c716cd364a --- /dev/null +++ b/txscript/data/taproot-ref/604aa389e1cdb7844558781a66e69bb80e5f7ed4 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270240100000016d9ce96dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b740100000085d2d2f90174352f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acc1040000", "prevouts": ["3fde11000000000017a9149d4bcb1ed806c9beed692a78614f8b90a68c708187", "7903270000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21571f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["15bb12fdf12c0e4a1e19ec0ed405846f8e030af8e2f45a52e90f8b4b848d733c528a438c305cc14eaafe646856418e70cd834fed506aa34c27265e7829ddc9ae"]}}, diff --git a/txscript/data/taproot-ref/6070c8050e46e845c5170ec25daefa937dbbdd11 b/txscript/data/taproot-ref/6070c8050e46e845c5170ec25daefa937dbbdd11 new file mode 100644 index 0000000000..a0d9486890 --- /dev/null +++ b/txscript/data/taproot-ref/6070c8050e46e845c5170ec25daefa937dbbdd11 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8b000000008783f9a3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf850000000061d3980c048f94c6000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7f11eac39", "prevouts": ["ed4553000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "e55075000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["304402207c3560a1b325f60608c03ba21e230e144c06005942eb9b208c676bb569b242e102201e3ab2f0c0137ba95e943535fe46234ce0fbf9143783044187046bc848149f6901", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["30440220590fd32adbcb6e036526a61ea254a11fa14d3319fffa382dff23e0b3395c509f02207ec326f9affa0aa6108fe6b4fb5534d50de66a021083aa3d6ace4bbd65568f3601", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/608151513d665821b3914810e70e9c1f957da187 b/txscript/data/taproot-ref/608151513d665821b3914810e70e9c1f957da187 new file mode 100644 index 0000000000..55b0d2b881 --- /dev/null +++ b/txscript/data/taproot-ref/608151513d665821b3914810e70e9c1f957da187 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702800000000800da0c18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b4000000004386efe703b659440000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1bd3c834", "prevouts": ["d1a1100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "46513600000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "483045022100a3b9a90f7f608d76fc20be55a2b18001ffd1d09a68f110e8f572715ccc89718c02202f88a2681be70195652e0cf90a000781c6e131e92210db2d4d8a77508a6c18e7852102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "483045022100aa9878010ce7dd01e0970ceabc1a33669e4adc188f69f35882800203fe1feca3022063d04c1b13e431fd4395fbb297ac2bf06dca4755dc60a1910855cd3c4215b4b2852102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/60a40b71e2980d806f6e3f1f604e1c25d8d684a9 b/txscript/data/taproot-ref/60a40b71e2980d806f6e3f1f604e1c25d8d684a9 new file mode 100644 index 0000000000..4b0aeea0c2 --- /dev/null +++ b/txscript/data/taproot-ref/60a40b71e2980d806f6e3f1f604e1c25d8d684a9 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfe010000000fe2765760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ea00000000cfd16a8c01ff36080000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796ba030000", "prevouts": ["92fd270000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "b4031300000000002251206c786b308a9c6a675d6ba645c0b3fdb6ef76f1ce96e6f31b784e53054a24ec87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360ed7b0b6321a9c82dfd18851526d308dc485f056f75d2abb96b2300df7f1dd61"]}, "failure": {"scriptSig": "", "witness": ["6a9f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/60c433ddebf0bd6ec3f44d608946aed9e843587f b/txscript/data/taproot-ref/60c433ddebf0bd6ec3f44d608946aed9e843587f new file mode 100644 index 0000000000..3720170c9c --- /dev/null +++ b/txscript/data/taproot-ref/60c433ddebf0bd6ec3f44d608946aed9e843587f @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfd00000000abc441cc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4220200000015f555c90339ce5500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870b030000", "prevouts": ["114527000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "9d7b310000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["fb4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514c1cf5ffa00c6c7050afc353617823cd679ab4db6c6aacae1c16f62a2980653852b51aac478484d8a075e848b67a41ce9b347e1249fa49816f898b909a6d4bd5c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}, "failure": {"scriptSig": "", "witness": ["4c52fb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93695454243f1cd73e7efe7199757ab68ab99257375d0485b32e96b03b75ee2089778b7d2e6e031ffcaa796ad02cee9894dc771f62b9a69e495a6b0c07c9d130bc643d925f8e6664e67417d113cf51c5b4c3126025efa5f83bf5b16dba6746279b738273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}}, diff --git a/txscript/data/taproot-ref/616a7fdb9927448c5c9e34f94d4f6d784f55ccf8 b/txscript/data/taproot-ref/616a7fdb9927448c5c9e34f94d4f6d784f55ccf8 new file mode 100644 index 0000000000..d62bf54c5c --- /dev/null +++ b/txscript/data/taproot-ref/616a7fdb9927448c5c9e34f94d4f6d784f55ccf8 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4160200000022cbc59f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700c0200000019f988b38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46e00000000d2570be0027ad87c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc70deadc2a", "prevouts": ["d5b6320000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "59ad12000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "5152390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "8d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829640e65f27972e690b56e28a8f49ec76fed3450565b59143bd547c42619e148d8047789ecbd47ea83af97bdb87f8422a4707031714ddb05eaa38b24e158a7c35"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360a8a801582dd903a75de5904df4445cb714185a34938b03fb7716e9516670c429640e65f27972e690b56e28a8f49ec76fed3450565b59143bd547c42619e148d8047789ecbd47ea83af97bdb87f8422a4707031714ddb05eaa38b24e158a7c35"]}}, diff --git a/txscript/data/taproot-ref/617d47ec32a898ac6e2b5bdd9b8e643408054596 b/txscript/data/taproot-ref/617d47ec32a898ac6e2b5bdd9b8e643408054596 new file mode 100644 index 0000000000..7e97511558 --- /dev/null +++ b/txscript/data/taproot-ref/617d47ec32a898ac6e2b5bdd9b8e643408054596 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708a000000006cad66f9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf50000000010b9b10002826d6b0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca5000000", "prevouts": ["c136110000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "bf2e5c000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514c57128c8a67973c5c0637342f282ffab122f5a34eae9e616b37e48a600a7a243e02ad6eabd24d4d247e98c297de2a9d81d67e55d72d4ddf06c8e9a23565ad8a003e045cb689fe4fc6de332c618eb0cdce02c2dd8aae7c6dd6f70bdbaede2814"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670ae177af992db50f31dcdf0d3e38cfa7e2e74b3eb9ff8cfcd46237e8c91da365f20acab37c5a5cb044828a71c51f411f3799e0c9201344692cb6121a679af6a96525fdd0eb5f3c5c39bf5b04d78b37703e3d3b538b36e17fa0ddbdeb236a5daa4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}}, diff --git a/txscript/data/taproot-ref/61ac7af8ebd0ac559618d67f23d159b57dce5577 b/txscript/data/taproot-ref/61ac7af8ebd0ac559618d67f23d159b57dce5577 new file mode 100644 index 0000000000..25849920c2 --- /dev/null +++ b/txscript/data/taproot-ref/61ac7af8ebd0ac559618d67f23d159b57dce5577 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2e000000004f19aad78bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a9000000008152fdb1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8b01000000bc4390e0033a13a400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d3c8e225", "prevouts": ["20dc4d0000000000225120ec87a05d11c16a148e05f58a688dc5bed4b2941085b66901aaa75337acfb52a4", "f0dc3300000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "0f0a25000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4e16c32678f9526b399cba9b784e72f2992f57e86dc0d30aed359cd8163f6c1"]}, "failure": {"scriptSig": "", "witness": ["6a6a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/61ad3f5b692481700ab46b1c77ecf7e1590f4f72 b/txscript/data/taproot-ref/61ad3f5b692481700ab46b1c77ecf7e1590f4f72 new file mode 100644 index 0000000000..48195102c1 --- /dev/null +++ b/txscript/data/taproot-ref/61ad3f5b692481700ab46b1c77ecf7e1590f4f72 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7900000000f330f40adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b590100000008d985f0031e937400000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac2cb95a1f", "prevouts": ["9343500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a6ef260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f2", "final": true, "success": {"scriptSig": "", "witness": ["6a09bd3b259d35714994da18e608796841604a3aa418b893979bc70b65d26913f37371cb50fd2d1bf67f3ba4969d4d43b8d018e122f3be7584b245da98c646ed82"]}, "failure": {"scriptSig": "", "witness": ["1b6e3247f48fea47a56cbc1391b4aa6d417090bb66e4eac3feaa66c163dc0ecbd1de148744174d4e5238a52a5cb80fa32e1d1ac598b302807f39a1f00d513413f2"]}}, diff --git a/txscript/data/taproot-ref/61ad53ecbb9e93b9d193624ee3222dd39af8c8a4 b/txscript/data/taproot-ref/61ad53ecbb9e93b9d193624ee3222dd39af8c8a4 new file mode 100644 index 0000000000..a6a5e0a972 --- /dev/null +++ b/txscript/data/taproot-ref/61ad53ecbb9e93b9d193624ee3222dd39af8c8a4 @@ -0,0 +1 @@ +{"tx": "865915d603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4200000000458456e0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9d00000000e0cafcf560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707a000000000805b2d203a5255300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4a000000", "prevouts": ["ed2920000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "3f51250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e9fa0f0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d2c366f5f09fc7681ee328c1d1e0744e3d1f6968f411bc983eafb1d97babb7357017647596b1d0b5d4400ffddc5cd50d9aaa53b080f112dfaa2c5985c87c2ab6054554b46e48c04e7631c61fb50d897e6202de7a2650e8e40522947bca33e6cb1402e8ea9ddce4852f0460c99dd3632d833d13dbf42d93b664b88a5ac58d27e9dd411dd68cc2a921a90710ccde304737ed292254dc1b1face00754a7ec9ac0de659194f441184ff96b2cad650d3f53bf15e9d6da8e325857d5aee2b252475d17ab0508ed4eaeae32469282e40f203de623d3cb895eb9bb084bc1304d98d64631cf422de97bfba40f0325e2086add112b420880c543fb742da4d8cdfc0b83091a5478a1b7d4fc836fe6b505f2163d79bbea0b9560c41feca534e9076f70d4481b18cb03b42242bd7987b6040d650f8a4bc410c78d6481ba58b633e3e60ae24d114645a7f0279eb111c4613279adc31608460cf8e526bc2d92a75c2c941b174d172281f4b5fe85af826f5e874e4b11e9900c07dbf8d5b47f7871b8db5cb853f661e8c6b1ab55854d0715ec68418a75887950f3776efc9cf312aef724f17fbec30bd7a5c191712fd1cd05ebfc3fb0f6d32ba36688067c260012c5564ee44b6983d7e284055be54a6a73aea1762b58339e2d48d84060d6049e16b58bb8f3e01bb3aad920e4b1b395c05a697d3e5f511f4d2062db1ff237e5672433a8e5da8c4c311413e31766f53f97f89b75", "6c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699ac01d1255123521c36b523ade2f83d5f7b8cfaacc623fc56a5e5790c6fa726582208a7b7ada7f1b97e8a78343d1faf2bcdbc0a6f50e4fc104dcbcaf06e1472e7ade389b5221dc8da0332285833f8f90d31bff9f5dd8cabba4bb6916c2c5f203000b960c1063a40dfb5dc510671dff140eefb73aa6757bc42ddda0d13c6b661"]}, "failure": {"scriptSig": "", "witness": ["4d09026294caed73fb93cbdc2d4cc7c05cbb2e5d67cb415e4bdd98714d6671da1da886775dfb9a1731b8b3252b535fee4a037cfcb44bd4e4af04a3ab23a63ee4e3bdc916c8d0c8abf69d82ad05b5ce0ae927de1f7942b63cba10ad8f5a996b56e998cb051e29f8ebba2a09643b0974c301c6768e85f363aee4376fd2e6a5b5c60b7234f0fdd44ba0670dfc50a13bd80821bfca84b1b0a76ad5aba6f7cd1d5b374ef3dc46fce9480c38472066d540b56a1625193741413aa339a484da5980a773544e2ea67a4a5a6c335e524ff8aaa5cab5e6a23bb41fe3898a8fec94ed42e1d73e965203020fda8fbcdf3a9fb55772f90a8215e9923be8201216d216d1d6915a827a256d0f4185b1b938ec5aab78fd91af7e8ff8042b23a072fa71aaac7f4f7162575bd9aab17780993b109029770444eba185a81b69436a8372d3df59b0d03c20c08111e0e38b5569a68c89002f5d099191b304a6a72b91e9829cadefc342a5bb0041abded379b05ad94118e34b464311fe10eb1fb398ad2351ec5431711f52def2426d268fc2098175e0734494f37385e454057f2feac6faaa5ccffce27e8af066527a7f05c49c755944d240e3223ef9b97b7dee6ab0ecb007c7dd47822121d80bbd8b7f02788d438d1f49551e88203dd130874e4bb9f0c2f798e9b416534d9b267e28dd24a3d5898443d0aee66a306338b26f99195ba7878c47253ad22d8a8977212669db090aec72dca275", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369b3812b1e99c6fdedf163c708140d27f446ac63a89153db0a9d90b526328f674582208a7b7ada7f1b97e8a78343d1faf2bcdbc0a6f50e4fc104dcbcaf06e1472e7ade389b5221dc8da0332285833f8f90d31bff9f5dd8cabba4bb6916c2c5f203000b960c1063a40dfb5dc510671dff140eefb73aa6757bc42ddda0d13c6b661"]}}, diff --git a/txscript/data/taproot-ref/61af1bfa70f27db871da9994cee2a1fa6dbfe915 b/txscript/data/taproot-ref/61af1bfa70f27db871da9994cee2a1fa6dbfe915 new file mode 100644 index 0000000000..6c663fb176 --- /dev/null +++ b/txscript/data/taproot-ref/61af1bfa70f27db871da9994cee2a1fa6dbfe915 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4200000000909948478bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47a00000000b7bad9750152878e000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47877d532648", "prevouts": ["407b6800000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "67d73c00000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e54c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b15c6036a676a492a4bf737064ce6a21b64de8ad159d3b2e60d879468caf8957d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}, "failure": {"scriptSig": "", "witness": ["4c52e5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4deb89faaac3ba7f5e16436fc8221b82cf02c075e22a72f26a59deb249ff0d9e9edc23a266999aa1773fe99be867e95cb2abe2d57657b7a4dc20a388644aabac6d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}}, diff --git a/txscript/data/taproot-ref/61cb3c37ef29bf5abdbf60157dd9334ea8578716 b/txscript/data/taproot-ref/61cb3c37ef29bf5abdbf60157dd9334ea8578716 new file mode 100644 index 0000000000..26a09e6eff --- /dev/null +++ b/txscript/data/taproot-ref/61cb3c37ef29bf5abdbf60157dd9334ea8578716 @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270970000000058396aee0262b20e00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75b869d3f", "prevouts": ["246010000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "6f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa250e9882e2e133b56af40caa5e77ecf964d6e28c7a51ea626a8db4d1e1f7bbb4a3f8f9fe88f0f431b5ffad473abfcf1c4b340e1c7daa1232bf4c86f035b8cc51"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d671bc8379695bd53537ac42fe7f6ce70c4715992c44bf872eb735ea6e29d06250e9882e2e133b56af40caa5e77ecf964d6e28c7a51ea626a8db4d1e1f7bbb4a3f8f9fe88f0f431b5ffad473abfcf1c4b340e1c7daa1232bf4c86f035b8cc51"]}}, diff --git a/txscript/data/taproot-ref/61cca434775b13627deda2ffc7b421cc834c16ee b/txscript/data/taproot-ref/61cca434775b13627deda2ffc7b421cc834c16ee new file mode 100644 index 0000000000..aa618207fe --- /dev/null +++ b/txscript/data/taproot-ref/61cca434775b13627deda2ffc7b421cc834c16ee @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127010000000008e090c5160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cd01000000885fa63502431e1c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8a000000", "prevouts": ["68d90f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "d1220f0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["dd4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb48439541955ba1ee927ac695664eb0a176a74cc392dce51705e9d682cc4042391e6ff37e966b1384c4d5bfa916e4482452180179a80b37f756d07f3e2976ea2d444f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dbb12e8fa457546fdd4a7d9164919411804187407b1d76f0315307aa97171b6e8439541955ba1ee927ac695664eb0a176a74cc392dce51705e9d682cc4042391e6ff37e966b1384c4d5bfa916e4482452180179a80b37f756d07f3e2976ea2d444f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}}, diff --git a/txscript/data/taproot-ref/61cd2f257a7e5a750b8f03f5aac0ffb2badc3aef b/txscript/data/taproot-ref/61cd2f257a7e5a750b8f03f5aac0ffb2badc3aef new file mode 100644 index 0000000000..ae8613b20f --- /dev/null +++ b/txscript/data/taproot-ref/61cd2f257a7e5a750b8f03f5aac0ffb2badc3aef @@ -0,0 +1 @@ +{"tx": "0200000001f85ef04c4139d614d10d1a30e75a9f6421df67317126da87b2f877c2ab20246301000000002a67d6e90189d4f84f050000001976a914a875a4732dcf342e2587f26f2b7b2ea4a2fd587488ac30050000", "prevouts": ["1acc45b01400000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid", "success": {"scriptSig": "", "witness": ["576dd7bfb72e5379a8317f3a54b9287d49891291fd96a2084e781943b3424287a63f413d1b4cccd89e1529deaba58b40aa10b57644af7a2ee55203e2c0244f02", "20cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3ac", "c0cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f312f383ce02997bd7885b2023ff24b4d79c49e77348af650460f5903df7baafc9"]}}, diff --git a/txscript/data/taproot-ref/61dfcc18f9bbed9da1c93970d11da1509777d17c b/txscript/data/taproot-ref/61dfcc18f9bbed9da1c93970d11da1509777d17c new file mode 100644 index 0000000000..84e267f312 --- /dev/null +++ b/txscript/data/taproot-ref/61dfcc18f9bbed9da1c93970d11da1509777d17c @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bae00000000e0364cf58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46100000000669af35004b73f53000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca91b3e44", "prevouts": ["43dc21000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "923d34000000000017a91482be44661ef9d172a86ea47619409ff206130f7487"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2256202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["a660fdb7c4037739f334e7e659b27905e93eaddab34558b64574115300f23f90816ae8cb635589087ba290c7a4fe45f90d9e077b34d78f553880d7ba813979ca", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/622454dc9deabc8438f95f3e6280211c37369c04 b/txscript/data/taproot-ref/622454dc9deabc8438f95f3e6280211c37369c04 new file mode 100644 index 0000000000..11e592195f --- /dev/null +++ b/txscript/data/taproot-ref/622454dc9deabc8438f95f3e6280211c37369c04 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270170200000079ce70c5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf31000000004c1ea1b001a9b353000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748760020000", "prevouts": ["7ff80e0000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "541766000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "347d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823ac03c85a7bde4aa83325c4e9fa3803d6178be55885bf5b72d341e036ded0599070c3fd2cc03cfe72ec91581f9e22200fa4c4f6deb8dafcd335310e90efb11e5"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e273fc53fb3c003aa1081c29bba6e2ce61bbe16b764fbbf36a77a34a2c2a6596a750add471e9b5b51db6817cb10861abf00379c9e2c8d017af134b88039c39e3ca882fe3c585d1ac8aa5218112791e3065e91b4e1e0362790dbd367cd44cec36e97124583e57aeab90707503ff0d8dae530166a9193c4517699e1743b45d7c12"]}}, diff --git a/txscript/data/taproot-ref/626dec99c8f47a95e864b2a31b4ca6b916ee594c b/txscript/data/taproot-ref/626dec99c8f47a95e864b2a31b4ca6b916ee594c new file mode 100644 index 0000000000..5f4393d3a5 --- /dev/null +++ b/txscript/data/taproot-ref/626dec99c8f47a95e864b2a31b4ca6b916ee594c @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127014010000007885ab88bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3501000000d8098c37dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0800000000ce51b63e0198b6c300000000001600149d38710eb90e420b159c7a9263994c88e6810bc7bf71183c", "prevouts": ["2537120000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e", "5971770000000000215d1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "58b05a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["b060881f6fee60f523a0890c4673283817e38433cc5cd4db7c376bb5c48f932c30e3141d824141d7176dcab8d3aaea2d82867678a23d6d379d141b4f9d5f637f", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/629399f535a4b780a7126fd274938c9e1bdd9b94 b/txscript/data/taproot-ref/629399f535a4b780a7126fd274938c9e1bdd9b94 new file mode 100644 index 0000000000..28e0524f1d --- /dev/null +++ b/txscript/data/taproot-ref/629399f535a4b780a7126fd274938c9e1bdd9b94 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd100000000ec47e22bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfae01000000926ff007049a1bec000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac12020000", "prevouts": ["942b7c0000000000225120cebe24bd65f3df56aab440a71cbc9879a1b3f80f985a5dd97b0c93b61f81cd49", "6cee72000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6afd", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ecf11a840f350f547c61b448cdd6e366448a3c04413fe40af096eb0d980da89820e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1e0a7be32fdcca7a506e9ce249f658cc089bc7a3d23614d55e872a83e7956fea4416efa3a61de7db58e4e5b27e55eab88df01883130071a88e8c07ccbf4e37c61"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173acf0ef20a11005175256561cf2f67252fad6f828fd45e261da47aa072728c1e1d416efa3a61de7db58e4e5b27e55eab88df01883130071a88e8c07ccbf4e37c61"]}}, diff --git a/txscript/data/taproot-ref/629683fa749137e2dfd6e82633d304ea6c124ce3 b/txscript/data/taproot-ref/629683fa749137e2dfd6e82633d304ea6c124ce3 new file mode 100644 index 0000000000..fe76f11a19 --- /dev/null +++ b/txscript/data/taproot-ref/629683fa749137e2dfd6e82633d304ea6c124ce3 @@ -0,0 +1 @@ +{"tx": "9f516898028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4370000000009665a87bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe60000000014113c8e04b9d8c0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac96dffc49", "prevouts": ["6081400000000000225120b10c5cbe32c5e90da6e76e6bf182a80e9130a66e1280db2d9eaabffb93bce832", "aeb98200000000002251205b7dc500a06d9d49351272d9ef7a52148a11476ab62e1647e512b05f260e1644"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da7a3882115c20da13b0db94a14cd63dfa5fecd118ec27d0fe3f55ed094799d9"]}, "failure": {"scriptSig": "", "witness": ["6a5e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/62c572a03d69a6b40d25947abae19bf6ce5eb385 b/txscript/data/taproot-ref/62c572a03d69a6b40d25947abae19bf6ce5eb385 new file mode 100644 index 0000000000..5b4fb69fa1 --- /dev/null +++ b/txscript/data/taproot-ref/62c572a03d69a6b40d25947abae19bf6ce5eb385 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c701000000252fad978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42f00000000e9e83d9b03a9ff6800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787f6dec441", "prevouts": ["e4a632000000000022512035c5e2b60676b638367c49c5274cc65e6feb881fb1407d2a5f35cf666d25b965", "0b5b390000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063df68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d5f68448c89c580d464efc0ff5819ac3386b6086c96d1a6f5384fcf87289b415a18b5f2fef84521b683d8aac742b48aa2197bd0282730b1a4f3a8fad5441e2c71c315aec02adde316e700f87e7c47f474d1ec7cdd06b196ee567d81a15967a13360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368461da0bf0f5688f9852115eae774a4cdbbb182b967d387ebd70cf0c7ed10d95473717a4c1e901899f4f84b73650625e3fd5128aa3394961893ec6e831ca5ba551d880cc047c10a424f65fe9dd9096492f3efd8e08517d04362957faed36c3f852ff338358c59a252efd0a17af70f1cdfe194eb24c5d50483b26343bf89011bf"]}}, diff --git a/txscript/data/taproot-ref/62d04745f9fcb76848b12153a162a268f14abeca b/txscript/data/taproot-ref/62d04745f9fcb76848b12153a162a268f14abeca new file mode 100644 index 0000000000..66b15aabce --- /dev/null +++ b/txscript/data/taproot-ref/62d04745f9fcb76848b12153a162a268f14abeca @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1501000000e3ee7de3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c32010000003f2fec4a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b8010000006499adc6032e11bf00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc77d690e25", "prevouts": ["38975c0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f", "cb9154000000000022512096d49a663447a0304343e0ca844d9bda5a7da8dbda233b650dfa03e219f7bd31", "eee1100000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bfe22090f7ab89ba3505a6a05ede881092e9f2c3b80d443c66a4d230bc2d602b8024f0f821479c34a3d08a46a80a2c380535e71b033b1c786baa16eef71e1977ae2f7927e5cc4d53e0e18212acda8d85e01e1da74473232947322e5e96654c18"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fabf8cf3051908396d96a16e21f9fb14717dee7b5dfac112f56d0746b9362fe4375cb645b004d221127868eb317b35b9739fc590ddfdd834a11f89e113e113367cae2f7927e5cc4d53e0e18212acda8d85e01e1da74473232947322e5e96654c18"]}}, diff --git a/txscript/data/taproot-ref/62f4696a4d80fd4c0dc13ef75f8bacef6743b8d7 b/txscript/data/taproot-ref/62f4696a4d80fd4c0dc13ef75f8bacef6743b8d7 new file mode 100644 index 0000000000..a6c9eaaedf --- /dev/null +++ b/txscript/data/taproot-ref/62f4696a4d80fd4c0dc13ef75f8bacef6743b8d7 @@ -0,0 +1 @@ +{"tx": "e61fc582038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45601000000c4e2b5b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2001000000c5b7f7db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41a020000002528aeb801fdae1700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7c4010000", "prevouts": ["f0893300000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970", "8b96760000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f", "5e9f320000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "c37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c08ab59be3ec08c5813df127e6171cab5e5b5b7ca033be6df840b5a39ed859095a2fb75442cf9d6444c8679a19413f9a060e476aaf84ff603b3b22173ec950d19a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e8d213d90ee48874bbf2b18160b4fefa78452fd9fac91ad5f640de90a3ceda28c"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936207c9c4f97e2dba2ec4fa9382e1eb978f292c30dbe8b8adc6375e7e52fe13859672094c3f08b9327f7ee48bb8899708766c48e78ef53e5ef370aaf6f5fa99ca1ce42d201fd753cc19d7433434234602e4af838ce265353441a761579b9ecb89c78d53ca9a9f93e78db88a883cc9c42dbf55ad09041fa37b21a93adcd191d7180"]}}, diff --git a/txscript/data/taproot-ref/62f8cb127c31b1882150c0c8effbd39c09119e5f b/txscript/data/taproot-ref/62f8cb127c31b1882150c0c8effbd39c09119e5f new file mode 100644 index 0000000000..d3a313cd1b --- /dev/null +++ b/txscript/data/taproot-ref/62f8cb127c31b1882150c0c8effbd39c09119e5f @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdd01000000e63665ac02286c4800000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc43000000", "prevouts": ["bfd14a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_40", "final": true, "success": {"scriptSig": "", "witness": ["14e16d7dcc2c719c7e163b2e5d81cd4aa9781946ba7ddf2b596d9e93222b1177898e01d1ab846bd1d0ea1ba179cf1ff545f5df4442282765f7d7ac4ec7cb65b502", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["dc9a39165d8459b1342428c6aa2e0ef8334459b37b5e05de37f9f6aae4988063e26e3bbc10fefb72cbc5b57db9c825f3aef3e148754155f667f9a6e541dc2bdf40", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/630f756a29287a797ffb5586566bc1d25758573d b/txscript/data/taproot-ref/630f756a29287a797ffb5586566bc1d25758573d new file mode 100644 index 0000000000..2033b06ee9 --- /dev/null +++ b/txscript/data/taproot-ref/630f756a29287a797ffb5586566bc1d25758573d @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1b020000001b786e618bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ea01000000fb510c0860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700f020000007a80c8d8019ead11000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d2de3b4b", "prevouts": ["ab2348000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "bb733b0000000000225120c52c9d5db69f3d85ee35b65e5555252fc0470ab9a3dcbb72267f75438b29b283", "885a110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369f66c13277c1dff86476ccc2b2410b8070d8457ffe942302ee55e774342eccc7"]}, "failure": {"scriptSig": "", "witness": ["6a9c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/63167cb8ba3874badf57f0e855e7f02478cfd49f b/txscript/data/taproot-ref/63167cb8ba3874badf57f0e855e7f02478cfd49f new file mode 100644 index 0000000000..b62f8c1ce1 --- /dev/null +++ b/txscript/data/taproot-ref/63167cb8ba3874badf57f0e855e7f02478cfd49f @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0a00000000de79a0db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48d000000005b9d85b103a002680000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787cfaf4061", "prevouts": ["7c9e2700000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "aaf3410000000000225120efa68a115895f942057851c042deb7d61335a3ab48b9e56d15cb953fb46ad7bc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "0f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663c49ee3ba831a9a6786c5c6320bc4ec5a81d02658bcf51f9bb482c2f495569c68491001e36edf91058819766439c3f31bd198abbe3d2204f458ac7743e1d61ccf16a5e3db9e2b81c974405e52c4661efcc91a529144e47e78be5814d4a09901"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d14083827bc4b64cda0a8609af1f33bf70388b2df5d24ede096953ad9366a4004be90cc292444734c987c78e965b1739d018b44a402c956c06fcfea30a9c442ccf16a5e3db9e2b81c974405e52c4661efcc91a529144e47e78be5814d4a09901"]}}, diff --git a/txscript/data/taproot-ref/6316bbbc6a41808b00262eab5f5262fcfa97066b b/txscript/data/taproot-ref/6316bbbc6a41808b00262eab5f5262fcfa97066b new file mode 100644 index 0000000000..f21fb881a1 --- /dev/null +++ b/txscript/data/taproot-ref/6316bbbc6a41808b00262eab5f5262fcfa97066b @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0e02000000b7c1fbd004b19655000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787b7799960", "prevouts": ["2db4570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_89", "final": true, "success": {"scriptSig": "", "witness": ["fa33aed19e7348584fb2e7883bdbcedd805b763539f1da675e6647cc47c7cf8245200518f107ca97e6847db03dffcd717091a918e649240547789614cda9158c81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["02fc920bb623b62a692aadd32a1663b38b7e38efd98892807e5637239f974e1273937b6facc07344e9ada57e9e82daf6c971dc41b047e3e9ec58afe26396fd1289", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/63254af008fbdb6301cc07058a867abb97610c66 b/txscript/data/taproot-ref/63254af008fbdb6301cc07058a867abb97610c66 new file mode 100644 index 0000000000..60c37fd7dc --- /dev/null +++ b/txscript/data/taproot-ref/63254af008fbdb6301cc07058a867abb97610c66 @@ -0,0 +1 @@ +{"tx": "17d518f302dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5800000000e32f0abb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48400000000644a2ed2022f4f5700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc20000000", "prevouts": ["c7ec230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b9703500000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ff7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e9987eb7009ccae8c65258c62e5eac53ed5016922d24407b897adc5526f33b91916c082ffd0388de178727289f9edc245ed8244bc4e4186d1c7a66ea621fec0ad"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936481f5e4c3fecd787fe4d3635c6d8b344fb02d1f9c3cab01b9a7177bb21a6fd3df59f882dcce043ab5273f79d0d152c35fae0f251a6812c7f2d3daa07c20029a516c082ffd0388de178727289f9edc245ed8244bc4e4186d1c7a66ea621fec0ad"]}}, diff --git a/txscript/data/taproot-ref/633faf2de8dd00d4d8b3bbdda4d9f2125613a89d b/txscript/data/taproot-ref/633faf2de8dd00d4d8b3bbdda4d9f2125613a89d new file mode 100644 index 0000000000..c56385f932 --- /dev/null +++ b/txscript/data/taproot-ref/633faf2de8dd00d4d8b3bbdda4d9f2125613a89d @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41400000000eed2c5da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fa01000000017337ee03ceba4600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc71b7ed33b", "prevouts": ["8c5c36000000000017a91454957ff2b5c5fa7ace3c6fb485b914ecf6ce0c8c87", "2b5b12000000000017a91441ce0eb0e6e5800ced23a872818e5aaa63be0d5b87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1658142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["e73fcdf715aa776aab30a3a370117f5b9829a61e46b42aef46f9dbe2cfd582db4708e22a37de45f7b5fbba25fad2da084132d00e1888740299f644cae68b1224", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/63428d34338ada0748fdd95dc5f6db204de7543a b/txscript/data/taproot-ref/63428d34338ada0748fdd95dc5f6db204de7543a new file mode 100644 index 0000000000..3cd8ad8743 --- /dev/null +++ b/txscript/data/taproot-ref/63428d34338ada0748fdd95dc5f6db204de7543a @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46b000000000540a8d7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd30000000018732d9204c7b2b20000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5c000000", "prevouts": ["9d083200000000002251202ae35af575feea0dc18681bbd0ec0494b44b5926493fa5426b4858bf97ae878d", "4972830000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a19e3b1d939cb6a23d473766b748a130ade8f2a056e565bff706cd0491e745bb"]}, "failure": {"scriptSig": "", "witness": ["6a42616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/634458fa7be2820b5e56c8ae2c193b953af0ad40 b/txscript/data/taproot-ref/634458fa7be2820b5e56c8ae2c193b953af0ad40 new file mode 100644 index 0000000000..3af8a0b6cf --- /dev/null +++ b/txscript/data/taproot-ref/634458fa7be2820b5e56c8ae2c193b953af0ad40 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfc01000000e1fb988b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4080000000022028f9adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bea01000000a94b1fb4012f9338000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748777000000", "prevouts": ["30532100000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "b5243b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9a341f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_da", "final": true, "success": {"scriptSig": "", "witness": ["cc61fb581a65202f50b21e47d9e6512cb734d9ba5f06c87419797443abcadc2635a00a7a7e41d9c7c8b5413245d784be457434462df76d27e0824ee448e883e081", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["adf0f76363b1edc4e497a309491f6dc98e6d1ad1ad455fe8c72a0dd71a1630a596543e0f40922612ec9f654784002c61ac9cf7bb45da655c711ca10d28adbcabda", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6360d46053a73eb3d4ae1cc875f022d5d461f571 b/txscript/data/taproot-ref/6360d46053a73eb3d4ae1cc875f022d5d461f571 new file mode 100644 index 0000000000..95043a36cf --- /dev/null +++ b/txscript/data/taproot-ref/6360d46053a73eb3d4ae1cc875f022d5d461f571 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b45010000005275e07903f06b1f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1a010000", "prevouts": ["975b21000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "47304402200e4c2a11ca32ad615fb9e488fb9cdf0efc97c07b809095d014306faa39c1706a02206c88c9f9bf9508ceb9b70db058cb52c3121c091c3a0324bfd0f8b32cfe6534c183434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "483045022100b7c2eeabd221d1d26c576a23e5c724ea87662555f661eca76a32b7d7ed8d3f1702205b778f07aa13315ab18107518b3759dce5d8f60dd1c8ef82162cf56a30278e3c83434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/636131ac174bfe63b118e739bb030a2fae2ae0ed b/txscript/data/taproot-ref/636131ac174bfe63b118e739bb030a2fae2ae0ed new file mode 100644 index 0000000000..123ca7f2b3 --- /dev/null +++ b/txscript/data/taproot-ref/636131ac174bfe63b118e739bb030a2fae2ae0ed @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c470000000032889c918bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42c01000000160157c404c8ce8b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac88000000", "prevouts": ["2b65500000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "d0313d00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f7bc8d0bdc62b39e0e9c19d19fe3396114a1c841c50c9d6fec174cce198aba7d6cf9133aa763ea773cdeeac140de5c57dceee670de232cdd7f30405a52d22152c579d688b4f95dbfb27db809d6672e68433faf56213dd258fc375d7f1025581eff39b384b66ef78da8b5e0fd063098e306be159c39b9bdddd361b672f78fcd4a613242676014fd3768df8f726d2404332d810bb7f4f63fd447db170e8ff867a34a9cccaa1fc93353cba8eb3475cfbda4e27185757a4e54e43226365dc0f001362302833007e228c040015b1174b8b4237b9305b896720229169522f72b3cc0bd80743828e7844f5937e757b79fec363ab9c816b81974ee2f4619264b2bc91182eda6dc4ae2623b8a1d441c67b140e9a05e99107003011fdd6f6634dd3bcdc7ea430fc98bc2df94555dc7a8ac328bf55ac32217dbc35cdda6eb371067d22417f2a2459f960779e3789eb2e1dc7d2336fc20fb0a5ccf274db57235300fa0f463274794e151a11054804ac0128d76605b3421c36860aa113d488503f68a3c4c3397bf8df2cfa3eab9145f1b94516af2808c8161eede6b1d695e470f3ab43d788ba58a9313fbeb34f758e619c5f570da564e0595a22bc3d8dfb57928bf8c3ac435718da6618e0ffdcd5621dc77c98abf0213aef4eb2e99c4a8e320c818bea2191f40abd0834e1892777424382df9310f9dd1f5cf781b44c2c6669952ff8343924ea9bf6824e455576c7f0075cd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb43f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820aae41afa256ed506dae95e698e8dcc0fa26e2618e50e74a83d05bcf51ab890d620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}, "failure": {"scriptSig": "", "witness": ["4d090237aa9b18b4a7c908c5ae34894588ab96e245b74fec1610a49973392d6eeb6c62c6b55ff2af982a6c76cc379da7e493b10624673a2a6066fb0be803b8621e0250d0ffbba6300bc37b3e88c8df9651a41a3bd39c21e18a47527df7c1f1811b3a853dd5c0da23ab87915a78b77947ddc576e6dd88cd23d852fd9f0be1071eadab098fc7c34bdb3fb71c0c78b3878a11d7879e701374ec5e5e7fa82bcb7eb3184aee94d64a30695e99b9cbe54e4e1f85adf00a77b25b8ee341fddb7f500a1a79b56eaa4c9b1e40db48d11e160aad7e38abbcba2cf3bc8370e2b2f02ff957d174c51f74d6f8890e956a1bff47324cd1d2e8a645ca5b93aba2422eff9aece190871e5f8d8ec150a9026df3deae44b69a8e232e45f4c492062e38b6cb50cb740073d00ad61f02db0723b7c8fe4bd0d684fbe14e52694a717b2e08cc661d6d7bc9a94c218fa998141a6b67f89d9439c6aaac1c09ba4650fce90b887224479f6eb3a7214bdc445b10402263516da19e5539bf6f1092bcf30b97f28afa77531d922822476e186e957fcda37c306549ec22653a1f0f6f9db877fd8ff8baf769a5aafc10771ed5edb13c5b00b09be23c47c4aa55fa4149f79b3ab283470802dec04e1aa292c7534484fe0fa5a193ee5d338ad4aae61c4e68b94a10284c1a5793d533e8b453cc7dc36f2fd157dc760505b14c29f24a53af123b970da92597069e0f2583333aa62a9f2afa3a4b2a42e87561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004520e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e11863a41bc3dc2a7aa524e62e66740ce82713c2a995d68e9803c1affe373c89601029910a453e765cd82c29c3b576a90579a453f3a941b6b6175fa922e9a13196"]}}, diff --git a/txscript/data/taproot-ref/6391af63a3bab91b1f963e133bbb54d1ec7814cb b/txscript/data/taproot-ref/6391af63a3bab91b1f963e133bbb54d1ec7814cb new file mode 100644 index 0000000000..5d9a1e3ab4 --- /dev/null +++ b/txscript/data/taproot-ref/6391af63a3bab91b1f963e133bbb54d1ec7814cb @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaf01000000ef6fe8da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703c00000000151d319e02c354820000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acb4e81421", "prevouts": ["e0b1750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bc630f000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_cc", "final": true, "success": {"scriptSig": "", "witness": ["06c67c2af3e5d7e192675c72c1500639a3ec0e5b44b307c185cf19ae7fd8dee755a6dd69b80e43b1c944369de37d14f6aee25ee59d3ae30109ac4123e23dd30302"]}, "failure": {"scriptSig": "", "witness": ["25f6e6831fac5efe19a55328d4265e5ab4f29d1e290240341433446d9cd7d119c5e7f17f665a5986a8924a99932b9f953f5915847b7e65e94c5883af0210382bcc"]}}, diff --git a/txscript/data/taproot-ref/639afaf27cd09001a498697b15842c3394f9535d b/txscript/data/taproot-ref/639afaf27cd09001a498697b15842c3394f9535d new file mode 100644 index 0000000000..192b7934ed --- /dev/null +++ b/txscript/data/taproot-ref/639afaf27cd09001a498697b15842c3394f9535d @@ -0,0 +1 @@ +{"tx": "2b7a7ca6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4700100000089a957d260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707900000000d42a2be001ef6b390000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79653020000", "prevouts": ["076c330000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "f6b10f00000000002251204c956d2ed9840e95134d355554a887a299d70036ebf1550bbadc52fbd9ddc36f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/invalid_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["532e6937d0b26d3c96951d6910ffa78e5bc2c3d0a11d3635f6fd0066e011d574610b77cb12c0dc44a621e269efcc4407c852f8e03b55638be401f087e800511e", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/63b0cec5acbe499ece5bd821c8af36dd0de95819 b/txscript/data/taproot-ref/63b0cec5acbe499ece5bd821c8af36dd0de95819 new file mode 100644 index 0000000000..e7ee124a51 --- /dev/null +++ b/txscript/data/taproot-ref/63b0cec5acbe499ece5bd821c8af36dd0de95819 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4200000000909948478bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47a00000000b7bad9750152878e000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47877d532648", "prevouts": ["407b6800000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "67d73c00000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063dc68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e122ac0f20434af06d5694002e66a328e774b08c17356336e0bf0019524f47df1a7470af5f469e43c444817efa23ad8740a4ec3822d36804e7973b39d521bdef59faeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb43f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08238e917535475cf2110d0b0ae2ac5bf0f6bfd0fb66e9319f96694509bbaa8cb206d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}}, diff --git a/txscript/data/taproot-ref/63b754b26183ec079fd02af865aea1d5c49d93cb b/txscript/data/taproot-ref/63b754b26183ec079fd02af865aea1d5c49d93cb new file mode 100644 index 0000000000..b327557833 --- /dev/null +++ b/txscript/data/taproot-ref/63b754b26183ec079fd02af865aea1d5c49d93cb @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49000000000575c18d0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6e000000009b12d9b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6201000000323bd29c036d5608010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6ca6eb94e", "prevouts": ["b77b360000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17", "a9315e00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "7c80750000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "b17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cd3d9bae846d1e9f19df02762e6d45be556a5a66cadc4939a21519cb29aca313804e0ef706f1ca5c8b2fa38155abc6bb5e2265734815bc03afdad0836bb7f05989f510e73a03c44610e5cde856f75a0d7582565d561698089d126c5e7f66809"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93609b57e90423a4849aac73da1b4bdfdd2798990ba600420d32cf466c1f0d36594d9568d9f877f6ca0cee9df3d4970d26d0e286b65747316dde3c995de6e71d9f55bc912f5bf4aa2c9ddbc9747d59c78f40d0a0aa0a8a4f22dc70e3f9cdb9b6ae3"]}}, diff --git a/txscript/data/taproot-ref/63c6cb5ef992299a9604582c39c7f956c65860b3 b/txscript/data/taproot-ref/63c6cb5ef992299a9604582c39c7f956c65860b3 new file mode 100644 index 0000000000..1ee2a6a8fb --- /dev/null +++ b/txscript/data/taproot-ref/63c6cb5ef992299a9604582c39c7f956c65860b3 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702b01000000563eb1acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfe0100000075a2baca015d162200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca7030000", "prevouts": ["503d1300000000001660142540f27e90740933c99d4f17ab2dfc6c82951cfb", "112b4d00000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["cd6080e32a37eed9423b6209c11b9115af7004c3f774d587368b784e2d008cb826acbfaa43d1b4f66476a1fa51cb847dfc530f1dbca5a3d261af4280ee787fcb", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/63c8bbd564a4a1648edf9f05d80a6b089c40883c b/txscript/data/taproot-ref/63c8bbd564a4a1648edf9f05d80a6b089c40883c new file mode 100644 index 0000000000..3d54c3c6ed --- /dev/null +++ b/txscript/data/taproot-ref/63c8bbd564a4a1648edf9f05d80a6b089c40883c @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fb010000009399fa4e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c300000000bad4681203ed4f4b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3cb80434", "prevouts": ["c70b100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "38fe3d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ac", "final": true, "success": {"scriptSig": "", "witness": ["0eef8040e6fb98e9abf015034e584ef1376f63fe98fd888c6c7365fe0355f1aa5f1f9a0a35e483773b76f251cc0f7d187c9f080de5f67026a8d4b6eb7ea802b103"]}, "failure": {"scriptSig": "", "witness": ["c4a8ca265e1edaf1797ae5c8dec8e3912ab289ecbcc62a92fd850f7404e3d5fe154e317f22a7dd63c77dfb8bb7e734bd39ca8584e6f54dddcff6034765110560ac"]}}, diff --git a/txscript/data/taproot-ref/63cc94dee9c6256ddfe004eb9fcabb932627fcce b/txscript/data/taproot-ref/63cc94dee9c6256ddfe004eb9fcabb932627fcce new file mode 100644 index 0000000000..24330e791c --- /dev/null +++ b/txscript/data/taproot-ref/63cc94dee9c6256ddfe004eb9fcabb932627fcce @@ -0,0 +1 @@ +{"tx": "044da27e03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdc000000001a07b0b4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9501000000bff781dddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bee00000000ac3a7bb4026db9df0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67e030000", "prevouts": ["ca4f73000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "2fbf4b00000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "e43e22000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3e1f31af440bd9528b56a4b582a327979fd28cb44b9e62075e623987b4c0f8e3992fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900452c1673aa1d348e5f2f8444d57c2e384a9e542f3652a57ab10bce8213eb35faa5e1f31af440bd9528b56a4b582a327979fd28cb44b9e62075e623987b4c0f8e3992fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}}, diff --git a/txscript/data/taproot-ref/63e781018cd701d6d445dc7c4ea28f9a53de825f b/txscript/data/taproot-ref/63e781018cd701d6d445dc7c4ea28f9a53de825f new file mode 100644 index 0000000000..6c4791f121 --- /dev/null +++ b/txscript/data/taproot-ref/63e781018cd701d6d445dc7c4ea28f9a53de825f @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4050100000060d5b89860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c5000000004169b1a9047cec4d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acecddd42f", "prevouts": ["b7923d0000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "523413000000000022512097f3f32bbea7bd397ebd6824dc6e34758f0b169a6c237662287beed33756fea6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["bd4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f8a7004a68fdc05e100340c712f74a3d62667ca0b5d0eafc5e716949571fe18725432b67bf7a212872373c5ea5ac6512ad650fe3d5c26e1d584bcbdba0083b9a9e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}, "failure": {"scriptSig": "", "witness": ["4c52bd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363dcaea11c13b9b36db1e711f26b17d850c4278eabda72c0bd6c73a20768b7a5e98751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d50e634e19498d3396bfa452af2ece499faa564dc4b58fae514f4ede8dd179fb909e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}}, diff --git a/txscript/data/taproot-ref/642e1fbd4f64d1ba035193a0100aefc8d436121a b/txscript/data/taproot-ref/642e1fbd4f64d1ba035193a0100aefc8d436121a new file mode 100644 index 0000000000..9e886dbf6a --- /dev/null +++ b/txscript/data/taproot-ref/642e1fbd4f64d1ba035193a0100aefc8d436121a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9501000000ea4b4ae9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c140000000035454f190291a37500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac963fce3c", "prevouts": ["e1f320000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec", "dab856000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "bd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936061ae028cfb8cb00b52e1357b0e7a5a4109afe42dd36cfc91bfdcaee18ccf3547353a90cd56d8edfa9d59a5341a6c829ef2ec5b70cfecd5055b0e6c18dd5375841cfbdca9cced9a9297ecbc29dffc929789a1848311039b5a24b338cddf0aa70"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea156570f3d071b1e4b25e8baffac9afb6306bbc5a1ad7382e42273c38ec7578357b0da8b61d649cedb8c014d8a901c8639aee676049f740bf8079132edd04aed797dd6acf95c24b81e793c9c81b0ab80d381fe8deb935e4a90684c96acd4587"]}}, diff --git a/txscript/data/taproot-ref/642f40f85c3e92c672ec038a2e238351c6c24178 b/txscript/data/taproot-ref/642f40f85c3e92c672ec038a2e238351c6c24178 new file mode 100644 index 0000000000..4d9e41f937 --- /dev/null +++ b/txscript/data/taproot-ref/642f40f85c3e92c672ec038a2e238351c6c24178 @@ -0,0 +1 @@ +{"tx": "cc2a29fc03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8901000000c830c9abbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff100000000746406a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9601000000bd8ec8fe0286b12d0100000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cc349424", "prevouts": ["6a2b66000000000017a91408247b8d3db4e641d0be1ff23f14280256870a5187", "2f55760000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0074530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_6d", "final": true, "success": {"scriptSig": "", "witness": ["5925493590a1b0ce31553c34efbce5ab7e562ee82229ecc93b7176d52e25172f384b4b102d066dd69f65ec2b85103529c9ebb44f85e134f28475a26d682940c981", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["29706265b3834a43fed40dcc0cd7e5e09c120a09a70af16e08e62e9a0b8f2ee4084015afc0ad3cce7b499204bdb19e59be7de3f63af528d8e5f3de09dbcfe82c6d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/643386ed0f556a2227416f5b32e310b70a2cf743 b/txscript/data/taproot-ref/643386ed0f556a2227416f5b32e310b70a2cf743 new file mode 100644 index 0000000000..a5b3aca4be --- /dev/null +++ b/txscript/data/taproot-ref/643386ed0f556a2227416f5b32e310b70a2cf743 @@ -0,0 +1 @@ +{"tx": "4c61934d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b570000000092d58fcd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45100000000baffc09e01cd1c3700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acfc59935d", "prevouts": ["cfa9260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1b133900000000002251200120da136b46f6e1c164adef9ba0d2bbe634d7767c7946122aa4909c89df2221"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369892bcceafa0b9465950a6b9b3f74549d7ae8a8c1917a73c91a30481b31306c0"]}, "failure": {"scriptSig": "", "witness": ["6a7a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/643f751fa11ea6d366ace6319feda720f2e8accd b/txscript/data/taproot-ref/643f751fa11ea6d366ace6319feda720f2e8accd new file mode 100644 index 0000000000..4839589471 --- /dev/null +++ b/txscript/data/taproot-ref/643f751fa11ea6d366ace6319feda720f2e8accd @@ -0,0 +1 @@ +{"tx": "35adfe970360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d5010000006640029abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf78000000003657cfe8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdf000000008532f2b1014faa6c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4871d222b1e", "prevouts": ["96730e00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "d08c660000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "f2fb7b00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93656b2e44901702d460c7de97890111dc615bb44671c92f59d31a1c2531c59c007affae472ebffc4152ddce3f20794b01737e96becc2bb4a1a296a47c8ec0d29af569af0f9e86656db21fe5e74d4bdcdfc2cda5437bccaf9e3d568ba1282fc608d76e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1f12e5bdadb74bb113beeaaa5995d4ebaa92337455ee51746db1fb6fe7db125e52d50ee9aa3de1fe988255b0d8b9f34dc2cecc4a96432b9f704e90359a06b468476e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}}, diff --git a/txscript/data/taproot-ref/64537ec43a7b2b59f2b936c7247b94e44e1bb551 b/txscript/data/taproot-ref/64537ec43a7b2b59f2b936c7247b94e44e1bb551 new file mode 100644 index 0000000000..c17f4e1810 --- /dev/null +++ b/txscript/data/taproot-ref/64537ec43a7b2b59f2b936c7247b94e44e1bb551 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45f00000000788b972abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf02020000008b773e1560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702b00000000fdffac0001b6184e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8721010000", "prevouts": ["39113f0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "8f097000000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e", "d0ef0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641cc9c8285f79db4181623fd29c0ee1439eb4e8d4cf6c70106fa0146ca9f07d3ad1faed220136b938a4936a71b98f5f9e86de449242d6a82efdf7a3adba2ae62745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ab8d96c33f2aebdb2c8ac1cafafbc25c65e9bfa155bf2db52d1cee9a44b59f1419220fa8a7a918b3857a082d32be9fa2ecc61d36b58eead0239ee9c5d9d4afcd5a470b8497850c3a230fee464eb343180400453804118582df887251250b2f1"]}}, diff --git a/txscript/data/taproot-ref/648fef1a9a568a6e98c2cb836193a18ec11b60ce b/txscript/data/taproot-ref/648fef1a9a568a6e98c2cb836193a18ec11b60ce new file mode 100644 index 0000000000..30766cecc0 --- /dev/null +++ b/txscript/data/taproot-ref/648fef1a9a568a6e98c2cb836193a18ec11b60ce @@ -0,0 +1 @@ +{"tx": "0b6fe83703bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffe000000007cacfbdb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c468000000009c09df848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f700000000774f468401c92a7500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acbd79e031", "prevouts": ["dcc37900000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "129d37000000000017a91439ec132e1466f40f0086baa7ac253013e83c7dc387", "bc53380000000000225120f3eef30b2db388e6b8a313ffb142e2e6ffc970ce6b6a81ae6dc1d81725c678ea"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "215e1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["e9df93b6b02ca0341b0345a2523cec9961d8ca0d900cfd5450582da4b60610363d1cc329fbc34c7929fa8007b99f10aade2fbebaa3985bca24226f56725bba88"]}}, diff --git a/txscript/data/taproot-ref/64b6416da57fa74cb892f8728aac8bc6064ac5dc b/txscript/data/taproot-ref/64b6416da57fa74cb892f8728aac8bc6064ac5dc new file mode 100644 index 0000000000..279ebb88e5 --- /dev/null +++ b/txscript/data/taproot-ref/64b6416da57fa74cb892f8728aac8bc6064ac5dc @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1101000000a081b3de60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127053000000000c7b5fdbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc5000000006f40e899046516ab000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c6030000", "prevouts": ["bf8d4a000000000022512074a4c3567b4c4ece2d1ea256a6bf2f85bf4dc051497bd8ce7ed8816e2d4c108a", "befc0f0000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "19b35200000000001653142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dd5c8e7f006a3ea431b7b4119ba3be3e8bd1aa47a62245ee7cd009a4a7fa39b4"]}, "failure": {"scriptSig": "", "witness": ["6aaf616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/64c1ab90001da13422d892838a22208f71109eb2 b/txscript/data/taproot-ref/64c1ab90001da13422d892838a22208f71109eb2 new file mode 100644 index 0000000000..ae7bba12d7 --- /dev/null +++ b/txscript/data/taproot-ref/64c1ab90001da13422d892838a22208f71109eb2 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4680100000014cd4d66dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5b01000000d231e7ff03efb58d0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc27030000", "prevouts": ["9db93700000000001654142540f27e90740933c99d4f17ab2dfc6c82951cfb", "7b045800000000002358212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["e306379641defa88af163715a7c95126d1913945bd4b8d1a728c7e37d4b3879888f06f2be13e87d68eeae13ce45da9a2c8cf25215a8c593795cbbd4bd7a3aedd"]}}, diff --git a/txscript/data/taproot-ref/64c86a5fba96a19af3d7f98cb11533d79ff4433f b/txscript/data/taproot-ref/64c86a5fba96a19af3d7f98cb11533d79ff4433f new file mode 100644 index 0000000000..762e10fa42 --- /dev/null +++ b/txscript/data/taproot-ref/64c86a5fba96a19af3d7f98cb11533d79ff4433f @@ -0,0 +1 @@ +{"tx": "c3d0c9e202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf390000000058e04188bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfba00000000df72ae8d014799bf00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf6020000", "prevouts": ["18f26900000000002251200f726ea607d510d2ad25fd6aa0b3aa5046595182e7375298ea583ba69075a433", "51817b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369c9b89f6cd1c0bc520f57d1b93bb5b773cda74c14172240a9ebd81fab92ee691"]}, "failure": {"scriptSig": "", "witness": ["6ab5616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/64c9c1019b362e31675420967685e3e5e1d92f06 b/txscript/data/taproot-ref/64c9c1019b362e31675420967685e3e5e1d92f06 new file mode 100644 index 0000000000..4204f71eaf --- /dev/null +++ b/txscript/data/taproot-ref/64c9c1019b362e31675420967685e3e5e1d92f06 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccf010000000c1a2eeadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce100000000a5df58b402ee86b5000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac3e5be55b", "prevouts": ["6a2c5a00000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "604f5e0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "087d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd691c2a9908d9e7287fb91837cd9c32b2a21ac331bb306f4648aa27bb40422e45371e41a07562523a12648be26bdba66be78ce7e249298c356e66cf29847872e0"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367afe96f638fbf89584e25dade4bd67dd7e08c3a6572904b143b56a75af676e5d55b45b3af2af0c7a238665fed9a70950b75abf30a3f75b50a7b1cc61308c32d3371e41a07562523a12648be26bdba66be78ce7e249298c356e66cf29847872e0"]}}, diff --git a/txscript/data/taproot-ref/64e713b456a3f23cd86eeb23d796639b7c85d2b6 b/txscript/data/taproot-ref/64e713b456a3f23cd86eeb23d796639b7c85d2b6 new file mode 100644 index 0000000000..b48f7fdf9e --- /dev/null +++ b/txscript/data/taproot-ref/64e713b456a3f23cd86eeb23d796639b7c85d2b6 @@ -0,0 +1 @@ +{"tx": "dd0484290260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127004020000003a1f3dc18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b2010000009ee9318602534e47000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c9000000", "prevouts": ["e68d100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f4e6380000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_9b", "final": true, "success": {"scriptSig": "", "witness": ["01b5c8ffe0fbe48bc5aca298e8db8dcc9ae87ba7f6984815658060ceb708fdc1c00550e225848d5053e613c4d9b2f0dd8328ce4568f7eef204ccaea60de2a66101", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["84337753e8761f22cf9b0f9af87f32d092bb5d8092d70fc83d5f9e833d4512fcd2264207937b6394e059327eb67f923d45b0cb194c3daf68579d656615b3aff89b", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/650b0fcd68979a929ceb682e9024fb7beb57c2b1 b/txscript/data/taproot-ref/650b0fcd68979a929ceb682e9024fb7beb57c2b1 new file mode 100644 index 0000000000..41208d2f74 --- /dev/null +++ b/txscript/data/taproot-ref/650b0fcd68979a929ceb682e9024fb7beb57c2b1 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb6010000005bd07d78dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4800000000f3fbe79504c03f770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cf000000", "prevouts": ["6300560000000000225120df3728be21c89bb919091ec65a63fe2d83dc46feb767b141518f7734e1cf94cb", "b400240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bc3a384262d56f91b8a88cf4efc3914e768fb5c0b907358dff504e87b4ee0842"]}, "failure": {"scriptSig": "", "witness": ["6a74616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/652f7178db85a30195aec38e5bed56f8d492b18c b/txscript/data/taproot-ref/652f7178db85a30195aec38e5bed56f8d492b18c new file mode 100644 index 0000000000..41dc25ac66 --- /dev/null +++ b/txscript/data/taproot-ref/652f7178db85a30195aec38e5bed56f8d492b18c @@ -0,0 +1 @@ +{"tx": "c9c8ae8802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1d00000000fad144c4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9c0100000062d84ea8013cd619000000000017a914719f78084af863e000acd618ba76df979722368987428c8e4e", "prevouts": ["70f55500000000002251202411d699451e61c2ae1e9b07727f82864d3d401db7c2ec25b77e3a65ecc346bb", "fe6e240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["1e61d4d855ac6c46c9a99357789b79a67c50ad0de37287346a5acebf771114a1c8cb61f569b8b43a09ba674e89746baf16e1641bf951ef5ec1e7f7bd5e8d9197", "727f14770010c2293269cf848fb9991b29f239d9c1f3ead46ea41aaabcb616b7be4fda6cf5e3a5dcb5f3218b23531158cc6113c61d383eaef8f87882ab91f065ddfdf3ec975aabeceab120e48ff5f8dd9b577221b0a1049448f1b8b1693b5640f5f859c963247f679f6d34f6d497a9807104871df6022d7a336f8272d601bce26894ae75be976b93c3b2812ec7071b7e4a3ce8928171501e40074666f47ef0e68d3f672d4086f5b8eb013076c595e6428e55dbf3ba5642f920abf9247c5932b69396a7b69eeefd26749fc8eb4235", "750029dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b3250ac916929dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32506eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0daeff790ac0750a5c97c555dd00ad0e25822157617ee0633a1c9b091c67347000000000000000000000000000000000000000000000000000000000000000054273997c6b5f26f691e4d5428bee747f4fb577690066e33fbb86cc3a2ec9b53342550c32fe8e6b835909b157b681845926ff168cbfd9ff5cfb54bd6c774fd9157c5d03f132c6d240068d51b30f30e3d7b2786a2118a8eec0900f5b646cc34a216bbd72ae4633ad4d3f914989b57cd89ca1399cd505a1fed4f763b0e00d4674c2353162f5cadf9b6f3c32b777520a5d562a965fe0a5f3e985bdf7f770a65a1983f523a753630238635a85401e644b6ffd443cc41b1b226185056bff8402c91513dcc58ee4dd7ea460fa36871f87f40a7dce08d15f9f39cadf4ce5d6057706e74a452cd80efddb984cb2088de76d83d12c012975f6f8909fb41fa3853970f3c67"]}, "failure": {"scriptSig": "", "witness": ["1e61d4d855ac6c46c9a99357789b79a67c50ad0de37287346a5acebf771114a1c8cb61f569b8b43a09ba674e89746baf16e1641bf951ef5ec1e7f7bd5e8d9197", "d0d93a35ab56efdcbb0a0e948031ef7643e0e563ea007031880d0109b960bd716dbe481be7067ae39e002abb4c1dd69ed25b0c0cfba0de2cab8de19782402fbeea47f63dc13713f9041abdb84c2c9952a35c9a548255dac8e524701ed1d10e5f045f9569142255c08b330f35bc671d289d3b8ec4628587812c2c5a6c36e67fd682e8dac3f882c7214d3c52ac6d6c621401bcdc6df27628735ab4407dbf32371b54fc8d5462a3c3f9caf35df9bc2366a5d89844d292e8352eed73b060af31b8b85e7bf937e73ad4aaaa00098bf8", "750029dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b3250ac916929dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32506eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb0daeff790ac0750a5c97c555dd00ad0e25822157617ee0633a1c9b091c67347000000000000000000000000000000000000000000000000000000000000000054273997c6b5f26f691e4d5428bee747f4fb577690066e33fbb86cc3a2ec9b53342550c32fe8e6b835909b157b681845926ff168cbfd9ff5cfb54bd6c774fd9157c5d03f132c6d240068d51b30f30e3d7b2786a2118a8eec0900f5b646cc34a216bbd72ae4633ad4d3f914989b57cd89ca1399cd505a1fed4f763b0e00d4674c2353162f5cadf9b6f3c32b777520a5d562a965fe0a5f3e985bdf7f770a65a1983f523a753630238635a85401e644b6ffd443cc41b1b226185056bff8402c91513dcc58ee4dd7ea460fa36871f87f40a7dce08d15f9f39cadf4ce5d6057706e74a452cd80efddb984cb2088de76d83d12c012975f6f8909fb41fa3853970f3c67"]}}, diff --git a/txscript/data/taproot-ref/6536f2a8bf497dc4fb07e6344571b041ddf3e9ce b/txscript/data/taproot-ref/6536f2a8bf497dc4fb07e6344571b041ddf3e9ce new file mode 100644 index 0000000000..ba973cf12d --- /dev/null +++ b/txscript/data/taproot-ref/6536f2a8bf497dc4fb07e6344571b041ddf3e9ce @@ -0,0 +1 @@ +{"tx": "927a8af202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0902000000a680769e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c499000000003a7254960188a41e000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47871c050000", "prevouts": ["48375e00000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "babb340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b8", "final": true, "success": {"scriptSig": "", "witness": ["7bc450271610fc51bd47f0c60788ac3ccc38fe9e467ede448d0778b38acdc3731284425f5489c5ab7f7c67fcf29bb992a5e0c77cf4d03024a99a46d1837efea882"]}, "failure": {"scriptSig": "", "witness": ["06299b3516f1110561ca47a7acf31b7d84b22b71657bd54a6373e08be5501effbc6d03ff8b4fca485c2326200e3c9628893e52cd992c11296cfcb6cc6df446c9b8"]}}, diff --git a/txscript/data/taproot-ref/6552bfcd6579a934948b7068b4c551a0117ad0f9 b/txscript/data/taproot-ref/6552bfcd6579a934948b7068b4c551a0117ad0f9 new file mode 100644 index 0000000000..7a2040fdce --- /dev/null +++ b/txscript/data/taproot-ref/6552bfcd6579a934948b7068b4c551a0117ad0f9 @@ -0,0 +1 @@ +{"tx": "57a8be88028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4360000000053d6dc89dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c050100000069ebfe9f022b60820000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65c37ec52", "prevouts": ["657a3100000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7", "1017530000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "167d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e83f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828719dd3b5606bc946287d150a5ecd03b0f8e892d08bbecd28ea2e3769111c28051e3355b9fad1d20bddcd1a8531bcd58c93c4d9ee4159d68db4e08ecdffbe17e"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93632f8e635991ab12ca03b6bac9af37eb87a63c2667988d569707a1da1ce4c2228654bbf7a6388e898988522fa7e5d2ba9e6951646cde29fc617f56e0c3d8e4d50afd13a3b2c4c421c5355668ae9e4eec8bcb7618363c6e35efd204a43726d22d6"]}}, diff --git a/txscript/data/taproot-ref/657e868eb96e89c02af5430fd6fd6b371011ad19 b/txscript/data/taproot-ref/657e868eb96e89c02af5430fd6fd6b371011ad19 new file mode 100644 index 0000000000..a66d6cbb8f --- /dev/null +++ b/txscript/data/taproot-ref/657e868eb96e89c02af5430fd6fd6b371011ad19 @@ -0,0 +1 @@ +{"tx": "3e1bd7390160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701a0100000098cd36e703a3950e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374872414a15c", "prevouts": ["ae6c1000000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ed7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082a45769ff8e70e4bb7b91d42acbbb62837b0e871ab760bcabf7dfb792b2e999f3b131de5807af4725e3fdc8c81388bc895736ddb6e799e7163e8586c833ffc627"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e81749aa0b5d70f518b926cb476468410836d749f7ea53df886cb06228889683d97e5e7dcc199a2f568fd88e83eadcc582fbeb8fc2cdeb8c853fb2288d51fac1b4d19f2c0f6744ba7ac1f5ff1e4bbd0a31d1cdb1f5d58d1dbc476492d0098121b5"]}}, diff --git a/txscript/data/taproot-ref/65883b58c6b3dd90d25b39f5ccc47be52f17c9fc b/txscript/data/taproot-ref/65883b58c6b3dd90d25b39f5ccc47be52f17c9fc new file mode 100644 index 0000000000..f91b386c9c --- /dev/null +++ b/txscript/data/taproot-ref/65883b58c6b3dd90d25b39f5ccc47be52f17c9fc @@ -0,0 +1 @@ +{"tx": "065bd6d102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4500000000c1b6cdc160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270180100000068d0aff1028cb48f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69a350326", "prevouts": ["373e83000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "e4e50e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "a17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364a06e2178fe69175d6529a39be816f8352bf9d327635b0fd8c53cf86695522e146c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa09531ab440e1705f1c4b791477abf2a4fd5d47d92b3cb9e3998348c9d3a452b095176026b3e005afce4c10b5e59a002659822bde369bd64201565ae4c88fc95c"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936054a1904d9cec18d14f2a24d862d1037aa0e706c94223624db69aadf9635fbba09531ab440e1705f1c4b791477abf2a4fd5d47d92b3cb9e3998348c9d3a452b095176026b3e005afce4c10b5e59a002659822bde369bd64201565ae4c88fc95c"]}}, diff --git a/txscript/data/taproot-ref/658ae5cbb0d9d2acbdf007a1d56b7a8d343343c5 b/txscript/data/taproot-ref/658ae5cbb0d9d2acbdf007a1d56b7a8d343343c5 new file mode 100644 index 0000000000..1f58253154 --- /dev/null +++ b/txscript/data/taproot-ref/658ae5cbb0d9d2acbdf007a1d56b7a8d343343c5 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b14000000005d6cd1b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bd01000000cedba4cd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700102000000d9229fe1044be13e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c7040000", "prevouts": ["a80a1f00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "1e3d120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "67ba0f0000000000225120fa0c69fd3dab50066606d386e9137466ea422a077bab3cf3dc61d0cdd59f488d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ba", "final": true, "success": {"scriptSig": "", "witness": ["32c2327693d0bd2a234db09703de879adc7f3dd8758108608a267983bfcddcee57a1c18ce22d84579cfe5276f155338373869c36d45321d80bf2428090bd137881", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3a549ce4fc3d62f541fffe6227d9843d2c6148b2aec9bd8421b176fcd9fa9fa334fdd185140d94f81b290fac077123231421d36f5e0c73203d93796a27124a0cba", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/659a2dd2fa1b9d801f3241e5ff84637ce06ccb77 b/txscript/data/taproot-ref/659a2dd2fa1b9d801f3241e5ff84637ce06ccb77 new file mode 100644 index 0000000000..71c94c3512 --- /dev/null +++ b/txscript/data/taproot-ref/659a2dd2fa1b9d801f3241e5ff84637ce06ccb77 @@ -0,0 +1 @@ +{"tx": "6f94846601dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c03020000003ac5f78104706949000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787b9010000", "prevouts": ["87e64b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_12", "final": true, "success": {"scriptSig": "", "witness": ["2d178e3d04e54c535c149078274098588da6c2d35df619db034506a0c82a0ac76f2ae668d37f220414d806b09f8af4099b0da5c2d0e0fe8bab1bddf0a29559ec83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8824c40d99be7032cf44d21d6120c667cdf875c012883e52a4fd04d392cfd2c9adbd68145c69f7a15ee008e99818e85b47c625cedba870b88cf90984d03dcf4f12", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/65a933e1d1978ba3bd2f831c22458a755de9ba53 b/txscript/data/taproot-ref/65a933e1d1978ba3bd2f831c22458a755de9ba53 new file mode 100644 index 0000000000..79c89731cc --- /dev/null +++ b/txscript/data/taproot-ref/65a933e1d1978ba3bd2f831c22458a755de9ba53 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9c01000000ddd5aec9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6b01000000ae192cbfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdc00000000b552f5a70148b11f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69aa3133b", "prevouts": ["dd388500000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "3ddc6b00000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "1416560000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3044022053656d62d779c74dff27537a5ce3d86d8b9e5d99ad68f61a04af5f116d902513022041173bc14e430cd2c93eefabba2723e971ec86ec6fc6275eee70a7edecc53adc82", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["3044022063ece51f9799d0b8f55cd8c7ce93603b6dee8d9d95b6fb525c22ecf63c579b7d02202ab803e9c6d77ee947bf17be7d388afe4d5c188274a12fe66c6b3d6dc9802a8c82", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/65b54fb91b4a1cb8c833485f4d132f6e676256e0 b/txscript/data/taproot-ref/65b54fb91b4a1cb8c833485f4d132f6e676256e0 new file mode 100644 index 0000000000..3d6d01cf65 --- /dev/null +++ b/txscript/data/taproot-ref/65b54fb91b4a1cb8c833485f4d132f6e676256e0 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c48010000008639869704fe1f4e00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df979722368987ae010000", "prevouts": ["dcde4f00000000002356212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["059ae24d6eb313597f458e4b902a3ab80888f6266fc76748d0059bfd693f46ff2281f631dbf4acbfeb5a2bce2a20dd8b768eac99932f285edb9e8017bd95a764", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/65b5fce87c9d43529bc25317899f3d88952342f0 b/txscript/data/taproot-ref/65b5fce87c9d43529bc25317899f3d88952342f0 new file mode 100644 index 0000000000..2d5dc10807 --- /dev/null +++ b/txscript/data/taproot-ref/65b5fce87c9d43529bc25317899f3d88952342f0 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbc00000000f53d232fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5801000000a868a14b010a422000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ace1030000", "prevouts": ["f757210000000000225120d65a03f65f30f95ff11470521917ac5fe759126fe5e56fe4b3d214d8fd101829", "af9c4c0000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e870bdf58d84db84346f382aca3e68185eb5f8924061d5e755b2af78706b040"]}, "failure": {"scriptSig": "", "witness": ["6a3e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/65e72ac1ffd20fc948eb9fd0715334a200044fb6 b/txscript/data/taproot-ref/65e72ac1ffd20fc948eb9fd0715334a200044fb6 new file mode 100644 index 0000000000..f84f19a1f2 --- /dev/null +++ b/txscript/data/taproot-ref/65e72ac1ffd20fc948eb9fd0715334a200044fb6 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffb01000000542e9722dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6100000000f28b12b601df1e4500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac50000000", "prevouts": ["54a96e000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "b69c1f000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e84c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93616f8948a019ae5ead2cd9d851c765ad0220b162570156f4a7dc6af8fd2e75e36f4bc19c05a4ad9ae05992168d490013403fc5515955a55899592aa66a61db799770b862ef93acb6091cb4ff8ef135b3065b278142aa4adab757f952a626e2b26c80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641b80b929874d7d784cf6595e13e696e00b78ea74d97600c5f575c1369dc95b1b4e321dfd5536232eaef67cd7779b0e400c7a17a369dbe44f6d3cf0436c0a34cc80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}}, diff --git a/txscript/data/taproot-ref/65f7ef2d10a182c5af3e4c60b4f23f13770b1d2f b/txscript/data/taproot-ref/65f7ef2d10a182c5af3e4c60b4f23f13770b1d2f new file mode 100644 index 0000000000..32674ff225 --- /dev/null +++ b/txscript/data/taproot-ref/65f7ef2d10a182c5af3e4c60b4f23f13770b1d2f @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2401000000b40d39bf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c00100000020db294d014c696800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2e5e9e56", "prevouts": ["faea5c0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "118d330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_eb", "final": true, "success": {"scriptSig": "", "witness": ["ffbdd2fbbfb826428699c1389760712bdb2ce33b75bdfad3abb0430d455144c5afb96118b91da89339b33e9671cbee8751bf95de1898f1e79c62c00ed6213649"]}, "failure": {"scriptSig": "", "witness": ["5cd37f6b0fabab584df62e1cbfb23b3e3116d5c4db95b23f0c4b36975a60bbddc6304c23de2bee8c9d165a252ad170de31abf28a0498dc599cfd4f40ccc9574eea"]}}, diff --git a/txscript/data/taproot-ref/660b8322660c10bb3072efbf02a01b028869f3ed b/txscript/data/taproot-ref/660b8322660c10bb3072efbf02a01b028869f3ed new file mode 100644 index 0000000000..8530efbd3b --- /dev/null +++ b/txscript/data/taproot-ref/660b8322660c10bb3072efbf02a01b028869f3ed @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8401000000120a51ffbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf340000000013508af90254e3d2000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4872f19bb23", "prevouts": ["9bc45e0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "17e67500000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090267f2f3c4d147d8d888ba9ad3055e1d0c4f91e37099949561274b79da16702993590f16ef275f5e18cf3c1f57ea9060a4302786577560e2280a1b9e9b7639ae59932737f8ebac42f59418766737dad1fcb68c8dd2794ee6e8fdc714c7365eca1be14d46b266f1d3b73cf31db4aa62e1bbad5c115c2dbd5a4a2c3068fe12cf7e94eb58eaff6afeed696ee2d19f14551e522ca781ce52a4db78609b41ec72d3eabc48207564eaf91acb8993893a71c19a112b57ed5e7f43c115b76e68bca823a3320598e6b3f1206b6f8a6eadc326e36414a118fcfd1daea1ba87346ddad309ce8faa2c158016cd3b93a4df536f5946eb7723f4b14560e43c33e750d883ef355ff6a48463483556be10825b2ed4209dcf01f8830ab7a34a7ddf4026d6b860be90930c10b337bc7f1a33f0d1971f03d905efdf923bb1504adbb4f86dbf7ce2e73f1e25c9673c6c598487971db5606b005bf04f99bfab8e96aff708819b58134f9e0f4683a242a249ef3418fee09c6d9e307dfd8d0cab5eed172a1ebf20054b569776ca7e17d050fad3770b66e6516595d54020a329da47e2049caf8acc5ea5bb3c5ecc91ff2d602619dff8c32d1660339af09034881469e0f5c717783260e4751123e2bec729ec58d01ee1bd3509cbcd8df821d6445fc58a2588c240f4aac1fe03c8aabc146a40d0a07ac23b0c0536a0f6dc78d036d0dd444062d9414b336abbb1dc8a61820c220d7870cd75", "747d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ecff906089186a2156752da0c3c16267cbd92a27eecc3bf322cbdfb883eaa82d667ed562df09fa99b9816795ca593030d6e2a26df3d36427b327259a2f453cdc8077aea6ccf316b47e40a0e3636c5ad4f7738b9bfce630d4a478a0dbfcb51ed93"]}, "failure": {"scriptSig": "", "witness": ["4d0902d06a09f660812fd857dca0ba2b82c3be379a62eebcac0eeefaf72e27d97e91762c658d0f3e24bb39059b1dccf075b5133500b9132e3b50b7425cbc7b2bde60b709085af1f73ae5b99aee56fc6d9f756a297a9280dabe2c97537c6f68788c19bd27a6923e8b053ab59543ffc0caedeba20dd12c1df47d8752f08a07d6ec16f50376e1c8da666b94340bf503c4b82a0be5015b5f6dd04b7a8f5bd26a7a2eb8840b0df9672259b94ccfda595bb43c29b1c5cec2f4d6b2543333f94c3a8510aa324cd5cf0816837892bc3fb2352a629f50ed742854471992ae6b0e0ebdce19c27a410b7010e86b121755aef935392bb0657526cd59aa1f1d3ae4bfa84a3b3bd24452e76789df9f093356ca9af72c0c69e6e8ce056c683c0009dfee42d4a73f321f2388f079567cbab984af32035d0e0153fec26985f4a9660b029bb18f2d9c7ffca185e620ae5ded8494b448b160f1fa9ea240d3d722435d21ea2ec257b3ddffb687f8f1a63c0d4ad3a6f7cc17c95a2379a558954826170ce373505ddf5d4e5d25ea142726f58725fbe4aab33244b2be46022a6dee3b68dc584a2a23e6e22ad39390430248f78e410b87c17bdec5b73ec3492c56b7d39f844eb2977248fb851db2a6979729e9491baf884ae255336c6f7d14d15f94191361f0d3e7f463ed7054d234ffe54d42ade6bcc126fda1c0ca2268d0193204b6f999b59d3011e286dcdeff132e6b651ac8feb0094775", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faff7c473e619e0ca75adf5145a8683277729cbfddbd5802fec00494435aa4942fbfbb1ef2412aee06f4b75b9e20a72d4d9707545a4ae77abc538f76b00105406a"]}}, diff --git a/txscript/data/taproot-ref/660ef1c053328676703178f6c1f1a9eab0eba34d b/txscript/data/taproot-ref/660ef1c053328676703178f6c1f1a9eab0eba34d new file mode 100644 index 0000000000..98dd793db0 --- /dev/null +++ b/txscript/data/taproot-ref/660ef1c053328676703178f6c1f1a9eab0eba34d @@ -0,0 +1 @@ +{"tx": "9808329802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd90000000006966cb4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0b020000009599b4af03d11683000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d2000000", "prevouts": ["6e94630000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d835220000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f9", "final": true, "success": {"scriptSig": "", "witness": ["07f68954ad90da8e4def4cb40a6b37438126f12b7920455f8c466dde4e42995e4ed138381b2e9f4945630e2e06ed6c4354414dd0b08ad22444f5aa9fdcde4d3f82"]}, "failure": {"scriptSig": "", "witness": ["a2ed8b675086ecaaa80c92425e96cf0c8ed0bd9316a765efbd2cd0f570fee91a4ef4a72bf52b69ceaf007c37fe76cd18469cdeb36a7ac794caafbdfeaa8af25df9"]}}, diff --git a/txscript/data/taproot-ref/66252c3d296124f1a894a2bef80eb0b8d2780c58 b/txscript/data/taproot-ref/66252c3d296124f1a894a2bef80eb0b8d2780c58 new file mode 100644 index 0000000000..e8610a3c36 --- /dev/null +++ b/txscript/data/taproot-ref/66252c3d296124f1a894a2bef80eb0b8d2780c58 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cba0000000025e7d69ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5201000000d3af49b860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701202000000fc825ac201084a89000000000017a914719f78084af863e000acd618ba76df979722368987398c0a2f", "prevouts": ["33da480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "65a5590000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "064711000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_21", "final": true, "success": {"scriptSig": "", "witness": ["c82f5e30d2af58a7297953a3aa68b33786c55fb79c1bba7ad94e14ab611fd39f6d1c6115218a650564925281dd8eca02da21a154036ec8c2bfc0cd64ba08e3d481"]}, "failure": {"scriptSig": "", "witness": ["4e48c844d794446185f579607e123395a9c1768c80e7bc95102bc79ccc2a613253b329923a586fd91885cbcdf59bc298cc150bc4223d20e6ac1105870a26d2f721"]}}, diff --git a/txscript/data/taproot-ref/6652466b4852d5b5fdaaa69e10880f1a3b76c3fa b/txscript/data/taproot-ref/6652466b4852d5b5fdaaa69e10880f1a3b76c3fa new file mode 100644 index 0000000000..fa4dc8b583 --- /dev/null +++ b/txscript/data/taproot-ref/6652466b4852d5b5fdaaa69e10880f1a3b76c3fa @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9c01000000ddd5aec9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6b01000000ae192cbfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdc00000000b552f5a70148b11f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69aa3133b", "prevouts": ["dd388500000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "3ddc6b00000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "1416560000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "777d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364f5cab98ec3e6c74091025ab5a3440b5db25728dfeaaa4910bbb1ab354164160ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457e2aee6c91b47bf7b7aff3c5d3800b2287c2f5852e09bca12781ffc191c1d4f04"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082fa584ded413e2880e88fe5cf9cb62118b35d382d99cebe394016833778f1470de2aee6c91b47bf7b7aff3c5d3800b2287c2f5852e09bca12781ffc191c1d4f04"]}}, diff --git a/txscript/data/taproot-ref/665eb41953197df4c60f261f2844052bbd0c48b6 b/txscript/data/taproot-ref/665eb41953197df4c60f261f2844052bbd0c48b6 new file mode 100644 index 0000000000..ec0497ea40 --- /dev/null +++ b/txscript/data/taproot-ref/665eb41953197df4c60f261f2844052bbd0c48b6 @@ -0,0 +1 @@ +{"tx": "81800ee502dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bad010000009e677df3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3d010000005da75ce303080a4500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e785000000", "prevouts": ["6a952400000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "9b09230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93690527042795390690a9a4478775b8c816aa4ae99e8fa73671741082894bf9ec6c99cdefdc3473a619e12778c4cd588646c716d59e86e999fbd28728a66c3e7c6a7d0a3f3648f0d829df7cabdb8f0af96ecc09ebc190c461c6b5fbdc9f87abaf73acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004596d09828da376c7d22ded5a4cf88780a729051831fc4ab0b26d0bae49a473f5539caad535bb8d51429d9c94edd44271a241bcdcdcd941caf815b31d1e73ac1400dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}}, diff --git a/txscript/data/taproot-ref/66726b80715835e1ff8fad96f3c76a0309586a88 b/txscript/data/taproot-ref/66726b80715835e1ff8fad96f3c76a0309586a88 new file mode 100644 index 0000000000..296f888af6 --- /dev/null +++ b/txscript/data/taproot-ref/66726b80715835e1ff8fad96f3c76a0309586a88 @@ -0,0 +1 @@ +{"tx": "613ba07402bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2b000000006ac1a3f4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9601000000db51c5bc04110dc900000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787e2e1e433", "prevouts": ["42e6670000000000225120531ded2803baf703e9b8f23e3d6d5459ce6d94a03d15c5d2addf83c32bf56dd4", "0c7163000000000017a91480e36171416c0f598c1c20ba17ab3a3cf10a438e87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2359212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["ad842b989b79bcb22880964d30e6f0693d7eacdbf868dc0520a5dedae5a1bfdc82290d27ecbe1ebb09109ae46ebd8b43f43bf9d8c9ebad19893df048576b5869", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/6699c94d11593280e700614b550ad835b0025476 b/txscript/data/taproot-ref/6699c94d11593280e700614b550ad835b0025476 new file mode 100644 index 0000000000..2b1bb778ef --- /dev/null +++ b/txscript/data/taproot-ref/6699c94d11593280e700614b550ad835b0025476 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706d010000001db75c8f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e70100000040edebc3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf710000000010bd48dc0265f7b6000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc3fbaa343", "prevouts": ["9930120000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156", "dded350000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "1558710000000000225120ba259941c99089f87a1bc06d64ef249f01ab7891d30169746f94b5a6d9357ae2"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "success": {"scriptSig": "", "witness": ["08bd160d956025ebe6f5241df6244d6e62dfe0fb88fabd8fa085f027cdb6e08983df2e90448c7730c3529d90b42004d80406a3b544a53f76563f17fd038125b701", "36a9a96f7166ddfbaa2dc5cc2c013de209470d0eba56ac9126090164a840d376e07351c961e97010316ec6e1548e8f5987cd6c7d628a1410e986ba2e7696973fd2fcf9065c502e4c997685aaa21bbd36bb2f0933550d2feaa95b2582702fe319d4b561ca31aa80f51e2586f843837d23629afd8abf0fa7dd6d46139c6716b1ee27ef18ef8444ab2f530afacbde61c335546991df2142dd407ba5d3228eadffc353e662951df94dbc8d36c8723efa603494241f5633173eec52b5b43be566", "4cdc08b90e8b86d07d7f45c20793efd1389f3568cadb6ab29e4af1d96d774d0a1ee8a681bac9322fdb94fe27887b44b1ebd7d6f11e080431dd709e5bf4c544a59fa92f389f3a96768cfcb1cfe5ceb96c5af9e4665b20aab4457cec76157b472d0d4e8942a1f85da73f9a133b83fda7a5e702ce3e1f11ae0365b7f9bae6af0b0140de6a1569666a392a1cb405d38c52544e393518b5339eddd388bbc4fff323bb1f750292aec93898be4a9bcc624dfe04fe036d2e965fd9e9ceacf4ecc3a1a3949a6ee75e274d467cb4828827d336664d3efb2fd8941873ed27b0d40f0adf6d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d30785dadbc4ecd3025a77df10d8adbabc260c7057e27b10584057b3d7f4fc016a21374ff720e76b2196617c9800913718671966153738a51ea73a6432f4ab3bf0dff5a84056750eac9adbb488cfc819afd45d7b707bec8a1e4196bb51be6e7bd60ae29b735f5eff4bd25fb4d4fb61a513a82460c0ef0ce3d2ffc7cbd94b706fdf3b1c9c2cf996feb8c879007ed7f4c68554a2e57cf8c8c5c0bc9ff388144b9a0fe770db21d58cf9191bc21575dfd0a2264c0cda110f7fa0d71b1290f1293823fbc4dcbde5dd13a9e9e1ffc890a0e959188c645bcd70a1a7b91384daa8cd0156ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94da41cbe840438f89a6a0ac625a9416d834b3f33b3770c38031be21b28da83f000000000000000000000000000000000000000000000000000000000000000025c6934f9eba9abbc53e94d34bbadf28debc99a4d2ac249ed5cea3d36fd546bcfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b8962a9c54525fb58487c69f3712663acda1a843da215ac10cf024cc5bd45ecac30bf82fa8df3fd0384c459caa1ee82314748e96cda38a9a95edf31e5fa007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56c166a818eb0f0885e8d6a1af6a547dddc2c2cc277a8dd0e175cda0f0b475cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4afe4d2fa8292491b04ac94f3579e07ea2820a2efe8c5d7cdc321fc6fd962531000000000000000000000000000000000000000000000000000000000000000095effff3d1a70c342441b75631ef902ddf2ddc837994e5043de51789538c4dbb000000000000000000000000000000000000000000000000000000000000000011f2eda03ba6d94486ade61d4f3c93b8e423cfe6ce1a1b01125141c24b6438c889c3acf9263a560421ca2bce10f7d163a8804bb321cb7da79c6321a29d03c0dde8f8a7d1619889b6e3a150d7bc0e637be3080ce9d6ccc38d41a83743dd1e2c51e99aad7db8972198620f4ea74a4494dcd65849b55fd8e1ece8f54fbf0af6816b24cc9cb0793d870b344ae56ddd355b2e771f235e3ffc12354bb39485ad36a7aa7375a32a5e045112cdceecb459c4995999b6db133269a7d7358d416abf805fcfe41bd9bcc97369e423325c88712161f18c3503205998885f063c0525eb5f2d8b4acc167957e4020e85ba25c911f06a2a8dc6065efc34ecb914e933ca3c949405ad791c3a9b80e8890ceec5a58c830f53df34478d164ac44a0e0c38ded2479bdeab5ce9e141632689e266f38e2c2cd8c2cd0b87b08512f9d8712ad93c7abe36d741bed2d0e51e90ac9d31effa23e36c43a2783e747d266c1c0c9bfb7c41188affb8a6bead3e55fe5b88ce81a3b922ca61c1f3f5ce9967c59afa752cd066039867b23027b82614047fc513d36169cb1d4cd347548cc3fb6e78e3f5970f5bb9309fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5fb087677d8eaaf50535cda0874680349d20471d186a6fb56b78cf68a2a396e137d25fa124369759976882ce3899c05a26dbeac25aeec1cf4620ae772020e459e6412c40bf85598a7b2a1d269735d196a38c98f2625b15518b3c4a9f2847817000000000000000000000000000000000000000000000000000000000000000050b8df1d68417e1955818ca12a80830f22a56ebb200b8a376c5b18036e5db64c32fcad9214e2a916766c9050c03ce1b67348c9073fd3867310ec223da95f7bd0b13f87ce275098f394f067f4ee6c5df7673ad84d84aeb0703124d5f489130e8d00000000000000000000000000000000000000000000000000000000000000004ac50d3072abf1778fec113c724452f518053c9f7fe8facce0abad2bf44141b30000000000000000000000000000000000000000000000000000000000000000d7fa016be04d7edeb2ad3d3ef4ce0bba0c2e776eacc0346960e841a0abcab630a5402b4c585240b9106c2d62657fcacd4f19c06b671b744e1ecbceb7e2c8ddb859497008e46106b80a8805ba5558973a878d97ca009957406bfcf4f3cc897d0103583647efc6a941c9cfe5d6b5b5f481578dcbf633127cfad95c9abba62bf282ebfceb33a113b5e22da86f299457aaeed9447bb0ec57ea2815b0eb353e5cd591ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ee0ee28d901acb47d6b2e3fdb5f6a537a4da791c67d65d18f52aacc08b00aae90470036e7c921d30f1e843ef44d9bc86f36517d22d60a331a4d1a8dea235e7f80d73c2905d263cb6cb17a77ae3a30e0837f63411f14c374b716b9c6bf0fe03849a4b9a71603529d25c66ce8682f296c1b91f9585d9bce4508eea7314182397340edbee6c00206f0e0de3ec6a1871aa8a719b84c9b6b8fb7463d3f99614f6d97374f2fd3ce6b410e81bfc9bc528da4cf5d9c55900e3bf6e86cd931768d3ead34ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff107205b80d68d90d7ab6bed69c85d506bfecc9129a6124719dd9259f9ca83d66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff06718ff2b40ea9bb812d68372c657c4e7532ae9c339a045185f0387917cd48e13c5f4e9b318d0dd7d845bc8f57f6ae6f139c62bb692d8d719f358051e9248c01001f5ee4496e79d86e079c265acb5ad792cc2857f1209a998deb6bddd87ba3ef7f205ab1275eea909497773093891de01bbb4d8156133d83477d8fbca56ffa4deb34ce31eec3520b49735b8746a994b213b566af74c9c1fb7cbe5e620541610c95f5280707a1a0172908b6974840e0cf359cc126b37af177b8d7782a458af7783902143ad5dfd26a5bef60ce57360225212e86129c6f9f3a3270a836cebe5b0acc889cc1f77bd63c6735ba075f01207f32d19838517a7312739b05df7c8caf67793cb06c4e94ff4dbbfdc933770a06c250d228b385e7491459d5deb7a0ce0c8affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b96736d52acf68a3e5b7be814a229a3d9df7a7bf5248c1aeb12f78d0dec9d14da332e79ddab48e27584a8464eabda9f058099687b586c6a2fcb0c611940a702dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1fa44b17f3934485576cdcf58b8713527933168956c1c465eef29f1db88876d8487851be3035d8237006c63ae05685c20fbc14d0745cbfae1a17fa62d55714d92ae85994b3415c619b66c395869716600b3545e6f04a7d75c0ffddac9291bb1f754f557bbafb4940f6e54788495f56a1f54fa5f6aa9a82bd99d0be0f856b563b4ea4e734d1179aab74d5930f8fbb61515ee6b1b58a0ba829a2b1def4c1cff7898ed24b336b550b17055789d17a25b172537ae1455db70617c2b118ec651e0d1a017bae30ef06ee67f32da8a0cdb7e43b61dc49d24ad5a26720c83f5b363097fdf2f57a20a91be0e80418c95c7347cf587d43d81dc268fa8ed5f86fd32091bcdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5edabba63702f38eb276ca33af94b77993e1ba5f23eb3b7694279fad7dc0782faa00d8b92a9c7fe9a9dfcbafae4bb989941bce9b61bd618596de0668d488471cae72d0dc4fe68196d465d0209fe1b67054777bad876c563d524a2bad27847a6004db723030b3407c400759e494e54f84e95a798e6d7b6ef38d5d53f65115ecda6cba38c52ee68c6619d54bd6e944beba82747035dd0fbd77085e129c105f445e05a107367ba362ce285c83631f39881f8d0c4fa0e3f3cb2fed5f21932ea194cdc9ab2dffaa2cf5919398e71a1cf9a2863a86dcb10829e1cf959cfe4d00b6c34600000000000000000000000000000000000000000000000000000000000000003454f1097ec5491edd4f147033b634620ec5d0d80964113395bdee2320ba329ef00c4e734e3c6ce347d9561ed201ec77f8881bcb06775e12f9dd43dd028fae656cfa5ae40388ded790c34f9368e5a070bb1fb2c3a4db90309993e45db8c5afa1d4aad98abda7c8e28f3e634df6d4a3a0d87713d78cf95fb199e58383d7cc60f9016e7a0d93a40f984cae5e11618af8803d7397cefbc3d64e40c5831522f8ac297198bf4e3afbffac10a2104847b097edcf877f803375df6a74523fd598e491d458ae479d92e2ed7f073bcb9ced61b5d71df610122e42c8375479371a21f49c663d7599ea2c5554d0896ceef80302d058c9279be888e7b4f71796476ab7b22c77a28286392c4d0fff1b24a5df3c903ba128fd8345faf1c2843988b37222591093e67e4f1366a3bfc0e7a4e1a9d9bbc6821d1cc76282b6a8ac08652aa135d0e17c1a28329f1220195481046aa1c77488fba52c8bf7720bd50830db7130d77960cf8cab1103cf8a463558547838feec8e9963c40e20e79d41437ded67259e5aa2abf766655483fde84d7acabc45f067a2b7ef18fba26ceb1eb8e78aef99213de2d062c520ac10410a600409c7028e927e0f67c9341e32301a22408c0b63056a4c88733ff60f98087d4514f686719a7c163102f2df86cf29f8c93f39b7124a897908221d140f7bddda1cb54158603abac448e206755a5c88e48aa329b2a2a110301cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4c025675267608b16d73539d8e554eb4f1ddb834be786b27a2ce63fd997ef13a819061645333216a624cf08665a379470996c01670da635c11d17a0807db27e7", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["08bd160d956025ebe6f5241df6244d6e62dfe0fb88fabd8fa085f027cdb6e08983df2e90448c7730c3529d90b42004d80406a3b544a53f76563f17fd038125b701", "e2747c919a2159c67a575c24898ffa12c5493a737a14638ba8def1f3cd2d50732162b65ace13cd85007f6754d4373e287c35788e32f967a720b03bbd721f322e387495a3b2bcd0cf78934bf3c4c7c9665f7b3804734d4e95e90804539818ded992278dc24888eb7a825ae0044056f4b4ed2fb9a6a12ee22230fe3c3e3918022afa13d1a12002a337398f67a5af982b8fbbdcfcfbd7a5cefd09e652987f97edec4cbf8f91e13a91e5d5139ff8fa6c13f4d2d789d11dd2ff8332d6d647af", "4cdc08b90e8b86d07d7f45c20793efd1389f3568cadb6ab29e4af1d96d774d0a1ee8a681bac9322fdb94fe27887b44b1ebd7d6f11e080431dd709e5bf4c544a59fa92f389f3a96768cfcb1cfe5ceb96c5af9e4665b20aab4457cec76157b472d0d4e8942a1f85da73f9a133b83fda7a5e702ce3e1f11ae0365b7f9bae6af0b0140de6a1569666a392a1cb405d38c52544e393518b5339eddd388bbc4fff323bb1f750292aec93898be4a9bcc624dfe04fe036d2e965fd9e9ceacf4ecc3a1a3949a6ee75e274d467cb4828827d336664d3efb2fd8941873ed27b0d40f0adf6d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d30785dadbc4ecd3025a77df10d8adbabc260c7057e27b10584057b3d7f4fc016a21374ff720e76b2196617c9800913718671966153738a51ea73a6432f4ab3bf0dff5a84056750eac9adbb488cfc819afd45d7b707bec8a1e4196bb51be6e7bd60ae29b735f5eff4bd25fb4d4fb61a513a82460c0ef0ce3d2ffc7cbd94b706fdf3b1c9c2cf996feb8c879007ed7f4c68554a2e57cf8c8c5c0bc9ff388144b9a0fe770db21d58cf9191bc21575dfd0a2264c0cda110f7fa0d71b1290f1293823fbc4dcbde5dd13a9e9e1ffc890a0e959188c645bcd70a1a7b91384daa8cd0156ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94da41cbe840438f89a6a0ac625a9416d834b3f33b3770c38031be21b28da83f000000000000000000000000000000000000000000000000000000000000000025c6934f9eba9abbc53e94d34bbadf28debc99a4d2ac249ed5cea3d36fd546bcfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9b8962a9c54525fb58487c69f3712663acda1a843da215ac10cf024cc5bd45ecac30bf82fa8df3fd0384c459caa1ee82314748e96cda38a9a95edf31e5fa007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56c166a818eb0f0885e8d6a1af6a547dddc2c2cc277a8dd0e175cda0f0b475cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4afe4d2fa8292491b04ac94f3579e07ea2820a2efe8c5d7cdc321fc6fd962531000000000000000000000000000000000000000000000000000000000000000095effff3d1a70c342441b75631ef902ddf2ddc837994e5043de51789538c4dbb000000000000000000000000000000000000000000000000000000000000000011f2eda03ba6d94486ade61d4f3c93b8e423cfe6ce1a1b01125141c24b6438c889c3acf9263a560421ca2bce10f7d163a8804bb321cb7da79c6321a29d03c0dde8f8a7d1619889b6e3a150d7bc0e637be3080ce9d6ccc38d41a83743dd1e2c51e99aad7db8972198620f4ea74a4494dcd65849b55fd8e1ece8f54fbf0af6816b24cc9cb0793d870b344ae56ddd355b2e771f235e3ffc12354bb39485ad36a7aa7375a32a5e045112cdceecb459c4995999b6db133269a7d7358d416abf805fcfe41bd9bcc97369e423325c88712161f18c3503205998885f063c0525eb5f2d8b4acc167957e4020e85ba25c911f06a2a8dc6065efc34ecb914e933ca3c949405ad791c3a9b80e8890ceec5a58c830f53df34478d164ac44a0e0c38ded2479bdeab5ce9e141632689e266f38e2c2cd8c2cd0b87b08512f9d8712ad93c7abe36d741bed2d0e51e90ac9d31effa23e36c43a2783e747d266c1c0c9bfb7c41188affb8a6bead3e55fe5b88ce81a3b922ca61c1f3f5ce9967c59afa752cd066039867b23027b82614047fc513d36169cb1d4cd347548cc3fb6e78e3f5970f5bb9309fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5fb087677d8eaaf50535cda0874680349d20471d186a6fb56b78cf68a2a396e137d25fa124369759976882ce3899c05a26dbeac25aeec1cf4620ae772020e459e6412c40bf85598a7b2a1d269735d196a38c98f2625b15518b3c4a9f2847817000000000000000000000000000000000000000000000000000000000000000050b8df1d68417e1955818ca12a80830f22a56ebb200b8a376c5b18036e5db64c32fcad9214e2a916766c9050c03ce1b67348c9073fd3867310ec223da95f7bd0b13f87ce275098f394f067f4ee6c5df7673ad84d84aeb0703124d5f489130e8d00000000000000000000000000000000000000000000000000000000000000004ac50d3072abf1778fec113c724452f518053c9f7fe8facce0abad2bf44141b30000000000000000000000000000000000000000000000000000000000000000d7fa016be04d7edeb2ad3d3ef4ce0bba0c2e776eacc0346960e841a0abcab630a5402b4c585240b9106c2d62657fcacd4f19c06b671b744e1ecbceb7e2c8ddb859497008e46106b80a8805ba5558973a878d97ca009957406bfcf4f3cc897d0103583647efc6a941c9cfe5d6b5b5f481578dcbf633127cfad95c9abba62bf282ebfceb33a113b5e22da86f299457aaeed9447bb0ec57ea2815b0eb353e5cd591ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ee0ee28d901acb47d6b2e3fdb5f6a537a4da791c67d65d18f52aacc08b00aae90470036e7c921d30f1e843ef44d9bc86f36517d22d60a331a4d1a8dea235e7f80d73c2905d263cb6cb17a77ae3a30e0837f63411f14c374b716b9c6bf0fe03849a4b9a71603529d25c66ce8682f296c1b91f9585d9bce4508eea7314182397340edbee6c00206f0e0de3ec6a1871aa8a719b84c9b6b8fb7463d3f99614f6d97374f2fd3ce6b410e81bfc9bc528da4cf5d9c55900e3bf6e86cd931768d3ead34ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff107205b80d68d90d7ab6bed69c85d506bfecc9129a6124719dd9259f9ca83d66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff06718ff2b40ea9bb812d68372c657c4e7532ae9c339a045185f0387917cd48e13c5f4e9b318d0dd7d845bc8f57f6ae6f139c62bb692d8d719f358051e9248c01001f5ee4496e79d86e079c265acb5ad792cc2857f1209a998deb6bddd87ba3ef7f205ab1275eea909497773093891de01bbb4d8156133d83477d8fbca56ffa4deb34ce31eec3520b49735b8746a994b213b566af74c9c1fb7cbe5e620541610c95f5280707a1a0172908b6974840e0cf359cc126b37af177b8d7782a458af7783902143ad5dfd26a5bef60ce57360225212e86129c6f9f3a3270a836cebe5b0acc889cc1f77bd63c6735ba075f01207f32d19838517a7312739b05df7c8caf67793cb06c4e94ff4dbbfdc933770a06c250d228b385e7491459d5deb7a0ce0c8affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b96736d52acf68a3e5b7be814a229a3d9df7a7bf5248c1aeb12f78d0dec9d14da332e79ddab48e27584a8464eabda9f058099687b586c6a2fcb0c611940a702dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1fa44b17f3934485576cdcf58b8713527933168956c1c465eef29f1db88876d8487851be3035d8237006c63ae05685c20fbc14d0745cbfae1a17fa62d55714d92ae85994b3415c619b66c395869716600b3545e6f04a7d75c0ffddac9291bb1f754f557bbafb4940f6e54788495f56a1f54fa5f6aa9a82bd99d0be0f856b563b4ea4e734d1179aab74d5930f8fbb61515ee6b1b58a0ba829a2b1def4c1cff7898ed24b336b550b17055789d17a25b172537ae1455db70617c2b118ec651e0d1a017bae30ef06ee67f32da8a0cdb7e43b61dc49d24ad5a26720c83f5b363097fdf2f57a20a91be0e80418c95c7347cf587d43d81dc268fa8ed5f86fd32091bcdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5edabba63702f38eb276ca33af94b77993e1ba5f23eb3b7694279fad7dc0782faa00d8b92a9c7fe9a9dfcbafae4bb989941bce9b61bd618596de0668d488471cae72d0dc4fe68196d465d0209fe1b67054777bad876c563d524a2bad27847a6004db723030b3407c400759e494e54f84e95a798e6d7b6ef38d5d53f65115ecda6cba38c52ee68c6619d54bd6e944beba82747035dd0fbd77085e129c105f445e05a107367ba362ce285c83631f39881f8d0c4fa0e3f3cb2fed5f21932ea194cdc9ab2dffaa2cf5919398e71a1cf9a2863a86dcb10829e1cf959cfe4d00b6c34600000000000000000000000000000000000000000000000000000000000000003454f1097ec5491edd4f147033b634620ec5d0d80964113395bdee2320ba329ef00c4e734e3c6ce347d9561ed201ec77f8881bcb06775e12f9dd43dd028fae656cfa5ae40388ded790c34f9368e5a070bb1fb2c3a4db90309993e45db8c5afa1d4aad98abda7c8e28f3e634df6d4a3a0d87713d78cf95fb199e58383d7cc60f9016e7a0d93a40f984cae5e11618af8803d7397cefbc3d64e40c5831522f8ac297198bf4e3afbffac10a2104847b097edcf877f803375df6a74523fd598e491d458ae479d92e2ed7f073bcb9ced61b5d71df610122e42c8375479371a21f49c663d7599ea2c5554d0896ceef80302d058c9279be888e7b4f71796476ab7b22c77a28286392c4d0fff1b24a5df3c903ba128fd8345faf1c2843988b37222591093e67e4f1366a3bfc0e7a4e1a9d9bbc6821d1cc76282b6a8ac08652aa135d0e17c1a28329f1220195481046aa1c77488fba52c8bf7720bd50830db7130d77960cf8cab1103cf8a463558547838feec8e9963c40e20e79d41437ded67259e5aa2abf766655483fde84d7acabc45f067a2b7ef18fba26ceb1eb8e78aef99213de2d062c520ac10410a600409c7028e927e0f67c9341e32301a22408c0b63056a4c88733ff60f98087d4514f686719a7c163102f2df86cf29f8c93f39b7124a897908221d140f7bddda1cb54158603abac448e206755a5c88e48aa329b2a2a110301cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4c025675267608b16d73539d8e554eb4f1ddb834be786b27a2ce63fd997ef13a819061645333216a624cf08665a379470996c01670da635c11d17a0807db27e7", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/669ff69c2c67c7765c32e86e0eda8fcf04bcdbdd b/txscript/data/taproot-ref/669ff69c2c67c7765c32e86e0eda8fcf04bcdbdd new file mode 100644 index 0000000000..e3791cdf8d --- /dev/null +++ b/txscript/data/taproot-ref/669ff69c2c67c7765c32e86e0eda8fcf04bcdbdd @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4600100000096211854dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0802000000ae1def8304d9f05c000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987ce010000", "prevouts": ["77073800000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "36a4260000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "9f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa285f58facbc555a1823ccf774e09bcf8bed00fa79ba622996abd47a227307ebab591a16be56540de55d9fbfa115de937b3aca1e4dd0f5a93f17ebd2ebda95183"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f61d84cff52e05d72c3db95a85d4c347800acb4eb97e10662f9f4ebff4d0f9e0285f58facbc555a1823ccf774e09bcf8bed00fa79ba622996abd47a227307ebab591a16be56540de55d9fbfa115de937b3aca1e4dd0f5a93f17ebd2ebda95183"]}}, diff --git a/txscript/data/taproot-ref/66bbe506485ecc1f5f29905e93bbc326b119a9db b/txscript/data/taproot-ref/66bbe506485ecc1f5f29905e93bbc326b119a9db new file mode 100644 index 0000000000..4635407fab --- /dev/null +++ b/txscript/data/taproot-ref/66bbe506485ecc1f5f29905e93bbc326b119a9db @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba101000000a9a32afc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ce00000000d3ee6bbadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf600000000f28de0af0335865a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb813d458", "prevouts": ["5519240000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "15bb0f000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "0239280000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["35", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/66cb36473c4a75d094b0c109710f2456a52e3ac0 b/txscript/data/taproot-ref/66cb36473c4a75d094b0c109710f2456a52e3ac0 new file mode 100644 index 0000000000..6f00d1f193 --- /dev/null +++ b/txscript/data/taproot-ref/66cb36473c4a75d094b0c109710f2456a52e3ac0 @@ -0,0 +1 @@ +{"tx": "21283431028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49b000000002471ef9560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701502000000ffca41f901f4dc31000000000017a914719f78084af863e000acd618ba76df979722368987c191064a", "prevouts": ["4e9736000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "2315120000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["304402206dabc2d6bfe31004ed9f9f46abdd975f09ecd1146f315c4ada6291e50489053502201a1f7b7dccc85282c319eb5ca4a15a5a4ed1ec63c0d96213179a93d74b1f67693d", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["3045022100843b44b877e5e690eca634f3e2b00c683f5b4729583f5424b36129def7d4248e022060472eda1d2b0c78a08cb35fe7d8a17065626c3e1bdea20da6640e8241b71cb93d", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/66e881b64f9e9007cc27f9ae6ea1d9c09b7ff1dd b/txscript/data/taproot-ref/66e881b64f9e9007cc27f9ae6ea1d9c09b7ff1dd new file mode 100644 index 0000000000..69deff653e --- /dev/null +++ b/txscript/data/taproot-ref/66e881b64f9e9007cc27f9ae6ea1d9c09b7ff1dd @@ -0,0 +1 @@ +{"tx": "b898faab02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd001000000322d1fc28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47201000000a12eaadc03c7936300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac82030000", "prevouts": ["ca39240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee564200000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f2", "final": true, "success": {"scriptSig": "", "witness": ["d80b9460896c552efa2f1db7d015f374b148a85fe90e13db54827f9424fdd53ced619e4db7464aebe5995e5e277c2564dba5a4d2f150140859697e15e199815481", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a2108ee9a4ce6f69b7e337fe1e767411b4d1a9f8684f868571813a41116df1c6e609fa7bf04a66dcfda1c36ad472f19e947902a5ac5e2248ade24c4a53978860f2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/66fd2e2f42f7b15c03f46c8f5852fc2b2a1288d4 b/txscript/data/taproot-ref/66fd2e2f42f7b15c03f46c8f5852fc2b2a1288d4 new file mode 100644 index 0000000000..f44c6eeaff --- /dev/null +++ b/txscript/data/taproot-ref/66fd2e2f42f7b15c03f46c8f5852fc2b2a1288d4 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc8010000005c7f094c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fa01000000ae244f4003c3a18000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76e000000", "prevouts": ["182d500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1323200000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_17", "final": true, "success": {"scriptSig": "", "witness": ["a557fb53d5dd4d98fed94cf44dc84912bc1fadd1b2aca3adadd333dd19a5140a9f9527657baa3b3c427ea0f353d50903358cce00544d502e89ae55ce8ebc1ae801"]}, "failure": {"scriptSig": "", "witness": ["44fb34676b9daad624cb34574a24c03c9c7462532b7af617679445f8f653e3bb135b83eb1acd5444328e785c0686ddc87a64a227412ecc3cfb7a4370e921d09017"]}}, diff --git a/txscript/data/taproot-ref/6723a627907cb1d91034b75d6a69d055a9d2a9b2 b/txscript/data/taproot-ref/6723a627907cb1d91034b75d6a69d055a9d2a9b2 new file mode 100644 index 0000000000..b38d733d28 --- /dev/null +++ b/txscript/data/taproot-ref/6723a627907cb1d91034b75d6a69d055a9d2a9b2 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c290000000006481d8560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e0200000026bb47f7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5601000000f8a95f8803a645cd00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79665a0ac45", "prevouts": ["bc855900000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "782b1000000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7", "077c65000000000022512007a606ac1d369bdfe9b32b88a4b0d4c507785f2481b337f6b3340196eed3e896"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93610658657c9e95ab5519a432137c3fc0dad6c728261b2de6e60ccb78b9288ef57"]}, "failure": {"scriptSig": "", "witness": ["6aff616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/674c86a431b193721af73dfdf07aeef65a7ef508 b/txscript/data/taproot-ref/674c86a431b193721af73dfdf07aeef65a7ef508 new file mode 100644 index 0000000000..e9278f1e3d --- /dev/null +++ b/txscript/data/taproot-ref/674c86a431b193721af73dfdf07aeef65a7ef508 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45600000000205bddf760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700d00000000c8f1b58b0186fc1f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478744990c28", "prevouts": ["28b5380000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "36b6110000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "9d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936efb1adbb630f4af208384c658773c47546649f7183045c3ea461c7241e38f37a96b892175c0861377cad04fa4faba87807216c52ab5a24eadee36522f056d83a72756956c694637235f847009e8e23b8c05283b4a047903b3fbdb647ae4209c1"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363e053c547386d418b4b4623c4b95365b560c64b1d3965d2e285700304f83aa6fa832c2593bdac0cb0b42624935007d1442180dae3fe4e49dcedfd3101f5729d872756956c694637235f847009e8e23b8c05283b4a047903b3fbdb647ae4209c1"]}}, diff --git a/txscript/data/taproot-ref/674e2feab074ca0240a6ca55826b14e434793461 b/txscript/data/taproot-ref/674e2feab074ca0240a6ca55826b14e434793461 new file mode 100644 index 0000000000..a83df62ffb --- /dev/null +++ b/txscript/data/taproot-ref/674e2feab074ca0240a6ca55826b14e434793461 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706d000000001f9bde91bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf790100000000c42cfc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48601000000dc5b1c9a012caa0c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc786000000", "prevouts": ["2d69100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0c5769000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "3b5e3e00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902324256e2ccc712f51e09bb2517115ef3f7d8a0b9905ddff3a19af56c609f84b271fda4c990677887bbec1909e2004e70b01999a19e0f45b9ca2937754ce280b0f6b15ab303eebe6ee7e8f525a07ad9f1e1d9a2fddace045a288801d86f6069f79a21230c4012acb552f4af8824477a6ebc0029055d84046afe75c9db4a4a3ddd864bdc9accd9f215ee739f9cd4782438b506a0abcdd6c4ccbfe5dd4121710991a16b48dc0e72c7274073c99b1712817745477d40abec6245cec3c2d7a09b08d1b90bbb6091faf2ee768ac019fe91cada18ca141aa15a18b67475b10b72af3fdab7411a9a718aafda9685801ea862f0b36937d976cfdf621634e8c4a45ca4d754e0cdc4ddee4d28a1588ae9915a17821f85c77516a8b2ce6412586dfe1df8300592e31e3624b97350d5a0b8eb0474b7f739ea2e5b8991bbfba615b4e2c8249f61455993d52150af9f9527d8aa9e3af858af12af1bde8dda5c0e5dd5a98b2f62d5198e7c1f3ef2c6bf0abe407d29c33ab2368eb52f70cef85cf2c44755579a9efe174ef85c74017bde4ca326f1fb10621744b566e005f1543680d6f392c23fcd4d9098e4528d8916bb05ebb6b633e8c7f950fde48aafd21c1f816e473169d6129f137a04e9db776cd6d04222236537c5aef746e4fe8b174a2e9b2f238918163d1d04a3af1c1e418733418e1dc192b528061e6dc99d67fbb0728541d1e94ecd82533e9cc129bd101cc29175", "867d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363cdaa0eb757ae0199db07cccbb4145c327e3e07b9779dd9bc3db969b58b973854fc7631352e9fb39bf71f46c116b968047934be68cc4b25c7eb80a8b2383cf163ac108bed01ff7a3c4482bdb9637a0c08eda3eca9d378124f08be0fd1593c53eb98f84b0d7d6fcb38bca0562970da4fa4ac9189daad947902c07179846baca90"]}, "failure": {"scriptSig": "", "witness": ["4d0902571c8fc7b5aa059399c097dd92a905775c5319d995c2a7dbcaba31488134af38d3d89b7616112e7a93845dc38d66ee0ac381b6497028b516f57418335a224065d23dd53729eab3be7b296b5de82801637397d7454dc2e25fa7685c7e38133a188f7ae057c5cbc019ce883f908a819c42a7b83e0dceb87224d5c9d387944d0a8b7ec6a77ba4d6214d9a42af110635a1333ed8be52af9ab59803c22da1c1f6cfdd09d387f18d5a80a2f1d90b58c25c32a2275528b969ccebfe6461cac4ae9b223603e48d7b14c21b63417c2034b2308eda9e867de2f2b65a4a461d5c55fe7489a536747587a9ca33d74c34ccb9f41f43a17ca1bf0471b069de785a10050a3b2650d69ab27354a5c3f3e1390a4cfeb2415180c4b9b2d356afe640fdd482c45f0f7f2218459c308b09d84326655ac4fa3bd995c64da57c81f993bdc8c4f1547c1a28d09fd18e95cbf1e6a3a42ca2110aa48b60b2a16daaf4eca7c00cf0849e843662083768fd24f17c0efa7524f9b6b6a179c45bcd5498ff08d7e19d1065261d869e0fab148298dfe458a63946b62018ff11e75d13f09f8414e8dace3a89558cbdca6affe97958092fcb5d95293055e1ad1811dd54a9093b60a43af84ca99363e595105e8095bda457165b6b03cbf5a7c9df7eea5c4de0ea59243665b570df78c47cee7d8901f6ceb06746475320911adbc77f16d3815b07a32d4ffb5f1d175cfbd3f69159b01fbe43d43575", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e80adedab43a8ab423f9b5916bd9a862eb4f524e14c7176baa6699ffba0690b6e8b98f84b0d7d6fcb38bca0562970da4fa4ac9189daad947902c07179846baca90"]}}, diff --git a/txscript/data/taproot-ref/6766fbe9f961609fc3c2e2dbb922ddf1dc771d96 b/txscript/data/taproot-ref/6766fbe9f961609fc3c2e2dbb922ddf1dc771d96 new file mode 100644 index 0000000000..021ca0fa4d --- /dev/null +++ b/txscript/data/taproot-ref/6766fbe9f961609fc3c2e2dbb922ddf1dc771d96 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c424000000004c7ffa9e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270120000000067fecfca02e2db4a00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc71c501441", "prevouts": ["8aeb3c000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "adf20f0000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063db68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0d54e6d4b188f4ba3829c97f16419e7d7896d7c05fe6215d1417ce194d9971cb9e3dda2dfca806ccc9c3ad62846e64b9ac16121de5d926db5bebf2e82f8dec8d2a"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936120d11d3534b0b29d9477622fa88775a27b386783982fd9652b8fcb86806fa8be4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0d54e6d4b188f4ba3829c97f16419e7d7896d7c05fe6215d1417ce194d9971cb9e3dda2dfca806ccc9c3ad62846e64b9ac16121de5d926db5bebf2e82f8dec8d2a"]}}, diff --git a/txscript/data/taproot-ref/677c2fb0bd66dbf157aed281b05b92ad2c197c37 b/txscript/data/taproot-ref/677c2fb0bd66dbf157aed281b05b92ad2c197c37 new file mode 100644 index 0000000000..f81e2f7ea8 --- /dev/null +++ b/txscript/data/taproot-ref/677c2fb0bd66dbf157aed281b05b92ad2c197c37 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700302000000ab56471b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41201000000d13155dc035cd64100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdd5eaf2b", "prevouts": ["b4e90f0000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "38243400000000002251207c84ae2d9063cc63412a30e00823aa01b05bc54bcf6d9936dc1c650bbdc9e98b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "a37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2f8f33b00019c5a92b78a4d0765b6724114f5676deb8014962e3b41b4c6baea3fd3695492b964dfcc45d3a474d456ab4db8430bda5885b2eccf08499e11263dad2054b94cb6efba565738f5dbf6ee5a67458962b65d77e1cf5e0d2c1c00b2210"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e1bbd263bb9b57787cc1695f6735ee6aa4874511c0d77def079ec8f767826a474cae923b25d556389dd5dd645f6d7ddd89a07a74a73dddd3d85d7b65ae33798aa"]}}, diff --git a/txscript/data/taproot-ref/6790425ac6ab89b1bf9e69e61d0a23def2470c84 b/txscript/data/taproot-ref/6790425ac6ab89b1bf9e69e61d0a23def2470c84 new file mode 100644 index 0000000000..a79455f15b --- /dev/null +++ b/txscript/data/taproot-ref/6790425ac6ab89b1bf9e69e61d0a23def2470c84 @@ -0,0 +1 @@ +{"tx": "0972a5e80360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702f000000002df915e3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0d010000005dcd57a3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc0000000008fb04dcc0287d9c80000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac77000000", "prevouts": ["915d1200000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "ec355c000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7", "26b35c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b1", "final": true, "success": {"scriptSig": "", "witness": ["d02f2370cc311fdaea8d390cfa1c63b0eef7d0ea0cb51421ecec6c381cd6cf992956c198c54e508542ddceb10ef1876b5a5fc8c5264bd02bb08e399775a6e603", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3f5405c60901045cf8fbd21b5f236cad6076976eaa41fb829aeb8c9ed18e1fda3c10a5b23d4bcb0d29cc4699811c7889c813758769510ca9297c0ce8bd5cfe35b1", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/679748203674073239d2e5a0f7f9da26bc60feb9 b/txscript/data/taproot-ref/679748203674073239d2e5a0f7f9da26bc60feb9 new file mode 100644 index 0000000000..ef8efec2d9 --- /dev/null +++ b/txscript/data/taproot-ref/679748203674073239d2e5a0f7f9da26bc60feb9 @@ -0,0 +1 @@ +{"tx": "a48d03e901dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ceb0100000038ff23fe03ebf15b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914719f78084af863e000acd618ba76df979722368987c7030000", "prevouts": ["47925e0000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090249269449cb326047a10e121b8baf579dfc910fc86d8756d3d64a30ecb902b60983a6acffde72b37d73ff805d4a067b5bedbfe5dd27718bcffa1f513bf206fe3bbd445eb62ec5e611aab5e81966239f9d22c150c70bce2542b910c00533d1e6c1422b34a4b9872249ff0e032b1cff26dda1215a8a65b8fc3a9c4916faabc1fc866f9d98d4941e5fe497f94b8d6295c6dadd9e6a2bec9afae7206d31784fb40cce579e518d3c72919c72abbaed9dc27e5dc690e202529f0923eaa67d0713611842459d1af9c8c203b30001e91257090201acf15969ab1014213dcaf3a6c0588bca46fb0b2428f48349c3aba1e9e9eaf55f960d9195af927770bbe5872508bfa63938d125a7cc7a745f5bda9a895981eac471b1e9ef053bfa85c1d0aa0c51a2f910868246ef88aa33c88d8acbba6e1e5d4ce1730d298ee2350e93125ab9b7a5d5f7d394f5290e5d6499d02968ebb90d19c22c3d331d0ed6190e756b23e246d840450f0183b41de6f839688c02083164ecb977277c95999208db8225a093cc11ecaf834b54efe26953d7eba8d5c35ade50bbab8e1835e8f14c9380038a8e77d7235490abb1e3773be0a8cf3ea5e5c8bb356d76acd5b0f03bf41e3110f7a8c159b060c9af9963c3f4c6b47603425ceefe47087cad7ea8165f01b577821038a8b4624d39272c18edf602e0569a235770f31a4b58cfe15bfb9a51b1f0165a98a57034057028413da99d88724775", "147d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369dd73bd5bfb795bb2efbe9fe3f0d415ac42feb9661e311246ef70ddb758e793a9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100efb63111b06c7a0ce3f44d9f6906db8fc60057b72694cfd58ed25db88d188e5fc"]}, "failure": {"scriptSig": "", "witness": ["4d090299631bf7d4f8df9b4cd3e194c46774ab087eb57a2a7a8d07162b82c319d70d52650ec87bff9d6bb08a7f411786e6f96a2468dec2f411ad741b81c63ac3618d37e32b1837fbe49be9bacce1d49b6fa3bdc190163b2993f77dfb8f0aeb0ad9b0372fbe9b5da046332153ef0f16d8f7c336bab5295f4eef3adcbbf10f9cf95d1d0a9ba283033f90873a908540b2dc91e6b3eda6b9c056bba2385e5e428d90f215ba411e685941f2690910fde28d427d5d837766fb1e7d9e7b517811e3642647e8bf345b2d07ec5bf3491d34a17cb7c2b91717e6b681433d892bce179c28f95054a99ade9e509600620efc81cd577f9ba7fa90b7ea844c5d1d22cb104c38032700293bf8bbe4ea3da72bb9b1c446c351ec9366e52c226f0784d4e94e489126de7351f1e13bae76efbe72ab2bb2ed864f77f061042896fc35aad9b08b6d05ee30c732cf0c4c87cf634e5afe6cc67912a18306c5f9df5073c18294ff832a16f1647e6c2ef6259d751b7eb5538365496d07f08450d06fffd6cc260e038a3a9d48907d9ff676471dd0b74b52e30d8d5a3020f1e398e73cfec7729acc0452412f43a95453e5b68da12be11d77f978e5693310dbb4589411997134cb5c4703b010120086dcdf5e253d4877ca62065237d1946d1aedbb650ea7137825ed36ace21e8cd60537a1b42561b26c428170d1ec4a67224394f7ce85ad8016777e39f730f2edbf57b24dc156d62826811e0f75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8fdc2d7aa80560d1a81b9ed628b4b72c1af718550327182f7e69256034992ba893488b030fbb16fa8d50c4f1f044e6df81cbeac111f0be15e3f466e559374b3e5568dbaf979cca58396dcf271ee6fc736edd00965a3b0ecce9c87347ff88ab08a"]}}, diff --git a/txscript/data/taproot-ref/67cfc5cf8010d9b1c152301eae06d149589112ba b/txscript/data/taproot-ref/67cfc5cf8010d9b1c152301eae06d149589112ba new file mode 100644 index 0000000000..d0e5f9ca08 --- /dev/null +++ b/txscript/data/taproot-ref/67cfc5cf8010d9b1c152301eae06d149589112ba @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be9010000003b4ab8d18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49301000000992f62bfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c36000000004f65d726032c18a700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5f079022", "prevouts": ["617c220000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029", "dc55330000000000225120884291612dcc22b2c0e2cf19d55719f5f9dfe9624bd12dad94712b18ad4d330a", "c6da520000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d5cfcb01809ee692b36a4c346827dc2d7fb8406b64058641986dd57c7b689372"]}, "failure": {"scriptSig": "", "witness": ["6aa1616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/67f26334e58a0356529496d89738359b7a8dd136 b/txscript/data/taproot-ref/67f26334e58a0356529496d89738359b7a8dd136 new file mode 100644 index 0000000000..d6651d3cda --- /dev/null +++ b/txscript/data/taproot-ref/67f26334e58a0356529496d89738359b7a8dd136 @@ -0,0 +1 @@ +{"tx": "896c810602bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfee01000000fadb3ee3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfee00000000d2cc268d0308cbd900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df979722368987e4000000", "prevouts": ["7dd76b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f3956f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e1", "final": true, "success": {"scriptSig": "", "witness": ["22b1a41c5ff182d73532b7af01acf7b278eedb842baa8d5673e0e1c97e39421fe359f38f6ba1508d7f043439a9be3f32fd916c5f31484fd84893cab9c98ae25c83"]}, "failure": {"scriptSig": "", "witness": ["5e2469fd440d3f05159d931cbd94637b1b549f11501eb3fd2e994aff16fdc10660caaa048399316d746ae8d25875ecd16764e28ff7c70aaab93fdcc6cdec20f0e1"]}}, diff --git a/txscript/data/taproot-ref/68052b4483af39b51b45980874124e3793c72420 b/txscript/data/taproot-ref/68052b4483af39b51b45980874124e3793c72420 new file mode 100644 index 0000000000..5a6ae99e4b --- /dev/null +++ b/txscript/data/taproot-ref/68052b4483af39b51b45980874124e3793c72420 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caa0100000063e069f98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49701000000410c148c017dbf160000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e712fb6959", "prevouts": ["8d71480000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "40c43200000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "b37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb9ecb57c15ba33b94e28a5bb7b52abdb34f711a224c068b58d3581d180ced2335a4766d58ec26ce2b4efcbf65574b66558d9985cca85178600ded982bb1eb8a33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a368ced990ebadb111ebc3982eac7e308f07f99a9264ca6c949f56162916d7884"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e46f47172cc098fd97d2a24de1b24a28ec1a07dba8121311e99b8793de3d58a2c368ced990ebadb111ebc3982eac7e308f07f99a9264ca6c949f56162916d7884"]}}, diff --git a/txscript/data/taproot-ref/680f37fd69b7d65b2bea1f6968d0d19d60d93bb6 b/txscript/data/taproot-ref/680f37fd69b7d65b2bea1f6968d0d19d60d93bb6 new file mode 100644 index 0000000000..839a0d3aa5 --- /dev/null +++ b/txscript/data/taproot-ref/680f37fd69b7d65b2bea1f6968d0d19d60d93bb6 @@ -0,0 +1 @@ +{"tx": "24ca7fe402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6b01000000e24a61968bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44500000000ca3ae0ff013c003800000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88accf07ac48", "prevouts": ["577755000000000022512054c099d7cf7db0853ef8782c8a4f2f22d5ed4b1e2f91866bde088ab8cd4c1400", "60373900000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e5135059a6e03da2faf37010c543c3df76a3376febfb8fd92f682776fb9c956d6fcd0fab6a67c3bf230276b49a6ca24f17dacdd3ceaaa340a5ba0b2ba475b0ee81a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ba1d7044f76185c852e3494a6fce96de1fdde778c7130ed924b07f57193456c18c78e356042728a8dc5293f4719d9544479381d7bc53161d8023b722566e5250874a9774daa89f30be275a1ff5113653dfa1548b9628ff9725cf694401ebdfe4"]}}, diff --git a/txscript/data/taproot-ref/682b9ef29382e2d77b5242e0860693527c825702 b/txscript/data/taproot-ref/682b9ef29382e2d77b5242e0860693527c825702 new file mode 100644 index 0000000000..ec68f31d63 --- /dev/null +++ b/txscript/data/taproot-ref/682b9ef29382e2d77b5242e0860693527c825702 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4d0100000097b2f1d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff300000000335a90e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43900000000f069d69701a1ee2600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aceb020000", "prevouts": ["98775d0000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf", "e37b73000000000017a9148462ed29696925d7688e1db8e76ef9e6667f05b287", "74ed3100000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d068", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a3792efafec61e3ae0d1fe66ad279b80b6a6067d0a217ee4ff0d115ccd768a971469e71666f51d71b691366cd88792f62b60965457ad0f8cff2baa31a91ced83d191de94316b2d555b882a7ea052cdcffb2858bcf3e9dcd4db66bb89a9914d760d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cdad8b7f4602765077dff9aa4c4351956f6937ba55252f34491fabec0d3f596721cddf589dd211ac28650b11a57c9c7761090d2defca181b3dbd9260ba7b6b1d191de94316b2d555b882a7ea052cdcffb2858bcf3e9dcd4db66bb89a9914d760d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}}, diff --git a/txscript/data/taproot-ref/68560332b36281ab2ef6e177361019a087666119 b/txscript/data/taproot-ref/68560332b36281ab2ef6e177361019a087666119 new file mode 100644 index 0000000000..10743cdd27 --- /dev/null +++ b/txscript/data/taproot-ref/68560332b36281ab2ef6e177361019a087666119 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703000000000fd549f910445780f0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e703030000", "prevouts": ["cc251100000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364c3da4617f1ee0f61cdd6b0c3800e0774a5e631cb6cd048785fdfa88f1b1ef57f81a0ae7b640e88bbe84e7c412f47337f1d12d37f95b062c539998fd28213cbdf3b3fb8d5121830dc5ea13d084a01bce62f4c2426ea7fcb92dda33a6ec3d9661"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef4a0b996a651997ca76f2d80ba069e4ceeac28cbc038cb062656a276693f78c3bd101e45a609d3b8e0b3b6f0b7594624f7e9102ef5d5dd3027418de40ebb2180d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}}, diff --git a/txscript/data/taproot-ref/685bad2808b9ebb6dd3bebf554aba2916e169a21 b/txscript/data/taproot-ref/685bad2808b9ebb6dd3bebf554aba2916e169a21 new file mode 100644 index 0000000000..b62fdb5b22 --- /dev/null +++ b/txscript/data/taproot-ref/685bad2808b9ebb6dd3bebf554aba2916e169a21 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfa0000000056f07197bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2e00000000e97e04addceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2e010000004e146fe30155a353000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6ed721a49", "prevouts": ["41e1250000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "b7c76800000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "603822000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063ca68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360933b5913dd2a3e84067c9c541247d08bdb55bc364eff1883b3d8a61fdf16b63d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c1012b923c15ff4ca5711684c82f77f7d0ace9e417918255ff860668826001128a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c1712c20a07a0457620eeaae766c8e6d37825c65d24f292e9d3da524b2ddb2c1be01dd809c80d07fbb65649666935b9712ecafc77e536b2a27c3cd6425d00c1ec7034c4ece6ceffdf067bd97d8bd2a80e986f14e8b5dca33ff1523eba7a77d63"]}}, diff --git a/txscript/data/taproot-ref/685c94cdfdc42c71493f0fbf86f6cc75a2bfe7f5 b/txscript/data/taproot-ref/685c94cdfdc42c71493f0fbf86f6cc75a2bfe7f5 new file mode 100644 index 0000000000..da7e77ac11 --- /dev/null +++ b/txscript/data/taproot-ref/685c94cdfdc42c71493f0fbf86f6cc75a2bfe7f5 @@ -0,0 +1 @@ +{"tx": "7b13900c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b76010000009ad734fedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4b01000000c5b820b103cef56b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e745000000", "prevouts": ["0177270000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "43f5460000000000165e142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692bef2ddc6a80d85c82e7a0acbf372ad032dbeb6650a3adfeab3820e5dccb400d7b73fe79aa50781a03db77b9e22252058e372f5a0275feae864cfaf4c2a217ec513aca5799d408eee0c275015e54cf6f255f9c56741048ad8672ad33d4825d8e26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93665e98030e68d3feb8f9ccbdb19e208fd51005dad116ab71fa8ee0a355037b3e1709247cbe4599f1b40c45655be9c4524e18ab036a38ca357e6d7c21966c7872b33cf35ac099042702f37424b07b91f05c9425e6e1d18ffa37c0a546b69cafd337007ac6d9f1365651a4d55e6df0dcb109d268cc6c386b355a4997173bc95c886"]}}, diff --git a/txscript/data/taproot-ref/6864a32b8e40345c0b76999afe5f1c070d474908 b/txscript/data/taproot-ref/6864a32b8e40345c0b76999afe5f1c070d474908 new file mode 100644 index 0000000000..5659876d09 --- /dev/null +++ b/txscript/data/taproot-ref/6864a32b8e40345c0b76999afe5f1c070d474908 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21000000006dfe2883dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc201000000b98404e201166f0a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a627f75b52", "prevouts": ["6cbb5b0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "dcc01e000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "f07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e829259a32967333cc74bf44ff096d479961194fa0f97de632ce420fba7b687b9321741bf2762a3041d275698fd56a81520b6404e88c31ed080bdecc36c09cb10e"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93615d9371bc52daa468585b81d9a616dfec30fa985244c10c6347844b2dacd11a03e6b1501de3c77a58ed25563289f7380fad902eb870a0fdd7293169316d7b75ff88c7bee1bb9c109f1c6365501285b6447b8ae029d34f47d1dd1efc50e8947b4"]}}, diff --git a/txscript/data/taproot-ref/6864d1927bc63a92a60460a41b2a104d48d49e0a b/txscript/data/taproot-ref/6864d1927bc63a92a60460a41b2a104d48d49e0a new file mode 100644 index 0000000000..d9e301cd74 --- /dev/null +++ b/txscript/data/taproot-ref/6864d1927bc63a92a60460a41b2a104d48d49e0a @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703100000000aae7c1ca60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127001010000004823318f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270060200000039d291e50304902e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e70b3b865a", "prevouts": ["076b0e00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "6753100000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "176f12000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "1f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e576fdfccd5cb93347e3ba64a7809a8c9fb7be90a7e18659d0b981582f285e98b3e02c0e1665e1d6a4b6ef98a6ef3a3632c98688db315e4c8eb8907479035d72"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936220439f899a0db699c3bd5563527680191a7809c0f178d96b69d6a5e01a1309ada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8a47d733f2ac96a3990499de942ef9a5afce6e4fdb28ae911c182ccc4b722ed2ed661e9ebd30f651fa020177c2a1e4ce51b505c9194e43d6074b392863f250ba"]}}, diff --git a/txscript/data/taproot-ref/687590a8d9eb9f62d77022572d103d4c5adc9867 b/txscript/data/taproot-ref/687590a8d9eb9f62d77022572d103d4c5adc9867 new file mode 100644 index 0000000000..3a2b29449f --- /dev/null +++ b/txscript/data/taproot-ref/687590a8d9eb9f62d77022572d103d4c5adc9867 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127014010000007885ab88bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3501000000d8098c37dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0800000000ce51b63e0198b6c300000000001600149d38710eb90e420b159c7a9263994c88e6810bc7bf71183c", "prevouts": ["2537120000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e", "5971770000000000215d1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "58b05a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ac", "final": true, "success": {"scriptSig": "", "witness": ["b4f7a89986206bb57be108f2587503325139625ec4adacf07a04d254fc9ada78e346601951c0ac808362b101028f3b8943716321a9b11ced5fefa304cdeb6ada", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7a608dc0f7d86f502dbcf40071a0824808709a0f90556d79dd4a8769a8f4382721bc45741c406121d867b44ea1636c09d50462631f6c4b1f522da1190f663f06ac", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/687648741dc59ceab592c14d35fa96ac27ef98d1 b/txscript/data/taproot-ref/687648741dc59ceab592c14d35fa96ac27ef98d1 new file mode 100644 index 0000000000..1749d6d0fd --- /dev/null +++ b/txscript/data/taproot-ref/687648741dc59ceab592c14d35fa96ac27ef98d1 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be301000000fb36def3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb301000000e6af33afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0c00000000754fa2b201d3161100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac7fabae57", "prevouts": ["c6bf250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b787490000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "1205240000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_39", "final": true, "success": {"scriptSig": "", "witness": ["0dab70a6fb2b5c835fc49da75566c5dd7d0d65403cdc08ce6a89060a5fa82e4319f8551389c3e13d604e9db9e69dcecb2e493ff5fc2de8225ed213d11b8d84b003"]}, "failure": {"scriptSig": "", "witness": ["f01f4ef223236aefb003b32d2e08eb5ec0d2bfaa4f7df8addcff85e63022d39078518400fa18b1ab5a59ea7a4d6b5faf3fe5a079d1fef82145f2bf3819f5e4be39"]}}, diff --git a/txscript/data/taproot-ref/6890f89ae85a96d458a2e92ae84db78ff5a3d8e4 b/txscript/data/taproot-ref/6890f89ae85a96d458a2e92ae84db78ff5a3d8e4 new file mode 100644 index 0000000000..3ad3da7344 --- /dev/null +++ b/txscript/data/taproot-ref/6890f89ae85a96d458a2e92ae84db78ff5a3d8e4 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0f00000000fea24c75bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0402000000ffd0d85002b76feb0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72e261f40", "prevouts": ["aca878000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "3ab5750000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e17387e8fdb6e1953b8492ce494f93b549856be52be3e0b2251aade3a72c8c2c0db79b88164a8f67b1298a482dda9483af1363bdf02371c7e121a2c285843f3f1e449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c8b4938871a8e43bb69010d25957b1b3dd5e0f775cf541eef5db4a9b76fa4cf4c71af5165e16a75a4d38ea496516a466796a1cbb48ef44578cf258de537130fb0277e21fac1036469cce09bee47dd6f35fd38d265061a05632a5c9d8280907c6449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}}, diff --git a/txscript/data/taproot-ref/6893c34edde19b9be594417a3321f7522c83713a b/txscript/data/taproot-ref/6893c34edde19b9be594417a3321f7522c83713a new file mode 100644 index 0000000000..f1ca122a06 --- /dev/null +++ b/txscript/data/taproot-ref/6893c34edde19b9be594417a3321f7522c83713a @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3d01000000da98460ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8401000000f6fde8a203bc4d9400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c147d44c", "prevouts": ["fc6370000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "5ab02500000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a96", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cbc2a23a7d8296d4ada3bfb9f5a799f80f89c8192169ead6b004adf320674e5033a51c0dffe7e5434825b6cc7212f0d90dea7a5d3b9982f8882f19203896a3c56fcd0fab6a67c3bf230276b49a6ca24f17dacdd3ceaaa340a5ba0b2ba475b0ee81a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bbbcd71201d7d2549d70d2328372419fb63309196d1406c01d663de3764feb62b186acb2a5feb9ca494b2668e3b95b217c5b1a118ef72c41b67fce4e6b051c90eb4e626fbd1c5a1d96a595c16e39be42f50aa7a1faa8ff1a1c0cc640b6e10eb9874a9774daa89f30be275a1ff5113653dfa1548b9628ff9725cf694401ebdfe4"]}}, diff --git a/txscript/data/taproot-ref/68ae4d6748f33706497031526da5fa76f0c923a1 b/txscript/data/taproot-ref/68ae4d6748f33706497031526da5fa76f0c923a1 new file mode 100644 index 0000000000..ed60de8803 --- /dev/null +++ b/txscript/data/taproot-ref/68ae4d6748f33706497031526da5fa76f0c923a1 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2701000000e971dabd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e601000000fb959bc7028d473700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a660000000", "prevouts": ["241d270000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "0c0a1200000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["cb4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936140d663498a4274ecf7f45240089a1df766efe22ae76bf8a987a78cbf23a246a1937db199a07e1996385ab03857d8e2ee63e136796e4b408281aef544a937c0c73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f551d5f9df51039c21b920ecc011c032a9913b031d76462e802a27cbd0d0ed8dd6d723e038e6335a667e0268d00f4826306437ee84552cc7f8172181160444ef73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}}, diff --git a/txscript/data/taproot-ref/68b62ec5b8680759a52e8934526dbf400162c104 b/txscript/data/taproot-ref/68b62ec5b8680759a52e8934526dbf400162c104 new file mode 100644 index 0000000000..431c5cc248 --- /dev/null +++ b/txscript/data/taproot-ref/68b62ec5b8680759a52e8934526dbf400162c104 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706d010000001db75c8f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e70100000040edebc3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf710000000010bd48dc0265f7b6000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc3fbaa343", "prevouts": ["9930120000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156", "dded350000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "1558710000000000225120ba259941c99089f87a1bc06d64ef249f01ab7891d30169746f94b5a6d9357ae2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ab7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e1084d1aecbe4c7880bb8a882fc35fa9ebdfb0d7259cb873bd54dfc151a0965e70144ecbe7fb1e6c18f5b14cfe26e6e35ca66fe7cdb676ad740673ee849f6d44e7c07bb1aa10d02d314eb70c923196d0e49e71087637e2d5a1d7fe44c2440c398"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa94b0c937046f490030e0d20905ef6ea85b70027c49d9391eab6e36e103b9e792f3dd0bfdeb3f64daf38e1101738c14790d5f1c68393c583b55b6fea5718d19818cb303569f28fbe8acbcc2d27d183e3a68170f5392df28f40a03efea695d856e"]}}, diff --git a/txscript/data/taproot-ref/68c6c0d42504385245c61282657b3afb267a068a b/txscript/data/taproot-ref/68c6c0d42504385245c61282657b3afb267a068a new file mode 100644 index 0000000000..1b16d382a8 --- /dev/null +++ b/txscript/data/taproot-ref/68c6c0d42504385245c61282657b3afb267a068a @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3300000000fd918ce48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dc0100000057bd5083dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf300000000c9b3ff710361ce9d0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961aad1f34", "prevouts": ["7dc71f00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "a33834000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "59974c00000000002353212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "5a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f5a747f2c0893f79fe153ae918ac3d696de9322aa679aae62051ff5ed83aa502db79ef349d3e4f05529a42271c6cf93f8e06fd8991a688edddf7288612a03eef8b5457f6f65490151d40d3d05d55f9c92d8dec73c7aa55a79aa7c51354918829c531ca70e78518003474f611c07657b0808402a053b744a80e6cf25146bdf24b"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0f84c5967c23664bae19475758c80d637c70256aa4f8440547e3702c69f37ebb4949da8d2968254411aebae49708200d0b19b59a844616925b107b397a8b89bee9c212f1ab0dfa1a42522b9ca3467b009d36f3b841f39cdc4da4a0520ce4fa4"]}}, diff --git a/txscript/data/taproot-ref/68ebe4901e5b73c0d6c376b14ab93cb27b6b9b29 b/txscript/data/taproot-ref/68ebe4901e5b73c0d6c376b14ab93cb27b6b9b29 new file mode 100644 index 0000000000..1b06240cf0 --- /dev/null +++ b/txscript/data/taproot-ref/68ebe4901e5b73c0d6c376b14ab93cb27b6b9b29 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3101000000eae4e7e90370872200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79619010000", "prevouts": ["5b7b250000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09022f9ad783d94518a53419533d0ba556a28c40c576bd961d392d21fecba958cd5ed244f61562037b43c30e20c78eb20b2bf5f2ba2fb6058f3e6e1fdd05c56e8a54d75571060e983ce0c5dc7ac0009c119ceaadcb3147fd13407074ae267fc26afce241cad575953b8cca2778894c709284b34dfe2956ac9985026f376388e418738fabf5c9f6690dd8587198f4e1ff7d71ec79f6e4dc95a66f6d99d2d7534a367f2a3b164269d3807c3f32a860066f2a4646fbdb5f1905cfb8450cc437b41c3014f1dd201e31d6f0ad531e7498fcea50deb7610b375fc44156b8b49b1081830c66e9e7fc7b86187dfc255966918178fed022908e386cde03521f70e85d90f6ab4391cf008d0df8b5d95f800770605c9ce9906362bc9d7e76eee2fa337a864dd52121591d0c5aee89e0cb8cce92bd26e309e8f2495fe57b24a8b950d98d0f9a0fee209b11bc1f96af9596219c4ecba28de97f0397601cf4c5dab3c91dd5f8f682d18806c13f63c78905f0c0a71f314abecc4a29c00a67467c42f5b2e55f3dced9fbe2b6836ac14c52517852792b7979b155996bcc54f993486b0c5213588d68557b52d1ed57dce4c483044c3e7e6258094ef129a63d6548121dc1481968712ee329fea3090f7903a7e5dab1262163108bc172cbaa307c503715cf970569950b41b0335e106d6a1ece839e2b78efb74f63059d5ba63655013c98ece82bad74b28f6a858deca40350649d6e75", "4e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef65db0c35e25312ba208c3242b68aa03b8861e5321a792f3566305ae352922e80d03cc4210f6c8d536ca11754de7a86c068de81055f4750ba9e0b801f8560f6a4a8046f0466b39966676954eca5d67ee52b1615e6fe46612ea9ab4edfa131fb"]}, "failure": {"scriptSig": "", "witness": ["4d0902ff5c2c0824edcd5ce542426bbd7edb7a2638e5bbd0353dc30e76d6911226baf2dd576cd43c0f12c6c4727ce90c40e551adc54dee75fbb28a41dc196e30ab91b63e831213926aa2bb5633804b904e97da19677bcd29c31618722851f5bcee66b289b775523eb782ae971fbbcc27eca67e2e8116bd42fc4018315d78835c1b2b51f342f86f3371836e9e321ebc03e4028d83fb66b10cced0a4a5573bba11bf02a3614bbd86555d53f494d5b1abaf414909cd68e899a3c65d2af3c93e4ac83c7e99dbbf5e8eb112a51314d557594843b93ed91cedc071a25fc38758ff0fc0ea874a7136f1bc6fc6d00ef58141fc0a37a0acfc6fd05728f434e2ed55732bad355de0e1e0369451d58ec35f689be86ba16473bba3afa0c36e9fb9fb5642b10f6cf649c96e81395811d8bdda0ea23612a08c202eb7c8141b6363a1de1a0119df8a2a4330358e6377f2dc0835e9f49cb0e9409638b39e7cd34488a1463e6e2a9eb71c6c4bc82630877a692a0d1a234bc6d03c35e2e85f6ed73f809df6e4227d8441dd82e4f9040d7d40fbf19033280d1883b24e69c1e2573d0fca560fdaaf14e0a8d407d46c91f4468f12e63394f2e2a813bad02de78eb9a72bbdb9e0e26b7586334bb9d62a7bf8082a5bbfdbca764c0976ab92ff16ab751652e0142ba0702ae8277f9dff9c6ea6ab0d64155683716242729023c0926cc9ab46e9b591330d2d6bd16535f7c542f4210c672f8375", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e9fcb6847defd4ab5435e313e937417091a847a9b6ba01e1bd1b0fdc0d1cd93789d8abe9ca6155576d0a7d6ce7b2728ac84476385b9c54c38b8a9cbf195895186ab153920b849b6028620ffd2b7e486a6f5e2411aa058dab621c72a45f67f5d8e"]}}, diff --git a/txscript/data/taproot-ref/68f2022142d8ce6c1188c67a635ce455d70e8668 b/txscript/data/taproot-ref/68f2022142d8ce6c1188c67a635ce455d70e8668 new file mode 100644 index 0000000000..c20811ca0f --- /dev/null +++ b/txscript/data/taproot-ref/68f2022142d8ce6c1188c67a635ce455d70e8668 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9a01000000b5f930dadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8d000000005ea06fac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127044000000007a558cdd0125890e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b1000000", "prevouts": ["5c0c570000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "7bdd4c0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "fc3d0e0000000000225a202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["15adfbdf2d9a81e924eb07cf93fc65631167ebeb7622328e77506ad9f633cbf6301c16517569b4b305066bdf9a44f200d00aca1696de04b0bcff77202ab867b4", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/68f3ade32553e6641d33ffec7c4bbbe70c966a75 b/txscript/data/taproot-ref/68f3ade32553e6641d33ffec7c4bbbe70c966a75 new file mode 100644 index 0000000000..9e700dc34d --- /dev/null +++ b/txscript/data/taproot-ref/68f3ade32553e6641d33ffec7c4bbbe70c966a75 @@ -0,0 +1 @@ +{"tx": "46adb1710260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709c01000000b5ef5db360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127053010000000d2fecdc02d72f21000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac59010000", "prevouts": ["9044120000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc", "d535110000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/branched_codesep/right", "final": true, "success": {"scriptSig": "", "witness": ["fa0524343816d323bbd31d2f3636430e704d2c13fc1e4184cfcd8f8926c91d01c732b89b2131ea4075dfcda5fd1c7b83816e9e0e666d2c0393563f2b58266e1b", "", "4d1301e76af030918e8d96a5e9c2094c9ba06d0ada8d0810ebc2f79ad890d92025a41b5cd08bdfc0cf7d4c9986cceba43fa0e9be5c2377c104330d94f07ea76f76de7aaa32e78ca0685201fb53e48ff30be8b782d5aacce7aecdb4508fb3a4147892070176fda3b74cad0a6f35c859d5e0d7627ae9b9ca8fdb5a4b5b652d3629350b6e6f11f7de2a627705b189459ee6bd1a593add61bffcce4e74b7b6af7efdd904948c80a13bf6734dd07387413a317d6a1134ecf76aae32aa7cf062cdb54d519d560c7a8549bc2fc161f890e330d20d78dced8994561d3d2bd7cdc1ede9bf9342f772d50abe38243c80d5649d81cd34a40ddfd49451e3305d4428e8856314a7308213c662f7f2d689b318f65bfcd530b15515dcf57563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ccd8c60a773165cc937efb02bc1b35e1115ac0671e1767a3af984f55e4d3c01bac00967532285e5651a233a5d3d97b0c986d2b78702c704bc34e0fc184218be"]}, "failure": {"scriptSig": "", "witness": ["ca47eedab1e22272267f0bbe91700822021f48b5888b39453d754b2bccf2f0cc3cef84fcd8b4969612016f023df66ead1d451d5c00ee9162fdadb086c2091e6701", "", "4d1301e76af030918e8d96a5e9c2094c9ba06d0ada8d0810ebc2f79ad890d92025a41b5cd08bdfc0cf7d4c9986cceba43fa0e9be5c2377c104330d94f07ea76f76de7aaa32e78ca0685201fb53e48ff30be8b782d5aacce7aecdb4508fb3a4147892070176fda3b74cad0a6f35c859d5e0d7627ae9b9ca8fdb5a4b5b652d3629350b6e6f11f7de2a627705b189459ee6bd1a593add61bffcce4e74b7b6af7efdd904948c80a13bf6734dd07387413a317d6a1134ecf76aae32aa7cf062cdb54d519d560c7a8549bc2fc161f890e330d20d78dced8994561d3d2bd7cdc1ede9bf9342f772d50abe38243c80d5649d81cd34a40ddfd49451e3305d4428e8856314a7308213c662f7f2d689b318f65bfcd530b15515dcf57563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ccd8c60a773165cc937efb02bc1b35e1115ac0671e1767a3af984f55e4d3c01bac00967532285e5651a233a5d3d97b0c986d2b78702c704bc34e0fc184218be"]}}, diff --git a/txscript/data/taproot-ref/692178574c30ecc0fe297e53225c7fe6b7047923 b/txscript/data/taproot-ref/692178574c30ecc0fe297e53225c7fe6b7047923 new file mode 100644 index 0000000000..4c95ed4d07 --- /dev/null +++ b/txscript/data/taproot-ref/692178574c30ecc0fe297e53225c7fe6b7047923 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700500000000d5fa4fd7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2f00000000fc361b8a0386bd590000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df9797223689879194515e", "prevouts": ["7158120000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "8aa7490000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "227d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e299ff42588850ae9aea87963ebfdf54b1866351a1c5b06174c8f3cba5c9b3108a2960a95becb1bbbe0636e0493c58f712af9b8da417013d797bf12c130ac560a4a9bce64ad1fc5af22ad5621933415c83e23766bbab20239912b691ace9dee2"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e86a45def9951625cf02c88598f8616d12bef3cc01ed824d79a70edf31b7fbe0e1a4a9bce64ad1fc5af22ad5621933415c83e23766bbab20239912b691ace9dee2"]}}, diff --git a/txscript/data/taproot-ref/692a5e26fd84eb7c487336a8ad5a27bbf550d3e5 b/txscript/data/taproot-ref/692a5e26fd84eb7c487336a8ad5a27bbf550d3e5 new file mode 100644 index 0000000000..2aeac14b1f --- /dev/null +++ b/txscript/data/taproot-ref/692a5e26fd84eb7c487336a8ad5a27bbf550d3e5 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5701000000bcb31209dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7301000000fa266ec5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd8010000005d4ca570010206ad000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d3a8b624", "prevouts": ["82e721000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "d0211f000000000017a914a5f28fe5532719f979169bfa3a31d5746f69452187", "fa38720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2357212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["23afd0f6352c489a263a48cf14d0dd717d50f486dc4046c2eb221875549b4056338600238683b6fbcf4b6791a455c92760fcb8f4ab092a15bba60baf978cdfdf", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/693b4e80b442d5871a480b72fc7f154489eada7b b/txscript/data/taproot-ref/693b4e80b442d5871a480b72fc7f154489eada7b new file mode 100644 index 0000000000..70051d8a6e --- /dev/null +++ b/txscript/data/taproot-ref/693b4e80b442d5871a480b72fc7f154489eada7b @@ -0,0 +1 @@ +{"tx": "9a9e95db02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7c01000000d1dd92ed60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b200000000832b678a025db336000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdfa28c60", "prevouts": ["c1f3270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a348100000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_9c", "final": true, "success": {"scriptSig": "", "witness": ["90b0d723931e2bb36780c33a4088d618e3b2a4b65f90c54aac0cca4b0f367c8803536b5d04eda010945d247bdc5fe6c2ca6d65d22ac962a4da49e11c5d412e52", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["19e4c4dc972df7e0765a345c3a8147c755b37dd40dbc3be82ca5fd75ff50ca5a5414c7a7b415cd8d2981de1b7b4b9ded00950847094007126ad7100fce95ca839c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/693f1072f030299b192b97d19cba8ff9e045ceba b/txscript/data/taproot-ref/693f1072f030299b192b97d19cba8ff9e045ceba new file mode 100644 index 0000000000..83ce6a336e --- /dev/null +++ b/txscript/data/taproot-ref/693f1072f030299b192b97d19cba8ff9e045ceba @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49d0000000063080aaebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa801000000660303ee60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ba01000000be4370b5010fb78c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7d8000000", "prevouts": ["c21240000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "da9f8400000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "a0b10f00000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b79b39d6cb61f48e6672b5ce685325f452f02f77d276e735b3392558c3ebee21de995344388049b948e4027b164fbf3fcb33b41e61c2f73c46060eaa1498de732e4881f4d906ebe4692161c26f2f86178cf5393c151301131e44f1cf86f8b21096ef7b1ca4b123dc476d04b2e3b6400f7ed578e17b2104739df24448a2eace6db9d6eaa43315a18a478b7fdb7deac7553c55f55a5e298f59e4d90f18f3b97de15b7a9211f342491d312d4640e2331123890148c67161c5502b31e8e2f0e268d6c139453a495e88797ecc12302c6d892337a0154e2b2d807662c6eb401cf063914114a603ae9f7d2d38002631449a759e0a5149c5faded1b7da45791f060974075dcd3047d4ebe3751cea6149f2ba8fa49fcd87a7135c1506b6707760362747da18a05fc7533b7c6c0600aa0f60ee7fa9b8b087b7b7c80eea539899d6a3b43454ac0bece29efc3e9ef95535ae3d3ed5087643dceafa5a2d5042ab64bce4d8547cc725c737e0c5143b19e107fd7c9eb5451cffbfe11d2f39bc089897f9e6ad2cdeaa91e221217fbaeadc5ccdddafcbd30432917c3b71915949017a9294e9f89a5a11b2de83f6e856071f064ba75ec27384d185ac5806ad33e0240f779de2fdab524dfb40c1a6c71a76e3f30547e604725a19dea1eff12cad7b9cf9f58c0b0e8f681923b4223a3cdd4e1479ec35a72017bba87c0bf4e5fa6f4ee091475a54e296e013a552f16e73a4040375", "4c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e891faf9d665bb151ea32d070ad80c7b31483dfb68e75e940e326e177970210d6f819d45740b1e9d6e416a8a4978331345395bf058ef0b936b66c7755017d83c65"]}, "failure": {"scriptSig": "", "witness": ["4d0902036721bed1287c33bbbb92e89e0eff42275c7a5a2e4fa4686175c3983daf57c190e9a7cebd60e38e9b04c0000a28da0c441dbe7221fae3c24e21f16b2174379e68e277c25b451dd9c144a523e056bc810bfc8eb54b8fd639e396a3620b38d5af0fadedfece7bd7eab6d55c7b8bd60dabb9bb508ba6b27f83e49f9ebcec5c0dfbca14072dd23125885a7ff1453f0d3d65b8217d3601f9dcfba2e7539a422f0966923cd0cee2a26c48f42e8558ada699cb0bcaff26d2f1d454b14cf33a6f32c907a47774461fa83a98f8130a8a0c6bc9fadbe2b5133ad348b3888fc20e1f0f8b690f0104501973435a46ed01508777e163e60589fd3dc792c22368311a7689c7860a825cca5edc2f116236d01ebba671b7301f57b2beb55e23ef0a5d0718905adf275234471a04656d9f4ef57a47b944d2b40d3aec62937a9273ebf1af5f887188e927ef492a18a53701e1b6f9d50118c43dddb6dd1bb36ae0bfa37d78766eee5ae0831ea5127c280aefa7bf984ce6797f7551ee29cd9b8b26ffad110d12b05fa3b0669a0d5fa19d7c1a775866d7c34f8b869e67c93a6795278b567b5ab2978563793623f81e1eb778c2d0bb2003d28db84870dc76d8507ea4fc3a7ea58661c0e2bcafad3590b3a4e4eb058bd0a92c4f0a8c833b8aeae47f35d70989862b3520eaf6c0833bcbe320489d55529826d1689c940b615a605094fa67ff28870a83ec26a867ff06cafd4ebbc975", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936188aba67a59ab5982a35b0b88af28c395ee73611f1233e5ccb71bc1279e708bb0315d5fffb9cd0a0ee84b5f33e057fa02d78cd067c105b2c4520fb43cbb3cdd0d30287fa60720c35e6546eaa391bbb3975ba5e1722a6124c426d678e7f784bd9"]}}, diff --git a/txscript/data/taproot-ref/696eb3cf37f866313a3dbf40b4af77d45f827d98 b/txscript/data/taproot-ref/696eb3cf37f866313a3dbf40b4af77d45f827d98 new file mode 100644 index 0000000000..f074342ccd --- /dev/null +++ b/txscript/data/taproot-ref/696eb3cf37f866313a3dbf40b4af77d45f827d98 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709e0000000047e9de70bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf36000000000931f20a02e0517500000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc22fbf46", "prevouts": ["e25a0f000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787", "c8216800000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["cc4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688e21e0ba4623d9f1238b4cab1fe6058b8adee7f586c209e41396c5ed78664fb1e80b1f8b709fd7e9f8915460d72d278aa0d12452680dedc295e1cc62d069d9c5f8b38696f7f521c781f821b55aa4ff86c04fbebd102ad129a9d47907becd36b4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}, "failure": {"scriptSig": "", "witness": ["4c52cc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0d00ae7d77688765097c61dd6dc7203a99b1de19633b0fe895af4a245d0fe1ab9735478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}}, diff --git a/txscript/data/taproot-ref/69763ca3d19be4c3d360ac96f990730c211450f4 b/txscript/data/taproot-ref/69763ca3d19be4c3d360ac96f990730c211450f4 new file mode 100644 index 0000000000..ba198cb03d --- /dev/null +++ b/txscript/data/taproot-ref/69763ca3d19be4c3d360ac96f990730c211450f4 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700302000000ab56471b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41201000000d13155dc035cd64100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdd5eaf2b", "prevouts": ["b4e90f0000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "38243400000000002251207c84ae2d9063cc63412a30e00823aa01b05bc54bcf6d9936dc1c650bbdc9e98b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/padshortcontrol", "final": true, "success": {"scriptSig": "", "witness": ["96edcf3d2ff03e75e15cb688a69a9145f917f18fc1907d79b682e3c5ae27ae90b87ff58a7f5fc74786825a9291da4f3f5615625de8f4fc43ca6766bab2c724ae", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20"]}, "failure": {"scriptSig": "", "witness": ["96edcf3d2ff03e75e15cb688a69a9145f917f18fc1907d79b682e3c5ae27ae90b87ff58a7f5fc74786825a9291da4f3f5615625de8f4fc43ca6766bab2c724ae", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2030a5a7f3bb1d8a36740590"]}}, diff --git a/txscript/data/taproot-ref/6977dc4cb03457ddcfe3fb5e4ebd32c7a60a4f4e b/txscript/data/taproot-ref/6977dc4cb03457ddcfe3fb5e4ebd32c7a60a4f4e new file mode 100644 index 0000000000..6ad45c6eae --- /dev/null +++ b/txscript/data/taproot-ref/6977dc4cb03457ddcfe3fb5e4ebd32c7a60a4f4e @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e900000000852477de60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704301000000434e8635dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bab01000000ef552e5e0380634000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875e020000", "prevouts": ["f4eb1000000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8", "4b251000000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "e5f4200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a6", "final": true, "success": {"scriptSig": "", "witness": ["6dc81c0e415de7c9f522a5abcae782ff177bd07390420ae7339bb131c7d0d5cf172296cc98dc31023c5dc0ae8da07aec290eb7c6a91aa8539187d44339d473dc", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["4b9fb81f9867a1b174e1b429a8aea705300f841a00c070da618ad4dafb7c24e280ce9d7e7b9213b692adf7276aba4acd804c8adad309cceae38da850ec1eb62fa6", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/697a7f07151aad714b88aad13a439841eb1d849b b/txscript/data/taproot-ref/697a7f07151aad714b88aad13a439841eb1d849b new file mode 100644 index 0000000000..b426e57f73 --- /dev/null +++ b/txscript/data/taproot-ref/697a7f07151aad714b88aad13a439841eb1d849b @@ -0,0 +1 @@ +{"tx": "66a8b84102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf440100000027cdb0cb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a301000000fbab0fe603154c8c000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc74dc3dd23", "prevouts": ["ff977d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8a63100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ed", "final": true, "success": {"scriptSig": "", "witness": ["82300fbea4eef67691c08244338531c3737a190699728b50381ca4992578a33ca38b3c3450038a813eee1c168a6bbd57e9228f9f672dec6dc57bd843dea76fbf02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["17d393fee9a3b7b3979e0e603de2353d10d9bcff79830d9b76d117cb93629dd7dba32261c6c6933ad072df9d347532d13d7ca5d88ecff20037169053cbb4eabeed", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/69c1c268224ffcce5d6dc13b49962a3c8887c2ba b/txscript/data/taproot-ref/69c1c268224ffcce5d6dc13b49962a3c8887c2ba new file mode 100644 index 0000000000..c78bf0b8af --- /dev/null +++ b/txscript/data/taproot-ref/69c1c268224ffcce5d6dc13b49962a3c8887c2ba @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bce01000000e9160568dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7d000000004acaea1b0404d97d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374873d020000", "prevouts": ["7f13270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "37b0580000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_4d", "final": true, "success": {"scriptSig": "", "witness": ["6342099a527d5a2f27f6c97be59bbba6bbe68b385e8beede02041a57fdea60eab00aa1b932374a0c44ba09eeb42d3524be87050645f97ac42cb1965fbfa829f401"]}, "failure": {"scriptSig": "", "witness": ["400b05938759609eba837076dc410cff019d984f61113e8dd2168b99ece14ca63316079a60765466cc00cef56d29a59088b9d1c1cc078b1fa649ee01fca03b9c4d"]}}, diff --git a/txscript/data/taproot-ref/69d24f5639ca8a5eaf58924722cc313b9936c330 b/txscript/data/taproot-ref/69d24f5639ca8a5eaf58924722cc313b9936c330 new file mode 100644 index 0000000000..85271df79f --- /dev/null +++ b/txscript/data/taproot-ref/69d24f5639ca8a5eaf58924722cc313b9936c330 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127095000000005c767951dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8e010000004a51eaed04d34b570000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc73b010000", "prevouts": ["4f500e00000000002251207642517ca6719fb19e4d50e91940e680bbab7ca2eac6cb77783eaa45a9fa38f3", "342c4b0000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936761301ea059e5d2efb2c92912ea7774ef29449812e7d265e858b6fd1c0b51434"]}, "failure": {"scriptSig": "", "witness": ["6a9b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/69f36a1e1c567e1d5e44edc58c355abb92e23f68 b/txscript/data/taproot-ref/69f36a1e1c567e1d5e44edc58c355abb92e23f68 new file mode 100644 index 0000000000..45e714fe77 --- /dev/null +++ b/txscript/data/taproot-ref/69f36a1e1c567e1d5e44edc58c355abb92e23f68 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b14000000005d6cd1b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bd01000000cedba4cd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700102000000d9229fe1044be13e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c7040000", "prevouts": ["a80a1f00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "1e3d120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "67ba0f0000000000225120fa0c69fd3dab50066606d386e9137466ea422a077bab3cf3dc61d0cdd59f488d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d768", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936abfe64118223b3c7ae9aa80074b53dd2a4e83d9249918438f788702c58e4386314746b6cdbbdbe747c087a2d99e7432ddfa1db1d7a6445e7dea3810e7475536557a61376c510bdd1fc860151a3b261939fa407ec1a2d0490cf2efc4278abc783"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f3613db4328df8356bb49396f684a07533c02af693a1f1370e1c4eec8af8b548908709641cf32dc4788f906f7e3621a0528df09509ddf1e9982e4479aa4b5d9a2d50ee9aa3de1fe988255b0d8b9f34dc2cecc4a96432b9f704e90359a06b468476e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}}, diff --git a/txscript/data/taproot-ref/6a35130e1e9674f6d1c241fd478fe85332fbdbb1 b/txscript/data/taproot-ref/6a35130e1e9674f6d1c241fd478fe85332fbdbb1 new file mode 100644 index 0000000000..d4a07492b1 --- /dev/null +++ b/txscript/data/taproot-ref/6a35130e1e9674f6d1c241fd478fe85332fbdbb1 @@ -0,0 +1 @@ +{"tx": "f566a34e02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbb0100000061ba5eab60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702c00000000845ff5f404e063680000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478735000000", "prevouts": ["da89580000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5ee4120000000000225120770a4859be8fbe7a841bd8e66a93f9515817dcc93bcbf3e365174d34bc6304a6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_cd", "final": true, "success": {"scriptSig": "", "witness": ["b7754e9094c652ebeda837bfa63d050337f67969fec6b0da1adcbb1d6189cacea5759a0b3bf1d641a9d344704c15dfc8d65e7303d48e2a2fb902e5f569c9144982", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["addedeecbf0a5978da663bb1e37be31f6a4b8c7cf48769fe49d2d8afc3194bd98b2616497deacbe55bb1d7c426829a3d1da1629ccd03e5f9e01c4b89a5143324cd", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6a37620db708370995281cf6c46512cd60efeda8 b/txscript/data/taproot-ref/6a37620db708370995281cf6c46512cd60efeda8 new file mode 100644 index 0000000000..1e70d29d15 --- /dev/null +++ b/txscript/data/taproot-ref/6a37620db708370995281cf6c46512cd60efeda8 @@ -0,0 +1 @@ +{"tx": "d2a4b633018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c80100000073d678ff03878d34000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acc9889e3c", "prevouts": ["be89360000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d2593bff1b0effa885b0aee87a7b2d32e61d34e0a8c26ab8da95f21cdf0740a021a06fc3128a9eadf7c181b12783fc0ac677434699a36c8776c14fb861b85f3ba54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dabe61c7346d5e238de070e35e4de194798ce817dea2f205b09d5c015998f3d54e3e51653db7a26891b04c3a1156361c2ac14b53ddf2b0df0fb784e58b5ceef674166a9b0f1c55c1671126e5eb7d3b70cf827ee1dc762db7ef6404d6cf84ba0da54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}}, diff --git a/txscript/data/taproot-ref/6a8e8effd233033afabfdaf9d971d772b2bf9ecd b/txscript/data/taproot-ref/6a8e8effd233033afabfdaf9d971d772b2bf9ecd new file mode 100644 index 0000000000..c69cc25dd5 --- /dev/null +++ b/txscript/data/taproot-ref/6a8e8effd233033afabfdaf9d971d772b2bf9ecd @@ -0,0 +1 @@ +{"tx": "b1bb4f9803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2400000000817a20b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127002000000008e1dc3c4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2e01000000783f4ee701e06a59000000000017a914719f78084af863e000acd618ba76df9797223689870f010000", "prevouts": ["90cc23000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "7ab50f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "546d5600000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_2b", "final": true, "success": {"scriptSig": "", "witness": ["38ed76305929f02dc349485a61c09a6c830e24769200d31626eb387aa97068874ae3508ac14ff04b57c3a47bfc82fda6e627e3598fb139a1d7431e904158202301", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["e3bfb102a8ae4aa8b7cf028538d64a4e507655f0c6543d9708b6da907b5a3a528fd8709be59d04619725fd0c1df9c3e698925a6c20c4adf2593fcbb7ee21f36c2a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6abb0ece7e16ec849987f8c8acf3aee7013ec5de b/txscript/data/taproot-ref/6abb0ece7e16ec849987f8c8acf3aee7013ec5de new file mode 100644 index 0000000000..4b887cd600 --- /dev/null +++ b/txscript/data/taproot-ref/6abb0ece7e16ec849987f8c8acf3aee7013ec5de @@ -0,0 +1 @@ +{"tx": "0ffdd2c802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa301000000e046c88abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3b01000000c75831b90470e1e0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac68aa0452", "prevouts": ["a79e7f0000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "da1c640000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "473044022019b75a030c13440d0d25d275157e4f1c8eb6c5f583c5720f3b60fb2de123007a02200fcd4f1305bb03ee79a22f7b1a6af61a05dda3a0e59345ce880952bcc0c9aaf5b2", "witness": []}, "failure": {"scriptSig": "4730440220619c5c65290ae5bb6210dc7ae9e8b32431a22ab84050373e1248680426cc603b02200929fde99a5101b851dbc6f332917cbf6ea421ba3c54b06ac2e30ac7f4976d13b2", "witness": []}}, diff --git a/txscript/data/taproot-ref/6addba1d7123769bf9727a6a4106110126f36086 b/txscript/data/taproot-ref/6addba1d7123769bf9727a6a4106110126f36086 new file mode 100644 index 0000000000..3bfb7cf09a --- /dev/null +++ b/txscript/data/taproot-ref/6addba1d7123769bf9727a6a4106110126f36086 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce3010000003bfe4fc1018631450000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79627030000", "prevouts": ["3c1f4b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_44", "final": true, "success": {"scriptSig": "", "witness": ["306f528964a2f5b7939f9ac242ab90719dce5b19dc0b69ec69ffcdd460fa36cf3edbb5d80f2402319194811e27113309eac01201b1684f8c9716d5301524eea402"]}, "failure": {"scriptSig": "", "witness": ["be99136011f0913eb2dedfba07c610bbcde72af7c9df4f493a6f6fed292467bbc23da1f22a895d343912d9247ee4a88f064fd2a97374d2624d945ed28d89d8f544"]}}, diff --git a/txscript/data/taproot-ref/6aff050ffc62f58100aca0e5b1839f097fe65155 b/txscript/data/taproot-ref/6aff050ffc62f58100aca0e5b1839f097fe65155 new file mode 100644 index 0000000000..f74cc021ab --- /dev/null +++ b/txscript/data/taproot-ref/6aff050ffc62f58100aca0e5b1839f097fe65155 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd9000000006f1fc6ecbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6e01000000753656c9038b73c300000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388aca1000000", "prevouts": ["eb125600000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "6b7f6f00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "807d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a0a4157aaff13ca2809f2717d1454e35c7fe22b58bbf3d38eb14bb2d8f6dda2c9bb3dc44e72947935649b33aa2d807ea07560e0c2333a7ee2c40c2820b24a64a090cbfbdc5dfcad7ff4463f3cf2898b3c754f5d70a369d7bdece79053e0da647"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e6d3ed6bb397f900bca42f5c55206e9e9a5556fe68666fe0d64ebb28af9dc03c732beddb8df376ed0f15f8ca557ca4fa4dab9ea34398a6bb2b3d4cd5dda00bcea090cbfbdc5dfcad7ff4463f3cf2898b3c754f5d70a369d7bdece79053e0da647"]}}, diff --git a/txscript/data/taproot-ref/6aff0519662314531494b8b3319e2768ebd40a35 b/txscript/data/taproot-ref/6aff0519662314531494b8b3319e2768ebd40a35 new file mode 100644 index 0000000000..6869586d9f --- /dev/null +++ b/txscript/data/taproot-ref/6aff0519662314531494b8b3319e2768ebd40a35 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f800000000fdb29b5b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705101000000f4984f1f04d30d4500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ba000000", "prevouts": ["a949370000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "4e5a0f0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa234cf532d828cda123a8c35eaf5d21c66c96423d9004c9f2b6e0f5ba33bf4e7b5b0de380cf0ebf0fa9d17e1d1edb87a374b64935c1c67f0c5024fcc072643681"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9edf285c3ff17340269ce4937990b92b11525a7bbe669dfecc4ad5542cd24bf5111e542fd849c49f4d44aada2d8e1aab946c793c1d334242f5a6d1a51a6de2d5b0de380cf0ebf0fa9d17e1d1edb87a374b64935c1c67f0c5024fcc072643681"]}}, diff --git a/txscript/data/taproot-ref/6b14353e2b7d7788062623a8ab274c36f8e8bf3b b/txscript/data/taproot-ref/6b14353e2b7d7788062623a8ab274c36f8e8bf3b new file mode 100644 index 0000000000..54f4ce8558 --- /dev/null +++ b/txscript/data/taproot-ref/6b14353e2b7d7788062623a8ab274c36f8e8bf3b @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca9000000009dff9cf2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8e0000000003edc09f0396a2ae00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689872927853a", "prevouts": ["872f5600000000002260202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "759c5a00000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["5edb9a0c74e702190efa0d08a6efde6df53a84ca9ddce445816b6240e779519091725c66624cdb8d7186ec31dcef6a5fa4f81e7cc1318d959d333c1a90ae40a1", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/6b611309b991acee95b55b4b19539f65ceccf76b b/txscript/data/taproot-ref/6b611309b991acee95b55b4b19539f65ceccf76b new file mode 100644 index 0000000000..f39738ed2b --- /dev/null +++ b/txscript/data/taproot-ref/6b611309b991acee95b55b4b19539f65ceccf76b @@ -0,0 +1 @@ +{"tx": "dd3b93eb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4350100000001cd7ca760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703001000000c72c4ce603c01c4200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787eb283c35", "prevouts": ["7397340000000000215e1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "621410000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["304402205c8335b25c6f8f036f04b0a7a3e460073f8a36d06701a4eeb13e61cc29bb9a2b0220292e057865f1e7c9fc5119e4fcdaeca77f3158fad6904b64e5a1387beba8fc78b4", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["304402206e61a9131f28e30cc16a2d8792a47fdf81d0c09cc344c63365c212538741123102202757695d5930069c5b70f93e64909d952e881d022a0971eefa759612c252247fb4", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/6b861044122a6b081803e3a99f47b40277743d06 b/txscript/data/taproot-ref/6b861044122a6b081803e3a99f47b40277743d06 new file mode 100644 index 0000000000..f5012f5f52 --- /dev/null +++ b/txscript/data/taproot-ref/6b861044122a6b081803e3a99f47b40277743d06 @@ -0,0 +1 @@ +{"tx": "7fe69d4d0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706601000000d2634dff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40401000000a84fafc5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0002000000b17c94b301c64a37000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48713020000", "prevouts": ["0a4311000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "feaf310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8d227a000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_56", "final": true, "success": {"scriptSig": "", "witness": ["fa795ffbeaefe29bff34e91ad2ad22149ca65e0bb83013f3009cfc9339fa23bfa8e87879dca8231d707f76cfc9397be931b40354d0c5cadf8486dce72984417081", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["881c091013dd2e1068f9c53039d914e8bf786fcc64fa14604ef8634811a0405ecc42a12197ce6e8143b334ee01309722b6bebb17a3c968498ae23201503ded0156", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6b8790739dcd1f8d3ef41a03c6508717d78feb52 b/txscript/data/taproot-ref/6b8790739dcd1f8d3ef41a03c6508717d78feb52 new file mode 100644 index 0000000000..92888194eb --- /dev/null +++ b/txscript/data/taproot-ref/6b8790739dcd1f8d3ef41a03c6508717d78feb52 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf270000000002c2377a011b63710000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb077df5e", "prevouts": ["4e6080000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b2d644bb9e96bc550db818ad4a9f84f3bfb9c250241a6740872b4a4bc563fb4ad98bb198f102a907fd10c5bf2e0e4d2bfc9bb38d19b996f85912f97f03c8ac578a90658a7aad5df2d1c5d455740a8352e3ec45e758de66fe280b4b2a8d141889e9ceeda484a8fbb1974ef5b6bb846e6aa0bee04d9164b21ca42714104493fce64045e2eeb8e4797e4583bc9141ca032f9d244ac5291204277e2c4bc03a0cd8fd7d46c21b60cf0d9ecd056fe6b7c4bea1b0665c0e45ec7cdb1aa4e44798a73095419520db9a346ab675e69b41b219bf0b0918dc85834c39e61149d384a66cdc9685afc92afa4cee53c89aa91bc367fea6b6ecf6075c09b057c0a586321352373d89a8c2c3c1e551f2f979a319eef589d3e031c5b58059bbdb82e6bb79a6bcf7b1a6126fd103eaf833d2b59274603ebcd148187f79a393b4adf3d77634429d7c2ab80767a446cb320c8b5498f66082d597c913a9d3ec74505f51538a20b70d042c82b08f52b3b835e8bf542aac88722f125c1f89c6a8c0f5888169a63ac2dbb5f8171573e7fc73f7b275f130be21323c4d8fb6670d055bc28b50bf6d43b2f4ac2fb9f971aaad6cb51f55587a440aac23699ac35cff9053f452bb53a67268195ce2e21d4484140b8d38907e32b086cba42bab7204cb80d2420f89f310f95bf8ee3f9cf59f3c1ef4e35da197e5232e91ea0e5a67b9bc6ba8c4f039b311f6dcee13956dfb948604b13f051975", "027d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08244c267ebca37631eb8e8b6e08a101702978fd7f172e21a8d6d6b527626f4402168cf2d3d0be95621d7446294d89d9a2894510d2dfb4e1a33e7316a17e39cfc99"]}, "failure": {"scriptSig": "", "witness": ["4d0902f9e1cbaf4725ee2c8f729e48cc0aec6866934bc3ea610b2c6a629b109cdf36811fca45561939289d34ebccaf6a88180973115ce8705913ae2086b84370bb0b9d2806ecd0ac6731ef8e77383cc12a75173b1f985c86e562915b39ad04fb20874f1046f2a4b16114423ecd26baa954cbba65c8f4d034e0aef9172f5c06e3ee6ec6d80ca1fbd68ae166d4a1aea8842b72adb03e5a414b4c521a460d7dc0a6eca458f6f1d3fd945687d8178de82d4012138def9bc93a2682a9c610d13d3d47718cc728c010ba1728a8763eb82ffefab35e6ad06b5ad874022b1dce383c61389ebd626ed74ff33bf8e49ea6f348e74f81d38c83d2dffb85d92d0d0c8ef6337491067f3cd9cfaee2b39b1d972f9998f34bc2bc5cfda7083b039c5047cfb560574c4393ef6a915ead6b7254cd5c6853bfb6b3d331c23b64a774758d535f401e66ef078876d20fb7e3d032cc84daf0a4ec0b463f366d6665925b20765ce5dc18f4e2dd8b008fe240195687dce13b07ee3f9c7f7ff6176cc6ef9a5c716ac35e610629ea0c9cfbf9b17d395be58887af2f68859723b0623f1911c9ceaf788efa7c4c1040ab94ee97f388bc5e18fa505b6e65c7fb2590f4828b331028f1680e20356636c6a69bd048eefbc04cd4a1e26242e280626565c5fe2dc6c5ff2d65783a12234e941b6f5cf0518500daf13ad9742de619cfbc5f5ca745e3fc1c5e9ea5af49a54e58208ebe6bb081f095363f75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eea584dae4332b3044a4c8d351fbda1a9ce22b0be13f72ff111d82ccfa4c6759e0e32049d91f42cbcb04955cd98e985d287b85d3c77c1154d8406ae5e2d81b7b1"]}}, diff --git a/txscript/data/taproot-ref/6ba407f0a422507bed18c1d5b52f1f550c278fcb b/txscript/data/taproot-ref/6ba407f0a422507bed18c1d5b52f1f550c278fcb new file mode 100644 index 0000000000..622e7849da --- /dev/null +++ b/txscript/data/taproot-ref/6ba407f0a422507bed18c1d5b52f1f550c278fcb @@ -0,0 +1 @@ +{"tx": "9b03967e038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40201000000116593bcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c30000000008140a59460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bc010000003f8a038f03ce439b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a61f020000", "prevouts": ["fa123a000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "d8a45300000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "95390f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_4c", "final": true, "success": {"scriptSig": "", "witness": ["86ce071bf60dc606020d2b39afd8cc4ef834eacd817eba063a1fcbd579e2a6d88968cc7292a81c746ed58b21bc7014940f83da3b3c243703ba69b93864e4072802"]}, "failure": {"scriptSig": "", "witness": ["85cb2c73dd46ae83844964ba8c6f7c039a81439e6e2c9d651d6ba8964d1305a9620c12012ea9fc6d62e638b0b7497e68ab5d7db547b5f548b098859a63e3d1a14c"]}}, diff --git a/txscript/data/taproot-ref/6bc93c9d2144506aeb9dbbe41a5b4a095f8fe9cb b/txscript/data/taproot-ref/6bc93c9d2144506aeb9dbbe41a5b4a095f8fe9cb new file mode 100644 index 0000000000..43a0bc1f65 --- /dev/null +++ b/txscript/data/taproot-ref/6bc93c9d2144506aeb9dbbe41a5b4a095f8fe9cb @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf201000000ce5eda9bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2f010000005618a396bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0701000000427c408b01084841000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487d4145d56", "prevouts": ["24fb4c0000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "4f8a7600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "3763820000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045f693e8696ee404d8be98a67cec2febef1e0f75b013501a27963a3fb4300a4da26e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360f6c1019362bec2bf08a39208cd8ab9e5ec501f845acab16bbbd93a90644444aa6ec201a93e79c82aebcb32c5742cba4049490cef67cba707365d2e1379631f73bd198ccbfa9c702c0592bb8c84a948c36ef9eddfd1aec8278a333dab45811656e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}}, diff --git a/txscript/data/taproot-ref/6bde125fedeb05208eb8991bab6ad0713a60d9e4 b/txscript/data/taproot-ref/6bde125fedeb05208eb8991bab6ad0713a60d9e4 new file mode 100644 index 0000000000..9753aed16c --- /dev/null +++ b/txscript/data/taproot-ref/6bde125fedeb05208eb8991bab6ad0713a60d9e4 @@ -0,0 +1 @@ +{"tx": "0d8311b402bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd701000000fe04979960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700a00000000da955a9d01905b3a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a636020000", "prevouts": ["df00720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "73d312000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a8", "final": true, "success": {"scriptSig": "", "witness": ["fc26ccb95093c1f4d7d5f63bcca121f2d079547ae6cf70d8b73908c4c50796e6393470992ee7048db8d856a94f0699d2396119f30de7021675c12148b1dc6b3602"]}, "failure": {"scriptSig": "", "witness": ["49e53212930b1a04c55cb7b2da7b7410798ee22339e97d608a425f035a77c6daaa2da896e48892c11530a044939863c86635a89c5c479cd41b6830d9b103cfd7a8"]}}, diff --git a/txscript/data/taproot-ref/6be0d8042ea3f474de849bc8205c65b017a3d587 b/txscript/data/taproot-ref/6be0d8042ea3f474de849bc8205c65b017a3d587 new file mode 100644 index 0000000000..ababc08b2c --- /dev/null +++ b/txscript/data/taproot-ref/6be0d8042ea3f474de849bc8205c65b017a3d587 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127080010000003832b55860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f600000000395e212301b0d0000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79609c18144", "prevouts": ["126f1200000000002360212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "1cc50e00000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "997d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b19b5f1885a20d35a814ca61d4ff855898dc4931a7face6e73cd2cb9656d66dde3e7df71444e7cc76d8e211582e4acb0f4a71a503115fbd605db9d475b3b0609413afa0de0ff2ef52577d4c80443f6003c675907986908c28bc93ded208ca160"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363b008e11d5a212ab8cf1e35e075d499c0a83e06f0fb3690023328021119d686440197dfa5e15d56b0c52ba6c1e960d9371338186786a853de15f9da987536b6f0e580b14ffff5bbee812c9f6e3af6b100c6b4cffaf41971c257964f1fb14f6f9"]}}, diff --git a/txscript/data/taproot-ref/6c1bef32f6ca0cfaee1705746902336e4fd67e96 b/txscript/data/taproot-ref/6c1bef32f6ca0cfaee1705746902336e4fd67e96 new file mode 100644 index 0000000000..ca6f223d12 --- /dev/null +++ b/txscript/data/taproot-ref/6c1bef32f6ca0cfaee1705746902336e4fd67e96 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47a010000004febb4ce8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45701000000ef83efd203d03a6d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac6e000000", "prevouts": ["a714330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "28593c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_7e", "final": true, "success": {"scriptSig": "", "witness": ["18e4979551e7e9dea17ee3a1af3a495cd8b6825bfa50e3189214e8a4c313567aa87267c54a59b9f2a9e77b01de73e083160d0144cdd660f8907f8d922536ba1382", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["811439e6d09bc5d45950c0d14c811531f11006434039013de4c863a5d779f410116286832902192e14cb7afd307f8e73d4d9f5d52058e52b38de6c8c6709cdbd7e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6c3db2c6ab0b6b80838387b923869561f9e1cf11 b/txscript/data/taproot-ref/6c3db2c6ab0b6b80838387b923869561f9e1cf11 new file mode 100644 index 0000000000..a64a953498 --- /dev/null +++ b/txscript/data/taproot-ref/6c3db2c6ab0b6b80838387b923869561f9e1cf11 @@ -0,0 +1 @@ +{"tx": "5cfa37d7028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a301000000ee493d81dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7d010000000e4618c40212f89a0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcac3bac60", "prevouts": ["b6d9410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "dde95b0000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "da", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93647616881cc706df192d68bdb7ce4fefac112c6e83b2fc7e7a0b73ea4516ce84599aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41dc38fa67d6e370c9f405c2af01822f370dc317d6e78d2f71aa14f0ce4de56d6ee4d75780d36bffae9b56136e6d27c02b8d233efdc800bb260bfbba6a6f94b87"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e116c8ab92abfbe4bc2686b5b42764123e12e1b7fae7b64d8b1bf7005c7df7fa0a3ad7647dae649c97c815eebecc244cfd5d14ac6da92e0e18049c71625e2af9496ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}}, diff --git a/txscript/data/taproot-ref/6c7e6cdda9913347f0ba8eed8f914941cec5b2c1 b/txscript/data/taproot-ref/6c7e6cdda9913347f0ba8eed8f914941cec5b2c1 new file mode 100644 index 0000000000..db6538f5c0 --- /dev/null +++ b/txscript/data/taproot-ref/6c7e6cdda9913347f0ba8eed8f914941cec5b2c1 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6701000000a473d9cfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cda0000000076ecb2df043144cd0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7edb0fd40", "prevouts": ["2b0574000000000017a9146f2d26adc5ad58653becfc45ce03a0b1167b1b7e87", "56ed5a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "225f202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["385484846fa19f210d3cbc3ad01284046f449d4536f52d57b6ca832e6f1422fc1317b9ccf2d8431150be3ed07f786824360850b023600447926a67b46da42918", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/6c8a1b2ea553e6dfa5f653afeeb135465732aa6e b/txscript/data/taproot-ref/6c8a1b2ea553e6dfa5f653afeeb135465732aa6e new file mode 100644 index 0000000000..e1a2eed239 --- /dev/null +++ b/txscript/data/taproot-ref/6c8a1b2ea553e6dfa5f653afeeb135465732aa6e @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ce000000004bd0f99e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270610000000097c65b8d01828a39000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47877a0b633c", "prevouts": ["06f4350000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "30571100000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c968", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d781d2df2a0bcb6c98ddf188a5de84fa915a80c53246c09cb7161fa1ccd707e89fc6d70c1c4e15dab7d2fdd5db26cf688ca78f103ab970182d2c6706fc8281bcc9238bf2d7dc0bcf11838c34785251ea2fa5f3bb034bc98e2e8efb0909b7dbc17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b91f1c16b63f67fc716dcb8fb6def1d88e508150b21ac27e49c0548d78f0224d3bd2bf476d5c79b80d1dc385df1320868058b4af6871225604d123c25805c1374cc0fc2e3b1a564cf058e89401e888e3d8222f635de2bcbc595bfcbb872403dfb24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}}, diff --git a/txscript/data/taproot-ref/6c8acc451d0c73e74ad6918585d0c8776498affd b/txscript/data/taproot-ref/6c8acc451d0c73e74ad6918585d0c8776498affd new file mode 100644 index 0000000000..f0fdd2575b --- /dev/null +++ b/txscript/data/taproot-ref/6c8acc451d0c73e74ad6918585d0c8776498affd @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c81010000006dbe9804bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6101000000606c4766027ae7c2000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487afaba04e", "prevouts": ["7ea54c0000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "8668780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "a37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2f8f33b00019c5a92b78a4d0765b6724114f5676deb8014962e3b41b4c6baea3fd3695492b964dfcc45d3a474d456ab4db8430bda5885b2eccf08499e11263dad2054b94cb6efba565738f5dbf6ee5a67458962b65d77e1cf5e0d2c1c00b2210"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e1bbd263bb9b57787cc1695f6735ee6aa4874511c0d77def079ec8f767826a474cae923b25d556389dd5dd645f6d7ddd89a07a74a73dddd3d85d7b65ae33798aa"]}}, diff --git a/txscript/data/taproot-ref/6ca4ca112dc6f3b82a4ee1dcb539f5412b61802e b/txscript/data/taproot-ref/6ca4ca112dc6f3b82a4ee1dcb539f5412b61802e new file mode 100644 index 0000000000..9582dd5207 --- /dev/null +++ b/txscript/data/taproot-ref/6ca4ca112dc6f3b82a4ee1dcb539f5412b61802e @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2f00000000f8ba7bed047a426f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac7a010000", "prevouts": ["0700720000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "777d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368847b894970b8ab4b6874deecd5eaf7148b7f894b2a434601f88998036d2a73ada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed76a514a469a046f8a639d1762af89c30ccdce4827317950871fa39f73bf898af03474d1f6825ec143575bd2e16c5d5a5b633189d07c1a3af4de94c30aa06021"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936449975fa8a41d909b43ff06fbaa008862a465221f52e8be68d48e129639049c7afeb4bd46271bdc4aa2a06eff134ee0adb3f92d28971d2f43ac771ecfb2750b1f03474d1f6825ec143575bd2e16c5d5a5b633189d07c1a3af4de94c30aa06021"]}}, diff --git a/txscript/data/taproot-ref/6ca7072324326a43f42b641dd4cc2d785bfbb7d6 b/txscript/data/taproot-ref/6ca7072324326a43f42b641dd4cc2d785bfbb7d6 new file mode 100644 index 0000000000..9dc4fd311a --- /dev/null +++ b/txscript/data/taproot-ref/6ca7072324326a43f42b641dd4cc2d785bfbb7d6 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfa0000000056f07197bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2e00000000e97e04addceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2e010000004e146fe30155a353000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6ed721a49", "prevouts": ["41e1250000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "b7c76800000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "603822000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "eb7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936627b63f045b77224e514acc1eb365b6e9afedea5819941d6cc405fd56980362633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a9e937f21fcad1bfe108fe60be9a324a720a35d98355df5fe53ca48d5593a6c6b"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e7d8de85c21b0b3fb0a3c0b5a47bf8fb76656439613f0da43488fdbdb40ca82a29e937f21fcad1bfe108fe60be9a324a720a35d98355df5fe53ca48d5593a6c6b"]}}, diff --git a/txscript/data/taproot-ref/6cbefe4b22649c02c818e52d3142c768ae99b9eb b/txscript/data/taproot-ref/6cbefe4b22649c02c818e52d3142c768ae99b9eb new file mode 100644 index 0000000000..b16cb276af --- /dev/null +++ b/txscript/data/taproot-ref/6cbefe4b22649c02c818e52d3142c768ae99b9eb @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b08000000005eac31d2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5f00000000e9c12dda030e24a300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487c5010000", "prevouts": ["bb4c220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5a55830000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_89", "final": true, "success": {"scriptSig": "", "witness": ["acc27a423aba2a823e9fe2d1bdc4b8059cf4b1619195bdec2e4b544b8646a7f2f3126c4b8994bbf829a1fbbd635b2761f52142e8de89328df43b0a0049119fce"]}, "failure": {"scriptSig": "", "witness": ["6be9a01f6cd066f5dd0d9ee1fb98474b62b1651e4f1c3df92e1fa8578cb38fa3add2b597c806f0d122128acf5f654be0d138beffee28bcf7ca4972046836a8ad89"]}}, diff --git a/txscript/data/taproot-ref/6cdb87bebca9057c621affd2eddfbe726630b1c6 b/txscript/data/taproot-ref/6cdb87bebca9057c621affd2eddfbe726630b1c6 new file mode 100644 index 0000000000..7dff22543a --- /dev/null +++ b/txscript/data/taproot-ref/6cdb87bebca9057c621affd2eddfbe726630b1c6 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf7010000007a32a641bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff50000000030c813b30337aecb00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7aa000000", "prevouts": ["f054530000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb", "d4857a000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "267d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed3613095503852f968cf254efcb9d0b7a7155094671c0665bdc16a67bf9a23af91e402d116972020cc4db8f7e1431e7a7416668817d422dd270400f40dd8d238"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361cf75455252e12219cb13ff880bc28451a916c621a385ef21679c99f872f6341f7219e5458c3fd087680f56af7e0cb5a098c29a419645486255ebba5b453a7aacd4c02f64c49cc162ff9325daec6263c98ea78a2c5346e44c6d55d79722c7edb"]}}, diff --git a/txscript/data/taproot-ref/6ceffd0098b1fadf6f95341e39b6b1486b6e2dab b/txscript/data/taproot-ref/6ceffd0098b1fadf6f95341e39b6b1486b6e2dab new file mode 100644 index 0000000000..074786edf4 --- /dev/null +++ b/txscript/data/taproot-ref/6ceffd0098b1fadf6f95341e39b6b1486b6e2dab @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43a01000000450efd63dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc600000000a8e0fb6603d47d8500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac08030000", "prevouts": ["3c3f35000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "79ec520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["bc4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08220e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e14a8563068286881d42b1c4901d93a483973910fd5653bf7ebbf040741f7cd837150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366e4bbdeda5d79348f03632b8a5af46cbe5e2e7d60e47397790df9d5358fbd9e8d5154a115ce154f943bf3cf8f46c74cde664956f57cd29b00bedec3f53c1a73157ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}}, diff --git a/txscript/data/taproot-ref/6d1ad01f9d4765e28554608aaaaf7f86d7fee48a b/txscript/data/taproot-ref/6d1ad01f9d4765e28554608aaaaf7f86d7fee48a new file mode 100644 index 0000000000..c5ff533a99 --- /dev/null +++ b/txscript/data/taproot-ref/6d1ad01f9d4765e28554608aaaaf7f86d7fee48a @@ -0,0 +1 @@ +{"tx": "de79ea5102dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1b0100000001706ee4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6e0000000064da1f9602df27bd000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d8020000", "prevouts": ["a8084d00000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85", "b2d1710000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "107d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936acc696796e153717ed5a6a385f9de8b7611279c250cec566122acf9b81ca854846c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada7506a3091a1e28dfc5b9aac4646748f840add9c91a317c4120c5f1dff96d2e4520b5ceb13d27db1b37ec8ee9ee9482aafd08fc62c5401b1fb7c7b4ff374c3d"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630300b02e92706ec4fd7f3b61fec60afc7cf4f75cde7fe0ccf1bedc3ed3184dadad4d220d15ec254ba214a445cc73922794d5f92559e27b8850a422e98de131f09630471a62c8657382c38b342878f0042beb3ba209e0ca1417f9db2e3d45f6dbd940ade039b405c8439b762bfbc73f9441ef227e6f687b6d94ebcbac32155c7"]}}, diff --git a/txscript/data/taproot-ref/6d2c53b612c9e3931c251808123e215918c34b60 b/txscript/data/taproot-ref/6d2c53b612c9e3931c251808123e215918c34b60 new file mode 100644 index 0000000000..14c876474a --- /dev/null +++ b/txscript/data/taproot-ref/6d2c53b612c9e3931c251808123e215918c34b60 @@ -0,0 +1 @@ +{"tx": "8d072cdd028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c408020000006c4d0c91dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be800000000b35dfbaf0267815900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6e14cf126", "prevouts": ["7b9236000000000022512085b1b5643880360a93ad399dd8d1aa945ccf0115d9a41dc926feca691d280be1", "8981250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_2e", "final": true, "success": {"scriptSig": "", "witness": ["f532f377f686cf38784a48d4b1af3f0c1b47e4764fd9c037519daa4fd3774a67d301e8315621eb9f1cd9883b764223700b5c6c9f5e4a95e152b2de2f4005e46d03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["d4cf78493dad4d8866c65df8e600155a4847578ac9c82896c6527a6d6ffcfc326dddabef9fa2466bda9cb0fc4c4951fc5a4795e872a7049530987652080206b92e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6d6cb592531f25b7c0a1a607342e2c3dcf35ac1f b/txscript/data/taproot-ref/6d6cb592531f25b7c0a1a607342e2c3dcf35ac1f new file mode 100644 index 0000000000..d5210518b0 --- /dev/null +++ b/txscript/data/taproot-ref/6d6cb592531f25b7c0a1a607342e2c3dcf35ac1f @@ -0,0 +1 @@ +{"tx": "035d7f1e018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c481000000004e33ec9a02352a320000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748754075456", "prevouts": ["470535000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "bd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8357b0da8b61d649cedb8c014d8a901c8639aee676049f740bf8079132edd04aed797dd6acf95c24b81e793c9c81b0ab80d381fe8deb935e4a90684c96acd4587"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365510f71f915f218e0cfe3f7c324e3aee59ad2c2f3157a77c6e7c2eb6b867ca43ad1c924a2744de25921620091a34db181a435ddb56a0dc8d3bb0ce452693f5f97353a90cd56d8edfa9d59a5341a6c829ef2ec5b70cfecd5055b0e6c18dd5375841cfbdca9cced9a9297ecbc29dffc929789a1848311039b5a24b338cddf0aa70"]}}, diff --git a/txscript/data/taproot-ref/6d776b8dcea06b627feb06e8e07e6455f48086d2 b/txscript/data/taproot-ref/6d776b8dcea06b627feb06e8e07e6455f48086d2 new file mode 100644 index 0000000000..2496cecc08 --- /dev/null +++ b/txscript/data/taproot-ref/6d776b8dcea06b627feb06e8e07e6455f48086d2 @@ -0,0 +1 @@ +{"tx": "2164258c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c801000000643e6ce4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1b010000002e5c44cd0201878c000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65633f05d", "prevouts": ["e17b11000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "ecc07d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_bb", "final": true, "success": {"scriptSig": "", "witness": ["b223293d4e5c89ee8e58073747bae998861fc142a465a072b4dbbe72be87b842d5706b47ad6c744b1d615a6e4d977b18f9a8e8084b0a22891475eaf6a44fbc0703"]}, "failure": {"scriptSig": "", "witness": ["05472656d9355b8e4e91a9f33d9d5b2ff57ab40f5629f1ace63fe30d46f9613bbf9b920597dd711bc1b8b615ce8f4c19d79f4b4e7c5e9282023b737468936f63bb"]}}, diff --git a/txscript/data/taproot-ref/6d807824d43b2e677fee210fcdda1e52cabbbbc5 b/txscript/data/taproot-ref/6d807824d43b2e677fee210fcdda1e52cabbbbc5 new file mode 100644 index 0000000000..ac5f832253 --- /dev/null +++ b/txscript/data/taproot-ref/6d807824d43b2e677fee210fcdda1e52cabbbbc5 @@ -0,0 +1 @@ +{"tx": "f66b5ce4038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c465000000005be9d6eedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc300000000394663ffdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c08020000000e1b4af6047d16af000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a62067231f", "prevouts": ["3e80410000000000225120783dfb3310d474c767ef9239befe26bff1665135289516e5417abb1737338f98", "172323000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "8d5d4c000000000017a9141757f4686f091b43a46fa47e92d07c87fc7a205e87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["fc4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900458771b6e792b25070418091d57f3336a76b43209d1f0f67eabea9d94d6d252d60aceb16be1ebf4fc69deaf064fc7bf5d7ff2149818b5ba4c28c799d30ad567cc959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a2d931e3ff2386eb1ce0fcf605e183edabdccf2d0088e28537def66ac2ff1ddb690da805934f4f93e9c0efd4d4edfea04743fe60c173721d1481257c7ee1801e4e0df2464f99a35d5bc9fbf69ae3045675e957332f77327dfd622124d00cb4df"]}}, diff --git a/txscript/data/taproot-ref/6d874714ddd3706018c9051c55abbcf1210b4643 b/txscript/data/taproot-ref/6d874714ddd3706018c9051c55abbcf1210b4643 new file mode 100644 index 0000000000..f5f4df5833 --- /dev/null +++ b/txscript/data/taproot-ref/6d874714ddd3706018c9051c55abbcf1210b4643 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f20100000037a88ef660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701a02000000b0c706bd0158741900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac4f8a5b2c", "prevouts": ["00a53b0000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "ac790e0000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_mis_3", "success": {"scriptSig": "", "witness": ["5ab8d870a6ff8eb16d81d15eb5b54c0f8833047e31fd03d61249b6002ded1c6e26f82cafb87703e0b309cfccff06b45a8d457a3ca8af72c6aa5ead5bff906019", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "5029eec7b1423a63e23d005879d82fb235f46a5d11005cd1b9809ce32666a3cd8f16083df6ab04d1f4f22bc8bc2a6be49238f1e17914f9ed5bc73052d59e54a463bebcc9f176dffbde06285b4bcff4ab025da5e25306f317c23259a59a6294af215beaa7b7e03c1b3d9e5dd0309c706d78ebcdfcce9bcd7708b6186dbf94069584fb0f0eddb37ec06b8337a79c2c18b703b2b6e1d36b1791181821475a68ec47f137298db6ef9101128cc42bbd3ed09b83cd5d46611d"]}, "failure": {"scriptSig": "", "witness": ["ee71a984c12de547232246ddd7eccd6d50c28419b99e7c3cb06c85418bae53d349c58a59d1e70382989d25fd9aa83cf05f0dc37330ff5c4a6ce0e9ba1f18c08b03", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50dd340beb9458b6ef"]}}, diff --git a/txscript/data/taproot-ref/6d9b8efdf33eb396820e03892263d3b784e5dcf5 b/txscript/data/taproot-ref/6d9b8efdf33eb396820e03892263d3b784e5dcf5 new file mode 100644 index 0000000000..2fb75a2412 --- /dev/null +++ b/txscript/data/taproot-ref/6d9b8efdf33eb396820e03892263d3b784e5dcf5 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708f010000007d6193fc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f6010000004a71e3b960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705c01000000093cd1cd02363e64000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87f047c423", "prevouts": ["df2c110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4a5e4300000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "818712000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09028fa34082c6b789795b8deb89ca5ed1b94eddc15c8ea94b56ef410571d37bff430fa8860257386bae16349634a008631000dd487604a66e5656c2c41b7955e2a086762f8906ec9265bc2713a062be9c7697e5af1532d38b1b6e01f767e6e96753fabf7bdac9e9fde9936ebce7f36e7ef1fd3029a307a75841e994b0f5ee710c2c7f0ae0eaff558933778923dba086f975a51eaa1042b24d36506104a4078f48bfed9d162891c0efa93568557022954e612e338db4e1a630557ed83e73c47e48d392fd13a97f8b490bc5901567cceea222543468cb8c76b0ca318255bcf3c7f060839bddcdb5b3aa3f3893be19978c82235b6c8ca7f1de746767f9910d8b1c1d2d659ab71ef4cd12c91168c35b0d8c90ff63bed28de375c13dc7ce0f1afb16827cd2ce91e5532a7bc624ae20289bfdc4ff980e7beed16f48aca1c25d83f9c39722b52de8884c4bacec4eb55e39a604beca0f0d474329855d86205059148b62d579b8380b486f03945040fca8bc09c77101bbe86f2ffe6f64c2e14ffbe6731eadf0e9db0229e0077e11684ddb7eb5e67498a3f960b39f3070ad3b836b8aa4e753cda98df48f327ce58125b8c3db4652c66123f4b1bdd47f13ce7427b4b9c9d9945c398a5a01e80f1aad4d1cab8971c56da6a75f7b82ff83843f14f38b9af68b1f38a1099f547b2375ce0012ee641b00431d669c42732e7e1010f17298d959dabf0c85c974c421751278307598", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5120e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1390e5640971602922d6b073671c4e08980ecd1f17d1da07e150f68606efdd1f96e2c0067d6235544c969c57bb6383bc4dfe8083fe3443e336f29d85bd1c9f087"]}, "failure": {"scriptSig": "", "witness": ["4d09020743d42a1c01f9d4b54773974aaffa2d1558c919ba6cdf39f5d17d1238d38b3112695b7b591710697c545a33a8f2b4807e2ec6b33a0bb35016364746ca079c008fc53d76a811fb03264da5f64ad4cc76a1422b8a6709b8cab05c279d38e66d7a66dffd6817214024a4bce70b5a73769dc8696c4adef71ccdcd6f9bcb4d371b62bf536ab973b153bb28daf0671675bd5541521833c3ea45b90220709d465d1fe68d95de672233958d176d0dcd4349906365434128537b559cf6269c85ecbc35e566b56a6fa101026ecd6d13a4f60972fe32673689bcfab9ed9e8bb86e419635d0afc50ee1ebea23280194d4ab2afd278e095c38175d2dd6725252f6b92bee7980719e6549df0e8494227f11c867356cc6295ac34b69810099e5b363b880f94ccdb5168660ddf2bce902efcaea5f0b5b3cd0e54cbbe879e33e6ff9d886c501e4fe73e2fffe674f6aaad26c7f04ab0ad7c11c31991ed3e785e85648ce5337cd7cd0f1d97f8c256689f24539f179281d7223e905b583e1c1d7c7b2fa4599a2a71035b634b4851e77042bb7b9b328f900d1b504755cc24696ac48ec93ddcebfd7a12088d3b05415db04abe45b37ef0a3b5315b3c9ddc3bcee0c845477867b7bcfc324fffcdec539ebe00a503e0f9122f7c9fd09fa0c580abe703f28a698d6779f5bbc0bc1493cf70adc1c534fbe55f8762e25552ae7c70b971754ae7763fa1d33a2636cc38033faf0c5a99b7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364da7e9c765d4069add7c566222dcc2fa8795999e4c66c2e0659e8e7b5c350f927bb22a9d6ce3a4416076bcdc0e15ff24e2eba93ece471e96a0af39f5a01dd3ec6e2c0067d6235544c969c57bb6383bc4dfe8083fe3443e336f29d85bd1c9f087"]}}, diff --git a/txscript/data/taproot-ref/6de00eee762e4ed839eb40fe1f0e25de0071e584 b/txscript/data/taproot-ref/6de00eee762e4ed839eb40fe1f0e25de0071e584 new file mode 100644 index 0000000000..fef46a4f34 --- /dev/null +++ b/txscript/data/taproot-ref/6de00eee762e4ed839eb40fe1f0e25de0071e584 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ee0000000050e3528e025ff735000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a63d010000", "prevouts": ["b7b7370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_15", "final": true, "success": {"scriptSig": "", "witness": ["1306a7911f8b30043267498bfba57f3bafde8a6ab4cef1af462e1d5dfb2794af72c44c02b05f4f99485705cfad4f2ee2ae8be777f80917f85e5ce590c0e303f002", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["aedf3d834fc929d88abfb96482de1f78f2f4450f25517ac2b0296ecaf2772138db486f2ea5e693b3bd3926a1e1018921c0980ed49c1394b332431448b2e4136115", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6e0058983c03e5e6a363e64deb28a252b20617c1 b/txscript/data/taproot-ref/6e0058983c03e5e6a363e64deb28a252b20617c1 new file mode 100644 index 0000000000..c54ff09ec9 --- /dev/null +++ b/txscript/data/taproot-ref/6e0058983c03e5e6a363e64deb28a252b20617c1 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127085000000006a1e55d2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd30100000063e1818f049b9e8f00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478706bd7426", "prevouts": ["4a4a0e0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "868a830000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb468405cb22a39b2e10cd1afb6cf33a44daad2098e05cd2010bbeaa225bcf768d84cef708a58e9a16c040ddf6ca6eff300c7bff2a5c928617bb01c850b0a79e89f728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b9d6e3f5d9915a7f17d348d09ea3f9ebd96660129a97625007e31c70764ffd301ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456a39aac74ee3f63949b9c215c515b0db1b113f4639b3fb19cd99ba22ff01310c728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}}, diff --git a/txscript/data/taproot-ref/6e20107c698b7f36b9163a7db7382e068caca218 b/txscript/data/taproot-ref/6e20107c698b7f36b9163a7db7382e068caca218 new file mode 100644 index 0000000000..1087b0f436 --- /dev/null +++ b/txscript/data/taproot-ref/6e20107c698b7f36b9163a7db7382e068caca218 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd101000000f3f4ecba01f6b73500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acec000000", "prevouts": ["7f71600000000000225120e17cb865e0c0755340e16ca2f2e2945dbce4ced3da83dcb29c6dddb7ec4631cd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aee516190bb66aca76b48f5e931006083b84d9812f39b791c31f97fb29b3271d"]}, "failure": {"scriptSig": "", "witness": ["6a22616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/6e41239fdb2bae4970f0a9787e683e94dcfb1760 b/txscript/data/taproot-ref/6e41239fdb2bae4970f0a9787e683e94dcfb1760 new file mode 100644 index 0000000000..76a7d10bb7 --- /dev/null +++ b/txscript/data/taproot-ref/6e41239fdb2bae4970f0a9787e683e94dcfb1760 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2401000000b40d39bf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c00100000020db294d014c696800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2e5e9e56", "prevouts": ["faea5c0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "118d330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_csv", "final": true, "success": {"scriptSig": "", "witness": ["8c3bf2f418eac8321ca5a10f3517be596df988d9e7a89dbdf658d38fb16eda1678109f53f9b36d5bac53e35b5d115ecaf5213cdac29f9c322e9dc2162360c839", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bdd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a37f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}, "failure": {"scriptSig": "", "witness": ["8c3bf2f418eac8321ca5a10f3517be596df988d9e7a89dbdf658d38fb16eda1678109f53f9b36d5bac53e35b5d115ecaf5213cdac29f9c322e9dc2162360c8", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bdd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a37f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}}, diff --git a/txscript/data/taproot-ref/6e59dc43f59b064311d89a689dd58f9a905d10e3 b/txscript/data/taproot-ref/6e59dc43f59b064311d89a689dd58f9a905d10e3 new file mode 100644 index 0000000000..2d18e2d0da --- /dev/null +++ b/txscript/data/taproot-ref/6e59dc43f59b064311d89a689dd58f9a905d10e3 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41e00000000689473618bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e500000000333fa0f201c56120000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d2000000", "prevouts": ["c2e73700000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1", "5e323600000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["dc4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c9da215fb1c7a7d8158d804bf09a7228ca7acab75bba3128cb1f7201ab6c755a6950266b78c1c1a06b0abf9d183417cba91a47bb46abdc469d8aa6f91cbf6a3fa39f866618102a4b08e1c83cadbbeb41bf3ed62f238c8432fccdf019ac45545bfaeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}, "failure": {"scriptSig": "", "witness": ["4c52dc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369df4b46da53b8939729e9a07a7e7594fd498eddc254844cb75d19f3809a7ad1b8f84e1cc8430872045fc695723e7e8ea88aa60745b893850b41017408051d8396d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}}, diff --git a/txscript/data/taproot-ref/6e85ec4ec7f9980d8de6d6892d1415072155eb5f b/txscript/data/taproot-ref/6e85ec4ec7f9980d8de6d6892d1415072155eb5f new file mode 100644 index 0000000000..1d756f0a7e --- /dev/null +++ b/txscript/data/taproot-ref/6e85ec4ec7f9980d8de6d6892d1415072155eb5f @@ -0,0 +1 @@ +{"tx": "af047eec0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708d0100000035cba8a8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0500000000056a088502900d7b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca77d2341", "prevouts": ["67e6110000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "63c76b00000000002354212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "6b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8a2960a95becb1bbbe0636e0493c58f712af9b8da417013d797bf12c130ac56070886d9e3726a9aa8a2b94454683b5181a970edd894e0d0cd75aad09f75436b2"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e85c9148ab8fb2f0e3b60c30486bc2998c5a9fcff153a4260746061263c245b36a70886d9e3726a9aa8a2b94454683b5181a970edd894e0d0cd75aad09f75436b2"]}}, diff --git a/txscript/data/taproot-ref/6e99af85369d8643f1c91d6e46c038af402d368c b/txscript/data/taproot-ref/6e99af85369d8643f1c91d6e46c038af402d368c new file mode 100644 index 0000000000..6cc08b300e --- /dev/null +++ b/txscript/data/taproot-ref/6e99af85369d8643f1c91d6e46c038af402d368c @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcb01000000cbb48829046916610000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a688000000", "prevouts": ["24016400000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "737d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facefa89993a6c83e98df45cdbdc82d28bd33af2548fc79063bffdaaeafd2a52fabe4f7cbc7087a9eecd21f8f9de83a71ce09520dfa28ecbf12e6edbc22e0d0c39a8cadcf9bcd23f9249fd09eb8b2b9ca63044a0ccef58f4cae9402f6ead4c2071"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93613adde228e33b56d36b730183a3076a84484135166bc954854de5c480ca0e58dcefa89993a6c83e98df45cdbdc82d28bd33af2548fc79063bffdaaeafd2a52fabe4f7cbc7087a9eecd21f8f9de83a71ce09520dfa28ecbf12e6edbc22e0d0c39a8cadcf9bcd23f9249fd09eb8b2b9ca63044a0ccef58f4cae9402f6ead4c2071"]}}, diff --git a/txscript/data/taproot-ref/6eb985be69c6686dbcfaa0cfeba04cbc68dd5298 b/txscript/data/taproot-ref/6eb985be69c6686dbcfaa0cfeba04cbc68dd5298 new file mode 100644 index 0000000000..4cc11b36ff --- /dev/null +++ b/txscript/data/taproot-ref/6eb985be69c6686dbcfaa0cfeba04cbc68dd5298 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270780100000092a442168bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40500000000ac1f958adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2b000000009c4898ea02e6d16d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875a481120", "prevouts": ["2b3f120000000000225120c10f9a5287d6d37684b1ac107332d66417d952fdf60fb9cd3e9fa5de48c339b4", "fcef35000000000022512070bce5a25570b494d89a85af7ba09d895150a56587b7f7acec0c02ca42514b39", "91f927000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363e1f8250be4afe1bc8d4d0a31bd3742c51e208f85fe088e4f07f552051790fdb"]}, "failure": {"scriptSig": "", "witness": ["6aa9616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/6f3e92cd7c0bd1c759a5d1ec589fa593028c2f27 b/txscript/data/taproot-ref/6f3e92cd7c0bd1c759a5d1ec589fa593028c2f27 new file mode 100644 index 0000000000..dac3ca09f8 --- /dev/null +++ b/txscript/data/taproot-ref/6f3e92cd7c0bd1c759a5d1ec589fa593028c2f27 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7c000000006ccee4d5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf550100000006f9c30c016ca90a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1b9c1b47", "prevouts": ["66cc700000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9fee7e0000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "da7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a47bed56458bb8201cfe785d9ebbccb6afef9cc99128ad29d757c102b7b9c0a9eb0481d56926b359fa3e2e34471adba51fafc61fa70dea7541795bc082db9408"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366a029025d4987be8973c8fee4cbbf96b701afaf5d6753deff2d6dff0516fae4ce4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a47bed56458bb8201cfe785d9ebbccb6afef9cc99128ad29d757c102b7b9c0a9eb0481d56926b359fa3e2e34471adba51fafc61fa70dea7541795bc082db9408"]}}, diff --git a/txscript/data/taproot-ref/6f52449eba2cea1fa19799e7de8f931e69c70cdb b/txscript/data/taproot-ref/6f52449eba2cea1fa19799e7de8f931e69c70cdb new file mode 100644 index 0000000000..b95be97e27 --- /dev/null +++ b/txscript/data/taproot-ref/6f52449eba2cea1fa19799e7de8f931e69c70cdb @@ -0,0 +1 @@ +{"tx": "1f1a48c703dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9b00000000fdf160f9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c03010000009968b6f760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270150000000060f62d8a013c37600000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc85000000", "prevouts": ["5a1a200000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "f39b5b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b0fe12000000000017a914b0b53ba433a336ced94ed75e23248458a1c69fab87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/emptywit", "final": true, "success": {"scriptSig": "", "witness": ["0c52ef46377fa809dbac5ed322d299d79134955de3618b10201d5faebce378c813ff45e1cdb421317e190245c5ea70d3fd0fff89e028c062d128760bd4134490", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}, "failure": {"scriptSig": "", "witness": []}}, diff --git a/txscript/data/taproot-ref/6f56fca6cc1c01fee921e3ebec30d918b7e84af1 b/txscript/data/taproot-ref/6f56fca6cc1c01fee921e3ebec30d918b7e84af1 new file mode 100644 index 0000000000..1c6651a76d --- /dev/null +++ b/txscript/data/taproot-ref/6f56fca6cc1c01fee921e3ebec30d918b7e84af1 @@ -0,0 +1 @@ +{"tx": "392083b603dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf8010000000320c5cf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704701000000934072f4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8200000000df73f6d504ec96cd0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac1b08b24d", "prevouts": ["47805900000000002251204e3fb1c88f2893b13c1c33c3a0d0cd819c49ecb88ca3deab379ce318a8955811", "1ca9100000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "e5a5650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ac7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa30268d77a27dfffd2973b5655548cd241058e748ff39c1f9c0ebcc25f2590463fc485b911b91245b46c320351c8e1d13bb30ee22c3f953d2224593bd4b5088ca"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bef2dd3e84f04fd56d20bf9e4a65c47b7f88dfb77d0f893796cf86007758622a30268d77a27dfffd2973b5655548cd241058e748ff39c1f9c0ebcc25f2590463fc485b911b91245b46c320351c8e1d13bb30ee22c3f953d2224593bd4b5088ca"]}}, diff --git a/txscript/data/taproot-ref/6f6d754696a56d367c058bd6cef710ac92a36c4d b/txscript/data/taproot-ref/6f6d754696a56d367c058bd6cef710ac92a36c4d new file mode 100644 index 0000000000..06b66bf342 --- /dev/null +++ b/txscript/data/taproot-ref/6f6d754696a56d367c058bd6cef710ac92a36c4d @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704200000000ec50a7c302a98c1000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787bf020000", "prevouts": ["043e120000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d98400ecd38521c785b85d37fe584d5d3682edaaae69d132e432540ebea68ba98c233b01e9e4730468573eec45eca5240787c123c03c41e786660d09325d057b4693d177569b8d5579a02ab5e075cd178f2a42353c5d571f41250e8a97a85151d0d9c83f966fbfff1e9f396160c66ba7b103d9245ac4e650ba070672b1a1c9b323060322fd5866b88016a7795daaffc3b634631ae76dca8ca14360f9d880d7c3174e4cc5cdea7118af9c25b7083ede26cb71fd8cbabb2a85b68ff2144b480342ecce0f18506a2ed93df165583b9702e9e55c40127db06cdaeebcb16fd49a39dd7688f57f7ec0331ece16655e5cfa452cc5a34e2d99d9acd6aa82b2930cd7c51d8ec8c08c969f35dded2ac5211a07651b1490eca967d0969098662fa62c23faaf7f37560bf1cea161076a69d3ae4f2b50278b5b0671f70a6a7a9f972c768516cab7672be25d8ccaac83d74a410248bb26ae387a9395dda350458e7a1d7aba28007ee2f135f66cef318ca1e84fdabef5dfcbd5c84bd05611d8fbfe43240fc3302e87fb4c62bdfc28fc865b26a09d0a3fe4e160bc71c2ee831e2847ab48330f0dffee804ba74cfc144497a6330119f6f1b52ca2e002b832db99031c384eee4af001ca76171d2684187f381780bf8fbe3949c3e2d087f0875907283ff5ac0e7131009fcf340caff5cdead5d660c6f55336fef40515e6e7a32fc232408392ee1a70b25dbb4e3ac620ab06ae75", "1f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6fb037ff446ebf56375516806af4ae7659446d7a3fc7277956df288e29adb4cec0d930d2ad3e784600f5ffd1efb1e58c37063febb6da2a9c1576d111e3c4564ed661e9ebd30f651fa020177c2a1e4ce51b505c9194e43d6074b392863f250ba"]}, "failure": {"scriptSig": "", "witness": ["4d0902d023ed8c46eb022249818b381c17252e7b245aea99a2445ad1eb80a93f572ca3611d97071118248afb797fc7946a532c9561d197e8accd84a36d0f8b30767946626bcbdb7440048493c2b2a958ab755577dbb3bb4615e4403d69d13cb5f1f7c851610ece3d8d1e6ff42a08b7a8d74370c1a666a38cd53ca8d31a71cb0216780a4239f6c9ac15f28cc3f16e01e9b786e9ea531b1ac3d301b98231c7862a6564c36fabc82759c25fcf6f0f04cfdfe19010f64689dd60f0088e4b303a8241263ca08c1aa15ea99f2dfeba6afbcde92cd883288a1e7e1383c31f1e955ff4a64b0ad12bb4605f631d0a3bce1d806b84832135d2c267d1556b4737ca21aca1c9c2e93fb6b0d8642f5990ec7f758d7b99c99f1818a49063ee4eb79c09c958a39b6b37a22390ebe395d73ba3105ba1b0c95a7a31aa59a4232e09eb300941668f2a9bd24d48a3d3d1d08ac8f96942a2614e9ee108887abbcd92d2240c18dc863eaa48ad88726ce2b53f897e62c2eb76b62dc90ab22bae5b9cc87a1611ea5dac0118e4ac950b6b95d5d466f58e9b7131fc2058e078143825c2f5ee21d28c14d961c9731105f2123fc3626aabdba6b41aa330e0ed44860f8faf1bf7259f38fbaf97e630edfb8ae6d0367ddb03a735b1647088a4557b04eb406df846f7d6e2cb9b10c38a9e1e8fe4727612f1c56a0230507d879287ca1c00594f0cc3ea649a3e726a0d0ba3240482938d8a042fef4875", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d3a1ffabbe96d474dd83c1fffece889ca7c1560b62811bbde312ff5c73e7fdd346c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facfc86bca0a8859889d9efd3fba9c68487fa49a78b15c293938d32f430a3e576ab3e02c0e1665e1d6a4b6ef98a6ef3a3632c98688db315e4c8eb8907479035d72"]}}, diff --git a/txscript/data/taproot-ref/6f7390dad86b309a8464acc781b7a22cdc6164de b/txscript/data/taproot-ref/6f7390dad86b309a8464acc781b7a22cdc6164de new file mode 100644 index 0000000000..4f1407d77b --- /dev/null +++ b/txscript/data/taproot-ref/6f7390dad86b309a8464acc781b7a22cdc6164de @@ -0,0 +1 @@ +{"tx": "044da27e03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdc000000001a07b0b4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9501000000bff781dddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bee00000000ac3a7bb4026db9df0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67e030000", "prevouts": ["ca4f73000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "2fbf4b00000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "e43e22000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ce", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900455067193501824fc7e1f7f904c1e32fba78339d7701e72316b16feebc15a414abab692e734634bfaf43d653c1e6f6d8e8d14797d8e4fda7a04cf5eec270202b46d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367d1fd0be73b6182e4cd51ed7a2b120ef2cd5ccabb8492e6bf7f26137f064f14b8def8465bc2f3cbc3837b9c231547f51d7c9e247c478e05a849822285048dd5e0ea67bdb3398814286540937ec364df004af879f987225ad05d036a51e8223e6d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}}, diff --git a/txscript/data/taproot-ref/6f775290762b949c8416b8db72a80fd4f625aeeb b/txscript/data/taproot-ref/6f775290762b949c8416b8db72a80fd4f625aeeb new file mode 100644 index 0000000000..20a1329617 --- /dev/null +++ b/txscript/data/taproot-ref/6f775290762b949c8416b8db72a80fd4f625aeeb @@ -0,0 +1 @@ +{"tx": "6640765702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5f0100000029d0c5b9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1e020000000a5e90fd0143ee2a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7ea02a33c", "prevouts": ["6120210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0999250000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_db", "final": true, "success": {"scriptSig": "", "witness": ["6d195f0a72ee656832bd23e0ae205f238cfdbaf9dc0614c8317838871fff6566db7a60c05ef9c6409974711884c70a3201e9559490602f40f10880b4bcfbcca4"]}, "failure": {"scriptSig": "", "witness": ["589d3f38c3ef00f94500624751906d8829d0715f1f4ef2ee87449ee48dcf6532d23b5a18e46f25ce0ba7923f2f58bec1783972ef424ebbbd8f5b24419d82837bdb"]}}, diff --git a/txscript/data/taproot-ref/6f8393bbb9d02857705efc61028b43ee819ae6ef b/txscript/data/taproot-ref/6f8393bbb9d02857705efc61028b43ee819ae6ef new file mode 100644 index 0000000000..b6b1647018 --- /dev/null +++ b/txscript/data/taproot-ref/6f8393bbb9d02857705efc61028b43ee819ae6ef @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1402000000d73d2e948bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4200200000097ebd4f30302dd930000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ad30a625", "prevouts": ["a81f570000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "e9523f000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa552be7238817b807c577e7c571d318055dfcbd95cc3dec1b5752f3912212e63f5a7735bc8e0f27305ca0f6b127eb0c71998afa21cfa1408dfc03edc17ac2e42ff4035580f6aad3e4d48161cfa55cd77c0146622bf63e71def681bc3cbf8a6f"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f01d0d256ad0d229e53661481dce388404558ec2529e0bc1d85e0261a585159aa9fad2668c863ea9bd6dd9197c1c49c61c2b9d7888bac8bf6fef03fc3ace0a5a"]}}, diff --git a/txscript/data/taproot-ref/6f8e2a9cd5725921d637323d42b65faaa53b2d0c b/txscript/data/taproot-ref/6f8e2a9cd5725921d637323d42b65faaa53b2d0c new file mode 100644 index 0000000000..f1a46cb1fa --- /dev/null +++ b/txscript/data/taproot-ref/6f8e2a9cd5725921d637323d42b65faaa53b2d0c @@ -0,0 +1 @@ +{"tx": "ebb0671102dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b780000000086a4f4c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfb01000000f9046ad00132320800000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac41935239", "prevouts": ["9e3b2000000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "fe3c270000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "fd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0822c6cefb1e181eefac563b15a866f5ecfc3c81e54821b9e81f79abce745f7d95962d72dd1cd8804fbc0be1dcf6a22214dbfb5210e6cde6f2a41edfb954edd50fb"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93647aa351277e8bbf9be587a60760fe90499ff4f7bade942ae6e0cdc6741c21b4ae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e850656d0bdb94b88d381f7a82b87984f770e250bf999894456706d2524183d15d62d72dd1cd8804fbc0be1dcf6a22214dbfb5210e6cde6f2a41edfb954edd50fb"]}}, diff --git a/txscript/data/taproot-ref/6f9c6ccc8504bc417cff64152e5d55f2da6384f6 b/txscript/data/taproot-ref/6f9c6ccc8504bc417cff64152e5d55f2da6384f6 new file mode 100644 index 0000000000..f89407ffc3 --- /dev/null +++ b/txscript/data/taproot-ref/6f9c6ccc8504bc417cff64152e5d55f2da6384f6 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4300100000062fdfcd68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45900000000e93273c30153505600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac25000000", "prevouts": ["c047320000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "3e083400000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "48304502210096d384e390bffcffba0c22773ea4cb94ad5cab4501ae286afc4b73f51eb354ea02200f921c9edff46d1c10ed000b87e42175a53e6ad34153078f00d7117a181080aa38", "witness": []}, "failure": {"scriptSig": "483045022100b176add6f5dd593f76f827e87edaee5dfc9e13ad73b04082ad5f05123f21ecab02207f271738f4c4fe0575dee0967548844f3ff5cc2cb1da627d8637a4f64cf4f60f38", "witness": []}}, diff --git a/txscript/data/taproot-ref/6fae620fa980b4c2193b8d1ca489fecb771da643 b/txscript/data/taproot-ref/6fae620fa980b4c2193b8d1ca489fecb771da643 new file mode 100644 index 0000000000..0949ec2ac1 --- /dev/null +++ b/txscript/data/taproot-ref/6fae620fa980b4c2193b8d1ca489fecb771da643 @@ -0,0 +1 @@ +{"tx": "71b5e2d803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba401000000be38a9c2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9b010000003949d5b6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba2010000007c0e80f601ed1c22000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787e6a4735d", "prevouts": ["4a3f2100000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "f873240000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "4005270000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f84c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bb84f5f1451210ceb72432b3e6d63235af9ffb877329c35283c8b2d18797507891e44dcd1430a53a9228b1d4df01e5c5d5af3846f876ba8dd78ee7e669e7153a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93616b2433637002a6288e5b498008a36f83adc9a4b9c08229b0f65a7712aba099bd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5129caa746058fefa69912501c9b6f792a531f2cb30638f1f343d3625f0a93b066f288028cdab461d62f9273620b97315e6e9af9458f777a616c1bade2d3f6a89e"]}}, diff --git a/txscript/data/taproot-ref/6fd7c011c1e087678c2fc502f6049d5a1610b285 b/txscript/data/taproot-ref/6fd7c011c1e087678c2fc502f6049d5a1610b285 new file mode 100644 index 0000000000..ed7bb551d6 --- /dev/null +++ b/txscript/data/taproot-ref/6fd7c011c1e087678c2fc502f6049d5a1610b285 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb30000000093a746acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cec010000007ed5e8d5021f6fb300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd239a551", "prevouts": ["0e86640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "519f5000000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "e47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e13278694ce96e600b1b1379af0dda4dcee22bd0822513808885cb6e68b7803daccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457ea7c8dd4a05a6083e4a7ce3fc20cde94d430ec03cbfbe8017e9dc8ef3bce99a9"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820d58db0463b9d01080baa2617114f2c0459e5723b09a0137090d28117705b675ea7c8dd4a05a6083e4a7ce3fc20cde94d430ec03cbfbe8017e9dc8ef3bce99a9"]}}, diff --git a/txscript/data/taproot-ref/6fda74aa278e18be569d89d76d2b7d189719fc9b b/txscript/data/taproot-ref/6fda74aa278e18be569d89d76d2b7d189719fc9b new file mode 100644 index 0000000000..e156647fe3 --- /dev/null +++ b/txscript/data/taproot-ref/6fda74aa278e18be569d89d76d2b7d189719fc9b @@ -0,0 +1 @@ +{"tx": "564957d90260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702a000000004dcc25e160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b100000000af182efc0194a10e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac93b72d3e", "prevouts": ["5f160f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cdd10e00000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ea", "final": true, "success": {"scriptSig": "", "witness": ["4bd561d66e58c68fe761237a83f4cc3e98086d7177b59215ff63bfb32c4d4970c60acbff8553353aff690d1f8d399eac4ec267201dfe585f84457b46abccec3181", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ac361121751eecd7ef5f546cb4d4ffa6a292e05f81086ef168557f1098cb7430017430a92e6ce30a54411b3b7baaf44da203655aded95efafb52ca8d4f8a5a92ea", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/6fe4cc6bb00f0db22fe4cf7e68170752bf9e1f7d b/txscript/data/taproot-ref/6fe4cc6bb00f0db22fe4cf7e68170752bf9e1f7d new file mode 100644 index 0000000000..83fe5ed885 --- /dev/null +++ b/txscript/data/taproot-ref/6fe4cc6bb00f0db22fe4cf7e68170752bf9e1f7d @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9301000000b42ed6a28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d90000000081fe60ac049d5a9100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac47d04324", "prevouts": ["749a5a000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e", "d2c139000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "347d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faa00efe7e15c1e643e9e1cfaff50670e7cac10128754f4af7dc416953d80cca2b070c3fd2cc03cfe72ec91581f9e22200fa4c4f6deb8dafcd335310e90efb11e5"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366956433f4fb745717b89f2dabf7821b404dd73db8a334af9b6b63fb319135fc93ac03c85a7bde4aa83325c4e9fa3803d6178be55885bf5b72d341e036ded0599070c3fd2cc03cfe72ec91581f9e22200fa4c4f6deb8dafcd335310e90efb11e5"]}}, diff --git a/txscript/data/taproot-ref/6ff3146da9ac0acb6f0c208976dc39290b684b16 b/txscript/data/taproot-ref/6ff3146da9ac0acb6f0c208976dc39290b684b16 new file mode 100644 index 0000000000..459e15670d --- /dev/null +++ b/txscript/data/taproot-ref/6ff3146da9ac0acb6f0c208976dc39290b684b16 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c910000000057056869dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c47010000003cf378558bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44d010000006ea78b090428b4f3000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac70000000", "prevouts": ["9f7a60000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "8619550000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "478f400000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e068", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93628082d35abe6ef83905e008989e1064363253e92a96e384c0e19752d72666028d81cfe71594e1389c7dbef12605d87c33af6e429193e755ec800f4a6d58e14260941252319b1d0989c3ca3905f2d65278f17fb3ebe6fd71301329f8e450b42a05a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a353eb258bfe69706fad87149f0062bbeb66245797a793aa1397e15fb4e048a6b8fb8a6613bd9c6482328b74d7fce63938f8fb7ab14fbe335c660b528e72f6791d26af6ddceab3892536958f1ea20dd7b885ab499207106c7decaa6511a0e4c5a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}}, diff --git a/txscript/data/taproot-ref/6ffb4a945d04f8b031049d6b6fa49f15f19568e5 b/txscript/data/taproot-ref/6ffb4a945d04f8b031049d6b6fa49f15f19568e5 new file mode 100644 index 0000000000..97b6a255f1 --- /dev/null +++ b/txscript/data/taproot-ref/6ffb4a945d04f8b031049d6b6fa49f15f19568e5 @@ -0,0 +1 @@ +{"tx": "ce6d8fb40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707b01000000a82eaabe60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702600000000318dc6de03fb901d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e7b3b94c", "prevouts": ["945c0f00000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "65c510000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["ce4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb2c5514a992c22e53e3a04f6b085a9b65917ab3f28cc532348e66ade0afda2c959bd9b34bb85690c892593228383c48f2c7a3855b4947a3dd1708d13c567655d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d65a5d3ec5f807343f2d36728ab3e78b89e6b3a032f7e993a165c380ec55ed8fd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5125e7936dacf44c2cc5542287b329619dfaa06ef235a847d66c9c2df863225da6d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}}, diff --git a/txscript/data/taproot-ref/70103c6bfa6033fc750d73a791d50375a1b86fea b/txscript/data/taproot-ref/70103c6bfa6033fc750d73a791d50375a1b86fea new file mode 100644 index 0000000000..ab95a1b2e4 --- /dev/null +++ b/txscript/data/taproot-ref/70103c6bfa6033fc750d73a791d50375a1b86fea @@ -0,0 +1 @@ +{"tx": "23ccb2ba038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d2000000000276dbdddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc201000000bff559ce8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49b010000003499f1aa02d96dc3000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac8a010000", "prevouts": ["334c420000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b5fe4b00000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "3fdb36000000000017a914aa4a4e70b11f4eec4760f77206dc93b02350fcff87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a9", "final": true, "success": {"scriptSig": "", "witness": ["cf68cfacc0717997e89d00fe409492469bd7456be2fc7cfebb9c7ed437f9f9aa61feec882601b4f1eb93a70437592989b0186ea2a24bdd82882f6bcb2f99267382"]}, "failure": {"scriptSig": "", "witness": ["28a307c3bf4658b932c6b9e8c636463b608b420f93e72cd6fa25b9206ef847ea6baed922ac2d3299c636619e2657554f56c28eb4e789c4560ce0e38db5db8444a9"]}}, diff --git a/txscript/data/taproot-ref/70294d4a0a0438dea998f982369933dacc66aacd b/txscript/data/taproot-ref/70294d4a0a0438dea998f982369933dacc66aacd new file mode 100644 index 0000000000..3ddb130aef --- /dev/null +++ b/txscript/data/taproot-ref/70294d4a0a0438dea998f982369933dacc66aacd @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709e01000000b32c5df604b4520d000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac61030000", "prevouts": ["c4080f0000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063bf68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93619d862adf527dcbd6251afda613bb700de56c3c64ed29851c444942e2faf911420e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e10ad4e0ac96c164f1885f81b1e139f05879070681278f68106e4fa54c23a8038d82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab6cf39500705731d4b2d9ebe0ca35e7ccc55c3e2e84eceb274b16f05174389b911e2ebc11e8ff6aef3c08be5d8086fd4b944e3e1f7063038c1b6dadb4d48ab0219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}}, diff --git a/txscript/data/taproot-ref/708f0996354e7df20b2aef4b10bc9586dcaa5db0 b/txscript/data/taproot-ref/708f0996354e7df20b2aef4b10bc9586dcaa5db0 new file mode 100644 index 0000000000..55230d8920 --- /dev/null +++ b/txscript/data/taproot-ref/708f0996354e7df20b2aef4b10bc9586dcaa5db0 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42300000000b20b5953dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4baf0100000081d35f7204231e5800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fced000000", "prevouts": ["db4e380000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "31d2210000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["df4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936be89d319d8869e9bf9ae746cc5e400e37fd9a102b3c132ccd07930db67bce60a51d880cc047c10a424f65fe9dd9096492f3efd8e08517d04362957faed36c3f852ff338358c59a252efd0a17af70f1cdfe194eb24c5d50483b26343bf89011bf"]}, "failure": {"scriptSig": "", "witness": ["4c52df", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369421f0c813f1c39cbe21c39d454fdad8d39c88e7d0478d0b244f0694cec3217cd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5115b534b99635107bf366447ce9661d5eae557250694ef66e76c31b44d1abe134360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}}, diff --git a/txscript/data/taproot-ref/70c7802de56e11939701cba269f74c5c54434e61 b/txscript/data/taproot-ref/70c7802de56e11939701cba269f74c5c54434e61 new file mode 100644 index 0000000000..a76b046575 --- /dev/null +++ b/txscript/data/taproot-ref/70c7802de56e11939701cba269f74c5c54434e61 @@ -0,0 +1 @@ +{"tx": "5bee4af203bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2200000000c005eba660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ed0100000060fdda93bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf65010000000bf347b903f07aea000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689872898922a", "prevouts": ["c7c87a0000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "d53a0f00000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "1e11630000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6aec", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514ff463d85551b82eff8f4009a79f35c7c71a55ad97e02e5d54d505fc944ebf2db68406090ec9503da6e41d61411400226504a16a75c985e068fea4ead469507b3b719bf4b6df334f4ad3966afd516fb2a8d294cb4fface4e4609ab1c9f988c5a"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369eeb256fe03de844f7630ee1f9d4f8bd53f7cfbd5ea69e2aa5922cbf41317df14ff463d85551b82eff8f4009a79f35c7c71a55ad97e02e5d54d505fc944ebf2db68406090ec9503da6e41d61411400226504a16a75c985e068fea4ead469507b3b719bf4b6df334f4ad3966afd516fb2a8d294cb4fface4e4609ab1c9f988c5a"]}}, diff --git a/txscript/data/taproot-ref/70cd3f4760a280eac2806e6373034a5e750cb013 b/txscript/data/taproot-ref/70cd3f4760a280eac2806e6373034a5e750cb013 new file mode 100644 index 0000000000..bd14e3346b --- /dev/null +++ b/txscript/data/taproot-ref/70cd3f4760a280eac2806e6373034a5e750cb013 @@ -0,0 +1 @@ +{"tx": "9cb7d226028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e800000000505ce1bc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43601000000043fdc9a0412077300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689879f020000", "prevouts": ["728d4000000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85", "e467340000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "9a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e874224dbe9932044562df2f9dbf2ed3a87afba7bd9cf6855f9f40e4c24add8036ef17902325999cb16876d9e124f321b7a2400c6233e0b61b95917979ea167214"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362dd94ab6ac3ba59fc544244dcd9eb18ac121794a237f6dbebbd82fbb662320abda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e75ccfc706e32ae7f6b2a63f59d728082bfb2443bbee0d6dae87ff94b5ceebef57e56d08eecb8b548a03ce82dd22dc92a64f1be159e88ba8944ed4666490b777c"]}}, diff --git a/txscript/data/taproot-ref/70e123fe2099ae69883a84234ee7d2c67ffae902 b/txscript/data/taproot-ref/70e123fe2099ae69883a84234ee7d2c67ffae902 new file mode 100644 index 0000000000..ecb83e3c60 --- /dev/null +++ b/txscript/data/taproot-ref/70e123fe2099ae69883a84234ee7d2c67ffae902 @@ -0,0 +1 @@ +{"tx": "8dbcaa8f0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704e000000001f96ee99bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb900000000f13ab3910248cb8c00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac4f13664b", "prevouts": ["cc920f00000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "1dc97f0000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a7f", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d1e2e06d6ff5c459c120ed1951ff2f8353cc05da31129bd66db4aa2f495d014ff8d5397512e216c7ab52609f0ab27ccbbfd2b7e561d7599ada55e292956af911ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93657c0032d4e48b70562ff2a9a0f5ac730dd2177fd5d330b71920c0f4217bb1e47d82f8c55e99af1bc6044802eb870171f459184b3c99e354e12eac4f204be9c37cf5fd42f9969f7f2472ed1fa62ffa49909a09466cf06ef7c57cb1be351156c54"]}}, diff --git a/txscript/data/taproot-ref/70f98e7683065de833f78e968b12a17560c6d145 b/txscript/data/taproot-ref/70f98e7683065de833f78e968b12a17560c6d145 new file mode 100644 index 0000000000..cda9e56c7c --- /dev/null +++ b/txscript/data/taproot-ref/70f98e7683065de833f78e968b12a17560c6d145 @@ -0,0 +1 @@ +{"tx": "69e9ad9d02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6600000000c9d7deda60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f001000000c805afc401196533000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f871b91163a", "prevouts": ["17806000000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "eed7110000000000225120934cc30b71223b04aa2af20106e445bb93ef4a67adba137dbea8fd26e6a0b3fd"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364f585542b894e5830b48f56f4cc72472e37b8c308eeed1b26541f7876cad2bcd"]}, "failure": {"scriptSig": "", "witness": ["6a6c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/7125c24e3079aa7ecd8a075096657aa41cbf32aa b/txscript/data/taproot-ref/7125c24e3079aa7ecd8a075096657aa41cbf32aa new file mode 100644 index 0000000000..97b926ffcc --- /dev/null +++ b/txscript/data/taproot-ref/7125c24e3079aa7ecd8a075096657aa41cbf32aa @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf55000000004245bcb4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b17000000009c83f3e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3a01000000932991810400c0e700000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac6fe3af24", "prevouts": ["3f1c6e00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67", "ceaf1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "75615d00000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f1", "final": true, "success": {"scriptSig": "", "witness": ["2c48c1f997828ff35b795585beb51556a9e7da80571b3b9d00a7ad3fbab2c4bd1b73f08720100c7885c7fced95be4f4025449564a0380c71699a694a110da3dd81"]}, "failure": {"scriptSig": "", "witness": ["440bb0fbb382877d0b30eaf1ce461ea54c7d31459e74d0acd0eda91c41409ff3b3fad5b95b5c624aa71c744c931c5532c29b16bb56d9627c8adb3f2cfd0323cdf1"]}}, diff --git a/txscript/data/taproot-ref/712c593d655c49212ff38704eff4d5d68d14506d b/txscript/data/taproot-ref/712c593d655c49212ff38704eff4d5d68d14506d new file mode 100644 index 0000000000..b9158cc2e9 --- /dev/null +++ b/txscript/data/taproot-ref/712c593d655c49212ff38704eff4d5d68d14506d @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4460000000086c6650edceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc500000000f5bf2afe03cdd85f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac3de12d2f", "prevouts": ["c9003a000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "c668270000000000165f142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["71eefcdb8d2379aa4114d1652ff5b26ff9e9837a357afe394faff811594b984a68cfccc007366d1849ce7ea39f0378e7103d955f117853687334736851d75c37"]}}, diff --git a/txscript/data/taproot-ref/713565a78c4f0eefe92a042e831427511dd4f5b9 b/txscript/data/taproot-ref/713565a78c4f0eefe92a042e831427511dd4f5b9 new file mode 100644 index 0000000000..de4957cc6c --- /dev/null +++ b/txscript/data/taproot-ref/713565a78c4f0eefe92a042e831427511dd4f5b9 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c09010000008fbe4ad0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7f01000000637407e402af757c000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6af040000", "prevouts": ["41885b0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "e76b2300000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["81", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824d4a172c841d8bdf967229e1606322d36b03ac644f3c557c1b9d417f1b2a2a789823c6bcc0c06b1ccedd8f3302fb965778bf11fdbd4830d29cbc62f32a77240ccdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362abad23705572fa5091822077faf7723b4aee0fe16a98731801378aa56415cd84d4a172c841d8bdf967229e1606322d36b03ac644f3c557c1b9d417f1b2a2a789823c6bcc0c06b1ccedd8f3302fb965778bf11fdbd4830d29cbc62f32a77240ccdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}}, diff --git a/txscript/data/taproot-ref/715cf3f1edec8508d34687cba9eb9735c4113fc8 b/txscript/data/taproot-ref/715cf3f1edec8508d34687cba9eb9735c4113fc8 new file mode 100644 index 0000000000..6274e18b8f --- /dev/null +++ b/txscript/data/taproot-ref/715cf3f1edec8508d34687cba9eb9735c4113fc8 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a00000000b81b6fb28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4440000000042523524047aca7f000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374872584c954", "prevouts": ["2c8f4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cc64350000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_9", "final": true, "success": {"scriptSig": "", "witness": ["25cb817a20ad60a967642bcf9e2bde3234fc99257daa6369fb16f8db5a10332890010ea7a0dc27c45136a30d74e9a89fbaa5a189f9c8401f49ec912b08ad036703", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1b30baf514a3eba21ac4e0dd30c9a3f880398ad89900f83580914b631c7e1a55da4199b85d08a7769dc836336718908b9d2f3e0c642c8bb29120dc47e0f5539109", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/716e9a2309a2d14f0b54d759df166270321962ca b/txscript/data/taproot-ref/716e9a2309a2d14f0b54d759df166270321962ca new file mode 100644 index 0000000000..4f39e6ae2d --- /dev/null +++ b/txscript/data/taproot-ref/716e9a2309a2d14f0b54d759df166270321962ca @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46101000000b6d1aeac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707b000000000a17a0dc015a9020000000000017a914719f78084af863e000acd618ba76df9797223689878f020000", "prevouts": ["2a803200000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "dc95120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_55", "final": true, "success": {"scriptSig": "", "witness": ["70b172c476617b79f6ebd78f1152014d36200c813615b503e3cde754ac5b44089e89c84b97f88b912779b208f5edafe0888df609eefc9b377c020c46644949de01"]}, "failure": {"scriptSig": "", "witness": ["59bec9303e6e85d67f84761eec9a2af84c74df855ca43cb3aa2d5b35d9f29f4a8c50c54e635d7d769eeebda02120978e4600d43567ffdb9db8e334ba25cfa04d55"]}}, diff --git a/txscript/data/taproot-ref/71807ffa82a2c8190651c69c857cb71bcb08e301 b/txscript/data/taproot-ref/71807ffa82a2c8190651c69c857cb71bcb08e301 new file mode 100644 index 0000000000..347207f434 --- /dev/null +++ b/txscript/data/taproot-ref/71807ffa82a2c8190651c69c857cb71bcb08e301 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfd010000002957ffe6033cfd1f0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79625826548", "prevouts": ["49b32200000000002251204581460b504b6638e3fea2d0934fd04d28875d06c13da9be94a1b9d0f13f4099"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936803ab98b0f9ddf6f3e41ca6fb773f94017ab748bdc2b143170ff14bdba4b72f5"]}, "failure": {"scriptSig": "", "witness": ["6a37616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/71a2de6544779c774612b1f87277375ae9792a62 b/txscript/data/taproot-ref/71a2de6544779c774612b1f87277375ae9792a62 new file mode 100644 index 0000000000..f03a7f00a8 --- /dev/null +++ b/txscript/data/taproot-ref/71a2de6544779c774612b1f87277375ae9792a62 @@ -0,0 +1 @@ +{"tx": "6287608201bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf350000000033d65698012a9d05000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487193a7b37", "prevouts": ["9780700000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e94c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ac778bb6e9889cb94937fc77a861bf4edb1757bb7369dd12c591a6cfed1c6a5fcbd8218c9dac71a3535cf40d08210778548ef11a7c40c018c5ea1885d9980740ce9ba0618adb3ee44483a22999a54a4e1710b9846377d8164aaa29371d79f22a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93636d4c52f29c92967d3f95d954ae2b8d45ca9ec3ae28f3ad290d21ee88ac8013e5e04c998862288954a26ee7ce146837a88020619bd4ef6b5d2b0b49b83f7fafffc7f9c78871d6a598c7c7c3f4c8210a5c47caa8abf9700608b6e75845c74a6c5"]}}, diff --git a/txscript/data/taproot-ref/71d2976410e52b3891d47b0bf5daf36223655072 b/txscript/data/taproot-ref/71d2976410e52b3891d47b0bf5daf36223655072 new file mode 100644 index 0000000000..9405ce88bf --- /dev/null +++ b/txscript/data/taproot-ref/71d2976410e52b3891d47b0bf5daf36223655072 @@ -0,0 +1 @@ +{"tx": "b519aa9e02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7b000000005fde7c9860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a8000000008d3b00900238e98e000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7a5030000", "prevouts": ["b94b820000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "893c0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "47304402207298e9f137c42b68f8a3eff5f4558ee11594a946363a925fdf428b2dab5761de022072df6188aa1e65a8fca130f7c42a267a3d95c5eeecf77af9c0454ffbae8f4ade85", "witness": []}, "failure": {"scriptSig": "483045022100f55c0187c96fe2aa0fb1f25fd36d194aa15cb0994999993e349ea70323ca80210220310892946f3796e322083e4d44a3ba9243836aeb819df7c7e861ca769bafc38f85", "witness": []}}, diff --git a/txscript/data/taproot-ref/71d3d5be815413f81a15e1f21d82fa46ce4eeab9 b/txscript/data/taproot-ref/71d3d5be815413f81a15e1f21d82fa46ce4eeab9 new file mode 100644 index 0000000000..e5fac92912 --- /dev/null +++ b/txscript/data/taproot-ref/71d3d5be815413f81a15e1f21d82fa46ce4eeab9 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be60000000081cd06d2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba600000000e8ea84da04f3fb48000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c8e69e59", "prevouts": ["4c1b2700000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "bb67240000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c54c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694642e1d6a26a11a0c6e91919f09b278112d3d9e7557d10f9f51d88907efe7b71ca095b957df84f3ee7611aa117e5662ab64755743d6d9c5cff6305984f4054c5075e3d7a2801b75eefdf65cb630fc6bd09768ae07eb1bf67760ac5f1c253b1300a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900457ad860089e7bc2a902df7d26b00c72c3270dfe98d44c73f0cc876602eea860a2660eca3fa0edb42c0ab30ffe3daaf6f1f409e953104f48559c2b804c71af6a81ce4d7767c8a9637a0804b073b1eb172c67de67ce152ade33f2591a85dfee2e5a"]}}, diff --git a/txscript/data/taproot-ref/71ea7e6e573f89e2a23138bfbd547d888bdb7c55 b/txscript/data/taproot-ref/71ea7e6e573f89e2a23138bfbd547d888bdb7c55 new file mode 100644 index 0000000000..eda3a1c2af --- /dev/null +++ b/txscript/data/taproot-ref/71ea7e6e573f89e2a23138bfbd547d888bdb7c55 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2001000000af3b7dc802d19f4d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac491a804c", "prevouts": ["075e4f00000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "107d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e86665110f53a885bff43176a7d7b6b195840e7c84801cde818ee8fcc4f3857331bd940ade039b405c8439b762bfbc73f9441ef227e6f687b6d94ebcbac32155c7"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936abb663633cecfbdf047dd686359b8961732858ab1d7ce30f20dcec80a10ff65c32fffbf821c428499cff2b0139c90d93037c61d12af2692624d5246efcf2a3a14520b5ceb13d27db1b37ec8ee9ee9482aafd08fc62c5401b1fb7c7b4ff374c3d"]}}, diff --git a/txscript/data/taproot-ref/71f13e97734a6166d08d71982621f3785ea5ae3d b/txscript/data/taproot-ref/71f13e97734a6166d08d71982621f3785ea5ae3d new file mode 100644 index 0000000000..842861294e --- /dev/null +++ b/txscript/data/taproot-ref/71f13e97734a6166d08d71982621f3785ea5ae3d @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8301000000820c50a18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48c0100000021f32087dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbf01000000a91f7be901ef40c600000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acac07da2f", "prevouts": ["4cf95b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f456400000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "d4ce59000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c8", "final": true, "success": {"scriptSig": "", "witness": ["9becb17c1231fe529b6ea1a407ad1f82bc91a5a3732db42c15e13346bfa188bf9b620c62ee46cc570b395da25ebdfb35478b88adc06b46b6e5a77897618bdac103"]}, "failure": {"scriptSig": "", "witness": ["a9b7629951a0e094e8cf85c20147b28cdef214259be99a5e0cf25c04ed748e5354323fd920adf1d6c338bb51b5aa7b55720db9abf98276ce581ea3e6c0f8a408c8"]}}, diff --git a/txscript/data/taproot-ref/7217d80b5053a43d6fb6822470d12e76b42b2764 b/txscript/data/taproot-ref/7217d80b5053a43d6fb6822470d12e76b42b2764 new file mode 100644 index 0000000000..8f297b5d9e --- /dev/null +++ b/txscript/data/taproot-ref/7217d80b5053a43d6fb6822470d12e76b42b2764 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9501000000ea4b4ae9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c140000000035454f190291a37500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac963fce3c", "prevouts": ["e1f320000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec", "dab856000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ba7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824a7888d88a49f036a686b85959429d2c21b5cc7c31f53deb0eff848be794e4af5668d978bcc8d3ac0b8aded42d2a4a1c5e69a5396581e310868cb48ff813edbf"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361a6268ec6605c0a71a3baf80bbaf2c35e719965b840f442bd67e2fffd291e10546c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa8eec2374ba6ebc72bec4e80a7a4eb00aacc51a24e1026152998b46c213b611dafed5a24f2185242e3d6c1310740c566533f3942992fafe5f5be2785933680ed6"]}}, diff --git a/txscript/data/taproot-ref/7222bfdff7231c2aa5afe88a9b8860e057c947b7 b/txscript/data/taproot-ref/7222bfdff7231c2aa5afe88a9b8860e057c947b7 new file mode 100644 index 0000000000..0b86ab4a89 --- /dev/null +++ b/txscript/data/taproot-ref/7222bfdff7231c2aa5afe88a9b8860e057c947b7 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44f01000000e8d79ef28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4aa01000000a7c6011a025172760000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df9797223689874bb33631", "prevouts": ["98d7380000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "af6e4000000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "fe", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d877db375ed8535ba033f90d60f6b296e0f2bd1d7897409f54097620de448bdd800fc56907ebb8e18291aa6f74a5d7a46b4d60066ab44c243b43072452172e3365bb68c3eae5e6cd9b20289e581f52d4e8c0cb4ba58bcd8be9e67bc80fb920a1e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f273e05517e7d7c4ebae818f78ffc6ae6bbd8b4691985bf60fb53bef1b79009a0d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3b44d8b0f62b2d27de7be259100200d6da1e5303b29f3eaa1b6a4eeb0c96a42f364ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}}, diff --git a/txscript/data/taproot-ref/722914ef8c3dfacc1243877cf6bc0be5cc3eb6c2 b/txscript/data/taproot-ref/722914ef8c3dfacc1243877cf6bc0be5cc3eb6c2 new file mode 100644 index 0000000000..9651f7823f --- /dev/null +++ b/txscript/data/taproot-ref/722914ef8c3dfacc1243877cf6bc0be5cc3eb6c2 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e02000000912e21dfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9a0100000031b47cf98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4980000000092ee46990448da0101000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd8010000", "prevouts": ["ac7a4e00000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "3b7a79000000000022512065eb0ad8f24d6d8eb63c7f85eaa52926e45dd0588dc97971df796ca5c67918e7", "18b33b0000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["5ec5d50688ba958a318a24ccf231a4caca99043b5b9aeadbd4fdcfd6164e7f05d4bf1d7360752e902b5a043be1e5fab205990eff07191ee96b5faf8686f7ecfd01", "61e0f6c7957000856f68afdf46b3201ed9e484f794d24fca155304d56b298ac6a240551a16db", "753535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a200636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1605044119c566b794159a23a9ec14e8a93eb35aca328c0e9d704ad02ae272660d408f2c3322130c1b8d98bcdc511cbf08ed6626c6ad5103ccb066ba3a446285d944bd9ad9eefb4639ed414d71b7c064f5fd84ad1c711132e2e9ebde5b94751b1e89caf5e2beb3889a98787abd8bf5d9afe0e4fc9dce3fea32eac6b23d618250000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cb7826dd75b46e39b7208110a8e4187cc050392b3240f6316343fd3b5c2b15070000000000000000000000000000000000000000000000000000000000000000adeb2aad8459e3024ad2c2668541698cc8ce93668bd039750f5cc00fa3a4e14a9decdf7367ccf39a5da3025933ebbc5bfd9a59aaa537efe38ecc935db60cc7971db1de8dd1ebdcc2290e210e150309d2465c3e1f8f0d5b69187fa4290bc75b4804cb173a164212cb7d19614d96e5768c34d4dfd8433301572533455de27a30fc0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a15dc305681a926f377a601cf7c23c071267546f841030423230b4c08d220bf6c9371e0d47758eea2a2ef95e5c74652fe359e7a84bebaedd8f5cbad2e472078c89f4b57a3fe8ee55a2db8bc582dc2c086d6e2013270905e13b8a693cb448c815eb89bc8c94a921a08e17d69803aee69436fb8d642a195d2e3dbfd7ff4b07ea357c8c08c8b755ecca4dcd7260f3fc75b2bb426acdb917760f3c308a9dd56db50effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3514cd63adf5931b68575d063acc4ddc8ee198aba956d89a95c52880f987a5661f576596297ba20062b14f5c152df22829b55362d0bf62d312082561adedf5860061d9b857fa33e2925e2cfb59d3468d01d142aaa17ffdb306a6bcb3eb8c12b272df65b9b97bd8b6d3366db979794369fb42a62a32050c03dd496726c738740ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff952d98373bb692a211303639b04be8941ab69fc8fd8eaf22c25e4559817e4fc473ffe52f713c9509fb97eef4ec0aee20aeaa224974f203ffd301248a8ef6a3f6872745ff295f39dcc43a0fc05df9a0cc9ffd5055d92afa2346ebb2066376e8e558469301a9b6e263ea24102e6961fa2ae1e169c19c62b66d80499088e745bb6f00000000000000000000000000000000000000000000000000000000000000005d5dc489b6e5ed040e15480e64d74b78db75e01ffbe580e92d8a83b4ea6feeca1bb0a648bf98b56229535d4a542e847b45e4adfbc121dbc34dbbeee80e65545d00000000000000000000000000000000000000000000000000000000000000004acc8aa50fa881b69533ab9d152609c0dd064f9d02eb2148495e4078c79340440366f3dea0a2618a35d2722e492eac5b3289be3b7f85d789a6abbe08045b1f31ba87451c2d4b0cc017130b862b1b8210b40dde36f5718c48875db29461a66c2affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000005617bca7ef5e6cb18dbd2fbf24d980e9ccc7f39b70e1ff40d2405bec8d53fe9ad115c1e28ec2189fe47803972a7fd0c558f3daa78566e4be2b36a0c28dd423c200000000000000000000000000000000000000000000000000000000000000002cc1350b22905345362f666e73bada0a8b51404f26211cfbc3dec8c5f395a58b52852d919e15fed226b531c6dfac78217d3f4ec616843da9bcf13cde5dbbd2d252d6e794e5dc155b8e8b5bc46dfdef923814f07c6da7f5104e902378031b941645923efd542f46b65b36296d8568e958d60068696cd8938867d7ad1895bb717534d7e98d5d8c463537c2038f4061bf2f53e73a877ae92d3bc93f95b6b2c5c4028b7d821ebd6a528d2ad07e0f8f328041c9ff00dfc88352e2b863e9ea217d37350000000000000000000000000000000000000000000000000000000000000000d6d1be3f9f22d73e15361b24c926056f492e08e7a2e66c25e9ba2084e65c4a2effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff522e22e9fbda23fe7bac8b261b406cfa379fcb4bc4be65b2f492439cbb293259ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f54a5a7a721fbd7dd169a7f9816769ffaa8cecf08f113505d0a4dcb7eb2f1e8ca9f216f3ebe4a4ecf792769b51ef6f3617d8f04df33be5ac634a8e6f503bd6cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56067b6a3b8238e03d3addcd41f3fe569f8fe63463f45b4f69f30375e6a57dbadd986b6448bbd0d70ce5ed3edd16f37a28aee9a0401ba2c333ff2410e9a31a75ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5ae0d8d847a44579f27fe19e31b1c7c43ce8d41d474656aec9130caa444b60a4446178611dcce24e889d9c2f7ac8464806786032e4870ec6cf39ff3c83279c62000000000000000000000000000000000000000000000000000000000000000068d75ecb954c141cddc6009102adcf05c4c577a456815f49daead75edc4b18c4a2acf3bb28d15d945db1b63fbca8bb15e96676ee0b85dd00a211c659200d55bfa653963c6d225171a310191ba5dfa12da98a0e8e0a2e2415ef8ddcec6835f8b3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff12202008f40f7309b3c7453e91986dfa6e32732e08dd2af6d91e15390ae3deac65255920dc1074edce60bcab1348c3cf866f42b23a58ae1393ba69b8913d65cf0d7fae50141c3e3108f4cbd1f13b7333ee41b96c67cbb7b1e60558f2194f13f10000000000000000000000000000000000000000000000000000000000000000bce4fabfd555fccc54f5fb39c21eb1d92489e12bb54ca79bbfa9f07d2638ded37b8e51d0f490b30741c958cea8c2a821c55ff6f7121bf7a8aa5f94c8b2c4490b45ae10473939f2a532a8213d6cf3326962066d30f164f24697e7a4b8b5a81a7dfbf8bd91da6890ef3a8a40d33886b39f7db38aa33a4342654de37e996b482e821a6ce9571f0eb53fa2dd67c21bb74554b69b76e576f0b4f083e420a992ba9e15ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60eeea331b14f18667651bf2de9c937da7f86785e94288f19cd993d39fd8b1aa161ccf2dd39620d042a908d49ac607762ee1691c06958d3c3eca6ee05c80c309fd35f339800d1b526ce4bb0397359720aec6e2f6d7f29ba49fc55e76c17239660000000000000000000000000000000000000000000000000000000000000000b925063e800b0f603da8d6fee95ba9c797ca5e92e1da12cf510e4253f04467b3a009e9599efd22e228aa8754c121d637e7a29a4bc809a559a8e2b318fd2b7ccc6e974f144d38b7409092881bbecf143c7512f55ed5c01b8f0ca56efae83305391cf16e342c26171396d6203043abfe8d255e066ab2ec23f4f77580cf3395b3d94cd16b22791568a984ed01f8c62118b04ff9d1b7174a72070d84db138355bb5267b3181e480e62b991a2488b2cbc4b9ab69233eee79413425868b1bccc0dd2894c34b15442dbb5f3cac263a7b67c9f668ccbf40cce28939869d980e7a08e0d6affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2976d896158f2e452dcc5e82e7d94c1222a6ffeff8e3a642bf53dfb88e75aa3f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d35faa5bff08e02176b268bba767bd054ea45a6afbfab0ddfba339a189039dca8b13a84a55fbcfe4071810185a6ab685582cdad9badbc263842bb6b3daa84928357bc54732c2af7a9a8ae86b96da00b5a963772a438d7e575bdb417620bf07c98f3fddc91038dd143041b7553320eb0531f466cae85ef567a7b56aa8264eec7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaaad7f7b1c89fa9fd603038fc9dbfe91846830b37b89309d35ddbcb21eb7ead4b8419d165ba657503d8c8fac9e04888ecb0155d5656cfddcba611a3aa0deffcbcaad93eba073531c6f6122c7951e1093a14d7d07bfae4a4b494d8f26bb7682e9057aa808812a8bebeae3db2629d339b2690300e2d74c081c42fba304dec7563e2272f782359ec29c0f81d54b78ac02848f2d147ae5baff5b799cbe9574db748cc8044689ec1ededf59a10179cf1c112201a907d1e43f6310836c65db58825f0bd04dbc30ef782cb1c3e43b3a3d078c29bf67ceedf5fca61e7271688fe90d4ff6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b0033303d2de10daa76692b6ea201f57b0ea985778960d539da234f8d3d4ecf49f2fd2807beed1e234c20ff1ef0b91eceb83a7113d70bd5b11d6587b35bbac16bc25f0276e423d15bd494a0479c35701478b3997351af11ca8999e16b5a52a916f13a7059e3b88e2cb535ee3c857e3ffffbb30a2860ddf4ebf171608cc80c41935edaa6170f0ce5dff93a1a6b257c7fec45d35fca37c2d259f9b54c53519b5c934029a6d3cf9f905f1c6598826093b6fee6c7092d3e686e16c75eb2167e69b8695230e51389257769e372b1670d700f244923da50dd40177d1ce87f84d31bd0c081f7e8141153f9fbc10e911d5ff34edc6a0674311901ce1842ef2ed590077ae7c054ca8f4adece2737c3d25c3a526c8563a76d32f3376157a6695e986acf0eb85804d72c8a9d84a3774c76b0d3ba17a425a1cc8bac1277801502756727303ba88f2efa561ed0f2798907aa73edbef22c3d6f8c067dee4a79fe78dcad882b064bad4b4440ab524295af9c4432accb4a52b36e45630fc3b7e8586c780f045b1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff695247c5d28f538e46d903d8bfad21d8a131d84f54ca82a749a9e24150287ddc"]}, "failure": {"scriptSig": "", "witness": ["5ec5d50688ba958a318a24ccf231a4caca99043b5b9aeadbd4fdcfd6164e7f05d4bf1d7360752e902b5a043be1e5fab205990eff07191ee96b5faf8686f7ecfd01", "654d55e7f53cb9ed66b4fec695499e0fdec362af3359e09edf4e71bd02087ed3101b036275", "753535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a200636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1605044119c566b794159a23a9ec14e8a93eb35aca328c0e9d704ad02ae272660d408f2c3322130c1b8d98bcdc511cbf08ed6626c6ad5103ccb066ba3a446285d944bd9ad9eefb4639ed414d71b7c064f5fd84ad1c711132e2e9ebde5b94751b1e89caf5e2beb3889a98787abd8bf5d9afe0e4fc9dce3fea32eac6b23d618250000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cb7826dd75b46e39b7208110a8e4187cc050392b3240f6316343fd3b5c2b15070000000000000000000000000000000000000000000000000000000000000000adeb2aad8459e3024ad2c2668541698cc8ce93668bd039750f5cc00fa3a4e14a9decdf7367ccf39a5da3025933ebbc5bfd9a59aaa537efe38ecc935db60cc7971db1de8dd1ebdcc2290e210e150309d2465c3e1f8f0d5b69187fa4290bc75b4804cb173a164212cb7d19614d96e5768c34d4dfd8433301572533455de27a30fc0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a15dc305681a926f377a601cf7c23c071267546f841030423230b4c08d220bf6c9371e0d47758eea2a2ef95e5c74652fe359e7a84bebaedd8f5cbad2e472078c89f4b57a3fe8ee55a2db8bc582dc2c086d6e2013270905e13b8a693cb448c815eb89bc8c94a921a08e17d69803aee69436fb8d642a195d2e3dbfd7ff4b07ea357c8c08c8b755ecca4dcd7260f3fc75b2bb426acdb917760f3c308a9dd56db50effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3514cd63adf5931b68575d063acc4ddc8ee198aba956d89a95c52880f987a5661f576596297ba20062b14f5c152df22829b55362d0bf62d312082561adedf5860061d9b857fa33e2925e2cfb59d3468d01d142aaa17ffdb306a6bcb3eb8c12b272df65b9b97bd8b6d3366db979794369fb42a62a32050c03dd496726c738740ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff952d98373bb692a211303639b04be8941ab69fc8fd8eaf22c25e4559817e4fc473ffe52f713c9509fb97eef4ec0aee20aeaa224974f203ffd301248a8ef6a3f6872745ff295f39dcc43a0fc05df9a0cc9ffd5055d92afa2346ebb2066376e8e558469301a9b6e263ea24102e6961fa2ae1e169c19c62b66d80499088e745bb6f00000000000000000000000000000000000000000000000000000000000000005d5dc489b6e5ed040e15480e64d74b78db75e01ffbe580e92d8a83b4ea6feeca1bb0a648bf98b56229535d4a542e847b45e4adfbc121dbc34dbbeee80e65545d00000000000000000000000000000000000000000000000000000000000000004acc8aa50fa881b69533ab9d152609c0dd064f9d02eb2148495e4078c79340440366f3dea0a2618a35d2722e492eac5b3289be3b7f85d789a6abbe08045b1f31ba87451c2d4b0cc017130b862b1b8210b40dde36f5718c48875db29461a66c2affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000005617bca7ef5e6cb18dbd2fbf24d980e9ccc7f39b70e1ff40d2405bec8d53fe9ad115c1e28ec2189fe47803972a7fd0c558f3daa78566e4be2b36a0c28dd423c200000000000000000000000000000000000000000000000000000000000000002cc1350b22905345362f666e73bada0a8b51404f26211cfbc3dec8c5f395a58b52852d919e15fed226b531c6dfac78217d3f4ec616843da9bcf13cde5dbbd2d252d6e794e5dc155b8e8b5bc46dfdef923814f07c6da7f5104e902378031b941645923efd542f46b65b36296d8568e958d60068696cd8938867d7ad1895bb717534d7e98d5d8c463537c2038f4061bf2f53e73a877ae92d3bc93f95b6b2c5c4028b7d821ebd6a528d2ad07e0f8f328041c9ff00dfc88352e2b863e9ea217d37350000000000000000000000000000000000000000000000000000000000000000d6d1be3f9f22d73e15361b24c926056f492e08e7a2e66c25e9ba2084e65c4a2effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff522e22e9fbda23fe7bac8b261b406cfa379fcb4bc4be65b2f492439cbb293259ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f54a5a7a721fbd7dd169a7f9816769ffaa8cecf08f113505d0a4dcb7eb2f1e8ca9f216f3ebe4a4ecf792769b51ef6f3617d8f04df33be5ac634a8e6f503bd6cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff56067b6a3b8238e03d3addcd41f3fe569f8fe63463f45b4f69f30375e6a57dbadd986b6448bbd0d70ce5ed3edd16f37a28aee9a0401ba2c333ff2410e9a31a75ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5ae0d8d847a44579f27fe19e31b1c7c43ce8d41d474656aec9130caa444b60a4446178611dcce24e889d9c2f7ac8464806786032e4870ec6cf39ff3c83279c62000000000000000000000000000000000000000000000000000000000000000068d75ecb954c141cddc6009102adcf05c4c577a456815f49daead75edc4b18c4a2acf3bb28d15d945db1b63fbca8bb15e96676ee0b85dd00a211c659200d55bfa653963c6d225171a310191ba5dfa12da98a0e8e0a2e2415ef8ddcec6835f8b3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff12202008f40f7309b3c7453e91986dfa6e32732e08dd2af6d91e15390ae3deac65255920dc1074edce60bcab1348c3cf866f42b23a58ae1393ba69b8913d65cf0d7fae50141c3e3108f4cbd1f13b7333ee41b96c67cbb7b1e60558f2194f13f10000000000000000000000000000000000000000000000000000000000000000bce4fabfd555fccc54f5fb39c21eb1d92489e12bb54ca79bbfa9f07d2638ded37b8e51d0f490b30741c958cea8c2a821c55ff6f7121bf7a8aa5f94c8b2c4490b45ae10473939f2a532a8213d6cf3326962066d30f164f24697e7a4b8b5a81a7dfbf8bd91da6890ef3a8a40d33886b39f7db38aa33a4342654de37e996b482e821a6ce9571f0eb53fa2dd67c21bb74554b69b76e576f0b4f083e420a992ba9e15ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60eeea331b14f18667651bf2de9c937da7f86785e94288f19cd993d39fd8b1aa161ccf2dd39620d042a908d49ac607762ee1691c06958d3c3eca6ee05c80c309fd35f339800d1b526ce4bb0397359720aec6e2f6d7f29ba49fc55e76c17239660000000000000000000000000000000000000000000000000000000000000000b925063e800b0f603da8d6fee95ba9c797ca5e92e1da12cf510e4253f04467b3a009e9599efd22e228aa8754c121d637e7a29a4bc809a559a8e2b318fd2b7ccc6e974f144d38b7409092881bbecf143c7512f55ed5c01b8f0ca56efae83305391cf16e342c26171396d6203043abfe8d255e066ab2ec23f4f77580cf3395b3d94cd16b22791568a984ed01f8c62118b04ff9d1b7174a72070d84db138355bb5267b3181e480e62b991a2488b2cbc4b9ab69233eee79413425868b1bccc0dd2894c34b15442dbb5f3cac263a7b67c9f668ccbf40cce28939869d980e7a08e0d6affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2976d896158f2e452dcc5e82e7d94c1222a6ffeff8e3a642bf53dfb88e75aa3f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007d35faa5bff08e02176b268bba767bd054ea45a6afbfab0ddfba339a189039dca8b13a84a55fbcfe4071810185a6ab685582cdad9badbc263842bb6b3daa84928357bc54732c2af7a9a8ae86b96da00b5a963772a438d7e575bdb417620bf07c98f3fddc91038dd143041b7553320eb0531f466cae85ef567a7b56aa8264eec7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaaad7f7b1c89fa9fd603038fc9dbfe91846830b37b89309d35ddbcb21eb7ead4b8419d165ba657503d8c8fac9e04888ecb0155d5656cfddcba611a3aa0deffcbcaad93eba073531c6f6122c7951e1093a14d7d07bfae4a4b494d8f26bb7682e9057aa808812a8bebeae3db2629d339b2690300e2d74c081c42fba304dec7563e2272f782359ec29c0f81d54b78ac02848f2d147ae5baff5b799cbe9574db748cc8044689ec1ededf59a10179cf1c112201a907d1e43f6310836c65db58825f0bd04dbc30ef782cb1c3e43b3a3d078c29bf67ceedf5fca61e7271688fe90d4ff6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008b0033303d2de10daa76692b6ea201f57b0ea985778960d539da234f8d3d4ecf49f2fd2807beed1e234c20ff1ef0b91eceb83a7113d70bd5b11d6587b35bbac16bc25f0276e423d15bd494a0479c35701478b3997351af11ca8999e16b5a52a916f13a7059e3b88e2cb535ee3c857e3ffffbb30a2860ddf4ebf171608cc80c41935edaa6170f0ce5dff93a1a6b257c7fec45d35fca37c2d259f9b54c53519b5c934029a6d3cf9f905f1c6598826093b6fee6c7092d3e686e16c75eb2167e69b8695230e51389257769e372b1670d700f244923da50dd40177d1ce87f84d31bd0c081f7e8141153f9fbc10e911d5ff34edc6a0674311901ce1842ef2ed590077ae7c054ca8f4adece2737c3d25c3a526c8563a76d32f3376157a6695e986acf0eb85804d72c8a9d84a3774c76b0d3ba17a425a1cc8bac1277801502756727303ba88f2efa561ed0f2798907aa73edbef22c3d6f8c067dee4a79fe78dcad882b064bad4b4440ab524295af9c4432accb4a52b36e45630fc3b7e8586c780f045b1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff695247c5d28f538e46d903d8bfad21d8a131d84f54ca82a749a9e24150287ddc"]}}, diff --git a/txscript/data/taproot-ref/7275e47aff6a2c0f8bacb56d065aaba591e02a30 b/txscript/data/taproot-ref/7275e47aff6a2c0f8bacb56d065aaba591e02a30 new file mode 100644 index 0000000000..c438e634dc --- /dev/null +++ b/txscript/data/taproot-ref/7275e47aff6a2c0f8bacb56d065aaba591e02a30 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3c010000003492e39adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccc010000004291f994019baf2100000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac92000000", "prevouts": ["4ced810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "102e5100000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "e27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93644f036b5ef9fb8fbfbe8fef0b688d1e976e3d8ae9eec3eca289a706e0eef31c0d6719dae808d80c72548faab257df36cf98b115c53ace18df08612b967e5347aeebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7acec7827d9bc9e4e8e39cc141cf7690ea6843d6b50eda1fc8d5571fb149b2aabab"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820bc8e394a89b61e744ca0843579507fbd14c939f32cc2eb6ce7075b90210fcdaec7827d9bc9e4e8e39cc141cf7690ea6843d6b50eda1fc8d5571fb149b2aabab"]}}, diff --git a/txscript/data/taproot-ref/72790cb9d6895411ac13e44b9be62c5cb05584e7 b/txscript/data/taproot-ref/72790cb9d6895411ac13e44b9be62c5cb05584e7 new file mode 100644 index 0000000000..00f3f2588f --- /dev/null +++ b/txscript/data/taproot-ref/72790cb9d6895411ac13e44b9be62c5cb05584e7 @@ -0,0 +1 @@ +{"tx": "ae013cc4018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44c010000007f00bb99025ba03e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487e7010000", "prevouts": ["0c4a4000000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "627d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e889c476762c97a1f480fe93da3602a750f62c0ee9bbab5a4ae1c7a4219e84dbc327529efe07ed3ec82dce77345a5c0eb368b138839946732056b6a908dbf5f05c"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fabe3373372acbd8f7355a742b339dc4113bb3ad1c8e82e6b2233d51ce74beeba4a979a031634820b293704e38f33c20e5acd9cb2a8735bda71fecc5f77708044027529efe07ed3ec82dce77345a5c0eb368b138839946732056b6a908dbf5f05c"]}}, diff --git a/txscript/data/taproot-ref/7282e73fa9d18fc99fa2f10c51211fe1079693fe b/txscript/data/taproot-ref/7282e73fa9d18fc99fa2f10c51211fe1079693fe new file mode 100644 index 0000000000..b459deec7b --- /dev/null +++ b/txscript/data/taproot-ref/7282e73fa9d18fc99fa2f10c51211fe1079693fe @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43a01000000450efd63dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc600000000a8e0fb6603d47d8500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac08030000", "prevouts": ["3c3f35000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "79ec520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e2", "final": true, "success": {"scriptSig": "", "witness": ["e8ec293f7fa5184aa33811971677e4dcc782a30455f4b891bb8a3039e24024b734dfe0b5fdb2faee3233091b1e30b19b049e0a9408dfc7bbc30ad53db37397b581"]}, "failure": {"scriptSig": "", "witness": ["c370d2f8e980c82071fca4f3a2034caca9617d7cceea7260466f9b8912793c707c872b00a1da8ada8686dc520958fed35487b3935027a011704a230c42b1027fe2"]}}, diff --git a/txscript/data/taproot-ref/72893e972bd42b8697f75e7ac80c8885bf7c3a45 b/txscript/data/taproot-ref/72893e972bd42b8697f75e7ac80c8885bf7c3a45 new file mode 100644 index 0000000000..1a45f4d4b6 --- /dev/null +++ b/txscript/data/taproot-ref/72893e972bd42b8697f75e7ac80c8885bf7c3a45 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca8000000009decf0f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127016000000008d9b95b7029da96d00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac87195644", "prevouts": ["6d105e000000000017a914ca8d66b8079fd8386ff3ae1d10b869f5605e693b87", "404511000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "bd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faad1c924a2744de25921620091a34db181a435ddb56a0dc8d3bb0ce452693f5f97353a90cd56d8edfa9d59a5341a6c829ef2ec5b70cfecd5055b0e6c18dd5375841cfbdca9cced9a9297ecbc29dffc929789a1848311039b5a24b338cddf0aa70"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361eef65a04a420b347c827375227f302f031c014f488d196b114eae238398371fd4c17033a0423a3758914e896a84d75b6af3e7ce95cad06f99098a3cc7df4a1ef248cd26a95289b2c5b6dcbde70ff737dd7b8c2860adf4f4d2fc326868c95410d797dd6acf95c24b81e793c9c81b0ab80d381fe8deb935e4a90684c96acd4587"]}}, diff --git a/txscript/data/taproot-ref/728c6175ed68889cfe3f359471f509fd1da1623a b/txscript/data/taproot-ref/728c6175ed68889cfe3f359471f509fd1da1623a new file mode 100644 index 0000000000..f99b438053 --- /dev/null +++ b/txscript/data/taproot-ref/728c6175ed68889cfe3f359471f509fd1da1623a @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f8000000006d3588dc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709300000000775f78d38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45c01000000bf2c651d0114714500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1f010000", "prevouts": ["14030f00000000002359212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "0f160f0000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "13d73e0000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["aca3a5ded9f7d237520217cd24fefa492de0e6805413ebb39cc01b8f920819abce1996bb36eb2d4e73c88a9e82dbce2d459505aef6c35d81255e0b421387fb45"]}}, diff --git a/txscript/data/taproot-ref/729abe2b4cc9df53668a78ea8236ae421f3b5173 b/txscript/data/taproot-ref/729abe2b4cc9df53668a78ea8236ae421f3b5173 new file mode 100644 index 0000000000..776d904d3a --- /dev/null +++ b/txscript/data/taproot-ref/729abe2b4cc9df53668a78ea8236ae421f3b5173 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7001000000fe2a26babcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaa000000006e3943b604070dc800000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987fc927851", "prevouts": ["7fcc4b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "59217f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_3d", "final": true, "success": {"scriptSig": "", "witness": ["d195098ea69908e20beb604f9d5d4e23b2d97471868dec2373f48882b351f427b33c8dfbc149a16495ec90ceaf575c56abc83e0553b485cda7313749dce1abb183"]}, "failure": {"scriptSig": "", "witness": ["314ecd9b60a03fa259fa9cc84335fc70c8c25c8f0d1dc56bc022dec1f097b5d15675ee358aa3cf72217bb8065198d6be3f455c7c3307157cbd5b4ef6cc7cf6d43d"]}}, diff --git a/txscript/data/taproot-ref/729bc90d92d1235d6d3bc4c56bfc5a7cb1532e39 b/txscript/data/taproot-ref/729bc90d92d1235d6d3bc4c56bfc5a7cb1532e39 new file mode 100644 index 0000000000..d5e6fda38d --- /dev/null +++ b/txscript/data/taproot-ref/729bc90d92d1235d6d3bc4c56bfc5a7cb1532e39 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce90100000083239af2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ced00000000c0e951d4020615ad000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748700000000", "prevouts": ["3403520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c7f65c000000000017a914f0ed99a28545ab2ceacee60b5537a9e5c34fcd5187"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_55", "final": true, "success": {"scriptSig": "", "witness": ["6acc2c2de3ce53227191cc890f0abb65b823cdd8e61ffcda47c292aed303bd6708bdfcf319d6a4477feeb5be660509a426a22e8057a02a2bedfba33fe692cc2c01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b4512f593f052cd58b67f815e173320cf9af4300706e2fe67b3b2eec0f789e2def21f50791bd6412c15282efd253eee9b146d1f12455d03d7420c1527a9c876755", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/72a19edf12311bc49d7e72f4ce0d25f68b5ba472 b/txscript/data/taproot-ref/72a19edf12311bc49d7e72f4ce0d25f68b5ba472 new file mode 100644 index 0000000000..db59dcc220 --- /dev/null +++ b/txscript/data/taproot-ref/72a19edf12311bc49d7e72f4ce0d25f68b5ba472 @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3401000000ac6c38ad0460c56f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac92ef0b31", "prevouts": ["17c57100000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a89", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368f392c492a5b36963abcdb7fbf7476b495f34d23a20e2b9245c47655ae80aa8c1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454b1cf341ebb9351320fe3e143ffa2dad1c15696d7ac983fbe7e302fe7a073e7ecf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d8b8b59ec9330d10cfd242c1699350bed4f76e625017108107d5490f0b0ac19bcb3e0a345cce78c1fe891e9b22b966ce84a8b12623d949f63d5e15e148dd67959d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}}, diff --git a/txscript/data/taproot-ref/72b351e21f164a536ef913cda1b95716c0de23ce b/txscript/data/taproot-ref/72b351e21f164a536ef913cda1b95716c0de23ce new file mode 100644 index 0000000000..8df3b6d406 --- /dev/null +++ b/txscript/data/taproot-ref/72b351e21f164a536ef913cda1b95716c0de23ce @@ -0,0 +1 @@ +{"tx": "5fbef0bf0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e4010000002fbbd3ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702400000000b17fc38b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4020000000022f32a9201149c1700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6691b05e", "prevouts": ["0bd8110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "02e3120000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2", "37553d00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "487d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a78f03f4c984da33b67a1f34f73d9f3117d7a8717c805ff9e9061dc3289a8d8637a3a83b36cabe27f746cef99f5e6f5a048cb284627a25ce795acc8b79f1d63b4d178bbecd44a62a975bb89c44ce69c4bec935ce63261f4a792ecb896593fa3c40210bd7db211b82a407c19f9567cde5a01f8f2a3c3dc032c7ac21169de78447"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa8d88ca5d2ed422cbef7221efcadc1e9b79f7a9a7e5e37a381143666b41a8ce50be5e2af3a3c1a6754948d639a5542927d59c509fd5287d02d091c2a39a812b527da89940c9c2be3d3cb1ea9fc374137a74dc3bafe909c68993f298761996d666"]}}, diff --git a/txscript/data/taproot-ref/72b831f893332ad3733b0af04ea0e76cac65b5dc b/txscript/data/taproot-ref/72b831f893332ad3733b0af04ea0e76cac65b5dc new file mode 100644 index 0000000000..fb651beac7 --- /dev/null +++ b/txscript/data/taproot-ref/72b831f893332ad3733b0af04ea0e76cac65b5dc @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3901000000294d73f38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f000000000428d778904fbaeb6000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796f7b3ae3c", "prevouts": ["d7b8770000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "2ac54100000000002251202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "final": true, "success": {"scriptSig": "", "witness": ["2c4f4c08e82cd2748b627f594356ee1770e152d3ed937afef341d5d1405729e94dcfb2a411d61060992531f5176fcc33e0ffb407fb249880edbc638e48a7e26c"]}, "failure": {"scriptSig": "", "witness": ["5c1ed01d05ee9ee8ad3e08908198b0301ea4e75cf4b3866a7d5d4378720216ddec9c11e00494a12839388999355a222cb9579bbf423c9df99bc9b63a48938ea2"]}}, diff --git a/txscript/data/taproot-ref/72bd024e4b285894458f234b460fcaf90e8445cb b/txscript/data/taproot-ref/72bd024e4b285894458f234b460fcaf90e8445cb new file mode 100644 index 0000000000..f69b95ee29 --- /dev/null +++ b/txscript/data/taproot-ref/72bd024e4b285894458f234b460fcaf90e8445cb @@ -0,0 +1 @@ +{"tx": "52d03179028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44a0100000058a0458bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9e010000002bb7bb9501169421000000000017a914719f78084af863e000acd618ba76df979722368987f336fc30", "prevouts": ["806a3300000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "b81e8500000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902bfa1c4843af01b31af8a2762d5db46c30cda3b585094fbd43f3b9d3819a59b72bd28e5dd9c9165e17af1897a1fb1a549933ce84c4393144f63e25f92db635e29c54f872d537c59606ac1b48291ab39b568f8775d4ba386487b73deff380006cf78f96dab00f767c7cec7d50f740cc2c5d6f11098ac68329141c60d3fe0a7bac73f708f6dd15f8a55e9e91e0aa3dabcb90e3d6814df4367be279674e0bc4cc64c5728639023535b6b9e528f8f4c614570c08bee325815acc9ed749ce284d04fa974e36bbec791dab69813d2d3db8ce0d39a6a8ce501c916971d1e64e1479a28018399f63e83ad1de05268803bbd24a1f18dae14e19afe3ccce4ad25dc6f55019473ec586022070bb42d6ae89cc5e1e44e9ff2b0e24d1846b12153dfd4574c9981a1182e0f02fe584eea436299584292f8f31e81aab81d785ac9123fce4bf6b1c74703457034e5177ebf98cf8221e9895c3a8c309a3ca32872df0f66822f44e27caa7b3d03e0a362215ac479b6231c30eab6aa5b78a1fca0dfe4c872612fef770ab42ae1053ef4ea0bb10193183894eb74e85e70a12a9406abcca9279c7efc388b27833682c510f6e4dd1fbeef6f65a2977eace89ce820838527df7834e080ae90c2cb622660da184c183eba125dc5000caa45e1e6bea5ad8987df557077cfacf75c9cb74e82b905e589f542894676a846400f38cc9918fd3edb7a1e430522b642ea14a056ff1a1b349175d0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e2d2a48a19715e5e10213804ecd6bef4aa9ea7ea8b0db9d9bc22fd189820ca533f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823bd101e45a609d3b8e0b3b6f0b7594624f7e9102ef5d5dd3027418de40ebb2180d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}, "failure": {"scriptSig": "", "witness": ["4d0902f35ba5c782a43fe11859ef38643d9f5cc5f66959b5784b61362d938dcf683fda03c5e104443018355dea3370408d6b90250d7f8b6cf090fe060e634798d9e5ecb565e48904a8fe406080169def180c6df0b9b32c95e743c8f6afb14b46194b319634cc92534b4c747714ac329dc11e15c671954aafbc2cba5f3439296581f5bc783bd13feb0fb2a952df94cf7b7592f4abe3e19620467a7ba1ac28f4daa1cef3000f085ee69d005802120348ccc35b8b14a346808d4a9fdc758279e6683b2b57ab03ce02095a25020e059aacf856bfd2b665e439a3259b4e1ec9ffa90f5abae8e8d6a5e36ed40f52e187ac0c517ed6a794cc0c2789eea42321bbf88d124dfc36c27e99e00b3f8ee6c6d57b792144e6d24a12bd52271b6b7bf3daab66413431b222fb7d9be19e90437706275b06a8a50b2cc12706351de59ff26226046af7a9b1e354d40d191cc9cb8ad552ee127bc7c84cc4849f5b2856f2cfedc401ebbde8247461343265e85257fb86ec572065a84f76bcf56703b9d952a64805bc6ccb7549c604902a5d0a362590abe5584e3e79ab6d1bf76494ae03e979b359055b1f618671ac02bb602a610eff8af7a83bedf0f886b884cf77bb86ecf1163903f4a3b0dd2c945416bc9ffefc1fe629a039e89e0a850f340989089df982bfb4c524cac30649e3d4dbb93cbe835a9cd45de74d0d86d23c102ced1a8c65a4c0578a2a39776da79582a6aaef4bba527561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4daaf72f6551695de9dd2e4eae28f07b41c9ec36110061b2152d7ab3729ab44bcf81a0ae7b640e88bbe84e7c412f47337f1d12d37f95b062c539998fd28213cbdf3b3fb8d5121830dc5ea13d084a01bce62f4c2426ea7fcb92dda33a6ec3d9661"]}}, diff --git a/txscript/data/taproot-ref/72de723051c80828a6318b2251cdaf29db2600f1 b/txscript/data/taproot-ref/72de723051c80828a6318b2251cdaf29db2600f1 new file mode 100644 index 0000000000..60f0eb9e2c --- /dev/null +++ b/txscript/data/taproot-ref/72de723051c80828a6318b2251cdaf29db2600f1 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705b0000000087b009d7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfff000000004b4bd0850218eb8600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ace6000000", "prevouts": ["aa620e0000000000225120787bdd18c6671a560ba1e95ace53716ad824e1d735ffe5db246005d995daa6d5", "d04d7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_41", "final": true, "success": {"scriptSig": "", "witness": ["f7bad6a6d2dd226cba0787608e7d3eee2683d5a7909f5e60e60f13683f64c2bc84e83f1f3647c0349df7caf22e9d3955b077dfd85e6b923c87826e764a13a11881", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["693ba7d5c1417efdc0bc6903efe077bbb12aca28713ae932e8f576cce2aaecde52fa0395a69333e489e1f1d09eb77c3e2b2be24e101573af3b2d55187035429441", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/72e0280dc174679a75da3799cbb41ffe349f9f46 b/txscript/data/taproot-ref/72e0280dc174679a75da3799cbb41ffe349f9f46 new file mode 100644 index 0000000000..9d5c6bc4dc --- /dev/null +++ b/txscript/data/taproot-ref/72e0280dc174679a75da3799cbb41ffe349f9f46 @@ -0,0 +1 @@ +{"tx": "b925e88602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2a01000000148d50bc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700e02000000c93381a40114a80a00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac61010000", "prevouts": ["4a2c2400000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8", "368a10000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/emptysigs/checksigadd", "final": true, "success": {"scriptSig": "", "witness": ["", "a035aa3353996b17b5f039dccdcec2d19d71ca2c276ab8786d48ce6a773698b13cd0e27b26c902ca1161fb0f4544bfb14144fb0a44de5e11dc4d1cc27bf974a4", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad00207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ba91", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362993ec8e6179853847d0ee69316ca3a644767c37040f1b0ab2fe506df774d43ff52d98203d7275fad400ed3b197c4c0e8622d77cbcb79cf7a2a00d2fc972bf5002f82dbe4a6db58ee88633b3148d57fb2531bfad9bc912f2dbffc1de55c895509f476918f5ef695c8ab5ffd8fe1863125f9680a1d644e34f9ad8af958befbfd6587daedfcae5757dc790e5fd5fc7e5c85e6dacb92622ee4c35b872074113a22f2a18578b4c6324a679aa30a9e18da15f3551b7d2bf7b5529f4cace820b36473095447d483b1abd7672dfbc0cc5c4264ab29836baf9b905a296f16e6d7c4104528318720e482b09cec20c29a01196f6fc121b2f5494846d4028dc1ebe79751ed047cd408e7e45afc1c667eeea2951fa67d23f0c47f336029f3cc34d8d5ee74ae5de2a3f8aaceb3bdbc013310ea640cd38cdfcaee1e27c35353c5cddffee02d66e0ff2f27b7c8a7bbfbc10862c4415251567b33d7da846974ccc2adf2991d8af397a6da280d39d27fbd3b610ad765c3e7fc2a4ee2753fa02407aa98d856b9c1e1f2c5eddaeb8557ce0f7cc7880e698091ab104cabb34aeeeb5d0f57ea86d1ebc555dfde575d48d1eaafa8343c63d6f5425984d2425aca274be02e47a5142e089ba2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["", "276d682e2ab430b2fb2b82fd5bde04a0b000be3736bf2157325bfdc3aac5862b717a17470ae448d4f18a8b1aed54ae0015dcd479ee0bcfec6a2892a09dea54e9", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad0000ba91", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a9741ace787c3ba5c17bc53ff36467ca73e7d39d03d72c6c77f3cc9496b5503c76c6bd7420b2cea4f2928cd085843fc4ee0f453499d35ceb8e5ee9e0b79ba717f59440f4e67fc23aac21c7aacca3721c15c1516f2a9f6ac5bc60d230b02657b3851023fff65d6f40c4a5aacdb8cf0d40cd5e401b126df9fc0fadb4679eec7ea2f2a57b87935eaa4a17599a5b4ec099d7a36236ecdcd81c11f97ca92c8fa53087e6bf8bd64d9529d83870441f7e27274cb99ec835a095b7ea70a5a322cc5d52b423c6ddcadebf58a5025a8cb1ec3b901e96065e689e06d0af72db26f3ef0356de3494b0db6c991873dc7e87677bcd9ca13e114307dc9071f99f39a46a7715d3533a0941f2233db7810b6423a9958b3dcf1c09c67396d8ec9b45a8144fbdc7a52361e3fd655fb6f9a1743e8f45f41cebeee6a97926aaeee4c3f916a47c83a2790053cbc6b756194fb3ede31be6e35ac6727938739a1ae9b6b028b18e770eedabfadc618cf7f3a0d639ba509d355272eadbcb76778d4d1d605237c1cf557850c008acfa6a9da80a755a207eb5a3ad02b1a2cff248af93ddec122a727b43b9e8dbb8b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/72f423c06f55b024fcd60e3acd20f596205615ab b/txscript/data/taproot-ref/72f423c06f55b024fcd60e3acd20f596205615ab new file mode 100644 index 0000000000..370e607a33 --- /dev/null +++ b/txscript/data/taproot-ref/72f423c06f55b024fcd60e3acd20f596205615ab @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2d00000000e75314b28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c475000000008149b6b701e48d50000000000017a914719f78084af863e000acd618ba76df979722368987a331533c", "prevouts": ["713c4f00000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "6a1339000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "a87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8159738ff2c4f90cd16c07bb852218b8a19eccf086ed61d505eed94e2770983c2cd165f299bdaaa06ccf8947d9b12e815a5b39fc50068532880492a3446c423d89e26d26d9f798657ab1642d8194f1f5dc9158412142f65824f82701f20125ac7"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360696a8ad49f6bde3bd1da86a2495044ebc8bdff93c87d1dc4e64279442168fbe337e31cedb20dd0ec36f43f7131008eded9387a241f89ca892d220549655a6e95def3d75afa0626f5ab572f3c9ae49b6567bf85ec43d0b3933062a3ad8b1e492"]}}, diff --git a/txscript/data/taproot-ref/73319dedec7db18100aca1acbdf582d38ed80c64 b/txscript/data/taproot-ref/73319dedec7db18100aca1acbdf582d38ed80c64 new file mode 100644 index 0000000000..616e5785b6 --- /dev/null +++ b/txscript/data/taproot-ref/73319dedec7db18100aca1acbdf582d38ed80c64 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44601000000379174ae60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700c01000000bc09d7fa046db3400000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f877d020000", "prevouts": ["b65e310000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "60391200000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "8d", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93698751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d593f37adfd687dc0da405a76cf860eea33b50edba83aa9aefe64ccc08331b86a062cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004529493e63f0262db246dc905ef3bca459233a7269b5efdd4093c0b189ca3e559193f37adfd687dc0da405a76cf860eea33b50edba83aa9aefe64ccc08331b86a062cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}}, diff --git a/txscript/data/taproot-ref/733a381bc9e56cec2e4a856413e56d0bb7972662 b/txscript/data/taproot-ref/733a381bc9e56cec2e4a856413e56d0bb7972662 new file mode 100644 index 0000000000..26011e7353 --- /dev/null +++ b/txscript/data/taproot-ref/733a381bc9e56cec2e4a856413e56d0bb7972662 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127042010000002bb691cabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb3010000006a9750e360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707e010000007fb4f7fd04ef69900000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb3b44031", "prevouts": ["86751200000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc", "695c6d00000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "bbd7120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "fd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa4304fc86dd976b0937fa56c41f386d806abfef37789b2eae5a350cc5f24e0b07f4148296d57de26c46202ca6ca2132af69ac5e2240f6410455c1127b810a8937"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c1b9bacdca57d9824556224747bb261aea2ae7ed0ce11a73241cde6387669db02c6cefb1e181eefac563b15a866f5ecfc3c81e54821b9e81f79abce745f7d95962d72dd1cd8804fbc0be1dcf6a22214dbfb5210e6cde6f2a41edfb954edd50fb"]}}, diff --git a/txscript/data/taproot-ref/734891576e6360feb0a79e5f6326f4a0f3310853 b/txscript/data/taproot-ref/734891576e6360feb0a79e5f6326f4a0f3310853 new file mode 100644 index 0000000000..1f6431c0c3 --- /dev/null +++ b/txscript/data/taproot-ref/734891576e6360feb0a79e5f6326f4a0f3310853 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bf0100000078d86c1b0145ec0d000000000017a914719f78084af863e000acd618ba76df979722368987eb020000", "prevouts": ["fe973400000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "737d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a7cf13551a0cc26f1b867240faef9a11531fafe338f01dd82df40bdec0900967702c501a2f323d94577f3c4b353be8e702d3f9991edd341efb02c3132264010bb33a63f37675deadbbcd666ca6b38ad7090050f3dcc6bba45985e955ec185c53"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ca8610289a1fbd8cd81a98f9c36747bf01b158efbf5089bf299485f821bf6f7f55519fad8d6a945f0e016807e9ea80f240f92b51e0c4078917dfba5f2209ef9db33a63f37675deadbbcd666ca6b38ad7090050f3dcc6bba45985e955ec185c53"]}}, diff --git a/txscript/data/taproot-ref/73617507f1dbe680e93caaef1d078ac92ad846ba b/txscript/data/taproot-ref/73617507f1dbe680e93caaef1d078ac92ad846ba new file mode 100644 index 0000000000..1d864eb333 --- /dev/null +++ b/txscript/data/taproot-ref/73617507f1dbe680e93caaef1d078ac92ad846ba @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c429010000007cd02a6701eb623600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac64ba9355", "prevouts": ["c2a640000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ef7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361a06a52f87096620bfe5973d93b2be2652521f7b71c204e6ee336f5bff2f8e5582a8da46561b857dd56ed73270ec2a55b69a5f7c1db8df98b88468b2be2ca2b7eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac8ef60344f111a9c34d055af59cfd42b130acbf4987ee3354719b7c9974e4d449"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363b6bd5f9b965c7c7d639d1aafbe3f4870e0ac5697c7e0e93783e5267088edc7c7a25236fb2b0caf4a960afecbd8538cf949b3ef5b854c8fdc156128073078e11b030008666d4260a12bee868d13ea953ce9c9319f2222d8e8469ea0b912b8ceb"]}}, diff --git a/txscript/data/taproot-ref/739b15f40bb87a9e4f1a8399ce654d068bd0d30b b/txscript/data/taproot-ref/739b15f40bb87a9e4f1a8399ce654d068bd0d30b new file mode 100644 index 0000000000..5aca0aea44 --- /dev/null +++ b/txscript/data/taproot-ref/739b15f40bb87a9e4f1a8399ce654d068bd0d30b @@ -0,0 +1 @@ +{"tx": "de79ea5102dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1b0100000001706ee4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6e0000000064da1f9602df27bd000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d8020000", "prevouts": ["a8084d00000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85", "b2d1710000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_keypath", "final": true, "success": {"scriptSig": "", "witness": ["4deae274edc8cf58b4240480f46ea866b00c1a550b4c565c4cabc660970a0270abdeb41e3c54dcc555aff4128d30703cac10c2475e4029217b38601ce47d6ae0"]}, "failure": {"scriptSig": "", "witness": [""]}}, diff --git a/txscript/data/taproot-ref/739c724fbc1d946d981066a3f82cfb09a034ba1f b/txscript/data/taproot-ref/739c724fbc1d946d981066a3f82cfb09a034ba1f new file mode 100644 index 0000000000..08ec37a837 --- /dev/null +++ b/txscript/data/taproot-ref/739c724fbc1d946d981066a3f82cfb09a034ba1f @@ -0,0 +1 @@ +{"tx": "8724841602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1b020000002b49f9e18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41500000000a39d908104476a65000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47873b010000", "prevouts": ["ffb125000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9", "e565410000000000215f1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93649df6e65f74a1616f8b796c28e27e3bfd060faa480f7dcf522b455914aa3f7b8f4bc19c05a4ad9ae05992168d490013403fc5515955a55899592aa66a61db799770b862ef93acb6091cb4ff8ef135b3065b278142aa4adab757f952a626e2b26c80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d3987bd803fccffa941cee4c647c3a6675599cd3c733dba5d2640e5418dbaac99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4b4e321dfd5536232eaef67cd7779b0e400c7a17a369dbe44f6d3cf0436c0a34cc80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}}, diff --git a/txscript/data/taproot-ref/73a2aaa511c3c79634f98183fed1aa515112c30c b/txscript/data/taproot-ref/73a2aaa511c3c79634f98183fed1aa515112c30c new file mode 100644 index 0000000000..90121b112e --- /dev/null +++ b/txscript/data/taproot-ref/73a2aaa511c3c79634f98183fed1aa515112c30c @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e400000000e43d3005dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdb01000000dc21dcf7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1000000000413109ca01c445280000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca4000000", "prevouts": ["00ca0e000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "3c28250000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "bb275b00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c57d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93627fda090ca9180dfb5a3d6eb89a34d71879acd8ae0b8ec415ba4fd7717d6a8ba4a4f1964bf857a391dd30579e6c45654815fe99168eae3a652a179c44e1715327def1cc2232d9b1ca5244635fcf6779cb15e82fb856baa2ca11d8fd1da35295f"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826d35158b06e93427cedf9700445f423da8a62a86b9572893cb3b0c5b8130f93e00378a892e4dc43a17c9ebd71803200f2f24c9a40c2827c304e59be9b4a7df0b"]}}, diff --git a/txscript/data/taproot-ref/73ee1a7d0acd1f7e6a29e2cc9de52adf757c34f3 b/txscript/data/taproot-ref/73ee1a7d0acd1f7e6a29e2cc9de52adf757c34f3 new file mode 100644 index 0000000000..e7ffdfb358 --- /dev/null +++ b/txscript/data/taproot-ref/73ee1a7d0acd1f7e6a29e2cc9de52adf757c34f3 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700801000000b8b76795dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5a00000000f6c7ab86017eae1700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac00030000", "prevouts": ["cb9b0e000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e", "91a75000000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063ed68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630b7c2d4c1b790332bf4ebbdc264de6d20aff90470c4eba5176f312f66ccc9b0d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c9b0690fa0521f4fddf88c65f69e0716898ebb5a52dcb1ee37dd2f34a8a99dbd71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936777cd695cd6aba6282d5f8080c91c9295c817959fd1278b1f2c6fb3d2abee1f43e4c13dfee647a17f9595e8b3c65969e7c880cfffed6449fdebc16325bda3bb094cc415af9f84001a6feea45646803cad285186914838c4558edfc97d3166e78fd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}}, diff --git a/txscript/data/taproot-ref/74033d1959e62921897648eae99b7576a518dcbb b/txscript/data/taproot-ref/74033d1959e62921897648eae99b7576a518dcbb new file mode 100644 index 0000000000..d6889b6b23 --- /dev/null +++ b/txscript/data/taproot-ref/74033d1959e62921897648eae99b7576a518dcbb @@ -0,0 +1 @@ +{"tx": "c10517cd02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd0000000008c471e8b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49a01000000bce4bdca0378d8a400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d4783521", "prevouts": ["59bf6f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "536637000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["be4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4c9baaf460c9b08d8af0a53251cd8db921d22667fbf74eb915957e4e9d1c209d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51f60e2d3154f769650886384bb096233f0069490aec77c98efe910f3ad816f81d7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93678e2a199559b583075ea620e9a27812bb6f07692e0c8149045f4c4859f098adbb388de3dfefb2132719c310aa79074581b330ff4b72041fe2a3e03933132949f61eb6e6fd21ad84d93c7a0474b2daf5b011002cbe34781a2a14a95ac7c4e00ae344cebdb8ecd56ef01fad0911d9d88482970ec36d3a04b84eda7f5b5c68ec938"]}}, diff --git a/txscript/data/taproot-ref/74068e2edea30ca07fc3d6536b7beb1e73610c5e b/txscript/data/taproot-ref/74068e2edea30ca07fc3d6536b7beb1e73610c5e new file mode 100644 index 0000000000..573d8530b8 --- /dev/null +++ b/txscript/data/taproot-ref/74068e2edea30ca07fc3d6536b7beb1e73610c5e @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705a00000000b2b3b0d302b7360f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72a000000", "prevouts": ["d0bf1000000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09020544eeceeff632bb6e519e5549d9b5a6e9b634ca09f43ac1c130004e4c23f1a01a32ef677fe7324fdadddbdacde92f5baab4445e85cff3eca3f1163d053bd9432af40a863d65d7fac6059ae5642cb933c7992e619eea75364fcb04ea95e7668ab3374b308597badb6e427ccac499affd6448ba29ceeaaf7d210f4593990494ae6f216a12dcbd590f574f3cf90d417e982fb239bc3525967f97f48d94fc9b83cc7d99862bc7a2342c0c591f5d4063df53c764e5e181963daf496de1ba07f5359e71a56cf05731ba73f7a81ba09f0bf78a6e9a50e7df44dabdcd6980de8fa7f709dc14d56f699e0b69a2a98df9e06215741794938afe48d8d650c84a052f19cf0d77ffe1bffd0caeab8da2d2283ba3e9e50fa4520207732252b8be333baba2a342ed47b1d2ffe529ee86635d230a9ea2efe215a8f9df75ab72095434e8f33e29a33e4508ccd168b9c410c919ed4b158478104dd6339bdb9972401a69a64492995d733b3bc0fe121aad9b3fbec71af7acbca077fa757f4f7e9e0bc8f4cf9bcdeb90d325a7c66716dcf949bdf6307720a3eab6a00b575d525575f8430e9f436c81bc43aeb9f771b0b9288461a171fdc5c2896ae471e256f103615d9015d0b20248e888f3917deb2d68a0e1cbec38fc57390d2f42720c0a674b24a46d5c6b1f859f33fb0bab19d0e0c4168ff13bee3f7065321a68087b3816f2dd6c17e528187421d855889ddd172fd53afc7586", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93629a4cf536966159d361460fab7b3e5d8cc5d596b48cf3118556d4193e0f355519a49af0eb7097a2b25f70d75fc7fd7c267678862dc5ecafe442b2ce2fa2401f5a112aec6b4b8b5b1ca7f36a9e0521bdf2c7802df3cadcb1e8aa67d830b4a0d3fd33ab5c29645e0220ea4ffd8cb7e67404885cb8b0cf94872336c7b06d59c3124"]}, "failure": {"scriptSig": "", "witness": ["4d090250f01e0b8d9ba2d86efd14acbe327dc3bf35551da31875cf846de2653ad21bbbd90bb3e7c95de0d4e3b2ed7cbe51f2797fca07a39eb6630aaf8d2dac2cf206d9c3dea424b1926948e047ac6a4f489c50a7f40be480fe99f8457b6fff735b05d80ecb631f1b2a715477f58b3c7208ece3b04995ed905a78df6c5d06d619dc10d403f04b28c9ad0e61f9bb58430d1237ba9200561f3a41d77c8030f71284edf78b43f485ad7ddfb9e7f94a69f7e8fdaa55f9121b1a06e30f479acaaf0a69367b5309afa847d2f62739e97c537bc4f784170eb8ec830db268e25fc119cbc1cffec39600f45f513d9d9f3d532affd3ab936fa5275d7857b33c27b95d28e33444bb5a60999a95611e2c9c1bf8889f872316fa289d4278ab21c4ab56a752be5ce9297e78a47111e797135af130db01e33a1089944878bb7bee712cfd5e217d58fe34d43625523be41cfe75b2e9fdfdba2757a3a03751cd1468d87b4cbf79ae6fd1ad783649d0a5c022683493288f5c8b210b05452d5ea78f9a703a617cf8552d4f7bbe35f07a20417503c58f318e606012e91f6f8ad8bc42f0cc103b8080653f662557b9b8fbf9e11dd17e329d7e15902d1122aedec46685d2a9aaacf46edce4be90c70d74c71e1c362a9a1f653f02de7dce7077b2b33f90a321be48c690741912628028abdc99aba0863099d0e4b0189c3434d427b55e2f3def90b99796f78df91997adb4519ee24b5718a47561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93656455b54c589ad33b571e695863e621bdfbab9d554d43b73aa0458e592a0e805056f60ea686d79cfa4fb79f197b2e905ac857a983be4a5a41a4873e865aa950715c685a6e20a464c0638846c4feb0cc1ab19a0a1d3cef03660e119c827d202a5d33ab5c29645e0220ea4ffd8cb7e67404885cb8b0cf94872336c7b06d59c3124"]}}, diff --git a/txscript/data/taproot-ref/74077dff1318da9fbe3c8ecbcf570fa2b161a310 b/txscript/data/taproot-ref/74077dff1318da9fbe3c8ecbcf570fa2b161a310 new file mode 100644 index 0000000000..e2bdad603f --- /dev/null +++ b/txscript/data/taproot-ref/74077dff1318da9fbe3c8ecbcf570fa2b161a310 @@ -0,0 +1 @@ +{"tx": "3980379002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7f00000000bdb16596dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc001000000f9f628ff01158fbf000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a68a000000", "prevouts": ["b65179000000000017a914f955a33e905fb6c7b7e694c8cef25993577deafb87", "68725e0000000000235b212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["dd847f17abd19500624fb671cc44dc06eb3fd029961806af87c7fe856962bed3c2ee456c83fdd6f3cb50df3b7efd2dda87b00a3db6ef23b78fe45e0732a40b2c", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/742166e63d37f163f9bfa53c3d1ca1c432028519 b/txscript/data/taproot-ref/742166e63d37f163f9bfa53c3d1ca1c432028519 new file mode 100644 index 0000000000..34f6b4067c --- /dev/null +++ b/txscript/data/taproot-ref/742166e63d37f163f9bfa53c3d1ca1c432028519 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9d0100000067e4a0f360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d0000000088944686bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9001000000dc741ab4037f16ee00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb3af1b32", "prevouts": ["de725e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c5840f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ebe5810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_84", "final": true, "success": {"scriptSig": "", "witness": ["0e909defcefc58cbe5d6bdf423b88960162905a00d86dbc26073abb85e0493652667a5e8ecebaffc41bca6c8bc95f9c2f03e4bb89aa1dbf27e3a7a4399adb59181"]}, "failure": {"scriptSig": "", "witness": ["c048a583d15a4953ad7ad44d01a147f619065a71c86a43a0b7887740bbe66d7d1144ebbbb0295b3245979e179edd2e80cbbd1137e2504394e7b843722316117684"]}}, diff --git a/txscript/data/taproot-ref/742c9cda5fd595f2f4acc988670128b67aa2cce0 b/txscript/data/taproot-ref/742c9cda5fd595f2f4acc988670128b67aa2cce0 new file mode 100644 index 0000000000..28407e4e81 --- /dev/null +++ b/txscript/data/taproot-ref/742c9cda5fd595f2f4acc988670128b67aa2cce0 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705f010000000381a28bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfde010000001fdee4ab01e9047600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acdbd92745", "prevouts": ["55c40f00000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "cb836e00000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["3044022063b92c108c0a3b1ca0bd9f5ac2b553e68f307e72f55338a3b9ea2bb70adbb68802202eb65b655e4e689d91f50cd16fe8225078588b23d2b77d6489c88129fec986bfe9", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["3045022100801250364f0bafd1dc0f50226529e275c07eaabc3290c69b5c687faa8513bcda02207c72eb10d0c3655e5570f5c4466ac3b2d22b9157682527f1eeecbc5ac5be4512e9", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/743bd395e890e120441210e9d92579d0c7fd94d9 b/txscript/data/taproot-ref/743bd395e890e120441210e9d92579d0c7fd94d9 new file mode 100644 index 0000000000..57bf5a2e38 --- /dev/null +++ b/txscript/data/taproot-ref/743bd395e890e120441210e9d92579d0c7fd94d9 @@ -0,0 +1 @@ +{"tx": "c37ec3c302dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbf01000000556bab88bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc10100000073720da201fb286d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdac25b29", "prevouts": ["55e22000000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "e2aa6a00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "807d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93605d69d8562a6373f6f9d195fc88f9f90dbe0e07cddba6bc8e429596bb29181bd035ced5e3ad5845cfafeba3c70c2f6d2785016db0dd7771d558e4afbfe1a1e9a3dbbf3726cbcb24bd9ee344fc88539efd23f46f5d6cac68dd1bf47840d55ab8c"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7ef0a13ce9e71fa3d63dc84aef012cf9a91b29c00460432671c98dc081a42ec3f9b6f826008f58b0a2f0424fb9eb1e858fa037e128d89da74120b3f1d2e75bf3dbbf3726cbcb24bd9ee344fc88539efd23f46f5d6cac68dd1bf47840d55ab8c"]}}, diff --git a/txscript/data/taproot-ref/74433925d2da6bb3c3edcc954a98eca9eeb57abd b/txscript/data/taproot-ref/74433925d2da6bb3c3edcc954a98eca9eeb57abd new file mode 100644 index 0000000000..bb99eae4c0 --- /dev/null +++ b/txscript/data/taproot-ref/74433925d2da6bb3c3edcc954a98eca9eeb57abd @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4160200000022cbc59f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700c0200000019f988b38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46e00000000d2570be0027ad87c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc70deadc2a", "prevouts": ["d5b6320000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "59ad12000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "5152390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_1c", "final": true, "success": {"scriptSig": "", "witness": ["2e958cb393e98ed3c7d7e58b731ec756001a1b0a116ab033516fec055e8c3376866d75f1809ee05c97e44995c782cc8ab8cada6211b947316ddb5e564e7a8b5682"]}, "failure": {"scriptSig": "", "witness": ["9b3462788a7eb84137936bdf47842dc926c6fe2d4178145eab1501246a50f9a6b6ee8b7c329694709afd4aec03c85913acf1cf65de2682aa26ce1eeb93c39e7c1c"]}}, diff --git a/txscript/data/taproot-ref/746569f919dd66a45ca13b1e18824a0afdb22d9e b/txscript/data/taproot-ref/746569f919dd66a45ca13b1e18824a0afdb22d9e new file mode 100644 index 0000000000..844ff64aae --- /dev/null +++ b/txscript/data/taproot-ref/746569f919dd66a45ca13b1e18824a0afdb22d9e @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d02000000cf6fd6acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdd00000000770059ed60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270030000000080b8e2a304c1997600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5997e11d", "prevouts": ["a72f0e000000000017a91481d4142ddc5ce7a3de4047bd48b623419b5bc45e87", "8cd95a0000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247", "ae2e0f000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21591f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["d5729fe5beb15e862e97824b3e77f62d547e4d7dfdfda48f0f1db8021c4609078bb18be07093da3cff1e66c20d1cec450c766c8f7c0063c652f35c1cffba5332", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/74685cb831119333da8b5a7c83e055eedbef944e b/txscript/data/taproot-ref/74685cb831119333da8b5a7c83e055eedbef944e new file mode 100644 index 0000000000..5e74981814 --- /dev/null +++ b/txscript/data/taproot-ref/74685cb831119333da8b5a7c83e055eedbef944e @@ -0,0 +1 @@ +{"tx": "e4ec8ca402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0801000000348e6ddadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b190100000032c930c80498cd6f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8700000000", "prevouts": ["3514520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "71481f00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09027120ca60f6b28613313f39c76138c923761a185c46cf92000e57fc4b698b9717265802d1f12654a882a5054470f5c83ec5c2e91bea44ac31292c7fe96ec9fd38eda7c4bb92d1a3b27ae80880ffcedc19f4709737f153d5fa2c954ce6a6e80990bf0ca1acbc35ddba8937f00938b737761384e04aa584745d90c9ee1df2768524a2ae64d2a311fff731f5ac8cca6f4241edecfd74eecad37be56edc2218b55af7849e9da340436c2b0d5efad3f27acd961379efb7ab58696d87d391f50b3e518ae8576a527df7df42b240c1a6d10f537b7c9da4f275174aa30fe0eb1087b653ac217a2ffd22df3cce2bf77c2bef6fa46b37a544712632a115b2c2257d68046dfac04322a24bb5d4779b8e9b9679fe1a1404a0d082c9f35d4f4be172fbb23b2ebb02237d42011eea906d9a36981142ad290e0ad2c601daa8e5d0d3f07fa77ce40f4c5a8816f3e6787132aed37de61d560c68bf26141ab07a45d2032dfd6e4028b8df1d66191e97c05f294b1acf8a1cddc689a7177fbdef447dde98a59ea6425901af736f212b7df9340d00333434347e7363c84022cbe2aea627b8b3441d5df80e099f16da892f6cad2095774ebff83fc960ffec3a04a5f0612948e757a380b37526599c62f3dda82f7b54b0df99a1f03e26bf7cb9ee7bf7e655b07901220b1b2ca7facd5737b512c557060577656c59cafbf55cea181c25639f3b9ee44fcf7e15df61cec944ca229cae75cf", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4197eab9a6b3049015e2aeaa64734336ddd9b9acdec5b1d6588bac0b5808dea8f5f88ccdecf77b0d26ba8d6f3209049de9d03155be73752c3625590c2269e1c4cf4a62e14d7fc4acbfb0196ec29a60565ac2b3043dda4cedec8cb1ff291b90d41"]}, "failure": {"scriptSig": "", "witness": ["4d0902ab481f6fcb9aa5a8e5f232f5a4c42e63bd4b4802f85f765c4f86b3642a96c4b2a29ca3743e82c49dfc023531a9e1a9475e798aff3ca219bb15a1be92e22fbc417ef9dbb625a77c4722a06c91efb2406f45141df83a1eb2e41e02e0b5ad437665b491a310c476cf2aac20179a28bb9d37a8a3755893d99bf2f9bc9095ea8a8c19caba0c4d2a91eacf2d641057b4190dc1d210a1300732b6230f4a3480fd73273c893f9882435706ae0782447237c2e30789e5d87ca4d8c07c59fb055f028ce24b4cdd4cbd5c85b799e969d8c7ea511b2090e3755baf4f850831305a4e7f913df06d5580753ec0892f14fe3b9e24587f125a6b3a6e70291ed7b81ffc9a7a4187cb8242b11b1fbbc4f05142097e7b356e745245f2a2da045ed56ad925b2715089d3df0c2864c46883557be0c648fbcdef7e68aad34c1b9e84a53b562064a3b5a356b93af9589779b0f36c18e3a0c6b1fb11712cef253005ddc34e7afd95ea287c2a72c3e8ef8fe04df9318ba6bcee74b64c61197f21287e94b2c47c16c007be81c0881e38996c7862fb9d546689b67b000dc11eed6996fb2648f6df01ba8ac882597887f4fd10238df4de0a23d4aade84604c050b0f84fac397a0c89d7bd5342962abefa8be4ab1d7adea4743c27d67111e42ef63cd5c91d1e2dc128c07ffd88af0033a5aecaa2f1dd4fa21ecf6d56e44e6174cebe10baa70892bf2d48a57eb26346fc1e815caa29b1d6d7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c43753bef0c8da8689692db8eb397ee477bb8335164dd3b4990f2dc8206c25aee4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0decf70b79dd1be85a38988f8929e7263abb01bba95965800009381ed351eddb0fa653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}}, diff --git a/txscript/data/taproot-ref/7482f850ee397dd25bd1687e64b7eea626e9c608 b/txscript/data/taproot-ref/7482f850ee397dd25bd1687e64b7eea626e9c608 new file mode 100644 index 0000000000..b137fa866f --- /dev/null +++ b/txscript/data/taproot-ref/7482f850ee397dd25bd1687e64b7eea626e9c608 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf49000000007d987b7260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270eb000000000aaa262202847d7500000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac22010000", "prevouts": ["8e0b6800000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "b7e20f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_21", "final": true, "success": {"scriptSig": "", "witness": ["63f4c2e86b6fe02c3cbebdba369c949ad42dc874716b6ce4002d023bea343f477d4977ef3779a12efe8978ada7ffce9734a9bb7c4af858497bf0ad7cf09e953803", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["93805f4e0934c879021dcddd54d0ede409773e1c738114880dc32467eed12740a2a5fa06fb3b0991fec42355c5ec5bdd5f6b3db166fcdff63a48527993867cac21", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/748b5f0d6e2f9fa4665f7445654524ae50ffc8ad b/txscript/data/taproot-ref/748b5f0d6e2f9fa4665f7445654524ae50ffc8ad new file mode 100644 index 0000000000..78945d9667 --- /dev/null +++ b/txscript/data/taproot-ref/748b5f0d6e2f9fa4665f7445654524ae50ffc8ad @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43c00000000668a0bdfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc300000000031806d602a2158800000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac11cba52a", "prevouts": ["b5fc3f0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "d02e4a000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_cs", "final": true, "success": {"scriptSig": "", "witness": ["9ffe67de9dfc53c440d6856eb082fc36ae05a78663903eb9f7566ab675ad287bc42d3024658ff9b9b18d72fad23dcd3a94d0ea21bf38aff2d8bdb73593433ffe", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}, "failure": {"scriptSig": "", "witness": ["9ffe67de9dfc53c440d6856eb082fc36ae05a78663903eb9f7566ab675ad287bc42d3024658ff9b9b18d72fad23dcd3a94d0ea21bf38aff2d8bdb73593433f", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}}, diff --git a/txscript/data/taproot-ref/748ece6f6568749de6856f4e101f00d04a22d979 b/txscript/data/taproot-ref/748ece6f6568749de6856f4e101f00d04a22d979 new file mode 100644 index 0000000000..45924464d7 --- /dev/null +++ b/txscript/data/taproot-ref/748ece6f6568749de6856f4e101f00d04a22d979 @@ -0,0 +1 @@ +{"tx": "0a05db0e028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4230100000039d351eb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707f010000009a75c1ee016fad22000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cdd4d843", "prevouts": ["852c310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2f131200000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e568", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bab5e9c9c7fa88158bc6151e5274dedd524a29f558f8a01649a3b2357052ed1f8cf2788b31c6a31a23c8dbe6ff03f22a1631db08af18d9e87ce7bf14c25a50385e7270ac6e52de2effa1ad4f1d7cc04618f1a83be30b0454843cf6016e9cc3658f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08239f0e83d2be49ca995d97c64064bae5b8c7dff64f3bec17af779836b699250933d2e072fd8e8376d3a54b2bea1bfbfff1298aece70c0bc2934c8eaacc3044fe58f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}}, diff --git a/txscript/data/taproot-ref/74965c4ae1074a7c5d80f0889dda62db64f0d7d3 b/txscript/data/taproot-ref/74965c4ae1074a7c5d80f0889dda62db64f0d7d3 new file mode 100644 index 0000000000..5385c5354a --- /dev/null +++ b/txscript/data/taproot-ref/74965c4ae1074a7c5d80f0889dda62db64f0d7d3 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709d00000000dd342c8a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127014000000002d192c0760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d00100000015c28620013a9a03000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a600000000", "prevouts": ["6c730f0000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "a76f0e0000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76", "ef970e0000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "487d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361b6bead8fe288e6ce929026c6989676110fbb022d60d8870f6195026b963435337a3a83b36cabe27f746cef99f5e6f5a048cb284627a25ce795acc8b79f1d63b4d178bbecd44a62a975bb89c44ce69c4bec935ce63261f4a792ecb896593fa3c40210bd7db211b82a407c19f9567cde5a01f8f2a3c3dc032c7ac21169de78447"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93665d4f284dea934ff4ce7884dd9c30919ca3bc6361c3511237c2fe9a645a7cf7afbef2b09bb3fcc5f7a097fe825ffcbc345a4a7607f02adcd9241733378f6a21f7da89940c9c2be3d3cb1ea9fc374137a74dc3bafe909c68993f298761996d666"]}}, diff --git a/txscript/data/taproot-ref/74b0040c6bed65b152921df24d1d78125695306f b/txscript/data/taproot-ref/74b0040c6bed65b152921df24d1d78125695306f new file mode 100644 index 0000000000..d684855cb1 --- /dev/null +++ b/txscript/data/taproot-ref/74b0040c6bed65b152921df24d1d78125695306f @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff2000000001c75619cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4900000000cff75994dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b07010000003c029216047236f3000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8784d7ee4b", "prevouts": ["ac7783000000000017a91408247b8d3db4e641d0be1ff23f14280256870a5187", "06404d000000000017a914b60a534933f6e50f3846e396b9868efc9e681f4187", "4408250000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "4a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93627de835b8fd66a06eb530d511ef26a01c76127d8d9e29dda3bf7872ee1dae3c946c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faeebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac749e2a390543356cdb3691ba8d54627dfb45f7f1132e94c1a4e909f84f1614c2"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661eef72702ef339b2bb87603a397e70b07da9997acf93d66380977d6359fdd3deebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac749e2a390543356cdb3691ba8d54627dfb45f7f1132e94c1a4e909f84f1614c2"]}}, diff --git a/txscript/data/taproot-ref/74ba2f22626f43b6a2563b0cb35c620433682d40 b/txscript/data/taproot-ref/74ba2f22626f43b6a2563b0cb35c620433682d40 new file mode 100644 index 0000000000..015fb5324a --- /dev/null +++ b/txscript/data/taproot-ref/74ba2f22626f43b6a2563b0cb35c620433682d40 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dd00000000e98bdfcfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8a010000001e3b31c4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf10000000006ffb29ef043b09130100000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd0000000", "prevouts": ["f1ac0e000000000017a914ff6a0b1cf86e786bc6de2387f1927f71fd08cd0c87", "cda7830000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c", "20568200000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090277e046b6bf46fb9432b295afa59f87aa799c05ef75516949187963bdc7008ff5bd7ac8b78c16d5422de50893d9f72b53ee28d433178a18a419d2628955bdfcdb5cf517add5bd02de201108a36787987d54b49be934373ef8619eeeba4551fb1f108e22d1842ad5fc956b406068687eba97c2cfed42c9c35e0c8f6a7b9c793cfa1890697d4bd403d7e73cba15c8c0db317096afb05713f74d12abedfb8c357a7b007246e3bdc98398ff62271301877d16260cf3f87536fc0e2f33cf1b35058514ee567ffe93ac1649f1a423f7fd8576e10263cd44e56752849437e1948bbdd491fd4caa22c4cad0b5fd6753d703cf8b7c022e2cf995c0b4eddc3e4909b660674c96a2c82327cf51cf75896799fee143a39ae83611e10c9aeace4d5add85acadc4ab10f3154f5d1ed34fe63ead7894f9820adb34499d6a4e4b03a0417794139f90c5d2653246fd282679cb8995f240c2a549e0c6dfa744abab426d351ff4040f2cf39da4b5616e71afba8e1d1407f54fb6226037bc287b40ff329edab0bcee63c964e4db36a68037204f6e627a61a61dc9d1acdedaf30bf0647fe8e6ff0427b596c4087c76123798ad0b5ac5abb30a30e79c997076500358fac1598aa3ff5a8d2b91f372dbdc561452241ca601e8ba3fe6753c1fcd35ea85825c1e81dd38695c9f24d235aff0084551d88b16a3caf65d3833910ef718d66f6ef5c4822361194c22fef841aca19684201575", "d07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eda52357b0961fdced6c3795a6a09818322ab10c7001337037a8d029681d8b6eda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e15c449093bd19eda03bff23881ea6078d018b9cd0ffff6e12447ca822e876d277e36b196311c1a9d305bc653889017f46f4c4934a1587d131a83127df4466fae"]}, "failure": {"scriptSig": "", "witness": ["4d090210dd75754c358c3462614730f8fd667c8713dd1e9e6d27696b1f1277853c1c47bf15739a3f3b30efdd4a843c49882223c4822d94d60498680e22d0721edebf629daa84e773e6937333c6330828ee71a92f0b008894b2a3a6722d69c5d423f9228118f4835f3c87b9586c3544d8d296a516d2fd667319eb53e8ba9157b10081e7af413449a44e1df139f738618391e76e960c7c3f4a12688b12531353d92ca07d25281d949ec03fd791d9995526739521e5061601236a8204c56707d8a59b82fd6014635a80912d9b4332a05642552204855bd801d21ac1cdf4642e3fa826cbede07ed3d26812ad85d21e74f58a2a2f9ec26aa6ff9ae1cf0fa3688de5b71ce4bc897c70fe80711833ef90058acca215c1303c93036a2216718a426fcbed07e2bdd5691b33073ead7dd730b9004911199c3045382b4daf8ae7834cd7d9685eefe46c5d1d958ad3cc72b851bcbad4d51bd7501a67fb7672d731f9b53d9410c0e76db3578bdf68c2f1348ad5aa0308adc7c07656044368aa2270429e044d8778e27dd8cc409c8a1a754f3723bd8b6704fcefb6a14c89bda0a536a1b60559033f916e9311c24656fcd4f354204ebd61df13ca591de0f55e8b88e73e16f282084b4f2497ede6963a143a088d1a67611148cce1d37cb340b98dd2dbec921b3651190c7552e63b36c929507bc79fef294ad60f51ee8083b99bb1e8adc86cbb05c39f28b69cc5c6735027020e8375", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ef78ec8d95f7a630a87f4a69d09adcdf12479e6b3f8e7304927bbc129b24d5867420b3503815f4c7b180839898c4c4aff0ab6ef4d8b082708dba105a321f7428"]}}, diff --git a/txscript/data/taproot-ref/74dba0abfcd70931e9e189f44c9fe76cb1cdbb0a b/txscript/data/taproot-ref/74dba0abfcd70931e9e189f44c9fe76cb1cdbb0a new file mode 100644 index 0000000000..c0c1dd359f --- /dev/null +++ b/txscript/data/taproot-ref/74dba0abfcd70931e9e189f44c9fe76cb1cdbb0a @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b4010000009fa83274dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7e00000000eee18aed04b9ab5c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acec010000", "prevouts": ["5a6440000000000017a91495eb8fe3d959e08a2cc279c1b4ede1921d14a93b87", "fdbb1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2257202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["ee979f36ea2c02a592926939e3326dab1625c9106db43b47b5bb96060197b48c55035cd0f9b24ae1f3588780876fc9aae0ecec5f2210ee85544970f15a2340de"]}}, diff --git a/txscript/data/taproot-ref/74e0dd99e051486e796a28c6482f0b52f0af67a1 b/txscript/data/taproot-ref/74e0dd99e051486e796a28c6482f0b52f0af67a1 new file mode 100644 index 0000000000..be0fcaf4fc --- /dev/null +++ b/txscript/data/taproot-ref/74e0dd99e051486e796a28c6482f0b52f0af67a1 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41f000000006b0b55c0033f723f000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87ab000000", "prevouts": ["cd0141000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "473044022049574749461bcaba97ee33251e5ae7da21a9891faf2394a14e26e9c1cda04af50220722a83970d53cedfa8506b95a2da4c595d409e80998e553d45077273bacabd37814104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "48304502210086010bad88a9aaa45b2b005071cbe88af385eb08e0af69a32db43abed8a304ca02201f4b320384110796b35f03ef451483d2fd4ff9e27c98f53677dddffa794e7f93814104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/75255d425818aa4e45fa7a8ce30896b30e5f57bf b/txscript/data/taproot-ref/75255d425818aa4e45fa7a8ce30896b30e5f57bf new file mode 100644 index 0000000000..4e8e71ceed --- /dev/null +++ b/txscript/data/taproot-ref/75255d425818aa4e45fa7a8ce30896b30e5f57bf @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2101000000cfe0b1b560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701701000000d6dee7570105fc0400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4c000000", "prevouts": ["48997400000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945", "60ea120000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "327d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363674d83ec545aed04205f6c8011bc6d879deeac8bfcd4272e2d7b511be5f791a25d31a4d328a06fbd663a9de03f4f743ae6731d946a7b64875ecbfa9fe5ecb492e4cd18b5d1ec472eec5a95c6c9d67ba3848eb933b0b41a8c6d3176a27b07997"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac0f29a0308f7dd1d25542f1a27a19e78219e8b2987efd922e316e5388ecd586b0246b7a5461d23b2ebf642f7df88e05c9d62107f66abf7b5f94d7753ce57b53620e954adb3b90d8c3597d54022d70f5af7b761a66be618c54dd56feea2be872"]}}, diff --git a/txscript/data/taproot-ref/75362838d1ed152f60dc3cb74924d167c1b0fd2b b/txscript/data/taproot-ref/75362838d1ed152f60dc3cb74924d167c1b0fd2b new file mode 100644 index 0000000000..b9db0f36f3 --- /dev/null +++ b/txscript/data/taproot-ref/75362838d1ed152f60dc3cb74924d167c1b0fd2b @@ -0,0 +1 @@ +{"tx": "c6e5ab7401dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba9000000006a198ac904d2d91c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478793020000", "prevouts": ["9dee1e000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "267d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed3613095503852f968cf254efcb9d0b7a7155094671c0665bdc16a67bf9a23af91e402d116972020cc4db8f7e1431e7a7416668817d422dd270400f40dd8d238"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361cf75455252e12219cb13ff880bc28451a916c621a385ef21679c99f872f6341f7219e5458c3fd087680f56af7e0cb5a098c29a419645486255ebba5b453a7aacd4c02f64c49cc162ff9325daec6263c98ea78a2c5346e44c6d55d79722c7edb"]}}, diff --git a/txscript/data/taproot-ref/7559c841c04c474bc9ff45fe8504abb5d4e8f57d b/txscript/data/taproot-ref/7559c841c04c474bc9ff45fe8504abb5d4e8f57d new file mode 100644 index 0000000000..987c9bb0b7 --- /dev/null +++ b/txscript/data/taproot-ref/7559c841c04c474bc9ff45fe8504abb5d4e8f57d @@ -0,0 +1 @@ +{"tx": "8724841602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1b020000002b49f9e18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41500000000a39d908104476a65000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47873b010000", "prevouts": ["ffb125000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9", "e565410000000000215f1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["fe481de0054653f6dc89220421b81205d1f67dc9bf372464b33058d3f36b609fda47be226b9e2c17f1a76095a66ef57d64048027692203b62e8260064c28999c"]}}, diff --git a/txscript/data/taproot-ref/757adad4f7dd459070f4f1b1f4f4f2374a57ec6c b/txscript/data/taproot-ref/757adad4f7dd459070f4f1b1f4f4f2374a57ec6c new file mode 100644 index 0000000000..46ef8bc98d --- /dev/null +++ b/txscript/data/taproot-ref/757adad4f7dd459070f4f1b1f4f4f2374a57ec6c @@ -0,0 +1 @@ +{"tx": "a117860f03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc701000000bdcfc3bfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5600000000a3e6ebc160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e2000000008a5cc9e102a66ab2000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7d1010000", "prevouts": ["8417810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1a8a2400000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc", "27c20e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_db", "final": true, "success": {"scriptSig": "", "witness": ["4cc2c7023a430a883c4f30c9f42ebdaa1aa7c2932b51bda841d87bccfdf05e6468523df06590868d0ba60d2d45be07ca474c644b3e52d61d00e7eedb1912625082", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1dc7edeb9c04f789c631f77d100607021302f58c78bacb3b7097fac0c17fad76e0b3808c65096c821ab6f6fb5f2a18be1b415dcefa06ae3611f4fd666fb2132cda", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/75ed237efa308c478c8ee1faa516c94e45f17495 b/txscript/data/taproot-ref/75ed237efa308c478c8ee1faa516c94e45f17495 new file mode 100644 index 0000000000..df0848f167 --- /dev/null +++ b/txscript/data/taproot-ref/75ed237efa308c478c8ee1faa516c94e45f17495 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47e0100000034d6f85adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8200000000012c3b33dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d000000008f19ffce02f518ac000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987d0010000", "prevouts": ["baec39000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "d7d2500000000000225120b982c4866c93df3772712b36d4336b477e2dfe66f304c80c21f6bc33f20b8495", "8ecf23000000000017a91418261fd2fa0b0480c86b918607add1dde9f7026a87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2255202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["48930aaa45fa2fdb9010214f5b3d024c882fe1cfedbfdb0bb0e749a4ceda95a6b7c7e36ee19f4b85834e93a81fe9f6df72c1cf673b443ed2431e18f758f3ce5a", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/75f1856401af3c6957b627bba156ed076e49ef5a b/txscript/data/taproot-ref/75f1856401af3c6957b627bba156ed076e49ef5a new file mode 100644 index 0000000000..1350564217 --- /dev/null +++ b/txscript/data/taproot-ref/75f1856401af3c6957b627bba156ed076e49ef5a @@ -0,0 +1 @@ +{"tx": "ee452a9b01dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2201000000f780eafd011ba61200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac4c010000", "prevouts": ["0392270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_64", "final": true, "success": {"scriptSig": "", "witness": ["c13b367e48558707f232e0325203b68f70aab6a4d20d4867ecd67aa7c4e5c731e84cddce8ef781dba48accf56b0bf6b4d3d96240cd50e06d65a38f24c59f7e6082"]}, "failure": {"scriptSig": "", "witness": ["e6f210916038ee5faf17710a0f9f9798c135fa34dd30f72de516abaaca2d9c64f80dc4750875dca324c6a07d47f0ee50caa84974466d68868f78efd0ec10280464"]}}, diff --git a/txscript/data/taproot-ref/762487d62765bf58b6c712ce69edfc2a9d91f23c b/txscript/data/taproot-ref/762487d62765bf58b6c712ce69edfc2a9d91f23c new file mode 100644 index 0000000000..d23de65c80 --- /dev/null +++ b/txscript/data/taproot-ref/762487d62765bf58b6c712ce69edfc2a9d91f23c @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709800000000daf956298bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45e00000000b3893e6902e64243000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e740010000", "prevouts": ["4038110000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8", "f0bd340000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "f87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cd6beec103bd564656e486a3d8accdfada5c9b845f4a923505854c0068c70f9c9e87f1230a4dffa49f76a6d91b3ffe7dc371ffdd064326b56030bc36a92eabd9a0f16f4cfe8b052d74bbe565102becb5d9831a57baf41b6ebc95ac4a46ff7ed8"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e6214fe237ac2788af17775070b6b8447de06a17f7a8c679a51835b9edf50ef76a44cf4e9a2100eeda9c03b98c53803fc7517d02bc9d83cbf3bcae8bb7675812a0f16f4cfe8b052d74bbe565102becb5d9831a57baf41b6ebc95ac4a46ff7ed8"]}}, diff --git a/txscript/data/taproot-ref/767dc9730435e95ff0446a5e08a10843c28b5e4d b/txscript/data/taproot-ref/767dc9730435e95ff0446a5e08a10843c28b5e4d new file mode 100644 index 0000000000..55ead189c4 --- /dev/null +++ b/txscript/data/taproot-ref/767dc9730435e95ff0446a5e08a10843c28b5e4d @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cf00000000f88076ab01307b070000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc6f020000", "prevouts": ["793e330000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa1941f75e5ef6b91990230755a95e91c03e6de7762e861be9dda5623c3157397ffd5e8f79d631fbf207b458b911c1cf4efab0aea5316113aa9c93bea92caa9fc9"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360caa8a549ebb1e902e0f1d1f46675540fab11c0d150014a35b1dcb4da9e7097c8742f7aec0ae53a52a244a2c0c214837ef2ff67b990e770e70b44d703b0bde01fd5e8f79d631fbf207b458b911c1cf4efab0aea5316113aa9c93bea92caa9fc9"]}}, diff --git a/txscript/data/taproot-ref/76967f9679742d07c45801b75cdb5ec88f3ea2e6 b/txscript/data/taproot-ref/76967f9679742d07c45801b75cdb5ec88f3ea2e6 new file mode 100644 index 0000000000..8291f37199 --- /dev/null +++ b/txscript/data/taproot-ref/76967f9679742d07c45801b75cdb5ec88f3ea2e6 @@ -0,0 +1 @@ +{"tx": "62db20530260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b30000000059a62bffdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8d0100000072c0dded011a3b5000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4c2e7253", "prevouts": ["f1091000000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190", "c7f15f00000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "d07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e81c85c730685924be02f7d46bcb10c9c474c6189388cc381e7f7055dcad1cfa477e36b196311c1a9d305bc653889017f46f4c4934a1587d131a83127df4466fae"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0d5e55afeda99172050d01357d6d8287f4824ba4286577d269d78bc9373ff36ef78ec8d95f7a630a87f4a69d09adcdf12479e6b3f8e7304927bbc129b24d5867420b3503815f4c7b180839898c4c4aff0ab6ef4d8b082708dba105a321f7428"]}}, diff --git a/txscript/data/taproot-ref/7697ccd8a0cbc267875cf87e7ce982f8dbffa82b b/txscript/data/taproot-ref/7697ccd8a0cbc267875cf87e7ce982f8dbffa82b new file mode 100644 index 0000000000..69941cec66 --- /dev/null +++ b/txscript/data/taproot-ref/7697ccd8a0cbc267875cf87e7ce982f8dbffa82b @@ -0,0 +1 @@ +{"tx": "2718af9003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbe01000000e5a9b0d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7701000000d487d4b6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7c01000000a122a7d901541e3f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e1010000", "prevouts": ["436e760000000000225120cd69e6502803f0acddd51df30ad464e69e95dcae732a2073690eba6ce00d0199", "a2f375000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "0988520000000000225120a98c6fc01fa4c9d83199250e6e76cd0e9fc22cdfbaba8827d6d131a9d8267c4e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["304402202d7eb41b6e60bf733120e010d292433a057feec2cc7a5fc84c2b276461dc325602200615777448796abb85280f106b4af2c3e49f053aaf847fac06d13f874035c81d81", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3045022100d7d5ea8cbb8b2c64b33217a89f9bddc851bd242a1d802dd08a314b665479c13102203db82ca0415d06d4e8f12cc07445f43169455fc7af14b91ba48398c0ee28569681", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/769cf64713d5676b0d7823f406502b750f29f48a b/txscript/data/taproot-ref/769cf64713d5676b0d7823f406502b750f29f48a new file mode 100644 index 0000000000..233f4e570b --- /dev/null +++ b/txscript/data/taproot-ref/769cf64713d5676b0d7823f406502b750f29f48a @@ -0,0 +1 @@ +{"tx": "c273581502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf30100000056f903e4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb901000000a48e00d50318bda000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787f9020000", "prevouts": ["c6aa49000000000017a9148fdfffe253d045df4a2985902e5465482e50374187", "da125900000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "047d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84030e911897c6e4798122efc4265e48d96402783f565c89ff2a62155c020859d8460181b685601280cbfaae0e90478ea5ae6fea73a2d03f5a79a14a3e0c6d503"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93665f2789c044d6944fb0be746f461fd1d8ebe7179986f1cc1563b6f682e3c1e51e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84030e911897c6e4798122efc4265e48d96402783f565c89ff2a62155c020859d8460181b685601280cbfaae0e90478ea5ae6fea73a2d03f5a79a14a3e0c6d503"]}}, diff --git a/txscript/data/taproot-ref/76adb95f40dd46b0cd442f82b7eb70ed237f1676 b/txscript/data/taproot-ref/76adb95f40dd46b0cd442f82b7eb70ed237f1676 new file mode 100644 index 0000000000..a854e55aa5 --- /dev/null +++ b/txscript/data/taproot-ref/76adb95f40dd46b0cd442f82b7eb70ed237f1676 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c9010000000264f714bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf53000000001434957104c9c89e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79635000000", "prevouts": ["8db2310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3ae16f000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_35", "final": true, "success": {"scriptSig": "", "witness": ["e464d0cd9a97650724c91b3b02001772134e34f1e4ba7d063dd205525e0197395a67b7a026c596fc600b464560f8b825d539f59e70c4c5469da928d42a777fcf"]}, "failure": {"scriptSig": "", "witness": ["26822854eb5f3ac6826ad6a345dcf6faba210b3fe719d913b14c54e0d4c0955c11af367a70a5f7c383a3779cdf0846c71e6dd060eabbbcd85c652136fb43ef8535"]}}, diff --git a/txscript/data/taproot-ref/76ba7be2b975f49a68b47d255757883a4fe65358 b/txscript/data/taproot-ref/76ba7be2b975f49a68b47d255757883a4fe65358 new file mode 100644 index 0000000000..2b72f0addb --- /dev/null +++ b/txscript/data/taproot-ref/76ba7be2b975f49a68b47d255757883a4fe65358 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f4010000009c66389e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a601000000edc649680396c34c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acbd5a055c", "prevouts": ["012010000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47", "89513e000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_2", "success": {"scriptSig": "", "witness": ["f68fa9407bb9c6c147d0bcf5b59479a1744fc235eaf3f2d82d3a681179c902382a8f1302caeb069ade2252ba144b15a72015e6aee0577f7b247e01c10f879a9e02", "501e50790708f3c0d8f1b46f37ff1084b6a4d5423da1665f3c27dfe8224bccd17e478ce1444c4da453e399f233e7c7d2668ab1f6ca02ba9ad5b2496606704a6748265ce43a0316ea3cc86819a9881b08a8220ecd8184d9229ee69552df464bdfbe7d7dc2fa3295f277d9fa7e90525a"]}, "failure": {"scriptSig": "", "witness": ["187a22eb65a90679e9f31119bf2f035f76258b190a612fab8f156a375bc1e08e25ec5533a534f2797e55c9aae494478e31a07a1adea6c1574ece4f31312c50dc02", "500456a57af69a6a9615ad0e4c280ddd57d32d3f29bb568db26c714c074fb8de607d387efb6b26f9c1883843260188d3dd9974888a77b2b473f26783f36b3ec6b0ba7c12bebd30fd6992270fd1bf7d71dfcc01ab9893"]}}, diff --git a/txscript/data/taproot-ref/76bc86d13bce32da92769372e37076c675520959 b/txscript/data/taproot-ref/76bc86d13bce32da92769372e37076c675520959 new file mode 100644 index 0000000000..e11af1e601 --- /dev/null +++ b/txscript/data/taproot-ref/76bc86d13bce32da92769372e37076c675520959 @@ -0,0 +1 @@ +{"tx": "b96146fd0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270aa00000000012841abbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffa010000002b0920930287757400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac12010000", "prevouts": ["3995120000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "1686640000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "a47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630a51e3ee68449166d2da506d8de0f0b7ef39424ebe5f034d615a238e9b2a225f873bed7b94a92ccdf1432eab063a27f935bef099df6a1cbcf6734b218f2b6aa9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100eec4f69e5cd9a0f0c1fda8eb2f54297e33bc5edab35b299e65e2653a923d6ca55"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8df22966d6a6c55ca54713f7180fb521ad1601010bda1f1af87739ba1b0e44e80ea84c8431ee0615517346b97932410ca977012a316263f78a9edf0a452e478a09da521cfc521edd35405d6ff7b10120e980b699014de05f8e600b437ffa9c347"]}}, diff --git a/txscript/data/taproot-ref/76c17c551bd5e5ae2efbb26f2e05d12c9c8181b3 b/txscript/data/taproot-ref/76c17c551bd5e5ae2efbb26f2e05d12c9c8181b3 new file mode 100644 index 0000000000..a39f92fbc6 --- /dev/null +++ b/txscript/data/taproot-ref/76c17c551bd5e5ae2efbb26f2e05d12c9c8181b3 @@ -0,0 +1 @@ +{"tx": "ad0f55ba02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf000000000020d415c6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf37000000008751388004a9f403010000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487cb7cdf54", "prevouts": ["781681000000000017a9144c4b1fc943f04d775886b4f6d3c3c73bf7d3118c87", "2435850000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09024006cd93f5f60b084a9c8d08f966dbcc9e0e70a9926d232a9d958679ac161177943a477f798fd4066b5de32773201a141cd1bd70630c76c1e8b2f926b8ba6f9b9b55fcffe7283f010f84dca936f6e4f37e43378a46bc9713305239853e990b19eda28c5adfda4c1c8f00de1b7b471df302ca39c5374c820318be1dd64637a82964fc76c9b01d1f1afe3cfd00a8adf6752e94618728612a75b17677b1c372e67ca03d2d84e4b9585d4349a76c29c73465c53023ebd14646e87c6fb627b295e8e5867032bfc1847b955c2f695686aacd19214430264b19fa8d2e5c50f2ec853b20575cee6c7117370456f0a19aee799d2a0679311ffe7e42340b3e894b2fc62b52d041561474f4732d0ae3ef9107270a57bac8caa37c38d93cc64adf33323dea692befe5d67c5810f88cfc6dba97bc5acd2cd826b1174a2c25a6d2ae2adb0ebfcff6fa6bc464f2d3fa9d92208fc6d45b281b0c2bbe3c39f1bb17352c9880d1e326299b539ff176a29a8b237193fbdcf15904ee226d50970479af8da478a3b752580dd42b7909129104044b6f96a7a9e54d107a8a43f2fc07fed2f1cbba13d9a758d8c1029b873a24096bc59dd83fcddc0adc1868fdc90959a6e8778ff13dec76647f2d948e4bd9fd230f8700a7d2a9daad6f2ee75f1072e7f8b5ea3e1a5a0ee2a563b6f6f03f5f933bf23d3e06f53711110bae4ffd1dd3f4e4fb829a1b3035f3e0f8b9152716e4e57e3975d5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fbe755e9607a08942b2a918c9c9a472649e9fa8321d88cb3bf3ced4d061fe811b5f329bd8499c4f72b132f747438a5079d3448c35be74257418716cc5d770d7ef69ea04c091b2bc3b7c7ae53ee1804d998a6447fcbbef49abb62b7a394c4c123854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}, "failure": {"scriptSig": "", "witness": ["4d09027d14f8c3a2194bfac66d9dee24939361a77803dde263fb9cfeb1c17256bbfa96dce43ae1187ee059eeda6f4a22bc3c4d22487d90adc1cd10d26145e062ff813781b5362e4104a65a5495606caefe9c74fab11e327b8b2d2c1f28ca64d856fcb28820944de1432fa4be9b70683b9d3204a30db612be6042f7418e3bc4b8e0ece834fec9ea755191d39c613ba3ceacc88030cbfa70757b061d88136cbb818b57b7636241d513dbe961db18b7b31b43d6f729b1a55ed562982c351fcfae96a479d77469a0b9e0bdad84e493c178691f49c33fa5cb8630f0ccea0e6988de4af6a045df07fedaf3c6bafa5c1ee8757268563650f952eaaddd8888ef6f1bc90764fe229d24aa6cf7333a3d93153709194472b804878701a3867799c3dd511d11b87c53c5e5eeb2c86fa57cd8d4f59cb5c0ff79da0deac1dfb505193ce9d27f5eb3b3a10171f5ecfdfa663e35a838ca974f9716f4d8aac6116a4bd1beaeddb0d0d902b6486749d8ff6cba3d2b396b954557c03ab8937704b1198fc0400158f233cbabf9cbf24afe585ea27f70c227b685adaf3bc24d4488750d1bafd03d986d43c7cb91f8bf1772b422c074261562c96124339fc36922a344c5eaf47c1be00b5883aeb39635b40c551e98fc79f7b2242103640435571ba8f144376b8511c259fe764c775e34af4f3dc89db069e6fd7de81a4bdf64bf1110cd31942b419474fea5d645d4298a0ba4917eac51697561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6754763bd81125d3562783a12f8a78fed0af3e064c5aded9a58b08a7329535c99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb44c2f2200f850d6a1609ea6f282082fe51ae8a55145cebb4c521120909a7edcb74b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}}, diff --git a/txscript/data/taproot-ref/76c565f5646ff08d8c740ffe4cf133d9c8a3fe65 b/txscript/data/taproot-ref/76c565f5646ff08d8c740ffe4cf133d9c8a3fe65 new file mode 100644 index 0000000000..d49d4150fb --- /dev/null +++ b/txscript/data/taproot-ref/76c565f5646ff08d8c740ffe4cf133d9c8a3fe65 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43b00000000ae08b4eadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c51000000007a44b5c0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b640100000061c4ffd403bdd4b60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac57010000", "prevouts": ["f0d03b00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "96d759000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "3c68230000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "7e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936564aba5bb494d1265d2fc5f111904e284bf007c2b0a6386000b21954c3f321a8fbc41b165d26ac180ad5b5d4c7fd11b6e5ed18084ae5d6505f3de45d58844c1cfa5d068ae686a8bb1ac9947127542ac866077ad522de57cab26ce701d52bc951"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdb95efb91d04564594d9dcf752eb8fd975bf01996a0bb9f9eb7163324924bcd44fa5d068ae686a8bb1ac9947127542ac866077ad522de57cab26ce701d52bc951"]}}, diff --git a/txscript/data/taproot-ref/76f5c55837a53eb0781baf11e0de07184a6d08ee b/txscript/data/taproot-ref/76f5c55837a53eb0781baf11e0de07184a6d08ee new file mode 100644 index 0000000000..b118f36524 --- /dev/null +++ b/txscript/data/taproot-ref/76f5c55837a53eb0781baf11e0de07184a6d08ee @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49d0000000063080aaebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa801000000660303ee60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ba01000000be4370b5010fb78c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7d8000000", "prevouts": ["c21240000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "da9f8400000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "a0b10f00000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c14c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5182d044aa67ca69515bddcd39ff85ae31d999a9a5b32af0a0137c9fa4b226ee88d3f52a2844c5f7874c7d430ecd2ddfcfe713e30c56da5784f950db6acb8f092a"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936049f747986f150b9437633843d291800b849149650f68a8c294c910246137135d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5182d044aa67ca69515bddcd39ff85ae31d999a9a5b32af0a0137c9fa4b226ee88d3f52a2844c5f7874c7d430ecd2ddfcfe713e30c56da5784f950db6acb8f092a"]}}, diff --git a/txscript/data/taproot-ref/76f83799d26fbfe8607158f4718d6f5cfdc8621b b/txscript/data/taproot-ref/76f83799d26fbfe8607158f4718d6f5cfdc8621b new file mode 100644 index 0000000000..c61a5960d7 --- /dev/null +++ b/txscript/data/taproot-ref/76f83799d26fbfe8607158f4718d6f5cfdc8621b @@ -0,0 +1 @@ +{"tx": "9a4d26d2028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4340000000054ebc4c9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd401000000535d55b401bc3e0000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac08000000", "prevouts": ["e42e3b0000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba", "2fde5c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "c87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e8373588cf8424fe73474f68ca177013b4f80e2262b45a155b55745d3c6e43c7da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e65775dfb1ab8912d99abba269b246de78dce1dfa6fdc8b38f44f7be80bcbeb76c308d8e78b0cea59e70bbcac5990a047bb63a968328232757672e5e931dda055"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9fd4215134e0743a43db076a2ddc66cd37630a1ee932cb7432b56663f87783368e9a99c27257089f8586472cc94222e874ab5c5b462fc98ac1b045b7a37dce65323990ac9ba96640afb66df99f25054f5788ad16157a03b33c6c26a70bd925e21136d3d9ecdf371b2101a7e86edb56e15b10ef185a8506988239bb2b5a4c43e"]}}, diff --git a/txscript/data/taproot-ref/7705fd1f70110abbefb84b8bb3679338dc85008b b/txscript/data/taproot-ref/7705fd1f70110abbefb84b8bb3679338dc85008b new file mode 100644 index 0000000000..2d5bc22462 --- /dev/null +++ b/txscript/data/taproot-ref/7705fd1f70110abbefb84b8bb3679338dc85008b @@ -0,0 +1 @@ +{"tx": "a5db689303dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8e00000000ee83d8e88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49d010000003a8b0fcadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6e01000000d40773fa021b25830000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ace0020000", "prevouts": ["24a5260000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8", "e8e73c0000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "4909220000000000225120acc511cd55079365da76d18a33af3ae7411f3879a9caec918e9264c8959f5dac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "f87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cd6beec103bd564656e486a3d8accdfada5c9b845f4a923505854c0068c70f9c9e87f1230a4dffa49f76a6d91b3ffe7dc371ffdd064326b56030bc36a92eabd9a0f16f4cfe8b052d74bbe565102becb5d9831a57baf41b6ebc95ac4a46ff7ed8"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e6214fe237ac2788af17775070b6b8447de06a17f7a8c679a51835b9edf50ef76a44cf4e9a2100eeda9c03b98c53803fc7517d02bc9d83cbf3bcae8bb7675812a0f16f4cfe8b052d74bbe565102becb5d9831a57baf41b6ebc95ac4a46ff7ed8"]}}, diff --git a/txscript/data/taproot-ref/7722142222386c62ee3cf0d244202e77b759f34b b/txscript/data/taproot-ref/7722142222386c62ee3cf0d244202e77b759f34b new file mode 100644 index 0000000000..e429db0465 --- /dev/null +++ b/txscript/data/taproot-ref/7722142222386c62ee3cf0d244202e77b759f34b @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42b00000000ec4681d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb3000000009a1ab7c503f24e9400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac34030000", "prevouts": ["33df3e000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87", "787358000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/1000inputs", "final": true, "success": {"scriptSig": "", "witness": ["783a38a223450cbde7a7b41248ea105f1ec2f7d27d06ffe0bc173368cb79926bde2e9bce343e87772e2c0b6d19e0fe954a756a263ffd3f2e47dc5fecbe0178ff", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "75757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361b31d32273cec10a388aae06b849f4b58d319b8be15342d1582ba39dbae41cdb8d0c3ae4ecd69aafe0cfe43a84c5490ce66f12d05fca780d5434df16d81c50b707b0958e6f1d30ef106eee149eea009878f1bb16c67ddf543cd3674e13327b7267ad95278cf386dea223e62e70daac0dffb1914a422911909ea2326740a911ee4e6da2445d77f245beebfb228d762c59bc4a45aa12cc4f427fb039e22e0741b8a9b8ab344cf2739c9b0c32934aa3ca09577646326af4e24188e665bd1ee1286ae8a1d97d8069ed729c043647fddc6f0881774cc6af50354826eb57bb80c2a537064e7784a32ac7a58f3a60a34997c8053014901c71ada75570a50a230c2a15812d8c2d47d0d67efe3e8b51d627e5dfa00d213ab14a67d5c44c645d4238abb49f653b56bbc07059ab8fbe5f7a1d8b1a014d2dac79b80c168f374716643afc9d2078ce779d35b8b9495da82099971fa23460f65b58297658f8344073387644345bf93c5d65e32b9def275a3e26d7cfb887654cccdb12315dfea4cd4a0817d8d4bf17002da8b6956793790e2522cdbbbc51c3e76cc941c9170ee3ae91039a9479105f3564c54269032898a6cd874ff4d1fe0ed410013dc82714eb7a54d64226e3868b0e659112c9f7f4ef135ef7e3677927c686e2cfb83a5642dd1287d117c18623babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["4cdeb6cda4ea5936a8a548d271d20e8d3ef2c43f6561a714f40b06e7505d8d94b88b42fc81df8d1be972e219a062df18d5287dd15867ee2acb2617d76d78281d", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "7575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c83b46994d7f8e6994644064e85620b72250802c25869579473094af99741c2a53d70a499a2b9d07fe4e0e6cff337beba7d38cc150fdbb661dba76e5139a2443acf95dcf25aa121eb2e54ca553120788d0e687c373c34db8910d412871842a61c2ea6390cf7a5065adb655a43cff9312a2403aeb5ea762cebdde4d887b73eb6c49d3b8c8be8af93872b6db7ce0bb5cd37d778c1b0ce6796d0a810415378a7c3dba1b225e18c65d1c10de9a0cc3035ad2761c5c76198c2ab54b8cab7c145b5d828d1cae81044ccd077cc0a6748c134e6cde0d0e3b375ff99dd8f5fc12660edb07ce033cb2548bda430cc0fe75bbd863ef5499578603dd05ac225ff92af4da5b7edca4fc2d6b3b9f6d10b16f2fe0d93e1083dbdcc6039116dd558b96d689a9b6ca973655fd5fd3ea54b033deec3d8b0af8f9d2f52797f3400e4f6e622e7375dc6acdc7095d9956755e1260b1db6b35d4ca0cf370620b49d6dc89fdc714ef75e3b9ab67361a9d368d00307e918b8d4e9a4b3c809cfb6b1f27d7ad87a7bffe6c20b1e1faf1c68c7350ed7e5b99510cfa520ad19515f62e946aa86743be480fffad58a57b391dd67ba025b9a60505ecd7fa3b5ed0808730285af9f495e709e1f92ab88b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/77258dc253bbfcab9ac3a990bda4f20592f9c651 b/txscript/data/taproot-ref/77258dc253bbfcab9ac3a990bda4f20592f9c651 new file mode 100644 index 0000000000..97352fa5d3 --- /dev/null +++ b/txscript/data/taproot-ref/77258dc253bbfcab9ac3a990bda4f20592f9c651 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7a0000000049367eecdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb401000000a94652fe02ebd56900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3c355049", "prevouts": ["00244800000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "b705240000000000215b1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090246f5618e5237005debb856b786290b415637a1f1f1a00b78394a2d854ae88184dc518e76c1d0627e1fe87196dfb3184222e3d53ab50086f526676338692cd57aa39de2eee4e49e6fc648d0e1d92b9244f783bd61d8495cbf60156e481943e28725e017a0709c4f1a3b669b97b961b83d37c24e693aa60a3b8937221ca43c4d96da489130dc24ac5f4b557d80f10ff8077fd1b865d5ae5ff9cf1d071ce753a596f82dcccf4fcb896a4c7ec4f8e5f4b4a01717947397c24951c8b9ba68f01496ca75d7786ee34a7542f6902453c7fccd18c2840cdb3ade118295c7c8c88c455528d2ac7ce8157692d77956c0f57ad92f44c0e57d5b9898c97b2cdbb268c4d84330e9926befbdbf984c1af249e28cc5facc6d12e398ae5dcdc5c223064114e7ce1dc06eb9db5c0c312b0da142287f46ade46e172d0e14f185c037330d56013e49240ff80aa1cd46430225d00b7ee8d67b872b8a007c70096685afad973157901f18541086fa4f750a09063bbda0e34362b64b212ab54c72c796a057ec422f3373255fb591079ac1e0bd0514664274dc04e096940d2f5523c7aa014dad38b79b854efcc61a8378d13696473f2c8a348d2aa7a88a349b5bb583037240d8bea60bf770eeb95b028bcdbaa3eacc796aef49eb18f561719b075c40b93a5262e6163c25870a5769aba3873d711682537fe07947f2329b8e8e03602c5ca949122137cd048b986e5a9dd2f44ee19375", "ff7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d6cb4833cb0ce17ffb0b5ccd72f003893ae0529ac21789df7af68ae41f1b87092e9788694c2a4005ded48f6fe23dc6801bfbcf181c543907f81cb41df22d2e77f27794099b656b9faa6b5043ba50cab982b2292ed8155b5f0f6568a958ea63ad187b9e30f7e626b28b6dbe2d7b101f74e326290698090dbb0a7eb7a50daae87a"]}, "failure": {"scriptSig": "", "witness": ["4d0902583306149d617c8af0d3c9a7ae919cb88dd68546e03b4ff5f3cbb9347fa2bfc7e5f580d91a6472b5df5e81ac87753ee2dc93c9d8b159efdd7b1ec3c30125b8e80a8082db6598397ca849aad678e0a67c92cb0aa5581a790057337e59fa48ac8a61f2e67d971f89fafe602e1e62daa84539988ac72be858145801fcab3e32be9cc5d1381ef0696fd749222a2823d18bc9ad5d01fdbc37f18b0938e262048edd139ff4fb0099648b9b62522c651ee03f16688c7f3890cacd95b7804f5d191416ac304e9eed73faf971784e8f3619d2e3230a4efdb4b559d4feed1841eb260945981acc03a56b24b53fa54a77782ebd672abe447262aafad0e11cb063d976c810239b9780a5c578d17577a9a6c3a7c19a52bf20b15502e106d34bdbba56f5fd3633731025b75ee4f096c6aa73d56d8ead7b9f6f4b98dd99771e8d6479b8bf49cea2432a54c4791c3e806558e322db4f77c50b31ede95a5481de826932c72fa6cced57a20a13913e3eaf1b54e2a715fce1c7bcf8c17da9ce5bde6fa27b4a561f0f7b8a96ae33c135033153fb00036ba100e433719c314697284a3fd87f3ad61279c7481101852476cd45cd85f51d99762ebc18748cb929fe1cf31063d5dd3371605fb91885871fa7005b9b4613397ac13beb1b19cdad92dad4cfb814035e578b12cb2cde1cdf3aa529916b7d90570cc32de8f3b0347a57e985d6efb24ef0103c73e0554638498f3c339dcd75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360250bf0957827ec0ef4e6919f825b41a841653c5bffb12706dd1bdd45b1dd4a32e9788694c2a4005ded48f6fe23dc6801bfbcf181c543907f81cb41df22d2e77f27794099b656b9faa6b5043ba50cab982b2292ed8155b5f0f6568a958ea63ad187b9e30f7e626b28b6dbe2d7b101f74e326290698090dbb0a7eb7a50daae87a"]}}, diff --git a/txscript/data/taproot-ref/7726ec0c41e3e97e7d617065e6504efb8f024cd4 b/txscript/data/taproot-ref/7726ec0c41e3e97e7d617065e6504efb8f024cd4 new file mode 100644 index 0000000000..a670fb4f62 --- /dev/null +++ b/txscript/data/taproot-ref/7726ec0c41e3e97e7d617065e6504efb8f024cd4 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f9000000002952ca0e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703501000000ec13486101dbaf04000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ebb0ca47", "prevouts": ["2b700e000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "1417110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_fa", "final": true, "success": {"scriptSig": "", "witness": ["ce70a1e19d53314c8df0e2a5969f4095575c775cf66ea5b042050a2e6b928ef33d973a510be348fca910c81a6b006319f42df4249808e7db6f7512a32b3f7ff301"]}, "failure": {"scriptSig": "", "witness": ["272aa10ad3414d8c91bdfae458f2fe02bc11f33e05e33b074c62d86d42b06729761198eda32e1621fabda0200f8b3385703317c34553eb418eb491d80263252afa"]}}, diff --git a/txscript/data/taproot-ref/773d0e073333f130bcff75d37d1111faaebee058 b/txscript/data/taproot-ref/773d0e073333f130bcff75d37d1111faaebee058 new file mode 100644 index 0000000000..0bacff9054 --- /dev/null +++ b/txscript/data/taproot-ref/773d0e073333f130bcff75d37d1111faaebee058 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4d00000000734e99b70459591d000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7ad010000", "prevouts": ["c5021f0000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e7", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93668ce749c68de633516e195736934f8a88269848cb24cae075fce4521e857a6cdd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c61a1ab416979399a3dea56cc9db65331fc4d8e9e627e6b90ed3a4ebdc2f66c36df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936feb3983b18e4525f0a8518cd3710c3b144f3f0d5edea574e13e05d297dfd94906cbd7cfc5d340306ce0f8e37fe1bfa8aba9fd4064e6187eeb928db0d0bdab726391a14412c925771c32fa4c7776d5872be2a56fee9c5a8de868e7e6e5a4c84da"]}}, diff --git a/txscript/data/taproot-ref/774784914f2077e1681344cb01340a934be26ba4 b/txscript/data/taproot-ref/774784914f2077e1681344cb01340a934be26ba4 new file mode 100644 index 0000000000..de619d44ef --- /dev/null +++ b/txscript/data/taproot-ref/774784914f2077e1681344cb01340a934be26ba4 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49000000000575c18d0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6e000000009b12d9b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6201000000323bd29c036d5608010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6ca6eb94e", "prevouts": ["b77b360000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17", "a9315e00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "7c80750000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "83", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936777ff8a9412e94f7b77cdcac9df137438df90b973affcaf29cb29560429bcc3e8ed6c904d531fc0d19ced9482d4cbb64035dc55104164ba190923612d3f9e9a82b9d1447cbfb5d72d5da72ac5ad193469eaa6b44c038aa23e2a9d2dd480586adaf3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93683933d45c3442f615ee20a7137db960cea3b9cd87b48587a4de9c490e5a6c9c899aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb439b32d44b6ff86c799acdff23ced11a294722ef2b8af6951bf8429e3bda52b31af3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}}, diff --git a/txscript/data/taproot-ref/77907cfa0df9ad35b28a28dc974519599031d5b7 b/txscript/data/taproot-ref/77907cfa0df9ad35b28a28dc974519599031d5b7 new file mode 100644 index 0000000000..8ce468222b --- /dev/null +++ b/txscript/data/taproot-ref/77907cfa0df9ad35b28a28dc974519599031d5b7 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270de000000007f4af652dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca600000000e56eff118bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48000000000454a026504e231a400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e79f410645", "prevouts": ["a4bd1100000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "f33b5400000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "67d540000000000021531f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["ca", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f336cbd2c434dcde2d093b968cd4500063515049b2ab4f542ce372ccec22f446d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c1012b923c15ff4ca5711684c82f77f7d0ace9e417918255ff860668826001128a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d520ce1e8f5df7741068fe8539649c9e500f335a96aa69621db8e7a39b2f9d4cf99c996d59a69d75c183cc1e3ba6b17987582b2274e87a7d50251745c93805cc8eba4e75ed92f6e82baf0cd6101dcd67879c020ab703e3dac001fd69a24240ecc7034c4ece6ceffdf067bd97d8bd2a80e986f14e8b5dca33ff1523eba7a77d63"]}}, diff --git a/txscript/data/taproot-ref/77a416c6802644089ebc937712578c64cd114e2e b/txscript/data/taproot-ref/77a416c6802644089ebc937712578c64cd114e2e new file mode 100644 index 0000000000..ab3e4f8fed --- /dev/null +++ b/txscript/data/taproot-ref/77a416c6802644089ebc937712578c64cd114e2e @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf12020000006d57da0d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40d02000000dae2d1f001858c5300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acca000000", "prevouts": ["52eb790000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "240d3b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_cb", "final": true, "success": {"scriptSig": "", "witness": ["bb951b2bf5f8b50ac52303fd39cd7e7ee711071d15167ca9042fd85d21f87764ab10f415e04cd3e75f2e8b46a80fbdc069fc63a1387ff905a470a1a12f35152482"]}, "failure": {"scriptSig": "", "witness": ["f08a28ec32f09defe6338e79247dae57bedf496481795544319895a06a7cc9c4cbc3cd24999dc52b54f255bad6b0b7d26397c351013611c22d308e836c32495bca"]}}, diff --git a/txscript/data/taproot-ref/77b1d215fef8b044b5354a64c3541f96a5eed3ef b/txscript/data/taproot-ref/77b1d215fef8b044b5354a64c3541f96a5eed3ef new file mode 100644 index 0000000000..459bfd42ea --- /dev/null +++ b/txscript/data/taproot-ref/77b1d215fef8b044b5354a64c3541f96a5eed3ef @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a400000000bf14df5cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c000000002070b123bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd800000000fbff2f2002a8abd800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac05ebd32a", "prevouts": ["79d30e00000000002253202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "5ed7480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "853c8300000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_8", "final": true, "success": {"scriptSig": "", "witness": ["b362dc06d7903fe7aa481fd01a349477e849a2b2c2a0084a62d0c03cb8dafe03be4914b397c8b8344016432f6dda686d022696d71b84d693b53d8ab96e5068e702", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["4fabf967b8b61daa66d17eac1a6a529b154585fdd88677c8d6303ff07c92a0c823e794bc94216d774d400ed24518aeec8eeef43bc841c029e053885fdbf37ef608", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/77bc35d370a04908ca4a6126a011623e2b09442d b/txscript/data/taproot-ref/77bc35d370a04908ca4a6126a011623e2b09442d new file mode 100644 index 0000000000..2a5e692ad8 --- /dev/null +++ b/txscript/data/taproot-ref/77bc35d370a04908ca4a6126a011623e2b09442d @@ -0,0 +1 @@ +{"tx": "cc88653202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf07020000004b0446fa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ce0100000099320c9c03335573000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898713000000", "prevouts": ["3517640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "07b7110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c2", "final": true, "success": {"scriptSig": "", "witness": ["e8a86ea3274b426616d7ac445a38c720cb20975e3424eae2d80e8e03719b20780dd5ba3279a450ec522aa8a4ee88ca4f4f89fbad38b6688fe79c38539489f91681"]}, "failure": {"scriptSig": "", "witness": ["bc32942281c86099d29e759d3023958a300d3e30ba576ca39b392a2c62d18a9d82ed94667163aff381954a9a35eb1e9be50abaff847df3bdbb7057601202ab09c2"]}}, diff --git a/txscript/data/taproot-ref/77d0cc6e1223f82ea66b45b7eefc97601034b9bb b/txscript/data/taproot-ref/77d0cc6e1223f82ea66b45b7eefc97601034b9bb new file mode 100644 index 0000000000..013a1350c4 --- /dev/null +++ b/txscript/data/taproot-ref/77d0cc6e1223f82ea66b45b7eefc97601034b9bb @@ -0,0 +1 @@ +{"tx": "5f9251c902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf800000000bc13d3a860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705b01000000331e88c204b46b2e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48766d85037", "prevouts": ["0f9b210000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756", "89ee0e000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "a47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e534eece907d9a3224677f965f53c0f955581a0bf9d57668f5d1001f37295acad5e071d65b1ff2cbb44adb2a0836dee99e48dd3c256c0643eaf2d4db2ac89d0f9da521cfc521edd35405d6ff7b10120e980b699014de05f8e600b437ffa9c347"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082df22966d6a6c55ca54713f7180fb521ad1601010bda1f1af87739ba1b0e44e80ea84c8431ee0615517346b97932410ca977012a316263f78a9edf0a452e478a09da521cfc521edd35405d6ff7b10120e980b699014de05f8e600b437ffa9c347"]}}, diff --git a/txscript/data/taproot-ref/77faf5783504d2bd51c625bcecb48b8f87e8e165 b/txscript/data/taproot-ref/77faf5783504d2bd51c625bcecb48b8f87e8e165 new file mode 100644 index 0000000000..242948191e --- /dev/null +++ b/txscript/data/taproot-ref/77faf5783504d2bd51c625bcecb48b8f87e8e165 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4050100000060d5b89860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c5000000004169b1a9047cec4d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acecddd42f", "prevouts": ["b7923d0000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "523413000000000022512097f3f32bbea7bd397ebd6824dc6e34758f0b169a6c237662287beed33756fea6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93621b5bb1a2359f3a8af3fe21ba351d114491ae91346d1641e02870742c471727b"]}, "failure": {"scriptSig": "", "witness": ["6a5c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/78251c5d9b329e36203639010c03798c0e1dcf20 b/txscript/data/taproot-ref/78251c5d9b329e36203639010c03798c0e1dcf20 new file mode 100644 index 0000000000..77527a1f43 --- /dev/null +++ b/txscript/data/taproot-ref/78251c5d9b329e36203639010c03798c0e1dcf20 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c701000000252fad978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42f00000000e9e83d9b03a9ff6800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787f6dec441", "prevouts": ["e4a632000000000022512035c5e2b60676b638367c49c5274cc65e6feb881fb1407d2a5f35cf666d25b965", "0b5b390000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0ba1be0be881933f6293c21d0f105b497a44aefee74f972fd39705efeced0a4"]}, "failure": {"scriptSig": "", "witness": ["6aab616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/78536c856a97d639ec3c9e87656c03a486180cb2 b/txscript/data/taproot-ref/78536c856a97d639ec3c9e87656c03a486180cb2 new file mode 100644 index 0000000000..8c2535d7bb --- /dev/null +++ b/txscript/data/taproot-ref/78536c856a97d639ec3c9e87656c03a486180cb2 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9b000000002f21cb13dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9000000000819e17eb04c2af770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e707f3412a", "prevouts": ["4faa590000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "4d91200000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51709247cbe4599f1b40c45655be9c4524e18ab036a38ca357e6d7c21966c7872b33cf35ac099042702f37424b07b91f05c9425e6e1d18ffa37c0a546b69cafd337007ac6d9f1365651a4d55e6df0dcb109d268cc6c386b355a4997173bc95c886"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08297185a6c30608fff89dfccb39a96a02e4addd353a2af1bc7b33caa3a3ac07fec6e41ed285c226ab336f92f35d989a379104ed593ec3ff802714cc8e85daf0b3be26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}}, diff --git a/txscript/data/taproot-ref/78a8516593c8bad79e4092b1b3fc0a850a266c4e b/txscript/data/taproot-ref/78a8516593c8bad79e4092b1b3fc0a850a266c4e new file mode 100644 index 0000000000..5258931f78 --- /dev/null +++ b/txscript/data/taproot-ref/78a8516593c8bad79e4092b1b3fc0a850a266c4e @@ -0,0 +1 @@ +{"tx": "52d03179028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44a0100000058a0458bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9e010000002bb7bb9501169421000000000017a914719f78084af863e000acd618ba76df979722368987f336fc30", "prevouts": ["806a3300000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "b81e8500000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902ee2fab3e49e94f134e5eba454f125062d59ad39f7debc4b1de7b03393300b66cf60cbf310deb0bb8188a5f81dd989130bd5376f4b45afbd70b75330fcf47720df203f66e463a570e0d5cac4962b40a4ace1d328235d8871bef51e6ee71faa78a210d998072726a67258bc4f7f4a4e2391e463c0e74fc6a18cfb4bff2ae7475feeb1a335ae1912b8088f693b3f94d5a67aa12bc0e9385d33b009ea0de294c0ed04b64682814f89b5ce13df01f3a44b1f62c372febcb4c279268d070b842cb594ad4da7bd9fdd85ef65231d2b1283390d20d6d8d1b08e18563bd309482a7a16a72188f11ea140be5ae1ad90880159cf60ceff326288b068bb65d8a605b99e045cb944acf3a4d7f3ddb5e964bf9a11591f2d25cc4fd62f301a0bf03503e6825852503d2561cb82b7e2e07dc7ca798b92494503b2ee97881ae8c181d7234c3fa3b8479e6b5f654c640c1b3423adea9ffae983e0a596c4f42a365d65a87cd99e6eabe302500bb2e5440ec0103d8588670e268435443ec0dc87cd579529ede56b9f37a8ad91dda3529fc9eb9ce7f9c8753b1419c8a8a9dc78700861a14a7780f6908c0c01c4926cb77b04e45bcbe9dad07cbcb7daf5220dfdadf8e306b5e64b4eaa144ec4fac95b458388967abb4d113cb6cc23750c2044ee25a1ef9c962d2b73f37ca850055b2fdf845d3f72055c971d8501c19d8648073cccb1bf8b53ddbacd029a2ecf9a9cb2ed9dbba1875bb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb450430626a247d567d7470b6045f35bcd343227bea51bdb051c26a41fa3e304da7017bb5ae96064d7d19e957b5258c9c864deb4239d29676eb164d7ecbdb9fd5a354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}, "failure": {"scriptSig": "", "witness": ["4d09020cc1d2522adfb67359ba949637b69a52117483c8ee70f60244c4e7e2af5918779dfdb23910a8220aa324edf4cda261f8cc48fc6e9f19eeb1f689be87051c7edd6fbc70991c91a8c689c5c4e927169786d228aac781897812a927bd43aeb89bd5b8a3c9dcf1723660f7406bed9d58dd3d071ec3a18559214031574a26403dbfd7d0363b8259f06094912e5a1899414c93d94f7a0b85ecec0e49e19a3cd66d83b87583ece7a22f87843937f040306362b1ce585dd4a47d2c7fc819b498c10e67292a1445025e539f9ab035ad98077d68ba9dab40a602a3f771ac8683633fb495422fec4ffa5c0d0dbf6421dad60cf1fd65eef73f2d76aa5dae90775b20344f968134f1c5b354a74678d68e7b591c00138fd6e260958279d675c054ef8834bf9f924bb0e2854e39fb82c9b3df9cdc3b7f62a47a230d1eb97c0db53f9828fa83fa5b8f8604182b08ec5b1564013bb4226d84061257a057c1df65cd7010e4362980bb2e3da57a424888740d3a0a15392e0728b81832c6cfd88f6bb2e34494f4cb20956b7174016096d00a32108e8c9588759b424d70574b8f162a6e0285d087326e5d6b811f31fa119800561ab77fdad0051063a94fa81bb3b6bb01a93ae7a094cae3053ff110dfeefc2b7f44ed025b14d4f08706d90ad54accbc80c9d122dfe330c833125fc9471cc5b94fcfab6924fb896b339ada1cbbc2875667da1a4ef53bffca9ee6d409bc96bb59db7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93691af7e676faf0d787dd6628f8d068756dd2de2473b94e5aa63915f168764e8211ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454c3d251f378473e49463283b18fa00944324abf75c7e60d6956acdb0e7ed03a7354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}}, diff --git a/txscript/data/taproot-ref/78a85c295a5f5c62f56d7eba74225f31406a0b51 b/txscript/data/taproot-ref/78a85c295a5f5c62f56d7eba74225f31406a0b51 new file mode 100644 index 0000000000..f04bd4ec92 --- /dev/null +++ b/txscript/data/taproot-ref/78a85c295a5f5c62f56d7eba74225f31406a0b51 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41400000000eed2c5da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fa01000000017337ee03ceba4600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc71b7ed33b", "prevouts": ["8c5c36000000000017a91454957ff2b5c5fa7ace3c6fb485b914ecf6ce0c8c87", "2b5b12000000000017a91441ce0eb0e6e5800ced23a872818e5aaa63be0d5b87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1657142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["3dc5f8d29912ba73ca1abbaec21d76bef211e04def0ab69376a3dcc8bfffdbce1db6c1afd3f50a254197f695bd395be48e2c839bf1691044018d14a93d6a09b2", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/78aa0f27c839d5f0b6120545131237373c9ae941 b/txscript/data/taproot-ref/78aa0f27c839d5f0b6120545131237373c9ae941 new file mode 100644 index 0000000000..58e4ac8792 --- /dev/null +++ b/txscript/data/taproot-ref/78aa0f27c839d5f0b6120545131237373c9ae941 @@ -0,0 +1 @@ +{"tx": "238858b702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bca00000000c2cbecccdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce60000000068a68ee4039e927a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acdf40ad44", "prevouts": ["b94a230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "97ef580000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ef", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e76d3451324b9138e1a02bc99606f85398a5c02ad518c2db619f89974ca9e92c026557b708b5ff4838890b3ef28f2dfcc17fbcba41194ca68927d7f0eaa3f8db921261d9825d6464319e11fb6c7a9f7c01f613629293fb1fa80574c155a587736c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93693ba0b31f1a953c5b215b358b32e1b4fea0fd384922a25a91c841ceac44a754290840bd75c8ee6dcc19a553b4e3bda7516a8577ecf1c365a05a7b0ad0f101a1c215b4c606cdda8e0cd0631e1e6566a3457cf9b2eb8ccfe9cc1918e65b703d3f7cd241e6bbc5ebedd8f50ae206f1f82a1e41ff5c139455a0ddb0d368f52a47602"]}}, diff --git a/txscript/data/taproot-ref/78bb53d71409ce127d2a0ea2bb3fe8ab857c3db0 b/txscript/data/taproot-ref/78bb53d71409ce127d2a0ea2bb3fe8ab857c3db0 new file mode 100644 index 0000000000..283512de6b --- /dev/null +++ b/txscript/data/taproot-ref/78bb53d71409ce127d2a0ea2bb3fe8ab857c3db0 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127042010000002bb691cabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb3010000006a9750e360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707e010000007fb4f7fd04ef69900000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb3b44031", "prevouts": ["86751200000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc", "695c6d00000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "bbd7120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090273831a69d6f99c9e8b1965d77307084ef95fe23f8d4d8156e40e61f335957222af8040d693d19286ee11869b6d980cfadb50f278abcdd240d6a1dee48bb6e365f30dc45f61d5a8ea5f2225b266f79fa03ce639434bf2b7330e1d0cae71698c620ae5c1ee9c793dd8dd9a0f96adec0cf6f1716f4932fc7d535d27563ccc8c86709514fb8a3cf7d44fcae9c933134274d8f38889274b1372e468a7dd5b026591bf30764dfca47b04b587b5a257ec7c1f593344828c48332d95b6021ad6fce2944c4604a90d8890a921ca4b0641a9606db5022eb4fd2b73edccf3607aee01d10cbd0aad130f86860f45c075a84bba27eee6e85f585a8dceddff56debcaf93681b8397db0b8b9b16ec55d7407d7b05b9ae3bf6d13dabbb3dd2b1c73a1e3a9fc2434c305700cb2dcda6ccd2d8084740dc7e88b7ffabf0cb412adf7e9935da0ba6671e33ece30bb8361eba6b65519511cef1365ca8aa70a3f21a6b6500a931327919af0a5f47e8ca84b516b56bc8950174ffe70d320c59c64c6eb0968bdd56b1243250277b00e22e443a8962f54900a91f8041115156416ac0a72fb8c8f748e14042e57b05aef234204d7b829a7d28777deba1ae74dcee6f97235807653e5081dac6149d7be33b6e49def0ff8df238629632d5abf89a23b114284cdff13c7d5d57a77d7d53f2c8f59b75c9e37b06d94b1483ff70bb2461b1b3f03a4e9bd954ead6b300fdc09e2ca6a0f268f975cc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360082200294bdc578fc5250803dfab01bb18c9abef135300b000405e6b83754c366d64d66e5a8ef59726e977ff218232e5171732e5d132f479dce590bd8ea056135478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}, "failure": {"scriptSig": "", "witness": ["4d0902581e99f97f54669cc06c56921886c717256e17b36781163fa3f3ee36124505af852cabebd2ee1c05fc06f0c8d604d6fdb89c5e54c632a00bb96dcd5fe231b3abc0050c1e37150c3124182f9405bdf62d863557ecfa8329ee51f1aa0a483e8361e5b77aeaa4443487cec4c7f1e1d419815c150f800b633c859ef6ee36cc6dc0a7ea8da3aff4d2eb323527b9e30da37a30d484722c764fa073c591d19fdde1692c5d6ac204d4c3e4565110fcbd8a9928480f8f4160cb90480f4f52a3c09cd5606d2beca568663e180e4d6076bd7f1aa0414c97c0e1f9ce99fbf9f02ae7f915fe68da3fa8dc868390956de9885978a4a44ff97c2af0b02f9d498e59fcfff9ee883008d45007170a48b108970f09da08ab18b535d02c648fa7b6c6816b163c609ad8a05116b74e7ac04a72ce6cbe35404f90f91c84c7fd754c82fa0f19b2353dbab60806e943242017e7998c0a8b64287b4f909283dd5d5c5b70713c09065865931f8603c09d2f5ed193bcb6be6897a7b1a3462ceba781e7bdf0a7ff3fb56c9ee933dfde0c014c4f1b10799e25a00242f06c27dc4e5ce6bc99bb70afa35522cbf36d7c9202909e4ba63ceda1e3a671bfac269d719896e91bc5707a72ae9520fdf3362c4e0c9e01f9f41a18913096620aee35b7a9c2380044b6e13ea9cfc8d722b2349ab33f272ef6f15526396fcb5c1a8fa9fc527c301018b24d935b9cd9cc2fa733370c9a9712513041587561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936421987bd13df4c70e6bf953d88dd086caae9ed404be58b48bef1d4141595753e11c8e78922f12cf5b391747592eaf9e84d545161f4f09ddc8c51091bc04ba49d4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}}, diff --git a/txscript/data/taproot-ref/78f579fb1bbed4948a321bcad1a70116b995076e b/txscript/data/taproot-ref/78f579fb1bbed4948a321bcad1a70116b995076e new file mode 100644 index 0000000000..b940880d76 --- /dev/null +++ b/txscript/data/taproot-ref/78f579fb1bbed4948a321bcad1a70116b995076e @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf610000000058cecab6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c12020000005cf0669103c7c9af000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e736847739", "prevouts": ["b31f680000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "09424900000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902968ce8fa391872c7c8f598dbc24515a2e1ed3a9223392f7dd5d21cc8694cb6dbbcf16537d34fd537904562f1304b6b6dfa3bc2c76930c5ac13c0120088b526214161fb6edf3d22690e1490528f5f291cbc1fb9299ce923a65e4c10dbfcc498d242361700ad444b86097c1dc0c1e7b14160d977ba5df782de32e0128145408c6f8507486013f59b8bccaf02b65d6fe4ecd13fd250ffa6c53a7c730ad3e8f685892d7a7581b23db6a11263ac0ff978ab7d7aee07f2b6b3de2155164b507e962c3d8a4f83b1112eb706139607a880324b7e98f57c79e69d52a14ad3fc121c74eb4704aa1f52d919e987d256cfae0389ba66aaff2bbc1e68f9693f689b40149cc01a74f20b433316062f43763850bfef8e1f6d5b1bd9ecee1f15a8fc1430216aa0e95c546f38afdaec91b97ac033d03502666a9721a20eebe063eb9abaadba33ea63c041668d2b82cf50d29785484b88cc043e929c614f6876384963f989167b6260b61fe596964a1e2338c10d658b885980f7e46dc9ddb72c288cc41573e199691c637b2320dc57eaec9e642f7a2abe37f10ecf96ece71017c6f30131544209d34a06086c91973bf72642f12409889ab4633434abca8fca74c0424e9d13fb516bcf9c662d572752b08ddaa2208df31e200e830f7d98eb378127f1643f3168edb7b038c9410bab5f8417b5f1586093f6987027536a7f189a74c34ba2118e1ac1ac2be847c87dba2833491f7562", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c1b5bd5af873b3cf6e5a90ed7dfa03da09ad4c4f61aedb4357c87f13244d0d44ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2a28c39ce330a19a0d6c22ddc640bc3609271e6194de475fecd1ad84a88d361935a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}, "failure": {"scriptSig": "", "witness": ["4d090297fe5071ffba2c2a12b64809619052831713fd9ecc38fc6e5093d9573f9ef8ef7424ecf7a39c7b8ddcfc80fe0efc9444064af0f0255fdfd318e3e893576b57c61b92e02d4bbeffc039babe9a7c0b9e4d67f7f35cc14081f35b87794151006854c0e3df36ac252ddd243a8e5175ee7779b7741e17291ee894478134bcd22f81d3fbffb9fb71eeca5c1d26ed7d66b8e089d44748274d94626f73478f40ca5761178772a0dba3769df491488fbbacd04b3811135700d60fcf444b02f6f2b79ab6a4f36f1b7348ab022fc8d463818d0d68e672e6c93d7ff1b6557763169065f05351e8273fe78872b85d8316a04460789d3e7963a69a82d3817496e9993d4629c2c2ade56a343b904f4e2ab8b326ec729aa46aeca259bbc31f60702676cacc799f32c7dda8bcf63b76a957924a590e7427fb021f750e88451589bcaf8e5a102a13601492c55f6eeb426976d6e32f682b85aadcb5f5f197df5be2f484aeb113fbeed29f0362f1bedece52fffc6235b6bede7d499e9a6b0d73469cf4d41eaa491e2c4e20a270446b18df776e767cf546ad2369e39bf80f808bfaefb4f68528f09e27b7a6fbc6211c01cc2748b55497c8cd9f1f94430a327c9f2a83cec9a758b455eb95a4ed12e2bd8b6bcf1f8360f35635ea8d326fd9878f13102f4bd6910ffc5302ab1f7dcdf3d88f7461eaedab4580bfb20b8a0ee31d6f26d28c68f6f2b770e10b5487c5e0f9af9c34c7037561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d511ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004522ebb88c16ebf61dfdf766657f947c6b679bf36be3a1118c2e7b2b24c8fd5c2a5a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}}, diff --git a/txscript/data/taproot-ref/7929ee70089306f9173670db39ef247d71e6d01c b/txscript/data/taproot-ref/7929ee70089306f9173670db39ef247d71e6d01c new file mode 100644 index 0000000000..75d007a18f --- /dev/null +++ b/txscript/data/taproot-ref/7929ee70089306f9173670db39ef247d71e6d01c @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705e000000007f3b89fe60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127009020000009be7daae0426b41e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7968bbbee5c", "prevouts": ["67bf12000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "58640e00000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d468", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a89721c820f4bdb361f8db64c173640a0ae9a66952c98750353100cbbdfa52ee05ff666526b724612289f11d9af684c97588c9b58f885be5f0bca0261c5a78c938b5973806e5396d9f6a2ad240022103fc2376d5af9a7129252a47c1a6405aad5a470b8497850c3a230fee464eb343180400453804118582df887251250b2f1"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93632e5acefd4c8c7967aec45b85cb0451f2bc6c0507eb8db9d83e69d481800454c36ccddef3149683af65c31c85a3c06583d8e56fa5e9b8809ad6476a55251e65fad1faed220136b938a4936a71b98f5f9e86de449242d6a82efdf7a3adba2ae62745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}}, diff --git a/txscript/data/taproot-ref/79348dfc973141bd7bee5f470ac28ffd56e6591c b/txscript/data/taproot-ref/79348dfc973141bd7bee5f470ac28ffd56e6591c new file mode 100644 index 0000000000..1c3063a819 --- /dev/null +++ b/txscript/data/taproot-ref/79348dfc973141bd7bee5f470ac28ffd56e6591c @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d4010000004448e7b2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7e0100000089d641a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a0000000083a09fad0354caca000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acfa030000", "prevouts": ["5e70100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8e686e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d1414e00000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "e07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fadc06adab560b35cb72027d4fb118b7ccde081e5b76834bff6a0280f6d09fe7dea410273431f29264d27122ed0946ba884bbeaa1cf1ddeb7776ccdcb7bb2f1db0"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652e908c96e49e4bdd4a9a5cd975173f05101b0d874a2afa662ca1474523c4400dc06adab560b35cb72027d4fb118b7ccde081e5b76834bff6a0280f6d09fe7dea410273431f29264d27122ed0946ba884bbeaa1cf1ddeb7776ccdcb7bb2f1db0"]}}, diff --git a/txscript/data/taproot-ref/794d2929ccd4a9f38151fa274b7bba0a898aa30c b/txscript/data/taproot-ref/794d2929ccd4a9f38151fa274b7bba0a898aa30c new file mode 100644 index 0000000000..1159c4af5f --- /dev/null +++ b/txscript/data/taproot-ref/794d2929ccd4a9f38151fa274b7bba0a898aa30c @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf86010000000341de5d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46b010000006e8ce12b02cd14ac0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac61030000", "prevouts": ["0f05780000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "26f63600000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c36ac07773bbf46c88fee963ca0e4e4acd235bc6e1c8e4009a2ad8ce5db6e1e1e8615c203dc23cb029e7db21a2c25ffa1e58a217fce4f910f96298df6e880ff594fdda965251e4b25324fb25d524f5afff8c7c52a3da7c11a63e869099762eda71455bb45119ec6780a0bd8830f6e5001315edc9a69a5b17e492d09cb408a943a1375e317b16913793017cab657fa068bd0c62abc4c87f853f6b530048a7940352cf090a054588d89de8f408e33fcdaf02e97783d5331ff41f2699ee40d724c1509b0829671152674c6934eb690ca8f6ada1b111d9fd4b6b043a4978f5d9fddf443e1cc08a00649ea2341ad3a3d2220d6b91e63f28567fad751d788441ad53c7c41db5335a4b6a7a5b497631f1734f57f8c3477b215ea2788e234d9e785147df5b043d75b387ea6d337a75c2614816831b3344be2f0d6f35d7b6cbb950fc0e713d4c7d90180fbb3b3f81515bcc6c302e5b45494a81f0928942274dacb4277e5d99ad80699999551b86611f63047eb490dfa50b0b6d3cd2185920fa7c29586b65605164bf2b3743a9770fc819738f427cafe01266b55eba21d8b7e17229559861b4c2ed27772ab8cbad46f12f89eb216d4c536fa28364964cb93a729de392ae1599300eb61c090fb0cf80958ac7c6def73a078f26dfe5db4a4b46433223080e657d3406d5ea39fa444c7321536ae4fe24abb458102fab31f5bc57cb964c69fb41625ef10fc7a997aadc75f8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900457103c9e8ba836cb8a4e14cf2cfa4f8a9b341b4f4aa6fb02102628b5e7003f327891e44dcd1430a53a9228b1d4df01e5c5d5af3846f876ba8dd78ee7e669e7153a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}, "failure": {"scriptSig": "", "witness": ["4d0902abc134d4a183d563244ab47c2e6a1f7681b5552650c4046f01d596f54eabda0a73914b5ac396eda2cbf3f7e4b7ab2e96f729e23bc88096b9a99b041b586ca9382dc1f96212aed6049d2c0d3ea8a550fc7bc7f59efca0d793894b829f1a71e2f57f7f2d0678b0c08ce24ea177c561bd4f797ca17aad2d41e0db9fc5e37f4d81e4ddf045d5820d91ea58cf83d716427a6642407d61f030f35982be61d5dfdd1c5aeeb50bc2315366fa90ffe1a3a757cec691073fbadf5808ebdeceedf64a19c0c08d7c1160867726d9c396d2dc5924bc87d54c9ad2c2b327dfc3610b843bda05f962d1f71f831aa11b2f2c07d9656765af23953eacc4a54055c17c4c4efa613ae4d3837365515535f81e29310e8fc401a34920016e92d64211449eedb39e3bccc8f34938159285f7efeae16f7e17c0d0b947f8f0af51f36968cce2dcf10e6a9ff995df8ff20e39bba09cf69bbe4dcd3e55a9e6cad74f676601163992779e2069f591355edaf5f5efad07d75c7d6ef094cbdb713500d6d213941919d92a107fb4f55bc9ec469dbaad2c96371adb1c5d1b80f68598526b996c1fe60cfda7787fff600e27d11d97db37965a5d5d765a60c31ef25ba58f7e63ea812d85de17b25f117568c7da369c1e7a4ea1d7e2b5f66607598ca1787a1a95249ff7a148f2bdb3d475e37fb968d36d4f0917f5b94f5fef2bffb99a8688f72036b2b543229cbbd0bbaf986ca7c768a1e9da4a7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5129caa746058fefa69912501c9b6f792a531f2cb30638f1f343d3625f0a93b066f288028cdab461d62f9273620b97315e6e9af9458f777a616c1bade2d3f6a89e"]}}, diff --git a/txscript/data/taproot-ref/79693f140367ae963c396d7952f2b07e3e603755 b/txscript/data/taproot-ref/79693f140367ae963c396d7952f2b07e3e603755 new file mode 100644 index 0000000000..6f4aa336d4 --- /dev/null +++ b/txscript/data/taproot-ref/79693f140367ae963c396d7952f2b07e3e603755 @@ -0,0 +1 @@ +{"tx": "3995509b02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c05020000006f476edcbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8f000000009096b4e5019114a90000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000", "prevouts": ["0e825f000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "336a680000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082784ae775de15fa9e8fc81d7676ee4bb7b8b5e55729a9bd981757787c0c2477c76fd75cc9ac1e6f185878d252db6c7bbd874f5ae03fa9961d4f4a0208503b0750f17ad4bbf375bb62f626ec8048d4347cc1eef977780228a6d2fc47294088d561"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ee8e66f30a7a87e143e326dc67fe32abe85ab342f564e4c116c01cede66b1fe20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e192555fb599a2fbb7b206b08358b85e40a527ad21aa064f750df81600ff72cf4ef17ad4bbf375bb62f626ec8048d4347cc1eef977780228a6d2fc47294088d561"]}}, diff --git a/txscript/data/taproot-ref/7988534604fb11aa559428f200cd7631d266dcdc b/txscript/data/taproot-ref/7988534604fb11aa559428f200cd7631d266dcdc new file mode 100644 index 0000000000..2961c0e170 --- /dev/null +++ b/txscript/data/taproot-ref/7988534604fb11aa559428f200cd7631d266dcdc @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff901000000939dafac8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47c01000000d2c3b2ffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2801000000052131c304cb62b800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c6010000", "prevouts": ["1f9b64000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7", "1e9b35000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "49a720000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "267d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89ed12ee2db6918b2bff03768a1c947d0f4fb00a38b9989b1add1650628df27e9913d4be53f363cb6dc14d29c1d7e4819045cdc001ac228b3b700074691e2599d91e402d116972020cc4db8f7e1431e7a7416668817d422dd270400f40dd8d238"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366c2c3e102c733a0311253a9baff0bf90ae1d58c1cd06313c904a26512d8ace0ad3613095503852f968cf254efcb9d0b7a7155094671c0665bdc16a67bf9a23af91e402d116972020cc4db8f7e1431e7a7416668817d422dd270400f40dd8d238"]}}, diff --git a/txscript/data/taproot-ref/7993ab06fc93824943100f468b83a388dc8396fc b/txscript/data/taproot-ref/7993ab06fc93824943100f468b83a388dc8396fc new file mode 100644 index 0000000000..0f2b1b2502 --- /dev/null +++ b/txscript/data/taproot-ref/7993ab06fc93824943100f468b83a388dc8396fc @@ -0,0 +1 @@ +{"tx": "71a4ed46028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44b01000000ec698ea18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47501000000cce1158c0485037000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac31010000", "prevouts": ["8ce9360000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5f533b00000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_63", "final": true, "success": {"scriptSig": "", "witness": ["0bf62e3fcb8cd9b3b2fb1feff203fb325907918df0fdd8f99feaa6108f15940b66eac66989e3d8bfc953f821791b0b5ddeaccd955cc2692db8b0d8dc0eb65838"]}, "failure": {"scriptSig": "", "witness": ["d31037a44199af88171941e79afaac6887d8a663590b9ff482039e14b6ede2265ad2f7de51506a10e124a0336396fc476eee00ebc8b99d96802c538dd19f7e6a63"]}}, diff --git a/txscript/data/taproot-ref/79a78205700940deac5a3af06b37f7a837ba5d0c b/txscript/data/taproot-ref/79a78205700940deac5a3af06b37f7a837ba5d0c new file mode 100644 index 0000000000..805619ac25 --- /dev/null +++ b/txscript/data/taproot-ref/79a78205700940deac5a3af06b37f7a837ba5d0c @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0b00000000841f9a698bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d301000000542e177d01f3141c0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce455ed3d", "prevouts": ["95cc5a000000000022512089cd9bcf9fe9207377d5b979d86bcf752d8d9dc577da80e024c55776b1ac583b", "47af310000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "227d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c13c6885c53a07614131d749dc0b9c4fac4cbf357599a76450ee1c7b87f78943dc4c18ce03381be5d83370dbaee0482c0440aa7aa94902a00244e0237bd29478fcb15428af69077ee4e47ddc8bd2adcf7d97a29fc56c75a24a213a103a1e3586"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e86a45def9951625cf02c88598f8616d12bef3cc01ed824d79a70edf31b7fbe0e1a4a9bce64ad1fc5af22ad5621933415c83e23766bbab20239912b691ace9dee2"]}}, diff --git a/txscript/data/taproot-ref/79dcbe312ec0cae55271acea3fbcad77eb51a258 b/txscript/data/taproot-ref/79dcbe312ec0cae55271acea3fbcad77eb51a258 new file mode 100644 index 0000000000..41f2478fe7 --- /dev/null +++ b/txscript/data/taproot-ref/79dcbe312ec0cae55271acea3fbcad77eb51a258 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c910000000057056869dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c47010000003cf378558bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44d010000006ea78b090428b4f3000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac70000000", "prevouts": ["9f7a60000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "8619550000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "478f400000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d54c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365edec6927239e37481c871e98a308ae148761fbd82cda43b44eea2241bece5c01ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045135ed0e678ad02d8eb601751aa1b9acf14c9c27e67d62b009394546cc2bb02284b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369dd67732c9a7b3d13cebfee85233046128c54acdc3b639bf5b0c42b2ec55215b4c2f2200f850d6a1609ea6f282082fe51ae8a55145cebb4c521120909a7edcb74b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}}, diff --git a/txscript/data/taproot-ref/79ed5f67b23082b621f1d3d307cbb3833df70b36 b/txscript/data/taproot-ref/79ed5f67b23082b621f1d3d307cbb3833df70b36 new file mode 100644 index 0000000000..25f0dee513 --- /dev/null +++ b/txscript/data/taproot-ref/79ed5f67b23082b621f1d3d307cbb3833df70b36 @@ -0,0 +1 @@ +{"tx": "9808329802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd90000000006966cb4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0b020000009599b4af03d11683000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d2000000", "prevouts": ["6e94630000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d835220000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "837d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e6193e4630789cbfbdcb7d6fc995ac4f032c6d5611c1f6b733abe8356e59ddce06294a5d2648496e5016f850eddfdf01467fe69221e8567db6ec356a8117d8a748163db171dbfcbf374971659a5a65d0378eae0ee15db360ca8cf80a8c2e13046"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d4241eba4335af55cb703ef1b6547d641330ec95ac5c4cf0d3e8e3ea3eadc07c09d3f278379d69ec93b9031f683f10c8ab57e2d08c050c4811cb81bd332eb9e3ff15e37d03bf407745d47da370f693bba1bd1439d95d9059575aa23ebc3ce6e3"]}}, diff --git a/txscript/data/taproot-ref/79ee5f66d93ee0d29f8b42ccf65fc760525867d6 b/txscript/data/taproot-ref/79ee5f66d93ee0d29f8b42ccf65fc760525867d6 new file mode 100644 index 0000000000..7d5ba81f35 --- /dev/null +++ b/txscript/data/taproot-ref/79ee5f66d93ee0d29f8b42ccf65fc760525867d6 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706d000000001f9bde91bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf790100000000c42cfc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48601000000dc5b1c9a012caa0c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc786000000", "prevouts": ["2d69100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0c5769000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "3b5e3e00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["8a4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a508197ed6624452fb9289507f9cfe4408c1b7912a8bf4cd7fce31e05c3b62298751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d56e427c91532996b84ed2c37f8a26be8637de11530a49bfc255181ba6103e3464915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93655f123e6810ac5f5b7b4df9ac6326a0dbfbe957e974eedae7b2682ba3a8c02e5572db529171a47fc33c2e4ee960be7fb9400c27bdb6fae7dcdae272f7c7daab09b045cee6f1e54629d213b8dbfcd9de8aba2dd7f34fe21c75d81b8576e463c6b"]}}, diff --git a/txscript/data/taproot-ref/7a043102c33d83ed36e9879386a6e618668535d9 b/txscript/data/taproot-ref/7a043102c33d83ed36e9879386a6e618668535d9 new file mode 100644 index 0000000000..331c0bb3bf --- /dev/null +++ b/txscript/data/taproot-ref/7a043102c33d83ed36e9879386a6e618668535d9 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb001000000f97f388a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702801000000697c5d8a043f238c00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87fe000000", "prevouts": ["cce97e0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "fc540f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f8", "final": true, "success": {"scriptSig": "", "witness": ["05e31890e2496566adf98bd934dd029381da0fc49f134fcdb3893d4a3c0c03095ad365334618f693e153c89ec07a0a13f93331a6f18873bd6f5c5d588b8e319e81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["33dad7d4828eb94cd241bcfd765c1c0f883f2aca3617c31c021d1b764e328c5baec790392ff21e9d2fb5cbc3f82810cf633a4f8689edd9643e8db70549c5125af8", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/7a111af866866f2de4ef478fd546fb1c0fc25d0a b/txscript/data/taproot-ref/7a111af866866f2de4ef478fd546fb1c0fc25d0a new file mode 100644 index 0000000000..f5c2728280 --- /dev/null +++ b/txscript/data/taproot-ref/7a111af866866f2de4ef478fd546fb1c0fc25d0a @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0a000000000dcc735dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaa0100000058f69bca01f683110000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7af77dd40", "prevouts": ["61a26c0000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e", "cdb27100000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["304402201c9d0f0e15e942865c85a4a840ed0881e1d024f84c3eb034100f8b0c396922fe02201a02f3bf3fb0c6c33081c6936c2e25f47c9446461abd965f8639665e5f44a85402", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["304402203cbe8db24b2fdae8be9f184f148d12841ea66b8a4ff188602cb2fa179195940402205114fea29a22a6f40edace5f804d1ded0b7f0f10bfb2123cbb74b93a5862c28a02", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/7a1820d857c8a49a2db73ca33ae771ff2942dccf b/txscript/data/taproot-ref/7a1820d857c8a49a2db73ca33ae771ff2942dccf new file mode 100644 index 0000000000..d50874b73f --- /dev/null +++ b/txscript/data/taproot-ref/7a1820d857c8a49a2db73ca33ae771ff2942dccf @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5000000000b2eddc38bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9b000000005a19fb67020823d500000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac37a54057", "prevouts": ["fe80540000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1a6f820000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["fe4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93679936465fe465f0d401827e55c2317c08ad696e5227da5899b92494a3d57c5ba365bb68c3eae5e6cd9b20289e581f52d4e8c0cb4ba58bcd8be9e67bc80fb920a1e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365bc17b4d65ff6300e0318663c163f0b05a2443748654960ec7f2fad9f3ccdb63dcc932fa7eab9febb69f8eb1775db86ae183d64bb0b86855f9228e743b2ec6db917e8250b412828d56f092e1d9ceabdbedccb5671620a7e05a1f5a122fcf72f11e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}}, diff --git a/txscript/data/taproot-ref/7a490995df2d5f17d023de70297a3ccd20b7e9f0 b/txscript/data/taproot-ref/7a490995df2d5f17d023de70297a3ccd20b7e9f0 new file mode 100644 index 0000000000..afac7d4a20 --- /dev/null +++ b/txscript/data/taproot-ref/7a490995df2d5f17d023de70297a3ccd20b7e9f0 @@ -0,0 +1 @@ +{"tx": "50c82e5902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc301000000530c23e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9f000000006367e0c201cce1b500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac97445a20", "prevouts": ["24234d0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "0cba7d0000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "947d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa7085091e7b587d9e3d903161356c0634077d7e43e5aac1c0c25d5c3c805eac670235be472b05f11e998cd7dc8896eb16b23bac01933cdabddca8bd45937e3454"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936417d2d865202d20eebfd4aacf46381b0ece3fddc39ce14b62446cc40f8d1090e3ee723c85209fe64e13625f9e221aa1a5a0132ad156eaddb44490f9df3bced660235be472b05f11e998cd7dc8896eb16b23bac01933cdabddca8bd45937e3454"]}}, diff --git a/txscript/data/taproot-ref/7a4a6b8236fc89f7d9e11728eab5f34c87b831ca b/txscript/data/taproot-ref/7a4a6b8236fc89f7d9e11728eab5f34c87b831ca new file mode 100644 index 0000000000..9a4542c1e2 --- /dev/null +++ b/txscript/data/taproot-ref/7a4a6b8236fc89f7d9e11728eab5f34c87b831ca @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41b01000000b82575a3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6501000000474aeda00135f745000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47876fa28731", "prevouts": ["0e6e320000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "0ef12100000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93698751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d59dac82751ef42f4155e8d0286eb609cd4bc8c8b3be93c107754fe282612bb362f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f984e6e7c95b40499dfd8f685cb7972c8a61cdc9574ed2e0983d5b6eeeffb3572402ee5f7d01023de35bf8c020790747879409f1771ca1b4a9af174b095ec7ee5aa467dfe2257bccb94fb5bf6723e840de90a3890266560a9e3d72c84089f55cf37d2bf9ac9d65f4f9542d60f6497573c04b4d7313f44a5c611386102890a1c"]}}, diff --git a/txscript/data/taproot-ref/7a59b37e047189062f0abaf0d629290ecfb35f75 b/txscript/data/taproot-ref/7a59b37e047189062f0abaf0d629290ecfb35f75 new file mode 100644 index 0000000000..9bf6408aa5 --- /dev/null +++ b/txscript/data/taproot-ref/7a59b37e047189062f0abaf0d629290ecfb35f75 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4620100000077ad6e89bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2002000000f77fe99c020797ad00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac10010000", "prevouts": ["0b6c38000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a", "12fb7700000000001657142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "247d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fabda2774425301130c379b9a863bac2b926fc4ec0dd6af03d15dab43b60e3a64c440784f6f41cc1ae323b623cf5dcb000da45020704fab66b6b5f2ff7d67a93a3"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b9b18a780ce64b599d9d3042fe9b5b93046b018637f9f8cec8ef00735e099ba32f1db23017f271ba09e9de40cbf6bd4b292cb969b1168724d03b4425efd5cf153506420e788c3ffd3d8d88ddb9154e82106737a8dd2b5d0940daf68f275cd0d7"]}}, diff --git a/txscript/data/taproot-ref/7a69a216cc5a6c99a19546872d16973b864b8ec6 b/txscript/data/taproot-ref/7a69a216cc5a6c99a19546872d16973b864b8ec6 new file mode 100644 index 0000000000..c57f802603 --- /dev/null +++ b/txscript/data/taproot-ref/7a69a216cc5a6c99a19546872d16973b864b8ec6 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce501000000881946a160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270870000000050efa3a7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb100000000ea994684043ae79000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487046fe641", "prevouts": ["b8fc5900000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5", "d298100000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "290d290000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "3d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa671c5f6e3fdb2cca9ff2c8978272a7c72309b5e793932f9bb10a0961dd619da6701c89cbc41056f58ce11974b5756eca381e306e17d72fcef5e58c3aca02cf1415eb41ce20b61903eca7e2f7903a7c5f76d50ccbb22a22a302188dbad2e46b28"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367a4323bca4261be341492d2c8aaea5b9c8cd338f75ff3ca656464aeff6e26a7ada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eef9a48fcabec25982850a496e19df71982d596f167265e15d1ec282fb30074b91cb891527dccd7fe22077390053ac1c45ab6e7110116df1a30c9559411f432f5"]}}, diff --git a/txscript/data/taproot-ref/7a6afdaaff4560a33eba5ebd9df662b110b72dc2 b/txscript/data/taproot-ref/7a6afdaaff4560a33eba5ebd9df662b110b72dc2 new file mode 100644 index 0000000000..df164b4594 --- /dev/null +++ b/txscript/data/taproot-ref/7a6afdaaff4560a33eba5ebd9df662b110b72dc2 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42201000000a7edade360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702e00000000e8af8ed604cd3f4100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388aca7030000", "prevouts": ["d6d3320000000000225120bb5a47f5af791bd0da95f040450c31e81733ad36d8a4b487e3e6f1ab189dc604", "3056100000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dca1b743bdc65e78d5c2b60771c4ad4566262fe3c3305a8b61aa9fbf6a15bbf0"]}, "failure": {"scriptSig": "", "witness": ["6a5f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/7a87119e2369843226572e9e9603e14022ad565d b/txscript/data/taproot-ref/7a87119e2369843226572e9e9603e14022ad565d new file mode 100644 index 0000000000..6b0901b6ae --- /dev/null +++ b/txscript/data/taproot-ref/7a87119e2369843226572e9e9603e14022ad565d @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bce01000000e9160568dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7d000000004acaea1b0404d97d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374873d020000", "prevouts": ["7f13270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "37b0580000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["624c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f393068994750671244e9a386d61bbc7bdd03428d67a6b3b3603ff438afc80a6abc42ab3738335b78a2a7135de763706b017ef32cb75bc24ca1210f74f6e5b7b3fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a90fb3f53527a925db2b4d49a3795cd34d4dcf648c4b3a4a108990f2ed12b180a28c39ce330a19a0d6c22ddc640bc3609271e6194de475fecd1ad84a88d361935a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}}, diff --git a/txscript/data/taproot-ref/7aa3606e89e98945870fd6072bc248da2ac00194 b/txscript/data/taproot-ref/7aa3606e89e98945870fd6072bc248da2ac00194 new file mode 100644 index 0000000000..dc3e167371 --- /dev/null +++ b/txscript/data/taproot-ref/7aa3606e89e98945870fd6072bc248da2ac00194 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce90000000060bcc3aadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8b01000000049096870147a1430000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d32e1233", "prevouts": ["141a590000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "33cf5e0000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "3d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93616f1c2cf89bd49cb1976d122ca27f5e410eace75a032574b33edbcc631c7f3564ed4022c883bcffdd4981a43d80a989f638bed5cb710560195e12f06d5f3803c1cb891527dccd7fe22077390053ac1c45ab6e7110116df1a30c9559411f432f5"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362d14cd9d1df0b21fbc10702de522193e26661e8ce0c7001bc045f1599fb03383dc8c5662064e2d9613ba0f54feafa13b4a8d810a28ca520b1cd1b9628c3c1add15eb41ce20b61903eca7e2f7903a7c5f76d50ccbb22a22a302188dbad2e46b28"]}}, diff --git a/txscript/data/taproot-ref/7ab6a9ca3af298309556e392c5a2145121ecad20 b/txscript/data/taproot-ref/7ab6a9ca3af298309556e392c5a2145121ecad20 new file mode 100644 index 0000000000..2b380f4207 --- /dev/null +++ b/txscript/data/taproot-ref/7ab6a9ca3af298309556e392c5a2145121ecad20 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ceb00000000ba7843f08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b5000000008141d6b70267698d000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966df5ad4e", "prevouts": ["fc6750000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838", "81bd3e00000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "b47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367e7b268f617d00298f513ed9d959e4853656836f4da5bc24b22bcfc49034b4c690a6d927376acace3683bbc4ff9f5d15a4c9ee2ad4271a1fb38c29668c3ce61898ae4fb28ba039f9030001532aa52d54afebb8b1d186c7283d6707334cdf0cf3"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8f8e322f728f7f2bda8f14cbbb71f9286e41438f49abc55856c1a694b654384417e736a60655dc533a38837433a3a305c9a2d5b0314030c91796018120c3e9a44"]}}, diff --git a/txscript/data/taproot-ref/7ac66a26b371216e55464bd620f00f9b3cabf539 b/txscript/data/taproot-ref/7ac66a26b371216e55464bd620f00f9b3cabf539 new file mode 100644 index 0000000000..41971f6ee7 --- /dev/null +++ b/txscript/data/taproot-ref/7ac66a26b371216e55464bd620f00f9b3cabf539 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ce010000007fec828bdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b09000000006f3caee503bdb35a00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac0f030000", "prevouts": ["950536000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe", "2df02600000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["86", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366c9ccce34c09bc03bb8aaff06a11df09f3692c1f74f2178409984d1ab3c04f3715c685a6e20a464c0638846c4feb0cc1ab19a0a1d3cef03660e119c827d202a5d33ab5c29645e0220ea4ffd8cb7e67404885cb8b0cf94872336c7b06d59c3124"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b05e9ad3756e137278ae6e6e7c10c62cfba95395c884b707ca96162ed87516a80d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3b4167115de6998fecfb714975bc270adc7a6998f06c7ef8576e15f157ca8963750636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}}, diff --git a/txscript/data/taproot-ref/7adcfb6ec993d4f55872e19410191727163f6958 b/txscript/data/taproot-ref/7adcfb6ec993d4f55872e19410191727163f6958 new file mode 100644 index 0000000000..05a0244572 --- /dev/null +++ b/txscript/data/taproot-ref/7adcfb6ec993d4f55872e19410191727163f6958 @@ -0,0 +1 @@ +{"tx": "b50f094902bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3f00000000c673fec7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb80000000046642ba302baa7c5000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acba7f4b39", "prevouts": ["15be6f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b7ea580000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d868", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362564fd3423e77940cb8b994060b12804efb6a1c8e075c570e076404309a24192908709641cf32dc4788f906f7e3621a0528df09509ddf1e9982e4479aa4b5d9a6e41ed285c226ab336f92f35d989a379104ed593ec3ff802714cc8e85daf0b3be26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a3a181e1fb4c9a4cc49dfa16bddea418e5b2b086e1a4ccfab14939545a03d5c99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb406f18ba19de64c771db55f5af06ee3412ffaea1fa921290752d742eff6a1e67f7007ac6d9f1365651a4d55e6df0dcb109d268cc6c386b355a4997173bc95c886"]}}, diff --git a/txscript/data/taproot-ref/7ae9dff22041f4c1fe093655030d83341a775789 b/txscript/data/taproot-ref/7ae9dff22041f4c1fe093655030d83341a775789 new file mode 100644 index 0000000000..bf9225f029 --- /dev/null +++ b/txscript/data/taproot-ref/7ae9dff22041f4c1fe093655030d83341a775789 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfef000000005d9bce2a02f6057300000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac32cbb850", "prevouts": ["95e1740000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "137d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cc2bf80b2db027afc6ff7c1eb2245c9e3cd90dfd08684ab7b931baf85a586a71155f23cd39ff67d8b5a6775be7b28a3d1b06bcb926a8f69937c20b78b14c2d485d0346f0de7f7080f7758bd86c81c482f81ad0c7703311f4b65ab9d7b77c9f00"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e048ad2721d56e7698732cbf102ae8e792035911a0ba8e4825f0ff9fa3590c070ac5ef61da5659d8214c667aee1dbe4febf87286965cb6fe696f5c1a17be3da5155f23cd39ff67d8b5a6775be7b28a3d1b06bcb926a8f69937c20b78b14c2d485d0346f0de7f7080f7758bd86c81c482f81ad0c7703311f4b65ab9d7b77c9f00"]}}, diff --git a/txscript/data/taproot-ref/7b1eb9664a41baa7f5e742f91eba9581bd509407 b/txscript/data/taproot-ref/7b1eb9664a41baa7f5e742f91eba9581bd509407 new file mode 100644 index 0000000000..47809a8bf3 --- /dev/null +++ b/txscript/data/taproot-ref/7b1eb9664a41baa7f5e742f91eba9581bd509407 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdc0100000013b74e82dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3900000000fe9609b5020f333b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acd4a59f23", "prevouts": ["e1ae1e0000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f", "18ef1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a0", "final": true, "success": {"scriptSig": "", "witness": ["e23b393e9310418c33887f2e5655dcee6a8f5513e26de88ec8d0f1f46471ae2781421200609ba458fa40e41055eb8b7285d8c9465d511e0a3d537e272028a38682"]}, "failure": {"scriptSig": "", "witness": ["7d7da58583662a894d67136d1b64aeeff2e3ba3e8d136f57b0fba2e14bc974220278358ac13a9779cb9b8c866e4b1fee40a0b30fe6a7b4abab9b513c01d5d8bda0"]}}, diff --git a/txscript/data/taproot-ref/7b242c6392ed925c411f5a03c01a5b224498873d b/txscript/data/taproot-ref/7b242c6392ed925c411f5a03c01a5b224498873d new file mode 100644 index 0000000000..e514df880a --- /dev/null +++ b/txscript/data/taproot-ref/7b242c6392ed925c411f5a03c01a5b224498873d @@ -0,0 +1 @@ +{"tx": "4f48ddde0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704f00000000ab8735e8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1702000000c289f8a9017946670000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7cf020000", "prevouts": ["0633100000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17", "bd2f790000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "d67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4fd5de156dec52418d0df8cecdd3495838e4d1d1b80598a34f381ec5024e2c9bd0211bc754da142cb3564162304068e34e33074851a6380a45a2a3191e3f102"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93671224880017bea54f91316a6ee82c754324ae6c5852e98edb5316f0ad1dd13a7eebb44c2a26e7d04d06be9441726cfca165ed247b802be55a42fd4c1a57db75ef0c0cd32dca2782b49e872f77a6f41a631e1b6bec2669bf2370bfbcbf3d4a769630d95c26588949f1b3ae4e4e429080b434b995fa18047406852c727cd9e6feb"]}}, diff --git a/txscript/data/taproot-ref/7b302c63a0c095634d5b99d885e31d50d348915f b/txscript/data/taproot-ref/7b302c63a0c095634d5b99d885e31d50d348915f new file mode 100644 index 0000000000..a5d4185ef3 --- /dev/null +++ b/txscript/data/taproot-ref/7b302c63a0c095634d5b99d885e31d50d348915f @@ -0,0 +1 @@ +{"tx": "861025b202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9b0100000044a148f28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a001000000788338a8029f0189000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acafa0f542", "prevouts": ["2c4f500000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e", "af973b0000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f24c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5c223b2b99456872194ca1969830bfef335ab1526807af314f38e6ee168621b20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1c56c8a32008d6f6a63b4b8ddfaeeeddf640e9afea8e86008d2331d68e9435ec7ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}, "failure": {"scriptSig": "", "witness": ["4c52f2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb427e2cee51cdefa725eb1f8255cf98d00ca42f29f054478581d82ff254acc1f11842c4c20f1fedac94edf4ee37dcf580edabb0aa4839378386ec3447d53f529f2ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}}, diff --git a/txscript/data/taproot-ref/7b385bf3549519df825d01ede2e8d9864af0d4f1 b/txscript/data/taproot-ref/7b385bf3549519df825d01ede2e8d9864af0d4f1 new file mode 100644 index 0000000000..e8ec8e1f1e --- /dev/null +++ b/txscript/data/taproot-ref/7b385bf3549519df825d01ede2e8d9864af0d4f1 @@ -0,0 +1 @@ +{"tx": "d336dfaf02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccf00000000eb3e058b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d701000000e10936e7046a80940000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48745010000", "prevouts": ["c49657000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d", "db093f0000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "7b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8e069ba5eeb0bec6bb336aeedfc480da3e66ab61ed5906063fe5b68f45dcb12952affe3792374ee751e9779d236e331236b2211c0285bb070b7e5d58aad1c033f64fb6de85916ce1333b57715a419fbbb7fd448155796c8af09a2e4a2bc14d947"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367588a9e23979d821fd29244dca8e20c36f5fbf7a2828b65ef7678089e87c8fd3565447efa486312fa493bc3efa8d0ca00e2c766484411258b08f0fec6b85156cd34322f35809060e9857f404c38bdcaf402c3d07c78e42a3b4d1eaa304dca88a"]}}, diff --git a/txscript/data/taproot-ref/7b8328e1cf64ee86aed185c42ef2d58842a86505 b/txscript/data/taproot-ref/7b8328e1cf64ee86aed185c42ef2d58842a86505 new file mode 100644 index 0000000000..d61a3d0a4f --- /dev/null +++ b/txscript/data/taproot-ref/7b8328e1cf64ee86aed185c42ef2d58842a86505 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf160200000050c0ec8560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705d000000008597bb100331928b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc94010000", "prevouts": ["f8447f00000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7", "18440f0000000000225120d1655db6fcb356decaccee2a8cc0c67c6e760726bed93f7ed1bf145bc7c6bd94"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d1137f8b15a9c4a2a780a0ae495bfb79a9a7db3f2ae43a0aea42148b525fe64"]}, "failure": {"scriptSig": "", "witness": ["6ab8616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/7b9f95b7241f7c9902e959452e13b67e26806ad6 b/txscript/data/taproot-ref/7b9f95b7241f7c9902e959452e13b67e26806ad6 new file mode 100644 index 0000000000..b7c2eb28ca --- /dev/null +++ b/txscript/data/taproot-ref/7b9f95b7241f7c9902e959452e13b67e26806ad6 @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705601000000fa8520c302573110000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df979722368987507c0427", "prevouts": ["f002120000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ca7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93602a88ba31ed3d41248d257786b5634ab0e5c1afbee5cd3bd44dcce92371e3b6ce4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8bfe61acb5630f372e1ed5eec342882068788aa3656bac92c2951e857c300141b065bfcb7199ff8296c5f7d41f3b2c6067d88c0a33f2878328c609d56cc191f12"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab5bafd7c1f93de46b79074fd81f9b2e5cf089f85eea866c1ed233ec2c502c77e3449c69d4dd26d8f08d0fe98a8e8c1c38138c07c2a650710c465fa6c38a97e3ce21dc20c2e8df5336572f81421322a354c6d32fb525b1159d1e49b1e9404bf5"]}}, diff --git a/txscript/data/taproot-ref/7ba72ec40b0c475f5d75c1845b6a75ce8fa2c003 b/txscript/data/taproot-ref/7ba72ec40b0c475f5d75c1845b6a75ce8fa2c003 new file mode 100644 index 0000000000..d71d6d0c63 --- /dev/null +++ b/txscript/data/taproot-ref/7ba72ec40b0c475f5d75c1845b6a75ce8fa2c003 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1800000000ddf5b1838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4780000000089a2312a02051d56000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acb49fde2f", "prevouts": ["49f925000000000021541f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "afa3320000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "80", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a254e7cc6b57a9a94b6584709e7056848938ff7b5d3cd788647ee9c8c010053bd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b44d35a0b3fc5d8cdca17f6fd766b3b7f076a7a891ad519d38c56688c70ff9dbd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93689697d7380f4ad31bdb00c7ff0dc66aa22f6bae188bed2870f771977d2fb8298280ecd46f67705e4464578fc0c4eafd6d20a38d5c68152a49fc5d0c6b2a7c87ed2fecf8564d6a652bf0232997fa790ca314d73b111c417284694cd1738ccb12191585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}}, diff --git a/txscript/data/taproot-ref/7bcb414301b9d095183f9b852a0c948309483542 b/txscript/data/taproot-ref/7bcb414301b9d095183f9b852a0c948309483542 new file mode 100644 index 0000000000..d177943f6b --- /dev/null +++ b/txscript/data/taproot-ref/7bcb414301b9d095183f9b852a0c948309483542 @@ -0,0 +1 @@ +{"tx": "1af00c3402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd0000000006c00f6ad60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705401000000ca7050f7032c0a5f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796a3093b4e", "prevouts": ["bd14510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "81c20f0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c5", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5115f1aeabcd45f20884fa261b27121b1c083fa5a2716bfd01069fab98e18c3b0e4b23f991898c0f7e80b32f00b838c1f1514616fab2a47083539335b67c2689fcce4d7767c8a9637a0804b073b1eb172c67de67ce152ade33f2591a85dfee2e5a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936811133f2935f27641e5de866d6b2526674271c11378ecea72e02f5c1283f85606c8f4b27179de8a3c9fbcc0ecf825a44b7564122e0508108d3381c6acb047da700a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}}, diff --git a/txscript/data/taproot-ref/7bd191b72e7ea5e8407c5a81557fb3489574834c b/txscript/data/taproot-ref/7bd191b72e7ea5e8407c5a81557fb3489574834c new file mode 100644 index 0000000000..e39a41e6e2 --- /dev/null +++ b/txscript/data/taproot-ref/7bd191b72e7ea5e8407c5a81557fb3489574834c @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be700000000d5ae6cd9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c040200000082777c9703cb766a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79656000000", "prevouts": ["4bf723000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "ef46480000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "0c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e85ada3d451ef6042e8b6b9e1a05667773e16935ec77c1049456c2d3709876bb0617d0d4fc7404dd8984f6a1705481d95654b515a34c586c99c11bfe20e9503459"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663a164d6d530eee3fa9d7e4db273a17bbca3a4f14a5c58ce7db70383c13db5d1234cf532d828cda123a8c35eaf5d21c66c96423d9004c9f2b6e0f5ba33bf4e7b5b0de380cf0ebf0fa9d17e1d1edb87a374b64935c1c67f0c5024fcc072643681"]}}, diff --git a/txscript/data/taproot-ref/7c0066094d3af7d6ae9649b1e0d8c4f65d29d5b7 b/txscript/data/taproot-ref/7c0066094d3af7d6ae9649b1e0d8c4f65d29d5b7 new file mode 100644 index 0000000000..e0aff19efc --- /dev/null +++ b/txscript/data/taproot-ref/7c0066094d3af7d6ae9649b1e0d8c4f65d29d5b7 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4b00000000f912b3eedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5001000000e0efbb9d02305ac300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e775040000", "prevouts": ["b6b17500000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "bb5450000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "4c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366bccaadcfa8d465832aab59065aa8d3e626f6f7953285a334a61d2728458c8250315d5fffb9cd0a0ee84b5f33e057fa02d78cd067c105b2c4520fb43cbb3cdd0d30287fa60720c35e6546eaa391bbb3975ba5e1722a6124c426d678e7f784bd9"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362c2c5f63cb8189e158f8fb075febdc1164769262e328fe4583383832734546d391faf9d665bb151ea32d070ad80c7b31483dfb68e75e940e326e177970210d6f819d45740b1e9d6e416a8a4978331345395bf058ef0b936b66c7755017d83c65"]}}, diff --git a/txscript/data/taproot-ref/7c3defc5ef17cddbacd31b76689e0f6d0737ac57 b/txscript/data/taproot-ref/7c3defc5ef17cddbacd31b76689e0f6d0737ac57 new file mode 100644 index 0000000000..8031a181be --- /dev/null +++ b/txscript/data/taproot-ref/7c3defc5ef17cddbacd31b76689e0f6d0737ac57 @@ -0,0 +1 @@ +{"tx": "6ce4a80902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0600000000fb9a44d08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4aa00000000cd2115bb0257a88400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc0a7ea020", "prevouts": ["59204b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7ea13b000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_85", "final": true, "success": {"scriptSig": "", "witness": ["695769ffff5be4e03469e3c5569ca7a6f29500f1e996023f01ed486bcdfbbccacbda5e33d5b1540dd7f1424141ac31b7a800cc7e914db5f01069bc91eec3e80a81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["51cce5536ab32b9a7f786d62a0e2ac4ee155062851f4919c2ad5e2683c0406f86833a10d7be40fa8f9802ed72130ab96cdd4e4bc6324373bcdfba4e868b3f90885", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/7c7017c2b46f27580791e590ff2536195830225d b/txscript/data/taproot-ref/7c7017c2b46f27580791e590ff2536195830225d new file mode 100644 index 0000000000..2f20a00128 --- /dev/null +++ b/txscript/data/taproot-ref/7c7017c2b46f27580791e590ff2536195830225d @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42001000000e00a97b08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c413010000008f316cc504fb1b70000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a640010000", "prevouts": ["14ca400000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76", "66fb310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "e97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0edd1eeef23b4191adb89e631380cd7acdd7acf00b470d5a9d9dc70e20df3f09bd7d7e2e0b29bfb283546875adbaa200efb560b624d50a8165ce6ae8ed501592"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cba7bcb35edccb3c3e0177d255d46e6d1d70e0b739c307d2394c91927eddf8d70edd1eeef23b4191adb89e631380cd7acdd7acf00b470d5a9d9dc70e20df3f09bd7d7e2e0b29bfb283546875adbaa200efb560b624d50a8165ce6ae8ed501592"]}}, diff --git a/txscript/data/taproot-ref/7c7b7ccbaea2f13ad6524f8a286a5a8e5de67e21 b/txscript/data/taproot-ref/7c7b7ccbaea2f13ad6524f8a286a5a8e5de67e21 new file mode 100644 index 0000000000..c5af2b72f3 --- /dev/null +++ b/txscript/data/taproot-ref/7c7b7ccbaea2f13ad6524f8a286a5a8e5de67e21 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1101000000a081b3de60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127053000000000c7b5fdbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc5000000006f40e899046516ab000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c6030000", "prevouts": ["bf8d4a000000000022512074a4c3567b4c4ece2d1ea256a6bf2f85bf4dc051497bd8ce7ed8816e2d4c108a", "befc0f0000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "19b35200000000001653142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "1f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8a47d733f2ac96a3990499de942ef9a5afce6e4fdb28ae911c182ccc4b722ed2ed661e9ebd30f651fa020177c2a1e4ce51b505c9194e43d6074b392863f250ba"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368244bc6a63b5727baff32c8b1af1e9c979b77b213f20864b1aba73e32e7aa16fcfc86bca0a8859889d9efd3fba9c68487fa49a78b15c293938d32f430a3e576ab3e02c0e1665e1d6a4b6ef98a6ef3a3632c98688db315e4c8eb8907479035d72"]}}, diff --git a/txscript/data/taproot-ref/7c81f44f5bced662dae488456a190a2b5b68c852 b/txscript/data/taproot-ref/7c81f44f5bced662dae488456a190a2b5b68c852 new file mode 100644 index 0000000000..d4204fb4ad --- /dev/null +++ b/txscript/data/taproot-ref/7c81f44f5bced662dae488456a190a2b5b68c852 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4df00000000d95f0a96dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8f010000003207e989016e8a0d000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d3010000", "prevouts": ["4a6b3a0000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde", "6934240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d", "final": true, "success": {"scriptSig": "", "witness": ["a80f05eda5fa6452191355b5e1bb0d14413a0834082572e8c7d771847039082ff4028dfa36b64d27678ddabdbc69f16d7446912da8038761ba6261574fbbcd2181"]}, "failure": {"scriptSig": "", "witness": ["6d92fce635d2cf9555981c7cb111fe1c0d137db468756d6f2fc95702a43e94218b9b189cf30a760b11d004b71866a4614097942592723a53e7a264efe8f307bb0d"]}}, diff --git a/txscript/data/taproot-ref/7cc6f39aa5cdd7a9af8b06f6627638b3bb770f40 b/txscript/data/taproot-ref/7cc6f39aa5cdd7a9af8b06f6627638b3bb770f40 new file mode 100644 index 0000000000..a54aba1544 --- /dev/null +++ b/txscript/data/taproot-ref/7cc6f39aa5cdd7a9af8b06f6627638b3bb770f40 @@ -0,0 +1 @@ +{"tx": "0972a5e80360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702f000000002df915e3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0d010000005dcd57a3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc0000000008fb04dcc0287d9c80000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac77000000", "prevouts": ["915d1200000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "ec355c000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7", "26b35c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100a6d2ab2947172e87e0d0420fcaf6652049471544cee25e0b022dfc55e36b0b0602203b0e29188ba06f91bf1ab0ccd70b7c641136597585c13c2ee17a619ea2713dfb834104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "483045022100de378d47a3861a1b30501fde0c947d82cd142397252fb61db7da9ba97ec0a2360220707b12cb0f3cf8b2ea50d322da7b3a68e1c5864180dd2520a58d7ad101cc093e834104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/7cfcff79af9057d0133f2b5da206b608722bd025 b/txscript/data/taproot-ref/7cfcff79af9057d0133f2b5da206b608722bd025 new file mode 100644 index 0000000000..7c0642eb53 --- /dev/null +++ b/txscript/data/taproot-ref/7cfcff79af9057d0133f2b5da206b608722bd025 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf601000000eb15c2fddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7701000000ce8ae4fd044f5f4e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a64ae04558", "prevouts": ["5f3d280000000000225120768c54f13dde172f25cce5a33aed38e02f08031f35d73759f73c7d1a105e2823", "abac270000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "287d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ec32039a2864f4c6d05138d42a3bc8d06036aba11fa129d2d36383244da9c9e18f8625f860d8689a2679aa71112fac717f40bee978e3269b215b9f9d8467661efcb4d33820b2e80b50b7a60cab20b6261c566fe48480267b41ad585cde9a4bb"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936980a251d9658563da155f8261bfb8adc21885ea6961ac467eaee09920ce56e15e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e896153d9d0825641ad9dc2862c4b07cae929842b36229bdcb06007f7d47362644efcb4d33820b2e80b50b7a60cab20b6261c566fe48480267b41ad585cde9a4bb"]}}, diff --git a/txscript/data/taproot-ref/7d568d459cf98a02f42d26cf7a40def28f45c07c b/txscript/data/taproot-ref/7d568d459cf98a02f42d26cf7a40def28f45c07c new file mode 100644 index 0000000000..a9e19d6a17 --- /dev/null +++ b/txscript/data/taproot-ref/7d568d459cf98a02f42d26cf7a40def28f45c07c @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707401000000447c0d19dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb600000000c89d618601bb761000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac83d9c85a", "prevouts": ["0d1d1200000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "d74954000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "4730440220111c8a8e4f7073ab568c295023ec7cd24c3d7003c51272c8bf4d187d87ee4d3602200aab60c8970b4d9a4f4181b88bbc1cbcc267169fdc72dcb7ee19e07486c03e586d004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "483045022100bc09fb85699d2d1050ce419e41f756b8d8e91d16e70fb3095ec494c143e6cc47022010834768e94c9da9680a4c68d39bc302651dfa20c77d0fa8057ef1b324c753406d01014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/7d77c20b635f8d363cafef80ce333359495fddeb b/txscript/data/taproot-ref/7d77c20b635f8d363cafef80ce333359495fddeb new file mode 100644 index 0000000000..8eca7b7a37 --- /dev/null +++ b/txscript/data/taproot-ref/7d77c20b635f8d363cafef80ce333359495fddeb @@ -0,0 +1 @@ +{"tx": "dbf3e74b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b890100000001737dbc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700a0100000096c4f09401d39209000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478760000000", "prevouts": ["7252240000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "189a100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d4", "final": true, "success": {"scriptSig": "", "witness": ["9d0831b6254a9df865600f216d1b11bd1b435ca20e650cce38e4788d5b555c7f2e9510d3c0e5f62fbcd753efb1fe9faf68a42863c02e4a5ec62edf31d3a52f9202"]}, "failure": {"scriptSig": "", "witness": ["ce36f271cd209957a8c4fe15564c95ad1969360a0dfd19764c6bc1ad1fd4ab5da1aa3dbd7981dbbd0ba65e822adce8229396ffefc2c5f641027f8c090fe53e91d4"]}}, diff --git a/txscript/data/taproot-ref/7dbdb91634696f23cadac0af049ca2841cbf75df b/txscript/data/taproot-ref/7dbdb91634696f23cadac0af049ca2841cbf75df new file mode 100644 index 0000000000..6a3c192d8a --- /dev/null +++ b/txscript/data/taproot-ref/7dbdb91634696f23cadac0af049ca2841cbf75df @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2901000000fe70cee560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c40100000092a97d7a03d69a2f00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4a846650", "prevouts": ["c485200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c66f110000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ac7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e5a9aa32e218bbd7702dd80b5ebdf509d58cd1514da294d038190654a927a1119f9ef29ad3e74b34f129235a64deb65fb580c2718ff9462ea3ca43b3a4f56170fc485b911b91245b46c320351c8e1d13bb30ee22c3f953d2224593bd4b5088ca"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93658c6fb8444bf3f1c71dc62d586de8f6b9f63c49598648e9eb416ba7b8eeb55d0f6e1ab16ab4bc20af15f35a7f6b67f82a67b85511624b76e02698979773111889f9ef29ad3e74b34f129235a64deb65fb580c2718ff9462ea3ca43b3a4f56170fc485b911b91245b46c320351c8e1d13bb30ee22c3f953d2224593bd4b5088ca"]}}, diff --git a/txscript/data/taproot-ref/7dca132115921f6d0134e317bc0c5b2e5b97934d b/txscript/data/taproot-ref/7dca132115921f6d0134e317bc0c5b2e5b97934d new file mode 100644 index 0000000000..3203b59ea6 --- /dev/null +++ b/txscript/data/taproot-ref/7dca132115921f6d0134e317bc0c5b2e5b97934d @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c0100000093647caebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd200000000897280c9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf63000000009dfb36d60406682001000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388accbd14a30", "prevouts": ["e211480000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "22e868000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "cd58720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_7f", "final": true, "success": {"scriptSig": "", "witness": ["27eb6a64cb17ded93d9f3b3641927a59f5d27199512c219b61736963630809fd0951b55407ee9bf6fa1533b234a10f6e97712cb7e7b1e8f96b547fd9713d0a4801", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["08e7b763fe61e85a11cc699bc7b9346760359b81598c06e1749ae83486b7ab8bac6a81e2d83204f96c7235413b8eee5c13e9ecff5fb2f40a9b7060b36d4fdc117f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/7dd14622cf7fe1695e710f01b45d90250043dea6 b/txscript/data/taproot-ref/7dd14622cf7fe1695e710f01b45d90250043dea6 new file mode 100644 index 0000000000..9ce1d1a6c4 --- /dev/null +++ b/txscript/data/taproot-ref/7dd14622cf7fe1695e710f01b45d90250043dea6 @@ -0,0 +1 @@ +{"tx": "ad0f55ba02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf000000000020d415c6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf37000000008751388004a9f403010000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487cb7cdf54", "prevouts": ["781681000000000017a9144c4b1fc943f04d775886b4f6d3c3c73bf7d3118c87", "2435850000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21511f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["182f98d35b656395a0e279e8ac79bb10de9f4a0abc90e5019b10ba0ada67ce243d579250203a24e5ad38b67da658ac80b5be97b672557738959f625878e9628c", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/7ddf0e4fc007dcceddccc60c7634ce32af1c1782 b/txscript/data/taproot-ref/7ddf0e4fc007dcceddccc60c7634ce32af1c1782 new file mode 100644 index 0000000000..fa39edc63b --- /dev/null +++ b/txscript/data/taproot-ref/7ddf0e4fc007dcceddccc60c7634ce32af1c1782 @@ -0,0 +1 @@ +{"tx": "8e58b9e9028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b301000000df8399ad60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270620000000088e2538303dd3145000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d6bda649", "prevouts": ["7be839000000000017a9146704ae21c886c9ded757e2b67d582abfc91902d487", "05500e000000000017a914f955a33e905fb6c7b7e694c8cef25993577deafb87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21581f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["0d74bc0c44327702fd68a9e5652814cb4b2ec976729a3f33e2510bc66054b9d42152e2231d14e91753c54ff32f3659e978c0b9868dd8fbf4e474944350321844"]}}, diff --git a/txscript/data/taproot-ref/7de80c1c4a6415b28404560b4e476f7ff798b292 b/txscript/data/taproot-ref/7de80c1c4a6415b28404560b4e476f7ff798b292 new file mode 100644 index 0000000000..bbebcea0d4 --- /dev/null +++ b/txscript/data/taproot-ref/7de80c1c4a6415b28404560b4e476f7ff798b292 @@ -0,0 +1 @@ +{"tx": "9a15a34503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6700000000b98902bb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47301000000b91d6fd260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703d00000000c51f3a80025f6e7000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964c000000", "prevouts": ["e6fe26000000000017a9141582f8bc3490e924b143f387e99eced40303eaed87", "fca73d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "973b0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2355212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["fa032475eb0e364864508278f4504454d21962b347e1c5dff402085489120264a90583560a08b8f94092ec583e9a0827710ef8d9d8bb8e6129d91ae016cdfedf", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/7e165223d7af3c0a9b55423a23a84315b3549c34 b/txscript/data/taproot-ref/7e165223d7af3c0a9b55423a23a84315b3549c34 new file mode 100644 index 0000000000..3ee9be070a --- /dev/null +++ b/txscript/data/taproot-ref/7e165223d7af3c0a9b55423a23a84315b3549c34 @@ -0,0 +1 @@ +{"tx": "0972a5e80360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702f000000002df915e3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0d010000005dcd57a3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc0000000008fb04dcc0287d9c80000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac77000000", "prevouts": ["915d1200000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "ec355c000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7", "26b35c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "027d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aa7d3ae1fdbd8d879becd21fdbe0d91f4e7a114144544c8c67df92a7e5482d1e69828280661f54bb25ef200c9d39138c753346ae1cc558703fbc48b26980763768cf2d3d0be95621d7446294d89d9a2894510d2dfb4e1a33e7316a17e39cfc99"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b93aeeec33fa290f41b43fbabb5874009d9963b54e8d894b1b04df286a8ec41aea584dae4332b3044a4c8d351fbda1a9ce22b0be13f72ff111d82ccfa4c6759e0e32049d91f42cbcb04955cd98e985d287b85d3c77c1154d8406ae5e2d81b7b1"]}}, diff --git a/txscript/data/taproot-ref/7e2b8b5d88ab86a02660c9f930b1dc7bc915500f b/txscript/data/taproot-ref/7e2b8b5d88ab86a02660c9f930b1dc7bc915500f new file mode 100644 index 0000000000..d3329aa19e --- /dev/null +++ b/txscript/data/taproot-ref/7e2b8b5d88ab86a02660c9f930b1dc7bc915500f @@ -0,0 +1 @@ +{"tx": "1f1a48c703dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9b00000000fdf160f9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c03010000009968b6f760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270150000000060f62d8a013c37600000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc85000000", "prevouts": ["5a1a200000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "f39b5b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b0fe12000000000017a914b0b53ba433a336ced94ed75e23248458a1c69fab87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_2a", "final": true, "success": {"scriptSig": "", "witness": ["22b22bdc7c8764d8a370ddf4e44c2bde5dd67a33f19a9b524d4fc0fe016fa1d4ad8e3533012a33afddb611580a5c978a05458c4bc60246296c2b982f04dc431c02"]}, "failure": {"scriptSig": "", "witness": ["7e21c85c67b66fbbf1d94c0a4b9238c1f3a7ecb1b5af4b8d21d34119b2ee5973e2bdaefd1ec9fc2cc6ee595c77b57ef15bebd989bb97449a0639a4368e99ee792a"]}}, diff --git a/txscript/data/taproot-ref/7e2f0de68af4544f103e74bd384b74b2e2f85241 b/txscript/data/taproot-ref/7e2f0de68af4544f103e74bd384b74b2e2f85241 new file mode 100644 index 0000000000..29334406ab --- /dev/null +++ b/txscript/data/taproot-ref/7e2f0de68af4544f103e74bd384b74b2e2f85241 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47a010000004febb4ce8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45701000000ef83efd203d03a6d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac6e000000", "prevouts": ["a714330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "28593c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e2", "final": true, "success": {"scriptSig": "", "witness": ["f25b6aadc3c2b33254ec57dffd2c5cb94f23b0e57a16fb495537416c3a31f0fd0be6091a8fd8908867ed74ac8f605a96ceb12bfe1980082e55b69961630a128682", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["77cc97bbf70d60e153aece39c2fc93f62ddf4922d93c3e7492f27018d29208307dd98245d89eb2adbdd3edb95fcd244fa4fd5ad9edf5f90a0b01460428091e3ce2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/7e4029c06ed03535d5f51420d860c7da16cc155e b/txscript/data/taproot-ref/7e4029c06ed03535d5f51420d860c7da16cc155e new file mode 100644 index 0000000000..a3feae9668 --- /dev/null +++ b/txscript/data/taproot-ref/7e4029c06ed03535d5f51420d860c7da16cc155e @@ -0,0 +1 @@ +{"tx": "ed787e2502dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4101000000e197ff86dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bba00000000cb7df6900128ef2b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87281dee3c", "prevouts": ["7dd81f000000000017a9141a56e0fb41afaf4b9e6feff1797087c69015162687", "4674210000000000225120801095ecb8b6618653d214b38461db03e06a33e3af24d0223ea647d6569eff0d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "225e202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["64b433ca7a1fabde520bade4bfaea818a96144cc46107cb1135781b43404a3a8abfba83e664bf2f87295b35658a6da12fe4e51d1a30f33a4dc72c9930f5f1c52", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/7e70e8a2a78ad2b7e350dc4a07651a5bf027cb57 b/txscript/data/taproot-ref/7e70e8a2a78ad2b7e350dc4a07651a5bf027cb57 new file mode 100644 index 0000000000..54f5a364ba --- /dev/null +++ b/txscript/data/taproot-ref/7e70e8a2a78ad2b7e350dc4a07651a5bf027cb57 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0d00000000f0d0e5afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb5010000001fc1f48c03cccb44000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acfc000000", "prevouts": ["f2bb1e00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "59da280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_cs", "final": true, "success": {"scriptSig": "", "witness": ["4bffc3b1097343fca22d5fcdb57100e76f29666e1054fd1e887e2c7efb35b3d6e1f60e1fff905f0c719d392e95ba00c2dcad1188a8ecf4c928f2afbf7926c3c0", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b7922a9ef31868fd0bdd2720bc44a83a05911c979e226e14df12e43105fabe25154b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b7922a9ef31868fd0bdd2720bc44a83a05911c979e226e14df12e43105fabe25154b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/7e874b33beab6c09e8cdbcdcf34c226d959f53a7 b/txscript/data/taproot-ref/7e874b33beab6c09e8cdbcdcf34c226d959f53a7 new file mode 100644 index 0000000000..6387c3c585 --- /dev/null +++ b/txscript/data/taproot-ref/7e874b33beab6c09e8cdbcdcf34c226d959f53a7 @@ -0,0 +1 @@ +{"tx": "0edf5c600360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ef01000000195c71c7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2a01000000128387c360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706301000000d6a1ca9b01111250000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478780000000", "prevouts": ["77320e0000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "f6ba6f00000000002251208082b91639ce415d44b93ebacde06f605687bdd15466bf93e6aed91c1a4a19e7", "1f6e0e0000000000225120ca2f7736d38d84f93b62b86d7eca19a35f2cfb6705849a1c6400bed56ad761ae"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["784508e5109e40dbf20ca51397fc002ed5125470fd6554c0ee7e14d8497660a36c8964118cef10e8571c4346463a248344c471511dcd0fe340cdb879230e75fd01", "39", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366766fac9c6e784db5f8f76fdaecc5908d346fb10e2a94f3d53afc856df676be9db8a063504914bc780e57f4ce8afcf899f13bddbc9ba6d59a4f52d0470abfbe40b0e8bb2b66fc463e2d54d81f90a0e5f51dcb3568b3086b1f357bf91f83906944fe8fe1069e54ae3b3cb1fdd7472a21ddc8023e0d3d8d2e4897c7cab26f377f7", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["784508e5109e40dbf20ca51397fc002ed5125470fd6554c0ee7e14d8497660a36c8964118cef10e8571c4346463a248344c471511dcd0fe340cdb879230e75fd01", "", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366766fac9c6e784db5f8f76fdaecc5908d346fb10e2a94f3d53afc856df676be9db8a063504914bc780e57f4ce8afcf899f13bddbc9ba6d59a4f52d0470abfbe40b0e8bb2b66fc463e2d54d81f90a0e5f51dcb3568b3086b1f357bf91f83906944fe8fe1069e54ae3b3cb1fdd7472a21ddc8023e0d3d8d2e4897c7cab26f377f7", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/7e926dc258ef73747c6dee6961a01976f75e194f b/txscript/data/taproot-ref/7e926dc258ef73747c6dee6961a01976f75e194f new file mode 100644 index 0000000000..5542d0372e --- /dev/null +++ b/txscript/data/taproot-ref/7e926dc258ef73747c6dee6961a01976f75e194f @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709100000000dc1650da8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49c000000002a8e0ff10207f94a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac4c010000", "prevouts": ["a0e70f000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "e1773d000000000022512015f6c01f4cbfbd03849fbcce8a636b49e5c18ed85b3712a10e7757f33687c2ef"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e04c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93660eaf4545b5f7166123e054cf15eb738fe32912d9aa58946aa01c3af8881f1593713490b1e7aa24138c57a652efa6d547b3fb45fa4f05027d6d9331efbfa4d517cc0cd924d9aecb0bc2fcf01621d0e73a88693291594fa52fe0219caeccfa5b3"]}, "failure": {"scriptSig": "", "witness": ["4c52e0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ed9d9b4b668c8953715b364fc922d70c032801be88e8b1547978372f57dddd133713490b1e7aa24138c57a652efa6d547b3fb45fa4f05027d6d9331efbfa4d517cc0cd924d9aecb0bc2fcf01621d0e73a88693291594fa52fe0219caeccfa5b3"]}}, diff --git a/txscript/data/taproot-ref/7e952aa0d4d919ea11291440bf1f5548858938d6 b/txscript/data/taproot-ref/7e952aa0d4d919ea11291440bf1f5548858938d6 new file mode 100644 index 0000000000..3fa8a0050c --- /dev/null +++ b/txscript/data/taproot-ref/7e952aa0d4d919ea11291440bf1f5548858938d6 @@ -0,0 +1 @@ +{"tx": "66f1c1cd0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ea010000009c1919fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e000000000477db4ae01416e1b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4879c000000", "prevouts": ["77a610000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "afed0e000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c368", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936353eae18109edee214f2be0a3d138643cb97d12a4be5b4a3033565f50658463d637f7085334bd6ace67733ad5f759fad65febfe656f63b2b30abaed1d2ea29dc9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e8c9e4d0011cdeb9b088f09f0ebbbf16a9fa32ee194ff7dd3162fc83b18004e07cb9328b065f9eb1f6f110e9fe7273590c885552330e2c3269c2432845ee2744cd8777bf679e716871b092f46e3a69645e6fd098b2f58cf3078cdf1926d6f261"]}}, diff --git a/txscript/data/taproot-ref/7e95b122591089fda778a2dbd434c55672c92346 b/txscript/data/taproot-ref/7e95b122591089fda778a2dbd434c55672c92346 new file mode 100644 index 0000000000..f16655da22 --- /dev/null +++ b/txscript/data/taproot-ref/7e95b122591089fda778a2dbd434c55672c92346 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ee00000000e3d0b991bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa8000000009f4a9bdb032cf480000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796122e1a27", "prevouts": ["a2331000000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "dfa273000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "", "witness": ["3045022100c251462192731569098900cf1d3b21cf946d6e773e17b9ba0bd3310fe26e3bda02201c53d83c8af1e3b9976a6c6575994f9358ff87e1ad9688369c27c6ee2a57839783", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["3044022019d5bd6e1a1ea306364e81fd63fa9199fd0293d96d83b3a65609ca11ca70b8c7022038f911df8254b7d76da4d4003d68b494cbb1edd6981f67e48474773a5e75f22983", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/7eaf9980118567289bdc91759abbffb031b64227 b/txscript/data/taproot-ref/7eaf9980118567289bdc91759abbffb031b64227 new file mode 100644 index 0000000000..79d91aecfb --- /dev/null +++ b/txscript/data/taproot-ref/7eaf9980118567289bdc91759abbffb031b64227 @@ -0,0 +1 @@ +{"tx": "af7531b002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b15010000003f6948df60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700702000000b229d6fb012748260000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc4f020000", "prevouts": ["bee5240000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50", "25fa0f00000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c3d637b7011ffd00eedbb445a8092699a300f1bf27d1605b591c1c40de685c877c8ee2696e70fd78aa4612c8389c2f050673617b62a757077c4637d3dbb9c49ff52eaf25b03ae274bca090a0b92b839559e9d06510d569b9673468a05ff100ba3e27f6892dcd04d2917fddca63a34f682577eba1dfc9759e8b6f640961840efc15b96da4e473f5c8f5de0305fcd4504806b0195502d7a0403b7bcadbd35689eb9516feab007ccfcc5593e606fc87902da536366e37aa3ae4d9a13e794280aec0d945d0bdcf8875238ab24b771e85c85fe25eae1c7f852c24035bc708c50f711b7c87e3ec5a3675262ca7e9677c17c773c51b1c82ee074440c201e10a5229ad8f70ec228bf41d70cbef2ffda3ee36bc003e82e73cba0f45b5fb050f0e71c732835637c7890a29da273e369192adf6bdee514e7677d24a38911b650e8b10fcba06ea15f5081327675a8b203d1b859d16f94352eb975f491949d673c2380dc2af40d1a21d347f56b9657020fea68ee6a3041c2a29946f0cf7a892c7af3160e00889b8644ba8ace8ad79828769fd9d05a157ddccee7e7f4749fc43b3fc5b7df728521d8f809c394a5193da2faf2c00c59bde8e4e114ff76474cd710b13a183dab9bc0928c7d41ba37a26ecd1f8b05535e24d05ce14b47e2967f02521874205ea0e02c636ad2c46a937e4ec619370cd2c58eb123f9ef7380c2b0377117c5965f8ceec96e349cfff3b1c926475", "9f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d928217635fbec2956e337d8cc635fe8686b115d27313616c09cd1eab494f2822016530e482bf934dddf93f5dc5c8477f8e54d8918bd8c9b20d47f007dad28fe6f3617d560800e971f99646d89bd2028caf0c6d02b6f505a11fcad3ec349c801"]}, "failure": {"scriptSig": "", "witness": ["4d0902f1cd2fa2b7c261d5486386a1264e4af878b2f4c5d663b3b0c67cfc28c712388798b8261c41e0b044e90932c7909cd8102817b4e6d97135ef44adc0bba486b9b683edfda424e49226f651512008f3a0a63438e6c3ccd45f5d3ea57c82ccd0a502a9ee472bc43f930b1bf26eec8a35ad8b278cb5901984aed2f4d8e58d05dc90533927da8594e8acce30ec1ae29af933f9688576424853cb374c9deea7018a895cf86ed74c71255a353f7d6deb9b19f5c8f487fb41ef7805c74e296c14fb249c1fca128b69309800b504f636c47a15cc36e5833bedd70937e13485bb0a33e63f10cc94709f320e92cec22b595a155313c9af153e82538978da14bfc9bbb2a5ee0170bf1c8fcf60bbfaa4d4dba73e2ac2bb8a966a19f5df071568fc6c78c6e63601e44206358767a1cb6b2d86983d8e8ed45052fe049030d547baa085458eff60b6b0d5cb09959d612a60c904c8baffa6dd634b65d32e08d7a8951dbdf9991959e07c9a934b197dc8e137008719b9735a79a5bc56941b6ed78cb321007bb46138646678c8624bf4d7d1ed94dbd9beae8af23f16dad5a7c5ba22a69d8132a6b9bf6d22b46880503528628dc53d98bd117673b2b3ee49d742a8a2a135683742d91b3a6f554fb32a9adb71d4553e9c0abe58e37d629efc42a76fc2945d40f4d5712fd9a33ea72f4115e230d9955d9cfa859dabe809c2198c8bfce85051cf35da7e8a7612425289c42e56619c75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d17a8d967edabc547e7e1f87e3be6b8f080116454f38ecbb7d9556d120e85891ee453f7f7ccbda5a0ba96115b963083e4b2e9e93a3abf82e4dae88dd7e6a6b566f3617d560800e971f99646d89bd2028caf0c6d02b6f505a11fcad3ec349c801"]}}, diff --git a/txscript/data/taproot-ref/7eca413996ccecf266e5bf306d63db50903b1ec0 b/txscript/data/taproot-ref/7eca413996ccecf266e5bf306d63db50903b1ec0 new file mode 100644 index 0000000000..9477d2de1c --- /dev/null +++ b/txscript/data/taproot-ref/7eca413996ccecf266e5bf306d63db50903b1ec0 @@ -0,0 +1 @@ +{"tx": "2bd6955703dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca700000000c8472f80bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4600000000d13b7096bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf22020000007262dfc601ef371a01000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac991f5956", "prevouts": ["846a520000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6", "8cbd7300000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "3c5a750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "4730440220187c42c98be72805ee6a6005328cf68088eb005b2ad3e49bb24b484c8b33083902200a2b9a27d2ffa0868f0d65f9d1bdea15902b86887a5bbb245c4d277150dde879342102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "473044022003afaea420bb105276001b4fd88ab9393ef3276a8f51b7b5f348028460e5dc610220381780c541463889708cc3ef67fe60bddd79e869e5e56652a33e4d53d4100782342102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/7eeec8eac2847cfc829b4f04a7732871fa5b33bb b/txscript/data/taproot-ref/7eeec8eac2847cfc829b4f04a7732871fa5b33bb new file mode 100644 index 0000000000..f7783c9cde --- /dev/null +++ b/txscript/data/taproot-ref/7eeec8eac2847cfc829b4f04a7732871fa5b33bb @@ -0,0 +1 @@ +{"tx": "87114d0402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bda010000001bcacfcbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5a01000000684733a90404c2710000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acefe46a4e", "prevouts": ["33a22800000000002251207a86f45d21fdb08435e271cb417d7b8bb1e066ea2bc109ea12043ac97c7d3e10", "94014c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936275aca17f49935962eac90c180a8f819c2936e0eac025cd2a6a39b05ffb78047"]}, "failure": {"scriptSig": "", "witness": ["6ab4616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/7f31dda7857641eb43ac8f245109af960b934c86 b/txscript/data/taproot-ref/7f31dda7857641eb43ac8f245109af960b934c86 new file mode 100644 index 0000000000..7997b4755a --- /dev/null +++ b/txscript/data/taproot-ref/7f31dda7857641eb43ac8f245109af960b934c86 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9101000000f4573a6f04da7c2500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac0f4c6c56", "prevouts": ["766627000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "677d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e5c46f8483e321cebaf2ee3308d3646486cc3944f1006fd31d055421496231102bba6f8d4f5daf96bc6060ee089cc6dcbd533ad30ddd55009697a11ce72a351d2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdbceae773fe677547a5f8be2986f5e4c7dc436c0d3f0e1e86711aa468c8778215"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082687eac120734a03ae4c27d3bf57e4c4c383799b8e878ebb1c20141d650e89e9fbceae773fe677547a5f8be2986f5e4c7dc436c0d3f0e1e86711aa468c8778215"]}}, diff --git a/txscript/data/taproot-ref/7f36ff093686c198384796967779e512b39b0067 b/txscript/data/taproot-ref/7f36ff093686c198384796967779e512b39b0067 new file mode 100644 index 0000000000..c5b3666f28 --- /dev/null +++ b/txscript/data/taproot-ref/7f36ff093686c198384796967779e512b39b0067 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa700000000ceefd48b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45f01000000e73d30ab02afa5b7000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7719a5825", "prevouts": ["0af9810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a25e3700000000002251205d2a5ec9abc88b8aa90a173ff406be7abff8b14799a4f6ae3ad10e99906551f7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936435ae76ebb71dc9bdd4eb981061c35de943408dcc30d58732258fe975e745805"]}, "failure": {"scriptSig": "", "witness": ["6a21616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/7f37fc6f46dfd2056c23dce7388e996b2e007166 b/txscript/data/taproot-ref/7f37fc6f46dfd2056c23dce7388e996b2e007166 new file mode 100644 index 0000000000..4f099d0da4 --- /dev/null +++ b/txscript/data/taproot-ref/7f37fc6f46dfd2056c23dce7388e996b2e007166 @@ -0,0 +1 @@ +{"tx": "8afa4c8302bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1b020000003cfad686bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5401000000082929ed0293b5f3000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7ba010000", "prevouts": ["962f7b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "51277a000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902af3a911aa679f7e606cda485f57acdd53a140d2363ca6ab2a2da3182409741271a038cd152447d92e99cf720e89c7f69987bf3f52c56880f40d10e1802b6f96664211907f8b191a7566205cc36cf793a0b41a905e8c81ddf9f033bdaeadf9c88bba302fb88d20f188df877b814aab86991fb5a4e6171309c703b2c5e1617e18c53c8d9ab0ccb7612c3e8021ec2b9004e8a713f3e3f6aa0149557fea0356a69662b072ec3c0791a1e9477d975ccc161667fe05b7770fa4afb89958e1e060baeee59deb8799c4d0da2decde5cfdeaf63c5945b1a2193887319b7a2e88f98fe390c02e3f38cf9337fe608811d28ced82549e4f221177ad1746374e0c5c9ac7ab02bd5a4fdeab12d2b0bc5c1800779585726264669a6f82960de6f3d8385ccf6eac83f768e9263ed4b01d400e3fa10d5efc506c0f6ddbe7eada4203493b89514a0864548c53a0882a42201b87c88a2ab39eb9c2db6be8ae372da2bbf60b5de69fbbbb265bd919a73fa7cb4f9d16d5b89eb7d96948e9a90222e13d87a54aff156fcbf969c47bd46d0e0ccfcb0f1a9a8ab48a976ba48369735feb355cd48003d5b94dd39d85e247cde37f0ad88ee5df038047bc569f7fb868c27c85435b0d671a3a40fd4b2a16ca7052d9304f61aa432257ca7d234aabee4a8e95144945d25bdece32ea1475d8fb9e9b6cf465b90524e53f6ca353368f1d2c750cdf6ef69d8b7cdfc643c9b4e28e3d523b64e75", "267d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4636362d36fe430e464691f92fe9bddeedaa1a868b07f700ddbcea110392233913d4be53f363cb6dc14d29c1d7e4819045cdc001ac228b3b700074691e2599d91e402d116972020cc4db8f7e1431e7a7416668817d422dd270400f40dd8d238"]}, "failure": {"scriptSig": "", "witness": ["4d090245450b3e387113d0ce5d0371276bf6936933bd20eca3542c8a0636aa706b44a2fee9299c961e33398111243df0aef0b83e5a7c9a5347edaff04f8aafb495ae71b18d0ebf602ef8f1f816612095ac53819e0f7aec71ed33698972db5e08333813009885d7b8d3065cbfb559a3644e6fa40c190ebabaa2b8f01fecde4484aec8951db5efd5639edda806a7c032a28247917183f654e5afa11440f81d77df0d152c105709fb458dc0a2884579ebb0a99ae4b01916b6cc1c1f30a37e794bca974ae8f6ef5e77196689875fe4d1cb2fbf1bb88172715701c77acf0d198262a8033ef2de49d9009e30472770c63307c986f5da4fdb3ec8baacae8409df045c6289a11aa427c7499977574c9d6777111ad3d479f8372456e766a95b388e6bf3fec7d250c0a518a559ef6dab42edbedd059d58ac472c6af092c448830b2b68327250b8517a4359c86540eddeafce06983977c41caacde58f15551f3e7e5bc17f791f6b261076072d040214a5da939a4292f940edcf6186fae7121e44366b01d7f5bb7753d09cd8e9ed2c732c005ac6d8a4301653474e4c8e25d48bc27c5006642fad23a1ca8359daf4264acea7a2f2a7878135fdff0e688d9ed6d2fff68a9c4dc89a8826de329726219fa1a5260b122905ac10d2b6c691af715179177433449a17d73c2224359815eee3a34b6c0be96cbe9b97de7d3ad86f7d9e8cc868739e898eef8d995283aa61f7b38cac6a75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f7219e5458c3fd087680f56af7e0cb5a098c29a419645486255ebba5b453a7aacd4c02f64c49cc162ff9325daec6263c98ea78a2c5346e44c6d55d79722c7edb"]}}, diff --git a/txscript/data/taproot-ref/7f5fb097a29a27b116140b9366006e578d1139ce b/txscript/data/taproot-ref/7f5fb097a29a27b116140b9366006e578d1139ce new file mode 100644 index 0000000000..bb118b82c2 --- /dev/null +++ b/txscript/data/taproot-ref/7f5fb097a29a27b116140b9366006e578d1139ce @@ -0,0 +1 @@ +{"tx": "007958d602dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9e010000000160a5b4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2302000000b9f715cc01b1a3b900000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a5020000", "prevouts": ["8ce35f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "47386e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f9", "final": true, "success": {"scriptSig": "", "witness": ["577367ed863cbd40fe824ed1756571da2db8ce634648d5afff58d64391215c28a1231178cb28d84833af6a5bf04e82bf49a147fc72b4a083e7285c8719cb2f2001", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["611b2f417623f690adb513d383a2976867502accb39f2f7ec363f47a706e0933661e7060ddbc7147c21f485c212d1c826a0c2aa3a7dc45e8c9acb53a2fd798f3f9", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/7f6b5c7e454d101b3d586c7653b251e1aaa8404d b/txscript/data/taproot-ref/7f6b5c7e454d101b3d586c7653b251e1aaa8404d new file mode 100644 index 0000000000..1443ce8888 --- /dev/null +++ b/txscript/data/taproot-ref/7f6b5c7e454d101b3d586c7653b251e1aaa8404d @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1701000000c7fc959a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704c010000007eceaec901a7a40e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce500232a", "prevouts": ["49ba1e00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "f00011000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "48304502210094a2a0dcb83ebe9818aaf887f84bb68cba54c5e376590146f070df10c7e9ac7e02207dca24c14026289cf3e9c046f2ddfc6ba274006aee79de870f2640104522bfe4012102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "483045022100881d2f9416fd35184a097cc6b5566732ed3f5265ede249783b8d21eb015413a0022026f3a6b6fefc2ce1e5ecf42a93d0e583b4aec62945f0dc9a864487a0e8657fde012102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/7f76a08aef5329137e1c80a8f4fc7245375849d9 b/txscript/data/taproot-ref/7f76a08aef5329137e1c80a8f4fc7245375849d9 new file mode 100644 index 0000000000..219485dca7 --- /dev/null +++ b/txscript/data/taproot-ref/7f76a08aef5329137e1c80a8f4fc7245375849d9 @@ -0,0 +1 @@ +{"tx": "dcaf384b02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cda01000000cf8850f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd400000000479871ed013270a100000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc4ef5541", "prevouts": ["db3f47000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "03855d0000000000225120fc12a8d66cb681b25d9244e35510bfc0dfd4b0ce262903c87a066ca254a38f8e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090211e5ca7772292b1441e62cebc7470f5bb206c51aab540a8c0106d008dd2ed22fae5fc24244a2b4371591cbd5c8c42c64355a4b38a62b3bc33cba2c1c1300453c77fdb4e16a51c82c2d3929034feb33f016bd1bbc00009f128284aa84885515c45973e014e7dda5cff953423da3b14a1688a13446a47ab3301287880af7722eb96cdc0d12d9ba47f8a65c37d05386f81abefb301f1a91d69e9ba6a01bfba13c3f1d7a0029162702a800ea83954fd5854d235f2ced6c0c3538c66e6da9e7714cc037542c9c1faf47333d80d4e2cc628d9f1ce2589c1b72a2377063cc38983669036f6946492f76345938c023617137cb4fb8884dea466108f3daa73e5d4da38d81e4cb2f08137a83e1a54fe5e9e86e7e62d1c0a355e3a2ee345594c57c043c8d2239e80f12fd5922a23d3aac7420ed5a6c0c0638277fb281f3798892ff24d2b0c3714ac1f0e23cf2f9b55e57da8d9ab487c129df028d91d76de8c37ae965698476189266b7d4dd76c52c4f23c02039018ad7ea5b8745aebb87ec4adaed22c50b2e2e666bcb5b755cdf7b6596c1537594012503452e0b4e16ba2752967acddd798bd5d7a3ebb18f5e5944663b5e570c04cda945930aa1363fd32bd91522701f7bed01b1e8e56572cfcc8bfa7940179ff2aa8e6f0c4ea1f6c7b97c5674b98c986a2d9b70ead7424d6fccf5be6bb136ced57a2df23d01f6f5282046d26ea5f4aeaefa479aaa5078c262ff8175", "2b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e83f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082885bea8937005622f3eb8b2c440108feebbdb5f3ff09e0402c722754cbcd9b2d195038de5261112827291f7af9c58b034003ed818b7e5ec0d4ccdf81f6c2ea4d"]}, "failure": {"scriptSig": "", "witness": ["4d0902fad7da56013d94c7a2f1e1441b0e0151b7dad7e0fec924e4565474039c3fab075da1bb75c325d628dd4339bd8bb75115a95d42acff0c04c0642dd9e23fd80fd2a4e0bb3ba292e1491bc114e7958ff515832bb364c25335e706f305eddff3b282025ed1ec827bdcd494e446ccaeaaca74f7df7ec5c5cdec3a36c15b20de7ea87031a7bc31558af79e9d2a13d5f717af88d4c8fca5020abefb83bf08419400586529dc8e1cc0a107dcab571dac46d266d3cd9fe8127d955ff4bcc4422d83d9f098943e85aaeee380c717fdbb8bd60236884e22d4eecfb5cc88bdaafb862bf160549607dfd4b1aace0f5f3492ed5676d62326087430bb046709cf9e519eb9c01bf7f6ca78a1a70f8ab87c31e66feed7a8aff7079359042ce004892dc0c96ff16ddc832d908a053793e55748aebc560fcd5f7bf75e20e31612a264c546093b8919eb7d88f0c1c5f494b7eb5132ea7f8d14baabf475409ef35fbe00ee41332d03c4e43ad5f0ca69d92fa596c61757867ce47274077f7201f71a9187fdb997caac5a745bf4529b7c51279a25a4acad72a3cc51478bcf825d68d22d3ed4bc2b9ac4bfc48a31cef64276bdfd10e33ff8cce5528c558a1a8396ea69e44e9e6a5d4a78ef3358f442dadb3d3a2ce8491bbb8706f49ee462b4bd5233a392a484d8db73e9f6e7e6669c5292a9c40535a011b592821782d4c4f67c32b7f746b8bf062af89d189022e1f6a2029ff4020075", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a9bf3b6b5783b5bb1528abe4ffb8f169250f3a45ac3fcf85a8b33da4afe75cfffb898061b9e990a9b5449c5e7217db506cdc93f8f373bfce07d03a77edf1b275195038de5261112827291f7af9c58b034003ed818b7e5ec0d4ccdf81f6c2ea4d"]}}, diff --git a/txscript/data/taproot-ref/7f7be6c8663be7951320cb6c651781e5583ed65e b/txscript/data/taproot-ref/7f7be6c8663be7951320cb6c651781e5583ed65e new file mode 100644 index 0000000000..e7eff966a1 --- /dev/null +++ b/txscript/data/taproot-ref/7f7be6c8663be7951320cb6c651781e5583ed65e @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff8000000001375d4d460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f101000000e076448004e67f8600000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acb4030000", "prevouts": ["620f7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4e3c0f00000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100f7769039e9849a23425809e640b988b91d6c25b3533ff27b05e3e9f49373604b02207c1fc11838f5183c4272c5096f5a56d8ade47bc2707254ceaeeb9549f8078c37fe", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["30440220775c2323a9c98f6c597702add339149e4d0bb96db939394bcc4eaa264fea3bd902201e15716d0db5f9a1e482d38b68fd3465c4043993b66067d07a6c994d33750ca6fe", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/7f8f81d1bf5547aca3adaba322cccf59977c80b0 b/txscript/data/taproot-ref/7f8f81d1bf5547aca3adaba322cccf59977c80b0 new file mode 100644 index 0000000000..8267ef7ad9 --- /dev/null +++ b/txscript/data/taproot-ref/7f8f81d1bf5547aca3adaba322cccf59977c80b0 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfab01000000353da8e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa900000000724751d30155c54600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1ed6a542", "prevouts": ["8b607600000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "23c780000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ece7439a6da18213b739641e86399840a31603efd6bc35e889cb5cc2f58e891a69cfd1883d9d94906422bb83623918edcd109683f826bcbf676882b31fdcf44192fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366888396ae9b1a8f191aefcd5a7a56acfa3ac01b0d4c8aa849bbbe9a5944eb071c75ad5b0c19c64f5d3a7fdf07b71b1a8f8b99e999958fe2a8fbfcbf733553f9475ca33d7e1e5f2997f74dd285eec8a0e5cba5080c4482d5b595e9662ee4b93be0a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}}, diff --git a/txscript/data/taproot-ref/7f9d1a52ba029c7f6e88ff84575df1fcb1075619 b/txscript/data/taproot-ref/7f9d1a52ba029c7f6e88ff84575df1fcb1075619 new file mode 100644 index 0000000000..335e059a2a --- /dev/null +++ b/txscript/data/taproot-ref/7f9d1a52ba029c7f6e88ff84575df1fcb1075619 @@ -0,0 +1 @@ +{"tx": "e61fc582038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45601000000c4e2b5b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2001000000c5b7f7db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41a020000002528aeb801fdae1700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7c4010000", "prevouts": ["f0893300000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970", "8b96760000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f", "5e9f320000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "417d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e832d46fff335db0bc559e9bb1dfa0a13335da6dee7eeb053c06bd06875f6e68356831d286b681d36077bb0670e25d1d3b2bbe36e9d696c3276746d4ede397eb7d"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361e2c9952688e2a9f00f4b0b73b9f464050183c79369b385e87738acd2c915b017155e8c33f0c07f7d0de889297fa065f1be8d31098e32dc97a677fdacd11d05345bbf2815375aaeee056e6b05e441f58ef8c911146e9d15e94b57fcda7a8d0b76831d286b681d36077bb0670e25d1d3b2bbe36e9d696c3276746d4ede397eb7d"]}}, diff --git a/txscript/data/taproot-ref/7fc1bf414713fa9f80c252358021f9f97b15c792 b/txscript/data/taproot-ref/7fc1bf414713fa9f80c252358021f9f97b15c792 new file mode 100644 index 0000000000..b7704af321 --- /dev/null +++ b/txscript/data/taproot-ref/7fc1bf414713fa9f80c252358021f9f97b15c792 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127072000000003a6d923adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2301000000ec825d2b0388966900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a76d4227", "prevouts": ["e98711000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "583e5a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "98", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936862595c5db495f9659b55a4931c0d6b5790089471348683bf5da646fafe3acb03f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082241df2003654f0fe7fc4600eb797dff990a6f251f130f49fda58fcd5b0cbb08c94c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936135308afc3f1b0427026314dc25c4582126331f233b7d3a6426128e486397ca6241df2003654f0fe7fc4600eb797dff990a6f251f130f49fda58fcd5b0cbb08c94c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}}, diff --git a/txscript/data/taproot-ref/7fdcc6c41ae23f27834e5e1303ac7e3a7a01c43f b/txscript/data/taproot-ref/7fdcc6c41ae23f27834e5e1303ac7e3a7a01c43f new file mode 100644 index 0000000000..f046704962 --- /dev/null +++ b/txscript/data/taproot-ref/7fdcc6c41ae23f27834e5e1303ac7e3a7a01c43f @@ -0,0 +1 @@ +{"tx": "ec16b2e503bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf71010000001e2984c9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cff01000000d37921d6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9d010000006e9e6c8f0155bb16000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8796000000", "prevouts": ["55bd6700000000002251201b1a5025b4fe9992b0e02773e7f35e6be2fc0ec95e56c0e62f01a84c1b9caac2", "4966600000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2317250000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c9", "final": true, "success": {"scriptSig": "", "witness": ["856df688e7ec8ac2de3b3eaa7ee2c7e7a01666ae97f299f0b097fe46b64ab0dadf920716a3c53bea12cead7678a3a4e2191045ebdbcc09071df6e16f1f3d1a8182"]}, "failure": {"scriptSig": "", "witness": ["0b679c2460e33142fd5e633ea0bc7372ce1690c74bb2710fd3dad6ca5f9488fc04fdd91246154aaf9b55e028b491fb2178fb927661012a992cd546f294c553a9c9"]}}, diff --git a/txscript/data/taproot-ref/801315c10fe0fcc26c0c57bc8f631cd93596168d b/txscript/data/taproot-ref/801315c10fe0fcc26c0c57bc8f631cd93596168d new file mode 100644 index 0000000000..aa0b3b28e6 --- /dev/null +++ b/txscript/data/taproot-ref/801315c10fe0fcc26c0c57bc8f631cd93596168d @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4db01000000aa09a19cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0f0100000069f2c7ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270920100000099f9349f028e428a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487596bf447", "prevouts": ["72db310000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "266e490000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "02ff10000000000017a9146704ae21c886c9ded757e2b67d582abfc91902d487"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "165e142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["3d54f7211a3131376c7caa6a4b4da03c4647e46af1be525c2948322529d5cdc37df71a7e64a98902d2b01b0324693b015a50e45a7c9a70a90ff7509a0e55e760", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/80333b40950b8f22b44ba7c383dc625b1b094df3 b/txscript/data/taproot-ref/80333b40950b8f22b44ba7c383dc625b1b094df3 new file mode 100644 index 0000000000..084bcbb49b --- /dev/null +++ b/txscript/data/taproot-ref/80333b40950b8f22b44ba7c383dc625b1b094df3 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8900000000168e1e960489df45000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcfb000000", "prevouts": ["65ef470000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d06c877dd86d961faf24eb5b06d1067a63efc55cb5bd19f84e66e81c1d8ce78d7393228d3eb0988ec9fcd75a06765f40457a0e9e3bb59ba4b5eb203b8f76edc57f6cdae672933b8d5270426b7bcec0c61df57a4cef656f5283364a160b6c04deb40b6eb065ccc984fff697bc0344c73ec5e9c5fa63ee26dc05c836112749986b744d4a3b93694a2036550277dc68556ac354f120b33f0bd1571b2aeebeab2200e4da1320df8c8e059de66dcf03e0874eaf7750b0860f98f35b7c10b70415f810946403a50eac215b8a7d39af3ba37d1c853a5ceb47d5ebf203fbced8e91a41125d9eb7089d1d443182afb63ff3eeb03e8f4b2b2046e574c27bb996a70d0246c3a1ab981e979740802b973b3d4aa7e58d071ff91f2d41d97d37f18bb45210a75ce52d2325dd6ded929c17b877085d54fc30f3575a84ae5b2dc38e8050d9f2c611672b1aff3354b1fbc527e3197cc46e4d2bb3c6818ef1b6ae3ecbf5b3f3b4c8e9dbe48b18cef645103ccdcfcf86abffc5e8a4480c163e735d8457cb48df90a060fcbe1ed9e1c00ff3886ec60efd8106d97b05deb93b548311458dae2584bba85471378bb768fa26627ed9b17fdcb450bba081f30ede1a16f65cbf777ac7baa3d3dd2dec517eec9810d6157d19c2fed82f1c1b7c4e977217343fd8a4f69f9d48575b3530ff1f79d081abc60fa41e1c24210a813c24c8304bfdd11c556d86905547bc78d7614227413d6275", "f87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e85d94fcac167164a1e762fdc7573aeb7aa116b8ba9fcc5f9bd36bcc426cdd2c869a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e5422b6de6500db2bf907e4c5314ebb405475f57406f25afe5ac62a92a9e6c58b"]}, "failure": {"scriptSig": "", "witness": ["4d09020154afaf81a15a88692650b1880577fbae1973e489fe66b93c9d4772ab4a226d42760a78db03608edbc96b23ac65bd7df559dc0fbcc976fe9f1e20c98f810604e279ec97ce3904bf07a966de51e245d43cf42810de716a4d61beeaaa151e03b13180abf8071029304830b9a5af10d6874cf21d45bff46220e7d60d8dc063bed28d7c8743aa5064e3385e49a13cf5b2de933f80eb3eed607426e79db5e0c57635e8de240f91a6ee2b89346f7a09e3bc71773d07382e0eb21bc27780aac226484693a819eb8e203c698ecd787d2cca6faf00fd37640962faed8de5868a063f3916a11c4b4ef313ce66557c2dcd33b2e97ac557f6d3438168a408590c1266eb8219b6d72b9ab780ec15730412666aa58eae131d7a1597774bd07fbf7cd225af26d7989948e3e9a809d8d442afb3de88849be8a71b4055a44e37a3c6029dc77c75e8da3d5a70830520ebc8d370121915ad7ba6ff0124a977ae28109be082a2c8eb80a5f1c56be56e6ca5f5c271393bad7184cc4f378a152e0a70b40c55f0a92f25cb5516dbe20f856958bc09f4b3239808ea2cf6e95e5893b805aa9ca16181fe46f848779f4a8758a14ebb155c45759b248ac73a3589bed623400f70b17bc63a230a0564f596e21deb6fc4a5bea4d9221a472d45052339fd1152e835a5e930f4ee61045b35d8d18cd3e6f0a4638c950b10b9fbfdf910959ac1e96c00c147b3143ecb4dae38b59b8d3956ea75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826a44cf4e9a2100eeda9c03b98c53803fc7517d02bc9d83cbf3bcae8bb7675812a0f16f4cfe8b052d74bbe565102becb5d9831a57baf41b6ebc95ac4a46ff7ed8"]}}, diff --git a/txscript/data/taproot-ref/80376b2b822b9baaef72428ca022d2e8ad5fab95 b/txscript/data/taproot-ref/80376b2b822b9baaef72428ca022d2e8ad5fab95 new file mode 100644 index 0000000000..fb2aa6e2e4 --- /dev/null +++ b/txscript/data/taproot-ref/80376b2b822b9baaef72428ca022d2e8ad5fab95 @@ -0,0 +1 @@ +{"tx": "8ab8cf8c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be401000000e633f1b18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b800000000e45ce987016a015900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac56b72021", "prevouts": ["64751e000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e", "23a9400000000000225120c1102a8f1f1acb509ea40275c13487a0c613f8d79621443165b53e6eaf1338d7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936462aa15e09838b54adb150b3e07c4d162c70ef3c9412f75fa68c6ecefae7c30c"]}, "failure": {"scriptSig": "", "witness": ["6a63616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/803cd5f12d095d218780ad627b0b82b0bab86370 b/txscript/data/taproot-ref/803cd5f12d095d218780ad627b0b82b0bab86370 new file mode 100644 index 0000000000..9dcc8b1e85 --- /dev/null +++ b/txscript/data/taproot-ref/803cd5f12d095d218780ad627b0b82b0bab86370 @@ -0,0 +1 @@ +{"tx": "d14930c602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbb000000002238ed8360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703d010000005e661cef048a862e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca4ce8961", "prevouts": ["33ee20000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "cfd60f0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5118137b75632fc8469b6d274d74e13d397486217d72038875bba282e5d91314c39823c6bcc0c06b1ccedd8f3302fb965778bf11fdbd4830d29cbc62f32a77240ccdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045770c141d000b7389bcb028eba0df2d51be96e98815503d59ed22f20e414bb1bdd3571a06a1d33120289e06483b2785a7356eedf367170ec7792d3587508789d4da9670c383f4b71f5a22d48df0589bd68dfe195935a65f1aeaa80f10f8ca6973"]}}, diff --git a/txscript/data/taproot-ref/8046cd7645e89a0fda7d8f8378e8425fefabb6e8 b/txscript/data/taproot-ref/8046cd7645e89a0fda7d8f8378e8425fefabb6e8 new file mode 100644 index 0000000000..60b3bb112b --- /dev/null +++ b/txscript/data/taproot-ref/8046cd7645e89a0fda7d8f8378e8425fefabb6e8 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7000000000ec9b048ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7301000000231716990186d7ae0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e776040000", "prevouts": ["2956780000000000225120e126375bd164d085eaf078f7c968ba0351125367548e57f6cc6688a24dc88c09", "3cd947000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366da9ade92a00cd903f2bec778be2e2fcad1c3b4b24d4dc7374dfc8c654eb770c"]}, "failure": {"scriptSig": "", "witness": ["6a28616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/804b90af698434a3596956677aba5a5f73dbaed0 b/txscript/data/taproot-ref/804b90af698434a3596956677aba5a5f73dbaed0 new file mode 100644 index 0000000000..8af6c3783c --- /dev/null +++ b/txscript/data/taproot-ref/804b90af698434a3596956677aba5a5f73dbaed0 @@ -0,0 +1 @@ +{"tx": "02a25573038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44300000000a45df2cd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d7000000004530aec2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c62000000009004818202ae91bf0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478724ab1f33", "prevouts": ["520e3100000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4", "942a410000000000225120327dc9effbe915b227349282cadfcd45dc438d4f1c3ec72713111ad7587a718c", "f2415000000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ed7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa229db830b5291510bfd4e55fc2f3a45cfb4105ece0af57cbfe0942d597b32d0c27d2631c3cab5fe643277004a2e6838e79a7dd6765c91a13be066042b33c17d3b131de5807af4725e3fdc8c81388bc895736ddb6e799e7163e8586c833ffc627"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4a97da4cacb7d2ba59131ae423230c4733e99b93a89fd0934cd3e0ba8b31d50a45769ff8e70e4bb7b91d42acbbb62837b0e871ab760bcabf7dfb792b2e999f3b131de5807af4725e3fdc8c81388bc895736ddb6e799e7163e8586c833ffc627"]}}, diff --git a/txscript/data/taproot-ref/808bb1522f5aa5de2dee150c5fe9b2240c76f14e b/txscript/data/taproot-ref/808bb1522f5aa5de2dee150c5fe9b2240c76f14e new file mode 100644 index 0000000000..424132bf62 --- /dev/null +++ b/txscript/data/taproot-ref/808bb1522f5aa5de2dee150c5fe9b2240c76f14e @@ -0,0 +1 @@ +{"tx": "32d633d502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4a01000000a75705a460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704e01000000a92a96b3047a596a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac49000000", "prevouts": ["76e25a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7e79120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_29", "final": true, "success": {"scriptSig": "", "witness": ["cfe693420f1cc693cbed5917368faf6dd8b05cb899e1a5e7faf739c1dc96cf3f09c85d5184c172fe5274d72ce3ae2632c22a18b4963f34484be0e3df7343a59a01"]}, "failure": {"scriptSig": "", "witness": ["1bc7a81d5f370cb009c1a825051a8a06a4cdb01c16eaea4d759faaeddd0d0d1846089c86038e31eb8d62689d741c5381a3a4e484ac11503b7622c28d78290c8a29"]}}, diff --git a/txscript/data/taproot-ref/809f182745ce2d04f2ed1126bbd41c71d290955e b/txscript/data/taproot-ref/809f182745ce2d04f2ed1126bbd41c71d290955e new file mode 100644 index 0000000000..a4e8bc3499 --- /dev/null +++ b/txscript/data/taproot-ref/809f182745ce2d04f2ed1126bbd41c71d290955e @@ -0,0 +1 @@ +{"tx": "e82fd79b028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40002000000f2fd11988bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4740000000030e1c39504a9a063000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac9333884e", "prevouts": ["093f3300000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "1a28320000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09021ab944e180ca31231b50da81439e79b19f1d40a763242bcb978571d8e6bf01f0a6b4f8f4b8ae3b68cff1b3575eaa97c39ca283faec5f0ede51ed06900ef11a22af65cdc28f23829319f23532649532f496486515ea290ef6375ac45f938f02b4ca4da8fd51c2c5464b485cfdf6eedb5d4d45484487838fe9ee3532825c860e1a47a8069ea88787779140b0a29ac14c6b91600d4dfc4479c061f27887672fdea84d9949802016361d6a2523051964fd0bd11a94aae3293f2feea136dbf91290c456f4fd7484497d4bdf1b8d20d80fbe0e8d5df554c5ae0ff6e90af0eb14ae4c06504140fa117d39a97be2c5cf8627d99bd6003bf57f7f3c98cfc1f368f6247df366f0653c143c65b2dadd7125f52bf477865e4338d882d2ef44da0067f7c689b6961fd506cad0f2e6ae6193313cd39def5e1805323e1681ae3dcd73be7840289305d5a4eea7a5aad40ad12382eef9423be5ec5fb39aa9f3c76704a36b7df182cc128706dc64c925c9799762661f920a364b106bf396df366080905ca3aa74a5689ba80721df515c7740f565efbeced669805c90db9c75cdf15ed97ac6e98c7fdb106a7b1d40df5037554f1fb51c5f68d0de15f83d81177bd63c6dfa6c20345e816ca22a1a454dce2ce07087da3a56f6b18e5f1ac62e4338dab9a5a4aa6d0ceb14118bbbfe9b54c3c6a93898cc7465d767ee7d4474fd51d8ee52637c8051cb190c0ea86f70b6f90c26c875f9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0d5bb8659128f7d307893f477315172a6feef29cf3fc1fd27176c3d23e09b029752367bb7d11bbe7d9666c447942212a409021a53e3151df7f84d090727acdc4c9"]}, "failure": {"scriptSig": "", "witness": ["4d0902c2c3423ec372fdea4a6d2781f624ccf83906af35c178114f947f239143d19d3718b2b8b52c996a41dc4544ae6c1d446b137dfbedd48eaf00ea49b0cb53466edb1f67314c1d9c0c2f1bb74fffb92f83a91796513ce221c1c5b3cea15978aca386d016df8ad648359e1f19d81977a647cfc05e3be62c488e2178935a42ed4eea6b0a24b2ed071c0fd1a17f8a80e7bffe2c5edaf3d7eca0776abb8c6d68eb72bfcc7d72d344b9666c157db190b8463f4a4cee3a008b50fb1d8724e1d0871c5c789f8da4fa81b4cf23866c33de0b69ede882ec5789bf6dc770d3870c52b35e2cf4f1416ff279a7609982a29370ce24ee32474d17b51b860a2dac03cb6b83ff8ca36bc6efef6c641792a282360bd4d989ceb3b38999e3717b0637dc854611d7031a9d4c998afca5abb2cc7ffc306802130fe2a47d06547719c3a5d5bf29ecd9c381f3f3fda66a01ac744cd0756da364ee2a349f51c2f80e353a355dbe805ade1660d05647ba754f227b8034596d554e05d347bf0b2c1f3347c8381dbed6bf000cf381952e9c608561a07c23318d9b5bd3d53c4e32b27955fe7250c29126650449261c1ce399ae508ccb8c34c4266eead892eeb22a41115663209ea6c61d4218a8c393774508ff240273f8f0841af50fa11f267ce42c183d8d9d417bb23a1513ac4271cdf1d179f67ffd4719450e78c86a8f4876e4408cef099408a4d2a29e43e4f0861f66023fe400a1bbf87561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f6efdc35f2fdc8737195d16fefb12181ba8a3475ed2464c84ee729da1de50531ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045a58cdb730d5140e8751cef937639de4f5fbc77d98986906c68a7616d2fa212f87d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}}, diff --git a/txscript/data/taproot-ref/80b5c3a4f3efc732cfad5a798289e246619f8977 b/txscript/data/taproot-ref/80b5c3a4f3efc732cfad5a798289e246619f8977 new file mode 100644 index 0000000000..18336844bb --- /dev/null +++ b/txscript/data/taproot-ref/80b5c3a4f3efc732cfad5a798289e246619f8977 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41202000000c2df2cc2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3e0000000000c889220437d98f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a63a584d51", "prevouts": ["d5a340000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "1f1a5200000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "5c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936900f19854bc90d6c79e0184be6bef7ba18c323656bf267ebd46e4fd22ae910800ebd37c9b7767cfa75ada9a6605680756deb542ec34cf1dc29d9c7b172412f3174e87bfb4d3d415907d7a3196832fc57be4f6d746253c89a46e8e4c968740366e8f45a3ac55dff4b7d62b0bc42204f13e92c55212ff162d480a58edc7717abc8"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936369642414e3e6cba27e1a8d43018b0c6e901f2bd9875554ba9baf88aafe131fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e24e037abdf69c22f44b0c591ad93651f749184eaa819a8a63a5d4092bdddfb78f243c72f4e074898aab8058b3c73fee97ec3b9723e213834a8398e97170c1356"]}}, diff --git a/txscript/data/taproot-ref/80b9b953d5d211827d5046ddef05778d9e6fe889 b/txscript/data/taproot-ref/80b9b953d5d211827d5046ddef05778d9e6fe889 new file mode 100644 index 0000000000..abd464db0d --- /dev/null +++ b/txscript/data/taproot-ref/80b9b953d5d211827d5046ddef05778d9e6fe889 @@ -0,0 +1 @@ +{"tx": "c3f06660028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47b010000007a1ec183dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6001000000e09642fe0241047a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000", "prevouts": ["c7ac340000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "04b3470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_3b", "final": true, "success": {"scriptSig": "", "witness": ["e8ac4e116fd92452319a1cc55e5c83d33673880df2371ae4bb58250f6c2e0c0eadbf3d56f96a5c55bc8d5e4fdcbbfdb5810d8883e809c1c2c58b8d4f57703e9b83"]}, "failure": {"scriptSig": "", "witness": ["c975edc8daae13a6159ac81c4cba985c2834b2c25e887bbb6c48a3f68ac92345442389cf911d8b9ba1f2cf2ba8fcc9a99405e004d5250c6ff176cc4aae3d7c503b"]}}, diff --git a/txscript/data/taproot-ref/80ce5e7fb2b5a1cf0cf9bb4b9a786e4bf6735056 b/txscript/data/taproot-ref/80ce5e7fb2b5a1cf0cf9bb4b9a786e4bf6735056 new file mode 100644 index 0000000000..682d060d96 --- /dev/null +++ b/txscript/data/taproot-ref/80ce5e7fb2b5a1cf0cf9bb4b9a786e4bf6735056 @@ -0,0 +1 @@ +{"tx": "d7f2d62701dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1301000000fb32e38c04ad51230000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac80010000", "prevouts": ["1116260000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063cb68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e3dccf8482e84b4ddec6df4dd40915d9305dca15dfe62535982a83db5fc62d181ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900450e2995ea6b9af074c8994aee2f7f851552d9aec0cda14b2daf9a27b43dc2eeb28859d05a814eb862cab9a6acf3b7acf0881c47896b22b56466b77992f62c0511"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a8aea858d1ec7924adb827dda39bc25501e41dc8d888bd1e3815f5a6593acc760e2995ea6b9af074c8994aee2f7f851552d9aec0cda14b2daf9a27b43dc2eeb28859d05a814eb862cab9a6acf3b7acf0881c47896b22b56466b77992f62c0511"]}}, diff --git a/txscript/data/taproot-ref/80d98df3c15079be160fd7897dc74ef9a9b4774b b/txscript/data/taproot-ref/80d98df3c15079be160fd7897dc74ef9a9b4774b new file mode 100644 index 0000000000..1ff7c2b326 --- /dev/null +++ b/txscript/data/taproot-ref/80d98df3c15079be160fd7897dc74ef9a9b4774b @@ -0,0 +1 @@ +{"tx": "f566a34e02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbb0100000061ba5eab60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702c00000000845ff5f404e063680000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478735000000", "prevouts": ["da89580000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5ee4120000000000225120770a4859be8fbe7a841bd8e66a93f9515817dcc93bcbf3e365174d34bc6304a6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936460d293845900fca9c67e1db672bcfeaadc226f783a04384d1d04876572e8fae"]}, "failure": {"scriptSig": "", "witness": ["6a2a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/80dfc8a9fc0fe40ea7577dfd42a34b367905756e b/txscript/data/taproot-ref/80dfc8a9fc0fe40ea7577dfd42a34b367905756e new file mode 100644 index 0000000000..1fa58a28ed --- /dev/null +++ b/txscript/data/taproot-ref/80dfc8a9fc0fe40ea7577dfd42a34b367905756e @@ -0,0 +1 @@ +{"tx": "53f634e403bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8d00000000fb2721ebdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c86000000001da8c8acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5c000000003f491bb602892f0601000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7ad000000", "prevouts": ["2902640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e4a94f0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "e76455000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "f07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08235987c1d75c441670cebdf615816c6f42e3d99515a7a7b9841c20e75c916465ebec2e27f579b173781717090b44a070e7a8880532a05b17dc998986213b0a92d21741bf2762a3041d275698fd56a81520b6404e88c31ed080bdecc36c09cb10e"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936942bb4c31de59fc8dbdb77a6c08d9745d0ae402a84080ebd7ee34cdc7a4c1a1529259a32967333cc74bf44ff096d479961194fa0f97de632ce420fba7b687b9321741bf2762a3041d275698fd56a81520b6404e88c31ed080bdecc36c09cb10e"]}}, diff --git a/txscript/data/taproot-ref/80ed8061d1dc94f53f2e897f7421f7e7109037ef b/txscript/data/taproot-ref/80ed8061d1dc94f53f2e897f7421f7e7109037ef new file mode 100644 index 0000000000..d118567329 --- /dev/null +++ b/txscript/data/taproot-ref/80ed8061d1dc94f53f2e897f7421f7e7109037ef @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4f00000000aace61d9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4101000000718e46cd01acf570000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e4000000", "prevouts": ["a9c1470000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6", "1a5c710000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a6", "final": true, "success": {"scriptSig": "", "witness": ["821c257e5ed2521423b7500974532e621a22013791af83a38dcd2d4520ad76a52dce176b7f4bdace7ae038c1255872c30fdb4c4265ab8386111b394f0f1050bf82"]}, "failure": {"scriptSig": "", "witness": ["682aa0cab91cb477ca201a52de1faf92bdc48805833577035c57f575a4bf7daf103a3797b52ca761dcad8c8da41ebbd2d5baef8e75d8aa22c9ae427389ed8f7fa6"]}}, diff --git a/txscript/data/taproot-ref/8114bd4cff1787b06e5836915e62486478f693d1 b/txscript/data/taproot-ref/8114bd4cff1787b06e5836915e62486478f693d1 new file mode 100644 index 0000000000..98f85da36c --- /dev/null +++ b/txscript/data/taproot-ref/8114bd4cff1787b06e5836915e62486478f693d1 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6101000000fa271d9660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270790100000078cbba8d03582c3100000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1c000000", "prevouts": ["2453230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b6c010000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4f83673b9228ad584e3c758d3a7ef913b0130d95503994689e6b12c1cc0f2a2ca477f7eac6c013e182e33a949b526b028f901138401b50189d2a4f50cede7d4a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364a27ab33ad30c866663b6aaa2ec98e71770b4a6226bfe80c47bff7f69f5996db8ef0ecf285bc5470eddb41e1019d9d697e32571bfa8271cd432e6dc81a28355aef31942b1858214ae33105eca3f0b2cf78e8df05a3972acf71e40f309e975162b655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}}, diff --git a/txscript/data/taproot-ref/8114ee0d2c07fd933798fcf7febf9e08b6cf1043 b/txscript/data/taproot-ref/8114ee0d2c07fd933798fcf7febf9e08b6cf1043 new file mode 100644 index 0000000000..7d6da3c09b --- /dev/null +++ b/txscript/data/taproot-ref/8114ee0d2c07fd933798fcf7febf9e08b6cf1043 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4660000000079caaceddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9400000000319a8008014ac71c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a631000000", "prevouts": ["e90e370000000000225e202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "72f2250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_94", "final": true, "success": {"scriptSig": "", "witness": ["637df903528a2669960c10cf7795becf41f1f860494a168863b39218676c0c82e53e14409cfb5fe51bdc1860873c6431ccfb6b826d4c0f0b723a6669c08cabad81"]}, "failure": {"scriptSig": "", "witness": ["8b0280e6eca447946658aea61f185059689f16e6f65d76e3246fd3472322b4da51e9fbda0def6847213d6d92128dff0d1281c65e72da2efcb54d3837ad492ebb94"]}}, diff --git a/txscript/data/taproot-ref/813b01314937089f22d1d64ac7030c5da92ac36d b/txscript/data/taproot-ref/813b01314937089f22d1d64ac7030c5da92ac36d new file mode 100644 index 0000000000..84abd8bb82 --- /dev/null +++ b/txscript/data/taproot-ref/813b01314937089f22d1d64ac7030c5da92ac36d @@ -0,0 +1 @@ +{"tx": "392083b603dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf8010000000320c5cf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704701000000934072f4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8200000000df73f6d504ec96cd0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac1b08b24d", "prevouts": ["47805900000000002251204e3fb1c88f2893b13c1c33c3a0d0cd819c49ecb88ca3deab379ce318a8955811", "1ca9100000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "e5a5650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_32", "final": true, "success": {"scriptSig": "", "witness": ["e047390b6f2b815028e622b67a7c936b80e970c52de504236c67cbf13d8c9482ee5fe7f40e51fcff18c2e560c4af726b808d134b30257dabcfc414253719d5d482", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["72005ca1df610bee84eee7a8d8422d4d602e1ada34b64f16c0c11fe2d328f4612ad623f7286c59b5018e507e97b0c9efe07f71afec9ba04ad22cf5776ab96dbd32", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/814755d13f451119bbd6e341778fcca05d023f99 b/txscript/data/taproot-ref/814755d13f451119bbd6e341778fcca05d023f99 new file mode 100644 index 0000000000..2cfb65c2a8 --- /dev/null +++ b/txscript/data/taproot-ref/814755d13f451119bbd6e341778fcca05d023f99 @@ -0,0 +1 @@ +{"tx": "5c4be34a02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe001000000849623b560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127009010000005cf056c8010da88300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acf148915d", "prevouts": ["3a4e83000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "87df120000000000225120656f89671a8f47d6bf2e8e427ddcf5c0f85be8fade6cfb3bd1e5b2fd091df805"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "5a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8b94a0debb1820c84163419892bb0f6faeb0ccc065c72968f976a9287eda7854dee9c212f1ab0dfa1a42522b9ca3467b009d36f3b841f39cdc4da4a0520ce4fa4"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936552f570dbd2f2d23e23457387a9f0809f04049394e9226f0f3f744fca44fa69fb94a0debb1820c84163419892bb0f6faeb0ccc065c72968f976a9287eda7854dee9c212f1ab0dfa1a42522b9ca3467b009d36f3b841f39cdc4da4a0520ce4fa4"]}}, diff --git a/txscript/data/taproot-ref/8152fa388ef907459fca58c6382e7cf481e8b03f b/txscript/data/taproot-ref/8152fa388ef907459fca58c6382e7cf481e8b03f new file mode 100644 index 0000000000..2338e015aa --- /dev/null +++ b/txscript/data/taproot-ref/8152fa388ef907459fca58c6382e7cf481e8b03f @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa0000000003a5d8e9060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703b01000000b886ef2002b9017a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87de3e9141", "prevouts": ["613d6c0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "1208100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["dd4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb48439541955ba1ee927ac695664eb0a176a74cc392dce51705e9d682cc4042391e6ff37e966b1384c4d5bfa916e4482452180179a80b37f756d07f3e2976ea2d444f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}, "failure": {"scriptSig": "", "witness": ["4c52dd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ba6fa17392019bae4881bc31f2cd312244d559032edd01d38bf5ef60bdbbc9cb6537362191d9a5e0aa3a730b93b6f98a99ef63ed893bef4b9dfa7e3451eaf360e1f075c573bc42ff1b5fdcad1a87ebee849fc17bcfc5c414a2a4f901b5a19cd44f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}}, diff --git a/txscript/data/taproot-ref/816316a3b73af9b70141fff8b2deda8269d38d34 b/txscript/data/taproot-ref/816316a3b73af9b70141fff8b2deda8269d38d34 new file mode 100644 index 0000000000..e752726ad9 --- /dev/null +++ b/txscript/data/taproot-ref/816316a3b73af9b70141fff8b2deda8269d38d34 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd400000000b4b636e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4350000000068748b9903215e57000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87390ebb5b", "prevouts": ["0e7b25000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "a72b3400000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "8f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bb3df96467ce9fc7fc29c8ddd81586e6582039bc398dcb0af9e4be844b7de22da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457f8fae370a255a677f2f729010dbb329fa966ed9a0dd82e5083dd7ea90426dc47"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082458187dbd74455692a21727c8254a8cae6fcc3fc3c7e883861248db6e64d9919f8fae370a255a677f2f729010dbb329fa966ed9a0dd82e5083dd7ea90426dc47"]}}, diff --git a/txscript/data/taproot-ref/81639ecf4a65a0d2972d186cbca46aa48c408a2b b/txscript/data/taproot-ref/81639ecf4a65a0d2972d186cbca46aa48c408a2b new file mode 100644 index 0000000000..36ccfe8d88 --- /dev/null +++ b/txscript/data/taproot-ref/81639ecf4a65a0d2972d186cbca46aa48c408a2b @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c0000000003bd730a360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b701000000ad8a8be30263f44c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487deff4536", "prevouts": ["9cd63d00000000002251200fcaedfb972c31a562a88e2127675cb61d773b6b9ce4a4a9159012ab236e47b8", "09b9110000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93612b529b7bb29b24c3871885345303f71ca892c4f89489e73513829c3eaf83d96"]}, "failure": {"scriptSig": "", "witness": ["6a38616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/817d2dc89f753f1b403cbbdd6c078eeee50563d1 b/txscript/data/taproot-ref/817d2dc89f753f1b403cbbdd6c078eeee50563d1 new file mode 100644 index 0000000000..80fdab2390 --- /dev/null +++ b/txscript/data/taproot-ref/817d2dc89f753f1b403cbbdd6c078eeee50563d1 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c40000000009d51e232dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c42000000001c11fa30025f6fa30000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48730f47c39", "prevouts": ["9532570000000000225f202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "3d794e0000000000215a1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["ed9fd964f63d35214f9e8c00b0068cf2068da31bf44e5bc4957beee74745f0d1e21743e8cb3228f9486688a0ec355024ba54f99da996f1ec409e6279b24d6c89"]}}, diff --git a/txscript/data/taproot-ref/81873f88c2fbdb0a58e15e3492b63cb1eeebd61d b/txscript/data/taproot-ref/81873f88c2fbdb0a58e15e3492b63cb1eeebd61d new file mode 100644 index 0000000000..6552f1c92a --- /dev/null +++ b/txscript/data/taproot-ref/81873f88c2fbdb0a58e15e3492b63cb1eeebd61d @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270de000000007f4af652dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca600000000e56eff118bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48000000000454a026504e231a400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e79f410645", "prevouts": ["a4bd1100000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "f33b5400000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "67d540000000000021531f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93656b2e44901702d460c7de97890111dc615bb44671c92f59d31a1c2531c59c007affae472ebffc4152ddce3f20794b01737e96becc2bb4a1a296a47c8ec0d29af569af0f9e86656db21fe5e74d4bdcdfc2cda5437bccaf9e3d568ba1282fc608d76e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1f12e5bdadb74bb113beeaaa5995d4ebaa92337455ee51746db1fb6fe7db125e52d50ee9aa3de1fe988255b0d8b9f34dc2cecc4a96432b9f704e90359a06b468476e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}}, diff --git a/txscript/data/taproot-ref/818a1e4250991ce3f414e0f7215308cf2f23f7fd b/txscript/data/taproot-ref/818a1e4250991ce3f414e0f7215308cf2f23f7fd new file mode 100644 index 0000000000..2a3df3e6c5 --- /dev/null +++ b/txscript/data/taproot-ref/818a1e4250991ce3f414e0f7215308cf2f23f7fd @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a801000000aa951bf3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bac010000001c53bd7ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe9010000001c47564f026e879f0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca040a226", "prevouts": ["0c261000000000002258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "8c5a260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7f456b00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "b17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93631b8b349c71009dd0699fa095c14930b92d0ccc3f805605dccb4e079a114365fc037589144f6259b59768147ff9100354b3b8b337e77dac87d022b72101a452a989f510e73a03c44610e5cde856f75a0d7582565d561698089d126c5e7f66809"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366359014879f365de32ce308b078826923e3810adf17a39985dd2e1f4b53925a86d4441481b861885f5ed94900bbd5862c55ac99196b75719f05c0af3923d20525bc912f5bf4aa2c9ddbc9747d59c78f40d0a0aa0a8a4f22dc70e3f9cdb9b6ae3"]}}, diff --git a/txscript/data/taproot-ref/82050e725b7ee8e6090dcb98775499dc19017c4d b/txscript/data/taproot-ref/82050e725b7ee8e6090dcb98775499dc19017c4d new file mode 100644 index 0000000000..700ff4f217 --- /dev/null +++ b/txscript/data/taproot-ref/82050e725b7ee8e6090dcb98775499dc19017c4d @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccc00000000943576cf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41600000000780387a8028e4e9c000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac10010000", "prevouts": ["a4b05e00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67", "293a3f0000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6acf", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dacf42e82bb70907a1945a35a6e6e5987b28c8057479ae5c8d9a8053dc0ce2143f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828121d7901a27ea565e1cb6f91818c43a3dc8f46dc56db80c8bd3776430739107a653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e14d5a9b7fc917253ce709706ec0b90ac12c0f363dbc177a85b066bc4407805851ecf70b79dd1be85a38988f8929e7263abb01bba95965800009381ed351eddb0fa653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}}, diff --git a/txscript/data/taproot-ref/826b8362320fe6f06ab5a2f4b4fbf5c94448170f b/txscript/data/taproot-ref/826b8362320fe6f06ab5a2f4b4fbf5c94448170f new file mode 100644 index 0000000000..8f5dfecf5a --- /dev/null +++ b/txscript/data/taproot-ref/826b8362320fe6f06ab5a2f4b4fbf5c94448170f @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42b00000000ec4681d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb3000000009a1ab7c503f24e9400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac34030000", "prevouts": ["33df3e000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87", "787358000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["304502210086fd6f82cf9f17bcade605d0205e270a8df0beb7b5dc1c0ac7d9aea62967244902203d82f6f92e619a97b40933947edf1fa3acf9e8b4c1cb0502fadfe3a0f277eb2401", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3045022100a64cff4a632e760eab859075e6c7fb4875c413ab70ed25272ee4dba0ded87e5702204c828040502d9d3036480487652af08a9d9aa8629142899dcfec6b40631cf18c01", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/8283d17b50ed5619f147c5b35a8f94626b7d5b26 b/txscript/data/taproot-ref/8283d17b50ed5619f147c5b35a8f94626b7d5b26 new file mode 100644 index 0000000000..aec3da84e9 --- /dev/null +++ b/txscript/data/taproot-ref/8283d17b50ed5619f147c5b35a8f94626b7d5b26 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be60000000081cd06d2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba600000000e8ea84da04f3fb48000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c8e69e59", "prevouts": ["4c1b2700000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "bb67240000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "", "witness": ["304402201c6742ac2a1f0ac4c6da40bc3b37590ae74b22cc39bbbbad3cfbdbbcb477a9440220430741708bd41f2043ed464a5bef8a03c954a35030b5c85bae7f7ad86c841c7a82", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["3044022044f71b4c8b957ae93b353ba9cbe0821820ac7302acfb0994a8d29d76222a12b70220382530d71424d8bae92a654ad3fb69cb0cb5740a7d25f8bef56af2807301082682", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/829c3ad6c8ab04d87634c91b6fcd79faa92656fb b/txscript/data/taproot-ref/829c3ad6c8ab04d87634c91b6fcd79faa92656fb new file mode 100644 index 0000000000..84912537ef --- /dev/null +++ b/txscript/data/taproot-ref/829c3ad6c8ab04d87634c91b6fcd79faa92656fb @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707d00000000065ad5c8021cce0b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914719f78084af863e000acd618ba76df97972236898775967c61", "prevouts": ["185b0e000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93674456283e1c6db6717d3e15ed53ad7b64612fc008d624aa1e2dd3f9c613e2b4568c195719e600029237bb2bee296a81ae54a1bf44210bb387eff41995ca6f68fbfb640520cc13bd7f4751eea589bfdaf463667e9e3eebb3331ccb48f0e9ad4c4d3f52a2844c5f7874c7d430ecd2ddfcfe713e30c56da5784f950db6acb8f092a"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f6c5cdfdaa55ce393d431a80dfc39c32ae0ebbe82478f6b10a6f2143ea646fac82d044aa67ca69515bddcd39ff85ae31d999a9a5b32af0a0137c9fa4b226ee88d3f52a2844c5f7874c7d430ecd2ddfcfe713e30c56da5784f950db6acb8f092a"]}}, diff --git a/txscript/data/taproot-ref/82a84993b98a8fb62799914dc21be4be700e7b5d b/txscript/data/taproot-ref/82a84993b98a8fb62799914dc21be4be700e7b5d new file mode 100644 index 0000000000..bef19504ff --- /dev/null +++ b/txscript/data/taproot-ref/82a84993b98a8fb62799914dc21be4be700e7b5d @@ -0,0 +1 @@ +{"tx": "273ed95401dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5e00000000ab2de7d602a8b822000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac61b0b131", "prevouts": ["156624000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["bc", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900459312a224ee6564b861c658371f7a6f0026ad2c58d86ce869dc9b432e830a527104966f092bf1e4b4348fca11e7254311373308f7fc15e3d44d6a2afffa343c9657ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b04dbe1d7a597ef7e58582d6b28f055a2f440add2d85f9dd7bf5919989399b7220e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e14a8563068286881d42b1c4901d93a483973910fd5653bf7ebbf040741f7cd837150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}}, diff --git a/txscript/data/taproot-ref/82e6db8a76fd387b0eb64cb1d7bf968ef761fb96 b/txscript/data/taproot-ref/82e6db8a76fd387b0eb64cb1d7bf968ef761fb96 new file mode 100644 index 0000000000..fb8982db17 --- /dev/null +++ b/txscript/data/taproot-ref/82e6db8a76fd387b0eb64cb1d7bf968ef761fb96 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6c0000000082abd590dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf4000000001ad7dbb460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e60000000013b495130186bf0800000000001600149d38710eb90e420b159c7a9263994c88e6810bc720b41b44", "prevouts": ["0cc849000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "fc1a5d000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "703713000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ab1d378806798b040ca166344440300741f6fb82aa8969ca5a4c2b8cac21f271c2a3c32f2d98482ccc0ae7bd6919d8eb72134d3589ab943a0402c8a931ea420419704ddfd13dc63b1b4156372563d65f148a89e112fdd9cbf47f8afee5da0a9"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936282619f1a8afd21996d5c3a5869507072982adc0eccbed94d05afc8e7e03bbd81915e430f0db2345814ef782ce895d8c23952d8feef260d8eb90daec0803de3eef05bece11fc4259c24dede9b1787a65bcee91937b36a28d108e88384141e6c4419704ddfd13dc63b1b4156372563d65f148a89e112fdd9cbf47f8afee5da0a9"]}}, diff --git a/txscript/data/taproot-ref/82ec131b824b4c3f3757e1edd238735d0656fc37 b/txscript/data/taproot-ref/82ec131b824b4c3f3757e1edd238735d0656fc37 new file mode 100644 index 0000000000..c54736762c --- /dev/null +++ b/txscript/data/taproot-ref/82ec131b824b4c3f3757e1edd238735d0656fc37 @@ -0,0 +1 @@ +{"tx": "19d3c01403bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb400000000d4d080ff60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700b01000000657831fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49400000000aa2e2a9604f321bf00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f871a000000", "prevouts": ["0c0877000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "894f0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "be6b3c0000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_3", "success": {"scriptSig": "", "witness": ["f62e9109b0b954a14f4b2cbdd8ecf546bc9a0b1ac8497421ec4e80363047dc50beb837570521fa587ffef32067b49b072a0dfe4154ada7cbede415a8faa6fd3d03", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "503a1438c7ff5056987cc50215e85ff51437a7837657b729ad9904ac517f3ac825a81587aa5c780487ca9f74ea6afceb7a5561614c8a23c0cc32d3e5dce4affcf8d4f7e5fc1339f0249e98d9ee1b1404342cdad96f67cdac3bd316ca"]}, "failure": {"scriptSig": "", "witness": ["c6646540e8781cb72f220fb986f517249606cf46da2c22de89ce1bc6e9ec45343a1bc1d045931b5dab65ae615e882cef2a91cb107f4b2f94adb9fdc05d1395b103", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50b3ea659427b833b5edce881509000018807cc6d254cbc585da2de4f58e764da3b80d1687e73184a280689d8b65f9ef480f7338a84b9f1a694f309141ba2586f23705283a15a106ef6f99dda776763ae9f389417748182774fa5bd7224370fd1a9d16b994ea677f6763beddd17ef27f3889f3acb0b53016ba7f6dda39659b087b03ce98b46a122f39b5c7055215d3b2730e16a479d65f41392485bb69ed6549b90c76bdca86e78dddf6"]}}, diff --git a/txscript/data/taproot-ref/8336cc9fb782ee91ec2fca64631271cf0078de20 b/txscript/data/taproot-ref/8336cc9fb782ee91ec2fca64631271cf0078de20 new file mode 100644 index 0000000000..97be45eee7 --- /dev/null +++ b/txscript/data/taproot-ref/8336cc9fb782ee91ec2fca64631271cf0078de20 @@ -0,0 +1 @@ +{"tx": "1aeda83f03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9900000000a9e71ddadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1601000000c1e722ec8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bb01000000a0e9adf902bb0efd000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdf000000", "prevouts": ["6cae7f0000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "02fc470000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "ca9e3700000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cf27e6a544d4d056b81298ae945bd953114a4d53eb4cd249af296d27d349369f6ff84cb0de1f41d907799f0bb3a3d4c37b57eea0ba754203aaf5b7b2671fe888a4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac1cd6ddb9f33f1548d1cedeef681a9f9b56b8dfeb29539fb9e8c97369362df74052bd780e62e78eddfa6319e1e9b5f2922c9c635f126e8f8471707cb2f26f8c7017bb5ae96064d7d19e957b5258c9c864deb4239d29676eb164d7ecbdb9fd5a354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}}, diff --git a/txscript/data/taproot-ref/833a14196d27bc959251f1d19b9e4e6829d267d5 b/txscript/data/taproot-ref/833a14196d27bc959251f1d19b9e4e6829d267d5 new file mode 100644 index 0000000000..1f3f5862c4 --- /dev/null +++ b/txscript/data/taproot-ref/833a14196d27bc959251f1d19b9e4e6829d267d5 @@ -0,0 +1 @@ +{"tx": "bec0953402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9e0000000094ed6d9960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270eb010000004ac8e1f601e4ee1d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8789e0e922", "prevouts": ["686f600000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "10e70e0000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["fb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936832cdd808d94d07e5d991a3d0c5a8b4a06c9fcd7df1eeedb760eeb7a3be6ddfe43d925f8e6664e67417d113cf51c5b4c3126025efa5f83bf5b16dba6746279b738273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d466d9f82b2327fc04ce4429e47540ca0f52fd08e57643f6e07da44ee4246ab9eee8539df42e1fa2e5e9e7b75fbe1b52db879ec8a622b496736c99966ce19d0038273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}}, diff --git a/txscript/data/taproot-ref/8366f34c8cc56c4971befa8d4905f0f436bf6cda b/txscript/data/taproot-ref/8366f34c8cc56c4971befa8d4905f0f436bf6cda new file mode 100644 index 0000000000..434d309c4a --- /dev/null +++ b/txscript/data/taproot-ref/8366f34c8cc56c4971befa8d4905f0f436bf6cda @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa700000000ceefd48b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45f01000000e73d30ab02afa5b7000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7719a5825", "prevouts": ["0af9810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a25e3700000000002251205d2a5ec9abc88b8aa90a173ff406be7abff8b14799a4f6ae3ad10e99906551f7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a3", "final": true, "success": {"scriptSig": "", "witness": ["c041fec03511016f270e27d281cada38eae10b7dd1790a912e5dec61e295cb8f45e2b1515dcc23af7de4c27b6e0d1d75ffed8cf005bb3c1734d44393b153858402"]}, "failure": {"scriptSig": "", "witness": ["6ef33353ad367cdeefca9bfa0f7092aa788f8a6d8ff4b66f7814676037f15b20f9695bbf857d1d1c08f7d1eae4819be8079184ffc46332b9b2a41ee0bdb34abda3"]}}, diff --git a/txscript/data/taproot-ref/8393e8cc899fa71d1c638c5cb8eea55c40342700 b/txscript/data/taproot-ref/8393e8cc899fa71d1c638c5cb8eea55c40342700 new file mode 100644 index 0000000000..6420768e97 --- /dev/null +++ b/txscript/data/taproot-ref/8393e8cc899fa71d1c638c5cb8eea55c40342700 @@ -0,0 +1 @@ +{"tx": "aacaa01b02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1d02000000f3d0e9f9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c44000000008657808f03639ccc000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487941a2455", "prevouts": ["d91d7900000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d", "197d560000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f4b186db3068532a32fed88b54244ea5875c098571a7b8b359e587f4f4af633460b19c0accce5a24a056b98cce949d671afb14dd91d0cbdd469fc3f22c90b1553249301ac20ee33639c015b4a618b106ac87c8ade2ff7aca8998bda2366a260c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d0665fc26da953a71983666256fc3789345858164e4e7f74d6a240db5c0da6cab352ee2a6a8e236a875eeadb35b814571c290bf5fc32e6cf848a4bdb48a3dff6032c3262f8d7c29daaf8f9846bf0ed9dbcc4a0f9aeeb7c8ab8b4ceb985f45a6c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}}, diff --git a/txscript/data/taproot-ref/83945bfa970aa433de420b7ac4f4efcc297ec972 b/txscript/data/taproot-ref/83945bfa970aa433de420b7ac4f4efcc297ec972 new file mode 100644 index 0000000000..b5a074058c --- /dev/null +++ b/txscript/data/taproot-ref/83945bfa970aa433de420b7ac4f4efcc297ec972 @@ -0,0 +1 @@ +{"tx": "bbb137fa0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a7000000004902a3b1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbd01000000f5d511fb02eb6d33000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac27000000", "prevouts": ["1b9c11000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "1c9d230000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "c37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661e47f5626b1dee7ec991e30519a96bad8de97cc54e04912e68057c15d6ba2285a2fb75442cf9d6444c8679a19413f9a060e476aaf84ff603b3b22173ec950d19a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e8d213d90ee48874bbf2b18160b4fefa78452fd9fac91ad5f640de90a3ceda28c"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ecaceb5ed46230d7b49b5ab2b34a8a36729addbd68724e584e32fb6f2cc866bc08d213d90ee48874bbf2b18160b4fefa78452fd9fac91ad5f640de90a3ceda28c"]}}, diff --git a/txscript/data/taproot-ref/83970d72a6907256d4feab8e061182642c3d4b24 b/txscript/data/taproot-ref/83970d72a6907256d4feab8e061182642c3d4b24 new file mode 100644 index 0000000000..3453047685 --- /dev/null +++ b/txscript/data/taproot-ref/83970d72a6907256d4feab8e061182642c3d4b24 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ae0100000008a2ec32dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9c00000000ab39da2d03d6d489000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc742d7ef21", "prevouts": ["0d91320000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6cac590000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_4b", "final": true, "success": {"scriptSig": "", "witness": ["51c615f74c4bfb2a16f20334483ab145ee4219cad3738cc52c15ff3728d75f599768728bbcffd7ed615ac96674e46d7697c2a6da75a027df0c8143ee112870fd"]}, "failure": {"scriptSig": "", "witness": ["75e7c24a8ee892730f0f9c5f8f70babd35c480db5048f5818ad4db9f7bfdc255a98ef0f17c30ab9fda1bfd9c402304913022677fa539649b0e37cfedc2fbe4604b"]}}, diff --git a/txscript/data/taproot-ref/83b00e365af084f70ba64981a783c5ec81c0e650 b/txscript/data/taproot-ref/83b00e365af084f70ba64981a783c5ec81c0e650 new file mode 100644 index 0000000000..a61e742cf1 --- /dev/null +++ b/txscript/data/taproot-ref/83b00e365af084f70ba64981a783c5ec81c0e650 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f3010000005c7b308b013a071b00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac34030000", "prevouts": ["1fea3a0000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090256cffc752b1fdaa9103090c4c563227213be9648420b90299cb28c029182ea234713a9511fa6aa7f04776db56ae40e997cfd93d0b64614f5cb7eeb387a2a6843a073858936975d88f4e9824386c72d5d53a4ffdf59aa0c69c95ed081535f0dd7b61423cbbf043d0fa0884dba70416dd460f36da7a9510ec647a355a76c7c4b8c4fe3bf24a5ad7b7adecdc4207910251354bb2a1dc599176cb27543426ae01c41fc446658fcc908a31cdfc6351ec94e1d1d2b1dd938384c6692ab857380fc8575484c72b7af7cf97d68f68a066f8311e39b70a1f39f4b2c27df9ed77e24e3cd5c9fd6b99186f2a4dd1dfab7e293dda7e43fc979c5f06fab25271accdda3bc6eac852c44f02285ee0f632607404b8d042bcd1ab3069f528b63f6b59ec1354615795f965ba3d11e32e74cc8f291fb17d9bb4f90ce312b67dfb9706a117863c664e0de4cdd6f557c3def01e257b589acc5f5c70665abd50028fcc83b50894f57e279e39b4502023b402367806ef07bd1df63cc28991a8ed27646da3a912b224590aa80bd05113cadb0238eff5e29e876e53a08f0f051fc97e8086b8d43a11e3d1c917b10343f5100b293aa24874a3468c99c3a6447074d55d8dd0112f1e88b87c5caae6cd27e8f40e234750956f0d527fc81d00b6e450723ea14c532738a1d10ac8181fc1098cf4104ad97e3b8a6f7d2dd1bbd449d4e49e1d897092ee3ed53b05f446ef6349fa00dfb37b775de", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cdbe36c8d36f09fc182996d5125522ce46e288b7df8e779685b1cb3e493768f59c9e480d0f492be6e2f1ef49af1ad63a3a1c7bbd1c59ad16db6c35add41291c9811034f174cb7bd77652d345f06878a8d4eb3ae1b92590cd10e2563bf228d2d6bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}, "failure": {"scriptSig": "", "witness": ["4d0902e119470798dec3b186efc64abfbfc69df83ffd4de7ff38e90851e04a31a86c32dec05d0d32ecc4ae8d89d335dd8ddff1e69c0d8725520a39005e646340307e8fa2ce21d59ac1296a589002a00340a34b06008e322c294d663639adb40cf728f594469af8623bdc42071077eadf05c3b187bbc23c145b4fdaa37dc8d3a135a8c330109eee5888856ddae86b7979c8f53dfea489c09ed94d810409f39edce217398cb965eaeb8d6142d947f6e1d05bf2c4909b5bbf372f0d14ac44aaffb6f23bf153553298952cc2953b453fb575590274f017969bef4786deb21f760973c458dd2ec859a0dc6bee24a75c07a3a5e5d11a928c2754f1752db28aa34643686d24510b20296d8cdf965130a8c5e47c848cc043df8b181745e750afa49473bdf49dac963c8628b74ec02152a5b155bb108813c3e733969bb9f014d864b204eed6259d97f70e393bfa58c0ff3dd77901d5a4869053b0822620310d2b34671f58bc9439d84254644300966320ed74992d83086d98ac0f34062d664c2065a49b3b0f130fa8f936abd16709e13341ffa0179a276001885b7614bfc5a392f7bba574945f9cd6f40663ba65d6e7980145d5dd25abae21f724815565699d5df6be0ded72b459ef2cd853fe0e1f1e64be7bad4343ecf404e24b163faeb24755f4c8d29093b769c2b9bec3f8133e7f5a5bfd7b69932d0060858ce7e2172cad96d0ca4fc5d5f25368b9eaecd8544f857a7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365ab412a59dee6e3fdf14a7910ee01c80a0ab04929895b54093d5d7f83333528720e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1aac1f02719ff09c82d93c60ae8b21e31f1ec3fca4030b09dbe2604c5a66091c209208a3d5cb0b20fec302022af702ea090b934668d0752a16a75cba2aae8c677"]}}, diff --git a/txscript/data/taproot-ref/8434ef7375003e0e049d9248cca04a7d89a51736 b/txscript/data/taproot-ref/8434ef7375003e0e049d9248cca04a7d89a51736 new file mode 100644 index 0000000000..273b90e9d7 --- /dev/null +++ b/txscript/data/taproot-ref/8434ef7375003e0e049d9248cca04a7d89a51736 @@ -0,0 +1 @@ +{"tx": "56b4ad660260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708400000000a354aaeb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c6010000007d9bcf8c03f5b61c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e746000000", "prevouts": ["81920e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74e50f000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_65", "final": true, "success": {"scriptSig": "", "witness": ["c67a892674b55913536a1b86e02331a59492878def3d40d83fce5ae88ef80e4f93a32d8e933002060e26448685db9c2ee46d4bbbb8366733c24e8b16ab831f39", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3f1ae307735c7bd08745d9ba68a62c09e9ed48f39450a1cfbfb5eb7198e9c97a625a50692c1977c346a20d99f4b6490b8b4f304cc559c17d8e2c7528b585404b65", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/8442ffd276255dd9c5995c977f30f700234f866f b/txscript/data/taproot-ref/8442ffd276255dd9c5995c977f30f700234f866f new file mode 100644 index 0000000000..c86097d517 --- /dev/null +++ b/txscript/data/taproot-ref/8442ffd276255dd9c5995c977f30f700234f866f @@ -0,0 +1 @@ +{"tx": "359812e802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7201000000f61b3eff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47f00000000acc258aa01c7a31a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88accb010000", "prevouts": ["d21d2400000000002251204aa7ef3c48fcabcb6102b9295fbd3d8d5e51a18011383dd7b1650a23dcb19459", "fe98330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_6b", "final": true, "success": {"scriptSig": "", "witness": ["8829f4ad8d433e9a75bea23a67abc1f638720439cada1378d01191f39dc386c762a8fe2ad52ccb4cf539506fd07fa13585108f9cdf3f5bbdb913b4fe34cebc9702", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c8016b6737c31aed802bb2d0c0c4692101d96dc8874a8037bae43314f33e0a9957ccfbe9b59bdb35a6fa58d9bc83327587deab6d9366a21d62fd17ce7aee6e716a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/8462f1863bdba9f38df24dbeb39d9be31a8b3d93 b/txscript/data/taproot-ref/8462f1863bdba9f38df24dbeb39d9be31a8b3d93 new file mode 100644 index 0000000000..403dfb1a5c --- /dev/null +++ b/txscript/data/taproot-ref/8462f1863bdba9f38df24dbeb39d9be31a8b3d93 @@ -0,0 +1 @@ +{"tx": "a16810340360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270320100000001d67dfb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701a00000000ce8a8e9e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40601000000d70e389401384e260000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79622030000", "prevouts": ["40320f00000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8", "2701120000000000225d202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "41d2360000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "d27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f894c78f54379a902572b9ff840f9e21b54e663bd24ed566c0b03aa8c4c0e0a633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a9b801fc18e2353a9cd4de337bb33433fbe6225e21bb8b5572b0acaa50d11b7f3"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936285975d087512001f0808626ddb099c402deab2a31fe6815cda4a96046af47231260ed9ec9ab1e79007d15fbab81df65c0fb14652b0fe58f2b730a3e13657de0e39f192d4dec24b48e9231a08b7d2e64fac2040aad69c16c1d9eedfe5fb62ebc"]}}, diff --git a/txscript/data/taproot-ref/8478b1cc13202df27bd080e55410e541629423e8 b/txscript/data/taproot-ref/8478b1cc13202df27bd080e55410e541629423e8 new file mode 100644 index 0000000000..8366bb1c92 --- /dev/null +++ b/txscript/data/taproot-ref/8478b1cc13202df27bd080e55410e541629423e8 @@ -0,0 +1 @@ +{"tx": "faa2764402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c11020000009f2c27d5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b77000000005ce06ec703e2aa73000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6fb35962b", "prevouts": ["7b284e0000000000225120e0ca4cb327604d8bb54d855256413a632bce5e2185126ca2f73680d7829d5a91", "ad77280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a93db9de682c659f71e2df2283b4442c1538d3696de14cf44411646e85b3f4a8"]}, "failure": {"scriptSig": "", "witness": ["6a6f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/847ca904186295e8fd47a4e29885615907cb992e b/txscript/data/taproot-ref/847ca904186295e8fd47a4e29885615907cb992e new file mode 100644 index 0000000000..ef281bba6b --- /dev/null +++ b/txscript/data/taproot-ref/847ca904186295e8fd47a4e29885615907cb992e @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41a0000000077b56489dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdf0000000045bcf180046ed1640000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a647a36e60", "prevouts": ["e4d03d000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "4dd2280000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "be", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93659372e262d5a0f9ef536aae388303ac1332900989a5444d826ec2580d67fc3a21a521886ab29756862a71c0453b77f880429f1d68b1fae0f34d555c1e4747b3e7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a5bb2be9c002390585aecd6a44dd843628783a58b1ff5512778ad80556de83f015cb0c87b91becc5e8e88545f518ccd4dd82a3936db012f0c0e2ff8a479534101a521886ab29756862a71c0453b77f880429f1d68b1fae0f34d555c1e4747b3e7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}}, diff --git a/txscript/data/taproot-ref/847d38e6322523b12583cde1ac03aa9cb6c11494 b/txscript/data/taproot-ref/847d38e6322523b12583cde1ac03aa9cb6c11494 new file mode 100644 index 0000000000..921b8647b0 --- /dev/null +++ b/txscript/data/taproot-ref/847d38e6322523b12583cde1ac03aa9cb6c11494 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf60010000006c56fddcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf700000000cc52dde28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41200000000d0282f1d047d49ca00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d8000000", "prevouts": ["a7a86f000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "7af02500000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "2e6e3600000000002251200fe4658e0dbf66b6be10f530376fb0e6dfa185e9d7f38ef5d5af1eba17e45594"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d06edae5b29d15a8589ecda9763945c36b5c241cf3df1afb796e5c490e9af3a4"]}, "failure": {"scriptSig": "", "witness": ["6a5b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8485b7daa7b9582b7257e4ad6aa767ad9b2c7173 b/txscript/data/taproot-ref/8485b7daa7b9582b7257e4ad6aa767ad9b2c7173 new file mode 100644 index 0000000000..92a3ba4b02 --- /dev/null +++ b/txscript/data/taproot-ref/8485b7daa7b9582b7257e4ad6aa767ad9b2c7173 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe7000000001665f807046b096900000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48788f9e455", "prevouts": ["ce146b00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "c57d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363de8b7b4122057e6036b6b3743e89ea35e047ef60fbd0be824b8516a5d1bfd004639ba4332756735e08e9dd0c9395e600a8a67669bda3acb22644b013566df8000378a892e4dc43a17c9ebd71803200f2f24c9a40c2827c304e59be9b4a7df0b"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826d35158b06e93427cedf9700445f423da8a62a86b9572893cb3b0c5b8130f93e00378a892e4dc43a17c9ebd71803200f2f24c9a40c2827c304e59be9b4a7df0b"]}}, diff --git a/txscript/data/taproot-ref/848ef68b2028c2d1d2c774427baef8811e6973c6 b/txscript/data/taproot-ref/848ef68b2028c2d1d2c774427baef8811e6973c6 new file mode 100644 index 0000000000..764601be43 --- /dev/null +++ b/txscript/data/taproot-ref/848ef68b2028c2d1d2c774427baef8811e6973c6 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c900100000041cd9365dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb300000000928020b40148ac3f0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e734010000", "prevouts": ["e292480000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156", "0e52270000000000215f1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364f8c4c0241059f879e07c0bc8f393a68e96022201a845cb28a0ca7d7bda2740f4b04f8f54a0a76ae0e4c7aeaaef28ce29fe1b2cd8b193a4d28e758ec231d2b883bd198ccbfa9c702c0592bb8c84a948c36ef9eddfd1aec8278a333dab45811656e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93665513df49044bb35b46ae900575a7eb3f6e681c52a9940fe88416598d87c452a3070c0d29d47e9fe7be7df27becdaf45cc7da31561e827162b16aa01fe84c4a24f44ecb3bab6b962a7ffa14a2ce082ec551943f33ce508b63a8ee30ee5e49264"]}}, diff --git a/txscript/data/taproot-ref/84b78b9ad073a948405f0b7ab62f9f69118ba8f0 b/txscript/data/taproot-ref/84b78b9ad073a948405f0b7ab62f9f69118ba8f0 new file mode 100644 index 0000000000..3066b77180 --- /dev/null +++ b/txscript/data/taproot-ref/84b78b9ad073a948405f0b7ab62f9f69118ba8f0 @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5000000000de02e99601bf326c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876d010000", "prevouts": ["5f74740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b4", "final": true, "success": {"scriptSig": "", "witness": ["ab872e6a59e30e38791afbd7e3e528b83731d6ec6a91b4a195a975bb55dcaa8f2c6b2d1254846413fbd7ddc33eadcd632914a4b1726ad459f5156be39b459dda83"]}, "failure": {"scriptSig": "", "witness": ["9b036a78fc192e530dd3291f0394faa404f3a9ac30ce54008d17049cf08ca28373d7770948cc4a4daec748f6d28161827ae03e5072c1d9ced55a995ed3343e41b4"]}}, diff --git a/txscript/data/taproot-ref/84c54f3da6a5e6fab8e1f0e9e437a602b838b808 b/txscript/data/taproot-ref/84c54f3da6a5e6fab8e1f0e9e437a602b838b808 new file mode 100644 index 0000000000..6a6ac6aae0 --- /dev/null +++ b/txscript/data/taproot-ref/84c54f3da6a5e6fab8e1f0e9e437a602b838b808 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd700000000fbd7ecb1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0f010000001dc16bf4039bbc640000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca8010000", "prevouts": ["f84c4800000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "ac261f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_91", "final": true, "success": {"scriptSig": "", "witness": ["a8b0ccd91053aa6f75806777f49917fbd414369473204b5304e83df5fa9f9b01aaef1e6624db43330a47439ff3982c569c36aa3665f167e2396e7281000eea2903"]}, "failure": {"scriptSig": "", "witness": ["165a25b414f4fac76d97b5945bcfd00721eeaf105c96d4de1e08b03838d09305b861aca6404486c92c4c1da4b33f047ce3d7be1318fbf527c3c56dadb3179ecf91"]}}, diff --git a/txscript/data/taproot-ref/84d1cf1063766590aee538d2b55b7bd3698c0de7 b/txscript/data/taproot-ref/84d1cf1063766590aee538d2b55b7bd3698c0de7 new file mode 100644 index 0000000000..c5e3ba3c79 --- /dev/null +++ b/txscript/data/taproot-ref/84d1cf1063766590aee538d2b55b7bd3698c0de7 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c485000000008b339dabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0600000000e4e34c2901612901000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48716040000", "prevouts": ["f0d93500000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1", "dd75230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_77", "final": true, "success": {"scriptSig": "", "witness": ["8a2d7940f583926ef1d2b26a5caf70e9a1521d8003a94aa2d109a81bceb8463cb5aed13b1030978dc80fc2ccdb4406e1bb280185d4d66f1892bb93e95d780bc302", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["de5a9ffe358c6f96c9b9b36b0a33333da6539d4cf81964c1b77807df3c5ea75baab5adaf0a5bbe117389accf1ccf1ceb8e5ef1fa9868dfcaafec87001a519dc276", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/84dce9fa92c533d455e0c1f97179960220f0a855 b/txscript/data/taproot-ref/84dce9fa92c533d455e0c1f97179960220f0a855 new file mode 100644 index 0000000000..a0706edfc6 --- /dev/null +++ b/txscript/data/taproot-ref/84dce9fa92c533d455e0c1f97179960220f0a855 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfe00000000526d26b7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2701000000c3f9d3d90238f9730000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79600000000", "prevouts": ["20c81e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e96a570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_1a", "final": true, "success": {"scriptSig": "", "witness": ["6e3d234b45458616b432f951eaf3bfa9348f9d18eaaa57f5928eceb141a837f2ad2d54132538b48ecb27e077ca4a20fb4cf5b96fb4f7351a535518f8abde92ae81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["d5f63c5027d4441a79055ac686bf7196a0ae298d677ef524d0d3d17ebf91a971b13331950a51a4d2f2ef752758c5556db444d993abbecc461172f66cb304835a1a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/84f74ecd7dcd980cbe8f5c5df3e9de9eb9e2198b b/txscript/data/taproot-ref/84f74ecd7dcd980cbe8f5c5df3e9de9eb9e2198b new file mode 100644 index 0000000000..154a04af71 --- /dev/null +++ b/txscript/data/taproot-ref/84f74ecd7dcd980cbe8f5c5df3e9de9eb9e2198b @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0d00000000c0b8e70b04391d53000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac50020000", "prevouts": ["fffc550000000000225120f98f853e6b4327f1b4277c37b28aefc415c1e953b3fa9f1ef781dc42a80d9b71"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f7693534e61619efc826df84c4da4b2cac3827d7f1ac50b56bb7a432d3ab8c0"]}, "failure": {"scriptSig": "", "witness": ["6a3f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/855137df77e723cfc86499f4fdb99f284ce7dfb2 b/txscript/data/taproot-ref/855137df77e723cfc86499f4fdb99f284ce7dfb2 new file mode 100644 index 0000000000..eb998d0c77 --- /dev/null +++ b/txscript/data/taproot-ref/855137df77e723cfc86499f4fdb99f284ce7dfb2 @@ -0,0 +1 @@ +{"tx": "0a67d5d202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf03020000001e51faa7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7e0100000001bfdca8034512b7000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac9d83214c", "prevouts": ["bb446500000000002251209884719338e1397826c7fc76b57dc9070e1ae6721fe0f4052d3f32cbc4476e6a", "857d5300000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "success": {"scriptSig": "", "witness": ["9a93579f0dbc902f20eb3236a29b7795691edc34488210105260dc33c84244ab7a8be3bc9902ab848f83aadb729fa498e01c72a0b8ad9cd2f7360cf8a87d8342", "dff13c08fd97ac682a573ee694c37059b46188b1d526eb3d271d01abf3d3e8141f8113c8d0fbc0a74cdd677197f4ef907c45ea3af9beafd302ad0312f7a0ea52fb2545864d1d7b63340ffe54c9415e1965ef3e433b5bc241e80c610ff8ca934ac9a7d7de52c4fdd78d25726174f2eeb3ba10eefe1fffbc06d2", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aa89738a4c7df4b7e53305df69816a357977ae495ada28d1f508ae0a3b0f08607008d2479bc8b48a246a101ee4b49f0a15a2b0675f0b4b0afee40f21d20b176002322d9b2b60b6e4fd37374163d324c1a6de10f97494d57fc835c33571c5954c8b48a46ebf64bcfb2c54503bf63dee8c40bb51ab59d3df7fecd6d739cedcfe31d768c3c060aa2af011a8ed5af22581cd10184f0ac421571baef6daffb4794bbab275aef13afd117b1160c12da710c6f8f8edb229a889aaf5082ca0fb234dad31bd7a0a2c186fbb5f5bd36ce6bf04ff01cc35949f4ca5d8c5226548c44d324f93473662e31fbff764a3c491e007914a33226c3cae281cdd07f30e6995bef0cf025c2274a75cb4b6ac9405a299cdc7fe3c10b56a5a3133c41cf4007b7e1d7f7a0ad997ed7d66498ec30b5244ac9c72026ef3138743e712b33a45d0b4b81becfa754e45f14ca2740c90eeac17126f8b08e6fb37566a8e657e0f4666eb6c857038e6d4518202151ea7f2cb6516f16339991381e736cda7031484c4b5efcec0f41a079773c21fcf7a9e922d8f9e257b114c80cab1157d015696785b2f06431a2263750000000000000000000000000000000000000000000000000000000000000000", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["9a93579f0dbc902f20eb3236a29b7795691edc34488210105260dc33c84244ab7a8be3bc9902ab848f83aadb729fa498e01c72a0b8ad9cd2f7360cf8a87d8342", "6e981877b4503e0d242ccc256516bcd30cf0d06ca1dfdb0fa15eae4e28be9e0dc98570a9028366a8c3563759719d1069bf15b93b893ef58bfc4ef0a14f650b96928d0e6a55f94b099e0022f47650fb9377a072b994b16763e14c6e3406f2e806393d50459b72167ad8f970852979d4d127b5b22aa951ba2f", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aa89738a4c7df4b7e53305df69816a357977ae495ada28d1f508ae0a3b0f08607008d2479bc8b48a246a101ee4b49f0a15a2b0675f0b4b0afee40f21d20b176002322d9b2b60b6e4fd37374163d324c1a6de10f97494d57fc835c33571c5954c8b48a46ebf64bcfb2c54503bf63dee8c40bb51ab59d3df7fecd6d739cedcfe31d768c3c060aa2af011a8ed5af22581cd10184f0ac421571baef6daffb4794bbab275aef13afd117b1160c12da710c6f8f8edb229a889aaf5082ca0fb234dad31bd7a0a2c186fbb5f5bd36ce6bf04ff01cc35949f4ca5d8c5226548c44d324f93473662e31fbff764a3c491e007914a33226c3cae281cdd07f30e6995bef0cf025c2274a75cb4b6ac9405a299cdc7fe3c10b56a5a3133c41cf4007b7e1d7f7a0ad997ed7d66498ec30b5244ac9c72026ef3138743e712b33a45d0b4b81becfa754e45f14ca2740c90eeac17126f8b08e6fb37566a8e657e0f4666eb6c857038e6d4518202151ea7f2cb6516f16339991381e736cda7031484c4b5efcec0f41a079773c21fcf7a9e922d8f9e257b114c80cab1157d015696785b2f06431a2263750000000000000000000000000000000000000000000000000000000000000000", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/857a099c2b46ccc02b866b3d0c0eb37858af7f6b b/txscript/data/taproot-ref/857a099c2b46ccc02b866b3d0c0eb37858af7f6b new file mode 100644 index 0000000000..7b2cb0582b --- /dev/null +++ b/txscript/data/taproot-ref/857a099c2b46ccc02b866b3d0c0eb37858af7f6b @@ -0,0 +1 @@ +{"tx": "aeb1416d02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1400000000d2529385dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2f01000000774ad9b801e1a53e000000000017a914719f78084af863e000acd618ba76df97972236898769876854", "prevouts": ["c5d0730000000000225120cd23ad59c6016ee1812d662f3dfa4b488c728badd6e7eac21806d0875fd86aaa", "03124a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93659b2dba12142179b1097cc93efd347ce95e71dd12a795db31a4271de04236572"]}, "failure": {"scriptSig": "", "witness": ["6aa8616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/857c4d2b4cbe976e614059e4d9eeb613c69a523b b/txscript/data/taproot-ref/857c4d2b4cbe976e614059e4d9eeb613c69a523b new file mode 100644 index 0000000000..d23b12cfec --- /dev/null +++ b/txscript/data/taproot-ref/857c4d2b4cbe976e614059e4d9eeb613c69a523b @@ -0,0 +1 @@ +{"tx": "deb4eb260260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708801000000b89731f8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b360100000085b672c00156510a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a698744740", "prevouts": ["80ad12000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "eebf20000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "3b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93607ffa4357b1418f2570d4fe87dfe37d7ee3541eab3f2e6079ff7fe47c21164c3ee7dbe7f66d64a980d12157b84c42445cf47ca482a00d5396c717810eb35e86629f15cefa9911251712bcf83078e1db490f7db40c14a26e0e577f39f7cfaf11f"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e29ca03a9371c532b03ec93c4ffb27f967cf1c414c08502d0b6e094a92f799b5fc7fa9328de6285e10958c6b3d6f5d3c073b4c582e31cb42904dcf82d4bed78a29f15cefa9911251712bcf83078e1db490f7db40c14a26e0e577f39f7cfaf11f"]}}, diff --git a/txscript/data/taproot-ref/858fcb46fd11dfff505511ab32c43de93cb923ab b/txscript/data/taproot-ref/858fcb46fd11dfff505511ab32c43de93cb923ab new file mode 100644 index 0000000000..e747e8c511 --- /dev/null +++ b/txscript/data/taproot-ref/858fcb46fd11dfff505511ab32c43de93cb923ab @@ -0,0 +1 @@ +{"tx": "e714d45702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf73000000005e8f3194dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1b000000008732789101f288010000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e798010000", "prevouts": ["9d317d00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "c26c240000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "be7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd522f1cef67c43cc160020062cdc11d631b4f6eefdd5e68f18dfd86aed0bbdde4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8c20793b34d3eca391845c9ee05577f0fe1c8a49b621d2ce1a9da4783f236266e6f69f1f3a976918b4a05b157c0a8e21d478cce8b5d78fdf690138c8d187dd5c9"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb7c20d175283666615e94eef717cc04c54a6d9612bfb359a13b4f03ea50e15671092566d000aee18de877d7d37a6499dcaa40717b87fb42c4af8a156e9c8751ba72dfb389a6a0bb3f8b3aa7842bba2225719f72a11deb6eb959f4e6afb1e08b911ebac8c921821ba74d98d656401ec4b56b2bfe8f672693a939227457b8b1a2"]}}, diff --git a/txscript/data/taproot-ref/8592c80000cf304bf52753ab309ceb04e2652ec5 b/txscript/data/taproot-ref/8592c80000cf304bf52753ab309ceb04e2652ec5 new file mode 100644 index 0000000000..5e7ae0226f --- /dev/null +++ b/txscript/data/taproot-ref/8592c80000cf304bf52753ab309ceb04e2652ec5 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff0000000009808edabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba601000000851525c48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47701000000859dffb10302a2e2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374871878ff56", "prevouts": ["74b9810000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "6309280000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "0ace3b000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00639768", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082088456232115bcc24dec0b5a24cea45f7d15fc3427ff6cd91fcf5dc3f7efaf083288455e3867d2ff7594cc417650f42f79f93c98aaa5c5ef25eb3554c8bf2ec6282285524a15c732567d099967405d35f7136f74f48f011bc4ab279ad8d14f14"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd36adc2e08ee387ad104b346fceb00365162d18a911b71ada63b74469326ca305f4756eb22a3c38e0612932b2e111811a644330efb7a4d77fa512235b8ceac2f213b900f5cb66b025bdcf0538d69427e8f93cfc9741b2125e61cf9215fad53f373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}}, diff --git a/txscript/data/taproot-ref/859bf525139277f5088a3ce814f120ba25928ba7 b/txscript/data/taproot-ref/859bf525139277f5088a3ce814f120ba25928ba7 new file mode 100644 index 0000000000..780881d543 --- /dev/null +++ b/txscript/data/taproot-ref/859bf525139277f5088a3ce814f120ba25928ba7 @@ -0,0 +1 @@ +{"tx": "bbb137fa0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a7000000004902a3b1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbd01000000f5d511fb02eb6d33000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac27000000", "prevouts": ["1b9c11000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "1c9d230000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "cc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bac3d01da396ed984241b54aa1bb3aef909b4fdbe414b6dae042f63774e412bba22abe4a548a0fc6dfdb5b637d4f02bd7b4a4be5fc13f7c30d33fe8bd172a30474a999e2826f1f27f01ebf91ad073bfebeca039a55919a1ef327838bd290026ec1da8cea892037e805a477afbb54b1f5ec380954f076c0bcd3c4e3d4797a8d6"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082af68f276ddb4c0fc7f0310a620a2f1f9fe6c0e4e29d0e280a559099e56625bc6391effb841e4c3f4ca92b599bc572f2bc6440711e20bdc5ba4fc353379105b198f95dbc4edc81931664a748b39a9978dd32dedaf5c850114f6bd2f5098c050fb"]}}, diff --git a/txscript/data/taproot-ref/85c3b1c5bc8469eb9f51ee2b19c514d2dcc9d4e5 b/txscript/data/taproot-ref/85c3b1c5bc8469eb9f51ee2b19c514d2dcc9d4e5 new file mode 100644 index 0000000000..866926cff4 --- /dev/null +++ b/txscript/data/taproot-ref/85c3b1c5bc8469eb9f51ee2b19c514d2dcc9d4e5 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4020200000098371f3adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbc01000000059cb1e5044b7b7900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6f4010000", "prevouts": ["a15f32000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "55b04800000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "a17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c812096c7134552cd7fcb4579ca5ad4743c34f32df04030bf869cb557754a4a4fb15e70bbc27f4f9ee6ce894c5f8660c4bc0a21501abf5c583e18e279746b733479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae668dba12609f1dce2a1e29faaa62ff248d54f408b31ef31944f67a579d4fbb4"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e856012e14d1393796178822b876e37f88bfb8786abf6d56f290a567bb98032f4de668dba12609f1dce2a1e29faaa62ff248d54f408b31ef31944f67a579d4fbb4"]}}, diff --git a/txscript/data/taproot-ref/85c9ddc38fbb85bd175bf3ac00a626752b964461 b/txscript/data/taproot-ref/85c9ddc38fbb85bd175bf3ac00a626752b964461 new file mode 100644 index 0000000000..b65e5aec54 --- /dev/null +++ b/txscript/data/taproot-ref/85c9ddc38fbb85bd175bf3ac00a626752b964461 @@ -0,0 +1 @@ +{"tx": "2168928d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b680100000082a688d3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0600000000b79a99bf04f55a8e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ace8020000", "prevouts": ["0ab323000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "5cb06c00000000002353212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["9621b319c232918a7110a0dda37564d742a55c1be3d598ea7d166118b890070cac09138ae5f98033b6f64e501f2c6196913f21224e80329f83922ebf9ff84a92"]}}, diff --git a/txscript/data/taproot-ref/85cd37fe2c7301fdbdedfe4eee2559a27232c9e1 b/txscript/data/taproot-ref/85cd37fe2c7301fdbdedfe4eee2559a27232c9e1 new file mode 100644 index 0000000000..a4adf4713c --- /dev/null +++ b/txscript/data/taproot-ref/85cd37fe2c7301fdbdedfe4eee2559a27232c9e1 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffb01000000542e9722dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6100000000f28b12b601df1e4500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac50000000", "prevouts": ["54a96e000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "b69c1f000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "dc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082276acb01c569c39653cc9be144b4517abeee153b1e65c2a7dfaac73ffa4f7941ad29df8a0e62e4f40897f8996914b12118c918ca2851b639742aeab01f587290"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ec1c00ca223002bbb4a77b296f490434ed2387551884308e16e8dfcb52ea12e9f3bfe8b0458382ba4f4ce4b13b8b707c198a710172b0004e49e202e4d70abaa7b"]}}, diff --git a/txscript/data/taproot-ref/85db7ff2b922cfebbf367553f67005a39f7c7481 b/txscript/data/taproot-ref/85db7ff2b922cfebbf367553f67005a39f7c7481 new file mode 100644 index 0000000000..c67b4336b2 --- /dev/null +++ b/txscript/data/taproot-ref/85db7ff2b922cfebbf367553f67005a39f7c7481 @@ -0,0 +1 @@ +{"tx": "0adb3c5a0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c30100000007c9f6ac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704a01000000e25f26870387721e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2a817952", "prevouts": ["569012000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679", "59830e000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "6f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936543e4415e2a4e40b55ce2e476aee6da566062b9d3b6813c54da2c8fa9b5db829796126e2d69a152489172163b4bb3b76a5285668b37fe09a10764d2324ee4a01a6ef766bda57b4717926485a86d332fc460fd2733e6a54825f17015621dd4290"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eee33f25a3bc4431a4899fa373225b82f91b265358d1b8c12eb75241dfe6f4bf6dc39ce81a6fea632ecf565fa45d7a7ca50aa2e3b548038c9066d72b539243596a6ef766bda57b4717926485a86d332fc460fd2733e6a54825f17015621dd4290"]}}, diff --git a/txscript/data/taproot-ref/85f392952d2f71a976ea2c35e174e534ade34805 b/txscript/data/taproot-ref/85f392952d2f71a976ea2c35e174e534ade34805 new file mode 100644 index 0000000000..76d26ba37b --- /dev/null +++ b/txscript/data/taproot-ref/85f392952d2f71a976ea2c35e174e534ade34805 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c455010000002e8aa283bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1c010000000ded30ab019a4146000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478713000000", "prevouts": ["2248400000000000225120fc4f9d8aed21e545c10b3b4fb5f7ffa2432ec2f4c867e738428f21cc99cd5336", "4c276f0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["1e1f83551bb2f331bca92b461cdf8a63776e92073723dfaa24cddfdf85444fe37e4a3dd0bda69af212cdf64c6b4a2dafb1ceca20b748ddd4ba07e87facba897201", "71905065eccacd55d9a6d165d50fedfbb2d9b18962f7ed13600f0a7ed474250792719ff4eafe1b845a981bdd4218a50467da843feac66c4460b4bd10f8df51b2c4bcdf4a3ce34c5c818842fabf052e89d90619d38bed2ff59cfac6675ae4a15d71516055936cd58c04403235b49a77361946ca1a61afcfc359bdd8c7445e8b851b2c5385f2a40700779b70bb6134103ebbd337c662e0fcb3f1", "75003535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a2ac91693535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a26eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cafd838e61ab3aa45c319601b563b9c658905b907134deb4cc79f3bc13ff369b0000000000000000000000000000000000000000000000000000000000000000273ca7b5af5c33cd596a394254ccfccd1ad7f414cf24eaf5251ee142edfc6bba19e1974746bcd95f883b2c5f8b9cd70ecc189bb284120cbe237fccafca83785a0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2f292326c7bf2ced92e8e5f55f7d4c058bc53f0dc5d72e6f54d90a99bd448a0a7d3178fe8ff3d1648fd0414c507f32ef1a859472bba31e5fd87f9395eb28563d000000000000000000000000000000000000000000000000000000000000000053cb80cf27390b5f3a9b6e8f7b62b6973f471195333decc81153a008733c93f4fdb984c50376bf112fc5b1ba5121971048d8604acf0e95c0aba37777dccd84f7265ff857dd5353a6f266df0c827cc2177bd50674255e0d749a1de050f0543a3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa255cc08baca582f171c88e3afb5850782245b5ed7b91c999e195e37d9159bd5d8e80d80e4a0fe1afa47b4cdcdbc993cd0db79675bf4cd78cc37b4de49bc27cb8b09e1ee9dff2bd5c170a69d6407e15bee592ac7316759c0b21c1ce5c1e004f3bfa663a0599002637d08bc203534805f26d034051e6a67e85ccc9bd956c8d8706de45c3a48843ffe045e251fe069222fe8da2ee54f1847880aa81efdcaa9d8525d20e0edacf2383ded399026cf8bae72fa36b1caa97db067cb54ec3ec4bb5d4284e14408a569f47e5deb40589b32bf49aa1bc60a3632cd7e9e9585937c90d6b5f93801b1dd258f77e7dbd42a444590190088faf2dfd4654dc4249a5d6ad34325ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d5a204a83fe59bacd1cae520ac4d3bed216198175683bb791441d91e89feaf10000000000000000000000000000000000000000000000000000000000000000ad10f52d27e62a6a591b25683e510603924fa6b0f324a16e58aba1d57e478ab50000000000000000000000000000000000000000000000000000000000000000612e5dc139866e7b4626935f13e419d7c281bef6c5b9deccffb02e9f640fef85ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff737008e4121812f7dfc661b4b82fed08887fe73b0c9217265c2827b63ba2f13f59d5370a9318774a5bf4ce7ad10f052d6dd560323b574a7a7e042e3b227c162770be6fea8df19f1fd40bb23931116b7b3d192544775e300f6ade15d75b2779cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0e1f2198ddd478c68fe8bc5cae5fba8f760af3223933412457b382baf708df1000000000000000000000000000000000000000000000000000000000000000057f91a0ae05815cff02d68409806996d2bc455488ec896bddcee07d0c4d6c70e139403ed87e7aea928d90e04ec3797d79f44ff8b7c3d9e6ef9026af18da7ced2aef523a35a1d80f25f28c52fe09f4bc05ca9ca4c55aea7c169ac86caaa8897ad0252fa602c378c73546d62399d429bcd6a33226f823339715698ea6591be845059b987a2a1bc15e860ae688586a890bd57be17a71de63951967861e056cacefc3e95b857a1b91d9aafcf992cc9dc01a2a4e6f9dc4c8c5e5c4349f555667d7123d849ded7c59f5b86a0da4c79ba396037cfeacc2ac9a8670ad8578ef2a84e5b6bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ea8ac52b648c54e233c15f34def3254a14db47c628758cc7829432e590914faffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffba5c0b91f828bd18271ecd6c4dae93559e9116cf9453bfb8206f901c6743a9cab01bdd510ce4686cea15c3f76949dc144c8f536e699c49f2451df15a870b78ba972c14264ec6d656dd0713cc207f47f0e2b60a1603beb401d0415a3512fdf67fa08d29024c222184cbfb9fc309295d41252e71df924cfd4b9fe9b39eb22f41181ab69b3bfc67a2b0ad743abc470de8038dd4cffa9b86d840403dfb3e6648c0a179acb062d52d263d2938a23080f331b79b7876025046056dc587a22c510e2d0800000000000000000000000000000000000000000000000000000000000000004987b50f34c8c73a37611a384c940b3a992fd3bda13c7977cdea16dc908999c5ad194a9100e95b709f58c760940fd261f58c1801ded98189feb7da08b4e25ccf52b90c8f8e4677d6c7f36ed648f8c95f3247fc7e430a5a5a6da0f580faae6b322bf75bbd6fb247d37416816ff2b34cd40b41adb272237d45191ba43ecfccf66413662ed229705db4b58c9f1f0e7d2c93731755b2ec8225c11cdc26a2509fa8b369eb4bf0bceb70705498c3365658a01c491f03b4c4e96703d754886c48762cd38a9eec07f58066af8bd1958d1581996c3dca686cd7de13fc50562f63913be5680000000000000000000000000000000000000000000000000000000000000000599902bb31b9b47be94d47ea436572ad1d40cc78837396efff19b94d67743d19b36da655666e784462b1bac23bcf49c043cb8938813dd768fa10677620e66edcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb11474d8d7d45a2162c042c809a94637dfae668979492f2bc26f7df267ccadd5472bdc5055cebca364de35de1988fdcf5d99bd1e5f5650a306bcd3365aac47cb00000000000000000000000000000000000000000000000000000000000000006c75b7ec805e6b759379b193d8ddc7f05114cd92dcc9ca81e8d74d4fc647c79de0a4b67933c0571d3ca17ad20d3b84ae5e111c16c67dc40246b2162f4a5e875273648b120252a93c9a01dedfaff864a1c8c97cbfeaa8b7bd7269ebce3fa6c80779240a0ffb055322193a51582b49b6149a85e20d3cf0c5c8d8b23ea8621d9893f8f45270f1ed4c0c735210b7375bb798129e7fc52760d85eb6f9ff49956a1b632d065334eb4aa61a8f6fb07859ebd6156484933ae3ff6b47e2c00ee48a86a6d81db1dd4b77f271b2cb0663cbff1f3356a17005383ef098ac293f71fcb4cf6dfeaebe874adbf1f83e61cbe80d100dc3d727ce63fb671143124592f75daa70648e00000000000000000000000000000000000000000000000000000000000000008ebc3644557f9a14c4447e9063b696e1ef247c64b251adbd183e45282236b50309d3c1994d5fc4da7358467a2d99f469e77b3a0a4cfee42a190dd92e3101e8605ec6de73fa6cd87c792a85e8d1bce2b27f416f0863be8ee106b0cf300ebaa03b272be4c918bca9b79514fac857babe12ff83a7b9160dee3098b71acf612b6fcaeceea30c1150339fe31dd6da8f421e4e10d2cf47cd9edbd2fd74a87954883dd2cc2756e7455df3bb78fac74f3fe83014d0b3f8ca1c15678b712f6a2c4154bc91ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48216462d877d3d730dcd17ca53780ba486bd88f865ce5608ee144921a3fe0bed5468ed4cc5ac248aa4159cb1ae718483fc82bacdaca36bbf7d3244fda58e01363687c820deb74bbcd202fd2b32ef452f36d50891b57f1e318f2f36ef6e7acebb83f7cf6cb8f273468962b6feed445e6801ab97ca9f5756b00280f654c279c8100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011811a812dfdf49ff524d92f338dc7800912fbbef314a3bf56a6010d8b8c4e1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff557f48844356415d0ed40cb48bb3240d578a5b08167d1e1f30a44f4785332649ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff493c0cdbc18a65bf391d45918c887ba6fee56f41a91fe91082b446ba6486bb5bc2236ab0aecf6d68afb88b6a2409b52abe4c48c0974209d445c47da956c1f8720000000000000000000000000000000000000000000000000000000000000000"]}, "failure": {"scriptSig": "", "witness": ["1e1f83551bb2f331bca92b461cdf8a63776e92073723dfaa24cddfdf85444fe37e4a3dd0bda69af212cdf64c6b4a2dafb1ceca20b748ddd4ba07e87facba897201", "9cb52c193f69929371be021ea2914521eae608cf2f38adcb19961ef85b4407612c35bb494adac35255ab4f1921dfc623accce9e20b6e7cb5363eb73ff94410047a014d93c07f1a84ed737f6e98caf7c8cc2b9be4e3e99d0650a0dcb0121350b26c0e2733752f4ec3b56273b29a2190e0177cd0ea9cfc95070a7d18edafeb40d9851ef75a8c6cb488547bddfb1630acb2ba90d85656047ac2", "75003535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a2ac91693535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a26eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cafd838e61ab3aa45c319601b563b9c658905b907134deb4cc79f3bc13ff369b0000000000000000000000000000000000000000000000000000000000000000273ca7b5af5c33cd596a394254ccfccd1ad7f414cf24eaf5251ee142edfc6bba19e1974746bcd95f883b2c5f8b9cd70ecc189bb284120cbe237fccafca83785a0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2f292326c7bf2ced92e8e5f55f7d4c058bc53f0dc5d72e6f54d90a99bd448a0a7d3178fe8ff3d1648fd0414c507f32ef1a859472bba31e5fd87f9395eb28563d000000000000000000000000000000000000000000000000000000000000000053cb80cf27390b5f3a9b6e8f7b62b6973f471195333decc81153a008733c93f4fdb984c50376bf112fc5b1ba5121971048d8604acf0e95c0aba37777dccd84f7265ff857dd5353a6f266df0c827cc2177bd50674255e0d749a1de050f0543a3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa255cc08baca582f171c88e3afb5850782245b5ed7b91c999e195e37d9159bd5d8e80d80e4a0fe1afa47b4cdcdbc993cd0db79675bf4cd78cc37b4de49bc27cb8b09e1ee9dff2bd5c170a69d6407e15bee592ac7316759c0b21c1ce5c1e004f3bfa663a0599002637d08bc203534805f26d034051e6a67e85ccc9bd956c8d8706de45c3a48843ffe045e251fe069222fe8da2ee54f1847880aa81efdcaa9d8525d20e0edacf2383ded399026cf8bae72fa36b1caa97db067cb54ec3ec4bb5d4284e14408a569f47e5deb40589b32bf49aa1bc60a3632cd7e9e9585937c90d6b5f93801b1dd258f77e7dbd42a444590190088faf2dfd4654dc4249a5d6ad34325ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d5a204a83fe59bacd1cae520ac4d3bed216198175683bb791441d91e89feaf10000000000000000000000000000000000000000000000000000000000000000ad10f52d27e62a6a591b25683e510603924fa6b0f324a16e58aba1d57e478ab50000000000000000000000000000000000000000000000000000000000000000612e5dc139866e7b4626935f13e419d7c281bef6c5b9deccffb02e9f640fef85ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff737008e4121812f7dfc661b4b82fed08887fe73b0c9217265c2827b63ba2f13f59d5370a9318774a5bf4ce7ad10f052d6dd560323b574a7a7e042e3b227c162770be6fea8df19f1fd40bb23931116b7b3d192544775e300f6ade15d75b2779cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0e1f2198ddd478c68fe8bc5cae5fba8f760af3223933412457b382baf708df1000000000000000000000000000000000000000000000000000000000000000057f91a0ae05815cff02d68409806996d2bc455488ec896bddcee07d0c4d6c70e139403ed87e7aea928d90e04ec3797d79f44ff8b7c3d9e6ef9026af18da7ced2aef523a35a1d80f25f28c52fe09f4bc05ca9ca4c55aea7c169ac86caaa8897ad0252fa602c378c73546d62399d429bcd6a33226f823339715698ea6591be845059b987a2a1bc15e860ae688586a890bd57be17a71de63951967861e056cacefc3e95b857a1b91d9aafcf992cc9dc01a2a4e6f9dc4c8c5e5c4349f555667d7123d849ded7c59f5b86a0da4c79ba396037cfeacc2ac9a8670ad8578ef2a84e5b6bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ea8ac52b648c54e233c15f34def3254a14db47c628758cc7829432e590914faffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffba5c0b91f828bd18271ecd6c4dae93559e9116cf9453bfb8206f901c6743a9cab01bdd510ce4686cea15c3f76949dc144c8f536e699c49f2451df15a870b78ba972c14264ec6d656dd0713cc207f47f0e2b60a1603beb401d0415a3512fdf67fa08d29024c222184cbfb9fc309295d41252e71df924cfd4b9fe9b39eb22f41181ab69b3bfc67a2b0ad743abc470de8038dd4cffa9b86d840403dfb3e6648c0a179acb062d52d263d2938a23080f331b79b7876025046056dc587a22c510e2d0800000000000000000000000000000000000000000000000000000000000000004987b50f34c8c73a37611a384c940b3a992fd3bda13c7977cdea16dc908999c5ad194a9100e95b709f58c760940fd261f58c1801ded98189feb7da08b4e25ccf52b90c8f8e4677d6c7f36ed648f8c95f3247fc7e430a5a5a6da0f580faae6b322bf75bbd6fb247d37416816ff2b34cd40b41adb272237d45191ba43ecfccf66413662ed229705db4b58c9f1f0e7d2c93731755b2ec8225c11cdc26a2509fa8b369eb4bf0bceb70705498c3365658a01c491f03b4c4e96703d754886c48762cd38a9eec07f58066af8bd1958d1581996c3dca686cd7de13fc50562f63913be5680000000000000000000000000000000000000000000000000000000000000000599902bb31b9b47be94d47ea436572ad1d40cc78837396efff19b94d67743d19b36da655666e784462b1bac23bcf49c043cb8938813dd768fa10677620e66edcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb11474d8d7d45a2162c042c809a94637dfae668979492f2bc26f7df267ccadd5472bdc5055cebca364de35de1988fdcf5d99bd1e5f5650a306bcd3365aac47cb00000000000000000000000000000000000000000000000000000000000000006c75b7ec805e6b759379b193d8ddc7f05114cd92dcc9ca81e8d74d4fc647c79de0a4b67933c0571d3ca17ad20d3b84ae5e111c16c67dc40246b2162f4a5e875273648b120252a93c9a01dedfaff864a1c8c97cbfeaa8b7bd7269ebce3fa6c80779240a0ffb055322193a51582b49b6149a85e20d3cf0c5c8d8b23ea8621d9893f8f45270f1ed4c0c735210b7375bb798129e7fc52760d85eb6f9ff49956a1b632d065334eb4aa61a8f6fb07859ebd6156484933ae3ff6b47e2c00ee48a86a6d81db1dd4b77f271b2cb0663cbff1f3356a17005383ef098ac293f71fcb4cf6dfeaebe874adbf1f83e61cbe80d100dc3d727ce63fb671143124592f75daa70648e00000000000000000000000000000000000000000000000000000000000000008ebc3644557f9a14c4447e9063b696e1ef247c64b251adbd183e45282236b50309d3c1994d5fc4da7358467a2d99f469e77b3a0a4cfee42a190dd92e3101e8605ec6de73fa6cd87c792a85e8d1bce2b27f416f0863be8ee106b0cf300ebaa03b272be4c918bca9b79514fac857babe12ff83a7b9160dee3098b71acf612b6fcaeceea30c1150339fe31dd6da8f421e4e10d2cf47cd9edbd2fd74a87954883dd2cc2756e7455df3bb78fac74f3fe83014d0b3f8ca1c15678b712f6a2c4154bc91ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff48216462d877d3d730dcd17ca53780ba486bd88f865ce5608ee144921a3fe0bed5468ed4cc5ac248aa4159cb1ae718483fc82bacdaca36bbf7d3244fda58e01363687c820deb74bbcd202fd2b32ef452f36d50891b57f1e318f2f36ef6e7acebb83f7cf6cb8f273468962b6feed445e6801ab97ca9f5756b00280f654c279c8100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011811a812dfdf49ff524d92f338dc7800912fbbef314a3bf56a6010d8b8c4e1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff557f48844356415d0ed40cb48bb3240d578a5b08167d1e1f30a44f4785332649ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff493c0cdbc18a65bf391d45918c887ba6fee56f41a91fe91082b446ba6486bb5bc2236ab0aecf6d68afb88b6a2409b52abe4c48c0974209d445c47da956c1f8720000000000000000000000000000000000000000000000000000000000000000"]}}, diff --git a/txscript/data/taproot-ref/863c74afe345aa2460edf06abd9aa101ade521bf b/txscript/data/taproot-ref/863c74afe345aa2460edf06abd9aa101ade521bf new file mode 100644 index 0000000000..a43487cd26 --- /dev/null +++ b/txscript/data/taproot-ref/863c74afe345aa2460edf06abd9aa101ade521bf @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf91000000002b06489adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd001000000a1a8c5bd0374ded3000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487df000000", "prevouts": ["ca847d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "defa57000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0dbe0cdb6e99edcfec16766ec5847d1f54ccd051e23ee2b2272cffaae333295d1b30b2981ae69232c3f6c5ff759e9ad4102f31f3fc5e7a3a4ffd34dce2e2e06026"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51e707b6995f8993c03f45183b0bc1e0ebe72a0445f3f0cf57f2d95712f279e1c2be0cdb6e99edcfec16766ec5847d1f54ccd051e23ee2b2272cffaae333295d1b30b2981ae69232c3f6c5ff759e9ad4102f31f3fc5e7a3a4ffd34dce2e2e06026"]}}, diff --git a/txscript/data/taproot-ref/8641c37d6051843e6ca2af00b13ec220650722d5 b/txscript/data/taproot-ref/8641c37d6051843e6ca2af00b13ec220650722d5 new file mode 100644 index 0000000000..295aeb1d00 --- /dev/null +++ b/txscript/data/taproot-ref/8641c37d6051843e6ca2af00b13ec220650722d5 @@ -0,0 +1 @@ +{"tx": "e0ed141303dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b93000000001fcf05f6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7a0100000091bd69b9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc8000000009a4857d5047746c200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487bf000000", "prevouts": ["bec22800000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989", "73802000000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "8c967a00000000002251208560e60ff9f5f50e17abe0faa94b8704db3bcecc7cb6f74a11a752b4bbc814f5"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360c6fd00de61eb3e1d1c6b14a5c219f23903679f62342f964773f78df2cf30666"]}, "failure": {"scriptSig": "", "witness": ["6a03616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/86808a5b2f495881fed3418379a96faec86f72a3 b/txscript/data/taproot-ref/86808a5b2f495881fed3418379a96faec86f72a3 new file mode 100644 index 0000000000..6737dff06b --- /dev/null +++ b/txscript/data/taproot-ref/86808a5b2f495881fed3418379a96faec86f72a3 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3b00000000110e443e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d6000000007304bad901c0c94000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac97000000", "prevouts": ["32502700000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "2ad4360000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "c87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e868e9a99c27257089f8586472cc94222e874ab5c5b462fc98ac1b045b7a37dce65323990ac9ba96640afb66df99f25054f5788ad16157a03b33c6c26a70bd925e21136d3d9ecdf371b2101a7e86edb56e15b10ef185a8506988239bb2b5a4c43e"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a48ad409340116ac239d5c746dae159519851dfc1ab3c3ad2152d495f5f1663b52e804f6a261e09ec86c0fb6e6ff5b26564af7d86f56b1539029a07a3794a04021136d3d9ecdf371b2101a7e86edb56e15b10ef185a8506988239bb2b5a4c43e"]}}, diff --git a/txscript/data/taproot-ref/869a1712bd79edfc9d95461a25217f1b4b203e29 b/txscript/data/taproot-ref/869a1712bd79edfc9d95461a25217f1b4b203e29 new file mode 100644 index 0000000000..84c0798307 --- /dev/null +++ b/txscript/data/taproot-ref/869a1712bd79edfc9d95461a25217f1b4b203e29 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdd000000008a9c37cebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0f02000000eae7a34c03b3f48f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7c198d544", "prevouts": ["5d6e23000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "e07a6f000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["3044022066dcf42879c592d57b40b12b5b358b9c1c140fd25638889bc3d110d915ebab3802201230eb2902a683aefb94dff163f86dc2de66878c48a01d7a77e4c3cae813af3601", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["3045022100aeabcf3e19de6dd8ba23cbc9c1beda5d7bbf44e41927f43ee425f87da583df1402203bda596e67695b66dfe856c4e3aef1401a04e6dc9394540159257def137864ab01", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/869e9e9fd462fca683f8b432da94616198c8eb41 b/txscript/data/taproot-ref/869e9e9fd462fca683f8b432da94616198c8eb41 new file mode 100644 index 0000000000..db49b818b6 --- /dev/null +++ b/txscript/data/taproot-ref/869e9e9fd462fca683f8b432da94616198c8eb41 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43c0100000095415d86dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6b00000000d4fe448802e1715d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2708ec21", "prevouts": ["fc1c370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6fad28000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b3", "final": true, "success": {"scriptSig": "", "witness": ["90ac5345a1f7059a3860ee56ba9f595556776139c921143307722a9cdecd90d279a4010ab4a7071b951e2795f32f8f605e22e5084d1602f723054d7a3e97a0c983", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b3787d79274d50571af70bc04d570b112e0177223e453f31a810a5bf9a975e9432023d432f177f6bca6d4133f6961490919ff66a969071f5b24817325d5b8f28b3", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/86e9313b4a88cc4785b502796f36bd97f1174856 b/txscript/data/taproot-ref/86e9313b4a88cc4785b502796f36bd97f1174856 new file mode 100644 index 0000000000..5592f23f4d --- /dev/null +++ b/txscript/data/taproot-ref/86e9313b4a88cc4785b502796f36bd97f1174856 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4070200000035c405e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca301000000f48bf49ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b52000000003a56f2d902d8daa3000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac6c000000", "prevouts": ["5bc8310000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "a32d5400000000001652142540f27e90740933c99d4f17ab2dfc6c82951cfb", "05a12000000000002251202b18b828586b5828635076972ee0bba96c3f290312125c393cc54d832abc1349"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "d97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84852eda400aa94cfe5024bf6d05446bd810daab3c27f5a95b027bfb109f343b83d33b10ff9eee8ff434f7c79f826d5967b94922da2ad2ccade1cbab3a3658011"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a3526d2a5f8c4f602200f77573bcd308e02a3725247a50c328bd371ff84e2072d5942624d66fc39e30c2a996d85a0dad9a6418b79db996452744438b84f9614682a6e83df749f265180f93fd54e474915a8abfc6fef0a760c06d61a0bf42967"]}}, diff --git a/txscript/data/taproot-ref/871647145b6c79309648164fe2e9294d7ba23b0b b/txscript/data/taproot-ref/871647145b6c79309648164fe2e9294d7ba23b0b new file mode 100644 index 0000000000..734074abe9 --- /dev/null +++ b/txscript/data/taproot-ref/871647145b6c79309648164fe2e9294d7ba23b0b @@ -0,0 +1 @@ +{"tx": "859599e302bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0e00000000418ab0fedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3b01000000eea2fbf30421558e0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac52000000", "prevouts": ["715e6b0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "c673250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a7", "final": true, "success": {"scriptSig": "", "witness": ["23b0d43cfedbf7e5e2a7d12a7001c12944b081f478b73c12f151c9788336c1988f5aa0e593aaef7ecf3a0d8df16bb25ca3dcd345d8b3faeb716b23214e13241582", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["520405065323335d97d24f9b14120e88bd4cbe3b9b85e84e6f50477be8e673802921987159f4e1fcc4de81bfac1979894da0b368effefc1d88dfab65b68b2340a7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/871b6052e7f9a98779e47518bd5f8bf607a0e268 b/txscript/data/taproot-ref/871b6052e7f9a98779e47518bd5f8bf607a0e268 new file mode 100644 index 0000000000..f909413f9f --- /dev/null +++ b/txscript/data/taproot-ref/871b6052e7f9a98779e47518bd5f8bf607a0e268 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c13010000000be331e3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6a00000000b0cea3c303fd75cf00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb3030000", "prevouts": ["6a5f51000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "eae27f000000000017a91448964eab407ad5d6e123f59d9280ca7998f71bce87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2351212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["949576924f61566a81f8e2fc476db988f70735fe3efb5b0b8a3c7745c025d91dfa932233e661c3be0cad5b027933f921b7a5ee56a0d51065e09ac9f6f94f1e16"]}}, diff --git a/txscript/data/taproot-ref/87360adcbd85bcb0816fa5f993fc9a5e14182074 b/txscript/data/taproot-ref/87360adcbd85bcb0816fa5f993fc9a5e14182074 new file mode 100644 index 0000000000..d94b630906 --- /dev/null +++ b/txscript/data/taproot-ref/87360adcbd85bcb0816fa5f993fc9a5e14182074 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8801000000e3859977dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1f0200000017508a9f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708601000000d56fc4e201266d0000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7e89ca15d", "prevouts": ["0f5467000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "e47e5a00000000002251205857fc26f723a58058d8b22639f4b33f8ef23084aa37309f77fdf87ef7a99b1a", "92430f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "success": {"scriptSig": "", "witness": ["809ad1df077d70287fc6ca0fc5f8a1334cd61d3393cf6df7e2e7a1d05d9a944d601000ba5834308063fcafae4b7148cd701ea67464b78b3b8143543cff54547801", "50a6662878d52eebaa6f34ef95f87d4bf918bba5d86f3d58af5e7e288defcc6458195b238ae1d4a6427aaaaefa27dddac2f2179e9b8a9837493cf2455442f766305458394d3c339a8641cf4754553b7edf7041082b614ac31ae27981582800872d7b905db993679f9d4ad82e53560699768884e562204d24f16cbff9214fe5c7cef3d032dbadf0f28a05dc672c096a1e2f7e2e35bcc9412ae6132e1ca089f46532dd90f9cd4effb389c0c6cab868a6e09eb482a5e93a0efcfe82eb4bbf3fdc1d3f787ce792e83d3e319d3bec10cf7f5c"]}, "failure": {"scriptSig": "", "witness": ["07bb2fc8647a42ebb616f3f893dc8feef08096c966089256ae1dc44fede3193ed8e174212c9defb504cf827457177a59b5e93ff8cc2402eb70bd904eefce197c01", "50878585d9ddcf767e45d57c3006aca03e08"]}}, diff --git a/txscript/data/taproot-ref/874116a3fba0e5b88378c9825e5b2cd8fe9707c6 b/txscript/data/taproot-ref/874116a3fba0e5b88378c9825e5b2cd8fe9707c6 new file mode 100644 index 0000000000..bc745e1caa --- /dev/null +++ b/txscript/data/taproot-ref/874116a3fba0e5b88378c9825e5b2cd8fe9707c6 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6b000000005c19b047dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4300000000fa054f9360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127072010000002e2b715c0281e4d10000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6940e7f4d", "prevouts": ["ab4c790000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "48984900000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "4c73110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_69", "final": true, "success": {"scriptSig": "", "witness": ["da36f559a95c4fe3365718da6adff666b82414394edf582c70196463cb4c80a7c32c1905b7b21dd343dee9dad2c89feec310eee7cf9a46ed7cf026852dcc86ee82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f1a8f20db9520fa60eb4b8c12751eaed1f9f4527f28d83a8134e6465bb95d368da98c79e421580a8c9bea79f12e32d1c27565a0fedfbf2bf8750ee1a60c0f5c069", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/874498dbd2d21fb6b01edf60814088feb89dc02e b/txscript/data/taproot-ref/874498dbd2d21fb6b01edf60814088feb89dc02e new file mode 100644 index 0000000000..577a20d05e --- /dev/null +++ b/txscript/data/taproot-ref/874498dbd2d21fb6b01edf60814088feb89dc02e @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48f00000000d54e494e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127089010000004f3ee92e0308664200000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ace75cfe40", "prevouts": ["113b33000000000021591f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "14ad1100000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902330b623fd8e192f208076d7e17c6e6b31585828ed34de7687213ef68459ec73831edf7d688638ae4d5b635e71d71747759d283e0630ddcef2affb4ce19e1884779417f38b58fe0e8a96813fb53afd0943939047563e3abb8803cb931f5fc54791a76dd6e609611cd984bf604fc08aa38c2e2ace73287a0669644069ae1151f0cb90b2c761ea7ea4be3ebb657a6978dbc869ad3ca3744a225b680f286c9de0fc3dcd8eca16906f5d3a5f5bd1088703380b1f7fc542afc4057c4f18af28c9dfaf51e916f145d7a70ec4b9e900c72ae8357efb10ae217dc8ca99baf71161a2968e7789ecc085c49c4c3718cae4de5102eeae0b4dcfdb0442ab94d27f5f6df696a2b83bf767b2e5e2b63bb76b2c69cc2771ad0be749c9e41801f9b3b521e20159f271ae08bc8e3ffe28e7f91dbad8f1adf15aa3f7f731daf319ea6ee3c47084541494f127b35698e0394303012b006459fc393bb65bd97f447abe07e0658ea078923e484cfd6420b197d08c9a8d69435e95b29ace900580a1e29bc5399609717ab6f12a85705a2ce099a53e480892a6dcf47a9865a9ab04064d36c322e95c5c4a9cbcb4be5ec71313371f63fbad065b7cd43bec0b1f4815c1a0748f745c09d68777abac29c02e0bf35eacc50dbd5632502cc19a844d0611ae32d5ca2810fe4846d93295c67fa5d7afc8f8eecb2a9c904f7e229da2cc41f962815c4a45b5deb3697ffa1616ac594480532f5758a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e8007fec94eb3c5305297f43f34a17512a7dc89cab863bce10ae6260a115e064d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51cfab3477f7b3c3eab66b712f7a90f2a0c89c5ec16767e7d6e87c9be44117720e9b045cee6f1e54629d213b8dbfcd9de8aba2dd7f34fe21c75d81b8576e463c6b"]}, "failure": {"scriptSig": "", "witness": ["4d090206da9bdb9064f97b7ff3415bc6d7e7812e5900887a588912f41302be9d134f389ed1238f4d68f0f4aa13dd8c454172baa2a3fed6b54de097cbfdeba2588a007aa46e9e2df6445cd859c67f6d827397e7691f30b7ce749a12d698fd5403fa44b8e3b4d1301959c29a1770b3cc97ae2f21a6aa597b44e045d88c10d45661ed9a76106aea77199339b299db1342ba3b1bf8e817403f998417fa2858aff602636573a4418732fe703dde9098a8157d0bb57ed77f3dfc103987a87f9f7f852f89327cf51167031cf0eee20c69bb98e1e64746ddd8a57d7a0a0e13031cc467eb0150471252956093155cb56b2fcaebcbd970d55470fb5c0bdde60ccde978b6b4881d8f1c208a161e15b850a31fc46036a1316354cfb35c07ee3390474dccc04bd533a75713c10bcbe96c9c36a1f93b65979e8c6f8553af5ff4d86568c0f8cdb97f6d28da37fcb40f21cf4d33a08d5036e27ca62c073f722c0eaa48a572d895a01f1cf04e2f66cdada9d793e8f2eb09a59ca029282bb295f61735f7c4ad5d7405b4cd80d62534c14ffd374c84ad64ef4ef2b63d9582e930e25680feb044c225dded401f453306d74d830c65e56b52b5b1ea73d090d423f8a1604742c1c613ec3ce2e1ad14c383cfb976236457e0d6b291c3ad0447db4c25f351012977e4f507128214a2535f7b17a7d2af2b839bafe2adc7a94612302c459c704c5ab21c9d5590a92de0a178593ea88c8cf4417561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b80456191687daec4f7052b209d86d943f2ed0e607345185a76aba26d7ed1a66d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51cfab3477f7b3c3eab66b712f7a90f2a0c89c5ec16767e7d6e87c9be44117720e9b045cee6f1e54629d213b8dbfcd9de8aba2dd7f34fe21c75d81b8576e463c6b"]}}, diff --git a/txscript/data/taproot-ref/874b8f129a3df7a4c057a29c6d71bfa99137ed88 b/txscript/data/taproot-ref/874b8f129a3df7a4c057a29c6d71bfa99137ed88 new file mode 100644 index 0000000000..39864d0a60 --- /dev/null +++ b/txscript/data/taproot-ref/874b8f129a3df7a4c057a29c6d71bfa99137ed88 @@ -0,0 +1 @@ +{"tx": "b898faab02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd001000000322d1fc28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47201000000a12eaadc03c7936300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac82030000", "prevouts": ["ca39240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee564200000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "577d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630f38818e89feee14623c9b7a0eb4bdd9acabdc6da78fd3d02418e3152c5680b35bf8914ec6f25b4d9fa0eb4d13d0c5199bab9da1f0dbae1e1446f691f7eb6d53a8385792857b3824bc259fd95f469eb32c57805e5f383de6590f06749d208e6"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93628f51c82c3c6baa906179e2c4249a4fd3466ca100eba1cb5559cdc57701c951ff4a7dcfb64e618b34998ea64659fe772d1fd358b29e003b2257b85d2ca618476a66706abdbe591f97764059d8785051c12d40b9c9543fb83334d204ae23d8b59"]}}, diff --git a/txscript/data/taproot-ref/874c302461e364f71a8f6570728f98611a5c96ce b/txscript/data/taproot-ref/874c302461e364f71a8f6570728f98611a5c96ce new file mode 100644 index 0000000000..770bcad8b1 --- /dev/null +++ b/txscript/data/taproot-ref/874c302461e364f71a8f6570728f98611a5c96ce @@ -0,0 +1 @@ +{"tx": "8e961b1c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b601000000d2b48baabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4d010000004b4050d501d0c7520000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72bcffb39", "prevouts": ["4f560f00000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "bd2f6d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "fa7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e806f1c7e5fb59ec6be7dc8dd9b5e5a9bf4b5e4bf2d4887cde3c9822cca7ddc75b6ac496a48f5e08c9a0063585476106fe61a3ff4222f4c7aaafd1f65bf01170e2"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa89ffffd8cde8e3769edf5532f5f6b1952f639561cd4ccd6343a91fb81843409ef1076b289256cd19daa60d704e81db3a39e457bb71d9d0e29c4cb2075820e5e1"]}}, diff --git a/txscript/data/taproot-ref/8753f414b84b9ccd0c62553961f88f7c0264c379 b/txscript/data/taproot-ref/8753f414b84b9ccd0c62553961f88f7c0264c379 new file mode 100644 index 0000000000..1335a04e10 --- /dev/null +++ b/txscript/data/taproot-ref/8753f414b84b9ccd0c62553961f88f7c0264c379 @@ -0,0 +1 @@ +{"tx": "a5ed58ed0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d00000000034e4feb1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0200000000551f05a603895f38000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac388b6049", "prevouts": ["0a9b11000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "7181280000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936af7aa65714282a5b35066fa70de922413df84699e1278cb2a83e1b8810c1ca1420e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1c56c8a32008d6f6a63b4b8ddfaeeeddf640e9afea8e86008d2331d68e9435ec7ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364230902f346ba40e65ddf0aa0663e4719e9615d7abd3dcc6db3c9c5544398849c56c8a32008d6f6a63b4b8ddfaeeeddf640e9afea8e86008d2331d68e9435ec7ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}}, diff --git a/txscript/data/taproot-ref/8768655b2d8b6e0cca092c104735354aee0c9b0a b/txscript/data/taproot-ref/8768655b2d8b6e0cca092c104735354aee0c9b0a new file mode 100644 index 0000000000..e0c8119341 --- /dev/null +++ b/txscript/data/taproot-ref/8768655b2d8b6e0cca092c104735354aee0c9b0a @@ -0,0 +1 @@ +{"tx": "5f8a773c01bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7e000000002bdb96d603a0746a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acbb000000", "prevouts": ["f7196d000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_82", "final": true, "success": {"scriptSig": "", "witness": ["121729a4e5066a4248b812517e0edf3437d4c4b2f3ba9a2e78c1807293563fee00376f779a717136521a6b2fcb1e81a50797141f82f607249310e6061e267f6082"]}, "failure": {"scriptSig": "", "witness": ["51b52ebc32f95d77310b05d7ce627d95505bd3759a65ab95e85815b9805cf114474082a4c88b3240926afea3b994de5e303a6117645ccfb52feb49719de6525682"]}}, diff --git a/txscript/data/taproot-ref/87d794de1dead52b89760fa5e136596c5b59bc40 b/txscript/data/taproot-ref/87d794de1dead52b89760fa5e136596c5b59bc40 new file mode 100644 index 0000000000..891a2f9619 --- /dev/null +++ b/txscript/data/taproot-ref/87d794de1dead52b89760fa5e136596c5b59bc40 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708501000000de5aa6eb04b7f80c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8713e73120", "prevouts": ["746b0f0000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "9d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a832c2593bdac0cb0b42624935007d1442180dae3fe4e49dcedfd3101f5729d872756956c694637235f847009e8e23b8c05283b4a047903b3fbdb647ae4209c1"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364d9cfd389e774c529beca95e1955030c310e90019de0d0c1b56b68b6d8ca0660e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a832c2593bdac0cb0b42624935007d1442180dae3fe4e49dcedfd3101f5729d872756956c694637235f847009e8e23b8c05283b4a047903b3fbdb647ae4209c1"]}}, diff --git a/txscript/data/taproot-ref/87dcc971a3beea2e91a4d7e9643a5539ff94d52f b/txscript/data/taproot-ref/87dcc971a3beea2e91a4d7e9643a5539ff94d52f new file mode 100644 index 0000000000..c4b41b318f --- /dev/null +++ b/txscript/data/taproot-ref/87dcc971a3beea2e91a4d7e9643a5539ff94d52f @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4201000000b563db75dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc301000000f098e3a68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c467010000003d1d4d040391f7a8000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72db95c2a", "prevouts": ["4e8e4900000000001657142540f27e90740933c99d4f17ab2dfc6c82951cfb", "f6a2260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1053b0000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["10e15c282e576b17bfa2876e6f1bacbf88ffd1379b4e62c959e7a0cb2c38cd7dbed5366df6618f3d43dd972519a4352c852d79b6918df80a8e243facb2b23c73", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/87e1e382d129600c7e7f842f983fa6e87de06c9c b/txscript/data/taproot-ref/87e1e382d129600c7e7f842f983fa6e87de06c9c new file mode 100644 index 0000000000..c4db2b5a92 --- /dev/null +++ b/txscript/data/taproot-ref/87e1e382d129600c7e7f842f983fa6e87de06c9c @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be0000000005fe3e49860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702500000000186ba9b004a336300000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7962a2a795b", "prevouts": ["614222000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87", "3766100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3044022031d0a6c9b5e92fcdb84d6557f499872d27859093e7316b0e154f8d8662ee3d720220269ed46ba2a8fe869fb9360cbbe9d3ee953e3678b0d9ecb293e1c11dfb6e927381", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3045022100bf6d27232fb258e64481499016409a1b4498a7c2c1ce9f20b08b1f6921865f1c02201543c89deba4677abe4b0bbd51c1a25778f55a15f59cf288f26d393b9fd725b581", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/87f0c2e540270b3692ef13bc2b91234c893bea37 b/txscript/data/taproot-ref/87f0c2e540270b3692ef13bc2b91234c893bea37 new file mode 100644 index 0000000000..d0c8913a9c --- /dev/null +++ b/txscript/data/taproot-ref/87f0c2e540270b3692ef13bc2b91234c893bea37 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe601000000c65799e260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ba00000000d4786d82dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8f00000000fcfa74ef02a77fbf00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d5000000", "prevouts": ["6bf861000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407", "d5740e0000000000225120f53d4d34de47a5fffffaf2fc2c78ea776a7cd8d2ae45e19539d143c70b3fc5d0", "5eaf510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e02982c20c8bd2555b9dc2466c73f0b476ea38d756de2725bec69a609b7769b1ef31942b1858214ae33105eca3f0b2cf78e8df05a3972acf71e40f309e975162b655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4b205b49dca00d66246302f0b0e6aac7e300ad432a7c010b19b7b2f949f7f012a70b4d2addc31b8421907b0cff80194a5513593e3802bd921239c9c6063ea806bb655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}}, diff --git a/txscript/data/taproot-ref/87f8602bd7dcfb5af1052f424e7403550ff631de b/txscript/data/taproot-ref/87f8602bd7dcfb5af1052f424e7403550ff631de new file mode 100644 index 0000000000..61255e1ac7 --- /dev/null +++ b/txscript/data/taproot-ref/87f8602bd7dcfb5af1052f424e7403550ff631de @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a900000000bab6199360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702000000000ac5597b703f23b1c000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48752d1432e", "prevouts": ["fa6510000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "febe0e0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_cs", "final": true, "success": {"scriptSig": "", "witness": ["1fccd586c3c0004345a49e4332aebc93c1c521d426b22d91ad94cd11d6a86f00bd4fd16d0dff163ef724c99cfdaf74446a2fe735de4f33acafb79a8ac99b3c4c", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}, "failure": {"scriptSig": "", "witness": ["1fccd586c3c0004345a49e4332aebc93c1c521d426b22d91ad94cd11d6a86f00bd4fd16d0dff163ef724c99cfdaf74446a2fe735de4f33acafb79a8ac99b3c4c00", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}}, diff --git a/txscript/data/taproot-ref/87ffa0846cd9a6bebb41a9d3d719ba376c69285f b/txscript/data/taproot-ref/87ffa0846cd9a6bebb41a9d3d719ba376c69285f new file mode 100644 index 0000000000..614bd158bd --- /dev/null +++ b/txscript/data/taproot-ref/87ffa0846cd9a6bebb41a9d3d719ba376c69285f @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42a000000003ca5b8c5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bda000000002a7cdb2b04cf6957000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487c7000000", "prevouts": ["013e340000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "9b13250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090250ce2cda282f55a10517ec40d7b0a4d4723d97464a39e402aa3cc6bbbf8a97e997e1ba87a132b43999ae3c534ce6b0df46b1699b33e54048db660459703a7bb99adcdad885c8b59a1306830fb48c02fbf2893a61db78b5f23278552a67fbdcdf8821ea664a2762c9e189df8e74a493988683a5e50a63cadd5b7b75c1fc41a25c478d6fc1c34c161d1e46d1cd1ec2c1e09264759568016693edcd1e1cf828a73e46a89f0b97c422661fdff143b758e0409ff82b4e568e40849853dcf05ddd1879ac5ec5044d58041465d5e14e7912c3bfbeb12c1e07e9a4adf54f3df393489e5a0acabca79fb7cdde4e362be43d793fe33a1d8a5119d5dbfd9a5e94f20db9a3bc171bc4c2381064d96f80f5730a8686dfeeb925b6caeafd76a421023477beeafceb7dd36613ebf82b32539bde45b5d0195454f7bf5464dcbfefce8e6ebd9480ea29c5240707cc2f69394cd984814a36bef812b25114be38776b769833e659369a4532b4f62eb5df88d68ddcccfe1774f8d3c6bfa36940cd57fbff4cce90ae47b8dea5276a9473d18d5298f4e7fcb62080b8626f88b3bcbcf37205ec8bbd3fd78af577cc0bb5ef389e788a325de6410981ddd6d5d24c5f3d0b8cf1d856891400577e0d1f928153034907421efc0c9215636539d3e9b9d88ff8694f004f178565307f3950d55b827218340ed7027b8914002e233f10c6c0d7a3e84e765f08fcf3e8a1cf7ddbeafbdcee6075", "1d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a72a63dad112e73676294041a75425f56752d13d00a049b2fb88a4045546b166879334807fc224780ba3e72651a115d27f4d0acc1c4b651ff2820865c4364ddea37f54c31b0dcd6e392a972a33f542af4c40de53091de86bbd5587895c52a53"]}, "failure": {"scriptSig": "", "witness": ["4d090253da6a2214a870ef763c7e5a533d492d5c841a1b9839601fddc34f4abe707a02bde2776320d884a2c69174ff797485cf14a383dccdcf34e631e1c4ebd4d5a8ec99d7ab6c3107c82a5679084adaa2a77a51384f11380d19e40b95b8faf8e79412b96cc83b2015a382382057d320d9e37daf6c74becdd3f80992d98ade6dcf77cdf6a2c88dc7a6d7546d79caef81fa8ae5d6a3c9c466ed4db9da9e3e60a24f55127936e1eb126239c57ac6db39ac35b907db081fe372d13e52b55e0a5da3b5e8a21ba37991247bdcf6ad8edc57d3ad1ac4d29ffdb5fa63c21b04ab385ca53eeec5f08d43d5d5188c75e020baae2614c4f7875bd30853bd7e765275bf1f7ce698e2ebb4c420a237d5e6ffb134204c0368d1d802c7774569bf673db172b87e2b1d34a577145d561001b4c9188a1a05c52d44688842190bedafdb3f2a6fe8302a1eaec08fdb3934c86067f984cee9af06e2c7884b6d9638986cc450e913769e96ba58b38b8b73a8f6a0628014e37be090eaf8dce3dbe260ef53397aea7a426af450efb9c8fb7504eb5f2831536f4c1ea3f2a0b5f598c726c11707b3b12f70e90767db8354aa4b5b7f000f01877ecf0ea4d9d4dc892c0e2c644910bb8bad22647ccce6606a597cce1adb0e994c806d3a39b4b8ed81b715957580b5ddf488a187411c688e7f8334a097bb94b9c882d1c19bdbdf10405880fb9a6c83972111eb38cee1329f15287ddcfe74a6d375", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa422ef55f7568e8dc283b8fa041d75ce76b297151a0e1c7ebf12f48a20b112ecb6879334807fc224780ba3e72651a115d27f4d0acc1c4b651ff2820865c4364ddea37f54c31b0dcd6e392a972a33f542af4c40de53091de86bbd5587895c52a53"]}}, diff --git a/txscript/data/taproot-ref/880f03671efb6dcc3f3fdaae9491625f46f6e4ac b/txscript/data/taproot-ref/880f03671efb6dcc3f3fdaae9491625f46f6e4ac new file mode 100644 index 0000000000..34d6e4a624 --- /dev/null +++ b/txscript/data/taproot-ref/880f03671efb6dcc3f3fdaae9491625f46f6e4ac @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c43010000003f472588bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4501000000d3e842e9032ea2ca000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac62000000", "prevouts": ["20175100000000001659142540f27e90740933c99d4f17ab2dfc6c82951cfb", "d2437c000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936908709641cf32dc4788f906f7e3621a0528df09509ddf1e9982e4479aa4b5d9aa78a04935edfb84e1b4b71380d58e01ed379cbb21cec8f8440ec0fbfce597ab8cd941a6bc152cbea0496b075d4b2611b435301778200e60e8b4147cd93749673"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620b045a5921ba670650c9c8b3cfa2abb5a81e5b0d26916ef9b1c65eea7b40a6ba250e002f75c6b1c142228c210e3ff9b9da21a81c3d6d31af30c750433b28b6418ea1dd842879684de6ce36adf7429742f60d84d7359dfb2eae76d7b546c72259feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}}, diff --git a/txscript/data/taproot-ref/8829fdc647553393e0d223a098067bdf44dd2c3e b/txscript/data/taproot-ref/8829fdc647553393e0d223a098067bdf44dd2c3e new file mode 100644 index 0000000000..29440d4054 --- /dev/null +++ b/txscript/data/taproot-ref/8829fdc647553393e0d223a098067bdf44dd2c3e @@ -0,0 +1 @@ +{"tx": "e4c3fc72038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ad00000000ef3908da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270740000000074614a9ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1001000000e3195ced032611a5000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487bd79c71f", "prevouts": ["c47c41000000000017a9148bc1125bf4e3450c593a5be1ae9a05461832d39a87", "ad5b0f0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "b47b560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902ea5423d4612223c88e79cfd8f9c85f9e8dd0a6b0fd4128e85a165643e2750703125a2f5df03a21df586c245c4f945b8d6d8e026475887da84faec7a502c9fe60c30d7cddc0b2b9f2b727ba5f730bcda8e3cbd0063aa204197d71f66caf9468a34e253abb4bf344256cb04c799d51217d8736aa9b25a61ed1887f949565449c78a7fa7f59eb23d4bbe4ecac95cd08dc9f495ffe7c4c9f467123fdaf119a61e78a1850132ddca18eac1fdacea443a6eff548dd0eb4b02a5276ba646cede0f5adc591d4077f9f21d4a1db3a17f9db0c644182d1e333c0d8d9a05fe477120d2825ea4cf5e62978c7bfc46ecd74b95c054b70675233c1bf173b2886044b4b3a124df01ae7b7a944a2a68b4512695dbfa2be4999fe2a74ed4596177107a3c052ff66c4e66c762f8d4ce61d65ccc5575d52a7c95b699540625d0d826f0a33b045b68758a527e3f7af95474e73e1fd01dda3e9d3df38442c6274f6719b476c63e02269794b2738655cbd769164339eec5646979d3a7a2a29b40574907277745a7b622185f634623072a81c8f5f78eb60131ac8c378297bbd03d4359f0caa1f4610da0ef67f51296995d3b7dedb2a9ecb1b6c2eb126c3697586e32f438714f31eb28ffedc4cde72f67f746a15fd3dc917a0bb7e4ac2dd44ff5611677740f7b02e8eed47d194ff6952431c162901acceb73e96f1dd276eb4c9cf5fa64475bddbec32c54a69e74bff34cd356fce2a75fb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a8e05ad6a2ccae9f66c9a515de938f93f122fdde3ef761cb4746351f00ac75fd78b7d2e6e031ffcaa796ad02cee9894dc771f62b9a69e495a6b0c07c9d130bc643d925f8e6664e67417d113cf51c5b4c3126025efa5f83bf5b16dba6746279b738273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}, "failure": {"scriptSig": "", "witness": ["4d0902972aeb42bd1e1ff14cd3b1739f4b358751f99707b5f8b9ecce5a822d0b4e535abd7333ca35ef4ddb9989551f0d04e80e9b695e4422fa929f8881ef8f580ff62e8fef05333864d96d7255347402b2fabc9920212ac9f462c3b540ec4a5a9d9729764b7f469548af62d278c189ce5507559fe56ae0e1cd63a6c4ba7dcfd7cc71ec389435b55c1675423d81dd0c0f71df28972136e137b59554c0151f4d7e42ad25097555bee399b1e0e045968a7b080a2afd8f21eec0692e670f047ca10422890664f56fc0239e8fa0973fb2ae370ab6e56fac17761cb77c46f5051df32b560a7d6f54f71e3aeeeb17101c12e0f24ca18f954e2f2d034b20287c9c92f7aa0c2616764d234d87ea314b2f050bdae434a491dc54919922beccee8516400319927a3e1824007bdebb83a94cd9629c391ee57a62644f035532b6b7553d65fdee680579045c23d317921577fb3bad4adff9e57809144a4e4b8277eae2f071c911fded8960c036dc981e50f3cab1a4b80ae3263da638e4d6f02787f53e6f56a2fc9bafb8cfad3f0f5355d3a36aa3ecff88dc864b05dd192533bf8f2287246e94453f93d5065dcac3dd9c8549032b69cbc842571a7223f4fdf51dda181b34d50789751df8226f898b40ad7488a48805318c348c65d3826027324ba0efeb1d6e4201674bc52449525ca22c328e04b680b457e98b2c2026c29acad95f1253d8db23dfac1be40de63cb7c47e0a1c6c7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93600b2d24cdc995533ca5136ddf99c649a7656cea6d4e88007bb6550a8679541173f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082eee8539df42e1fa2e5e9e7b75fbe1b52db879ec8a622b496736c99966ce19d0038273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}}, diff --git a/txscript/data/taproot-ref/882c32949367f4f504b543399fa13b4f4118344d b/txscript/data/taproot-ref/882c32949367f4f504b543399fa13b4f4118344d new file mode 100644 index 0000000000..95bf807f1f --- /dev/null +++ b/txscript/data/taproot-ref/882c32949367f4f504b543399fa13b4f4118344d @@ -0,0 +1 @@ +{"tx": "ea9513f50360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e500000000325a22e960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127099010000008f727e8160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b0010000007ad921c20200f131000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e789000000", "prevouts": ["e680120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "519e10000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "67ba1000000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["304402200dc7891706cdad6e3d6cfc5e81a64aaf77a5b6bc8810c248b5e493a1f14a3ca3022049cfd2a3de2444b9e757ff797b2d867c33a291d515584664755c91abe827f29582", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["304402200d21c2978039d65afe25838f8bb132eff50c41a2a84fbd1909d70eaaea18c8a702207d32e19eb305341fcee33ea31ec200feaadb0fd9c7a9ccb3489e83d53a350f8282", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/884b9c73958e305260b7aa5b9969660166f550c3 b/txscript/data/taproot-ref/884b9c73958e305260b7aa5b9969660166f550c3 new file mode 100644 index 0000000000..1066c1a040 --- /dev/null +++ b/txscript/data/taproot-ref/884b9c73958e305260b7aa5b9969660166f550c3 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbf00000000a56b6a2060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f400000000b6cc542e020ae337000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acd5656735", "prevouts": ["148b28000000000021561f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "a4aa11000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "937d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936063b325ba14742a409980c1f892f30b155825542c53b8d83ef812e2e7f36a27808ba990ecca3673e7fa8965b90b12b1af4599069410dd603db7b6040d82b00ca2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd6f60e166ab3c31d6fe53c0e4c47c333102fdf48f7428a1dab907384d3ec09a32"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828b73eb14a8afa044a1a6f0495df635bb2745ae30a5fce84d6222f661b17136fd6f60e166ab3c31d6fe53c0e4c47c333102fdf48f7428a1dab907384d3ec09a32"]}}, diff --git a/txscript/data/taproot-ref/885db56c9eb82324c5a0f7e7aebd3d215505a5d3 b/txscript/data/taproot-ref/885db56c9eb82324c5a0f7e7aebd3d215505a5d3 new file mode 100644 index 0000000000..83b2c2b591 --- /dev/null +++ b/txscript/data/taproot-ref/885db56c9eb82324c5a0f7e7aebd3d215505a5d3 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c429000000006320e29abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5800000000394a92ad03058d9d000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fceb010000", "prevouts": ["57323200000000002257202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "ab5b6d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_13", "final": true, "success": {"scriptSig": "", "witness": ["32f22dbdfa1b26314684b5f5c57a4ff80e039089a64fead7df159c976b0c79be8372a0a62c5b04962820e40f3df9fb32324fd5060b2e31187452da2b20ec16ed03"]}, "failure": {"scriptSig": "", "witness": ["3b6054816d24a81873e62305a458b19bfb0a5ee92dc0a4bc4c1cad39c309b96811d3e187bcbb56b1bc02a385a1bf719315e3fc5b6e71365ae7800521c8d1c7ff13"]}}, diff --git a/txscript/data/taproot-ref/88684adb319365b522f644e785033cac77380e06 b/txscript/data/taproot-ref/88684adb319365b522f644e785033cac77380e06 new file mode 100644 index 0000000000..1110bc1e50 --- /dev/null +++ b/txscript/data/taproot-ref/88684adb319365b522f644e785033cac77380e06 @@ -0,0 +1 @@ +{"tx": "9a528aa802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf76010000007a3820ef8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a80000000038f526ba02ce2c980000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acd87ed42c", "prevouts": ["60e1680000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "5ef9310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "483045022100a5137299b03f814aec9199e85b3ee34923c4dc21a6cadfb3d79e2f5ddddf585002202612fd44339d2787fe9740dcfa86645776aa9eecef389fb6e08586c0ca2721a634", "witness": []}, "failure": {"scriptSig": "473044022029843b5432f0a4eb7a17ac0e430819dd664c8297167f9fa3965081d0c4427a0702206d00b729d0b6c97db926b64d207ea48e58bfce6c109e5326d46d9d1efe50449c34", "witness": []}}, diff --git a/txscript/data/taproot-ref/88797c1357072ec5f6d7a77f8f554fdf14935742 b/txscript/data/taproot-ref/88797c1357072ec5f6d7a77f8f554fdf14935742 new file mode 100644 index 0000000000..d1435ddf1f --- /dev/null +++ b/txscript/data/taproot-ref/88797c1357072ec5f6d7a77f8f554fdf14935742 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c700000000f132150a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270af000000009c88c48704e0582000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374876daaae5e", "prevouts": ["e225100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "19be1100000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_5", "final": true, "success": {"scriptSig": "", "witness": ["6af86ace4b5b0adc0f633234efe0c6fe5535821d6373137115c18acb360febeb08ac53193f96df42dba610abae501128f53d0ef7692c61c7b6e476b4fc323bb5"]}, "failure": {"scriptSig": "", "witness": ["1519e557356698397c225eb0f398cb6d4887c32e6cd21c869e74f5d17b966ea7c52fb3e6c5bb75c3cc07425e17b7ed7720dcf76cef4ab97238e93535f836078705"]}}, diff --git a/txscript/data/taproot-ref/88d3c033edc04d341651610ce654caab89f0c589 b/txscript/data/taproot-ref/88d3c033edc04d341651610ce654caab89f0c589 new file mode 100644 index 0000000000..46b5afdea5 --- /dev/null +++ b/txscript/data/taproot-ref/88d3c033edc04d341651610ce654caab89f0c589 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6d01000000b06dc58edceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4c010000002a7e2e9adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc90100000011c898bc0363a0a1000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a663000000", "prevouts": ["3c7c220000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "23ef240000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "d7255d000000000017a91498e55eac47e04767f832d50008ff18559102c9e787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "cb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652247e5dd926380ab694d48c4d41b564ea6c104d6001198f68608a68dc76789170b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720d6d723e038e6335a667e0268d00f4826306437ee84552cc7f8172181160444ef73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4f551d5f9df51039c21b920ecc011c032a9913b031d76462e802a27cbd0d0ed8dd6d723e038e6335a667e0268d00f4826306437ee84552cc7f8172181160444ef73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}}, diff --git a/txscript/data/taproot-ref/88e2041ce84c5a5fd2b056669856844691b520a5 b/txscript/data/taproot-ref/88e2041ce84c5a5fd2b056669856844691b520a5 new file mode 100644 index 0000000000..8a004d02a6 --- /dev/null +++ b/txscript/data/taproot-ref/88e2041ce84c5a5fd2b056669856844691b520a5 @@ -0,0 +1 @@ +{"tx": "8a55f3a20260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127021000000004a3d07fb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40e01000000ff9e6bf701948e070000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7fb010000", "prevouts": ["7a301000000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "1e2442000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_0", "success": {"scriptSig": "", "witness": ["5411ab388a5e613c9f5563c8b99b26cd7efa5ace3b7518b8bed09cf3cf08999db537d3a1ef3cc511f889c92b1c3f6f6cc31c665512cef9f588c9e6259cd6e1cb", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "502ed118eab16e576a66fc0f0979ed6e0b1f1c027f87c826"]}, "failure": {"scriptSig": "", "witness": ["9395491a345d7fdcffa83c296f121e38f8b550b1a5592513a788f8b85fa5122ffb49d8fbfcabdac37cacbc272bd83e871590206290bc35d9fd1d2e2037618411", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50d3147e86a8d316b180e0220e7493dd9f1ae2275b3d1d372f71e943394ef5af16779683c76935ca1f1f134899c77cf497cfe4474e83da69006b7b4b9f502d2a77281656c5c6d484ad50c7c5d04a5e762e865695dc89cf888137ecfb5b55ab8d66"]}}, diff --git a/txscript/data/taproot-ref/88e2266275388545e1f8f54b8fdbe89bbac43274 b/txscript/data/taproot-ref/88e2266275388545e1f8f54b8fdbe89bbac43274 new file mode 100644 index 0000000000..ace6057c5c --- /dev/null +++ b/txscript/data/taproot-ref/88e2266275388545e1f8f54b8fdbe89bbac43274 @@ -0,0 +1 @@ +{"tx": "3ba8d6ed03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1d01000000e3bae3a4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8c0000000072f053efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e01000000551026e5037abdec0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963948d921", "prevouts": ["75f85e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74c36b0000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "26ba240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d568", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936feca977ec5b5f207aa2c7cd2bb0ad4303854687107e6989c92d62d0c0a78ef8fb5f329bd8499c4f72b132f747438a5079d3448c35be74257418716cc5d770d7ef69ea04c091b2bc3b7c7ae53ee1804d998a6447fcbbef49abb62b7a394c4c123854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bff0445c3472362aaf493b483fc3cd3d99d32d9ae5b8ca00af6d946998df7578135ed0e678ad02d8eb601751aa1b9acf14c9c27e67d62b009394546cc2bb02284b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}}, diff --git a/txscript/data/taproot-ref/88ec99f421c2381e497fe2fc13b4f6dd8e8786d1 b/txscript/data/taproot-ref/88ec99f421c2381e497fe2fc13b4f6dd8e8786d1 new file mode 100644 index 0000000000..ef1391e78e --- /dev/null +++ b/txscript/data/taproot-ref/88ec99f421c2381e497fe2fc13b4f6dd8e8786d1 @@ -0,0 +1 @@ +{"tx": "4e0dd6e902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8c01000000124e14ea60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709701000000743f899101ad8b36000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4871e000000", "prevouts": ["60bf260000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "a3c812000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09027cd42eea675503086394052e96de2c7c00a2603057cbfc04739ef98af2b9fa9fe84682cd9a5e0b675c5201f22b16a5ba3b6ded254e8ec6111a1f6c09c9f49c01eaf7613f5f07fb856f1ae69d911c594f7c8373283c4ef95c08de3209da2c6803315f3bfe751a8cdd3e0d79022625e15b6c2daa3069f5a5d7e0448b403764d61847995ffc70693d96b5484f7ae2759b248c64985e8bfda3450e4278eae2551a77134fdbbba7f307606940661eacbac1a5196e45648423e83a53224b13015eb826fd699b43f0d116e5a66d0f2911de33b0c8d5d312ad7fe1ab97b62d0f5c81daeb0b4ee6efd64e3f74f56c7ad53eb40a61a75c72c304ca31d81a02905f3ae33b4db39d1388c3cab6d8e13f0907bdad8cf56d343e07b6fd780e4de27fae4957bf70c37e547940709ed8620b24a10ec565ffb0052eb39b4ab2f51c15082da35ddc69a81abc28b74f2a14f9abdd0aec758caa567e01dc64e49236f108e5fc5996fc5a547d1c1dacfcbe1e74ae122605a161274ceaa110bc9284f82355346ab02ecd3a25713ee3942defe4cfae8e728dc01aa52e2769ca39fa48b9580bbda2a45e1f6842771e608f219b600b3f7e2592082b02ac473973d4c8e1f140e2f812243425abc106a3aee3d00c1b0f49601664f47f8c2a06199835e58bec4b024a8bfe918f0affe49afac71be96026e2be9beb5f60c63cca6c532095c3e7f747e885d8129af3d52e87a2b30f46b47c75", "897d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e9facf4edbbf526ff5eeb12780b24daca1831089abc7bf461f974d05d276c4783ac632f1e88e109b3d5485dae08acb0148fc939094c3a94300b3efbd66c89bc20"]}, "failure": {"scriptSig": "", "witness": ["4d0902005fcda15b5547a050a302ff9b4c53ad25d35dad2db6d8df3c20f8d06f2817828306b864a43e12ed07c87d1d72a5ecb874ff8e60f3644422d9c5f0c4e6e7290587eaf407954dbce6ad0267ea92dfe86f9a2cf8e0009bb462fd14e10d406c7693961eaa8b13470e8eda3dae670a7da99c340f2bf013735f7aae9876c215224e3c3470f4e828c57fc99a7919ea4694ea64c906e75a3a70546b22348f6437665e503c89fcd86d553eed601edff18d482701827d89551dfe10f897c83f052b0691b0c9ec1b17489c3f09d7cb547627f526c25592ee507d6f2db55039e751687f6aae77982954d5389d86e92f9bf23100973997f3bb5ae8ccb4c78a9b824446fa617bccac36232a924bbb87004ae32843c8f1e95419ff2deff79cd4f05903caf27e62c98436014f1beaf72278ec1adf1f815ec9f45a9cc21e01170b784000d765915035d8ce83de39da7090b67b547d74a2ff1ca7f0dba97d6f1397df5db1f33febeeb399a04cdd269ba9e88d6fd942ebe7aff993758d73bb7d70b90ad55a926469a63c4e87abee1ef7cb5566f67c64a433cf6a384881a14256467f4ec8c73edcf14ea62b1adbf3b0bbb28236b4696b72d0ee600c7ac8c81de05302a90ca105d9d86a87ac18a1bbfc92f034233704c165b46a89c8d8d458cdc9cc9afffdd525e7d67ca0fd36d6ea4e3a6e9ad1f18222fee2be2b77a5d6e8ad0c17cd947f1fab6714c70e3bba959f57a3d29775", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d5a3aa5a515fb236d07a83ce20afcf6942ac7037fee8ee73df010e8d2641866618ef0696df011c2e84d95b8f4877f40057090cebf81e873c0600d23ea60362df6c56da6b4a79dd49e001229b88fb5122d120ac43d63d1be0cdb38b208b21132e"]}}, diff --git a/txscript/data/taproot-ref/88f24d3d0ee361f07b6a968b39726f1326ec9166 b/txscript/data/taproot-ref/88f24d3d0ee361f07b6a968b39726f1326ec9166 new file mode 100644 index 0000000000..5f63a5e21d --- /dev/null +++ b/txscript/data/taproot-ref/88f24d3d0ee361f07b6a968b39726f1326ec9166 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9d000000009313006660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701800000000454fe720038533720000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4cdccd43", "prevouts": ["d1d765000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987", "7bc40e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100944997cb5650b2465d9129612102ac1f86dc6492d6735de55b23b03d212fbd760220336c6d8eefcb240b835fe92eb55b684c6a2675e08698e582feb664efb446ccbe034104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "483045022100a75fd2fb2e26a1d3bc517dbdc5d419a7445025f2d7d20e7c0a7a6821607008cc0220522d346f973006b7a1f91a042f4f1e16954a0f74a55a0758dc36b8a407d5b12c034104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/89063488083093835287b1f9c18b2a7944664176 b/txscript/data/taproot-ref/89063488083093835287b1f9c18b2a7944664176 new file mode 100644 index 0000000000..6bc9869591 --- /dev/null +++ b/txscript/data/taproot-ref/89063488083093835287b1f9c18b2a7944664176 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702f0100000063a3e9c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700502000000f4bedc840447552100000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acae030000", "prevouts": ["fef7110000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8", "2a3712000000000022512077461b0e3955cce0a8e05b12e20464a062d47e96c909cad0353185349b78401d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936adaaf8ebdf7a353de71c15a37034f51fb6be564e19f20a2692fac514c8d543cb"]}, "failure": {"scriptSig": "", "witness": ["6a19616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/892cc3023c1245c75dd88475a0e49fe4d5063dd9 b/txscript/data/taproot-ref/892cc3023c1245c75dd88475a0e49fe4d5063dd9 new file mode 100644 index 0000000000..3f5fde2fb6 --- /dev/null +++ b/txscript/data/taproot-ref/892cc3023c1245c75dd88475a0e49fe4d5063dd9 @@ -0,0 +1 @@ +{"tx": "e4ba8c7202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c69000000005862f3e0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcd00000000a6beadbc02bf667500000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d7010000", "prevouts": ["d38156000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "608c210000000000225120242fbb4e68c81dfdc905839a5aa96f20c82583acd27e1bde1e06ec2a83f43f26"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b11badc1b045853cc6ce807b5e540444f7b87b7ae8b48e40871fd90309c75788"]}, "failure": {"scriptSig": "", "witness": ["6aa4616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8951f7b39335a2e501908ed76548372ea5979b19 b/txscript/data/taproot-ref/8951f7b39335a2e501908ed76548372ea5979b19 new file mode 100644 index 0000000000..fd08186495 --- /dev/null +++ b/txscript/data/taproot-ref/8951f7b39335a2e501908ed76548372ea5979b19 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b68000000006d4aa6088bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44101000000ac7b6e38014a4656000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f870b000000", "prevouts": ["297523000000000017a914a1b035f555fd87548264c3580a1f62a42acf027e87", "8479410000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f84a27e6cfa94e00b267aae0852f2041373509fc9af9b3b7fcc66b10f710e312dcf0c734edfbcac159d7813ef9562f4df1a796390e1a91bb6f745d3b9c841d624c8fbf2363a77354fc9c61d01c3ea3e8806c47304e5a0571bc5a832b63c4c4c93c50effc4608d2c714b1f589c510b82e2cb4bd2fb333954004903b4f08f38a79"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936629ce26d76b9b6ae4f96b691e050d04905dbbc4177f4fe4be81239365d442ac099aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d85ffea93b39ff48f026a1de615f9bd5d9d5cb27805fa051e581b49afd71e8d341e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}}, diff --git a/txscript/data/taproot-ref/895da8e67657010ab55eddf2b5e50156498f59c1 b/txscript/data/taproot-ref/895da8e67657010ab55eddf2b5e50156498f59c1 new file mode 100644 index 0000000000..8e78b3bdb7 --- /dev/null +++ b/txscript/data/taproot-ref/895da8e67657010ab55eddf2b5e50156498f59c1 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c57000000006bfe37f5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd9000000002b9ed0c5018f7108000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478720040000", "prevouts": ["571d530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a4e51e0000000000215c1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_71", "final": true, "success": {"scriptSig": "", "witness": ["fd1dbe90240c181a478fc7e390e34eb91e0305fb144e4de97169b0a2a9c10b074eaaa3b779ee1ba002fa9263c4072160a9eabe0c7495d97138c300e9d57f5de2"]}, "failure": {"scriptSig": "", "witness": ["7f579a24f80702c5a5046aa8d1686b53ce1e7a7fa83d61b36a5039dc63ab48d732d3d7baab6d385eab40bed5e14b1849caecfef505c2a8d246a5ba889a776d4671"]}}, diff --git a/txscript/data/taproot-ref/89843a3d7b0d8895dac3541e10e30e0400dc0f5e b/txscript/data/taproot-ref/89843a3d7b0d8895dac3541e10e30e0400dc0f5e new file mode 100644 index 0000000000..3ba6f1f40c --- /dev/null +++ b/txscript/data/taproot-ref/89843a3d7b0d8895dac3541e10e30e0400dc0f5e @@ -0,0 +1 @@ +{"tx": "d07c79b8038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41f0100000018502eebdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9a000000002d3f28d1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c170100000063ffc498030747e700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47874de2e530", "prevouts": ["a595390000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "51a15800000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "dec15700000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004599aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb406f18ba19de64c771db55f5af06ee3412ffaea1fa921290752d742eff6a1e67f7007ac6d9f1365651a4d55e6df0dcb109d268cc6c386b355a4997173bc95c886"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e197185a6c30608fff89dfccb39a96a02e4addd353a2af1bc7b33caa3a3ac07fec6e41ed285c226ab336f92f35d989a379104ed593ec3ff802714cc8e85daf0b3be26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}}, diff --git a/txscript/data/taproot-ref/899da8e446fd56d043e8d9fbd5821c09500c8654 b/txscript/data/taproot-ref/899da8e446fd56d043e8d9fbd5821c09500c8654 new file mode 100644 index 0000000000..360ab509d8 --- /dev/null +++ b/txscript/data/taproot-ref/899da8e446fd56d043e8d9fbd5821c09500c8654 @@ -0,0 +1 @@ +{"tx": "e1a1f69c02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0100000000f91c71a18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e201000000d7f6cca303f3e29600000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac8b000000", "prevouts": ["b9075d0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "61e43c0000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "717d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e8a1eca6f0ee4838d072753f510379a45001b572be63db33e52094017d71a11fe4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8674d0c931fae68ff43996ef27e2c8ff69e275e322181f769b95dd7ebb695302b667dde4f09f14471eadd81946489c41cf4fd01382a4947d773f1f2d4d0db4c57"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d3905b5eb580817a508bd2452bf8931c371ea644e13d674abeda6dc13dde8f16674d0c931fae68ff43996ef27e2c8ff69e275e322181f769b95dd7ebb695302b667dde4f09f14471eadd81946489c41cf4fd01382a4947d773f1f2d4d0db4c57"]}}, diff --git a/txscript/data/taproot-ref/89c130024a3230c8800c10efba7110244146ea67 b/txscript/data/taproot-ref/89c130024a3230c8800c10efba7110244146ea67 new file mode 100644 index 0000000000..7a6dc7634c --- /dev/null +++ b/txscript/data/taproot-ref/89c130024a3230c8800c10efba7110244146ea67 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e40100000087e476028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47200000000408ded1d02f5c75f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987a7000000", "prevouts": ["6082310000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "792e310000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c24c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361d17d6661cc8fb2f1af7119061da5758e988d072e66a98fe62e54b70963bbb8620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e119ca94dd80cd6ec848cff445ef1653ae8d91bf4217e3b4bb0faac1831ae9489bd0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}, "failure": {"scriptSig": "", "witness": ["4c52c2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936737a6221c4287b1aeadc2bab6c338b93b1853c569e1bc8424c8e0cbc8249bbac20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e119ca94dd80cd6ec848cff445ef1653ae8d91bf4217e3b4bb0faac1831ae9489bd0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}}, diff --git a/txscript/data/taproot-ref/89d3b93983fbc2ea121d1407d7944b74f44c67ae b/txscript/data/taproot-ref/89d3b93983fbc2ea121d1407d7944b74f44c67ae new file mode 100644 index 0000000000..9580d633b8 --- /dev/null +++ b/txscript/data/taproot-ref/89d3b93983fbc2ea121d1407d7944b74f44c67ae @@ -0,0 +1 @@ +{"tx": "0200000001f85ef04c4139d614d10d1a30e75a9f6421df67317126da87b2f877c2ab20246300000000002f8f319604f3a7861511000000160014f2ca549f2f8613e81a7cb48fd110f37b7fb1529a580200000000000017a91402e53bc18808b3955166f5113b83b265fa421e9987580200000000000017a9143fd5279308772d81081a68d882f81a7ac08fe1d9875802000000000000160014bf1a19526352877c6b170dd8786dc91b1610ae1ceb8f3f5a", "prevouts": ["dd6589151100000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/keypath_invalidsig", "success": {"scriptSig": "", "witness": ["2acb152055acd589ab559fab80591212866cc02b4a6967cab7e92676567cdf906fe0cb89855e0f7bf24b1b402af7b12ec05358eef773b32c861a8e53280322b4"]}}, diff --git a/txscript/data/taproot-ref/89db7a1ad6220b1635de9734c32a76ab69bb70e3 b/txscript/data/taproot-ref/89db7a1ad6220b1635de9734c32a76ab69bb70e3 new file mode 100644 index 0000000000..8ca1a4ed41 --- /dev/null +++ b/txscript/data/taproot-ref/89db7a1ad6220b1635de9734c32a76ab69bb70e3 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706d000000001f9bde91bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf790100000000c42cfc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48601000000dc5b1c9a012caa0c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc786000000", "prevouts": ["2d69100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0c5769000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "3b5e3e00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f6", "final": true, "success": {"scriptSig": "", "witness": ["007bd681c6dc9c8c21217ef9bcc62c4dd2b145578198511d6acc59e8f60f176abf98b3e7c63ec1be58765e29b81e930315db501bc126e047c76f6a2bb5e238d782"]}, "failure": {"scriptSig": "", "witness": ["bfa88c48012f165fc070b203cd48090df0fd5b243e12775ba2fa7dad623f6caad2c3d363440efa1f991c79523dc99436bf88b1b88f6f70f536dac72e5278ad65f6"]}}, diff --git a/txscript/data/taproot-ref/89df1562d15e81161f4c47827c0802d44a116dcd b/txscript/data/taproot-ref/89df1562d15e81161f4c47827c0802d44a116dcd new file mode 100644 index 0000000000..84ba97ad28 --- /dev/null +++ b/txscript/data/taproot-ref/89df1562d15e81161f4c47827c0802d44a116dcd @@ -0,0 +1 @@ +{"tx": "db2f843102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1c0200000066a63388dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1f01000000bf6ffcb001a26d3d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71019ae4b", "prevouts": ["a799760000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "62b4510000000000225120db9ddec7a132eff6af262a32a64079b83118332a0594bc0106395f5efc921419"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ab7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936868a8b5d4fa4ebb812e9187140be33b96106da21b05039089cc432e85b6849d0588819b06684552554786b2b49e7cd3d9dcfc0725dc4b3b93f8768a6a84fb31b7c07bb1aa10d02d314eb70c923196d0e49e71087637e2d5a1d7fe44c2440c398"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93686c31dcf8859245bfdb2cad1cc94d16ee0f95fa651e4b9f3d702e098ccaa2b3aa05ea26d8201abb1a5c146c7fb3e541bebd813f78d5cb214a01f0b6fbe6f45888cb303569f28fbe8acbcc2d27d183e3a68170f5392df28f40a03efea695d856e"]}}, diff --git a/txscript/data/taproot-ref/89e008ea516ef46108ee4b85055e4cba034e75c2 b/txscript/data/taproot-ref/89e008ea516ef46108ee4b85055e4cba034e75c2 new file mode 100644 index 0000000000..8df3ee4717 --- /dev/null +++ b/txscript/data/taproot-ref/89e008ea516ef46108ee4b85055e4cba034e75c2 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45b010000002378e255bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2701000000bcdd8d74044f8ea9000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478740000000", "prevouts": ["780d3e000000000017a91481d4142ddc5ce7a3de4047bd48b623419b5bc45e87", "ab0c6d0000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21591f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["5b1ac49476ce8752c6dc77f30c28a07a3c6555a0b869ccadbc97ddecfc5a9a87f24eb13ce140b2c2dadfb72d43206eb9e2965523aa3f02d2e478c54bb4a4e034"]}}, diff --git a/txscript/data/taproot-ref/89fa19afc7b932f3749a095009d1bf1c6162c607 b/txscript/data/taproot-ref/89fa19afc7b932f3749a095009d1bf1c6162c607 new file mode 100644 index 0000000000..5767afb631 --- /dev/null +++ b/txscript/data/taproot-ref/89fa19afc7b932f3749a095009d1bf1c6162c607 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ec000000003f55e4d0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4d01000000793d45fa02b27535000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a15b323f", "prevouts": ["522912000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "43a8250000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["ec4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd4d99442df2d897dc88267982d8eb20b7dde930eaaf897e66f6a5ce7f7a19008bc5bddb1ae8a97e111feaf10767a648ae88621f6e3dc27f3d4b61f2a6f156b2a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}, "failure": {"scriptSig": "", "witness": ["4c52ec", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1ea5b08b003f1d8a082790805ee2a5a4def5fb527637606ac665fe1637cb888218bc5bddb1ae8a97e111feaf10767a648ae88621f6e3dc27f3d4b61f2a6f156b2a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}}, diff --git a/txscript/data/taproot-ref/8a0a41ec1bffbaf105b7b5b3784d680d00446960 b/txscript/data/taproot-ref/8a0a41ec1bffbaf105b7b5b3784d680d00446960 new file mode 100644 index 0000000000..c6884998a5 --- /dev/null +++ b/txscript/data/taproot-ref/8a0a41ec1bffbaf105b7b5b3784d680d00446960 @@ -0,0 +1 @@ +{"tx": "ddd1479b0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702c010000000c199496bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfca01000000ce7dd895015e5252000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67e020000", "prevouts": ["67df110000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "ce3d7e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a85", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9e4bee3c96900e797e1fee678d6e06beb60b8d47d410b933df49cb9a9e4051dd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51f1361648aec2fada6693d9b39e398a39a20a7ec02f5f37d94bd6d3a28893e48e1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a3c2beca4b8e4f57261ec8681e6b4464b1dc20a4d14bb0589bf8084eb401fef1f1361648aec2fada6693d9b39e398a39a20a7ec02f5f37d94bd6d3a28893e48e1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}}, diff --git a/txscript/data/taproot-ref/8a0ad7fc3cf79a721233622b6ae7a4bfc52c228a b/txscript/data/taproot-ref/8a0ad7fc3cf79a721233622b6ae7a4bfc52c228a new file mode 100644 index 0000000000..ecd97b97ba --- /dev/null +++ b/txscript/data/taproot-ref/8a0ad7fc3cf79a721233622b6ae7a4bfc52c228a @@ -0,0 +1 @@ +{"tx": "a8b92e5502bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7c01000000345ea6848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40901000000fc4b1ed502e2dfa00000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac69b80e4e", "prevouts": ["8402640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7c773f000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_16", "final": true, "success": {"scriptSig": "", "witness": ["b1f4e3b8205028770f75a86f26f17fd5c0022451cc288b1d20de7e9503f6e4bb05a65c31706029f2ca81866adeae840d8cd1c063688f8b224e01c0c88ec2f19e02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["39952cb504494eade9631824e8b0187360a59b693b51a347283bb6d608b5e70a5e274c3ebb63fe4d777fa4f9437ed11bc98facf35ade273ee5c06bd763aad17d16", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/8a2775fc1b4fdf627698087dbc89fc1a3b0943be b/txscript/data/taproot-ref/8a2775fc1b4fdf627698087dbc89fc1a3b0943be new file mode 100644 index 0000000000..13f64d365c --- /dev/null +++ b/txscript/data/taproot-ref/8a2775fc1b4fdf627698087dbc89fc1a3b0943be @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270130100000004782a72dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1e010000004a150c568bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48d01000000dfbafbcc0153c12000000000001600149d38710eb90e420b159c7a9263994c88e6810bc776010000", "prevouts": ["053e120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1850210000000000225120bf7c0652824d65f4682a3056a4ee7d3427d5bd09fcf8c412b9591353033138ae", "3e9d3b00000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361eff29e1a89e650076b8d3c56302881d09c9df215774ed99993aaed14acd6615"]}, "failure": {"scriptSig": "", "witness": ["6a0c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8a289fe11f09a8013015d4bdd383c4d26de1f483 b/txscript/data/taproot-ref/8a289fe11f09a8013015d4bdd383c4d26de1f483 new file mode 100644 index 0000000000..ac1991494d --- /dev/null +++ b/txscript/data/taproot-ref/8a289fe11f09a8013015d4bdd383c4d26de1f483 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb700000000d737d52860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d300000000aa1153480339fd2f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796741c1828", "prevouts": ["d3ed200000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "6e931100000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["ed4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93655e252cfaa9768c1119fa64085e95b8d16b96942ccc526bc25f5651427cfe139d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c9b0690fa0521f4fddf88c65f69e0716898ebb5a52dcb1ee37dd2f34a8a99dbd71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}, "failure": {"scriptSig": "", "witness": ["4c52ed", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360411da0ef60a663b804e7225eddf07cb547b0be4fa0e1866d29c65c2bfc285257eb7d8a059ff700a84b94cf01bc4b173d99041796f2088e1a59df5cc5c18f54d86475c33b310e45b92339559838140b9b3f3d62b1cf111e129ddf9f566de62eb71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}}, diff --git a/txscript/data/taproot-ref/8a29d68c4034560207bd08a36c47e26953bebe3f b/txscript/data/taproot-ref/8a29d68c4034560207bd08a36c47e26953bebe3f new file mode 100644 index 0000000000..494b38d548 --- /dev/null +++ b/txscript/data/taproot-ref/8a29d68c4034560207bd08a36c47e26953bebe3f @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127093010000002d19d9aadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba200000000c727f6d70274d23500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748705010000", "prevouts": ["f447110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3830270000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c5", "final": true, "success": {"scriptSig": "", "witness": ["d207c56374a7ed88115838212127ae62b4f5c0a8c9245d3276c8ab5214e160e3d4fdfb9a2cc7bc3678ad4f4ce96159f1b3a803cb40a3f1c6b4fccb83494e689f01"]}, "failure": {"scriptSig": "", "witness": ["5252a210e47bf9a706de505f720b8f4e49ac89359706d0765d1d47817c280013ae4825c81edf38b21dea276996e2af22826dc4d32f1a57723e699742a38dff74c5"]}}, diff --git a/txscript/data/taproot-ref/8a3477e0575b2a93269f750c0395201cd0f19a37 b/txscript/data/taproot-ref/8a3477e0575b2a93269f750c0395201cd0f19a37 new file mode 100644 index 0000000000..3d3909f205 --- /dev/null +++ b/txscript/data/taproot-ref/8a3477e0575b2a93269f750c0395201cd0f19a37 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270230000000056475b9ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca0010000002f35f8e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8900000000ccb14bf503f56ee6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898746a49225", "prevouts": ["6ab20e0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "e73c5e000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "aea27b00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638968", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5f4aac5bedb8d92acb3d38ea9721137c03ef46c31c1e33f2b8a1b5032692e959886f85ebb300297009aa959255e1f8e976b091c7e06b33477ed400c40a83b4ccb3e0a345cce78c1fe891e9b22b966ce84a8b12623d949f63d5e15e148dd67959d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936166b0e2d82fdc11b86a491b111c45071722397947c900f7dc0756a6987fcf7514b1cf341ebb9351320fe3e143ffa2dad1c15696d7ac983fbe7e302fe7a073e7ecf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}}, diff --git a/txscript/data/taproot-ref/8a3c9306c70ceb610d6f1f738df6679eabff4238 b/txscript/data/taproot-ref/8a3c9306c70ceb610d6f1f738df6679eabff4238 new file mode 100644 index 0000000000..465e7ad769 --- /dev/null +++ b/txscript/data/taproot-ref/8a3c9306c70ceb610d6f1f738df6679eabff4238 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48f01000000072c8a9abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4e0100000043944632025c9eb500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1c4cd623", "prevouts": ["881937000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "7fda8000000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ca", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f336cbd2c434dcde2d093b968cd4500063515049b2ab4f542ce372ccec22f446d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c1012b923c15ff4ca5711684c82f77f7d0ace9e417918255ff860668826001128a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d520ce1e8f5df7741068fe8539649c9e500f335a96aa69621db8e7a39b2f9d4cf99c996d59a69d75c183cc1e3ba6b17987582b2274e87a7d50251745c93805cc8eba4e75ed92f6e82baf0cd6101dcd67879c020ab703e3dac001fd69a24240ecc7034c4ece6ceffdf067bd97d8bd2a80e986f14e8b5dca33ff1523eba7a77d63"]}}, diff --git a/txscript/data/taproot-ref/8a52da0771f3d868955501e901d2540538f4d521 b/txscript/data/taproot-ref/8a52da0771f3d868955501e901d2540538f4d521 new file mode 100644 index 0000000000..97d52e1487 --- /dev/null +++ b/txscript/data/taproot-ref/8a52da0771f3d868955501e901d2540538f4d521 @@ -0,0 +1 @@ +{"tx": "b824250602dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7a01000000fd949edddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1401000000948f09de04c9c07800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487fc000000", "prevouts": ["ef115600000000002251209f6df9bf0ba86119ec56bc774d8ddd924452496c0c827ee2df6dd8b5f3d2e1ef", "e303250000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93635d60f8ae57e87c9caa24a9d39cb53ca5fb1c070fbd40625acedd7253a41b651"]}, "failure": {"scriptSig": "", "witness": ["6a6e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8a7bd56f4854fd39ca2b9dac03cf4e4f92a1b93d b/txscript/data/taproot-ref/8a7bd56f4854fd39ca2b9dac03cf4e4f92a1b93d new file mode 100644 index 0000000000..8f80f9b6d7 --- /dev/null +++ b/txscript/data/taproot-ref/8a7bd56f4854fd39ca2b9dac03cf4e4f92a1b93d @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd10000000089808f898bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f9010000006c9d49b102408d97000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac25e01256", "prevouts": ["56c25f00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da", "91d339000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "3f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369aba35d3104e600974e554b9cb99049f7aee0f23ae7c74d9fbe3a88b265c838bd728e192bc5f69ac80b4a6e0537a86a2095372e08a2c76143a8a8a3d0ed1b85bc06da1f6599d7e514a71ffa8a2afff73792fcf1df1b953d2196d009aa835a52703985aa46dcbff8b0495de750bd1afe74a661312f7eddf1146199ee1ea8c08aa"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3d62cda1d889ee05ca59ece4e76d2fa27c0bab47b49d4f70b1e2cb0efe9a711fea811edfde1d836b623c2094badb4ab8bc7795b2b49da5506600222f32ea3fbd"]}}, diff --git a/txscript/data/taproot-ref/8a8928f98f7dd800744cfcdbefeff96b97543b76 b/txscript/data/taproot-ref/8a8928f98f7dd800744cfcdbefeff96b97543b76 new file mode 100644 index 0000000000..a5d083f583 --- /dev/null +++ b/txscript/data/taproot-ref/8a8928f98f7dd800744cfcdbefeff96b97543b76 @@ -0,0 +1 @@ +{"tx": "766d60d703bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1201000000da307bb5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0000000000def8accadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba10000000099eb13d001d42a740000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72a040000", "prevouts": ["f9057b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6272570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b92221000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "937d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2350f02f615a91dbdd9bf0827d9652a9c0f0c48b61032bfc7abdf258f76a30109625eb62ff27a7a3a1f9ea411032fb959ab5a0c50697db7fef72f456b5013f4a62d371a9b01f30ea116c30e8195d2d6eb7c97c8692c0c95de95a904f83b96ad4"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366533bb586569e93ca4a2e8b34ab37dbed5250778907945cd2689174a39ff06ce2350f02f615a91dbdd9bf0827d9652a9c0f0c48b61032bfc7abdf258f76a30109625eb62ff27a7a3a1f9ea411032fb959ab5a0c50697db7fef72f456b5013f4a62d371a9b01f30ea116c30e8195d2d6eb7c97c8692c0c95de95a904f83b96ad4"]}}, diff --git a/txscript/data/taproot-ref/8a95cc474b746e69625f0fe8c262c07a37a82a7d b/txscript/data/taproot-ref/8a95cc474b746e69625f0fe8c262c07a37a82a7d new file mode 100644 index 0000000000..d5c2872406 --- /dev/null +++ b/txscript/data/taproot-ref/8a95cc474b746e69625f0fe8c262c07a37a82a7d @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270940100000005a0461d010a6804000000000017a914719f78084af863e000acd618ba76df979722368987c7000000", "prevouts": ["7c9b110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_6c", "final": true, "success": {"scriptSig": "", "witness": ["f9d6d1cb31f9e227829546490c6cd0c0b52bc1c3a5838984c3e685bcda8254e0f1afa415aeb8736a44ca1bb04b5a05dd1f17b5696cccc66625fc9a531735ad6c01"]}, "failure": {"scriptSig": "", "witness": ["8aed9816ace7e2ee68b6ff38879d2366a47516ac9fcaf3c1846446fce6bd6f293a839996456ef86d3b826f3e0e6e26ff78a5a600f80b28b3ec3703b4d131cf076c"]}}, diff --git a/txscript/data/taproot-ref/8ab6f611cd721ca128cb8f5ea3078c1b431d5704 b/txscript/data/taproot-ref/8ab6f611cd721ca128cb8f5ea3078c1b431d5704 new file mode 100644 index 0000000000..c7c5d45c21 --- /dev/null +++ b/txscript/data/taproot-ref/8ab6f611cd721ca128cb8f5ea3078c1b431d5704 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b100100000018a6bf8ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc8010000001c25910902ab3e8900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875502f91e", "prevouts": ["12271f0000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "ba146c0000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e368", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514e3e51653db7a26891b04c3a1156361c2ac14b53ddf2b0df0fb784e58b5ceef674166a9b0f1c55c1671126e5eb7d3b70cf827ee1dc762db7ef6404d6cf84ba0da54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366180c1fbed8b69bb15135837f8534a2d361ae32955d37b8de7eb439883150e361741062de046b8f3bdf7ef41b5db27631c489deab6fd85436806296af4173e7e74166a9b0f1c55c1671126e5eb7d3b70cf827ee1dc762db7ef6404d6cf84ba0da54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}}, diff --git a/txscript/data/taproot-ref/8abdd04f7c724f0a762d03fb6fb80e698280ae9c b/txscript/data/taproot-ref/8abdd04f7c724f0a762d03fb6fb80e698280ae9c new file mode 100644 index 0000000000..c0bad46e33 --- /dev/null +++ b/txscript/data/taproot-ref/8abdd04f7c724f0a762d03fb6fb80e698280ae9c @@ -0,0 +1 @@ +{"tx": "af7531b002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b15010000003f6948df60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700702000000b229d6fb012748260000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc4f020000", "prevouts": ["bee5240000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50", "25fa0f00000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "227d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c13c6885c53a07614131d749dc0b9c4fac4cbf357599a76450ee1c7b87f78943dc4c18ce03381be5d83370dbaee0482c0440aa7aa94902a00244e0237bd29478fcb15428af69077ee4e47ddc8bd2adcf7d97a29fc56c75a24a213a103a1e3586"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e86a45def9951625cf02c88598f8616d12bef3cc01ed824d79a70edf31b7fbe0e1a4a9bce64ad1fc5af22ad5621933415c83e23766bbab20239912b691ace9dee2"]}}, diff --git a/txscript/data/taproot-ref/8b08333db48411d829619458a66585a39efcbb11 b/txscript/data/taproot-ref/8b08333db48411d829619458a66585a39efcbb11 new file mode 100644 index 0000000000..6e29548c63 --- /dev/null +++ b/txscript/data/taproot-ref/8b08333db48411d829619458a66585a39efcbb11 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b14000000005d6cd1b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bd01000000cedba4cd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700102000000d9229fe1044be13e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796c7040000", "prevouts": ["a80a1f00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "1e3d120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "67ba0f0000000000225120fa0c69fd3dab50066606d386e9137466ea422a077bab3cf3dc61d0cdd59f488d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6607ccaad4a40cbb35d90662461c37fc46c0a06aef072d0f22e66c7426113f5"]}, "failure": {"scriptSig": "", "witness": ["6a69616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8b2cadafb5c90652623fe20f1da4fa65454b1764 b/txscript/data/taproot-ref/8b2cadafb5c90652623fe20f1da4fa65454b1764 new file mode 100644 index 0000000000..5d867c97df --- /dev/null +++ b/txscript/data/taproot-ref/8b2cadafb5c90652623fe20f1da4fa65454b1764 @@ -0,0 +1 @@ +{"tx": "7f672b810260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704600000000d96525f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce000000000157fcba20390206e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a66a020000", "prevouts": ["5d7811000000000017a914b0716f1bec91d4758ee97d9063c9da884dd2ba5287", "32655f0000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c768", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0406f8ad106053ce18d601a69e7ac0d788ca81f875fce58e79951c9b079357c4ecdbff3eecb3f5fa90fd3ed1bb4a8c0c36fc15f71a4102bd4f372c5f95e5c7d5941b26b476c022edf868776977d31e53e85212ba204fe552062798c457a392dc1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c27b7e516a1b3919c0c2aae21712d1c7c40c32040b64b5fd9dbe249132a2d861ab0398bc4828dee75def1007ce877d708ab4ca86c9734bfab291d4bd05bae3eec1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}}, diff --git a/txscript/data/taproot-ref/8b379a5db43a90e8d77da62355f3ac86f95b1422 b/txscript/data/taproot-ref/8b379a5db43a90e8d77da62355f3ac86f95b1422 new file mode 100644 index 0000000000..7618477a46 --- /dev/null +++ b/txscript/data/taproot-ref/8b379a5db43a90e8d77da62355f3ac86f95b1422 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cde000000009f5d27808bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d201000000283e3bd98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42700000000da52b0940417c3c800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e52a3644", "prevouts": ["6fb15200000000001653142540f27e90740933c99d4f17ab2dfc6c82951cfb", "55f23f000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87", "a8d8370000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c9", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936643cf28b3f57e3e135ddaf8a1f03437647ba3161555e3c3b2dda50db56032ea077878475803065420b5149b394b9f2a263406aa3a3cf62bdb9b13e67809a83ebcc9238bf2d7dc0bcf11838c34785251ea2fa5f3bb034bc98e2e8efb0909b7dbc17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d3c147557fd4654830368843709159d459528293d28ab2736e9587eb54fea08bf48725aff660a72fd31f8e9799fbe605d57d774c031cecd8b6989780acb581b6b24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}}, diff --git a/txscript/data/taproot-ref/8b436810adfe76e9f0a84f1a2382284cefc4128a b/txscript/data/taproot-ref/8b436810adfe76e9f0a84f1a2382284cefc4128a new file mode 100644 index 0000000000..52b6003bb7 --- /dev/null +++ b/txscript/data/taproot-ref/8b436810adfe76e9f0a84f1a2382284cefc4128a @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ee010000002a96f3a28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f4010000000cf823d504af574a00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fced92f55c", "prevouts": ["dae111000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "57623a0000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c74c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d86572024cf807c4b041deab506320299ff116921971164ef72b2742896e58a89a98f91cdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}, "failure": {"scriptSig": "", "witness": ["4c52c7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d5c50aa1912c177c20f79fe229e02015d7cb9a41b9e5cf4d8e88b9fad70bb67a0d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3ab0398bc4828dee75def1007ce877d708ab4ca86c9734bfab291d4bd05bae3eec1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}}, diff --git a/txscript/data/taproot-ref/8b4a8862bbb6306cc7b4473bba476bcaf6383aee b/txscript/data/taproot-ref/8b4a8862bbb6306cc7b4473bba476bcaf6383aee new file mode 100644 index 0000000000..4983f84bd2 --- /dev/null +++ b/txscript/data/taproot-ref/8b4a8862bbb6306cc7b4473bba476bcaf6383aee @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cad010000006f1f83aa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702302000000807b5d64015f1d3700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1d010000", "prevouts": ["3a024d0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "f1401400000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a47841bfd1c7801e119366e06eef8526d3a7e36eb6419e26d5e658afa9c8cca5b88f998be5301314da3588cf7094ff0b779091d289dc1f0b3826508d93d51b78c2782374d67da9500785d400f7ef10ae84f146bbb568355094c68456b68f7a283b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb0a7dd9fe9480c6c770de395b90f3ae6bfd835bf7cfa16a827fc723deabf662a469bfc8de16b0968070038325e6b76e7740524a1c4ae3d3f158ce1e63cb3bfd7c6ac6071aeb5642f86cbd8c403a36f49b1ae971c310fa0b2c6d23cdcc52f9ae3b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}}, diff --git a/txscript/data/taproot-ref/8b5c3d67f71726b53372b58a37b41fce4a30a5ac b/txscript/data/taproot-ref/8b5c3d67f71726b53372b58a37b41fce4a30a5ac new file mode 100644 index 0000000000..2569544acf --- /dev/null +++ b/txscript/data/taproot-ref/8b5c3d67f71726b53372b58a37b41fce4a30a5ac @@ -0,0 +1 @@ +{"tx": "9f516898028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4370000000009665a87bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe60000000014113c8e04b9d8c0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac96dffc49", "prevouts": ["6081400000000000225120b10c5cbe32c5e90da6e76e6bf182a80e9130a66e1280db2d9eaabffb93bce832", "aeb98200000000002251205b7dc500a06d9d49351272d9ef7a52148a11476ab62e1647e512b05f260e1644"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367e3e831b563b2b880bbf500bbc169294f1ed56123dafb9d201684792ec0730d8"]}, "failure": {"scriptSig": "", "witness": ["6a4d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8b5c7dbd04ac3065bf6c8164f3068ebc910ddc30 b/txscript/data/taproot-ref/8b5c7dbd04ac3065bf6c8164f3068ebc910ddc30 new file mode 100644 index 0000000000..d96c5a4755 --- /dev/null +++ b/txscript/data/taproot-ref/8b5c7dbd04ac3065bf6c8164f3068ebc910ddc30 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0601000000cd66d1bebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf64000000002ad67cc0048a99e0000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac56000000", "prevouts": ["9ca76c0000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "71787600000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "e67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936436f2c3332eeafdc86102af3c688be283ada2e1fa472215067cffd97efb6f869e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e824d900ba5429999a9d5e0d5b2b257ef1523eacccb529e56e7cf347f802d02f5093d03784866e2fdd94d7d1b7c12b1f0da96746c05c19b8696f0ac6a701ba8135"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93674a87b9bffe1a64ed32d6b76ba55fcf88384cfec2ec89e9610ad09f9a858aa1324d900ba5429999a9d5e0d5b2b257ef1523eacccb529e56e7cf347f802d02f5093d03784866e2fdd94d7d1b7c12b1f0da96746c05c19b8696f0ac6a701ba8135"]}}, diff --git a/txscript/data/taproot-ref/8b714927de7515d6467407861bea2d1b6816f769 b/txscript/data/taproot-ref/8b714927de7515d6467407861bea2d1b6816f769 new file mode 100644 index 0000000000..7bf99e2eb2 --- /dev/null +++ b/txscript/data/taproot-ref/8b714927de7515d6467407861bea2d1b6816f769 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e400000000e43d3005dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdb01000000dc21dcf7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1000000000413109ca01c445280000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca4000000", "prevouts": ["00ca0e000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "3c28250000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "bb275b00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/oldpk/checksigadd", "success": {"scriptSig": "", "witness": ["15912b8bc6304a33b8ed9d265d403d3802e220f88982dfdb6140a347643b52711d78e260943da36f6ebe274489b03d50f52b72255a7e4d010c67d28a86c13b16", "2102871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362c90e4fb2a2921352a86dc7c131784720f0df4e82c7414e3d711f961d82204f725d2d811f1fcdf038ed551a0402edfb56d2882c43855b6a90156ad93536f2a610b12816ededf24e7a65ef26600ff9c8d6dd6be11892b31bc567d31a4224fa918dc78db5a53c26d137b3cdb2b3520f4dc1e22712cbed9218761dec041353758fad69ad387871b891a9868cd30ea616cc787b69a97197bdc922cdd155c8ad8c453965701560206cf1b3adefb9fc7df786920fd1994eeff2c65a7509446ea0945156e83c1ddee4936f7055b581c15b022cb9fc52c765ee248979ac64249602a239e3d351e4d299371dcd96f5d6f96d46c92a1b411ab803a45e7e6d51443156c8f100202def45ffd88d49fddde6662fe7624f6dff183f786d6ce43460a7a16256f5521d7fab248574dc85f779b345c50aa2a58555066e952f31a388332632e2803ad2025e8fb1db960e910596f419fefc77f259577ed82c1cd7ab83eba63e03c4a2615c22c4ce3b706c1d8a9a9d3ff978e7621b37a6868e1d99e3364a361d6bae06a319789fad1a51c3692427fb2b20d7269f1c10af57e5ea3e2c20e0e79126c0422063108b9f07592932b9e5078ce575b814c49190e939925197578c8b829acd51d8b0e659112c9f7f4ef135ef7e3677927c686e2cfb83a5642dd1287d117c18623babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["c917a99b78f4b28b8b2a524e089c2965c939a52d493680da9d7c6ebe049034bfdf12f4070cd3ac3ecbd4ffc690272386f2ce294d6a953327d2eac43ecbb606c1", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d2db232a58a684473efffe5f8be15c17374986169cf18c1adb110b544d48679b6f3543d66dd2934a4b4b5b83f3181725b5ccb68f1096ac62351c7c97bd1fb9501b8110e709da1864e3fbcb3b5249515c34bb807e7a52bfe6718950e769cad388c56ff404b78dc0a0b90d50115d89846b94a2b0a1f0895318a364e3dc179dd61f9b1e0d638a311a5be1486a7a4c42f89ed43ffd1d5b18820f631006aab35c0b2a02b593180c53027b35b862cc29f04a25efce114c7682377a83dbcf64f6fe42598064c72ae707f2b03b7d69f3c0306a0bb5edc9aa2d90aecbb96bd412d5b1ee8f00d68262204427d46410b755bc31a6012df0b06b921e6cd021b936d3d4c99eead90212921e1142bda8cb81c5ff3145b34391c40797432570ad9a88a0958a1b955fe09784706370c5f6fd13c48513ab6cc16af1e04504ea44462b93ae24aca3b2228a833ef2c51accd6ee09327b5cb9ad2975d597ee135bfef0964473e20f824ec199d2a72d3d5f5ff6ee974913584144656ddfc893ea617971c4925fe8b7e1c4f556906203221bddfee6deb7780e80a3769637a05bcf2efe708f1aaa4a6ffdc17363486d1e033637af9f6d28292a4f4527a2090bfcb5efca2ed9c0d63c01e16c98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/8b7781da37cae546b0800cc96db74dfb1988fa5d b/txscript/data/taproot-ref/8b7781da37cae546b0800cc96db74dfb1988fa5d new file mode 100644 index 0000000000..a84105428d --- /dev/null +++ b/txscript/data/taproot-ref/8b7781da37cae546b0800cc96db74dfb1988fa5d @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c485000000008b339dabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0600000000e4e34c2901612901000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48716040000", "prevouts": ["f0d93500000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1", "dd75230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6adc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367137195a510293ea231b2d4432bd69f7d82c958dc1ea3c0850c3e080e60319b4a39f866618102a4b08e1c83cadbbeb41bf3ed62f238c8432fccdf019ac45545bfaeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c4113e49c86f839239ec362989ec8b927e111aaa7a55b69f94a02373a905535683faa9f1fb55f2c754174031ab88b9fb2c4d1471ac070ceb12091a666ed99e827470af5f469e43c444817efa23ad8740a4ec3822d36804e7973b39d521bdef59faeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}}, diff --git a/txscript/data/taproot-ref/8b8235aeb63d5111ff81b6406893e2c114f3d163 b/txscript/data/taproot-ref/8b8235aeb63d5111ff81b6406893e2c114f3d163 new file mode 100644 index 0000000000..0823aed2f3 --- /dev/null +++ b/txscript/data/taproot-ref/8b8235aeb63d5111ff81b6406893e2c114f3d163 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41a0100000058adf9d98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bc01000000feafeba002c3807700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac0756be2a", "prevouts": ["75b6380000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f", "472441000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "147d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ad1099cc9bb3a5e2066786e30d0fff4359b3ce527e140b44a0b5c89c6b4383919a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100efb63111b06c7a0ce3f44d9f6906db8fc60057b72694cfd58ed25db88d188e5fc"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e5061717769e1dacf027f152dbc7d505d6964cf4bcf3126b59284ff35a733198fdc2d7aa80560d1a81b9ed628b4b72c1af718550327182f7e69256034992ba893488b030fbb16fa8d50c4f1f044e6df81cbeac111f0be15e3f466e559374b3e5568dbaf979cca58396dcf271ee6fc736edd00965a3b0ecce9c87347ff88ab08a"]}}, diff --git a/txscript/data/taproot-ref/8b926866858180ba6c9e1a87ace930fdf129b59b b/txscript/data/taproot-ref/8b926866858180ba6c9e1a87ace930fdf129b59b new file mode 100644 index 0000000000..ea14ab5efc --- /dev/null +++ b/txscript/data/taproot-ref/8b926866858180ba6c9e1a87ace930fdf129b59b @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704001000000baee91adbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4c0100000055b2f3940307357600000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6a048da2e", "prevouts": ["6aed0e00000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "77d6680000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902488b34b36e34d820caceca2b79bd093fa8a7714f7500d5ee32536265b602f40f0be44bf66930e1724203b4edda0782d8468bd533d05c7fdc0daacf035698098cc81547ee2e067b75c4c4ec2758a52c52a5616c5ccfe85bea79a0642313ef787480076ceb3e7bcbd56fa57fc5527fe643943cc62483d8d33d856b11ac8f7468d5e121309217a7cfe0378fb6b8588cc6c238711b6e0f0a743e13ab9659bc5650e69d326cfe0177f77579b9f648a9526ac0adf1ac4aa175e56143c74b73c641e861e14c6385e683c554f05a2a8de1a56c36192818205f7371740c35c4d082d58f3d4565ddd1aa3fd5dcd4540515e951a78585fefa6471481652a715f77b3ab0a57bf75f8022f89794bdd054d1a466bc6a1a93fcab956d4448c487c812b5e8d42ba697c6b8415f59660b3bdbf4716fb44ba65c1f53db9afc770c05fd32fc7d34ec95572b1f0e114817859dcd2a97796b00be013d06337ef342c8d75d8bef8abb166e853fc1f2c339b577da907bd404a0a10f72f801a31ab9da083e8e7ae2705cf97e1e36a1033e49a98994c2ddcf8042c5683c49f146edbf289ab81ac74575a5001cdefb0593c4bdc0bcd16ca5368eac04a8548e49d2a1e6671888a0a6a07c5df09d0d17b5469a08e62c6f44a11792da4516be317009b893ade47e399153235b94d95d9d42ed709c43b27b97ef04905eda2c02c10cfb4dd66beb3f700568ad248c83c7fa2a08ce5466524175", "fd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a82c424d3aba119543b343a8fde7bc4fd3ae7e2d0954a13e45d13e7747deceac3deb15f38c362b741ec1998ad5d47cefa85b35179e49129213f0ee69ef729f0eebdb1eebdcbd8002197b9f44a9e59d0e9024523da319a2f3d109fa4e426d654ff4148296d57de26c46202ca6ca2132af69ac5e2240f6410455c1127b810a8937"]}, "failure": {"scriptSig": "", "witness": ["4d090228c008f2f00b965938e70e66b1c2240283ad8d6fb0fbeafa20098375453b83ff87ed6acd50f3e1e5a93c8c2a20cf6355c1381095c3ff0ca468c914221061dfd3aaac28b18ffa44a6f2db2ac97138c0ea44a60daa0bcb69dcaa228ab94e4cd0c2f45ffed095bb83bf9886cbcd6c27b4d1c20f9083d7d731d9ac7b97b45d67c01b766be68a1b1334d68e74567fde836f7ee413ac884b93ffe1f7e629398d1813caab28579a1c04b45862bf9b2a23fee4f9abe2d9f6e00956ef030a60804c1484d0bd8cbee736dd421db2391fbbd685723fea2e34f1c69e2e9d830f814c62f1d505d3f966eb386ff35af103cedb0d660bc3f4017c6f8748e15efbb33d653c9eb585409748513f60564f55300dce491c2b6d9b2c77336293933a5dce6c1a14afe99de694d46f7fd8e56d7932a33a89b94ddde89aa868963732f739f372e6bdb56fc829ada990fd7a7606e7ba28d4e129fc100ce739ac54182324f5171060259e1de802ae6bf9ec2e54c92f0f12c04f144e1bcc02fe11b8c2fc879f3eda9c2a24a8e23f63f47489914d0ce6151fe926f8e059dde43dab62207f7cf0b8814f9d0f9259e5d05b8b34e3b60404db5160e91aa7a688803898f9d88471156c482a70a2bb8cd36c8cef4fa6382f1184c02f4d336dd768a0d9803057d0a887ff311fca5ff095b2d8e5873f46ac71a49da7eb3cc1fdad662d3f7f58547be544cb315d7145ae352874c038fdaeed224575", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936df064c117c137d5c206bbed5b1bea19788f933559dc29ad302e98441d59c8ac23deb15f38c362b741ec1998ad5d47cefa85b35179e49129213f0ee69ef729f0eebdb1eebdcbd8002197b9f44a9e59d0e9024523da319a2f3d109fa4e426d654ff4148296d57de26c46202ca6ca2132af69ac5e2240f6410455c1127b810a8937"]}}, diff --git a/txscript/data/taproot-ref/8b9de640b20beae0f41a3d88dacf8e7c8c00e4a9 b/txscript/data/taproot-ref/8b9de640b20beae0f41a3d88dacf8e7c8c00e4a9 new file mode 100644 index 0000000000..33f32e2d98 --- /dev/null +++ b/txscript/data/taproot-ref/8b9de640b20beae0f41a3d88dacf8e7c8c00e4a9 @@ -0,0 +1 @@ +{"tx": "d666eeb702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b37010000005ba523eadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2500000000a14399b10167ff3400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac93222b49", "prevouts": ["60c422000000000022512036c493d82a149ae4f58587b8995f80246acaf3fa754ebc9da78117b68027b383", "5e4f2200000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "dc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366c8229ef6249eef7d294f23c9bd7511150aaa9bb9283ed908def3a40c2c66d128080c17c1a9ba5ea8a3780f9d0897aa41ac6e03bb9fc27a0b4027847c33ef9f08f84e1cc8430872045fc695723e7e8ea88aa60745b893850b41017408051d8396d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a38e917535475cf2110d0b0ae2ac5bf0f6bfd0fb66e9319f96694509bbaa8cb206d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}}, diff --git a/txscript/data/taproot-ref/8babec8da5a26469095793b097811d07f256a5e9 b/txscript/data/taproot-ref/8babec8da5a26469095793b097811d07f256a5e9 new file mode 100644 index 0000000000..3aad8cd052 --- /dev/null +++ b/txscript/data/taproot-ref/8babec8da5a26469095793b097811d07f256a5e9 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42c0000000025baee978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42d00000000755c9fcc03cfd46800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac95000000", "prevouts": ["4b5534000000000022512014c9f4af3daae468ca53c2c267c1d6c7824da89a84a3ef6d580562d3f844fc64", "4ff0360000000000225120b7b7f868117fc9823373a98908173a9736217ba3f26290a84f96d4cb32d63ac4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e36d5ca6990a7cd162e850c8419d259e8861c79e5a640a9cd7cd8c694717bae0"]}, "failure": {"scriptSig": "", "witness": ["6a13616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8c4cbb21d02e5d466fb2539022255760626149f2 b/txscript/data/taproot-ref/8c4cbb21d02e5d466fb2539022255760626149f2 new file mode 100644 index 0000000000..af02cc01bc --- /dev/null +++ b/txscript/data/taproot-ref/8c4cbb21d02e5d466fb2539022255760626149f2 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9d0100000067e4a0f360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d0000000088944686bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9001000000dc741ab4037f16ee00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb3af1b32", "prevouts": ["de725e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c5840f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ebe5810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_18", "final": true, "success": {"scriptSig": "", "witness": ["b78d1fc6cb415d6599bdfbc6d3a791fdf9dccc47efb4a71a0c2913613e80984a1b56b751c6b8b760f2149c6ea7d88a1d02bb24720914df9c787e261afc3afa5b83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["2286d794a4355fc5eb36b721bd98592433e50ac481f8d95ef9e79cdb4b233da780ed9b45a5850461755a12ab9f94990a8edcaaff434e12ba4193e1abba6a13fd18", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/8c504464b5b4239a47fd8d4b185c3e0e1b6c1af0 b/txscript/data/taproot-ref/8c504464b5b4239a47fd8d4b185c3e0e1b6c1af0 new file mode 100644 index 0000000000..00a17e0724 --- /dev/null +++ b/txscript/data/taproot-ref/8c504464b5b4239a47fd8d4b185c3e0e1b6c1af0 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc8000000000f67fec902df6b2500000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87f4c6d04d", "prevouts": ["2826270000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["bf4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cddd07b9b59a457ac18abed7266986241d091147981a1ef9d43f6473969f25041ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045911e2ebc11e8ff6aef3c08be5d8086fd4b944e3e1f7063038c1b6dadb4d48ab0219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}, "failure": {"scriptSig": "", "witness": ["4c52bf", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661c1881d39258f1e1cd2a227228c64064431f4d8fcb20ff13365666a49c5d8ea1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045911e2ebc11e8ff6aef3c08be5d8086fd4b944e3e1f7063038c1b6dadb4d48ab0219675e68f7f320420702225b2b85f84783248daa0c82b4ef34e304883a54210"]}}, diff --git a/txscript/data/taproot-ref/8c716ab740c917b4df170efbc22b4e47873d8e3d b/txscript/data/taproot-ref/8c716ab740c917b4df170efbc22b4e47873d8e3d new file mode 100644 index 0000000000..7f4ce7892d --- /dev/null +++ b/txscript/data/taproot-ref/8c716ab740c917b4df170efbc22b4e47873d8e3d @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bc00000000045d0f63dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0301000000dc9d369c018f9e5b000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787a2000000", "prevouts": ["fc803f0000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "8d43260000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100bc459ddf7bc4bd64dea0cc033111fa1a9bf37ecba688b57b124bd5ed93a74d2102204836f32b9271675ee184510c8c21f3ba36f991d13b2b3053550d6f334ae4fde083", "witness": []}, "failure": {"scriptSig": "473044022021007c145d7511680491dfedb1ae554ef2648e19ddb40e39ae86e4664ec0ed08022071f6dd5b3e75068f1782393520a3d8b08ec20479446066a88dc4157af42e593883", "witness": []}}, diff --git a/txscript/data/taproot-ref/8c7dc16b0e4c9ef242cc7ca7264ea3a4cb62a9bd b/txscript/data/taproot-ref/8c7dc16b0e4c9ef242cc7ca7264ea3a4cb62a9bd new file mode 100644 index 0000000000..f528e4a09b --- /dev/null +++ b/txscript/data/taproot-ref/8c7dc16b0e4c9ef242cc7ca7264ea3a4cb62a9bd @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c330100000072fc8e80dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c83000000003e0d57f5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1d01000000594c5146046d9223010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79661010000", "prevouts": ["bb6c5900000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d", "aa9357000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "edbe740000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "a37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe0803cf66684a81fc29be90af35ef83120eb264a0869d6933307511725bb51c5a5b11a87f009b0ff9f397e99e72fe38b81dbea82be72f6430c36b07738f500beebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7accae923b25d556389dd5dd645f6d7ddd89a07a74a73dddd3d85d7b65ae33798aa"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821bbd263bb9b57787cc1695f6735ee6aa4874511c0d77def079ec8f767826a474cae923b25d556389dd5dd645f6d7ddd89a07a74a73dddd3d85d7b65ae33798aa"]}}, diff --git a/txscript/data/taproot-ref/8c87d28e9f82d8cb2da362853cbfd7f6ed73becd b/txscript/data/taproot-ref/8c87d28e9f82d8cb2da362853cbfd7f6ed73becd new file mode 100644 index 0000000000..c543de899b --- /dev/null +++ b/txscript/data/taproot-ref/8c87d28e9f82d8cb2da362853cbfd7f6ed73becd @@ -0,0 +1 @@ +{"tx": "6a7bc0ae03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2d010000005909f2bfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc501000000c4642ca8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b22020000008a37259c02ef808b00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4c7b8943", "prevouts": ["697b510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a86c1f0000000000165b142540f27e90740933c99d4f17ab2dfc6c82951cfb", "e3fe1c0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["ea4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93645dd27374e1e3840d53c2eddc23e77f3daecabe9190b2b544b03414f960ba3ee83976a7e8bc20bfa4c53f64ff2df47d867849c8cbf6df51014735817968d498535c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0df322cf06423056ff4efb147ba4330d28398a4f05a11ad98b1121aa54f60b594336f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}}, diff --git a/txscript/data/taproot-ref/8cac7b8d77d23a0085a03a673ee2021520fbabea b/txscript/data/taproot-ref/8cac7b8d77d23a0085a03a673ee2021520fbabea new file mode 100644 index 0000000000..7076d914a1 --- /dev/null +++ b/txscript/data/taproot-ref/8cac7b8d77d23a0085a03a673ee2021520fbabea @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e800000000a2a1cdefdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf5010000003ccba3d9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5100000000276aa1a901227028000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787240e3c58", "prevouts": ["3b470f0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "fb0b200000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "0b2527000000000022512067225551b50f550878fba08cb06856b99d76e57e98d7477f94810d7b1bff9dd2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694fe84cb69964c9ab88d8806a3dd882c1fd4c1e968ee9a10fe0c80ead4a8f7623f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082eee8539df42e1fa2e5e9e7b75fbe1b52db879ec8a622b496736c99966ce19d0038273d2ad306f831e931ee90238e60477c8ec11f350a3ad34ea06c6c58bf7ea3"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f8871c7955fe825167f5509f939eda783797f3f4df0f87146827f8d7c3a13ff899aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4006cb24f353cfca0d245645f6b16ad599c212098eee86bd01fc37c5c4a863127c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}}, diff --git a/txscript/data/taproot-ref/8cd544fbd46d49e76648955888fc3047bf5e24bc b/txscript/data/taproot-ref/8cd544fbd46d49e76648955888fc3047bf5e24bc new file mode 100644 index 0000000000..c1ef24e01e --- /dev/null +++ b/txscript/data/taproot-ref/8cd544fbd46d49e76648955888fc3047bf5e24bc @@ -0,0 +1 @@ +{"tx": "cc2e403e02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb10100000091ff68d6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb901000000bd8eaca701a18f31000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478795736527", "prevouts": ["94a2240000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "ca7d660000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100c24b55bc85bd2bab08c4322ef1e52e7bfddd9534fafdac4aef5da15d474d71fe0220638ecb567de22c82b81a9050d4e21e129e2db4630279c94c2190a38f9c614629e9", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["30440220747a718a2dc63b4a990a31528f8d1270c9d4998f7394690dd93f1a6fba831c5b02206eb3d4e574ff01ab9f5dc6636e455ced3b550ff0ad013abfbb92ed33fc32f378e9", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/8cde25f4590bc7a0cb88896228ad8d28ecb9641a b/txscript/data/taproot-ref/8cde25f4590bc7a0cb88896228ad8d28ecb9641a new file mode 100644 index 0000000000..f30ab708d5 --- /dev/null +++ b/txscript/data/taproot-ref/8cde25f4590bc7a0cb88896228ad8d28ecb9641a @@ -0,0 +1 @@ +{"tx": "5cfa37d7028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a301000000ee493d81dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7d010000000e4618c40212f89a0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcac3bac60", "prevouts": ["b6d9410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "dde95b0000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype1to0_keypath", "final": true, "success": {"scriptSig": "", "witness": ["1a69d4f798ccaaacaf5eb67f604efe840dbdc7338d1db7478929a0409f5c83ea57d0aa5b9fd2beaae3f02d842c70b395fde01bedc6348ba4d791041b52c16deb01"]}, "failure": {"scriptSig": "", "witness": ["1a69d4f798ccaaacaf5eb67f604efe840dbdc7338d1db7478929a0409f5c83ea57d0aa5b9fd2beaae3f02d842c70b395fde01bedc6348ba4d791041b52c16deb"]}}, diff --git a/txscript/data/taproot-ref/8cf7c389a03e6d9d8cdd4dc0ee8615f54cccd395 b/txscript/data/taproot-ref/8cf7c389a03e6d9d8cdd4dc0ee8615f54cccd395 new file mode 100644 index 0000000000..21deebc8fa --- /dev/null +++ b/txscript/data/taproot-ref/8cf7c389a03e6d9d8cdd4dc0ee8615f54cccd395 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b98010000007a51900704120721000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67b000000", "prevouts": ["50e823000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "473044022015cd3cdd20b2e149491ecf741cbc79454e753352c45992000426222868f84a240220703d90059025922e3f189c0edbd9f80345b8cc6bad80db8a62188a8e3839b734834104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "483045022100fab45dd95f3fc509a9089af109ee35f08fb20acae9b4aee952f13b95bfd42f9f0220104aa3321b0ddb40628d611465ddc16321eee078cb6b7e39a21a5d17c641b827834104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/8cfbcd30e59e458884ca65687215ef8a39fa420b b/txscript/data/taproot-ref/8cfbcd30e59e458884ca65687215ef8a39fa420b new file mode 100644 index 0000000000..cf8b514ba0 --- /dev/null +++ b/txscript/data/taproot-ref/8cfbcd30e59e458884ca65687215ef8a39fa420b @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6a010000003b24bf8adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2201000000fb57589c0357a6d200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcca000000", "prevouts": ["abbb75000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4", "64ed5e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c3df7ad94edd5dd8384ea059f961cc865730b5779c671ee2d6f7eddd0a74f8f7eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7acea811edfde1d836b623c2094badb4ab8bc7795b2b49da5506600222f32ea3fbd"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823d62cda1d889ee05ca59ece4e76d2fa27c0bab47b49d4f70b1e2cb0efe9a711fea811edfde1d836b623c2094badb4ab8bc7795b2b49da5506600222f32ea3fbd"]}}, diff --git a/txscript/data/taproot-ref/8d2e1d4e20c8a37b8483b0636a53106414b2e098 b/txscript/data/taproot-ref/8d2e1d4e20c8a37b8483b0636a53106414b2e098 new file mode 100644 index 0000000000..244df6fd67 --- /dev/null +++ b/txscript/data/taproot-ref/8d2e1d4e20c8a37b8483b0636a53106414b2e098 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfeb0000000068aa1af660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c0000000003ed329820294e97f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48725bbbd2a", "prevouts": ["f0006f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "da2e1300000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "c57d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363903e3bb34d25cf71b6983cf4f2b76fbc603b2adde28e34b23c45d7f67d4a2394a4f1964bf857a391dd30579e6c45654815fe99168eae3a652a179c44e1715327def1cc2232d9b1ca5244635fcf6779cb15e82fb856baa2ca11d8fd1da35295f"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e6d35158b06e93427cedf9700445f423da8a62a86b9572893cb3b0c5b8130f93e00378a892e4dc43a17c9ebd71803200f2f24c9a40c2827c304e59be9b4a7df0b"]}}, diff --git a/txscript/data/taproot-ref/8d84c17e2d2a5f1b483ec417d4084cff8a83bd8b b/txscript/data/taproot-ref/8d84c17e2d2a5f1b483ec417d4084cff8a83bd8b new file mode 100644 index 0000000000..b8873ae0c1 --- /dev/null +++ b/txscript/data/taproot-ref/8d84c17e2d2a5f1b483ec417d4084cff8a83bd8b @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be001000000a799f40abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4f010000001e21c462bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9a0000000077dd0fb3022989fd0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a611000000", "prevouts": ["025a1f00000000002251203d94c30f7ef8b0d9d4c7a773497c0af2bbd0a232f6e89c19e65bba66d7e2056b", "c0e969000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "f4dd760000000000225120ff67dbe5f480d52a3db68ddc8756a5701c353a5e478c53504b3368e48f095423"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936008088d7cf4bcfd919dc74e7ee4f6736dc4eccb5f6f5d741e30b3c7eda377cbb"]}, "failure": {"scriptSig": "", "witness": ["6a09616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8dad5eca9780e98722de60bdf4209e99730b7ce0 b/txscript/data/taproot-ref/8dad5eca9780e98722de60bdf4209e99730b7ce0 new file mode 100644 index 0000000000..0ea191f74c --- /dev/null +++ b/txscript/data/taproot-ref/8dad5eca9780e98722de60bdf4209e99730b7ce0 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1500000000e2737d19dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b03000000005a250c9e0284fb83000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71e000000", "prevouts": ["2d5f6600000000002352212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "6b0a200000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "c87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fafaf4d01509d00362d1685157096ce13f6e0df1edb9baa8d22d7c425316c78328c308d8e78b0cea59e70bbcac5990a047bb63a968328232757672e5e931dda055"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93610bd61aa5ca2d5bbe3b0fd477fc193f06add97123cde67a86227ce5080534856faf4d01509d00362d1685157096ce13f6e0df1edb9baa8d22d7c425316c78328c308d8e78b0cea59e70bbcac5990a047bb63a968328232757672e5e931dda055"]}}, diff --git a/txscript/data/taproot-ref/8db878b9f4d8758552ba375e70b1c319d8ca0248 b/txscript/data/taproot-ref/8db878b9f4d8758552ba375e70b1c319d8ca0248 new file mode 100644 index 0000000000..ec2675f9f2 --- /dev/null +++ b/txscript/data/taproot-ref/8db878b9f4d8758552ba375e70b1c319d8ca0248 @@ -0,0 +1 @@ +{"tx": "0100000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c30010000006ac7d40b042bcd4b0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47877c030000", "prevouts": ["b7da4d000000000017a914b60a534933f6e50f3846e396b9868efc9e681f4187"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["4182c373cf43d0dd9bf6414da623c57558ab25f87b66cb8aedf074334ca027beb6cd78beb6752e2cbb85dac453db9d5daa3f06470db784573f68e4d75e673e9c"]}}, diff --git a/txscript/data/taproot-ref/8dceab2924460f1a418835afa3ff5d4bde00914a b/txscript/data/taproot-ref/8dceab2924460f1a418835afa3ff5d4bde00914a new file mode 100644 index 0000000000..ca5615205e --- /dev/null +++ b/txscript/data/taproot-ref/8dceab2924460f1a418835afa3ff5d4bde00914a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdc0100000013b74e82dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3900000000fe9609b5020f333b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acd4a59f23", "prevouts": ["e1ae1e0000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f", "18ef1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4fd06ba2b74fab4c367f8e8e0519d3d9be3851343b71a963fa32cdfd438e05528a09ca0f6d73d82e88e284042e116dab9fe2cbfafc110f6c0fbe5b2788367c646ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b24d4fab40ea135233ddc8c9f724889f007818f7ffad5749db3376d8fcf405e18faf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}}, diff --git a/txscript/data/taproot-ref/8dd1413b2a30d480170c4918b00b9b7abe7ae2c6 b/txscript/data/taproot-ref/8dd1413b2a30d480170c4918b00b9b7abe7ae2c6 new file mode 100644 index 0000000000..1664d000d7 --- /dev/null +++ b/txscript/data/taproot-ref/8dd1413b2a30d480170c4918b00b9b7abe7ae2c6 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2d00000000e75314b28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c475000000008149b6b701e48d50000000000017a914719f78084af863e000acd618ba76df979722368987a331533c", "prevouts": ["713c4f00000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "6a1339000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4bb0b9e3baaec320f7de46eda77f4fdd2cda08039a1867e75a703bfdee0f4ff6d1cafc3da456d473afb79353f7068dc1822b24dbf9d7eaef6a0c8c9b611b05e979feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b6ddcef20c10c61d9e21e2293389fb4d83401974c63955ae345dea7dfe41530ea78a04935edfb84e1b4b71380d58e01ed379cbb21cec8f8440ec0fbfce597ab8cd941a6bc152cbea0496b075d4b2611b435301778200e60e8b4147cd93749673"]}}, diff --git a/txscript/data/taproot-ref/8de4d54ede6f78c61866173f8b1096d7f5e3f478 b/txscript/data/taproot-ref/8de4d54ede6f78c61866173f8b1096d7f5e3f478 new file mode 100644 index 0000000000..f7411e8169 --- /dev/null +++ b/txscript/data/taproot-ref/8de4d54ede6f78c61866173f8b1096d7f5e3f478 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706b000000004daee3458bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4810100000091e255d604661a4c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac4d000000", "prevouts": ["e2cf0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d3ed3e000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "dc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e96c63bd25ae92bbd16086cd18a0ced65254d43d2db01fd8c973d5ac979d0978d49cd47170ad660e437289f08833289e3b90e14293c0ba427f1ef2b5a93f8559a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e3bfe8b0458382ba4f4ce4b13b8b707c198a710172b0004e49e202e4d70abaa7b"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936754c3400f5b19129397404414e73e7234111a3665d4d5bc651a2a24db00d5dfa276acb01c569c39653cc9be144b4517abeee153b1e65c2a7dfaac73ffa4f7941ad29df8a0e62e4f40897f8996914b12118c918ca2851b639742aeab01f587290"]}}, diff --git a/txscript/data/taproot-ref/8e0a71d16611cdac906bb4dece9fbf87d1a0fc8b b/txscript/data/taproot-ref/8e0a71d16611cdac906bb4dece9fbf87d1a0fc8b new file mode 100644 index 0000000000..6a5fb05a25 --- /dev/null +++ b/txscript/data/taproot-ref/8e0a71d16611cdac906bb4dece9fbf87d1a0fc8b @@ -0,0 +1 @@ +{"tx": "a1212fcc028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f50000000035a475f48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c476000000007698abaf02c9fa77000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478702030000", "prevouts": ["bdc53c000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e", "d6083e00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93698751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d539caad535bb8d51429d9c94edd44271a241bcdcdcd941caf815b31d1e73ac1400dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4360d69898a7d9d7cfe47282f038ce081b7b00f0e720fcc7ce2a76c05a52019262a5aef24b6a1c01bacd2a24a37cefc04a347b590d10f3bd98469f969c355217b0dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}}, diff --git a/txscript/data/taproot-ref/8e1a1f4379046e33058d6b3df5184a181b98a2b5 b/txscript/data/taproot-ref/8e1a1f4379046e33058d6b3df5184a181b98a2b5 new file mode 100644 index 0000000000..f669a9ed14 --- /dev/null +++ b/txscript/data/taproot-ref/8e1a1f4379046e33058d6b3df5184a181b98a2b5 @@ -0,0 +1 @@ +{"tx": "1d7233850360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708c010000004c7f1e8bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf76000000001971cdc460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706001000000c78a86e4027ef68b0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f877bbf5d2b", "prevouts": ["4e1e0e0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "19636d0000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "a6081300000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["ed4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93655e252cfaa9768c1119fa64085e95b8d16b96942ccc526bc25f5651427cfe139d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c9b0690fa0521f4fddf88c65f69e0716898ebb5a52dcb1ee37dd2f34a8a99dbd71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fdb145940c290b3b086078f684e0e7b02072f4c479430733c205d9de9d8640bd3866c9dc2005c39fbfa40f99a1086b922c913a672fc19646edbf7ab3e480e00f86475c33b310e45b92339559838140b9b3f3d62b1cf111e129ddf9f566de62eb71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}}, diff --git a/txscript/data/taproot-ref/8e38afa0e7c920bbb4aec155f70d1940028204ee b/txscript/data/taproot-ref/8e38afa0e7c920bbb4aec155f70d1940028204ee new file mode 100644 index 0000000000..d70e10f953 --- /dev/null +++ b/txscript/data/taproot-ref/8e38afa0e7c920bbb4aec155f70d1940028204ee @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270250100000036c4ee558bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4510100000070e54af860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ac000000007953921f012baf0200000000001600149d38710eb90e420b159c7a9263994c88e6810bc727afb653", "prevouts": ["de1d1200000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "bbba3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "781d120000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["bb4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936023cf8e98f7450905a417c9ac38276f00b59951e06c79e90063ed7e2000f468fba5ae8cba4ed1cb91f8a2ddbe7d0c8637ea6f49c0896515a628c3bea1aa465996ff84cb0de1f41d907799f0bb3a3d4c37b57eea0ba754203aaf5b7b2671fe888a4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ef25451e1287905b17423f83e08d071b8f612240bd231ae948ab742b6a6315350430626a247d567d7470b6045f35bcd343227bea51bdb051c26a41fa3e304da7017bb5ae96064d7d19e957b5258c9c864deb4239d29676eb164d7ecbdb9fd5a354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}}, diff --git a/txscript/data/taproot-ref/8ea1e2b4445b668065a333641c17f3c6038f2f27 b/txscript/data/taproot-ref/8ea1e2b4445b668065a333641c17f3c6038f2f27 new file mode 100644 index 0000000000..3df01eb11b --- /dev/null +++ b/txscript/data/taproot-ref/8ea1e2b4445b668065a333641c17f3c6038f2f27 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43d010000008a18adb58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4000000000016efe5ec02e2766c000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac05000000", "prevouts": ["47b438000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "3dcc36000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063be68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4b388de3dfefb2132719c310aa79074581b330ff4b72041fe2a3e03933132949f61eb6e6fd21ad84d93c7a0474b2daf5b011002cbe34781a2a14a95ac7c4e00ae344cebdb8ecd56ef01fad0911d9d88482970ec36d3a04b84eda7f5b5c68ec938"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362358e12ac09d2a6885dfcf9eb233087f34097060d523dcf896ae6036206d510973668dc71689fe0651b36a481e24aaad53f2818649afcdf831b4092eda1b840fd3726db1c97dedfc82502578948b1d779eb886e6296c36bf50b8d2fe25c32b8a344cebdb8ecd56ef01fad0911d9d88482970ec36d3a04b84eda7f5b5c68ec938"]}}, diff --git a/txscript/data/taproot-ref/8eb143cfc057b1ffa8e90069a1d1ff91a90ac794 b/txscript/data/taproot-ref/8eb143cfc057b1ffa8e90069a1d1ff91a90ac794 new file mode 100644 index 0000000000..60e7c96fa2 --- /dev/null +++ b/txscript/data/taproot-ref/8eb143cfc057b1ffa8e90069a1d1ff91a90ac794 @@ -0,0 +1 @@ +{"tx": "1a7ddf0002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1600000000f71b52aabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbb00000000a38578fe04d6958f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fccc000000", "prevouts": ["8900200000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "aa79720000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "de", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f9ea8f2e65eb73025cf4611eb81b9bc973c238c936328a8046b3068be11236b1823ff0d5c6a769fa09e08a59a2485b611e1511239bba2f80aba2b92be945f1b811034f174cb7bd77652d345f06878a8d4eb3ae1b92590cd10e2563bf228d2d6bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb423dda11617dc042479e1d576056805c31872018ddbd603e5e1ceb926e90a3395bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}}, diff --git a/txscript/data/taproot-ref/8ebc6173196e2c3ad4ea6d665b4893fd67690d70 b/txscript/data/taproot-ref/8ebc6173196e2c3ad4ea6d665b4893fd67690d70 new file mode 100644 index 0000000000..aeefa32bf0 --- /dev/null +++ b/txscript/data/taproot-ref/8ebc6173196e2c3ad4ea6d665b4893fd67690d70 @@ -0,0 +1 @@ +{"tx": "c924110102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff1010000009d574b958bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46900000000c2a4e1b8022e86a90000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a621a7f84a", "prevouts": ["fc546d0000000000165d142540f27e90740933c99d4f17ab2dfc6c82951cfb", "a0373e000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["56c614673f4398579993d3f4aaf119ab2881e992735707c31e57e1b6ba410e5c388597bf331c1ce9348b07097e077feff8c24a499b9048a615ad9d4426845dfc"]}}, diff --git a/txscript/data/taproot-ref/8ee6b6a7957bf8ed03aa4b95dbc232e5ba56ead5 b/txscript/data/taproot-ref/8ee6b6a7957bf8ed03aa4b95dbc232e5ba56ead5 new file mode 100644 index 0000000000..2860220070 --- /dev/null +++ b/txscript/data/taproot-ref/8ee6b6a7957bf8ed03aa4b95dbc232e5ba56ead5 @@ -0,0 +1 @@ +{"tx": "7a4c3a2f028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43e00000000402394cabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf43000000006307458b036973a8000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374874c040000", "prevouts": ["887434000000000022512003ab4180fdf64546247c5e9f6e4b9eec37b1d29fb6f370a343f066de5418d90b", "20ad75000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["974c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93626364c264ca1a1a3113427e98f88e51ff7da2e89277d01d72659b15bd38bb6d4bbdd0eb743f16fddaffdc87a703f35bd0417e0996b155e435c0add546ea723b55a7303e26d6b86d2a780c30dbeb7ba87c6a0494b901c3875fb9ca7f2f12bb2fd373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}, "failure": {"scriptSig": "", "witness": ["4c5297", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f96b744a52162d67d7aee619d433d93e0f112e198bfa8f90bd1cd431f60087e13288455e3867d2ff7594cc417650f42f79f93c98aaa5c5ef25eb3554c8bf2ec6282285524a15c732567d099967405d35f7136f74f48f011bc4ab279ad8d14f14"]}}, diff --git a/txscript/data/taproot-ref/8ef96afc00349b4248ec31f4755d1020b7fdda03 b/txscript/data/taproot-ref/8ef96afc00349b4248ec31f4755d1020b7fdda03 new file mode 100644 index 0000000000..98ffc58700 --- /dev/null +++ b/txscript/data/taproot-ref/8ef96afc00349b4248ec31f4755d1020b7fdda03 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f02000000edc4c2a1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7d00000000b6e37ef8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b970000000032ac10e903965dd000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c020353f", "prevouts": ["db0b40000000000017a9147e06846ce22cd5e23f7e03391c0538498e0e18ed87", "234c6c00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "693f260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "de7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367d67b48ae102939b394e240fe50b972a2db09c5d140b2e0ff38ab31a95ec777f3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08267bf5ee6e785c98394c7354db9cd2cb879e9766d4c80c1499d7b3e856282bd13a05e4a06b32de803bd9a925f4d86502b21cf2d106a73f15ada31e997750cbc80"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b4419e0140799871ba1426129d6a886ea24b454e319298d6cbfcc8b7ce92d14093a387cbf4f722495a20cca4e5071672ad9cff48cf2966de7657b6ee347f57da05e4a06b32de803bd9a925f4d86502b21cf2d106a73f15ada31e997750cbc80"]}}, diff --git a/txscript/data/taproot-ref/8f07475a5f9d43a948b3b96452aea50918e4b9b7 b/txscript/data/taproot-ref/8f07475a5f9d43a948b3b96452aea50918e4b9b7 new file mode 100644 index 0000000000..aac4f275b7 --- /dev/null +++ b/txscript/data/taproot-ref/8f07475a5f9d43a948b3b96452aea50918e4b9b7 @@ -0,0 +1 @@ +{"tx": "b50f094902bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3f00000000c673fec7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb80000000046642ba302baa7c5000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acba7f4b39", "prevouts": ["15be6f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b7ea580000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e9", "final": true, "success": {"scriptSig": "", "witness": ["852ce8c162dca0ea890fc9fec348fa03e54a13028c16172ebb382603917641b41788499ee10e8c9f8c6852fb4271d9d35198440ee8c07b034569a912a2def30102"]}, "failure": {"scriptSig": "", "witness": ["abda8561fb4486cac1e1ec3462430fa73446dca4a2307887ebcf4fe1ed2f2c1916e84b4595655eb805e80df9b3b73dc86851cac3fabd958c0081ea03ac51b943e9"]}}, diff --git a/txscript/data/taproot-ref/8f0862b153c849b8d035fa189f7ec654f8b3e862 b/txscript/data/taproot-ref/8f0862b153c849b8d035fa189f7ec654f8b3e862 new file mode 100644 index 0000000000..0cebb522a9 --- /dev/null +++ b/txscript/data/taproot-ref/8f0862b153c849b8d035fa189f7ec654f8b3e862 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c750000000034d93ff2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb10000000088399385027739dc0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac02010000", "prevouts": ["d9be5a0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a", "22ee83000000000017a914c7d65cb5025eac8b5bf295baac9287994ab34b9b87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c568", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f0a6523615754b4aa54ab7599e81d37a390fe5e9971e25848ea770d0aa595f2c3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826c8f4b27179de8a3c9fbcc0ecf825a44b7564122e0508108d3381c6acb047da700a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb47ad860089e7bc2a902df7d26b00c72c3270dfe98d44c73f0cc876602eea860a2660eca3fa0edb42c0ab30ffe3daaf6f1f409e953104f48559c2b804c71af6a81ce4d7767c8a9637a0804b073b1eb172c67de67ce152ade33f2591a85dfee2e5a"]}}, diff --git a/txscript/data/taproot-ref/8f0aa9d861c14d5c32d60092ba04c2253666c4c5 b/txscript/data/taproot-ref/8f0aa9d861c14d5c32d60092ba04c2253666c4c5 new file mode 100644 index 0000000000..9920489e8f --- /dev/null +++ b/txscript/data/taproot-ref/8f0aa9d861c14d5c32d60092ba04c2253666c4c5 @@ -0,0 +1 @@ +{"tx": "d7f96b1903dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca701000000c90fb0fadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0602000000fe78deebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b92000000002e15949302b1769a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1a020000", "prevouts": ["3eea5800000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "d5e41f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "688424000000000017a91495eb8fe3d959e08a2cc279c1b4ede1921d14a93b87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2257202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["4020147d8321202672cb3638e9c82713747ef93d8af087d578629c0f65dae5616b8a0993ba3ee86e8e20e32b1d471c10be28c391d7d67f05bf44acb12bb214c1", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/8f4ba01ca74a466747b89a116a26047e58536ef9 b/txscript/data/taproot-ref/8f4ba01ca74a466747b89a116a26047e58536ef9 new file mode 100644 index 0000000000..d95adc9d09 --- /dev/null +++ b/txscript/data/taproot-ref/8f4ba01ca74a466747b89a116a26047e58536ef9 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cee00000000168bbd8bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5e010000006458ed8f0459b6b50000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a607030000", "prevouts": ["7ea84f00000000001658142540f27e90740933c99d4f17ab2dfc6c82951cfb", "3dc468000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["11b78558c296e038f53e1518c4e81c6eceb9ddd85c9f10faa08f9aa192446b2615dde6ff920d86ef09b7dad738c2cdab602d5cedfddfa1deac7365c5e8e1275f"]}}, diff --git a/txscript/data/taproot-ref/8f56d7ddb9c736b9c89113453c379ec0a21341f9 b/txscript/data/taproot-ref/8f56d7ddb9c736b9c89113453c379ec0a21341f9 new file mode 100644 index 0000000000..dd02866cec --- /dev/null +++ b/txscript/data/taproot-ref/8f56d7ddb9c736b9c89113453c379ec0a21341f9 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc400000000722b13ffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1101000000ea73819702fc8940000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f872fbbd44a", "prevouts": ["04a720000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "b70022000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "797d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93644f5e531b2d1fc6d65a483d63fdb8b5e6dc0a2ebdcfef74cb54fbc1e51fef52fccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f45727aec9530f4cf05d3554e63105b96634da39f3c52c35c251ce860693e97320b3"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93681a3012a8ca754d1d79ae7fb9e13063abcccb354ed9b617596389eb42efb17e66301af72c0f0fcbfc62431a82320b93fda30ebabe1c669499e3cf52b4dc2b40fe711fb6ebac21c15598dc6feca0613664d86278cc532834585097123290bb3d45be39dc57762be2d9b1a04aa5b570805d23104bfe4fa54c392bda5d51f7f4540"]}}, diff --git a/txscript/data/taproot-ref/8f7ed4f89eb5a042d9a19a78e61c47e5c984a9fa b/txscript/data/taproot-ref/8f7ed4f89eb5a042d9a19a78e61c47e5c984a9fa new file mode 100644 index 0000000000..cdcd0b6d7c --- /dev/null +++ b/txscript/data/taproot-ref/8f7ed4f89eb5a042d9a19a78e61c47e5c984a9fa @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708401000000a79891d28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46901000000540de0f504bd1452000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ace8010000", "prevouts": ["1a9a120000000000225120fc75765be35c7498e91185d3d44c5b81ace48e1fb56783e170e4fddd4a850715", "8ec7410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d5", "final": true, "success": {"scriptSig": "", "witness": ["cd014610cbd7f458a02c10d7176e0f4551e37025b8c16bd0eaedf84a76dd2e31f203181c9a051184edce67f74c60877c3c0d60e30b53d4381fcddd5a9feba38781"]}, "failure": {"scriptSig": "", "witness": ["4628dde71dcd903a954776027f1cefb0dbdfe0935a7d25f49dc6e87d05c32a3403fbccf57b98e50c9847aa0245450bc0e9b200b437039fc699c29e89706117d2d5"]}}, diff --git a/txscript/data/taproot-ref/8f94c8c6a37bcc91d7a39416023f9d78ff08129a b/txscript/data/taproot-ref/8f94c8c6a37bcc91d7a39416023f9d78ff08129a new file mode 100644 index 0000000000..fdd901a404 --- /dev/null +++ b/txscript/data/taproot-ref/8f94c8c6a37bcc91d7a39416023f9d78ff08129a @@ -0,0 +1 @@ +{"tx": "d950a147028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4710100000088ae7b8cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd2000000002feaa9920273d1630000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75c917233", "prevouts": ["201d410000000000225120682cff718d7cbe051bd5beaa1ff36d3547b88d6d4bf403f10c1645a08d942ef8", "4ae5240000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f7adfbd1b335a199d22a67c621fd1ccdebcdebb8f2e40814f300cc202bc5ea67"]}, "failure": {"scriptSig": "", "witness": ["6a61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/8fc0dcb82f3f88e6c20e123adddbce9afa79dd7e b/txscript/data/taproot-ref/8fc0dcb82f3f88e6c20e123adddbce9afa79dd7e new file mode 100644 index 0000000000..967534bbfb --- /dev/null +++ b/txscript/data/taproot-ref/8fc0dcb82f3f88e6c20e123adddbce9afa79dd7e @@ -0,0 +1 @@ +{"tx": "8b21c5e6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c432010000009e90c1d88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44d000000000d1ee0b404151f6e000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac44010000", "prevouts": ["bb693e0000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb", "20ab3100000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["64494e39aa5da0bca64e8c163b9e9fe1f66a9f918081932cdbf8daee4107ff59740de9a96444781e8924afea1310454612b128548f818066128aea1dd0e4c6ff00", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/901261518c53841cdeb55041f748183f25fbdb6f b/txscript/data/taproot-ref/901261518c53841cdeb55041f748183f25fbdb6f new file mode 100644 index 0000000000..0e9b26c5f3 --- /dev/null +++ b/txscript/data/taproot-ref/901261518c53841cdeb55041f748183f25fbdb6f @@ -0,0 +1 @@ +{"tx": "b8c2a6fe01dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b470000000048cd72800462b822000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758837320", "prevouts": ["b68e2500000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["bb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bfcd38c1da080d9fa5f350ac5c5d82a433c6ad7048f1837ebebe4defa9773a5a1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454c3d251f378473e49463283b18fa00944324abf75c7e60d6956acdb0e7ed03a7354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936597c2f6b8dc6d15eebfc9ce9773556a5675730a3f06ef70be75161d60adb64d2d0e13bd92b8f417e9a9e83db8f63381783cc5b261abc3d56b5d515d800102f0ba4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}}, diff --git a/txscript/data/taproot-ref/9014cd1a175ea66532264c818ac4692ed805357f b/txscript/data/taproot-ref/9014cd1a175ea66532264c818ac4692ed805357f new file mode 100644 index 0000000000..d58d4a08d6 --- /dev/null +++ b/txscript/data/taproot-ref/9014cd1a175ea66532264c818ac4692ed805357f @@ -0,0 +1 @@ +{"tx": "46adb1710260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709c01000000b5ef5db360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127053010000000d2fecdc02d72f21000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac59010000", "prevouts": ["9044120000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc", "d535110000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e94c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ac778bb6e9889cb94937fc77a861bf4edb1757bb7369dd12c591a6cfed1c6a5fcbd8218c9dac71a3535cf40d08210778548ef11a7c40c018c5ea1885d9980740ce9ba0618adb3ee44483a22999a54a4e1710b9846377d8164aaa29371d79f22a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}, "failure": {"scriptSig": "", "witness": ["4c52e9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045ead6d3e810571e3af6462e6592387cebd820372bb489ff10eea7a83e6cd68e83cf301e2cd98ef2d5c028e1b110cc6503fb01279ff4eb452c3408c39d22674b4dfc7f9c78871d6a598c7c7c3f4c8210a5c47caa8abf9700608b6e75845c74a6c5"]}}, diff --git a/txscript/data/taproot-ref/902fc67f6a0dd7c17809ac0002972da218f32b8c b/txscript/data/taproot-ref/902fc67f6a0dd7c17809ac0002972da218f32b8c new file mode 100644 index 0000000000..41381e5c9b --- /dev/null +++ b/txscript/data/taproot-ref/902fc67f6a0dd7c17809ac0002972da218f32b8c @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b090200000035a3cbd1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7b00000000bba5cbc704e85a47000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796f3703632", "prevouts": ["490f2800000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "e0772100000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "537d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365679c4b80b1f02a904f6a1e97bc1e5029a390245cd2e5f4f1bb6526c613587c3c1fcc94e870ec95c088fd37f5daf805336fc0aa07ac91d9d5a0c770a5a47ed76aee97a7dfb8acbc78fdce4694f8ba1e1e3bf612a81f34559c93e6dfd336d600fd892d02e0db2d70aca72db86bdb1e35d04291625c81ec0b3d884b10be9f787fb"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a54256964294f7e46fe5d25ab3411c34d3792ff29ea326544b7c68695f53859e150f8c7b4812d3362c6afa34922f3b5cc4b63cc9e98285537a088f4a7fe3bee"]}}, diff --git a/txscript/data/taproot-ref/90439abb1bce7df95926ac69fbe35e9a75849704 b/txscript/data/taproot-ref/90439abb1bce7df95926ac69fbe35e9a75849704 new file mode 100644 index 0000000000..b5104d1802 --- /dev/null +++ b/txscript/data/taproot-ref/90439abb1bce7df95926ac69fbe35e9a75849704 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c09010000008fbe4ad0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7f01000000637407e402af757c000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6af040000", "prevouts": ["41885b0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "e76b2300000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c40fbd6c2414aad6fe6ba729f95c47f497dc6a4d2aac2f66dd85c70e3b597d70a112aec6b4b8b5b1ca7f36a9e0521bdf2c7802df3cadcb1e8aa67d830b4a0d3fd33ab5c29645e0220ea4ffd8cb7e67404885cb8b0cf94872336c7b06d59c3124"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ad3d30479f0689dbdf59a6b840d60ad485b2effbed1825a75ce19a44e460e0999aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4a89eab7efa8b8df17a82e815a072b99e340ac1768e499ee92fb25d88959474e250636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}}, diff --git a/txscript/data/taproot-ref/906de10a0641d6cd4c0dd422fe885c2f9691128a b/txscript/data/taproot-ref/906de10a0641d6cd4c0dd422fe885c2f9691128a new file mode 100644 index 0000000000..b8bf0b6d09 --- /dev/null +++ b/txscript/data/taproot-ref/906de10a0641d6cd4c0dd422fe885c2f9691128a @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703a0100000094624dca8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ba000000007ee534a402fc76420000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac6f5cb72e", "prevouts": ["1ba20e000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a", "c868360000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "247d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a5787881982eabc9f10a574183ce87b535a8253f66971d7d0c58826076cb527312b5d836754160f4cb099c4d8b267e29847dad01b12a09dec3875f376ae126ea3506420e788c3ffd3d8d88ddb9154e82106737a8dd2b5d0940daf68f275cd0d7"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb9b18a780ce64b599d9d3042fe9b5b93046b018637f9f8cec8ef00735e099ba32f1db23017f271ba09e9de40cbf6bd4b292cb969b1168724d03b4425efd5cf153506420e788c3ffd3d8d88ddb9154e82106737a8dd2b5d0940daf68f275cd0d7"]}}, diff --git a/txscript/data/taproot-ref/9076f59736d1a417df0e4e53465ba7f80da49859 b/txscript/data/taproot-ref/9076f59736d1a417df0e4e53465ba7f80da49859 new file mode 100644 index 0000000000..3f96220d31 --- /dev/null +++ b/txscript/data/taproot-ref/9076f59736d1a417df0e4e53465ba7f80da49859 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702b01000000563eb1acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfe0100000075a2baca015d162200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca7030000", "prevouts": ["503d1300000000001660142540f27e90740933c99d4f17ab2dfc6c82951cfb", "112b4d00000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["7f4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b6d9476ecc09d849d3c16682d4a6fd2c22d5514554f5544b52408747bbaff174e17cc42fca95eeef15c2a149426edd48c8eb93e73982ab4fa8378007bf5ef888ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}, "failure": {"scriptSig": "", "witness": ["4c527f", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361279a387fb722f4f14f9a7780c31f5e75533d5e2ffb38299b6ef0e006f47591370f73741da43ca43557c58f6aa15023f4cf70566ac935702465d6fb0f93d4429f8d5397512e216c7ab52609f0ab27ccbbfd2b7e561d7599ada55e292956af911ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}}, diff --git a/txscript/data/taproot-ref/909f04b9af20cf2cb275ec1cf722f9a40b234fdf b/txscript/data/taproot-ref/909f04b9af20cf2cb275ec1cf722f9a40b234fdf new file mode 100644 index 0000000000..45802fa046 --- /dev/null +++ b/txscript/data/taproot-ref/909f04b9af20cf2cb275ec1cf722f9a40b234fdf @@ -0,0 +1 @@ +{"tx": "92ddf3650260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708c0000000087e1aecfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdc0000000073684b970280a936000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acf0000000", "prevouts": ["8995100000000000225120264b35643a3a3a95953dacde7cb6bcfadafc46c4f235409840aae4392ea87839", "9d4d280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_fb", "final": true, "success": {"scriptSig": "", "witness": ["93aa89b646b2bd1010a2742dcd1f6e7794f4d56d1902013caedc8745ed9892d89368216724385c6a8369cce97298829a9572e94f23dc1651205a49c485459c8a01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["2ab97fba5fd71c40d7e71a0c7981cee5c56b17c61858fd7ffb6d3bb435d4784847061cb8a5d9cf2c41b9a98685349df8e1cf47aeb4faffb01570abe48f54e075fb", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/90b75e22907115340a987929a776f6f3bea1d9b5 b/txscript/data/taproot-ref/90b75e22907115340a987929a776f6f3bea1d9b5 new file mode 100644 index 0000000000..b3cbc4d030 --- /dev/null +++ b/txscript/data/taproot-ref/90b75e22907115340a987929a776f6f3bea1d9b5 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2001000000681b64db04e2ee2200000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72e030000", "prevouts": ["e46125000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ba7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a0ef97ab7ee9fc1eac24be41bfdadcbb7c9625a4e882ca5abbd81147d09c0527a47630aaed9dd66550bfcb0f3b3ec2bd830a8a42bcee9dbdef471b4e5cf2e89f5668d978bcc8d3ac0b8aded42d2a4a1c5e69a5396581e310868cb48ff813edbf"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93654dfb6f6b9a2b04f4592afe6e08b27d0dfb1567237811ea996f2ccf3ff1cd1054a7888d88a49f036a686b85959429d2c21b5cc7c31f53deb0eff848be794e4af5668d978bcc8d3ac0b8aded42d2a4a1c5e69a5396581e310868cb48ff813edbf"]}}, diff --git a/txscript/data/taproot-ref/90cddd59c8cf3bcac6b2fb6df29c9362c3a69855 b/txscript/data/taproot-ref/90cddd59c8cf3bcac6b2fb6df29c9362c3a69855 new file mode 100644 index 0000000000..936af9641c --- /dev/null +++ b/txscript/data/taproot-ref/90cddd59c8cf3bcac6b2fb6df29c9362c3a69855 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a00000000b81b6fb28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4440000000042523524047aca7f000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374872584c954", "prevouts": ["2c8f4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cc64350000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "137d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820ac5ef61da5659d8214c667aee1dbe4febf87286965cb6fe696f5c1a17be3da5155f23cd39ff67d8b5a6775be7b28a3d1b06bcb926a8f69937c20b78b14c2d485d0346f0de7f7080f7758bd86c81c482f81ad0c7703311f4b65ab9d7b77c9f00"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fabd41cd46598692ca564feb702471a27c2b329b731a2dc6dbcecd3c4d6afe3efd7c43b740c0608ac721897ca7a4b0bbd2ef7e62418d1fc20274bd386c7c0d4d7e"]}}, diff --git a/txscript/data/taproot-ref/90e012902ea03831fe652fb98c2f284c57217115 b/txscript/data/taproot-ref/90e012902ea03831fe652fb98c2f284c57217115 new file mode 100644 index 0000000000..c8ed4d98bb --- /dev/null +++ b/txscript/data/taproot-ref/90e012902ea03831fe652fb98c2f284c57217115 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0e02000000dfbf3a19bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa10100000034a2a0af02fe7ad10000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487dac0f83c", "prevouts": ["fef26900000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "568269000000000022512030fd389dfc6b7dc5f4caf58ddf04b54dbb338c7b69e334c29cccf1a655d02655"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663380db981ab01c8cfc2b73d24e17b0f36e1c245c11385e230b04af30b6c7e74"]}, "failure": {"scriptSig": "", "witness": ["6a1b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/910480b0cfba5cfd886687f687f8a73d081c0b15 b/txscript/data/taproot-ref/910480b0cfba5cfd886687f687f8a73d081c0b15 new file mode 100644 index 0000000000..a5c146ec7c --- /dev/null +++ b/txscript/data/taproot-ref/910480b0cfba5cfd886687f687f8a73d081c0b15 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0102000000461e5b9c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a5000000003a7310c4024533a8000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487eabc5253", "prevouts": ["a46675000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "4386340000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_0", "final": true, "success": {"scriptSig": "", "witness": ["9303ce586d3f3b9a63015f43a435770e5ff8303edd9c923b06ec079cede831c821d292b735a33f7b710e370cbc2f72495737104b083da863c1d97e86f18fb169", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["df6f99acba42349bdd2e021c65a8ab6f7ba49d65c3e4be2e0e716036dc379e7a2023ee4cd29576f7b351343e9c3363a282fa46f5c44c4cae1108329113f94b70", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/9143eec00e7c0dcba52a44c54c7fea4ca90ac9db b/txscript/data/taproot-ref/9143eec00e7c0dcba52a44c54c7fea4ca90ac9db new file mode 100644 index 0000000000..7f8a172184 --- /dev/null +++ b/txscript/data/taproot-ref/9143eec00e7c0dcba52a44c54c7fea4ca90ac9db @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a4010000001d6355fcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2a00000000547be58f03d0fb9600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1baad02a", "prevouts": ["dd48400000000000225120cc4d42e69b853b2a0a5827098521167109822d5a10f2066982dd9b410753f660", "8391580000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aab4ceb46e8915e34a175c818206b2f8c71eadd166d81881d5d09dfa18400c85"]}, "failure": {"scriptSig": "", "witness": ["6a24616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/914d626c074a269b3a9d1451d77761c9b6e8db28 b/txscript/data/taproot-ref/914d626c074a269b3a9d1451d77761c9b6e8db28 new file mode 100644 index 0000000000..cf38f17a8e --- /dev/null +++ b/txscript/data/taproot-ref/914d626c074a269b3a9d1451d77761c9b6e8db28 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cca01000000beed76a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfa01000000006e98b98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b701000000b215db96035f51d900000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7f08c9e1f", "prevouts": ["f6c5510000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "2aaa4900000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "ab2940000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["fa4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6765b3a9293f3bfd6c3b684051ad5b8ba6e731c254b25e3cb8e354d60cbb2971a4e7a29e9a68a1d6e5ccf500c3bde1b862f2704e441e939992f2bf5a528056a3bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367c6933323ad2fa3948334e88be7f42bd024e40c953b9156393334b52718986a762b588f53b8753752456cb241f753d144ff0679dfcac60637407bf69aac4dc17f8b8afd7beb88d43ca6c6d2d58dc9425172bd95ccf582b2eeeba83616a9d27d33bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}}, diff --git a/txscript/data/taproot-ref/91b3598a2ceedd0e45722fd9287672a13bf221e1 b/txscript/data/taproot-ref/91b3598a2ceedd0e45722fd9287672a13bf221e1 new file mode 100644 index 0000000000..58f312b188 --- /dev/null +++ b/txscript/data/taproot-ref/91b3598a2ceedd0e45722fd9287672a13bf221e1 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6f010000002411c5ba8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cc01000000e72a29ce0200e059000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966a000000", "prevouts": ["699f250000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f", "36ae360000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d7", "final": true, "success": {"scriptSig": "", "witness": ["3ad20fc73a72f0f30c43fd5739e28f93c47d9d9a5111c7667c56a166563a16ba12a9b528b0d7b90ffb72cacfce34bf6b9696dfc9c508792c972faa29d6ca5e8582"]}, "failure": {"scriptSig": "", "witness": ["fe228f450b45239e48687e39a77d68b1bb9e36fbbff2b47425d8556a1374b55a54b4c459cc808cf415c4824044b752ee2f65dd71deb8829c324f3085ef7f03cbd7"]}}, diff --git a/txscript/data/taproot-ref/91deadec3dc6c425ddc903b195066184526341bb b/txscript/data/taproot-ref/91deadec3dc6c425ddc903b195066184526341bb new file mode 100644 index 0000000000..41d7d754cf --- /dev/null +++ b/txscript/data/taproot-ref/91deadec3dc6c425ddc903b195066184526341bb @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127011010000009512ffec60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dc000000001b1f74a901fa2f0300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac929f8435", "prevouts": ["9a331000000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5", "e0c2100000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["ee4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ba746a1e3af4c529d3cdba1b4e6cf9b58f2b1e1d981455be45b81cc2f039993b0f3b0db014ceaa26ae02ffb8f31853eb721e6357de034fb71f3898341a9ea5240028cdc19f89baf6c362287c7c7841c4536091540a9bd978c440258b5fe7844c439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d519b8dfaa69151d05ccddc10c8c1e468eb7b78f9ad17f99ee1b916fd61bdfbcfce40899fd8696dac9e3afc960f0a100b615a3c324ed3a125e98af98336f748ba56"]}}, diff --git a/txscript/data/taproot-ref/91eb11de4a9b1c364da7e342da879d0915930da6 b/txscript/data/taproot-ref/91eb11de4a9b1c364da7e342da879d0915930da6 new file mode 100644 index 0000000000..aba7fc77d9 --- /dev/null +++ b/txscript/data/taproot-ref/91eb11de4a9b1c364da7e342da879d0915930da6 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701c0000000093e5369f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270700100000013a28ec804895c2000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787270abf5f", "prevouts": ["4552100000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "3d1c1200000000002251203e1b6fae524f56ebd8e25d4d2010b2e478325da2c77049f1de4edb81deddfc75"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_cs", "final": true, "success": {"scriptSig": "", "witness": ["e3c59f8247ce8aa4799c2ca4717b16ffaa80f6c89cf4202246034ba419606982c92a52db48d81748ec0d8f52054c1b0e07bda560b56782996d2b40afe7360328", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}, "failure": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}}, diff --git a/txscript/data/taproot-ref/91ed8c8f6952e9dfd27a3d45454432bd4886c8d1 b/txscript/data/taproot-ref/91ed8c8f6952e9dfd27a3d45454432bd4886c8d1 new file mode 100644 index 0000000000..3f2f6c7f6a --- /dev/null +++ b/txscript/data/taproot-ref/91ed8c8f6952e9dfd27a3d45454432bd4886c8d1 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43d010000008a18adb58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4000000000016efe5ec02e2766c000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac05000000", "prevouts": ["47b438000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "3dcc36000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_81", "final": true, "success": {"scriptSig": "", "witness": ["771bc9c7f412418640737a6c0afed578a4b8c78dcddc73a90d10e6acb2eb12a6fe8a32012fd9aeda27adccbe1eb3e7f0dab702af25480ae5f95598e333ce30c981", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["1751957682848ab9a393ac27fa1018f9eee8546277f50b728134f598b87e5618f34203be06222a0a52b70555f65339646b1983b20babba4eb14dbf0b1ac7df5a81", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/91f11c0a3851e5a1b473cfd412ff28fcd7903c39 b/txscript/data/taproot-ref/91f11c0a3851e5a1b473cfd412ff28fcd7903c39 new file mode 100644 index 0000000000..af7878a940 --- /dev/null +++ b/txscript/data/taproot-ref/91f11c0a3851e5a1b473cfd412ff28fcd7903c39 @@ -0,0 +1 @@ +{"tx": "98b7339702dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6701000000ce4b1aba60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d400000000185f3c8b02ea2a5d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48721010000", "prevouts": ["58bb4c00000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7", "60a5120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "f47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e760cc2203422c55a835172c125a7e245d244f5477158f1701a7cdf5578cf79bddefbee90a18838bf61213a4f1f5f31a75e180b842cfb60d5f81d26cbd38f8652876f4540117e7e2fda63f7a015ec774d613b8932caa4388fa9ce7145d42cc7f6"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936391b5ed75d7758930f62a8b38c606eddd0f0b98832e7378176311548388961dd44a76e856afdfa077951e950d1b00a9b743b1044161111d30eb56bfa7ddab902890bfc944cea42013591059ba9f4ec0a95c62699d2133b38017223ef90bcb8e42b4a87a36ff2ed7228bcfc2438815b30cc1c98339504e1b834e10aaf4a034051"]}}, diff --git a/txscript/data/taproot-ref/91f5456cb58ea9371b0fc9864e05767c7a8ee7e4 b/txscript/data/taproot-ref/91f5456cb58ea9371b0fc9864e05767c7a8ee7e4 new file mode 100644 index 0000000000..45fde9e672 --- /dev/null +++ b/txscript/data/taproot-ref/91f5456cb58ea9371b0fc9864e05767c7a8ee7e4 @@ -0,0 +1 @@ +{"tx": "997c8d6803dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb000000000b13b4e848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fc010000003b13f7f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf4010000001bbc0c8c04cff9dc00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870cba8322", "prevouts": ["4d2151000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec", "2a41350000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "170c590000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "bd7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082956f78f875a4cff3dc955be6c960f7b458e90648c2291f520c96d2b85cf15d2941cfbdca9cced9a9297ecbc29dffc929789a1848311039b5a24b338cddf0aa70"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641dd31aa852e6f71aedc584ccf1bdf704b326c74e68fda16d455fddcb9868622956f78f875a4cff3dc955be6c960f7b458e90648c2291f520c96d2b85cf15d2941cfbdca9cced9a9297ecbc29dffc929789a1848311039b5a24b338cddf0aa70"]}}, diff --git a/txscript/data/taproot-ref/921d11cbd9a6ba01c1bbfcc40c1205f6ef275acb b/txscript/data/taproot-ref/921d11cbd9a6ba01c1bbfcc40c1205f6ef275acb new file mode 100644 index 0000000000..0b27ac89f2 --- /dev/null +++ b/txscript/data/taproot-ref/921d11cbd9a6ba01c1bbfcc40c1205f6ef275acb @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c60000000077e8b85d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e6000000009e49a865016e35600000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb9000000", "prevouts": ["2580370000000000235e212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "0ca03a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["b3790a49c3a8fac6cbb4a7a2da0753a5d801f15728935ae6d5fcba46453fcc4ad01f70cbb990e1a8ad773906c5f6548e1f1204cebeb378f9a06402f44c770412", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/9238fc472251c9a3c817ab6cc5ea4e97c3d05410 b/txscript/data/taproot-ref/9238fc472251c9a3c817ab6cc5ea4e97c3d05410 new file mode 100644 index 0000000000..9e3b865bd1 --- /dev/null +++ b/txscript/data/taproot-ref/9238fc472251c9a3c817ab6cc5ea4e97c3d05410 @@ -0,0 +1 @@ +{"tx": "2aa979a101dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0702000000473615e8043c2958000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e701000000", "prevouts": ["18555a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_22", "final": true, "success": {"scriptSig": "", "witness": ["3b4215d1fe4d81d1f7ada506c6ec1c5f09f70af31c4f02969ff8f0169e11063b7394a4f70584f6afd0d1490540ca3f338645d170c878bcea20231697c3be698a01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a430cc306d25ad17bb0ed55ac02c00b6e1d0e372c2097f9d9bfbff1e27edb774accba4681e9320955590f2eaf7c0fcacfc42e8b1c0ad2d70207f2854e8b04b4122", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/9250a8a685e1f24b96edf202f1204a332bcb0ba3 b/txscript/data/taproot-ref/9250a8a685e1f24b96edf202f1204a332bcb0ba3 new file mode 100644 index 0000000000..fcc86f2c1d --- /dev/null +++ b/txscript/data/taproot-ref/9250a8a685e1f24b96edf202f1204a332bcb0ba3 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9c0000000073b9617bdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565caa00000000e018eef0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf8000000009055c6ed02596ab6000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8cf5391e", "prevouts": ["56552100000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "682a4e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d136490000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c64c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456a39aac74ee3f63949b9c215c515b0db1b113f4639b3fb19cd99ba22ff01310c728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cabf014ebcda750672d1ac021cd6394a2c6c5dad7d3d27b5e1c481868bd978a68405cb22a39b2e10cd1afb6cf33a44daad2098e05cd2010bbeaa225bcf768d84cef708a58e9a16c040ddf6ca6eff300c7bff2a5c928617bb01c850b0a79e89f728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}}, diff --git a/txscript/data/taproot-ref/9266cfa0d3adb02eaa15bc09db296fa853d6deed b/txscript/data/taproot-ref/9266cfa0d3adb02eaa15bc09db296fa853d6deed new file mode 100644 index 0000000000..ac68c9023f --- /dev/null +++ b/txscript/data/taproot-ref/9266cfa0d3adb02eaa15bc09db296fa853d6deed @@ -0,0 +1 @@ +{"tx": "fbe4c329028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42000000000fb3c3896bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5a000000001dda1dea04b72eb200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac2d040000", "prevouts": ["268a3c0000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8", "fd69770000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "2c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936768dcade149bd5f0639738187159aaf838493e37b26b5112985adcc9222a637ae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da733fe71e3ce0c37752cc3ed22f63651cf62c657cae6a4db35497744053504dcc62bd398c27c2bcf203967681d855a98ab83c6f29a4f091e05b1c584209e732"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663d313380d2564372a28c167374b7b81401e305a9c99cf4fec75b57ce768e17944f4b784770790344d4d1238d6245096bcc9e2ff88373fd56766bafd01d3e44ecc62bd398c27c2bcf203967681d855a98ab83c6f29a4f091e05b1c584209e732"]}}, diff --git a/txscript/data/taproot-ref/92848420c5779bd1c6d954bfc933383296c73c07 b/txscript/data/taproot-ref/92848420c5779bd1c6d954bfc933383296c73c07 new file mode 100644 index 0000000000..5d37ec6cc5 --- /dev/null +++ b/txscript/data/taproot-ref/92848420c5779bd1c6d954bfc933383296c73c07 @@ -0,0 +1 @@ +{"tx": "2718af9003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbe01000000e5a9b0d4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7701000000d487d4b6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7c01000000a122a7d901541e3f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e1010000", "prevouts": ["436e760000000000225120cd69e6502803f0acddd51df30ad464e69e95dcae732a2073690eba6ce00d0199", "a2f375000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "0988520000000000225120a98c6fc01fa4c9d83199250e6e76cd0e9fc22cdfbaba8827d6d131a9d8267c4e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366244692c25961778f5b75d5cf74ad811a2554082270838de283603655c691fe8"]}, "failure": {"scriptSig": "", "witness": ["6a75616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/92886f1a44cabcf2e2c4dcef68ee37caa458c47b b/txscript/data/taproot-ref/92886f1a44cabcf2e2c4dcef68ee37caa458c47b new file mode 100644 index 0000000000..1aa12b8d6b --- /dev/null +++ b/txscript/data/taproot-ref/92886f1a44cabcf2e2c4dcef68ee37caa458c47b @@ -0,0 +1 @@ +{"tx": "2cc2c040028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4180200000083645dc7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7f01000000daddb8d20432929f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac3c000000", "prevouts": ["cf0338000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7", "3c73690000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "267d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936642c909a10fe0e4fc753179e3d5cd4c801ae2c5d7d5d2a41704b786877d5c99912b49f68f31842330decdce79aecc48c70a85ed65081abd3cb605a7bb4f89ac9cd4c02f64c49cc162ff9325daec6263c98ea78a2c5346e44c6d55d79722c7edb"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936de6c09700178cad280c48f26380917825225e73e9c59e12e875f11cf4740c82b2135dfff529a8c82f4e399fa9509c5b3ed194ad634f2dd2a3feda036a1773d4612b49f68f31842330decdce79aecc48c70a85ed65081abd3cb605a7bb4f89ac9cd4c02f64c49cc162ff9325daec6263c98ea78a2c5346e44c6d55d79722c7edb"]}}, diff --git a/txscript/data/taproot-ref/9289711f9cf1406a577387a27b8bd4930e29fd38 b/txscript/data/taproot-ref/9289711f9cf1406a577387a27b8bd4930e29fd38 new file mode 100644 index 0000000000..f2f2b85889 --- /dev/null +++ b/txscript/data/taproot-ref/9289711f9cf1406a577387a27b8bd4930e29fd38 @@ -0,0 +1 @@ +{"tx": "859599e302bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0e00000000418ab0fedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3b01000000eea2fbf30421558e0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac52000000", "prevouts": ["715e6b0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "c673250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93639446218003eca9d9f50ac312e5383ca657554b5edcf97b5924c2574c3b360b5233ca416c78a4619c687785de007f14a4879f9c7a0556256e1b46b2a7e5a39b3c2782374d67da9500785d400f7ef10ae84f146bbb568355094c68456b68f7a283b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ed1da247c42feee519ec084f389faadb1fea6967491a64d33a6aea1bb627006bab4aa5d5e3dbd00e7a6b81724e903c1ca482dc7bc8339f552afc52b4f38fc6a5b77966166a359aa5541e77c34a58fd9dcb7d88ef6e7e0cd0e140e1adf959d28b"]}}, diff --git a/txscript/data/taproot-ref/92bddaa4b62dfceaf980ba7a89bb0cc57e8fc52c b/txscript/data/taproot-ref/92bddaa4b62dfceaf980ba7a89bb0cc57e8fc52c new file mode 100644 index 0000000000..fd60d42639 --- /dev/null +++ b/txscript/data/taproot-ref/92bddaa4b62dfceaf980ba7a89bb0cc57e8fc52c @@ -0,0 +1 @@ +{"tx": "a117860f03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc701000000bdcfc3bfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5600000000a3e6ebc160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e2000000008a5cc9e102a66ab2000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7d1010000", "prevouts": ["8417810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1a8a2400000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc", "27c20e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e4", "final": true, "success": {"scriptSig": "", "witness": ["a985b6ea14e9b384a3f4d2502a8c2585bd9b302b9f06f0e12a12d3b558bf75e828d121472590c20aa3e4ffb987d4228fa29188047671e063b79be8c43cc5f543"]}, "failure": {"scriptSig": "", "witness": ["f6279669b6d24a185a71b38dd7f03e2bd16b11b68ce29bd56654f5984ee2bfc1dda5582e2309066e5b56ade9d1e09239c8b7f91f725f39e0fec6632a2eff9933e4"]}}, diff --git a/txscript/data/taproot-ref/92c132ca1fe8044c1317c18feaca645a54713ffb b/txscript/data/taproot-ref/92c132ca1fe8044c1317c18feaca645a54713ffb new file mode 100644 index 0000000000..114a6f500c --- /dev/null +++ b/txscript/data/taproot-ref/92c132ca1fe8044c1317c18feaca645a54713ffb @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb80100000095c037858bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4770000000021da5818dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce800000000a4b8f83f04b7dcdd00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c45bb44b", "prevouts": ["724b5b0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "d90c3500000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb", "294550000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "737d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e855519fad8d6a945f0e016807e9ea80f240f92b51e0c4078917dfba5f2209ef9db33a63f37675deadbbcd666ca6b38ad7090050f3dcc6bba45985e955ec185c53"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a242f3c19d0f129445711ab0315a1086723bfcb35974ff1fec8f3d86f68a5ae585062220981136031499d54282dd1dc217e6360b68c94112219f47c832c6b09fa8cadcf9bcd23f9249fd09eb8b2b9ca63044a0ccef58f4cae9402f6ead4c2071"]}}, diff --git a/txscript/data/taproot-ref/92e0a98f523af81899be75f9371608fd9948b337 b/txscript/data/taproot-ref/92e0a98f523af81899be75f9371608fd9948b337 new file mode 100644 index 0000000000..ddffcd971a --- /dev/null +++ b/txscript/data/taproot-ref/92e0a98f523af81899be75f9371608fd9948b337 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c40100000047cb6918dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5c01000000fd2ae32903ce9890000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6dd902a4f", "prevouts": ["8d4638000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "ebef590000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360b0630a14fdba5198d2cd32fc4420c8a8ab4ff45908222cfc645bf4223ff04bdf827dd3f971806aab342b51fb6c2519c5b3aa410ee2eacb06207a66da829722129de37322ddf566a2356077a247b666bf816d75bd62d8842c555909c8a1545e03de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f54907a8d380556c8a330e16c78ee3af2c39f1cd46f776ecc20664efdc303ae9784ae775de15fa9e8fc81d7676ee4bb7b8b5e55729a9bd981757787c0c2477c76fd75cc9ac1e6f185878d252db6c7bbd874f5ae03fa9961d4f4a0208503b0750f17ad4bbf375bb62f626ec8048d4347cc1eef977780228a6d2fc47294088d561"]}}, diff --git a/txscript/data/taproot-ref/9309be25161f4e02117ef32870ded9650d0e4f7a b/txscript/data/taproot-ref/9309be25161f4e02117ef32870ded9650d0e4f7a new file mode 100644 index 0000000000..539d70c9d8 --- /dev/null +++ b/txscript/data/taproot-ref/9309be25161f4e02117ef32870ded9650d0e4f7a @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270df010000000d2d46bf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704500000000609e4da760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a601000000c24588ea01641b0d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87260bfd52", "prevouts": ["9707110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bde20e000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "f260120000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090282ff177af1b03054d9c533035830763fb8eed35ccb16c065252fcf995ad2b48163ae68b5dd01087842b3e484f15d0a4f1025d64dcf323509de1ac3f699ee00d92862e3d2e4a00dae2d2bf460d063ebf696ee1b6448b3462fa012f93150e1d2385ab3423de5034d0bf6b883b58ab8a7057cbc85f1fad044e7cbb12692b60a9ffc7479d5bc9c599ee817464b600b7c06eca8f80c467c517b2505f69f50d4670387dd1ee40d21bcc5c3c6c239f7a37f221431e055b20de844fcbbaf0417e691bd2b3b4ecba0d2a58811ed21f9f3d135caf9c6b7eccf507f71d2fe648b91b7e44cb901b76231dc68d4c1a79d0d4f9716dae56af7d0fe7ed863410f47ff37c2479842d4b8e00a62117bc9cbe89d24bad9c6a5dd07387e5a241d1b05e3f7a66fbf6920a68347e7a77757d557331da781a24930e1b4aa71b5f032f038bb0486545d79c84dab779aed2ab483083299127fdb95dc06fa6109afe7c7ac534a917bf19264f582ffc6c1361562a64fe82a6b1b294200ae02ab7f1346e070b6a8e871fd5acc5b6a0e23c2a73c941f36dc574a0e2681d625bb2b0373e609e18e641d34ed612fe3945aaf8a9cbb9b2f21306a6e7696088ec98ddeccd83dc79c65ee255f7dd573ce57b9edea5409ee4d8e3b5368f5a5bd503bf93a0a2153a9f659540231b73290ae7f251bf5eed0016a813ef8b0cb2e2bfaff590b23dc4b202ceb069186ef037a83a88199ddcc08484f4875c1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d03936fd2fb4ef675a9d8a495ac774f716ce2d4f21b7b05b81097d6a55e8066268c195719e600029237bb2bee296a81ae54a1bf44210bb387eff41995ca6f68fbfb640520cc13bd7f4751eea589bfdaf463667e9e3eebb3331ccb48f0e9ad4c4d3f52a2844c5f7874c7d430ecd2ddfcfe713e30c56da5784f950db6acb8f092a"]}, "failure": {"scriptSig": "", "witness": ["4d0902821c10f127db89ceb87239f88878cc98b92ec3ed8b8ad829ab4661b9d817091b2b4aa34d5c09c480b6e57f52f63b75396db79eb677021ec87518ac3b638b3ff98aaaec867e0efb8059b3bd538d3444624f74a8003cb1f4e935c70e238bcb57c5a183fab319e390d56be708f163171921bc2f2602cbd76f218ea6657acd2c35ae90bbe3c865b0d4de3fc39bd67983309a6fce9eab76f715de3e089ce872270c2a957f3005ae1fddd6a6b6cdcb6a931ccbab5475a6df2663096ff4008fcb681a691bd1254aef5ee56d923c50a427e7e4b99a73aeddfed8d017a2e5f725bcd42de38eee0670318d8a52ef12fa68a8753919dc95db7e14e7a3b4dd8f520698f92828591df62ac08888e1c8e570aad0c69dda337e79ddba0302bd304c2368f7a797d1e0d13d275ed79f9b2189ddee123fcd32445a0b6665253adfcb81acf8bc69c4668dc93529eb0b24fc04c608ea4abf9f9c988c1f65467b7b87e6573590e72b86f1d38cc2efd7de367e3b86874d4599b26d9f08b3f3490180d80325fd9914efc5eb1a9183bae733c8dd9876c11151c6e5c84a101b8600ede75d5ce52fa14928f9c266294b8a9dda7be93501a326ace83253bb3629bcbd1737cdc875da9aa24ecc66466393ef872ade843506bf6587de45dfe873094ee660dbed9d0a9a07f1adf339f66d32f8c8a623182321819995c347ba5eef8216e42efbece0f25e1553bb00cec58d85e8f8e26593bc7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366e4810b5abaf07487c81afb7f96e2c741409f4a370f93ea97a6bd648850fdc6949f82d663a1e447420f2cf05179af13964281439b8b427a6cb4b09af5b0cc1910a67b80b81ed02a57999348bdd390384d424a2522cd0278ffab5313e035bd402791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}}, diff --git a/txscript/data/taproot-ref/930d453e2c53ce2b64bd0f4b950552f988bdbc20 b/txscript/data/taproot-ref/930d453e2c53ce2b64bd0f4b950552f988bdbc20 new file mode 100644 index 0000000000..cc810aade2 --- /dev/null +++ b/txscript/data/taproot-ref/930d453e2c53ce2b64bd0f4b950552f988bdbc20 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c493000000004619122f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705600000000f0a051aedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdb000000009966758c01ba080700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac63030000", "prevouts": ["901e38000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "2cff0f00000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f", "676a26000000000017a9144c4b1fc943f04d775886b4f6d3c3c73bf7d3118c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "187d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb45493bacb64184bfdaef659f2e68a43f5d1d327dfc30cda594d93dc7e3d57d802a37b3510d82dab4bdf4d6195b9af4c8a1df2dd8a601b49dccd2ea1725fb9deb0356d5dc7bb189d5700ce63be65cd47bafc75bda640418bb3b77b52e492b0f"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93636d6e71a30deb5a5d82f1357d7fcc989127a050b444c84f666f959b2abd8d977a2a72d9a87053684bb0dc48081cf5c5135ec23a32b564c6b97b91a1c581596c8802a37b3510d82dab4bdf4d6195b9af4c8a1df2dd8a601b49dccd2ea1725fb9deb0356d5dc7bb189d5700ce63be65cd47bafc75bda640418bb3b77b52e492b0f"]}}, diff --git a/txscript/data/taproot-ref/934c8ad33d4e9c5c13372bc93bf26cf3107839a5 b/txscript/data/taproot-ref/934c8ad33d4e9c5c13372bc93bf26cf3107839a5 new file mode 100644 index 0000000000..c091b73e0b --- /dev/null +++ b/txscript/data/taproot-ref/934c8ad33d4e9c5c13372bc93bf26cf3107839a5 @@ -0,0 +1 @@ +{"tx": "00b76927028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4250100000051bf30848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c20000000038c234a6029a2a6e0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76c020000", "prevouts": ["61da3a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "77cf350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype1_byte_scriptpath", "final": true, "success": {"scriptSig": "", "witness": ["b73f22519c98fc73bb986a24583b60887b0a67b85da0acb5c14e44e24482799f1f2548b81e9f47ffd7b93357b6d67abd8803365637f5e37c889064c304d5bf8a01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b73f22519c98fc73bb986a24583b60887b0a67b85da0acb5c14e44e24482799f1f2548b81e9f47ffd7b93357b6d67abd8803365637f5e37c889064c304d5bf8a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/935a6ed5b994d0bfdaf42bf6dd6fef4ccdbfee4a b/txscript/data/taproot-ref/935a6ed5b994d0bfdaf42bf6dd6fef4ccdbfee4a new file mode 100644 index 0000000000..79b043d1dd --- /dev/null +++ b/txscript/data/taproot-ref/935a6ed5b994d0bfdaf42bf6dd6fef4ccdbfee4a @@ -0,0 +1 @@ +{"tx": "2b467a1e03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3d01000000139453f3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b81000000002569e0acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4c01000000b62770a0012fe80c0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc33010000", "prevouts": ["8f265c000000000022512035205488698c55c3e7035f1484d2f513744eb9d8b6fb6f0df083f7669ef0bfda", "7d6a1f0000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "d6c05300000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "8b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e4d7dc2c55a7521ecc297ff7217b922438f95dd9c29c118a2bf5c9e2c8f8c84f32a50ac17afa49989b8cd5fe09550e31f987b9afab4d6ff7fb0ac42074cc4b38f"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cde8e58194ee2d9158b02514bf803786a3307a33652aec833c6f0052c5cf85f6d8095c4fc48dd4a937a2ab720b4c7b803df056a6d61c0b781e24263fdb2663252a50ac17afa49989b8cd5fe09550e31f987b9afab4d6ff7fb0ac42074cc4b38f"]}}, diff --git a/txscript/data/taproot-ref/935dfd118a575d599a75b00db37955c92ef6471b b/txscript/data/taproot-ref/935dfd118a575d599a75b00db37955c92ef6471b new file mode 100644 index 0000000000..ca6b5aa858 --- /dev/null +++ b/txscript/data/taproot-ref/935dfd118a575d599a75b00db37955c92ef6471b @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bad000000007399e0b901dce016000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c8a96144", "prevouts": ["ce9d23000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3045022100af6a7d7b71ea42aca50daea1b2785de692f5639191ca5de1a446b2606c3b70d102202cef98b741c37cf76638cd84a7a5ff65cee1d4c0336d88ba7cc0205b281bd73e02", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["30440220661007a625300efcb420ff2d48a0f35a2b93fc4f60ba6c97e850e702a21a8ab902200bbfffbf14db197035a482ceead87fec107f8a6ec3c175f26ef0334f76cdd58302", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/936af0357943e249bd7e428753fc79b7870c4f96 b/txscript/data/taproot-ref/936af0357943e249bd7e428753fc79b7870c4f96 new file mode 100644 index 0000000000..d5623131f7 --- /dev/null +++ b/txscript/data/taproot-ref/936af0357943e249bd7e428753fc79b7870c4f96 @@ -0,0 +1 @@ +{"tx": "81f75e6703dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cae0000000014a05bb260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127036000000002ce4eb9c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702201000000586df89c03fad66a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487470e335d", "prevouts": ["52384c0000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "aa2a13000000000021521f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "06580e00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d64c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7d6bb54cde9cc6775748a201bb3f5d5704911b2e65f691925d2f8dff2efd34cd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51e30d689b41c4cadafebe300f1e3aad2e0751ea174af1d1313cd49baaa526270b3acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}, "failure": {"scriptSig": "", "witness": ["4c52d6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366166923529a9a0d12cf4938b50b7953e2ef8bb3db7f2829ccd570d4454b0cea3ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b22a5aef24b6a1c01bacd2a24a37cefc04a347b590d10f3bd98469f969c355217b0dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}}, diff --git a/txscript/data/taproot-ref/937fe4be2d5689c59d7c617e65996d41cfafdef5 b/txscript/data/taproot-ref/937fe4be2d5689c59d7c617e65996d41cfafdef5 new file mode 100644 index 0000000000..b4b8d7aeaf --- /dev/null +++ b/txscript/data/taproot-ref/937fe4be2d5689c59d7c617e65996d41cfafdef5 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127008000000009184f39cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8b00000000b18bd5d28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43300000000963b85dc031aab6f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7697ea15d", "prevouts": ["9e2f0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3c0a27000000000017a91486e5fab3386e07350db4c59e442dbaac96c1816287", "7c613b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_5f", "final": true, "success": {"scriptSig": "", "witness": ["abeac8960f7dafe5a2e919555e6460b7298142019262fa2dd4a3998dd53ab06ef01fa95a8f5c7115cdd23c95b01baa6c114ff467c2c00d7034601f04964c964e02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ebe010b49f957d45f204485fbb45e4d2e39be523a59a672c79d6cdffc24e9d2478f697633ab9722ee9bf575ffd5cbed28ac54eddf8585cb75e64cea6938a04ba5f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/938f94084baf3b93faae268cc5e094df56f01f7a b/txscript/data/taproot-ref/938f94084baf3b93faae268cc5e094df56f01f7a new file mode 100644 index 0000000000..2330077966 --- /dev/null +++ b/txscript/data/taproot-ref/938f94084baf3b93faae268cc5e094df56f01f7a @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3501000000d42eb6c660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ff01000000c3ef7ad960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270af010000003e9053a503f715690000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7a21d363b", "prevouts": ["1cfc47000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "edf4120000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "94c6100000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063da68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cd92e45bf75a1b2b146804c0ed0f2bf0edd954f9eb17213b8b1a71c9ecae831299aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41dc38fa67d6e370c9f405c2af01822f370dc317d6e78d2f71aa14f0ce4de56d6ee4d75780d36bffae9b56136e6d27c02b8d233efdc800bb260bfbba6a6f94b87"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e3c96742c83ea0214d677c4de90733cc5cf86dd9f7c70b49cd7ec12a5a3c726d44455204ada9566561196f14caee307d16123ffe4b49d60aeadbae3e053e0a80355d713f01682c54eefc137cacda341f8a928ca67657dd1895f9a847e54f584f6ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}}, diff --git a/txscript/data/taproot-ref/939a2a924292c7f549cc8f8be939826a3de6b820 b/txscript/data/taproot-ref/939a2a924292c7f549cc8f8be939826a3de6b820 new file mode 100644 index 0000000000..e8c4ecd780 --- /dev/null +++ b/txscript/data/taproot-ref/939a2a924292c7f549cc8f8be939826a3de6b820 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2800000000247f1be9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b470100000047d17b1904693c7500000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a62ec0844f", "prevouts": ["06e6540000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c65b2300000000001654142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e8", "final": true, "success": {"scriptSig": "", "witness": ["27816d2cc5e307295f9ba635ace825ae8c14604646013dd9594278abd50b430be530f3befb40017274871baa04f1800a5cd248c1b3a3770c186d0282e7abc58603", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["98d48ff1adcac3a0192abb8a2e0be7c8003f545fc28598db93a71f04f6a2c156240504bbd88a980304a4019c528c0a7dd3ca2c91f095a436811f65e39fb97f3de8", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/93aa13626c3895c12d82d3763e8e916a16a4fd52 b/txscript/data/taproot-ref/93aa13626c3895c12d82d3763e8e916a16a4fd52 new file mode 100644 index 0000000000..892c8a5988 --- /dev/null +++ b/txscript/data/taproot-ref/93aa13626c3895c12d82d3763e8e916a16a4fd52 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c1010000006ac7384fbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1100000000d73802e703a25eb7000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787b7000000", "prevouts": ["edca3c000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a", "b02b7d0000000000225120dbe65d5ea7d032bcaa5c118e4e1c91ea90d9063ab0b7377212d71cac34e27d50"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "success": {"scriptSig": "", "witness": ["48dd24f01ec389c6aa1c7c4de0b543aeb7f7b94ce820364d0184fe1f53bb065b1f23b30375a33b2b3e6d1fe920de9ef494292be62f0839c8a86aa0485b8beaf301", "a841b52a03af9c7e163427d00515846e743a7742c851a17eed0e6750dd8bb1970a6dcf20fe11b9097be804fee2d1d2b5eb52ef5e9a3a3cfdbd591edaac5d21a173a27d205bb8dd0a0749cb58ab4bd9efe53f7741b168eb2fec9fec62fdb3b7e9b89307413f68cc5d210df7aa5e3a8eef4ede53f94819860a15e3df80d2e97faf8ec65314dfdc3b9b023b57ef2ebd8547c892eb980de90baf9dba38718d2c481766b51315650b5b30", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb1e2cee3375e7a3617675c25794b8c82600f0458264a31e18d2893f71349a5cd20ca8a5b7d3b1bcf360b00e7a0b722e2c5fd3427d5a260246eddbdab3f29e162ee67a218d8499637a26bda36d2a17a3cf791d730915010a6ed0f6452f27224075229ccf552e66693fc023137dae6b03340574af2400f82bbc88f0e481dfc6497225ae0f110f2ee402496f4c339c19a1a603c6786c41be9b4f1c959b2ca4b7880000000000000000000000000000000000000000000000000000000000000000df81a15cb6157a997d23e8367bc6e778d43b26a7391e5efb842e07519fcf2f5399227a58e60ec9e6b42a2ed2fb9ba79d0d26d1d87db5e12175dd2f9c8b16ba652b7b3a6205956e6401c9f35d4a5d33dd0a3ba5495645c15232ff408091a30533520eb4d3a37acbfa4c2b9722f9927a216f07a961a50bef6bba63780c811be1198e724c90cae14c8ffc23ac098ba9b59d9b588fecbfb275ff754d9dc17b3e6dab8d918da947f768627accc543f58f7af31796b5434de8613084eef99decd2baf300000000000000000000000000000000000000000000000000000000000000009234f113cec6627bd6ac8487d93e3699e63c0cdc0619913cce44a51bb0f688eb39877db85e83f0c862d8633caf73a9326257144d7176cafa8629ff0c5b38202a68fe5f304ab2ad9df483dcda2ff7725fc0e7e89294fd0dc679c1a7a07ba414cec58399542820a6aeb2dcf95a041f323d25665f9fbca28886436077cb8be2b10e31362f5e1499ab046a77707a9c8a0c435df78be3b55c3a6aa2922cfe1a01bd14ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff31c7de372da1e17aa478b3e87520204bd20d956f29738cc824c65d8de94324675825aeb0fe9679d64732737cae4ba38ca353b68a4f3eba202b9e314708b61a2e127a0c4fedc2ac6f4adae18240490bb27d7b42d7a168ac08ce6ea079fee6bf690000000000000000000000000000000000000000000000000000000000000000079e65eb1dd2b124a80a8d35bd0029f27fad92fd612b1ff614a8d4a1e5d10ac90ca4c6b50bdf0ed8b864853222019b328796ac321814e1d88f0cdb52f5aa3ba6e58a400dad16b21b14843c4424ec0afbb1772a50e159adf93555f0a136120ec972364c2e6d4aa20a1a8760c5871a6c917650d01c13b664a51dff2bc2bdeeac8ab861982347bd397a1ab93465b080589fc2bf6ee04e3185af7edf8d73dd55326d7b5c915c87acd549339f916f567e3369a5da1912d46d34d7b79ee00a0f8f2ba621d95e82e83fb663631b922d7a9f430ff22c25e07756efeddca343b1c4b3a8986f764e232f2029831716841f4e2abbdd8d103f6085c0a1f56917c01df509ec2e54cb9151558f651cc1e1b0dd0592348420b5594962e953963c0c0e096ab00923e8ecb379c644d74c955a84899c399b1e8c36549036aff13bfb1fab7b36dbaf6b71072d7c456b323bea80f0c3438b35d27f68c3519c42d521cfd221c075e69f14c4dd61e158de2d244554bec2d52888252aca842988327a2f2c49ff1ad52390d29f53dee873326723dd1a456679a3d517f466dbf3230c244aef28d8c67137e393000000000000000000000000000000000000000000000000000000000000000065531fe14e1068f925b6ad5eddec6ccc3a1a910af7f93bed7d3c70bbd93b084effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c7429955b1371d76b9c5a03b2fed2fd7dceac38e721517ec9f63023b74898ba85b9b164b24a926af6531d00893e478019cfa474247430d3a6096db76e0dcf0ec2b7b2b03358038f744b4635e6a84169ae25b213a9b65407a11ad3ec283f8fc79117dfa1bbe4ceade5337c6474155c446f134c4d4564a096a9405b040d4c0de000000000000000000000000000000000000000000000000000000000000000003c243208e98b861d291ceb50342fdfcfdd2cc43175606849f5496c47d47e7b9f04e7c7f30e550162bb4e0f661d6d64b5508f6d2150ed0a6a176f58c2a0eb6d1bf98f69bb6b1d58ad95d0bcc0b605a2085e4dbc1d0b56b3d6128b4f3902d9f0dfdfbb02b23dab79a0011639290e791225b1ab6dc81fc967d21d215948ce50b05f9708d3303f22e7a9dadd0fa3d4fa152f585f19469e1fcc3d405562abbf025f8702f28380b57e16ffaaa570b43cd17e0b6725068ce5e1c9b1f26372a59ae55afef8cfe865368c14fff7e62b8a82478cbac8578808c103929716f2e137361eb7db000000000000000000000000000000000000000000000000000000000000000041b4fd78862ab3d40b1a51cf7d2d6a0288f4cd18a6612051787a5edc2b50167d0000000000000000000000000000000000000000000000000000000000000000a30c266ae1feccd856e1118cc2d68023e52e0de09538816b5ac79fc50efbe7a8727b36045284b7fc2ddccb6f164e73285988fe07dd03d753bb860f41763dbbb2bd9d5111ec067cdb62525b4849415ee86d0dabb4f8a73f6a30de4a539b3b3b95c54f52439fa5168156d15c3e37ab4d37225df79f7422a89d7e3e4135493ff2921ca0ce83222df7eb15ef31d5146da6f9e82f634324cef74550b85ab12337a9fc98fabbb879a80d0176390bad5bba043552303bbee8282dd8fe2449d37f8c088bb01645dd23fb480dc58884ab0e79d9d73494685c7618db1e70b517776321df6276416aa2b26db419ad1a6290893e169be8a70ca9a03781d069d1e58494e580e3a3d96bb0c10fdda9c69e5203b65b6c433092b434accb75594be0ef3b78e6f4267efa3be104ea80c6b41bdd8a4dc87e235c63ec296223fc649fb6af88b370344586eb6d563b9e215635863855633d8788ca69fed658f7b5051dfbbf42cf15878b6fc9bc815afb4af4c54f7088f28dcf9316d12f55d2d8af059fb8d59d6adfcdb6e068fbc7a9bab2aac249f58fa82f831ac02d98b64b4d69596372c61d3640d8dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff645d8253e8231e99b910b430c044a014f3c592f83c269553d49a3ea5eaefa182ba4ed8965a4012c5a826cbc3f0c69ebc16c1b50bfba73b679316f5b531956b2660a4cb2ace9b3bdeb09ae753192a0f8509bfc958c1b8892d68be28a91967f7e4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000967247d014acd37115d25537b0a6ffd6d8dfeadd62c2d9217c5cd05d25c7e3aa", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["48dd24f01ec389c6aa1c7c4de0b543aeb7f7b94ce820364d0184fe1f53bb065b1f23b30375a33b2b3e6d1fe920de9ef494292be62f0839c8a86aa0485b8beaf301", "430fa5c2e82a4549f63114ce2424c1c0614b93de19eaa8338300d03bdeb1ffaa55051b666a7533d3e9c4994ff63915420d4141f2623de61a081f22ad87dc13bf2aaca326c4791cc9a669dfdb85d4a2eba88c98ad1d69c768615fd1f8ddd33bcbb04ff38770d988f6555bb4537b52701a08f315922a1c2f14c801ccfb0403e89cef3695acaee51e07030730102f873e4a8ed153883d0a69c7232b148282c8e1ae832080e1a17991", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb1e2cee3375e7a3617675c25794b8c82600f0458264a31e18d2893f71349a5cd20ca8a5b7d3b1bcf360b00e7a0b722e2c5fd3427d5a260246eddbdab3f29e162ee67a218d8499637a26bda36d2a17a3cf791d730915010a6ed0f6452f27224075229ccf552e66693fc023137dae6b03340574af2400f82bbc88f0e481dfc6497225ae0f110f2ee402496f4c339c19a1a603c6786c41be9b4f1c959b2ca4b7880000000000000000000000000000000000000000000000000000000000000000df81a15cb6157a997d23e8367bc6e778d43b26a7391e5efb842e07519fcf2f5399227a58e60ec9e6b42a2ed2fb9ba79d0d26d1d87db5e12175dd2f9c8b16ba652b7b3a6205956e6401c9f35d4a5d33dd0a3ba5495645c15232ff408091a30533520eb4d3a37acbfa4c2b9722f9927a216f07a961a50bef6bba63780c811be1198e724c90cae14c8ffc23ac098ba9b59d9b588fecbfb275ff754d9dc17b3e6dab8d918da947f768627accc543f58f7af31796b5434de8613084eef99decd2baf300000000000000000000000000000000000000000000000000000000000000009234f113cec6627bd6ac8487d93e3699e63c0cdc0619913cce44a51bb0f688eb39877db85e83f0c862d8633caf73a9326257144d7176cafa8629ff0c5b38202a68fe5f304ab2ad9df483dcda2ff7725fc0e7e89294fd0dc679c1a7a07ba414cec58399542820a6aeb2dcf95a041f323d25665f9fbca28886436077cb8be2b10e31362f5e1499ab046a77707a9c8a0c435df78be3b55c3a6aa2922cfe1a01bd14ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff31c7de372da1e17aa478b3e87520204bd20d956f29738cc824c65d8de94324675825aeb0fe9679d64732737cae4ba38ca353b68a4f3eba202b9e314708b61a2e127a0c4fedc2ac6f4adae18240490bb27d7b42d7a168ac08ce6ea079fee6bf690000000000000000000000000000000000000000000000000000000000000000079e65eb1dd2b124a80a8d35bd0029f27fad92fd612b1ff614a8d4a1e5d10ac90ca4c6b50bdf0ed8b864853222019b328796ac321814e1d88f0cdb52f5aa3ba6e58a400dad16b21b14843c4424ec0afbb1772a50e159adf93555f0a136120ec972364c2e6d4aa20a1a8760c5871a6c917650d01c13b664a51dff2bc2bdeeac8ab861982347bd397a1ab93465b080589fc2bf6ee04e3185af7edf8d73dd55326d7b5c915c87acd549339f916f567e3369a5da1912d46d34d7b79ee00a0f8f2ba621d95e82e83fb663631b922d7a9f430ff22c25e07756efeddca343b1c4b3a8986f764e232f2029831716841f4e2abbdd8d103f6085c0a1f56917c01df509ec2e54cb9151558f651cc1e1b0dd0592348420b5594962e953963c0c0e096ab00923e8ecb379c644d74c955a84899c399b1e8c36549036aff13bfb1fab7b36dbaf6b71072d7c456b323bea80f0c3438b35d27f68c3519c42d521cfd221c075e69f14c4dd61e158de2d244554bec2d52888252aca842988327a2f2c49ff1ad52390d29f53dee873326723dd1a456679a3d517f466dbf3230c244aef28d8c67137e393000000000000000000000000000000000000000000000000000000000000000065531fe14e1068f925b6ad5eddec6ccc3a1a910af7f93bed7d3c70bbd93b084effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c7429955b1371d76b9c5a03b2fed2fd7dceac38e721517ec9f63023b74898ba85b9b164b24a926af6531d00893e478019cfa474247430d3a6096db76e0dcf0ec2b7b2b03358038f744b4635e6a84169ae25b213a9b65407a11ad3ec283f8fc79117dfa1bbe4ceade5337c6474155c446f134c4d4564a096a9405b040d4c0de000000000000000000000000000000000000000000000000000000000000000003c243208e98b861d291ceb50342fdfcfdd2cc43175606849f5496c47d47e7b9f04e7c7f30e550162bb4e0f661d6d64b5508f6d2150ed0a6a176f58c2a0eb6d1bf98f69bb6b1d58ad95d0bcc0b605a2085e4dbc1d0b56b3d6128b4f3902d9f0dfdfbb02b23dab79a0011639290e791225b1ab6dc81fc967d21d215948ce50b05f9708d3303f22e7a9dadd0fa3d4fa152f585f19469e1fcc3d405562abbf025f8702f28380b57e16ffaaa570b43cd17e0b6725068ce5e1c9b1f26372a59ae55afef8cfe865368c14fff7e62b8a82478cbac8578808c103929716f2e137361eb7db000000000000000000000000000000000000000000000000000000000000000041b4fd78862ab3d40b1a51cf7d2d6a0288f4cd18a6612051787a5edc2b50167d0000000000000000000000000000000000000000000000000000000000000000a30c266ae1feccd856e1118cc2d68023e52e0de09538816b5ac79fc50efbe7a8727b36045284b7fc2ddccb6f164e73285988fe07dd03d753bb860f41763dbbb2bd9d5111ec067cdb62525b4849415ee86d0dabb4f8a73f6a30de4a539b3b3b95c54f52439fa5168156d15c3e37ab4d37225df79f7422a89d7e3e4135493ff2921ca0ce83222df7eb15ef31d5146da6f9e82f634324cef74550b85ab12337a9fc98fabbb879a80d0176390bad5bba043552303bbee8282dd8fe2449d37f8c088bb01645dd23fb480dc58884ab0e79d9d73494685c7618db1e70b517776321df6276416aa2b26db419ad1a6290893e169be8a70ca9a03781d069d1e58494e580e3a3d96bb0c10fdda9c69e5203b65b6c433092b434accb75594be0ef3b78e6f4267efa3be104ea80c6b41bdd8a4dc87e235c63ec296223fc649fb6af88b370344586eb6d563b9e215635863855633d8788ca69fed658f7b5051dfbbf42cf15878b6fc9bc815afb4af4c54f7088f28dcf9316d12f55d2d8af059fb8d59d6adfcdb6e068fbc7a9bab2aac249f58fa82f831ac02d98b64b4d69596372c61d3640d8dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff645d8253e8231e99b910b430c044a014f3c592f83c269553d49a3ea5eaefa182ba4ed8965a4012c5a826cbc3f0c69ebc16c1b50bfba73b679316f5b531956b2660a4cb2ace9b3bdeb09ae753192a0f8509bfc958c1b8892d68be28a91967f7e4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000967247d014acd37115d25537b0a6ffd6d8dfeadd62c2d9217c5cd05d25c7e3aa", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/93c0123f1118e26a15aba5739d9f8db784f21efa b/txscript/data/taproot-ref/93c0123f1118e26a15aba5739d9f8db784f21efa new file mode 100644 index 0000000000..fd5a5acb89 --- /dev/null +++ b/txscript/data/taproot-ref/93c0123f1118e26a15aba5739d9f8db784f21efa @@ -0,0 +1 @@ +{"tx": "8e58b9e9028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b301000000df8399ad60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270620000000088e2538303dd3145000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d6bda649", "prevouts": ["7be839000000000017a9146704ae21c886c9ded757e2b67d582abfc91902d487", "05500e000000000017a914f955a33e905fb6c7b7e694c8cef25993577deafb87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "165e142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["2bb1a56194abdec51c8331e26013315467988ddbcb79c43216b1b1c8dedd9980c1370b18bcd322d72ddba207457f2254b5a0de08eeee92794bc91278330a2a49"]}}, diff --git a/txscript/data/taproot-ref/93c6f793e89f2bbe200dcd083729e8e2af40c2f2 b/txscript/data/taproot-ref/93c6f793e89f2bbe200dcd083729e8e2af40c2f2 new file mode 100644 index 0000000000..40f4f2f520 --- /dev/null +++ b/txscript/data/taproot-ref/93c6f793e89f2bbe200dcd083729e8e2af40c2f2 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be701000000e408386d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46a010000004e24027602e24e58000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48790000000", "prevouts": ["6c72270000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "f5703200000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "167d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5d52fd3619198ed9f30c361c888b4873ceed26f5355cdc470271342f0477c7346c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa654bbf7a6388e898988522fa7e5d2ba9e6951646cde29fc617f56e0c3d8e4d50afd13a3b2c4c421c5355668ae9e4eec8bcb7618363c6e35efd204a43726d22d6"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936623e05fc14b6e5762de92ccf74a58ef66fb3d817a3f0508030881bf1f629d27293bd46d889920012fd3d654be778806775b1e6ea0b6836161b66543651907968afd13a3b2c4c421c5355668ae9e4eec8bcb7618363c6e35efd204a43726d22d6"]}}, diff --git a/txscript/data/taproot-ref/93c799f74d4e3a3b8dafa975cb2453af687a8872 b/txscript/data/taproot-ref/93c799f74d4e3a3b8dafa975cb2453af687a8872 new file mode 100644 index 0000000000..22b1e84fde --- /dev/null +++ b/txscript/data/taproot-ref/93c799f74d4e3a3b8dafa975cb2453af687a8872 @@ -0,0 +1 @@ +{"tx": "d505974903dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7d010000009a3a5dc3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b710000000071f6369760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f501000000c7d508ab0473fc5900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487b6000000", "prevouts": ["a02e250000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "b3ca250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d95a110000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "367d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a25034f4670dba2bfd8b532fe5e2c4399b1757245b955e89574c41111a3f13a78448a7537869648343bbbdc00eb4ac0785a5f2aec0111e81b0d25ebde82a92a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93618278c07a795a465b0e01ec560e597d9dfa9576d66260ea15112d4b854280992e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a25034f4670dba2bfd8b532fe5e2c4399b1757245b955e89574c41111a3f13a78448a7537869648343bbbdc00eb4ac0785a5f2aec0111e81b0d25ebde82a92a"]}}, diff --git a/txscript/data/taproot-ref/93cedb385de6371ec85a3086d53c93ba0e1c6926 b/txscript/data/taproot-ref/93cedb385de6371ec85a3086d53c93ba0e1c6926 new file mode 100644 index 0000000000..a86d36976e --- /dev/null +++ b/txscript/data/taproot-ref/93cedb385de6371ec85a3086d53c93ba0e1c6926 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ac000000001d48c503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5b00000000989542d002fcd25600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748795010000", "prevouts": ["0bce3100000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "9010270000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ae7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8b509ab67bbf3c81955fa9e200008a666546f84b8be37a00b57f87c80ceedbec790189ee9b6b94816743a58868693b6f0ba58cb07e4c6d5ed2ce590077e887d5b"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ba812021bec55125a4043e092087428314c694c64b021517d83eab825dad5a3d31f1765c4043c65869fc44409698468cef1d88a3aab3981df946f88d25a1c2d5c67b1d078674a4d97323398e107b13ccefe9299bb9116e21f935c64f37bba24f619c7e3fc3d0f43b284295c7c76b7ff66dfc7bbdbc495ce3e8e20608c97360e5"]}}, diff --git a/txscript/data/taproot-ref/93d43e9d7f08eba5daa4d394a95703498c7e2139 b/txscript/data/taproot-ref/93d43e9d7f08eba5daa4d394a95703498c7e2139 new file mode 100644 index 0000000000..cd0cc6ea96 --- /dev/null +++ b/txscript/data/taproot-ref/93d43e9d7f08eba5daa4d394a95703498c7e2139 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd400000000b4b636e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4350000000068748b9903215e57000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87390ebb5b", "prevouts": ["0e7b25000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "a72b3400000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090254786fef98432f4ab257de77d302d189d2ec0f232bca6e2b1fca1feecafcfd854aa110d377d2578d0c1fdcfab4625f708ec4a38dc8cf6d91b4cd2d6fa7746fc563a7f7f0be9e1c1dedf1ec82a8900e7f329d7ed68e76b2c3aa579e3cd196d7366dda6ead2d7a3cdb21a3c8591c9c9183c51bc87260b4343623866120ffc72049ddc4812e61ad04bbc17d557f01e129c68f43b2ef82823b92d171c9fc5184eef6e77b45a0584b9d6f8763628e8f834b0e2ce9a08a6111927c0338b35615f221f46b6b6c43bff73856bac7ab70f3e7781249fb9043d9729ec319cd59d47c4bbba97252ca86c7c979feb223705d89d73a82bd768709e6e3ff0cc4c20ca28ad786041caa0828c6c8a6d2d4c1f99bdce7f0422cc95fe8372c33eca9e19d8f7288ed49001b819b206bcfeece64e3ea9867467f0697ef1e9e0756ba8e47fbd131c2fc0be13b0e15531b21de162d6151e53382d93941118bbe01035677c4469176ae13f991dfcbdbb07502cf46281b3c3b1b9ea1d170c437f5eb01e94331a544eeb07430ae71b6b229166fbc7682a8eb6033b5c0d53f2b133c9069db2619d299afa0627f989aee5400688ea4e41bf5cbaa0a17e02af5d12be9fcf82259f8cdfb7c0795c5fbf2b469b2324f531658e4048dec8544e6ecc22414d82aabeea7f98face78e63cc33e642aff2b66a041216741c0fa19009745012091a87683d040341ba6a7352234ab0357ce803479275d7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661747dd2a7267965918e87a9e7a48fc27a69ab683578f071fc2334710db08db0569af0f9e86656db21fe5e74d4bdcdfc2cda5437bccaf9e3d568ba1282fc608d76e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}, "failure": {"scriptSig": "", "witness": ["4d090231d74aad9ffa52eb77299edc3988789dcbc5d72ab76b297a80f562b7cea5a5dc21290fbfdd52f58fa0223a8c9dc3d11ea859c976e4837c697f05a286628fc13d83328f2e61534a39c729e16b54a3d54c3d9c1517f491295295b78f4934daa61986b7b02d6747ced33510e8b7cd3aa80a2131bc13169390dcc2540e87bcfc7742ebd4cc19e33993f11974952b38742181e1e73f4626a124a43656f4da23c2e78afe27986d9a79d56140391885cc1c0c4cce7d4c7fbfe2c08f6d447f3116e3674593c51212b661e7b791dee5b677c0fce3d524ffbfdad7c72dc4667e3b0a02a260efda42351cdcc6c792472e22740d5732e8267cde1c05cfcfb9d9d3610dec797b67ed9a88b832d9d09da1d46e9444068b00591ff70d0524d2df2fb8c61afc69dbd903ad7efd7b112a5dbe832abb52433bb39352690574e89330121f6683fb8d13a0c6096f1850f752b0976646fd2b8aad149048b66a74c8aa3f601c79734bf15b184d79a1af4281d6b68c6fe483848b1f19958ce6d1aec619c0d19c7113d5ec84560f716a7668c76aa54a39afb08789520ea58f18c88ad778f442fe97bdbd5c901819e62ae3126f82427110228cb9c8e33706abe8e7d33235abc851154ad1167c2bb7eb124781ae4fe0f0ae46067ca5373b7b987010f2aac7c3591fc839ca3f76722bd645aeb1efd6fe1137905af39a4e65fb07882d5960e3a1a5c7514785b68751fcc61aa138c620de7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514c1a4ef98c473095d2df256e4c96a081ff076f8ed25b9a6c5f4dacfc5de1b1d157a61376c510bdd1fc860151a3b261939fa407ec1a2d0490cf2efc4278abc783"]}}, diff --git a/txscript/data/taproot-ref/93db6d7b5e262a03c9f6ccf71ef4e8de7acf6fb6 b/txscript/data/taproot-ref/93db6d7b5e262a03c9f6ccf71ef4e8de7acf6fb6 new file mode 100644 index 0000000000..2acb5d0412 --- /dev/null +++ b/txscript/data/taproot-ref/93db6d7b5e262a03c9f6ccf71ef4e8de7acf6fb6 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c90000000024f8cfb50281b62f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478786010000", "prevouts": ["7ccf310000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "617d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93680e322cbeba9447e623c355f3a00500243eb51ea80336533073705560965e3918a99f3582d6399c0406dfe65dca998a5ce57b7e950df5f64352e1bbf6c7fd210dd304186c0a2faa80f59261766b0cb9b0760b78eb1f31f166a6f091ab62e6898"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e0063b43826002dc6eba62f224851f0eabb14759fb10c707a6afd7fdb59e93aad3ab6b2d4691bf881316931c587f0a213fdb9026021e80f212e72f88982a6bfdc"]}}, diff --git a/txscript/data/taproot-ref/940254cd6f8f945bc5f1edcef83ba2afc7edfdef b/txscript/data/taproot-ref/940254cd6f8f945bc5f1edcef83ba2afc7edfdef new file mode 100644 index 0000000000..65e54587fd --- /dev/null +++ b/txscript/data/taproot-ref/940254cd6f8f945bc5f1edcef83ba2afc7edfdef @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4210000000088e395bbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9e00000000065185d6011fae600000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc33040000", "prevouts": ["64d14100000000002251200aab5f0acbd570bedd550e6582d56f36bedceed0a29e5b4b9333b469d2c71737", "cfe726000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d0fe92aaaf9bcbf8f57bd6244a8fb4fbc0ca25d6d0424a43c103cee319c92082c98e5e9b0eaafdadb9b7184639bef269c7aaacc3aec400bafa574ee50a78d1c937b14430a19c2205facd906c64531600bb76adc53c9239ecd75bae8c55bd685bcf3ff5e4714c7e8d810364dea3179289049fc10102165a272bee60a9bb0427608ea0c76ca562fdd4d43e116602f3ca94b17365734a5a0ba06a4ca64c0a9f137e7ff037a8161020c2b9003b47a154a213b107ab80df1b79fe463c6fe3bed41dc1bcf455f14d4ddf7dfb8ac1d65a0f9a0aacc1b9c81335ac9fb2363f9b6fa9058f80066a0732d766ca0ea37d6667f1666075ddaee7b27d19725f1c2486ee4bd8ac431cf264f79215b64b507ea97b1af114e87dbef89fcf415595792bf33ddaafe4e9cf134e006f62ff0b1122ef3f2242b819a878fe17809a9597f28045074ed7b52974e9a2b2f05315decc5cee231aa321423b241ab8e9c1b20a1521f4d37ea0747a7ac6000411f3fe8ca75807e9a388bfcbdbf7a379d660bf95a051a3d46e047a38bdda72b3636fab9ffa0c34167e5afe27cc07ef32aa0bc86e5da4d4ed317ed5efd400a69b89be6d90d8d4e982fbed2549fa4d4e31d925a249114ec3f5d9d482068eb691a4a3ca0f220a499ef9de26ff5dd482f47ba408f57ae2524dad882aced40d933ebdc6ec50f04f74ec925805b936f16eae8e504713ec623a73a9964da95ef83820d6432ee37075", "247d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e85e7553debb7d46df339c30c507d2c3e528ab4da6adeae898375a123e3f0f1c20ee08d5698d988fd8465309aa10a601f39a775c4be89f69280a5de9411e45585f440784f6f41cc1ae323b623cf5dcb000da45020704fab66b6b5f2ff7d67a93a3"]}, "failure": {"scriptSig": "", "witness": ["4d0902d8ab9144589dfd188ed38c29a38146fdfae6fd14d7c3ad459816265fa1894697c74a9e81531014e365716550c9dbfba913e7c388df5aa87a9c914bdea04479f13aa5ebb240666c4d5ef29aab31796575a12d1576f0e6698a07473e2ce75eeec88793e9ed55dae3de690d6b58461f88f890c4e4195ff4ee742d58b88f125474b0ba4bbd369820b859e91664859466c8b7ed0396441f26e2c21c0e8ca389bb4a87ba802ed78d31367e48c32b7ffb721bf41d7729610cc9aef06315350089fd04d7fe46c04babfb5e36ac3ff677808d5e139cbe9343cb5224d8f6e230e06d833466e300ff1d874b87c81b4ffbb9c262af0fbc8c67293ff78f6f3c29a2404ba660a6712ea7c4f6298cd80669ebf5acbd76c916cbf9b9eba54642b17d50dd19abe9cf598a8be8f4cbfc845b0c281009da22f2601f26d180c33c922d6915baa2c40406d256800ca4baac9a3ee509c5e5fc178737f643cad6cbccae98ea54370671fef481aab536b786ea76e462b473a60c2133ab4e0f52866bd71552cdfffeace9a551c0bf894321d39efec519c272fd60c0604baafcd1177665a0d02c83eb5520db7d389e3d6183f84bfb17660592c001c0bdeee2468aed3f6f562d87aa1f2b0fe0f8c36d8b7c40e1d9888c591005927595391b443efa5a6bb9408ac3dcfad3d177d97a629e9b435b2e2df4b44046ac4a818ba0c3063cbd6c3fd178f4eb6d4ffe032cf8dc0552fc5173bb3675", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93624d31f15a10278dcb4f9d1f0a96cdf3049a06339797676c8885dddd4f0fc93a7ee08d5698d988fd8465309aa10a601f39a775c4be89f69280a5de9411e45585f440784f6f41cc1ae323b623cf5dcb000da45020704fab66b6b5f2ff7d67a93a3"]}}, diff --git a/txscript/data/taproot-ref/94136714739c4978945621f669ecaf025dff07f8 b/txscript/data/taproot-ref/94136714739c4978945621f669ecaf025dff07f8 new file mode 100644 index 0000000000..861890c689 --- /dev/null +++ b/txscript/data/taproot-ref/94136714739c4978945621f669ecaf025dff07f8 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfc000000001e5111c0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf720000000083aefab460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270490000000053752fdd0376fea8000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987cb000000", "prevouts": ["de10240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8c427700000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "5ba60f000000000017a914a2a8d85df2f20a0aaff7224012fc4cee13e29cb987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_20", "final": true, "success": {"scriptSig": "", "witness": ["a090d9990b2e412cd6e3c8e32f54fda22d116b9c0bb0efa2dfca7db13c0b9e6e375a2108dc5208770275f4090b58cd9dabb9541452357807808d9894058659c883", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c9840e15d47a73e5867c99b9844c7b2b14ea7dabec79d1143b5d1e2bfa9734cce169380b194d264cb4e2a3914a690403441bd5608735929f1fc3eb4bb8fd6bb020", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/942302c74767926cf73be9bc6753fc422157855d b/txscript/data/taproot-ref/942302c74767926cf73be9bc6753fc422157855d new file mode 100644 index 0000000000..e81ffa9caf --- /dev/null +++ b/txscript/data/taproot-ref/942302c74767926cf73be9bc6753fc422157855d @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cab01000000c52c83f28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41902000000b66db99f0378a38d0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f874b030000", "prevouts": ["b33c4b00000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "74f3430000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00637f68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c177cafa467da566f6ea98c1f090f5884eb8b4c26177aaa2b6576cf2c9201f80d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51d82f8c55e99af1bc6044802eb870171f459184b3c99e354e12eac4f204be9c37cf5fd42f9969f7f2472ed1fa62ffa49909a09466cf06ef7c57cb1be351156c54"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f7be44faca900f8c301ab589905499652f78692082c5eb6dfc73a67bef26ea6d1e2e06d6ff5c459c120ed1951ff2f8353cc05da31129bd66db4aa2f495d014ff8d5397512e216c7ab52609f0ab27ccbbfd2b7e561d7599ada55e292956af911ecddbcce676de51918ff82e75e695523ce4d8df7d4ec353d45ae6331617767e1"]}}, diff --git a/txscript/data/taproot-ref/94232b6796277453192019999be8b0fce849e3c3 b/txscript/data/taproot-ref/94232b6796277453192019999be8b0fce849e3c3 new file mode 100644 index 0000000000..a82e356498 --- /dev/null +++ b/txscript/data/taproot-ref/94232b6796277453192019999be8b0fce849e3c3 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be301000000fb36def3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb301000000e6af33afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0c00000000754fa2b201d3161100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac7fabae57", "prevouts": ["c6bf250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b787490000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b", "1205240000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "1a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08240401d3043d3e54134521a2f6b274f3ac0e46a5b9a6f95ac49ca3a75270b4793801cbe9d84ce1e82e006940c90d66235295537a514918e448d1b01c99be1031af2727a08c83da142d000f7f66d34a23554b296f940ffe81022e50f50dcfdd8b9"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360dfbde9ab9ff110150d651dbb4a3d630519bc9a746ddaf163b71af588c3b00d4febf22132d9643e24ed9082227473dd30d4d39a0b990b222eadb4d87d4a2f8740b87aa3d77021654e9bdded249075f42755a492250fa9a6a44787c57353d93e356798b11c96dafc2935d577afad31a6537ce4b1a48ff27833822cff5fe95a51e"]}}, diff --git a/txscript/data/taproot-ref/944304c86610b738afbff55026632249b735f401 b/txscript/data/taproot-ref/944304c86610b738afbff55026632249b735f401 new file mode 100644 index 0000000000..b9081021d1 --- /dev/null +++ b/txscript/data/taproot-ref/944304c86610b738afbff55026632249b735f401 @@ -0,0 +1 @@ +{"tx": "5e99ba8803bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7500000000df8a91a8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3f000000005c7bc9e9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0d02000000a28c08c40314b9e600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75c6ed459", "prevouts": ["48417900000000002258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "685e2300000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "f0a04c0000000000235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f94c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c138752b88f442304cd570a99b7416851da048b7f1df3ec1a880a296df45b544a4dd4bfc6549e8d5e198b0f1e67d147f6db02444245a6cb27bc19444f2462468d332399bdd0fdb741da8d579adddb10dac50c4b595c0031ea1e156729d78e3487d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}, "failure": {"scriptSig": "", "witness": ["4c52f9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936546f12ea3782fdfa089a8659f2ae7491ec9907437584497a98bb88f5268eaae43f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bb0de8cab6875867027c85350e6845db37b89c1faa2a12b075d8db116249f7bd2367bb7d11bbe7d9666c447942212a409021a53e3151df7f84d090727acdc4c9"]}}, diff --git a/txscript/data/taproot-ref/9447c6b9ffec17e55cc04961dec9cc9affec21dc b/txscript/data/taproot-ref/9447c6b9ffec17e55cc04961dec9cc9affec21dc new file mode 100644 index 0000000000..9eb058c5d5 --- /dev/null +++ b/txscript/data/taproot-ref/9447c6b9ffec17e55cc04961dec9cc9affec21dc @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cde010000000845aabfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9300000000e34899db029dd8b10000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87a5030000", "prevouts": ["4f865d000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "302c5600000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c34c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667037ae3d106809ce95ad6513527bfd5a0b48627df6eb2b59a2167c6498316646ad1aa2e9998afd312977ef35369de24510af161418b16660639891f4f8529ff8cfae4f24e00136258a4229df9ce1533cc743f70cc4e5c0214ad74c09f63cc0b9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365dd02223ca4597acd8de63d12e0412289521ae63f6f7ad5a46a5d7d4a8953badd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51073db8fdd32dfd70cc3c0b801d057b12e5f9f3471dc2e8803f572b477b94c5e2cd8777bf679e716871b092f46e3a69645e6fd098b2f58cf3078cdf1926d6f261"]}}, diff --git a/txscript/data/taproot-ref/94862fb03e48c18301c8d883c0b89da06351e369 b/txscript/data/taproot-ref/94862fb03e48c18301c8d883c0b89da06351e369 new file mode 100644 index 0000000000..212062a9a4 --- /dev/null +++ b/txscript/data/taproot-ref/94862fb03e48c18301c8d883c0b89da06351e369 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfac010000005fbc51e78bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ff01000000a025c78004003eb7000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acfa151a24", "prevouts": ["c84d7d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e9ba3b0000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_4d", "final": true, "success": {"scriptSig": "", "witness": ["eea2c9edfa24f76bf4760d2a53bd5b8ade8432fb437d2ea08ea102ddf0a886847a9109e356829c1e5ec30eb7f17bb5b039959fbb21922fb2bace86851ca3037f01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["73706fe5284f98b0c6a4177669acbc4dc59fa654f9e1420e0a99696196bd82863daf911dab8343e09409419414b646f94616d36728dcc15f2b90c8b1c5cd8dbd4d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/948c81d5b83d1cdb3423d9e81a61becd8bf2a7bf b/txscript/data/taproot-ref/948c81d5b83d1cdb3423d9e81a61becd8bf2a7bf new file mode 100644 index 0000000000..31eb82d4be --- /dev/null +++ b/txscript/data/taproot-ref/948c81d5b83d1cdb3423d9e81a61becd8bf2a7bf @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f8000000006d3588dc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709300000000775f78d38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45c01000000bf2c651d0114714500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1f010000", "prevouts": ["14030f00000000002359212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "0f160f0000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "13d73e0000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["99", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364d586cb5de2dd3058dd7e227544d59b90431907c0aee9f3c45dbe5cd5ada47d3637edb6ad97271a1ba84afbf70caa284b53510d77fb53cff70120791d9457d51af95302e7a08635545e6c64d05a20a7ff60718981ac8a997d809f6391d7b2d9241e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4db2b7303d128165c3aee76333e625284db46e202d1b30be35d2598f7d6b886c0b317c85b837bc971133c463a5a02b3e438f62c623f33a660d87550a4209620af95302e7a08635545e6c64d05a20a7ff60718981ac8a997d809f6391d7b2d9241e79d00d576d46a63d36f208105835dedf99b7ad1f6575dd8e28af32480c198"]}}, diff --git a/txscript/data/taproot-ref/9499a40681e896adc4c45047502a358ed7cf1237 b/txscript/data/taproot-ref/9499a40681e896adc4c45047502a358ed7cf1237 new file mode 100644 index 0000000000..1e18d1e7e9 --- /dev/null +++ b/txscript/data/taproot-ref/9499a40681e896adc4c45047502a358ed7cf1237 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0200000000cc03c0d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c680000000072bf48db039442c600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acc4ec2f20", "prevouts": ["e2656b00000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "65ce5c000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "", "witness": ["3044022049ee0c47c4f3a735b510cb6f85e3c6bcf9d275e29e5f7f2f3693e3ccd37efd7802203f2307995276e4ef52ae9b8526a9d4980553586de3f19a457e49e2cb25530eb483", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["3045022100e83255d06c540e8f2511e4bb337d3f43cbd43f57f38ecc1711fc24a9d900884b02200a06d832866bd94d4ce0ec6a694cb41907ea5dffd79f2d723a99711fc0014fa083", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/94a9f7a609640945c820b281c9b05d992b0ac4c2 b/txscript/data/taproot-ref/94a9f7a609640945c820b281c9b05d992b0ac4c2 new file mode 100644 index 0000000000..6a9540276c --- /dev/null +++ b/txscript/data/taproot-ref/94a9f7a609640945c820b281c9b05d992b0ac4c2 @@ -0,0 +1 @@ +{"tx": "c7be2d510260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f2000000007a27fcd68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d300000000f23e2aa40213964400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898778fe3e3b", "prevouts": ["d736110000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5", "8239350000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a144e2b32fb029cde325456c88021dd04a80b93e0665f7e39c1e8a56bfdcaf4a64b5cd80fb8cd7c947a98554a389db356265b198fc72df311d010d98c3d6e3928"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369849f93802d015225ce464a5059afd3869fe1ff89f107510c0c7d17e487c82c619ca94dd80cd6ec848cff445ef1653ae8d91bf4217e3b4bb0faac1831ae9489bd0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}}, diff --git a/txscript/data/taproot-ref/94f8b89ee92aa4c7d64eb59fa7c8811ee71c5de1 b/txscript/data/taproot-ref/94f8b89ee92aa4c7d64eb59fa7c8811ee71c5de1 new file mode 100644 index 0000000000..487cb3b8ab --- /dev/null +++ b/txscript/data/taproot-ref/94f8b89ee92aa4c7d64eb59fa7c8811ee71c5de1 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bea00000000ee0a502560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fd00000000d7a42f82dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b80010000009c57242704fe4b5500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48746e08936", "prevouts": ["2584250000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "ec9f120000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "64811f00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902680cc4d69146017a87b95bc547afdc8c45fd5312dfb8ed85131cd90383e2229ac196cc1b7148264c63efde8ea5c704d3b11238759cde1ce9235761ba139ed649fa688962dd8029b5dee8bc6fb982c30e5b06d9767cc362c4b9390a68c43e16bc1c1881ef11d328480e30df61013ce5a8af6ccc1d5f007ad18deac8d334d8fad10a0f7c3a47fe4f4113b295d35c14b92870e07e8dd29a8b17beeaa043d0913dca2a424c8d5d9d41ba2caba3b8adc2b0701a1d51be9cb8c2355d8ed6c30d02cbe514e9ba86e9d6146e590e8fc5ee991ab01be077ed9e50ee4b79d9dc7c1b4fb696fec7f50f9d12dc5c52138c30d07405a8074aa265239c4a11127d697b0d28a005ea83087d7a292e13f36f12fa02f3cc254c18fda00694af2a203ce13a3c056c9dd7b463bcb560d567551ab8196949f358a1fb04b557534191ecdcc62a0168d46b57e8a79fa88a3f4c899774ea337268b029300257e83616ca739b013820230ca81fde2507f404a41f127600082432bf097b260ac0fad2113dbf5fc83e0b043d19a51b792e819d76ae730df85361497cd1a6b1e74a57c03373b6b92190784dffdf55eab1a901eaa1e1f7d99b5c1aff1c83c2ce0e63e8d757d8ac0a1ebe38cedf8d7f4edcf6f8f94b88f70cf7967bfc8f26b0fe0533a8678f053e8c12776e6a230c0566250e4ec4d28409584d8f5625cfce5cb6e6b019fc0fcf554760cea342cfbf2a0765165ca163aeb075", "8b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d8095c4fc48dd4a937a2ab720b4c7b803df056a6d61c0b781e24263fdb2663252a50ac17afa49989b8cd5fe09550e31f987b9afab4d6ff7fb0ac42074cc4b38f"]}, "failure": {"scriptSig": "", "witness": ["4d0902a1e8be2efadc6e1b0482eeefecf4e0a64bfef0392b24f5f1c3f62ef22ff58a1338b60654178185c84b277d68f45b68af128503a812dca3290351a5adfb9df0e90cd2624337b3135d7b435fbce48abb693252ff88972819c5a11d19ed2a6c8abb6cb3516175c7b22545b775c2fe6dc390c8b8a873002b0253055d69d2f650c7d8861bf0913a4f3d6de1ae14ea0d8420607391fef732362fa23e3441142d31f166a095c3dc8c2455923625acc971f12be1b3941ebf25b414fbc6a503f62b8be062c3bd6ad3875438b45136355e1c8a4208a077492961c2dd91f4437ac9fc785c423b4d223fc8f11ce7aaae64a7651cde0f8a8b341bd419c60e9347bc1d2af15ab87b484d561051118c34dc18c648ea49ffa0352e61c3a51f0e286325e5a1de2cb842bdbdec170e69ca04d2fbfeca4971376d67fb7223bca0b899ff426f872d28bba90bb2fe075ff5454a8cee45bde09db8c05634ad3f2d74f96701997c4a2e4a513c0c9b281a5328959d6154c48e18c8aeb46fc289d106379c480836ddb931d85fe4b17f7d1b3c2bc34fb101fb86cd16474dfeab80818020e76fdaabdf54ebb12214d39331489476f40e839735f9ddf5751d1fc9d4b6f6c298919abd91709350c0d9f30b0baf5187a823b78ecd1331ee94fa6b2eff010fcf9f491c8f09914f34bdc7c935eda6f7b8f893fdf2237544e2e5981ddc0c6d5a5847e2e5d2f0d382affdd29d08cbf8552eac8a75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367791b2bfed2b76187482b9df9c71e44fe3c2ba7cf851c9a73d39e20991cc5821da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e86a27b1635c4d20405f5eb1d8e1a675f8ac3bff005ffde1fde7fd53008c3096ff2e441b555c43a724b579c479d380c278f8ccac4217fbfdcb96526a1dcd96287"]}}, diff --git a/txscript/data/taproot-ref/9506e2eb82ae6c5a245403a82c8c36c49e7dd19a b/txscript/data/taproot-ref/9506e2eb82ae6c5a245403a82c8c36c49e7dd19a new file mode 100644 index 0000000000..3ebd980ac5 --- /dev/null +++ b/txscript/data/taproot-ref/9506e2eb82ae6c5a245403a82c8c36c49e7dd19a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b650000000040181b27bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfed010000000fb6f19301b3c016000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487fc000000", "prevouts": ["9d322100000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "cfc2690000000000225120a276d97cc1349e693e88dad472b695a8145cd2b116efbe16166838c11f43c819"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a90b348cb78586aea9abc13e0f8e119b3cb755ae0df5cadce93cb6748afec68f"]}, "failure": {"scriptSig": "", "witness": ["6a07616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/9512c13d6e0d292adb68e6b0ed8f466ba396e30a b/txscript/data/taproot-ref/9512c13d6e0d292adb68e6b0ed8f466ba396e30a new file mode 100644 index 0000000000..e3c5d98c41 --- /dev/null +++ b/txscript/data/taproot-ref/9512c13d6e0d292adb68e6b0ed8f466ba396e30a @@ -0,0 +1 @@ +{"tx": "0b70bbbf028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43d00000000a3e895eadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc2000000003880c1b703b6b6550000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72396585c", "prevouts": ["eb37320000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "98662500000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ec", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828ed780475d4e357c95738577784a2a9ab12c45b3a32d4ee82ce9965ecaf5f6bbb17c496824b626c02ab547b0eab6d99cf720fc5f5950d9f56a4e0f1a7586e075a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368fc8101a1f14b662558c0e8593c88d9d486003e9c8266cbc14341013234749228ed780475d4e357c95738577784a2a9ab12c45b3a32d4ee82ce9965ecaf5f6bbb17c496824b626c02ab547b0eab6d99cf720fc5f5950d9f56a4e0f1a7586e075a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}}, diff --git a/txscript/data/taproot-ref/95285e78757c883cf8644bfcd7749e4b08cb59c4 b/txscript/data/taproot-ref/95285e78757c883cf8644bfcd7749e4b08cb59c4 new file mode 100644 index 0000000000..f2a6cbf486 --- /dev/null +++ b/txscript/data/taproot-ref/95285e78757c883cf8644bfcd7749e4b08cb59c4 @@ -0,0 +1 @@ +{"tx": "a77294ea028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ae0000000081d69fbb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a501000000e28dd3c903cee874000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961f030000", "prevouts": ["b5783700000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "506d3f0000000000225120fd767bc2bb07e4ca9357cd933b3dc41f590c00db442e0ea12a871bb96cd7e63e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f0eeba7c0eacb784f7272b1ab2a5d964d7d07dcaa25aa39271492b80a379da12aad829192d8416594973be53751c2dc095bf33e54427303a5b8b45ebdea5dafd99ead232f95c20736c4ca28d40406922684ff7a84c70e432a4f6a4d4d1893c4694e361b142bccbbefeea6ac26126d4f4fbb610699e3a27d96f99d1b67de22f2f"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a92a11deea73e637f6f589c2d30a1664a56b9683feb403a53636f2947938dad3fb7770917eb0311339f7797b42ae31badf39be5fac652227efb4e28a80f4e35f46b3ac3e0eb552c07a1c6336d6a3e2704f93e82a6d5b4a7907113e7cf17bb16c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}}, diff --git a/txscript/data/taproot-ref/9528c094e6823258fc43686ee4fdc5d619021a94 b/txscript/data/taproot-ref/9528c094e6823258fc43686ee4fdc5d619021a94 new file mode 100644 index 0000000000..d315a1eb7d --- /dev/null +++ b/txscript/data/taproot-ref/9528c094e6823258fc43686ee4fdc5d619021a94 @@ -0,0 +1 @@ +{"tx": "aceead2a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b940100000081d662d860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270db0000000091e8ebe1033d623500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acb2000000", "prevouts": ["f89c280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "688a0e00000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "b37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670eb4afebc61f249a9d49057fe9b24516a5ecc1080546262d6e5ff85cfdb211b95b7d6bda25431cc8e02e54f2e1c95b50d23fb11d52c977ad7d2dfd588f90c1962055c347ba5402321504576f6c37d0c6cb1d044ee75df535bc9eec0560634a7"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e846f47172cc098fd97d2a24de1b24a28ec1a07dba8121311e99b8793de3d58a2c368ced990ebadb111ebc3982eac7e308f07f99a9264ca6c949f56162916d7884"]}}, diff --git a/txscript/data/taproot-ref/95418ddbd4a17ea011fd39c57c1e4389b711dd7e b/txscript/data/taproot-ref/95418ddbd4a17ea011fd39c57c1e4389b711dd7e new file mode 100644 index 0000000000..7b41eb29c3 --- /dev/null +++ b/txscript/data/taproot-ref/95418ddbd4a17ea011fd39c57c1e4389b711dd7e @@ -0,0 +1 @@ +{"tx": "bc407aaf03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6600000000004780dadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9500000000b762a584bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfec00000000c46558bd01b5e525000000000017a914719f78084af863e000acd618ba76df97972236898718b7f726", "prevouts": ["d3706e00000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "a20f210000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "60e3700000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ebe99bd20db478a4ea38512f1221f176d7e5053d85ce724541b970d7e312b589d332399bdd0fdb741da8d579adddb10dac50c4b595c0031ea1e156729d78e3487d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51a022e8e4f1240b3c3d4bb5c70f2b4ea702b5d8a670f036755e200b5950ffec075bb8659128f7d307893f477315172a6feef29cf3fc1fd27176c3d23e09b029752367bb7d11bbe7d9666c447942212a409021a53e3151df7f84d090727acdc4c9"]}}, diff --git a/txscript/data/taproot-ref/954e0aead2f1448d168416547f795dc8baa7eb10 b/txscript/data/taproot-ref/954e0aead2f1448d168416547f795dc8baa7eb10 new file mode 100644 index 0000000000..af9b0facbb --- /dev/null +++ b/txscript/data/taproot-ref/954e0aead2f1448d168416547f795dc8baa7eb10 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4b0000000063774ab860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d500000000cc67262401117116000000000017a914719f78084af863e000acd618ba76df97972236898756010000", "prevouts": ["628d500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2452120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a0", "final": true, "success": {"scriptSig": "", "witness": ["e1a9667d17a1e75a6cc9b884de02170067a2cb8a87597ae011abcb81b842566b811bb42d1fbca1b65f2f533d0c90ecbdda5fde3c77f5f764a9bc4e4d90e39b1a01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f345510d74b43d1b7e579d4942af46b8fb961ac81025798e2b95973a88e8427415a940f02fcf29c821a73d5cda19b090f1112a8c0ea74e04dca5d390688fa817a0", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/958966b97201943c2831502b3f5bbcccc2d1b2f3 b/txscript/data/taproot-ref/958966b97201943c2831502b3f5bbcccc2d1b2f3 new file mode 100644 index 0000000000..11074d9b7c --- /dev/null +++ b/txscript/data/taproot-ref/958966b97201943c2831502b3f5bbcccc2d1b2f3 @@ -0,0 +1 @@ +{"tx": "b063326b03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfd00000000d54304dcbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe900000000f78d71fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707000000000eeb7db83038ea0cc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689870b010000", "prevouts": ["daa652000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "f0016e0000000000225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "33870e000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["e68b325ef03fa84280a54b34dbf53a9277b395ea2fd16e226cca8ec132028a05ed3734d002e1b197dc424e81a0707786eadf555401954d3232adbab2301adeb7"]}}, diff --git a/txscript/data/taproot-ref/95957430f0fd0b98963bf7080efffaa2efc45563 b/txscript/data/taproot-ref/95957430f0fd0b98963bf7080efffaa2efc45563 new file mode 100644 index 0000000000..4a2dbbc855 --- /dev/null +++ b/txscript/data/taproot-ref/95957430f0fd0b98963bf7080efffaa2efc45563 @@ -0,0 +1 @@ +{"tx": "760cfce6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41e020000008082e1c6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1a010000009b10e7d2012db07a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478726010000", "prevouts": ["2967330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5d51770000000000225120bd5bbc5b1bf3fe4b708ed63f9408b7b63aebc344d9604176f38c41259c503453"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bf", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936848548a800d3e3b730b60aa08b661ee08371fada4c88e7cee944eccb1db67c8820e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e10ad4e0ac96c164f1885f81b1e139f05879070681278f68106e4fa54c23a8038d82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93654ba7869cf3ca4b2b50b47f0812896a39a8cfc31061938cd1631f43d1a68bccf0ad4e0ac96c164f1885f81b1e139f05879070681278f68106e4fa54c23a8038d82745fb8509382ce1e64511ce3c1d55be477e9687cea49eaad32aa52098dfc07"]}}, diff --git a/txscript/data/taproot-ref/959b1c7bccd9efde5105f9deaa24262e6171f127 b/txscript/data/taproot-ref/959b1c7bccd9efde5105f9deaa24262e6171f127 new file mode 100644 index 0000000000..be3cac94ba --- /dev/null +++ b/txscript/data/taproot-ref/959b1c7bccd9efde5105f9deaa24262e6171f127 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6b000000005c19b047dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4300000000fa054f9360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127072010000002e2b715c0281e4d10000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6940e7f4d", "prevouts": ["ab4c790000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "48984900000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "4c73110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a7e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb482f3f1132320d0959751765567119a0f105dea34ff98e3a4034ab732ff09dfdbb3b80bda1b133ebf5523b41a15c88aa3d5202619e06dcb6a8f4a5442678614e2fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d615c4047bfcad7b0449dd11a2b25a6fa73c03f83d31e78968dc9546bdf436c01f4adb00685858cbe7bcb6f491f781bc30000d79c976ba3736fd7b7a39329ee30cbb6a1bc9c683a9249ad6bea98cd3b225511a23bd3763b6594afd12d3e036b5faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}}, diff --git a/txscript/data/taproot-ref/959ef5c1dfba6621fcd8365261b27885ba0eedfb b/txscript/data/taproot-ref/959ef5c1dfba6621fcd8365261b27885ba0eedfb new file mode 100644 index 0000000000..1de88c4dc8 --- /dev/null +++ b/txscript/data/taproot-ref/959ef5c1dfba6621fcd8365261b27885ba0eedfb @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d70000000095241478dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7c0000000022e144c003cb9d2d0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7c0000000", "prevouts": ["839b0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b091210000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_df", "final": true, "success": {"scriptSig": "", "witness": ["af0635ab83a466aee85370db6138ba6f81a6ba673b5166ab7d2d00abc52b902073c09e41df60a83ed9e62c1641786b24221dc6f31dfc18d50d14d34e2081568b82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["4349984b549f290e220e0f2c73fbee085e81fdab3eca4143e77ef7df71aabcaeb3d61669d45a10fcd71f2f4163d6a3f8e598bf41824b9bc5e6e18927c020a291df", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/95a04b0c50967b773d91751126d1ffe273287347 b/txscript/data/taproot-ref/95a04b0c50967b773d91751126d1ffe273287347 new file mode 100644 index 0000000000..7e4f189e22 --- /dev/null +++ b/txscript/data/taproot-ref/95a04b0c50967b773d91751126d1ffe273287347 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2800000000247f1be9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b470100000047d17b1904693c7500000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a62ec0844f", "prevouts": ["06e6540000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c65b2300000000001654142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["7f4e68e27590d41fc1d96b76995c0151017c929b2188301d6e02341a4932e699b7d144d2e1920d69af10294c7f52fc08ec27b4dd1d77a6e98601371e91cac3e5", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/95afe9b1e8db35a5924aabbffc0a617e6862a1d3 b/txscript/data/taproot-ref/95afe9b1e8db35a5924aabbffc0a617e6862a1d3 new file mode 100644 index 0000000000..85ab7be4cf --- /dev/null +++ b/txscript/data/taproot-ref/95afe9b1e8db35a5924aabbffc0a617e6862a1d3 @@ -0,0 +1 @@ +{"tx": "01000000011221809fa938f2ef41f6621f6e6a0e75e05349f5a7d7094926420abdf536093c0000000000229bfbc70260ef6a521200000017a914ca5375a68588393c82c00f5d2ab21f91e99aa5ce875802000000000000160014ca9858c362545bc83a3b93e73b12b27a9b3ca00336010000", "prevouts": ["1ff76d521200000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_invalid_unkleaf", "success": {"scriptSig": "", "witness": ["8ce42f81440679dce044d02079a20729983aecfbca152c25d3e936f88c156f8f864364944d6f770c25d7d919ef277045ed1a2464dbb3348ff6203227b2ceb794", "20cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3ac", "c2cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3cbfc5d7464d6f9932fdfbdb59ed04135d3da1fd24a1d97149f3f9fe8acd746e901c94ae67cd857f8f23543b618b38154b6c0432568bb8cf7638fb55d4cc0a24e"]}}, diff --git a/txscript/data/taproot-ref/95b65f78191ad63ba2149f216ad4b1f3a404ee82 b/txscript/data/taproot-ref/95b65f78191ad63ba2149f216ad4b1f3a404ee82 new file mode 100644 index 0000000000..66d91c76fa --- /dev/null +++ b/txscript/data/taproot-ref/95b65f78191ad63ba2149f216ad4b1f3a404ee82 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270980100000024408861bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc0010000009526508501d78f510000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7b999eb5b", "prevouts": ["1e9e100000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "7d097d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f04c65b7c7fd446794a0bdc7f03ec8afe87e7a8979190b8a8d9a7dedf756203a11731258bb3fdfadddb7ae68c53504a25c25356d55367047ba7d256d75a6bb7241a69b934cd2855d9902b26cd23bdcccf828bccd6e43a3687ae54088365633ea5dc2f0a95b502e4151e8232c2eec29d5b91164a6c3efda9c7376ae9fed31d914cf212ab5ab74f971205a7753b54b656f917a7b294d9b6a817dd76a3e453c6f840db86805c7cb385de8fc3d1ac66fdeaedcaabc386c1916cac954990c516fc95baff6181bc66beaaac59a0100489e4596eb40d5697bcf8697c592b5eaffed24eec828c05d4879bdf28244a14189170e9f70cd4a3afee97d564176cc829168fb5a98e4a63785b4466fba8e7b565aa871ce26f989b0536a7646a0bc580713a3a615f832d438f6425370f7a3f8670f1ce6cdc8355b220ca4dc90117aa12d1555fb93ec247e0cbaed1c2286ee1e34f4268a0351fa5997e6e98a181d16b689af29a10addec4a16d9117df49bd167838028309e06e4810cf5bdb46d8d180727e1d838996b93db41eb8cde82043d3a861045a0c204d1ac0befcb1503c642df5c5b7af6574da030ad3d0e211d39e9811102b4b2c4ac09a0f318395a8ccc186afb21733f9f6de47ef03f047c5d04a73fe1a3136ea8cfcbea5b652129a1849148d63cdfbd624a1a4a5c9a31415a2020bdbc5c3d15d0431329283b110f52abf1b86971f7f2dfa80e4ad36734afa46575c9", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0d74e6cd8e612cb42cda5f7f42dc10fbfe42e4e0a9faed92158fa7e41e5f92051e17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}, "failure": {"scriptSig": "", "witness": ["4d0902f90151c0d9003beaf4adabb925bb8a538073d1fe2883d65c3b6bfc063e3dadc71bc19f7148581d56637e697264c849c2bee9c3cbecc48b284f09f334d95b6f6e4cdb3c7b5ad0393eba0cece63b5866876813b79548ce0fccb39a847f41ecd1d5947c3af0dee314c4e7fd3b87300a529bee34c7387ba18cce0553fbb0e4fc65270818e3e5cef061cabae8304ebc8a3b4d77b3b167dc13a6027ac9ee5a2b5a8f41ad352d20fe1978e5338eafdb24f5c9c593f3894aaae2ee735a316d269ea9a777aa13ba0e4530c3c3945ada7ffb046cb6b95cadc322964492fc86af3eb6db122791637d739ffe83e25b1ead3c86e6e5ed044d814cf8ef50d2dbd148f359f07ad8cd87d19a9f83c4be854c5b32f528265adc3edb6df5022c169ac58c05edddffeecafc7ad25ee315d3147947df3f93909d565d2a8a460c7423149b7212ddb6d268f0cc480865353dfc0fedc82c5d480545f56e3d29d6b374d1038b85db7dc2dbd2250a3e941608a6a6f4d43173f1c628f32fda8490cb0e070c91c6f740a6c0248051ca7c7f9c237666e45de1d322044f7c781bf969eae945f53d1e4f2d0b80173dbee3aecb101c4609bcd398ad93abbea7bc8132bc6de6aea2af19d955edd29f077c421875353c80bcbf0801960a00253c8d6d549f3bd4119ae0ee22cfcfbe0ad868859abb18fd3ea1e7996ce5b71e8979bebb38eb17a029d4a0876ef8b834f2dc71e445e546abc3a83a7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936615498dc0588a9270f8c0d1f3dae5ae97705b42ac78067124fb5b8bbe1895d4977878475803065420b5149b394b9f2a263406aa3a3cf62bdb9b13e67809a83ebcc9238bf2d7dc0bcf11838c34785251ea2fa5f3bb034bc98e2e8efb0909b7dbc17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}}, diff --git a/txscript/data/taproot-ref/95bc7b2db1ac665317576e24031e551189f4efe7 b/txscript/data/taproot-ref/95bc7b2db1ac665317576e24031e551189f4efe7 new file mode 100644 index 0000000000..95acaacb94 --- /dev/null +++ b/txscript/data/taproot-ref/95bc7b2db1ac665317576e24031e551189f4efe7 @@ -0,0 +1 @@ +{"tx": "7f02f66c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701001000000807656f68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43a000000004a3e6fa701c6143f00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd3010000", "prevouts": ["bc16110000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "a79a400000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "1d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea5e09f506d3786832e30b2bdef7e552adbbac598072ee50ea4bccda1394a3023f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08233479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a4bb2c7d85af23cd06361a8d9967d47c0827d7b479cd52e2216fb2d12a2ff38bc"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fc4cca0131d18d8150e9d666d72698d77b9db3880415ba5ae0e811c11ff8a05c33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a4bb2c7d85af23cd06361a8d9967d47c0827d7b479cd52e2216fb2d12a2ff38bc"]}}, diff --git a/txscript/data/taproot-ref/95da825d4132e9de80a280c89ba82724643b74f2 b/txscript/data/taproot-ref/95da825d4132e9de80a280c89ba82724643b74f2 new file mode 100644 index 0000000000..0bc239cf92 --- /dev/null +++ b/txscript/data/taproot-ref/95da825d4132e9de80a280c89ba82724643b74f2 @@ -0,0 +1 @@ +{"tx": "b5d5ba7e02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be900000000704da091dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b970100000044b31bb50347704b0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796a3010000", "prevouts": ["2c7d240000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "12a5280000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "f07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363b039c0e9d8bf6e88a427a2ddf5980e431ac842cc97f6c7b94ab341d52b6d0fdbec2e27f579b173781717090b44a070e7a8880532a05b17dc998986213b0a92d21741bf2762a3041d275698fd56a81520b6404e88c31ed080bdecc36c09cb10e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652dd3253268b521b8234f9a6c7de3fba7d5f203b8100eaddd2fc9e08d24fa7c435987c1d75c441670cebdf615816c6f42e3d99515a7a7b9841c20e75c916465ebec2e27f579b173781717090b44a070e7a8880532a05b17dc998986213b0a92d21741bf2762a3041d275698fd56a81520b6404e88c31ed080bdecc36c09cb10e"]}}, diff --git a/txscript/data/taproot-ref/95e7d15b24fad0c2e4780004a45b735813a6d457 b/txscript/data/taproot-ref/95e7d15b24fad0c2e4780004a45b735813a6d457 new file mode 100644 index 0000000000..0aa37be26a --- /dev/null +++ b/txscript/data/taproot-ref/95e7d15b24fad0c2e4780004a45b735813a6d457 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9b000000002f21cb13dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9000000000819e17eb04c2af770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e707f3412a", "prevouts": ["4faa590000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "4d91200000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "47304402203b3b1b67ef1f56303fe41dd67bed9260158e77033ba8fa721dca9e2d2697a8eb02203e1ffc8f83c9481ae0dacdc38dd1ceafa8b085447dcb3d956041fd010a9b6de683", "witness": []}, "failure": {"scriptSig": "47304402205d90f4735ea2ed121c9fb17b44121becc089a101496976b6cc676c40e7c67d1702201b7d122e86ec7260af8111647d8b9191264c697bdf4c3dab15977b35ed8a168183", "witness": []}}, diff --git a/txscript/data/taproot-ref/96089d3e37c85cc3e1727b58cbcd209157529a71 b/txscript/data/taproot-ref/96089d3e37c85cc3e1727b58cbcd209157529a71 new file mode 100644 index 0000000000..2a7200610d --- /dev/null +++ b/txscript/data/taproot-ref/96089d3e37c85cc3e1727b58cbcd209157529a71 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270de000000007f4af652dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca600000000e56eff118bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48000000000454a026504e231a400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e79f410645", "prevouts": ["a4bd1100000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "f33b5400000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "67d540000000000021531f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["81874ea55bb484ce75fe27abc22c65268eccb0819379e66ab9445a41764683988d2bb4ba25bd6eea6753501005e4b83c29e3040cd120cf530ca321279e53f5ca"]}}, diff --git a/txscript/data/taproot-ref/96197c6b417cdc946b9a34b57ac7c50feea0ada4 b/txscript/data/taproot-ref/96197c6b417cdc946b9a34b57ac7c50feea0ada4 new file mode 100644 index 0000000000..707b82f1da --- /dev/null +++ b/txscript/data/taproot-ref/96197c6b417cdc946b9a34b57ac7c50feea0ada4 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9501000000a8b3eea4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6601000000cc72cc87043cc19900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71b040000", "prevouts": ["60ae7b0000000000225120ab4625f49c703a23e189ede82045800566d41c1fd8d57f05292e3c6cc685d2ae", "2cba2000000000002251205ab8b22cfa491307edea11ffaf6a065b7e494e63cc66e0c2b2743a26e3a8b68a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["6b12de5f3b333ec91a047d2b43355f415e4ded9a048bc4f4c16cd75bc930219eb3cb6b26366d4bad0a4fd214d65a8c781f3bb167d706c82a2b6a51162381b92e01", "352284dad82b036af43c24e5be3d4994b4373bf4aeae6a240f2a9ae6cc6d3c06e2e19a3ce2c8a072121a67a8a07c2cf1b93bd083ef6ab9aa680b27cdc2329f626b8cce5da597a591e75d2a8ed1e812c6e7551f15068bb6831c3225785bc5c6c2703d7bcf080f9f14bcabbb776658eeb4f677e1c5c957353ec1a30627379db5a0d305b7dd5a8a0b212ecc9ba14cc6f9b4a05c880aec358cd18f7542e54c4f18ce27b5a7232f1648ba1efa39ce36051325acc3d969879eba227154a8c715f3cb1eae8db4150435d3e259cb017d7141ab16f799f11dc5d3e4acfc5d920b33820fd6f8ffc51133edf6f5a5be8d98", "7523fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da00636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366a4132c35eb83b939fc40cc5ccf1cca5af9baff7a5985ad17bef59ab852777703b9a5bcde44843206d9ea957ca2ea9b9d7d55c77ae8c0385d069207fc690dbb30000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0279d32bd902e9dc737021a8d5c1ddeca94898b34864580aae6c64e56b91b81d4dd5ed814737efbcd07c3935f1b55530aa0394366918bc0dfea70abb7a1c69697e8025fe74d0081f7f9a15f533dd681c110855a593b2093844df61448887940809482d422e99a138b392f7354f51e541f10e9b811a38838d323cb0ff3b540f600000000000000000000000000000000000000000000000000000000000000003357ce03edaa37ffb79837839ba74a5028457f4db579843aa562808bb81c250fbc0c6c92c04daf27c17f22ca50729b712619fbbc6793628ec6c6f909f39ffefd800d29ad6642d761bb7794bfbb470a4a8f0d43aebb8e69f7b18a8cbdeec7db6375ecd39d4f765446c5c810baed0c32c1b405039ad2245d6ae04f3beb2032eaa5000000000000000000000000000000000000000000000000000000000000000050ad678e9755084e5b456fb01e726fa2728836ed92539436a7ad264ccdbeb1a000000000000000000000000000000000000000000000000000000000000000004a11e7a9becbeb391512b13f8cb073d0841508fb6e490b3b828c8d1aa087440479e6a0b23eda5a42214f52fb49d6caad0f86da22499a5aa2ee74e67078183072a256bf045c41e66bfec21cb8c884b31edef389b9768f333f414fb77f74129cd6", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["6b12de5f3b333ec91a047d2b43355f415e4ded9a048bc4f4c16cd75bc930219eb3cb6b26366d4bad0a4fd214d65a8c781f3bb167d706c82a2b6a51162381b92e01", "11fa8d4eaa1bffff91f036208ca07e441fdce1f75d66275c7e79fc0b518b1a97104f105fb558a3f7e62583b80e54fcf0605e9e623ed6bc4940d9f6e44f2b87d5bbab05f8904b5224237e72419f6da552d315e600dda0a9e87f548149b016fe552107dea4fa25220681fb39daaa14d7afe75be22885afd26487e89cd7c96c244fea56feb1ebf6b8a854d51ccb004e777419ff52efd4ad3612c7b97990f1ae504d812bbacee33fed8f73f773c79af7d993663f7485d563f2cc33ddf28ea6eb2abefe9797e06a3195464d566ac734de140fc79294b75d07e698aaced5e4cc826df8f452c35940010ee6930161", "7523fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da00636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366a4132c35eb83b939fc40cc5ccf1cca5af9baff7a5985ad17bef59ab852777703b9a5bcde44843206d9ea957ca2ea9b9d7d55c77ae8c0385d069207fc690dbb30000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0279d32bd902e9dc737021a8d5c1ddeca94898b34864580aae6c64e56b91b81d4dd5ed814737efbcd07c3935f1b55530aa0394366918bc0dfea70abb7a1c69697e8025fe74d0081f7f9a15f533dd681c110855a593b2093844df61448887940809482d422e99a138b392f7354f51e541f10e9b811a38838d323cb0ff3b540f600000000000000000000000000000000000000000000000000000000000000003357ce03edaa37ffb79837839ba74a5028457f4db579843aa562808bb81c250fbc0c6c92c04daf27c17f22ca50729b712619fbbc6793628ec6c6f909f39ffefd800d29ad6642d761bb7794bfbb470a4a8f0d43aebb8e69f7b18a8cbdeec7db6375ecd39d4f765446c5c810baed0c32c1b405039ad2245d6ae04f3beb2032eaa5000000000000000000000000000000000000000000000000000000000000000050ad678e9755084e5b456fb01e726fa2728836ed92539436a7ad264ccdbeb1a000000000000000000000000000000000000000000000000000000000000000004a11e7a9becbeb391512b13f8cb073d0841508fb6e490b3b828c8d1aa087440479e6a0b23eda5a42214f52fb49d6caad0f86da22499a5aa2ee74e67078183072a256bf045c41e66bfec21cb8c884b31edef389b9768f333f414fb77f74129cd6", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/962bb09ab095bcd35f7f34055ed0fa8ae434af02 b/txscript/data/taproot-ref/962bb09ab095bcd35f7f34055ed0fa8ae434af02 new file mode 100644 index 0000000000..4616f5f918 --- /dev/null +++ b/txscript/data/taproot-ref/962bb09ab095bcd35f7f34055ed0fa8ae434af02 @@ -0,0 +1 @@ +{"tx": "7c5fc7c8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cd0100000043a3c7eedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0f00000000209d439903a82a8c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e763020000", "prevouts": ["4cba380000000000165c142540f27e90740933c99d4f17ab2dfc6c82951cfb", "d2fc540000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["cdcd03b7982f23ad354233e9488a289dda72216c8b27a5e543001742fbf05d9388147474fc08919f4af4f6550f081c79cb058547d8047ec5e1876def72c265d4"]}}, diff --git a/txscript/data/taproot-ref/962d79802cab79d4bd0c5d840a5f94281465c290 b/txscript/data/taproot-ref/962d79802cab79d4bd0c5d840a5f94281465c290 new file mode 100644 index 0000000000..b19a042a97 --- /dev/null +++ b/txscript/data/taproot-ref/962d79802cab79d4bd0c5d840a5f94281465c290 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6900000000d4abccebbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb700000000bd7983dd023b8a89000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47874aafe95d", "prevouts": ["0bac2800000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428", "09de63000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "577d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa1c685f9e7861cf217f0c3f090528b45399014026e5720182b0faf436212c9d85a66706abdbe591f97764059d8785051c12d40b9c9543fb83334d204ae23d8b59"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363dccf744be476308f3ad44f6863ff9a5448f7fadb85d23dafd7b2172bbeece448cd69c149de1c0fd775c23d200817106db3811e77c5a94d49bd03e58d7bcfa223a8385792857b3824bc259fd95f469eb32c57805e5f383de6590f06749d208e6"]}}, diff --git a/txscript/data/taproot-ref/966f41ea0609c64925ecaee5ba1af166ae43fdda b/txscript/data/taproot-ref/966f41ea0609c64925ecaee5ba1af166ae43fdda new file mode 100644 index 0000000000..d5fca4b3fe --- /dev/null +++ b/txscript/data/taproot-ref/966f41ea0609c64925ecaee5ba1af166ae43fdda @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d01000000a146999d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40b00000000f9d200c960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706c00000000e4a24ae5038de26200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79693145c58", "prevouts": ["a3d2230000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30", "ba3a3200000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "f60b0f00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368c95805bfbd60030f39f9e7ff54381e8f5f456ab69fdb578716fcf2f064cb19a3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08208660b63218e506e6f6271f897377780851eb071546e65f7287d9a4083d90048d0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c599d2b9d61b74acf4ac0275e657007f4671c4b15d8de5ed816ccf5810b1da1108660b63218e506e6f6271f897377780851eb071546e65f7287d9a4083d90048d0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}}, diff --git a/txscript/data/taproot-ref/96735cbde31cd1fbca452de029d3f77a7072dd87 b/txscript/data/taproot-ref/96735cbde31cd1fbca452de029d3f77a7072dd87 new file mode 100644 index 0000000000..5d7a646e80 --- /dev/null +++ b/txscript/data/taproot-ref/96735cbde31cd1fbca452de029d3f77a7072dd87 @@ -0,0 +1 @@ +{"tx": "caa0da5f02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa6010000007ac8318cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0f0200000026999d930300049100000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac207a7f41", "prevouts": ["a2016f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "fae5240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f4", "final": true, "success": {"scriptSig": "", "witness": ["54f0f7cf5f504be8abaf25e0b378e6ebfc11f5daf7f8dcb88dccf69023cd9a190480c402fa675a57ec9e3761dd0a4b8cfcd4083f3a5c08bfea856fad103d396603"]}, "failure": {"scriptSig": "", "witness": ["967748dda729efdfbd36cfc9b244c0f31dbbf5a106454f5839566692ec8ac6a074f2a17b1b83a7f21d122ff25a96f9219602c5de0d6779e0a40510e55b7c5bc8f4"]}}, diff --git a/txscript/data/taproot-ref/967784fbda80e2586d2566b1d20422c209de8e3a b/txscript/data/taproot-ref/967784fbda80e2586d2566b1d20422c209de8e3a new file mode 100644 index 0000000000..22221c3589 --- /dev/null +++ b/txscript/data/taproot-ref/967784fbda80e2586d2566b1d20422c209de8e3a @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47d01000000bf12ba80dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e020000007eaf3ef5041e8d5500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79693000000", "prevouts": ["fd043300000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "0f3225000000000017a914a5f28fe5532719f979169bfa3a31d5746f69452187"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00635068", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082464f19ce228e2f316c50129d6edd6267acdc0242055b306d7ddf31bf4be6326132cb43424d7ca27a7abc5fd0c2fa249f92b1e992144deb3864a86d466f79c2cceedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cb2894c14af897d5f38758afa36e148e02b3b317d7add528440e83327826095a4fe66249dd01ecee23c2f5e0ab3cfab587707d36ba83a587f4ef7ad777b411580826552c6add4a61cb16ac7f3706b11d0158c18b61683494ca90054287b9ac7bc2fd9879a2ee2ae7d76224c991edc718b1729f7f1922f570a67a21926d2cc48d"]}}, diff --git a/txscript/data/taproot-ref/968b512c074558ddde3b21c60e2886fd579c950b b/txscript/data/taproot-ref/968b512c074558ddde3b21c60e2886fd579c950b new file mode 100644 index 0000000000..b0914b6ab0 --- /dev/null +++ b/txscript/data/taproot-ref/968b512c074558ddde3b21c60e2886fd579c950b @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a901000000929372e9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c190100000046ba7ae502e2b28d00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748795000000", "prevouts": ["d018370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "22c3580000000000225120dd69e0acb4456a75559641628e54f237a5bfa27624d5103e01688d193a4ffbc6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d6f20f9c142c896504037837674b191b1b5298a1d8195d4919ee117d333470ee"]}, "failure": {"scriptSig": "", "witness": ["6a41616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/96a0422936b6ca5c4077e1e8fceea23c5dd146fe b/txscript/data/taproot-ref/96a0422936b6ca5c4077e1e8fceea23c5dd146fe new file mode 100644 index 0000000000..8ae01395c1 --- /dev/null +++ b/txscript/data/taproot-ref/96a0422936b6ca5c4077e1e8fceea23c5dd146fe @@ -0,0 +1 @@ +{"tx": "64f4e4390360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707701000000fb3218d8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ced0100000081e9f5b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcc010000006137ffcd047b7d89000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6034d4655", "prevouts": ["3d9412000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "be405700000000002251208ab07249a1fdfb04b130308cc651220c9430f0ee7d7b49fe0191e15183fe6b9a", "277321000000000021571f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "483045022100b435743e7d6a6a86d4bf4e05e5ba0631fc508b01f4ba4aba81ca3da895dfd63d022050621ea3bb4a49cc2fcd0fa340211e04bf8f261d8e5a343691cd4decec93930481004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "483045022100ea0fd795d63bf3ae74d7bccd20e922c4f25f18161bada16e83931d546594786a02207b106a137ceb2572fc756fe27f5161d9ce2d2b57b91c1c5df406fed4301e0f208101014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/96aac36c65d79125e3ee07ec601f71c0c09b0cb2 b/txscript/data/taproot-ref/96aac36c65d79125e3ee07ec601f71c0c09b0cb2 new file mode 100644 index 0000000000..b20df230e4 --- /dev/null +++ b/txscript/data/taproot-ref/96aac36c65d79125e3ee07ec601f71c0c09b0cb2 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270900000000030ccb953bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf360100000044aec6de01f70b180000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc12a84e37", "prevouts": ["90430e00000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327", "f73e8200000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "577d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa1c685f9e7861cf217f0c3f090528b45399014026e5720182b0faf436212c9d85a66706abdbe591f97764059d8785051c12d40b9c9543fb83334d204ae23d8b59"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363dccf744be476308f3ad44f6863ff9a5448f7fadb85d23dafd7b2172bbeece448cd69c149de1c0fd775c23d200817106db3811e77c5a94d49bd03e58d7bcfa223a8385792857b3824bc259fd95f469eb32c57805e5f383de6590f06749d208e6"]}}, diff --git a/txscript/data/taproot-ref/96c1bbeb23affbc8ce9c5703062a448e21a42eeb b/txscript/data/taproot-ref/96c1bbeb23affbc8ce9c5703062a448e21a42eeb new file mode 100644 index 0000000000..f01557776f --- /dev/null +++ b/txscript/data/taproot-ref/96c1bbeb23affbc8ce9c5703062a448e21a42eeb @@ -0,0 +1 @@ +{"tx": "fc52232702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff701000000ec1eb2dbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b00000000007f7b48d60234038c00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9d000000", "prevouts": ["15e1680000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "86ae2500000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902fd4beb2efab09f5c1dea67f0404d4beb74562d7f251bd1c8da47103abc0967a88e01a8a958f45477aba1d9a18fd19f77dc2b7c5ad8aa95a23afeefed2b22616ff8dda7edc1049de7ddc9946ee99db2507679ad0212f518f997c928f3d645921920259d311fb616f00108fdbc78cbc5b96068b92690f12aa2cab1817bd7ddfb46e4dedeb66000ddc0dec609904f8bc6d19c08d8ebb23cc2995580730e20da6acbb7c2951806e4fff1ed9c364d526160343bfe201473b3cae34feed3c78b67c7869f445e4c780ec64c41f9f65285c2799fb671a70ccf47d48b438f2dd6c56500dc3e4ba47ded0c92403113ee8d5627f823e3f93594ae547afeea3fa03ddb3f33565d51d5d1c854118e4d1866609ba643163698e5f996e5349302d4031e98e8309cbfbcdb34097c651c25184e3bf830a98225024886db9c56aa5c47b800d42e28dae3f154dcedd2c5e05f69d3337d11c6a92a8a5ec40368edeec57f1e25ca9900f1bb4f4777d4bcbe83a89a0bb0c4e89c0da2b90e2de467a0d87878f8798882a49bf7f7f0e98ad14db1bf37010ede85c0d4fee5d09f8ed7ff6dc16182feee67e8447a94f7a142a26df23ba20b0129f1dbe1f1702ac0bfaa8c58c3afd73c2a2abbd69edade9d4cf3c2d45ab7056859ec5536903107bcce243c8f2e875a30b4faa59180c6e3366116c6de1dbca753256a97e0c361403369617cbf369f2df58aa907dc0562989ef9d7a00c9475", "e47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ff14d7fc37de90fa932265d82b56b477544485d0b71458024cfdbae8fd1d2d30ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457ea7c8dd4a05a6083e4a7ce3fc20cde94d430ec03cbfbe8017e9dc8ef3bce99a9"]}, "failure": {"scriptSig": "", "witness": ["4d09029cc360e3bbc9da84d7fcdbe1e6033d03b0303967c79f31333f856d952481dd23db9d92b0a89deeefcd1725fa4b31bcb34fcdd2480a42414fbfc8f196965b3cbdd8c04837a752f43095b370791b59fae7b70c73f7710dbb7c78e86a695a5ae058f06ba041302e86514b1954ec35c8a46964a12fc9debc3e584c8d1170b199d4b9bdfe90aaa24bae6030148e7167859e141f8b05e251c6b65f76f5538e3e10dbc35617266ba02bab2f2a92bc1570bc20b53ab86c8a9e9bd8b9e52c88e838354c6cd22d249b5a30a1fb3bfe4d3895feb98982c311a5ae5b8bd5a3c2a6095367c99997dfe56ddc47e146b475e7ee570df3ef2c20eedca37aa6ee3a12ad1c3b1d32f36aa2a45071fbc007335a465b5392e40ca1e5907ac32b4403ddf11ee8df1c7c083e37a04230757b99523ac78965ea065999542817224a06cb51f9ce7e879e3307bfc22d7ac2863626a7aa2c69e6b2ebda8181461bdc2b8b95537b8f2a6462832cbf1edfaba7bd4d7ab02aa2cc8564e48418be6b3e87ef060a554c53cfce4393b5726c618173c99faacebcea5b78a156a57c81591a530207dc9875fdf49c554501d15783d15b7500d0f44b5bd753658170367f51b58f79bc8d23c2a6de7bb1367d5927d337a511d99d34f0676f0c18aea8236f101c2a33252deeb314379c4ed048da249b536b73f368a099a6f7a6013db8308c4bc4dc3763d5b66a8cd7b721ea8babb9e34268ce49095b75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9b4a3f63ebc452069e6f153a09db4040a1a2fd26aff12c704ff589f805461b9455476c3fa5bfea733d4af800001099064b64c061f8e2c0be311cfe06abfabc5158e114954b29a1fe443083941979d23a0210cc324956afb3dcce424fb4eceefbefe4cc2cebe7bba8b4a4f82666342333b91a450af49acc0f1954b5763bfc142"]}}, diff --git a/txscript/data/taproot-ref/96f5f4a5b64b8e8462a72eb1d259066fce9fbe2f b/txscript/data/taproot-ref/96f5f4a5b64b8e8462a72eb1d259066fce9fbe2f new file mode 100644 index 0000000000..f408010df2 --- /dev/null +++ b/txscript/data/taproot-ref/96f5f4a5b64b8e8462a72eb1d259066fce9fbe2f @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701b01000000bba7c5fabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6801000000b62f87d103d8d78700000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac0e687c36", "prevouts": ["37c01100000000002251203261e4f5d874791dc168faa2b4a2c68848e71e1814a86d26b34f54a7b16af8d3", "be1f780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652a1eef91367cd6d74c4f46a0acdd366d2fb1ed04bd26bd49e3b512a0ae11ddb"]}, "failure": {"scriptSig": "", "witness": ["6a2f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/9700352a9f17c39165256df2f2f7e4fa2ec9de61 b/txscript/data/taproot-ref/9700352a9f17c39165256df2f2f7e4fa2ec9de61 new file mode 100644 index 0000000000..bf48af767a --- /dev/null +++ b/txscript/data/taproot-ref/9700352a9f17c39165256df2f2f7e4fa2ec9de61 @@ -0,0 +1 @@ +{"tx": "4431cfc6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40701000000be5f58b98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bf000000000206778f03fb9a7700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f871feb932f", "prevouts": ["fede3f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "5c57390000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "da7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936043c0126a9ff46f80efec90b265339725ec2187e176bf61e9c8112d2ff543febee00e627ce877dc7a3321ebc519bf09c5aac598ee9e81cf6d3228685de2d2a5f9a29f5cb7818ea23e4b491695dace811707e8772e99626d3237c076ba9a076d6566ba3404d3656bfd0df4a55f82c254cdba579fd51be164a5cd21fa2faf92a44"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9267ca3ecfb5dde8490070ee5c8f144d07948eba84ecbc5d8caabe33435ae9c3fb4f37cceedf64e5ab756f8bcf3191fe56bd549db8641e271ceb60581364e38eb0481d56926b359fa3e2e34471adba51fafc61fa70dea7541795bc082db9408"]}}, diff --git a/txscript/data/taproot-ref/9749e874bbbae2a0dce118ef7501ad135ea6cddc b/txscript/data/taproot-ref/9749e874bbbae2a0dce118ef7501ad135ea6cddc new file mode 100644 index 0000000000..5faf866590 --- /dev/null +++ b/txscript/data/taproot-ref/9749e874bbbae2a0dce118ef7501ad135ea6cddc @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c200200000056d3cc57dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf501000000a74f649460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270020200000040bd4f300326debf000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac82010000", "prevouts": ["1dfc5f000000000017a91480e36171416c0f598c1c20ba17ab3a3cf10a438e87", "34075000000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "95c61200000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638468", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb415f8a538f68d5e42651660e8feb349dcf42bebc9266cba18280404d93052698127135a2a7712dc4ffb0f490ef0a9e18994dae8053f69b06dfd6a349e2375b7df7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c777889b9c675ef10221c9e4ff4402fe24beb4f9fe9422385447f7b634cc13289910ef1376b2f57d6157bb9e8c31b4bd4b9d07432c4b683bf27102948dfaafec7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}}, diff --git a/txscript/data/taproot-ref/975509735c405d7f26b8bd4c00a32158c4f2911b b/txscript/data/taproot-ref/975509735c405d7f26b8bd4c00a32158c4f2911b new file mode 100644 index 0000000000..48cc061449 --- /dev/null +++ b/txscript/data/taproot-ref/975509735c405d7f26b8bd4c00a32158c4f2911b @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48f00000000d54e494e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127089010000004f3ee92e0308664200000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ace75cfe40", "prevouts": ["113b33000000000021591f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "14ad1100000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["4093438ed6da8aa0c53e5f73939acb7b5def70806f19c4bbcda28a1a09767df92d47a93e38f6d7349c99122a7c8d3236714cd472d0f69a7526a04cfcd596e6aa"]}}, diff --git a/txscript/data/taproot-ref/976fab0e9af7ab44ebc738f13b377d23ab763465 b/txscript/data/taproot-ref/976fab0e9af7ab44ebc738f13b377d23ab763465 new file mode 100644 index 0000000000..683e72ca2e --- /dev/null +++ b/txscript/data/taproot-ref/976fab0e9af7ab44ebc738f13b377d23ab763465 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700501000000f60e8805bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe501000000e6fd15b5017fe3180000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc6f000000", "prevouts": ["0eef110000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "673f660000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e268", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dd64d3df7c2a1d0f9fe00a8caf7064500c77c82c895dd028fc814cb494a55b73b88f998be5301314da3588cf7094ff0b779091d289dc1f0b3826508d93d51b78c2782374d67da9500785d400f7ef10ae84f146bbb568355094c68456b68f7a283b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c488a3deb56610eb7fa861052ad162bc8070dd60208b70c3d0d74ffd3dcedde8b0bd2b339cdab1cb752df7db1bf10e0fcc4b57fed7d380ff50ba3a0b4b018724b77966166a359aa5541e77c34a58fd9dcb7d88ef6e7e0cd0e140e1adf959d28b"]}}, diff --git a/txscript/data/taproot-ref/97703896dfbc748c76753b9dc807252baa7d17ab b/txscript/data/taproot-ref/97703896dfbc748c76753b9dc807252baa7d17ab new file mode 100644 index 0000000000..023d52725b --- /dev/null +++ b/txscript/data/taproot-ref/97703896dfbc748c76753b9dc807252baa7d17ab @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd10000000089808f898bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f9010000006c9d49b102408d97000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac25e01256", "prevouts": ["56c25f00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da", "91d339000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090246543e41f0b80bb5e83bb79dfabda2a0e5f0914e3b04d1b972c8ea454ffcc6472c7d3803a1b27f284f58e315690d55f3f2ef118ddc881d277edd79c9ad2e39ed87ff4df0b573ab9ae53ea9f7c078000d5c6a8613f551f9edb92869a8d4e9f869c5ae583c0707b077ed7d2bcf7fe8cd662ac4722259d8a855280302f629238f694f0b32b87cf323e16a36595056ae8f0f3581324145fd3af76a84237f54bb8f691f6c0cb8f056341fff9eddaaa2787457ec778260722dd15dbaed31323e10a41237c25a9e1924f8b9af54f4d658dc4ceafe1da8e051c6cf56ce978f81e87b2edf8d4381d8e4e74527fe097ef28385eb59cf1fc14ce1a7fb666c9199dec92095d001588bd69fa34dd48f4221746e4550c71b30fa3cff6d34f6db43e048ed090af0100b44ba90fa935005c99ce5a7a9f5de0e04f558a8d2bba9a4fcb70a36e0a74cf91d213ae345381d8838d0208fb9989ab8dddd142d8699b52af35a13ad069f2aa55e8c867b633f09cf3cd075349913b70eeb94b987a26d9f8f47669dd0c37cddddb8c7e4a7ae5cab3138fb8c11a82a04bb8644e63fc04e3c835ea3cbc546b9331fabb6fe5f1fc9da736db78fbe86216c407b27458af80880308dea2f7bd74340b4726c026fdc1e2db6c76e25b2587b31c8aff5fc3ddad37427fe41464eecf44b2433a3b8c3accaa9d2193c1cbf85c110abe637f10a15d9a5f8e9c19f80561306757098ddd232bd62d975", "807d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e83f9b6f826008f58b0a2f0424fb9eb1e858fa037e128d89da74120b3f1d2e75bf3dbbf3726cbcb24bd9ee344fc88539efd23f46f5d6cac68dd1bf47840d55ab8c"]}, "failure": {"scriptSig": "", "witness": ["4d09021e7cc742df1d8426ec5e0354302afc2ef28f05853ace24873f2f941bdf0062915adef0d02c8c07780c644235e9674d50817d46953398509cb0acc1b8a61814b912df44568a59537d3868039aa41848c17e46d8f2f57ae1966afc65c5de4479e6738c5cbed9a4361b2331f9f8000c0943dc8a4b8a0ce2660cfa5da928f892111b5b4413b74badf46607d41829b739602f4cab78f987903e11b3f919664381d50ed10a0a999fb43ee7fdeb8a544fb2c500eea770be304cc72871d07a7d716bb2ae2be06f96a582b8e22eecd12bcc0164d5dfba3036f4ece0abf4c2aa9586cba9e1aafbfdf4de3b1268a9f8ae402ff04751fb3daaf121f782327495a377a6b26f0aae35de31e5ce5f4000520ca237af6947548ef3b51a6d9aeab73c825258b91541aa3bd9d300a9ab5f682f2e23383414b38916b97eb9dfcc12efda370421c6030c98614ff908880c9f5008b40d32b65ae2615b39063b8949a28372420942b1306d1e0bd86ea60541222d6cddfef76ce9b2d5e381ae1713b88ba89d7e6466bce355257549ced269aa5feb24a68e8246119be7bb24761588996d7f3fdf256e24832fd831a218c227848657b9550d3cad13223fc5006aa79a2e794eb9d0f6819818eb16b5315002a3a4fcee4538a660359e702c908f953daa8f640f1ed615b5262bb6db7b709126ba18b8cd23be0684fbc2734f2c8447138962ec2f369c0e82ec8cf18446f3cbf0b555ee1f75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936039633ad3a04c2b48f1d44fa7c2039ba0cec5460a32c6bd9aee54d5879a3fc75035ced5e3ad5845cfafeba3c70c2f6d2785016db0dd7771d558e4afbfe1a1e9a3dbbf3726cbcb24bd9ee344fc88539efd23f46f5d6cac68dd1bf47840d55ab8c"]}}, diff --git a/txscript/data/taproot-ref/978c3a312999502111000de7dfe47b35516164f4 b/txscript/data/taproot-ref/978c3a312999502111000de7dfe47b35516164f4 new file mode 100644 index 0000000000..fbe7080627 --- /dev/null +++ b/txscript/data/taproot-ref/978c3a312999502111000de7dfe47b35516164f4 @@ -0,0 +1 @@ +{"tx": "23ccb2ba038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d2000000000276dbdddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc201000000bff559ce8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49b010000003499f1aa02d96dc3000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac8a010000", "prevouts": ["334c420000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b5fe4b00000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "3fdb36000000000017a914aa4a4e70b11f4eec4760f77206dc93b02350fcff87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "473044022074551d8f048a30da7c61f6f386676c51ab4071e1e30acb091ce1e3cb1f5ed93c022008742d772ee3b3bbc8a0b73f5627414852753fa6291f813c19dbdd9b2a4e63cc034104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "483045022100d8da7568d38772f9cae6eb86bb06ddb7e61128512f1bb9b44da900cbb612a10e02204f4e6dbc0d82a032a89d2ee6983db8f8e68abab0eabbccd339694217312accd8034104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/97aba204ef02b37a3627221d61d8e55c8a4e1c89 b/txscript/data/taproot-ref/97aba204ef02b37a3627221d61d8e55c8a4e1c89 new file mode 100644 index 0000000000..f54b510a1f --- /dev/null +++ b/txscript/data/taproot-ref/97aba204ef02b37a3627221d61d8e55c8a4e1c89 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4db01000000aa09a19cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0f0100000069f2c7ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270920100000099f9349f028e428a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487596bf447", "prevouts": ["72db310000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "266e490000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "02ff10000000000017a9146704ae21c886c9ded757e2b67d582abfc91902d487"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1052557e81dd342a2b41230b0afaea8d13945f509c20a84912c3e9d5b86183ac33720a820d9abe67125ff39f44ffa31194d8e2e56ac0de67f7992994257d70be631e5a3cd6e337eb252bd8d7a8d95e14a531fbfbee4d245debca50b247e512ad1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360b6966964f86bf7042b2b8d0a9c38ad26b592ca0cd295eff76ced7d8c125b4a44a68ec639edecebbcc441a95b015cfc7d67c6cfab51cac7643a880d3dd4163fb31e5a3cd6e337eb252bd8d7a8d95e14a531fbfbee4d245debca50b247e512ad1"]}}, diff --git a/txscript/data/taproot-ref/97cc85297ae928c35b606a80f058ab18ea5187d1 b/txscript/data/taproot-ref/97cc85297ae928c35b606a80f058ab18ea5187d1 new file mode 100644 index 0000000000..d7821ad56b --- /dev/null +++ b/txscript/data/taproot-ref/97cc85297ae928c35b606a80f058ab18ea5187d1 @@ -0,0 +1 @@ +{"tx": "615a5ae8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f501000000cb91e5aebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb600000000f9c80c9a0168a86500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac40208a60", "prevouts": ["8d6035000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "62a67200000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100aa13db2a3dc117ca3698a46b87fdd7e9a0163ce6c20e927cb59b6d3dfe23cc90022006549da89414cce206bc037e78f0df7acb38931a2bcc9ebfd315b3a27775e0fe03", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["3045022100a6d3758b22a0837ae6cab7847b42f9b3d95e3d24e3662bc06a0f91fb2dcae16102205f9c9b8433ea44fc8488be5413237a9a890224b6c74d618376c14520f04040d603", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/97f61b6d98c9ffe5ca701f864969608db86c81fe b/txscript/data/taproot-ref/97f61b6d98c9ffe5ca701f864969608db86c81fe new file mode 100644 index 0000000000..8c5df99bf9 --- /dev/null +++ b/txscript/data/taproot-ref/97f61b6d98c9ffe5ca701f864969608db86c81fe @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdc01000000f1553faf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41f020000004d967d93dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b20000000009c7a29f501e4bd6e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac9946af3a", "prevouts": ["8fa24e0000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "07ca3b000000000017a914a7d99db8790799e567017bcc9951f7f968dba70f87", "48721e000000000017a914a1b035f555fd87548264c3580a1f62a42acf027e87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "215d1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["385f9b7511c5668b97f134642d8641fe4d541f4939e6edef8c0a138595b38cd8467d4691a7de84fdb38ad659746ff95930b07135d6178918fab0bef05c859758"]}}, diff --git a/txscript/data/taproot-ref/982a43466eb400711eaa92486fd3a9b22d4ed22c b/txscript/data/taproot-ref/982a43466eb400711eaa92486fd3a9b22d4ed22c new file mode 100644 index 0000000000..be95bd3050 --- /dev/null +++ b/txscript/data/taproot-ref/982a43466eb400711eaa92486fd3a9b22d4ed22c @@ -0,0 +1 @@ +{"tx": "2bd6955703dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca700000000c8472f80bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4600000000d13b7096bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf22020000007262dfc601ef371a01000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac991f5956", "prevouts": ["846a520000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6", "8cbd7300000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "3c5a750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "2f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a46c7d29a0db0614f2e0f0dc0c143215db302e3c05619472d7444021c8cb05584a68514c5be2766b31ac79cb27b74c816d51537da76cf4fa244470107a7172f8ed6bb91bf977e9e370b444e9d5512cd4ec7f3694a9311c01272a4c1a167cd930"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d13a5469ede1e46cfc998c93aa642cff0bd84312ec04d003cb1cc577ad9b5d6a9cca9c712bd5dbc651b74ba1f32b079db60a81520e454f56bdbd9ff2bb730ac4a68514c5be2766b31ac79cb27b74c816d51537da76cf4fa244470107a7172f8ed6bb91bf977e9e370b444e9d5512cd4ec7f3694a9311c01272a4c1a167cd930"]}}, diff --git a/txscript/data/taproot-ref/984d407c9a0781d661b22c64ad915a555d3bf64d b/txscript/data/taproot-ref/984d407c9a0781d661b22c64ad915a555d3bf64d new file mode 100644 index 0000000000..5be41c2585 --- /dev/null +++ b/txscript/data/taproot-ref/984d407c9a0781d661b22c64ad915a555d3bf64d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf91000000002b06489adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd001000000a1a8c5bd0374ded3000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487df000000", "prevouts": ["ca847d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "defa57000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_8e", "final": true, "success": {"scriptSig": "", "witness": ["5a3f0c6d3d7d5ecbab1e157172e7fc37f17b55606503fc090ca8679a0ae29fa572e074a75ff44ee4c5988207d5a7a86f1ae241c175b6b126af2b8d8cd21b8f98"]}, "failure": {"scriptSig": "", "witness": ["371288ce6346cb7587f24781557107377254815a3e3bd489fbf22e2cf3729dcde326864dc5e270c65ee003af52dec3621437dbff5ad061c77177028380d50dc58e"]}}, diff --git a/txscript/data/taproot-ref/98500d46f789f6e67f2c3e2f6af290db2fc124cd b/txscript/data/taproot-ref/98500d46f789f6e67f2c3e2f6af290db2fc124cd new file mode 100644 index 0000000000..6fce4e6f54 --- /dev/null +++ b/txscript/data/taproot-ref/98500d46f789f6e67f2c3e2f6af290db2fc124cd @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127090010000005ac683e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c380000000038d3a0f20107b609000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87cd821a49", "prevouts": ["b65e0f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "d17c4d000000000017a914a68ade9e67dbb5e8acf044461cfd5bd8dcf592c387"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_83", "final": true, "success": {"scriptSig": "", "witness": ["a01258475bcb19795d0a725f8bb820d8094e9dfe0f9dbfb98fb7b7d8f4fa18acc75b50b3674fb8e4287b02b2fa9b5e7a993ad4a040674610b3531bcfc24be74183", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["9a7e25e9ce3cac285fe683d0fc7c497ff31dfd2437de629505cf8666201b958f2a2f6b715c348e215b75cc112a8d24df3ef57cbc52b7c3803b070f4e5eb7fa4b83", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/9886f8415dd6095f89ff7e519af7516c9b7dc352 b/txscript/data/taproot-ref/9886f8415dd6095f89ff7e519af7516c9b7dc352 new file mode 100644 index 0000000000..ed1a14c4f4 --- /dev/null +++ b/txscript/data/taproot-ref/9886f8415dd6095f89ff7e519af7516c9b7dc352 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5a000000007aff33b5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf83010000002d294e3a04d10a8f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748772020000", "prevouts": ["1e5020000000000022512038bab72068016f902ab3c55307335e21603c18bf2ed309a060537ac5746c9535", "8f3a7100000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360bc8d8ca652832e81193e5224505a6dd6e16def6e59730a097de7e2e8bd37573"]}, "failure": {"scriptSig": "", "witness": ["6a55616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/98bd202ec6667081b4a70e2f6b929af634ac6d68 b/txscript/data/taproot-ref/98bd202ec6667081b4a70e2f6b929af634ac6d68 new file mode 100644 index 0000000000..ae7914475d --- /dev/null +++ b/txscript/data/taproot-ref/98bd202ec6667081b4a70e2f6b929af634ac6d68 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7f00000000ec0883ebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf400000000af6e853204717b76000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487e7000000", "prevouts": ["408f560000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "d3d9220000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "2f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cb0eee81661f2fefaf772a8bdabbcbada52a1b0c3a58f1bcc7f9bb01897d4d674e9031d393e93ec4f3e9da8fc51e83b82f31256dd96ef4af94581a47eb5c67bc"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ca2ffab0cf338eb106c1ce200445cc90ecf54781f497edfad4f32965f124fa8cb0eee81661f2fefaf772a8bdabbcbada52a1b0c3a58f1bcc7f9bb01897d4d674e9031d393e93ec4f3e9da8fc51e83b82f31256dd96ef4af94581a47eb5c67bc"]}}, diff --git a/txscript/data/taproot-ref/98c6e09cd9cdc3967e01f4842102de38d4cda1a9 b/txscript/data/taproot-ref/98c6e09cd9cdc3967e01f4842102de38d4cda1a9 new file mode 100644 index 0000000000..7eeb4eaa0c --- /dev/null +++ b/txscript/data/taproot-ref/98c6e09cd9cdc3967e01f4842102de38d4cda1a9 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff6010000004f498f07dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c860100000008441211dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7700000000fe3bde330149db9a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9fec5531", "prevouts": ["f6da7500000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "dde94700000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "c6d94e000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e11f8d24c2756f16b9efc524121d49339a04fd56a536f956352850ed4d5018a4abf7205f064a536655663faab66bf2e716758d251376e4a55710082b6d7272244791bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f70487ae4384611f908618191b61bece567637059dee67ecc200d57fcc06025825f2fc2293577bab1371dd996050d2a4e8a01eb34ee2db6c09974277461b3e6691bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}}, diff --git a/txscript/data/taproot-ref/98c83bcdb5956bb94639dc29099871c76564d6bf b/txscript/data/taproot-ref/98c83bcdb5956bb94639dc29099871c76564d6bf new file mode 100644 index 0000000000..e2791e99cb --- /dev/null +++ b/txscript/data/taproot-ref/98c83bcdb5956bb94639dc29099871c76564d6bf @@ -0,0 +1 @@ +{"tx": "d1497db003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5a010000000ac409eddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1802000000b7a057afbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff7000000007c740f92045d5fac0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce5030000", "prevouts": ["d1a0230000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e", "d84b2000000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1", "d77c6b0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["dc4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c9da215fb1c7a7d8158d804bf09a7228ca7acab75bba3128cb1f7201ab6c755a6950266b78c1c1a06b0abf9d183417cba91a47bb46abdc469d8aa6f91cbf6a3fa39f866618102a4b08e1c83cadbbeb41bf3ed62f238c8432fccdf019ac45545bfaeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900453f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08238e917535475cf2110d0b0ae2ac5bf0f6bfd0fb66e9319f96694509bbaa8cb206d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}}, diff --git a/txscript/data/taproot-ref/98d122b2f88e6c5326c77b7a643d054909d0e33a b/txscript/data/taproot-ref/98d122b2f88e6c5326c77b7a643d054909d0e33a new file mode 100644 index 0000000000..c386df40f9 --- /dev/null +++ b/txscript/data/taproot-ref/98d122b2f88e6c5326c77b7a643d054909d0e33a @@ -0,0 +1 @@ +{"tx": "d666eeb702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b37010000005ba523eadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2500000000a14399b10167ff3400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac93222b49", "prevouts": ["60c422000000000022512036c493d82a149ae4f58587b8995f80246acaf3fa754ebc9da78117b68027b383", "5e4f2200000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368f01bedd13dfce24680e9fc996c53be28560337df17d0cea5b3b3f87d7eec203"]}, "failure": {"scriptSig": "", "witness": ["6a43616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/98d39d50572a07ce2b34b997b11f0801efe034d0 b/txscript/data/taproot-ref/98d39d50572a07ce2b34b997b11f0801efe034d0 new file mode 100644 index 0000000000..0b017c261d --- /dev/null +++ b/txscript/data/taproot-ref/98d39d50572a07ce2b34b997b11f0801efe034d0 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45f00000000788b972abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf02020000008b773e1560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702b00000000fdffac0001b6184e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8721010000", "prevouts": ["39113f0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "8f097000000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e", "d0ef0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "95", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045cf76285204aedeb2e654c32bdcb90a470f0de651bfbe7b8c0c018e8a9ed468384d6fbd68a9aac62cc0fc4848936fa6d465cb32a19d5a751074f74d9c4f7fb368ab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e461b72f89a2c16bf6a5015001c0ff63d37cf9f24e8cabb5685a98f400e46d3aadc7c8b3bda8f17728820267d55a41d559bf30f92e294931cb4fa644579829c4d4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}}, diff --git a/txscript/data/taproot-ref/98e6557609649d2edfa5303dc85da6929b3e46cb b/txscript/data/taproot-ref/98e6557609649d2edfa5303dc85da6929b3e46cb new file mode 100644 index 0000000000..e672ff02fc --- /dev/null +++ b/txscript/data/taproot-ref/98e6557609649d2edfa5303dc85da6929b3e46cb @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce90100000083239af2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ced00000000c0e951d4020615ad000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748700000000", "prevouts": ["3403520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c7f65c000000000017a914f0ed99a28545ab2ceacee60b5537a9e5c34fcd5187"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "215b1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["de02cad6e29bf921d2ee6d5b33c41a108255f36fa9623c61f0e96c86f42e8e441d21577181e866ea37b28e9ea5766de3c538d6f5ea9f67d742fa39b5267a9204", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/990480b357aeb905cfea6ff646718d101978e980 b/txscript/data/taproot-ref/990480b357aeb905cfea6ff646718d101978e980 new file mode 100644 index 0000000000..27bf20e18b --- /dev/null +++ b/txscript/data/taproot-ref/990480b357aeb905cfea6ff646718d101978e980 @@ -0,0 +1 @@ +{"tx": "566cc775018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bd010000004d504fd902a1db2f0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6ac000000", "prevouts": ["d76c32000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09028e545a2899d62cbe3b738c9c1ae244e41921f7a57ff172ba0f409d97b6073605c05a5c8dbb6c6b85ef68a2f28077c7807549d1dc086420bc40feb82128b69730aff8ac1bf8b1b7e0c1e9987facf95dd3497e94bbd184114141fe611f68f4ade7b19bf64e26dcb089e1c95ceacd5f47b50273b183a08ef8ea0d19ce5a0551ec7e1b3745288e5d762fc0159b86b547fb2c8d6f8b566133ce089d218d77b8e252c231219cfc6f399f3d653774ecf1f32fb724e5929a4fb0a2f90424ea3243d0b0561ff3f51bc130d61b7582d625173a9c36127d0c734024e6c646d44585c27677e53d611d282b734967cc39965c7b17135bb0fe6bf4b9d15a7f7b6ca6f0273513b939e013916201ec9bc7770b3a26a4d86db33bce49d9c99363c5bd2e05d34d1d7ee31f1dfc101a8a53b55f13b4e61e33cc48cdbfe95b0fc3623b554676e4677d1dd0eb3e0828f814b232e164ff7c8dd5e780d683032e9e78dadf1e7cf1045908b2a84e630df4186852a5a76fb5870f53c39edc5b2a8b9d76d617f65e9666d5a73e0040aa6ef3b695f10f5066465dd0da66eac64b0d90b90e8ba57eb8077e4da6189ae6be29c366e732b3d52e50d021b977f0bfc86985efa0174ed4366cd1b2fb147d33b3002e9725f1579da95fb84855e9be572b61474768bc26aa8b2713686c015d7e86d8c64d36d19334c9bb9e79974d8475bcb6a70d4a52a9acbda9699b37bdfbb05128574800f0a375", "7e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f08dc66ea0f9eb261a29c2f3d2c5e9ee1b32bf5c43d9ea273248408128efb172da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed3fb5b8f7b3afa290146b30788656a8f4c2497a65b1555cd50f1d702ddc8a1f8f2e4a14a40b0acbe20218e44481fe6660f01d2e0cf04e3bc8d4452bacd1080d1"]}, "failure": {"scriptSig": "", "witness": ["4d09028e619fb67d98b88e56079643a6388cefbd0ae51238d974d376ed217947350fa41c76ffca263f1deb415a94d111727fdb5fa30dbf49c1a2df8c5cc07be6ff336791ba1a7b551f651df744fbbdf78f904d5c830c1942a8e0d0fc99eeb6ae2a886a2b97da69611bb45021d2f983c92c6dae88adca3ccbf94254c909d1c1b9f98d34ec9662a78466c0178ee401ecf2dae0ec862e1bab220dc3090a375f040511b708d7a648d43254b8bb829eafe9945138ab81f11a4e5f257986711145a7723cf457bba6cc32a92dd8cb09666ab2af40f3351f8e278a2b2cccc13b4c32e6948d00367dcb320fdc4d4d03b3f5cbd19e757d4a3f799957b8d2d54ed0a4633ea7ecd33732b9d89b3de0354546c1fdc0b66cb5fb52b8993912e23cb204c178bba638700b5cca1f91388d476567eb17d65c741c8c6de9868a74289208cfa87c08ea9f6c7a4b0dd4ab65db185bf911851c17d9ba8441643afe9806a85cf4ac1fbc4efd1efff6be2e12c48b8854c39c6df838470a461fa92ad759e0c9092a5c9bc0ab5501812b8a7d3699a67d33686a93b927b8c2f1e1dbda70aaac733c7e7f5060e6286ef3ec8824626b9a0c23c95dbb7be30ab298e7d10d8cdf8ae383a7c06887e2584c838f7805abfb2ce81dd7d60665291c9846bbe7dea0ec32b132a8857db4ee614b1cfee778358448fd8035f4d35169bee34c22d4b9af843f628f68bfdc0d30f017f80df222a2d2eb0da58075", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93622dd8d97b260f7d47840eeb54422aa4324349cfe541c38798b74309f8db1f0cfe4e9bfb46536bdbe14fd1969523d98350611f9c0fc6236e31514e2d43f59e146f2e4a14a40b0acbe20218e44481fe6660f01d2e0cf04e3bc8d4452bacd1080d1"]}}, diff --git a/txscript/data/taproot-ref/990924cc189ea41b110bc4dd575460c49374f23d b/txscript/data/taproot-ref/990924cc189ea41b110bc4dd575460c49374f23d new file mode 100644 index 0000000000..ee35844d93 --- /dev/null +++ b/txscript/data/taproot-ref/990924cc189ea41b110bc4dd575460c49374f23d @@ -0,0 +1 @@ +{"tx": "6a76990802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd8000000001d4b6c88dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4a000000002f820b8201e0103a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac02034d61", "prevouts": ["b82721000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838", "cf8a1f000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638e68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363c1a09f721b671ff8e4281f9d7689b05138335bc6147fe0c6fcf3e4fb775b626dbab9fd6af1020d04f0143fc46ba56c091000bcdda14289cb5d3981fd1d5b5a654f33cd0b31c9bc4dfcaccd89caa263c020d1b70f58e7e0e884ce19a773d6b5f30b2981ae69232c3f6c5ff759e9ad4102f31f3fc5e7a3a4ffd34dce2e2e06026"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082df5339745586104756c1fc6d4b54e2b6a7d81daf8b03d1fc2a4a51881171d1a3099eb053c54d8f72c6d7331f9a1bb3bf1b628df692ad9b7eecd4e01f4a47bb5aed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}}, diff --git a/txscript/data/taproot-ref/99621f82461534b8907da50ed4c7020620244c46 b/txscript/data/taproot-ref/99621f82461534b8907da50ed4c7020620244c46 new file mode 100644 index 0000000000..d61aedc32d --- /dev/null +++ b/txscript/data/taproot-ref/99621f82461534b8907da50ed4c7020620244c46 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5a000000007aff33b5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf83010000002d294e3a04d10a8f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748772020000", "prevouts": ["1e5020000000000022512038bab72068016f902ab3c55307335e21603c18bf2ed309a060537ac5746c9535", "8f3a7100000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "187d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93606a629bc116268be1a17da3f53dc5135cb0ba720860d61650af2ab2ef2f0d65c919a726f5226a1e5e752df6df7fd59ca609863b1a6d095747bbc103e423fb93280858ffdbef3a81ff8eaeb69bf692b0617d2bdcb9145576d5843e6d9e5e1cb0c"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364394e80ff16ebdd0b8084d2a2ac0d9fd937ef7443fa96a9eeb67a82d8ebac460b6019e279bd309d4b7ea698da82947cdf92f55834d49ec05c8520ba423c90b8e919a726f5226a1e5e752df6df7fd59ca609863b1a6d095747bbc103e423fb93280858ffdbef3a81ff8eaeb69bf692b0617d2bdcb9145576d5843e6d9e5e1cb0c"]}}, diff --git a/txscript/data/taproot-ref/996fd99ab96f9643d5e5713a831995b17e7a3d6a b/txscript/data/taproot-ref/996fd99ab96f9643d5e5713a831995b17e7a3d6a new file mode 100644 index 0000000000..66948cd931 --- /dev/null +++ b/txscript/data/taproot-ref/996fd99ab96f9643d5e5713a831995b17e7a3d6a @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d101000000275cfca3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5201000000eb0037a702a3deb500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374879c010000", "prevouts": ["c22c3400000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "f5b983000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a86", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3b4167115de6998fecfb714975bc270adc7a6998f06c7ef8576e15f157ca8963750636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456619599a2832199ea7520e829579ac708ea18d94219cc28453716c125c7ffbf6b4167115de6998fecfb714975bc270adc7a6998f06c7ef8576e15f157ca8963750636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}}, diff --git a/txscript/data/taproot-ref/99d1d11e7c7797862b2f093aecd2482708213a46 b/txscript/data/taproot-ref/99d1d11e7c7797862b2f093aecd2482708213a46 new file mode 100644 index 0000000000..a3beb8349a --- /dev/null +++ b/txscript/data/taproot-ref/99d1d11e7c7797862b2f093aecd2482708213a46 @@ -0,0 +1 @@ +{"tx": "0b70bbbf028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43d00000000a3e895eadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc2000000003880c1b703b6b6550000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc72396585c", "prevouts": ["eb37320000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "98662500000000002251201b272935825fc7ce2e9b3b4937db8df8af2100736ca7626b35b3c53dfa94e3e7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "b37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936903d2a659aad03c667a6b873e21cea168414c29d3474a9880634e3e12e550e8c33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a368ced990ebadb111ebc3982eac7e308f07f99a9264ca6c949f56162916d7884"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93613226b488a95574c43053209c9e6fe8a3ea8bc7dade3cccc06ee2b8f5d857db7ebec8f444f9538a00b5e533aa370349d7181cba703021b72fe611d481b359a8e62055c347ba5402321504576f6c37d0c6cb1d044ee75df535bc9eec0560634a7"]}}, diff --git a/txscript/data/taproot-ref/99dec7b1a061c754594c315d70173856ee38ca53 b/txscript/data/taproot-ref/99dec7b1a061c754594c315d70173856ee38ca53 new file mode 100644 index 0000000000..3255ea72ac --- /dev/null +++ b/txscript/data/taproot-ref/99dec7b1a061c754594c315d70173856ee38ca53 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcf00000000a7f3a3d603442a200000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac8380d953", "prevouts": ["05bd22000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "3f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6cc0ae96455d40102dba07421af533c8bf9d94b7db74d6a9e1f391a278928dbc06da1f6599d7e514a71ffa8a2afff73792fcf1df1b953d2196d009aa835a52703985aa46dcbff8b0495de750bd1afe74a661312f7eddf1146199ee1ea8c08aa"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365ec1e7079ff1f62dd2e6a74a9c34f414c9b037a2415ab122d560dbd709f7ca5d76a51402fc917873b776340a7337d6d9d98f28c38cbc7d5e61e594cad9a2611aeebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7acea811edfde1d836b623c2094badb4ab8bc7795b2b49da5506600222f32ea3fbd"]}}, diff --git a/txscript/data/taproot-ref/99e6e3dc68bf0e9973d9cda82f1300e98c4d58a0 b/txscript/data/taproot-ref/99e6e3dc68bf0e9973d9cda82f1300e98c4d58a0 new file mode 100644 index 0000000000..4fe23a84a3 --- /dev/null +++ b/txscript/data/taproot-ref/99e6e3dc68bf0e9973d9cda82f1300e98c4d58a0 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c487000000004bc7f4e2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb6010000002fc980f20145803400000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1c40ee26", "prevouts": ["9dc3410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "deb0220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a4", "final": true, "success": {"scriptSig": "", "witness": ["bba6cf312b17f70b0bf3bc8f96ffb32d469389521cd80abb773d5515de765e8cdb26bb39e2ba5dcc75b3f41dd96c0f4316822d0a5ac3509fe638ea458513a7d482", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["16c56447a1bab4a3de363c353c62237dcb621bf6c2031fb095b189e1bd5dc305a360e5a87d1d296ddf0f99851111bb932cb3098f416974be701f82c9139e7786a4", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/99e8319b516c140aa7badd1e9ef03d1ff1c3bee0 b/txscript/data/taproot-ref/99e8319b516c140aa7badd1e9ef03d1ff1c3bee0 new file mode 100644 index 0000000000..309be8244f --- /dev/null +++ b/txscript/data/taproot-ref/99e8319b516c140aa7badd1e9ef03d1ff1c3bee0 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1300000000eb0c7ff9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9f01000000c78597bfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a020000000af4cdaf04a802d1000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76dfb7e54", "prevouts": ["501121000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "7beb5e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bbba52000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_91", "final": true, "success": {"scriptSig": "", "witness": ["153e3dd9239b5f948de197bd87b90c21bb2ea1083c45afcaa3dbd6117d0a8af737c543a7cdc3de748bc03bcbe2543895eb30f5c8fc77b9b91aa0ea93ac7e61d7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["09c03bc8aab785dd8bf9d4f391eb0f2376edb2e03fb72f4f04fa90b3e86a5045c3f38fd5030a4d668e106bd49c3e4bf7c07cc461f0190578ccdca9fae0a1ff5a91", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/9a11c2fda7b9c43e2b7720bd72c00e2503c9dd88 b/txscript/data/taproot-ref/9a11c2fda7b9c43e2b7720bd72c00e2503c9dd88 new file mode 100644 index 0000000000..4a8a51ebf6 --- /dev/null +++ b/txscript/data/taproot-ref/9a11c2fda7b9c43e2b7720bd72c00e2503c9dd88 @@ -0,0 +1 @@ +{"tx": "d181cd7103bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1f02000000538bccd660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704f0100000003fd78e5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf30010000001a08da8c020568e0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ace80c3a31", "prevouts": ["725f600000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "3713110000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "e23c710000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93651a4b02d6d2d00f96ed624458ca7b08560a5ba04522c3d997cce9fbca7ffe3f57e5a3ad1358e4c8217aebfca59af3ae3bc6dd2d33fcb7e66f52e86370eeb61bbcdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045c27b7e516a1b3919c0c2aae21712d1c7c40c32040b64b5fd9dbe249132a2d861ab0398bc4828dee75def1007ce877d708ab4ca86c9734bfab291d4bd05bae3eec1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}}, diff --git a/txscript/data/taproot-ref/9a309f12e7243094d23099f5433d19602252797b b/txscript/data/taproot-ref/9a309f12e7243094d23099f5433d19602252797b new file mode 100644 index 0000000000..d662de8fad --- /dev/null +++ b/txscript/data/taproot-ref/9a309f12e7243094d23099f5433d19602252797b @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bea00000000ee0a502560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fd00000000d7a42f82dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b80010000009c57242704fe4b5500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48746e08936", "prevouts": ["2584250000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "ec9f120000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "64811f00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93629d2c1e655ac438f3db70c25cc3a59e74790bcf64cc75b6e948452f3070fd7888cf2788b31c6a31a23c8dbe6ff03f22a1631db08af18d9e87ce7bf14c25a50385e7270ac6e52de2effa1ad4f1d7cc04618f1a83be30b0454843cf6016e9cc3658f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b733bc242514943bdb2f3483e8eeacfc336f33bd44d397c28f9e3357b5aa8100b15c6036a676a492a4bf737064ce6a21b64de8ad159d3b2e60d879468caf8957d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}}, diff --git a/txscript/data/taproot-ref/9a89b6f3139174829b27ab6ead21acbf001ee2be b/txscript/data/taproot-ref/9a89b6f3139174829b27ab6ead21acbf001ee2be new file mode 100644 index 0000000000..32411aeaa9 --- /dev/null +++ b/txscript/data/taproot-ref/9a89b6f3139174829b27ab6ead21acbf001ee2be @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ad00000000d70bf3c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b08010000005adde9fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b60100000078ddf57604cdc96f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787521e713c", "prevouts": ["6eb8120000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "686e1f0000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "02ce3f0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "d27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362aacdbaf7feb2ee84db2dc99af1e5f6e1450a5c488d9b9b44f0760fa1ba6b92f9a9c5d9290705897ef911507dd26b72756738dae23c9379fd676f365e52e00fbc5e1171eec0a28263e9818d2dbd976f4b8066e50dd8906a411b6a9dd47f52980e39f192d4dec24b48e9231a08b7d2e64fac2040aad69c16c1d9eedfe5fb62ebc"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93621ef10389913bdbd846df0d9639979edfa3f7c76677006bc1a57e34b3956825b9947182c2cf442266d627de6569afbd254a849da3e2d989b935a76fec010797d33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a9b801fc18e2353a9cd4de337bb33433fbe6225e21bb8b5572b0acaa50d11b7f3"]}}, diff --git a/txscript/data/taproot-ref/9abdf13e2635797e12d342e2dfb31a9c80d0edd9 b/txscript/data/taproot-ref/9abdf13e2635797e12d342e2dfb31a9c80d0edd9 new file mode 100644 index 0000000000..24c6bed713 --- /dev/null +++ b/txscript/data/taproot-ref/9abdf13e2635797e12d342e2dfb31a9c80d0edd9 @@ -0,0 +1 @@ +{"tx": "0100000003d15657a619affff084fc6b1bc2cdf5e85e399bb207d84ace710aa8effb82232f0000000000378eeb7906f5bd527bde63f7c45daff54c390a64a59dabeafc8078a9bd0a050f54db6b44010000000038906fb3492909e056fa5c0ef2af542be68aba07da39583e95b43e24484150891b1d5323000000000077e0c98802d0235951380000001600146d764276c66fec1127e5074db5bff3aa6c52553358020000000000001976a914b2c48f336848c91e9c274b4615a238e127bb7e2d88ac40000000", "prevouts": ["24977ad110000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "1ad1d66814000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "14cf091713000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_invalidcb", "success": {"scriptSig": "", "witness": ["1ded90332935ec88558f8584ac1a3e9b0da6155cb557dee011e261e061c7d76f37a6a92adfedf2fc3d952ec6d1eb50248b6051ffd6e84fa3b4b0de26206ae46c", "20159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717ac", "c0159f9373f8b28a67627a464ae370e1e712c79726144a1a48958863033f16f717a00074c7e8df7fd91f9df9f350398e675f9ead7758f02aef75359e3279a8e0e7"]}}, diff --git a/txscript/data/taproot-ref/9adf5a63b8158c84d6bc327d0b1ac1b5964a3ac4 b/txscript/data/taproot-ref/9adf5a63b8158c84d6bc327d0b1ac1b5964a3ac4 new file mode 100644 index 0000000000..2d205aea92 --- /dev/null +++ b/txscript/data/taproot-ref/9adf5a63b8158c84d6bc327d0b1ac1b5964a3ac4 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc8010000005c7f094c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fa01000000ae244f4003c3a18000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76e000000", "prevouts": ["182d500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1323200000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "437d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682ab6dc69837b4247049ddc8b7ffe2c3e23edfe00b3a8b82ed1d42877f84b2a53d8f160074737ef82cfbb3f905f5039c6634e29d53352416ee52711c9b5e3cc1cc59ecfca53d850b1637d6273d8700d7dc702fb5baeba7c0d1778aadee75959b"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364715b474cae40c256682884c4b9f99cc4a0ea50646de4f5d3b66b0a6d8a5bfae3b3e543c1be24a694e5b6685838ec47a730681350c8079fce99319dc90d9ab403d8f160074737ef82cfbb3f905f5039c6634e29d53352416ee52711c9b5e3cc1cc59ecfca53d850b1637d6273d8700d7dc702fb5baeba7c0d1778aadee75959b"]}}, diff --git a/txscript/data/taproot-ref/9ae58507a65058e0fe31de871c7a34bab5415ae9 b/txscript/data/taproot-ref/9ae58507a65058e0fe31de871c7a34bab5415ae9 new file mode 100644 index 0000000000..eff3ac5589 --- /dev/null +++ b/txscript/data/taproot-ref/9ae58507a65058e0fe31de871c7a34bab5415ae9 @@ -0,0 +1 @@ +{"tx": "5d30506801dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0f0000000053f538be04083620000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc741000000", "prevouts": ["56d222000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ef7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e83a19147259427e9ccdbc6f2b8e5e1f30c562b83bf76874eaaaea903675d8ebeda91d0eecd1ce224dc9f5ac46de57cb81ed44d1050e451131a9df60f58ad735b030008666d4260a12bee868d13ea953ce9c9319f2222d8e8469ea0b912b8ceb"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936547a4bbf5868550c6b5042f98020e4d4cbb7f37004221482c8f9e6bd9702217de4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e87a25236fb2b0caf4a960afecbd8538cf949b3ef5b854c8fdc156128073078e11b030008666d4260a12bee868d13ea953ce9c9319f2222d8e8469ea0b912b8ceb"]}}, diff --git a/txscript/data/taproot-ref/9aece0f0260af3664b7ed391226bcf127e9fd163 b/txscript/data/taproot-ref/9aece0f0260af3664b7ed391226bcf127e9fd163 new file mode 100644 index 0000000000..4cf4a36c49 --- /dev/null +++ b/txscript/data/taproot-ref/9aece0f0260af3664b7ed391226bcf127e9fd163 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3300000000fd918ce48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dc0100000057bd5083dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf300000000c9b3ff710361ce9d0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961aad1f34", "prevouts": ["7dc71f00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "a33834000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "59974c00000000002353212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93690527042795390690a9a4478775b8c816aa4ae99e8fa73671741082894bf9ec6c99cdefdc3473a619e12778c4cd588646c716d59e86e999fbd28728a66c3e7c6a7d0a3f3648f0d829df7cabdb8f0af96ecc09ebc190c461c6b5fbdc9f87abaf73acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004596d09828da376c7d22ded5a4cf88780a729051831fc4ab0b26d0bae49a473f5539caad535bb8d51429d9c94edd44271a241bcdcdcd941caf815b31d1e73ac1400dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}}, diff --git a/txscript/data/taproot-ref/9af8af68c2f18bca7d94dd8b48ce8692c89ffb04 b/txscript/data/taproot-ref/9af8af68c2f18bca7d94dd8b48ce8692c89ffb04 new file mode 100644 index 0000000000..ceffc77630 --- /dev/null +++ b/txscript/data/taproot-ref/9af8af68c2f18bca7d94dd8b48ce8692c89ffb04 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45301000000f58a3dee8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44100000000b63cad77dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bef0100000079a1743d0344399800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df979722368987ea000000", "prevouts": ["8b783e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "624c37000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "3919240000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sig/flip_p", "final": true, "success": {"scriptSig": "", "witness": ["3a32644baefe3ac33337db5680b91ada91bb1492e89948fe78283f042ee27a18f32a7e077dffd72a2dfcedb3c11a76ac85e79a08a4ac88d837c7474d59c03c5e"]}, "failure": {"scriptSig": "", "witness": ["2d2a002c59ae4f1ad1ff62e8b28787be77ab902f4904301a256bb931da009eaaa0b17b1e971da1628442ac83d6d8d8f1e97b9b3bc114b901a069bacb649de84d"]}}, diff --git a/txscript/data/taproot-ref/9afe6dae1af7cdc07ef615de0c3d2ebdd4f68c15 b/txscript/data/taproot-ref/9afe6dae1af7cdc07ef615de0c3d2ebdd4f68c15 new file mode 100644 index 0000000000..4ad1295e10 --- /dev/null +++ b/txscript/data/taproot-ref/9afe6dae1af7cdc07ef615de0c3d2ebdd4f68c15 @@ -0,0 +1 @@ +{"tx": "dd3b93eb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4350100000001cd7ca760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703001000000c72c4ce603c01c4200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787eb283c35", "prevouts": ["7397340000000000215e1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "621410000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["4365f1bafa45f9923db203de3ac8ed384e7a9fab5b5ff70682d274a571a3cb19c273da9aa6bd2b34be6b693eaba26bfe7e2cbabd3fb79f0845a0a5727bf14481", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/9b42d222b18945ea05823e8a6dbcb0d54a364700 b/txscript/data/taproot-ref/9b42d222b18945ea05823e8a6dbcb0d54a364700 new file mode 100644 index 0000000000..886de2acf1 --- /dev/null +++ b/txscript/data/taproot-ref/9b42d222b18945ea05823e8a6dbcb0d54a364700 @@ -0,0 +1 @@ +{"tx": "55f3a2c603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5b010000003b874fecdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0b01000000e740bcee8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4580100000096508f98011c849e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac56000000", "prevouts": ["4ff72300000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "9d0f53000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0", "b9943e0000000000225120beebf2e29d62b55aba368e7e892512e69e2ef37d942bd7f6bc768a8958380305"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e40618ced8556b537519ff4ae76117678a5ce8c97b03273c29fa3282403423df211491142a38ebb10a24e36aadbe0cf227dedfd0966bcf56b2aea8b33dc3fd67f"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a0125ce869dfcbad463e82b09ee300f32db0e22e1716cfd6fb616cefb0ac74cc40618ced8556b537519ff4ae76117678a5ce8c97b03273c29fa3282403423df211491142a38ebb10a24e36aadbe0cf227dedfd0966bcf56b2aea8b33dc3fd67f"]}}, diff --git a/txscript/data/taproot-ref/9b4d35c34d31ab2b9e6a0becef710c9b00ec976c b/txscript/data/taproot-ref/9b4d35c34d31ab2b9e6a0becef710c9b00ec976c new file mode 100644 index 0000000000..1961fe426f --- /dev/null +++ b/txscript/data/taproot-ref/9b4d35c34d31ab2b9e6a0becef710c9b00ec976c @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cd000000001739216b015e94010000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7968b000000", "prevouts": ["36f40e00000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09021d0e349534330893be62c43bf685af661b5deade0e796f154898d44d7530c5ecbf482869a96c1dca3c401c1cbbac55725c36d42e27620af71b1c8469fc7227e96b95218e4f8e8b0bff434249370ca6e8497f5302b1485f8ef61d3da1f0e788f1fff219d5616dabf4995b68f7ca0704435d99993c0f67b7eee5e0d2bbbef538f606c575d54143153fe24c3290e15022f0bab428fd67dc89580af173da65143a37c4b062f8c60dce2f4bf2d26c127db203821c357c72df8863193fd8d0de1b762b872be6e9afe9c3cff474d7fa825bb5ccd3820680794df6712957331ee8f1d0e090a31ccf0822418061ef32bc2db6daebc9c051ec1f72fac11905989a081c0565d61a71c95e4a0ac2695d7f10455117ade868a109f8713085ba1c5537ba85560d4ec944acc9ea75da0561e3ccc91bdf3fbf47c143ac4fe74a8eca893c2e033cb32e49c91d15ecd9ac9ca791fdee1a49a61cd1b936b081d9b60e8cb89a117aa7a7ccb67a461638fd0fbcacdabf01d2d6c0ab7e2563334f24397ba0857dc4da22e9528176cf818553d368eb6d209520140f06827d86094476a290d5e9ac05d752e58e06886f193352fbd921ee45cd32c6e62ee8a297a1741da5304f537bd13f8b1b7ce9cf5079b649cf50180902bfbebf85fa66a5980032331234f62e1dc8aef84c7437bde84b72b1776f861c9a2ea937bbdf677a00f225e5befd2c34fd67686f1a023ab4c12bcb38c94e7550", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ec3e8652ccdad0df59b5761f2ea097b8016af2709c74f31f9ca84c9f99f70f610826552c6add4a61cb16ac7f3706b11d0158c18b61683494ca90054287b9ac7bc2fd9879a2ee2ae7d76224c991edc718b1729f7f1922f570a67a21926d2cc48d"]}, "failure": {"scriptSig": "", "witness": ["4d0902883f4eef938c9952b2f2c72ff143ff181a42a1d180e3b595395c0e98240fc25815fe095bac959a256a3d4a5914c9ff25b548addb7097982fecad7ad4b54a1f3b1f3e5c0267b73ce9b5732c6a8f083896e98a34b05b7fe4bbc9b178c8b5c15ae1071a244e87e38ec6c5afd208d5ff4aed4c281f3c39a3f2b14103ee4bb9948b4e9e650c413be5662f0ed9340211481065fbca9b6e37fe1422930f29e070c88ef2fcc75a3775073b09208d1dc60cf4337b8d7402588a8eb6af60226281b8f1feba0d961eeef878b46b4bb0c20130145cbaadcd9d52204839700fb5b5135a3e75c50d675aa21f4412f71b4699f3f846574db63999a6dafb5956c967ec6ba80e3aa92de521a298fe901fce2e0fe2a0d1835b3cd42a05f420dc02824704cbfa65a59e0b62ba42d0b68270be62376b03583635db5cea65fc867f7d3f67f3921153b79489596706407b1190dc95c4043c94766e9026e990e5e9eb0e2ff91c00e3c9dbfa49014c99b1b956ad4c1bd8928bf1ee741a336af4d1f8416874904e6fe32e47ae88bbd07df2a802fd1fa61b7c7c197091ade9e91c7fac65f2cf8b9327293fd6c71922ecdadec083d48dfee6a1a5074468bf78f2b8df60d045f1b6b5ad84766dcc07a4c16e485e59d63cd8494bdbcfa0538aeeb932640ed257b3b8ab501064dec04086971fe269948f6f81e797cb5ded2f881504b32c82c46205f36e1f910ad44082f0b3f7b119172e1a7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4faa718416d21ef008df2257ef512539448f5ca520db3fa3c7b8aa919421e6092eedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}}, diff --git a/txscript/data/taproot-ref/9b51c6d0b56ce78a3dd7924a0c74626beea4b529 b/txscript/data/taproot-ref/9b51c6d0b56ce78a3dd7924a0c74626beea4b529 new file mode 100644 index 0000000000..74b8691034 --- /dev/null +++ b/txscript/data/taproot-ref/9b51c6d0b56ce78a3dd7924a0c74626beea4b529 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce00100000057728689dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb2010000003f48ebf8048c75b400000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac751fe021", "prevouts": ["016e5600000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945", "13e05f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_81", "success": {"scriptSig": "", "witness": ["e13295c7b6ed57a759038704cb8ddcf0808fe35c803fc1457862f9900fa469f9462a0315d3c3880b499fb50096b0540d80f23bdc98005da87909a8928753d08c81", "50638f7cede42607b05e090bf1ac6d41a5a84c4929cc25c2da17c34d977b4b42870d7946377dd689c4c2e096a153831cfd9694f76933b4d225852f5916897f0d7cc071fef6cc91a660fc5df03d8e86571f931d7e613b53ae5550b59a1715b187cee2b4bf1bfc2282fb1d0a7182090163f183fcbe241440c03ad1c789151ccfeca21deb266a51c17c4a5d29dc79072e084a3d729721d5fb86fd35373f277a2862408302635620f322a64d1440ae5ef50931f8de8969250859c9115e28e24943326ce02a365d7e5870490aa8df3a685497e5e7272091d09038541e1d919362dff3971dcab173b3572692cf2c5488ef1b1ae79dda0aaadbb0"]}, "failure": {"scriptSig": "", "witness": ["9aa7cf253ec29d548228a588e981555279ca42d5b2479bb0f774c6b009fdbd4cf127341e4d00b02b977f5dccf48587fdec0c07e373343a22447782773da7898381", "50947eade5523082efb2526fc1ce6790501a5ea02eb097910424f44142541929dd3a910215affd9b3a4c1c2e8dc750c9aa1a48c8ded93fc8fc6bdb067381b3e9ead203af6f47d3a5b7862e4f3deab7dc6edca0afe1ead31013d57e6be66830ea914d9e47f50bce83d6adb3f391da"]}}, diff --git a/txscript/data/taproot-ref/9b62911307d4c57e65b67719613737ad5d45433f b/txscript/data/taproot-ref/9b62911307d4c57e65b67719613737ad5d45433f new file mode 100644 index 0000000000..7a924109a3 --- /dev/null +++ b/txscript/data/taproot-ref/9b62911307d4c57e65b67719613737ad5d45433f @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21010000000ae3668c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127048010000008de810588bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40d00000000fa4dd06f0403f6a000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870d92972e", "prevouts": ["96975b000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "3597120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cab1350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "47304402202102236249a2c7ca5dbf805a527d929f15d385667c6de48eae33debe18c14ab102201f0d31e8944160dec4c98499ab94f0467ece919f9c83bba062ade9b72261ed0603004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "483045022100ff0f8af7011e35ce0bc791225830a59fd29bc471eb2074beb42c51d0e79a241a02206273dfd59e248dc077b982e88ca651bac26ae2a79bcbf89b7d5822c6e0cbf5800301014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/9ba6a6cf62c5826ffc6fcd084371c29d51f194c7 b/txscript/data/taproot-ref/9ba6a6cf62c5826ffc6fcd084371c29d51f194c7 new file mode 100644 index 0000000000..162fd32c8f --- /dev/null +++ b/txscript/data/taproot-ref/9ba6a6cf62c5826ffc6fcd084371c29d51f194c7 @@ -0,0 +1 @@ +{"tx": "d97d1cfb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46601000000d2c0dabe60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703900000000021a8ba701f3112f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964a030000", "prevouts": ["4aa7410000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "15ab0f000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "5a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936648f7288da451c6edcb2ab904ab412d7719851ebe4c732831d3fb8a1e081c682db79ef349d3e4f05529a42271c6cf93f8e06fd8991a688edddf7288612a03eef8b5457f6f65490151d40d3d05d55f9c92d8dec73c7aa55a79aa7c51354918829c531ca70e78518003474f611c07657b0808402a053b744a80e6cf25146bdf24b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367960d7b37dd1361aee34510e77acb4d27ddca17648a17e28475032538c1eb500da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb4949da8d2968254411aebae49708200d0b19b59a844616925b107b397a8b89bee9c212f1ab0dfa1a42522b9ca3467b009d36f3b841f39cdc4da4a0520ce4fa4"]}}, diff --git a/txscript/data/taproot-ref/9baed9539fb0ad3446fb36b9804e562244aec18f b/txscript/data/taproot-ref/9baed9539fb0ad3446fb36b9804e562244aec18f new file mode 100644 index 0000000000..3345d158ec --- /dev/null +++ b/txscript/data/taproot-ref/9baed9539fb0ad3446fb36b9804e562244aec18f @@ -0,0 +1 @@ +{"tx": "d4ff116302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0900000000f64f3be68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c482000000007d0525a00173622a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d17e085c", "prevouts": ["e5b54d000000000022512074d6c61045a03724ef8fd881d073e11ff568ecf53a923220aba8b11cef73942c", "fb75340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b274c5efd2c9897d6afd12185a48991ee50489712c76155d50b07e4f830953e"]}, "failure": {"scriptSig": "", "witness": ["6aba616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/9bb0ba96392a718e713162631e2036c2a0708ce2 b/txscript/data/taproot-ref/9bb0ba96392a718e713162631e2036c2a0708ce2 new file mode 100644 index 0000000000..49a6dda733 --- /dev/null +++ b/txscript/data/taproot-ref/9bb0ba96392a718e713162631e2036c2a0708ce2 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fa00000000486720d6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb200000000fa9d4aef03b15daa000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac24ac6649", "prevouts": ["0aaf3d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "804b6e0000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ac7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f6e1ab16ab4bc20af15f35a7f6b67f82a67b85511624b76e02698979773111889f9ef29ad3e74b34f129235a64deb65fb580c2718ff9462ea3ca43b3a4f56170fc485b911b91245b46c320351c8e1d13bb30ee22c3f953d2224593bd4b5088ca"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93621ea3e1176867e27a76e6bfe64b0f928a3852297448d22c2e9793b9d6d23c8f132d0ccdc2029b00ec7048abf887bee187f4acce1681536a58b887d4e93139fe875006811b549bdf6e8160f30212dc3199b386e615ec459cd6a9a101291e049b6126490c72a5b15e8927e2896ebf8102d665fc08f8a92e888d3aee8fbb5026d2b"]}}, diff --git a/txscript/data/taproot-ref/9bb98651acde18815c952146548c472023a22072 b/txscript/data/taproot-ref/9bb98651acde18815c952146548c472023a22072 new file mode 100644 index 0000000000..11a796c716 --- /dev/null +++ b/txscript/data/taproot-ref/9bb98651acde18815c952146548c472023a22072 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3c010000003492e39adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccc010000004291f994019baf2100000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac92000000", "prevouts": ["4ced810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "102e5100000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_3a", "final": true, "success": {"scriptSig": "", "witness": ["51b67b449e083bbea12e4d732039d6e9458dbca041e8cdacc6092706154f23c9721b41d26d738a8a206906876f5c36b69047ec883c49b62b658f866fc0b8a68e81"]}, "failure": {"scriptSig": "", "witness": ["a7d37dfaf176d232e348a4bcdd544f0a0e684beef3662be4f81e6e4f61e4951eaa4b3a294d8ae5287681c3f14645099d0d360e9c6fba489d3e69ae11a40b6e963a"]}}, diff --git a/txscript/data/taproot-ref/9bbe3f1ede4caaf74b619e6e82cb6b6f779f366d b/txscript/data/taproot-ref/9bbe3f1ede4caaf74b619e6e82cb6b6f779f366d new file mode 100644 index 0000000000..e815622a6a --- /dev/null +++ b/txscript/data/taproot-ref/9bbe3f1ede4caaf74b619e6e82cb6b6f779f366d @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1200000000f79331a1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1c00000000af1cfe2a0186b90c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d3d29e43", "prevouts": ["46751e0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "1b83220000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09028511e012394139000bc474cbba2e91828002ee1683d62562f44cbd4305dc55106c19ef457daf4470ac49b68596c0a2472a1ff336f24ce431dc440b5cac5c64c7447544ab72369925e9fbeca386f6073c0e6f2aa87c1227b8ef450abee94fcc89f71c4f16193249d67af091917262ecc40f88e9f2535ad72f7d8c2781628c4c96fc7ed17c77c4879ed77fa4ee71a86dba366a6a2720b1bac55468b05b8751ea1aef16a096ac7b60f13294523cf0891ce5c9b7f32888d4b33eb973e0a222cffd75eadca880fd2238f2a12fdb95957f399fbd0208d403eca733a4d4646be9e17e3bdaa17c64af6397935d237e49a083ea46b1b8c27c952a6dfdb13cd9dc4341e9e33c336f9f61ee332361de5cced250a8033e13eef8a1b56886f5b4e299e9325f391a676b48b10b561f5b9005b08dd2c97814edcbe1d4d84455479a477dfacc3e44b71c34de0641a6821f1a2d86cddac537251cbdaa0170d14d0e6dbbd725aab806c49fa41979ee22c893d4ce2c3c816507207dd248ece7a85aae1b10fa218488b47a60747bf95bb2e5b8cb33c2587b484238b645f2717f0b6ac8a55409b91fde74f7338e8ec911baf31aab2bd1749765a9a94c9f2bd01f7892fb54d49d868b3270a3ae5a1ee577e0f98b9d484bde5a4ee561bfc6770fddbf62c7e2a175762d43ae654e99a87450a72541152aa6c1b88d0a583aee33d43c1475d2ccb788aa18b1ffcc6650464ed71884de75c7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef60611d2eb8e1764aafee2de1c0cc952281cc47e938078f6f5fa59ba73f89875941b26b476c022edf868776977d31e53e85212ba204fe552062798c457a392dc1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}, "failure": {"scriptSig": "", "witness": ["4d09028af4cb89c337cb0aaa5e26b169472571b8797a849d19cc8b3ccf89aabb9c7fefcce3d209e0ab43f3fd293014b9837a7990f53d56712165af825c31986ed9a36f9162b63e97b1849e8761b5d6939228aa1b0790de195dc963bf55aea2346fd9c8ed8be829181f769ff476641f3d20c6a18efb4a55200a76b3a25c683dda241312071fd4d9099f48600f73a56c6d1c086baa41e762fa1709481025f26ef886a168d5094efea51fc571b4db67c04ef79df0b80fb7ec9631ecedc0cd62f0045ce17983b05c9becbab53fb6249d0e39df7157fe0867a8a7f133f0fce9e1302d46e6e4e592c045cdc56e6e78fc26404db05cafc8717ff55bd5e9687fc03d35ffd7f576301da6fae93ba6906f7cfac82f8d2845c1166f34f3de8fbdd8f64f9ee72ab41a40611fb637bb3fa636f7be04ae26ea4fe645a72fa9f25e89baba9550c7a2078f1df10bc8a68b0b17c0586c9b5c0374c4aa3735a9af48b6a5e3a2e8d145e05b6c71c077471dee5b0532efc99645fdbb26f59c5bbfe0cd930e5a258f1b0146c33f67d12ff2b4271e6a3dfdb1bcbde181d93d90c3495519afc96dbef113e60e9a7d0661c1463e0dc42b515ae78df35507416385347688f062aa0abe1741a49d45303ee27e12e70f868456913ea58c9bb8935600e5857ffc7c2514d4346af8828c37f798efa6470e44fb3d9a5a62d99f6c72650b7d449ac6dcc55a9c54f7c5cd9a7f8bd9444216023f3d3a7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e10ec0b51bfc4485592d1a8fc32a0105404420a8dd2ba09b048dd208f3df546c127e5a3ad1358e4c8217aebfca59af3ae3bc6dd2d33fcb7e66f52e86370eeb61bbcdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}}, diff --git a/txscript/data/taproot-ref/9beb9170ecc8bc4e97002efea295cafc58d55688 b/txscript/data/taproot-ref/9beb9170ecc8bc4e97002efea295cafc58d55688 new file mode 100644 index 0000000000..151e89f473 --- /dev/null +++ b/txscript/data/taproot-ref/9beb9170ecc8bc4e97002efea295cafc58d55688 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bed010000004b8c4692dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc00000000064d1b7e701d6ec0500000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5d040000", "prevouts": ["d41126000000000017a914927d550e2674fb9e1f6ae1260d00989fc596dd7f87", "690e290000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "f37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364fb8570387c74e796d15284503f002089d8bb47567604cc51171761387d9a6214c9f6a777e87112c04511ef8a291d390ec48b54e57ed7e78d9086ead135876e880eaa4a5149b34d26f0437dfc3cc15f8b829f232fb4e000d97f0d76bcdb6c884"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa7bedb3584a87481f218db37ff1fd20e008c2f171ef887df99e3acc75d9f4a6f1d93ab99c02c1580916967b23bff6c51eda165404bd9578af086db7302f1c7275"]}}, diff --git a/txscript/data/taproot-ref/9c1a6591aef6efd4346aa9f750f87940a9783107 b/txscript/data/taproot-ref/9c1a6591aef6efd4346aa9f750f87940a9783107 new file mode 100644 index 0000000000..3bdf49cbfc --- /dev/null +++ b/txscript/data/taproot-ref/9c1a6591aef6efd4346aa9f750f87940a9783107 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb001000000f97f388a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702801000000697c5d8a043f238c00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87fe000000", "prevouts": ["cce97e0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "fc540f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ef", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652f3ac1aace3c10cf444e97bb7d38ad5b50faf5df229a4892c0d3ad9e10ad091215b4c606cdda8e0cd0631e1e6566a3457cf9b2eb8ccfe9cc1918e65b703d3f7cd241e6bbc5ebedd8f50ae206f1f82a1e41ff5c139455a0ddb0d368f52a47602"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41645f371c8079005f8f776d501e78f2a21020e20da39870ba1dbf85c4a15b7eacc28207c7af5a37f80d9c7bda068b6f89abe5b5cf72eaf80ed3e31c2f1c9dfaa6c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}}, diff --git a/txscript/data/taproot-ref/9c3a7896381a924c326a82a884be65e632a9f190 b/txscript/data/taproot-ref/9c3a7896381a924c326a82a884be65e632a9f190 new file mode 100644 index 0000000000..94d71fd2dc --- /dev/null +++ b/txscript/data/taproot-ref/9c3a7896381a924c326a82a884be65e632a9f190 @@ -0,0 +1 @@ +{"tx": "a115863c038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48b0100000096e9c4c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49901000000144124f9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf9010000004abe32e30189092c000000000017a914719f78084af863e000acd618ba76df979722368987dc000000", "prevouts": ["e7c0370000000000225120975437f6ff12fc45d8ef3d74f3d05cfb35811edf79338d42e1008b4e2cf45094", "6ef4350000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f", "c869260000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09022ef6775c55da8bde108420fca4ddb99f4c8d91494476301bf3e0d5537c74b70e3cacbbb2142caf78dd2b767d5173f0f3490b25ddb57851f8e76247c728a2f7c64bbdbf2de4a3a14be4a8379114ae6f0d1e04d7338c4597e4bb79b704147b6d5f22373ae9a338d2e0e26d6bdb5ef9e606fc0f0225045a415cce0b05756972064bda704b00b7605c5b8a0823881f2026d897cfabd4b49136260b7a20b748128e12d39af03d5953d034a406ccc188d7c35a3c00ea18c58b95ee79b01ae3702030a64589f8fd7705b9c85eb658058a2f10ef5b1929f004c95e0280dc515d68923bc2abc739b0835f19aa3830089cb74ef6cfa9e99016c261fa9860630ba7d6382a270eb61f036f40fc33d326d1b00d482b03bf4ea888e80fb209caff7e8b8703ed36303434a9eb4ce5dc2f92aa2bcd44568e17fec866140f01e458b7877659a97dd1058800e3f7645672f5eeea15d6a83d5054bdc1ad88e27da941df87c5c6947fa52efa4ee5d2765c30bf3062c4d9f59b67fdec4f5c0db0da718f3c7cd645aceebe99329ada54fd99c54039925e62e76a53b732a23fb15fadfacbb04d6501448c8c40e44165f2d89202dd7305e1be76485e3461a6a3bc0bc64ed8f67574236c47347484c9cb0960e058a49fd6b1554f43197aef49da5cc0bf11bb998037513d0473972b679ed9d3abac8e43f7ae8dc99fe551f1aa9c6ab9a492fccd91a3ace183796772019de4b121fbd975", "947d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89828c38da3f3e346edf59d2f92319d23f93cd7e709e1c3907c38a06ec412d61efe847a112bc0d43d64007e06b59459a0c0ad8818c3210afd17f00e931ed6a3b8"]}, "failure": {"scriptSig": "", "witness": ["4d0902189ebccd35a8c56645eb040f2740f2f31231d3ca373a7f5e13dcf15b898005d4cccb4c8567f1485b9c0b82ca1637baa18471a7750657aeb8d725d21a5f97e070d36472f4772ad92555c64f9664cfe0257767f1a7e24919c67bc7cccf46812c219073463743cdff6a5ca420fa01998b2a85dcb694914098c9da6e5571ed4a7965fcfe364b84bdd9a5bcd756beb7f37484fb910d3b8eb1172feac4f788509694e01de58950ec57af7ac69e596c0ce8650b6d64fee8175bf7177f494e0b24b9783c22c83c856a519d18c273afb982807601c64d8e246343926e3e4662a5f830ed176ccf53243e8706681b8fc60556e46aa61ee4c7f12f15d687f4c3be2d4f5ad0705bab10c417adb1f2fab2bda7b3fd0297b198db502deaa5c6aa83c286358ade2d0c16e1e21b36210125eb61c5c2076275b169aefd7141e860bcc01c127ec2bd108b884fd45ea544e739262ce4710399214d2f17806971c7a330e715b26a6456a8a01180349db1db589bfad3a5439542c5cbd2e58aa8183ecb8adc6b1a4821f3cac1ed2c282faccfdd0799df3850e415112444bbd1bb12a5d1c7ea970a89ab28f3dd8f43a0374931efbeaf8a0167f13e5a3bf2247ec365ea540ada381ee88d60e55a155b57fa3051dc0936ef804f9ba5d3bf929a41c974cdbcf1903f9fa47417fcb9b230b7db2a547e43c9845e139fc797f10128fc57622b2e73119ebd89b58beb8baf7c6626a6eafc7075", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a9be5c2685d91ef557cf0947b16abd2128cd8ef8101163de4969c73a48a3f3202e00206903aca02b9ef6b315776a46e2bb12ad4a7f610ddc80848357a2bf29da5432af4ca45b9bbe99b3e8be0ff589ddab81e08d94f2d38bc0283112328f69fdfe847a112bc0d43d64007e06b59459a0c0ad8818c3210afd17f00e931ed6a3b8"]}}, diff --git a/txscript/data/taproot-ref/9ce105ac118fb5187b993ba8e83d9b199dc86fe9 b/txscript/data/taproot-ref/9ce105ac118fb5187b993ba8e83d9b199dc86fe9 new file mode 100644 index 0000000000..44ec6c215f --- /dev/null +++ b/txscript/data/taproot-ref/9ce105ac118fb5187b993ba8e83d9b199dc86fe9 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48e010000001eafe6a2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5900000000fd8a98450287b78a000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac6f000000", "prevouts": ["9605370000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "21fa55000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "", "witness": ["30450221009b2722d1f1689f2480760fc08ce6c8857a2f2e681fba01edef937ab1a86c393b022001834acdf9f396329968b90f07cb2879ab0a0e374ece804c1f949b5982f6427603", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["304402201706bc807e41337680cc860e84a34e1e8ab6907ded6cb0a350c07b84965dfa2f0220091e8858f4d4706b0e48634941ff61bcc9fc8a408dbc2136e1782f9c690a233c03", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/9ce973c4df052f54b32f61eb27b74cff377e6752 b/txscript/data/taproot-ref/9ce973c4df052f54b32f61eb27b74cff377e6752 new file mode 100644 index 0000000000..bf4eca0732 --- /dev/null +++ b/txscript/data/taproot-ref/9ce973c4df052f54b32f61eb27b74cff377e6752 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127016010000005a40fda98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cb010000005cc4a369dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cab000000003c7930a40216509d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac25272e3f", "prevouts": ["2ae70e00000000002251204929a185ed20b7f7e86ae8920b068b5e7d5df0975bee6bbfbcd97b6bb81e709d", "b3c23b0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65", "8b34540000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["df", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936744d5f1fe8cccbe7a1aaa208055fcd73d33095ca4828da666b0d1eca647814e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5115b534b99635107bf366447ce9661d5eae557250694ef66e76c31b44d1abe134360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d27e649847556e23192b8aeafe173c243f56175d6d7082b77d4d94508f7534d8345e83ad245d963f373c443dd6457dec3808a4f865920e34bbc543e7d04d4c3d1c315aec02adde316e700f87e7c47f474d1ec7cdd06b196ee567d81a15967a13360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}}, diff --git a/txscript/data/taproot-ref/9cf29382585d7d87b68e19e5244cd47ddedf35c0 b/txscript/data/taproot-ref/9cf29382585d7d87b68e19e5244cd47ddedf35c0 new file mode 100644 index 0000000000..212ef40b19 --- /dev/null +++ b/txscript/data/taproot-ref/9cf29382585d7d87b68e19e5244cd47ddedf35c0 @@ -0,0 +1 @@ +{"tx": "9a15a34503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6700000000b98902bb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47301000000b91d6fd260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703d00000000c51f3a80025f6e7000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964c000000", "prevouts": ["e6fe26000000000017a9141582f8bc3490e924b143f387e99eced40303eaed87", "fca73d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "973b0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_28", "final": true, "success": {"scriptSig": "", "witness": ["0b630d3287e3e85358955715f2f0a3f4e5eb1e6afa47984d58d93a641f8f0c85ff6f85114616b4ac1257a62699a40b11c88e474166094f1a71ab96eeaff883f2"]}, "failure": {"scriptSig": "", "witness": ["caa9ddb135c95030d0e1c412c4d93870d366d1b9ec3b6665f52e40293303ea623101ee592c430f9248c2587460f5f43666ed3b4a97fa8b08db20b2db5930e06f28"]}}, diff --git a/txscript/data/taproot-ref/9cffb02f79fc72e41c0ac0b800b862fb39b0a7fd b/txscript/data/taproot-ref/9cffb02f79fc72e41c0ac0b800b862fb39b0a7fd new file mode 100644 index 0000000000..9333c0dedc --- /dev/null +++ b/txscript/data/taproot-ref/9cffb02f79fc72e41c0ac0b800b862fb39b0a7fd @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f100000000f59b89c58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49700000000fbb20ce604dacd49000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc88977143", "prevouts": ["5b30100000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "0b153c0000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "837d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e6193e4630789cbfbdcb7d6fc995ac4f032c6d5611c1f6b733abe8356e59ddce06294a5d2648496e5016f850eddfdf01467fe69221e8567db6ec356a8117d8a748163db171dbfcbf374971659a5a65d0378eae0ee15db360ca8cf80a8c2e13046"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d4241eba4335af55cb703ef1b6547d641330ec95ac5c4cf0d3e8e3ea3eadc07c09d3f278379d69ec93b9031f683f10c8ab57e2d08c050c4811cb81bd332eb9e3ff15e37d03bf407745d47da370f693bba1bd1439d95d9059575aa23ebc3ce6e3"]}}, diff --git a/txscript/data/taproot-ref/9d13b7a6b273e9242c1092d047290e60291087da b/txscript/data/taproot-ref/9d13b7a6b273e9242c1092d047290e60291087da new file mode 100644 index 0000000000..5770e6a08d --- /dev/null +++ b/txscript/data/taproot-ref/9d13b7a6b273e9242c1092d047290e60291087da @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b400100000067e43aff60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701901000000e9710afe02937a2d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4879c000000", "prevouts": ["19c62000000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "b6700e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "4c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b60f374068df7c3adbd1ea091e34cebca1ce39bd416cfdbd5223e6e299acb4c6847bb38ebdfc0ac99f7b57f94cb3711bd799e3f024c53d691ca5d12dd06ff53bd30287fa60720c35e6546eaa391bbb3975ba5e1722a6124c426d678e7f784bd9"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac26d679bf3e8de49490d281730f914e806b1d94cee4bc2d775ba3680f9ace98f724f53fccbc5998418268712ec4a55c070b8ba5ae4e04e2685482dbecadeb1c847bb38ebdfc0ac99f7b57f94cb3711bd799e3f024c53d691ca5d12dd06ff53bd30287fa60720c35e6546eaa391bbb3975ba5e1722a6124c426d678e7f784bd9"]}}, diff --git a/txscript/data/taproot-ref/9d2325335a737991316f3231a676fb415c357be8 b/txscript/data/taproot-ref/9d2325335a737991316f3231a676fb415c357be8 new file mode 100644 index 0000000000..ede0669f03 --- /dev/null +++ b/txscript/data/taproot-ref/9d2325335a737991316f3231a676fb415c357be8 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff2000000001c75619cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4900000000cff75994dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b07010000003c029216047236f3000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8784d7ee4b", "prevouts": ["ac7783000000000017a91408247b8d3db4e641d0be1ff23f14280256870a5187", "06404d000000000017a914b60a534933f6e50f3846e396b9868efc9e681f4187", "4408250000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1655142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["829737e149730f35d49cc71ef0e5dc5a78d0a82a669a8d3820dc6ce454be71374970a23d87752512deae5f5565adae93d05958d0b8266ffc47742c389bcaff46"]}}, diff --git a/txscript/data/taproot-ref/9d3dab224014b620dde2b56cee3fec23463cb909 b/txscript/data/taproot-ref/9d3dab224014b620dde2b56cee3fec23463cb909 new file mode 100644 index 0000000000..1eaba609db --- /dev/null +++ b/txscript/data/taproot-ref/9d3dab224014b620dde2b56cee3fec23463cb909 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4000000000968b3edf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270df000000007d2befdf02b2673400000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac65020000", "prevouts": ["6a47240000000000225120363e143e65a8c3ceb9072edb61818663e66ab42c4302b81f45dac8c3551b5de2", "27c911000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a0e3c1fe12052284d0803cbff9e1f4b5700444776faa5407abdfff7c22af0e38"]}, "failure": {"scriptSig": "", "witness": ["6a5a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/9d6211da7d3f0bda14d5067af27a1abd46dd187d b/txscript/data/taproot-ref/9d6211da7d3f0bda14d5067af27a1abd46dd187d new file mode 100644 index 0000000000..09128e618b --- /dev/null +++ b/txscript/data/taproot-ref/9d6211da7d3f0bda14d5067af27a1abd46dd187d @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba000000000a4dea4a4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c51010000001e406ea960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e01000000c86dabae0117a21000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac57020000", "prevouts": ["0ca3270000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "d08c4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "08ab110000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a80", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363cc6c18dbb2ad1cefe6366db899026a91e492c9d37a466c4a7f55432a4bad27920e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e16014c92f678e181bf1dc3c918b3709f7d7746b7ca1ad43207ed3c2b1249c00bdd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d9fee1d17d522d8600ea529ee17a1f25da379f68e3940e5d1c004f35581e554ab44d35a0b3fc5d8cdca17f6fd766b3b7f076a7a891ad519d38c56688c70ff9dbd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}}, diff --git a/txscript/data/taproot-ref/9d6647e7af1e10de1b3c608d829400e5663b3d7e b/txscript/data/taproot-ref/9d6647e7af1e10de1b3c608d829400e5663b3d7e new file mode 100644 index 0000000000..9e98c19e28 --- /dev/null +++ b/txscript/data/taproot-ref/9d6647e7af1e10de1b3c608d829400e5663b3d7e @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c38010000002c06be89dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7a00000000a16685fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c7010000002dd89bb302d4447e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870e000000", "prevouts": ["c10b4a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0b942700000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "29fb0e0000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "47304402204f706f03a0f3d126c1c369ef5e64567fe561b29f0673774f209c572d8ced6c6d02202dc968afbd20503547c8c438729fc56f236f25bd7087f0914e3a392a14f987840100", "witness": []}, "failure": {"scriptSig": "483045022100f2d0d08b3cc8d7d7a6f50f87a0e65b472b823d06798c9ccc93a97b79eea4ce1a02207317d721674eb5284277f938bccf7853fa205392ded546fc67a2a373506f652d010101", "witness": []}}, diff --git a/txscript/data/taproot-ref/9d86f6cf43b5947de7d50f80fec0483a9072ee0a b/txscript/data/taproot-ref/9d86f6cf43b5947de7d50f80fec0483a9072ee0a new file mode 100644 index 0000000000..b1b0ddb148 --- /dev/null +++ b/txscript/data/taproot-ref/9d86f6cf43b5947de7d50f80fec0483a9072ee0a @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfeb0100000087f4e5fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41101000000bf8e4fc9046e05b1000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47878e020000", "prevouts": ["9ae07700000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "0c683b000000000021581f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936269ff6546b497129ba1fe09f7f94be9a0d73dd3621c79696a97c5ae123801203edc23a266999aa1773fe99be867e95cb2abe2d57657b7a4dc20a388644aabac6d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004539f0e83d2be49ca995d97c64064bae5b8c7dff64f3bec17af779836b699250933d2e072fd8e8376d3a54b2bea1bfbfff1298aece70c0bc2934c8eaacc3044fe58f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}}, diff --git a/txscript/data/taproot-ref/9d8bf71616bca5ac31e24117c80dad52352d5c2a b/txscript/data/taproot-ref/9d8bf71616bca5ac31e24117c80dad52352d5c2a new file mode 100644 index 0000000000..e12abd3997 --- /dev/null +++ b/txscript/data/taproot-ref/9d8bf71616bca5ac31e24117c80dad52352d5c2a @@ -0,0 +1 @@ +{"tx": "81f75e6703dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cae0000000014a05bb260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127036000000002ce4eb9c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702201000000586df89c03fad66a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487470e335d", "prevouts": ["52384c0000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "aa2a13000000000021521f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "06580e00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "d97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363255b317c7de6e9ae6bb70a9fb776c4c6a00d056fb5cee6a264a49253b234c169208680e05d04c3942bb784f68e647b385a50066aeeb87d1b11822ef550a3a38682a6e83df749f265180f93fd54e474915a8abfc6fef0a760c06d61a0bf42967"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361d56eca119efe8600c7ddbecaafaac765d2e5fc0abc9d3eeeeb65fccd7070d9846c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2d5942624d66fc39e30c2a996d85a0dad9a6418b79db996452744438b84f9614682a6e83df749f265180f93fd54e474915a8abfc6fef0a760c06d61a0bf42967"]}}, diff --git a/txscript/data/taproot-ref/9da24604599fa08b01181b48265429ebf1cb213a b/txscript/data/taproot-ref/9da24604599fa08b01181b48265429ebf1cb213a new file mode 100644 index 0000000000..db380e26ae --- /dev/null +++ b/txscript/data/taproot-ref/9da24604599fa08b01181b48265429ebf1cb213a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6f010000002411c5ba8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cc01000000e72a29ce0200e059000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966a000000", "prevouts": ["699f250000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f", "36ae360000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "c37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bfec9f4a544cac12ec45faee03e073e2ca7a1afd48c2e8b5a3a7ddbd5cfcc3ac9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e8d213d90ee48874bbf2b18160b4fefa78452fd9fac91ad5f640de90a3ceda28c"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e1906c602469d9808f25282c821ee4b4dcb0a7f347257f6810852481d8753948638c14f042a58a31b61c3859e3b726944cfc511dd17ecaa68ed5dba7522a36ac78d53ca9a9f93e78db88a883cc9c42dbf55ad09041fa37b21a93adcd191d7180"]}}, diff --git a/txscript/data/taproot-ref/9db297bad5b8a7a06f76713a5b05cdf2148f3b19 b/txscript/data/taproot-ref/9db297bad5b8a7a06f76713a5b05cdf2148f3b19 new file mode 100644 index 0000000000..3d8ae082e4 --- /dev/null +++ b/txscript/data/taproot-ref/9db297bad5b8a7a06f76713a5b05cdf2148f3b19 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270db010000002e0520a960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bc00000000add0448a04b7351e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac07010000", "prevouts": ["c18f0e00000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "51ca1100000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "447d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e46ff9fefe634101043d8ca11d5a4647687c0df4bd98e414158186cc8065d9a91f7b6e2c095a2b9a1b3d0ba71ae2a36fa91117ca9fadc253f03c0f98f0de350244f357c04ffd5ab4b0848fd0bc62a9916d6f879ccec8b8201b6b82c9f83bee932"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93685122a638a9254058212aed1298d113a9036b8f89f151ed985c2121175e9df03288d1d486ad1cd5e981ede7314b9e0cd98a009052c160e03e008903fffd682c3fa4004b2cd3f2b5519985ef4ce40029d6249627881f39179d9882ffc68f5bb6a"]}}, diff --git a/txscript/data/taproot-ref/9dc1141da1d44addec511e26f89d5046f97da2c6 b/txscript/data/taproot-ref/9dc1141da1d44addec511e26f89d5046f97da2c6 new file mode 100644 index 0000000000..2ff036f76f --- /dev/null +++ b/txscript/data/taproot-ref/9dc1141da1d44addec511e26f89d5046f97da2c6 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1100000000c319839760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270290000000027cc25ce0383556300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b1030000", "prevouts": ["e6d3550000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2", "32340f0000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["30450221009f7df4ccb7286f01184071b2f2469e5e6d722c72bdaa5b81d0388e786cb12fe602204dae6ebc306b7645955a0b84c9b88e5d8c8cbdd3451e63c80b1280b339c9a0c283", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["3044022015dd4161c186d3aff010b31cce213e8deb239140a647b3d1c8bc78530800002c02201a0dd4eb46ce03f267a7d8f137747f2e8eac2dfefc81ff83ea23e582b3c5b39b83", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/9de0c2afad49fa532a8fea5e4dad68a5f1ab8a22 b/txscript/data/taproot-ref/9de0c2afad49fa532a8fea5e4dad68a5f1ab8a22 new file mode 100644 index 0000000000..7627ebd05e --- /dev/null +++ b/txscript/data/taproot-ref/9de0c2afad49fa532a8fea5e4dad68a5f1ab8a22 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8801000000e3859977dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1f0200000017508a9f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708601000000d56fc4e201266d0000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7e89ca15d", "prevouts": ["0f5467000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "e47e5a00000000002251205857fc26f723a58058d8b22639f4b33f8ef23084aa37309f77fdf87ef7a99b1a", "92430f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["44a1978381621ea420f72e8990d0e7e3e28b43fc61e5871ce0943344d4e89fad3c52f36026a30816ab6735b4080d6faaf738c7c90a71229b6fba0ca2720305f7", "87855a", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93607866517f563f914300dc56dfa5f8b2e234717fbb3f83d73d2cc5efe2ba41a0ed98b24582cbb8737e8c7220d7d498ed31f2b9f710dc34600e46a3149ab474161d7d68e31704311d4b712cdf1e1d8e79c279e23740497741197ef9bd8a24d462d629f5f2ff4b5efda05305db76ce9925e0213f8c3960aba617c7546d52b2974abc697220ad4d17d3512c24d5ae155b6adcfb044ab79ab20bd38e1e28a80464f484cbd75784e993be530d5676f8dc2ee09b64f1f32f66cdc7b4ff59c4092b7cf376ee8f8c1e1fa9aab23cd1073c3056ca33bc71f7534defd8cb78efeb53cedcb5960dbdc44debd3a9d6581183ec7e582c81ae2ba327dcd9a8a8596b9498c5442e0f6f4cf1c458df91a0afea0d2c153bcc49a5c91080076e369005eee9d0f0f929c287d66d90c4cbe9643f4dd5fab41adb0ea5f21af54c16a7905d7aa75be9e79abb756e94dd6dbf8811f581a6677dd5040b0770d6580c8a23956aee345bb51bf7e732609e0d9888e8fabb595ed61aca9adfd730b42bb4be3264e3b48daf2dfdb1dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c02e90a504fb885b35041a93f57bf95bff975e3ce3b01edd50e093d99d3d1a7000000000000000000000000000000000000000000000000000000000000000076077fab5cfacfe0d44da24115518e7cc923cfda0846fe7d6664ce76c18ae77effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa4fbc6152007b768a0a9e0ea555589417531593915a16dcb5161fa990fe790e2193b77feb85593374d68ba2893ed797c76657c07a7c180e1e161979ce40fd06297a169906078a0293dbc950d85ed90e3a1c6acd68c7233757f5f87f37ea46f07264225bad0351757cee8fbc4204b2b1c4491d39d7192eb176f116ba4cff6f2bb641533f7966d3bc46e7b79fec79f6d1f4df0a1c250c0cacbcf443017af88329adefe7756b0306fc33d2eb0028f4ee0fdb0a1974fcf7045f05d180ebd9603c6150000000000000000000000000000000000000000000000000000000000000000136517a08a3d4af2465b8c7ec780a2358a75ad5f187b663ab087a650f574e59a37bda4a363bd5cba9df5a222a4cd106bc990d013c633cd17f3dc6a39e3467108b67086733584b7622003be83be8f789fa11afe304d7e275cc0beee4ea78d11afffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6ff2c617481b75c05b00bd34dee98a92e192ec68ab8484dff43174aea4c66a85623f05c824104f4894efaa986601a7a0a173fcdabe3bf55f33f03d6e9324c0330e981f9e9d7858cf2744234d067f7c65c2f06e45483768054a3cf417124ddf90000000000000000000000000000000000000000000000000000000000000000c857f6b8c4189b4ab1c06030d0f3bbc9d6efcf5e4be3c29626e522a27a0d0ec21df30051e5e20486210b635d36c83ff9cbad4f361067a21c9ef9659cbf15e489de0065e2010eeba19fe5ad09a950e50d2806c8000de4dbb8e5489b2204a312bdfd9d0203e8dcd91d0d623b187e073ac11e62e92ea76c3bb72e9e90e1a35cccd6", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["44a1978381621ea420f72e8990d0e7e3e28b43fc61e5871ce0943344d4e89fad3c52f36026a30816ab6735b4080d6faaf738c7c90a71229b6fba0ca2720305f7", "e522", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93607866517f563f914300dc56dfa5f8b2e234717fbb3f83d73d2cc5efe2ba41a0ed98b24582cbb8737e8c7220d7d498ed31f2b9f710dc34600e46a3149ab474161d7d68e31704311d4b712cdf1e1d8e79c279e23740497741197ef9bd8a24d462d629f5f2ff4b5efda05305db76ce9925e0213f8c3960aba617c7546d52b2974abc697220ad4d17d3512c24d5ae155b6adcfb044ab79ab20bd38e1e28a80464f484cbd75784e993be530d5676f8dc2ee09b64f1f32f66cdc7b4ff59c4092b7cf376ee8f8c1e1fa9aab23cd1073c3056ca33bc71f7534defd8cb78efeb53cedcb5960dbdc44debd3a9d6581183ec7e582c81ae2ba327dcd9a8a8596b9498c5442e0f6f4cf1c458df91a0afea0d2c153bcc49a5c91080076e369005eee9d0f0f929c287d66d90c4cbe9643f4dd5fab41adb0ea5f21af54c16a7905d7aa75be9e79abb756e94dd6dbf8811f581a6677dd5040b0770d6580c8a23956aee345bb51bf7e732609e0d9888e8fabb595ed61aca9adfd730b42bb4be3264e3b48daf2dfdb1dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5c02e90a504fb885b35041a93f57bf95bff975e3ce3b01edd50e093d99d3d1a7000000000000000000000000000000000000000000000000000000000000000076077fab5cfacfe0d44da24115518e7cc923cfda0846fe7d6664ce76c18ae77effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa4fbc6152007b768a0a9e0ea555589417531593915a16dcb5161fa990fe790e2193b77feb85593374d68ba2893ed797c76657c07a7c180e1e161979ce40fd06297a169906078a0293dbc950d85ed90e3a1c6acd68c7233757f5f87f37ea46f07264225bad0351757cee8fbc4204b2b1c4491d39d7192eb176f116ba4cff6f2bb641533f7966d3bc46e7b79fec79f6d1f4df0a1c250c0cacbcf443017af88329adefe7756b0306fc33d2eb0028f4ee0fdb0a1974fcf7045f05d180ebd9603c6150000000000000000000000000000000000000000000000000000000000000000136517a08a3d4af2465b8c7ec780a2358a75ad5f187b663ab087a650f574e59a37bda4a363bd5cba9df5a222a4cd106bc990d013c633cd17f3dc6a39e3467108b67086733584b7622003be83be8f789fa11afe304d7e275cc0beee4ea78d11afffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe6ff2c617481b75c05b00bd34dee98a92e192ec68ab8484dff43174aea4c66a85623f05c824104f4894efaa986601a7a0a173fcdabe3bf55f33f03d6e9324c0330e981f9e9d7858cf2744234d067f7c65c2f06e45483768054a3cf417124ddf90000000000000000000000000000000000000000000000000000000000000000c857f6b8c4189b4ab1c06030d0f3bbc9d6efcf5e4be3c29626e522a27a0d0ec21df30051e5e20486210b635d36c83ff9cbad4f361067a21c9ef9659cbf15e489de0065e2010eeba19fe5ad09a950e50d2806c8000de4dbb8e5489b2204a312bdfd9d0203e8dcd91d0d623b187e073ac11e62e92ea76c3bb72e9e90e1a35cccd6", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/9de4c3db0a099c27c523988b4b750ce3ee2c0ffc b/txscript/data/taproot-ref/9de4c3db0a099c27c523988b4b750ce3ee2c0ffc new file mode 100644 index 0000000000..a35494f2e1 --- /dev/null +++ b/txscript/data/taproot-ref/9de4c3db0a099c27c523988b4b750ce3ee2c0ffc @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705f010000000381a28bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfde010000001fdee4ab01e9047600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acdbd92745", "prevouts": ["55c40f00000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "cb836e00000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51f2809a2eb594a6d82ed798bedf8d6754ddd1a8a74001a2f8f1c3cb07bb651864f3b3fb8d5121830dc5ea13d084a01bce62f4c2426ea7fcb92dda33a6ec3d9661"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93643c2517ac3ab4c9161235a0b54014a7814087b294481d246f392479809e3784cd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51f2809a2eb594a6d82ed798bedf8d6754ddd1a8a74001a2f8f1c3cb07bb651864f3b3fb8d5121830dc5ea13d084a01bce62f4c2426ea7fcb92dda33a6ec3d9661"]}}, diff --git a/txscript/data/taproot-ref/9e080c9060b0017ebfc6f81bd854014a8fc88ee8 b/txscript/data/taproot-ref/9e080c9060b0017ebfc6f81bd854014a8fc88ee8 new file mode 100644 index 0000000000..a26428c225 --- /dev/null +++ b/txscript/data/taproot-ref/9e080c9060b0017ebfc6f81bd854014a8fc88ee8 @@ -0,0 +1 @@ +{"tx": "08aca4d7028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48701000000c4c226e3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5801000000dcb7abfb040634aa00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87b5000000", "prevouts": ["5b9a3500000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81", "7dc8760000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["964c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456bbb2d2aacfa419948546f2c8aa96b4ab4a80289c3c8034e795f45f733cf7ae0b35fa22f4b25dbc3a6b67e691e1ba7f45df255baed4abd058cf23fbf36a7f21681a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}, "failure": {"scriptSig": "", "witness": ["4c5296", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b186acb2a5feb9ca494b2668e3b95b217c5b1a118ef72c41b67fce4e6b051c90eb4e626fbd1c5a1d96a595c16e39be42f50aa7a1faa8ff1a1c0cc640b6e10eb9874a9774daa89f30be275a1ff5113653dfa1548b9628ff9725cf694401ebdfe4"]}}, diff --git a/txscript/data/taproot-ref/9e0885e261051e23c61d7b6859e9c25f16f9aa73 b/txscript/data/taproot-ref/9e0885e261051e23c61d7b6859e9c25f16f9aa73 new file mode 100644 index 0000000000..2a920bd2b8 --- /dev/null +++ b/txscript/data/taproot-ref/9e0885e261051e23c61d7b6859e9c25f16f9aa73 @@ -0,0 +1 @@ +{"tx": "ce6d8fb40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707b01000000a82eaabe60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702600000000318dc6de03fb901d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e7b3b94c", "prevouts": ["945c0f00000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "65c510000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "387d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663dbae3fcd58a782f045d72728c5bacfc693bf32c12881b703312d3ef1ff344f9b60e5914c50703ee8fed26b085ec7bf74c965cec3b126e70865dabf0c3179e2a12168afdb4ef286e7748ddb08cf408d85b089f504486378d2bfb535c0d2875b"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93687eb9cd48618043924a0552f13e304cb7cf31192705149ca53d1915b0f7b733ffbb5a1fe7b9516d3f9237414125c5ee80cc77ac3c2791cf19c93edd24acc7f158fa601fcc68a78472d280e0a6f10ace0c22dad9ad93c154f995d1132d7b2f793"]}}, diff --git a/txscript/data/taproot-ref/9e533595a0cd03757f4ce00ca1a54a38453f6274 b/txscript/data/taproot-ref/9e533595a0cd03757f4ce00ca1a54a38453f6274 new file mode 100644 index 0000000000..324498bdfd --- /dev/null +++ b/txscript/data/taproot-ref/9e533595a0cd03757f4ce00ca1a54a38453f6274 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0f020000000b347dcbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9800000000d4e7428104d53da800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79686010000", "prevouts": ["17065400000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f", "71505600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "187d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faec2668268b08b6c5058ff907ef397af6488febb6d6ea42f9f262b28546ce31faeb0356d5dc7bb189d5700ce63be65cd47bafc75bda640418bb3b77b52e492b0f"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936de248b3259490a8f0e1d30062da8e3e2b08bcf3de85e2266d4c4622ab2525e61ec2668268b08b6c5058ff907ef397af6488febb6d6ea42f9f262b28546ce31faeb0356d5dc7bb189d5700ce63be65cd47bafc75bda640418bb3b77b52e492b0f"]}}, diff --git a/txscript/data/taproot-ref/9e7cd3ed8c99ea2f99c6c55da41e1a2e4c56fb9b b/txscript/data/taproot-ref/9e7cd3ed8c99ea2f99c6c55da41e1a2e4c56fb9b new file mode 100644 index 0000000000..4cbe7798f7 --- /dev/null +++ b/txscript/data/taproot-ref/9e7cd3ed8c99ea2f99c6c55da41e1a2e4c56fb9b @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270490100000013ecb1ea8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47c0000000014f64124025d7c40000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acbaacd11d", "prevouts": ["250d100000000000225120a2880b97adcad5e9d951ecbfc4186ac77c307365c746cd6918dba256e34886ce", "13f6320000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "success": {"scriptSig": "", "witness": ["4a4b60f20052e77fa5e17f0f78dddc61af17054366c298978de230333c885d93e95ab6a8134b6e7e9cb1b4967a308ddaa357d787584eeb620ab20a1b7dc360da", "1cdd65e76f83b2dbab7e250b2b2af8db0a04726cb392d0f232516ae3cb68d014541ca3e63a447e8ff52eadf4aa201210c9f4711964c5b663c1a633fda71af67135d709f832b51f284909e49d2ce464c05e80d69dfcbfbbcd3eb0429fa09140d70c35cbf1c1564970f3c71486e86ab5f9d1b88ec50ec8760fa6024695f1605f0568f69217dafd2f0858a37463081bccc4b6693d6b6062de223bef28b5f72e590fa6efa8ff7a3b2e3362062453cbab08e85f5772ce7f2275f3c178f4ed2ec31c588d372e2f02dbbd22a422f0c4fb450884b715e3703606a48f075628ce7e2d41ee63271e84e58d68", "750442c441325163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936038317a9484741889b65c6c22a4d2befdac9a678d76b2139ff47cbccdabce0b075f9de8df9315d179ab13788a9f0a51aed124e9640fe933e0f2dfcd9ba53c650631439ea9479dd43966b5504a57521f1af14b4790d111c4cbcdaaa06b43a1d2c2d818ae92a6038e6df4e77267968ceb432b81fbab4ebf89d2a9e818069d61c087f36f6b993284bd299bca34b1a11009a2ac5385792b05da61d3dca9472536a2e8a47e91632c7febab8b31522c67292f5f625403fe8973fcc5108275eedce267860a161f6a6fe54f76f5ad160876535005425790db445f57b5b3831be508169355c76d28e8ad9d664eb67c41e2e14329e89b79108abfd032672d949297150b8f4fad6d628b62d3fbdf07582a7284e2e3d85250a63e5900c1526f9548cdf96a93b00000000000000000000000000000000000000000000000000000000000000009191506396eb586b31c9d87517b8792c8c3a17034bdc0d3961fc908c8159255b6c6a9bb578cda592892c253df30cdab068ec7aa209c413ca97183e14518fb3db003c5eabb59dd96d3a7f84b7c8e277eb49c48b1a9a0e3e47a50aab828286fe23aee95ca313d50c59641d7142d949b6098ced445b5b01f5d1c99d703db933e1ac604b6ddef78cd4c47ce10b866e3efad318d59660191e471bdd2194bf328a62fdbad3e00dd4963ade259ff5db3df42dbcdffe2ac5e1c22e0b8fa89e5042046e0f0000000000000000000000000000000000000000000000000000000000000000f787ccd98da746b19981235e716eef61efbb45eb09898bffb9102775e17e4ab71525f4431581d1859a3fe28dda84a8e05ece074e1bf73eff9ae9ccc8bdd119dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e3016f9f9f0caac60190d697ecbad2ea23264a15326ccee406c1d2debcd99bc1519e7f5286023b9d9ada950a832a7c6c497f1195f9c9700e4cc3b0d7652c08d95a8bbc6a44f965eff8b9ad39018af091fdeeb7dd381382eead642930f8600db152a61b9c3d06841939315c14abd28633038ec8d28f77e12ea8001c7cd16a079026b531cb72704102c66830c4be1fdb7821c7101f6dbad3ace793033b347a86015975080c91c305bf53061e64a4e3fcfe157dae50046d86486c5285ef3ef4d15508fc2b4f97f5096ef799f97eba0a39cdffa8d74567559c66fb0dfedac41173046eb626bc5e88b8a1186b7493a9566b7438856599dda96bc4b06349dd58a6795000000000000000000000000000000000000000000000000000000000000000016482ce883d75875f9b58c0c52203dd0094428e1080c20b1909393fbf3ab3915249fd5c976b4b439c8e999d18122f1b3819ccc62e4f184826aa80ec2fc633f967b64d246947cd5a4e73b402db89139cdfda66f8a53440ed6f62dd8f19c1de714f27197236c1b61553e78131a4eb06ca345c24328ae271b4b92a999637123f13683bed5fcdb5e2736f2bd04ea49d7a09a01016aa4b975c7149b1339984f2c4da19ed4eefef6001b5fe776689838adeb4b94263f0a13eaa636ec29ad664ac03f17ec14fa631165009ec4cfcc06ddafc5728535436fefbc34bdab735cd9fb07f81c0000000000000000000000000000000000000000000000000000000000000000cede8a0759d10e57ac431416240020aa1041d88dc5ea25e80beb4f813b948e10ffd2f236b14bd8ae5fffea290c7f6185094e436a0c3c12682fca2d542c6b54d7b26dee6de2be63b3c5cd0d3732c9a3b1a936a016dfb69ec3deba56a3997d7fae30db2a65025e8a47c9c537ae20a4510e816bda13bed12168abfa5de2cfd710c6b843a456cedae9a8c041b3f3d24a12964af86793708450f7f964b4773be4de7f76699a2b09f0d63ecc32afbd3e7e093edc892989190f778e643d8fb47172861c60abc276ea1f64dec42f37feaad848a37b07bcecafa2a30df41080bcca811fd200b7ffc88f1611bdbd0b157f033263a58e491f31ba4d6c0a94f3dfea301e91e300000000000000000000000000000000000000000000000000000000000000008dfe6489bf48f6d3f6631088c12e0b1dfdf29904b6b58d73d3a36ddb3ead01fce7eb01e964bc836fee76a110cb4b53e79e3494aee516c5debb8f7e422ee40276eba6e7d9981f508979fe7fece1ea94f6471faa57b9851a679674b6802778e2c64bbb27ab0758dc5dc51ed0b395e80d9ea5010146aa1438592554d041de1dad617f84c15d0d8a058d7a255bcccd7b29b0e05ce4f3a77399991ade7ec24513d47e493a2155b7efbbcefdc64ada9767566bd2e635610831ed7793409a224e3c634dff075fccb2ffc6270452d3d19b29c42ec59fa6d222f8dcbdbd13a4587007460f8bd4004f2eee7c0f550c29ef21f56fe0f3143417d6799079eb8081169d49cb6e60eec5824bfbe4510df2c33a7ab8bc9066a1686f6e046c63799ce91404f2b3f2e090cd534e843476acb5c7221f1ebf96d617251741dcac6370179580f62c881562d3723e0b1997f3f2c1e6459aaa9aefad842a5eaf0ca86aa0e1fa1ad8c44403c97616d6c4573e9538b9da4fe42e00326fd178df218f0915d2ee0d7f31aa42472d4a415b09b6c465334a1de7425c93db2bb0a0a31bfacf7914c05df1d44c13cea886b4074c506ea43a458508c06f5d2e09d0a634ff24643fd2732d0c0ce608bf4418568e5f4dc4d9c10cc7f51535fd9506e57fac47f6538778f470188b3092b70000000000000000000000000000000000000000000000000000000000000000d451538220b62b15eb837dde746a548175548de2e34828d6c3e21b46a140c64f5af24904a3770e347b475bcd37e69f01bccb44cb672cc2e091edba220307c2b9a35d310fb7880cedb5aaa258873bffc03b1728c981367fab4bde83e8013cc2a131ea937cc9d462877bb7cc8a698eca9df5243fc292d919436388a67a97fc36c9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6b3d2f9bf76b5e7f269099f19bfc11d67ffdb0f7d81dff8f85af90095347da85ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff904cbccfc2fd8552081cc9d94479f68f56bdbd8ca0e764a0473c53832929347a70f725975d16a543bff6e6429387999df01469893c61678a855a421415b277355960e2acb4d1f4ae8e93692c69cc178531bcb90543b69dbe8ba75e4c2f794ff8dcc2ea513dc34c35fe0662f48cf0c473a7433d5a789d39a21df5cc77e502999d7944f53d7474a42d645e2eaf665493201816057f307ff181c9513d9b81c6afff7c244780df2b822c8603ad8b7c5c2cd394f61ccda89559f17ab7adbdb38938fa1e0586a1d0b87ff795c835f64e99b11e3165df8b2d0e90a4227af6576ec0fe044887ffb3aac40ba5988059b4d32fe8b1f721235c644c6d4e895cad48b4ef152effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7b7b8b85b0c5df1bf94a8ed42d63a20d5ab7873b62dce2a4b7e0fe75ded19f6bc50997156d6b6a43003b4b097de50b426293a49ef32d20b4cf4aa10e1f9f6a33b75f1d24542de0ef4dc28aee12be2e13407198faf5d6c1701201382d3cc694e6b91628552a7e4a3a47bb7fdfe1fa5d6ee6a914f73e3ad93d0d2ea5b18f89cf9012d68f6ae7d50ef18a65911259e28b70a2ec9edd99be44f2742848de01c1139d4fe4fe128396b3c16521cdac94dcd5758b5c1e3d847d392b5673519e9be3c8f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e392f4165719c3fc591a221a18cd76d487a20aacb1f6eb5e90f6e3fcb603b2bd968e26e2bb195b9a749657edf13ab8034a5591d809ec65349a77b352235266eedbbed849fcd5cd85dabecac8a0f95060c63a2591a9c4c30e6fc2f681dad4034ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff496e6e91cb7cfdf79d57bfb33739f04be4206abd598eef2dbcd30502e8d8fcb608d0eff949b55a8d3acf725a10096ffa528dac1425cbe77e0767d9f70a4f297c8d419cf1db45d736321fe436422c91188d6293034a6ef69090da00ee0c806d6205128635787105ab2fbb65c2f9cd90518c50a19119ffa61d88eed3fb3567028dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33b53f64cc5b42f98e6a545543ae061b4447e606f29d2b330878531c757faae2bbc521c511e5a977f87e050b7e2483faf1f07f1ef31bdbb96e9f15ef77632ee8a395bbd3c906994aeba0c198d7ebe1bc11370c12204f5ed90f396b299f361b7debe005232c9eb4d2149e0a8f861061b6da21fbcb4266037053e9d88ef930fa28000000000000000000000000000000000000000000000000000000000000000035eb9ff40d576cbbcccc148c325fb4511c3513f3e9fa22642ca8437988eb18e6fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5682ffdef1554936f423a87dac08d9c81b23529a58291f655ce958a51e043bba149b5315d1b32fc5ec2f3a3215c12b34df9b5127478e70245ac1e45097ae37014bc7665b5a987f8027c6fbe028e975157cf00a9a0d04d52c9b20f4b16e62d075e9c384c0cced8236246496f61292392b7e0d94e06bdf63f85438c95ad4c2e", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["4a4b60f20052e77fa5e17f0f78dddc61af17054366c298978de230333c885d93e95ab6a8134b6e7e9cb1b4967a308ddaa357d787584eeb620ab20a1b7dc360da", "a2d563c755f3de1f62a1eb8f1445f638642861ea23334cf6739ac5cf9e0715143d7a56b2ef9061d75fdd6196cbb0d17b7eb340d4c6baca0b7666b1a64fc044a9046f821627862a198129a3006a64d2fb798262b9602a218fe96933bed19ff85b860fd0e21cdb6987770f925f32fcada1634785cb47e35f52ed654ae731d1328cc18787cd2059e8ac65e9b0bccb6bbde5c6c7ceaa163fbf996429ccdf8bbcfad702faa2273483d2226ed91b972b97f05716ea26c03e32075d44a258371e918a4bd70e7139061b49bd68ec8cebcefeee0c248b5d0b3f7d2c35b63673be07350f49af6e8843c74a", "750442c441325163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936038317a9484741889b65c6c22a4d2befdac9a678d76b2139ff47cbccdabce0b075f9de8df9315d179ab13788a9f0a51aed124e9640fe933e0f2dfcd9ba53c650631439ea9479dd43966b5504a57521f1af14b4790d111c4cbcdaaa06b43a1d2c2d818ae92a6038e6df4e77267968ceb432b81fbab4ebf89d2a9e818069d61c087f36f6b993284bd299bca34b1a11009a2ac5385792b05da61d3dca9472536a2e8a47e91632c7febab8b31522c67292f5f625403fe8973fcc5108275eedce267860a161f6a6fe54f76f5ad160876535005425790db445f57b5b3831be508169355c76d28e8ad9d664eb67c41e2e14329e89b79108abfd032672d949297150b8f4fad6d628b62d3fbdf07582a7284e2e3d85250a63e5900c1526f9548cdf96a93b00000000000000000000000000000000000000000000000000000000000000009191506396eb586b31c9d87517b8792c8c3a17034bdc0d3961fc908c8159255b6c6a9bb578cda592892c253df30cdab068ec7aa209c413ca97183e14518fb3db003c5eabb59dd96d3a7f84b7c8e277eb49c48b1a9a0e3e47a50aab828286fe23aee95ca313d50c59641d7142d949b6098ced445b5b01f5d1c99d703db933e1ac604b6ddef78cd4c47ce10b866e3efad318d59660191e471bdd2194bf328a62fdbad3e00dd4963ade259ff5db3df42dbcdffe2ac5e1c22e0b8fa89e5042046e0f0000000000000000000000000000000000000000000000000000000000000000f787ccd98da746b19981235e716eef61efbb45eb09898bffb9102775e17e4ab71525f4431581d1859a3fe28dda84a8e05ece074e1bf73eff9ae9ccc8bdd119dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7e3016f9f9f0caac60190d697ecbad2ea23264a15326ccee406c1d2debcd99bc1519e7f5286023b9d9ada950a832a7c6c497f1195f9c9700e4cc3b0d7652c08d95a8bbc6a44f965eff8b9ad39018af091fdeeb7dd381382eead642930f8600db152a61b9c3d06841939315c14abd28633038ec8d28f77e12ea8001c7cd16a079026b531cb72704102c66830c4be1fdb7821c7101f6dbad3ace793033b347a86015975080c91c305bf53061e64a4e3fcfe157dae50046d86486c5285ef3ef4d15508fc2b4f97f5096ef799f97eba0a39cdffa8d74567559c66fb0dfedac41173046eb626bc5e88b8a1186b7493a9566b7438856599dda96bc4b06349dd58a6795000000000000000000000000000000000000000000000000000000000000000016482ce883d75875f9b58c0c52203dd0094428e1080c20b1909393fbf3ab3915249fd5c976b4b439c8e999d18122f1b3819ccc62e4f184826aa80ec2fc633f967b64d246947cd5a4e73b402db89139cdfda66f8a53440ed6f62dd8f19c1de714f27197236c1b61553e78131a4eb06ca345c24328ae271b4b92a999637123f13683bed5fcdb5e2736f2bd04ea49d7a09a01016aa4b975c7149b1339984f2c4da19ed4eefef6001b5fe776689838adeb4b94263f0a13eaa636ec29ad664ac03f17ec14fa631165009ec4cfcc06ddafc5728535436fefbc34bdab735cd9fb07f81c0000000000000000000000000000000000000000000000000000000000000000cede8a0759d10e57ac431416240020aa1041d88dc5ea25e80beb4f813b948e10ffd2f236b14bd8ae5fffea290c7f6185094e436a0c3c12682fca2d542c6b54d7b26dee6de2be63b3c5cd0d3732c9a3b1a936a016dfb69ec3deba56a3997d7fae30db2a65025e8a47c9c537ae20a4510e816bda13bed12168abfa5de2cfd710c6b843a456cedae9a8c041b3f3d24a12964af86793708450f7f964b4773be4de7f76699a2b09f0d63ecc32afbd3e7e093edc892989190f778e643d8fb47172861c60abc276ea1f64dec42f37feaad848a37b07bcecafa2a30df41080bcca811fd200b7ffc88f1611bdbd0b157f033263a58e491f31ba4d6c0a94f3dfea301e91e300000000000000000000000000000000000000000000000000000000000000008dfe6489bf48f6d3f6631088c12e0b1dfdf29904b6b58d73d3a36ddb3ead01fce7eb01e964bc836fee76a110cb4b53e79e3494aee516c5debb8f7e422ee40276eba6e7d9981f508979fe7fece1ea94f6471faa57b9851a679674b6802778e2c64bbb27ab0758dc5dc51ed0b395e80d9ea5010146aa1438592554d041de1dad617f84c15d0d8a058d7a255bcccd7b29b0e05ce4f3a77399991ade7ec24513d47e493a2155b7efbbcefdc64ada9767566bd2e635610831ed7793409a224e3c634dff075fccb2ffc6270452d3d19b29c42ec59fa6d222f8dcbdbd13a4587007460f8bd4004f2eee7c0f550c29ef21f56fe0f3143417d6799079eb8081169d49cb6e60eec5824bfbe4510df2c33a7ab8bc9066a1686f6e046c63799ce91404f2b3f2e090cd534e843476acb5c7221f1ebf96d617251741dcac6370179580f62c881562d3723e0b1997f3f2c1e6459aaa9aefad842a5eaf0ca86aa0e1fa1ad8c44403c97616d6c4573e9538b9da4fe42e00326fd178df218f0915d2ee0d7f31aa42472d4a415b09b6c465334a1de7425c93db2bb0a0a31bfacf7914c05df1d44c13cea886b4074c506ea43a458508c06f5d2e09d0a634ff24643fd2732d0c0ce608bf4418568e5f4dc4d9c10cc7f51535fd9506e57fac47f6538778f470188b3092b70000000000000000000000000000000000000000000000000000000000000000d451538220b62b15eb837dde746a548175548de2e34828d6c3e21b46a140c64f5af24904a3770e347b475bcd37e69f01bccb44cb672cc2e091edba220307c2b9a35d310fb7880cedb5aaa258873bffc03b1728c981367fab4bde83e8013cc2a131ea937cc9d462877bb7cc8a698eca9df5243fc292d919436388a67a97fc36c9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6b3d2f9bf76b5e7f269099f19bfc11d67ffdb0f7d81dff8f85af90095347da85ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff904cbccfc2fd8552081cc9d94479f68f56bdbd8ca0e764a0473c53832929347a70f725975d16a543bff6e6429387999df01469893c61678a855a421415b277355960e2acb4d1f4ae8e93692c69cc178531bcb90543b69dbe8ba75e4c2f794ff8dcc2ea513dc34c35fe0662f48cf0c473a7433d5a789d39a21df5cc77e502999d7944f53d7474a42d645e2eaf665493201816057f307ff181c9513d9b81c6afff7c244780df2b822c8603ad8b7c5c2cd394f61ccda89559f17ab7adbdb38938fa1e0586a1d0b87ff795c835f64e99b11e3165df8b2d0e90a4227af6576ec0fe044887ffb3aac40ba5988059b4d32fe8b1f721235c644c6d4e895cad48b4ef152effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7b7b8b85b0c5df1bf94a8ed42d63a20d5ab7873b62dce2a4b7e0fe75ded19f6bc50997156d6b6a43003b4b097de50b426293a49ef32d20b4cf4aa10e1f9f6a33b75f1d24542de0ef4dc28aee12be2e13407198faf5d6c1701201382d3cc694e6b91628552a7e4a3a47bb7fdfe1fa5d6ee6a914f73e3ad93d0d2ea5b18f89cf9012d68f6ae7d50ef18a65911259e28b70a2ec9edd99be44f2742848de01c1139d4fe4fe128396b3c16521cdac94dcd5758b5c1e3d847d392b5673519e9be3c8f1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e392f4165719c3fc591a221a18cd76d487a20aacb1f6eb5e90f6e3fcb603b2bd968e26e2bb195b9a749657edf13ab8034a5591d809ec65349a77b352235266eedbbed849fcd5cd85dabecac8a0f95060c63a2591a9c4c30e6fc2f681dad4034ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff496e6e91cb7cfdf79d57bfb33739f04be4206abd598eef2dbcd30502e8d8fcb608d0eff949b55a8d3acf725a10096ffa528dac1425cbe77e0767d9f70a4f297c8d419cf1db45d736321fe436422c91188d6293034a6ef69090da00ee0c806d6205128635787105ab2fbb65c2f9cd90518c50a19119ffa61d88eed3fb3567028dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff33b53f64cc5b42f98e6a545543ae061b4447e606f29d2b330878531c757faae2bbc521c511e5a977f87e050b7e2483faf1f07f1ef31bdbb96e9f15ef77632ee8a395bbd3c906994aeba0c198d7ebe1bc11370c12204f5ed90f396b299f361b7debe005232c9eb4d2149e0a8f861061b6da21fbcb4266037053e9d88ef930fa28000000000000000000000000000000000000000000000000000000000000000035eb9ff40d576cbbcccc148c325fb4511c3513f3e9fa22642ca8437988eb18e6fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5b5682ffdef1554936f423a87dac08d9c81b23529a58291f655ce958a51e043bba149b5315d1b32fc5ec2f3a3215c12b34df9b5127478e70245ac1e45097ae37014bc7665b5a987f8027c6fbe028e975157cf00a9a0d04d52c9b20f4b16e62d075e9c384c0cced8236246496f61292392b7e0d94e06bdf63f85438c95ad4c2e", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/9e94137b564120169fc22f85678cc20df3a1128c b/txscript/data/taproot-ref/9e94137b564120169fc22f85678cc20df3a1128c new file mode 100644 index 0000000000..dfa8148b56 --- /dev/null +++ b/txscript/data/taproot-ref/9e94137b564120169fc22f85678cc20df3a1128c @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdb000000005eaf85bf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e0010000001162e7efbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9701000000c3c69fd004347af5000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac82745761", "prevouts": ["612151000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "c6b8340000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "f439720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_fc", "final": true, "success": {"scriptSig": "", "witness": ["853d42ba217ade276bec4bea9889ac9bc09bd83ccd2a574c1ec175793897451a023b7a3dd01ff5bdebe81973ca7a3aa93c82eb4c451744e825ae82138795337a81"]}, "failure": {"scriptSig": "", "witness": ["2197770bd3e8af3068f5b727a940172231dabd48c25a549f8fabdbf7849cb03d66ef506ec44d013bee39596e01a81a55d1712dfc9969d7cc6b04e92a8a2f5e1dfc"]}}, diff --git a/txscript/data/taproot-ref/9ea50ae0758462d0e77fe1397a5af6f83ad15f39 b/txscript/data/taproot-ref/9ea50ae0758462d0e77fe1397a5af6f83ad15f39 new file mode 100644 index 0000000000..526eef44c4 --- /dev/null +++ b/txscript/data/taproot-ref/9ea50ae0758462d0e77fe1397a5af6f83ad15f39 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0d01000000ccfbefbebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6000000000dc712be3025d9193000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5db0833e", "prevouts": ["4dd627000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "bd686e00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["cc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4c890db8e530b3b97e91b56063afadbbd8e6ac326e3356562c0a5ff1591f041d611c8e78922f12cf5b391747592eaf9e84d545161f4f09ddc8c51091bc04ba49d4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9132ef9050946e44b1b7e4a7390d57682430e3f2d85fcffb45dfde53ebbf6533b9ff415677aca4bd8bea8fa89699624d8c5f018d44ea89c1d7716b3c6d0480766d64d66e5a8ef59726e977ff218232e5171732e5d132f479dce590bd8ea056135478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}}, diff --git a/txscript/data/taproot-ref/9eafe1e70dda380dee958b8ae1138ab758f76857 b/txscript/data/taproot-ref/9eafe1e70dda380dee958b8ae1138ab758f76857 new file mode 100644 index 0000000000..62b7a4b8fe --- /dev/null +++ b/txscript/data/taproot-ref/9eafe1e70dda380dee958b8ae1138ab758f76857 @@ -0,0 +1 @@ +{"tx": "47c0016f0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700301000000248adfaddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca601000000923ad6d7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb500000000bc64099104f8507b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72f050000", "prevouts": ["71151300000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "c3c7480000000000235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "db32210000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["3f60ee6422cba2535462f4db96604e19e6933f9ddc844f2cbae9020787628186d28d2d4a69e121e342ddc673acb66f074bc82c6bc9cc69c5bd04dbc197acfbd0", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/9ee645ca92c85ae4515e7e01d35579bbc6cb046f b/txscript/data/taproot-ref/9ee645ca92c85ae4515e7e01d35579bbc6cb046f new file mode 100644 index 0000000000..7325539ad4 --- /dev/null +++ b/txscript/data/taproot-ref/9ee645ca92c85ae4515e7e01d35579bbc6cb046f @@ -0,0 +1 @@ +{"tx": "232bcb1b0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a201000000a1df09d060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f201000000b8a452ae04e91d1e0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87b413c54d", "prevouts": ["175e0f00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "f6db100000000000225120c230ba0a2d20add5df8769fc65d7fc3a12d7cd95ad679e3207a6c75325eb884e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f369480f07347d294c5ec55b6a8cae19a0490f895004383b3ec97d49c181391a"]}, "failure": {"scriptSig": "", "witness": ["6a2c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/9efceb8b8d6841f20ca0f194b19427087f5a97ea b/txscript/data/taproot-ref/9efceb8b8d6841f20ca0f194b19427087f5a97ea new file mode 100644 index 0000000000..208e66cd89 --- /dev/null +++ b/txscript/data/taproot-ref/9efceb8b8d6841f20ca0f194b19427087f5a97ea @@ -0,0 +1 @@ +{"tx": "a16810340360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270320100000001d67dfb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701a00000000ce8a8e9e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40601000000d70e389401384e260000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79622030000", "prevouts": ["40320f00000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8", "2701120000000000225d202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "41d2360000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "437d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e83b3e543c1be24a694e5b6685838ec47a730681350c8079fce99319dc90d9ab403d8f160074737ef82cfbb3f905f5039c6634e29d53352416ee52711c9b5e3cc1cc59ecfca53d850b1637d6273d8700d7dc702fb5baeba7c0d1778aadee75959b"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365897004e5f672ac93567f286623682ce4a0a35c34d22bab90c872b273d023f79eb1e69b2064177327a27f356e828bc3139f73429a3608cb2420b3294d8fc1681cc59ecfca53d850b1637d6273d8700d7dc702fb5baeba7c0d1778aadee75959b"]}}, diff --git a/txscript/data/taproot-ref/9f0427c58e85128c73cd97a9ba41519871d70331 b/txscript/data/taproot-ref/9f0427c58e85128c73cd97a9ba41519871d70331 new file mode 100644 index 0000000000..288a041d16 --- /dev/null +++ b/txscript/data/taproot-ref/9f0427c58e85128c73cd97a9ba41519871d70331 @@ -0,0 +1 @@ +{"tx": "00b76927028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4250100000051bf30848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c20000000038c234a6029a2a6e0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76c020000", "prevouts": ["61da3a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "77cf350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e0", "final": true, "success": {"scriptSig": "", "witness": ["35540c96d2bfcca0452351ba875b59e83ab1f4d5d0fa61dc4ed7ed92b4093546ba99177546d6cf56947268693dfdb10fd157965ad74192149732ea5f85c2b81183", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["34d491b130dcb0ae19d2353fbd64025d920e705161fdf0b754baf6a5b03b973c268c756e206c3a1f773d3ddc6e1c388ff03ae03cc386f617bf060655d0aca78ce0", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/9f07a530e3bc65a6d0a8da0a8ad697b5dc9ab202 b/txscript/data/taproot-ref/9f07a530e3bc65a6d0a8da0a8ad697b5dc9ab202 new file mode 100644 index 0000000000..9ad3cb0a2f --- /dev/null +++ b/txscript/data/taproot-ref/9f07a530e3bc65a6d0a8da0a8ad697b5dc9ab202 @@ -0,0 +1 @@ +{"tx": "4fe15df402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c790100000077a4d0f7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1801000000465f338e022e7dac00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac43000000", "prevouts": ["f92b510000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "5e795d00000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "437d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362c503a4390cea1e1efd273895e3e36c6de149914d80a97a30106137d896fa43dd9a73345c989c90f21221bc9fa2fdbe5d62b34ad323157a62317cd84046f2af72db79fc77699d349d3583c063c1ca5cb78d93faef419ab336fa45db1a25ff641"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a84e311995f98367a2a93ed7b61478a76d5defba7ed050312f02844091a9eaa94274b5900613cb2e14ccbb49f92be42e903262ce34f92c4d0a103e0ecbbdfe862db79fc77699d349d3583c063c1ca5cb78d93faef419ab336fa45db1a25ff641"]}}, diff --git a/txscript/data/taproot-ref/9f0aaa42e73656b0fce8443aea84266d564470e9 b/txscript/data/taproot-ref/9f0aaa42e73656b0fce8443aea84266d564470e9 new file mode 100644 index 0000000000..40449f7893 --- /dev/null +++ b/txscript/data/taproot-ref/9f0aaa42e73656b0fce8443aea84266d564470e9 @@ -0,0 +1 @@ +{"tx": "4b419ba103bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe30000000088c28bd08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cb00000000ab5264a260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709f010000009807c48504d038ca0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d33e7c40", "prevouts": ["2bbf7d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "af753c00000000002251204b9049d3a4bee03b6d234dd4c8f499fa4ef0a49d04247a5113735801c2defee0", "5551120000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368f473022b83f4d732c0de08884fc6e64a6a991aee44950e226c71d5763f7c410"]}, "failure": {"scriptSig": "", "witness": ["6a73616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/9f1fe443098130f838ce7d5c1460cdc0f13bb12e b/txscript/data/taproot-ref/9f1fe443098130f838ce7d5c1460cdc0f13bb12e new file mode 100644 index 0000000000..b1ded70f7a --- /dev/null +++ b/txscript/data/taproot-ref/9f1fe443098130f838ce7d5c1460cdc0f13bb12e @@ -0,0 +1 @@ +{"tx": "d4ff116302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0900000000f64f3be68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c482000000007d0525a00173622a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796d17e085c", "prevouts": ["e5b54d000000000022512074d6c61045a03724ef8fd881d073e11ff568ecf53a923220aba8b11cef73942c", "fb75340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_9c", "final": true, "success": {"scriptSig": "", "witness": ["802a42ae5675834395947fcb3301ea27e1f88de1c06305b5e411769cc3eb0f7e6aa758fee41cb45d165baada061ef4f9ad04c228c39304ceb2cde313b177aea602"]}, "failure": {"scriptSig": "", "witness": ["0355d69a42e370d45f177be489afefe75cf14be29e730dfc681d2c9b39dd86de1be6d1b5e5a13e8724d662a1ecebf029a01d9f93ab41eaf4dda7039e1b9bc8f99c"]}}, diff --git a/txscript/data/taproot-ref/9f282d2e013696b3d63d9269bf869f906bd8cef4 b/txscript/data/taproot-ref/9f282d2e013696b3d63d9269bf869f906bd8cef4 new file mode 100644 index 0000000000..30d63cce3b --- /dev/null +++ b/txscript/data/taproot-ref/9f282d2e013696b3d63d9269bf869f906bd8cef4 @@ -0,0 +1 @@ +{"tx": "40d9dd910260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cc0100000012faedd7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3e01000000bdce0ea40285d78d00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487a77b7a2b", "prevouts": ["2dc31200000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "55a47c0000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "947d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823ee723c85209fe64e13625f9e221aa1a5a0132ad156eaddb44490f9df3bced660235be472b05f11e998cd7dc8896eb16b23bac01933cdabddca8bd45937e3454"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cd5c5526e8b6e5bba0b8549e6c10fc917e32634749acd6fe76e24f40621e4ab46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa7085091e7b587d9e3d903161356c0634077d7e43e5aac1c0c25d5c3c805eac670235be472b05f11e998cd7dc8896eb16b23bac01933cdabddca8bd45937e3454"]}}, diff --git a/txscript/data/taproot-ref/9f78e819952e56d7b1961320d611fdc489b34e51 b/txscript/data/taproot-ref/9f78e819952e56d7b1961320d611fdc489b34e51 new file mode 100644 index 0000000000..6369115253 --- /dev/null +++ b/txscript/data/taproot-ref/9f78e819952e56d7b1961320d611fdc489b34e51 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ed01000000980d4ec98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40a02000000fb01bfe604d937760000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48738fdec36", "prevouts": ["e7e9370000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "685f4000000000002354212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "f87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367d28bb4086bcad3c01f7529c578d8b63b0b6c407c08968e5bfbdcc4c6df9aecac194f5b64ca7905ecbca48e3f65ecb2f68dc17df34a907a9e0813d7f728c588e9e87f1230a4dffa49f76a6d91b3ffe7dc371ffdd064326b56030bc36a92eabd9a0f16f4cfe8b052d74bbe565102becb5d9831a57baf41b6ebc95ac4a46ff7ed8"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e9b3730ae0e9b8e06af6fa3903dd842ff49b91f4387036eb6432f756cbb46a1de5422b6de6500db2bf907e4c5314ebb405475f57406f25afe5ac62a92a9e6c58b"]}}, diff --git a/txscript/data/taproot-ref/9f9bfc59905231b990a2d55faaa21a4cf26c8781 b/txscript/data/taproot-ref/9f9bfc59905231b990a2d55faaa21a4cf26c8781 new file mode 100644 index 0000000000..b1068a843e --- /dev/null +++ b/txscript/data/taproot-ref/9f9bfc59905231b990a2d55faaa21a4cf26c8781 @@ -0,0 +1 @@ +{"tx": "f43d36db02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1700000000fe6134a060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270be010000003e5d2c98033b5d8b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac2b000000", "prevouts": ["170b7f00000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989", "32960e00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "967d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fc1eee9341b55b342bc880e6adbdd53cdc9613ecba777072f7bcad421f4395212729135af56592d99186c3f010fd31ebf46aa180b9496740b245c4ec874c834ddfa3c45458ee21e782394432ca1779912e92f35e0ff52c3985a5265a8dee58b3654e31a1d81b19a8c2670362b3a1330b2f2d66c8db1c8314023a61983d2ff610"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936aab9624243e0b9e984d7a536e29f62b11f4b6f668202918f5cad885cf8171da63f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bf86d7708a8015fd8c392d5dfda539be3c55b3d42b83ba5bec57bef080407e280ad15d5ff3e747c4643a2e7779e2cae74c1db700bc0de7d47935e7ffa6ea968f"]}}, diff --git a/txscript/data/taproot-ref/9fd2c2accbc395448a7b5d7d8bcafd190ce329a7 b/txscript/data/taproot-ref/9fd2c2accbc395448a7b5d7d8bcafd190ce329a7 new file mode 100644 index 0000000000..9d3a8c1b28 --- /dev/null +++ b/txscript/data/taproot-ref/9fd2c2accbc395448a7b5d7d8bcafd190ce329a7 @@ -0,0 +1 @@ +{"tx": "4b419ba103bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe30000000088c28bd08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cb00000000ab5264a260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709f010000009807c48504d038ca0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d33e7c40", "prevouts": ["2bbf7d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "af753c00000000002251204b9049d3a4bee03b6d234dd4c8f499fa4ef0a49d04247a5113735801c2defee0", "5551120000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/codesep_pk", "final": true, "success": {"scriptSig": "", "witness": ["5164a501ab32e15e9e3c23adadff22bc621cc2941d2556b87b03a508ebcedf186b1452f373101e87165c0e90b925b2d6a2d4504ec6df161837fe6ffdf88a89a601", "ab04ffffff7f20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba05000000800087", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da6cc091e0a8cd8c992defa26813cb6b91db62f9622e0f05cf39923c26861d57bac00967532285e5651a233a5d3d97b0c986d2b78702c704bc34e0fc184218be"]}, "failure": {"scriptSig": "", "witness": ["9b67a30061f0a5c1986b1876193bf412b442c91cfc03ca8a1ebf0eb10c08a58f9311887d9d686725e982104112362571b923525bde686102f6f12be796bfa69f02", "ab04ffffff7f20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba05000000800087", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da6cc091e0a8cd8c992defa26813cb6b91db62f9622e0f05cf39923c26861d57bac00967532285e5651a233a5d3d97b0c986d2b78702c704bc34e0fc184218be"]}}, diff --git a/txscript/data/taproot-ref/9fda11dcb9654da892e82b6566c4aeab962c8278 b/txscript/data/taproot-ref/9fda11dcb9654da892e82b6566c4aeab962c8278 new file mode 100644 index 0000000000..2fb24ec291 --- /dev/null +++ b/txscript/data/taproot-ref/9fda11dcb9654da892e82b6566c4aeab962c8278 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c71010000004ff55bce8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45000000000c0c2d20502325f8a0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac3b000000", "prevouts": ["c9644d000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787", "75c53e00000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "96", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ecfde006308150423bef8aa56b6413bd3f073574ad71e6210b8ed31bba8cafc4eb4e626fbd1c5a1d96a595c16e39be42f50aa7a1faa8ff1a1c0cc640b6e10eb9874a9774daa89f30be275a1ff5113653dfa1548b9628ff9725cf694401ebdfe4"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362fbabb5db73937a530b9f0def2837a539507418901e7622f5d905eab1607cdfc1bdee2e16a63898e861f6346f98a8f5f2a90fe2be47e52912f18205e56fa5c07b35fa22f4b25dbc3a6b67e691e1ba7f45df255baed4abd058cf23fbf36a7f21681a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}}, diff --git a/txscript/data/taproot-ref/9fe5d577717a9a11e4740f29f231fa15b9f4d01c b/txscript/data/taproot-ref/9fe5d577717a9a11e4740f29f231fa15b9f4d01c new file mode 100644 index 0000000000..d1680b8e96 --- /dev/null +++ b/txscript/data/taproot-ref/9fe5d577717a9a11e4740f29f231fa15b9f4d01c @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe000000000930c87d0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2a00000000cbde473a01036620000000000017a914719f78084af863e000acd618ba76df97972236898797860936", "prevouts": ["e1c0710000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "1def81000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "47304402205b083d7b3cb3f17ada2bc1041ba1de5c663db5e5ed4e79b6029a95c605079f6d02203e8ccb853b5b8db54c9c5faff5397c824d2675d750efb31c5c69ba7ac39ddacd82004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "483045022100ee78dba8677223030aacb6dd161326d004e574759eb4103242f0c00172948727022030adf79c1c6abc4c5af368abd91cb228f7dd70b3b4b1279079a8f32c67d05f658201014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/a01b0232919914b0a33ff87262f8ba59543b0ab6 b/txscript/data/taproot-ref/a01b0232919914b0a33ff87262f8ba59543b0ab6 new file mode 100644 index 0000000000..a10a2233cd --- /dev/null +++ b/txscript/data/taproot-ref/a01b0232919914b0a33ff87262f8ba59543b0ab6 @@ -0,0 +1 @@ +{"tx": "5546a66c038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d400000000b5d77298dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b120100000066b879f3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfda010000004fcfbcc7041d3ac4000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf2010000", "prevouts": ["968f3a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ebe5240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d3e1660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_95", "final": true, "success": {"scriptSig": "", "witness": ["e84803ce85205a41a43df53d568f63f8f346b92a1e7bf717914f776b12834ed1be3f55a2f58d18d24a06f24f0f902667a5d94f4d24a6503c3f979bfae6764128", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["89dd635496138974a37ebffedfe59f49ad8e2097daaa3857a104e9fa608215165971823bc03bc4831d9d012681a530de54da49e895e32d446c4a3bfae68f9dc895", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a027f0c1c564bf78407eed47f2a9f03c60eadc02 b/txscript/data/taproot-ref/a027f0c1c564bf78407eed47f2a9f03c60eadc02 new file mode 100644 index 0000000000..0ca1e02774 --- /dev/null +++ b/txscript/data/taproot-ref/a027f0c1c564bf78407eed47f2a9f03c60eadc02 @@ -0,0 +1 @@ +{"tx": "fca5d31203bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb801000000d35e6ddfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4001000000e5f842af8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49500000000cbb138bd029ea525010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b6000000", "prevouts": ["208c780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "859d6f00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "eaec3f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e6", "final": true, "success": {"scriptSig": "", "witness": ["121e62952257555587343d62e407df07dc5b15950df2db8c56570a4d2dc1bf1b7caf6a9f4ad1dcc7724d58c75774aedcf52142bb9b675403eb3b211c013fdf0882", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["951e0fb07e827b0a8f589288751d295eb266246153395c5d65c3e78fb204249fe9d4d90b7a5e81945f948c4851b08b14f4e617d52c53daa7219bafec8ec3f546e6", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a0482c5ebc234aebacf836bed890b373827b5958 b/txscript/data/taproot-ref/a0482c5ebc234aebacf836bed890b373827b5958 new file mode 100644 index 0000000000..5cf0817361 --- /dev/null +++ b/txscript/data/taproot-ref/a0482c5ebc234aebacf836bed890b373827b5958 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d60100000045a55a8fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c760000000073f099380186396800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2586664f", "prevouts": ["f629120000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544", "06e05a0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["ef", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93652f3ac1aace3c10cf444e97bb7d38ad5b50faf5df229a4892c0d3ad9e10ad091215b4c606cdda8e0cd0631e1e6566a3457cf9b2eb8ccfe9cc1918e65b703d3f7cd241e6bbc5ebedd8f50ae206f1f82a1e41ff5c139455a0ddb0d368f52a47602"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41645f371c8079005f8f776d501e78f2a21020e20da39870ba1dbf85c4a15b7eacc28207c7af5a37f80d9c7bda068b6f89abe5b5cf72eaf80ed3e31c2f1c9dfaa6c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}}, diff --git a/txscript/data/taproot-ref/a04e38678141417445359665f17e2c444cc55835 b/txscript/data/taproot-ref/a04e38678141417445359665f17e2c444cc55835 new file mode 100644 index 0000000000..8be635df29 --- /dev/null +++ b/txscript/data/taproot-ref/a04e38678141417445359665f17e2c444cc55835 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffc010000000732978e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270880000000072fd39a2034e918800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e776a0d52a", "prevouts": ["c1b27a0000000000215e1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "57e90f00000000002254202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["e4eb2e5c01db2c5b9db34a40e1ecc9df9d595262605d1edfdef071ce3b0817d8eceada0922be4bad565f02cddc3a9e4cd3511d2d4e5d807c47c8cdd21f6d5468"]}}, diff --git a/txscript/data/taproot-ref/a05131b921bd9d6b4ea47f249e51ee98efc05f54 b/txscript/data/taproot-ref/a05131b921bd9d6b4ea47f249e51ee98efc05f54 new file mode 100644 index 0000000000..2dc645c35a --- /dev/null +++ b/txscript/data/taproot-ref/a05131b921bd9d6b4ea47f249e51ee98efc05f54 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc7010000003a0d4fc5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1700000000c98173e6018bbc4f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87921bfa49", "prevouts": ["658421000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "ad0a4c00000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "", "witness": ["30440220617804bde9751b8e890809c5ae8cb4248073155a3e13528353f768c0f0ba8a5f02200113f5d6ecccb5da08e0bde30bdf39c3c00a0780d316404fff35f4a72ced2b0003", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["3045022100f18a3f95e2004bd66a0a3a0815525e7972b561d3e272814b34c80e0281bb5263022002f128c1be80d75ebafe7a5b7d39090b044fecf53711c2c207993e40f9d4341d03", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/a080874cf108744cedfbb712de9629eed229ec49 b/txscript/data/taproot-ref/a080874cf108744cedfbb712de9629eed229ec49 new file mode 100644 index 0000000000..337fe5c37f --- /dev/null +++ b/txscript/data/taproot-ref/a080874cf108744cedfbb712de9629eed229ec49 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42001000000e00a97b08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c413010000008f316cc504fb1b70000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a640010000", "prevouts": ["14ca400000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76", "66fb310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_26", "final": true, "success": {"scriptSig": "", "witness": ["23388bb3a5f4f6abb0332f564b193dc02a0cd02cc61add95565958256289a4f6d6f0acd3a0109a874c4b9506ba9e20009fc8531f773b5b27389417744e41482481", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7a2c9962cf680d1a1949e1777423a989b9237cd5a84cbba496f3845ecf411c7fef3976ad52bf74807c25f8416ebb7b109279aa53cfa926a8d478ec4525563db326", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a086f46eaeca09d3649d592dc5a55044d8de1f41 b/txscript/data/taproot-ref/a086f46eaeca09d3649d592dc5a55044d8de1f41 new file mode 100644 index 0000000000..7a0c4a5a83 --- /dev/null +++ b/txscript/data/taproot-ref/a086f46eaeca09d3649d592dc5a55044d8de1f41 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b990000000015e6e6d3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3c010000008991028ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6901000000414a92e6031b996c00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acd3000000", "prevouts": ["7bf1270000000000225f202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "1007280000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f", "867e1e0000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "d27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa1260ed9ec9ab1e79007d15fbab81df65c0fb14652b0fe58f2b730a3e13657de0e39f192d4dec24b48e9231a08b7d2e64fac2040aad69c16c1d9eedfe5fb62ebc"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e00def9a487cc21401761fbf52dc8ab7b9916cdeb8a2e13a665b6447e5fe6b3009b801fc18e2353a9cd4de337bb33433fbe6225e21bb8b5572b0acaa50d11b7f3"]}}, diff --git a/txscript/data/taproot-ref/a0951cc6042b25d64914d945c4e3758a0407ea87 b/txscript/data/taproot-ref/a0951cc6042b25d64914d945c4e3758a0407ea87 new file mode 100644 index 0000000000..8cc97d8112 --- /dev/null +++ b/txscript/data/taproot-ref/a0951cc6042b25d64914d945c4e3758a0407ea87 @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c201000000284b139001864900000000000017a914719f78084af863e000acd618ba76df97972236898786010000", "prevouts": ["6eef0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_68", "final": true, "success": {"scriptSig": "", "witness": ["677efcd2049ae6dbb42fded0ce28f72dd12eadc92f8136f6756f9b034b8eb7615d6066c637acda634ea7548db5f5369997b43b662a9375a2b26966087b42c43102", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a55fa646dae7e86847c3d31ed2c1676129007e5469172b8ba702009de06d4c7a70938f5e4ef21cef3af388fe1f3f68c477d0d03b08b263b35e32ac42dd1a020568", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a0c092d70e81d7131ac1cb03d9ac8db9d2c0709b b/txscript/data/taproot-ref/a0c092d70e81d7131ac1cb03d9ac8db9d2c0709b new file mode 100644 index 0000000000..4374c92962 --- /dev/null +++ b/txscript/data/taproot-ref/a0c092d70e81d7131ac1cb03d9ac8db9d2c0709b @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c00100000051c121fa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703b00000000d8839a9a038a522100000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874c59263f", "prevouts": ["e94a12000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "eafe1000000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "b47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a8eb7b62c5fe5ddbc3113da031846421086c0b7ab5b0b159fa40d7d79be15e64eb712e9c877d580eafa00acbc739496391db115356dec5d41c0ac008be904b5898ae4fb28ba039f9030001532aa52d54afebb8b1d186c7283d6707334cdf0cf3"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed5b4f8de6a475e1475ecf0ed158bd12476ce010b28dce6527e02a32226fe48562e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd7e736a60655dc533a38837433a3a305c9a2d5b0314030c91796018120c3e9a44"]}}, diff --git a/txscript/data/taproot-ref/a0d64b88f7e1a35f28c08292725d25214520f7a6 b/txscript/data/taproot-ref/a0d64b88f7e1a35f28c08292725d25214520f7a6 new file mode 100644 index 0000000000..c959d27ec1 --- /dev/null +++ b/txscript/data/taproot-ref/a0d64b88f7e1a35f28c08292725d25214520f7a6 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127075010000009e5d05f1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0a01000000bbe4edb3018e8b46000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478715087253", "prevouts": ["3e281100000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8", "f75d75000000000021601f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c57d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363903e3bb34d25cf71b6983cf4f2b76fbc603b2adde28e34b23c45d7f67d4a2394a4f1964bf857a391dd30579e6c45654815fe99168eae3a652a179c44e1715327def1cc2232d9b1ca5244635fcf6779cb15e82fb856baa2ca11d8fd1da35295f"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e6d35158b06e93427cedf9700445f423da8a62a86b9572893cb3b0c5b8130f93e00378a892e4dc43a17c9ebd71803200f2f24c9a40c2827c304e59be9b4a7df0b"]}}, diff --git a/txscript/data/taproot-ref/a1258cbda9cc624bb9f238882cc84253a1dc87c2 b/txscript/data/taproot-ref/a1258cbda9cc624bb9f238882cc84253a1dc87c2 new file mode 100644 index 0000000000..eca64a77f4 --- /dev/null +++ b/txscript/data/taproot-ref/a1258cbda9cc624bb9f238882cc84253a1dc87c2 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4910100000045a9a31203bb9d36000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8724030000", "prevouts": ["845f38000000000021531f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["1dff371c0f48cfce29e4d1379377185cdbd69cc7427224110ab9dff4e29f28ea6b2a1651841473ef5b0f5ed2ad0fbe587aaa778f04f4456f364ce1af0851add6", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/a1430a0798548b8c620d89157e6f2a54d9f94f2e b/txscript/data/taproot-ref/a1430a0798548b8c620d89157e6f2a54d9f94f2e new file mode 100644 index 0000000000..d7c29e8a53 --- /dev/null +++ b/txscript/data/taproot-ref/a1430a0798548b8c620d89157e6f2a54d9f94f2e @@ -0,0 +1 @@ +{"tx": "98b7339702dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6701000000ce4b1aba60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d400000000185f3c8b02ea2a5d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48721010000", "prevouts": ["58bb4c00000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7", "60a5120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_88", "final": true, "success": {"scriptSig": "", "witness": ["9ac70dec29b2d3b092978378623c536333802faa1d197b5a9126542d8a8f655c9825ac68cf05536e49b469ea4e590d48d4b1d33bbfa2f030852beaa3d03733db02"]}, "failure": {"scriptSig": "", "witness": ["1d0539899e4afc00c6b5a2a46c857894e39ef5f40ac0f41971a439b814642001fbd0475b4c60100e0dcbca00073b89b31aab779df85964e6e4e4ff412eabd0bb88"]}}, diff --git a/txscript/data/taproot-ref/a16835f468084695f51026fc26ce3f842fc97714 b/txscript/data/taproot-ref/a16835f468084695f51026fc26ce3f842fc97714 new file mode 100644 index 0000000000..b31e7575db --- /dev/null +++ b/txscript/data/taproot-ref/a16835f468084695f51026fc26ce3f842fc97714 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0a00000000de79a0db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48d000000005b9d85b103a002680000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787cfaf4061", "prevouts": ["7c9e2700000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "aaf3410000000000225120efa68a115895f942057851c042deb7d61335a3ab48b9e56d15cb953fb46ad7bc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93693a02b6204e347b33b2d98f85c3b8af4711c830846c7f7c064463fb607dbf182"]}, "failure": {"scriptSig": "", "witness": ["6a45616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/a17272e8d29e6c955e3b27761ff0e3908e202ff1 b/txscript/data/taproot-ref/a17272e8d29e6c955e3b27761ff0e3908e202ff1 new file mode 100644 index 0000000000..258b3bd2a0 --- /dev/null +++ b/txscript/data/taproot-ref/a17272e8d29e6c955e3b27761ff0e3908e202ff1 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cea00000000937427d7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5000000000476245d802ecc273000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689870d97cc2d", "prevouts": ["dbfa5400000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "704f21000000000021601f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["504c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f933d08853672a2275403f631a185860433b7a30f3dde2a4cbab45ca4cd5b5bf04d1c6645dfa5bcea0755bc1d945f129b754bcfdfa4df703b30809220c35586032cb43424d7ca27a7abc5fd0c2fa249f92b1e992144deb3864a86d466f79c2cceedc10b0e9ea9319d9c2157dfe80b60aa665931711963da9ab109764ff1ab789"]}, "failure": {"scriptSig": "", "witness": ["4c5250", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454fe66249dd01ecee23c2f5e0ab3cfab587707d36ba83a587f4ef7ad777b411580826552c6add4a61cb16ac7f3706b11d0158c18b61683494ca90054287b9ac7bc2fd9879a2ee2ae7d76224c991edc718b1729f7f1922f570a67a21926d2cc48d"]}}, diff --git a/txscript/data/taproot-ref/a175484c1508738494b7c85ab928bb65c4a07f42 b/txscript/data/taproot-ref/a175484c1508738494b7c85ab928bb65c4a07f42 new file mode 100644 index 0000000000..bf7986859c --- /dev/null +++ b/txscript/data/taproot-ref/a175484c1508738494b7c85ab928bb65c4a07f42 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709a00000000122eac46bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdb01000000f84b9d610414df8a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acc3010000", "prevouts": ["2fb60f00000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "e1c47c0000000000225120a607964ea93077ca088588fe8df58ca0f1df7737d7763c94d5c7768cbab371de"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682236f031bcf8158863f62814cbcace59e68087524fe7963c37c3cbb351e6c152016530e482bf934dddf93f5dc5c8477f8e54d8918bd8c9b20d47f007dad28fe6f3617d560800e971f99646d89bd2028caf0c6d02b6f505a11fcad3ec349c801"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd05043d7db3391e92844c941c401bd083e4053f3eb43fc17e8ceb6537f5686293df6a2e62376e6a3587300ef2d1a395dd90428413a52508272625b5a1a189adb591a16be56540de55d9fbfa115de937b3aca1e4dd0f5a93f17ebd2ebda95183"]}}, diff --git a/txscript/data/taproot-ref/a17a5140033f84e309aac8415b2a580b4050203c b/txscript/data/taproot-ref/a17a5140033f84e309aac8415b2a580b4050203c new file mode 100644 index 0000000000..461b47d017 --- /dev/null +++ b/txscript/data/taproot-ref/a17a5140033f84e309aac8415b2a580b4050203c @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9d000000009313006660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701800000000454fe720038533720000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4cdccd43", "prevouts": ["d1d765000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987", "7bc40e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_8b", "final": true, "success": {"scriptSig": "", "witness": ["51326a5167baadf31a00bc3d2b48d3c3cfb07acf7730c83e95b38e5f666f75d92979d2e684501eceb5fbb9af8c7a86d08ee9b429114ab4cf3cda44d753dcaff7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["6b16e7f81810078d188c33250f16bffb3f542f0b746fe2adfd7b71f3b3c5d5f11558fb927e6ecd7a2e948e784074b97926eaa25f45e014a4cd3f6163ee64fd3f8b", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a1b572d1fe5a9c9111033297ae5ff70014c256ce b/txscript/data/taproot-ref/a1b572d1fe5a9c9111033297ae5ff70014c256ce new file mode 100644 index 0000000000..e42ed982fd --- /dev/null +++ b/txscript/data/taproot-ref/a1b572d1fe5a9c9111033297ae5ff70014c256ce @@ -0,0 +1 @@ +{"tx": "bec0953402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9e0000000094ed6d9960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270eb010000004ac8e1f601e4ee1d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8789e0e922", "prevouts": ["686f600000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "10e70e0000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f768", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173afdf1522df456d7fbfe0d29a7744cbe637017dd01cd6de5bb6b2c07ed06f430b01c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45438ad321f710317d8f3678f772f8337c845de7a4601c479cd7219e318503b74fdf1522df456d7fbfe0d29a7744cbe637017dd01cd6de5bb6b2c07ed06f430b01c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}}, diff --git a/txscript/data/taproot-ref/a1e666afd74df95cb5c06318730dff9116d6a22f b/txscript/data/taproot-ref/a1e666afd74df95cb5c06318730dff9116d6a22f new file mode 100644 index 0000000000..7b62e01096 --- /dev/null +++ b/txscript/data/taproot-ref/a1e666afd74df95cb5c06318730dff9116d6a22f @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c22020000002413a1c9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6701000000ebf5dac603056f6a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca045f754", "prevouts": ["7aa5480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "691d2400000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "997d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93659100ab1d99009eaf631522d0390412a62a32905c7f687f8ed538c1d75c8e249e3e7df71444e7cc76d8e211582e4acb0f4a71a503115fbd605db9d475b3b0609413afa0de0ff2ef52577d4c80443f6003c675907986908c28bc93ded208ca160"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93617fe6272c5fffac4ddc4c47d3a6fc8218dc4d9298ec687e863b37acdb8199f2e2e3b986c0375fedeed2562a6fa36a7b38b0ca47fc0125e42be2f4bc52e49716a3d673df10a8cc98fc65477367c7f3bb838b82569297570384f0d4df8cd49e6dd413afa0de0ff2ef52577d4c80443f6003c675907986908c28bc93ded208ca160"]}}, diff --git a/txscript/data/taproot-ref/a1e97b7bd972796aecfd4b83180776a015f64a8e b/txscript/data/taproot-ref/a1e97b7bd972796aecfd4b83180776a015f64a8e new file mode 100644 index 0000000000..f3e5d82a45 --- /dev/null +++ b/txscript/data/taproot-ref/a1e97b7bd972796aecfd4b83180776a015f64a8e @@ -0,0 +1 @@ +{"tx": "d9cbeb5702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b06010000007bcede8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706901000000a3cb8e8102bd1e2b00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acf751961f", "prevouts": ["eec71e0000000000225120761ee5da1a196558fc88c883f4c68738765f8bbbf6c28fcf877f70c5de6e3c55", "e7850e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_3c", "final": true, "success": {"scriptSig": "", "witness": ["c507825b3f9bf70f017994ae1df5ac75578936bead8bb05b78cd70c87125a69a7c46fbadf9b2f51f4e2765a6106a176d24e1a4992539ba56828d4985faab548682"]}, "failure": {"scriptSig": "", "witness": ["01244039c8ea5b9a2a132f9b114e5b22d246af4e78d2cceebbd75f5796d4155d064da7f5887bbf9ab0b3ebb7fdf2e1da9e2aed8854c5fd92415f57eff6efa0343c"]}}, diff --git a/txscript/data/taproot-ref/a2124d0d2b17ee1f1e0998338eea25cffadf437c b/txscript/data/taproot-ref/a2124d0d2b17ee1f1e0998338eea25cffadf437c new file mode 100644 index 0000000000..b26aa4a44b --- /dev/null +++ b/txscript/data/taproot-ref/a2124d0d2b17ee1f1e0998338eea25cffadf437c @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf03000000004470afcedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5e0100000089cf15fa0167036c000000000017a914719f78084af863e000acd618ba76df9797223689875024b63a", "prevouts": ["d3667100000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a", "6789570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "627d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369bc6aac193a2262f175e26a90d4e5bab3913dfe7b51f554c807a6921f2d2c0809fadf8666e14892eeb42c4caff758b4cfca6e22c4a95966045c21c8e48555a5679949ec80dae58a557a09f1025b3e427a5f07bf4ca030ef1ccb63f0b9143cb03815577f72abc2219d93608f0bf386debaad95a87d0f429ecb808b0f22f69367f"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082be3373372acbd8f7355a742b339dc4113bb3ad1c8e82e6b2233d51ce74beeba4a979a031634820b293704e38f33c20e5acd9cb2a8735bda71fecc5f77708044027529efe07ed3ec82dce77345a5c0eb368b138839946732056b6a908dbf5f05c"]}}, diff --git a/txscript/data/taproot-ref/a2135bcd7d491b07a72fbd501a3b0be1b9f3bdc2 b/txscript/data/taproot-ref/a2135bcd7d491b07a72fbd501a3b0be1b9f3bdc2 new file mode 100644 index 0000000000..0c692030f8 --- /dev/null +++ b/txscript/data/taproot-ref/a2135bcd7d491b07a72fbd501a3b0be1b9f3bdc2 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41001000000e9f03e5d0270ce3100000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7f0d49b42", "prevouts": ["99d0330000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ca7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fad3ea1307367f624c7798ae24e76be5e7488cb515c8e68b506a720d3dc582d682065bfcb7199ff8296c5f7d41f3b2c6067d88c0a33f2878328c609d56cc191f12"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365151d9a62ecf9f92cdb971a6167587795b5c91d8697e265bdca4e7bdbf735582d3ea1307367f624c7798ae24e76be5e7488cb515c8e68b506a720d3dc582d682065bfcb7199ff8296c5f7d41f3b2c6067d88c0a33f2878328c609d56cc191f12"]}}, diff --git a/txscript/data/taproot-ref/a21f2d7b6393cda8bcff8df7034062e8925f6377 b/txscript/data/taproot-ref/a21f2d7b6393cda8bcff8df7034062e8925f6377 new file mode 100644 index 0000000000..7290433b26 --- /dev/null +++ b/txscript/data/taproot-ref/a21f2d7b6393cda8bcff8df7034062e8925f6377 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d200000000e2e3d8f2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc5010000003f7b88ba0234cb5c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3c020000", "prevouts": ["62951000000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327", "bbf54e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b0", "final": true, "success": {"scriptSig": "", "witness": ["593d88a581ae2068becbab43fefd1d17ffa613cb98b37a3a8b63ef4e476e067e8466eed57b0e08ec18bb88d000e9f14b8ebca24888c0eb6db06d114e3db4d622"]}, "failure": {"scriptSig": "", "witness": ["d829372431cc203d9de3d6850a28ee9793748eaeb53e292c2533a44764cd414f387231fd303d2e96344cfdca1088ba84d673a00c19704086f4c137bd223abe4bb0"]}}, diff --git a/txscript/data/taproot-ref/a2452fe77f45ef6a612ce676a6ad9d9002b9331e b/txscript/data/taproot-ref/a2452fe77f45ef6a612ce676a6ad9d9002b9331e new file mode 100644 index 0000000000..63d8584c8f --- /dev/null +++ b/txscript/data/taproot-ref/a2452fe77f45ef6a612ce676a6ad9d9002b9331e @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4eb01000000db6b973760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706401000000f98306f1010fe10c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a648000000", "prevouts": ["3f4243000000000017a91448274ba0d73ec00ce63e7922c9d87a48fd0c670f87", "04e712000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_mis_83", "final": true, "success": {"scriptSig": "", "witness": ["90cbe6d26f857fa883258d920cbdf22387c79b10ff494ac881ac7757bd1e49ffae3b557583913b4161163c1bdefa8d417579be5431bdc8c5d22fd8e2d9a327b182"]}, "failure": {"scriptSig": "", "witness": ["e4c347484f9fecee907d5ea84cf457aacabb6f8628c4b46d156aec0ee8fafec3905ca034020a3f856ee7e9b76dbbbc88be6378dc1afd24b3a26160548236d48f83"]}}, diff --git a/txscript/data/taproot-ref/a25b4431040ecd4aca97dad2844cf0080a40800b b/txscript/data/taproot-ref/a25b4431040ecd4aca97dad2844cf0080a40800b new file mode 100644 index 0000000000..d6c2f415bc --- /dev/null +++ b/txscript/data/taproot-ref/a25b4431040ecd4aca97dad2844cf0080a40800b @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1200000000ec2ee3f4019a091400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acfba1de46", "prevouts": ["2b2f5800000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["96", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ecfde006308150423bef8aa56b6413bd3f073574ad71e6210b8ed31bba8cafc4eb4e626fbd1c5a1d96a595c16e39be42f50aa7a1faa8ff1a1c0cc640b6e10eb9874a9774daa89f30be275a1ff5113653dfa1548b9628ff9725cf694401ebdfe4"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362fbabb5db73937a530b9f0def2837a539507418901e7622f5d905eab1607cdfc1bdee2e16a63898e861f6346f98a8f5f2a90fe2be47e52912f18205e56fa5c07b35fa22f4b25dbc3a6b67e691e1ba7f45df255baed4abd058cf23fbf36a7f21681a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}}, diff --git a/txscript/data/taproot-ref/a26f67d81684b9007a2109269de4afe49d23f938 b/txscript/data/taproot-ref/a26f67d81684b9007a2109269de4afe49d23f938 new file mode 100644 index 0000000000..f334688527 --- /dev/null +++ b/txscript/data/taproot-ref/a26f67d81684b9007a2109269de4afe49d23f938 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a000000000a3952b5460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fd010000003122469d0459d21c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374877bbe1c4b", "prevouts": ["18610f0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f", "4db40f0000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d9c8c610c58b12163b15ce1ff0c983435a041d13f702eede880a5fb51dce7b8bbce26b858ee1964694df49c854956bd940a4e6651ee2613ac0889a0ca62307c4d72c52511105e97e14983251382fdf68bdae07d0042fda702379b1c9403b67023e44a45315583d327e7312b81cb8f53dec35ca32de8466ced99ea71e9219129b995e0663487f2bddd900c74ad42782a9c835acf86207646b774bb477d587572328d90ae425554246818ac43f1d8e3b189c8d28461b4468ccccadd31674ae163ffba23d7896e9fb65f8b9c99c34057cd73f6c86893f7320894b884c7553efe7e6e9881b7f88932f10cff6d493bcb0b95fb7fb160789e627bbc1ddbdf36f06957c30c8bff80af6305085aa6f36b4c0400a971cdaa9bf8afda35dcd11ddff5f5cc4339a6d602f30bcbb976d6aee00e81841ed043a959ec2150fd868d7d849e322ea402535fe2183efadba2ec82321c80eb01e2a2ba6abf2833171702a9b9e775833f9ca70f37ccc835cab225090255925fe40be04864f85fd2e70ec40d6a6388ffc9fba87c716c3f00dceb0e97a83bb8a7b27cb9f65fa4299aa454db0990a2f0fb75376f4c95368491900fa2baf8982997c80dafbd2a045638462df603e9dd00e03b9ce90595cdfa04ad10eff0cecd58163bca944cb97b5af01389b995b0a9b8b370a57d548957b25b256ab1cb762fc77324128f5e195aa0cc0215b6abf664ade60af5ebca4b7731154c775", "617d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4e8a9e18f0e69854b67be61a040c3060df6bfbf530bdefb330c865ce8049deeb0e931380661372836164f4a50b3ffb46f1fe83bc177b7c1bf309591800c178bdd304186c0a2faa80f59261766b0cb9b0760b78eb1f31f166a6f091ab62e6898"]}, "failure": {"scriptSig": "", "witness": ["4d0902430eae536e3faa601a9e76609811e76a3dfc9a1296c3e47ed14eccd00ec12de8dd5d86813dae402d0b309129da5fefe13b09e30658f5ee798ab210d2775dc0a835fb84cdedd3a89c8384a99c1f27a8a08052caf06188bd85a1d3a0f89c84ed2549097a76c87343fdd01621a6be421df0dbacffeb3589a7f504fb7b848f2ad4ca397b67e75756fb22a37fa4599f826f59e839e770c7b9d6487b7fc434d93ee1a7e78a8c75413a1ab29c3ab90dd2d2da6875c8542b2422f24cad7e5d2ba8243962940a1f6505284a704c10e28c577929c8e74f23d96b5d5929431fac1a7e75ab70a2a1ed9bd2475b07253d23686033a4e465b9eb32a20a4b81419d3c4796282d298dad6e2610f415f1be2c43720702653bbb467da91390ec7d74a7fbfa0c21b0d116ec394b7205aabd6cbf62257034a44414eaa5f0c50d46b9e388cab815cbd45b683f69a72a94302de34d5294b8f6d7712e69ad8ea68f827d9f874ec3b54815cf2d8697984cbfb270c068d2e89d23fb88fa8b9bab375b563a102ebb2de69a13d7c7bfbde807c8f50896b4be261043eadc465e458adc207757d425860b53617b5fa7f5f6f2b7f95cbf1b878204488b467f7178cffd1ef316dab4bb1732135b3de5b9bb227e511d8a56578cd3668750c23119f3df2ddd45f85fad2af46c46dc6aa36f34cb815a642f2352b403db64e2b4fa77d4db8e6e14ac3ea1c25d10b6a911a95cbb7076c9ed3151bf75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d6338037856eb5e5100eb03828e7e22b5e2035e7682cbb657d792b71d534eb2f43a93d7e1c40927dcd10fd5d28aa4402a453542c320ae883aef57b2a7090ae6b3ab6b2d4691bf881316931c587f0a213fdb9026021e80f212e72f88982a6bfdc"]}}, diff --git a/txscript/data/taproot-ref/a293d31bc0cff7b14f873a325579ef283c8e2068 b/txscript/data/taproot-ref/a293d31bc0cff7b14f873a325579ef283c8e2068 new file mode 100644 index 0000000000..0b91537104 --- /dev/null +++ b/txscript/data/taproot-ref/a293d31bc0cff7b14f873a325579ef283c8e2068 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb501000000739790e5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc401000000d48d3cbfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c06010000008bfda2e203856df3000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6a988fe22", "prevouts": ["3bb34f00000000002251201aa53d82b3e96e8e01ae5203880cf5cebef0e054596b6f65010b7ca42a314e33", "5cd8500000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "7f6954000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93636ec3b08c91f84b7488277bf883618c6df6d611cc9638a5cd67e555f32bc0de1"]}, "failure": {"scriptSig": "", "witness": ["6a26616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/a2a3d1e6a386b04424a390d174bdd394f0b88602 b/txscript/data/taproot-ref/a2a3d1e6a386b04424a390d174bdd394f0b88602 new file mode 100644 index 0000000000..30674d104c --- /dev/null +++ b/txscript/data/taproot-ref/a2a3d1e6a386b04424a390d174bdd394f0b88602 @@ -0,0 +1 @@ +{"tx": "6a7bc0ae03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2d010000005909f2bfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc501000000c4642ca8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b22020000008a37259c02ef808b00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4c7b8943", "prevouts": ["697b510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a86c1f0000000000165b142540f27e90740933c99d4f17ab2dfc6c82951cfb", "e3fe1c0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["1c8ae8c42dca6eec413a2a33e76060a08817f826743139ab4caefbf03e884c281167c767454bc3c057abe112dfabda4a58e393e744ee39c71cf5ba744b10c43f"]}}, diff --git a/txscript/data/taproot-ref/a2ad73830bfcdf027adbf16721e9d3b54303b060 b/txscript/data/taproot-ref/a2ad73830bfcdf027adbf16721e9d3b54303b060 new file mode 100644 index 0000000000..b9d1be0ae8 --- /dev/null +++ b/txscript/data/taproot-ref/a2ad73830bfcdf027adbf16721e9d3b54303b060 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c68010000003c978ae7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6e01000000196033aa023d2f98000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac56020000", "prevouts": ["530253000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "25e24700000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00639668", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93601486982337d932f8a5da13542a421b8e8f9ea3c3f47614babafc47e0d3ee68833a51c0dffe7e5434825b6cc7212f0d90dea7a5d3b9982f8882f19203896a3c56fcd0fab6a67c3bf230276b49a6ca24f17dacdd3ceaaa340a5ba0b2ba475b0ee81a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db0a763bf19cfa833013adb8a01fda43f5416b14010ea87884a0fe04caa7ffcc6bbb2d2aacfa419948546f2c8aa96b4ab4a80289c3c8034e795f45f733cf7ae0b35fa22f4b25dbc3a6b67e691e1ba7f45df255baed4abd058cf23fbf36a7f21681a75fe046050f41c6fcdb9e38a8e16ceb2d96bb057130f662fa5c2664fdaf5d"]}}, diff --git a/txscript/data/taproot-ref/a2c43c8aa3d41b7eab2ae20fb1f9e973802d902e b/txscript/data/taproot-ref/a2c43c8aa3d41b7eab2ae20fb1f9e973802d902e new file mode 100644 index 0000000000..8eff24b61c --- /dev/null +++ b/txscript/data/taproot-ref/a2c43c8aa3d41b7eab2ae20fb1f9e973802d902e @@ -0,0 +1 @@ +{"tx": "d181cd7103bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1f02000000538bccd660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704f0100000003fd78e5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf30010000001a08da8c020568e0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ace80c3a31", "prevouts": ["725f600000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "3713110000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "e23c710000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821fd87b85adb72b018dc8118730af51fe2e1fc2345a45c291032ad5ea0f36db09afcaf82673e7b509fa61dcb6f9390da3a7ce1e18401449d1277235bd9d9c04d9a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363801b0fa4cf19ddcf56ab9da9960ae09931238675d987d4e01d2f119420058266b70d0ea7480f8ba050345bd8e4e7681bbd8db77ef27050d0a3831748599db67afcaf82673e7b509fa61dcb6f9390da3a7ce1e18401449d1277235bd9d9c04d9a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}}, diff --git a/txscript/data/taproot-ref/a2c7ad1b00fd60ced001c83967d4fb945e86a28a b/txscript/data/taproot-ref/a2c7ad1b00fd60ced001c83967d4fb945e86a28a new file mode 100644 index 0000000000..5173b5d083 --- /dev/null +++ b/txscript/data/taproot-ref/a2c7ad1b00fd60ced001c83967d4fb945e86a28a @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a1010000009c56d373dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbc00000000662fdb6e03de2e7d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd858f22c", "prevouts": ["c78532000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "4d314c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/minimalif", "final": true, "success": {"scriptSig": "", "witness": ["a6462aa0ea470e7e5c32fa016f17fa7bd944e60fff375b5c3d3a24dfbcae204ad958e244ecea882182ced9c81b658a32811b319012b9e7465b483d1ad799c316", "01", "6320871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac676a68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692f0de23ee769069055d0d6d05652e1367445947e897223d0b74ba21bedb5258c23c60128fd3e7af8adaf4abc6718bf379ce4956c06c6d05419568a3b7fbb4becdfa5022fbf9ae5dfa56f4098acf4285bbe92d9aeb187fa2d4d396f6e0eee31df9d9ff7331949f40b876b1f64f1a10013ac65e222e2c8b225fa80db88dddb53aa6a2d9e7459765b4c09c28753bc2ff55d05ebac69a2359cac2688619c9c27618eeb68ce69b97818447ab7b9a4ba90bb798d21d9027f4de024baf5f3b5f4da875d446577c2ae0ff5873a151ab353523af1af4fb00651b9bde1c1989520e7d338bffb609e59d45c7d1e0be4118ae582299f3fc1b7f496d16d6ab2d0d6e0f7a455128ce34dda559eb1787d0c8deddf8f5f19f9fd4c2ccb2eb142b7063fdfa79ad71051bfd8661ff100df5daaf9353084b6d3751b20c475840529a2a7efac33ff2efdbb6b7c86f986531e7bd2af85df536ab9da539cb9ad98883aa4960532e755ead635b927ce0af32fb24943035d26d0ea88bbdc698d8d4264beb9c7e8103a368881360dc44ae3d69de3386cee559eb49e6c76a737e105f9117431d64c73a13a31f98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["a6462aa0ea470e7e5c32fa016f17fa7bd944e60fff375b5c3d3a24dfbcae204ad958e244ecea882182ced9c81b658a32811b319012b9e7465b483d1ad799c316", "003031", "6320871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac676a68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692f0de23ee769069055d0d6d05652e1367445947e897223d0b74ba21bedb5258c23c60128fd3e7af8adaf4abc6718bf379ce4956c06c6d05419568a3b7fbb4becdfa5022fbf9ae5dfa56f4098acf4285bbe92d9aeb187fa2d4d396f6e0eee31df9d9ff7331949f40b876b1f64f1a10013ac65e222e2c8b225fa80db88dddb53aa6a2d9e7459765b4c09c28753bc2ff55d05ebac69a2359cac2688619c9c27618eeb68ce69b97818447ab7b9a4ba90bb798d21d9027f4de024baf5f3b5f4da875d446577c2ae0ff5873a151ab353523af1af4fb00651b9bde1c1989520e7d338bffb609e59d45c7d1e0be4118ae582299f3fc1b7f496d16d6ab2d0d6e0f7a455128ce34dda559eb1787d0c8deddf8f5f19f9fd4c2ccb2eb142b7063fdfa79ad71051bfd8661ff100df5daaf9353084b6d3751b20c475840529a2a7efac33ff2efdbb6b7c86f986531e7bd2af85df536ab9da539cb9ad98883aa4960532e755ead635b927ce0af32fb24943035d26d0ea88bbdc698d8d4264beb9c7e8103a368881360dc44ae3d69de3386cee559eb49e6c76a737e105f9117431d64c73a13a31f98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/a2ccb0337cf44bc0b3562bbf7dcdd792989d5faa b/txscript/data/taproot-ref/a2ccb0337cf44bc0b3562bbf7dcdd792989d5faa new file mode 100644 index 0000000000..8c13940605 --- /dev/null +++ b/txscript/data/taproot-ref/a2ccb0337cf44bc0b3562bbf7dcdd792989d5faa @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb000000000e4f669ec04ac822300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a666040000", "prevouts": ["be952500000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090294fad9d9bc6351fdc94a7656afba8e89e5b812c6783493607a705880eaff1d63d8cfbb05a417579db75737cd3968abc12f70acec2df8eb9b4c546bf9d65017846ccbf6a2b245ed571bd16fcd5798304b39184a3ae968e101d288fef11a1da81d5b0385df894b44d857ee1973418f340ec899109cc89ff39915142f1b3bd692136dd7b39e6f8399273156172436f8cdaa2acd91c244247e385e7dd7b3ae2f200b578cc6d05f86d3a0804953e7c4e76a080408110420014e78cd2170f59d51abe1cff9a532fa5a8efcad381b6c909fce21fede9c800215eaff842449e8e2bbf98590047babb43b1e452a08ba542e25f1a43b924d7c00c45429949767f9778025b2a671986d23f396a8108581502bf5715a287348b92b53a1695b7206ca70c95fea0745b88d592d6cd8e518f8ac9f5bca3b46572df53f660faef30ac24f45566a2bb301b6dbf5b1659c4a2de17907531ca4d8bd5dff7cd50bc5783034bd546529680fddfda909da11af34fc21bd52ae5386941c0a539a93f9258363d35d5a289ae5fd70f17bb3573bb6ec8b1e20501d90257da1253cde48cd8af24bd29a12181683361a802f0e5ae73d53f9b379aebadfc81181a4ab063779b4dc6f77f1c47b91d9f97c86c194079e479de12e07d39bddbf5198c9373da9a4b27a66c33b6015efdd892d6243237655402791e8a882511f0bc52f3b1ed4c15d21bebc24c052d1fced800fed6ab363bab1bc75d4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362999d4fffedb03f009e32ce21e56d156cd5a3e9aac3f7c46145f08b7b6c81b0f70b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d8657208959ac4fa8a57d164b76708dc6f63c2efb2484bc5a77a391ceb66b2f5ad6b35f745d0948d124101db49c294d83630876065ae400dd84de1c183cd8c786ec24f9"]}, "failure": {"scriptSig": "", "witness": ["4d0902224dbb5cc65ce0dd92bdb20bdc334a3500936782a9cac75aa5987e27a9555ae9b53b8272aba9ae29b1fe58a74e7af7515844dd1c5a6de2eb5da739c71498eeb837e21f5b6fa7bddf9f8c1f96f0fef15baaf56c679fa3bd8c737710ad12d08104c2633ba7bbef4c24856aa9f82ba758e98c5f74e0efc51924ad14da596bdf94793f498eac18f8585edb2a522096534c52a21b63378a3db58f8f281bf7f18ba8fece00df01f12a6766b7f0d7b86e5e23e0c1b8a61445347b9a6fbe2bd4bc7b08c96765c5296dcc83cfd7570f56959e55af1da3e3a62fb82389e972cb37ea002c5e3d8ad64d6f5c95071fe89dcc54cfb979d42a19100092d501b07520c41a6848b3bb25253411938477e2c586703234a413952673d02dba6c0e9f3608aaabefd7c02a8c7b570545c976bb4b81f7ed8d1399e3b427311378269a5d464ebdf85305dd2041fb01c50e125531dca89bab32c4d5e20c7eeb4c75080d980e41d96500b1ab043fbe1a7d2343415ea21c81f26eb77a0a9ecb6f967a082790852813c946c811994adddc14b42304cf79e541652c2a37010c2b490217a86c2689cb48e066f297d403d6e63316cfb9fa2f583bca07dfa3c690fa0c971890e7f73731d89ac19691e4cf947492808656c0eca895845bd825847655573280d39fea3400964205e96b96474a7aedd7317a58da42f3e95be942e01bdd8a49e73666631aa1a4e2bd9a92cae6b54f9f6eb9e2f67561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93698f67b82a647171bd8e62e386c086816d8191afc712ffc3b55ea5f04f05c8f03e05ff666526b724612289f11d9af684c97588c9b58f885be5f0bca0261c5a78c938b5973806e5396d9f6a2ad240022103fc2376d5af9a7129252a47c1a6405aad5a470b8497850c3a230fee464eb343180400453804118582df887251250b2f1"]}}, diff --git a/txscript/data/taproot-ref/a2f70a0c20b111ca1ab34de6f2319109527a564e b/txscript/data/taproot-ref/a2f70a0c20b111ca1ab34de6f2319109527a564e new file mode 100644 index 0000000000..99dda4da16 --- /dev/null +++ b/txscript/data/taproot-ref/a2f70a0c20b111ca1ab34de6f2319109527a564e @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708b000000003bc37beebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8401000000aa486e00015ea55a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1e098721", "prevouts": ["322111000000000017a91448274ba0d73ec00ce63e7922c9d87a48fd0c670f87", "d110710000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2251202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["31d78719058083e83da50049f7f5e9dc1ff4c8049e59853f1a2b5a64a95a7e08a161ddc9bf87f24fe39c335d48f9299fd21e5bc8ab0e5e4948929d043d21b0d5", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/a32041608e8afe0ca18b503f0e9c30cd1480f6e2 b/txscript/data/taproot-ref/a32041608e8afe0ca18b503f0e9c30cd1480f6e2 new file mode 100644 index 0000000000..c9440f130f --- /dev/null +++ b/txscript/data/taproot-ref/a32041608e8afe0ca18b503f0e9c30cd1480f6e2 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a010000006c9b93db8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d601000000fcf1a38ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b33010000009c6a06b504e4ebae00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987182a0b5d", "prevouts": ["29c3530000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "0ffb35000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "bcdb2600000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "6c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa2e65fef4aab856faf00f568df948255673469e3e5fcfbe6f15d7212245640ae7ade389b5221dc8da0332285833f8f90d31bff9f5dd8cabba4bb6916c2c5f203000b960c1063a40dfb5dc510671dff140eefb73aa6757bc42ddda0d13c6b661"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa537e729fcf8585ba70be9503b33ad258cc8c70f658d9ebd11d7348a395e977e6872a8a6de95a80dc4a6e95ba0e12854eab511c8acfff04c6cfab0ff55ad6b178"]}}, diff --git a/txscript/data/taproot-ref/a32cec9ef7fd885815ad4d76f8a45026473405b3 b/txscript/data/taproot-ref/a32cec9ef7fd885815ad4d76f8a45026473405b3 new file mode 100644 index 0000000000..1020bfeb3a --- /dev/null +++ b/txscript/data/taproot-ref/a32cec9ef7fd885815ad4d76f8a45026473405b3 @@ -0,0 +1 @@ +{"tx": "0200000001a86a862f8a1bc1808f7ba2abcc71e2c0ff30c2c698fc832f6545a8dcb978b6cb00000000003bb9f1ec02bd2aa1fc110000001600143f886f8feaf75ad7bedd5713d4d148e7c97c1134580200000000000017a91402e53bc18808b3955166f5113b83b265fa421e998704f78020", "prevouts": ["de2ea3fc1100000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid_opsuccess", "success": {"scriptSig": "", "witness": ["6d02d0213a37fd5a30867aa1387a81339fc2ddd1d3cf93c769e1d1383d69d5bc7e92044187af535f3f12de8952a123bf6cdc45dad9163ba4efd411fea48ca188", "20cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3ac00635068", "c0cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f370d37925ebbaa58968ca2d1c370a50dc7325130308285a7d9868d3ad5a34267b01c94ae67cd857f8f23543b618b38154b6c0432568bb8cf7638fb55d4cc0a24e"]}}, diff --git a/txscript/data/taproot-ref/a34ff67c5e9162f46fa22c082d21a7ac7a23c3a9 b/txscript/data/taproot-ref/a34ff67c5e9162f46fa22c082d21a7ac7a23c3a9 new file mode 100644 index 0000000000..6032d5d5e7 --- /dev/null +++ b/txscript/data/taproot-ref/a34ff67c5e9162f46fa22c082d21a7ac7a23c3a9 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc900000000ad2a3dffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5001000000014b29e90202c4900000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6db010000", "prevouts": ["7b506f00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "9412230000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "473044022040a892018fc73a356b7fe23f749069ec79e165913f21c1a04a63694f7db0fae202205668d51c6fcffa1eeabc76b5de44df2a9dc8238aba9eccc6658c15c1dfd29442832102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "473044022047a161dc84e361ac65e3c873c518fb2c1d1bc3424e76c89ae6d59229bdaa491b0220408620098a8a676cb3cff43f54ed3613e015e32655b7c600fd7a6cc67d64e172832102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/a3770de2569e6bc576e5a3947ac08e8bbe24cb5b b/txscript/data/taproot-ref/a3770de2569e6bc576e5a3947ac08e8bbe24cb5b new file mode 100644 index 0000000000..48f6da9c36 --- /dev/null +++ b/txscript/data/taproot-ref/a3770de2569e6bc576e5a3947ac08e8bbe24cb5b @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cb01000000cd9868e9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2b00000000cd3ed02203b4d76700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc734010000", "prevouts": ["3a08110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ba875900000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368440119a86ba00e0fd0b2929859510ad60f42825154794cb59f75e9814c77960a7d0a3f3648f0d829df7cabdb8f0af96ecc09ebc190c461c6b5fbdc9f87abaf73acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365c6e591f067e3c45f61af74326cd1da3b20a4081ce43e1a5881a0f018aae470fe30d689b41c4cadafebe300f1e3aad2e0751ea174af1d1313cd49baaa526270b3acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}}, diff --git a/txscript/data/taproot-ref/a3823af6285ec27ac5824bddb591a1f209bc4018 b/txscript/data/taproot-ref/a3823af6285ec27ac5824bddb591a1f209bc4018 new file mode 100644 index 0000000000..bf0130e5b1 --- /dev/null +++ b/txscript/data/taproot-ref/a3823af6285ec27ac5824bddb591a1f209bc4018 @@ -0,0 +1 @@ +{"tx": "32e88e8b0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ef000000009ea8758704c0f81000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac55867d32", "prevouts": ["480a130000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "9a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e874224dbe9932044562df2f9dbf2ed3a87afba7bd9cf6855f9f40e4c24add8036ef17902325999cb16876d9e124f321b7a2400c6233e0b61b95917979ea167214"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362dd94ab6ac3ba59fc544244dcd9eb18ac121794a237f6dbebbd82fbb662320abda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e75ccfc706e32ae7f6b2a63f59d728082bfb2443bbee0d6dae87ff94b5ceebef57e56d08eecb8b548a03ce82dd22dc92a64f1be159e88ba8944ed4666490b777c"]}}, diff --git a/txscript/data/taproot-ref/a38819d7d0147d7cfd3e537fe3756def5a12274d b/txscript/data/taproot-ref/a38819d7d0147d7cfd3e537fe3756def5a12274d new file mode 100644 index 0000000000..3372f61946 --- /dev/null +++ b/txscript/data/taproot-ref/a38819d7d0147d7cfd3e537fe3756def5a12274d @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1b0100000056ef84c6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1500000000048e2596dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e000000009ecaa1df0136422d000000000017a914719f78084af863e000acd618ba76df9797223689875e000000", "prevouts": ["f4dc280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee4f4f0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "53ad4d000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/oldpk/checksigverify", "success": {"scriptSig": "", "witness": ["a38abf14611e9ff1d34569f50e5ad70c70c0ad2c047d938ad2b2a0935b80f8cb6900e47ddc95c94d1eb0bbfa9084da5b49420934f189889d03680744d4b7ddc1", "01b82103871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba01b787", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936380fd5bbdbe4794ea806caa5282c1aef1ffe7d45b4d59f1e9bfad28e3ae4fdca981fadee890ab4417c631792739c4ef8fb641e8446934fa0c8e1805c6909f26281276199cbe4e146b3e88d862cccc3aa4bc6307d35ab5018dae88bfea6394e5f459cabb6ab8c3678b74468069be988139c89c57e63462e56e8133cfed14536d81dd4df20fda0be7a55ac17f98a2aef20e321e01e857502a1cfe23cb6a4ad15866ef67e84dd915acb377988412d057835ef837084affa2d0a196ad926b0944a0ca5ee8aeb035ad1d4ef60ba4feb3fceb7383c5600a25eb23627ffada3881a0f6a4d1f74f48d4492f1e0d45f509c9657df63343859227ddf7f2609ac6ace00e705712f857e99c90e704ad61ead5306e2eb41e85853cd64144b1c0edf26fa2e09017c6b0121788120229dd303fb71c48fd037e58f2c5360624d464c160b0d96d9aa9209aee4db1949f5c818182820cafcc77b58f0cee811d9c138e6e925c6ed7b5822c7dab2635ca4d983bce69908efc2d6c8e3a4e02d107fe54b591d6c8cbc0ea2e862ced977f81641729beff04e69bc449bbaee4ae229138f125e8f575c30a32bf5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["3c0b1e0fbd5b5a33aeb59c33de952643664232300e1ed72158ee7c07544b2883f05ff592b537b06d8478520d1140d76bc9b5fd6b6c44d4d5ab286556044ab9dc", "01b820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba01b787", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a4ab26b19b12dd5ed84675a14c998105d6f885db851af25affc21adf58dee419d170c934e59191828af4b443d621af5306292ce84d9ec7d56e4d5e95f4a2b883b6fd696714014486fd7f93eb277485a7e6b2ad9076f6f17fc1c22a649c512cece24022bfb434738800d6aeadbb65c0b5f1c54fd97b098ababd1df24d7362e80f41af64fbf9620aa43b24a95927199d6cd96f713b6c21c4241494f6ef0a4794b137108eeeef0d1cdb0bf8b9c7668f98c08793001c20de814582aa46fe17366f71bdfc32c1e1c145969abcbef65c26a893c9816b7a71a91b71dcfe4a49fffd792905e89fbc0a67267d9092cb76689d3f43e2e6846ec5193713df91969e861cb60c31b4d84c9ed58356d00f548e6c0b7494dab0ae598e30a63a373db1671630b0e008f7f368b69fdb42cf55796ee854208b1524a7b7ad1fac452c6296b4ad4fb087b0a6f9680ce7f5ca5bec9338fe334e6832114c99db2b4b78f7605856e14f0f922c7dab2635ca4d983bce69908efc2d6c8e3a4e02d107fe54b591d6c8cbc0ea2e862ced977f81641729beff04e69bc449bbaee4ae229138f125e8f575c30a32bf5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/a3ad36fa2c2c376afbf409d8fb83e076d6d87bac b/txscript/data/taproot-ref/a3ad36fa2c2c376afbf409d8fb83e076d6d87bac new file mode 100644 index 0000000000..3649311e74 --- /dev/null +++ b/txscript/data/taproot-ref/a3ad36fa2c2c376afbf409d8fb83e076d6d87bac @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9d00000000e8af27168bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41900000000f499c33c02627c86000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac0e38aa56", "prevouts": ["e39f5100000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "229f370000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6aef", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c819f8b552bfb697703837962fb5d6d337df981c1fc75a4b0c4677dcaf4c57d1026557b708b5ff4838890b3ef28f2dfcc17fbcba41194ca68927d7f0eaa3f8db921261d9825d6464319e11fb6c7a9f7c01f613629293fb1fa80574c155a587736c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936850341f24ae52694fce0385034fc0ca207bd809c3dd5acf22e07c8bd464ce0dd70b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720cc28207c7af5a37f80d9c7bda068b6f89abe5b5cf72eaf80ed3e31c2f1c9dfaa6c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}}, diff --git a/txscript/data/taproot-ref/a3af8000afdeacd1c3d6137959029e3b260c72ad b/txscript/data/taproot-ref/a3af8000afdeacd1c3d6137959029e3b260c72ad new file mode 100644 index 0000000000..541e855371 --- /dev/null +++ b/txscript/data/taproot-ref/a3af8000afdeacd1c3d6137959029e3b260c72ad @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1102000000ac4cac65dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b710100000030a16be304f0b149000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374871ce85d41", "prevouts": ["40ac2300000000002251200330f6e5108e4b6ba1453dcbe3913edfcf5a50e8c8a7a117f516f4d28e4936cb", "0f2a280000000000225d202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "737d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e85062220981136031499d54282dd1dc217e6360b68c94112219f47c832c6b09fa8cadcf9bcd23f9249fd09eb8b2b9ca63044a0ccef58f4cae9402f6ead4c2071"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa1755d4e71afcc10f3d2573fa2263bf007b883f1245d387f3f26fe0befbe96d0f3ec5aec6a85c1ca54f3417a27e00c281f3765ee450a46261b59de169989c9a702c501a2f323d94577f3c4b353be8e702d3f9991edd341efb02c3132264010bb33a63f37675deadbbcd666ca6b38ad7090050f3dcc6bba45985e955ec185c53"]}}, diff --git a/txscript/data/taproot-ref/a3b21dcd0e4adb6a0ef920d74555d2f699917d39 b/txscript/data/taproot-ref/a3b21dcd0e4adb6a0ef920d74555d2f699917d39 new file mode 100644 index 0000000000..f9075ec82b --- /dev/null +++ b/txscript/data/taproot-ref/a3b21dcd0e4adb6a0ef920d74555d2f699917d39 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b90000000044735f0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a5000000005a25110d02bd811f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8714020000", "prevouts": ["8cf00e000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "bb0213000000000017a914381003aa1ce42a7df73f2dd1e6e78ae0a36c6b1c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1654142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["a7453dfdeb8869b5bb652ffae48f6657b375ae7df60698807dd8d42c38f5a6eec49f150bcb1ba18149b1b52c375342794f0a329b99cb68eb140cf357ca19e900", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/a3ce74eabac11a8d8a11955afa3ad09d86b22961 b/txscript/data/taproot-ref/a3ce74eabac11a8d8a11955afa3ad09d86b22961 new file mode 100644 index 0000000000..100ad7c91a --- /dev/null +++ b/txscript/data/taproot-ref/a3ce74eabac11a8d8a11955afa3ad09d86b22961 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6c0000000082abd590dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf4000000001ad7dbb460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e60000000013b495130186bf0800000000001600149d38710eb90e420b159c7a9263994c88e6810bc720b41b44", "prevouts": ["0cc849000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "fc1a5d000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "703713000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c34c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667037ae3d106809ce95ad6513527bfd5a0b48627df6eb2b59a2167c6498316646ad1aa2e9998afd312977ef35369de24510af161418b16660639891f4f8529ff8cfae4f24e00136258a4229df9ce1533cc743f70cc4e5c0214ad74c09f63cc0b9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}, "failure": {"scriptSig": "", "witness": ["4c52c3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936325295392cdb69462e5fa0b7e1c132defbdb6aa7844957c05fd0634208e0d9391ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900457cb9328b065f9eb1f6f110e9fe7273590c885552330e2c3269c2432845ee2744cd8777bf679e716871b092f46e3a69645e6fd098b2f58cf3078cdf1926d6f261"]}}, diff --git a/txscript/data/taproot-ref/a3d08eda208b96260cb5b47c1478e155264ff8c1 b/txscript/data/taproot-ref/a3d08eda208b96260cb5b47c1478e155264ff8c1 new file mode 100644 index 0000000000..7d7d029a00 --- /dev/null +++ b/txscript/data/taproot-ref/a3d08eda208b96260cb5b47c1478e155264ff8c1 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a801000000aa951bf3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bac010000001c53bd7ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe9010000001c47564f026e879f0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca040a226", "prevouts": ["0c261000000000002258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "8c5a260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7f456b00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e4", "final": true, "success": {"scriptSig": "", "witness": ["e024351a3b37dcebaa1474684171d9baef2ed8e829e8ac5f9cc2f8603f446a44b6372f13e163438b21ccae47a1c3b71a1aa44fb100a2ba48abca6d92c3eac1d383", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8c14e5c28ba217a2a0b9e5e1144541a12a6b6f168cb4f11927030c4ed7086abedeefb7df8795729eed921e0b3a8ab21eaebe87b9dece8ea74ae0757fd4008b5fe4", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a3e5f143cabf7cdb1f6111fd744b4230796b6064 b/txscript/data/taproot-ref/a3e5f143cabf7cdb1f6111fd744b4230796b6064 new file mode 100644 index 0000000000..fe0575f100 --- /dev/null +++ b/txscript/data/taproot-ref/a3e5f143cabf7cdb1f6111fd744b4230796b6064 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f8000000006d3588dc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709300000000775f78d38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45c01000000bf2c651d0114714500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1f010000", "prevouts": ["14030f00000000002359212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "0f160f0000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "13d73e0000000000225120b5149551dc0241ae0d4420d11e06c98ebd87b9a952c2fc2c5fa7ce9cbc250e4b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "167d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936394c54942360201b0e5a9c52bdb8553d3b85213f639fc7674feca5a4529f4e0b46c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa654bbf7a6388e898988522fa7e5d2ba9e6951646cde29fc617f56e0c3d8e4d50afd13a3b2c4c421c5355668ae9e4eec8bcb7618363c6e35efd204a43726d22d6"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6552d9f0078438d40136d7ff6a38e228e91ae2f5adfdceb2d12241afedfa4e08719dd3b5606bc946287d150a5ecd03b0f8e892d08bbecd28ea2e3769111c28051e3355b9fad1d20bddcd1a8531bcd58c93c4d9ee4159d68db4e08ecdffbe17e"]}}, diff --git a/txscript/data/taproot-ref/a42eb9002c5144273a55bdd736db4fde19aee488 b/txscript/data/taproot-ref/a42eb9002c5144273a55bdd736db4fde19aee488 new file mode 100644 index 0000000000..0499469c89 --- /dev/null +++ b/txscript/data/taproot-ref/a42eb9002c5144273a55bdd736db4fde19aee488 @@ -0,0 +1 @@ +{"tx": "cb12a30301dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b410000000093957aa004ee5723000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c8010000", "prevouts": ["e701260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ec", "final": true, "success": {"scriptSig": "", "witness": ["f671cd90230e59c99f43246d5ef545b039ddb07eee4eafcb7e762383f5f8f05fa12e2fd888ec24463dab47f7eeaae2e3f7465558fe6d42244e1b7076fe27c57903"]}, "failure": {"scriptSig": "", "witness": ["24d7bd17c40082d1ea1c4c34ddcafa36f6f645554947258aae820d3df0d3dd099d1e83a8218def63bf804543e97007f61429814d17974322650350bd51221b20ec"]}}, diff --git a/txscript/data/taproot-ref/a446bc4e40187735edce2ecd8fcd0e7ed43952ee b/txscript/data/taproot-ref/a446bc4e40187735edce2ecd8fcd0e7ed43952ee new file mode 100644 index 0000000000..e3fd863379 --- /dev/null +++ b/txscript/data/taproot-ref/a446bc4e40187735edce2ecd8fcd0e7ed43952ee @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d1000000007867cfcbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf47000000009ee3dbbf01c2b77700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6c0d4c1e", "prevouts": ["55523c00000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "ad3d770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/script", "success": {"scriptSig": "", "witness": ["744950d34e41c67563935eb0feba01124ff2eb3deebbd8f2fb7d01a9a4f422bc5cf2e941a659ec3818e2ff6dba56b48d7e35faa21cbe4d8020952eba9546464e01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "503649286e99ca454968e6a58006ddf2a84da5aa86807e02bf27971d483d0091c1d21244ec4579fb8bf719c18ffc64ed357fecb7793dec9c42889c91b8377e56e0022c2d1e4e6846e4a8c039a076e1d7f02d8a3d13f2d999cdea35eefd86b1faf3c72f68daf650a578a71a5d32f6ad9f9fdb44e38629a942eb13276d4ae8f5ee86c296bceb9a6856cb850f453e31a8c79eb9ba78fd01c24ea30f8b36568b981382fa36c47f186c0b1b758ecfa914c8b08c237c997aff85f83846f613649c4275946e1cc10de782324f6dc6a2c2332a7c9653353f"]}, "failure": {"scriptSig": "", "witness": ["a9a2da3e97bdf73fe0202f6f9491f249110d4337a3de5556b638db26b05d811503395f4efa8f00c9674e51fcbede64058b201f7f0db2b2def94d5204e2f167a002", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "5022c15322a98cca10055037984c8f7c1fc5a8d7e545709fb9da6db45bab7ce1e714435eff81ff68b22c94a7b28b3b8abfebbba8d463e6b3d85b30917d8fb5ef614bbcc9d69779e92ff30685dc4f1d224f49e1c6ffda9d4e944e58c4fe261e17e9bf0f22400ba63d376606f972eac3ddf667a4668a3fcafaadb18b94d599ec8ebe7cf2305ce17330b3a5d041bc7da35168a1b8d4d963dd3a809c54c84738dea1fb24a4ede875a6de5bdaae5bf483e050a3819e2b28ec1cff5125e930165e4487ba9725d0f4c5eb98618b514b61d4722798d85c669757dd5d60b6f48db862084f54ad52182f5ac95ae5aa24b42a38516f"]}}, diff --git a/txscript/data/taproot-ref/a45d7d60a1eef620afd536f4d69cd4196a0fa6e8 b/txscript/data/taproot-ref/a45d7d60a1eef620afd536f4d69cd4196a0fa6e8 new file mode 100644 index 0000000000..22cd5de2d7 --- /dev/null +++ b/txscript/data/taproot-ref/a45d7d60a1eef620afd536f4d69cd4196a0fa6e8 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701b01000000bba7c5fabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6801000000b62f87d103d8d78700000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac0e687c36", "prevouts": ["37c01100000000002251203261e4f5d874791dc168faa2b4a2c68848e71e1814a86d26b34f54a7b16af8d3", "be1f780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_1d", "final": true, "success": {"scriptSig": "", "witness": ["9e5596a7d6e0167f2cdc966eb0027253600ef10c9c2e71bc5f95ea1aa4c272fda7b82ae9bc9762bea5a1fd85c51eb4739b474b0ad266465607524007f81ea4ed81"]}, "failure": {"scriptSig": "", "witness": ["097fd97cde86b0bdbf8cf4e0affa7f9be88e093af052871846d97ec0309089ee6a7a48888d31535d88d7a663abebd77612c0d6e6e50165422f057c7cb36539581d"]}}, diff --git a/txscript/data/taproot-ref/a460475c32082067af4eb3aca7203a69381aec6f b/txscript/data/taproot-ref/a460475c32082067af4eb3aca7203a69381aec6f new file mode 100644 index 0000000000..5a1f8c3596 --- /dev/null +++ b/txscript/data/taproot-ref/a460475c32082067af4eb3aca7203a69381aec6f @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffc00000000cb2d96c4010b104d0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7969a020000", "prevouts": ["adb67f000000000017a914de933560a9a700a6d4f856bfa5cf61713cb34ea687"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "235e212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["9812921cf248a3062afe01f52b057f93bc52be09c8e70356114c3dac90a44a78e9a37585aa57022a1bb560677e47262ea82588fb92ec25026b7373ec8f443817"]}}, diff --git a/txscript/data/taproot-ref/a47eeeeb9c724e0247b882207d4598df2b1f9db0 b/txscript/data/taproot-ref/a47eeeeb9c724e0247b882207d4598df2b1f9db0 new file mode 100644 index 0000000000..09572007ef --- /dev/null +++ b/txscript/data/taproot-ref/a47eeeeb9c724e0247b882207d4598df2b1f9db0 @@ -0,0 +1 @@ +{"tx": "4296b05c0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d701000000192c02da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703800000000b70f74e6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c010200000054072fbe0445ff6e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e4cb024e", "prevouts": ["0526100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "099f120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "39c14e0000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "d47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef9197423ce94fe6d3a105485c3c73b77ffad3b95ed69b8a8a6b271b9e98a9e69ea84370bdaf8fbfa2c728119f306db95ff534e2e627fabf0c000f69380d4e93e"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d3902af40bb61a9efe79ee43d7d4f3634249f4c0f866d22c6fec937b93868b1cc94371513ed03fc9b5b146a2753e7b1ecbc6d9bbcb6df59d8f1ce2dd42b56b227fe8633af3ad90c30a4ff6253cd799a6a417bd03591c5308acef4cef6c60fd438c2fd1368e2cc97a2933efae2d13561032948a77b2cd5d87b5e0b8010cd9f32"]}}, diff --git a/txscript/data/taproot-ref/a4b22b3869f32433a3caeafcc3e2dd92c010757d b/txscript/data/taproot-ref/a4b22b3869f32433a3caeafcc3e2dd92c010757d new file mode 100644 index 0000000000..14994dd4d0 --- /dev/null +++ b/txscript/data/taproot-ref/a4b22b3869f32433a3caeafcc3e2dd92c010757d @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffc010000000732978e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270880000000072fd39a2034e918800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e776a0d52a", "prevouts": ["c1b27a0000000000215e1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "57e90f00000000002254202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["a7b105433b4b1915ec19c609d0b6840b2317365b6a7eb657bbcdd76d3d3912ab855ce3c33a90f875c923d0c169d56c5e39986a1740ce00a05bce538bf8270c29"]}}, diff --git a/txscript/data/taproot-ref/a4b538f21947ef1c76087aab101911f7a2cd4ab0 b/txscript/data/taproot-ref/a4b538f21947ef1c76087aab101911f7a2cd4ab0 new file mode 100644 index 0000000000..9cfce6eeb5 --- /dev/null +++ b/txscript/data/taproot-ref/a4b538f21947ef1c76087aab101911f7a2cd4ab0 @@ -0,0 +1 @@ +{"tx": "48e98f73028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d8000000003dc93bfadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba4000000008f1f5de404739f53000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87e995ba23", "prevouts": ["5d97310000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "9d9e2400000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "0b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362a0eb75e0ec60f99eea3c4e68929a801de09f0e4bcbbd6e06765583d12703af849153cc622aa353482ad0128e41c922a496803621b9ad28f713d97cdce77464b2c78e40500fa05b550b7f6357dbf83024c41a574f6a1706762c104fa8aec3fcb"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360bb3fcad263c09d62d88f37d53a8d6e8b6c0ffad9eb9ba751d541b924f6b0c72784d9e7ee919b8817f3904ff7d27b5c3a4ce3798ed5b994b75288b8e9341d9b42c78e40500fa05b550b7f6357dbf83024c41a574f6a1706762c104fa8aec3fcb"]}}, diff --git a/txscript/data/taproot-ref/a4bb5997e547796263c8fda8ffb4c87967e2ea43 b/txscript/data/taproot-ref/a4bb5997e547796263c8fda8ffb4c87967e2ea43 new file mode 100644 index 0000000000..c244ca9a8e --- /dev/null +++ b/txscript/data/taproot-ref/a4bb5997e547796263c8fda8ffb4c87967e2ea43 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ad01000000ef211fe4028ab70c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787f3f31e41", "prevouts": ["be800f00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "4730440220636fde6853b48edc1b78fbacdf8768615e54e640313826ec042c4aa2f54c013202201612a55ecb781ea6823b82e2ec5800c9dca08e26a0e064599c82f5d7a398ef220200", "witness": []}, "failure": {"scriptSig": "4730440220031fae161179bb8add96b7c89a51e67734bc2d777ac835884d1165ce7e2eae5902206de02e996289ed42308e0fedfcf705b229d90349fcc01d5197a814fee4e6d855020101", "witness": []}}, diff --git a/txscript/data/taproot-ref/a4c0daa47b25c77cdc37c485b2ddaf4db6edaac6 b/txscript/data/taproot-ref/a4c0daa47b25c77cdc37c485b2ddaf4db6edaac6 new file mode 100644 index 0000000000..16bafc6261 --- /dev/null +++ b/txscript/data/taproot-ref/a4c0daa47b25c77cdc37c485b2ddaf4db6edaac6 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f801000000038e6fa4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c00010000005e6f05c7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6c00000000737b03c302ffe3c000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac65fd242d", "prevouts": ["a82c3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d5b75e0000000000225120733adac9df449b2595d1b217303cc00a8e3c5ae4d51e5f74120e9d2d90d81fcc", "1b492600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a4", "final": true, "success": {"scriptSig": "", "witness": ["fbf8792532c477932b747a99f61b557d12cb46507713730600155cdb8f3a776c503ee471a29640697d98e34d9119a061ad3caee33cd9d9bbac787aaf5dcdf4f901"]}, "failure": {"scriptSig": "", "witness": ["7f8c8537664c6f2eeaf91b657ba7cc6895d1aa0fe2c0885f37793add2c395d16089098f6604d651e3475cf543add9736e3f120d2c707dee16aa349af6ad83490a4"]}}, diff --git a/txscript/data/taproot-ref/a4d7bdb95ff0421ff9f027700815f81ebac50d03 b/txscript/data/taproot-ref/a4d7bdb95ff0421ff9f027700815f81ebac50d03 new file mode 100644 index 0000000000..647c65e27e --- /dev/null +++ b/txscript/data/taproot-ref/a4d7bdb95ff0421ff9f027700815f81ebac50d03 @@ -0,0 +1 @@ +{"tx": "bc10ab850360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e20100000056ca8ef0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd500000000f9c6cbc3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfc0000000042284be90453929600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e73aa04c47", "prevouts": ["1d5b110000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "dc1d28000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "74b25e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d2", "final": true, "success": {"scriptSig": "", "witness": ["f2e1c3063dfad656cdd87f5e5a153559fd347131f02e4d0cb00b9816c408f4d9f56702b811d6d890880b926242802e654fa08c69e001e2014c5f725971923baf81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ae543c27c9d7e2b5dacf2092b56cf7326e3f7ef44348332872fcd56cffa4dea037e5bf77c583353c48f518246297e8b5455c1f8cac2f6dc7f8516d0786006f16d2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a4e49ce4052c6a3e72232ff2f764b972159ce65e b/txscript/data/taproot-ref/a4e49ce4052c6a3e72232ff2f764b972159ce65e new file mode 100644 index 0000000000..fcfae4045e --- /dev/null +++ b/txscript/data/taproot-ref/a4e49ce4052c6a3e72232ff2f764b972159ce65e @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b910000000007b8c7cb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d2010000006a6039d303ae933100000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748784110e48", "prevouts": ["759f24000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "1a8a0f000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902618ede92b79a5b81809f6cbb26b0f1acb3409e7eee532034a88be8a398ec0fc9e8bae35b7130da34b76c6912521a66e6d156c4a61b6a4f19c323dbc56647c7c09cc0a995a9624a6108b3adca49d3e5c558bbe4098b4f03aca75acae8806c408593df9b242a22bd3dbcfc450464dc687e8ba3b5ac763210a91aa5588ef48fbe706f33b0a91f8b4057efee182b3d7f8e9d0f6d2d1bf00d3380b2489ac28bb722a2ae386d09a12af0bea36b4609b5e1662abb9688b845a97909a07ea6ed082482cb0f8a18571a19fc332606d53ecac060ab8f585ed152fe4bae3d7addbf5e19266680e723d15620ca051f419f395fd3ffbea6c26439ee3d45b49c3040bea98f21b09311d37d8c076987c6de0751e3c37e1d3e2145e1fcc15bb7571deb64e30470e3d5e2579b9ab2fb01e48ebd18244e466d8aaee7532374064a7915e91207994da877a90a236c05e5874d6a68a05bb549a3e635b20ce0d940a3a92fafdde7b5de323c40c4d66c02788ac7dd75a3244cf2d50d30ced6e9ec73c2e1c813659c64316c1d224160491a95d95580d1bc38262f85a30179ca2209b0e9150865e01025bcea9b2658a567798805f89ddfa0928b28b1b0127a6aad69d598c0c878a5cb05c830f758e09dc456f7e69c8570e1ab65c9dd11630fda7bfbb2ef3cd24ffa4923ad5e4b200b2da300f8cd2d4c288e06175249c71acb366ca55fce5f376df1e3309f9f9e7a3816f667b2c3de75", "5a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa16aecc6ca17fc53cd4672680bbeaf62b9cce164f53144e8804363c70dd634bddc531ca70e78518003474f611c07657b0808402a053b744a80e6cf25146bdf24b"]}, "failure": {"scriptSig": "", "witness": ["4d090262bc2c10a1a04aeb55a82a0122da77b0351c7d4b28d13bee21b1822a66f8067a9eb096f98fed70a9de8e3cbc91cf3e9f0e13cc236280597a9265fc990d257bc8ab3da5717d7b43be30598cdd6f584c5d3e467ad444ba8b3d1160b268d9ddbd9c978e4911bc9e245d3483c9e4a1ff3861ffaccfaddcdd9c6b0146f3427e7157902ce167f7aec7783e48fc11ab3873dc205b462de4211ecf528330b39ca6ed5c288037757fb1d92e09b98fd4e34cb092b7e3a92c1db4821a18f49c423e672b23ab77e00b3d19d542384532ccb7567d295ba784d9fcda882e69953760480a70da3ff80cda93414fac989f2144248bb80e0c3b61eb68d6e0758e15d54d6f5e8db8c142fc7174077e4dcc32e6b10a293a0559cbbc14e96c8b4ad0e2e75ce138d7db55226d499dbd777a3ad7868098f973501c799bad6dab3bec7eb26d178842846ba147c734e1247a38cd869611b312e003c758321273bf4ce164fde63ea1024ec514420a512df157829071ce5cb78f064e870c1b796c7e7d1f94ac816b798de27e0188a8a3b7b563ac0204af27b398fab1c3e04ef5ab6ae9048d5ace29665802543b28237c2ac917173755a65d6354e70f823b9aa88e0f564e55ec4084877d211673c3c76574b6c2be8602bc4478ac8c9821b2928d2f3619b1929bcecc35acca42f3ca385cff254af0519d0c12ab85cc8422f15a6a91d08d249d92633ebcc8f345811268894700d4cb352d75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bb365091e02541d750ef46249caac5d7ae4cd563209d5fc3ab846231dfad5f298b5457f6f65490151d40d3d05d55f9c92d8dec73c7aa55a79aa7c51354918829c531ca70e78518003474f611c07657b0808402a053b744a80e6cf25146bdf24b"]}}, diff --git a/txscript/data/taproot-ref/a4e87c35b253e9246a0bd98cbe936ecccbf2d89a b/txscript/data/taproot-ref/a4e87c35b253e9246a0bd98cbe936ecccbf2d89a new file mode 100644 index 0000000000..20aa5b31d4 --- /dev/null +++ b/txscript/data/taproot-ref/a4e87c35b253e9246a0bd98cbe936ecccbf2d89a @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8900000000e8a3feaa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707c01000000afd25c9604adb63500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc65ed682f", "prevouts": ["d10f290000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "52ec0e0000000000225120a04971ad2b8c16a17e70d417eb355b323e82da2726ed216775e912c08433fa96"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369dcce049c3ca75880493e046b41be90d5f823e94fd712225d408efa6e34d380a"]}, "failure": {"scriptSig": "", "witness": ["6a6d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/a4e89f79f42904ee1b600ddd79f2d3e27c855da0 b/txscript/data/taproot-ref/a4e89f79f42904ee1b600ddd79f2d3e27c855da0 new file mode 100644 index 0000000000..a32bb19e14 --- /dev/null +++ b/txscript/data/taproot-ref/a4e89f79f42904ee1b600ddd79f2d3e27c855da0 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfea01000000f5e5319edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7f01000000447e5a1e03ef0fcc00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874bd55a28", "prevouts": ["f0347a000000000022512017e91ee0326ee2050a26c2cf73ffa8316bb13627b7c7250ab1d4d36a20fb6045", "5da4530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936abb130808be8125d340e7afa0707ecdf35c3f77b9e0336bfcf0ee3f8116d85d2"]}, "failure": {"scriptSig": "", "witness": ["6a4c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/a4f449044130b59be750db18b3dd9cfd3bae5588 b/txscript/data/taproot-ref/a4f449044130b59be750db18b3dd9cfd3bae5588 new file mode 100644 index 0000000000..ca60fa6c78 --- /dev/null +++ b/txscript/data/taproot-ref/a4f449044130b59be750db18b3dd9cfd3bae5588 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4be000000007e34d8a360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704c000000009d55639704a6b64b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6f14dd35d", "prevouts": ["34853e00000000002359212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "86520f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_51", "final": true, "success": {"scriptSig": "", "witness": ["60fad9cb2ef641fd2568fe31d2da694e720492e5632a431391143f9573de0152a805ed2e45e23e1996e1c605e032315b8dfa107c764f26ac133ccfaa4f303abb03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["6a7fa61fa0ad828f8814bb99dd2442f9b7418b22342b44fcdea19b331d8be058602b08b1a3758dc1df186f64b87df2c5d93309c81b098f005ff063600672786b51", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a4f68b87043e04396cfebc9287c9d7280448eacb b/txscript/data/taproot-ref/a4f68b87043e04396cfebc9287c9d7280448eacb new file mode 100644 index 0000000000..fc11a83a58 --- /dev/null +++ b/txscript/data/taproot-ref/a4f68b87043e04396cfebc9287c9d7280448eacb @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd9000000006f1fc6ecbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6e01000000753656c9038b73c300000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388aca1000000", "prevouts": ["eb125600000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "6b7f6f00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "e67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bda127a894a5039ec4946eb5e413110ae843599cc7241c4a3c4a3a9c1b93ad088256d6f90d235a6ba3188b640209fb1b87a6d8106344fff793e748ee999a397d93d03784866e2fdd94d7d1b7c12b1f0da96746c05c19b8696f0ac6a701ba8135"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e92d7728fe824bb86fbd19678fc348031552299afe2faac0cf612835804e2a859ea19512c809756aa5c58e4cd3562935caab0c2ca4eda8db33914ce4decb3cfe9d11a7792f25f0da70e8485da42647201d1062d1bd001b767f1b05dec6877400"]}}, diff --git a/txscript/data/taproot-ref/a4faeb187eb7094b39e0f0699026cacbbb9d2ea7 b/txscript/data/taproot-ref/a4faeb187eb7094b39e0f0699026cacbbb9d2ea7 new file mode 100644 index 0000000000..f3b70b993d --- /dev/null +++ b/txscript/data/taproot-ref/a4faeb187eb7094b39e0f0699026cacbbb9d2ea7 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfab01000000353da8e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa900000000724751d30155c54600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1ed6a542", "prevouts": ["8b607600000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "23c780000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["89", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea0237369b8fe49ed1b05e21155f7ffba4fa029aaf0d531232d0302472e08390b90b3e537e0a498718b42d83f823725a04b39327b9237d74ba7af037a7c89be8bd8f71710e2f4773b226617f0b144a9d046788db13e8347a383f909c13421323cf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e15f4861bfb2a6452ac4a4804b2c6a2c641047e4f139d9501cd1bf471f8e5b3ea6913d98effacbdfffd2adbbf71932929e08e9cbcb7e06a345b8d84d9192524cd99d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}}, diff --git a/txscript/data/taproot-ref/a4fb1b9f52700ffd6bf24f06e73666810b0e3260 b/txscript/data/taproot-ref/a4fb1b9f52700ffd6bf24f06e73666810b0e3260 new file mode 100644 index 0000000000..538c576ba8 --- /dev/null +++ b/txscript/data/taproot-ref/a4fb1b9f52700ffd6bf24f06e73666810b0e3260 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bae00000000e0364cf58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46100000000669af35004b73f53000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca91b3e44", "prevouts": ["43dc21000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "923d34000000000017a91482be44661ef9d172a86ea47619409ff206130f7487"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/emptypk/checksigadd", "success": {"scriptSig": "", "witness": ["66f66dc43d5bab9b14f3c2043e7c9c8f5b48eea7b9a26d1fbb5c2053d5ad26f158ef14efb526af95e741b301b9ddc874aa544674b29eda87ea49e44def600a34", "010420871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab6877fe4b93adbae43ba31547b2a28b8426e0e264fdaed20741da068e2fde6e79c828b389cc6fa067cc52fe12ccd40f3ff3a983633ea848ec15a2b4831982f7737d8b833e0825ba099c8467f76b1421be2b77993c7e62810ff98ea5481a16a5d99cf36381d9d9a20d2ce9dedaf9116dfe3a9922c76fb47afa7d001862ca7c11a241ff59189a6703879e4c72ba11924ce43c0100733bc95eae687ee9079c18adbe9f9dcc9df76457daf667e614b0a2c9769f05bf9e4612cf41468a5c2edec8b27561be12136e03a34f8e495e73b5ead1813b7376b7b4741440bb77381e68f2c66a36d3584cf1098f42b1db0e5adb952c76295af580ac8e57b6e152c1a3838880c25423e484f9a894f0cd7a4f7a55204cb9503269f7db7c978ae9e1aae745e8cba1e95faa8cd3a458c6fcfad037bb3042008f870bffa75e1adfa3bc03f6ed1f3bf446321ead565d6569148652da647f2ba80fca39d16e6d7a41565c11b66fda799209aee4db1949f5c818182820cafcc77b58f0cee811d9c138e6e925c6ed7b5822c7dab2635ca4d983bce69908efc2d6c8e3a4e02d107fe54b591d6c8cbc0ea2e862ced977f81641729beff04e69bc449bbaee4ae229138f125e8f575c30a32bf5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["67ccc0728bf9fad1ff3f340d11258558170c1ed2901962d8a5b0cdd03b69e39bca660bd274c98fe768d09184690e7edc805f72c0f2c0844782e11374bc30f338", "5400ba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368cc4d632c25fb1473ebc2c4691dff712f1529879b16cf6e01c3498b371ad5643f043ba3d030a3b9cb1de0a60e5c22d352c9a6b0167bb0429c65653ad93c6b5ad75df7d692cfa002fbaff39a633e2a3d0c51d8dadcd4fcf0c857fbd83ad169fef2faba22bfc7a47f9e635144f510dd0bf27279d7f381c4c7abb10bfa7caa6f45212b1384dfb83dad558f50952f8dc7a4c93fc05bc0bf8f252596f3f99dcc4aa25ab6fe4c1776346de255528baa11f4624c0da11cd67d3944bc9e3c23527f253a174940966dd57e339c9cd051354c05cad3fffcfa87d89865f388df6a9793fb850795b387e411ef7ecd738a90c270a9e8b41d104f0901d65be980e017742035d2ed5a15550423aeac2e288a32ca51234efdd8592bd1b66a7f846be8561b7af73c90baa320cf1711a17ed2a311e1783897c17c40a4468373563049ba8a82c1cbe704bb8d89f21761581480cc9fb789613a87d31235185f9da4b4384725e898ebf0d2c5eddaeb8557ce0f7cc7880e698091ab104cabb34aeeeb5d0f57ea86d1ebc555dfde575d48d1eaafa8343c63d6f5425984d2425aca274be02e47a5142e089ba2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/a506dd32985fc68730bdda9ec17bd68456455ba2 b/txscript/data/taproot-ref/a506dd32985fc68730bdda9ec17bd68456455ba2 new file mode 100644 index 0000000000..268352458e --- /dev/null +++ b/txscript/data/taproot-ref/a506dd32985fc68730bdda9ec17bd68456455ba2 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfa0000000056f07197bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2e00000000e97e04addceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2e010000004e146fe30155a353000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6ed721a49", "prevouts": ["41e1250000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "b7c76800000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "603822000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_1", "success": {"scriptSig": "", "witness": ["fc48c577f7b5f3a703a5457be6f551460eeec93367865b5e2166424adbd1ac3f295acb1edf1714f4860d94394f74ea0548e4029291eaacbf244d914336ab151701", "503968e07b294f35feb7b41d27b4819473f873691d15ff549a9c12cc197e081edc87f8aaabd5ebeafa67615807d69a5b8c59ab0fc24eff57f7038dd2a483827b9df9939d6c556bc4f61675143f9caaa0ee0eb629928a741ee0c0249ac16173d1cfc9234322a1176ae0448323160a0563b03c500ff64963073b7d70cc0f6f06b5590fbed5bbaf8ac6"]}, "failure": {"scriptSig": "", "witness": ["74b5530153f0d51da985b311d560f666dfbb61e8b9bdfca17b755d9895fd49777944913f55fb6a495648a81575841648e376dfb3e9221ff8b5355d0abb1c093201", "50ab65cd189b8d11a3d39f9aa1c4e4348f27eb114f13c04376a07b961672d9f88eb38e1cc0356851fc987efe8dc2b46d4fc293720acaa06889605c608a90cc198133cfe14ffbb4468fc36bd8f61935282308cd22b7210c1b193d6d10ff0c7865c5bc41e2f93eab4be9657499c5a2e6ba1bd68d979dbf272743232180969389e056d43b368c"]}}, diff --git a/txscript/data/taproot-ref/a51dfad994645830ec06457aa99a3680c881234f b/txscript/data/taproot-ref/a51dfad994645830ec06457aa99a3680c881234f new file mode 100644 index 0000000000..f828e020bc --- /dev/null +++ b/txscript/data/taproot-ref/a51dfad994645830ec06457aa99a3680c881234f @@ -0,0 +1 @@ +{"tx": "19d3c01403bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb400000000d4d080ff60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700b01000000657831fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49400000000aa2e2a9604f321bf00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f871a000000", "prevouts": ["0c0877000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "894f0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "be6b3c0000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "4830450221008f55521fb6f7b72388272102c08b0552b3196cad4de688785c363ddf2dc08a1a022069babc1ba2081a37ce9b4b4266842ea5da2a13d9d0bfa2ddafd691d1381442f4022102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "4830450221008b70ded494a4076203863d4eb5d8e5c5ab630ac1dae865777894a00fe390e37a0220372fe37418928a39b8867f2e57e66abdc633a07b5a652f199845798216aeb573022102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/a52cb7e463be1bd639929b2d3988c313fb4189b5 b/txscript/data/taproot-ref/a52cb7e463be1bd639929b2d3988c313fb4189b5 new file mode 100644 index 0000000000..ee8d416238 --- /dev/null +++ b/txscript/data/taproot-ref/a52cb7e463be1bd639929b2d3988c313fb4189b5 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c720100000018c71abf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b800000000898d559f03957a56000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48759030000", "prevouts": ["83a74800000000002355212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "20d90f0000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "d67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e81925aeb587789c20eb4609a9df455cd23a7da5ff4c702feb6a2f003989c380a08a47f828b5683f18d8d2a0301cf32ab60b8042f73dfba3f43f347d91ef120fb4bd0211bc754da142cb3564162304068e34e33074851a6380a45a2a3191e3f102"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362b0e17b8bf42b7e584614961f092aed83eff492a60c922e0543c90531401fe8f1925aeb587789c20eb4609a9df455cd23a7da5ff4c702feb6a2f003989c380a08a47f828b5683f18d8d2a0301cf32ab60b8042f73dfba3f43f347d91ef120fb4bd0211bc754da142cb3564162304068e34e33074851a6380a45a2a3191e3f102"]}}, diff --git a/txscript/data/taproot-ref/a545cc27e2d474a7a7b7ae974d6c61935d3bdfb6 b/txscript/data/taproot-ref/a545cc27e2d474a7a7b7ae974d6c61935d3bdfb6 new file mode 100644 index 0000000000..b8f0d327ec --- /dev/null +++ b/txscript/data/taproot-ref/a545cc27e2d474a7a7b7ae974d6c61935d3bdfb6 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cde000000009f5d27808bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d201000000283e3bd98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42700000000da52b0940417c3c800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e52a3644", "prevouts": ["6fb15200000000001653142540f27e90740933c99d4f17ab2dfc6c82951cfb", "55f23f000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87", "a8d8370000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["30440220598cfe5677068ee7d3f8d23516d7f12f26863c7ce363ba0ae679b3d9ab8f00c8022033f63fb7accd3895abd01f7c381f4166f0fcd309d239da4d2f34e5a783675c2703", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402201962a3ec2d64685ae979b254f13dd532803ce2c9cded4f32114bb36ac1c081f002206cea3880395cdf053a9941d48b417ab90bc1a6604b09b5bb82387986ad539b0303", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/a547e004e80194fef36be8b3932bb2a42502c7b9 b/txscript/data/taproot-ref/a547e004e80194fef36be8b3932bb2a42502c7b9 new file mode 100644 index 0000000000..0b021374a3 --- /dev/null +++ b/txscript/data/taproot-ref/a547e004e80194fef36be8b3932bb2a42502c7b9 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45c000000001eec319bdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc6010000002d1bd40e03dd94810000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79633219028", "prevouts": ["7cdf33000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "d3f44f0000000000225120d1b91456e68c356a2c859a7d0862df581c6fe76c88121c19c4713ce29cfc8e45"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "797d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368e9ed2886e7908e27181476c22eef50b42616dd4d44ef70273b9f072453f43980793fbcba16d5416bd6f0933503ffe6704f239223875a49be11ed5869ee331b55be39dc57762be2d9b1a04aa5b570805d23104bfe4fa54c392bda5d51f7f4540"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa0b1051acd7c1b2d32995b3df0c6921af5f8ed3327e7e16cb8a5e0bd007230af127aec9530f4cf05d3554e63105b96634da39f3c52c35c251ce860693e97320b3"]}}, diff --git a/txscript/data/taproot-ref/a54e57e8c7e474bf56e54f46813916ef373a9d88 b/txscript/data/taproot-ref/a54e57e8c7e474bf56e54f46813916ef373a9d88 new file mode 100644 index 0000000000..61746c5815 --- /dev/null +++ b/txscript/data/taproot-ref/a54e57e8c7e474bf56e54f46813916ef373a9d88 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704001000000baee91adbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4c0100000055b2f3940307357600000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6a048da2e", "prevouts": ["6aed0e00000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "77d6680000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["b155cac647d3a0fb0ea2fbbc1aee38b1e76a67093bffc5c29647aa83bc0ce13318ed70863611ab4ec13fa0038580dff9c3e61bfb5cba4794f036a1575c23cf130ea96bb076942e2677916402cc07120d25739fc5", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/a56763f3af3e1d367ff0097d69c129ed4bae7f00 b/txscript/data/taproot-ref/a56763f3af3e1d367ff0097d69c129ed4bae7f00 new file mode 100644 index 0000000000..03efe1c334 --- /dev/null +++ b/txscript/data/taproot-ref/a56763f3af3e1d367ff0097d69c129ed4bae7f00 @@ -0,0 +1 @@ +{"tx": "4c61934d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b570000000092d58fcd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45100000000baffc09e01cd1c3700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acfc59935d", "prevouts": ["cfa9260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1b133900000000002251200120da136b46f6e1c164adef9ba0d2bbe634d7767c7946122aa4909c89df2221"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_aa", "final": true, "success": {"scriptSig": "", "witness": ["8cf068babb2c0c13e3db94dcb2c9f69b5f104764182a1e578613869dd03d4ff64f8745de6175c713d73a2491a62bb989fb3cdbfee11d9ef353af36547802a04a01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["22e0f9b2e60b85843675de81ec6f465296914fcd0f19bb529e24d0df00da2213ac8f298f41d449c0e04ae5d34671df4d7fc031ecc159eb322f8b5bc05e93bf22aa", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a5706ef86f9f5e79c7eb3a0ed8168f28bdc25f87 b/txscript/data/taproot-ref/a5706ef86f9f5e79c7eb3a0ed8168f28bdc25f87 new file mode 100644 index 0000000000..1ed99fd466 --- /dev/null +++ b/txscript/data/taproot-ref/a5706ef86f9f5e79c7eb3a0ed8168f28bdc25f87 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c850000000050957517dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce601000000ac49e6a1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5101000000703ea34b033cef1101000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a641020000", "prevouts": ["59c348000000000017a914ff6a0b1cf86e786bc6de2387f1927f71fd08cd0c87", "fabd5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a3736d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_93", "final": true, "success": {"scriptSig": "", "witness": ["df4c70f13b8f5d4c14b7b2cb79dca889bd2eb1478bc03a936b124688c978c5963643c698aab7d14e9f681bdd30bc79a7cd0042f493fa54399a617035fe11de3b82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["26162aa5f56f85577691407bb0e37d318c7f92c3b0e17eec3376255a970b709601cb3aceb03a3407a1cffcdf90a24e8bfc9b586be9cff7b5db48d43a2dadf62d93", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a574eeebf64538810c2a45c5864f3209361e1c96 b/txscript/data/taproot-ref/a574eeebf64538810c2a45c5864f3209361e1c96 new file mode 100644 index 0000000000..f560d1b21d --- /dev/null +++ b/txscript/data/taproot-ref/a574eeebf64538810c2a45c5864f3209361e1c96 @@ -0,0 +1 @@ +{"tx": "d336dfaf02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ccf00000000eb3e058b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d701000000e10936e7046a80940000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48745010000", "prevouts": ["c49657000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d", "db093f0000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ef7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e87a25236fb2b0caf4a960afecbd8538cf949b3ef5b854c8fdc156128073078e11b030008666d4260a12bee868d13ea953ce9c9319f2222d8e8469ea0b912b8ceb"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b1d33bd2ec2ef2b80e561b3c30cfb99b356a60261a599d7e1f2ff199de481a6e8ef60344f111a9c34d055af59cfd42b130acbf4987ee3354719b7c9974e4d449"]}}, diff --git a/txscript/data/taproot-ref/a59cd78a997d502a498c2b597cda9c8cb9b435e4 b/txscript/data/taproot-ref/a59cd78a997d502a498c2b597cda9c8cb9b435e4 new file mode 100644 index 0000000000..6e4e2237f8 --- /dev/null +++ b/txscript/data/taproot-ref/a59cd78a997d502a498c2b597cda9c8cb9b435e4 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbf00000000a56b6a2060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f400000000b6cc542e020ae337000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acd5656735", "prevouts": ["148b28000000000021561f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "a4aa11000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["76f3c1c5360f37e418543fc90fdf11d4bc49ee0f5761f9397c721536f011ef6bee48fa7085ddb2789aaa88835f495523673adc441d8fbc12423c05431834c02b", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/a5aaae5e5cc3955871ba97a7c41d307fef2b72eb b/txscript/data/taproot-ref/a5aaae5e5cc3955871ba97a7c41d307fef2b72eb new file mode 100644 index 0000000000..a8aa7d3de6 --- /dev/null +++ b/txscript/data/taproot-ref/a5aaae5e5cc3955871ba97a7c41d307fef2b72eb @@ -0,0 +1 @@ +{"tx": "6ebe113f03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c480000000082f72a8cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba501000000f5b89fa8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcd00000000c556cf97037ed2db0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acbb000000", "prevouts": ["98a94b0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "d2402700000000002251208f7166d23fc1e45fbcf26b51bd386ab915626b0708475a8743064036728c78ed", "8f956b0000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "e97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e88b8d8a8d8c003fabb93595bfceed403f9a1266ee95e7fa8447cccdf398ce498db8321554bafe286e6661652cf416d3db0b455024b23404eea069d656c79e4f25"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e84a72ef51eb7f1fd93b7716e160b4419190ea5192ffe31c8263ef308a11abcda602e473c0179dfd44294f4ddb50d827cec9d4b4e0c6eae7f68c0301f0fdfe7e6b9e5e4bd2cefcda110a5bf613694738c198174b403d264db4691720c8f18fc7b8321554bafe286e6661652cf416d3db0b455024b23404eea069d656c79e4f25"]}}, diff --git a/txscript/data/taproot-ref/a5ace5adf4a44f04399e15b18f44e6a83e13b549 b/txscript/data/taproot-ref/a5ace5adf4a44f04399e15b18f44e6a83e13b549 new file mode 100644 index 0000000000..4f5af7d060 --- /dev/null +++ b/txscript/data/taproot-ref/a5ace5adf4a44f04399e15b18f44e6a83e13b549 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9a01000000b5f930dadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8d000000005ea06fac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127044000000007a558cdd0125890e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b1000000", "prevouts": ["5c0c570000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "7bdd4c0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "fc3d0e0000000000225a202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720f48725aff660a72fd31f8e9799fbe605d57d774c031cecd8b6989780acb581b6b24737b64a51a2c518aa096a7a1ea5ca18eed83cdd20aa73c19d83535c466892"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d510b2b16248e513241b83875342c0ccd59e2b6d40dffb5019b56610da5b5de422d74e6cd8e612cb42cda5f7f42dc10fbfe42e4e0a9faed92158fa7e41e5f92051e17d2416a1ef9313076e185902c26d9ae3ba1c967c4fe3d78707cdcee712bc7b1"]}}, diff --git a/txscript/data/taproot-ref/a5b907c867904b2e2631128c5f637988bef1282b b/txscript/data/taproot-ref/a5b907c867904b2e2631128c5f637988bef1282b new file mode 100644 index 0000000000..26cabc7b8b --- /dev/null +++ b/txscript/data/taproot-ref/a5b907c867904b2e2631128c5f637988bef1282b @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40300000000adc681c160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b301000000dee1962b01d87c34000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478764020000", "prevouts": ["f8753600000000001656142540f27e90740933c99d4f17ab2dfc6c82951cfb", "65390f00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_csa", "final": true, "success": {"scriptSig": "", "witness": ["221e1e1f3eececc228910338448dee6024c7288f8c252bfec6a82722f916b512993669a6e26724735390f42f619be92a22f916665ce809bdefc3eb63c759b5cf", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef32555276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}, "failure": {"scriptSig": "", "witness": ["221e1e1f3eececc228910338448dee6024c7288f8c252bfec6a82722f916b512993669a6e26724735390f42f619be92a22f916665ce809bdefc3eb63c759b5cf00", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef32555276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}}, diff --git a/txscript/data/taproot-ref/a5c7d3a86b0f7fd48476aea167e188ad2e930dac b/txscript/data/taproot-ref/a5c7d3a86b0f7fd48476aea167e188ad2e930dac new file mode 100644 index 0000000000..5c2d8b7560 --- /dev/null +++ b/txscript/data/taproot-ref/a5c7d3a86b0f7fd48476aea167e188ad2e930dac @@ -0,0 +1 @@ +{"tx": "232bcb1b0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a201000000a1df09d060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f201000000b8a452ae04e91d1e0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87b413c54d", "prevouts": ["175e0f00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "f6db100000000000225120c230ba0a2d20add5df8769fc65d7fc3a12d7cd95ad679e3207a6c75325eb884e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_keypath", "final": true, "success": {"scriptSig": "", "witness": ["5b901a4110669a243d2b1eeb05469658a3dc98adb1d7bd56c7c637fe495d38af3aad12243a99cd5b81af57cd02fefff61656d4e179954f3a1f6ba88b6115ea9e"]}, "failure": {"scriptSig": "", "witness": ["5b901a4110669a243d2b1eeb05469658a3dc98adb1d7bd56c7c637fe495d38af3aad12243a99cd5b81af57cd02fefff61656d4e179954f3a1f6ba88b6115ea"]}}, diff --git a/txscript/data/taproot-ref/a5ccdd516198da910321185e29de6f20d9be2985 b/txscript/data/taproot-ref/a5ccdd516198da910321185e29de6f20d9be2985 new file mode 100644 index 0000000000..78b832e6d9 --- /dev/null +++ b/txscript/data/taproot-ref/a5ccdd516198da910321185e29de6f20d9be2985 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d02000000a05c23cf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e70000000024c7cacb02189b38000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987a8344a32", "prevouts": ["0e0e270000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "ae3f1300000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "9f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e93df6a2e62376e6a3587300ef2d1a395dd90428413a52508272625b5a1a189adb591a16be56540de55d9fbfa115de937b3aca1e4dd0f5a93f17ebd2ebda95183"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936327099b01b253298afa4f7cd9d288beb4aefe51868cce630b6f9dfce458fab5ee7391eb2542a03443f1c351bcd0fdf78b6f5cd40e118bcfcda3d325918034371ee453f7f7ccbda5a0ba96115b963083e4b2e9e93a3abf82e4dae88dd7e6a6b566f3617d560800e971f99646d89bd2028caf0c6d02b6f505a11fcad3ec349c801"]}}, diff --git a/txscript/data/taproot-ref/a5d4903bde9105b510f48ef3783702f402c38289 b/txscript/data/taproot-ref/a5d4903bde9105b510f48ef3783702f402c38289 new file mode 100644 index 0000000000..0b6df5b1c1 --- /dev/null +++ b/txscript/data/taproot-ref/a5d4903bde9105b510f48ef3783702f402c38289 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3c00000000038eca4160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270650000000086bf9efc01da691800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac09bb0336", "prevouts": ["9b0e76000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "3acd12000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902eec2e5a57d677921aa4096b27e673aab99e6095c2094b15af3537f8be01164cdd3ea6510c2c74c68cd36b1cf0be60c3824f19bd36a3462cb5ac7e08db9df41d96c4f7ab6fd8f106635912e51b082a2848c5bfb02ec6000d7efe4f6694170a3a2093f1029782f675b2667204b8638dc957e76d3f5a894c2cfd3581361c2f06a35ef6fe913fe7f0ab9112b1ef2c4a2c5fd84fa449f4795765b025f3f8da609f4a80fccbff16d30aac4246f49f2cd18ab97355156dddc16af612a05b65f56bc170ddb0b8163a0dd5677bcb6718ed4ec9bdce3f614bd322f7eba943e26cca0f3fe141f02c2fd0f728970035effe127950da0258fbea1780a2d956085748424d3d41a16148da948e7d6e115d355436ed2d385e7542d4b75fbd95633b43947c2049445a6136a82780b035e8941b4d5aee7b0fb9a0887d44fd67b4ee47f923c7f1714673ab8c2b2ddd3fdc975ddaec7a3ac9ddb8d9bb74bcc86595f27668d49beeea4ef7053a84af86c9434571da729603d8647b39fe6d173d70fc8c7ae6ca7f40c5a3cd6d924ea8ef86e621e44696d8d5c99bd283d7c4f7e533f8ed07dccdf5ce13e3970c9534fd32e9601ac4b4bcffecc6b385ef1672b67c941c2e1b91332a12b8dc3a28900dd5546dc7fae081100c70851f052e0c668a7fffb79667009f7e6af9544135ceaae30b3efc6647c9865a71cd01cbfde034eee5724ae7a826a6552690c93308bca3be2ae16604875", "cc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac391effb841e4c3f4ca92b599bc572f2bc6440711e20bdc5ba4fc353379105b198f95dbc4edc81931664a748b39a9978dd32dedaf5c850114f6bd2f5098c050fb"]}, "failure": {"scriptSig": "", "witness": ["4d09028695c928210b8a04282fbfe862a176d53daedc4f373270b87a731c794df8a5ba9babfc041a3d2559894981d2033f68b9e65fcc30886452be0a17f7913f06e13cf00f61424f331dc32df986fe3e817cd25153eee79f062c58bb21516c9f4bfd2bd57e63190004d0c8de74d9a858f80453c92a26168df1ee86a6570628810c311da96ea1552827306efc86de691c94843a887e6d82ce1b0e454de12fcb294e41d81936a9c26ff62b7c289b6e17d649f3901d5214c915cea5b5b2b8f5b4cc7c8f23b6336948429946d6925baaffdcd30908657f7e3b4b0927d499d93ad2f1c0af5654e96c001b55122ad9a07a4d7e55da201776171c08179b53e3603375660d28a92752fa35d72630f777617cde4738fe39e9bbb5fac7e6fb9aa0a512aa9151e83a410cead4e136dac1d042be70176ad9893d0151f2c83e4e607c8f4b2e441c4a742f01f146998cce2c5108b2066e200ea5af86f0f1736294873424a4712700743e461d49a31cef41c0d11da73549e1f2aea5a1f073b93ea6af5cb02c8fd6cf4983dfc86fdf1d1a3437aea4807b4fe3e3ccd1b9669f840e7fb442cc2c7abba36fecea288756f1aa31464d06de6c313b90fcb003653339ce222ba0fc7e9561dda2cc6bf148aefcd8cae1dcb1a5d62a048cefd0b5e18fea383069ee4261c479fe60a98c9fda82c4bdaa6a388f52cf4c848943df42a37cdbee53e5d5c60455a6bd9b739b9adf55c5883e136075", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8f31245d0339f22fddf0c8a157372cfa350cb7b4c29fad108e38a2a212532063d8f95dbc4edc81931664a748b39a9978dd32dedaf5c850114f6bd2f5098c050fb"]}}, diff --git a/txscript/data/taproot-ref/a5f0f80d6202449807c3c23b59496812943f4d12 b/txscript/data/taproot-ref/a5f0f80d6202449807c3c23b59496812943f4d12 new file mode 100644 index 0000000000..6e97bfa79e --- /dev/null +++ b/txscript/data/taproot-ref/a5f0f80d6202449807c3c23b59496812943f4d12 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c33000000003fb3db2960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708000000000f56cb0cedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5600000000b56ec84c033b18af0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac87d19161", "prevouts": ["5469470000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "ad4f1100000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "392e580000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "747d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9d51b7afe827d3ebe2ba9d78269a9de5b698f1c4b4dd21f6a9ac5eedea4c46567ed562df09fa99b9816795ca593030d6e2a26df3d36427b327259a2f453cdc8077aea6ccf316b47e40a0e3636c5ad4f7738b9bfce630d4a478a0dbfcb51ed93"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826e257627f53ae21a01782ee3e7d4da03b01bc19a25fdaba4c8a32b8ecf0a2d91bf4492fa00dc56072e72009d776219274bea6eb51adb458249eab71940c27cb4bfbb1ef2412aee06f4b75b9e20a72d4d9707545a4ae77abc538f76b00105406a"]}}, diff --git a/txscript/data/taproot-ref/a610da0c9997c31b63719e6fe71e9b82d48595ec b/txscript/data/taproot-ref/a610da0c9997c31b63719e6fe71e9b82d48595ec new file mode 100644 index 0000000000..7c9845970f --- /dev/null +++ b/txscript/data/taproot-ref/a610da0c9997c31b63719e6fe71e9b82d48595ec @@ -0,0 +1 @@ +{"tx": "0affb4e102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb601000000148475f38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42101000000c9d6518c023f499c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf4e9e538", "prevouts": ["110a680000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5f3e3700000000002358212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_9e", "final": true, "success": {"scriptSig": "", "witness": ["ed0921a70f405b28f146ee780fe72d7aa100ee6487cd304e5ef0c1ad64e2786e7801ec6e9e89efca57dcd7ba92347680ec58009f8cdeca548938e006adea4d1283"]}, "failure": {"scriptSig": "", "witness": ["707f61a7b7877effdb59b96e8a661221cef02288cb18fb588cde977d58bc77b2703acadfa8d5e49065795b658a98406355c10a2500a1e0e9e42ce7dd40f12cd59e"]}}, diff --git a/txscript/data/taproot-ref/a63c8dad9a5b7049824ad507266f11ef32fef7c3 b/txscript/data/taproot-ref/a63c8dad9a5b7049824ad507266f11ef32fef7c3 new file mode 100644 index 0000000000..d648eaeebf --- /dev/null +++ b/txscript/data/taproot-ref/a63c8dad9a5b7049824ad507266f11ef32fef7c3 @@ -0,0 +1 @@ +{"tx": "7a4c3a2f028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43e00000000402394cabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf43000000006307458b036973a8000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374874c040000", "prevouts": ["887434000000000022512003ab4180fdf64546247c5e9f6e4b9eec37b1d29fb6f370a343f066de5418d90b", "20ad75000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "final": true, "success": {"scriptSig": "", "witness": ["ef4e3ecce5d603e2d157e805fa5065208266e33fd73623d634c8de72e786f0311af4cb7678bbf2159735c79f83fe03a1a89cc7191d09be3128e2430e2b7f37b8", "40aa3b83941ca7138c8b99c297ecaf38b30f45cee32bd171fa246b253f034d39a77078b2c441861fe83c78db80d7a38b3f7bacf4b698898ba38e4e79f1856dc4ad6a16affed09ec4d6c9a2", "4cdc9925d14c6a90de73495e12e353b24d1bab3e395e525bfa7801b627f0b4e87848425136ebcb9db95449f5953ba463a95ef31b42a3cf0b40e2a4cc2e38ea793ee9b93f98bf3526908a43602118c4837ddd5b66d5dd1d72e356161d3d3ec27bd92143416829ede2a102bee99dcb87bf3469cb550b0adb0a469b36d8d6de17dfdf028e23163063fd42bb48833c5f567f083650fdaf927174fdfb6586dbb757513f9d72de77e5dd84d1d9b751c146a59275e1951767ce3cc2e53d3a813252d4c47b30da077dc3e6574aabfc5a5c823286ba68da388751732556e70a7c2b4c6d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641efbbae90d977c0a77f4a6d00a1fdc193ecaca05aee87ad86fd7458efc1bf9850616ba036f0261d3fbb05bc424770fad9d81a2fab9eae73d3c6a84d24acde4cf7d259f27303adeefe063910662639cd9206b8eed45d51f9a3ddc7becb8e1d697b81bbe024263f56fc7a5f55cd5c1f3dce1d35803fca6550652a1481f3d5d41582d86073393cae44f941e67fb2d850fa0d7a841f3f7007760f5a04dab5a6c76bf8e13d57cbeea15c73e171cc780d6a9ed9745a67e290449b49e5bc260f913c109b2712604811149f7e1fe8660b15f3e9c7c27b36e0865176f061702b8197645464b90c25eadf8e3e7dfb1e0fec34e85834a1a5dd46e16fe1d533563469e8c1b505fa9a39ef433ee7b7ce87bd7d2ac142a5c16fd03db838e94b94ded093b75bdf93a2a91e66878d1a6a955a8d70f562f6276e393d3ac94b5eeab37bddf8de0f74f7f54bd02628b355177f1dd586f09e37f1b80ec17858d180db76c7ee658d4c390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058daf0b4fadf03c4de067af76b756c06c36d23c217cef183c97956a3fb3177f7ae9b9f79d9ac6ec5c9f3f07e75b6b2eb78d303c91d98a4f03fb478fa73d35778ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000dce634dd5f9bc5e08acfd55a920a255912d7ebfb63916c4272554460fd5ae1f40000000000000000000000000000000000000000000000000000000000000000"]}, "failure": {"scriptSig": "", "witness": ["ef4e3ecce5d603e2d157e805fa5065208266e33fd73623d634c8de72e786f0311af4cb7678bbf2159735c79f83fe03a1a89cc7191d09be3128e2430e2b7f37b8", "a725c68ec8f406dfd7dbf5a273f87645e55f6f5239a31ca00c76a2c7c65d37942611ca42e24d2db79d1f7f6e5466e7bdc2da45f856237221c84dcf3043d3d61b251cb4c9f1b338946c17", "4cdc9925d14c6a90de73495e12e353b24d1bab3e395e525bfa7801b627f0b4e87848425136ebcb9db95449f5953ba463a95ef31b42a3cf0b40e2a4cc2e38ea793ee9b93f98bf3526908a43602118c4837ddd5b66d5dd1d72e356161d3d3ec27bd92143416829ede2a102bee99dcb87bf3469cb550b0adb0a469b36d8d6de17dfdf028e23163063fd42bb48833c5f567f083650fdaf927174fdfb6586dbb757513f9d72de77e5dd84d1d9b751c146a59275e1951767ce3cc2e53d3a813252d4c47b30da077dc3e6574aabfc5a5c823286ba68da388751732556e70a7c2b4c6d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641efbbae90d977c0a77f4a6d00a1fdc193ecaca05aee87ad86fd7458efc1bf9850616ba036f0261d3fbb05bc424770fad9d81a2fab9eae73d3c6a84d24acde4cf7d259f27303adeefe063910662639cd9206b8eed45d51f9a3ddc7becb8e1d697b81bbe024263f56fc7a5f55cd5c1f3dce1d35803fca6550652a1481f3d5d41582d86073393cae44f941e67fb2d850fa0d7a841f3f7007760f5a04dab5a6c76bf8e13d57cbeea15c73e171cc780d6a9ed9745a67e290449b49e5bc260f913c109b2712604811149f7e1fe8660b15f3e9c7c27b36e0865176f061702b8197645464b90c25eadf8e3e7dfb1e0fec34e85834a1a5dd46e16fe1d533563469e8c1b505fa9a39ef433ee7b7ce87bd7d2ac142a5c16fd03db838e94b94ded093b75bdf93a2a91e66878d1a6a955a8d70f562f6276e393d3ac94b5eeab37bddf8de0f74f7f54bd02628b355177f1dd586f09e37f1b80ec17858d180db76c7ee658d4c390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000058daf0b4fadf03c4de067af76b756c06c36d23c217cef183c97956a3fb3177f7ae9b9f79d9ac6ec5c9f3f07e75b6b2eb78d303c91d98a4f03fb478fa73d35778ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000dce634dd5f9bc5e08acfd55a920a255912d7ebfb63916c4272554460fd5ae1f40000000000000000000000000000000000000000000000000000000000000000"]}}, diff --git a/txscript/data/taproot-ref/a65e2a892ee1771cf4861f2c1bc2d5f505645c14 b/txscript/data/taproot-ref/a65e2a892ee1771cf4861f2c1bc2d5f505645c14 new file mode 100644 index 0000000000..6c64012223 --- /dev/null +++ b/txscript/data/taproot-ref/a65e2a892ee1771cf4861f2c1bc2d5f505645c14 @@ -0,0 +1 @@ +{"tx": "b063326b03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfd00000000d54304dcbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe900000000f78d71fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707000000000eeb7db83038ea0cc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df9797223689870b010000", "prevouts": ["daa652000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "f0016e0000000000225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "33870e000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3045022100f81b8bd0e5856e3eea9ceb7a34c12f671328026bf899b61a060b387234269cc60220282122f39466da35d6ffe4a7c2a6e38c2ce97ab4464dfc9eba2d1b0d06a30b3f83", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3045022100e75e677ca31a354f30032050d1126fd0546e139de92a73a5392bdebbed38158c022014973c9342a6e814ab9ed22a17b67e9e04d31507de7cdd7d9a5151e3dcec325583", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/a66d01f6351976b51603542719f7e00648878dc0 b/txscript/data/taproot-ref/a66d01f6351976b51603542719f7e00648878dc0 new file mode 100644 index 0000000000..acfc7bdbab --- /dev/null +++ b/txscript/data/taproot-ref/a66d01f6351976b51603542719f7e00648878dc0 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8701000000bf8067dedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca100000000d2a15cb9029568c300000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47876b040000", "prevouts": ["d3fe700000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e24b550000000000165e142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_40", "final": true, "success": {"scriptSig": "", "witness": ["e426331a8fad2cc97e797187ef99b7fb1e378c4b008a351c3c78fcc06c2f00057798b65a87a8f8be462cc502689790c7d9425918e1204cccf4eb617969dbb42603"]}, "failure": {"scriptSig": "", "witness": ["04499c1d4b3d8718dfff9ce4e57130b60d88e4fccd295f0ad8449031d050ffc80c8e162bb14652433f5b3c9e08c5b22a0cfad24b1c9b900f8b017783a4c534bd40"]}}, diff --git a/txscript/data/taproot-ref/a686f07063eda38bb50a12b8bff95eb203e492e2 b/txscript/data/taproot-ref/a686f07063eda38bb50a12b8bff95eb203e492e2 new file mode 100644 index 0000000000..6ecb9d87cf --- /dev/null +++ b/txscript/data/taproot-ref/a686f07063eda38bb50a12b8bff95eb203e492e2 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3e01000000c939c0b1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3c000000003e7a40d504d3214600000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a603000000", "prevouts": ["72c32600000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "70d6210000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d668", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936661e017775885ff16b303f239ff1d68a27e8f3b845da3c007af0c869ad5cd4dbd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51e30d689b41c4cadafebe300f1e3aad2e0751ea174af1d1313cd49baaa526270b3acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08296d09828da376c7d22ded5a4cf88780a729051831fc4ab0b26d0bae49a473f5539caad535bb8d51429d9c94edd44271a241bcdcdcd941caf815b31d1e73ac1400dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}}, diff --git a/txscript/data/taproot-ref/a6932b59aafceeb75607a7b5c0b5d93b3f2e17dc b/txscript/data/taproot-ref/a6932b59aafceeb75607a7b5c0b5d93b3f2e17dc new file mode 100644 index 0000000000..5dc9b50567 --- /dev/null +++ b/txscript/data/taproot-ref/a6932b59aafceeb75607a7b5c0b5d93b3f2e17dc @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ed0000000005c790a2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6c0100000018167116dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9f00000000e046d60303b5e5830000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e74d241b32", "prevouts": ["69900f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ae0c58000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "92f41e000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4b4e321dfd5536232eaef67cd7779b0e400c7a17a369dbe44f6d3cf0436c0a34cc80764b3c3e93e4958bf58fae47a07e6a3ac966c9bf86a1c799b8570c4674755"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364111e840683a1cfa1052f9cfdcf24e918a2939e690b2f7481352b952cd61f4023f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f61f73219d91856056394a010eb6c8ee7f13c9683181be224f0fcf47ad20d61b9aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}}, diff --git a/txscript/data/taproot-ref/a6b7a9259b013c7a8613e1a5291dff6a4c46e85d b/txscript/data/taproot-ref/a6b7a9259b013c7a8613e1a5291dff6a4c46e85d new file mode 100644 index 0000000000..e4f22dc83f --- /dev/null +++ b/txscript/data/taproot-ref/a6b7a9259b013c7a8613e1a5291dff6a4c46e85d @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd3000000009fe7febfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b86010000005573ef0e03daf96e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787dcce0e48", "prevouts": ["492f4f00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "2c5e220000000000225120d0cab111a0a7736e4b6d77027eed86efb57774f05b322cfbf052f28c507b8b1c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "b17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cae86cd3dd9bd9d0577c5e628f8c108447049b8824610cef934ea775cccad27dc037589144f6259b59768147ff9100354b3b8b337e77dac87d022b72101a452a989f510e73a03c44610e5cde856f75a0d7582565d561698089d126c5e7f66809"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d00392cf6f299065ffbf5a36392615c3de37904e8baeaf39337c685dfd4950987965eeee556c39a9ca7aea66d0df3ed5bb1c1b5d1b815eb2ab41d6c7fc5721f63804e0ef706f1ca5c8b2fa38155abc6bb5e2265734815bc03afdad0836bb7f05989f510e73a03c44610e5cde856f75a0d7582565d561698089d126c5e7f66809"]}}, diff --git a/txscript/data/taproot-ref/a6ba23753e57cd1a1f2d7e37472e4679a0f113a7 b/txscript/data/taproot-ref/a6ba23753e57cd1a1f2d7e37472e4679a0f113a7 new file mode 100644 index 0000000000..ffeca1c769 --- /dev/null +++ b/txscript/data/taproot-ref/a6ba23753e57cd1a1f2d7e37472e4679a0f113a7 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1101000000c10c2513dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4a000000001013795b0240fdcd000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac35020000", "prevouts": ["660a7d0000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "ea8852000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000062", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f93f6925a87bd14746adb659f1fe3cf13cfffe886e85290181fd9d778229362a9b124451a95f66d328740c8f74b6bc79ec66573930240463dbcd03d8389735ccc3a658b9783cc0a28fcc02932d4b85eca4f49aba0b4fac0b36a7e3a0001ff4113fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4a90fb3f53527a925db2b4d49a3795cd34d4dcf648c4b3a4a108990f2ed12b180a28c39ce330a19a0d6c22ddc640bc3609271e6194de475fecd1ad84a88d361935a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}}, diff --git a/txscript/data/taproot-ref/a6c5d8b49fda54f8534027bba1269af6af46da1f b/txscript/data/taproot-ref/a6c5d8b49fda54f8534027bba1269af6af46da1f new file mode 100644 index 0000000000..eb446a307d --- /dev/null +++ b/txscript/data/taproot-ref/a6c5d8b49fda54f8534027bba1269af6af46da1f @@ -0,0 +1 @@ +{"tx": "1708ab0302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1902000000fef83395dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb400000000292d34e70146f851000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87f4000000", "prevouts": ["dd835a0000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4", "51594f00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "417d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e53f01d9cbc4ce44e53bf46e342c1ac713c14ac9ff1cc3e88a31c5570fba253bd819e00a9246c8c145cff8a91ff4546d478c6c8e3d7b4e3f7e61102a4388494af"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e6b3e1503a75cab4228de52cbc7114305d9c61d6436e3951ac91baab2f1e550532d46fff335db0bc559e9bb1dfa0a13335da6dee7eeb053c06bd06875f6e68356831d286b681d36077bb0670e25d1d3b2bbe36e9d696c3276746d4ede397eb7d"]}}, diff --git a/txscript/data/taproot-ref/a6ccf2fabae7c6419459beefef87fd1e78fb2d4f b/txscript/data/taproot-ref/a6ccf2fabae7c6419459beefef87fd1e78fb2d4f new file mode 100644 index 0000000000..bc26c57525 --- /dev/null +++ b/txscript/data/taproot-ref/a6ccf2fabae7c6419459beefef87fd1e78fb2d4f @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca801000000af0593dadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1e000000003ce8e7810303907300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b3a96d28", "prevouts": ["2743510000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "27ec2400000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "e27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ddc5ef0753cfbbae9ae95a5d7a8057a0f244ed9534f11134802dcf3d6e001e11de3dcad145b88b360fb9f51ed5363f34910a171e61f360dd6bdf047d4a1b93cb212021a26ea5e00fb993aa3d0fc1bd1e431f365db69035b8e4625845fc9b697c"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0bc8e394a89b61e744ca0843579507fbd14c939f32cc2eb6ce7075b90210fcdaec7827d9bc9e4e8e39cc141cf7690ea6843d6b50eda1fc8d5571fb149b2aabab"]}}, diff --git a/txscript/data/taproot-ref/a6f23c5bb6dad507a24fea1ceecc0df2a026481c b/txscript/data/taproot-ref/a6f23c5bb6dad507a24fea1ceecc0df2a026481c new file mode 100644 index 0000000000..3b90beed62 --- /dev/null +++ b/txscript/data/taproot-ref/a6f23c5bb6dad507a24fea1ceecc0df2a026481c @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4901000000213507c5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5300000000f92f4bb6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf150100000091782beb0145d3670000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc4eafb2e", "prevouts": ["6e315000000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "96f25c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "60086b0000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "0b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93684c23a4f834a7effc42b1c4f88dcc82246b0d4e764e461eb4f4db8348ecfb3306eee185c5450ca8ff820874ed786a77ca41a0ece110e4e1e272b53628d0f659ee0d9bed60e53dfa6fe8b58229f37daf0597893c765c7b30814eb9e16fca89b86"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef92671edfc08b1595b62488145cc68a42644b51379cbb9ed71181eed5e56f97e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8784d9e7ee919b8817f3904ff7d27b5c3a4ce3798ed5b994b75288b8e9341d9b42c78e40500fa05b550b7f6357dbf83024c41a574f6a1706762c104fa8aec3fcb"]}}, diff --git a/txscript/data/taproot-ref/a708a2f8ec818a38ec29e17b587179a32b43d704 b/txscript/data/taproot-ref/a708a2f8ec818a38ec29e17b587179a32b43d704 new file mode 100644 index 0000000000..25e42af2f8 --- /dev/null +++ b/txscript/data/taproot-ref/a708a2f8ec818a38ec29e17b587179a32b43d704 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3101000000c451b5dd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127015010000002772d9f604f9e86c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df9797223689876014a635", "prevouts": ["13265e000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "6cab110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "2b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670b7161a5b1cb29051dcb3b6acc763e0bb56982feda88150ccd46d276a32260d527b3d6e358222ba6f0d0e44427df3c74648eb5abf60e34311dababed48c5c2bd74d03d2cf0ae79996d1bf896237ca201e78f1b4c5ece550af4c0e01e9fa9886"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e44f1db148647e579a127c5c190f6913605985e391579ddf83e446378ee4bc7a1d75fc84f2af88925f7ad475b3203cbf9256a43a0cda52d14a3416be93a7fb1c4d74d03d2cf0ae79996d1bf896237ca201e78f1b4c5ece550af4c0e01e9fa9886"]}}, diff --git a/txscript/data/taproot-ref/a70da8709e12ffb27292ce7290967a40c89cf126 b/txscript/data/taproot-ref/a70da8709e12ffb27292ce7290967a40c89cf126 new file mode 100644 index 0000000000..9b43debdc1 --- /dev/null +++ b/txscript/data/taproot-ref/a70da8709e12ffb27292ce7290967a40c89cf126 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaf01000000ef6fe8da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703c00000000151d319e02c354820000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acb4e81421", "prevouts": ["e0b1750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bc630f000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3045022100e3ea4829c15a3bf776b65a0fe0b1e6bb100a0413eb3b20dd5820721f3a62cce30220223e98bd049ac8f17a050b740e2a8cff561ace71bae3711903eb991d6e66976082", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["304402202e4e74cfef2382a010e10be770a5126740c96b42c360beb847292202b380fe49022043a288cffa8855e928ed3ad9029d166d467591dee6597cf40b5e941982dd81b082", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/a72f0993c4460fa269fecd7c19909f1a8f319d4a b/txscript/data/taproot-ref/a72f0993c4460fa269fecd7c19909f1a8f319d4a new file mode 100644 index 0000000000..f2f537ab78 --- /dev/null +++ b/txscript/data/taproot-ref/a72f0993c4460fa269fecd7c19909f1a8f319d4a @@ -0,0 +1 @@ +{"tx": "2b467a1e03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3d01000000139453f3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b81000000002569e0acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4c01000000b62770a0012fe80c0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc33010000", "prevouts": ["8f265c000000000022512035205488698c55c3e7035f1484d2f513744eb9d8b6fb6f0df083f7669ef0bfda", "7d6a1f0000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "d6c05300000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902346020a3263d5c4c92afc2504229468ef459e0c8a9425c4b8d7ad735c4ccb785c9498de5c43d514bac29008e912d831cf2bced5c999b623ff09c62adf6557f97ae80d9e399719012a7d1818a223b88fd05226bb64f4410d12c988e3255557b67fa6820165b381a9852e5e7a1c65d27ce16d1a13b893e68d6e1a5a4a7779735685573fbd3f40f31d7b19f02187a97d4069eba036d9e3c34ffca5326f3507b0b8f3bc18803d1e1e1b297e5c6ffd68e0263ec749efbcaf3394297688a5a82bc869a2e3361fc6ab00381d17e644540619e23e06c328f5ba3925570d4e0d672633b571014293081eaf061ec8026cf778e4639dadcab6db4e70281c6b5a6edcef61155f3b41bf44c1c0b87ae762458aef3e3afe7958edbf20d24453040f80538842ea10459d5537825a3f8643daa481d567b0fb169e8c194f1aaa697479cdd94e45e9cafda25267ea6bef876bce509606e4c8a465e1e2395455bddd09d08e3bffcbf397b8e3736568834900b2d4655bf8e1beee4e7eb3eba37ad9cbeeeb467de3c84187621921a6a12b8d66e632bebf7fd93f93acf4c2f200067a4f61956d776145f4c67e7c8156db0586407a9438f23190b426d1569138af117f08d062371cae0ad0d58e023d755ba0498661894ed3ce24eb3afb5c9a245a058072621f58289a70b4463e331aa052570f8ab87060962c9ced574171afcd493da05c0eb34d3a4216e010bc30138d695cc181875", "e07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a9c082d7a7f7de44a9f5e716083bee5abe71d27348a6c6c8c4ae2385abf8d44dcfc84644ef9fcb418936abdde9e6d46d404f44a19de7b4f5c4865233c46051e9a410273431f29264d27122ed0946ba884bbeaa1cf1ddeb7776ccdcb7bb2f1db0"]}, "failure": {"scriptSig": "", "witness": ["4d09023cdc65778912e029db5fe78cc6d0b5525d191b55df27ad4610d3fb7db57298422c170fe1d73a30c1667b0282287d9d54a7ba2b101737721a7476993b8a90d38472e7c2d0acd92f1cf21549b7472adfcd070ccaf6b875206e4db55e2f9ed6cd848bf44e340cd155a04ea322aee16c896614c4bbfaa6e8f6b38f0ccd72d9ed8789a9b7597eebdc6d0c6c92eba9fd7029d391807df09619fc2883f1172ac79d004fe87c89974245e5077a6ef34286a24cf2f96ff82403cf12528673d08083d4b52b343622f1cf9d63c62fed5fc18274173fa2766944e4f3b0268cff4443f771e8781519ad8bd4cfcfe70f6b562735c35ddbbec49b4cbf5a84640a6a7d1d22254ed80f65ed54e63fc545f5732479218c1ff2e15a7f5625c152cc6a1c89a8459b585c7f04ffce84ed0569514183d1c6ccb76f6c772b651421c6b52ea282a1fe049ab742a3017f8a15b8984c8adbd8860a3503a0c6ea08db6faa6658eae1aa36be517a65921509e62b8de98a22d113b2e644cff96696e3196b27920461e8dbc6f4c02a09736dc6b25387b13bf94bca5762ee58d82ba67037939e65e39b2cadde03d71b2efb4ca894fe8574d95dd2d10c3916c37f6b4552b1bb65e636e5c4d424de266883004593f8db6752c111a25448ed4bf9e70bda17b69c780b0374a7aa852f14762a4cb4ad1ad570f0047966505ad03410abd8836032b83cf3fce8a71f463ab4fb02b4cdbea4b2059d4b75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93653ef5c0f24be88f175543190b3df0cfd9a18eda71b356c1e4a2e53d4881e725e8e461ced71aca9bcca55b69078fb4637b626cf10c8373b915aa1b57bf9dc2b76cfc84644ef9fcb418936abdde9e6d46d404f44a19de7b4f5c4865233c46051e9a410273431f29264d27122ed0946ba884bbeaa1cf1ddeb7776ccdcb7bb2f1db0"]}}, diff --git a/txscript/data/taproot-ref/a732f61f7a104110a42397e2f2bcff054f17f50d b/txscript/data/taproot-ref/a732f61f7a104110a42397e2f2bcff054f17f50d new file mode 100644 index 0000000000..2fc2ddd85b --- /dev/null +++ b/txscript/data/taproot-ref/a732f61f7a104110a42397e2f2bcff054f17f50d @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0a0200000089a51db2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6301000000b13edf8504c9d17400000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac29b2eb20", "prevouts": ["4612240000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258", "7a71520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b4", "final": true, "success": {"scriptSig": "", "witness": ["be7e3880ca6e693cac1a5f7889b2e04ad8fcf784d322dd445711a14b845f980a726f127e294281ba8f5a371ca3abda7ef5d65b57bf5cc940de9b0f93cfcdeb9683", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7ef176ec3b5b8e94bc337627fe40b23168678ae536a574515e51fe301b78516c38d4453cf77eb2468ba3a5123a5fc2f6f4dc946b5299b279d5aada1bb926d962b4", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a736014c5e879818948ab14c8851770efe5d5fbb b/txscript/data/taproot-ref/a736014c5e879818948ab14c8851770efe5d5fbb new file mode 100644 index 0000000000..65581ff4f7 --- /dev/null +++ b/txscript/data/taproot-ref/a736014c5e879818948ab14c8851770efe5d5fbb @@ -0,0 +1 @@ +{"tx": "66f1c1cd0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ea010000009c1919fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e000000000477db4ae01416e1b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4879c000000", "prevouts": ["77a610000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "afed0e000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/input80limit", "final": true, "success": {"scriptSig": "", "witness": ["5334ea9e86c7471e37a8b4d5526bc777286b69216c68a844e99e50793190372976b4027c2d9672d4916d60f11b1bdbeeedeed5383c2dcc9f8828f31bde8f845e", "34935091b35283d2de16b48ee783ac66311b6ca0edc7b43b5205053f47522eec8534fac18aa726240187128ec99ebd521e90f971d252f3c4c735939c807f73d659dc58e7434887fe7e9b9422c7223808", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93633f145906eb3b0b9144503b7e952fa7ac030804bf21818b76946b0617a1dc901d4021eb67a5422f2c264ab2e161e443ad68483a924a10f3067064f47bfc1aa823d0cff3dcc0a2d4e46fc30f48a30ceeaa99fba3feb9f110c8632a3b2fa3f4f4f8fbdead7f8de6a8aad36d37b0d589bc9244c1684fd5ac3294cec67c7c6e587a6904ede5a53833ce5d447360be78b94add963f9070eac219e9b04ee2bdd400ddd04364ae3f3c0d48023a93d8481ba8ff7adab87d79476f69028f3fb22b08d057964bbb3ea34308947c748760264ee9e03eb1f98d2b66028dab654f580a418be99661f479a6b0f557293064f4a690bd09af98d8bd3a778ce8944b23259946622ee8f58700e34290ee018923271c5b5338c26b1c5ef6f25154ea2cb21c87cb2bddad45cd3b88d2dbb65b62cf977bb614d0efb5c9353a8b35cfa01122561253231744c2c32064ddb3ff0f538be34c536787771f8aa5aec123a81e8014a979ffa6906075479528a5b4db5d683c0884af4c8976d652dd9505f85dd291fe0843ffd0ff27865ba15c8822e63cb0be5982c1ef15a41fad555080e76aad0b72a8aa15726acd51679a62f62b306cf011a5d1358e6ba8e189d7358bc43376d46dcace83895e75b2934214492b999e4970e4990c42fb0eac353aa09117e3e38145bdbc22646e577b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/a73a44e1dbbda1a5482aab336034e0f3b2631b86 b/txscript/data/taproot-ref/a73a44e1dbbda1a5482aab336034e0f3b2631b86 new file mode 100644 index 0000000000..9e17e39491 --- /dev/null +++ b/txscript/data/taproot-ref/a73a44e1dbbda1a5482aab336034e0f3b2631b86 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a020000005f503664bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3a01000000af22f6838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45a01000000ec72071c0131d9410000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc7bf29061", "prevouts": ["8127570000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "5719770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4e193e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090235768cc18c827edbc85865db0e988cb5b087aea9388ccfaf882c583719a0cfdf8615ffc50c0449bd2f76210a99e4a2c6d78a6e9d76bc7cb276b1de91886e6905d0b086018a1de6c37cd8bfa48aafc0ee04c063fe0bd102bd1407b19000390a77fea54f87a9576ea959d4be9379a20cf94100df7cdeb59173933133c38b0884125a9e997c58e6ef2a0ecc7902f5f7d48e852b738d3ab4657ea88a29fcb53a8aa379403dbad6b3ddb0913f1b8a8662e41d80f4b9f87daf4587bec216680991e4ef6eaec2d21a83291f49b0b10b146f15a02aad8f346e529fa7536824f156184b373df9169ddcc88415995537434a208ea94cb45357989220c2e9a0caa3650097413871c015b020e5eca366975eb4c86fb0576fc3d49ff90a4086365d2979cb38f2735db5bc95f109476ca68b391204e5b61dcd085fe3b075834d266f6f815884ffda7b43debe8f46ec694648ffb6e95f4cd72d9757e0923b2ffe0f090ec181c2f3a533bc1b00ce5850920916777d45a54cece91289e987e797cee320ac6097f0c941f9ca59a2f08ff378195f2e080c4ee150be00da65419286ee9e3a80eda2a6ce4e09721e913ccbc3c7b54422603602fbaa881c0d2d66bbca7b7f7be2670167c512a71c08c9cd45d102d2fa0d328bd1741e20d95aeeeeeed3db2ab1db20a8bad87833418897f35e6587a7427ec2f33fd730ffd169990e7e7211eb6db48ad411faa35811f4098ab71c8e75e7", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe99ab9c338d93c77fb73e36d1c4a98d4f4968424582f3ad48770429ba47f9c01ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045809bd2604b63a9913b428e9bd239a7888c90ad67a336710c360335112147f5da391a14412c925771c32fa4c7776d5872be2a56fee9c5a8de868e7e6e5a4c84da"]}, "failure": {"scriptSig": "", "witness": ["4d09022527e500d120152e18c6e624bb2fde94a3a4f66e7e630e9836935fe44806ba207ea23ff722849369b25be6e16f49fece2bf2e5fff4c0027b8a6792995e97ad33849d39d5421d7c08ffded882a25db3d4e73908c5735ec774ee705a90f380e900420b6715ffa313c178573d8d6c4a9bbd2bf67e4235f7e0720c0ef8bee3224e0b13b8835d88062126170d329fcf7e11ec3e3db3e49ca6e3f6f49854f443072e1f3f988dc5b234d26516ccad4a4268aa4909a96cf1380553097ab3ab0db61536357d6635d21de410a2a81869c8c6eba6082a13ab5aa5bb63c2c4ceca070941e0ae742480ecbc127d6d1156dd3c7f71065f3a39b66f5577301e3978551ab3d1dfa8f0e633123cd2f9f041b3b3f7c911f5060ba6d0327cc368905bd1e2a46e24b7c56a546577eab2035af69b5ae767e72ad4fbc415e25564850821811e598fc8c33e5e834a236faf9cc90b4b9c87ec6eaf43fb91cd1953971c7f43ac756b728decb5020c50ef56fcbcd16f6e4157010d4264ef85c53f67b9ea8352ff1bf37a449f47eb1c7bad1498b0af78af01ac973a6bb3f68d93cf0f890f14362e4a53b53861efb9e4ccc1d8a51e242d08c5ff3bdd2e420db9294fb8ba3c197eb0478308be33416a003e8f456cb8adfaac1cb07fa625280b44e7ddbbf572415c8c81742a825887b1924f2025625199e78bb9d14998915ee9eb98657e1eb5a6857f54f51d4773eeb5b7a38d17eec1a5987561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360513f5f632a7f8be58086e0894937cecc6daf0ca2d073151c884d599ae841f03ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b292a4f502e305109d81040f98432632ff806e9beae33e8faa7e022234476532106df482d4085282f873fe38dcb59fc4eea3656d896112fe243f784a0cfce46b53"]}}, diff --git a/txscript/data/taproot-ref/a742d0a1cc22ae97a4d67dae7649bce1710b89db b/txscript/data/taproot-ref/a742d0a1cc22ae97a4d67dae7649bce1710b89db new file mode 100644 index 0000000000..409c4e0592 --- /dev/null +++ b/txscript/data/taproot-ref/a742d0a1cc22ae97a4d67dae7649bce1710b89db @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3b00000000110e443e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d6000000007304bad901c0c94000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac97000000", "prevouts": ["32502700000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "2ad4360000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "483045022100828cde6313848c24476a72f2b71e49823f118872ba1aae36c5c144fd38e29eb202204a36eb88e21ab4de59e851968b047406b2e5028e4ca303dba5ddd1669f856c2e8200", "witness": []}, "failure": {"scriptSig": "483045022100de41570bb83244d8a2515d1ec806a05c3749a96f7fe9bc234a8a36155089798f02200f8fd23a97f60a695c8931d32f2ef14158d724defc916738d9bfab3926a98ca8820101", "witness": []}}, diff --git a/txscript/data/taproot-ref/a758aa7b471d865a094148a124f948d84c1137bd b/txscript/data/taproot-ref/a758aa7b471d865a094148a124f948d84c1137bd new file mode 100644 index 0000000000..b82479efd1 --- /dev/null +++ b/txscript/data/taproot-ref/a758aa7b471d865a094148a124f948d84c1137bd @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706f00000000c32c43f2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf320100000028b9c79a0196fd4300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac7d040000", "prevouts": ["bd700f0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "b5d872000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/emptysigs/nochecksigverify", "final": true, "success": {"scriptSig": "", "witness": ["", "a42d66e22764169649205bf660a36401a5998de14e4e22ac5fa0f49349dce91254650d6f18dc28cac415e74088abc041f585e96e0c884e7de64d36aff8058e70", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac91", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b87c3d13bda4bc96912d9e1d3614b88ea00288653983e5946dd79f95cad56850892bd312bf555f4ddaee895b667ff52e0154e570fb3b21fb70ce55962eaacfa82b8a8694f12869a73a7c9258692c0a516e36ca599c5440cd48185ae688899f972334d1082e7cf9fba1fb8bfc554039e0d30e1d717d7bd10b1687557faeaf94ec531fe2ceb6eb6fc38e892c8463543d75fb6857ed3555003db7d30631ee24ce556745e6d5f13398b82293345b14639057cfe7c9133f3a817857bdff96787ef39c49602cf62409ee25e64fef6eaf4f70b438998ea376bf89aac812460edc6098d5da36431739388703f162bfd6be43cc18929921c1c825eeda473da76ec1d4f9fb59fb388f102ea0ad67c71defac059c7c8b93c58afe1a654026c6fac78536b8b1901243e25851de0d6781e7f528327af4772fe14b340f1eedd75761d4eaa742157b0a6f9680ce7f5ca5bec9338fe334e6832114c99db2b4b78f7605856e14f0f922c7dab2635ca4d983bce69908efc2d6c8e3a4e02d107fe54b591d6c8cbc0ea2e862ced977f81641729beff04e69bc449bbaee4ae229138f125e8f575c30a32bf5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["", "9c418e456752bdad7c2a2d78dd2db333058a2e8bfb74a2b52dad6b93bca13e67de20aba6ec94b42f141ce7c8f2919f900cbd63cb40934b67e8dcdaa9619fae31", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad0000ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362eb6571610c70f380db264fcf96c64d03665ff198a8b827b7dc791c63516783eb15bda27b7d8ad82c85268f5d7748d6dcf4d5072bcbe6bf1db653a2b9f2a52aaefcd318d6541bb5a7c7e45ebeaed5c7d25dc635446e705c786f9c4ce147f37a9d7197dbb5cfd3049014661f05d5163a8221229ada4cd88087da855b3b81d63fd0b4b5ca1a0f5388bb0d625260e6bd80c4a0feaccd254afb0720be0eacad2de6c8dae29fcb2d9844e6741948f3aa4951320b2ca0e41fcac9fedee7a10c5c5bbcc67dc10fcceb6178979afb039d0ca186b3f923d92479e0d54bcf61271ab453ef19a06951f11ae8cfc71593005298dcd015b99ad04d1f6c27a7163f3dc19ce9a31d4d2a49b2999dc23f41d9ca3b7abd0a877a9fecd5f2ef4fd5885309ed79fd905492e27c5aa3537568f6734824d9e13d17b040b5b13f58e286505de213f86581d977acef7f6b695f70556e0cf280f2f492800c5063304369626aa3de8e4870d2a17002da8b6956793790e2522cdbbbc51c3e76cc941c9170ee3ae91039a9479105f3564c54269032898a6cd874ff4d1fe0ed410013dc82714eb7a54d64226e3868b0e659112c9f7f4ef135ef7e3677927c686e2cfb83a5642dd1287d117c18623babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/a76b07ca76b8129996817bda9c15cfe6c801c496 b/txscript/data/taproot-ref/a76b07ca76b8129996817bda9c15cfe6c801c496 new file mode 100644 index 0000000000..2a7123623c --- /dev/null +++ b/txscript/data/taproot-ref/a76b07ca76b8129996817bda9c15cfe6c801c496 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f801000000038e6fa4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c00010000005e6f05c7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6c00000000737b03c302ffe3c000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac65fd242d", "prevouts": ["a82c3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d5b75e0000000000225120733adac9df449b2595d1b217303cc00a8e3c5ae4d51e5f74120e9d2d90d81fcc", "1b492600000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d24c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820ec8a0a1d660d587d93edd278a1416bd3a7fb5c67f78681973183382c988e9bb422e3784e386a40d51dfdc8b2696050c6780884f0aa6a0f3f5d0b1b514784d82ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936973a7bdafd3a5ef35a7e23347c5fdd71b10175a725fb4e7f58b4fefebafdb0115d26c3c7079b274e62542512e39807ee92511541c708e3b51bc61366b8def992ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}}, diff --git a/txscript/data/taproot-ref/a777b3aa2b4eb6ca1a87d04550c620145fe1fd1d b/txscript/data/taproot-ref/a777b3aa2b4eb6ca1a87d04550c620145fe1fd1d new file mode 100644 index 0000000000..ea9252c0e2 --- /dev/null +++ b/txscript/data/taproot-ref/a777b3aa2b4eb6ca1a87d04550c620145fe1fd1d @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8801000000e3859977dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1f0200000017508a9f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708601000000d56fc4e201266d0000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7e89ca15d", "prevouts": ["0f5467000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "e47e5a00000000002251205857fc26f723a58058d8b22639f4b33f8ef23084aa37309f77fdf87ef7a99b1a", "92430f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_24", "final": true, "success": {"scriptSig": "", "witness": ["57d29c2b50a27ced58aab6a3c76a12c7ad3b9623b943af4a48702d9de690be2fd078169290c1dd1971a2619341656b66e10275c86e6754072abfdb798e920f7c02"]}, "failure": {"scriptSig": "", "witness": ["3551c4fde51445d427eb98a70efc9e5bfb2163ae2d5133a85c1edb7235bf8af3e850dfa6675b240c96bc470db72e9d17bf57c49006ca487e4e9d41062a410ce324"]}}, diff --git a/txscript/data/taproot-ref/a78c1ce484d2b06f18054390abe8ba3738befc47 b/txscript/data/taproot-ref/a78c1ce484d2b06f18054390abe8ba3738befc47 new file mode 100644 index 0000000000..08b88ad4c9 --- /dev/null +++ b/txscript/data/taproot-ref/a78c1ce484d2b06f18054390abe8ba3738befc47 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2901000000e28d14cabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf02010000006dad27f30176a80c000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478703010000", "prevouts": ["44a84d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9959750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_36", "final": true, "success": {"scriptSig": "", "witness": ["40d5a58c9885ab7b1d1b678f6341099506d6bd43698166fe9693788d68c3202d405084d971bd6eb3c5cd0961931e990efa18c030af1d944e42704c294e4db4f502"]}, "failure": {"scriptSig": "", "witness": ["5c6e9893b26b4a6d283f23a6f0f8cb1f11ef43e00fa8aac44ab80ff72cc50d96b10c9af93888770b3b71256cf70dca77d9367c0e3fd22800a4784c2e1a6c417f36"]}}, diff --git a/txscript/data/taproot-ref/a7ca771886a4f3f8ef1274e272ed3b75f1c52957 b/txscript/data/taproot-ref/a7ca771886a4f3f8ef1274e272ed3b75f1c52957 new file mode 100644 index 0000000000..db0f9a7e76 --- /dev/null +++ b/txscript/data/taproot-ref/a7ca771886a4f3f8ef1274e272ed3b75f1c52957 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700500000000d5fa4fd7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2f00000000fc361b8a0386bd590000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df9797223689879194515e", "prevouts": ["7158120000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "8aa7490000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c668", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364338f70e5e33632588fc102a877b38a4fdb50459f63c5574a90f5a912ec702d9d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514a68ec639edecebbcc441a95b015cfc7d67c6cfab51cac7643a880d3dd4163fb31e5a3cd6e337eb252bd8d7a8d95e14a531fbfbee4d245debca50b247e512ad1"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d7e5dcbe8dfb5ec682ee6209548eff1fd1425d8165cb88b4f9c5546369c4bac6a39aac74ee3f63949b9c215c515b0db1b113f4639b3fb19cd99ba22ff01310c728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}}, diff --git a/txscript/data/taproot-ref/a7d8752018d8cded7995daa9e4cd387a0f75eafc b/txscript/data/taproot-ref/a7d8752018d8cded7995daa9e4cd387a0f75eafc new file mode 100644 index 0000000000..cbd57f46f1 --- /dev/null +++ b/txscript/data/taproot-ref/a7d8752018d8cded7995daa9e4cd387a0f75eafc @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf55000000004245bcb4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b17000000009c83f3e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3a01000000932991810400c0e700000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac6fe3af24", "prevouts": ["3f1c6e00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67", "ceaf1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "75615d00000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ff7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8cba978c9f8bb8ad08bb333d68e8bfcd03859985a79755d391cef5d6f406deb57187b9e30f7e626b28b6dbe2d7b101f74e326290698090dbb0a7eb7a50daae87a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93601da56f1886d9f6f914134eb53345fabd457f9b9efbcaf83e02a7ef8dfaa155f3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f59f882dcce043ab5273f79d0d152c35fae0f251a6812c7f2d3daa07c20029a516c082ffd0388de178727289f9edc245ed8244bc4e4186d1c7a66ea621fec0ad"]}}, diff --git a/txscript/data/taproot-ref/a7edc21f3d053cf490a4f0032887dd77602ce962 b/txscript/data/taproot-ref/a7edc21f3d053cf490a4f0032887dd77602ce962 new file mode 100644 index 0000000000..c04c45997b --- /dev/null +++ b/txscript/data/taproot-ref/a7edc21f3d053cf490a4f0032887dd77602ce962 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0a01000000b500cca2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb0010000004057a30b02358044000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7da000000", "prevouts": ["8e402500000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "389821000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d64c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7d6bb54cde9cc6775748a201bb3f5d5704911b2e65f691925d2f8dff2efd34cd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51e30d689b41c4cadafebe300f1e3aad2e0751ea174af1d1313cd49baaa526270b3acfa007b318c5da81cf6562f4932e2754570ba3b679b809769f541be0a6b617"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1360d69898a7d9d7cfe47282f038ce081b7b00f0e720fcc7ce2a76c05a52019262a5aef24b6a1c01bacd2a24a37cefc04a347b590d10f3bd98469f969c355217b0dccf8e3471e4a61057d1540548a04f67f25f6a36812a8ea9d07747f2e4b3a8a"]}}, diff --git a/txscript/data/taproot-ref/a80117d2623452c4c4d047ad5ffdcd2cfd707957 b/txscript/data/taproot-ref/a80117d2623452c4c4d047ad5ffdcd2cfd707957 new file mode 100644 index 0000000000..d098b52b19 --- /dev/null +++ b/txscript/data/taproot-ref/a80117d2623452c4c4d047ad5ffdcd2cfd707957 @@ -0,0 +1 @@ +{"tx": "b3c1472202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf2000000000576e88bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd70000000004c7aada0154af38000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374876209cf31", "prevouts": ["efcf20000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "a7286400000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f64c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e88526c13eb9f3ceda07aab2d6470ded7d71666b865703d69a451a4808570d93ab836f202d3609bf617cb7b4b7700532182ae3d2e1a09e3b3f38346196fd93b669cfd1883d9d94906422bb83623918edcd109683f826bcbf676882b31fdcf44192fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93643ff5ae612146c623386afcd59c1296ef50bdcb60fcd6c7914b141fccfe9e234ece7439a6da18213b739641e86399840a31603efd6bc35e889cb5cc2f58e891a69cfd1883d9d94906422bb83623918edcd109683f826bcbf676882b31fdcf44192fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}}, diff --git a/txscript/data/taproot-ref/a814c0230632e5c08f097102f2033615293348b7 b/txscript/data/taproot-ref/a814c0230632e5c08f097102f2033615293348b7 new file mode 100644 index 0000000000..2ab5851edb --- /dev/null +++ b/txscript/data/taproot-ref/a814c0230632e5c08f097102f2033615293348b7 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2901000000fe70cee560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c40100000092a97d7a03d69a2f00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4a846650", "prevouts": ["c485200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c66f110000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_72", "final": true, "success": {"scriptSig": "", "witness": ["11e22a9e4803cde68c6394178c87bb58aca43a6acf77019d87ad91e3c6c671dd7fc40b515b8ca1e601b764945ccb365ca6871801d05571783d480089b1d9693183"]}, "failure": {"scriptSig": "", "witness": ["54338879af07fd4bde5c2f7c68edcd64ec57c357b701c48cd732917be1fd800693456971040f5f75476bee95ec3579dd7cef72a2e8c4f8199d042358a9fb081672"]}}, diff --git a/txscript/data/taproot-ref/a83603464a89b1ff53b86c47af7c54b0f8a72405 b/txscript/data/taproot-ref/a83603464a89b1ff53b86c47af7c54b0f8a72405 new file mode 100644 index 0000000000..1f1a18d01e --- /dev/null +++ b/txscript/data/taproot-ref/a83603464a89b1ff53b86c47af7c54b0f8a72405 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42a000000003ca5b8c5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bda000000002a7cdb2b04cf6957000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487c7000000", "prevouts": ["013e340000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "9b13250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_1a", "final": true, "success": {"scriptSig": "", "witness": ["970035fdf6c2a35ebb629e3866a63d1ad69b6ee1eb66de87cb661f8a8fe3173f2bc76a5a9aebbf2bd493f92e5f84bac6d418c499852642cc5d64b58b4abd787683"]}, "failure": {"scriptSig": "", "witness": ["4c37d4dbf74b8e1bca59778650430b3745be9d4b1228eb549c230b0407d0c4333818bcef4c632cad10bb17b74df923f3a166c32a9511b73351ab8f515ce3499d1a"]}}, diff --git a/txscript/data/taproot-ref/a858130542274ac050eecd7df40f62a22f2af3e5 b/txscript/data/taproot-ref/a858130542274ac050eecd7df40f62a22f2af3e5 new file mode 100644 index 0000000000..9d5a178f7c --- /dev/null +++ b/txscript/data/taproot-ref/a858130542274ac050eecd7df40f62a22f2af3e5 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4da01000000f19794d98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49201000000e17d8ac402e45f79000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65afb4455", "prevouts": ["b8394000000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "18193b00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["84", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b09f12ec1a5fa4aa343993f316f0126821d68bdf7911bc110cb6f7136d98f163462b9d29a734e556c6b2d2347029c074a964aefd93d416389a14ef3ddb3da113c419005ce053ef5676128682d79317eecff4f27ad8f3a341c1729484208650bf5e521f6248097fdc64ff5a0a6cea9e07e7c649e93dab8ac6058acbfaf1ad70aa"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694086fc36ff4db5fca7b596fd90c3389887398c2c7f02b2c132cac3937a1991e1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900459910ef1376b2f57d6157bb9e8c31b4bd4b9d07432c4b683bf27102948dfaafec7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}}, diff --git a/txscript/data/taproot-ref/a87851edeb5a5db0f65fd04d5730500bf77c3e76 b/txscript/data/taproot-ref/a87851edeb5a5db0f65fd04d5730500bf77c3e76 new file mode 100644 index 0000000000..afdde25101 --- /dev/null +++ b/txscript/data/taproot-ref/a87851edeb5a5db0f65fd04d5730500bf77c3e76 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8100000000cd228e8dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa4000000004c9db3ce04ea51bf000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a60d000000", "prevouts": ["11384c0000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7", "6aa37400000000001659142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["d94c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363223f590d275dbf98f3959a26c5345f553357b5bd8a825b42274d58542b11fc5131be74f8e69d59b35718025ad78971477354696379895e31ee13c64e6c94e9a3a6c94bbfbe0c8d8162307ea587875a7b29cdfde589bfdf70042a40a3445f95ec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ce5a205315494d2cbc0845b221baea99481be73664e5e27f84c5797e8ccf74a7a3ea69b746c966c84daf122809976a6bce8b1d887b17a6e963c4c690b8a790e73a6c94bbfbe0c8d8162307ea587875a7b29cdfde589bfdf70042a40a3445f95ec19ec7aa48c905d8ed6637f3c17c0400a43c560e5c859444683190ee16fe2235"]}}, diff --git a/txscript/data/taproot-ref/a8a3b52078ade562edb5a7dc6ab61ce4b3cca2ab b/txscript/data/taproot-ref/a8a3b52078ade562edb5a7dc6ab61ce4b3cca2ab new file mode 100644 index 0000000000..8a951c3930 --- /dev/null +++ b/txscript/data/taproot-ref/a8a3b52078ade562edb5a7dc6ab61ce4b3cca2ab @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f3000000008d771f89dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd500000000c1cefaf2042f856000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf2b3e221", "prevouts": ["23500f0000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43", "c97753000000000017a914e014b0ed75ce4306970c9f63e88b08a5a7bb4d0f87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "617d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e2d9d76ecaacf763fa245da0e21bf637d9a70bbacbab17d040c4c51a52a3413843a93d7e1c40927dcd10fd5d28aa4402a453542c320ae883aef57b2a7090ae6b3ab6b2d4691bf881316931c587f0a213fdb9026021e80f212e72f88982a6bfdc"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e83f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820063b43826002dc6eba62f224851f0eabb14759fb10c707a6afd7fdb59e93aad3ab6b2d4691bf881316931c587f0a213fdb9026021e80f212e72f88982a6bfdc"]}}, diff --git a/txscript/data/taproot-ref/a8b03c8e24ef968616c561f18edd3944caccbc5f b/txscript/data/taproot-ref/a8b03c8e24ef968616c561f18edd3944caccbc5f new file mode 100644 index 0000000000..77e376964f --- /dev/null +++ b/txscript/data/taproot-ref/a8b03c8e24ef968616c561f18edd3944caccbc5f @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff0000000009808edabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba601000000851525c48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47701000000859dffb10302a2e2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374871878ff56", "prevouts": ["74b9810000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "6309280000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "0ace3b000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "597d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faa393999847c63b69274661db27cd2e7bb4343911a06570db858c301dc754c7eb4be962498b383c32e8a84fa570ade752f3a2216469b10dbfd65078bd8e1b5998"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a236af21b488012c2421836e39d217363cb976e6d84d75dc27b845e8fa3877b3e1a055bce30035b144601862be42e0b1f1d387c5344cafae4ff25a0d1808b56acd61c62feef9509bc7b3762bc81079411fa6867ea4986820580c60fa1e8298e9"]}}, diff --git a/txscript/data/taproot-ref/a8b6c76ee96d3aab811609a8979cfcc67cff79c6 b/txscript/data/taproot-ref/a8b6c76ee96d3aab811609a8979cfcc67cff79c6 new file mode 100644 index 0000000000..4cd0c3ec0d --- /dev/null +++ b/txscript/data/taproot-ref/a8b6c76ee96d3aab811609a8979cfcc67cff79c6 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be200000000ee786e5160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bd000000003fc93dccbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5c00000000b8e3e08703aa61a2000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a678fb6231", "prevouts": ["1b322300000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "217511000000000017a9141a56e0fb41afaf4b9e6feff1797087c69015162687", "f93a700000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "9d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a832c2593bdac0cb0b42624935007d1442180dae3fe4e49dcedfd3101f5729d872756956c694637235f847009e8e23b8c05283b4a047903b3fbdb647ae4209c1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364d9cfd389e774c529beca95e1955030c310e90019de0d0c1b56b68b6d8ca0660e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a832c2593bdac0cb0b42624935007d1442180dae3fe4e49dcedfd3101f5729d872756956c694637235f847009e8e23b8c05283b4a047903b3fbdb647ae4209c1"]}}, diff --git a/txscript/data/taproot-ref/a8cd8ebe1c92a5ce01cb9d553c32988d450e82c9 b/txscript/data/taproot-ref/a8cd8ebe1c92a5ce01cb9d553c32988d450e82c9 new file mode 100644 index 0000000000..047f67cd97 --- /dev/null +++ b/txscript/data/taproot-ref/a8cd8ebe1c92a5ce01cb9d553c32988d450e82c9 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0901000000304617538bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41901000000d85fa7830225df550000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ace8000000", "prevouts": ["d42d200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "517537000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_14", "final": true, "success": {"scriptSig": "", "witness": ["5db449c20988a545b2c3b5f047023aa6b582f5149664cdd8ac8fd4816e980dfd564f6114607f398abfac602ab58fd1d8a69889a2384c28fd8dbb486f591d524f82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["9399abb7aa94859a85d8277e3a6200ebaf4e87f9a3bc74fc366b52db04938298abecf8289cfbd7c8efe9e119940929e81c23d2dbb78f510e009ebea74a1952c814", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/a8f6f74ddb0e0e8e8361ea297e0abac830cc1dfd b/txscript/data/taproot-ref/a8f6f74ddb0e0e8e8361ea297e0abac830cc1dfd new file mode 100644 index 0000000000..48cbafae4f --- /dev/null +++ b/txscript/data/taproot-ref/a8f6f74ddb0e0e8e8361ea297e0abac830cc1dfd @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf090100000080c5ae2e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c408010000006b50ec9a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46f01000000809ae9ca023333d50000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e78c000000", "prevouts": ["8b6969000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "5187380000000000225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "971f3600000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["f259980f9f225d7b43c3471d51a041623278740413d717b078cf94bbdfcfe080250664c119f639ad9c92d5beabe942124a2293c1a07924c261b1283a169c8c20", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/a912b73ec5ce6f1628bcb8d8e2dca4f96fb71c5a b/txscript/data/taproot-ref/a912b73ec5ce6f1628bcb8d8e2dca4f96fb71c5a new file mode 100644 index 0000000000..97eff394b9 --- /dev/null +++ b/txscript/data/taproot-ref/a912b73ec5ce6f1628bcb8d8e2dca4f96fb71c5a @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cf010000002d86ee8cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba5000000005702dfc60407903000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a627000000", "prevouts": ["e2b60f000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "91282300000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100b2294fec2090424a2bc0a41d32ee1200089bd3acc05f34a7300ae8fa367c024702207d8c120680e254106dcc929875cf72bab4870e2611ea3b700a28e71008cf55b7032102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "473044022078e1a505fd632debff7ad03779c8596f10ab310d178f048c3f34b7ec91fd132e02206cbec89154cee6b01a5a062e75a7d7ef5e435e258f8173517d9c93e611b5aa09032102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/a91984528078da07c39af230d966ecfa33124d9d b/txscript/data/taproot-ref/a91984528078da07c39af230d966ecfa33124d9d new file mode 100644 index 0000000000..4706f60c9c --- /dev/null +++ b/txscript/data/taproot-ref/a91984528078da07c39af230d966ecfa33124d9d @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46d010000007fc9e944dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd50100000032d28935bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9401000000353048d30172b24c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ee4b014d", "prevouts": ["17883d0000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "4e40240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c40a6f000000000022512026ecbdce513e5cfeb779eb6a118aa90fae67510c7ee9bff64af6ca27f9068c2e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "success": {"scriptSig": "", "witness": ["7ac11bb78f6874d82c97842aab9a20959d7ae4d83df2dd8a8858170678c05f0a8378d25abc8e73105705cb5ad5c9227f9427f8789caed1c4be27f0587bd643a9", "cc26a8dfd73130266b06a6a47254e04953432f4decbaf8e28dfb7203c052c76cc5a66c1d8a9a2db33603831ec0a0a84cb1cf7e35d6ca1c61f38765c15f9f21071e5580ac3af5545267773a0024d487ff0be757055c80d3fdfe97c5950f521910ef12c3850392c121da12b15ccce7e329a98fce1597ec9d6008e17b", "4cdc07df07fcb3cf785b22ee27afa90728be120f1ac0a2e769f9272c5edf1fb6ce565a0d422a5371039e21c90d6a96379b3c7b115df2ef9cf3c5dfbbff451a8fc49af5e71a097a063fc5fc0e51954038d4ed83b0b917dedff39b353d16332f6c73ea87c2f17d34ee0ee448bc6281ff38f3ed58a92492f6b27bb4cf8134330a59c4387fe0b42aaa77ba10cd6f18c32b7c54ab11e4614a22ff211af1109af450ab8c9b2aeada03ba8fe470a7f6eaf870dd19a9dc98d7b9234e3dbfcb78a62b17b380128fb56fd93d7c1a731626a031f70f1eed6975bee3211391cdd52df9736d0442c4413251646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360aea55674e4a11d078f591c1d921a5492b3bb1be59c0888480755169b7cb15871b7d6818b35e0ea957fad9863835d6347f8f6d9876df5968ca112bcfbceea191949498aa0661d911fbb3348dbcbac453fdebadc4dcd6e311c35c7a5ebf5bbb8bb3920587ebbb9fabc18b7b5c766e9cc9224f8e189e96604be4f961e6da30e1098ad20ddb8bada843816d8e39090b6f68402c2f42ed7e4ff2296393411067a3cc738678ade87a0f60fdc733941515cba8985a82e53060b8d87ae1337100ca868b8dcd092bea6f9e0ab4424f42e6b521eb0ab30e23651fe2bdd8792a11b70c0811ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9e78b7ff580b9714966e7b7b3f9ed004f3990177fddb99b669445d7c1658bdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ede07d4dc7a6bbc7633f9636c3cae9c9db2a0684350bd4065f892a977c68dfcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000008da7e7fc95bdfb9802fa80d920249c2a040024a29c3d7028418946dfb418b33cde545c1438d0372e217a29e61fbda9bfe166556b40c8ff5588f9b2f8951784a711ce63ac71f4b06b9613a79e6108a6e59a2aea5a02d73ed398ca5f6873371ae4cfb0fd2388ef534f0ba1d41d6104a73537cbfae9352c0718fc697592e7056a5ae684870c35202af39cbe0f4d3dc2f44bfb95cab676962ba44b0db6f5e781031ec272ff862a0c809875f9bab87ecc81f2b0576517f3a9963117b503365b64c7a55bde9dafd590f07e9bd8096ae18426952cd7a6a5d90d1b22eb178eb948f93f3affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c57eb9ca01b12caf07c899b2156122922d93e5c05d7b2583e362d173f8e6b01f8d0016d6aba064b8a962d3b2a6c67418815cda9f1d614693aa3e7d82d1106256c5c857024d5dd604cdce5349cce83df62f353eb06e19c5bbad5b461003943ddcd02d97acded234e511f7ef67a86668958c36c395c197a567f77189a2ae0968fc69c3c29c8c0dc361e29f35fb38537a07141885ef9c8697bb4a755b3f65b4fa700000000000000000000000000000000000000000000000000000000000000000c50e512d885169807860ecb1359e927f1d3026393c57dc608c349a7d92d1fbaccbdea492e545c2e9487711bbf6956b889bc74fff183d4785aa28a26b0a090ccb028567c5aee05ea6e1fe0f29ad1629fd5a2489f448148363c89c91b1e16b35a4e95a2bb7d8dc76b9baf117c4390e476b7284bd4af1eae0050ccb46aadf905a5a6952d7b6ddcd40ee4770ddf66cc91abe733ec79bb7da150cd579f6e34ae438c", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["7ac11bb78f6874d82c97842aab9a20959d7ae4d83df2dd8a8858170678c05f0a8378d25abc8e73105705cb5ad5c9227f9427f8789caed1c4be27f0587bd643a9", "9f5d8529c066da90b7c26740035edfa3f15481590570e26e07f4158bf395ae2191251d82f3146488e7c8007b9e6eb88624b0ae7e7bbd405f68db4c3d5bb83bde7148f38acde11f5ab33c3fbcd2636b5725dbd640c658d4851759f78cdb87fcfd0ba9fe8a8b60c793223322fb7cbed449668946433b2663810ebc", "4cdc07df07fcb3cf785b22ee27afa90728be120f1ac0a2e769f9272c5edf1fb6ce565a0d422a5371039e21c90d6a96379b3c7b115df2ef9cf3c5dfbbff451a8fc49af5e71a097a063fc5fc0e51954038d4ed83b0b917dedff39b353d16332f6c73ea87c2f17d34ee0ee448bc6281ff38f3ed58a92492f6b27bb4cf8134330a59c4387fe0b42aaa77ba10cd6f18c32b7c54ab11e4614a22ff211af1109af450ab8c9b2aeada03ba8fe470a7f6eaf870dd19a9dc98d7b9234e3dbfcb78a62b17b380128fb56fd93d7c1a731626a031f70f1eed6975bee3211391cdd52df9736d0442c4413251646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360aea55674e4a11d078f591c1d921a5492b3bb1be59c0888480755169b7cb15871b7d6818b35e0ea957fad9863835d6347f8f6d9876df5968ca112bcfbceea191949498aa0661d911fbb3348dbcbac453fdebadc4dcd6e311c35c7a5ebf5bbb8bb3920587ebbb9fabc18b7b5c766e9cc9224f8e189e96604be4f961e6da30e1098ad20ddb8bada843816d8e39090b6f68402c2f42ed7e4ff2296393411067a3cc738678ade87a0f60fdc733941515cba8985a82e53060b8d87ae1337100ca868b8dcd092bea6f9e0ab4424f42e6b521eb0ab30e23651fe2bdd8792a11b70c0811ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9e78b7ff580b9714966e7b7b3f9ed004f3990177fddb99b669445d7c1658bdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ede07d4dc7a6bbc7633f9636c3cae9c9db2a0684350bd4065f892a977c68dfcffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000008da7e7fc95bdfb9802fa80d920249c2a040024a29c3d7028418946dfb418b33cde545c1438d0372e217a29e61fbda9bfe166556b40c8ff5588f9b2f8951784a711ce63ac71f4b06b9613a79e6108a6e59a2aea5a02d73ed398ca5f6873371ae4cfb0fd2388ef534f0ba1d41d6104a73537cbfae9352c0718fc697592e7056a5ae684870c35202af39cbe0f4d3dc2f44bfb95cab676962ba44b0db6f5e781031ec272ff862a0c809875f9bab87ecc81f2b0576517f3a9963117b503365b64c7a55bde9dafd590f07e9bd8096ae18426952cd7a6a5d90d1b22eb178eb948f93f3affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c57eb9ca01b12caf07c899b2156122922d93e5c05d7b2583e362d173f8e6b01f8d0016d6aba064b8a962d3b2a6c67418815cda9f1d614693aa3e7d82d1106256c5c857024d5dd604cdce5349cce83df62f353eb06e19c5bbad5b461003943ddcd02d97acded234e511f7ef67a86668958c36c395c197a567f77189a2ae0968fc69c3c29c8c0dc361e29f35fb38537a07141885ef9c8697bb4a755b3f65b4fa700000000000000000000000000000000000000000000000000000000000000000c50e512d885169807860ecb1359e927f1d3026393c57dc608c349a7d92d1fbaccbdea492e545c2e9487711bbf6956b889bc74fff183d4785aa28a26b0a090ccb028567c5aee05ea6e1fe0f29ad1629fd5a2489f448148363c89c91b1e16b35a4e95a2bb7d8dc76b9baf117c4390e476b7284bd4af1eae0050ccb46aadf905a5a6952d7b6ddcd40ee4770ddf66cc91abe733ec79bb7da150cd579f6e34ae438c", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/a98e2c1c0077687fbc9166f61a386e4a7023ae4f b/txscript/data/taproot-ref/a98e2c1c0077687fbc9166f61a386e4a7023ae4f new file mode 100644 index 0000000000..8e8e5b3baf --- /dev/null +++ b/txscript/data/taproot-ref/a98e2c1c0077687fbc9166f61a386e4a7023ae4f @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa200000000fb3d70f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49f010000007d25f0a80274e4bc00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8783ce9f30", "prevouts": ["3ff27c000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679", "638142000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "6f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361835f9abe9a741de0e36f4900df38cc6cd8be0480d341e9b7353c9d58c608762796126e2d69a152489172163b4bb3b76a5285668b37fe09a10764d2324ee4a01a6ef766bda57b4717926485a86d332fc460fd2733e6a54825f17015621dd4290"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936702c3c7c1f1da03c8b27f2bc575737070d61786cccc09f33c0640d21457e29b546c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa250e9882e2e133b56af40caa5e77ecf964d6e28c7a51ea626a8db4d1e1f7bbb4a3f8f9fe88f0f431b5ffad473abfcf1c4b340e1c7daa1232bf4c86f035b8cc51"]}}, diff --git a/txscript/data/taproot-ref/a99032acc713604176f8d95263865e2c6dd015fe b/txscript/data/taproot-ref/a99032acc713604176f8d95263865e2c6dd015fe new file mode 100644 index 0000000000..dfeb2e29c6 --- /dev/null +++ b/txscript/data/taproot-ref/a99032acc713604176f8d95263865e2c6dd015fe @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c330100000072fc8e80dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c83000000003e0d57f5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1d01000000594c5146046d9223010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79661010000", "prevouts": ["bb6c5900000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d", "aa9357000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "edbe740000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "dc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362be2eeb3e4370d4c69f7ce59bd76cde59e3fcce79660aa43abb7ce9c746ff5cf86395c8bc923896e22972506a7f348d4e1ec7a5bf3aa363c117ffaeeeab3b8c4ad29df8a0e62e4f40897f8996914b12118c918ca2851b639742aeab01f587290"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936622093dee6774f07419f4929649c97094c7480c0dfd32637f9af19a1dbf7f73a7ec7f48ddb853ff8ec7c3ca68869c312ba33903dcdb15647a5295c052617846c86395c8bc923896e22972506a7f348d4e1ec7a5bf3aa363c117ffaeeeab3b8c4ad29df8a0e62e4f40897f8996914b12118c918ca2851b639742aeab01f587290"]}}, diff --git a/txscript/data/taproot-ref/a9b04af95ae95e9a60941ab351fb387c007938a2 b/txscript/data/taproot-ref/a9b04af95ae95e9a60941ab351fb387c007938a2 new file mode 100644 index 0000000000..8ccfd4a512 --- /dev/null +++ b/txscript/data/taproot-ref/a9b04af95ae95e9a60941ab351fb387c007938a2 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41a0100000058adf9d98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bc01000000feafeba002c3807700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac0756be2a", "prevouts": ["75b6380000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f", "472441000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "7e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93601763a9a2ad9de81aacd638dcfd4fda3d0aea4cfecb2218c942c0044c1357ce3e4e9bfb46536bdbe14fd1969523d98350611f9c0fc6236e31514e2d43f59e146f2e4a14a40b0acbe20218e44481fe6660f01d2e0cf04e3bc8d4452bacd1080d1"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e846c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fab95efb91d04564594d9dcf752eb8fd975bf01996a0bb9f9eb7163324924bcd44fa5d068ae686a8bb1ac9947127542ac866077ad522de57cab26ce701d52bc951"]}}, diff --git a/txscript/data/taproot-ref/a9b58c8a3ebf4f2c3c8af6242b20c43aa733d6c5 b/txscript/data/taproot-ref/a9b58c8a3ebf4f2c3c8af6242b20c43aa733d6c5 new file mode 100644 index 0000000000..371389f21c --- /dev/null +++ b/txscript/data/taproot-ref/a9b58c8a3ebf4f2c3c8af6242b20c43aa733d6c5 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf101000000673c277b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4370100000035cb6dc58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45d0000000023dea660014dee30000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47879c010000", "prevouts": ["f5ff280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0bce3600000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "67f0410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_53", "final": true, "success": {"scriptSig": "", "witness": ["bca52a308ea9cc503e4a56e8b76ba72a2c7527ab3924670a2699ac00f6041665e818cff9fd2719ee27efc7e67e9c6856e37e102a7beb5dcdb7b99eabade779e481"]}, "failure": {"scriptSig": "", "witness": ["290bbd2e84cad0d8171e4e2ec772ae058e958508d478b4ab0e067ffe5d835bab3ae40149ec150f8524a0e6bec7ccb6559acd0cefd987a5796d13fc69eb2ff4ac53"]}}, diff --git a/txscript/data/taproot-ref/a9b81c4e5e52ddeed6c3bb9ecb2f67d7e056eb1f b/txscript/data/taproot-ref/a9b81c4e5e52ddeed6c3bb9ecb2f67d7e056eb1f new file mode 100644 index 0000000000..bc2e04d19f --- /dev/null +++ b/txscript/data/taproot-ref/a9b81c4e5e52ddeed6c3bb9ecb2f67d7e056eb1f @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41700000000818fa90adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0101000000f46e8321024948840000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e784621a3f", "prevouts": ["e47a390000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278", "b2b14d000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ada", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936908709641cf32dc4788f906f7e3621a0528df09509ddf1e9982e4479aa4b5d9a3ad7647dae649c97c815eebecc244cfd5d14ac6da92e0e18049c71625e2af9496ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936868af79d4708fca6e37519c0f8ad1a0e8e0651f5b156ad2621a5318cd7dee94748d61d9b48b1fd3c9dcc7ce9fbab23c91d7bbaaf6610449bdfa8b9a4fdaeae22ee4d75780d36bffae9b56136e6d27c02b8d233efdc800bb260bfbba6a6f94b87"]}}, diff --git a/txscript/data/taproot-ref/aa0024897deb20273f4fad0f856967621953d402 b/txscript/data/taproot-ref/aa0024897deb20273f4fad0f856967621953d402 new file mode 100644 index 0000000000..99c8dec143 --- /dev/null +++ b/txscript/data/taproot-ref/aa0024897deb20273f4fad0f856967621953d402 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf330000000056a475b2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cba01000000746cca94dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cca00000000ed67c018043edd1c0100000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88accb010000", "prevouts": ["e2be7c000000000017a91441ce0eb0e6e5800ced23a872818e5aaa63be0d5b87", "3be74d00000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "38fe530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "bb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bfcd38c1da080d9fa5f350ac5c5d82a433c6ad7048f1837ebebe4defa9773a5a1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454c3d251f378473e49463283b18fa00944324abf75c7e60d6956acdb0e7ed03a7354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936597c2f6b8dc6d15eebfc9ce9773556a5675730a3f06ef70be75161d60adb64d2d0e13bd92b8f417e9a9e83db8f63381783cc5b261abc3d56b5d515d800102f0ba4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}}, diff --git a/txscript/data/taproot-ref/aa0d4dde043c88d76ca0b51949f90e102187198f b/txscript/data/taproot-ref/aa0d4dde043c88d76ca0b51949f90e102187198f new file mode 100644 index 0000000000..8466345d40 --- /dev/null +++ b/txscript/data/taproot-ref/aa0d4dde043c88d76ca0b51949f90e102187198f @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700d020000005955ac21bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1301000000b41584b4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b35000000009f42a30602486899000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c5b9435a", "prevouts": ["ac30110000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "f49e6700000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "7202230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09029545fea06d348ae6624e1c2545fcbe83430063ce13acf465f55bc5faa1aea3fed5cb34f9ce734f5a4a81dfe9eaf2248afdb4ecd223722b2ffdc4d03248d66d4bbbac76d42a70beeac94857f31fc0166892df72f77f49ae5a78767f167bf772a07a98afc46e36d0f4dd741d2b87523cca6458395d28d36deaca72107dd8fa7e0af8b420a4b899cf33240a23064276c0d372e29e7230ad2b12494eefd73a419631e61fbb49e04eb223f37cad74107b23211effae45b6849633cf216aabd66bfc3a5b50ac3ac2dd3b22f771b325d66925bafeb593e88f713496661a176a4a85746825c515740c2b33412a4d74b13140d21d5e8a87458f445aab6440494d3094be25ea54febfc54cf69eeef18371a038f9eb716869bae6fc137c73226a047c1104e35aa1f3f9d105bd449a269463808b6bf981f1bbc60efc8970511d196f9c90e037f5bbdcc666c7bfc1ed19a601d5913a7f20c7bf23e0bb8502f692c4a81103006e17dd4c362810bf502d2481f23c01f8e2041d5a8ca9f4574038fe017f6e150a7f4c78a4d26a307089889ccbb8708de6036650a93c08c111a909f6111fece4378dc1221238b62f3e5549ff7b6aa4e63dd6d4130a02089ed4140a8cc67abdf444afe386004387cddec22d41aa5aac473a048b3800d83d2257ce979d902daa1de78c4601ecfe3491c8a34fc9d8c21471920ccd56cb264941bd8c4469556ca493e4217bd7a545599ec5fb9d75", "a37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363dfa57dfd82955cb3c2f71f4cd7fb6c8829916a42fdf422289d8c886c1cea6eeeebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7accae923b25d556389dd5dd645f6d7ddd89a07a74a73dddd3d85d7b65ae33798aa"]}, "failure": {"scriptSig": "", "witness": ["4d0902debded4a128c081b897dfd50e79e5486cdfb87ce58f88de1fd8f4f02a9ecb27266f07a777b3ee1b67a766762b74c012fddd109cacd3e5311980d75e7cd6da8273afcb0f3410ed974b15d8dbafe36e803e13b8f941c22a6f8614f9bd7c13f64be931fd0ea5354a2a8a811539ee67109132977911e190246cdbd1e115505040435a3b29fbd9b70962b63d1027acd470f4e3e7130d40199f33dbb3c573f9552cab23d6b62915f2d6025efc03a3fa33fd5813afb58bd7213dc18dd824f48c8163c780030929e8787cd59e5e450e941d754f6045abfde62d5156bea8836d65500cf3f275641c27b2b4133483d416648aa6585b52d356d253ad5c6e165efe27a92b6ec86354ae8f54bae78d17abd8661f0b98ce0962d1d045714b6f073a8c924920e2d6d491ba7abad2c6e4c963995849ac03e0a898555ccdee86fcc12883053c218807da5aa7a0362ea2bc979bfd6deb633d49c186d26d269c7ae93790a7549068fcb3f98cdbecf914222223191a6d2b533bd008e2b55ac2ba5c1c8732b7aef037aca22a72bb983e3a1619b3f90f4eea9763fb28addf281c344ba1399cc71a2be4917ced7062f3a14fd2749dfbc71a300f1958b45a9f12c33e541e5ad3fcecfe4aae2d655cd7d4496fd6d48e524076a95a4f2039900a5276b402e15c7b68ab40fb1a8e73749be8010d265d33f2f5ec482a4710c3231adaa72554b42228224a2c046303b129f76043d355f5275", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8842663f27fdccb53374929a05698df7a3618af6b1227ea033500411481dec31ed2054b94cb6efba565738f5dbf6ee5a67458962b65d77e1cf5e0d2c1c00b2210"]}}, diff --git a/txscript/data/taproot-ref/aa17922f64ff7cd6d4aeb56bfab8af47218a86d1 b/txscript/data/taproot-ref/aa17922f64ff7cd6d4aeb56bfab8af47218a86d1 new file mode 100644 index 0000000000..40452b43c4 --- /dev/null +++ b/txscript/data/taproot-ref/aa17922f64ff7cd6d4aeb56bfab8af47218a86d1 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44601000000379174ae60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700c01000000bc09d7fa046db3400000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f877d020000", "prevouts": ["b65e310000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "60391200000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09022ae802224670715d13146496fbec411ba7cd021183576a4da576c5e7df6afab0e2f7703d5bba5162b779161bb33b72d459e59b56a14229a279dfd58a2810cb209257ded4c8140ddfd2634db4d14b135aa8019c3d6cb0aae2e98d268e32ab9acf75400928e12a21e0b0e8f021e96bb09b34a4c89503846f206ce34b90e3e85e103c5797dd74e8f22d334752a2767540a28dc4de88ed0b7ac8632706da8d65b935ad71017de5ae2ae86ac5ba0551827f67f53bfc0bad7c4f96952b4330b2a06d020dd03ce89234d5bcc9c71cd7d55bf23ccaacd1d4fde6c846a5a6be88f630a2ebf5f2d823c82d312a3ff8a4e4f581ac7bf187fc1362f46d8cddd7181e9115dc30f85f963aedf354e2d412a4a8410835b34b28748e75f6faf6acaca5c56aecb03b334d10b5aff219dace3883518ee582fd1e83f218cd77005514ef6d4ceb3a16011e71f692dfde80bc81769f7f37a057451e56e8e43264c3d173a32b01a92bea68fcb6384846449d4b56e3cc476417b4c957cb776c2dd2351e23910349b344decdeba6c7a25fdb7e9fa85012e2fd8b99d313a99ca393408d4b8aa353361a4d017fb3ad97caadd1cbd3adb7aec97014ac8a7c8d23e16853815477748aa8d1cc1f6b7d1bb294fbdead603fed042e5de6cdd5b98d5b785e7fb0f3c4e61f307981c225c2523aef15fdd34ef8c83c27f9820a647b03c687b1b5a379fcd1a4491de9bd9551a7bfb434fca6fd1c75", "627d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93656d54f472826838e1a603c388c018d7e2c442e320e1b9fe79e87cbf43c9b1b239fadf8666e14892eeb42c4caff758b4cfca6e22c4a95966045c21c8e48555a5679949ec80dae58a557a09f1025b3e427a5f07bf4ca030ef1ccb63f0b9143cb03815577f72abc2219d93608f0bf386debaad95a87d0f429ecb808b0f22f69367f"]}, "failure": {"scriptSig": "", "witness": ["4d090222c733a1aff26dafa63fb9768f3d0600fafadacad8057e99bf90d3f1f37eeffdfb09e59697c521f0e4803e05e56f9f3f798e039bb7da0fcfe460ba1332e9a22d9e3403fcea2ac1e215fc559e6a81afe356daf73a0e77505772e64c54f5a26ffc157e9c31735412eacf8e39643689b78e0c741348f09f8a5dad152a621664273cea665cc13e9ff35717f2631522d971dabbde3a54a0dd0b09870955ef1d2de98d44881b7a5c776b604a9cbf7fa6a4504e4f1b624b1f1f59e74ed52ce83ac1c30aeb69102b1038a662d802d3efec0aae30eed412e2533607cee148ef37970c5662fcccbeb035f867498fe57329e18c038c1cc51ed5e1ff60a95aa69e048a32d985bf7dee6599cbdedd8783cf3e8085eb29438a36dca688beac460e8a3631c143e593e545f87af6f2a324e5c3644f10fd6a334db07b1dfd9802bc0d7accfd24cd6f02d0c051d34018db2955993017f1cc32b87ece0dda6aaa49f9658120956b80510d0f06f1a5323ee6903bfe1990182f31ee270b96765e6433ef695d7a4f002d07236daa1f6efa67b190f8b1499f4df76485518b2fac4f906d0e63d3eb0fdd57e5b37539a89243ae7707a66964b1e90ef41d61a69928e73e447fdd0b4819e77c5c292111b9de58026936e505a38746f15013a7ed2893e71d427ffa9c9a7b22c0ab2a827f2cfa5701ead6202ef29a060c05380aea813c122cde0ed0cf9ff1b75e70ed8c02de4036e0c67e75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936054631cbd4c23a7a986551177d2d547e6cd133349cfae470f4b00878641ba0dd79949ec80dae58a557a09f1025b3e427a5f07bf4ca030ef1ccb63f0b9143cb03815577f72abc2219d93608f0bf386debaad95a87d0f429ecb808b0f22f69367f"]}}, diff --git a/txscript/data/taproot-ref/aa376ce844fe5f3d69f1047c99cbef99e732dbdd b/txscript/data/taproot-ref/aa376ce844fe5f3d69f1047c99cbef99e732dbdd new file mode 100644 index 0000000000..6ebbcfeec0 --- /dev/null +++ b/txscript/data/taproot-ref/aa376ce844fe5f3d69f1047c99cbef99e732dbdd @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd20000000060f33779dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b70000000001ed470278bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ab00000000c60fe4de03dd71ba000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987a6000000", "prevouts": ["e3725e000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "5044260000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "2a20380000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "017d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ae3d185db005c09585d5b0f947903fc32969987416884748fade3bb438b9cd79d7f8ee1a917297df4869582a1b348cabbff1db4a1952fbd39d89a346cd02d0a88810a2a55ef559e3dd2f859359930339f67e2de31eeac841179b888fd41fd8a3"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c9328a947efdcbc124cee070bf3f4cbfd90ae8e6a9d27cdf09ac9715c089de0e54ce7cc5f439b597f56fd9de2c1657ae9d64eb6e71f5398fcdfdc60a0bc251e633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae05873438be84f92d1402d5d55e9fb409fe52800aaeb5db180b239b834bc1ca2"]}}, diff --git a/txscript/data/taproot-ref/aa471973e1dc517ae959d5706167622da05bab46 b/txscript/data/taproot-ref/aa471973e1dc517ae959d5706167622da05bab46 new file mode 100644 index 0000000000..229131afb4 --- /dev/null +++ b/txscript/data/taproot-ref/aa471973e1dc517ae959d5706167622da05bab46 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1b020000001b786e618bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ea01000000fb510c0860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700f020000007a80c8d8019ead11000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d2de3b4b", "prevouts": ["ab2348000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "bb733b0000000000225120c52c9d5db69f3d85ee35b65e5555252fc0470ab9a3dcbb72267f75438b29b283", "885a110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/emptypk/checksigverify", "final": true, "success": {"scriptSig": "", "witness": ["1693bfe5b28d435d17ac23e9b193024d3c7a1ed0f364352c5b0b607a3b33ce903f5cab3637a41d6f22164e60b2d7a0a2a6b804a1219c1bf3da94471784ed8ec2", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d2db232a58a684473efffe5f8be15c17374986169cf18c1adb110b544d48679b6f3543d66dd2934a4b4b5b83f3181725b5ccb68f1096ac62351c7c97bd1fb9501b8110e709da1864e3fbcb3b5249515c34bb807e7a52bfe6718950e769cad388c56ff404b78dc0a0b90d50115d89846b94a2b0a1f0895318a364e3dc179dd61f9b1e0d638a311a5be1486a7a4c42f89ed43ffd1d5b18820f631006aab35c0b2a02b593180c53027b35b862cc29f04a25efce114c7682377a83dbcf64f6fe42598064c72ae707f2b03b7d69f3c0306a0bb5edc9aa2d90aecbb96bd412d5b1ee8f00d68262204427d46410b755bc31a6012df0b06b921e6cd021b936d3d4c99eead90212921e1142bda8cb81c5ff3145b34391c40797432570ad9a88a0958a1b955fe09784706370c5f6fd13c48513ab6cc16af1e04504ea44462b93ae24aca3b2228a833ef2c51accd6ee09327b5cb9ad2975d597ee135bfef0964473e20f824ec199d2a72d3d5f5ff6ee974913584144656ddfc893ea617971c4925fe8b7e1c4f556906203221bddfee6deb7780e80a3769637a05bcf2efe708f1aaa4a6ffdc17363486d1e033637af9f6d28292a4f4527a2090bfcb5efca2ed9c0d63c01e16c98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["fbfad8d835135af4001e59862b3e17fa552904e0a0ce2e872868206be76519ca1dbdfa700541b0b064ebd20e3cf5be2043d83d3b780e4ff926f91b48c65ec35d", "00ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b37f9cba90643389dcb84f8bb3d7354cace0c9189961587fd423479e33fe4bca7f7bc4310acf33ff6106d71eeafb5e618c06787526c83b3a4f243d9848205cbcd98a80529c2a931358c54a01926483afd2817144d11587481c84348a7a5d142851dee7e8956e7989ef1b2310726d24273d46cfad50082ad927e9fc98f9c143d160fce98e5a349b93a878297fe66e998ee720c75d1643072843d75bdb4b18b12adcdd58f284ab1c59b498a19651ff144478d4b0b5a2922bd70cb075f336fe9f4b68777d0bbd7b6c4a577c7fea562e9f4fea2126efe76f3d0ad98be5dbd6871c94c0000d45126f851620d2066634add2abef2580dc803514e3ba652e78e482b6135b10babe6957670b3c4aa2c76f4112b74affc1af435c8383e13a10ccc3e8ee7052652d5467ddd2e384b678ffc365e66fbacf63a4fbd01922cf714b18ee68a4e383d323036182d3162529448348339fc9acae0372091043e56911cb51e390ea725dd19e02d4685ba017b89767b5c8376f6b66370e3202d9e807c9c5b06b99c098acfa6a9da80a755a207eb5a3ad02b1a2cff248af93ddec122a727b43b9e8dbb8b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/aa56f625476b200e65ada22557c871b0993ff86e b/txscript/data/taproot-ref/aa56f625476b200e65ada22557c871b0993ff86e new file mode 100644 index 0000000000..bc8c68e714 --- /dev/null +++ b/txscript/data/taproot-ref/aa56f625476b200e65ada22557c871b0993ff86e @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb70100000009c40cc18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43f01000000a76706c2046e9aa400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a61f296e39", "prevouts": ["7e7f6f00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "395737000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a6e961960920036299d1290338b03b5fc0897f2d1c8c4c30f54431f2f0ee319875bc139b944cf1f8d9ed8319ee656276635441c9dbef5e9eb4c61f0ceb683bead4fef1ce24aa15771c39819008f8fd2690127aca0aec153183e70aed34d15336657496d8b13d384313b7ad283ed3b4c5292d6b176114427cb3fe829cf130dd77ff5f11ce3c672c5977051de6c6a7ff55f64183600a82656c96402e98f961e727d93b5b34d8a32d796071d788cb1cdd6212e6740bc003f6f33e7d9fe189815f33aca8ca32c35197fb65562669c2f1466fc27a7d78f4f20b43ee3d8c20d2f51bb8ed6fd203c7097b3920f0598a07b8b2c6661bcba2c61971974c50fa88cdb7f9e3cca427ce61eeb88980b1af88ddb9bc121fa6f908ea9ac784f19b1662dc862cc789f31c0a8d92d90549c9b192c2362c668fab700dc9a744fb8645fca7e66ceecf523df27c017b001039084cfcaecc4f3fc957e37f26464b7f1957cfa1f0edb6396eb9b9dedc5eeaa59a3a122e1f80b60fa77c78d5052ed476e8aaf910094db652d41955f9cf148b476fb1824cdef660d8cf66ddd57d946b6048cc8265bcbfba522e74d42a6a4914cb35ab6f6847adc7f2e3d1d18593dd7cba6c11770d319856183767c77754ecbc734c40e5dff8e8bd104f69e5ee5720ab801718227155131d9815497d51632d3ce862793423863967c90f8f6bc2773de8f88f40a79608b4498abcb7514cd35c01455075c3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51073db8fdd32dfd70cc3c0b801d057b12e5f9f3471dc2e8803f572b477b94c5e2cd8777bf679e716871b092f46e3a69645e6fd098b2f58cf3078cdf1926d6f261"]}, "failure": {"scriptSig": "", "witness": ["4d0902cbc5aa41643b6c51d7b13a9a3ec2bfd5cfef5cf0f3ff575c817e8be58f2ae4c07c71c6c5f7ab6b78f7bf50065c5abaad1147d417d090fd16f5174d56dd97fdce6603cf36ca929f3968b77b7f426e8d579011b3a783f4b31ac9c5b9f4c962e1242a6556b375cf9a2ecb331bc7a301bdf245e5476ab1a4beffe73294404c26866f596e282869777c6f3c62c1b2822fc667ed42ce32b806135cceef6abf45611f2a4a006e4031cce851779b65ebca91f456dfe34a2bb391143b7c31cfb8bfd36287e20d3a94cb2f5f477b69e87af3d7dd7848be6204645f04db752f36d664591e4ef3786f81153ea3048528ed9e68117b1c8b58dce4652d3de1a2df1ee51926b7e8e33f84e1deee0283c4b990c33b3cc2fda057ec41d1514476141bf012876f160c355b16772e2a83f2cd8edfe491bdf73a428c68cd94412ee12e20dc5927891912b633ba5733ceb498c516289af39d6c593fa32147b7b0e218e55257ee9eb03b74a779b09a4cd5b5f6e5121ad6f2bf75bc453dcb608a6031004eb57c61dee83442533c82f90a664f3d4b2192d666df4b2c3ee7e328b80a6eb6e5dcba7eae4303ce1719fff7f71a3e67bf8a4645c38706af0bb1b40a117000314b63cb1e637f0e8e9fb529d56d1797acf1427771672099e42403357ea9603774cb05a16c54bde721e45fb61d2967c17cfbdb6a88b921e4021e047e39e4fb918fe3d240c9049cabe43c84280d89e439aa9b7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a346b8ad70cbb62328f229bdbc3f197dc64b80564f2ec5a0a874aa96f70b3c11ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900457cb9328b065f9eb1f6f110e9fe7273590c885552330e2c3269c2432845ee2744cd8777bf679e716871b092f46e3a69645e6fd098b2f58cf3078cdf1926d6f261"]}}, diff --git a/txscript/data/taproot-ref/aa76c2e6c5a061d0580802966b8efb8804164d68 b/txscript/data/taproot-ref/aa76c2e6c5a061d0580802966b8efb8804164d68 new file mode 100644 index 0000000000..b4692ce469 --- /dev/null +++ b/txscript/data/taproot-ref/aa76c2e6c5a061d0580802966b8efb8804164d68 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8600000000ce2f9983dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4601000000204160840467558b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ba17e93a", "prevouts": ["35af690000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43", "468324000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "617d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93695bb8d2654824dd3955526038f4022aa362c37fc7f85a8eff2e4eedc1db354e88a99f3582d6399c0406dfe65dca998a5ce57b7e950df5f64352e1bbf6c7fd210dd304186c0a2faa80f59261766b0cb9b0760b78eb1f31f166a6f091ab62e6898"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820063b43826002dc6eba62f224851f0eabb14759fb10c707a6afd7fdb59e93aad3ab6b2d4691bf881316931c587f0a213fdb9026021e80f212e72f88982a6bfdc"]}}, diff --git a/txscript/data/taproot-ref/aa8eac8fb7ebd4e613d8bdbce660665b3f45fa66 b/txscript/data/taproot-ref/aa8eac8fb7ebd4e613d8bdbce660665b3f45fa66 new file mode 100644 index 0000000000..eae7a6beaf --- /dev/null +++ b/txscript/data/taproot-ref/aa8eac8fb7ebd4e613d8bdbce660665b3f45fa66 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127076010000009e98a7e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb70000000033ac90db0331e2690000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f878995083a", "prevouts": ["2bc7120000000000165a142540f27e90740933c99d4f17ab2dfc6c82951cfb", "e0b558000000000017a914d574841bde7bf0817694c799002118e85acf040e87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["dff0006548d0260c0a1dac0892042eb1e23b110b81a12e1d068876601929ed6ac8749a22e15e624632b52257c2a704abf274f6d805aee49c4b3668b32f2efa00", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/aaa6693d92f9027513267fd416bd6201171873ac b/txscript/data/taproot-ref/aaa6693d92f9027513267fd416bd6201171873ac new file mode 100644 index 0000000000..43ad3b3fd4 --- /dev/null +++ b/txscript/data/taproot-ref/aaa6693d92f9027513267fd416bd6201171873ac @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6c0000000082abd590dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf4000000001ad7dbb460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e60000000013b495130186bf0800000000001600149d38710eb90e420b159c7a9263994c88e6810bc720b41b44", "prevouts": ["0cc849000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "fc1a5d000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "703713000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b9cd8a3131493f9a38a21fcb48f1eba7224ac37029eebe06423782cc0227356a6b70b7a62b5c5e0df92365fb7d59f0bc38341b3d2e340457f550b81c2c042a2c34a04a5098447f4e0398dc0c9a2c4efe1278fc77be1b3d48003403aba1647b18fc8d6c1b07c83ef33d2e4f6f549d1e37a8a4712f5ca3077e4083fa19c096182fca0777e37589bc4580da08a05badd8730bf744c4992f5d50e09f508d744d3513fb4e219b36b5ea7738b1ce4f855932bb3cd87cca3066cba6663ed3ed25149aa013897acd25ecca7572fb466e83e2d0415c9aa6966072bbc72d7844a948a578a8976593b24a6e318433ee35188a12037ebdcde58e40c27745aba9875db31d97a2aeac76c4b49722ec8240b2872409a8d41addcf54646c31b8d758151ca431e11c12c94691ab0602ed63ca4ad0063aa269fe92180628d9157ea1002bf9b04e1f21dc77542cbf93670541053b0bf2da4be5bc2f9d6889574141d15acf183bbaff9c7a1ed845136486d7fb708d3b0a870067113d93f5add14823d7100e62015364b60d46996ab563139069663a27841b7c812d0ffcd69a36da0def4988ef89f3b1c62ed27eb39541e747e402b7e8e5f2fe1dcb115faeb28d7377ef2fa157886512f57ce8d8b63ba8b5143e91ecdfd7fd135f6cd352193fd910e2e5862c998bc956034e841142c6e231b382418c0a92e44b1607b80179d30c8ec5c9b07fac7a31d3f64bcfb5911377e71b8c75f6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b6ced9e64c6943ac670763abd5f717e15a7508527424507437b13b7c3de1f72e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bc80a3081e946651089c17942e2d2b7e0a2ba8b51162f8e9c4f29cb18d1603310a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}, "failure": {"scriptSig": "", "witness": ["4d09027b619195d54a4b56dd9a65e2f82bfc8d9d39dcac3973f228597b598b7df306aaac130870a83828d085d2549a149f97652604785dde1d37c687e5cdf29a17a451e9508c624ef75818fda145e62fb23a47b08e7fd9e3dcf4a5c057100a538e921018a9e7debbdc364607738d22378455479e577cfa3773e4927726f5f970ee2e997b0f3a3c164ae45811306ee93ae2c497f2545e1a79cb2152d86e301c5d1e5c8c0b902c947459a5fc6c4a739b24d0e30bf52551399f845b1c725b79c7855ec8dcd89f922110407a7da6c9d5b46d7969a30175eb0c7136836b07ad23e95fc81e2e986046449b8b329da5a258e48cc7e4dd33a3efbc0e06b56526247c092476ce3028951cb9a34d52564d73d4d0c0b743e0a6a639b1e1a974f4e83b231e396a0425b27ca5dae555f94bf4efd7746634fe26e5d0548127abfc8dcc0adf24d0e81053ea6eae37e394c59715aff0dbbdc8f97bde90611aca3e800942b5cd785a5b66b2579b7e411b6932c9a0c8be3be66a6641d3ef79d2a8366d7f6ad1d0089bd0692ddd33c68edf3116ecfd7fe8a102a994fae2f118fc0d91b7dda468b006ac2ec69415e943885310b20ac51e9d25f9ef762465517e59663e005681eb1d6e9fec63d30a27cb9f676c366582b265362bc58968b589fd07640f66feaa137072f8746f423fef594e7d975069aaa83a158219014be0a4610228c4cec86a5d4b4dcb07f7c17cc2eb55036f4e8df77561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936de506355e3cf60ace4cef323af6093f7f8acc431ceedff9be89b34e31adfa37dab836f202d3609bf617cb7b4b7700532182ae3d2e1a09e3b3f38346196fd93b669cfd1883d9d94906422bb83623918edcd109683f826bcbf676882b31fdcf44192fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}}, diff --git a/txscript/data/taproot-ref/aab859864bc25e0a7b430273941b291f2b765ba7 b/txscript/data/taproot-ref/aab859864bc25e0a7b430273941b291f2b765ba7 new file mode 100644 index 0000000000..c83ed67e2c --- /dev/null +++ b/txscript/data/taproot-ref/aab859864bc25e0a7b430273941b291f2b765ba7 @@ -0,0 +1 @@ +{"tx": "d2300b08028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40302000000f7c3138fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4401000000dfa691ce01a7032d00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac6b020000", "prevouts": ["21ae390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "358e5700000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b2", "final": true, "success": {"scriptSig": "", "witness": ["7be32c72334b10d1ceb87f1628d69a055e362ae6399e8f3caea7734554d7f404b806c40f527deec4f936d3c3f5efd89b95f0dca8aa6719bcb3288cc2bc952919", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["30a2af13cb5dbb0192b2e4c32f4677c39f56879e7f39ab9adbf9bb63179d2bd9d9de71928a380b53e028f4d5c145f2971c94f0bba6058422bd827c7da9c47063b2", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ab1a9283d7a85a42aff52d1937193ca27a794187 b/txscript/data/taproot-ref/ab1a9283d7a85a42aff52d1937193ca27a794187 new file mode 100644 index 0000000000..3b826cec84 --- /dev/null +++ b/txscript/data/taproot-ref/ab1a9283d7a85a42aff52d1937193ca27a794187 @@ -0,0 +1 @@ +{"tx": "d21e6dcb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44801000000e3a0c5abdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c52000000009db4d7d80252268f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5a61c420", "prevouts": ["4d7d41000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "c9354f000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/checksigaddoversize", "final": true, "success": {"scriptSig": "", "witness": ["46fb23060054e2ae7f44f744498642d34576a50319d408c31a9aa40c4754fdacf7d8505910d566fd902d1b2824351e39b6bc737e3534c9c12b5f54a0fab7df02", "04ffffff7f20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682419aa8d327067d95b4d536ebda455395190dd39e18c03232c492cd77bbf5c60655563be430965c12747e751ecddd5d613c326da0f298b6d45d5546ff9dd2ae4b9207f7f22c04ad05799130349bf7a540cf626b5f0a6721ec598560e06bc37c524a194b587849a62681eb9ecfc58471f5db76a054ad222105d6bb4a3b31f73358dcad47cba8e25f74a6437445fae536d2fc98c7487c1d21b3cfb5f5da8b0c2c7f51ab2403311907e0e6eefb69db0ea9627a1f736af8b880d64776e77cdcfad0db33a6bcee22afe78593b06e3e9eba900a802e002bc410d58121b00203e38fcafd9c9a4a65bf2c3535fb687f4d013bfbc8370da866330e8ae0a289930d67ad7eadec89f6dd5d95ee9482e5d679fc9b2ac5b5f79305e9bc53f8e44773a97b7da7b264c52f17389da701e27ebeb344ec2483d6d2fbd801b12beb3b02b8a807d69e5f8f1ecf0284d5344845e5c6781a87f37142204f7c9741aa330acd0daa91ff9e2b619b683119747c3df61c0924a6b44488817af04f06674d926c898b0b6db546464e05bf50edce7b1f5ca81822687132cf7d30ed84f6dc8ca7e183a338d302e00ae160e990742032df386ec8547eb181c0d102fa876c1cd80d9ef530fa1c065d2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["c022a9962f27b65ba8ab2636af9f7be02b206ba5ecfc1ab6808cf5e49bfff897137a29532a6e74f6a941c57403777143643f7996349946723e8231eb1d52b7d9", "05000000800020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ca373a9284d9516d65ca57d42aeefe677abc27971d99a0e576ea3e033f0e37e18e226a88f8de1ffdbf8653e5e5c99d8ed6854f82ec6180716e498db4090bc6632eca1c10f6e29adacebae9c18d35728cfda46eaa96261d129acdc4b9e453cdf8e00a42427634156bf48aae55d12e65b2b6cdc4abb92f4ff102785641e1ad0d5b12d8443b4b548fc10604f059128cc28d89f7aec36eeec0a36f070495d2024be6b4d9c782523004c55b59cdfe76d2b17eaca8dbca1786e586c09b966ccead252fef997c426d9e949c5a3515b5e0042d45e4be44351c6f149d4fc020759a6f4b0d67374e7caf20322e7084d9546ded12af1d1c5a4e1ba9f0c95d59cab087df6e422f503472e6304a227f15c06c4bf90b77a0576afae68bfe51800240c398f7b74c3dfc6c9c46ba420c22a4b23a6e73e8909bd27f9a6cc2eba3b71442d590039c84de8a0e517ca4f4c263b0ab1b11f7cea6a468382fed8b4a21a3e6c2259e4be3735e9e781db25a304cb2b703fb372b5fb8e69d12880f4d83920da47a594e16bf0d7b8ad7363e0a6ef78402a031bc0a044f5a7e6c01a5c111176c74efd8c6d7787a57b391dd67ba025b9a60505ecd7fa3b5ed0808730285af9f495e709e1f92ab88b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/ab3899ee5c2ed560ae6beb77e71e4950fc17aab3 b/txscript/data/taproot-ref/ab3899ee5c2ed560ae6beb77e71e4950fc17aab3 new file mode 100644 index 0000000000..62cb033bd6 --- /dev/null +++ b/txscript/data/taproot-ref/ab3899ee5c2ed560ae6beb77e71e4950fc17aab3 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45401000000823bfdc18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4180000000071fce1b204401f74000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac97050000", "prevouts": ["167039000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "9eb03c0000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902afaedba19cb07ec09801623e11075a7ababb418ea1b7c72a87ff84ab94884be0ff71ed539686fb926a5a8e18f3a529710f152f7d75586ce74c16f7e698a04d7a3d5e9087794f38ba5c142d6f8703d3e92545eb79478f909ff27933cea4e107c57b944b4db8c28397be2b62a24f2524c9f4c6ebb62120e65fe3dc54311b573f267932dd23a179b51486ee3df1e2efbe176d93e1172f177ae1d00b1a7475cf9ba06799a9546950496f3cf8baff20ee660d0d98a1cc31e98561a5a9ee018a8907d9ada2957a91a98b742d80904e4005615c403b06e184d52d32f08b96c2f0307b2a79d73843c4ce0cad81c21bc936ccf777a00362ed5c2295b49b2809ee15b4def6a493a3c64afa02ee7322a0a56a8717faf742b7b28b56b7cd0f2138dec6498799576554f5d387c9c3a7ba8e33d8305d529b585bad9121620ac4011e603a3ff94524fb1be6d6cabaec1c188f7012b2fc728b1ee92dba8f4a6fb43d02ec841f4be3bbb291319987fce484e11b500d1acbf8d553e9aed556ff6fd17a88477066a25f6556f2af28c147aca567d34b33ae17105192dcdda8f1b6c96748662bc8428da0c4bee1616c2197215c7aaed62894bbb43c2fb5bad3831052d055aa2e2d78a1c6d23445e27cbad83fdbfd86558fe8d46ab871212c2cf82232477640c01c3673b305d891992dfa26d73e696e928fd355da5437211f6d15d6107b9d8c1e6ffabc4dadb6dd682fdc95c93975", "5c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936747197b798ab967e07c108f007a4e907b9ac872703c3a06a0173ecb6d9f2921e0ebd37c9b7767cfa75ada9a6605680756deb542ec34cf1dc29d9c7b172412f3174e87bfb4d3d415907d7a3196832fc57be4f6d746253c89a46e8e4c968740366e8f45a3ac55dff4b7d62b0bc42204f13e92c55212ff162d480a58edc7717abc8"]}, "failure": {"scriptSig": "", "witness": ["4d0902ee4099c1b8af946c46ded066c6a996103ea2900a9f9448f7f9ce44826a2467b76235b369763273f90a1dc0261df39f8e85940c155532f372907c8b28317344624df52d38fe54f1205efb313d927a1e234ae6ac3096ec247636bcb7b9af082a4d4492758599673e4dbe94decb5bd6d9637926ee909d9904218632c4197de102d5844db217b68ebecd3d7bb48d853e4f1fea6d07fce5877a82f29a195e9f1e656b77281cefd2808215ec157cd56aae00592212c9f3ab650cf372d69091d0a1a34fb1403bab22c1a0e15305c413f789c2a01cd21b660565fa5ba9f75471a261dc0e9a629a43a8ca651d93c6c74023526c2998068a6cd19fe7ffc8d2764f9a275694cc0df97438e287f01c4a2fae01c0ff148438b698bd2f19ff0319a8e5d9d7cc9402b8c1890b0b8aba1e0a8c6eb8e8a9806942a862035e8d1453dcd13d402423284b5d563a9ddf71e6d8facd5a5455c07a86e876aa9dd53b998df32cdb78605ec8ead49f9e0c7a3a80270d7e10aed5fbb3b40b9780343427efdb4223d694e52cb95db932e52ccb040530a601c6c25dcdf6cfa488f77d370767b8533180399b98d41e3369af4ec7f28a4bb419e3ddcafbcd604cfee6733dfa23992659ff75375e8f38dc16ab6ffa42551da4dce6e787055ffde5e33c8c2c1ce58c07096cb7c3f1578a32daa5183e727e9827d1978f58d854651a2c3dd6bdb6880dff44a5e4e906457513f70aed30da9e5175", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e24e037abdf69c22f44b0c591ad93651f749184eaa819a8a63a5d4092bdddfb78f243c72f4e074898aab8058b3c73fee97ec3b9723e213834a8398e97170c1356"]}}, diff --git a/txscript/data/taproot-ref/ab3bd8d93632f274ea33e6bac92fec9215c4f20f b/txscript/data/taproot-ref/ab3bd8d93632f274ea33e6bac92fec9215c4f20f new file mode 100644 index 0000000000..445a18bc87 --- /dev/null +++ b/txscript/data/taproot-ref/ab3bd8d93632f274ea33e6bac92fec9215c4f20f @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba0010000003f954bf360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706501000000f7025ddc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ec00000000d17f70eb03851b6d000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3a773856", "prevouts": ["90ed1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6154110000000000225120685f1f4d981f8d279e9288f3fac3f130840e4486d97e094876558f7ee35a7d24", "1f353f000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["304402201ea9793149473141599ef76aaa580bd98f5b76a3c859ee25a8cadc4e20593e4d0220393b8c9b051abf0f4bd2a9c2662964b9b2c836899d7f97cc0926c0642a090a1aa0", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100ef3fb4bcebbdc0847da0040badbfdcb28262eca9e90b23e6a5e8cf61c38f13f802201c199cc72e1c3cf48228ddd38daf02350e3e9b159d24ad5f025fe475b74c86eba0", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/ab3f300e2417c10f0eedeee88f719e82892e53a2 b/txscript/data/taproot-ref/ab3f300e2417c10f0eedeee88f719e82892e53a2 new file mode 100644 index 0000000000..f06006825a --- /dev/null +++ b/txscript/data/taproot-ref/ab3f300e2417c10f0eedeee88f719e82892e53a2 @@ -0,0 +1 @@ +{"tx": "dfd2e9c702dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3201000000e75193c860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c6000000003e731e9f04828f2e00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7eae9964a", "prevouts": ["f48f21000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "b6d40f0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f04c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045ad7df43f1383df9f0df0a1e0ce133acd14e2258cbe9a702da78bb61f4d1a9bc80eb43d08761fb76661299d0344fd2d8bfc7de5e7c6dc622156e95971f4b8396db5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}, "failure": {"scriptSig": "", "witness": ["4c52f0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936276aee05659d89654db507d09a750387aefafff0901ff8ece8a28a5fdcfac69a8e2168769c1e98187b117731eccdce651c542044ebcbbccf53ba5dcae5773e361c2a3c32f2d98482ccc0ae7bd6919d8eb72134d3589ab943a0402c8a931ea420419704ddfd13dc63b1b4156372563d65f148a89e112fdd9cbf47f8afee5da0a9"]}}, diff --git a/txscript/data/taproot-ref/ab5267db0c03e93e08f51b597821900db93ae75c b/txscript/data/taproot-ref/ab5267db0c03e93e08f51b597821900db93ae75c new file mode 100644 index 0000000000..433ae0d345 --- /dev/null +++ b/txscript/data/taproot-ref/ab5267db0c03e93e08f51b597821900db93ae75c @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c00020000002b7885eb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e50100000052310cfd02d0af62000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac12010000", "prevouts": ["b53f550000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247", "eed40f0000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "847d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e83f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08276735f386d1a4700f0e60fd19c47be953169b4ae01039887cebf253884ac2528c568c76d6b344a062dd798f6575db1f1731d6a7ca3f2682e7e1b801cd94d3826"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369b280e7b0e172100b660b30f153c20cd729b6a3e92d21f97d20774fbf01245e83f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08276735f386d1a4700f0e60fd19c47be953169b4ae01039887cebf253884ac2528c568c76d6b344a062dd798f6575db1f1731d6a7ca3f2682e7e1b801cd94d3826"]}}, diff --git a/txscript/data/taproot-ref/ab8bd300852ee0d05f0c8d476f4205347466c6e3 b/txscript/data/taproot-ref/ab8bd300852ee0d05f0c8d476f4205347466c6e3 new file mode 100644 index 0000000000..16ee36a0f2 --- /dev/null +++ b/txscript/data/taproot-ref/ab8bd300852ee0d05f0c8d476f4205347466c6e3 @@ -0,0 +1 @@ +{"tx": "487bef7002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1002000000de8b8aa4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c69010000002054ea8402c7f0a4000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87a505741e", "prevouts": ["b4c85d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1ac8480000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364dc685ecbd8fbb467f50be3541444cace52e2a96f82f6e3a97ffe7c20b40a1e235701ef224ad20174d0190f97f9f6d3f23a41bbc27fc82fd96c9e1fc2f7b2cb81ef28805a30acff873fd9260c6b3bfee2b626467fb0ce04f716d513a8a4b08b6f288028cdab461d62f9273620b97315e6e9af9458f777a616c1bade2d3f6a89e"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f183944a14618fc7fe9ceade0f58e43a19d3c3b179ea6c43c29616413b6971c1fd87b85adb72b018dc8118730af51fe2e1fc2345a45c291032ad5ea0f36db09afcaf82673e7b509fa61dcb6f9390da3a7ce1e18401449d1277235bd9d9c04d9a72d00f85eae87f4cc31996f158484f267a3b4b9a04e006b9a1cff5c0be2781e"]}}, diff --git a/txscript/data/taproot-ref/ab8ffe370320d075a8c7b9daefaf545d29b7ac1b b/txscript/data/taproot-ref/ab8ffe370320d075a8c7b9daefaf545d29b7ac1b new file mode 100644 index 0000000000..076725a333 --- /dev/null +++ b/txscript/data/taproot-ref/ab8ffe370320d075a8c7b9daefaf545d29b7ac1b @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc10100000045d79042bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf650000000093c03899033fb4c3000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac0a030000", "prevouts": ["9f9c520000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "0ae7730000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["fb4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d514c1cf5ffa00c6c7050afc353617823cd679ab4db6c6aacae1c16f62a2980653852b51aac478484d8a075e848b67a41ce9b347e1249fa49816f898b909a6d4bd5c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93658233aaee0e6be68e94a661d667ba26ec53439df00cf64033a82f3558122bc08006cb24f353cfca0d245645f6b16ad599c212098eee86bd01fc37c5c4a863127c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}}, diff --git a/txscript/data/taproot-ref/ab9b4c72f3a16b2e16d40652ec33ca2a8ee4d3ef b/txscript/data/taproot-ref/ab9b4c72f3a16b2e16d40652ec33ca2a8ee4d3ef new file mode 100644 index 0000000000..93e23d6859 --- /dev/null +++ b/txscript/data/taproot-ref/ab9b4c72f3a16b2e16d40652ec33ca2a8ee4d3ef @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f9000000002952ca0e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703501000000ec13486101dbaf04000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ebb0ca47", "prevouts": ["2b700e000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "1417110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "cc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa45716b950e27a233a501a90011450809f321d0f7541cd1975fe5718ce8e53406ec1da8cea892037e805a477afbb54b1f5ec380954f076c0bcd3c4e3d4797a8d6"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eaf68f276ddb4c0fc7f0310a620a2f1f9fe6c0e4e29d0e280a559099e56625bc6391effb841e4c3f4ca92b599bc572f2bc6440711e20bdc5ba4fc353379105b198f95dbc4edc81931664a748b39a9978dd32dedaf5c850114f6bd2f5098c050fb"]}}, diff --git a/txscript/data/taproot-ref/ab9c711cf8bbafb6cdfd30f945bfcb03cf0272b6 b/txscript/data/taproot-ref/ab9c711cf8bbafb6cdfd30f945bfcb03cf0272b6 new file mode 100644 index 0000000000..516b9931b5 --- /dev/null +++ b/txscript/data/taproot-ref/ab9c711cf8bbafb6cdfd30f945bfcb03cf0272b6 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9600000000431e98c960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127048000000008ede57ff04e6946e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987ddbdc542", "prevouts": ["320f5d00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "6a0f130000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "47304402202a8ba61e58c9d7ba6cbcd346ef5c7351f9d2a0bdb7ef7c857111135bdcfeefca022040b7385d8f2a8df68fd527196e4d88138c4bf01b4c160db908b51928b563838d8100", "witness": []}, "failure": {"scriptSig": "47304402201914b8fb7b2ef0ca7b231c5ddc350f2d53699dea6c0d9b369e58590e81a6ba270220552b7f1712a4d9a2439b70adeae3fd9cde34be3c36392e53b111590d0bf757bc810101", "witness": []}}, diff --git a/txscript/data/taproot-ref/ac0b35cbd93f63ed7452d6acebde72ca9fcc3d81 b/txscript/data/taproot-ref/ac0b35cbd93f63ed7452d6acebde72ca9fcc3d81 new file mode 100644 index 0000000000..d1c31a372b --- /dev/null +++ b/txscript/data/taproot-ref/ac0b35cbd93f63ed7452d6acebde72ca9fcc3d81 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4160200000022cbc59f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700c0200000019f988b38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46e00000000d2570be0027ad87c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc70deadc2a", "prevouts": ["d5b6320000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850", "59ad12000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "5152390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "867d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936926f2b50f3fbd9ffe22dc41af4426bcb82a03b8aad9cfd0cba46d108de7a4ac73ac108bed01ff7a3c4482bdb9637a0c08eda3eca9d378124f08be0fd1593c53eb98f84b0d7d6fcb38bca0562970da4fa4ac9189daad947902c07179846baca90"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f28332fff4e521a34f62a6094c9ca083df763bc212ee1a103146f1ea11bafd96b069f256e7b53185a64c953a8831f99a2248244dec917c9fc219bffc52b204f"]}}, diff --git a/txscript/data/taproot-ref/ac2088d883a0a84ac9d499824adcbd32f90b53c8 b/txscript/data/taproot-ref/ac2088d883a0a84ac9d499824adcbd32f90b53c8 new file mode 100644 index 0000000000..fa99360a7b --- /dev/null +++ b/txscript/data/taproot-ref/ac2088d883a0a84ac9d499824adcbd32f90b53c8 @@ -0,0 +1 @@ +{"tx": "bc10ab850360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e20100000056ca8ef0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd500000000f9c6cbc3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfc0000000042284be90453929600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e73aa04c47", "prevouts": ["1d5b110000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "dc1d28000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "74b25e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "797d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364c421c3900c3463ef8c952c4f696eeb0bc35e56e2135d4a2e925409c37853bd90793fbcba16d5416bd6f0933503ffe6704f239223875a49be11ed5869ee331b55be39dc57762be2d9b1a04aa5b570805d23104bfe4fa54c392bda5d51f7f4540"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bed135788b70ac7e03f21dc901124d8cbfe8ea126f939efbc4c5594a61331086b1663b8b45656caee420ee834d80103f5ad80f9c4de199ff6879db0155217f4eccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f45727aec9530f4cf05d3554e63105b96634da39f3c52c35c251ce860693e97320b3"]}}, diff --git a/txscript/data/taproot-ref/ac3cd67c26d777875eeebe2e90c716e8bd592ff4 b/txscript/data/taproot-ref/ac3cd67c26d777875eeebe2e90c716e8bd592ff4 new file mode 100644 index 0000000000..9dce465669 --- /dev/null +++ b/txscript/data/taproot-ref/ac3cd67c26d777875eeebe2e90c716e8bd592ff4 @@ -0,0 +1 @@ +{"tx": "324e93d202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9a010000002b5640d48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fd00000000938fb6ab03c0a05f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca2c5a437", "prevouts": ["7def240000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "57833c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["8d", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93698751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d593f37adfd687dc0da405a76cf860eea33b50edba83aa9aefe64ccc08331b86a062cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004529493e63f0262db246dc905ef3bca459233a7269b5efdd4093c0b189ca3e559193f37adfd687dc0da405a76cf860eea33b50edba83aa9aefe64ccc08331b86a062cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}}, diff --git a/txscript/data/taproot-ref/ac93b3ca2d9c1ec6e07725af461ea07bb19c4dee b/txscript/data/taproot-ref/ac93b3ca2d9c1ec6e07725af461ea07bb19c4dee new file mode 100644 index 0000000000..c44db52452 --- /dev/null +++ b/txscript/data/taproot-ref/ac93b3ca2d9c1ec6e07725af461ea07bb19c4dee @@ -0,0 +1 @@ +{"tx": "bbfdf13103dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba801000000044ebdc3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba3010000006ee87db8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0700000000b29ebcbf04633b6a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc791357b23", "prevouts": ["55991f0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "bf142400000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335", "5a22280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ab7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082a05ea26d8201abb1a5c146c7fb3e541bebd813f78d5cb214a01f0b6fbe6f45888cb303569f28fbe8acbcc2d27d183e3a68170f5392df28f40a03efea695d856e"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363cf3c913a0d0151d6af78c78da1c827a410891daf294851874f6597f4ed324381084d1aecbe4c7880bb8a882fc35fa9ebdfb0d7259cb873bd54dfc151a0965e70144ecbe7fb1e6c18f5b14cfe26e6e35ca66fe7cdb676ad740673ee849f6d44e7c07bb1aa10d02d314eb70c923196d0e49e71087637e2d5a1d7fe44c2440c398"]}}, diff --git a/txscript/data/taproot-ref/acef576be556d6720814253fa450ffd2684c3c7b b/txscript/data/taproot-ref/acef576be556d6720814253fa450ffd2684c3c7b new file mode 100644 index 0000000000..0cce5b0fcc --- /dev/null +++ b/txscript/data/taproot-ref/acef576be556d6720814253fa450ffd2684c3c7b @@ -0,0 +1 @@ +{"tx": "9b03967e038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40201000000116593bcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c30000000008140a59460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bc010000003f8a038f03ce439b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a61f020000", "prevouts": ["fa123a000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "d8a45300000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "95390f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["844c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51120199479ee6d2d4c88363683365d3fc0e890ec8511afbf0335c75bda2c0295827135a2a7712dc4ffb0f490ef0a9e18994dae8053f69b06dfd6a349e2375b7df7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}, "failure": {"scriptSig": "", "witness": ["4c5284", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362266a7dcf41e8820204b3c7c313a73998dbb7a25b9b7d0a8551836cbdc8e1fb771f92e1336a687ea436697fbd19181210e765b944dc821397d885c783bf2f2425e521f6248097fdc64ff5a0a6cea9e07e7c649e93dab8ac6058acbfaf1ad70aa"]}}, diff --git a/txscript/data/taproot-ref/acf314897698e9e208634f10df880184d9a7754d b/txscript/data/taproot-ref/acf314897698e9e208634f10df880184d9a7754d new file mode 100644 index 0000000000..b3592e9eaa --- /dev/null +++ b/txscript/data/taproot-ref/acf314897698e9e208634f10df880184d9a7754d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1d00000000065a48888bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f300000000cb7a9eb304fff3a800000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac0c020000", "prevouts": ["f03a7100000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "75223a0000000000225120cf3d4a21d95f409285a815c665903ee1793a8187aefd3a8003cd262b63069349"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d303776f49134788675b6d5b8e7b8eaed975f4d3e59d9f0e5d87dd448448e55"]}, "failure": {"scriptSig": "", "witness": ["6a1c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/ad1589197b44cb0c659b26869de6c66b103e9682 b/txscript/data/taproot-ref/ad1589197b44cb0c659b26869de6c66b103e9682 new file mode 100644 index 0000000000..01a443f26c --- /dev/null +++ b/txscript/data/taproot-ref/ad1589197b44cb0c659b26869de6c66b103e9682 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d901000000d5ab22dfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf98000000009e40c06902500e8f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796b4d1895d", "prevouts": ["8fbe0f00000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8", "f80a8200000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["30440220789eb29595867f82396e51d5c7d9f29952c0fc4f15adcd99147964726678e0ac02201e539d06a9b8036bbdc86fae321b6e02c6617bb2cbad6db08de13a2250b29af931", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["3044022078042c6547ef7114819b28d5f39cd7658f2774d195dde461f784474718bad9b002200fbc52b8cd87a8ceeb47da23e70f33fcc7ad67c4716828202877590f7b5f6b0831", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/ad16650f9e472fb459eb487a9f883c894760b565 b/txscript/data/taproot-ref/ad16650f9e472fb459eb487a9f883c894760b565 new file mode 100644 index 0000000000..af6dd11e7e --- /dev/null +++ b/txscript/data/taproot-ref/ad16650f9e472fb459eb487a9f883c894760b565 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b56010000001507ac2fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c880100000047f521e4028cc57200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df9797223689874a000000", "prevouts": ["8ab320000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "3c7654000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "867d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364703c1194851d3d768ad1a24962dbcbbc112958428edbb9508a4568f63128e38ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f4576b069f256e7b53185a64c953a8831f99a2248244dec917c9fc219bffc52b204f"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d95cb9e4ba0f14f7a61daff0d77db36648450ca2d57fdcf621c9e46ecaedc2ea0adedab43a8ab423f9b5916bd9a862eb4f524e14c7176baa6699ffba0690b6e8b98f84b0d7d6fcb38bca0562970da4fa4ac9189daad947902c07179846baca90"]}}, diff --git a/txscript/data/taproot-ref/ad382a856cee976ed155aa5fae9828cd059ccb26 b/txscript/data/taproot-ref/ad382a856cee976ed155aa5fae9828cd059ccb26 new file mode 100644 index 0000000000..69d7bc34ce --- /dev/null +++ b/txscript/data/taproot-ref/ad382a856cee976ed155aa5fae9828cd059ccb26 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0d02000000f8d073b0039dd41c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac60040000", "prevouts": ["1fc51e00000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "107d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082dad4d220d15ec254ba214a445cc73922794d5f92559e27b8850a422e98de131f09630471a62c8657382c38b342878f0042beb3ba209e0ca1417f9db2e3d45f6dbd940ade039b405c8439b762bfbc73f9441ef227e6f687b6d94ebcbac32155c7"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365814385e7aeaada39c80cac3230b4e4d86779350f7373f36ef6f8a954e148cf2da7506a3091a1e28dfc5b9aac4646748f840add9c91a317c4120c5f1dff96d2e4520b5ceb13d27db1b37ec8ee9ee9482aafd08fc62c5401b1fb7c7b4ff374c3d"]}}, diff --git a/txscript/data/taproot-ref/ad4069abc0712cf1f3c8508b699379282bbf556a b/txscript/data/taproot-ref/ad4069abc0712cf1f3c8508b699379282bbf556a new file mode 100644 index 0000000000..1248ac843e --- /dev/null +++ b/txscript/data/taproot-ref/ad4069abc0712cf1f3c8508b699379282bbf556a @@ -0,0 +1 @@ +{"tx": "c44943fd0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705e01000000f83269838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f01000000d07eb1f80331d14800000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc15bca94a", "prevouts": ["76f80f0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "dad43a0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["954c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93629aff60e439a9718fb9441d494108642f29be2d6809c2540641ffb56ffbcae4b3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082adc7c8b3bda8f17728820267d55a41d559bf30f92e294931cb4fa644579829c4d4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}, "failure": {"scriptSig": "", "witness": ["4c5295", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51aab45d9ee0154589058109bae8be3e72a724d93a0656d7cd013110f238c03b0975c046d699a38e7801f010fab6b697cc237a48311758c02bc29e281a6d7a682eab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}}, diff --git a/txscript/data/taproot-ref/ad58a3216af0b6f002972233963f6be39c7aee60 b/txscript/data/taproot-ref/ad58a3216af0b6f002972233963f6be39c7aee60 new file mode 100644 index 0000000000..e404e2ec54 --- /dev/null +++ b/txscript/data/taproot-ref/ad58a3216af0b6f002972233963f6be39c7aee60 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21010000000ae3668c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127048010000008de810588bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40d00000000fa4dd06f0403f6a000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870d92972e", "prevouts": ["96975b000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "3597120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cab1350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_6f", "final": true, "success": {"scriptSig": "", "witness": ["2c040c7778bcc65cda8395e7ae062e13853bcb5c861388366263d03fb307317c58e8b78d598290d629d0b6548b9661d177061b7e80254969222349ae5df948c182", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["9e5716207969a18ac4adbec99a101d03e1ba3a535a4364a8c32eaeac0eacc6d165d0a3f344bb31e5f81ea744d1d6c571a71687eb566b5820f8ea73fc2420b9ba6f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ad67e4cfbdacd913d6561d8fe08f456a4341a88b b/txscript/data/taproot-ref/ad67e4cfbdacd913d6561d8fe08f456a4341a88b new file mode 100644 index 0000000000..20cac90cf8 --- /dev/null +++ b/txscript/data/taproot-ref/ad67e4cfbdacd913d6561d8fe08f456a4341a88b @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2c010000006700468d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701b02000000de835db602815d6100000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6f3010000", "prevouts": ["61ec530000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "4ef50f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["de4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365d68cd89157a1768344d3693d5ddb5d4f8008c6471ee21a81a3a4b68d16bfcc31823ff0d5c6a769fa09e08a59a2485b611e1511239bba2f80aba2b92be945f1b811034f174cb7bd77652d345f06878a8d4eb3ae1b92590cd10e2563bf228d2d6bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361a24f92e0fd66692248020bc486fd34464c8d03dbe31b3b0085981632dac5adc23dda11617dc042479e1d576056805c31872018ddbd603e5e1ceb926e90a3395bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}}, diff --git a/txscript/data/taproot-ref/ad705acdd20e8da3a2171681cbf04df9fa98a3f7 b/txscript/data/taproot-ref/ad705acdd20e8da3a2171681cbf04df9fa98a3f7 new file mode 100644 index 0000000000..59454d2974 --- /dev/null +++ b/txscript/data/taproot-ref/ad705acdd20e8da3a2171681cbf04df9fa98a3f7 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42e00000000888dc23702e4e4350000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898796acf448", "prevouts": ["37be370000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["cd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936305e2bbfe940f420c214662e3966ca6ecb30394037d73a78f87c1b0a0c14e367fe052270a8089f5fc5ef9a63e8f4df43751c17d276a547e2cd275b71d0b6242a8fd238d2decf6f7142c55252dfef824eea080278838d8f4f1f0f617cfe47b5d91029910a453e765cd82c29c3b576a90579a453f3a941b6b6175fa922e9a13196"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93679da927ebea46a5f8996fbcb41ba1476306b8185e9784cfd3fab60be6d7447790aae41afa256ed506dae95e698e8dcc0fa26e2618e50e74a83d05bcf51ab890d620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}}, diff --git a/txscript/data/taproot-ref/ad8af6e7441c7a1e3628b69f1ca22b74068a2278 b/txscript/data/taproot-ref/ad8af6e7441c7a1e3628b69f1ca22b74068a2278 new file mode 100644 index 0000000000..536b51eee9 --- /dev/null +++ b/txscript/data/taproot-ref/ad8af6e7441c7a1e3628b69f1ca22b74068a2278 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce7000000003197a88edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cea01000000b341e2960409599100000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6e0000000", "prevouts": ["745348000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987", "f5084c000000000017a9146db815d9819f256ca5d1e70b15558a98689cc52e87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "483045022100dc4a0c1f7116c24b0267bae3735ef4ec04fe060b1f6d55e8cd232c392db401f80220028f4991338f75df258163fa70a9db009594955c8ef0a5c0a16b3649ac74e511914104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "47304402201c3ef58e787111c074aa64c7937924c0b1155bd0992253ea0bba254a2bfbb0ff022070aebb6d8f372d8c4b663071ea6afa00b43368c5f2ae9d18dc618f1479442644914104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/ad9cdf2ad4d35e3f1e5279c581d0394ae2aa6972 b/txscript/data/taproot-ref/ad9cdf2ad4d35e3f1e5279c581d0394ae2aa6972 new file mode 100644 index 0000000000..9db9034296 --- /dev/null +++ b/txscript/data/taproot-ref/ad9cdf2ad4d35e3f1e5279c581d0394ae2aa6972 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6601000000e283ae2e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46f0000000047eb5b7102ce5f95000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787a9020000", "prevouts": ["5f6c5f0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a", "3359380000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e7", "final": true, "success": {"scriptSig": "", "witness": ["1aa95253650cc6d00a356588dd7da7ad3c29b203f2fdcf5a6d4de877c86da7e9e8ac7bc37a62561e1aa29ebbac1f18727b3a450ed56b7a80b0b6d2d784941b6d81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["df05766cc097f87d57410e983792f6d30a26c2826ec54429c66c18e4f06c78c8e34cbb0bb7305a27314f3367022214517487177d0e352b55b2542bfb9f33225ae7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ada6178e8321efd51626a855bc6e5557d68ca3fa b/txscript/data/taproot-ref/ada6178e8321efd51626a855bc6e5557d68ca3fa new file mode 100644 index 0000000000..c777b7225b --- /dev/null +++ b/txscript/data/taproot-ref/ada6178e8321efd51626a855bc6e5557d68ca3fa @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfeb0000000068aa1af660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c0000000003ed329820294e97f00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48725bbbd2a", "prevouts": ["f0006f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "da2e1300000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_4f", "final": true, "success": {"scriptSig": "", "witness": ["51f2527e40f3c83d875e342791e5296256ff69e845f8b18d97625782c0af94569a38aeab1ce7071a24bb4016880bce1da4c5d26de354f211e2b35a9fa131d8f6", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["41b2d8cc2138842cedc7d45cb864c1005bbb1cb097d5eb3de46e6317324293e56cddd227fea706548bbf66400a2f7b32d0dd31f015fa97fc1951ec5410f313444f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/add98ecf3dbbc875a84ca24db0f18c054af38335 b/txscript/data/taproot-ref/add98ecf3dbbc875a84ca24db0f18c054af38335 new file mode 100644 index 0000000000..eaf588e8ec --- /dev/null +++ b/txscript/data/taproot-ref/add98ecf3dbbc875a84ca24db0f18c054af38335 @@ -0,0 +1 @@ +{"tx": "007958d602dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9e010000000160a5b4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2302000000b9f715cc01b1a3b900000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a5020000", "prevouts": ["8ce35f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "47386e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_11", "final": true, "success": {"scriptSig": "", "witness": ["3b5d6864aa8b433301841fc85ddbcf12ebb46b666238eb0b881222149f7d4dd5ecc0f416bb1e1abc3971ca0cd951af99ce876f5a95fab1dbaf84fe06464aced982"]}, "failure": {"scriptSig": "", "witness": ["5358641b54d1ac74d8e48e6e15852693d4ddb9e024818b3d2811c9f082f0a380f2bc49f761b727fd1e0450912cd5c0fe81f243c703f85f401c2d458686f60a7511"]}}, diff --git a/txscript/data/taproot-ref/ade2c248d7512985cd0840191f643e986e49db2e b/txscript/data/taproot-ref/ade2c248d7512985cd0840191f643e986e49db2e new file mode 100644 index 0000000000..a2f39c073c --- /dev/null +++ b/txscript/data/taproot-ref/ade2c248d7512985cd0840191f643e986e49db2e @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa200000000fb3d70f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49f010000007d25f0a80274e4bc00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8783ce9f30", "prevouts": ["3ff27c000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679", "638142000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082380f015d033fe7faead4766c682a770029d5c79030785f2d26c440da4ef071fea3aa70c847d82166fa4c32b27cb78dba1a5c77b2d4b8269442df723c9129fb762c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367abd407fa50d9a42f4099c8eac0d1d23fd0b10ba46053f4def08af2f64e6c099e0a7be32fdcca7a506e9ce249f658cc089bc7a3d23614d55e872a83e7956fea4416efa3a61de7db58e4e5b27e55eab88df01883130071a88e8c07ccbf4e37c61"]}}, diff --git a/txscript/data/taproot-ref/aded7ddfdd7ffa25f49bad4502033ca4a8591786 b/txscript/data/taproot-ref/aded7ddfdd7ffa25f49bad4502033ca4a8591786 new file mode 100644 index 0000000000..5802a78b65 --- /dev/null +++ b/txscript/data/taproot-ref/aded7ddfdd7ffa25f49bad4502033ca4a8591786 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40e00000000fb7b46b8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb201000000c6e24f480102291f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1932c947", "prevouts": ["d42f3f000000000017a914a2a8d85df2f20a0aaff7224012fc4cee13e29cb987", "219e2000000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "b47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd7e736a60655dc533a38837433a3a305c9a2d5b0314030c91796018120c3e9a44"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fad5b4f8de6a475e1475ecf0ed158bd12476ce010b28dce6527e02a32226fe48562e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd7e736a60655dc533a38837433a3a305c9a2d5b0314030c91796018120c3e9a44"]}}, diff --git a/txscript/data/taproot-ref/adf617416382c5deb595144ff94dce09117c3181 b/txscript/data/taproot-ref/adf617416382c5deb595144ff94dce09117c3181 new file mode 100644 index 0000000000..099795dee0 --- /dev/null +++ b/txscript/data/taproot-ref/adf617416382c5deb595144ff94dce09117c3181 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c60000000077e8b85d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e6000000009e49a865016e35600000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb9000000", "prevouts": ["2580370000000000235e212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "0ca03a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_8b", "final": true, "success": {"scriptSig": "", "witness": ["cf64ee3a79e442811f63b0ffe23daef785a9ecdb87cf959732eb729e831c4655faa61e8523d42834c141936cd0335f189bfea17fe510969612697f84875633a5"]}, "failure": {"scriptSig": "", "witness": ["8a0d36835b26f9d683f3d9c19b3d4eeab7dd4d637e2a3638c71f10745d71bcd3e2f5ff33ee2e9b226970d0d07930cf49ca4aaedcfd90816e50fe0af79389e3168a"]}}, diff --git a/txscript/data/taproot-ref/adfe9ae4df4e249a66eb91fd2f8b26ee063e6f76 b/txscript/data/taproot-ref/adfe9ae4df4e249a66eb91fd2f8b26ee063e6f76 new file mode 100644 index 0000000000..c34c764670 --- /dev/null +++ b/txscript/data/taproot-ref/adfe9ae4df4e249a66eb91fd2f8b26ee063e6f76 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c00100000051c121fa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703b00000000d8839a9a038a522100000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874c59263f", "prevouts": ["e94a12000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "eafe1000000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "3b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a1daf2fbdc5eba8a219f1f8635fe45cf0e30925345452464a53096773d109ba7ef84fce916674b46359d0327d7b56c183d26d6053da1b16053a1f90da8a1d4e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369517bd2ec6e222f593b12487f5a7b1eaee696b6e0fbcce419bd0b390383a361246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fafc7fa9328de6285e10958c6b3d6f5d3c073b4c582e31cb42904dcf82d4bed78a29f15cefa9911251712bcf83078e1db490f7db40c14a26e0e577f39f7cfaf11f"]}}, diff --git a/txscript/data/taproot-ref/ae32aa63248b35fca6503c67fb4fd2acf15a98ad b/txscript/data/taproot-ref/ae32aa63248b35fca6503c67fb4fd2acf15a98ad new file mode 100644 index 0000000000..4b8b291a89 --- /dev/null +++ b/txscript/data/taproot-ref/ae32aa63248b35fca6503c67fb4fd2acf15a98ad @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc400000000722b13ffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1101000000ea73819702fc8940000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f872fbbd44a", "prevouts": ["04a720000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "b70022000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090255a68059051d49dc036a91ceae241a396273c034f022db6a818141bf265dc30c5201cb46753304681691b9649f09da7741a7b64c377e606fb3856414454f237ecadadac897ba1fc4b311aa512b072fe017e284a2890e2496dac58d38f87105bdefc99d683fb855f817d799b305d9b16884b20d0d38dd1ad8ed26f885533b19a0fc60a17da9a28bee8ec2836d2ef863fce90fc5e892dbb95d9e75ebe39de2568b6aa42c26140a779198ecca7bea5cbe76f87ff0d508e6b81e7c21cbf275526ae9a1d2036d1e3ec75ceb5874c5c2566d614224d944ffe7fe9ed70e9ab34c04f186861021e4d43f2010e0bf7865491c460cf014dbb672dbd60984f30bd7441f48eb5c9a14dde7c48925034fe695622ffe1939929c06357f1d9543b449f2624258c4c7356d987120e3e2bd149a41000202e6c96eb12be79e085762ffff999a96a03609e6387abddca33e4699f3470ed89d55a68c3be9690f50ff10d119b316d81163d2c0aa6151c66e1571e3934fc44257e996f4aed98683f43efadf64d039c8a0ba36ed3feeb6ac2ca131c344aa4faef408e4133cacc2101c354e17fc6c90fdde4122aefc8b4db4906ba621cfda6c80dc9bb27978127e0ee088522436cbf1cfb0e53e161dbc0360e60d20047ec17ebdf1b2e2098e08f9d57c0d35c434647fafaf33be22884bd403059003e627e72e9942afb2cd0a76f5d4a245fbd46c8f7da8ccb52465774f7635bd211275fd", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6f6cfa678e6eb5d7c16d1e165dff8cc02eb6f9167a730e645b4ae310f8d0f8feaef31cbfe48887fad20fb93d6cf3134c2cce06fe301c1f80fb34276495816473effc93d9a59775ec6af4eadc6f66e855123af6e736654ec63572366f38b17272c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}, "failure": {"scriptSig": "", "witness": ["4d0902320bd827e6f25766fbb1643379276937e6ba22a5479e7f7ee5a2a62c12daf809326a5c1cd95a8377784ca82184e72ca5d80324d673d8cd14d377f3731a59b5120fe4f94c096eef8a217cbc9491a47d0e16db08b50326954b1c47fd6cad8db16547c520d10be8850430302a25b54aca05b69d86f1012258a7357d541d0ac3b7f14ae5e7aa4cff2ee59abe7308a166d54692f84e78fa4e735a054a570410c2f7517444008bf5581761801bd93fc3a32c00d2087792f0bced0098fe0505549310bb449450f45f500b3f7601c118ccc3864fdb35ee06004ac141019fd21a21a4c2db18be26840e267f066016cff913a31931240896195d0e1662a0f0f335c8e864cdc97c2f4bb18eab43888c4935b89def484de71b370e8644c2d290698e8071656b88f6ad173268780c6eed6d034c055c2c772e5260bd44693f98cbe8b182b915c1dd50ef469637b5293f73c696aa0edf86c62729f158e32304a27ed0af0317e2d88135f44fd8292b45f12285a76e040574efffb387b75f7466ee3f98a066b0249c0b4db882b5dd8956400ee89656c363b8b0f116b94d80576711c3d8134f6475f3511a1d7bfae37b31fc3a22412ed184c2d85d6241e2f0a97e6ef8b04bc81f028a06f4128db6fc57397ccf2ea40b32ba1593b52e4121986cbf415d9e98e6537bf876bf78a516ffbfb04e739cfb3c04c1e021240d62fae3e9f4c14bb9e4c798d105394d8e6bbebb82b00d7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93639d1288aac8e3de47a92a81d83162e567702fa83ce81d1d7859f59a963fb0a5beaef31cbfe48887fad20fb93d6cf3134c2cce06fe301c1f80fb34276495816473effc93d9a59775ec6af4eadc6f66e855123af6e736654ec63572366f38b17272c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}}, diff --git a/txscript/data/taproot-ref/ae87ecd86f7053ab8d71a8f1fc84c2d2c62b472b b/txscript/data/taproot-ref/ae87ecd86f7053ab8d71a8f1fc84c2d2c62b472b new file mode 100644 index 0000000000..e7f9f6050b --- /dev/null +++ b/txscript/data/taproot-ref/ae87ecd86f7053ab8d71a8f1fc84c2d2c62b472b @@ -0,0 +1 @@ +{"tx": "ddd1479b0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702c010000000c199496bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfca01000000ce7dd895015e5252000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67e020000", "prevouts": ["67df110000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "ce3d7e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ad", "final": true, "success": {"scriptSig": "", "witness": ["052a73ca708259b3bb65de74ce0515e7e734dfd1339562a3812ccecdeeb095a984282b16d81ff7add38ab390de4607eb3034eb9ab6f4d70b93289b972533a91601", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0f8931209156bc3f0ee8b5ac577dcfe8d80b7ec008817e6ecd5de0b6e3e36efc5095c83f795e94962897556aab4651fbc5b68067ff269dda82d8345b8cb8545dad", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ae887143b966f102e6e5967f76ea3c041af92e65 b/txscript/data/taproot-ref/ae887143b966f102e6e5967f76ea3c041af92e65 new file mode 100644 index 0000000000..0c49465ffd --- /dev/null +++ b/txscript/data/taproot-ref/ae887143b966f102e6e5967f76ea3c041af92e65 @@ -0,0 +1 @@ +{"tx": "7c5fc7c8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cd0100000043a3c7eedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0f00000000209d439903a82a8c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e763020000", "prevouts": ["4cba380000000000165c142540f27e90740933c99d4f17ab2dfc6c82951cfb", "d2fc540000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "6b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8a2960a95becb1bbbe0636e0493c58f712af9b8da417013d797bf12c130ac56070886d9e3726a9aa8a2b94454683b5181a970edd894e0d0cd75aad09f75436b2"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e85c9148ab8fb2f0e3b60c30486bc2998c5a9fcff153a4260746061263c245b36a70886d9e3726a9aa8a2b94454683b5181a970edd894e0d0cd75aad09f75436b2"]}}, diff --git a/txscript/data/taproot-ref/aea2776fad1a4341ceaff3aa6cf21d9c37587a96 b/txscript/data/taproot-ref/aea2776fad1a4341ceaff3aa6cf21d9c37587a96 new file mode 100644 index 0000000000..1536bb4084 --- /dev/null +++ b/txscript/data/taproot-ref/aea2776fad1a4341ceaff3aa6cf21d9c37587a96 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6400000000d6c56a950144091e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf3010000", "prevouts": ["53272400000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "", "witness": ["3045022100e9e465b25b90ec4eae268ef097fb812ce90072ac31c7776933d00f87ccc3f12902206810ed43604b92f161ddee0e83dbbe0e744a39104b412b51700cf83ee01df40e81", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["3045022100d9a904875514a7aa3e65f5a9d3352506fb833af39f699af134638e442793aaa30220507ca95fdf22ed259e4735b46cc6aee4cd83fe6b3edc21e565430d2b47ea4a8d81", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/aeabf0753dee7e4de87a4ffe6e1414931333b32a b/txscript/data/taproot-ref/aeabf0753dee7e4de87a4ffe6e1414931333b32a new file mode 100644 index 0000000000..c6d1d3e6a4 --- /dev/null +++ b/txscript/data/taproot-ref/aeabf0753dee7e4de87a4ffe6e1414931333b32a @@ -0,0 +1 @@ +{"tx": "8bbbb434028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f7010000001a4f028560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a5010000007c0d8cd903a9a243000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc79e010000", "prevouts": ["bcb73500000000002251201aac33169e9e7c3154d6a008d33b220a63d8a9ebf4646c8ee915f75ae7529b5f", "7f111000000000002254202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_1", "success": {"scriptSig": "", "witness": ["d2f9ec4434fc2ac4979f7c04e488493ee4ea63447b7ef13a368a98518994a09256a7f90bdda1dffcf99431017cbd3b64005e647ca38c1a5f20c2829a59ff0b8d", "9dea30801666942bc30596a757b6eee144dfd44d4c2fa2b4471d057e67f6cfe38909b4b9c2bc868c14ace2c9b5be461ec6ade41dee10002b767c43ddb633baffdfdf4a3b6df3d8069cc2a57155a738abe04e94623cdac78fb96cf500bf09aa551e7906323cba85c438510d0049f947176fb882854178c62fa905bff7a383111004eca216edc79741f93dbd6ec96799cf1282960d7798bd20376ae8ab15ad3609171f0170f27e527d494ddaf368d75e37f0dfe153be1c3d7fe30e4079f5507694ea5900acfefaf1aa478cdfd5", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c7bac8717a1f08a6b77c9fbb718269890891be6758928f5cb3459153ae0de08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000830922897e89e68c07e04de6d130a27a5a951f6b1aea2d24f385224743fe4c81ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff694a2fed14c09c6754383f2742dfe418030d1e2c2b2d9cadf387b2a0b16a674cbfc87899f716171e154af0bccbf57f58c200423513fd20280e4271c015ce23d2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0764280133642a0ed4b654cc75dfadf1e378ce8acdcbe1f4a0f7a47f7d20191c0efc8634b965b6826569b65bbffd03219f5c4d8456855a0953aedfad181fda86acd927010d9a5ae3a537588717dfae67083c7634f11bb0d744d4721be4cb0020ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffded0dcf006e86da3002739810e9ad712096942420be48d9757cd65133947cc3bcd0d4f9505d2e403cffef6a6039352eddbf9a714198b1bfa01d247685e1772482d1417f69a2838888e3a6dd70ac5912ee50ff90eb582cda45050b26021e94bfc0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fcdf3e831ff2a692396b71aeceaa5752edf7d64553043662bdb2d035fb6f12effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a1ef1c2c5ab25bc5f00c54aa521540a4bc5a22373dd3145d69f7b626b451135f26739ad8b291a182ebf937d453bffaf5086c66dbd78a4243f5b0af19440d010062781e17adece575d184c126c5da260c183814a1f67c6a33283d2fba36defc93cc2de204cb8a81ef1684806085128d0ce219fdc369074a7dc46fbdda93dab33200000000000000000000000000000000000000000000000000000000000000003a87f62c494f2a95168b096362df7318617c6cb887ad731b45580133eed928454594baebe8131bde06413f226e83bb09c3151fda212ed80d12bee7005552e1a1217f6beed3ebf104cc984d6e6da46579dd5abd1429d4d2f47aca227449caeb7efbd6af6b3c830949083609f210edf4ec0010a880f769894781ee19f6adb76794e00f658893eedf5989891add29f45acfe46abab84de632ecce600a81f7679979ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa85a8a68199b26ce7c96d456241b7d90151eb88ab81514a583104294333511af701c01f1e0d14775ed14889ed08edd4ff91ff3f0e0fdbf97d8de74ccce18be1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045fb260a6bc61047b69ef16e0cc4bb8ee88d9aeae61c1a066039634dea89385dc54d401b29ad7fdac3595fec3fd4df95bed63a5a08c9d98d8e153add63b22a2a0000000000000000000000000000000000000000000000000000000000000000b235ad0219ada7c0df38535235f11fa8135fa1542de32c2085f2897fdf4955ceffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff68725897865e09ad9e12163864a1fdc5a83a32b6c064f95c1c8a9a36a897f7db75cc6f29cf10b949d2cc7cb57622633bc213ea5e692ce3d44657d8c5c707c5ba31b43609c459b7b7901f80f51492bc95378fb3f51f4333f40890d02bf8835b8292c971f13f0e411919275c65512e9c41d69d3146f117cac27a17ca58231b69b30524b4ded2a7a7bb414a6358cf90604f43cd149d2ee54f056f74e93731c4e526e4344c442186c15590dab0b903a653a642f61d736b49f9482ec326949b95d911000000000000000000000000000000000000000000000000000000000000000095710be98c313fc8abfe4dbe5e065e2e4c224318d84f1d0db7c7c3096588aeff9ff0b86d8a356851e3ee9cb426803a2b8ba4eed715f6804f35175197f9887261a569e2ef4d3895e1a175463355399ec2cd499b34c4977fccb1eb2faa5ac1effc61847e55807b96fe13424e8c3436e556c18ec0bff5018646dd1187dc4baf8afa39e6897e52e177ccd3cda3515910c5a85e4cf5360d6a6a91df37cd69e6c474f1057f7a6dff52f81da94d713d78d8e2a7302de7af2a79eaf7dea0841eb2eb46f431791a44b0a9f0111d1748d1b61a8e0359989ee9d0ff21d3b86129d7211f658c51446878c7085bf068c96163382f5d1e38130a4cf5390fe250df3257ed33f6a073f59ee9a2f14d32e113351088b0fe1afe58ad0c33793836685ef598c5b421780fe98e94eaa9bd32f02ad5d46c507f9d47d4e5df03244f5162f84934b75e6cd8f6525ca88eb66d3294a6b8d93267d4765ffb34ae1aeaa56683eca4eed616eefd625e750326639c16c7742950cea1f7d372481df0a88a1bbe8b8f0514d20d379fcf0c142b16cc6ab3cd60840e65406333199e12f456259f1390a1a79e87cf247fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff828e7d646be89df0357092d4bd543bdd6a111a6b61aae0450bf922173932ba59b39c19407a62e4a2e22f818da2908bfd56a6f51ea96e1de5d81b178866d230f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}, "failure": {"scriptSig": "", "witness": ["d2f9ec4434fc2ac4979f7c04e488493ee4ea63447b7ef13a368a98518994a09256a7f90bdda1dffcf99431017cbd3b64005e647ca38c1a5f20c2829a59ff0b8d", "272f7a1f236902cd20ad291a7a6a076cc603fd2200d9162b36bee2ec618f823f4bb6fb0dc87fa61339e1e22da3d3d8a2868e0a921807fa3564fb3b003046fa3484ee876a0bbecfa359eadcb1918946604807c53f7581fa1b1736b47270219e1eb26d9cb6dc959825c7684c1572bdb596188e93ce617d02d8a846632712da739246328c451c10d22ace4202a544f85846a75e316f3002620f3e92971db914f251ad86cf5a3fcff9d6961025bdbc4a744d816d28f5ce2e6bb2222c2de6ad04d9343b0ad67b7c7775dd3b7eb4", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2000636ead686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead527cba5387", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c7bac8717a1f08a6b77c9fbb718269890891be6758928f5cb3459153ae0de08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000830922897e89e68c07e04de6d130a27a5a951f6b1aea2d24f385224743fe4c81ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff694a2fed14c09c6754383f2742dfe418030d1e2c2b2d9cadf387b2a0b16a674cbfc87899f716171e154af0bccbf57f58c200423513fd20280e4271c015ce23d2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0764280133642a0ed4b654cc75dfadf1e378ce8acdcbe1f4a0f7a47f7d20191c0efc8634b965b6826569b65bbffd03219f5c4d8456855a0953aedfad181fda86acd927010d9a5ae3a537588717dfae67083c7634f11bb0d744d4721be4cb0020ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffded0dcf006e86da3002739810e9ad712096942420be48d9757cd65133947cc3bcd0d4f9505d2e403cffef6a6039352eddbf9a714198b1bfa01d247685e1772482d1417f69a2838888e3a6dd70ac5912ee50ff90eb582cda45050b26021e94bfc0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fcdf3e831ff2a692396b71aeceaa5752edf7d64553043662bdb2d035fb6f12effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a1ef1c2c5ab25bc5f00c54aa521540a4bc5a22373dd3145d69f7b626b451135f26739ad8b291a182ebf937d453bffaf5086c66dbd78a4243f5b0af19440d010062781e17adece575d184c126c5da260c183814a1f67c6a33283d2fba36defc93cc2de204cb8a81ef1684806085128d0ce219fdc369074a7dc46fbdda93dab33200000000000000000000000000000000000000000000000000000000000000003a87f62c494f2a95168b096362df7318617c6cb887ad731b45580133eed928454594baebe8131bde06413f226e83bb09c3151fda212ed80d12bee7005552e1a1217f6beed3ebf104cc984d6e6da46579dd5abd1429d4d2f47aca227449caeb7efbd6af6b3c830949083609f210edf4ec0010a880f769894781ee19f6adb76794e00f658893eedf5989891add29f45acfe46abab84de632ecce600a81f7679979ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa85a8a68199b26ce7c96d456241b7d90151eb88ab81514a583104294333511af701c01f1e0d14775ed14889ed08edd4ff91ff3f0e0fdbf97d8de74ccce18be1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045fb260a6bc61047b69ef16e0cc4bb8ee88d9aeae61c1a066039634dea89385dc54d401b29ad7fdac3595fec3fd4df95bed63a5a08c9d98d8e153add63b22a2a0000000000000000000000000000000000000000000000000000000000000000b235ad0219ada7c0df38535235f11fa8135fa1542de32c2085f2897fdf4955ceffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff68725897865e09ad9e12163864a1fdc5a83a32b6c064f95c1c8a9a36a897f7db75cc6f29cf10b949d2cc7cb57622633bc213ea5e692ce3d44657d8c5c707c5ba31b43609c459b7b7901f80f51492bc95378fb3f51f4333f40890d02bf8835b8292c971f13f0e411919275c65512e9c41d69d3146f117cac27a17ca58231b69b30524b4ded2a7a7bb414a6358cf90604f43cd149d2ee54f056f74e93731c4e526e4344c442186c15590dab0b903a653a642f61d736b49f9482ec326949b95d911000000000000000000000000000000000000000000000000000000000000000095710be98c313fc8abfe4dbe5e065e2e4c224318d84f1d0db7c7c3096588aeff9ff0b86d8a356851e3ee9cb426803a2b8ba4eed715f6804f35175197f9887261a569e2ef4d3895e1a175463355399ec2cd499b34c4977fccb1eb2faa5ac1effc61847e55807b96fe13424e8c3436e556c18ec0bff5018646dd1187dc4baf8afa39e6897e52e177ccd3cda3515910c5a85e4cf5360d6a6a91df37cd69e6c474f1057f7a6dff52f81da94d713d78d8e2a7302de7af2a79eaf7dea0841eb2eb46f431791a44b0a9f0111d1748d1b61a8e0359989ee9d0ff21d3b86129d7211f658c51446878c7085bf068c96163382f5d1e38130a4cf5390fe250df3257ed33f6a073f59ee9a2f14d32e113351088b0fe1afe58ad0c33793836685ef598c5b421780fe98e94eaa9bd32f02ad5d46c507f9d47d4e5df03244f5162f84934b75e6cd8f6525ca88eb66d3294a6b8d93267d4765ffb34ae1aeaa56683eca4eed616eefd625e750326639c16c7742950cea1f7d372481df0a88a1bbe8b8f0514d20d379fcf0c142b16cc6ab3cd60840e65406333199e12f456259f1390a1a79e87cf247fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff828e7d646be89df0357092d4bd543bdd6a111a6b61aae0450bf922173932ba59b39c19407a62e4a2e22f818da2908bfd56a6f51ea96e1de5d81b178866d230f2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}}, diff --git a/txscript/data/taproot-ref/aeaf78544ff09661df34acf0ab140ca8f6834d93 b/txscript/data/taproot-ref/aeaf78544ff09661df34acf0ab140ca8f6834d93 new file mode 100644 index 0000000000..072875a4cd --- /dev/null +++ b/txscript/data/taproot-ref/aeaf78544ff09661df34acf0ab140ca8f6834d93 @@ -0,0 +1 @@ +{"tx": "ec16b2e503bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf71010000001e2984c9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cff01000000d37921d6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9d010000006e9e6c8f0155bb16000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8796000000", "prevouts": ["55bd6700000000002251201b1a5025b4fe9992b0e02773e7f35e6be2fc0ec95e56c0e62f01a84c1b9caac2", "4966600000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2317250000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367bcfe338274b1b9eb3713335acbbd071cce1617cc6f1391b8f2a52678a8c2e0a"]}, "failure": {"scriptSig": "", "witness": ["6ab2616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/aeb2510aa3d77a9c6dcf533982e3925d74a03591 b/txscript/data/taproot-ref/aeb2510aa3d77a9c6dcf533982e3925d74a03591 new file mode 100644 index 0000000000..8eff19ac59 --- /dev/null +++ b/txscript/data/taproot-ref/aeb2510aa3d77a9c6dcf533982e3925d74a03591 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d200000000e2e3d8f2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc5010000003f7b88ba0234cb5c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3c020000", "prevouts": ["62951000000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327", "bbf54e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "447d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8288d1d486ad1cd5e981ede7314b9e0cd98a009052c160e03e008903fffd682c3fa4004b2cd3f2b5519985ef4ce40029d6249627881f39179d9882ffc68f5bb6a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08208f12ff2db60e07951e3ece83f8d4c41d9b16f9cd93bc43e76ab3ca16313aee1430173849036d038bb15ccd29e38ea974083458e0cf50b14971883c73e09395afa4004b2cd3f2b5519985ef4ce40029d6249627881f39179d9882ffc68f5bb6a"]}}, diff --git a/txscript/data/taproot-ref/af3246dfb5ebe1bed3d537e239a99af7422239e7 b/txscript/data/taproot-ref/af3246dfb5ebe1bed3d537e239a99af7422239e7 new file mode 100644 index 0000000000..127ab7fdc5 --- /dev/null +++ b/txscript/data/taproot-ref/af3246dfb5ebe1bed3d537e239a99af7422239e7 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5c0100000075641680bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8a0000000017e471b5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf300000000ac1340c303f3d21d01000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79694c84f5d", "prevouts": ["ad2d7f0000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "7d0e7e0000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6", "9da622000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "eb7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7d98603ca11f2d62da2f097293e2a9fc40838a31eb24ff9d7fe998ee66e0434e58e476735d98d5a1185fd7ff42bb7b31cec58182079010d151d415fc7d6c3e4c2ce937a5de573933a673baa3adefc0607b7a8b345eb0a9388ff089ef522bdd2"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fec5402c57463b820a037283baf958dfe8fa8ff5b14330867ba864fa7bbb305c3f13c9f2c0ba7c3724f3080ca99cfd230291165bf004db5bbadb2403d0b759af84ce21fa65bd655e7fa8dd3695f51b098b96b5173f87464f2936878bf520f49fc2ce937a5de573933a673baa3adefc0607b7a8b345eb0a9388ff089ef522bdd2"]}}, diff --git a/txscript/data/taproot-ref/af39e152ec29cf6ef9124bc09c621887cea05402 b/txscript/data/taproot-ref/af39e152ec29cf6ef9124bc09c621887cea05402 new file mode 100644 index 0000000000..f532828321 --- /dev/null +++ b/txscript/data/taproot-ref/af39e152ec29cf6ef9124bc09c621887cea05402 @@ -0,0 +1 @@ +{"tx": "deb4eb260260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708801000000b89731f8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b360100000085b672c00156510a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a698744740", "prevouts": ["80ad12000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "eebf20000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "3b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93614dfe64472aec633187704e5e239fcd5c5090a7796420cc2de2328e6e5d0b2fdee7dbe7f66d64a980d12157b84c42445cf47ca482a00d5396c717810eb35e86629f15cefa9911251712bcf83078e1db490f7db40c14a26e0e577f39f7cfaf11f"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936617393d62275fdee443a8234280e41d5e175967af62b17afa1af3cdfa9c72adfd450a1526d7659d1d0ab8a304ec78556741ee62c830e21f1e920b63ff49823b3524213bc04a867e2e908d02e9cd05b1befa37bc2f591ad783cb0f6fd2a1a72397ef84fce916674b46359d0327d7b56c183d26d6053da1b16053a1f90da8a1d4e"]}}, diff --git a/txscript/data/taproot-ref/af4d15714a467c338537aaa00108e2bee33e8426 b/txscript/data/taproot-ref/af4d15714a467c338537aaa00108e2bee33e8426 new file mode 100644 index 0000000000..4c8cbad9c9 --- /dev/null +++ b/txscript/data/taproot-ref/af4d15714a467c338537aaa00108e2bee33e8426 @@ -0,0 +1 @@ +{"tx": "4fe15df402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c790100000077a4d0f7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1801000000465f338e022e7dac00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac43000000", "prevouts": ["f92b510000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "5e795d00000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["854c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a8a30cc5f8be195df182d3a0e5016923565d012c99df51a6809fe7dcf26e6445717b4e30a5884e3e55754911c167a338fe4fe766d1d9ad9fb23fde5d0da8b2aeb2a240b376911c9876b3695f79f395ec3f2d97b1695e5c0e7f397f1ed982e79a1b6e729898dfeeff93e2067a7d076aa1bb7914d367b163cafe54fabf88cb14d8"]}, "failure": {"scriptSig": "", "witness": ["4c5285", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936991387851c8cb36895aad31d9483f47fea8c6c064a0164a0cd6e51381ab611551ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045952384bfcd198c969b60204543b8b578741ae3068409132e955e5c7af181f3d3734b3a7050eee065844830ad8d45a710891f78004f5e7f35b8fd72bf3ee94449"]}}, diff --git a/txscript/data/taproot-ref/af58cb52355f4201682a37056445b679070634b3 b/txscript/data/taproot-ref/af58cb52355f4201682a37056445b679070634b3 new file mode 100644 index 0000000000..dd09db0ef2 --- /dev/null +++ b/txscript/data/taproot-ref/af58cb52355f4201682a37056445b679070634b3 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2e0000000021998959dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd701000000289af2e28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49001000000cc78bb2b01117a7000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acc484a04d", "prevouts": ["5bd120000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "0a98200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b4ba39000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_bd", "final": true, "success": {"scriptSig": "", "witness": ["cbf23365cb8880b133d27b3d20c3cccc29fe770e97aafa1521ac972d4c2cb1b607d19e1ad6bc0c00cb86e327fbe7b7eb490bb73be336576ab7c4285b92b7ec0a82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a7f8ce60fca0759d86bd881fbfeac239709c0fc464072faec998076586f156bd383ca59126ba719524d83634bac11d8d770490bbb92df2577ed827ba954861bfbd", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/af5fe2e1f2c809eb47dbe26c8a45e6a55718cce6 b/txscript/data/taproot-ref/af5fe2e1f2c809eb47dbe26c8a45e6a55718cce6 new file mode 100644 index 0000000000..9b93abf83b --- /dev/null +++ b/txscript/data/taproot-ref/af5fe2e1f2c809eb47dbe26c8a45e6a55718cce6 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e000000009ccca0ec8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44301000000298165898bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e700000000f154399c02849c8e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966d030000", "prevouts": ["a9371f000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "49f43300000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85", "fb803d00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "97", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369753cb1a5a2e209ace27a7eb8605f5f7017a5ce229afe5de89ccd0b48219a4f45a7303e26d6b86d2a780c30dbeb7ba87c6a0494b901c3875fb9ca7f2f12bb2fd373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362b9f3130479ebcff49fd970febd3f22cafd2118ccf82fa26a081c98b144e890c088456232115bcc24dec0b5a24cea45f7d15fc3427ff6cd91fcf5dc3f7efaf083288455e3867d2ff7594cc417650f42f79f93c98aaa5c5ef25eb3554c8bf2ec6282285524a15c732567d099967405d35f7136f74f48f011bc4ab279ad8d14f14"]}}, diff --git a/txscript/data/taproot-ref/af7648fbe02efa3d9188b9b61ce6422012612477 b/txscript/data/taproot-ref/af7648fbe02efa3d9188b9b61ce6422012612477 new file mode 100644 index 0000000000..68493b9e3f --- /dev/null +++ b/txscript/data/taproot-ref/af7648fbe02efa3d9188b9b61ce6422012612477 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc701000000c9ec5c9303ea284700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acfa60e623", "prevouts": ["70d2490000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_df", "final": true, "success": {"scriptSig": "", "witness": ["35dc529b40db63194d9535aec01fa52120529785c86f0de6ddcd00d518c37e6a2a250b192ac880acdf33caba9bc2faf5426d9f0edf9625043ec863f6a92437c902"]}, "failure": {"scriptSig": "", "witness": ["670b1bc7c74622e6f1bf0ab98abe803b48a381cb70eda81e44f36308e73cd7eabc17c358501e8bab93d976bc68da1bfdd6675e6bfa1b567ff6865d3fe2e655f8df"]}}, diff --git a/txscript/data/taproot-ref/afa5c3718b0a518cee419488c60f2f2741ba28ff b/txscript/data/taproot-ref/afa5c3718b0a518cee419488c60f2f2741ba28ff new file mode 100644 index 0000000000..e3c83fe697 --- /dev/null +++ b/txscript/data/taproot-ref/afa5c3718b0a518cee419488c60f2f2741ba28ff @@ -0,0 +1 @@ +{"tx": "73092d65038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46c000000004658eea8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa401000000a7b39fe5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c450100000060837bf002397b12010000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a60fdfb23c", "prevouts": ["afe43a0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "7ec5840000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee20550000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "697d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0827bbe6274b0dcd2777fc9b1075bd65318fdd52335751f1d5034a6ddc9c2a447578de3449b5e2c621283b68ab187cecafc7aa77a8721601b5317d3484f84536019"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b7af11fbeeafa2e26d6ced4a592e7faf61316ffa4728fe11920bc0a66ec98491cb7a7ab5fd71851d574a9c26887a3027e1173994a10fb9074a9680b95d402bf38dbbed29828226c3a1e74b431b518dca4e99f1ee054f76cd9b7bd5529b5cc8688de3449b5e2c621283b68ab187cecafc7aa77a8721601b5317d3484f84536019"]}}, diff --git a/txscript/data/taproot-ref/afb161887b4215368f593a2d8d8b6bc32170698d b/txscript/data/taproot-ref/afb161887b4215368f593a2d8d8b6bc32170698d new file mode 100644 index 0000000000..89e0d53357 --- /dev/null +++ b/txscript/data/taproot-ref/afb161887b4215368f593a2d8d8b6bc32170698d @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff0000000009808edabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba601000000851525c48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47701000000859dffb10302a2e2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374871878ff56", "prevouts": ["74b9810000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "6309280000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "0ace3b000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902e8e2a3911e1bff2fa3c4af1bc21243f6a834f260cf8a45deb24e4dcea3a99066e2307133f37cbbfe293ea141cadd9a4dd6438bc8da73ae0a01d8d901734469bed1bba87eb66086cf67e2aa9090726ff8a65d448a45ec5afde73e2b01c7a7d6fc0933d7cbcf0b39a6ceb0a67b693dcf784cd711b7bb15972b8a86470a75b9adf05308a078bdc3619b5ef299b0e4bd26b571dc77c8364f588f0b2489610ff0ee96b2a13a56eedae4f4d1490054746f610a2b419d1a6b49e53507e2ec7d3292e4d368b89f9cc2849592fe253c18a92385d93032157aa51d3305f0849bb3ab936076d03650b590b720851e18ecb026c399d835546cc9f4b4438d56d2cde0e08fb04a4815197b6175917310348930121ac7922edc1076068a6dec8186fbb9fb643b91589d4db8fbed751c5e1fc51faf53b606ed49d1556556ea55ae538e4de6881c59f693d8a4dc682a4ac513f7d1bb540334d075356b12b102ce9e6f69a3407fb34fda3ff05be62e0d753a00308b365906892b7b4b8c071b00ff331aee88c3ffc0e83e7c7d6d1eb522ff9258de018918c127a9704314652711d12773f6d9cd56907c0f1cbbe23d435e5ce1d1a68e141e91147d85c3f03eb7c13857033c2208fca3c666e00e1f639ce0707a2c392d54561f3f9bc926fc64fa1feff8324737870e45e912bd4e713dd23a47e7109abcc6eff986b24748ee27353e918b775a84ab599a9a4aa3220d3fbf77d91f75f3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d364ae2d506c0e3a74220f01cc1ba6cfccc161ccd59a1bbc3e0ce3e51240b4b1e8db2f81248ad9ed5128a6abc5bb92ba3aeb558dfcb95d0b55c9fe030b8e1ae1c9fc6c767d5aa72b6a61d813f4dedd67fc97d91e71acf86e276ab6f41d1da0fa8c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}, "failure": {"scriptSig": "", "witness": ["4d0902633fd27b06bc6bbd5d48e8427495c63be19e420b0fef59f0913ef0c5e5b601b1ff61677cd840af631165ff3bec87362c2d593b4144b5f8b45ca087d173f116b4b62310952f06a057d3154818a2ce6209a4afde69e73962ef6fd9fe6c0857be663eb4e8978d463b20f33f08c4238fd124f2261df2d644ac6bd8277ce3963c88c415140bd655841eb4be252a74158fc8c3f3ede1a5cd650dc5b9979700bf08ec0c481f5df6002b2b728a5db9bde5d5816d895d1ea5714e7ea8535cc09082f22d5b84ade610d0d60a1463221ee67cea6deae01775d13cfc1d3f77029578c89d34f1c6c2e9d25bdca41fd18dd6153bfaa55afc087bf9d436e3b7f4a9d8e15433b225bae863a53403f985a88ca2e22a0efb61fe741e8884e0bac9db99baa711eaf780a5efd3e0660442aea3bd8b9d34e860ee021a95a0b762fe2d739cae6456695c503c481ccec8f584c36547d96016a5b42c0c91ba1c469ef3d6d3ce349586daa13ea1dfe7f92f49e141f188896b8e6aa3b2383aec26206123651a28e301b6756b78b8a31047453f27a7e7e533510f919cade4ef6e4918c065ebf6e427c4389b00065e3cb6844657ac0b29ed017a7b2b2af12c3ef03668914de2ec0813283cab255b3dcfc171be041fa8009d2c91d4197d7d5942ca46b1f0657de6441693ac7300d7bab75eb526c0b686fa449614aeb23af4bf481897024eebfbe4b2b86b51c658d5137cd017770f6f90a87561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082c145688b3898d8a1374847539a36067c996b07f78d82debe95e7e288000a7bb1b9cd72275efe6b477d9cf0b54cc21959221ed58300fa90def59e56d53bf5ae178c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}}, diff --git a/txscript/data/taproot-ref/afb93dea86c318802ea31536847bc3786c8bb47c b/txscript/data/taproot-ref/afb93dea86c318802ea31536847bc3786c8bb47c new file mode 100644 index 0000000000..7f624d8f79 --- /dev/null +++ b/txscript/data/taproot-ref/afb93dea86c318802ea31536847bc3786c8bb47c @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9500000000d03e1c89bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd101000000992df1f804e162e200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac708d0a37", "prevouts": ["a310810000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba", "b1dc620000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a767488fe42262d771f95d10749b7596819dd0a85061a1366a23d9cec3529dbf37f8d6a4384f014fca2d3cdbb6112c7d6167187a43622fb7ab70c92b59ba97398cf3dcdb1aca371f721e0e3bf2b2651b51ce3ba34aca28f0f47f34a6674cf0fb6779b1e291bab0968202ad270cf91a37e8e31cb960dc611520cdaec411dbef0bb438b99b0a7baca4c5e023deb9dfa7f55f0d7c88254219d1d3c98dfe892bfc8f8324df57a3e5b194b205a3c7f8aa1cab1620a3fdc223fafd171ecb77cce8d929758597b5c0dedc9d4f406ea14d44e0aba6bacf906745e14634ba22c2d6adecc5adff9ab3378b04fd87f3178620c97c49e5a7d9a10dc4fbdec708826d17697df6c6ca981815440ad0e511f84ea6a59a12b1df196226cf591713eb0cabb7b00f4f1d4f40f607eb6a7c507e1ac6fa066076680ebb59ec4c99338001e72ef655f1f099e7a090b31e95872c696e526e62b2c5954af635d44740a1da0cd4652e3ab75129698ec2953d332e3b3e36aa9dec875973cab9f403c6645a5b24909c576b715ef36f0e0fb57360f5055aacb7d71a55cb29abe039a297828208198f2978d0590d3a38d01219c3899d2c539c990df2530622775473b7f0ba933b387801ddcdbbe9d392ed7df4f0289a986b6563976f98dab72bfd3d8d9759606cc298b7c4201a300f0fc18e6f9f98bd3fbedfaf70f77889e4921d85798eb8203cdbbca8ea0814f2f4db802ffaf752968775", "c87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366ecdbb67ef0066ec076e429fc04f46dda670ca9551cd024f28a867117fd70946da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e65775dfb1ab8912d99abba269b246de78dce1dfa6fdc8b38f44f7be80bcbeb76c308d8e78b0cea59e70bbcac5990a047bb63a968328232757672e5e931dda055"]}, "failure": {"scriptSig": "", "witness": ["4d090250fd27dab27acfa32f56d759b2189bb517126d1d58cdae68b0d3a6d7ebd46d0401a1e864699a0916fb10b127258ee5ad4577d7fc38f477e1eff0b6e61675f7b576d1249f26b5d5b50e72d298952ee6b9242e8657beb8d5a1ba10b864a1acd35f0ed833a3a500dc64df8bfe02c80109926344fa28e37118551fe5736ac39032695e7e2b97b02a1b857ca030c63c22870af71119aa9ad4a47fa96c61224c0de063824b48c7de543b5ba08ed42f6eb663781b0745ec17cce9ce5c9a63ea2d6508716db7ecbd1d857e70f7c5b734b6b60f8c017a415b107bb6cc4029a29eb85517ccfeb60e05ed10a1c589050b5ceaaaad33620ea9b3a58f5d8d163776c9a4082cbcd80db648d6ece66990f3a771a94d353c88312e76a045809364c60a73a3b90ddc68d7d04204139ff38be71298dd3331e4738ed805f3d9ed877897a169ad30b59bb834029c4dcd1913f2526755edbd6b4d23ad63e53dabcc96c3de8c0bdcd9a2f41da0e14058b9831d65964caf40a85f1ae005d1162eac570ef6b3f6e391b345accb4e4390e54b1212c44da9e5c3ba8c4905054e719326b653166bcc856588902aba38e792149b7bba8e1d9d23cc2b38d197178911f79ee7b8bc6c0c155e0e3f24b049ff779c8f960b2e36730757b3f9cb8a5c9392de83fcf56b5d845724f7d41486e3e0f92da3189c0f56d43cbb55b439af9dc8f06f18811849d40fa6914d4bc1e8ef06bef75c48e48875", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c0a8280b2b2a3355b689f18819ebbf93b19ad428a3d20831a21570336086a5905323990ac9ba96640afb66df99f25054f5788ad16157a03b33c6c26a70bd925e21136d3d9ecdf371b2101a7e86edb56e15b10ef185a8506988239bb2b5a4c43e"]}}, diff --git a/txscript/data/taproot-ref/afcc94478400491055613ccd42f75d4fa9c1ceab b/txscript/data/taproot-ref/afcc94478400491055613ccd42f75d4fa9c1ceab new file mode 100644 index 0000000000..a982f29e0e --- /dev/null +++ b/txscript/data/taproot-ref/afcc94478400491055613ccd42f75d4fa9c1ceab @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf500100000025b6048bdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf0010000009bc157c302da139300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d8000000", "prevouts": ["923e720000000000225120279eabb29e123e29b3e35f5f3a43ff6342d7d66d04195fa790bd9d720ea8f0a0", "4a6f230000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["83", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936777ff8a9412e94f7b77cdcac9df137438df90b973affcaf29cb29560429bcc3e8ed6c904d531fc0d19ced9482d4cbb64035dc55104164ba190923612d3f9e9a82b9d1447cbfb5d72d5da72ac5ad193469eaa6b44c038aa23e2a9d2dd480586adaf3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93683933d45c3442f615ee20a7137db960cea3b9cd87b48587a4de9c490e5a6c9c899aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb439b32d44b6ff86c799acdff23ced11a294722ef2b8af6951bf8429e3bda52b31af3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}}, diff --git a/txscript/data/taproot-ref/afea0adf1a155b6acd7f6a1aac9dcfd781f953f1 b/txscript/data/taproot-ref/afea0adf1a155b6acd7f6a1aac9dcfd781f953f1 new file mode 100644 index 0000000000..aa37ed8a1f --- /dev/null +++ b/txscript/data/taproot-ref/afea0adf1a155b6acd7f6a1aac9dcfd781f953f1 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1d00000000065a48888bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f300000000cb7a9eb304fff3a800000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac0c020000", "prevouts": ["f03a7100000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "75223a0000000000225120cf3d4a21d95f409285a815c665903ee1793a8187aefd3a8003cd262b63069349"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000089", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936918449c1f1d7e2aefbe78c65a77cf74e4228164403355e620ea48ba4f143fa01b90b3e537e0a498718b42d83f823725a04b39327b9237d74ba7af037a7c89be8bd8f71710e2f4773b226617f0b144a9d046788db13e8347a383f909c13421323cf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0825f4861bfb2a6452ac4a4804b2c6a2c641047e4f139d9501cd1bf471f8e5b3ea6913d98effacbdfffd2adbbf71932929e08e9cbcb7e06a345b8d84d9192524cd99d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}}, diff --git a/txscript/data/taproot-ref/b0225ebc20fa76a5b5efb83881756503681565fa b/txscript/data/taproot-ref/b0225ebc20fa76a5b5efb83881756503681565fa new file mode 100644 index 0000000000..207afaf20b --- /dev/null +++ b/txscript/data/taproot-ref/b0225ebc20fa76a5b5efb83881756503681565fa @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1701000000233e40828bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c407000000004acef7c7044c5ca200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72614dd3a", "prevouts": ["a8956b0000000000225a202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "ca23390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_52", "final": true, "success": {"scriptSig": "", "witness": ["02938847ff632f0f0c15c9da24e9f4861811b6531ee8af7c9e02f39ad63ef28c10cad94e45d7e63ada960257dac7134e318c5fc4e3631d9ac5cab2fd1104c8a4", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["73932d62aa9804ec33dce96cc8d8cd7584c04c5a33c2622c295f30a583122cf80cf93ba581f052ef81a337da361eb6b1c1de6e1cfc8da709e8c30d9851609ee552", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b02921b398ef06202f6f3b3f652c3c8f10888607 b/txscript/data/taproot-ref/b02921b398ef06202f6f3b3f652c3c8f10888607 new file mode 100644 index 0000000000..4f1f905678 --- /dev/null +++ b/txscript/data/taproot-ref/b02921b398ef06202f6f3b3f652c3c8f10888607 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c409000000009364ac4260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ac01000000ed34be6e039fbf50000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709310e52", "prevouts": ["e41f420000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f4301000000000002251205fbb8ac28e580fb39d87ab9ecacdc52316773607abc8ac10a5707b0a5a311000"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_35", "final": true, "success": {"scriptSig": "", "witness": ["4489f55740956045636f25efa0cbe6e85b2c8ee4d441897964459e3cd03f05acb364cf48b8ada980762c69be6321049428d0df54f118b99f1b835aafb9af4b3402", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ec20d8ad8daa4cc44419b71add25a720ba43571d629c871e26a246cf9b160e5f6a0fc2fa687cea0778b0a1ac915f06cba52040d8eb94ea040e0029b3af0e266335", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b068dde987664207f704c5b73a6444bd16d46da8 b/txscript/data/taproot-ref/b068dde987664207f704c5b73a6444bd16d46da8 new file mode 100644 index 0000000000..cf56f72a5f --- /dev/null +++ b/txscript/data/taproot-ref/b068dde987664207f704c5b73a6444bd16d46da8 @@ -0,0 +1 @@ +{"tx": "1a1da20f038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c496010000003477079360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127029010000000b0db5c160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700e010000000bfac8b303bf195b000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487198ac73f", "prevouts": ["ed513c00000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "fd2d11000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9", "5ac90f000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "b67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93602d7bf344b6095ff9cc0433017c53b008386fb3f597f891117b70dc62f0c39c7781c07d8975c94d77b7f566737b45f640ec74b2b98cad100fb0cff19b6594ed691244d1d955381053a5c36db6928ef13bb9242569ee84b58d7018329936aac78"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e848df663f65f0e27b2d1567423d7462b229bee90dcacba8c1bf1c1a66aca7f6821d9a3f11774810afeba87c9188100d693899e640a37210c96e3be6a00ac01d4"]}}, diff --git a/txscript/data/taproot-ref/b06a48e5c2bc5a6b1fc1fec7273e5642a15c8c13 b/txscript/data/taproot-ref/b06a48e5c2bc5a6b1fc1fec7273e5642a15c8c13 new file mode 100644 index 0000000000..5f5a2e0659 --- /dev/null +++ b/txscript/data/taproot-ref/b06a48e5c2bc5a6b1fc1fec7273e5642a15c8c13 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf070000000062aabd978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f10000000022d1bc9003560c960000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb3c81660", "prevouts": ["78b26200000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "1625360000000000235d212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090225807767cddd3374bea047dc917aa65ddde9500a4f784a5475f11dc4d628a2f955e9d72912892e9623eb0f203ab77e10032e634036cf2003ace8b6842bb6197de20edaa6aade498a89585d703af8e07290591314d078fc0843ae351874d2eb7b6d8f2ef5d9bc6c22bd43af2a2c27a44b63b8ab2d570c6b21dca418c986aa8be530ab6d1db50754a3674e8a4593a35bff580992e1170d9a890161930e100a870d254e7b22d9e2090e57a9dc6cbc471049f17c4ab0e2ff55f692eb88690b907a619e159c7f68872fac64c5e0e4bafe6f9cfebd6b64ebedc5fcc0fa912adf54c0409d8a9db1ecdfb77182ab68fb7b1a6ef72f43fdce054b94031a07b2e58ce5f2198aafe8bfc2ba167e35c9d2ad9f8225d5f4ed1a8b9c413c926cd7d69ecde7c63b6304dace749363ea462e9d4546b9cab81a1c09d5b28c787390e7d1379fdf7f635d4fd93305c3f34e87c8ef39bfdf50504b97c6a30e16c9dccea3bdb3b8fd08594ad445673bb629dc3e8cd0693433c8a630e755a4bd51f6e90a1271b2ff591feb49eb1b477993a3608c44bc4e344891301720ff6c4d140c2ded57659605f3c998c3ff60db73e396de772ed312a2b083094b30d026c80f3e91686f015465665a2f0b421dbe9968553f1b4263ba747582105322dc53250dc6ba483fc0e931f31b528c90766ec692015565b8404f064f44acf69615fc38bab734d57350273aef7863c8b64291de596641917584", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93687b90958d8851f8faa791a740c8e3d6af0bcc9b19c9a9104c49c045e7b5d9363462b9d29a734e556c6b2d2347029c074a964aefd93d416389a14ef3ddb3da113c419005ce053ef5676128682d79317eecff4f27ad8f3a341c1729484208650bf5e521f6248097fdc64ff5a0a6cea9e07e7c649e93dab8ac6058acbfaf1ad70aa"]}, "failure": {"scriptSig": "", "witness": ["4d0902c232fd8782c69989f630df34a3fed3b47664fab8d68a4b3ab2fea23d7077d103e58d59aa2e87dc60281ce6386fab2796d20098c04252945a82b2129388d5646ae87124c7ef1be1faff5b766dce9390ae2852899b6e64c375740bbf30943cea03f6002ecd65e85251c740cf4431f9d96b1e72052e2d6b09056efce86fd8ce56d752817758f5aafd71a3ab3510011453b6f0d40fda91b3040934b59ad603f641bd254c35ccab398d6ea4a4f7f2057f5a8c0a4520cb27073766fb7ce6785d398ed7c5cdf11a7fba3c07e872cf0a7d9c30800d3a7f9c1c2f9db7ec208fde50e1af7130e64f0ecb21ddf8ed4486e4e907d3ffee8b8934830c2fdecd4f03a8a811d2b53071471fb9e30ecb18d4be64af405ef72a8a9e7e771edb7a7408001922cc4364dab5b9658994afe148864d1cfffed68a7cabfc31cc046b2112943711f2afea1811c734637d0035bd1add11155fcc92acafbb4db9ec3fe103fcdddc0b2f0cef43c0a310029dfc2df33e946642057a31441e5df68eddc9428d25503dcf8d9fd8e3e0e7e3d2a36405de1f3b98d16d05e322fd004b0bea658c01c73a96ee69ac20ea606e2170fccf3a7eaaf5195418ace9009e36129b0b231a45bf164571cdee42157a01a6bfb6e0b3085173f44c168b9006a5a8756a20d48f5b431ab85462363fd5c47cda75f58fe208856583069d8af0e3d020bc0e1dd8d78490f0ecfcca2a45411717354a42a63b91137561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93616970ca0a1645a57dd7e4993535d76d7bd8f0b29a77eaf17ba06fe1d93791444c419005ce053ef5676128682d79317eecff4f27ad8f3a341c1729484208650bf5e521f6248097fdc64ff5a0a6cea9e07e7c649e93dab8ac6058acbfaf1ad70aa"]}}, diff --git a/txscript/data/taproot-ref/b075dfb300337efeb5bdabad39fff800ee516fa3 b/txscript/data/taproot-ref/b075dfb300337efeb5bdabad39fff800ee516fa3 new file mode 100644 index 0000000000..5c2830d964 --- /dev/null +++ b/txscript/data/taproot-ref/b075dfb300337efeb5bdabad39fff800ee516fa3 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127021010000006fe273ab02ff3b1000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87cd000000", "prevouts": ["1b07130000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09025c73a78f2756d264b727f445a0c2966587566bebaa0b4909fdf57273a0c1f229cb62f9667e1c4f824ba89cda36c5b581e20326169466388becd60f066f4e6d525a6a6c1d01ee84dfa23efe8bff2f481cc00996602104f3cc3833f052e9f1b6b0ae1e8cda9cef064b37b361411bc6f27afbbd323aff2512f7b81a951e671351032cf12c849ebd7ae332bab4cdb0033dd1ef2fecb9b27da0f08370e1df09daf0c9d561ce31859d3beb8fd1b42e34fce3e4c7f9219e7456dc0f825d4682d8c6f05137a20643f5d59b64eac1df8627f95754060223e94e833f5904a6e4d5829bb9cf89b217bc1501b701260d3cfcad2a55e902d51cf82ee74319c76844ecb067e06cd750e2e70b738abee804751679dca275cc14a161ca0bc07e016dbe0ab90e2f35195dced5a0dc91961f62f93aa1afba98200d87835390189d1c73e6fc21fa3d5a823e315ef8c2e1040441eb8f5ccdeca5d03ff2aa1eedd6151c3407b29c17e426347bc05c329763109233e8386a8a9f84f56abb45d44475e03d5cead01bba223d6c2c343e5c5ce10410c8de4e6631401ed6a443f14eedd76b49fb3ce82aadf976f305e8842ed58f22d81985c27af5e9f5449721b4e514b4f4261ac3998b6d694c1f533c50c3e01dec592b8bcd72fe26d3bd717d3cf81c5dd903cec3b52d152d54b621c7bb3de609d18ae6e3ec5646f3d7f75bbe204b441095ef5d5a45d93df8046e687bdeb82e95398d75ea", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d46957f69408ac379450e9bb4389343450626e215c5ed15c0a7aee568fcd444532777cb2583add22ba560e78ee9942bfe3080d15b9172e7f2c8ac5adf5c65a1c36f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}, "failure": {"scriptSig": "", "witness": ["4d09021fe139ef2f28fe9b836b87a916cdc079bc6a39d8c815596d237edffae5a131736609cfe655cc3fd898781f7641f0cd70151ee13806e43e5d2dda37e538dcaff3cc82e917cc234d9b39c30853ee7dec592a410cd98e1690436c4f6031c859bd372c37a16270853724e50413f4a592e410f24b760fae202d040fb67c880c5d504711975f6ca0cbe25d0fcb8ee628e6e188a188499f2f43e2f4d6b0b5e288f17e9117705ad1728792ff7b149b3928b13e617612e6d75cf39ba4e409391e081e90801e06690f124aaabb9abdec4f8f3a2d79cc0ad386ca6fa9d927ddf99081705d598ce8a18556ef7b9f52f0a4753eec9b55989585774b192205cd33d0b912fe8e863d42601523a49fd46f5df4ef70c3d0bde51a3abf84935749abc273790fdef99e2555eb3681ea165e56c54fb670d87b2ac8f8a8ad536f9a5dbd38157a3ef5b47fed1f6e45dc2058434862784f10c77ed61dd874e2b1a662709461642eecfff4161ea4986c23a03748170c4fc33e583dcb1fe7606e398dc4ad7abaef2a53a3a03d5531e9031f078201e710106d77e52d74660cd5ef9b10464ab69e78bef058fec08972a6f259519fae0776ecc6b81b9cea7bb67820d3fee59d4c978883ab9522fbc0212a77315ce83e6b00b5cc582b0ac710f8d3cb29fc804e0ef16da7d799cf41b6465912830924393f9bd1603733ddf8eb7fe62d2dd352db45bcf004bff89d6f01effbb0952a1767e17561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369c26013edb97e3ff451a8f909180c8326a435dedafe5a83ac52c9f1bf8b152f16aea47614063a58d04deed750fbc1e2c170629d7889e26e95c64d3b658c7538905d194d5538f9d0578f97aaac3520494006fe8ed5ea4118540907b045326452835c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}}, diff --git a/txscript/data/taproot-ref/b085cb29b4ab162f71d870e1b8f890fd0cf23cd6 b/txscript/data/taproot-ref/b085cb29b4ab162f71d870e1b8f890fd0cf23cd6 new file mode 100644 index 0000000000..a2a88ca800 --- /dev/null +++ b/txscript/data/taproot-ref/b085cb29b4ab162f71d870e1b8f890fd0cf23cd6 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c0000000003bd730a360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b701000000ad8a8be30263f44c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487deff4536", "prevouts": ["9cd63d00000000002251200fcaedfb972c31a562a88e2127675cb61d773b6b9ce4a4a9159012ab236e47b8", "09b9110000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902addd150bdc5faa9073d3026a89ee3a83638e006b85fce8df78ff3a5342cac9f0f8ffd4979aefbafd524a3800293ad76a76b34f84dd4a3b78e536c86aa056d764787fb984bc77e060196cb9ac369affdf5eb3c2d1fab5307950ec3877075c0dfe6d877d3c1ddf55f09d924619eccf87c0dae4f4f995d57266fa5445a49e10e2cf39b3f548235c4378cc21fcc3c356341e0910c9b811c55dccef17788d7471e063b0cacf18d805d597ded2fe81e4114d6ffb90f29f13e369154e376bd9b7a050c4f41f9765666a8188490caac683cfc4d9a20bc8fbbd34be1826c4d8f5550275e4aece9ba372f149145022c8fc3ea9b71074e287776cb455b841bd4059b4231ff30d93e94d36f311ec69cd967f062a51ccbb7fcac7a533b4518151b54a9fb619e17f4a25d8d4356c43e5f485bf335d710a825b5ba74f47eee53d14faffa2ebff59f31c99068735ed14c9a22781016f4992415590a7e0472a30d30b117d57ae33a3b0c40ca1cd16c1b5aa1541444136bfecd46add624d95abb5dcde73b39ade4b2db82b5793a14da1cca41e2918deb5833e4f256d7c6f200b1688bfa2ed4fb8a9d45c2468ec32f5b069a56f266923242b2a98c93f847b97053a295a325d4799002013e88d0dfd378efcc9539fdd077c66998e0a443916cf50d71b24c9a54e43a6d6cef56c9b47b5344682466b0d8ae2f7b7b0c92255abc5db2f8e49a86fce194ce78b8170728670c23c5e75bd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef20d31d73af45144650ecda4bfa65e941320968360f95ac17d612a18851d4fdede6356752267b6a4958657c43b99b93cfd40f762fcdaad4937ef48d6413f31b5843f54915b2c97abdf26ed2d562b36c2375ce95d63af6aa508e6368a687449"]}, "failure": {"scriptSig": "", "witness": ["4d09027739f2ea80564eb4ff7bb1ceb524c01579510d94e3a290a69b3399a812039b89574afbdb86bcba9fa0f516082b61e41e4668a2cb9715a2a7052421104434edd8b75d398c3bb2a00a41e25a55349cdf6b1a354082d4fff8a1472ca2fdc6b302672807a635887d1e562a935edbe0de04a1aa37830170c07e3cf04f9b607545289aab146d87e481f5c67456f75e8c59dbe39cfbc19b4290b296a077e7db0a542e9c3a5aed74a8b306d183b491e8dd4d696e7c4683a95b619406f5522705671d6da9f8c92646e84fdc5b3dfe20aa68bf45da12ed9c418e5825d64726ee64e4c6bef2d3b03d92ffb5d5cccce2ed73d91b6198bd6149fbf490fc668f1627c43420d12af28257b1f78e4a1ca224bea36c0b684821c253ef37eff25ad911b600a94ff4330aa62ac6ce23b4b569d639b2e9654d651b1f1392a6d049b39682feeeb401bc4c9ad33ee702d507f36d54ff846d5885ba81d4fd599776ceb049ad3d43c0f1aef9e99059b965db1181c794eecd57101a2b1f5fb741da4e1253d7b60ffe29d7b8dced3a7940f9a9070688654322f70df2bf54af903858172d05571d590f31fe7e785512b997c1f444d5acceec7734c6ad8a1ffeae1bb4c956252fb86bb8f92446f7d8e80ff9ac0a5b76e425a75cc1a20071d66485428ff11d9e07fe7a9c93f73fb22c023e512704b75713bcdee57e6b38ecd6ee32e66a4878e331560a157e4a5d2d76057a33ef15d592c27561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51631743d48971d1733c6ca7857843602fffe2e4122fe98dc3fa85acbd6da797d181cd61fd18311004a5536d1440b72b537197adb3a0d17581cb4a1679e89097edb5843f54915b2c97abdf26ed2d562b36c2375ce95d63af6aa508e6368a687449"]}}, diff --git a/txscript/data/taproot-ref/b08ac583665d8a49691a3a09c1d5cc1ee3b8a416 b/txscript/data/taproot-ref/b08ac583665d8a49691a3a09c1d5cc1ee3b8a416 new file mode 100644 index 0000000000..a8dec052ba --- /dev/null +++ b/txscript/data/taproot-ref/b08ac583665d8a49691a3a09c1d5cc1ee3b8a416 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe800000000f78152b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3501000000776103a803669483000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58000000", "prevouts": ["8c6f65000000000017a9148bc1125bf4e3450c593a5be1ae9a05461832d39a87", "f6cb200000000000225120a4b352e79354edfd3e864ed1ce6cc38f1a5faee50592882c88cc9fa5a730b850"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1653142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["2d6ac4038ca612d9aa5964b6877692495030730eaa4feddcf58aff6cf05b1ad3b83ad532944b79f035bf2d523d92a80d442edec9788a52ed82e1cb17a312f542", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/b0a4831326c413d2804c49788050b9f91a6403f7 b/txscript/data/taproot-ref/b0a4831326c413d2804c49788050b9f91a6403f7 new file mode 100644 index 0000000000..e0ec213de8 --- /dev/null +++ b/txscript/data/taproot-ref/b0a4831326c413d2804c49788050b9f91a6403f7 @@ -0,0 +1 @@ +{"tx": "1dd1ae6902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce500000000026e16df8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4100000000051563e9502ec56810000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc2caab52b", "prevouts": ["e99947000000000017a914de933560a9a700a6d4f856bfa5cf61713cb34ea687", "3f4a3c00000000002352212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["c121ee29e14189ecf575f48042069fb1cb2b67dd6b993ad51959e998da257d68d3a68e24af1b5a566a1cdd1366976d79d186e98fff0e84827211c49253546ac8"]}}, diff --git a/txscript/data/taproot-ref/b0ad1929e6a50924bb0dc2de48e23ed645f857f7 b/txscript/data/taproot-ref/b0ad1929e6a50924bb0dc2de48e23ed645f857f7 new file mode 100644 index 0000000000..c1a3325392 --- /dev/null +++ b/txscript/data/taproot-ref/b0ad1929e6a50924bb0dc2de48e23ed645f857f7 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5400000000ddaec8968bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d5010000003ef568afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4900000000daee1d6e0386b1db0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac56000000", "prevouts": ["92bf790000000000235b212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "309640000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "c96623000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e04c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93660eaf4545b5f7166123e054cf15eb738fe32912d9aa58946aa01c3af8881f1593713490b1e7aa24138c57a652efa6d547b3fb45fa4f05027d6d9331efbfa4d517cc0cd924d9aecb0bc2fcf01621d0e73a88693291594fa52fe0219caeccfa5b3"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364be51c95465cbea3588c9b6c76130e9be14a08cee11d82588795957f6f854169ed9d9b4b668c8953715b364fc922d70c032801be88e8b1547978372f57dddd133713490b1e7aa24138c57a652efa6d547b3fb45fa4f05027d6d9331efbfa4d517cc0cd924d9aecb0bc2fcf01621d0e73a88693291594fa52fe0219caeccfa5b3"]}}, diff --git a/txscript/data/taproot-ref/b0c00b0f653fb7d6d9c6d10a355b006e90bfdefd b/txscript/data/taproot-ref/b0c00b0f653fb7d6d9c6d10a355b006e90bfdefd new file mode 100644 index 0000000000..4e408fc5e1 --- /dev/null +++ b/txscript/data/taproot-ref/b0c00b0f653fb7d6d9c6d10a355b006e90bfdefd @@ -0,0 +1 @@ +{"tx": "2072d98802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1502000000525dbd8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704d00000000be747faf02cbaf2c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71c86fa53", "prevouts": ["2ae61d00000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "45be1100000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "4830450221008f0c40df843421f9995dc8849f3172df73d4b5fd29aadcc223b653fe669ec833022009210cdc0ad39a9379cb9238adbc1aa5caac67c361c7fa00eeb31fa978f029aa022102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "483045022100c4c9372bc11cc688d6f1c6991c3751d7ea1790aff7667073b59aa93cfde5207102206218bee0f56bea822b59ea8eb941d8ae5165e8233debe0813cece3c23eff08ef022102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/b0c6d5f594246c874ab683269116303a280482fe b/txscript/data/taproot-ref/b0c6d5f594246c874ab683269116303a280482fe new file mode 100644 index 0000000000..c92d53419f --- /dev/null +++ b/txscript/data/taproot-ref/b0c6d5f594246c874ab683269116303a280482fe @@ -0,0 +1 @@ +{"tx": "5ba8d15b028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b100000000a28f43ffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4301000000f4d3acf404f3d25800000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87e490d753", "prevouts": ["4153340000000000225120dc3b17a9e97101dd89a6713513f87d72e341f4413af90c87ebb03089172b5d03", "e38a27000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f14c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360c9deb8d7324d76c36ab4f0759c9a5c2cbf4147d65f4b6b168ab1ae532394b7618ea1dd842879684de6ce36adf7429742f60d84d7359dfb2eae76d7b546c72259feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}, "failure": {"scriptSig": "", "witness": ["4c52f1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f5b4495dcd3a27e5602f5de3a080a46677a554abf7524a5bdccd10201372c8add300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d513887c728222b860c37147d016a38c71344b48ea7c651274945970f6f23c5cbb4cd941a6bc152cbea0496b075d4b2611b435301778200e60e8b4147cd93749673"]}}, diff --git a/txscript/data/taproot-ref/b0c73ceab30b62cfa56f40cdfd49c1ce58f55a01 b/txscript/data/taproot-ref/b0c73ceab30b62cfa56f40cdfd49c1ce58f55a01 new file mode 100644 index 0000000000..864941a86e --- /dev/null +++ b/txscript/data/taproot-ref/b0c73ceab30b62cfa56f40cdfd49c1ce58f55a01 @@ -0,0 +1 @@ +{"tx": "da12e55f0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fc00000000eea8349660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703e01000000fdb2d88004830d1c000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ae0c615b", "prevouts": ["ec020f000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "54ce0e0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_csa", "final": true, "success": {"scriptSig": "", "witness": ["8f1a24494dab1f03b22408d30520e77aa4b48f8efe7bfd25e309627ca6ef94831c5b9e9893ec34b026caab7ace36a85ea44d74fd60d608b08b4adbfd946aaa99", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439befee6fda3cb49175c9fcdc99039bdef34bed6f8c885214259c1ab60f6e0548afc8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["8f1a24494dab1f03b22408d30520e77aa4b48f8efe7bfd25e309627ca6ef94831c5b9e9893ec34b026caab7ace36a85ea44d74fd60d608b08b4adbfd946aaa", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439befee6fda3cb49175c9fcdc99039bdef34bed6f8c885214259c1ab60f6e0548afc8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/b0d9006bd4700ed6403142773e914c7bb257d345 b/txscript/data/taproot-ref/b0d9006bd4700ed6403142773e914c7bb257d345 new file mode 100644 index 0000000000..072800f47c --- /dev/null +++ b/txscript/data/taproot-ref/b0d9006bd4700ed6403142773e914c7bb257d345 @@ -0,0 +1 @@ +{"tx": "77f1ef930260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d8000000007f6b15fadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7801000000785a0adb01d6d25800000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac0f040000", "prevouts": ["0be812000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "b5ed5d00000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d3d8e8f866e5c93cba06d034c6b0155dc3fb6dcbd1bfc23f94a2cd6d77087a79e8e97acb88a684ebbcf6cd53614657887cf2ab5b7ffa8568b23c580b7cee3fc759745caf2cf1f64f8d8e099707b0430cd5fd31acb7685c6a1867b5bc101b65c89699cbb3a49a3897e0d83b291e8d094574fad4ed03d5ac8d24902fc0d71816e5a01cf78466d0111abb0b3e024e5370f04f86266460cd148af38066a9e860c0847b320d45fde3aae686ac2b310fd0bf93ad880531303bc7f2d255d45e73de07d6fca8354843ef40cee7aaca7bf0a9cf1aa0266b7033d46512959c919a0dc469d3ea8c9e088f6952906d8357b118c976c65519fad6a7ad6a821a520095ffc14606c72631dd95a79efe95914a01937a0dbe25ad0df2539c40a0b6cc7476508b543e54e7925f703533143e8316c1dcc1a1e34c3cabd3e12844f89a0df860daea8b272ad0f051ef337e2708309be9b2396fce6c7de72da317cdff67b98ce2e1216aee213c3f50ee2abf3dd3560408b42bdddd8e8336a73e40085d1b188b3316dd4ac7f635765bd465c6fa35c9791eec15e38b6aecf672eccd911b447cf8e19ba7672a2aeab4f44cb25e76d787d6bfd0e350023a8ab46f0a251b535ba9946ab6768e452c08df6fb79f41652e42abf050d5a97c84d1dd6bc4786238ab259c635664debac17cf199666dc5fd13017896868fb3899eea4147d92148f3c6633c6084a4bb1448c5f182983d9a25f575", "997d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa40197dfa5e15d56b0c52ba6c1e960d9371338186786a853de15f9da987536b6f0e580b14ffff5bbee812c9f6e3af6b100c6b4cffaf41971c257964f1fb14f6f9"]}, "failure": {"scriptSig": "", "witness": ["4d0902ba389a32aaa53e4ec0ad44c9d8814f282e8bd985c5b24c932c4ec9101951fcaa12437d38d476ba2e04b73ff6ee55766553e676532e78610356df94be8c3b3f9a24bab69cb55844372babcee11d2cf244f125eafa0ac50c2ca0c871fbaa4ade748dfa14014c83c5854b74c698b42ce3602f98c25f7e15d6804356ee77085a9a79ff23638663a7adea296198ecf3cd44c1780b0baf2c91c7206ea060e82742ca1b2dae45e1c096ffcc2ae1263410e832623f12751ced80fa1fd300676e7da4d18f9aa8f78ec9640dff223deee293c230fcc4b3389ccbd80d97f2f249d3ac1aca366ec81cbf003b84cae439f312714e3a08a8c595d6f2e4fabad6e855c1a9d52a56dd210c8306721edabdf003fcd5c1aab55ab55fda70c623a342b2e0e22ef877cf05c988445c35bccaf0f1b6b11a459689c07b7bc445a8788dbfcead938e9c6a26c5f1f64d2aa102d9d939d2323f005e6d7a1a95d69bdcf5c7c36eb8b3a18219e03930f460d903efa02636284ffe60039ed141bb122e9a7552b3097ce713fa9ed4ba55df01b250e7a537a09f588624d6762e9d9d65cda6abcf5f6c4fbd2056df5a7bbaaf489d29e3b19780b2484b0cd1eaa1489fa5c9a1272b6a1e7d6d6fd514d5ababfbe88cd90dbce7d6c8382a69a24c9781c2f5551b8671047fc64f49ca9f6a3e8986ded806a9bca38b001d959f67262c010bb09a827db9877fa71495ad4c03c6adfd338b8374cbf475", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0822e3b986c0375fedeed2562a6fa36a7b38b0ca47fc0125e42be2f4bc52e49716a3d673df10a8cc98fc65477367c7f3bb838b82569297570384f0d4df8cd49e6dd413afa0de0ff2ef52577d4c80443f6003c675907986908c28bc93ded208ca160"]}}, diff --git a/txscript/data/taproot-ref/b0e3df60a56490ae4dccf3851d020b40b21b8b7b b/txscript/data/taproot-ref/b0e3df60a56490ae4dccf3851d020b40b21b8b7b new file mode 100644 index 0000000000..688584d688 --- /dev/null +++ b/txscript/data/taproot-ref/b0e3df60a56490ae4dccf3851d020b40b21b8b7b @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf16000000008e795ba101d0fb450000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc79020000", "prevouts": ["0b8a700000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ec", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365b2437d263ee0812a46b558174956b86c0172ee942f1fd166ed8fd2626e33ca1b17c496824b626c02ab547b0eab6d99cf720fc5f5950d9f56a4e0f1a7586e075a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369250ad1237d5633d63cd08d0b09aa1b36322d1a916eb5c296c4ee8f819a8dac8ea5b08b003f1d8a082790805ee2a5a4def5fb527637606ac665fe1637cb888218bc5bddb1ae8a97e111feaf10767a648ae88621f6e3dc27f3d4b61f2a6f156b2a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}}, diff --git a/txscript/data/taproot-ref/b0ec063bde9113e41cd5590763cc5a80a27e57df b/txscript/data/taproot-ref/b0ec063bde9113e41cd5590763cc5a80a27e57df new file mode 100644 index 0000000000..247ba75ea4 --- /dev/null +++ b/txscript/data/taproot-ref/b0ec063bde9113e41cd5590763cc5a80a27e57df @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc101000000c198db84bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcb0000000017fde2f5039f7f8c00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8716010000", "prevouts": ["56ff250000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "2f89680000000000165a142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fe", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e11fa2939e65832b6ff7989f1e054fda271120b52cec29bf8626e2a96fe398ca78fd22261ee209e04df9662f52c9dcffd1f6e65f5b546fd3c131bfb02c186b05f664ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663af012b32f8cd1cc038c1d6c2a62e919380767bc592e88c57dc97e62501e69d1fa2939e65832b6ff7989f1e054fda271120b52cec29bf8626e2a96fe398ca78fd22261ee209e04df9662f52c9dcffd1f6e65f5b546fd3c131bfb02c186b05f664ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}}, diff --git a/txscript/data/taproot-ref/b105a50748888b6356015fc47a88bc2be5715d6d b/txscript/data/taproot-ref/b105a50748888b6356015fc47a88bc2be5715d6d new file mode 100644 index 0000000000..65bc917fff --- /dev/null +++ b/txscript/data/taproot-ref/b105a50748888b6356015fc47a88bc2be5715d6d @@ -0,0 +1 @@ +{"tx": "da5995b202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba300000000e933e5a4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb40000000057e27db101a5fd2600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac59005b4b", "prevouts": ["fbbc1e000000000017a914bf07e8218e5a3c93fa381357100b6dba1ff2a91287", "4a0220000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2354212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["46348d658f319ed8e5e84e982370a36f8491173a86692b9da360a4075f02aede095bad76d7ee1e122c1a39d990b0987229848868db4f88a6f1b9810355a2f8cd", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/b14851f777181f4d6991a19eb5faf986f6c5d922 b/txscript/data/taproot-ref/b14851f777181f4d6991a19eb5faf986f6c5d922 new file mode 100644 index 0000000000..b0ddc298a3 --- /dev/null +++ b/txscript/data/taproot-ref/b14851f777181f4d6991a19eb5faf986f6c5d922 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cce01000000b3e4cc8d01b08b0800000000001600149d38710eb90e420b159c7a9263994c88e6810bc78d3fd55e", "prevouts": ["ddd4540000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_1e", "final": true, "success": {"scriptSig": "", "witness": ["1aa2b00dab226a1614867273b5cbaea6697e6eb5f0f7550c269dffc763e80d293ead063e8602322512500c46b66fe2de223e525bfd509e9e6c90783f5c7eeb1c03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ef811be4e94b39e868a761df447fba2f0d661c0aab700cf68bd0103a7a5082f1ed3b710cfb6403ca70ac2a6301a1b980b4ae3d86cafa8d4d943655b9c453086b1e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b16c3acf4e0fdb0086f5e645c0abf5248401f236 b/txscript/data/taproot-ref/b16c3acf4e0fdb0086f5e645c0abf5248401f236 new file mode 100644 index 0000000000..3877cc288f --- /dev/null +++ b/txscript/data/taproot-ref/b16c3acf4e0fdb0086f5e645c0abf5248401f236 @@ -0,0 +1 @@ +{"tx": "af5f933c02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2d00000000e528e6848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c439010000007ad0089d046ddda8000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac76000000", "prevouts": ["1a906b0000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "abfc3f0000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/branched_codesep/left", "final": true, "success": {"scriptSig": "", "witness": ["4523737481b1266900a60dd0715caa3d8050e4b2273427d4fb5a605322f3ba6ebc4eb06341778556cbb9e26f8681ed4aeed30f0ec3214a91bf51e6e585f4be0583", "01", "4d1301e76af030918e8d96a5e9c2094c9ba06d0ada8d0810ebc2f79ad890d92025a41b5cd08bdfc0cf7d4c9986cceba43fa0e9be5c2377c104330d94f07ea76f76de7aaa32e78ca0685201fb53e48ff30be8b782d5aacce7aecdb4508fb3a4147892070176fda3b74cad0a6f35c859d5e0d7627ae9b9ca8fdb5a4b5b652d3629350b6e6f11f7de2a627705b189459ee6bd1a593add61bffcce4e74b7b6af7efdd904948c80a13bf6734dd07387413a317d6a1134ecf76aae32aa7cf062cdb54d519d560c7a8549bc2fc161f890e330d20d78dced8994561d3d2bd7cdc1ede9bf9342f772d50abe38243c80d5649d81cd34a40ddfd49451e3305d4428e8856314a7308213c662f7f2d689b318f65bfcd530b15515dcf57563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ccd8c60a773165cc937efb02bc1b35e1115ac0671e1767a3af984f55e4d3c01bac00967532285e5651a233a5d3d97b0c986d2b78702c704bc34e0fc184218be"]}, "failure": {"scriptSig": "", "witness": ["8962f0b4e7c0263efd37394edd17b3c3bf9ee95c25efd464d1df92a111014e055adb3f5da6f85b6250dd1a9169c4c1c8b555e842bdea3aef2b7f283184f2f3b3", "01", "4d1301e76af030918e8d96a5e9c2094c9ba06d0ada8d0810ebc2f79ad890d92025a41b5cd08bdfc0cf7d4c9986cceba43fa0e9be5c2377c104330d94f07ea76f76de7aaa32e78ca0685201fb53e48ff30be8b782d5aacce7aecdb4508fb3a4147892070176fda3b74cad0a6f35c859d5e0d7627ae9b9ca8fdb5a4b5b652d3629350b6e6f11f7de2a627705b189459ee6bd1a593add61bffcce4e74b7b6af7efdd904948c80a13bf6734dd07387413a317d6a1134ecf76aae32aa7cf062cdb54d519d560c7a8549bc2fc161f890e330d20d78dced8994561d3d2bd7cdc1ede9bf9342f772d50abe38243c80d5649d81cd34a40ddfd49451e3305d4428e8856314a7308213c662f7f2d689b318f65bfcd530b15515dcf57563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ccd8c60a773165cc937efb02bc1b35e1115ac0671e1767a3af984f55e4d3c01bac00967532285e5651a233a5d3d97b0c986d2b78702c704bc34e0fc184218be"]}}, diff --git a/txscript/data/taproot-ref/b1776090f6173a9a430ec315e3ed5aabd24b1b72 b/txscript/data/taproot-ref/b1776090f6173a9a430ec315e3ed5aabd24b1b72 new file mode 100644 index 0000000000..20da9c8c70 --- /dev/null +++ b/txscript/data/taproot-ref/b1776090f6173a9a430ec315e3ed5aabd24b1b72 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3400000000f74ebda1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd6010000003ae740d901134630000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48757010000", "prevouts": ["a750530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "71fb250000000000225120199333ae2814ece819e66b6eda683343e1bb1d0c50810e300807466af2e93101"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936342529f4bbd62010952df5aa365e09694a0beaf9b870f79f3a07fd65a287ec77"]}, "failure": {"scriptSig": "", "witness": ["6a31616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b1a7636cf60adfde2e1358221f019b1e6b4155d6 b/txscript/data/taproot-ref/b1a7636cf60adfde2e1358221f019b1e6b4155d6 new file mode 100644 index 0000000000..130da96d80 --- /dev/null +++ b/txscript/data/taproot-ref/b1a7636cf60adfde2e1358221f019b1e6b4155d6 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127042010000002bb691cabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb3010000006a9750e360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707e010000007fb4f7fd04ef69900000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb3b44031", "prevouts": ["86751200000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc", "695c6d00000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "bbd7120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_7", "final": true, "success": {"scriptSig": "", "witness": ["8315fd5c3d2b13597202ae29fd5f14b518ec83978a94fa219ed3381eea2945c54347ad9ec3bab91865b4c8dcb398073743086dcfdb350b66e5a4362c4e68f13b83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3ce6377c37ce0024d6f35dc7deeb34796c29d64fb0cef7bfd62d6906b93e4834500958a64d6651b58bc7e108ba19cf8f89baa42ce29fa0896342f4433925ff7b07", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b1ad5a93a73ac48400168c0d0d6867c722e2ee94 b/txscript/data/taproot-ref/b1ad5a93a73ac48400168c0d0d6867c722e2ee94 new file mode 100644 index 0000000000..f5561e93c3 --- /dev/null +++ b/txscript/data/taproot-ref/b1ad5a93a73ac48400168c0d0d6867c722e2ee94 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b200000000ea14fb878bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d000000000294766f002728a7600000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87bc010000", "prevouts": ["72c13d0000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f", "12c53a0000000000225120a7af56c53f6997dc9f888a8c6887a5f8ee9cb96a9d70fc301f3f9e386ed85991"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ae4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93687ed348611d475a2912210bc8204a20bb00aa96f38a8888f1ea4486413b1a5a6d53bd36d32adc19f711473d01abcb44e7ab561baea4d664230dfa9381cfa8f4828a09ca0f6d73d82e88e284042e116dab9fe2cbfafc110f6c0fbe5b2788367c646ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045bf410b10c26f46641013d73a91af66d7632b0672c14a8d3b0dadcce48aba69ffe0b789927f620aeddbf74aea18c74264c468c5fe823a741d176e0a42636f367e46ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}}, diff --git a/txscript/data/taproot-ref/b1b4eed63248ce097e83d9f1723c6762b7de9c27 b/txscript/data/taproot-ref/b1b4eed63248ce097e83d9f1723c6762b7de9c27 new file mode 100644 index 0000000000..bb2f3ad8aa --- /dev/null +++ b/txscript/data/taproot-ref/b1b4eed63248ce097e83d9f1723c6762b7de9c27 @@ -0,0 +1 @@ +{"tx": "a67a7ab50160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707a01000000d50a14dc02bb6f0c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5a000000", "prevouts": ["a46c0f0000000000225120a2b42a3d113bb3bd52e1704c60ab477d21ed62730f87bd557087d89b305101d6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365796547f4e6a3486b790cf242f8b11aecb4a0209f6696518a51333fd17057295"]}, "failure": {"scriptSig": "", "witness": ["6a71616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b1bf9f8b4545db1b4c96961e0e20f15216c0e8b5 b/txscript/data/taproot-ref/b1bf9f8b4545db1b4c96961e0e20f15216c0e8b5 new file mode 100644 index 0000000000..be403d0272 --- /dev/null +++ b/txscript/data/taproot-ref/b1bf9f8b4545db1b4c96961e0e20f15216c0e8b5 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa201000000a54e1d1abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff600000000058fe3ae01afaa8e000000000017a914719f78084af863e000acd618ba76df979722368987b0010000", "prevouts": ["b38b84000000000022512005ff23ad1561e684c08dc4654c3a622730f716f9dbc5d4d5a4cd20d536b8ae37", "e07864000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93665e966627d89ed7c11a6fe076b6d05158b5eb3f9d5a5f655bd22fafbcd8e8b08"]}, "failure": {"scriptSig": "", "witness": ["6aa2616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b1c08a839cd0acb873c5f79044f09ba166bfa26d b/txscript/data/taproot-ref/b1c08a839cd0acb873c5f79044f09ba166bfa26d new file mode 100644 index 0000000000..671bca0fed --- /dev/null +++ b/txscript/data/taproot-ref/b1c08a839cd0acb873c5f79044f09ba166bfa26d @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7501000000e6d878d9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3f01000000a46d7fa2018ab5160000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7e2c51b57", "prevouts": ["edec250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "902024000000000022512068a70acb8902a9bd7a8a0bf24e1b522fed50855c0b1040069930cd3d961acf32"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a897063338365c0b13a26eff7985b69373cacf065397f325e0727d23d4450987"]}, "failure": {"scriptSig": "", "witness": ["6a2b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b1d288dfd536ad13a01041e19c9c11fead33ff91 b/txscript/data/taproot-ref/b1d288dfd536ad13a01041e19c9c11fead33ff91 new file mode 100644 index 0000000000..805d1a864c --- /dev/null +++ b/txscript/data/taproot-ref/b1d288dfd536ad13a01041e19c9c11fead33ff91 @@ -0,0 +1 @@ +{"tx": "6b76e011028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47901000000f2a234b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cf000000007d7052db024ba54300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a3000000", "prevouts": ["2531340000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "dc6d1100000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "f47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa056823e3960e672c2faac6672d149a4ac5db30e5c30fec842c5078845a2fea890bfc944cea42013591059ba9f4ec0a95c62699d2133b38017223ef90bcb8e42b4a87a36ff2ed7228bcfc2438815b30cc1c98339504e1b834e10aaf4a034051"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682115a2dfa9b95e696b2e1876a43d90a8957d7c1a0aa8ff9ef276528e0707301bf93feda87a2a10f8ccaf134f5ef6c2a0b95d03f8827da72e1e875b6e78a8a5e876f4540117e7e2fda63f7a015ec774d613b8932caa4388fa9ce7145d42cc7f6"]}}, diff --git a/txscript/data/taproot-ref/b1e426a1d9ca218fe8dfbd94e4f84deb69cf3add b/txscript/data/taproot-ref/b1e426a1d9ca218fe8dfbd94e4f84deb69cf3add new file mode 100644 index 0000000000..cf52be42c4 --- /dev/null +++ b/txscript/data/taproot-ref/b1e426a1d9ca218fe8dfbd94e4f84deb69cf3add @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb500000000cce811ac04718e6700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876c000000", "prevouts": ["889069000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "47304402201372b7b7415affa8d3a31d7d460063a924f66bdada8bbac4d28d3b0fdc1ba8c0022073caf6a462020ac81fecfbd367190fea654b7ff08d0576352600411c07b97a2a01232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "473044022044a72a8e7b670dc72045e89e8194caa82ad3645f93f17a8182f9d8ce21b29f43022030c4bb3114aaba72e0b5eae6ede44f4945c81d051bb753e52ba318f50dfa49b901232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/b21f2a634774a50314c4e0ef19018373cfff5761 b/txscript/data/taproot-ref/b21f2a634774a50314c4e0ef19018373cfff5761 new file mode 100644 index 0000000000..4ee1bf8907 --- /dev/null +++ b/txscript/data/taproot-ref/b21f2a634774a50314c4e0ef19018373cfff5761 @@ -0,0 +1 @@ +{"tx": "d105fdc102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0301000000971ac2e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41b00000000099cdcd0044657a70000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79617aa1023", "prevouts": ["43046f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c8213a0000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f5", "final": true, "success": {"scriptSig": "", "witness": ["23578c1e3a91ef0dfa332e6c5f58b6f8a1326086c1c7f132e92a17743a8ecb1270c9c7a29f195755c38741e41418904623b09aa69c86ff03882ad7b2512d0a6f81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["da0ef200be08b34b52a38dd86ffd4fb1a09e600f236028eca5b9dcbb9e23092a51cc8f5e5095ffe7e3730997fddf64eb77ec3b8709a7a72cba234cb65c14cbc2f5", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b25b243c1918bd286e71165a606917ad6566dcb9 b/txscript/data/taproot-ref/b25b243c1918bd286e71165a606917ad6566dcb9 new file mode 100644 index 0000000000..035cb7bcf2 --- /dev/null +++ b/txscript/data/taproot-ref/b25b243c1918bd286e71165a606917ad6566dcb9 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4700000000041e430c102ce663f00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a664db913e", "prevouts": ["125d420000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "b87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369c645b03c2051c6beb7aa80d32191caa487d851613efaf1c31edf92889bcbe40ab6940ee0f3b13da6463e2f516d6c168d9c5d733b385f1180629b82031abf4ccad8c3985a8e2539d42260561cfa7167d8724d0e4cbcfaa47665e96933724a3d86960f5e71abb11fb1594f725adbdd26a9f61c928558a58ca58d11d05eb565d16"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365f3587725e5247e447e4cb6b14e0c535c8313d8ac3ac5420f5f1daba6f6e0dbaff5a0b04042772840f11ed5a15b1f6f5628d6ed53a9b814a67fccb7bf41c87856960f5e71abb11fb1594f725adbdd26a9f61c928558a58ca58d11d05eb565d16"]}}, diff --git a/txscript/data/taproot-ref/b279bf9258b4c48220f05e2e891b91c7b13e0572 b/txscript/data/taproot-ref/b279bf9258b4c48220f05e2e891b91c7b13e0572 new file mode 100644 index 0000000000..5e8b738104 --- /dev/null +++ b/txscript/data/taproot-ref/b279bf9258b4c48220f05e2e891b91c7b13e0572 @@ -0,0 +1 @@ +{"tx": "a115863c038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48b0100000096e9c4c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49901000000144124f9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf9010000004abe32e30189092c000000000017a914719f78084af863e000acd618ba76df979722368987dc000000", "prevouts": ["e7c0370000000000225120975437f6ff12fc45d8ef3d74f3d05cfb35811edf79338d42e1008b4e2cf45094", "6ef4350000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f", "c869260000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e968", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369091fd32923117b71e5ab9b92a9d13a05584ef6b1cd43e2a5b18703bfba3f09acf301e2cd98ef2d5c028e1b110cc6503fb01279ff4eb452c3408c39d22674b4dfc7f9c78871d6a598c7c7c3f4c8210a5c47caa8abf9700608b6e75845c74a6c5"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360382dff41a76e3f98bd5f592608b4db8a292c887d72fd2428e596a0b3632a30fead6d3e810571e3af6462e6592387cebd820372bb489ff10eea7a83e6cd68e83cf301e2cd98ef2d5c028e1b110cc6503fb01279ff4eb452c3408c39d22674b4dfc7f9c78871d6a598c7c7c3f4c8210a5c47caa8abf9700608b6e75845c74a6c5"]}}, diff --git a/txscript/data/taproot-ref/b2bf386739903299a1cce995ba58544747eee3f9 b/txscript/data/taproot-ref/b2bf386739903299a1cce995ba58544747eee3f9 new file mode 100644 index 0000000000..5be3e313ce --- /dev/null +++ b/txscript/data/taproot-ref/b2bf386739903299a1cce995ba58544747eee3f9 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c71010000004ff55bce8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45000000000c0c2d20502325f8a0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac3b000000", "prevouts": ["c9644d000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787", "75c53e00000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100e36580573e0a91d83bc09082f0299661313823e7209f148b8d24fd7fb24d766402203fea28f7195f9da5736cbc034e6814e5677d7cdf1e82d8a7ffa6ec7ee6027f7d02", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100ee5f2f79d1dfa297deb5e9d30940b1d3bf18ff8834e93d97ee1cdce6fe334584022043d33a96df3ccb719bd0b403a8b1f8d5d2052c81656880854070990252baf53002", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/b34497bedf19b0567d48c3bb9d3c6c6b7285bf56 b/txscript/data/taproot-ref/b34497bedf19b0567d48c3bb9d3c6c6b7285bf56 new file mode 100644 index 0000000000..8fc74b13d4 --- /dev/null +++ b/txscript/data/taproot-ref/b34497bedf19b0567d48c3bb9d3c6c6b7285bf56 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44900000000f5f5607edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2400000000a5a0567a0347928500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a66dc2b32a", "prevouts": ["ddf93a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "57904c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_31", "final": true, "success": {"scriptSig": "", "witness": ["7fb04c03105eb712ed2d128076563b8b30f2f03bfeb616f3328177986172e52d658a19b84d106954de7195396167fe7231c36719ef075a18e673f7c5f14723d881"]}, "failure": {"scriptSig": "", "witness": ["8821379d423344363033262f0dc7e1a0eca6be4b8c1b8da95f780b0f4477745d9e2cca68605640ed89ff1a7947969d34d7f39995e632a62c0b534399f8ac0e1131"]}}, diff --git a/txscript/data/taproot-ref/b354cb571d5964e5709107acf8b69b7a52691648 b/txscript/data/taproot-ref/b354cb571d5964e5709107acf8b69b7a52691648 new file mode 100644 index 0000000000..bddb9973c3 --- /dev/null +++ b/txscript/data/taproot-ref/b354cb571d5964e5709107acf8b69b7a52691648 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff901000000939dafac8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47c01000000d2c3b2ffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2801000000052131c304cb62b800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c6010000", "prevouts": ["1f9b64000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7", "1e9b35000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "49a720000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3044022026a14e608bd2246518963f984a9e5b5115db068eebad21bc3cf427842d648baa022040f8a2a0e6cfdd5ec2d386836ef4471903aeb51035135613129d668e99e17a978a", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3045022100ce87c284455926c4e3c8c87af70f206abefaf9e8f69b32e44b2198d863dfd8ba022046b01e4f4024ecb9a7f2a28cec55d456f1193bb9d053c62d25e49a4b900079948a", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/b3621ec700f1905ab8a89bd0dc990c56dc5b2619 b/txscript/data/taproot-ref/b3621ec700f1905ab8a89bd0dc990c56dc5b2619 new file mode 100644 index 0000000000..f5a959df3a --- /dev/null +++ b/txscript/data/taproot-ref/b3621ec700f1905ab8a89bd0dc990c56dc5b2619 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e000000009ccca0ec8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44301000000298165898bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e700000000f154399c02849c8e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966d030000", "prevouts": ["a9371f000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "49f43300000000002251209c5a589e416b2bf8d886ac38373c12ee12085629030d3f34ed2b7cf34700cf85", "fb803d00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e54c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b15c6036a676a492a4bf737064ce6a21b64de8ad159d3b2e60d879468caf8957d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936899bb7d21500b6999eed5216ea1db5a9ff8f61deccc2645d4f480296bc202312deb89faaac3ba7f5e16436fc8221b82cf02c075e22a72f26a59deb249ff0d9e9edc23a266999aa1773fe99be867e95cb2abe2d57657b7a4dc20a388644aabac6d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}}, diff --git a/txscript/data/taproot-ref/b36fa07023f7e2c301fca71c92d63d4b9d3dbfe8 b/txscript/data/taproot-ref/b36fa07023f7e2c301fca71c92d63d4b9d3dbfe8 new file mode 100644 index 0000000000..15aa96385c --- /dev/null +++ b/txscript/data/taproot-ref/b36fa07023f7e2c301fca71c92d63d4b9d3dbfe8 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b22000000000e68496b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41601000000d14c8d5b0305ca5300000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac832c5e32", "prevouts": ["ef35240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6975320000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936036751089af36ed5c0ef7dca2a713ca9b31e3a2dfbb12490c74aaef9653ee48ca81c44a09079faa406e9dfe20ff322801dbd7fb1c55ee11d2e1c43aeb4d3cbdeaf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}, "failure": {"scriptSig": "", "witness": ["4c52e4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f526a05401741d274ca9fd789911b95efb3576d14523fea071e177c96656d1d00d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3e0b789927f620aeddbf74aea18c74264c468c5fe823a741d176e0a42636f367e46ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}}, diff --git a/txscript/data/taproot-ref/b3acffc7854d876acec4be4e8f02c5785c9786cc b/txscript/data/taproot-ref/b3acffc7854d876acec4be4e8f02c5785c9786cc new file mode 100644 index 0000000000..2a7611ce63 --- /dev/null +++ b/txscript/data/taproot-ref/b3acffc7854d876acec4be4e8f02c5785c9786cc @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b500000000011604128bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49200000000a36624610468c3470000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac78010000", "prevouts": ["c58410000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "78f438000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09028457bbd4dde9afe54c6c2f8bf83f35729e8a3c9e3f23c7b45ebe65b3357ca85ba15558e0f24533deb2ad2e0dfc079668e04eb421c0e2c28a1833f987c5703e15e99e9f16c1d7e2cbf21118c5c7a42bb57c03f20c696c809013509da488b0900c36ccc11ed60de7f2b3193acf4bca28e7471e4a4f3e92e18db3c80be44d88366eaecf124256cc09d419f3007cbd45e532c7e161d444960db0a606664e7489063dc115f699143d8262d93cdcd2e852f54de92a5455b2223ad2026a3f055d922a3b7f3058b3ebc2058c266a163f2c1e61e34e6673ccd0de302bc8246ca75f0732b32cde0b5c37b8a43742ab926f9a48c4b3542ba852c7c6265855f72cf618bd01c288c6da46285171dfbf34ef42e0e834681adca76cbfa08b77612f94b9b1d87b85209cdfcfce4a87c627cb9b4f60a3fd0b5fcab7c8bc062549dbbe439c71ef25f2b07824f1d0559c3608866f73d7fd9f84d702274a5f665dd297174046d225cf284ad5e1e09c55f1d3e928555a87a15bd8832beb55fa30d5c30d23778b366a85fd66ac86fa77767709a37d79154f7a1efec1ca022b58707f95c575b80cd0faf4a9dd54d7086c392a13972e59cc84cf32d2e580412fb43af3f35545097afc5ebff4ea2674454b5dd4d21ba1e39a91a676820063c0b5b86e2555feb5e55ce9d14fd1f37e606c00b460cf6483502886fb49e26c6c98df83c3857a5e7c9f437bb66396519ccb05c6fc9264b275be", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08215cb0c87b91becc5e8e88545f518ccd4dd82a3936db012f0c0e2ff8a479534101a521886ab29756862a71c0453b77f880429f1d68b1fae0f34d555c1e4747b3e7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}, "failure": {"scriptSig": "", "witness": ["4d0902448027d910a2c28dacaec9bdd36e54d01a99672e8db16135ab21ec0692430600c747da65853b1cf02165f4678d55c1bcbc8283c376e90dd59705b414f1da4a9ce01bccb19275b5eb0b8989b4b07a4c855cfbab900a8ed67f4450e5e8cc1362e31d0214557b4475a4156d36999c20f30ea4647742c65ecea157f0057e92fc45cbf9aa47a6eca8ceabd833f0c0a3f6e09b0345e161c1f7fe5d481cd0d7ad86896a57f797ca4270b3eb89a1f4e194d5fccd5be89213155a5ca76c9e019fb7822290116f7b3cb3195037f42ac343a08dd8fda33c5384e19d1a3f222120eb6abb57f47ab64fd5c12484368fc506f9607dd06c552a69c2b68913caa2f0d86e85c99c76030a11f49685653b4fc48903daa0ef2c35e8b1f53ca50b027134027dfa337e051c8c03b9135423e051f6300f649c1fc7e44a58d0589c881749c20dbd3c2c81d4ec965ba222057687889889e36b6cb24659f84a1ae2424aee0e1ac18c378c0f8cdea39cf55d91209ab5eb8e044222187baccbd0a177a66028e1068125751b781bd8031af392fa08ee6c72199b8dc266373ce74d5c52fc4b6b81f620f40a45a6de112a0e4b41a1c2587b7353b791a55ffafafb742d9d4de2895f8105a388e3852bf220ad0328c2c1d5ede8ee77152506efb453129419062688877ee09540fd932f7f89b42cf7921e5d4de7fadf405303b58bf8eedae10e67d29e8385a7444428f60eeba39051ce4b8c1e7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004573668dc71689fe0651b36a481e24aaad53f2818649afcdf831b4092eda1b840fd3726db1c97dedfc82502578948b1d779eb886e6296c36bf50b8d2fe25c32b8a344cebdb8ecd56ef01fad0911d9d88482970ec36d3a04b84eda7f5b5c68ec938"]}}, diff --git a/txscript/data/taproot-ref/b3b35af21b57765c4439d83505e2c122bcd9d159 b/txscript/data/taproot-ref/b3b35af21b57765c4439d83505e2c122bcd9d159 new file mode 100644 index 0000000000..2f80d038ad --- /dev/null +++ b/txscript/data/taproot-ref/b3b35af21b57765c4439d83505e2c122bcd9d159 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf330000000056a475b2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cba01000000746cca94dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cca00000000ed67c018043edd1c0100000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88accb010000", "prevouts": ["e2be7c000000000017a91441ce0eb0e6e5800ced23a872818e5aaa63be0d5b87", "3be74d00000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "38fe530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1657142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["ddaca7147b466835165381f7ed37d503db143637d11c7f16d815ec7bc34c0e9f3a3dba96eb04d63e872619684c4194998a63514ef6ffe93f0eaccbaa87b1ba47"]}}, diff --git a/txscript/data/taproot-ref/b3e2b23acbebfcbc2e5f4e54d4fd7005740cae7f b/txscript/data/taproot-ref/b3e2b23acbebfcbc2e5f4e54d4fd7005740cae7f new file mode 100644 index 0000000000..1ecc22a58f --- /dev/null +++ b/txscript/data/taproot-ref/b3e2b23acbebfcbc2e5f4e54d4fd7005740cae7f @@ -0,0 +1 @@ +{"tx": "dc7f15740260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705f0000000035065d94bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfce01000000f213c3dd049fb7800000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796be95ab32", "prevouts": ["b8bb0e0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "cab3740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_96", "final": true, "success": {"scriptSig": "", "witness": ["34560959274ce200db1d719b55427c3303d033c50526abb970120c21652c1fd5b042a3f3c49127804a8c8adbe59568dbea857e4c659d85397addc46c6801573781", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f302f24d0117461617ce1b6b980dfc41fff8cd5a392a2ca79afa0ef89953151aa3facc1f97810d994aff6d4c78fca137172cc5262e030d9deb5713444271bf7996", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b3f7745d61088bde2d2244a961085a6e8ca22a22 b/txscript/data/taproot-ref/b3f7745d61088bde2d2244a961085a6e8ca22a22 new file mode 100644 index 0000000000..078c12ede8 --- /dev/null +++ b/txscript/data/taproot-ref/b3f7745d61088bde2d2244a961085a6e8ca22a22 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127033010000009cf2b10cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2201000000378971070259bd8600000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47876dd8b95c", "prevouts": ["f1be110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3569770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_42", "final": true, "success": {"scriptSig": "", "witness": ["9f78e6a85ef709de7f86cf0d03afb24fe26ebf8b0838c59205b84c09c0b6618bb13a587e2e95d0ca877f3a7d77caf5fff1347cad9c23141bbc6a379e69978b75"]}, "failure": {"scriptSig": "", "witness": ["5600a15e3d3dcda56bf739d4b2460c7e70c94ba5b898979da5995e9024d91915c69804b009ae0c69dec98bfc8151ff4f2afa620a9b6a2749fe8ba1e4c8ba387942"]}}, diff --git a/txscript/data/taproot-ref/b3fb8896212c7278ddd055ebe8806a9aadfbdbf4 b/txscript/data/taproot-ref/b3fb8896212c7278ddd055ebe8806a9aadfbdbf4 new file mode 100644 index 0000000000..6a9ed58cb2 --- /dev/null +++ b/txscript/data/taproot-ref/b3fb8896212c7278ddd055ebe8806a9aadfbdbf4 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c700000000bbe4adda60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708e0000000066bff0d104cae04d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc00050000", "prevouts": ["16044000000000002251203931946bff2228105059183c00ae321e35895921175a46193bb089ee2b225687", "44b610000000000022512088bd92c864bebf276ea78553bffd47e68dcce8f95537d9019b0b776be36b3d44"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688b84dd89443b974221dd5eff164e8c7b4057a81ff0cc18ff546def1b21c1105"]}, "failure": {"scriptSig": "", "witness": ["6a3c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b42a78220d5bf6c02b4d64f379b4963da854ecf8 b/txscript/data/taproot-ref/b42a78220d5bf6c02b4d64f379b4963da854ecf8 new file mode 100644 index 0000000000..94fb92dec5 --- /dev/null +++ b/txscript/data/taproot-ref/b42a78220d5bf6c02b4d64f379b4963da854ecf8 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47e0100000034d6f85adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8200000000012c3b33dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d000000008f19ffce02f518ac000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987d0010000", "prevouts": ["baec39000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "d7d2500000000000225120b982c4866c93df3772712b36d4336b477e2dfe66f304c80c21f6bc33f20b8495", "8ecf23000000000017a91418261fd2fa0b0480c86b918607add1dde9f7026a87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "483045022100da1b4e54c424c8fef5e652a21593fc43edc68fe19436869c978748b96c6c8e370220590e270596f36e2a5c33e3ced8f8ccc5532124d2e7a2c78f161cd6da7ca9c2c791434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "473044022023bd90580bf102b8a2e6f2dd3c092f8a5c299803237ab3bdbdde10261c8fc74102202c43afa40239f58b8992ce023a963ca87bd50783c6b9ca999883cf25e9a7989a91434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/b471b7933c10f89f075ebd244fc7dce18cc064ec b/txscript/data/taproot-ref/b471b7933c10f89f075ebd244fc7dce18cc064ec new file mode 100644 index 0000000000..fe47317fca --- /dev/null +++ b/txscript/data/taproot-ref/b471b7933c10f89f075ebd244fc7dce18cc064ec @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41a0000000077b56489dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdf0000000045bcf180046ed1640000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a647a36e60", "prevouts": ["e4d03d000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "4dd2280000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362c7d9ab9143a7761e2df5d26d7dce1bb1763a647714ba4cc57b12c7d6fe17e6cd81cc5051f53cb756176679d36bd97691fe000700c9f2a0965e3d67cfda5d0f8a81c44a09079faa406e9dfe20ff322801dbd7fb1c55ee11d2e1c43aeb4d3cbdeaf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb43f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824d4fab40ea135233ddc8c9f724889f007818f7ffad5749db3376d8fcf405e18faf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}}, diff --git a/txscript/data/taproot-ref/b4881b1ab0b628b8e08950b8799b2a7b2f90f6bb b/txscript/data/taproot-ref/b4881b1ab0b628b8e08950b8799b2a7b2f90f6bb new file mode 100644 index 0000000000..8a315bf3c9 --- /dev/null +++ b/txscript/data/taproot-ref/b4881b1ab0b628b8e08950b8799b2a7b2f90f6bb @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa0000000003a5d8e9060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703b01000000b886ef2002b9017a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87de3e9141", "prevouts": ["613d6c0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "1208100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_dd", "final": true, "success": {"scriptSig": "", "witness": ["bfe7fbaea9e6ebafc9381e9106abc49428b4671512b0473af5735258dcf67890912a355d6966818247a937598c69cc96531125a2133b11e801d7228c73ecdaa703"]}, "failure": {"scriptSig": "", "witness": ["5132b07bcc6acfa772d3138671c3aeef0959298dfa8fa65d479c55f37a9fb161cbcc8ea2ca8d38a1da9ce524097c03023b700950b6bb5105cfc31de866ea1408dd"]}}, diff --git a/txscript/data/taproot-ref/b4b0e6e8de840a729657842fc3f326a51926695a b/txscript/data/taproot-ref/b4b0e6e8de840a729657842fc3f326a51926695a new file mode 100644 index 0000000000..1a70a81d1f --- /dev/null +++ b/txscript/data/taproot-ref/b4b0e6e8de840a729657842fc3f326a51926695a @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705c00000000fc3ba74b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270360100000034bc366cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfa0100000055a193d8039f024700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca335554b", "prevouts": ["c58a11000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "75690f000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "91f92800000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["3044022074e56ffa3a4d847aa657df9bff182c4d04ca6703dc0472e30f640c62643e846802204657a0386fe4f248370d383918cf4368819da1ff42714343fab31202303c261a02", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "witness": ["3045022100fe3d0ccde45b37f951070b3fd63855b43be9601dcd7424a46f29b6b02f10412102201c28d54a18ee32cec518e1223b89360bc9aae84abc523ec6204e9323a220be8102", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/b4c0e993f516711b0d2941c1993f065eee0512a5 b/txscript/data/taproot-ref/b4c0e993f516711b0d2941c1993f065eee0512a5 new file mode 100644 index 0000000000..0d502a8ecd --- /dev/null +++ b/txscript/data/taproot-ref/b4c0e993f516711b0d2941c1993f065eee0512a5 @@ -0,0 +1 @@ +{"tx": "8b21c5e6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c432010000009e90c1d88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44d000000000d1ee0b404151f6e000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac44010000", "prevouts": ["bb693e0000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb", "20ab3100000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "d47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e1d15be41604f0459412a6d9aa888e4d019cca614dbd3b30e8d19f8f49981c6d3eef830f28a0ecbd34c70640f7829eb7d86b0cf2da24853f16b74ab53bbfd728ea84370bdaf8fbfa2c728119f306db95ff534e2e627fabf0c000f69380d4e93e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93669e6d8ef22861e07fee4583a5ab47fb4893c942079130ef347ee1cbb0ba45047b93338c7d107e01cff6d052285c57a3fa3547f5f14e99776c0371239cd8619173eef830f28a0ecbd34c70640f7829eb7d86b0cf2da24853f16b74ab53bbfd728ea84370bdaf8fbfa2c728119f306db95ff534e2e627fabf0c000f69380d4e93e"]}}, diff --git a/txscript/data/taproot-ref/b4d27baa0c7f4d587689db8a9529b71fa55341ec b/txscript/data/taproot-ref/b4d27baa0c7f4d587689db8a9529b71fa55341ec new file mode 100644 index 0000000000..64d2e0bfbc --- /dev/null +++ b/txscript/data/taproot-ref/b4d27baa0c7f4d587689db8a9529b71fa55341ec @@ -0,0 +1 @@ +{"tx": "caa0da5f02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa6010000007ac8318cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0f0200000026999d930300049100000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac207a7f41", "prevouts": ["a2016f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "fae5240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_e9", "final": true, "success": {"scriptSig": "", "witness": ["1fb82bf0788365d728b9ff776845a4e1f6da622c3a3295c1075ab60b728775a56f1011bf9abcd25f0f6b4fb7c1c50cee22ab9747d0c3802a8c50e3ba5365cfca02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a5020f0599578459c0780e9c3b5c31a50d7e7746c1b31a86c18f61edebf412d0d89c3e8dc51e10fabf432cfd1c01e623abea27728e26071ff4f2146db7c316c4e9", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b535e18acfb42d8eca463e3d005649eeec97a029 b/txscript/data/taproot-ref/b535e18acfb42d8eca463e3d005649eeec97a029 new file mode 100644 index 0000000000..2b43c6dd95 --- /dev/null +++ b/txscript/data/taproot-ref/b535e18acfb42d8eca463e3d005649eeec97a029 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c496000000000fcc65bbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfef010000009a2231fa0450179e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47870d661d36", "prevouts": ["4a9e3b000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "4982650000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "success": {"scriptSig": "", "witness": ["80fb1b5f90655833fb2fb0d6544b68b278de03509ceecdf4541097c227c5d12b7f92fa5e55f14d4d3aa3ee121077bc96e339253480e204a5518b6f302c2e2429", "50f83aa6dbc36226127df9bd7f4f11dd44b4564bd055dc6a444b407f57b32cf927e368aff72559a720863118400c618ba399e55609f5fc1179d6b71e77cbfd1446f2330ab168753a9446f5ed4ab346f402ef05e51c45ef88771b98f5cb3754cb17134b350320e9c9fa337765e77cc50a29575fdde5894d121e8da51572acc7412c42f83ce285264318fd37fd8e7ae56dfd63970556fb593e4bea75fb66a42d319c0fb740a7fe9c2f73e0ec5224aee24d72327a9a4ee36c438856e3672e92619fdda171"]}, "failure": {"scriptSig": "", "witness": ["567eb9d22b837f710af064336faed00db3b47f08f118c0d9e4d4ba4b117b35fe779cc346421f0b4e3856060641633fade6d7bd71988fb22e87e0d9b20b9e840b", "508e48a54ec604c6853f0ff01aa13a403804219a8119d8054779accb0c4f1141a293d2696e38346244d19cffc8f2363e41711b4ae9c67c4137372a1ae83a3aad8ba8e8282e06130cab41ba926aa565f40b01ef02748111badd2199443071f85233a701e0c767d70116c7aa151e3cd4d53d487c5fb8ca6bbd939cc342f52f15d18259ed480b20b484f8afed1edb18429667758218e3b31537d0d3f833796852e94cf5a61e93738c88b321187c3e072c6fc406fa79ee9cb6"]}}, diff --git a/txscript/data/taproot-ref/b537477b73545075fe86dcab51eee08a1eff1f93 b/txscript/data/taproot-ref/b537477b73545075fe86dcab51eee08a1eff1f93 new file mode 100644 index 0000000000..5713f7dcdd --- /dev/null +++ b/txscript/data/taproot-ref/b537477b73545075fe86dcab51eee08a1eff1f93 @@ -0,0 +1 @@ +{"tx": "fa183ec302dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b530000000029438bd260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709d01000000a26a9cc804691a39000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7b8b82732", "prevouts": ["2b15280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "acb41200000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_1c", "final": true, "success": {"scriptSig": "", "witness": ["fdf6052c7128cb3d7cbe7b01584ec28858463c9e347f1776890c13ff6f9c822293d102363c44d36e16bc450b9d21ce49ba3a3f33dd04e04d559fcb38d5cf839683", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["aa09de2c1d11bbc4f812f1cf5c869732780aa67ca6e755a34bcf1829608d28f85d21aca0b3f60aaa2e90e2086ba15bf80ac55612322747d7af2aecf7c1d8020a1c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b545791a846adc504218666c3218bfaa83bc90d2 b/txscript/data/taproot-ref/b545791a846adc504218666c3218bfaa83bc90d2 new file mode 100644 index 0000000000..1d824d14f7 --- /dev/null +++ b/txscript/data/taproot-ref/b545791a846adc504218666c3218bfaa83bc90d2 @@ -0,0 +1 @@ +{"tx": "97ca34d70260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127044010000004c539de760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f0000000002921dd9f0244a22100000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48781000000", "prevouts": ["264b120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4732120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b5", "final": true, "success": {"scriptSig": "", "witness": ["3b2a5952a72457b7b400ce8af078faa4007c2fa0dc6721ac6bb4779e311f2809d329095342fb90a773f2635129d25fb0f5e2f46f4d00b2e4ef0fccebbe21f67101"]}, "failure": {"scriptSig": "", "witness": ["e2a81bd58fa54fa09bf8575704de54873d6576817d7f581c2d3e7d0a900774450a9597d4f54b16e46e1345b5c4dada41270b0e458cb4bfd3d043f09674980d1ab5"]}}, diff --git a/txscript/data/taproot-ref/b56d0867bbc5b009c7f592e99f5d598f728cda80 b/txscript/data/taproot-ref/b56d0867bbc5b009c7f592e99f5d598f728cda80 new file mode 100644 index 0000000000..8d54462565 --- /dev/null +++ b/txscript/data/taproot-ref/b56d0867bbc5b009c7f592e99f5d598f728cda80 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c720100000018c71abf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b800000000898d559f03957a56000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48759030000", "prevouts": ["83a74800000000002355212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "20d90f0000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["bf127f6c66b7e1102e7e4836650d9806400ed78271d46cc373e046582cdf8390c98ecc85b9404e8eb4b8e9e9b79bed4773fdb5eb0d950bfc127e46a8c7225e62"]}}, diff --git a/txscript/data/taproot-ref/b571a84a7a61d25a217f263add5e84836c981aad b/txscript/data/taproot-ref/b571a84a7a61d25a217f263add5e84836c981aad new file mode 100644 index 0000000000..c072031727 --- /dev/null +++ b/txscript/data/taproot-ref/b571a84a7a61d25a217f263add5e84836c981aad @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5201000000c07a9ac860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703c01000000d90833cb03dc493500000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc90186125", "prevouts": ["5c76260000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "80e51000000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "", "witness": ["3044022002fc22cb5825c98d7bd61746fa0370018ac55f3ae979ac16cc7c8ebd432135a8022069913fe82371b7bb7b9e5791aa9f2734f4b9a2ec187bfd1342519f8d227b8d5582", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["30440220540cbd88fd5b5f45e8d5470557e27c89c6379a2a87dc3d2e15536008fe93c215022061a594385c325818d40303c0489d5f913f71d62c722443f0f080e98527afcae282", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/b592aa01c9d16fda0673296c91e16d85378ef308 b/txscript/data/taproot-ref/b592aa01c9d16fda0673296c91e16d85378ef308 new file mode 100644 index 0000000000..43dbb651a4 --- /dev/null +++ b/txscript/data/taproot-ref/b592aa01c9d16fda0673296c91e16d85378ef308 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703100000000aae7c1ca60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127001010000004823318f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270060200000039d291e50304902e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e70b3b865a", "prevouts": ["076b0e00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "6753100000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "176f12000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e144d0ff37a890039c0ba21f76704f7cfad8b9e86a035546ebb7c5a6ad2c2135a28cfae4f24e00136258a4229df9ce1533cc743f70cc4e5c0214ad74c09f63cc0b9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bd5fb013d649a0b113a2236243da0be0326b44fd96f8b22737f30239849c7b4bc63b209b29a3611ab6267155884a7f894b498570c9db6a86ba3046458c9f77af637f7085334bd6ace67733ad5f759fad65febfe656f63b2b30abaed1d2ea29dc9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}}, diff --git a/txscript/data/taproot-ref/b594302e03843a9f9c9551e5065d334f5788b18f b/txscript/data/taproot-ref/b594302e03843a9f9c9551e5065d334f5788b18f new file mode 100644 index 0000000000..640697cecd --- /dev/null +++ b/txscript/data/taproot-ref/b594302e03843a9f9c9551e5065d334f5788b18f @@ -0,0 +1 @@ +{"tx": "4b63d655028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43401000000a620dba3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1201000000e5f7c897016aae05000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374878343df53", "prevouts": ["fabf390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "197a490000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype1_byte_keypath", "final": true, "success": {"scriptSig": "", "witness": ["884d96208de777f6364e510bbc81304d672ef7db1a15dcf8bcb2f398b0883e272073807a37ffa0461435a5af025f423ca0b2d9b5d35bb0f0d8c47a35f4e8d8c001"]}, "failure": {"scriptSig": "", "witness": ["884d96208de777f6364e510bbc81304d672ef7db1a15dcf8bcb2f398b0883e272073807a37ffa0461435a5af025f423ca0b2d9b5d35bb0f0d8c47a35f4e8d8c0"]}}, diff --git a/txscript/data/taproot-ref/b5c23ef36f914bfe6734a376e3ff23afa4056cdf b/txscript/data/taproot-ref/b5c23ef36f914bfe6734a376e3ff23afa4056cdf new file mode 100644 index 0000000000..905529a43a --- /dev/null +++ b/txscript/data/taproot-ref/b5c23ef36f914bfe6734a376e3ff23afa4056cdf @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c700000000bbe4adda60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708e0000000066bff0d104cae04d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc00050000", "prevouts": ["16044000000000002251203931946bff2228105059183c00ae321e35895921175a46193bb089ee2b225687", "44b610000000000022512088bd92c864bebf276ea78553bffd47e68dcce8f95537d9019b0b776be36b3d44"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936269f9110b37a3f6304bf0d8aebdce70c5dee6f88f5a6dfb0bad103ece716e201"]}, "failure": {"scriptSig": "", "witness": ["6aac616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b5f858c267b5596e80a4ca9e1d9d9fc97493a161 b/txscript/data/taproot-ref/b5f858c267b5596e80a4ca9e1d9d9fc97493a161 new file mode 100644 index 0000000000..284f0bada3 --- /dev/null +++ b/txscript/data/taproot-ref/b5f858c267b5596e80a4ca9e1d9d9fc97493a161 @@ -0,0 +1 @@ +{"tx": "603fae9901dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2300000000c5bac1bd04e5355a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac8e010000", "prevouts": ["62125c00000000002256202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["b492d21c321102276ae54fcbf77e697296436ec49857e79b4e0a7584486c791422a1272287f86f4f5d3201c76c402eb6c628126578e460265310ed7aea9a1c76"]}}, diff --git a/txscript/data/taproot-ref/b5f894878cea25475b042e2e6dccf49267130d0f b/txscript/data/taproot-ref/b5f894878cea25475b042e2e6dccf49267130d0f new file mode 100644 index 0000000000..6bbd52b400 --- /dev/null +++ b/txscript/data/taproot-ref/b5f894878cea25475b042e2e6dccf49267130d0f @@ -0,0 +1 @@ +{"tx": "d86b930c0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706b01000000d429abdc0248030f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4873da65f51", "prevouts": ["e828110000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "4730440220457a47572b23dd0d2a48139bbd294dd602f0cad076ac14ae0886ccf57e812f2602201a54df631df3eee230d529cf98784ada27e28f7c38a4467e8800040b41e84ead03", "witness": []}, "failure": {"scriptSig": "483045022100936308966ca9b9c527e9745cf7d2b5f2967b4bd835046a2d2973600a87ee3267022004bb1a268e144013a0ebd54a6206a35437c296f6b7e0a374c7bb1c2406b7054f03", "witness": []}}, diff --git a/txscript/data/taproot-ref/b605240fb46dc5b5a62d8e4fe44362074c17cd79 b/txscript/data/taproot-ref/b605240fb46dc5b5a62d8e4fe44362074c17cd79 new file mode 100644 index 0000000000..7ddd1bbc2a --- /dev/null +++ b/txscript/data/taproot-ref/b605240fb46dc5b5a62d8e4fe44362074c17cd79 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcf010000008c867549bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe200000000ef2a1b630206169c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71bbb9c40", "prevouts": ["35f922000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "d5937b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_1f", "final": true, "success": {"scriptSig": "", "witness": ["3d51d6ffe85877bd6004b393ef7f15b111ba6d02fad2f9f9661b53daad79f924d545836a6feddc88ed39436c384291a1bc5fcca53b2a2485290361ddb750df3603"]}, "failure": {"scriptSig": "", "witness": ["b3291bee08e4d9de85e3a72f891616b457b12e09495bfa31a8e9210132fb83e42ba7e5673343d4167b4c92aa327ef24486d03271070cb2a14998268a78b589531f"]}}, diff --git a/txscript/data/taproot-ref/b62a40520073f939f2c0c9f173f5df055dbcfe5e b/txscript/data/taproot-ref/b62a40520073f939f2c0c9f173f5df055dbcfe5e new file mode 100644 index 0000000000..2d24a5ebf2 --- /dev/null +++ b/txscript/data/taproot-ref/b62a40520073f939f2c0c9f173f5df055dbcfe5e @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb70100000009c40cc18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43f01000000a76706c2046e9aa400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a61f296e39", "prevouts": ["7e7f6f00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "395737000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "47304402202c91e7f01d27010cded1cdf6210b8e9c1aef45a1d3cda35c826ecfa6534754bd02207524e69961de2b9a3d678dd3525112b09426f58be3a27b56d6fa9add335e84a15400", "witness": []}, "failure": {"scriptSig": "47304402204c06704c3428f9330bc27477f70a27c9bae8972f8738dda3275092ca46a2652002203649cda029cd903c61848928680ddaaf5159c5163b6e0cad87e50a043c64a8b4540101", "witness": []}}, diff --git a/txscript/data/taproot-ref/b646f8b3b9e38907889dca9d182ffcb148c5eb86 b/txscript/data/taproot-ref/b646f8b3b9e38907889dca9d182ffcb148c5eb86 new file mode 100644 index 0000000000..88ee50e33e --- /dev/null +++ b/txscript/data/taproot-ref/b646f8b3b9e38907889dca9d182ffcb148c5eb86 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c455010000002e8aa283bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1c010000000ded30ab019a4146000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478713000000", "prevouts": ["2248400000000000225120fc4f9d8aed21e545c10b3b4fb5f7ffa2432ec2f4c867e738428f21cc99cd5336", "4c276f0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["ea4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93645dd27374e1e3840d53c2eddc23e77f3daecabe9190b2b544b03414f960ba3ee83976a7e8bc20bfa4c53f64ff2df47d867849c8cbf6df51014735817968d498535c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}, "failure": {"scriptSig": "", "witness": ["4c52ea", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4209c1516ced38e23a698f2fc59f604e56c30e06a1cb7b1c589f3d617aca8a56aea47614063a58d04deed750fbc1e2c170629d7889e26e95c64d3b658c7538905d194d5538f9d0578f97aaac3520494006fe8ed5ea4118540907b045326452835c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}}, diff --git a/txscript/data/taproot-ref/b64c6d5ba93dfc04d7a168f3316abb231668ca1a b/txscript/data/taproot-ref/b64c6d5ba93dfc04d7a168f3316abb231668ca1a new file mode 100644 index 0000000000..1ba30d12d0 --- /dev/null +++ b/txscript/data/taproot-ref/b64c6d5ba93dfc04d7a168f3316abb231668ca1a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb600000000b0eabc15bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe500000000b52cf8660410c1a200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47874be99750", "prevouts": ["4bbb220000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "61aa810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_11", "final": true, "success": {"scriptSig": "", "witness": ["754c6bbbbb47123cf5061653be919e1c7e9a44b19d1ce850dda4fe02230e9d2ccca6bac0eee738facf790fce0061d544554a12a0db3a258a8b1160c4bc835e8282", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a3ff602ec2a4530a3b327108b02ffa864190fea846935b9da5199c0fa9f6e25833749ca4ab1672e94bb4e0c8de654f2190f24c0a1334f37b25a7954e4b8985c011", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b66c4be98c84d4c925dd2af48a775cc657d0344d b/txscript/data/taproot-ref/b66c4be98c84d4c925dd2af48a775cc657d0344d new file mode 100644 index 0000000000..d185c645b5 --- /dev/null +++ b/txscript/data/taproot-ref/b66c4be98c84d4c925dd2af48a775cc657d0344d @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127080010000003832b55860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f600000000395e212301b0d0000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79609c18144", "prevouts": ["126f1200000000002360212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "1cc50e00000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["fc2469f70d2142b6c5a1bc787c6753454192d596cfa5390f25fdd84f537c2ffc2924d14846e63516a9c8eedfa1d017bfc24af99d1ad2bb0ff02030359d376267"]}}, diff --git a/txscript/data/taproot-ref/b6737bb08c29b827385850c321cf5d8413acfef6 b/txscript/data/taproot-ref/b6737bb08c29b827385850c321cf5d8413acfef6 new file mode 100644 index 0000000000..7eff83e8c4 --- /dev/null +++ b/txscript/data/taproot-ref/b6737bb08c29b827385850c321cf5d8413acfef6 @@ -0,0 +1 @@ +{"tx": "7712fd3c03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc600000000fa2131a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3a000000004f6247e1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff3010000003fb10ede01318d5900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac50880832", "prevouts": ["21d5720000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "a3c12000000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "1de070000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d34c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08279688f26c44e4c38ecd8996ded351dfac291f6a9fe2ce500158a378a1caa9ee2234a5a049dfcee5b69ebdb7c70e6242c675d1abc9cd58c84d7f9a8e8e1277a43a4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}, "failure": {"scriptSig": "", "witness": ["4c52d3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dac4f378a9a739f7649f71d424bad959e415e848838a94c69104635e832cea3b9dff863108f68b54d204f4b43b2fddebfd69630b8c1a20ba8be96c4e7e2557a5003e045cb689fe4fc6de332c618eb0cdce02c2dd8aae7c6dd6f70bdbaede2814"]}}, diff --git a/txscript/data/taproot-ref/b67e4f02f0ff506105dfa4a0171d89ceb6d26cfa b/txscript/data/taproot-ref/b67e4f02f0ff506105dfa4a0171d89ceb6d26cfa new file mode 100644 index 0000000000..e1734d0cc8 --- /dev/null +++ b/txscript/data/taproot-ref/b67e4f02f0ff506105dfa4a0171d89ceb6d26cfa @@ -0,0 +1 @@ +{"tx": "06cb7a96028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42e01000000df4b95b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3200000000adddb4a50374fb5d000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acea040000", "prevouts": ["f3563e00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc", "fd30210000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063cc68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823b9ff415677aca4bd8bea8fa89699624d8c5f018d44ea89c1d7716b3c6d0480766d64d66e5a8ef59726e977ff218232e5171732e5d132f479dce590bd8ea056135478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93691eb1c3299922e83783cf541642d83e80fab5b37c6dac002e0721b387482d418e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0d00ae7d77688765097c61dd6dc7203a99b1de19633b0fe895af4a245d0fe1ab9735478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}}, diff --git a/txscript/data/taproot-ref/b68b738158b1aed99780946dcf5925a67eb68cca b/txscript/data/taproot-ref/b68b738158b1aed99780946dcf5925a67eb68cca new file mode 100644 index 0000000000..70d0028c7c --- /dev/null +++ b/txscript/data/taproot-ref/b68b738158b1aed99780946dcf5925a67eb68cca @@ -0,0 +1 @@ +{"tx": "103e89be02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b830000000082ed4bd360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709600000000ede849cf0184480a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e70c17ce26", "prevouts": ["149c1f000000000017a914bf07e8218e5a3c93fa381357100b6dba1ff2a91287", "e7361200000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090267fc598d5d0990aab5eca74a300797727d5da5385f212423b091cc7f2acfa60548df3a5cb82ee4c876de16da801e2ebd5fe8475cc30cadc6702ebb12f00b5f8539eaf618a09b5181b85803347fb9f8e598ae19bc63ae84dce1ae3f9e8e7756966ac249855ff750144e912780ddd39c2a5b70f27bff87d7f00fd6285e51ef24ad582ae24bed990085c4cd13b0d32be8d6aee7b079890ba38b8e726cf7d44e1257930e2dd64fd41cc58722b4adee6be37aec54fb05e620e0c5b5d63802f527cf867e5464d1f0cc86a192d5e93a8d67bca994877e0c81d3b0de7419ff86db787da60b4172f12dcd47bede99d2ffbb72d43f802d915f8d948e41db713e7233e210523126e4470165dc66e35effc2da885e5c464a64a6b899fac7fc25835b4ecac0b8c07380e37a9fe968a4b4860fe840763e665c85d5da803d29f5e5e32b896b351f0cb77ba4a8584a58a1493d06cd69dd2b1ec4308ba00bf6835c6c9a23ddb8f1799d4c886966b226b1d5090677ed11e50f295bc0e61f484dd42e15dc48484ec0777f3b03efe6110ae38a3e3aeff626cdab476e673b68804f5af62c17895fbec895bc6a42c3706cc48774dc6a3377867b82ae4421478d29a97d78ab1a0cace6b97b123de08f39bf1f92ae6603c8b0584092de737e7a317bc5141764344dd8f4fffe096f4b360f4111657b613d3eea8d7b7d173fab23a4b67316419e7fbc8b7030a418d1eec06be385482375", "437d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faeb1e69b2064177327a27f356e828bc3139f73429a3608cb2420b3294d8fc1681cc59ecfca53d850b1637d6273d8700d7dc702fb5baeba7c0d1778aadee75959b"]}, "failure": {"scriptSig": "", "witness": ["4d0902783b6c6baf1e098e5de445840e1ee526e9dd14dda816a7e697dac5d31be1ef733973aa233c2167087e226a7b8a6ce4e0a59fecb61f28bf9a74de3e6c796c7d73399f9de452978d7b488e61c3e232707b4abecec3c5482f190e16642efac6fc8cb99eb6603b226440193c324c9896b2b3ff646e40dba03a8b0e16b5642f75792a7c7d524c4e6b3150aaf6a8b081494783a76a5c0ea4cc4e206cad37e0392f33b5b31b0983aed42db4660796319245b56c3b13dcd909370631d91c65bcce5cea7f80ef52fa90352d222dfdf6c8af7d7becb37405ee4266af2d36d34a974bfc828ebf27242b370e4caee6d399117df0e27a33f74b3c0780bfbeb43ff6649cbad7511396ba9786b7ddcd021c5752f77632dd0354dbc44b30cb638fdaf6be8cb03ce428835dc962809414f2fe1a9a5927c648c1f0941256175f203ee8bde81b6320f2e11683e77837d7a14dba5ebcf0e5fb2c42febae600f4a6f5610b47a7a16c8989c3b413cfeb797bcb66b73df50dd124a2ff1f798b0fc5b17c5faf2f98dcfe9584ef1ec7239e3fb29a136a31e1f96e3dfb65b098fbf9273cbad3879f90e0ae01c8fbf06a7a09c4aa8c1117b7ffbbfcb49a1b32d1dea98ad54762256b5c871a52da38b8c2f9b1a4d2aaebd3d6a6dc9b0eadade95ae3d17ad21b6ecfe9dd73b775b1416c8d7c3a06f8f3a6e5b4af79e6993b11a6b6870e3c9e0a78ac6a6b16eeae2d344bd22fbee6f7107b75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824274b5900613cb2e14ccbb49f92be42e903262ce34f92c4d0a103e0ecbbdfe862db79fc77699d349d3583c063c1ca5cb78d93faef419ab336fa45db1a25ff641"]}}, diff --git a/txscript/data/taproot-ref/b6df4711f8c031a1f3fc609594a2746d2d4e3d62 b/txscript/data/taproot-ref/b6df4711f8c031a1f3fc609594a2746d2d4e3d62 new file mode 100644 index 0000000000..547875d1b2 --- /dev/null +++ b/txscript/data/taproot-ref/b6df4711f8c031a1f3fc609594a2746d2d4e3d62 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1102000000e34a2009dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bde0100000060eae28fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c540000000002789cfd01dce73200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acae030000", "prevouts": ["6cbd6c000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "4c421e000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "b0574a0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902ea2a8543d58089589a40b07f9ee7d8e6ca0b93852ee3965f129beca3d7c8c31858b1e7cd9247161961c2f08ce0d61fed0332457240000658dab3fd5eeadaaeba07f8f0114379a61860299044b9887ed039c5468a2ad50f2d9c91820990bffe87f5a49fb8c34aef2ae4d76dd932bb9256d3aa3c8b513260c6b544025eb4eecba0a138ce6f273b00f5c5a904db028f1f2fdc4ff0dfb2cbda1929147478f84d9fd3bc70b914f3299fec1d849be2dfe5e51902dec6e1c88bc24896fdbd7045b7ee7f5807f54b27f6a6932e7ef3b118a75f9c1189aefcd3b0d68151acf6db87aa01b9e657354e9502a308435d7cdbc2039e46cb2de6027aea7d5f7a37bd3587ff6b27c787b8eb3512d87288180fc03efccb6f74cc1685ed9beef4a7f3dab3cd913e93ef088c060378332ee4e4ae97bd42ea901b63a5c87bdce557173a84e659c9ae69eff47d8a5f945305ccbdd689bfc41da73de2b5d6b0ab8cc7c69490c6187d4dfaf38e2628d801bbeaab7a05aac804a3f23a73c0698a3d4462d30f7d1eb3893039b2a0bcdccb5f529a42fbfc5ff5daa945f2c7e28e48e151def0b9a53f5e993174cc6519630b4ae1678ecb77195907b392be24fbec8b2683a932488ee9f2f85cb346a06a033a8e05c686407a9eedd676653ffa7ba700aef9bb5fcb36081889f89a2e9dd89088cf4a9208cdff32ba6450ae0b74f891a15eff8a7a5a1a7905ffd6d70a56821de4e8b8036e75", "8f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad1d8c040d98f7e016b556934cac423be94b74d6bd2b0327759368d6fd53a8bada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457f8fae370a255a677f2f729010dbb329fa966ed9a0dd82e5083dd7ea90426dc47"]}, "failure": {"scriptSig": "", "witness": ["4d0902bfbfda238b86155a766904b0624aaa9ae74aa5c10ce197c8c229b94e56a4fc85ceed26821a1ea73c92033ca70e957b8dbd9a9b3abe4057eae50b98894b4333e65e01058f17698b3f88d538617a3b07ba3e007601e1f66064a1f6bd45e603a182b0240b651af669f5567b1e754e8f43c5d14e1b42a55a015c9abc0d3483b97c5c8a26a6eb12f9fa7535ec5767928c2660e60d0dbf72182c6bd2d6a448bb4bd2e942a76290c5bc83fb46a8ea2642f3d34be05801e93805c1b4bfb9a63cfb81e3bc2bff57ba188746dae79077b27fb150d02f6ded4cb71e56a2a4201728d78a63e1246b2ffdb6d4b3a36637d0e950ca84feca553e8f4a8cd1102deeaf3ef5429c4a35829b4bfaaf93a8d53b1bee41947ace99d1081c0806edc8a8c7d2d468edfa9bf53bf7f73367631579c0e54dd7c58ecf8986974d3294b1824e0ef99db38354f9250a79a9157233c47626f1883734b3ff6443fe8f2cbe4ac3711ca63560ed7c877a793b4f0d0e8be7a3fcd60a22d5709fb2a255df764ccc8190fed807f26fc4e7e70e265f752aa310243b5a3d5ecbcf84e4309cdd340b0e93e1b2865ca37530dacd4ce6921d48273c78ce05be0d8e1734aba468ad940209d8dce8a20855b9009a7c013344fa43a591369b52d95d7257d5679ce5727609981a2683994d62c40d5be554d9d3a5b857179e00cd75a5a9a27faf76e0737e46d6cee23d300965f6ab002262d0dad76626ddf175", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93659bcb84e47153ff4e79014703dffadeed7ba3d8123da0f5fd44832628b9f5c46a79f40e3d51694d686dc3a1ae4413ff10533c43d32121e1e1cac9518583e4de2dd5f972b05e2f18c3e7c797b604beeb8879a3af7f1e10968a0ac8aaf9d489fe7"]}}, diff --git a/txscript/data/taproot-ref/b6e1970eedbfd9c6a474d94f15274687adf86c2e b/txscript/data/taproot-ref/b6e1970eedbfd9c6a474d94f15274687adf86c2e new file mode 100644 index 0000000000..0662f878a3 --- /dev/null +++ b/txscript/data/taproot-ref/b6e1970eedbfd9c6a474d94f15274687adf86c2e @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706c01000000ba310ba08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41100000000bb14c6b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b42010000002e7adaf704ccf9680000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987d84ad23d", "prevouts": ["3b2c110000000000225120e0fbe9053c6d2a439b1df3d9c89ed0e68b8279a92dae6907e23437dbb3b4029a", "a9cc330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6891260000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "2c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa44f4b784770790344d4d1238d6245096bcc9e2ff88373fd56766bafd01d3e44ecc62bd398c27c2bcf203967681d855a98ab83c6f29a4f091e05b1c584209e732"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c923690eabf3e888647cb597bd60e90f4b3beb7649a22c5f2f6c3fb70e5402f8da733fe71e3ce0c37752cc3ed22f63651cf62c657cae6a4db35497744053504dcc62bd398c27c2bcf203967681d855a98ab83c6f29a4f091e05b1c584209e732"]}}, diff --git a/txscript/data/taproot-ref/b71c95db43c402381d9a9673ab063f0735eb1d31 b/txscript/data/taproot-ref/b71c95db43c402381d9a9673ab063f0735eb1d31 new file mode 100644 index 0000000000..c49d1b06a3 --- /dev/null +++ b/txscript/data/taproot-ref/b71c95db43c402381d9a9673ab063f0735eb1d31 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3200000000bfb51208dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf700000000ddd630b103d1d6aa00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796cb000000", "prevouts": ["b68d4f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ec455e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_4b", "final": true, "success": {"scriptSig": "", "witness": ["bccf6e13050aeb8ac005e70d8018d8107e34f741b2369633964dbb497d651d804189b0cddd15cec8b0e3759f14988585d474f90d4ab502756081b2a349860d1981", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["51599d223b7052c676a9454d653433b56f94f2697326ec796cd3b37efa0d666e3e00920c32fe2613350b98393a273c95605480fcf1b625dc2a4b43c7973c7ff34b", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b71ebb4f48a1c213c17c8b1e9166cc38b072dc9d b/txscript/data/taproot-ref/b71ebb4f48a1c213c17c8b1e9166cc38b072dc9d new file mode 100644 index 0000000000..81916fb108 --- /dev/null +++ b/txscript/data/taproot-ref/b71ebb4f48a1c213c17c8b1e9166cc38b072dc9d @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3500000000f75e818ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdf01000000a0889ad4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b87010000002757f8a404a146990000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875dfe903c", "prevouts": ["79b65900000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "221d220000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "80fb1e0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["dd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2823dff2991922f121728685824385d20f53064595141c17e375e09b6c17310e1f075c573bc42ff1b5fdcad1a87ebee849fc17bcfc5c414a2a4f901b5a19cd44f11caf36eb2bc7b2ba56ad05f43983925bc55248f9b66a13a767efbac40c00"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d5adfb4b655ff7e7194216f0c9ec7a59b69961b08133bf278a8ed5672f2f6a4fc12d2886f924517b8c41f4755cb69ff55f68e740076f0e346dfe7ab1da23e202491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}}, diff --git a/txscript/data/taproot-ref/b72daece9e0661e0bd4c8a41d26c73ba8eef4882 b/txscript/data/taproot-ref/b72daece9e0661e0bd4c8a41d26c73ba8eef4882 new file mode 100644 index 0000000000..9ab237b428 --- /dev/null +++ b/txscript/data/taproot-ref/b72daece9e0661e0bd4c8a41d26c73ba8eef4882 @@ -0,0 +1 @@ +{"tx": "81f75e6703dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cae0000000014a05bb260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127036000000002ce4eb9c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702201000000586df89c03fad66a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487470e335d", "prevouts": ["52384c0000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "aa2a13000000000021521f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "06580e00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["e2724605c4d92803b851d6620f06e0d958a4b1b46f4b00b63c352345415d348718303dca66502c00dbb004c294b733f60a36fc50534cbd729ca50ea92420f08f"]}}, diff --git a/txscript/data/taproot-ref/b795709244b876a1f75a1d801c74732832748ebb b/txscript/data/taproot-ref/b795709244b876a1f75a1d801c74732832748ebb new file mode 100644 index 0000000000..95cc07fb81 --- /dev/null +++ b/txscript/data/taproot-ref/b795709244b876a1f75a1d801c74732832748ebb @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf19000000009d3e6ea68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44800000000855c81ec04bce4aa000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478709000000", "prevouts": ["c8fd7a00000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9", "b6d4320000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_fe", "final": true, "success": {"scriptSig": "", "witness": ["73f0609d8312d50f238ef85197f18969449b5e42eaf67672e52d267bc2ce04873cbdbe489a991fbf55ce250b5deeb979d151f00834aee929b2fb5fc830c7e4a783", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["6759884cd9dd6ddf52603745cb0d4119162bc3252a8c5ecc6387b2ff47b0b12c26281611269371ea660cb960f3c06c3a0d343d0e4135a13c1ffb4d6c5e43ba69fe", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/b7a501079daff65d0e768364b11ab44c69980aa7 b/txscript/data/taproot-ref/b7a501079daff65d0e768364b11ab44c69980aa7 new file mode 100644 index 0000000000..a30d506805 --- /dev/null +++ b/txscript/data/taproot-ref/b7a501079daff65d0e768364b11ab44c69980aa7 @@ -0,0 +1 @@ +{"tx": "5fbef0bf0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e4010000002fbbd3ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702400000000b17fc38b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4020000000022f32a9201149c1700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6691b05e", "prevouts": ["0bd8110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "02e3120000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2", "37553d00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09022809a22ce415cd93da3551dc7ffd852852cab6f35d23cb1d0d7e613eed9fc66abf2e19981a69be7a410c3cf6dfbbc6231d86b6a1e3b66a6c09bf9e862619cb01695f6cd14c2f38ed754875265275921449bcd49ae4f519d7991c8db15da5f847cf9ded8468e0d7d8869beb37f5a0966fe88dea7439c83f28be66f6310f2ca48ff2c078312ff7dfeccf1571f35d440fa1621e437680415a1db4328534cc3b94b59bf9a302e5df863888cc6bce065cff43d4ffe433ab606a3c424981a47ec784cb08bc42021ce359eda8dc514f8b5483ae94b96a1d9b4fe6e24acb41cf3e61d90828d4df299ad7c8e657765c03029efbe005c678a7a749ec5e37a58c527bfef0de1cd4eeba7a8dbf2ac25609e6b8f80781f774cf2e8edf1c32937d430d05a32daaef6cd68e07d292d7a826c330f1fafb00bad4c8b81b8f1c7936c7b5ae82af8cf3d996c01da49943982a2acbbd30e5567f2ec0ae9d162248bf58a345330711afb2fcf9b78220b5f12948efc31168b9182ccd59653533d984156ded6008c8939c8671e8c11f727bbc6345131b4fad70476f8d778655b6183ae5e15376d7f2ccc060272d13e30c21ec881b046f01434866929f57ba84fc81790abf3e5410f472b77a69f45fc8c9d2c67989736834a3b8b8cae459096aaadd335aba72b1366cd10aab3a332cef8714d060ba2dc11456a0365a972f8264006ac38f77164895932d9ba45ed2fb62e287375c3c75", "317d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93631b55cc0c5b23f0878108315b133cb569cbdbe54eced0808ecfcc8dcd3b5cd21e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84187c77ca06c68e3a239e6fea37385de49c0e93bf09ae3a990bb588f1e26193612f65ebf74c8b951b09da599ea3d6f486010b8cccb0a2142ec39aae62c1ca3e7"]}, "failure": {"scriptSig": "", "witness": ["4d09029ea27b7aa5fec2c6f890a40deb4f7d968e92c778d31ba59576228222aa7f3216dde170cce0627ef958c3ca920e9a2ce49e8b562413fa8aac8c9c45909fd83bd56eb890f642f19abeda30106d70e81c66d2c0124b2ce5dfd2f284f114b16b872b5b7025a3174492b681d51f78978e3dccbe7cc543ab7a4ae59366d1bddf226939c70981719d45ab400069303974689b4708742b6847562484d343770a7271a4ba3f3a4247a862d6b34382f6de0b68669b67b44469b5c7149539a3a3dcb688a6f700715e79e08d81b190afab120018763bc5ecfe7798b36d5f3c4fec0eb709beb648672433ee1ebd5e41649cfcc3f8409b317fd7c2ba3391a18f299d08542ed3ae9b4d8a498bf4b694a2ac403ea0629a5f4b4b448cabfe8696eb3856fdcc13b8724240481507aa3079024292df65d5394ea4f58567eb577440c64b4acfe485eb01cf96d018193c9e795e7d40af5e4f6d83b08be0a28c12befe2fc20b6506912cc23eddad14ec750fff90f33ecac2e82c6decce27bc4bf5da9ba9ca6746d42f16a6dc4cdd26a5f234baaf7a1b109f7d4c5bdbf3b02f86f69ca32abbca3b2934be5063bd6b65f96817d5248df49fdc3daf99740241d2d80763f6a6f7c578d57827886ec5513f3da4d4fa30f4776b3a598a9f9ee6337f4f198597f093be704d76a7e557dc1001000c3d6d8640a5e68dc1628df821d3a79f8ce3c70a120d15e1bc23b191e6a047648d7a2b9075", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f104fd43f647cf48bfa03c2b2a6872b15b37af0458c377c74f4ad739ad26066de4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84187c77ca06c68e3a239e6fea37385de49c0e93bf09ae3a990bb588f1e26193612f65ebf74c8b951b09da599ea3d6f486010b8cccb0a2142ec39aae62c1ca3e7"]}}, diff --git a/txscript/data/taproot-ref/b7b1691a7efc0fca08ac5b931ccb3dbf5aa891d8 b/txscript/data/taproot-ref/b7b1691a7efc0fca08ac5b931ccb3dbf5aa891d8 new file mode 100644 index 0000000000..16277c0d02 --- /dev/null +++ b/txscript/data/taproot-ref/b7b1691a7efc0fca08ac5b931ccb3dbf5aa891d8 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5301000000c8edde918bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43e01000000b111da8a0260cd5e00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac99d03b50", "prevouts": ["5d9f2200000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327", "3afb3d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_bc", "final": true, "success": {"scriptSig": "", "witness": ["f5dc1e9f5a2e36ac4c1d6ec4efe5c9ba754ed1eca39316121f45cfaa9e9393e6aa45ab57aec86393120554af15cf16633ebf8683f294b241ddb9349c2683927101"]}, "failure": {"scriptSig": "", "witness": ["95f49ff7c5d6609b50c638245a04fe676228f552aca436297f596b9c7ae88f49d470cffa6ec0b8a5658731c9d527af5a8c5070f2c37dd8bc297d0976552f198bbc"]}}, diff --git a/txscript/data/taproot-ref/b7cc907a8b0d3c3e1994be68a40873b4e99a5f78 b/txscript/data/taproot-ref/b7cc907a8b0d3c3e1994be68a40873b4e99a5f78 new file mode 100644 index 0000000000..65a3328c56 --- /dev/null +++ b/txscript/data/taproot-ref/b7cc907a8b0d3c3e1994be68a40873b4e99a5f78 @@ -0,0 +1 @@ +{"tx": "2bd6955703dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca700000000c8472f80bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4600000000d13b7096bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf22020000007262dfc601ef371a01000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac991f5956", "prevouts": ["846a520000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6", "8cbd7300000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "3c5a750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_de", "final": true, "success": {"scriptSig": "", "witness": ["60ee1849f70397dd53b2c5014afd28ac9b5168cb4fd39d9cfe2a33bcb509d273118e3cd069227e56503feeeade700105f347e8f4db802570c9b84f37bb349f09"]}, "failure": {"scriptSig": "", "witness": ["811911d8cc800e5bac115ecdd09729f4ec4055b4c97e67cb4b609bbb718e373cf0ef14f4c237699562e12211b9427860736810871689943baf1238885b4aa45ade"]}}, diff --git a/txscript/data/taproot-ref/b8079c5bdcff63a0f477e2f79dd8aaf4928abda7 b/txscript/data/taproot-ref/b8079c5bdcff63a0f477e2f79dd8aaf4928abda7 new file mode 100644 index 0000000000..74eef9fb59 --- /dev/null +++ b/txscript/data/taproot-ref/b8079c5bdcff63a0f477e2f79dd8aaf4928abda7 @@ -0,0 +1 @@ +{"tx": "83cc59aa02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bca010000003af476dbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc6000000006aef47a201686f3a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac94020000", "prevouts": ["5b6a1e000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "26871f0000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d3aac2ee03ff761670d75d570c1e6415f11113d875e7640d99f370f2f823c02e22a66b502779d6b233f9a5a075cab3b2a5d3e595dfdfe607248b2d2d8734c7b9f4d7ab890a2001a7be6cb25cf630fcd24657943ff80a7c5a11988ecbf9e80e4620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360c9e55bc2fe3ef8dfdc81a5c5017743f46c247ba513700e3a77c0392e087a2b01863a41bc3dc2a7aa524e62e66740ce82713c2a995d68e9803c1affe373c89601029910a453e765cd82c29c3b576a90579a453f3a941b6b6175fa922e9a13196"]}}, diff --git a/txscript/data/taproot-ref/b809617c671f07711eb77d11353900df3a1020b0 b/txscript/data/taproot-ref/b809617c671f07711eb77d11353900df3a1020b0 new file mode 100644 index 0000000000..e100c8f0cb --- /dev/null +++ b/txscript/data/taproot-ref/b809617c671f07711eb77d11353900df3a1020b0 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be200000000ee786e5160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bd000000003fc93dccbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5c00000000b8e3e08703aa61a2000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a678fb6231", "prevouts": ["1b322300000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "217511000000000017a9141a56e0fb41afaf4b9e6feff1797087c69015162687", "f93a700000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["7e4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4efe8c29822d261ccff72913d153de8b886275dc8d15210ffbb43fd45d8b4e8e401215e29d5d13de3b6ed62165bc3378402ce71158bd1208562fc299f33fc22fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}, "failure": {"scriptSig": "", "witness": ["4c527e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93623f8fe7108d8d2644871df6900a0fe81471c37675c8944fa27134bd5cabedd2fbe9bce0da1a8e0eb2f55600b1edecb05394963f1d059e6505f0ccee9d28b62f6faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}}, diff --git a/txscript/data/taproot-ref/b83c1c0b8c3121745e8e5a5de023dfb379736329 b/txscript/data/taproot-ref/b83c1c0b8c3121745e8e5a5de023dfb379736329 new file mode 100644 index 0000000000..1e4efeda6a --- /dev/null +++ b/txscript/data/taproot-ref/b83c1c0b8c3121745e8e5a5de023dfb379736329 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45c000000001eec319bdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc6010000002d1bd40e03dd94810000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79633219028", "prevouts": ["7cdf33000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "d3f44f0000000000225120d1b91456e68c356a2c859a7d0862df581c6fe76c88121c19c4713ce29cfc8e45"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936050e4717a932781b58420bc98b1449b462749c8b90f030d521274e1d9d2820a1"]}, "failure": {"scriptSig": "", "witness": ["6aa5616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b83df399d9754f536f1c099dfad005119a65be7a b/txscript/data/taproot-ref/b83df399d9754f536f1c099dfad005119a65be7a new file mode 100644 index 0000000000..c413f3467f --- /dev/null +++ b/txscript/data/taproot-ref/b83df399d9754f536f1c099dfad005119a65be7a @@ -0,0 +1 @@ +{"tx": "32272e2d02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc400000000cf2c1cae60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d101000000bff585a60172ae45000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69d78181e", "prevouts": ["f8e8500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ae000f0000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902fcd5ccaac3277274c885ecbd13cd7175500623b9fb97ff2f869e2692422865ba8426b29a2035ebbea3e832e99a94d94e6dac5bdbc1bb42d9c1f8f70400fb21cc130256499e4516eaa82142063a796eeb2961ffc895a7b136a5e0a43990d45691af70865f1ab456e27d4fe486fc548bd83dadbbc70e68d20f6b971256042465618655e7c3128ecab20b656ac884fd444341babf56f6436069541e0ce70bad083ba2bc3a792bd0688f057880b5efe97e51cb8a0562d4aa9f4d93deb74dc24dc6b8a88657914dd12b864c65b954fa26ea623a471878ebef7d6420b8267ca25142dcc545e12ab34bcb2361ee6170a765e7f2abcc14d4e7b587f72939be775268ea88b4b29b0c21cbad0972f1bc16d4c28a6e289ecbb271faba2a2245f65d76a07196fad19ad8561f01a07947dc3a2b088a66d47311ef80ef347ea40352715d784a3309100254a0e607c7bebf436a857e780cc8aff08b6fbd33d1b78fe3ecaa99a7273933c5125817bc39e080841a5c93f5cd22394ac57e834a0e263e30cbdce9b99cd5c01b5e49d5047c8d03003e07b7bb4e189d092fe76f8bb326e4ffff6b45daa5a555900a9524fcf9507f09c5a787d85dc604917ee8730e63c521f4255d09fdaf339a7b2ea221d76d6a442f139cab05efde25c3eaa2d2218a990a29644f68678fa12b803c4c39e21d4ec8d1610dc699e25cd509cd581892d63272b5663774b7b20a1a9e53faddbfbfa975", "f77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ab40a058b7c313978774c1555b16602cbe206701d99a72007414dd67b2fb202e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e80a4dc25bef94d3da1f821dff96c297a1e496d55e040bded104527be104f359289411b885fbcd56b4d2cd2e695cafde2fa2de7097172cb34b20e1fb870aea9a6a"]}, "failure": {"scriptSig": "", "witness": ["4d0902aff08fda62482b24b5f32fe34827834434205911d753f2d77ecc56d42edaa6d653bd43e1721a9b1f588e2ae2a1e6d987530d402a1e4d57a8861c7a976b079a283bf88c46aff9e94f08785978372c4b2af5c352f399fa25f11601d6470acca48e4b396d6b79a1209c8006a0a50fbb371065b7caf28c7af6aaa3e5c9e6c4ff2fc88de04bd91cedc9a911c062a1a19c0a3e42c4b04e4cca5e3ef8d64aca722ddbb6c6fbe6349b6e6683e3919869fc14cde247bc557aea4ffd9141a69416aadc45e5778a665bd58ac91b4726726cccd8776dd01a1f88512577b0a9e0e2109fd4c8ddd4c5a61b70909fba5743b5461137c9bf7f4961e4762e797553348b25c97e746f5ee29dd1669bda8c1a024502069815d3eedc9a4457d00c9a070686efbd4baf749a17bde187f70ccb0c2820c3346b62ed6ab071a4f60814f8a4c7a7d18074306a4a7e85ce2ebc925fb8ffeb64c316d93ce453d9a36fc000387761bce43dd5567c6d4e06dc522521b3aa39cea40a1305cb1c77f4a251e46b4611dad3f9af2b6d119b9701b32d6e270b87fb26fc1ec8a83fbeaab7eb1dec8d50ce8a5b63af74852c4896d80e3662b7ca2424755955a9c620a4e854c4bdbdc9581135488ebc3fc902ec5d4e8a439d97e17843e59d495e33c05adf3002788c245e2deb1456cd1ba1c2d10dfd951e5d5149865ee9acb29980b163865388cba2b9d516817e360cb2c76a2e580a8fc5454a05be75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365b7feda3faf3b509a00db86c0dc57451a75b4c8e29704952ed7181b28626181681b72a8cc1600d8047fe8b56626831fcb5b55f7ee61ebb9b8b91fcb4b55947dd0f5943df1a7722c938328966c7e5ac747f85bf050d43cd9195f6df88860ae066"]}}, diff --git a/txscript/data/taproot-ref/b83ffefda146d967a06f51678c18eff540980695 b/txscript/data/taproot-ref/b83ffefda146d967a06f51678c18eff540980695 new file mode 100644 index 0000000000..0a4b3895d5 --- /dev/null +++ b/txscript/data/taproot-ref/b83ffefda146d967a06f51678c18eff540980695 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c429000000006320e29abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5800000000394a92ad03058d9d000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fceb010000", "prevouts": ["57323200000000002257202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "ab5b6d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["dec9becce88c7c6ee39fcee29799b588f4e9694890ad4d72d43cbdac13b43b56712e17786a3b14e0edfc289967f985fcfec313b8d86e770a57ff687c43ebeb15", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/b84cd36f16a07a3e7153b397d87779a08b904316 b/txscript/data/taproot-ref/b84cd36f16a07a3e7153b397d87779a08b904316 new file mode 100644 index 0000000000..fe80906bdb --- /dev/null +++ b/txscript/data/taproot-ref/b84cd36f16a07a3e7153b397d87779a08b904316 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3a00000000e20d6af9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c56010000002af908f40301a1b1000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487363aad34", "prevouts": ["c6e55a000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "0950590000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3044022052f16b724718d5d77b170aa4a0649894eaff50e35b4ba654ebd8133c9d49ccc602205a22bc37c35edbc45a40b447096237ffc711a1d1c5e07f7d78c960db3354688902", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3045022100bd8d09d38b897f1c0801b75640ac816877ca0cc745dd3164524ec5dcf23645bb02200b3ccaaaf17a5c1b60126f10109508e8bc3f64c74993be06e5e97c0df7f1c10602", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/b8500830a3e73890fbb7f1b5e546f8dd9a851acb b/txscript/data/taproot-ref/b8500830a3e73890fbb7f1b5e546f8dd9a851acb new file mode 100644 index 0000000000..5e506231c6 --- /dev/null +++ b/txscript/data/taproot-ref/b8500830a3e73890fbb7f1b5e546f8dd9a851acb @@ -0,0 +1 @@ +{"tx": "e051097e028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45500000000dc24bba48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4730000000064d00afb0499a17b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e789010000", "prevouts": ["24093e0000000000225120c7cc4d9ecf94fd1d6052a234c093a72236440d0ef34d0ac6810605a4931ceb69", "e12440000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "937d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6989904a8cde4fda674e6637e527bd6de2a53b0230c00b4e7a907379bd295f79625eb62ff27a7a3a1f9ea411032fb959ab5a0c50697db7fef72f456b5013f4a62d371a9b01f30ea116c30e8195d2d6eb7c97c8692c0c95de95a904f83b96ad4"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eef80e072d9ae36a55284136a2c9e76672de3126f98fa88525427fae9ded2e51f65737139d8cb51b826e6105ecbce8352aa10f0d50686f2268ca6d7900ff7d4462d371a9b01f30ea116c30e8195d2d6eb7c97c8692c0c95de95a904f83b96ad4"]}}, diff --git a/txscript/data/taproot-ref/b8684e0746d02b30dd7444f365d9552810403e85 b/txscript/data/taproot-ref/b8684e0746d02b30dd7444f365d9552810403e85 new file mode 100644 index 0000000000..94782fc4fc --- /dev/null +++ b/txscript/data/taproot-ref/b8684e0746d02b30dd7444f365d9552810403e85 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46d00000000e4e24797bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd0010000006cf86596dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbe0000000039bf39d9014d7b6700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5e010000", "prevouts": ["b9ba3900000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "cd767b00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "7a8f2100000000002357212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c0366ec45a9d9bc801592451e6399fa02357b8334be28646395e2ec94ddeb39bb1543ca1584ea503ac3e69392f5078ffd6b6e91116d56d4435edabf7e60c3346210b38210de6eed18078ec7fa9def7ef716a428e93131bd2794f7c122831166ac03a540c31f8690e86784c9a52b0566b025d98d660ac37324cbdd21cd10c5515324223f91f2f2364f3b9a161cc8d201503f97a8a087b890961c411eb315bf828248be007511906992f2eff0c0f69bfaffe8edb48e706bd837eb7a12b0b5464657b0d4d6080cfac16d6ab7b26f7ada4e39c077b4e5d36ce06ff4de1b5361c1db735067d04aa8f6a550285f3785440f394eb3c5b987c7592af4161fe625562d267754e69cc133001d3f3fff9868fdaf8f671140f32e95a6daf081916d95d71c134070bff5a89b9d3b347bb83f8e5d60b6c78b7be40ef0eaea57ac7a4ac9ccece84d933812ca2e8cd2b99f18d74e69090d07f2bc3dd4768df412c1e22b7cd51c4a1660cd7dcb23c94315b7b5fb392c72bda8af2462da7d0b12db581ec3bdac5eacdd03f5a664e7bb64b6c1a2cd4464538a2969ce7c8043807d16792880a2c26b4262aa814ccd540735f14795a3328e4ffc86b95c6c68d71b197272c7a127bf23fd3a7edb03dc474461bde9a1ae94e881ebe8fef3efa2545e93e734fe9377465ec16a3c1169b72040e1594a4249781f8b93bf68fc19d06e27b6e13c65d5853ff89bd01f48f0849c5f667f675", "a87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082337e31cedb20dd0ec36f43f7131008eded9387a241f89ca892d220549655a6e95def3d75afa0626f5ab572f3c9ae49b6567bf85ec43d0b3933062a3ad8b1e492"]}, "failure": {"scriptSig": "", "witness": ["4d090250d67d916710fb89098556f00026adf7b864251a16d2cb7b2d2b61c409a5a4d80260cc9c69f755a8be6ff363326b30e804216b940723a2db3e4c66a11c02beb83b3f4eb3bd7defaf0aae6cf6e1ddeeb1d12d32da2654d1b983f1e826d0733ed6db62713ac19998f8cf6ae472b5a1b45de9810e548d9ed7f3019581983ebc882a75e4d3b31153b28bde33cf86d8a5ab5360ee3818747f452128d16f2886535ed99bff3f262720527fe8628c3c9c966bedf38180ddfaa743a58b96195e0fd2389d284d15bf4e75c28759bd80457c4b3de89fa6a6751a888346094a99479cb9ad620348f838fd3648154f1cb56140018031883614ac7f7c2e0d052ced1f65223ce138a2170f221fe0b6e628eae6c309db58fffea2c9ed23f787951fe32e37a24c02139055a8004b8df1faf53ae69ca059d97345aedbad464cb1d383be4137ec884c5b89ad8be4c74710a3a244d498840b4effb5fc489d1e06b40d9f8639ea2dbaf645af36f6c0076bc791245a6a26056653019da3e004a424dc02aac1fd8491b451743610b7d33b30f841a3e4374acafe4a49e914d111585d7ee95f350d4bef51d1cfa650d2a031b57625db0fb5f8403829c1ef4b1626f0ad61b95200cb870b71fe93f7e118f1254d918268b1b76519a5fb06b17cc111ded39d4b91d12d5dd38c46cdade09bb546bbcf073cfccb0a37304799665f8bea124ba6c01560e7a1184f237b7bff1edc1340f17475", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366970443a5f937fd7e30cf678e864feb942aa0b5cd234984b56eed725c04cef145480c0b3df47fa838c1e54894d9f77b7e2e8bb4e3c514b095e8a55995fa5d8569e26d26d9f798657ab1642d8194f1f5dc9158412142f65824f82701f20125ac7"]}}, diff --git a/txscript/data/taproot-ref/b8a16da4c5a5e56d3c75e8933ac8d444b9d06ecc b/txscript/data/taproot-ref/b8a16da4c5a5e56d3c75e8933ac8d444b9d06ecc new file mode 100644 index 0000000000..cf5a5ab353 --- /dev/null +++ b/txscript/data/taproot-ref/b8a16da4c5a5e56d3c75e8933ac8d444b9d06ecc @@ -0,0 +1 @@ +{"tx": "32a22d0702dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2500000000efb94c898bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46401000000695cd28101bdee5300000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acab3f1920", "prevouts": ["d04b53000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679", "5d2f4200000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "537d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93665ec05b081d8cd7cfb81d71467256aa2a6894d13c77a9fd61c7ca1fe9e406c9b2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fde150f8c7b4812d3362c6afa34922f3b5cc4b63cc9e98285537a088f4a7fe3bee"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829a54256964294f7e46fe5d25ab3411c34d3792ff29ea326544b7c68695f53859e150f8c7b4812d3362c6afa34922f3b5cc4b63cc9e98285537a088f4a7fe3bee"]}}, diff --git a/txscript/data/taproot-ref/b8a400a5412cc152b17a2cda851c5874dd5ead2d b/txscript/data/taproot-ref/b8a400a5412cc152b17a2cda851c5874dd5ead2d new file mode 100644 index 0000000000..9acaab3d6c --- /dev/null +++ b/txscript/data/taproot-ref/b8a400a5412cc152b17a2cda851c5874dd5ead2d @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bae010000006b85b084dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1c020000003e333c8a0305983e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7beb20230", "prevouts": ["9b361f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "07072100000000002251205109082c92be6cdaf88bccd1fbf3eb83cfab83a783afec3533a63ba21c303957"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936354bdfc687dcb90cdaf5d25b86065c592329a4749c4c36a0ad850fdc148b768f"]}, "failure": {"scriptSig": "", "witness": ["6a27616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b8a97f2ecce17499487b6afbfd74dcdb69711ff3 b/txscript/data/taproot-ref/b8a97f2ecce17499487b6afbfd74dcdb69711ff3 new file mode 100644 index 0000000000..d2f660e889 --- /dev/null +++ b/txscript/data/taproot-ref/b8a97f2ecce17499487b6afbfd74dcdb69711ff3 @@ -0,0 +1 @@ +{"tx": "7f7876df028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4830000000034c2a7f160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270da00000000bd4927c901e6090f0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb48a7a2d", "prevouts": ["7e07350000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb", "36b70f00000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e64c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93623815ccbf6fec00b3e507aa7d5724ef597227ebd84c2b7f91468956cf3ee8c66d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51575d1df7a3e4c47ed4bae99c3344f7d42d0c4d3b112e8138771efc2bc74e29dd3ff737734404bbc9015f34371be38b9f5376f1a60720e7cf7da81354011ad4f7"]}, "failure": {"scriptSig": "", "witness": ["4c52e6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93697a95948ed2e3cb613b3ada11a161da3add6b7c74ec133d99efecd0d159759ced300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51575d1df7a3e4c47ed4bae99c3344f7d42d0c4d3b112e8138771efc2bc74e29dd3ff737734404bbc9015f34371be38b9f5376f1a60720e7cf7da81354011ad4f7"]}}, diff --git a/txscript/data/taproot-ref/b8b534195cd5db1dd0cc83d99d7face7ebae029d b/txscript/data/taproot-ref/b8b534195cd5db1dd0cc83d99d7face7ebae029d new file mode 100644 index 0000000000..fdc0be032a --- /dev/null +++ b/txscript/data/taproot-ref/b8b534195cd5db1dd0cc83d99d7face7ebae029d @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705c00000000fc3ba74b60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270360100000034bc366cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfa0100000055a193d8039f024700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca335554b", "prevouts": ["c58a11000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "75690f000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "91f92800000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6abe", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f2d5359d5c824637daa1dccfae2526f7581d719b807a72f9216dd7beac93c786d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51f60e2d3154f769650886384bb096233f0069490aec77c98efe910f3ad816f81d7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363048c6f46b8964ec3ddca6b987410b71b075e8047b63352cf4d6b057f019c8edf60e2d3154f769650886384bb096233f0069490aec77c98efe910f3ad816f81d7a9dfad218b10cddcf05e9e788f58784bb5d8eb58cc0f6cfe4d23ba63d85e381"]}}, diff --git a/txscript/data/taproot-ref/b8ba77481215495fefc3d9c89e8e4251b1514f9b b/txscript/data/taproot-ref/b8ba77481215495fefc3d9c89e8e4251b1514f9b new file mode 100644 index 0000000000..5bfe2ad36c --- /dev/null +++ b/txscript/data/taproot-ref/b8ba77481215495fefc3d9c89e8e4251b1514f9b @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270490100000013ecb1ea8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47c0000000014f64124025d7c40000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acbaacd11d", "prevouts": ["250d100000000000225120a2880b97adcad5e9d951ecbfc4186ac77c307365c746cd6918dba256e34886ce", "13f6320000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e468", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93632e765439daa048bb33f9db790a8aba9692d1958e0de693fa6e1c64f973cb8f2d53bd36d32adc19f711473d01abcb44e7ab561baea4d664230dfa9381cfa8f4828a09ca0f6d73d82e88e284042e116dab9fe2cbfafc110f6c0fbe5b2788367c646ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51bf410b10c26f46641013d73a91af66d7632b0672c14a8d3b0dadcce48aba69ffe0b789927f620aeddbf74aea18c74264c468c5fe823a741d176e0a42636f367e46ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}}, diff --git a/txscript/data/taproot-ref/b8c25103015cf79375d6f576186c9bf014842e27 b/txscript/data/taproot-ref/b8c25103015cf79375d6f576186c9bf014842e27 new file mode 100644 index 0000000000..7ed6a8e98f --- /dev/null +++ b/txscript/data/taproot-ref/b8c25103015cf79375d6f576186c9bf014842e27 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca9000000009dff9cf2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8e0000000003edc09f0396a2ae00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689872927853a", "prevouts": ["872f5600000000002260202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "759c5a00000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["dc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366c8229ef6249eef7d294f23c9bd7511150aaa9bb9283ed908def3a40c2c66d128080c17c1a9ba5ea8a3780f9d0897aa41ac6e03bb9fc27a0b4027847c33ef9f08f84e1cc8430872045fc695723e7e8ea88aa60745b893850b41017408051d8396d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a38e917535475cf2110d0b0ae2ac5bf0f6bfd0fb66e9319f96694509bbaa8cb206d96bf27adab25b1c800ec6de9073e8fa8f2a3b567072b632cff39ce61bb3673"]}}, diff --git a/txscript/data/taproot-ref/b8c863f970b2f3c39e353171b5902be0355002ed b/txscript/data/taproot-ref/b8c863f970b2f3c39e353171b5902be0355002ed new file mode 100644 index 0000000000..606db95a3a --- /dev/null +++ b/txscript/data/taproot-ref/b8c863f970b2f3c39e353171b5902be0355002ed @@ -0,0 +1 @@ +{"tx": "b76923990260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270be000000001e0361fa8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40c02000000c541bcca04e7f550000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987fe5af33a", "prevouts": ["2373110000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "71844100000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ed7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93653d0566d70d930cda13d1b062e2c88465358c715016c982afb82a06e0ad8ccff998d6970ca8674a6d6a6636f00d706375e44157ef6300dc02db98f8ce0d082c1d19f2c0f6744ba7ac1f5ff1e4bbd0a31d1cdb1f5d58d1dbc476492d0098121b5"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362a8804e07b9224c1961ba20baa4cc70c8c0737ff46ed8d377d0925d64085806f229db830b5291510bfd4e55fc2f3a45cfb4105ece0af57cbfe0942d597b32d0c27d2631c3cab5fe643277004a2e6838e79a7dd6765c91a13be066042b33c17d3b131de5807af4725e3fdc8c81388bc895736ddb6e799e7163e8586c833ffc627"]}}, diff --git a/txscript/data/taproot-ref/b8daa1c785e390cba67ca10da7ee578c00efb805 b/txscript/data/taproot-ref/b8daa1c785e390cba67ca10da7ee578c00efb805 new file mode 100644 index 0000000000..bea27d1084 --- /dev/null +++ b/txscript/data/taproot-ref/b8daa1c785e390cba67ca10da7ee578c00efb805 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbe0000000064ec2af8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce201000000970d9888023a6b9c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874e000000", "prevouts": ["24ae4d0000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2", "a8e9500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "487d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ebe5e2af3a3c1a6754948d639a5542927d59c509fd5287d02d091c2a39a812b527da89940c9c2be3d3cb1ea9fc374137a74dc3bafe909c68993f298761996d666"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936379a98b85b817e20bc3376f43a8b74803a7c6b50cc59446ffb1c9510b7649235edf94ae33f5606292dd7c11b30be28c4e66005bd3313ca427ad5ed734d53452840210bd7db211b82a407c19f9567cde5a01f8f2a3c3dc032c7ac21169de78447"]}}, diff --git a/txscript/data/taproot-ref/b90034052330d016cb6261caaff33ff9b2007d1d b/txscript/data/taproot-ref/b90034052330d016cb6261caaff33ff9b2007d1d new file mode 100644 index 0000000000..15e749c0c5 --- /dev/null +++ b/txscript/data/taproot-ref/b90034052330d016cb6261caaff33ff9b2007d1d @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfad00000000a2a222a28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40602000000952b84bebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0c000000007b93a1dc01c8cd08010000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487078ca733", "prevouts": ["be076700000000002251206e4088e3ab3053e34fa9f42678349f51acfd745de3b6b8ba599a97db56ef8c25", "59dc4000000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "0d6b780000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e668", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363c8787110c399dd6a0c6d756e60eda0cff5ff48042b3961bab6f48a69e180bd63f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08225f2fc2293577bab1371dd996050d2a4e8a01eb34ee2db6c09974277461b3e6691bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93615e2e378f02ea6f7ce0cc7f488a9f895da61864d8652fb9a6ebeb0f0a3c3389abd4c1b076909910aa73b6afb36aebfd26014933f900bad794466c6fcd625cde53ff737734404bbc9015f34371be38b9f5376f1a60720e7cf7da81354011ad4f7"]}}, diff --git a/txscript/data/taproot-ref/b953ae08ca074cfcfeda2be630b7eabb0a0feef0 b/txscript/data/taproot-ref/b953ae08ca074cfcfeda2be630b7eabb0a0feef0 new file mode 100644 index 0000000000..a95b12247d --- /dev/null +++ b/txscript/data/taproot-ref/b953ae08ca074cfcfeda2be630b7eabb0a0feef0 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9600000000634b90858bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48800000000344f78fb01beec02000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6c14e4b3b", "prevouts": ["520829000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4", "bada40000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d47d6a591cabcec873405f70266ef9b449bbb661e70e913f5c6f7abacf68414d3da7f20ec44ea0c236deaffde6efab934d360adb6b1ef008f271a526ec7cdba39048511e8e7c789ed514f9b13c26fe9741cce3b90a661d5b889439e5d7d62c33484e62ad4f4dce8d32582292ffe4d070ec4c8f9d723f4844058420a1d2537a8779fb9a42ce7bededc340d517b18f18dff67f3331aaa53e77c1288b33e0659f28d1436a2dfbcb096f3fa7a9e82e4786f556e1925c35cb013c45081eae57c540ad3cab3ce1c281550896845d8655ab71cdf8a708c06d5e54834baa17056693353b5dc04ae9334b2c10884d411bba0cd4e3fd984fa90f4b1e65c93fd2cb10728f751d98256c54b1d5d60fed0e78dcbd500dc356cdcf890680cb3c77c92e45c4ddd12e63ca3d1030639b0f9d2870e33b774e8d3b66c5032eced1bc99d923efa37b6ff74dffa59a90dedaee32c243845aa41477abbc18aea66fd7d8b62f57cb32be897197769682fb2416e7d5ab926f268d9a4bddef2f123b5f72d6a815e7d059ffd89b1153ff46fc4270b9bb40d5a0599c596362d692c06f2abeea5bb5ba7bfee1ae36fdd7cef72ab89f2e37b666bbb7827241e994666012b80d44990e765c6cb21b75d212e364b854e8ce7e2280710fe693e17eb5c2b5efd090243ca88e975a99137aec767e7b0a8cc26a136a7facb806aa7e36a522d8e37d1af4637583ea07b2aa644956dc50448f9de475", "3f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d04e294f7a5b40072490018d5d8a3de038b17aff9339380d2d4333d5f6423b4d728e192bc5f69ac80b4a6e0537a86a2095372e08a2c76143a8a8a3d0ed1b85bc06da1f6599d7e514a71ffa8a2afff73792fcf1df1b953d2196d009aa835a52703985aa46dcbff8b0495de750bd1afe74a661312f7eddf1146199ee1ea8c08aa"]}, "failure": {"scriptSig": "", "witness": ["4d0902b75caf9c5aa0b18720b832ac4a860a72079b0933cd4aee7f6a42767e6bdc2fb299ff8b15d94cd461a60fcec57a65f88997e2b82088dc241e59c4a30edf5cb9514594c59910600c16b7992eb68858c1d504bbb3f6e0b3825645656b307107a06112a3d7232d92b8aca56de6ead6f6ed4d8e1fd6e97535744f9087b3dc8c69a521e5eb9c7c12c35f98eb5170638598eb057617179b6bcabc45e7e7b88822db163ed9c1eee9910c076bedddbbb32366280c40dcd22de76caa6f62f7db968727e17dbe0fb3bb94e9f6b0d47c3d4bac1ac14dcc7eeca79c000bccf71f1abac60157aee194a9efa8eadf12bf8262c205d2c1dd9b5ff12bcc0b83ca007cfd8515c1c96b8a403b18d440ffa22f7ed5d3b99c0d8288e765d7908bdf22df77246b203a9018cec284205578fe41ca1cc21582dd13b7a60d87c99e18f520ea9a0d13cd471a0e1100aafae7af41c962daed23a3f3cb52f0f42dee62002bcaf208cce0461ec5853d9c80a50469d1fcbeaef6641f7911fa6ba4368bd810e552400de6a60423bcf431f3111c6e443a8450a170bef34eeea444080016ad97b889604296ebbcfb11b9a2102d5905e226c5501c6e27a46661e55da12ac9fcba9749541402f49e73b1111297a618b67bad0e43fdccce6edcf674256a1b4d98dc8a87f6cf67340064ca7a4abfb0b16a69f28accb3299af1f72961123649f74b3c647c06204d6d6a850f6977e60376862e615ff575", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8d874772a13c5a1227fda830887213a5c965a8abbda46e6162f44fffadfc4d1ce03985aa46dcbff8b0495de750bd1afe74a661312f7eddf1146199ee1ea8c08aa"]}}, diff --git a/txscript/data/taproot-ref/b95d3cec25b96ed5bf972cb98ca8c6476eac7630 b/txscript/data/taproot-ref/b95d3cec25b96ed5bf972cb98ca8c6476eac7630 new file mode 100644 index 0000000000..e41ae9a7df --- /dev/null +++ b/txscript/data/taproot-ref/b95d3cec25b96ed5bf972cb98ca8c6476eac7630 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ee00000000e3d0b991bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa8000000009f4a9bdb032cf480000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796122e1a27", "prevouts": ["a2331000000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "dfa273000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["984c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c161624a971c36aa6290c86687ec80062b931dc8c82c07703e18fb2ec2014c60afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a4b5563559956b4521d685614895115ff3b761ab3fb4dd1d8def3bf310bb092b594c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}, "failure": {"scriptSig": "", "witness": ["4c5298", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a12a44ae7bb936654d5435f70f6326205890d9cbcd8f02cde2bb6c76aaa7e01eb806b7a00459a4c1bc30a7ac808d25283aa8d21c996014515e9974f153b7e8517bb22a9d6ce3a4416076bcdc0e15ff24e2eba93ece471e96a0af39f5a01dd3ec6e2c0067d6235544c969c57bb6383bc4dfe8083fe3443e336f29d85bd1c9f087"]}}, diff --git a/txscript/data/taproot-ref/b95e31c70d4e1c7f52eb020450f422dc69f2b3f1 b/txscript/data/taproot-ref/b95e31c70d4e1c7f52eb020450f422dc69f2b3f1 new file mode 100644 index 0000000000..4b6c019bbd --- /dev/null +++ b/txscript/data/taproot-ref/b95e31c70d4e1c7f52eb020450f422dc69f2b3f1 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfad00000000a2a222a28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40602000000952b84bebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0c000000007b93a1dc01c8cd08010000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487078ca733", "prevouts": ["be076700000000002251206e4088e3ab3053e34fa9f42678349f51acfd745de3b6b8ba599a97db56ef8c25", "59dc4000000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "0d6b780000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364b15973f9e600691a7121e5a6d9041a72a23eb89accec8cb085df69123b371a0"]}, "failure": {"scriptSig": "", "witness": ["6a47616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b960c57badc5a9291e8064176397f05700f998c2 b/txscript/data/taproot-ref/b960c57badc5a9291e8064176397f05700f998c2 new file mode 100644 index 0000000000..f2a203f91b --- /dev/null +++ b/txscript/data/taproot-ref/b960c57badc5a9291e8064176397f05700f998c2 @@ -0,0 +1 @@ +{"tx": "5d45ca5a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3100000000f9556abb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bb00000000953fe6a9045d685e00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8eb7014c", "prevouts": ["0290260000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e", "4f64390000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090232a7d9540e819110b107f6806f46a011f436b75fb93fe17e39c8ee0372fe984a240250a8f89e9e33f4d8f379d28d0a1423442646c2fca29a18045f0ba3b2604739e3bcb29ec9009d3f67a34463f4d3fcc99f56cc92487a0a4d2ad91a6342e074ab46540ebcdb38cd9da5e2b50f1201e593a7a47eb4af02f96189c31d0611e0f4f9a8beb5d78214a78ac25272a79c3f8318c263d3d19c2c5a6aeabf5122827819a2322b7f5d4ade23260119c5e270a0d11141999237f190d5622fd5170bc3a5bed81b8419a8ab7f4c20aec0ba572df27723ee8479df0f9c4b5ee02d017790e84df26d1ad350d4828f9a622afb00a4b82ad5f33a878a0156f5e2d8689edddb11fe1a646924021476d4afe3004d347fc7f4298c0627232902d43b1cd8c5995b2d1ee48dca2a3874e61f8a20048fa0ceca86e772781399b118b25ef6f02d353b23fbb6d14779161847aab61803d52aed242941a8c737887347858dc0b97c9e92b9222e62a44ec035e42703218610b25ad1d7ccb25d5f21b06a9f863cfe54f094b7ef8a2b06e02417add8727c34692534ec7d8586e04ee236c8afd05aa2a4096c71e8bca3a3adb1e0f6cc31ee9ce7714929f2510bc994c2eb2e83b59e57f585cb85ac2457f723b5cb2eee76490d7638adc392e71478edf1ca486ad85008ff302d130c2f1a047229bf819f061df89bd590465df3564c81f6f837ac3c461678540a863dc4a291cc14e30a541575", "777d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936241614d3e8cd52fc3453eb56ac2732fb9749715b82b545e0f2eda17e1fed7410da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed76a514a469a046f8a639d1762af89c30ccdce4827317950871fa39f73bf898af03474d1f6825ec143575bd2e16c5d5a5b633189d07c1a3af4de94c30aa06021"]}, "failure": {"scriptSig": "", "witness": ["4d090210c346f34eb67b338583137ace294a1aebed3911dee8c3dceca8e91c55e3627e2f8f5c70edd8c6df28db02a4db35805d8f191c106f349c0d9a80e71616a0d5c21f957ddb16c65f29ab300ef8efcce8c442db76d27ec5d4c89a145cf16781cdc0051799ed1683f30f4efd4f2c3aad0ced47f41090a8bf766f7b0d6d4d27a3f60ef037224aff7e719008daf73a18afd001da1f32ea188f5de3471ec641cbe4d4a2eaebfd4523d17d3a90136887284082386956f1fb9594b737c3a2e901eff31e0edc7ccf6ab28f595a736b0a4b609934b77ecff3b7fd2eef0753758fef7867c5870b42f68e589d325189b24b6ce8cf550acab48000c2f0964412c086767cc9f7060abc3012a108d9c875325f83feafc4c43b4946814fdedb69fa8353bc65b9ca68fc553ce7e4f604f96e8ec2f5e139a759c2937486074b4282bf0ede4ff90ee41678bf23198dd93dae501abc1860a8999fceaec36e55917c79c2aee4ef98e0d25d544879340d06bea0ac4bd5c247cb60dd49ab4082b6a14742fa85dc3e842319e814ee5cbc09903cb53ed210dedb42abf09d3739d2152b9d1c141011d341a02605dcec05c6fd5144ad35d88719b81df2effee83878ef28572a03ce12c81ffc6c31591bf8beca586461da8b6eb5ba416a4c52fe17ed9be78d799d853cf5e3fffd80f46519a2f1711fed22e1ad91bee20c0c6ba9032ee7a127fe94bc5153c22b28371e896598908f4886f775", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8afeb4bd46271bdc4aa2a06eff134ee0adb3f92d28971d2f43ac771ecfb2750b1f03474d1f6825ec143575bd2e16c5d5a5b633189d07c1a3af4de94c30aa06021"]}}, diff --git a/txscript/data/taproot-ref/b98b3ae70f7b3075d295829a4a779d63ac54efc1 b/txscript/data/taproot-ref/b98b3ae70f7b3075d295829a4a779d63ac54efc1 new file mode 100644 index 0000000000..eb44d8e671 --- /dev/null +++ b/txscript/data/taproot-ref/b98b3ae70f7b3075d295829a4a779d63ac54efc1 @@ -0,0 +1 @@ +{"tx": "dcaf384b02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cda01000000cf8850f6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd400000000479871ed013270a100000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc4ef5541", "prevouts": ["db3f47000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "03855d0000000000225120fc12a8d66cb681b25d9244e35510bfc0dfd4b0ce262903c87a066ca254a38f8e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936651597828edaf1ec5c9dd157a6c1e84adb29e876232419c139df01e87050662f"]}, "failure": {"scriptSig": "", "witness": ["6a06616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/b9c4f033e767c62469be7d0c9837ff7976269c03 b/txscript/data/taproot-ref/b9c4f033e767c62469be7d0c9837ff7976269c03 new file mode 100644 index 0000000000..0c7559a343 --- /dev/null +++ b/txscript/data/taproot-ref/b9c4f033e767c62469be7d0c9837ff7976269c03 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5c00000000bbab6ce0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb500000000c4ee82fc03fcbb79000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f878865e72f", "prevouts": ["34dc260000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1", "8bab550000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "cd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936305e2bbfe940f420c214662e3966ca6ecb30394037d73a78f87c1b0a0c14e367fe052270a8089f5fc5ef9a63e8f4df43751c17d276a547e2cd275b71d0b6242a8fd238d2decf6f7142c55252dfef824eea080278838d8f4f1f0f617cfe47b5d91029910a453e765cd82c29c3b576a90579a453f3a941b6b6175fa922e9a13196"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93679da927ebea46a5f8996fbcb41ba1476306b8185e9784cfd3fab60be6d7447790aae41afa256ed506dae95e698e8dcc0fa26e2618e50e74a83d05bcf51ab890d620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}}, diff --git a/txscript/data/taproot-ref/ba1c9764d8c0c80309b24333c675854c1e92edf6 b/txscript/data/taproot-ref/ba1c9764d8c0c80309b24333c675854c1e92edf6 new file mode 100644 index 0000000000..5bd8d87a1d --- /dev/null +++ b/txscript/data/taproot-ref/ba1c9764d8c0c80309b24333c675854c1e92edf6 @@ -0,0 +1 @@ +{"tx": "88a47fd8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c442000000001eaf11b1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf21020000000137c7d2049d1696000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc370c5044", "prevouts": ["466038000000000017a914525ca05541c81a105639c2efb802eaf5596cfe0187", "94b8600000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bfec9f4a544cac12ec45faee03e073e2ca7a1afd48c2e8b5a3a7ddbd5cfcc3ac9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e8d213d90ee48874bbf2b18160b4fefa78452fd9fac91ad5f640de90a3ceda28c"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e1906c602469d9808f25282c821ee4b4dcb0a7f347257f6810852481d8753948638c14f042a58a31b61c3859e3b726944cfc511dd17ecaa68ed5dba7522a36ac78d53ca9a9f93e78db88a883cc9c42dbf55ad09041fa37b21a93adcd191d7180"]}}, diff --git a/txscript/data/taproot-ref/ba1e6bbaa2a233a2a9e108339e2a03d15db6c21a b/txscript/data/taproot-ref/ba1e6bbaa2a233a2a9e108339e2a03d15db6c21a new file mode 100644 index 0000000000..ceb19b207a --- /dev/null +++ b/txscript/data/taproot-ref/ba1e6bbaa2a233a2a9e108339e2a03d15db6c21a @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3501000000d42eb6c660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ff01000000c3ef7ad960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270af010000003e9053a503f715690000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7a21d363b", "prevouts": ["1cfc47000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "edf4120000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "94c6100000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063fc68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694b89f2c9aa4f05454573899159481db85bea08e9a51a1491468cab82b3ad58099aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4690da805934f4f93e9c0efd4d4edfea04743fe60c173721d1481257c7ee1801e4e0df2464f99a35d5bc9fbf69ae3045675e957332f77327dfd622124d00cb4df"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e979609d128077ee19fefa6d4a5ef99e5cd2ea32c1a2ff3bbea06157366b07e58771b6e792b25070418091d57f3336a76b43209d1f0f67eabea9d94d6d252d60aceb16be1ebf4fc69deaf064fc7bf5d7ff2149818b5ba4c28c799d30ad567cc959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}}, diff --git a/txscript/data/taproot-ref/ba213f9e83bc18ee5d889ce921f71786661cdb49 b/txscript/data/taproot-ref/ba213f9e83bc18ee5d889ce921f71786661cdb49 new file mode 100644 index 0000000000..f1c95891e2 --- /dev/null +++ b/txscript/data/taproot-ref/ba213f9e83bc18ee5d889ce921f71786661cdb49 @@ -0,0 +1 @@ +{"tx": "cdcd5a9802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa500000000b8ae7dc6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bde000000003c6de5f402e5588f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acc9000000", "prevouts": ["a5346f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e224230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_8d", "final": true, "success": {"scriptSig": "", "witness": ["ee038fdd8bc71ef14a370e519b0379c7953ce4f05b4f564315288d1fcf85078e3fd1446e11bbbd68d919d106bee0c647dabcddafc0551562fa8914a65899263403", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["6eeab9143adbb3c61f29938a1ee836c6c0935bf48783c9d794631c96841f2c4ed1c73540ee96b8d3fb5033fa547e225242871081b822556d71ce4f4f75b80dc38d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ba60320519e241dc303d027571c1b6b6677274ef b/txscript/data/taproot-ref/ba60320519e241dc303d027571c1b6b6677274ef new file mode 100644 index 0000000000..74275e7fdb --- /dev/null +++ b/txscript/data/taproot-ref/ba60320519e241dc303d027571c1b6b6677274ef @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf06020000005a8d6e1adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4600000000fc86371d025cac980000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787141e232c", "prevouts": ["22827a000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "7aab20000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "8e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d512a2ca63ffb455d99d5e48d0ce26693d60c39456d7af39366f9ddaeb418e2954f33cd0b31c9bc4dfcaccd89caa263c020d1b70f58e7e0e884ce19a773d6b5f30b2981ae69232c3f6c5ff759e9ad4102f31f3fc5e7a3a4ffd34dce2e2e06026"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045df5339745586104756c1fc6d4b54e2b6a7d81daf8b03d1fc2a4a51881171d1a3099eb053c54d8f72c6d7331f9a1bb3bf1b628df692ad9b7eecd4e01f4a47bb5aed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}}, diff --git a/txscript/data/taproot-ref/ba66a56ebc2679a2d9e33cd52effe2bf5657ba63 b/txscript/data/taproot-ref/ba66a56ebc2679a2d9e33cd52effe2bf5657ba63 new file mode 100644 index 0000000000..978ad75912 --- /dev/null +++ b/txscript/data/taproot-ref/ba66a56ebc2679a2d9e33cd52effe2bf5657ba63 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca501000000580c3db604f64b4e000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce6010000", "prevouts": ["2926510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_80", "final": true, "success": {"scriptSig": "", "witness": ["975cf7e75f24f1001d638322626a92d040e1840080b79b68d55ae4a3cce3e821fa218b0c276e5f0325550959133c82bfd5a0ac54edf7843766a0c1fdcde06ced83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["edfbcf6ef8812f0c9289fef29458750a771593910ee4b3a385ba78c1dea78375289729cd1f265c8e7eafa6f29a70f36f042df16df8506977cd8ed85762f7518880", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ba71d7ae4697eea6a410b7c4d7d542ded867b329 b/txscript/data/taproot-ref/ba71d7ae4697eea6a410b7c4d7d542ded867b329 new file mode 100644 index 0000000000..254cd9b842 --- /dev/null +++ b/txscript/data/taproot-ref/ba71d7ae4697eea6a410b7c4d7d542ded867b329 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b800000000041ad790c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42f01000000ab6dc361024f625900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac25af454e", "prevouts": ["dbfb260000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17", "a8f73300000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090293ef17bf1fa91f04d0b8b89561878205c62e6abcd2848db48e9afefc5692257fb659812a041bc5613b20cae249417bd75457bb1dc9e549e93b90b402126834642811092bd589d7a536f571ac31d065876f9fce6dae907cb4181efde5f99d8e51c342d162246815af7b493a6ed4d86acc6b2927a0959aa7c2ab2077135ec9eb67639fa97dc284ce3e722dd5e32c6fa0c1f6bc454dc738a97bf8a812d4828e77feb15e87c4e02063dfe94552b548d5c9992f442a44dd28ec37fa6e862b3f75a0519de0ffd45bf2568f163db900f89e46e3d9d407cfcc3bdd662c25f9ca03901105754d408f98069624a38fe69b2bafcd0fb55292405a1a8b3bd08da62d18383e4cedd12a6feac39c3c30b40874ddb55f4355a6d35ba615f27641c55c3cf822911649c7d6fab98eab20d0b131bee2a15f61e4f34cb727b3e6126e2e6d3d309d32eeceff29ef8adada28f02eb602d6eb06708bd4dd7376bf5f9b8e5db867e374e29d02974e317fd35b591949c9a9d05a90ea0ce61fc68c7828ff9205226a46822d801c51d2198e0a12a5304fd8b74935b47647c28cfea893f2e311db5829c033b749d96a7bb9c967c55dcc744812156deb0ffe57c1c1f6ad32cc33812f5d99473f7bc77084d5cf0ff7e0e085c549c0986fe2cec4b2ad46d5bde3a22cc7e18a9b7f32a4ba8bed15e19a3a268114d7d3eb562fef99bbf5f3fc454f5db73ec791d612f9fb450ed8261220cb1c7589", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ec9b674b6978b70ca392c5eae7e83a8b3e88bba03d1a19232f64d1d4e5749809886f85ebb300297009aa959255e1f8e976b091c7e06b33477ed400c40a83b4ccb3e0a345cce78c1fe891e9b22b966ce84a8b12623d949f63d5e15e148dd67959d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}, "failure": {"scriptSig": "", "witness": ["4d090252e5575fbdf6faf0ba0191b2588ffc308c433e98a153ed48ffadec721607983a686e8cd9cbae745df144c864eaabc2f3d7d588feb5af050ba4d1335dcf8b4ebe035a5ba4b74f35770175015f0148507128ed6c7e21f71f37d3acbd693251db8886782b140740b74138a6b4c3f624a756c085ee5a8c0b962b3c1ef131c2a17ec2e8cac5927f1613dec9ecd854e3f913c82123e821a42db55211a1ea5df526fbdf273a5d1a33b679a5ce0ba624abc8e6b2b855d820549cfd44af4f3e816bc7135af9891ac6c272c649e5f8b22250c641a41d4d5b1a80c6074a2c99cab8f250cd3e54a0d2d2e9cb58f7f1a052643b037d9fb1a68dd622de0687d989e4d594113136036bf001f70a6603169eb672231ffdff8526d23560ccdfbe6cd6209cf7d2bb0897fe3d5af2c8e40bdadcdc00b6d7d6fc6b7b15cae136f97d22f4dfe2ac1590a9404f5758dac119bb842a62a3a66a66d1e913f2a6425816ece9318ba35cd7656f4fcaa2536c3fe42d793aedec2a9b2dcab6e5c9f57cd7f0ce83bd717292a195c9b3416d6469a7871430654c96f9bca568740f71df574df1eadb78b9de7676672e3e3173785cc74e9ef18097bdff44fa0442871cb992d4ded3ee9613314b8003515a90bb6ee33c1fc1ece5002af9b68de57ee30df851195e757529ee5cd4fb4c66562601829d195198809d7b2d59e963706be83f997056f2f18aa3ea4b353cb870cd989e49a9fd5ea7ae7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936908709641cf32dc4788f906f7e3621a0528df09509ddf1e9982e4479aa4b5d9a913d98effacbdfffd2adbbf71932929e08e9cbcb7e06a345b8d84d9192524cd99d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}}, diff --git a/txscript/data/taproot-ref/ba830627ab470b34e7d889cad07110a91669d64b b/txscript/data/taproot-ref/ba830627ab470b34e7d889cad07110a91669d64b new file mode 100644 index 0000000000..30a405c6ee --- /dev/null +++ b/txscript/data/taproot-ref/ba830627ab470b34e7d889cad07110a91669d64b @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe30100000030bf24908bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b901000000527fb1ee02a3f9a600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac15e93a5d", "prevouts": ["33896b0000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588", "92d63d00000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363886a001b09f635a34304806ead39fcd4b50b9b619b2b6bc0eb87693aaa0e04953249301ac20ee33639c015b4a618b106ac87c8ade2ff7aca8998bda2366a260c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367661e28ff42a08d72c3d32c7503c1e2b25874d2f6a5abb894f6bc68d84afb9a8b553f13873b7614c747e02d52f281322dd98cc8d4ce789920cf593b75c6f05693959a095ba405700a8bdcb88c47f737d45523ad768f5b3698c80add34f2e764b"]}}, diff --git a/txscript/data/taproot-ref/ba88104330b37c0458b14c5d53739d04527f803a b/txscript/data/taproot-ref/ba88104330b37c0458b14c5d53739d04527f803a new file mode 100644 index 0000000000..ab16a80716 --- /dev/null +++ b/txscript/data/taproot-ref/ba88104330b37c0458b14c5d53739d04527f803a @@ -0,0 +1 @@ +{"tx": "da0c3ef601dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b190000000029ce61fc02a28223000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987a512d032", "prevouts": ["acc625000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["3045022100d827c78cc6c8469955f38ebcce0da421cfe33e5917c97c4d1e6aef11cbc613730220504c9adc9e61e9fb428030a8fa6c9a57a778d19c656fe491e342a1dd6a67297703", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "2200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3", "witness": ["304402203d73098df48a8a66efc76370fb5cdf484540419a8282aface6eb4bc971438623022077efe8581f1fadb82fb18b27992ba1ad048d2ae042d4b5902ecbd62b2033bae903", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/baa4d60cb12ba51a47909ac8227ee6df6d0dc0b2 b/txscript/data/taproot-ref/baa4d60cb12ba51a47909ac8227ee6df6d0dc0b2 new file mode 100644 index 0000000000..6b0e3875d6 --- /dev/null +++ b/txscript/data/taproot-ref/baa4d60cb12ba51a47909ac8227ee6df6d0dc0b2 @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1401000000cb03ad92028bf17300000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac3fafd534", "prevouts": ["83137600000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "fa7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366c55d1291de37bc0cd0b0f7c57f56af990eb1972b2f3e36942e3050d61bb245448c1a9074fcf4072701b6c332871422b1ccd41e69925b4b38aff436cff44d889284b3c1002850d4c89a68130d64a5a5ee29d0b1bb458f5120fd1f649ff1c37e66ac496a48f5e08c9a0063585476106fe61a3ff4222f4c7aaafd1f65bf01170e2"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e89ffffd8cde8e3769edf5532f5f6b1952f639561cd4ccd6343a91fb81843409ef1076b289256cd19daa60d704e81db3a39e457bb71d9d0e29c4cb2075820e5e1"]}}, diff --git a/txscript/data/taproot-ref/baa96c5298845a9d61eb221acb395d2256d66ee5 b/txscript/data/taproot-ref/baa96c5298845a9d61eb221acb395d2256d66ee5 new file mode 100644 index 0000000000..5413438771 --- /dev/null +++ b/txscript/data/taproot-ref/baa96c5298845a9d61eb221acb395d2256d66ee5 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127075010000009e5d05f1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0a01000000bbe4edb3018e8b46000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478715087253", "prevouts": ["3e281100000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8", "f75d75000000000021601f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["7eb34c8d1a1387448db057283b1804092fe8bed759b596c8dfc46534dc3d0f1722ba7889f2042d25cb663e37ff265891415c0a89e5b0424d7b65816c493c5c76"]}}, diff --git a/txscript/data/taproot-ref/baa9d2ad62a330c543ec07ad2137ad8de21565a1 b/txscript/data/taproot-ref/baa9d2ad62a330c543ec07ad2137ad8de21565a1 new file mode 100644 index 0000000000..b03c4d6b92 --- /dev/null +++ b/txscript/data/taproot-ref/baa9d2ad62a330c543ec07ad2137ad8de21565a1 @@ -0,0 +1 @@ +{"tx": "a3d01f1001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c770100000035a382b702fba44d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc759010000", "prevouts": ["41624f0000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361a24f92e0fd66692248020bc486fd34464c8d03dbe31b3b0085981632dac5adc074cc5cf84a1d913e1f5647d3427cc0d6d469f0e5b86c78a49890e87126542fa0e1c61743bed8ba943c0dc40e80402f7423773c7111097ca9c5a140b1b3c94b9"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360bc51bd168651c63bebcb5a0fcd6ee1be5c250061dd549ccafb897d97d2a0ffcd13faaaba0b83fb431d1a23feb7d5de22e491a7fb36e5108ab00e1ac0e7366690e1c61743bed8ba943c0dc40e80402f7423773c7111097ca9c5a140b1b3c94b9"]}}, diff --git a/txscript/data/taproot-ref/bab370c81fa011cfbd5f4933e8e203b69b4613b9 b/txscript/data/taproot-ref/bab370c81fa011cfbd5f4933e8e203b69b4613b9 new file mode 100644 index 0000000000..b7c2878fa5 --- /dev/null +++ b/txscript/data/taproot-ref/bab370c81fa011cfbd5f4933e8e203b69b4613b9 @@ -0,0 +1 @@ +{"tx": "e4c3fc72038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ad00000000ef3908da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270740000000074614a9ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1001000000e3195ced032611a5000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487bd79c71f", "prevouts": ["c47c41000000000017a9148bc1125bf4e3450c593a5be1ae9a05461832d39a87", "ad5b0f0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "b47b560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1653142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["56ce4aac32ddc9b0137d682bf44e63f566123fbe72d36ac728c4c036e10f935e932ca13d7c8abfafe7f931daebe311f7a74c17285775adc4974f5334e62efd80"]}}, diff --git a/txscript/data/taproot-ref/bae295c693b97cb9ce1c49550985444f7083bf7d b/txscript/data/taproot-ref/bae295c693b97cb9ce1c49550985444f7083bf7d new file mode 100644 index 0000000000..fe25e83c2a --- /dev/null +++ b/txscript/data/taproot-ref/bae295c693b97cb9ce1c49550985444f7083bf7d @@ -0,0 +1 @@ +{"tx": "c273581502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf30100000056f903e4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb901000000a48e00d50318bda000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787f9020000", "prevouts": ["c6aa49000000000017a9148fdfffe253d045df4a2985902e5465482e50374187", "da125900000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2360212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["beec2376560d540aba6c3ed02d7cfac13e24e9ba2aa6adaab3ea03441f54fe5e25ce154b67c1a0b40e9cd2da65b692918c4773b9676fa8a30c6f734919612855", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/baf106403ddec9a4e35d93e4d7e9c8858a1db975 b/txscript/data/taproot-ref/baf106403ddec9a4e35d93e4d7e9c8858a1db975 new file mode 100644 index 0000000000..10eeca7dda --- /dev/null +++ b/txscript/data/taproot-ref/baf106403ddec9a4e35d93e4d7e9c8858a1db975 @@ -0,0 +1 @@ +{"tx": "c99d682202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5e010000002c0ba2bebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf67000000009fdb47ec02affe8e00000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79659a35950", "prevouts": ["2cbd26000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4", "dbd56900000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93669f2c139be00fa1c9661184516144ce5a6d9ace7645806e68661c56c0e240889d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d513887c728222b860c37147d016a38c71344b48ea7c651274945970f6f23c5cbb4cd941a6bc152cbea0496b075d4b2611b435301778200e60e8b4147cd93749673"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93674f520513e79457cf4495a2bb1d0fa039ba02e927188e1401590d675eb0e8e803887c728222b860c37147d016a38c71344b48ea7c651274945970f6f23c5cbb4cd941a6bc152cbea0496b075d4b2611b435301778200e60e8b4147cd93749673"]}}, diff --git a/txscript/data/taproot-ref/baf7af0bebc3219aa43e93f239abf44c3c75cc84 b/txscript/data/taproot-ref/baf7af0bebc3219aa43e93f239abf44c3c75cc84 new file mode 100644 index 0000000000..96a9a8fc43 --- /dev/null +++ b/txscript/data/taproot-ref/baf7af0bebc3219aa43e93f239abf44c3c75cc84 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f02000000edc4c2a1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7d00000000b6e37ef8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b970000000032ac10e903965dd000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c020353f", "prevouts": ["db0b40000000000017a9147e06846ce22cd5e23f7e03391c0538498e0e18ed87", "234c6c00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "693f260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "215c1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["ca40b7b6930883ea4773d0a5d65f6d0ca782ec6b7a5254db897aef0eb51e0214c651abb28ba77c3e02b75e8110dd9e73eb30e9654b7a3004f962b8bcc1d9f935", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/bb00878c7c40b024bd20fd9e026f76cc0f01bda7 b/txscript/data/taproot-ref/bb00878c7c40b024bd20fd9e026f76cc0f01bda7 new file mode 100644 index 0000000000..ce247e9b69 --- /dev/null +++ b/txscript/data/taproot-ref/bb00878c7c40b024bd20fd9e026f76cc0f01bda7 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6c01000000caf387b6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0701000000d913f3dbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf000000000d47bb5d904ec5a0d010000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acef05f434", "prevouts": ["5591730000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "a0b64e0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "88954d00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100adf0b5c7fce312bfca152bef09bfeffeff54f562953e06529c43f48db67fb4a502206e88b5700e794d2dd7f247a12fcff802052474109397c0fe9c579b0b0091ce4a032102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "483045022100a84ca6818390bf29e4d1994c4b9d9fb4754fb1bff4ece03745f030530214d6d602200ce39a19f127dfcb702bca006eae4b9f4e9e6c3c50b9365433d0ba9ae8d96c93032102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/bb06616585d2cf60ef82187fc0334f6ddea3aafc b/txscript/data/taproot-ref/bb06616585d2cf60ef82187fc0334f6ddea3aafc new file mode 100644 index 0000000000..705aed8cf6 --- /dev/null +++ b/txscript/data/taproot-ref/bb06616585d2cf60ef82187fc0334f6ddea3aafc @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3d000000000652fa9703c1fd7200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acde63cd56", "prevouts": ["7af97400000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "48304502210086ea90cc5c0728dde80728c034b5f5d7fac95f6ae8d2c33709cd8c5e42060daa022049e439d5201732b05eec818672fc4a721a99f33137803e2a8362e331048fa53b814104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "4730440220458935b7ce817cba8b030fc203ea244413afa5c774155a3c8df693aa9e9ed47002200d6efbcf65dcd22b0d73cf5e298b7d89c3171bf7327d5e2710234026ef9616ae814104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/bb0848b612e67f32638209d33374606f9f878516 b/txscript/data/taproot-ref/bb0848b612e67f32638209d33374606f9f878516 new file mode 100644 index 0000000000..b415999820 --- /dev/null +++ b/txscript/data/taproot-ref/bb0848b612e67f32638209d33374606f9f878516 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd801000000872a088c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c418010000008af1d13301eb745300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3d95c32e", "prevouts": ["a1705a0000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "2fb636000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["bd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d6822c3ab459532077d5f4bfcf7544c522d220251729d5888eecbf9f185531198751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d50e634e19498d3396bfa452af2ece499faa564dc4b58fae514f4ede8dd179fb909e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900450cffa7efd13876b56a4fb6d16fe87f2b3bb25d39f5e6fb1dfb5ce04c0283c8690e634e19498d3396bfa452af2ece499faa564dc4b58fae514f4ede8dd179fb909e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}}, diff --git a/txscript/data/taproot-ref/bb213f4cc6adea71bcd254acd7a66de7a21a8fb5 b/txscript/data/taproot-ref/bb213f4cc6adea71bcd254acd7a66de7a21a8fb5 new file mode 100644 index 0000000000..67a32d2242 --- /dev/null +++ b/txscript/data/taproot-ref/bb213f4cc6adea71bcd254acd7a66de7a21a8fb5 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcc0000000071630ddfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5d0100000077f260fc03d5faa90000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df97972236898796000000", "prevouts": ["5be962000000000022512064408326fad1f8311f590f6e6ba281aab75c91070d1d43ff117e995859b8513a", "a8d4490000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_0", "final": true, "success": {"scriptSig": "", "witness": ["d121f7b2fa46772f2cfc578befbd81b504abefd6778e5865b2c5b6755c31495101a118f46f050c81cbbadf2ffa0c9c6b08d2e446670a69be17d0290a8143215d01", "fd57a900020f02c3225354a96ffd477821c7786c05a231b56f81d951b932bd379fad0980", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4aa4f7c8436ca8d8981f6f5734f4602dfc0c44e18db601a12eb96596b0cd18640e63690ce5cc95121adcc35e07ced275f2317c26a179d197ac053960f0f4f147a1cb17023e1e615d13464769edd83781954ce40c3e997c10d9d563131adf152b0b301466fcc99b487f54bcdf71fdafe08c75b498cdfca3ea44357f25a0a6ec1207896441457fd2b6c92ace09ad12d6a1cc6b03727b3353dcdfd94d4fb9d5a4f5d74f2796b98f2c27dc0d9d31f80b5c4be6860f52f23a3a23047d434b27debfdaa5a5078d4000d66a22e2c7b3b94a6a7821f00597277fa5b950f8272c7903fe6ef223bac505f7b73447842270fe9ad944c23bba89cffd18d813eb3c3f2c24dfee534b9c8f80c0cd634f790cfecd39060a61cc867d995e38f8c6a0545cebbec068e85966b052432e8ff002c73077be3268fdff064ea813fbc6f3f7637440b79e3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2f2ca99382fea6afccba9d7672b7238401aa02b3b5b65688095ee89641bd0d65891ad30dc566cd59f177e8cbac8dbc3c996efc49302767d1b5e8302894ec74300000000000000000000000000000000000000000000000000000000000000001acc7e6410c48b21f942db9b7b4f79e17ad6a1c7b719589c08a3fdd6624f970e69846db1afc2154e1c9b23714d29820591741b528a79c50363c0b8135dd178597c6cf129cdfefe06dd1b65bb9b9833c588f329ca16e44f4922ec27e42f62a21a78dc34601aeabf1736ec43781ef95b3e08c43d501af801162a35b11849c3964e7e9cc8b5df612fdcb98046254270875c794792c2f1795b8a882171fccfcf5a3584eafa4dff58e1449b3590ee1f833d71be88bea01fa882e89dd9e6148cf49fd1336381ecd289df25dea3c476bd57aeee10d0a4768f98395d0c6ed4bf356b9fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0e5cd23fea34561ccb7889a4f3b36be34e31b5943a06d8296ebc608c9d6f623f000000000000000000000000000000000000000000000000000000000000000055352ef2f6f7fc99a3c6a206ea828aa4e121e5112a7c5da62760a74958cd5984d868bf4ab5cd3050056231123a19adfc4f0723563dab4b706f9de6e6b5726c807e092985e1a1ee2652ddb19520a43f0cedd86b3699c87c18cc5962ee2f78f44f9e1c3a244d9f6facf3574099b42dcdfffc66292e8ba642d6f825063545a645e40d074afeb4bb9161c3149ae3e5e41690ae09ee6a59fe6ead775dcf89b4a4e29fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4bf5d21a9c1b7fb9354cb3098f96d6935ea68dc47503ca75a2482ff80c6cef1effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff869e424456dfa56753d4e9e148e949946e27dce809fbdae6e5feab58e8d27c1a00000000000000000000000000000000000000000000000000000000000000005022de3fa16ca886cf2a7b7d19434a609127511a912f61d63e9581885edd48b7c8a75cb4c1835c21d3ffdb9773c68f02697633377815b13b49d519281ec51bec0000000000000000000000000000000000000000000000000000000000000000335425ff4e513ffd6c10b8d74664ea3700983559c48b23ef405bc66be8820272"]}, "failure": {"scriptSig": "", "witness": ["d121f7b2fa46772f2cfc578befbd81b504abefd6778e5865b2c5b6755c31495101a118f46f050c81cbbadf2ffa0c9c6b08d2e446670a69be17d0290a8143215d01", "42269ce82f5929d7b42290dae7cb60c53a31b6a7e3b3e6eaea5b5598591109fab37e9d", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6eadac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4aa4f7c8436ca8d8981f6f5734f4602dfc0c44e18db601a12eb96596b0cd18640e63690ce5cc95121adcc35e07ced275f2317c26a179d197ac053960f0f4f147a1cb17023e1e615d13464769edd83781954ce40c3e997c10d9d563131adf152b0b301466fcc99b487f54bcdf71fdafe08c75b498cdfca3ea44357f25a0a6ec1207896441457fd2b6c92ace09ad12d6a1cc6b03727b3353dcdfd94d4fb9d5a4f5d74f2796b98f2c27dc0d9d31f80b5c4be6860f52f23a3a23047d434b27debfdaa5a5078d4000d66a22e2c7b3b94a6a7821f00597277fa5b950f8272c7903fe6ef223bac505f7b73447842270fe9ad944c23bba89cffd18d813eb3c3f2c24dfee534b9c8f80c0cd634f790cfecd39060a61cc867d995e38f8c6a0545cebbec068e85966b052432e8ff002c73077be3268fdff064ea813fbc6f3f7637440b79e3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe2f2ca99382fea6afccba9d7672b7238401aa02b3b5b65688095ee89641bd0d65891ad30dc566cd59f177e8cbac8dbc3c996efc49302767d1b5e8302894ec74300000000000000000000000000000000000000000000000000000000000000001acc7e6410c48b21f942db9b7b4f79e17ad6a1c7b719589c08a3fdd6624f970e69846db1afc2154e1c9b23714d29820591741b528a79c50363c0b8135dd178597c6cf129cdfefe06dd1b65bb9b9833c588f329ca16e44f4922ec27e42f62a21a78dc34601aeabf1736ec43781ef95b3e08c43d501af801162a35b11849c3964e7e9cc8b5df612fdcb98046254270875c794792c2f1795b8a882171fccfcf5a3584eafa4dff58e1449b3590ee1f833d71be88bea01fa882e89dd9e6148cf49fd1336381ecd289df25dea3c476bd57aeee10d0a4768f98395d0c6ed4bf356b9fedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0e5cd23fea34561ccb7889a4f3b36be34e31b5943a06d8296ebc608c9d6f623f000000000000000000000000000000000000000000000000000000000000000055352ef2f6f7fc99a3c6a206ea828aa4e121e5112a7c5da62760a74958cd5984d868bf4ab5cd3050056231123a19adfc4f0723563dab4b706f9de6e6b5726c807e092985e1a1ee2652ddb19520a43f0cedd86b3699c87c18cc5962ee2f78f44f9e1c3a244d9f6facf3574099b42dcdfffc66292e8ba642d6f825063545a645e40d074afeb4bb9161c3149ae3e5e41690ae09ee6a59fe6ead775dcf89b4a4e29fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4bf5d21a9c1b7fb9354cb3098f96d6935ea68dc47503ca75a2482ff80c6cef1effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff869e424456dfa56753d4e9e148e949946e27dce809fbdae6e5feab58e8d27c1a00000000000000000000000000000000000000000000000000000000000000005022de3fa16ca886cf2a7b7d19434a609127511a912f61d63e9581885edd48b7c8a75cb4c1835c21d3ffdb9773c68f02697633377815b13b49d519281ec51bec0000000000000000000000000000000000000000000000000000000000000000335425ff4e513ffd6c10b8d74664ea3700983559c48b23ef405bc66be8820272"]}}, diff --git a/txscript/data/taproot-ref/bb4c46289dbd303f6704b3a08d9e02f4c48b84e6 b/txscript/data/taproot-ref/bb4c46289dbd303f6704b3a08d9e02f4c48b84e6 new file mode 100644 index 0000000000..cd82bd085d --- /dev/null +++ b/txscript/data/taproot-ref/bb4c46289dbd303f6704b3a08d9e02f4c48b84e6 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4600100000096211854dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0802000000ae1def8304d9f05c000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987ce010000", "prevouts": ["77073800000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "36a4260000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902984083f971962febc2c9860df8dbd8699ca3fcec1a80f1b154752afb2bfa600e958f7ef313d6cfd20a5e6f3ae7ab897ef0cfc782af2a4185e6346883b8ae3ab07f3b7efa36f594be222d6738725562c44af05a495355b3f14a2d5bbae2f3e749cc735de4420d6316f0c3efae0eec72db55cce81826f68bf6475a9c7dcbadbeea486777f5a11718fa0a838fb82c89cb8517ae1b716d2cd227b58d496d998d62b53df1303fc734396fdf730d10cc641962e61ea09e4d6d34464cd4f306ea5df12b3f59acea54d40ec78298e7fa8c921b1fb67a81dcbd96681fd85ec7c637a0eca2696d8d48ec5a8ecec13638b37c239cdf1018853ae111b906e75ea9f3e69ffb912000ba2d5e5a7c408366093c7d69511e4e3ad83fe692827d8e0def82629e64d4a378cf59dbd07bc48dbc0281bec4e2e578718c5698079cb66b0c347a5d6ad263863640089ebb391d8e7552d3579ac4e5a3db829ca1f6f7a94127c78e5be2338695d45010d7af7f73b5d6d8c4c74354419b103ae2bbc8e050764e43fc198fd2279ee94901a990f590f1fd27b391451406a68859981f92a53e27860fd49fddd170e06fed02e483d8cdd43c977abb16fa54c4aa85480a8e7d620c37d08e371cb315e8bb1d7e978dc2588dc59ecc494827e98f0fb6621d6c9f38cb8b57eb22215058f4a3a233f6db5cca02e2bb99a1c860fda02f0c096b6610a52c70395c6df0c41e6d4041385ef9f8d46f75", "ac7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365d10d3505502b83681f86b5c9bb7a4ac3d4a0d96424a17c6ae9b696d9543a30775006811b549bdf6e8160f30212dc3199b386e615ec459cd6a9a101291e049b6126490c72a5b15e8927e2896ebf8102d665fc08f8a92e888d3aee8fbb5026d2b"]}, "failure": {"scriptSig": "", "witness": ["4d09026ca67e1918315273ff584130fa87692d8728f8624d2d55e5f24260b40f42677080994722e90ac5823ab52aa7e7b9d28bafb6abb149eb6d72e21c1270cb57dc1dfc89e103ae0ffa061688e495e902f874d94648fb9dd0a863518a6da81b1eb3a1f1a622d1723e78fdef3029478f2a97ce2a9a9d46b4c31449b7315da3cadd0fd1a4ffdcaa3b7e1e201e8136d51c8821a081a2acd8c5d78fd9476e923359fa4e28f1a1f1ac82539276daec1d1d231169c6bbe9d1dbbfdee0f36085e058b5d2a4ca6477a92590978f1a5afd2d8ada44ce79b3dd92a07db1cb614f611302f81e048d618ea1a941f4ff7d429471d69b3887440a89f1be49bfa34590a3c691f3f66a7e3b96d101f882f782bf079616687f6fd478ba0d6b916e33bbf8b816aab4bce598b414d2a08591742ad31c50eb0488ba1fc92e6c49e30074819d97049712c7782df2dc8cdb2c4db2f9b825bf44688efd725ed74987ea039088631433209df39ae7a6509e5303c6e62f02723085ebf6885b7f51c19f8c650dfc000009f82d8454cf2dacdc21c2aaeeabb9839b0a887acf92b672b5f26a168bd84dcef0bc0de9c22151ba1f2f17d75a17b4af6cf0509db86db70b0f15114749c727e585bb3e2812e207e2619e49bfccd6b24dfdd52a91f7e2f6951faaebf2cab15861a575b1feab4e43290ecc5e3d47091aeceda97843280fea4b68c5f6861108b0612826ce6e1d09e65a5eaeb34214d11075", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e877e3df24c23560dc7d916d43eb4e055d70ba52495a1ba5531ef20ccccb2bc5f4126490c72a5b15e8927e2896ebf8102d665fc08f8a92e888d3aee8fbb5026d2b"]}}, diff --git a/txscript/data/taproot-ref/bb4cc97eb2c8303964e3730c003f85cb88a0211d b/txscript/data/taproot-ref/bb4cc97eb2c8303964e3730c003f85cb88a0211d new file mode 100644 index 0000000000..301f66b2d4 --- /dev/null +++ b/txscript/data/taproot-ref/bb4cc97eb2c8303964e3730c003f85cb88a0211d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4e00000000a4ee171060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708b0100000082b99690015cef6a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc8000000", "prevouts": ["f6f17d00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc", "84ac1100000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a8a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a57a923cb0dd0cd2e6b76c48071b6322c8175ad0a8d13c02ef85aecf2afc050a837054ce51ecdc9e3a3777b2a8e44b7f174730ae5a790047b9842df02ff9276d2430956d1468bedd56ced1f149c0a08e9d241f188aa41dfacb5e515f08af1f16915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93619a55fbef70c8b7cc656576193fa332be9fc9118054e5528da63a20c6970f02acfab3477f7b3c3eab66b712f7a90f2a0c89c5ec16767e7d6e87c9be44117720e9b045cee6f1e54629d213b8dbfcd9de8aba2dd7f34fe21c75d81b8576e463c6b"]}}, diff --git a/txscript/data/taproot-ref/bb7141b532ed1aa0b98bd58bc84ec2e08f2e47c0 b/txscript/data/taproot-ref/bb7141b532ed1aa0b98bd58bc84ec2e08f2e47c0 new file mode 100644 index 0000000000..a75fab1e83 --- /dev/null +++ b/txscript/data/taproot-ref/bb7141b532ed1aa0b98bd58bc84ec2e08f2e47c0 @@ -0,0 +1 @@ +{"tx": "757a763b028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c476010000001189b0d6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3f00000000aa93a3e00138d3410000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5f354861", "prevouts": ["8ba4330000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a", "91555b0000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_3", "final": true, "success": {"scriptSig": "", "witness": ["384ee4fb4d496f70a06229e8cd09d2a04dbd57daae4fc7ca23f2a10d0392e3743331b19d4eb71f89acea580f07d154d2b6ba4e689989e2529d80a4f503e64a2303", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["cfee87544a77568c1d7685042c5de42aaf0417477075056b53986d9cfbe0f4adb0453d878cc44b92a126ec9792dac29cc999d0eb2d5b84bb4e1e3ee73fd6f85c03", "04ffffffff20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba04feffffff87", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/bb7fc95bb6e35ae77514934a3e4ffa53a6516e13 b/txscript/data/taproot-ref/bb7fc95bb6e35ae77514934a3e4ffa53a6516e13 new file mode 100644 index 0000000000..2c20ee9185 --- /dev/null +++ b/txscript/data/taproot-ref/bb7fc95bb6e35ae77514934a3e4ffa53a6516e13 @@ -0,0 +1 @@ +{"tx": "7fe69d4d0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706601000000d2634dff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40401000000a84fafc5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0002000000b17c94b301c64a37000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48713020000", "prevouts": ["0a4311000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "feaf310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8d227a000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1c75ad5b0c19c64f5d3a7fdf07b71b1a8f8b99e999958fe2a8fbfcbf733553f9475ca33d7e1e5f2997f74dd285eec8a0e5cba5080c4482d5b595e9662ee4b93be0a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367d0d894f81359a419367fc8ac631148e3eadd39a7159e1d5f784b52cce329de7bc80a3081e946651089c17942e2d2b7e0a2ba8b51162f8e9c4f29cb18d1603310a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}}, diff --git a/txscript/data/taproot-ref/bb85f9b909ffd0ec974d57b8e96a0afe8031c95f b/txscript/data/taproot-ref/bb85f9b909ffd0ec974d57b8e96a0afe8031c95f new file mode 100644 index 0000000000..7c6dd2c7e2 --- /dev/null +++ b/txscript/data/taproot-ref/bb85f9b909ffd0ec974d57b8e96a0afe8031c95f @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701c01000000ec402aaadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0c01000000553296460139f8080000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79629030000", "prevouts": ["dd961000000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7", "f5212600000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "cc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4c890db8e530b3b97e91b56063afadbbd8e6ac326e3356562c0a5ff1591f041d611c8e78922f12cf5b391747592eaf9e84d545161f4f09ddc8c51091bc04ba49d4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9132ef9050946e44b1b7e4a7390d57682430e3f2d85fcffb45dfde53ebbf6533b9ff415677aca4bd8bea8fa89699624d8c5f018d44ea89c1d7716b3c6d0480766d64d66e5a8ef59726e977ff218232e5171732e5d132f479dce590bd8ea056135478fd9f7e773d9cefb2e6c2d4f28929a19e0115b3c92e29fd8719e7d86d1ae"]}}, diff --git a/txscript/data/taproot-ref/bbb302be328567aed2f8a9548699284ede429dc6 b/txscript/data/taproot-ref/bbb302be328567aed2f8a9548699284ede429dc6 new file mode 100644 index 0000000000..e62fc7bb24 --- /dev/null +++ b/txscript/data/taproot-ref/bbb302be328567aed2f8a9548699284ede429dc6 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270980100000024408861bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc0010000009526508501d78f510000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7b999eb5b", "prevouts": ["1e9e100000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "7d097d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_49", "final": true, "success": {"scriptSig": "", "witness": ["204b61452f9fe2fb1644e91d0ca36695254feed8785abd3325db874c547c91572b2f1761d2ffa90b2a93c95a49d286533238f378297c2acb5e2eb7b0755e37f702"]}, "failure": {"scriptSig": "", "witness": ["bbc793ee902203e310aa3b4301fa4d7302103c559626d0574b354dc520c989f3eddb6d8c6718f7bc3e284a4bcd31f3c720f139560e8c6d24897c7a41b140edb249"]}}, diff --git a/txscript/data/taproot-ref/bbc60e9c8fe20335286b1b4c11f2554bf44bde1c b/txscript/data/taproot-ref/bbc60e9c8fe20335286b1b4c11f2554bf44bde1c new file mode 100644 index 0000000000..669b2c507e --- /dev/null +++ b/txscript/data/taproot-ref/bbc60e9c8fe20335286b1b4c11f2554bf44bde1c @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be100000000ec6e0586dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf100000000fd59c1ae0257407d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a666000000", "prevouts": ["82e01e000000000017a9141d8eff3030620b266a8bb5e50900ecd7b2ab72da87", "111260000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21561f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["57402a79b3e34fb69adb8b73c9d4d342a664fac0487a866ab4b684cacd69568755b3fd53b9b7c1c095388601fae8a88f38cb55ad2a3600a606af17cd42a27027", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/bbd6a4aa19b13347c78851a8c39dc87ba2c6cc26 b/txscript/data/taproot-ref/bbd6a4aa19b13347c78851a8c39dc87ba2c6cc26 new file mode 100644 index 0000000000..71a77f5f1b --- /dev/null +++ b/txscript/data/taproot-ref/bbd6a4aa19b13347c78851a8c39dc87ba2c6cc26 @@ -0,0 +1 @@ +{"tx": "53f634e403bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8d00000000fb2721ebdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c86000000001da8c8acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5c000000003f491bb602892f0601000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7ad000000", "prevouts": ["2902640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e4a94f0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "e76455000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c1", "final": true, "success": {"scriptSig": "", "witness": ["d48795d278f51367d376a8c5b3347124429f9a6d16bac06a83ca0298e3466ed83ef0892cf4983bd1b037b3b76124c2d81437b7019fb053841262394ca5b7dfc802"]}, "failure": {"scriptSig": "", "witness": ["0ba57f09640013df5738ef1948c73db63feb1b5219a4a0fb4277720579deebc06826e0fe2630b1cdf70c8e60de098725216694f45c022bd81437ff2fa70674e0c1"]}}, diff --git a/txscript/data/taproot-ref/bc18a41aa534670b3eb06ea552eeaa43a8bf670b b/txscript/data/taproot-ref/bc18a41aa534670b3eb06ea552eeaa43a8bf670b new file mode 100644 index 0000000000..c0a32ca172 --- /dev/null +++ b/txscript/data/taproot-ref/bc18a41aa534670b3eb06ea552eeaa43a8bf670b @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127008000000009184f39cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8b00000000b18bd5d28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43300000000963b85dc031aab6f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7697ea15d", "prevouts": ["9e2f0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "3c0a27000000000017a91486e5fab3386e07350db4c59e442dbaac96c1816287", "7c613b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "235a212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["58175476044a116be4e68d81ab3d7e6c5b8ff3c5bcc29620e7e8706c8e9a04cbd5a2c8424767b86dbba4a5fd3809175bbce64f1d301898a6c4eef159c70fae7c", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/bc44929f9083ce895cef6e68e78c51d907624850 b/txscript/data/taproot-ref/bc44929f9083ce895cef6e68e78c51d907624850 new file mode 100644 index 0000000000..2af5f31e93 --- /dev/null +++ b/txscript/data/taproot-ref/bc44929f9083ce895cef6e68e78c51d907624850 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa701000000f7176d97dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce401000000c70bcbe401c58e01000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ef01641e", "prevouts": ["75707700000000002251202eded5f58e3549770351ff682af5b38d1de1354573522cd8f1060c49001c6d0d", "9d5b480000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d18d5ba7e45c34badc4e90cee645c54b876f7f533727ef4633edf3b7bfead266"]}, "failure": {"scriptSig": "", "witness": ["6a3b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/bc61d16fcfe7499f1dda3e1aebd61701783f32bb b/txscript/data/taproot-ref/bc61d16fcfe7499f1dda3e1aebd61701783f32bb new file mode 100644 index 0000000000..2433261588 --- /dev/null +++ b/txscript/data/taproot-ref/bc61d16fcfe7499f1dda3e1aebd61701783f32bb @@ -0,0 +1 @@ +{"tx": "10ea334502bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8b00000000fb9e01a48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41402000000a58a699c023885b700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487eb020000", "prevouts": ["761e7c000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "7e153d000000000017a914b202aa31930f9cb7b85a632f41f1539f30714abf87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "483045022100e00cb280a9fbc8ed27fbdc1a1684322d90191a7935deff2b23d3029a3742920a022045947575715ad69202135ad7f07f38e1ab9956abd66bf39f11045178c3b3af6a93232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "483045022100eeb3c5cc3dc2659769bb7f4129e3e16cf63cf88bfbaa8793a1d19011c0fa84e0022054f780b1d64e8a4363bba38b9fe081ed29e9ecc52c46d0da13e279bff943328b93232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/bc63fef6a6e1da11f5ad9cdc8c82557d301f7f93 b/txscript/data/taproot-ref/bc63fef6a6e1da11f5ad9cdc8c82557d301f7f93 new file mode 100644 index 0000000000..3cfe6ea91c --- /dev/null +++ b/txscript/data/taproot-ref/bc63fef6a6e1da11f5ad9cdc8c82557d301f7f93 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d101000000275cfca3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5201000000eb0037a702a3deb500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374879c010000", "prevouts": ["c22c3400000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "f5b983000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["98", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936862595c5db495f9659b55a4931c0d6b5790089471348683bf5da646fafe3acb03f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082241df2003654f0fe7fc4600eb797dff990a6f251f130f49fda58fcd5b0cbb08c94c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936135308afc3f1b0427026314dc25c4582126331f233b7d3a6426128e486397ca6241df2003654f0fe7fc4600eb797dff990a6f251f130f49fda58fcd5b0cbb08c94c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}}, diff --git a/txscript/data/taproot-ref/bc94c09d187af83d11bc158ffad91041ae1cccf5 b/txscript/data/taproot-ref/bc94c09d187af83d11bc158ffad91041ae1cccf5 new file mode 100644 index 0000000000..b70e7b42a3 --- /dev/null +++ b/txscript/data/taproot-ref/bc94c09d187af83d11bc158ffad91041ae1cccf5 @@ -0,0 +1 @@ +{"tx": "59b68c5b02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5b00000000757001b360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f90100000023805aa70289676e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc3e020000", "prevouts": ["b8776000000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a", "d7ba0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "627d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e889c476762c97a1f480fe93da3602a750f62c0ee9bbab5a4ae1c7a4219e84dbc327529efe07ed3ec82dce77345a5c0eb368b138839946732056b6a908dbf5f05c"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fabe3373372acbd8f7355a742b339dc4113bb3ad1c8e82e6b2233d51ce74beeba4a979a031634820b293704e38f33c20e5acd9cb2a8735bda71fecc5f77708044027529efe07ed3ec82dce77345a5c0eb368b138839946732056b6a908dbf5f05c"]}}, diff --git a/txscript/data/taproot-ref/bcd93267863bf6c12c490fdca519c9a6fb257676 b/txscript/data/taproot-ref/bcd93267863bf6c12c490fdca519c9a6fb257676 new file mode 100644 index 0000000000..8f49d77a88 --- /dev/null +++ b/txscript/data/taproot-ref/bcd93267863bf6c12c490fdca519c9a6fb257676 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be9010000003b4ab8d18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49301000000992f62bfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c36000000004f65d726032c18a700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5f079022", "prevouts": ["617c220000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029", "dc55330000000000225120884291612dcc22b2c0e2cf19d55719f5f9dfe9624bd12dad94712b18ad4d330a", "c6da520000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09026316b3093e23cff5690a75befd7cff394a52cf7787e8654c43261bad0ae27abfd44e3d11c05bbc6e169291527cc0f4b05c37423d26165a9dbb082ed968bd6c683fe43e0cf34c12bdd6c2bbc66540b69a0ae144094abb7915888128b105a11f4de02353eba4eb2530803e14dfc07ac199002b212a24188b9e4f8cc0627190a56d547ed23a2507013cef2f1b8f2ca05356db533832fa6da70c31c65344a535d09b7f26a8d03f4f8e1303a368401f99300fdb02e79bc4b61bf78bfe9b8c494e3a2ada666c8ece2fb35ab5071fc0e135bd5a9b717c8aed49023e51fb504dfa1acbbc3fdfb6b37ebcf8e49ba646420d4b0e5ff7a26ced95774a58de0f76636f3824a359677420022dd07e81f1057163ee6171773c3a86d4ca42cd18b750cd288ef9d9d22e08f74f2a5b2a1da0b11cd9995d2c8b7b4bf24d72e00e2c5e956f84db761b40e14b0e9ac43d720da48fabbe946a54688f82dea65984a4db1f6ec6a116b8d78936a0c6ed4e6373bcf3a49f293d7ceb52f94dd7b511c5fa1acff68938736200c1e0faa878a51934afc483a4b8fcd4d3b30ff49394a57f9f7285acab6591b4db76c3cb33986af636daa8d12b2422211dc6fef8c7caf1baeab2603864ca5d2f429cfb8961eeb8b5c9f36e0ff50048b7e9181086d23bbafa0454d441c78a210e09f48540414010f0e92302ac8554ccfbb209ea9bb040a91578f8dd84abaabce2584280531ab9001ab3cb75", "287d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082462eebfc32d9e48af9ce92e50735d36faef083a1171bd1899835a9be2fa30ea55b4ae3ee914d52223472aa57f653ca8073aef0e7910b2553778e1ae03228475361bc10490c3b13d9c4f63caefcea4aba06d3a92ca8668ebd56c703a638058ee7"]}, "failure": {"scriptSig": "", "witness": ["4d0902dd9ea2ba14162add791a826aa4d18a2bf83aadd9fa241e5ce02e32edf1e21604725da111dc2871901330a81248307fdae3749a7bb6622be0017b88aecd56c8fb6784b529c18355ca4392e369fe39c4ec899eaebb1736791d517cee8672d415dc4a1a6d1e2a53326aced46560b4e4c6440838be5333ba364661b4b936d2cb5e9092bcdf53a18fbd9dad2873390ce9d70a5897a9754d089d66dd5a6e5c448c677fd45ed4aa4c8399909ac76508f67e413087ec3e422be2c5a6b1024177101929ac548a3929db2f130aa99c640587e909b53345662449ad6051f94665459f1ecf1b5f7a28ba891ee9bb94de167eac25ed1cffa509ddf4dba7c71d2b5161ad5ba24979f00e01c8f38a9f216e350c2462c6d87b9aff146cc2a6e140944830637d9fac839b488eca6e06b4f529e25af9e092cc77422f21f170d94944db3c2083e8ac972d19b6891dc09aa29c75ee1f28d982882675efd5445525666b7279edae27205508c041d2e5ff6beea552cfad24739ebcdb352e511f33e7d7a5d8c2fa68e96136a2e2e7d8a3427f7d6e5aff3f747f06375589b19f0a86d5fb00e280a6c6ff1282decd519207f62ddafa3f14597a506517c5ab0faf16b3f530c7c7651f9a14c93b335bcda499637407f5ddb7c342c3ff36bb6c9ed6144764652eeea2296dfb3621ba5f342c31335ecb60f407a6f0a7efba1966d35f210dfd9ee9309c18c141d4ea62c094864c276de4b175", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e896153d9d0825641ad9dc2862c4b07cae929842b36229bdcb06007f7d47362644efcb4d33820b2e80b50b7a60cab20b6261c566fe48480267b41ad585cde9a4bb"]}}, diff --git a/txscript/data/taproot-ref/bcdee1bf1b6f002a01bcb15b07e1ceef6be9c962 b/txscript/data/taproot-ref/bcdee1bf1b6f002a01bcb15b07e1ceef6be9c962 new file mode 100644 index 0000000000..6009aa296b --- /dev/null +++ b/txscript/data/taproot-ref/bcdee1bf1b6f002a01bcb15b07e1ceef6be9c962 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42300000000b20b5953dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4baf0100000081d35f7204231e5800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fced000000", "prevouts": ["db4e380000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "31d2210000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936efd379c9bd4c758e31629b45da72255f4fbe43a7d074fe2e3f642017976348fe1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045135ed0e678ad02d8eb601751aa1b9acf14c9c27e67d62b009394546cc2bb02284b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936084e1b08cdbacecafb7fe0fc3375aa5281f8489002cb7af196f64e737a534ac134849a28cba9aacf50a598dea57ce3ca224575357c4c8c887db8ba6ff2354671f69ea04c091b2bc3b7c7ae53ee1804d998a6447fcbbef49abb62b7a394c4c123854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}}, diff --git a/txscript/data/taproot-ref/bcfbb863f9751dbc9e52565fa18f52d7cfc28dc0 b/txscript/data/taproot-ref/bcfbb863f9751dbc9e52565fa18f52d7cfc28dc0 new file mode 100644 index 0000000000..2a5624da8d --- /dev/null +++ b/txscript/data/taproot-ref/bcfbb863f9751dbc9e52565fa18f52d7cfc28dc0 @@ -0,0 +1 @@ +{"tx": "9ca1b5ad038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46400000000a64e37f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e001000000fa4a59c660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703701000000d0973dde03647656000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd90b845f", "prevouts": ["ae4139000000000021511f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "4d750e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7465110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["0ec179f5aa9aab3890cce0bd1f48a6488eb01e39c43647fffb3d4715e58914dac41fffaab53dad2b6f3bae7f48c508c1baf0cd580756d01b34db596112971498", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/bd06f79eb234682d1b026c5b614cea268261d69b b/txscript/data/taproot-ref/bd06f79eb234682d1b026c5b614cea268261d69b new file mode 100644 index 0000000000..1c068a07b9 --- /dev/null +++ b/txscript/data/taproot-ref/bd06f79eb234682d1b026c5b614cea268261d69b @@ -0,0 +1 @@ +{"tx": "c10517cd02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd0000000008c471e8b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49a01000000bce4bdca0378d8a400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d4783521", "prevouts": ["59bf6f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "536637000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_5e", "final": true, "success": {"scriptSig": "", "witness": ["5f36dde2a806443a28c62c5e35174eaa03da2458f83478089899614f9737fb9116f0885286c095af83ba64d43e14bb6ee6a637cd0e004f5d2d357c950260d0bd"]}, "failure": {"scriptSig": "", "witness": ["518f7a889717ea067c416eba5560f8ce9405a39894357f02cb803a566343a4b81c7d2df2abcf152d2f9eddf7ddffe779a022c1e884d7114dfe3efbcb0fa6f50e5e"]}}, diff --git a/txscript/data/taproot-ref/bd10e29dccdef5c1bc2693b295ca9c3ee1a5e9fb b/txscript/data/taproot-ref/bd10e29dccdef5c1bc2693b295ca9c3ee1a5e9fb new file mode 100644 index 0000000000..95165104d2 --- /dev/null +++ b/txscript/data/taproot-ref/bd10e29dccdef5c1bc2693b295ca9c3ee1a5e9fb @@ -0,0 +1 @@ +{"tx": "615a5ae8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f501000000cb91e5aebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb600000000f9c80c9a0168a86500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac40208a60", "prevouts": ["8d6035000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088", "62a67200000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "8f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a5823ed2420796b51d928b322338d26a1b11db5af291eb20326b952994336cfce4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e81f261744aaaab7b61bfd8b873ce05c274059b1d1cb072d2d2c67e8900f407405dd5f972b05e2f18c3e7c797b604beeb8879a3af7f1e10968a0ac8aaf9d489fe7"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369dd7d600adfc804e2c499c39b2008fe85e995bb2ca03b92b0580b9363b6d74c2ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457f8fae370a255a677f2f729010dbb329fa966ed9a0dd82e5083dd7ea90426dc47"]}}, diff --git a/txscript/data/taproot-ref/bd4570befca425281b554426e78e723b29b91aeb b/txscript/data/taproot-ref/bd4570befca425281b554426e78e723b29b91aeb new file mode 100644 index 0000000000..babb00e6b4 --- /dev/null +++ b/txscript/data/taproot-ref/bd4570befca425281b554426e78e723b29b91aeb @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff40100000023239086dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1b000000007b8490a101327b760000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79613fcc133", "prevouts": ["b0486c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "47c754000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/1000stack", "final": true, "success": {"scriptSig": "", "witness": ["2f8144252e57e2ff668ec3e4f237ae5840a370eb2f20eb22560bfecc7693b401766c4898f6d52974f274b58378b6c916e297548aa1d170e07290aaaab569f311", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab71800260cc4c45d928081596c283425b86befc4cf867721566fba167b9248f9962f30cd6fbb48af3455887495dfee86d4a98af282e2d7bac6fb2ca2e45891be3a6edcfb587287623b4acd2d694696a040c035c3516bffcbceafadc18652f0116feb5c363cc9ca7ae37fc813d8e2765e43ab73c23e8259fb2c39466019f40dc69ec72a5666efca96852a89de09ab7aeffee4b172252222f5c5e8b6c3009c9df82670f592845de8ccf6ed9bbefe639facbbd54f6cf7f8beb23a81bc5872764b7c781e74d39289c012c9134c71aff2c94895c0ee3473cf7b2b9f1482daaf679eefbf975fb4201e0a2b814c3bf547e47eb4a23672ac784435f04b7336600ec6a82dc784183e7f3cc14811fb1ab50df3116b5ed0f06967eb560f7b9991615332c0ef3606a7ffa22127f3860c477e614ab0b0e9d584049910be53886cda4c5b22b7fece622d42e15d9a09f8ac238b01a6949cb9ab79b540250a90b3fc35ed3b857ba67cba4445e9cd0a613a5e6e514eea7a9da662a1fb003dc0b1555d407474a0fa29f0302a595cadbe6f0743d5ef50dc2b0826f0f2e0e84d35ce4b31a2be87bad075dfde575d48d1eaafa8343c63d6f5425984d2425aca274be02e47a5142e089ba2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["29d1cca0486ba0e3d27e539fe1535f40da0bc2b0cd6308caee1a038a00a697aa82cce42f11a621c5250f59e468c62cacf9e98937655e26a12d7d2c3a5c6e5c16", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad517676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767675757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575757575", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936153e27070caa292b693ba4ddea8b9482a94a8730fa33c3b3b79ac286ebe40d98bb9d4f1e1e27d029ac6035bf75b0bf88e449c1157741f34d74a96fa066585cd40f99255f893286e215f8002b6d42379ac05485fc11174807e91a31d72f31064dc7fa482117f2c5ad3e450de7bb7eaab611474644f8e1f61caa7962547399fb88342aa615c18023bc33d53d99e896741c8b9f092f128901fe7c9ab35d5600ba72a7eb899eb88c356ab781f6b961c1d6de999781ad65362895c26bf88f330758ef0a72f7d97ec67241c9c95fa34ba9ebf41e4b62c116447535fc0507b0528b1da112264249cddd61d525ccd9ae6ce25acc100082ea9e5e5b1e11e9dc8fcb842061b7fe5c11f617e89d9c8027e8e5abc775a151a67e9ae53e23ce27de7d6b1c7da91877336e92e5a41e5368ea40610a7e213130c1b8bf4fefe5f8f2ad406b661c206a1fa3da1ed0725b15b20ccd115752a72fc7118badcbaa8e05d81ae5299a6df4da1ae37bd6e3382ad5e5e5895bec0d8addde979cb59da276665f005ec58aada8e1b94341016fef68bb49557d2278eb05de13cc05cd27e5f6f381c44fd0963b076f28feb26558d4d064770c2eb738b0251c60e0a639239140ddba0ceb61ff7c3e738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/bd4b0d5ede1b9b28ba821e22b21d2e67eb35fb46 b/txscript/data/taproot-ref/bd4b0d5ede1b9b28ba821e22b21d2e67eb35fb46 new file mode 100644 index 0000000000..3087c426c6 --- /dev/null +++ b/txscript/data/taproot-ref/bd4b0d5ede1b9b28ba821e22b21d2e67eb35fb46 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703f010000008417bf8f02fd950f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a66f040000", "prevouts": ["1d8a12000000000017a914b202aa31930f9cb7b85a632f41f1539f30714abf87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "225d202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["2f3970c4d5172c246e2ea982a8bb87c9305b9cbf15d84bfd540d941f6f122ebe2ef3c3501030089b489936ea72e2e92c2663ed2b20a02369ba745daddc80a6f2", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/bd5b6bd1cba3b3c9511abe6e7ba85869cc7271a8 b/txscript/data/taproot-ref/bd5b6bd1cba3b3c9511abe6e7ba85869cc7271a8 new file mode 100644 index 0000000000..b9060f9ba3 --- /dev/null +++ b/txscript/data/taproot-ref/bd5b6bd1cba3b3c9511abe6e7ba85869cc7271a8 @@ -0,0 +1 @@ +{"tx": "0f23d10e02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0602000000ff1278f3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2d010000005422bc8b0191e85c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4878f7b482f", "prevouts": ["ab6a490000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "388f1e000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["80", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a254e7cc6b57a9a94b6584709e7056848938ff7b5d3cd788647ee9c8c010053bd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b44d35a0b3fc5d8cdca17f6fd766b3b7f076a7a891ad519d38c56688c70ff9dbd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93689697d7380f4ad31bdb00c7ff0dc66aa22f6bae188bed2870f771977d2fb8298280ecd46f67705e4464578fc0c4eafd6d20a38d5c68152a49fc5d0c6b2a7c87ed2fecf8564d6a652bf0232997fa790ca314d73b111c417284694cd1738ccb12191585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}}, diff --git a/txscript/data/taproot-ref/bd647eceba7eb445528903854da69225eb46a33b b/txscript/data/taproot-ref/bd647eceba7eb445528903854da69225eb46a33b new file mode 100644 index 0000000000..1707c1be31 --- /dev/null +++ b/txscript/data/taproot-ref/bd647eceba7eb445528903854da69225eb46a33b @@ -0,0 +1 @@ +{"tx": "778899b603dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c95000000007c54b39660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fa00000000b5fe039b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a8010000002867b9b101c0ee1900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2bb98647", "prevouts": ["325f4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1bc120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "09e33d000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ce60b07daa005e7e961b1cd1197a880b0926a9defc492f43af4f596fa4d95286ebf10485a7565da4888b0296454aba30a39a8416dd3eaaebe7fea4a18750e931ca477f7eac6c013e182e33a949b526b028f901138401b50189d2a4f50cede7d4a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}, "failure": {"scriptSig": "", "witness": ["4c52f4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b270b4d2addc31b8421907b0cff80194a5513593e3802bd921239c9c6063ea806bb655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}}, diff --git a/txscript/data/taproot-ref/bd806dc6dd950acd2fb4799772f9284b52b3eefd b/txscript/data/taproot-ref/bd806dc6dd950acd2fb4799772f9284b52b3eefd new file mode 100644 index 0000000000..b9e3d342bf --- /dev/null +++ b/txscript/data/taproot-ref/bd806dc6dd950acd2fb4799772f9284b52b3eefd @@ -0,0 +1 @@ +{"tx": "aeb1416d02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1400000000d2529385dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2f01000000774ad9b801e1a53e000000000017a914719f78084af863e000acd618ba76df97972236898769876854", "prevouts": ["c5d0730000000000225120cd23ad59c6016ee1812d662f3dfa4b488c728badd6e7eac21806d0875fd86aaa", "03124a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_3b", "final": true, "success": {"scriptSig": "", "witness": ["0039ced3a4e60b7417f7be29cfbbedede4cdc075ac33a70fceb0742fcfd301b8947895373ef1792ea5a97a226e4c9206957f21475c0be7c76ca15f50b84840ca82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b0f50233317f8973d9568589c79e87b3a0abe2422eb4e297ee7885dd08ffc30eb3ec01e52c478a1862c02c685da06ff070a3643fea6feecdbdebf802c10d73433a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/bd90aa727c6f46c0b214029c4cc55665db207ed4 b/txscript/data/taproot-ref/bd90aa727c6f46c0b214029c4cc55665db207ed4 new file mode 100644 index 0000000000..6ffe2559b3 --- /dev/null +++ b/txscript/data/taproot-ref/bd90aa727c6f46c0b214029c4cc55665db207ed4 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bba01000000a2f78b97dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b82000000003a48009dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5301000000e7fb77e004cb3fcd00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7f2000000", "prevouts": ["d4b42600000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "69c2270000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "926981000000000017a914971b3e5f9ac480bdcebf6ea71a9fc7de0ab164e287"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "387d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d6aad208f2c248715bdc6adf729c9891a9ee5b587a39890b212ec8f00fab902c542915153386019108494d00e6bbd0a8a4ab824ea9158d8694b82aeea9ace0ff7118923d14a9704f5c6065ead9bf1df659362e443facca38f7fc54a29b18e2b8fa601fcc68a78472d280e0a6f10ace0c22dad9ad93c154f995d1132d7b2f793"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7acf5321bd3c280560a6e93f009006b65547a58d72ede42c89f2f760c3bf47a1d1aa12168afdb4ef286e7748ddb08cf408d85b089f504486378d2bfb535c0d2875b"]}}, diff --git a/txscript/data/taproot-ref/bdb75495237a21c1632a1d8002a2de43c75cbece b/txscript/data/taproot-ref/bdb75495237a21c1632a1d8002a2de43c75cbece new file mode 100644 index 0000000000..7143f19b27 --- /dev/null +++ b/txscript/data/taproot-ref/bdb75495237a21c1632a1d8002a2de43c75cbece @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd801000000e90e4673dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c17020000001ba48a0c0414137a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdbfcc93d", "prevouts": ["a9982800000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "c1345400000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e64c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93623815ccbf6fec00b3e507aa7d5724ef597227ebd84c2b7f91468956cf3ee8c66d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51575d1df7a3e4c47ed4bae99c3344f7d42d0c4d3b112e8138771efc2bc74e29dd3ff737734404bbc9015f34371be38b9f5376f1a60720e7cf7da81354011ad4f7"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bd48f9ec9eb75f9ed6679e2cf51ddd5d7e1370016b30ba4c50a73a51ef54d3d62f8e5029e924e7d935b65d329b99c619ed2851847f9f95e76ebd19c6b8448036f7205f064a536655663faab66bf2e716758d251376e4a55710082b6d7272244791bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}}, diff --git a/txscript/data/taproot-ref/be342f285479f59388d4ad299b262298ea0a194a b/txscript/data/taproot-ref/be342f285479f59388d4ad299b262298ea0a194a new file mode 100644 index 0000000000..98682f34f3 --- /dev/null +++ b/txscript/data/taproot-ref/be342f285479f59388d4ad299b262298ea0a194a @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ce010000007fec828bdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b09000000006f3caee503bdb35a00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac0f030000", "prevouts": ["950536000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe", "2df02600000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902aa8d4b20e90453331fa307a9dce37fc19f92fe8330d08a9319a0a632a1f803039a26fadd5ca8540c6485927fb92a3cbd1e9386c4fdd6557743de564d62b2df1eadaa1f9045a1a1dec1c27f9c04101023b9e199d1d4fd77f9645ab6630375ecc949891f381a015e70f2b098bcb9ca20885a6a9a4468365630b792f17cbf5ab8f2b30cee7603afa29c82e020e47f93d6a67ce57944ee7b4dd94dcdd40f9026ae0a6ca1db23e0f4152a4004cfd3628709f8f9866a495ba9594a16f45f307a6742edfafdf6096c99c2ea4428d14f6d0e940217a090e0f474202570a539316e2eea9d0a8c41641ef66f4c7528eb92a6918b2b61cdd4172734c8e5ea6618e214830fb2a843fc0979887d7181a40811b189b7fd2d6271519b538c91f52f26dc16c3e49241cb5a7354d01304935caaf3d79d4362075a86882c1a4314e438a768019f462228e4940edd2639266cb1078e0636ce3d3e3188d8e2ef57328c192760a51d31944f20dbc4065e55ef8ff1ddbc2cd5ecbede6b2e24cdc902a0b33a41aa4af853beec8ef4a87f2e23a4aaf28880819685ac4c10b785f6772169aa2f790bf00b8b08d85bf9ba6a337ae4d145cb872856e0612daad3654981092b36f65a1ae47364de5243dcaf5e0d703a795538a39a3d8da4fe4a59e4ab087d8e1cc6d65da5b35d9ae981c8562fa5861cb9e8922d1b53178ab7189acb79bbd921a52d3795d62379e07a6e2f63c7094cde4175", "937d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c8e826522e1ca857c1f86e804e4cf6a726b8f2b2090951428365ce33c52bd4d08ba990ecca3673e7fa8965b90b12b1af4599069410dd603db7b6040d82b00ca2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd6f60e166ab3c31d6fe53c0e4c47c333102fdf48f7428a1dab907384d3ec09a32"]}, "failure": {"scriptSig": "", "witness": ["4d0902053ca9fade99b14e5569f3699c39d4fc566908d41c74805e85c43aef4e30e3b54d0abf18e17b3057855519b850be83215fa82203e186d0dea3f734dc965815040aea9fc92b7178551a3cda8cbfeb5964dcbb035f7e341e53912a25a89f174984de82b1ab47bfa1ab6bd36c325201452c580a30f892d9835e89cf4d9bb8d3a69f6d6b807db410552792113af6e1f53f0c86807ca30b823c6403e8f32d8fe2ac4a2da9bdfa2be962ea78d9d581f85390393c9325a94792f435ad3b2f76944f602fdaf0ca1a108579a25c39d0291308392f817de5cdfd1d584ae0873ed718f2505d5964b76dcbffdea5fdfa2b0099ef34ed4f1251c23533bca341429f309499346f6ff23db4de63966a91c68052c064e9be87dab97917f6fd5c468977796278a95d816ed51fed207d05a400863bd35350fa343a95b345285f54ff5b4242cc3709713c313b46e5d094e64ec4b968eea4054e9ccb9fcb44adcf14e379e7c81bf7a5ea3c88a159be69809de42fde5df2ba8f0ca45c7aab31bc657fa1eaf4dd5cec36dcf6c5168c5a60e0597e7ad7725e177969a937cc67d2276ae8fdd9b470486122135695cb66d52ca70287e8a66a833182c5c4e111f0eac056bf99c4bbf2173417ae815f232935684226c0444f52245a82cd7eb560c78febe6d3297cb6d16a65c144210e065987c306d40a78d0f65a1767b46fb7817004298b2c412099008bdb1b1e78ad657cf36bb5079075", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d68141f1158f138a84a3a31991a11ebccc606b1e605d90f596b1985e9f081fd92e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd6f60e166ab3c31d6fe53c0e4c47c333102fdf48f7428a1dab907384d3ec09a32"]}}, diff --git a/txscript/data/taproot-ref/be4056e6d4621f67f649cc023b36d0616763fb74 b/txscript/data/taproot-ref/be4056e6d4621f67f649cc023b36d0616763fb74 new file mode 100644 index 0000000000..6bdb0165b9 --- /dev/null +++ b/txscript/data/taproot-ref/be4056e6d4621f67f649cc023b36d0616763fb74 @@ -0,0 +1 @@ +{"tx": "35adfe970360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d5010000006640029abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf78000000003657cfe8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdf000000008532f2b1014faa6c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4871d222b1e", "prevouts": ["96730e00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "d08c660000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "f2fb7b00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "8b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9ce7b6ad2b5db54c83a35a4c940a86c1986dd4e23a9b088042cb3ad14ebadacda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e86a27b1635c4d20405f5eb1d8e1a675f8ac3bff005ffde1fde7fd53008c3096ff2e441b555c43a724b579c479d380c278f8ccac4217fbfdcb96526a1dcd96287"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8726c3b29d073c2dbcf72056f4f7511ea796d648b755097daf6738edf6332d6d84d7dc2c55a7521ecc297ff7217b922438f95dd9c29c118a2bf5c9e2c8f8c84f32a50ac17afa49989b8cd5fe09550e31f987b9afab4d6ff7fb0ac42074cc4b38f"]}}, diff --git a/txscript/data/taproot-ref/be5fa21ede21c3ae07d18916186307eb0dbd0b20 b/txscript/data/taproot-ref/be5fa21ede21c3ae07d18916186307eb0dbd0b20 new file mode 100644 index 0000000000..925528c431 --- /dev/null +++ b/txscript/data/taproot-ref/be5fa21ede21c3ae07d18916186307eb0dbd0b20 @@ -0,0 +1 @@ +{"tx": "a8b2c1d602dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5f00000000a06df2f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42701000000a95303a40343c087000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7967f000000", "prevouts": ["517148000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "1fc6410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_76", "final": true, "success": {"scriptSig": "", "witness": ["4f8433f2f7f1ba4576941e6e8aec25b95bde8ecfb62e2ae3c7b9d8629519096bfeeffabd5d79ae1fdb64e15529dfd4067e4767d4e0f7de3f01aecb9f39ff606502"]}, "failure": {"scriptSig": "", "witness": ["ef01a51bf5a1a9c05df3f37ef53f59e15b00c57214dc80267d115ce196a1c6306e1ea4d5fb19035e981640b897cfb590759189c0ca1520a4e8261d10642818d976"]}}, diff --git a/txscript/data/taproot-ref/be6dd32445672ad01a41728099573f056d19f11b b/txscript/data/taproot-ref/be6dd32445672ad01a41728099573f056d19f11b new file mode 100644 index 0000000000..eb22035fdf --- /dev/null +++ b/txscript/data/taproot-ref/be6dd32445672ad01a41728099573f056d19f11b @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d00100000061bcd71c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46200000000492c8d5abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfde0000000026f8a34302b303e60000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87ab000000", "prevouts": ["6f8234000000000021551f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "b983310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c2d5810000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["f14e5905ca8541b51d405c71cf3b707b00110c385335fc5149daa88a2cbdee9bf8e885b0d23f4d2d1febc8c047ff70d3e28c87b150df581dfeac0436f45256a3"]}}, diff --git a/txscript/data/taproot-ref/beaac08761cf0537284bd2fb73e52c21bf944e0e b/txscript/data/taproot-ref/beaac08761cf0537284bd2fb73e52c21bf944e0e new file mode 100644 index 0000000000..90a1a0d333 --- /dev/null +++ b/txscript/data/taproot-ref/beaac08761cf0537284bd2fb73e52c21bf944e0e @@ -0,0 +1 @@ +{"tx": "8346c76302bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfec0100000049bf40cebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd201000000179187ab04897dd9000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961d3c802a", "prevouts": ["952770000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "18786b0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09020132a6a877721f6182c4900c8c9a91ee785719f3dfbcfc4679289a1694c470b90c9077c924505af201de570bea2460b67bc20b4d0b3675c884fdc16bbe98935ba7bff6f3222652f89bfe65fc275b90c0d36c5b2b0c1c59225cca442549c7fc76e2a056ba0fe01368d4d6c46f7c804d7f4d75e0ec8381f1b1ff0cab79577028c2b69154cd021e395227da4c66490b4cdb1b52adfdfabe9c727f4a3ba9543e3e8d284fe38fd10c2cbbdd926c87377b2666ea2ba16ae6fd9286bcb4b157246e9d22c7d15c58dafcc7f824dfbc8b2ed260996d8a8545c083d9bd5f8a4797c3bf4b2d8c0020b54b7d381a8ab8f0e3e91fc27a470029835357cb11be900f086c301c65c4de2fd3e1f4d00e69cc02ef8dbe3eb99c6c4355375f172a20e7d2b926f81f542520582216a6e2131dffe588259eb75d46f4993651ccf6a0c4a40d35a76efffaa3e3bbfb2895b5352f039a93e2ca64bff32bde694c8e3803fcb7ea045e23f18beda32168645203709a71c5496190638e13f30440aac591e0cba87cfaf1880b6bceeabda515773804f242f525e90dbe4f3d308dc0f26ebde88142a7510f7c0f1432e9c0800fecbd0353acdda68a2a615bfb24283bf0839199e56c0a4a195159784af1ff3938611a6342132b83f1963153e52f99fd26d80cabded14c269d6011defb370bb4ea58f62162cf5856745a887a4120ba846127cb0c4190a7f3ef5f07ab915f5a57d974eb299175", "5e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360255f52c8249e8178ded2a32ad0258987e50c1cb8bb770ab3f43966deb2a2d7ae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e865cca6be1d3cc9714f9205dc72257def63c8e50f66dbe399f94c25bd2c6a85f30c8cbc16505271ed8ce1a03d67d2c4a35529bcf4a25ace24696315022c27c9cf"]}, "failure": {"scriptSig": "", "witness": ["4d0902808d9404fb4b3798376a988157648593747e7a034cd98f53a6630d1b615af6c9cf43478542ad720ede86dca64be382ef0e7232dbed262fc18ef85d7b108fec2e5939a32ffab50d9b9a306395a98b4438222f42f4c0bf7744e09e5c5334d80a1cf4e12e67ac261099d97b3f9564a5a20bbb1a30ac1ccaacd2a0f88877a5b27e30cd484ec42a1a1509b4964a22df568b947821363aa1b33b01ac33a12dc41a996399b9c2586588f3f0f8116bae35052bbe98590afcbb8164a88ba19ae268a23bb8ff3c24b4bf99466aee5074480c785afb89bea43717ec6ea3626da91bcf9e11a9447cde92f7f7a1be0456c9ebb54a2583690cc6cc204ba6a28f03911c9486329265f1150e7f926d1c60171010be6c7030f7a7da91caba79fdfcfdfb62ccce9b5a2273f749a541c852e9450dd0f42153d038171a22a253f9501d5b4036d314ace61142185e6767ceae26c996bd135b32886e72a686202ea4511e986c3fbbfc43f581bdc70b1eccce05ea76faac3246f41d8c44819b1b5c6c1009c12ecd268c517f2a1eb6ae8ee4ac0e8f701f79e6cb9411861314cd4df8ac183754289b71cec313e217f07928dbef2ee814970bacb39395d837db23cf0b5671d2d9c50514dfa11df6df706095cebb605911f5fcb0ccec1921508f64340978fee108ab3bec6a460f81f10f0a291e354e54ae0212addbfc48dc59b37fe353f9c779475bc2c9e18996149035ce888383817e75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f7c874ff1fbfa959c18ef617f316a882ee2198cf6b5111461971622ca58a5e82e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e865cca6be1d3cc9714f9205dc72257def63c8e50f66dbe399f94c25bd2c6a85f30c8cbc16505271ed8ce1a03d67d2c4a35529bcf4a25ace24696315022c27c9cf"]}}, diff --git a/txscript/data/taproot-ref/bebcb9f288f4fe614ba1fcc940d72dd3a2e9182c b/txscript/data/taproot-ref/bebcb9f288f4fe614ba1fcc940d72dd3a2e9182c new file mode 100644 index 0000000000..c01c11d971 --- /dev/null +++ b/txscript/data/taproot-ref/bebcb9f288f4fe614ba1fcc940d72dd3a2e9182c @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be801000000bf09559001077e01000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374871a7a8a50", "prevouts": ["20eb220000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["954c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93629aff60e439a9718fb9441d494108642f29be2d6809c2540641ffb56ffbcae4b3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082adc7c8b3bda8f17728820267d55a41d559bf30f92e294931cb4fa644579829c4d4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac8a0bed6c7bbc1bb08bce33089c031a9168eb2767a677139df21750243f2d5cc1a4178950446608ddf8409535ad79bdd567504e9e3f05b7b17ad70ac9eb9eeed4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}}, diff --git a/txscript/data/taproot-ref/bf0031c6d9edfce82c4f7c49f277cbf11c628084 b/txscript/data/taproot-ref/bf0031c6d9edfce82c4f7c49f277cbf11c628084 new file mode 100644 index 0000000000..dda9ea1ea8 --- /dev/null +++ b/txscript/data/taproot-ref/bf0031c6d9edfce82c4f7c49f277cbf11c628084 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cc00000000b8f83b5e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b000000000ea20edd1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7b010000009599d10e01c5f72d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac71030000", "prevouts": ["f6d641000000000017a9141757f4686f091b43a46fa47e92d07c87fc7a205e87", "5b42100000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "0c43250000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100b659af5bc7bf80c0cc1eff37ce34f65896a55c1b5928722bd104ad49c4575d8e0220432bb1178b580c0df0a6a1997145559af84288267326e28e33274f2adb30a24f81", "witness": []}, "failure": {"scriptSig": "47304402203185c77604a8be90ca85a2635f87cbc38e72fed7f3bf5b6167da1b72a247f115022052f94c5dab151061d03ba94f1cdaac6993fc438b0578e71ca6ccd902a03e5e0581", "witness": []}}, diff --git a/txscript/data/taproot-ref/bf1ad139661581e23e01c40061ebbcbdbce507e7 b/txscript/data/taproot-ref/bf1ad139661581e23e01c40061ebbcbdbce507e7 new file mode 100644 index 0000000000..019dcd17b4 --- /dev/null +++ b/txscript/data/taproot-ref/bf1ad139661581e23e01c40061ebbcbdbce507e7 @@ -0,0 +1 @@ +{"tx": "8e961b1c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b601000000d2b48baabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4d010000004b4050d501d0c7520000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72bcffb39", "prevouts": ["4f560f00000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "bd2f6d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a1", "final": true, "success": {"scriptSig": "", "witness": ["62c49876ef07b3464242db73f082f9d482b7d88c47d5cdaefb0696f8b368f778aac96a46d323b54768c65fbcdd1819196713f6af1948e3ce372bd0c8a4e618d001"]}, "failure": {"scriptSig": "", "witness": ["4ba62b3b90e2fef1f92a3b27aaad83a28597f4f4da0704b7156490f23b896c84d09f5bf1ef52bdcf7eb59102e61b453081e878cd30c3f461caf01a536b1c9929a1"]}}, diff --git a/txscript/data/taproot-ref/bf2b441671494bdd813cbde459c3f201b5dc132d b/txscript/data/taproot-ref/bf2b441671494bdd813cbde459c3f201b5dc132d new file mode 100644 index 0000000000..ef0b8f1919 --- /dev/null +++ b/txscript/data/taproot-ref/bf2b441671494bdd813cbde459c3f201b5dc132d @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4620100000077ad6e89bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2002000000f77fe99c020797ad00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac10010000", "prevouts": ["0b6c38000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a", "12fb7700000000001657142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["f680ed04b947655837744bfb290282b3ede1b1c03b28e020f9570c073aea52469f618a73356d310f01231c0f2514a2e3ea11b3e86f75eeb186369e46407f1b54"]}}, diff --git a/txscript/data/taproot-ref/bf34c8983707b06356e258d949ea5d5b386f793c b/txscript/data/taproot-ref/bf34c8983707b06356e258d949ea5d5b386f793c new file mode 100644 index 0000000000..a045088914 --- /dev/null +++ b/txscript/data/taproot-ref/bf34c8983707b06356e258d949ea5d5b386f793c @@ -0,0 +1 @@ +{"tx": "59b68c5b02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5b00000000757001b360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f90100000023805aa70289676e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc3e020000", "prevouts": ["b8776000000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a", "d7ba0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d2", "final": true, "success": {"scriptSig": "", "witness": ["cb494deea94a2cd8ababcb8fcf7dbc7effa7ab798ea761eedf5d548de2b675327ececfd5df4402be7a02e3fbe261c8fefdbd715c10be79eea5e927c83fc49ed202"]}, "failure": {"scriptSig": "", "witness": ["e8a6df26db3a2ea40536d18f5e81c11356febd0254cc7dbfd8b4cc92dee2591d6bf31cc12bdac996b4f175fd3b91434650e56e8841a0644e9151289511f742d4d2"]}}, diff --git a/txscript/data/taproot-ref/bf699d29a3431d6314083edeeb34fd0d30d0e88a b/txscript/data/taproot-ref/bf699d29a3431d6314083edeeb34fd0d30d0e88a new file mode 100644 index 0000000000..246fe204fa --- /dev/null +++ b/txscript/data/taproot-ref/bf699d29a3431d6314083edeeb34fd0d30d0e88a @@ -0,0 +1 @@ +{"tx": "b519aa9e02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7b000000005fde7c9860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a8000000008d3b00900238e98e000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7a5030000", "prevouts": ["b94b820000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "893c0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_30", "final": true, "success": {"scriptSig": "", "witness": ["1a366301c21fb2865414b257437c6af46ca4fa4026c61eb2ab45c76a81b611796c8e0cad59e491e89ba1278be357f59bd9cf83e2a4917655ff122a8dd747d2b8", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["727ba101668dd9d696423d14995064c79a348530ada915b63da561501941e1bf6f259c3042955d86539ce8166d91a9f01b2a2e75203eb8ef47eef4904c0242b330", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/bf79de65a5198ccae719f56cd87e06ebfa963388 b/txscript/data/taproot-ref/bf79de65a5198ccae719f56cd87e06ebfa963388 new file mode 100644 index 0000000000..2f24c9389b --- /dev/null +++ b/txscript/data/taproot-ref/bf79de65a5198ccae719f56cd87e06ebfa963388 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6c01000000b9a21ffd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127021020000007ef33ff3034d9e330000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748708010000", "prevouts": ["63bb250000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "75911000000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "473044022052d7102a163c80f64a7aae845d78b2e032c436c0dd276056382e5275aa761ce7022076b980a2f2c3b13942ec8dbd136b42bdee7ca576a458c5d2e868c04749d6237a384104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "483045022100e97b79f0a2e7bb4360de3703f8a466702afce2783ea138e3b8c6d1a134eefc5e022035717439d025bfc02900f1eee67232f6750dc7a9d3d25ee9994dd1094b7cea7f384104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/bf8f7dfface9a3a19ae105b018ef9c8464a7766a b/txscript/data/taproot-ref/bf8f7dfface9a3a19ae105b018ef9c8464a7766a new file mode 100644 index 0000000000..b639c486ac --- /dev/null +++ b/txscript/data/taproot-ref/bf8f7dfface9a3a19ae105b018ef9c8464a7766a @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1a01000000a7f6e1770244d21e00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac65010000", "prevouts": ["52d8200000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090251eea22263f54538b839a6e32c80ddff99515487950d5444108c6f8a8e8ca641b6c0487d1db717c0eac924992e8bef503da80796d3e700236bd91a046c66bf6f581d292348d74dee367df26854ae2bafdab0efcac13535eed45a6161d6863ae0dcc5309b52195f8c153bef6500ce9337d5a878607824289cdf4f96ee2e9b460a108e6ae88c4a191ad3ec30f4fa402435d59c0c5ecf1773e9ffafd97fa234cc5e228be6f36ede1a9c44914d93a40989fe60db040c120d4764a603257d10467beac52484784d9220ca4bd4869181753d9eb5920945713eb5c9404817b24c595adf19d8375075eae0163f4efe48b8f941798d28946d9c22097c66bc288bd921841269910b0a340dc412f31301768884b191bae4ec497c86dee71ae8c75873726c2e4bd0432ea697079968b652f2e5093959b52ab950bb88fe6ac328fc97b89b2069365d3c0b560cbc6f3e47dd020e76ce36c778819c8ef72c302c105d386e9fc77ba2bf426e1b61807b6883722d971f417d6297e5a4e5b908665929e72770628ce9091f1d8865f83e87baed095c783237195ea097aed852c3b4501dc818c7418db7b7f8a08b3cd91f794ca828149c188d989d9e10786ac0dadfb481f5bb4999f648ca3676e0054302f8495116865cfd34b67384e5484196f5763896fa0bc6a4b89bbffdb892ecc474486d5df3e5c3d35097d77a7819e0b9b02cd70115383c002a5240c7eeb11a7bc6bbe675c6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369789e47787c008d4b1ac49f7e3520e3ba1acc4e691f9f1b35c0f1c9c9f09fa8dd47d6f16ac79aa20d3ae71c6838a1908b9e31e7785a52acba39807bb47995dee4cef708a58e9a16c040ddf6ca6eff300c7bff2a5c928617bb01c850b0a79e89f728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}, "failure": {"scriptSig": "", "witness": ["4d09027a6033e9dbfea74785b42dfd58d65ba8e050f5c1a962def70288a71b93b29e609b52d344aa2296979c814e18dc6d773606a6be5ccacab835684150956ffba6465e2a8eb24e7c1b6b276665edc23759b8c1e11b2e60c8c1f6621f70602e29461c1c622701a2f511d787d26deda0efd5565bdedea959a73ce06e434bc94a8cfebd98c950623f4cb4ba9a19937104957765152e6bae28ea1394edd961fddd05774c25d95e1f4856cf3f81a85668cb6a2bbc15ce1324b58799cd1c42e431b5ff941744bddccbdb236105dea7256eac21766951651e44326483f405f27fbafb9587b9f7e7984ac031eff0ab84f9428a6cffdc2fbf504db623447bc8a1a7fbe77abf1e55f48568d396c005e7650bf0a7e0f0cf918dfbd682ff08b7e3f9c5059ebf02aa1b9e2ab14db294de581fffc6c97bd1dd8abb5d09c4e7bbcabe260c57dbedf61ea3f7908b6680920829e1c62a85e56c5967acf0faaabbb240fea111ab6b47415ad9bc4f9bc0dacdfb26506fda87f4e4dc053d94aa271fdf63be7b39bbe4a2b56ac4b7e11f135b17ce6825fb3154bcfee4f462c4ce2ea7e560410e0a257486e17cbe61c9edbf07163496576607b64a01e3dcd68de40344a1911cffda9c038685a76bbba29684c78cc4f4503f516f82ee5533c813b0552f19794570e082d0f329582d339ff2d00faad8a01180f0f1a62b32fc84fc20a66fabf88a0f43ed625d00fee405c5066f699f81d47561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ead70583f94efe61957c66762db35c674fdba58ede6e88df118535ee414388d1d47d6f16ac79aa20d3ae71c6838a1908b9e31e7785a52acba39807bb47995dee4cef708a58e9a16c040ddf6ca6eff300c7bff2a5c928617bb01c850b0a79e89f728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}}, diff --git a/txscript/data/taproot-ref/bff5be66a4aacf336f6a1a8aabdf35a37bd49c75 b/txscript/data/taproot-ref/bff5be66a4aacf336f6a1a8aabdf35a37bd49c75 new file mode 100644 index 0000000000..d27a402f95 --- /dev/null +++ b/txscript/data/taproot-ref/bff5be66a4aacf336f6a1a8aabdf35a37bd49c75 @@ -0,0 +1 @@ +{"tx": "da12e55f0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fc00000000eea8349660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703e01000000fdb2d88004830d1c000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ae0c615b", "prevouts": ["ec020f000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "54ce0e0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sig/bitflip", "final": true, "success": {"scriptSig": "", "witness": ["269713504f96ad0d5e815e0440517832f21c478fc2d6309403d12a480fbfc573610d537266ba1625441cb13ebaa0130c80406a24d389c7418bc393378d6cafce"]}, "failure": {"scriptSig": "", "witness": ["269713504f96ad0d5f815e0440517832f21c478fc2d6309403d12a480fbfc573610d537266ba1625441cb13ebaa0130c80406a24d389c7418bc393378d6cafce"]}}, diff --git a/txscript/data/taproot-ref/c0039aba73061b1e9d1b5673c11d9a6fec6c2d2b b/txscript/data/taproot-ref/c0039aba73061b1e9d1b5673c11d9a6fec6c2d2b new file mode 100644 index 0000000000..fb1b688e53 --- /dev/null +++ b/txscript/data/taproot-ref/c0039aba73061b1e9d1b5673c11d9a6fec6c2d2b @@ -0,0 +1 @@ +{"tx": "421bd7b302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c140100000064fee5d560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270da0100000002f966fe026fee650000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac3dd3f227", "prevouts": ["28285a0000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "d69a0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_6e", "final": true, "success": {"scriptSig": "", "witness": ["fd5507f6af4da610b2e11b16af216d70c6610eeee1f968fc780e18d4f36ef31b2023a28220727b3d8b4065b9c08b37a1852a97408079d5b77d7d75f23db9a93c"]}, "failure": {"scriptSig": "", "witness": ["29188078163bd5145a8a0de99510d5ffc89e8661cca31f30c98d499f21d967417895d29d080228ab6bc1cfab52e1ce2f5084e3a489caa5d07086d7d0d6ea14f36e"]}}, diff --git a/txscript/data/taproot-ref/c0201387de1a365edea3ae462c8e87757ac56e21 b/txscript/data/taproot-ref/c0201387de1a365edea3ae462c8e87757ac56e21 new file mode 100644 index 0000000000..6f283a7e52 --- /dev/null +++ b/txscript/data/taproot-ref/c0201387de1a365edea3ae462c8e87757ac56e21 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f900000000bceb13d28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dd010000007fcb8fed015e995a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9009232e", "prevouts": ["e33d3a00000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "3bff3b00000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638a68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d1b96e81cead6ac3d8926975c578d0c5f6545830f656c5959ed0243cedef90c4837054ce51ecdc9e3a3777b2a8e44b7f174730ae5a790047b9842df02ff9276d2430956d1468bedd56ced1f149c0a08e9d241f188aa41dfacb5e515f08af1f16915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082141ceaec0b62943b85ddb54ef2037615ee2bfdc3c88602ea27aeaa6ef1c2e0ef6e427c91532996b84ed2c37f8a26be8637de11530a49bfc255181ba6103e3464915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}}, diff --git a/txscript/data/taproot-ref/c0264fc040cf13b7e91a6413eb4b7c76c194b45c b/txscript/data/taproot-ref/c0264fc040cf13b7e91a6413eb4b7c76c194b45c new file mode 100644 index 0000000000..fb0a581602 --- /dev/null +++ b/txscript/data/taproot-ref/c0264fc040cf13b7e91a6413eb4b7c76c194b45c @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c470000000032889c918bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42c01000000160157c404c8ce8b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac88000000", "prevouts": ["2b65500000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "d0313d00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090243e0a9de6aa979cc1bd88b6f32b35b4f5cdc1ec6e3e50d6b382ffc140619020502e3dac94586500826980ef68f25c7a35c549d8cf7d2e1480a389ab4d5e2eb68d9e201ab6549c6a8b8ac426f4b82d4a89652f77b80e00df28d6616db3db9e96135e12e6c152d7c0100cfccb8615c74957764aeb7d5ad6448c51828ec198994875033211110d8b3cfb563c5cd1366b16876cbcc5db52441964cad03e76250d7582c480089a8fff6e20abacd855b81296f7c35a46d4fce3b1a3875c5fe4985c647cfda295db1c94cfab6ec04e3345f4f3a5f5313ebca6e75384ebd4c5889811996f336073b7e16116739202d3f059e6651743e73bc6b2fca133a5e1b54372f3730f243a49e2ad890f0b5594e8dcd157859956df24ba6be251c891e8cc9e715c4c4aca028eae77ab2bce2fd3222a470271a196adb8ae47bc2d7515ec7cf2299e1809df3ff2ca956a98410438adbe209cb9e04326f163f16908f45172f783805ec2a65ab2bb608f338a05c0a7c46ff040c17f3159ca8204c3e47d374a5e05684039f93cb106121724e7ed3f63a8a338c75a306da0dd8e73623cad2d9d33ab5722581a4ecfd47e92a796325510c50730059a39cdb9f52a46205a2cb87e1d2048770dd972d7fd024a59ffa9283d9ceac95216de9cec1cd754468637af08d344c773e85399d876a7aaaa02217aef357181c3865ac890b0e8c369d215c6bd480677af007b044957124d5d9759e75", "417d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa7155e8c33f0c07f7d0de889297fa065f1be8d31098e32dc97a677fdacd11d05345bbf2815375aaeee056e6b05e441f58ef8c911146e9d15e94b57fcda7a8d0b76831d286b681d36077bb0670e25d1d3b2bbe36e9d696c3276746d4ede397eb7d"]}, "failure": {"scriptSig": "", "witness": ["4d09023b22c252102d0bbdc5bdfb0b10f0211835830b2d023c89a4c6a3100b98bc91d24a22bd28a86dd359472d3ca61510f8faba76e767a64635040f1a4aab80bf02a107e53e10092ab8ca4a5af75f2d3ba5998720fd5b8dea6cde37717f3572484f316a623de86e9dfce26b97e15a2b1a0df861d003a4b38fae7dfdb5a4ffb8bbaadcbf3327e420640dfe44cbb88285367e9a38838be7ed6147945329072c047dc202a219a42c7dfdff341bbd7d1c499f863e057343b3acb88c1e3e076fcf2c89f267836fc7ebbf50eb104b55101a1fdfdf1eade9f49a9614c8cc6530ed36051cd65583af538c6c34b4004c52945b2749616749e49afd7fdef0a4d3564630fc2968533882ce1d73f01bdcbfa3e98854b96530db3248950f3c49dc29120694fe5ceb27a9585264df2ddb512a32ad320f7e636b93c19d18f8102fadbbb4be4d89dabecbcea8e764e0815de011dd680a8b0ab054521697d5e21a82a92a03fc628a7a98479b56c8f25f9c8590d83afad3d27586a8851c6bf7a8c6b4926f179db446db40e1a36e842799e78123ca9e41fcfa465a2eb617c5e12abd9b700787930e8a8e109b8162ae7e0fc8ae97d86313808785857c09df13cae1025aeba1a534b430ad1036d59b7179a69655402e648dcb2818f4b7de07ab2cb0773a8c9ffc93bd8b7e0c5064c821673174fbf1f7ec5519f5336d4ac37efcf28e7b8f44f7af6bec432d3acd29fbe57a7c96402f2175", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c59b01a00c1a8ba5a1aee08e5db1d927de1139bb693668c89cce1a6ad71d2265ebfb5abead622ee588f8a14df4b864e849bfb1ffa426a7f0fc441a7ea7f9f3e8819e00a9246c8c145cff8a91ff4546d478c6c8e3d7b4e3f7e61102a4388494af"]}}, diff --git a/txscript/data/taproot-ref/c02fa738eb666819f177a296b855df242f3744a5 b/txscript/data/taproot-ref/c02fa738eb666819f177a296b855df242f3744a5 new file mode 100644 index 0000000000..02c0ea5791 --- /dev/null +++ b/txscript/data/taproot-ref/c02fa738eb666819f177a296b855df242f3744a5 @@ -0,0 +1 @@ +{"tx": "cc6f3def0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a90100000072a16fcbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1d02000000bff28abf0409d36200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ace2040000", "prevouts": ["38281000000000002251203e6b8aa12170bf3e8ad7f10d608d1ed027d7fee17123c5116152c821758451f4", "bc035500000000002251202f329ebb629b1bb09406fd99900762644c979122f44ddf705116f636c54af1f8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "final": true, "success": {"scriptSig": "", "witness": ["2076b02e7a8c092452fe8cc7600e3d4714f6f512ea929a851b89bd5345065c98b75d96051f8b7e11f69b43a4d71281831a42fa4dd83efe2431868a258047e2e6", "2d095a1f1062fe7bd8", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead587cba5987", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f14c077a5df9569646929ff390715adf76260bbf779418b239f42b6e5c4df0bf6e04a680a3e09d2c1c78b970124d832e17e53b3edd07c25f73a974632e6fcb1bba955e8474be2e5ac086aee3ec774721171b5e328eaea831dfbb16e2e79f74edede1cb3350aa36ceb33b3b6c7090611381813ed3ae357cb7bb9b2dc70f0d254d"]}, "failure": {"scriptSig": "", "witness": ["2076b02e7a8c092452fe8cc7600e3d4714f6f512ea929a851b89bd5345065c98b75d96051f8b7e11f69b43a4d71281831a42fa4dd83efe2431868a258047e2e6", "aee58931a9775a2c", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead587cba5987", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f14c077a5df9569646929ff390715adf76260bbf779418b239f42b6e5c4df0bf6e04a680a3e09d2c1c78b970124d832e17e53b3edd07c25f73a974632e6fcb1bba955e8474be2e5ac086aee3ec774721171b5e328eaea831dfbb16e2e79f74edede1cb3350aa36ceb33b3b6c7090611381813ed3ae357cb7bb9b2dc70f0d254d"]}}, diff --git a/txscript/data/taproot-ref/c04290c4f9037a6b82b7d2392c6c80c1ae11f80c b/txscript/data/taproot-ref/c04290c4f9037a6b82b7d2392c6c80c1ae11f80c new file mode 100644 index 0000000000..6c957abda5 --- /dev/null +++ b/txscript/data/taproot-ref/c04290c4f9037a6b82b7d2392c6c80c1ae11f80c @@ -0,0 +1 @@ +{"tx": "e7e3b9f90260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c80000000068e24fd8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9200000000b1a782c802e7456700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33e6a42c", "prevouts": ["d19c12000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe", "fe5b560000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c24c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361d17d6661cc8fb2f1af7119061da5758e988d072e66a98fe62e54b70963bbb8620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e119ca94dd80cd6ec848cff445ef1653ae8d91bf4217e3b4bb0faac1831ae9489bd0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d5c78237289a8636bb429226e0de9c7befeb1ddb6aefa0b188bf3d9b51e606da144e2b32fb029cde325456c88021dd04a80b93e0665f7e39c1e8a56bfdcaf4a64b5cd80fb8cd7c947a98554a389db356265b198fc72df311d010d98c3d6e3928"]}}, diff --git a/txscript/data/taproot-ref/c066693ba1a2191967ded9338dab201a79f31370 b/txscript/data/taproot-ref/c066693ba1a2191967ded9338dab201a79f31370 new file mode 100644 index 0000000000..2dc3d6790a --- /dev/null +++ b/txscript/data/taproot-ref/c066693ba1a2191967ded9338dab201a79f31370 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c0100000093647caebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd200000000897280c9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf63000000009dfb36d60406682001000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388accbd14a30", "prevouts": ["e211480000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "22e868000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "cd58720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_csv", "final": true, "success": {"scriptSig": "", "witness": ["7839dcdcda4a68b6d8036ffdea6037a2585da1410160ab98fda3e8769595116fc1ec486a359dff8aa6e022c34e6e36cb414aa7731574a0c2f6477f8ad6603886", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bdd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a37f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}, "failure": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bdd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a37f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}}, diff --git a/txscript/data/taproot-ref/c06e8cd4278bfe18806835f29e8892fe38588b77 b/txscript/data/taproot-ref/c06e8cd4278bfe18806835f29e8892fe38588b77 new file mode 100644 index 0000000000..06f6ec5a04 --- /dev/null +++ b/txscript/data/taproot-ref/c06e8cd4278bfe18806835f29e8892fe38588b77 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127047000000008b866bc6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c94010000009b039ae9048b395c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8740000000", "prevouts": ["aed50f00000000002251204f95e2d0ca6e5ead217b338fd8f5ed161ed18d9deb82c1fc7cc39fccfd04e4d9", "414e4f000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef9dd54afee6993a303fd38df7733ffe3104c2b75362843dd01bd11eb312076d"]}, "failure": {"scriptSig": "", "witness": ["6a00616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c09fc10086b95973815a1c9f85b9e89af0b68a27 b/txscript/data/taproot-ref/c09fc10086b95973815a1c9f85b9e89af0b68a27 new file mode 100644 index 0000000000..d5def469fa --- /dev/null +++ b/txscript/data/taproot-ref/c09fc10086b95973815a1c9f85b9e89af0b68a27 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0802000000f4ac4498dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c370100000052b315f604819bde000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac2c000000", "prevouts": ["1d9887000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987", "206059000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3044022023c1fa86a88954f5ec7acf465d03a69066358cc1f41dd00038fcfaacaff94641022066878e3a4f54cb42e604936659bd75168525b2d7c6308baad77ee15e685e418f8a", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["30440220681e0fc8eaf45c7a4d3765b5b8f7b5f8cdff8c9d0a0509521717d4e78089587602204a23362f703e0bbc418836ee5ec11f616f326f7280a1deb22ab9c45df9883b9d8a", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/c0c65b781da778eab58a96c85067f90b2d4d1f4c b/txscript/data/taproot-ref/c0c65b781da778eab58a96c85067f90b2d4d1f4c new file mode 100644 index 0000000000..68b3689ebc --- /dev/null +++ b/txscript/data/taproot-ref/c0c65b781da778eab58a96c85067f90b2d4d1f4c @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b040200000046cd652b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40a0000000042a9c23e0462eb5600000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac77020000", "prevouts": ["05bb1f00000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989", "45ee380000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "d27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362aacdbaf7feb2ee84db2dc99af1e5f6e1450a5c488d9b9b44f0760fa1ba6b92f9a9c5d9290705897ef911507dd26b72756738dae23c9379fd676f365e52e00fbc5e1171eec0a28263e9818d2dbd976f4b8066e50dd8906a411b6a9dd47f52980e39f192d4dec24b48e9231a08b7d2e64fac2040aad69c16c1d9eedfe5fb62ebc"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93621ef10389913bdbd846df0d9639979edfa3f7c76677006bc1a57e34b3956825b9947182c2cf442266d627de6569afbd254a849da3e2d989b935a76fec010797d33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a9b801fc18e2353a9cd4de337bb33433fbe6225e21bb8b5572b0acaa50d11b7f3"]}}, diff --git a/txscript/data/taproot-ref/c0d2b1edf6f56cba1a8e2d0b100cb918fd7f803d b/txscript/data/taproot-ref/c0d2b1edf6f56cba1a8e2d0b100cb918fd7f803d new file mode 100644 index 0000000000..c48c9231ba --- /dev/null +++ b/txscript/data/taproot-ref/c0d2b1edf6f56cba1a8e2d0b100cb918fd7f803d @@ -0,0 +1 @@ +{"tx": "da5995b202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba300000000e933e5a4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb40000000057e27db101a5fd2600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac59005b4b", "prevouts": ["fbbc1e000000000017a914bf07e8218e5a3c93fa381357100b6dba1ff2a91287", "4a0220000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "027d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c4b75a5eca83c62ea415013ce3486a59b49eae62a9a2157a509d555c51c755a41a39935f0afddba064f6b0bc8589127966a984604296ac06f9873b8ee7d7aea369828280661f54bb25ef200c9d39138c753346ae1cc558703fbc48b26980763768cf2d3d0be95621d7446294d89d9a2894510d2dfb4e1a33e7316a17e39cfc99"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cdf75c6f1206420e3d576f860d6a0b821efde2bf3dc8c692e6dddc88ddda04bce4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8c6a1fb55f16de67c2a92ad96c93aeea32aba2f93d3355ba34bd608160e8b6bc30e32049d91f42cbcb04955cd98e985d287b85d3c77c1154d8406ae5e2d81b7b1"]}}, diff --git a/txscript/data/taproot-ref/c0d30a73338909cf56a6d97fed0221e78bb7731d b/txscript/data/taproot-ref/c0d30a73338909cf56a6d97fed0221e78bb7731d new file mode 100644 index 0000000000..78837e1900 --- /dev/null +++ b/txscript/data/taproot-ref/c0d30a73338909cf56a6d97fed0221e78bb7731d @@ -0,0 +1 @@ +{"tx": "6b2602cb0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127000000000001a450cc004ef260f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc76e87a825", "prevouts": ["d647110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_37", "final": true, "success": {"scriptSig": "", "witness": ["dd90dada34e2cb3bc0c1f80a336b1a28e617f0aecced79d25a14a8df4af56efead7547171fcf2c4f50d3fcce324131add81909360a6e82e57e467ce37f261a3303"]}, "failure": {"scriptSig": "", "witness": ["3867cde0f18449fc23edbe75601ddda66b9b7009fffe15dd979272260da4fc1dc8abeeba4ccabf453fe16db9a442b5c646058dbaa922b2edd935c0a795bd485237"]}}, diff --git a/txscript/data/taproot-ref/c0ea13628224c7cfa08a24dfe6cac5360c02d61f b/txscript/data/taproot-ref/c0ea13628224c7cfa08a24dfe6cac5360c02d61f new file mode 100644 index 0000000000..541b9fc93c --- /dev/null +++ b/txscript/data/taproot-ref/c0ea13628224c7cfa08a24dfe6cac5360c02d61f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3101000000baf8229cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8700000000f34c48e804c866e000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6bd667b36", "prevouts": ["9873650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ffb47d00000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "537d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365679c4b80b1f02a904f6a1e97bc1e5029a390245cd2e5f4f1bb6526c613587c3c1fcc94e870ec95c088fd37f5daf805336fc0aa07ac91d9d5a0c770a5a47ed76aee97a7dfb8acbc78fdce4694f8ba1e1e3bf612a81f34559c93e6dfd336d600fd892d02e0db2d70aca72db86bdb1e35d04291625c81ec0b3d884b10be9f787fb"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e89a54256964294f7e46fe5d25ab3411c34d3792ff29ea326544b7c68695f53859e150f8c7b4812d3362c6afa34922f3b5cc4b63cc9e98285537a088f4a7fe3bee"]}}, diff --git a/txscript/data/taproot-ref/c0f5b91a651c2d181d2e204758d6556b2d362c11 b/txscript/data/taproot-ref/c0f5b91a651c2d181d2e204758d6556b2d362c11 new file mode 100644 index 0000000000..e6201a4208 --- /dev/null +++ b/txscript/data/taproot-ref/c0f5b91a651c2d181d2e204758d6556b2d362c11 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b22000000000e68496b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41601000000d14c8d5b0305ca5300000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac832c5e32", "prevouts": ["ef35240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6975320000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c7", "final": true, "success": {"scriptSig": "", "witness": ["87e3932eb099c3a059fb9468137ffd33308793027e7135b38b0ecc5a08d91c45cc164d4234ebfbe9f94994d9ae1d69ac2c9ef3b2b3b5d0dcd235ed096686e31d03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7252e641df0bc016fa072ecdc25a5bbea78bde919a71fc5f2f2de2b195a4ed4f0d54ad8b20505e040c9d01f9ef590aa9a6075c04ebd94c0e7c7458100ab44580c7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c128857e0f643e229c430eb8ef7d3f5aaad861fb b/txscript/data/taproot-ref/c128857e0f643e229c430eb8ef7d3f5aaad861fb new file mode 100644 index 0000000000..b9173ed7c5 --- /dev/null +++ b/txscript/data/taproot-ref/c128857e0f643e229c430eb8ef7d3f5aaad861fb @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708100000000b5ce03e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6f0000000017b9b5cd04deb385000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87ead3593a", "prevouts": ["0888110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1a5f760000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_72", "final": true, "success": {"scriptSig": "", "witness": ["4601f45f51444d2268f82b339eecc385de6945a5b41c3525f900f19450dbe9530d6edb84c287f92e243a66a673c87803d4d308ebbda4316be2f69b2df679da9b03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3975a172f6b9b20183f14bb7f9de1a72f3c5c7ab43ef24b60ad06bb2e05fadf338c613e35c08c3e71fd711b3d47c24f6da5c168f4c613e9e89e57286f4d102cc72", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c12b71a60e309ebef55284d493cfd3665116ac35 b/txscript/data/taproot-ref/c12b71a60e309ebef55284d493cfd3665116ac35 new file mode 100644 index 0000000000..298f74b9f7 --- /dev/null +++ b/txscript/data/taproot-ref/c12b71a60e309ebef55284d493cfd3665116ac35 @@ -0,0 +1 @@ +{"tx": "6ebe113f03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c480000000082f72a8cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba501000000f5b89fa8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcd00000000c556cf97037ed2db0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acbb000000", "prevouts": ["98a94b0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "d2402700000000002251208f7166d23fc1e45fbcf26b51bd386ab915626b0708475a8743064036728c78ed", "8f956b0000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c003e47312495abd0ecea483b7c96f6c06baf07e98ce450a7ab8fc6c1d015d8d419750c06d432bee308f0fae4716b69cb6c25810329b8790fd49c679f7455a77c48cdcd8dbcfef9ad7c7a30771944f2cd4ff67f595b136e3713763062e27bf597e2a087af95959b20705299b695bcc76a7499066c9215d50f1f19d347c9606929e8c43ab2d3c8341e5ddb2e7a976063d2510ea844334a2f10fee1c2a194b374a38e3ab6d6964d755bc0e13212d27e73f5bd049b310ddca632309f40d884ffbd4a43518f5a62961bb48ab613036012a74e221a13c741ea9d3963160e74d5f4ca891448693b23cfe7ef23bcb8ad48cf9686b8b274e632515f150eaba77a1534100a1fa86c4673276316b981d8d3078e7ee0664161ffdbc80837594e11de603fee93a0900422ce8414d3d9ec31eabad215388986f38891e227d1396cd5133088788fd1284c6850ac04377717ea6b69cdfd22358623870c8c1a53b7eef11cd26dfae1a739b323e4dbd888fcc7e46e0308658560a426909489d4b1feb2a72a4042cd2a6f461ee247c48f08002b32a808e4f110f3ce3c9c632099629abb70ecc66da9b3fbb5a8749c9b147a33d669d56f22b0174c822ddb2128eaa425729f909cde6e1918db476fe7415b5713e1ef82d92e0d54e9c900746e84627a7f3ab67a68c4f52ba4928939805cb52647547755ed599179711f9afdca1c437b25d71a95b51f9495b6d66766f017516ff7595", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936efc04f522567ba440a5ccb1f894ddfa30e3ed18bf7db19d3822c68f4f6bc07d299aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4c1a4178950446608ddf8409535ad79bdd567504e9e3f05b7b17ad70ac9eb9eeed4a2033150a39b6917f88ea297b4f989401264ea3eb8667a511a69e57850c639"]}, "failure": {"scriptSig": "", "witness": ["4d09026a1aa4aff7525e1ad84d9de23fe30241b0645131eb0823fe1b7b6ee6335627908d03fb9eddac278ef646ff04d5cad2b264959ac6f25e1b57d2ddf53be312006ed4a10b770de0c068b97e514f09193b3dfaf4a5fe8f2e481cfb3202cbcb0dd886844f0bac52b8c4e8d11c13e990ac4dc212cf14e7cfd6418fb28c7255839eaf8686486cfa8ba11e1f2ae28e8028e92e4196d11f678551aae673860c2b90207c87dc73675e7e892238ee288a1cba2e68007a97af98924dd2b7ecf893334e8386e75749a121dd864ace9c3d6bc81631c5af4ce37f99ef20dd33a41fcf6b8a4bf1f7b1ea0c88bdbb0f728012bfe3e7bbc302faa78fba4886febdcd99875986a8735de6c2b4d2fe313fcff2d74ee5e92b316b4b112585ed46eced024814390a0e4cee6927ab3668932e3d3e94ad79201f4eaa5eeaf6435cc18f138b3bc125456034fd0d94a1c730f35614b898ec8c39f80c07136a617e4a07bba4188069bbaf630da2a801e4c525385a6971ef34b8e1e9fc1f8932814a12bfb6e36c90e8cfea1c01613fe57711ed3412f7255790e6d7aaa5d6f36fa3099d9587ad673890a20ac2b5f609959ed4eac6d35e6ae71a2ef50210543fcd8c2027939f36c9f792cad02d014d42822e1d22bc242afd14f1130e2817391fb27f983e15133611a49692d5619036af5b3c36abede1390da9c78fbefcdeb60846d406856ed79d67c73c13b7e57285f29a8984fe8d0180c37561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369af08a3754cbd3d543e874a27ef2608692e4496bce300b07224b27cbee5eea1575c046d699a38e7801f010fab6b697cc237a48311758c02bc29e281a6d7a682eab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}}, diff --git a/txscript/data/taproot-ref/c146489c520399688a56c27fa5210f00c10e9e5b b/txscript/data/taproot-ref/c146489c520399688a56c27fa5210f00c10e9e5b new file mode 100644 index 0000000000..b2fdcba3be --- /dev/null +++ b/txscript/data/taproot-ref/c146489c520399688a56c27fa5210f00c10e9e5b @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3c00000000038eca4160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270650000000086bf9efc01da691800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac09bb0336", "prevouts": ["9b0e76000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "3acd12000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "907d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363bb05f98c2e695c01e670dd2e228a24813d9ab38bd8282e6b549b79433642df758fa50c6d7a3057541347f50382af7d86a4158110d747d8a87c6e51bda235e7807d6dd053b835b300872a79bbaa392d17bbe19548a92a63c5948e9fc7e63dbc8"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93653f88528edb69bcf55b01eb77e975ccd2596bca40cd6e1e17cd60b66f98d72ab693163a47c3dba2861e33fa837573abaf06e3047dcd3f7c322d2576c3cfe3d489f4b63c6df7ef43e2db8ec562e1d1dc49232dee39216a09a14bc3b6a66d1e38f07d6dd053b835b300872a79bbaa392d17bbe19548a92a63c5948e9fc7e63dbc8"]}}, diff --git a/txscript/data/taproot-ref/c180a8fea16357ccb1c9e9a5b1fcde5e0137ba39 b/txscript/data/taproot-ref/c180a8fea16357ccb1c9e9a5b1fcde5e0137ba39 new file mode 100644 index 0000000000..4ecb535a70 --- /dev/null +++ b/txscript/data/taproot-ref/c180a8fea16357ccb1c9e9a5b1fcde5e0137ba39 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701602000000869bf9f460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701402000000ab8972f801e82b1100000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac09010000", "prevouts": ["a0941100000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "2266120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["ca4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb460e4b742334a3ba05c34377629280dcb4ee1c5981341754674382732961bb035dc18898993c284d2f731b7495cb62c60e8571430965d040562487638e1f1fd248a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93693549492b615adfe57dda9a6672912be33acba3c614b0a4dd60f18b8fbbcd54c60e4b742334a3ba05c34377629280dcb4ee1c5981341754674382732961bb035dc18898993c284d2f731b7495cb62c60e8571430965d040562487638e1f1fd248a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}}, diff --git a/txscript/data/taproot-ref/c195e2cf967dde5160c0de3b6a514dbb2ff8485c b/txscript/data/taproot-ref/c195e2cf967dde5160c0de3b6a514dbb2ff8485c new file mode 100644 index 0000000000..c56c728414 --- /dev/null +++ b/txscript/data/taproot-ref/c195e2cf967dde5160c0de3b6a514dbb2ff8485c @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8000000000896880f4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2302000000409c9b9802fd1ba200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdfcb3a45", "prevouts": ["2ca35d000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d", "3634470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ea", "final": true, "success": {"scriptSig": "", "witness": ["e528ab615282b5f0511a58b57e63faebf8e8947790793f371e3c9f72032feb5af440ff65e2a1a43986e65cdacf01f3e5c551d5a019bb37ed8b2272bdfe68e76082"]}, "failure": {"scriptSig": "", "witness": ["7976428c28abccdf2f940adf0684acfe07c9eba9f9b1b456d68b6759fd089665c379e5e54ceddd2e782583fe0a14c3ddf2357e4343a56e9feade163d9dcdd8d1ea"]}}, diff --git a/txscript/data/taproot-ref/c19c13729ac0ec5c7e396da5494a3f513d31d8e8 b/txscript/data/taproot-ref/c19c13729ac0ec5c7e396da5494a3f513d31d8e8 new file mode 100644 index 0000000000..3ab3d99910 --- /dev/null +++ b/txscript/data/taproot-ref/c19c13729ac0ec5c7e396da5494a3f513d31d8e8 @@ -0,0 +1 @@ +{"tx": "d6166341018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4790000000010c750d201fd6300000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478789020000", "prevouts": ["2d9c3e0000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e44c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936036751089af36ed5c0ef7dca2a713ca9b31e3a2dfbb12490c74aaef9653ee48ca81c44a09079faa406e9dfe20ff322801dbd7fb1c55ee11d2e1c43aeb4d3cbdeaf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e13f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824d4fab40ea135233ddc8c9f724889f007818f7ffad5749db3376d8fcf405e18faf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}}, diff --git a/txscript/data/taproot-ref/c1b84b02f4cf106428923ebb095dd6888ae0ac50 b/txscript/data/taproot-ref/c1b84b02f4cf106428923ebb095dd6888ae0ac50 new file mode 100644 index 0000000000..6915b404cc --- /dev/null +++ b/txscript/data/taproot-ref/c1b84b02f4cf106428923ebb095dd6888ae0ac50 @@ -0,0 +1 @@ +{"tx": "ed787e2502dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4101000000e197ff86dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bba00000000cb7df6900128ef2b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87281dee3c", "prevouts": ["7dd81f000000000017a9141a56e0fb41afaf4b9e6feff1797087c69015162687", "4674210000000000225120801095ecb8b6618653d214b38461db03e06a33e3af24d0223ea647d6569eff0d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362fd70b7ac25e6ec5d20c4437e9dc3fc360c9cad49d8a5534acf4ee938278cbb5"]}, "failure": {"scriptSig": "", "witness": ["6a4a616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c1bff9e88ae4e9b8bfd1976fa22c1802e6db3962 b/txscript/data/taproot-ref/c1bff9e88ae4e9b8bfd1976fa22c1802e6db3962 new file mode 100644 index 0000000000..0f55af5536 --- /dev/null +++ b/txscript/data/taproot-ref/c1bff9e88ae4e9b8bfd1976fa22c1802e6db3962 @@ -0,0 +1 @@ +{"tx": "b809cec502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4d00000000826028da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708200000000d8400db60264ac6e00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acd4000000", "prevouts": ["3910600000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "4937100000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["e34c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f0d1bc393c3c3c2b57b8b86a9e8a64bd1d4b9e0fd1bc4525ebf92e13eb29f90821a06fc3128a9eadf7c181b12783fc0ac677434699a36c8776c14fb861b85f3ba54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360a4f638ce23d17c39a29ede58d266fd12593fb14b584adf686071e58cd6de6a5d2593bff1b0effa885b0aee87a7b2d32e61d34e0a8c26ab8da95f21cdf0740a021a06fc3128a9eadf7c181b12783fc0ac677434699a36c8776c14fb861b85f3ba54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}}, diff --git a/txscript/data/taproot-ref/c1e5922d5f60798c78f4d0d669795bdad1a0801b b/txscript/data/taproot-ref/c1e5922d5f60798c78f4d0d669795bdad1a0801b new file mode 100644 index 0000000000..04d11f5609 --- /dev/null +++ b/txscript/data/taproot-ref/c1e5922d5f60798c78f4d0d669795bdad1a0801b @@ -0,0 +1 @@ +{"tx": "757a763b028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c476010000001189b0d6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3f00000000aa93a3e00138d3410000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5f354861", "prevouts": ["8ba4330000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a", "91555b0000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369c3c8aba3b1d9c892342e3bb33d29486ec8523eb8867e3a771f2201c80f0f2143493aeab6959567855d46871d1975f827c269435f7c9757b13dbaeb906d5d20b01b5a419c18d23e8c03ade77009761f1ea37c255231895048329572c11717ad56187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b31cd2587ef1d28654819f6adaa2ac28a0f894d9dd869941f90cec36533241ac3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821de3578bd50e4aef3f42172206e28aaa53f32c3941b8b4ddcf806814652917426187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}}, diff --git a/txscript/data/taproot-ref/c1eeed88c600ab669ef89bb18d5ef6a6830d4f0e b/txscript/data/taproot-ref/c1eeed88c600ab669ef89bb18d5ef6a6830d4f0e new file mode 100644 index 0000000000..9999814bd0 --- /dev/null +++ b/txscript/data/taproot-ref/c1eeed88c600ab669ef89bb18d5ef6a6830d4f0e @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c64000000003cf989cedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8d01000000056889d804c0d86800000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac35030000", "prevouts": ["ec1e4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a78e1f000000000022512088381247371028bcbdc4971a16b3f7d8df868484be1d753506f5bf6782ea1e55"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936443f9e607c139397158640c1b36ff7afb5325bf4b323e9b48798bcd0a0abafc0"]}, "failure": {"scriptSig": "", "witness": ["6a93616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c21065afa4b19740633e3c552a080169d12b4afb b/txscript/data/taproot-ref/c21065afa4b19740633e3c552a080169d12b4afb new file mode 100644 index 0000000000..20036e5455 --- /dev/null +++ b/txscript/data/taproot-ref/c21065afa4b19740633e3c552a080169d12b4afb @@ -0,0 +1 @@ +{"tx": "dd2936eb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49e01000000af2fb8efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1100000000d31f29b504d62552000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc89ec6633", "prevouts": ["327935000000000022512008f3b8bffed108016f8bc06cf0d4d62b3035ac315959ae84338bee34a4bab63c", "dbac1e00000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6afa", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045b9350299288462116e81ad139d1cf2552ad17a94ea609f697964ec86e4a0e9d9319d91594da7fa35d5ac76c3396b108bc28aa6233c389d8680e4f0461963fe656f5053dc49cb92d20c30fe5ab09c589302aa9886b9c794d18405aff33121a169"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936454ba48940f06012a7e7a07aeda3ebe402d4ace9093c69f202ee75e21741471ec26d78b90df0408cccf5a173a397f35b7225b23776926a85911da6ca9e3721966081f43f8c34257025162ccf1daca48ae61c99356c3eb24d5601d3c52dd9de2a6f5053dc49cb92d20c30fe5ab09c589302aa9886b9c794d18405aff33121a169"]}}, diff --git a/txscript/data/taproot-ref/c2268af10452034a5d5f9268c6f6797ab805a459 b/txscript/data/taproot-ref/c2268af10452034a5d5f9268c6f6797ab805a459 new file mode 100644 index 0000000000..5443a00a86 --- /dev/null +++ b/txscript/data/taproot-ref/c2268af10452034a5d5f9268c6f6797ab805a459 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7a0100000095d9f0a38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4af00000000ea0b84ea030401b30000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1bbc2046", "prevouts": ["1ff07f0000000000225120aee326bed25c38bbd2065ec54ba80d7933aa4c88bcaacc9a661dae671bd05d2c", "3a2a350000000000225120cf1cdbebd76187b7cc76a29147a6cff8f4ffead99137b52e0c175bb15fb623b3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4a004f07a59de9b760d587d4f325f6314ed9590119c6b43921a305306c0ac45"]}, "failure": {"scriptSig": "", "witness": ["6a02616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c22963b5f52cca482bd79213fd1c9fd9819b85dc b/txscript/data/taproot-ref/c22963b5f52cca482bd79213fd1c9fd9819b85dc new file mode 100644 index 0000000000..676ea02453 --- /dev/null +++ b/txscript/data/taproot-ref/c22963b5f52cca482bd79213fd1c9fd9819b85dc @@ -0,0 +1 @@ +{"tx": "4a4547c3028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46301000000d1c47481dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b90010000006136b0e302a00c5b0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898718b3c029", "prevouts": ["4bef3800000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "d1392400000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ff7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e9987eb7009ccae8c65258c62e5eac53ed5016922d24407b897adc5526f33b91916c082ffd0388de178727289f9edc245ed8244bc4e4186d1c7a66ea621fec0ad"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936481f5e4c3fecd787fe4d3635c6d8b344fb02d1f9c3cab01b9a7177bb21a6fd3df59f882dcce043ab5273f79d0d152c35fae0f251a6812c7f2d3daa07c20029a516c082ffd0388de178727289f9edc245ed8244bc4e4186d1c7a66ea621fec0ad"]}}, diff --git a/txscript/data/taproot-ref/c23bb15b95f0283493b5e9660535131e08c4b442 b/txscript/data/taproot-ref/c23bb15b95f0283493b5e9660535131e08c4b442 new file mode 100644 index 0000000000..ffad9f19a3 --- /dev/null +++ b/txscript/data/taproot-ref/c23bb15b95f0283493b5e9660535131e08c4b442 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2c00000000a3ce2e21dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1702000000adcbac73bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b02000000deea024702e1a1c8000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ace21d5c2a", "prevouts": ["e96d23000000000022512063372fcd34ad063156fb4dd322415aa59bbac8cc6a5a5ba702cef28a298d42aa", "ffd225000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "485c8200000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "final": true, "success": {"scriptSig": "", "witness": ["3045022100ea1e8cb884e128aa84d9e40a3c40db5fa74daef688a97cdcd9e6988d7e0e193c022045dc6b602193065d44469f3544d01626e2370c3267e9d6061182721d9f2bfaa001", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["304402205581dd3e5ef023d6b841531afe247e577b4fdb74ff032c21a2336221f63cf020022069f44da106b7ffbc8b296911dc01eaf67bbbdc7681749a0d72a088121abc404b01", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/c23dc3dee1bab058e9dda39e357268464aff6993 b/txscript/data/taproot-ref/c23dc3dee1bab058e9dda39e357268464aff6993 new file mode 100644 index 0000000000..abbc96548a --- /dev/null +++ b/txscript/data/taproot-ref/c23dc3dee1bab058e9dda39e357268464aff6993 @@ -0,0 +1 @@ +{"tx": "4e4d1dfb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a100000000b81df2cbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcc01000000b1bc72eb0373d0a700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df979722368987c51ca14c", "prevouts": ["558933000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "ccf77600000000002251209d7a18923cf92d77a70864db68b8be9c97fe6f327eec6aa2ee3bdf40725ab507"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b9798a20989a5feb5a965ca55edd87ba1217bc1ca04ecd2269077cb90160a0c2"]}, "failure": {"scriptSig": "", "witness": ["6a46616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c259be6e071636a46f638dc71fbf337480a65d62 b/txscript/data/taproot-ref/c259be6e071636a46f638dc71fbf337480a65d62 new file mode 100644 index 0000000000..495252c51b --- /dev/null +++ b/txscript/data/taproot-ref/c259be6e071636a46f638dc71fbf337480a65d62 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba0010000003f954bf360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706501000000f7025ddc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ec00000000d17f70eb03851b6d000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3a773856", "prevouts": ["90ed1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6154110000000000225120685f1f4d981f8d279e9288f3fac3f130840e4486d97e094876558f7ee35a7d24", "1f353f000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7eb1717b6b13726048969a2665ae197b80aa3a5f647d9b50693aa355611c1a6"]}, "failure": {"scriptSig": "", "witness": ["6a0e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c2606a81031cc7d45d665ff29e83009cdaeb09b4 b/txscript/data/taproot-ref/c2606a81031cc7d45d665ff29e83009cdaeb09b4 new file mode 100644 index 0000000000..c387d8358f --- /dev/null +++ b/txscript/data/taproot-ref/c2606a81031cc7d45d665ff29e83009cdaeb09b4 @@ -0,0 +1 @@ +{"tx": "3969ed4802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7b0100000059dcb48ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4101000000052af5c1039b12b0000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acdb000000", "prevouts": ["a65d5b0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "6f45560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_1f", "final": true, "success": {"scriptSig": "", "witness": ["bdeeaee1525e0b53b60a342fbbf99f814b8f7419e1a4c3609cf9e0df3412bd4c47ce6f1a34e8420e890e3da1d3b6302bd99f2933852ac9af26c1b10c8030892982", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1ec178ea05b35e92b545d8fbd11b059f8d8bb6a4a2a2e07d7f6f85028876d933474961b12ec3626a11226bc4c62b729c8fa089a0a669867de4cd6602966440251f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c2615fefcd8c48ae15d7cdf715cb7cbe15365bb4 b/txscript/data/taproot-ref/c2615fefcd8c48ae15d7cdf715cb7cbe15365bb4 new file mode 100644 index 0000000000..6d861bfd68 --- /dev/null +++ b/txscript/data/taproot-ref/c2615fefcd8c48ae15d7cdf715cb7cbe15365bb4 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5301000000c8edde918bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43e01000000b111da8a0260cd5e00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac99d03b50", "prevouts": ["5d9f2200000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327", "3afb3d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "447d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457430173849036d038bb15ccd29e38ea974083458e0cf50b14971883c73e09395afa4004b2cd3f2b5519985ef4ce40029d6249627881f39179d9882ffc68f5bb6a"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa08f12ff2db60e07951e3ece83f8d4c41d9b16f9cd93bc43e76ab3ca16313aee1430173849036d038bb15ccd29e38ea974083458e0cf50b14971883c73e09395afa4004b2cd3f2b5519985ef4ce40029d6249627881f39179d9882ffc68f5bb6a"]}}, diff --git a/txscript/data/taproot-ref/c274fc041bc18ec36b6fc361335ee8c903ba6539 b/txscript/data/taproot-ref/c274fc041bc18ec36b6fc361335ee8c903ba6539 new file mode 100644 index 0000000000..96738b2219 --- /dev/null +++ b/txscript/data/taproot-ref/c274fc041bc18ec36b6fc361335ee8c903ba6539 @@ -0,0 +1 @@ +{"tx": "e4c3fc72038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ad00000000ef3908da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270740000000074614a9ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1001000000e3195ced032611a5000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487bd79c71f", "prevouts": ["c47c41000000000017a9148bc1125bf4e3450c593a5be1ae9a05461832d39a87", "ad5b0f0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "b47b560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_4a", "final": true, "success": {"scriptSig": "", "witness": ["6f5add61f387f705b44928391e0e61f052851a5b6fc42e27ecbd22e50f941c9675a8958a35c82f8498529775d6c03090bbd893a043402fccd51f9e695a3aa57481", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a4ef629598f6c12594cf05a0b803168efd510ed412d7fe6dccb3066c1333c50bdbf86eb477835fe54992648b7af262e5f118ec9d1e9016364402960d58b762224a", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c2b521f99f9142ffd0f06f35fdbf0a1e6db3b411 b/txscript/data/taproot-ref/c2b521f99f9142ffd0f06f35fdbf0a1e6db3b411 new file mode 100644 index 0000000000..9b4bc68ba6 --- /dev/null +++ b/txscript/data/taproot-ref/c2b521f99f9142ffd0f06f35fdbf0a1e6db3b411 @@ -0,0 +1 @@ +{"tx": "b1bb4f9803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2400000000817a20b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127002000000008e1dc3c4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2e01000000783f4ee701e06a59000000000017a914719f78084af863e000acd618ba76df9797223689870f010000", "prevouts": ["90cc23000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "7ab50f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "546d5600000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f4b186db3068532a32fed88b54244ea5875c098571a7b8b359e587f4f4af633460b19c0accce5a24a056b98cce949d671afb14dd91d0cbdd469fc3f22c90b1553249301ac20ee33639c015b4a618b106ac87c8ade2ff7aca8998bda2366a260c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d0665fc26da953a71983666256fc3789345858164e4e7f74d6a240db5c0da6cab352ee2a6a8e236a875eeadb35b814571c290bf5fc32e6cf848a4bdb48a3dff6032c3262f8d7c29daaf8f9846bf0ed9dbcc4a0f9aeeb7c8ab8b4ceb985f45a6c3d30bc3225049ba56ac02c164836762858abedae6e6cb81f8117394fa9e456e"]}}, diff --git a/txscript/data/taproot-ref/c2bc316e1620048c72dc6375bd6c4de0d175594b b/txscript/data/taproot-ref/c2bc316e1620048c72dc6375bd6c4de0d175594b new file mode 100644 index 0000000000..cbe1b04d3b --- /dev/null +++ b/txscript/data/taproot-ref/c2bc316e1620048c72dc6375bd6c4de0d175594b @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdb000000005eaf85bf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e0010000001162e7efbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9701000000c3c69fd004347af5000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac82745761", "prevouts": ["612151000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "c6b8340000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "f439720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "d97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c4a25f5074612e823ed206625c69690dedc2f0ffcf1fd8ec35ac2b8f31f4b29f72d95b601af8434dcd53e2a5d08dfad1c07e45b1031877afc5b1801af7debef3d33b10ff9eee8ff434f7c79f826d5967b94922da2ad2ccade1cbab3a3658011"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93673ae5f4f7cd376f4441ea68f12423409d9361f7b0ff0edde6dbcb904ee162fe14852eda400aa94cfe5024bf6d05446bd810daab3c27f5a95b027bfb109f343b83d33b10ff9eee8ff434f7c79f826d5967b94922da2ad2ccade1cbab3a3658011"]}}, diff --git a/txscript/data/taproot-ref/c2ccbe9e06e6c7ce6e43c0b381322fc7dc10a2c2 b/txscript/data/taproot-ref/c2ccbe9e06e6c7ce6e43c0b381322fc7dc10a2c2 new file mode 100644 index 0000000000..2e2d439bf3 --- /dev/null +++ b/txscript/data/taproot-ref/c2ccbe9e06e6c7ce6e43c0b381322fc7dc10a2c2 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e02000000912e21dfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9a0100000031b47cf98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4980000000092ee46990448da0101000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd8010000", "prevouts": ["ac7a4e00000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "3b7a79000000000022512065eb0ad8f24d6d8eb63c7f85eaa52926e45dd0588dc97971df796ca5c67918e7", "18b33b0000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "847d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f045d3665eb25ef0cfe4d08419a1eb3800b7f1f14f27f92c2783d7ecc4f2c0fda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e9f6b3154707dfd0cc47160c458b5d6bbad5dbae79d1b1aff02b8c8f076d5395a9f31796df107fae040796e44aea27c7a7d41418cdc7206378fd34089f9daf951"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93676c67a55215528913c30fec21d45efa8c386b671cc94599e91e8442d85e2d1cc9f6b3154707dfd0cc47160c458b5d6bbad5dbae79d1b1aff02b8c8f076d5395a9f31796df107fae040796e44aea27c7a7d41418cdc7206378fd34089f9daf951"]}}, diff --git a/txscript/data/taproot-ref/c2cdbf0cad554855e5a2c77ade2426042fd077d0 b/txscript/data/taproot-ref/c2cdbf0cad554855e5a2c77ade2426042fd077d0 new file mode 100644 index 0000000000..a6f6f56451 --- /dev/null +++ b/txscript/data/taproot-ref/c2cdbf0cad554855e5a2c77ade2426042fd077d0 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbe00000000a95271d0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcd01000000c9707a1b01a42ac8000000000017a914719f78084af863e000acd618ba76df97972236898781bd9444", "prevouts": ["5b3179000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "9c0875000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402203bf34d1bd454373a50eec8a5e728c39cb8e09001f12513069d215a1b1680188502204f118ccef7d2555779780a1fde3d1b0f336f9132acef2601a8459619177c910902", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402204b3eb0544a48531b4bb966c0bfd3b5b6ef629545c27f893e1f6bbb12c375a0580220733de28a1be355583ae9fc59d112b671bdf0b2ac08b4dc69a6217b5819c7440002", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/c2fc3139b18939587fa9376d426b5ed6e5a7d384 b/txscript/data/taproot-ref/c2fc3139b18939587fa9376d426b5ed6e5a7d384 new file mode 100644 index 0000000000..b2539a2659 --- /dev/null +++ b/txscript/data/taproot-ref/c2fc3139b18939587fa9376d426b5ed6e5a7d384 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3b0000000048f62767dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3600000000af19cd280474a0a200000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df9797223689873baeb45f", "prevouts": ["0bec7b000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "0f91280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["fd4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365f3e79e727db2ce69498c039b8b655f97a15b215378db35ebb03872d036f84823effc93d9a59775ec6af4eadc6f66e855123af6e736654ec63572366f38b17272c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51cf0ef20a11005175256561cf2f67252fad6f828fd45e261da47aa072728c1e1d416efa3a61de7db58e4e5b27e55eab88df01883130071a88e8c07ccbf4e37c61"]}}, diff --git a/txscript/data/taproot-ref/c30440e2e36842767c6880d3419ffd67d8fc65e5 b/txscript/data/taproot-ref/c30440e2e36842767c6880d3419ffd67d8fc65e5 new file mode 100644 index 0000000000..f66a6a4557 --- /dev/null +++ b/txscript/data/taproot-ref/c30440e2e36842767c6880d3419ffd67d8fc65e5 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7001000000a1395d8cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff900000000c2c480d30471ffe6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e733000000", "prevouts": ["a365820000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e03f670000000000225120f6b24239f005e5ad8a4113ec06c48cda726a0e511c023e717379412f24fce34c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8728012ebba8229da41e85c5b00392b3bf786c257585b2b15d31aca865d893b"]}, "failure": {"scriptSig": "", "witness": ["6a87616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c30828b92e910f121013ae0e7e80f112ff29c40a b/txscript/data/taproot-ref/c30828b92e910f121013ae0e7e80f112ff29c40a new file mode 100644 index 0000000000..dc29ae2e88 --- /dev/null +++ b/txscript/data/taproot-ref/c30828b92e910f121013ae0e7e80f112ff29c40a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce7000000003197a88edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cea01000000b341e2960409599100000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6e0000000", "prevouts": ["745348000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987", "f5084c000000000017a9146db815d9819f256ca5d1e70b15558a98689cc52e87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1660142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["3d7449d3d77f1da18c3361e93814547b7c2706a727e9fda503840ec216e01fb524548e807051b5032d4b8ace50a272df365cc1bb8608790ac017d997eab25e9f", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c30e1db5cebdf16c793ac3774df5940ba0cbd27f b/txscript/data/taproot-ref/c30e1db5cebdf16c793ac3774df5940ba0cbd27f new file mode 100644 index 0000000000..1a16550b22 --- /dev/null +++ b/txscript/data/taproot-ref/c30e1db5cebdf16c793ac3774df5940ba0cbd27f @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c22020000002413a1c9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6701000000ebf5dac603056f6a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca045f754", "prevouts": ["7aa5480000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "691d2400000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_73", "final": true, "success": {"scriptSig": "", "witness": ["51c9e0ab65da7fccc01d3bd3d58d7c97ad08adb582ab798a516708555cf656e4d6c5f66658aa78c5d42acc5e28261abc0947fe01a867207f73196947a5b6d38481", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["bd03c9cf21c7618806d5e409ef472b991a286b52d2131d7c0e602691857d270b49d6b52711682b55c4046644496c905826f5230b3068d461823df725fba4bda073", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c34e8364c057d48255c31d4626eee97cb90971f7 b/txscript/data/taproot-ref/c34e8364c057d48255c31d4626eee97cb90971f7 new file mode 100644 index 0000000000..d6cb2b5b99 --- /dev/null +++ b/txscript/data/taproot-ref/c34e8364c057d48255c31d4626eee97cb90971f7 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3101000000c451b5dd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127015010000002772d9f604f9e86c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df9797223689876014a635", "prevouts": ["13265e000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "6cab110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d5", "final": true, "success": {"scriptSig": "", "witness": ["85838c332a60598ae003c09c62d8c6a00b57488a5977fe58dc59d3ac4b5e2d7b98ed6004b3104eeac1d9be88b15172a86df3662d7085e9867e0a44c15a36aec503", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["4b331e586a685915952247921e66ec5d71d2e07ff2b64a9185e6004453a31e0636e318d9194dcfb999dccbf82287d5dc6999f63243a1d36850618b1ac0dd4139d5", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c34ea38700b3874b1fc56b98fba764e26e442bbf b/txscript/data/taproot-ref/c34ea38700b3874b1fc56b98fba764e26e442bbf new file mode 100644 index 0000000000..a10fe95911 --- /dev/null +++ b/txscript/data/taproot-ref/c34ea38700b3874b1fc56b98fba764e26e442bbf @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1800000000ddf5b1838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4780000000089a2312a02051d56000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acb49fde2f", "prevouts": ["49f925000000000021541f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "afa3320000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["f3d1ed496c94623ac0a726e91f1ebdf8d2f1f8fcc969396465b5fd55d0a712c470db6ad280ddedd08026910fb3b73f38cc204ea712a73f0461c35e266bcc793b", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c36f9ecac75a1f8369062bd659d7be8116d9426f b/txscript/data/taproot-ref/c36f9ecac75a1f8369062bd659d7be8116d9426f new file mode 100644 index 0000000000..52358b726f --- /dev/null +++ b/txscript/data/taproot-ref/c36f9ecac75a1f8369062bd659d7be8116d9426f @@ -0,0 +1 @@ +{"tx": "c6803302028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48001000000509492ecdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba7000000001c4789db03c46952000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6caebe045", "prevouts": ["280f360000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65", "6f4c1f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "df", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936744d5f1fe8cccbe7a1aaa208055fcd73d33095ca4828da666b0d1eca647814e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5115b534b99635107bf366447ce9661d5eae557250694ef66e76c31b44d1abe134360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d27e649847556e23192b8aeafe173c243f56175d6d7082b77d4d94508f7534d8345e83ad245d963f373c443dd6457dec3808a4f865920e34bbc543e7d04d4c3d1c315aec02adde316e700f87e7c47f474d1ec7cdd06b196ee567d81a15967a13360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}}, diff --git a/txscript/data/taproot-ref/c3759872dcc57d4041c64cfe3164f0beae9647dd b/txscript/data/taproot-ref/c3759872dcc57d4041c64cfe3164f0beae9647dd new file mode 100644 index 0000000000..929cbf6ccf --- /dev/null +++ b/txscript/data/taproot-ref/c3759872dcc57d4041c64cfe3164f0beae9647dd @@ -0,0 +1 @@ +{"tx": "dbf3e74b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b890100000001737dbc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700a0100000096c4f09401d39209000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478760000000", "prevouts": ["7252240000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "189a100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a0353c5fbec3cc02a1bc5415d9b11e293487c4582e3bf764f748581ab8af1a21ed68ad085f5a382b0c2fbdd0c22361680fdc52720905ea6f5dbd48c464194db6aedcd2fc9c5943fe706019db34269a1ea53cca57e4f35fb05ac8058a5f51476448699f23776665bd579d3518c0e194fb49f63244e5db8117060de3cc6ffd2eb3100ab31a14e3515571954fcb661c2c8d74c8e506be28b545f26de328e9d2779070e53d4ebc66c177b9fd080ae4f11e27d641f53fe30f6c64c58b84ead84cae709863835327fe1a7fe4a8976b703b592dbc3d259b73e2ad87632a3f2940c432dc0d8950d3e20c8784fa2a6e25576a01ee58417463b338c8f28637c8a756bc9dc58e5849a5875bc3f702b6d37eca2704b77802926670adbbb6549b4f48cfa18565a655123c24f5062f8eb147cb15312aa871cc6c3becf43165c541b0ce8d93b20925848228fa13c09e05763ce05713c531205c76ab45b055e284ccdfdc89691a3551de7276dbddd1c547e2cde3ed75ac6b67742c95ce80ce2b4edf9f8f4a772910d9d16413082269ae065f28bc88e007b723a2539efd081eb4574a8b21c2ea77967cf3354fe09764afe6ab12d4c73cef933f480498c98c576589fd995b601c2504648c485e209a0761dc1b2fee8c09bc5612d735f694c3a508050988def09a808da552d382936217948cfd8fb0538b7d0674724d2a349c497f952732f4e47ddc45242d009cc2b8aba16f75", "367d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936081632f3fe6f9ffa833663821f6544b710f6647bb31cd6fca3974f1c38eb8a74293ebb87675db407435945ccb2e2a6a79ad6cc0b8e2f03768d51396c4a1768b6d4d2cf0b4a04f3dfea651ef6d0b2c4d5fffa0a14be5e227661027bf8174dd263cddd84017ed719a58f336e1892f80afe07727626533c4c78318e44c39862ffd3"]}, "failure": {"scriptSig": "", "witness": ["4d0902b1185ae26fd8fbdaa90c2ffc87f13436571c7b8bc43ab1bb2c6927b296eeba7eda9d5cad8204e4182bc8dfb6326e98a45b19c3e04ab998cf774a9cd59514a39519944fea0721220ec9f67c08cc8769aa11805ba2d2baf8742d7abebedd893fcd60be501824168b0d7f38636bd0f9f563f94c1d15e75db5993ed1c6b8de187f95c5ec7334ad62aa0ba08c3ec489a9fc9be069e4732f9fbacd49771b78784b5c5af56e88ff351bf5afbebfc30387753be76312b3903b85db9621738b7fb164e587972b720fa7a5fb5b858c9d101f6b13b46905834b11ee8be00d797c468f42fac1e5d94c24cee8d360a968d571de68bf927d96c377e73fdc1433290a6197b9bb7510155efd661eec9cee2792ebf1bd38a99c73d595c5b2e56a684ca28437fa71614758c34ed4660a8600d1b8a7eab51d85d2c50fe7245a178220a35f17cd0a72e5923127c6d7de0120987191a7516acf5e772ebf22b48a55ecbf6cba26f6dc0664a114188c120bbc6d8586f7a08947ff22d193ac2543bce6c83584b87b8f8977433dd41eff14ab8dfe6b98d5f8b825455d00c126b4a43705e022b0f663e2ae8dc5d30c15a3168977dda3688d4c487c28e8d24fb3b25dcf34d6e7004f32a8cf38b56024913764eab419c634fea81ff0cbe2742f6128c142051ccb614933ba48a653c29649c746f7d6f45af54a0769c00872cecef3466191c1213e713696d1d6cb596f9761f401e1eeacdf75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb94a5b3352296838f351f650ec3ca72e25dc2a412f5bb92aac76541fe277cb7178448a7537869648343bbbdc00eb4ac0785a5f2aec0111e81b0d25ebde82a92a"]}}, diff --git a/txscript/data/taproot-ref/c37b0f05074e165869fb4e36093d5d05e7f5cd58 b/txscript/data/taproot-ref/c37b0f05074e165869fb4e36093d5d05e7f5cd58 new file mode 100644 index 0000000000..e7561b0624 --- /dev/null +++ b/txscript/data/taproot-ref/c37b0f05074e165869fb4e36093d5d05e7f5cd58 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2400000000153b568004314a6900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac500a954a", "prevouts": ["f5056b00000000002251207c84ae2d9063cc63412a30e00823aa01b05bc54bcf6d9936dc1c650bbdc9e98b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/truncshortcontrol", "final": true, "success": {"scriptSig": "", "witness": ["ae8ab4a2676af693dae1493617eae9caa947f452112902321a990ac6d74668a97ca7b2de345690fcb1815bf33baed1aecade9d1324b0318ece0425e4d9129855", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20"]}, "failure": {"scriptSig": "", "witness": ["ae8ab4a2676af693dae1493617eae9caa947f452112902321a990ac6d74668a97ca7b2de345690fcb1815bf33baed1aecade9d1324b0318ece0425e4d9129855", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", ""]}}, diff --git a/txscript/data/taproot-ref/c38df517f192e8ee8b749587f2286408e1add7af b/txscript/data/taproot-ref/c38df517f192e8ee8b749587f2286408e1add7af new file mode 100644 index 0000000000..9846d9e719 --- /dev/null +++ b/txscript/data/taproot-ref/c38df517f192e8ee8b749587f2286408e1add7af @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270230000000056475b9ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca0010000002f35f8e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8900000000ccb14bf503f56ee6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898746a49225", "prevouts": ["6ab20e0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "e73c5e000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "aea27b00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d25bfca305a764261d6521057603065fa946acb912c8ef078a9b999bf9159765f90762efe0ab9c58ac6ee07d07c88c733679b2f6b8a5cfbbffbf19600e5ac3c60b9de9d2ee16786568422ac483b36fe1c9fcf95e65bd3b063efa967e10d688730cf51f63f2f8d866e6663e3b4cb94fe811e1886694db682d7576d055e1b313b79f8ca6e54d8d125a3942d479774dc7a0d5f4e722a498ada7ab9ff7e33cb285ea9a05bfc8ff664a654c0014933940d35ffb6330ad111c7ba46295d01d70b1ad1e8ef0a133c3b33ad3b8b427be3f91cdfab40c1d8987229c4083581d550d42a4f5e6456b7000ec246f155d2feac21a3a09fac2bf6a859cf6c4d01f490d9e8bcef9c62daf9504d6b14d9fbeaebe8463bf3d637aceba337e936de34abcb8c37565724a388f7b21c96aa2e6b7a9708f4a9d2a9c66ec97e68d455fa500aba487966518e2f4d4c1a37f461ed6564676d4569607b21af0360a8afab9f99fb3d27cfa42d6a93bffd3ffc7be1120514697ac003584621b33a5ce5b81b734f9ef02cb25d0190a2baeb94634c32942a2f0309eae50b104420d724fdc1a0b68418915c254da6fd68d9fb31883fb21d8cc35fb13468b0908b466787e2a7a7e4518ebc560400f6a0c0784a24a35d9dcde65b878efff28b989e80b7bf9fb3aab53a326db801dbe9c9c47b01b567e158995ca8316ce84b01614dd5b7446bb86909e9ec5ec80c2a80920ee5041b262a9284175", "a17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08204a5fb755beb1eb88fd06fac279ccb2aada241654186a69e6e0c04e3255c18f895176026b3e005afce4c10b5e59a002659822bde369bd64201565ae4c88fc95c"]}, "failure": {"scriptSig": "", "witness": ["4d090274c8897502c436ef5bd271900ed9cf2e4489580d4929443ee4b54bdcc447f5bf4ffa9ee2a9543e50dc29871f45738f58664faae0e9a0762a1c3891d331318a3639c6da5b34f1f5712fee12ea17c629d3947499670a36d9764ebeb484445d3a1b995c5a90d513b4910821e3b8973a691e594af54ddc677bdd6f3a2aaed2b2c593c45785ec834ee2909e7c4d0ec2b93020f7e01db088f3244c252fd8526847108b04e675352df98bfea502fc7b82fe4ceb001313ea8b3f29faf3b1d25350ba2ad704a823a10fc8d9f148df7bd06185d600e4f8f0ad0a2912c87abb39975335cf0b3f8aa949020d49a947271834ecc40f7509e40a01559acd39f0d8a8bc40a908424a5f991f5ee3ba5bc12a29d015bac511be049ce986e39aa14f2590e5291d5cb0d96b3b7b64636220b73c76f376767539887a8d4ceeb8671e5b5a92381f9b4e1f6a836a5881e02b8af8140cdaa1a237c6ca7258c3efb641543fd15414ffae1940b5ee1c4b0d1a641d79d6ba7af663635c61cd6eec9c1a615295f099ede06729c6c747ca7281bf648477b8eb27cfcb2c682022e055d620df8aa75a70fbb923496f4eedda6f31b942017684ce49b902cb0e6860f11bc310939b085b972f211035c8091bd5973d18fa53ec56ceed6fd5086a3dfbf0caaeb35ce20ccba35644f51538a0b8feaa810749cf605d8611a1c752b716cb22a8cffb4642292b1ad976d9a56a9813360a4406eebd9275", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936807704338d8ff9f1c6c694bb815b9b0acb03731da8a0b1434ebd817fa66edf1846c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa09531ab440e1705f1c4b791477abf2a4fd5d47d92b3cb9e3998348c9d3a452b095176026b3e005afce4c10b5e59a002659822bde369bd64201565ae4c88fc95c"]}}, diff --git a/txscript/data/taproot-ref/c3a855f0999c9f0c734c21ec479b4a2de052c197 b/txscript/data/taproot-ref/c3a855f0999c9f0c734c21ec479b4a2de052c197 new file mode 100644 index 0000000000..6386cccdba --- /dev/null +++ b/txscript/data/taproot-ref/c3a855f0999c9f0c734c21ec479b4a2de052c197 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42c0000000025baee978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42d00000000755c9fcc03cfd46800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac95000000", "prevouts": ["4b5534000000000022512014c9f4af3daae468ca53c2c267c1d6c7824da89a84a3ef6d580562d3f844fc64", "4ff0360000000000225120b7b7f868117fc9823373a98908173a9736217ba3f26290a84f96d4cb32d63ac4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b1ad425f8fa42485d7293364b8a850d7e34fa33327ba7ff1de82301dc0a195e0"]}, "failure": {"scriptSig": "", "witness": ["6a7b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c3ca44e765c59aef19ebc14444cb23801ff338d4 b/txscript/data/taproot-ref/c3ca44e765c59aef19ebc14444cb23801ff338d4 new file mode 100644 index 0000000000..2d3834ebc2 --- /dev/null +++ b/txscript/data/taproot-ref/c3ca44e765c59aef19ebc14444cb23801ff338d4 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c33000000003fb3db2960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708000000000f56cb0cedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5600000000b56ec84c033b18af0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac87d19161", "prevouts": ["5469470000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "ad4f1100000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "392e580000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "eb7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7d98603ca11f2d62da2f097293e2a9fc40838a31eb24ff9d7fe998ee66e0434e58e476735d98d5a1185fd7ff42bb7b31cec58182079010d151d415fc7d6c3e4c2ce937a5de573933a673baa3adefc0607b7a8b345eb0a9388ff089ef522bdd2"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fec5402c57463b820a037283baf958dfe8fa8ff5b14330867ba864fa7bbb305c3f13c9f2c0ba7c3724f3080ca99cfd230291165bf004db5bbadb2403d0b759af84ce21fa65bd655e7fa8dd3695f51b098b96b5173f87464f2936878bf520f49fc2ce937a5de573933a673baa3adefc0607b7a8b345eb0a9388ff089ef522bdd2"]}}, diff --git a/txscript/data/taproot-ref/c3f3469ae6022ba9a824d15d3e5c6966ecd2729f b/txscript/data/taproot-ref/c3f3469ae6022ba9a824d15d3e5c6966ecd2729f new file mode 100644 index 0000000000..7a3982e272 --- /dev/null +++ b/txscript/data/taproot-ref/c3f3469ae6022ba9a824d15d3e5c6966ecd2729f @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b930100000044a29d078bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40600000000ce8be267bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffd000000004601938b033b82dc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33000000", "prevouts": ["0ba127000000000017a914e014b0ed75ce4306970c9f63e88b08a5a7bb4d0f87", "44813e0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "691a790000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2358212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["8f6e30f3e56f652139cfd8158d375f33d485dd0df08e2f04d20e3a4c8483122635fa195cd56cae46f25bf0f0a5697ea06506b59d758f9fc437dcb656cdd1652e"]}}, diff --git a/txscript/data/taproot-ref/c42ba6332f5103b6c07a6d7b7c7a96e1345fcad3 b/txscript/data/taproot-ref/c42ba6332f5103b6c07a6d7b7c7a96e1345fcad3 new file mode 100644 index 0000000000..f26409fcee --- /dev/null +++ b/txscript/data/taproot-ref/c42ba6332f5103b6c07a6d7b7c7a96e1345fcad3 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ec01000000cb4377a0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffe010000004024cc68026864b900000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdd020000", "prevouts": ["64e73a000000000017a9140917710a6236c7a08b54f54b004ee705f2913e3087", "d82a810000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "235f212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["ab4e0ec3823951d486f9919ba80751933ed66a0103bfa7a6f7350498163a4207c3765fb3b485bf9e438288b898517a24a341a53a713d248ed56b9e4397156ab8", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c4499beb83fe2bbc215490890a252106247a0d03 b/txscript/data/taproot-ref/c4499beb83fe2bbc215490890a252106247a0d03 new file mode 100644 index 0000000000..4771461e0e --- /dev/null +++ b/txscript/data/taproot-ref/c4499beb83fe2bbc215490890a252106247a0d03 @@ -0,0 +1 @@ +{"tx": "88a47fd8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c442000000001eaf11b1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf21020000000137c7d2049d1696000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc370c5044", "prevouts": ["466038000000000017a914525ca05541c81a105639c2efb802eaf5596cfe0187", "94b8600000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "21521f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["81cf41ac01a8d340559ec283da8639f3fff7a149b72f7168ecf7c03f4414197cc498af8b0c059c0e1181f6662b53f98c1fcc8d007d3e425884e23a06c8de5ffb"]}}, diff --git a/txscript/data/taproot-ref/c46f7002e386e4c4fd5c63195b15a2720dc604c6 b/txscript/data/taproot-ref/c46f7002e386e4c4fd5c63195b15a2720dc604c6 new file mode 100644 index 0000000000..1095aa4e59 --- /dev/null +++ b/txscript/data/taproot-ref/c46f7002e386e4c4fd5c63195b15a2720dc604c6 @@ -0,0 +1 @@ +{"tx": "4b63d655028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43401000000a620dba3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1201000000e5f7c897016aae05000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374878343df53", "prevouts": ["fabf390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "197a490000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["c5eaf172084393ea09a176390f4340749936672be03925208dc1f3cbdd1cf29a65dbe5716817f2f69003e2143c5e08043bf2f8dfbd59fad28648d31d2301f8", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef3255bdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/c4b2c2074e18699523a8e60939dabe323e8cfcc8 b/txscript/data/taproot-ref/c4b2c2074e18699523a8e60939dabe323e8cfcc8 new file mode 100644 index 0000000000..02de777b06 --- /dev/null +++ b/txscript/data/taproot-ref/c4b2c2074e18699523a8e60939dabe323e8cfcc8 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b74000000004fcd769dbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9d0100000099219efd01df608a000000000017a914719f78084af863e000acd618ba76df97972236898710000000", "prevouts": ["b816270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5df17c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_30", "final": true, "success": {"scriptSig": "", "witness": ["2503a87d74c773c4ed6a048416b1efc81fcf8d395b0435b453f7c08e2d5fa2f0dcc0bc4fe63991f93aafae30dff7fb33065c6aecae2bfeff9344aae72d49921f81"]}, "failure": {"scriptSig": "", "witness": ["8b436722229002c05ea6227a29ab4f3713ab338d5186cdd97fad8a99c28afc00214b81f78110290ac1ac8e3695a2c46f2340fbd99add439f17606a80d715429e30"]}}, diff --git a/txscript/data/taproot-ref/c4c19d4cee5d79334aa9c0ff61f19d321cc3941e b/txscript/data/taproot-ref/c4c19d4cee5d79334aa9c0ff61f19d321cc3941e new file mode 100644 index 0000000000..8f46ddde5a --- /dev/null +++ b/txscript/data/taproot-ref/c4c19d4cee5d79334aa9c0ff61f19d321cc3941e @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba000000000a4dea4a4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c51010000001e406ea960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e01000000c86dabae0117a21000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac57020000", "prevouts": ["0ca3270000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "d08c4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "08ab110000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_16", "final": true, "success": {"scriptSig": "", "witness": ["be863d3cbeba81efdade24b193a1f92667829d56035609ea44bb08a9739be1c5adb31005e64216ab1cb23a0575cd5533c045a435ee02777f58da29ebf95f75bb82"]}, "failure": {"scriptSig": "", "witness": ["d3a029059e0dcc015bec136d195e1af3206f9150495ab29ed25a2747483c9b619e3b23555a2b749300d9db591cf7ddd4fe4b57d28a5a6cbedf7f7cfa5d0ca42516"]}}, diff --git a/txscript/data/taproot-ref/c4e28343af816c29311d37b8559a05b14d797dd9 b/txscript/data/taproot-ref/c4e28343af816c29311d37b8559a05b14d797dd9 new file mode 100644 index 0000000000..7e4bb864ed --- /dev/null +++ b/txscript/data/taproot-ref/c4e28343af816c29311d37b8559a05b14d797dd9 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4901000000049cf49e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b801000000bc4daa160275809a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e754000000", "prevouts": ["0c3a6400000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "53e838000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["b1a80ca318006d147a1d5e9a294c73ae01beed6bc88e14ab81d5c11d79d99e2396b4366028f860e35e0a8e59195a81b7eb4ac68f35c80f4dfdfd5e0bda8358acbd6832953ae64d", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/c5c550da4ca7e932cdd65a9656f2f7c611148d24 b/txscript/data/taproot-ref/c5c550da4ca7e932cdd65a9656f2f7c611148d24 new file mode 100644 index 0000000000..650dbbe13a --- /dev/null +++ b/txscript/data/taproot-ref/c5c550da4ca7e932cdd65a9656f2f7c611148d24 @@ -0,0 +1 @@ +{"tx": "9e51fc1b02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf32000000004143349fdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4beb000000009abff0ed03c1d68f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ace21a0c39", "prevouts": ["01b468000000000017a914a8c07d8aa161ec0fed82ac1dc93d81dd0a92012687", "54c72800000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "235b212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["80e9c356061bf2ece818b285b3817fd796f5e94296dcfef4c951890ee0a1392b75d52da360c9343ac115e95d49959626b9c80f33ebc2f427e11f0e5d889c151e", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c62a6dec1ec0c7508b82a35dfbcc1d66455eb241 b/txscript/data/taproot-ref/c62a6dec1ec0c7508b82a35dfbcc1d66455eb241 new file mode 100644 index 0000000000..6364250e5e --- /dev/null +++ b/txscript/data/taproot-ref/c62a6dec1ec0c7508b82a35dfbcc1d66455eb241 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4601000000944c61c260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706800000000ba4a2dc30216b76a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966b000000", "prevouts": ["4bc55b000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "f1b4100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "dc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e96c63bd25ae92bbd16086cd18a0ced65254d43d2db01fd8c973d5ac979d0978d49cd47170ad660e437289f08833289e3b90e14293c0ba427f1ef2b5a93f8559a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e3bfe8b0458382ba4f4ce4b13b8b707c198a710172b0004e49e202e4d70abaa7b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936754c3400f5b19129397404414e73e7234111a3665d4d5bc651a2a24db00d5dfa276acb01c569c39653cc9be144b4517abeee153b1e65c2a7dfaac73ffa4f7941ad29df8a0e62e4f40897f8996914b12118c918ca2851b639742aeab01f587290"]}}, diff --git a/txscript/data/taproot-ref/c62d08fa40199eb68353dc3045f6c961f21f080c b/txscript/data/taproot-ref/c62d08fa40199eb68353dc3045f6c961f21f080c new file mode 100644 index 0000000000..53f5365e5d --- /dev/null +++ b/txscript/data/taproot-ref/c62d08fa40199eb68353dc3045f6c961f21f080c @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ed0000000047b48efbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf38010000006d3fa388017bcc44000000000017a914719f78084af863e000acd618ba76df97972236898720010000", "prevouts": ["ee9241000000000017a914a4e57198280c195671631f8b9014214c2f083b3c87", "da80710000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2260202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["f0349b0aee20ffdcc09dfdbd87d830a0aa3a64778c92c76b12338811097b9fcf9b67ec92e0109d3a50c1dea117f169c9422e93a567b54205210b26c8f23016f1", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c63b3815a0dae098fa0dce37acfd79f213436d49 b/txscript/data/taproot-ref/c63b3815a0dae098fa0dce37acfd79f213436d49 new file mode 100644 index 0000000000..7954471e12 --- /dev/null +++ b/txscript/data/taproot-ref/c63b3815a0dae098fa0dce37acfd79f213436d49 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f4010000009c66389e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a601000000edc649680396c34c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acbd5a055c", "prevouts": ["012010000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47", "89513e000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "a77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364a2a9cdde08cc910ce988b5b3af607c33ce20f2129cfc5515902d1db320653d12915fd873a4966f8e9b4a3b328eef3933245a1c852c287990317c3760d8289da96773453f0744a158be0509abdec64f05b1db7ccf03251d8359952271b442a24"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93668c2eb14f3f3b0f24a166b832cc6f7897859f8840212d3936488d8e89e33a87eda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e389e677eaf5eeea89a70f01c0aa3bc14cf3320f4b6dd8cc61f33138af3398b5b11a008161139ac7a92b00665158d25501a881aeebdfdbf881ee45b85e0726c11"]}}, diff --git a/txscript/data/taproot-ref/c63fa7c5e9f3cfa3be54296de8fcb8c5bae42ab6 b/txscript/data/taproot-ref/c63fa7c5e9f3cfa3be54296de8fcb8c5bae42ab6 new file mode 100644 index 0000000000..721116375f --- /dev/null +++ b/txscript/data/taproot-ref/c63fa7c5e9f3cfa3be54296de8fcb8c5bae42ab6 @@ -0,0 +1 @@ +{"tx": "1aeda83f03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9900000000a9e71ddadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1601000000c1e722ec8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bb01000000a0e9adf902bb0efd000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdf000000", "prevouts": ["6cae7f0000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "02fc470000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "ca9e3700000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063dd68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c4bab67da474338ff25cc5ed4d52931383799134580fe83cedc8cfd52799276c98751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d5c12d2886f924517b8c41f4755cb69ff55f68e740076f0e346dfe7ab1da23e202491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d5adfb4b655ff7e7194216f0c9ec7a59b69961b08133bf278a8ed5672f2f6a4fc12d2886f924517b8c41f4755cb69ff55f68e740076f0e346dfe7ab1da23e202491431d89488c08702db3cd2303e8a25c8ede371a8df5f96996e099ce5df632e"]}}, diff --git a/txscript/data/taproot-ref/c66c43a4b77a41b0bcafd8714216e0e515ea32c1 b/txscript/data/taproot-ref/c66c43a4b77a41b0bcafd8714216e0e515ea32c1 new file mode 100644 index 0000000000..bad39b44cb --- /dev/null +++ b/txscript/data/taproot-ref/c66c43a4b77a41b0bcafd8714216e0e515ea32c1 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127076010000009e98a7e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb70000000033ac90db0331e2690000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f878995083a", "prevouts": ["2bc7120000000000165a142540f27e90740933c99d4f17ab2dfc6c82951cfb", "e0b558000000000017a914d574841bde7bf0817694c799002118e85acf040e87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "235d212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["5d53555bf050efc78515fc7cb41c96d7a5577eda299f538f278e08d430aea10e705ebf7db220e1af5856af41294d05b57012e168300ed505ba92d690f812f174"]}}, diff --git a/txscript/data/taproot-ref/c671d0d61110d22335aeeff604afc7a78832a1f0 b/txscript/data/taproot-ref/c671d0d61110d22335aeeff604afc7a78832a1f0 new file mode 100644 index 0000000000..bacc74ee14 --- /dev/null +++ b/txscript/data/taproot-ref/c671d0d61110d22335aeeff604afc7a78832a1f0 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfda00000000be838db68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e80100000074bdb79c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b0000000006cc0e3ed03fdbde60000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a613ede228", "prevouts": ["566f7f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5c51330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0198350000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_75", "final": true, "success": {"scriptSig": "", "witness": ["aaeba6c1347ae721ed1685124a736b3d03522c05f4eb1a01b2bb8b6d33440b30622063dd44f473bb102095c4dbdc709ac36c17dc0b49b65992348cab9968a96583", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f76413d14bb611731012362e78efbcfe20d658bf81085c416db1b1893e09f72916007c0e69aaf4f61624911b83893045ba5c3c5749bedee55aecf8f8b404d72d75", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c684723b339ed9a247b5fe843d2111fcb009cbf2 b/txscript/data/taproot-ref/c684723b339ed9a247b5fe843d2111fcb009cbf2 new file mode 100644 index 0000000000..9b70410987 --- /dev/null +++ b/txscript/data/taproot-ref/c684723b339ed9a247b5fe843d2111fcb009cbf2 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b650000000040181b27bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfed010000000fb6f19301b3c016000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487fc000000", "prevouts": ["9d322100000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "cfc2690000000000225120a276d97cc1349e693e88dad472b695a8145cd2b116efbe16166838c11f43c819"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "de7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936337de194323cc2d0e259e7f698dbd99f7b4adcc7bc7010d92bfb10064ddb4e563f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08267bf5ee6e785c98394c7354db9cd2cb879e9766d4c80c1499d7b3e856282bd13a05e4a06b32de803bd9a925f4d86502b21cf2d106a73f15ada31e997750cbc80"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93639134f96039a0fa33d353d3657d4f6c27571ed27c9ba3a414c0fc3979439528967bf5ee6e785c98394c7354db9cd2cb879e9766d4c80c1499d7b3e856282bd13a05e4a06b32de803bd9a925f4d86502b21cf2d106a73f15ada31e997750cbc80"]}}, diff --git a/txscript/data/taproot-ref/c6911c815fc4eb1fdd0b9ab9cd09d3f6af2c6188 b/txscript/data/taproot-ref/c6911c815fc4eb1fdd0b9ab9cd09d3f6af2c6188 new file mode 100644 index 0000000000..bef8dcb178 --- /dev/null +++ b/txscript/data/taproot-ref/c6911c815fc4eb1fdd0b9ab9cd09d3f6af2c6188 @@ -0,0 +1 @@ +{"tx": "52c12c3202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7d0100000055114ebadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd000000000a78541e802e64d970000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898705010000", "prevouts": ["7bdf770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bd21210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_af", "final": true, "success": {"scriptSig": "", "witness": ["2e3a1fe130f76f0975ce2f5a48f984eaba47d877b38c26b106e6462a25092e38b7847704594af22f6e7dc42466872e3c7f2321322660daa44272609008bdc10c03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3cc4f3eedcf6199066344440ca1432536c072339d4b248de0b748e303ebf125d5c30576b558570cd4a2e55a21fba5edba7c6662c60ac98b2bd85d5646dd35a91af", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c69155ad942486c3313ec96fba99eb4b629b0b7e b/txscript/data/taproot-ref/c69155ad942486c3313ec96fba99eb4b629b0b7e new file mode 100644 index 0000000000..2990e2bbc7 --- /dev/null +++ b/txscript/data/taproot-ref/c69155ad942486c3313ec96fba99eb4b629b0b7e @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ad00000000d70bf3c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b08010000005adde9fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b60100000078ddf57604cdc96f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787521e713c", "prevouts": ["6eb8120000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "686e1f0000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "02ce3f0000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["de4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365d68cd89157a1768344d3693d5ddb5d4f8008c6471ee21a81a3a4b68d16bfcc31823ff0d5c6a769fa09e08a59a2485b611e1511239bba2f80aba2b92be945f1b811034f174cb7bd77652d345f06878a8d4eb3ae1b92590cd10e2563bf228d2d6bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}, "failure": {"scriptSig": "", "witness": ["4c52de", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363088a34860ed35f53da8979e97e04104e910b65ec5cc0eb3f7ffdd72be74d9da9c9e480d0f492be6e2f1ef49af1ad63a3a1c7bbd1c59ad16db6c35add41291c9811034f174cb7bd77652d345f06878a8d4eb3ae1b92590cd10e2563bf228d2d6bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}}, diff --git a/txscript/data/taproot-ref/c694a3b9670b92c47faef2482e1c373a96c84b7b b/txscript/data/taproot-ref/c694a3b9670b92c47faef2482e1c373a96c84b7b new file mode 100644 index 0000000000..0d1f968bdd --- /dev/null +++ b/txscript/data/taproot-ref/c694a3b9670b92c47faef2482e1c373a96c84b7b @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba800000000d44957fc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127059000000009e3999d502b1992d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ace6010000", "prevouts": ["9ad1210000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "92710e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "success": {"scriptSig": "", "witness": ["a69703bebdc49ffe28abcf4254c1e74f8ec62adde182675482310127231ce7fd145b0804a7e3b6a31c29921730a32ba8172061616170deff64acf66b7623ce9e81", "503f8c9a366ad4b7874653c110b34a04d85573ccceebbf42bb1624f0fd511c90cbbff3e616b6e563b6a73d39a2261da87df0319d882f80ff1170aabe48774ae76b5d4ed0326f39bfe14af90791d2ad0670d71d2718dbc542525425a8198447b90be5b28a57ac002e78f0eeb72f5044ee454bd21c76d3aba39e7a0f15573b735227331fda5d20883ed980e3d3ac53009493fd8ab45ecad062ed5b18373454e2fc9cc2a7c57e71614a42338273be8852e9f1df3a287ed0bd698afd025d027622799f917b7b29f4a37e2679a6b8e4e696655e7bc45e"]}, "failure": {"scriptSig": "", "witness": ["ae9d34ecc3acfdabcc7bd36fafb8dbffffd3d4a940c623b580e8ce08e4a7c7417adc0cd0658cb320b61b1a5f1a17327ad4ed3d27eeea9a6999ffaf544b0cab7481", "507ded0c5c1a30ec2c4ff46bf5deb5555c6ea2ba62db47889e0ac3730a703948f7b4d21a36530e2d16b76f80eae968a0cee80a5ff46bfc2f8d77f637f562bb8348fe9ff875d7fdd5589fd4f1fbac5e83f3c64649ecda77aa3384732c8d30c85c3aba744bdf3026f15bef7e8e523626eaf26be9e64b6ce6653aa38c273b903b6ca7511e553e31a42565959cc1956e1355695a4552a6f2e2e4578dd7ff1b40b2fde29742c704b0fe9b1d42b85c6eab03cd80739e3c8e85b23b447dd1cc2b"]}}, diff --git a/txscript/data/taproot-ref/c6a2dc24e570bc2a810731231121944aa2c4a595 b/txscript/data/taproot-ref/c6a2dc24e570bc2a810731231121944aa2c4a595 new file mode 100644 index 0000000000..95357da61e --- /dev/null +++ b/txscript/data/taproot-ref/c6a2dc24e570bc2a810731231121944aa2c4a595 @@ -0,0 +1 @@ +{"tx": "4e0dd6e902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8c01000000124e14ea60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709701000000743f899101ad8b36000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4871e000000", "prevouts": ["60bf260000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "a3c812000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93632573be4a708d1acd494d76701189b0a3fd387886b4d95dd6f8cd186553549461ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900450e2995ea6b9af074c8994aee2f7f851552d9aec0cda14b2daf9a27b43dc2eeb28859d05a814eb862cab9a6acf3b7acf0881c47896b22b56466b77992f62c0511"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362c2930913668888644f6abb9a2a8056455fd3fc4d16f365da86be00cecad5d5791fd70f8e44f42202023c580ea06f1578af3f03a2439147535e7b1f16736e0d18859d05a814eb862cab9a6acf3b7acf0881c47896b22b56466b77992f62c0511"]}}, diff --git a/txscript/data/taproot-ref/c6fa56d9a3cfa039c883bb5289ea577b65e788ce b/txscript/data/taproot-ref/c6fa56d9a3cfa039c883bb5289ea577b65e788ce new file mode 100644 index 0000000000..c67d320cd0 --- /dev/null +++ b/txscript/data/taproot-ref/c6fa56d9a3cfa039c883bb5289ea577b65e788ce @@ -0,0 +1 @@ +{"tx": "8a3f410701dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1902000000d2f9abcd02daec1d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487d2148434", "prevouts": ["27b8200000000000225120ed3968cff76493ece295a6213927f156d049a0539b8afc5b562db91ee008c85a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361b7a72aa3a05c14cb6a669fa7fd0ca3554039543f0462d8a88f34b84c6433f22"]}, "failure": {"scriptSig": "", "witness": ["6a15616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c709197b022538558c64745e06cce6340703a73d b/txscript/data/taproot-ref/c709197b022538558c64745e06cce6340703a73d new file mode 100644 index 0000000000..b088e7df7e --- /dev/null +++ b/txscript/data/taproot-ref/c709197b022538558c64745e06cce6340703a73d @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1100000000c319839760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270290000000027cc25ce0383556300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b1030000", "prevouts": ["e6d3550000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2", "32340f0000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "717d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a84e3bf2953ddc9cb8e31c297a3a65f2ea0223693047b485ee05dec8a9b2b04be4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8674d0c931fae68ff43996ef27e2c8ff69e275e322181f769b95dd7ebb695302b667dde4f09f14471eadd81946489c41cf4fd01382a4947d773f1f2d4d0db4c57"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b2bba68bdba5bb63faec40886b7424a0b364c5795c89d5df60ab242d96dbfca40b90ee144c073a081d1ef827361e7936248dbf88e4cb0dcdac45f51ff02f5de2667dde4f09f14471eadd81946489c41cf4fd01382a4947d773f1f2d4d0db4c57"]}}, diff --git a/txscript/data/taproot-ref/c70d23ebccdc1ea73e6448b1df58f62d71582adf b/txscript/data/taproot-ref/c70d23ebccdc1ea73e6448b1df58f62d71582adf new file mode 100644 index 0000000000..f9ebba57df --- /dev/null +++ b/txscript/data/taproot-ref/c70d23ebccdc1ea73e6448b1df58f62d71582adf @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4300100000062fdfcd68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45900000000e93273c30153505600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac25000000", "prevouts": ["c047320000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "3e083400000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "", "witness": ["30440220573cb450c7c479523c98f5fd7c0e3aeeb22fbd9dcb772dffee75759da4b9dd9b02205bdd134c1584568c52b16feeeec73fe4e15875b18291e465e0326083df476c6203", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["3044022074260d008f6bf380e44ae47b7dd5339a2a19382b3c9530ac6a6494f11d3334a0022066b16e1e6002bfb8017dcd93322f8a9b057e074cf111913a708d5b9b3e74b8de03", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/c71d9516b42225f3514b4d1df627c022e4817ee0 b/txscript/data/taproot-ref/c71d9516b42225f3514b4d1df627c022e4817ee0 new file mode 100644 index 0000000000..6bd7def036 --- /dev/null +++ b/txscript/data/taproot-ref/c71d9516b42225f3514b4d1df627c022e4817ee0 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfc01000000e1fb988b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4080000000022028f9adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bea01000000a94b1fb4012f9338000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748777000000", "prevouts": ["30532100000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "b5243b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9a341f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100c4a77541eab702eefb7750e4886d4b888f4c7ae032224e10a7a9ed17bda1e69b022058545e74087066a9e8392b327e6dbc90c3e898d39e7ca09b651247b8610b2a113d", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["304402205aa9bbce6272bb98eca7922f03b6379467297a57fe2656b7d223e453ecf91221022016d865dc6133fcee77025a773e1a0f092f08c5d511fb4d801f2f918873a09b4d3d", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/c7252d6f48851dc47f8c3177537e12abe69a084c b/txscript/data/taproot-ref/c7252d6f48851dc47f8c3177537e12abe69a084c new file mode 100644 index 0000000000..618ac9224a --- /dev/null +++ b/txscript/data/taproot-ref/c7252d6f48851dc47f8c3177537e12abe69a084c @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8301000000820c50a18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48c0100000021f32087dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbf01000000a91f7be901ef40c600000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acac07da2f", "prevouts": ["4cf95b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f456400000000000225120269138224e3ba14f27cd7cbdc9d1fed32e4c458a99f813a17992a22634094152", "d4ce59000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b68f30278051266e32481f29671a6189c6d353ffd83711e7b38c9357ae292bfdef3840bc6208da4f30144e2790f7ad52c95799fa09daeedea4f2bb4d9f8b26232798618f38f0b364851781b96e66cca1de96243a2ea383776a2b78640b336af04751e020aab18a578c160db4bf05505201763cac112612af1054c31721257208a64f4af43c45e5547211998e16db9ce94345f16cfc05b1f9a89f661272a54271f3f6064532838a3f48054e69a9ee6a55c84397e7a4bb580041e254962e67467112f5084d81e25e4fd96298d96ddcd537c8088829b663cef50c89e18f6ae80dd70aea90519a4b5ef32eb4a7a4236439517a9ef63d9db55c1c383574c0a17ad9575d6dc934f930851e90aa137fc749c3d4fd3f7f0fd0446981ba95063db4212d7c5d14a5e976d3527358465b91ada5afd3b360db77237ad1f117aaa3e84b57f56074cb59b16663b9970d68bbcba192e336d6f8e517e7cfc2848f6a55e052f25ccd849b84f134715364648d104ab55ef2e6671e3e8f420c02a0a0ef86a6ffada4cd6f4ef3ff8a70ea4d840835edbd39479dc0097befe81496ec152f3d8586edea4241d808f3ee9e2996fa3f160493433ae02c6add47c3ca7d33be0dec67be891b81c0d0c0c0e1f9c1ea9b6fe9c6522f083054883b553e7bbe87d966bc26c81b7d20aedf8d4fbec41954fce82a22068dffe4663536d2eab6b77683ad0dc09a8b7d2af3503049f24a2259bf75f1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fbe69cbb8061b83a83f1a5e61a364ffaacb63a1b8e8ddb476f2412726180c54b4f4a9cbf846248908cc3621c28de38a375d9ce3ef1fd8ded826daa29f51353851cafc3da456d473afb79353f7068dc1822b24dbf9d7eaef6a0c8c9b611b05e979feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}, "failure": {"scriptSig": "", "witness": ["4d0902e7bfcd69aa83973e920cd991eba9a815d391e2f67cd94758f503fe66bcbf169936b6436f8403487bf6f6b179c5c0cd030cf62d297627935617fca57a9add700f43a185b369789eeea0a86659a3431599c80a459c78b62eaa4430be15f16224a70a460ceb62a78921999ef3514c01e585a5ab904ee63c6212334f4db59284ca00b12917b5873e6a926fe36fb2fa152ebbcf34124292546a03ed6bbc4d870f46067408bba5a44f28e869891a0aa4775e20fe2908632908b768a953aa6ad40b0d60d17b1ce81d48c43d2d9652ce7175a6c3fa4b1f09c4f4992e37422dbb4ad250c67c08cf420d1ef673614ee1755a0af62741f00de0f0e025b766772bd3fa4254a93eacbefeb1559a30a937daa56fa5f1714e25c0c89c5944c13aa594ae452d0a88aebd838a1395fd4989016c9c17f172262bdcbaffb8ceb48ad682e53e4476d1180d0a3e2c021f158aa6206b472042620d9cee55925f505a7c239444084a8a49879e1a3cc366a97e3eacb83ef329e663ac0c57c31a1d501488b2c727fecb2167ebc0534f2c32e6177dd83002eae9e29d37646d88cc3c85ff8f968d8dcd2541ccbbd6908eb6b4a58c45c1d929c1b9a08e526a86a219d351109f952ec1152979a54f7609e048543d0572ba5bce1b11d28cccd7f9376d9a7520a9dc6c2788391f04a90efcaa33bec155882e45690af21f1b11e5fd49f0a59f74a64a50da300437864431632dfc10c402d1917561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045a250e002f75c6b1c142228c210e3ff9b9da21a81c3d6d31af30c750433b28b6418ea1dd842879684de6ce36adf7429742f60d84d7359dfb2eae76d7b546c72259feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}}, diff --git a/txscript/data/taproot-ref/c75d0a897f9c6981d81da8b49be331ba03439313 b/txscript/data/taproot-ref/c75d0a897f9c6981d81da8b49be331ba03439313 new file mode 100644 index 0000000000..1564748881 --- /dev/null +++ b/txscript/data/taproot-ref/c75d0a897f9c6981d81da8b49be331ba03439313 @@ -0,0 +1 @@ +{"tx": "9a4d26d2028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4340000000054ebc4c9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd401000000535d55b401bc3e0000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac08000000", "prevouts": ["e42e3b0000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba", "2fde5c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_5", "final": true, "success": {"scriptSig": "", "witness": ["3e76da909411b9aa4a2821f57e1793ffd7ec31709f737922e03de8e63612b877aa259965f78bc28f8240612a1a198a565ae3bd287f041f727515659fa948708d02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c92bcc39f88de0fccf05594a42dfe3635edb57ce21917883d27a19fa0554c878a5dc33fa7839ae067eb0e322af7872b61aeafce79b30eba6b88bd373e3b2506905", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c761e8c4c51ea45aa6c56b949fdc22e5d4c60cf1 b/txscript/data/taproot-ref/c761e8c4c51ea45aa6c56b949fdc22e5d4c60cf1 new file mode 100644 index 0000000000..a7302601f1 --- /dev/null +++ b/txscript/data/taproot-ref/c761e8c4c51ea45aa6c56b949fdc22e5d4c60cf1 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41c01000000818e558c025e5e3400000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac27020000", "prevouts": ["622f3700000000002259202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["e63904a1aaf4a9aebf1f82d156b1ef26f7e6b8586b945d1c33a8575bf074195bd38c7743a15ef171cd8fdf6519c1ed314604b3d15b0cd80f7dacc5b26f871c60"]}}, diff --git a/txscript/data/taproot-ref/c763c8080d8e8e78651eaf9140b7aa3fef1d52d4 b/txscript/data/taproot-ref/c763c8080d8e8e78651eaf9140b7aa3fef1d52d4 new file mode 100644 index 0000000000..9db50b49f4 --- /dev/null +++ b/txscript/data/taproot-ref/c763c8080d8e8e78651eaf9140b7aa3fef1d52d4 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c38010000002c06be89dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7a00000000a16685fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c7010000002dd89bb302d4447e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870e000000", "prevouts": ["c10b4a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0b942700000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "29fb0e0000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_94", "final": true, "success": {"scriptSig": "", "witness": ["ce386fe989eac7c2d83399fd33490506e49a5c9e9acd1419806a333e0bd803f0573450a048cecd2febc4615c11766d2b55f52052473e30149feda2a9ef632f7f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["625d4991bb3dcc0ec03a460c5f35ed2e794bdf4fdafc610fa83659c9b362c7a2371272fc050707aa27fc7ff596547a97df0956bb0c3957a705dff7b869853d4f94", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c77f06b7f82e62ac50865f5ee4163ae369969020 b/txscript/data/taproot-ref/c77f06b7f82e62ac50865f5ee4163ae369969020 new file mode 100644 index 0000000000..b96157f87a --- /dev/null +++ b/txscript/data/taproot-ref/c77f06b7f82e62ac50865f5ee4163ae369969020 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4070200000035c405e2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca301000000f48bf49ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b52000000003a56f2d902d8daa3000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac6c000000", "prevouts": ["5bc8310000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "a32d5400000000001652142540f27e90740933c99d4f17ab2dfc6c82951cfb", "05a12000000000002251202b18b828586b5828635076972ee0bba96c3f290312125c393cc54d832abc1349"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ba06655263132793ff4f7f3ead2f9f2f86fc9ceead0ef33e48b2027a64ea445"]}, "failure": {"scriptSig": "", "witness": ["6a8b616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/c785d388c9a15886ab980f88b666d4945c7ee4a6 b/txscript/data/taproot-ref/c785d388c9a15886ab980f88b666d4945c7ee4a6 new file mode 100644 index 0000000000..8be04c8cab --- /dev/null +++ b/txscript/data/taproot-ref/c785d388c9a15886ab980f88b666d4945c7ee4a6 @@ -0,0 +1 @@ +{"tx": "487bef7002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1002000000de8b8aa4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c69010000002054ea8402c7f0a4000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87a505741e", "prevouts": ["b4c85d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1ac8480000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ce", "final": true, "success": {"scriptSig": "", "witness": ["5553abd056338fb08b4bbb5c79dd9a6ad62e1e69b98132dffee6a4aa8ec8778ecc463e52fae07201e14fcfa23151e711460bbdb9b38e3727f6a1b5152fa9dac083", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["6e0fa93028289a8dcf0b927eff3fac81b83bb034e741fa1f2521825841a22cd219eb445e0b7d9f07636541e18a878539c729e5e72175cb5da8d58b9997fabe72ce", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c79333ec6723390b7f1563f388c7a50d86f860b2 b/txscript/data/taproot-ref/c79333ec6723390b7f1563f388c7a50d86f860b2 new file mode 100644 index 0000000000..b75cbc5730 --- /dev/null +++ b/txscript/data/taproot-ref/c79333ec6723390b7f1563f388c7a50d86f860b2 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6d01000000b06dc58edceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4c010000002a7e2e9adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc90100000011c898bc0363a0a1000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a663000000", "prevouts": ["3c7c220000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "23ef240000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "d7255d000000000017a91498e55eac47e04767f832d50008ff18559102c9e787"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21601f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["754f3ae87867a6344f53f4d50002692b1af8401e629b96ac03a9e310075a77957dcb468362594e4ac069e3cfb3a6b2d23f0975c072755245d82efe0f95c911f9", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c7946ca286a4c1e04861f5fe7ff7982618728e8f b/txscript/data/taproot-ref/c7946ca286a4c1e04861f5fe7ff7982618728e8f new file mode 100644 index 0000000000..7ea8266f9f --- /dev/null +++ b/txscript/data/taproot-ref/c7946ca286a4c1e04861f5fe7ff7982618728e8f @@ -0,0 +1 @@ +{"tx": "543aa354028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44a0000000011a31ca4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7401000000580331d803fd42a9000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acad535e40", "prevouts": ["137f32000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587", "1a62790000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100bca98a852f9cbde62ceefaac0cb08b690e73a3e0d3b47f10d72f23355d3772ca0220186709f1b3a4435dc09bfa20db77937c9131c244446cd9b0d352ec70501bab0b812102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "483045022100c1c64d231b4b54e02126ac4b06ff870f1b6ecd427eb5b32fe8c58d7d6a38dbfd022070ca91ce07c0919442dde6ee8a4778f442409e31b096b1a32abf4047b49a3492812102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/c7a2d84c0203fa2c48f932ed3cdb57e9bc3d4cd3 b/txscript/data/taproot-ref/c7a2d84c0203fa2c48f932ed3cdb57e9bc3d4cd3 new file mode 100644 index 0000000000..2e14e59363 --- /dev/null +++ b/txscript/data/taproot-ref/c7a2d84c0203fa2c48f932ed3cdb57e9bc3d4cd3 @@ -0,0 +1 @@ +{"tx": "4013c48c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6201000000bf7eceeedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca901000000a70f748001caf00c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac9a82d82a", "prevouts": ["164228000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "eaa954000000000017a91439ec132e1466f40f0086baa7ac253013e83c7dc387"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "215e1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["2e494ef1cb42ca52a79be07dcf9f4a1153a518041c0afcfe69056dcee0f6a6e081bc6e8a26754af686353f1576078eab72262b3b5420112f625b2ee5ed759977", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c7aa7f6d958c6e29a221a767f1d7b3c103fe86b2 b/txscript/data/taproot-ref/c7aa7f6d958c6e29a221a767f1d7b3c103fe86b2 new file mode 100644 index 0000000000..98bc1675c2 --- /dev/null +++ b/txscript/data/taproot-ref/c7aa7f6d958c6e29a221a767f1d7b3c103fe86b2 @@ -0,0 +1 @@ +{"tx": "3ba8d6ed03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1d01000000e3bae3a4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8c0000000072f053efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e01000000551026e5037abdec0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963948d921", "prevouts": ["75f85e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74c36b0000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "26ba240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_9f", "final": true, "success": {"scriptSig": "", "witness": ["c565b4ef286c95813ce6b5b51ff2844046260175f110875745fa85081fee1ef80c0116f6fc4797038ebd8c17a89a9da570d8ba9c8801a4d4b478d122c43340b182"]}, "failure": {"scriptSig": "", "witness": ["6f7d7b44273b0bde92c1635efb75db031624b81a2fb540843eac8b187a188487d2b01f3c4adbc11b882c69ff06f411986857bf336ece7fbc55cc6c2f152515ec9f"]}}, diff --git a/txscript/data/taproot-ref/c7b48c2518d6d2a2a5acd628f2fb397cad2ac0ea b/txscript/data/taproot-ref/c7b48c2518d6d2a2a5acd628f2fb397cad2ac0ea new file mode 100644 index 0000000000..b7f5c89ec8 --- /dev/null +++ b/txscript/data/taproot-ref/c7b48c2518d6d2a2a5acd628f2fb397cad2ac0ea @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfe00000000526d26b7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2701000000c3f9d3d90238f9730000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79600000000", "prevouts": ["20c81e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e96a570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_1b", "final": true, "success": {"scriptSig": "", "witness": ["5d57158b4533e2a6888571746faa954dbc3f85386414fabd7023b25f5dcb9083a6d44833ce64f3f9db87e8c48f832c558b434974ceab2c45ab91ee55ded5cf9d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1f9f8626ee14c89bfd6462423f93c9a4f6f8892951d3abe4bee78cf76d57527e7b92cc0038a65df939b8f89b45c52a9e932bcbca2b9e26d71fd713ef377940d11b", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c814f8c932eb8ff0b1b54d8a85929406a22a72f6 b/txscript/data/taproot-ref/c814f8c932eb8ff0b1b54d8a85929406a22a72f6 new file mode 100644 index 0000000000..368a484ef1 --- /dev/null +++ b/txscript/data/taproot-ref/c814f8c932eb8ff0b1b54d8a85929406a22a72f6 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49c01000000fc23b6c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b040100000067f7ca9b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f0010000009dd718dd01c92f7a00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac43010000", "prevouts": ["ad873700000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "baf1220000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf", "f44440000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d04c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b81ff7cc7637e0c05982e17a8e208328988859d4b2b7eb979a1983188becada13f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823bd101e45a609d3b8e0b3b6f0b7594624f7e9102ef5d5dd3027418de40ebb2180d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}, "failure": {"scriptSig": "", "witness": ["4c52d0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936efbe4fce68f3b8555862407b2d13e298861a0b71ec35e363803758f270d7e6091469e71666f51d71b691366cd88792f62b60965457ad0f8cff2baa31a91ced83d191de94316b2d555b882a7ea052cdcffb2858bcf3e9dcd4db66bb89a9914d760d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}}, diff --git a/txscript/data/taproot-ref/c8172ac90dca46ddecfcb6abf992c70d492bdaf0 b/txscript/data/taproot-ref/c8172ac90dca46ddecfcb6abf992c70d492bdaf0 new file mode 100644 index 0000000000..a0b68a330a --- /dev/null +++ b/txscript/data/taproot-ref/c8172ac90dca46ddecfcb6abf992c70d492bdaf0 @@ -0,0 +1 @@ +{"tx": "b7fcc267028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40301000000e44fc5b9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbc00000000dc4397dc0231b2b6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388accd833d55", "prevouts": ["960e360000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "1224830000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "da7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93647b36fbf58146635091204325275bf32c600005bcae8b0ef3bfa655f050786d2ee00e627ce877dc7a3321ebc519bf09c5aac598ee9e81cf6d3228685de2d2a5f9a29f5cb7818ea23e4b491695dace811707e8772e99626d3237c076ba9a076d6566ba3404d3656bfd0df4a55f82c254cdba579fd51be164a5cd21fa2faf92a44"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c01f27a250fc54a819b2f6e5182b6f4b8059de1027a76afb9faeb15ebb7f4449a47bed56458bb8201cfe785d9ebbccb6afef9cc99128ad29d757c102b7b9c0a9eb0481d56926b359fa3e2e34471adba51fafc61fa70dea7541795bc082db9408"]}}, diff --git a/txscript/data/taproot-ref/c8203a41b6f45793c2150ed5554ab5bf5c7eae94 b/txscript/data/taproot-ref/c8203a41b6f45793c2150ed5554ab5bf5c7eae94 new file mode 100644 index 0000000000..9e97e11d1e --- /dev/null +++ b/txscript/data/taproot-ref/c8203a41b6f45793c2150ed5554ab5bf5c7eae94 @@ -0,0 +1 @@ +{"tx": "01000000011221809fa938f2ef41f6621f6e6a0e75e05349f5a7d7094926420abdf536093c010000000070ad45a90433d150b310000000160014ca9858c362545bc83a3b93e73b12b27a9b3ca00358020000000000001976a91472fb0c729bce8fb851f92a5ad48d3d4231beda4988ac58020000000000001600144bcade4cacdd490a6aa7afbb8ba77ed6898137ac58020000000000001600143f886f8feaf75ad7bedd5713d4d148e7c97c113409010000", "prevouts": ["2e6353b31000000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/keypath_empty", "success": {"scriptSig": "", "witness": []}}, diff --git a/txscript/data/taproot-ref/c82943e824916226a82dbcda450c1cf3f21df1da b/txscript/data/taproot-ref/c82943e824916226a82dbcda450c1cf3f21df1da new file mode 100644 index 0000000000..0bf3fc1903 --- /dev/null +++ b/txscript/data/taproot-ref/c82943e824916226a82dbcda450c1cf3f21df1da @@ -0,0 +1 @@ +{"tx": "35adfe970360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d5010000006640029abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf78000000003657cfe8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdf000000008532f2b1014faa6c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4871d222b1e", "prevouts": ["96730e00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "d08c660000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "f2fb7b00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "4730440220745645c13b4b275aac783c64d4d570fb12a959f1f428fb878c54bd13625b3b730220692113b354fb6c333a611a2439070174f869ee1bb77807a644cce3c7866c81dc0300", "witness": []}, "failure": {"scriptSig": "47304402202527f22743fe76485a67d2b696439540bee96a2c89dec0424ffa698d61d7d5ec02202170150595f24ec82a3c3d442e6566536273f96cc0422a00814f50099047b602030101", "witness": []}}, diff --git a/txscript/data/taproot-ref/c83f86babe52fc934414d829d4969407bdaa8de9 b/txscript/data/taproot-ref/c83f86babe52fc934414d829d4969407bdaa8de9 new file mode 100644 index 0000000000..1d6dc6cfa1 --- /dev/null +++ b/txscript/data/taproot-ref/c83f86babe52fc934414d829d4969407bdaa8de9 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bac00000000a4c899b2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3301000000510c59fc02e5e69f00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac52020000", "prevouts": ["13cf270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "33bc7a0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "1a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa8e84781bad1ba81b7ce5b7be6cf9bec34b59091704d19096b61e5a37e7aa266c56798b11c96dafc2935d577afad31a6537ce4b1a48ff27833822cff5fe95a51e"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369ae37181c42054bd3d996a0cb9fcac8a434e22d455bb156486fd105951d5862240401d3043d3e54134521a2f6b274f3ac0e46a5b9a6f95ac49ca3a75270b4793801cbe9d84ce1e82e006940c90d66235295537a514918e448d1b01c99be1031af2727a08c83da142d000f7f66d34a23554b296f940ffe81022e50f50dcfdd8b9"]}}, diff --git a/txscript/data/taproot-ref/c85880f71216bacfb5f45a917040c76a5b933f5e b/txscript/data/taproot-ref/c85880f71216bacfb5f45a917040c76a5b933f5e new file mode 100644 index 0000000000..027edd4bba --- /dev/null +++ b/txscript/data/taproot-ref/c85880f71216bacfb5f45a917040c76a5b933f5e @@ -0,0 +1 @@ +{"tx": "b9d6ebbf02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce801000000681a4abc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c401010000007e28d0e301fb412000000000001600149d38710eb90e420b159c7a9263994c88e6810bc77e020000", "prevouts": ["f476560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cb49320000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_9f", "final": true, "success": {"scriptSig": "", "witness": ["a4d50c81527021ffc43e6fbd6cc40e5ceabe3b5aadbf2de7ca7133677010e3d8a1dea8ec67b9ec2bb8fe716e36f51cd11a26a69558024d7ddfcb106610df3809", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["4d7be77c7cc3ca06110277ed73b6fbf51e8926ca1635f8ed75cd16ff780d79607fdeb96c019c10c32f39ef9a0197aef4ec72b60017860f0908f2d630b7b3e0659f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c85ec330c8ffb17623ec929fd4a198c3b768811a b/txscript/data/taproot-ref/c85ec330c8ffb17623ec929fd4a198c3b768811a new file mode 100644 index 0000000000..9fc12d6910 --- /dev/null +++ b/txscript/data/taproot-ref/c85ec330c8ffb17623ec929fd4a198c3b768811a @@ -0,0 +1 @@ +{"tx": "d21e6dcb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44801000000e3a0c5abdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c52000000009db4d7d80252268f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5a61c420", "prevouts": ["4d7d41000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "c9354f000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/emptypk/checksig", "final": true, "success": {"scriptSig": "", "witness": ["9b424e1044e5dc7cdc531e12877671db688a9a52da4a0cf3431e55d0c4d577a816c10033dc6e3e1e8efa220fadc65dce1ec52ad30da949263406fd68f5196304", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cd2d09394ee01f4cbf453b8e43120c6bca0157ff833036c4a91161ae8d6db3dd3595e47f783dea9cd898c640c1ccf4b7d0ff5bfa4236f535dc6b4728299c1d69fb9e9eefbd8dee3e5857c0a5c3742d0e58764b1e6eec73b89290af63b7ef8123f752582a11afed87b1aeeab00a91ac5167325e0fc3825def3a8307d2082c1acae8c13f957496bd85a8bfb196b41115877f1c292877d449cb5d56eb109a1f8e695176267bbd1b7867e2eebc439e9f1978d6a17134b75a8bbf0107687388ddeb5ca20cf31e30816ef7bffd0e43d4efa6c46d11185474d89ac75f693a7c477baa289311c864108ea260dd739a7c927abea94bbd3ef2fa436b5348a12a03476bb9e451f31f95136dbefe9a42f2bb6868f993acae25cfce8fc0d73b984508d267a487b041864f4ad19f6b2782b89895068e96969bc0c0cb50b64c3b84612df4c73208c4bcf6cb070e67449ea1a036232a8155856b27be4c634558db013e06b79c26858824757e3ab18b9476867ac69e63e36877af9fee4aeb519472ff5a504bc7e1bb8a70b57e599289922abee7f7cb3f5c4b4e0126255c9af59ddd6c8d572a0551d9a0b10fc29ed9ec9ba811a78159d56d191855f20d80384a7f598d54defaeda75074e07476023602dfde1c8d0d124f96edbab4af8198f97e6bceba6cad7de517a8f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["eae4171cce628642d6e5efa57c43cbc6d95289533e778a30726e24617dfd41fc57c1622715784b71214b1252a1b92d886f69d300f26dc1f4f8e670b4afb9609a", "00ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b0431b55481a374c89f40eb98ef9d2a1ea4a15c1fa25842c8dd1b505d3f733008998f104a41d430584d29acc5d80983bfa4388185b9ecb4fb5f364585438a9bd260600b62c8ed4db4bf12723005c7f766cb302a575f8872965ad67f65636a6b0c8f171a0659181424fedfeb48947aa5b62ebec348497eb70a0e4b9dfaff17fe7851f2fbba69e8a986917b32b5f76ef63e06d7f778743be5452643f44f99ea505f10f2cde5a4729d525a487b41d56d434ed7dc5e0aa5e11e544eae0c7246ef2b3ea5155719b875991d083ecd32183be0f5ac452a5905295b6a0b91be04b40b76e4803cbe3d00c239899d4914097448c043dde77fd42773528487758c6d087e8cf83fa64278d817919e62c4d23adcbc207f804fcd146d72915d8e061e85a8f6a6e6cb9d4e0a9220b07d19fc28732eb4bb2345d54d956bd2d189c6a5f87f1c011bb65cbfaa9ed654ade91c00c9fe4f57391c241e95cfd60b1f44f495a05086ba006260268f3fa4d832afae96ff672bd19d7e928d42bc878143589bed193337fe656f28feb26558d4d064770c2eb738b0251c60e0a639239140ddba0ceb61ff7c3e738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/c86c77b200bac67eba1a81988b36e0764528deef b/txscript/data/taproot-ref/c86c77b200bac67eba1a81988b36e0764528deef new file mode 100644 index 0000000000..fc1b27c730 --- /dev/null +++ b/txscript/data/taproot-ref/c86c77b200bac67eba1a81988b36e0764528deef @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b040200000046cd652b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40a0000000042a9c23e0462eb5600000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac77020000", "prevouts": ["05bb1f00000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989", "45ee380000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "967d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362da8eb1c279bfe4030c40984debdf0218f758d92db84bca846c9a6c0c2c889522729135af56592d99186c3f010fd31ebf46aa180b9496740b245c4ec874c834ddfa3c45458ee21e782394432ca1779912e92f35e0ff52c3985a5265a8dee58b3654e31a1d81b19a8c2670362b3a1330b2f2d66c8db1c8314023a61983d2ff610"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936034fed625626755137a076a5dc7fd4623114bcfec779f6cea9743d7f2e859f08b066835f4c858657284bc4f27395efb05761f76f20d1739098d7bca44617346d654e31a1d81b19a8c2670362b3a1330b2f2d66c8db1c8314023a61983d2ff610"]}}, diff --git a/txscript/data/taproot-ref/c8e586d3f61c1ad22568794bbfcb69f57cb8b000 b/txscript/data/taproot-ref/c8e586d3f61c1ad22568794bbfcb69f57cb8b000 new file mode 100644 index 0000000000..890c457187 --- /dev/null +++ b/txscript/data/taproot-ref/c8e586d3f61c1ad22568794bbfcb69f57cb8b000 @@ -0,0 +1 @@ +{"tx": "9701b121028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40902000000f80e52cc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fb00000000f5b250cc04079570000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961fe84c52", "prevouts": ["510837000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9", "0f433b000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "247d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a5787881982eabc9f10a574183ce87b535a8253f66971d7d0c58826076cb527312b5d836754160f4cb099c4d8b267e29847dad01b12a09dec3875f376ae126ea3506420e788c3ffd3d8d88ddb9154e82106737a8dd2b5d0940daf68f275cd0d7"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb9b18a780ce64b599d9d3042fe9b5b93046b018637f9f8cec8ef00735e099ba32f1db23017f271ba09e9de40cbf6bd4b292cb969b1168724d03b4425efd5cf153506420e788c3ffd3d8d88ddb9154e82106737a8dd2b5d0940daf68f275cd0d7"]}}, diff --git a/txscript/data/taproot-ref/c8ef39151618f6cc8716604cb9c29f93559b5a3d b/txscript/data/taproot-ref/c8ef39151618f6cc8716604cb9c29f93559b5a3d new file mode 100644 index 0000000000..8dddd58d91 --- /dev/null +++ b/txscript/data/taproot-ref/c8ef39151618f6cc8716604cb9c29f93559b5a3d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe000000000930c87d0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2a00000000cbde473a01036620000000000017a914719f78084af863e000acd618ba76df97972236898797860936", "prevouts": ["e1c0710000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "1def81000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361a24f92e0fd66692248020bc486fd34464c8d03dbe31b3b0085981632dac5adc8586fdecbef25bbe615615e0698f2a9b21ec544d3ff645908914cd0f4da91c05854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08216dab5147ee209d2bb54465ac69ced1cd5e726256fc4bc53cec72e983b39694d8586fdecbef25bbe615615e0698f2a9b21ec544d3ff645908914cd0f4da91c05854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}}, diff --git a/txscript/data/taproot-ref/c908a5304c6a71d150881ee923df19a58e37c8e9 b/txscript/data/taproot-ref/c908a5304c6a71d150881ee923df19a58e37c8e9 new file mode 100644 index 0000000000..013d01447b --- /dev/null +++ b/txscript/data/taproot-ref/c908a5304c6a71d150881ee923df19a58e37c8e9 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe601000000c65799e260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ba00000000d4786d82dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8f00000000fcfa74ef02a77fbf00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d5000000", "prevouts": ["6bf861000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407", "d5740e0000000000225120f53d4d34de47a5fffffaf2fc2c78ea776a7cd8d2ae45e19539d143c70b3fc5d0", "5eaf510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_cc", "final": true, "success": {"scriptSig": "", "witness": ["257ad40fbac7c2d9f1a9e1db11fe94e6d194cddbdfcc69058e46acfd792194a47e9db4a1310bb5a16f76584af5dd5ac853267f15f72ff68abf7cc6f1c148320382", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8efa6ef9e488aeb43095ccb5f019bcf9a725b4c0301f1f987108cccc2c353f71479d1387a06f9e82db505b3c295a715d1c64356626b5ba99499f95399c076f54cc", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c91a0b63271792838de6f8620c116c19028be7d3 b/txscript/data/taproot-ref/c91a0b63271792838de6f8620c116c19028be7d3 new file mode 100644 index 0000000000..d92af07f13 --- /dev/null +++ b/txscript/data/taproot-ref/c91a0b63271792838de6f8620c116c19028be7d3 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45401000000823bfdc18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4180000000071fce1b204401f74000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac97050000", "prevouts": ["167039000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "9eb03c0000000000225120d568b8728ac27b6616789818942be5cb929e56b49b97b92550ddc2846ca38bde"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "477d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71edbbe6d997bdcd7c7603d7696a19dfa7a137162827825260b73e89d3e21fe597dfd9e929a06047270fff43ba4c6b47136464c62381aba7ed74ab98bc69d199aa4"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365453fa1cf5661ca4e41648bac18e336e0e2b6f234348e01e3b9405a211d280e1da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71edbbe6d997bdcd7c7603d7696a19dfa7a137162827825260b73e89d3e21fe597dfd9e929a06047270fff43ba4c6b47136464c62381aba7ed74ab98bc69d199aa4"]}}, diff --git a/txscript/data/taproot-ref/c92d0b7830a59c91b7478b9bc6537abc9104ab24 b/txscript/data/taproot-ref/c92d0b7830a59c91b7478b9bc6537abc9104ab24 new file mode 100644 index 0000000000..e3ee3209ac --- /dev/null +++ b/txscript/data/taproot-ref/c92d0b7830a59c91b7478b9bc6537abc9104ab24 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709400000000b5af37dfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdd010000009d67e5be0212197900000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac7c000000", "prevouts": ["48250f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6c8d6c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c8", "final": true, "success": {"scriptSig": "", "witness": ["5ad3e8d9a3c034433bc5885320a6655c35f6fb4e4e21044159dacdbcda9705b392aae27f099a5709080f29e5818c42df824672dedb9277c7fb3587be15223d3283", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f20b460bf96dd5ce5d26f77c330de8a82f53b5576f2a8e66bae591dee0bf66460981456cc948cf5b380d81f43bc2b48eac39b7e6c4f6462a11c21f9b529fc875c8", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c94bf93a205b5120777d3d7dedacadaf6c732df5 b/txscript/data/taproot-ref/c94bf93a205b5120777d3d7dedacadaf6c732df5 new file mode 100644 index 0000000000..335828f4b4 --- /dev/null +++ b/txscript/data/taproot-ref/c94bf93a205b5120777d3d7dedacadaf6c732df5 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706b000000004daee3458bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4810100000091e255d604661a4c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac4d000000", "prevouts": ["e2cf0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d3ed3e000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_8a", "final": true, "success": {"scriptSig": "", "witness": ["3c5348f3d426d431117278556a1bd1f6999fa0ac8af1a93e61940c66473da6585068419e3ec05d2abcc43f57e5d386db0bd53db27b8c1723ed341b1dfc7c27d302"]}, "failure": {"scriptSig": "", "witness": ["0550351ea676302c8e29b537dc137b16fbe9bc07fb2f19fddb08262c010f767f655ef51d24d7014c8d81700f04c74b01d93a8c7950d416611dcfbb65e35d66ac8a"]}}, diff --git a/txscript/data/taproot-ref/c95a348b7638eb340903fe3cc3532859ffe5403f b/txscript/data/taproot-ref/c95a348b7638eb340903fe3cc3532859ffe5403f new file mode 100644 index 0000000000..6f50980525 --- /dev/null +++ b/txscript/data/taproot-ref/c95a348b7638eb340903fe3cc3532859ffe5403f @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44401000000b1151faf01043f0b00000000001600149d38710eb90e420b159c7a9263994c88e6810bc70bcbd924", "prevouts": ["a134380000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_10", "final": true, "success": {"scriptSig": "", "witness": ["c8d082fd536dc393bbe63bcb99dfe609a785a548abee33b3216dbaf05dfa98af96156992a9fe4379615e11109a1e061f91047150302685f8055bf5695655d21082"]}, "failure": {"scriptSig": "", "witness": ["f162e77ec00e3c4853db7fcf3d8d5f85418b3c457ad9107f25232686eefd6c42910d174f5404a351f9217e2af3df799b1c8f46cffca3bed06f954226578729bc10"]}}, diff --git a/txscript/data/taproot-ref/c965920ad9808bd3f6a009ce5335213895163c4a b/txscript/data/taproot-ref/c965920ad9808bd3f6a009ce5335213895163c4a new file mode 100644 index 0000000000..26a424540b --- /dev/null +++ b/txscript/data/taproot-ref/c965920ad9808bd3f6a009ce5335213895163c4a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b790100000051704d828bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ab010000002cc3b20304c1485f00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc47cb040", "prevouts": ["74b026000000000017a9144582b7676ffb8c3a2735b8e71e172a272e3e33c087", "3db63a000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bc", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad81a9d5fb34658f56ef265a5ea50d6ba4a88b7d3df0c15a8523e96f4d1d6f82d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d516a0ed0b6cdb130b03f26b8a245e72d5247ee3941518d7e9956496f6ce27b97d7150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682cd8a89140098d6b7e3aadd747ce5bb6ed64c7673e0c8243d2c4037d581567c4a8563068286881d42b1c4901d93a483973910fd5653bf7ebbf040741f7cd837150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}}, diff --git a/txscript/data/taproot-ref/c968d693525b4f56eb70b070dbf41555841fa170 b/txscript/data/taproot-ref/c968d693525b4f56eb70b070dbf41555841fa170 new file mode 100644 index 0000000000..4474cc7e37 --- /dev/null +++ b/txscript/data/taproot-ref/c968d693525b4f56eb70b070dbf41555841fa170 @@ -0,0 +1 @@ +{"tx": "c3554c7202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0e0100000076c92ed6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcd0100000015e8f9ac0162f93d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac8ebf4b29", "prevouts": ["f7b753000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "2b9321000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "47304402202977185013ef83fa9176d431083b8ea006c249bf46248d8d379060c40e5c00bc022045f72dda06b542a894a9fe4ab8928e139c3be905b48ad6ea9407d9dfa4f8743682232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "4830450221008497a8a4f8f306b7177f773470b917d254f06199bd013267c78f1496e0565a7b022038bdb3b6ffd73226b87f75359b1022709e6c1ca74c510093a47866f3eebd64c682232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/c97c22cac658b5a97d90aab28ef2a0126a80ce6e b/txscript/data/taproot-ref/c97c22cac658b5a97d90aab28ef2a0126a80ce6e new file mode 100644 index 0000000000..e4ee6b231a --- /dev/null +++ b/txscript/data/taproot-ref/c97c22cac658b5a97d90aab28ef2a0126a80ce6e @@ -0,0 +1 @@ +{"tx": "87114d0402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bda010000001bcacfcbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5a01000000684733a90404c2710000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acefe46a4e", "prevouts": ["33a22800000000002251207a86f45d21fdb08435e271cb417d7b8bb1e066ea2bc109ea12043ac97c7d3e10", "94014c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_fc", "final": true, "success": {"scriptSig": "", "witness": ["019fbd076e3722f15c832e92193e6758fb07191e463f5d19072ce5acf798553401b73760bb149a69eeb50ee562fdb3fe44eee54d85ac3fc1e90f7c7a2f028e53", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["d9ad96e8d42bfb5e16324da41d98c52e904bc6ec5dcc6f0c4b0c14bedcd6b01d10210267d4ae016ddb5244060cf6f66183e06da4d196baaa9892e0eb8c57249ffc", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c9810cb06137edb22aba29ce495e0f5e87073b06 b/txscript/data/taproot-ref/c9810cb06137edb22aba29ce495e0f5e87073b06 new file mode 100644 index 0000000000..1008cae481 --- /dev/null +++ b/txscript/data/taproot-ref/c9810cb06137edb22aba29ce495e0f5e87073b06 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf10010000001f3f7932dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3401000000f67932efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2102000000826b9d0304a1acf2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688accafa8b37", "prevouts": ["0a62760000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "ff685e0000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5", "64a1200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["ee", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f25297efdbed2aa8c1ec8b5437cb1f621645355ab4fec48723d1bef81dab8b605e01deb44bf60eeaa09a037ba0d53221083944f657819e2d2b55bb732cda3dfdd207214d6df2d18dfa237afd6016520e9e6ed6636ebebd182087bb183877c35439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d519b8dfaa69151d05ccddc10c8c1e468eb7b78f9ad17f99ee1b916fd61bdfbcfce40899fd8696dac9e3afc960f0a100b615a3c324ed3a125e98af98336f748ba56"]}}, diff --git a/txscript/data/taproot-ref/c9888f4ae613d1778de5399e9c17e6e517df9292 b/txscript/data/taproot-ref/c9888f4ae613d1778de5399e9c17e6e517df9292 new file mode 100644 index 0000000000..d977293252 --- /dev/null +++ b/txscript/data/taproot-ref/c9888f4ae613d1778de5399e9c17e6e517df9292 @@ -0,0 +1 @@ +{"tx": "5e99ba8803bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7500000000df8a91a8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3f000000005c7bc9e9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0d02000000a28c08c40314b9e600000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75c6ed459", "prevouts": ["48417900000000002258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "685e2300000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "f0a04c0000000000235c212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["faa0a1b1251aef70c3685bfc73637131763e34d62b9aa33bb5780f7131ce8dc197dca2c1059cdaa8026c06e2d3296033eeac23bd31f342ab2bf7999193848c96"]}}, diff --git a/txscript/data/taproot-ref/c9a84f25b1d55cfc33df56ee356e86772a479352 b/txscript/data/taproot-ref/c9a84f25b1d55cfc33df56ee356e86772a479352 new file mode 100644 index 0000000000..3fcc79a5a0 --- /dev/null +++ b/txscript/data/taproot-ref/c9a84f25b1d55cfc33df56ee356e86772a479352 @@ -0,0 +1 @@ +{"tx": "fca5d31203bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb801000000d35e6ddfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4001000000e5f842af8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49500000000cbb138bd029ea525010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7b6000000", "prevouts": ["208c780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "859d6f00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "eaec3f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ae", "final": true, "success": {"scriptSig": "", "witness": ["a84935e7de5977d16b5922aff52ce3e71b50501c577410d644e6087d6ba0dc6440e8db429a4385f68ed70759eb234a95178055731a782558080bc4e13bae0d6702", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["be9b2e228b31e15939d29f0660c5e14498216d715cc3bcb3da2a9b10722470e44ff011d9c32738f989d34537550b9538ef95c5a34cce30391e8f88144558e9cfae", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c9addf4f9fd1a956c97c9babd5981d0c8295e152 b/txscript/data/taproot-ref/c9addf4f9fd1a956c97c9babd5981d0c8295e152 new file mode 100644 index 0000000000..30d7540cc6 --- /dev/null +++ b/txscript/data/taproot-ref/c9addf4f9fd1a956c97c9babd5981d0c8295e152 @@ -0,0 +1 @@ +{"tx": "c4706a100260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f700000000efbe80c4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcf0100000062bb14f502b16d800000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898726000000", "prevouts": ["9d9a100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "012f720000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e3", "final": true, "success": {"scriptSig": "", "witness": ["6871b63fd3c0e28f430be859ee58e940374f716e5c39e47e258b850be84d504770a88c3645586e4264f47ebc91556974438aef78392f59b878936a7c1548789281"]}, "failure": {"scriptSig": "", "witness": ["82a00280c9418e2fbf7a49397d1d2354ce6561a74ad6b2d88cf9f3267847b0aeacb932ffc542fa7d3a02a7408cfcf2956cbff43dc1fb8e8e7cffed784cc3ec54e3"]}}, diff --git a/txscript/data/taproot-ref/c9b398e28803f0f2e675448f50d7f4d8c39e8991 b/txscript/data/taproot-ref/c9b398e28803f0f2e675448f50d7f4d8c39e8991 new file mode 100644 index 0000000000..9c26e323b0 --- /dev/null +++ b/txscript/data/taproot-ref/c9b398e28803f0f2e675448f50d7f4d8c39e8991 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbd000000008b1e38c6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6100000000422eee7f02753dcc00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac466b3933", "prevouts": ["6b948300000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "7a884a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype0_byte_scriptpath", "final": true, "success": {"scriptSig": "", "witness": ["0f3e7f21e5f22b16c508572df5b2369151fab5d20cffcf7e24c3d8901ba4d658336a51205bf64a016c1b5d3ab4f21f766e4b89c112ff0f9b1f68b59c9a7e0660", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0f3e7f21e5f22b16c508572df5b2369151fab5d20cffcf7e24c3d8901ba4d658336a51205bf64a016c1b5d3ab4f21f766e4b89c112ff0f9b1f68b59c9a7e066000", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c9d4c34b8cbf8c16d5b1e01af0f0541cdd36456b b/txscript/data/taproot-ref/c9d4c34b8cbf8c16d5b1e01af0f0541cdd36456b new file mode 100644 index 0000000000..d4621e4d6d --- /dev/null +++ b/txscript/data/taproot-ref/c9d4c34b8cbf8c16d5b1e01af0f0541cdd36456b @@ -0,0 +1 @@ +{"tx": "2cc2c040028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4180200000083645dc7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7f01000000daddb8d20432929f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac3c000000", "prevouts": ["cf0338000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7", "3c73690000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_8f", "final": true, "success": {"scriptSig": "", "witness": ["314ee8a5e310fe2648a3d28897a720c681976566449d206bc237738e4fac05f55184abe6dd34db74e1681612eae486e22bb537fe8d7a112c394f57a1b5a8927002", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["658e0008620631287884f7a93ced9692400c38bf3f4e4e8e8c32ee688304151989a1d4260b129f8807378d5cbb8510ca8c34df3bfb1a210b2ae6e13da73e5e9f8f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/c9dd51e291d1902fcc5389ef9f70290ea166e35b b/txscript/data/taproot-ref/c9dd51e291d1902fcc5389ef9f70290ea166e35b new file mode 100644 index 0000000000..12fd402262 --- /dev/null +++ b/txscript/data/taproot-ref/c9dd51e291d1902fcc5389ef9f70290ea166e35b @@ -0,0 +1 @@ +{"tx": "32272e2d02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc400000000cf2c1cae60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d101000000bff585a60172ae45000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69d78181e", "prevouts": ["f8e8500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ae000f0000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_6d", "final": true, "success": {"scriptSig": "", "witness": ["07681357fd8e216d8858882b0449b7b01e1738466bc35a2c6349fb9cdb477af43cbf3665d0844d7baaecf26dc4682470fc4dac4d130e58f1b7fcca649c4560f281"]}, "failure": {"scriptSig": "", "witness": ["dcc081a61a3db0025177c7bad923d394d8b73b872e306cef18ce6712a7cab76e513bf4d9ebc0c206fe47ced6b99881bfc61ccecc6c0d03c2f7cc5b3f73078e556d"]}}, diff --git a/txscript/data/taproot-ref/c9ed258ea27321037ce42d665a00191863c1ddce b/txscript/data/taproot-ref/c9ed258ea27321037ce42d665a00191863c1ddce new file mode 100644 index 0000000000..52823f6361 --- /dev/null +++ b/txscript/data/taproot-ref/c9ed258ea27321037ce42d665a00191863c1ddce @@ -0,0 +1 @@ +{"tx": "feb46ba5038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45901000000d71bd59f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4be010000004e14988560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a7010000008348decf04584a79000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987a5c20248", "prevouts": ["41353600000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac", "744c360000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "28650e00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a925fb010e9dac59891c803b6a81d462f65c56c77cfff52e46d3d042538a83699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb44c2f2200f850d6a1609ea6f282082fe51ae8a55145cebb4c521120909a7edcb74b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5116dab5147ee209d2bb54465ac69ced1cd5e726256fc4bc53cec72e983b39694d8586fdecbef25bbe615615e0698f2a9b21ec544d3ff645908914cd0f4da91c05854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}}, diff --git a/txscript/data/taproot-ref/c9f4f38c06357e5794c082ee3a691a02193ff1e2 b/txscript/data/taproot-ref/c9f4f38c06357e5794c082ee3a691a02193ff1e2 new file mode 100644 index 0000000000..a574ca6d08 --- /dev/null +++ b/txscript/data/taproot-ref/c9f4f38c06357e5794c082ee3a691a02193ff1e2 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3300000000fd918ce48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dc0100000057bd5083dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf300000000c9b3ff710361ce9d0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961aad1f34", "prevouts": ["7dc71f00000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "a33834000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "59974c00000000002353212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["cfa9527db8d94ecaaa4c5f84aa069855344a8e1139532addc267645c320553d1c5ad4a9b270df90a342dd9b911679319b2f4fb7001219e073c30ee0f733f6d1e", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/c9ff164d902f41698dc1714ef130057761a13f8c b/txscript/data/taproot-ref/c9ff164d902f41698dc1714ef130057761a13f8c new file mode 100644 index 0000000000..1e6b638032 --- /dev/null +++ b/txscript/data/taproot-ref/c9ff164d902f41698dc1714ef130057761a13f8c @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb6010000005bd07d78dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4800000000f3fbe79504c03f770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cf000000", "prevouts": ["6300560000000000225120df3728be21c89bb919091ec65a63fe2d83dc46feb767b141518f7734e1cf94cb", "b400240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_88", "final": true, "success": {"scriptSig": "", "witness": ["1e05e1776b78adaad2bd6afe32e838186227902346f39d0d1ec0dc731f955917061bee9697264a842c6a1c6017cab8e2a02eab8e7034229b91f90efe394cb7be01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ed5ae8658026fb9fbf8b98482691b24930e2da2f95446930aee2540f6fd9c21ce4d8af1099c773e60a9d955c063784f0a8ef1629439e32afca12fa7fbc8d94a488", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ca067c02b5a5e0209c277a0cea71db50a16d380f b/txscript/data/taproot-ref/ca067c02b5a5e0209c277a0cea71db50a16d380f new file mode 100644 index 0000000000..58fa21152e --- /dev/null +++ b/txscript/data/taproot-ref/ca067c02b5a5e0209c277a0cea71db50a16d380f @@ -0,0 +1 @@ +{"tx": "ae141b9f03dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bab000000003d92aca3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0d00000000851034978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c445010000004f05579f031209c70000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e741700146", "prevouts": ["27c222000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e", "30c5690000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "23df3c00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090243f58a90114b6aa402bb4f9b0bceb04a56c354faadcd2b5b9336e75fc30d5e9f9d13252f48d8e515aba940330f12781bf2dcb32238d271b2594c8d1a8582a180eb34ebb90b8f13751fcab19fed4d5c8f7a33fe6ce4b976293dfd876314d79c63c6224861310ae2c1db0266e829804965e1c2117a7c9864c8f15dc999f8ece559765b9c0542ada65cd9ab908d11f5fb47c1616e8cd7552b13623868362e9b7fa6a8cbab1e92dfd8c6612e99a33d5f2debefb52b4535b958b74e991a4cc5a43871723a8bda06d5779b1bc91616dd0a339a801014b31e55346967ce4c347922956948a52f91d8751d2e1d4f2326a1afc0b13f7dc183beb529ad11b555c762b1ec2f4a3043ca77cc66e720dad42a457675725090bf60b84442f6e2acce8199eca0f8c7d395f2ca783e8619a335cd535a2869ee8cefcd76697f623fba01a42545ba6f68d83c67ef1296bf9b083268d413c8ba9e1fd5ce2fdff10fc32334f7c0b85ec3b6480cdeb962e9cb3ebb46fbc6717f80e670851a28c3283cce7e102d0195f01affbb32227166559ab085101b7a9629172b4261a7cf328cfcdaf13cc92950ffc74333e0f7f8ce3d23fa106cda339f3075467fc09fa29f76b8f1c1f2b100c72804e5368ffb58f2624b51e91e2be1cee5a87ed643fd475b177c9937de61b73752398fa21ea98f7021e8381ef7e9b487a2cd64358ffd6658362e2c8eed02061ed97829a8c39fff34452e2275", "c57d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364fa4baf48be6a9a9bfef03be76e85cf973a3cb7e8c90715eed2621d73e79b1f04639ba4332756735e08e9dd0c9395e600a8a67669bda3acb22644b013566df8000378a892e4dc43a17c9ebd71803200f2f24c9a40c2827c304e59be9b4a7df0b"]}, "failure": {"scriptSig": "", "witness": ["4d0902e7ed58a5d1e45da459f2a8e0301ddde15594acc54ff095d5d2c1d0db00b18a64067c74aaebb832d05839becaed55329079673fafa9c00ba7aaf53db021eb459d86bcf78fc89fb0cdee21f431c48d294eabb6a2a8828c3722c8dfb9211be3f0d1084c88ad021beaafee806d632f162ffa9f21fb18ba7dbd1e763d3c7f3efd8e541d988e4c15369c8580b310433f994a584413b63d7114ca1c4bc5772878c53dafff0826ccfac1cc760968b205fb23f87113ab3cbd52b0fe41667fdae55ecd89eb73cb16b89167168e67737985be61d4d215c5ee924df6f031ad9b95064eb38af55e5858321f64709b1a5e8eb28ae7e1d642427b66fdd1db886f41fc4cec2d8accd9dc6ac75543574a8ac5791295bf33874275c24f34ae216fb5cbbc43bd155c7bc443c593117ee8b47ee46f048a5773951b17c6157f5105cae16d624f45f0ddc7a465d7cf5141a58fb568f26f087ef45238957e67f1a2511533e0bdfc76c5f69fa11aed2c3e70e1cfc199806a5c8b0218e9b8cca38ca39b92df174dce8fbcecd3a216bbf86291c9f658076b7e421f153e9f643e6109e739c64b5f6030f4c96025526103cfaca2d4b34f85384667c57cf4a948ecb5abeba9ab5c4337e14a154e21d19c1ca49e483c47031bc5399c36969d7c90f8b874dc0b1a580ca7e266bce0b78e694cdee14c4d2fb79cacecb5127798c5bcfd6e5868ba26939c019edfd24a87833f1d6503b2a8b30475", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bfaddd47df3117200f65a8f2511f385e6ac107d57fbe48a596b05dda60e029cf7b7f3ebdceab6737726d3802236d8368ee483fc4ea684d1523b8c26fc56452a37def1cc2232d9b1ca5244635fcf6779cb15e82fb856baa2ca11d8fd1da35295f"]}}, diff --git a/txscript/data/taproot-ref/ca0a2329b586ff39d07383acaecfac1982afe0df b/txscript/data/taproot-ref/ca0a2329b586ff39d07383acaecfac1982afe0df new file mode 100644 index 0000000000..081db8d898 --- /dev/null +++ b/txscript/data/taproot-ref/ca0a2329b586ff39d07383acaecfac1982afe0df @@ -0,0 +1 @@ +{"tx": "db04e35402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b79000000000f3aa8f7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6a0100000042e6cff403695068000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d4ac9f56", "prevouts": ["937e200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74a7490000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c189d3ccfc4948b891aeeaa0f3c252a2902566ef59534bff7a4e867353c33bc2b8fa02a75f2c14ed7d5d0c703f04231a07d54b48265128b0f19f2675cea0a3860ede327a4530e163a08fbb39bc817df8c091647ff10fb19edf5f4101cfd44f0728600564ddbacf5f3725d0c966242f43412b32595be2c9ca0d2c059543867768a8d33d1bf79d85f5789ed848b4533d26a370a1b4a52752612c3d95f6c9d7b97cc934929db8420892ff1120b3c8c411e7767f40152742529dbe086742fadccf432c5345103c8c13190cf3010d182fe02d8996277fcb1d8c0dd593ecb0c1647922a35fbb5d082a277e9fcb414aeff4ec604e33093271e410b73792c789bd98357022d689161dac98863f8867a2e8590ab7ab931d13115977bcd8874d51deedbb047e3fb805cf26aa098ea789f097a2c6d3e9e8b9b6d34b063a2bf52fe3898469afe255722307e5eebe754d452672d60e4dda8a30e597138ff88ac859d98c0c8b4b2c6a9fef104e1ad8d5a53e845c2808e6646c9baf7d5deaec69c7a555bdd130c6a535805a4949dce00f232022cae114cf670818daaf23edb3ef951e7a9bf38d0e9bc6a574dbb62cac0361814c354890e90104ad45b2caa0cb52ff7672428a54dcaa9bcba030922ef862f3ca177f3b9177e9cf150d0195a41ffd5d614cc6fa28d3c01b9be056c8b32d725c90c5678d3d31bd1b5b1280330478832e9f6174b96b8e5d739a142aa31a2d4575da", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361761f890f132d60292ea9451ab2a689005be47319d7fbcba26241d791200a2a1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5148d61d9b48b1fd3c9dcc7ce9fbab23c91d7bbaaf6610449bdfa8b9a4fdaeae22ee4d75780d36bffae9b56136e6d27c02b8d233efdc800bb260bfbba6a6f94b87"]}, "failure": {"scriptSig": "", "witness": ["4d09027227454db5a9dce2f62dff1570059e93008b6e8c35d4e3d4e482cad6511a693458fc0d59d509576c02daf8b311fdef129763c25d11584af2f46db53929e4ffe32210c73eb4c051c3e3404f9ad77d66a9633ed5eef418fec88818f57e4eb469f93e9f19b21031ed544cc3067e30c21f8564ce1b4b5cc2ba01de9179b8f19a218c7211994dced3705ddfeaafcb061f39868d712aef73133c13c21e740a748b2189fc29efaf763b43ddf1ed875432a692de5387774f9f2aa9348cef432a97685c4ca3bed90e36ddc75d70dd32df2fb7170dcd755463f2503cef896d2b34216b5d19bf3af32add48b32873e5238b30cf69dd5fd8731f02e5ac1acb1f23ebea7d820ee214e912136d79ef5b2e262a457efb4db3b60bf93ad1a947b0cc9160a1bdb0548d5b95c2b86a99874e929ffd538da8550de01886a5b35dd961126fd7c31a2389659b8f7e5553415bb37f2344ca22ced132c0cb2ea101cf91e9d76cd7da5f8af2b000abe5683868913b7e41060349c54313f2dc7bf3177e2a26c7c4640ae7f7f9314474a5febb01a7feba1ffd9b7d7421bd0dabf6acb5a33a806120cf600965e54cabe06fde2694de8229595b732d394b3717bde45fa91aba89be40099a61dbf25c26af762285c63373ffb9b087d0cab28d21ad6a60fbbbed9feb7e67b767b529b98023459c9717a4473beed5f3b3b272a238dc98c3e9e197cd1ceabb56f567d5c6e4541e8ff07170547561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d0c3719315ff0531af977ff551a321675e96f6255e2f5d4cea630188659c9757473df9812949ea11fa7cd8f7a31f5257bc4998fae53c5743d03c7cfeceae664b355d713f01682c54eefc137cacda341f8a928ca67657dd1895f9a847e54f584f6ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}}, diff --git a/txscript/data/taproot-ref/ca10907ed5b956b8d7c600609307e951fa48d8e6 b/txscript/data/taproot-ref/ca10907ed5b956b8d7c600609307e951fa48d8e6 new file mode 100644 index 0000000000..7c4c4e4254 --- /dev/null +++ b/txscript/data/taproot-ref/ca10907ed5b956b8d7c600609307e951fa48d8e6 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4460000000086c6650edceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc500000000f5bf2afe03cdd85f00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac3de12d2f", "prevouts": ["c9003a000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "c668270000000000165f142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826047efe14993a8a73b9baf7cd14f960037ac1d53bb1921fe06fa7eee8637040814a663af4c315d4c0e419951403071b67d2106b9ce8bb6d7e6c872100135a32b791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b9fcf0a7c92dd23244df9580e55d15e57255b9f51d71ced09e9b8172bc04386f6047efe14993a8a73b9baf7cd14f960037ac1d53bb1921fe06fa7eee8637040814a663af4c315d4c0e419951403071b67d2106b9ce8bb6d7e6c872100135a32b791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}}, diff --git a/txscript/data/taproot-ref/ca10ab334b15fc1a219962a002ba20266142420e b/txscript/data/taproot-ref/ca10ab334b15fc1a219962a002ba20266142420e new file mode 100644 index 0000000000..4b5de6cf52 --- /dev/null +++ b/txscript/data/taproot-ref/ca10ab334b15fc1a219962a002ba20266142420e @@ -0,0 +1 @@ +{"tx": "7712fd3c03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc600000000fa2131a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3a000000004f6247e1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff3010000003fb10ede01318d5900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac50880832", "prevouts": ["21d5720000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "a3c12000000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "1de070000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb468405cb22a39b2e10cd1afb6cf33a44daad2098e05cd2010bbeaa225bcf768d84cef708a58e9a16c040ddf6ca6eff300c7bff2a5c928617bb01c850b0a79e89f728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b9d6e3f5d9915a7f17d348d09ea3f9ebd96660129a97625007e31c70764ffd301ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900456a39aac74ee3f63949b9c215c515b0db1b113f4639b3fb19cd99ba22ff01310c728ffffb27e62918c729ff5ffa8fa6bd185df3cc350f3591557de0b18c4f64cb"]}}, diff --git a/txscript/data/taproot-ref/ca3a2137d38c1e9a98dd585fbb1e5e6483a855d0 b/txscript/data/taproot-ref/ca3a2137d38c1e9a98dd585fbb1e5e6483a855d0 new file mode 100644 index 0000000000..f84011a743 --- /dev/null +++ b/txscript/data/taproot-ref/ca3a2137d38c1e9a98dd585fbb1e5e6483a855d0 @@ -0,0 +1 @@ +{"tx": "49871be601dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb301000000721231a4010d471900000000001600149d38710eb90e420b159c7a9263994c88e6810bc780010000", "prevouts": ["b2472000000000002356212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["571c7b7dc40213dca493216192ace957d503428885c314dbde509aff240517098ac878b539c1e639d59320025659a8295a91ab756c9aa8af233f8ece7b4c2ca5"]}}, diff --git a/txscript/data/taproot-ref/ca4f72eced8e3ace4cb06faea7d35e7831c1e5ce b/txscript/data/taproot-ref/ca4f72eced8e3ace4cb06faea7d35e7831c1e5ce new file mode 100644 index 0000000000..5ae7d5903f --- /dev/null +++ b/txscript/data/taproot-ref/ca4f72eced8e3ace4cb06faea7d35e7831c1e5ce @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700801000000b8b76795dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5a00000000f6c7ab86017eae1700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac00030000", "prevouts": ["cb9b0e000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e", "91a75000000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "347d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366a824c5b532f5dda933d832154b0c83ad7fb2ac42414be4d26e31bf47f087a0bc5a4ec1ad3c05e8d6cb6e5418cc65ab3865118805b06cbf11da98fae87c97132e97124583e57aeab90707503ff0d8dae530166a9193c4517699e1743b45d7c12"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365b9f16c64cb33bf07d6b2062c92fadc965674f21ecb7c903fe1fc58ed8d39da03f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823ac03c85a7bde4aa83325c4e9fa3803d6178be55885bf5b72d341e036ded0599070c3fd2cc03cfe72ec91581f9e22200fa4c4f6deb8dafcd335310e90efb11e5"]}}, diff --git a/txscript/data/taproot-ref/ca4f932e8cc3a4b016fedf455e955c89cd7237bf b/txscript/data/taproot-ref/ca4f932e8cc3a4b016fedf455e955c89cd7237bf new file mode 100644 index 0000000000..413c2d3ae6 --- /dev/null +++ b/txscript/data/taproot-ref/ca4f932e8cc3a4b016fedf455e955c89cd7237bf @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703700000000456bf00a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e101000000c6f1b10a040edf4700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcba4b604d", "prevouts": ["e40e0f000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "5b843b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d", "final": true, "success": {"scriptSig": "", "witness": ["46c27b068d411d00453bb2f23978d33612f157158f2d1269abfb8ed2544d04a8adf80e60ff2220e9106ea2e3853e1adbf64af1c1067c6438ddeccd3c2dde41de81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["234ec4b6bc847f464e80243ad1eeda31abf28a2f9d86b856b88941d8c2489fc1632d85df12d4f5918f16580caa1ff63ce082abc86e52c9194d5413e3042c6a390d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ca67aeff72a1ca354129ea9f32b49e63219b5d98 b/txscript/data/taproot-ref/ca67aeff72a1ca354129ea9f32b49e63219b5d98 new file mode 100644 index 0000000000..1fc100664a --- /dev/null +++ b/txscript/data/taproot-ref/ca67aeff72a1ca354129ea9f32b49e63219b5d98 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4beb0100000031c4939d02d3aa1d000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48717010000", "prevouts": ["085a1f0000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063e168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cdf2b0c702c09265c526c69132e8e88ce07fc31df75ddaef1d0c3cd9ea36fb3bde4683e2f88a3942929fc88a4cafb8eec09785ff7c9f0b883255a650cf557ca66ee26669afb6dac63e75f53b4cae6cf36ae7535fe99100c6f349ffc46155d224f44ecb3bab6b962a7ffa14a2ce082ec551943f33ce508b63a8ee30ee5e49264"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4963aabf3cc95b3b3dcf7e67623762453db9f8eda97e088037773d00ff58aedf693e8696ee404d8be98a67cec2febef1e0f75b013501a27963a3fb4300a4da26e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}}, diff --git a/txscript/data/taproot-ref/ca8e90d773aaf3a6cc447fa963353434f82c0e50 b/txscript/data/taproot-ref/ca8e90d773aaf3a6cc447fa963353434f82c0e50 new file mode 100644 index 0000000000..45bf018727 --- /dev/null +++ b/txscript/data/taproot-ref/ca8e90d773aaf3a6cc447fa963353434f82c0e50 @@ -0,0 +1 @@ +{"tx": "d76dec3801bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb00000000010ed51ba02f2876300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7c1000000", "prevouts": ["b8e6650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_20", "final": true, "success": {"scriptSig": "", "witness": ["9852b68a87443e7d0f8c72a0aefda4c1820b67a688b4e96fa603e9153677a222af819f875ec547bd48f98ba87cbade90524887f4e8a7b00b097b384f42e12f05"]}, "failure": {"scriptSig": "", "witness": ["b7dcb5993b6b8ccfdb8ed4e5418b19ba6f0d9016bd32bfecf1b180ead15b77de8c555aae32af79c63e23a0a41f3bdbaa51026ce9476a5c4f4a296260a2e6d58f20"]}}, diff --git a/txscript/data/taproot-ref/ca8ead844b2d1ee6d2526ed1a548996bc943ea68 b/txscript/data/taproot-ref/ca8ead844b2d1ee6d2526ed1a548996bc943ea68 new file mode 100644 index 0000000000..99e743f215 --- /dev/null +++ b/txscript/data/taproot-ref/ca8ead844b2d1ee6d2526ed1a548996bc943ea68 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa90100000010059b838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4580000000033dc898602dc7baa000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac08020000", "prevouts": ["31d1760000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "c135360000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "487d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082edf94ae33f5606292dd7c11b30be28c4e66005bd3313ca427ad5ed734d53452840210bd7db211b82a407c19f9567cde5a01f8f2a3c3dc032c7ac21169de78447"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8d88ca5d2ed422cbef7221efcadc1e9b79f7a9a7e5e37a381143666b41a8ce50be5e2af3a3c1a6754948d639a5542927d59c509fd5287d02d091c2a39a812b527da89940c9c2be3d3cb1ea9fc374137a74dc3bafe909c68993f298761996d666"]}}, diff --git a/txscript/data/taproot-ref/ca9fc42da81222da6dec277f6346109bf564fefb b/txscript/data/taproot-ref/ca9fc42da81222da6dec277f6346109bf564fefb new file mode 100644 index 0000000000..416ceae361 --- /dev/null +++ b/txscript/data/taproot-ref/ca9fc42da81222da6dec277f6346109bf564fefb @@ -0,0 +1 @@ +{"tx": "b7fcc267028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40301000000e44fc5b9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbc00000000dc4397dc0231b2b6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388accd833d55", "prevouts": ["960e360000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "1224830000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c6", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366adb67c50db990d0ffc018ab512ddf792ce3fc48b23d63faf640ed9594ca022e3720a820d9abe67125ff39f44ffa31194d8e2e56ac0de67f7992994257d70be631e5a3cd6e337eb252bd8d7a8d95e14a531fbfbee4d245debca50b247e512ad1"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93643147b93bbd48179e21d8eb390a9e202d46507542ccdb812323f4df5ed47756d052557e81dd342a2b41230b0afaea8d13945f509c20a84912c3e9d5b86183ac33720a820d9abe67125ff39f44ffa31194d8e2e56ac0de67f7992994257d70be631e5a3cd6e337eb252bd8d7a8d95e14a531fbfbee4d245debca50b247e512ad1"]}}, diff --git a/txscript/data/taproot-ref/cab98434bc48379e0a365fff01d6b79bf577457a b/txscript/data/taproot-ref/cab98434bc48379e0a365fff01d6b79bf577457a new file mode 100644 index 0000000000..e09ea1c335 --- /dev/null +++ b/txscript/data/taproot-ref/cab98434bc48379e0a365fff01d6b79bf577457a @@ -0,0 +1 @@ +{"tx": "ac8ef70c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f500000000cd6aca99bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1002000000166066d902baef900000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf8000000", "prevouts": ["a32e1200000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "c53281000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6aeb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365ecdf9d6b38b43c17196dc2a7eea65eed5a0468b71e2bc36574efa54ca32faa03f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821e09e6d24dde1e7a9afb38743b4c2dd55dbb58a3a1803a82bc7b3a42584fec8fa9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4434501c222c2b9303845523b2a5615208b9d5e9b8dddf3d495d8511b54149dc414f0d108097d00934ef2973385fcf188ce2945eb833bd9e90fcb9cf025505833cf9ce2244c675144b577c27c052f9ebd481172245e28e9502c6c6e8f12c64fa6"]}}, diff --git a/txscript/data/taproot-ref/cab9a4b9aa0799313bf8c71e90011d910fd2eca4 b/txscript/data/taproot-ref/cab9a4b9aa0799313bf8c71e90011d910fd2eca4 new file mode 100644 index 0000000000..96db64245d --- /dev/null +++ b/txscript/data/taproot-ref/cab9a4b9aa0799313bf8c71e90011d910fd2eca4 @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff801000000b0c13d8502d4c3730000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a66c020000", "prevouts": ["f03676000000000017a9140917710a6236c7a08b54f54b004ee705f2913e3087"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "235f212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["37d5a197074413e5cfff18078c7c380d852f8aa839695132f190dfc1e266dcb4022523404abfb40d63a3c077cca5e8f4717bc99d7098e6032665c433962bd459"]}}, diff --git a/txscript/data/taproot-ref/cabd7d24e6498c820ccd2a79a03cc481607909e5 b/txscript/data/taproot-ref/cabd7d24e6498c820ccd2a79a03cc481607909e5 new file mode 100644 index 0000000000..f11edc25e6 --- /dev/null +++ b/txscript/data/taproot-ref/cabd7d24e6498c820ccd2a79a03cc481607909e5 @@ -0,0 +1 @@ +{"tx": "c07ee00c0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270200200000062d802d1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cef00000000fd6645bddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3b01000000fb6fb2d2013a6d4300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac24ec9a3a", "prevouts": ["db2511000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "86f3560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "946057000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_64", "final": true, "success": {"scriptSig": "", "witness": ["6a9ce750dc4495b912f5de2c7936b6dc9fbe0af39f57de380f5cad36d870dc90ba56720d46ccb0f7aad7441e5d16f5a21b5fb94e64ab8da12271bf0566043c8b81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["07907fa33089d2ceb658e9e552e4d1055527a7801ad0e2a249b547b24574fcbed9145c3c2b436e8622b22f05a6b1ec42219ad1dcc5d752d71ecd51b3885572a964", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cafd0a9a6dab6200dcb88ecbf7e265de1ad5d317 b/txscript/data/taproot-ref/cafd0a9a6dab6200dcb88ecbf7e265de1ad5d317 new file mode 100644 index 0000000000..11037f9343 --- /dev/null +++ b/txscript/data/taproot-ref/cafd0a9a6dab6200dcb88ecbf7e265de1ad5d317 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c491000000007392a7f260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707500000000579abf8d03798c4b000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876b000000", "prevouts": ["f7dc3e000000000021581f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "ee930f000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["222c69bbe3f4f1673e8cf45df278568891b3a7d6fcffd5abc410b2b797aa1927f2d6ff83effa9adf6d3ef712d53a5534bb3fd91915849ae9fb719034ebf80b1d", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/cb181959ea829e3c8e81c95a1bbce81b35f8d2fd b/txscript/data/taproot-ref/cb181959ea829e3c8e81c95a1bbce81b35f8d2fd new file mode 100644 index 0000000000..5138e934ea --- /dev/null +++ b/txscript/data/taproot-ref/cb181959ea829e3c8e81c95a1bbce81b35f8d2fd @@ -0,0 +1 @@ +{"tx": "aacaa01b02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1d02000000f3d0e9f9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c44000000008657808f03639ccc000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487941a2455", "prevouts": ["d91d7900000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d", "197d560000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063fe68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cebf3516b3dc8f192542925d4b3d82199c3e0c8e4a17ec07f1fddd55aaac307b917e8250b412828d56f092e1d9ceabdbedccb5671620a7e05a1f5a122fcf72f11e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d515ba7b576a8dda08f1b482f8c289e95e9d52783e5c439690d7dbc8078ddf6e59ab44d8b0f62b2d27de7be259100200d6da1e5303b29f3eaa1b6a4eeb0c96a42f364ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}}, diff --git a/txscript/data/taproot-ref/cb1b57e08db865390f1b4cf22118530463b721aa b/txscript/data/taproot-ref/cb1b57e08db865390f1b4cf22118530463b721aa new file mode 100644 index 0000000000..1ea1e384eb --- /dev/null +++ b/txscript/data/taproot-ref/cb1b57e08db865390f1b4cf22118530463b721aa @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1b0100000056ef84c6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1500000000048e2596dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e000000009ecaa1df0136422d000000000017a914719f78084af863e000acd618ba76df9797223689875e000000", "prevouts": ["f4dc280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee4f4f0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "53ad4d000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "6c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0825b22591e944b414d99fe534a482351afe29b8e90b07993fb7f3f85b72380ca5294fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e872a8a6de95a80dc4a6e95ba0e12854eab511c8acfff04c6cfab0ff55ad6b178"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8537e729fcf8585ba70be9503b33ad258cc8c70f658d9ebd11d7348a395e977e6872a8a6de95a80dc4a6e95ba0e12854eab511c8acfff04c6cfab0ff55ad6b178"]}}, diff --git a/txscript/data/taproot-ref/cb5cd2d881a8e8202863c29e2d692b6245167dd1 b/txscript/data/taproot-ref/cb5cd2d881a8e8202863c29e2d692b6245167dd1 new file mode 100644 index 0000000000..b6b8f03202 --- /dev/null +++ b/txscript/data/taproot-ref/cb5cd2d881a8e8202863c29e2d692b6245167dd1 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a801000000aa951bf3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bac010000001c53bd7ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe9010000001c47564f026e879f0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca040a226", "prevouts": ["0c261000000000002258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "8c5a260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7f456b00000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["aa7f169ca09b5112de5218fd2061e9503480eb8c97f5a6094e304468cd47b3358daf879617418a2d2041960835dffa29e30966714b97b3855702656bcbc75a5c"]}}, diff --git a/txscript/data/taproot-ref/cb7c58b77b079764dd1fdd95626fced2ad539c7c b/txscript/data/taproot-ref/cb7c58b77b079764dd1fdd95626fced2ad539c7c new file mode 100644 index 0000000000..dbc7bf79aa --- /dev/null +++ b/txscript/data/taproot-ref/cb7c58b77b079764dd1fdd95626fced2ad539c7c @@ -0,0 +1 @@ +{"tx": "3b690b7c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd20100000061e238addceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1f020000001b923abc018b9d0600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac8a000000", "prevouts": ["180323000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "ffde2200000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "0f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa6f8d113c18817a044fae8525416b35b4656d6d7185568187de608cafb5211e2f68491001e36edf91058819766439c3f31bd198abbe3d2204f458ac7743e1d61ccf16a5e3db9e2b81c974405e52c4661efcc91a529144e47e78be5814d4a09901"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c7116f5c3e80617093632a2db9fc234f36b396a24b73f6adf68743edb71604c5d8798a2c57206b85b6eca830bd166e5350a1cd63f89078c321fceabfae97dd5c29bd03bbcbebf503f24139d653052e63a9a9f3faf73bed4a74eee576514948d11491142a38ebb10a24e36aadbe0cf227dedfd0966bcf56b2aea8b33dc3fd67f"]}}, diff --git a/txscript/data/taproot-ref/cbdd9f9ee3d06ce2cdfe2000194d0fa14bb03cb0 b/txscript/data/taproot-ref/cbdd9f9ee3d06ce2cdfe2000194d0fa14bb03cb0 new file mode 100644 index 0000000000..388a03f9a8 --- /dev/null +++ b/txscript/data/taproot-ref/cbdd9f9ee3d06ce2cdfe2000194d0fa14bb03cb0 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c453000000000462a8e904bfaa3200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75b000000", "prevouts": ["d43b350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_97", "final": true, "success": {"scriptSig": "", "witness": ["23baa00c82b9cc499dbdc6037c9ab83f4323f73ae95a0de7d0271fe4f3d2660a3aaaa2f16890c7a07940d2ba9498b73c241be285333e1c3ea78a6b57700cf51d82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["1337dd860788e13931302a7e317e5705364f2bb589159cd4363ec42493f2aca5247ea30fb521c5268763bdace0fd6176964bac82528e902a1ab83d25b0802a6b97", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cbe16c2c588c6bc7000fbb04188632167236d008 b/txscript/data/taproot-ref/cbe16c2c588c6bc7000fbb04188632167236d008 new file mode 100644 index 0000000000..84afb210be --- /dev/null +++ b/txscript/data/taproot-ref/cbe16c2c588c6bc7000fbb04188632167236d008 @@ -0,0 +1 @@ +{"tx": "b4abf2a802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4baf00000000b44aa8a6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7a00000000201254d604ccd0a80000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a64c020000", "prevouts": ["87bb2600000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "998a840000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936269ff6546b497129ba1fe09f7f94be9a0d73dd3621c79696a97c5ae123801203edc23a266999aa1773fe99be867e95cb2abe2d57657b7a4dc20a388644aabac6d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004539f0e83d2be49ca995d97c64064bae5b8c7dff64f3bec17af779836b699250933d2e072fd8e8376d3a54b2bea1bfbfff1298aece70c0bc2934c8eaacc3044fe58f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}}, diff --git a/txscript/data/taproot-ref/cbfe3b47d8728af1b60451af99e980f90dc89668 b/txscript/data/taproot-ref/cbfe3b47d8728af1b60451af99e980f90dc89668 new file mode 100644 index 0000000000..0fdc32b0cf --- /dev/null +++ b/txscript/data/taproot-ref/cbfe3b47d8728af1b60451af99e980f90dc89668 @@ -0,0 +1 @@ +{"tx": "6ebe113f03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c480000000082f72a8cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba501000000f5b89fa8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcd00000000c556cf97037ed2db0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acbb000000", "prevouts": ["98a94b0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "d2402700000000002251208f7166d23fc1e45fbcf26b51bd386ab915626b0708475a8743064036728c78ed", "8f956b0000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93626dd86fe63929c58a9e26dc691794fb2cff71343e8c54d7eaccca19ca634607d"]}, "failure": {"scriptSig": "", "witness": ["6a4e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/cc06cd6c0a43860436758eaf21a715c3ecebb6f4 b/txscript/data/taproot-ref/cc06cd6c0a43860436758eaf21a715c3ecebb6f4 new file mode 100644 index 0000000000..618d448b53 --- /dev/null +++ b/txscript/data/taproot-ref/cc06cd6c0a43860436758eaf21a715c3ecebb6f4 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5e00000000bb4e8ee2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8501000000acba6b03047a1da200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac91030000", "prevouts": ["a3a5820000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "952e220000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "b87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faff5a0b04042772840f11ed5a15b1f6f5628d6ed53a9b814a67fccb7bf41c87856960f5e71abb11fb1594f725adbdd26a9f61c928558a58ca58d11d05eb565d16"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93695dc9c98a36c2184a4aed19b2e2b490335edbf9105ab62ca8297ce8361fd2945d64c15a931058236adef8a4965d2af6c40e751c52c93bf72b53dfa72cc6c024bd12296fcc73680f3617d8f33f0de746e19dcfecb08411ea531ade48d4ab609a0"]}}, diff --git a/txscript/data/taproot-ref/cc13210738ed00cc6f24c6bdcc72bc63f13783e2 b/txscript/data/taproot-ref/cc13210738ed00cc6f24c6bdcc72bc63f13783e2 new file mode 100644 index 0000000000..0b796a6c95 --- /dev/null +++ b/txscript/data/taproot-ref/cc13210738ed00cc6f24c6bdcc72bc63f13783e2 @@ -0,0 +1 @@ +{"tx": "d1497db003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5a010000000ac409eddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1802000000b7a057afbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff7000000007c740f92045d5fac0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce5030000", "prevouts": ["d1a0230000000000225120595c2c45ec3b255cb7947059399917a9363337ebaf1f68587c1f93f355b1a53e", "d84b2000000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1", "d77c6b0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "7b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936338668e4e5aab28bcde1228c1172683f4e862ace4afbb2c726076e6970101528d15ee116aef2a5177f7228fbf74f7a33b70e884325424982f9125cdefb107591d34322f35809060e9857f404c38bdcaf402c3d07c78e42a3b4d1eaa304dca88a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688ea954498e4daa92a6ad47f2895ae184189a1c00dbf2f0b5426ffb4ba470bbc3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082565447efa486312fa493bc3efa8d0ca00e2c766484411258b08f0fec6b85156cd34322f35809060e9857f404c38bdcaf402c3d07c78e42a3b4d1eaa304dca88a"]}}, diff --git a/txscript/data/taproot-ref/cc3fcfad22ff1374fc57610045f054311fc92f6d b/txscript/data/taproot-ref/cc3fcfad22ff1374fc57610045f054311fc92f6d new file mode 100644 index 0000000000..8191f95605 --- /dev/null +++ b/txscript/data/taproot-ref/cc3fcfad22ff1374fc57610045f054311fc92f6d @@ -0,0 +1 @@ +{"tx": "613ba07402bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2b000000006ac1a3f4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9601000000db51c5bc04110dc900000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787e2e1e433", "prevouts": ["42e6670000000000225120531ded2803baf703e9b8f23e3d6d5459ce6d94a03d15c5d2addf83c32bf56dd4", "0c7163000000000017a91480e36171416c0f598c1c20ba17ab3a3cf10a438e87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "success": {"scriptSig": "", "witness": ["935646b576b0b11572ecb7d763b3752d1b3e3071d68da7989bc27b0a11e41c2484ea9660583a3ab9eb0f36df160c9695f81df5ac47b4a66b087ead00f53a488b", "82a33283e5d5c118bc3d691b8db05e02da66167cc666945c453ffb4a09ea4a4472f9364d2e6916bb47f5525f79ee246301e8f3b5402002ee1596b70345de3028792e3e7493ada914165f2cc1af7df32cd3bdd523ed818868225a87bd58614d6621d163c6c60a90c06a34f4005fc5a17cbf96fde743024c1621781857a3541283727569c1749751335dea0142545e2b3a41a6db82280f82c229f7552c6b87", "7529dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32505163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936209fcbf868c6a92e3c0922601247e008b3969bf10bdcd8ca5fa998dc09f06a802f0687d3d34dc8b489cf59c8c228dbf015289fca3e4efd1722cfb109cc2081b7ca6089e21816ee6fd9a868544bf105dae013cb095fc7c6576ac374e7e8f3f8a7602d400119a30f02884c803070bed436c54f0c764acba1003e7b049809258f4f014d23742a8b0635629b71bdc4b60db6613049ead7caa2d9b094988249ecdbb9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1943d105a940d03e9376e8b3e63e48c7f2ff317953610e0508c36b01b926f3cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe393e179a7c211225fedfe245fd3ff3e5b3b1c166e4ec0cb700ba82adf7aeaf5ad30f1d4b86ba70fd5952ff2c48b877f705fa7be27f33e4586133d7e5e03ab43e1599d86a25d8f86a682e21d7f29ade2766977671fd4b7506d0d0b5207b0389f00000000000000000000000000000000000000000000000000000000000000007306296b50d506f086f706301f20f725476797ace7d41d8e468e65190ed21eaa414484a1e0e20d9687323f6fce972a7a1fd6e153a4ef49341e3410a13e0063c2a182bfd0ee25f13c6ae38b4288d9a81f069ad6c09f922b6ddbfe4a3348425f453eb697bc1fdc52047a055b28f979b09368d0da8f46da673012037611c64f24321754d5499f8d4371da62fc4af30a52025d38436a936952f1b22a2f152627c609d22eb9d1dc260d11d3d0ab60b5b2aa1111fe23dcaa8498d486e83fabbf555ffaae55a871098d440d13c08dc61184cecc9fca543fd2d38fbc3f0a8209d0e327ad3e1ea5d1d342e58f9725d4f24f287d7f695e6f7367c0b147c406839b6f030da936a9d2298abcbefa3909a813ea3e209227741a2f982d73f026fa7995b10b7941ca1c65131d3215c8773fd39e328aa908c34c88767ae8beb7c98bca985e9e69025922cafb18a8e3286b8333f1c32af113971af648debda5f7a678f807a69a704ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5066f4b09a82745bdbff3fa2cfb73c1e652e1607b0bff475648df74fd8cf08f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013af8904e1b79af564ab7f5afff68a2e3a7266ad5fa82631bbd9a95c5349fe52241c28ae717ce886306e999440b0dbce9372afc7b8cd81e3950bceef0e6d5145923205cc3475b468205b508844fff1cba286c6c4e2ff27b038252313498562a8f0ea45e8cb1d1c5851995e10985ecb619a06de0a240887d1a160813387d846a42410ae81325b565e9589b6e31631d911ab8678fa2f130377d850da29e6f934bea5d5329fe1c33baa779c27ad78bd9f979007888b131969ce0d52d9a0c1635b4dfdb12f2b62cf7736cf70ffff63226c8e300d163a02cf44f3fb6c8d7a9b87fdbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00942d3f1f97d12ca642e60b32e55257b9f2ca905b11dd8880e159a34972f1f0000000000000000000000000000000000000000000000000000000000000000cae63e109f271654eb81bceae7b9c8b2d63ed3f7609cdfde56e8e3017b189bc9da4f7821cd5488e443f829e75a5cfd10ece6c0ce2e09c00b52f986184d74f654cd71816d36dd62349d50f8907985256f4897ada0dddf3bdee11f3eec82f046c407dc150fb3957dd1110f98674d4628e447aa99ad7d4ce5b77b9b61673db283890000000000000000000000000000000000000000000000000000000000000000843217d87b626094c87746ae63facc04ba6cfb18df41de050cf290ba923cdec30000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa785034f31ca41d97e22d96c048424c6c5f47e4e02f5d319c1ad79a8af057c7be9b2fd26b09f5289641de9fabec1b4afce90be6c87ec4dc958481741d42bf3e03b70fbe2ba7043aa8a3d576a354996ee39e30f7a6e45c8de59569288659f0ccfb6af35be1196b8a78de45053eaf8ad9e4cefa14533a0d55d44ed7a16c49f566ef8e2c17cbaf3cba96e205eb120df0ee008d601f642b32ca775c1dd1034841c28d30bd54dfc020d0973914dd4fc03525aa38a12a2d2478b1b3983187c8220bf00ddacf0537de087eeb84179c2b7b129ce1a17257549013160dbe484c9ec243157dfb321c8e5f99aff6743898e964b6e962fbf472b1fc11465e82ba58922e00a9baecda451bd0bda31d6b56f8fb35e04c5efce2e164e269979fd5f8a3ad19422c2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e8271eedb99588d76c587d61cbc001753212af09a33c76077832afb7ec7bb7800000000000000000000000000000000000000000000000000000000000000001965ca26b454da66c7e1feafa45468a24da27a44b4ae760f1487992bb3d3cd644a2fd07ca94ab1b3a5a610f04909fb93b5e4668f5de49294c8adddf0cbd18190000000000000000000000000000000000000000000000000000000000000000049ad7827f314ff46d53b82cc7b55d79a144869b9f71ac2e54d0ecaeceaa07d534b179a52a405bd5263a6c4989b3eac46a4221618c2a8afac08bdcb125670726f85c03d117a587ce130803bd78a9f636fdb5f10257619ed4e1ba7e11f2770a5744c543e977a48984739ac6e93a3a77a563d0632e65c7fd46e476b1ca70c3455a1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff493c612fe574bbd2488fd60abd7173e07a3b5207bdc9a3c7b940f48fd042861804f9e00d834e8b81fd807b280556335504af2c326a6c0e740d4bc81d2173666b93e432f92290af3de5dd855f57f66bb08ade71ec6097f204b9c28939e778521fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff090d2ab16acc7b36ee013fc3d24b20bacd45bc1a519175f55d9cd2041873dfb9436b83cf76a5cc3721fc6c2d562e03cd5c0e89e2f006e7cade685aea921af0acffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f80f82119a89b03095a1361de8e05dba6c36b4feeef2920b2576bb7d91e412a3ece1b56c2492e002fbed1b98bd3f808f43332a4ac6a99701b26d87c5be54b5e69f13c97c97062f0dea2872e87b2e6a72577166c4791392b24a7b80bf93af85bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71a3e93deef542a49e152b87d81a3ac84a3285e7f3cef7cf8f0fa806dfc906d27c7e8b4fbc67c25a2aac37ad899bb8bc865118d3df8e99a5c4276ca115d9675eff73e6d0f505395120fd02a6c0c6f272d1520d6d6e450a0a7f318343b310169effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcff21cc4ae43b31ce85b6f99113615b55ee5087c7922dbdfd82aa065b9253626f004ecedefdd1d3aeaead8dd5c8e44ac769bfc0b626b2525630621cf72375c5352de4a30c7888dd8802e0e2b34d96ecc3d606aa2d93f371bdd05a3fd13f4a5261fbd831a23f77facf5f60aa07ef7caf3f0c954193a726de6e70e2b7052f5517e"]}, "failure": {"scriptSig": "", "witness": ["935646b576b0b11572ecb7d763b3752d1b3e3071d68da7989bc27b0a11e41c2484ea9660583a3ab9eb0f36df160c9695f81df5ac47b4a66b087ead00f53a488b", "8d67dfcb201b43654275cabd911f2be40f34ace56402838c7eddaa8d720270aef7dfa4e61d708504558d34ee23a6c7d645ea7dcad3763f6fc7c5043b367c652f6073ac302b950dbcae919a77e65d6fb4669b3dc231380ea84487f0a74d2cfb0677ba1f143c6aff0447c042a4207865d89129f64fa254f2c1debdfcb5919841bcdd159822f28f6163203105049211c22a2ac5997e3619aa79be3b8ddd24", "7529dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32505163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936209fcbf868c6a92e3c0922601247e008b3969bf10bdcd8ca5fa998dc09f06a802f0687d3d34dc8b489cf59c8c228dbf015289fca3e4efd1722cfb109cc2081b7ca6089e21816ee6fd9a868544bf105dae013cb095fc7c6576ac374e7e8f3f8a7602d400119a30f02884c803070bed436c54f0c764acba1003e7b049809258f4f014d23742a8b0635629b71bdc4b60db6613049ead7caa2d9b094988249ecdbb9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1943d105a940d03e9376e8b3e63e48c7f2ff317953610e0508c36b01b926f3cbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe393e179a7c211225fedfe245fd3ff3e5b3b1c166e4ec0cb700ba82adf7aeaf5ad30f1d4b86ba70fd5952ff2c48b877f705fa7be27f33e4586133d7e5e03ab43e1599d86a25d8f86a682e21d7f29ade2766977671fd4b7506d0d0b5207b0389f00000000000000000000000000000000000000000000000000000000000000007306296b50d506f086f706301f20f725476797ace7d41d8e468e65190ed21eaa414484a1e0e20d9687323f6fce972a7a1fd6e153a4ef49341e3410a13e0063c2a182bfd0ee25f13c6ae38b4288d9a81f069ad6c09f922b6ddbfe4a3348425f453eb697bc1fdc52047a055b28f979b09368d0da8f46da673012037611c64f24321754d5499f8d4371da62fc4af30a52025d38436a936952f1b22a2f152627c609d22eb9d1dc260d11d3d0ab60b5b2aa1111fe23dcaa8498d486e83fabbf555ffaae55a871098d440d13c08dc61184cecc9fca543fd2d38fbc3f0a8209d0e327ad3e1ea5d1d342e58f9725d4f24f287d7f695e6f7367c0b147c406839b6f030da936a9d2298abcbefa3909a813ea3e209227741a2f982d73f026fa7995b10b7941ca1c65131d3215c8773fd39e328aa908c34c88767ae8beb7c98bca985e9e69025922cafb18a8e3286b8333f1c32af113971af648debda5f7a678f807a69a704ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5066f4b09a82745bdbff3fa2cfb73c1e652e1607b0bff475648df74fd8cf08f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013af8904e1b79af564ab7f5afff68a2e3a7266ad5fa82631bbd9a95c5349fe52241c28ae717ce886306e999440b0dbce9372afc7b8cd81e3950bceef0e6d5145923205cc3475b468205b508844fff1cba286c6c4e2ff27b038252313498562a8f0ea45e8cb1d1c5851995e10985ecb619a06de0a240887d1a160813387d846a42410ae81325b565e9589b6e31631d911ab8678fa2f130377d850da29e6f934bea5d5329fe1c33baa779c27ad78bd9f979007888b131969ce0d52d9a0c1635b4dfdb12f2b62cf7736cf70ffff63226c8e300d163a02cf44f3fb6c8d7a9b87fdbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00942d3f1f97d12ca642e60b32e55257b9f2ca905b11dd8880e159a34972f1f0000000000000000000000000000000000000000000000000000000000000000cae63e109f271654eb81bceae7b9c8b2d63ed3f7609cdfde56e8e3017b189bc9da4f7821cd5488e443f829e75a5cfd10ece6c0ce2e09c00b52f986184d74f654cd71816d36dd62349d50f8907985256f4897ada0dddf3bdee11f3eec82f046c407dc150fb3957dd1110f98674d4628e447aa99ad7d4ce5b77b9b61673db283890000000000000000000000000000000000000000000000000000000000000000843217d87b626094c87746ae63facc04ba6cfb18df41de050cf290ba923cdec30000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa785034f31ca41d97e22d96c048424c6c5f47e4e02f5d319c1ad79a8af057c7be9b2fd26b09f5289641de9fabec1b4afce90be6c87ec4dc958481741d42bf3e03b70fbe2ba7043aa8a3d576a354996ee39e30f7a6e45c8de59569288659f0ccfb6af35be1196b8a78de45053eaf8ad9e4cefa14533a0d55d44ed7a16c49f566ef8e2c17cbaf3cba96e205eb120df0ee008d601f642b32ca775c1dd1034841c28d30bd54dfc020d0973914dd4fc03525aa38a12a2d2478b1b3983187c8220bf00ddacf0537de087eeb84179c2b7b129ce1a17257549013160dbe484c9ec243157dfb321c8e5f99aff6743898e964b6e962fbf472b1fc11465e82ba58922e00a9baecda451bd0bda31d6b56f8fb35e04c5efce2e164e269979fd5f8a3ad19422c2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3e8271eedb99588d76c587d61cbc001753212af09a33c76077832afb7ec7bb7800000000000000000000000000000000000000000000000000000000000000001965ca26b454da66c7e1feafa45468a24da27a44b4ae760f1487992bb3d3cd644a2fd07ca94ab1b3a5a610f04909fb93b5e4668f5de49294c8adddf0cbd18190000000000000000000000000000000000000000000000000000000000000000049ad7827f314ff46d53b82cc7b55d79a144869b9f71ac2e54d0ecaeceaa07d534b179a52a405bd5263a6c4989b3eac46a4221618c2a8afac08bdcb125670726f85c03d117a587ce130803bd78a9f636fdb5f10257619ed4e1ba7e11f2770a5744c543e977a48984739ac6e93a3a77a563d0632e65c7fd46e476b1ca70c3455a1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff493c612fe574bbd2488fd60abd7173e07a3b5207bdc9a3c7b940f48fd042861804f9e00d834e8b81fd807b280556335504af2c326a6c0e740d4bc81d2173666b93e432f92290af3de5dd855f57f66bb08ade71ec6097f204b9c28939e778521fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff090d2ab16acc7b36ee013fc3d24b20bacd45bc1a519175f55d9cd2041873dfb9436b83cf76a5cc3721fc6c2d562e03cd5c0e89e2f006e7cade685aea921af0acffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9f80f82119a89b03095a1361de8e05dba6c36b4feeef2920b2576bb7d91e412a3ece1b56c2492e002fbed1b98bd3f808f43332a4ac6a99701b26d87c5be54b5e69f13c97c97062f0dea2872e87b2e6a72577166c4791392b24a7b80bf93af85bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff71a3e93deef542a49e152b87d81a3ac84a3285e7f3cef7cf8f0fa806dfc906d27c7e8b4fbc67c25a2aac37ad899bb8bc865118d3df8e99a5c4276ca115d9675eff73e6d0f505395120fd02a6c0c6f272d1520d6d6e450a0a7f318343b310169effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcff21cc4ae43b31ce85b6f99113615b55ee5087c7922dbdfd82aa065b9253626f004ecedefdd1d3aeaead8dd5c8e44ac769bfc0b626b2525630621cf72375c5352de4a30c7888dd8802e0e2b34d96ecc3d606aa2d93f371bdd05a3fd13f4a5261fbd831a23f77facf5f60aa07ef7caf3f0c954193a726de6e70e2b7052f5517e"]}}, diff --git a/txscript/data/taproot-ref/ccb6fc2bd7df140d0acaa9fa4f6c64be65339a60 b/txscript/data/taproot-ref/ccb6fc2bd7df140d0acaa9fa4f6c64be65339a60 new file mode 100644 index 0000000000..c51cccf1e9 --- /dev/null +++ b/txscript/data/taproot-ref/ccb6fc2bd7df140d0acaa9fa4f6c64be65339a60 @@ -0,0 +1 @@ +{"tx": "f33c648a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1801000000efe045ba8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a4000000002db817c60273f54f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aca3000000", "prevouts": ["3d7d1e000000000021511f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "c54b3300000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["d274921aecbeb3031c4325f0ef8a23adff0ed7989377ee835ac54787b8fdc4f2e7295329ab844153de271583114b354e1e43309c3042e16794fa1975c037eba8"]}}, diff --git a/txscript/data/taproot-ref/cd083f5472e5c5b1f0a2910e5400ed9fb0e38379 b/txscript/data/taproot-ref/cd083f5472e5c5b1f0a2910e5400ed9fb0e38379 new file mode 100644 index 0000000000..d6254a96d2 --- /dev/null +++ b/txscript/data/taproot-ref/cd083f5472e5c5b1f0a2910e5400ed9fb0e38379 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c78000000003e1cfcb0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c87000000004eb3e1eebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf930000000022a849d80147e877000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487a8000000", "prevouts": ["f2d35400000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "17484f00000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4", "72f17a0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902826b92e489c52391673ca744d83e228293191492e2d901db7a033a79c8bea7107eace03029c7129e39f3a909dc8ffe6b90754373717e66246ccedc9e052ed3d6f550060f0ee501c40ff79c029c26083e18a30c721fccad49fc127d0138c5608d790468a1f908be0dd9443c422cb7f689609ea85e72e839d44be27b8840f24073ba9ba9e2676ae2b15b97df7d96fa3f62f8117c08ecaa7dec882326e49141d72434ae0223efbfa2637f4daea625871c0b4fc084e3fa81cfdeb510df6319b840af59ca47ba6219e980848081fb5184c9fbad150419b97722cacd33a99d36d4c1082663b7ed0f0b0935c3620ffe25d962bb6ba30ab655e89c143c3eaf32cbc12d940cd3caea23f564eee36468a2f5d4ba8653cb5837d435980439856a40575f7fcb49e0b745a20c7b75465eab42551750dca0fdd0d6dc23bb7b14c971146ef323cdc8dbe963984b5687dc0dfe86f1e19c038372d6f6955d208d2d5ed69e66894e5cb0b4593e39484c4982d496c02b4da70965dc5ecbde230f631bc9238e1dd5a414c0438ea322fd21242a0cc1844a81169e1061b230b9291e6419e8232cab07a18c20e18931d64438d901d160d81a90bf853931aa46937a04413d857398704891418b9ebdd27a70ae989ef2ce174463d50452a9d311211ef46f0853d1a6ed9aea7eb65aa728a6cf4a3252ddc6d2e30533a54d91b9c4b1fc47e2ad977447a265c728bb7c106ebb7d428d9775", "ed7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ef2f17803e9b9097b7e9c6a3fa063cf57bf5437f6dd783e7782f9707a99cea5998d6970ca8674a6d6a6636f00d706375e44157ef6300dc02db98f8ce0d082c1d19f2c0f6744ba7ac1f5ff1e4bbd0a31d1cdb1f5d58d1dbc476492d0098121b5"]}, "failure": {"scriptSig": "", "witness": ["4d0902e89b80a27a3a8ceaca1bae7baa51dfdebfb01f7c38d20dd1d9c160e369f4ae61b4bc8a91a7eb6e23a129c512fd7435b24c4132c28155c8d81633abd69c37370f8a69096e8ad562190f3f442bcdbf603048257efbda11522a32e379b47315641be17f1884b7e3a19200d178c73d44812b811024532c2902141a9e77e0bf7b5c649be427c95ec4c948df084512fe80054afc1bde0e8410dbfbff1fd1ecf4dd870345a54df2024ec5608edaf6c0679b7f69b8280d4f870db70f10863172d6fe146f8afd03df1cceba90aeed3cd934e55b4f4d2fc15a1b38a51730211d2b639dbf7039c4f3ad638d222108c6c32742c0f67ad0ba919ffa320d6f85b954789b1cf996ce496e79e8955840811779e79814d0a52bc5872ad1e8856cbf85264848cb5c2146666d7d38916aa352b9ed144eccd298336b2280ee36fb055f60fe92c8f69a644332af45e96da46ed3760824b147d403e6e5c62b511fd7d59191d907efa45e45eb9996af32f75153dbc2199effc69d53b80833c7f2c639acd216db21142101ae4073dbfa30a32a93c68a57d27ab6fc5acf77447bf9b735610ab3a975b87dcc58909e00fe8ff9493d45937b14bfa39deb7262845cf63b8711b20f452c9e03a355bd4dceb5a573592d20063886337281d1231e5e8479b16b3e822f63e79a72ffbde97cf7aab8f01ef3d784d4855d54dd5968ce6aba3b18dcc1426011abfc5851e13172a7cf5ce9fd3b2675", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670a4bc76aed2418d25137dfbb0a799899196711239bc580b794f0105b1596aa027d2631c3cab5fe643277004a2e6838e79a7dd6765c91a13be066042b33c17d3b131de5807af4725e3fdc8c81388bc895736ddb6e799e7163e8586c833ffc627"]}}, diff --git a/txscript/data/taproot-ref/cd2bb450b14d6d4aeb2383f17d0b52532a6d60bc b/txscript/data/taproot-ref/cd2bb450b14d6d4aeb2383f17d0b52532a6d60bc new file mode 100644 index 0000000000..bb2dd36d62 --- /dev/null +++ b/txscript/data/taproot-ref/cd2bb450b14d6d4aeb2383f17d0b52532a6d60bc @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703700000000456bf00a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e101000000c6f1b10a040edf4700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcba4b604d", "prevouts": ["e40e0f000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "5b843b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082dc2f05b59194cbdf87848463e1c2c1324ea07adf35e05c7c9d5f4b3dae1cf3a20eb43d08761fb76661299d0344fd2d8bfc7de5e7c6dc622156e95971f4b8396db5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ba371f3d414732c1c9e15a0164c634559da48866c534aa79174298bfda3b2aedc2f05b59194cbdf87848463e1c2c1324ea07adf35e05c7c9d5f4b3dae1cf3a20eb43d08761fb76661299d0344fd2d8bfc7de5e7c6dc622156e95971f4b8396db5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}}, diff --git a/txscript/data/taproot-ref/cd2f80cd83fdc9c096ed0c6e1e02112a0e62dd16 b/txscript/data/taproot-ref/cd2f80cd83fdc9c096ed0c6e1e02112a0e62dd16 new file mode 100644 index 0000000000..cdcbf0827f --- /dev/null +++ b/txscript/data/taproot-ref/cd2f80cd83fdc9c096ed0c6e1e02112a0e62dd16 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe30100000030bf24908bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b901000000527fb1ee02a3f9a600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac15e93a5d", "prevouts": ["33896b0000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588", "92d63d00000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "da7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936043c0126a9ff46f80efec90b265339725ec2187e176bf61e9c8112d2ff543febee00e627ce877dc7a3321ebc519bf09c5aac598ee9e81cf6d3228685de2d2a5f9a29f5cb7818ea23e4b491695dace811707e8772e99626d3237c076ba9a076d6566ba3404d3656bfd0df4a55f82c254cdba579fd51be164a5cd21fa2faf92a44"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e9267ca3ecfb5dde8490070ee5c8f144d07948eba84ecbc5d8caabe33435ae9c3fb4f37cceedf64e5ab756f8bcf3191fe56bd549db8641e271ceb60581364e38eb0481d56926b359fa3e2e34471adba51fafc61fa70dea7541795bc082db9408"]}}, diff --git a/txscript/data/taproot-ref/cd4a620abc44efff9ec16d12232d21d35383be02 b/txscript/data/taproot-ref/cd4a620abc44efff9ec16d12232d21d35383be02 new file mode 100644 index 0000000000..7302c4c4fe --- /dev/null +++ b/txscript/data/taproot-ref/cd4a620abc44efff9ec16d12232d21d35383be02 @@ -0,0 +1 @@ +{"tx": "b9d6ebbf02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce801000000681a4abc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c401010000007e28d0e301fb412000000000001600149d38710eb90e420b159c7a9263994c88e6810bc77e020000", "prevouts": ["f476560000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "cb49320000000000225120860c89f9477f4b6d0745b3db3a3158e326aac77c9b39db987890c5dea40689bf"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dba6d090ce6eeca8f19bee4c4b18bd87e742c613226dbb66d44b3d8c22cd4f417d143406647e47f2aa45aee5a8d37fbb079fe3a633dc3f79123da3b3ed47a821a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93645b70697259a6092735a83fd9185b271706fbd91da528cf82e26060ba02f7d12c3950c17255228812280bec2d0cca04b586565374a97ee6c913745c9c1a159600ce9ba0618adb3ee44483a22999a54a4e1710b9846377d8164aaa29371d79f22a2fa119ef3ac370f8290f87fe8954e212d8c61d3545cf9da1d8aa62b42f72813"]}}, diff --git a/txscript/data/taproot-ref/cd536df731fdebe8bbafa86ebef1f6c819648a78 b/txscript/data/taproot-ref/cd536df731fdebe8bbafa86ebef1f6c819648a78 new file mode 100644 index 0000000000..19c138d9f6 --- /dev/null +++ b/txscript/data/taproot-ref/cd536df731fdebe8bbafa86ebef1f6c819648a78 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b00010000006626179d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4dd000000002f9f28d801c65c470000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e70cd67b4d", "prevouts": ["308e200000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "e53e310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_cf", "final": true, "success": {"scriptSig": "", "witness": ["bae9395b8894fcb53fcb94909630e0fa8a7b6639cc70b42d414bdc065976bb6134718999d87a92fa944fb8e715b732bbe403f303c5d78afd294a31419a2b92cf02"]}, "failure": {"scriptSig": "", "witness": ["bffb08b72fb67852c00a7affdfd1ac38d86230e434c3ffec1a01f8f80ece2c15cc413867f11f0d51dbfb27c50080cb9c4799be48f62416760d85c944157b1d58ce"]}}, diff --git a/txscript/data/taproot-ref/cd553bbac6c8bd33ad432ca2077facbf41604f68 b/txscript/data/taproot-ref/cd553bbac6c8bd33ad432ca2077facbf41604f68 new file mode 100644 index 0000000000..29039d5384 --- /dev/null +++ b/txscript/data/taproot-ref/cd553bbac6c8bd33ad432ca2077facbf41604f68 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1502000000692e59dbdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdf00000000d423c2f302fde5ca0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac6ee00e50", "prevouts": ["0990850000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "90e7470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ab", "final": true, "success": {"scriptSig": "", "witness": ["1b145c19a6eef262e669c0544ef41c63da8b0cea3e09dde2c5df4af0522431b770886ba4158cedabdfcc1094cdaef9c2bcb69961d579197838229249f074750981", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c94b05e615cb27ed909e1a6839bd774f1b7acba2a2bc54c44c4e7085075fd210d5b29939d12fc91b80c458b89bae1acfe521d0d4ba0720b867ec0686181907ccab", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cd8b40b4ffe13dc923550924d4133d5ac918ecc4 b/txscript/data/taproot-ref/cd8b40b4ffe13dc923550924d4133d5ac918ecc4 new file mode 100644 index 0000000000..f695b99fb8 --- /dev/null +++ b/txscript/data/taproot-ref/cd8b40b4ffe13dc923550924d4133d5ac918ecc4 @@ -0,0 +1 @@ +{"tx": "02000000031980a99ad1eac101c8fe3dd9b7c19f4e81dda5a690601a9eedc2ce713d9132e5000000000007acc88a492909e056fa5c0ef2af542be68aba07da39583e95b43e24484150891b1d532301000000001ad6d4dc1980a99ad1eac101c8fe3dd9b7c19f4e81dda5a690601a9eedc2ce713d9132e5010000000079e1bbdd02ac0b058b320000001600146d764276c66fec1127e5074db5bff3aa6c52553358020000000000001976a9147d8c30278dcbf5bd88310a3c91abbeb33651906c88acd137773e", "prevouts": ["7371c1150f000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "b7e4d4f711000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "6689717d11000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_invalid_unkleaf", "success": {"scriptSig": "", "witness": ["25428a9bd8f0b5b74290865c0e042df7df41ee41a4cdff2193fafef490ff48290a0f40eeb563d2c0b6520066936103d46ace942c00a77679690a7ffcc3a6cf25", "20159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717ac", "c2159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717c320986550a60a376b2d6a26894b932a0140931c95b78be03572545c726a283e7902b78fc59ae74800241e9b7a2e0578a35ace37791478c3e04a51e81e708c61"]}}, diff --git a/txscript/data/taproot-ref/cd8ca448ef6a3c3fa7536eee563579389b399c7f b/txscript/data/taproot-ref/cd8ca448ef6a3c3fa7536eee563579389b399c7f new file mode 100644 index 0000000000..a1008f8dd1 --- /dev/null +++ b/txscript/data/taproot-ref/cd8ca448ef6a3c3fa7536eee563579389b399c7f @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270190000000065a894b4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bed00000000c5e85eed04a6fd3100000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787cd030000", "prevouts": ["661a0f0000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6", "f080250000000000225120ed31d524ef6bc5b71a68a40bfd6359c52f177bae49683ad83ab62d1806c34929"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c32bcf051f24a436904823a4e93e2341ae2a2e44bd383fcc6ea0da3aaabadc12"]}, "failure": {"scriptSig": "", "witness": ["6a40616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/cd935e81f7b958dc94cbb682f2c926e1e63fc213 b/txscript/data/taproot-ref/cd935e81f7b958dc94cbb682f2c926e1e63fc213 new file mode 100644 index 0000000000..1eafe41714 --- /dev/null +++ b/txscript/data/taproot-ref/cd935e81f7b958dc94cbb682f2c926e1e63fc213 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2b0100000003d33c9abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffd0100000038eb109e031793e40000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc01802d38", "prevouts": ["08d775000000000017a914613e66961ccf40c7c83ed07cc80b2528cfe51edb87", "e447710000000000225120e477b1c5b341d71bb24c39a2320bc0d86da52fdae37edac491a92c571a2df14a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2258202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["8b4006d050d277b69795e6a2f473003c12721ea302bec3c0af5c31aab3915060d527563039784230876f668b0bd717c49fac01cc4482315f6f4e7e1e5f541695", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/cd9562d304291faf33b2752268819af3d9fdd593 b/txscript/data/taproot-ref/cd9562d304291faf33b2752268819af3d9fdd593 new file mode 100644 index 0000000000..db615af2df --- /dev/null +++ b/txscript/data/taproot-ref/cd9562d304291faf33b2752268819af3d9fdd593 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf05010000006c94ab778bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40c01000000a9aa24900176de0a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a603010000", "prevouts": ["46617a00000000002257202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "f7ef3b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_65", "final": true, "success": {"scriptSig": "", "witness": ["c88fca301f28870dc7b00e87169aa933f0b517d595bf2219880d036e9341cf0010e0fb47bc33890f3a50d8282602a012d4e6fec3f63f7257a0f344d2b250abf302"]}, "failure": {"scriptSig": "", "witness": ["028efc73b374903084f5d5764340bf31627fc1e2ed3048299aa3f9e1fd4d9db5e39abcfde42bdab263c2a91e2392a9cec5ad262251b54cb84be4a2f871200e8865"]}}, diff --git a/txscript/data/taproot-ref/cda64a68115a3ca8971a2747b360b387fbe1d1ec b/txscript/data/taproot-ref/cda64a68115a3ca8971a2747b360b387fbe1d1ec new file mode 100644 index 0000000000..c5fb940871 --- /dev/null +++ b/txscript/data/taproot-ref/cda64a68115a3ca8971a2747b360b387fbe1d1ec @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c487000000004bc7f4e2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb6010000002fc980f20145803400000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac1c40ee26", "prevouts": ["9dc3410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "deb0220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_fd", "final": true, "success": {"scriptSig": "", "witness": ["d85f74a2016b0d3a0d15194034043af044f7ba411d3d1714454db830b63e729f4cce3f5cea3832d1fbafe2e5b2f817c5f5a64c5e07e2e0efcc0f7706e743bbb481", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["82807f54bec9c57334a769c386b52f3f9b91a4db2800ec02ef38736720221a9af43cc45a23857d9d570a1d184dd02399a11b1d31ebb4f0887084fab7c33b4a92fd", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cdaa800ed715e873d65a75ff494c085689777769 b/txscript/data/taproot-ref/cdaa800ed715e873d65a75ff494c085689777769 new file mode 100644 index 0000000000..4b471be592 --- /dev/null +++ b/txscript/data/taproot-ref/cdaa800ed715e873d65a75ff494c085689777769 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf06020000005a8d6e1adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4600000000fc86371d025cac980000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787141e232c", "prevouts": ["22827a000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912", "7aab20000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "5c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936900f19854bc90d6c79e0184be6bef7ba18c323656bf267ebd46e4fd22ae910800ebd37c9b7767cfa75ada9a6605680756deb542ec34cf1dc29d9c7b172412f3174e87bfb4d3d415907d7a3196832fc57be4f6d746253c89a46e8e4c968740366e8f45a3ac55dff4b7d62b0bc42204f13e92c55212ff162d480a58edc7717abc8"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936369642414e3e6cba27e1a8d43018b0c6e901f2bd9875554ba9baf88aafe131fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e24e037abdf69c22f44b0c591ad93651f749184eaa819a8a63a5d4092bdddfb78f243c72f4e074898aab8058b3c73fee97ec3b9723e213834a8398e97170c1356"]}}, diff --git a/txscript/data/taproot-ref/cdae175fecf9783890ad4364fcdb7e9a26312c86 b/txscript/data/taproot-ref/cdae175fecf9783890ad4364fcdb7e9a26312c86 new file mode 100644 index 0000000000..72d049b286 --- /dev/null +++ b/txscript/data/taproot-ref/cdae175fecf9783890ad4364fcdb7e9a26312c86 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42d01000000bdb630c88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cd000000003ebb08c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f400000000c26dee9901a9b60e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374879a000000", "prevouts": ["804a37000000000021561f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "47ba3c0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "dfe4400000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "1f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b8d3859c02806498ed0a6443c7e281ed1c8160789600c9782f40e9c097f1ee0446c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facfc86bca0a8859889d9efd3fba9c68487fa49a78b15c293938d32f430a3e576ab3e02c0e1665e1d6a4b6ef98a6ef3a3632c98688db315e4c8eb8907479035d72"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936606f5652115a36f7672906b3ba9acfb073c3f40076f433b0f89c9999ba02a3338a47d733f2ac96a3990499de942ef9a5afce6e4fdb28ae911c182ccc4b722ed2ed661e9ebd30f651fa020177c2a1e4ce51b505c9194e43d6074b392863f250ba"]}}, diff --git a/txscript/data/taproot-ref/cdbb9c9c88d727637e88c5e5f34b796e03a77c9a b/txscript/data/taproot-ref/cdbb9c9c88d727637e88c5e5f34b796e03a77c9a new file mode 100644 index 0000000000..ec08472ea2 --- /dev/null +++ b/txscript/data/taproot-ref/cdbb9c9c88d727637e88c5e5f34b796e03a77c9a @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0201000000a5902247dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b260000000016a000b7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0100000000de383c3702a0e7a50000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4879304df5c", "prevouts": ["f2295f0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544", "0b62230000000000235f212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "bbe224000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/cleanstack", "final": true, "success": {"scriptSig": "", "witness": ["01", "", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f38ec708f0cf53f3b369b3194db6b979fe0cb271fdaad68f02f83e00e6bab6c4f8b9b2591be70a62ed3962c9e65bdf4177c7447c68cebff2d50efdff4267028038515792f22723cd4f021229082349c4f04e1c54e852907992b3d89f9f323988af933dd569ab8ef4734d9ed0029c610ce683439beaa7b2b92d7d5f3785f11f206e293a68e74ead54fc4cd1f2ee252d1412756669ccb87bd0be0195a2fd9047454977d199608b74a0583630fc942382dea1a9b64fce701a02c5c9f815a8d6f7f6fff61305d3bcffd98981c35a7377ac16ebecf9e810a20df0b649c6b66617c71e24bf028b3b4bc9e1d250c72ce187c3ed97dd11379f788342a725ef5254e8152c925be1fdb6690c4e55e22d4093392cf82d7f0a3f5de5ae9c0ca33a9077da1d6d424b46db02ff988fc19cf23a4951173feb3eeb5cf27c148448535e997b51bd7bbd49cc1c9d1c5543faf51f246263bc293a1ec3b05628bc84cfd7f4dfccc3e91545ebbb7a20d90802d61cb761b7ed3a9d8977f7a5521df44543d663068a2348a7c7f6542a544c030cbfdd70964c7e81d665feb2adbff25ad3ab75b67ecf3712c09a0b10fc29ed9ec9ba811a78159d56d191855f20d80384a7f598d54defaeda75074e07476023602dfde1c8d0d124f96edbab4af8198f97e6bceba6cad7de517a8f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["01", "01", "", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f38ec708f0cf53f3b369b3194db6b979fe0cb271fdaad68f02f83e00e6bab6c4f8b9b2591be70a62ed3962c9e65bdf4177c7447c68cebff2d50efdff4267028038515792f22723cd4f021229082349c4f04e1c54e852907992b3d89f9f323988af933dd569ab8ef4734d9ed0029c610ce683439beaa7b2b92d7d5f3785f11f206e293a68e74ead54fc4cd1f2ee252d1412756669ccb87bd0be0195a2fd9047454977d199608b74a0583630fc942382dea1a9b64fce701a02c5c9f815a8d6f7f6fff61305d3bcffd98981c35a7377ac16ebecf9e810a20df0b649c6b66617c71e24bf028b3b4bc9e1d250c72ce187c3ed97dd11379f788342a725ef5254e8152c925be1fdb6690c4e55e22d4093392cf82d7f0a3f5de5ae9c0ca33a9077da1d6d424b46db02ff988fc19cf23a4951173feb3eeb5cf27c148448535e997b51bd7bbd49cc1c9d1c5543faf51f246263bc293a1ec3b05628bc84cfd7f4dfccc3e91545ebbb7a20d90802d61cb761b7ed3a9d8977f7a5521df44543d663068a2348a7c7f6542a544c030cbfdd70964c7e81d665feb2adbff25ad3ab75b67ecf3712c09a0b10fc29ed9ec9ba811a78159d56d191855f20d80384a7f598d54defaeda75074e07476023602dfde1c8d0d124f96edbab4af8198f97e6bceba6cad7de517a8f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/cdd70dfc5c39ec02e5e48d747003dccc345d9c35 b/txscript/data/taproot-ref/cdd70dfc5c39ec02e5e48d747003dccc345d9c35 new file mode 100644 index 0000000000..f12623e5c2 --- /dev/null +++ b/txscript/data/taproot-ref/cdd70dfc5c39ec02e5e48d747003dccc345d9c35 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706f01000000230ae7af60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d600000000224fd88202d97b1f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a626000000", "prevouts": ["621d120000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "78ea0f000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004599aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb406f18ba19de64c771db55f5af06ee3412ffaea1fa921290752d742eff6a1e67f7007ac6d9f1365651a4d55e6df0dcb109d268cc6c386b355a4997173bc95c886"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e197185a6c30608fff89dfccb39a96a02e4addd353a2af1bc7b33caa3a3ac07fec6e41ed285c226ab336f92f35d989a379104ed593ec3ff802714cc8e85daf0b3be26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}}, diff --git a/txscript/data/taproot-ref/ce08102de2f440a689645ebc57829a604424b751 b/txscript/data/taproot-ref/ce08102de2f440a689645ebc57829a604424b751 new file mode 100644 index 0000000000..0e6a07c724 --- /dev/null +++ b/txscript/data/taproot-ref/ce08102de2f440a689645ebc57829a604424b751 @@ -0,0 +1 @@ +{"tx": "63a8de0b0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270400000000003003e95dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6000000000987504ec042540390000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478761b26b4c", "prevouts": ["d92113000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "f77028000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "fd", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9d8f10db74f979c41891759fc87cc010c6171f34a4dc4fa278f7920467dc96cd9f77cfc3030f4fa2d9551f14353e565e33cb9a72a19e79fd0e4930553ab0cc3a3aa70c847d82166fa4c32b27cb78dba1a5c77b2d4b8269442df723c9129fb762c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936427f03015f7a96869233965cfd3869b27cd157bfb8ae4cf2df456ac491585181380f015d033fe7faead4766c682a770029d5c79030785f2d26c440da4ef071fea3aa70c847d82166fa4c32b27cb78dba1a5c77b2d4b8269442df723c9129fb762c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}}, diff --git a/txscript/data/taproot-ref/ce29a0262edb0e4c4a3905e19cb08c9a4e8318ba b/txscript/data/taproot-ref/ce29a0262edb0e4c4a3905e19cb08c9a4e8318ba new file mode 100644 index 0000000000..cd812bd879 --- /dev/null +++ b/txscript/data/taproot-ref/ce29a0262edb0e4c4a3905e19cb08c9a4e8318ba @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c13000000007dd53f9260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b5010000000b3d637101b5bf3d000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d1010000", "prevouts": ["ba5b49000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "a090120000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/minimalnotif", "final": true, "success": {"scriptSig": "", "witness": ["8cadfaf51f6d962fcdde8eb5af4e11e99fe61a0ee123419858ccc8e5d240b848ef2e5b00a9e10a337b8e276a7f106d051f269bc6b641ab1b0f84c42b182cb6d2", "01", "646a6720871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5e13cad19c924f09e742cf01d7e012810213f06b075da864011776c4e0e33ce5afd4f5a80fdb0e775e9347ffe0d8d06d20821e8392839b829c29e03cf24dd39e09e6d21873535d25ffee6834466c284ff42ef82d8fa2fdd706d38dd213905035c198717912f4b406e8d3b313d97c1127d1135c371a850790824e04061625b9d13fad9f6d66cfea14ccee2f27c94687462e60c93097e3ddae516a269438c7ee5497178e22127db6c7f8f175fff2d2055fc4c08a025732ff7ea1096ec159efbddc6f248e0af5869f80622f637a3edafb79d72487846d4b0589ad8df1e49d86b58ae982564b911df2d2fca61beb75f1ecc1a3526592822acf1cb81afd4e2a93f13b7dbd0c12ffd99a2b3242b359ecbd2060409f001c89f4f8371cd210f37fc35c4b1df78360227d44f218f9c188c83f404e81070c2440736b5601340b7fe06d3b1bec47189a7be4ffc0056c3ee876b2f14785a511ffb40f655d5a8b5fa356d4081558c155b0d7e8c00e6282b2c83a0b7370731ce99ff8996d6837e990d84e1874f60a177a028d5b32d1137467ad00d3419299404906e230dd6a3cb22ab6dff4f06738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["8cadfaf51f6d962fcdde8eb5af4e11e99fe61a0ee123419858ccc8e5d240b848ef2e5b00a9e10a337b8e276a7f106d051f269bc6b641ab1b0f84c42b182cb6d2", "013030", "646a6720871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5e13cad19c924f09e742cf01d7e012810213f06b075da864011776c4e0e33ce5afd4f5a80fdb0e775e9347ffe0d8d06d20821e8392839b829c29e03cf24dd39e09e6d21873535d25ffee6834466c284ff42ef82d8fa2fdd706d38dd213905035c198717912f4b406e8d3b313d97c1127d1135c371a850790824e04061625b9d13fad9f6d66cfea14ccee2f27c94687462e60c93097e3ddae516a269438c7ee5497178e22127db6c7f8f175fff2d2055fc4c08a025732ff7ea1096ec159efbddc6f248e0af5869f80622f637a3edafb79d72487846d4b0589ad8df1e49d86b58ae982564b911df2d2fca61beb75f1ecc1a3526592822acf1cb81afd4e2a93f13b7dbd0c12ffd99a2b3242b359ecbd2060409f001c89f4f8371cd210f37fc35c4b1df78360227d44f218f9c188c83f404e81070c2440736b5601340b7fe06d3b1bec47189a7be4ffc0056c3ee876b2f14785a511ffb40f655d5a8b5fa356d4081558c155b0d7e8c00e6282b2c83a0b7370731ce99ff8996d6837e990d84e1874f60a177a028d5b32d1137467ad00d3419299404906e230dd6a3cb22ab6dff4f06738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/ce4f3f6725a58e41e3545de8f93475f0f9402a52 b/txscript/data/taproot-ref/ce4f3f6725a58e41e3545de8f93475f0f9402a52 new file mode 100644 index 0000000000..69f265607f --- /dev/null +++ b/txscript/data/taproot-ref/ce4f3f6725a58e41e3545de8f93475f0f9402a52 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1f01000000f063541e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bf010000003a54a79804b961930000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7969a010000", "prevouts": ["f0058500000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "6a541100000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_keypath", "final": true, "success": {"scriptSig": "", "witness": ["e4edee017e3a08e1f91b7c97a26d29155c6281d50438dcc8a29476fe9a68b99b38b60acc6eef69f102de8cbdfc6d6676e477dcdd31618e0e5de4955021147f94"]}, "failure": {"scriptSig": "", "witness": [""]}}, diff --git a/txscript/data/taproot-ref/ce5a6e30faecc2d2f249b1bb1b0a21cbffc46674 b/txscript/data/taproot-ref/ce5a6e30faecc2d2f249b1bb1b0a21cbffc46674 new file mode 100644 index 0000000000..d8a6795cd4 --- /dev/null +++ b/txscript/data/taproot-ref/ce5a6e30faecc2d2f249b1bb1b0a21cbffc46674 @@ -0,0 +1 @@ +{"tx": "08aca4d7028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48701000000c4c226e3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5801000000dcb7abfb040634aa00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87b5000000", "prevouts": ["5b9a3500000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81", "7dc8760000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "747d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c1c1cec2ec4a702b027c32afe8f050a7abd6c53cc1a056033971ea23441aa0d3133f027656d2d9f64ade865091a06c0b2adab14558eca27c91472397a1e3806e077aea6ccf316b47e40a0e3636c5ad4f7738b9bfce630d4a478a0dbfcb51ed93"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e86e257627f53ae21a01782ee3e7d4da03b01bc19a25fdaba4c8a32b8ecf0a2d91bf4492fa00dc56072e72009d776219274bea6eb51adb458249eab71940c27cb4bfbb1ef2412aee06f4b75b9e20a72d4d9707545a4ae77abc538f76b00105406a"]}}, diff --git a/txscript/data/taproot-ref/ce5c007dab411a6a225c1b09181578eaf6edf364 b/txscript/data/taproot-ref/ce5c007dab411a6a225c1b09181578eaf6edf364 new file mode 100644 index 0000000000..79d6f7df82 --- /dev/null +++ b/txscript/data/taproot-ref/ce5c007dab411a6a225c1b09181578eaf6edf364 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b400100000067e43aff60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701901000000e9710afe02937a2d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4879c000000", "prevouts": ["19c62000000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "b6700e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ec", "final": true, "success": {"scriptSig": "", "witness": ["54d11a88f6ce79d225f0cdafeed5c39d788e16259d61c5275b50e80b3bfb5cfc0f07c172834590e622d40318935009275316a465729aa9a75fadd25c8412620903", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c62d4b9d44dbed0370531ed32f21bf252d426199ac66e81b743502f6d76b552a0decef315f1bf33a9d57e67d162139ca6c11ce525a33c23aa5c502e86c6132a3ec", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cea069b190b73ea7c41e48275d6d0841d7fdd8f3 b/txscript/data/taproot-ref/cea069b190b73ea7c41e48275d6d0841d7fdd8f3 new file mode 100644 index 0000000000..6e951eaad9 --- /dev/null +++ b/txscript/data/taproot-ref/cea069b190b73ea7c41e48275d6d0841d7fdd8f3 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708401000000a79891d28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46901000000540de0f504bd1452000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ace8010000", "prevouts": ["1a9a120000000000225120fc75765be35c7498e91185d3d44c5b81ace48e1fb56783e170e4fddd4a850715", "8ec7410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a8d43fd877bb06b6facd7893ec8875434e1fd6bce1c56381938fe22b4b8acec"]}, "failure": {"scriptSig": "", "witness": ["6a78616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/cec62d6028ecb0885e4adbb89b0c33222ed71d55 b/txscript/data/taproot-ref/cec62d6028ecb0885e4adbb89b0c33222ed71d55 new file mode 100644 index 0000000000..bee3b718e8 --- /dev/null +++ b/txscript/data/taproot-ref/cec62d6028ecb0885e4adbb89b0c33222ed71d55 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf03000000004470afcedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5e0100000089cf15fa0167036c000000000017a914719f78084af863e000acd618ba76df9797223689875024b63a", "prevouts": ["d3667100000000002251201dfb228dec79c6e234b1139c58dcf8de3e24a7459acbe9e029f267c6e1783b9a", "6789570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_2f", "final": true, "success": {"scriptSig": "", "witness": ["fbe428a73441a68af60203a55a4796d04d6f7b3d951051d223215aa7524135416a59285e20ba65f22407661e4b0e817881fa778153f27a9463868edf179b7ea002", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["dce78f8d62b7353eac36cc02e196f1e0fdbef7f47d6d25af99c7cd75252046cb8d358f809e8cebf26c5b550b8dd10259fe535a4d6492a829d3f2511a94400d6e2e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cedf97481d67a8a89199abfe8c15570cd253967d b/txscript/data/taproot-ref/cedf97481d67a8a89199abfe8c15570cd253967d new file mode 100644 index 0000000000..899aa2890b --- /dev/null +++ b/txscript/data/taproot-ref/cedf97481d67a8a89199abfe8c15570cd253967d @@ -0,0 +1 @@ +{"tx": "c500bd8803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6b010000005ed744c48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49501000000484908fc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43b01000000f2652ed601e58f2a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7f5010000", "prevouts": ["d29a240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d2823f0000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "17283b0000000000225120f103da370e61120ffbfed9be73547691440e55c4664603c27eb9ef615a7ccbdc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_cb", "final": true, "success": {"scriptSig": "", "witness": ["5e0ce5e8cd876b82df1fee58302adc4a3cce5803b7d0457172dec7e3f92827dc4e86ce27f3caf22b2e99c5bdfa1613a471da67739d4ea61c0554672aee7c256a03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["dd0861ee7b028ba56c85794d6d6df9ca3da7ead869c9b2f2e0dd7c7bc422489e54f0f5153e25ef95a8174efd803a357bf707f2f3d5c1257294e2ecbf98f6537ecb", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cef118940d5799540be8721e2453120639fbe14e b/txscript/data/taproot-ref/cef118940d5799540be8721e2453120639fbe14e new file mode 100644 index 0000000000..33722a7f2f --- /dev/null +++ b/txscript/data/taproot-ref/cef118940d5799540be8721e2453120639fbe14e @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706a010000003d8886bbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf770000000088db63dd03e1877e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478742010000", "prevouts": ["ee0f13000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "54426d000000000017a914f5a65ca4534ef3ca5833434c0dd44a3e128f499587"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "797d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936744fd1b2faf1c01ba2c17357d1ace23791aa902c4bf843c70bade4192b70605de711fb6ebac21c15598dc6feca0613664d86278cc532834585097123290bb3d45be39dc57762be2d9b1a04aa5b570805d23104bfe4fa54c392bda5d51f7f4540"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820b1051acd7c1b2d32995b3df0c6921af5f8ed3327e7e16cb8a5e0bd007230af127aec9530f4cf05d3554e63105b96634da39f3c52c35c251ce860693e97320b3"]}}, diff --git a/txscript/data/taproot-ref/cef395bb5063aba1aeaafde86a8bfd4c3ae80b8f b/txscript/data/taproot-ref/cef395bb5063aba1aeaafde86a8bfd4c3ae80b8f new file mode 100644 index 0000000000..101a562f63 --- /dev/null +++ b/txscript/data/taproot-ref/cef395bb5063aba1aeaafde86a8bfd4c3ae80b8f @@ -0,0 +1 @@ +{"tx": "c6803302028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48001000000509492ecdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba7000000001c4789db03c46952000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6caebe045", "prevouts": ["280f360000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65", "6f4c1f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ff", "final": true, "success": {"scriptSig": "", "witness": ["80cd77aa3a5a4d1be123e789c5879de71495ae44e99f4f3081f634dd016da10a6ad9d4183d48e68fdc1329648a49d9d16a3721394702132246e3268da339dcfa01"]}, "failure": {"scriptSig": "", "witness": ["a8a47a4d127e94dfa116aa6f85a91249b93c2c90aa812d931b967b2d478b78d99b047e56da681d5a4efb92aa309c553397823d9d8fee1f0fdfb32e16fb0caac0ff"]}}, diff --git a/txscript/data/taproot-ref/cf1726d92ba0a57e5cb508f7f38cf8c30c31572a b/txscript/data/taproot-ref/cf1726d92ba0a57e5cb508f7f38cf8c30c31572a new file mode 100644 index 0000000000..1434e6c6a4 --- /dev/null +++ b/txscript/data/taproot-ref/cf1726d92ba0a57e5cb508f7f38cf8c30c31572a @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b800000000041ad790c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42f01000000ab6dc361024f625900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac25af454e", "prevouts": ["dbfb260000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17", "a8f73300000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "7c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac26c11d7825777e0f2ddf610788c970bf175cde25cef7de4e72e41494d53bd31202adea3ba63b8efb220ed0b92cf765f01931ebb31f4963f663d14c15b1e6099a711983bc616996e2ac47b27808b31a9b7e87f7ce1f3571999dd3a2a57f1080"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d5fbcf61a2a7c737f60b9029794ca77d60e8dfd9dae9f2322432c03bed71ef108eae3f5bf5f4c26def68bde658fd1412dc2dfb494d39d6b1bd4ba6a274f177d9a711983bc616996e2ac47b27808b31a9b7e87f7ce1f3571999dd3a2a57f1080"]}}, diff --git a/txscript/data/taproot-ref/cf19361572439227ba12b4d90a84b45c9c77a6dd b/txscript/data/taproot-ref/cf19361572439227ba12b4d90a84b45c9c77a6dd new file mode 100644 index 0000000000..7fe05d20fe --- /dev/null +++ b/txscript/data/taproot-ref/cf19361572439227ba12b4d90a84b45c9c77a6dd @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3b0000000048f62767dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3600000000af19cd280474a0a200000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df9797223689873baeb45f", "prevouts": ["0bec7b000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "0f91280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b0", "final": true, "success": {"scriptSig": "", "witness": ["c7e23a2efb0698e1e188a96e58fa23ab5f3de24d0b4c52659dd65caee28d205b8a745781bb8e9aa4e1ad4c31660cd509c53aebdae36b6dea247baceb00afef7d01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["07f48bf2b7d960f2c678093938bc0f4159a8d0c214c961d4370b73333410e9771ad486d70ed4e2692b7af347a8934fa8b6733a90fdf5ffce20193ed60e7d5a25b0", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cf1b9fbc48a705e782d90e0caefa83731663957e b/txscript/data/taproot-ref/cf1b9fbc48a705e782d90e0caefa83731663957e new file mode 100644 index 0000000000..b12feb9261 --- /dev/null +++ b/txscript/data/taproot-ref/cf1b9fbc48a705e782d90e0caefa83731663957e @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709d00000000dd342c8a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127014000000002d192c0760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d00100000015c28620013a9a03000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a600000000", "prevouts": ["6c730f0000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83", "a76f0e0000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76", "ef970e0000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "e97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93661b2d540c156192df9dd49945f9f5192f7dda818524a6c961824475c653b1c861a6bebb6dd497db999161621b23fc9287dcbaa466f13da5d035327b94edd053dbd7d7e2e0b29bfb283546875adbaa200efb560b624d50a8165ce6ae8ed501592"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93603d885e7f20d9b45c46863644d45c7ae3e217370ab6fbcc5b4c9a947f89430a48b8d8a8d8c003fabb93595bfceed403f9a1266ee95e7fa8447cccdf398ce498db8321554bafe286e6661652cf416d3db0b455024b23404eea069d656c79e4f25"]}}, diff --git a/txscript/data/taproot-ref/cf3ddc0d11192bb67b1d1a9c46dba9cb99e1ab37 b/txscript/data/taproot-ref/cf3ddc0d11192bb67b1d1a9c46dba9cb99e1ab37 new file mode 100644 index 0000000000..dff67c8a70 --- /dev/null +++ b/txscript/data/taproot-ref/cf3ddc0d11192bb67b1d1a9c46dba9cb99e1ab37 @@ -0,0 +1 @@ +{"tx": "4817304a02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8b0100000004f694a9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7b01000000216ddf84044aeae6000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6fe1c4f2f", "prevouts": ["c95b7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d8d96e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_dd", "final": true, "success": {"scriptSig": "", "witness": ["1693a98377fa50d7dbb818dadf1792b7c1ad3a9cb0abe14df45247b12cfd987bd2f475502d3514ff2031b0fe233422feadf71d7adb6d6f4e6d99684e5a36ee7e02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["bd4d02fbdc6d4cca7c7ab7a18a93dc76587b1effe83bf61f523e109534dd4e18c4ed61fac327eab914a154a2c68d5dc3b1561b45057df520bc7e7a5398554b3fdd", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/cf87f1c7fe8d84db93cab39e5ec4fc004b0daf45 b/txscript/data/taproot-ref/cf87f1c7fe8d84db93cab39e5ec4fc004b0daf45 new file mode 100644 index 0000000000..ba44f20c43 --- /dev/null +++ b/txscript/data/taproot-ref/cf87f1c7fe8d84db93cab39e5ec4fc004b0daf45 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c68010000003c978ae7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6e01000000196033aa023d2f98000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac56020000", "prevouts": ["530253000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "25e24700000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "eb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936548e02ba2703ccddc552600e93f0a288f5116c529acb2e0434ef3486de3078ba3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821e09e6d24dde1e7a9afb38743b4c2dd55dbb58a3a1803a82bc7b3a42584fec8fa9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b965c838716597843dddd943276d0695a7197e96f70841ed980463eb99376fe31e09e6d24dde1e7a9afb38743b4c2dd55dbb58a3a1803a82bc7b3a42584fec8fa9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}}, diff --git a/txscript/data/taproot-ref/cf99a5aabda5c420d162ea57e1d44c83b4a5f444 b/txscript/data/taproot-ref/cf99a5aabda5c420d162ea57e1d44c83b4a5f444 new file mode 100644 index 0000000000..3756373750 --- /dev/null +++ b/txscript/data/taproot-ref/cf99a5aabda5c420d162ea57e1d44c83b4a5f444 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c64000000003cf989cedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8d01000000056889d804c0d86800000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac35030000", "prevouts": ["ec1e4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a78e1f000000000022512088381247371028bcbdc4971a16b3f7d8df868484be1d753506f5bf6782ea1e55"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_2b", "final": true, "success": {"scriptSig": "", "witness": ["63722b021a08548fa744e1c0a27362a8610e7dd1c30906c69a3b2816265784581a676077685bd665aec715a8abf2751334393bad43e0e4e9ddd3607487551c2a81"]}, "failure": {"scriptSig": "", "witness": ["7bb9e09f4b1e0d730c22de6690becf1e6d3a1f100064d17fad55857421d91f42962148b4c56127aacfa0c7f4df742e899e7fa7e1909e235c3f4a1b34e70273f52b"]}}, diff --git a/txscript/data/taproot-ref/d01804b3f650a230ba4caf6f35710074094ef4bc b/txscript/data/taproot-ref/d01804b3f650a230ba4caf6f35710074094ef4bc new file mode 100644 index 0000000000..da8df8b48b --- /dev/null +++ b/txscript/data/taproot-ref/d01804b3f650a230ba4caf6f35710074094ef4bc @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2800000000ffe4807d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705201000000dbb069df02474e31000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7bdf76d22", "prevouts": ["1acc2000000000002351212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "f970120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["42ee508d18775b48c94fd207b2626ef394875aa76ea60442ce21a9f0a0fd97bfd705eaf6f95c9eaa6ac9bd6caaf5b9dd6f001d593c2e73b9c5a614dddd582546"]}}, diff --git a/txscript/data/taproot-ref/d018c44a4a260f0faa1c368b22e6fd2da47b4279 b/txscript/data/taproot-ref/d018c44a4a260f0faa1c368b22e6fd2da47b4279 new file mode 100644 index 0000000000..40d03c4e21 --- /dev/null +++ b/txscript/data/taproot-ref/d018c44a4a260f0faa1c368b22e6fd2da47b4279 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3f01000000b8a74f8a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44f00000000e90788d160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702a01000000ca5a428f0116f30700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ace4010000", "prevouts": ["45214700000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "d6963e0000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5", "aee20e0000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09025f772e1437a5b0cc96ef0a34bd193568a916eb560a1c5dddef20463194398d4a14d16e0938cd4678c75f1bd5c1bf871936da2b6748c97bf7fc1fbff8fcdfab084ca628a9dff35f7224f3de1f7ba44a6a23daaaf545a4e77775718db7c6a82b29b43709b6a0b61403e815015f55384b9788cc634138766626c4ce0bce5dbe3da90c8417165766291c5877f3f1bf1fc9592b336e6e417c329942273fc005d0a2f83bda9a03b86966c91ba21108d1761a66a58734da36ac7e4d608a3bec7d3fc8bc1621814203c7cd0c95c9bf4e721d568e2e542e5b43e3825c03b564129bf270d9ed1cd8fc5f46a2e64edbbd92016de955383e9f1819476ce03e8141b08549536afdfecc08023f1d20a96fba281fa7c5bc1f31c161f5351a47e2db41e94e21cd0613b1bf91aaf8fefe2a16b73fc24dbe8080d3af20233a0adcebdc9497d02c5904e358694815d1d3524aa4e4452f3d13fd0f355d8ebc39374249ee7694fed0dbaef31ac6d73517586a4a28f68f8b206998d5137b22e8524e843c1108b6af1ec8af93b37ceebc645c7e671fe1476405d469151316c26dc1bf30f3b391f13c299e078ab260bf9c73c4d12e7884451119b44116164167438eaa4ac7562dccd9ac92ded2ebc0b85f069c3e5598e19e02713f05d7548c510209d9e4344fd110ae0660e299ecbb7d27ac950ace1af6aaad167514a6a6cc0a7fe3212b18746ec8e2c2c615cdd0c07515bccc42d475", "067d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e87f2e70a8b9232395faf03242e8d41e7097acd4f110215ae4f1c21e826dd60490c48ffafb7a4cf249a6909d8fbff6ddfd3f500331ce755bc2f73b79afc0800987"]}, "failure": {"scriptSig": "", "witness": ["4d09027708c97aa828833b11b783b5491081b1284c4f33ce5be3a35a4dc94744136fa2cd391e56c9a439e360a518c65cae46495d4574f86817dcd16bc3a3213f4c7d88e0ba8857d3b152f2b2e48fcccdada96afca309af0e78c23dec043b6f39f2b3f333f9f4675f15fa1f241e6a08975968b985b18415ddd5b73a092567ffb72cae99e975a8d0eb1d9ab9ec238cd331baaa2230f211e1ff898256b50e67890468947aaf693273b833c736f724fc73ad991bed14f06ab346440d6dcd960c5ca6949d874cf8a40b269479171fd4b7444400a48e10c420de484ffe9ca2739c7c2cbab0029885b837668531acc7ec9dbbdd28ae206dbd599e55c11e952c593b055a65c55ae9088f94248659c26265b8f68c00004b4d5cde70c38966d13e9cde87648d19a89df27909672c047ab5fdd42e482dd0315161fe54d7c0a8e7d330e7e17a69fecb4a1bba8df1ea1e4296c00c6099f8d8640357924af89a805814fd36512e59ce52d10350e67b62398dd708ae41f0e70ebcdb2c81dc72b69e5c5bc394709fbebc9c1b5fa58ddc3959c3ecde73e0ba690a2c6afc5aab47cd0c2138f8d1c4cd049bd2a239f3918265b30a6126920f8b142d3cc96a368b86e1782fc2d1f501837d2a16d0abf1e31ea47e605c5e6d4725a34bfe2b6d1420a10ca38bf362b3c3ecd34d40d5222a270842221d424682d0b6ea7c4b347543ccb2e0d383d32a9d6326bb81e0401e6ff36a84e16d2e75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936432946cb8c3cdde7216acad2d64eb2e5d48360b34b21542ce9dd46c17c6dddcb6ed3422fe95872366e2174646ef4116c9fafb56aaaad9ae25dbd472ec9cd0fc1c48ffafb7a4cf249a6909d8fbff6ddfd3f500331ce755bc2f73b79afc0800987"]}}, diff --git a/txscript/data/taproot-ref/d023d686290f14c19a40f74a18a2c183ac38c02f b/txscript/data/taproot-ref/d023d686290f14c19a40f74a18a2c183ac38c02f new file mode 100644 index 0000000000..4286736acf --- /dev/null +++ b/txscript/data/taproot-ref/d023d686290f14c19a40f74a18a2c183ac38c02f @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a4010000007ffa04c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b250100000082473360dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0b00000000b573fe37040fb04f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e790c8515b", "prevouts": ["d2ef120000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278", "8cf01f00000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "df861e0000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["da", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93647616881cc706df192d68bdb7ce4fefac112c6e83b2fc7e7a0b73ea4516ce84599aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb41dc38fa67d6e370c9f405c2af01822f370dc317d6e78d2f71aa14f0ce4de56d6ee4d75780d36bffae9b56136e6d27c02b8d233efdc800bb260bfbba6a6f94b87"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e116c8ab92abfbe4bc2686b5b42764123e12e1b7fae7b64d8b1bf7005c7df7fa0a3ad7647dae649c97c815eebecc244cfd5d14ac6da92e0e18049c71625e2af9496ad20bb4e3465af36c086d3f45ee510bb6828f8cbf764ea9958c57f38670043d"]}}, diff --git a/txscript/data/taproot-ref/d07029fee875ecd9778957b1eb1b6ed3ba90c94a b/txscript/data/taproot-ref/d07029fee875ecd9778957b1eb1b6ed3ba90c94a new file mode 100644 index 0000000000..6a78adcda9 --- /dev/null +++ b/txscript/data/taproot-ref/d07029fee875ecd9778957b1eb1b6ed3ba90c94a @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd401000000a64a7c9bdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2f00000000f9b73b8e0300959b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a695000000", "prevouts": ["8f217a00000000002251204bd530dd92500289ca536d9e0216beec7b39c81554ac6dd1e9e4cc3828e76161", "ed1f240000000000225120e9a13f65c3f3d085beb38984e1c9fb296d2b0d4cc9211abac3477617752bcef6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "fa7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93692144fa78a37f9d4158f2341b3f64ea9d93b698f8b61fb7d7e21bdfd4d5c0b363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ef1076b289256cd19daa60d704e81db3a39e457bb71d9d0e29c4cb2075820e5e1"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c5b5d638e62e1ee83083719c01950228b7d23e6528a32df7f751a90376aaaf3e9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ef1076b289256cd19daa60d704e81db3a39e457bb71d9d0e29c4cb2075820e5e1"]}}, diff --git a/txscript/data/taproot-ref/d076c78276e47d5f2551df88390966202a644ad4 b/txscript/data/taproot-ref/d076c78276e47d5f2551df88390966202a644ad4 new file mode 100644 index 0000000000..41b87948f0 --- /dev/null +++ b/txscript/data/taproot-ref/d076c78276e47d5f2551df88390966202a644ad4 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8300000000f7f2e8ffdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c620100000059b834bf029896b0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb18bbe4d", "prevouts": ["86e863000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696", "36094f00000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902452dd112dffa504dee00bb871d5fb4f4cdc70bb11249957e0e42b70388c4a35d888c1540f746007436556326f9f553b5e8fc84ccfeaae44d745d9111f51e6ca22c76388fe40c280094e2d50b8eb25b3d5d3f8a901851dddb1357ee99fbd5de701bffb10f097a8ea1e51916519b83ee492a5cb6dff803d7ea9f8817de5981ce0a6784288b95334560faab08243f18cfd85ae93f45ae21b664c7c3ef2107879ffe657f4ae9a4191b0ae3389d693b03b82b13b6fb2eade79e6fdc8b0620f27893d87606f39c26c0076f2e1ad5212e6b08f11e5dd5b7e14a135f93d0a3941ac2bf08b272c73146298e3cf6200bf885886acad5056a355aaf6a0fe27d668948112b32abf3dc83ea45b434aa9e66871668d0fbfdb641cccf5f34df7652fe634d33b674fa0a247d7637c467853e91cd41150a08ecc9aa8aac03cd223b4c9cc85c24b8fff7b7f77069a5ea7dc3450efd896b6cbfb3cd07764170fc30472b14126c987fa8b5fc53fa4bc5fb46cdb8cf7e32982bfb09c2c04ea3924799fcac32e5363b3fbf0eb85b291b1dcf2b0c7b31121af0b8f61ec158cbb5822dd1cd01195cd89ad9ab03ad276c165c0766f5a90241ec0e0cc152803a23389d7af769d970cb37cec53471d5ba61638c456d3eaa0f5b5454ce50e0b5af0c243810611e07968722358e65d5a0658d9609214e6d90bacb2e35981e52a2b1743fcaab7e7b276d85ceca8df6c40ce9b8508f882b8675", "ba7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936912fef94e10f79ce4c6c6612f6fe3346bd2414e9192a19778305ffcd15009acf20c3a872da93914874859cef7e5edec23fb149ebdaab98333cd5c691dfba4028fed5a24f2185242e3d6c1310740c566533f3942992fafe5f5be2785933680ed6"]}, "failure": {"scriptSig": "", "witness": ["4d0902d2208c9246ee7bc47f92cc9c50637293d565e48a057c7abf75635165c186271e4ea5aa83572f20d79ee4ae1669fff288bb7d2ecae5f7bce411fa9906cf9ab36ef8492e397cb36baca77b073614a90111b5b4fcb30bae5be7b0c165d1caa26fca436f608e507ee81e8dd4c003a5eefb33cd057f0ed28457e6de9e36699586b005e80c2712a8081ed204774657de77b11e2ba60b1d9c9b67a72b051088ec912507161f26b3ec7ecfe19cf4898eedc1cb356851099eb587874b83b6dbe44cc06c4004f1b27753d9e336e9f02535dd635f5e618663f2d8938af2ad8a564fe16ae9daea0b2521267c3f3da68e0759eadcd8bed2758f0905b6d41800fb3c2b3bf3d95b6219a9271804a8cfa1cbf23bdc5aabd4ff73c4b36d313162c832b72aa4ab30dd1eedc1811b7f9528b3698a42629c6ce46b57479090146564d6359f006b31bb11e0ca7c499c7366a4f0a872f283b3b5b95d9d05e3e2e8ed33dbce69d978a5f30e004e7452907fa67bcf0e3227569aa2a3f69378e147ae2419a3902be080524190239fbca5a6a5d4817fde99caa5671340db54fc90acac1a9eb412b48f83e53d7d521a24dd811767905674692294862f85517ea0c29e16b3e11ca44aac46380601d72fd45209082934ccce8a36f4b57a138ce36ba0d19807b9040ba897b8e3ea6604eba3abad5b4cc280b6c6f0452955ae9e9af5c8ad88e8dd0ca5b0f0e7caf9ecf51a5b9699fb66cc6175", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93691e172e3ff7e60f8bcc64ca363376b5038c5dffab23b3a4652792c10b41fac7b20c3a872da93914874859cef7e5edec23fb149ebdaab98333cd5c691dfba4028fed5a24f2185242e3d6c1310740c566533f3942992fafe5f5be2785933680ed6"]}}, diff --git a/txscript/data/taproot-ref/d0a5a7631c5914f69f44abe8d926e7ec265b3853 b/txscript/data/taproot-ref/d0a5a7631c5914f69f44abe8d926e7ec265b3853 new file mode 100644 index 0000000000..1aa2031843 --- /dev/null +++ b/txscript/data/taproot-ref/d0a5a7631c5914f69f44abe8d926e7ec265b3853 @@ -0,0 +1 @@ +{"tx": "4c754ce802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9700000000926720a3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c80010000001f7d298004572a9800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87b7128437", "prevouts": ["effc4c0000000000225120e181fd7d5a5189f175c5e112edc7401a8c528393c340dac4325961e6f48db1a9", "631e4d0000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "success": {"scriptSig": "", "witness": ["026ec354772fa246b3f0394a9e69110fd2c48311f27d0c83cf8b19d69fd72b9f68464473cc633b4bbcc97889ed4f974651cf2c418b211c75953a72324b8c9c3e01", "f344c8e4486ebdcd988b2c662b6fc4536264f7c1fcaa7f", "7523fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da5163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000bb98778e8b0119682a9e95c76c4762be2b7b0bf0af1ca73bc0d6917921d524ed593db1d8acb3dfc8a5301acf8994f458dd9d809af960217efae134cab2d25a5f3c460051f84ecccb8f94d91e8f35ff993881479ef3c2169078ea27fc1efd1879a83cc0faef5622f00b8684cf9aab916e899c621cfc98f9f8c2408069ee7742b8df1aaa521baa55c818edd5f58122a9dabab919dee88588727f15fe990b660ae80000000000000000000000000000000000000000000000000000000000000000938d5ff6e156e40e5c4bf0dde7f997191f0241386be244bc16425fbe8cdc6f0ef602ef92689002c6bf91fb285c22f83902557ab54b48323f842af71c4a5aca8bd17144d302f4672930a59a8fd6f3285880cd0ed72ae5907c677bb5bb848794afdcb2d5a71197cec237324ce49a219fb4b348d43177ffdd620782ec813b0b718dbb422a33ecb9c5fc1baa551d82e3cc524ac42ee5adff9057861b868ffe286ca8e287bceebc9035fdd129c920261484dadf8c85121151a621722a1712b23dff52ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc38abd44f49c2804a30c3ec31e3b0967d877e32532956cef050547e598b7b6c70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4b198453811f4c7a4bdd024a8af2c1627be36162779620096c812afd232c90833dce75b24e5e6d274d07e66a9a7da01e56ac0c23936774565897466c1386d3e602343ba7b60b2d0bfe9adf8187eee7f66fe6e07b90e1dd329b8842c2dd191ab003c4ad09d6bc9e246e261f33ceff387720f0fdecbc8059efd62d26726f9474efe1ad2a1021334296cbdfddc898cf292a71591ef70ae96753f9a2981208137b980042b88f0b1d9b2df68a486c1f31d1954350c1ad6dbc6aac04fee62bf9af05992176c77eb7f499dc36668a407834cfd7ac683b66ee2f492c30b665576b40cd3c7e7dc5f13bbc29aa99b7843fedde809b37a57e3f67fe64be4f701efe2c48a46eb4b083ef651d082e8e1a71eb72b6551e6fcdc8402db81e47be0db1fd619d7437d921c5102703ee65f7f0c9c8f3d8bc7e85120bbb075fddf0174c4891020cde023d9672046e2971470903d516190724adb48d739135139e61752564471a4998b5505afd0b845ccfeb86985325af1e27752d0b7eca51204bf535d2ef9d1a46a3d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff173ac20ed5a5381f618aeb45a84c2d2f87ed17c8468292a432dcfc6f552e8da6ec0ea6b531c8335f869772adaacd80c5eb252f3d9b814dcaad502c1f975db75afffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01feb7a289dea91399595dcedc43b350f0a98563ce843d6e8ba7cc624f22d7033c74c6fb62ef5d452fe8a5df2de783272e8355b57f1d01ee014414364d40d97", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["026ec354772fa246b3f0394a9e69110fd2c48311f27d0c83cf8b19d69fd72b9f68464473cc633b4bbcc97889ed4f974651cf2c418b211c75953a72324b8c9c3e01", "8d395c7053ebafc530ee7f3432c52796fe7bffb2c857", "7523fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da5163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000bb98778e8b0119682a9e95c76c4762be2b7b0bf0af1ca73bc0d6917921d524ed593db1d8acb3dfc8a5301acf8994f458dd9d809af960217efae134cab2d25a5f3c460051f84ecccb8f94d91e8f35ff993881479ef3c2169078ea27fc1efd1879a83cc0faef5622f00b8684cf9aab916e899c621cfc98f9f8c2408069ee7742b8df1aaa521baa55c818edd5f58122a9dabab919dee88588727f15fe990b660ae80000000000000000000000000000000000000000000000000000000000000000938d5ff6e156e40e5c4bf0dde7f997191f0241386be244bc16425fbe8cdc6f0ef602ef92689002c6bf91fb285c22f83902557ab54b48323f842af71c4a5aca8bd17144d302f4672930a59a8fd6f3285880cd0ed72ae5907c677bb5bb848794afdcb2d5a71197cec237324ce49a219fb4b348d43177ffdd620782ec813b0b718dbb422a33ecb9c5fc1baa551d82e3cc524ac42ee5adff9057861b868ffe286ca8e287bceebc9035fdd129c920261484dadf8c85121151a621722a1712b23dff52ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc38abd44f49c2804a30c3ec31e3b0967d877e32532956cef050547e598b7b6c70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4b198453811f4c7a4bdd024a8af2c1627be36162779620096c812afd232c90833dce75b24e5e6d274d07e66a9a7da01e56ac0c23936774565897466c1386d3e602343ba7b60b2d0bfe9adf8187eee7f66fe6e07b90e1dd329b8842c2dd191ab003c4ad09d6bc9e246e261f33ceff387720f0fdecbc8059efd62d26726f9474efe1ad2a1021334296cbdfddc898cf292a71591ef70ae96753f9a2981208137b980042b88f0b1d9b2df68a486c1f31d1954350c1ad6dbc6aac04fee62bf9af05992176c77eb7f499dc36668a407834cfd7ac683b66ee2f492c30b665576b40cd3c7e7dc5f13bbc29aa99b7843fedde809b37a57e3f67fe64be4f701efe2c48a46eb4b083ef651d082e8e1a71eb72b6551e6fcdc8402db81e47be0db1fd619d7437d921c5102703ee65f7f0c9c8f3d8bc7e85120bbb075fddf0174c4891020cde023d9672046e2971470903d516190724adb48d739135139e61752564471a4998b5505afd0b845ccfeb86985325af1e27752d0b7eca51204bf535d2ef9d1a46a3d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff173ac20ed5a5381f618aeb45a84c2d2f87ed17c8468292a432dcfc6f552e8da6ec0ea6b531c8335f869772adaacd80c5eb252f3d9b814dcaad502c1f975db75afffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01feb7a289dea91399595dcedc43b350f0a98563ce843d6e8ba7cc624f22d7033c74c6fb62ef5d452fe8a5df2de783272e8355b57f1d01ee014414364d40d97", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/d0b362a6e10e2e3ca3df573c3918408d11230109 b/txscript/data/taproot-ref/d0b362a6e10e2e3ca3df573c3918408d11230109 new file mode 100644 index 0000000000..d269574ca6 --- /dev/null +++ b/txscript/data/taproot-ref/d0b362a6e10e2e3ca3df573c3918408d11230109 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1901000000f2b706a8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb701000000d5414634042e88c0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c6010000", "prevouts": ["2f50740000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f", "994d4e000000000017a914a68ade9e67dbb5e8acf044461cfd5bd8dcf592c387"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8672094c3f08b9327f7ee48bb8899708766c48e78ef53e5ef370aaf6f5fa99ca1ce42d201fd753cc19d7433434234602e4af838ce265353441a761579b9ecb89c78d53ca9a9f93e78db88a883cc9c42dbf55ad09041fa37b21a93adcd191d7180"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facaceb5ed46230d7b49b5ab2b34a8a36729addbd68724e584e32fb6f2cc866bc08d213d90ee48874bbf2b18160b4fefa78452fd9fac91ad5f640de90a3ceda28c"]}}, diff --git a/txscript/data/taproot-ref/d0c14f7b59f5b7c5e2348a842c4f17589992edef b/txscript/data/taproot-ref/d0c14f7b59f5b7c5e2348a842c4f17589992edef new file mode 100644 index 0000000000..4884f83cc9 --- /dev/null +++ b/txscript/data/taproot-ref/d0c14f7b59f5b7c5e2348a842c4f17589992edef @@ -0,0 +1 @@ +{"tx": "bf72937702dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c91010000006ea375f4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd700000000a67e3fba04f02f8000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7afb7485f", "prevouts": ["158b5f000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "80a3220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51e96c6534a767436613e49f724d4ec24036cb4bdca8403821be2a67ec4c00c0e3731d32c4c28957ee8de75561afe63689e2428997edbca796d37c8feacf80dd0b4e0df2464f99a35d5bc9fbf69ae3045675e957332f77327dfd622124d00cb4df"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93663b062b9ef0e1745417b82292d0a45beaaab5fddfb801e218eae4d41ef530e1af41497843ee5deed9b1c1ba808c351924818107785eb2ec7667e528f438b571239c06a64e39d88ea3d05132fdd32c8e90a6b90ff74e726fde2d8f99de3a7b89959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}}, diff --git a/txscript/data/taproot-ref/d0d80b81785e11a47eb4778cde0392ceee57d442 b/txscript/data/taproot-ref/d0d80b81785e11a47eb4778cde0392ceee57d442 new file mode 100644 index 0000000000..cd07207af7 --- /dev/null +++ b/txscript/data/taproot-ref/d0d80b81785e11a47eb4778cde0392ceee57d442 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf101000000673c277b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4370100000035cb6dc58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45d0000000023dea660014dee30000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47879c010000", "prevouts": ["f5ff280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0bce3600000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "67f0410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_e7", "final": true, "success": {"scriptSig": "", "witness": ["b44a270191ddbba370b2df3c8772c2f3e42831dd5be0b90a5cbeb0cf8ce1a66083d7842fa44ab943f434d94ad5c1b0f653a1760d98d66dff6ac2956033d0c9aa01"]}, "failure": {"scriptSig": "", "witness": ["2b78efb142fce672572cd76fcc69165e2efc16527d8cf902c0c97f8ab89297d438729b24433e96bb183b5385ca9c72379393b5f55557b3a967fab001440e115de6"]}}, diff --git a/txscript/data/taproot-ref/d10cc817535fbf7ed3ccccfffd59542e31fd811c b/txscript/data/taproot-ref/d10cc817535fbf7ed3ccccfffd59542e31fd811c new file mode 100644 index 0000000000..315adbd66b --- /dev/null +++ b/txscript/data/taproot-ref/d10cc817535fbf7ed3ccccfffd59542e31fd811c @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4300000000d2837e2e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c484010000003ef0486f03696259000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8761727c27", "prevouts": ["e16b230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "43df37000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c0", "final": true, "success": {"scriptSig": "", "witness": ["41ee4a5bfdeedd772913161e78302877dfbc4cc9dbdc3a8afef12267a74efac53d11e4410662363c2716887073db7e0c39233f6d6585799112bec5039123de5082"]}, "failure": {"scriptSig": "", "witness": ["2bf82e8403f67bf0e2f3c6fdfa23374316b64b6262919ad503c27710c989f7f42365bb6371bea7157eaa8e62a7db79881a31a820cf97a3fc19f8b2377efe27a3c0"]}}, diff --git a/txscript/data/taproot-ref/d120192543d7524d72dbae6640c1fd01b655ba8b b/txscript/data/taproot-ref/d120192543d7524d72dbae6640c1fd01b655ba8b new file mode 100644 index 0000000000..3bab54a9da --- /dev/null +++ b/txscript/data/taproot-ref/d120192543d7524d72dbae6640c1fd01b655ba8b @@ -0,0 +1 @@ +{"tx": "02000000017cacf58c1885ec7a53b7658a58e4f1dee7e8d7a954fb736b3a502279c0be18ef0000000000823ec9e901aef6adca0d000000160014bf1a19526352877c6b170dd8786dc91b1610ae1cfadcf14c", "prevouts": ["87dd816c1100000022512034153a16ef8458ec2412ba42dd5be0fabd8b4c2f532d179dc958fc1fca3cae43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid_opsuccess", "success": {"scriptSig": "", "witness": ["8c62f256a1571e9f48b1901c6193c928ad34746ea514f6d6b11a2ef54c82ad150e244978614c20e9aa60a3270dd7fbdb230e6b28fe98190090fa42ca691bacf2", "20cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f3ac00635068", "c0cb0ba18c127bd01c824f94fd2578ac4109c167b40bd92fd4f8ede9600f7f41f370d37925ebbaa58968ca2d1c370a50dc7325130308285a7d9868d3ad5a34267b01c94ae67cd857f8f23543b618b38154b6c0432568bb8cf7638fb55d4cc0a24e"]}}, diff --git a/txscript/data/taproot-ref/d13e9dcbf612e2b605c913bf461a40c14c78981c b/txscript/data/taproot-ref/d13e9dcbf612e2b605c913bf461a40c14c78981c new file mode 100644 index 0000000000..933e2d3a97 --- /dev/null +++ b/txscript/data/taproot-ref/d13e9dcbf612e2b605c913bf461a40c14c78981c @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c26010000008481b789dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6a000000000539fbbf038fa4a4000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487c283824c", "prevouts": ["38d65900000000002251201902cefa81d0b0fe2050344a0485b195b36f31ece5900d0426a9de0fd01dcd1a", "f9154d00000000001600141cc39a492a6f67587324888ae674f2f534a7639e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100c97fc9e3a7076e04418abfac48194f9096d7796e2ef4e86c039e00e620c8d595022061eff5f893d2f720219fb5da7830f9c65710419d91339eb976a9a5e6e151226101", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "", "witness": ["3045022100d8e2f7a50c8e633ef64221d1574079a291550e12b0a1d7f8fa744c052d220b5d02207e6bc0a05d68076b1953f2f72c1302c329fb32f1d3c0e598475d77701758237201", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/d145e690ead8e8b91dcf655a058473fba40e05c4 b/txscript/data/taproot-ref/d145e690ead8e8b91dcf655a058473fba40e05c4 new file mode 100644 index 0000000000..31bb8d7968 --- /dev/null +++ b/txscript/data/taproot-ref/d145e690ead8e8b91dcf655a058473fba40e05c4 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc4010000002b6191afdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21020000009884a17cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1c000000007c4b09c60226af4401000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd3000000", "prevouts": ["c299750000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "05cc5a000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "080976000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6adb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936264742859895a6868f8bab4d4afceacc8909a577d10be3fb51e14ab1077baea299aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4ba0f4accdd80d494e1b95824e4feb55c95caee559d90e25fbf6396e2b6be61303dda2dfca806ccc9c3ad62846e64b9ac16121de5d926db5bebf2e82f8dec8d2a"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b7f6b7f6faf43deefc8dfb90058dbe61b727862c364ff314077bff4a6c878d2754e6d4b188f4ba3829c97f16419e7d7896d7c05fe6215d1417ce194d9971cb9e3dda2dfca806ccc9c3ad62846e64b9ac16121de5d926db5bebf2e82f8dec8d2a"]}}, diff --git a/txscript/data/taproot-ref/d1624ab2e4dceb28dc1e7d8f042d85271b474f44 b/txscript/data/taproot-ref/d1624ab2e4dceb28dc1e7d8f042d85271b474f44 new file mode 100644 index 0000000000..3668ba0fbc --- /dev/null +++ b/txscript/data/taproot-ref/d1624ab2e4dceb28dc1e7d8f042d85271b474f44 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc000000000567fd09760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e3000000006cc4beb260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703901000000fda958d3043a449000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf24a3044", "prevouts": ["c9366c00000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "2745130000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "d0db120000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063ee68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c5d177712b0cd548c59bcfc2592962097a3e59d4c97937b4438e3f3d5730f1a20f3b0db014ceaa26ae02ffb8f31853eb721e6357de034fb71f3898341a9ea5240028cdc19f89baf6c362287c7c7841c4536091540a9bd978c440258b5fe7844c439ca2b6d52d4fa79aee6ecbc14a8999a29f1c28c4c5c5b9dd610517c3b748ae"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93684766e391fce98464b6a114031f5ccc7f792c1ff341430b2176744987b7570923225856dd898bc2835af0cd8c351393955c132e627f28271e91b4e6043d8131340899fd8696dac9e3afc960f0a100b615a3c324ed3a125e98af98336f748ba56"]}}, diff --git a/txscript/data/taproot-ref/d17443611cb2c74ecfda516700477ecdd4ccd1e8 b/txscript/data/taproot-ref/d17443611cb2c74ecfda516700477ecdd4ccd1e8 new file mode 100644 index 0000000000..0d014720f7 --- /dev/null +++ b/txscript/data/taproot-ref/d17443611cb2c74ecfda516700477ecdd4ccd1e8 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8401000000120a51ffbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf340000000013508af90254e3d2000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4872f19bb23", "prevouts": ["9bc45e0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "17e67500000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09023b9d47925be78b5d388b6d784408664a9a561a65b01fc4f675086acda230728ee4e1beedf6dbec0fe40287000a79bd3e91d72c72517edae08d5af32f9b823f6ccfdc682a7dfed51d7034240e91b3530c12c97b3c8598e165cd1d27006b19a24d23e96b32bca1e69bcad2e94ce6e36eac7e974015b8cbe3686d3c4b926b006c4f084648aa3b9f38ac2eec4dec49fd0a995f79b9b7d184bcf74a10cd932c376997479c8a53fe82a486b91f8e022491cfb892ced4b0d33103d161c61c000223f557739496486d0c8a4b4b1f9b9a4131bc23fd23ab6225c1d1b565c01f6b9f8e9e93273ab21a28f6d1b3561d38660ad60091dcbd2ec29ceed09d536132110c788dae73eb76406b7ed0c247f209e123a9d77a6bbc2b578a88f7a8acd4050d97fe1e52d8af325742dda5f5ce67cb31c6df8fcdb84befac948909e22de9f1b6513398d297083da4e6ed503438f5cb8eb2a264d04677fc74dc747a5a746151575a4cba425995a16e2a66035900c69425242818f282de3abc501ac314672dc53aec77a8600de8be9a253a24cf48364f9a4b69e3eedd88693bf7a75ccba08b4d106e480937296916c499ce84ff0e7185de1f02e8647a280117b6033cb840ea024c40a3d4c72d45929af73c8dfc8fe7d8fbefbbdfbe69a7b2943a61009c81e5faac43cbd53a7e2b693ac260c61f9fd9498b01fbc467394969c26c8ffa54dc0d889c79332eefc2f32be05e172a458875", "327d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366fc0e1156245507405f9d89b0f31139d8ec5e61fa01242e57235d244728830438ce3cfcf38b656b5bd992972d83f897c8aa5da1de7c0e12ea4c0aa09cdb3dc1d2e4cd18b5d1ec472eec5a95c6c9d67ba3848eb933b0b41a8c6d3176a27b07997"]}, "failure": {"scriptSig": "", "witness": ["4d09026343d381cb50353a61f09f2a021fa74437ecd6d461707b3a97fd4ff005456a0c3e6b3e75642463046c65dbe4bd98623a64c1940da4b93b5d7732abee3259c9cf71425da9f43988c27f144a56d2a8a85c33f0d5dd07ffa309b6683517ee28ffd8facc3338a129d67272c3ea4c07710495d127a7862b304a3ff9e1f177d244d4ea409196268a67b07993a679bed84781f6f792219dd6bbdd7736f05a6b4934edcbd24877b1afc2fb112ca30bf9d1bb159dd48d4476b12e603b76be95bcebb17482faa65f35a4788fec267ca709bd3c517acaf88f1fadef18faad566c4f603d3e468620ab3f393b4356c79436b4dc0dbef92edc8d3991b99924d44c7339fa511dde3a3d94d036760fb533de78860bb33ff3dfa464f28eba733fb672ebf3be46a299a39b309803e48e721018587f8ba8121b6d38b2f1f5ebc749947c164e0e63bc32f8846c7591b6bdc6aa245a503f2cd0bb8578f158696d5a57aa785b7ba3c9c79565b8793b7a34d276742c88f2c2bb982889ac54bcb5648419001e4d7e38e1aa379ce88e59d8b6dd1ae05ebbdb0457f2fb0cc7d7125e766ceb8c407b004d4802f21ab6313f731906702b00a81c8ce40c41e7f8d418e9593cd6b8b8ff7f26ec66eb5716b4f452ea66c4582c4793eaf18b8f887ccce715143eedc4cd402ca9d3f3681d8203e648ea1784219ae9fd62db3d80a298ba5a7b91ee6f5a473d6781916463574f47a8ba9450ab0475", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e08902a07d3a610262cf0bf6826274beb2bca0848f03750f1d66d9fdb1ecc982925d31a4d328a06fbd663a9de03f4f743ae6731d946a7b64875ecbfa9fe5ecb492e4cd18b5d1ec472eec5a95c6c9d67ba3848eb933b0b41a8c6d3176a27b07997"]}}, diff --git a/txscript/data/taproot-ref/d17802655b5504bb0405ee7934ae6e14c9c2f6af b/txscript/data/taproot-ref/d17802655b5504bb0405ee7934ae6e14c9c2f6af new file mode 100644 index 0000000000..3711f62a91 --- /dev/null +++ b/txscript/data/taproot-ref/d17802655b5504bb0405ee7934ae6e14c9c2f6af @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7000000000a124ab458bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4260100000088e9d0d702bff683000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874b010000", "prevouts": ["493c4e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d06538000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_bb", "final": true, "success": {"scriptSig": "", "witness": ["2c1f8a6b8a3e1e65db41fb16c34dde8abbf9a07dcf9d1d2598d82f9a4b109d6c3026cf4de56c2c3c2fecc82acd80738cdb3d4277950cb6b5a53937f10f4a808281", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5dd4e6192911482efae6143db50952abbce491617e685dfb17f5fc8c5eb0a2dbe1f71c0cb031479f1b3e701db46fbffff3befba0b0ea9c0a5297333a1f778f98bb", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d17b2da02d1d622d7b71dade71d9adc392999c5b b/txscript/data/taproot-ref/d17b2da02d1d622d7b71dade71d9adc392999c5b new file mode 100644 index 0000000000..170ca7041f --- /dev/null +++ b/txscript/data/taproot-ref/d17b2da02d1d622d7b71dade71d9adc392999c5b @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46101000000b6d1aeac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707b000000000a17a0dc015a9020000000000017a914719f78084af863e000acd618ba76df9797223689878f020000", "prevouts": ["2a803200000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "dc95120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936428394a21751eb365095acdba6a51fe3b8c76f6f3fbac7b096ac1d441a9276a33f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bb0de8cab6875867027c85350e6845db37b89c1faa2a12b075d8db116249f7bd2367bb7d11bbe7d9666c447942212a409021a53e3151df7f84d090727acdc4c9"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a022e8e4f1240b3c3d4bb5c70f2b4ea702b5d8a670f036755e200b5950ffec075bb8659128f7d307893f477315172a6feef29cf3fc1fd27176c3d23e09b029752367bb7d11bbe7d9666c447942212a409021a53e3151df7f84d090727acdc4c9"]}}, diff --git a/txscript/data/taproot-ref/d17e92c55da82ddc95d75ddd15779fff2868ff46 b/txscript/data/taproot-ref/d17e92c55da82ddc95d75ddd15779fff2868ff46 new file mode 100644 index 0000000000..6bbfef6ce3 --- /dev/null +++ b/txscript/data/taproot-ref/d17e92c55da82ddc95d75ddd15779fff2868ff46 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e3010000008ec9c53704b6083a0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc49f1ff30", "prevouts": ["7cbd3b000000000022512000397e1d57464f1b51d5b2f938080db6c4e519ee29109bc6f6c1d6348cd27c4a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["5213d545740b1eee420152efd776896cbc83c605e7beca755e6ac4956f5c0e56da1967fd70074547a77d44379ae0cce2f3513f89456347155dfc985d416a50a301", "a2623e62430210b79dfd89e9ecde828b1022c4a38f949a279f089b5dc757123af75661db2ad675fdf7ec98dd8b8a91ff17849a0ce00d81cec63b9b69407330ad5bea44ac0c67b0573f3a36a4ccc4310678c420e3002fbf3767ce59020f35b136fc966ecaf6e5bfbd680595b7ce557e8fbbb66afaad440316415c9f040d0e09beddb0162209f6ccda6702a45cb9f84615695d23149759520f434a3a5b58bd7382", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936633863466ba87c1899c11f16db5b5be0b750ddadbb4e4dbf6166f79835a38c4430f887e27b668da7b3424a30decccb6d55871a4e29eee8a603d0c8f2f4fe43ed80bd6026482109028f84842e41827e2a19fb594fbebb92d759210479d260a45dfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbd76256e657933b8bb0a3ec931de5f3d544c0494761c33fc05af675339868669dee2fe44c250a9724efe4ef76ee53bd67b02e08dbd5226c6902177c0148ae73cfa900e42222759350e9b4c2dda999abc00ff6c2dea9524b5f9c6b9dbb7e67af10321050f369f8f4d86f2a13beef36eab6fb9986fa6476de7f6521b2f2571887ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff160f9c68214e30f2520000c0ef6d7596e0ce0d821c8b93328e13c5bba3fae013a57cb6f757a543ac0f10b44ab06156a457a3793e3736d517badbe684390a3930464395a806820194d875d016530f881a948b5b63d5aaa812ca6e6850da17e6510000000000000000000000000000000000000000000000000000000000000000d8c5a17c42d6966898a04caa8deabddc88d00d45a1e69c3fff5d96ab709f9fd63e4924cff277f09d336755660334144b1f08333d1bbff0b53bf0650f86ad4624db4987771bc4e0593314162db6515b1a797790cb487b94090c2574bb44a7bd4dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}, "failure": {"scriptSig": "", "witness": ["5213d545740b1eee420152efd776896cbc83c605e7beca755e6ac4956f5c0e56da1967fd70074547a77d44379ae0cce2f3513f89456347155dfc985d416a50a301", "418e0e04c63da5594a93360f940424baa87943afe2b6ac7da03514b687d0de15ddbc8867c4be25f77029eca788b1d7a203898a129f9ed4dcca1ca2abcadf8d3ac5968aa84f17357deecc1eacf872c13f8e69bc5d941cb60a3cd008c685c2968c3d19c6a85df215b7a02232e5c5d114c885238996d35033878b2b7b44e7139ad7982dd28f89ff4e516e66f6ad133f236d7ee84f06c410a7b5dffdfa387284b5", "75005a20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5a8820871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936633863466ba87c1899c11f16db5b5be0b750ddadbb4e4dbf6166f79835a38c4430f887e27b668da7b3424a30decccb6d55871a4e29eee8a603d0c8f2f4fe43ed80bd6026482109028f84842e41827e2a19fb594fbebb92d759210479d260a45dfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbd76256e657933b8bb0a3ec931de5f3d544c0494761c33fc05af675339868669dee2fe44c250a9724efe4ef76ee53bd67b02e08dbd5226c6902177c0148ae73cfa900e42222759350e9b4c2dda999abc00ff6c2dea9524b5f9c6b9dbb7e67af10321050f369f8f4d86f2a13beef36eab6fb9986fa6476de7f6521b2f2571887ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff160f9c68214e30f2520000c0ef6d7596e0ce0d821c8b93328e13c5bba3fae013a57cb6f757a543ac0f10b44ab06156a457a3793e3736d517badbe684390a3930464395a806820194d875d016530f881a948b5b63d5aaa812ca6e6850da17e6510000000000000000000000000000000000000000000000000000000000000000d8c5a17c42d6966898a04caa8deabddc88d00d45a1e69c3fff5d96ab709f9fd63e4924cff277f09d336755660334144b1f08333d1bbff0b53bf0650f86ad4624db4987771bc4e0593314162db6515b1a797790cb487b94090c2574bb44a7bd4dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}}, diff --git a/txscript/data/taproot-ref/d209841a9bb6b9ed3a4954465f454a0d304ef888 b/txscript/data/taproot-ref/d209841a9bb6b9ed3a4954465f454a0d304ef888 new file mode 100644 index 0000000000..a7cfef78da --- /dev/null +++ b/txscript/data/taproot-ref/d209841a9bb6b9ed3a4954465f454a0d304ef888 @@ -0,0 +1 @@ +{"tx": "08a01054018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ba0100000063b897c10365303500000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac2f010000", "prevouts": ["6afa360000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_ee", "final": true, "success": {"scriptSig": "", "witness": ["b9954da706c9e42b2a7899115a48000cce3cbff5e669fcae880e0e4b6fd2e90bbfa8d904376cf7275e35885247b8df3aa48d5b57ae307d1de4b97ed53de879b303", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["9cc79cf95e40dc85c56510090eb746bffe18417404c5389872f466671721f53b43918c0b407b15c789c2190ce650362040bc4386019549c32a58a4e9246b3436ee", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d263cabcd95f3dae465820283cf9b428e89c02f6 b/txscript/data/taproot-ref/d263cabcd95f3dae465820283cf9b428e89c02f6 new file mode 100644 index 0000000000..e32a9d0c3b --- /dev/null +++ b/txscript/data/taproot-ref/d263cabcd95f3dae465820283cf9b428e89c02f6 @@ -0,0 +1 @@ +{"tx": "bc407aaf03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6600000000004780dadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9500000000b762a584bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfec00000000c46558bd01b5e525000000000017a914719f78084af863e000acd618ba76df97972236898718b7f726", "prevouts": ["d3706e00000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738", "a20f210000000000225120a30b9ec0293a7d9469ba59688876e580c43929cab6dae613a98b7270f0f04b32", "60e3700000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6acd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363699f0be280803bd87ec3489190568883decb4ffe607bdc225a59725135347c6fe052270a8089f5fc5ef9a63e8f4df43751c17d276a547e2cd275b71d0b6242a8fd238d2decf6f7142c55252dfef824eea080278838d8f4f1f0f617cfe47b5d91029910a453e765cd82c29c3b576a90579a453f3a941b6b6175fa922e9a13196"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367a22d20941183d012c749b02b1f998abfcaf580dc1273b137a622627b312eac248aa6a6dbcb4c7060082480e3e536b464146150e8b2e96d2b5eabf2aaf1fe24e9f4d7ab890a2001a7be6cb25cf630fcd24657943ff80a7c5a11988ecbf9e80e4620a19fd562e5ef578d66d29c84f34a4223ab3b995d34ad300c7b5f252d5e140"]}}, diff --git a/txscript/data/taproot-ref/d27d3711e16baa8c89ff9c90b6ed0622ca86ff8e b/txscript/data/taproot-ref/d27d3711e16baa8c89ff9c90b6ed0622ca86ff8e new file mode 100644 index 0000000000..e9b3f4e6f5 --- /dev/null +++ b/txscript/data/taproot-ref/d27d3711e16baa8c89ff9c90b6ed0622ca86ff8e @@ -0,0 +1 @@ +{"tx": "4b61cf630260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270550000000048887186bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1902000000afa4fda102cbb3790000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8728747447", "prevouts": ["5c850e000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838", "74946d0000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "c77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93684f69dbeafcf17cb0c1d0b541de5da243f0fb8e40c7c35b0ae2476c51c78eca8bb71aa1af8b43c653f5bd4a49a6dd2a2c220faf9f7ee0d38ca763740363240a33f5a7735bc8e0f27305ca0f6b127eb0c71998afa21cfa1408dfc03edc17ac2e42ff4035580f6aad3e4d48161cfa55cd77c0146622bf63e71def681bc3cbf8a6f"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93685fb25bfb3e9aa8dc2d3ba5503ee0e44a578ca0e52ee091cacf7c1e498936ff2100dfdf5c7f83af5d4cdded17045999c289d0f075ba6add5c0ed7b0f5c1761ac2ff4035580f6aad3e4d48161cfa55cd77c0146622bf63e71def681bc3cbf8a6f"]}}, diff --git a/txscript/data/taproot-ref/d2957d9af2c85119d0e66bf643c7eb85bda86170 b/txscript/data/taproot-ref/d2957d9af2c85119d0e66bf643c7eb85bda86170 new file mode 100644 index 0000000000..ce4b20d932 --- /dev/null +++ b/txscript/data/taproot-ref/d2957d9af2c85119d0e66bf643c7eb85bda86170 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b05020000000688d329dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8400000000b676ae7f03dd933f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688accc010000", "prevouts": ["1e2c230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7edc1e000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3045022100b9c272fca46b4e4417948f9f19e148d97fbf4ece274bcbff643234569df5b9be02200f7f72f031c6899a6c004a2a49d00349521df6b8263ae8621167c081249e524882", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["3044022026a718eaeab5c1c8b610484db1b3cb9e2269f6a29e620537b6b9f926e56ede9c0220419bce0d78f032a025bd26b4a5edd1c3edf560e114416c3891423296b6f4966382", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/d2c7c0da2861f14114f11766107a7b8aa6efd73b b/txscript/data/taproot-ref/d2c7c0da2861f14114f11766107a7b8aa6efd73b new file mode 100644 index 0000000000..7536410af2 --- /dev/null +++ b/txscript/data/taproot-ref/d2c7c0da2861f14114f11766107a7b8aa6efd73b @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4000000000968b3edf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270df000000007d2befdf02b2673400000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac65020000", "prevouts": ["6a47240000000000225120363e143e65a8c3ceb9072edb61818663e66ab42c4302b81f45dac8c3551b5de2", "27c911000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/checksigadd3args", "final": true, "success": {"scriptSig": "", "witness": ["34d7b6834c098f4c242e042d63d01ab0de2affe9b53a453a926bc43cc83955893c3fdff5a67a92f7b66c5c637277bc502b0c7005f40e28ce0a33af11b1ad2d39", "5420871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a034685013eb12d0936a5af43ae0e5638d7148ca8da311dd51cf2e290b05ed820ba5102bbf7fbeec60e292aba2a12d06acbee3d1ff3068be768a5f8ab1c15c8b5f95428243b01e6b613d868e39a3cd6f8053f3b8a58a5b42db19ed132d0fdc37ab205f68d8ec55f68ec14e7908e46173699cdebd091fbaa00eafb7815b9069cba262853dbe467a837dbe26fc7f3ad7cd7a62e462e47b7e1bb60054913e91ba6c655d89a1acb7a851de7428c381ead1ba6d1d417e8b953e51f7c670e3863576c3b88611529e8d8ac178c50676d0c91193955b6fb062740847f08c84da5efc29fd5abdcdd61aefa92e26b138e07522d025d19d1fad7762f9c1f70685829a115613fda528b23fc9436db397402f0e7a3d49cf7a01c31cfb831fc26b2262ab8efbabef6fb95525f08c0ad7b451d163f6e35eb4e415957ac629ef0511fe91c7e5e389d906758caa877012f69cc4f32b8c78b5f62c54ebb03c94d75afc9f0e4835f9336f422423aeb19ed8c37b62b0dd1dc6be563591d9481677ce9900692950fc288a25dd19e02d4685ba017b89767b5c8376f6b66370e3202d9e807c9c5b06b99c098acfa6a9da80a755a207eb5a3ad02b1a2cff248af93ddec122a727b43b9e8dbb8b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["0075b04346e84b6bd32caf3b67b01a56918618682945ab139fe7a9442af0edca2e09652e3e4bca2a4ea235496f3e09ee13e0b38f67da65c7db6074fe5af923d0", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936116f7ad79cd980a022e493d4988dcb1c1b19360c243df8a6c0950ab23ab0c7b69a452cd9073b5f6ffa9e0ccac843a0ce980eb49f1486d2b77bb32b8a94ab6aac66d00f82bb5f2502b956f0c84a51f0e2d02681cc066da536434475c27d851b6d641b0074fcb2e108dc7caa0b55e06c8df3afe81a3ff46ed53f36d13d5f23b7704b55a70bf5793074dc8fcb95a01ffd76c6a7cb3d0a8a0bc039bbffc30b1ced991ce4b1fed6b43d58d9dac2cb7509c7d861499d5ac1d29ab5263dacec4e0c0a847572e6d828a5c45198364cb694bf803dc07555e2d22b7e9f02e8aa8fbca1012f863039c28015c411e675d5dda0e14b5c56378d6deb77e15828d0e89e693b67172ac39977b8d69cebf8dbbf0b021643d19f979fbcf2541dbe46954e2cee6fd107d88c1a48e272320e36e966c5f51d20981d7c2f219d616fffd90e68676bcf4376036134e534d46faa7f08f82a13af8ce2b56a651461eadb4a959e6ccc1a170149ce30f8ef3cfdfb2c400e7b66e7423c5c736cf055f99edd585361b210bdce8bf4614881305c12cbcb98ccd23333e30795e428d971b7425c40394bfc0ee466f4cb7363486d1e033637af9f6d28292a4f4527a2090bfcb5efca2ed9c0d63c01e16c98b35f150399876b232678a58bf83578dbb2c055ad176d56177c4ac303846e798f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/d2d896106278d4a3d97f13f67d9366baca387121 b/txscript/data/taproot-ref/d2d896106278d4a3d97f13f67d9366baca387121 new file mode 100644 index 0000000000..5d5c1bbeb3 --- /dev/null +++ b/txscript/data/taproot-ref/d2d896106278d4a3d97f13f67d9366baca387121 @@ -0,0 +1 @@ +{"tx": "e9ce9d250160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bb00000000783c3be90224b51000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478741963b5a", "prevouts": ["100a130000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09025fd87d13604b549f5c5d9101e72f91f565f9a4b09089125f17363e8d39781061a1116a7fa26a5e15153b1b04ec5c325ef1144c798d89deb6ac7146600bc8b3a85474b15a8ba9cd7bcc3a3b0f2a5b6baae3db82f029ec24b529b591db166e3a6ddacd36d3a9bfccc8cf7a7ec0013435c3be190971d30b9ef4dbbe4b78abe79e199eecbd8c64649806d99b6c767eb5302d37713de0fbd93dda07026bcd56247146764b3614dd6e04eb5dbf3f6285186046e2d7e5a86a6c94411e67f4da968d5509ce548a8cb7469271a6423add5d835ee96f11a716aca74568a0e78e6997c438df1f646128e37b76cb4e02c3ee32c6850fbec1229a0fa54ccd282d2308ed54f76b44a3c6796d137dd7cdc318f409d2b83ae0ab2b239629f84856878b201b635b3ec49b01b8fa5c3fc41da299665d628ec7e2cc9b6ae0f568f231f74bd21bd043567cee9cf15ca2a1cd2f1539ac690afbeda819e56a8b751d793a5bc3a9bebe4ede4f35e642b7ed3cf4bc4eb420e9647b3ba84280a06f00dc9e508933d5198a64ac5a0ebf1b86dbe640757e126da7db9544b2b80995daee939d796167e737aace5841e8df4b35b2c8408bf167e59b3b0a49f7ff9be3ccac313436821296cf9572d44d6c87c954fb27c311f58ba75675bdda4e75b45bc11cca69215d0e267868cfce674deeb027a58dc129a57f641db3261c65c3f4cdb948dff72eb2aaeeb0413841d86e0f50dbbca8f53d75", "be7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936076f7a3cf0e2f36f4ca53be6e04d67b19856e69fdea7bebc7bb759d42c5b4076ba72dfb389a6a0bb3f8b3aa7842bba2225719f72a11deb6eb959f4e6afb1e08b911ebac8c921821ba74d98d656401ec4b56b2bfe8f672693a939227457b8b1a2"]}, "failure": {"scriptSig": "", "witness": ["4d0902d82542d2bb36816386406662a46b8b4d97949063bc4ceacd26c34c5b8b1837fee1742f54c38246db4103a3e69c48fbd67a097c91e71cf214c8a958f785a2edb60f26760bd059ff28aacd16bd665011c6ffeee89cf4ccb7bfc8417be7af78c45d77c27d953091cbdd2d9a4c74474cb9979253d8f6aeb6be4f557c74192e43ec4c2e2e10f04edbe9932cfad63a92402f70acc37a066b14e74cf3c3c909c2ecac416eaa938ab350de7f863cda2153efbd95a02a558d771bba9bc7af5ab28144648f2691a5cbbe5b2c9d2a7d43059c7f2ad6e3b75eb88598c3aa1fe32471205bd2aae7046c9336c88ee3c2cbb8eeeed9f445ba27de310466b552515afa0bb7f60eea5d75a671effe37f936052ca2730046b743f5fc00e06b38595545abab6f3cc13fd20a35b8a1276e81ec872ad459840f4a036c661650add69184e4b41dd0b5d2323d43beffe9a6f2d98d38c038c32ae46e39bd52d37113c175eb6e6cff8e7d4316338e9075f0793898cda3b190f21c2a930dae6e1d5263f1139334c1560d3c28c6c1220a311e848fe1a1a9a30b587294ca044e9c31ff190a077700c0242a468894206cc3dedf52f4af1bce4a1b99ab06e849e83e33744693e039038b3c0fae8f17f83516bcd5251f68ac124fec1c98ed5f2b5b7105f03c37bd00b97ffb210897f14b0fd4c1b6cbbd115b23a3a899803fc693864a0bdc91bf2e61d1f73ba0c3e3523498d722039635fc6375", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08271092566d000aee18de877d7d37a6499dcaa40717b87fb42c4af8a156e9c8751ba72dfb389a6a0bb3f8b3aa7842bba2225719f72a11deb6eb959f4e6afb1e08b911ebac8c921821ba74d98d656401ec4b56b2bfe8f672693a939227457b8b1a2"]}}, diff --git a/txscript/data/taproot-ref/d2e69860ee1527c081669b81f428a0dee46fe218 b/txscript/data/taproot-ref/d2e69860ee1527c081669b81f428a0dee46fe218 new file mode 100644 index 0000000000..f7e76f97a5 --- /dev/null +++ b/txscript/data/taproot-ref/d2e69860ee1527c081669b81f428a0dee46fe218 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49801000000f2d4614a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270130200000074abd946dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9f0000000045a6249304c5089b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acf499373c", "prevouts": ["31f4380000000000225120d7db2432b77440d39106fdcd5c35c463320f36611b8bc46e3633cb3a8d85086a", "83da110000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4", "30d0520000000000225120c3b9d8e50d42de1212377aa9427da72fe17222669efe5204fac1f05c34f6e65b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["c9814340c116ee7a7f1ec50a6e887138bece1466a8f41b531064e8332a1b7eb83262695b117324e414bff4b434764265606301afacf357ede632c3d610b42b85", "89d7bfc245dfa9a9e22885e14845f5c61e01147e5d2217537dd9fe2b405f17cc5585c6d1f45769381467a48d16b1a2bc8be8fc6e5ce47929367641c50b4c226556d9d79c6f5079c66f6456c7df6315388a740190b0c8537b49d746385ca4", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff298fa6498c8be80449c6afc36a9cc6fbe03f2bf753868bcdfd83742d3f15e0c78d10ea3c6f32d3a6f5838ab7302c54d32f4d174b42eebba04b42b036c92456890527c3afa4f32981023115cf41b6bd705d39dfaa189bb389c418f62feb842b8cc812709ee7ec7ce0efa87592725391608778851ec3ba1962d921196d266f2de200000000000000000000000000000000000000000000000000000000000000000f157c370629feb737ef2d30ba1dd35638c064eeda02da7f75f5160bffe3a87885d19d121f62414db00d181c72f2eb14c4eecfe1d60a440773723e87999b842bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec9cf93515a02f9b2b7efe37b1d95837e2a6ef926c49d6f6da29afa7c6cb7232e1bdf3c701a78946e2954b0acb3565b29caef7efc21248964af19ce1c4d361ec00000000000000000000000000000000000000000000000000000000000000000403628f9a3214ba76f7ef16cb06c5730ba697c8b0b763e179bc63ef34bb00050000000000000000000000000000000000000000000000000000000000000000a98a3e02ec5c0c5634b41ee3c3e12c23b713de0f661fcd232dee20dc213f1c3c0000000000000000000000000000000000000000000000000000000000000000d22369a4a09867a7725a7fb28324a06e1d01e65d400a8c67157a6db05b604a00301aa6f569e79a305215df3d29e3dcd907743777a19b753d73122be5d2387b72ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e0c7f641133840dae1ac14bd0005337334ddea87f27f48a1a73f30b4a190b43a16435e8a68a20ecf9f776cdf03f22d8b245bf1e045ed1b153062efecb4166676c916655d6688c405368c97e413d12ca8f4c621d110670e0cba4c1c017a52f035f513c5c5890afc6f149bbe95ca4db7f498ef1918b89c0abdf5f33481de97d453400db9d0d8645730bd82fc2b50d2881aaf279d99f7de05deb676cddff1820a2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc346c320acc0e0a3397584a01f82e2d8b27ca017e661ab69cc6792ed7b0328adf883c62321a29743b652800c3d6c6791d82cdc9b8810e1a18e9f1f1042d2877ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16b7dc80f5921406159df5defe0d72ecc44b773d77e09cb2859d2f9cb9701a6c68103fb0c769caf135c1041cf452b40eeaed935c292b8642849d51680a3d5da2b151231b57f161fbcdded96bb19227c9a168c951c9d8ff89771d09647a09dad8b8f34d578ec5b4dab6a07ebe896e9c00f79aab289798ba5cf949bc26586bc7cecdb7cda6956865a5539e65b8f6c2ff2854ec44fe30cd77bd6b500b49188f30d50adbd6b8bb983d8484e9adec7bd3490fe0a83e625dd274a43a5effcfd26785d077644848458d41c9088e67e5eda0391198151639dc2bb89033e5d7375ea32a12fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbaba57575c43d523ff1138ef79198743692cf46496fe391288dd5ee75b8bbeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff564437900748348ebb33b2141c46774d364f2642eeea45a22e17a69ab1c35b7285d326bf8ddc71daab5f6bcdff7bc3207438351c0c4ea6d72e9f6a92732eaee57f2be15320d7dc462a9c195ca432ba61c23fda813b43253af753706f7d7f421668321843ef4d117a70e2f6f9c82cbecd61e3b09ce71b8f9c91c1c65e04dae9c0000000000000000000000000000000000000000000000000000000000000000031f33a3ba38a75fb98685b2bab94900d57c5ba843ed48c6510c3557b457c895e5fe8437ecdc202a00d480305acc32f32ea33bbb45d5cec5a20a722af35c6383b68c1188cb53955707ad5c2cbd687adb516430d30104722f2fa7ee1e58eba23a1132ac42795db81764eb54e0ba89db26c4f7dc85995964eb7d34cd624d98fa28855575ff006a8ac1b79c8925c19b0d920095744a2ed424deb3d3c84fe40774df4d2e14d7ddbe521c9411b37ba2f7438e22e5bce675d39fe94adfaa822b288528702d551bf1cdedddf37a8f88589810f91287f46eaf71d3155ea2fa4bea56dd23e3e1ec526d9e362c63c8511aa14b0b80814241468949de13c84e3dc031850ddcfe79eb89b1b8dfcebbf0e95ec19c70303c24dbd25b29f40deb9c1466fa1d968310000000000000000000000000000000000000000000000000000000000000000f06c45097ffb9b0f0ac114866ead353710f365a1c34e4bbf5c5a49d92577842ba753662187493b9caaabaaf7ca62d9165ac99ed503ffdd4b2d1f61a32b62ea00000000000000000000000000000000000000000000000000000000000000000034ec41e24a59341f115c1f82e4318ba25c658659a0f2258877842e0a77c02b99f5e6ab50d1e18c76a468d91f9cbbda8b24aec6cfb92c8943cd92dd1fc26692bf0000000000000000000000000000000000000000000000000000000000000000b1c68d20df5780a4929d0629c473803180840620aea50c6f5a6032c090836f0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41840fff3ff3e0967cc8bc2e015d06a2e5f56c8c7f9a1673dd2be5613606a19471e771d09add9e25b9b1616175eb39b4098ff55d4b86b8627e49830c45d95e5c8319eae0b2c67007be01e106fd73d306846630337f044c2408e3050c634053d0f482c95044859735b3c75ac45e635c9b06c902d57c84acc435d84f14038029246dfc1add60c42d3b0e497eecfac072a2fbfb8626315529579c09ffd4ef0fe0e35bc43f562d1208350a37d67c85b982feeae7ec97ccc93519a76088580f77aa7ae0548edd7cfa287127c98df94033cbe1d5c7f63a6f18b29f9c19861f22e9a4e1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ea178be4be471ae4a0787f12a8483ed9a06b70778628ac1fba28501b3ab4caa2fb77a22b17ec8547bc2d4fa20e20467a237f9782b1659c485323a2b6f9856de1c63f3235be4f3278746d4c077615e52c67ba876f90f9b46e2f2a5bbb3d0fea4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f520de29503220f2e1803e858c15d5d9aaee9e77bd7328cbe7dd63298d1627d1e6db73c583bdcc0c7f328ba6497a4c1647a9a117d0b43ddb5ce4308807f2d6408c736a5b6db6df33e3de82b73a78a57ba411a18ae82aa5799316810d3273aa40570e58785eea61730be1d591c5e8ceee63ef656242aca204f4ef9bb699b3937d18bdccb58ddf0e508d619d9c6ce2fc94b5827eed2621412bf4eefa8b1f26cb2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff022185ec5c7891d09ca9999d2e0fc762a3e71d5c64dfa7c30c1e54a255bf45c200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cbd47697217c8c1b98010dfa381a791d456fe8790fdc0e177cb1b4fbdfb7387cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000768e0f41cbd8a853b4805769796a87f4c4faeda97513f0caaba6c549728f6484ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000119bd68aaeb576bce488adaa8410e2ae59180392711ba2ac13139d45505251cc38b76fbdfbd6748dfa5c00a880b28217e36f27d6ccc778b5cb43c2c7317b175648edb43e5fb127e41d19b073776e31125b383bd3daddc1d2af79753972ef68ee0a1f9abee5076aa5c4724795dfe5a75f2d0a3eaf86c8f1616326beb4cca4f08d21ca90171326f786f261094c4f7910cc728820bf54221d88314d847d978e23f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3439629d821490a79bccb222959a1a577fa4547fa3ed3860a35e55c08efae940ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0576521287f781dd7f45553f66fd3db3438fe16683af2a074d1b5b2e232c8c17aba1a17cc646e289a38552e4c38deea7f06fde9605879717a168fbd1750ecf9d99c6ae61b8126fcbd58d936074304c316229f0bccb99e2d00f20c86d238956f1b5d7f83fa79e0e67f9d2246f0742f8d617f9a01c5ab434e253e6f5d706046709"]}, "failure": {"scriptSig": "", "witness": ["c9814340c116ee7a7f1ec50a6e887138bece1466a8f41b531064e8332a1b7eb83262695b117324e414bff4b434764265606301afacf357ede632c3d610b42b85", "f40a1e242cce6925d9bbc80e8048354d578177047d6fab4e1fa146cf3ce53fb1968ecbaf9b24b1e6b4c243ba14ddf000be368c2f8500658934796293a26a0d6bd1b6d7df8214e14187d82644e5e05f10f1873f13a8516b97b99435bbe1", "750020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac916920871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e206eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff298fa6498c8be80449c6afc36a9cc6fbe03f2bf753868bcdfd83742d3f15e0c78d10ea3c6f32d3a6f5838ab7302c54d32f4d174b42eebba04b42b036c92456890527c3afa4f32981023115cf41b6bd705d39dfaa189bb389c418f62feb842b8cc812709ee7ec7ce0efa87592725391608778851ec3ba1962d921196d266f2de200000000000000000000000000000000000000000000000000000000000000000f157c370629feb737ef2d30ba1dd35638c064eeda02da7f75f5160bffe3a87885d19d121f62414db00d181c72f2eb14c4eecfe1d60a440773723e87999b842bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec9cf93515a02f9b2b7efe37b1d95837e2a6ef926c49d6f6da29afa7c6cb7232e1bdf3c701a78946e2954b0acb3565b29caef7efc21248964af19ce1c4d361ec00000000000000000000000000000000000000000000000000000000000000000403628f9a3214ba76f7ef16cb06c5730ba697c8b0b763e179bc63ef34bb00050000000000000000000000000000000000000000000000000000000000000000a98a3e02ec5c0c5634b41ee3c3e12c23b713de0f661fcd232dee20dc213f1c3c0000000000000000000000000000000000000000000000000000000000000000d22369a4a09867a7725a7fb28324a06e1d01e65d400a8c67157a6db05b604a00301aa6f569e79a305215df3d29e3dcd907743777a19b753d73122be5d2387b72ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e0c7f641133840dae1ac14bd0005337334ddea87f27f48a1a73f30b4a190b43a16435e8a68a20ecf9f776cdf03f22d8b245bf1e045ed1b153062efecb4166676c916655d6688c405368c97e413d12ca8f4c621d110670e0cba4c1c017a52f035f513c5c5890afc6f149bbe95ca4db7f498ef1918b89c0abdf5f33481de97d453400db9d0d8645730bd82fc2b50d2881aaf279d99f7de05deb676cddff1820a2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc346c320acc0e0a3397584a01f82e2d8b27ca017e661ab69cc6792ed7b0328adf883c62321a29743b652800c3d6c6791d82cdc9b8810e1a18e9f1f1042d2877ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16b7dc80f5921406159df5defe0d72ecc44b773d77e09cb2859d2f9cb9701a6c68103fb0c769caf135c1041cf452b40eeaed935c292b8642849d51680a3d5da2b151231b57f161fbcdded96bb19227c9a168c951c9d8ff89771d09647a09dad8b8f34d578ec5b4dab6a07ebe896e9c00f79aab289798ba5cf949bc26586bc7cecdb7cda6956865a5539e65b8f6c2ff2854ec44fe30cd77bd6b500b49188f30d50adbd6b8bb983d8484e9adec7bd3490fe0a83e625dd274a43a5effcfd26785d077644848458d41c9088e67e5eda0391198151639dc2bb89033e5d7375ea32a12fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdbaba57575c43d523ff1138ef79198743692cf46496fe391288dd5ee75b8bbeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff564437900748348ebb33b2141c46774d364f2642eeea45a22e17a69ab1c35b7285d326bf8ddc71daab5f6bcdff7bc3207438351c0c4ea6d72e9f6a92732eaee57f2be15320d7dc462a9c195ca432ba61c23fda813b43253af753706f7d7f421668321843ef4d117a70e2f6f9c82cbecd61e3b09ce71b8f9c91c1c65e04dae9c0000000000000000000000000000000000000000000000000000000000000000031f33a3ba38a75fb98685b2bab94900d57c5ba843ed48c6510c3557b457c895e5fe8437ecdc202a00d480305acc32f32ea33bbb45d5cec5a20a722af35c6383b68c1188cb53955707ad5c2cbd687adb516430d30104722f2fa7ee1e58eba23a1132ac42795db81764eb54e0ba89db26c4f7dc85995964eb7d34cd624d98fa28855575ff006a8ac1b79c8925c19b0d920095744a2ed424deb3d3c84fe40774df4d2e14d7ddbe521c9411b37ba2f7438e22e5bce675d39fe94adfaa822b288528702d551bf1cdedddf37a8f88589810f91287f46eaf71d3155ea2fa4bea56dd23e3e1ec526d9e362c63c8511aa14b0b80814241468949de13c84e3dc031850ddcfe79eb89b1b8dfcebbf0e95ec19c70303c24dbd25b29f40deb9c1466fa1d968310000000000000000000000000000000000000000000000000000000000000000f06c45097ffb9b0f0ac114866ead353710f365a1c34e4bbf5c5a49d92577842ba753662187493b9caaabaaf7ca62d9165ac99ed503ffdd4b2d1f61a32b62ea00000000000000000000000000000000000000000000000000000000000000000034ec41e24a59341f115c1f82e4318ba25c658659a0f2258877842e0a77c02b99f5e6ab50d1e18c76a468d91f9cbbda8b24aec6cfb92c8943cd92dd1fc26692bf0000000000000000000000000000000000000000000000000000000000000000b1c68d20df5780a4929d0629c473803180840620aea50c6f5a6032c090836f0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41840fff3ff3e0967cc8bc2e015d06a2e5f56c8c7f9a1673dd2be5613606a19471e771d09add9e25b9b1616175eb39b4098ff55d4b86b8627e49830c45d95e5c8319eae0b2c67007be01e106fd73d306846630337f044c2408e3050c634053d0f482c95044859735b3c75ac45e635c9b06c902d57c84acc435d84f14038029246dfc1add60c42d3b0e497eecfac072a2fbfb8626315529579c09ffd4ef0fe0e35bc43f562d1208350a37d67c85b982feeae7ec97ccc93519a76088580f77aa7ae0548edd7cfa287127c98df94033cbe1d5c7f63a6f18b29f9c19861f22e9a4e1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ea178be4be471ae4a0787f12a8483ed9a06b70778628ac1fba28501b3ab4caa2fb77a22b17ec8547bc2d4fa20e20467a237f9782b1659c485323a2b6f9856de1c63f3235be4f3278746d4c077615e52c67ba876f90f9b46e2f2a5bbb3d0fea4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0f520de29503220f2e1803e858c15d5d9aaee9e77bd7328cbe7dd63298d1627d1e6db73c583bdcc0c7f328ba6497a4c1647a9a117d0b43ddb5ce4308807f2d6408c736a5b6db6df33e3de82b73a78a57ba411a18ae82aa5799316810d3273aa40570e58785eea61730be1d591c5e8ceee63ef656242aca204f4ef9bb699b3937d18bdccb58ddf0e508d619d9c6ce2fc94b5827eed2621412bf4eefa8b1f26cb2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff022185ec5c7891d09ca9999d2e0fc762a3e71d5c64dfa7c30c1e54a255bf45c200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cbd47697217c8c1b98010dfa381a791d456fe8790fdc0e177cb1b4fbdfb7387cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000768e0f41cbd8a853b4805769796a87f4c4faeda97513f0caaba6c549728f6484ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000119bd68aaeb576bce488adaa8410e2ae59180392711ba2ac13139d45505251cc38b76fbdfbd6748dfa5c00a880b28217e36f27d6ccc778b5cb43c2c7317b175648edb43e5fb127e41d19b073776e31125b383bd3daddc1d2af79753972ef68ee0a1f9abee5076aa5c4724795dfe5a75f2d0a3eaf86c8f1616326beb4cca4f08d21ca90171326f786f261094c4f7910cc728820bf54221d88314d847d978e23f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff3439629d821490a79bccb222959a1a577fa4547fa3ed3860a35e55c08efae940ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0576521287f781dd7f45553f66fd3db3438fe16683af2a074d1b5b2e232c8c17aba1a17cc646e289a38552e4c38deea7f06fde9605879717a168fbd1750ecf9d99c6ae61b8126fcbd58d936074304c316229f0bccb99e2d00f20c86d238956f1b5d7f83fa79e0e67f9d2246f0742f8d617f9a01c5ab434e253e6f5d706046709"]}}, diff --git a/txscript/data/taproot-ref/d2f56cc722b3fc0ac3792e7c09a53592a22039af b/txscript/data/taproot-ref/d2f56cc722b3fc0ac3792e7c09a53592a22039af new file mode 100644 index 0000000000..135ebe6f85 --- /dev/null +++ b/txscript/data/taproot-ref/d2f56cc722b3fc0ac3792e7c09a53592a22039af @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1601000000ce4364e8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe400000000a9dbb2eb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46000000000b49550d804b90201010000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc60416b55", "prevouts": ["b6636600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "becd650000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029", "4eaa370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "287d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93676df232e5f5dbd05da99b40a2d8bb3049d7c61774161e08ff9e9412064d827f55b4ae3ee914d52223472aa57f653ca8073aef0e7910b2553778e1ae03228475361bc10490c3b13d9c4f63caefcea4aba06d3a92ca8668ebd56c703a638058ee7"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936487012bffc3542e5de07889edd53e2df3ecd4fff064617ebba77d1f64b07458d780a528759e22c32b672b3582ec3b98210a6d7cdb045b8c2f36dc39043db702a61bc10490c3b13d9c4f63caefcea4aba06d3a92ca8668ebd56c703a638058ee7"]}}, diff --git a/txscript/data/taproot-ref/d2f8f204891c46f5ba28af13b77da60a054ed30f b/txscript/data/taproot-ref/d2f8f204891c46f5ba28af13b77da60a054ed30f new file mode 100644 index 0000000000..5111921a66 --- /dev/null +++ b/txscript/data/taproot-ref/d2f8f204891c46f5ba28af13b77da60a054ed30f @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700501000000f60e8805bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe501000000e6fd15b5017fe3180000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc6f000000", "prevouts": ["0eef110000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "673f660000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "367d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682baaeffa6f4cca00281777f85149243151f0b330252f89793101ed1e71b4558293ebb87675db407435945ccb2e2a6a79ad6cc0b8e2f03768d51396c4a1768b6d4d2cf0b4a04f3dfea651ef6d0b2c4d5fffa0a14be5e227661027bf8174dd263cddd84017ed719a58f336e1892f80afe07727626533c4c78318e44c39862ffd3"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93678acd166f5af146663a37ec796b256aac405c63a52b6185b9a05d94fb3f895c89a25034f4670dba2bfd8b532fe5e2c4399b1757245b955e89574c41111a3f13a78448a7537869648343bbbdc00eb4ac0785a5f2aec0111e81b0d25ebde82a92a"]}}, diff --git a/txscript/data/taproot-ref/d33cb0c2e7c01d420f375159f3d266e71d9c3bcf b/txscript/data/taproot-ref/d33cb0c2e7c01d420f375159f3d266e71d9c3bcf new file mode 100644 index 0000000000..cc98e0c477 --- /dev/null +++ b/txscript/data/taproot-ref/d33cb0c2e7c01d420f375159f3d266e71d9c3bcf @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be200000000ee786e5160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bd000000003fc93dccbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5c00000000b8e3e08703aa61a2000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a678fb6231", "prevouts": ["1b322300000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "217511000000000017a9141a56e0fb41afaf4b9e6feff1797087c69015162687", "f93a700000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "225e202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["755a1b2196fc9c98ce064f8d5237f4299cf20054ab4b74433647e559cd0c73c7b05c9f639d371958d478df28de23c020a099ec8c9bd52e67e377df64c336a43c"]}}, diff --git a/txscript/data/taproot-ref/d34c8b66d9e51e1f51b9432c19d0d95ce51aa297 b/txscript/data/taproot-ref/d34c8b66d9e51e1f51b9432c19d0d95ce51aa297 new file mode 100644 index 0000000000..29d8b0bb07 --- /dev/null +++ b/txscript/data/taproot-ref/d34c8b66d9e51e1f51b9432c19d0d95ce51aa297 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3b000000009f43309c02d7c155000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acce000000", "prevouts": ["cecc5700000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "b47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367e7b268f617d00298f513ed9d959e4853656836f4da5bc24b22bcfc49034b4c690a6d927376acace3683bbc4ff9f5d15a4c9ee2ad4271a1fb38c29668c3ce61898ae4fb28ba039f9030001532aa52d54afebb8b1d186c7283d6707334cdf0cf3"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8f8e322f728f7f2bda8f14cbbb71f9286e41438f49abc55856c1a694b654384417e736a60655dc533a38837433a3a305c9a2d5b0314030c91796018120c3e9a44"]}}, diff --git a/txscript/data/taproot-ref/d35d96943b798f0362dee33b1c9dd9f5ce520bf7 b/txscript/data/taproot-ref/d35d96943b798f0362dee33b1c9dd9f5ce520bf7 new file mode 100644 index 0000000000..012b9b5c25 --- /dev/null +++ b/txscript/data/taproot-ref/d35d96943b798f0362dee33b1c9dd9f5ce520bf7 @@ -0,0 +1 @@ +{"tx": "2cc56a15038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49a00000000ec9501e6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7b0000000043261ee960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e100000000823f43cc013ca96b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487b5010000", "prevouts": ["c1243f0000000000225120036cd49b0a5a8928de04f8e04bd3da02711fbb4d9053aeba12a20cf11cba05b5", "bb6f4700000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "cd9e10000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["bb4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936023cf8e98f7450905a417c9ac38276f00b59951e06c79e90063ed7e2000f468fba5ae8cba4ed1cb91f8a2ddbe7d0c8637ea6f49c0896515a628c3bea1aa465996ff84cb0de1f41d907799f0bb3a3d4c37b57eea0ba754203aaf5b7b2671fe888a4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}, "failure": {"scriptSig": "", "witness": ["4c52bb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d513f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d0e13bd92b8f417e9a9e83db8f63381783cc5b261abc3d56b5d515d800102f0ba4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}}, diff --git a/txscript/data/taproot-ref/d386337a1d0705a7cc519dc2e044e51c1831c3f8 b/txscript/data/taproot-ref/d386337a1d0705a7cc519dc2e044e51c1831c3f8 new file mode 100644 index 0000000000..22524d07e7 --- /dev/null +++ b/txscript/data/taproot-ref/d386337a1d0705a7cc519dc2e044e51c1831c3f8 @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40402000000237d988701de051b0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e760030000", "prevouts": ["fa9142000000000022512077ac2a27a93614a377debb8ffed5c2ae54185f2c1c8dd8a23e6a2ab719a18bb4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f14c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360c9deb8d7324d76c36ab4f0759c9a5c2cbf4147d65f4b6b168ab1ae532394b7618ea1dd842879684de6ce36adf7429742f60d84d7359dfb2eae76d7b546c72259feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dddc2da628ad214b987c122c871fd025273e900a2be892363e6938be42c4976bbb0b9e3baaec320f7de46eda77f4fdd2cda08039a1867e75a703bfdee0f4ff6d1cafc3da456d473afb79353f7068dc1822b24dbf9d7eaef6a0c8c9b611b05e979feb3ebfb72e1f3a9e601929fc7eea4d0eaba4c5291f01c808279d3454a78ee1"]}}, diff --git a/txscript/data/taproot-ref/d3918bf85a56fd7561082f401a5ebd4a0d642f87 b/txscript/data/taproot-ref/d3918bf85a56fd7561082f401a5ebd4a0d642f87 new file mode 100644 index 0000000000..8060e1c864 --- /dev/null +++ b/txscript/data/taproot-ref/d3918bf85a56fd7561082f401a5ebd4a0d642f87 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3e01000000cfab0487bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6c000000006aa54fd6047c69d500000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc797000000", "prevouts": ["a7a25a0000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "970b7d00000000002251203792436bc7394fc8cacb2bd2cdac9c86871063933d86113811cf92ac8fb26226"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "", "witness": ["3045022100874bdd6a54f7eecc10b3f521b6b54e8e8134fbfcd1cb0244af35dcd6f1cf732002207142edf17de35f94e887a1b036a1e51fb330ca7c615c9a631cdd757c5983df4331", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["30440220445d2691f1bfa7e9b0a01ee23c2ca35cd3ac20a513713f2c3a51d8302b156d550220276e86b3b5305e923b840e592f750473aea52a88dafc8bbbedbb0177beb60f7f31", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/d3abb997507d97ede96a2ca419dd8554e22db558 b/txscript/data/taproot-ref/d3abb997507d97ede96a2ca419dd8554e22db558 new file mode 100644 index 0000000000..2c39bcf012 --- /dev/null +++ b/txscript/data/taproot-ref/d3abb997507d97ede96a2ca419dd8554e22db558 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b930100000044a29d078bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40600000000ce8be267bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffd000000004601938b033b82dc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33000000", "prevouts": ["0ba127000000000017a914e014b0ed75ce4306970c9f63e88b08a5a7bb4d0f87", "44813e0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "691a790000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_7a", "final": true, "success": {"scriptSig": "", "witness": ["86dbadf3e40b21343798c676aef44eebedf45a74500ea8d1fcbfeb9286d15b65b93e769bf19d3a5f0fcd437299d33ca1965375f35daacee8ffc72dec3a354a4e03"]}, "failure": {"scriptSig": "", "witness": ["59029869f5fdd96afc76b79c39335738d11ac3ad9b10962d9914c5114cb5a70272a9c248e2027abc2223d7f9f60fb80e2db357ccc02d410a4da700d05db083a57a"]}}, diff --git a/txscript/data/taproot-ref/d3ad578f5f3076aa52c4e35e8a0002582433fef9 b/txscript/data/taproot-ref/d3ad578f5f3076aa52c4e35e8a0002582433fef9 new file mode 100644 index 0000000000..7a0a186e3a --- /dev/null +++ b/txscript/data/taproot-ref/d3ad578f5f3076aa52c4e35e8a0002582433fef9 @@ -0,0 +1 @@ +{"tx": "8346c76302bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfec0100000049bf40cebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd201000000179187ab04897dd9000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7961d3c802a", "prevouts": ["952770000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "18786b0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5125e7936dacf44c2cc5542287b329619dfaa06ef235a847d66c9c2df863225da6d11737bfd86c40bc108767f37b7ad1553e96cd0852cc5d3aae7d4d5919ea2951"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c5794b22775b9246017f02a30576904e360f7f30d7ba69e42da1f949da49f647a6a38b8d39a057b5d03cc3fb1c5a8fc6fbbf2afa69d215fd7d0ba06cabd825c0959bd9b34bb85690c892593228383c48f2c7a3855b4947a3dd1708d13c567655d4436d921361743dde8d98d3cfa724f09037452104a82644e108bdf9bf6fbb39"]}}, diff --git a/txscript/data/taproot-ref/d3ae88e79c1801c2da2ca48244ec5455bb3abe76 b/txscript/data/taproot-ref/d3ae88e79c1801c2da2ca48244ec5455bb3abe76 new file mode 100644 index 0000000000..394e303e6d --- /dev/null +++ b/txscript/data/taproot-ref/d3ae88e79c1801c2da2ca48244ec5455bb3abe76 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127047000000008b866bc6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c94010000009b039ae9048b395c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8740000000", "prevouts": ["aed50f00000000002251204f95e2d0ca6e5ead217b338fd8f5ed161ed18d9deb82c1fc7cc39fccfd04e4d9", "414e4f000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000eb", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1135140675f37d3c6ffc244808cf22673ce324d5ba1e34c99f7d0972c5ac012a46873018117c319506164013bcdec2d285df0b840d64f5a35ebdb06eb3e2afdaba9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936863bd85e5c9e012d214e27cb7267ffbbead239b623635de7a566ce4333f17723135140675f37d3c6ffc244808cf22673ce324d5ba1e34c99f7d0972c5ac012a46873018117c319506164013bcdec2d285df0b840d64f5a35ebdb06eb3e2afdaba9431f387a803f7df77af21560d586d92c96180a56916d6b7efaaea6f10ba4ca"]}}, diff --git a/txscript/data/taproot-ref/d3d3e2a151a062b9f319dd5ba2d382d38c8c95d4 b/txscript/data/taproot-ref/d3d3e2a151a062b9f319dd5ba2d382d38c8c95d4 new file mode 100644 index 0000000000..28a638d469 --- /dev/null +++ b/txscript/data/taproot-ref/d3d3e2a151a062b9f319dd5ba2d382d38c8c95d4 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706600000000263fbb6adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1a00000000cebe71a7030bb62e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d5afd460", "prevouts": ["9659110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bd0c1f00000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_3d", "final": true, "success": {"scriptSig": "", "witness": ["691ab130c457e109ed5ac51ed10f812a9def72df45dd4cddaa769e1b77962f1eb6482c848efb32b473a27a3cdbe10b12291f65448ad793146652d83c464ebb3b83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["060bf7550f4b508dd272f5b422b20197e949ad8ba93243e176c2e2fc1280a5482479d97a4a1a7205321c25e75dfceacda3881ad016cfe75edb6218ea8c3fad043d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d3e5ffbc18b1ff4b1db6426ef3962f8c9cf5cdf0 b/txscript/data/taproot-ref/d3e5ffbc18b1ff4b1db6426ef3962f8c9cf5cdf0 new file mode 100644 index 0000000000..830d8adb70 --- /dev/null +++ b/txscript/data/taproot-ref/d3e5ffbc18b1ff4b1db6426ef3962f8c9cf5cdf0 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8700000000f0211ceebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5d000000001eb9ae8703257e82000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac66000000", "prevouts": ["c04021000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "9df262000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090210639343de065849c855ae8c35c35d79666934225ad4176929280fd7d98de7d372da64f016d53ac645ec6eb2bb75041ab3ec31c104cc4d99203ffdf062685ed6047cd592a11d2e622fafdc2dd6a77c0d1d4f4849cd64f7cd456c33496b0ed86274bc23fffc29d5bc5eb3bb4d491cce1b737152dfc7d88ba95efed373bcd5325e7288266e179365ccc3ad401afb7089ab0d2f9ec4f562a45a5a308bb7f2ce3288f12d1408a727e16a6a0629768b45aea534dcc09fc52a4b3a9e0bb25a0291c71f1968e5b539192d61e09fd93d40bb37144fd393a25e12538bf836a8a8d79f36d5e4b273368aff7a486ec0543fd1ddc52884ed8d3441606a690fe1ce7ccbba7604ce66294c27250667d04077a534ffe15e47ddae3d32dfc45a9f7ba1a75ec88e1cb45ebc8738fe4049e47642fd85194ee3aa6a713c090fea5a54fb883bdf5b87b13474066eda7cf7cdf4fdd5199c2bced7cb779014b30a523729d5c0e9d8343527454e865fd0ac63c8f364c80a4e34eedf8084cd345faa202fe3dfa706987e561fa8df2e85f8198897e55afe5d24edd4f6361b0bfa88b0fc7fe65006f39007d5b0d4cf0c13c736a9aef097e2f052bb26b4b760539274e8787ad5d50b7e16d76e700aeb721c72b0801e40cb8d77a2c41404351be65c9b3a32d39faa18ab39633ddac0f28a12ea956276a91c87b87df1f8182f8835d355a9c7984d327b17cd603dc9edb98b9aa13cacc7bd75f0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2f0292c5c10d160f8e0745cc9e7b1222beed517475d04a852f0f3c02abb361f19b5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}, "failure": {"scriptSig": "", "witness": ["4d0902cc289225ce3c228894dbc80760454c1aeb27ad26e34631ef9e5f5006fe1e9fea33a4b4e5814879a1a0a060b229b12b1b9688b5c2c3744a22c22cadbeeb24ca29aa1670e923050051c67fbd806989a2a0b7dc39906531482a883ee4f58b606ea15194ad3d6b9d716a0f9b17c2cd54d8af1ffc51838f5c8b0145ffd143cd960b52152d0601eeea04418de957e6a3c1b2590b0584393a603abea7311af32bb9bf624fc452c2bb45dd66c507642dbc2362fb9b3f621bb724818ad55725f8b05b775f44cb93520607a349d1fdc5f83325346b253c636c8e1f1efb76d3dd395c2f37811729de74581eac32afb07e8addd6c73738582ac425b011e1bde8526d3b354a6aaf81a428fd9f1e67dd5136f77a766f86aebd11ad1b56dcc6991a2a22ac08fd225eccd44e58feff6f1a6bb536558784130054fb6ab8f8a4e49bde6fd30ebff43c103c6a2b16cc9c375f212fbfcf87cf5dcc9558236290610ce5f8f1722c3696c00c5069ea9e970f8c10fe4562a7ca3f63e2e78870ae04e27af40b0675c9eceb4b663b24e46678f6c269838a0847d58a1cdf102166f91519f04b378d09373302cfab575e5aced5f0b0b121edd74d5867d603abb1d81ed95cbcd31c19928711b394e4eae0208d75108a37f6604fef20f3f258d6f3ec0997ac7ffc6a64125fb8a9ba290ff89d34996c78dfa5bd93a1af4e00f01362ffd90eaf1a7c28d31784811282bc710e4e059497ac297561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93683df6dc1d6178033e3954d6b2c194a6e795ec7ec27bf3469af38305b38a5a5488e2168769c1e98187b117731eccdce651c542044ebcbbccf53ba5dcae5773e361c2a3c32f2d98482ccc0ae7bd6919d8eb72134d3589ab943a0402c8a931ea420419704ddfd13dc63b1b4156372563d65f148a89e112fdd9cbf47f8afee5da0a9"]}}, diff --git a/txscript/data/taproot-ref/d411fdd25ef73e64648572aee57803f358cf4bb2 b/txscript/data/taproot-ref/d411fdd25ef73e64648572aee57803f358cf4bb2 new file mode 100644 index 0000000000..7d206ea865 --- /dev/null +++ b/txscript/data/taproot-ref/d411fdd25ef73e64648572aee57803f358cf4bb2 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be0000000005fe3e49860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702500000000186ba9b004a336300000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7962a2a795b", "prevouts": ["614222000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87", "3766100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_46", "final": true, "success": {"scriptSig": "", "witness": ["6fc0b4ac26fa3c0981daf6fa30ebba83cf50713a53d9dbcd77ce663c555eebef82090c1b56db0ff1eb33c794c88ed3f4260ef4fd53cbab5d1f2da3206a3de3bb01"]}, "failure": {"scriptSig": "", "witness": ["ff3ab9773206ffebd944eb847f3c56694d96b1a40b4c2a57349a3619cd1b7aae3e274c6bee07372a37f39750bc5112fae080a6a7edf4ec4407374a6b83d214ad46"]}}, diff --git a/txscript/data/taproot-ref/d4208a5824d1318820b3784412f424db595f35ae b/txscript/data/taproot-ref/d4208a5824d1318820b3784412f424db595f35ae new file mode 100644 index 0000000000..f0f73f2b72 --- /dev/null +++ b/txscript/data/taproot-ref/d4208a5824d1318820b3784412f424db595f35ae @@ -0,0 +1 @@ +{"tx": "ea9513f50360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e500000000325a22e960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127099010000008f727e8160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b0010000007ad921c20200f131000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e789000000", "prevouts": ["e680120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "519e10000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "67ba1000000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "807d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffc1f73e1ef7cb741aed576361a28c4d25cbb42ec9d623905630c989b808b3539bb3dc44e72947935649b33aa2d807ea07560e0c2333a7ee2c40c2820b24a64a090cbfbdc5dfcad7ff4463f3cf2898b3c754f5d70a369d7bdece79053e0da647"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0826d3ed6bb397f900bca42f5c55206e9e9a5556fe68666fe0d64ebb28af9dc03c732beddb8df376ed0f15f8ca557ca4fa4dab9ea34398a6bb2b3d4cd5dda00bcea090cbfbdc5dfcad7ff4463f3cf2898b3c754f5d70a369d7bdece79053e0da647"]}}, diff --git a/txscript/data/taproot-ref/d42eec126dd7b1e4c2c574ddba68f4d0228c3d09 b/txscript/data/taproot-ref/d42eec126dd7b1e4c2c574ddba68f4d0228c3d09 new file mode 100644 index 0000000000..9713048806 --- /dev/null +++ b/txscript/data/taproot-ref/d42eec126dd7b1e4c2c574ddba68f4d0228c3d09 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bec00000000078c47fcbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd5010000001a65b428042cf0a00000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478710020000", "prevouts": ["f72520000000000022512084127e09a3e5abb8e6ea0ba3ce4737d1c2349f1be422ff5ce1609ab9b3fbb01d", "497283000000000017a914269f407e1403e9e55237bbaed7146c0fbc0fe6c987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "225a202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["0d7022bf110305446ee518fb05f21aa2c432c46510d8a42becdc0afd12f93f2cfb5f82bfd89a4fe0b1ef89cc4b055d78fb203e3916e76b238691a99fa328e0c3", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/d48d445fdf8825eb982e112320fe51da22271d30 b/txscript/data/taproot-ref/d48d445fdf8825eb982e112320fe51da22271d30 new file mode 100644 index 0000000000..350cfed3cf --- /dev/null +++ b/txscript/data/taproot-ref/d48d445fdf8825eb982e112320fe51da22271d30 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700d020000005955ac21bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1301000000b41584b4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b35000000009f42a30602486899000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c5b9435a", "prevouts": ["ac30110000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "f49e6700000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "7202230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "4c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef724f53fccbc5998418268712ec4a55c070b8ba5ae4e04e2685482dbecadeb1c847bb38ebdfc0ac99f7b57f94cb3711bd799e3f024c53d691ca5d12dd06ff53bd30287fa60720c35e6546eaa391bbb3975ba5e1722a6124c426d678e7f784bd9"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936870a6298af9b4a910f0552eb873b8943700e6bf1d8a778048c3563dd43b31778e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e891faf9d665bb151ea32d070ad80c7b31483dfb68e75e940e326e177970210d6f819d45740b1e9d6e416a8a4978331345395bf058ef0b936b66c7755017d83c65"]}}, diff --git a/txscript/data/taproot-ref/d49f2424f7e47981e92cdca8a120fad3b5b46351 b/txscript/data/taproot-ref/d49f2424f7e47981e92cdca8a120fad3b5b46351 new file mode 100644 index 0000000000..2cc9c5441d --- /dev/null +++ b/txscript/data/taproot-ref/d49f2424f7e47981e92cdca8a120fad3b5b46351 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6d00000000774e8a9b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b1010000006be7d4170139141c000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8744020000", "prevouts": ["c81348000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "e5dd3700000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e6", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e11f8d24c2756f16b9efc524121d49339a04fd56a536f956352850ed4d5018a4abf7205f064a536655663faab66bf2e716758d251376e4a55710082b6d7272244791bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f70487ae4384611f908618191b61bece567637059dee67ecc200d57fcc06025825f2fc2293577bab1371dd996050d2a4e8a01eb34ee2db6c09974277461b3e6691bbc3b31bcff977684854464ae3dc2a24522286fe393648b51abc79cc246ff8"]}}, diff --git a/txscript/data/taproot-ref/d4a61c1883d529642358ce1ad476eae28f347140 b/txscript/data/taproot-ref/d4a61c1883d529642358ce1ad476eae28f347140 new file mode 100644 index 0000000000..914ce10aeb --- /dev/null +++ b/txscript/data/taproot-ref/d4a61c1883d529642358ce1ad476eae28f347140 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbe0000000064ec2af8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce201000000970d9888023a6b9c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874e000000", "prevouts": ["24ae4d0000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2", "a8e9500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_62", "final": true, "success": {"scriptSig": "", "witness": ["9cc731e5a9cf904d607e62059bd6a4db7527a21a15bfe90786abc0161cd84599b93326922432c10ed41c9764636d932a9a71ec02d3d2071c7fbab46d4bfac0c503"]}, "failure": {"scriptSig": "", "witness": ["2093a8dfd613b52c54e91ec6c58232b496c823ceb1598cf5a44404d6abaaca163568efc88cd1ade61ca458bfc780954c410d9955431d285d88f2b3d34ad7baf062"]}}, diff --git a/txscript/data/taproot-ref/d4b2d30318741bf9642c79ca255322762ff5a669 b/txscript/data/taproot-ref/d4b2d30318741bf9642c79ca255322762ff5a669 new file mode 100644 index 0000000000..719070a46f --- /dev/null +++ b/txscript/data/taproot-ref/d4b2d30318741bf9642c79ca255322762ff5a669 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6f01000000928f47ca60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c1010000000276321b048f28600000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc1683433c", "prevouts": ["d36254000000000022512055d32a9b44ee6fb3a2a0e7e2d6444c6afa4ce43aaa0c5357064383c70ed0d31b", "3f930e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936257a75f8119edf70e3bd862f4b5d9d4a02f47e43cb7a52febdf672916561824f"]}, "failure": {"scriptSig": "", "witness": ["6a76616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/d4bdc84c656fc906c865b5369626edd1bc0d575d b/txscript/data/taproot-ref/d4bdc84c656fc906c865b5369626edd1bc0d575d new file mode 100644 index 0000000000..bb5ffdac13 --- /dev/null +++ b/txscript/data/taproot-ref/d4bdc84c656fc906c865b5369626edd1bc0d575d @@ -0,0 +1 @@ +{"tx": "f558c58603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b980000000056c18ef4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2401000000aee696e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42a01000000869aac980117bc3d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdb518220", "prevouts": ["e140210000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "49c88100000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "8e2839000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/invalid_cs_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}, "failure": {"scriptSig": "", "witness": ["d79a506e698c3db808d28f100485c98af4a3b06242b45dda2258d5655cfebb6700ca51d9e4cd4938233267c1edf81ec1568cbd923f0071d6ce79a27fb98b93ce", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac91", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313dbdf1030dff2ec7c5788ba50ec11394c7b78eb3f2b816626023d6daa3a2572114c8faadd8f5d0204cf52c57e4d5fdb2eaa5d356938be1ba736d0df22531309921"]}}, diff --git a/txscript/data/taproot-ref/d4bfa057df6de164cf5907d1054f7b8f37dc55ca b/txscript/data/taproot-ref/d4bfa057df6de164cf5907d1054f7b8f37dc55ca new file mode 100644 index 0000000000..38177e002e --- /dev/null +++ b/txscript/data/taproot-ref/d4bfa057df6de164cf5907d1054f7b8f37dc55ca @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7d00000000bdb388de8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42302000000684f888f0147fd2300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5ac08453", "prevouts": ["109027000000000017a91468f63610c45a6790781558e4d5ce83e16e8f3f3b87", "d6aa3a000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_mis_83", "final": true, "success": {"scriptSig": "", "witness": ["1dfc303e1378c5b9638d5df1ab09ea73422f921a0aed50d9e94c1a02e70d05165f0cb1a872baabd755d0358941dcc25e9c7a0ff6012c7d1b795707462c88507902", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["d30e78f6ab0993b1b0fefa7dec7acc92beefaeed95046194370a16d669347ae5370213671c42b238db5e28413f8683324567f89469f214ed143499de21d0529783", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/d4d9f5cbd1cf9b75c9821d5d4746491e46efecb0 b/txscript/data/taproot-ref/d4d9f5cbd1cf9b75c9821d5d4746491e46efecb0 new file mode 100644 index 0000000000..7d834ad9df --- /dev/null +++ b/txscript/data/taproot-ref/d4d9f5cbd1cf9b75c9821d5d4746491e46efecb0 @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd3000000002c5cd68504874a25000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487f1b85c37", "prevouts": ["5160270000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["f34c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364b47e9b9572a2fdbea0003eeba5c6c5df8476b78e561177a43bb360ce14ca93ec9fc6c767d5aa72b6a61d813f4dedd67fc97d91e71acf86e276ab6f41d1da0fa8c03caa221836b2e776996c8fa4c69c403af6889ee9c99c5c1fa82cf4b3a1b61"]}, "failure": {"scriptSig": "", "witness": ["4c52f3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4e05de1aec4dcfd94364dc697d2506f2d3dcb95f0b1cd2734b3ed6d289f30b19a3cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}}, diff --git a/txscript/data/taproot-ref/d4eb08a9f93ac1b16665f4266fcd570b760e0b41 b/txscript/data/taproot-ref/d4eb08a9f93ac1b16665f4266fcd570b760e0b41 new file mode 100644 index 0000000000..3ccaeca9c1 --- /dev/null +++ b/txscript/data/taproot-ref/d4eb08a9f93ac1b16665f4266fcd570b760e0b41 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbf000000007c50ca91bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf94000000002da740f8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0101000000229667af01daee3f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963a040000", "prevouts": ["27a64c000000000017a9146db815d9819f256ca5d1e70b15558a98689cc52e87", "24147c000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "aff2740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082dc2f05b59194cbdf87848463e1c2c1324ea07adf35e05c7c9d5f4b3dae1cf3a20eb43d08761fb76661299d0344fd2d8bfc7de5e7c6dc622156e95971f4b8396db5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ba371f3d414732c1c9e15a0164c634559da48866c534aa79174298bfda3b2aedc2f05b59194cbdf87848463e1c2c1324ea07adf35e05c7c9d5f4b3dae1cf3a20eb43d08761fb76661299d0344fd2d8bfc7de5e7c6dc622156e95971f4b8396db5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}}, diff --git a/txscript/data/taproot-ref/d4f11edc0601915ee85baffdd4721b1d1b3b60d0 b/txscript/data/taproot-ref/d4f11edc0601915ee85baffdd4721b1d1b3b60d0 new file mode 100644 index 0000000000..c0336f4cba --- /dev/null +++ b/txscript/data/taproot-ref/d4f11edc0601915ee85baffdd4721b1d1b3b60d0 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e10000000064472c8d0459df38000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4872a000000", "prevouts": ["67e63b000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "657d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364a310fc6f479979a5eb932d4070c1430d885228cf96926ff0d6233d323e177b97a9921914746f344d752c7034b32810721c9853c38c376ca018a4c3c5bab65757fdb01d6ca2155f5be7a678ca6a1e1d0c436995e81f878ed9c74997cf4fccddd302781454c6297f6b8a579760f4d591c0acf84ff9d038b064bbab8a5d53835db"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936991fbe960c4d007c38cd214187495a17c7b10e613ea03451dbfa2e0ceb38b03138fd10ac28b4a0ae18793cce60e7e7ebbedf1e3488ce0551c956bc9cf517ba032bc2c7d802e8c870cc0fefcfae9d23d316cca1682651be3bf62b663d5ddaa443"]}}, diff --git a/txscript/data/taproot-ref/d4f65e281be1feebd4750e113b05138a9c44f486 b/txscript/data/taproot-ref/d4f65e281be1feebd4750e113b05138a9c44f486 new file mode 100644 index 0000000000..6b9e44cfb8 --- /dev/null +++ b/txscript/data/taproot-ref/d4f65e281be1feebd4750e113b05138a9c44f486 @@ -0,0 +1 @@ +{"tx": "dc9f3d8802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf46010000009ae647c88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44901000000ed7e76b5043306b500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8725000000", "prevouts": ["89a97b000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "5f003b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "47304402206af2a4432a634af2be9cf92ef05597f05a5d0c402c81b5dfba0ffddd0ce68a4602205008d3965ee05d5e162deed3002a5eda9c09718ca5a1f34c0ca8e684cf6c6d282f434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "47304402205ccf0e4f051da6faff455f471d7cb21d060a81bd9a4406cc2cb3ff894fa9068f022059adec1278f732b0be7311e822dc67933a5a5350167c8d2758886b96422e08c52f434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/d5048f880c8259302815a101c17c687a6ddbb1d7 b/txscript/data/taproot-ref/d5048f880c8259302815a101c17c687a6ddbb1d7 new file mode 100644 index 0000000000..a6fe25965b --- /dev/null +++ b/txscript/data/taproot-ref/d5048f880c8259302815a101c17c687a6ddbb1d7 @@ -0,0 +1 @@ +{"tx": "359812e802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7201000000f61b3eff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47f00000000acc258aa01c7a31a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88accb010000", "prevouts": ["d21d2400000000002251204aa7ef3c48fcabcb6102b9295fbd3d8d5e51a18011383dd7b1650a23dcb19459", "fe98330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "success": {"scriptSig": "", "witness": ["32c7f223ac8967cba1691441ddd5b520404e6bd0586c612deabf23d031d91a443085d6cce769ac9734b9b8ba4128f6a337aed4173615dbc876bf4a4f948d7dda", "b7f6d3cb3c4aa862ef0f0af5a93791c84b9a4f79d873c58aa1f1b9a6fa74644b2137b1affe0fa2bec0e58e50e8e427ff90a092721f35d350b955c467a028b3fd94233ee19770485f1a219d09698a976352e3d4e59d9f7739131d03b71909a098d709482d9201058335a4c65496a9cb45811afebc0e074f5330fc7cf19b719a74c3f3", "4cdc9f84ed1706b60db6f8353f94ee36918be19e7397219203e68b81eeee7727728614d8be75a911849e2d27cfd2444c8bd030a51fddd8ba2817bab96ff90891530b70e677806ab2fc53710551e6818c80e4d1c7e3f964bb94112a4ffc7fb8cba5cf5186358ba4561f6b9530426ba8bf9d2edf6f6d5c8aa9480138f624d76d0794a97fc5c98ee71d9ed4372184b95bb954a76c0e60e519c35fb52f66aae5f32ae797ed91ab8cf26978dc5f05136945bfcec85d0f05013c62d122f4ed5ec87498a05acf741efafecf643b2f56879f8be6fa13cc42087889815b078a6081de6d29dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b325051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a888b001aa38ca4f81f28c348a28e97928d44bd2c2abf7fc923a6982caca431730e2fae8262ecb686a2c0d0b0d7956dde278299606acbcf55eb63db970af7c026559bbe2fbb3ee1b794a568864bae20cc54681e521994968a26f53c0b9047b1df7c5842cca2c5b35e4f143ef350328511c82fdc94d887b021b126a7f63f6eba1219890701613affcb7f92686256a960a6e542bad4487e0f11507ff102da8494efba0e17d9549ec2a5df5da3da78510b4a393c87d28646fd879356f5c36a863575a62101539f29fa2237caf606916095c2facae2e89a1f9a90aa10e855b6dd2e843dd5152050bde1b0e57aaae0d2e237805329ac7ac8a97ce21055a714b651db1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b51b359a9dac5d197ab79419c16a4ab0bd46b8b627fb9c6a515c02b9ea364bea061db9590375c6fa034185521fa93c3738906f28c37ae3b14a830f37a77332c2294f905f6f7fc94a2257e6e30b8e9521a4b96bce7cc6d2e71ba2935d7385e6e0bba479f1cbf6e111aa8e290b91c6252136611d1c70947ee0df00a6830d16d5e29f45db4e1660090530903145de1823c587b88fc33ddbd58861f782171956a3c4a9752b34d80250f27c4f5300249446d1d296c12a0deb46986727cf4f8a4b8f30000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebc4dc6bf140432997c194cdd67857c8587a7e76ed4bd63e8babbb53fbbba0ec53c42f9004e9b0cb5ff998c6279de68d16a8683d19f391af0a230431b39e907869112349cb6c79929ea35acc94f2efae6ccf162076d698f158369121387744ccffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f46cc218f0a250008da1f30776fea2b77f14055783fffefdb1ff34e74a73f675c8cda47bf66ce13290e0f054d23a1b57fea18685da4f43cca95c40b98b98c941f088b7f15b556fe17bd3de64e86eaf19aa9f40e6f1613d0f3f72e0bc519a650356c9ffc9cd375ffc62dabd5f28de7c7e401c5af46327ca92921753dca3a175a61871bd24dedb950762a2b74aa1ef62aadcf270bc64ba18ec6479a50f7273b1038fb81667be79a2d0044bc6b38ed1df424e3d08f00986eaedf8db9a0cb413bbd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000135e9a6ceada7813b3002f4f251c5724687e3edb62caab37ad7794a7b2e317922dc678efff966a67e49699749288c22d68c9683c8fd7929d265b9474902cd79dc5f4aa8f9ac2d9b99ce2009d49cad0c4a2f89298b4df2303437444ee49c645850000000000000000000000000000000000000000000000000000000000000000ab3dc1b4cc112a7e80c80274c91d249d1e9bffd2252e25112522a6372a3bd6b01839137a43de2932be810f3e03c1a128c369bc85b7c9df253c31446ca2c1ef3040a25a00a887a56ae01f798570b8dece82dffef1eed19bbe49fb48d4c42286112e068ab65c13eda692e3fb2096a0e880ad71c6174edd855fd39ceab37bf8e8efb2fb7f90b786ec9996e01ac6656567cc82d2ca0b9bb04c2f60d4ebfa4c7ca1c454849be350fc11e221571b7983906fc1b212ce398fa81e1aead15cc4fa5a2757bbdccd1d8ce9190883ce9da885acbf3f5722562bb4e524d492798055c63521c20000000000000000000000000000000000000000000000000000000000000000603a9c46007d94ed32805f706394426ae8697d8deb5803a09ff0e82a8f3e7a210000000000000000000000000000000000000000000000000000000000000000aaa2c5c52ccae92631a5af34aa3c38ae0b25f991e86a99572d36a6ddcf2415acf780d638505eb8ad331ef26db2712a0232aeb4f211016fe4b629ae9aa9de04180d867bce0bf602461f7d40b314c8d0d63a4fe769f8b92fc1f5445ae1ee6b94b56ff1b7e7d94538031710c3401ebdd2a1a3ec976382579482b7e9f403c1af1dbdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff74248f05ecb92be6b918266dd25e9542bdac05bed733e3b5dfd0150921ddcbc6636a335b68c02027991377ea8b23b1c00b1068b14d50a461bd4737c3b6f5fc663496d6915942c9826b255926030095b4b4a2f9ed5c2460e8c007ee4b311ae4e1d9984f176f32915b66363a142811b933bc191a02409497ccca80fc13dbc750bfbfab6232e52109e8513c1f2f26eed770f84beb853e9d20caa032c59180a76f06fd83b812b978864749e6c8ea721ef7f44a188035ab3943b43f5b2784459e28e10000000000000000000000000000000000000000000000000000000000000000e4577a5de16b3fa88f0bf818340f27f202e8c88260a11fc2ad76bb76f17ddf34ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81ee5aaa5a4ca5f929aff24c7ea434335a3f8f103b02bbb5bffbc49c01076c08da75c3c36fe1beefba884e996a7abd95993cced2e5cfe401a3e00bcd8ef577650a37766312c8614df2ada6c45e2d320b8d7a45e25084f162faad41984ec81ed03a5db47d122ab4312c4e56410f2a242a770fe834e4c519b500344a9e01c30dc74661e9dc30ba59e103040919946cf31cae17353ec21d89138e527bf669dfb000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa6012aacabaf14046dad28434109856202eaa8534e380e796a479b37473870f07a74cd2f13aec3346b552f07009dce101d630c6026ebab6901bde58db017b2321f8890fa3315cb1a251c51fee105129d2cee6f1c65e5f86164c752899776e48395b981e0fb6d795b741aede21d193b9242074932b4d9fdd28e8a1731b67658e215954a4dae80e4cb2b1476bb2b862457c49070f367c8f481ba90ab6d08f8f1bfdce993630eacf3addb6686d885184bac046c555702f40ef207faebd154c03523d1b9d67349b47e8f0adf808cd6a116759226ef2767e8115b8bed5794a15e4dae84ef977bc823dfcb17095c38010c14ed1230a1e355d9c8ee4cbdfbb49db252e6c7529d8dae43548a0fed6e93730af5756b7a53d1138c48735a53341dd5b954da394e879341a6e6a4f8b05d184e238340649c481955527911d5bae9d4c11f499fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b56ecf6f51fa16adb2a6a6753909944dc19eaabe9174db67570dfb07cef263d85de64cc08c3efee4fe5f48c3fb88bbce7f5158ac7729240e2abad48ade8157c7b7863a4ceb1e8a7f9619724f03742d8632e3e563943004cd8ca7b6cfcdae593317f52a56961a13d1d425f12a7fd246347b01a744fc526a3bb8f71ff27667d32e0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000e7655e3fb09734ff7e305818f2ff67018017317c6b43f6df3b46b13ae189abfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb95aa3a37cff9fafa2eff8edeb9afeef1abd6423388e4132b8b4330200412724c2c59374e4ce8664e9c6380fcd7ffe1ab595bc06f0dd83302c1b30e2263225d50000000000000000000000000000000000000000000000000000000000000000c8b94f83818a376911b8f2a136cea4f86f7139f994375170d20b97ed1c853f66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4670b9b748b210a86cc2f2b1444680692b3bf4a3acf0d4fa958989e1ca1d34eec267afd1bb5f98c113bfb1b3a162fd54e413f7ab2dbb52d18428ba704a11c4bc83abb92039ddae21bbeeb271ca6c9de459f8996c433ecf34220619c3923ab53a0000000000000000000000000000000000000000000000000000000000000000cf6f0bf7ea92ec1083bf86998d9810c7ca9e221ed7fac97055379c9ac9a45ad7ea385f129019a1d8c0238a75abe0ec20820b7c3e10c3a672b2b964ebdde8b7e50000000000000000000000000000000000000000000000000000000000000000db03c8da878ee56228e0f2c23e7503073e63e33b82902ce15014d673079e0a1c00000000000000000000000000000000000000000000000000000000000000007bb5edb3223212d4c5b74bc419f4af7e65eb6b19c8935896fcbe82b1afb5dc9dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7163e7d847d570da354f75e2c4fe5a2b8f6949b3968698af9532b7d642789054a53b1e86b07369fef041cf59e9ed38e257bd80fc10a32f8bcc35e000e63845509487c7ec7791be4181c662529bd3fcd9477db17059fde5f7f867aa46b69540c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e6b99882291313ebd54f327c6fd86607d5f66d51011e570ef7b5a7edc18ade0f36470b73d195d01c88cc1dbc98a19badd4ce4802653f5495c5c8c79c87e0cb601d6c05f501075ead8dc1610cbdb77edd5fafc1197d7141e57ad239a5aa3dd34c70734efc5367420aac2d4358ef038fbe53fa6ffdf3456ba8dc2c94fc44f9d73f0000000000000000000000000000000000000000000000000000000000000000d7424680efb589544e95d57f84e5b9f08394b6b1d0679da58e8e58c596770a3bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}, "failure": {"scriptSig": "", "witness": ["32c7f223ac8967cba1691441ddd5b520404e6bd0586c612deabf23d031d91a443085d6cce769ac9734b9b8ba4128f6a337aed4173615dbc876bf4a4f948d7dda", "e6f4758c5558d3f74d88a980acac6aa59fa4a039bd6154aad55ad34fd1aa23d3681e188df17a1ed625615ef86075db0063f237dee5a87a9d704acffce449d7d10d06f5ce816b85c5223f9c03154f66bc26b7de2f19cb301c263ed58a002bafbce8fdf489175b65c8c0238fbe32a872120fa3f17b0bd9ea86f346f928d51f1a9d26", "4cdc9f84ed1706b60db6f8353f94ee36918be19e7397219203e68b81eeee7727728614d8be75a911849e2d27cfd2444c8bd030a51fddd8ba2817bab96ff90891530b70e677806ab2fc53710551e6818c80e4d1c7e3f964bb94112a4ffc7fb8cba5cf5186358ba4561f6b9530426ba8bf9d2edf6f6d5c8aa9480138f624d76d0794a97fc5c98ee71d9ed4372184b95bb954a76c0e60e519c35fb52f66aae5f32ae797ed91ab8cf26978dc5f05136945bfcec85d0f05013c62d122f4ed5ec87498a05acf741efafecf643b2f56879f8be6fa13cc42087889815b078a6081de6d29dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b325051646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a888b001aa38ca4f81f28c348a28e97928d44bd2c2abf7fc923a6982caca431730e2fae8262ecb686a2c0d0b0d7956dde278299606acbcf55eb63db970af7c026559bbe2fbb3ee1b794a568864bae20cc54681e521994968a26f53c0b9047b1df7c5842cca2c5b35e4f143ef350328511c82fdc94d887b021b126a7f63f6eba1219890701613affcb7f92686256a960a6e542bad4487e0f11507ff102da8494efba0e17d9549ec2a5df5da3da78510b4a393c87d28646fd879356f5c36a863575a62101539f29fa2237caf606916095c2facae2e89a1f9a90aa10e855b6dd2e843dd5152050bde1b0e57aaae0d2e237805329ac7ac8a97ce21055a714b651db1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b51b359a9dac5d197ab79419c16a4ab0bd46b8b627fb9c6a515c02b9ea364bea061db9590375c6fa034185521fa93c3738906f28c37ae3b14a830f37a77332c2294f905f6f7fc94a2257e6e30b8e9521a4b96bce7cc6d2e71ba2935d7385e6e0bba479f1cbf6e111aa8e290b91c6252136611d1c70947ee0df00a6830d16d5e29f45db4e1660090530903145de1823c587b88fc33ddbd58861f782171956a3c4a9752b34d80250f27c4f5300249446d1d296c12a0deb46986727cf4f8a4b8f30000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffebc4dc6bf140432997c194cdd67857c8587a7e76ed4bd63e8babbb53fbbba0ec53c42f9004e9b0cb5ff998c6279de68d16a8683d19f391af0a230431b39e907869112349cb6c79929ea35acc94f2efae6ccf162076d698f158369121387744ccffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f46cc218f0a250008da1f30776fea2b77f14055783fffefdb1ff34e74a73f675c8cda47bf66ce13290e0f054d23a1b57fea18685da4f43cca95c40b98b98c941f088b7f15b556fe17bd3de64e86eaf19aa9f40e6f1613d0f3f72e0bc519a650356c9ffc9cd375ffc62dabd5f28de7c7e401c5af46327ca92921753dca3a175a61871bd24dedb950762a2b74aa1ef62aadcf270bc64ba18ec6479a50f7273b1038fb81667be79a2d0044bc6b38ed1df424e3d08f00986eaedf8db9a0cb413bbd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000135e9a6ceada7813b3002f4f251c5724687e3edb62caab37ad7794a7b2e317922dc678efff966a67e49699749288c22d68c9683c8fd7929d265b9474902cd79dc5f4aa8f9ac2d9b99ce2009d49cad0c4a2f89298b4df2303437444ee49c645850000000000000000000000000000000000000000000000000000000000000000ab3dc1b4cc112a7e80c80274c91d249d1e9bffd2252e25112522a6372a3bd6b01839137a43de2932be810f3e03c1a128c369bc85b7c9df253c31446ca2c1ef3040a25a00a887a56ae01f798570b8dece82dffef1eed19bbe49fb48d4c42286112e068ab65c13eda692e3fb2096a0e880ad71c6174edd855fd39ceab37bf8e8efb2fb7f90b786ec9996e01ac6656567cc82d2ca0b9bb04c2f60d4ebfa4c7ca1c454849be350fc11e221571b7983906fc1b212ce398fa81e1aead15cc4fa5a2757bbdccd1d8ce9190883ce9da885acbf3f5722562bb4e524d492798055c63521c20000000000000000000000000000000000000000000000000000000000000000603a9c46007d94ed32805f706394426ae8697d8deb5803a09ff0e82a8f3e7a210000000000000000000000000000000000000000000000000000000000000000aaa2c5c52ccae92631a5af34aa3c38ae0b25f991e86a99572d36a6ddcf2415acf780d638505eb8ad331ef26db2712a0232aeb4f211016fe4b629ae9aa9de04180d867bce0bf602461f7d40b314c8d0d63a4fe769f8b92fc1f5445ae1ee6b94b56ff1b7e7d94538031710c3401ebdd2a1a3ec976382579482b7e9f403c1af1dbdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff74248f05ecb92be6b918266dd25e9542bdac05bed733e3b5dfd0150921ddcbc6636a335b68c02027991377ea8b23b1c00b1068b14d50a461bd4737c3b6f5fc663496d6915942c9826b255926030095b4b4a2f9ed5c2460e8c007ee4b311ae4e1d9984f176f32915b66363a142811b933bc191a02409497ccca80fc13dbc750bfbfab6232e52109e8513c1f2f26eed770f84beb853e9d20caa032c59180a76f06fd83b812b978864749e6c8ea721ef7f44a188035ab3943b43f5b2784459e28e10000000000000000000000000000000000000000000000000000000000000000e4577a5de16b3fa88f0bf818340f27f202e8c88260a11fc2ad76bb76f17ddf34ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81ee5aaa5a4ca5f929aff24c7ea434335a3f8f103b02bbb5bffbc49c01076c08da75c3c36fe1beefba884e996a7abd95993cced2e5cfe401a3e00bcd8ef577650a37766312c8614df2ada6c45e2d320b8d7a45e25084f162faad41984ec81ed03a5db47d122ab4312c4e56410f2a242a770fe834e4c519b500344a9e01c30dc74661e9dc30ba59e103040919946cf31cae17353ec21d89138e527bf669dfb000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa6012aacabaf14046dad28434109856202eaa8534e380e796a479b37473870f07a74cd2f13aec3346b552f07009dce101d630c6026ebab6901bde58db017b2321f8890fa3315cb1a251c51fee105129d2cee6f1c65e5f86164c752899776e48395b981e0fb6d795b741aede21d193b9242074932b4d9fdd28e8a1731b67658e215954a4dae80e4cb2b1476bb2b862457c49070f367c8f481ba90ab6d08f8f1bfdce993630eacf3addb6686d885184bac046c555702f40ef207faebd154c03523d1b9d67349b47e8f0adf808cd6a116759226ef2767e8115b8bed5794a15e4dae84ef977bc823dfcb17095c38010c14ed1230a1e355d9c8ee4cbdfbb49db252e6c7529d8dae43548a0fed6e93730af5756b7a53d1138c48735a53341dd5b954da394e879341a6e6a4f8b05d184e238340649c481955527911d5bae9d4c11f499fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b56ecf6f51fa16adb2a6a6753909944dc19eaabe9174db67570dfb07cef263d85de64cc08c3efee4fe5f48c3fb88bbce7f5158ac7729240e2abad48ade8157c7b7863a4ceb1e8a7f9619724f03742d8632e3e563943004cd8ca7b6cfcdae593317f52a56961a13d1d425f12a7fd246347b01a744fc526a3bb8f71ff27667d32e0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000e7655e3fb09734ff7e305818f2ff67018017317c6b43f6df3b46b13ae189abfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb95aa3a37cff9fafa2eff8edeb9afeef1abd6423388e4132b8b4330200412724c2c59374e4ce8664e9c6380fcd7ffe1ab595bc06f0dd83302c1b30e2263225d50000000000000000000000000000000000000000000000000000000000000000c8b94f83818a376911b8f2a136cea4f86f7139f994375170d20b97ed1c853f66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4670b9b748b210a86cc2f2b1444680692b3bf4a3acf0d4fa958989e1ca1d34eec267afd1bb5f98c113bfb1b3a162fd54e413f7ab2dbb52d18428ba704a11c4bc83abb92039ddae21bbeeb271ca6c9de459f8996c433ecf34220619c3923ab53a0000000000000000000000000000000000000000000000000000000000000000cf6f0bf7ea92ec1083bf86998d9810c7ca9e221ed7fac97055379c9ac9a45ad7ea385f129019a1d8c0238a75abe0ec20820b7c3e10c3a672b2b964ebdde8b7e50000000000000000000000000000000000000000000000000000000000000000db03c8da878ee56228e0f2c23e7503073e63e33b82902ce15014d673079e0a1c00000000000000000000000000000000000000000000000000000000000000007bb5edb3223212d4c5b74bc419f4af7e65eb6b19c8935896fcbe82b1afb5dc9dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd7163e7d847d570da354f75e2c4fe5a2b8f6949b3968698af9532b7d642789054a53b1e86b07369fef041cf59e9ed38e257bd80fc10a32f8bcc35e000e63845509487c7ec7791be4181c662529bd3fcd9477db17059fde5f7f867aa46b69540c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e6b99882291313ebd54f327c6fd86607d5f66d51011e570ef7b5a7edc18ade0f36470b73d195d01c88cc1dbc98a19badd4ce4802653f5495c5c8c79c87e0cb601d6c05f501075ead8dc1610cbdb77edd5fafc1197d7141e57ad239a5aa3dd34c70734efc5367420aac2d4358ef038fbe53fa6ffdf3456ba8dc2c94fc44f9d73f0000000000000000000000000000000000000000000000000000000000000000d7424680efb589544e95d57f84e5b9f08394b6b1d0679da58e8e58c596770a3bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"]}}, diff --git a/txscript/data/taproot-ref/d52e561715cddf6ccf811873e1d9570a5b25b677 b/txscript/data/taproot-ref/d52e561715cddf6ccf811873e1d9570a5b25b677 new file mode 100644 index 0000000000..ec1bd47753 --- /dev/null +++ b/txscript/data/taproot-ref/d52e561715cddf6ccf811873e1d9570a5b25b677 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40e00000000fb7b46b8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb201000000c6e24f480102291f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1932c947", "prevouts": ["d42f3f000000000017a914a2a8d85df2f20a0aaff7224012fc4cee13e29cb987", "219e2000000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "215f1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["bc4b90593b05b9ff449ee11caef0798fd71c32a36f41a3420bae79279e38d3afe6d7923e8cbd990636b3822461c6070222735fccc1a811b2a51da486ff0995a8", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/d5466e451d61467e6bd45f66d7608457be8a656f b/txscript/data/taproot-ref/d5466e451d61467e6bd45f66d7608457be8a656f new file mode 100644 index 0000000000..12fa0527cd --- /dev/null +++ b/txscript/data/taproot-ref/d5466e451d61467e6bd45f66d7608457be8a656f @@ -0,0 +1 @@ +{"tx": "f4b07dcb0160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704601000000e99584ee02b3830f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d9000000", "prevouts": ["d773110000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090284f49978384c0b3541a853e003fb71b78619282c1d6eff5ef6c525c5380db9adbb77c600a840e08da90cf963bd3eccf4cd71788e11abb8e72ff5eb20e5e2b7ad4d81be200e5f909d2668b06941be5bf4af139aea8e31f371cea837ef2a13b9e207bccbc3a500195cda61e82681b1aff50f9a9316782024d1961c67ef137759fda284117cc43477f213f1850b114cc8f1cabe8cb618a024ddb1425a250f2127b27e4fc0df67994e36260c59f5aebd9cb9881fd03e1bf6ab86f3b9b5f6cbc80d70439aac8ab95fbf6ffd7ee910079a20a88d170b7082f03aaadbc2bd43e34e6541a760f1e76a2c3dcdba2ddbb09f24be651c78e2ccdef22bb12147b52ea8a21fa4349ad806187d1c5b2b372a232d6b1e7dc671ba1fefb06dacc47a961c39c5b3691de0d291a4c17f9968bf2de5485f559dfc563a7879914c195fd0de37410471c2d5be4ce5505badb18993e84c14a4f8d73e917535224747dd9f3803c298b84f79e5f9b0e7f64c3c1e86ffea8fbfbde25ed1ec8a4e19336e7dd389454c681a378b01b854d039605e7f63ecfbd3b639fcbb612d7ca5444bd968b9e6009522d42bea240d1069e1976d0ac035a8c0a5f45799fcef2339e8ab73ac569601fb4bf47ef25c8d0a9f77051a9de52facab241c2d878aa14e2615285268f514e4a6c713bb60befa3a32f73c1f6c0e8322860ae221e33ad4271ebc7a61c70dcfff8b47c74e1127c8d5636e9708713f75", "f07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367f19d13d85523b75ce99e37b4eb76b07a29c0c5af0a35faf8d29e39dbe1f5f9646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fadf7eb609cf6b5925737ad21e523a1c8cc87f95ebe19353e64c9623e085aa5557f88c7bee1bb9c109f1c6365501285b6447b8ae029d34f47d1dd1efc50e8947b4"]}, "failure": {"scriptSig": "", "witness": ["4d09022d172730b6b54f775690086a5f8940eab41849bf10cdc8b09b523a205515cb8f5c373c27f89f293b7d7ee790ab0b974c69c331aad40832b0b5104aea50a70bbe7de3a844c6aa52384febb0e293ea7991a9f7e170fdc81c01eec25e1342f18753370a42f4f025d781297df195da3b790d57d2492a8b7d3dadbd94d734dd054a35b095a68a028b3e9f46aa6e173dfa771e4dff1ef780d48eeea15f07d6ec11d8661ac90a682e295e793983c0471b3a293e76a6031464edea06a0f5a85f94a53c576dc1a7344bc2a6c2c1d59625195e5cb0e84db47944164fd65e579ec1836868e7f143f19638cecd3bcec05194c5071448153d34c74225b9feb0bbdccf8376ca0b3a8daf0a2f52082d5044e8fafadbd1516225d6497ea78f7ddb0eb7d29cd7eb090f9ef7ef8c7cd479806dba02bb28d0ce6e5b660dea77dfbea4650c7501f6d3f55cb16339118b9ea7b8ecfc1cc26f73c1ada541debe7ce764c1e735fe4fb9f3b49591e55e73a606df3c0e043b5edc10afb0ef51467d88061fb1a9ae1097f438c8f2007d5a40467a80430ba299224ade766b05b4f39d763be2c2df1105f1c98da5d3cca51b44aed31aabde4d470ed63345101d43302710478236906e9faa255fc5adc14760ac0fa64a26bb07434d70669ac66c9832d65bce8cd31e332c5340b9c0434e70ad12de2b149cfa6d8ba712325fa8eec50a0deaced60e575e77bc9e7f909a2b448b29220175f475", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef410cc536787f5b60ec7eff151035c62e0db5c59dc9e94e3d527a7bd7513d4346c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fadf7eb609cf6b5925737ad21e523a1c8cc87f95ebe19353e64c9623e085aa5557f88c7bee1bb9c109f1c6365501285b6447b8ae029d34f47d1dd1efc50e8947b4"]}}, diff --git a/txscript/data/taproot-ref/d54c6961bb95000149d7cffd738f1f34eaf1d825 b/txscript/data/taproot-ref/d54c6961bb95000149d7cffd738f1f34eaf1d825 new file mode 100644 index 0000000000..94ab975741 --- /dev/null +++ b/txscript/data/taproot-ref/d54c6961bb95000149d7cffd738f1f34eaf1d825 @@ -0,0 +1 @@ +{"tx": "fea3974303bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaf00000000f2daa1b1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7200000000c374aebcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb2000000006b51dbf6012250b200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac38d83e24", "prevouts": ["447672000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "be8e1f0000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "cbfa2300000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "7e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365b6bfb69b7e814fcb4dcebe676c838c8fffdff04b3ac333f34250baee888dfa2fbc41b165d26ac180ad5b5d4c7fd11b6e5ed18084ae5d6505f3de45d58844c1cfa5d068ae686a8bb1ac9947127542ac866077ad522de57cab26ce701d52bc951"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a63a87ae51c747f55e6919561fc04ebff87ed8246314dc037503ca155d679649d3fb5b8f7b3afa290146b30788656a8f4c2497a65b1555cd50f1d702ddc8a1f8f2e4a14a40b0acbe20218e44481fe6660f01d2e0cf04e3bc8d4452bacd1080d1"]}}, diff --git a/txscript/data/taproot-ref/d54fe454199d96dd8e1ab2d0069417d2b9be7cf7 b/txscript/data/taproot-ref/d54fe454199d96dd8e1ab2d0069417d2b9be7cf7 new file mode 100644 index 0000000000..385a864ebd --- /dev/null +++ b/txscript/data/taproot-ref/d54fe454199d96dd8e1ab2d0069417d2b9be7cf7 @@ -0,0 +1 @@ +{"tx": "cc88653202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf07020000004b0446fa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ce0100000099320c9c03335573000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898713000000", "prevouts": ["3517640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "07b7110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b9", "final": true, "success": {"scriptSig": "", "witness": ["15d07b0cc069d30a8ec13eb5c3c23f4c5fa614b462e80e9480e9551ed27212168ea433cd0db8ffa10084f62cdb4e67b4d3c21720c72835959de1e43326e6999f81"]}, "failure": {"scriptSig": "", "witness": ["880ddc33cdc662b931bf97f18c063e2f8df2da245148308449957d439fb044f1c2c701efe5d3276d655f0e8aa551d5d3d70f0d2626268afaafbcab0008d594feb9"]}}, diff --git a/txscript/data/taproot-ref/d573fa9122441a358ecf4c86ea6af4d26e08d93a b/txscript/data/taproot-ref/d573fa9122441a358ecf4c86ea6af4d26e08d93a new file mode 100644 index 0000000000..521e7c2bbe --- /dev/null +++ b/txscript/data/taproot-ref/d573fa9122441a358ecf4c86ea6af4d26e08d93a @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd50000000053f403cadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8c0000000080e6db55bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0b010000007bfc680003fe5216010000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc79aa1c358", "prevouts": ["f266720000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "bdf22300000000002251203d5ffb7cd06f5c84b56ec9f73ff7cc3a22b38565d229330748f260d30800c008", "acc68100000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "6b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364ef05760570d2f55d281475192af611d2decac15c2ab8d6f0b8da16f9770487605976fe26432a41f3547171b2b9abb696d7de0172bd15211267873326056804912e839b87dc613c826a9c62085431a96f79b8782d4b0fe31dfc75aede09e250a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e85c9148ab8fb2f0e3b60c30486bc2998c5a9fcff153a4260746061263c245b36a70886d9e3726a9aa8a2b94454683b5181a970edd894e0d0cd75aad09f75436b2"]}}, diff --git a/txscript/data/taproot-ref/d5892cc02088b2b7e11febc39b2d7cd9ed96fec6 b/txscript/data/taproot-ref/d5892cc02088b2b7e11febc39b2d7cd9ed96fec6 new file mode 100644 index 0000000000..9d46276026 --- /dev/null +++ b/txscript/data/taproot-ref/d5892cc02088b2b7e11febc39b2d7cd9ed96fec6 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5400000000ddaec8968bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d5010000003ef568afdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4900000000daee1d6e0386b1db0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac56000000", "prevouts": ["92bf790000000000235b212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "309640000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66", "c96623000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100fd9c26e725eb72c96d343a30ab0919a8743718b5e3ad9a96ae960c31b7fe7e77022017e309e156ba3fcaa65d37f96b761bee39809bf4c421eabdf0700e9ede7db76603232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "47304402207af5bda9ff36368566c85a1f78801dd8928199f1f991d03264ca8ec4b0bc8fde02204842a3ef83ddb802ad5759a6030c209ed1dc46e39747dd7eb8bd72e2299c2d6903232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/d58b0cd6e4cd0f7d08d8c5cd8f64fb89bc6c77b3 b/txscript/data/taproot-ref/d58b0cd6e4cd0f7d08d8c5cd8f64fb89bc6c77b3 new file mode 100644 index 0000000000..01f27c00d3 --- /dev/null +++ b/txscript/data/taproot-ref/d58b0cd6e4cd0f7d08d8c5cd8f64fb89bc6c77b3 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf81010000007d91abc060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700400000000377d028060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270550100000075c420dc03d8f996000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876c030000", "prevouts": ["daf6740000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "cd0112000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47", "923912000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_82", "final": true, "success": {"scriptSig": "", "witness": ["03e0d56738bd29832c858290db3feb3b1326ac63c3da9b37b60a4cb140dda9706426e80fceef3247cc89534ff2e81ee92c37bf0ba70b09f0358dd3766536aa9482", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["fb98395126ae6c08fa5a8441642dd48a958a78e183cd269e3d717016044bf62c13b399cd45a8b42e2087bab912a0c9782346b1111688101a4867635d2b593cf582", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/d5ad81a47205ca9893336dfcc66e370ee84776ce b/txscript/data/taproot-ref/d5ad81a47205ca9893336dfcc66e370ee84776ce new file mode 100644 index 0000000000..c6975ba828 --- /dev/null +++ b/txscript/data/taproot-ref/d5ad81a47205ca9893336dfcc66e370ee84776ce @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e400000000e43d3005dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdb01000000dc21dcf7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1000000000413109ca01c445280000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca4000000", "prevouts": ["00ca0e000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "3c28250000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "bb275b00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["8d4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368b6d963912b4b21c343ab35d829758acd38b20aa323c58d3577851a32d8d38189886f85ebb300297009aa959255e1f8e976b091c7e06b33477ed400c40a83b4c185c953dbf0a33402e724bbb72e47d874a897a0941d53d9706dc82e2e14efc19f43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}, "failure": {"scriptSig": "", "witness": ["4c528d", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936945f49fdec6cb7878f2e144d67bd9f1df9c3c82417cbc22aa6b753f3ef0a3b346a7569334f57ff848fadca8fed75a3aad007c69b24557dd271b830b96d574d63f2f7628d981d9c0428415dafbd1cc169dd3ce50060f3002d6f03fa895459568af43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}}, diff --git a/txscript/data/taproot-ref/d5f073d2ccb1d4bc1f4bb2d64971cda535f3abc4 b/txscript/data/taproot-ref/d5f073d2ccb1d4bc1f4bb2d64971cda535f3abc4 new file mode 100644 index 0000000000..8cddb3ba44 --- /dev/null +++ b/txscript/data/taproot-ref/d5f073d2ccb1d4bc1f4bb2d64971cda535f3abc4 @@ -0,0 +1 @@ +{"tx": "956ac78c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd3010000000bede5d6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbd01000000dd0c1e9303c6f18f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79631010000", "prevouts": ["3db3220000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8", "db25700000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090220181b368ae9d7b686eee6a548d44d6bdcc9fe30a6de125b97673e7d821100af65ecf3a24e1cbf57b13b489afbd03c380b95b725d75afc24ef9216a1d3152497fd62f20f2199f0b6cef32c93b993f120feb97cbde5df1640daaa84adccf4c1f8be4fb14ff684684d5b94cd21a968c49fa17358bd3f59fed0ac33240b0380e3d65efaaf40dc851fa06a6807dbf7acb44fe9417f5ef5b46a81299ecfcb87a81d79a36581cfa6617c1fc9e11fab50263e241e065dd60501497f31a03ebf94b3d7c57025ea7858101bcca00b9e0c8885c29e42f9b4773d424a61023af6ac20e7a312042cc9d2b6d72102f1c0b8358320b58f3e8c75910ef5a30b1aebe3752a89a8d2613d7ba29ce2dfca380aa57e25576a9e3de5e4c608fc58340287460bb14dca4caa953b7fa0b4783b270665975bb33bb4afea36e1509fb2c5c4bc870b344aafa5f36bfdf768f68679ed2aea606febe613e055a7357f4f0f3fefc740b676439b75ed699596f3a183339d2e44cd21339b6002e71407188d72f56a3273f524eb50a8044b6f08c567124def6bd60e40102cb2aca69d1082e654dd39b1ac31b69ffb5e10005ef25be97fc5f5de9a5974a9c3bb52255e6117e6d68bb92c97179367e86bbbf3875c7c0826f8e74ccbbfab3f0c834ef8e3c86538083fe16b28c3f44c23223d710b7a771722b80610b8d17fd9db89819e8f3740fc3f6e8bf323358f3f3ff12210d4c6a18a40dbcb75", "2c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93651437a197bbb5be4a199519bf1e4665ed1db87a2684648cfccecc1d7537eb154da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef5981cd58c469d4842aa56f101a76a4447dba55ab7a128197943d7701f95f2823b7ec1fb3aca1c665feb629f75b86bc6796ed5eb830658d68574ea157b89fde9"]}, "failure": {"scriptSig": "", "witness": ["4d0902aade6f58f8b7d35ae1fda73390c7bc5965e4ebc9672f1e606845ee10806f002d94a96e12df5082f218e7baf227819dfcec4d27037e3c3392e82161e13aa9ba496538c773f503a94d7708b61ebe0f38000fb23a2220fc199a6b6b56ae8999dad05fb0eacaf4c3141da64bf2be7ffa24ed4986a26c1c8de433e5125cca967112adb967f3a1b9f3c4b1017683599fd0d9c94def03d9c12873437defb7db0c60db96686794d88ad96572d05fcf57255dea02e071319a3666efb14632a8fb2329a2e7fe20fe1c8ee77ec2298dc5e573d5fdac59cd8a26ac05b987c47ec8f57364cd3208b7efd35f8ea7746819fc0b164ec561d410b5e12d34102f38b067664b2af3efcbc25013e35aa61c7ac4443eb6680af87d844fa91736070045b5435279651002c0e829528383fef6a57a1dde5423eb94e1b41bb07d2065c9ec411f0bd1eddea2184e9b886e4e39c696da976834e2a98ee84e0f57252d58ec28d28b46dcdf4d5dda3ad185e6fc19af7758435fd3d5107a46ab726811d8babef37e3968243480fad3fe9524aaa61ae983e2a0e73061900731d534630644a62abbae72a64044d3d55659b6995dbb07681afeab530cf18d30617a9d1418ef86a91984388e9707ca3626416cc5b6d1afda0045f684e1d9a0e4eb11feb73d52c37d1902c34141b2944be315375ae2d705f2e7eb183be3fa3f8bb12d9ed2ea546f64315b961d9b855f31b922d4d74ed5f4b9aa75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082872b08559f184ac3ac9956d54e492d7f98285a254bf010e00b63b6bbe75054353b7ec1fb3aca1c665feb629f75b86bc6796ed5eb830658d68574ea157b89fde9"]}}, diff --git a/txscript/data/taproot-ref/d60ddd04ef59ce7655ce0640bb9f05a050c50572 b/txscript/data/taproot-ref/d60ddd04ef59ce7655ce0640bb9f05a050c50572 new file mode 100644 index 0000000000..97d6920125 --- /dev/null +++ b/txscript/data/taproot-ref/d60ddd04ef59ce7655ce0640bb9f05a050c50572 @@ -0,0 +1 @@ +{"tx": "1d7233850360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708c010000004c7f1e8bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf76000000001971cdc460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706001000000c78a86e4027ef68b0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f877bbf5d2b", "prevouts": ["4e1e0e0000000000225120c45578f833be1999146583d65d32aef269809cb1ed8bbdb950ed204b8b0de0ff", "19636d0000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "a6081300000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a6865d40cf942811304c2da2a26fa22b20d7be7d75ad42e96fecbb30c380f98d0d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3f2a2968b4ea0558d79f1ec3cd2b8a530982c6b5ad0be17180e93d11bc09903133cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045a6e9c603f7f99515daebfc2839154302ca67407333b540c062b355b85f19a07ff2a2968b4ea0558d79f1ec3cd2b8a530982c6b5ad0be17180e93d11bc09903133cace0aa47e1a0afcba116b3dffe01d164ab3e15a9a2b15599aaabc05c638667"]}}, diff --git a/txscript/data/taproot-ref/d6114c41966cf276af2ac91a43b0dcfdde3ff6ec b/txscript/data/taproot-ref/d6114c41966cf276af2ac91a43b0dcfdde3ff6ec new file mode 100644 index 0000000000..82d45ccf9b --- /dev/null +++ b/txscript/data/taproot-ref/d6114c41966cf276af2ac91a43b0dcfdde3ff6ec @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4001000000f6f17dea60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701902000000d12b24b1025b3564000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787911ee449", "prevouts": ["6b4456000000000017a914269f407e1403e9e55237bbaed7146c0fbc0fe6c987", "b6a71000000000002251201649567eb00a0fbdde29b894a99c9dfb586a4dcbbedf9e66ed23f8b13544bc3c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "225a202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["996a028585cad8e678304597bd54ce9798c74f6462b9feefb83c1e89c082f298852c39340930c5dcc9f33fbc63ae68f778283660b365deb431d667da2f8da5c5"]}}, diff --git a/txscript/data/taproot-ref/d64045b67fe7d9bbac6b1955c9709dc8f62c2574 b/txscript/data/taproot-ref/d64045b67fe7d9bbac6b1955c9709dc8f62c2574 new file mode 100644 index 0000000000..3b92677df7 --- /dev/null +++ b/txscript/data/taproot-ref/d64045b67fe7d9bbac6b1955c9709dc8f62c2574 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca8000000009decf0f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127016000000008d9b95b7029da96d00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac87195644", "prevouts": ["6d105e000000000017a914ca8d66b8079fd8386ff3ae1d10b869f5605e693b87", "404511000000000022512011543fb5006d5ad7e809c5c2abb17f794bc49d4d5bd86d23c4ceb0e33576d3ec"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "1651142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["951bebd424233f0904c77bd753db297cb4475b0567ee71cf6bedaca2ce86b58e9fdd40fc2a73908e92929fcddc80d5e9cd4516b87b9ba6e66634baf24db55102", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/d65a0ff7ac01950da5c822d87cd1f1b94663c71f b/txscript/data/taproot-ref/d65a0ff7ac01950da5c822d87cd1f1b94663c71f new file mode 100644 index 0000000000..27a1683f5f --- /dev/null +++ b/txscript/data/taproot-ref/d65a0ff7ac01950da5c822d87cd1f1b94663c71f @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2a0000000037452ca28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ca000000003ed3dc9a0168c22d0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fca639323d", "prevouts": ["1e6c240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "06ca36000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_57", "final": true, "success": {"scriptSig": "", "witness": ["17c01d2ff743f9966af357e3451f00a8fa83cdb2de6f1ee41ab22e4d1b86e5eb00833d2ab3b114006fa03e1caf9671f267949345f4209e3b993a05690397994482", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["d6fa3e12cc67ee12b147999b55629328538f6b6653a824d66ac3ddcf288321aacf8841c9d76cc92fe19dec3633cfb0f829195429852d9357c80482474b1e8b7f57", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d66bdc15b3bc47537708b688679685d7823933ec b/txscript/data/taproot-ref/d66bdc15b3bc47537708b688679685d7823933ec new file mode 100644 index 0000000000..aefaf04d40 --- /dev/null +++ b/txscript/data/taproot-ref/d66bdc15b3bc47537708b688679685d7823933ec @@ -0,0 +1 @@ +{"tx": "c3d0c9e202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf390000000058e04188bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfba00000000df72ae8d014799bf00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf6020000", "prevouts": ["18f26900000000002251200f726ea607d510d2ad25fd6aa0b3aa5046595182e7375298ea583ba69075a433", "51817b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_28", "final": true, "success": {"scriptSig": "", "witness": ["1a78064d35d88fb109a98f8de6282d7909a6656b6f6df24d2e8dfd5f00ad80db8503d49cdf084b5d6bb23f1b0d7fdff85b9d09bc1603cc797f66c9d03e02a0ef82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5d1ac27c784be09b0899437baf038c3371b483a8b88ca09d7edc6413f1db830b82c16690ef04e1c208c7ba0ac6cdf86725c9ec6fa639aada8eeb572e7ab8d4fb28", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d6a9e0d913d7e024afc093007237124f4a34364c b/txscript/data/taproot-ref/d6a9e0d913d7e024afc093007237124f4a34364c new file mode 100644 index 0000000000..36cfd1850c --- /dev/null +++ b/txscript/data/taproot-ref/d6a9e0d913d7e024afc093007237124f4a34364c @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a700000000d7649d888bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41b020000005bb521d202828c7d0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787ef020000", "prevouts": ["68bc400000000000225120fd6d9780dc4cf57c79720b9d63f8d64d8d63d8ff447ddced8591f521343270ca", "10fa3e0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638368", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a7f496087fdd0464c266da8b16ca4acd01559ec68405b54c53e2b4568db5223db0bdfd7fd43775a37ae3e20c8f8514aca25517db969733cf8d9f690f9b6d8ea23f980255362d30444bd4a09dfd60422f4fe5b70b7cde78729ca8cd52cb50aace"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93650ad14178052915368d31081c43d3a6fa89eb4eda43da202390c5f626134fc598e881bd6493e98dc576a1c76b7dda488b188d283086ec2219562e3f5b97e3fb63f980255362d30444bd4a09dfd60422f4fe5b70b7cde78729ca8cd52cb50aace"]}}, diff --git a/txscript/data/taproot-ref/d6bb41e59dad21fc3ff2d5bb0c784b27307ee4d3 b/txscript/data/taproot-ref/d6bb41e59dad21fc3ff2d5bb0c784b27307ee4d3 new file mode 100644 index 0000000000..d0591cfa2e --- /dev/null +++ b/txscript/data/taproot-ref/d6bb41e59dad21fc3ff2d5bb0c784b27307ee4d3 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6d00000000c3f473d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf60000000080c431b7017add220000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796f31d0d46", "prevouts": ["61587600000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "76ed4f0000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e148eb929e36bf5d0ae927afe6ca96e40c19e477115e42779571d6d91d45ed5d842c4c20f1fedac94edf4ee37dcf580edabb0aa4839378386ec3447d53f529f2ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936724f9d0df23615753016e7eb8d62571c0b8a17dd151f7df09f79bc44b2e134251de3578bd50e4aef3f42172206e28aaa53f32c3941b8b4ddcf806814652917426187254dcadbfeb5c8509faa2902470872e97e8359524e33e4df3f76314d708e"]}}, diff --git a/txscript/data/taproot-ref/d6e668abcd05531d83ec0bdff606bec2368882a8 b/txscript/data/taproot-ref/d6e668abcd05531d83ec0bdff606bec2368882a8 new file mode 100644 index 0000000000..ecfa4e888b --- /dev/null +++ b/txscript/data/taproot-ref/d6e668abcd05531d83ec0bdff606bec2368882a8 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127085000000006a1e55d2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd30100000063e1818f049b9e8f00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478706bd7426", "prevouts": ["4a4a0e0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8", "868a830000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["ef4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fbdd38c28c61f1b7a6e8ceb22fbafcfb9b20df7a8d7411fb9f5b9067992d68d9921261d9825d6464319e11fb6c7a9f7c01f613629293fb1fa80574c155a587736c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821645f371c8079005f8f776d501e78f2a21020e20da39870ba1dbf85c4a15b7eacc28207c7af5a37f80d9c7bda068b6f89abe5b5cf72eaf80ed3e31c2f1c9dfaa6c6fa26e4842a5ec51b34186b71f91671a7cf578e5677dc1f65db5fd4f943bbd"]}}, diff --git a/txscript/data/taproot-ref/d6e9b28f9645fdf80b2547f4a875bc298680a83f b/txscript/data/taproot-ref/d6e9b28f9645fdf80b2547f4a875bc298680a83f new file mode 100644 index 0000000000..f5665bf0db --- /dev/null +++ b/txscript/data/taproot-ref/d6e9b28f9645fdf80b2547f4a875bc298680a83f @@ -0,0 +1 @@ +{"tx": "971ef45d02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0e01000000bea1139a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127071010000003f3d64ce026c8d91000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac6b0faa40", "prevouts": ["a3c78400000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "88c10e0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/empty_csv", "final": true, "success": {"scriptSig": "", "witness": ["73936867cbc752d6d5e918c808ef94d2b30a081fc0afbac71aeaede820c61f1f11edc6ac869e18b547305f11ddc0cbaf702ade19a9fabd35a044b883ddf20f23", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313ddd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bd74920921194c3fc66d38202825db8e721d0743d3d0e753f82fd9a2f6e54313ddd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/d70c950a9b6157fdddbd8eb01fed07f12638844f b/txscript/data/taproot-ref/d70c950a9b6157fdddbd8eb01fed07f12638844f new file mode 100644 index 0000000000..ddb2d85b7b --- /dev/null +++ b/txscript/data/taproot-ref/d70c950a9b6157fdddbd8eb01fed07f12638844f @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fb010000009399fa4e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c300000000bad4681203ed4f4b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3cb80434", "prevouts": ["c70b100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "38fe3d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_19", "final": true, "success": {"scriptSig": "", "witness": ["c3f4e2739cfee480f6ce6755af8338ea541ce1cd0f6ac85f766a96f7c3bb5754771260a7145a087bff6e91d1e8f665c3c9c5dd3586375643896565f93b09be2d03"]}, "failure": {"scriptSig": "", "witness": ["d34fb7972d268a6402aa623cd67a508390eca4d74388630af9a0ea472db609338a03ce2e47cea6044ebd34ecb4ec2a8c5b2215a5c0000bc9ee43f062b36e627019"]}}, diff --git a/txscript/data/taproot-ref/d71a3d01673ec097d7272cd0fcf4fc12f19a90e8 b/txscript/data/taproot-ref/d71a3d01673ec097d7272cd0fcf4fc12f19a90e8 new file mode 100644 index 0000000000..8400678164 --- /dev/null +++ b/txscript/data/taproot-ref/d71a3d01673ec097d7272cd0fcf4fc12f19a90e8 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cee00000000168bbd8bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5e010000006458ed8f0459b6b50000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a607030000", "prevouts": ["7ea84f00000000001658142540f27e90740933c99d4f17ab2dfc6c82951cfb", "3dc468000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402202fe46beaee17fb95603445977dc6d53128815ceba0f497af5fe350f08100b10b0220258c6c4336316098609c532976678a9be7902bfdd66f3de0f486b163ae25f0c6b4", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["3045022100b5d13b2d25ebb0103c87080c4d506c47742f160549632a71ce11621c880d174902205d1d676eedda2b53d88c32d26353b79db0ce9f65e853b368d4def62572c227bfb4", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/d72363609fde245d8d04d59c1d9e2386e97f61ec b/txscript/data/taproot-ref/d72363609fde245d8d04d59c1d9e2386e97f61ec new file mode 100644 index 0000000000..1fc4a7deac --- /dev/null +++ b/txscript/data/taproot-ref/d72363609fde245d8d04d59c1d9e2386e97f61ec @@ -0,0 +1 @@ +{"tx": "b8a0e6aa02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7401000000992304cfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b58010000007f10f6d10409577100000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7abce484b", "prevouts": ["81ea510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74d5210000000000215b1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_7e", "final": true, "success": {"scriptSig": "", "witness": ["72e42b800386932a5c1253e07f7d7b49da9ac834ad3a47c835ffa87c2508691f7bf7a5cd0cd5626c428c2c57e2b676ba33ec961cd3282f6e600750a5df670cea83"]}, "failure": {"scriptSig": "", "witness": ["01c0bfbc0cb79388da00eeb21138d5db21dcaef99fe5dd2af7f9b3d063f3770e016fcc32cbc341cff4c9d3d6aeea9c2da9491d0405ceaf83815e0361bc0b51347e"]}}, diff --git a/txscript/data/taproot-ref/d73e808e6fe07bbd4cac3998bbd227cb333f3860 b/txscript/data/taproot-ref/d73e808e6fe07bbd4cac3998bbd227cb333f3860 new file mode 100644 index 0000000000..8c398c9caf --- /dev/null +++ b/txscript/data/taproot-ref/d73e808e6fe07bbd4cac3998bbd227cb333f3860 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb600000000b0eabc15bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe500000000b52cf8660410c1a200000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47874be99750", "prevouts": ["4bbb220000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "61aa810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ee", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e11ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900453225856dd898bc2835af0cd8c351393955c132e627f28271e91b4e6043d8131340899fd8696dac9e3afc960f0a100b615a3c324ed3a125e98af98336f748ba56"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f8c1bb9e22d4bd0c89749bc52dae3cca8ec48a5f1e8dfdaa19896840c71bd601ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900453225856dd898bc2835af0cd8c351393955c132e627f28271e91b4e6043d8131340899fd8696dac9e3afc960f0a100b615a3c324ed3a125e98af98336f748ba56"]}}, diff --git a/txscript/data/taproot-ref/d7435dd29bb609d8a757deda3c46bae9522fafb0 b/txscript/data/taproot-ref/d7435dd29bb609d8a757deda3c46bae9522fafb0 new file mode 100644 index 0000000000..cfdf6eab09 --- /dev/null +++ b/txscript/data/taproot-ref/d7435dd29bb609d8a757deda3c46bae9522fafb0 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8d01000000117807cebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0d01000000ea8fb1ec02e7b0ce0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898749102860", "prevouts": ["7bdc65000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "e5246b00000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "48304502210092a855718f24f2886aa3d91e0f75399fbe051333c27010ad6e4507836b56535502204b63cba97b2b03a57551a44a74d9f5134282cf638e44735be1b5edce8149d1ee02232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "4730440220262f9e4d589ead27052d908d18769296c446c083c082f3f763e12ff25fb9d75602206e2eb3c67773345306ae4ed2a1d42774a40e2dabc2c2acf0a1ae01226dca153c02232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/d747c65611d3195e76faeea3dbaca70f0255d690 b/txscript/data/taproot-ref/d747c65611d3195e76faeea3dbaca70f0255d690 new file mode 100644 index 0000000000..07de01f12f --- /dev/null +++ b/txscript/data/taproot-ref/d747c65611d3195e76faeea3dbaca70f0255d690 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfac0000000017ce8cabdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5f01000000fb96d0ee013f6e34000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787bcab301f", "prevouts": ["18dd840000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4a3e5a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_17", "final": true, "success": {"scriptSig": "", "witness": ["526f44df0ce6e752ac2884b0626b8e7a7f0084f7c024c112c8e0ca4c80cee249cea4426a37dc15a8b4ed5e7cf6440df0ab0e76c58b0f9b7a32135cde3fef077f82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["bf4aa0341f2ca2f234bbe493e34014b9b9b485dad45bb34748e352c6afbfc2ac14b16023b240bc1702e8f37fc40ad3ae0de9b01e4bbebee967fd48f87c0dcba317", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d7482427db68b72ab957e74167dbc8c28842b070 b/txscript/data/taproot-ref/d7482427db68b72ab957e74167dbc8c28842b070 new file mode 100644 index 0000000000..fb07f9fb66 --- /dev/null +++ b/txscript/data/taproot-ref/d7482427db68b72ab957e74167dbc8c28842b070 @@ -0,0 +1 @@ +{"tx": "ea6657fb02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7c000000006ca5e1b2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c82010000009c4ddacd0182ae3b000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487178c3054", "prevouts": ["08b54b000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "d0105400000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6abb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b3e5a0f5e9e7b51fd9351e97ab2875ce03ea25b7f50ee6c9dfbf583fc643f52ba5ae8cba4ed1cb91f8a2ddbe7d0c8637ea6f49c0896515a628c3bea1aa465996ff84cb0de1f41d907799f0bb3a3d4c37b57eea0ba754203aaf5b7b2671fe888a4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361e30f0a1ba0bac296285a8eeb76649cc75d9671ad0bf9d85d254b2b980baede83f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d0e13bd92b8f417e9a9e83db8f63381783cc5b261abc3d56b5d515d800102f0ba4b6f827e9c7b2c56d61f57ac31f0aa4c5b637b7f763b3a1a4d37c3a7fd6ec38"]}}, diff --git a/txscript/data/taproot-ref/d7491a450345ac8fd8bd2da583d6974224917a83 b/txscript/data/taproot-ref/d7491a450345ac8fd8bd2da583d6974224917a83 new file mode 100644 index 0000000000..4773adf767 --- /dev/null +++ b/txscript/data/taproot-ref/d7491a450345ac8fd8bd2da583d6974224917a83 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c21000000006dfe2883dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc201000000b98404e201166f0a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a627f75b52", "prevouts": ["6cbb5b0000000000225120d767e62fcc8e1bdc4b74e073e2be32f51425a180d82e9ffb428311c4083f028f", "dcc01e000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d5777eda6ae5c204d690125e9653b41f5769ac9c6851370f10250a6b2ccac04ea2e4b018ae467cd9e863b5163b939197444cc55447de8b2a8f3873419df9a4569ba9145594a303a5de701ee272913bbdbdf833a16e266529740eba3398a826c4475381071377a904a3ab61e5bcdb977b8678744db0e4e43e9c798254dd628b4760105c23156fd1782b11888d55d8ceaba6e0ad858e98aa76f2b99916ad1542e3abc774ef2c9ae78b994dfdfe5cf95aeab76f0ffae9fba9c9141d0cb6726431a9c49c274462ebd1ad944b974966f14004f3285dfe51a242b73def7cece22c6a6642ed45196c98e53e403e074c47e5818f196cbb925d73ef54372edd2a34cafb8930d878eeb01e0cf9afe66cf2b67c0c5996d8692b7dcb6735aeacbad052570f29707cbc3051a8942b75a7bc478116fc67d99645aa5d96b210d6388f1eed11b8a512a559d326fe6e47e33f732eb68374a09d7ee85afa7f75eed7b5317da716d76979cbe3eb93b96366603b0d4b0acfad56a1662731cfa070d400b3f775ea595bf4d21f8e66ec48de8ea1a86b42b78d5d87e838d7b86ef4fb830f3edfc2506cb9ab4d466fae8e8da46716ca15d34afede50f374b22d59793f67ad361721a34f382ecb3024fc10c0d8c404509025aa759b34fa5950337f5571be7b59cb570b2a8f0f18b61864f42c4e91c546ed4ed23827cc32ee879820bea642d9c295d68c0ec8342e94da1d5cab92bbeb758e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93696c72109085338a697f752fc7c68dd136f18d7357ab421c630a98b1ec147d871b7a2231cf916c441aa882850e5209a465c1bf953237149df21eb7dcd7136fa198d550033184c6424688af85d43f5bf525b7f6d8111e731f6e2359cae2801b117ed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}, "failure": {"scriptSig": "", "witness": ["4d090296865444c72a6d3120f5231f82ef03374c3d40310f2bd583b251ba8b90a2594086cfa677d21b49a5f37209dff62a16f1ec505260d9c77e6285877315b6a49908a7e97feaaaeee4268a1f0a7209e1dfe6d76154dc287215c40b05357d3d370048dca2114bf69b69661cbd0e15cd662221679d6f513dcf4e27cf6e81f6a4be1a146e0ecf7faf2c73e0464b9769b122a81450a8ff7bf928454a2d9af812711387ced726142455b36b6ecf69c44ad108e716f767c50012930359f8e78440b3fbd7f1f35f70d1120b440649358a9f512eb8ee80adc0a97818e8153db4dbac2d38ee803fa7a47f36be979039484bfe98b550d7111cb7a8a6c4d4c3559f3c8e6707bbfd96c1ed4011e7ce14fd29b42202f1ce9696867318cbe460538c246af18a23ec56427fb9e44a0686db068cc7c086d3bfbde2983e594beffa36af4b1a1c3e84f250a488f75e7b71b61a3ba5c66a3fbaccaf2ed96680efa1add34daa7cb53b6180e93565d3ebdd08ed4fe6886a6206540f87e2abdad1248cd61e3536ac24aed9dc7238c530b0094fa0d4b793557e0035cbfdbb59b5daf1cd19bef17d05c9b943d555222ce4c899ceac0ad7662e0670dd909606615ffdfe811e2e54236522ae1c9e631fa8179330482ed448d67cb7c94f16fe24031d835ce7dfdd35b5ed75e24ee6ad87dab103daaccb1ae515e0e9b5704ad035e5140f71ce78875274df9a609ff5aeba5cd40faadcbf757f7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368956bfaa7088a8d3f86f6b7188e51d428c43bfe63f671887027ad947d21b21d5dbab9fd6af1020d04f0143fc46ba56c091000bcdda14289cb5d3981fd1d5b5a654f33cd0b31c9bc4dfcaccd89caa263c020d1b70f58e7e0e884ce19a773d6b5f30b2981ae69232c3f6c5ff759e9ad4102f31f3fc5e7a3a4ffd34dce2e2e06026"]}}, diff --git a/txscript/data/taproot-ref/d750ca1379d7933d2b0750e621fad549663516ca b/txscript/data/taproot-ref/d750ca1379d7933d2b0750e621fad549663516ca new file mode 100644 index 0000000000..7d9c383e1e --- /dev/null +++ b/txscript/data/taproot-ref/d750ca1379d7933d2b0750e621fad549663516ca @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6e000000008740a6c30102fd1e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcec030000", "prevouts": ["bc6524000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "47304402205cf4684ac9f00685c2dd185c79138189aece15e2bb9b0453df083311130e940e022068495053305437fd97c5460375b32b7116dc177cb4b61e261382d3646c36cc2582434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}, "failure": {"scriptSig": "483045022100def79fa8580f7bd10e0714593f232c9a681e9fed41a16e50eba6419d96dd75d1022048ffc8eed8b18c2d5360cf808a969c4b485569d73778e6b5b8b728ded2843ce182434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/d762cef9eb8735ca5282dea549336970c32f0470 b/txscript/data/taproot-ref/d762cef9eb8735ca5282dea549336970c32f0470 new file mode 100644 index 0000000000..a2bdb6ca81 --- /dev/null +++ b/txscript/data/taproot-ref/d762cef9eb8735ca5282dea549336970c32f0470 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3100000000c6e677ca0122dc2300000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac33000000", "prevouts": ["22285300000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d4a3aa954d99a0808b2bf4a34eaad4b274a9f5644d16bf38e374bdd4b78dc43f514fdf9f9996eac64dea8e2d2f21992353683b4356a5ad33c6e291ec1ad35138e6f79db5018c5008c2793fb1616ea93309d5c027be1e59893d6060c71a6102191c898158b7fcfb160f80fd5a667319a26ed738f03d0fec7f5e21dedc8e58f7f5a44725dbb915d52a1ade336e1339991650ef5fa3bb4246712940565ed8e61548010f17bef50d4917018cedc3dddfedf9a36d70eb639f570f56bc062398b5fad3f0ea524f69fa6a81ae3f19560f4a4cefe79970059ff1d1da3061d66c8ca69cef782c7a5b81b37151588088925ebc1fae398b78f0bcf12dfd8320cd0929f09993bedc48f67609f5c1489d149817bacb77a5e8609ad9e118e9e6ea76300cc4dcfbc299ccefbd49fb04b6be370a8b523d8576b68939c6177a0807392a47a77b61201fe8471251870aee32be6e7c613d4d558c65dd12cdb1ae3615b0314d74f7c2dbe1a78f0751eb7110f9674191ab1f6ec20f5be9a9390c1f878138681a15e2576aa4e49151ef0d4b3396b24636a4ce1b4820072529ceae8f9c653c1dacdefae7473153ab32cc22cdab23dc5eca23330795cc80f0aee7a25f6d319d6a7270e2164f9dbcf6886681b5984782976d20f6289144e2ac179aab6939179c3d26f1349fee33f84d3a82abf2f18b57c552b1396a7f529a0cbb15d4806b89f2d24a12ded8a20fd5af6371584849bd75", "f47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082bf93feda87a2a10f8ccaf134f5ef6c2a0b95d03f8827da72e1e875b6e78a8a5e876f4540117e7e2fda63f7a015ec774d613b8932caa4388fa9ce7145d42cc7f6"]}, "failure": {"scriptSig": "", "witness": ["4d09021557521404173230fbd3573c8c228fd0b9da648409807110bf2c67922313c66ec8fb89ff95aac79a3ff89edbd68e27331d93267c3f3719ae65ba121a05e632cfeb78511a65fb00c6fa7cc7204ffa2deb020576ac4293ebde75cc7b5c29196e8fbcb63a4d2193a32119a43a957eeca7400be342f72895a80fcfd70cd9a8756722a4e057d5bae6c3bb9f9a72b7f7a5ce0e338589d630f06e17c253936a2dc9aa9e0b3a44fa6751f52dd57f6ed02d4cd3e50c9d54d172bf193ef665686f04a97d54761c945de1101bb37a44b978675835a1b875a226d5865c4d07abf04a5c3c9ad5bb54cc751c520f96e9ec51b31220ceb32d8ec7a9d690945f14319e017042eb34ed69b4f6de74f20c44ec7e165d7350ff78b0af3fc2e09efab06d14e3bd1b81d9753a284d712cd7ed72171254780579af3da233fef20f9c5d4d691db1f208550fd69158536a08ca9844e0746b0c49c31da77004aa3b1469e41ffe2b6caa7f056872b42227f8f17a59b5738a9c257a832f32e726997bb7326040df2522b245338d4b81a4e2d0d4d705e220063f1b0946b27731a3596d8aec95ab8a8d2df9ff6f21565506a180974a3485301cd1d41bb54efd8766614c8f14bc116f6e02f558577fc1743a3b7cb7282bc6eba0eb4ffe198cf5e1242f06bae5260975c84d73f67d5bda21772649faabb4b03f24c1ef26af2930d1817218ea73607b2645e29f4589f786372b4123e9a6a5f275", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd6cb83260dd517d361871e17e0728affb238ee2bec7c6aec1cb32ffd91f6217defbee90a18838bf61213a4f1f5f31a75e180b842cfb60d5f81d26cbd38f8652876f4540117e7e2fda63f7a015ec774d613b8932caa4388fa9ce7145d42cc7f6"]}}, diff --git a/txscript/data/taproot-ref/d784977d5fa21c31f0f510f5a1e2d50f7815c63e b/txscript/data/taproot-ref/d784977d5fa21c31f0f510f5a1e2d50f7815c63e new file mode 100644 index 0000000000..365dc1e5e3 --- /dev/null +++ b/txscript/data/taproot-ref/d784977d5fa21c31f0f510f5a1e2d50f7815c63e @@ -0,0 +1 @@ +{"tx": "d2300b08028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40302000000f7c3138fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4401000000dfa691ce01a7032d00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac6b020000", "prevouts": ["21ae390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "358e5700000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51c26d78b90df0408cccf5a173a397f35b7225b23776926a85911da6ca9e3721966081f43f8c34257025162ccf1daca48ae61c99356c3eb24d5601d3c52dd9de2a6f5053dc49cb92d20c30fe5ab09c589302aa9886b9c794d18405aff33121a169"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93645ced882a1c46bd68a59c6fcc58699bfeb6e11a3b6e75b6ce8d2c57343bebb685d4b392b2e4c368022144328e009ed21ebc6df76a38c37cd5c7ada1ffb4033c71a4e7a29e9a68a1d6e5ccf500c3bde1b862f2704e441e939992f2bf5a528056a3bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}}, diff --git a/txscript/data/taproot-ref/d78a59aa9fae45d7cbfb5d42a6d57744818f4f3c b/txscript/data/taproot-ref/d78a59aa9fae45d7cbfb5d42a6d57744818f4f3c new file mode 100644 index 0000000000..0abe869050 --- /dev/null +++ b/txscript/data/taproot-ref/d78a59aa9fae45d7cbfb5d42a6d57744818f4f3c @@ -0,0 +1 @@ +{"tx": "48e98f73028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d8000000003dc93bfadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba4000000008f1f5de404739f53000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87e995ba23", "prevouts": ["5d97310000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "9d9e2400000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "483045022100d30fb719d1875c3c46a98de77aa793514cb4e060b327e008fbf9a49a1fb4dfbd02200dd642d886252d60c35be8083cc2c2ef6f299c6b8e97aca1a620ab49de5f700f01", "witness": []}, "failure": {"scriptSig": "4830450221009426393fad42dc8e3a25b09f48fd67527c6c34835b9bfdf3efa36ee170f652d00220217d0f35f8827a01b873d11ce17f14715db62d7b9b383a10e0bd6b0347f8fb2601", "witness": []}}, diff --git a/txscript/data/taproot-ref/d78b2cc4912fce258a371b34976f623504f00bf5 b/txscript/data/taproot-ref/d78b2cc4912fce258a371b34976f623504f00bf5 new file mode 100644 index 0000000000..023dc1f7fb --- /dev/null +++ b/txscript/data/taproot-ref/d78b2cc4912fce258a371b34976f623504f00bf5 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c425000000001d54d0dc0137222b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709c2562e", "prevouts": ["ec0b320000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f24c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b5c223b2b99456872194ca1969830bfef335ab1526807af314f38e6ee168621b20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1c56c8a32008d6f6a63b4b8ddfaeeeddf640e9afea8e86008d2331d68e9435ec7ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb3b0196023257ba22828ffd68cac8334c8e9a2a606c57d60a81549d8eadaf9727e2cee51cdefa725eb1f8255cf98d00ca42f29f054478581d82ff254acc1f11842c4c20f1fedac94edf4ee37dcf580edabb0aa4839378386ec3447d53f529f2ea2726256ae6b84713fc66a1300a8292dc92aa88ab82f645f24355049764a6c4"]}}, diff --git a/txscript/data/taproot-ref/d796184dcd2791587af889f67ff0bd146da22bf6 b/txscript/data/taproot-ref/d796184dcd2791587af889f67ff0bd146da22bf6 new file mode 100644 index 0000000000..b5429f05b4 --- /dev/null +++ b/txscript/data/taproot-ref/d796184dcd2791587af889f67ff0bd146da22bf6 @@ -0,0 +1 @@ +{"tx": "70ffc10b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b230200000009cc2dafdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3901000000dc9f8bc8023bb179000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787fe43162a", "prevouts": ["1d03210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "85905a0000000000225120d10cdcba7157d8df26718afda7706aaaa427ac1b5d7e5fac924a4c3a7b738d66"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367515070ee7198470edadce4815bf305ab61e24283d7b82873b83e6e193884685"]}, "failure": {"scriptSig": "", "witness": ["6a8c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/d7a0524afa7b58f919577fc272101adacde12154 b/txscript/data/taproot-ref/d7a0524afa7b58f919577fc272101adacde12154 new file mode 100644 index 0000000000..82f5b9a1ee --- /dev/null +++ b/txscript/data/taproot-ref/d7a0524afa7b58f919577fc272101adacde12154 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4cc00000000b8f83b5e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b000000000ea20edd1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7b010000009599d10e01c5f72d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac71030000", "prevouts": ["f6d641000000000017a9141757f4686f091b43a46fa47e92d07c87fc7a205e87", "5b42100000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71", "0c43250000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "165f142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["aad4d413d20b93ea249d3e5b97cd97a840de55d834d32fd568d08b78a552527f58a0f6b25ef52bbbd9d5b6a44f3865cf7ecfa8a812f1dfd3dfad4d158881d217", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/d7ae7546c73cd724ed329a7e111b1874f3fad3a3 b/txscript/data/taproot-ref/d7ae7546c73cd724ed329a7e111b1874f3fad3a3 new file mode 100644 index 0000000000..5bfec08c3e --- /dev/null +++ b/txscript/data/taproot-ref/d7ae7546c73cd724ed329a7e111b1874f3fad3a3 @@ -0,0 +1 @@ +{"tx": "64f4e4390360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707701000000fb3218d8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ced0100000081e9f5b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcc010000006137ffcd047b7d89000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6034d4655", "prevouts": ["3d9412000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "be405700000000002251208ab07249a1fdfb04b130308cc651220c9430f0ee7d7b49fe0191e15183fe6b9a", "277321000000000021571f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["8f0324b98e4a688bc8e9b083c101ac36cf765277408c730c20d51e09aa664a607b2ce3280a394734af3b1693e8387e167c6fae4d56b86da1cfd2e115cd7aaa2d", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/d7c12a570bce792607b3d5f23fc34ef6392109de b/txscript/data/taproot-ref/d7c12a570bce792607b3d5f23fc34ef6392109de new file mode 100644 index 0000000000..c0b3579efe --- /dev/null +++ b/txscript/data/taproot-ref/d7c12a570bce792607b3d5f23fc34ef6392109de @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cce00000000e19e8a348bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ef0100000011e89353dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0c02000000b3dc5d44043c69d900000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac92010000", "prevouts": ["d9e6520000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8f6b320000000000225120d70bb5030b4517d64d2a3c38713515b320a06334d0ff9db76c903984d8e384a2", "bcc555000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c5", "final": true, "success": {"scriptSig": "", "witness": ["6c51571d1e64c9599f61f1ea0bce152c3d229e809091a22321e757af056d247e577257d9d9cda5806cf10e78a471e4a104b369a91e3eaea1a4c6dba8b69bdbc701", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3bd704f7d6f451f1604ae63a01b60d188ea3642f7abb2a6cb93f488a329c74452395e75ee8ab1dc41bce85be9e945120119418ec10d6e58258d9d90fb9c7d451c5", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d7d1782dc0b7c5e12cccab548a33619bf58a1db8 b/txscript/data/taproot-ref/d7d1782dc0b7c5e12cccab548a33619bf58a1db8 new file mode 100644 index 0000000000..94ae53cab2 --- /dev/null +++ b/txscript/data/taproot-ref/d7d1782dc0b7c5e12cccab548a33619bf58a1db8 @@ -0,0 +1 @@ +{"tx": "f8e59ec202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b020200000080e71b9e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d01000000ff9dfcfa024f03350000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787b5000000", "prevouts": ["2b8d260000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "b21a100000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936626685b331694d0de841e58d95d1842d28c3900fed13098d035c30bbed037f96e5aa467dfe2257bccb94fb5bf6723e840de90a3890266560a9e3d72c84089f55cf37d2bf9ac9d65f4f9542d60f6497573c04b4d7313f44a5c611386102890a1c"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045716f66701312fe6b613a3a288c903128f650d73beac5c480044fdeaa8466574a9dac82751ef42f4155e8d0286eb609cd4bc8c8b3be93c107754fe282612bb362f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}}, diff --git a/txscript/data/taproot-ref/d7ed3928aecf2d3acbca2fb8d2ee7775f7f52ccf b/txscript/data/taproot-ref/d7ed3928aecf2d3acbca2fb8d2ee7775f7f52ccf new file mode 100644 index 0000000000..9588a724d7 --- /dev/null +++ b/txscript/data/taproot-ref/d7ed3928aecf2d3acbca2fb8d2ee7775f7f52ccf @@ -0,0 +1 @@ +{"tx": "1dd1ae6902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce500000000026e16df8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4100000000051563e9502ec56810000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc2caab52b", "prevouts": ["e99947000000000017a914de933560a9a700a6d4f856bfa5cf61713cb34ea687", "3f4a3c00000000002352212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "235e212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["b1b7dd95dbbc4cee32ba2d986ab178ae22de42cf1b059d3f8356fb5e12a6e7588b901314fc23e0525185d577ffd9102b11373a3a6ac4c901d530c8474f23495d", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/d7f54f75c60667b7fd883f34d666d917d0b88809 b/txscript/data/taproot-ref/d7f54f75c60667b7fd883f34d666d917d0b88809 new file mode 100644 index 0000000000..e14fb1a3a1 --- /dev/null +++ b/txscript/data/taproot-ref/d7f54f75c60667b7fd883f34d666d917d0b88809 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4f00000000096ba8c2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7400000000156c38e103eb5d8b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac71040000", "prevouts": ["1e47260000000000225120bf924c4d20f2c9cd0e276b93ccb8cc76d8c2c0447a0551ca648744a57795d235", "27a266000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "success": {"scriptSig": "", "witness": ["65914ed79dc6a229c28e0dc26cdeee837174dbe2710aa6a80d4782e83fe77faca7f46bc228a85982527e7d0748a105c3ef5728c5c2bb620cce3eb8944daf3af801", "aa7f0b81f4cb1cd2336ffad5dab8926b34399f1c11012c3a1e54275224f18b74e41c641cf9c789e0eb82f2b2ead830842fb1984609db3e4513d5004dcb38662936c6381aee07a8eb74934799299728e6ee118844e0ded5b15717e7d24d25ccebd8368e6d4fd71981f679d698a6b3ec1c4a124c1a68a9a2260a7b5265d26225dff4ea0b7d76ce8c4a92d656bdef5e5e6b775f5329dca0372a69f3c2357574762f5aa3424dbb2a632b81ed6e2c2095521864f9e86255a7efd8fcce33e56f784e7b04ab198dfd", "4cdc4916429dd43b46f96dbe1b92564950ea25319f017c28a3d59fc97674260912d96b90f24f18c0b44c5c74ff9dd38153bb932495b13acdc6c1f0b9304d843f165c0af0abb830fd641bcdfba64300ccdcb77a6e8e0faeae54ca0250603da7b06d7ebb64cfb0e5b5cca94c0b67fc26786c24e73cba1bd4da99114567a0b548a78f03fe08c62ce444163b256e8900a7401fef6af425f482ca2e86c695e1c17184f6f75bb21288a275b0df284f4fd47ec71ea061163991d67f9945b2217ddfae42ed4a3861523dc90f088a2d082eeeeb03da0202a78dca428c18740b7b658d6d3535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a251646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367fb5552ee6381cdc963f2111a6f573fcfbed929a5b7c4ed5b3a36f5e0db7ec66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc98b3c9ce3df34033bc3dd90a77b2b0db97c9c89981b5cf75c5aa87c293dde5a21e1620c18b37992f243287ac1416cf3325e32c6396edb12577e7662588de4da7928e438ad9fbe70f4d0badc06c7ee4c83ca813fca202605ce9f9b474875b982e0d55f0109232bc00dcf6dc13410e1b395cdf86e7f0f25d39d47923d809812313dd2594d6ac6f637d534b85c20b93114807839d2feb8bdd37a4ed3b0575f0b6bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa32866219c62026f7943059472a02015d9196422dc18cf32ccdfb1bc543c558bb77001a65742f0ec68ef04f1d1de20e1df0c901f62fdf302b0bc2e7cce56c3b25365115c24f001a1f7f6a466f6429ac5452b824ea332bc55da340486be9211e3c1557cbbec067595eb9403e301c9e5b7ac8d7a6875267436812a9f0e99cbea472635a14868093c7960743b4a3454dd3e5ff5639a2725f2433e65396d247e4d210449f63fdec596e5519c6eed966e2f0980b7a713615db5c14d0d64781166ded471a3b6219a83e6c68a031243b897edd79429041868667756862c9d1b38194a57f3d6fa22beb60e2897e24fcb4fe6f183151874d2e032bb70dce4e519d9632c234421d7622a200065f0ec2d551108c54d6bf63cfb84e70b5f86d0861e641f01f31a7f197a76b16e6c33df21de22f6872242719b47812d22907a96f1611514039a4aa8563b19c1d1d11250331c8705531967758c6a3336e611888684dcbb61c27b"]}, "failure": {"scriptSig": "", "witness": ["65914ed79dc6a229c28e0dc26cdeee837174dbe2710aa6a80d4782e83fe77faca7f46bc228a85982527e7d0748a105c3ef5728c5c2bb620cce3eb8944daf3af801", "9fedc5161501185b324cb50c457a91a7ba7c6e227cba17aa0392ab48f2fd03680d1d500e13fa9af4ed2cd6cc7add756725e40c8e6d4d3ed6126e66f09b00f84b13ca28d8d3bf472d6657d4cbc095463ea2e63abe54a309a8ea6b76c66926677a273a4b323f3e4aeb7ba746851a22abbaccd64fecdc7f1584883607a23deb3ac630a431276beb47b05f5f7375ad04c8a48591d0e7513d0a18936bcb9322e6e895eceb98185fd96373b6d4615290bfba32d462265411c42034c517c94f0ac20b609cc801c8", "4cdc4916429dd43b46f96dbe1b92564950ea25319f017c28a3d59fc97674260912d96b90f24f18c0b44c5c74ff9dd38153bb932495b13acdc6c1f0b9304d843f165c0af0abb830fd641bcdfba64300ccdcb77a6e8e0faeae54ca0250603da7b06d7ebb64cfb0e5b5cca94c0b67fc26786c24e73cba1bd4da99114567a0b548a78f03fe08c62ce444163b256e8900a7401fef6af425f482ca2e86c695e1c17184f6f75bb21288a275b0df284f4fd47ec71ea061163991d67f9945b2217ddfae42ed4a3861523dc90f088a2d082eeeeb03da0202a78dca428c18740b7b658d6d3535c89aa41017e2e19c399f1f47af6c33f3263783acb32e3a29832fe4577130a39c7146c51f0cbb1aa7598f0b61eccd6e728b5970a251646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367fb5552ee6381cdc963f2111a6f573fcfbed929a5b7c4ed5b3a36f5e0db7ec66ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc98b3c9ce3df34033bc3dd90a77b2b0db97c9c89981b5cf75c5aa87c293dde5a21e1620c18b37992f243287ac1416cf3325e32c6396edb12577e7662588de4da7928e438ad9fbe70f4d0badc06c7ee4c83ca813fca202605ce9f9b474875b982e0d55f0109232bc00dcf6dc13410e1b395cdf86e7f0f25d39d47923d809812313dd2594d6ac6f637d534b85c20b93114807839d2feb8bdd37a4ed3b0575f0b6bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa32866219c62026f7943059472a02015d9196422dc18cf32ccdfb1bc543c558bb77001a65742f0ec68ef04f1d1de20e1df0c901f62fdf302b0bc2e7cce56c3b25365115c24f001a1f7f6a466f6429ac5452b824ea332bc55da340486be9211e3c1557cbbec067595eb9403e301c9e5b7ac8d7a6875267436812a9f0e99cbea472635a14868093c7960743b4a3454dd3e5ff5639a2725f2433e65396d247e4d210449f63fdec596e5519c6eed966e2f0980b7a713615db5c14d0d64781166ded471a3b6219a83e6c68a031243b897edd79429041868667756862c9d1b38194a57f3d6fa22beb60e2897e24fcb4fe6f183151874d2e032bb70dce4e519d9632c234421d7622a200065f0ec2d551108c54d6bf63cfb84e70b5f86d0861e641f01f31a7f197a76b16e6c33df21de22f6872242719b47812d22907a96f1611514039a4aa8563b19c1d1d11250331c8705531967758c6a3336e611888684dcbb61c27b"]}}, diff --git a/txscript/data/taproot-ref/d80fa30ad1a0824f0da7b212e606ac5496c0715c b/txscript/data/taproot-ref/d80fa30ad1a0824f0da7b212e606ac5496c0715c new file mode 100644 index 0000000000..c443190e65 --- /dev/null +++ b/txscript/data/taproot-ref/d80fa30ad1a0824f0da7b212e606ac5496c0715c @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40001000000879be48fbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9600000000f30fa8d6019bf8a2000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e62e0b28", "prevouts": ["7d1a3c0000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "7f417a00000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "f87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b76277e7ebb6a6beae3662bd89a171afd4e408216155b40c014c7594821f932cc194f5b64ca7905ecbca48e3f65ecb2f68dc17df34a907a9e0813d7f728c588e9e87f1230a4dffa49f76a6d91b3ffe7dc371ffdd064326b56030bc36a92eabd9a0f16f4cfe8b052d74bbe565102becb5d9831a57baf41b6ebc95ac4a46ff7ed8"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f353434ff448b07af6ab9f2d6b7abed88cb8a262b2c34c793eec61b98efadc45d94fcac167164a1e762fdc7573aeb7aa116b8ba9fcc5f9bd36bcc426cdd2c869a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e5422b6de6500db2bf907e4c5314ebb405475f57406f25afe5ac62a92a9e6c58b"]}}, diff --git a/txscript/data/taproot-ref/d86ea65d288be1fd03e9e19e503b17612c637374 b/txscript/data/taproot-ref/d86ea65d288be1fd03e9e19e503b17612c637374 new file mode 100644 index 0000000000..797df5eed7 --- /dev/null +++ b/txscript/data/taproot-ref/d86ea65d288be1fd03e9e19e503b17612c637374 @@ -0,0 +1 @@ +{"tx": "a8b2c1d602dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5f00000000a06df2f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42701000000a95303a40343c087000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7967f000000", "prevouts": ["517148000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "1fc6410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "2b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93618bdd98e4dd01571cb4788615e57aa4d3492f4068752bbf05bf3e40f7708bf38fb898061b9e990a9b5449c5e7217db506cdc93f8f373bfce07d03a77edf1b275195038de5261112827291f7af9c58b034003ed818b7e5ec0d4ccdf81f6c2ea4d"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa44f1db148647e579a127c5c190f6913605985e391579ddf83e446378ee4bc7a1d75fc84f2af88925f7ad475b3203cbf9256a43a0cda52d14a3416be93a7fb1c4d74d03d2cf0ae79996d1bf896237ca201e78f1b4c5ece550af4c0e01e9fa9886"]}}, diff --git a/txscript/data/taproot-ref/d8ac2a246d17295baa73602fa55f5ef1d6edd095 b/txscript/data/taproot-ref/d8ac2a246d17295baa73602fa55f5ef1d6edd095 new file mode 100644 index 0000000000..31b6f15c9f --- /dev/null +++ b/txscript/data/taproot-ref/d8ac2a246d17295baa73602fa55f5ef1d6edd095 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700700000000cf91ab8ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1e010000002e60e4f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43f0000000034add3ce038151bc00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79695b58e1e", "prevouts": ["055d0e00000000002251203236882dfaab6a61030776953d98ee1af902cb36dd280fe66ad8ee191278ec27", "e3536f00000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "e1fd400000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "387d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d03a0e2dd976c032df5ba11c8ac0ec783bfd7377fb7304a38f58a019219dc2e3f7118923d14a9704f5c6065ead9bf1df659362e443facca38f7fc54a29b18e2b8fa601fcc68a78472d280e0a6f10ace0c22dad9ad93c154f995d1132d7b2f793"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8f5321bd3c280560a6e93f009006b65547a58d72ede42c89f2f760c3bf47a1d1aa12168afdb4ef286e7748ddb08cf408d85b089f504486378d2bfb535c0d2875b"]}}, diff --git a/txscript/data/taproot-ref/d8d54db51b8f8299982f8136c6058c9e8063811b b/txscript/data/taproot-ref/d8d54db51b8f8299982f8136c6058c9e8063811b new file mode 100644 index 0000000000..74423f0123 --- /dev/null +++ b/txscript/data/taproot-ref/d8d54db51b8f8299982f8136c6058c9e8063811b @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b600000000e9c7f4e6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcc00000000ae03d8a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b63000000004e7e6ee9020bc17c00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acc8010000", "prevouts": ["529f330000000000225120973a94e36a4a923b8d161b8fe153210f91b56b5e4fa7540d30da78859ffb8897", "1b20280000000000225120035d0d8894332b18eeb5087880b9b7fe7a878dc0e9a501d9b85908b60f4f194b", "d2c2230000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a8814e3956d08f0194fae5aa4da4023be389b084c13928eefd595af05138750d"]}, "failure": {"scriptSig": "", "witness": ["6a33616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/d8def6ae46c2ae1d19b457603e2015ddad467ad3 b/txscript/data/taproot-ref/d8def6ae46c2ae1d19b457603e2015ddad467ad3 new file mode 100644 index 0000000000..2781bb2777 --- /dev/null +++ b/txscript/data/taproot-ref/d8def6ae46c2ae1d19b457603e2015ddad467ad3 @@ -0,0 +1 @@ +{"tx": "7d81ada40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ab00000000a5db64b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf970000000016aebcde0482f29200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79663000000", "prevouts": ["bef7110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bca582000000000021521f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f6", "final": true, "success": {"scriptSig": "", "witness": ["f9fc9e4d9ac519dbdce2fb2127d2c12d0355253ff8909de84f5bf5b9e6469f8e2faa5bcbd974a71190e7a1cfc4470fb755181d83987c36a4003d93f96c532e9d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5263da901d565efd7d04f0f476aecec6f0bd20a16d03f37ea48b578ea23197bb7520611bb100569dcf1b7902b5c2b7bc23f139f28705cf6ba3072112ada68a03f6", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d8df811ed2f11c79fe945f4943ea3299a251ecb0 b/txscript/data/taproot-ref/d8df811ed2f11c79fe945f4943ea3299a251ecb0 new file mode 100644 index 0000000000..c429421dde --- /dev/null +++ b/txscript/data/taproot-ref/d8df811ed2f11c79fe945f4943ea3299a251ecb0 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3d01000000da98460ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8401000000f6fde8a203bc4d9400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c147d44c", "prevouts": ["fc6370000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "5ab02500000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c04c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688fc8f615032475bb12c71b7eb73effb9d0886ca0e0e26ca1dee2899bd81981c1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004500c8753d4e6010499b58065b36892efcd9281a64e85ebf7c5dcb8f6f4baee16c3de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}, "failure": {"scriptSig": "", "witness": ["4c52c0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5120e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e192555fb599a2fbb7b206b08358b85e40a527ad21aa064f750df81600ff72cf4ef17ad4bbf375bb62f626ec8048d4347cc1eef977780228a6d2fc47294088d561"]}}, diff --git a/txscript/data/taproot-ref/d8e4caa314d508c3062410f0d680eb589488140f b/txscript/data/taproot-ref/d8e4caa314d508c3062410f0d680eb589488140f new file mode 100644 index 0000000000..f0ffa4921e --- /dev/null +++ b/txscript/data/taproot-ref/d8e4caa314d508c3062410f0d680eb589488140f @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1000000000e348ed568bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44e01000000d194e30f035234630000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709ed1724", "prevouts": ["119624000000000022512048dae93b9a8752a11e2bf9d811f71f83e914d496dade834e573813f3fedfdad6", "607441000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d95196c0d5dca92f2d33c0ebad1483bfd9a8aee93ace9d0b7d3c96541db4e2fc"]}, "failure": {"scriptSig": "", "witness": ["6a35616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/d8f77e44fa8aab802aa9131ae9f319611a054835 b/txscript/data/taproot-ref/d8f77e44fa8aab802aa9131ae9f319611a054835 new file mode 100644 index 0000000000..90e8cbba11 --- /dev/null +++ b/txscript/data/taproot-ref/d8f77e44fa8aab802aa9131ae9f319611a054835 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c61010000001257accddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c650000000012c97ec6018f237b000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374870b5af43b", "prevouts": ["bc124f0000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "a21c580000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["fe", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368d877db375ed8535ba033f90d60f6b296e0f2bd1d7897409f54097620de448bdd800fc56907ebb8e18291aa6f74a5d7a46b4d60066ab44c243b43072452172e3365bb68c3eae5e6cd9b20289e581f52d4e8c0cb4ba58bcd8be9e67bc80fb920a1e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f273e05517e7d7c4ebae818f78ffc6ae6bbd8b4691985bf60fb53bef1b79009a0d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3b44d8b0f62b2d27de7be259100200d6da1e5303b29f3eaa1b6a4eeb0c96a42f364ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}}, diff --git a/txscript/data/taproot-ref/d915944728f949574638f5527cabdee757340ecc b/txscript/data/taproot-ref/d915944728f949574638f5527cabdee757340ecc new file mode 100644 index 0000000000..68ae813b62 --- /dev/null +++ b/txscript/data/taproot-ref/d915944728f949574638f5527cabdee757340ecc @@ -0,0 +1 @@ +{"tx": "d14930c602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbb000000002238ed8360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703d010000005e661cef048a862e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca4ce8961", "prevouts": ["33ee20000000000022512023bf095063e7bb97384fbec96f4f01ad8898e1e0efd80c3cfbd3ae44a7eaec2c", "cfd60f0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "a17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365782dad4624e1436d6ea54bb6ab260d102b127668043cbd100ab813dee80a28c33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae668dba12609f1dce2a1e29faaa62ff248d54f408b31ef31944f67a579d4fbb4"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e56012e14d1393796178822b876e37f88bfb8786abf6d56f290a567bb98032f4de668dba12609f1dce2a1e29faaa62ff248d54f408b31ef31944f67a579d4fbb4"]}}, diff --git a/txscript/data/taproot-ref/d92c58e19437f5a57d606edb988ebe5449b4db1d b/txscript/data/taproot-ref/d92c58e19437f5a57d606edb988ebe5449b4db1d new file mode 100644 index 0000000000..3bacffa1ba --- /dev/null +++ b/txscript/data/taproot-ref/d92c58e19437f5a57d606edb988ebe5449b4db1d @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5d0100000065384aca034e9a750000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748722cca356", "prevouts": ["bea4780000000000225120ee3305d066df7da0d9359f951912ab6e6d37e7b862aba6249b3f95860f1fdc83"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "597d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936312c79d7240b9e23cdcc387c1150aad8c47f5ef9191447124def4f04045de1e0613bea5824cd1812f2095288c03f032c5bbbfbbcd6a739f4744a40299340ab834be962498b383c32e8a84fa570ade752f3a2216469b10dbfd65078bd8e1b5998"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93606d200554e8b3644c14695358e08280b763a8aec693ef25cad933bf038da2c47e343ebd89880aabef0f18c5bef462b16920a32508939784a2317d7ebda32c7f1d0160c53d01d80ab4be204ae4e021ad6f56ad3990ac4b37baa4678d530d3ba4ecd61c62feef9509bc7b3762bc81079411fa6867ea4986820580c60fa1e8298e9"]}}, diff --git a/txscript/data/taproot-ref/d93387aa595f09f4e40642c715176275012422f9 b/txscript/data/taproot-ref/d93387aa595f09f4e40642c715176275012422f9 new file mode 100644 index 0000000000..815d93fc66 --- /dev/null +++ b/txscript/data/taproot-ref/d93387aa595f09f4e40642c715176275012422f9 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3400000000f74ebda1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd6010000003ae740d901134630000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48757010000", "prevouts": ["a750530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "71fb250000000000225120199333ae2814ece819e66b6eda683343e1bb1d0c50810e300807466af2e93101"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_74", "final": true, "success": {"scriptSig": "", "witness": ["aab015fdea84fe0e91b8322a7ea01a7840986b3432f88733206552a5c62be599f7e0b49e00292635f4c69b5af6c9e5bbb31350bcae561d509ad2e819d0d044a103", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["a1ef0ed3f13b7f1fc33423c1212ec936086c8dbc09a62853ae1373058575354d28ec806bceabf20ce2771f5ef4b21441aea0cc247743eb9a15ea3208635ebe1574", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/d93dd1d6d2d9b39d77cd72571effaec51dad73cf b/txscript/data/taproot-ref/d93dd1d6d2d9b39d77cd72571effaec51dad73cf new file mode 100644 index 0000000000..2fb099eb52 --- /dev/null +++ b/txscript/data/taproot-ref/d93dd1d6d2d9b39d77cd72571effaec51dad73cf @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1b0100000056ef84c6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1500000000048e2596dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e000000009ecaa1df0136422d000000000017a914719f78084af863e000acd618ba76df9797223689875e000000", "prevouts": ["f4dc280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee4f4f0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd", "53ad4d000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ba", "final": true, "success": {"scriptSig": "", "witness": ["a9a5b68f1d86fd8af024c4f75d1a38f2d10e7637c64a54a2894f0cbedd1e1af59d12b32f020938759a67837bc3fef012ce7d045cb2bb06c6242d1c290206a37082"]}, "failure": {"scriptSig": "", "witness": ["a664329d30e124e738e84ce40146800c1ed5357bbda9e916be43639b3b641673b9c5b2282f208af0925bff854acec14556591069033fae97600e5395e3790f45ba"]}}, diff --git a/txscript/data/taproot-ref/d9462d451520aea896848f14167cad63f8eb631b b/txscript/data/taproot-ref/d9462d451520aea896848f14167cad63f8eb631b new file mode 100644 index 0000000000..c06d3cae70 --- /dev/null +++ b/txscript/data/taproot-ref/d9462d451520aea896848f14167cad63f8eb631b @@ -0,0 +1 @@ +{"tx": "b354418b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2b01000000785719ab60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d801000000a030ebbf032d37300000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac35050000", "prevouts": ["1c06210000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9", "72e9100000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008d", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936529ac28ba9126d334d2bfe78381a644e93a06c9df65fba8ceb6ff6d71211d607f2f7628d981d9c0428415dafbd1cc169dd3ce50060f3002d6f03fa895459568af43de7556260bd81909ce9fa765818ab5d5ff32210a0a876b048ce5ffdf4a21f"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936550f803589323383905fb3624331699e0907c54c55ae82563b3c36b855e46ff6b25240bc46c035392207c1076e816011b96fc57f286e81391f52d072a1ebea8b62cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}}, diff --git a/txscript/data/taproot-ref/d9632d4e4f8d7cc9db523291bb7442332d7c588c b/txscript/data/taproot-ref/d9632d4e4f8d7cc9db523291bb7442332d7c588c new file mode 100644 index 0000000000..8cd0e32729 --- /dev/null +++ b/txscript/data/taproot-ref/d9632d4e4f8d7cc9db523291bb7442332d7c588c @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701c0000000093e5369f60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270700100000013a28ec804895c2000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787270abf5f", "prevouts": ["4552100000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "3d1c1200000000002251203e1b6fae524f56ebd8e25d4d2010b2e478325da2c77049f1de4edb81deddfc75"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["8136e60b5a749db7055c098de5c767d09d597e5fb58a7abd1b3b1c5562a2a0de9063b9b4e2d193a68ab4a790844cdad53eb6ffd787a41ddc3e084b1eeaacd8d701", "6f729d8258fa1d21cf5e2a685a69f7", "75005a23fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774daba5a8823fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da6e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b28fc3474578691d9e244d7b16b501b38340815892291711d256157ad1ee8dad0de486812e546ee343fc80b33a28f311d3769c55b9f9af57521b8222f62c50b838823e011c3227b6379bd1fafb84ee100b553f66bf120084f89826320ec9a568298dde6fd35a7daedf6e8b43006adf2c3120c6e52ace67cfaa97cf3292ad0adf762774921380a419cd0244be2cf22fc9482b6be6695cebb3f4a25992592b5ff00000000000000000000000000000000000000000000000000000000000000006e692c29a2af08d0c07bd51a20c6f04115844f224a8f2483500101b22c98b78749d66a1bb126827bab6e123cad1c62c1d2c4c3b11621ab38aab2dbd2fadfbb92b4bc223aff5abf00ae2194eba7e7507c4679c544ee0f8fdcc942cb71079cf6590405d7b50775128ddd691afc216d299aa73690516e177ce40e767b014d7234afd3c813fa1c1e96078ceb5d0c20ee865c609d00bd2764aba33dab8299d82201f8f37302572b4032cf89a221f094ee0f776acb1948e2971cc52c7548b0766ce4f700000000000000000000000000000000000000000000000000000000000000001d089b5ad5245ccb86bfa71e3b9f1dc4b881f35f18527b8a712ac27fa4d0077a9be4fbbe05d6b742e19a169393f8399ac49b6a3f8fe25e357fbd21be65c5e480febd64ea7daaac5bc7a1202bcb709ed9698e442c24e3acda87b93669ee8f6e9a8121ebe960744f9749796aafb4b96fb0d838ff9a74d0510dc4ff39bb1a9f4c551c4d8539fa98efdc030f11f2d49ed06f459005af216c5950be29f9248ff8a98647cb83b84db5f0a77171f66bfa83a44fa126bcc7c362c5dc48462fdc3d10a0bbd33772a9ef6caa14e124af9b8cacefeee271d9ca6261be901d26b266105e4b84de10dd7de7d0a271d5dd2e892b957c0aeac76223b0c8a9ae5d28f17f1522d0cef29dac0ecf80bfa2bf2419821d2fcc148757f849b7ee26f8409d618121a637b57b79f04b8200de1b3f169bd662d9ab3977ddda4d399e406b026ce1fb8338f8f33db4eb1ee22921e9b7482cd813335e7a5fe207feb124a119889288f698f4ae2852a529075dfd03b6616b347751547bd79643623e5ac1e391aaf7dfa5a4cb7acc5d4d122a8d3c9493bd10bf5f9fc690163ad98c83fe2fe82629f68c75b9a4ad7f65dfac95d2b6a9580adfe1eb93c34c5b3d07ba658c17807015fed9d87202ca3f7162dded8d8809d366758b5968df33bbb14065deabdd83cb2467e8249ea2a808a89e0e6c85afc06f9ae1b4713e1880b1090ac5e3f7ec32968aac2a003f61127064473c9fd3a2c3dac4f849aba576e319cd9b9b4508583384e8741401427ab18623ad10afad3383b0b306a03bd495ff84a8665b410373f619b18b144ab75d81bd0000000000000000000000000000000000000000000000000000000000000000d73ec15d7f56b5a16b80e54d411bb4a9d67d1c66f078f825ff042fb865b9ea2df92a551b325735c4674c323f8ed8a3c63f4fc3f8c623173ec6985991b8b6f0e0f957ccaddda9182dc82949e6dbf6a1bfa91f4127cbd3124861088c1fd3176f4703eb8b1395916cc80ba6648ba7b0a1a11844e81635c58a50f5c88d0ce3ec1c82b68c4089be2fbb5f7736a3a221d94c0c12d4d0a003e754324c3d7174e4406ddcbbb561cebe9800256ba4504c3fc950a79fd8c2c6c30625d45e3094ef221f9951a436147f0eefdfd78dbfd2735ee3da7c2899f0ee4e18a2344b5d0e1638192defacc59095c8c3cd683f765618a427009da6fd4b5c09e5d0be10694d96688c37c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a6ad1d9b822582ae9fa8dbd97c350030f17da5c15189bac30a6a7e7f21dc18ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000001ddaad8a5eb165c8d8255498038debcfa140e20dec6301387f98b99b6063338211ae48db51a42a878e484aa563b47d2da3956c5922dca14f6b9db6c24f7bf27988e0fa67203cb2467ecbe60e720fa758aacc2eeae0404c729234a6fddd4c9abfa912d4c87fd2730c0ee798a40f30844018ccfb663649e211a633638ba8bc7556169e4b43106fb02cbec7f91545ad7e8b8205b2d8dd9667739e82fc60d41fa5a55370e872a375fbd5b7ea6681dcd7562c0c0d7824b4703a4610006ef27d28ce53791a32b5344e3a8723bfefd2c361cfc9e6e5e8afb4156ec33bff105db026cbdf", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["8136e60b5a749db7055c098de5c767d09d597e5fb58a7abd1b3b1c5562a2a0de9063b9b4e2d193a68ab4a790844cdad53eb6ffd787a41ddc3e084b1eeaacd8d701", "18c1e902812f9b4a82d1035803bf", "75005a23fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774daba5a8823fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da6e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b28fc3474578691d9e244d7b16b501b38340815892291711d256157ad1ee8dad0de486812e546ee343fc80b33a28f311d3769c55b9f9af57521b8222f62c50b838823e011c3227b6379bd1fafb84ee100b553f66bf120084f89826320ec9a568298dde6fd35a7daedf6e8b43006adf2c3120c6e52ace67cfaa97cf3292ad0adf762774921380a419cd0244be2cf22fc9482b6be6695cebb3f4a25992592b5ff00000000000000000000000000000000000000000000000000000000000000006e692c29a2af08d0c07bd51a20c6f04115844f224a8f2483500101b22c98b78749d66a1bb126827bab6e123cad1c62c1d2c4c3b11621ab38aab2dbd2fadfbb92b4bc223aff5abf00ae2194eba7e7507c4679c544ee0f8fdcc942cb71079cf6590405d7b50775128ddd691afc216d299aa73690516e177ce40e767b014d7234afd3c813fa1c1e96078ceb5d0c20ee865c609d00bd2764aba33dab8299d82201f8f37302572b4032cf89a221f094ee0f776acb1948e2971cc52c7548b0766ce4f700000000000000000000000000000000000000000000000000000000000000001d089b5ad5245ccb86bfa71e3b9f1dc4b881f35f18527b8a712ac27fa4d0077a9be4fbbe05d6b742e19a169393f8399ac49b6a3f8fe25e357fbd21be65c5e480febd64ea7daaac5bc7a1202bcb709ed9698e442c24e3acda87b93669ee8f6e9a8121ebe960744f9749796aafb4b96fb0d838ff9a74d0510dc4ff39bb1a9f4c551c4d8539fa98efdc030f11f2d49ed06f459005af216c5950be29f9248ff8a98647cb83b84db5f0a77171f66bfa83a44fa126bcc7c362c5dc48462fdc3d10a0bbd33772a9ef6caa14e124af9b8cacefeee271d9ca6261be901d26b266105e4b84de10dd7de7d0a271d5dd2e892b957c0aeac76223b0c8a9ae5d28f17f1522d0cef29dac0ecf80bfa2bf2419821d2fcc148757f849b7ee26f8409d618121a637b57b79f04b8200de1b3f169bd662d9ab3977ddda4d399e406b026ce1fb8338f8f33db4eb1ee22921e9b7482cd813335e7a5fe207feb124a119889288f698f4ae2852a529075dfd03b6616b347751547bd79643623e5ac1e391aaf7dfa5a4cb7acc5d4d122a8d3c9493bd10bf5f9fc690163ad98c83fe2fe82629f68c75b9a4ad7f65dfac95d2b6a9580adfe1eb93c34c5b3d07ba658c17807015fed9d87202ca3f7162dded8d8809d366758b5968df33bbb14065deabdd83cb2467e8249ea2a808a89e0e6c85afc06f9ae1b4713e1880b1090ac5e3f7ec32968aac2a003f61127064473c9fd3a2c3dac4f849aba576e319cd9b9b4508583384e8741401427ab18623ad10afad3383b0b306a03bd495ff84a8665b410373f619b18b144ab75d81bd0000000000000000000000000000000000000000000000000000000000000000d73ec15d7f56b5a16b80e54d411bb4a9d67d1c66f078f825ff042fb865b9ea2df92a551b325735c4674c323f8ed8a3c63f4fc3f8c623173ec6985991b8b6f0e0f957ccaddda9182dc82949e6dbf6a1bfa91f4127cbd3124861088c1fd3176f4703eb8b1395916cc80ba6648ba7b0a1a11844e81635c58a50f5c88d0ce3ec1c82b68c4089be2fbb5f7736a3a221d94c0c12d4d0a003e754324c3d7174e4406ddcbbb561cebe9800256ba4504c3fc950a79fd8c2c6c30625d45e3094ef221f9951a436147f0eefdfd78dbfd2735ee3da7c2899f0ee4e18a2344b5d0e1638192defacc59095c8c3cd683f765618a427009da6fd4b5c09e5d0be10694d96688c37c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000029a6ad1d9b822582ae9fa8dbd97c350030f17da5c15189bac30a6a7e7f21dc18ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000001ddaad8a5eb165c8d8255498038debcfa140e20dec6301387f98b99b6063338211ae48db51a42a878e484aa563b47d2da3956c5922dca14f6b9db6c24f7bf27988e0fa67203cb2467ecbe60e720fa758aacc2eeae0404c729234a6fddd4c9abfa912d4c87fd2730c0ee798a40f30844018ccfb663649e211a633638ba8bc7556169e4b43106fb02cbec7f91545ad7e8b8205b2d8dd9667739e82fc60d41fa5a55370e872a375fbd5b7ea6681dcd7562c0c0d7824b4703a4610006ef27d28ce53791a32b5344e3a8723bfefd2c361cfc9e6e5e8afb4156ec33bff105db026cbdf", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/d96eb1935933e5d8a16bab96d06d05f8b1ab6619 b/txscript/data/taproot-ref/d96eb1935933e5d8a16bab96d06d05f8b1ab6619 new file mode 100644 index 0000000000..aaca7a6e23 --- /dev/null +++ b/txscript/data/taproot-ref/d96eb1935933e5d8a16bab96d06d05f8b1ab6619 @@ -0,0 +1 @@ +{"tx": "4296b05c0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d701000000192c02da60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703800000000b70f74e6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c010200000054072fbe0445ff6e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e4cb024e", "prevouts": ["0526100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "099f120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "39c14e0000000000225120bbde5ba4efe7e1dea8424d44f6a18f36c486dd20519c71d54e639e6583aa7bfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_c7", "final": true, "success": {"scriptSig": "", "witness": ["c1a85d8b3eb980f76eabd5741f07251635cff2f196a301480812513bb5d63da81eec3fd4d352263e70d2ca1df90242916fb1df6dd125a9f1faeddc52c804b6e7"]}, "failure": {"scriptSig": "", "witness": ["561bd7846262baae81f6792ab6d77c043e5928476d727ec47177cd0f017253062b020befafbd057076f69c3e16900a483820fb4aa0691426335697c2cb2f68cfc7"]}}, diff --git a/txscript/data/taproot-ref/d9721f612be2c4596ef2507879885c69a5e6e58d b/txscript/data/taproot-ref/d9721f612be2c4596ef2507879885c69a5e6e58d new file mode 100644 index 0000000000..4d42231cb1 --- /dev/null +++ b/txscript/data/taproot-ref/d9721f612be2c4596ef2507879885c69a5e6e58d @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4470100000039193aba8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a3000000008ece121902c3e279000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787819fc62d", "prevouts": ["8ad53b0000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "73f74000000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "327d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b0246b7a5461d23b2ebf642f7df88e05c9d62107f66abf7b5f94d7753ce57b53620e954adb3b90d8c3597d54022d70f5af7b761a66be618c54dd56feea2be872"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367bb4cde3e3cc203faebf1c98a38c23c69871d6882171bec860ddcb5f2eddf6363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b0246b7a5461d23b2ebf642f7df88e05c9d62107f66abf7b5f94d7753ce57b53620e954adb3b90d8c3597d54022d70f5af7b761a66be618c54dd56feea2be872"]}}, diff --git a/txscript/data/taproot-ref/d975fa857300c644b1b8b86b9e5579116325e3b6 b/txscript/data/taproot-ref/d975fa857300c644b1b8b86b9e5579116325e3b6 new file mode 100644 index 0000000000..eefbec47f5 --- /dev/null +++ b/txscript/data/taproot-ref/d975fa857300c644b1b8b86b9e5579116325e3b6 @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4db01000000aa09a19cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0f0100000069f2c7ce60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270920100000099f9349f028e428a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487596bf447", "prevouts": ["72db310000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "266e490000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "02ff10000000000017a9146704ae21c886c9ded757e2b67d582abfc91902d487"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063c468", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367be4a8bb12b73021ccb63a6bc4fd84e79b116d92f00fdc636ff8584a9737600fca92fb159a7f16850def0f13a878cd04653ddced5aa57281dcbf7f9041e8663ebbd17872a9d61e54e96dfef681da77b5399be78aec05b527019b8e812e967c33a95f177959a3d24a94a797d1e607e5550897d4e95d12a52323e6e8eeeab3383c"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699870a105b0e885032e1422b6e64265097934c5360dbbe05b4622b568c1cc270161570c3f10a90b75a16babedba4ef90c71a7e82b9436df981e4930578e77912a95f177959a3d24a94a797d1e607e5550897d4e95d12a52323e6e8eeeab3383c"]}}, diff --git a/txscript/data/taproot-ref/d97fad7ecab4d8f234efc71d9e0019d3cd6866be b/txscript/data/taproot-ref/d97fad7ecab4d8f234efc71d9e0019d3cd6866be new file mode 100644 index 0000000000..b42ceabfdd --- /dev/null +++ b/txscript/data/taproot-ref/d97fad7ecab4d8f234efc71d9e0019d3cd6866be @@ -0,0 +1 @@ +{"tx": "70ffc10b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b230200000009cc2dafdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3901000000dc9f8bc8023bb179000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787fe43162a", "prevouts": ["1d03210000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "85905a0000000000225120d10cdcba7157d8df26718afda7706aaaa427ac1b5d7e5fac924a4c3a7b738d66"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_57", "final": true, "success": {"scriptSig": "", "witness": ["a063ce31fba109939234fc01f06aaf1ab642b56141e01b0c1ea84cf22e940aff2fda3c46aea52c8af7433dfaa9f0268a09381bed9deb4cdf35951912ee7fa6a703"]}, "failure": {"scriptSig": "", "witness": ["aa796f3cfdb2b54fef664c0efc3b65c55eeb55a838824f29aeb5f23162930b42f4602b8e974d7da283a76a3231a1657fbdc37d0c49a0d5efc890dfcde9887e2657"]}}, diff --git a/txscript/data/taproot-ref/d9d8525ff675d165e7bd245edb10bef8ffbabf37 b/txscript/data/taproot-ref/d9d8525ff675d165e7bd245edb10bef8ffbabf37 new file mode 100644 index 0000000000..3effcdeb85 --- /dev/null +++ b/txscript/data/taproot-ref/d9d8525ff675d165e7bd245edb10bef8ffbabf37 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45301000000f58a3dee8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44100000000b63cad77dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bef0100000079a1743d0344399800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df979722368987ea000000", "prevouts": ["8b783e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "624c37000000000022512099a26739d97cb47a5f7edeeb47465139706da2fc4352eb812a3e381cc2e19a92", "3919240000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "897d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e825e476051edc329ceb3a02f4bde28569ef4d6846a9140276d24ddc98c1f436ac1726cb8b9ef30538f8a1a93f31e75c47dd280be49ef0cf0ee8d9ed88fe0918226c56da6b4a79dd49e001229b88fb5122d120ac43d63d1be0cdb38b208b21132e"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e74521192f9881d050e9eb7f2031b3bef3eee8197447af4f964ecbb21ec264c058e965213f8dbdd3ccbab86b6d585f0f8e78abed831015bbc989f3cab476ce59ac632f1e88e109b3d5485dae08acb0148fc939094c3a94300b3efbd66c89bc20"]}}, diff --git a/txscript/data/taproot-ref/da15d30445dcabf73491b38ff9b7fd6ebf09fabb b/txscript/data/taproot-ref/da15d30445dcabf73491b38ff9b7fd6ebf09fabb new file mode 100644 index 0000000000..7567bc1cab --- /dev/null +++ b/txscript/data/taproot-ref/da15d30445dcabf73491b38ff9b7fd6ebf09fabb @@ -0,0 +1 @@ +{"tx": "6fe1dd5a02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c070000000006cfdada8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48600000000e8441bcf03113b90000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487cf000000", "prevouts": ["bdc05b000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "6a7436000000000017a91486e5fab3386e07350db4c59e442dbaac96c1816287"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["fc4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900458771b6e792b25070418091d57f3336a76b43209d1f0f67eabea9d94d6d252d60aceb16be1ebf4fc69deaf064fc7bf5d7ff2149818b5ba4c28c799d30ad567cc959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}, "failure": {"scriptSig": "", "witness": ["4c52fc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365599acbe1f244de2cb64ba6851492e50472c162a45b9ea3e19f7ca89ee01985a731d32c4c28957ee8de75561afe63689e2428997edbca796d37c8feacf80dd0b4e0df2464f99a35d5bc9fbf69ae3045675e957332f77327dfd622124d00cb4df"]}}, diff --git a/txscript/data/taproot-ref/da20174fe1299204fdf8cca351a424cf681308a2 b/txscript/data/taproot-ref/da20174fe1299204fdf8cca351a424cf681308a2 new file mode 100644 index 0000000000..e18f5445ad --- /dev/null +++ b/txscript/data/taproot-ref/da20174fe1299204fdf8cca351a424cf681308a2 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127041010000001720b19702a1341000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acac33b72b", "prevouts": ["32c9110000000000165f142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["e397277edb9892f8bacbdcb6543289fb0df076055a91ea7e74f59d361d35c07b375a39ee6d07249e82169004b19323f96057fdeaa6b91474614cc9ea8b65e71a", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/da3eafaf969feb19889dd744b3407db1aa866e06 b/txscript/data/taproot-ref/da3eafaf969feb19889dd744b3407db1aa866e06 new file mode 100644 index 0000000000..baddc2299c --- /dev/null +++ b/txscript/data/taproot-ref/da3eafaf969feb19889dd744b3407db1aa866e06 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1402000000ff7187b9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8600000000e2bd2fabdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b54000000005614c499012d9a5900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388aca876a75f", "prevouts": ["cc547700000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "b4db27000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "aafc28000000000022512008ff927e8178e20f38298d934a97845982dc7c5901b7d815cf7926413ad6b4c2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "657d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d46ed5c88be999b027defe78826bdf9f79fd708eb8b2e1895cb28c5d0d8f8cf07a9921914746f344d752c7034b32810721c9853c38c376ca018a4c3c5bab65757fdb01d6ca2155f5be7a678ca6a1e1d0c436995e81f878ed9c74997cf4fccddd302781454c6297f6b8a579760f4d591c0acf84ff9d038b064bbab8a5d53835db"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c56699834a23a35d7a8a8e446f06483c0f6f4014465e54b19938cdc9d35914e3da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e38fd10ac28b4a0ae18793cce60e7e7ebbedf1e3488ce0551c956bc9cf517ba032bc2c7d802e8c870cc0fefcfae9d23d316cca1682651be3bf62b663d5ddaa443"]}}, diff --git a/txscript/data/taproot-ref/da802c4897e37a5e51f367edd23444c11faa33aa b/txscript/data/taproot-ref/da802c4897e37a5e51f367edd23444c11faa33aa new file mode 100644 index 0000000000..b799cd97bc --- /dev/null +++ b/txscript/data/taproot-ref/da802c4897e37a5e51f367edd23444c11faa33aa @@ -0,0 +1 @@ +{"tx": "d3c407fd02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf59000000008d3110a5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce7010000001d03cbb703ec85ba00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc53000000", "prevouts": ["c7df65000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "38585600000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ed7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa229db830b5291510bfd4e55fc2f3a45cfb4105ece0af57cbfe0942d597b32d0c27d2631c3cab5fe643277004a2e6838e79a7dd6765c91a13be066042b33c17d3b131de5807af4725e3fdc8c81388bc895736ddb6e799e7163e8586c833ffc627"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4a97da4cacb7d2ba59131ae423230c4733e99b93a89fd0934cd3e0ba8b31d50a45769ff8e70e4bb7b91d42acbbb62837b0e871ab760bcabf7dfb792b2e999f3b131de5807af4725e3fdc8c81388bc895736ddb6e799e7163e8586c833ffc627"]}}, diff --git a/txscript/data/taproot-ref/da8a14b376513348d7ee34b10ff6883f15cc6fd5 b/txscript/data/taproot-ref/da8a14b376513348d7ee34b10ff6883f15cc6fd5 new file mode 100644 index 0000000000..d13ce6578c --- /dev/null +++ b/txscript/data/taproot-ref/da8a14b376513348d7ee34b10ff6883f15cc6fd5 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf280000000029e4a59edceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd60000000005371cd401525245000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48722d99d32", "prevouts": ["4f2071000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407", "990126000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f7e6fecf7b275192c192a6fcd4b891efb7eaa132d8f10fb9190d0a2baa8d1698e004caa59c1baee03f2237f93c7a785aa484b5867d64be51a3270ee620a8e47365db42922f11ed75220edc6c675ddb7d1048605814ef88b38ccc0746b4208adf1b33c78d0723c2efa37f4f3536e545b2e8b2611b89e2ddafb64647effdd93bfc49c8718c058091c10073ac0cd025d6499d83f9ae0269b4d108e8c33cd7cfe9d27858ef80e971b2149ef8e8c576e5ed3461f20d8c2fb97c44720c1c482a436fc48625d5942d4a34ba8e3e26f8fd6589d0569e0041d3960b3cd7c5a08083107befc5e998ca21829da0c5229d4586245f5e3dabbf24fdc911215b9ccf407e62ad75e7b7149e77cc3993b985c49f8376b351cef110f46679bccf8edf7bf773647022ad9f4cc29ed3db956ed2f80af7588dc351e984e2d0a02e22f4293b73fd7d70a72a94ab7463884dfd80003ee289b3a255c9e27fae49a88e2e46f680a1b0778406f0fd29166bf0cbbbc2c3755a93127d6b3872101c04322c88e7d432f45a2f408bb705b72d280fae5fce9ebe9fe4ba070cf5ff6e85f4d85939dd7f993cbeeaee01a730e76a471127b4d2bbde21a68a06f778c6f4e0a3e65f0bf055617e3ef36efa2a6c99413b4ef664db4bb2365e81a5311819bbd431a1790458565ccabcbd30dd260bae0a2a0d3f4011b6b09a1c27da2f35ea9f8f441167e4eb7ee7ce3893fd6166fcc718902d9a348475f4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045a416fde06d6dd90590ccaed91ef0bd8538f486647382cbeeca5e39ce4df66da0ee1e8f33acc088355c2f0e93e4abfc8ab0ff1ea986a1dad4f5112c46f486a1d1a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}, "failure": {"scriptSig": "", "witness": ["4d0902b50eb576fa724141013151db3fe66801fb01f150be3c196047a70e1fc835bd115ff9187b10725dd8393d80463cdddafa5543e4cedcd5864913b75b2febf91db85a19a38b78684cc9cadf4b3a0d088db6597dd003722bb9d825a9082064e51bc3eeaf18a188b89a5de4615b5f0220c954ad46a18a31b82adc288d3b5a7d377a78b885599c4c35d3df694452d47b59657598e437784dd82c7dfce8e03b65a0c3c2a530d33cdb8fe6aeaf8fdb4dde11ea982ac9dedc5a700941c2f661a36cd0f5deebfe8c4b648f88badf4ac3c19c6ca74cf2a24ce56506450d43632d3ec05daf5a9bcac770f957742173eb63b7fb6712bb9ceacc22bb776ab956bc9782368fd4d2b6fa1ad9f01768cb58bead89b323917c6f665475e0222df300700348f005fbe8ab8a89a47a59143590b9cc5dbead51085644c1aaf6fc7c9c5f37b31527e36f77a1eb547315b20445e6b993e28c4e9de6341cc018b4592cd16433c4136f657b992badb3d8aa47436462044799e321298885980913e3e261c5856eef7de1e62c19901b03f0f8cf45a0db1fcccb30e22801ab42f3a382078593e7fec6356f23d23dd74c001419da5ed4d7b36d3912fc77f0cbe7b89fede5147c85a4954b39ef5a7fd9a7d480b01dac3000147fdd817cab3089813d1f55954b3c5bd08df5e5a83bbcb00290d8e895b6f20aab917ef22fb0534fa1938c2e756dec1171cf5aeb23c6f582e5f5584d942afa887561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93614c1f8c55bcbb87ce1813a4e8a3f18dc4a3611102a5652e00c734483b892a61dee1e8f33acc088355c2f0e93e4abfc8ab0ff1ea986a1dad4f5112c46f486a1d1a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}}, diff --git a/txscript/data/taproot-ref/da91d607fd954405726ab36fa5677e8163634ff7 b/txscript/data/taproot-ref/da91d607fd954405726ab36fa5677e8163634ff7 new file mode 100644 index 0000000000..cde0a53bbf --- /dev/null +++ b/txscript/data/taproot-ref/da91d607fd954405726ab36fa5677e8163634ff7 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e800000000a2a1cdefdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf5010000003ccba3d9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5100000000276aa1a901227028000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787240e3c58", "prevouts": ["3b470f0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "fb0b200000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "0b2527000000000022512067225551b50f550878fba08cb06856b99d76e57e98d7477f94810d7b1bff9dd2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93642d44eab8720c399910a71555eabe43edd1236492240e69469f7f7192498f0541ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045161570c3f10a90b75a16babedba4ef90c71a7e82b9436df981e4930578e77912a95f177959a3d24a94a797d1e607e5550897d4e95d12a52323e6e8eeeab3383c"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369282728574e1b1dad705c3c0a0adb2b81d4b75ec5106c57c346257d4ae7d3e8d74048a48c6eb42f280da39a6557d46ee4318cb4e3319043ed115bdbceba7fd7e7407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}}, diff --git a/txscript/data/taproot-ref/daad29bf36401da76f1b83f5cd1cc0335bf5c14f b/txscript/data/taproot-ref/daad29bf36401da76f1b83f5cd1cc0335bf5c14f new file mode 100644 index 0000000000..9f88916a2a --- /dev/null +++ b/txscript/data/taproot-ref/daad29bf36401da76f1b83f5cd1cc0335bf5c14f @@ -0,0 +1 @@ +{"tx": "dd2936eb028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49e01000000af2fb8efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1100000000d31f29b504d62552000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc89ec6633", "prevouts": ["327935000000000022512008f3b8bffed108016f8bc06cf0d4d62b3035ac315959ae84338bee34a4bab63c", "dbac1e00000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "success": {"scriptSig": "", "witness": ["c29b73f6d4115d0c8e2738347376b55bb645c9cb6ad33c9281c831847882821d5ee65f251bab3a02529ecabd935895e97fca13d6ab67c7ace8d72acb94da7407", "8d1f1a906bbf8348bae9366c058a6fe47fb27ecda3cd3ad8206b30589f0ae75ba36001b98055c70fff349d7445ded05eefa8b81089d97a610452d99b649ea382a9b321ecafd3355c4a3b6ec2e09daf4862278225be16fa57e54aafbb27bf9ec7fcc41f105ae70897f50b78", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362cabe4bd1dfe44f9c25caba22ae59e3ed616e0689bb4f0b439d419432e0754930573dffbef728e5f99ec750705b6ff33b4fd9a55f096fd6a737f31f5d0ba7958c431bd7cfd178bfa5c503ab9bb30155f754b7440556fac234eb58007b393c1e6fb24b505461cd1c68932171e021cb72f7a33ff9ec4bbd11f5402ae84f80317ba487c0a4cf32355cf011375687701fe8418d2adf8e5e1545d0028a7dc3585337fb0262e7c9e1c1e177bdbe7391a3265195b8f245141d8d3aeab23f3e1ee9342a5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b759fe35edaa668e572ec3fb2f74edfb27e216052824354fde5b11e7019f9536ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbebe4e320083eed53d867fa6110ab26e788c0e09fcf0f69fb246d02c4951d2380000000000000000000000000000000000000000000000000000000000000000f5fc0c70852c992a99f1b853f11b1f96c9466e2970bea59100d9a925e04cb9381d0e45ebc6eee1203f3e4253ca802a70216924f9d3fcc0d846c53379a751124c1abebf6972bd8dec0eeabb3a7dd423ffd6db53672f9738a6bbd309f39c87e62304cbe06ce13b167c7a29b168646a1f7f6ec8dc95602f01774adf4afc0ab664e1fc4481b20a20cd342cdefd58f3c5dc6bda01d9ef41efc4186145fab7a365b0c9fea2644e2a0afca15d5493009ffdecfe82c74eae4ff314a3775974b43ee68ec570df5e89a63f903565324bf1f73a402ffbd2be955eb9f77a4318e04c24b50e72b0399b5690ad077e97d0040a1f1ef80c25d5c96b430c8bb258a29caf359533551815af5ff8e2965c0426b2a8c66b645d36029d22f44854c58c12d55bb504336e6129379b8aa42604e007e9a69a05796276b2f2dfc1cfcc060d7f2334346d5c3b0000000000000000000000000000000000000000000000000000000000000000dad077641e06245e5d79e8b0d2e1e78402698e2a12caaad79bf0ca77b31ac85300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff25f0d05f1adfb4b6f7f137e15a3076d9204c33d3e041f6861d4540fbe5e18fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7afaa2c6e77b77a4ac661fd898d095eb31421ce9aed365ce8ad2a5796c62b7db7008ae5a86aa245a539305d892736c91fb54d58ba14bfbe8837e70a216c99e74e4e6a4d06cc22e40e3936850bf89196337a582df24d67457843f8ab67dab6d612ed6a19c7672eba3d7a9faee0b1b951a9089e36fc3d813f06c3f5dd6e9d714f8ceb944f2650401eeb23655094c17b6846b621d3fbd7b91a2b644a465b30bb7096017aff21939d6b5e36f9553ee0ee8eae5c6623103eff2e661ae2d49dca2c8005280b25f708d9649a491b2dd6d44143e8f8a4ad8a0ae333499c4edf1460c8878ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8635274c8151c84cfebf83774462c86c2e9cd3a8ff8e932b85a20a8c08e2aa7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1dc562f92ad18037323a661225ea648c987112688c7b8c0231c592e537a44b0e72a8e3ca2db1d46d6631766499597ec88e1169f9620f8218c50a7bacd82915cb5e702081e69eb24fb5b6c7eaf0d40632e9bdb81aa751ddc997607c0671580b6e6c3ed50118115aef62170fa6f14088bdbeef1052e4b53e713d94fc86ff1bc78f7d651b379d743c0e595c742fad553b59485aa1e2fbaf3a1f0c57907feeb76271f72d3536fde6f9cd33b1ab6c921c4b1aa3a4e60db08844023c94b1937b23cf80000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8612c57cd5a990efa9a2a75e9911de9b6a1af594dafa60d9a1fe869c19e71859257a08356782643d9c248791ac934329ae033be1df8847df5bfee34a71e7e64f8876017d09c57d15c33df46c96f26e695d3f39cb930371b405b76dc2e7fbbc94a8b267308c5aca5f3049ff66e72dd6b6c4962ce24a29a3f82cfec426d56a0450601dc3143c29c1131e7d95b1354474edcf393b1320713b90ec3cdb87780191ab951ab137be8814c1c5231ca70ffd4e0ba965ae8496ddb9ac413f4a546ec21282876918e8f99b358acead2ce01d3b9cdf4db89382dd8c655076c07c1896f4d57740612050b5e470d4afb0891b1f99eca2aa1a0c78d1533778ba97e8a798abd9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff023971c3ac138e1865daad101fe68a8df408be7d78d2dc1de272885db76a7850fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ca8e0c0c7af18b1157148e0b76c618e63f4ec3de179fdc0bfa22867fad7ea9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c8f2e1a2938a99fea74dfcefd7a5befd0b433e71dc553f6b528e8127c11ecbeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000004f5c3932dc531ceaba055d56f02e0277a9034a4aaefe973587dc8e326aacb06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76cb9cf95dd12747dc8373c8126d81269d98ef9d0b9dd83dfa1f8af7961f1703a1982c44e7d17f44633b5674371174a16b3f4ab4f8f2bb4a79547934314eeb700000000000000000000000000000000000000000000000000000000000000002171a77a6b9a3527ee52dfb1288ed18012b2659d0011d94a481c4c64bb9d82b257a77991677ba0f5067ccdf21a7fc6079dbf81fcf9ce0b02f5d5194afc87fa0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e3c5475f7f3b57a26c1d90a1c543267589e5a9630a57673d1d9a14ef717c09095ff813e02cd4e577b6043f9cf6007ac072abd76b1ef65d5fdfc38548895a657394258661e521e0f6bf9447382c9be6ca6b06aaeaa2f1517f7e0029dccd39818", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["c29b73f6d4115d0c8e2738347376b55bb645c9cb6ad33c9281c831847882821d5ee65f251bab3a02529ecabd935895e97fca13d6ab67c7ace8d72acb94da7407", "10449375497a886b134261e8fee56d57df90fd5228f9aa236fbede6e1af6ea60f16a12e2fd2b9ae82c6ca11d9f472a19192405da1cfd509bfabdc31e7a080fa828151fef2b74f9d9b0d63bc5b44e45230960bffdbe6c4637831735b2c89206d51770f65059c401cf6c97", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362cabe4bd1dfe44f9c25caba22ae59e3ed616e0689bb4f0b439d419432e0754930573dffbef728e5f99ec750705b6ff33b4fd9a55f096fd6a737f31f5d0ba7958c431bd7cfd178bfa5c503ab9bb30155f754b7440556fac234eb58007b393c1e6fb24b505461cd1c68932171e021cb72f7a33ff9ec4bbd11f5402ae84f80317ba487c0a4cf32355cf011375687701fe8418d2adf8e5e1545d0028a7dc3585337fb0262e7c9e1c1e177bdbe7391a3265195b8f245141d8d3aeab23f3e1ee9342a5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000b759fe35edaa668e572ec3fb2f74edfb27e216052824354fde5b11e7019f9536ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbebe4e320083eed53d867fa6110ab26e788c0e09fcf0f69fb246d02c4951d2380000000000000000000000000000000000000000000000000000000000000000f5fc0c70852c992a99f1b853f11b1f96c9466e2970bea59100d9a925e04cb9381d0e45ebc6eee1203f3e4253ca802a70216924f9d3fcc0d846c53379a751124c1abebf6972bd8dec0eeabb3a7dd423ffd6db53672f9738a6bbd309f39c87e62304cbe06ce13b167c7a29b168646a1f7f6ec8dc95602f01774adf4afc0ab664e1fc4481b20a20cd342cdefd58f3c5dc6bda01d9ef41efc4186145fab7a365b0c9fea2644e2a0afca15d5493009ffdecfe82c74eae4ff314a3775974b43ee68ec570df5e89a63f903565324bf1f73a402ffbd2be955eb9f77a4318e04c24b50e72b0399b5690ad077e97d0040a1f1ef80c25d5c96b430c8bb258a29caf359533551815af5ff8e2965c0426b2a8c66b645d36029d22f44854c58c12d55bb504336e6129379b8aa42604e007e9a69a05796276b2f2dfc1cfcc060d7f2334346d5c3b0000000000000000000000000000000000000000000000000000000000000000dad077641e06245e5d79e8b0d2e1e78402698e2a12caaad79bf0ca77b31ac85300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff25f0d05f1adfb4b6f7f137e15a3076d9204c33d3e041f6861d4540fbe5e18fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7afaa2c6e77b77a4ac661fd898d095eb31421ce9aed365ce8ad2a5796c62b7db7008ae5a86aa245a539305d892736c91fb54d58ba14bfbe8837e70a216c99e74e4e6a4d06cc22e40e3936850bf89196337a582df24d67457843f8ab67dab6d612ed6a19c7672eba3d7a9faee0b1b951a9089e36fc3d813f06c3f5dd6e9d714f8ceb944f2650401eeb23655094c17b6846b621d3fbd7b91a2b644a465b30bb7096017aff21939d6b5e36f9553ee0ee8eae5c6623103eff2e661ae2d49dca2c8005280b25f708d9649a491b2dd6d44143e8f8a4ad8a0ae333499c4edf1460c8878ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8635274c8151c84cfebf83774462c86c2e9cd3a8ff8e932b85a20a8c08e2aa7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1dc562f92ad18037323a661225ea648c987112688c7b8c0231c592e537a44b0e72a8e3ca2db1d46d6631766499597ec88e1169f9620f8218c50a7bacd82915cb5e702081e69eb24fb5b6c7eaf0d40632e9bdb81aa751ddc997607c0671580b6e6c3ed50118115aef62170fa6f14088bdbeef1052e4b53e713d94fc86ff1bc78f7d651b379d743c0e595c742fad553b59485aa1e2fbaf3a1f0c57907feeb76271f72d3536fde6f9cd33b1ab6c921c4b1aa3a4e60db08844023c94b1937b23cf80000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd8612c57cd5a990efa9a2a75e9911de9b6a1af594dafa60d9a1fe869c19e71859257a08356782643d9c248791ac934329ae033be1df8847df5bfee34a71e7e64f8876017d09c57d15c33df46c96f26e695d3f39cb930371b405b76dc2e7fbbc94a8b267308c5aca5f3049ff66e72dd6b6c4962ce24a29a3f82cfec426d56a0450601dc3143c29c1131e7d95b1354474edcf393b1320713b90ec3cdb87780191ab951ab137be8814c1c5231ca70ffd4e0ba965ae8496ddb9ac413f4a546ec21282876918e8f99b358acead2ce01d3b9cdf4db89382dd8c655076c07c1896f4d57740612050b5e470d4afb0891b1f99eca2aa1a0c78d1533778ba97e8a798abd9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff023971c3ac138e1865daad101fe68a8df408be7d78d2dc1de272885db76a7850fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8ca8e0c0c7af18b1157148e0b76c618e63f4ec3de179fdc0bfa22867fad7ea9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1c8f2e1a2938a99fea74dfcefd7a5befd0b433e71dc553f6b528e8127c11ecbeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000004f5c3932dc531ceaba055d56f02e0277a9034a4aaefe973587dc8e326aacb06000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76cb9cf95dd12747dc8373c8126d81269d98ef9d0b9dd83dfa1f8af7961f1703a1982c44e7d17f44633b5674371174a16b3f4ab4f8f2bb4a79547934314eeb700000000000000000000000000000000000000000000000000000000000000002171a77a6b9a3527ee52dfb1288ed18012b2659d0011d94a481c4c64bb9d82b257a77991677ba0f5067ccdf21a7fc6079dbf81fcf9ce0b02f5d5194afc87fa0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e3c5475f7f3b57a26c1d90a1c543267589e5a9630a57673d1d9a14ef717c09095ff813e02cd4e577b6043f9cf6007ac072abd76b1ef65d5fdfc38548895a657394258661e521e0f6bf9447382c9be6ca6b06aaeaa2f1517f7e0029dccd39818", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/dacc869b2d12c823c9a4bb00e5edcd51d35c5978 b/txscript/data/taproot-ref/dacc869b2d12c823c9a4bb00e5edcd51d35c5978 new file mode 100644 index 0000000000..7d40505818 --- /dev/null +++ b/txscript/data/taproot-ref/dacc869b2d12c823c9a4bb00e5edcd51d35c5978 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fd010000003193dfcfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b54010000005b35cfa901599734000000000017a914719f78084af863e000acd618ba76df979722368987f8010000", "prevouts": ["5c99400000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bf2620000000000017a9147e06846ce22cd5e23f7e03391c0538498e0e18ed87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "215c1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["81460df501ef435ba685c790d0e36c12bc849c884a1d74cbd9cb660662cde4ab52904a5773b01fb806c06221f2a2cff19cc19c63dd306fb6ad8a66565e62d4b8"]}}, diff --git a/txscript/data/taproot-ref/dacf3352a5bdd39737fb53affdf284ce61f4e97e b/txscript/data/taproot-ref/dacf3352a5bdd39737fb53affdf284ce61f4e97e new file mode 100644 index 0000000000..231bc034b6 --- /dev/null +++ b/txscript/data/taproot-ref/dacf3352a5bdd39737fb53affdf284ce61f4e97e @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c40100000047cb6918dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5c01000000fd2ae32903ce9890000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6dd902a4f", "prevouts": ["8d4638000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "ebef590000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1a6ec201a93e79c82aebcb32c5742cba4049490cef67cba707365d2e1379631f73bd198ccbfa9c702c0592bb8c84a948c36ef9eddfd1aec8278a333dab45811656e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366f96bfa32a795a0be15451bd7a8acafde79cf5d8ce79cbaf82150de20d1f80e0d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d513070c0d29d47e9fe7be7df27becdaf45cc7da31561e827162b16aa01fe84c4a24f44ecb3bab6b962a7ffa14a2ce082ec551943f33ce508b63a8ee30ee5e49264"]}}, diff --git a/txscript/data/taproot-ref/dadf4bbba1d78a438712afd4e84df10275987f0a b/txscript/data/taproot-ref/dadf4bbba1d78a438712afd4e84df10275987f0a new file mode 100644 index 0000000000..f551539b97 --- /dev/null +++ b/txscript/data/taproot-ref/dadf4bbba1d78a438712afd4e84df10275987f0a @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bf000000003562bfc98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45b000000002c898a1201ae153c00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3607604e", "prevouts": ["fcdc1200000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67", "58eb3500000000001656142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063cf68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365dbc42be0fb4d05018f85e57934c949bd98e16e34360285c47c1ce52c024f3275f88ccdecf77b0d26ba8d6f3209049de9d03155be73752c3625590c2269e1c4cf4a62e14d7fc4acbfb0196ec29a60565ac2b3043dda4cedec8cb1ff291b90d41"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b243421d00bd68ca1d9baa1bebc840cebaefc3d7d0b6247bd057554b13606328cf32df52f44331c723f7b513b476c9aa41e2dab3be9ace9864b6dc0f919492d46a7a52674f359a7dbed67a49e09732132053a9cde77eaa564fdce3cafe7738b9f4a62e14d7fc4acbfb0196ec29a60565ac2b3043dda4cedec8cb1ff291b90d41"]}}, diff --git a/txscript/data/taproot-ref/daf266d227dfb92686b3d8cb80cb4d2c4e849468 b/txscript/data/taproot-ref/daf266d227dfb92686b3d8cb80cb4d2c4e849468 new file mode 100644 index 0000000000..4d61d75288 --- /dev/null +++ b/txscript/data/taproot-ref/daf266d227dfb92686b3d8cb80cb4d2c4e849468 @@ -0,0 +1 @@ +{"tx": "a4fc63a00160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fb000000004f310ed9015b8f0900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1b62b249", "prevouts": ["40f10e0000000000225120be45abe027d497ea26107f03649e0802eba12fae4acacbea0c6ebae5b321218b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "success": {"scriptSig": "", "witness": ["55f9180acac0838f7aa1a21e01a619dc1cd4977eab715ce88d17747ba537a0054aba6af37c6c42bac656973cf2e4f13e5a4f9d7ef27228ba1b261d9e1af6353b01", "5ae231f7b92b6e7ff4b1c248b4e5a75888890d44106d168b427d7340e184ec2857ab8aeef4b5f093a66c7b13a6b984b308c98643e08d388b48a22f7a1db8addd359c3375115f7590a20d16d76db0f81a2d49f912f1728d9298db8ed980b5c421f8d16bccd67770c1a26dc4d6d4e3e1cee739cc04710e519a6b8c728579a1c760652fc14fb76f417847bcd07a9a97255266d9866337d73163eaf8d97c7a9bd8f3b4d49753562543334533417f50d42cc99b7e7d6bc82ce1f67ffc81f8252a06cdbb0efda92e288def8069ac56b08a3c8833913627ab03", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20085d1431608a13d9e6d01431e93410d0dfdde60be047e951ef24da4d3d563a1a2bc7c2cd41751e202a72526c257759aa8dc4c33bcbb906937916d53546f277fcfae54ec38d67691557f02c9486972b1f0a8d62d8c1693381df763e8d970fab0cd3dda486f5bdc474013b8bad18ae6d722a5ba69383a7cd585fda02504065248af15a3c286c6cf88b781d8aa9b25674bbcb31583b2191a103a1fee039520cd1bf1183188141ead37fc87cddc1d3f30d9695c97fd00d747e65bd4a7d849628ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9fa185b00cbde494d34ce557c66053774e3d64cd4d41c82296238541df37f7375773b0d19b541d18f41b1e60e49d95bce01c4415a68e11a481d7e4b48568fbfb92e08e3b46d0c7aa5705d957d4c2071652c9a3dc9f0413f64febec95a1bc1f4707aca466883e6bca921172a478d5dd8bd84cd0572fd601163f8ff45fb21683feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff45e0bedf46992462b895ab90f2e44b74d757f7074ccfb73a9d58ee8190489b361eb319a8e4eddca72a02c9ca104b7d00b05ee954cbf2a4ad2ef087218577a2caffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c59dd14a0c109e7683d0b33e5fcbab56ed7fbedc496a2bc37ad2f5fc291f000120456d60ca44db9fb0edf4768044a03e43bd461df4e0d8a7548c718395a74874e4a7f5241dd03ab792a0432554b8a1f5e037e2d586c68921c697c4349a6f57e9bc885c0e8504bd97aa7f1ab8f2e0eeb6b4ca00f7c0007b57e43e27cbd04448558f093548ee2d82731794a40acac6a0162c04fd2b804ec3ab016561b892644939372985ac19d8e73e58fdddfa22f02ae9f3bc3aefe5465645783f4455d6a8e9f000000000000000000000000000000000000000000000000000000000000000020f3ac5b09c24ec47d0a3b7e87fa10cce6dbd8aee340ba8fa9afdf245aa1a200045619bfc6fe4dcd4271da4d2c924f6704c4b81b569527fcbc3aec026c62af5b0000000000000000000000000000000000000000000000000000000000000000196619618544aab26162c4e763b10109da5d92f3b3ecf8a34177dd558f03328dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff397ca559b6ca786194ee70a65ba9c0a55d343344e10b0b11641d21831b294646227c1ecc8d4cf9ecd3cac1c41a56a4c6947d991a122c8f38d348838ba28b21cc8e555ea33dc50534f2d740b3c56792b0b46c9eb674670cfedd74452dffaebff200d095f262b9641d0a63a251be87f585954997437a8745480952fe38adc03aacc57b988d100f65b42312c817241ef64c42f92a647294c92bdf5a912d6215d5110000000000000000000000000000000000000000000000000000000000000000319cf3332908783f8b393a9db63f2c45c8fcf3b58d2024a5b36d4994fa7776d30000000000000000000000000000000000000000000000000000000000000000a11c07e8d5fd88cbba499ac53cc3d4b519e58ff55de45d057a4115e6a3db64244104796de59dfe1631bd82618a3aef5ac88c98bd75d409c76da60cf7e91aa075d12a8fc7a0c7f61476451703d7ff28a8acc17f4368cc21f8e39e1172c2cf7d5222c61a939659ab875f6bc0c71aa211f012c80ffaa9729f49f3b9b788461e540c6c586ad4c36419fc3846fd82ee6bd89a0d635bcab8e990bda7fab24a5d8dc59f23c62fee033a6e645355b86714f40b234af64e3eddf523afafdaf593c4bee739ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0367da238d38b742e29327af08cec9f71a0c3c93503d32b5cd6035a5ba684c90a0ad0e0ab7b5f831dd3d72ce93181a4a2fab4fa10e90e7946680f539150184e07d2e5848296567199ab87909f6259b45f23b3869464b261fb877d4b3614548a891081ddf6520b5b25b6d0d23e1f11b58c82b00f6f4e6f1dfeacb1a81f92f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851b1a5d164febcd92802d7ba14420652e1fa5cecf9156304d795e86187c1cf92a190b1be1376cf48670e93db187ba7db279cc5bb3d6c30f3130db18d95a231dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff223525b9fe0911b292333d948c81212710156b273d62bbac979aac51264348e17a8622602a1b8519eeb0161b133a290bf32ce3a05a8748f8feba8948f7a2ae1f92ce16ccd074bd21a434ad36c9d8c72c0edf199d10efed77b6f6b305b59b76f6000000000000000000000000000000000000000000000000000000000000000009f230367ae24a8b0fc0b06755bb62c237af82c0537658377aeaa1ba7bb6e6287d274ef14f5f1065a883387bf1a735f355f13334b58762ee02a93a7d91c07c240000000000000000000000000000000000000000000000000000000000000000ce45a8fe9167d4c375805fe5220d93bdd00b8b4ac0385de28f71d631f4d8f059c5e00448b8071c055d284584e4b4b3ff9d8b2d2a46609b375d022eb610e9898dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5e42b4ae9e59beb0239d89bac0e19c34b00b7ed5fa73c66f9665d312cffe7774020372772a41e566516a9f5449f7ad8a25e4e18ff0eaf65e2e8ab5d3ae98f6970000000000000000000000000000000000000000000000000000000000000000ebf2b30bccbb7e5b9714aa95118ef7d1b5dcabbe2efd5c99169bce1882b83b29e9e3fd717a5ed6035c512e8af8ee657b562ad4f6b77a41986e21d177f14c5c239c2e07f4e6ea8697d6f93536e742d756477f3593f36d8c0e737b7260fdb9110c2bb589b0f67c48f52dfa873a05140356c5508bf7b18d8bee1637cfa83207d3004a724018af9ef92756ac5328e1ffc45f8f6618bbd789c7519d7bda73a734d5981c56cbe92f6bab7ef7eef4145d83a37c4f95d3c92daa5a208de8d71620a6e5f072e8d485958a4c1a5862dcfba015d183f1ec4c318b7d278424ba13a6ea8b4cbf24440bd604239bd3ee7909c434904cb49bcbfe9c79ebfbbcb0a49b72a96e7b112f9535975a729f795b119588924b03760c7ca2ae4d2d582b4d761ad50d7c48e840f4dc21a989d180e6e32bde9da1497e9a2af7e6fdb1440eaf2a9bdabbeb8cd9a9a8aa55dc54fdc9d390552d62fe23a61c4ec784cc7829d58b9c41671c0385ee35285ad73cf9a7e31973f81533253e0d65bb924115cc62fcb1f56b50cc3d6345fee4735c9dbf00427ab5a4672ad64b77441c3ca7f8b12e307b99090fe85088bb58c51bb634febc23c5e582e01231835e3b9de55f35884dbaf3b49d634cbde8bf4f35f10548014bd4feaa862f44ccb01eacb5e9f43d74c83c190f9157db8db9d8bb255184981f1f50d9b4ab62596c825feabad713f7e5e3671db6fda47cfe0613ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaf3d61e00f7ea105d52de95e2214c64540ec59e6ba70b03ad9644d06275d4a7badc5438c360a1ed0e06f28ce791788a5a1dcd4a38da21c8d537050cbc6e4a353fec2be47ababfa3b968ad98a81c1db525f475fbbe875b5ffbc13c51a27cf8c92509c4a544d5537008c5f39dc9841d45bb1e1db3267ed0283bed4e2a656fd20c8b47ced7c0dcc324c5bfc2aa2392c0079b9fd4a2dbf0784fe1e0500e06367283b295e4f90d8f029176be25607d86d3844058fd54a661f2bd33946b8d320ce7704dd3a0e1733623317bd58fdf32bc93dd192e9a3f97709b6c367728c46947e5b1b75f37336f7363e3df3ad6234d97c87432a2e3ba575e9c096920b313a872d6e502b54f1dff5482e96e72b1ac8720015f4933afc264800e7b085fc465d02d4b0db000000000000000000000000000000000000000000000000000000000000000000f626a941aef43ffd04452b229df6da8fe26af44cb7d4a59362c927484b0df5e3cd73f750dfa56359be3367fb818e655479e50aa8b5a1969de43dda5281d3d57282014796fedb899df18abece1b8f86d456bfa53afdc3767e6ec834d4d260b23cff5fbac9a71946d3669ed6248547591a4c7ed56a3265b689c374a88076450494c684e895b2af6fc6f872e9bc9d180e1dad0974e282e8258f0b875a82c9a90807900b51a7b7d32a871e28b54c96624d0f6d828d0c4dff20b003d5fb016c08fbb3759d99d156356462a80c393e8dfeb7ca0643461411c52d11b4704d144f477f0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a1c50c054395de600f0ca8f4471527e0bd9ca4dcb45a0ba7e863df1ee95c01182162b865a9b136e3042b2ddbe1b0d83033ec2ad60b528846bd18b280d87f43c82e9b32503cafe113b34ab89fd58dfc6e275b4cf912c8678b769fdf4bc4ec98b61e53887b33854f07be5b1a726fa667adfc2cc865e8aa0954eb79e4fd050a96d3c6af388797a01c67e5c682b84b253f9ba48654bacecc6fae35c8d430ce63f7109d1170337b5668c35bb66648600cb1b343cb9064c820ae30abe3b4655941c4cd7ae8ca34736d559ed5b0a98f9c4a03942412b5813236eb73d543aa1750b0f307"]}, "failure": {"scriptSig": "", "witness": ["55f9180acac0838f7aa1a21e01a619dc1cd4977eab715ce88d17747ba537a0054aba6af37c6c42bac656973cf2e4f13e5a4f9d7ef27228ba1b261d9e1af6353b01", "304b9b4d1c3487ebc87037fb80fece772541220d1699afc7248dae1a61c8e57210f71ba881724bef0411ac2def288653c7d0546cb8c43cf26695b401442a9f3c1f2346933da58531df56216282b22b086a975d0f3ca59720d473a946cd9c130f5c9d3d45584c1deef5ea58a6836b78dd9d1b8169aa5f54dda1b937092a6a3e88e13e3f1fb4872f3aaaf30f83c473fd53bb02014cc68c9ef4fbdae260792ac57abab3cbecc6f04230046425c1166639f84a39907fbe324c219b77143d998eec88be206e7ea68313c90d4c29a1855a776178ba00dc1d", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b20085d1431608a13d9e6d01431e93410d0dfdde60be047e951ef24da4d3d563a1a2bc7c2cd41751e202a72526c257759aa8dc4c33bcbb906937916d53546f277fcfae54ec38d67691557f02c9486972b1f0a8d62d8c1693381df763e8d970fab0cd3dda486f5bdc474013b8bad18ae6d722a5ba69383a7cd585fda02504065248af15a3c286c6cf88b781d8aa9b25674bbcb31583b2191a103a1fee039520cd1bf1183188141ead37fc87cddc1d3f30d9695c97fd00d747e65bd4a7d849628ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9fa185b00cbde494d34ce557c66053774e3d64cd4d41c82296238541df37f7375773b0d19b541d18f41b1e60e49d95bce01c4415a68e11a481d7e4b48568fbfb92e08e3b46d0c7aa5705d957d4c2071652c9a3dc9f0413f64febec95a1bc1f4707aca466883e6bca921172a478d5dd8bd84cd0572fd601163f8ff45fb21683feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff45e0bedf46992462b895ab90f2e44b74d757f7074ccfb73a9d58ee8190489b361eb319a8e4eddca72a02c9ca104b7d00b05ee954cbf2a4ad2ef087218577a2caffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8c59dd14a0c109e7683d0b33e5fcbab56ed7fbedc496a2bc37ad2f5fc291f000120456d60ca44db9fb0edf4768044a03e43bd461df4e0d8a7548c718395a74874e4a7f5241dd03ab792a0432554b8a1f5e037e2d586c68921c697c4349a6f57e9bc885c0e8504bd97aa7f1ab8f2e0eeb6b4ca00f7c0007b57e43e27cbd04448558f093548ee2d82731794a40acac6a0162c04fd2b804ec3ab016561b892644939372985ac19d8e73e58fdddfa22f02ae9f3bc3aefe5465645783f4455d6a8e9f000000000000000000000000000000000000000000000000000000000000000020f3ac5b09c24ec47d0a3b7e87fa10cce6dbd8aee340ba8fa9afdf245aa1a200045619bfc6fe4dcd4271da4d2c924f6704c4b81b569527fcbc3aec026c62af5b0000000000000000000000000000000000000000000000000000000000000000196619618544aab26162c4e763b10109da5d92f3b3ecf8a34177dd558f03328dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff397ca559b6ca786194ee70a65ba9c0a55d343344e10b0b11641d21831b294646227c1ecc8d4cf9ecd3cac1c41a56a4c6947d991a122c8f38d348838ba28b21cc8e555ea33dc50534f2d740b3c56792b0b46c9eb674670cfedd74452dffaebff200d095f262b9641d0a63a251be87f585954997437a8745480952fe38adc03aacc57b988d100f65b42312c817241ef64c42f92a647294c92bdf5a912d6215d5110000000000000000000000000000000000000000000000000000000000000000319cf3332908783f8b393a9db63f2c45c8fcf3b58d2024a5b36d4994fa7776d30000000000000000000000000000000000000000000000000000000000000000a11c07e8d5fd88cbba499ac53cc3d4b519e58ff55de45d057a4115e6a3db64244104796de59dfe1631bd82618a3aef5ac88c98bd75d409c76da60cf7e91aa075d12a8fc7a0c7f61476451703d7ff28a8acc17f4368cc21f8e39e1172c2cf7d5222c61a939659ab875f6bc0c71aa211f012c80ffaa9729f49f3b9b788461e540c6c586ad4c36419fc3846fd82ee6bd89a0d635bcab8e990bda7fab24a5d8dc59f23c62fee033a6e645355b86714f40b234af64e3eddf523afafdaf593c4bee739ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0367da238d38b742e29327af08cec9f71a0c3c93503d32b5cd6035a5ba684c90a0ad0e0ab7b5f831dd3d72ce93181a4a2fab4fa10e90e7946680f539150184e07d2e5848296567199ab87909f6259b45f23b3869464b261fb877d4b3614548a891081ddf6520b5b25b6d0d23e1f11b58c82b00f6f4e6f1dfeacb1a81f92f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff851b1a5d164febcd92802d7ba14420652e1fa5cecf9156304d795e86187c1cf92a190b1be1376cf48670e93db187ba7db279cc5bb3d6c30f3130db18d95a231dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff223525b9fe0911b292333d948c81212710156b273d62bbac979aac51264348e17a8622602a1b8519eeb0161b133a290bf32ce3a05a8748f8feba8948f7a2ae1f92ce16ccd074bd21a434ad36c9d8c72c0edf199d10efed77b6f6b305b59b76f6000000000000000000000000000000000000000000000000000000000000000009f230367ae24a8b0fc0b06755bb62c237af82c0537658377aeaa1ba7bb6e6287d274ef14f5f1065a883387bf1a735f355f13334b58762ee02a93a7d91c07c240000000000000000000000000000000000000000000000000000000000000000ce45a8fe9167d4c375805fe5220d93bdd00b8b4ac0385de28f71d631f4d8f059c5e00448b8071c055d284584e4b4b3ff9d8b2d2a46609b375d022eb610e9898dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5e42b4ae9e59beb0239d89bac0e19c34b00b7ed5fa73c66f9665d312cffe7774020372772a41e566516a9f5449f7ad8a25e4e18ff0eaf65e2e8ab5d3ae98f6970000000000000000000000000000000000000000000000000000000000000000ebf2b30bccbb7e5b9714aa95118ef7d1b5dcabbe2efd5c99169bce1882b83b29e9e3fd717a5ed6035c512e8af8ee657b562ad4f6b77a41986e21d177f14c5c239c2e07f4e6ea8697d6f93536e742d756477f3593f36d8c0e737b7260fdb9110c2bb589b0f67c48f52dfa873a05140356c5508bf7b18d8bee1637cfa83207d3004a724018af9ef92756ac5328e1ffc45f8f6618bbd789c7519d7bda73a734d5981c56cbe92f6bab7ef7eef4145d83a37c4f95d3c92daa5a208de8d71620a6e5f072e8d485958a4c1a5862dcfba015d183f1ec4c318b7d278424ba13a6ea8b4cbf24440bd604239bd3ee7909c434904cb49bcbfe9c79ebfbbcb0a49b72a96e7b112f9535975a729f795b119588924b03760c7ca2ae4d2d582b4d761ad50d7c48e840f4dc21a989d180e6e32bde9da1497e9a2af7e6fdb1440eaf2a9bdabbeb8cd9a9a8aa55dc54fdc9d390552d62fe23a61c4ec784cc7829d58b9c41671c0385ee35285ad73cf9a7e31973f81533253e0d65bb924115cc62fcb1f56b50cc3d6345fee4735c9dbf00427ab5a4672ad64b77441c3ca7f8b12e307b99090fe85088bb58c51bb634febc23c5e582e01231835e3b9de55f35884dbaf3b49d634cbde8bf4f35f10548014bd4feaa862f44ccb01eacb5e9f43d74c83c190f9157db8db9d8bb255184981f1f50d9b4ab62596c825feabad713f7e5e3671db6fda47cfe0613ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaf3d61e00f7ea105d52de95e2214c64540ec59e6ba70b03ad9644d06275d4a7badc5438c360a1ed0e06f28ce791788a5a1dcd4a38da21c8d537050cbc6e4a353fec2be47ababfa3b968ad98a81c1db525f475fbbe875b5ffbc13c51a27cf8c92509c4a544d5537008c5f39dc9841d45bb1e1db3267ed0283bed4e2a656fd20c8b47ced7c0dcc324c5bfc2aa2392c0079b9fd4a2dbf0784fe1e0500e06367283b295e4f90d8f029176be25607d86d3844058fd54a661f2bd33946b8d320ce7704dd3a0e1733623317bd58fdf32bc93dd192e9a3f97709b6c367728c46947e5b1b75f37336f7363e3df3ad6234d97c87432a2e3ba575e9c096920b313a872d6e502b54f1dff5482e96e72b1ac8720015f4933afc264800e7b085fc465d02d4b0db000000000000000000000000000000000000000000000000000000000000000000f626a941aef43ffd04452b229df6da8fe26af44cb7d4a59362c927484b0df5e3cd73f750dfa56359be3367fb818e655479e50aa8b5a1969de43dda5281d3d57282014796fedb899df18abece1b8f86d456bfa53afdc3767e6ec834d4d260b23cff5fbac9a71946d3669ed6248547591a4c7ed56a3265b689c374a88076450494c684e895b2af6fc6f872e9bc9d180e1dad0974e282e8258f0b875a82c9a90807900b51a7b7d32a871e28b54c96624d0f6d828d0c4dff20b003d5fb016c08fbb3759d99d156356462a80c393e8dfeb7ca0643461411c52d11b4704d144f477f0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a1c50c054395de600f0ca8f4471527e0bd9ca4dcb45a0ba7e863df1ee95c01182162b865a9b136e3042b2ddbe1b0d83033ec2ad60b528846bd18b280d87f43c82e9b32503cafe113b34ab89fd58dfc6e275b4cf912c8678b769fdf4bc4ec98b61e53887b33854f07be5b1a726fa667adfc2cc865e8aa0954eb79e4fd050a96d3c6af388797a01c67e5c682b84b253f9ba48654bacecc6fae35c8d430ce63f7109d1170337b5668c35bb66648600cb1b343cb9064c820ae30abe3b4655941c4cd7ae8ca34736d559ed5b0a98f9c4a03942412b5813236eb73d543aa1750b0f307"]}}, diff --git a/txscript/data/taproot-ref/dafea52d56a314eff0b38df4ddd35be40d4f6d24 b/txscript/data/taproot-ref/dafea52d56a314eff0b38df4ddd35be40d4f6d24 new file mode 100644 index 0000000000..55edb91cb8 --- /dev/null +++ b/txscript/data/taproot-ref/dafea52d56a314eff0b38df4ddd35be40d4f6d24 @@ -0,0 +1 @@ +{"tx": "7c7bc09502dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4a010000005814a0c1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf72010000002a1554c90484e08300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7fc000000", "prevouts": ["d98421000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87", "3e4f650000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063ef68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900453d5fd5ac800672ea3242021b662a824007132163c3d52e3d81e7af2ac2d1c56b1aac465e0caf83cc75bfd3b0ee046dffa2f2de04035b6590b107e2b54cd5d5d2cd241e6bbc5ebedd8f50ae206f1f82a1e41ff5c139455a0ddb0d368f52a47602"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93613ba376e93f66744fa625cc79ecff51fb47f28c65369299fa6e04614a4c71f0c3d5fd5ac800672ea3242021b662a824007132163c3d52e3d81e7af2ac2d1c56b1aac465e0caf83cc75bfd3b0ee046dffa2f2de04035b6590b107e2b54cd5d5d2cd241e6bbc5ebedd8f50ae206f1f82a1e41ff5c139455a0ddb0d368f52a47602"]}}, diff --git a/txscript/data/taproot-ref/db01c81c34e5e86ae44bef70289a143173916fb4 b/txscript/data/taproot-ref/db01c81c34e5e86ae44bef70289a143173916fb4 new file mode 100644 index 0000000000..b80c1783bb --- /dev/null +++ b/txscript/data/taproot-ref/db01c81c34e5e86ae44bef70289a143173916fb4 @@ -0,0 +1 @@ +{"tx": "24ca7fe402dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6b01000000e24a61968bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44500000000ca3ae0ff013c003800000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88accf07ac48", "prevouts": ["577755000000000022512054c099d7cf7db0853ef8782c8a4f2f22d5ed4b1e2f91866bde088ab8cd4c1400", "60373900000000002251203a052535d72bc3628b339fbda1fb177653fe86e5d6ac7ee3c6549de6bfc2fe81"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670d6a4c90a07321387fde84458427ca433b667233a08bf96ea1eb88ad41e0526"]}, "failure": {"scriptSig": "", "witness": ["6a92616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/db06c61fa468b40855c83db915cf67df55dddeb9 b/txscript/data/taproot-ref/db06c61fa468b40855c83db915cf67df55dddeb9 new file mode 100644 index 0000000000..7241357f75 --- /dev/null +++ b/txscript/data/taproot-ref/db06c61fa468b40855c83db915cf67df55dddeb9 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1500000000e2737d19dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b03000000005a250c9e0284fb83000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71e000000", "prevouts": ["2d5f6600000000002352212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "6b0a200000000000225120a4d11f9ab8dc6b61afd987f8e15499b9970edef61488d41b5de77b1846913dba"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["3090bbd9de73322484fe270a1a5006987b8a5c5a65561f363b9082a8a4d72247aa6e1a20569ca99586eb0faf55052c786c3f42a9a0c66427f716bc6a713525b3", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/db191d70ebee38a520718fe3a295896a1840f111 b/txscript/data/taproot-ref/db191d70ebee38a520718fe3a295896a1840f111 new file mode 100644 index 0000000000..cfaf3152f9 --- /dev/null +++ b/txscript/data/taproot-ref/db191d70ebee38a520718fe3a295896a1840f111 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc000000000567fd09760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e3000000006cc4beb260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703901000000fda958d3043a449000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf24a3044", "prevouts": ["c9366c00000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "2745130000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "d0db120000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "6c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a238d55badf8acf8a76486c1c58a90ba61d2c17882158465b124e563f4a2674d94fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e872a8a6de95a80dc4a6e95ba0e12854eab511c8acfff04c6cfab0ff55ad6b178"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab66e6e50f0e23344b2fb4fbd1c94b97eff6a18e7892810f712f9b1a97473dfd5b22591e944b414d99fe534a482351afe29b8e90b07993fb7f3f85b72380ca5294fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e872a8a6de95a80dc4a6e95ba0e12854eab511c8acfff04c6cfab0ff55ad6b178"]}}, diff --git a/txscript/data/taproot-ref/db2f754795e1478498a59b3071a7852a32a70b8e b/txscript/data/taproot-ref/db2f754795e1478498a59b3071a7852a32a70b8e new file mode 100644 index 0000000000..78d857afaf --- /dev/null +++ b/txscript/data/taproot-ref/db2f754795e1478498a59b3071a7852a32a70b8e @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46d00000000e4e24797bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd0010000006cf86596dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbe0000000039bf39d9014d7b6700000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5e010000", "prevouts": ["b9ba3900000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b", "cd767b00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "7a8f2100000000002357212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["eaa4642f4330fa159cd36e1f76f94f0db6b32781d14b9657ec806a3f15c9a354be453a1673ceeb5e892325b8164dd70df71151f21c618e823cfa0efb4e5c2667"]}}, diff --git a/txscript/data/taproot-ref/db41febcaac001cb453d4a2ca2a285784d5a9cd8 b/txscript/data/taproot-ref/db41febcaac001cb453d4a2ca2a285784d5a9cd8 new file mode 100644 index 0000000000..627c6932e1 --- /dev/null +++ b/txscript/data/taproot-ref/db41febcaac001cb453d4a2ca2a285784d5a9cd8 @@ -0,0 +1 @@ +{"tx": "90a986b40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127057010000006a8f8b938bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e400000000e9d5c1d403674e480000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7e6010000", "prevouts": ["90c70e000000000017a914aa4a4e70b11f4eec4760f77206dc93b02350fcff87", "88c33b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_8c", "final": true, "success": {"scriptSig": "", "witness": ["9d2afeab3339f6c041d62d67173e41fa2c415ff2b6bcc94668a38ef02334ba32496d5fe93ea2ebbe87e55dd1d8da5746a7a4fe7411c3a735b4cf211f01cc286a"]}, "failure": {"scriptSig": "", "witness": ["aae11303411b6934e548effefbf23cbab32a12136172bfd514f6e59db1fea5a8863bbb56364030d301cbe5e076f75dd9fab38029efa2eb81a5fab4aa741623508c"]}}, diff --git a/txscript/data/taproot-ref/db5b9f12551bfc0e07e9c89d6d5971df6e4eea17 b/txscript/data/taproot-ref/db5b9f12551bfc0e07e9c89d6d5971df6e4eea17 new file mode 100644 index 0000000000..3e9b6f5a17 --- /dev/null +++ b/txscript/data/taproot-ref/db5b9f12551bfc0e07e9c89d6d5971df6e4eea17 @@ -0,0 +1 @@ +{"tx": "e790d7e20260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700600000000a8b6c4cfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c020000000097a222af02a72e6200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987f3a42b2c", "prevouts": ["f69a100000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30", "dce2530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_78", "final": true, "success": {"scriptSig": "", "witness": ["2788d8a89c370d99883e88f683d3c5384c214aa6ab2719b7550df346a013c182b5a071050fa3800882e97e857395bfd448bc47982cdfe0ed5e6e63a2d42d5b0881"]}, "failure": {"scriptSig": "", "witness": ["36bf1292f13abd6381161984681530183cb2bc712718ea61abc593a7c3252979ad679f6307aaa79d0ce3e2247df304e4413228c0197d06e2614f0a3ed5245d1078"]}}, diff --git a/txscript/data/taproot-ref/db715816bbafa4a288124a98d0cb4df6a364cb3e b/txscript/data/taproot-ref/db715816bbafa4a288124a98d0cb4df6a364cb3e new file mode 100644 index 0000000000..3acbdb62c5 --- /dev/null +++ b/txscript/data/taproot-ref/db715816bbafa4a288124a98d0cb4df6a364cb3e @@ -0,0 +1 @@ +{"tx": "3229dd7102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfca00000000dbcb3ddb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704b01000000c5a717a901a974190000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963a010000", "prevouts": ["a632640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ed0d13000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_84", "final": true, "success": {"scriptSig": "", "witness": ["746fe437dd51c6f5dc427aa5fde5d23e51a912ed8e1881ea7e1c79127ee0618eea3264fb81b4b8ad1048f8515f5750e4ea6593e68ee068bee03748a83e23c05e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["8cdb8a151c3976ba31f9f2d90682f43e18a1a73006976fabe14d189f4aad042319b5a9e4a7fe5ce626b300e06ca341187c9e91ae689700217e86bb09570f9e0b84", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/db81d6ad0913097959d953bb6c2e7d576f846a11 b/txscript/data/taproot-ref/db81d6ad0913097959d953bb6c2e7d576f846a11 new file mode 100644 index 0000000000..0b6761831d --- /dev/null +++ b/txscript/data/taproot-ref/db81d6ad0913097959d953bb6c2e7d576f846a11 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b790100000051704d828bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ab010000002cc3b20304c1485f00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc47cb040", "prevouts": ["74b026000000000017a9144582b7676ffb8c3a2735b8e71e172a272e3e33c087", "3db63a000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "215a1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["459f4ecbb0a3a82d0080a8f3151984c9ade2caf1cd3d49ae1dd72ebf8acde1e29413500358c6cb02169f4883257b111c19e68129849ed47cf2f036258c963cd5", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/db9eba0b2b563ba067b7fd8e8ee5ddad9b770dce b/txscript/data/taproot-ref/db9eba0b2b563ba067b7fd8e8ee5ddad9b770dce new file mode 100644 index 0000000000..48f10ef140 --- /dev/null +++ b/txscript/data/taproot-ref/db9eba0b2b563ba067b7fd8e8ee5ddad9b770dce @@ -0,0 +1 @@ +{"tx": "56793ff30160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706400000000bff850ab031d17110000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac92030000", "prevouts": ["3f2113000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e15f20acab37c5a5cb044828a71c51f411f3799e0c9201344692cb6121a679af6a96525fdd0eb5f3c5c39bf5b04d78b37703e3d3b538b36e17fa0ddbdeb236a5daa4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa108807fd1da60fca18a375aa3fa2202a3eae5e0bf99a9374f58816bea445c879688f26c44e4c38ecd8996ded351dfac291f6a9fe2ce500158a378a1caa9ee2234a5a049dfcee5b69ebdb7c70e6242c675d1abc9cd58c84d7f9a8e8e1277a43a4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}}, diff --git a/txscript/data/taproot-ref/dba31a12d1adba28878c2a0b52b782a5c72d9972 b/txscript/data/taproot-ref/dba31a12d1adba28878c2a0b52b782a5c72d9972 new file mode 100644 index 0000000000..af2e2fb757 --- /dev/null +++ b/txscript/data/taproot-ref/dba31a12d1adba28878c2a0b52b782a5c72d9972 @@ -0,0 +1 @@ +{"tx": "c20c2afe018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44700000000364b2a8502b5253900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487b1e3e120", "prevouts": ["23af3a000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e11a0564ffbae55e310260a86fb5d8e023b18d3b1f7fccd674c43ebd3bc7ee476ad1aa2e9998afd312977ef35369de24510af161418b16660639891f4f8529ff8cfae4f24e00136258a4229df9ce1533cc743f70cc4e5c0214ad74c09f63cc0b9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93631892e886f9eab59552021ac67ec1685d33f952811cf826cd2d9160e628fa5a644d0ff37a890039c0ba21f76704f7cfad8b9e86a035546ebb7c5a6ad2c2135a28cfae4f24e00136258a4229df9ce1533cc743f70cc4e5c0214ad74c09f63cc0b9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}}, diff --git a/txscript/data/taproot-ref/dbef858a545baf2d110f1d0e917e4ad258acf993 b/txscript/data/taproot-ref/dbef858a545baf2d110f1d0e917e4ad258acf993 new file mode 100644 index 0000000000..4df4ddfd1b --- /dev/null +++ b/txscript/data/taproot-ref/dbef858a545baf2d110f1d0e917e4ad258acf993 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4470100000039193aba8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a3000000008ece121902c3e279000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787819fc62d", "prevouts": ["8ad53b0000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4", "73f74000000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "1f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362175f5032bb3b53c0a968ee3a2c82bc18dba93c9ba8710418637c72c2d6d5ab6ec0d930d2ad3e784600f5ffd1efb1e58c37063febb6da2a9c1576d111e3c4564ed661e9ebd30f651fa020177c2a1e4ce51b505c9194e43d6074b392863f250ba"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93675adb4fc0189a1382c89853bdffb590e4ee25bdb1025c4992edc4ac6fabdde4de576fdfccd5cb93347e3ba64a7809a8c9fb7be90a7e18659d0b981582f285e98b3e02c0e1665e1d6a4b6ef98a6ef3a3632c98688db315e4c8eb8907479035d72"]}}, diff --git a/txscript/data/taproot-ref/dc01bbbcdac6b5bb939e4be9ca56e5b8c3d165af b/txscript/data/taproot-ref/dc01bbbcdac6b5bb939e4be9ca56e5b8c3d165af new file mode 100644 index 0000000000..94002a32dd --- /dev/null +++ b/txscript/data/taproot-ref/dc01bbbcdac6b5bb939e4be9ca56e5b8c3d165af @@ -0,0 +1 @@ +{"tx": "78fb85ab02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7e01000000c5e6ddac60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708e0100000019cdf7a804af2e3400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acb51aa824", "prevouts": ["0c31250000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f", "2b311100000000002259202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["a85efc3365bad0b94f18bee63a98e02288e29fc22eb62c5f052f41b29f60279c153a5df2b7f313b969c88a1208137dcbfb528cd2393ad2a1364a332debbfcc43", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/dc0806f74a893b88a54642a35cd820535fde3ed1 b/txscript/data/taproot-ref/dc0806f74a893b88a54642a35cd820535fde3ed1 new file mode 100644 index 0000000000..80876f5cbf --- /dev/null +++ b/txscript/data/taproot-ref/dc0806f74a893b88a54642a35cd820535fde3ed1 @@ -0,0 +1 @@ +{"tx": "6feaa06102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf13000000008c1dfd8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709b010000005302e8d802def79200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6bbd63d48", "prevouts": ["853382000000000017a914a8c07d8aa161ec0fed82ac1dc93d81dd0a92012687", "53ae120000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "217d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffaaa48811ce5d96ea10d6e15d7cfc53aa0391399ecd77424ef22989b7ffa3a21a54b706cb1ffe8cdd8302265f43043d8c7f0cfca18957505a6e0d7d2690f95c84bdfafc9427bbc75e549436fc0749ee4f6acf063a9661c81b3024fc653ae79a"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369c5c44f52676cf7b33376b75ee003282f22d070fd845339939cf148bbb71db7cdc39cab162b5ecfeb387365be0497ecf3ceb69817352d9280526c0f75de7c14184bdfafc9427bbc75e549436fc0749ee4f6acf063a9661c81b3024fc653ae79a"]}}, diff --git a/txscript/data/taproot-ref/dc161355dcd6047181d0cf4e25b6a5525f6fe50e b/txscript/data/taproot-ref/dc161355dcd6047181d0cf4e25b6a5525f6fe50e new file mode 100644 index 0000000000..d5e313c187 --- /dev/null +++ b/txscript/data/taproot-ref/dc161355dcd6047181d0cf4e25b6a5525f6fe50e @@ -0,0 +1 @@ +{"tx": "81800ee502dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bad010000009e677df3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3d010000005da75ce303080a4500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e785000000", "prevouts": ["6a952400000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "9b09230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_9e", "final": true, "success": {"scriptSig": "", "witness": ["7c9bb0acb751426c5cc6ea32a3f5c9347a563ef2988d59352005d1c36cc6f0bfa59c4e63837ea561e1d1e26a84e6276861a1d9624cd749494f17757e17e26c2b01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["32f21156cdbb9ded6aa9fe145d74d41b68d28db695f49c8fab7b369fc021e05fb27ff582fcb87c198c65366d897997a3fa66fa6047fc1093912012c7fdbe8b999e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/dc3539d6d3a6a1eaf48ce5185a088eb43b9e383e b/txscript/data/taproot-ref/dc3539d6d3a6a1eaf48ce5185a088eb43b9e383e new file mode 100644 index 0000000000..c0c20e86ca --- /dev/null +++ b/txscript/data/taproot-ref/dc3539d6d3a6a1eaf48ce5185a088eb43b9e383e @@ -0,0 +1 @@ +{"tx": "50f7ec8e0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706701000000a45b1eefbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb501000000d4e342ea0211518b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7bfe0a757", "prevouts": ["10c212000000000022512019a5b11800237af5c16615500994d92c1a7914053179f3c566b1561c365a8348", "41977b0000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902b151d05f5c544acd5f2fff279a3779ee8e89af81e18d97889353464eaadb130e8d3413ba6e577baf4d8733c0b095f735ff202c72d9575d28728312b33c499e7f4e44d8f0ed55b71ff8a33ebea3e1652fa9859defde465709be500aa03793b3b9b07561ec0126bc3e82d419006d041a670775dfadbe4e9e78025cb2b6d140da291a4441a0adef86c62c7dea5c5b1ed132608d00865780bc2f3cf6bb58714f97eb297a5b4055ca996975749aa2a69f2792f39fc0e3c0340f33d60bb232311b33a8fcf95e330a8e5bf4352b0d3c29874702cad5c5ee93e40307a0697dcd8c03de4cb9ccba6a679ff08b660e5b847ab96d1304484327d32d1c7531db3ff32728a2fb7c72a763081dcb518d811584513db3cf2be291186e6282921ad0ba3e9de4a7eae013147022dc494ea27fd2df005abddf10a820f9b7b4a9bae2ce7d0315656fe1e3099059fa0a07c69f923cbe9c5c50e86a431922f4fdba4537c5df9444d653e5580a6e3cbbb7335192c1760380b652f028af1727be33147807b01c0665ea90b617ee004dc59c606e981ef4ade9b226b2598c3041f45d07091b87c42d55767dfc4dd835c6ce1ed27645b8339df3b93270646adc22e396685605f5a50929fa6f3f40c0e35f651d8fe82ed4c6a97932bab711eed801a2d8686f447248d5632782048991fe2584f2a532df7f58ca64ca6c64c45aac8a5ab26dfc1a5cebd0a3c66606bc3bdf1d1f8312c54275c2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936df70b12ca9ad71e3708c972229d1f7eefd79706f0a4ef65e90c6b3ef25905faef0288dcf8f2e1e03125ab45cd0efca3a23715e7661e5c17627e98d50057f87374b5cd80fb8cd7c947a98554a389db356265b198fc72df311d010d98c3d6e3928"]}, "failure": {"scriptSig": "", "witness": ["4d0902618d6b37504d0441f180e56a75d19e5e3302c2dc67943293ca97dccf79de9c8757aa9259f2d7806dc2b6c389fe32a3755e0b3012fcd2a6eb9ee38a1c5e1ce2691cd369e5c50b7f74d07600fbd9d1f3a1e178f5fe032dcdcc0a2928faebb3ac395bdc946d625cbbbc03e3613df56d48022e72c362e06b078f82e765cd80078dc15df41d9a8f77e9483b19a595ab1462f53d42c828a5f7600ec63d67466ea1d91df6bbd1696569d02707c7512a654c7398734bbc132037c8528700a44cd86417a5ead73157f285a5164a3a5ff9d17419c6cbc20c8a32651197418e4edb7b8a4e38db201e8e97aa0e04edcf0c5d3b9388f191faf37aa3153be0fc9d4cbd505bd91d47c8c530c37391015ec0047816b4aae30d91a0796a6b9377e32b9a69c5b75aad97eb141a3cd2d0d0a766aaa050ba03403171fd31895bb63ddc5a35d440b856cf994fa1dd9834099dcde68eb90c988741bc87d4a062b6147829b5b44b6e873fa553e8d5ce15257a4b2fecb4e4d130f614618342b541b848b2e7db72cc0d90a7a835b8d04825de3cd7fd3b8aee2d42784aec89a48cca971e681e0d87b5f43726426d23498cc28f7eb13ca9b395c1e345b2fb2cc16ace2ad4dd025aa492ac7c20505d2752b936b5da44acfa0efb85b48099a08d12a082167ab3e2cc9ce36a09a5aacf12fe920f43ee3144d4a5e2ff88750f688c1055e8c7ac4190cba8691d0438f210dc6a4b51226e9a037561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bc1c7496d6757072a067a779454a816e2c160e7eee0de44d001da2d4f54ec2983f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08208660b63218e506e6f6271f897377780851eb071546e65f7287d9a4083d90048d0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}}, diff --git a/txscript/data/taproot-ref/dc480267e0ef9ce538b42b77872f2b3532c35322 b/txscript/data/taproot-ref/dc480267e0ef9ce538b42b77872f2b3532c35322 new file mode 100644 index 0000000000..adc9d61c64 --- /dev/null +++ b/txscript/data/taproot-ref/dc480267e0ef9ce538b42b77872f2b3532c35322 @@ -0,0 +1 @@ +{"tx": "c5f01f0f028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d50000000053b9fe8c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ea00000000961af2b201963241000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a653040000", "prevouts": ["1b69330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5a393e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_2f", "final": true, "success": {"scriptSig": "", "witness": ["01e67d9236e680014b0a43138816d86775c08e96eb5097d6286cc11f1af3584e0f3d9e485fbe7ad42e6b51da2f6358de56b8892fe01be323da3409b86a82be2182"]}, "failure": {"scriptSig": "", "witness": ["7ac7473fc85b9c2eb526adddeb3d8ffe2caf07dbddcc9c7abef2e572eee73d23fbf64d26d34185b466652df784329359d5b19b6d4b077315b879cdd95657b6342e"]}}, diff --git a/txscript/data/taproot-ref/dc57d8ffab2a6632708a04cb288629b09aa5c82e b/txscript/data/taproot-ref/dc57d8ffab2a6632708a04cb288629b09aa5c82e new file mode 100644 index 0000000000..cbf5878db3 --- /dev/null +++ b/txscript/data/taproot-ref/dc57d8ffab2a6632708a04cb288629b09aa5c82e @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3800000000d4d32d95dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb4010000008376eebf04e5a4bd000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac14000000", "prevouts": ["7e08700000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "c0bc4f0000000000165d142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "f37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936111cdf76836f174788069938d43a1f118e1d6048d7db416209f274b647d1178e3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cfa000ce8b9790c39a5d5a4e1f475bb1ef714fb8e08d79945cb39f042227236d80eaa4a5149b34d26f0437dfc3cc15f8b829f232fb4e000d97f0d76bcdb6c884"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368ad006099a5afd91da2bb050912b31486a1a5f178aed6fde7a35ffc349c590e4cfa000ce8b9790c39a5d5a4e1f475bb1ef714fb8e08d79945cb39f042227236d80eaa4a5149b34d26f0437dfc3cc15f8b829f232fb4e000d97f0d76bcdb6c884"]}}, diff --git a/txscript/data/taproot-ref/dc593bc1e5ac44230400eae2d39c99148ad34e4b b/txscript/data/taproot-ref/dc593bc1e5ac44230400eae2d39c99148ad34e4b new file mode 100644 index 0000000000..cadf31d6b5 --- /dev/null +++ b/txscript/data/taproot-ref/dc593bc1e5ac44230400eae2d39c99148ad34e4b @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fb010000003f2b16d5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb10100000040c4b8b401a85c0700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac817e0b21", "prevouts": ["29c23b0000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588", "3cf4590000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "da7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823fb4f37cceedf64e5ab756f8bcf3191fe56bd549db8641e271ceb60581364e38eb0481d56926b359fa3e2e34471adba51fafc61fa70dea7541795bc082db9408"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93640073767799ee8ff1c3237f84bb48a6083252a313c1fa00b27a2ee1d2ebb2429bb1bf216bf716c84a1c7f4bdf291db4b4c93f804d437ac6faff07f214860f972566ba3404d3656bfd0df4a55f82c254cdba579fd51be164a5cd21fa2faf92a44"]}}, diff --git a/txscript/data/taproot-ref/dc6dcb26e66c42982855aa1a52a31fd33b250e19 b/txscript/data/taproot-ref/dc6dcb26e66c42982855aa1a52a31fd33b250e19 new file mode 100644 index 0000000000..854556bf4e --- /dev/null +++ b/txscript/data/taproot-ref/dc6dcb26e66c42982855aa1a52a31fd33b250e19 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8d000000009628e1ab8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f10100000041654ba460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c200000000352cd7d102283e7a00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7eca46228", "prevouts": ["be4828000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "99de42000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "344811000000000017a914d574841bde7bf0817694c799002118e85acf040e87"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "235d212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["69e6bc89953f2b0b0c076080e1b1bf82e003d213bc47f2decb4bfb7dd00185074d1f0b339d45eabd92e63f1bdfc039a5ce924f42bea5e81dcee29d9e9d181099", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/dc9395f17d85f800578e0d6e8bf89ad9746befb7 b/txscript/data/taproot-ref/dc9395f17d85f800578e0d6e8bf89ad9746befb7 new file mode 100644 index 0000000000..946142125e --- /dev/null +++ b/txscript/data/taproot-ref/dc9395f17d85f800578e0d6e8bf89ad9746befb7 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a0010000004e3bc7cc03dc0f100000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487eaddd940", "prevouts": ["37d6120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_59", "final": true, "success": {"scriptSig": "", "witness": ["b6d3a366aff24b46704df81362b580979561a3b16a1c4d76434e953d807fdfe29a4c23a73ba23e64c4bc5aa9d740b938e86ac7950e36377352031ac309fa882083"]}, "failure": {"scriptSig": "", "witness": ["9bfc637a2a6385d9b8593f113685a19173e12cab9b1fefa49cde86302930010671a0dadf6e5138f2167e15616224a826a1b38722abcee3820132ee2950d781e159"]}}, diff --git a/txscript/data/taproot-ref/dc9899ac6fe73116d5e9f16eb5d414386eaf20b6 b/txscript/data/taproot-ref/dc9899ac6fe73116d5e9f16eb5d414386eaf20b6 new file mode 100644 index 0000000000..1000afb983 --- /dev/null +++ b/txscript/data/taproot-ref/dc9899ac6fe73116d5e9f16eb5d414386eaf20b6 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a4010000007ffa04c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b250100000082473360dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0b00000000b573fe37040fb04f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e790c8515b", "prevouts": ["d2ef120000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278", "8cf01f00000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "df861e0000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "7c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac26c11d7825777e0f2ddf610788c970bf175cde25cef7de4e72e41494d53bd31202adea3ba63b8efb220ed0b92cf765f01931ebb31f4963f663d14c15b1e6099a711983bc616996e2ac47b27808b31a9b7e87f7ce1f3571999dd3a2a57f1080"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d5fbcf61a2a7c737f60b9029794ca77d60e8dfd9dae9f2322432c03bed71ef108eae3f5bf5f4c26def68bde658fd1412dc2dfb494d39d6b1bd4ba6a274f177d9a711983bc616996e2ac47b27808b31a9b7e87f7ce1f3571999dd3a2a57f1080"]}}, diff --git a/txscript/data/taproot-ref/dc99d264d246e0de31744757d56e34f81e69221e b/txscript/data/taproot-ref/dc99d264d246e0de31744757d56e34f81e69221e new file mode 100644 index 0000000000..0e1d0c88bc --- /dev/null +++ b/txscript/data/taproot-ref/dc99d264d246e0de31744757d56e34f81e69221e @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270780100000092a442168bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40500000000ac1f958adceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2b000000009c4898ea02e6d16d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875a481120", "prevouts": ["2b3f120000000000225120c10f9a5287d6d37684b1ac107332d66417d952fdf60fb9cd3e9fa5de48c339b4", "fcef35000000000022512070bce5a25570b494d89a85af7ba09d895150a56587b7f7acec0c02ca42514b39", "91f927000000000017a91452f6f26c4daf61bee17f895b7ca2f2ddc941756987"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100f42f6c018177cb6f7105c075f99d29a4c97a752dd0c249abbf778e3c64da803702207c67f762f80a9017759a0a8937f633674b978e631e3fe50f0560dcbd1fdebf47824104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}, "failure": {"scriptSig": "47304402204603179e9745c6afe10773d58da9ccbab4370b6e6797d3c23e24133311c6ad8502201b8b93b2a5ccdb37f9100d56efc80eef597145e1887b75b74281ecd793cb61a0824104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd218931976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/dca299a0e651d9aa555003ff4a5031f3fccf9743 b/txscript/data/taproot-ref/dca299a0e651d9aa555003ff4a5031f3fccf9743 new file mode 100644 index 0000000000..3f88d32140 --- /dev/null +++ b/txscript/data/taproot-ref/dca299a0e651d9aa555003ff4a5031f3fccf9743 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa201000000a54e1d1abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff600000000058fe3ae01afaa8e000000000017a914719f78084af863e000acd618ba76df979722368987b0010000", "prevouts": ["b38b84000000000022512005ff23ad1561e684c08dc4654c3a622730f716f9dbc5d4d5a4cd20d536b8ae37", "e07864000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361759826991d2ee0a231520f5bcab8f69f31b666272ed9a6e30669b1001adc5384cd3bb01e072d01d43d3082324ff6e625f5d569cbe89802b785fdd288bfd31c9a3f8f9fe88f0f431b5ffad473abfcf1c4b340e1c7daa1232bf4c86f035b8cc51"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8ee33f25a3bc4431a4899fa373225b82f91b265358d1b8c12eb75241dfe6f4bf6dc39ce81a6fea632ecf565fa45d7a7ca50aa2e3b548038c9066d72b539243596a6ef766bda57b4717926485a86d332fc460fd2733e6a54825f17015621dd4290"]}}, diff --git a/txscript/data/taproot-ref/dcaa02212efb1b1d7b35ccd1cd382be6b3e66e71 b/txscript/data/taproot-ref/dcaa02212efb1b1d7b35ccd1cd382be6b3e66e71 new file mode 100644 index 0000000000..e19dd80f08 --- /dev/null +++ b/txscript/data/taproot-ref/dcaa02212efb1b1d7b35ccd1cd382be6b3e66e71 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfae00000000c465f18adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8c000000000e1ef5a50158f18b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6221bfc54", "prevouts": ["cd3b7a00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da", "c6be550000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "807d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a0a4157aaff13ca2809f2717d1454e35c7fe22b58bbf3d38eb14bb2d8f6dda2c9bb3dc44e72947935649b33aa2d807ea07560e0c2333a7ee2c40c2820b24a64a090cbfbdc5dfcad7ff4463f3cf2898b3c754f5d70a369d7bdece79053e0da647"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e6d3ed6bb397f900bca42f5c55206e9e9a5556fe68666fe0d64ebb28af9dc03c732beddb8df376ed0f15f8ca557ca4fa4dab9ea34398a6bb2b3d4cd5dda00bcea090cbfbdc5dfcad7ff4463f3cf2898b3c754f5d70a369d7bdece79053e0da647"]}}, diff --git a/txscript/data/taproot-ref/dcbd31842dac9e7cdaf7ca65e510582bfd1d1a9b b/txscript/data/taproot-ref/dcbd31842dac9e7cdaf7ca65e510582bfd1d1a9b new file mode 100644 index 0000000000..87553ac9ef --- /dev/null +++ b/txscript/data/taproot-ref/dcbd31842dac9e7cdaf7ca65e510582bfd1d1a9b @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6f010000000801f9338bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44e00000000cafb6acc04e6afa2000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac06010000", "prevouts": ["8cea640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "606d400000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d6", "final": true, "success": {"scriptSig": "", "witness": ["99797b3bef2647f0fc3e108287a672fe2690ad2f27eeb822b6af994efcd1d7fd99e746521c2b5d4c5950cd4de1dae34a8e5f901e1d03bc340b0e61d8d8d1180e81"]}, "failure": {"scriptSig": "", "witness": ["42bf19149e0537555a9aedfec5cf298a03d6d1cf9cbee9c02633db46777e2f7d68be071519d2e6225543a85093bebde0c65a44201d746ee5e1de054c727f36a5d6"]}}, diff --git a/txscript/data/taproot-ref/dccaf2fc47adc1a3b05f03d5fac2a95f989db10c b/txscript/data/taproot-ref/dccaf2fc47adc1a3b05f03d5fac2a95f989db10c new file mode 100644 index 0000000000..4da3d28993 --- /dev/null +++ b/txscript/data/taproot-ref/dccaf2fc47adc1a3b05f03d5fac2a95f989db10c @@ -0,0 +1 @@ +{"tx": "5c4be34a02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe001000000849623b560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127009010000005cf056c8010da88300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acf148915d", "prevouts": ["3a4e83000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "87df120000000000225120656f89671a8f47d6bf2e8e427ddcf5c0f85be8fade6cfb3bd1e5b2fd091df805"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367113f827a4d4aa8309fbec7694384e6d0aea4a4c939b956fb497455d6a3b7402"]}, "failure": {"scriptSig": "", "witness": ["6a7d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/dccd7c4272928f022003ea9c7aaa12dcc004a54c b/txscript/data/taproot-ref/dccd7c4272928f022003ea9c7aaa12dcc004a54c new file mode 100644 index 0000000000..b2e437034c --- /dev/null +++ b/txscript/data/taproot-ref/dccd7c4272928f022003ea9c7aaa12dcc004a54c @@ -0,0 +1 @@ +{"tx": "bc10ab850360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e20100000056ca8ef0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd500000000f9c6cbc3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfc0000000042284be90453929600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e73aa04c47", "prevouts": ["1d5b110000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "dc1d28000000000022512026e2288702160262aebf9b5500cc105d511ee57f41882217b8afa588f3f75fde", "74b25e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c35cd12e8df2fb297eac9d1d135ad50ebd5c464169db6cd9048b151cc7b74cff30080bfe0d76f5066f10c66f5d5c3ff5fe5758eecd3e6b9073fc254bed53c0ae7a5a7f6c287e55c2508813e4a2d248a2412565afbb00cc59f351354b41e897d691cffbca125e9cc38dadd2bd6a98fbb0a43ebb9c62fa8983d26463a9832d19fb411274d4c7f5d6e4b9a56ada23903fa750e271ba59746401cd0606e400be1948c91bf922835d303611e8d7d6f74a6f21af328a37ac045f1895912150ca9181da44410b8fbfe45ce02fa88dc842f161a8c058ea95504a177df9b83d21fb749bfc74c3873c7cd0ea4e084ffb352a1b6b7d97217a6b468aa140a782328890859efab80349b7e9d689a6e588b87397903a7c54fc8b79b82f985f56d3bba6ca35c940fcfafcc8fbd7d1aa771b6aa91e6478222b3a6839b7a5a174d8eba8057fceb5b4516e8a5fedd334b26c57fffc8f4c4dd2311212e87e176ed0bca301c5892bbbdc608766c77c1c8ae9fd65ca3fb91952bfffec93d0beb79cd1d50842d02d74129e28924de0de4ea1be5d02e808d7f87ea2e4db9a635abad9f010e7547e6034b1f68d900268a7aac3aaeadb2d0f75b9017756b8e7bb847053ba194f6bedc7b48662db89a5943ef93d2c921fdf32d517081d7cf6c12d3638aaf5395805d5657e6d1be568a1036aeb9b78a4025cefe05dc5ead041670a24224000cdff2ba4148d1107d832450fd66c7b3a1775f7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368e053cb9a5d09bfe690ea9eedb365d345eaa3c8a3a4d080ab62035ed4ab4aed83e2d335f383706a312226510c4ca5ed297e59b2981bccad977d4984b4ab81a7bbe0beccf8b53a38f7a20d51eb008bdc60f78fac094fdd23935202ece673d8622376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}, "failure": {"scriptSig": "", "witness": ["4d0902adbacb7afddf1a2658f2562dd9d05cef4dca2c5b5a80cdf085afbd75b0fa25fe94e951d0bd501d86d1a523db7db3e039f84aa26d1c3891d01fee2a5b52645b26a9bc08b60629c89eabbaccbb714419f52fe39ac746b8e6518c5f4782e74988c70f0fe5ec57cfb9713595c9219dbd29e9afece13d20eae6855e297f2893ab244ec7948f513e22243fdca3961205f2ecacddbfab385edfd5cef8404288a95b099faa6388602ddeefd5b97d1ddd4047cd504f418e770251b58f7b4e0f38f3fddbbd39f51f97ae2904fdb80276fc00da90e8cedc82d201f4f6e6fe89e72168f826cfbc4ab45eea1b564629e01706c5e6659f2768bdfad1b65af704b4559df38f19cd1c10a888a3f1bdcfd643d231d316835f2c78ca297b6acc7886a727b386ba9c2a79ce978e40edde47bffd7c10adf01479b4c9298f789b348586971038b4b8f87d481a1876614929b14270edeab577b0986b222919d1a6e05d339a7b4e9fe49487eaaee65571644aae9eddee531d1cc22553abca3044de2f33893ebea6e4f54747052ddfc1379c73b40d19c6c665c12e43cd5c4b410914c88b406b86f3e00b80973581d9bb45a143b02ff8f4ef8f13d1863b5deb68eb4003bcfd0b352c59c3bcf8234d41cecf2e380360009b3f0ed6b59f4ba6a835b882a1b2b80b0fff3ee410d1d8c41f0eaa2d3b70340e46c711d7bfb4409a54f9a9ce88feadfb1f42b73495ca830ad862bb77ffd4f87561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082c18d13f23505bf80401329c8d1a0bac5ffbe219ba0d96925c38e985a7086f175ac8db205c7d3bb0390b2e22910f5d1cbad00807eee3325f4c4e7f4412ed3064a1c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}}, diff --git a/txscript/data/taproot-ref/dcd041ba07357566b4ee1ed3cbca6574c6154f10 b/txscript/data/taproot-ref/dcd041ba07357566b4ee1ed3cbca6574c6154f10 new file mode 100644 index 0000000000..6eed590c9d --- /dev/null +++ b/txscript/data/taproot-ref/dcd041ba07357566b4ee1ed3cbca6574c6154f10 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf56000000009d725befbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa600000000046d18dc04521cf200000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acbc0a924b", "prevouts": ["e40573000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "c8ad800000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "", "witness": ["30450221009b401ebef219005e3a57b6d2be0cedf1a32ad249bbea0bcaf018dd0d78d25cfd02205722f3db1fbe3135c63e7458cc0026e0c2d5ea86cc0faa7867315a0bd906f91d82", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["304402207c56c6f56386fec171bd13e5727eefd8a6873247188b2160d6491f7e26a3689702206b0578c1093d9edeaae3eac932bae1ba5a729c4926ac878176c8f671139a8ce282", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/dcf7577a80ecef6f3ca732dc2e3adaa48e682fdb b/txscript/data/taproot-ref/dcf7577a80ecef6f3ca732dc2e3adaa48e682fdb new file mode 100644 index 0000000000..64ad8ad0ea --- /dev/null +++ b/txscript/data/taproot-ref/dcf7577a80ecef6f3ca732dc2e3adaa48e682fdb @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700700000000cf91ab8ebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1e010000002e60e4f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43f0000000034add3ce038151bc00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79695b58e1e", "prevouts": ["055d0e00000000002251203236882dfaab6a61030776953d98ee1af902cb36dd280fe66ad8ee191278ec27", "e3536f00000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "e1fd400000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b3dde2cf2529f9d05b2e5492588ecb6418b108a4e637793f6ec2e549504b90ce"]}, "failure": {"scriptSig": "", "witness": ["6a59616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/dd000d20a2f313c18520373a1f18e05ed9a150e2 b/txscript/data/taproot-ref/dd000d20a2f313c18520373a1f18e05ed9a150e2 new file mode 100644 index 0000000000..ef661bb9fe --- /dev/null +++ b/txscript/data/taproot-ref/dd000d20a2f313c18520373a1f18e05ed9a150e2 @@ -0,0 +1 @@ +{"tx": "b1bb4f9803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2400000000817a20b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127002000000008e1dc3c4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2e01000000783f4ee701e06a59000000000017a914719f78084af863e000acd618ba76df9797223689870f010000", "prevouts": ["90cc23000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "7ab50f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "546d5600000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["bc4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08220e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e14a8563068286881d42b1c4901d93a483973910fd5653bf7ebbf040741f7cd837150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}, "failure": {"scriptSig": "", "witness": ["4c52bc", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a882b0c6bc267a79bb740ac1a2362d94d3f68ec4048cb2b97f57abfb863c1e846628fbf290b9055f1812e9325160cdda478fd06188bac581533b5ab5319162eb04966f092bf1e4b4348fca11e7254311373308f7fc15e3d44d6a2afffa343c9657ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}}, diff --git a/txscript/data/taproot-ref/dd0b6ef4b264cf0858480a3460b856a1c8f6dc1d b/txscript/data/taproot-ref/dd0b6ef4b264cf0858480a3460b856a1c8f6dc1d new file mode 100644 index 0000000000..8317233251 --- /dev/null +++ b/txscript/data/taproot-ref/dd0b6ef4b264cf0858480a3460b856a1c8f6dc1d @@ -0,0 +1 @@ +{"tx": "8bbbb434028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f7010000001a4f028560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a5010000007c0d8cd903a9a243000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc79e010000", "prevouts": ["bcb73500000000002251201aac33169e9e7c3154d6a008d33b220a63d8a9ebf4646c8ee915f75ae7529b5f", "7f111000000000002254202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["0b29c03cd81df73a2b574156c0daea3474ec5851a59a011a7d667c3a3646addc88edb1946575a4f48e3b2c20e66d9cdda77515ec287f3b5e972d0c7858810a34", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/dd51571565035f293d86c40ad779317f87aedf8a b/txscript/data/taproot-ref/dd51571565035f293d86c40ad779317f87aedf8a new file mode 100644 index 0000000000..09442da743 --- /dev/null +++ b/txscript/data/taproot-ref/dd51571565035f293d86c40ad779317f87aedf8a @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701e00000000c57d4392bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4d0000000052ad4c7c030fba7b000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8b92b750", "prevouts": ["9f611200000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5", "65ea6b00000000002251208b7fe9d4f09d2d8e7a4070c707b9c580ba6935dccb7bf02b3c8420577f22e1d4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93684086780442dbcf859ffd73a59f855a4b5c3e4d7f57dc79247a591757b7f2310"]}, "failure": {"scriptSig": "", "witness": ["6a04616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/dd6e129061e453f9a72be030e9baeee3e56fcf0f b/txscript/data/taproot-ref/dd6e129061e453f9a72be030e9baeee3e56fcf0f new file mode 100644 index 0000000000..11712ff558 --- /dev/null +++ b/txscript/data/taproot-ref/dd6e129061e453f9a72be030e9baeee3e56fcf0f @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4280000000012c312408bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44b00000000ca4d1b9204be1e7100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc70b020000", "prevouts": ["7eca39000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1", "85e938000000000021551f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["7ee4a8652a801c81f21832a7f20b2aeeac576839e9f39d404e47e760404363a752189c2e02859c0b294e9c8d33bc582084722dcf67aefbe0d7c9864b0815deaf", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/dd8c174c7b3d3ef26b6db13442b39a50c7f55222 b/txscript/data/taproot-ref/dd8c174c7b3d3ef26b6db13442b39a50c7f55222 new file mode 100644 index 0000000000..5cc48ab3c7 --- /dev/null +++ b/txscript/data/taproot-ref/dd8c174c7b3d3ef26b6db13442b39a50c7f55222 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be001000000a799f40abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4f010000001e21c462bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9a0000000077dd0fb3022989fd0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a611000000", "prevouts": ["025a1f00000000002251203d94c30f7ef8b0d9d4c7a773497c0af2bbd0a232f6e89c19e65bba66d7e2056b", "c0e969000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "f4dd760000000000225120ff67dbe5f480d52a3db68ddc8756a5701c353a5e478c53504b3368e48f095423"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "2b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ed75fc84f2af88925f7ad475b3203cbf9256a43a0cda52d14a3416be93a7fb1c4d74d03d2cf0ae79996d1bf896237ca201e78f1b4c5ece550af4c0e01e9fa9886"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eb23e8c041b6f4d0a05567219b1a5ab7cf1a58d3c1a796ae684015a86918ec863f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082885bea8937005622f3eb8b2c440108feebbdb5f3ff09e0402c722754cbcd9b2d195038de5261112827291f7af9c58b034003ed818b7e5ec0d4ccdf81f6c2ea4d"]}}, diff --git a/txscript/data/taproot-ref/dda325195c906944f23de872fa78b2af88631c09 b/txscript/data/taproot-ref/dda325195c906944f23de872fa78b2af88631c09 new file mode 100644 index 0000000000..46f0eeadce --- /dev/null +++ b/txscript/data/taproot-ref/dda325195c906944f23de872fa78b2af88631c09 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1c02000000d71284f38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a6000000003d5157d4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8501000000f9d154d30318e4eb000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33000000", "prevouts": ["bfc05d00000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428", "4d2b37000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "cbce580000000000225120aa00b33df18083b0bc269fd07ade71d6a19be5cfe3bbc4e226f77b4058e47cd7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a6bb84e606fb4bb9387730170fbca9e5289d9440f7292b1ebb809b518ef1c84fdc80ae76bb602ab42c46ee853876ca8af61f2b21e003be040fdb009bd17dbb4f808384abb6b187f3a97f85a063898a14354bfb17bdb5626bb6d4aa801087006088c291dc1aa090e3b655056beb5ce7365d5ebffee3580e955fbded69dfd9656f305ac12737920f128f98e38724db72105d47ccf6840d2d22c6868ec556696fcbc081736c6479355882158f8726ea12bbf670d0eac31becf906b74921eea7a9b485468c42290d70e72261e0116bfb043597a3afe9f7779165e7d71f7cec739431151e0782a674060d44293b0b30b0e0d493e6fa018ff3060b0ba0c13acc5c5d9f8cef8ecfcd7f3ce64c4ce9155b12d09f350591a77e1bc9621af17727c816cbf27d5d69b57bef31e5cfa79c3d9e13787c9d339d245c82eca9e912a0a8b367cb289dd644b4437e5102db1ea0cde98f315bab58e280843fcf83d43273a407759260d8923d41234c55e9b71d39bbde607457b1b3b3200b8003b7611559ee92765aa262750cd1d92f91292b98bbd0da028e4cd990d8b4d5e308d6e244d229941183f85edef40a13349eb4c5c53df23ab5a6db33699126fefac34a2c7bc06dc536eda3ff1e3d70568bba7896e628358410ecfcbbaa858685a949833f02a8426c1b65a68021097bdda07d856151940ab1e401679bfa34cf7f12c294f7d9888afb651ec01ce26bb3e3f800737475", "577d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bab7869953280f6d3f7a7bc51b385a6914d08ccd41c6d33c824b12a8cb000a8b3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828cd69c149de1c0fd775c23d200817106db3811e77c5a94d49bd03e58d7bcfa223a8385792857b3824bc259fd95f469eb32c57805e5f383de6590f06749d208e6"]}, "failure": {"scriptSig": "", "witness": ["4d0902abf2f600a9304c04bcce9bcac11aa4bf71b23d1edc75714bff9d6d16c8b4c5f5f764a7fd68bffaf5daa76d8e6d2178c799216e396add1c552420f5f03b5f17cc42999a48a67c6253858a591c679189f0512fc421cf88286940215c9da0c89bf99fc0eeaa098a302b407fe5262103b0c1c039ed5486baa49ef6c661a987421a1fccc490adcf1c3b9355bfadf7f64d98b9b5ebe547630205f30ad78b502369ea7ad94967397b938f2f8dee79fe42d0142588028f3120f3119a8749aa662a48d6d4a1682565e368c69497c961f651f541d5ec37db7e1eb5d0943dcf7d18814ca548270db782a374b5fe181e3aa4d71316491cdcf059eb3aa8360bb2249982e57a1ead8a1a033f063f64dac81aac257489a8b482531e8659415f9211e572f2a9adf107e4678e472f40dc676c071e71633d1e750fcfa9e567a932d6dff1d259b3a949c07c2e07af45a964fbbf0cd03fd064c49db660e1cea47993dace6959ccfd8f9ab18e9dd74363aa9126ad872f0213643488a74cbd376177e8f73d724bbbadb6c192d640108cff927e3ad05ff85d732895e2d96f9ce0d68e6e2c77b897a9c8c13145825c695d820da1b299c2c768559067c093bfa465721231be70ec67b8cf3b1ee78b887a5145ca97d1248d0d462c4c0510756fb6ad7028fbef3691262d862ea39ec0ea007d322cdb02ecd216f02b7ebee9e29d21a810e98ffc0302ee094db2525df955699153203ac975", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef4a7dcfb64e618b34998ea64659fe772d1fd358b29e003b2257b85d2ca618476a66706abdbe591f97764059d8785051c12d40b9c9543fb83334d204ae23d8b59"]}}, diff --git a/txscript/data/taproot-ref/ddaf37dc11a8574b722f076f36e746bc7c60e215 b/txscript/data/taproot-ref/ddaf37dc11a8574b722f076f36e746bc7c60e215 new file mode 100644 index 0000000000..58944f5a5e --- /dev/null +++ b/txscript/data/taproot-ref/ddaf37dc11a8574b722f076f36e746bc7c60e215 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd60000000099b168e7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb2000000007a2554fd01db7f7600000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac30020000", "prevouts": ["05864a0000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "291c560000000000225120327f04e65f02f8e03ce78ab2157c33b783b64287146459b669c40017b50fedbf"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c4981c98d09047ee82e029176f402026e6ee9597298967debab1e2419faf3d4a"]}, "failure": {"scriptSig": "", "witness": ["6a36616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/ddd4994f43b538ffca8eb9b28ca5fb499238d0b9 b/txscript/data/taproot-ref/ddd4994f43b538ffca8eb9b28ca5fb499238d0b9 new file mode 100644 index 0000000000..3b3076b605 --- /dev/null +++ b/txscript/data/taproot-ref/ddd4994f43b538ffca8eb9b28ca5fb499238d0b9 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ae0000000047920cabdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5301000000a1ccabe104ac0f5b0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9e8d6f25", "prevouts": ["14790f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "910b4e00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_csa_neg", "final": true, "success": {"scriptSig": "", "witness": ["", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["ba6d96573030157ef56c9d58a9f6e2a8f1a2029ef3ca0c7e3c6029ad8ca7c939d505002e346ef8c252c3a611a23a5cc65a692ac2493fca52ddbeccf55d7032", "5220aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5287", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439beb67122ddc1617dce4a8b1a7532423bf4057eaff692b9473bcfe092baf144466dd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a3754b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/dde699e331a7df59bcdada620624b5ba61dc5dd0 b/txscript/data/taproot-ref/dde699e331a7df59bcdada620624b5ba61dc5dd0 new file mode 100644 index 0000000000..9715e72660 --- /dev/null +++ b/txscript/data/taproot-ref/dde699e331a7df59bcdada620624b5ba61dc5dd0 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1602000000242acf68dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be400000000ae8b607802db5a4a00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac46000000", "prevouts": ["b1e125000000000021591f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "55a626000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "final": true, "success": {"scriptSig": "", "witness": ["04b024de73e0ac65162974d16ecbcb5344408a1f2303658c477ad436b50d7a0d170f01f16ebd920f4b9c192d817db5a2d631b2a8cb30509bf210822d5121a55d81"]}, "failure": {"scriptSig": "", "witness": ["e14cb87c7c2b7106c97582ec52117c0baf173593f092a800e8514885f11c92c2621b4c1a97c87cc56315d3e22eb73936548eb923070084e09f9e4de56a58b73b81"]}}, diff --git a/txscript/data/taproot-ref/ddebb704471c13ddfaf31413aae6c013515a3717 b/txscript/data/taproot-ref/ddebb704471c13ddfaf31413aae6c013515a3717 new file mode 100644 index 0000000000..79cb9ea6bb --- /dev/null +++ b/txscript/data/taproot-ref/ddebb704471c13ddfaf31413aae6c013515a3717 @@ -0,0 +1 @@ +{"tx": "778899b603dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c95000000007c54b39660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fa00000000b5fe039b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a8010000002867b9b101c0ee1900000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2bb98647", "prevouts": ["325f4c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1bc120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "09e33d000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d0", "final": true, "success": {"scriptSig": "", "witness": ["ba093c0e952d439e8dd83a7a9ff81ab4bfec29c44d47b1ddbdbcb3d47423869423f0cc753b8d3fa277b7a7f7d96ce6bdb715c773bdad20f48b369eda0ce5434c01"]}, "failure": {"scriptSig": "", "witness": ["150bc1c19fb98d8104ecf60c020b122cf117a8f86e2063c6e0fecf4ef426756940946e2efb395bb2a303c875115f02fe495d8cae2834c762a12c956342e745ced0"]}}, diff --git a/txscript/data/taproot-ref/ddedd372fed9df45da4d1a59cf4f5cb35009e49f b/txscript/data/taproot-ref/ddedd372fed9df45da4d1a59cf4f5cb35009e49f new file mode 100644 index 0000000000..99a5ead75a --- /dev/null +++ b/txscript/data/taproot-ref/ddedd372fed9df45da4d1a59cf4f5cb35009e49f @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc1000000001e5a14ae045e7a76000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fccc9dde3b", "prevouts": ["0c70790000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_b2", "final": true, "success": {"scriptSig": "", "witness": ["4b537f91a28e8f5a72ea79222386b8312f93a7865ee41bb74d3490551dcef8dd453a0260dcfd4ad1e2dd8071a47f73135dcf9de9b7e05d926824c7f959165c1102"]}, "failure": {"scriptSig": "", "witness": ["ac637c79140b15f841cd2405eee050dfb85c39a3344157a57cecaf53405c53cda0877aab0f13f2199d6d13a40f1400396ad15a9f2e3713083fe842f2cce141aab2"]}}, diff --git a/txscript/data/taproot-ref/ddf80ae28fa37fbe9cd6a838ae2c428932ef3961 b/txscript/data/taproot-ref/ddf80ae28fa37fbe9cd6a838ae2c428932ef3961 new file mode 100644 index 0000000000..b9ac3285b4 --- /dev/null +++ b/txscript/data/taproot-ref/ddf80ae28fa37fbe9cd6a838ae2c428932ef3961 @@ -0,0 +1 @@ +{"tx": "05439dcf03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce400000000e23122ffbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2801000000445b0faddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5e00000000b41645be01b3ac85000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487d2010000", "prevouts": ["5f875f000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "f27f6200000000001651142540f27e90740933c99d4f17ab2dfc6c82951cfb", "90775b000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "db", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936158dbdd04fc8b1597704d885de388d9e8396e20d8d1d942e0680de9f689953519f09ad02cb012ed2091760f4e9ad26775ad10447e2b9e598a8be746abc4727fb4e3966518140ddfb4b2a9d93e012e33d80f6a3bf7f24f1b44efe84ec3ac236f0e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93674592b4fb9d11d06e04aedf373a859381c5b821797864f536763c5371283881ca04823906532712c3d4cb334ae6c7c41a1294a824a25b5277d43f47953a1da33e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}}, diff --git a/txscript/data/taproot-ref/de08cbb895403680951a2ebc90561ac53b1a1f4e b/txscript/data/taproot-ref/de08cbb895403680951a2ebc90561ac53b1a1f4e new file mode 100644 index 0000000000..b971dcaf5a --- /dev/null +++ b/txscript/data/taproot-ref/de08cbb895403680951a2ebc90561ac53b1a1f4e @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8101000000d15525dcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cac01000000f2c7c6da0498846a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acbf000000", "prevouts": ["b8cd240000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "6979470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a925fb010e9dac59891c803b6a81d462f65c56c77cfff52e46d3d042538a83699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb44c2f2200f850d6a1609ea6f282082fe51ae8a55145cebb4c521120909a7edcb74b0fe5a2ac2c1f7a0cb2705bdbeb7bce3dd33edb4ddacee2f772f92b01147433"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5116dab5147ee209d2bb54465ac69ced1cd5e726256fc4bc53cec72e983b39694d8586fdecbef25bbe615615e0698f2a9b21ec544d3ff645908914cd0f4da91c05854b8121e0ae10d162a4774d9a1b75cd5b5f6f9e51813910e8b7b5db2ca997d7"]}}, diff --git a/txscript/data/taproot-ref/de2a5caabe3e3b0b1b01533e95ed8f482c6ba0fc b/txscript/data/taproot-ref/de2a5caabe3e3b0b1b01533e95ed8f482c6ba0fc new file mode 100644 index 0000000000..1263e31164 --- /dev/null +++ b/txscript/data/taproot-ref/de2a5caabe3e3b0b1b01533e95ed8f482c6ba0fc @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b05020000000688d329dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8400000000b676ae7f03dd933f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688accc010000", "prevouts": ["1e2c230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7edc1e000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_34", "final": true, "success": {"scriptSig": "", "witness": ["6451d3179e62dca0cc40b81a493aa72f1a9c7ed28955784fa11e9acb9a663176f67fe8d9f8e88f5aca7a340d2dd56318b5306b6b8507f4aac26ab64103c9bb04", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["b34ffc91ae7554fb840d132cf67c074147c9171cf5d309cb403196ddc51ead9c0ac0831a2e63767b53c37f985a9ec82b3da0cc3199d0efe13405f5a077c2918334", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/de4f89a55a6d907d16952ca4e4166a5979c39c8b b/txscript/data/taproot-ref/de4f89a55a6d907d16952ca4e4166a5979c39c8b new file mode 100644 index 0000000000..ef9ec66a89 --- /dev/null +++ b/txscript/data/taproot-ref/de4f89a55a6d907d16952ca4e4166a5979c39c8b @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf201000000ce5eda9bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2f010000005618a396bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0701000000427c408b01084841000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487d4145d56", "prevouts": ["24fb4c0000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "4f8a7600000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "3763820000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "cf7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936748d121e1e21609f79570eaf4a0c66e6f2ca68747216dead3ef769b37e72a366da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed2b7053bd8f6b5ad2f12d7ae765b8b6e1c341259e3dfbe95167fdee949bfcc9ffe03d403be23d34fe95cd8ea927043998b4b921fc49b039e78905cbd289b8eab"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0822a853d9097b45eb0aab266931969d1621607f85e2073f603093b953a54be8539d6c4167c25132c432c9175336dcf34ec1853eafcfbd891c58e0cd045b8bc4542"]}}, diff --git a/txscript/data/taproot-ref/de5a7c1447572e08c6b28e753fe662ac083fd6d1 b/txscript/data/taproot-ref/de5a7c1447572e08c6b28e753fe662ac083fd6d1 new file mode 100644 index 0000000000..d2d6e2bd6c --- /dev/null +++ b/txscript/data/taproot-ref/de5a7c1447572e08c6b28e753fe662ac083fd6d1 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd700000000fbd7ecb1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0f010000001dc16bf4039bbc640000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca8010000", "prevouts": ["f84c4800000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "ac261f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "fa", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bbf1d1d3d3f3a5ef5765b8348d5c92141ed2621e0ac73cf7baa1850fff99acc06081f43f8c34257025162ccf1daca48ae61c99356c3eb24d5601d3c52dd9de2a6f5053dc49cb92d20c30fe5ab09c589302aa9886b9c794d18405aff33121a169"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a1d35e36d71f4211ee8dcb476ced8f16f1af9e215de664588adfe8e8df5b115526ad4257a22b62302a767a5b8896008d1af7055b6fcc30f1a04cbcad06de5cf2f8b8afd7beb88d43ca6c6d2d58dc9425172bd95ccf582b2eeeba83616a9d27d33bc3f3b627616b9f836af78c18ce00964f5f9dce3e851898685189c72823645e"]}}, diff --git a/txscript/data/taproot-ref/de5adc575b18b1c34a68e95cecf166f402e523ff b/txscript/data/taproot-ref/de5adc575b18b1c34a68e95cecf166f402e523ff new file mode 100644 index 0000000000..16ed3ac84a --- /dev/null +++ b/txscript/data/taproot-ref/de5adc575b18b1c34a68e95cecf166f402e523ff @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9e010000004e8d62c98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48e00000000c08d65870131f23500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac01adfd1e", "prevouts": ["0c3422000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e", "6c6838000000000022512014ab2ce168ab85feead37e4eac5416d9445f157495b1751829a16d631c43d5c4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "347d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93600b38fa5d865fdb23dee295cf5e738ef43355f5bacd695a02d663a7b470d4077ca882fe3c585d1ac8aa5218112791e3065e91b4e1e0362790dbd367cd44cec36e97124583e57aeab90707503ff0d8dae530166a9193c4517699e1743b45d7c12"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936671dace471e6820f5f8191987c15715f38317ddaf0403bd182cd1a89365688b3a00efe7e15c1e643e9e1cfaff50670e7cac10128754f4af7dc416953d80cca2b070c3fd2cc03cfe72ec91581f9e22200fa4c4f6deb8dafcd335310e90efb11e5"]}}, diff --git a/txscript/data/taproot-ref/de5af33427175b7548895fa5441e430afe11d1d5 b/txscript/data/taproot-ref/de5af33427175b7548895fa5441e430afe11d1d5 new file mode 100644 index 0000000000..45a48a6be8 --- /dev/null +++ b/txscript/data/taproot-ref/de5af33427175b7548895fa5441e430afe11d1d5 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b68000000006d4aa6088bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44101000000ac7b6e38014a4656000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f870b000000", "prevouts": ["297523000000000017a914a1b035f555fd87548264c3580a1f62a42acf027e87", "8479410000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "215d1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["248c4ecbff0376e38497f2505ebe59d4d0b15bd0e611d1b4b35a48707bbcf0dc895d691e1f190450c250940b11242caf62e507bd623fffa83199602a467b0e80", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/de6875a737b7c8020f44b1c99b70c4853e661ecf b/txscript/data/taproot-ref/de6875a737b7c8020f44b1c99b70c4853e661ecf new file mode 100644 index 0000000000..2490e7ed64 --- /dev/null +++ b/txscript/data/taproot-ref/de6875a737b7c8020f44b1c99b70c4853e661ecf @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc000000000567fd09760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e3000000006cc4beb260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703901000000fda958d3043a449000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf24a3044", "prevouts": ["c9366c00000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "2745130000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "d0db120000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936910f902344d2bcc0b5c96564c3b5a3672469d9f6056abedd80e999d51f34e041aad829192d8416594973be53751c2dc095bf33e54427303a5b8b45ebdea5dafd99ead232f95c20736c4ca28d40406922684ff7a84c70e432a4f6a4d4d1893c4694e361b142bccbbefeea6ac26126d4f4fbb610699e3a27d96f99d1b67de22f2f"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004599aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb44041dd00c04bb207a9f54805a750c9f5dad18a896c6f9e3a7e4fce73f8863b3a94e361b142bccbbefeea6ac26126d4f4fbb610699e3a27d96f99d1b67de22f2f"]}}, diff --git a/txscript/data/taproot-ref/de6cf2f6180404aa31b1db7d09cf2baddd601d44 b/txscript/data/taproot-ref/de6cf2f6180404aa31b1db7d09cf2baddd601d44 new file mode 100644 index 0000000000..f340451914 --- /dev/null +++ b/txscript/data/taproot-ref/de6cf2f6180404aa31b1db7d09cf2baddd601d44 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3e000000004eecdbfd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40400000000dc744fac8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48801000000149ea6b603d7969a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88aca8a50227", "prevouts": ["6f9121000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "11d139000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "5094410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_3e", "final": true, "success": {"scriptSig": "", "witness": ["3dc6991c17f520cd55b16b150ed1995c6a1226a91f67b1a6d5ba6a7269700a92dcc657abf599861635e5fc0d66434ae4ccc199d53c6b841a85aaf940c3fec2d681"]}, "failure": {"scriptSig": "", "witness": ["f45ff07ce00a4d91199bc40e46be5804cf896608d1c81a4172f7085e51bcd009d2cb520821c0ecd6b92afb1723f9f01443a014d80e837dbbca1de1485d1915fd3e"]}}, diff --git a/txscript/data/taproot-ref/de8a035daf19e89e29ba0bbdd71dffd1f9cadc5c b/txscript/data/taproot-ref/de8a035daf19e89e29ba0bbdd71dffd1f9cadc5c new file mode 100644 index 0000000000..86fb49cac4 --- /dev/null +++ b/txscript/data/taproot-ref/de8a035daf19e89e29ba0bbdd71dffd1f9cadc5c @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf250000000093e955ff04cfff7e000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796cfee2c54", "prevouts": ["40b581000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_1", "success": {"scriptSig": "", "witness": ["0409560971b69583c42103f76826e83d36226f497642c1c6e056bf875cfd5b928b25c6a218e0437035cf85fab6453439b8ec6d4386666317f829eaaceaf7b05f01", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50c891a70b8bb0132d0f693184daa3329f78466fc9e87f04faf00ccc234f11cbc269582b1834d781248799d0c926cf244530da7f9165cf2fc991d2fec2f44ccdef5d8d15caf631eb020f1deed6dec3c08fafb000f7595206524acb72bd61db3340a2a9f8aee6234d7ec65930079413cbe93f6f7c3cd9c34ec4470bd910e815cab46747863ffed685af4ab3e31b82858c7a773131cbd1c90c619709da593c321725b70c7da46e5fa46e8f9cc56e7f2459eee9af5db86137006f87300e47bb2b354dd64d234346e8e9fe2eed2d229414d66bf97b2ec9aaff75223b5a66136b86775e5350ad9486368b"]}, "failure": {"scriptSig": "", "witness": ["fc32ccb82868ac36ba7911908fcd8dc5ddbb53c91b6ef0f1621d39422e976761c760683f1103fa9b79781c40bf4bad2a993187c6e71136792896bfff62bc6daa01", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "5030bf7e5ec30f854e35517036d813901349f2d6244832b3bc5486468741d351e82c8af6d288bf060cd34a3f99272b1903fa4ff56d6ba0c7253860516424f52c5c53348aee89d1600124636622cd34a7582b"]}}, diff --git a/txscript/data/taproot-ref/dea753eea55e305608844a4f00655549302ce7dd b/txscript/data/taproot-ref/dea753eea55e305608844a4f00655549302ce7dd new file mode 100644 index 0000000000..a841273cf8 --- /dev/null +++ b/txscript/data/taproot-ref/dea753eea55e305608844a4f00655549302ce7dd @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf301000000f07fa784bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa100000000b808a1ce027a278e0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca0020000", "prevouts": ["830c27000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "027e690000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902bf02ff641e31f09c4d35f5f406a11ff59fc515d404a4a638b15c3f346fa771c567a27c0265f0cc211826b11b668419c055a77cc263e5986478f40e36657717f6b3a494dccdbf7cfdfc113bf627df190fb2360826940e8850acef35bca523acec0beafad403c60450194456d4770deb9054ba19193734f2b8ff2f2b4798b0518f188e4058e7715edcec862947ad50fb19cb614d10f704bbbd2bc43e6f29a172284486f05f1b01139e01521a7bc268c3300c519adba03b3f6dbad13db6bb1050419efda175fc1eeb3f4ce71917d919d529af76136b443c86acaee438f9bde767581c2d65117ff9f027cd9305ce42ae74106f593b094ac591d4c01b9924c2bc9f9313ad6b4ea0c567c91d5b3dc9b84ffb5c10afcdc6b7ff988dc09496bc5c6bd335a13a011dc4f18c48c721535707bc1aa7051e42d21b3885895ed4860cd871b68951a0fd86f67af4bb2d42e8edf5960caf8b1187c0e84208355a375e879cc90d38f188fed3188001390acdc2702176daaa94b594ba4c56540f582ebbe168d48cda00494821897826f62a13c9f4910a10e5a39565412e8f3273d6caaf8cfa6a3d56517f3418e5584ce7e54978d358ee9e83d188d475acb6d12643fb8c91b3e7b014be143cd618987d9f8b40ce66eb3eb70c025ff4021184a96dcf7bd27a26899c53cf64b5bd1b90d76704c0583e81e9131e16634f95e3b9c6f00e77a85678eba25e0da1b75d2a718353ab75", "dc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936093a5eeea5c169e2fbc7166a6430bf79557f7d46655a225e460f903debcec3108d49cd47170ad660e437289f08833289e3b90e14293c0ba427f1ef2b5a93f8559a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e3bfe8b0458382ba4f4ce4b13b8b707c198a710172b0004e49e202e4d70abaa7b"]}, "failure": {"scriptSig": "", "witness": ["4d09025b96938ed9b3e4fac18d3da6b49763a5d1c34f785686c491abcdda7f392637aaaefa9909e13d4efdfe5f14a4418fe2d8e8e0b8ab3c13e853972594541dcacbe2d8bba2c38f5646253b655ce00ff5dbf5db7e6644750d34b04d44dd606792170ad91e6adc2c170ad52dd3fe3488c2638393ed39ef5c81f377ee0bf464625ca87831006409548f75c7297842b5727f1394476709a3b33c213242be9f34de430fb90cd841597d692675a6ecb5d00be96655331d6e18595c82a563fc1ceef4d248f9d2fe2207855fba5d31247eb0edc92df45cce99077376d7620498d1151fe2e173e54aab7a7809d0e378eb276f5c998bf2ff463f6151b93474b013c4faa80c237ed5d9b38e70d8df604f8956948e1c88a1689a39f02e66a398cd4ca7fdcf81d6dfe98c878e287334378fb96e629f020866f9a77151f4351519ee88c560dd0843092ae5e1ed6ed3c5d8ab3beca1c227cd3be60f92ffe1237fe2ca3b1bf9e7445a9fa46f40f45fc77cc8bfc0388f74d81782efca16a0241c65b39ac9525a840784ccd99b95fc4d4124757de96272ccd15c27f01cda7ea2360b999be49e7c3afd21959fb7f2a1b7f70fa882d330f8fca48cf70041a1d4b3c6f1e3f5216804e3aa76b355a895bf7507a14e6e45543e76421fd39d3cc02dbef65531679b93357b3cde0852e62f1f2c66f8740f8294db350a0d85b0cfce382a8011875cb3a0711d71283ed3cba54bbcff15442875", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b824c9a54cd29e76b81e5147f3a84f06642da94bb2b4205613c863597e0bce9e9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100e3bfe8b0458382ba4f4ce4b13b8b707c198a710172b0004e49e202e4d70abaa7b"]}}, diff --git a/txscript/data/taproot-ref/decd88daf9600a38bc143777492f37dad4565eaf b/txscript/data/taproot-ref/decd88daf9600a38bc143777492f37dad4565eaf new file mode 100644 index 0000000000..e11f3c545f --- /dev/null +++ b/txscript/data/taproot-ref/decd88daf9600a38bc143777492f37dad4565eaf @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4b0000000063774ab860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d500000000cc67262401117116000000000017a914719f78084af863e000acd618ba76df97972236898756010000", "prevouts": ["628d500000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2452120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ad", "final": true, "success": {"scriptSig": "", "witness": ["008e817620cffc0c3a58d346ec64b478e48797b6850c6886decdddfc8d5a669ec3888c25c02b6c8deb655209278156b58913cc6e1d1609d6ed4882a25df93eea03"]}, "failure": {"scriptSig": "", "witness": ["de9a8f689e63f3d7c0df31662b3b8c773b214aa835cf868832f5dd09fcf95b578e02fe4de5c383172e84694b9f8567de9b84f790e5eb689351290152957f8693ad"]}}, diff --git a/txscript/data/taproot-ref/ded66ffb0cbf19f233f516bd3c63fe712650ef33 b/txscript/data/taproot-ref/ded66ffb0cbf19f233f516bd3c63fe712650ef33 new file mode 100644 index 0000000000..7fb357970b --- /dev/null +++ b/txscript/data/taproot-ref/ded66ffb0cbf19f233f516bd3c63fe712650ef33 @@ -0,0 +1 @@ +{"tx": "0b6fe83703bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffe000000007cacfbdb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c468000000009c09df848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f700000000774f468401c92a7500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acbd79e031", "prevouts": ["dcc37900000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "129d37000000000017a91439ec132e1466f40f0086baa7ac253013e83c7dc387", "bc53380000000000225120f3eef30b2db388e6b8a313ffb142e2e6ffc970ce6b6a81ae6dc1d81725c678ea"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "7e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e19aed6a34821d65edf69e9d12354a87f406d02be059705f92363392a057792142e401215e29d5d13de3b6ed62165bc3378402ce71158bd1208562fc299f33fc22fc39b3065f81e3c179a5faa7416c7afc60db6bda904d6a600fd6a7a1aeafb2cb"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a0d0ac5788f723aceb0a237bb228183ae381a676877b38e9861fc4f2162de386b9b4175db22b4058fbb32c1c98b401bd6f80a734567664ffaf4b869d5cecb8c8be9bce0da1a8e0eb2f55600b1edecb05394963f1d059e6505f0ccee9d28b62f6faffec7faeeadfdc2f9d17b998c1a9153f333fbb08a178932d29a7211446b62a"]}}, diff --git a/txscript/data/taproot-ref/ded72412b30434c168fa06e48b7e054269d006c0 b/txscript/data/taproot-ref/ded72412b30434c168fa06e48b7e054269d006c0 new file mode 100644 index 0000000000..4089a026a4 --- /dev/null +++ b/txscript/data/taproot-ref/ded72412b30434c168fa06e48b7e054269d006c0 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfea01000000f5e5319edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7f01000000447e5a1e03ef0fcc00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4874bd55a28", "prevouts": ["f0347a000000000022512017e91ee0326ee2050a26c2cf73ffa8316bb13627b7c7250ab1d4d36a20fb6045", "5da4530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_80", "final": true, "success": {"scriptSig": "", "witness": ["345e2569f6bc0378e11a381d7bfedb50dd311079ab6fba0c139fd4c352ee4a013d70cd2a332bd949e5b31b78cb892ac21831c9926563830e7fa72a3cace113b601"]}, "failure": {"scriptSig": "", "witness": ["679889311f25bbe6df48ba73daa150525f92b1bc85b626691a1e912f172adaba0f64af3ac315e6be452128c690c103935a87893244d08b695e476f53427131af80"]}}, diff --git a/txscript/data/taproot-ref/dedc75c0c2ee756e9070605ce546167cacfbcaca b/txscript/data/taproot-ref/dedc75c0c2ee756e9070605ce546167cacfbcaca new file mode 100644 index 0000000000..a2b67c89c4 --- /dev/null +++ b/txscript/data/taproot-ref/dedc75c0c2ee756e9070605ce546167cacfbcaca @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1300000000eb0c7ff9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9f01000000c78597bfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0a020000000af4cdaf04a802d1000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e76dfb7e54", "prevouts": ["501121000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "7beb5e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bbba52000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902675f54c964084363882394ad998da229764604e92985c5054486ac5d718d80f7061a038266cecc59eba9f612781c12845a659d75b65c37dfba7fa65cd6287d9d3bbb14fdad236378803b242648eb36bd7d85be915c6f706c8cb45101fa0af7e8d4c9d61932cfaee823776ddca35413dbf8f9dfbe7f091df3bbb341ef625925e347a00b960fe77bdae5e40e7c3fe4152f39aa5ce7922c5cbef4e9af35320ef7d6cf1260eed59167599bc1d88847bd7027f489351a5bf3cebd7be6e39c09553a4a61f79128569257af65e6b704eefdc93a586843e609c5d689c5ebc0160d4add0e5656194eca0d9e4fb668fab50b7b70333da27c820899454973aff50e92f99bd002f41661432b0dbe1909db9ef5ed10f30d0e3fae24a8fa9e1d01bc348ebc427ab8a8815ace325fbd4835c9a6c80adc5c47d2df50ba768fdb536f21257a29c2719978dcc3ea8240072bd2143e7a999e70eed11751c0ee817b8ace48a3a6faa4dcbdb1fd57441d1d5e696179eb7e05ae4e9fa20b5d0e9b0b4902a8ec1060ce4c6476ba85b6386f855ef3f0edc1f266605d0c1eac9e65329ad9f4b34a9d65ad717f9236f0906a18ac9d956854db9fcbea7700545f7de87d28db70ad14b6c229684c5fd109c6217ad0ee2a2d020de6829968b151591e58f1656e8e81c04dd9f77c3283504e14d452fc69b7f16b91bae882748fbeeec3731b6e5bec203e273e0f97f428c5341b85567750177597", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936adcfeb9b29c6ed44c20ba80ac794e3b3be7a6204c6ce082a2474d233e7fa669cff42e4d873fbb915aa5b42e254ee79c6fd372778836ebbd6336959492b60478df213b900f5cb66b025bdcf0538d69427e8f93cfc9741b2125e61cf9215fad53f373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}, "failure": {"scriptSig": "", "witness": ["4d0902c34d9b5ef32efa4b78f99a029fc6956dfe364fc0c000ad51b638365278a19a703b498f4e601855ef0f0bfe54de14b7a9b5683c8687790a838c9cac2d86284bd554593f9993309e96b3db5c5cd5f007f6964e77788283b128f688a72ac331c8ae8a23a8b631d0b797cc3c0e804353951c5fa876ecd79570ef6d349b1de34410ddf9953617e94e9248882ac09c2834197bbfc6a1e00a353933a6576321541fca3b21bbca281e6fd79c7bbbe0ce0fc058880455faa49a90ee12130d8bf20d7ad9e1e1a3813b10e39fae954e7aa72ad1ccb5d7c9353f24102c0ead2294cd0df0845c3f6cd438601822420563e463e88a37fe06bdd32dd847d534786df94d1c5b2cd09b08b9aff272ce947f85ab0f67f4df058ecde27d058036848bab5dd7c75d1bfa24caf08bfa6ca004ad475cb0b68d6e7029082556ba911f0d5f814986a486cbdb8189998825612817936c1ed1ec967275feec6d446caab86ff88fd880c0461b8d7c31ac3028521722e46a20edf02c551f2f5b9568a9b4d327af1c739a4cef202b97742b56bad83d03678baf57b22e33861ebe8d97ecf423db50053fc3fc651092851070cc8f4074a46a35bf04036f6b1f23070bed2713df5b3c26448dec1790312e26c8e07453672572bcf56d73606a9dc09bb98c42000a217c3fdd2f442e864b372c78ceabbd6fb9d43e11ab367fd1ed574045c3ec42d41a1db84da2e61fd717d05f6424355325b73c7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d9004505f4756eb22a3c38e0612932b2e111811a644330efb7a4d77fa512235b8ceac2f213b900f5cb66b025bdcf0538d69427e8f93cfc9741b2125e61cf9215fad53f373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}}, diff --git a/txscript/data/taproot-ref/dee101172e339916048ad363fb6995306d7dd142 b/txscript/data/taproot-ref/dee101172e339916048ad363fb6995306d7dd142 new file mode 100644 index 0000000000..3e8a9e8a23 --- /dev/null +++ b/txscript/data/taproot-ref/dee101172e339916048ad363fb6995306d7dd142 @@ -0,0 +1 @@ +{"tx": "e2951d0503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2900000000faacbcb9dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1601000000b69418878bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4eb000000002de75a95023fb57d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689870b6d6e3c", "prevouts": ["4a82260000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258", "6f1924000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "0ab0340000000000225b202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["c14c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5182d044aa67ca69515bddcd39ff85ae31d999a9a5b32af0a0137c9fa4b226ee88d3f52a2844c5f7874c7d430ecd2ddfcfe713e30c56da5784f950db6acb8f092a"]}, "failure": {"scriptSig": "", "witness": ["4c52c1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f59112a8c06ad701f9edfa42ec0be4849dcf79d254814ed43ac6a9ae6ade45014a663af4c315d4c0e419951403071b67d2106b9ce8bb6d7e6c872100135a32b791a13a85e5c2e660174c9a1e69b8f96263917ef129d2001c822ceb7fc389f44"]}}, diff --git a/txscript/data/taproot-ref/def37ff0a6957f0a571488b66a768f20f7079048 b/txscript/data/taproot-ref/def37ff0a6957f0a571488b66a768f20f7079048 new file mode 100644 index 0000000000..e27808a85e --- /dev/null +++ b/txscript/data/taproot-ref/def37ff0a6957f0a571488b66a768f20f7079048 @@ -0,0 +1 @@ +{"tx": "fc52232702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff701000000ec1eb2dbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b00000000007f7b48d60234038c00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac9d000000", "prevouts": ["15e1680000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "86ae2500000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d512c6725dd4617fe2c0113ef50b93a252f15ac43c20ed2eeb851ef9070637abf4dac8db205c7d3bb0390b2e22910f5d1cbad00807eee3325f4c4e7f4412ed3064a1c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa3b35d8b29d4381edf568701a69a1e2b58fb6f81852737bbb7ef3118982f806dec24bcd5a84e558ba1632e81361cbfb2715ab9fa3d579aef34157cfe08620975813d9fe920e311eca68d9da8ac683d4c5ffd57c03f9174ce1b6c58fb2e14cca376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}}, diff --git a/txscript/data/taproot-ref/def74495863bbdf9d1af666161152708f2ba582d b/txscript/data/taproot-ref/def74495863bbdf9d1af666161152708f2ba582d new file mode 100644 index 0000000000..164f0003df --- /dev/null +++ b/txscript/data/taproot-ref/def74495863bbdf9d1af666161152708f2ba582d @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdd000000008a9c37cebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0f02000000eae7a34c03b3f48f000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7c198d544", "prevouts": ["5d6e23000000000017a914c7049bed1fc82cf46b0539507abaa88864b6346987", "e07a6f000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "5c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2e0fed7abdf786fbd6951af9acc54241aed127c5f19f62d09ba4f0526eb81a5df243c72f4e074898aab8058b3c73fee97ec3b9723e213834a8398e97170c1356"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f95811175664830046faed455096fec372413cf10fdfd9c9c39f3ab5db40cc592e0fed7abdf786fbd6951af9acc54241aed127c5f19f62d09ba4f0526eb81a5df243c72f4e074898aab8058b3c73fee97ec3b9723e213834a8398e97170c1356"]}}, diff --git a/txscript/data/taproot-ref/df029e9ebb9e83aace8f0071d2840c27c3ceda07 b/txscript/data/taproot-ref/df029e9ebb9e83aace8f0071d2840c27c3ceda07 new file mode 100644 index 0000000000..4a37cd07c6 --- /dev/null +++ b/txscript/data/taproot-ref/df029e9ebb9e83aace8f0071d2840c27c3ceda07 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcc0000000071630ddfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5d0100000077f260fc03d5faa90000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df97972236898796000000", "prevouts": ["5be962000000000022512064408326fad1f8311f590f6e6ba281aab75c91070d1d43ff117e995859b8513a", "a8d4490000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "617d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93680e322cbeba9447e623c355f3a00500243eb51ea80336533073705560965e3918a99f3582d6399c0406dfe65dca998a5ce57b7e950df5f64352e1bbf6c7fd210dd304186c0a2faa80f59261766b0cb9b0760b78eb1f31f166a6f091ab62e6898"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e0063b43826002dc6eba62f224851f0eabb14759fb10c707a6afd7fdb59e93aad3ab6b2d4691bf881316931c587f0a213fdb9026021e80f212e72f88982a6bfdc"]}}, diff --git a/txscript/data/taproot-ref/df085e9114f63f74c86f24312e70f7b5318ad9fc b/txscript/data/taproot-ref/df085e9114f63f74c86f24312e70f7b5318ad9fc new file mode 100644 index 0000000000..2d9af9b9a6 --- /dev/null +++ b/txscript/data/taproot-ref/df085e9114f63f74c86f24312e70f7b5318ad9fc @@ -0,0 +1 @@ +{"tx": "36449a2c02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0f0100000000b960bcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3700000000576d43be01f4b34c00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac83000000", "prevouts": ["5386840000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8", "e6232600000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "017d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363a70d9b275504125857cbaafe4a923049b33c80b4c83ac6cdbd36bca05abf17733479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae05873438be84f92d1402d5d55e9fb409fe52800aaeb5db180b239b834bc1ca2"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361819509e9671e02e7a4d8cb2e99fbc3fdcbb7d0847ecf4f66821ff751ef18b028874369940c44314cd428c72b977b6d1fa375b1e54ddd71363c505e3530065c38810a2a55ef559e3dd2f859359930339f67e2de31eeac841179b888fd41fd8a3"]}}, diff --git a/txscript/data/taproot-ref/df12a4966bab2fafa4ffe3a2ffbbbe8d697046c2 b/txscript/data/taproot-ref/df12a4966bab2fafa4ffe3a2ffbbbe8d697046c2 new file mode 100644 index 0000000000..b9d932425e --- /dev/null +++ b/txscript/data/taproot-ref/df12a4966bab2fafa4ffe3a2ffbbbe8d697046c2 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b56010000001507ac2fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c880100000047f521e4028cc57200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df9797223689874a000000", "prevouts": ["8ab320000000000022512049309db7adc24e71859de9f715c32a97834a8db8d4836c0bee01675ed84352f5", "3c7654000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063bc68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362bdbcaaa23cdff8083cd34ab41f9ef3fcc9019d9deb6ba18cee7c393fa19240cd300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d516a0ed0b6cdb130b03f26b8a245e72d5247ee3941518d7e9956496f6ce27b97d7150e68e664a4d5c991e5183d0e7966d99b6c66da3079bb04bea44808922b61bc"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a75a59cefab6a6e43e7cd7f010e1e9163ce51aff720166368ac5c7faa51270509312a224ee6564b861c658371f7a6f0026ad2c58d86ce869dc9b432e830a527104966f092bf1e4b4348fca11e7254311373308f7fc15e3d44d6a2afffa343c9657ff193055e5853205a1117b7666344cdb66562f15b4d40280f3656784bf5cd3"]}}, diff --git a/txscript/data/taproot-ref/df16a0297efbbe308fa83a0f3e6ad417689b028b b/txscript/data/taproot-ref/df16a0297efbbe308fa83a0f3e6ad417689b028b new file mode 100644 index 0000000000..d3a9d47da9 --- /dev/null +++ b/txscript/data/taproot-ref/df16a0297efbbe308fa83a0f3e6ad417689b028b @@ -0,0 +1 @@ +{"tx": "53b6091d018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40c000000008e6ea7d901a6021a0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc80000000", "prevouts": ["b0743e0000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902996d356a528fcab7ee830ee5aaf2f5d101b1d192eb1378e4caf2bc8f7a426db18ecde281277f52b180790f35b399c99253d7468b53c1615afa504b916c407b5adbcd4bcba48185971e9b4ad829ae532801a5858524d7c201dd0a33636f9c39c4f79ffdb2c535a7cb79d18f495f7c58b1767548ed28de79220d0ada361e0f6ca7f102c05ae817e2970b9411aa3474c781c6b7ce83752fdd1eee3524603770e083092ba4cb6666d682211c0274b02799958b5badeed0e064fa6980b55f83d88e5e84efb6f8fa598fcdbbd912c6f6ea85585dd9d50cc6a32ad71046375904c41da5af9ca7ad95c9a84bfc36e75f7e642a3fd5c8d0321c49e73c2c2ed3397fe5cbff5847c65bf28c370b3098852eb99b7187e799452dbada4949e52efbad4bb8f690fce7ee4e2908a7c823209fa861f0f2d12c8f3270af8f14b003371f3696337142a6c6ba3dc380b9977576a9f14281d8c7c2c77d153ede428de528575fbc5bc04b70d600c52a8820be15d9c57f838509718a741ce7de0488e6ca6f484bf081bb8901647ee93e722cbd4872274838b00e133f1946d53b0e15da55b41d208b4a47db4448d1c2496ab32757e5f94e7f31e6ada4f3ed6e8c369b29f4d2772ff1067231895809abbc87ee75a83d8f327194de90dab8dfa5cd3dc101b9c43f9c2dbb0978eeb496b04e61984ff85ee95fd0160542b2a43c4fc7cde5daec3b457afe38e7e21157212fd466b38dc875", "cf7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936143c349571a367481e690b7209c29b5ce19961bf557985bd6c7d96f3e64328220309cb272f305cf5bf6862d0b37519cb4aa2491edaf37578d4af3081a91facd0fe03d403be23d34fe95cd8ea927043998b4b921fc49b039e78905cbd289b8eab"]}, "failure": {"scriptSig": "", "witness": ["4d09022f26e02f0df918a0d0e06ac416b58e90305ac32689786eda24ff8c32e7b56991e9743a412fffe4c37604a8b64afdac3d04385544f890c8e5247dd42b08b2393323d86a0417517d9fd631db7eb530dfe6aa8e77ebc55e3987391d0001a2ef665ee3793bdda91214f0e2b77908a5565c5be5dae994d6a702f5d568421fffcf614c987dd9e12f09077c467a631121e4e49018b4b900ce0022fe0dc56b201f79d5a3fb64b474a8c9eaf6889d01f464b1aef04381d4277a0a440cb3e3c9a74bb05d988a8d37655dad5d846f6188ed93755e86d36d9b43027dda6429ebc92d04b13102e683357b92d6378f149206deaf0cd2920c65781a5eddfbe4d3eae96293cf0c633f230919dd41f17c0519e5c76f75104661446904939eba161191c8a39bca19345817ca250176e355ff21fe8cd91746225bea5b74adddf15f129189681bdf1d10fadc688fa387a156ee113df5812a2dcecb0b89a5dda4008e77dde9de93f187f8606f5fc69bb0717275338ce3b39e18827425dfaed39197253174a810a0c323fa40c60ef5c9a3d67f5fc5df7194565e5b6dd9bdc396ba7a4f60b2293801eba075d6322824fd978aa0c19ff88286a7a2079d48f9799dbffd44fb4dea28bc9c61e9d5faba8f9ef2c485c707a8c93e3c29dffceb49fdddc69e24a62dac03329c67f6cbd0f60f71e57a9d256c5491c70813fa7ca5a1dae54825276e390a1c730e8780932a3ae66381f8ff6b75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367713179303850cc700febfc1488c688622fdc6710045748da9f51ba3077a9d29da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ed2b7053bd8f6b5ad2f12d7ae765b8b6e1c341259e3dfbe95167fdee949bfcc9ffe03d403be23d34fe95cd8ea927043998b4b921fc49b039e78905cbd289b8eab"]}}, diff --git a/txscript/data/taproot-ref/df865486869273fb5f7adede25fcadcb18ce2221 b/txscript/data/taproot-ref/df865486869273fb5f7adede25fcadcb18ce2221 new file mode 100644 index 0000000000..1ab24e894c --- /dev/null +++ b/txscript/data/taproot-ref/df865486869273fb5f7adede25fcadcb18ce2221 @@ -0,0 +1 @@ +{"tx": "b824250602dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7a01000000fd949edddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1401000000948f09de04c9c07800000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487fc000000", "prevouts": ["ef115600000000002251209f6df9bf0ba86119ec56bc774d8ddd924452496c0c827ee2df6dd8b5f3d2e1ef", "e303250000000000225120a0c53dc99d5bda6251c68fa12a805cfcccc74115072cce855438d885fbd38ca2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "487d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ebe5e2af3a3c1a6754948d639a5542927d59c509fd5287d02d091c2a39a812b527da89940c9c2be3d3cb1ea9fc374137a74dc3bafe909c68993f298761996d666"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936379a98b85b817e20bc3376f43a8b74803a7c6b50cc59446ffb1c9510b7649235edf94ae33f5606292dd7c11b30be28c4e66005bd3313ca427ad5ed734d53452840210bd7db211b82a407c19f9567cde5a01f8f2a3c3dc032c7ac21169de78447"]}}, diff --git a/txscript/data/taproot-ref/df8de808e45c8839831abd0deb0cabf9143753a4 b/txscript/data/taproot-ref/df8de808e45c8839831abd0deb0cabf9143753a4 new file mode 100644 index 0000000000..6f789bd684 --- /dev/null +++ b/txscript/data/taproot-ref/df8de808e45c8839831abd0deb0cabf9143753a4 @@ -0,0 +1 @@ +{"tx": "71b5e2d803dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba401000000be38a9c2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9b010000003949d5b6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba2010000007c0e80f601ed1c22000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787e6a4735d", "prevouts": ["4a3f2100000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb", "f873240000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "4005270000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09023f9c84743c3be04ebacc743a2b6aa04750418f91bd1282a1cb40d916fb911d671a40db603a9aa900a6c8bb50f3419112460cce22921155a835fb336813220d71659a1eba21ccfbdab649f30721bdf6c430146a1c95e0ccce4ed5226e6217eb4022ee019f8038b75a9874fb1a5b110f10a1dc7f655e2ad0c1114ef5d93047389bdf7b8b96f73ba1b2774d9c0626965c34f401c611ecf3f0e070377768025e35140b2278ba78b03ba17272647acd1234b5b6dc75ca9874ff04e870ad0fc6dbf5257ea3c07f6e33eb28bacd0002482b8f20e39da68dc9c239b31f6db812a812f5ad84ade7f28c1c0cf8786c974e07b0a62a10a549a8bcf9f009f12b1e2ce3e1807795a2ece75ebd7234f3fa529c73c9e59409e4d28f3420c85f35af6b8386c13f00517bf689833e3ce60ff2508c7467a9e533c1be1f70c69df354dadfbb80fdab00b60167134fb19748b56b30e3260bd16092ac2113d3cc059e00ca433f5fa866c338c290d9e652ea0e893f97cf55540c8dbd0a74fb6ce2b446ab524deee537f6f1a79723834a9b5137bb86557683e14652dc5886bb13c89ed1a0cc9e5216012855c6cf1389599c2bd375cd011bd12c7c14bf51dce3cfb6e1074675852b92d4a2842a37057690a087b76475e97c91484afa2ba44006fb2d727b8ae7b6e978b526b3499ccc6177bb3e1d4d105b6d26598a6ffad84f5c5b2b68ee666f13dba48dc267c2cc4bda576082bea07580", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4e222414f291e7c8e231e07541c9ce63e3a938f40bc45d6936d3328c3939c0fbc26dfe099323fd489e28deb26e949bd9371fd3334eb17fb18f59b980c6dd72afd91585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}, "failure": {"scriptSig": "", "witness": ["4d09022a58ed26e6d19916da5455f120b9bd3f2627182e441e3e44087278382c827e1406aabe52b2e3be20a766bfa8daa37c81be9d1e017c44380f169df0d387627c920637b06649191ae08d7614cd6de635a83a5b6d35951b1f23da988fc0e96df01bd8392ffd08fea2839948d1ef45d7b228557a1ffd1f4207aa6227343e2c4b261213f3b0571bcb967001b380b88c55efa3e1d78025ee77003c585f311bc08eb46c30141ac11cdbd754c48b0e1eaf61927101dc14a87c52905031eeca89f754b89a8b7200cf3de2a837159a2152ff59ecf16d13eadcc2dc29b37762a303f712b65310a969ecb44515db112190059301b60c558a27845d6c4b1ec832340e6d5f8796c6c1ce46e9645180b7ec72c10fc1f798f3c08cb0c13bcb85b32c1b03be328c2fdc4f4001407a99d0b5810ee6ba73f721f7a9c8cb3b523ab6122c49fb81c3b97bf53b0c42118c0eb24c4c1219adb65bd9bdfd4c5efe789dcb33a5eee8147edd27dcacdc05978e9619e6e824d4508966e73c1e069212e3aa5c14c19025974b35e7115b0c0b9e42dbb4d8715a7a24b7ce32196103a23feede16fa66ebe811aedaf62ea6ecbfeccfc5a5c45c434b02201f043459ba0fe9bdae08fc5bf5d79a9f65ddebcf80473d78607dbe6808ba7d03be03ea057cb66b2ca7ab3b16a06f3666bcda75ba19a9b2120ed3f421af3aa7177b52104fe713100fae661b633b5f9568f8fd06ebd8ad1fbe3109837561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364386f400f3ec9e99e4a117ad3157ad40372b43bbbdd0f0bff3bd4d11670e39fb26dfe099323fd489e28deb26e949bd9371fd3334eb17fb18f59b980c6dd72afd91585e32e966e39b6b25c1732dbccde0ae2700833a1164b08d78002e58493a9c"]}}, diff --git a/txscript/data/taproot-ref/df8e03791d82b6610c2c15664032e32589ea35a8 b/txscript/data/taproot-ref/df8e03791d82b6610c2c15664032e32589ea35a8 new file mode 100644 index 0000000000..53e3440b5c --- /dev/null +++ b/txscript/data/taproot-ref/df8e03791d82b6610c2c15664032e32589ea35a8 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703300000000690e42c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42102000000816bc2b260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f701000000b4d361eb03c83c6000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcad010000", "prevouts": ["3f56100000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "e9274300000000002251201d9d7b8068d804e3524a88462f1a480f3f4200cc7b90f0ee3c3216cc2f53f488", "35100f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368982585ef19be154a5d0887475e9222bb71fccbba422f418bf7ba462437a3b52233ca416c78a4619c687785de007f14a4879f9c7a0556256e1b46b2a7e5a39b3c2782374d67da9500785d400f7ef10ae84f146bbb568355094c68456b68f7a283b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0e6ddebd74405781922a3c06ec9e019fa66c9803c79b531f33e986452ce61d5d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51ab4aa5d5e3dbd00e7a6b81724e903c1ca482dc7bc8339f552afc52b4f38fc6a5b77966166a359aa5541e77c34a58fd9dcb7d88ef6e7e0cd0e140e1adf959d28b"]}}, diff --git a/txscript/data/taproot-ref/dfa3c5fef1b463d98f523033ec70daf8d4bf8803 b/txscript/data/taproot-ref/dfa3c5fef1b463d98f523033ec70daf8d4bf8803 new file mode 100644 index 0000000000..6f77a1617d --- /dev/null +++ b/txscript/data/taproot-ref/dfa3c5fef1b463d98f523033ec70daf8d4bf8803 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8300000000f7f2e8ffdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c620100000059b834bf029896b0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb18bbe4d", "prevouts": ["86e863000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696", "36094f00000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "0f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa6f8d113c18817a044fae8525416b35b4656d6d7185568187de608cafb5211e2f68491001e36edf91058819766439c3f31bd198abbe3d2204f458ac7743e1d61ccf16a5e3db9e2b81c974405e52c4661efcc91a529144e47e78be5814d4a09901"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c7116f5c3e80617093632a2db9fc234f36b396a24b73f6adf68743edb71604c5d8798a2c57206b85b6eca830bd166e5350a1cd63f89078c321fceabfae97dd5c29bd03bbcbebf503f24139d653052e63a9a9f3faf73bed4a74eee576514948d11491142a38ebb10a24e36aadbe0cf227dedfd0966bcf56b2aea8b33dc3fd67f"]}}, diff --git a/txscript/data/taproot-ref/dfb36ff8904f4e8107d8ba666de3e5f94f741bfe b/txscript/data/taproot-ref/dfb36ff8904f4e8107d8ba666de3e5f94f741bfe new file mode 100644 index 0000000000..f8dd052903 --- /dev/null +++ b/txscript/data/taproot-ref/dfb36ff8904f4e8107d8ba666de3e5f94f741bfe @@ -0,0 +1 @@ +{"tx": "66c9d80602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bff00000000e4b956c2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b000200000011b1a9fd045972450000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876c7bd32e", "prevouts": ["8ef71f000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "f8d7270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_3f", "final": true, "success": {"scriptSig": "", "witness": ["11a821d804282ed3f8e49777158fa60fbe76e19e1873d2b28bbe5fa3125262909cdebd9455e37fd062bb1fb94bb22d7d4c2b8ac112dec4121b4012271f6c3de282", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["168a4a2774d61b7aff005ce782158729fd2cd6e14544b385725fba1617b32f9538600f79a3bd53f864e50f423f15e9bd90bb3f8c8569c803dbf82c31a3ed70e03f", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/dfca4159ab78bba17ae0d77f088b5aaeb3144266 b/txscript/data/taproot-ref/dfca4159ab78bba17ae0d77f088b5aaeb3144266 new file mode 100644 index 0000000000..36583ab97c --- /dev/null +++ b/txscript/data/taproot-ref/dfca4159ab78bba17ae0d77f088b5aaeb3144266 @@ -0,0 +1 @@ +{"tx": "f608de5102dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1c01000000234b88da8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e200000000afc6ffcb04a1565700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7bcb4062d", "prevouts": ["be01210000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f", "4c44380000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_da", "final": true, "success": {"scriptSig": "", "witness": ["60c79cf8a600096f8a85a9ef515c8744cd0d0a5c56941db9adc89a5e1bb8650788eec46fb60722058a82881355c0151ecba184eec81b3e65fcc49856e6bff75281"]}, "failure": {"scriptSig": "", "witness": ["be63d79f66a757cc5525c3eb51df4e41a12accd97657f116f5ef6b6d92f81e6e9ccd110de22c04592dc48a197929ef7130d8af195193716c1e3a9ce10923978eda"]}}, diff --git a/txscript/data/taproot-ref/dfe3a4307a38993f68b0c2518ea2e3e590b0c9d1 b/txscript/data/taproot-ref/dfe3a4307a38993f68b0c2518ea2e3e590b0c9d1 new file mode 100644 index 0000000000..285bef3a8d --- /dev/null +++ b/txscript/data/taproot-ref/dfe3a4307a38993f68b0c2518ea2e3e590b0c9d1 @@ -0,0 +1 @@ +{"tx": "421bd7b302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c140100000064fee5d560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270da0100000002f966fe026fee650000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac3dd3f227", "prevouts": ["28285a0000000000225120ac0f4213e8783833c45f3d5eb7ad9dd617b78266b96dfb5473a425c0f67cf18a", "d69a0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "a37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368269b16152528d89fc36f021923e691aa0c01b4f1f2096ea68808bf45cf529e55a5b11a87f009b0ff9f397e99e72fe38b81dbea82be72f6430c36b07738f500beebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7accae923b25d556389dd5dd645f6d7ddd89a07a74a73dddd3d85d7b65ae33798aa"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93638efb5b103e2deb74012998154e31323d0912cade4af687f6058be382e79ebb3842663f27fdccb53374929a05698df7a3618af6b1227ea033500411481dec31ed2054b94cb6efba565738f5dbf6ee5a67458962b65d77e1cf5e0d2c1c00b2210"]}}, diff --git a/txscript/data/taproot-ref/e0128963856adfa8520b26e571a93610b5355887 b/txscript/data/taproot-ref/e0128963856adfa8520b26e571a93610b5355887 new file mode 100644 index 0000000000..88925e11c2 --- /dev/null +++ b/txscript/data/taproot-ref/e0128963856adfa8520b26e571a93610b5355887 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3f01000000b8a74f8a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44f00000000e90788d160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702a01000000ca5a428f0116f30700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ace4010000", "prevouts": ["45214700000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "d6963e0000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5", "aee20e0000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09021f71643238160aad99ba4e027345691308f1a5ce1cf20b87d58d7ea3aef4fcdb6a2c2aa2c33e7e356f0f8e6210c18f5a49f6198cfb4856caf0aa59d925240a399418058dd0fc3c0470836560c06f2e37985ec97545e6eac2d298d96da35344bcf5033169fd58ca8cf08f41de9d11fba54420c36a3f5cb2b7d4ac0832b96be595041b139d57af1e2b42cc68404691c598f16fa4614f19b3658b6c991419fe337685b444d747e001490e7ee2d293cca6ea81b80ca4cd24ba1616eaed11e1a26086f7f42284b88fd1ed32d5641cdf2965f4ceffe7823a52bfe2cc2e6db6e93a93e243c8a1cc2eafc853804648716654f42a5bd5d17da0e52a08bf3d10d7a85e89a73e162f29f0d394ca9673a0ce8bb0cd0522bd55131ba1b013eb95c9a403930cb92924d2908b57a0735e47d32fc537733ff9702137044743ec4358a977219f7d49a377186b0e2bf0920804088d78478b5c88e5806f3865b2a68bb0f431386e7c1c37405c989c183cada54a0ab1d002e271c524fe4e1acc9112e64c2057563ee94f38b720ebae7452c6245526d8bd975373dd68c2af912d52f00f7ddaf62a3314e525c1404541ae0ef217c499252779d8cd687abe56bea342f034a28a122b90c520ad6530cb7a94b30cccb606580a42a787bbb0f589b8dbbc8553ea0e262ba56e7ee0f46b778e6669d541e7a7b5b298851016882c21b5880e2548d9b79ab6f38683870bd85f9d979e456a75", "0f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e84be90cc292444734c987c78e965b1739d018b44a402c956c06fcfea30a9c442ccf16a5e3db9e2b81c974405e52c4661efcc91a529144e47e78be5814d4a09901"]}, "failure": {"scriptSig": "", "witness": ["4d09026921d9bce9d183e1fff6c943711a9afaea661b56ee03416b7a046706e051b8d43fdbb8c01506d5ba97e16d05e1e287c632bb0e7a58ecc3733f05c47163c2a8ef12bba1d5a5385a040797170a04bfe23df641aaca9ac639cac5807d0bfb5db2bef492559149cb6cb5aa7b9f3fceeb26a281f074aa1b8e7bb7e7a3f7b06f0dd315bc9e466f4065769a4885f3c88ebeb9819c854f090ab9b06bf5301e628801e557defd0f64d7b4cc6fd9a23a9b7d394a35be478e027effb8d0512d431d844ca025b7f270ce1a0e9211e050c1b2d1747475d62e1f760b420d4db0808f36a8f5cb3953e5c09c03f4da723e0d5f5bd61af4bdb428fe95699b7026c81233fc54182034d270ef3ba7115e59155f4d8089155aa951234360131490b61d11c7760d8f8f806f49761a5e89bf2ffbdf5f1bd5957424df7eff9c666c6d4a5ccd73ec87aff5c61fdfb60a568beff0ba051fcc1f5fe7ffec77ff2a82fece0daf6ae3498091e1b6bfb8f6e2740339fdbf757a11727b9c61f5812a20cba28bda15c41093eb19246485cbcebaa8c0e9d00bd6b185ee4d899b4b018f22d8ba2c5c2045656d831c82ea24cc493f30cfcaea40c6165b7c3c3174ab2e3c29ca62495c996ab409eda86d5ca04c4eb547f8ee39b44a99cd4c35302de5d0270ca88f177a63797b661ad46f15af47e2f75dc19076339e85d3253645f4d39ed906a8801b62eb97facfd0fbb9fe77bd75ac916456de0475", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0825d8798a2c57206b85b6eca830bd166e5350a1cd63f89078c321fceabfae97dd5c29bd03bbcbebf503f24139d653052e63a9a9f3faf73bed4a74eee576514948d11491142a38ebb10a24e36aadbe0cf227dedfd0966bcf56b2aea8b33dc3fd67f"]}}, diff --git a/txscript/data/taproot-ref/e03443f852b194c164bc4732fb9c5cc86effe4f6 b/txscript/data/taproot-ref/e03443f852b194c164bc4732fb9c5cc86effe4f6 new file mode 100644 index 0000000000..f747a9e6d2 --- /dev/null +++ b/txscript/data/taproot-ref/e03443f852b194c164bc4732fb9c5cc86effe4f6 @@ -0,0 +1 @@ +{"tx": "0edf5c600360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ef01000000195c71c7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2a01000000128387c360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706301000000d6a1ca9b01111250000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478780000000", "prevouts": ["77320e0000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "f6ba6f00000000002251208082b91639ce415d44b93ebacde06f605687bdd15466bf93e6aed91c1a4a19e7", "1f6e0e0000000000225120ca2f7736d38d84f93b62b86d7eca19a35f2cfb6705849a1c6400bed56ad761ae"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b210e7034c35130f37a4c8504b3b1ce362cd53a6c695edf7c15e8918a2b984bc"]}, "failure": {"scriptSig": "", "witness": ["6a14616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e0588caa737bfbd960ff3fd219ca062193aa6bf0 b/txscript/data/taproot-ref/e0588caa737bfbd960ff3fd219ca062193aa6bf0 new file mode 100644 index 0000000000..a4128d3133 --- /dev/null +++ b/txscript/data/taproot-ref/e0588caa737bfbd960ff3fd219ca062193aa6bf0 @@ -0,0 +1 @@ +{"tx": "67281e5e02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfea000000004aacbe908bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42200000000a23368a302d754a3000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898740461b2f", "prevouts": ["a9f1670000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e", "032d3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6abd", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45bc79ec207f4553f17b4d8afbf0e47b02e8cf3ab2b0172732171fcb0f92ff87125432b67bf7a212872373c5ea5ac6512ad650fe3d5c26e1d584bcbdba0083b9a9e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936effe4d48aab6fcce879b221d7012ab600ee1e9c541d61044892151855353df93631743d48971d1733c6ca7857843602fffe2e4122fe98dc3fa85acbd6da797d181cd61fd18311004a5536d1440b72b537197adb3a0d17581cb4a1679e89097edb5843f54915b2c97abdf26ed2d562b36c2375ce95d63af6aa508e6368a687449"]}}, diff --git a/txscript/data/taproot-ref/e0aaba61fbc722b30669314cc389d44b8f989110 b/txscript/data/taproot-ref/e0aaba61fbc722b30669314cc389d44b8f989110 new file mode 100644 index 0000000000..6aaaefea87 --- /dev/null +++ b/txscript/data/taproot-ref/e0aaba61fbc722b30669314cc389d44b8f989110 @@ -0,0 +1 @@ +{"tx": "a045fd37028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c414010000002c805d92bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5f01000000eb722fc402346c99000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689873ec82e5d", "prevouts": ["2b8b380000000000225120d8440763d2116f9dee5377791731b3635bb44d7a42fb2b8a8507b8fff76ccab7", "dddb620000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646dbc3aa3b80e9e2d0a0162b269fe7cc9ff8c1b234cee9fd626b14f4beea4ba0"]}, "failure": {"scriptSig": "", "witness": ["6a7c616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e0bbbcbab18f481daf5b315491e268254f4983fb b/txscript/data/taproot-ref/e0bbbcbab18f481daf5b315491e268254f4983fb new file mode 100644 index 0000000000..eecb76762f --- /dev/null +++ b/txscript/data/taproot-ref/e0bbbcbab18f481daf5b315491e268254f4983fb @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8c01000000dffcc7d7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfce0000000016cac3e60495eabf000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8729020000", "prevouts": ["937b5c00000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "5f7e650000000000225120e1a0c74a8d16f26f13c9c4b6f4a1ceec6071856e9cbd0cceab614068d31377db"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a29675a8a9f92469804a42001d31f755afd3155cf1499e996268a614f1896320"]}, "failure": {"scriptSig": "", "witness": ["6a1f616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e0da4e0fe645f0a953ac5735fde4706cca9e1197 b/txscript/data/taproot-ref/e0da4e0fe645f0a953ac5735fde4706cca9e1197 new file mode 100644 index 0000000000..2a2365fe07 --- /dev/null +++ b/txscript/data/taproot-ref/e0da4e0fe645f0a953ac5735fde4706cca9e1197 @@ -0,0 +1 @@ +{"tx": "32d633d502dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4a01000000a75705a460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704e01000000a92a96b3047a596a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac49000000", "prevouts": ["76e25a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7e79120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_5a", "final": true, "success": {"scriptSig": "", "witness": ["00a5b92cf209ea7a03233faaab06f3473c81218f097ae47a29d670f4125c454524d7fae66ef0c37054e12cda1f510131fa2add7087e9c39d0e4e3d21cc16fda2"]}, "failure": {"scriptSig": "", "witness": ["32dacef7b8b950c592a6a4bc06665dc63b08f0e930d52f08014ac6a5a2ca79928d028a7825d769b60bc56402f865828a4689f495269a5fe8e4c5c8cdbc205fb65a"]}}, diff --git a/txscript/data/taproot-ref/e0ebae4900e11a9672f2ae78e61178aa6247650c b/txscript/data/taproot-ref/e0ebae4900e11a9672f2ae78e61178aa6247650c new file mode 100644 index 0000000000..ea2d4fbd64 --- /dev/null +++ b/txscript/data/taproot-ref/e0ebae4900e11a9672f2ae78e61178aa6247650c @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c200200000056d3cc57dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf501000000a74f649460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270020200000040bd4f300326debf000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac82010000", "prevouts": ["1dfc5f000000000017a91480e36171416c0f598c1c20ba17ab3a3cf10a438e87", "34075000000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "95c61200000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "2359212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["106a7e3049dc2c6347306abcffd6f8c8b3f26d4b7ee65ebb24d0fa41c8692b957b5654e881ef324dce199491145286cfa20a23ee05d277712bf9841942e08319"]}}, diff --git a/txscript/data/taproot-ref/e1087672834b43c44e37cba854b5b9c9f7179a84 b/txscript/data/taproot-ref/e1087672834b43c44e37cba854b5b9c9f7179a84 new file mode 100644 index 0000000000..3255e85af9 --- /dev/null +++ b/txscript/data/taproot-ref/e1087672834b43c44e37cba854b5b9c9f7179a84 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e5010000000f6b49bbbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf66010000005e3d45c0020d06a1000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acc2a8f43a", "prevouts": ["777a3800000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc", "e9266a00000000001652142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "317d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa37da87d72e5c2c3f2bf3679d8ff958ed33e42af1e2394a1323a8da273322fa97a4517c545b323e839a783e2c84e61e1f1046ec65ac2c085bba4fcd3b8ecf0c89"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368c9b7003f83096f4e27f57dbc2b99136041ca132bb1f5d87466faccd9e3f4bc737da87d72e5c2c3f2bf3679d8ff958ed33e42af1e2394a1323a8da273322fa97a4517c545b323e839a783e2c84e61e1f1046ec65ac2c085bba4fcd3b8ecf0c89"]}}, diff --git a/txscript/data/taproot-ref/e10bddf4873386e1fe3f6dc0f2b20f5c151c89e1 b/txscript/data/taproot-ref/e10bddf4873386e1fe3f6dc0f2b20f5c151c89e1 new file mode 100644 index 0000000000..7e74ecc84e --- /dev/null +++ b/txscript/data/taproot-ref/e10bddf4873386e1fe3f6dc0f2b20f5c151c89e1 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcf00000000b38236dfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8a010000005a24c55301f9287000000000001600149d38710eb90e420b159c7a9263994c88e6810bc78fb4e75d", "prevouts": ["e7bd7500000000002251208ae894af2a9600386c37dee4cfaf898fd39bd624f9812efea0f89b144f5e3b3c", "1d6a230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93664b32368c4af7eef3a1be2a374bfa1d9f7dd677f641009402fe4ef93ef570ac8"]}, "failure": {"scriptSig": "", "witness": ["6aae616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e11d98e0003ce918a6fad19f550ea0702a879911 b/txscript/data/taproot-ref/e11d98e0003ce918a6fad19f550ea0702a879911 new file mode 100644 index 0000000000..f8d35330db --- /dev/null +++ b/txscript/data/taproot-ref/e11d98e0003ce918a6fad19f550ea0702a879911 @@ -0,0 +1 @@ +{"tx": "9b03967e038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40201000000116593bcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c30000000008140a59460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bc010000003f8a038f03ce439b00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a61f020000", "prevouts": ["fa123a000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787", "d8a45300000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "95390f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "47304402202cb966c001ff37b464f6a3883ff23bc4b0b57f1077577beaa81a695db7c60587022034da4a6ed8c3808c3465ad5b31113581e7d04baacf44b96f4faa3d621508d30586004c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}, "failure": {"scriptSig": "47304402207212228898a16d87e7b89181af917c2db17d7f012b69287cd1b63d85cb6ab5f602204cd659fedcc04ca4c50ccd2e793458c59db2e733899c3073b5421e5747fd58a28601014c4c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "witness": []}}, diff --git a/txscript/data/taproot-ref/e1326c178bf8e7b80cda8ea9f9dd86938329c849 b/txscript/data/taproot-ref/e1326c178bf8e7b80cda8ea9f9dd86938329c849 new file mode 100644 index 0000000000..d77737053d --- /dev/null +++ b/txscript/data/taproot-ref/e1326c178bf8e7b80cda8ea9f9dd86938329c849 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc900000000ad2a3dffdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5001000000014b29e90202c4900000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6db010000", "prevouts": ["7b506f00000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "9412230000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09025d20600f8db0995e20ae953328fc2d250dfa7161b98e0947b7c54aa754e13053679b8323bffa9b132414ffee703819e68939792426d5672ac9fdf37c787361c23cc28abd6958e28d511ce9d3e5f6bd2b57c07ec0fe7e6b784bf2d226bc5617f13eec00e5b6c4640b69b2c499284bc14a001c9c4d2fb51320c4906d93754c59457d24413dd583ff2483526a7cbf762d06dfc9a0b589bfc5ed4cbd52e6e5a6349c8823ff6fa496531c863460edc2a4c7abfffe1b6c003f31b0ef6a051310077b0dff1dafeeeac4403e906d1383666202fb0cb2237b786b81212e27f236c224842c62a078b61a662104d68ed88246df5f678b326097586e66fe3badee56299f3bb85f74062e90838ee76f3381731e8a47cf3cd1837de25e0d0056e963b7e3068825e803560d29eec26c0527d6e2aca1efe08e5f39f059bd4dd36ac29e4067587a43b80904d2dfb06ce9b2941bdda3b18e6c5fa29ef67add45b3a7c19d625142348120d711d622185dd394ebdab51dd1e9e2c5dd995d0c440124d4f178e6548aca7a757ec048cdfdcd5b0d725f0e2d16933f03b4f63e0cb5cfb686a8db2c8c9c5b6bfb0cbc3e5df68919b813f4d48617cfc0349580aaf16495ce2a3995ea8545e427f0fbb31b219d730067f0e2a2865ccc63018e9d525e640d2a58e569109c9db29d9adef28f50580df9f3e2cdf59234a4a2840cdd3c96803d561c39e772524ee0a4f2709cb5e67c06f34975", "d97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e8cfdf3dc4b41074e6d5bb67bf9f12a242211e880ee715069382ad177c5f1aa2ff72d95b601af8434dcd53e2a5d08dfad1c07e45b1031877afc5b1801af7debef3d33b10ff9eee8ff434f7c79f826d5967b94922da2ad2ccade1cbab3a3658011"]}, "failure": {"scriptSig": "", "witness": ["4d090288ebbaed409d5dec4a49a41d1e5245e0611e0f139929d3186910562dd04cbc8171eb9eff0f7ad61c53e411b73b00c6b6d1e4dc21fd29c953cf32189b3cec13613bd6e7ae258d7780ef237ad8c3bc4b29db43dd21b541d63d3691cc6ab72e906d0e31835741465137ab2e32ffe9c3c813d63ed743045fdfdb8f7c3338803117f6e87963a229ddfeca20488ea69309f5bffa9de3718db6af8553ef417af2b359c0db4b7e5dd711d7f024ecce8d458c4be30a1bf7b48f452b2dc5d354a51feee0db64f532866910bd11e279f72923196350d15350f6f6cf8e5afcc3aa3dfd1287689b0db3274888d0acce3740fdf581c514ab918b173f101a83b02663bcb5356f614ca17aff8cb6479081d3751cb822b371c67df7c6e9b965fa00da2934ef18924387878254d29e3e6a0f4cde3d7abd9c1d4bd6ee8caa429862a654341f60e6d8aa9b61d15271b944ca3c0aeefaa44585dbe3a1cbbe689d4ebba739298f62ddb5fac93cc553029d155c2a476b57a118e6e9aad0e9d7800ec13e1b81243e2d7fe3c62303c7ce9f91cab21212953f05cc02f230a219255c78308e9b941f219079234b3b2694230f51c01b71f74b8df5375422c78d775800576e52452b55845d9b4f1e6e3879786fceb1da5e3d654fa5c88d99d70c7880425e5ca562b870366baea4380b6266e9267dcda6a67354e574f0dacd6ee9a711a10b18c05bcf415ab6f95133b731b759ed1226287475", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93629500195d2baebed23c7ef8c6d51f922864fd4e8b73fd6bc85a789a27ba769e79208680e05d04c3942bb784f68e647b385a50066aeeb87d1b11822ef550a3a38682a6e83df749f265180f93fd54e474915a8abfc6fef0a760c06d61a0bf42967"]}}, diff --git a/txscript/data/taproot-ref/e147111796d5b53a6bf6dc9458c50027b4d09f87 b/txscript/data/taproot-ref/e147111796d5b53a6bf6dc9458c50027b4d09f87 new file mode 100644 index 0000000000..e250ffe405 --- /dev/null +++ b/txscript/data/taproot-ref/e147111796d5b53a6bf6dc9458c50027b4d09f87 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4da01000000f19794d98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49201000000e17d8ac402e45f79000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65afb4455", "prevouts": ["b8394000000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259", "18193b00000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "317d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936baa8b3b4b8a0b13d474f8e303d1fb88b1f31b08e2de6caa1fb01bb3d4c0176023f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08228c5b97b98364e562d83f29d0f7226f72eeb298058e828607471d679ccabea05a4517c545b323e839a783e2c84e61e1f1046ec65ac2c085bba4fcd3b8ecf0c89"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936848a98c8453c3accedd5d6c98b5c0c5ec67507e057504b5eef02067a388f801228c5b97b98364e562d83f29d0f7226f72eeb298058e828607471d679ccabea05a4517c545b323e839a783e2c84e61e1f1046ec65ac2c085bba4fcd3b8ecf0c89"]}}, diff --git a/txscript/data/taproot-ref/e14960a185290ebe95ae6279b9e869e837251710 b/txscript/data/taproot-ref/e14960a185290ebe95ae6279b9e869e837251710 new file mode 100644 index 0000000000..1a200ab7bd --- /dev/null +++ b/txscript/data/taproot-ref/e14960a185290ebe95ae6279b9e869e837251710 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca401000000a89fb6d18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d9010000001d4379cf0321668a00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689870d020000", "prevouts": ["d6ca500000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "40f93b0000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "spendpath/trunclongcontrol", "final": true, "success": {"scriptSig": "", "witness": ["c9198bc74e031c9f9e1006abf908758af04e32f0efad12b4c539b1ad2f1627a4b18cb5326fb182d40da5651a09ed969a7b567354f769e97ba429222fd687a6bf", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b78be31b16966ae882c7ab2969dfe11d69b83e8cde47f805ca2a48764752b9cbbf718e574c4e60a583d038972ff24d56360066622b8e32dea6b1f072fad3e0b0e380268a7da44256761590e2195a1dff8c2ca3465130317c0b1ce6724329355e20e712a8eff36d68da3a9b55d8bbb5a56a7c2dffdcf5fda45eb6b04c97de1b90a9e89bcdd7fc6427334431f09d8e083275d692f7a4ea32eb53fdbdfeec8936fdebd95377ebbb40a5c3979ca7a09e65ec6c5748b544907952af1da6c4191f216d633f9d096a188370cc7644b4de45f8a3fbb7f05176fe1bfc064b167b3764b5cb27ad2fcabac681aa39bfac7410cf932536ccdfbd274af833d6abcfedcd9d4c1498e9d4b7b30f3d9fa0392c06867240a1ba1a87750d1e987b2d58da218ecb361b00000000000000000000000000000000000000000000000000000000000000009bdad734e6e3fe025a23777ea959457c1a4763e34fcab485472093e82ba34b6229d0943d0dd65679f059096147c046ad897f468fbc7f0a5601dbec82a0f68715000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22495b1a4a1891c2253e36490ec96b1607292246135e2ed22c7edd6214f6c4ccdea0dcdbbb8847f77c0f70ac956ee6bba8c40a0b009ffad84cd54ab946361a6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff18f399bdab8e1515fa960b1287180525634f46ea99e1abbe989bb40b526952a90000000000000000000000000000000000000000000000000000000000000000628a6886de34834298757e072e274ee77a4d415a9bc3d63ed1662b32da0ae780ae848ce8fab73b9d81a11f76fe66b44da73b126a34408d3c66751c72220890517cf20095ddaa0e39b232b31746ec7d72310bf019f8e327de3674ae303353457c15de3dba4653cc4dcf1aef7ad34da9a6e4dce0835909a4c56bc51365dd121e694e4b2521dee2aea7f1e363ab964e95ddea9a07d1bce3b8a3aac42fdb8c579806000000000000000000000000000000000000000000000000000000000000000011a021c551a25e01f25d0d9dac6016d3d162351a82137bb91b22bfae9f045767ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94b85d84adb74dc8849bf68f7e7469b98f295bd36fb195c45201c22f7f51d7fe0ed5f704019db5dd1539bbdec3d10e4d036cd037a9d70bb63362f21155e83d2b884c27c034bececdabc8344c8ceefaa5fed486be97d0159d9e6135d56395c958458e55b61aa7341b09ae049d0672ff67c18b036dfcc7c5a2c445b20c65da2e3f0090e86822a05d1d3ab2755a0710df642a4830645df3cedbb48385055b4367c357c5b074248d5062281dd686e2e28c0db8cf03f5ff95cb38d07a5642aeab2532913ebcf29d0660bcf17c396b8002d858a3ef5e68c21ab69a91658cea1f72293446ead3dd0f3a755ddc947c71a48392aa4e3eb7c08ddf4714f57b848c510532630000000000000000000000000000000000000000000000000000000000000000fca92079c632d81adf4a3b258d4338af2b60dab20ebe6975f46e68810bb132c4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb2b202fb3661f0c5604a0c3eeda6978898cb37ff9278e5815d4e5196d466e9dfffa689ab64e3f127861709db1a50a711dc149ccb8834e53273c631f65bb0e52b0000000000000000000000000000000000000000000000000000000000000000145c7a14c04fd30ad7b80bec265d4604563dba8052d658057020ef2cd3fbe02e0000000000000000000000000000000000000000000000000000000000000000db2e0632f9699acbcb6e37f50cb31c205968760c274f796186d2315ae7d0601d198bba16ea8c7c243529aac098a927346981499c1f3d3e915d1fc6006fbee8f3fa36a1bb0792f95109f467202971580cd63a07736022b617fb7faa45b21b687181dde60e4136be7b6472aa99ad0f684bbc7824749be06f19ada3f5689cad234a381d877d08be120085ef8fc78e37e3373af7f7308a09b4da9997f73f1c0e944a4d0e363294d7bc67031d3de2ffe261a4e5b184e40e0adfe553898f8150324ea67e8e64f950f72ed0fb74ac43c4fd37923915c3c77c6e2157db1d340d3f3ac001000000000000000000000000000000000000000000000000000000000000000076877632c0c065446105116b544cd4d4f2fba46cfd0165780841f0e1ded6f203fb11634d6d4bbb66e02c391d2888d1425ed03f8b7c3b266486734e343c8b3065baa96329af5c8916564fdd90306c7f310d0014586839c251c233b0dcd30f1719d76b6c3eea9ec2caf5040160071fd94cb00de6ed94875876911f904c6c82dc02ee05c87b3cc4a312252048a5200d75bf90bf4f177eb21e3a0d0e765df413f586cba37d953ba406a8cacb905df75c6f6aa4acdfb84a186ae48853356010f38a1cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff97172ee737f1fa9fb929d8292bb2805ff2268c1b0c4fff5ad29c3652d417025053beb6b633975ad3f0b7a983b4e91e3634c812e7e0d65b0fc1270e5bd5a5bd9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000758aebc787b8916e0a88054bd7cce2d63159bf3d0a5daa0256c439c0b2be1afb140c2f70c319de7013bfe2ce2f011bd84d0cd5c4e4eb06d8af9632b603050c8acf273cbc06d80241339df46b65983438c9445c72e2d6b679fd5cf6e645f31694c87a152e5f16de4bf4fe061d11bf67c3c55720cfb37afcd9a0b54996a99c25eee3f320714fd12ce7654c4b83ca0e8afd2b5b4653eda4c797f044939d0d37b62a02be4bfd0192151653144c57650b8401437a01e70ffb9708d9c8751aefb6327e2ab6c48476921b919ace450440c9dd3e97ff786356293b0f5e01fdbeefdabdc80000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000f564116ca2c9937e596fbd82c1183c5915ef10da4f2f72a35334d9c31585ebb89583133c4a14cff9bfc896e5498359f9d87aac7448ef0fdf7199d92511ca7cadb02c9d98725bdd0ad7f7a987a22a8f616f1889aa556e391c1342c2104f633d2b441775e029add390c31e46a9317bc638b6bb5a51b3f2642be45b92748a1672e8c5ccddf10a6a1a44a06133152de9863e0698c1071e33600e07f738f34710de276af9fdacc866f0e01802fd5b5a9ed9a86994f959abfdcd54ad7670e3c498a2d0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000a36ca445cf1a781a8bb9dafea3d20c8891f4667789ed11a288a320247bb68adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcdf9887df53b35dd5a0aa6a4448bd6b792254dbc3c59493986f05f41661c74fe1fc9192c3b74775c5d594c3a7d05ddf95c6dcbae7f30b9beba7d66f64b9e04af446e4e747db79ea28e3dde4e13f284ade9ad3056115c4184e22133e89b49c8e1e007fe29858f36d52f89a88e25a29916a611a81e2ff0100c6a149676ffe2ebe709cd018dfc65f933b96aa86ad2c25f70a3fe9fec3043261be9bbab80f5042ad0000000000000000000000000000000000000000000000000000000000000000ef468c5fe9b6a8b732686a20e7f7c65543bc50da4f1262ec1eafd44fec2462ddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82a159a179389e402345f5153d944866f5da1b1520c2b1281d64d5c9a01929d3e0a818a6eb2febbf43e99c4ca262fc3121359042b561868763ac470241567826f08106b87cc2b22e8eab99b95d827ef386a9ca8422e9fee9141b482d14d70496f6d075ed3065418248c64e82bd7bab5ebfbb93a89fc1fd132e8ea5cad1c0cd3aefbd47181b4e937b7a44e95701dbd40f2ce2d0fe197917a109df7f60fd18d04e0000000000000000000000000000000000000000000000000000000000000000ea7ca48b4d6661dc0e1e70085dee3fccefca29073f686dd0f619444664c3fbc20c62bd38f5a5e193879e1bec2f6a4738c90e10a17dff7a9e399e8aa9bd4988d6459f5cb859e4c808c90f6ed0019fbd2673a9fb29843a766a017f7e160eb6143b355d89624b619efd0c816daf144921029e0517958795158b584de9f6852208dd1df3f8bc459112072b86adbd8c1163d34f720f54185f97b46b3354765de3ea1d23eb0e99276b7387cc9ecaf0ed692624b99e838e49f0d5eedcd56e377cc79791efc6b1f2266d6a4b08d5859a07c31e1404a018b03669aeb715ffc019d94d751246df2cc47965811c390361848484f692ba14c2e62e6f44b542bd52879bcc034937dbbcfcfc3e873a19b446a92392f35f1c4faa401d84fb12cda38f2dac70e2b14374d6fa475421d762df54df4a569b148b7f3ac1914d1624fcc62841501ac36dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8e8f1a68daedd98588f5fcbea31a8a940a4d32d65684223664bc5f399ef64fd8e229aeedf2df90ca58fec8be2b5af84a9783b08a067145517081f6715e380e74c3a4428ecab42b0023a47dba881b935634d9f2aa7aec5222e99f2ceb1be8101500000000000000000000000000000000000000000000000000000000000000009bc483b6d6ba9fc1f1c4a62e522dfffc09f678788b69c0cb263b5999e11bc3923abc7a392e8271d6b4b8a78124a036c473893a94fe314717d95bed941efc79afa37447111a784689db7d3094206768abfd29b8f3255c8ab5531531e94576579b82ccad9763146d19045ac42f2a46b4286b4b51af7fd6fe115a15fc962c1fb984eea1571bc255d199ef16b2e71ab062469f335574bb9b2adc00e9c166c27d6e1f000000000000000000000000000000000000000000000000000000000000000089eb19b8880af1bc072e67e7e1440929ba857958738cae978ba7ce95231066aa0000000000000000000000000000000000000000000000000000000000000000b0dedac4e789728a5f5680de06b8c7a14a8a057c82868ff58b767e51ba45a3a695d7853ec13823fe853b357744f1d93fc74db6a2a647594f3d40e6b2c819eceb00934c1614f0446884767042ada569edbedb35763667f0a9ba256d88f8b98a3f1a6fe93ae751c55106a2651e129aae2e49d93d782b623fcfac8063d61fabed3f878def2616efa4a4a7fcabc756acfb04b8aef3f8c2852f4b6a095a79df89adcb"]}, "failure": {"scriptSig": "", "witness": ["c9198bc74e031c9f9e1006abf908758af04e32f0efad12b4c539b1ad2f1627a4b18cb5326fb182d40da5651a09ed969a7b567354f769e97ba429222fd687a6bf", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "b78b"]}}, diff --git a/txscript/data/taproot-ref/e170c4afc7cf3aa9e0e5c2670686778994fa4f11 b/txscript/data/taproot-ref/e170c4afc7cf3aa9e0e5c2670686778994fa4f11 new file mode 100644 index 0000000000..b76c7f3bc8 --- /dev/null +++ b/txscript/data/taproot-ref/e170c4afc7cf3aa9e0e5c2670686778994fa4f11 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708f010000007d6193fc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f6010000004a71e3b960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705c01000000093cd1cd02363e64000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87f047c423", "prevouts": ["df2c110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4a5e4300000000002251207ecf5669449c43a088571b8452d22be90b9f1c03aea1b9900f46f7b654cd7ae5", "818712000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d0", "final": true, "success": {"scriptSig": "", "witness": ["fa4f73410381304292d94eaf5d8be3f7f2709a235b0fd37bb8bfb41ed3d02f7f60a3462e85dc669c0a16166a16762a451637002a03f74f88a1992fad6eaee8a3", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["849bfcd3084d95a95d93738298a994f11f9b7ed192d1e5b96bedad04c2e4a53519bc220cdd391b9087031e62781b4aebc096bb7823bdd92ee8e17099f9c5999bd0", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/e184bc711398d7c0c1fa6934192fda6c555a1cb3 b/txscript/data/taproot-ref/e184bc711398d7c0c1fa6934192fda6c555a1cb3 new file mode 100644 index 0000000000..b0f3669544 --- /dev/null +++ b/txscript/data/taproot-ref/e184bc711398d7c0c1fa6934192fda6c555a1cb3 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5500000000e17386c6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbf01000000655e64b60215bcbb000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48731792f38", "prevouts": ["e16e49000000000017a914e18c03fb168c1c1b3408ffb477de8ff77b0fbd9587", "c198740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_93", "final": true, "success": {"scriptSig": "", "witness": ["73d4d8990c22287ea75a72b4076651141cd6db6f3529c3865a66cf8fc4e3d5ce9fc88adcc46e4a93ab1320539cd37986901375f02dd10c9581c899c41cf953cc02"]}, "failure": {"scriptSig": "", "witness": ["bedda449369dfa9d19f670f7ef2005015a16df8e7d720d532ededc00843dc2616c36d7936248781ce86cccd0c60245d8eafd71596ada74735b311887035e8e9693"]}}, diff --git a/txscript/data/taproot-ref/e1b11848fd01dfa0ba32bf126463d9d364ab4313 b/txscript/data/taproot-ref/e1b11848fd01dfa0ba32bf126463d9d364ab4313 new file mode 100644 index 0000000000..9b41c3223c --- /dev/null +++ b/txscript/data/taproot-ref/e1b11848fd01dfa0ba32bf126463d9d364ab4313 @@ -0,0 +1 @@ +{"tx": "9cd4c5f8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40d0100000043103d8c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127060000000005b59fac60132e71700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac67000000", "prevouts": ["9f583d00000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "5860110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "047d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb6863138d45c5b9211ebf4039595f6572b1b39ac7fa7faf75aa7045d3f3541879de556ac6994112f2dbe51e2f18419f84f5e3afde46d5119f13558b672a3f6371a343680beaae3fbea53ecc49afe7cbe880992a117d636f336d7d159be7b446d"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b3e41ed570d7da98aeefbdf157119883206a3ec62c5ee7bcc27bd56cc9670384030e911897c6e4798122efc4265e48d96402783f565c89ff2a62155c020859d8460181b685601280cbfaae0e90478ea5ae6fea73a2d03f5a79a14a3e0c6d503"]}}, diff --git a/txscript/data/taproot-ref/e1ba585df080f7b1a7f8f2c7db5dd610f19174de b/txscript/data/taproot-ref/e1ba585df080f7b1a7f8f2c7db5dd610f19174de new file mode 100644 index 0000000000..eae9f1edda --- /dev/null +++ b/txscript/data/taproot-ref/e1ba585df080f7b1a7f8f2c7db5dd610f19174de @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709a01000000adafb548bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8201000000cf248c1a03e0558a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac05010000", "prevouts": ["bd9b110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4ea27b000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "027d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936420b598f8858794c178995f11a8e34655a29ef30c99d23407a26d0a64bc31f191a39935f0afddba064f6b0bc8589127966a984604296ac06f9873b8ee7d7aea369828280661f54bb25ef200c9d39138c753346ae1cc558703fbc48b26980763768cf2d3d0be95621d7446294d89d9a2894510d2dfb4e1a33e7316a17e39cfc99"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936228879bafec8e1069b4e024c9320127e455344299f19b4d97495a4e33db3a44844c267ebca37631eb8e8b6e08a101702978fd7f172e21a8d6d6b527626f4402168cf2d3d0be95621d7446294d89d9a2894510d2dfb4e1a33e7316a17e39cfc99"]}}, diff --git a/txscript/data/taproot-ref/e1d952db862331ca79b0a9c72c162374fb1857d7 b/txscript/data/taproot-ref/e1d952db862331ca79b0a9c72c162374fb1857d7 new file mode 100644 index 0000000000..0229fcc7a7 --- /dev/null +++ b/txscript/data/taproot-ref/e1d952db862331ca79b0a9c72c162374fb1857d7 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fc01000000fc7cc7ccbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfed0000000086d73080029a989400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748768010000", "prevouts": ["e92f130000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "09138300000000002251207b42365751b5fdb0753f79b4cadb5a33cc8ff9fcbce7e5edcb6c5338d7e5f81e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "f37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93678222c567c1a65829550fd3c2183189ca7aadcb6cabdbec6c6257af0e513de4394fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6ed93ab99c02c1580916967b23bff6c51eda165404bd9578af086db7302f1c7275"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e87bedb3584a87481f218db37ff1fd20e008c2f171ef887df99e3acc75d9f4a6f1d93ab99c02c1580916967b23bff6c51eda165404bd9578af086db7302f1c7275"]}}, diff --git a/txscript/data/taproot-ref/e1e49dcfb28496b89f4ea5ce3dc0d76d880076e4 b/txscript/data/taproot-ref/e1e49dcfb28496b89f4ea5ce3dc0d76d880076e4 new file mode 100644 index 0000000000..183ebfb38f --- /dev/null +++ b/txscript/data/taproot-ref/e1e49dcfb28496b89f4ea5ce3dc0d76d880076e4 @@ -0,0 +1 @@ +{"tx": "0fe2948902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be6010000006a51eadd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c4000000007dccafb10437fd2d000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7964bd1f750", "prevouts": ["e56f1e000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529", "981f110000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902cb38dfd361afd702c974a25d6865c03a173543537bb6578cdbf2994118157fa521ccdb3f8045d4d5f0b904cbeabc676c128b409ed28168c6044cfe3b374420726862d0d97426f6d11bf9912c253c2638aa41ed0a752203e7cb7cd60868268865031356d1c91af74f1188ded93326d2c57325f143090da96ffcbebd1cee73d74ae7f70e850a37a9ecde11e5a233fa5d4d0edd4905cc4bd8f4a77e2b9fd98d210e355fb7b7b658cf41f01c7b2443e8fda819ccb94cfd2aa6a52be675282748f651167987994112e78dfd7946d9e3843351b817919ac4796e190f09447392834baa612ce71b2fe18ef1c78ee194204c6680f17b0e812c2f3566c1823ed1cb25385aaad6f752dbde1a700d4870ccb70dab75a104c76b8bfd64dc9ac4a165c6c5258a85ce9cba41d6f6a6753cc42b280fb8eeab3e16eb22113fcf2bc80a9033c054cfa3cec68d0afe1184fa970e59b0b5ef2ba28b02cd3e27b6834c431ab8da4f26e2bbc5ea27e77d614616949f2536788421cd80a05ec7125e6db60ba00f96b9e7ef306bb24bdd1554c8a2a62d1443a55e7e3b5735c81a05a63c5db4704d36f7b92ba54f982ab742b17468dd3732e764abaeceb27839e2da9bd94d67218143774b38b3d7e484e46d0322370c445b8e38c10e206b289c5991bfa7502436102bc9ad223ef391d1d482aa3df54a4dcbabc9faaa1c989e5dcbe40b2ca69236959bc0c192f315c054ca8e2fe6fd75d3", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4272895df1c355058834787a12b20ffb756990efd77bd7ff75ef6e99c81f77af73e02ad6eabd24d4d247e98c297de2a9d81d67e55d72d4ddf06c8e9a23565ad8a003e045cb689fe4fc6de332c618eb0cdce02c2dd8aae7c6dd6f70bdbaede2814"]}, "failure": {"scriptSig": "", "witness": ["4d090210557bf04b49bb164a20cb96dba3802883f479e809c623a52d15f1acd522b8191d415389ac455766a36d682969ba18e280eec2c8a3dba4a9079ed35f9f384e7d77c2f2a51588a00408410066542a509b255d0eb2b042061776e7fcfffc47d39f01b0050e585894905ad848179dddd272b0a0ebb225eec06159370f554d603336af639b6d546acbf4e39279539b7b002694cf148e4099f6d279090a7beccc29549da9c8d25bf11125b4eda377cfee0cbaa319314f438d9a12131e6eb48a2cbcd92c1de6920d64dba658daf5b96b01e35dcdeb20009fcfec02b70130d86776087793a62d5d75d7a03ba1d16be28d90f30e7f86048d06326aae5e9560099cfbca949ed312d31cc0ef94c7fa3dff82a0a9e883fab8f5c68b4f348bf51890b27fd3f54b585902e7842d92358b8b32c67fac4b6d89ca90d81452d17603de4895ff5c4b712d447e48043caa33841cfc5f46d9c77a7bec3e7471b93b4fe261a687df340e3900bd7ddac564e3ddac29a4dc87f90db96fd4376ed1159ae71827fd438549d92b126296b2a6627dffe99ee4e1193293d8c2d3e57bfee318091294e7bc3db042e9538d51dc42eb1a4b002563c1148b41d8d9be23ee37acc019dc3adaa9cd5f94ee72037372ab2b2e6af5f1726369ce62318618f42bec75c5b5480da57b1f39f98c39fc9b9752b1b8b8acdeacea5384bde5d0a86fa105c7e6ef7a558ff96da77be1fb32344fcc3b09cd7561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93660bbd289a3574b95652603eba9bb146799ea91d5db46701829a42358fd9ad106234a5a049dfcee5b69ebdb7c70e6242c675d1abc9cd58c84d7f9a8e8e1277a43a4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}}, diff --git a/txscript/data/taproot-ref/e1f0807d7b3a4bba613963e80beb7c74850d5c28 b/txscript/data/taproot-ref/e1f0807d7b3a4bba613963e80beb7c74850d5c28 new file mode 100644 index 0000000000..5b77ca7456 --- /dev/null +++ b/txscript/data/taproot-ref/e1f0807d7b3a4bba613963e80beb7c74850d5c28 @@ -0,0 +1 @@ +{"tx": "02934972018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43000000000ee48958c0115ba1c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7d1000000", "prevouts": ["26aa3b00000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/popbyte_csa", "final": true, "success": {"scriptSig": "", "witness": ["cecd5264025adf4013b9549d7df8d8922594246fa1594dd3b27d6f08cb3cc80694f97376a401e6372f386b2b9dd34f1a6474928660619a394f14cadb3d20692d", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef32555276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}, "failure": {"scriptSig": "", "witness": ["cecd5264025adf4013b9549d7df8d8922594246fa1594dd3b27d6f08cb3cc80694f97376a401e6372f386b2b9dd34f1a6474928660619a394f14cadb3d2069", "0020aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ba5187", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b4156e42857b376da8d6c773cfda98a48ea1c932813c83e4082e9a92127ef32555276eb689076808afe36911989d4823aa7576798f07a1060fc609cd8f041d5c3"]}}, diff --git a/txscript/data/taproot-ref/e22480aebb82f3343403252198ba68a247b6d046 b/txscript/data/taproot-ref/e22480aebb82f3343403252198ba68a247b6d046 new file mode 100644 index 0000000000..b93a842091 --- /dev/null +++ b/txscript/data/taproot-ref/e22480aebb82f3343403252198ba68a247b6d046 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8f00000000ed8cc89e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45a0000000057eac8a603966c5f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac496bcc1f", "prevouts": ["7fdf280000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a", "752e380000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_3", "success": {"scriptSig": "", "witness": ["4a40e5df678a84a92a1b8acf5811cbe61f2ddd41409d091d66f4b0975d350abb88e347986859019450db73f9e8a9fbdb143578940b833f98c7a9772c7218864303", "5083deecf4721c9cdb4119d484f0caeaf438104133a0c467de03fedcdf2a6bcd686be9e73c"]}, "failure": {"scriptSig": "", "witness": ["f096abd28f18cbdc97736ca689aee4cc1da800e447ab15087c032854ecea78e38dd869ecbcf665fd8055fc1fed8d7996f64895a0d406057ee149bd85209ac13703", "5018d17b90f0439b917a7d21e57f85801093"]}}, diff --git a/txscript/data/taproot-ref/e24851678d123d31e1507cb51348f5b1dc101d4c b/txscript/data/taproot-ref/e24851678d123d31e1507cb51348f5b1dc101d4c new file mode 100644 index 0000000000..c2ea7a9553 --- /dev/null +++ b/txscript/data/taproot-ref/e24851678d123d31e1507cb51348f5b1dc101d4c @@ -0,0 +1 @@ +{"tx": "66c9d80602dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bff00000000e4b956c2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b000200000011b1a9fd045972450000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876c7bd32e", "prevouts": ["8ef71f000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "f8d7270000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "5a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb4949da8d2968254411aebae49708200d0b19b59a844616925b107b397a8b89bee9c212f1ab0dfa1a42522b9ca3467b009d36f3b841f39cdc4da4a0520ce4fa4"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363156d98d4892d7410c1d56e89a5dac6879f3c721d967b53738c8218a78e8dbaa16aecc6ca17fc53cd4672680bbeaf62b9cce164f53144e8804363c70dd634bddc531ca70e78518003474f611c07657b0808402a053b744a80e6cf25146bdf24b"]}}, diff --git a/txscript/data/taproot-ref/e2496a88dd988d4f3ef82308c3cca33a874d45aa b/txscript/data/taproot-ref/e2496a88dd988d4f3ef82308c3cca33a874d45aa new file mode 100644 index 0000000000..ad4c0f973e --- /dev/null +++ b/txscript/data/taproot-ref/e2496a88dd988d4f3ef82308c3cca33a874d45aa @@ -0,0 +1 @@ +{"tx": "9323717b02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9f01000000a919a7ebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b380000000000b460fd01079d2e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6da000000", "prevouts": ["4a23220000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "54912800000000002251205e14f4853651bdc12bc00c912e88f09aa7f67557a17e07f4e10b78cd4d829738"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f9", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d79df6a78da0f5e7e8abe67a937df0199bc2719081f435200b4d9406e022e7e11ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045a58cdb730d5140e8751cef937639de4f5fbc77d98986906c68a7616d2fa212f87d6928db58d705af4b513465b8e8f739d066723840f3c873585fab69756481ab"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365fb6cdab2e5dc224d99eb40cef967cec823dec47795ecc7beb7ac0a6ad6c13edbb0de8cab6875867027c85350e6845db37b89c1faa2a12b075d8db116249f7bd2367bb7d11bbe7d9666c447942212a409021a53e3151df7f84d090727acdc4c9"]}}, diff --git a/txscript/data/taproot-ref/e255d1877a2010d7fcfc04ed18a7a010df14a2c0 b/txscript/data/taproot-ref/e255d1877a2010d7fcfc04ed18a7a010df14a2c0 new file mode 100644 index 0000000000..34ce67f94c --- /dev/null +++ b/txscript/data/taproot-ref/e255d1877a2010d7fcfc04ed18a7a010df14a2c0 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b4010000009fa83274dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7e00000000eee18aed04b9ab5c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acec010000", "prevouts": ["5a6440000000000017a91495eb8fe3d959e08a2cc279c1b4ede1921d14a93b87", "fdbb1e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_49", "final": true, "success": {"scriptSig": "", "witness": ["f893eeac963b1118173a285f4a8546ce8791939bb90759eda807c640c7750059bf7c9b8e63f1fba83a6fb70a5520b46d24c643ed5f198311ae039bfcaa82504982", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ede171272bd7f49dd7b6c99912e3d475f14d5b710683506840ab3ca043c5142eb876a08a8feca7a0fdff718bc790551fa8e864b5702fbb483fd91e5e775e9b3949", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/e25fb2f6402ada66247ba900b01f074eb85ba330 b/txscript/data/taproot-ref/e25fb2f6402ada66247ba900b01f074eb85ba330 new file mode 100644 index 0000000000..a7cf72d12f --- /dev/null +++ b/txscript/data/taproot-ref/e25fb2f6402ada66247ba900b01f074eb85ba330 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703e00000000c3348ab560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707c000000000d6403d70465f522000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a67f64dc44", "prevouts": ["2d431200000000002251204e94ede8d65c6640c4e6b607af4038eeb61cf5c03f43315636aeaf4bbf4b4fcd", "482b130000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2172fc08f39dec38a16acdaea6f2fb40d915f4bcb39aadc0ac96def6ea8d2de907407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6d5e8883e00432528415be42327fc5a4a6375200eeb9467b263c8c2a6402f75ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2172fc08f39dec38a16acdaea6f2fb40d915f4bcb39aadc0ac96def6ea8d2de907407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}}, diff --git a/txscript/data/taproot-ref/e279990fd5d183e1d8b4f404ff9bb849d49c365a b/txscript/data/taproot-ref/e279990fd5d183e1d8b4f404ff9bb849d49c365a new file mode 100644 index 0000000000..ab62fe30e4 --- /dev/null +++ b/txscript/data/taproot-ref/e279990fd5d183e1d8b4f404ff9bb849d49c365a @@ -0,0 +1 @@ +{"tx": "6feaa06102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf13000000008c1dfd8060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709b010000005302e8d802def79200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6bbd63d48", "prevouts": ["853382000000000017a914a8c07d8aa161ec0fed82ac1dc93d81dd0a92012687", "53ae120000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "235b212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["a89bf0e7e51d916bacac8530956b4a105bb87b458404335cff97cebc187bc4d2ff6ede95852665dbba540f70fcca1837a4dad11db9c39d91dbccce39527bef7e"]}}, diff --git a/txscript/data/taproot-ref/e2d5ca40d2c53fc997406f6b09aab24c3df0d72c b/txscript/data/taproot-ref/e2d5ca40d2c53fc997406f6b09aab24c3df0d72c new file mode 100644 index 0000000000..0957d8c81a --- /dev/null +++ b/txscript/data/taproot-ref/e2d5ca40d2c53fc997406f6b09aab24c3df0d72c @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270250100000036c4ee558bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4510100000070e54af860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ac000000007953921f012baf0200000000001600149d38710eb90e420b159c7a9263994c88e6810bc727afb653", "prevouts": ["de1d1200000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "bbba3e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "781d120000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_csv", "final": true, "success": {"scriptSig": "", "witness": ["2daba7d27b40e2d99db733e13347a769a2b8ce0ef8210b2fab4a605fa1e1ead27aee99160be27976455f20c218134cb9104f7212bb065b9828a4ea0d4be7daa5", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bdd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a37f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}, "failure": {"scriptSig": "", "witness": ["2daba7d27b40e2d99db733e13347a769a2b8ce0ef8210b2fab4a605fa1e1ead27aee99160be27976455f20c218134cb9104f7212bb065b9828a4ea0d4be7daa500", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad51", "c16caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bdd10f3c8728958fb0bcc53cdfc759a82731936f05c1a0078c53069409a334a37f37969b6a2e7d48dc77eb5766055d03d7a66c5c1ccb6908b74db43ceb06b6b0d"]}}, diff --git a/txscript/data/taproot-ref/e2eeef8ece1fd34ca3dc565f6c64e1e27ffe4394 b/txscript/data/taproot-ref/e2eeef8ece1fd34ca3dc565f6c64e1e27ffe4394 new file mode 100644 index 0000000000..333370fbe4 --- /dev/null +++ b/txscript/data/taproot-ref/e2eeef8ece1fd34ca3dc565f6c64e1e27ffe4394 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c55010000006d0e8729bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1200000000fec08d1f036360c3000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdbfe094d", "prevouts": ["a0155100000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "95f273000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sig/sighash", "final": true, "success": {"scriptSig": "", "witness": ["520193ebe9230453608bc1f99ebf3d2e834490f0d69577d94d919e3c7820d57f33e138d2fc2445113ceb9a1e2f5cacb7abb5d79a2a4bac18c85b9ceaf0c7ac9d"]}, "failure": {"scriptSig": "", "witness": ["2024f6aaf5a84cd78ddc8ba0de2c6373fdcaeebbd152bf13f0463fb733264b8b24dafd196e73e940962f9d46bc6f1ce175526454d67411550428869530397429"]}}, diff --git a/txscript/data/taproot-ref/e3196566970071a5ddde94e45545b255dbb827b6 b/txscript/data/taproot-ref/e3196566970071a5ddde94e45545b255dbb827b6 new file mode 100644 index 0000000000..b4bf4bb2a8 --- /dev/null +++ b/txscript/data/taproot-ref/e3196566970071a5ddde94e45545b255dbb827b6 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705b0000000087b009d7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfff000000004b4bd0850218eb8600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ace6000000", "prevouts": ["aa620e0000000000225120787bdd18c6671a560ba1e95ace53716ad824e1d735ffe5db246005d995daa6d5", "d04d7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_2", "success": {"scriptSig": "", "witness": ["230d1df19eff895e2599855a9bcb46b5f5e1b3b373521c264d1aed4067621e005e146c4ef4b898a3967c08d4ffceb8880330bec7acfd85f0a072d5a377c2572c01", "d5874c9986c6a813b67dfd48c9d32dccf21d139797772b545a585f8cbd64d51d007c244e10a60e13fa5097d4c8e01f0a2b325c854b5dfc824e6507780da91bd51a5cecf14d4477b219c25e6bf3dd571ee5aa236f4dabb5a653463676c0a9420bc7c7093f91bad0783b41e8df1bdfe570a39a0ec152ef4479e556a576d62392b2f831a91c45d25bb417bb5f84555aa645b725020d72ef88d06713a751c049272bfd19d8eef16d9a8fde3e5a54118cf117dd598c874113766b643874e89b9d0acabf612a5aaedb0b2ef0cebcdbbb02e0547b897f86f3c0e2d91451036381617f56563e44940284b020885863", "4cdc105ac9b3989c262000fd41f356e1594f27e622977e8ca48ce72891a0916defa02fd5dfec33efdb8b6bf698a2c508f78cd5f6dc6351b9e710753eac332b4b0314ec5f88ea0913156067223bc47bfa60317363c5378343de0a7f973d25b1c088495ba67482f004d018f86cb4d4445669cfa5442ee7e6aab33f1880a9417576df47838c5baa51dd59f18c1da304b81ca290660158c3ae8f4f2d4914b1083cb263a334dc4111a32d8631080a1a75b07131f08d763dfc4f6df987ea9ce43051e0560426535c7089468111a6ec584443daf182f395ad482e834b882f93c0df6d23fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da51646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936673ee8f995d5f053411291b7c711500e5bf5c2b8a04e2c08b17c1d99d191b288df2608c583a153244c14bce98b397ce61bb40bd7c92bdaaee99635b9843e0309f946230ab5c0bb8920790afb616352841690f577ce41be5cea97f5ed9d976756ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff094eb8ad8baddfbbaf914601b8cd3207cfce58ecbfc9a1770bf5199b01284a18ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e36585f56a8cfa0ab578b87774720cb80d38fb01b1a38a68e031956b2913c38680106056ff0214383bda029a0df88b9ac095b1cf501a23193ed6c4499c2ce968b682063ff9a9990d791188847d9b771876ecaebfecec19c1b640ee7c9d3c4280000000000000000000000000000000000000000000000000000000000000000f42272f3861859d50669482280bcc7f9cbc8131d23d9d947d5221a85d9facfdf4fbb31b6cbe0ccdb6beb614ca7ea11bd2950d588063675e87fd759f3d3f7c4745173f5b65d4791e21af11d27f540d12b5457ac4938f2f8cc2555897fdb2f64dad5641e5cfc7011274a4dfcd053fd282c053954196a97b1f30396010b458e473affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff731ad8edd2ebf9cdfba95d48249bf196956cab254a6bd0145d9acdbe8567f9c4731bb19b42ddf13fa14055564fc231eaf1f8a88cd899fc0d480926d41e88b558ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fd67e8d13139bc8ed0ac9ce1ee2a3e339eb470fe60d69025a5e99fd57d9f4814d5b8f9dfbb84bc2f49c0ac30da01884a7605ae3a48121e6eefa7eb9769bb57433d58ea9bd94db6658ee31d16330cdb3b3e4c2f8154f78e8e8a424710055555b675d1c6dfa7df33aef4350e36be45204dcc6066f35fa406039d9ca66f00123a31fa7659d6dfb7a506ddcd43fa2434d22830282f76613ee35c36122a2cfcfd6bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff644ae27fb2131bbe69749878ca427c23f0619613aa90e17c2b22e2a76fc397966ed39df72b1b8dd446ac582ac132955f3deecfd8176c8d4f279162992b8ff954c03eb5a5e79f7003e9743036de3e4794dae5236a16bb8515ef8e25dddb0cc96600000000000000000000000000000000000000000000000000000000000000000e6dff3e4c52c8c7736c645348e898fd4f4ddbc7ff00bb73d488a1c030d37d54000000000000000000000000000000000000000000000000000000000000000084b14accb769af52b16713af4ec9846635a9c611446103d32ac9b3c6ab16c3adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61a02d51c32c7f9d4fe7f399ec07cd0f3ba353479c3c15c0a87097ff48c4caf00000000000000000000000000000000000000000000000000000000000000000ad32c00abd55cf610b89dfbfcd4f29dc4bfebcd6d66065d13b22b92f3ad0527379768a3d820e347636f13e321b2ad2c9ad5599e83e03583b2fa761f782de4404751d656e1cc9cf447660c0cb44ac96c4e63cfe9f0ee87756335259cdc4c034df321007715711022e43f721812cd9efa1d07c9b3512248a9f944cf27d024542b0000000000000000000000000000000000000000000000000000000000000000071f9b5aca7b9043b9a7a87c56c7374088a1a5ae564ab0ae71df1152621bb00f2573e89a7fc58b722b567ceba9cbdf4568d01f20059b5f0d67ce2f02a5c26d2f6f32d341ee92e5ddc5efe0ba8b7aa3dc71aef00afe9787130cd0221fd19c8b7ee2a5762b49563e18585c6edc15ab23e8a72508b05dee38b5f51d6c972631186d58395cb0e36c38f2285f1e6c301c32b78bbf79b1f4a8f3d92a6a11ffd15be7ffecc86cece7401ad4ed0bf21ab49b443d1e16320b275500e520ba1dccc99771a56048d46b8b7365efdfe5cf88d9c0ffc3fea4797d122aea191bdfce588c8554fdccef95f09527f0681a9d581e220e0bfbfcc9ccd6ecb8e28e08a1575f3dbe0731700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0b14817ff235fe92c1a6562a7b2290e5ed6d95310a63277990576053be34f1d8da9bb2465ff85d048d65d212d740ad94c8db8b0670b3c282fcca8a1637381b8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff36804768f0736ff1a653ceccc7fdafa2244398fb3528fbaf22acf3b699cc49e359d02ebf3d32d8b15334b9dbfe5523163c5b5ebb1cc7eb05bc6dbf88b98fa101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff47dca9acdb92211f9e7dc4b057b9dce286a552926821c4f5b0fbe794a80bd20ba990edd6a246b95d2411447466b2e2ccc1589c8e153fce8f160db98ef9b2e105c360afae5455111e55f3716f0a6afb5af6605025be25d40a7048db97134ff9e545bf7d344599742b95a76595bf0a647cbfd58e3cc32b7e7ed09e55f82d7b9ccfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff63407cbe1bee091ee8256cb65a3009db4a9a7b0f6712b8071cd5f05bfef9d60236f916c2ebbbc5ad701920af5c7f3ec01a1176574a2b39938ef1f295b91758d015aefde4a6e712e45ce4dda43fd681c7e831aba25743f9c9fafbd98364fdb7c6b89eed55165851ca85176e686c4d82f029dd4fc961daf96804887b653ee23e34638ac68efbff837bdbb9b534401511b9069e69b7a2a12cf78d1f52a26e098cbc6c8d3a4b41955c65bb497c551e6cc1b8a57f839221d25bcf5e7acb0f997ad99ede3099588d6f1a2bd3476a897297c8bd479166d11e15b1fea505fe8427bb8fbc3a94eb37abe20387b3e0fb8637712d3bd65b08e562916a74eff73a16871fe3bc54a8010e3afc091f48296c48c7abb69ee8236f7d2bb6e655c9dba605afb329c6b32176f5e7041c438b2b05d4596d53a42c830fee890fbfbdaa66edeabc98ecb8600706dbcd1b497cdc739d3c7bf16f0b1aa967cbb59504da18175a9854139217140a43e4428e9659648f0fff6f037f9b5dbfd2da8f615910499ded9a2c50179b", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["230d1df19eff895e2599855a9bcb46b5f5e1b3b373521c264d1aed4067621e005e146c4ef4b898a3967c08d4ffceb8880330bec7acfd85f0a072d5a377c2572c01", "96e20fe4bac2808aa502ec996ff850f405e3344620235124f0902a1acfde934716ea99c8394a6555af8e80f0b496acf9c9caa8e984ac44ddca7e8bf4bab51dbf33bbae041d5b9d242d8543742c2f36053671956ef8426680654cfb81ec6d8c97eab00fccb33b5c2ffb0b39b3cdc41cdae4608616d67a0277013ea3a407a59898dd284f33fd554e83994c67ab0f9767757c0615c73a4d2e0d7115a8d27219e4f42affa2820a2f02e0055004b2dffa17feb3fd9bf3965fe2a3af275042f8095d50530a99a29eb3f45c23d14bbcb1341357918fbc612a04b661c9a923bcf77bbb95761ba5ad9f38d276b9d2", "4cdc105ac9b3989c262000fd41f356e1594f27e622977e8ca48ce72891a0916defa02fd5dfec33efdb8b6bf698a2c508f78cd5f6dc6351b9e710753eac332b4b0314ec5f88ea0913156067223bc47bfa60317363c5378343de0a7f973d25b1c088495ba67482f004d018f86cb4d4445669cfa5442ee7e6aab33f1880a9417576df47838c5baa51dd59f18c1da304b81ca290660158c3ae8f4f2d4914b1083cb263a334dc4111a32d8631080a1a75b07131f08d763dfc4f6df987ea9ce43051e0560426535c7089468111a6ec584443daf182f395ad482e834b882f93c0df6d23fd04c789370a4769e07702aaabf2e481e97af0e9353c38f4af320a201c86fed16774da51646eac69686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead547cba5587", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936673ee8f995d5f053411291b7c711500e5bf5c2b8a04e2c08b17c1d99d191b288df2608c583a153244c14bce98b397ce61bb40bd7c92bdaaee99635b9843e0309f946230ab5c0bb8920790afb616352841690f577ce41be5cea97f5ed9d976756ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff094eb8ad8baddfbbaf914601b8cd3207cfce58ecbfc9a1770bf5199b01284a18ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e36585f56a8cfa0ab578b87774720cb80d38fb01b1a38a68e031956b2913c38680106056ff0214383bda029a0df88b9ac095b1cf501a23193ed6c4499c2ce968b682063ff9a9990d791188847d9b771876ecaebfecec19c1b640ee7c9d3c4280000000000000000000000000000000000000000000000000000000000000000f42272f3861859d50669482280bcc7f9cbc8131d23d9d947d5221a85d9facfdf4fbb31b6cbe0ccdb6beb614ca7ea11bd2950d588063675e87fd759f3d3f7c4745173f5b65d4791e21af11d27f540d12b5457ac4938f2f8cc2555897fdb2f64dad5641e5cfc7011274a4dfcd053fd282c053954196a97b1f30396010b458e473affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff731ad8edd2ebf9cdfba95d48249bf196956cab254a6bd0145d9acdbe8567f9c4731bb19b42ddf13fa14055564fc231eaf1f8a88cd899fc0d480926d41e88b558ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fd67e8d13139bc8ed0ac9ce1ee2a3e339eb470fe60d69025a5e99fd57d9f4814d5b8f9dfbb84bc2f49c0ac30da01884a7605ae3a48121e6eefa7eb9769bb57433d58ea9bd94db6658ee31d16330cdb3b3e4c2f8154f78e8e8a424710055555b675d1c6dfa7df33aef4350e36be45204dcc6066f35fa406039d9ca66f00123a31fa7659d6dfb7a506ddcd43fa2434d22830282f76613ee35c36122a2cfcfd6bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff644ae27fb2131bbe69749878ca427c23f0619613aa90e17c2b22e2a76fc397966ed39df72b1b8dd446ac582ac132955f3deecfd8176c8d4f279162992b8ff954c03eb5a5e79f7003e9743036de3e4794dae5236a16bb8515ef8e25dddb0cc96600000000000000000000000000000000000000000000000000000000000000000e6dff3e4c52c8c7736c645348e898fd4f4ddbc7ff00bb73d488a1c030d37d54000000000000000000000000000000000000000000000000000000000000000084b14accb769af52b16713af4ec9846635a9c611446103d32ac9b3c6ab16c3adffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61a02d51c32c7f9d4fe7f399ec07cd0f3ba353479c3c15c0a87097ff48c4caf00000000000000000000000000000000000000000000000000000000000000000ad32c00abd55cf610b89dfbfcd4f29dc4bfebcd6d66065d13b22b92f3ad0527379768a3d820e347636f13e321b2ad2c9ad5599e83e03583b2fa761f782de4404751d656e1cc9cf447660c0cb44ac96c4e63cfe9f0ee87756335259cdc4c034df321007715711022e43f721812cd9efa1d07c9b3512248a9f944cf27d024542b0000000000000000000000000000000000000000000000000000000000000000071f9b5aca7b9043b9a7a87c56c7374088a1a5ae564ab0ae71df1152621bb00f2573e89a7fc58b722b567ceba9cbdf4568d01f20059b5f0d67ce2f02a5c26d2f6f32d341ee92e5ddc5efe0ba8b7aa3dc71aef00afe9787130cd0221fd19c8b7ee2a5762b49563e18585c6edc15ab23e8a72508b05dee38b5f51d6c972631186d58395cb0e36c38f2285f1e6c301c32b78bbf79b1f4a8f3d92a6a11ffd15be7ffecc86cece7401ad4ed0bf21ab49b443d1e16320b275500e520ba1dccc99771a56048d46b8b7365efdfe5cf88d9c0ffc3fea4797d122aea191bdfce588c8554fdccef95f09527f0681a9d581e220e0bfbfcc9ccd6ecb8e28e08a1575f3dbe0731700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0b14817ff235fe92c1a6562a7b2290e5ed6d95310a63277990576053be34f1d8da9bb2465ff85d048d65d212d740ad94c8db8b0670b3c282fcca8a1637381b8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff36804768f0736ff1a653ceccc7fdafa2244398fb3528fbaf22acf3b699cc49e359d02ebf3d32d8b15334b9dbfe5523163c5b5ebb1cc7eb05bc6dbf88b98fa101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff47dca9acdb92211f9e7dc4b057b9dce286a552926821c4f5b0fbe794a80bd20ba990edd6a246b95d2411447466b2e2ccc1589c8e153fce8f160db98ef9b2e105c360afae5455111e55f3716f0a6afb5af6605025be25d40a7048db97134ff9e545bf7d344599742b95a76595bf0a647cbfd58e3cc32b7e7ed09e55f82d7b9ccfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff63407cbe1bee091ee8256cb65a3009db4a9a7b0f6712b8071cd5f05bfef9d60236f916c2ebbbc5ad701920af5c7f3ec01a1176574a2b39938ef1f295b91758d015aefde4a6e712e45ce4dda43fd681c7e831aba25743f9c9fafbd98364fdb7c6b89eed55165851ca85176e686c4d82f029dd4fc961daf96804887b653ee23e34638ac68efbff837bdbb9b534401511b9069e69b7a2a12cf78d1f52a26e098cbc6c8d3a4b41955c65bb497c551e6cc1b8a57f839221d25bcf5e7acb0f997ad99ede3099588d6f1a2bd3476a897297c8bd479166d11e15b1fea505fe8427bb8fbc3a94eb37abe20387b3e0fb8637712d3bd65b08e562916a74eff73a16871fe3bc54a8010e3afc091f48296c48c7abb69ee8236f7d2bb6e655c9dba605afb329c6b32176f5e7041c438b2b05d4596d53a42c830fee890fbfbdaa66edeabc98ecb8600706dbcd1b497cdc739d3c7bf16f0b1aa967cbb59504da18175a9854139217140a43e4428e9659648f0fff6f037f9b5dbfd2da8f615910499ded9a2c50179b", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/e31f0de61f44c1cdc4d261d497cf718662ce97d4 b/txscript/data/taproot-ref/e31f0de61f44c1cdc4d261d497cf718662ce97d4 new file mode 100644 index 0000000000..a00418cdbe --- /dev/null +++ b/txscript/data/taproot-ref/e31f0de61f44c1cdc4d261d497cf718662ce97d4 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb8000000002b0429fb020c692500000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758f03a40", "prevouts": ["610d2700000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "b67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3bc00f369fc994f47536ced64d5e4f722a68c2ed1128957c24de4b5158af0ec621d9a3f11774810afeba87c9188100d693899e640a37210c96e3be6a00ac01d4"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e848df663f65f0e27b2d1567423d7462b229bee90dcacba8c1bf1c1a66aca7f6821d9a3f11774810afeba87c9188100d693899e640a37210c96e3be6a00ac01d4"]}}, diff --git a/txscript/data/taproot-ref/e3201e6cef5abb4e32884e254d83db6c48c0c98e b/txscript/data/taproot-ref/e3201e6cef5abb4e32884e254d83db6c48c0c98e new file mode 100644 index 0000000000..529582764b --- /dev/null +++ b/txscript/data/taproot-ref/e3201e6cef5abb4e32884e254d83db6c48c0c98e @@ -0,0 +1 @@ +{"tx": "ad9cd02d0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270920000000053c5d9ebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b30000000008440aebf0409af2f00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487cb000000", "prevouts": ["15f4120000000000225120571bc713e1a1d58bc4a7da330f9b17653bffa646093e5f5e3088fb48bff87491", "d2071f0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ca7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93602a88ba31ed3d41248d257786b5634ab0e5c1afbee5cd3bd44dcce92371e3b6ce4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8bfe61acb5630f372e1ed5eec342882068788aa3656bac92c2951e857c300141b065bfcb7199ff8296c5f7d41f3b2c6067d88c0a33f2878328c609d56cc191f12"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab5bafd7c1f93de46b79074fd81f9b2e5cf089f85eea866c1ed233ec2c502c77e3449c69d4dd26d8f08d0fe98a8e8c1c38138c07c2a650710c465fa6c38a97e3ce21dc20c2e8df5336572f81421322a354c6d32fb525b1159d1e49b1e9404bf5"]}}, diff --git a/txscript/data/taproot-ref/e3588db1c621c20dd15839f0a47a91d2b3a7c779 b/txscript/data/taproot-ref/e3588db1c621c20dd15839f0a47a91d2b3a7c779 new file mode 100644 index 0000000000..172bcfaca2 --- /dev/null +++ b/txscript/data/taproot-ref/e3588db1c621c20dd15839f0a47a91d2b3a7c779 @@ -0,0 +1 @@ +{"tx": "abcdc84802dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2300000000aef782f1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7f000000006a9856a70490143e0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914719f78084af863e000acd618ba76df97972236898704010000", "prevouts": ["dd33220000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "a0951e000000000022512051ad98b74eb9bb69aea595719e60a4b6c63bb1a22877115ad0df464229651088"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902fedd680285214298911720ea086f10cc79f987583addf2911375bd8024287541a1448e26a144f03af5db908309e4f116a413d39ee3dd1a900a336252fe40e2e9bc24811782ce338d9c98743a2cbccfc6c5a393dfe2140c007934a639f8ede25f164238fc43d62ccb9e2992cc8e5c5a5af01008bf2453cfbbc130db1970d6a1fb0bebbe8ae45eb100ea03981e5ee5d74d045d5e3bdcabf510442864f9de07134a74efbf408b0066c39a5fad284c2057c425ca415e15629aae9002b637a934f07668799d861f841e531c791e155f5ccd3f1258e025ad973cb5df69655c9594bef86ef29d0712609f98430c2fdae9fab3bd2d649ebc79a82ab5bb5ecc3ebcf4274ed600653ca8c41332e092844ec86b755ba6e6334aab62a5250982558c6390a64ab7aca27258b3eced2086c37bb26d4e7df0246adaef9c0323885e6fb51003ebb78d29c2f59e735e2dcd1e94a34fb6843af3cb7ed12dde16b5563e37e4132eb42522ef331a308a1025861060387966efe19efefb4da3db2cd671ddcd6f32a23cd1578b332ee8ad9b97c56a6f678badfea004399978d23da3c0fe7a137d798a7ab6bd70e20be62e6f59bc5caf1b0092264a9a24d6c0c258d7848b002c276280bc50faa2b322b95ede4a236b2d4c4e6b5954a4381559faddde157ec14303c175646791ffbb32a6899588f288704a9cd05c89a9bc833681f46b5385ceb62e18cacd8aab1cb335102540fd7775d8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b842f99ea244c665df26628cb4bbdbb47487c1eabb2046fab742bacaeedea65833cf35ac099042702f37424b07b91f05c9425e6e1d18ffa37c0a546b69cafd337007ac6d9f1365651a4d55e6df0dcb109d268cc6c386b355a4997173bc95c886"]}, "failure": {"scriptSig": "", "witness": ["4d0902173173196458f600957f1ad598578320c270d324d15ed40c256015face8b7476ff26442cbf133db0f2a3f83b369b6d68178ee9e21d95d246050dddd1019f4ec3f8cb32192ad0054bf2b3877db0479f80702afb6b562a744ac2828f0f044c3de5abc5001359b2b1b5c62e7fa13d375e33a649a8818bd4873ce23071dac29484c0fdef2475e033f7afd5b0c87e98694c9380172836aa95eb2a65b9d54d3f814d4c4691eacb4bf2b7fcc8b36f20f449940de5e882b0b8d2614a209de7fa223fd94fe5b5c562468c076563cbe25429935cd01a032345b52506a2ee2144bb9ac3c4c90511e1329fae67d842cd218cec63b175ce578ec2d8782cf71048c593c4678dfa9e66d45451d8cb74c99c94d7790b74c56417c62b651da353e15636fa48fb5b4a3e974ae1ad02a771a7f5907569988e56f483326b3a0eb8fd362a74b6c3882ce617db635ff39394dd77f1838b51fb65f6710f0a5301c9d68ebe6ca6aa6d21632de5a6e20319af1edc5bae1d290de271949eed71bfdeb089eabdebb7e778fa2863fdf0ca7c02efbdb14651f6f4bf8e1e5b566bc0e21ede4ed513ada769ce7d49b7caab3769a6752db202ba14aac07d817cfc9a67cd7a881891801e39bc59aff5d759453300f1a618e843d38db301a6dc4ac4ddf4c9a7477328dc2242f62d9e0e78694bb95e96fa5c472f4d419c967db3c466be72f2aab141a7c64dfcfe9ea56c70a154edc41a805c76607561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bfe9fe1aabc74f583e9b16d04818af537700e25fe268cab74fc74f0ecdec5c0c908709641cf32dc4788f906f7e3621a0528df09509ddf1e9982e4479aa4b5d9a6e41ed285c226ab336f92f35d989a379104ed593ec3ff802714cc8e85daf0b3be26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}}, diff --git a/txscript/data/taproot-ref/e35adac42c2fa3fac81b5b56415001d9ef213aa9 b/txscript/data/taproot-ref/e35adac42c2fa3fac81b5b56415001d9ef213aa9 new file mode 100644 index 0000000000..2f26f91837 --- /dev/null +++ b/txscript/data/taproot-ref/e35adac42c2fa3fac81b5b56415001d9ef213aa9 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706101000000587c2fe78bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c428010000007d05a6b102dfca430000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac31718742", "prevouts": ["d4c011000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "f5ed340000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "", "witness": ["3044022001d242d79af56e82790a35cabb034cb4620012c4c2b71802b81ce194276bdbc6022034a598a1f6a01f6e21201ae38684321c3f4d721d8ad9132ef00b81937ece3d0902", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "", "witness": ["30440220594c794d944be222fa18971f80be7d6f317a6a8d098db0a8588bba4de170d60f02203142f36632a7057f912086eaf61f7e22470311cf09cdc466e68125e8c7c81cb602", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/e36c31c772e822a277d29a41f45a505e97121618 b/txscript/data/taproot-ref/e36c31c772e822a277d29a41f45a505e97121618 new file mode 100644 index 0000000000..c67e0f4e25 --- /dev/null +++ b/txscript/data/taproot-ref/e36c31c772e822a277d29a41f45a505e97121618 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0102000000461e5b9c8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a5000000003a7310c4024533a8000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487eabc5253", "prevouts": ["a46675000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "4386340000000000225120997d8f010f68a117b9644ba05425738241c47f04463545c88006dd06ca2c16fc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/pk_codesep", "final": true, "success": {"scriptSig": "", "witness": ["c208d8f6cfebd1d11aa78e93527acaa8fc1cb4839be6ea139939100422019850954bd45d21b8eee6fcee480987eb2d737f581c7a5fe0040436175d0fb3528eb602", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20acab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ec9922274474f414215b9a6cbe20bd673e018c9fd10f6b8f0738c7388433633"]}, "failure": {"scriptSig": "", "witness": ["2a2d911382801beba1b7f099b56b63e3553173074cbf37af82ac6d6aa5607708ebce7224de1113b8c841aced42773c0da5d9f9ace310006f47ef08aeff9f2dfa81", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20acab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ec9922274474f414215b9a6cbe20bd673e018c9fd10f6b8f0738c7388433633"]}}, diff --git a/txscript/data/taproot-ref/e37bd80d8483f80595f8de680651a88967e6b765 b/txscript/data/taproot-ref/e37bd80d8483f80595f8de680651a88967e6b765 new file mode 100644 index 0000000000..22cba05303 --- /dev/null +++ b/txscript/data/taproot-ref/e37bd80d8483f80595f8de680651a88967e6b765 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b550000000085442cebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8301000000993071c6049f014a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c8000000", "prevouts": ["9ec324000000000017a914f5a65ca4534ef3ca5833434c0dd44a3e128f499587", "f67527000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "final": true, "success": {"scriptSig": "", "witness": ["ce4de256d45582b670a4c1239812adc50b8390a19555a28771c44c39ddbc9e48d8c51b601472ea40be046eee3e3d60fbfdb8443327969b51457f5013bb126d3701"]}, "failure": {"scriptSig": "", "witness": ["3500b4be1bee9f95f9a302c177ec0d9aacdb67032ac0b8f0a6e776e6f0f07277da13f209756779cf5c8a2faadd8d57e4d1a08889aaae5e620bb9146da2cf444e01"]}}, diff --git a/txscript/data/taproot-ref/e385046269e21e18e9615b10675db2b779814ea6 b/txscript/data/taproot-ref/e385046269e21e18e9615b10675db2b779814ea6 new file mode 100644 index 0000000000..92f30f9b23 --- /dev/null +++ b/txscript/data/taproot-ref/e385046269e21e18e9615b10675db2b779814ea6 @@ -0,0 +1 @@ +{"tx": "feb46ba5038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45901000000d71bd59f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4be010000004e14988560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a7010000008348decf04584a79000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df979722368987a5c20248", "prevouts": ["41353600000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac", "744c360000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "28650e00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "b47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936258544fd2f36a8de2d2245a51d08c72c32ca668da38c73d56f207266764d588feb712e9c877d580eafa00acbc739496391db115356dec5d41c0ac008be904b5898ae4fb28ba039f9030001532aa52d54afebb8b1d186c7283d6707334cdf0cf3"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082f8e322f728f7f2bda8f14cbbb71f9286e41438f49abc55856c1a694b654384417e736a60655dc533a38837433a3a305c9a2d5b0314030c91796018120c3e9a44"]}}, diff --git a/txscript/data/taproot-ref/e3cb84cf87cf0a5a0e394a62331f15e54cde54f5 b/txscript/data/taproot-ref/e3cb84cf87cf0a5a0e394a62331f15e54cde54f5 new file mode 100644 index 0000000000..9f7fc42812 --- /dev/null +++ b/txscript/data/taproot-ref/e3cb84cf87cf0a5a0e394a62331f15e54cde54f5 @@ -0,0 +1 @@ +{"tx": "2bba28450160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f3010000004fa5d0840202ee0c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac49000000", "prevouts": ["25880f0000000000215d1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["8b73e459b89a1d7a6b88e5dcd2cb404d25a635453075b8226871cb5f22c54414eb1214c006685a6b83d7048a59fb5a2969fedfe791fc3d4331e98c48e2a3fc3f"]}}, diff --git a/txscript/data/taproot-ref/e3e431ac9b495d6b12f584909dd0891e732ef378 b/txscript/data/taproot-ref/e3e431ac9b495d6b12f584909dd0891e732ef378 new file mode 100644 index 0000000000..c4e3471e0c --- /dev/null +++ b/txscript/data/taproot-ref/e3e431ac9b495d6b12f584909dd0891e732ef378 @@ -0,0 +1 @@ +{"tx": "e8d0e7300260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127071000000007a5fcead60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705801000000c2c69bd103096b2000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487b8556127", "prevouts": ["487a12000000000022512001f97817fc806a0f47072a55dae4866d18cdd8ca9234fe6851c34258ebf487c5", "e3b0100000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c9c968f9ba5683eb348a293824f936ba4aeab271178d077d8ae451d14797c79222d5ed5700e388fb215a3094328c95f7fb8c0abd1c53ca3ddf4f6d104c5d7ca1d6d3ab3f84dcdbc85d8f5796c1007b8de7ebec0ac109a6c154a12806951c54ff53fd942639f8cfddfa6b5c7d3e587f19a72de0735c456d43455d9227be6160d7d51cf84dec7373b20d8dff64470f8825bcf7a34b731edcfcaab5cd3527926e19048eff542861d21764d3a7d60b7055cb763b9e71d8a9b15a5f7816be2c84fa6d7957487878e06ce9b558a90e7ba780e3c6b77f6c5cca4984377806306df92586eb63ef5a88dcb01c0577640ceeda630459a2e96d36108e9a5631b935af8244919e7ebc5e420f037e17cc9851b95c9aa23cc94855e5257466ccc2e3898ecc7f59ce29ca9fc25d7826cf6af6046a773cd48f41c5ce6a759ecd21e203f4ad8087f456ef3dd527f31f92cd689a30a1bd4d577ef202e5eb071d633e809b19c6d79e76613882ab7fd9c4aade2c7af7ac0f9912b8e04241827ffb0d3d28d9a1fb964a108cc0c3cd93c2bb66ec1c3672b8866ffd3942ea203761b76b7ef45fefb49d0d1e0e0b0cc7abba5ec4f6dc96eb0ca68a09348c9aec4234c7b428a1cfb9cdc45cbe479b8c418aea752f7c7d0f59210b329e7521454940693c821ffc617b7a5373fe53042ac45c569c272c3ab27261c71876396358482a9908e08ff06912fcfce2f30a0129cd58655981a175", "837d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b2b6f8ce03da5bdf49a66edb45495bfdc91333d4a04a6613bbe19192007d3d876294a5d2648496e5016f850eddfdf01467fe69221e8567db6ec356a8117d8a748163db171dbfcbf374971659a5a65d0378eae0ee15db360ca8cf80a8c2e13046"]}, "failure": {"scriptSig": "", "witness": ["4d09022d1561713753fea5caeb9249549182ca03c636e9461d9b0323932c15ccfeee04988a3ce896f53eedfec4b9fcbd3576f92f688c7cded1d5b1c30dda1df445daac9d3fc376e6ce5b2353313d56025c9202544107727d0e30bbf04085d5582f344bd8c8dd145611dd50d0ef23dc0c0de4dcc8d11e302364f31301605471a3efd8ee421d884ae01d30aee5eb87c42356941b111fd28fa08cfd0689aa6260cf539626ed8134e3844d07c75ee0f6055b0c878595064c23ae2362343ff6c702963a2039302ec2aadb1e8d979710224c17a7129c49ba68c485b6ce7e5132be3110fb2d88fc7c3aa6b4c8f9895c6be2847c75656885e1ff6b697a4b16fb612927ccae55c3148d621fd9a029fcfa2220d0b422f23a488393d0c1be154890d3958088d2a4d8d51832488046954044b3436d950683bb980b7a9b5bafb2ef19f3441c9a342ef2522109af52e6fc59377d0a931d479adbb836283b1f615c76b645c5aac05dc73a49fae0680eee3c9c45ce5afb0d40e52395564b525c751b4eadd986720f7bcdabbc6c75a5922f00b27186554838a76a01140a4ff0831cd6f55d97989ad81cb398265042cd92f132f7b1e3a122ec0992212ea276eeaca7f43a26207fdac60c452a6583d7006821ba3edba5cd3b8d2cc568b4296fc307b7a7f24777499b25d56750be6781a18b9885087b86f560395a2bc59687a0c8a4ec41e283946738a288ce230cb956bbd51be1187575", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08209d3f278379d69ec93b9031f683f10c8ab57e2d08c050c4811cb81bd332eb9e3ff15e37d03bf407745d47da370f693bba1bd1439d95d9059575aa23ebc3ce6e3"]}}, diff --git a/txscript/data/taproot-ref/e3e86951be6edc4911741f8779b8b81f8e19669e b/txscript/data/taproot-ref/e3e86951be6edc4911741f8779b8b81f8e19669e new file mode 100644 index 0000000000..3e8d4ce2c6 --- /dev/null +++ b/txscript/data/taproot-ref/e3e86951be6edc4911741f8779b8b81f8e19669e @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc200000000f7b7a2a260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700e00000000e4710aa80255ee7400000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca0000000", "prevouts": ["07906300000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428", "db0f130000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_68", "final": true, "success": {"scriptSig": "", "witness": ["317a4a103b58c27d45baf7c2345a56d485f935e67341ff7860080d48fc6c612ab3e7403e0969f416469c26e125fe7f84f10ada2b55715b4ef00569d0aeda4dc501"]}, "failure": {"scriptSig": "", "witness": ["e9e95c398878e7c153910b7372b1eeed9e33a6a35139d9c23ab6ce95bc61c3935e0b522c7c1ebd7f1f56082fcde31fd7bb0960496b7e3b76777b4ebd1a9de57c68"]}}, diff --git a/txscript/data/taproot-ref/e3ee89b296eda3cdf6b73af88989c9879d826a5c b/txscript/data/taproot-ref/e3ee89b296eda3cdf6b73af88989c9879d826a5c new file mode 100644 index 0000000000..072fc1714a --- /dev/null +++ b/txscript/data/taproot-ref/e3ee89b296eda3cdf6b73af88989c9879d826a5c @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40502000000389ef4cfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cee01000000e0711392020eb285000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796e55e102f", "prevouts": ["67343e0000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2", "df294a00000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "compat/nocsa", "success": {"scriptSig": "", "witness": ["304502210092edd3ee6aa58f60c85c28ab19899569f84427455e953a6067d0c7be58c03a9b022024e4be6cb369ffe36d3e1a170f088e65ce99764c3d18d9676ac8be7956f78789b4", "", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}, "failure": {"scriptSig": "", "witness": ["30440220391263d7f642df701bbcdeb9507c7984c17558e293cdde994791b453888a7d910220678b14a06f1aa80274dbb0bc4ba4782adbeb0d27647d0f470d2c2ed989f52ea7b4", "01", "635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68"]}}, diff --git a/txscript/data/taproot-ref/e43e0f4dd6d04ff5cb7feb566ac7effde65eabaf b/txscript/data/taproot-ref/e43e0f4dd6d04ff5cb7feb566ac7effde65eabaf new file mode 100644 index 0000000000..108ce2c4a4 --- /dev/null +++ b/txscript/data/taproot-ref/e43e0f4dd6d04ff5cb7feb566ac7effde65eabaf @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f20100000037a88ef660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701a02000000b0c706bd0158741900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac4f8a5b2c", "prevouts": ["00a53b0000000000225120cc81d141bd4bdeba62b4e9a08040837dfb25b01ce96f0a5c25fe4ac81b625b74", "ac790e0000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c5215006313e029bf4eb62de3a0d4c6426daac8c531925f7b139c5f1723992229e67b015cd7b874bc075cd8f51008581fc4dcb4842056c029414218bc5a2feea4e1a1df3005c486d02b3b61ec29a3ead78a560e6676b99d8231bc4c29d368d9dca55106a340450f53ec45ed7b5d4071e79002f361b58580dc2466fe9efe2cba7b0bcb5b129bb00b4193c52d316e696f5ab59e4483b71c971a53f07dcdc22de9facbc3f066badcd574f0881f135a18144d897a16541570b87091f3d47cf5926be2ece685dc95e9e271f98062588b23ba81a90f823bbdbf466a963b10e9497e247904cb1cc4b54a4f8e68049e986f75d87dee8bcb611665e159271f6a697112d67275f8876920fd14d255b900753bbd34b8f2a6902ef047de948fc0884487818dbfbc4b88070c7efba56867ca33e52e8a29a2b999d37560bc034a3777da508f05cf56d69f9969990db70f9842f789c55c1324a8723cdbdca5414db759c77f160a345a6e272ab11ca860aab60327b83a22f27365645dde14434d19fa3f3addb88de5cf5defc398a1ee50f8926088b018723eee2ddd5cf5225cab49f6824c923b02829a5b163add1d099d6676a11624693b453045079aef57d1ad91f45ab9a8ced1d4cd6d759a49fd0fbdbee5378a96c8f80d5511fbe9c909c2daa187e8ccaba2231f06c88aedd700e92af11d81847a9190a579bb636255414e15fc2357a08a28d038a2d18a25e396138bf75", "f37d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a2e17bb353b396a85b82cbbb125d8a12b9798e1795cafa1972a041833c1bc52e4c9f6a777e87112c04511ef8a291d390ec48b54e57ed7e78d9086ead135876e880eaa4a5149b34d26f0437dfc3cc15f8b829f232fb4e000d97f0d76bcdb6c884"]}, "failure": {"scriptSig": "", "witness": ["4d0902e3fe184f2a584656cfe013e8b8d9bab901a7882e6c01e4909c59da879f52259175469cd16c2ae4cdbf13f2128b40b98307aacad74d63ee814384acf19f90c3889d2b3f09221a91db4510360db5e17103575797f76fd6314372944a728f5ab3c810963aaa4a98fbda7314777e340d0e0de988c76fae34af0b3e8091dc749110206fe334be37a1170de5dae87800eadc17d27d08164aae335a6c40fb101017ee2b8b3e0c0ea07e252b8c4f621814aa8d9d1a7fec447e8b2c9c4d469ab80b6d8022e2ff6495e926fa72521572643ecb402c43e5cf6e5012cc14f621bc3843d0f9568b635b8dea92cddbc30e54ca332010674402743c50d9c9b8cfa8971b00337701bdee793d48e1d32da8425aad74e23580700dbc1eaf20553468f294dfd47085c667d2cf184767e487163114c9a8959eb3d7edcc536ff000692ec48989012c6c770e5aee575ed68fe3838163abea4fc898e8c233c32003ad218b205313be65e4b0802ce610f45eb9864331d42b9db88b26e9479f911e8c13d8473514c711590b876a2efdfc3a658a6baf6bd6b7a50c95a88c70a93a9495c7fbc6aa7030ff8371ac24ec1f2da075d0bc04cca17e30b20b640962744eabbe565e03d4698e9d5af66cc2f2d7cd79ae87f03c3a42151c803ee0cd74f675935282e8982ee0a1d47163fef3157ce9bffdc6f89699563365092c7d95aa1e87242e43243f2f5e1fb1f4dc19f77cfa33bed98054b875", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364de51b04e37785a51f8e3fff41f769838c27cc7008169d15b9197fc58a3b6e093f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cfa000ce8b9790c39a5d5a4e1f475bb1ef714fb8e08d79945cb39f042227236d80eaa4a5149b34d26f0437dfc3cc15f8b829f232fb4e000d97f0d76bcdb6c884"]}}, diff --git a/txscript/data/taproot-ref/e4400ed471cfae79f01e699c1535a927cd7db111 b/txscript/data/taproot-ref/e4400ed471cfae79f01e699c1535a927cd7db111 new file mode 100644 index 0000000000..4d64df14fd --- /dev/null +++ b/txscript/data/taproot-ref/e4400ed471cfae79f01e699c1535a927cd7db111 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf9010000001645c582dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1802000000937c02e50338aea400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a62e010000", "prevouts": ["a5fd570000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5", "f4774e00000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "067d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367d67d1e8ddacf64724cc3740d78bc4f84845b0b5bea6009d6e539481d3db422385587f46271ff71c1a8d3d9e62b351dc1e7761b3de349b9de66c491fc83cbc116ed3422fe95872366e2174646ef4116c9fafb56aaaad9ae25dbd472ec9cd0fc1c48ffafb7a4cf249a6909d8fbff6ddfd3f500331ce755bc2f73b79afc0800987"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8f8ecbd50a1c4de67b0557ddaa829ed57a787bea0d02f899effe5611de93fd37f2e70a8b9232395faf03242e8d41e7097acd4f110215ae4f1c21e826dd60490c48ffafb7a4cf249a6909d8fbff6ddfd3f500331ce755bc2f73b79afc0800987"]}}, diff --git a/txscript/data/taproot-ref/e4403314230ec5266c263c14b3167d0495467abb b/txscript/data/taproot-ref/e4403314230ec5266c263c14b3167d0495467abb new file mode 100644 index 0000000000..fabb598110 --- /dev/null +++ b/txscript/data/taproot-ref/e4403314230ec5266c263c14b3167d0495467abb @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6d00000000774e8a9b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b1010000006be7d4170139141c000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8744020000", "prevouts": ["c81348000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "e5dd3700000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["f04c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045ad7df43f1383df9f0df0a1e0ce133acd14e2258cbe9a702da78bb61f4d1a9bc80eb43d08761fb76661299d0344fd2d8bfc7de5e7c6dc622156e95971f4b8396db5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1baf3800ace8e6c95c7e7a9d035d879049832cd6be429795a36cd3109eecab56cf0292c5c10d160f8e0745cc9e7b1222beed517475d04a852f0f3c02abb361f19b5b66a7e788d7f4d892aefa7b705b94e6e3402f32316550d3b683ba5e55fe37e"]}}, diff --git a/txscript/data/taproot-ref/e4476c9611f68d7aed1329b54ac787a7dc19d3c1 b/txscript/data/taproot-ref/e4476c9611f68d7aed1329b54ac787a7dc19d3c1 new file mode 100644 index 0000000000..38b613b57d --- /dev/null +++ b/txscript/data/taproot-ref/e4476c9611f68d7aed1329b54ac787a7dc19d3c1 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf9000000001cfa84b301032e4300000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac7d9fda3f", "prevouts": ["e64c4d0000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "8b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93694fd982e1b11b93dc03e5fdd59b6f9045cac66289faf2302448a1260c5bfab6e4d7dc2c55a7521ecc297ff7217b922438f95dd9c29c118a2bf5c9e2c8f8c84f32a50ac17afa49989b8cd5fe09550e31f987b9afab4d6ff7fb0ac42074cc4b38f"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cde8e58194ee2d9158b02514bf803786a3307a33652aec833c6f0052c5cf85f6d8095c4fc48dd4a937a2ab720b4c7b803df056a6d61c0b781e24263fdb2663252a50ac17afa49989b8cd5fe09550e31f987b9afab4d6ff7fb0ac42074cc4b38f"]}}, diff --git a/txscript/data/taproot-ref/e4549906b6821c9cfd2bdad13fcedc9f2ce44c8f b/txscript/data/taproot-ref/e4549906b6821c9cfd2bdad13fcedc9f2ce44c8f new file mode 100644 index 0000000000..b978cb6f03 --- /dev/null +++ b/txscript/data/taproot-ref/e4549906b6821c9cfd2bdad13fcedc9f2ce44c8f @@ -0,0 +1 @@ +{"tx": "01000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46e01000000aca912a00381e13900000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac82010000", "prevouts": ["a8e93b000000000017a91437a5c76a04bb604ad99785877003310ab74c7e2b87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "165c142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["80b334005ae104106759e292d674d3c28f902644005e258094b870c5c188475a4d383eebf6d0674734689ed679337c48c7e9e5b3670c4a14848905637136d946", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/e46150bc653c31e407e6428aa1a6ebf50bf84aea b/txscript/data/taproot-ref/e46150bc653c31e407e6428aa1a6ebf50bf84aea new file mode 100644 index 0000000000..e9050e74a6 --- /dev/null +++ b/txscript/data/taproot-ref/e46150bc653c31e407e6428aa1a6ebf50bf84aea @@ -0,0 +1 @@ +{"tx": "f66b5ce4038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c465000000005be9d6eedceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc300000000394663ffdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c08020000000e1b4af6047d16af000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a62067231f", "prevouts": ["3e80410000000000225120783dfb3310d474c767ef9239befe26bff1665135289516e5417abb1737338f98", "172323000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "8d5d4c000000000017a9141757f4686f091b43a46fa47e92d07c87fc7a205e87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_3", "success": {"scriptSig": "", "witness": ["837a68045efd193f0eb98ca50d563125d43cff74e3c8c6993f43e21667b07e47cc0c5f992a02db219e1e3c03868efd69627b67b71a0f123ce6455bc5a05df79d01", "456e0e62f9289faf12d8e11aee380df2533753c3927854b1e1321c9ff057df6551384b8ae66513bc066eb9275264d9cf0a4d2d1b1575b79ef2cb29159b7b8a0491af222b67bffda905921df2f95a3c286ee992a87d57b4d447f8ee8a7e67969ad490d8f4847c62e3ae5e0e10b6131bec9dcbaf49427c4defa69f0e12795793e55f0ae087d32680c944c36b3a1a7833d518f5e70149b9c9527a0d", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c76cefb21a62104116911d8e8b2e45a18b2b96bc39350390a3dc53de4d7433000000000000000000000000000000000000000000000000000000000000000063d1162584884dbb484b96d1ed4ce4a0512e9716da39c30918608fb6f95bb2c400000000000000000000000000000000000000000000000000000000000000007272812a8889423cb2003a913d32f365c6d35c633594956d5a9cc90b17ca754ac922743679a5a6af278245238d6037175a7256ad00ffbf996a910ea41a7610511fd163d9c8018e5282f21786763a4c52ced4820abfeb403b0b1d7fa7bde30aa139f8ac87943424ef90f5364034d8a7a26fc904027381798e6672c9d1936f41d70000000000000000000000000000000000000000000000000000000000000000105d0ae378ff1b6f0fa719acd7567a35003274abc0d03dfa689f7e95b6df185cabef40480030bfa6b896c61fc6ab80d156e2156d028bac1f1f329a98ee46486d723ba82ec9188bab38613f5640a54fe3d3e7ed44ecc46fb288a21d330e6567a9f8b0768f17293d87e4ae3a232d31846bee1650f75b19c2a43b567cde0e7cfedbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015fc8b4e5af59d5edc2e4cf6be0818a13031d25cb9314ed8998d05c9cf9daf778327c59652234f3b0f296f92c0ebab6d2ef46ce54921b25a9f796c10c849f301ea03ca4f88fb6350e9feab730d33f323a2394c1f5dfc7b9e461a2eaa76eeb264ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed71b9a2736a87d63a4ca2ffa70dec04b8d71a924a48cafbc763ba6e1b0451a5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93816283a2c90c6d10a38061255b862e01577a0aa3eedaa665d8d20a43f1f74f828ac67de897d9bd1366af382045d9cb5797e4e6bc32c8b9ec3c9f5409dfb3fc20060d514f2b33562929bff48ddb4def570ab6a586533f3c1e41e334d3bd092c2ee6a87b947424e4cae845652366f0676c63850638a8d7ca63c4488ff4877408e608068cbc48255ea77105456f8969fb5dd36568aa4bc87035ee2cae1d30427acf63a0460e3135d3368beb2008f7310ad4143e8e5f370736a23446973f3f334c3ca209e6ec3c56f25e2dabfbf555248f02682ab46318b9bbf2da715a12a2b2bf9999705e46af7c358b8ba60d80b4508a8c9729639522f6f63c83c2a34606c8b094d807c24f0d2b08c9b8232bda7b6e3087fd0203bf7f39947db5d25a3f8e6f75246f0d608eaad49446ff6b5b1b9926953d3d883734e979f05038afe526de750ba72fc5d944722c8e9426ab6d57685ee28c2fe526dca1ecba98eea3cbd008295bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000052e3496d6cbc35d102a166e3843d452442a07a0a4683064f6ae0bc1615cd43da11ddab6ebb387dfd7492ec96dbed8283eba9ad068a1aea18c111af22641b5067cf80a56e18218d8ac219d18a141ee4d9fc814d478139d60a5c964e9d08a884073eb6a973dc07fe6fa35dc99d39bacabfd586f0b9398b3c1fd154587b5c3b48f60000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6930f03d4ec7b261c172e4c2de02c038f1f230c95d821038c10fae578ee20b27814b8f6e76637ecaa9724e004e9b7ecff1ccb2a630f559c053260a9b7f06768d20aabc63cfba2703eefc30c4b61979f6687ac7e66014a751fd7ac847906810b54ab005d2ab3d381b1bde5ff1c4d0503824cce1d347ab7ba95e12c9812c2c7bd771eb468ebe3c1ff4b22f9ae8563970f7c9208d2a57c3bd5fd8fe188feb76ef7b483b54318337e0bbe16b685dc49cf5d4dba35cd4fa202c7740447b41dd988cece00bb2acebcf172fa7e5c0535296e8daa79167a7f2aae6bd54c3f86b0caf53785baa30d0f3a9b6354c0e96a550a4a59b52b66ac51c6518574b6a2d37aaf5fa77ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00749959ccb6776715d0a7f8e958f9ad8de11205e38827aae38a8700cbd6ffd9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4d1f0778be7e7bf68fbc278adc13515356a7886375ae569c6d601af68aa4f07608d91ded0e41e98d5b81f401676e1ef23541a78ef2e9f460861d5716b482f8f00000000000000000000000000000000000000000000000000000000000000003c3e3a26d225dc69e41910d4af8ca5636f765bdbf9ab00c5be8e82099baa8caa206f85846ef59ecaf3883eff6a46b3dcd02ac966bfb5bc3deec6e032efa01933ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000005e9fc283d0edbbda40a787148720e8c002fd283713cac16a390569aedd312910f6b4d7afde0ef1ad599e16d159c21c3a5749d510b625adf48d88503247e62ea9", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["837a68045efd193f0eb98ca50d563125d43cff74e3c8c6993f43e21667b07e47cc0c5f992a02db219e1e3c03868efd69627b67b71a0f123ce6455bc5a05df79d01", "de9d790e2b77dfd852c61699aec17f9c4f439cfaaeb4b321b377976ef72f80b123427abe65e164a8c136982d21905c11034db1f08f74707ded1d5c3e4e3d78e5b18ac37c0aeccf67f600e669909fe39ea8e197f99f9d177e0acd3a0e50311f9c0eba4c6ec701c39ef6ba2f9b2389512b150a7df1d08acbaf360a344c89ebda9fa611d18b9a0776e902271bff0f7010b6e9cf80c422a6a0641e", "7520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e205163676e567cba5788686ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead6ead587cba5987", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff05c76cefb21a62104116911d8e8b2e45a18b2b96bc39350390a3dc53de4d7433000000000000000000000000000000000000000000000000000000000000000063d1162584884dbb484b96d1ed4ce4a0512e9716da39c30918608fb6f95bb2c400000000000000000000000000000000000000000000000000000000000000007272812a8889423cb2003a913d32f365c6d35c633594956d5a9cc90b17ca754ac922743679a5a6af278245238d6037175a7256ad00ffbf996a910ea41a7610511fd163d9c8018e5282f21786763a4c52ced4820abfeb403b0b1d7fa7bde30aa139f8ac87943424ef90f5364034d8a7a26fc904027381798e6672c9d1936f41d70000000000000000000000000000000000000000000000000000000000000000105d0ae378ff1b6f0fa719acd7567a35003274abc0d03dfa689f7e95b6df185cabef40480030bfa6b896c61fc6ab80d156e2156d028bac1f1f329a98ee46486d723ba82ec9188bab38613f5640a54fe3d3e7ed44ecc46fb288a21d330e6567a9f8b0768f17293d87e4ae3a232d31846bee1650f75b19c2a43b567cde0e7cfedbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000015fc8b4e5af59d5edc2e4cf6be0818a13031d25cb9314ed8998d05c9cf9daf778327c59652234f3b0f296f92c0ebab6d2ef46ce54921b25a9f796c10c849f301ea03ca4f88fb6350e9feab730d33f323a2394c1f5dfc7b9e461a2eaa76eeb264ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed71b9a2736a87d63a4ca2ffa70dec04b8d71a924a48cafbc763ba6e1b0451a5ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93816283a2c90c6d10a38061255b862e01577a0aa3eedaa665d8d20a43f1f74f828ac67de897d9bd1366af382045d9cb5797e4e6bc32c8b9ec3c9f5409dfb3fc20060d514f2b33562929bff48ddb4def570ab6a586533f3c1e41e334d3bd092c2ee6a87b947424e4cae845652366f0676c63850638a8d7ca63c4488ff4877408e608068cbc48255ea77105456f8969fb5dd36568aa4bc87035ee2cae1d30427acf63a0460e3135d3368beb2008f7310ad4143e8e5f370736a23446973f3f334c3ca209e6ec3c56f25e2dabfbf555248f02682ab46318b9bbf2da715a12a2b2bf9999705e46af7c358b8ba60d80b4508a8c9729639522f6f63c83c2a34606c8b094d807c24f0d2b08c9b8232bda7b6e3087fd0203bf7f39947db5d25a3f8e6f75246f0d608eaad49446ff6b5b1b9926953d3d883734e979f05038afe526de750ba72fc5d944722c8e9426ab6d57685ee28c2fe526dca1ecba98eea3cbd008295bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000052e3496d6cbc35d102a166e3843d452442a07a0a4683064f6ae0bc1615cd43da11ddab6ebb387dfd7492ec96dbed8283eba9ad068a1aea18c111af22641b5067cf80a56e18218d8ac219d18a141ee4d9fc814d478139d60a5c964e9d08a884073eb6a973dc07fe6fa35dc99d39bacabfd586f0b9398b3c1fd154587b5c3b48f60000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6930f03d4ec7b261c172e4c2de02c038f1f230c95d821038c10fae578ee20b27814b8f6e76637ecaa9724e004e9b7ecff1ccb2a630f559c053260a9b7f06768d20aabc63cfba2703eefc30c4b61979f6687ac7e66014a751fd7ac847906810b54ab005d2ab3d381b1bde5ff1c4d0503824cce1d347ab7ba95e12c9812c2c7bd771eb468ebe3c1ff4b22f9ae8563970f7c9208d2a57c3bd5fd8fe188feb76ef7b483b54318337e0bbe16b685dc49cf5d4dba35cd4fa202c7740447b41dd988cece00bb2acebcf172fa7e5c0535296e8daa79167a7f2aae6bd54c3f86b0caf53785baa30d0f3a9b6354c0e96a550a4a59b52b66ac51c6518574b6a2d37aaf5fa77ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00749959ccb6776715d0a7f8e958f9ad8de11205e38827aae38a8700cbd6ffd9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4d1f0778be7e7bf68fbc278adc13515356a7886375ae569c6d601af68aa4f07608d91ded0e41e98d5b81f401676e1ef23541a78ef2e9f460861d5716b482f8f00000000000000000000000000000000000000000000000000000000000000003c3e3a26d225dc69e41910d4af8ca5636f765bdbf9ab00c5be8e82099baa8caa206f85846ef59ecaf3883eff6a46b3dcd02ac966bfb5bc3deec6e032efa01933ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000005e9fc283d0edbbda40a787148720e8c002fd283713cac16a390569aedd312910f6b4d7afde0ef1ad599e16d159c21c3a5749d510b625adf48d88503247e62ea9", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/e4a1dbfb8711c43befec064b8fd396058b0c54af b/txscript/data/taproot-ref/e4a1dbfb8711c43befec064b8fd396058b0c54af new file mode 100644 index 0000000000..5c1cbd7396 --- /dev/null +++ b/txscript/data/taproot-ref/e4a1dbfb8711c43befec064b8fd396058b0c54af @@ -0,0 +1 @@ +{"tx": "17f2605402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc60100000098f115be60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270230100000050702df8027ffe3200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48752b40928", "prevouts": ["5c6025000000000022512040649a1fb199947d796ba41a749770af0c9b8b8f2ffad14d369b18f56746cbd7", "9a19100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082c63b209b29a3611ab6267155884a7f894b498570c9db6a86ba3046458c9f77af637f7085334bd6ace67733ad5f759fad65febfe656f63b2b30abaed1d2ea29dc9de97a2505c9a0de734aa1a6c773f3979bd21cdf34ebf80e6ce3c625c087f57a"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936832e78f2a5d9b0c4680fc7dba3a6d5673c26e47a2a412d10c5fe178db4951a94073db8fdd32dfd70cc3c0b801d057b12e5f9f3471dc2e8803f572b477b94c5e2cd8777bf679e716871b092f46e3a69645e6fd098b2f58cf3078cdf1926d6f261"]}}, diff --git a/txscript/data/taproot-ref/e4ac1ef7380b8d2111b6763169a1743b27f8990e b/txscript/data/taproot-ref/e4ac1ef7380b8d2111b6763169a1743b27f8990e new file mode 100644 index 0000000000..ab2fd7eb9e --- /dev/null +++ b/txscript/data/taproot-ref/e4ac1ef7380b8d2111b6763169a1743b27f8990e @@ -0,0 +1 @@ +{"tx": "ce0f492d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be2010000003249bdd560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c501000000dac634860214d03200000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88aca6414d55", "prevouts": ["f6a9240000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78", "23d00f00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "217d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e4f67f6e69cf51b25bdfcad90ab02b519823ccb2f4612df68d1a9a4df99984c88f488f9b2dd04714e2920653c1afab7d010d81355bbe53edbfcaebea15ff1da48"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe391bfd09479964276dd59b1d58dc35d2e52175d5fee5e0ea28559bd14655b056da9396880b08a11a17662bac4a7b382e749572eea29fa5ac5793c70e2d18ea5bb5ed745f7425de3873ba37c460c85acd2f4f50490d9d3680fc958bb85bfda6f488f9b2dd04714e2920653c1afab7d010d81355bbe53edbfcaebea15ff1da48"]}}, diff --git a/txscript/data/taproot-ref/e4be0b4404267bdc3cff4674612fa0aafae17da8 b/txscript/data/taproot-ref/e4be0b4404267bdc3cff4674612fa0aafae17da8 new file mode 100644 index 0000000000..204997173c --- /dev/null +++ b/txscript/data/taproot-ref/e4be0b4404267bdc3cff4674612fa0aafae17da8 @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf9000000005afac8d501efd4070000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963b2ee04f", "prevouts": ["82df230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_61", "final": true, "success": {"scriptSig": "", "witness": ["1da26216c5fa21de293a98697b7f3e6e24dd98e9b97695c15c1739edde291ec24824714e58e4e9f472cb3672c9bb1c6f83d4ae985e1a389fc55f599a575691bb02"]}, "failure": {"scriptSig": "", "witness": ["4b78771f6b75db27ee3b71eb66c82f7ce11a2f6207a3899336db332f998a208ee25739e1e5eacccdf2e17e07da72c1e52bd0af03b979f7a670f99099a53358f461"]}}, diff --git a/txscript/data/taproot-ref/e4ed5b23d5de1068cbbde995bd4acee64e91aa7e b/txscript/data/taproot-ref/e4ed5b23d5de1068cbbde995bd4acee64e91aa7e new file mode 100644 index 0000000000..b4e23d30d5 --- /dev/null +++ b/txscript/data/taproot-ref/e4ed5b23d5de1068cbbde995bd4acee64e91aa7e @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705100000000fbf40f81dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be10100000028107fd004ce692f000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688aceb524132", "prevouts": ["aafc0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "43d42100000000002255202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["bf12b3ce410208e8d45324bc449e14020662d67526263b8e81eb7a746fe6fcf0a151b2f58e36ed3b57ed3d1aee1ecdfd43cb0fce5e33bf3a750433f4d93c9dcb"]}}, diff --git a/txscript/data/taproot-ref/e4f857e19db4cfd96f2d5054dbf40b5a9e492dff b/txscript/data/taproot-ref/e4f857e19db4cfd96f2d5054dbf40b5a9e492dff new file mode 100644 index 0000000000..8d0636f2d9 --- /dev/null +++ b/txscript/data/taproot-ref/e4f857e19db4cfd96f2d5054dbf40b5a9e492dff @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf08010000004772068e03027a5f000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d2020000", "prevouts": ["3a8162000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f668", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361b9ac4799763e2e351da63ecca5a6348aa482c3eadd4509c967c8b6a34c76e4075ca33d7e1e5f2997f74dd285eec8a0e5cba5080c4482d5b595e9662ee4b93be0a1b6150087d660153f154c744da46b7319b80aea4f8e08f23015968f3b1d87a"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d512c1673aa1d348e5f2f8444d57c2e384a9e542f3652a57ab10bce8213eb35faa5e1f31af440bd9528b56a4b582a327979fd28cb44b9e62075e623987b4c0f8e3992fb5cf2427ede6d61c8a74b8487764d962b41d4db4b67b9e943a724e86dc0ff"]}}, diff --git a/txscript/data/taproot-ref/e4f9951077eb874d4585b5156eb27d51d2efbfd3 b/txscript/data/taproot-ref/e4f9951077eb874d4585b5156eb27d51d2efbfd3 new file mode 100644 index 0000000000..c09296d485 --- /dev/null +++ b/txscript/data/taproot-ref/e4f9951077eb874d4585b5156eb27d51d2efbfd3 @@ -0,0 +1 @@ +{"tx": "a045fd37028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c414010000002c805d92bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5f01000000eb722fc402346c99000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689873ec82e5d", "prevouts": ["2b8b380000000000225120d8440763d2116f9dee5377791731b3635bb44d7a42fb2b8a8507b8fff76ccab7", "dddb620000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "e4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f4fd06ba2b74fab4c367f8e8e0519d3d9be3851343b71a963fa32cdfd438e05528a09ca0f6d73d82e88e284042e116dab9fe2cbfafc110f6c0fbe5b2788367c646ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b24d4fab40ea135233ddc8c9f724889f007818f7ffad5749db3376d8fcf405e18faf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}}, diff --git a/txscript/data/taproot-ref/e50744f139df817035a18b49f300ba44cb0343d3 b/txscript/data/taproot-ref/e50744f139df817035a18b49f300ba44cb0343d3 new file mode 100644 index 0000000000..ef751cf6d9 --- /dev/null +++ b/txscript/data/taproot-ref/e50744f139df817035a18b49f300ba44cb0343d3 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b090200000035a3cbd1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7b00000000bba5cbc704e85a47000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796f3703632", "prevouts": ["490f2800000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "e0772100000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100a3a5a8f8f08e76ef265172a8b0ec8b18f87ebb9279f084af614732c0d539310e022049c0cee6779ea3a42951fdcc769c32767d87fcf292acdba013654415e7a41d16812102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "483045022100f34f93c9a62849fd11a5918c863019d5b8c04806102eeb1cb8cb2e6f0a57529602206b166fbf74e0fbdef8baffce8dfa2ba6efc8cfb5d9ee54622b28dc1ce98a7f5b812102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/e50e205a1d18fcdba7e8e5fcee9033cc4707f9c7 b/txscript/data/taproot-ref/e50e205a1d18fcdba7e8e5fcee9033cc4707f9c7 new file mode 100644 index 0000000000..a059c5f487 --- /dev/null +++ b/txscript/data/taproot-ref/e50e205a1d18fcdba7e8e5fcee9033cc4707f9c7 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9e010000004e8d62c98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48e00000000c08d65870131f23500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac01adfd1e", "prevouts": ["0c3422000000000022512054aab8bc8194c133af7274183a7f3060903412eb7cc1a08d3d6a62e380c86e5e", "6c6838000000000022512014ab2ce168ab85feead37e4eac5416d9445f157495b1751829a16d631c43d5c4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93602e89707d8973173175c84fc9b7dd7d6cd1c0e0172d2891381d5a5bf4c8c8577"]}, "failure": {"scriptSig": "", "witness": ["6aa6616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e52cfe3453de9b1d75444df456949cb75040b8b6 b/txscript/data/taproot-ref/e52cfe3453de9b1d75444df456949cb75040b8b6 new file mode 100644 index 0000000000..1743137d5a --- /dev/null +++ b/txscript/data/taproot-ref/e52cfe3453de9b1d75444df456949cb75040b8b6 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5c0100000075641680bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8a0000000017e471b5dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf300000000ac1340c303f3d21d01000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79694c84f5d", "prevouts": ["ad2d7f0000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b", "7d0e7e0000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6", "9da622000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "4a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936528a77605e4b8cd768848df1e60fd0b649927a7f2710fbb5502fd93c97ebecd446c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9faeebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac749e2a390543356cdb3691ba8d54627dfb45f7f1132e94c1a4e909f84f1614c2"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082696e0a39b8006d5c38246735bc900624bc412e796f8d634640137370e1472505749e2a390543356cdb3691ba8d54627dfb45f7f1132e94c1a4e909f84f1614c2"]}}, diff --git a/txscript/data/taproot-ref/e531badf585946f2d8e4ca711ad08bfab23b255d b/txscript/data/taproot-ref/e531badf585946f2d8e4ca711ad08bfab23b255d new file mode 100644 index 0000000000..c15c3d7302 --- /dev/null +++ b/txscript/data/taproot-ref/e531badf585946f2d8e4ca711ad08bfab23b255d @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5201000000c07a9ac860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703c01000000d90833cb03dc493500000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc90186125", "prevouts": ["5c76260000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "80e51000000000002200201c085867a8a36cc3b43fbed118fb6a6a2b3372fa424ec2d949bf17badd0269e3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_keypath", "final": true, "success": {"scriptSig": "", "witness": ["0e48a332b41c140e93e9e231b83c39b2237a87e263e3c1c5078ddfe3d6bff461d042642b49d4aacb0cc8a62eeeeda6c962df57b73f8e90a63ff031d35ea02abd"]}, "failure": {"scriptSig": "", "witness": ["0e48a332b41c140e93e9e231b83c39b2237a87e263e3c1c5078ddfe3d6bff461d042642b49d4aacb0cc8a62eeeeda6c962df57b73f8e90a63ff031d35ea02abd00"]}}, diff --git a/txscript/data/taproot-ref/e556fbc1cbc098965abc9f19de4e699a65701b97 b/txscript/data/taproot-ref/e556fbc1cbc098965abc9f19de4e699a65701b97 new file mode 100644 index 0000000000..e85b7098ee --- /dev/null +++ b/txscript/data/taproot-ref/e556fbc1cbc098965abc9f19de4e699a65701b97 @@ -0,0 +1 @@ +{"tx": "d505974903dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7d010000009a3a5dc3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b710000000071f6369760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f501000000c7d508ab0473fc5900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487b6000000", "prevouts": ["a02e250000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "b3ca250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d95a110000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_2d", "final": true, "success": {"scriptSig": "", "witness": ["4057160f8c6426979d7439e60ba99759a3935003a8db5b7aca3a5c86a40293a9e05787c2f446b47de87682322df79a42e7b2c8c24b4f265fef710f0f7a68931701", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["12ca3b46c2bc154a147b7ee71a8b5ea042b5deea224b0c72564a5d75a7b0ea6471512e0e7254671afda5d4a3f90e153eec8074d30706e1c8a6cdff43e353abd92d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/e5a06372794c8a0907ebcab73767cf918aac39aa b/txscript/data/taproot-ref/e5a06372794c8a0907ebcab73767cf918aac39aa new file mode 100644 index 0000000000..ed2643e923 --- /dev/null +++ b/txscript/data/taproot-ref/e5a06372794c8a0907ebcab73767cf918aac39aa @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708b000000003bc37beebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8401000000aa486e00015ea55a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1e098721", "prevouts": ["322111000000000017a91448274ba0d73ec00ce63e7922c9d87a48fd0c670f87", "d110710000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "be7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa48ad50d9ddf0b427aa1cd7e89a01799c6e7ad3b5475e2761c9fcf711fad5d46d911ebac8c921821ba74d98d656401ec4b56b2bfe8f672693a939227457b8b1a2"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d1deaf9b354b7bba504b77e6156643d72237d1ca0dc157d7f2482ea02765e9a648ad50d9ddf0b427aa1cd7e89a01799c6e7ad3b5475e2761c9fcf711fad5d46d911ebac8c921821ba74d98d656401ec4b56b2bfe8f672693a939227457b8b1a2"]}}, diff --git a/txscript/data/taproot-ref/e5c2adb3e9fbf1cd914078ec2a63b5eb9a6e3abe b/txscript/data/taproot-ref/e5c2adb3e9fbf1cd914078ec2a63b5eb9a6e3abe new file mode 100644 index 0000000000..df10ac65b5 --- /dev/null +++ b/txscript/data/taproot-ref/e5c2adb3e9fbf1cd914078ec2a63b5eb9a6e3abe @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c438000000001ea2ccb8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf180200000014118e3a013b6381000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748747a2fb1d", "prevouts": ["0dfa40000000000017a914f0ed99a28545ab2ceacee60b5537a9e5c34fcd5187", "67f27700000000002251202b6311c61a2a508a144ec510c52a71fff5d62c4fa86296d42faefa4fd619b162"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368a6d05bce1350142da4c8baa3641d62f98981f8d5be82f6cd048a62bad6f0283"]}, "failure": {"scriptSig": "", "witness": ["6a49616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e5d4d4aeaf98b811a93af7c9329c6daf9589e991 b/txscript/data/taproot-ref/e5d4d4aeaf98b811a93af7c9329c6daf9589e991 new file mode 100644 index 0000000000..7c0abaa311 --- /dev/null +++ b/txscript/data/taproot-ref/e5d4d4aeaf98b811a93af7c9329c6daf9589e991 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce00100000057728689dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb2010000003f48ebf8048c75b400000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac751fe021", "prevouts": ["016e5600000000002251201ca29abe36def88662b96aa36425514db4706e1e50a53467368d6fc22d19b945", "13e05f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "327d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363674d83ec545aed04205f6c8011bc6d879deeac8bfcd4272e2d7b511be5f791a25d31a4d328a06fbd663a9de03f4f743ae6731d946a7b64875ecbfa9fe5ecb492e4cd18b5d1ec472eec5a95c6c9d67ba3848eb933b0b41a8c6d3176a27b07997"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac0f29a0308f7dd1d25542f1a27a19e78219e8b2987efd922e316e5388ecd586b0246b7a5461d23b2ebf642f7df88e05c9d62107f66abf7b5f94d7753ce57b53620e954adb3b90d8c3597d54022d70f5af7b761a66be618c54dd56feea2be872"]}}, diff --git a/txscript/data/taproot-ref/e5d756b155e51281410e56562a664673b0c34fcd b/txscript/data/taproot-ref/e5d756b155e51281410e56562a664673b0c34fcd new file mode 100644 index 0000000000..4880599579 --- /dev/null +++ b/txscript/data/taproot-ref/e5d756b155e51281410e56562a664673b0c34fcd @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc301000000859e9063bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdc01000000d82019748bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c431000000003461614d047e0708010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e9103047", "prevouts": ["f007760000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "93d9610000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "f14b320000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "d27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0829947182c2cf442266d627de6569afbd254a849da3e2d989b935a76fec010797d33479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a9b801fc18e2353a9cd4de337bb33433fbe6225e21bb8b5572b0acaa50d11b7f3"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e800def9a487cc21401761fbf52dc8ab7b9916cdeb8a2e13a665b6447e5fe6b3009b801fc18e2353a9cd4de337bb33433fbe6225e21bb8b5572b0acaa50d11b7f3"]}}, diff --git a/txscript/data/taproot-ref/e60ac2a186190f5f41d0f98adb9107b436491c32 b/txscript/data/taproot-ref/e60ac2a186190f5f41d0f98adb9107b436491c32 new file mode 100644 index 0000000000..a1b8163959 --- /dev/null +++ b/txscript/data/taproot-ref/e60ac2a186190f5f41d0f98adb9107b436491c32 @@ -0,0 +1 @@ +{"tx": "91f42efc01dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c84000000001f7a65f003c7cb5a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914719f78084af863e000acd618ba76df97972236898726000000", "prevouts": ["c47a5c000000000017a914525ca05541c81a105639c2efb802eaf5596cfe0187"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "21521f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["69223f2e1a925dc7c5c485a09fd8f6062cc12da6766059d7d491ee86c66f018695f6f914479e07f220c6674e287fde9eabb44ee085615328446a1b09e8b1c1c2", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/e617e275740cca2c1002733c0b62505410149814 b/txscript/data/taproot-ref/e617e275740cca2c1002733c0b62505410149814 new file mode 100644 index 0000000000..0030e4c90c --- /dev/null +++ b/txscript/data/taproot-ref/e617e275740cca2c1002733c0b62505410149814 @@ -0,0 +1 @@ +{"tx": "ebb0671102dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b780000000086a4f4c3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfb01000000f9046ad00132320800000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac41935239", "prevouts": ["9e3b2000000000002251208ee514ac0f4f8afe6d51e826a65d73d8e6a6dbdc4949f433ee9013cc9ac16e8b", "fe3c270000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_83", "success": {"scriptSig": "", "witness": ["9adaa546032c13f5bd7fb396b9ed84af3a7459c050647a6330658e9fa44eb7cf97f1a3312d52caafa27d6a9e543d4aa3a3f183eb05d8fd4926126463f51458f482", "50e1b68863e2eeede36d96ad7ac37856d5df41c5724361e24ace24ce217b92c38dacfc12b9f6775dfe75b4a01ecbf3ca273e9b00a3a0091ca9e623337d4d69e596340911bc0df754c4c74472ddab49a8afac1c5c0d6f0e98320ec7baf2983a6d2ea246f654219f544de38eb16e4d4bdb05797a36d25c4147476b26578d7dffa6d6cc75232672843ac1f553401c29ca3967dfbb52ec4d2a4feea31c8af17b2a"]}, "failure": {"scriptSig": "", "witness": ["d09d0fe5ac5750cb15453c48244c0722aa5e012d919be95d80ee37b2ea9ce3523f23f78af73aa23bdba4a706cff89810c83b7a828936e1629b318ea544d682d282", "5017eed178b867748f37569b5f1d1079e76759c5d72c3505330886d9daf00a76e65ec760926e487dd2cbb63e11aacc8a49c816345da54d66ef3bdb4a5a27a939325a5ae593e6ccae"]}}, diff --git a/txscript/data/taproot-ref/e62e88a5e5a9d90dbb6072f7ccea09b105b0f310 b/txscript/data/taproot-ref/e62e88a5e5a9d90dbb6072f7ccea09b105b0f310 new file mode 100644 index 0000000000..66bcb9fbba --- /dev/null +++ b/txscript/data/taproot-ref/e62e88a5e5a9d90dbb6072f7ccea09b105b0f310 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d4010000004448e7b2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7e0100000089d641a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a0000000083a09fad0354caca000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acfa030000", "prevouts": ["5e70100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8e686e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d1414e00000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_86", "final": true, "success": {"scriptSig": "", "witness": ["5990cb2c8e00ea2a16a0f151d44f74ddc66438063a923331cfec5656dc2da5d14f77f8a988d29a40a97a327fb21ef0155a095c22a2d48f49d849b08bcf5622ae81"]}, "failure": {"scriptSig": "", "witness": ["bf447c48889e60b479e4f2c98a44a3bf4acbcf12d088f7a9af60a69414fa11d5e6b86a6d98bb1cfbe666a197f7ef485d3d6282e5ddee02f0427e63019bf51ac786"]}}, diff --git a/txscript/data/taproot-ref/e638e75f42344b0c3f6564246955fb5d040cf293 b/txscript/data/taproot-ref/e638e75f42344b0c3f6564246955fb5d040cf293 new file mode 100644 index 0000000000..ea92f61c14 --- /dev/null +++ b/txscript/data/taproot-ref/e638e75f42344b0c3f6564246955fb5d040cf293 @@ -0,0 +1 @@ +{"tx": "f912fae802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0902000000bd0732c4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5c01000000dba8b4d3014d37660000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966d030000", "prevouts": ["836c7c00000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5", "b5d1240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090206502592ab6fd45f774824457c83bfd05fd40c14b81295dd6d2197ae6f00b9a56d866a90a563d4594718017f360e7186af48c8b3ca16b8a002797b9080c8eaf0fab6ef8dfaf1a4259ff13023f68c3179e8bc6d43d0d48efdffce8a74b302304c2532e3ccaedae996197ee7f3693ec1fbd860de8b01c61fc469e8dd2bc640e9ffbcb326bff9d12debbd5d42aaf5a2f795512403658d1f5fbd07bd6a9269587e096a5c4977f8a3118da868fc99b729de21968d4a7d7840b549b8ff218931aa84ceee49867eb5c6e1f4ac83eb3dbc566549bbf103d6eac6cc1241e290c2a459181ad3874a4824146cb1f094111e6a892eb13cae6bdcb9e09c7818c97ad0075acf7638bd05cb925a4589f880847e2ce1bc517c2a6286b9a29241500205351295812941fd601d008c2cb57c9872109dc3053a024d57dd6faefce1eeaf0efb4416b0ec73430e00fc48a22902a5864c6267f79a6eac2352bb28b90581acd912cfacfc9e34112938a48fc12be480ae906bfe0a4c1583c53b29fd71b011f858e86522ab06d5dd207cedc2b4926c053fd8af96e7c27d1feb49121d4954dce1648baa3e6c7ae5202f7cdb0ee4290616ba0f470cd408a30d2d308f3ec99d6bbc0b58ea6daa796b5d18fbe4f00f4f9a5408870995913af92f29d840343b6490ed446d73321ceae02dfd51990c320423485dfe63ecf24725e058fc88a87240cf0e7b12a993d1b2f9fd57d09d6dbb1fca75ed", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ca8c0e626ecf2ef1fe50d0678891192825218ee00caccaeebba0271af988572e94cc415af9f84001a6feea45646803cad285186914838c4558edfc97d3166e78fd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}, "failure": {"scriptSig": "", "witness": ["4d0902ce681a3d9f79d82a9dabaeb3ef080757585c84d247986ecb06f13e02e67f974a7d91974ee5914d5328e7e9c903d86f0ecb68283249842c7788c9600a3a4ef7c54635d8e15dd32dc4223da1daeac48d03f8981349fb0d45034043faaba67107ea1be7d9b079f9b6001a54266eac89b0948bcbe1623851671e097ac8a6846d406d65612039be94223bd9b3c1e42e823218c5a109a7cb4f92bbbc5be64b96dc2d072e2edea859bced484922dc5c26471781e6ce9172b896a403102edad052ae0759a7d69e93fe9ab6dc294fbfd417cb916646a5ffb1a5510a2526dd103507682b338b65075ae94e4176232468381ba55c0651697284072ce527b3705cfc6719cd1bc74e2c4a16d687d8ef8b1eff9e0a672d14c55038f1aa3909e8d3a40ab602221f99b87fb7e2da8b044b42bd76b372877f00f64a95e0e8308a983f961df92446b7630de6f41a76746ce2a20c3cc61b539feedc9a2364ed5ce16fd213cf48c734efb79ca0899f04a759377be0f1d3b806b291c568040cc5e4d87827ced3c3acb773e1c017cb4db77633d39f219e524a43fddf8646450fce092297117c946f9e111a631d2a475ed5a2bb03be1f89c98418d91aa40d144e0c8f775b9a291e941061449852feb2ebea67aca3c9c8ec72afc67497a171a82d535db50df6a5698240df7047e7a753357b7ae29c00151979c67e1ddacc58d6e021a63be146aaa4cc29b9f1330ab7068b9fa473887561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb43866c9dc2005c39fbfa40f99a1086b922c913a672fc19646edbf7ab3e480e00f86475c33b310e45b92339559838140b9b3f3d62b1cf111e129ddf9f566de62eb71d4983925d18ba40c8655020b616e094614baaa1bc1b56f6416d7610eedc4a1"]}}, diff --git a/txscript/data/taproot-ref/e649d79b9010e5f76ed8c6e317e55e0e91802bac b/txscript/data/taproot-ref/e649d79b9010e5f76ed8c6e317e55e0e91802bac new file mode 100644 index 0000000000..4fad8780ed --- /dev/null +++ b/txscript/data/taproot-ref/e649d79b9010e5f76ed8c6e317e55e0e91802bac @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d01000000a146999d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40b00000000f9d200c960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706c00000000e4a24ae5038de26200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79693145c58", "prevouts": ["a3d2230000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30", "ba3a3200000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "f60b0f00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "417d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936571460ba76479f128232c1e7f3cb97430b20436d33add020c19a42e032587e00ebfb5abead622ee588f8a14df4b864e849bfb1ffa426a7f0fc441a7ea7f9f3e8819e00a9246c8c145cff8a91ff4546d478c6c8e3d7b4e3f7e61102a4388494af"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d0254c28ec270bdf41d4337856af66ad3dc8a43a5d3e633735369ec57cf2fec9da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e53f01d9cbc4ce44e53bf46e342c1ac713c14ac9ff1cc3e88a31c5570fba253bd819e00a9246c8c145cff8a91ff4546d478c6c8e3d7b4e3f7e61102a4388494af"]}}, diff --git a/txscript/data/taproot-ref/e660a993ca6c73039fade4ba3407920ada89923e b/txscript/data/taproot-ref/e660a993ca6c73039fade4ba3407920ada89923e new file mode 100644 index 0000000000..34a4eb1dfd --- /dev/null +++ b/txscript/data/taproot-ref/e660a993ca6c73039fade4ba3407920ada89923e @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf57000000008fef5e0960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a200000000630d7c750370197c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac27da9e2b", "prevouts": ["6d146f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "35ba0f0000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_8", "final": true, "success": {"scriptSig": "", "witness": ["565200a441bd8b33543b7d269c983d8205f3e3529da82e6dbe97079bebcd43624d9edd44919ada73cbbd16a552dc8f7abcc78f8d83fec5c5cafa9aaebb358a4183"]}, "failure": {"scriptSig": "", "witness": ["d5c7c919526b7c3c680b3761493b2bc4d2d01c6531647abee47966cf899369e4fdd074ffc209aa0742deb56a238fa0ee9e1c478bb1ce610149ac95a6a1583c5808"]}}, diff --git a/txscript/data/taproot-ref/e66bd9898efc98f464bdb5ece0b4f62d602dc737 b/txscript/data/taproot-ref/e66bd9898efc98f464bdb5ece0b4f62d602dc737 new file mode 100644 index 0000000000..333c18cd63 --- /dev/null +++ b/txscript/data/taproot-ref/e66bd9898efc98f464bdb5ece0b4f62d602dc737 @@ -0,0 +1 @@ +{"tx": "10ea334502bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8b00000000fb9e01a48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41402000000a58a699c023885b700000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487eb020000", "prevouts": ["761e7c000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "7e153d000000000017a914b202aa31930f9cb7b85a632f41f1539f30714abf87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "225d202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["f21859a748d58a120b039827bc9f62d58b657c5eba5d59c9910395a6444373d32e691c8d6c874e8a48c7c3accb5eb868c1dcb19634bd3bb0153d21d09d4693e1"]}}, diff --git a/txscript/data/taproot-ref/e677ad001a80f4218fcb1f38a8705f1d1caeb999 b/txscript/data/taproot-ref/e677ad001a80f4218fcb1f38a8705f1d1caeb999 new file mode 100644 index 0000000000..f868238522 --- /dev/null +++ b/txscript/data/taproot-ref/e677ad001a80f4218fcb1f38a8705f1d1caeb999 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c100000000e823d301dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc801000000d7978e97044cfd5d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac13000000", "prevouts": ["01ee380000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65", "2cfe260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6adf", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082345e83ad245d963f373c443dd6457dec3808a4f865920e34bbc543e7d04d4c3d1c315aec02adde316e700f87e7c47f474d1ec7cdd06b196ee567d81a15967a13360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f7f06e83b8f8d2d2dd50faf041bd8485749e4d90a35c5351976a06488b0663fe15b534b99635107bf366447ce9661d5eae557250694ef66e76c31b44d1abe134360497a554a17affee0221519da82623f7958d9c28014b232926f5323d6c78d1"]}}, diff --git a/txscript/data/taproot-ref/e68c741fb9f3bd4beb774a6295165f0719b15942 b/txscript/data/taproot-ref/e68c741fb9f3bd4beb774a6295165f0719b15942 new file mode 100644 index 0000000000..e39ac27422 --- /dev/null +++ b/txscript/data/taproot-ref/e68c741fb9f3bd4beb774a6295165f0719b15942 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8700000000f0211ceebcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5d000000001eb9ae8703257e82000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac66000000", "prevouts": ["c04021000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "9df262000000000022512027ab4b673389804c5c881c6b67bb0bc00b1e4ec28a98fe3352d53ecc50b40912"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "5c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ae78f6229172221ba8b4bfb3a8449e63620c22f298b6d0c8a103fdc8dcdae51974e87bfb4d3d415907d7a3196832fc57be4f6d746253c89a46e8e4c968740366e8f45a3ac55dff4b7d62b0bc42204f13e92c55212ff162d480a58edc7717abc8"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b3bb59441821a6815989813e9c3e139ed3a2bb96c5c0b1bed0297fe997254dd09e517178a4498250bd09ce9aecd8afa5f6f049a9750e0fcac48ec3d6edc1b53ae8f45a3ac55dff4b7d62b0bc42204f13e92c55212ff162d480a58edc7717abc8"]}}, diff --git a/txscript/data/taproot-ref/e69ec7f55ad3c08cfcb37946cda5c9e8bd2f23d4 b/txscript/data/taproot-ref/e69ec7f55ad3c08cfcb37946cda5c9e8bd2f23d4 new file mode 100644 index 0000000000..5edf2583a1 --- /dev/null +++ b/txscript/data/taproot-ref/e69ec7f55ad3c08cfcb37946cda5c9e8bd2f23d4 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9400000000c44b13eadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0401000000a6db52abdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c54010000002c43129203bb4104010000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6b86cdd5a", "prevouts": ["b93560000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0", "27ca5d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "17f34800000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "a77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e389e677eaf5eeea89a70f01c0aa3bc14cf3320f4b6dd8cc61f33138af3398b5b11a008161139ac7a92b00665158d25501a881aeebdfdbf881ee45b85e0726c11"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363e9eb096ec4c0e60b6c49349abcbb61376af9764a0a95f04ae72fcd7b6082681146d6305f54208d13896b102f4aea30badeaee99896cb007ba6ff00553e24c3b2915fd873a4966f8e9b4a3b328eef3933245a1c852c287990317c3760d8289da96773453f0744a158be0509abdec64f05b1db7ccf03251d8359952271b442a24"]}}, diff --git a/txscript/data/taproot-ref/e69f704fabb54c278ef86ba0a840cc8b462fd273 b/txscript/data/taproot-ref/e69f704fabb54c278ef86ba0a840cc8b462fd273 new file mode 100644 index 0000000000..563d76c926 --- /dev/null +++ b/txscript/data/taproot-ref/e69f704fabb54c278ef86ba0a840cc8b462fd273 @@ -0,0 +1 @@ +{"tx": "b3c1472202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf2000000000576e88bbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd70000000004c7aada0154af38000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374876209cf31", "prevouts": ["efcf20000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "a7286400000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e17bfbf8111851fd9ae24a1858afec5c4de6caf1cc26a2e2b06a933db436efe54e71f92e1336a687ea436697fbd19181210e765b944dc821397d885c783bf2f2425e521f6248097fdc64ff5a0a6cea9e07e7c649e93dab8ac6058acbfaf1ad70aa"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367e85fd122cb37c54650db3c457c4ccc1d826b9d67b5660e25842c64e9724a27a7bfbf8111851fd9ae24a1858afec5c4de6caf1cc26a2e2b06a933db436efe54e71f92e1336a687ea436697fbd19181210e765b944dc821397d885c783bf2f2425e521f6248097fdc64ff5a0a6cea9e07e7c649e93dab8ac6058acbfaf1ad70aa"]}}, diff --git a/txscript/data/taproot-ref/e6a0539a6bf9730e9f7197aac29cee83936137c2 b/txscript/data/taproot-ref/e6a0539a6bf9730e9f7197aac29cee83936137c2 new file mode 100644 index 0000000000..76a87f023a --- /dev/null +++ b/txscript/data/taproot-ref/e6a0539a6bf9730e9f7197aac29cee83936137c2 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c580000000089646dbadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc10000000056ed9eb1035d779e000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc30010000", "prevouts": ["bfdd4a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "a25e550000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["ea", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045538b2525e5ad3e6ab2346b1907a9f51d3650fdbb6911031be2b995911891caa483976a7e8bc20bfa4c53f64ff2df47d867849c8cbf6df51014735817968d498535c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0df322cf06423056ff4efb147ba4330d28398a4f05a11ad98b1121aa54f60b594336f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}}, diff --git a/txscript/data/taproot-ref/e6beac0076a3f98639e16833588cb1f7c3630b56 b/txscript/data/taproot-ref/e6beac0076a3f98639e16833588cb1f7c3630b56 new file mode 100644 index 0000000000..4e3e25e593 --- /dev/null +++ b/txscript/data/taproot-ref/e6beac0076a3f98639e16833588cb1f7c3630b56 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb001000000037ef9808bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48201000000c798b1410490418700000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd3010000", "prevouts": ["2c324c0000000000225120bf14cc6d2f64add112964063c7917cbfbca584b2015bb2b877e08d516634d692", "d1193d000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936df6796774709e20f3de4e580719925f05298bdadc26b77e803df81f5078f2094"]}, "failure": {"scriptSig": "", "witness": ["6aa7616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e6c4139fc79b0036b50c35d40646356790b47698 b/txscript/data/taproot-ref/e6c4139fc79b0036b50c35d40646356790b47698 new file mode 100644 index 0000000000..41c15f0f22 --- /dev/null +++ b/txscript/data/taproot-ref/e6c4139fc79b0036b50c35d40646356790b47698 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4201000000b563db75dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc301000000f098e3a68bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c467010000003d1d4d040391f7a8000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72db95c2a", "prevouts": ["4e8e4900000000001657142540f27e90740933c99d4f17ab2dfc6c82951cfb", "f6a2260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f1053b0000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_2e", "final": true, "success": {"scriptSig": "", "witness": ["7538d0a63a0ef5288628e67c8f42c8f3aed351a24b2ae3dde09043d648ebda2cafbef1a4e404938bf8deb99cf4db150a48fd3c3c7b50d250044bc263899916d2"]}, "failure": {"scriptSig": "", "witness": ["5e50c2f2c4e0e081fa7e758f6a7f4d4f01748c4a1282ea2100199c782ed2ce61ca2bddc98aea44730eb62977d87dcf02abe52760bd1d26507533ffb2e9d2675c2e"]}}, diff --git a/txscript/data/taproot-ref/e6d6a1ae86f60f1e63f309397a0008e6d4943d50 b/txscript/data/taproot-ref/e6d6a1ae86f60f1e63f309397a0008e6d4943d50 new file mode 100644 index 0000000000..d1e7b42215 --- /dev/null +++ b/txscript/data/taproot-ref/e6d6a1ae86f60f1e63f309397a0008e6d4943d50 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a000000000a3952b5460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fd010000003122469d0459d21c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374877bbe1c4b", "prevouts": ["18610f0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f", "4db40f0000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ea", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936688d2e46a192ad60a20fdb5c472affa9c3d9be48c29791f78ee3d204a0eef9e805d194d5538f9d0578f97aaac3520494006fe8ed5ea4118540907b045326452835c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5170b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720f322cf06423056ff4efb147ba4330d28398a4f05a11ad98b1121aa54f60b594336f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}}, diff --git a/txscript/data/taproot-ref/e6f3612a73d29882780cefe3d036f68100cf0c7b b/txscript/data/taproot-ref/e6f3612a73d29882780cefe3d036f68100cf0c7b new file mode 100644 index 0000000000..9eb06cd818 --- /dev/null +++ b/txscript/data/taproot-ref/e6f3612a73d29882780cefe3d036f68100cf0c7b @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4100000000055c6482dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfa00000000f46499b502d29a9d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8767d58622", "prevouts": ["f8df48000000000017a9144370350f30aa8f875e3d2a13be81f25f19bf1a6387", "14b556000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "165b142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["d116ed280c0713e398d54bc4383551f2cd0480ed987ce39caccad5a683a97d66049edee4bff1ee72c96dd4951968ef034acb58d2bd50aefa3edd27f16bfd0e2e", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/e721205c821d1cfd009e603052b5cee6c677c52a b/txscript/data/taproot-ref/e721205c821d1cfd009e603052b5cee6c677c52a new file mode 100644 index 0000000000..7077166792 --- /dev/null +++ b/txscript/data/taproot-ref/e721205c821d1cfd009e603052b5cee6c677c52a @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709b000000007f3424108bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4af010000004517a8d7048319420000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875f000000", "prevouts": ["e4820e0000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "3867350000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d84c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93602817a41c51ca033292e6ad0865adf1b315ae27488bc31b0f8fb3dd6e91881b7d7b73fe79aa50781a03db77b9e22252058e372f5a0275feae864cfaf4c2a217ec513aca5799d408eee0c275015e54cf6f255f9c56741048ad8672ad33d4825d8e26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}, "failure": {"scriptSig": "", "witness": ["4c52d8", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f7f0d1fb1b0bb9d70ab8433d07e43e66e6dea85179fd9a6b3a0e9d7d243e07dec513aca5799d408eee0c275015e54cf6f255f9c56741048ad8672ad33d4825d8e26db4ec4cf8c6a12d3bfb33a6f8c1ee971c26c5be04413f1d9dccd7296a9839"]}}, diff --git a/txscript/data/taproot-ref/e72d5da834d577e08d8919888da3491b1cfc2395 b/txscript/data/taproot-ref/e72d5da834d577e08d8919888da3491b1cfc2395 new file mode 100644 index 0000000000..ffdf00058d --- /dev/null +++ b/txscript/data/taproot-ref/e72d5da834d577e08d8919888da3491b1cfc2395 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dd00000000e98bdfcfbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8a010000001e3b31c4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf10000000006ffb29ef043b09130100000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd0000000", "prevouts": ["f1ac0e000000000017a914ff6a0b1cf86e786bc6de2387f1927f71fd08cd0c87", "cda7830000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c", "20568200000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "165d142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["1d11ff9e6594593cbb3db3d706e5329836b53d7b1047452a5869d53e1e3c549c28e59d7a782b615eb017decb90ffe64a5567a5514f624bc899c426cfa3c229c3"]}}, diff --git a/txscript/data/taproot-ref/e73715f248773b481cfeb2552aceaf18e4b03797 b/txscript/data/taproot-ref/e73715f248773b481cfeb2552aceaf18e4b03797 new file mode 100644 index 0000000000..613544fc23 --- /dev/null +++ b/txscript/data/taproot-ref/e73715f248773b481cfeb2552aceaf18e4b03797 @@ -0,0 +1 @@ +{"tx": "3c688b8f028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c501000000794a30f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c30100000090cacde503a0306f00000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a61e4ba658", "prevouts": ["83f8390000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8c143700000000002357212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c1", "final": true, "success": {"scriptSig": "", "witness": ["817c1b70322061ce0acc5c14edc6eca45ef09e96a86c84bfe84de4e15e71c3a112e6dec6bd65f6f58cf770798e63aa14936fbd2a1854a777163081c081d972e502", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["d97bad7ba6d489e059b694aaf49587c68e53e5c0c5dfab57043ed92cdbd8f4daec5ed88fa517a3a2384d1bd7d7394a15d8d3b7847a9ff1af17b25304f16525a9c1", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/e7865be06886b6e888fd9d883d55c5faee586ef4 b/txscript/data/taproot-ref/e7865be06886b6e888fd9d883d55c5faee586ef4 new file mode 100644 index 0000000000..881d0394e6 --- /dev/null +++ b/txscript/data/taproot-ref/e7865be06886b6e888fd9d883d55c5faee586ef4 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1901000000f2b706a8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb701000000d5414634042e88c0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c6010000", "prevouts": ["2f50740000000000225120554d9dd7197117aaa4d7426c37fed7dc5f4b29ff7dce4879497bcc4232903b0f", "994d4e000000000017a914a68ade9e67dbb5e8acf044461cfd5bd8dcf592c387"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1652142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["77f72fcb63f4b3ee909677bb7ca7023720d1d4ed165ce3976dd8898c9b2dc24d781d3439d220f0403fa0dabc6eed1007f1e2332502d61e6af736e38ef9587c08"]}}, diff --git a/txscript/data/taproot-ref/e7a375809c225d5450a212abb59a2046d1b5e007 b/txscript/data/taproot-ref/e7a375809c225d5450a212abb59a2046d1b5e007 new file mode 100644 index 0000000000..901ae0b293 --- /dev/null +++ b/txscript/data/taproot-ref/e7a375809c225d5450a212abb59a2046d1b5e007 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfeb0100000087f4e5fe8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41101000000bf8e4fc9046e05b1000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47878e020000", "prevouts": ["9ae07700000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "0c683b000000000021581f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["8429a4229b24b38dc77d9f95f72ca2d0ed52126309f69eefee92d5f8f8a8a1b7a6f8cc54c9b2918e742352ad35d793ef376e6c30766c9de854f951d1cd88406e"]}}, diff --git a/txscript/data/taproot-ref/e7c4905ac16a9774e7e810abf68b112d641b2d9e b/txscript/data/taproot-ref/e7c4905ac16a9774e7e810abf68b112d641b2d9e new file mode 100644 index 0000000000..7824d04dc1 --- /dev/null +++ b/txscript/data/taproot-ref/e7c4905ac16a9774e7e810abf68b112d641b2d9e @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7a0000000049367eecdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb401000000a94652fe02ebd56900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3c355049", "prevouts": ["00244800000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "b705240000000000215b1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["f85913f1b9c9175497e63ff3fe4937cd61dbdc806165848d02e5a64f871aedd45b5d1212cfb7047204ada9057a4be48c2c6f5ce87a05578bda43662f72114f97", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/e7c5c79c85fb153f7749dd5dcfa97ac1401ef95c b/txscript/data/taproot-ref/e7c5c79c85fb153f7749dd5dcfa97ac1401ef95c new file mode 100644 index 0000000000..2ed71e9f24 --- /dev/null +++ b/txscript/data/taproot-ref/e7c5c79c85fb153f7749dd5dcfa97ac1401ef95c @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a4010000001d6355fcdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2a00000000547be58f03d0fb9600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac1baad02a", "prevouts": ["dd48400000000000225120cc4d42e69b853b2a0a5827098521167109822d5a10f2066982dd9b410753f660", "8391580000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "d67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eb1986d7e8e27273be987a3f59c249d736830c7b6f9b487df38f4ee68bd2c5d06630d95c26588949f1b3ae4e4e429080b434b995fa18047406852c727cd9e6feb"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93630ca117f3a3f5d0edabc733225eb4a624a098c8f44ec26e7a92d0c8239372396e4fd5de156dec52418d0df8cecdd3495838e4d1d1b80598a34f381ec5024e2c9bd0211bc754da142cb3564162304068e34e33074851a6380a45a2a3191e3f102"]}}, diff --git a/txscript/data/taproot-ref/e7ccede981bb4c65fa47e7fa310a9348a7109ba3 b/txscript/data/taproot-ref/e7ccede981bb4c65fa47e7fa310a9348a7109ba3 new file mode 100644 index 0000000000..adbe09588c --- /dev/null +++ b/txscript/data/taproot-ref/e7ccede981bb4c65fa47e7fa310a9348a7109ba3 @@ -0,0 +1 @@ +{"tx": "c3f06660028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47b010000007a1ec183dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6001000000e09642fe0241047a00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000", "prevouts": ["c7ac340000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "04b3470000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "cf7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b956c939d6163a1ef6c18d735cf5e1060a6cae99cf52377ddb1bcdce2fbed5e246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdd6c4167c25132c432c9175336dcf34ec1853eafcfbd891c58e0cd045b8bc4542"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93634aefa031e9db0c34453688b34a5619e3290706aa35ba0709fdb07560fb296d4d2b7053bd8f6b5ad2f12d7ae765b8b6e1c341259e3dfbe95167fdee949bfcc9ffe03d403be23d34fe95cd8ea927043998b4b921fc49b039e78905cbd289b8eab"]}}, diff --git a/txscript/data/taproot-ref/e7d9419f6cc1411629e9a09076e350aef3f0adbb b/txscript/data/taproot-ref/e7d9419f6cc1411629e9a09076e350aef3f0adbb new file mode 100644 index 0000000000..13de4acbb6 --- /dev/null +++ b/txscript/data/taproot-ref/e7d9419f6cc1411629e9a09076e350aef3f0adbb @@ -0,0 +1 @@ +{"tx": "7d81ada40260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ab00000000a5db64b8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf970000000016aebcde0482f29200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79663000000", "prevouts": ["bef7110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bca582000000000021521f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["e852cfaa079c741f4515ed79da14c225d7b03a58e519cbec8eed2b9f348fb7af8f04275ce86156ce1f7cf928a482c97ed207ab38aea691780a93b26f97168cf0", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/e7e9f1bdab686670c7fd4b590aaad6feacbbeb73 b/txscript/data/taproot-ref/e7e9f1bdab686670c7fd4b590aaad6feacbbeb73 new file mode 100644 index 0000000000..b9135ef0d2 --- /dev/null +++ b/txscript/data/taproot-ref/e7e9f1bdab686670c7fd4b590aaad6feacbbeb73 @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a20100000089eab0dd0233813f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acf0030000", "prevouts": ["dee3410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_60", "final": true, "success": {"scriptSig": "", "witness": ["cc8487fc4d8489c3dd52ad2f090001b7531935033f3d5e5702c8f840635cdcae03686ec27b39d28f069c6861935fa5bd2518d0e3df19d4105f6b77d4e494bdfe01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["71a2cf08522bdd941fe5e66a848714af5060294311b0d9c3bbc39dd03a5765ad1b79a43471ccb50dbb47d3ed01f0968cf742e61b3a11c9b2b83017f404fe961b60", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/e7fc7fe2e56e39aff52a6c1a3f3ddb20c48651d6 b/txscript/data/taproot-ref/e7fc7fe2e56e39aff52a6c1a3f3ddb20c48651d6 new file mode 100644 index 0000000000..99c421fc10 --- /dev/null +++ b/txscript/data/taproot-ref/e7fc7fe2e56e39aff52a6c1a3f3ddb20c48651d6 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1701000000c7fc959a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704c010000007eceaec901a7a40e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fce500232a", "prevouts": ["49ba1e00000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d", "f00011000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902d159c28a2f7b7ff761fcae8ee32cc830457aa38ec63388ab160de97533fb61586998360b9068725ea0665cd56dec1773293b984e638653e276ddb940a478231daf72f21632fd7e3ecd6fab2fc91e3817f81a6e65d8de141b20738b1168f2ecabf718fa6df5c065202725a56079ab76c2de31bfb539ad3e5006bdad61c04edae70e1c9715723adbb198c0b9b0528e68f6b2478092674b4f635a3a6b11b2b24f6762e0a22da1c1936c58ab72bdf067e8cc1bffdb55ab5a4160ccf39ca08ac52535cc8b7997a427f0f676a71268c4953a83a8d72f34eb10e3b6d2b8be8b5dbe409fa1dfa47c3e1d8ac614c2ce9397e33b844964671bbe69760709ac194afeaac4779b8c6d1e07121045a0cb6a829ae823a7b2756cd9384dfd0b898b6d9a01bcd9b3b9f022362e16b19858b6afc09abe929c7b5b674a8b13c8b8624ccb75d438a45a08551dff47086baf3a7dc8af4640cce2264d5a9c447f818ee7e36570e45447dd067c137eead04f8aba641a58402e8b18718a962700445f17b42639c70878131802797d440e4a396d57275ede06a4eb2245b269e9086d0b43613df07375ae7657dcc45db6dde0fbd8bc41aec2cf731b0ad4dce8187e46484006e574b6d34deeac077d46127626f5b09c056074bfe2a5e570ff58d12405fe1a5f694c47c466e5072758c6dff00857afdeac0c548c446c93c51b2b59bc49e5071ff577b70c7954028fba7e7943a8946f2d75e5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a9f8156eed7fd3bb2b4cab14b5333356fb81c736bb205a27ebd75cfc9ceba70098751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d53d2e072fd8e8376d3a54b2bea1bfbfff1298aece70c0bc2934c8eaacc3044fe58f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}, "failure": {"scriptSig": "", "witness": ["4d0902237352b9799019813fe8fc82812659e28cffa3b4df7cd8b99140004fec11d26c8e6e3833370bb3d9d63c081c137c716e45a436056e672483d0a8fa3acf300a2d520d38a64fc6a0839c79ad79bb1fe02acd8deef2047e5f41b3daf06c4d9daef4997ab4f23daee4a2244bf63c5ff7ad1cb54c95a6f0c6456b0ceed3760fe8564a72cb79ac32ffb51a15d338a703af6066eb0fe07fd15a2be1e5f18d1895741202eb959b350229aa3de61a60fa4a2e6461e355246bb7158b8b45b41dde12b31155447efbd8542350e99c06dab30b94cb6dae1bd5c4ef8b96ca8611ac964a664e9b5e094ec92a0862361cf119f6f217c3ce712a7fbc8d45fa5e59dd68728e5281e5d5bc3fde591ae5a01fd49af46a9fd6a1fcb3fd93d5f8012fa3aa28d423f76e258222be10a3ce87176d4572f09ecb44aef2f72a3967e5f13d22177691b935f62760a67f3b23746a5a5fb7eabdb926419bf3ab3762b5830c1059bd1507f46a884864a2b9976af3dc0d6e6815f626e882f6804f8f768465ffafa0c1611ba9b3cfc9c284012c958e417862c016a07d08ee4cdc544b4de37bcc6680eec107f2d392fe6fa35ab6a3053fc4f3e454206e63c98f0c0f26e62bea46a9fb5afe549c07abef16f4a67130ee2b6eeed9eff4f8a040f0ab60395ddef39da8b8d19681b23bb85c4d740b491eb3fbb4c42deee0e752c7932c40c49e3632872230df3e50d8a6d80f44c5273ff329aa34197561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bc95516ff73e0ba0ea1936e2d89c1346855b35984437390d0b37500c31b5ae455e7270ac6e52de2effa1ad4f1d7cc04618f1a83be30b0454843cf6016e9cc3658f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}}, diff --git a/txscript/data/taproot-ref/e81dc94c8743dc71b11667a65c76c5ef0e8eaef8 b/txscript/data/taproot-ref/e81dc94c8743dc71b11667a65c76c5ef0e8eaef8 new file mode 100644 index 0000000000..05927b2714 --- /dev/null +++ b/txscript/data/taproot-ref/e81dc94c8743dc71b11667a65c76c5ef0e8eaef8 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3e000000004eecdbfd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40400000000dc744fac8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48801000000149ea6b603d7969a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88aca8a50227", "prevouts": ["6f9121000000000022512080d15096ed03a913dd2615bb22b23502eb7f2ed72305dfdc851835561a0e6974", "11d139000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "5094410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/pushmaxlimit", "final": true, "success": {"scriptSig": "", "witness": ["ecbbe5a58e56fc80617b50f40e8af25c687c94d5a2f495fffe6052e8208eb884d77559ab0dcb0ff20e20604f09ba63bf7be3d6725ab88d81795bda5303d11684", "4d0802dd367a9ac4f69febe46eba96d8c2f0d894999cc95e11a3752f36b909723af9f18cf4da7602cad914034fc5a537f98ae658c499b0e1a228ffbf969c46c3176961d54d84a1e2bdac62384ad86b6b5fd22eb64007deeca4fac2a25f07d438b1d447af3f70ca476afa81b6177521a83ea0450893aadf4505236a5b604f34fe34d751eab3b606e442eb193fd3d88d123519908efb861979119251072e986c11be6899d2d17715c7aaedadc57d69207a4f43d2a934692540443561bb859596cdfc04e9784923c242e3233844eb48630dd5b0cfff6c9d821a3033f4660bd7b2a31f7ced1a4f0718ade4eafc82a54228ab0fb5b64e023b4f9fdb2e38f89cba2a9d8a4e89b5db6d51a1e0b90b643ae4120bd39145491ac7483b352e26b402af0e66fbd8532ef898890412938f3059ea3b3d00d32a6226790fd3b9a95c7cb09d8d2e535d8a42583ea3560691294e26ef26ba32b8396c624e883c1a9a2485617957f02545c097b3408ecac495c02cf770443c2c2280db60e9b9b953dc45368187e72f0b4cb67623dbff3a8b4025e1d92dc3ad63e85aadcde076c7cbfb49eb1c18effeb2434c02e32dac73e5a2ecb59ea357e16d6e74a361cfe5b8025687a73eb0afff120e1f25598d2d554a88b5b5b155b74148a54eb796b1226bd3c23ff46107d96ca2e57878eded8c8d7bdd002c8136b19738e91b283fea5873f25b609135b6c2bea838b726f4245374034f667520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936103cadbcaf2fa5df6e479334a11b958e5957fa2effaa354c06c9313f5686f6aa838550afd43b5c0ac0246c83f68665bd17c01b14cd3e86e9325c0425666bb85e05597bbc76f9d2c64c37772f9ff7280274d9ed9557cc805ea3025c75bcdf8ac78dc251797150d329b8e820d63bb5d58a12f58566ad0e9367e2ceaf5315e4d4628d4486556d0140df24dd8957661ed20e0acff298adf92d4035aba275ac667a2f77ab26e4de9e9f465a75df7696c385eaa6ecb043bc8f566ffbcb0e87dddc5e410142f60a8ebdb7285f9bdeaaac297e7aef914f175757f6209e65e1d504efa78f95e357bd5ce0e69f0bae0d0e5c78e813bcc733b431bf5c1d7f887580db0ed48d8b3e1a4fab038dc3bdab705ad8495d4c7432b8ceb30c4183e94a977ca62a62234e97d4fdf1ae4efe28e87c8298a66c795d715b7214edb50bff87ec712d9aa017bebc678b84a7871003d789a8d21944528b51ca78090c337c3c6ce4e3b71f5ce1dd261fad3bbe190c3c47864868b24b9d45ca4f9b7ef6df09ecc5e2c2e3251cfe2c030205566d26d99f7670359563d47c70c3c17ecce0772c32e7d70afd0c074a7f07ffa6395a21fd19628398e628d5ac5d3d7f77ef8bbf3ea7985fee799a2e0b5b2934214492b999e4970e4990c42fb0eac353aa09117e3e38145bdbc22646e577b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["16430af64cb8a3637928d82525db3199acc8c7d90ee5577d812b8431f994ef9f21a2450e4836b8202a044b3b452d9cdd2a07b064886eb5bfb0b84c29af3b5927", "4d090253d399d62628661e736b2df48f4a21782649e99e3929d4834566b927c48f821c06be3519f174f66b8f7b1ed0573c71d1ef55b750ddb00b6ff488c57c2e6a993f19f272125f0155ca8a6c7d9017b340a112b94c4a99e353ecfd7189a27175829025a66133bcca1ac7be915db7391a8300d7de1696a53eac4d825ed3df0f9c8ed892987299646d1f4c0bc8f3ef535d1606bd00ab33111927f918d4fc40e1bafe5431e782f66894f41cb83f7852536f01e91a040f9415f86ae5fe7a7ac42c9566ecf8dfbafae09aea4e8e5f60cc0eb0a07db2bca657ec8fb88a7f0125951051920e9420d02cc31bc1404610d1fba1effd8d2b614f69bd73d03ef57aed7a352acae3ac92de39ef4d6645e620afa87290786e1cff9857db6719b117b9744e0b9a8d975674694e82ba43931ef8c0c510884953f690f7d652d44569b9ae7b613a00e4e7ff2e22dcd75855f1d42297ec21c4a529054d8a09fc90359f6cf64e604f76cf4a238407e122fe82be719a8cf960a9b20339b86a2634ef79c1ca6831d4da925ada516a0445dd6d587f676f2829644d884f5d16e116839e8958b39e77040acbdfab78582b91ea9a785724b3cec68a8483cd7b0f56a6065defb5d40c0d109d8a0776397c37f38c2d04be28a66b3a320f07daec3f144e878c74e7702258683b5ae7630b4b66d037e8f0f9a26cb3a609bf865c958610d487ff4625b9678d3e89569c9783217b8dc58a6021407520871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe92399151827fdc18825d14251a865e31a5e1c49f80697ce6a3e65db1b6f47c9e2d76b439eb8b90f256c0b5d415475c63c19e74341f69b4cf4d655a142f136b31916e23bdbc1135794d0d6806dd39e768f0b3fefa547ce8553ebcc58a86bee262ed34707a6ec3057d6919ec05d5b94f67ae87cfa587eaef2b12b91ceccc6ef8a875d8879e2514959e0266d8bde9aa7bdbb78c9ef4e7ac7f5cf4ebab7eddebd4a06e111d3be560136713863636b8209103ca01a3cbb41d43efd48545207f107eb77133ba9a11333aec7eda378031b485f5b8e8eabf57bfffc8ba4619b40408b783eb29786b9c7e54d29bd57a82aecf88557e00d4e8aef97ade3b73179d439f2293912176cd8098a5570cf2ae8a62d493725eaf54ef9754ca785295569a25e301492e27c5aa3537568f6734824d9e13d17b040b5b13f58e286505de213f86581d977acef7f6b695f70556e0cf280f2f492800c5063304369626aa3de8e4870d2a17002da8b6956793790e2522cdbbbc51c3e76cc941c9170ee3ae91039a9479105f3564c54269032898a6cd874ff4d1fe0ed410013dc82714eb7a54d64226e3868b0e659112c9f7f4ef135ef7e3677927c686e2cfb83a5642dd1287d117c18623babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}}, diff --git a/txscript/data/taproot-ref/e81ee8a9a2165602a74cee1bdc447e2da39ab762 b/txscript/data/taproot-ref/e81ee8a9a2165602a74cee1bdc447e2da39ab762 new file mode 100644 index 0000000000..710c38e929 --- /dev/null +++ b/txscript/data/taproot-ref/e81ee8a9a2165602a74cee1bdc447e2da39ab762 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbc00000000f53d232fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5801000000a868a14b010a422000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ace1030000", "prevouts": ["f757210000000000225120d65a03f65f30f95ff11470521917ac5fe759126fe5e56fe4b3d214d8fd101829", "af9c4c0000000000225120f855ac1dd07b462ddddee29099c3eda9b5eca4e8470208f3b94e6aab9d37482c"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "f77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08275fbdc6cf2e777e050e79c533e418db275d42efba7f8dbffba71190cfdc033660f5943df1a7722c938328966c7e5ac747f85bf050d43cd9195f6df88860ae066"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ab23e209afea8ddaa27b117399cf1dfb5b8cbf4adc6eef68e1faf96f2bd7a900bef6e20d4c5455f6a7eb766c9d2ecc1d4fc5a0b2a6436d41d520177b8d84d9981b72a8cc1600d8047fe8b56626831fcb5b55f7ee61ebb9b8b91fcb4b55947dd0f5943df1a7722c938328966c7e5ac747f85bf050d43cd9195f6df88860ae066"]}}, diff --git a/txscript/data/taproot-ref/e84308cd3dc05d65738bf940c73e11c1342f53dd b/txscript/data/taproot-ref/e84308cd3dc05d65738bf940c73e11c1342f53dd new file mode 100644 index 0000000000..2ceb68782d --- /dev/null +++ b/txscript/data/taproot-ref/e84308cd3dc05d65738bf940c73e11c1342f53dd @@ -0,0 +1 @@ +{"tx": "0edf5c600360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ef01000000195c71c7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2a01000000128387c360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706301000000d6a1ca9b01111250000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478780000000", "prevouts": ["77320e0000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "f6ba6f00000000002251208082b91639ce415d44b93ebacde06f605687bdd15466bf93e6aed91c1a4a19e7", "1f6e0e0000000000225120ca2f7736d38d84f93b62b86d7eca19a35f2cfb6705849a1c6400bed56ad761ae"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dbc4082c88742c64e777227e559cc787fa79f9ad49b3844bdd2aa78bdd53ae153e2d335f383706a312226510c4ca5ed297e59b2981bccad977d4984b4ab81a7bbe0beccf8b53a38f7a20d51eb008bdc60f78fac094fdd23935202ece673d8622376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d95f1ea0a1fd23653d05da4ad0eda243001c7a04351d1c2a22e8a2afb82411fc18d13f23505bf80401329c8d1a0bac5ffbe219ba0d96925c38e985a7086f175ac8db205c7d3bb0390b2e22910f5d1cbad00807eee3325f4c4e7f4412ed3064a1c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}}, diff --git a/txscript/data/taproot-ref/e8597fda210c9006c4eb35f55099dd53f0804f47 b/txscript/data/taproot-ref/e8597fda210c9006c4eb35f55099dd53f0804f47 new file mode 100644 index 0000000000..6665834633 --- /dev/null +++ b/txscript/data/taproot-ref/e8597fda210c9006c4eb35f55099dd53f0804f47 @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5b0000000030b2815b03305c6c00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69846252a", "prevouts": ["2cdd6e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_6", "final": true, "success": {"scriptSig": "", "witness": ["48139ca85c5fb7a70b53c6639a15fd7d9d6dc1b19fa2b1f15fb8b272c65b0ca1372b1f62f390098744d5db2d5892cd455c73be7b67ed24c419bfc8121f770d2d02"]}, "failure": {"scriptSig": "", "witness": ["b3d155c35adf27f8d46a5f951b4aebe4e749148ab80c2d0a54832b9c82991fb700277d32ffe299eae938dcc67815a210ac71ba84e381bb96ccfb8e7d0ffbff9606"]}}, diff --git a/txscript/data/taproot-ref/e85ebbbabefe13b277bdb7bb290e81d48aaae843 b/txscript/data/taproot-ref/e85ebbbabefe13b277bdb7bb290e81d48aaae843 new file mode 100644 index 0000000000..c852537693 --- /dev/null +++ b/txscript/data/taproot-ref/e85ebbbabefe13b277bdb7bb290e81d48aaae843 @@ -0,0 +1 @@ +{"tx": "6b76e011028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47901000000f2a234b660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cf000000007d7052db024ba54300000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a3000000", "prevouts": ["2531340000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "dc6d1100000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "0c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c2538f548eb9d319d165a467796d1e60ec6673916444f0d66e1a9edbb7d8ec4eda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e5111e542fd849c49f4d44aada2d8e1aab946c793c1d334242f5a6d1a51a6de2d5b0de380cf0ebf0fa9d17e1d1edb87a374b64935c1c67f0c5024fcc072643681"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f347fc09b13f9ab949e4d0dd849e76d18bd9ee465aaa47c5e053192723bafcd48d88e70532c494439586c1157b8a644f11fc532506ec8f5af612c230a11997e628257bae22e6d8aedb31b43cfe467850e731fb88c1221782039a4c16ef44c35617d0d4fc7404dd8984f6a1705481d95654b515a34c586c99c11bfe20e9503459"]}}, diff --git a/txscript/data/taproot-ref/e87e2014a5a0695a3cdffdfe859201eb8beb9fb0 b/txscript/data/taproot-ref/e87e2014a5a0695a3cdffdfe859201eb8beb9fb0 new file mode 100644 index 0000000000..ce4c118a9d --- /dev/null +++ b/txscript/data/taproot-ref/e87e2014a5a0695a3cdffdfe859201eb8beb9fb0 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127095000000005c767951dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8e010000004a51eaed04d34b570000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc73b010000", "prevouts": ["4f500e00000000002251207642517ca6719fb19e4d50e91940e680bbab7ca2eac6cb77783eaa45a9fa38f3", "342c4b0000000000225120c09854f56274e1d35482cf8e2025d8ad7496c75563e822d6c9c7b32cf3be83f2"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "717d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a84e3bf2953ddc9cb8e31c297a3a65f2ea0223693047b485ee05dec8a9b2b04be4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8674d0c931fae68ff43996ef27e2c8ff69e275e322181f769b95dd7ebb695302b667dde4f09f14471eadd81946489c41cf4fd01382a4947d773f1f2d4d0db4c57"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b2bba68bdba5bb63faec40886b7424a0b364c5795c89d5df60ab242d96dbfca40b90ee144c073a081d1ef827361e7936248dbf88e4cb0dcdac45f51ff02f5de2667dde4f09f14471eadd81946489c41cf4fd01382a4947d773f1f2d4d0db4c57"]}}, diff --git a/txscript/data/taproot-ref/e8ac301abd5dee5dd4ef8cb0670844bca13f0323 b/txscript/data/taproot-ref/e8ac301abd5dee5dd4ef8cb0670844bca13f0323 new file mode 100644 index 0000000000..f7fb620ff3 --- /dev/null +++ b/txscript/data/taproot-ref/e8ac301abd5dee5dd4ef8cb0670844bca13f0323 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0a01000000b500cca2dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb0010000004057a30b02358044000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7da000000", "prevouts": ["8e402500000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "389821000000000022512046885de037d9f439e247c936086c9c89d6da1bca43dc543d3e57bccc8a96eb66"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93623ae85726644c2de015503b238f6d2ff3873dd043771b87773ddc298654b0280d81cfe71594e1389c7dbef12605d87c33af6e429193e755ec800f4a6d58e14260941252319b1d0989c3ca3905f2d65278f17fb3ebe6fd71301329f8e450b42a05a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b1651a3fc1c4e1b7c3cd67236d38206903995e4c6229f7d3322c375e330dd9b093e484a9e3a7c57c3845514d142b984218effb649d9e5eb3f309ab706810aa991d26af6ddceab3892536958f1ea20dd7b885ab499207106c7decaa6511a0e4c5a35b5683fdfa8774cce0e3f4376573bc9dcdb125f140a48d9cd3d58bda5cb68"]}}, diff --git a/txscript/data/taproot-ref/e8de8be751822aa2e8bcf086b89ae6ca68052255 b/txscript/data/taproot-ref/e8de8be751822aa2e8bcf086b89ae6ca68052255 new file mode 100644 index 0000000000..de9b3dd108 --- /dev/null +++ b/txscript/data/taproot-ref/e8de8be751822aa2e8bcf086b89ae6ca68052255 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704b000000000a65acfd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c465010000008cdf959c01c1fe0600000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5e000000", "prevouts": ["d88a0f0000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f", "d44c330000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_mis_3", "final": true, "success": {"scriptSig": "", "witness": ["a9ed556b27362671a397085cc5922c9405eca223ef8767b92c77d05d88825c366863b68cedf019302ff5992904ef35c251cf329ed6de69ab09180d8174374ba681"]}, "failure": {"scriptSig": "", "witness": ["3d5ff17f49108195b875a93aa5abac40e5935025485f0926dde5450549f11be4ecd6f9485486ad3c9da1504a287802e044ec30cfe7133e982f6feb4c1f4ffda403"]}}, diff --git a/txscript/data/taproot-ref/e91b8692e5e50d7452d085b3580b9cdd1676e122 b/txscript/data/taproot-ref/e91b8692e5e50d7452d085b3580b9cdd1676e122 new file mode 100644 index 0000000000..687d501eca --- /dev/null +++ b/txscript/data/taproot-ref/e91b8692e5e50d7452d085b3580b9cdd1676e122 @@ -0,0 +1 @@ +{"tx": "fea3974303bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaf00000000f2daa1b1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7200000000c374aebcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb2000000006b51dbf6012250b200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac38d83e24", "prevouts": ["447672000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "be8e1f0000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "cbfa2300000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090224bf439fe3680c2b2deb33938ad3d8f62744ebc2b558801d3176378115594d8a264e659939d2770dc5147f806da486661c4424f5e0dec5dbc07c2c2d236996e6dd6ccb90b03451784749cbe074d7202f9238e301b7f9d9be57b4e5453e108fd2e90c4980484b324ae4a426d9f130db03c003219fc0fe85e1e9f40cd8c23ac812b66388942d907a364795683cae213ee5b4774e4f6ab09b045af5618a666eaf92862bdef32be8b1028e908240a47fa1283028aa091a903b1e34b094a4f0ed755dbfa3fef595a09d6362e3629802adfe25e87dfbd32951d351000285c6a9b2c24f67ee5b131ab0c2790eb69f5cfd89e3720cf6ce4fc31c5dddefb71161f9d84536a894fede0008c82b8d0f46b99621e50764e84286f972813ddd6c79334284a2e6336da1b85e00e040e006fcbb0474c0ed3dfec05732ef40d4b1b778c64084ebddb06db78cd5db9d9287dc6e11a968849169805c0dcf33a642634beed9469dbd414c184e77ffc60fe95220e00f21e392b71ed8a30743611d7a3c8f19789e24284b874d0bf52facbc34449b0d3b1d46940e1f5b2a49ef635fa77f1c9e743866a0c38dff619cab74787b07ec81d3233c788cdc83fc33f16de981bcbfddb3efef0e4fb4648e9931db1e10fb490b0e26a3f547c7e1d686d2f5e76b8deac447ef7118c131b7c8302952cbb90a184c2ddb086bcdaf77f804c2ada2f49339565125ce337ed9910d5f3ed3f3724875", "187d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082b6019e279bd309d4b7ea698da82947cdf92f55834d49ec05c8520ba423c90b8e919a726f5226a1e5e752df6df7fd59ca609863b1a6d095747bbc103e423fb93280858ffdbef3a81ff8eaeb69bf692b0617d2bdcb9145576d5843e6d9e5e1cb0c"]}, "failure": {"scriptSig": "", "witness": ["4d09020231e986b8d2cc144826b67e819040597933571334414f20589a4272e02b0d2a5bb7e3997e196c6a9cbb0f25ee3a5dd8a3f07374c4826bf097ee885ee5887c8572c7912a5e3be8b0eef00ef609837066dc82d249a2b50a51361d6c86b109531702f2640c351bd8850c276c7dbb4ae0c99832475455544e80e0fba6d9df2839eb18684d63083b32da34d9e5b6bdccc7d316eb92fb2c5bb4b8920bc718148d1352edf5c89457aae80ae3019737a43f5e7b9f5ac29c209368987e043c0f2a2591bdd083e5d61c804e5d7556d03d22a1c4363bcef1a2274d2225da431d6fb250e2f6773c71c1877f97ba98d02c383e1d2297265460b8f50ba0a520b81c419a158932a4380e899cb8d034423d9b37d43c119d63451d4c6da1951ca75feeada9359c313fea859ad7a547648c40193374e3e0ec97c03fe9c409805689bfd59614bd82e9345c09fc64dd6303d5d0dd18a44cc784ff1d55901d900decd3666ef97e1ad9cbfd08e7bb7f77e3b13b6fdc5de36fb5b3b75e2b5fe757b69b669b16c8034bb0b6a77fe1783d35a000e5c115c64dfc4e54270fb523d5dc34007bcf59f6e7a078b321bbcbb826e3a6d666d5c6fbd63cd7acaa140e1021613f51f21d03b85f09df44bae5fd4d127d0c4b217146330caea7dc95dd88912cb5a8aaf5b952e999dd1e8c4910cbee46661ea0c3c029b7f6217c0bdeab00d38a2e98386919f0ebbf07ed7bf90e73be500d755f9a75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a2a72d9a87053684bb0dc48081cf5c5135ec23a32b564c6b97b91a1c581596c8802a37b3510d82dab4bdf4d6195b9af4c8a1df2dd8a601b49dccd2ea1725fb9deb0356d5dc7bb189d5700ce63be65cd47bafc75bda640418bb3b77b52e492b0f"]}}, diff --git a/txscript/data/taproot-ref/e93758815f2e92fcae33eeb424961ee124cec2c7 b/txscript/data/taproot-ref/e93758815f2e92fcae33eeb424961ee124cec2c7 new file mode 100644 index 0000000000..d2a30b4135 --- /dev/null +++ b/txscript/data/taproot-ref/e93758815f2e92fcae33eeb424961ee124cec2c7 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709a00000000122eac46bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdb01000000f84b9d610414df8a000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acc3010000", "prevouts": ["2fb60f00000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c", "e1c47c0000000000225120a607964ea93077ca088588fe8df58ca0f1df7737d7763c94d5c7768cbab371de"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364cbf97bca8f4e93312d4d79f006e70724fd22ee96fbea9c47aa9d0945795d6f1"]}, "failure": {"scriptSig": "", "witness": ["6a9e616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e9501001531cf5569b3b23daa63df0825b2e06f3 b/txscript/data/taproot-ref/e9501001531cf5569b3b23daa63df0825b2e06f3 new file mode 100644 index 0000000000..c6a3ef3c8c --- /dev/null +++ b/txscript/data/taproot-ref/e9501001531cf5569b3b23daa63df0825b2e06f3 @@ -0,0 +1 @@ +{"tx": "0200000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8800000000e5c675c7011a1f5a00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4cf09922", "prevouts": ["cc1875000000000022512020555e2c878e81dabdc8b4bbb4d8fbb562c672b13f4ba4a3f97a1487e7c521d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e8", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362cc5df8a4115da779f8a758b20ada553e9e091a2311498f2aa3552034f30084e276a8166e5256dc9010e53101dfdb6dbd4fafdb1e785ffcbffe7e4bfe923fbf99aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d3d1c8f95326a5f9176c86e1c30427cdf7afee7eae03ceb2fdd83531b682283cf61f73219d91856056394a010eb6c8ee7f13c9683181be224f0fcf47ad20d61b9aaad3e4ddcb787e09feaf57a938d0a46e7e94627a74ec9b410f8a5374ea1d35"]}}, diff --git a/txscript/data/taproot-ref/e98353914c5de48ee650dfff9741c1285bf29368 b/txscript/data/taproot-ref/e98353914c5de48ee650dfff9741c1285bf29368 new file mode 100644 index 0000000000..266cc868cd --- /dev/null +++ b/txscript/data/taproot-ref/e98353914c5de48ee650dfff9741c1285bf29368 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270bf000000003562bfc98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45b000000002c898a1201ae153c00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac3607604e", "prevouts": ["fcdc1200000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67", "58eb3500000000001656142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["1778e6788727fd076d7ad6b184d1c3b78ce26ec25463ec8a133f9d2380a680e0e6c65743b86b754004089f8e9f44fb643ea7ca18f4f397cf9a7576e515133e95", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/e9a85210b1a1018e7666d51f88430bb5d8bfdb3e b/txscript/data/taproot-ref/e9a85210b1a1018e7666d51f88430bb5d8bfdb3e new file mode 100644 index 0000000000..7be16770e5 --- /dev/null +++ b/txscript/data/taproot-ref/e9a85210b1a1018e7666d51f88430bb5d8bfdb3e @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c55010000006d0e8729bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1200000000fec08d1f036360c3000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdbfe094d", "prevouts": ["a0155100000000002251205327380047190b39068e361063e76c0639ec95616567f9015a7792cf50895358", "95f273000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "siglen/padzero_cs", "final": true, "success": {"scriptSig": "", "witness": ["ab8126d03f1f78d9217af03abbd9f6f462a5378ded568ec749eabf659f9b2c895f1922b5c5b86ed28fc30b8fcfd6d05689dec772f11b8d1155ede4ec23d93399", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b7922a9ef31868fd0bdd2720bc44a83a05911c979e226e14df12e43105fabe25154b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}, "failure": {"scriptSig": "", "witness": ["ab8126d03f1f78d9217af03abbd9f6f462a5378ded568ec749eabf659f9b2c895f1922b5c5b86ed28fc30b8fcfd6d05689dec772f11b8d1155ede4ec23d9339900", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ac", "c06caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439b7922a9ef31868fd0bdd2720bc44a83a05911c979e226e14df12e43105fabe25154b26074893c3ce6717cee85a9b2116337c9f3fc57ee6bb0ed20c59821243ce0"]}}, diff --git a/txscript/data/taproot-ref/e9b76d10a6eebe9f37aaf17e3c71921c02524b86 b/txscript/data/taproot-ref/e9b76d10a6eebe9f37aaf17e3c71921c02524b86 new file mode 100644 index 0000000000..6a5ce1013b --- /dev/null +++ b/txscript/data/taproot-ref/e9b76d10a6eebe9f37aaf17e3c71921c02524b86 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9c0100000086f844cdbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf57010000000f4c07bd014c2ab2000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48780020000", "prevouts": ["ab6b560000000000225120cf270920c53765cb04b9e9f4d4bb11730a43c2f8bc3507d6160e85b28c4cc6fc", "09216e0000000000225120460dfd59ffac97f33cb704e62d40a80655c52408ecad6b881ea54a9bb408923f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bf8f72dfad74eb16af74ee8217f4e342864fc9cf9d5e103f73a49ce67e9f6633"]}, "failure": {"scriptSig": "", "witness": ["6a66616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/e9bf6e5a4cbd00e35ecd77dc39c1f9264b9f4dc1 b/txscript/data/taproot-ref/e9bf6e5a4cbd00e35ecd77dc39c1f9264b9f4dc1 new file mode 100644 index 0000000000..bab1117b39 --- /dev/null +++ b/txscript/data/taproot-ref/e9bf6e5a4cbd00e35ecd77dc39c1f9264b9f4dc1 @@ -0,0 +1 @@ +{"tx": "766d60d703bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1201000000da307bb5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0000000000def8accadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba10000000099eb13d001d42a740000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72a040000", "prevouts": ["f9057b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6272570000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "b92221000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_b8", "final": true, "success": {"scriptSig": "", "witness": ["15b241a18d04a42771fec15b73c4db2772fb31e6482de615f9168512d7aed780824cc9984bc28d28cb74bff9e7699d1b2833154cf9cf0bc9c75efb8d59c233e083", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c5dfd59f67ded796f82d56457492083a1d78f992fc728e1e0c10af747e89ab40a5cea1b6a11416ee7d75fb22faf26f82301b42c5d06312223fac879c9c8f6ce9b8", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/e9c730fdf2c5807b82dd1e4d042e404651d4c118 b/txscript/data/taproot-ref/e9c730fdf2c5807b82dd1e4d042e404651d4c118 new file mode 100644 index 0000000000..0806a17dec --- /dev/null +++ b/txscript/data/taproot-ref/e9c730fdf2c5807b82dd1e4d042e404651d4c118 @@ -0,0 +1 @@ +{"tx": "6b2f1e3902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2700000000e8905cd3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4ba9010000008c35e8f9017e2c3400000000001600149d38710eb90e420b159c7a9263994c88e6810bc7445d4235", "prevouts": ["09254d000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "36be28000000000022512081b6fde8d6a32bf994f385f13e2db06adc6a69d3d570a785570e2b0fcec09f40"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["fc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082cb6beef37ee5dce9a0d87dd9110e965067099d7e22847272a5a9481e46004ae8aceb16be1ebf4fc69deaf064fc7bf5d7ff2149818b5ba4c28c799d30ad567cc959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8f9b91a8bd77dea62c47e49d062c2fcfe01875e2df978edbcee5db59c7daa26cb6beef37ee5dce9a0d87dd9110e965067099d7e22847272a5a9481e46004ae8aceb16be1ebf4fc69deaf064fc7bf5d7ff2149818b5ba4c28c799d30ad567cc959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}}, diff --git a/txscript/data/taproot-ref/e9d4196818fdc0fa92415cb4a2aff1b96c783b8b b/txscript/data/taproot-ref/e9d4196818fdc0fa92415cb4a2aff1b96c783b8b new file mode 100644 index 0000000000..8821f8fceb --- /dev/null +++ b/txscript/data/taproot-ref/e9d4196818fdc0fa92415cb4a2aff1b96c783b8b @@ -0,0 +1 @@ +{"tx": "1b7091bf0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705001000000fb6c19bdbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf80010000000a4e7ece028b5f8400000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7e7000000", "prevouts": ["8822100000000000235f212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "1dd2760000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_95", "final": true, "success": {"scriptSig": "", "witness": ["663e41f180a2d9bd4bf89a200f61d4c4041a58022bf544279e89646148da20d87664efef3680cdf50306c8f8892d70a4c1c09213091d01567e546578e1786d5683"]}, "failure": {"scriptSig": "", "witness": ["7b79b0f1b63f68b849e927aeeceea7afc37eadab1d23460c1b0b93955ba450b7648d791bf0f0895de4eed4029e3c95f406634fb10b0d7df8e8f6912437c497ae95"]}}, diff --git a/txscript/data/taproot-ref/e9dbacbd2e05c550b025911cfa3ca5803dae805e b/txscript/data/taproot-ref/e9dbacbd2e05c550b025911cfa3ca5803dae805e new file mode 100644 index 0000000000..c3e32a1d26 --- /dev/null +++ b/txscript/data/taproot-ref/e9dbacbd2e05c550b025911cfa3ca5803dae805e @@ -0,0 +1 @@ +{"tx": "0200000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8a0000000043c498c602dbdd2100000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48736416c47", "prevouts": ["c8ba240000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["3045022100f6e5f8178cd31de7928c8c779f2a0b31b162e144fedfc790a8d0d60cde704fa0022041023acd1f1cca412cd549457cb3c0456ad4a259c8cad4777619706cbb47525b01", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["3044022053ae4374102415afbf1c09363a4201290af1e87883545c7cdb5e7308718185fe022007e9b9d422a093a32c711f698350747391b89fb6f3fd50005bb92adf8880da6a01", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/e9ddf35ff01ae9bc71730f02a17a6079411fde98 b/txscript/data/taproot-ref/e9ddf35ff01ae9bc71730f02a17a6079411fde98 new file mode 100644 index 0000000000..ebb86432ce --- /dev/null +++ b/txscript/data/taproot-ref/e9ddf35ff01ae9bc71730f02a17a6079411fde98 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd100000000e6d2f9d0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1801000000ccd8cab80133f516000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487bf169b47", "prevouts": ["492721000000000022512083c0e539f639337ae8c0354a4e7a9605e4ad1b55261430431fd50e3d65b9e0b4", "7355690000000000225120da5b2ed68dc062d9fd59cecba48d2679c72738370140766f8e961cb8717de4a7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "2b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936135ad0cd7c9b6311df988de8317b2c783507c964445beca4d69314b6889edfdc527b3d6e358222ba6f0d0e44427df3c74648eb5abf60e34311dababed48c5c2bd74d03d2cf0ae79996d1bf896237ca201e78f1b4c5ece550af4c0e01e9fa9886"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a543900b336a3c008870ed4aa640473f983a69734480d339364ae43ad1d21b16885bea8937005622f3eb8b2c440108feebbdb5f3ff09e0402c722754cbcd9b2d195038de5261112827291f7af9c58b034003ed818b7e5ec0d4ccdf81f6c2ea4d"]}}, diff --git a/txscript/data/taproot-ref/ea1fa2cb1864ebe376683d33d94b64f0f54a43dd b/txscript/data/taproot-ref/ea1fa2cb1864ebe376683d33d94b64f0f54a43dd new file mode 100644 index 0000000000..b6c8626702 --- /dev/null +++ b/txscript/data/taproot-ref/ea1fa2cb1864ebe376683d33d94b64f0f54a43dd @@ -0,0 +1 @@ +{"tx": "92ddf3650260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708c0000000087e1aecfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdc0000000073684b970280a936000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acf0000000", "prevouts": ["8995100000000000225120264b35643a3a3a95953dacde7cb6bcfadafc46c4f235409840aae4392ea87839", "9d4d280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a7d0890151f60a75c7483286f2af96bab693a8b52a762410918ebecb67b1fcf5"]}, "failure": {"scriptSig": "", "witness": ["6a2d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/ea224ce2e986d690db2a198af3f98a8408cdb30e b/txscript/data/taproot-ref/ea224ce2e986d690db2a198af3f98a8408cdb30e new file mode 100644 index 0000000000..59f51b3045 --- /dev/null +++ b/txscript/data/taproot-ref/ea224ce2e986d690db2a198af3f98a8408cdb30e @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd6000000006b1f0cfb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fe000000009f41f51201fadd4e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac43020000", "prevouts": ["70e7780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "88ef0e0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d7", "final": true, "success": {"scriptSig": "", "witness": ["49c5480c4e801fb1f08ee5f62d4ad02c1042f28eeb851515c34bed1cf2474cf9ecbd21699af034e64b3498e72b9a37112fbf942188a4161b13cd39b92ad4166f82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0dad9ae1523e8756e95813fa243398e94eed2db1ac8ce3c18982dec25c131cb951bc6428be63ee6512885913cf3f677a20c872dd4dc1888f722a88e51a00a60dd7", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ea3247c42e38f93b6d8af0e43d7f34cc4bc25070 b/txscript/data/taproot-ref/ea3247c42e38f93b6d8af0e43d7f34cc4bc25070 new file mode 100644 index 0000000000..a6ea6e57c0 --- /dev/null +++ b/txscript/data/taproot-ref/ea3247c42e38f93b6d8af0e43d7f34cc4bc25070 @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127069000000000173f79f03215a0e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898736e85250", "prevouts": ["cd2c110000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e34c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f0d1bc393c3c3c2b57b8b86a9e8a64bd1d4b9e0fd1bc4525ebf92e13eb29f90821a06fc3128a9eadf7c181b12783fc0ac677434699a36c8776c14fb861b85f3ba54f7803bb2e93759f587214c70a485617458826e57c89c2ab5c5e7ce47181a1"]}, "failure": {"scriptSig": "", "witness": ["4c52e3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082c71af5165e16a75a4d38ea496516a466796a1cbb48ef44578cf258de537130fb0277e21fac1036469cce09bee47dd6f35fd38d265061a05632a5c9d8280907c6449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}}, diff --git a/txscript/data/taproot-ref/ea3a67eab454450f7603fe0cd98a27c731eb5d00 b/txscript/data/taproot-ref/ea3a67eab454450f7603fe0cd98a27c731eb5d00 new file mode 100644 index 0000000000..2e3e7f5869 --- /dev/null +++ b/txscript/data/taproot-ref/ea3a67eab454450f7603fe0cd98a27c731eb5d00 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3e01000000c939c0b1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3c000000003e7a40d504d3214600000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a603000000", "prevouts": ["72c32600000000002251209f730866f32bab360a89a22c38a65c192ad65d3314437626484a41919647b175", "70d6210000000000225120c08dce064ec071eea1f5304817c49a2bfdceb360f072491bf2d2a32ed65843b9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00638d68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365d51fb579a91f1e7017ad05018cdacf515cd9ac84a638e495c8fd6bd929425d520e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1b25240bc46c035392207c1076e816011b96fc57f286e81391f52d072a1ebea8b62cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08229493e63f0262db246dc905ef3bca459233a7269b5efdd4093c0b189ca3e559193f37adfd687dc0da405a76cf860eea33b50edba83aa9aefe64ccc08331b86a062cab3a6172a7c832406474b8da3677455d75595a690190458c84d19d8a3ecc3"]}}, diff --git a/txscript/data/taproot-ref/ea3f5822d3ff42dc536ca2f868583167e04fcb24 b/txscript/data/taproot-ref/ea3f5822d3ff42dc536ca2f868583167e04fcb24 new file mode 100644 index 0000000000..f0c9f6b888 --- /dev/null +++ b/txscript/data/taproot-ref/ea3f5822d3ff42dc536ca2f868583167e04fcb24 @@ -0,0 +1 @@ +{"tx": "c924110102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff1010000009d574b958bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46900000000c2a4e1b8022e86a90000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a621a7f84a", "prevouts": ["fc546d0000000000165d142540f27e90740933c99d4f17ab2dfc6c82951cfb", "a0373e000000000022512024241b8c28db08f46e2039187a480378b2a1ee734bde764c6e80647709b09b47"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_2", "success": {"scriptSig": "", "witness": ["7def27dab81d3bb1bbe6c4df097458960df6d03b8661956cb1c35d6c5b35cdd1c91ad0f80756ee7390afcc463d34a727db2ef08ff09b798c7f5634eba68ea6c302", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50570a00062fbe5f2ba43c1fb734d7908e3c1ee32333dda1dcec69957da1e118083d167d510ba2bc372333720694bad65a519ca6b72ae91834facc8467645219f5f9d7313ab87c8f2f7079842eddd426ba30b697b28a521993f2980bd50b915a9e61349791576d5c1eac87f44608922d8204938ae3b98dae4182c0dfd7bcb1df466f741f"]}, "failure": {"scriptSig": "", "witness": ["3003e9772507cb0c5e3dd49a5b105b156801e591908408a867c039718bc33807a67e0575fa64fb8b6a58e57e4bc21cbe74594ef8a31b343cf567b8e7c491217b02", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50b4b71b1612e36ab0bf6006d0430e9b1e14db5f9adcea079419cd36c7f5b4145eb349c69f981154e73f7c555dde6b62faba046ede1af79fad4330047697b0ceb6b07d53401b3e0539a2037854f36cab7c38e7"]}}, diff --git a/txscript/data/taproot-ref/ea9383c734b03a942fd3c33b4cd6172b0c606aeb b/txscript/data/taproot-ref/ea9383c734b03a942fd3c33b4cd6172b0c606aeb new file mode 100644 index 0000000000..199e998808 --- /dev/null +++ b/txscript/data/taproot-ref/ea9383c734b03a942fd3c33b4cd6172b0c606aeb @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfc000000001e5111c0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf720000000083aefab460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270490000000053752fdd0376fea8000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987cb000000", "prevouts": ["de10240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8c427700000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "5ba60f000000000017a914a2a8d85df2f20a0aaff7224012fc4cee13e29cb987"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "215f1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["e92b57286193ec8e221ee627b752db89b05173ea63f7bcb01b59aac63359c00bb799c86be0b19a2a62d88f80e8c71158d3d6e6de1692be63f452f9e42fcc640f"]}}, diff --git a/txscript/data/taproot-ref/eaa2ec29b35602bac1202162cc43997d10f21ed3 b/txscript/data/taproot-ref/eaa2ec29b35602bac1202162cc43997d10f21ed3 new file mode 100644 index 0000000000..3ae45e31e5 --- /dev/null +++ b/txscript/data/taproot-ref/eaa2ec29b35602bac1202162cc43997d10f21ed3 @@ -0,0 +1 @@ +{"tx": "5546a66c038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d400000000b5d77298dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b120100000066b879f3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfda010000004fcfbcc7041d3ac4000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf2010000", "prevouts": ["968f3a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ebe5240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d3e1660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_f", "final": true, "success": {"scriptSig": "", "witness": ["7ee81e7753d0ccb087504760ef812f50a1bd452ccd70f0bab9e56546ad5c0f79c9e7c007972f85ef7389f9cc36c701731efc28a2857c41631dfbf9855806d3a781"]}, "failure": {"scriptSig": "", "witness": ["bc9253c658f5096ee1292b9aa93a488d9253a6793ed6b516b66a0e0c4f2cf436c027a31a3a1c07718ed3a4e0e3c17441bdb086f2cc725fd71de5cde56672569b0f"]}}, diff --git a/txscript/data/taproot-ref/eaa7b118760debbe1d5a3d4a62d81d966ab89097 b/txscript/data/taproot-ref/eaa7b118760debbe1d5a3d4a62d81d966ab89097 new file mode 100644 index 0000000000..8d1e7c0ba4 --- /dev/null +++ b/txscript/data/taproot-ref/eaa7b118760debbe1d5a3d4a62d81d966ab89097 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0d02000000419a5faf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45e010000005e59f2d60130516600000000001600149d38710eb90e420b159c7a9263994c88e6810bc72b000000", "prevouts": ["73ad7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "046131000000000022512094bfa417ff7fec0e1f7b84edca83ca6ff73ff5ab901944aa69a26f9bdb9b300a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936175673ced4c1651dc112a32d9e4be1c148bacaad18c2392100569d5094651b3e"]}, "failure": {"scriptSig": "", "witness": ["6a64616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/eab77792be235dec9f3313676498d907e560b5cc b/txscript/data/taproot-ref/eab77792be235dec9f3313676498d907e560b5cc new file mode 100644 index 0000000000..eadb168914 --- /dev/null +++ b/txscript/data/taproot-ref/eab77792be235dec9f3313676498d907e560b5cc @@ -0,0 +1 @@ +{"tx": "02000000031980a99ad1eac101c8fe3dd9b7c19f4e81dda5a690601a9eedc2ce713d9132e5000000000007acc88a492909e056fa5c0ef2af542be68aba07da39583e95b43e24484150891b1d532301000000001ad6d4dc1980a99ad1eac101c8fe3dd9b7c19f4e81dda5a690601a9eedc2ce713d9132e5010000000079e1bbdd02ac0b058b320000001600146d764276c66fec1127e5074db5bff3aa6c52553358020000000000001976a9147d8c30278dcbf5bd88310a3c91abbeb33651906c88acd137773e", "prevouts": ["7371c1150f000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "b7e4d4f711000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "6689717d11000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/keypath_empty", "success": {"scriptSig": "", "witness": []}}, diff --git a/txscript/data/taproot-ref/eae489d9b326b6e764166ddf53140f5ddb3b425c b/txscript/data/taproot-ref/eae489d9b326b6e764166ddf53140f5ddb3b425c new file mode 100644 index 0000000000..8e81cc7693 --- /dev/null +++ b/txscript/data/taproot-ref/eae489d9b326b6e764166ddf53140f5ddb3b425c @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ac000000001d48c503dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5b00000000989542d002fcd25600000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748795010000", "prevouts": ["0bce3100000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "9010270000000000225120e3b65a069bc68a4d57751d6a27b5b12923d0926a31ec4185f6f10a22de1840d8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "2c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a969cf06ec193d0358c31c8afad5bbcd547aa0657673b5bb10a44e38c372c44cda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef5981cd58c469d4842aa56f101a76a4447dba55ab7a128197943d7701f95f2823b7ec1fb3aca1c665feb629f75b86bc6796ed5eb830658d68574ea157b89fde9"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667e3c1aa8bd39d6182a2299f940d076e52caf4ade4a085ff8961d11623e68188872b08559f184ac3ac9956d54e492d7f98285a254bf010e00b63b6bbe75054353b7ec1fb3aca1c665feb629f75b86bc6796ed5eb830658d68574ea157b89fde9"]}}, diff --git a/txscript/data/taproot-ref/eae7770e2a494f15bf0e76460740c8d2e1cbd22e b/txscript/data/taproot-ref/eae7770e2a494f15bf0e76460740c8d2e1cbd22e new file mode 100644 index 0000000000..0a8d71d1d2 --- /dev/null +++ b/txscript/data/taproot-ref/eae7770e2a494f15bf0e76460740c8d2e1cbd22e @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1d02000000a05c23cf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e70000000024c7cacb02189b38000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df979722368987a8344a32", "prevouts": ["0e0e270000000000225120d822e1bd1f5ea10d0aa44b8067d00045600d13617c1c35db91f3c0990a68d49e", "ae3f1300000000002251202ba931d41ccae6aa7348a9ccd120452bafbc02325d8b1badffbe10b3b20f3d8c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09021ad436a62d53c1e9319a4ce5c1f22396667078af1f47c4295f505e3f973743d30ee347cda830f26acda70755c08fe8fe809efd6bf4d50fb50bb6cab9862d692f901ae3b974b43b1a3509f3b5a6305047a85308f2241784bd16da924f98f87441592e7090afa233f3924b55d0ab8345968af770b69dfc48c8cab765a259fecb5a1c15b649498c70f518e51b9314474a30a13b53e9a1019ef417e2f59a4ec649043913cfed6dd77dc54554304778e1596bb7747a68f5ffb9a351652787224c93546bc081171e714bd6464ccf1ade083d261f187d437347b1070252599d748940d79bd76da40515e08b87ccfa60023fe737bee305572a2fc9e6c177d68afea91503bb63b7ec19570ea0f3c02fb839f9146b96a230bb94dd9a7c2b2ca6c6553f0b4c2af42e56face25fc9395285df0a794712bb7dff2d372032f836dca409b5471263a02ebc504f781424bd16510f596de58555c2439e1f0ed712522d71506c32e5d9c964756eaa8a2f091525b5f8cd129d00f7f89d68170159159f5159742c592c36ec96afdf51d788255af1c796d1b5e67dc4894fc1a70814d04190ea9b0c50a61d73182f02f23c7bc47a509cb0d7621b7af18d7c4bb71ceaa5096371bf205f5ed8a7960d2fdb05b026261196c580377d61c36c349b4af12b2b95c666c54b115a0796dae0418854d5d3bc10757cfed63ecdbcaeb7e338e987d85eb7ba658ff5f38426511321a9c90f7bc75fe", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b65fb99ebaee40b89c75f91c70dc33c0629af8f94b6b045d23ce00b5520b0d89fd22261ee209e04df9662f52c9dcffd1f6e65f5b546fd3c131bfb02c186b05f664ab0b66352e66b5bf600abf31d1005c5406f4575b339026213ecb21a668977f"]}, "failure": {"scriptSig": "", "witness": ["4d0902deed117a70cbd602036c28373d45eb7eacc1729850a732356b2cf078735f228bb5dc16f032ff691f9aaefaa3332955f92a97507674d0f7b9b85b3850d0c1470082093787ce4c067d246ca53514d9519126e256d2e7e98dcf57577435cffee9d7d84ff3fe0dab92d2e8def38e12721755d17b7399cc07be1a89caabaf12b35df57a10e5c92e34989f5a0be6224e9568ebc8d6878f71e96003633177fac5b6e9a83b340a92170370da5e5757b7711188aaa7e5b87b03603a7820181ec0d95de1bdb2253c2db801ee942edb80d410a718077d922bec63c5b18d1399b3a1a86c5c5636032b93caef8ef2f74d21808ebeae118b386709b5b5f3f794f72e6ecce401a2762b29b8c3c66df0bcfb9256bbadbe48dd9dff8fbab1418eb225189c557fc67a0aaa9baf5a1b08545cf1edaf2a5c433a495316c3a5ef7a41064a21c45cf1396b2c934c1b486b58122c278524ada0e13f3cfc3c97c7cc8d0623b5fcf85deb1a820405f63fb9dd3b9fa8200c6ea621a3fde93e2ec514574b7b6fa01b0d8bb1f17e13c8430f11abc978eb1dd0a7a31943c8530861fa00112781e792087e25a455074616fd56004ca29d8643aafcd6b61fe71685d76dbb96e0ce3b953cb66e1bd0380122a1aa2717079f03d68aa095134663ccb99df295bf8717d2a0deb05e38431e7af30d25b8eb0cb0ec87c49c4c4fc18355edc6a83b816e22f6b5af6621cb3e084ffec8bf5986e0abea7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4dcc932fa7eab9febb69f8eb1775db86ae183d64bb0b86855f9228e743b2ec6db917e8250b412828d56f092e1d9ceabdbedccb5671620a7e05a1f5a122fcf72f11e45c38e8a62a0e5058038ea76117f85fe5d704aefa5d806bc1a7cbe3a990946"]}}, diff --git a/txscript/data/taproot-ref/eaee09f4a0e178165105cf2ccf81513fc80541b9 b/txscript/data/taproot-ref/eaee09f4a0e178165105cf2ccf81513fc80541b9 new file mode 100644 index 0000000000..ea57cf382b --- /dev/null +++ b/txscript/data/taproot-ref/eaee09f4a0e178165105cf2ccf81513fc80541b9 @@ -0,0 +1 @@ +{"tx": "0ffdd2c802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa301000000e046c88abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3b01000000c75831b90470e1e0000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac68aa0452", "prevouts": ["a79e7f0000000000434104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac", "da1c640000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["ec4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd4d99442df2d897dc88267982d8eb20b7dde930eaaf897e66f6a5ce7f7a19008bc5bddb1ae8a97e111feaf10767a648ae88621f6e3dc27f3d4b61f2a6f156b2a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d686773729ee45a24450fddb7da6d0266ea60d425b2bcaf3694e59ee80e6a1a3dddfc46016955cd26bcdfd077adbba0d60eefd6e0317def1b858595de21efb103b719bf4b6df334f4ad3966afd516fb2a8d294cb4fface4e4609ab1c9f988c5a"]}}, diff --git a/txscript/data/taproot-ref/eaee80bfbe65037b08eeecc39e40e2b8276a958d b/txscript/data/taproot-ref/eaee80bfbe65037b08eeecc39e40e2b8276a958d new file mode 100644 index 0000000000..5283649e20 --- /dev/null +++ b/txscript/data/taproot-ref/eaee80bfbe65037b08eeecc39e40e2b8276a958d @@ -0,0 +1 @@ +{"tx": "32bd0f0b03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7301000000a2d6c9c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a100000000c06b56c760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127000020000006321a4850146cb4d000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48709ff9333", "prevouts": ["03b67e000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e", "f22b120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "802711000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sig/flip_r", "final": true, "success": {"scriptSig": "", "witness": ["834991d8360f77f5e8eacbfb2dd7d75f47d7e3c31e3c59d47f21d6a50f84c8d39faf86705135d7e0acd121dfa01f6e118c9d093b26d8e923c829c9961f595d9c"]}, "failure": {"scriptSig": "", "witness": ["834991d8360f77f5e8eacbfb2dd7d75f47d7e3c31e3c59d47f21d6a50f84c8d36177dd7e4cd5d9b381bd755ddc4cf098a8e29a5bd0f0f0e7bb744408adfc1e1b"]}}, diff --git a/txscript/data/taproot-ref/eb0e20fe944dc77d38b2fc2582d02c80d3d9628f b/txscript/data/taproot-ref/eb0e20fe944dc77d38b2fc2582d02c80d3d9628f new file mode 100644 index 0000000000..deee2387a1 --- /dev/null +++ b/txscript/data/taproot-ref/eb0e20fe944dc77d38b2fc2582d02c80d3d9628f @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2701000000e971dabd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e601000000fb959bc7028d473700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a660000000", "prevouts": ["241d270000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "0c0a1200000000002251205ac64cb5aeb40708d1f7499406291fd8487a0b8d6b028f8783495d150925a7bb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "e67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9b5783d82402a6ca1f9b43e9c3fcda656bc8f4fc44d071b6c51ae46a253cfc5e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e824d900ba5429999a9d5e0d5b2b257ef1523eacccb529e56e7cf347f802d02f5093d03784866e2fdd94d7d1b7c12b1f0da96746c05c19b8696f0ac6a701ba8135"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366a6713437001d677a136bbd3fc0158159f58de7b5c6a1fb5a4ed17480094b62285f665641dd2adac3083650f9d93a4e0ff6d52a887a3a3677c2728d09852a8a99d11a7792f25f0da70e8485da42647201d1062d1bd001b767f1b05dec6877400"]}}, diff --git a/txscript/data/taproot-ref/eb372b84ca640e23188861d0efa04be45ee5f243 b/txscript/data/taproot-ref/eb372b84ca640e23188861d0efa04be45ee5f243 new file mode 100644 index 0000000000..8603e79b81 --- /dev/null +++ b/txscript/data/taproot-ref/eb372b84ca640e23188861d0efa04be45ee5f243 @@ -0,0 +1 @@ +{"tx": "e7e3b9f90260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c80000000068e24fd8dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9200000000b1a782c802e7456700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33e6a42c", "prevouts": ["d19c12000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe", "fe5b560000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "937d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef65737139d8cb51b826e6105ecbce8352aa10f0d50686f2268ca6d7900ff7d4462d371a9b01f30ea116c30e8195d2d6eb7c97c8692c0c95de95a904f83b96ad4"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e88b73eb14a8afa044a1a6f0495df635bb2745ae30a5fce84d6222f661b17136fd6f60e166ab3c31d6fe53c0e4c47c333102fdf48f7428a1dab907384d3ec09a32"]}}, diff --git a/txscript/data/taproot-ref/eba9b48ee4b2ed1d213ff803ba46409241800f53 b/txscript/data/taproot-ref/eba9b48ee4b2ed1d213ff803ba46409241800f53 new file mode 100644 index 0000000000..06331a9d2d --- /dev/null +++ b/txscript/data/taproot-ref/eba9b48ee4b2ed1d213ff803ba46409241800f53 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4de0000000065ee38b08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42b01000000779fbafc031c5471000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987fc040000", "prevouts": ["a15c3f000000000017a9144582b7676ffb8c3a2735b8e71e172a272e3e33c087", "af4434000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "215a1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "witness": ["008cca768bb80d31843d8ca0979e53192231a3c965cd8573f4fb822896e85d7ad2957dca3b910c03486750e7923d63faaff2223f617f604bcef4d53f1f51186d"]}}, diff --git a/txscript/data/taproot-ref/ebaab3cbf799854c56be5ea1c8570b79e12530d3 b/txscript/data/taproot-ref/ebaab3cbf799854c56be5ea1c8570b79e12530d3 new file mode 100644 index 0000000000..8151a63e87 --- /dev/null +++ b/txscript/data/taproot-ref/ebaab3cbf799854c56be5ea1c8570b79e12530d3 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c452000000003b7dd6d08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41501000000cf2ca79e04c0e7650000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e702dfca59", "prevouts": ["4fb5330000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9b2335000000000017a914a7d99db8790799e567017bcc9951f7f968dba70f87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ca", "final": true, "success": {"scriptSig": "", "witness": ["a0f00d6cfeb7232a691f0b4cf5b04549ce7c7572d39c059f9d59628de33704911059a1f337e9f2b018e186081c7cf7e05102c78f3e49650f2bc272cb47f32e1b81"]}, "failure": {"scriptSig": "", "witness": ["0b5b72be3d24ae132681bfde8ec47d85c7baf8f1186e01a58f415295a2a0a89530aaf42be4ae1f4617033793b95600f531d4294b7b325eb3fcf896042307677eca"]}}, diff --git a/txscript/data/taproot-ref/ec0558d3bd9826dcf5a547231702b26bb029d5b3 b/txscript/data/taproot-ref/ec0558d3bd9826dcf5a547231702b26bb029d5b3 new file mode 100644 index 0000000000..dbf2582eb7 --- /dev/null +++ b/txscript/data/taproot-ref/ec0558d3bd9826dcf5a547231702b26bb029d5b3 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1b0000000022e6d7a8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc401000000b2de69fa047e0aa800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acb1040000", "prevouts": ["39ea810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2995280000000000225120fd40216dd29fb2eecdff7e4128bba3cfbee632fa2e745a84c0cfcf3475ca43df"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_5b", "final": true, "success": {"scriptSig": "", "witness": ["ba3b0ebe67469642f50db51902a0e1f5eec5fc64bd8288118523f2403de23e5bad9391ee55fc1da552c25e568d95398e0d709c78b78f2e04f8dc95a889d317c703"]}, "failure": {"scriptSig": "", "witness": ["1cebfa42f618d7ab09b669150af2d6b37e3f6f0dac9436c45197094568aa0183a3391348348341e268761460e4eeca8b264a2e5468e0a12c75db604f94630f685b"]}}, diff --git a/txscript/data/taproot-ref/ec11e48dae90b65ac226a309a6ab974cfc87474a b/txscript/data/taproot-ref/ec11e48dae90b65ac226a309a6ab974cfc87474a new file mode 100644 index 0000000000..b47341871c --- /dev/null +++ b/txscript/data/taproot-ref/ec11e48dae90b65ac226a309a6ab974cfc87474a @@ -0,0 +1 @@ +{"tx": "ae141b9f03dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bab000000003d92aca3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0d00000000851034978bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c445010000004f05579f031209c70000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e741700146", "prevouts": ["27c222000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e", "30c5690000000000225120216a7619bc8bfafa3d746edfaa5de0aae98c6d9b6031b40cdfc5f53f6bfe1b1b", "23df3c00000000002251209afd231cc3806be681d40ad69b07250c6c3c148fe648fcc127815dce6f5b16e8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "1d7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369cbf82e6b81de47b655febedbc15934cca8850242400ffe44c9c244a6aaae8fdc92cd4ecb05acffc69b3cce67f0fe15bd50aa9f87096dacf733b4583e5e3d147ea37f54c31b0dcd6e392a972a33f542af4c40de53091de86bbd5587895c52a53"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ea680f8e17236a8fbc1196317399c346aeca722ffefcaac5ef62e17ac4625d25b4bb2c7d85af23cd06361a8d9967d47c0827d7b479cd52e2216fb2d12a2ff38bc"]}}, diff --git a/txscript/data/taproot-ref/ec236a1ba693a15d7cd145cb072b03a9edafd25d b/txscript/data/taproot-ref/ec236a1ba693a15d7cd145cb072b03a9edafd25d new file mode 100644 index 0000000000..4f5726ff72 --- /dev/null +++ b/txscript/data/taproot-ref/ec236a1ba693a15d7cd145cb072b03a9edafd25d @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f100000000f59b89c58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49700000000fbb20ce604dacd49000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc88977143", "prevouts": ["5b30100000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "0b153c0000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364e1c80865788996a05c5a9f6b0900b0096f6056de983ef887886ef5950a10b0c0d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3ab0398bc4828dee75def1007ce877d708ab4ca86c9734bfab291d4bd05bae3eec1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4aede7f6feac32430a03a6fb4ca18c03b66145006034584e3a19904465ea1e66424cf807c4b041deab506320299ff116921971164ef72b2742896e58a89a98f91cdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}}, diff --git a/txscript/data/taproot-ref/ec2d9171350303a508d3a35306e1da95e2d45a8c b/txscript/data/taproot-ref/ec2d9171350303a508d3a35306e1da95e2d45a8c new file mode 100644 index 0000000000..2141241fbb --- /dev/null +++ b/txscript/data/taproot-ref/ec2d9171350303a508d3a35306e1da95e2d45a8c @@ -0,0 +1 @@ +{"tx": "7fe69d4d0360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706601000000d2634dff8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40401000000a84fafc5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0002000000b17c94b301c64a37000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48713020000", "prevouts": ["0a4311000000000022512023961a2514901a699ec375254af5daca285299be5db377524e8c4f227aa80aab", "feaf310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8d227a000000000022512010c0a77c04a6b5898371cb41f56ff3be56bbf4ef28e67a70faaf4ce5d87e562e"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["8e", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d512a2ca63ffb455d99d5e48d0ce26693d60c39456d7af39366f9ddaeb418e2954f33cd0b31c9bc4dfcaccd89caa263c020d1b70f58e7e0e884ce19a773d6b5f30b2981ae69232c3f6c5ff759e9ad4102f31f3fc5e7a3a4ffd34dce2e2e06026"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045df5339745586104756c1fc6d4b54e2b6a7d81daf8b03d1fc2a4a51881171d1a3099eb053c54d8f72c6d7331f9a1bb3bf1b628df692ad9b7eecd4e01f4a47bb5aed4b6001a8fdeaa28275cc8a939e32dd3c3fbbfbba5c677bbce429d0c1a1675d"]}}, diff --git a/txscript/data/taproot-ref/ec3dc1b7325240192c1e37e75c29831fa68e98d4 b/txscript/data/taproot-ref/ec3dc1b7325240192c1e37e75c29831fa68e98d4 new file mode 100644 index 0000000000..e09a66e44d --- /dev/null +++ b/txscript/data/taproot-ref/ec3dc1b7325240192c1e37e75c29831fa68e98d4 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270350000000098af0dd360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701f00000000ce699485013f66180000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e77b030000", "prevouts": ["54ae1000000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "fe110f00000000002253202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["ec706e6205a2d2f4858924a5688a6a1063f32ceab6133572aaa27d1da6be3d420df0d865f9aabc3f9efa2ca71feaf638b96c1c3a5c2e66d4474fbfe5471820d4", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/ec4c99541792d43b2c11d31a995e9d4e6494735e b/txscript/data/taproot-ref/ec4c99541792d43b2c11d31a995e9d4e6494735e new file mode 100644 index 0000000000..da5e5c3c27 --- /dev/null +++ b/txscript/data/taproot-ref/ec4c99541792d43b2c11d31a995e9d4e6494735e @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705800000000d62312c4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e01000000c89799be02be4f63000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca4226936", "prevouts": ["69e00e0000000000235d212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "ced55600000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "483045022100b7da1733a408d387bdfad13a62e1e4790313d9eaddea89f8b07588dbefea6c3d022055dbdbbdc8f09652590d5551affe85bf7b4ea441afe925b3585f63e008e40570824104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "47304402207ac9f2de3e9d9c53bfbc1e22ffeb93c2f14a38f3f022c1e3f3c0d8a63fd47fc10220286a8e54ad5b85f671dd214b551b08b973c5b4ddc9d3b04ce84c9a168f9fad40824104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/ec5f10d715ff4121c9af8001b65d91bde62f884b b/txscript/data/taproot-ref/ec5f10d715ff4121c9af8001b65d91bde62f884b new file mode 100644 index 0000000000..347634aee7 --- /dev/null +++ b/txscript/data/taproot-ref/ec5f10d715ff4121c9af8001b65d91bde62f884b @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfff0100000064056d8d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700201000000167321d8034e0186000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb31b4546", "prevouts": ["9f5278000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "368c0f00000000002251203dc2472455090bb3a6b10d2b5a6f86a9b76268c5f2a3511c1c846486e45d4259"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6a84", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0821ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900459910ef1376b2f57d6157bb9e8c31b4bd4b9d07432c4b683bf27102948dfaafec7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fd5c0d5bb068ac75772b5a2ef9617f963c08904a0623a1a21cf299a7cded424b120199479ee6d2d4c88363683365d3fc0e890ec8511afbf0335c75bda2c0295827135a2a7712dc4ffb0f490ef0a9e18994dae8053f69b06dfd6a349e2375b7df7644b3dbe2d9311c88339dffa1c0be80a46778a5837645266f0e84452a246701"]}}, diff --git a/txscript/data/taproot-ref/ec7ac5952f631f170c9cf5ab7afb10a2800e3be7 b/txscript/data/taproot-ref/ec7ac5952f631f170c9cf5ab7afb10a2800e3be7 new file mode 100644 index 0000000000..d52e402cad --- /dev/null +++ b/txscript/data/taproot-ref/ec7ac5952f631f170c9cf5ab7afb10a2800e3be7 @@ -0,0 +1 @@ +{"tx": "ce0f492d02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be2010000003249bdd560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c501000000dac634860214d03200000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88aca6414d55", "prevouts": ["f6a9240000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78", "23d00f00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["cc4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688e21e0ba4623d9f1238b4cab1fe6058b8adee7f586c209e41396c5ed78664fb1e80b1f8b709fd7e9f8915460d72d278aa0d12452680dedc295e1cc62d069d9c5f8b38696f7f521c781f821b55aa4ff86c04fbebd102ad129a9d47907becd36b4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe06075904b2d09b06d544283b5ed7948355e691785c7b3e1a952a1a705151fec890db8e530b3b97e91b56063afadbbd8e6ac326e3356562c0a5ff1591f041d611c8e78922f12cf5b391747592eaf9e84d545161f4f09ddc8c51091bc04ba49d4e19d3b2ec28c8925d54c04f383936b915813fb16b738060565344c47074fe42"]}}, diff --git a/txscript/data/taproot-ref/ecc052cec3d69b0b941945fcfee7fcca160fee0f b/txscript/data/taproot-ref/ecc052cec3d69b0b941945fcfee7fcca160fee0f new file mode 100644 index 0000000000..c56090d149 --- /dev/null +++ b/txscript/data/taproot-ref/ecc052cec3d69b0b941945fcfee7fcca160fee0f @@ -0,0 +1 @@ +{"tx": "77f1ef930260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d8000000007f6b15fadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7801000000785a0adb01d6d25800000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac0f040000", "prevouts": ["0be812000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "b5ed5d00000000002251202b9c9277757683e3a6231ec9844202804510fe71120186742480ec3d3f4624b8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "907d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ed16c11561cb4e52cbc61ad76d34e49a6feea77f682efcf50ee22f89bd1fa0f0da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71eccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457ba4f11ff80ca9181e3d85997fa959accb8f97af45a52bfd0df916797673441f5"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa51b810e60c043042e0bb2eafa8cecc8c22fa830d489bdf7de51e14fd273b03e0ba4f11ff80ca9181e3d85997fa959accb8f97af45a52bfd0df916797673441f5"]}}, diff --git a/txscript/data/taproot-ref/ed414b2d37754fddb26883baa6399318c130524f b/txscript/data/taproot-ref/ed414b2d37754fddb26883baa6399318c130524f new file mode 100644 index 0000000000..d34b2630f4 --- /dev/null +++ b/txscript/data/taproot-ref/ed414b2d37754fddb26883baa6399318c130524f @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ceb00000000ba7843f08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b5000000008141d6b70267698d000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966df5ad4e", "prevouts": ["fc6750000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838", "81bd3e00000000002251204f36246572598982690fae3c78190d13eaf0433be2e576bf73c1db563e0893ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "c77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936685ceb4100efa5e54cc068990ea9a5bf606617cab6629ff60e87e062a72f36c14639ba4332756735e08e9dd0c9395e600a8a67669bda3acb22644b013566df80a9fad2668c863ea9bd6dd9197c1c49c61c2b9d7888bac8bf6fef03fc3ace0a5a"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ef01d0d256ad0d229e53661481dce388404558ec2529e0bc1d85e0261a585159aa9fad2668c863ea9bd6dd9197c1c49c61c2b9d7888bac8bf6fef03fc3ace0a5a"]}}, diff --git a/txscript/data/taproot-ref/ed5648d424b5a21a684d02bc55bdcfab06ec276e b/txscript/data/taproot-ref/ed5648d424b5a21a684d02bc55bdcfab06ec276e new file mode 100644 index 0000000000..26154edec6 --- /dev/null +++ b/txscript/data/taproot-ref/ed5648d424b5a21a684d02bc55bdcfab06ec276e @@ -0,0 +1 @@ +{"tx": "7712fd3c03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc600000000fa2131a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3a000000004f6247e1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff3010000003fb10ede01318d5900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac50880832", "prevouts": ["21d5720000000000225120d8356a7a267600b4bf6c9db376097dc60a7f0eeddcdf6366770ff3523c8fa4d0", "a3c12000000000002251204e4a8cfe4f68f657f81d61368182a9dc3b463ed6fb97449e34c0870f4967da87", "1de070000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ff7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936422350ecfc721a5c21c0cf4040c9c5a64d0462da5ea720aefe426d2501e13eb1f27794099b656b9faa6b5043ba50cab982b2292ed8155b5f0f6568a958ea63ad187b9e30f7e626b28b6dbe2d7b101f74e326290698090dbb0a7eb7a50daae87a"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361c0123a470b1883e55ff9e366e23b08502d89d95970981457b7d383b3cec07169987eb7009ccae8c65258c62e5eac53ed5016922d24407b897adc5526f33b91916c082ffd0388de178727289f9edc245ed8244bc4e4186d1c7a66ea621fec0ad"]}}, diff --git a/txscript/data/taproot-ref/edb0a385324372442f7d831b7fa747c2a2ba5d40 b/txscript/data/taproot-ref/edb0a385324372442f7d831b7fa747c2a2ba5d40 new file mode 100644 index 0000000000..1364ef5f22 --- /dev/null +++ b/txscript/data/taproot-ref/edb0a385324372442f7d831b7fa747c2a2ba5d40 @@ -0,0 +1 @@ +{"tx": "c44943fd0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705e01000000f83269838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40f01000000d07eb1f80331d14800000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc15bca94a", "prevouts": ["76f80f0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "dad43a0000000000225120c5051fcb1fbe13589a66714c26f344d0ddde4ff1aaba22c9e96bf2d553f61a5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["c5", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5115f1aeabcd45f20884fa261b27121b1c083fa5a2716bfd01069fab98e18c3b0e4b23f991898c0f7e80b32f00b838c1f1514616fab2a47083539335b67c2689fcce4d7767c8a9637a0804b073b1eb172c67de67ce152ade33f2591a85dfee2e5a"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936811133f2935f27641e5de866d6b2526674271c11378ecea72e02f5c1283f85606c8f4b27179de8a3c9fbcc0ecf825a44b7564122e0508108d3381c6acb047da700a5530ec2a7d4ba868ec61eef99b13bb3328da6d520ee28822b8288bba3da4c"]}}, diff --git a/txscript/data/taproot-ref/ede245d24c4ccbe651f556667d1de8b18984e6bf b/txscript/data/taproot-ref/ede245d24c4ccbe651f556667d1de8b18984e6bf new file mode 100644 index 0000000000..86aad37fa3 --- /dev/null +++ b/txscript/data/taproot-ref/ede245d24c4ccbe651f556667d1de8b18984e6bf @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff201000000a1f5ede7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf510000000013f48da304ee0ee2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e727585449", "prevouts": ["1d666800000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "adb67b00000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "ae7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ee4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8b509ab67bbf3c81955fa9e200008a666546f84b8be37a00b57f87c80ceedbec790189ee9b6b94816743a58868693b6f0ba58cb07e4c6d5ed2ce590077e887d5b"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ba812021bec55125a4043e092087428314c694c64b021517d83eab825dad5a3d31f1765c4043c65869fc44409698468cef1d88a3aab3981df946f88d25a1c2d5c67b1d078674a4d97323398e107b13ccefe9299bb9116e21f935c64f37bba24f619c7e3fc3d0f43b284295c7c76b7ff66dfc7bbdbc495ce3e8e20608c97360e5"]}}, diff --git a/txscript/data/taproot-ref/edf48d71ea536f47f2ebae0ef4c1a54805cfd2bf b/txscript/data/taproot-ref/edf48d71ea536f47f2ebae0ef4c1a54805cfd2bf new file mode 100644 index 0000000000..20f839dfe7 --- /dev/null +++ b/txscript/data/taproot-ref/edf48d71ea536f47f2ebae0ef4c1a54805cfd2bf @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf9010000001645c582dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1802000000937c02e50338aea400000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a62e010000", "prevouts": ["a5fd570000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5", "f4774e00000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "b67d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936377fef4062e93837ddc7af9cb3191f24f01157283f139309bedbafa016e9f95119cfe9d552d59ccbadc4f3846c4b5c3686f3389826ed032a892d1ca338e6ba63ca37f8027c2c0b0d436eabba5be8b19fe8a47d5b17abeebfa31c0139f25f704791244d1d955381053a5c36db6928ef13bb9242569ee84b58d7018329936aac78"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fd848df663f65f0e27b2d1567423d7462b229bee90dcacba8c1bf1c1a66aca7f6821d9a3f11774810afeba87c9188100d693899e640a37210c96e3be6a00ac01d4"]}}, diff --git a/txscript/data/taproot-ref/ee216fd86ba1f2f2eecc6892dba069f1fa7e2566 b/txscript/data/taproot-ref/ee216fd86ba1f2f2eecc6892dba069f1fa7e2566 new file mode 100644 index 0000000000..c92bd64675 --- /dev/null +++ b/txscript/data/taproot-ref/ee216fd86ba1f2f2eecc6892dba069f1fa7e2566 @@ -0,0 +1 @@ +{"tx": "a812a8340260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127011000000001b84d5c560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b90100000047458cbf0119a31f00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acba000000", "prevouts": ["7909120000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "c8670f00000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["ed", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08220e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e179a506f75037c50a9ea9c509d8c41e46c95fdf651773b41e5feb3da8f515025ffd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364239bb564bb88fab9cc8a68fc985ce74d0a60efaac94a2193d617d4650dce2ca20e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e179a506f75037c50a9ea9c509d8c41e46c95fdf651773b41e5feb3da8f515025ffd4cde6e083ceefa41c970e7ff247f88d4db270a866c6958487024deeb358702"]}}, diff --git a/txscript/data/taproot-ref/ee227dd2c697b5ad500c732edea24bd9f2ec08a7 b/txscript/data/taproot-ref/ee227dd2c697b5ad500c732edea24bd9f2ec08a7 new file mode 100644 index 0000000000..f0478cfb27 --- /dev/null +++ b/txscript/data/taproot-ref/ee227dd2c697b5ad500c732edea24bd9f2ec08a7 @@ -0,0 +1 @@ +{"tx": "ac8ef70c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f500000000cd6aca99bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1002000000166066d902baef900000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf8000000", "prevouts": ["a32e1200000000002251205e6805afb6d033a5c8eef8d51c29124f559c62b172323155929ced7c3b8e8a62", "c53281000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "387d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fafbb5a1fe7b9516d3f9237414125c5ee80cc77ac3c2791cf19c93edd24acc7f158fa601fcc68a78472d280e0a6f10ace0c22dad9ad93c154f995d1132d7b2f793"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8f5321bd3c280560a6e93f009006b65547a58d72ede42c89f2f760c3bf47a1d1aa12168afdb4ef286e7748ddb08cf408d85b089f504486378d2bfb535c0d2875b"]}}, diff --git a/txscript/data/taproot-ref/ee39d37f93b56b4c318cb83ca60e411ee5c1abbb b/txscript/data/taproot-ref/ee39d37f93b56b4c318cb83ca60e411ee5c1abbb new file mode 100644 index 0000000000..f2240b1bdd --- /dev/null +++ b/txscript/data/taproot-ref/ee39d37f93b56b4c318cb83ca60e411ee5c1abbb @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127052000000000b665d8edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c200000000084914c6603c36969000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7a37d794a", "prevouts": ["2f9e0e00000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d", "ceb65d0000000000225120ef9f6a66884775055065a73b34ff9ec529e6bca309e0ee5458de4d1e99086d65"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["df4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936be89d319d8869e9bf9ae746cc5e400e37fd9a102b3c132ccd07930db67bce60a51d880cc047c10a424f65fe9dd9096492f3efd8e08517d04362957faed36c3f852ff338358c59a252efd0a17af70f1cdfe194eb24c5d50483b26343bf89011bf"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365bf630a53e970a0c3ed444d8048d7a9defb53d27fdc7ed055594eb691fbb1ea35385991a3000310359e2a9adae84589f286ca8f4d4476598a0e772bdb8ecbe6352ff338358c59a252efd0a17af70f1cdfe194eb24c5d50483b26343bf89011bf"]}}, diff --git a/txscript/data/taproot-ref/ee4391649d8b6cf1ed2a18eef419b54a19d2f481 b/txscript/data/taproot-ref/ee4391649d8b6cf1ed2a18eef419b54a19d2f481 new file mode 100644 index 0000000000..f9f283c7ac --- /dev/null +++ b/txscript/data/taproot-ref/ee4391649d8b6cf1ed2a18eef419b54a19d2f481 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ef000000008cdb3d2f8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4740100000070de6b5704c11e770000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7d5000000", "prevouts": ["21b33d00000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "6ab93b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "ae7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360ef4bc0489494d72e70e64b388972e514562ef0f037a1295f9b046f981a6c54ffc0ca702511f3076acdc40632b43a1d65714ee25a695072e4ff6818d06cb6b94619c7e3fc3d0f43b284295c7c76b7ff66dfc7bbdbc495ce3e8e20608c97360e5"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8acf455c5d2fad677c631ef590e33b043ac89ad327665e6cf9d96250341867de4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8b509ab67bbf3c81955fa9e200008a666546f84b8be37a00b57f87c80ceedbec790189ee9b6b94816743a58868693b6f0ba58cb07e4c6d5ed2ce590077e887d5b"]}}, diff --git a/txscript/data/taproot-ref/ee4b75d279f94af5208664797cc453ca45044806 b/txscript/data/taproot-ref/ee4b75d279f94af5208664797cc453ca45044806 new file mode 100644 index 0000000000..87e4b22329 --- /dev/null +++ b/txscript/data/taproot-ref/ee4b75d279f94af5208664797cc453ca45044806 @@ -0,0 +1 @@ +{"tx": "dc7f15740260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705f0000000035065d94bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfce01000000f213c3dd049fb7800000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796be95ab32", "prevouts": ["b8bb0e0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93", "cab3740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "747d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdbf4492fa00dc56072e72009d776219274bea6eb51adb458249eab71940c27cb4bfbb1ef2412aee06f4b75b9e20a72d4d9707545a4ae77abc538f76b00105406a"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936740c20c98eb602ae4e7ad05a38b8b2af7b596435455e1533be50f503dd72332ccff906089186a2156752da0c3c16267cbd92a27eecc3bf322cbdfb883eaa82d667ed562df09fa99b9816795ca593030d6e2a26df3d36427b327259a2f453cdc8077aea6ccf316b47e40a0e3636c5ad4f7738b9bfce630d4a478a0dbfcb51ed93"]}}, diff --git a/txscript/data/taproot-ref/ee537050d4b74465e99c77d79aec50879344edb4 b/txscript/data/taproot-ref/ee537050d4b74465e99c77d79aec50879344edb4 new file mode 100644 index 0000000000..f6c1b0bd5f --- /dev/null +++ b/txscript/data/taproot-ref/ee537050d4b74465e99c77d79aec50879344edb4 @@ -0,0 +1 @@ +{"tx": "ce36f33a02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce1010000007e650397dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfb00000000bd1a57b903916ea10000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374872b040000", "prevouts": ["e45c4e000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529", "90e355000000000022512009252952876a5c13cea12f753600009323d5e64530eb665ff4d131016b9c0911"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f8e3d1763d4a4427ec633b67322f57c129a5e80babf61dc89134b834a86f0eef"]}, "failure": {"scriptSig": "", "witness": ["6a0d616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/ee666d81fc0411dbdbf38406d49ba05685bee495 b/txscript/data/taproot-ref/ee666d81fc0411dbdbf38406d49ba05685bee495 new file mode 100644 index 0000000000..060c1c790d --- /dev/null +++ b/txscript/data/taproot-ref/ee666d81fc0411dbdbf38406d49ba05685bee495 @@ -0,0 +1 @@ +{"tx": "fea3974303bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfaf00000000f2daa1b1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7200000000c374aebcdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb2000000006b51dbf6012250b200000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac38d83e24", "prevouts": ["447672000000000022512049509520b0f91b1265a5e49cd83a9b0f9e0f493349f712cd14edd64d1d2ac018", "be8e1f0000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "cbfa2300000000002251203dc36bb5a2188e61583976906c69e4e1213b5b3aef7eaef25acff80132ded84f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "cf7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936684835b9029b5ef0cdd410a4153383e35a43fd71742849ee7102ccebce63bb580309cb272f305cf5bf6862d0b37519cb4aa2491edaf37578d4af3081a91facd0fe03d403be23d34fe95cd8ea927043998b4b921fc49b039e78905cbd289b8eab"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b898d7164c63521d871163a04709f05e318ec8f97be239ce787baf514c9e3f692e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdd6c4167c25132c432c9175336dcf34ec1853eafcfbd891c58e0cd045b8bc4542"]}}, diff --git a/txscript/data/taproot-ref/ee92d4d96303e7296f561d5b3efe262b3993bc85 b/txscript/data/taproot-ref/ee92d4d96303e7296f561d5b3efe262b3993bc85 new file mode 100644 index 0000000000..17a6d1d9b4 --- /dev/null +++ b/txscript/data/taproot-ref/ee92d4d96303e7296f561d5b3efe262b3993bc85 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4de0000000065ee38b08bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42b01000000779fbafc031c5471000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df979722368987fc040000", "prevouts": ["a15c3f000000000017a9144582b7676ffb8c3a2735b8e71e172a272e3e33c087", "af4434000000000017a91405311b2c9f444185bafbe03a9610c5d95324a8c587"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "47304402204f1d0d1e42bfdc4758d48e17bed4509f062d62120e3f8ab50c70ca8564f380e7022069597f4706ae7a4259dbcc96a399168e657bc7a42b34e21ab8b616c2e1b18d35162102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}, "failure": {"scriptSig": "483045022100e734e86cb7e802dcdb76f77171ae3b06125cb261ccdb83d0a602d21be45c5b1c02202a8dc1f656029e582f0765533af65eea98ec9525edb093cf7ac469f4637730e5162102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc294041976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/eeb6e1a4eebe04ce7814c38efaf8b5b7e910296f b/txscript/data/taproot-ref/eeb6e1a4eebe04ce7814c38efaf8b5b7e910296f new file mode 100644 index 0000000000..dd86ad10f0 --- /dev/null +++ b/txscript/data/taproot-ref/eeb6e1a4eebe04ce7814c38efaf8b5b7e910296f @@ -0,0 +1 @@ +{"tx": "05439dcf03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce400000000e23122ffbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2801000000445b0faddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5e00000000b41645be01b3ac85000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487d2010000", "prevouts": ["5f875f000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "f27f6200000000001651142540f27e90740933c99d4f17ab2dfc6c82951cfb", "90775b000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "3f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa76a51402fc917873b776340a7337d6d9d98f28c38cbc7d5e61e594cad9a2611aeebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7acea811edfde1d836b623c2094badb4ab8bc7795b2b49da5506600222f32ea3fbd"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b75c051ccf245b031e4900985c151ba997c96374fffdfa34044d40aec7c89fced874772a13c5a1227fda830887213a5c965a8abbda46e6162f44fffadfc4d1ce03985aa46dcbff8b0495de750bd1afe74a661312f7eddf1146199ee1ea8c08aa"]}}, diff --git a/txscript/data/taproot-ref/eef8d1a1e8c3a9566015b3ae089052a50d3c3ddb b/txscript/data/taproot-ref/eef8d1a1e8c3a9566015b3ae089052a50d3c3ddb new file mode 100644 index 0000000000..67f7d6ba42 --- /dev/null +++ b/txscript/data/taproot-ref/eef8d1a1e8c3a9566015b3ae089052a50d3c3ddb @@ -0,0 +1 @@ +{"tx": "d2c4031102bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe40100000010467ce9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9901000000770146d6038921dd000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac0b000000", "prevouts": ["11f6810000000000225120b52a77e37c1fa9b4a7b934796858277b8dc346396dc90993eb725a9563cf0842", "b9f75c00000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "e07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dc752bbc00728dc9fc97a524e5c00d8fa73d20f44eeac2a564eeea9db1553afc3bc00f369fc994f47536ced64d5e4f722a68c2ed1128957c24de4b5158af0ec63ccd0bea79832f66dcec0cbfd0592e3eb2d999b46ac697170d667eb8939a9687"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e73d9d375b530aa22fee240902ecc7793689bdebd58e9771ff3d6e92b1aa7f5c13ccd0bea79832f66dcec0cbfd0592e3eb2d999b46ac697170d667eb8939a9687"]}}, diff --git a/txscript/data/taproot-ref/ef1b9627be8307d947f73d84910a2d343187898a b/txscript/data/taproot-ref/ef1b9627be8307d947f73d84910a2d343187898a new file mode 100644 index 0000000000..43d34542c5 --- /dev/null +++ b/txscript/data/taproot-ref/ef1b9627be8307d947f73d84910a2d343187898a @@ -0,0 +1 @@ +{"tx": "0100000001bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc20100000010e708c30198f04c00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac7b000000", "prevouts": ["ea217f000000000017a91437a5c76a04bb604ad99785877003310ab74c7e2b87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "165c142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["32b47c5333ab0bdb401ef0771e332fae7cbe19fb0f1fd61b1ee0ba8d9e764104377679372d1753ab1662eeed7e7162abbe9daee6672e3f3b4096e69f23a3cb7a"]}}, diff --git a/txscript/data/taproot-ref/ef34d2a06ed043b1d7aa5c55d07e649a98e022d0 b/txscript/data/taproot-ref/ef34d2a06ed043b1d7aa5c55d07e649a98e022d0 new file mode 100644 index 0000000000..000c89e072 --- /dev/null +++ b/txscript/data/taproot-ref/ef34d2a06ed043b1d7aa5c55d07e649a98e022d0 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c040000000044ed024cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bef00000000056c24ad01f45650000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748779000000", "prevouts": ["6a234a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4a73280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_33", "final": true, "success": {"scriptSig": "", "witness": ["f69218b245e6d49856976d83ce63f78c38e160a2f6c7a89a3e51e36a4fde7c535e36278c50071bdd70dc96210e0e4fa632d3ff29046d29e73d51c340595aa9b582"]}, "failure": {"scriptSig": "", "witness": ["ae46da8fd6ee642b526973827715bf7b1704fc5b4f256c1f52b58e580e469290beadfc2b8cee52a7c88438c0cbe332a85479de6984f219a7551ca8c441ef460a33"]}}, diff --git a/txscript/data/taproot-ref/ef5018ccc4d868e150c22f85faea02a352f124d9 b/txscript/data/taproot-ref/ef5018ccc4d868e150c22f85faea02a352f124d9 new file mode 100644 index 0000000000..03f9d83bb8 --- /dev/null +++ b/txscript/data/taproot-ref/ef5018ccc4d868e150c22f85faea02a352f124d9 @@ -0,0 +1 @@ +{"tx": "1708ab0302dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1902000000fef83395dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb400000000292d34e70146f851000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87f4000000", "prevouts": ["dd835a0000000000225120cd05dc3ff800de37cb40ac9c54624c99f7c63a87a98064fe9a32a769a26ad4a4", "51594f00000000002251207c531fdbcbb17294861c2fe9842b59c23605dbbb4aeaae1baaa0907152d9a970"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "137d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cc2bf80b2db027afc6ff7c1eb2245c9e3cd90dfd08684ab7b931baf85a586a71155f23cd39ff67d8b5a6775be7b28a3d1b06bcb926a8f69937c20b78b14c2d485d0346f0de7f7080f7758bd86c81c482f81ad0c7703311f4b65ab9d7b77c9f00"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e048ad2721d56e7698732cbf102ae8e792035911a0ba8e4825f0ff9fa3590c070ac5ef61da5659d8214c667aee1dbe4febf87286965cb6fe696f5c1a17be3da5155f23cd39ff67d8b5a6775be7b28a3d1b06bcb926a8f69937c20b78b14c2d485d0346f0de7f7080f7758bd86c81c482f81ad0c7703311f4b65ab9d7b77c9f00"]}}, diff --git a/txscript/data/taproot-ref/ef588660a2f4df9f52c4f476036ae92b435dd8be b/txscript/data/taproot-ref/ef588660a2f4df9f52c4f476036ae92b435dd8be new file mode 100644 index 0000000000..feec4cdf53 --- /dev/null +++ b/txscript/data/taproot-ref/ef588660a2f4df9f52c4f476036ae92b435dd8be @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6a010000003b24bf8adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2201000000fb57589c0357a6d200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcca000000", "prevouts": ["abbb75000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4", "64ed5e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_74", "final": true, "success": {"scriptSig": "", "witness": ["fcf934919cdbe5f3ba3a8b3facc9cb916f783bf56cfde2e97ff99e236230f91e3814acf1db6ed634540a9480579bc6c2378e28e318629e11b33f7ee4e6361a1902"]}, "failure": {"scriptSig": "", "witness": ["74616d1f4d5320e99ecb85a5d31ea0e471d4b5a231eee74add5fd45fe458ddac28af1f35702ee9264b19842e4729538fa52d3a785134a19c2d754e6bbab8f37e74"]}}, diff --git a/txscript/data/taproot-ref/ef7b84160b7025ab4d29b8bb32de27500874c4e0 b/txscript/data/taproot-ref/ef7b84160b7025ab4d29b8bb32de27500874c4e0 new file mode 100644 index 0000000000..a6a4b09bb6 --- /dev/null +++ b/txscript/data/taproot-ref/ef7b84160b7025ab4d29b8bb32de27500874c4e0 @@ -0,0 +1 @@ +{"tx": "01000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46d010000007fc9e944dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd50100000032d28935bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9401000000353048d30172b24c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487ee4b014d", "prevouts": ["17883d0000000000225120639f61e583baa036c10ed0b3dae79674c76249899948b2504e8e1e0ca79edc96", "4e40240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c40a6f000000000022512026ecbdce513e5cfeb779eb6a118aa90fae67510c7ee9bff64af6ca27f9068c2e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_d9", "final": true, "success": {"scriptSig": "", "witness": ["a066227205a1bbd7f1256dbb9dd7b511aa14ad75eb539150e3a7935ff673829158ce809435082b747307a9e9a19b238e9ae4f6d692580dd13577c42c51fb183a02"]}, "failure": {"scriptSig": "", "witness": ["fec8a50f82c2536d588fb7f3e1e4ca4d55f1e482002678b2a62e6c69af97d2964840bc0ed4b26c6ee7f580c12bde8ca15382dc22b95bc3bb6da4c53c0d74a705d9"]}}, diff --git a/txscript/data/taproot-ref/efab9adce18cdbdd285db520ec08c755b0916a2f b/txscript/data/taproot-ref/efab9adce18cdbdd285db520ec08c755b0916a2f new file mode 100644 index 0000000000..fa65b35bf5 --- /dev/null +++ b/txscript/data/taproot-ref/efab9adce18cdbdd285db520ec08c755b0916a2f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc7000000009095a1b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb701000000a352ab8601a88993000000000017a914719f78084af863e000acd618ba76df97972236898739000000", "prevouts": ["dade750000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5", "ccbd280000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "067d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0823f226bc542f166b7ab1884d7601266c0b79ac59ceed404fe5ce2372ecd38c8cf9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ed1973e93f7ad3f562801731a237f358bfce42fb636b2a0dab3a823989e87b4ae"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93662b4c4e03f8bbc4e0fa6de616a7b17503976357af82c5e4ff1a693444fc6910b3f226bc542f166b7ab1884d7601266c0b79ac59ceed404fe5ce2372ecd38c8cf9a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100ed1973e93f7ad3f562801731a237f358bfce42fb636b2a0dab3a823989e87b4ae"]}}, diff --git a/txscript/data/taproot-ref/efb25951d890dbd071c4a3811042fdb8e0bc4326 b/txscript/data/taproot-ref/efb25951d890dbd071c4a3811042fdb8e0bc4326 new file mode 100644 index 0000000000..a7182ac811 --- /dev/null +++ b/txscript/data/taproot-ref/efb25951d890dbd071c4a3811042fdb8e0bc4326 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc80000000000ffb097046bf559000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac6ba81537", "prevouts": ["1bbe5b000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063f468", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828ef0ecf285bc5470eddb41e1019d9d697e32571bfa8271cd432e6dc81a28355aef31942b1858214ae33105eca3f0b2cf78e8df05a3972acf71e40f309e975162b655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a3aec579bf900f7619d434dfcb8a1ac75e7d4cc09e331d2b80b2acddd570caf1a416fde06d6dd90590ccaed91ef0bd8538f486647382cbeeca5e39ce4df66da0ee1e8f33acc088355c2f0e93e4abfc8ab0ff1ea986a1dad4f5112c46f486a1d1a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}}, diff --git a/txscript/data/taproot-ref/efb757b9644c060f72a7441ae9f0dbb05935ddee b/txscript/data/taproot-ref/efb757b9644c060f72a7441ae9f0dbb05935ddee new file mode 100644 index 0000000000..f62431e032 --- /dev/null +++ b/txscript/data/taproot-ref/efb757b9644c060f72a7441ae9f0dbb05935ddee @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfae00000000c465f18adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8c000000000e1ef5a50158f18b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6221bfc54", "prevouts": ["cd3b7a00000000002251209dabef6569bf97dfdfd6e4e18b35ff722d4022017cd06d2812750df0c019f7da", "c6be550000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "697d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facb7a7ab5fd71851d574a9c26887a3027e1173994a10fb9074a9680b95d402bf38dbbed29828226c3a1e74b431b518dca4e99f1ee054f76cd9b7bd5529b5cc8688de3449b5e2c621283b68ab187cecafc7aa77a8721601b5317d3484f84536019"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366514e2792df6cd73727562f46c93cd47aa533cf6032189900e3e0a43e73e7f3e7bbe6274b0dcd2777fc9b1075bd65318fdd52335751f1d5034a6ddc9c2a447578de3449b5e2c621283b68ab187cecafc7aa77a8721601b5317d3484f84536019"]}}, diff --git a/txscript/data/taproot-ref/efbdf30300adcc55d7c50d4ec76a75496d6d7b7d b/txscript/data/taproot-ref/efbdf30300adcc55d7c50d4ec76a75496d6d7b7d new file mode 100644 index 0000000000..4e5f2a44e7 --- /dev/null +++ b/txscript/data/taproot-ref/efbdf30300adcc55d7c50d4ec76a75496d6d7b7d @@ -0,0 +1 @@ +{"tx": "73092d65038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46c000000004658eea8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa401000000a7b39fe5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c450100000060837bf002397b12010000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a60fdfb23c", "prevouts": ["afe43a0000000000225120b5971b61c25a2798e5070f8744a1dfc2e930eb6eb2b95087e25b503f53923ed3", "7ec5840000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "ee20550000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_ce", "final": true, "success": {"scriptSig": "", "witness": ["a1ba71fb12e1b3fd60210c51e6470eeb527193c5f1446147d1dc9175529a5f6f6880a92cbbb5228be8b7b145657fdd7758e8165df245a2f34b2dceb9a654036282"]}, "failure": {"scriptSig": "", "witness": ["8ae788a5918aef5b26a2630292d83d6ee61bceeeb132e6cfd3705c729fbcfe6ed62ebae4a1e1b71047810ca1db32b62d792eb4b05aa22b63463944c10577f381ce"]}}, diff --git a/txscript/data/taproot-ref/efc4b323ebe3c0b9e2f2fd7168ab4437570a54e8 b/txscript/data/taproot-ref/efc4b323ebe3c0b9e2f2fd7168ab4437570a54e8 new file mode 100644 index 0000000000..f8c19f442e --- /dev/null +++ b/txscript/data/taproot-ref/efc4b323ebe3c0b9e2f2fd7168ab4437570a54e8 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0201000000a5902247dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b260000000016a000b7dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0100000000de383c3702a0e7a50000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4879304df5c", "prevouts": ["f2295f0000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544", "0b62230000000000235f212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "bbe224000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367388cda01113397d4cd00bcfbd08fd68c3cfe3a42cbfe3a7651c1d5e6dacf1ad1ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900458e881bd6493e98dc576a1c76b7dda488b188d283086ec2219562e3f5b97e3fb63f980255362d30444bd4a09dfd60422f4fe5b70b7cde78729ca8cd52cb50aace"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a08be2b61717d300e25a6886a484f941c3f7d4fe4b568cc8a81fab5ca3208b59a7f496087fdd0464c266da8b16ca4acd01559ec68405b54c53e2b4568db5223db0bdfd7fd43775a37ae3e20c8f8514aca25517db969733cf8d9f690f9b6d8ea23f980255362d30444bd4a09dfd60422f4fe5b70b7cde78729ca8cd52cb50aace"]}}, diff --git a/txscript/data/taproot-ref/efce2a5687afc47a9a7951b0d14a86559eccd8af b/txscript/data/taproot-ref/efce2a5687afc47a9a7951b0d14a86559eccd8af new file mode 100644 index 0000000000..b0dfa1ea4f --- /dev/null +++ b/txscript/data/taproot-ref/efce2a5687afc47a9a7951b0d14a86559eccd8af @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3500000000f75e818ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdf01000000a0889ad4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b87010000002757f8a404a146990000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875dfe903c", "prevouts": ["79b65900000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "221d220000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "80fb1e0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "47304402202087be73d02616120f30209b25a1a1206d400ae632fafb4dbc13e48a14d3ccd302200a83c42f237aa800be508ecc687767cfbe849b2d5e4bd28c219a4e5e1c3092b2822102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}, "failure": {"scriptSig": "47304402207f105f2f348b02fb97457b6804d3e6d5d718370627a1b742049ea3ba452a70d0022031b860255b16014816d31097bb6e600748aea9f72faecbbd4b447dba4aee30a3822102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404", "witness": []}}, diff --git a/txscript/data/taproot-ref/f00c95582e31d9827eabb236ee8b4b776907a667 b/txscript/data/taproot-ref/f00c95582e31d9827eabb236ee8b4b776907a667 new file mode 100644 index 0000000000..dec034a32a --- /dev/null +++ b/txscript/data/taproot-ref/f00c95582e31d9827eabb236ee8b4b776907a667 @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704501000000ee4d8a848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40b01000000f0d42d8a0429894a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8749000000", "prevouts": ["30ce120000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39", "725c3a00000000002251205179b7d628a57252570761200f058df77fbc655a348e256a168d7aadf31418e7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "f47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a7c1713bb6fd836f670621a98005beef08cd27b654a92512fc54053c11f318fc2b4a87a36ff2ed7228bcfc2438815b30cc1c98339504e1b834e10aaf4a034051"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c6e69b04332a66418bb8cdc9057e862669dacd1ba9189b79de8865de4a0cdf7ba7c1713bb6fd836f670621a98005beef08cd27b654a92512fc54053c11f318fc2b4a87a36ff2ed7228bcfc2438815b30cc1c98339504e1b834e10aaf4a034051"]}}, diff --git a/txscript/data/taproot-ref/f015ec4058e4e7ae0d1a64823882e2e3fe9f8bbd b/txscript/data/taproot-ref/f015ec4058e4e7ae0d1a64823882e2e3fe9f8bbd new file mode 100644 index 0000000000..56d6c98dbe --- /dev/null +++ b/txscript/data/taproot-ref/f015ec4058e4e7ae0d1a64823882e2e3fe9f8bbd @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbf000000007c50ca91bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf94000000002da740f8bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0101000000229667af01daee3f0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963a040000", "prevouts": ["27a64c000000000017a9146db815d9819f256ca5d1e70b15558a98689cc52e87", "24147c000000000022512080bd047c4cf14a11f5476d57183f1020b00443da67a37d5b059d1b67b35ba9d4", "aff2740000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath", "success": {"scriptSig": "", "witness": ["404bbae303d496b8d34d72ae8bb19ff543f55f831bddc06bb9d80c8307ac57c4248bec3118ca0c2fb4e391065b3d5184ac54f40936fc05ef538e4831912d556402", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50a60fd5ef47cd4b364ad3d01b6c2a28d95f0862b577c9022702aca2037544c47ee429b94f08615a4b713f3d08444c21512ef45c01bd4c6ef81df85bec43cae07a95944d2a18ba750cdc3477c5af2cee0c2a4e52e6611ad1b246861a6aad7c209ef9c1fe44a9dc1fb076d2c567d0540b9128a4f0127b96dead7fdffed92ac95d020f6bd2a6d0ac40c9ed264a699ceec8edf8a899fd2665ef0d03b5de632711297489d097619158d0f84b1c9e3851a988ededefe4aef78c22038cdb86bee7ea243adad253ec1126b6"]}, "failure": {"scriptSig": "", "witness": ["085eae44e6c21c241b9120b8501938a6cb0cb676215ffa7f942d8d1f8ba5e269a7d9ef8b426879452b62969e8de1538093e95da9ba988d3892e25e79cbd0b88701", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50bd36acf066b58343cb81d29d18141760ee03d0080e47456eebe11bade90c08121e2da99af1fa847e41fd280cb0480eea5712b039af28a1ee01f0c57f13d5fc128c0dc27c1d596a463bbac8aa0884583c80f4511688c4f8bbd15446982001a33d195c65ff1b12fe5212cd902263ee0da25179e20f338cd2b4f930fc28ffeac2633fcb93ece080337731834d9fe14a7de80401fe86a09b06a063673d4b14e042e25ce6c603481e63d6cb660bfe3cb5df6b309d6699e4a225e88cf3a7c9a763623c1f402b494b4356520d0eb9bdd2ac28e8748a5422917730fab78b32a639cf"]}}, diff --git a/txscript/data/taproot-ref/f04d521c21ed8372ae0bcf98ee15b6ca83c85bc2 b/txscript/data/taproot-ref/f04d521c21ed8372ae0bcf98ee15b6ca83c85bc2 new file mode 100644 index 0000000000..bf68de8929 --- /dev/null +++ b/txscript/data/taproot-ref/f04d521c21ed8372ae0bcf98ee15b6ca83c85bc2 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf86010000000341de5d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46b010000006e8ce12b02cd14ac0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac61030000", "prevouts": ["0f05780000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c", "26f63600000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "a87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936070bcce77ee9cef21e7dde7a48a2affc6a0869a65b8cdae59e8ff14f5e2ace20cd165f299bdaaa06ccf8947d9b12e815a5b39fc50068532880492a3446c423d89e26d26d9f798657ab1642d8194f1f5dc9158412142f65824f82701f20125ac7"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d260805e6129c938d2ebd337f78d5f9c6d20fd2f0df083243f56c0722c96d98b3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082337e31cedb20dd0ec36f43f7131008eded9387a241f89ca892d220549655a6e95def3d75afa0626f5ab572f3c9ae49b6567bf85ec43d0b3933062a3ad8b1e492"]}}, diff --git a/txscript/data/taproot-ref/f052250556f0a305782ffc367c106bf8213e5199 b/txscript/data/taproot-ref/f052250556f0a305782ffc367c106bf8213e5199 new file mode 100644 index 0000000000..3880ae0b9c --- /dev/null +++ b/txscript/data/taproot-ref/f052250556f0a305782ffc367c106bf8213e5199 @@ -0,0 +1 @@ +{"tx": "02a25573038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c44300000000a45df2cd8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4d7000000004530aec2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c62000000009004818202ae91bf0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478724ab1f33", "prevouts": ["520e3100000000002251209bd2c3b94d09d0c3ddee02b44daf89c5e94fb9f94cc74cd030eef977051f59e4", "942a410000000000225120327dc9effbe915b227349282cadfcd45dc438d4f1c3ec72713111ad7587a718c", "f2415000000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "e27d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fae4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8512c582a906b097cf6fdaec64d2651566eff10d9e5eded90f3aff95e690654e4212021a26ea5e00fb993aa3d0fc1bd1e431f365db69035b8e4625845fc9b697c"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c592cb302a9f446744f5bef15703ec53b083cd3f0692dbc327d4c802b2b75627512c582a906b097cf6fdaec64d2651566eff10d9e5eded90f3aff95e690654e4212021a26ea5e00fb993aa3d0fc1bd1e431f365db69035b8e4625845fc9b697c"]}}, diff --git a/txscript/data/taproot-ref/f0b8804a6b3fa0ab08fb2e07758480377e212f0b b/txscript/data/taproot-ref/f0b8804a6b3fa0ab08fb2e07758480377e212f0b new file mode 100644 index 0000000000..dfd0101232 --- /dev/null +++ b/txscript/data/taproot-ref/f0b8804a6b3fa0ab08fb2e07758480377e212f0b @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc6010000004f2f5a8ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf201000000518448d70270749900000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487c5000000", "prevouts": ["81447d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e7081f000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_3e", "final": true, "success": {"scriptSig": "", "witness": ["245911bfc88ff9c207d514cec10b72c5c39a26d05763aab0157f9ea04cb532a58cb01c8cd3e08f56c5d7e76b5cd6974846e641384059bceee278fcdaec64855781", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5f71a1f1237c4091aad404ce88fcd1410d026b15cbe885a3b0896293cc18c8373e6204787797901467daae09e3a127562a226992d5cebc446b4ad33a573d6a273e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f0f31b265d33a5adb67af2f1fec8248f8855469e b/txscript/data/taproot-ref/f0f31b265d33a5adb67af2f1fec8248f8855469e new file mode 100644 index 0000000000..26fd0c20e3 --- /dev/null +++ b/txscript/data/taproot-ref/f0f31b265d33a5adb67af2f1fec8248f8855469e @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4db00000000fb0b3489dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bff01000000ea7ff3a203f9225a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acc75f7548", "prevouts": ["524935000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "93f3260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/unkpk/checksig", "success": {"scriptSig": "", "witness": ["00c45e6a38db8e64490d7884167fa7f7d3a4edc4de8f0a033cc292eafcf0eac26ade41a618476098f14304005d715eab6dc86a15679512b886155d8238cc9771", "51ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d4e264197456bd4c1b90f4fc8939bbf0610dca38d2fe38774b0a18ec6f9b89fd6d5d57b1dcd138e0cc147645402e61e69606b9792a3b1099031a7a147753fb7ce94cad6d75d2cb0ef900454538e7fd1b3ce4a6d54232bfa291f410b69a126dde54db117b6c10c3b79a9544d066c7c855e7686ab420f6a95e4ddf7a60395767a4dd4f3ac0a3984f3bd2e15d4b9ca628aa2c1824adca4bc410c6babf89cc776a6d4058a827f45ae2febfd6a48e1caac11f989a6c525b4da131ce52fd12e7f252fb6bb3fbe66e03f1e3d5d03c151a1f49af6fe35648ce1fb8bd1df07a497ff65e67ddf671b321fa9f2f2888d22aac2e45fde49c08b0dabc58a3dab9abff3ef25bacc98981699735d9d2ad5870d568ad1367f9ff314388b4fbc7f8cdd9ba342a7b5179c9ccf72d9e1b4864c4c957611c569bc9c3d7747c5432696dcc4a6932a52f70fba63ed8c75c68ab96fce5e685474517ffb0ff82c60ff0dc4d12440e21f52ab15ef11190bc97bcc8d0e99d5656d0891e3984baf383c021195a3f4accb96a873fe0d5c32a15e7fe92b17b2b8c3b841359f1b14625d34ce4c46a1c898e5b74301d7a21d399a47140b6711788aa4ac5bd9e63ac239ed45da28e932ea3acd6bd9f7f5a3113bfeca67cfbd40f858b9150f2d1112d4e5e609341baa11cda5532a4a71babac9d6f1aaabd147ca57e59285d2955e18da8762c420c4b0596550f02e8a0d0eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["8c81522dc5faeea7ed36e2c5155605daadc9320e51ad319bfd30bbafd0e19caa2f680299749f3becd74b3c421000dad930bc0e9537816ac6add0cb991becb806", "00ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366b0431b55481a374c89f40eb98ef9d2a1ea4a15c1fa25842c8dd1b505d3f733008998f104a41d430584d29acc5d80983bfa4388185b9ecb4fb5f364585438a9bd260600b62c8ed4db4bf12723005c7f766cb302a575f8872965ad67f65636a6b0c8f171a0659181424fedfeb48947aa5b62ebec348497eb70a0e4b9dfaff17fe7851f2fbba69e8a986917b32b5f76ef63e06d7f778743be5452643f44f99ea505f10f2cde5a4729d525a487b41d56d434ed7dc5e0aa5e11e544eae0c7246ef2b3ea5155719b875991d083ecd32183be0f5ac452a5905295b6a0b91be04b40b76e4803cbe3d00c239899d4914097448c043dde77fd42773528487758c6d087e8cf83fa64278d817919e62c4d23adcbc207f804fcd146d72915d8e061e85a8f6a6e6cb9d4e0a9220b07d19fc28732eb4bb2345d54d956bd2d189c6a5f87f1c011bb65cbfaa9ed654ade91c00c9fe4f57391c241e95cfd60b1f44f495a05086ba006260268f3fa4d832afae96ff672bd19d7e928d42bc878143589bed193337fe656f28feb26558d4d064770c2eb738b0251c60e0a639239140ddba0ceb61ff7c3e738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/f111543d0f442f268353dbbbf00ebe24c21f930e b/txscript/data/taproot-ref/f111543d0f442f268353dbbbf00ebe24c21f930e new file mode 100644 index 0000000000..9df0e6612c --- /dev/null +++ b/txscript/data/taproot-ref/f111543d0f442f268353dbbbf00ebe24c21f930e @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfd00000000abc441cc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4220200000015f555c90339ce5500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870b030000", "prevouts": ["114527000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "9d7b310000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["974c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93626364c264ca1a1a3113427e98f88e51ff7da2e89277d01d72659b15bd38bb6d4bbdd0eb743f16fddaffdc87a703f35bd0417e0996b155e435c0add546ea723b55a7303e26d6b86d2a780c30dbeb7ba87c6a0494b901c3875fb9ca7f2f12bb2fd373be813dc08f80e09d78de4ac5358a3bdf22545a425b50fe87daa20f96c44d7"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51064e90022f018e8cc473163b262248813e3dc7e43f487ab53623d6c75190b10b282285524a15c732567d099967405d35f7136f74f48f011bc4ab279ad8d14f14"]}}, diff --git a/txscript/data/taproot-ref/f1439b2e5f242df93c3d5fd61e367f850098495b b/txscript/data/taproot-ref/f1439b2e5f242df93c3d5fd61e367f850098495b new file mode 100644 index 0000000000..4cee6ddcd2 --- /dev/null +++ b/txscript/data/taproot-ref/f1439b2e5f242df93c3d5fd61e367f850098495b @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1a02000000688f084d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c2010000009ef8d859045db7a1000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acc63ed24d", "prevouts": ["8f31660000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8f393d00000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902992411240ec2753d3808be0a0b86c3cb00d1f0d3e39acac5e325e3b929eb9613b1ab07143677cc1743467afa0ff3dfdd315171c3d78cd0b46054b0bea3a7b36a22bf660ec92ddf353565429140cd649edc18ee664a92b76e5425b7f53f6cace3fa845f2d6c52cc321790001486738311edd5082ddcd29019aa701fb06fc7fa00b767a214a93e963eb1b7d818f44676b0c21b9839bfc2be13a443c8fa71f15d6404832f7bd6f474d1572fc4180090d952dee36a56b64345b3ed2fb8f2d87f22bedd0a597a44a89596e5e79711478b8713b6f4663606f8939f8134631de7810131d064b084392f85e0039c0b8980610a4722a443e6931511630e111ff47ef362fb837bf121bd6a54a3c5d3a50c27ee8d8bfd650e62a8ec240b9a8e9e0775132c97d7c6269db36f93a3ab42ea9a45fb12c1bb0c342cee2d0974af242c0751c2923d10905eeb4df7ae2e4c6a8da1bd1ff6ff0a6fff1097f571c25f8aa8ee15554734f4f498cba7ed2398dbb375eed5d6447d046f2fd689ce77d0e874dbe026901152fee1635acfe5c17e53eff7965c0218d706c95dcfd9b5a1bd9321c9fc3633beaebe23fab1ef8ca0aa038e30f4be9c2ce8d6030b9927a1dacdc064778a9fa0c092505d4a5d3f4a29e6a9d6fb20f74f0001fb5ebbb5f4c1484438ceb99557214909ceb0425baa0a937d16573c3464125ae7cf9739e480a5abdff4ba41183821f9aba3cc2fc871b6c3c17e75", "0b7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8784d9e7ee919b8817f3904ff7d27b5c3a4ce3798ed5b994b75288b8e9341d9b42c78e40500fa05b550b7f6357dbf83024c41a574f6a1706762c104fa8aec3fcb"]}, "failure": {"scriptSig": "", "witness": ["4d0902c99ff4130304325e5b01178d4ffda3c0e21c3bd612287c5a5ce107349391e85331108f98dac92f0abc67f2baa39d3612e382eca0dd7d7e2cb3b35cfb851f859a12412296e38a3b261b86a388fabc2e2a1588ae30b7383d82bba8e6e0d5ed5a850f56dd664e659ee5e69dcfce9781a3d6ab95823a179cb34d6fa8d0ad25ee1bae3ee9e2a9db6140fd94327c1061214109ce7c0be7722b8ad3f91663cb1a5df727235f5b89f6be6b2f5ee4555210858cad0d9262db26db5a0f935db6062941204844c91def066ea44e8729ebfb69b47b4ff7988b20c424a451c44f9d67e7a06d0c67f1e065e5e4dd0ed0bd0bfc7aacdcc12e6c72c521bf788cdd97d72cd2dd440482854e9b2ca7fb0b5170bccf8447f57a3d7467b31a8c02a2d644a16ba6173b3bf857e4cd90539d917959f32ca87506b5cd95212be4564ed5810135092d4fca29ac9da2b880a0147afa239c2049438992e6abef6cc3044f08e98a77b7e4d705c807ff9df6b36aca283a3c3f8078fe9299388ba91f3b20ed16b60d601f459b898bc36e3cc5d29ee025c12765ed1ca745ea7970fe239f22a074abbbc384996c0e731e3680a1bfcd75bc26139a311a632ca1a452d88d5c53d5b08cebcd9953aca69fd7d4ea896c28908f1328154864cfb2dedd72a0154f6a69e79924e5757b91bef993aded77880f732ec6b867ab2857bf7b5486612bb2f3306ddbf4f17bbfe3eae048c02865753a20453275", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ea51646124a2b4386d840e205fec55c7cefbdbe9c75e9c45dd558741f313d2d0ee0d9bed60e53dfa6fe8b58229f37daf0597893c765c7b30814eb9e16fca89b86"]}}, diff --git a/txscript/data/taproot-ref/f150268fcc20d8c1e1607d773fe9c2af148e9e8e b/txscript/data/taproot-ref/f150268fcc20d8c1e1607d773fe9c2af148e9e8e new file mode 100644 index 0000000000..8717682577 --- /dev/null +++ b/txscript/data/taproot-ref/f150268fcc20d8c1e1607d773fe9c2af148e9e8e @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdb010000008dcc48a960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127083010000000035858903fdee6a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ace2000000", "prevouts": ["a4ea5a0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "05d9120000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063fb68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900454cdb1f00ad8e6f49049c3b8916156053acbc542960ad6e1236bde6d1970b6ee852b51aac478484d8a075e848b67a41ce9b347e1249fa49816f898b909a6d4bd5c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93613731d743a1998dabf7620d1d828b5b28163c734bff41737a94b9bb5e3110fd84cdb1f00ad8e6f49049c3b8916156053acbc542960ad6e1236bde6d1970b6ee852b51aac478484d8a075e848b67a41ce9b347e1249fa49816f898b909a6d4bd5c77e07a04f832bf80fe1e45fa6237ff98bc90e935546ee680c041b2556eaccab"]}}, diff --git a/txscript/data/taproot-ref/f1728d0e4771e35b1cb1998adc82e22eb67a65c9 b/txscript/data/taproot-ref/f1728d0e4771e35b1cb1998adc82e22eb67a65c9 new file mode 100644 index 0000000000..043f2b3668 --- /dev/null +++ b/txscript/data/taproot-ref/f1728d0e4771e35b1cb1998adc82e22eb67a65c9 @@ -0,0 +1 @@ +{"tx": "a54aff3a03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf37010000008bb7459d60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702700000000a6f955b3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b590000000057ec95af02d213ac00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df9797223689873f816d5e", "prevouts": ["87ab7b0000000000225120637e54d800000b9ba863fd409e40dd20b023cbab04d0b624963d159680b37b50", "d308130000000000225120efe1fa8c8643b06748235620ecfbc876727366244fc928e9c2000087b14324f1", "17ff1e00000000002251209e3a3263c4a4d4739bdb7a9cc15be1576bf24ce130b027eee13d8f139fadd4dc"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "227d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93682fb3b4087072a481d7212df69b60b618087c4d1c0d29d2f7ee92b373e21faeb8a2960a95becb1bbbe0636e0493c58f712af9b8da417013d797bf12c130ac560a4a9bce64ad1fc5af22ad5621933415c83e23766bbab20239912b691ace9dee2"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936be77e2234f57b9b74ee6a68dadc788f2da89960fcb7a13e163371ae2a2591881f76c402a4bd1fd97ec7cb0657ebc265c6b14283a23241722901633641a1252aadc4c18ce03381be5d83370dbaee0482c0440aa7aa94902a00244e0237bd29478fcb15428af69077ee4e47ddc8bd2adcf7d97a29fc56c75a24a213a103a1e3586"]}}, diff --git a/txscript/data/taproot-ref/f172e0269b4ce4678ade6f0ac95a9448d2453792 b/txscript/data/taproot-ref/f172e0269b4ce4678ade6f0ac95a9448d2453792 new file mode 100644 index 0000000000..4523519453 --- /dev/null +++ b/txscript/data/taproot-ref/f172e0269b4ce4678ade6f0ac95a9448d2453792 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff201000000a1f5ede7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf510000000013f48da304ee0ee2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e727585449", "prevouts": ["1d666800000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "adb67b00000000002251206c2fec4e8a1c469e06f21e10d3391a530153ef860e8b3f034f0bee0104770428"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "577d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d04bade1c924e92c8fcf5c96cd70dcc3bcf23e3c6838a356e208cff365f4000b35bf8914ec6f25b4d9fa0eb4d13d0c5199bab9da1f0dbae1e1446f691f7eb6d53a8385792857b3824bc259fd95f469eb32c57805e5f383de6590f06749d208e6"]}, "failure": {"scriptSig": "", "witness": ["4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360d77fbfdbb69849d4ff0a6fb331fb6eeb19c0afba192c9d1db1aa05948f5f4b1da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef4a7dcfb64e618b34998ea64659fe772d1fd358b29e003b2257b85d2ca618476a66706abdbe591f97764059d8785051c12d40b9c9543fb83334d204ae23d8b59"]}}, diff --git a/txscript/data/taproot-ref/f17ba688055f4e28c6c763a1a67b55ffd27ab22b b/txscript/data/taproot-ref/f17ba688055f4e28c6c763a1a67b55ffd27ab22b new file mode 100644 index 0000000000..16b29473ab --- /dev/null +++ b/txscript/data/taproot-ref/f17ba688055f4e28c6c763a1a67b55ffd27ab22b @@ -0,0 +1 @@ +{"tx": "05439dcf03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ce400000000e23122ffbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2801000000445b0faddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5e00000000b41645be01b3ac85000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487d2010000", "prevouts": ["5f875f000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "f27f6200000000001651142540f27e90740933c99d4f17ab2dfc6c82951cfb", "90775b000000000022512045a6403ae49be683b272d9a42ea0a940324a318f771f036a6a11d0e9905b97e4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["6af7ee47b9fea2ed853d010eb737fc8ad260ee45bdb324eb6b890516a33267f7949a5cc4d847c4791c38caa75bc9b539b6ca6c3bc1b944a31ded162618a89211"]}}, diff --git a/txscript/data/taproot-ref/f18786606f38657d15f1d007fa2934ea6034a605 b/txscript/data/taproot-ref/f18786606f38657d15f1d007fa2934ea6034a605 new file mode 100644 index 0000000000..55fabc6f65 --- /dev/null +++ b/txscript/data/taproot-ref/f18786606f38657d15f1d007fa2934ea6034a605 @@ -0,0 +1 @@ +{"tx": "4cb277ca02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbc01000000987c9ec48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48a00000000ab7f4a8301368b720000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7960c7c812e", "prevouts": ["9c487c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7b65400000000000215a1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/annex", "success": {"scriptSig": "", "witness": ["710e80e6f953d1db34b9a28085ac9dff3d7ed72b1023658673e372a4c899dc71160cb84f2a911cf50116289c86f1e946e55b74d2e3fc851e72445def91e1395f02", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50"]}, "failure": {"scriptSig": "", "witness": ["24ac7b354f286edbafd63ef9dbef70db30d69a37c00bee175ddde69abf2e274cb252c230e696626004e8fb8a4fa3cf94b51edfb25b84200b9d2d6003341daf3a82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50"]}}, diff --git a/txscript/data/taproot-ref/f1ab87a390b003a1f262909e41e5d3853c0dee70 b/txscript/data/taproot-ref/f1ab87a390b003a1f262909e41e5d3853c0dee70 new file mode 100644 index 0000000000..738ac0cced --- /dev/null +++ b/txscript/data/taproot-ref/f1ab87a390b003a1f262909e41e5d3853c0dee70 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbe00000000a95271d0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcd01000000c9707a1b01a42ac8000000000017a914719f78084af863e000acd618ba76df97972236898781bd9444", "prevouts": ["5b3179000000000022512043e98e0a8fa214574b4f7d43d988f280e5f4237220ef6fffc40af5b8eb3be152", "9c0875000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["fd", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f9d8f10db74f979c41891759fc87cc010c6171f34a4dc4fa278f7920467dc96cd9f77cfc3030f4fa2d9551f14353e565e33cb9a72a19e79fd0e4930553ab0cc3a3aa70c847d82166fa4c32b27cb78dba1a5c77b2d4b8269442df723c9129fb762c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936427f03015f7a96869233965cfd3869b27cd157bfb8ae4cf2df456ac491585181380f015d033fe7faead4766c682a770029d5c79030785f2d26c440da4ef071fea3aa70c847d82166fa4c32b27cb78dba1a5c77b2d4b8269442df723c9129fb762c347795cbfd24b3bfff0bc05cfe1b5e01afc0104c4d9fbef2a45c75fa918ca8"]}}, diff --git a/txscript/data/taproot-ref/f1ac308d98f3a982e3c86ebf022541b3c7a53857 b/txscript/data/taproot-ref/f1ac308d98f3a982e3c86ebf022541b3c7a53857 new file mode 100644 index 0000000000..c943b8027b --- /dev/null +++ b/txscript/data/taproot-ref/f1ac308d98f3a982e3c86ebf022541b3c7a53857 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be100000000ec6e0586dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf100000000fd59c1ae0257407d0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a666000000", "prevouts": ["82e01e000000000017a9141d8eff3030620b266a8bb5e50900ecd7b2ab72da87", "111260000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f5fc9523ef5d711d376a7546b8613c92c6453cf935a9e008f2e992a07522e9b738db03092f78269092a33e7c3338556a6e9ae9561fbcd456ff3caaeddba2a65696ed8ecd3b1f44ea46526d24d4bdb104b33370162d4d99cc9d7116708e1ceeaac08455640a3ac76aa5c6a831ea8a150475947d0f012a80420c5ef4b99d41b3b921e9845154ae02ecc5f3b85b5dcb612455b128b26c9fed38c1df7307d8ec1c0a68785aca3e09b74cdea9dfec3ed29654e0091d59c1204ce0f7c4ecd06d0dc22461c22332ec984262317239a55ba879e08d8903fb5ddf9bf4a1a342abe653da4b6fc4009691fcd73db80ad705292deb492c8704b2aaf002530712fa18ccf6f68122b53f0c3f88ed8a0e43891d759f5db41c3edc9c01d1748ea606fece0e6573c53ff944b42e2f6c08711e02a86b1598d049b3143f27b694f5206043ec7d5d8fb52a435c0b0acca2e9a62c97ff91e84aabb95454e714e084fec3e82bf45c9e73b20e80031edebf4e250fd6b03660a20255081580dca8c5bcc9cf6933b1d330d8ea78bd7e037ce53844f0ee04423685ae0a48f3eca9d02cb31100b96be1337d4f9dabc87b8e7e43a6241a6126d440f6e82a2fa3b8ec1b0037e68b3024cca196139cc2ffe46f40ace1cd5aab0edfd3ad42782c1b3f0ea41e397bba0cdd5c0614a5ad38ff07dccf9f840b5ba02718860a7c3fde6f8fc863ca61179d8807252d21389c36fb6836170b45074d75", "677d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa5ea7fd6123a97de30c69bfce8661bc08bde914a895a50530d51ffe984d9d20eafa195b9f6f39c732eb35859a6bf094cf148e251ed4d8a79570f47a225cba2c42"]}, "failure": {"scriptSig": "", "witness": ["4d0902b09c19c120598fa6c16873b605bbc903fbc233477afea8d060cfd083527784a21e1355b343e76d8347c8ec4fe11941903c25590143fce536fd8770a8868b901571063e052c01468e7be77a7f72dd1bd17bcf2e2130e17a863594b707d01b8ff5319c745beb38917f3916eeb2c6b767779e4a3fa4eefd15185a62c520e20addb8039acacdbbd33ecbce7a78cf05116430dfea335414f6252403261cb0f6e9be0ca0862333b99c6aa6b21257a1a3816b07b8f1a0c557ef566ffffc501d45c8529074a278c6ecb897292a8e15b899eff316118d555102de9eb45b3047d89c12c002fd914f94812a6f9b374886b0de496067999cffec4bec1cd4a1a262edfe01d86b31d28742be89827594eb23fa98303c4a70e1bccad0380ad1ac0947660194e8b097f1b71d12285b720f5651dc9a47244c432611d4a12e84e98d550ecde8ebb5c05b0fc8dcb5c62dc22703c5dc86d3bc13ab63510feabc203ab6357548aedfecc8457ed74d2452f5a85e65681b01cc81885b5d3112f593475bfd4a83fb7c2cc672c96d6cab7a943d9756ee14be43537854dd72b61975eb9b6e1ae33048e9b1426a8713495865be752b216f5e50e33a1b53938e6ca5383f053eee821dd99dc9f66517e97ce5b7f3deffb4b936b3e5edbbb9a975ba87b54186b6b2ba0334fc591d728db44c4fb554feb0235473fccf58a9ba74e2f1cae5a1b4e10cd94fd42e0b8f5698b014a0d71764779075", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367495a4f76ff6a015f29b6766f26d7385468d8511cf5f36a8072dab9eb3448108da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e577a14a6eded01e2af38af60eef18c742302cceec7e721187e3fa159b8f76816fa195b9f6f39c732eb35859a6bf094cf148e251ed4d8a79570f47a225cba2c42"]}}, diff --git a/txscript/data/taproot-ref/f1b42b68e02cd3503158c2cedbad9f43b4a782fc b/txscript/data/taproot-ref/f1b42b68e02cd3503158c2cedbad9f43b4a782fc new file mode 100644 index 0000000000..275bff81ac --- /dev/null +++ b/txscript/data/taproot-ref/f1b42b68e02cd3503158c2cedbad9f43b4a782fc @@ -0,0 +1 @@ +{"tx": "edcfcdd702d9befb1e9c529d7d9073823d42f590d5d83a9ae9e8205a58b2deac400aa179de0000000000aed2b9bbd9befb1e9c529d7d9073823d42f590d5d83a9ae9e8205a58b2deac400aa179de0100000000c9ef9ecf037bb08b0f2100000017a91417076ced824a76f7f00aa0b9ce412f8713d9a8a68758020000000000001976a914798a0f34de6d8f95c4b7ca7c79a0cd208c63fb0888ac580200000000000017a9146e2b0fcc2c4086d85becf46dae6d7af8c0bb07518738d6ea54", "prevouts": ["d453c1ad13000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "8032cc610d000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/keypath_invalidsig", "success": {"scriptSig": "", "witness": ["faaf5f50af119edd122012c71f8cfae4ac508d740074eb7b756a30677ff9a98956fe107f93c3ead41c0d3254684125c1d48ec3a75f9c689a5ca6108cc2c81248"]}}, diff --git a/txscript/data/taproot-ref/f1b9e75c583d069af4d354379ec7cbf02e95c41d b/txscript/data/taproot-ref/f1b9e75c583d069af4d354379ec7cbf02e95c41d new file mode 100644 index 0000000000..ad07cd57af --- /dev/null +++ b/txscript/data/taproot-ref/f1b9e75c583d069af4d354379ec7cbf02e95c41d @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb401000000f091c7dadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf100000000be70b49003eef1a400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6a491a81e", "prevouts": ["c76f8000000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190", "24862600000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c44eecd9b500a2ebbf47c734afa5de1aa2fa12782431ef0dab5671510d72378f98751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d53d2e072fd8e8376d3a54b2bea1bfbfff1298aece70c0bc2934c8eaacc3044fe58f009f53a1a3347386cf74e6ce512c14e8f46a54e4d2c64fe3ab77cfdd670d0b"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dff5ed59a308aa7ea3a47918565838a3baa1b60a9bafa1ab86863a2da11a4fa3d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b15c6036a676a492a4bf737064ce6a21b64de8ad159d3b2e60d879468caf8957d0cdffd10ffbed86c0e7536425f8f402fac685ef3be7cf3af5c775f2718b4072"]}}, diff --git a/txscript/data/taproot-ref/f1cfa6ecbcc68ba081804e6b531a970f6cc70cee b/txscript/data/taproot-ref/f1cfa6ecbcc68ba081804e6b531a970f6cc70cee new file mode 100644 index 0000000000..10cd21d336 --- /dev/null +++ b/txscript/data/taproot-ref/f1cfa6ecbcc68ba081804e6b531a970f6cc70cee @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdb010000008dcc48a960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127083010000000035858903fdee6a0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ace2000000", "prevouts": ["a4ea5a0000000000225120defe27edd45ad927249675e5a926c89be2f3fb0cb8fc1f86ac9fffcfc79b097b", "05d9120000000000225120192ca6362cd6392703ab2318f0102b3cf7536ede6d4ff88793ef5f7d5ef4db5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "837d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936544a2a42c76e0ee837b7a685e04a782eea16b775b2dde41c180c8b9d92cadb62fcc3b58fc7cb9ae8c07f6b17b965d49129a74935af1e9f3c9d7206d9e0977573ff15e37d03bf407745d47da370f693bba1bd1439d95d9059575aa23ebc3ce6e3"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360a4c4e25d839cf1716ff290d0725037bfab2e64d2c89faf706269300ac3ba5676193e4630789cbfbdcb7d6fc995ac4f032c6d5611c1f6b733abe8356e59ddce06294a5d2648496e5016f850eddfdf01467fe69221e8567db6ec356a8117d8a748163db171dbfcbf374971659a5a65d0378eae0ee15db360ca8cf80a8c2e13046"]}}, diff --git a/txscript/data/taproot-ref/f1d42d84bf3c0ea75c9ac6babfdb06afac572bfa b/txscript/data/taproot-ref/f1d42d84bf3c0ea75c9ac6babfdb06afac572bfa new file mode 100644 index 0000000000..a7446f472b --- /dev/null +++ b/txscript/data/taproot-ref/f1d42d84bf3c0ea75c9ac6babfdb06afac572bfa @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6601000000e283ae2e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46f0000000047eb5b7102ce5f95000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787a9020000", "prevouts": ["5f6c5f0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a", "3359380000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "5e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08259bd71c400ab2f54869740392a5675e37e70879689c9d1a6bcb33863a193d8cf0c8cbc16505271ed8ce1a03d67d2c4a35529bcf4a25ace24696315022c27c9cf"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93601f485ab8dab36fc4237cf32204629d23ab8b7a9b8c57b9fb58bb07cc298c65859bd71c400ab2f54869740392a5675e37e70879689c9d1a6bcb33863a193d8cf0c8cbc16505271ed8ce1a03d67d2c4a35529bcf4a25ace24696315022c27c9cf"]}}, diff --git a/txscript/data/taproot-ref/f1e479e1e2ba063168c4201bc568c60b601c98f8 b/txscript/data/taproot-ref/f1e479e1e2ba063168c4201bc568c60b601c98f8 new file mode 100644 index 0000000000..ea764344ae --- /dev/null +++ b/txscript/data/taproot-ref/f1e479e1e2ba063168c4201bc568c60b601c98f8 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb30000000093a746acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cec010000007ed5e8d5021f6fb300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acd239a551", "prevouts": ["0e86640000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "519f5000000000002251201eee2c640bfce5c51bb2c40da2e9766a04a76652bb29070203cf3219889f560d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_4e", "final": true, "success": {"scriptSig": "", "witness": ["ebf58d73905fd7c2486efdfe028c446f051d8c8344f53b98e47411fe4d8b323585e3fc4b1f1daa84623695fbe505683961d9f0859b62ede344294bf63b39c73501", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["505564d18087b19bb65ff6a3b77d92c091f8e4c7a6c391db38a1a7b980674a4c43d31271578d327f1ee780db8b1df1b68d14e3e0e883b5b36403a06d68cec68f4e", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f20f49c8c8a09c2b68a66d3640886588c1e95299 b/txscript/data/taproot-ref/f20f49c8c8a09c2b68a66d3640886588c1e95299 new file mode 100644 index 0000000000..27b5356c7e --- /dev/null +++ b/txscript/data/taproot-ref/f20f49c8c8a09c2b68a66d3640886588c1e95299 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4901000000213507c5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5300000000f92f4bb6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf150100000091782beb0145d3670000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc4eafb2e", "prevouts": ["6e315000000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "96f25c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "60086b0000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fced35b867b7996fb51563de4ed354837a83892ec30e3bf6ca580b2c02aa0f9ad300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5174048a48c6eb42f280da39a6557d46ee4318cb4e3319043ed115bdbceba7fd7e7407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb445a42fba29499bdd7f6ed301115275954ea9ec94acc2dc80e39b9e79b601e9aa172fc08f39dec38a16acdaea6f2fb40d915f4bcb39aadc0ac96def6ea8d2de907407b97958d18eaa787c1cc29670cd8872e7fe2ef4ae33551cfe5c61fc2827ee"]}}, diff --git a/txscript/data/taproot-ref/f281cfc9b564fceae1f18905886e1a2ea6a79f8f b/txscript/data/taproot-ref/f281cfc9b564fceae1f18905886e1a2ea6a79f8f new file mode 100644 index 0000000000..b395b7873a --- /dev/null +++ b/txscript/data/taproot-ref/f281cfc9b564fceae1f18905886e1a2ea6a79f8f @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc7000000009095a1b0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb701000000a352ab8601a88993000000000017a914719f78084af863e000acd618ba76df97972236898739000000", "prevouts": ["dade750000000000225120d7a74e7d66477e5ce18f223a8c348977bbded01f23ea87f4513721d36eca07d5", "ccbd280000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_mis_3", "success": {"scriptSig": "", "witness": ["f0e4b330642ae27577f78ac81fd5af3c439a3cd130a668505cbc284e002db55d4da4533c1ef02836b6accdf97a78c84bf65b784119ea6e705ebdea90575341c1", "50ba592f23777ae38b527d1e68f48fbbd0597a4bd3512c0706cff7137b704520a6799688434c19b8a47faaa5b17c6887b3157b870a3c23288c8a8cbd09633106ac0a4ae8a59b92dbe9d5adb32aa66a90d0824a54e23936f4e8bd046cfff1c8d9b63774d6b0dbb485da602a7c96289a9aa07eb2248cb17ca8ad8af3b55c8b090e3abfda0e50755f980c8633d6044045c642c48ac87067"]}, "failure": {"scriptSig": "", "witness": ["776496b4f911f0697c460a01114e787f95fa7995f3b25255b937eab94f94397af2331eedeafce921e85ecfbff874f661187be0e9047de2a7ff06a7cb5ccd858d03", "508faf687e692be87644ca550eea652b1cd464122e1abd934e57354f21c84900652a187b4e9c5101ac2b49fcc7165c6a850bab92ea2123c52f"]}}, diff --git a/txscript/data/taproot-ref/f29cde4e4d18f502a83e953d7e6aafc162b49fb0 b/txscript/data/taproot-ref/f29cde4e4d18f502a83e953d7e6aafc162b49fb0 new file mode 100644 index 0000000000..26d23d88b5 --- /dev/null +++ b/txscript/data/taproot-ref/f29cde4e4d18f502a83e953d7e6aafc162b49fb0 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf05010000006c94ab778bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40c01000000a9aa24900176de0a000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a603010000", "prevouts": ["46617a00000000002257202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "f7ef3b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["80a38889277e6769c53ac3422cd17a5b04684959263ae1d4267f5e5d3300267c24c4f79d99ced191a71b09d34b0c3e867be45d2aac0ab8bf37496c932ecd79a6"]}}, diff --git a/txscript/data/taproot-ref/f2a7b6785e4184b100bb118d537c3e1fe7deed13 b/txscript/data/taproot-ref/f2a7b6785e4184b100bb118d537c3e1fe7deed13 new file mode 100644 index 0000000000..fe6f03e213 --- /dev/null +++ b/txscript/data/taproot-ref/f2a7b6785e4184b100bb118d537c3e1fe7deed13 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3001000000a624d4cc60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700802000000f83632e9019e1b0000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac56000000", "prevouts": ["d9161f000000000017a914e18c03fb168c1c1b3408ffb477de8ff77b0fbd9587", "c0db110000000000225120d6bee23394c39d6e16307905ff4e75971d1217bbe5d499666628583fea75678b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "eb7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9facd47700b8e47119238508fabe2c12c2c2868bd36dd1a15df7cf7a783bdc7d4f633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4a9e937f21fcad1bfe108fe60be9a324a720a35d98355df5fe53ca48d5593a6c6b"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e87d8de85c21b0b3fb0a3c0b5a47bf8fb76656439613f0da43488fdbdb40ca82a29e937f21fcad1bfe108fe60be9a324a720a35d98355df5fe53ca48d5593a6c6b"]}}, diff --git a/txscript/data/taproot-ref/f2aed5fc63d1322cbfa59dc10fc63c5c13905bad b/txscript/data/taproot-ref/f2aed5fc63d1322cbfa59dc10fc63c5c13905bad new file mode 100644 index 0000000000..52136dc124 --- /dev/null +++ b/txscript/data/taproot-ref/f2aed5fc63d1322cbfa59dc10fc63c5c13905bad @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf57000000008fef5e0960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a200000000630d7c750370197c00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac27da9e2b", "prevouts": ["6d146f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "35ba0f0000000000225120d1600e1e076c2da8b455f76340d5258bf45fecd0d78155a447a8b04344f8ccd4"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "1f7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362175f5032bb3b53c0a968ee3a2c82bc18dba93c9ba8710418637c72c2d6d5ab6ec0d930d2ad3e784600f5ffd1efb1e58c37063febb6da2a9c1576d111e3c4564ed661e9ebd30f651fa020177c2a1e4ce51b505c9194e43d6074b392863f250ba"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93675adb4fc0189a1382c89853bdffb590e4ee25bdb1025c4992edc4ac6fabdde4de576fdfccd5cb93347e3ba64a7809a8c9fb7be90a7e18659d0b981582f285e98b3e02c0e1665e1d6a4b6ef98a6ef3a3632c98688db315e4c8eb8907479035d72"]}}, diff --git a/txscript/data/taproot-ref/f2b01b12b747c63ff84c1d178f5cd881a09d61d3 b/txscript/data/taproot-ref/f2b01b12b747c63ff84c1d178f5cd881a09d61d3 new file mode 100644 index 0000000000..637d2dc654 --- /dev/null +++ b/txscript/data/taproot-ref/f2b01b12b747c63ff84c1d178f5cd881a09d61d3 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c440010000008819fbb38bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49f0000000080656b9904c66868000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787c7030000", "prevouts": ["455135000000000022512089bb171a5e185cc37daf7aa0871afa228227b6abbb83e8d3d329212a244ac814", "ebad34000000000017a914694a086836eef6461dc1e0510e2b2815c3da1cfc87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3044022076992d247ec2845d6864017ba617cc710fc6679143851d0990e851e5664b4b2e02206891148f8525123ea53574236cee83e0217b36ab019de5e769bf5762bfa3750d59", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "2200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "witness": ["3044022011c58ae31ff86478b242a709804f9c191da3cbfea8bdb58ce304a7d1fa32e15a02204220241dfe89c77fc08276827c3058791d477a294052753eca89c85dd52315b959", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/f2cf8fc04a84276827038c4814930bd1166dcb83 b/txscript/data/taproot-ref/f2cf8fc04a84276827038c4814930bd1166dcb83 new file mode 100644 index 0000000000..f0f5aeea7c --- /dev/null +++ b/txscript/data/taproot-ref/f2cf8fc04a84276827038c4814930bd1166dcb83 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b990000000015e6e6d3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b3c010000008991028ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6901000000414a92e6031b996c00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acd3000000", "prevouts": ["7bf1270000000000225f202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "1007280000000000225120e98e4d1ca072b074e8ce62a41eedb6ab06e3f93fe902ed968335e3f5f426ca3f", "867e1e0000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c3b743ad825b1ae728c2f1c4137682b4ff02b835bd4b7bdf42f6a798d36a71e5e07722f249c0241e62b789dc176f0288271b45f4ccd4acdaa89657f699a53419bb2c6df938780c1f04978657653ddf137825e301d5ad50b36cb6f0a81405322e76416e01666bc6a1cb261cc0f123e7cf1652eed5d0f4713fc4210a5fc106d9df48d1aa407ee6564ea9d7edd28cb03ea10a89783e3972a7a703c5db2d515a94a2c57e7a755ef6c5ee042c62c2ee9d3f95cfe637bc3bbd29cde92d9958e55e52eff742e84cd9569e3d058675330401d7e03f9a30beb48f7d18589efb1267ae02423a14bbc0859df1c4eb4214bf21f29fce6f28947f87ff5869fecb53761b28a0d9fc395e67c3f8a865060e8df463663f85313761b966e552649a58b67650680fd26d18521162978ca6a42352fc4c60be370cba6f839b9559a1f54749486dfe8cf879826e7e940ac8d38f1c03a7a51b367cfd5a30c19cc70bb14d708cbb61657315cb05f1761d152f0da2c8d28fff5a0d5542984b435732a0cd871130fe7b7037fbbd85e0251713ba6d64abe1a42172029d1099286934a1c8b2328f8c36661cca3b3675678cbaa07b7e0c6ab62e44b5a2d7d41234a7b48922d1ae08aa70af4724990ef11b8863c789a93405a13eff7d71edc6e7433414b334bd6f429140ec874fd3388662c7c600ee132004d4a4b8bbe3b575621ca1685dd5120bcd57cb82c268fb53cd69baeca84858b375e4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c351b40ac58314f065731b2e6ee4d3aaca3c0737d7eed49c686f1ff66e68fcdfd81cc5051f53cb756176679d36bd97691fe000700c9f2a0965e3d67cfda5d0f8a81c44a09079faa406e9dfe20ff322801dbd7fb1c55ee11d2e1c43aeb4d3cbdeaf2eb908b8657464a6ead7ee639edc82f346aa77dfb25920bb6227c2c4c35ffd"]}, "failure": {"scriptSig": "", "witness": ["4d0902bbc440d2c38048705b4157974c62c15679a2d924264f492f46fa562482574a88cd00fdb624964f032c7b891e760c6d561f4fb5115d63cf68d5cc64834e6e95649d90261a49ca9e34c9f9fc5b4d94e0761e2aae1ca65a116d00fc6202409f7b8e50a1ac3b7bb5a9b561b67d2cb37ca8371742007fb35074f136f18ef7fb3184831a254e3559b30df279d05c62b10a8e305210ec8bb8450f7cd9e9934f073e292470c91489d092c498adaadcca91ac797a0949065a4b491850122a56f254e741eda4c5e100f9573b7faae4da8826fbca2ad48120b0b8ddae58d4073790bc531675f6c5a1789407fac5677713747497835d4a523d66f930c1935046181fd99888952a2d07578ef8966661c941e2a415a6a3802ed20d791cb1e11b826641f2df11ec8d1457727a53377917f776f8fae2cc0fbddd2e2de9b29f13ac9d3cdfd2c24aaf160c6c3896d53af08c635499112d34b885e20d514190369f7716d063a8f4d2a2907c359cd9ba109b290329cf5694fb516d5a8ed08d477bd92047e270a84a8ff082a1538347cf09597de5cc3fc2ce73f33600c144254dc9787b14c650bae33b42b4c10a6d341bcb030ed24206a202867f9c38454e5514652b7c98eb9b3d5d6eb897dd0c522f3c52f11ae4e3c30a435de093f55390906d6be5fbcb7bf82898fb96ff4e03a14cf02f3ef4d514efe35f3394539f400d8a34e072457948a5fb98a70fa63d288c0987e8b2f37561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d007d93a2f34e060d7cc5cd39744499027b300a1a6c5700c758a8bb24cd5be060d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3e0b789927f620aeddbf74aea18c74264c468c5fe823a741d176e0a42636f367e46ec42a0fc3b2b57c90387175ef14e4ddb9fbb252ed168d3260bd00914c11302"]}}, diff --git a/txscript/data/taproot-ref/f306f010650c1ce3662a988f2d5c8848a114b742 b/txscript/data/taproot-ref/f306f010650c1ce3662a988f2d5c8848a114b742 new file mode 100644 index 0000000000..4987268a83 --- /dev/null +++ b/txscript/data/taproot-ref/f306f010650c1ce3662a988f2d5c8848a114b742 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4210000000088e395bbdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9e00000000065185d6011fae600000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc33040000", "prevouts": ["64d14100000000002251200aab5f0acbd570bedd550e6582d56f36bedceed0a29e5b4b9333b469d2c71737", "cfe726000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93680a36c50f8ef6c287427466622598093ce8ce9053bc22d3973767b96e5c582b7"]}, "failure": {"scriptSig": "", "witness": ["6aad616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f311f3194f27d91bd26c7ac20214d331ade7f1c9 b/txscript/data/taproot-ref/f311f3194f27d91bd26c7ac20214d331ade7f1c9 new file mode 100644 index 0000000000..592bd25a8a --- /dev/null +++ b/txscript/data/taproot-ref/f311f3194f27d91bd26c7ac20214d331ade7f1c9 @@ -0,0 +1 @@ +{"tx": "1b2bfb8902dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b780100000008eb22ab8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42600000000c4deaba3015955540000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc74506636", "prevouts": ["1b791f00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "c7163f0000000000225120de1091fc927c36de35363d478bd0613872bc5b94677334ee7c316f685fdd8d93"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "de7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936337de194323cc2d0e259e7f698dbd99f7b4adcc7bc7010d92bfb10064ddb4e563f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08267bf5ee6e785c98394c7354db9cd2cb879e9766d4c80c1499d7b3e856282bd13a05e4a06b32de803bd9a925f4d86502b21cf2d106a73f15ada31e997750cbc80"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93639134f96039a0fa33d353d3657d4f6c27571ed27c9ba3a414c0fc3979439528967bf5ee6e785c98394c7354db9cd2cb879e9766d4c80c1499d7b3e856282bd13a05e4a06b32de803bd9a925f4d86502b21cf2d106a73f15ada31e997750cbc80"]}}, diff --git a/txscript/data/taproot-ref/f32541dee791305368453ac147924b5c2d9dfff7 b/txscript/data/taproot-ref/f32541dee791305368453ac147924b5c2d9dfff7 new file mode 100644 index 0000000000..3cdd99ad4f --- /dev/null +++ b/txscript/data/taproot-ref/f32541dee791305368453ac147924b5c2d9dfff7 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8900000000e8a3feaa60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707c01000000afd25c9604adb63500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc65ed682f", "prevouts": ["d10f290000000000225120d1b58e92ff256598ad684e4e35c535f024a8511a42153841768436269707b6d1", "52ec0e0000000000225120a04971ad2b8c16a17e70d417eb355b323e82da2726ed216775e912c08433fa96"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902ea0e094034c5e6eb4c6031e9df0a3edf88d2031e7902cc2f751a948274f36cecb8308c36425a65e399229ca8616da8fc9a443a32cb426295828f29981941139df2d2045ea5a8332f99b43418ddeba4420c79fec9082d78325dc460cf6bf74caeb74bc07096985326770db739522f0f7e471d78d2edafcda7884589c570b574a8773120b4ebacbe20a5243295993a277823b0e2b996bbe943ac58a28ddd87e91eea56181dc3f34c5e44ee8c1e3e7bc1b2154967aa7e71fc8810b0e8855033999719c3238bdf5df21520d2eb31fd017829f95513941eb5983c8d9aebe44fefeac6b4a8c7e6ada0f18e71e76c02bf5a9889578ebca7b9a1c61568d1bfaab17bb9c4021fdbaaf5182fc271caa1dce8b8d9150067bc37e0023b3ac8d9403fc4f799830793c87604f69b0310f15020aeea5d6978128e84a08025566e793c7e394f43e4bd0fb1a6a7b107624e789c0bd509bb82de81cb13914cb6619e5da1f2cf9959e151bffcfffb6383b61888cf82e452e702b60d56fe2e36cdab57ad4faeae787bed212c425c8c19da4c89cb6806fdd78c26f28f9286bc2c6503b8bb4e694dba4c9d714859521409dc972b1e8f1eb75234a311d0ab775fcfbcf6ebfeda0238f5aa36e864ff4057bebe3aa5acba8487fe5af4e02fe94824a7cfde225ec22e5c7622791eb6ce6f5534e8f13ffc1243ccf528e2abd2d2c6a14669f58a9ab3121fdc3a59c8475a231bda08e2b375cb", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f53ffac04ec4df156873ff2ce8c8da5c67fc975976d2a82eb9a66b7e9ed214d120e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e191fd70f8e44f42202023c580ea06f1578af3f03a2439147535e7b1f16736e0d18859d05a814eb862cab9a6acf3b7acf0881c47896b22b56466b77992f62c0511"]}, "failure": {"scriptSig": "", "witness": ["4d0902fdb6b31fbf2ae8d66df0a611a81c789bea6696d01d691aa75aa7bc49217f89a97be1ff706ed8d47b85afd85daaa36c57ed1ffd25133aa10f3b13c1e9a92c95c7592a133d4660e49263b9913903b14537287f0a24d271d7ff58317cac16f46c1ea3e1d9dad0d8d33ad015df33f88f17664fd1557e66820ce5e6127ffeb4eb726715a876bfcc51a9f3f630ab567a41eeecdeb741820d54e43caaff93d8e931daf5857331dab922ba7262e31e0161f6783f2d29eb034deff5f510f5342b35cd40806b1ed465f7ac9c70377fc73e72ea99aa2479581f78174dba1b99dd17b299c723b59330c894f657c827f70c860ca17e9eec954a4984f1b47af2e3fc30aa34b523f8a92050bff7bc2af149480e368983c0d0c6c120400ef277603a1278eb4d70d3b6f270bd84825b50573217681b55c592348ff8ee587252bc0064b1c17c85732287e313f2dc8bf4c7a0460dd37bed0c2741aa921a5447aec3bdff57249408788dbd7b7740fa1d0edee98d7c6e6a8c569f8a16bc9081a79d3e88dbca03b6734f14429883fb7cca514419e5b59c7345de05291fee851f295d7f4cc86b7888bcf0f1cc4602d8c4d1aa8c67d743ad8f7c4b7e03ffdb3a1378ab17fdba3fc3658b885c3c7974f71e321daf7903a77ddb0446e293e8656e2c6762b694631fbb8f0ad04d0daf1907b41a6910322975bba188123c8afe21e03047617e66dd27050057e763f10a9baeebd2a8f4447561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936628965e7d974c507f702398db63655a3c25a623e9114254b8f562e8f543efbef70b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d865720d6d723e038e6335a667e0268d00f4826306437ee84552cc7f8172181160444ef73f74a88798a5fcf30fd7aa5fdae43144d667a238076c6d52287fea96c6e3fd1"]}}, diff --git a/txscript/data/taproot-ref/f34aa9739565ceed4d2a67fa8e24e1cffda032d0 b/txscript/data/taproot-ref/f34aa9739565ceed4d2a67fa8e24e1cffda032d0 new file mode 100644 index 0000000000..294085bdfc --- /dev/null +++ b/txscript/data/taproot-ref/f34aa9739565ceed4d2a67fa8e24e1cffda032d0 @@ -0,0 +1 @@ +{"tx": "64c16f4c0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700900000000414b74a060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700d010000005c64f2b20470e81c00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc733000000", "prevouts": ["d259100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "40f50e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_bc", "final": true, "success": {"scriptSig": "", "witness": ["86ebde0a97b9ac5e1fe581e0338422a4334a3070752cc547427cc67e4e79972fff8a03a01b4a85de9224f4748e7b54e0f702a8294ee5abc6607b9b43b1f58f7983", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["e5ce9a2a9092c727c83f017e2c3e1dff7e83820131d6451ba0643e6053c375a2e8b14c84ad5a4c0c475d87e8b2e739bc8c4788df6b419a169588acd93ede2fabbc", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f36797074db1a3316cf9f79b8cedbea196a94883 b/txscript/data/taproot-ref/f36797074db1a3316cf9f79b8cedbea196a94883 new file mode 100644 index 0000000000..338d7beea2 --- /dev/null +++ b/txscript/data/taproot-ref/f36797074db1a3316cf9f79b8cedbea196a94883 @@ -0,0 +1 @@ +{"tx": "15915fbf0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709900000000fb88b9dc8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c47d000000000fa7e7b903fc313e0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875b000000", "prevouts": ["55970f0000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "ca62310000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "367d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada435635f2cd61c9348f40975186bdc5a06175f59207abbbf8c9a9810dd12002cddd84017ed719a58f336e1892f80afe07727626533c4c78318e44c39862ffd3"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936041f230424bb8fbea78efad3eb719ee17a28dae5a1a9e7f1b55ee9d01d28ee75da435635f2cd61c9348f40975186bdc5a06175f59207abbbf8c9a9810dd12002cddd84017ed719a58f336e1892f80afe07727626533c4c78318e44c39862ffd3"]}}, diff --git a/txscript/data/taproot-ref/f3a1124f0e210f773fcb446a4c6325838f796dcd b/txscript/data/taproot-ref/f3a1124f0e210f773fcb446a4c6325838f796dcd new file mode 100644 index 0000000000..719c02e3d5 --- /dev/null +++ b/txscript/data/taproot-ref/f3a1124f0e210f773fcb446a4c6325838f796dcd @@ -0,0 +1 @@ +{"tx": "392083b603dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cf8010000000320c5cf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704701000000934072f4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8200000000df73f6d504ec96cd0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac1b08b24d", "prevouts": ["47805900000000002251204e3fb1c88f2893b13c1c33c3a0d0cd819c49ecb88ca3deab379ce318a8955811", "1ca9100000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "e5a5650000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f086534a94238de44df238570c9dd488e8c889ed3d519b7674a8cabbf1761d91"]}, "failure": {"scriptSig": "", "witness": ["6a39616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f3abe34a0b2b561230223ebd55fa58c1abfa4752 b/txscript/data/taproot-ref/f3abe34a0b2b561230223ebd55fa58c1abfa4752 new file mode 100644 index 0000000000..6f023a9317 --- /dev/null +++ b/txscript/data/taproot-ref/f3abe34a0b2b561230223ebd55fa58c1abfa4752 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127010000000008e090c5160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cd01000000885fa63502431e1c0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc8a000000", "prevouts": ["68d90f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "d1220f0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_2", "final": true, "success": {"scriptSig": "", "witness": ["de3e6296b539c5d43ba746df546722bcd0ae6fccfcde1791b4b3090311d145d44ac71ae37af183ab8fd2d6761d9e3d5bc8ed3fd820decc07d60599c01c2b802002", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}, "failure": {"scriptSig": "", "witness": ["c575125c0cae9f87297938fc1b4f162ef980f5458ed9333981f99a837ff75ccc9d18428235c2c340127231dda31a63b3c2afb31c3e74f35a587b4a61a75f9b3002", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936"]}}, diff --git a/txscript/data/taproot-ref/f3aefeaaf417737c9b08ddb588ac8f34f1bfd7c0 b/txscript/data/taproot-ref/f3aefeaaf417737c9b08ddb588ac8f34f1bfd7c0 new file mode 100644 index 0000000000..3a6d6ad9e1 --- /dev/null +++ b/txscript/data/taproot-ref/f3aefeaaf417737c9b08ddb588ac8f34f1bfd7c0 @@ -0,0 +1 @@ +{"tx": "50c82e5902dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc301000000530c23e0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9f000000006367e0c201cce1b500000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac97445a20", "prevouts": ["24234d0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7", "0cba7d0000000000225120f6ebc972e8b9359a70abca9662ec0add7397530b2d8a533f3315a928b489401f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902c6c81c190d27154708867b1912e00600f5e2aadf6695da87d92506f791f2d50df22c4110e6f50963c8aaa07a8b1f6f13e31272f737c2dfb86420c921d4e106300d97b6ff006e3f5381fdb806908db2ebd1b4b055814b5f6e3372c3a9f0b8cfe635cea4cf0a31bc6f7ac16acd7ee0f0302971cafba8d2c6a48e0464885538c1c0c3d683c1ce4c94f537c2363b8741da793676dc3541b9abed643ad3a672863582f11c70d48e4f983430d408a512c721a4b93565376c17081c7ea39f5552ac86cedaa18e9297a50c1293d88d3c2ef915a0878b49d3f9663131efb13f33d1129c69091231d141773654db9aecc95aa46518b68249cf219027c5349187b69eba6ae606a154410595b157aa9afa9156992e0ab68cd28e9932d008624d4ef659e4268c0555a1bdc833de6768e4d9fb6e8afb4a60cfeb1da2cc6bd6809e6bc3f0cbef415838f69920a477c892259d2e14678f90ac6ffac284d327289b987a37b66bd8972554cc997a4e0f9a0221ac727e9c76680f7017bec4cff5049e5778cfd8b66ae358282f9a20befa9a5e4ace98e9d8ccdc81dcfe0348e1c25871dcdaecadace9f4a784ede73e9c2727b5f7d13bcc25777be6ab788902a4b9e49f3f48aea1f034b8cf9cc99a8049058a0de716bdece82da3a6993b47ec85e767ea80352d1c5ff85d6ec7399108dc2dc273c66b798baf8f99516766ce211f35441300e2958e21c4b422c3d548014fe362ac7581", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a7634d18480d5775104fe67110de7da21df5ac87ea179725883df64beed806701d1058d265ad692c8fd0f688dbf18dd54d1f122592f426fec87ed7f5bf39e232f98bea6a80fea94b985145b0732d825e6fbd27add9cac654f3749fb201eaf5c0cdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}, "failure": {"scriptSig": "", "witness": ["4d090294888dc88238cf98041df8e3c1996005b78c0b1d0c47fadc0f0f9de29a1c58e5e1bf5d39bf5725da985df4565f9f7026bb0159ab38f5ff35371d7f3a0f39b5cd007ec86fd1711c9bc5ef8c3bf2b3913040a26ad3cb052a24ce7b496e6fea088ff23d86a2034095dab89d05399ec4d56f571d5e65648582695ee886e0de19fe51506815439cdb59b15b5dbfceff5b4c19d3a89ad971ef66685e79c82383d9440beffedb6dad95bbeea48565f39d5bc1a224ef530cf107d16ad69b0b700747cecf894543b1cfa1dc7bc939c7dd77ed6dc28967516eb34b32832a7cacab62b6f51211e7dad67a89899d6388257974e78134bc0c80e9ab302e5f4b22b2c55e489e02ac92617df9cf87d370a76d3d0a96dc3c9b1e84c65eef346404bacfd7f261443402facbee94c673bd20e4a28369ef37ee0bd5223a070fd1b87475592947a820873887b3878aecbea17b3277d8782a78620e354f8888d1042269422fc93f13960ddc7662550d2b770e3a8c230cc1cd03080423df1bd37646adb5cc5918f28e0cb7bd3b181d38f396bf628136e599d850472d7d8bfa5f848ea42bb3f9733fd7bdb0bce88979f136d60f05b8cd333f91987b83d262e7f1011f228dbe7bdc40f81b5ccb76c8a9e8425ace8a71ffe51812abf9bf00ae5b4f289f1b369fe442d449a41f1f7519be519efbdd2c03f7abaf4785dfc0f1dc74f79192cc1883a35f9c2bf037bd681f3154a7b418db7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361f65007fd58bd495e8e57cff0dbbf5483e3aa8e1943b9d4f8d3979ba8fb1336b1d1058d265ad692c8fd0f688dbf18dd54d1f122592f426fec87ed7f5bf39e232f98bea6a80fea94b985145b0732d825e6fbd27add9cac654f3749fb201eaf5c0cdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}}, diff --git a/txscript/data/taproot-ref/f3b9a054bd33583afbecffad0407dcd117b60cb8 b/txscript/data/taproot-ref/f3b9a054bd33583afbecffad0407dcd117b60cb8 new file mode 100644 index 0000000000..ac262e9902 --- /dev/null +++ b/txscript/data/taproot-ref/f3b9a054bd33583afbecffad0407dcd117b60cb8 @@ -0,0 +1 @@ +{"tx": "a117860f03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc701000000bdcfc3bfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5600000000a3e6ebc160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e2000000008a5cc9e102a66ab2000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7d1010000", "prevouts": ["8417810000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1a8a2400000000002251200653636fe1575a3601b4d73c1ea9151f68d884d4a6f1db0400b56f492c494afc", "27c20e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "317d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936def5188e99593db0c47de29d7d0d72f3d5f471d35a035eb3d04eaa88af1d74c23f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08228c5b97b98364e562d83f29d0f7226f72eeb298058e828607471d679ccabea05a4517c545b323e839a783e2c84e61e1f1046ec65ac2c085bba4fcd3b8ecf0c89"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362f419aa769806fe430d3ce09ee6cb2fadfcf1c0d8c9e17198fe43e74e8367efd14e57181048ac96cb53327a8f686080e72dc312071604fe817a5f66426afc20b12f65ebf74c8b951b09da599ea3d6f486010b8cccb0a2142ec39aae62c1ca3e7"]}}, diff --git a/txscript/data/taproot-ref/f3c37d9c9bc7bbacd5acc05ecfa2dd6b3e4079be b/txscript/data/taproot-ref/f3c37d9c9bc7bbacd5acc05ecfa2dd6b3e4079be new file mode 100644 index 0000000000..f9343ee852 --- /dev/null +++ b/txscript/data/taproot-ref/f3c37d9c9bc7bbacd5acc05ecfa2dd6b3e4079be @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf301000000f07fa784bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa100000000b808a1ce027a278e0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88aca0020000", "prevouts": ["830c27000000000022512019e1bca5d0c34a5bdc7dee301e7e444158f02d22ac120f0d8dd3e9f4121adc33", "027e690000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_eb", "final": true, "success": {"scriptSig": "", "witness": ["685ef156cf62d73f7cdfa2aaa38d597851af2e5a1174e6ba21f74069c7a7f652bf2a89669337c2df5864303f99ab421b6db4a112c06a3c780a0134634e047c7d82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["f95025e4e7746f2556748bfd41186c9f0acef9c795b926a51868bef67c11f8e5d7352ae4b83789271bd1a422e300028aefbf519b2f5ff63164e56ca26d145bb6eb", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f3dbd1cd81a692630c41a036e51a108069161d76 b/txscript/data/taproot-ref/f3dbd1cd81a692630c41a036e51a108069161d76 new file mode 100644 index 0000000000..a08729e6dd --- /dev/null +++ b/txscript/data/taproot-ref/f3dbd1cd81a692630c41a036e51a108069161d76 @@ -0,0 +1 @@ +{"tx": "56b4ad660260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708400000000a354aaeb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c6010000007d9bcf8c03f5b61c000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e746000000", "prevouts": ["81920e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74e50f000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/purepk", "final": true, "success": {"scriptSig": "", "witness": ["4f07e41f1e1869cb4e84b4b46e6b2becec9328e827c5508bd00b3ee6afaed6458a6cffa6a91593edf6921924e6549ffb69761dbc1575f6dcad78da8214ef9f40"]}, "failure": {"scriptSig": "", "witness": ["35a0b0e7fea0af4106791c6c8dc56cfee58a4fdd22f6710db193fef66db2972674f7aa041d4a50f478797756b9fe2bc180bf8f925d0aa702788f4067e8fb3507"]}}, diff --git a/txscript/data/taproot-ref/f41b245dc4b63227dcd52bf8df204c69ef2c632d b/txscript/data/taproot-ref/f41b245dc4b63227dcd52bf8df204c69ef2c632d new file mode 100644 index 0000000000..39468dd425 --- /dev/null +++ b/txscript/data/taproot-ref/f41b245dc4b63227dcd52bf8df204c69ef2c632d @@ -0,0 +1 @@ +{"tx": "927a8af202dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0902000000a680769e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c499000000003a7254960188a41e000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47871c050000", "prevouts": ["48375e00000000002251207492be7c38200a6f417f2df61c3857d7747fae6fd7807509c1951e5f14ba63da", "babb340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "d0", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364c3da4617f1ee0f61cdd6b0c3800e0774a5e631cb6cd048785fdfa88f1b1ef57f81a0ae7b640e88bbe84e7c412f47337f1d12d37f95b062c539998fd28213cbdf3b3fb8d5121830dc5ea13d084a01bce62f4c2426ea7fcb92dda33a6ec3d9661"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef4a0b996a651997ca76f2d80ba069e4ceeac28cbc038cb062656a276693f78c3bd101e45a609d3b8e0b3b6f0b7594624f7e9102ef5d5dd3027418de40ebb2180d690b53af7dfcad925f9834a18ad2ddc318ee8f8616a880729dbc2fd60dfccd"]}}, diff --git a/txscript/data/taproot-ref/f43a467e1ed501e4fae97b23c7ac5f51943b4a60 b/txscript/data/taproot-ref/f43a467e1ed501e4fae97b23c7ac5f51943b4a60 new file mode 100644 index 0000000000..792e2f6e81 --- /dev/null +++ b/txscript/data/taproot-ref/f43a467e1ed501e4fae97b23c7ac5f51943b4a60 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb401000000f091c7dadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf100000000be70b49003eef1a400000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6a491a81e", "prevouts": ["c76f8000000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190", "24862600000000002251208ba879939f2c6ad8b8ece6e7af2596449dcd53da6e9921656ed46c920282904d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902f76e832bccd01ebee3e3deb319aba4ff88054cd436a3bba64686bca9e093f588d862b5a59fc063cab1b3a383af372fa19a411d4a5078bf9ebfbaacec0e3152375cd0faa3c105b50cad764301ace5ba285e9bc80b2e66e84300c5aaf77cc1ac70ded079305b3fcb0016b0f642d20c98b6ba892f1e1f79353e013e926aee39f8278c92da8d29ca778b6c89558cd24b534ff2fc7d974c0b341a7bd2810d8aafe0940a9471b29f75ceb48659c5ac1d73ac8286841c09f8d5271aca3e4904b74a3a9fd4cb1c8fcbb961be477a22608dcbe76b13e3793f1611dae000e0f7fee8935471de81e262cfafc30719059c00db405f8e5216878441d3174d59729ed35df6e898a144dccf8d3258d77591d29b059d2b887c048f566d56dd28069a5bd6157dc294f8e3d228965f08e199095cad2d3990971e68be174c76587c416e61c2738dac7dbc823ebcf6eff0c9dada42d91667c474e8d5309a8cd5b25aa0348a66dc9ba987827271e077d79f6e31d5e02ae05dbfb533a16545261c0aace40e640deda1a1907ea5504d9e40ea86ccba1d1f132c15cd9e9a55facf7bb9422a28697023ecb566ae706e4e98abe581460b4426c0e51d0b685ffd58f51747008b61a04111630d72a2e144d1752c0b0dc2f92af0a47f6da7ead72259364f7f5433040128816f9f6efe8dc0cd95976b7a0f9f11c090023cab8085a9715eb951c8ef41945a6f735ab7d4429f272d96ac8b1b75d2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f27a0285e06e4d6dd48a2aa2db1f8735e89b1fe8bbcf48293d2d44c61aedd6c7536798c57c197a746bb2ed7f28bea5bf32719d74447f5bf93d90a00b781807a2845c4b1f0ef9796b099f7837236ca3239de7da07050a4e4f568f49f6a65718f105f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}, "failure": {"scriptSig": "", "witness": ["4d09025c60a37c5d0b8cdb3cd5ad1de44f9c13610bab8a2957eca32f397892def18c271db72dc7768c9e6badd7eeff51340c6159b1ae4098b01890d1e0eb43e810f73673788887f77c361956f69e57e7a1eed5c0d91f9cec1d6eb3ee17be0cb073d455aa700f15f970789270e4cb308357a4f37db3ee6123ceb7effed95788743cccd1ebb796f5af727cbaf45c256d029c769dba242207c78b822ef9ce7ef473f60f97a1aa71d1c49fc355a00fe2ca17ebcd085f1688eb94c28e219dcfac85a82e3a15c13fb67fd930b1efcbea5d61971c10e37cebb60fbc96ee4d71adaa9e127bd56ae60b93d2ed53df8df859c1d92f0750a38699aea78922e2e0ebeceb39cc68bdfe65ebddf4b0b3c9d79808c7c5bee00c6a5d248cf33cf46de648ef5f05f552292e10883855b292e8683bf850b1f7801f0f7ead5288670aa3868493b44c0762368e5678c8015697a1d26525586ef97ea1d42ae4055e13b6443d5b03b2d75aa13200f677bb63e48b6f76b36091e5475890f3139ab9210c4624a799c14861168ceeb3fc2a14844625c662dceb9219925c3a06c4d9c598c3fde4be3c14cf51c7180a353d50e84eabff5ab415ea7ee5c10e8e69a34573a019daf4e92524d172746f17dd6ea89ab06b56c35a8820d9cde59cb6c3f4e83e726013d05cb9e96846eb60ab1779db3f489eb46da2802680825c1e97157e6237cde850ed7950a3c2a6993dc4b7fe8cfe89205cb88fe57561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365b5b9e30f4b23104a86460dbf05c99022233dbfc847410bd2050778598c1a2352bdb5955fa247e32681f749888c9d4f86e5604dd03da59f821ad9d541fb8adcb845c4b1f0ef9796b099f7837236ca3239de7da07050a4e4f568f49f6a65718f105f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}}, diff --git a/txscript/data/taproot-ref/f4466a6264c406cffaf61cd062c6954b8145b827 b/txscript/data/taproot-ref/f4466a6264c406cffaf61cd062c6954b8145b827 new file mode 100644 index 0000000000..94e0e5e587 --- /dev/null +++ b/txscript/data/taproot-ref/f4466a6264c406cffaf61cd062c6954b8145b827 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c040000000044ed024cdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bef00000000056c24ad01f45650000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748779000000", "prevouts": ["6a234a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4a73280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_92", "final": true, "success": {"scriptSig": "", "witness": ["929ed163ff0f1968403a7b8395e155526bcc85f85a7f9dea235fecc15b898dff635386de83b54e1f267e640b3362afae10f7cd3cd3ea31890c3a653e49f5c71882", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5116b9156699710958f2f334ea1767e885d13a6e46bb2d6584166491503cbd57c4527619c26e46df6cdc7c97eaa9c6d6d2d0fae6b7ca1341a18815e7c94d88e292", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f45bfc326aa2978cf872bbd25ac92e74c51b222c b/txscript/data/taproot-ref/f45bfc326aa2978cf872bbd25ac92e74c51b222c new file mode 100644 index 0000000000..f11c43506a --- /dev/null +++ b/txscript/data/taproot-ref/f45bfc326aa2978cf872bbd25ac92e74c51b222c @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706201000000f53fbee960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127004010000008b79075601f01c0f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac54000000", "prevouts": ["cf231300000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9", "bfe7110000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "d07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e81c85c730685924be02f7d46bcb10c9c474c6189388cc381e7f7055dcad1cfa477e36b196311c1a9d305bc653889017f46f4c4934a1587d131a83127df4466fae"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b0d5e55afeda99172050d01357d6d8287f4824ba4286577d269d78bc9373ff36ef78ec8d95f7a630a87f4a69d09adcdf12479e6b3f8e7304927bbc129b24d5867420b3503815f4c7b180839898c4c4aff0ab6ef4d8b082708dba105a321f7428"]}}, diff --git a/txscript/data/taproot-ref/f4604f24ef1262cff35502c140d3a3ab09e62650 b/txscript/data/taproot-ref/f4604f24ef1262cff35502c140d3a3ab09e62650 new file mode 100644 index 0000000000..c71ba1c69d --- /dev/null +++ b/txscript/data/taproot-ref/f4604f24ef1262cff35502c140d3a3ab09e62650 @@ -0,0 +1 @@ +{"tx": "cdcd5a9802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa500000000b8ae7dc6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bde000000003c6de5f402e5588f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acc9000000", "prevouts": ["a5346f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e224230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_77", "final": true, "success": {"scriptSig": "", "witness": ["8c0047ba119d7105191261fc39d1282732eee7d88f438175d67723eebfc51ab36ea0ab5cbf93e3b0a20db2f749e37a1c1ad944e447887aa161ea142c1497c81803"]}, "failure": {"scriptSig": "", "witness": ["f72adece7342a4fe15d2acd2a7203104f1aa7deef53061d3eae495a89b722824b8dedb456d14e95fe589fe4da91f6f3ec12b414c0650506d3292b419ac15a9db77"]}}, diff --git a/txscript/data/taproot-ref/f47e1dd86121d4d47b5e315b8bc8f941d5c890ba b/txscript/data/taproot-ref/f47e1dd86121d4d47b5e315b8bc8f941d5c890ba new file mode 100644 index 0000000000..558e534e4a --- /dev/null +++ b/txscript/data/taproot-ref/f47e1dd86121d4d47b5e315b8bc8f941d5c890ba @@ -0,0 +1 @@ +{"tx": "02000000038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b600000000e9c7f4e6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bcc00000000ae03d8a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b63000000004e7e6ee9020bc17c00000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acc8010000", "prevouts": ["529f330000000000225120973a94e36a4a923b8d161b8fe153210f91b56b5e4fa7540d30da78859ffb8897", "1b20280000000000225120035d0d8894332b18eeb5087880b9b7fe7a878dc0e9a501d9b85908b60f4f194b", "d2c2230000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "4e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08230e8cb56a1cc46a8845ca28d4847c7375475f2f7976a44b43884e49f27807546ab153920b849b6028620ffd2b7e486a6f5e2411aa058dab621c72a45f67f5d8e"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936323ef28f4e99bb17bfac2f1234bc4bec8e02dbcd7bd8742e9803ed76c3e6ec8530e8cb56a1cc46a8845ca28d4847c7375475f2f7976a44b43884e49f27807546ab153920b849b6028620ffd2b7e486a6f5e2411aa058dab621c72a45f67f5d8e"]}}, diff --git a/txscript/data/taproot-ref/f49204f8e85d64be3490b7843476939194bca10c b/txscript/data/taproot-ref/f49204f8e85d64be3490b7843476939194bca10c new file mode 100644 index 0000000000..a9dadee231 --- /dev/null +++ b/txscript/data/taproot-ref/f49204f8e85d64be3490b7843476939194bca10c @@ -0,0 +1 @@ +{"tx": "e40f700a02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5d01000000e6a4029260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912708d00000000b040e98602ca483700000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72b040000", "prevouts": ["7b45280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2d0d120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_c", "final": true, "success": {"scriptSig": "", "witness": ["72d1d9985f2bb5f99db483d506f51dd7e1dd9b478d640f64ab7e50b4d632d63395182d40a5c1fdb413f6229fcf5b28aa09c465b3b0255fe1a7fe362a8f5e075901", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["0e56dc3d5f52661da4eb15a7f497abb14e4a556b13019d3eeb299b53b3b04e35945df7b2a495fd6a25aca05cf77af2eaf385c06dba788bed111780c2e85709440c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f4cc235e3a3e0f11b34f866c952d52ba470ce96c b/txscript/data/taproot-ref/f4cc235e3a3e0f11b34f866c952d52ba470ce96c new file mode 100644 index 0000000000..12fb7960c6 --- /dev/null +++ b/txscript/data/taproot-ref/f4cc235e3a3e0f11b34f866c952d52ba470ce96c @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48e010000001eafe6a2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5900000000fd8a98450287b78a000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac6f000000", "prevouts": ["9605370000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "21fa55000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "a77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fada584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e389e677eaf5eeea89a70f01c0aa3bc14cf3320f4b6dd8cc61f33138af3398b5b11a008161139ac7a92b00665158d25501a881aeebdfdbf881ee45b85e0726c11"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363e9eb096ec4c0e60b6c49349abcbb61376af9764a0a95f04ae72fcd7b6082681146d6305f54208d13896b102f4aea30badeaee99896cb007ba6ff00553e24c3b2915fd873a4966f8e9b4a3b328eef3933245a1c852c287990317c3760d8289da96773453f0744a158be0509abdec64f05b1db7ccf03251d8359952271b442a24"]}}, diff --git a/txscript/data/taproot-ref/f4e60bca3a955a55d00e4186db841023ceef4e20 b/txscript/data/taproot-ref/f4e60bca3a955a55d00e4186db841023ceef4e20 new file mode 100644 index 0000000000..9c679c28c0 --- /dev/null +++ b/txscript/data/taproot-ref/f4e60bca3a955a55d00e4186db841023ceef4e20 @@ -0,0 +1 @@ +{"tx": "a5ed58ed0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d00000000034e4feb1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0200000000551f05a603895f38000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac388b6049", "prevouts": ["0a9b11000000000017a914124ce61ffefcd78a2e382c17cb257bb0bdd741e387", "7181280000000000225120bb7ba78fb938249831f92608d0f71e24d86e7660c51dd93d52c4bb7a103fd2d9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "473044022077abc4cc6b7cd5d91ef1175435e1083fd35d2b7681733ffe6a07b7e80a90f19d02205ca8f3d8a33ee788395ad27c52bef0c43d0e251f548f9ca3a7ce2976afe576da81232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}, "failure": {"scriptSig": "483045022100ab43b4ecd06deb2c157ca010f94c1b58a8909e5d7715a349f80a42d8015fab37022024dc6e2228d2b16af1111b94da45d43a8b82672c1557405441724d7b92e712ed81232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "witness": []}}, diff --git a/txscript/data/taproot-ref/f50995c18b1bea7d6e8f78c8db8139687517a781 b/txscript/data/taproot-ref/f50995c18b1bea7d6e8f78c8db8139687517a781 new file mode 100644 index 0000000000..52642e2dd4 --- /dev/null +++ b/txscript/data/taproot-ref/f50995c18b1bea7d6e8f78c8db8139687517a781 @@ -0,0 +1 @@ +{"tx": "143da98402dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b440000000025c5a983dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1f0000000038ac8a9d039d224200000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e764451426", "prevouts": ["d3781e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "694a250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_dc", "final": true, "success": {"scriptSig": "", "witness": ["29ea9629f262b3ba7fbe2f9ae3264dce36ab42ddfbf22e319e2abebd7ee781bce6078cb25373936251d6b339549f142453c46a29b6346c6f1a2c9a36d857856f82"]}, "failure": {"scriptSig": "", "witness": ["796c8696d784442be86ab003b2b733669ece34a03828c19c9a994a9a2b0775e2fb3e9b528c99c92386ac583edd69176dd3993c6d52b5a7ec33d90393d4200c09dc"]}}, diff --git a/txscript/data/taproot-ref/f50bbc9cda906042a1e0c756df37b20c36a36df6 b/txscript/data/taproot-ref/f50bbc9cda906042a1e0c756df37b20c36a36df6 new file mode 100644 index 0000000000..1bb4cbf15d --- /dev/null +++ b/txscript/data/taproot-ref/f50bbc9cda906042a1e0c756df37b20c36a36df6 @@ -0,0 +1 @@ +{"tx": "8afa4c8302bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1b020000003cfad686bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5401000000082929ed0293b5f3000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7ba010000", "prevouts": ["962f7b0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "51277a000000000022512066359af2a4c6a03e108cd4566fff7ab36618284805810b34acf3d4b4f5538ce7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_97", "final": true, "success": {"scriptSig": "", "witness": ["ca3f7f1c7693625df3183e3c6e056b4d9107ebfda286fa1c63bac9824200f327f1546e36c20e959d2c2075dac800413d5d66982bd496abfd0962d5223ec2451503"]}, "failure": {"scriptSig": "", "witness": ["40086b6d183ac46211ee43153780b3bc677fddbe93aa07e7de7fcfb3811e130ef6041c90798758373405f1e89a4b819556afc76a305b8d17204c9755e38c6e9b97"]}}, diff --git a/txscript/data/taproot-ref/f54e6bed090f658f483733605be1def47c4a00f1 b/txscript/data/taproot-ref/f54e6bed090f658f483733605be1def47c4a00f1 new file mode 100644 index 0000000000..4e95b1fd84 --- /dev/null +++ b/txscript/data/taproot-ref/f54e6bed090f658f483733605be1def47c4a00f1 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c601000000236a23f860f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127010020000006b91e6da01a7a13100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac3e000000", "prevouts": ["83e233000000000017a9149ae30fb20c1ccf139e5b5804cecde274bac08df787", "2cb5100000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "9a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936385b7c6b5b390243aefe4c626f55742daed642572f577c299043227d557e4d8e703c0353c01e1109d81375c08919405978bc042794caf82a403da05ca89d0cdeef17902325999cb16876d9e124f321b7a2400c6233e0b61b95917979ea167214"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c31382c7cae07a09a83f26d089aa1893801559adf71a019d4b3fb52cf4a1693575ccfc706e32ae7f6b2a63f59d728082bfb2443bbee0d6dae87ff94b5ceebef57e56d08eecb8b548a03ce82dd22dc92a64f1be159e88ba8944ed4666490b777c"]}}, diff --git a/txscript/data/taproot-ref/f5584e332423dfd006828addcbd73f040328b087 b/txscript/data/taproot-ref/f5584e332423dfd006828addcbd73f040328b087 new file mode 100644 index 0000000000..830fe3f92d --- /dev/null +++ b/txscript/data/taproot-ref/f5584e332423dfd006828addcbd73f040328b087 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c38010000002c06be89dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7a00000000a16685fd60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c7010000002dd89bb302d4447e000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4870e000000", "prevouts": ["c10b4a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0b942700000000004c635b2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ba5c87672102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac68", "29fb0e0000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ade", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361358df4a1c3a93eee872ed849c2733aa302b60a4d8b7bf0bf84905e283593e8220e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1aac1f02719ff09c82d93c60ae8b21e31f1ec3fca4030b09dbe2604c5a66091c209208a3d5cb0b20fec302022af702ea090b934668d0752a16a75cba2aae8c677"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08299aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb423dda11617dc042479e1d576056805c31872018ddbd603e5e1ceb926e90a3395bf82ba79f2fbafe67448595b33026800f76a879cdfc27419c1eb96837433fbad"]}}, diff --git a/txscript/data/taproot-ref/f558bde45b06e08703659c22eb17a9b25f4941d1 b/txscript/data/taproot-ref/f558bde45b06e08703659c22eb17a9b25f4941d1 new file mode 100644 index 0000000000..2b000c60a0 --- /dev/null +++ b/txscript/data/taproot-ref/f558bde45b06e08703659c22eb17a9b25f4941d1 @@ -0,0 +1 @@ +{"tx": "fb4d73380260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700b020000008922b8d1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b10020000009e066ca8014bde00000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87e8020000", "prevouts": ["02ba0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5647260000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e14c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366ed0e779cc15e2a03d2e3d97c8cf6c7506658d81da92e90af03d7b12593133764b04f8f54a0a76ae0e4c7aeaaef28ce29fe1b2cd8b193a4d28e758ec231d2b883bd198ccbfa9c702c0592bb8c84a948c36ef9eddfd1aec8278a333dab45811656e171838972c3c3a6cdacf031a4825f83b841697bfdf19ec3d087e2c9ca65f0b"]}, "failure": {"scriptSig": "", "witness": ["4c52e1", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b8e2daca36c32f10b24a19a8031edd6fcfb8e5c5d75e4dfb877ce341a790b8466ee26669afb6dac63e75f53b4cae6cf36ae7535fe99100c6f349ffc46155d224f44ecb3bab6b962a7ffa14a2ce082ec551943f33ce508b63a8ee30ee5e49264"]}}, diff --git a/txscript/data/taproot-ref/f560ba3291103bb7f5cc015586c6946d5f9e8857 b/txscript/data/taproot-ref/f560ba3291103bb7f5cc015586c6946d5f9e8857 new file mode 100644 index 0000000000..4646985b4f --- /dev/null +++ b/txscript/data/taproot-ref/f560ba3291103bb7f5cc015586c6946d5f9e8857 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7001000000a1395d8cbcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff900000000c2c480d30471ffe6000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e733000000", "prevouts": ["a365820000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e03f670000000000225120f6b24239f005e5ad8a4113ec06c48cda726a0e511c023e717379412f24fce34c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/branched_codesep/right", "success": {"scriptSig": "", "witness": ["fced320f12908ab9299f9f2d8bfa76596ed6f1097c6f43f0f9410f41789b92c683585cf63979859ba714c37c2da2d50fb16e8f2f1d7652476d3d10dad6c5123e81", "", "4cfe26427fc7901b4262f3d916bc0dd8633c30e5af8ceea1dcacd253c102db78cd839b841955f61e94bf7285a2d0e43879ae3b488b8a01e39fb2cd2bafad8fa0106bbb3fade1a7f218e6696679e4d9a0064d7cfa56e38fbce9d589ae3f102c474c244515d6deda3c971875a105d875417da42bab76fa2a27b69ca61e195bbd59e9cd2768feb7ca6768e59331499fe3edd07b3541fad96c6dd5163816913f7c6f555b72f3810c341f5ef952f6cca9fcec7a4eedbd279af7c38d57c9fb075a83b87ca30e3f546f1d56461fddbec204d0d88a9eacf4b14d4a45fdd445f343e09b7eafa0d24b8c53bef7fbf18b28e1f65ddcba4f4f353831e32a3a7c6483034fcf747563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cbbc2d3d740d8643b25368816a3e2bcc8f965749028964b311d1dfcdbc4a53b754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "50fb21868826d5606c3dff3f36b025df0d3b561df6b9510e73489d482c0e7e3480fb67be3ddd2170aa8bf5159c12d8adcedb8dc6e0f499e39970e07cd46507b0b4b7fdab416239c7a124007a3810e88f9e40ac0bde38d32ccf66c7ba92a36b1fa36bdcd7a0efa5552df0f7fa1ca6395d1c8c203acc31622ef1af08d70793cea67b57de206c1800c40f69e73a6fcc2b9e9e77ae6c92d0705fc01b388e7fd9d6b0084c"]}, "failure": {"scriptSig": "", "witness": ["643136c013061262ba2d0702ecf7902bf1e0d3372ac8ee76245fa0f56441b080abdf8d8ac7d8f6abf211c5528a5a74ec91f0e1ec983ff874f3b05c42046763b982", "", "4cfe26427fc7901b4262f3d916bc0dd8633c30e5af8ceea1dcacd253c102db78cd839b841955f61e94bf7285a2d0e43879ae3b488b8a01e39fb2cd2bafad8fa0106bbb3fade1a7f218e6696679e4d9a0064d7cfa56e38fbce9d589ae3f102c474c244515d6deda3c971875a105d875417da42bab76fa2a27b69ca61e195bbd59e9cd2768feb7ca6768e59331499fe3edd07b3541fad96c6dd5163816913f7c6f555b72f3810c341f5ef952f6cca9fcec7a4eedbd279af7c38d57c9fb075a83b87ca30e3f546f1d56461fddbec204d0d88a9eacf4b14d4a45fdd445f343e09b7eafa0d24b8c53bef7fbf18b28e1f65ddcba4f4f353831e32a3a7c6483034fcf747563ab207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93667ab20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2068ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cbbc2d3d740d8643b25368816a3e2bcc8f965749028964b311d1dfcdbc4a53b754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629", "509984bd2dd4b2f9e02fde492614c99ea2a4bb6004b5adffdd1b6296c65cf81752cf3a84e2201b04c0f30a1d57ca53e99e2d25c08d6a19ecbd287f2c867cac45f61ccf3d68064d77d68eebd6b306e37ad94d3941c9e2cab123206b274c3591255c7cbba61c6102bacbe52b4d2c14a88cd687ca07cf609da9fab9a2b9d5889a72de2db2c3"]}}, diff --git a/txscript/data/taproot-ref/f58c6d8117f18e36e7e31efdf23c18aea2a31b7c b/txscript/data/taproot-ref/f58c6d8117f18e36e7e31efdf23c18aea2a31b7c new file mode 100644 index 0000000000..558f043d90 --- /dev/null +++ b/txscript/data/taproot-ref/f58c6d8117f18e36e7e31efdf23c18aea2a31b7c @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc301000000859e9063bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfdc01000000d82019748bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c431000000003461614d047e0708010000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487e9103047", "prevouts": ["f007760000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847", "93d9610000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587", "f14b320000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368c95805bfbd60030f39f9e7ff54381e8f5f456ab69fdb578716fcf2f064cb19a3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08208660b63218e506e6f6271f897377780851eb071546e65f7287d9a4083d90048d0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c599d2b9d61b74acf4ac0275e657007f4671c4b15d8de5ed816ccf5810b1da1108660b63218e506e6f6271f897377780851eb071546e65f7287d9a4083d90048d0ff373d5c06b418f4c5ba421f2e23a69b22cb6c2b7cf326686bcbc29e387cfa"]}}, diff --git a/txscript/data/taproot-ref/f5a0c3cda376e7bd8f7a27caa053bef8617f451b b/txscript/data/taproot-ref/f5a0c3cda376e7bd8f7a27caa053bef8617f451b new file mode 100644 index 0000000000..30502ebdfc --- /dev/null +++ b/txscript/data/taproot-ref/f5a0c3cda376e7bd8f7a27caa053bef8617f451b @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b930100000044a29d078bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40600000000ce8be267bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffd000000004601938b033b82dc0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac33000000", "prevouts": ["0ba127000000000017a914e014b0ed75ce4306970c9f63e88b08a5a7bb4d0f87", "44813e0000000000225120bb7c940411adc6c3ebf9039e294ad28122b4469bbe77b36f9a131b3cbe33d3d3", "691a790000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["00639568", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e178d069a3e06f8a8ee706e51fefe68609e4a48214bf7e1dad1e46f763a0ae6da54d6fbd68a9aac62cc0fc4848936fa6d465cb32a19d5a751074f74d9c4f7fb368ab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366daa55a1279544c862a5cabf14f22e4ccb66433690cdbb1ccf1805df6ac4593ccf76285204aedeb2e654c32bdcb90a470f0de651bfbe7b8c0c018e8a9ed468384d6fbd68a9aac62cc0fc4848936fa6d465cb32a19d5a751074f74d9c4f7fb368ab0b669047babd6208c97c1428e12fb9e633b2b0d2e51b7853d96a7caae1fe0d"]}}, diff --git a/txscript/data/taproot-ref/f5a0cbe081c8037a7f36d438e758b6bcd92abcbc b/txscript/data/taproot-ref/f5a0cbe081c8037a7f36d438e758b6bcd92abcbc new file mode 100644 index 0000000000..fb4492a9e0 --- /dev/null +++ b/txscript/data/taproot-ref/f5a0cbe081c8037a7f36d438e758b6bcd92abcbc @@ -0,0 +1 @@ +{"tx": "0100000001dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bee01000000c25d89b703362d1d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e72c000000", "prevouts": ["43c71f0000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "9a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e75ccfc706e32ae7f6b2a63f59d728082bfb2443bbee0d6dae87ff94b5ceebef57e56d08eecb8b548a03ce82dd22dc92a64f1be159e88ba8944ed4666490b777c"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e2d1c68c4ff0ed36e6c29e775aa83ecac22e61e24b7e7dc940647d04cc43fa53e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e874224dbe9932044562df2f9dbf2ed3a87afba7bd9cf6855f9f40e4c24add8036ef17902325999cb16876d9e124f321b7a2400c6233e0b61b95917979ea167214"]}}, diff --git a/txscript/data/taproot-ref/f5a7ff2dc8ee9ec1ef36b73c60de71d7978d3d27 b/txscript/data/taproot-ref/f5a7ff2dc8ee9ec1ef36b73c60de71d7978d3d27 new file mode 100644 index 0000000000..480b62f930 --- /dev/null +++ b/txscript/data/taproot-ref/f5a7ff2dc8ee9ec1ef36b73c60de71d7978d3d27 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c900100000041cd9365dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb300000000928020b40148ac3f0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e734010000", "prevouts": ["e292480000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156", "0e52270000000000215f1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["75cb4bd766694d40394530cd857fe437a01fcddde654f7ed68e78fb2bb074efe7598f030701efdb0578b746a828aaff9ace293ebfd9965fdf5c286a0e8d69774", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/f5b5807a9afa7c7b8351abe9a32cdd85d696c15e b/txscript/data/taproot-ref/f5b5807a9afa7c7b8351abe9a32cdd85d696c15e new file mode 100644 index 0000000000..b57b18bc4a --- /dev/null +++ b/txscript/data/taproot-ref/f5b5807a9afa7c7b8351abe9a32cdd85d696c15e @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270130000000018cebe6901988808000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787e4020000", "prevouts": ["3e88120000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["d14c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4595f1c75585029ef5fafe40c7b455be7b6317879deb123e683907f6588babc52172c8da9bdd43b70cbab8912ef1aa7926e5ad7e47a4f7b71ac936200cc947dd0f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}, "failure": {"scriptSig": "", "witness": ["4c52d1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1ba89d18ed67dd3d5d559101471702e4f2e7d1e8ead8a22feb9e78f041b8f409f5c55ad82284641cab824687b45d4293ada5fb8cbfc4ac19bcb5188e4cd0a7708cf37d2bf9ac9d65f4f9542d60f6497573c04b4d7313f44a5c611386102890a1c"]}}, diff --git a/txscript/data/taproot-ref/f5bbca8f5a7339d3dab2b5f758f426cdb744dd6d b/txscript/data/taproot-ref/f5bbca8f5a7339d3dab2b5f758f426cdb744dd6d new file mode 100644 index 0000000000..fd1ee5aeee --- /dev/null +++ b/txscript/data/taproot-ref/f5bbca8f5a7339d3dab2b5f758f426cdb744dd6d @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707401000000447c0d19dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb600000000c89d618601bb761000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac83d9c85a", "prevouts": ["0d1d1200000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "d74954000000000017a914e8fc5dd19b81880e9ce981652fdea2006e91539787"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d090201320dfcc205589abb9f6d1a57ea01bb662c2450eb85a7615df7e46d79c034c81390b1a692e0be40b5ed8f87cb09bfd322c5d415dcfd20d67e6e24e85c379fd383df9a01b4945bcf926e1464f5d40d70091c578ce7a111aea7644d7489e063b0796cce981de5019cd46c2bf28aedb6ca56cf0656426750cc88dbb4ec973c717d7eb04c28067d76b57fb8ad39cb52e752e80ed439c15afce1cb9380d3e858e6fd9a37c8eae4a2424369b5b53a74cfa8ffa45303be336f6e2f57101f06f1c68c9a3638691d30fee30466e25a22ce8a240977e86bdcbd85ca4a57335d686f6a0abea53454ba3e2d13af98fa064474b73618284889a20de4fe70510eed63a005b0b56bda892d2a3a019b41fb1f8438b119bd7cd4a3ba77ba1e7bd453cb85d1dcf29f7df87ba958b6eb85815f380c84b19d58c3fde88f4903d0acf19e2de66b09446e69af0b63a311f76eba3519da9eb8dd74f5eb49052e45c00be607bb37fd24521f2eb2bbaeb4ae794bad806bc0f0cca8efe373f4d53f46dad7054887dc3beef2b5c8e1e8715d0884b3d5c53fa4cab69184fbb1c9f563b92ab464f48ad02932354879999744cf7d00e038a5c66f3ad98e313a41b22dc8c41158bef1cd2b045c5a529eededb14c58f901e95a8829bda9f0564bb3b380258c2ef91545c757c136da2f098b1f3ffed1196b7f3404a580d0c5912f343d1f347f63125c7dd49085a474306af4db2d41f5d1afb675", "ae7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f6d622f24f94d4576586c4a0fe62a71171bea4f7ff6dcd9fa1e4ca2ca2c05ce8fc0ca702511f3076acdc40632b43a1d65714ee25a695072e4ff6818d06cb6b94619c7e3fc3d0f43b284295c7c76b7ff66dfc7bbdbc495ce3e8e20608c97360e5"]}, "failure": {"scriptSig": "", "witness": ["4d0902c6f3caedb81d6e4e6de66fef39f8fdf17a7cb6326257543aebe4600fb427dba52b7aaf6b23ede70ab98138207619c300545b230d8ab39521b0e41d2de5e7d1d0435ee0c5ddd68640cf2e1ed7dea31c8094c2edff80abd4c89e603d10e18974d0f700afa060af487fcfb086e24dca317f7a85d3f3ffa809c51c0ac937717e401912737c4ad9a739aa1613e21c02e18dba0827f8014353c521674b92f97eaf32a27fcf815e9f16b449ef93e291673e64182e4273692bb3d54dafa52bd34f8109a09e30e4ae3b9e19b21ec368e85e9134767a16ac243baad9287a66c89d618818258c57eebceb06ca4b5e81d10a999042cee62a3af387fac7865cc1080e875f7ed8ae6f4d92c3f8805d3f84d47dbc6e1723c1967b8de0e78734eaa791d521b79af6fc3a9dbc8d5963a65a1fbc2d4499e0032c29d3ef9c42facf6aa0b0797faf809d663557150a67fad176e1bf24b5bdeca06c300901759cb05110df159b445ad95898ab5822b0c01dff435c2cf798514d5c4ab78dc8b8d6f2811066610febc2ca69c217cf412b20672b752ad2ce68b83fb22d6d57a8cbc1be110e8f67c2192db5943107a13dbc34b18faaf1374c0f6a3f34a65944b626a14867d07c8e4a53f27c855a175f616832c471aa2e6d8f5a603d6372f3893e31419d5f509d250ee300b93250597e3b156122ef9974790b4b4096cfb9c1727a1d32f119a4466887d01587afd2fdb4f84bb520d09f75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360ed42aa30ea97095c7220961c159553b9c090cc22c12fe1d4b83524e8c61dfa4c67b1d078674a4d97323398e107b13ccefe9299bb9116e21f935c64f37bba24f619c7e3fc3d0f43b284295c7c76b7ff66dfc7bbdbc495ce3e8e20608c97360e5"]}}, diff --git a/txscript/data/taproot-ref/f5bcbe0530388a9d1b0ddeb9fd52bbf9553589c1 b/txscript/data/taproot-ref/f5bcbe0530388a9d1b0ddeb9fd52bbf9553589c1 new file mode 100644 index 0000000000..df0ded82ae --- /dev/null +++ b/txscript/data/taproot-ref/f5bcbe0530388a9d1b0ddeb9fd52bbf9553589c1 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4e000000008f41f4e3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b450000000076427492dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cff00000000c272c0da025f6a97000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acbf96ea1e", "prevouts": ["4be92800000000002251202cb475dcea7fe75e0d25a92a7081f6c5af7d6f4e70a5adbeeb9514e98fbe57b4", "7fc7250000000000225120b96a099e94d8f301268cd1fd84029824568c58021a9c30fb1dbdf65372024416", "79b64a00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["8a4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369a508197ed6624452fb9289507f9cfe4408c1b7912a8bf4cd7fce31e05c3b62298751320860179e53b82a877a47edb7ce4c17ae8ab38dd25c39273bf19ccb7d56e427c91532996b84ed2c37f8a26be8637de11530a49bfc255181ba6103e3464915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}, "failure": {"scriptSig": "", "witness": ["4c528a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367c1444e0411a2b4e4bcc0084c7f38996051d23c9299734e7bc32d46b93ec3b5d2430956d1468bedd56ced1f149c0a08e9d241f188aa41dfacb5e515f08af1f16915bb1b7e7b983dc2170cc97c5c6d5436afb034e74288517b9fa4d2c2ab63870"]}}, diff --git a/txscript/data/taproot-ref/f5d29c01f03e55e2269af62ed6364a98353003af b/txscript/data/taproot-ref/f5d29c01f03e55e2269af62ed6364a98353003af new file mode 100644 index 0000000000..635ab931a7 --- /dev/null +++ b/txscript/data/taproot-ref/f5d29c01f03e55e2269af62ed6364a98353003af @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912705800000000d62312c4dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1e01000000c89799be02be4f63000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca4226936", "prevouts": ["69e00e0000000000235d212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "ced55600000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["733a1760be1f718a81519e8b535437be910cf1951b19f7e07a21b5c046cea637584007bc94113149d72c0e4bfc05429159f5901dbe1d33e766cfe3842df2545b"]}}, diff --git a/txscript/data/taproot-ref/f5d9f6f2aa6f7e44a24ecb63e2ccbe34ba6eecfe b/txscript/data/taproot-ref/f5d9f6f2aa6f7e44a24ecb63e2ccbe34ba6eecfe new file mode 100644 index 0000000000..5545b8df90 --- /dev/null +++ b/txscript/data/taproot-ref/f5d9f6f2aa6f7e44a24ecb63e2ccbe34ba6eecfe @@ -0,0 +1 @@ +{"tx": "f558c58603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b980000000056c18ef4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2401000000aee696e48bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42a01000000869aac980117bc3d00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88acdb518220", "prevouts": ["e140210000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "49c88100000000002251203b5669f5562f5e3c9be85e1a1ee6c779850048d3bbc6506033f32dde6b1fbfbd", "8e2839000000000022512097c143d16968b3b30a5e5383953157c1c65b9df293dca96f701b7f6658094838"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d09029fc7f00d6f5ac88be30ec4c385a505b2a7301f6047048d1db6e83a86f8ad594b02c2950f2324dc80bb1f5cfe36b65c4dd96949295f353677b3fd4ccfbcbd49fc5ea409dec0adb5b1088340b238dabf31d6a535749725b94917bb55153a9060165684d5361834e46e7af48a4a5ba92081655b25c9cd08993e79c82c6d4e3a546884ebbf9cc679a157d8e67a8be410668e4ec4ac5484058744a7c68288a223a340e4e7773e96af7624df3a0bed85031bf082d1d4177d89d9264709f05fe221321329c584e1e006f1ffa21d6c00aea2c62d32ce3c15b495c80561e57f72b476b71b9b606a086a5cfdc0b5b4216c198d5d28122a84a52b54985f2b5e539a18c272248f99861a5cbfe9947f631bd37597211f0443036f312d5cfe7fa63dedc66dbe06d9884978f392ee6437a220935d820be4078e6a323fa869e478ca447107d7911a67ebce222208cf6ed2d4a5c978619f88afe01c1eb69e05d09ce23d3e222c99549823c1be27076bf7e12619897c221f5d5f2d008036aef51a5b5eaf63fb1f5d887752447422555a981cbe7bc99b1a004c07a7945edfe4b5f0ce8459b90153d3613ffa48700815e9437b334c6065b2e1627b5923b69c55ca0947119c51f4f78f108163cdaf2ac4105ab0292ae1adfdf85fa2f57df3ebb3eba360502ae8d807427055beb597a9621856c9b1870f3fde075b7b7e0878ed82a02f7bf03fd3d4f804d1c77778cb905ca8a55475", "c77d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bd16996175fbce054cbd8b5c26c2d40819e04cc8aa6e6500817533caa4fcbffabb71aa1af8b43c653f5bd4a49a6dd2a2c220faf9f7ee0d38ca763740363240a33f5a7735bc8e0f27305ca0f6b127eb0c71998afa21cfa1408dfc03edc17ac2e42ff4035580f6aad3e4d48161cfa55cd77c0146622bf63e71def681bc3cbf8a6f"]}, "failure": {"scriptSig": "", "witness": ["4d09022820950910e2c2871348a124f333a391425324cd524e7b16b4f024aef96f12de918197c6ddf0cd0d2c631080ca5228140d00c7cfb9fb72f1142db333c6331655a3b525baaa3b371e4f70311356d05a0caf5821665b7e34d395fe0902256ff10c4740aa27260fe1bde00ed631e661757cddab3b4a820740208656cb3d06c53122015fdffaf986d848227c15233e159f021e63850865a2c313f035532aff372a00a6f413244e86df4859c6b73a46344d1e2830c2371de434d0617238bc18b2ff4cd22f34bef7bbc51a14106277b8b2bb4297c1e4058211ba0484ce7d4c221a8dcf376299d7b232218b748113a5dd927bf6bc786cd36f85be00287cdef698c9b48dc61552bc3825ad989f594fe57494dfeffdad764634019d2cb04bdb168d0e715ac41a86cae1be018499f5db070d5850e85b7d29122445b5187ce9ff53487f8cdab77bf9e08e1620dd694b92a24a95ebf59b5e7df787afface40daacdc923506c077a0317a69097f479d74dea8070e070b3ceff7fb05e5f42d96aadeb18593470f02c0e75a2c2497165bac664323febaef5801cd5378c8ad5dc000e273b37fdf34aeb2976c90606761730f3e0a7056af8e8675d11512fa728e072761c3d7c5bcdead04fae565b672b4917aa0aa4751dc165d3bc34cf070de28e8f3a3c049d6203c11f44493124310ca2f3fab19d6d03a5aac111146df210742329342b06aac9d0860195915b07ce3616475", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8100dfdf5c7f83af5d4cdded17045999c289d0f075ba6add5c0ed7b0f5c1761ac2ff4035580f6aad3e4d48161cfa55cd77c0146622bf63e71def681bc3cbf8a6f"]}}, diff --git a/txscript/data/taproot-ref/f5f01b555c46d9d86c043b50cdf0dc05ea4c3d08 b/txscript/data/taproot-ref/f5f01b555c46d9d86c043b50cdf0dc05ea4c3d08 new file mode 100644 index 0000000000..eeb213d153 --- /dev/null +++ b/txscript/data/taproot-ref/f5f01b555c46d9d86c043b50cdf0dc05ea4c3d08 @@ -0,0 +1 @@ +{"tx": "bfeaf70b038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41d02000000f8f102f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270de010000002f563892dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2d00000000c1b137a404a710660000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac34000000", "prevouts": ["f4c73700000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "a13c0e0000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "0f2d22000000000022512022abfe1c27b62198bb616e4483022cc980778bee956a61d21a3456cf5e2e41f8"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366be5feeab2a431d8c7218b36375cedf4fffb9b506ae8c59f48bd66d7e5f8a828"]}, "failure": {"scriptSig": "", "witness": ["6a67616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f5f4bc663f8ff671a51d503c89c7a5659c0c37ab b/txscript/data/taproot-ref/f5f4bc663f8ff671a51d503c89c7a5659c0c37ab new file mode 100644 index 0000000000..d46b85708e --- /dev/null +++ b/txscript/data/taproot-ref/f5f4bc663f8ff671a51d503c89c7a5659c0c37ab @@ -0,0 +1 @@ +{"tx": "0b6fe83703bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffe000000007cacfbdb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c468000000009c09df848bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4f700000000774f468401c92a7500000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acbd79e031", "prevouts": ["dcc37900000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "129d37000000000017a91439ec132e1466f40f0086baa7ac253013e83c7dc387", "bc53380000000000225120f3eef30b2db388e6b8a313ffb142e2e6ffc970ce6b6a81ae6dc1d81725c678ea"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4a4e91ee040b5c2876196adb98fc298df501b5f790b55a4e06e019d08b67838"]}, "failure": {"scriptSig": "", "witness": ["6a72616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f614cb3aadb14fc4cea6a3fa949cf1c4a5aa490a b/txscript/data/taproot-ref/f614cb3aadb14fc4cea6a3fa949cf1c4a5aa490a new file mode 100644 index 0000000000..0fea298de8 --- /dev/null +++ b/txscript/data/taproot-ref/f614cb3aadb14fc4cea6a3fa949cf1c4a5aa490a @@ -0,0 +1 @@ +{"tx": "e790d7e20260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700600000000a8b6c4cfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c020000000097a222af02a72e6200000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987f3a42b2c", "prevouts": ["f69a100000000000225120ffd777cccd991739bb38ccbd9db99d10dd791a1388f121434fe253b3e6e47a30", "dce2530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ac2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe2e93ace48bd6003497027436d57b628443993a76d6dc4aa3bb8a3b957edfdc60a46f1edbb097ed18057c0e42fb935953c4336ec9d443d16e55ae39a225d9f2f0288dcf8f2e1e03125ab45cd0efca3a23715e7661e5c17627e98d50057f87374b5cd80fb8cd7c947a98554a389db356265b198fc72df311d010d98c3d6e3928"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93644238c4788dcc6d7bf741c635b7a2ee8b7477bdaeabf5c2adaf292bfc6ab135bafd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a144e2b32fb029cde325456c88021dd04a80b93e0665f7e39c1e8a56bfdcaf4a64b5cd80fb8cd7c947a98554a389db356265b198fc72df311d010d98c3d6e3928"]}}, diff --git a/txscript/data/taproot-ref/f62efd7cbffa78cde24f12d7daf90b120c6b3e5f b/txscript/data/taproot-ref/f62efd7cbffa78cde24f12d7daf90b120c6b3e5f new file mode 100644 index 0000000000..2914006092 --- /dev/null +++ b/txscript/data/taproot-ref/f62efd7cbffa78cde24f12d7daf90b120c6b3e5f @@ -0,0 +1 @@ +{"tx": "c1eba3db02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4f00000000e94ce9b9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf40000000000bf6ebc6028687db00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796bb000000", "prevouts": ["0e8d74000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "cf0d690000000000225120469ff3412c89f5805e53fbb9303c790a98dd32093d40e3b7dfe22bb05f85f37f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d09024ebce0629bfe29d7ba6d368ccff3460e1a6939014001793a16b4bbeaabcfe8d9658eb0f54423f22ac73bbd15ce4dfe62bad665a213d4f47a7f3dd73a1e5edeeb7237110748eef3b5c6748fb99ea355f7bb22202c6b9249880d7820934330a58e9dce0290ad6aaa1a9ac026f299662b74f072400cfb39a90e3761ce1d790a3c228ed0c9cb118f96b02a40139bbd89c6237a5241fe98c50a74b332a177f8194344d645c191c25a25df9c16a1ceff83a66b2ff4df732a4f2aa376498ef797ac0604c6048772daae84a060dd7fed4eeb1ab1038f22bc74d2fff093311a3b7e2636111fba9cd40252c4ced4eb1f425f264d9802850e4248873578fa520c13765a3ea680b6096e14fcd3fa5da7daeb36c193283f9ac88ad4ccee869a4a45bd48e1c3ff872cdc465236789005e60b2036f7a04202acadef004b5802640f059430ecb8d09d19e9b5cd88faf91533a65d1ab0c58b4ee13084e8839e03faff357ecf3b78571eb20e88d80e15b1004fe5a7cf8ecaa8172e9b087a4a5f51c8a5b94627efde060164c1b41d384614bb66230e385f731f996cf0c290689ab61be83e4cf239b2acfa35c9ed57ac4664c28f22818bd4c5e635c3f97d1ffc47607e0f7c183d9060617e6eb603e01862c0a9acdb02511d042014e927e4874191112f0b6bc84ffd7d35dbd41cb418aa12b1f7e87880b63621cefd28b9f8090b4ffcacb84fa97d7ac6350ace1f59f3e48b7c8375fc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e1f41497843ee5deed9b1c1ba808c351924818107785eb2ec7667e528f438b571239c06a64e39d88ea3d05132fdd32c8e90a6b90ff74e726fde2d8f99de3a7b89959b5d8c486a0b4fb1c0695d0398f92463f78d98cf4d122171b1dc85f0cff66bc"]}, "failure": {"scriptSig": "", "witness": ["4d09022d7de85d544e8436853be8013693a72cc6c30b813d64ae9f882060b095c5a999fbbb4a589bf19731b8d283648ffb368bea4264c552ec8fe3578eddaa30871ea0c4f540d4f7fa8eafc08de90b854c3c2f0957dd8f539a57467e93a7a6b58b6b3dbb4a46ef5309f0ec7719c385f9549cd413fcad3aee1f2c1b0cd993cf96126e940ea7929211b20fe43d519ddfdbff6b756348178b7963da8f7df7c7c364abc52c9bb336576c38334e89dc702112923cddaeb1fcd8b2238690e1f46ca0947caac42fd5bd37242d5617ffa5a138d94e656dd25f52f2ccb3531922d953aa331cf1bd39d55dc399ee95b4fbab2951853a12785cb09796c370277a36f05cdb7a4486a3ed4bef607698a457bcd5fd3f40e2a981e0a4bf83fb0cf6427162db55769b5f74c763c33f0fe8c3e7f142c436e93d4f40cb5caf022b11d05801a7f8b76869be36b5f2696d5d409e87a632c46fff13722480b5c0491985514c1bd32ed011ace3c1bb7a9f5e3ee42f953f2558d1414ff351d668a0810904ffd4b883078524b860af7947dd0b24fe2993bf935b86e9378f1570cf2eff21042b562bc253dcf9c53fd93df02806658842fca201e737ae19ae090ee72028d9ac8c58d8da147d5aa7500b80dee971b0205378abcf701b3143e24276ecd5d8143edc6d755c8d6bf0d756f893da3149f725f0d47c48ed211a594884172b43d6e1b6ebdc1f6f61ed732c07ff2c331b92d6951cc8cf7561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad0bf4e84093dac3642575e5fc14ab670bc7f09f3e86548c6d7239588697b0a299aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4690da805934f4f93e9c0efd4d4edfea04743fe60c173721d1481257c7ee1801e4e0df2464f99a35d5bc9fbf69ae3045675e957332f77327dfd622124d00cb4df"]}}, diff --git a/txscript/data/taproot-ref/f6389882692a6a18e427b73ca3a0a34f645e476b b/txscript/data/taproot-ref/f6389882692a6a18e427b73ca3a0a34f645e476b new file mode 100644 index 0000000000..034af92c36 --- /dev/null +++ b/txscript/data/taproot-ref/f6389882692a6a18e427b73ca3a0a34f645e476b @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8f00000000ed8cc89e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45a0000000057eac8a603966c5f000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac496bcc1f", "prevouts": ["7fdf280000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a", "752e380000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["d1", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936626685b331694d0de841e58d95d1842d28c3900fed13098d035c30bbed037f96e5aa467dfe2257bccb94fb5bf6723e840de90a3890266560a9e3d72c84089f55cf37d2bf9ac9d65f4f9542d60f6497573c04b4d7313f44a5c611386102890a1c"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045716f66701312fe6b613a3a288c903128f650d73beac5c480044fdeaa8466574a9dac82751ef42f4155e8d0286eb609cd4bc8c8b3be93c107754fe282612bb362f9b27230787fc79bd718ce7ac07558dd4f31dfc3ae0570acbd1df01407b1d4ec"]}}, diff --git a/txscript/data/taproot-ref/f63afc3910d5b449d7d26586af8681218677fd6d b/txscript/data/taproot-ref/f63afc3910d5b449d7d26586af8681218677fd6d new file mode 100644 index 0000000000..5d5defb63a --- /dev/null +++ b/txscript/data/taproot-ref/f63afc3910d5b449d7d26586af8681218677fd6d @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9f01000000d913cab760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127007010000005f0436fa04d7bb8800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac46000000", "prevouts": ["c4ba7b00000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "ef5f0f000000000017a914b1a54d09172ecbb89289f2a670acc3fe14ced9ee87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d090266d942314406b975f02cab7af6ecc78440c27b3d3a72a1e78dcf6fc9cd75ebe28a2027327e19d7af4fc3451b5f22b628be6f748c0cb425739ca9e3fca11f7e93f49741064f1f867b7959613cd7011a47b2b547aae7e7aa50bc2c3f0294541f37ad51b7cd2f735df63c176a1127a90f465850bfd52e7f18c2c0d703d80da1992fb06a4c3115d8cf78685ed571221004909abc87e28fa8504322e0589820a79a2e19fb773b72ffce35c9476da8b3312b3d436ae03c2350362cc68f90bf9e31c07def92d8b445e0bed1d38f9c2e774f4ad04f0f7023f7cb89875252babe5faaaef074c4528ca86ac1f6328c4310bbd91669c6d3372bac0937570cf907aef401e6fe786ff0b638ac875768198f3c4a1ff62cd1bd41d2b94af15512667277f9f9fbc709ab349ccc5b3e6e5a4acf2948b432f572bf934b9c943a1c14bc97f2d0f90cda3a85f74e67c459ff433e51f5d5af3c54397c121f06fd60231249b47fea21ff692bcddc233047cd3de6acad0b5ad0faa2ac9b2fbf1ea44745163c255e79476e8ea1bffcd9d998b6303fa275f370c6a3b7a710da2befd35930f6c325fc4d44a1bda0dd493299bed662bc82add91a4f73f4986823543e384b3cb9bea4d252923f952b3f22efdf659ec00d9ce3afccec73236410bdf4494774dae85ae3fdd1a9c7e94c424d2d92c6828c00bdf8032ba65de411300291fb96342c6176e7954544284742ca330d53bee819f675ca", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e11ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045be01dd809c80d07fbb65649666935b9712ecafc77e536b2a27c3cd6425d00c1ec7034c4ece6ceffdf067bd97d8bd2a80e986f14e8b5dca33ff1523eba7a77d63"]}, "failure": {"scriptSig": "", "witness": ["4d0902443801a5ceb04515c5bb3d43a7a4e32f80d5b93027a50d0f70c334edf2feb2bd3876929474e34cf963899e082f640fa1146eac6dc15dabbc5c94a5271a545941c54d09cae64ae26e6402bb6b537f09b83c677cf7a3977adb8f5d8c3415a6af030af5621929ad5557f1820858a0f38fa52e9ac9c351eab815bb745ae70056ba1ae667ce1e951e16081906d4f269bed8ee2abfe1e8f60c9414bc6b188cf45e9ec5a5f0708c5aeb4c87d2344d4df9511e6a196391fe446a65844dc07c1a2e80716ed0f08a508696cfe7f6b9618e3a563e02e143d006bbd81b9b9f6e9ed8b016c32df52a9aaf9401b703178ad644ebccdc55afcc59f8b856e5c7c16450ac925e4dbfc0e71baf1ad1919f506e8fe661df0b545608cfe98e9d18af07df46dd4587f59b205fdb8026f4728d8eb59fa3120b09f3d59e9161c59287a166343a26b40386626fd32a65170999b70ae05287b1bc92129f1b0ad772b4e96888ee68eb239eb3a4c0edbcf46220ca0b0f5f7cc9c37aac73be2b3e4b56facf7415f3a0b81aab240a96af42dbbfb29e10d3c90bf92ef8b63c01584742e053687eb52b718543a9df702e618fd62dd981a8d7f2c69f5f3318ca8183e4f2a9244e1379b8f981473a3143d4a92d909ee3a71dd1017998b5e90082ddaad5b9f333be64ea66a9441796701cb9bda6703cfa1038b5cb80a794446adaa3ff597b939534bef150d3e0b9198a43df73c9d239d482b4517561", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cacf8b2242350f428bd79d35dc27fac1c499655665084a78dd769bcfb813a07758c38514ede62462d8dcaca890d92a506794ae643449cc5c1c2c2667ece3d2dbdc18898993c284d2f731b7495cb62c60e8571430965d040562487638e1f1fd248a698426442c951e7251e4e87784c9556d503d37bf6168d5559e89d6402ee5a2"]}}, diff --git a/txscript/data/taproot-ref/f64c19e45d11b07f585d65dd6f72bcd502d95a0a b/txscript/data/taproot-ref/f64c19e45d11b07f585d65dd6f72bcd502d95a0a new file mode 100644 index 0000000000..8e7b8c59b5 --- /dev/null +++ b/txscript/data/taproot-ref/f64c19e45d11b07f585d65dd6f72bcd502d95a0a @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff40100000023239086dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1b000000007b8490a101327b760000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79613fcc133", "prevouts": ["b0486c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "47c754000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_f1", "final": true, "success": {"scriptSig": "", "witness": ["97553c1c80f820ad8a2f7f6b4e91f9d3f2825eab51067bbf878caaf5b312b690f286131b4a3b6a4397c7e4dd7e9ef5d00dbdc6e3051e04d6650bf5e3a1487e3c81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3ffb6362e225b3761d4130dbf8dc6a086744f6a148501704fa3b451a634beac10dc51e03aed889e7e7d286bc9bbbd1cc2717676dbc401080e89ed7a7a76998baf1", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f6514adef6dcf766ba7179320ec6c88126688614 b/txscript/data/taproot-ref/f6514adef6dcf766ba7179320ec6c88126688614 new file mode 100644 index 0000000000..4275ff6985 --- /dev/null +++ b/txscript/data/taproot-ref/f6514adef6dcf766ba7179320ec6c88126688614 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4f00000000096ba8c2bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7400000000156c38e103eb5d8b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac71040000", "prevouts": ["1e47260000000000225120bf924c4d20f2c9cd0e276b93ccb8cc76d8c2c0447a0551ca648744a57795d235", "27a266000000000022512091a4836ea80f7ca2c21897583e26dd6f79eeaeac6399c549c1cbaa135e7e4bc1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "cc7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93617c8f5b2810c993545fdf5f31da55f5a99b1608086c79b0b58f6326267dbef5eba22abe4a548a0fc6dfdb5b637d4f02bd7b4a4be5fc13f7c30d33fe8bd172a30474a999e2826f1f27f01ebf91ad073bfebeca039a55919a1ef327838bd290026ec1da8cea892037e805a477afbb54b1f5ec380954f076c0bcd3c4e3d4797a8d6"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368620c4ec8357c3a4a921d222018bacb93cc988a86d4715e25d6f1f1c6590be1bf31245d0339f22fddf0c8a157372cfa350cb7b4c29fad108e38a2a212532063d8f95dbc4edc81931664a748b39a9978dd32dedaf5c850114f6bd2f5098c050fb"]}}, diff --git a/txscript/data/taproot-ref/f6765d4b30feb17d15d4bd81601ea5788d8d26ed b/txscript/data/taproot-ref/f6765d4b30feb17d15d4bd81601ea5788d8d26ed new file mode 100644 index 0000000000..a77a584b3e --- /dev/null +++ b/txscript/data/taproot-ref/f6765d4b30feb17d15d4bd81601ea5788d8d26ed @@ -0,0 +1 @@ +{"tx": "9cd4c5f8028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40d0100000043103d8c60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127060000000005b59fac60132e71700000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac67000000", "prevouts": ["9f583d00000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "5860110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_a1", "final": true, "success": {"scriptSig": "", "witness": ["a10458261d945d50d53c0cc865f8205a443e4a8b6e03d86b1fd7cbfe931c330f25f7e0739ebf36285a76f076bb0d29d8bbd608b1e074c0059cd4541308ee236f82", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["630dbaaee14a73e0dd531b19daa63918a1ef7834129ea60ddaf7f8d379e31a1602644354fa8f1896316633e95af39782fab525d4fd185e23924cd8d1fef7044fa1", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f678ee4a403b466dde13be7e941db7ff7684a932 b/txscript/data/taproot-ref/f678ee4a403b466dde13be7e941db7ff7684a932 new file mode 100644 index 0000000000..cf2601d23f --- /dev/null +++ b/txscript/data/taproot-ref/f678ee4a403b466dde13be7e941db7ff7684a932 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfe701000000566f672760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912706e01000000333580ee0250697b00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcb141a65f", "prevouts": ["7df96d000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "c049100000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_81", "final": true, "success": {"scriptSig": "", "witness": ["0e6ae66a3f51db8c3cea8d4b020e7486e5e480dbd6f5db160cf5d1c224418958ce5aa0eea06f972ed12f6fc3975b440cee50491ac1499c5a8052daf0c743250a81"]}, "failure": {"scriptSig": "", "witness": ["3fae62c629d2349c86cd7d14514ae14fffd598086d1b9b8254be22cdcb3dfce4189c55232dbe4e7ac6c7afb0ee0b15bfaf726e3e05aebf2cfa61f0baae074e2d81"]}}, diff --git a/txscript/data/taproot-ref/f67b572dbad35568f4ec9ba53cafa2997991340e b/txscript/data/taproot-ref/f67b572dbad35568f4ec9ba53cafa2997991340e new file mode 100644 index 0000000000..180ebc1dcd --- /dev/null +++ b/txscript/data/taproot-ref/f67b572dbad35568f4ec9ba53cafa2997991340e @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf750100000056603c16bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf44000000000058d92c0486a2f60000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac1d010000", "prevouts": ["928a81000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "d39f770000000000225120c117fdddb90a3f1a4803136a1531a36879999867f6c1969f4ff0fed79ac77cc2"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/bigmulti", "final": true, "success": {"scriptSig": "", "witness": ["3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "e6646e438b3b1f02d76efa42b04933a551e24ed9c5819f394e57f2a17f84b4f405093e225e898bf889095e21a9434815b82c132c6b9d6ebcc5b1867c4e6560c481", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "e6646e438b3b1f02d76efa42b04933a551e24ed9c5819f394e57f2a17f84b4f405093e225e898bf889095e21a9434815b82c132c6b9d6ebcc5b1867c4e6560c481", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "e6646e438b3b1f02d76efa42b04933a551e24ed9c5819f394e57f2a17f84b4f405093e225e898bf889095e21a9434815b82c132c6b9d6ebcc5b1867c4e6560c481", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "e6646e438b3b1f02d76efa42b04933a551e24ed9c5819f394e57f2a17f84b4f405093e225e898bf889095e21a9434815b82c132c6b9d6ebcc5b1867c4e6560c481", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "e6646e438b3b1f02d76efa42b04933a551e24ed9c5819f394e57f2a17f84b4f405093e225e898bf889095e21a9434815b82c132c6b9d6ebcc5b1867c4e6560c481", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "e6646e438b3b1f02d76efa42b04933a551e24ed9c5819f394e57f2a17f84b4f405093e225e898bf889095e21a9434815b82c132c6b9d6ebcc5b1867c4e6560c481", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "3fd5064df06b6378bdbf1a394cd23b562712d7fd5a6af30a2b1ed8ac5b0855edb4abd752aeff738321808a5ba6f4c1da7447541e8789efe8b1b160da9e4d282d81", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "52020a006a3c51a8ff007707013d44f615459edb4ded77db33d5d011de20818d49fefd4bacd1b46f6a16f1d150a334cdb21effa85b4f7895b46cd1c267d32bad81", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "8e554f5f1743309a0778f2b5fc909834198524aea37c85ba783bf0b25c6bae798689beeb9c4f8c731deb98bbcb7fe82e9aee423fdf6bb35b22f9ecc8a1a46d5401", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "0b08c1d3debaeb4acf7b5b9a65c983b634c37a7e392f80e1a312d204642e8c664fc13bba250525f6b90d7cf98015076a92db8261756184728ab0beb7071c2f3283", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "162ee0dc9b3a50a8aad92914c992bbaab7bda8776cfeacf4b491de79b2ee4a919097d252aafa6a2ad8dd8db1bd4fbb0c16cdb330fcb740822c881cf7a75bd49901", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "91f49da0b66c676b7af2a1e315abc0af48995348e4faf299bb9b5b2470cc0adf31c8f63d235f8a6bb03a32f169bb95d617872b7b950c6c5e4e8b366c447912aa", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "22f8816c5f3164197d9a21d5c2962c29d960407abeebb896ba729b49f53584578a88674b63581c241695a226627d20b0f33b8f8aa77611318f80562e56c2a84b", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "52c0db6699f6e83c3e0437c15da3643375ec8a68ad63a11309594e24a3776c929c5d743e11bced02e7fa04200e0b942b6ec661d946d793eaf86e26df8ea1463f03", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "6e832128c9adb130a93fd46b603dca75c504659d5b92fabb988c8d52a98525be9550e5e0538ab26d06703c6ee9cb7f2a18fc6bde48ebd5bc1879a3d702ae50ce02", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "f74c41d6f1a7d5c93931573d11b3ec79e7ef7fe2bb3cfcd7782d2c776e723a8376e8ecfda58244904355b4e87a12833c9d378d5ced53fbe6e3eceb7de504610f82", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "6867e7e97f6fbb96bcfb4cafec0bfb762c0a6dc128e41bb51395a4a8ad3054a82094f9616417ecea8368e4b4c49930006cf6dbc561f0f3dd36ff6779d8677f4881", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "fadea797ae4e5fb8ac17424bbbdb074f26ad74dffd4da10f9fb6f8b4bbdf2c0300a47e40650f39511ad75b2f97979fe877a35a07fc9cf4ed66bc5f23e1ed5f4401", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "a2e6be7fa0cd409b24c4fc7e2c410ff8515069659619502eb1bdbafb0abccc5a4ee9bef833b0e57fdc626c1bac312a85727fa0d48572f8e0532a8c58f4bc7f9883", "7c9743c31946179108adcdef1c4f2fe79689962d4830ddb1c7e1772067e8ae5273613703c8cf47d8e4c7b22ade412372ac2a0d44772d2de8f421befee38c8496", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "e1ce0092f8137acf09b9b0dabfcb05b4be5039d0e1f4df7529d596c8ec66cc87544bee43d0851fb34fcadd71a93c34407e85c90265930183d44a3cb5ec1a421a02", "4297208ac0b29c1d30b9ba59a4d9fc33d46b535b14f9d39aef432f5c3dc0d1525f5006c6481e5e0fc0560c427db9261c345d95fb829a11892196501a54fcdda982", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "b4a85678040b901b8c34d97eb757bc741524a5fd885ea95676aca4b6b6c29deea57c4f8f0f8058d591ed416575031385d46983d85dd67865fb89e13aab675da702", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "fa4e58f43338f1f930992c0b902f30e5f9019897cdbc91e7b0b0cc66625966ffb8f4a949098540480c5f97015351b99f2948b4d4d90b6e4ec1d9033e5a03713902", "96eea49c646eb1798ca0889129172b3494a4f818dd9767f8eb804dab0f99ab189a3c7d8cd4247746f35e2930579e5f44cb8720712267717689f3fcbf7d6c11a302", "298be28ee9a3d699494d2d89ed1d26abc25ceb96e32da7dc8f0f3d2587889c8055f2677dc7f2d39e1499a1fa90af32aafe115a98572120721a2d77f46177422003", "2a583a8bd3b32ababe4e93d42b3609db8b1c08a635e8479b3b0cc5c68dd567396db501c5626d5e774f6f4e74beb43623e53020139ef821e2dbb1c8b0bccde8c382", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "1395e7663cc259f7e1da04aa0ff0892c2e0fe13b74271c45e25cae515c53ee9a1d0397a15a4731dfa3148c2a8a85ee717436c93e9f20260c6cbd3c000102c33002", "4f55feeb34753827f2ca2bfc1f361a4abcf07b4f9341c138ca6ea40089e183d50e2b5356ebd5575db2066bb37d77f73c5305810eeab7608426ea7d978f7c91e881", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "4243d4dd2611f501e6bd1212e10f5bff9cba16585db2fbb97cb8d81330d7cb36e9c16dbff1e88b7c29b25341a8252daf492cf020dc8fb8ea5c29661a1158150f", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "9afd76c4fe64e98b7f23447ed6a383e70dc37f28e3501bbdf82db4fa1c1c0edc65541b3eeccfdca4a5522113fdb04a0ce5ff4fbde15533641dbebefb465e480203", "698064499c70c4bc9c00774a26cf8424e243f7f62af8976ede1be4b7d3c4ee6f1f568c1a0079c7ffabd427a95a0a00f6edbbae848e3cb00610ad8abb4361053582", "030dcecd0dbd5d8c4b4d72c9c3696d4a22d7e135e202430b65781040e8b3a5b5c2e4a5c18e7d4f44a67b623b25baa155a3422fe6845375ba2465bf0d189571c682", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "d9ccf4e6cbff88b61e4962cdf239a441f0082547272d9ce19c093de1d2d33a26416787e4341722070d39e88d5b2a60ef2c2d9060b2c5a0d80fb6fbb053ac499b83", "87029d2d23d92d5ac74690e42187f82f5877f307d8e2ec0f0695b10369f5f7c26d27d3a1a5962a46b49853d125d96fa071484748474d668498813e9c052521b902", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "c4665890359fcfdd2fc57836de46f4c08985572c324f3fda52f12beb31f068d885b22539928683631fbb2c5c54cae53f4fb73fcf23cf55c0ec901ad1d47a6a8782", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "8f663cc49404a233ecfd04ff0e6503f1442fafb6d4ba9e91fd75c1542546e63226f755f74431069929f19607c27aedb91765518574f464bf4263538e309c372781", "8122e9f8ebfb3107442afb37809ac57ca1692259ee728c2708874cada411191cd7d0282f16432e66885035dca4884f39ee90a026b25ffc09fe47b3dd795c415701", "2a2b2dd9f50988d97627c16e6a894e93a90378c00c93bb40e7166a56f54e0b333bb25f3c832e521af2acca3e24b18afc609f96dc9f58a4fa426f974ed95cdda003", "be060e39922f9cc77fe0de9070af87e82a56c145f8bdaf73f3638f4a2f140e96efe26cbd3aa123c84e79b66cb44d89f584cc67fb0930bb2c2f9d640342b92355", "b25982266c33986d527464e5386ab16d3c9a510db36e2e84c39cd1b99e80bea6963298f831c4165252be5df580568278677184cb517158eb5480b4a8fb7592c003", "add90081b383eb4e7144163aa958e458cae442e66b4e0b7ba57ced9d538f6d1790de44c2ba38477d0642051b14b7eff26db8f24437412a6443c697912ae0025c83", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "4b7740f9eb6ca8f81024fae2ad8b8b65260c91a8ae2590769ca0950123224b0190f29ad79ee12db2a168ebf6386d06aa2b38f95cc41123f034e64917d307b9ff82", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "844f16b5ad563ec846dda659a6afa9690b12728ffe62392741091492f448d3b43ad61a288d502ba77ea6b9f16cc2d29a12e2b5df9c3067ae01341ac0c0c32b6c03", "8d4e891fd74d2736aa099c869182a6a26df385f99b4f08896c3096203293405ed62ee25f1fb7172826fe4b5efa7c34753189c6e68b34082595cca953825a596782", "9e6d195808802273413438a3cb89c2c99cee31f2837531ad71b344b9fdfabd53e350f17ddbc27a9874ed22f2798a3758a8a1c3117ab35a966100b341aab2289481", "beac7fd2ed8e9d7e73b6a460dcc9efb8e831437f2420f5ff7342455a628d1e046c96ba034cb94711a3f3ca5eb4206dc2226ad2b47f0e1293c95eb90ecd917bce03", "3600b868ea2d1716b70c3a99d4174a8b5f7d316045e2aad99cc339d80ff8a07d0f57f13ed661e5f1f2ac696415e9f4dc16e5af1168c5b75d6fa1c1a227741b4b", "89cf3185505d9bff784c2b4f56c1dacba0003f642e4d596c8bcf1ec3863811deed1a50d7a39a47c7558c188dc2ee2ae2637d83116da878bf7cc2ce718054298f", "87174492b6a4dd52e3556640f64a2ba7eab56db2c60047f03dadc4b4da100ab50e0d45bc0a418b2c2f9fb9288d3c9204c0255d951606e2600415b5ecb8531cea83", "ea39321d6e868755af165f19b6840e295b1254c956a06c144d2321e37e900c3cb6cb9ff53ed41233c45fcf4530a870385709af297b82290799a575e22b32832c02", "f1ca13fbbd32b1acfeee0280603c8ace2f7a73630b4a16813a6147663f1ca5b2078b4dd10f4611b6538f50fc65aed5843e1ebb28d5dcf9b37d3f6eacbd8ae01f03", "db2eec5c12097d7ddfb7c20b0c6daf53bf772c5bbe9a25a4f4345769ba04114e43260cd03393c94703c597c6872293c44bb5c1b88df6e24bdd9f6b8e3ecbaf4401", "84219f8564d07e8187d9a96bd5a867750ac55bd1e19485f66c9d9b8a5bcf17eeb00c2eed2e264e696760968114a1360a53545e010884c9a07e4f6aebf592430083", "1eaa4326e72f68ce61fe4f6c01030934328159e3d31f9051dc039322f95502f30f35c2e7d9a9261457e3ecb8ee2f46b98c6336464bd3ccd935602c03e475017b01", "0a5bb8f7532c10dd880f4ecea0ea65b109eb0fcacacbedd862b9804f8b43cd71edee6182322ae3f7abae1cb304ffb904d65c2f8c1c2d06e579bd5983549b80d881", "f8fd5a8b2d847641f5d03c383e41e40a3d6f7ecab7a150345bac107fad75609f2cf0e4bf3bece4d89c6b94ae60391cafcd7e4e1f6df203de9a6e96d1faa6ee5183", "0ad397e524c28244395794fc57009d62ac6494ebf3ee20b6d063418cba191629a50b56631ad5078be2eb622258257797f7f2625ee61a19e6d45c2db9713a3d4a01", "63746b8c49ca2ffbcd3d517ef0af6bd37a9bb313dcb1b517a75c6676b9ac29d2e1b8e46c988b48c81ef1184448ccf231388b42854696bbc606772784cd71bfbc01", "3036e749a837b9bea6484c80a089bd22672fbbbcc8a7eb32be34ba93274548ec9e19adfa1e3d478b1c68c9d010aa8c0fb441651dbad1f7e79bd31edf560deb06", "bada600aa7be5fc70862900be3c068c690e1d881e7a5ae38857a68a008c668e08791353a63b911c69113ab26431c3c642b3fbf58032e10f700cb3e05db51298083", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936baf4c6d0c51fc96b9141842fe9eaf61c74d8eb4071ad6a2f4b34154fbc32a2d5922bf45c763bb50fa537138ed62437fbd2e1df4bc0e607113a1e5917421b0b067b81b7fc382e624798cc3862955a77c75a888c0e53a3dde41653ba5595c82f9df1baeece72c9f4be68ddb6b2a880c83faf7068dab12aeee553a178b11ea29942e8b036c46d73bf6c33c89bca25cf4f18bd2d5b1ca273be0e396ac7d54c663262554f3299d422f9f8b70de66bb7fbb8073833305569dbf3d5161b03bab0dd3cc2c88365cd45ae6f6426efd2d7f480872cf752a3caad8153d5e359c0ca9017f5b27e4d685b42f14f8c1b90a7ef83ba1348df01eba80d283958a7db4d2fbc621a66fe77277ae713e4f306bbc005bda16e1b7eeebb2f27c524213352b20eb25d682ebd49cc1c9d1c5543faf51f246263bc293a1ec3b05628bc84cfd7f4dfccc3e91545ebbb7a20d90802d61cb761b7ed3a9d8977f7a5521df44543d663068a2348a7c7f6542a544c030cbfdd70964c7e81d665feb2adbff25ad3ab75b67ecf3712c09a0b10fc29ed9ec9ba811a78159d56d191855f20d80384a7f598d54defaeda75074e07476023602dfde1c8d0d124f96edbab4af8198f97e6bceba6cad7de517a8f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "eb05b16b5b411847efd57b5108e00967390ed4ed918f85eb29dabfced3e21a79b9dde9e2771038e4ed1ac05c8c09cb151a7872243c9430e55f8120e451117ef883", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "defaac63c0b79a5f10fd7f27f28a9075a3f57dc60b516dfeee046ef7c78257e3099560206098a6f916ba638bb1ed7072080d8d0aef580b9d443735b2e1400cf903", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "0b8bcbde5c38a9054b0de0b0867b75c1b450df38f7bffd31007d41e1b7097f3a120266ea93a99ffe378d4d15670e3a420e325725b30418ff03dfd11917d99b6581", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "288399afd52c6d80a9c2cab206290717709e94f06423ac8fcb29dd935a43004da3ea0bf3cef46b71f51622fc7336012abef68ef1a2217003f0772c6bccc9e1d403", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "4ba534916fbe1111a3fb08764d4df7c9668da0a89a868e04b14ff76593c50084138ef7a0a02332afd73c86fdbf204fdc838553155484e75ead697979f6e0666101", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "3732b61d846882d4a03081fef87847ad36416a8e83b3b70bc4c2548b852fe9ca367383d9336ded6ecebdbe85fdb8ab01a09a359609595fde719f017ae50da2de01", "43e327e5f0409334c78d0805cb3381dfb83af17afae0f6cf88550e626a03908a2aca80ee058807d12b42847c2e8516dae1d35cb3ad1ba7ab7937ffa4ebce111481", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "71fbce77e053f7357f8213ec44399c02a78599d64154b1e155f7de85cd3b7a1dffaeba7c4e45a2f73b5d1b532509959c36056e3f42112b077acfebfb115ad4d003", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "6441691c52de365bd02f0968ca9f29fb87d51d3796efd19b315e75400f4cba2a167724bd2c54966ceccb5b812ae480077cc0bde76b4befa69440e5a659e01bf902", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "5b0af420e335200272e7faf2d3be31dcf38e31b3ab5ebef3f3f110d53cd47d0f459f103263c2fc110e4b8c21fad03cecb366702b40722c7c4a748eeca4f1326302", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "65883bea43df1e4a9935186675101793e6c8065c7c3e69414f5d9335ac6b80ed27bccf9d4643cd66cc9e76f6cebc06038a78aa4a4e0e62bc767e2ed82bb7d8d601", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "f02472a18a242fb92632af71abf37f6b637d7b196d6381c871e274642c67468dbd8250ed426013f67697153f58b8d5dd1b51befd86e9199c66ccf4e611de80d701", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "10b2bc51c2a40d8c5eae536896c3a978e0c94fa848b54fa0d34d51d6b83ec2f601b4bdc8b961f50b1a71a583a3fe2ecb0c3d1765e23cad95660269d56e50389781", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "e74ab0926502627dc5173ae1564a4777b823102fa9e4c99071d1476979884a1843bc87ebcf0a5dae09a325c4168394f5ee328b9f6fef451e0c294489f1035856", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "b938220f84bcf121afacce88aa27cd86a4b54ada24dd4c04bdb03e8306bb9824014f7be93ebc5cec925fbb23f38ff9e1a7f6d34be31cc9410586af63ff4c7d2503", "8d7ff6b9e2e498a0bc887566f868d7ebdd6154853d223a51ec1d6bcb3b99070aa6052e80db8ca3f64253942f580993226455a0422a33f5ebfc793f7f680157a902", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "d7d817c444d4f9a99cc4fd65778b6ef903c638c1a65b1063e300b0788fc7463b630267ed35936aa7c9f8f88e411005027c5da42dcd44fd3d3593b6cffca2b09902", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "3888fd54b1fdfa67850bd05facdee5c0a2af50ce4dc30caf7b85c42a7060c7e98c9a56a90d17e054068a2af58662cfcd89248e2435a36fea86988313390d8a8a02", "eb35f11990d515fba653c01a97e84eae7807e6ccb3273c67e0a6d84240f08f0a179233199a68afb3d725baea3fb4c06613d662d82e302516b382049c63904f5903", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "dc033aeee4753843ad351837490d11b08c226ad729ebb8d121d090505f12db441a7b20095e87c27e546b7a11e9966265d6bdb7fcf52aba54b9975a642822f39f03", "3db38abf922e8e6178f25415486ceffadf0b8b194d853d15900421b4214f23f42a9f9d27331671906cd675425f9ff843219b43144f9d2f672a96c8fe52e94b6602", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "13af116f5a52e5aefa0bb5c817f352170ef68b1dbc3ad10fb3f005c7d9ab5cc3ea57ae411b3ee91dd48fb90557fb87613a744a5b7396717f2acfdefc0596d8dc", "b37ba4a02716b8f263b71baea2a773ec72c215ff51bc74a8f8f51ba9b1b449df5b6c366861bc82d501bf2578bfb00b06af668e1e3077dae496376b9df4839d1783", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "bf158ce54f791658ff0ead9c7086b96ff77371149cad4af7cb24563a4c2e6aae16fb20da962ae82d4c1a710bdb70c3855f1a1027a400f5369b234726c597a1c701", "3e736c65b269c253d155b63556d771bae49edcd84d763def7230f1c86ec57dec0add1b9167f8cb3bce7cdd9e136531931c1c80c23f7e0c19e19138bea41dd74082", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "1dfeb80554f47279f289ac27361bdc23e312f6d8089c84c6be5dd84e1f32ce0eedaf872d1e3046f8a441f6a4606511941e5fe17d6f847d1f52bf8113081eafcb83", "211ab573a260771ca707ec45a680a1f28f254ac091db8e0db8097a128d6252ea21fee7fa211f21c129f0e4e015b781e8a65312cf9f833bbaffde1c2c48a98dcf", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "c93ce6ecf6f91b65e3277c84870442be5c892ad70c4b45d59bf36bf50735d2a1ee22bb411447921910c32546e8a83a04009ec00915d5cd8908fad5b03b7d62a981", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "c60c548a6a2e8099c6fe02ab848cf615810f82696ce1b19e514bb3f09998b7d128120d7d9928169fc01dd9a5cb0b729292be1b434b513f402929a316c9f2c30382", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "3445daf3200cb6a4af0a2753eda75d48c52935b75531b47a63e2edc1aa16e90aab1fea5dce27c7f078c4296555889275f5bd00b374171dee1f5086552aab051b82", "a2553b49a4be897d842ee29a899bca3a8ef1dfe04de8c5a8118d0f6503c319921d3427d371c3b8b269bc43c0fc08978a637c5837dd22cff63fd9d6419a0488e082", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "7573cbf96c5dc7fac987ad6c40018b9e77f224f921b22e006dc20620d025a42a4ba500b98492183644b2d24b1910e7c0e54c7fde3833824223b11fa4fdc74439", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "4b9fd28735a855230dd23d770a23bac19fa3a22b3a5e768846564b1a7abb541f8931b7e14a203c2a0a9a588cf24317678e5c5c783d2a6a1c3b55b7a43b2a491982", "562dfbc3025a85f7b70d290a116db3313819037c3aa759dee418102407a1ca826d4ef2cd22d475d9010950098c8c00c2580c4c6e1e1663b436ec9f1c3fbf69e8", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "ae9f3e67366138212f01bf7590f86e7bd8504381ee13e6a205fc75b97faa536c0f0edbf2f97b92c6db377129d275920fd19c083725083d31dca655eaf50d4db101", "025587d778729c55c07b7b0d8a6fbcabec39bb89e6cbc5f1e3ae4112219442fd9a6e331f201d7da041f5f23d47589debc790ae3fa50b290867a5c533f8c0c9e503", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "cc81ad868b8066b871e6c15808f109447988d0cc7887e350ad1e16c9bdf8532d7340d27e6f108db9231838fff9d57ca7463904c06d5d35fea33e7505d61b73b3", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "eaec74709e1c8cf5c18318d56a56dea46df72c91e1e12d4cab9ff141cb994af291f51b727562585e2443e9d3b841c34e28a1324dad8a578f45d3ae1267c52e9b82", "bb304f7e2b46e5770e1bfdf5dfdaee0f8ec27b2ef9eb825e0cee739e2eb1b8df5efe0ea12ecb020b8928063af960fa9a4f9c34f246813b06ed62744afd1595b282", "9161a221e0bc0c8faca8664e12f19963c84fd58fbd55cb570ffc7252dd0142cac9741c8914588e481f494fbcc51dd0c267c2f7b2e3a7020ee5884279dc72698281", "23bd61c5efe6bf67ccd7cf5c1dd362675a40d533d42a69efd8ccef5966a186c7f23397aaec1ee5367014db2c4b110018f3ec47dace052e46425e7bc065619f8f83", "0d2317fbc7c46a318fceeba04c050b4d87ba8f605364ac36be38c988b531ced5e960811b50b597b774555916100f917eaf10e371c7e3e521ca4e3bcc9174156a", "580b2255e939b9f07affd7cb53b47a948a653ab8c83ae12a88f058f3961fc88fb78a55cf6962c038960cae1c4c5373ad254fdeb8c0e73b744ed02487f0ddf55302", "e5af289f4f72101636927b5cc0b7035664a732486f3b45ecfcf5280c930ef600cb3ba4108768b6039cf9e03d2550317762367114775daed19997b87a0555fe4b82", "ca13d66107ee0679c74de376f48c0985af6a6140439ad8ce045e0216d088cd96e8d69473b1e5c1b28b7c6fcf5be1161e0de150cea369b7c81d789705e117143d", "d01854415d41b72f0ab7a0a352070569648e92243de5319c4e3d50992e3e4e2edecd21857caa4b1e9e0a421f2683594bebe6feb2ab13e9a256469255602d1e4681", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "5a7a3bc5a6ac62d53cdc3f07e8ea8d7193c33aa8b228480f54ed24927fc2eef017fa7562197c4b22ef711e3e68fd43c89373d690a3bc90fadfdf506e48deb1cd81", "e4d23cdccd61b75de065dcc1dee646446ecc15be8e2587026202261f9de6144453b2e3c6c80e2f055934b7a8920bdca6219f5c74bad4e47b15c336ad8af2d97201", "99545e67d8a6300d3ea763ff8d4d3592607c863af68d974f7455af9845a7f3e4e56feeec5a6cc651c8a2cd59318514613c4c36d5c677b2dce7509ba04b76144c83", "5ff60567289c081d2a2be83ab3cdbf1df04fa611c48761381687deff378c1851cd8c2c690ae64f618989ae809a4697a2795f9382d7b4ab3b0cbc1999e972dba801", "f6dbaa4f7e21481177ccbdc20c79a06eddb7f5aef7e8bf2bb15fcda0b626304effef537dba2fb030c5457028cd47620357a36616ebc03c05d0be73e0575655f283", "b5649e02ca096577500d9e32ed33cddd06a8e295f50958c62db3797620e3fc68cf8b0a771bb5127adad96117d6b394351d69dc1c326ad06996eb8bbc3120764283", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "33da902da8d5e00c2c3b98c29ac5a5584f42e606186d76b91e2e8b24de9d3bcfd3a6028ca219081f9692fcc1062a1d11d82b874962ee05fa79ddd94053fb7c0081", "05a613ef620138483a8a3b22b66e22ae52ae8e93af16b79e594e6d7c646c131b2fadb8132f34a069f541795096726332b7e30efadd567cea475aa7ec92b3932102", "d478d7fb5c3c5d7a18685ce12dd5fd9091b539bda120207c3f564468a9e6f741c861a9dc82dc3f30df39bf15bbb3ef5c0b65ac0d73a19a5d68595cd840329a8703", "e050d56b7472dad7184b25a873554f8a17b2c1301206441e0c12f3b1e693d1d08ea0f9132b0ed51507e6b02a02ba2b6405afd64fba5dd00db2547e4dc91c083483", "20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206a4e69b2d742382fd2d0b1868b4f46c13f517106779a6a84cdb82cc93236c620ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad2024f8eac36f01b445e4e05ccbda5d9837ff02b817111f34eb558803358a912a5cad20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ad20aacac216c65acb65ef3292a5f58cd89c7b776ab275013d8a6787178c9f7d42a9ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad206caf8054a443c5f9bf7801c6777845f7d20ceb354457606c181abd059e61439bad200e3860eda17de017eeda334700d195c3489b9ce431ffc94162f935fd610d2354ad20edcc845d90377d6eb9b1ba687cafa22c44d0f7e8c97287e4e7eb1957a61f9755ad207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369922219aacccb81dde864a3ec40f7c21a3eb8f46c49c9a6994071aadbfa97168c7c64bfdd97d5d3271ab928ae76e5623ba7d07b188d7730ab7eeb107a27c6eb0f8be1a390cc3e305bfbd2465df21ce81c8757e8fd4f919ac1910e9b12e8ace1c156c6aa3bd0fb78611d2427aa9d66c53b6dd1ea581e1e02aa0fcf225d9954e28b54c96f697a7bb32d3344724c289f975baf6fb6a610298cf3ab7b48bc1a572854ef455f8f94906872fcdddbd9c69123ba3e37df0d5957477116d3e27701e750ab6bf49c94f22272e9428faf1bd5cd40ce646d682c490f2c884fe432ef578e6f0312a05072c8ded55048a84110539f7afbcf82c40e617d46c3e4d1fc146955518e3c1d75bee0a7f6e2696c22018a172015efca0c777be1921fc7ae15904975690bdf2e6d377467ec6d797eaddb36a951f6c721d32620e2a3c0d329704dcd15b7f71e451376176e2f55c3c2221a739607450191971d5992e750ad1451d6be82b7f6cf6936e6b1a3a12a398c2d5b5c2ecacf11b1e8a5face090fdc96f6614bd953dadc618cf7f3a0d639ba509d355272eadbcb76778d4d1d605237c1cf557850c008acfa6a9da80a755a207eb5a3ad02b1a2cff248af93ddec122a727b43b9e8dbb8b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/f6840c641bb58cad923fc4f9c092164413ff4ce6 b/txscript/data/taproot-ref/f6840c641bb58cad923fc4f9c092164413ff4ce6 new file mode 100644 index 0000000000..f929909a37 --- /dev/null +++ b/txscript/data/taproot-ref/f6840c641bb58cad923fc4f9c092164413ff4ce6 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4e01000000192acd32dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cbd000000000851923c0387ee7a00000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a632000000", "prevouts": ["a0f6280000000000225120371978f5545190cd02a51377bbff85a41bb9eff83258c615791f81074881249a", "d6ad540000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["804c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ef50ce65e1ce97b405f0b78362b0983814277331f92d6e6fe48e5fe1e54fcd63d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51b44d35a0b3fc5d8cdca17f6fd766b3b7f076a7a891ad519d38c56688c70ff9dbd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}, "failure": {"scriptSig": "", "witness": ["4c5280", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368815cfc997b4033dd639313db9a5ccb74d87c30d58988500dc693d33d8197cd820e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e16014c92f678e181bf1dc3c918b3709f7d7746b7ca1ad43207ed3c2b1249c00bdd0313c1abdf0fb4e55d9b6d58af17743a20615f5654a8f167dbe9f4cf3a09059"]}}, diff --git a/txscript/data/taproot-ref/f6907b785c509927b03981052c87de1c9ae5f772 b/txscript/data/taproot-ref/f6907b785c509927b03981052c87de1c9ae5f772 new file mode 100644 index 0000000000..f070aa8d31 --- /dev/null +++ b/txscript/data/taproot-ref/f6907b785c509927b03981052c87de1c9ae5f772 @@ -0,0 +1 @@ +{"tx": "bfeaf70b038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41d02000000f8f102f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270de010000002f563892dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2d00000000c1b137a404a710660000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac34000000", "prevouts": ["f4c73700000000002251209c711009ff170e3e5e8c60ed867f1e7c5df59ef27f30fd46ce0613d7fdb82b23", "a13c0e0000000000225120703c36fe53a423407a1cf4f4b00ea153b2ec4ec02148a4b96436a11f0ee0e0e9", "0f2d22000000000022512022abfe1c27b62198bb616e4483022cc980778bee956a61d21a3456cf5e2e41f8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["f5", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93648f8d343e45b2a3fbb17d68cee821227f9a1b53be93535e58c68639dc86e84fc4b6f5261b409d682c30910e7df322d9859114aeb60c7168b8885bdaa0165cc6510b3b87e8b9d8544644738d4851bae032b2bf37d3a4aa6541b936ff18c715610c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c7e8952e748deb89d7f1315439c5970ec42920b4cab4cfb00d3d1dcb758e23bdbdcbe75f074483e48d717af2cfa8ab1bbef1c35fc84f016c108dd10256d535ae10b3b87e8b9d8544644738d4851bae032b2bf37d3a4aa6541b936ff18c715610c711f738010c3c65afa09c620b919c88f85303c8a6c3749257da2d218fa6976b"]}}, diff --git a/txscript/data/taproot-ref/f69458974b285f9c2ac48a1bd10b3dff2d042a8d b/txscript/data/taproot-ref/f69458974b285f9c2ac48a1bd10b3dff2d042a8d new file mode 100644 index 0000000000..21bcead94a --- /dev/null +++ b/txscript/data/taproot-ref/f69458974b285f9c2ac48a1bd10b3dff2d042a8d @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4100000000055c6482dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfa00000000f46499b502d29a9d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8767d58622", "prevouts": ["f8df48000000000017a9144370350f30aa8f875e3d2a13be81f25f19bf1a6387", "14b556000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/disabled_checkmultisig", "final": true, "success": {"scriptSig": "", "witness": ["aed9d1017c0dd38a96d1e076c25f1e3d396e1e569f80f4dca4d688d65ac11e828bc6af326eaad2a1f9a4625c2278c8209f1bd3c12e9c3a733342c6323d88d76d", "20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365cd2d09394ee01f4cbf453b8e43120c6bca0157ff833036c4a91161ae8d6db3dd3595e47f783dea9cd898c640c1ccf4b7d0ff5bfa4236f535dc6b4728299c1d69fb9e9eefbd8dee3e5857c0a5c3742d0e58764b1e6eec73b89290af63b7ef8123f752582a11afed87b1aeeab00a91ac5167325e0fc3825def3a8307d2082c1acae8c13f957496bd85a8bfb196b41115877f1c292877d449cb5d56eb109a1f8e695176267bbd1b7867e2eebc439e9f1978d6a17134b75a8bbf0107687388ddeb5ca20cf31e30816ef7bffd0e43d4efa6c46d11185474d89ac75f693a7c477baa289311c864108ea260dd739a7c927abea94bbd3ef2fa436b5348a12a03476bb9e451f31f95136dbefe9a42f2bb6868f993acae25cfce8fc0d73b984508d267a487b041864f4ad19f6b2782b89895068e96969bc0c0cb50b64c3b84612df4c73208c4bcf6cb070e67449ea1a036232a8155856b27be4c634558db013e06b79c26858824757e3ab18b9476867ac69e63e36877af9fee4aeb519472ff5a504bc7e1bb8a70b57e599289922abee7f7cb3f5c4b4e0126255c9af59ddd6c8d572a0551d9a0b10fc29ed9ec9ba811a78159d56d191855f20d80384a7f598d54defaeda75074e07476023602dfde1c8d0d124f96edbab4af8198f97e6bceba6cad7de517a8f5d6ef56d49b8ba11f647b86ee2428967481742dac54c1b1db96e16689b33190eb95b56bdead0c1a3e523ddf7bef5f6922dc6a17860d350d0b88526962aa6ed"]}, "failure": {"scriptSig": "", "witness": ["310c75ef236fb8a50f79dee81581f474d0f8d39b2916f41991bdc08b1b780ead780e8c9f8fb115ef6d378b02de75443baabaadc650ac39cb7851392eec0635b1", "007c5120871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2051ae", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936292edf0afd686b76454ac87df521bc1c20693b4cbf4ff29ba5f26b82aeaaa557bb511d41255530c42c2dc7568891b0d4b6b428c113fd1f437f7663a920fae46b0695b1973a2559bc98006a7e217715863e999230b7b20484f04307e013c080eef35b474f97b8f06ea4e4e04f1e5d63321171a362b4f33b759b3e933f71931b5f724d1f762b37e5b1fff0421819b284e552d24d26eee84e6ec01115c5d0f886b3832c6aa2a8b18e93eb8bf2f5c97352e53451353dbac83899f0e369de8412999b8da44e477b0203d3bbaa363dadfbc71173258c4fb1f25bd6c995929d401498b15cdc7b86143259203add30582e3161638396fc272dbcd8b6a4efe6b4969c5cdb375f270f52c7be2d12ffd3fb62aa84f7ad164a11de5eefbe5a620438d35e655d5ba471096a5b3a3357976911e74f87b4ef980a685ede1cf19d01f46ed9b6e0b39b0cb365e6bcc032bc02d2b91a16da658905aec2c93de3186efdb1d567fbc8d5464e05bf50edce7b1f5ca81822687132cf7d30ed84f6dc8ca7e183a338d302e00ae160e990742032df386ec8547eb181c0d102fa876c1cd80d9ef530fa1c065d2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/f6a06f14f3641278ceae3733db1a7eff71fb3629 b/txscript/data/taproot-ref/f6a06f14f3641278ceae3733db1a7eff71fb3629 new file mode 100644 index 0000000000..f869c57103 --- /dev/null +++ b/txscript/data/taproot-ref/f6a06f14f3641278ceae3733db1a7eff71fb3629 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c413000000006d7c0687bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0c02000000532d33930418b6b700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc996e2420", "prevouts": ["69f4340000000000225120ae011602bde14b63ddf579d7a3b02b5b10535576fec511bc89b313092adfef76", "b9e8840000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902e36be21c1648e42ff0cc711472cd6fa783cd04cc1a12cd7af689e55d54a52071fc4c1d6826bb0f1d5981ad6014666f42c52f676caf3c2187a661492d3fafafed82e1a580356f2c3a1a179b7cef7b39b49972988463d10195305286c35b7ad54df1cceb82e3f641483b8c3c9f963194b5c8793d1673c4a40b8a1867297fafa77b7ff7278efb9d558c925fd26f9c98693943bc15a755d11f35835b301e80e48e9b2d480c9b6960c4f0347f08f63e0f781f33cd4bf4d3173f90438b58be65d784abcc8900f529dc1959b4efc92adfc954bcb0cc77cf775752798608ff7c25a74ab7f1621b238565bf9a84b5b69659e6fea49cb7b424bd76857bcd207c307c3c2495bfe976eb42421217602baff585fd0cf0f73fd3d12c7f60fe223e29d9e77da2323963462de7ecd65c1faae9c8a01007736b9eaccac9e3c2009c7aed6a0f7d5abc32d161db66575b2ec12ab9e3f7b928558827ab45565d2ccfe5f4c9713dc5c25be16cd36b640be42de607238d50ee5e8177691c96f106b0bc902c3d31863dac864d4518f0477e02f4d0094d255241732967ebf938e88001e42a47baadb3c59d0a68f447a28884229864d6739812e320509271e17eb73d075a58fcdd1caa882482f3692a526e3c72f415383940741acd814b29d0503dfed2a892a8718f25ee76851e96790cf593939abe4e9ce44dd4a5fc80f2b3966d5cda20296e6fb95c61576a081424d628d5f6e07775", "e97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369671c715ab747f188f78ea32a93d5e14629a692e3e2d5c6a647d72992224b4dd6b9e5e4bd2cefcda110a5bf613694738c198174b403d264db4691720c8f18fc7b8321554bafe286e6661652cf416d3db0b455024b23404eea069d656c79e4f25"]}, "failure": {"scriptSig": "", "witness": ["4d0902298d3654df85d1808fa4010a2758851d10cadb7c379115188a2388efa55be047d32340f236402d8e23cc9df254834bcdf632e60ef3858c051388dd3c8c023efca9373f968e3fa3d04454509135b46595d593ed1ba378371ebfa3ce86a5be46967f6c2db967e8f8291a4670427597d2e7a038025116060540c1b3ccfa4e428e17b0743d32ca427518d519e455bf8d647594f741aefb3f5335814d4bab0350883beb8cbc8aadf04e404a1baf6e8c7de7a8048867f72960d8253178bb587fa3fbf2fd13e13a160f463eebe3e888f574630d1c377be77e2b191871ad70db5bcb1f28e0cd4a0ddd43b39bb13350250be38c77a295448f71b243af03fae6ba0661c4071bfd8a67df2112a90f938cc36918f96c12e7dca1ee67b42796853bb2c096ce474a494326d4eac9dd52631716af52d4b9bef9d8f79126d032374baa5b9e17d75b557e26156378e2424d9605afaafaf26bd0ff7bfcef1aeabf504ac544cdea7760977ca008e4f66ac3cc8d036094956ed9133caab023655569902bd4a67e84310797aca194586d0f26762bad409ce4c26a9fe9a5cdbcb918e905e25f8caca4aec17dfb249f66bd1cf8d459adac779cab51c7db717a8ea39d659b5d469bafd99e0fa1170bf35d84b79befd1ce1de8f5c72b30613f3cd0f46a39b2e9430376ff969b8d40890eba045b9ede56b33cf5ff845cad7a3ce54182cd4d3831194fbbfe4a39e08c61719f075de1ea75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082a602e473c0179dfd44294f4ddb50d827cec9d4b4e0c6eae7f68c0301f0fdfe7e6b9e5e4bd2cefcda110a5bf613694738c198174b403d264db4691720c8f18fc7b8321554bafe286e6661652cf416d3db0b455024b23404eea069d656c79e4f25"]}}, diff --git a/txscript/data/taproot-ref/f6c823a2b3203faddc06a15a61e6f0e3f3e7fe8e b/txscript/data/taproot-ref/f6c823a2b3203faddc06a15a61e6f0e3f3e7fe8e new file mode 100644 index 0000000000..1a9b5a402f --- /dev/null +++ b/txscript/data/taproot-ref/f6c823a2b3203faddc06a15a61e6f0e3f3e7fe8e @@ -0,0 +1 @@ +{"tx": "f912fae802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0902000000bd0732c4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5c01000000dba8b4d3014d37660000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7966d030000", "prevouts": ["836c7c00000000002251206a4d91ff9a31e9c489593487b5cb005a27e6a3c932fea2fea0a301cdd0cfcec5", "b5d1240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_58", "final": true, "success": {"scriptSig": "", "witness": ["d8b0e4d224996352ba73ef996183b9955d073f1ec60363c33c9b3611957f30c16f4f4dfe36456bec60864ff270df7d30a37ada20b2507c92ef3e1f8b5c274aa501"]}, "failure": {"scriptSig": "", "witness": ["8272257499a041d5be190b5af3f96ca07c354a873b1e4ad8a69c466b0d3b9d43cb5a14514c1b74762c9bb7b8ae5543e96d291e2c61767de540d8f4cd217b2d8858"]}}, diff --git a/txscript/data/taproot-ref/f6d3771166a0c4e00527b2be21466030fb499521 b/txscript/data/taproot-ref/f6d3771166a0c4e00527b2be21466030fb499521 new file mode 100644 index 0000000000..e2b64a5680 --- /dev/null +++ b/txscript/data/taproot-ref/f6d3771166a0c4e00527b2be21466030fb499521 @@ -0,0 +1 @@ +{"tx": "72ce730f02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bbb01000000937aa8c7bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd400000000e0a2bed102189b98000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787660da74c", "prevouts": ["89f4240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e849750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_26", "final": true, "success": {"scriptSig": "", "witness": ["f6389311b4cb31cdf1ec12d0c4c39eec5db5b2c7de54a20afd089d6665dc93ab1086ceb2918a717616a0ae0a21da80696cf7d7b3abd8f9e1ea8f05ea3082b67f83"]}, "failure": {"scriptSig": "", "witness": ["d366f265a60c2caf049c130814921283978a9e885bba37faa953b7189b62ae62d2a1341debcfe6a8ba82269c181e9958a3dfb04f99fe8dbed5f54a999a6a3dab26"]}}, diff --git a/txscript/data/taproot-ref/f6d618ef7f588f9fc237b18f4ad42a84337ec67e b/txscript/data/taproot-ref/f6d618ef7f588f9fc237b18f4ad42a84337ec67e new file mode 100644 index 0000000000..60da220a55 --- /dev/null +++ b/txscript/data/taproot-ref/f6d618ef7f588f9fc237b18f4ad42a84337ec67e @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1501000000e3ee7de3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c32010000003f2fec4a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b8010000006499adc6032e11bf00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc77d690e25", "prevouts": ["38975c0000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f", "cb9154000000000022512096d49a663447a0304343e0ca844d9bda5a7da8dbda233b650dfa03e219f7bd31", "eee1100000000000225120ef3d9168d15fec7bf262c68665e35843469e387edd931854cfe5c2fa2f3223f0"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c0beb567ca3cf5eec8f2b4fea5c0d7ede6fbc0bbc7906d90d754244e5b426617"]}, "failure": {"scriptSig": "", "witness": ["6aa3616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f6e85bce5c033f269bbb51eb480ff58e9d814ed5 b/txscript/data/taproot-ref/f6e85bce5c033f269bbb51eb480ff58e9d814ed5 new file mode 100644 index 0000000000..3144494a62 --- /dev/null +++ b/txscript/data/taproot-ref/f6e85bce5c033f269bbb51eb480ff58e9d814ed5 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8701000000bf8067dedff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565ca100000000d2a15cb9029568c300000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47876b040000", "prevouts": ["d3fe700000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e24b550000000000165e142540f27e90740933c99d4f17ab2dfc6c82951cfb"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["77294239263c63cefaee8399c5c256965186c29241155919927710f05cfc7ab085a3c7586e312813f4daf6b24586e46458d0c39ec1aa96a749e9e0c8388113fc", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/f6f146c32b1b724af896fdd11df580e1dc8f0e35 b/txscript/data/taproot-ref/f6f146c32b1b724af896fdd11df580e1dc8f0e35 new file mode 100644 index 0000000000..04b0446984 --- /dev/null +++ b/txscript/data/taproot-ref/f6f146c32b1b724af896fdd11df580e1dc8f0e35 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4be700000000d5ae6cd9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c040200000082777c9703cb766a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79656000000", "prevouts": ["4bf723000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "ef46480000000000225120ed261f3c61e168679c7f8a74453f2ce25dbf3ff98d002ebf2f6af0aeed189847"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/unkpk/checksigverify", "success": {"scriptSig": "", "witness": ["9052e2b91c7f9ae1f160eb25db4ec360f7c239e15cca9ef5cb5d4358e1a3ee40d22f10a082e8b4ddcb79ab7f09810a157961849e76c255316cd6a56dc79a2a8d", "51ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bbc3da94060df099fde0d42b14bc2e005dd93c33495760511801ba15172f1f8d32782ebac08ee6855f863e78330cad81cc31684ecb08218331c6703e74d17ccdefb59a23293ea293fbf595ca4a3e5e00978c3fc1dcebbd125cbee91d2f1baea984f7f489c7d362405973d36f4ddc9c75260e31c037739aed91636c98efe375e5a4bb5a7c059035c2e1c5c045ea9950eb94ee0ec4463d646d9ffda84a02686f9fc4dcc13930ebf47f3b4a6b88080c0c6eb26d453af90a7fa4d8ab4db56eb36af7e0957f1affba45cff2900ae03ba8247c0570ad2c8e23a25e0e08aff668b2d11ff3cd9a7cdd1a85d506666c817a8f8dbdeadcbb31e576859629344cf4897025483c91c79f084c70ab4e7b7949b54a5e17ec2df6fc4020f94f5331e2d487fe252cedbd71523ec723318df75e8be30db5a3e2d050e114f6b0a5a9d375f5e1fbe58bece622d42e15d9a09f8ac238b01a6949cb9ab79b540250a90b3fc35ed3b857ba67cba4445e9cd0a613a5e6e514eea7a9da662a1fb003dc0b1555d407474a0fa29f0302a595cadbe6f0743d5ef50dc2b0826f0f2e0e84d35ce4b31a2be87bad075dfde575d48d1eaafa8343c63d6f5425984d2425aca274be02e47a5142e089ba2e5262a94fc3ddd3fb5606be458b593782b16d00ce4762d13e98a6ec8488c560f68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}, "failure": {"scriptSig": "", "witness": ["b77469896fbf3afeddec7e54649c6d0e986504ed0008e67814744deea8a6e70d8bed50e6e42f9b29ccd3b9a09f71629b9c92c84dbe343a0150e3e60aa2c2ee03", "00ad51", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367b37f9cba90643389dcb84f8bb3d7354cace0c9189961587fd423479e33fe4bca7f7bc4310acf33ff6106d71eeafb5e618c06787526c83b3a4f243d9848205cbcd98a80529c2a931358c54a01926483afd2817144d11587481c84348a7a5d142851dee7e8956e7989ef1b2310726d24273d46cfad50082ad927e9fc98f9c143d160fce98e5a349b93a878297fe66e998ee720c75d1643072843d75bdb4b18b12adcdd58f284ab1c59b498a19651ff144478d4b0b5a2922bd70cb075f336fe9f4b68777d0bbd7b6c4a577c7fea562e9f4fea2126efe76f3d0ad98be5dbd6871c94c0000d45126f851620d2066634add2abef2580dc803514e3ba652e78e482b6135b10babe6957670b3c4aa2c76f4112b74affc1af435c8383e13a10ccc3e8ee7052652d5467ddd2e384b678ffc365e66fbacf63a4fbd01922cf714b18ee68a4e383d323036182d3162529448348339fc9acae0372091043e56911cb51e390ea725dd19e02d4685ba017b89767b5c8376f6b66370e3202d9e807c9c5b06b99c098acfa6a9da80a755a207eb5a3ad02b1a2cff248af93ddec122a727b43b9e8dbb8b2911ad5a3c4781fcdc9458446cd8039a7a21ad2b04a0c05bedfec6a225c83df68f68735c6d9c5f75ce1cd0826710bb7023c4213b88fb8cd1791f3b2383bd77612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/f70b704bb277d70481b756371e4d92b9dadb2d85 b/txscript/data/taproot-ref/f70b704bb277d70481b756371e4d92b9dadb2d85 new file mode 100644 index 0000000000..79303ce56d --- /dev/null +++ b/txscript/data/taproot-ref/f70b704bb277d70481b756371e4d92b9dadb2d85 @@ -0,0 +1 @@ +{"tx": "55f3a2c603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5b010000003b874fecdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c0b01000000e740bcee8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4580100000096508f98011c849e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac56000000", "prevouts": ["4ff72300000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423", "9d0f53000000000022512081f3e2c470dc60fc961d81e2d216f02fa45ed4c5eaf6bbbfbde0597598d4a1a0", "b9943e0000000000225120beebf2e29d62b55aba368e7e892512e69e2ef37d942bd7f6bc768a8958380305"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_4", "success": {"scriptSig": "", "witness": ["036270b0fc922629af9d63df0a2ab1f46f62774a4d49b9604e7bbf7db065c708d5d745623ba42c6c792c3d243151db0298b9ed05baabc80c066f3b0b63c54bbd", "0ed26051fdfc5ff86fe6bada6ea9bd8841a38f63540bbe26b6dfafbd64a6a36eabf6c8b1a72e44f91b0ffcae2817f0f1bdbee6e5942b36dc3d892c176b779780953b03d354a3c15990cac2633355c6742c12b017553d672a6f944d38fdc50fbd186aba36577d09", "75000442c44132ac91690442c441326eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93697dbf8400667a0dd303fd91e8013ba1d04386425162936fe2029a8afb99ef7630000000000000000000000000000000000000000000000000000000000000000f9494ae9ab3a13b399d1a99414c0dbfe988d321676a1369253d0947894d0e537ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b49ecd98b5550e84a046a1812fb9d2c8d6182b88714d81ba4f60a0f5c6786604cf596788c84aa55abe532dd5d9848325503b324a4448506244ab0beefa59afcd34a47132b9344dce2c6ac0e777413d180d953c5a5875c046e5c0ad7653d19ea4142929a8ed6adb2a42e6b452112251116eebf7d902ca69fb0131f05456491eec1ef250b54f3081b3d98c96b290bfe3c2982c7741c64c8c68fbb05418f3ee34a3ef1dea874d6c44b1cfe017cc6acefa04d2e78ced15f458d79c76a693371216777f9a9632bef7a9fb6626fa7757897a30bd0829794b033b9be37803c1522ab52520c20b03ecd6549ff484e2d4ad57d2cb9e9ea0f8bdc15e86afe888f74cd5f9820ee3f1256cafcdd30219e28a6f3bf0f5c0ebe5f8ab689ca043c8c5a0494889b8d16091b4146e242203bca30779b8d23639a61b9a51eca2138b5bf777b7f662700000000000000000000000000000000000000000000000000000000000000002ec568c67ae88fbd52b9b91de3017124822d2ce5bb02f6c60aac9ebdf845cce052a47df41371558bb4153c50ba007885a09b762513b138bdec543facbb1e6a0f0a93e1a29012bb0cf497e58f1abf75ed87247377d54c33b2ca4c1eb2b248ab040000000000000000000000000000000000000000000000000000000000000000", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}, "failure": {"scriptSig": "", "witness": ["036270b0fc922629af9d63df0a2ab1f46f62774a4d49b9604e7bbf7db065c708d5d745623ba42c6c792c3d243151db0298b9ed05baabc80c066f3b0b63c54bbd", "ea74b91e0b130c5b1cea451c5593b7ac2e850d2862493ccbfe16fea3bb6fed5e9b84f21b014ecc9f8e0bbf5a9a945f89f44e173ee98681093dcb2173f950fa7921c314dba5e763c534bb35063aa8eb427d8bbdab9e4ef8c502392eb1c24a121c9bb0922b818d", "75000442c44132ac91690442c441326eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac696eac69ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93697dbf8400667a0dd303fd91e8013ba1d04386425162936fe2029a8afb99ef7630000000000000000000000000000000000000000000000000000000000000000f9494ae9ab3a13b399d1a99414c0dbfe988d321676a1369253d0947894d0e537ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0b49ecd98b5550e84a046a1812fb9d2c8d6182b88714d81ba4f60a0f5c6786604cf596788c84aa55abe532dd5d9848325503b324a4448506244ab0beefa59afcd34a47132b9344dce2c6ac0e777413d180d953c5a5875c046e5c0ad7653d19ea4142929a8ed6adb2a42e6b452112251116eebf7d902ca69fb0131f05456491eec1ef250b54f3081b3d98c96b290bfe3c2982c7741c64c8c68fbb05418f3ee34a3ef1dea874d6c44b1cfe017cc6acefa04d2e78ced15f458d79c76a693371216777f9a9632bef7a9fb6626fa7757897a30bd0829794b033b9be37803c1522ab52520c20b03ecd6549ff484e2d4ad57d2cb9e9ea0f8bdc15e86afe888f74cd5f9820ee3f1256cafcdd30219e28a6f3bf0f5c0ebe5f8ab689ca043c8c5a0494889b8d16091b4146e242203bca30779b8d23639a61b9a51eca2138b5bf777b7f662700000000000000000000000000000000000000000000000000000000000000002ec568c67ae88fbd52b9b91de3017124822d2ce5bb02f6c60aac9ebdf845cce052a47df41371558bb4153c50ba007885a09b762513b138bdec543facbb1e6a0f0a93e1a29012bb0cf497e58f1abf75ed87247377d54c33b2ca4c1eb2b248ab040000000000000000000000000000000000000000000000000000000000000000", "50d75b87fd561093bd1edd2d0501486fd64623253e0326c9df75ae6d8122d03b0dbf5ac7d883a45caab5f1f88fe684f21edeb8e93d9c7f031ff5e6c076e355ebe44b3d6910f92de91b4af4de773b65ede2767a7a68132ad63f3b140ef72cc1b2d4ecd05b709c31e84caba9ef44410127462d55c90b1f5b987dfa5ffd882da2aaf36e082aa548e3f29cf6a272be3ce0059aa5852a462670c31f0cb3"]}}, diff --git a/txscript/data/taproot-ref/f747e1181b2e9303715bc0aea1cfca3babf00705 b/txscript/data/taproot-ref/f747e1181b2e9303715bc0aea1cfca3babf00705 new file mode 100644 index 0000000000..60401427d4 --- /dev/null +++ b/txscript/data/taproot-ref/f747e1181b2e9303715bc0aea1cfca3babf00705 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2601000000813b7ae6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc100000000e9fc16df02e0e58e000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac31c5cb4e", "prevouts": ["c5496a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c351270000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_12", "final": true, "success": {"scriptSig": "", "witness": ["480b7d8154a08c33eb6752cd1a4ef32b3449233137562497e14b1ea02883727605cc99492a3a1a1f9be0448e7cb795486db3b2b5de7fb79c823984c76175eb9681"]}, "failure": {"scriptSig": "", "witness": ["7226559f0c7bcb20d2085b483fb75f2cbf4bdc32a89eed872dbe51ef1883c8adf6738c3855456940aebc36d087905349230a1db61ce23a0f35e1bda75a7dee9c12"]}}, diff --git a/txscript/data/taproot-ref/f75c71bf10464658e79f72142b2c327cd6ca3347 b/txscript/data/taproot-ref/f75c71bf10464658e79f72142b2c327cd6ca3347 new file mode 100644 index 0000000000..0e984cb418 --- /dev/null +++ b/txscript/data/taproot-ref/f75c71bf10464658e79f72142b2c327cd6ca3347 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2901000000e28d14cabcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf02010000006dad27f30176a80c000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478703010000", "prevouts": ["44a84d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9959750000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d6", "final": true, "success": {"scriptSig": "", "witness": ["f1b9973e470f973281d092e638a52fb208bad47e7949649360975f9c67c743a27fa0694e11f98cdc86fafbe22e1d62fa622aa836c23b8f276907b7ce14610a99", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["d301dabe5979a7e1d10219111f780ebabb52e9b37e1a33bc89020f5796dcefc60d1f8decc3378350da498359bcd57b8f1ae6fae1b2a714688b49b80ae0ab191ed6", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f77abd655150de8bda3b775fd291d5b2bf27a1e6 b/txscript/data/taproot-ref/f77abd655150de8bda3b775fd291d5b2bf27a1e6 new file mode 100644 index 0000000000..2dd5921e87 --- /dev/null +++ b/txscript/data/taproot-ref/f77abd655150de8bda3b775fd291d5b2bf27a1e6 @@ -0,0 +1 @@ +{"tx": "fb4d73380260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700b020000008922b8d1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b10020000009e066ca8014bde00000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87e8020000", "prevouts": ["02ba0f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "5647260000000000225120d09696ea45889505661e270865d17ca69a086fe0d8b7bd5ea027866d2c9b9156"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_36", "final": true, "success": {"scriptSig": "", "witness": ["3061bc88d1f8fb9ae3acd15cb6480b37fb1ecb8e164513fecce8772ee4492c1226124378f7a795307872588d406361d758367f77217177fae8a2dcb16a90a63f03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["3f5ab886cd9f588668f98639c13ac441a1bb186252f21c08f8a809612be7d5341d21a2a144267fe311dbc39c8e5f09c491584a4398cf3dbc1f170ef6d41311d436", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f77e7d751660a7149e80488c8245aeb9be6eeb1d b/txscript/data/taproot-ref/f77e7d751660a7149e80488c8245aeb9be6eeb1d new file mode 100644 index 0000000000..7390d992b7 --- /dev/null +++ b/txscript/data/taproot-ref/f77e7d751660a7149e80488c8245aeb9be6eeb1d @@ -0,0 +1 @@ +{"tx": "30e73289018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b300000000a96cda9602f2983300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc1c010000", "prevouts": ["255a36000000000022512063eb770f298cfb14c87c6cff1e0541dd7cbc30bdbab4472c0f37d52bd55ad696"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "ba7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8a0ef97ab7ee9fc1eac24be41bfdadcbb7c9625a4e882ca5abbd81147d09c0527a47630aaed9dd66550bfcb0f3b3ec2bd830a8a42bcee9dbdef471b4e5cf2e89f5668d978bcc8d3ac0b8aded42d2a4a1c5e69a5396581e310868cb48ff813edbf"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93654dfb6f6b9a2b04f4592afe6e08b27d0dfb1567237811ea996f2ccf3ff1cd1054a7888d88a49f036a686b85959429d2c21b5cc7c31f53deb0eff848be794e4af5668d978bcc8d3ac0b8aded42d2a4a1c5e69a5396581e310868cb48ff813edbf"]}}, diff --git a/txscript/data/taproot-ref/f796e5b0c5ce67017c553a21907fd6a51a1058eb b/txscript/data/taproot-ref/f796e5b0c5ce67017c553a21907fd6a51a1058eb new file mode 100644 index 0000000000..dbf7dcc2d7 --- /dev/null +++ b/txscript/data/taproot-ref/f796e5b0c5ce67017c553a21907fd6a51a1058eb @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fe0000000085a123a1dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb8010000002f037acc0296cc62000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcf7000000", "prevouts": ["d9ef3d00000000002251206830c8b1ebe925261a77111fca109651f909c8747b4715cea67841710683246d", "f66a270000000000225120a91988f47123ec31105f67d71740ec744dd8d7d897f95cb0546a10e5e456f756"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "a47d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdea84c8431ee0615517346b97932410ca977012a316263f78a9edf0a452e478a09da521cfc521edd35405d6ff7b10120e980b699014de05f8e600b437ffa9c347"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e1a56f6cf7d9f4db4b4e32634d67c1bdca6b80e06b787823c0e4d06c57c1163a2ec4f69e5cd9a0f0c1fda8eb2f54297e33bc5edab35b299e65e2653a923d6ca55"]}}, diff --git a/txscript/data/taproot-ref/f798f952feda25e6fc4b37a429dc368f73d0d158 b/txscript/data/taproot-ref/f798f952feda25e6fc4b37a429dc368f73d0d158 new file mode 100644 index 0000000000..ac46b54c68 --- /dev/null +++ b/txscript/data/taproot-ref/f798f952feda25e6fc4b37a429dc368f73d0d158 @@ -0,0 +1 @@ +{"tx": "e714d45702bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf73000000005e8f3194dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1b000000008732789101f288010000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e798010000", "prevouts": ["9d317d00000000002251208f0cd91064976d8c425b1144e179a495d561ff85b6a95fed9a42cd95fa3d7aa3", "c26c240000000000225120396e1e3d37873693c049a0e141d36811f0051f76fd306cc6c1f2259368cdf0eb"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902a2191cad4ac12fc03830217686fec87e60d095f1111907bb3fc06c0d6cb47e9809d042e702d6585841677c1d14763cb36c9cf9f668493ce4cd15571f69d2f697179cdb4aab317c820c41a985d9eea9953d9e4054f3c25b68c5ebac916139b8e40c29d98022d8ab7081822017ab0809762cd4a4f5b1d33d82e2d2d0187700ca3d79c3fdcdb40df1ebba49aecd234c8cd212a69165fff9957698ab22410ebd0e5c41342876b1d991ecd30526be45b908ba6ad7b0ff90eb7d39eeb2ef6176312bafd71c9d0d6046c2e69d0c5e59626d682d1730ba38a4f43dde27c6f2a00ee503599021c0100103e0ca94d893e93a9449d267c72f0394e3fd1671b99cea4f9590f442a99db365d7ddb2d50e4bee950b3a3802bf61a3f1ff7cbbb657ceec9858e9f7290270d3910323915e903d7800ce1f94345ff1a598ac38a9a5f0e27ad9b92d540dd86a17c8e0e0a48bf009378f99188b2e3df63f3820b5c86cecaf4360aff5abcf14b6fe19f45c795d61a3e2ab3b8547e90fb962bfe370585e9bdf7a2a5216e0b4371f3f8fc1d0533da33906017e2ef2a1283a4a52405c3eaa3cce9b937579c9cbc767e0253d4b81120cca717360c57d25292afb7cc281035dfc8d36f964a55507ddb17f8d55e913f364bad11bbece123c3ff1c87a5e5e4eee264117eaa03595bf3d5d4a7d462db97e5f1571d046ca94ffd6e6a6f63c20062c81e55f0ae7ed8b00b2865e8250c7b77d75", "de7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e093a387cbf4f722495a20cca4e5071672ad9cff48cf2966de7657b6ee347f57da05e4a06b32de803bd9a925f4d86502b21cf2d106a73f15ada31e997750cbc80"]}, "failure": {"scriptSig": "", "witness": ["4d0902feb5b4d617c72000c837d6307c9a30d8365d505597ec5ff3f4f32e6f589eb00bdf835db950509d560d0e40d3b94de30edcea7a2a5260ca56ddc0e1222b280a0edb9d6d583f25d177bd2e55443bce9f60368b6cedc5cf2f25e6d9a43e06c47d62e8b10f312baea422b66c701fe376b3c5d8b92e32011119fd7426df10add06d81944dc34da46e699aec2de5d305356cdcffc247a383df4414223860679cf4b308ec7c3e7628e1553f7c4503725c2a6538a6668b733b29471b00469f98e44b660ce5e7f73a60161df48f9fbde9ff86b8ae17e3d10fd5ae3d4fe2f6b79ff0b84f81368560a10d2a0c0ad6426d893254a030e6083ff84a37f32dd2f1604142d67e592b8c492212eab69b51546d79b805152c900dca19749ca760ad199a1e7b66d8677fd14b0f20474a91e0bef5e80788d714116b33bfcc3c61195e2e39c8686dfe0828696b4802fe6da812add1835f79fcadc8d5d9bbee1a51af5f51f354fda784e165e420613a9a0c08b315420c375f2f99f158fbb498d5313c89ba219294d2498e8511ccbaade19b35e2565d713da355e1b084a697327b8903efa56e50ac96199b29e357950c047b2bf7ba9e7b56624cdf649aa3f85dacb6df9ceaa924662e8ab5455af556e5c5ee729e2c525856bce73ff55d299daefcd1986720cb6a8b8a9c81af3b63dc652cf16f0be06631add05120349cd6a2a7c345161a41f5ffacbe5a67e00b2daad959da092a75", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93634583728296d6d19ab926bb0bc1431ae6daddd06bee0d19ae3ca41fbe739f4c746c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa827b55d11351c6fed41de6d200bca95500243dcc7874125f5161f5be208848f0ac1d0874bb493d5b277fe586a1908760dedf191b70e37bd9b06448d9d8257f0a"]}}, diff --git a/txscript/data/taproot-ref/f7a5375d5d273e7eda804ac9335745a3fcc568ae b/txscript/data/taproot-ref/f7a5375d5d273e7eda804ac9335745a3fcc568ae new file mode 100644 index 0000000000..9ee16812c4 --- /dev/null +++ b/txscript/data/taproot-ref/f7a5375d5d273e7eda804ac9335745a3fcc568ae @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5d000000006fb370c1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfa501000000e51bbcae03ddc2c000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc7ee3e34d", "prevouts": ["52205d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "6c5565000000000017a914ca8d66b8079fd8386ff3ae1d10b869f5605e693b87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "1651142540f27e90740933c99d4f17ab2dfc6c82951cfb", "witness": ["0a3bb896097a419e1dd2142d15ca29cdce58ca25683519d007c0375247923e3e112da8695311c8ace1290f454cdf8fa643597d91a8702a4515891dc6f5689f73"]}}, diff --git a/txscript/data/taproot-ref/f7ab44a4e73a9b24bfff6a263c608abce5696639 b/txscript/data/taproot-ref/f7ab44a4e73a9b24bfff6a263c608abce5696639 new file mode 100644 index 0000000000..3934897e40 --- /dev/null +++ b/txscript/data/taproot-ref/f7ab44a4e73a9b24bfff6a263c608abce5696639 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdc01000000f1553faf8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41f020000004d967d93dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b20000000009c7a29f501e4bd6e00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac9946af3a", "prevouts": ["8fa24e0000000000225120979ac728ddd945fd0096bd7ed70641d6c3e965c9318f95ca3c406aaae5bf23bb", "07ca3b000000000017a914a7d99db8790799e567017bcc9951f7f968dba70f87", "48721e000000000017a914a1b035f555fd87548264c3580a1f62a42acf027e87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2356212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "witness": ["55baa3c845ae5d2061ade5b7acf02ee43b6459a09322cee75fc9544b65c15945e7153e11411e1425e2d5cdf0d108160eb1d096c1608a71c38aa93f5f50781ba3", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/f7b76430a96ffa6355eaf12167d0ef405e2669d8 b/txscript/data/taproot-ref/f7b76430a96ffa6355eaf12167d0ef405e2669d8 new file mode 100644 index 0000000000..74f7b3cfad --- /dev/null +++ b/txscript/data/taproot-ref/f7b76430a96ffa6355eaf12167d0ef405e2669d8 @@ -0,0 +1 @@ +{"tx": "561ea52603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6001000000363305b7dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd501000000b8f01b8d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c442010000002b7372e904bd41b000000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748703000000", "prevouts": ["f0d7250000000000225120a633ee2ffb44c3c8f2264048054482ed19487fd868fbe840370e2c32dd11b85f", "3f614c00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "cdc840000000000017a9148462ed29696925d7688e1db8e76ef9e6667f05b287"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "d97d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08246c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa2d5942624d66fc39e30c2a996d85a0dad9a6418b79db996452744438b84f9614682a6e83df749f265180f93fd54e474915a8abfc6fef0a760c06d61a0bf42967"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93660530ff30bd14645256530cc55287fd1e806d6d3c7680a3fb3225b836d58fc798cfdf3dc4b41074e6d5bb67bf9f12a242211e880ee715069382ad177c5f1aa2ff72d95b601af8434dcd53e2a5d08dfad1c07e45b1031877afc5b1801af7debef3d33b10ff9eee8ff434f7c79f826d5967b94922da2ad2ccade1cbab3a3658011"]}}, diff --git a/txscript/data/taproot-ref/f7bc805d350c55cd8e24def5b79ca3b2fe88ae80 b/txscript/data/taproot-ref/f7bc805d350c55cd8e24def5b79ca3b2fe88ae80 new file mode 100644 index 0000000000..74df361e64 --- /dev/null +++ b/txscript/data/taproot-ref/f7bc805d350c55cd8e24def5b79ca3b2fe88ae80 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b5701000000bcb31209dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7301000000fa266ec5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd8010000005d4ca570010206ad000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d3a8b624", "prevouts": ["82e721000000000017a914fd6ce7566239793444b7f37a40ec4d7b008f5d0c87", "d0211f000000000017a914a5f28fe5532719f979169bfa3a31d5746f69452187", "fa38720000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_52", "final": true, "success": {"scriptSig": "", "witness": ["451c3a5a4904f7bd93ca0073da15e6622e91aa9d593f4a255a29a10d136f3d39108bcf11a3df9953645eec387ca67209671f1858729072f2757a9a7e8eea0b4b02"]}, "failure": {"scriptSig": "", "witness": ["f4cdefefb6a7bd12030fecb11bd4f83c94cd80777841abdc54f2f8ee1446b5f35388fe861c0f97ec7cd9e5fd29fdd36bfa29ebb009159d7bd11235fc299525a152"]}}, diff --git a/txscript/data/taproot-ref/f7c02de0b4f89c043a3ebcb28bcb0e1396fe0e23 b/txscript/data/taproot-ref/f7c02de0b4f89c043a3ebcb28bcb0e1396fe0e23 new file mode 100644 index 0000000000..7d6d342f98 --- /dev/null +++ b/txscript/data/taproot-ref/f7c02de0b4f89c043a3ebcb28bcb0e1396fe0e23 @@ -0,0 +1 @@ +{"tx": "0200000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bfc000000001e5111c0bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf720000000083aefab460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270490000000053752fdd0376fea8000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987cb000000", "prevouts": ["de10240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "8c427700000000002251200b5dd6f00fbd30bf243b0d8b333be0f43818e467cea4a7bf1010683a4a4290b8", "5ba60f000000000017a914a2a8d85df2f20a0aaff7224012fc4cee13e29cb987"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "86", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366c9ccce34c09bc03bb8aaff06a11df09f3692c1f74f2178409984d1ab3c04f3715c685a6e20a464c0638846c4feb0cc1ab19a0a1d3cef03660e119c827d202a5d33ab5c29645e0220ea4ffd8cb7e67404885cb8b0cf94872336c7b06d59c3124"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b05e9ad3756e137278ae6e6e7c10c62cfba95395c884b707ca96162ed87516a80d99f698065a0710b414a8468dfa99ef083756205b6b6c9922dcca3ca4b3dec3b4167115de6998fecfb714975bc270adc7a6998f06c7ef8576e15f157ca8963750636431b24706e8b1111073dac761b2ba654f4832b7b9ae2a348c6845c1d327"]}}, diff --git a/txscript/data/taproot-ref/f7c0db2c2ed3c1e6f19acace4e10c0a99df88018 b/txscript/data/taproot-ref/f7c0db2c2ed3c1e6f19acace4e10c0a99df88018 new file mode 100644 index 0000000000..196e31a18e --- /dev/null +++ b/txscript/data/taproot-ref/f7c0db2c2ed3c1e6f19acace4e10c0a99df88018 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb9000000001e948b94dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b63010000003a5b129a014d5c680000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc10000000", "prevouts": ["2162530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "da65220000000000225120e57a7d71b34e22305b9beadfd5a56c380e33d3960d06bf6fd3c82fe378d7b10f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "ea", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045538b2525e5ad3e6ab2346b1907a9f51d3650fdbb6911031be2b995911891caa483976a7e8bc20bfa4c53f64ff2df47d867849c8cbf6df51014735817968d498535c6739a4d626ca1df00777eecd105a7e72aeb1be910a44c9d3be4aa00e70c25"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0df322cf06423056ff4efb147ba4330d28398a4f05a11ad98b1121aa54f60b594336f2bcd90a4462875ebc34531696f5fa5671e0fb7e46050530a773670978687e"]}}, diff --git a/txscript/data/taproot-ref/f7dad92963bb917f67c0a5d9a11c7a623157603e b/txscript/data/taproot-ref/f7dad92963bb917f67c0a5d9a11c7a623157603e new file mode 100644 index 0000000000..ac28b3b0c8 --- /dev/null +++ b/txscript/data/taproot-ref/f7dad92963bb917f67c0a5d9a11c7a623157603e @@ -0,0 +1 @@ +{"tx": "5bee4af203bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2200000000c005eba660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ed0100000060fdda93bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf65010000000bf347b903f07aea000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914719f78084af863e000acd618ba76df9797223689872898922a", "prevouts": ["c7c87a0000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe", "d53a0f00000000002251208be5967f09a51b19904ca66f1d269a3e717a290858b79a423744c21b4f0dcdb2", "1e11630000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_50", "final": true, "success": {"scriptSig": "", "witness": ["eb5cdf47dfbec4dcdaeaef35da079ac77acd725f50587ecca7066e0927852259a577946b7050f0849503df0416626c9926a787150e48edcc897a7c1234c3d82703"]}, "failure": {"scriptSig": "", "witness": ["07310b3746196baaf0cca9a43862c3752c063b2834466b1b8b7e6695aa9ce37a50f891b00d69260f454a33f88bc50d9e5dc1d06e1d03ebedbbd338d53eaa1fe750"]}}, diff --git a/txscript/data/taproot-ref/f7e399c76d4ec4bad55a5e054f90aaefbbefd54a b/txscript/data/taproot-ref/f7e399c76d4ec4bad55a5e054f90aaefbbefd54a new file mode 100644 index 0000000000..8fd5b2a529 --- /dev/null +++ b/txscript/data/taproot-ref/f7e399c76d4ec4bad55a5e054f90aaefbbefd54a @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6f00000000469d4db760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ca010000008269a1ba0146b74100000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5d010000", "prevouts": ["31f95a000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3", "7c1d0e0000000000225120bb20e6409e7fbcbcf1a8716a3f89f05af40f970979e4b2f45be7c2d2ab8f00b7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "81", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0824d4a172c841d8bdf967229e1606322d36b03ac644f3c557c1b9d417f1b2a2a789823c6bcc0c06b1ccedd8f3302fb965778bf11fdbd4830d29cbc62f32a77240ccdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362abad23705572fa5091822077faf7723b4aee0fe16a98731801378aa56415cd84d4a172c841d8bdf967229e1606322d36b03ac644f3c557c1b9d417f1b2a2a789823c6bcc0c06b1ccedd8f3302fb965778bf11fdbd4830d29cbc62f32a77240ccdb938e1cb9dba9647cc0512f82c526c8f6107930613b31200f04f80acff8889"]}}, diff --git a/txscript/data/taproot-ref/f7eb97d1c42b9d53be75b54f5a30490ace43fa77 b/txscript/data/taproot-ref/f7eb97d1c42b9d53be75b54f5a30490ace43fa77 new file mode 100644 index 0000000000..5f04e2e7e3 --- /dev/null +++ b/txscript/data/taproot-ref/f7eb97d1c42b9d53be75b54f5a30490ace43fa77 @@ -0,0 +1 @@ +{"tx": "0200000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9c01000000ddd5aec9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6b01000000ae192cbfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cdc00000000b552f5a70148b11f000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a69aa3133b", "prevouts": ["dd388500000000002251207c2a27667caa5d47bc631b21441672d615738889d76e34100e2309c093e91351", "3ddc6b00000000001600141cc39a492a6f67587324888ae674f2f534a7639e", "1416560000000000225120e177c8d99167d2320778fe30cbe0b2c4ee01065c7b6db09c8aca7c8181e3cf6e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902ab15cafd2ede5df0b79eefab811fb7bf23d150773a2005e95993362dfa0181807d9096773c6cefd6a561c60f1f6ed2d9adba322870f78770d1035077543ce908c3c989d6c2838566e2e0c77c69ebc361c6082778a287a71e13db7019492cb240a7924bc8d20844a965bdcb598be942d1d8e3bf0357828998e34da2d97492f4d9d21f48f4b251a3081001332750ddae2bde2f2acacab391691b74dbbed9a58f72b9ca8017635d948198c2d75f7ecb38ac53b02c7c9d3f162df98cd5389000689129a69b0029d0213ebada0b524d31623669e74791e417841162cac2f5a829cf1c54ccdfa831551a7ff1fe847e981a29323ba89f569dd6e63217f0e41fa778f3946ef506fc4429b56d6c3a6e12617b6fba094948c0c9cd4e11140f5f7adb474e21621380de6c217dc4917ed51d1b5d2faefcc9b0094104d0be7317e48abf0a0d42610da0065ed1c7b4c33f086ee5062d1ee85f809db222b25a4cd04d43feb366a138f45478b782d88267e9a496427d97004c6a47db70fe80643b79cf9eb6cb86072f8523f4ab9c843af629cd1eab91c2c3402983e2930345b21badf98f22498d183adb240a80f6eaf3bd9d13060fa63839c0a00ef15ac0daaf3ddd2f59eede0753b90aa03755ee970676868112f46dcf6def6d8f2191ad46fbc4c04f181e948e5ee1c848c9ff113e92ae8ba80cc5bcc480592edb2132ff572817f5867cc452e4511eb7971489426ef8dd75", "b17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8d9568d9f877f6ca0cee9df3d4970d26d0e286b65747316dde3c995de6e71d9f55bc912f5bf4aa2c9ddbc9747d59c78f40d0a0aa0a8a4f22dc70e3f9cdb9b6ae3"]}, "failure": {"scriptSig": "", "witness": ["4d090237b3b33c6813b46332eba5415ef25009b0be4a356886f771175d6965c9e606364d6e8814308b372830242b4414c1930593f1d8fb8ddcbcbaa4d04f4f2f915416ada3ba16e05c9c637d2e80f9898a78eaaa2e8a08895a658cdfde0fa81692942e778b47b93f7b1ee5f878910f25aba6d16eb0864f7ddf6b3a224c8834eb93d31abeaee611db48e5777ed2f59ec1b298c7aa18fb3ba3659ffc21cdb2f844e734b653ad70613e27345af77fcde0c0013daa0ea60ea8c2faf44e37c150d5dd378fa0d03a2972eea13f92ae4e010deb0c3a0ad0ad04bca0e0875a7b53c327e78abc2cdbb1ef0ca1eda61189f415a92fb5858ffdfa7e9af466f8dc23e1e3f4e5d9fdeb5f456374f9edd0ab0327d1c8854fceaebbcc8f57efaa01b6a07dff5912ffa9350ad06c2b6f9fb810980bb373e0ce6959ccbd6291ce428190e871056b279ee087193ef48b2cd103d4773f981ad407c50006927103a142bff4d5b6e95252b61977fa5ed251eeb01de3e9c2d0d4e461cf3e78c68d080454926d010657ec8824134483d1e4746fa53e27e31ebe36a6c065e80d4aae50811b4f62fe97b2b88232c3f7e906132aa1a1cd8d7a1423b7a49ad555d8f30b94cb6d8d79f28432e3e6d0a92083cc341c0ecb674e79fa18d3918345a117e2fe68719445aeaca5e778ee3738ec3f3d8df273ff76cc72cc7d6ebfc61fcde4db69e29ac1bc172abde56ee3e31f27fd49af471071830d7075", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e7965eeee556c39a9ca7aea66d0df3ed5bb1c1b5d1b815eb2ab41d6c7fc5721f63804e0ef706f1ca5c8b2fa38155abc6bb5e2265734815bc03afdad0836bb7f05989f510e73a03c44610e5cde856f75a0d7582565d561698089d126c5e7f66809"]}}, diff --git a/txscript/data/taproot-ref/f7f77a67d9bea0dcf7942ed62f29985930122ff0 b/txscript/data/taproot-ref/f7f77a67d9bea0dcf7942ed62f29985930122ff0 new file mode 100644 index 0000000000..b15dfc58a6 --- /dev/null +++ b/txscript/data/taproot-ref/f7f77a67d9bea0dcf7942ed62f29985930122ff0 @@ -0,0 +1 @@ +{"tx": "c022df1101bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff4000000009ae69ab7048e3c67000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48733020000", "prevouts": ["28066a0000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "217d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e4f67f6e69cf51b25bdfcad90ab02b519823ccb2f4612df68d1a9a4df99984c88f488f9b2dd04714e2920653c1afab7d010d81355bbe53edbfcaebea15ff1da48"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fe391bfd09479964276dd59b1d58dc35d2e52175d5fee5e0ea28559bd14655b056da9396880b08a11a17662bac4a7b382e749572eea29fa5ac5793c70e2d18ea5bb5ed745f7425de3873ba37c460c85acd2f4f50490d9d3680fc958bb85bfda6f488f9b2dd04714e2920653c1afab7d010d81355bbe53edbfcaebea15ff1da48"]}}, diff --git a/txscript/data/taproot-ref/f803ece8ba109526994448413d0b5389e89fec0b b/txscript/data/taproot-ref/f803ece8ba109526994448413d0b5389e89fec0b new file mode 100644 index 0000000000..408629dccd --- /dev/null +++ b/txscript/data/taproot-ref/f803ece8ba109526994448413d0b5389e89fec0b @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c452010000004e24b6b360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127082010000008e6c8db2045a9741000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7965802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914719f78084af863e000acd618ba76df97972236898755010000", "prevouts": ["2c1f340000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "c8200f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_be", "final": true, "success": {"scriptSig": "", "witness": ["2a4e4d2690b383f6bf7d76118dc9b47a989676a8aa38c26587f9f3c1545e7c29b510fe6adc84ca6d4a92fb29af735684c01b8268c0bd2a40d6eb6fa3df15072d83", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["af77173d64c354a97cc4aff2aad7d33623f6d31a2ec2a595d5a535ede13602789ecb36a77b0a03d3dae4f13b6cf6c124afb14ba6d6f33b30d86dad64faf88538be", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/f808813d157995b8d10c3cffd1f2616528fdad1f b/txscript/data/taproot-ref/f808813d157995b8d10c3cffd1f2616528fdad1f new file mode 100644 index 0000000000..a5f3ecd08e --- /dev/null +++ b/txscript/data/taproot-ref/f808813d157995b8d10c3cffd1f2616528fdad1f @@ -0,0 +1 @@ +{"tx": "f8e59ec202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b020200000080e71b9e60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701d01000000ff9dfcfa024f03350000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787b5000000", "prevouts": ["2b8d260000000000225120eeb645229ded9c683f00135b937b2e4e86df68d251777aa040a582f59863bb1e", "b21a100000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["e24c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93605be3ea16000e1e5d0cd0f286bdd228006eef88980c7cd756b0c9f357e0882437c6ac6071aeb5642f86cbd8c403a36f49b1ae971c310fa0b2c6d23cdcc52f9ae3b30ae9fa149c8f8e298eb730b57bfc5eb02dfdad9864c9ec3129b8b9775e615"]}, "failure": {"scriptSig": "", "witness": ["4c52e2", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d51ab4aa5d5e3dbd00e7a6b81724e903c1ca482dc7bc8339f552afc52b4f38fc6a5b77966166a359aa5541e77c34a58fd9dcb7d88ef6e7e0cd0e140e1adf959d28b"]}}, diff --git a/txscript/data/taproot-ref/f8136e4e492396052082b2d3eb7f45ce735b580e b/txscript/data/taproot-ref/f8136e4e492396052082b2d3eb7f45ce735b580e new file mode 100644 index 0000000000..0a2673ecc7 --- /dev/null +++ b/txscript/data/taproot-ref/f8136e4e492396052082b2d3eb7f45ce735b580e @@ -0,0 +1 @@ +{"tx": "21283431028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49b000000002471ef9560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701502000000ffca41f901f4dc31000000000017a914719f78084af863e000acd618ba76df979722368987c191064a", "prevouts": ["4e9736000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "2315120000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["db4c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361eadd57732c956dfe38750ac99bf9f6a185a50e2b535aa6e427b8b7d9ced3e4c3f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082a04823906532712c3d4cb334ae6c7c41a1294a824a25b5277d43f47953a1da33e053a85c36f8a6bbb26ecc461a581c33f0f0e79993e29030d20b8bcc8871f830"]}, "failure": {"scriptSig": "", "witness": ["614c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936387e64f87645be2ecaf6d33cdf9f0facef33dfa6a290eb8ddb5654788a0f6944ba0f4accdd80d494e1b95824e4feb55c95caee559d90e25fbf6396e2b6be61303dda2dfca806ccc9c3ad62846e64b9ac16121de5d926db5bebf2e82f8dec8d2a"]}}, diff --git a/txscript/data/taproot-ref/f82150120ceb9a7b6d24c8144a2fc40fca6c7ded b/txscript/data/taproot-ref/f82150120ceb9a7b6d24c8144a2fc40fca6c7ded new file mode 100644 index 0000000000..614dae6e6b --- /dev/null +++ b/txscript/data/taproot-ref/f82150120ceb9a7b6d24c8144a2fc40fca6c7ded @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7400000000ed794b8ddff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2200000000422cea9001bc295b00000000001976a914c629d61df58baceae110d15eb5b55e144268615388acaf970346", "prevouts": ["1f3653000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87", "fdbc5a0000000000225120469ff3412c89f5805e53fbb9303c790a98dd32093d40e3b7dfe22bb05f85f37f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_hashtype_82", "success": {"scriptSig": "", "witness": ["96d64d818258c976c7920c0e8a7797d90fe7f62e090f4bdd61ec908801679506f89e5e41d15e0f24bab418a194ca5f9758a9dc13316239c5cad2fe229fc6f9b782", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50d3e09a20f2e8779831cb302d568c9425c209cb5b98a5ac88437b4b6666b13231624513d6aef0e03758f91deb751c2a3dbf203ac10049a5e6ee2a65b38f3f8c511254096298cedd5acf1630fe965b59d887030edb7060defe9daef5930ada70174ab0f22fce103aa046d86ea2274aa25f89def91e7c46d789623a231447612dae1eef9e01f79acce2e62dbf005feaf6acea63a5ce268397cb04a1e7e0e9a156a7d1cb0a60b94ceb314ccf884d21fdc56e4a24db35c759200c"]}, "failure": {"scriptSig": "", "witness": ["8950174d5d07f79d86a9641569535ddc0ccc9f2a952766d99565519120b22115aa910d6923993976405cc3feef2e8094d5d1a9a9d49f5486e2bf03ee27ad17c982", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936", "50bf4d1fe99c8a8d15a60f1705e2c91cd7af"]}}, diff --git a/txscript/data/taproot-ref/f846835025106a0f7d7d18630b87f4321e626835 b/txscript/data/taproot-ref/f846835025106a0f7d7d18630b87f4321e626835 new file mode 100644 index 0000000000..57d4ed38b6 --- /dev/null +++ b/txscript/data/taproot-ref/f846835025106a0f7d7d18630b87f4321e626835 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf92010000002d7002b0dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cb100000000c01dcced048b91e100000000001600149d38710eb90e420b159c7a9263994c88e6810bc75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79628eed841", "prevouts": ["b3f9850000000000235e212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "aa485e0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "6c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ec8a01b0e4032a423e99f1c4d6ecd2d2b88eecc51e0791d65e631b79e0d29889c3000b960c1063a40dfb5dc510671dff140eefb73aa6757bc42ddda0d13c6b661"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367eba9119756d434ff44abdee5a94e7585a9a57670d5d24b9bc15dfbf2b5caf57c8a01b0e4032a423e99f1c4d6ecd2d2b88eecc51e0791d65e631b79e0d29889c3000b960c1063a40dfb5dc510671dff140eefb73aa6757bc42ddda0d13c6b661"]}}, diff --git a/txscript/data/taproot-ref/f84d4edb22fee2109b5e00fd5ac471e49c15e25c b/txscript/data/taproot-ref/f84d4edb22fee2109b5e00fd5ac471e49c15e25c new file mode 100644 index 0000000000..35d78b1d25 --- /dev/null +++ b/txscript/data/taproot-ref/f84d4edb22fee2109b5e00fd5ac471e49c15e25c @@ -0,0 +1 @@ +{"tx": "3ba8d6ed03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1d01000000e3bae3a4bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8c0000000072f053efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0e01000000551026e5037abdec0000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb7963948d921", "prevouts": ["75f85e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74c36b0000000000225120901d00c5a53f44ff53918b171e70ab2bbbfff6b107bf8ab5ecdbe45602efd01d", "26ba240000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_85", "final": true, "success": {"scriptSig": "", "witness": ["85ba65144ec5de235f0845c21c253aa1f236daf1721ec5ce560cf0947c9254f4819f6f6d146c485d92203e4d2665a7f7363fbd13dfbe16419a9e9abc6957189081"]}, "failure": {"scriptSig": "", "witness": ["be6919a15e50ec80ba8b991c63f887f1d1ba2309d4801d573d3f335490584d69a3c8957c26bbf4258eb00d5939d2e8a6a5e560b66fcc72c12d58e58bf7dec71d85"]}}, diff --git a/txscript/data/taproot-ref/f86da2aa3ec8718d5308b84e38864225dfeb6819 b/txscript/data/taproot-ref/f86da2aa3ec8718d5308b84e38864225dfeb6819 new file mode 100644 index 0000000000..cf33c37b57 --- /dev/null +++ b/txscript/data/taproot-ref/f86da2aa3ec8718d5308b84e38864225dfeb6819 @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9501000000a8b3eea4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6601000000cc72cc87043cc19900000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e71b040000", "prevouts": ["60ae7b0000000000225120ab4625f49c703a23e189ede82045800566d41c1fd8d57f05292e3c6cc685d2ae", "2cba2000000000002251205ab8b22cfa491307edea11ffaf6a065b7e494e63cc66e0c2b2743a26e3a8b68a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364811c32104c8163ae86eee8111aeb1d0c2a95f553393d749299f51992bd2412b"]}, "failure": {"scriptSig": "", "witness": ["6a34616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f880da185f238333598d20ee2e139229db739f94 b/txscript/data/taproot-ref/f880da185f238333598d20ee2e139229db739f94 new file mode 100644 index 0000000000..09a33229d9 --- /dev/null +++ b/txscript/data/taproot-ref/f880da185f238333598d20ee2e139229db739f94 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd20000000060f33779dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b70000000001ed470278bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ab00000000c60fe4de03dd71ba000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914719f78084af863e000acd618ba76df979722368987a6000000", "prevouts": ["e3725e000000000022512058d9157fc9d952418a25b425d32bdf0bd8b0c43f9b89a53f52a9ce592c2bbecb", "5044260000000000225120af0a79bea452506df006e72c75367a56e4c5bc681991443c0d3eb6d09440377f", "2a20380000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["e3", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e17387e8fdb6e1953b8492ce494f93b549856be52be3e0b2251aade3a72c8c2c0db79b88164a8f67b1298a482dda9483af1363bdf02371c7e121a2c285843f3f1e449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c8b4938871a8e43bb69010d25957b1b3dd5e0f775cf541eef5db4a9b76fa4cf4c71af5165e16a75a4d38ea496516a466796a1cbb48ef44578cf258de537130fb0277e21fac1036469cce09bee47dd6f35fd38d265061a05632a5c9d8280907c6449280c515e7ef393424f0dc01282cb8b28e26e76822dbd41f29cf7fcf3ef3a2"]}}, diff --git a/txscript/data/taproot-ref/f881895a273c1bb8b76313a9f0ff65520ad27975 b/txscript/data/taproot-ref/f881895a273c1bb8b76313a9f0ff65520ad27975 new file mode 100644 index 0000000000..62c8c83082 --- /dev/null +++ b/txscript/data/taproot-ref/f881895a273c1bb8b76313a9f0ff65520ad27975 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf090100000080c5ae2e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c408010000006b50ec9a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46f01000000809ae9ca023333d50000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e78c000000", "prevouts": ["8b6969000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "5187380000000000225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "971f3600000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "677d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362ed6d007bbf77981b2b4b9d56de334ccb7bea90f2e4de65bf3c704c80b3ea05cda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e577a14a6eded01e2af38af60eef18c742302cceec7e721187e3fa159b8f76816fa195b9f6f39c732eb35859a6bf094cf148e251ed4d8a79570f47a225cba2c42"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936db89d69a983556104bdeaa20c3c7cf6c5eadccf0658711338de1f7551c0feea7577a14a6eded01e2af38af60eef18c742302cceec7e721187e3fa159b8f76816fa195b9f6f39c732eb35859a6bf094cf148e251ed4d8a79570f47a225cba2c42"]}}, diff --git a/txscript/data/taproot-ref/f8835febdb55dca918a36795f2203f4ee4a6b841 b/txscript/data/taproot-ref/f8835febdb55dca918a36795f2203f4ee4a6b841 new file mode 100644 index 0000000000..6e074162e6 --- /dev/null +++ b/txscript/data/taproot-ref/f8835febdb55dca918a36795f2203f4ee4a6b841 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270df010000000d2d46bf60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704500000000609e4da760f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a601000000c24588ea01641b0d000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87260bfd52", "prevouts": ["9707110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "bde20e000000000022512009aaafe5c25742bc31707a3d3e67825093b9287fcffecedf6a81328faea09126", "f260120000000000225120f52aac6d1851a3bcc3e02eab41e79301b2d0925e53812529fe85f9ade1401e4d"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902473cc65bfcdebfd82df412219de8bd13e6e17501aab721e02ae8ce645099ae0ceac3ad75b7b2e8da66ca599e3ec3079f034c51582f9904a0f4224e2b815e1a6be94a99dc1b3fbdf1fb155dca74cdb089ae0f782fc880a053987dc17b39be8a397abc573e43d15576dcbd4ec120705d4c89e928857e55195a0b263459b592069b25441c6e7f0a949d561f81bd864dd28a81461621fb802b7b3defb9d161cf5f292fea358382c405594fe46c5d7655e8f7473392626b6b883e97bebf21d217694720946d6c686a5d862c488f725be6a7986d982738d7eda987b568ca4ad627302bf6a22b042116e3498e69595046eb99b41cff7684ada77246142d19c7e4ff36d33ccfbc976d26f9d4d088dc3a0643b4e2a314ea145f82c97310d956fce8620466f08965c2a9337c8622558794fc766875506cd90bfcafee9f2f10b4a7aa2fba964296b71d469e1bfc45a25db6b5edb965d93140f03b3680a5931d9e361b8d27334e4c03b026a342fa5cbe675233f1bcd63c083c021921d68cae2c6b88a0e64795f53fe02812591f10ac604c9de783dbd7afdf487e58c57f4d16a5af509d93358b3cfd4e4efbd45254d95102136dd0878fe8409d7469d45ff157614f9e214ef13dfe4a8d6b44ae96e674844e20d3fd03b00a8ed5f79b319a20ef4399d0c11771065179d7901d6086b29fbe3e66117313c6385629c6a9ee003db61cf77258f6d950020fb5ea0cf187760d75", "9a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4bc06d4332bb52a2dcbc7a55bc4ae6946dddd938636e5b51064f41569d763ab36d8f87b1e85da432696d33eb6b4e5e78e6d1d086344ff9567d72236d13448237e56d08eecb8b548a03ce82dd22dc92a64f1be159e88ba8944ed4666490b777c"]}, "failure": {"scriptSig": "", "witness": ["4d0902012a9cd2f836f86aa506364424c28ef20cfce5502d236349bbb68136664f73482ff3cb957fe78bb3ed6e3c6a31eb5108e3dc23a4a60071a2dd99b9e1dad6ba60e351372f2d653dafe72efc7240b1cc4d30429db8d1492e3a046490880b4987bf517d5ef4f2fd6ded9786f539e2f2fc6a2c7f4563d0e03e59c1d5632ad313b561b8512b3a2a100899e3714244be3332ecc07a8f697f2a54b2eb871f1d52ea2fd55f65354d40eb8e765b6b9dcdb537cbeef1117a2c4f6d6f2f86ed7ec5e6edbd5d032b21b8384e1e231769646d556ce4456559dd4c68f732963d31b694f5b591c9108656b8a9cd1ab1a201752faa2de6e570b559689f4b47dc70cb250e49f2a20f719486d4cfd13965ec83f45b18719ec00cf2fbe8f487d26146c0bd16db7175200542eed3489556568bc23f3d41eb456e9956a501e2688fec080afd0a401cf288e1d7f8ec0e9ab679d5a7f4a1035caf7223047034cbaa27711159681e5d74d0aef443a2a88c74f1caea4cbf38a51cc8305018e81899c4d9d84c67b46a44e8ee0f6f339968726a93900409ddd8979ad042f623e954e7eb51bf9d3b62af636b2b5f1ef637e0546d97c6ee48591a4121bd4111de9ac98f0bc18555f234372637cd25e7f95bf04eea85268add7ef395f6689abb7bbd94b5ed5f870af2fc7a98f6ab15c7b86e5d36e1cc9ebce6a35059ba1934df4ecc832b15890717198148e20a00b9dc7143f4ac999028e775", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361423b2e0fb5322b254cab9d769b8e25c52cf91cc54a09a7894a482d3fd1e988536d8f87b1e85da432696d33eb6b4e5e78e6d1d086344ff9567d72236d13448237e56d08eecb8b548a03ce82dd22dc92a64f1be159e88ba8944ed4666490b777c"]}}, diff --git a/txscript/data/taproot-ref/f8930f55c55efa927ccec4a3a273d7af679fe190 b/txscript/data/taproot-ref/f8930f55c55efa927ccec4a3a273d7af679fe190 new file mode 100644 index 0000000000..60e7d61bcb --- /dev/null +++ b/txscript/data/taproot-ref/f8930f55c55efa927ccec4a3a273d7af679fe190 @@ -0,0 +1 @@ +{"tx": "3b690b7c02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bd20100000061e238addceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1f020000001b923abc018b9d0600000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac8a000000", "prevouts": ["180323000000000022512027f9b2b57f7a44e5bf8532a7eee0efe01d123524baab13824442034531d1453d", "ffde2200000000002251202bcd1037a7ead4d36c79b4ba9602283e849258826382b8d227fb6c37d295c423"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "c0", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360b0630a14fdba5198d2cd32fc4420c8a8ab4ff45908222cfc645bf4223ff04bdf827dd3f971806aab342b51fb6c2519c5b3aa410ee2eacb06207a66da829722129de37322ddf566a2356077a247b666bf816d75bd62d8842c555909c8a1545e03de843256fc2f72424a897ba91cb5d3893aa03eaf52af3ae765db300c5c19165"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f54907a8d380556c8a330e16c78ee3af2c39f1cd46f776ecc20664efdc303ae9784ae775de15fa9e8fc81d7676ee4bb7b8b5e55729a9bd981757787c0c2477c76fd75cc9ac1e6f185878d252db6c7bbd874f5ae03fa9961d4f4a0208503b0750f17ad4bbf375bb62f626ec8048d4347cc1eef977780228a6d2fc47294088d561"]}}, diff --git a/txscript/data/taproot-ref/f8d8d11d95153ea9449df09e90a108d0d46dd36a b/txscript/data/taproot-ref/f8d8d11d95153ea9449df09e90a108d0d46dd36a new file mode 100644 index 0000000000..46861277b4 --- /dev/null +++ b/txscript/data/taproot-ref/f8d8d11d95153ea9449df09e90a108d0d46dd36a @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf10010000001f3f7932dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3401000000f67932efdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b2102000000826b9d0304a1acf2000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688accafa8b37", "prevouts": ["0a62760000000000225120a1fcba824e09608ce0e4adebb5c0144bd444bc623da6b47f88c86cb859b1d13a", "ff685e0000000000225120d40d9fd470af8cb0d93055b906564b331441f52449b6053adb5dc55560c180a5", "64a1200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "4e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08230e8cb56a1cc46a8845ca28d4847c7375475f2f7976a44b43884e49f27807546ab153920b849b6028620ffd2b7e486a6f5e2411aa058dab621c72a45f67f5d8e"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936323ef28f4e99bb17bfac2f1234bc4bec8e02dbcd7bd8742e9803ed76c3e6ec8530e8cb56a1cc46a8845ca28d4847c7375475f2f7976a44b43884e49f27807546ab153920b849b6028620ffd2b7e486a6f5e2411aa058dab621c72a45f67f5d8e"]}}, diff --git a/txscript/data/taproot-ref/f8e2668d6408cd99bb9b4144dccc869b5b5c3995 b/txscript/data/taproot-ref/f8e2668d6408cd99bb9b4144dccc869b5b5c3995 new file mode 100644 index 0000000000..dad045acef --- /dev/null +++ b/txscript/data/taproot-ref/f8e2668d6408cd99bb9b4144dccc869b5b5c3995 @@ -0,0 +1 @@ +{"tx": "0200000001dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cad000000007467c8bd039cbb4500000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914719f78084af863e000acd618ba76df9797223689878589b224", "prevouts": ["454b480000000000225120ea4dd4fdddeb85910d968a8720de3e26cfa946a55a30f257fee5a4b92ccf36fe"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["ec", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0828ed780475d4e357c95738577784a2a9ab12c45b3a32d4ee82ce9965ecaf5f6bbb17c496824b626c02ab547b0eab6d99cf720fc5f5950d9f56a4e0f1a7586e075a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368fc8101a1f14b662558c0e8593c88d9d486003e9c8266cbc14341013234749228ed780475d4e357c95738577784a2a9ab12c45b3a32d4ee82ce9965ecaf5f6bbb17c496824b626c02ab547b0eab6d99cf720fc5f5950d9f56a4e0f1a7586e075a9cfc1055a4268af502090450271f6d102883ab16be8e011ae292d6da52fbee7"]}}, diff --git a/txscript/data/taproot-ref/f8f8928329f1f5ae3c966fb5ec2113e076eafcfe b/txscript/data/taproot-ref/f8f8928329f1f5ae3c966fb5ec2113e076eafcfe new file mode 100644 index 0000000000..2c8f6705dc --- /dev/null +++ b/txscript/data/taproot-ref/f8f8928329f1f5ae3c966fb5ec2113e076eafcfe @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c40000000009d51e232dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c42000000001c11fa30025f6fa30000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48730f47c39", "prevouts": ["9532570000000000225f202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "3d794e0000000000215a1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["549e585f569f0029b8ad233f810536bcc592cd03bafd9d4c76138b19f70f397e613e6db527ac4442db3e49e1f760d605b74d5c253e16ced5f48ac06e5c47c8bf", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/f8f9451ddef15046ebb34b8ada8344e100e77c6b b/txscript/data/taproot-ref/f8f9451ddef15046ebb34b8ada8344e100e77c6b new file mode 100644 index 0000000000..6fd3b3bc2a --- /dev/null +++ b/txscript/data/taproot-ref/f8f9451ddef15046ebb34b8ada8344e100e77c6b @@ -0,0 +1 @@ +{"tx": "0200000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf500100000025b6048bdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf0010000009bc157c302da139300000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787d8000000", "prevouts": ["923e720000000000225120279eabb29e123e29b3e35f5f3a43ff6342d7d66d04195fa790bd9d720ea8f0a0", "4a6f230000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93656e70bccfe8a05e4278ed37056f198005b9b7c7170c1af3ea92479ba6ee8fbde"]}, "failure": {"scriptSig": "", "witness": ["6ab7616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f90c809fa2d5593e55f0033ebff4eb6de3bf7a4d b/txscript/data/taproot-ref/f90c809fa2d5593e55f0033ebff4eb6de3bf7a4d new file mode 100644 index 0000000000..d78c060a17 --- /dev/null +++ b/txscript/data/taproot-ref/f90c809fa2d5593e55f0033ebff4eb6de3bf7a4d @@ -0,0 +1 @@ +{"tx": "8dbcaa8f0260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704e000000001f96ee99bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb900000000f13ab3910248cb8c00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac4f13664b", "prevouts": ["cc920f00000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "1dc97f0000000000220020e1b76f9b72221fc6d0b005cf598043f1c9baebcf6357c47a6fd2c54d470c73b1"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "success": {"scriptSig": "", "witness": ["304402200dec731c63b4cb576ed1aa0d68b96931c6ebefabde27dedf1c0cb0edb933a87602206432d636c7234f2784526d52b6ef0e7614915c1987b2906cf5fb26ddd4d85e6003", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}, "failure": {"scriptSig": "", "witness": ["3045022100ebc3c78555a75d15e19905be089a7086d4f3283446cc7f3eece805376c6a5245022041074126509f962778c6435c65cdb55abc66f4f8258f933a257e6ec784b80ef803", "4104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893ac"]}}, diff --git a/txscript/data/taproot-ref/f92ae6d39d23d890f0a4bbb1700628cf97bfd5a6 b/txscript/data/taproot-ref/f92ae6d39d23d890f0a4bbb1700628cf97bfd5a6 new file mode 100644 index 0000000000..d4549d2afb --- /dev/null +++ b/txscript/data/taproot-ref/f92ae6d39d23d890f0a4bbb1700628cf97bfd5a6 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf090100000080c5ae2e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c408010000006b50ec9a8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46f01000000809ae9ca023333d50000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e78c000000", "prevouts": ["8b6969000000000022512027fec823148be86509eead145c0fc284438e34535639d609cff1daade835bbe3", "5187380000000000225c202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "971f3600000000001976a9141cc39a492a6f67587324888ae674f2f534a7639e88ac"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "47304402206b0d26fc7d5aa03514d2525b7b97e2b089f28244da8583a4545ced8f2d8489a9022050e337d5704d85948d1f3fbd3cca389036727bb1e08426e0b98fc16ba695e765014104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}, "failure": {"scriptSig": "483045022100ed726120bec6c442a1f463d10affb9f04e8109102d21d2c3f2624e467f08e00402200294ba13cfbdfea82f4684cfb62e3091546d98f0f60dc501ac811c25bbd428bd014104d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893", "witness": []}}, diff --git a/txscript/data/taproot-ref/f92ff19d417dd30243bf0048d8947d33b4bf7064 b/txscript/data/taproot-ref/f92ff19d417dd30243bf0048d8947d33b4bf7064 new file mode 100644 index 0000000000..d2730958cb --- /dev/null +++ b/txscript/data/taproot-ref/f92ff19d417dd30243bf0048d8947d33b4bf7064 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1800000000ba47f20abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5b010000002d1ad987014ca42b00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac74b5bf31", "prevouts": ["d8116500000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "264d63000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902966530f152f3a446ee34537de1160c2c45522243c0aacf231686b36dc6b021273dc7698a8d3b96111f78979242a46c68076259ea722690fa2ed13b3bff3641576f66f2aa864515ae45a22c4e21628fd49b651dd942127d16de21c5cb84b73459a693871f7b74062fc5fe28f5f8fff510e8645a1f22a3ec507e87aca9179b72dd904440b0d41d13e13bff62907721a864040ffc87078c3c77bbd04c04b3f1e3a9c4d10186a80667274e75d1343f16b7c8494fefe947640b49d50a1034b0a6e407759e6065849f9d3ffc429fa8759d27b51f5ea04764fa94495845b1b7e14e546f423404724e5ef223bdf918b1e9e7dff7ceb6f94a5d6816d3e61424f41dc027e65bab6dc12bc40a444b0dd4f73899fa31e6b2899b0eda4bae05fbf173340037084e50562d3ac3efc4ca44e17e9e71e75b7a4bac44cd42427a6eaa44a07b51ff579f0888c304a93b86445a6262a3d1a6bec4174d8e1c3242407697c7307eca2659419f331762bd4a5f511f8f5809216722d8e3101fba876ad03379e3982eaf309c4795f11636695fb9bb6e5f5b8e214eee9a832018fa4d93a8b761ee148b28b5e5f7a6ffc590e64cc8e4a790696448167ec8ad24ec09ef2aad174975aebf311b9c37bfc157f639d81eb5e883ce4beec79f03d77841d94d571ef99bfac17b88173672e19bcf5431ab8a4bffb9f86408af0a661726d5aea4198f2f101c3a8466a1594efd3323159965f77775", "557d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365570074ba5d6534b1acd7012ede0bb8dc645b9846f6493ec98be18925bfc342d2d0ae3a8a51f8512ed3183c6b189898e3d13807be8720838a97bd7135cdf46e7da77d1c2cfbe9569ee5db2c51580a9857624040db9177af617be0771cc5b8a1b"]}, "failure": {"scriptSig": "", "witness": ["4d09025bda3b7d42ec465570f9a1c8b32a3b73052df58358a4cfb6d9144b73c58e42d1010bf3e26186d3eb501d05d8a7d394489cee54773e5787e3cf22abaf8d98dadac3f3de0a9e95a2a696a005176e8624565f027e42122cb5586da3a5138d9e27efb1450dfa3e56171f2d51e23674f82a5019f67b66e1e210cdd0e06134a94c0c92598f9c3437ae9e6a0b6afe889095f88b7833360f2d7674623cc0d0e24050459a8d19ac7749cf48eecd0e7656c1aea5f44f39d13e659d448fc3fb600d111e0de1ed7c04f747140118e4a638bd23ba4209d0ea9274e7fc363247904674f583df80fc6cab3e1a57f0a0f3d554afd3f02b023e7183f073dc04bfeb85cf0a3da04575d7bce0e3c9d106bf30d0a6b5b69744327765e2ff4b8e9d9bfaf2ace4645a0ad8cffb947799efe998f9bd2536d1c506bb06d44b8eda4303adafa63dbd61e9b42b8cf59188957679e185bb700be07de7e67ac158bc48bcf5ce1ccea48c55feeccd37c2356fe36a1c765300b60dc5b8b6a4eea659a1d124fc25f251d54e8405e0d63a1077fbe62fe8ac7cbaedb1f958422fba811740949c91c9b3c627e014b140dc33a320729194a0e7114f39a843204f930f537f0ecb5a9d33c58a9fb5f4659d6fe7f1a123a4eaa0118ad71f1855e33bccb1d2b8a06b1e386761a1acc02648d709df78a7ee4635529fbca5bfe3d9d43dbcf9831ad49a3efeb2bfd36c97bec30c1c3fc74bc0a4d446b50d75", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362e27c3ef10f9d2f55b89f870bb007bb039d5dbcdd8b8a07f79103695c3c109fdf33eaf0e0e2046a2b327db0183a88d397c5be0a86c812e98815a20f9da9843a2a4c5d50721208c85113b157b4dd4688510f63bd33d4c90ece0d9e0afcb8224b1"]}}, diff --git a/txscript/data/taproot-ref/f950057a3fe68206273e224b1a0c92d75bf4cffd b/txscript/data/taproot-ref/f950057a3fe68206273e224b1a0c92d75bf4cffd new file mode 100644 index 0000000000..512fd0b641 --- /dev/null +++ b/txscript/data/taproot-ref/f950057a3fe68206273e224b1a0c92d75bf4cffd @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf1800000000ba47f20abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf5b010000002d1ad987014ca42b00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac74b5bf31", "prevouts": ["d8116500000000002251204cd7ec6ae4f2b0a3444c5804c92054f57c943d1375da0f99d43cad136a94d2df", "264d63000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["3045022100ce090b0be1e63db11f84335f97a38a7878541f5f012bf3b904fcc0f6c840444a0220381008f21e1f710b2966444f8b7c78b5d2881f4c20cf6ae2d426a3f332112d4482", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["3045022100b6a94089c242da02f6d05ff53cabf59b77eea81481b11ec61c32c10570f20a6202204ddedc993527bc0d85e31aa1e8b9cc49fdf5ba326ccd4c3782a00e9f4d80333682", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/f9527f53e0c01295c939d322769c4900690eac47 b/txscript/data/taproot-ref/f9527f53e0c01295c939d322769c4900690eac47 new file mode 100644 index 0000000000..72516836a7 --- /dev/null +++ b/txscript/data/taproot-ref/f9527f53e0c01295c939d322769c4900690eac47 @@ -0,0 +1 @@ +{"tx": "84a1e22002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6700000000d31a558abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3e00000000a47f97e303c77edb00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7b8821e39", "prevouts": ["fe68600000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "69857d00000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "89", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea0237369b8fe49ed1b05e21155f7ffba4fa029aaf0d531232d0302472e08390b90b3e537e0a498718b42d83f823725a04b39327b9237d74ba7af037a7c89be8bd8f71710e2f4773b226617f0b144a9d046788db13e8347a383f909c13421323cf46474fab8e7e9306b35224640e271c3ad2c01a28b74e8035b5ea3da4b2d4b1"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e15f4861bfb2a6452ac4a4804b2c6a2c641047e4f139d9501cd1bf471f8e5b3ea6913d98effacbdfffd2adbbf71932929e08e9cbcb7e06a345b8d84d9192524cd99d8f9ebf09b0c450213ac35faa1ca38fcf1ad0a46ee35414da06dc92335be8b4"]}}, diff --git a/txscript/data/taproot-ref/f953c76798af4534303b789774638f6750bf064f b/txscript/data/taproot-ref/f953c76798af4534303b789774638f6750bf064f new file mode 100644 index 0000000000..42d597929a --- /dev/null +++ b/txscript/data/taproot-ref/f953c76798af4534303b789774638f6750bf064f @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf2b0100000003d33c9abcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acffd0100000038eb109e031793e40000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e75802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc01802d38", "prevouts": ["08d775000000000017a914613e66961ccf40c7c83ed07cc80b2528cfe51edb87", "e447710000000000225120e477b1c5b341d71bb24c39a2320bc0d86da52fdae37edac491a92c571a2df14a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364b234f7ec6a8dd17a567955d51e11bb1a7dcaabf34b2b14b63e8c8f172f77efa"]}, "failure": {"scriptSig": "", "witness": ["6a58616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/f95a0a2fc49acea853b2fa634e154189153c8e19 b/txscript/data/taproot-ref/f95a0a2fc49acea853b2fa634e154189153c8e19 new file mode 100644 index 0000000000..18f7314d75 --- /dev/null +++ b/txscript/data/taproot-ref/f95a0a2fc49acea853b2fa634e154189153c8e19 @@ -0,0 +1 @@ +{"tx": "d07c79b8038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41f0100000018502eebdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9a000000002d3f28d1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c170100000063ffc498030747e700000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47874de2e530", "prevouts": ["a595390000000000225120c4289f295f2323e1a679e2ac23fa4ce9cef8c78af5f55473b4c272e984282d2e", "51a15800000000002251209907b2e5a8727f92d01ee9564efd2935f4d16cad3aca9531ec5054e94bf8eff6", "dec15700000000002251204c67bfe7b8ea24990d5c0ded805d67c336776f2a51059014263e3e0b5e292bd1"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bigpush", "success": {"scriptSig": "", "witness": ["4d0902fc7bd4820f0eeae1572d9e91bf2bbbae9c08eb147bfb0969fecdb800d1aa84f10d7cd1713c107a0409705d93a596bdc07570c89add51ad52f005d502d8d02076e311eb89b5ad01844cc78dce05165ac3b3e7c979e5f44f9b0503f61ae72489f477f78beea5d696cd0d9c9686de99c5ba07f5f32243fcdbdfe771ff0582bc4e10b3277da13b0f1bfb40cf081c1578a2b2b1d73820e0fba0d8a49d8a414cc558b34e3ee6f260416a8313bb2c3970c033f58c7141da5adf81443d77748a56f1f871f8225ca5aa05d9efe31fef73e8a22a975d4a3eef3fd317171573ce0b1b2718f69d7030f0f1598974917249bddd6d6a13759e6145be40175a8ebad77131d7b8a7223c3710df0500f54f379ca19315ab7be8fd997d9e186d28107d1fbc882ef296b866dda790e3731b74b114485b8aa39af6297da11c073d0bcb31b92b2a21dc777e7063a642a5580678c51b8df973bc21f7987df2daf361a1478f9f4e8e04640eeb255fbee93fcd9b6e7a2f7985d48d68642107ffe409cc41d2d0ff585e8c4c9ae7266cc8c2232407435323d7b5fa4266264a71f265ac69ad4b7913396229684758a9a9bdaa5815f519d0f5371536b4a48a62894cc295fc7c7a5d81b8a85099d608391275776bd6c73b22a4123a59fc3a627608b111f389889df3ada0f361ebdb50c17a98cc6ab879b70470689d0da13a47063da79a3aae254304c25e7c6f687dc94ce84c598546b5f275dc", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d5183faa9f1fb55f2c754174031ab88b9fb2c4d1471ac070ceb12091a666ed99e827470af5f469e43c444817efa23ad8740a4ec3822d36804e7973b39d521bdef59faeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}, "failure": {"scriptSig": "", "witness": ["4d0902a01aa5c6a07e8b63c4b5caf6d935f8ced78752f84f4158b07970df28f8ac85848b2abfaeeb6f641e3dda2e01db7e678d4f0260f192616d0109a787dcdb71e6a00224cd795be015ce50c3afe419ce3392569ffa15d852421e4119bc357ddb8857dc0ff19e06d5aeffdcfd30c62f5549a3559789de15c841eab2c65dcc5a43503e63938f62daa8509b8430afbd2e4745445f84a8500d84dd7dd60b7c21120a16869919b097568deda20d7280777fc93de59d3fbb664b4474857f327b6425d62bcc4c61fd1758a0892761d5b29b5f757a383bb464ccaef225797aa00539ed641e0cb76a4c86cd2706ce1584583adc27d8f0004f8bc753459728ab820869a2be6fc35c75229093e0e22defcf9c83915a871fbbea227c8a83d8f0eca091e5f0f3abc0115d6c2b64870a4e7f1cee49b34e39ad9eb8335ca38bfbf886f75f1b899a0c8f3b7c83db0d8206cdfc7e36cc0b8916a30c087d8aa7cee72529c32ebeace7e6fd2e0994b7aac8d4a8151c35538d95e5b63dfa2b26c0fef794c85b8872a52c3cabbe936dba05ab2a262f853cdb05428677557721b5f72567d86fef1df45d77fe08fb1ae78f10fac539e7902de09b10cf00c5395ccb2e7911fd8d51b82f1c16c205db3e3353d19a686f3b49e9651941858c8d3fe44b8da718e05189938534bfe2aac7a9710a872bff685f65a6e25a682c4141259b772f7703b460c715d53c9706341ff283c941d0d899507561", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93688348219a84d53835cacb5e278792a361bab3f99c1b38c46419f6f84c91a9bff6950266b78c1c1a06b0abf9d183417cba91a47bb46abdc469d8aa6f91cbf6a3fa39f866618102a4b08e1c83cadbbeb41bf3ed62f238c8432fccdf019ac45545bfaeb7b84c883e27227adf79edca80c57b026715ff0da0f52c5e2d2aa306e3b89"]}}, diff --git a/txscript/data/taproot-ref/f9ae968bede9072e9913f275110691863b21d704 b/txscript/data/taproot-ref/f9ae968bede9072e9913f275110691863b21d704 new file mode 100644 index 0000000000..7b834042be --- /dev/null +++ b/txscript/data/taproot-ref/f9ae968bede9072e9913f275110691863b21d704 @@ -0,0 +1 @@ +{"tx": "4de70a2202dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1402000000fa3ce6a6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf401000000b6192cae031df747000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47875802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374872a010000", "prevouts": ["52c025000000000022512081fe6bd81c93a76bc00ce825f56a69a98e925b76c72731e1070d37ac4d963490", "e47b24000000000017a91477661b6925aaf216859ba3f511d1eeb98029e4cd87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "success": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["304402207d868a2f53f800e4387c8261971bbcbf2a44766462a25438f0a0ba5d3640c332022042097a752da9ee4dcda57407ed551f21cbfce9a2e9934a00351d1c001519a6ff01", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}, "failure": {"scriptSig": "1600141cc39a492a6f67587324888ae674f2f534a7639e", "witness": ["3045022100893ccf09d5a720800608a90705862cce4f26c9fbe9623b1d730ffe9e3d9ec93602205df4ecdca8b974423986f87124e1f8f9110147e52543bac90cf527d3ca1eb75501", "04d70500cb6c337bb15b9d342f75e4aef8fc44c2aeae92cf1059813b79463bc0773f9cb2f3e3ebd960820440fa2837455c997c4f35da4ba1c196cb51427fd21893"]}}, diff --git a/txscript/data/taproot-ref/f9e9604adf8a8fa70a8a2d8699243ba825c4c268 b/txscript/data/taproot-ref/f9e9604adf8a8fa70a8a2d8699243ba825c4c268 new file mode 100644 index 0000000000..fe93f045a7 --- /dev/null +++ b/txscript/data/taproot-ref/f9e9604adf8a8fa70a8a2d8699243ba825c4c268 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b500000000011604128bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49200000000a36624610468c3470000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac78010000", "prevouts": ["c58410000000000022512041c21a039e22b4c62c3aba6b6aeaf308dac861e9dfa80f1544cfdbe544b0d99b", "78f438000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a4f83673b9228ad584e3c758d3a7ef913b0130d95503994689e6b12c1cc0f2a2ca477f7eac6c013e182e33a949b526b028f901138401b50189d2a4f50cede7d4a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364a27ab33ad30c866663b6aaa2ec98e71770b4a6226bfe80c47bff7f69f5996db8ef0ecf285bc5470eddb41e1019d9d697e32571bfa8271cd432e6dc81a28355aef31942b1858214ae33105eca3f0b2cf78e8df05a3972acf71e40f309e975162b655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}}, diff --git a/txscript/data/taproot-ref/f9f75f9ba55d66c16536a85bc2406112ffaef2ff b/txscript/data/taproot-ref/f9f75f9ba55d66c16536a85bc2406112ffaef2ff new file mode 100644 index 0000000000..3575abcf1f --- /dev/null +++ b/txscript/data/taproot-ref/f9f75f9ba55d66c16536a85bc2406112ffaef2ff @@ -0,0 +1 @@ +{"tx": "26717be901bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfad01000000ca211f9e02ebb77c0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487a6020000", "prevouts": ["f3837f000000000022512056841eb16851a8254dd440f9b87fb50fd6caa3d6a42582cdb16ba84fde29c407"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6af4", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9368938b1de1479bd29eea6cd3e0abeaefd74a04968d0ad5778826ab6e5abe10907ebf10485a7565da4888b0296454aba30a39a8416dd3eaaebe7fea4a18750e931ca477f7eac6c013e182e33a949b526b028f901138401b50189d2a4f50cede7d4a6f8b9af6548d116d93931f99bf1698fdad997ce51263e0555061e012c5780fd"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936082ca7a5cfe1a9e0b80c54adc09274a6801d747ad511d5fafa337d754a1e0573ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b270b4d2addc31b8421907b0cff80194a5513593e3802bd921239c9c6063ea806bb655a633384d647dfd447ac375ea9b2c02c16d8a17436cec940ed1871036c5ed"]}}, diff --git a/txscript/data/taproot-ref/f9fc9e2a4f2af623fc883937402f30bb39d7194c b/txscript/data/taproot-ref/f9fc9e2a4f2af623fc883937402f30bb39d7194c new file mode 100644 index 0000000000..9b941588da --- /dev/null +++ b/txscript/data/taproot-ref/f9fc9e2a4f2af623fc883937402f30bb39d7194c @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270240100000016d9ce96dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b740100000085d2d2f90174352f00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388acc1040000", "prevouts": ["3fde11000000000017a9149d4bcb1ed806c9beed692a78614f8b90a68c708187", "7903270000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063bd68", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364beac8453c08a82879ff5e72e60d02b43bb4030aabb448d6315e82d153ff340281cd61fd18311004a5536d1440b72b537197adb3a0d17581cb4a1679e89097edb5843f54915b2c97abdf26ed2d562b36c2375ce95d63af6aa508e6368a687449"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d0820cffa7efd13876b56a4fb6d16fe87f2b3bb25d39f5e6fb1dfb5ce04c0283c8690e634e19498d3396bfa452af2ece499faa564dc4b58fae514f4ede8dd179fb909e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}}, diff --git a/txscript/data/taproot-ref/f9fe421cb9a3952dc45c8d26a7ddd2f53b952533 b/txscript/data/taproot-ref/f9fe421cb9a3952dc45c8d26a7ddd2f53b952533 new file mode 100644 index 0000000000..1d40e6290d --- /dev/null +++ b/txscript/data/taproot-ref/f9fe421cb9a3952dc45c8d26a7ddd2f53b952533 @@ -0,0 +1 @@ +{"tx": "865915d603dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b4200000000458456e0dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9d00000000e0cafcf560f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707a000000000805b2d203a5255300000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4a000000", "prevouts": ["ed2920000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "3f51250000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "e9fa0f0000000000225120398f9b6183163c03ad23a14c61a29f1667ce990766f9351cc380767011c973dd"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/no10000limit", "final": true, "success": {"scriptSig": "", "witness": ["269886b1e345109252e6f614d6637275d1af89f5e7fc3d31083c65a51898fa10ed42fc5eb18ccfee52739c3c519aa55766dfeaa266355ec1c9e850633a81a508", "00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d00006d20871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ac", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c4bd634f33c5ecdc824e032f7f6505e1a79908414cd9cb4904e5be53af7e276009aa0844af634d6a88942fc07e09cac01273a53719e9c7d657ab3dca82f27dff7476f30639288ee83f7e586fbe3eebf95392294d770910004bf988ac20d733d0689898eaa54a64e338f0d6f587db8967e9a32da3cd142bbda1995bbc1041216c07e8ceacce0cc704ff4253cad15b4bad56fa12d498e75acea888835d93f185996410acc12bc4c5dedac1c586862bc30c8c8c35c43f931a88b1e66ce87253be2d9fa8e1ab3eda915843deee8f6933962b6489afb9525529b0503d03bfa76215bd5c68195c04b797f18bb2cfea1a746c9cd9f9f26f7d097f82c81888e43ac3d6d788b3e61c662dc0c68cf1e428de0b3881159a8984908386c22cbf6cc6c3f2d9481e07e856e8b93123b7d28bc5ec1dae7bc0c0785a4b348cb95c92daf9b4a1a6d2b65cbfaa9ed654ade91c00c9fe4f57391c241e95cfd60b1f44f495a05086ba006260268f3fa4d832afae96ff672bd19d7e928d42bc878143589bed193337fe656f28feb26558d4d064770c2eb738b0251c60e0a639239140ddba0ceb61ff7c3e738a88f45b76d7bc9f694c0e4e272f5d4f15822286d483919ad24a64a55c6aea77b92a17291ccc674c2e3ccdda7238c0844a935fb5296ae650389c65e5133f0a612c82056373d0e95f592d1bc3cf4aac0fb3e0b8245a80d6d0d3bc3eab472fda"]}}, diff --git a/txscript/data/taproot-ref/fa167d1943fe2df543ef85cf25a11984cbd5a5a2 b/txscript/data/taproot-ref/fa167d1943fe2df543ef85cf25a11984cbd5a5a2 new file mode 100644 index 0000000000..1fd0a50f6d --- /dev/null +++ b/txscript/data/taproot-ref/fa167d1943fe2df543ef85cf25a11984cbd5a5a2 @@ -0,0 +1 @@ +{"tx": "010000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270dc0100000041fe47ba01f3b30c000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487053d2e30", "prevouts": ["40d11100000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bigpush", "success": {"scriptSig": "", "witness": ["4d0902e03f7d21d2b8b3e12ffd2f14d707486ff62bc31943c6b68eeceb6a6b3fef9d3493ce630b2b2a0663bab7a8067a372d46e196e4494d793481fc12488197d1622713e1eb72dd6cbe73a0f991c2e4a766adc7c3ffac77bbff9ba0a54cb3f1014915f638d82f07c2fd5d99ddc2273334f94b57b93cb8f6d22c796a8e33a6c5eee77ead76ab35ad4821740bcef67899f7c4969a749c27a073e4bda0108870e26e12b308af144ff9928cb2ae246ddf046fa82bf55d6da59100dc52334c56b59693b6cdcd073499deb245170d9e745ea845b1dd02fec310edc94d1599c90ba7ceb4bfb9b14072f6eb1e7a95a3e02916b246f87e71e6d0592afd5c93db66c7c1b12af4cb11bb733385f627495ba5ee6906620beaa8e13d2ca7f39a88b48e14ab31bab1b5273bd53f7134d84e7bbdc05bedf80ef01a9ada58734a1d03237d38aef755fa54cb1a20836611729b44293899a469d9a9b0816ea1f638eecec06268a42f743df127fa80a5fcc162a9152c25caafa1c6459f483b29a13119e28d25f947ecc83865e0170086b64192b40a3e483059301333ca6a83a0f8f421c1728080f67017dd5db6c1fe50b9aee076e16b3d10ca9240ef7b8cf0cb0ed00ac120759704b0f73814c45c3dd4c34e65b0919edc85c05c3650b2b4046726edd43af2032349fba6f037a302d25513fc800a0973c2cb0dbc742e0e866f8a2d892aedaeb617be122907e6136d36fa2e7d58a51875", "537d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9369e56f8367801e6cb4b8a091b8158ac933c3bc0e4e5c9ffc0637287cd390f6356c1fcc94e870ec95c088fd37f5daf805336fc0aa07ac91d9d5a0c770a5a47ed76aee97a7dfb8acbc78fdce4694f8ba1e1e3bf612a81f34559c93e6dfd336d600fd892d02e0db2d70aca72db86bdb1e35d04291625c81ec0b3d884b10be9f787fb"]}, "failure": {"scriptSig": "", "witness": ["4d0902094499413ccbdfb4c4c84178ca8e55e80b1c1ffe32e6be62459c17bfaa45e901bfd28210d71039246543dae4a04606f80beeba3cd68ed7aa3c7c027d3906b6094a30c79f513337d15a663a7e794ec1752cbf29f9f8f6fecd79ab8aaabc85c20a098a5f51dac2a4bc8b913e5e338bb859c5bdccf31ff0f31938776300e71b1be51ca66bec8707648a429e27004e4bbcbe404e6589b8dfa5cdedae589d70d88f06f0c342c2a2c4f0397367075f0933f113d12a04ccb82bb187fd815d79e919858ce39358cc83dd6755bf64abc7fcfe94db82d2967b98bbc2684e0fdee54fe642a54dd214ee6b30721a5a294abccdcb4dbfdd4f28d17a328a1fd1bc7d2471b86b2bcf92eaa08c3818dc0dfe0943029b312692bc4068cc7487554ec6d5bf7dfb57578ab4683bca02c20ee432a46ba031d439e2e5331d757e8c115fda7308c8f76db70a53d208a07ede01fbd5e51a4df26dea35af2d397046bea173ab97bdbd4c406006b1536ebcafe074fbc183a89001bdcf79633b5b910bb648e1cbaca45e06c27e34359e6bd4fa4f95843030558b4a3752fa11d355232f1d91b164b755e5335d5a204b9ac04c14bf73d2165f3e3931f270a3984a57aedec4e4ed57131ec1168c00a2cdc8801d4051e01303d4e13f86d4e3adc71bf40b74d69383702c2922d9203852eb7497f68acbb267c2dabbb193a60e16bd0abd55e78254d99cc3a028f85c9624b5c1151a072ab60475", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa1d38f649aceaf83ba76018e55a1207707882be6904852f7ab0998fc8ad53a321d892d02e0db2d70aca72db86bdb1e35d04291625c81ec0b3d884b10be9f787fb"]}}, diff --git a/txscript/data/taproot-ref/fa18264203439b69d71bc0bf47eb42c09a0276b5 b/txscript/data/taproot-ref/fa18264203439b69d71bc0bf47eb42c09a0276b5 new file mode 100644 index 0000000000..427feaf7b6 --- /dev/null +++ b/txscript/data/taproot-ref/fa18264203439b69d71bc0bf47eb42c09a0276b5 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4be000000007e34d8a360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704c000000009d55639704a6b64b000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6f14dd35d", "prevouts": ["34853e00000000002359212540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b8900", "86520f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["7e6d39cf53a6e18ed0d941a7377d313afcdb97dda6f3349e2246f7b995ddb3951d82f4e74bc0ac5e599dbe27a1645d2d26358c876b70e9cd431e6e277197cbdf", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/fa2f957cce50a9e152ca7a429346901042de9fc5 b/txscript/data/taproot-ref/fa2f957cce50a9e152ca7a429346901042de9fc5 new file mode 100644 index 0000000000..5e282bf339 --- /dev/null +++ b/txscript/data/taproot-ref/fa2f957cce50a9e152ca7a429346901042de9fc5 @@ -0,0 +1 @@ +{"tx": "b8a0e6aa02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7401000000992304cfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b58010000007f10f6d10409577100000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a65802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7abce484b", "prevouts": ["81ea510000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "74d5210000000000215b1f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "", "witness": ["badc8b1e93286f5cf5bb033f2b9660d704d1f7e6d4208b141e049bd781d7a0c41e1dda72e7ea98c1acc7d2125d2ec1142afbff8f8bd1473a60d6114908dcce48"]}}, diff --git a/txscript/data/taproot-ref/fa49e364b5b789a639515d469e423d52b4437393 b/txscript/data/taproot-ref/fa49e364b5b789a639515d469e423d52b4437393 new file mode 100644 index 0000000000..ad242e1c7a --- /dev/null +++ b/txscript/data/taproot-ref/fa49e364b5b789a639515d469e423d52b4437393 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c483010000004b90d992bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf690100000046acbee704b8599500000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487b8040000", "prevouts": ["a0413100000000002251202b3b427270f2ca619ae178ac9705b497d3b6bfee82eb9aa7db09432365097408", "cd9e650000000000225120444987fec3a0729a80d98404b6d5826620ad219568baea49ec5499ba522f466c"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "4c7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082126001c6c44c6d65a09c6d1b267ed4323a5b88ec68ff3dda19058d2d3d94a32d819d45740b1e9d6e416a8a4978331345395bf058ef0b936b66c7755017d83c65"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d840fd1b4336118158b49a207c7c1265147fcdb5164c3ca7c69b8b407af04dfd126001c6c44c6d65a09c6d1b267ed4323a5b88ec68ff3dda19058d2d3d94a32d819d45740b1e9d6e416a8a4978331345395bf058ef0b936b66c7755017d83c65"]}}, diff --git a/txscript/data/taproot-ref/fa4c5cdf26645ea0534a498e6eed0980cfb7a7c8 b/txscript/data/taproot-ref/fa4c5cdf26645ea0534a498e6eed0980cfb7a7c8 new file mode 100644 index 0000000000..eee2a929a6 --- /dev/null +++ b/txscript/data/taproot-ref/fa4c5cdf26645ea0534a498e6eed0980cfb7a7c8 @@ -0,0 +1 @@ +{"tx": "fdc7ce4202bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf0900000000f49ff5b1bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfbb01000000249669d202c284cc000000000017a914719f78084af863e000acd618ba76df9797223689875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e77d020000", "prevouts": ["f3566600000000002251209bc793d7c3b05f6eda9a2c26b213a9e100dca8f4a7f94360c5b61ae9a4f972e8", "cd22690000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_5c", "final": true, "success": {"scriptSig": "", "witness": ["9d69121c64aa823ae8029931fc63dc21a790a754effeedd0b99dd749f199a43b78578697e126f0e825ec8a34ee98dfd9662e0076aaa67f6733f937c1c2bef7e401", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["cd8961769bf3fe148f6d4d3437a9fd04af879c70323c770e7368a04f57fad871add4cd367cdd856d6d72dda471bc287778b07010e63d118d04461f1f4201a22f5c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fa597ee663f096b76cd93b293bc4d7f7aaefc262 b/txscript/data/taproot-ref/fa597ee663f096b76cd93b293bc4d7f7aaefc262 new file mode 100644 index 0000000000..58ea1bdc51 --- /dev/null +++ b/txscript/data/taproot-ref/fa597ee663f096b76cd93b293bc4d7f7aaefc262 @@ -0,0 +1 @@ +{"tx": "fa183ec302dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b530000000029438bd260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709d01000000a26a9cc804691a39000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7b8b82732", "prevouts": ["2b15280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "acb41200000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063bb68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93620e1233246ac9a23fcb5b3ba301349c9efee22ef31ffea4e16f8e5d228bda7e14052bd780e62e78eddfa6319e1e9b5f2922c9c635f126e8f8471707cb2f26f8c7017bb5ae96064d7d19e957b5258c9c864deb4239d29676eb164d7ecbdb9fd5a354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93690dba15435832e62db4273c7c8000a302670526f3381315f96b1fa3e28a433b54c3d251f378473e49463283b18fa00944324abf75c7e60d6956acdb0e7ed03a7354ad806189ae64381d3b11a94f516f6d81b0c787d08b0f0aee4f0e917017ea5"]}}, diff --git a/txscript/data/taproot-ref/fa5f468e5077c7552905d4b235d938ba656a8956 b/txscript/data/taproot-ref/fa5f468e5077c7552905d4b235d938ba656a8956 new file mode 100644 index 0000000000..c386df7ddc --- /dev/null +++ b/txscript/data/taproot-ref/fa5f468e5077c7552905d4b235d938ba656a8956 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf21000000004676830d8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41702000000bbb7591260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707600000000094760f703733ebe000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc56f0646", "prevouts": ["044877000000000017a914b1a54d09172ecbb89289f2a670acc3fe14ced9ee87", "4656390000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512", "ea96100000000000225120c72d052844e54654bf1b4ba7d482e0a32ceacfdb2b793a896c2e00e5d00b606a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "ac7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e32d0ccdc2029b00ec7048abf887bee187f4acce1681536a58b887d4e93139fe875006811b549bdf6e8160f30212dc3199b386e615ec459cd6a9a101291e049b6126490c72a5b15e8927e2896ebf8102d665fc08f8a92e888d3aee8fbb5026d2b"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e6183f419ce491b450889838cb0d7f10895831b7ec092cc5b3df9912c86be24377e3df24c23560dc7d916d43eb4e055d70ba52495a1ba5531ef20ccccb2bc5f4126490c72a5b15e8927e2896ebf8102d665fc08f8a92e888d3aee8fbb5026d2b"]}}, diff --git a/txscript/data/taproot-ref/fa6ab5df5a5d808c4d736244d69510fa6e17f904 b/txscript/data/taproot-ref/fa6ab5df5a5d808c4d736244d69510fa6e17f904 new file mode 100644 index 0000000000..6c515f88f7 --- /dev/null +++ b/txscript/data/taproot-ref/fa6ab5df5a5d808c4d736244d69510fa6e17f904 @@ -0,0 +1 @@ +{"tx": "671d5a89028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46a000000006a1175f18bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c41701000000b71cd6f70163c15100000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac85010000", "prevouts": ["96443e00000000002251205c592164d59d166201a2e20d3b054756549dd213ab6179e4cd71f1fda3a90111", "82ac3200000000002251207a2f20e860cda556c5e91362c7f67d77fa79d70cce9558dd8fd8d88940237552"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/return", "success": {"scriptSig": "", "witness": ["6ad7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045908709641cf32dc4788f906f7e3621a0528df09509ddf1e9982e4479aa4b5d9a2d50ee9aa3de1fe988255b0d8b9f34dc2cecc4a96432b9f704e90359a06b468476e3192190387ccfa53649887be3b08a6a0e7169a64b02c3bbfb054cf523373b"]}, "failure": {"scriptSig": "", "witness": ["6a61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ea06acabd314b946ab482c02917c0ab57ee7a12ea5d3f66acc20e49152ededa94c1a4ef98c473095d2df256e4c96a081ff076f8ed25b9a6c5f4dacfc5de1b1d157a61376c510bdd1fc860151a3b261939fa407ec1a2d0490cf2efc4278abc783"]}}, diff --git a/txscript/data/taproot-ref/fa7d0a81564418a5df2eae24548c51be6486a4aa b/txscript/data/taproot-ref/fa7d0a81564418a5df2eae24548c51be6486a4aa new file mode 100644 index 0000000000..9d0c25808c --- /dev/null +++ b/txscript/data/taproot-ref/fa7d0a81564418a5df2eae24548c51be6486a4aa @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912700001000000f3c0e6a660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707d0100000038f3cdae03080d1e000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f875802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc63000000", "prevouts": ["aeae0e00000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "dbf0110000000000225120c5b78d1c72b60a56d77dd9836e8bbc3efbf1d0cca20448403458031ceee22a71"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "087d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b67972f0806ad83b266cea94fe60bccfb9dd1aa3e3a25c977f11b54b402f72177a9c5848e7797e88ab157cf3f92cb1e084ad7139395a6330a6d0efe4ec0158f0520a79ac573d08fada6e0a495a70546abebfe2eb256837e38d30334686ccae33"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93641c9464980f97737135f85384f09f0e2a54d854eba07e7e38719fe827040e76bbc0204111bf7e5d13e3ecd3b1c8f71c6ecf5827e1a757374a2d5a102d95777fd392ef61cba24ca089522adfb015944d93e6e298b3bdb8572d6b7e61874c3a207520a79ac573d08fada6e0a495a70546abebfe2eb256837e38d30334686ccae33"]}}, diff --git a/txscript/data/taproot-ref/fa862d772ea0c551e8a2b2e955c3a314343a9249 b/txscript/data/taproot-ref/fa862d772ea0c551e8a2b2e955c3a314343a9249 new file mode 100644 index 0000000000..27c7d5967f --- /dev/null +++ b/txscript/data/taproot-ref/fa862d772ea0c551e8a2b2e955c3a314343a9249 @@ -0,0 +1 @@ +{"tx": "ec16b2e503bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf71010000001e2984c9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cff01000000d37921d6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b9d010000006e9e6c8f0155bb16000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8796000000", "prevouts": ["55bd6700000000002251201b1a5025b4fe9992b0e02773e7f35e6be2fc0ec95e56c0e62f01a84c1b9caac2", "4966600000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "2317250000000000225120103e7c2917eb37935b19ad951dd63925690af67710d97c5b32ba23098190dae6"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "4a7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364758c64267c751cdb3a7d0ad4e97f82b7320c0de5dc96a77478bcc9a1aac62dfb1956d2c402f72d86d9128969f4c9ed8db93dfb826b4075483e7d557b0e234b512efaba1d06903f148d2465ca4e4c6639d336576fa6993c6ca48823372648a44"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e696e0a39b8006d5c38246735bc900624bc412e796f8d634640137370e1472505749e2a390543356cdb3691ba8d54627dfb45f7f1132e94c1a4e909f84f1614c2"]}}, diff --git a/txscript/data/taproot-ref/fa8814b8ee8c8c0b59933c5df3e62bc70882f43c b/txscript/data/taproot-ref/fa8814b8ee8c8c0b59933c5df3e62bc70882f43c new file mode 100644 index 0000000000..38935df6da --- /dev/null +++ b/txscript/data/taproot-ref/fa8814b8ee8c8c0b59933c5df3e62bc70882f43c @@ -0,0 +1 @@ +{"tx": "ea6657fb02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7c000000006ca5e1b2dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c82010000009c4ddacd0182ae3b000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487178c3054", "prevouts": ["08b54b000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "d0105400000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000098", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b221c730e6687b91edd1d82ce458a1670f1f5c408c9b3edae12af622fd1823f6afd27be809d0458ddf0db95e5817368170188425ca115f37ef512065bd7b173a4b5563559956b4521d685614895115ff3b761ab3fb4dd1d8def3bf310bb092b594c58b1e468d5c742a8cec262986ad36b584a802070024df25b549bdc05f9a8a"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9365a5f4ba5a5870b42b6e90a30a8f8a9ba693ad2a3207303cea806cfbc5b598730390e5640971602922d6b073671c4e08980ecd1f17d1da07e150f68606efdd1f96e2c0067d6235544c969c57bb6383bc4dfe8083fe3443e336f29d85bd1c9f087"]}}, diff --git a/txscript/data/taproot-ref/fa90b9f27b4ef61835f27c23a72f15ab0bc2f8d4 b/txscript/data/taproot-ref/fa90b9f27b4ef61835f27c23a72f15ab0bc2f8d4 new file mode 100644 index 0000000000..fb525716e6 --- /dev/null +++ b/txscript/data/taproot-ref/fa90b9f27b4ef61835f27c23a72f15ab0bc2f8d4 @@ -0,0 +1 @@ +{"tx": "7647552a02dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfc01000000b71eb1cb8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c489010000005bb7d7a804ae458a00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac4dab3f4e", "prevouts": ["3c0e530000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "85f03900000000002251201e1e43c91fff99f096580082345e8b6c592108fedec9f6a82472097138f3a147"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_af", "final": true, "success": {"scriptSig": "", "witness": ["772396c83c3adfdfb4159e115ccd019751496615d9a86bf5ed75f0f6f6782ed43c6b3366d510c7b7b429087032f6518a4e40277126ab74c18e274e7fd89b97be01"]}, "failure": {"scriptSig": "", "witness": ["7e3b230549998be0e83e84993439922c5871fa7e8d0fca56b406287a8b167be462f1067da339b2298cc161acc2659ee0dccf2944fc0991a82004fc5323f4bf44af"]}}, diff --git a/txscript/data/taproot-ref/fab23300d1e8e0ac77217a22517738b6de5afead b/txscript/data/taproot-ref/fab23300d1e8e0ac77217a22517738b6de5afead new file mode 100644 index 0000000000..5a5e7484ba --- /dev/null +++ b/txscript/data/taproot-ref/fab23300d1e8e0ac77217a22517738b6de5afead @@ -0,0 +1 @@ +{"tx": "02000000018bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4380100000066bbaa8b02fe733a00000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875bc22d35", "prevouts": ["2d6e3c00000000002251203066114b40f5bd33eccc7991d35f41784b4d14ee4746b37c559802b9f69c1e67"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["cf4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936576dcfbd45e3fc8427f121d4200b68bae14bb12011fb1b2bbae78ffacf19fef2e4a15251ce914d64550800735eadc470245b559e7958aa5fe88058750f8ecc0decf70b79dd1be85a38988f8929e7263abb01bba95965800009381ed351eddb0fa653bf1dd2d82b0dcbd644d98f066b9fc3e48690fe18b2084515352f558033ba"]}, "failure": {"scriptSig": "", "witness": ["4c52cf", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045cf32df52f44331c723f7b513b476c9aa41e2dab3be9ace9864b6dc0f919492d46a7a52674f359a7dbed67a49e09732132053a9cde77eaa564fdce3cafe7738b9f4a62e14d7fc4acbfb0196ec29a60565ac2b3043dda4cedec8cb1ff291b90d41"]}}, diff --git a/txscript/data/taproot-ref/fac25d9ab05e1c85b45aa41798674daebf462237 b/txscript/data/taproot-ref/fac25d9ab05e1c85b45aa41798674daebf462237 new file mode 100644 index 0000000000..2547e36dd6 --- /dev/null +++ b/txscript/data/taproot-ref/fac25d9ab05e1c85b45aa41798674daebf462237 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e900000000852477de60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912704301000000434e8635dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bab01000000ef552e5e0380634000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875e020000", "prevouts": ["f4eb1000000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8", "4b251000000000002251206c72b3037c076bc24cb037d18e3d205b716c1618de062091033c827bbd6cacd2", "e5f4200000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "047d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4d71d423df8d84b17d708d44fb85f057f10e7a19067ae82c5093f6b2e5d73dc0d3ad511cf44769b6705694216a5b431b28318b130ebf832e7f6887216fa315d1a343680beaae3fbea53ecc49afe7cbe880992a117d636f336d7d159be7b446d"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c98631dd6d757e946b35f133dbe1fc758574142a05432a88a9c9ab5699e20b5a3af26a389e120e94680e27477caee46163f2ffed4e6499d7dcb61a15b1d76a7c8460181b685601280cbfaae0e90478ea5ae6fea73a2d03f5a79a14a3e0c6d503"]}}, diff --git a/txscript/data/taproot-ref/fad3ceab7d42e3ad2e07e8e88420e42ecf4dd0b8 b/txscript/data/taproot-ref/fad3ceab7d42e3ad2e07e8e88420e42ecf4dd0b8 new file mode 100644 index 0000000000..aa8ee08c51 --- /dev/null +++ b/txscript/data/taproot-ref/fad3ceab7d42e3ad2e07e8e88420e42ecf4dd0b8 @@ -0,0 +1 @@ +{"tx": "020000000206f5bd527bde63f7c45daff54c390a64a59dabeafc8078a9bd0a050f54db6b44000000000096e4218fd15657a619affff084fc6b1bc2cdf5e85e399bb207d84ace710aa8effb82232f0100000000d0187eb30492422a51220000001600146d764276c66fec1127e5074db5bff3aa6c5255335802000000000000160014a4c1279efe108bfac1a01a2fe5d5c45b8fa18363580200000000000017a9143f5d8a006e43f5509420a4ea1e0b36ae11579f4487580200000000000017a9143f5d8a006e43f5509420a4ea1e0b36ae11579f4487a529293a", "prevouts": ["22cbf72c10000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664", "ddc7342412000000225120b3c1b5eb7ad8055b17188a846c986bb22e20c96017f7532122d5f2784100a664"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "inactive/scriptpath_valid_unkleaf", "success": {"scriptSig": "", "witness": ["927f78d725339a9988bb82916001c2fe87cdbe2f22625c6e57a38b67b3a1e9cec429468441f91a498d977c0cfbb981493a854cadfbe774133a9c0875c07d3d79", "20159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717ac", "c2159f9373f8b28a67627a464ae370e1e712479726144a1a48958863033f16f717c320986550a60a376b2d6a26894b932a0140931c95b78be03572545c726a283e7902b78fc59ae74800241e9b7a2e0578a35ace37791478c3e04a51e81e708c61"]}}, diff --git a/txscript/data/taproot-ref/fae57409d88f4b4a8521c3bbd0560991c2a8986b b/txscript/data/taproot-ref/fae57409d88f4b4a8521c3bbd0560991c2a8986b new file mode 100644 index 0000000000..ccde46a8f7 --- /dev/null +++ b/txscript/data/taproot-ref/fae57409d88f4b4a8521c3bbd0560991c2a8986b @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a901000000929372e9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c190100000046ba7ae502e2b28d00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748795000000", "prevouts": ["d018370000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "22c3580000000000225120dd69e0acb4456a75559641628e54f237a5bfa27624d5103e01688d193a4ffbc6"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_7d", "final": true, "success": {"scriptSig": "", "witness": ["9b6b0b5e56df64ced40030513c996573d84ba715e04642611b2663e910925c6f4bb9811b7d90c53f38bd997d37193d541ba12fafe02ca029d260cea17267e6b202", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["718f09d59653ff2e9def5e1d294c31803d32b6394e8a400a74d6f2d4e1f94ded7e19d26d48aa2bf80c27192453c89a8f9f490c588c5d2c871cc988da5c3352297d", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fb0c60f40b98f2127746a9a359165bc8d41dcb8c b/txscript/data/taproot-ref/fb0c60f40b98f2127746a9a359165bc8d41dcb8c new file mode 100644 index 0000000000..6b1e736834 --- /dev/null +++ b/txscript/data/taproot-ref/fb0c60f40b98f2127746a9a359165bc8d41dcb8c @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cb00000000e2137298bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4b010000003490f9c1dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5901000000e9b952fd0237c4c2000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000017a914719f78084af863e000acd618ba76df97972236898757020000", "prevouts": ["30081100000000002251204ebf7559d8ece5a24eb4557ad9651ea9e540f660a3b9ceeb85b1a057c0cbe335", "bc186b00000000002251204ae1ababcab221c9b79fd61156e6b377c6d7a0004ca7d6810cc3f2d6a7149040", "22bd48000000000022512095cedeef0cb7aea3c0bd06d7fb572f0efff66b1d28013a778af1acfd69604efe"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "937d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71ef65737139d8cb51b826e6105ecbce8352aa10f0d50686f2268ca6d7900ff7d4462d371a9b01f30ea116c30e8195d2d6eb7c97c8692c0c95de95a904f83b96ad4"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e88b73eb14a8afa044a1a6f0495df635bb2745ae30a5fce84d6222f661b17136fd6f60e166ab3c31d6fe53c0e4c47c333102fdf48f7428a1dab907384d3ec09a32"]}}, diff --git a/txscript/data/taproot-ref/fb18611c9ee4a416896469762bdeb28572310087 b/txscript/data/taproot-ref/fb18611c9ee4a416896469762bdeb28572310087 new file mode 100644 index 0000000000..305f81baa0 --- /dev/null +++ b/txscript/data/taproot-ref/fb18611c9ee4a416896469762bdeb28572310087 @@ -0,0 +1 @@ +{"tx": "020000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703300000000690e42c28bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c42102000000816bc2b260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270f701000000b4d361eb03c83c6000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcad010000", "prevouts": ["3f56100000000000225120b874b1e22d211de93cb73e099e487e9eba0bad15702159b3571f2da29e9ccdb9", "e9274300000000002251201d9d7b8068d804e3524a88462f1a480f3f4200cc7b90f0ee3c3216cc2f53f488", "35100f0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_6", "final": true, "success": {"scriptSig": "", "witness": ["8c7b47569d187d9fb6d3209bddb5ab3e7bcbd6ffeb3a8b88b82ec3df5e38f5ce3014d70ff93e31690e6e7a9cd0991db7a6ae4548fca0e4395b82d91cc67f4a0782", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["7bc8cc7487cf84f6a0956d7c87b1d000eb1bd650ce6c4f9ee0974ef72428586e3fd1c4c2da9533a80705c394d952ff6decaa6e5f40b16875e0d6d9aa287a03c606", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fb193ee81245f14d9b19cacbf56cbcb01dec02be b/txscript/data/taproot-ref/fb193ee81245f14d9b19cacbf56cbcb01dec02be new file mode 100644 index 0000000000..7c47457789 --- /dev/null +++ b/txscript/data/taproot-ref/fb193ee81245f14d9b19cacbf56cbcb01dec02be @@ -0,0 +1 @@ +{"tx": "4c754ce802dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c9700000000926720a3dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c80010000001f7d298004572a9800000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87b7128437", "prevouts": ["effc4c0000000000225120e181fd7d5a5189f175c5e112edc7401a8c528393c340dac4325961e6f48db1a9", "631e4d0000000000225120a283e1ea0142d34d03fade4b28902cd262d82bab6ae3891658a9596d967dbc43"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "617d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e460f3bb33adb38a0b939502b6e7259f92f13a6469935cb372eb38500268af6f1b0e931380661372836164f4a50b3ffb46f1fe83bc177b7c1bf309591800c178bdd304186c0a2faa80f59261766b0cb9b0760b78eb1f31f166a6f091ab62e6898"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9362d1264c87f4fd59154372454f3974cb0401499307bfe3672aaf1c84c6b5643ec460f3bb33adb38a0b939502b6e7259f92f13a6469935cb372eb38500268af6f1b0e931380661372836164f4a50b3ffb46f1fe83bc177b7c1bf309591800c178bdd304186c0a2faa80f59261766b0cb9b0760b78eb1f31f166a6f091ab62e6898"]}}, diff --git a/txscript/data/taproot-ref/fb3a40b01dd182dc32fd94d86be6aeec9cfda7dc b/txscript/data/taproot-ref/fb3a40b01dd182dc32fd94d86be6aeec9cfda7dc new file mode 100644 index 0000000000..b43f08c3d8 --- /dev/null +++ b/txscript/data/taproot-ref/fb3a40b01dd182dc32fd94d86be6aeec9cfda7dc @@ -0,0 +1 @@ +{"tx": "1addd65a01dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c6d01000000c90a7298021f0149000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88aca6000000", "prevouts": ["4bb74b0000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "147d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ab0e9d9a4858a0e69605fe9c5a42d739fbe26fa79650e7074f462b02645f7ea7d9d0ef68974064b15682d7a9aede6e3fda6769a3db9d22f26322e1baaf4532e568dbaf979cca58396dcf271ee6fc736edd00965a3b0ecce9c87347ff88ab08a"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ab120007c9d6e5438fb32187fc2295f6e0f6d7a9b61cc04930744a089d58d965ad1099cc9bb3a5e2066786e30d0fff4359b3ce527e140b44a0b5c89c6b4383919a07a456edaef7c148906e899606040bd539df7c8cc4ad6955d406f95fd3100efb63111b06c7a0ce3f44d9f6906db8fc60057b72694cfd58ed25db88d188e5fc"]}}, diff --git a/txscript/data/taproot-ref/fb3feed4650211ed4fd84c29e022288219979e4a b/txscript/data/taproot-ref/fb3feed4650211ed4fd84c29e022288219979e4a new file mode 100644 index 0000000000..c6808f089b --- /dev/null +++ b/txscript/data/taproot-ref/fb3feed4650211ed4fd84c29e022288219979e4a @@ -0,0 +1 @@ +{"tx": "020000000160f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b401000000391043c902e2fa0d00000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478776010000", "prevouts": ["1591100000000000225120703a27ee37b547411791bd0e189100b9b1aab12509c8c95d384d172c3abbca5e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["bd4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f8a7004a68fdc05e100340c712f74a3d62667ca0b5d0eafc5e716949571fe18725432b67bf7a212872373c5ea5ac6512ad650fe3d5c26e1d584bcbdba0083b9a9e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93617cd6ee4f8b94dcd19f57a756bcb8a90fe2911c96cfd4cc653cd06b0f9d9556a5bc79ec207f4553f17b4d8afbf0e47b02e8cf3ab2b0172732171fcb0f92ff87125432b67bf7a212872373c5ea5ac6512ad650fe3d5c26e1d584bcbdba0083b9a9e9ba325ae7de51b47d98058ae5f9889bb6f52223c96865cd06dfd05531cc8a0"]}}, diff --git a/txscript/data/taproot-ref/fb47b82833fbb82a6a9844bcfa75012bfc49c9cf b/txscript/data/taproot-ref/fb47b82833fbb82a6a9844bcfa75012bfc49c9cf new file mode 100644 index 0000000000..5b49a991e0 --- /dev/null +++ b/txscript/data/taproot-ref/fb47b82833fbb82a6a9844bcfa75012bfc49c9cf @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bc9010000008d41693360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fe01000000b3acba1101460a090000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc89e64f5d", "prevouts": ["b00c260000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "90ae0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_7d", "final": true, "success": {"scriptSig": "", "witness": ["905259ed3a6600c70020cdb0b7411726f739bbd391413e8854b27206a8eeee859c2ceb63b692a5be63c475329c63dfd927d8be177fe715e97de4324edb0b240381"]}, "failure": {"scriptSig": "", "witness": ["625e61820c26157f79553e1b70a3a0f7e031893951c5b1a7f610ec9931a50b7d876d9e6986e773543d16a700b5fccbfb11ffa771e1e20157444aafecfe014b427d"]}}, diff --git a/txscript/data/taproot-ref/fb56305966435f548db004e141dd614dcb71150d b/txscript/data/taproot-ref/fb56305966435f548db004e141dd614dcb71150d new file mode 100644 index 0000000000..8deaff9e2c --- /dev/null +++ b/txscript/data/taproot-ref/fb56305966435f548db004e141dd614dcb71150d @@ -0,0 +1 @@ +{"tx": "020000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701602000000869bf9f460f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701402000000ab8972f801e82b1100000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac09010000", "prevouts": ["a0941100000000002251205fb82515a803bc66e22805d16c9967a9f99675502991462318dd4d89658b7382", "2266120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_4", "final": true, "success": {"scriptSig": "", "witness": ["c6d85fabb6cfea1892b3bc9dbed3194c971f18589af0585b597a745f07d3f63a1052b7ccb4b08be1505ead737f1870985337cd9f60c5f16d62a0c583a7dfa1ca", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["cc3dd89d7aa5a798699cd36c6630645657e8266ca54dda89aa335d7930a33605acfb27d771d8ecac702a66250281e9105b3968196010e0abb52dbf97879081c204", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fb6bbbb8192f592ebde7d1bb37924cade63c96c8 b/txscript/data/taproot-ref/fb6bbbb8192f592ebde7d1bb37924cade63c96c8 new file mode 100644 index 0000000000..f0299de841 --- /dev/null +++ b/txscript/data/taproot-ref/fb6bbbb8192f592ebde7d1bb37924cade63c96c8 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3500000000f75e818ddceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bdf01000000a0889ad4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b87010000002757f8a404a146990000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4875dfe903c", "prevouts": ["79b65900000000001976a914bb1edec93acb47abb0cd0078cfdb77063cd446c888ac", "221d220000000000225120086c5a8f8e6906e62f6d85a81f1ec942fa4d0768e046e2c41c1e8b8749778d7d", "80fb1e0000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063de68", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d7b27a3c30fa3f74fcb2fb63df4fd439cfb75b063c79b31cc96700ee0514110802b5f712fb146ffe69ff220cec8aeafe04d8a9d43d299b22043a34551aa1e56e09208a3d5cb0b20fec302022af702ea090b934668d0752a16a75cba2aae8c677"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936cdde2ff9e08044486741f25be80bacc73799296fd9f200381e6c31b1185faea4591d3592ddb0f56a18929886f1890713028f922113494349427ddaa1ea39184e02b5f712fb146ffe69ff220cec8aeafe04d8a9d43d299b22043a34551aa1e56e09208a3d5cb0b20fec302022af702ea090b934668d0752a16a75cba2aae8c677"]}}, diff --git a/txscript/data/taproot-ref/fb803c7f3034af611f6dd19c6cd55245f319dd86 b/txscript/data/taproot-ref/fb803c7f3034af611f6dd19c6cd55245f319dd86 new file mode 100644 index 0000000000..1847bc9e28 --- /dev/null +++ b/txscript/data/taproot-ref/fb803c7f3034af611f6dd19c6cd55245f319dd86 @@ -0,0 +1 @@ +{"tx": "9ca1b5ad038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c46400000000a64e37f060f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e001000000fa4a59c660f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912703701000000d0973dde03647656000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688acd90b845f", "prevouts": ["ae4139000000000021511f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "4d750e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "7465110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_10", "final": true, "success": {"scriptSig": "", "witness": ["3c098e408d58f71373567968cbca1b560e822ca3b24fcd98666b0c4d6a47f9e466c8a6d753121ed9497a6eda066ab59673423d343ae08f31966e5c6a5b84b8bc81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["34b2e9db76efd5bbce32a47f6a93610de3874fda52b060e6a7cfbedeaa76c85a7062626222eca22018b62b1ecaef7f9d85064b9c18dcf00a19a1fe7ebee5faaf10", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fb84f0eaf5bbab71df0de66b8e502f2e52604fac b/txscript/data/taproot-ref/fb84f0eaf5bbab71df0de66b8e502f2e52604fac new file mode 100644 index 0000000000..a1209a3d0f --- /dev/null +++ b/txscript/data/taproot-ref/fb84f0eaf5bbab71df0de66b8e502f2e52604fac @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cca01000000beed76a9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cfa01000000006e98b98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4b701000000b215db96035f51d900000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7f08c9e1f", "prevouts": ["f6c5510000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "2aaa4900000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "ab2940000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable", "success": {"scriptSig": "", "witness": ["c74c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93670b862a9e953c5158d35cb69a591b350b4931a459f6811c437cb72d14d86572024cf807c4b041deab506320299ff116921971164ef72b2742896e58a89a98f91cdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}, "failure": {"scriptSig": "", "witness": ["614c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d082aede7f6feac32430a03a6fb4ca18c03b66145006034584e3a19904465ea1e66424cf807c4b041deab506320299ff116921971164ef72b2742896e58a89a98f91cdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}}, diff --git a/txscript/data/taproot-ref/fb964d7fe5e195fa98766d8c4058c8258646e95a b/txscript/data/taproot-ref/fb964d7fe5e195fa98766d8c4058c8258646e95a new file mode 100644 index 0000000000..d9dce65251 --- /dev/null +++ b/txscript/data/taproot-ref/fb964d7fe5e195fa98766d8c4058c8258646e95a @@ -0,0 +1 @@ +{"tx": "f608de5102dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1c01000000234b88da8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4e200000000afc6ffcb04a1565700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7bcb4062d", "prevouts": ["be01210000000000225120d632d9c3807cee2f3b07918ef684335c8e7823a1a0eb476eaf46267e076b018f", "4c44380000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "147d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936f78d8e6fb6c853fdc672d488ae32f4e909f7a3793ceb1fbacf52fce604b8b07d7d9d0ef68974064b15682d7a9aede6e3fda6769a3db9d22f26322e1baaf4532e568dbaf979cca58396dcf271ee6fc736edd00965a3b0ecce9c87347ff88ab08a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936da584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e7a317a052512b66d9c0a593db192e28ab9b1379143982fc432aa6f278435f8ccfb63111b06c7a0ce3f44d9f6906db8fc60057b72694cfd58ed25db88d188e5fc"]}}, diff --git a/txscript/data/taproot-ref/fb9e6ec52fad74ca4a775818f110ba219adaadbb b/txscript/data/taproot-ref/fb9e6ec52fad74ca4a775818f110ba219adaadbb new file mode 100644 index 0000000000..bbb615ad7b --- /dev/null +++ b/txscript/data/taproot-ref/fb9e6ec52fad74ca4a775818f110ba219adaadbb @@ -0,0 +1 @@ +{"tx": "9a528aa802bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf76010000007a3820ef8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4a80000000038f526ba02ce2c980000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acd87ed42c", "prevouts": ["60e1680000000000232102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac", "5ef9310000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_79", "final": true, "success": {"scriptSig": "", "witness": ["47f6ec7e814a5acc4a2d30b2298879c35acbc0daa00962c7a9c41f87d614c802b3b0a55a51bea2d093bbe22be426d8f21eb878200b526824e44af1955ddfa4eb81"]}, "failure": {"scriptSig": "", "witness": ["001c07a63e03f4d4bf7b73fbf2f480044f0b54c11e24ad0c6ea4b00241ec5f85e91dfce4780a8d7f8e0cbbea0ee27f34426f89c017cb5a8faa515f91ed0890c779"]}}, diff --git a/txscript/data/taproot-ref/fba8bb171f6333a2f8f8099ed7061ca7507012bc b/txscript/data/taproot-ref/fba8bb171f6333a2f8f8099ed7061ca7507012bc new file mode 100644 index 0000000000..cf9eaa108a --- /dev/null +++ b/txscript/data/taproot-ref/fba8bb171f6333a2f8f8099ed7061ca7507012bc @@ -0,0 +1 @@ +{"tx": "2b467a1e03dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3d01000000139453f3dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b81000000002569e0acdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4c01000000b62770a0012fe80c0000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc33010000", "prevouts": ["8f265c000000000022512035205488698c55c3e7035f1484d2f513744eb9d8b6fb6f0df083f7669ef0bfda", "7d6a1f0000000000225120cae2bb06a958c067dd1208634cfec6f24075b217020915696a25607be87b4540", "d6c05300000000002251205e4247b509e7d8a6d6f324d155ac6817eba62ef7261a7c3067f7c871658806c5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364ad853b43a90b24cf1df821e2e638dfd9c14c3d8474f8af4a5aef1878bd54085"]}, "failure": {"scriptSig": "", "witness": ["6a53616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/fbae541afc8fd2842b660a15ba61db2dbd26dca5 b/txscript/data/taproot-ref/fbae541afc8fd2842b660a15ba61db2dbd26dca5 new file mode 100644 index 0000000000..69f10786a3 --- /dev/null +++ b/txscript/data/taproot-ref/fbae541afc8fd2842b660a15ba61db2dbd26dca5 @@ -0,0 +1 @@ +{"tx": "0200000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4901000000213507c5dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c5300000000f92f4bb6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf150100000091782beb0145d3670000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fcc4eafb2e", "prevouts": ["6e315000000000002251203d78fd2bb4b62ef0589e0f6d3292b9d4b4f73a96f936b719c8327103cb45d1ec", "96f25c0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "60086b0000000000225120f31e3a320eea15b969f8b18ed69a6dfb33cc054a2307ba2bd3877db1ef9fdc39"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_73", "final": true, "success": {"scriptSig": "", "witness": ["a0d981aa2f946ce124668f185fc5f8e7cc4b0dea59feceee0365603b1577a0e23ada5bb27e48debfa96504a531e975513e3eef10ea7ab753c817b2932d405b4d82"]}, "failure": {"scriptSig": "", "witness": ["968228efe5e280d21ca3d7c033c93d5da349f23d3120ccfc0c93c44228f536b2fd71ab923813d356412d93a515bc7fb8e0386238f9a898314cae0d7a5798925372"]}}, diff --git a/txscript/data/taproot-ref/fbd1df6484bc96485135c2b29c3b125355c62848 b/txscript/data/taproot-ref/fbd1df6484bc96485135c2b29c3b125355c62848 new file mode 100644 index 0000000000..c6f45a1130 --- /dev/null +++ b/txscript/data/taproot-ref/fbd1df6484bc96485135c2b29c3b125355c62848 @@ -0,0 +1 @@ +{"tx": "0100000003dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1a020000005f503664bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf3a01000000af22f6838bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45a01000000ec72071c0131d9410000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc7bf29061", "prevouts": ["8127570000000000225120679c204dddfbbd298129e4670a621c532ae6353c600a37c86662e442bb91ded5", "5719770000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4e193e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/hashtype0to1_keypath", "final": true, "success": {"scriptSig": "", "witness": ["0465f5807019e300f51eac08f5272990f1ca970cb0e1deaadf44250141d44de331a90434d535b49c339120ca7893dd5a3f879937e563104eace1e31ef490db52"]}, "failure": {"scriptSig": "", "witness": ["0465f5807019e300f51eac08f5272990f1ca970cb0e1deaadf44250141d44de331a90434d535b49c339120ca7893dd5a3f879937e563104eace1e31ef490db5201"]}}, diff --git a/txscript/data/taproot-ref/fbeb89304a55a7ab8a338b807ad02b8dd2ab9c28 b/txscript/data/taproot-ref/fbeb89304a55a7ab8a338b807ad02b8dd2ab9c28 new file mode 100644 index 0000000000..83f0a9803a --- /dev/null +++ b/txscript/data/taproot-ref/fbeb89304a55a7ab8a338b807ad02b8dd2ab9c28 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127072000000003a6d923adff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c2301000000ec825d2b0388966900000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc7a76d4227", "prevouts": ["e98711000000000022512009ca3b7467d9dea91d906b1b0e7a427b6496d4aab6be2799f71c47ade6ce7f57", "583e5a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d8", "final": true, "success": {"scriptSig": "", "witness": ["524beb9f61e89a1f59df769d68a1ccacfd26cab78398d52646483d8fdfa733a0b4571b776590cb1b8f43aacffd20be68473133a0c1a32d813e29b0889572d32e81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["c7785dcbb83d524a33cb932d8431188cc233d9c90416f996d3e19bfb5b8d9b45453906088269089c39c113b26a0464256b97f53da86a144d2d9647f908ffac72d8", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fc1908d2145aa6f1cf830f6aeb9bf24470454805 b/txscript/data/taproot-ref/fc1908d2145aa6f1cf830f6aeb9bf24470454805 new file mode 100644 index 0000000000..8e47ef4975 --- /dev/null +++ b/txscript/data/taproot-ref/fc1908d2145aa6f1cf830f6aeb9bf24470454805 @@ -0,0 +1 @@ +{"tx": "a16810340360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270320100000001d67dfb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912701a00000000ce8a8e9e8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40601000000d70e389401384e260000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79622030000", "prevouts": ["40320f00000000002251208fa17604bea1a2fa3728b697c38b10509b65e0ce8e421d974d98824035b3dbb8", "2701120000000000225d202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "41d2360000000000225120469b0d5af3b652b8630a1c8a749c6ca969e84c67dc08b1fae26a9cf0bb3b6587"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "", "witness": ["25ef58eb18e36d98d017aca2a5e61c3f3a073e2ce9fd7caaa909ebd761ca6f8f521440ee2c3e95cc0a6698708ea3a447ab3649da8ecf6d13d543db378c15f690", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/fc6ad6441d0d3ba1260efa94e68b4af0576bf63f b/txscript/data/taproot-ref/fc6ad6441d0d3ba1260efa94e68b4af0576bf63f new file mode 100644 index 0000000000..ba293501f5 --- /dev/null +++ b/txscript/data/taproot-ref/fc6ad6441d0d3ba1260efa94e68b4af0576bf63f @@ -0,0 +1 @@ +{"tx": "4431cfc6028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c40701000000be5f58b98bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bf000000000206778f03fb9a7700000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f871feb932f", "prevouts": ["fede3f000000000022512012b975b505febce3d90537f513ce86dc778c6aa76aa4c7c143b3b99f1662d22e", "5c57390000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_2", "final": true, "success": {"scriptSig": "", "witness": ["c98207f6e7e605a3700ebff3688f2b4769adf8b0d5ca1032dde96a951df98a8e0d478d3835bf3b542e9237d546024a898fc4cb8780c754bf7f55cc5d2d7ac8bb02"]}, "failure": {"scriptSig": "", "witness": ["f8f17060fc893a7aaa17959d793c734978e744c5b5293f0e109255a8bbf4939b85c1d02dc1af34a0497e2a4553d37d05c3750e735523ab90a49b3a0ce0aa252702"]}}, diff --git a/txscript/data/taproot-ref/fc6e7fbd1048ad4d4f9eadb18d79a7ddaddee244 b/txscript/data/taproot-ref/fc6e7fbd1048ad4d4f9eadb18d79a7ddaddee244 new file mode 100644 index 0000000000..d2222415cd --- /dev/null +++ b/txscript/data/taproot-ref/fc6e7fbd1048ad4d4f9eadb18d79a7ddaddee244 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfd6000000006b1f0cfb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270fe000000009f41f51201fadd4e00000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac43020000", "prevouts": ["70e7780000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "88ef0e0000000000225120eb71a13199b51ac9b0ace6bcee525494dad4a8780bc850f36224b177f5d9dc5a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "5e7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08259bd71c400ab2f54869740392a5675e37e70879689c9d1a6bcb33863a193d8cf0c8cbc16505271ed8ce1a03d67d2c4a35529bcf4a25ace24696315022c27c9cf"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93601f485ab8dab36fc4237cf32204629d23ab8b7a9b8c57b9fb58bb07cc298c65859bd71c400ab2f54869740392a5675e37e70879689c9d1a6bcb33863a193d8cf0c8cbc16505271ed8ce1a03d67d2c4a35529bcf4a25ace24696315022c27c9cf"]}}, diff --git a/txscript/data/taproot-ref/fc72b1ff88ff0bb9a8e7a27d860b1e727bc825b0 b/txscript/data/taproot-ref/fc72b1ff88ff0bb9a8e7a27d860b1e727bc825b0 new file mode 100644 index 0000000000..9239401d5b --- /dev/null +++ b/txscript/data/taproot-ref/fc72b1ff88ff0bb9a8e7a27d860b1e727bc825b0 @@ -0,0 +1 @@ +{"tx": "0100000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c13000000007dd53f9260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b5010000000b3d637101b5bf3d000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6d1010000", "prevouts": ["ba5b49000000000022512085bbaf732586004b91d5e29af7be3965e4cbd4294c3dd4aad30280f6dcbe0145", "a090120000000000225120473417efae73fd5e93fcc212950b9b19ee652cc977c17e6edd4b3172c741ca78"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "217d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa9505bf473a3597e826ed191951239b12c364d282b43e59333c5c9d2effa4a8821a54b706cb1ffe8cdd8302265f43043d8c7f0cfca18957505a6e0d7d2690f95c84bdfafc9427bbc75e549436fc0749ee4f6acf063a9661c81b3024fc653ae79a"]}, "failure": {"scriptSig": "", "witness": ["6a", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936612f59f79f08a8dcd41fba0e90fc36d30e7d0e0028aa30a51161912fee70ec039505bf473a3597e826ed191951239b12c364d282b43e59333c5c9d2effa4a8821a54b706cb1ffe8cdd8302265f43043d8c7f0cfca18957505a6e0d7d2690f95c84bdfafc9427bbc75e549436fc0749ee4f6acf063a9661c81b3024fc653ae79a"]}}, diff --git a/txscript/data/taproot-ref/fc833899bb452572fe6f3e84efd6737cca4eb786 b/txscript/data/taproot-ref/fc833899bb452572fe6f3e84efd6737cca4eb786 new file mode 100644 index 0000000000..be3abe6fd3 --- /dev/null +++ b/txscript/data/taproot-ref/fc833899bb452572fe6f3e84efd6737cca4eb786 @@ -0,0 +1 @@ +{"tx": "1aeda83f03bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf9900000000a9e71ddadff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c1601000000c1e722ec8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4bb01000000a0e9adf902bb0efd000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88acdf000000", "prevouts": ["6cae7f0000000000225120ac005ce4773d3aee0620b129ba36f72cd2ee645537f63f3488482809f788413d", "02fc470000000000225120cdee1b260cf2a57b2a4f41467ca1d526e01a2fabdcb63f8ae4942bbd063c3ae7", "ca9e3700000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b81e5f8184480151a33ea2ef90622481c324d5b0da017369a2ae7e89125987bb4ecdbff3eecb3f5fa90fd3ed1bb4a8c0c36fc15f71a4102bd4f372c5f95e5c7d5941b26b476c022edf868776977d31e53e85212ba204fe552062798c457a392dc1a6e987e7baaf45cc4656191a1a193c7abe05aba02d24b24cf2747f96e1d33b"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363cfa0f25e80db82d1df7d31067deb7f7ffba540dee916ca5c0f9f286a347a1270ec0b51bfc4485592d1a8fc32a0105404420a8dd2ba09b048dd208f3df546c127e5a3ad1358e4c8217aebfca59af3ae3bc6dd2d33fcb7e66f52e86370eeb61bbcdb1729650f5e7315a74782ce14a5f1169946bc7ff3758bb098f0ad0a25b2b7f"]}}, diff --git a/txscript/data/taproot-ref/fc9c2ac36745e20f981008bf5f85f146b9c9dbb1 b/txscript/data/taproot-ref/fc9c2ac36745e20f981008bf5f85f146b9c9dbb1 new file mode 100644 index 0000000000..76b23bca87 --- /dev/null +++ b/txscript/data/taproot-ref/fc9c2ac36745e20f981008bf5f85f146b9c9dbb1 @@ -0,0 +1 @@ +{"tx": "0100000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b440100000090a859b3bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf91010000003771e53e030b83950000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87d8030000", "prevouts": ["0817280000000000225120325bb8bd692aa21257fa568f0567c628c6e8ab7924eed74b5d76df030defb001", "86656f0000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/bare", "success": {"scriptSig": "", "witness": ["62", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d8b553b0a6fa8101b21fae89df5dd09b18d30a3ef06025a3f9cb6b07028f8b60ad339194ab8214f981edb9ff4477fbcef7a6ea6cf7b4eddf16a8a4e2aa6ff5b2a28c39ce330a19a0d6c22ddc640bc3609271e6194de475fecd1ad84a88d361935a9a81b6bc4d13af192f1d19d1915de95ad8d42e49add8bb4e9a9400ca460b05"]}, "failure": {"scriptSig": "", "witness": ["61", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93608efc3524da3cce9064a39cd829c421044a59a48c5000df9ec45b645663b2d3865d6469ded31e8361d538153e3993104db0c9d480dfc3dcfe9dd6d2fbda5f8f6abc42ab3738335b78a2a7135de763706b017ef32cb75bc24ca1210f74f6e5b7b3fd119d5a804161d41189f11d8f3e11243ae602674c5e73f1686492aa1f485fe"]}}, diff --git a/txscript/data/taproot-ref/fcc3f72c08a026d3c0f4cc50227793a26fc3efeb b/txscript/data/taproot-ref/fcc3f72c08a026d3c0f4cc50227793a26fc3efeb new file mode 100644 index 0000000000..84d87d5d4a --- /dev/null +++ b/txscript/data/taproot-ref/fcc3f72c08a026d3c0f4cc50227793a26fc3efeb @@ -0,0 +1 @@ +{"tx": "acbf9f810260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270cc000000000eb572d4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b920100000084c9bc8602e0ab2e000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388acb0633037", "prevouts": ["2dff0e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "f34f210000000000225120eec26bd33d4c7b88cfedb1ec4d1edaf2070bd273924a77ba1006105de9dd5258"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_48", "final": true, "success": {"scriptSig": "", "witness": ["154f4a7affa81c867d749fd1b19a4a69ce000dee1ca40bf935972f02c3a587f28d6b11986c09b73e0714491915a3b082f28a89c3b5450194ccde0964e2936e0881"]}, "failure": {"scriptSig": "", "witness": ["d5d3799e272d242fb0a696ce31aab9ada4d1feda51a108c8e0dcee97b7917d1dfe24f37583dadebde02c01505e0189d8f4f46bd1d9ca2a252209746171faf17d48"]}}, diff --git a/txscript/data/taproot-ref/fcd03d953e3452f116e4035d2029de953e62334d b/txscript/data/taproot-ref/fcd03d953e3452f116e4035d2029de953e62334d new file mode 100644 index 0000000000..429aee637d --- /dev/null +++ b/txscript/data/taproot-ref/fcd03d953e3452f116e4035d2029de953e62334d @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a900000000bab6199360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912702000000000ac5597b703f23b1c000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48752d1432e", "prevouts": ["fa6510000000000022512066e06b662ecb6981e0f3917eb0b6248b84ec5cd53a7a521c7d24c865c53918b4", "febe0e0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "907d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936a54b43c188a8877a2a3a86a1fc429fffab130c683e7f6d5ea2708892288e828358fa50c6d7a3057541347f50382af7d86a4158110d747d8a87c6e51bda235e7807d6dd053b835b300872a79bbaa392d17bbe19548a92a63c5948e9fc7e63dbc8"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361773499d4b7734b9d17b8063bb26023932d8136237a2a4376fdf258dbd3041e4ccc0d92396a6e5b4e10ed573234ead163b054b024f08ace7ccde70990779f457ba4f11ff80ca9181e3d85997fa959accb8f97af45a52bfd0df916797673441f5"]}}, diff --git a/txscript/data/taproot-ref/fcd91aa7ad2c0011f8f2516f5687f9e91aa76b71 b/txscript/data/taproot-ref/fcd91aa7ad2c0011f8f2516f5687f9e91aa76b71 new file mode 100644 index 0000000000..81241ed856 --- /dev/null +++ b/txscript/data/taproot-ref/fcd91aa7ad2c0011f8f2516f5687f9e91aa76b71 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b550000000085442cebdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8301000000993071c6049f014a0000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f87c8000000", "prevouts": ["9ec324000000000017a914f5a65ca4534ef3ca5833434c0dd44a3e128f499587", "f67527000000000022512068810aef011b819679577c24f008f8785d9903d2c43eb118d09024962a03144e"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/scriptpath", "success": {"scriptSig": "2259202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["715c4c8f8e8b3ed1787fc9df753dd65839bbb5842ed20e1c32139ea87d240b5694bd3b9318237b306aacb4ddd25830c6ea683312f30219e2522c1694eb888217", "207d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ac", "c0871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e2046c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa"]}}, diff --git a/txscript/data/taproot-ref/fcda2ec36cb7652d368098a0c2ac64665164601f b/txscript/data/taproot-ref/fcda2ec36cb7652d368098a0c2ac64665164601f new file mode 100644 index 0000000000..df8b0f4333 --- /dev/null +++ b/txscript/data/taproot-ref/fcda2ec36cb7652d368098a0c2ac64665164601f @@ -0,0 +1 @@ +{"tx": "4817304a02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8b0100000004f694a9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7b01000000216ddf84044aeae6000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6fe1c4f2f", "prevouts": ["c95b7a0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "d8d96e0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_2c", "final": true, "success": {"scriptSig": "", "witness": ["e860e3cdae548610f7dad2b1a4136b1635e0bb85a0f9315b93d16ad48e40c7f773241ce115d1663ab5c4746630764df389f967dce8621e24a38532460c94abe981", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["ebfce58453b0036ebb933e6816f5aac009ddf80d14115ebf6664464fc5e31f36a92fcc6c7ab2c8b3f6891f5f4deea77b318bd6deaf59ba2d0172089d4de347fb2c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fd03276208dbd6219a958f47d888d22fa303e89e b/txscript/data/taproot-ref/fd03276208dbd6219a958f47d888d22fa303e89e new file mode 100644 index 0000000000..6e7dc0fd0d --- /dev/null +++ b/txscript/data/taproot-ref/fd03276208dbd6219a958f47d888d22fa303e89e @@ -0,0 +1 @@ +{"tx": "28a354820260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270ff00000000be3b46b4dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1a020000000e78c7d001ff502400000000001600149d38710eb90e420b159c7a9263994c88e6810bc79c000000", "prevouts": ["1ea6100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9e2f22000000000022512061049d3bf8d8628387c6dd15fd6aa94597135d2428743d9f5049ba6d570084f3"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_3c", "final": true, "success": {"scriptSig": "", "witness": ["42740861859d08047fed4c9e32fdcfe049ac0cbd2db6bb0a9647b99dee8028c3ac59a5800d0796927a475ffd468cc0311b86e0034313f57941102410c85720bf01", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["711608cd1a51181983c5fe9bbe7491c3a0cb0daea2b35bfde8ac0b6a5f52f7d377ac459d82ecfa93a62be7244c55ac45b75bb94dc86c6f30dca7dd609bfe485f3c", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fd14286e8c496b3f62dea79de42d57a7b02b22fc b/txscript/data/taproot-ref/fd14286e8c496b3f62dea79de42d57a7b02b22fc new file mode 100644 index 0000000000..827d558b99 --- /dev/null +++ b/txscript/data/taproot-ref/fd14286e8c496b3f62dea79de42d57a7b02b22fc @@ -0,0 +1 @@ +{"tx": "e0ed141303dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b93000000001fcf05f6dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b7a0100000091bd69b9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfc8000000009a4857d5047746c200000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa93083937487bf000000", "prevouts": ["bec22800000000002251207e677ee6e0a9f5a7b76d32fc490de736680fedcc1b5666802b0cdd6035d1f989", "73802000000000002251208e3aff7c578d941c4c0ef50f0a58a5ae91118406955ace5ac0e7cb917f87f0e8", "8c967a00000000002251208560e60ff9f5f50e17abe0faa94b8704db3bcecc7cb6f74a11a752b4bbc814f5"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/bare", "success": {"scriptSig": "", "witness": ["61", "967d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e889b1afbd82754ccbdb229e33ad6472305abc54dae2fa9ac3a68b58b93ca8c8390ad15d5ff3e747c4643a2e7779e2cae74c1db700bc0de7d47935e7ffa6ea968f"]}, "failure": {"scriptSig": "", "witness": ["61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936393d3666f153f5444bbde9f12a33ca18bffeb96af6c3b3812e1be180585532ecbf86d7708a8015fd8c392d5dfda539be3c55b3d42b83ba5bec57bef080407e280ad15d5ff3e747c4643a2e7779e2cae74c1db700bc0de7d47935e7ffa6ea968f"]}}, diff --git a/txscript/data/taproot-ref/fd1a057fd69f2113eeeafc133d9d51c7cded9125 b/txscript/data/taproot-ref/fd1a057fd69f2113eeeafc133d9d51c7cded9125 new file mode 100644 index 0000000000..53b3298c25 --- /dev/null +++ b/txscript/data/taproot-ref/fd1a057fd69f2113eeeafc133d9d51c7cded9125 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270c700000000f132150a60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270af000000009c88c48704e0582000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc5802000000000000160014deb4696df95e4685eae8f9ff2e77fc7edabbe2fc580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374876daaae5e", "prevouts": ["e225100000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "19be1100000000002251204e92f58f07bd1c983dce937cb6ff2655b495f5bbe642bc389d13f2d55749a90b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "a87d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936783a3bc7d79cabcbcc0867fb5538daddb7c00a7193bf5b1437e698397aa24b0d5480c0b3df47fa838c1e54894d9f77b7e2e8bb4e3c514b095e8a55995fa5d8569e26d26d9f798657ab1642d8194f1f5dc9158412142f65824f82701f20125ac7"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936438d090c2a648f11c3897ecefe41fdc11118ed9b1c4529cbb2ee4038fc727b19159738ff2c4f90cd16c07bb852218b8a19eccf086ed61d505eed94e2770983c2cd165f299bdaaa06ccf8947d9b12e815a5b39fc50068532880492a3446c423d89e26d26d9f798657ab1642d8194f1f5dc9158412142f65824f82701f20125ac7"]}}, diff --git a/txscript/data/taproot-ref/fd1c6cdb67bcc23e0920c0b2724591695d7e88b1 b/txscript/data/taproot-ref/fd1c6cdb67bcc23e0920c0b2724591695d7e88b1 new file mode 100644 index 0000000000..5e9f806f35 --- /dev/null +++ b/txscript/data/taproot-ref/fd1c6cdb67bcc23e0920c0b2724591695d7e88b1 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c491000000007392a7f260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912707500000000579abf8d03798c4b000000000017a914719f78084af863e000acd618ba76df979722368987580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e4876b000000", "prevouts": ["f7dc3e000000000021581f2540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b", "ee930f000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pkh-sighashflip", "final": true, "success": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["30450221008e336def7ebe3e190b6ca7af316f7560a09ac6567f419ac68fe49abf806ff95a02200e9c0495f41c9ba589242c52e30d41f796752cd58aa61bab0ebca7adf24d811b03", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}, "failure": {"scriptSig": "160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "witness": ["304402205d3080ceb411b4ef46aef3fd3e2ab493b5e005b33ed0423fad0589e5334a6a840220070143503584eab6d74eba4d0bef2b4823d0f6797e946f5b60f11217ff587b4a03", "02972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404"]}}, diff --git a/txscript/data/taproot-ref/fd1d4fb758440d51c0db63f8a401ad4f7dd1ba6d b/txscript/data/taproot-ref/fd1d4fb758440d51c0db63f8a401ad4f7dd1ba6d new file mode 100644 index 0000000000..81db8a6cbf --- /dev/null +++ b/txscript/data/taproot-ref/fd1d4fb758440d51c0db63f8a401ad4f7dd1ba6d @@ -0,0 +1 @@ +{"tx": "a5db689303dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8e00000000ee83d8e88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49d010000003a8b0fcadceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b6e01000000d40773fa021b25830000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb79658020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ace0020000", "prevouts": ["24a5260000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8", "e8e73c0000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88", "4909220000000000225120acc511cd55079365da76d18a33af3ae7411f3879a9caec918e9264c8959f5dac"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "alwaysvalid/notsuccessx", "success": {"scriptSig": "", "witness": ["6a50", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9367ac1a66615b2aaa170e13c634fe4adc8e21579cd2ad4b0e05677ccecae701899"]}, "failure": {"scriptSig": "", "witness": ["6a30616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936fa0cedfc8c4c5a04ac3787009b16f69cf342d2af09b40867d2c29ecd108727e2"]}}, diff --git a/txscript/data/taproot-ref/fd1f6bb68c1a0317e7fb3e9c65ce2b765717f38f b/txscript/data/taproot-ref/fd1f6bb68c1a0317e7fb3e9c65ce2b765717f38f new file mode 100644 index 0000000000..b18f31334e --- /dev/null +++ b/txscript/data/taproot-ref/fd1f6bb68c1a0317e7fb3e9c65ce2b765717f38f @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709a01000000adafb548bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf8201000000cf248c1a03e0558a000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac05010000", "prevouts": ["bd9b110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "4ea27b000000000022512039db30de33ea15b8f8fd0a316b7175d66e0ba7a162f794600ae9aaebda3948b7"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_90", "final": true, "success": {"scriptSig": "", "witness": ["31fb061ded3aa06aeead8cef95af3f5ab33eaf6af75fb1c2c8068eeafc6a374453f6fa96ecabb51ed47a2e44780cb75ddc6744d295ebe3e8574c8a415afee6a883"]}, "failure": {"scriptSig": "", "witness": ["84654a7a4cf578f1918dc1d48048039bd30ae9ec1adc37bd1fe9378e377c2c6211b7ae7b0c96c997a4b5a60d39c1b8890eb1ede443ec626fe4b3ea6ce85a442590"]}}, diff --git a/txscript/data/taproot-ref/fd275d920066468018b3ec78708e01bbf4634f89 b/txscript/data/taproot-ref/fd275d920066468018b3ec78708e01bbf4634f89 new file mode 100644 index 0000000000..40dc82ceb7 --- /dev/null +++ b/txscript/data/taproot-ref/fd275d920066468018b3ec78708e01bbf4634f89 @@ -0,0 +1 @@ +{"tx": "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf6b000000005c19b047dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4300000000fa054f9360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d9127072010000002e2b715c0281e4d10000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000016001428425a8aab0a57cd9398c2c78c3d097fe1a397a6940e7f4d", "prevouts": ["ab4c790000000000225120a57586f77f9f96f121f5205525f023e067d8d4ffab15aca94e058cc3473eae5a", "48984900000000002251202361d91ff13391fd25020ba7e60c60643b5255f5adbfbdf7f0353592847fec4a", "4c73110000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001inputs", "success": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "f7", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936dbc4082c88742c64e777227e559cc787fa79f9ad49b3844bdd2aa78bdd53ae153e2d335f383706a312226510c4ca5ed297e59b2981bccad977d4984b4ab81a7bbe0beccf8b53a38f7a20d51eb008bdc60f78fac094fdd23935202ece673d8622376e34112ab1bc736956b41978cebed690ad16294afa2ba0e9d8b5fa7e9f6f2f"]}, "failure": {"scriptSig": "", "witness": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "61", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9366d95f1ea0a1fd23653d05da4ad0eda243001c7a04351d1c2a22e8a2afb82411fc18d13f23505bf80401329c8d1a0bac5ffbe219ba0d96925c38e985a7086f175ac8db205c7d3bb0390b2e22910f5d1cbad00807eee3325f4c4e7f4412ed3064a1c25c837ec0a1f852472f3f26e6d49055bb98717b7b68c46cae1e5f9804f9145"]}}, diff --git a/txscript/data/taproot-ref/fd30d1fabe3c70d63ebf6eb08fcc889f2062dd96 b/txscript/data/taproot-ref/fd30d1fabe3c70d63ebf6eb08fcc889f2062dd96 new file mode 100644 index 0000000000..f80858e599 --- /dev/null +++ b/txscript/data/taproot-ref/fd30d1fabe3c70d63ebf6eb08fcc889f2062dd96 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c43c00000000668a0bdfdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cc300000000031806d602a2158800000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac11cba52a", "prevouts": ["b5fc3f0000000000225120e32017a134852f161f6cfbdc82f7fe66db755e2ed5bb55497d5cae1e53c5c006", "d02e4a000000000022512019bef84f9e846c1fdc0e0b6c8a2e8cd0934b4588f64b20133ad72602ae6fe529"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/unexecif", "success": {"scriptSig": "", "witness": ["0063d368", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93699c890f1cb77bd1e07e1591340b8ea7c636a6b93a8dd025cb092d0253a3c2a4496525fdd0eb5f3c5c39bf5b04d78b37703e3d3b538b36e17fa0ddbdeb236a5daa4337ae81428241101d56ff91a1822e405405037c9afab8da6ba5df5d84918ed"]}, "failure": {"scriptSig": "", "witness": ["00636168", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364c6a87e468bc2f4636d01a06f33fa62a820a91bb3fa58159484fa6a6e3a3321f8f435ba6abdf70be4dec7b2a0789d26eb9361219ce4916c9f3e2c2146b2213509dff863108f68b54d204f4b43b2fddebfd69630b8c1a20ba8be96c4e7e2557a5003e045cb689fe4fc6de332c618eb0cdce02c2dd8aae7c6dd6f70bdbaede2814"]}}, diff --git a/txscript/data/taproot-ref/fd4b486776c7fc4e964a57db37f46b6fb893446f b/txscript/data/taproot-ref/fd4b486776c7fc4e964a57db37f46b6fb893446f new file mode 100644 index 0000000000..06d8951a60 --- /dev/null +++ b/txscript/data/taproot-ref/fd4b486776c7fc4e964a57db37f46b6fb893446f @@ -0,0 +1 @@ +{"tx": "62db20530260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270b30000000059a62bffdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c8d0100000072c0dded011a3b5000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac4c2e7253", "prevouts": ["f1091000000000002251209807c6fa5fbdf8b77e6e8a9ff33ccee8e5ba6f6b181d807daf9039f015b3a190", "c7f15f00000000002251208acf7a61bb45458dd86d3c9f45a9fce258820fbbf84c7164c88d41367f6e76b9"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d2", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93634d7d9bf32378ef7c35504ad126f5933fce7000c51c0cb771db02273ac9ce3ce99aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb45d26c3c7079b274e62542512e39807ee92511541c708e3b51bc61366b8def992ef429df53f77997a088ac7849be23d2367c05dc96029904e93835fc046c3c5b9"]}, "failure": {"scriptSig": "", "witness": ["000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9361ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d90045d300bab14a59e521ba24782c2f2145d4a7429c0cdd6ce75f9b04f76a9e5b4d519d9c6e51540aa9a09fa82ae61189b3f4badb16bfd2877ff7bde730e5687247de05f27aeb1527a9572d42a0ad2bcfbe2bc67b36cc3101a74fc3488cf03d6f1bd0"]}}, diff --git a/txscript/data/taproot-ref/fde4e348195fef4158d57bce09b8132261e53404 b/txscript/data/taproot-ref/fde4e348195fef4158d57bce09b8132261e53404 new file mode 100644 index 0000000000..1b29467033 --- /dev/null +++ b/txscript/data/taproot-ref/fde4e348195fef4158d57bce09b8132261e53404 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfcf00000000b38236dfdceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8a010000005a24c55301f9287000000000001600149d38710eb90e420b159c7a9263994c88e6810bc78fb4e75d", "prevouts": ["e7bd7500000000002251208ae894af2a9600386c37dee4cfaf898fd39bd624f9812efea0f89b144f5e3b3c", "1d6a230000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_d1", "final": true, "success": {"scriptSig": "", "witness": ["b812a9eccfdee570ea0932c50b747c18f9efb7d24bc86523f8013c60d6e2c9330faa5b6502762fdf009c7b2f67d233b7de4b49377639d2f0208da94d3dd7300e81", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5db5f597ecf51d78218b825845253793121754d6c4298eea9bd02cc8cfce48a7717b3cc912d223589d9e45812bb8c60d0ba478149802626104f5a169f7406d7ad1", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fe3a254545ba65877f7f12c1957e6983a9540725 b/txscript/data/taproot-ref/fe3a254545ba65877f7f12c1957e6983a9540725 new file mode 100644 index 0000000000..b0c2e7bb13 --- /dev/null +++ b/txscript/data/taproot-ref/fe3a254545ba65877f7f12c1957e6983a9540725 @@ -0,0 +1 @@ +{"tx": "02000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4fa00000000486720d6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb200000000fa9d4aef03b15daa000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac24ac6649", "prevouts": ["0aaf3d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "804b6e0000000000225120f46c27e4be4b28b9a4817d4bb21e6d76e9bff45d28c4e23d061d7fc56326d512"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_76", "final": true, "success": {"scriptSig": "", "witness": ["b34b78c0f4f93e8146e965541e2435fa7f87a26ca202cb0ca98dc2f2fd9f1171ec37a43174416403df31a5b17997fc8638d297220e5fe3f386bf3aab32b89ccf03", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["85b963bc8b6543e0415f70d92974aacf0a9e26dc91540e7f3f31d85ed46a53a54fc1041d4a1f34e94701747d3bbc467ad670f92261992740ef3312fdcadf6d4c76", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fe4991f96a4078203ed82f3dc9d57b0f5c8d7c31 b/txscript/data/taproot-ref/fe4991f96a4078203ed82f3dc9d57b0f5c8d7c31 new file mode 100644 index 0000000000..e8b68fd18c --- /dev/null +++ b/txscript/data/taproot-ref/fe4991f96a4078203ed82f3dc9d57b0f5c8d7c31 @@ -0,0 +1 @@ +{"tx": "01000000028bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4c5000000006242d66edff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565cd601000000ddd1212b04e58899000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8758020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a914c629d61df58baceae110d15eb5b55e144268615388ac58020000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88acb2000000", "prevouts": ["26f83d0000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "36595e000000000017a914856f7c6a5a6a1ac0e553b769a4c35bcb9fb6f50287"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_87", "final": true, "success": {"scriptSig": "", "witness": ["0d1ffaeeda23e31038e5a484758074dca0089f8b9381b15cc25283479e2840fad7f770b4f5decef5df5f22a16e045da1a2faeed7c103e10eed6daa193cd4b95703", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["5f524706c16a3a58297c7c107996d87e2cd25bc1f7d07eb761eb950dfbbd67007af96d52608ba90f24a6d035f47578079744da1e6c4829739e7015d3fcad5f0187", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/fe5a94896e814e80a5d4f0d17825ea303d136807 b/txscript/data/taproot-ref/fe5a94896e814e80a5d4f0d17825ea303d136807 new file mode 100644 index 0000000000..b4abf12d3b --- /dev/null +++ b/txscript/data/taproot-ref/fe5a94896e814e80a5d4f0d17825ea303d136807 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270a4010000007ffa04c8dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b250100000082473360dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b0b00000000b573fe37040fb04f00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e790c8515b", "prevouts": ["d2ef120000000000225120ea663cdaedbff64137eb6e6df4db9508c973045e9b4d61d7f67dd2d12ed5b278", "8cf01f00000000002251209ae0f9a30bb32466818047220431a71836305abdffa7870d853c3e44af672d80", "df861e0000000000225120dff7f04a1648925acb0c2995e1633664c97ab25bb4c317b29fea48d8a2c27a17"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "ae7d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363f7be6f8848b5bddf332c4d7bd83077f73701e2479f70e02b5730e841234d08231f1765c4043c65869fc44409698468cef1d88a3aab3981df946f88d25a1c2d5c67b1d078674a4d97323398e107b13ccefe9299bb9116e21f935c64f37bba24f619c7e3fc3d0f43b284295c7c76b7ff66dfc7bbdbc495ce3e8e20608c97360e5"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936252d0fde16f88d3d71135f2afb7fd13a00ae20e347d34ef21ddf868171a0f5b8b92d0c8bb72b9935581697fe84ef0173536b04207acfd5de8a2df8889a2a895490189ee9b6b94816743a58868693b6f0ba58cb07e4c6d5ed2ce590077e887d5b"]}}, diff --git a/txscript/data/taproot-ref/fe754dfb4207b538736ac33f4d6d3a8b39ed7eb8 b/txscript/data/taproot-ref/fe754dfb4207b538736ac33f4d6d3a8b39ed7eb8 new file mode 100644 index 0000000000..a4296b9918 --- /dev/null +++ b/txscript/data/taproot-ref/fe754dfb4207b538736ac33f4d6d3a8b39ed7eb8 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d912709800000000daf956298bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45e00000000b3893e6902e64243000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa930839374875802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e740010000", "prevouts": ["4038110000000000225120b77a4d3965d24a3fad7e13b4b8f89b1c642ad197d3735fb97eb5af1aa4db0ae8", "f0bd340000000000225120fa8a9eda5cf5b8cdf600ff6d95d78a3e3ba730f4e5093bedd0b749c08f958e88"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "017d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f93646c7eccffefd2d573ec014130e508f0c9963ccebd7830409f7b1b1301725e9fa54ce7cc5f439b597f56fd9de2c1657ae9d64eb6e71f5398fcdfdc60a0bc251e633479914332f6e309839a0f3b0f115e1019ec5f6a2a9189a2d7ee13d1c4f5f4ae05873438be84f92d1402d5d55e9fb409fe52800aaeb5db180b239b834bc1ca2"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e4f09646afdeac9857da657a09b8018dcf81d67c29f0281da7afdb83ec8526e8e4e5ee47dc19cce5f5bcfbe17d15c6a925997647a0a2c3c32d22380bb5e59a56e05873438be84f92d1402d5d55e9fb409fe52800aaeb5db180b239b834bc1ca2"]}}, diff --git a/txscript/data/taproot-ref/fe8a403b551fce23551c1a364c5d7a9bdf4082b4 b/txscript/data/taproot-ref/fe8a403b551fce23551c1a364c5d7a9bdf4082b4 new file mode 100644 index 0000000000..15810fd4e3 --- /dev/null +++ b/txscript/data/taproot-ref/fe8a403b551fce23551c1a364c5d7a9bdf4082b4 @@ -0,0 +1 @@ +{"tx": "010000000260f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d60100000045a55a8fdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c760000000073f099380186396800000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac2586664f", "prevouts": ["f629120000000000225120b4ca0199f2c1b4fe89ded0fec9677a159da93a40f23df8c7f92820e897b82544", "06e05a0000000000225120d05281144396364d925ea6b3a1aef63a9288a440d2428aed5ab1312e751c56f8"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "opsuccess/undecodable_bypass", "success": {"scriptSig": "", "witness": ["834c", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bf852205919db101e7100c264881cf502d3d2e764ba6b83faae2c86d526b113f2b9d1447cbfb5d72d5da72ac5ad193469eaa6b44c038aa23e2a9d2dd480586adaf3b292550aa3dd1beea84cf7009fb6c6992543e64edf52f25a9194aed3bcd7c"]}, "failure": {"scriptSig": "", "witness": ["4c5283", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936ff698adfda0327f188e2ee35f7aecc0f90c9138a350d450648d968c2b5dd7ef91ef6944ca9eae19b43c4423072484bbc3f643e0e770f53f8e7474c81f5d900458e881bd6493e98dc576a1c76b7dda488b188d283086ec2219562e3f5b97e3fb63f980255362d30444bd4a09dfd60422f4fe5b70b7cde78729ca8cd52cb50aace"]}}, diff --git a/txscript/data/taproot-ref/fead4cb9efe769ed34fc79a6f7f7c301fa44b950 b/txscript/data/taproot-ref/fead4cb9efe769ed34fc79a6f7f7c301fa44b950 new file mode 100644 index 0000000000..225043a2df --- /dev/null +++ b/txscript/data/taproot-ref/fead4cb9efe769ed34fc79a6f7f7c301fa44b950 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b8801000000c8c8d8b88bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4ad010000004c9346de03c1f76000000000001976a91401f109af244d8c7f2563284ac2d2ba7d6323a75e88ac580200000000000017a914719f78084af863e000acd618ba76df97972236898758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc731010000", "prevouts": ["4b5d270000000000225120795828cbdd13db8bfd99175dd96610ae8d272a9240d5c9e537830514248aeee7", "c51a3c000000000017a9146f2d26adc5ad58653becfc45ce03a0b1167b1b7e87"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "applic/keypath", "success": {"scriptSig": "225f202540f27e90740933c99d4f17ab2dfc6c82951cfb0b8674c83ad179cfbc247b89", "witness": ["73d8d5d8ed532f0f53c3e0f5a4fd64ce0dd9b9af52c8ee51179644ed0386a7e56acd541b49bef09466b789571a82c78c95f3dd46bd51b44f513d4a8f7cf182af"]}}, diff --git a/txscript/data/taproot-ref/fec0428a7d5b4dd2f894abbef22a4fd55b125e79 b/txscript/data/taproot-ref/fec0428a7d5b4dd2f894abbef22a4fd55b125e79 new file mode 100644 index 0000000000..85f4a0eff4 --- /dev/null +++ b/txscript/data/taproot-ref/fec0428a7d5b4dd2f894abbef22a4fd55b125e79 @@ -0,0 +1 @@ +{"tx": "0100000002bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf7c000000006ccee4d5bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf550100000006f9c30c016ca90a00000000001976a914f9cfef42654b8e1307276f4274b9e35435f17e8d88ac1b9c1b47", "prevouts": ["66cc700000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "9fee7e0000000000225120b5fac7f9d1efa21092b4bbfea1ca41fe5694dd20d67936ab2b478b1ec4aee588"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_unk_hashtype_a7", "final": true, "success": {"scriptSig": "", "witness": ["0dee6e0544a085c8a15febbd719b6e253db589d68487212f4ce2c93d742bc535830cca84f845d1506fbedebf02f9768a6ef5d1e4dbad8f878701309f199eff1681"]}, "failure": {"scriptSig": "", "witness": ["7e9a4442076322941c3512c0d70ff676e7f84fce1c13ccbc11dabed4705c8d2d1bb4ad1d0cb0b44b13dce392c77e728d7baefa05c2d60847d9743f4ecd129df2a7"]}}, diff --git a/txscript/data/taproot-ref/fed7b4e8b0ffa8ba7ee920409e365993f8f23423 b/txscript/data/taproot-ref/fed7b4e8b0ffa8ba7ee920409e365993f8f23423 new file mode 100644 index 0000000000..d64ac2a65a --- /dev/null +++ b/txscript/data/taproot-ref/fed7b4e8b0ffa8ba7ee920409e365993f8f23423 @@ -0,0 +1 @@ +{"tx": "0100000003dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bf101000000673c277b8bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c4370100000035cb6dc58bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c45d0000000023dea660014dee30000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df47879c010000", "prevouts": ["f5ff280000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "0bce3600000000002200204d9fa7499ad409ec9ec48eb45241c17306a16ea85aa9131c6c693d5ac440e116", "67f0410000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY", "comment": "legacy/pk-wrongkey", "final": true, "success": {"scriptSig": "", "witness": ["304402200eed20c923d2ec7fd6fd0412758ca0fd74be8a2b42e716a369b732d4b1812a3f0220749423388300602ad44c525c88e6a2f8b3364efc9ada5bd241f50da4f878f57901", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}, "failure": {"scriptSig": "", "witness": ["3045022100e120bcd0c42112150a93961039df1f5282548ffb791bebbf2063fc0ce3880b790220577f0761154e3f35545b6eaabd84153a6ce7e0b666805531e1647844d822c8b101", "2102972df56c6f8e97bfcc0f442f93cfc00fc91f37d7ee3708f904ad9af3abc29404ac"]}}, diff --git a/txscript/data/taproot-ref/ff02cab52406b52d736534063539b815a83e9ec9 b/txscript/data/taproot-ref/ff02cab52406b52d736534063539b815a83e9ec9 new file mode 100644 index 0000000000..5980156986 --- /dev/null +++ b/txscript/data/taproot-ref/ff02cab52406b52d736534063539b815a83e9ec9 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270130100000004782a72dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1e010000004a150c568bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48d01000000dfbafbcc0153c12000000000001600149d38710eb90e420b159c7a9263994c88e6810bc776010000", "prevouts": ["053e120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1850210000000000225120bf7c0652824d65f4682a3056a4ee7d3427d5bd09fcf8c412b9591353033138ae", "3e9d3b00000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327"], "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/1001push", "success": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "447d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936b929eb7e8ad4e073db170590e53035ad212210bb9f64e5a212e35f16cad1d1a0da290f4428e3e675f4a51c1ca36b5af7f0162ea7962d369252b53cfa5e2a91134f357c04ffd5ab4b0848fd0bc62a9916d6f879ccec8b8201b6b82c9f83bee932"]}, "failure": {"scriptSig": "", "witness": ["0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936473b52d2f86e55a148378d231c070b8b3f2682e3af8489ef4b5e89a9ad3d421046ff9fefe634101043d8ca11d5a4647687c0df4bd98e414158186cc8065d9a91f7b6e2c095a2b9a1b3d0ba71ae2a36fa91117ca9fadc253f03c0f98f0de350244f357c04ffd5ab4b0848fd0bc62a9916d6f879ccec8b8201b6b82c9f83bee932"]}}, diff --git a/txscript/data/taproot-ref/ff0c9a3fa047cac34488cf6902e39ceb0b31a1f2 b/txscript/data/taproot-ref/ff0c9a3fa047cac34488cf6902e39ceb0b31a1f2 new file mode 100644 index 0000000000..69baf697e1 --- /dev/null +++ b/txscript/data/taproot-ref/ff0c9a3fa047cac34488cf6902e39ceb0b31a1f2 @@ -0,0 +1 @@ +{"tx": "2cc56a15038bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c49a00000000ec9501e6dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c7b0000000043261ee960f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270e100000000823f43cc013ca96b000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487b5010000", "prevouts": ["c1243f0000000000225120036cd49b0a5a8928de04f8e04bd3da02711fbb4d9053aeba12a20cf11cba05b5", "bb6f4700000000002251200106699296107db4ccd4290b8d3cc7be3754a2d9979743f64d14b4c3e7741f8d", "cd9e10000000000022512014168556a36ebb5fc7069983062b713ccfb69f91c25af78f116f616f92a54679"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "tapscript/sigopsratio_5", "success": {"scriptSig": "", "witness": ["9a5c10aefbfe506270d18f51e3be8b44d93730a589604d3e1927f1a51d003c71429665b47fdf8bf1de06d0a417b9db74d9d56685b35ad6e57f11deee7d5177e9", "96e22827d237bafcee6a73a75c6a0e801dd9792f0b1f30f99cebac9452a0c866b29bbe5a422a3a3a108e60151df9d07fa61bb2fb824875f19faf5e0e", "75005a29dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b3250ba5a8829dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32506e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364f8548ac9430c378b802a76bf4e30330b029db06562270d6dfa552c82f7ad828e4624988dbf1a8e05379085fe4f1d6daf4c052cf4e31fa12e77ebff59a6d1354000000000000000000000000000000000000000000000000000000000000000081eb60ecb145257b9a19aaa8c28dcc18c09e8a27d8f71ac28dee91a3117f6396ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc40e504b0102296de467c96da7e93b9174579d48da6397918b442a10bcba6549ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d04f1eb9ef398401490690d5d07e06cff4af8360fe27af9a63bc5f407a83ca8a5241e263d8c98cebbf362e2f0177af6696af7ee410e6642fbe91e0e216320689b6c2f432398bccd3202a6fddea1631b0c72129de51fa4a0b5b8cdbbaefc8b37ea04bf92e580dc3c05cd14080d8c1d5af39f5dba79470b5c86f67841386278ef0000000000000000000000000000000000000000000000000000000000000000057ad767594cbafa2ef386a7d859e365266f1c6028473d451552269018c152754d35c1deee4ec7deaeaa831940ac201271b6ff776017bb50a44bcbd42a0c164b511cfe55e11095d26e1ccbc0bcc0f69c673f0a76d41cefac9551a860b225dc38ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff31f8c6befe27f7d412413acf38cbeb58b24a7961476c2b373b6ae26a6f114a1f49d18c9b7c39eaed314f293ff206f53e67992e1dba3e6c10d0cfb9c6f5c55874ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11bdf10d236531c096bed1430c3f73887f20c7a94898c8c08832c27fe2e7ae420000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe53f0c91c28ad9fb56769cb7f6852de91427d2cecd613e78323eb1647c287d4fe45daf562ed92d3f70d93d776c50cd7104170022f9714c22c0eb2a60e62e93d11d00987f263adad68f084a3fa19f55f577c12c00242e3df2afd487d4a9be407a77057648493ff83a64b83763581afc73f88546e4c8c65a1a183ac99fbe86254399cc5d7346b555c2da780d05477850ba4a1c8cf3e0174889ab50bd917dddbaa48b1465b1783e37520bae6833f5c1eb425b398b379bea622d9299e67dfa74fe46652a9c4d9d09dbe4efb9c134356818b8f370bd01045ad70aa4166a29cd56160c75f1ed36289f63eeeff2b9bc390022ca828a1e325f7db8790bae25846d92f384f331588ae8361ce48197c4fa3d84e917b7b094596a42c9fba9ff70a2df18d998ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5698d2f1e8d99f280adcafd85c48e656006e47b8f0eb554b25fad29f38026015c658a33b444cfb8855d6c8c6b7ee7831149e19a91fc7e7c36563558e288347a6dc14210dbdee7b1ee2afe12374313fc9e90f7d54bc72ca8c9728bd18f27a992f13cc42831ead5b3c2231edb7dbd5b41fa74b5183081618dcfbe43f899ca3a223501baa00eeec5d37da5a1c6973c6685eb86690a2196e95b6372c40f81163bc5534963657b2fad15ce0772d0f30ba336255a26afc2cdf1eb26984cb6e47e0c32f25e33a7a8681fee80b544addbffe10ec28fa79b05f0dbeee61dce9c221bd4db6"]}, "failure": {"scriptSig": "", "witness": ["9a5c10aefbfe506270d18f51e3be8b44d93730a589604d3e1927f1a51d003c71429665b47fdf8bf1de06d0a417b9db74d9d56685b35ad6e57f11deee7d5177e9", "b2a8004ce53e9ffdda644b661b18374f7b878a6d1c36733009cdd3ce5a69b2d783d72e6902bc31b3c3dccf2bf3aa8665128354ad1b8de05fbe8f23", "75005a29dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b3250ba5a8829dd0239d45c6ebc84fce483cb108c20da66a09760f11ee5126885a304919e89dccaa3bc1d22786b32506e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba0111886e607cba011188ac", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9364f8548ac9430c378b802a76bf4e30330b029db06562270d6dfa552c82f7ad828e4624988dbf1a8e05379085fe4f1d6daf4c052cf4e31fa12e77ebff59a6d1354000000000000000000000000000000000000000000000000000000000000000081eb60ecb145257b9a19aaa8c28dcc18c09e8a27d8f71ac28dee91a3117f6396ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc40e504b0102296de467c96da7e93b9174579d48da6397918b442a10bcba6549ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7d04f1eb9ef398401490690d5d07e06cff4af8360fe27af9a63bc5f407a83ca8a5241e263d8c98cebbf362e2f0177af6696af7ee410e6642fbe91e0e216320689b6c2f432398bccd3202a6fddea1631b0c72129de51fa4a0b5b8cdbbaefc8b37ea04bf92e580dc3c05cd14080d8c1d5af39f5dba79470b5c86f67841386278ef0000000000000000000000000000000000000000000000000000000000000000057ad767594cbafa2ef386a7d859e365266f1c6028473d451552269018c152754d35c1deee4ec7deaeaa831940ac201271b6ff776017bb50a44bcbd42a0c164b511cfe55e11095d26e1ccbc0bcc0f69c673f0a76d41cefac9551a860b225dc38ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff31f8c6befe27f7d412413acf38cbeb58b24a7961476c2b373b6ae26a6f114a1f49d18c9b7c39eaed314f293ff206f53e67992e1dba3e6c10d0cfb9c6f5c55874ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11bdf10d236531c096bed1430c3f73887f20c7a94898c8c08832c27fe2e7ae420000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe53f0c91c28ad9fb56769cb7f6852de91427d2cecd613e78323eb1647c287d4fe45daf562ed92d3f70d93d776c50cd7104170022f9714c22c0eb2a60e62e93d11d00987f263adad68f084a3fa19f55f577c12c00242e3df2afd487d4a9be407a77057648493ff83a64b83763581afc73f88546e4c8c65a1a183ac99fbe86254399cc5d7346b555c2da780d05477850ba4a1c8cf3e0174889ab50bd917dddbaa48b1465b1783e37520bae6833f5c1eb425b398b379bea622d9299e67dfa74fe46652a9c4d9d09dbe4efb9c134356818b8f370bd01045ad70aa4166a29cd56160c75f1ed36289f63eeeff2b9bc390022ca828a1e325f7db8790bae25846d92f384f331588ae8361ce48197c4fa3d84e917b7b094596a42c9fba9ff70a2df18d998ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5698d2f1e8d99f280adcafd85c48e656006e47b8f0eb554b25fad29f38026015c658a33b444cfb8855d6c8c6b7ee7831149e19a91fc7e7c36563558e288347a6dc14210dbdee7b1ee2afe12374313fc9e90f7d54bc72ca8c9728bd18f27a992f13cc42831ead5b3c2231edb7dbd5b41fa74b5183081618dcfbe43f899ca3a223501baa00eeec5d37da5a1c6973c6685eb86690a2196e95b6372c40f81163bc5534963657b2fad15ce0772d0f30ba336255a26afc2cdf1eb26984cb6e47e0c32f25e33a7a8681fee80b544addbffe10ec28fa79b05f0dbeee61dce9c221bd4db6"]}}, diff --git a/txscript/data/taproot-ref/ff0ecc250f060fadb2dfbc788f027f6c46ef6c40 b/txscript/data/taproot-ref/ff0ecc250f060fadb2dfbc788f027f6c46ef6c40 new file mode 100644 index 0000000000..ae2c711bd8 --- /dev/null +++ b/txscript/data/taproot-ref/ff0ecc250f060fadb2dfbc788f027f6c46ef6c40 @@ -0,0 +1 @@ +{"tx": "c1eba3db02bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf4f00000000e94ce9b9bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acf40000000000bf6ebc6028687db00000000001976a91497b8b6d3828f12a792c9de6df78e0b1514b7967688ac5802000000000000160014f19f1969da9e474444a7b8fc50ae71f46e1eb796bb000000", "prevouts": ["0e8d74000000000022512056830ed1745d06f5c865a011820a618c1aa3c70bd00028049bf30f33c5c664cc", "cf0d690000000000225120469ff3412c89f5805e53fbb9303c790a98dd32093d40e3b7dfe22bb05f85f37f"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/keypath_hashtype_82", "success": {"scriptSig": "", "witness": ["b2b1f387b9825b810412ce3419971c4ee5c35106a558c6faba67d6b82e228086ccb09a4cb73dd2e73ed6f9ced1e170e78aa8e29f47da6669cc424c6b8ced7e9d82", "50174d347af8ea2207120d07506725832b840dddf73f1573701a23084184426fbe18911e046a0533fd933b5b49f4886da199bf25550f53a1472cebe9e24e66298054be5d5301c3834510ed84198e654f3c8ca3a7e36114f8818c395e16c529419271a7c5ba205a3158e12afa1ac3446d681c5e51d94c308df2c33fc9c171bffb836429a9841d6d2710c26b80c6e227548562af49e67bc02b486214149e86e30321157d1289b382577c22fca76c52df489eacd2f933a225f2e03e47add671d2921b90c3b3f0dcf6badb0bc8ad21384a13ec63c85b6481357fddb63b2efda345"]}, "failure": {"scriptSig": "", "witness": ["bf64ecef48e9d5122211f7261b14a8fafed77649f7108a8c7f59a971722f50d0a7a21de1757c1deea12605a4de9fe961abc481200bcfdd36d1529f5f4a563cc882", "500cf653630e8d24a23667e26672a6cd044ac9ea916488d508863d2daef6177d00f03161f89a8d001d917167eec87c6ae8022f1afb02785ee38d82c6c95f22761059b6f68605"]}}, diff --git a/txscript/data/taproot-ref/ff269c4192d92ee1330ca6cb368ffaf3dec65d44 b/txscript/data/taproot-ref/ff269c4192d92ee1330ca6cb368ffaf3dec65d44 new file mode 100644 index 0000000000..6caa2b6eec --- /dev/null +++ b/txscript/data/taproot-ref/ff269c4192d92ee1330ca6cb368ffaf3dec65d44 @@ -0,0 +1 @@ +{"tx": "010000000360f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270130100000004782a72dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b1e010000004a150c568bd9b9012d1e9d0bc9c34df9d487a1d5663f1b37dbd4a857a2bddcbe25f0d0c48d01000000dfbafbcc0153c12000000000001600149d38710eb90e420b159c7a9263994c88e6810bc776010000", "prevouts": ["053e120000000000225120860597d3b29a47949c68e53703a7c358236fede9036ee1439f49b54ea72cb70b", "1850210000000000225120bf7c0652824d65f4682a3056a4ee7d3427d5bd09fcf8c412b9591353033138ae", "3e9d3b00000000002251200fa149a1be921b54e78f55c020f385d43ef2042352395c285ad3c0f835b7f327"], "index": 0, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "sighash/scriptpath_unk_hashtype_54", "final": true, "success": {"scriptSig": "", "witness": ["f46c55fd5a01d67b7b26b7208fbb53d9c3587c277f716f62b7030122f999b17401be49a0d19888c8fd110aedd4c0fbe5a162ec1b6b7da66f151ddb36d637776602", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}, "failure": {"scriptSig": "", "witness": ["55b094ae001890588580a9c3fa4c6d045ef5398d50b35f60e470f9b2749624677b457298f433856679c5aa0bd0184271256ad3b8135b037048375850e8807d7b54", "0020871bf677dcc1eeea213f60505c1c9f1695f8b7d2ee8bbacb3ba246e9f1e57e20ba5187ab", "c17d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9363ca46e263a260b65760ba16fc7221d8949b643b52b6000a40fc66cf5b479cf31754943580dc1bd6713260228477cc107c802e16d4edc27befd908a8bf6eb3629"]}}, diff --git a/txscript/data/taproot-ref/ffba9a51f35e6cfeb9726e3eb3551989a55a2ab6 b/txscript/data/taproot-ref/ffba9a51f35e6cfeb9726e3eb3551989a55a2ab6 new file mode 100644 index 0000000000..5f15505f4e --- /dev/null +++ b/txscript/data/taproot-ref/ffba9a51f35e6cfeb9726e3eb3551989a55a2ab6 @@ -0,0 +1 @@ +{"tx": "0200000002dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b910000000007b8c7cb60f8b8616e71e7ed05613145ce7cda782ac9861e64f9ce24e333ca1e91d91270d2010000006a6039d303ae933100000000001976a9145dabd582fbdb106f3f7460c03ce83bc27d461d0f88ac5802000000000000160014619b982e9f6832d2edb1a1ee4e7656a8d72c65e7580200000000000017a9148f07d0f98cfe0d6aff29ca20bcda3fa9308393748784110e48", "prevouts": ["759f24000000000022512040610cb8e3decd88d4c59cdbdfeb76bec671852dd837e2ccede76befc391039a", "1a8a0f000000000022512003f4235cf93ae95226c79f4ac7e76f24996218ade11a16913609a6e39f31ad9a"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "247d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936eebc95ded88fb8050094e8dfa958c3be0894eaff0fafae678206b26918d8d7ac2f1db23017f271ba09e9de40cbf6bd4b292cb969b1168724d03b4425efd5cf153506420e788c3ffd3d8d88ddb9154e82106737a8dd2b5d0940daf68f275cd0d7"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936d34b659cf09d8349f11874dab6e59e9cab85ba068159b5d193f4bbbdcc88f75d5e7553debb7d46df339c30c507d2c3e528ab4da6adeae898375a123e3f0f1c20ee08d5698d988fd8465309aa10a601f39a775c4be89f69280a5de9411e45585f440784f6f41cc1ae323b623cf5dcb000da45020704fab66b6b5f2ff7d67a93a3"]}}, diff --git a/txscript/data/taproot-ref/ffbfc4371313a95615a944ca1fb473bf2569d7aa b/txscript/data/taproot-ref/ffbfc4371313a95615a944ca1fb473bf2569d7aa new file mode 100644 index 0000000000..0524a69dc8 --- /dev/null +++ b/txscript/data/taproot-ref/ffbfc4371313a95615a944ca1fb473bf2569d7aa @@ -0,0 +1 @@ +{"tx": "cc2e403e02dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4bb10100000091ff68d6bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acfb901000000bd8eaca701a18f31000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df478795736527", "prevouts": ["94a2240000000000160014bb1edec93acb47abb0cd0078cfdb77063cd446c8", "ca7d660000000000225120618acdfff396d05c4f42f34a54f40947ed380d009b19743557014bb4ecd5d247"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/return", "success": {"scriptSig": "", "witness": ["6a", "847d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936e7e370719e3d30fbc2ea4d983b233608f68df319a16a215567d8496b6d2fdfa7cc3b36ccc81fe4912a925ea2b1eb99a41bced4468215b0c94e7bf4feca6759c79f31796df107fae040796e44aea27c7a7d41418cdc7206378fd34089f9daf951"]}, "failure": {"scriptSig": "", "witness": ["6a", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f9360641e660d1e5392fb79d64838c2b84faf04b7f5f283c9d8bf83e39e177b64372ff78d21b135ee37de5fb006beb46b85f4aedf8bacb6598da1f15171cdf92c209c568c76d6b344a062dd798f6575db1f1731d6a7ca3f2682e7e1b801cd94d3826"]}}, diff --git a/txscript/data/taproot-ref/ffc6076c34629ad5d440389f97bac8efcd2db5b7 b/txscript/data/taproot-ref/ffc6076c34629ad5d440389f97bac8efcd2db5b7 new file mode 100644 index 0000000000..b5542e27ce --- /dev/null +++ b/txscript/data/taproot-ref/ffc6076c34629ad5d440389f97bac8efcd2db5b7 @@ -0,0 +1 @@ +{"tx": "0200000002dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c3a00000000e20d6af9dff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c56010000002af908f40301a1b1000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487580200000000000017a914472b5d2e0c04ba5495728dd81d0885af2587df4787580200000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e487363aad34", "prevouts": ["c6e55a000000000017a914c9840c38196e75dd475876fc1e51c080e92b574c87", "0950590000000000225120c3ede40be7fa2b5d36872db3a22bce0eb482f16144c003b683cf5791052fa029"], "index": 1, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT", "comment": "unkver/undecodable", "success": {"scriptSig": "", "witness": ["4c", "287d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936c89a90bd6ee635b9a469d0d01d0c15436cff095a2a8e7aa2387b3d6b61c337a118f8625f860d8689a2679aa71112fac717f40bee978e3269b215b9f9d8467661efcb4d33820b2e80b50b7a60cab20b6261c566fe48480267b41ad585cde9a4bb"]}, "failure": {"scriptSig": "", "witness": ["4c", "c07d732801de7e0c866f2462f29c14b63e555159b62ba93a5d5963d1c04795f936bf7d06d12d9f93c68b7270a0e92986b9529219a8b1f03a05e07750c355db869496153d9d0825641ad9dc2862c4b07cae929842b36229bdcb06007f7d47362644efcb4d33820b2e80b50b7a60cab20b6261c566fe48480267b41ad585cde9a4bb"]}}, diff --git a/txscript/reference_test.go b/txscript/reference_test.go index d1f516ee2d..59acdb8da7 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -10,7 +10,9 @@ import ( "encoding/json" "errors" "fmt" + "io/fs" "io/ioutil" + "path/filepath" "strconv" "strings" "testing" @@ -192,6 +194,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) { flags |= ScriptVerifyMinimalIf case "WITNESS_PUBKEYTYPE": flags |= ScriptVerifyWitnessPubKeyType + case "TAPROOT": + flags |= ScriptVerifyTaproot default: return flags, fmt.Errorf("invalid flag: %s", flag) } @@ -886,3 +890,189 @@ func TestCalcSignatureHash(t *testing.T) { } } } + +type inputWitness struct { + ScriptSig string `json:"scriptSig"` + Witness []string `json:"witness"` +} + +type taprootJsonTest struct { + Tx string `json:"tx"` + Prevouts []string `json:"prevouts"` + Index int `json:"index"` + Flags string `json:"flags"` + + Comment string `json:"comment"` + + Success *inputWitness `json:"success"` + + Failure *inputWitness `json:"failure"` +} + +func executeTaprootRefTest(t *testing.T, testCase taprootJsonTest) { + t.Helper() + + txHex, err := hex.DecodeString(testCase.Tx) + if err != nil { + t.Fatalf("unable to decode hex: %v", err) + } + tx, err := btcutil.NewTxFromBytes(txHex) + if err != nil { + t.Fatalf("unable to decode hex: %v", err) + } + + var prevOut wire.TxOut + + prevOutFetcher := NewMultiPrevOutFetcher(nil) + for i, prevOutString := range testCase.Prevouts { + prevOutBytes, err := hex.DecodeString(prevOutString) + if err != nil { + t.Fatalf("unable to decode hex: %v", err) + } + + var txOut wire.TxOut + err = wire.ReadTxOut( + bytes.NewReader(prevOutBytes), 0, 0, &txOut, + ) + if err != nil { + t.Fatalf("unable to read utxo: %v", err) + } + + prevOutFetcher.AddPrevOut( + tx.MsgTx().TxIn[i].PreviousOutPoint, &txOut, + ) + + if i == testCase.Index { + prevOut = txOut + } + } + + flags, err := parseScriptFlags(testCase.Flags) + if err != nil { + t.Fatalf("unable to parse flags: %v", err) + } + + makeVM := func() *Engine { + hashCache := NewTxSigHashes(tx.MsgTx(), prevOutFetcher) + + vm, err := NewEngine( + prevOut.PkScript, tx.MsgTx(), testCase.Index, + flags, nil, hashCache, prevOut.Value, prevOutFetcher, + ) + if err != nil { + t.Fatalf("unable to create vm: %v", err) + } + + return vm + } + + if testCase.Success != nil { + tx.MsgTx().TxIn[testCase.Index].SignatureScript, err = hex.DecodeString( + testCase.Success.ScriptSig, + ) + if err != nil { + t.Fatalf("unable to parse sig script: %v", err) + } + + var witness [][]byte + for _, witnessStr := range testCase.Success.Witness { + witElem, err := hex.DecodeString(witnessStr) + if err != nil { + t.Fatalf("unable to parse witness stack: %v", err) + } + + witness = append(witness, witElem) + } + + tx.MsgTx().TxIn[testCase.Index].Witness = witness + + vm := makeVM() + + err = vm.Execute() + if err != nil { + t.Fatalf("test (%v) failed to execute: "+ + "%v", testCase.Comment, err) + } + } + + if testCase.Failure != nil { + tx.MsgTx().TxIn[testCase.Index].SignatureScript, err = hex.DecodeString( + testCase.Failure.ScriptSig, + ) + if err != nil { + t.Fatalf("unable to parse sig script: %v", err) + } + + var witness [][]byte + for _, witnessStr := range testCase.Failure.Witness { + witElem, err := hex.DecodeString(witnessStr) + if err != nil { + t.Fatalf("unable to parse witness stack: %v", err) + } + + witness = append(witness, witElem) + } + + tx.MsgTx().TxIn[testCase.Index].Witness = witness + + vm := makeVM() + + err = vm.Execute() + if err == nil { + t.Fatalf("test (%v) succeeded, should fail: "+ + "%v", testCase.Comment, err) + } + } +} + +// TestTaprootReferenceTests test that we're able to properly validate (success +// and failure paths for each test) the set of functional generative tests +// created by the bitcoind project for taproot at: +// https://github.com/bitcoin/bitcoin/blob/master/test/functional/feature_taproot.py. +func TestTaprootReferenceTests(t *testing.T) { + t.Parallel() + + filePath := "data/taproot-ref" + + testFunc := func(path string, info fs.FileInfo, walkErr error) error { + if walkErr != nil { + return walkErr + } + + if info.IsDir() { + t.Logf("skipping dir: %v", info.Name()) + return nil + } + + testJson, err := ioutil.ReadFile(path) + if err != nil { + return fmt.Errorf("unable to read file: %v", err) + } + + // All the JSON files have a trailing comma and a new line + // character, so we'll remove that here before attempting to + // parse it. + testJson = bytes.TrimSuffix(testJson, []byte(",\n")) + + var testCase taprootJsonTest + if err := json.Unmarshal(testJson, &testCase); err != nil { + return fmt.Errorf("unable to decode json: %v", err) + } + + testName := fmt.Sprintf( + "%v:%v", testCase.Comment, filepath.Base(path), + ) + _ = t.Run(testName, func(t *testing.T) { + t.Parallel() + + executeTaprootRefTest(t, testCase) + }) + + return nil + } + + err := filepath.Walk(filePath, testFunc) + if err != nil { + t.Fatalf("unable to execute taproot test vectors: %v", err) + } +} diff --git a/wire/bench_test.go b/wire/bench_test.go index c183df56e5..5176c962e8 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -226,7 +226,7 @@ func BenchmarkReadTxOut(b *testing.B) { var txOut TxOut for i := 0; i < b.N; i++ { r.Seek(0, 0) - readTxOut(r, 0, 0, &txOut) + ReadTxOut(r, 0, 0, &txOut) scriptPool.Return(txOut.PkScript) } } diff --git a/wire/msgtx.go b/wire/msgtx.go index 6cd591e3be..917a142e6e 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -550,7 +550,7 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error // and needs to be returned to the pool on error. to := &txOuts[i] msg.TxOut[i] = to - err = readTxOut(r, pver, msg.Version, to) + err = ReadTxOut(r, pver, msg.Version, to) if err != nil { returnScriptBuffers() return err @@ -1005,9 +1005,9 @@ func writeTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { return binarySerializer.PutUint32(w, littleEndian, ti.Sequence) } -// readTxOut reads the next sequence of bytes from r as a transaction output +// ReadTxOut reads the next sequence of bytes from r as a transaction output // (TxOut). -func readTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { +func ReadTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { err := readElement(r, &to.Value) if err != nil { return err From ba9fb8ece10e8a3019724f43147579d9429d387c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 8 Mar 2022 18:13:55 -0800 Subject: [PATCH 0645/1056] chaincfg: add taproot BIP deployment parameters In this commit, we add the deployment parameters of taproot as specified in the deployment section of BIp 341: https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#deployment. Take note of the custom activation threshold, as well as the specified min activation heights for mainnet only. --- chaincfg/params.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++ rpcserver.go | 3 +++ 2 files changed, 58 insertions(+) diff --git a/chaincfg/params.go b/chaincfg/params.go index c8ddc85d69..8873390f86 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -140,6 +140,11 @@ const ( // includes the deployment of BIPS 141, 142, 144, 145, 147 and 173. DeploymentSegwit + // DeploymentTaproot defines the rule change deployment ID for the + // Taproot (+Schnorr) soft-fork package. The taproot package includes + // the deployment of BIPS 340, 341 and 342. + DeploymentTaproot + // NOTE: DefinedDeployments must always come last since it is used to // determine how many defined deployments there currently are. @@ -370,6 +375,17 @@ var MainNetParams = Params{ time.Unix(1510704000, 0), // November 15, 2017 UTC. ), }, + DeploymentTaproot: { + BitNumber: 2, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1619222400, 0), // April 24th, 2021 UTC. + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1628640000, 0), // August 11th, 2021 UTC. + ), + CustomActivationThreshold: 1815, // 90% + MinActivationHeight: 709_632, + }, }, // Mempool parameters @@ -469,6 +485,16 @@ var RegressionNetParams = Params{ time.Time{}, // Never expires. ), }, + DeploymentTaproot: { + BitNumber: 2, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires. + ), + CustomActivationThreshold: 1512, // 75% + }, }, // Mempool parameters @@ -586,6 +612,16 @@ var TestNet3Params = Params{ time.Unix(1493596800, 0), // May 1, 2017 UTC. ), }, + DeploymentTaproot: { + BitNumber: 2, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Unix(1619222400, 0), // April 24th, 2021 UTC. + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Unix(1628640000, 0), // August 11th, 2021 UTC + ), + CustomActivationThreshold: 1512, // 75% + }, }, // Mempool parameters @@ -689,6 +725,16 @@ var SimNetParams = Params{ time.Time{}, // Never expires. ), }, + DeploymentTaproot: { + BitNumber: 2, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires. + ), + CustomActivationThreshold: 1815, // 90% + }, }, // Mempool parameters @@ -807,6 +853,15 @@ func CustomSignetParams(challenge []byte, dnsSeeds []DNSSeed) Params { time.Time{}, // Never expires ), }, + DeploymentTaproot: { + BitNumber: 29, + DeploymentStarter: NewMedianTimeDeploymentStarter( + time.Time{}, // Always available for vote + ), + DeploymentEnder: NewMedianTimeDeploymentEnder( + time.Time{}, // Never expires + ), + }, }, // Mempool parameters diff --git a/rpcserver.go b/rpcserver.go index b8012b2b01..8aa3e19516 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1259,6 +1259,9 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str case chaincfg.DeploymentSegwit: forkName = "segwit" + case chaincfg.DeploymentTaproot: + forkName = "taproot" + default: return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInternal.Code, From 23cf18b0505fe123d8ea89de9b98cdc73aa447f2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 8 Mar 2022 18:24:45 -0800 Subject: [PATCH 0646/1056] blockchain: use taproot script flags for validation after activation --- blockchain/validate.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/blockchain/validate.go b/blockchain/validate.go index 575861e2d3..89971e7fd6 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -11,11 +11,11 @@ import ( "math/big" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -1218,6 +1218,18 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi scriptFlags |= txscript.ScriptStrictMultiSig } + // Before we execute the main scripts, we'll also check to see if + // taproot is active or not. + taprootState, err := b.deploymentState( + node.parent, chaincfg.DeploymentTaproot, + ) + if err != nil { + return err + } + if taprootState == ThresholdActive { + scriptFlags |= txscript.ScriptVerifyTaproot + } + // Now that the inexpensive checks are done and have passed, verify the // transactions are actually allowed to spend the coins by running the // expensive ECDSA signature check scripts. Doing this last helps From f7f7bb33c10e92829f95ce5f750690ba6b37a03d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 8 Mar 2022 18:52:24 -0800 Subject: [PATCH 0647/1056] blockchain/indexers: add P2TR support to the addrindex --- blockchain/indexers/addrindex.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 2f0e2eeba1..7e9f36f104 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -10,12 +10,12 @@ import ( "sync" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -63,6 +63,11 @@ const ( // script template, as well as a 32-byte data push. addrKeyTypeWitnessScriptHash = 3 + // addrKeyTypeTaprootPubKey is the address type in an address key that + // represnts a pay-to-taproot adress. We use this to denote addresses + // related to the segwit v1 that are encoded in the bech32m format. + addrKeyTypeTaprootPubKey = 4 + // Size of a transaction entry. It consists of 4 bytes block id + 4 // bytes offset + 4 bytes length. txEntrySize = 4 + 4 + 4 @@ -573,6 +578,16 @@ func addrToKey(addr btcutil.Address) ([addrKeySize]byte, error) { result[0] = addrKeyTypeWitnessPubKeyHash copy(result[1:], addr.Hash160()[:]) return result, nil + + case *btcutil.AddressTaproot: + var result [addrKeySize]byte + result[0] = addrKeyTypeTaprootPubKey + + // Taproot outputs are actually just the 32-byte public key. + // Similar to the P2WSH outputs, we'll map these to 20-bytes + // via the hash160. + copy(result[1:], btcutil.Hash160(addr.ScriptAddress())) + return result, nil } return [addrKeySize]byte{}, errUnsupportedAddressType From 6ab97a3dd82a6bb290ee9a779907d6768a79e0b4 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 9 Mar 2022 16:31:50 -0800 Subject: [PATCH 0648/1056] blockchain: fix IsSpeedy() bug, add more logging in BIP 9 state machine --- blockchain/thresholdstate.go | 25 +++++++++++++++++++++++++ blockchain/versionbits.go | 5 +++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index b96c9bd3db..f1d7367493 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -171,6 +171,9 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // speed deployments can only transition to failed // after a confirmation window. if !checker.IsSpeedy() && checker.HasEnded(prevNode) { + log.Infof("Moving from state=%v, to state=%v", state, + ThresholdFailed) + state = ThresholdFailed break } @@ -179,6 +182,9 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // once its start time has been reached (and it hasn't // already expired per the above). if checker.HasStarted(prevNode) { + log.Infof("Moving from state=%v, to state=%v", state, + ThresholdStarted) + state = ThresholdStarted } @@ -187,6 +193,9 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // expires before it is accepted and locked in, but // only if this deployment isn't speedy. if !checker.IsSpeedy() && checker.HasEnded(prevNode) { + log.Infof("Moving from state=%v, to state=%v", state, + ThresholdFailed) + state = ThresholdFailed break } @@ -214,13 +223,23 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // period that voted for the rule change meets the // activation threshold. case count >= checker.RuleChangeActivationThreshold(): + log.Infof("Moving from state=%v, to state=%v", state, + ThresholdLockedIn) + state = ThresholdLockedIn // If this is a speedy deployment, we didn't meet the // threshold above, and the deployment has expired, then // we transition to failed. case checker.IsSpeedy() && checker.HasEnded(prevNode): + log.Infof("Moving from state=%v, to state=%v", state, + ThresholdFailed) + state = ThresholdFailed + + default: + log.Infof("Still at state=%v, threshold=%v", state, + float64(count)/float64(checker.RuleChangeActivationThreshold())) } case ThresholdLockedIn: @@ -232,8 +251,14 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // If we aren't eligible to active yet, then we'll just // stay in the locked in position. if !checker.EligibleToActivate(prevNode) { + log.Infof("Moving from state=%v, to state=%v", state, + ThresholdLockedIn) + state = ThresholdLockedIn } else { + log.Infof("Moving from state=%v, to state=%v", state, + ThresholdActive) + // The new rule becomes active when its // previous state was locked in assuming it's // now eligible to activate. diff --git a/blockchain/versionbits.go b/blockchain/versionbits.go index 0d1f898c0a..371d4f20e0 100644 --- a/blockchain/versionbits.go +++ b/blockchain/versionbits.go @@ -187,7 +187,7 @@ func (c deploymentChecker) HasEnded(blkNode *blockNode) bool { // This is part of the thresholdConditionChecker interface implementation. func (c deploymentChecker) RuleChangeActivationThreshold() uint32 { // Some deployments like taproot used a custom activation threshold - // that ovverides the network level threshold. + // that overrides the network level threshold. if c.deployment.CustomActivationThreshold != 0 { return c.deployment.CustomActivationThreshold } @@ -234,7 +234,8 @@ func (c deploymentChecker) EligibleToActivate(blkNode *blockNode) bool { // // This is part of the thresholdConditionChecker interface implementation. func (c deploymentChecker) IsSpeedy() bool { - return c.deployment.MinActivationHeight != 0 + return (c.deployment.MinActivationHeight != 0 || + c.deployment.CustomActivationThreshold != 0) } // Condition returns true when the specific bit defined by the deployment From 99e4e00345017a70eadc4e1d06353c56b23bb15c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 Mar 2022 17:49:45 -0700 Subject: [PATCH 0649/1056] txscript: add more detailed taproot errors --- txscript/engine.go | 2 +- txscript/error.go | 51 +++++++++++++++++++++++++++++++++++++++++ txscript/error_test.go | 10 ++++++++ txscript/opcode.go | 10 ++++---- txscript/sigvalidate.go | 7 +++--- txscript/standard.go | 3 +-- txscript/taproot.go | 23 +++++++++++++------ 7 files changed, 87 insertions(+), 19 deletions(-) diff --git a/txscript/engine.go b/txscript/engine.go index 3c8f207636..7dfd092eae 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -178,7 +178,7 @@ func (t *taprootExecutionCtx) tallysigOp() error { t.sigOpsBudget -= sigOpsDelta if t.sigOpsBudget < 0 { - return fmt.Errorf("max sig ops exceeded") + return scriptError(ErrTaprootMaxSigOps, "") } return nil diff --git a/txscript/error.go b/txscript/error.go index 9170895425..072778a268 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -367,6 +367,47 @@ const ( // bytes. ErrDiscourageUpgradeablePubKeyType + // ErrTaprootSigInvalid is returned when an invalid taproot key spend + // signature is encountered. + ErrTaprootSigInvalid + + // ErrTaprootMerkleProofInvalid is returned when the revealed script + // merkle proof for a taproot spend is found to be invalid. + ErrTaprootMerkleProofInvalid + + // ErrTaprootOutputKeyParityMismatch is returned when the control block + // proof is valid, but the parity of the y-coordinate of the derived + // key doesn't match the value encoded in the control block. + ErrTaprootOutputKeyParityMismatch + + // ErrControlBlockTooSmall is returned when a parsed control block is + // less than 33 bytes. + ErrControlBlockTooSmall + + // ErrControlBlockTooLarge is returned when the control block is larger + // than the largest possible proof for a merkle script tree. + ErrControlBlockTooLarge + + // ErrControlBlockInvalidLength is returned when the control block, + // without the public key isn't a multiple of 32. + ErrControlBlockInvalidLength + + // ErrWitnessHasNoAnnex is returned when a caller attempts to extract + // an annex, but the witness has no annex present. + ErrWitnessHasNoAnnex + + // ErrInvalidTaprootSigLen is returned when taproot signature isn't 64 + // or 65 bytes. + ErrInvalidTaprootSigLen + + // ErrTaprootPubkeyIsEmpty is returned when a signature checking op + // code encounters an empty public key. + ErrTaprootPubkeyIsEmpty + + // ErrTaprootMaxSigOps is returned when the number of allotted sig ops + // is exceeded during taproot execution. + ErrTaprootMaxSigOps + // numErrorCodes is the maximum error code number used in tests. This // entry MUST be the last entry in the enum. numErrorCodes @@ -443,6 +484,16 @@ var errorCodeStrings = map[ErrorCode]string{ ErrDiscourageUpgradeableTaprootVersion: "ErrDiscourageUpgradeableTaprootVersion", ErrTapscriptCheckMultisig: "ErrTapscriptCheckMultisig", ErrDiscourageUpgradeablePubKeyType: "ErrDiscourageUpgradeablePubKeyType", + ErrTaprootSigInvalid: "ErrTaprootSigInvalid", + ErrTaprootMerkleProofInvalid: "ErrTaprootMerkleProofInvalid", + ErrTaprootOutputKeyParityMismatch: "ErrTaprootOutputKeyParityMismatch", + ErrControlBlockTooSmall: "ErrControlBlockTooSmall", + ErrControlBlockTooLarge: "ErrControlBlockTooLarge", + ErrControlBlockInvalidLength: "ErrControlBlockInvalidLength", + ErrWitnessHasNoAnnex: "ErrWitnessHasNoAnnex", + ErrInvalidTaprootSigLen: "ErrInvalidTaprootSigLen", + ErrTaprootPubkeyIsEmpty: "ErrTaprootPubkeyIsEmpty", + ErrTaprootMaxSigOps: "ErrTaprootMaxSigOps", } // String returns the ErrorCode as a human-readable name. diff --git a/txscript/error_test.go b/txscript/error_test.go index 8a9cef0926..accdf11a8c 100644 --- a/txscript/error_test.go +++ b/txscript/error_test.go @@ -86,6 +86,16 @@ func TestErrorCodeStringer(t *testing.T) { {ErrTapscriptCheckMultisig, "ErrTapscriptCheckMultisig"}, {ErrDiscourageUpgradableWitnessProgram, "ErrDiscourageUpgradableWitnessProgram"}, {ErrDiscourageUpgradeablePubKeyType, "ErrDiscourageUpgradeablePubKeyType"}, + {ErrTaprootSigInvalid, "ErrTaprootSigInvalid"}, + {ErrTaprootMerkleProofInvalid, "ErrTaprootMerkleProofInvalid"}, + {ErrTaprootOutputKeyParityMismatch, "ErrTaprootOutputKeyParityMismatch"}, + {ErrControlBlockTooSmall, "ErrControlBlockTooSmall"}, + {ErrControlBlockTooLarge, "ErrControlBlockTooLarge"}, + {ErrControlBlockInvalidLength, "ErrControlBlockInvalidLength"}, + {ErrWitnessHasNoAnnex, "ErrWitnessHasNoAnnex"}, + {ErrInvalidTaprootSigLen, "ErrInvalidTaprootSigLen"}, + {ErrTaprootPubkeyIsEmpty, "ErrTaprootPubkeyIsEmpty"}, + {ErrTaprootMaxSigOps, "ErrTaprootMaxSigOps"}, {0xffff, "Unknown ErrorCode (65535)"}, } diff --git a/txscript/opcode.go b/txscript/opcode.go index 9819ee6510..6e0434423e 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -2038,14 +2038,14 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { } } - // Empty public keys immeidately cause execution to fail. + // Empty public keys immediately cause execution to fail. if len(pkBytes) == 0 { - return fmt.Errorf("nil pub key") + return scriptError(ErrTaprootPubkeyIsEmpty, "") } // If this is tapscript execution, and the signature was // actually an empty vector, then we push on an empty vector - // and continue execution from ther, but only if the pubkey + // and continue execution from there, but only if the pubkey // isn't empty. if len(fullSigBytes) == 0 { vm.dstack.PushByteArray([]byte{}) @@ -2143,9 +2143,9 @@ func opcodeCheckSigAdd(op *opcode, data []byte, vm *Engine) error { } } - // Empty public keys immeidately cause execution to fail. + // Empty public keys immediately cause execution to fail. if len(pubKeyBytes) == 0 { - return fmt.Errorf("nil pubkey") + return scriptError(ErrTaprootPubkeyIsEmpty, "") } // If the signature is empty, then we'll just push the value N back diff --git a/txscript/sigvalidate.go b/txscript/sigvalidate.go index 8d5a8eb590..0bd00c326d 100644 --- a/txscript/sigvalidate.go +++ b/txscript/sigvalidate.go @@ -291,8 +291,8 @@ func parseTaprootSigAndPubKey(pkBytes, rawSig []byte, // Otherwise, this is an invalid signature, so we need to bail out. default: - // TODO(roasbeef): do proper error here - return nil, nil, 0, fmt.Errorf("invalid sig len: %v", len(rawSig)) + str := fmt.Sprintf("invalid sig len: %v", len(rawSig)) + return nil, nil, 0, scriptError(ErrInvalidTaprootSigLen, str) } return pubKey, sig, sigHashType, nil @@ -402,8 +402,7 @@ func newBaseTapscriptSigVerifier(pkBytes, rawSig []byte, // If the public key is zero bytes, then this is invalid, and will fail // immediately. case 0: - // TODO(roasbeef): better erro - return nil, fmt.Errorf("pubkey is zero bytes") + return nil, scriptError(ErrTaprootPubkeyIsEmpty, "") // If the public key is 32 byte as we expect, then we'll parse things // as normal. diff --git a/txscript/standard.go b/txscript/standard.go index 2ad658304b..aa7a7970d7 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -482,8 +482,7 @@ func isAnnexedWitness(witness wire.TxWitness) bool { // witness doesn't contain an annex, then an error is returned. func extractAnnex(witness [][]byte) ([]byte, error) { if !isAnnexedWitness(witness) { - // TODO(roasbeef): make into actual type - return nil, fmt.Errorf("no witness annex") + return nil, scriptError(ErrWitnessHasNoAnnex, "") } lastElement := witness[len(witness)-1] diff --git a/txscript/taproot.go b/txscript/taproot.go index f07e4d015a..2e452f92d7 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -89,8 +89,7 @@ func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, return nil } - // TODO(roasbeef): add proper error - return fmt.Errorf("invalid sig") + return scriptError(ErrTaprootSigInvalid, "") } // ControlBlock houses the structured witness input for a taproot spend. This @@ -189,18 +188,24 @@ func ParseControlBlock(ctrlBlock []byte) (*ControlBlock, error) { // The control block must minimally have 33 bytes for the internal // public key and script leaf version. case len(ctrlBlock) < ControlBlockBaseSize: - return nil, fmt.Errorf("invalid control block size") + str := fmt.Sprintf("min size is %v bytes, control block "+ + "is %v bytes", ControlBlockBaseSize, len(ctrlBlock)) + return nil, scriptError(ErrControlBlockTooSmall, str) // The control block can't be larger than a proof for the largest // possible tapscript merkle tree with 2^128 leaves. case len(ctrlBlock) > ControlBlockMaxSize: - return nil, fmt.Errorf("invalid max block size") + str := fmt.Sprintf("max size is %v, control block is %v bytes", + ControlBlockMaxSize, len(ctrlBlock)) + return nil, scriptError(ErrControlBlockTooLarge, str) // Ignoring the fixed sized portion, we expect the total number of // remaining bytes to be a multiple of the node size, which is 32 // bytes. case (len(ctrlBlock)-ControlBlockBaseSize)%ControlBlockNodeSize != 0: - return nil, fmt.Errorf("invalid max block size") + str := fmt.Sprintf("control block proof is not a multiple "+ + "of 32: %v", len(ctrlBlock)-ControlBlockBaseSize) + return nil, scriptError(ErrControlBlockInvalidLength, str) } // With the basic sanity checking complete, we can now parse the @@ -347,7 +352,8 @@ func VerifyTaprootLeafCommitment(controlBlock *ControlBlock, // program passed in. expectedWitnessProgram := schnorr.SerializePubKey(taprootKey) if !bytes.Equal(expectedWitnessProgram, taprootWitnessProgram) { - return fmt.Errorf("invalid witness commitment") + + return scriptError(ErrTaprootMerkleProofInvalid, "") } // Finally, we'll verify that the parity of the y coordinate of the @@ -355,7 +361,10 @@ func VerifyTaprootLeafCommitment(controlBlock *ControlBlock, derivedYIsOdd := (taprootKey.SerializeCompressed()[0] == secp.PubKeyFormatCompressedOdd) if controlBlock.OutputKeyYIsOdd != derivedYIsOdd { - return fmt.Errorf("invalid witness commitment") + str := fmt.Sprintf("control block y is odd: %v, derived "+ + "parity is odd: %v", controlBlock.OutputKeyYIsOdd, + derivedYIsOdd) + return scriptError(ErrTaprootOutputKeyParityMismatch, str) } // Otherwise, if we reach here, the commitment opening is valid and From 30d58b98a16ef32caa475b49e9a58fd891af6e1c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 Mar 2022 18:00:11 -0700 Subject: [PATCH 0650/1056] build: add temporary replace directives for btcec+chainhash This PR includes some changes to them, so we'll need to use a temporary replace directives to ensure the build passes. --- btcutil/go.mod | 4 ++++ btcutil/go.sum | 5 ----- btcutil/psbt/go.mod | 4 ++++ btcutil/psbt/go.sum | 4 ---- go.mod | 4 ++++ go.sum | 2 -- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index ba110830fa..9b3cc2afad 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -14,3 +14,7 @@ require ( ) replace github.com/btcsuite/btcd => ../ + +replace github.com/btcsuite/btcd/chaincfg/chainhash => ../chaincfg/chainhash + +replace github.com/btcsuite/btcd/btcec/v2 => ../btcec diff --git a/btcutil/go.sum b/btcutil/go.sum index 8617dd8351..6958d531e2 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -1,11 +1,6 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcec/v2 v2.1.1 h1:xxivBG6pU3wwxx9qPNZP+2K0PXO9VmFLaSrwOFr24Hw= -github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 059bdab55c..868e433298 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -20,3 +20,7 @@ require ( replace github.com/btcsuite/btcd/btcutil => ../ replace github.com/btcsuite/btcd => ../.. + +replace github.com/btcsuite/btcd/chaincfg/chainhash => ../../chaincfg/chainhash + +replace github.com/btcsuite/btcd/btcec/v2 => ../../btcec diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index 3056278f02..8e55c769de 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -1,8 +1,4 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd/btcec/v2 v2.1.1 h1:xxivBG6pU3wwxx9qPNZP+2K0PXO9VmFLaSrwOFr24Hw= -github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/go.mod b/go.mod index 732ed420c8..f5295d3abb 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,10 @@ require ( replace github.com/btcsuite/btcd/btcutil => ./btcutil +replace github.com/btcsuite/btcd/chaincfg/chainhash => ./chaincfg/chainhash + +replace github.com/btcsuite/btcd/btcec/v2 => ./btcec + // The retract statements below fixes an accidental push of the tags of a btcd // fork. retract ( diff --git a/go.sum b/go.sum index 604e50543e..2dc38639a8 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,6 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd/btcec/v2 v2.1.1 h1:xxivBG6pU3wwxx9qPNZP+2K0PXO9VmFLaSrwOFr24Hw= github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= From c203b940f3c502fd97e69f5b5a54b5ae58c1c021 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 15 Mar 2022 18:42:10 -0700 Subject: [PATCH 0651/1056] build: update to btcec/v2.1.3 and chaincfg/chainhash v1.0.1 In this commit, we update the top level module to use the newly tagged sub-modules. Once we remove the circular dependant in these sub-modules, then we'll no longer have to do things like this. --- btcutil/go.mod | 8 ++------ btcutil/go.sum | 6 ++++++ btcutil/psbt/go.mod | 8 ++------ btcutil/psbt/go.sum | 5 +++++ go.mod | 8 ++------ go.sum | 7 +++++-- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index 9b3cc2afad..4f98f6939a 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -5,8 +5,8 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c - github.com/btcsuite/btcd/btcec/v2 v2.1.1 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 + github.com/btcsuite/btcd/btcec/v2 v2.1.3 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 @@ -14,7 +14,3 @@ require ( ) replace github.com/btcsuite/btcd => ../ - -replace github.com/btcsuite/btcd/chaincfg/chainhash => ../chaincfg/chainhash - -replace github.com/btcsuite/btcd/btcec/v2 => ../btcec diff --git a/btcutil/go.sum b/btcutil/go.sum index 6958d531e2..e4f26dfd1c 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -1,6 +1,12 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 868e433298..c2e36ff4fa 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -4,9 +4,9 @@ go 1.17 require ( github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c - github.com/btcsuite/btcd/btcec/v2 v2.1.1 + github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/btcutil v1.1.0 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 ) @@ -20,7 +20,3 @@ require ( replace github.com/btcsuite/btcd/btcutil => ../ replace github.com/btcsuite/btcd => ../.. - -replace github.com/btcsuite/btcd/chaincfg/chainhash => ../../chaincfg/chainhash - -replace github.com/btcsuite/btcd/btcec/v2 => ../../btcec diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index 8e55c769de..ccdbe0ae4f 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -1,4 +1,9 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= diff --git a/go.mod b/go.mod index f5295d3abb..b7ebe37c28 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,9 @@ module github.com/btcsuite/btcd require ( - github.com/btcsuite/btcd/btcec/v2 v2.1.1 + github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/btcutil v1.1.0 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 @@ -29,10 +29,6 @@ require ( replace github.com/btcsuite/btcd/btcutil => ./btcutil -replace github.com/btcsuite/btcd/chaincfg/chainhash => ./chaincfg/chainhash - -replace github.com/btcsuite/btcd/btcec/v2 => ./btcec - // The retract statements below fixes an accidental push of the tags of a btcd // fork. retract ( diff --git a/go.sum b/go.sum index 2dc38639a8..15e6ac4b7c 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,11 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd/btcec/v2 v2.1.1 h1:xxivBG6pU3wwxx9qPNZP+2K0PXO9VmFLaSrwOFr24Hw= -github.com/btcsuite/btcd/btcec/v2 v2.1.1/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= From 36e67158b28acb993c955705a7ce7f601e38d3ed Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 17 Mar 2022 17:56:37 -0700 Subject: [PATCH 0652/1056] blockchain: demote BIP 9 log statements In this commit, we demote a series of log statements added while debugging the modified BIP 9 state machine. These are rather spammy on mainnet, so we demote the transition logs (moving to a new state) to debug, and the remaining log (when we're still in started to trace). --- blockchain/thresholdstate.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index f1d7367493..35653bf8fc 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -171,7 +171,7 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // speed deployments can only transition to failed // after a confirmation window. if !checker.IsSpeedy() && checker.HasEnded(prevNode) { - log.Infof("Moving from state=%v, to state=%v", state, + log.Debugf("Moving from state=%v, to state=%v", state, ThresholdFailed) state = ThresholdFailed @@ -182,7 +182,7 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // once its start time has been reached (and it hasn't // already expired per the above). if checker.HasStarted(prevNode) { - log.Infof("Moving from state=%v, to state=%v", state, + log.Debugf("Moving from state=%v, to state=%v", state, ThresholdStarted) state = ThresholdStarted @@ -193,7 +193,7 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // expires before it is accepted and locked in, but // only if this deployment isn't speedy. if !checker.IsSpeedy() && checker.HasEnded(prevNode) { - log.Infof("Moving from state=%v, to state=%v", state, + log.Debugf("Moving from state=%v, to state=%v", state, ThresholdFailed) state = ThresholdFailed @@ -223,7 +223,7 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // period that voted for the rule change meets the // activation threshold. case count >= checker.RuleChangeActivationThreshold(): - log.Infof("Moving from state=%v, to state=%v", state, + log.Debugf("Moving from state=%v, to state=%v", state, ThresholdLockedIn) state = ThresholdLockedIn @@ -232,13 +232,13 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // threshold above, and the deployment has expired, then // we transition to failed. case checker.IsSpeedy() && checker.HasEnded(prevNode): - log.Infof("Moving from state=%v, to state=%v", state, + log.Debugf("Moving from state=%v, to state=%v", state, ThresholdFailed) state = ThresholdFailed default: - log.Infof("Still at state=%v, threshold=%v", state, + log.Tracef("Still at state=%v, threshold=%v", state, float64(count)/float64(checker.RuleChangeActivationThreshold())) } @@ -251,12 +251,12 @@ func thresholdStateTransition(state ThresholdState, prevNode *blockNode, // If we aren't eligible to active yet, then we'll just // stay in the locked in position. if !checker.EligibleToActivate(prevNode) { - log.Infof("Moving from state=%v, to state=%v", state, + log.Debugf("Moving from state=%v, to state=%v", state, ThresholdLockedIn) state = ThresholdLockedIn } else { - log.Infof("Moving from state=%v, to state=%v", state, + log.Debugf("Moving from state=%v, to state=%v", state, ThresholdActive) // The new rule becomes active when its From 56b048867b0f8a883413745d70e908d256266673 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 28 Mar 2022 10:14:43 +0200 Subject: [PATCH 0653/1056] psbt: allow empty bip32 derivation path BIP-0174 defines the derivation path being encoded as "<32-bit uint> <32-bit uint>*" with the asterisk meaning 0 to n times. Which in turn means that an empty path is valid, only the key fingerprint is mandatory. --- btcutil/psbt/bip32.go | 7 +++++-- btcutil/psbt/psbt_test.go | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/btcutil/psbt/bip32.go b/btcutil/psbt/bip32.go index 9fbfc73b61..6b22dc0654 100644 --- a/btcutil/psbt/bip32.go +++ b/btcutil/psbt/bip32.go @@ -40,8 +40,11 @@ func (s Bip32Sorter) Less(i, j int) bool { // little endian encodings of uint32 values, the first of which is the // masterkeyfingerprint and the remainder of which are the derivation path. func readBip32Derivation(path []byte) (uint32, []uint32, error) { - - if len(path)%4 != 0 || len(path)/4-1 < 1 { + // BIP-0174 defines the derivation path being encoded as + // "<32-bit uint> <32-bit uint>*" + // with the asterisk meaning 0 to n times. Which in turn means that an + // empty path is valid, only the key fingerprint is mandatory. + if len(path)%4 != 0 { return 0, nil, ErrInvalidPsbtFormat } diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go index 12038fbfa0..4ce73f05a2 100644 --- a/btcutil/psbt/psbt_test.go +++ b/btcutil/psbt/psbt_test.go @@ -11,10 +11,10 @@ import ( "encoding/hex" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "github.com/davecgh/go-spew/spew" ) @@ -63,6 +63,7 @@ var validPsbtHex = map[int]string{ 3: "70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000", 4: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", 5: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000", + 6: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000002206030d097466b7f59162ac4d90bf65f2a31a8bad82fcd22e98138dcf279401939bd104ffffffff0a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000", } // These are all invalid PSBTs for the indicated From 511b4648786e12661b9bea7e3105f55b0abe8982 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Wed, 6 Apr 2022 14:33:13 +0200 Subject: [PATCH 0654/1056] mempool: export check Standardness func --- mempool/mempool.go | 4 ++-- mempool/policy.go | 6 +++--- mempool/policy_test.go | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index f830a51382..a80d8ee4f4 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -15,12 +15,12 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain/indexers" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -989,7 +989,7 @@ func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejec // Don't allow non-standard transactions if the network parameters // forbid their acceptance. if !mp.cfg.Policy.AcceptNonStd { - err = checkTransactionStandard(tx, nextBlockHeight, + err = CheckTransactionStandard(tx, nextBlockHeight, medianTimePast, mp.cfg.Policy.MinRelayTxFee, mp.cfg.Policy.MaxTxVersion) if err != nil { diff --git a/mempool/policy.go b/mempool/policy.go index edba16ac2e..758f7e06a9 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -9,9 +9,9 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -275,14 +275,14 @@ func IsDust(txOut *wire.TxOut, minRelayTxFee btcutil.Amount) bool { return txOut.Value*1000/GetDustThreshold(txOut) < int64(minRelayTxFee) } -// checkTransactionStandard performs a series of checks on a transaction to +// CheckTransactionStandard performs a series of checks on a transaction to // ensure it is a "standard" transaction. A standard transaction is one that // conforms to several additional limiting cases over what is considered a // "sane" transaction such as having a version in the supported range, being // finalized, conforming to more stringent size constraints, having scripts // of recognized forms, and not containing "dust" outputs (those that are // so small it costs more to process them than they are worth). -func checkTransactionStandard(tx *btcutil.Tx, height int32, +func CheckTransactionStandard(tx *btcutil.Tx, height int32, medianTimePast time.Time, minRelayTxFee btcutil.Amount, maxTxVersion int32) error { diff --git a/mempool/policy_test.go b/mempool/policy_test.go index 5175b67999..1b29d71f1f 100644 --- a/mempool/policy_test.go +++ b/mempool/policy_test.go @@ -10,11 +10,11 @@ import ( "time" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // TestCalcMinRequiredTxRelayFee tests the calcMinRequiredTxRelayFee API. @@ -277,7 +277,7 @@ func TestDust(t *testing.T) { } } -// TestCheckTransactionStandard tests the checkTransactionStandard API. +// TestCheckTransactionStandard tests the CheckTransactionStandard API. func TestCheckTransactionStandard(t *testing.T) { // Create some dummy, but otherwise standard, data for transactions. prevOutHash, err := chainhash.NewHashFromStr("01") @@ -469,7 +469,7 @@ func TestCheckTransactionStandard(t *testing.T) { pastMedianTime := time.Now() for _, test := range tests { // Ensure standardness is as expected. - err := checkTransactionStandard(btcutil.NewTx(&test.tx), + err := CheckTransactionStandard(btcutil.NewTx(&test.tx), test.height, pastMedianTime, DefaultMinRelayTxFee, 1) if err == nil && test.isStandard { // Test passes since function returned standard for a @@ -477,12 +477,12 @@ func TestCheckTransactionStandard(t *testing.T) { continue } if err == nil && !test.isStandard { - t.Errorf("checkTransactionStandard (%s): standard when "+ + t.Errorf("CheckTransactionStandard (%s): standard when "+ "it should not be", test.name) continue } if err != nil && test.isStandard { - t.Errorf("checkTransactionStandard (%s): nonstandard "+ + t.Errorf("CheckTransactionStandard (%s): nonstandard "+ "when it should not be: %v", test.name, err) continue } @@ -490,20 +490,20 @@ func TestCheckTransactionStandard(t *testing.T) { // Ensure error type is a TxRuleError inside of a RuleError. rerr, ok := err.(RuleError) if !ok { - t.Errorf("checkTransactionStandard (%s): unexpected "+ + t.Errorf("CheckTransactionStandard (%s): unexpected "+ "error type - got %T", test.name, err) continue } txrerr, ok := rerr.Err.(TxRuleError) if !ok { - t.Errorf("checkTransactionStandard (%s): unexpected "+ + t.Errorf("CheckTransactionStandard (%s): unexpected "+ "error type - got %T", test.name, rerr.Err) continue } // Ensure the reject code is the expected one. if txrerr.RejectCode != test.code { - t.Errorf("checkTransactionStandard (%s): unexpected "+ + t.Errorf("CheckTransactionStandard (%s): unexpected "+ "error code - got %v, want %v", test.name, txrerr.RejectCode, test.code) continue From 71c844310a78c0eb58f38c4b09f41f89f5e26db6 Mon Sep 17 00:00:00 2001 From: James Smoot Date: Wed, 30 Mar 2022 18:44:30 -0700 Subject: [PATCH 0655/1056] Default to JSONRPC 1.0 if the rpcVersion empty --- btcjson/jsonrpc.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/btcjson/jsonrpc.go b/btcjson/jsonrpc.go index 553a7bc37f..ea4a213bca 100644 --- a/btcjson/jsonrpc.go +++ b/btcjson/jsonrpc.go @@ -157,6 +157,9 @@ func (request *Request) UnmarshalJSON(b []byte) error { // request. func NewRequest(rpcVersion RPCVersion, id interface{}, method string, params []interface{}) (*Request, error) { // default to JSON-RPC 1.0 if RPC type is not specified + if rpcVersion == "" { + rpcVersion = RpcVersion1 + } if !rpcVersion.IsValid() { str := fmt.Sprintf("rpcversion '%s' is invalid", rpcVersion) return nil, makeError(ErrInvalidType, str) From 796f1746b3ad3c88aa3a3369fc3483604f82f35d Mon Sep 17 00:00:00 2001 From: dekokun Date: Mon, 31 Jan 2022 19:20:35 +0900 Subject: [PATCH 0656/1056] btcjson: Update the fields of GetNetworkInfoResult Update the fields of GetNetworkInfoResult to reflect the current number of inbound and outbound peer connections. * ConnectionsIn - The number of inbound peer connections * ConnectionsOut - The number of outbound peer connections --- btcjson/chainsvrresults.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 7b771b12f7..4feaeda338 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -364,6 +364,8 @@ type GetNetworkInfoResult struct { LocalRelay bool `json:"localrelay"` TimeOffset int64 `json:"timeoffset"` Connections int32 `json:"connections"` + ConnectionsIn int32 `json:"connections_in"` + ConnectionsOut int32 `json:"connections_out"` NetworkActive bool `json:"networkactive"` Networks []NetworksResult `json:"networks"` RelayFee float64 `json:"relayfee"` From 67aad53f5eb1c696c5c1a8fb5c61fa54aebc5960 Mon Sep 17 00:00:00 2001 From: Tim Kuijsten Date: Tue, 22 Feb 2022 22:22:10 +0100 Subject: [PATCH 0657/1056] harden btcd on OpenBSD Restrict the available set of system calls to the daemon to the basic network and filesystem operations on OpenBSD. Further reduce potential harm by limiting file system access to the btcd data dir and the rpc files. --- btcd.go | 31 +++++++++++++++++++++++++++++++ ossec/ossec.go | 15 +++++++++++++++ ossec/ossec_openbsd.go | 17 +++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 ossec/ossec.go create mode 100644 ossec/ossec_openbsd.go diff --git a/btcd.go b/btcd.go index 3ace182cd8..1d1784d509 100644 --- a/btcd.go +++ b/btcd.go @@ -18,6 +18,7 @@ import ( "github.com/btcsuite/btcd/blockchain/indexers" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/limits" + "github.com/btcsuite/btcd/ossec" ) const ( @@ -144,6 +145,16 @@ func btcdMain(serverChan chan<- *server) error { return nil } + // The config file is already created if it did not exist and the log + // file has already been opened by now so we only need to allow + // creating rpc cert and key files if they don't exist. + unveilx(cfg.RPCKey, "rwc") + unveilx(cfg.RPCCert, "rwc") + unveilx(cfg.DataDir, "rwc") + + // drop unveil and tty + pledgex("stdio rpath wpath cpath flock dns inet") + // Create server and start it. server, err := newServer(cfg.Listeners, cfg.AgentBlacklist, cfg.AgentWhitelist, db, activeNetParams.Params, interrupt) @@ -296,6 +307,26 @@ func loadBlockDB() (database.DB, error) { return db, nil } +func unveilx(path string, perms string) { + err := ossec.Unveil(path, perms) + if err != nil { + fmt.Fprintf(os.Stderr, "unveil failed: %v\n", err) + os.Exit(1) + } +} + +func pledgex(promises string) { + err := ossec.PledgePromises(promises) + if err != nil { + fmt.Fprintf(os.Stderr, "pledge failed: %v\n", err) + os.Exit(1) + } +} + +func init() { + pledgex("unveil stdio id rpath wpath cpath flock dns inet tty") +} + func main() { // Block and transaction processing can cause bursty allocations. This // limits the garbage collector from excessively overallocating during diff --git a/ossec/ossec.go b/ossec/ossec.go new file mode 100644 index 0000000000..fc760ed9ea --- /dev/null +++ b/ossec/ossec.go @@ -0,0 +1,15 @@ +//go:build !openbsd + +package ossec + +func Unveil(path string, perms string) error { + return nil +} + +func Pledge(promises, execpromises string) error { + return nil +} + +func PledgePromises(promises string) error { + return nil +} diff --git a/ossec/ossec_openbsd.go b/ossec/ossec_openbsd.go new file mode 100644 index 0000000000..47aa2ae3ef --- /dev/null +++ b/ossec/ossec_openbsd.go @@ -0,0 +1,17 @@ +package ossec + +import ( + "golang.org/x/sys/unix" +) + +func Unveil(path string, perms string) error { + return unix.Unveil(path, perms) +} + +func Pledge(promises, execpromises string) error { + return unix.Pledge(promises, execpromises) +} + +func PledgePromises(promises string) error { + return unix.PledgePromises(promises) +} From 3faf68c8c57d925baea2bdcbcbc8a7efbbf99080 Mon Sep 17 00:00:00 2001 From: Tim Kuijsten Date: Tue, 22 Feb 2022 22:40:34 +0100 Subject: [PATCH 0658/1056] go mod tidy --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index b7ebe37c28..2e3333acc1 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/stretchr/testify v1.7.0 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 + golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed ) require ( From e0149d63a167f32c8358220e8df6b7f5647a5077 Mon Sep 17 00:00:00 2001 From: Harsha Goli Date: Mon, 7 Feb 2022 13:18:04 -0500 Subject: [PATCH 0659/1056] rpctest: ensure rpclisten is set to an available port --- integration/rpctest/rpc_harness.go | 61 ++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index cb49e42c26..2cb7e56d26 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -7,20 +7,20 @@ package rpctest import ( "fmt" "io/ioutil" - "math/rand" "net" "os" "path/filepath" "strconv" "sync" + "sync/atomic" "testing" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -64,6 +64,19 @@ var ( // default behavior which isn't very concurrency safe (just selecting // a random port can produce collisions and therefore flakes). ListenAddressGenerator = generateListeningAddresses + + // defaultNodePort is the start of the range for listening ports of + // harness nodes. Ports are monotonically increasing starting from this + // number and are determined by the results of nextAvailablePort(). + defaultNodePort uint32 = 8333 + + // ListenerFormat is the format string that is used to generate local + // listener addresses. + ListenerFormat = "127.0.0.1:%d" + + // lastPort is the last port determined to be free for use by a new + // node. It should be used atomically. + lastPort uint32 = defaultNodePort ) // HarnessTestCase represents a test-case which utilizes an instance of the @@ -509,24 +522,40 @@ func (h *Harness) GenerateAndSubmitBlockWithCustomCoinbaseOutputs( return newBlock, nil } -// generateListeningAddresses returns two strings representing listening -// addresses designated for the current rpc test. If there haven't been any -// test instances created, the default ports are used. Otherwise, in order to -// support multiple test nodes running at once, the p2p and rpc port are -// picked at random between {min/max}PeerPort and {min/max}RPCPort respectively. +// generateListeningAddresses is a function that returns two listener +// addresses with unique ports and should be used to overwrite rpctest's +// default generator which is prone to use colliding ports. func generateListeningAddresses() (string, string) { - localhost := "127.0.0.1" - - rand.Seed(time.Now().UnixNano()) + return fmt.Sprintf(ListenerFormat, NextAvailablePort()), + fmt.Sprintf(ListenerFormat, NextAvailablePort()) +} - portString := func(minPort, maxPort int) string { - port := minPort + rand.Intn(maxPort-minPort) - return strconv.Itoa(port) +// NextAvailablePort returns the first port that is available for listening by +// a new node. It panics if no port is found and the maximum available TCP port +// is reached. +func NextAvailablePort() int { + port := atomic.AddUint32(&lastPort, 1) + for port < 65535 { + // If there are no errors while attempting to listen on this + // port, close the socket and return it as available. While it + // could be the case that some other process picks up this port + // between the time the socket is closed and it's reopened in + // the harness node, in practice in CI servers this seems much + // less likely than simply some other process already being + // bound at the start of the tests. + addr := fmt.Sprintf(ListenerFormat, port) + l, err := net.Listen("tcp4", addr) + if err == nil { + err := l.Close() + if err == nil { + return int(port) + } + } + port = atomic.AddUint32(&lastPort, 1) } - p2p := net.JoinHostPort(localhost, portString(minPeerPort, maxPeerPort)) - rpc := net.JoinHostPort(localhost, portString(minRPCPort, maxRPCPort)) - return p2p, rpc + // No ports available? Must be a mistake. + panic("no ports available for listening") } // baseDir is the directory path of the temp directory for all rpctest files. From 061aef98af1321d2cad437afcb7dcbd562a5b3b6 Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Fri, 3 Dec 2021 14:30:36 -0600 Subject: [PATCH 0660/1056] btcjson: add addresstype arg to getnewaddress --- btcjson/jsonrpcerr.go | 3 +++ btcjson/walletsvrcmds.go | 8 +++++--- btcjson/walletsvrcmds_test.go | 14 ++++++++------ rpcclient/wallet.go | 8 ++++---- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/btcjson/jsonrpcerr.go b/btcjson/jsonrpcerr.go index d67b58bbb6..e5872bc51b 100644 --- a/btcjson/jsonrpcerr.go +++ b/btcjson/jsonrpcerr.go @@ -117,6 +117,9 @@ const ( // example, key not found, etc. ErrRPCWallet RPCErrorCode = -4 + // ErrRPCWalletInvalidAddressType indicates an invalid address type. + ErrRPCWalletInvalidAddressType RPCErrorCode = -5 + // ErrRPCWalletInsufficientFunds indicates that there are not enough // funds in wallet or account. ErrRPCWalletInsufficientFunds RPCErrorCode = -6 diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 1e061529d3..e3efb2e431 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -242,7 +242,8 @@ func NewGetBalancesCmd() *GetBalancesCmd { // GetNewAddressCmd defines the getnewaddress JSON-RPC command. type GetNewAddressCmd struct { - Account *string + Account *string + AddressType *string } // NewGetNewAddressCmd returns a new instance which can be used to issue a @@ -250,9 +251,10 @@ type GetNewAddressCmd struct { // // The parameters which are pointers indicate they are optional. Passing nil // for optional parameters will use the default value. -func NewGetNewAddressCmd(account *string) *GetNewAddressCmd { +func NewGetNewAddressCmd(account, addrType *string) *GetNewAddressCmd { return &GetNewAddressCmd{ - Account: account, + Account: account, + AddressType: addrType, } } diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 396153ef04..35d64240ec 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -379,24 +379,26 @@ func TestWalletSvrCmds(t *testing.T) { return btcjson.NewCmd("getnewaddress") }, staticCmd: func() interface{} { - return btcjson.NewGetNewAddressCmd(nil) + return btcjson.NewGetNewAddressCmd(nil, nil) }, marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":[],"id":1}`, unmarshalled: &btcjson.GetNewAddressCmd{ - Account: nil, + Account: nil, + AddressType: nil, }, }, { name: "getnewaddress optional", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getnewaddress", "acct") + return btcjson.NewCmd("getnewaddress", "acct", "legacy") }, staticCmd: func() interface{} { - return btcjson.NewGetNewAddressCmd(btcjson.String("acct")) + return btcjson.NewGetNewAddressCmd(btcjson.String("acct"), btcjson.String("legacy")) }, - marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":["acct"],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":["acct","legacy"],"id":1}`, unmarshalled: &btcjson.GetNewAddressCmd{ - Account: btcjson.String("acct"), + Account: btcjson.String("acct"), + AddressType: btcjson.String("legacy"), }, }, { diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 7268ad0a19..6408fc5791 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -1089,8 +1089,8 @@ func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) { // returned instance. // // See GetNewAddress for the blocking version and more details. -func (c *Client) GetNewAddressAsync(account string) FutureGetNewAddressResult { - cmd := btcjson.NewGetNewAddressCmd(&account) +func (c *Client) GetNewAddressAsync(account, addrType string) FutureGetNewAddressResult { + cmd := btcjson.NewGetNewAddressCmd(&account, &addrType) result := FutureGetNewAddressResult{ network: c.chainParams, responseChannel: c.SendCmd(cmd), @@ -1100,8 +1100,8 @@ func (c *Client) GetNewAddressAsync(account string) FutureGetNewAddressResult { // GetNewAddress returns a new address, and decodes based on the client's // chain params. -func (c *Client) GetNewAddress(account string) (btcutil.Address, error) { - return c.GetNewAddressAsync(account).Receive() +func (c *Client) GetNewAddress(account, addrType string) (btcutil.Address, error) { + return c.GetNewAddressAsync(account, addrType).Receive() } // FutureGetRawChangeAddressResult is a future promise to deliver the result of From 7eaf36006375250bcb68c6b51d060533aaf719ea Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Wed, 22 Dec 2021 10:55:09 -0600 Subject: [PATCH 0661/1056] btcjson: add addresstype arg to getrawchangeaddress --- btcjson/walletsvrcmds.go | 8 +++++--- btcjson/walletsvrcmds_test.go | 14 ++++++++------ rpcclient/wallet.go | 8 ++++---- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index e3efb2e431..5983d3f783 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -260,7 +260,8 @@ func NewGetNewAddressCmd(account, addrType *string) *GetNewAddressCmd { // GetRawChangeAddressCmd defines the getrawchangeaddress JSON-RPC command. type GetRawChangeAddressCmd struct { - Account *string + Account *string + AddressType *string } // NewGetRawChangeAddressCmd returns a new instance which can be used to issue a @@ -268,9 +269,10 @@ type GetRawChangeAddressCmd struct { // // The parameters which are pointers indicate they are optional. Passing nil // for optional parameters will use the default value. -func NewGetRawChangeAddressCmd(account *string) *GetRawChangeAddressCmd { +func NewGetRawChangeAddressCmd(account, addrType *string) *GetRawChangeAddressCmd { return &GetRawChangeAddressCmd{ - Account: account, + Account: account, + AddressType: addrType, } } diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 35d64240ec..21e90c22fa 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -407,24 +407,26 @@ func TestWalletSvrCmds(t *testing.T) { return btcjson.NewCmd("getrawchangeaddress") }, staticCmd: func() interface{} { - return btcjson.NewGetRawChangeAddressCmd(nil) + return btcjson.NewGetRawChangeAddressCmd(nil, nil) }, marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":[],"id":1}`, unmarshalled: &btcjson.GetRawChangeAddressCmd{ - Account: nil, + Account: nil, + AddressType: nil, }, }, { name: "getrawchangeaddress optional", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("getrawchangeaddress", "acct") + return btcjson.NewCmd("getrawchangeaddress", "acct", "legacy") }, staticCmd: func() interface{} { - return btcjson.NewGetRawChangeAddressCmd(btcjson.String("acct")) + return btcjson.NewGetRawChangeAddressCmd(btcjson.String("acct"), btcjson.String("legacy")) }, - marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":["acct"],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":["acct","legacy"],"id":1}`, unmarshalled: &btcjson.GetRawChangeAddressCmd{ - Account: btcjson.String("acct"), + Account: btcjson.String("acct"), + AddressType: btcjson.String("legacy"), }, }, { diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 6408fc5791..8b2e158fda 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -1135,8 +1135,8 @@ func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) { // function on the returned instance. // // See GetRawChangeAddress for the blocking version and more details. -func (c *Client) GetRawChangeAddressAsync(account string) FutureGetRawChangeAddressResult { - cmd := btcjson.NewGetRawChangeAddressCmd(&account) +func (c *Client) GetRawChangeAddressAsync(account, addrType string) FutureGetRawChangeAddressResult { + cmd := btcjson.NewGetRawChangeAddressCmd(&account, &addrType) result := FutureGetRawChangeAddressResult{ network: c.chainParams, responseChannel: c.SendCmd(cmd), @@ -1147,8 +1147,8 @@ func (c *Client) GetRawChangeAddressAsync(account string) FutureGetRawChangeAddr // GetRawChangeAddress returns a new address for receiving change that will be // associated with the provided account. Note that this is only for raw // transactions and NOT for normal use. -func (c *Client) GetRawChangeAddress(account string) (btcutil.Address, error) { - return c.GetRawChangeAddressAsync(account).Receive() +func (c *Client) GetRawChangeAddress(account, addrType string) (btcutil.Address, error) { + return c.GetRawChangeAddressAsync(account, addrType).Receive() } // FutureAddWitnessAddressResult is a future promise to deliver the result of From d14f18d329f2fd30a0ebab60ce585d0f815fea52 Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Tue, 22 Mar 2022 16:08:40 -0500 Subject: [PATCH 0662/1056] mempool: fix t.Fatal call with formatting directive --- mempool/mempool_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index 8df587f8a5..f0f8404cc7 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -14,11 +14,11 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // fakeChain is used by the pool harness to provide generated test utxos and @@ -560,7 +560,7 @@ func TestOrphanReject(t *testing.T) { // Ensure no transactions were reported as accepted. if len(acceptedTxns) != 0 { - t.Fatal("ProcessTransaction: reported %d accepted "+ + t.Fatalf("ProcessTransaction: reported %d accepted "+ "transactions from failed orphan attempt", len(acceptedTxns)) } From d537492a5d68f0aad8a7aacc73a5d0c89fda5df0 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 2 Apr 2022 14:57:59 -0500 Subject: [PATCH 0663/1056] chaincfg: use lower custom activation threshold for regtest+simnet The existing values were copied over from the testnet deployment, which uses a much larger miner confirmation window. As a result, the main taproot deployment would require thousands of blocks to properly activate in development environments. --- chaincfg/params.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chaincfg/params.go b/chaincfg/params.go index 8873390f86..2387c203ae 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -493,7 +493,7 @@ var RegressionNetParams = Params{ DeploymentEnder: NewMedianTimeDeploymentEnder( time.Time{}, // Never expires. ), - CustomActivationThreshold: 1512, // 75% + CustomActivationThreshold: 108, // Only needs 75% hash rate. }, }, @@ -733,7 +733,7 @@ var SimNetParams = Params{ DeploymentEnder: NewMedianTimeDeploymentEnder( time.Time{}, // Never expires. ), - CustomActivationThreshold: 1815, // 90% + CustomActivationThreshold: 75, // Only needs 75% hash rate. }, }, From 85b6f7ed2aaccd3ab17e909d34f8377ab5b2861e Mon Sep 17 00:00:00 2001 From: Torkel Rogstad Date: Thu, 26 Mar 2020 10:02:51 +0100 Subject: [PATCH 0664/1056] rpcclient: add getzmqnotifications RPC --- btcjson/chainsvrcmds_test.go | 12 +++++++ btcjson/chainsvrresults_test.go | 18 +++++++++- btcjson/zmqsvrcmds.go | 16 +++++++++ btcjson/zmqsvrresults.go | 63 +++++++++++++++++++++++++++++++++ rpcclient/zmq.go | 39 ++++++++++++++++++++ 5 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 btcjson/zmqsvrcmds.go create mode 100644 btcjson/zmqsvrresults.go create mode 100644 rpcclient/zmq.go diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 7d3a68dc41..99983288b1 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1460,6 +1460,18 @@ func TestChainSvrCmds(t *testing.T) { marshalled: `{"jsonrpc":"1.0","method":"getdescriptorinfo","params":["123"],"id":1}`, unmarshalled: &btcjson.GetDescriptorInfoCmd{Descriptor: "123"}, }, + { + name: "getzmqnotifications", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getzmqnotifications") + }, + staticCmd: func() interface{} { + return btcjson.NewGetZmqNotificationsCmd() + }, + + marshalled: `{"jsonrpc":"1.0","method":"getzmqnotifications","params":[],"id":1}`, + unmarshalled: &btcjson.GetZmqNotificationsCmd{}, + }, } t.Logf("Running %d tests", len(tests)) diff --git a/btcjson/chainsvrresults_test.go b/btcjson/chainsvrresults_test.go index aee514a9a4..8a11197af2 100644 --- a/btcjson/chainsvrresults_test.go +++ b/btcjson/chainsvrresults_test.go @@ -6,12 +6,13 @@ package btcjson_test import ( "encoding/json" + "net/url" "reflect" "testing" "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/davecgh/go-spew/spew" ) @@ -72,6 +73,21 @@ func TestChainSvrCustomResults(t *testing.T) { }, expected: `{"txid":"123","vout":1,"scriptSig":{"asm":"0","hex":"00"},"prevOut":{"addresses":["addr1"],"value":0},"sequence":4294967295}`, }, + { + name: "zmq notification", + result: &btcjson.GetZmqNotificationResult{{ + Type: "pubrawblock", + Address: func() *url.URL { + u, err := url.Parse("tcp://127.0.0.1:1238") + if err != nil { + panic(err) + } + return u + }(), + HighWaterMark: 1337, + }}, + expected: `[{"address":"tcp://127.0.0.1:1238","hwm":1337,"type":"pubrawblock"}]`, + }, } t.Logf("Running %d tests", len(tests)) diff --git a/btcjson/zmqsvrcmds.go b/btcjson/zmqsvrcmds.go new file mode 100644 index 0000000000..666ea2eb99 --- /dev/null +++ b/btcjson/zmqsvrcmds.go @@ -0,0 +1,16 @@ +package btcjson + +// GetZmqNotificationsCmd defines the getzmqnotifications JSON-RPC command. +type GetZmqNotificationsCmd struct{} + +// NewGetZmqNotificationsCmd returns a new instance which can be used to issue a +// getzmqnotifications JSON-RPC command. +func NewGetZmqNotificationsCmd() *GetZmqNotificationsCmd { + return &GetZmqNotificationsCmd{} +} + +func init() { + flags := UsageFlag(0) + + MustRegisterCmd("getzmqnotifications", (*GetZmqNotificationsCmd)(nil), flags) +} diff --git a/btcjson/zmqsvrresults.go b/btcjson/zmqsvrresults.go new file mode 100644 index 0000000000..a500b403ea --- /dev/null +++ b/btcjson/zmqsvrresults.go @@ -0,0 +1,63 @@ +package btcjson + +import ( + "encoding/json" + "net/url" +) + +// GetZmqNotificationResult models the data returned from the getzmqnotifications command. +type GetZmqNotificationResult []struct { + Type string // Type of notification + Address *url.URL // Address of the publisher + HighWaterMark int // Outbound message high water mark +} + +func (z *GetZmqNotificationResult) MarshalJSON() ([]byte, error) { + var out []map[string]interface{} + for _, notif := range *z { + out = append(out, + map[string]interface{}{ + "type": notif.Type, + "address": notif.Address.String(), + "hwm": notif.HighWaterMark, + }) + } + return json.Marshal(out) +} + +// UnmarshalJSON satisfies the json.Unmarshaller interface +func (z *GetZmqNotificationResult) UnmarshalJSON(bytes []byte) error { + type basicNotification struct { + Type string + Address string + Hwm int + } + + var basics []basicNotification + if err := json.Unmarshal(bytes, &basics); err != nil { + return err + } + + var notifications GetZmqNotificationResult + for _, basic := range basics { + + address, err := url.Parse(basic.Address) + if err != nil { + return err + } + + notifications = append(notifications, struct { + Type string + Address *url.URL + HighWaterMark int + }{ + Type: basic.Type, + Address: address, + HighWaterMark: basic.Hwm, + }) + } + + *z = notifications + + return nil +} diff --git a/rpcclient/zmq.go b/rpcclient/zmq.go new file mode 100644 index 0000000000..1a5405eb77 --- /dev/null +++ b/rpcclient/zmq.go @@ -0,0 +1,39 @@ +package rpcclient + +import ( + "encoding/json" + + "github.com/btcsuite/btcd/btcjson" +) + +// FutureGetZmqNotificationsResult is a future promise to deliver the result of +// a GetZmqNotifications RPC invocation +type FutureGetZmqNotificationsResult chan *Response + +// Receive waits for the response promised by the future and returns the unmarshalled +// response, or an error if the request was unsuccessful. +func (r FutureGetZmqNotificationsResult) Receive() (btcjson.GetZmqNotificationResult, error) { + res, err := ReceiveFuture(r) + if err != nil { + return nil, err + } + var notifications btcjson.GetZmqNotificationResult + if err := json.Unmarshal(res, ¬ifications); err != nil { + return nil, err + } + return notifications, nil +} + +// GetZmqNotificationsAsync returns an instance ofa type that can be used to get +// the result of a custom RPC request at some future time by invoking the Receive +// function on the returned instance. +// +// See GetZmqNotifications for the blocking version and more details. +func (c *Client) GetZmqNotificationsAsync() FutureGetZmqNotificationsResult { + return c.SendCmd(btcjson.NewGetZmqNotificationsCmd()) +} + +// GetZmqNotifications returns information about the active ZeroMQ notifications. +func (c *Client) GetZmqNotifications() (btcjson.GetZmqNotificationResult, error) { + return c.GetZmqNotificationsAsync().Receive() +} From 3986702b97d3395d6283d2b62e2cc5c41f46e770 Mon Sep 17 00:00:00 2001 From: Anup Chenthamarakshan Date: Thu, 9 Dec 2021 20:57:11 -0800 Subject: [PATCH 0665/1056] btcd: don't override explicitly set GOGC If GOGC env var is explicitly set, use it. Otherwise, set GC to 10% (default). --- btcd.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/btcd.go b/btcd.go index 1d1784d509..aec55e06eb 100644 --- a/btcd.go +++ b/btcd.go @@ -328,11 +328,14 @@ func init() { } func main() { - // Block and transaction processing can cause bursty allocations. This - // limits the garbage collector from excessively overallocating during - // bursts. This value was arrived at with the help of profiling live - // usage. - debug.SetGCPercent(10) + // If GOGC is not explicitly set, override GC percent. + if os.Getenv("GOGC") == "" { + // Block and transaction processing can cause bursty allocations. This + // limits the garbage collector from excessively overallocating during + // bursts. This value was arrived at with the help of profiling live + // usage. + debug.SetGCPercent(10) + } // Up some limits. if err := limits.SetLimits(); err != nil { From 1eede8721cd96b82ba0278a164fab352729859ad Mon Sep 17 00:00:00 2001 From: vpereira01 <42812459+vpereira01@users.noreply.github.com> Date: Tue, 15 Mar 2022 22:27:25 +0000 Subject: [PATCH 0666/1056] Adds GH workflow to build docker images on version tags Adds a GitHub workflow, and custom docker file, using docker buildx which builds docker container images for common platforms and publishes these images to GitHub packages. --- .github/workflows/Dockerfile | 24 +++++++++++++++ .github/workflows/dimagespub.yml | 52 ++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 .github/workflows/Dockerfile create mode 100644 .github/workflows/dimagespub.yml diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile new file mode 100644 index 0000000000..30cb21e4a4 --- /dev/null +++ b/.github/workflows/Dockerfile @@ -0,0 +1,24 @@ +# GitHub action dockerfile +# Requires docker experimental features as buildx and BuildKit so not suitable for developers regular use. +# https://docs.docker.com/develop/develop-images/build_enhancements/#to-enable-buildkit-builds + +########################### +# Build binaries stage +########################### +FROM --platform=$BUILDPLATFORM golang:1.16.15-alpine3.15 AS build +ADD . /app +WORKDIR /app +# Arguments required to build binaries targetting the correct OS and CPU architectures +ARG TARGETOS TARGETARCH +# Actually building the binaries +RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go install -v . ./cmd/... + +########################### +# Build docker image stage +########################### +FROM alpine:3.15 +COPY --from=build /go/bin /bin +# 8333 Mainnet Bitcoin peer-to-peer port +# 8334 Mainet RPC port +EXPOSE 8333 8334 +ENTRYPOINT ["btcd"] \ No newline at end of file diff --git a/.github/workflows/dimagespub.yml b/.github/workflows/dimagespub.yml new file mode 100644 index 0000000000..23bd407a76 --- /dev/null +++ b/.github/workflows/dimagespub.yml @@ -0,0 +1,52 @@ +name: Docker images build and publish + +on: + push: + tags: + - v* + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + # Build for default OS, linux, and common CPU architectures + # Reference https://github.com/docker/setup-buildx-action#quick-start + TPLATFORMS: linux/amd64,linux/arm64,linux/arm,linux/386 + +jobs: + build-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Docker Setup Buildx + id: buildx + uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25 + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker images + uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a + with: + file: .github/workflows/Dockerfile + labels: ${{ steps.meta.outputs.labels }} + platforms: ${{ env.TPLATFORMS }} + push: true + tags: ${{ steps.meta.outputs.tags }} \ No newline at end of file From b87a4f48353a4ec55b11fe47edd7069e14069575 Mon Sep 17 00:00:00 2001 From: vpereira01 <42812459+vpereira01@users.noreply.github.com> Date: Sat, 9 Apr 2022 17:04:59 +0100 Subject: [PATCH 0667/1056] Add LF to new files last line --- .github/workflows/Dockerfile | 2 +- .github/workflows/dimagespub.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile index 30cb21e4a4..a5de0e7de0 100644 --- a/.github/workflows/Dockerfile +++ b/.github/workflows/Dockerfile @@ -21,4 +21,4 @@ COPY --from=build /go/bin /bin # 8333 Mainnet Bitcoin peer-to-peer port # 8334 Mainet RPC port EXPOSE 8333 8334 -ENTRYPOINT ["btcd"] \ No newline at end of file +ENTRYPOINT ["btcd"] diff --git a/.github/workflows/dimagespub.yml b/.github/workflows/dimagespub.yml index 23bd407a76..19056ee07b 100644 --- a/.github/workflows/dimagespub.yml +++ b/.github/workflows/dimagespub.yml @@ -49,4 +49,4 @@ jobs: labels: ${{ steps.meta.outputs.labels }} platforms: ${{ env.TPLATFORMS }} push: true - tags: ${{ steps.meta.outputs.tags }} \ No newline at end of file + tags: ${{ steps.meta.outputs.tags }} From e153fefbad89191a62bce20d473b2a0795a8213f Mon Sep 17 00:00:00 2001 From: vpereira01 <42812459+vpereira01@users.noreply.github.com> Date: Sat, 9 Apr 2022 17:16:06 +0100 Subject: [PATCH 0668/1056] Upgrade go docker builder image --- .github/workflows/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Dockerfile b/.github/workflows/Dockerfile index a5de0e7de0..371931a5e4 100644 --- a/.github/workflows/Dockerfile +++ b/.github/workflows/Dockerfile @@ -5,7 +5,7 @@ ########################### # Build binaries stage ########################### -FROM --platform=$BUILDPLATFORM golang:1.16.15-alpine3.15 AS build +FROM --platform=$BUILDPLATFORM golang:1.17.8-alpine3.15 AS build ADD . /app WORKDIR /app # Arguments required to build binaries targetting the correct OS and CPU architectures From eb2eeaf848032ad5235ed1cdb37519415f46e6bf Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 12 Apr 2022 16:09:37 +0200 Subject: [PATCH 0669/1056] psbt: always use non witness serialization format BIP-0174 states that the transaction must be in the old serialization format (without witnesses). --- btcutil/psbt/psbt.go | 22 ++++++---------------- btcutil/psbt/psbt_test.go | 7 ++++--- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go index 73126c3eb2..5ea51eead0 100644 --- a/btcutil/psbt/psbt.go +++ b/btcutil/psbt/psbt.go @@ -214,22 +214,12 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { return nil, err } msgTx := wire.NewMsgTx(2) - err = msgTx.Deserialize(bytes.NewReader(value)) + + // BIP-0174 states: "The transaction must be in the old serialization + // format (without witnesses)." + err = msgTx.DeserializeNoWitness(bytes.NewReader(value)) if err != nil { - // If there are no inputs in this yet incomplete transaction, - // the wire package still incorrectly assumes it's encoded in - // the witness format. We can fix this by just trying the non- - // witness encoding too. If that also fails, it's probably an - // invalid transaction. - msgTx = wire.NewMsgTx(2) - err2 := msgTx.DeserializeNoWitness(bytes.NewReader(value)) - - // If the second attempt also failed, something else is wrong - // and it probably makes more sense to return the original - // error instead of the error from the workaround. - if err2 != nil { - return nil, err - } + return nil, err } if !validateUnsignedTX(msgTx) { return nil, ErrInvalidRawTxSigned @@ -320,7 +310,7 @@ func (p *Packet) Serialize(w io.Writer) error { serializedTx := bytes.NewBuffer( make([]byte, 0, p.UnsignedTx.SerializeSize()), ) - if err := p.UnsignedTx.Serialize(serializedTx); err != nil { + if err := p.UnsignedTx.SerializeNoWitness(serializedTx); err != nil { return err } diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go index 4ce73f05a2..8d66325ad2 100644 --- a/btcutil/psbt/psbt_test.go +++ b/btcutil/psbt/psbt_test.go @@ -64,6 +64,7 @@ var validPsbtHex = map[int]string{ 4: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", 5: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000", 6: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000002206030d097466b7f59162ac4d90bf65f2a31a8bad82fcd22e98138dcf279401939bd104ffffffff0a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000", + 7: "70736274ff01002001000000000100000000000000000d6a0b68656c6c6f20776f726c64000000000000", } // These are all invalid PSBTs for the indicated @@ -115,7 +116,7 @@ var invalidPsbtHex = map[int]string{ // This tests that valid PSBT serializations can be parsed // into Psbt structs. func TestReadValidPsbtAndReserialize(t *testing.T) { - for _, v := range validPsbtHex { + for key, v := range validPsbtHex { PsbtBytes, err := hex.DecodeString(v) if err != nil { t.Fatalf("Unable to decode hex: %v", err) @@ -128,8 +129,8 @@ func TestReadValidPsbtAndReserialize(t *testing.T) { t.Fatalf("unable to parse psbt: %v", err) } - t.Logf("Successfully parsed test, got transaction: %v", - spew.Sdump(testPsbt.UnsignedTx)) + t.Logf("Successfully parsed test %d, got transaction: %v", + key, spew.Sdump(testPsbt.UnsignedTx)) var b bytes.Buffer err = testPsbt.Serialize(&b) From 788fb8faf83cee336e984ac9e0a33b4125544bca Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Thu, 14 Apr 2022 11:25:56 -0500 Subject: [PATCH 0670/1056] rpcclient: add getnewaddresstype and revert breaking change This reverts the previous breaking change to the GetNewAddress and GetRawChangeAddress rpcclient.Client methods, and adds the methods GetNewAddressType and GetRawChangeAddressType for requesting an address of a certain type. This change allows the rpcclient package to continue to work with versions of the btcwallet app that do not recognize the address type parameter. --- btcjson/walletsvrcmds_test.go | 32 +++++++++++++++++-- rpcclient/wallet.go | 59 +++++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/btcjson/walletsvrcmds_test.go b/btcjson/walletsvrcmds_test.go index 21e90c22fa..0b5355e511 100644 --- a/btcjson/walletsvrcmds_test.go +++ b/btcjson/walletsvrcmds_test.go @@ -388,7 +388,21 @@ func TestWalletSvrCmds(t *testing.T) { }, }, { - name: "getnewaddress optional", + name: "getnewaddress optional acct", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getnewaddress", "acct") + }, + staticCmd: func() interface{} { + return btcjson.NewGetNewAddressCmd(btcjson.String("acct"), nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getnewaddress","params":["acct"],"id":1}`, + unmarshalled: &btcjson.GetNewAddressCmd{ + Account: btcjson.String("acct"), + AddressType: nil, + }, + }, + { + name: "getnewaddress optional acct and type", newCmd: func() (interface{}, error) { return btcjson.NewCmd("getnewaddress", "acct", "legacy") }, @@ -416,7 +430,21 @@ func TestWalletSvrCmds(t *testing.T) { }, }, { - name: "getrawchangeaddress optional", + name: "getrawchangeaddress optional acct", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getrawchangeaddress", "acct") + }, + staticCmd: func() interface{} { + return btcjson.NewGetRawChangeAddressCmd(btcjson.String("acct"), nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getrawchangeaddress","params":["acct"],"id":1}`, + unmarshalled: &btcjson.GetRawChangeAddressCmd{ + Account: btcjson.String("acct"), + AddressType: nil, + }, + }, + { + name: "getrawchangeaddress optional acct and type", newCmd: func() (interface{}, error) { return btcjson.NewCmd("getrawchangeaddress", "acct", "legacy") }, diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 8b2e158fda..64f1e40afa 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -9,10 +9,10 @@ import ( "strconv" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // ***************************** @@ -1089,8 +1089,8 @@ func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) { // returned instance. // // See GetNewAddress for the blocking version and more details. -func (c *Client) GetNewAddressAsync(account, addrType string) FutureGetNewAddressResult { - cmd := btcjson.NewGetNewAddressCmd(&account, &addrType) +func (c *Client) GetNewAddressAsync(account string) FutureGetNewAddressResult { + cmd := btcjson.NewGetNewAddressCmd(&account, nil) result := FutureGetNewAddressResult{ network: c.chainParams, responseChannel: c.SendCmd(cmd), @@ -1100,8 +1100,28 @@ func (c *Client) GetNewAddressAsync(account, addrType string) FutureGetNewAddres // GetNewAddress returns a new address, and decodes based on the client's // chain params. -func (c *Client) GetNewAddress(account, addrType string) (btcutil.Address, error) { - return c.GetNewAddressAsync(account, addrType).Receive() +func (c *Client) GetNewAddress(account string) (btcutil.Address, error) { + return c.GetNewAddressAsync(account).Receive() +} + +// GetNewAddressTypeAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function on +// the returned instance. +// +// See GetNewAddressType for the blocking version and more details. +func (c *Client) GetNewAddressTypeAsync(account, addrType string) FutureGetNewAddressResult { + cmd := btcjson.NewGetNewAddressCmd(&account, &addrType) + result := FutureGetNewAddressResult{ + network: c.chainParams, + responseChannel: c.SendCmd(cmd), + } + return result +} + +// GetNewAddressType returns a new address, and decodes based on the client's +// chain params. +func (c *Client) GetNewAddressType(account, addrType string) (btcutil.Address, error) { + return c.GetNewAddressTypeAsync(account, addrType).Receive() } // FutureGetRawChangeAddressResult is a future promise to deliver the result of @@ -1135,8 +1155,8 @@ func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) { // function on the returned instance. // // See GetRawChangeAddress for the blocking version and more details. -func (c *Client) GetRawChangeAddressAsync(account, addrType string) FutureGetRawChangeAddressResult { - cmd := btcjson.NewGetRawChangeAddressCmd(&account, &addrType) +func (c *Client) GetRawChangeAddressAsync(account string) FutureGetRawChangeAddressResult { + cmd := btcjson.NewGetRawChangeAddressCmd(&account, nil) result := FutureGetRawChangeAddressResult{ network: c.chainParams, responseChannel: c.SendCmd(cmd), @@ -1147,8 +1167,29 @@ func (c *Client) GetRawChangeAddressAsync(account, addrType string) FutureGetRaw // GetRawChangeAddress returns a new address for receiving change that will be // associated with the provided account. Note that this is only for raw // transactions and NOT for normal use. -func (c *Client) GetRawChangeAddress(account, addrType string) (btcutil.Address, error) { - return c.GetRawChangeAddressAsync(account, addrType).Receive() +func (c *Client) GetRawChangeAddress(account string) (btcutil.Address, error) { + return c.GetRawChangeAddressAsync(account).Receive() +} + +// GetRawChangeAddressTypeAsync returns an instance of a type that can be used +// to get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See GetRawChangeAddressType for the blocking version and more details. +func (c *Client) GetRawChangeAddressTypeAsync(account, addrType string) FutureGetRawChangeAddressResult { + cmd := btcjson.NewGetRawChangeAddressCmd(&account, &addrType) + result := FutureGetRawChangeAddressResult{ + network: c.chainParams, + responseChannel: c.SendCmd(cmd), + } + return result +} + +// GetRawChangeAddressType returns a new address for receiving change that will +// be associated with the provided account. Note that this is only for raw +// transactions and NOT for normal use. +func (c *Client) GetRawChangeAddressType(account, addrType string) (btcutil.Address, error) { + return c.GetRawChangeAddressTypeAsync(account, addrType).Receive() } // FutureAddWitnessAddressResult is a future promise to deliver the result of From 1a65f1ccf02541f3ec19f8761ff269f0a7172d11 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 1 Mar 2022 18:39:37 -0800 Subject: [PATCH 0671/1056] btcec/schnorr/musig2: add key musig2 key aggregation routines In this commit, we add the set of key aggregation routines for musig2. This includes the main public key aggregation method, as well as the aggregation coefficient which is used to compute "mu" when signing. The logic in this implementation is based on the musig2 paper, as well as this spec: https://github.com/ElementsProject/secp256k1-zkp/blob/master/doc/musig-spec.mediawiki. --- btcec/schnorr/musig2/keys.go | 166 +++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 btcec/schnorr/musig2/keys.go diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go new file mode 100644 index 0000000000..f69cc31063 --- /dev/null +++ b/btcec/schnorr/musig2/keys.go @@ -0,0 +1,166 @@ +// Copyright 2013-2022 The btcsuite developers + +package musig2 + +import ( + "bytes" + "sort" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +var ( + // KeyAggTagList is the tagged hash tag used to compute the hash of the + // list of sorted public keys. + KeyAggTagList = []byte("KeyAgg list") + + // KeyAggTagCoeff is the tagged hash tag used to compute the key + // aggregation coefficient for each key. + KeyAggTagCoeff = []byte("KeyAgg coefficient") +) + +// sortableKeys defines a type of slice of public keys that implements the sort +// interface for BIP 340 keys. +type sortableKeys []*btcec.PublicKey + +// Less reports whether the element with index i must sort before the element +// with index j. +func (s sortableKeys) Less(i, j int) bool { + keyIBytes := schnorr.SerializePubKey(s[i]) + keyJBytes := schnorr.SerializePubKey(s[j]) + + return bytes.Compare(keyIBytes, keyJBytes) == -1 +} + +// Swap swaps the elements with indexes i and j. +func (s sortableKeys) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Len is the number of elements in the collection. +func (s sortableKeys) Len() int { + return len(s) +} + +// sortKeys takes a set of schnorr public keys and returns a new slice that is +// a copy of the keys sorted in lexicographical order bytes on the x-only +// pubkey serialization. +func sortKeys(keys []*btcec.PublicKey) []*btcec.PublicKey { + keySet := sortableKeys(keys) + if sort.IsSorted(keySet) { + return keys + } + + sort.Sort(keySet) + return keySet +} + +// keyHashFingerprint computes the tagged hash of the series of (sorted) public +// keys passed as input. This is used to compute the aggregation coefficient +// for each key. The final computation is: +// * H(tag=KeyAgg list, pk1 || pk2..) +func keyHashFingerprint(keys []*btcec.PublicKey, sort bool) []byte { + var keyBytes bytes.Buffer + + if sort { + keys = sortKeys(keys) + } + + for _, key := range keys { + keyBytes.Write(schnorr.SerializePubKey(key)) + } + + h := chainhash.TaggedHash(KeyAggTagList, keyBytes.Bytes()) + return h[:] +} + +// isSecondKey returns true if the passed public key is the second key in the +// (sorted) keySet passed. +func isSecondKey(keySet []*btcec.PublicKey, targetKey *btcec.PublicKey) bool { + // For this comparison, we want to compare the raw serialized version + // instead of the full pubkey, as it's possible we're dealing with a + // pubkey that _actually_ has an odd y coordinate. + equalBytes := func(a, b *btcec.PublicKey) bool { + return bytes.Equal( + schnorr.SerializePubKey(a), + schnorr.SerializePubKey(b), + ) + } + + for i := range keySet { + if !equalBytes(keySet[i], keySet[0]) { + return equalBytes(keySet[i], targetKey) + } + } + + return false +} + +// aggregationCoefficient computes the key aggregation coefficient for the +// specified target key. The coefficient is computed as: +// * H(tag=KeyAgg coefficient, keyHashFingerprint(pks) || pk) +func aggregationCoefficient(keySet []*btcec.PublicKey, + targetKey *btcec.PublicKey, sort bool) *btcec.ModNScalar { + + var mu btcec.ModNScalar + + // If this is the second key, then this coefficient is just one. + // + // TODO(roasbeef): use intermediate cache to keep track of the second + // key, can just store an index, otherwise this is O(n^2) + if isSecondKey(keySet, targetKey) { + return mu.SetInt(1) + } + + // Otherwise, we'll compute the full finger print hash for this given + // key and then use that to compute the coefficient tagged hash: + // * H(tag=KeyAgg coefficient, keyHashFingerprint(pks, pk) || pk) + var coefficientBytes bytes.Buffer + coefficientBytes.Write(keyHashFingerprint(keySet, sort)) + coefficientBytes.Write(schnorr.SerializePubKey(targetKey)) + + muHash := chainhash.TaggedHash(KeyAggTagCoeff, coefficientBytes.Bytes()) + + mu.SetByteSlice(muHash[:]) + + return &mu +} + +// TODO(roasbeef): make proper IsEven func + +// AggregateKeys takes a list of possibly unsorted keys and returns a single +// aggregated key as specified by the musig2 key aggregation algorithm. +func AggregateKeys(keys []*btcec.PublicKey, sort bool) *btcec.PublicKey { + // Sort the set of public key so we know we're working with them in + // sorted order for all the routines below. + if sort { + keys = sortKeys(keys) + } + + // For each key, we'll compute the intermediate blinded key: a_i*P_i, + // where a_i is the aggregation coefficient for that key, and P_i is + // the key itself, then accumulate that (addition) into the main final + // key: P = P_1 + P_2 ... P_N. + var finalKeyJ btcec.JacobianPoint + for _, key := range keys { + // Port the key over to Jacobian coordinates as we need it in + // this format for the routines below. + var keyJ btcec.JacobianPoint + key.AsJacobian(&keyJ) + + // Compute the aggregation coefficient for the key, then + // multiply it by the key itself: P_i' = a_i*P_i. + var tweakedKeyJ btcec.JacobianPoint + a := aggregationCoefficient(keys, key, sort) + btcec.ScalarMultNonConst(a, &keyJ, &tweakedKeyJ) + + // Finally accumulate this into the final key in an incremental + // fashion. + btcec.AddNonConst(&finalKeyJ, &tweakedKeyJ, &finalKeyJ) + } + + finalKeyJ.ToAffine() + return btcec.NewPublicKey(&finalKeyJ.X, &finalKeyJ.Y) +} From 8343e462a62e6aa6c5a19e4bf5a1e7eb8e94609a Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 1 Mar 2022 18:42:43 -0800 Subject: [PATCH 0672/1056] btcec/schnorr/musig2: add nonce generation & aggregation funcs In this commit, we add the ability to generate the secret+public nonces, as well as combine a series of nonces into a single combined nonce (which is used when doing multi signing). --- btcec/schnorr/musig2/nonces.go | 208 +++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 btcec/schnorr/musig2/nonces.go diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go new file mode 100644 index 0000000000..7f9339d217 --- /dev/null +++ b/btcec/schnorr/musig2/nonces.go @@ -0,0 +1,208 @@ +// Copyright 2013-2016 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package musig2 + +import ( + "crypto/rand" + + "github.com/btcsuite/btcd/btcec/v2" +) + +const ( + // PubNonceSize is the size of the public nonces. Each public nonce is + // serialized the full compressed encoding, which uses 32 bytes for each + // nonce. + PubNonceSize = 66 + + // SecNonceSize is the size of the secret nonces for musig2. The secret + // nonces are the corresponding private keys to the public nonce points. + SecNonceSize = 64 +) + +// Nonces holds the public and secret nonces required for musig2. +// +// TODO(roasbeef): methods on this to help w/ parsing, etc? +type Nonces struct { + // PubNonce holds the two 33-byte compressed encoded points that serve + // as the public set of nonces. + PubNonce [PubNonceSize]byte + + // SecNonce holds the two 32-byte scalar values that are the private + // keys to the two public nonces. + SecNonce [SecNonceSize]byte +} + +// secNonceToPubNonce takes our two secrete nonces, and produces their two +// corresponding EC points, serialized in compressed format. +func secNonceToPubNonce(secNonce *[SecNonceSize]byte) [PubNonceSize]byte { + var k1Mod, k2Mod btcec.ModNScalar + k1Mod.SetByteSlice(secNonce[:btcec.PrivKeyBytesLen]) + k2Mod.SetByteSlice(secNonce[btcec.PrivKeyBytesLen:]) + + var r1, r2 btcec.JacobianPoint + btcec.ScalarBaseMultNonConst(&k1Mod, &r1) + btcec.ScalarBaseMultNonConst(&k2Mod, &r2) + + // Next, we'll convert the key in jacobian format to a normal public + // key expressed in affine coordinates. + r1.ToAffine() + r2.ToAffine() + r1Pub := btcec.NewPublicKey(&r1.X, &r1.Y) + r2Pub := btcec.NewPublicKey(&r2.X, &r2.Y) + + var pubNonce [PubNonceSize]byte + + // The public nonces are serialized as: R1 || R2, where both keys are + // serialized in compressed format. + copy(pubNonce[:], r1Pub.SerializeCompressed()) + copy( + pubNonce[btcec.PubKeyBytesLenCompressed:], + r2Pub.SerializeCompressed(), + ) + + return pubNonce +} + +// NonceGenOption is a function option that allows callers to modify how nonce +// generation happens. +type NonceGenOption func(*nonceGenOpts) + +// nonceGenOpts is the set of options that control how nonce generation happens. +type nonceGenOpts struct { + randReader func(b []byte) (int, error) +} + +// defaultNonceGenOpts returns the default set of nonce generation options. +func defaultNonceGenOpts() *nonceGenOpts { + return &nonceGenOpts{ + // By default, we always use the crypto/rand reader, but the + // caller is able to specify their own generation, which can be + // useful for deterministic tests. + randReader: rand.Read, + } +} + +// GenNonces generates the secret nonces, as well as the public nonces which +// correspond to an EC point generated using the secret nonce as a private key. +func GenNonces(options ...NonceGenOption) (*Nonces, error) { + opts := defaultNonceGenOpts() + for _, opt := range options { + opt(opts) + } + + // Generate two 32-byte random values that'll be the private keys to + // the public nonces. + var k1, k2 [32]byte + if _, err := opts.randReader(k1[:]); err != nil { + return nil, err + } + if _, err := opts.randReader(k2[:]); err != nil { + return nil, err + } + + var nonces Nonces + + var k1Mod, k2Mod btcec.ModNScalar + k1Mod.SetBytes(&k1) + k2Mod.SetBytes(&k2) + + // The secret nonces are serialized as the concatenation of the two 32 + // byte secret nonce values. + k1Mod.PutBytesUnchecked(nonces.SecNonce[:]) + k2Mod.PutBytesUnchecked(nonces.SecNonce[btcec.PrivKeyBytesLen:]) + + // Next, we'll generate R_1 = k_1*G and R_2 = k_2*G. Along the way we + // need to map our nonce values into mod n scalars so we can work with + // the btcec API. + nonces.PubNonce = secNonceToPubNonce(nonces.SecNonce) + + return &nonces, nil +} + +// AggregateNonces aggregates the set of a pair of public nonces for each party +// into a single aggregated nonces to be used for multi-signing. +func AggregateNonces(pubNonces [][PubNonceSize]byte) ([PubNonceSize]byte, error) { + // combineNonces is a helper function that aggregates (adds) up a + // series of nonces encoded in compressed format. It uses a slicing + // function to extra 33 bytes at a time from the packed 2x public + // nonces. + type nonceSlicer func([PubNonceSize]byte) []byte + combineNonces := func(slicer nonceSlicer) (*btcec.PublicKey, error) { + // Convert the set of nonces into jacobian coordinates we can + // use to accumulate them all into each other. + pubNonceJs := make([]*btcec.JacobianPoint, len(pubNonces)) + for i, pubNonceBytes := range pubNonces { + // Using the slicer, extract just the bytes we need to + // decode. + var nonceJ btcec.JacobianPoint + pubNonce, err := btcec.ParsePubKey( + slicer(pubNonceBytes), + ) + if err != nil { + return nil, err + } + + pubNonce.AsJacobian(&nonceJ) + pubNonceJs[i] = &nonceJ + } + + // Now that we have the set of complete nonces, we'll aggregate + // them: R = R_i + R_i+1 + ... + R_i+n. + var aggregateNonce btcec.JacobianPoint + for _, pubNonceJ := range pubNonceJs { + btcec.AddNonConst( + &aggregateNonce, pubNonceJ, &aggregateNonce, + ) + } + + // Now that we've aggregated all the points, we need to check + // if this point is the point at infinity, if so, then we'll + // just return the generator. At a later step, the malicious + // party will be detected. + if aggregateNonce == infinityPoint { + // TODO(roasbeef): better way to get the generator w/ + // the new API? -- via old curve params instead? + var generator btcec.JacobianPoint + one := new(btcec.ModNScalar).SetInt(1) + btcec.ScalarBaseMultNonConst(one, &generator) + + generator.ToAffine() + return btcec.NewPublicKey( + &generator.X, &generator.Y, + ), nil + } + + aggregateNonce.ToAffine() + return btcec.NewPublicKey( + &aggregateNonce.X, &aggregateNonce.Y, + ), nil + } + + // The final nonce public nonce is actually two nonces, one that + // aggregate the first nonce of all the parties, and the other that + // aggregates the second nonce of all the parties. + var finalNonce [PubNonceSize]byte + combinedNonce1, err := combineNonces(func(n [PubNonceSize]byte) []byte { + return n[:btcec.PubKeyBytesLenCompressed] + }) + if err != nil { + return finalNonce, err + } + combinedNonce2, err := combineNonces(func(n [PubNonceSize]byte) []byte { + return n[btcec.PubKeyBytesLenCompressed:] + }) + if err != nil { + return finalNonce, err + } + + copy(finalNonce[:], combinedNonce1.SerializeCompressed()) + copy( + finalNonce[btcec.PubKeyBytesLenCompressed:], + combinedNonce2.SerializeCompressed(), + ) + + return finalNonce, nil +} From bb7ba7b1fc64f71fed963e043274a49b7ea60449 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 1 Mar 2022 18:43:49 -0800 Subject: [PATCH 0673/1056] btcec/schnorr/musig2: add partial sig generation, validation, and combination In this commit, we build on the prior two commits by adding the ability to generate partial musig2 signatures, validate them individually, and finally combine them into a single signature. Much of the logic here is unoptimized, and will be optimized in a later commit. In addition, we also want to eventually have a nicer API to support the book keeping necessary during multi signing. --- btcec/schnorr/musig2/nonces.go | 2 +- btcec/schnorr/musig2/sign.go | 423 +++++++++++++++++++++++++++++++++ 2 files changed, 424 insertions(+), 1 deletion(-) create mode 100644 btcec/schnorr/musig2/sign.go diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 7f9339d217..bebc327124 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -117,7 +117,7 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { // Next, we'll generate R_1 = k_1*G and R_2 = k_2*G. Along the way we // need to map our nonce values into mod n scalars so we can work with // the btcec API. - nonces.PubNonce = secNonceToPubNonce(nonces.SecNonce) + nonces.PubNonce = secNonceToPubNonce(&nonces.SecNonce) return &nonces, nil } diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go new file mode 100644 index 0000000000..3bce9f1561 --- /dev/null +++ b/btcec/schnorr/musig2/sign.go @@ -0,0 +1,423 @@ +// Copyright 2013-2016 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package musig2 + +import ( + "bytes" + "fmt" + + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +var ( + // NonceBlindTag is that tag used to construct the value b, which + // blinds the second public nonce of each party. + NonceBlindTag = []byte("MuSig/noncecoef") + + // ChallengeHashTag is the tag used to construct the challenge hash + ChallengeHashTag = []byte("BIP0340/challenge") + + // ErrNoncePointAtInfinity is returned if during signing, the fully + // combined public nonce is the point at infinity. + ErrNoncePointAtInfinity = fmt.Errorf("signing nonce is the infinity " + + "point") + + // ErrPrivKeyZero is returned when the private key for signing is + // actually zero. + ErrPrivKeyZero = fmt.Errorf("priv key is zero") + + // ErrPartialSigInvalid is returned when a partial is found to be + // invalid. + ErrPartialSigInvalid = fmt.Errorf("partial signature is invalid") + + // ErrSecretNonceZero is returned when a secret nonce is passed in a + // zero. + ErrSecretNonceZero = fmt.Errorf("secret nonce is blank") +) + +// infinityPoint is the jacobian representation of the point at infinity. +var infinityPoint btcec.JacobianPoint + +// PartialSignature reprints a partial (s-only) musig2 multi-signature. This +// isn't a valid schnorr signature by itself, as it needs to be aggregated +// along with the other partial signatures to be completed. +type PartialSignature struct { + S *btcec.ModNScalar + + R *btcec.PublicKey +} + +// NewPartialSignature returns a new instances of the partial sig struct. +func NewPartialSignature(s *btcec.ModNScalar, + r *btcec.PublicKey) PartialSignature { + + return PartialSignature{ + S: s, + R: r, + } +} + +// SignOption is a functional option argument that allows callers to modify the +// way we generate musig2 schnorr signatures. +type SignOption func(*signOptions) + +// signOptions houses the set of functional options that can be used to modify +// the method used to generate the musig2 partial signature. +type signOptions struct { + // fastSign determines if we'll skip the check at the end of the + // routine where we attempt to verify the produced signature. + fastSign bool + + // sortKeys determines if the set of keys should be sorted before doing + // key aggregation. + sortKeys bool +} + +// defaultSignOptions returns the default set of signing operations. +func defaultSignOptions() *signOptions { + return &signOptions{} +} + +// WithFastSign forces signing to skip the extra verification step at the end. +// Performance sensitive applications may opt to use this option to speed up +// the signing operation. +func WithFastSign() SignOption { + return func(o *signOptions) { + o.fastSign = true + } +} + +// WithSortedKeys determines if the set of signing public keys are to be sorted +// or not before doing key aggregation. +func WithSortedKeys() SignOption { + return func(o *signOptions) { + o.sortKeys = true + } +} + +// Sign generates a musig2 partial signature given the passed key set, secret +// nonce, public nonce, and private keys. This method returns an error if the +// generated nonces are either too large, or end up mapping to the point at +// infinity. +func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, + combinedNonce [PubNonceSize]byte, pubKeys []*btcec.PublicKey, + msg [32]byte, signOpts ...SignOption) (*PartialSignature, error) { + + // First, parse the set of optional signing options. + opts := defaultSignOptions() + for _, option := range signOpts { + option(opts) + } + + // Next, we'll parse the public nonces into R1 and R2. + r1, err := btcec.ParsePubKey( + combinedNonce[:btcec.PubKeyBytesLenCompressed], + ) + if err != nil { + return nil, err + } + r2, err := btcec.ParsePubKey( + combinedNonce[btcec.PubKeyBytesLenCompressed:], + ) + if err != nil { + return nil, err + } + + // Next we'll construct the aggregated public key based on the set of + // signers. + combinedKey := AggregateKeys(pubKeys, opts.sortKeys) + + // Next we'll compute the value b, that blinds our second public + // nonce: + // * b = h(tag=NonceBlindTag, combinedNonce || combinedKey || m). + var ( + nonceMsgBuf bytes.Buffer + nonceBlinder btcec.ModNScalar + ) + nonceMsgBuf.Write(combinedNonce[:]) + nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey)) + nonceMsgBuf.Write(msg[:]) + nonceBlindHash := chainhash.TaggedHash( + NonceBlindTag, nonceMsgBuf.Bytes(), + ) + nonceBlinder.SetByteSlice(nonceBlindHash[:]) + + var nonce, r1J, r2J btcec.JacobianPoint + r1.AsJacobian(&r1J) + r2.AsJacobian(&r2J) + + // With our nonce blinding value, we'll now combine both the public + // nonces, using the blinding factor to tweak the second nonce: + // * R = R_1 + b*R_2 + btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) + btcec.AddNonConst(&r1J, &r2J, &nonce) + + // If the combined nonce it eh point at infinity, then we'll bail out. + if nonce == infinityPoint { + return nil, ErrNoncePointAtInfinity + } + + // Next we'll parse out our two secret nonces, which we'll be using in + // the core signing process below. + var k1, k2 btcec.ModNScalar + k1.SetByteSlice(secNonce[:btcec.PrivKeyBytesLen]) + k2.SetByteSlice(secNonce[btcec.PrivKeyBytesLen:]) + + if k1.IsZero() || k2.IsZero() { + return nil, ErrSecretNonceZero + } + + nonce.ToAffine() + + nonceKey := btcec.NewPublicKey(&nonce.X, &nonce.Y) + + // If the nonce R has an odd y coordinate, then we'll negate both our + // secret nonces. + if nonce.Y.IsOdd() { + k1.Negate() + k2.Negate() + } + + privKeyScalar := privKey.Key + if privKeyScalar.IsZero() { + return nil, ErrPrivKeyZero + } + + // If the y coordinate of the public key is odd xor the y coordinate of + // the combined public key is odd, then we'll negate the private key. + pubKey := privKey.PubKey() + pubKeyYIsOdd := func() bool { + pubKeyBytes := pubKey.SerializeCompressed() + return pubKeyBytes[0] == secp.PubKeyFormatCompressedOdd + }() + combinedKeyYIsOdd := func() bool { + combinedKeyBytes := combinedKey.SerializeCompressed() + return combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd + }() + if pubKeyYIsOdd != combinedKeyYIsOdd { + privKeyScalar.Negate() + } + + // Next we'll create the challenge hash that commits to the combined + // nonce, combined public key and also the message: * e = + // H(tag=ChallengeHashTag, R || Q || m) mod n + var challengeMsg bytes.Buffer + challengeMsg.Write(schnorr.SerializePubKey(nonceKey)) + challengeMsg.Write(schnorr.SerializePubKey(combinedKey)) + challengeMsg.Write(msg[:]) + challengeBytes := chainhash.TaggedHash( + ChallengeHashTag, challengeMsg.Bytes(), + ) + var e btcec.ModNScalar + e.SetByteSlice(challengeBytes[:]) + + // Next, we'll compute mu, our aggregation coefficient for the key that + // we're signing with. + mu := aggregationCoefficient(pubKeys, pubKey, opts.sortKeys) + + // With mu constructed, we can finally generate our partial signature + // as: s = (k1_1 + b*k_2 + e*mu*d) mod n. + s := new(btcec.ModNScalar) + s.Add(&k1).Add(k2.Mul(&nonceBlinder)).Add(e.Mul(mu).Mul(&privKeyScalar)) + + sig := NewPartialSignature(s, nonceKey) + + // If we're not in fast sign mode, then we'll also validate our partial + // signature. + if !opts.fastSign { + pubNonce := secNonceToPubNonce(&secNonce) + sigValid := sig.Verify( + pubNonce, combinedNonce, pubKeys, pubKey, msg, + signOpts..., + ) + if !sigValid { + return nil, fmt.Errorf("sig is invalid!") + } + } + + return &sig, nil +} + +// Verify implements partial signature verification given the public nonce for +// the signer, aggregate nonce, signer set and finally the message being +// signed. +func (p *PartialSignature) Verify(pubNonce [PubNonceSize]byte, + combinedNonce [PubNonceSize]byte, keySet []*btcec.PublicKey, + signingKey *btcec.PublicKey, msg [32]byte, signOpts ...SignOption) bool { + + pubKey := schnorr.SerializePubKey(signingKey) + return verifyPartialSig( + p, pubNonce, combinedNonce, keySet, pubKey, msg, signOpts..., + ) == nil +} + +// verifyPartialSig attempts to verify a partial schnorr signature given the +// necessary parameters. This is the internal version of Verify that returns +// detailed errors. signed. +func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, + combinedNonce [PubNonceSize]byte, keySet []*btcec.PublicKey, + pubKey []byte, msg [32]byte, signOpts ...SignOption) error { + + opts := defaultSignOptions() + for _, option := range signOpts { + option(opts) + } + + // First we'll map the internal partial signature back into something + // we can manipulate. + s := partialSig.S + + // Next we'll parse out the two public nonces into something we can + // use. + // + // TODO(roasbeef): consolidate, new method + r1, err := btcec.ParsePubKey( + combinedNonce[:btcec.PubKeyBytesLenCompressed], + ) + if err != nil { + return err + } + r2, err := btcec.ParsePubKey( + combinedNonce[btcec.PubKeyBytesLenCompressed:], + ) + if err != nil { + return err + } + + // Next we'll construct the aggregated public key based on the set of + // signers. + combinedKey := AggregateKeys(keySet, opts.sortKeys) + + // Next we'll compute the value b, that blinds our second public + // nonce: + // * b = h(tag=NonceBlindTag, combinedNonce || combinedKey || m). + var ( + nonceMsgBuf bytes.Buffer + nonceBlinder btcec.ModNScalar + ) + nonceMsgBuf.Write(combinedNonce[:]) + nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey)) + nonceMsgBuf.Write(msg[:]) + nonceBlindHash := chainhash.TaggedHash(NonceBlindTag, nonceMsgBuf.Bytes()) + nonceBlinder.SetByteSlice(nonceBlindHash[:]) + + var nonce, r1J, r2J btcec.JacobianPoint + r1.AsJacobian(&r1J) + r2.AsJacobian(&r2J) + + // With our nonce blinding value, we'll now combine both the public + // nonces, using the blinding factor to tweak the second nonce: + // * R = R_1 + b*R_2 + btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) + btcec.AddNonConst(&r1J, &r2J, &nonce) + + // Next, we'll parse out the set of public nonces this signer used to + // generate the signature. + pubNonce1, err := btcec.ParsePubKey( + pubNonce[:btcec.PubKeyBytesLenCompressed], + ) + if err != nil { + return err + } + pubNonce2, err := btcec.ParsePubKey( + pubNonce[btcec.PubKeyBytesLenCompressed:], + ) + if err != nil { + return err + } + + // We'll perform a similar aggregation and blinding operator as we did + // above for the combined nonces: R' = R_1' + b*R_2'. + var pubNonceJ, pubNonce1J, pubNonce2J btcec.JacobianPoint + pubNonce1.AsJacobian(&pubNonce1J) + pubNonce2.AsJacobian(&pubNonce2J) + btcec.ScalarMultNonConst(&nonceBlinder, &pubNonce2J, &pubNonce2J) + btcec.AddNonConst(&pubNonce1J, &pubNonce2J, &pubNonceJ) + + nonce.ToAffine() + + // If the combined nonce used in the challenge hash has an odd y + // coordinate, then we'll negate our final public nonce. + // + // TODO(roasbeef): make into func + if nonce.Y.IsOdd() { + pubNonceJ.ToAffine() + pubNonceJ.Y.Negate(1) + pubNonceJ.Y.Normalize() + } + + // Next we'll create the challenge hash that commits to the combined + // nonce, combined public key and also the message: + // * e = H(tag=ChallengeHashTag, R || Q || m) mod n + var challengeMsg bytes.Buffer + challengeMsg.Write(schnorr.SerializePubKey(btcec.NewPublicKey( + &nonce.X, &nonce.Y, + ))) + challengeMsg.Write(schnorr.SerializePubKey(combinedKey)) + challengeMsg.Write(msg[:]) + challengeBytes := chainhash.TaggedHash( + ChallengeHashTag, challengeMsg.Bytes(), + ) + var e btcec.ModNScalar + e.SetByteSlice(challengeBytes[:]) + + signingKey, err := schnorr.ParsePubKey(pubKey) + if err != nil { + return err + } + + // Next, we'll compute mu, our aggregation coefficient for the key that + // we're signing with. + mu := aggregationCoefficient(keySet, signingKey, opts.sortKeys) + + // If the combined key has an odd y coordinate, then we'll negate the + // signer key. + var signKeyJ btcec.JacobianPoint + signingKey.AsJacobian(&signKeyJ) + combinedKeyBytes := combinedKey.SerializeCompressed() + if combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd { + signKeyJ.ToAffine() + signKeyJ.Y.Negate(1) + signKeyJ.Y.Normalize() + } + + // In the final set, we'll check that: s*G == R' + e*mu*P. + var sG, rP btcec.JacobianPoint + btcec.ScalarBaseMultNonConst(s, &sG) + btcec.ScalarMultNonConst(e.Mul(mu), &signKeyJ, &rP) + btcec.AddNonConst(&rP, &pubNonceJ, &rP) + + sG.ToAffine() + rP.ToAffine() + + if sG != rP { + return ErrPartialSigInvalid + } + + return nil +} + +// CombineSigs combines the set of public keys given the final aggregated +// nonce, and the series of partial signatures for each nonce. +func CombineSigs(combinedNonce *btcec.PublicKey, + partialSigs []*PartialSignature) *schnorr.Signature { + + var combinedSig btcec.ModNScalar + for _, partialSig := range partialSigs { + combinedSig.Add(partialSig.S) + } + + // TODO(roasbeef): less verbose way to get the x coord... + var nonceJ btcec.JacobianPoint + combinedNonce.AsJacobian(&nonceJ) + nonceJ.ToAffine() + + return schnorr.NewSignature(&nonceJ.X, &combinedSig) +} From d25f072e715ba4d32469d1fd680e807fa0bfcba6 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 1 Mar 2022 18:48:09 -0800 Subject: [PATCH 0674/1056] btcec/schnorr/musig2: add test vectors from secp256k1-zkp In this commit, we add test vectors which are extracted from the secp256k1-zkp/ codebase and match up with the current draft specification. --- btcec/schnorr/musig2/musig2_test.go | 252 ++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 btcec/schnorr/musig2/musig2_test.go diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go new file mode 100644 index 0000000000..0b56f916ea --- /dev/null +++ b/btcec/schnorr/musig2/musig2_test.go @@ -0,0 +1,252 @@ +// Copyright 2013-2016 The btcsuite developers +// Copyright (c) 2015-2021 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package musig2 + +import ( + "bytes" + "crypto/sha256" + "encoding/hex" + "fmt" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" +) + +// TestMuSig2SgnTestVectors tests that this implementation of musig2 matches +// the secp256k1-zkp test vectors. +func TestMuSig2SignTestVectors(t *testing.T) { + t.Parallel() +} + +var ( + key1Bytes, _ = hex.DecodeString("F9308A019258C31049344F85F89D5229B53" + + "1C845836F99B08601F113BCE036F9") + key2Bytes, _ = hex.DecodeString("DFF1D77F2A671C5F36183726DB2341BE58F" + + "EAE1DA2DECED843240F7B502BA659") + key3Bytes, _ = hex.DecodeString("3590A94E768F8E1815C2F24B4D80A8E3149" + + "316C3518CE7B7AD338368D038CA66") + + testKeys = [][]byte{key1Bytes, key2Bytes, key3Bytes} + + keyCombo1, _ = hex.DecodeString("E5830140512195D74C8307E39637CBE5FB730EBEAB80EC514CF88A877CEEEE0B") + keyCombo2, _ = hex.DecodeString("D70CD69A2647F7390973DF48CBFA2CCC407B8B2D60B08C5F1641185C7998A290") + keyCombo3, _ = hex.DecodeString("81A8B093912C9E481408D09776CEFB48AEB8B65481B6BAAFB3C5810106717BEB") + keyCombo4, _ = hex.DecodeString("2EB18851887E7BDC5E830E89B19DDBC28078F1FA88AAD0AD01CA06FE4F80210B") +) + +// TestMuSig2KeyAggTestVectors tests that this implementation of musig2 key +// aggregation lines up with the secp256k1-zkp test vectors. +func TestMuSig2KeyAggTestVectors(t *testing.T) { + t.Parallel() + + testCases := []struct { + keyOrder []int + expectedKey []byte + }{ + // Keys in backwards lexicographical order. + { + keyOrder: []int{0, 1, 2}, + expectedKey: keyCombo1, + }, + + // Keys in sorted order. + { + keyOrder: []int{2, 1, 0}, + expectedKey: keyCombo2, + }, + + // Only the first key. + { + keyOrder: []int{0, 0, 0}, + expectedKey: keyCombo3, + }, + + // Duplicate the first key and second keys. + { + keyOrder: []int{0, 0, 1, 1}, + expectedKey: keyCombo4, + }, + } + for i, testCase := range testCases { + testName := fmt.Sprintf("%v", testCase.keyOrder) + t.Run(testName, func(t *testing.T) { + var keys []*btcec.PublicKey + for _, keyIndex := range testCase.keyOrder { + keyBytes := testKeys[keyIndex] + pub, err := schnorr.ParsePubKey(keyBytes) + if err != nil { + t.Fatalf("unable to parse pubkeys: %v", err) + } + + keys = append(keys, pub) + } + + combinedKey := AggregateKeys(keys, false) + combinedKeyBytes := schnorr.SerializePubKey(combinedKey) + if !bytes.Equal(combinedKeyBytes, testCase.expectedKey) { + t.Fatalf("case: #%v, invalid aggregation: "+ + "expected %x, got %x", i, testCase.expectedKey, + combinedKeyBytes) + } + }) + } +} + +func mustParseHex(str string) []byte { + b, err := hex.DecodeString(str) + if err != nil { + panic(fmt.Errorf("unable to parse hex: %v", err)) + } + + return b +} + +func parseKey(xHex string) *btcec.PublicKey { + xB, err := hex.DecodeString(xHex) + if err != nil { + panic(err) + } + + var x, y btcec.FieldVal + x.SetByteSlice(xB) + if !btcec.DecompressY(&x, false, &y) { + panic("x not on curve") + } + y.Normalize() + + return btcec.NewPublicKey(&x, &y) +} + +var ( + signSetPrivKey, _ = btcec.PrivKeyFromBytes( + mustParseHex("7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671"), + ) + signSetPubKey, _ = schnorr.ParsePubKey(schnorr.SerializePubKey(signSetPrivKey.PubKey())) + + signTestMsg = mustParseHex("F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF") + + signSetKey2, _ = schnorr.ParsePubKey( + mustParseHex("F9308A019258C31049344F85F89D5229B531C845836F99B086" + + "01F113BCE036F9"), + ) + signSetKey3, _ = schnorr.ParsePubKey( + mustParseHex("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843" + + "240F7B502BA659"), + ) + + signSetKeys = []*btcec.PublicKey{signSetPubKey, signSetKey2, signSetKey3} +) + +// TestMuSig2SigningTestVectors tests that the musig2 implementation produces +// the same set of signatures. +func TestMuSig2SigningTestVectors(t *testing.T) { + t.Parallel() + + var aggregatedNonce [PubNonceSize]byte + copy( + aggregatedNonce[:], + mustParseHex("028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61"), + ) + copy( + aggregatedNonce[33:], + mustParseHex("037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9"), + ) + + var secNonce [SecNonceSize]byte + copy(secNonce[:], mustParseHex("508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61")) + copy(secNonce[32:], mustParseHex("FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7")) + + testCases := []struct { + keyOrder []int + expectedPartialSig []byte + }{ + { + keyOrder: []int{0, 1, 2}, + expectedPartialSig: mustParseHex("68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B"), + }, + { + keyOrder: []int{1, 0, 2}, + expectedPartialSig: mustParseHex("2DF67BFFF18E3DE797E13C6475C963048138DAEC5CB20A357CECA7C8424295EA"), + }, + + { + keyOrder: []int{1, 2, 0}, + expectedPartialSig: mustParseHex("0D5B651E6DE34A29A12DE7A8B4183B4AE6A7F7FBE15CDCAFA4A3D1BCAABC7517"), + }, + } + + var msg [32]byte + copy(msg[:], signTestMsg) + + for _, testCase := range testCases { + testName := fmt.Sprintf("%v", testCase.keyOrder) + t.Run(testName, func(t *testing.T) { + keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) + for _, keyIndex := range testCase.keyOrder { + keySet = append(keySet, signSetKeys[keyIndex]) + } + + partialSig, err := Sign( + secNonce, signSetPrivKey, aggregatedNonce, keySet, msg, + ) + if err != nil { + t.Fatalf("unable to generate partial sig: %v", err) + } + + var partialSigBytes [32]byte + partialSig.S.PutBytesUnchecked(partialSigBytes[:]) + + if !bytes.Equal(partialSigBytes[:], testCase.expectedPartialSig) { + t.Fatalf("sigs don't match: expected %x, got %x", + testCase.expectedPartialSig, partialSigBytes, + ) + } + }) + } +} + +type signer struct { + privKey *btcec.PrivateKey + pubKey *btcec.PublicKey + + nonces *Nonces + + partialSig *PartialSignature +} + +type signerSet []signer + +func (s signerSet) keys() []*btcec.PublicKey { + keys := make([]*btcec.PublicKey, len(s)) + for i := 0; i < len(s); i++ { + keys[i] = s[i].pubKey + } + + return keys +} + +func (s signerSet) partialSigs() []*PartialSignature { + sigs := make([]*PartialSignature, len(s)) + for i := 0; i < len(s); i++ { + sigs[i] = s[i].partialSig + } + + return sigs +} + +func (s signerSet) pubNonces() [][PubNonceSize]byte { + nonces := make([][PubNonceSize]byte, len(s)) + for i := 0; i < len(s); i++ { + nonces[i] = s[i].nonces.PubNonce + } + + return nonces +} + +func (s signerSet) combinedKey() *btcec.PublicKey { + return AggregateKeys(s.keys(), false) +} From 69a42a35663bfabd0219c0194b1a9468d6bf494d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 1 Mar 2022 18:49:05 -0800 Subject: [PATCH 0675/1056] btcec/schnorr/musig2: add multi-party signing test case w/ 100 signers In this commit, we add a final test case that exercises the act of generating partial signatures amongst 100 signers, combining them into a single signature, and finally verifying to make sure the final signature is valid. --- btcec/schnorr/musig2/musig2_test.go | 76 +++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 0b56f916ea..8e3d3931c5 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -250,3 +250,79 @@ func (s signerSet) pubNonces() [][PubNonceSize]byte { func (s signerSet) combinedKey() *btcec.PublicKey { return AggregateKeys(s.keys(), false) } + +// TestMuSigMultiParty tests that for a given set of 100 signers, we're able to +// properly generate valid sub signatures, which ultimately can be combined +// into a single valid signature. +func TestMuSigMultiParty(t *testing.T) { + t.Parallel() + + // First generate the private key, public key, and nonce for each + // signer. + numSigners := 100 + signers := make(signerSet, 0, numSigners) + for i := 0; i < numSigners; i++ { + privKey, err := btcec.NewPrivateKey() + if err != nil { + t.Fatalf("unable to gen priv key: %v", err) + } + + pubKey, err := schnorr.ParsePubKey( + schnorr.SerializePubKey(privKey.PubKey()), + ) + if err != nil { + t.Fatalf("unable to gen key: %v", err) + } + + nonces, err := GenNonces() + if err != nil { + t.Fatalf("unable to gen nonces: %v", err) + } + + signers = append(signers, signer{ + privKey: privKey, + pubKey: pubKey, + nonces: nonces, + }) + } + + msg := sha256.Sum256([]byte("let's get taprooty")) + + // With the set of nonces generated, we can now generate our aggregate + // nonce. + combinedNonce, err := AggregateNonces(signers.pubNonces()) + if err != nil { + t.Fatalf("unable to gen nonces: %v", err) + } + + signerKeys := signers.keys() + combinedKey := signers.combinedKey() + + // Now for the signing phase: each signer will generate their partial + // signature and stash that away. We'll also store the final nonce as + // well, since we'll need that to validate the signature. + var finalNonce *btcec.PublicKey + for i := range signers { + signer := signers[i] + partialSig, err := Sign( + signer.nonces.SecNonce, signer.privKey, combinedNonce, + signerKeys, msg, + ) + if err != nil { + t.Fatalf("unable to generate partial sig: %v", err) + } + + signers[i].partialSig = partialSig + + if finalNonce == nil { + finalNonce = partialSig.R + } + } + + // Finally we'll combined all the nonces, and ensure that it validates + // as a single schnorr signature. + finalSig := CombineSigs(finalNonce, signers.partialSigs()) + if !finalSig.Verify(msg[:], combinedKey) { + t.Fatalf("final sig is invalid!") + } +} From 4b46b2298a690c4153a073c903c0a0d381796a35 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 9 Mar 2022 18:25:21 -0800 Subject: [PATCH 0676/1056] btcec/schnorr/musig2: add benchmarks --- btcec/schnorr/musig2/bench_test.go | 314 +++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 btcec/schnorr/musig2/bench_test.go diff --git a/btcec/schnorr/musig2/bench_test.go b/btcec/schnorr/musig2/bench_test.go new file mode 100644 index 0000000000..8bb42247c5 --- /dev/null +++ b/btcec/schnorr/musig2/bench_test.go @@ -0,0 +1,314 @@ +// Copyright 2013-2016 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package musig2 + +import ( + "encoding/hex" + "fmt" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/decred/dcrd/dcrec/secp256k1/v4" +) + +var ( + testPrivBytes = hexToModNScalar("9e0699c91ca1e3b7e3c9ba71eb71c89890872be97576010fe593fbf3fd57e66d") + + testMsg = hexToBytes("c301ba9de5d6053caad9f5eb46523f007702add2c62fa39de03146a36b8026b7") +) + +func hexToBytes(s string) []byte { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + return b +} + +func hexToModNScalar(s string) *btcec.ModNScalar { + b, err := hex.DecodeString(s) + if err != nil { + panic("invalid hex in source file: " + s) + } + var scalar btcec.ModNScalar + if overflow := scalar.SetByteSlice(b); overflow { + panic("hex in source file overflows mod N scalar: " + s) + } + return &scalar +} + +func genSigner(t *testing.B) signer { + privKey, err := btcec.NewPrivateKey() + if err != nil { + t.Fatalf("unable to gen priv key: %v", err) + } + + pubKey, err := schnorr.ParsePubKey( + schnorr.SerializePubKey(privKey.PubKey()), + ) + if err != nil { + t.Fatalf("unable to gen key: %v", err) + } + + nonces, err := GenNonces() + if err != nil { + t.Fatalf("unable to gen nonces: %v", err) + } + + return signer{ + privKey: privKey, + pubKey: pubKey, + nonces: nonces, + } +} + +var ( + testSig *PartialSignature + testErr error +) + +// BenchmarkPartialSign benchmarks how long it takes to generate a partial +// signature factoring in if the keys are sorted and also if we're in fast sign +// mode. +func BenchmarkPartialSign(b *testing.B) { + privKey := secp256k1.NewPrivateKey(testPrivBytes) + + for _, numSigners := range []int{10, 100} { + for _, fastSign := range []bool{true, false} { + for _, sortKeys := range []bool{true, false} { + name := fmt.Sprintf("num_signers=%v/fast_sign=%v/sort=%v", + numSigners, fastSign, sortKeys) + + nonces, err := GenNonces() + if err != nil { + b.Fatalf("unable to generate nonces: %v", err) + } + + signers := make(signerSet, numSigners) + for i := 0; i < numSigners; i++ { + signers[i] = genSigner(b) + } + + combinedNonce, err := AggregateNonces(signers.pubNonces()) + if err != nil { + b.Fatalf("unable to generate combined nonce: %v", err) + } + + var sig *PartialSignature + + var msg [32]byte + copy(msg[:], testMsg[:]) + + keys := signers.keys() + + b.Run(name, func(b *testing.B) { + var signOpts []SignOption + if fastSign { + signOpts = append(signOpts, WithFastSign()) + } + if sortKeys { + signOpts = append(signOpts, WithSortedKeys()) + } + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + sig, err = Sign( + nonces.SecNonce, privKey, combinedNonce, + keys, msg, signOpts..., + ) + } + + testSig = sig + testErr = err + }) + } + } + } +} + +// TODO(roasbeef): add impact of sorting ^ + +var sigOk bool + +// BenchmarkPartialVerify benchmarks how long it takes to verify a partial +// signature. +func BenchmarkPartialVerify(b *testing.B) { + privKey := secp256k1.NewPrivateKey(testPrivBytes) + + for _, numSigners := range []int{10, 100} { + for _, sortKeys := range []bool{true, false} { + name := fmt.Sprintf("sort_keys=%v/num_signers=%v", + sortKeys, numSigners) + + nonces, err := GenNonces() + if err != nil { + b.Fatalf("unable to generate nonces: %v", err) + } + + signers := make(signerSet, numSigners) + for i := 0; i < numSigners; i++ { + signers[i] = genSigner(b) + } + + combinedNonce, err := AggregateNonces( + signers.pubNonces(), + ) + if err != nil { + b.Fatalf("unable to generate combined "+ + "nonce: %v", err) + } + + var sig *PartialSignature + + var msg [32]byte + copy(msg[:], testMsg[:]) + + b.ReportAllocs() + b.ResetTimer() + + sig, err = Sign( + nonces.SecNonce, privKey, combinedNonce, + signers.keys(), msg, WithFastSign(), + ) + + keys := signers.keys() + pubKey := privKey.PubKey() + + b.Run(name, func(b *testing.B) { + var signOpts []SignOption + if sortKeys { + signOpts = append( + signOpts, WithSortedKeys(), + ) + } + + b.ResetTimer() + b.ReportAllocs() + + var ok bool + for i := 0; i < b.N; i++ { + ok = sig.Verify( + nonces.PubNonce, combinedNonce, + keys, pubKey, msg, + ) + } + sigOk = ok + }) + + } + } +} + +var finalSchnorrSig *schnorr.Signature + +// BenchmarkCombineSigs benchmarks how long it takes to combine a set amount of +// signatures. +func BenchmarkCombineSigs(b *testing.B) { + + for _, numSigners := range []int{10, 100} { + signers := make(signerSet, numSigners) + for i := 0; i < numSigners; i++ { + signers[i] = genSigner(b) + } + + combinedNonce, err := AggregateNonces(signers.pubNonces()) + if err != nil { + b.Fatalf("unable to generate combined nonce: %v", err) + } + + var msg [32]byte + copy(msg[:], testMsg[:]) + + var finalNonce *btcec.PublicKey + for i := range signers { + signer := signers[i] + partialSig, err := Sign( + signer.nonces.SecNonce, signer.privKey, + combinedNonce, signers.keys(), msg, + ) + if err != nil { + b.Fatalf("unable to generate partial sig: %v", + err) + } + + signers[i].partialSig = partialSig + + if finalNonce == nil { + finalNonce = partialSig.R + } + } + + sigs := signers.partialSigs() + + name := fmt.Sprintf("num_signers=%v", numSigners) + b.Run(name, func(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + + finalSig := CombineSigs(finalNonce, sigs) + + finalSchnorrSig = finalSig + }) + } +} + +var testNonce [PubNonceSize]byte + +// BenchmarkAggregateNonces benchmarks how long it takes to combine nonces. +func BenchmarkAggregateNonces(b *testing.B) { + for _, numSigners := range []int{10, 100} { + signers := make(signerSet, numSigners) + for i := 0; i < numSigners; i++ { + signers[i] = genSigner(b) + } + + nonces := signers.pubNonces() + + name := fmt.Sprintf("num_signers=%v", numSigners) + b.Run(name, func(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + + pubNonce, err := AggregateNonces(nonces) + if err != nil { + b.Fatalf("unable to generate nonces: %v", err) + } + + testNonce = pubNonce + }) + } +} + +var testKey *btcec.PublicKey + +// BenchmarkAggregateKeys benchmarks how long it takes to aggregate public +// keys. +func BenchmarkAggregateKeys(b *testing.B) { + for _, numSigners := range []int{10, 100} { + for _, sortKeys := range []bool{true, false} { + signers := make(signerSet, numSigners) + for i := 0; i < numSigners; i++ { + signers[i] = genSigner(b) + } + + signerKeys := signers.keys() + + name := fmt.Sprintf("num_signers=%v/sort_keys=%v", + numSigners, sortKeys) + + b.Run(name, func(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + + aggKey := AggregateKeys(signerKeys, sortKeys) + + testKey = aggKey + }) + } + } +} From e85e7c3ac72eb14617e781d70bc057a5f4d49b44 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 10 Mar 2022 18:47:52 -0800 Subject: [PATCH 0677/1056] btcec/schnorr/musig2: optimize signing+verification In this commit, we optimize signing+verification mainly by only computing values once, and reducing allocations when possible. The following optimizations have been implemented: * Use a single buffer allocation in keyHashFingerprint to avoid dynamic buffer growth+re-sizing * Remove the isSecondKey computation and replace that with a single routine that computes the index of the second unique key. * Optimize keyHashFingerprint usage by only computing it once during signing +verification. A further optimization is possible: use the x coordinate of a key for comparisons instead of computing the full sexualision. We need to do the latter atm, as the X() method of the public key struct will allocate more memory as it allocate and sets the buffer in place. The final benchmarks of before and after this commit: benchmark old ns/op new ns/op delta BenchmarkPartialSign/num_signers=10/fast_sign=true/sort=true-8 1227374 1194047 -2.72% BenchmarkPartialSign/num_signers=10/fast_sign=true/sort=false-8 1217743 1191468 -2.16% BenchmarkPartialSign/num_signers=10/fast_sign=false/sort=true-8 2755544 2698827 -2.06% BenchmarkPartialSign/num_signers=10/fast_sign=false/sort=false-8 2754749 2694547 -2.19% BenchmarkPartialSign/num_signers=100/fast_sign=true/sort=true-8 12382654 10561204 -14.71% BenchmarkPartialSign/num_signers=100/fast_sign=true/sort=false-8 12260134 10315376 -15.86% BenchmarkPartialSign/num_signers=100/fast_sign=false/sort=true-8 24832061 22009935 -11.36% BenchmarkPartialSign/num_signers=100/fast_sign=false/sort=false-8 24650086 21022833 -14.71% BenchmarkPartialVerify/sort_keys=true/num_signers=10-8 1485787 1473377 -0.84% BenchmarkPartialVerify/sort_keys=false/num_signers=10-8 1447275 1465139 +1.23% BenchmarkPartialVerify/sort_keys=true/num_signers=100-8 12503482 10672618 -14.64% BenchmarkPartialVerify/sort_keys=false/num_signers=100-8 12388289 10581398 -14.59% BenchmarkCombineSigs/num_signers=10-8 0.00 0.00 +0.00% BenchmarkCombineSigs/num_signers=100-8 0.00 0.00 -1.95% BenchmarkAggregateNonces/num_signers=10-8 0.00 0.00 -0.76% BenchmarkAggregateNonces/num_signers=100-8 0.00 0.00 +1.13% BenchmarkAggregateKeys/num_signers=10/sort_keys=true-8 0.00 0.00 -0.09% BenchmarkAggregateKeys/num_signers=10/sort_keys=false-8 0.00 0.01 +559.94% BenchmarkAggregateKeys/num_signers=100/sort_keys=true-8 0.01 0.01 -11.30% BenchmarkAggregateKeys/num_signers=100/sort_keys=false-8 0.01 0.01 -11.66% benchmark old allocs new allocs delta BenchmarkPartialSign/num_signers=10/fast_sign=true/sort=true-8 458 269 -41.27% BenchmarkPartialSign/num_signers=10/fast_sign=true/sort=false-8 409 222 -45.72% BenchmarkPartialSign/num_signers=10/fast_sign=false/sort=true-8 892 524 -41.26% BenchmarkPartialSign/num_signers=10/fast_sign=false/sort=false-8 841 467 -44.47% BenchmarkPartialSign/num_signers=100/fast_sign=true/sort=true-8 14366 3089 -78.50% BenchmarkPartialSign/num_signers=100/fast_sign=true/sort=false-8 13143 1842 -85.98% BenchmarkPartialSign/num_signers=100/fast_sign=false/sort=true-8 27596 4964 -82.01% BenchmarkPartialSign/num_signers=100/fast_sign=false/sort=false-8 26309 3707 -85.91% BenchmarkPartialVerify/sort_keys=true/num_signers=10-8 430 243 -43.49% BenchmarkPartialVerify/sort_keys=false/num_signers=10-8 430 243 -43.49% BenchmarkPartialVerify/sort_keys=true/num_signers=100-8 13164 1863 -85.85% BenchmarkPartialVerify/sort_keys=false/num_signers=100-8 13164 1863 -85.85% BenchmarkCombineSigs/num_signers=10-8 0 0 +0.00% BenchmarkCombineSigs/num_signers=100-8 0 0 +0.00% BenchmarkAggregateNonces/num_signers=10-8 0 0 +0.00% BenchmarkAggregateNonces/num_signers=100-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=10/sort_keys=true-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=10/sort_keys=false-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=100/sort_keys=true-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=100/sort_keys=false-8 0 0 +0.00% benchmark old bytes new bytes delta BenchmarkPartialSign/num_signers=10/fast_sign=true/sort=true-8 27854 14878 -46.59% BenchmarkPartialSign/num_signers=10/fast_sign=true/sort=false-8 25508 12605 -50.58% BenchmarkPartialSign/num_signers=10/fast_sign=false/sort=true-8 54982 29476 -46.39% BenchmarkPartialSign/num_signers=10/fast_sign=false/sort=false-8 52581 26805 -49.02% BenchmarkPartialSign/num_signers=100/fast_sign=true/sort=true-8 1880138 166996 -91.12% BenchmarkPartialSign/num_signers=100/fast_sign=true/sort=false-8 1820561 106295 -94.16% BenchmarkPartialSign/num_signers=100/fast_sign=false/sort=true-8 3706291 275344 -92.57% BenchmarkPartialSign/num_signers=100/fast_sign=false/sort=false-8 3642725 214122 -94.12% BenchmarkPartialVerify/sort_keys=true/num_signers=10-8 26995 14078 -47.85% BenchmarkPartialVerify/sort_keys=false/num_signers=10-8 26980 14078 -47.82% BenchmarkPartialVerify/sort_keys=true/num_signers=100-8 1822043 107767 -94.09% BenchmarkPartialVerify/sort_keys=false/num_signers=100-8 1822046 107752 -94.09% BenchmarkCombineSigs/num_signers=10-8 0 0 +0.00% BenchmarkCombineSigs/num_signers=100-8 0 0 +0.00% BenchmarkAggregateNonces/num_signers=10-8 0 0 +0.00% BenchmarkAggregateNonces/num_signers=100-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=10/sort_keys=true-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=10/sort_keys=false-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=100/sort_keys=true-8 0 0 +0.00% BenchmarkAggregateKeys/num_signers=100/sort_keys=false-8 0 0 +0.00% --- btcec/schnorr/musig2/bench_test.go | 7 +- btcec/schnorr/musig2/keys.go | 134 ++++++++++++++++++++-------- btcec/schnorr/musig2/musig2_test.go | 10 ++- btcec/schnorr/musig2/sign.go | 27 ++++-- 4 files changed, 134 insertions(+), 44 deletions(-) diff --git a/btcec/schnorr/musig2/bench_test.go b/btcec/schnorr/musig2/bench_test.go index 8bb42247c5..6d008641a7 100644 --- a/btcec/schnorr/musig2/bench_test.go +++ b/btcec/schnorr/musig2/bench_test.go @@ -301,11 +301,16 @@ func BenchmarkAggregateKeys(b *testing.B) { name := fmt.Sprintf("num_signers=%v/sort_keys=%v", numSigners, sortKeys) + uniqueKeyIndex := secondUniqueKeyIndex(signerKeys) + b.Run(name, func(b *testing.B) { b.ResetTimer() b.ReportAllocs() - aggKey := AggregateKeys(signerKeys, sortKeys) + aggKey := AggregateKeys( + signerKeys, sortKeys, + WithUniqueKeyIndex(uniqueKeyIndex), + ) testKey = aggKey }) diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index f69cc31063..2d0f26e022 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -28,6 +28,7 @@ type sortableKeys []*btcec.PublicKey // Less reports whether the element with index i must sort before the element // with index j. func (s sortableKeys) Less(i, j int) bool { + // TODO(roasbeef): more efficient way to compare... keyIBytes := schnorr.SerializePubKey(s[i]) keyJBytes := schnorr.SerializePubKey(s[j]) @@ -62,12 +63,14 @@ func sortKeys(keys []*btcec.PublicKey) []*btcec.PublicKey { // for each key. The final computation is: // * H(tag=KeyAgg list, pk1 || pk2..) func keyHashFingerprint(keys []*btcec.PublicKey, sort bool) []byte { - var keyBytes bytes.Buffer - if sort { keys = sortKeys(keys) } + // We'll create a single buffer and slice into that so the bytes buffer + // doesn't continually need to grow the underlying buffer. + keyAggBuf := make([]byte, 32*len(keys)) + keyBytes := bytes.NewBuffer(keyAggBuf[0:0]) for _, key := range keys { keyBytes.Write(schnorr.SerializePubKey(key)) } @@ -76,69 +79,128 @@ func keyHashFingerprint(keys []*btcec.PublicKey, sort bool) []byte { return h[:] } -// isSecondKey returns true if the passed public key is the second key in the -// (sorted) keySet passed. -func isSecondKey(keySet []*btcec.PublicKey, targetKey *btcec.PublicKey) bool { - // For this comparison, we want to compare the raw serialized version - // instead of the full pubkey, as it's possible we're dealing with a - // pubkey that _actually_ has an odd y coordinate. - equalBytes := func(a, b *btcec.PublicKey) bool { - return bytes.Equal( - schnorr.SerializePubKey(a), - schnorr.SerializePubKey(b), - ) - } - - for i := range keySet { - if !equalBytes(keySet[i], keySet[0]) { - return equalBytes(keySet[i], targetKey) - } - } - - return false +// keyBytesEqual returns true if two keys are the same from the PoV of BIP +// 340's 32-byte x-only public keys. +func keyBytesEqual(a, b *btcec.PublicKey) bool { + return bytes.Equal( + schnorr.SerializePubKey(a), + schnorr.SerializePubKey(b), + ) } // aggregationCoefficient computes the key aggregation coefficient for the // specified target key. The coefficient is computed as: // * H(tag=KeyAgg coefficient, keyHashFingerprint(pks) || pk) func aggregationCoefficient(keySet []*btcec.PublicKey, - targetKey *btcec.PublicKey, sort bool) *btcec.ModNScalar { + targetKey *btcec.PublicKey, keysHash []byte, + secondKeyIdx int) *btcec.ModNScalar { var mu btcec.ModNScalar // If this is the second key, then this coefficient is just one. - // - // TODO(roasbeef): use intermediate cache to keep track of the second - // key, can just store an index, otherwise this is O(n^2) - if isSecondKey(keySet, targetKey) { + if secondKeyIdx != -1 && keyBytesEqual(keySet[secondKeyIdx], targetKey) { return mu.SetInt(1) } // Otherwise, we'll compute the full finger print hash for this given // key and then use that to compute the coefficient tagged hash: // * H(tag=KeyAgg coefficient, keyHashFingerprint(pks, pk) || pk) - var coefficientBytes bytes.Buffer - coefficientBytes.Write(keyHashFingerprint(keySet, sort)) - coefficientBytes.Write(schnorr.SerializePubKey(targetKey)) + var coefficientBytes [64]byte + copy(coefficientBytes[:], keysHash[:]) + copy(coefficientBytes[32:], schnorr.SerializePubKey(targetKey)) - muHash := chainhash.TaggedHash(KeyAggTagCoeff, coefficientBytes.Bytes()) + muHash := chainhash.TaggedHash(KeyAggTagCoeff, coefficientBytes[:]) mu.SetByteSlice(muHash[:]) return &mu } -// TODO(roasbeef): make proper IsEven func +// secondUniqueKeyIndex returns the index of the second unique key. If all keys +// are the same, then a value of -1 is returned. +func secondUniqueKeyIndex(keySet []*btcec.PublicKey) int { + // Find the first key that isn't the same as the very first key (second + // unique key). + for i := range keySet { + if !keyBytesEqual(keySet[i], keySet[0]) { + return i + } + } + + // A value of negative one is used to indicate that all the keys in the + // sign set are actually equal, which in practice actually makes musig2 + // useless, but we need a value to distinguish this case. + return -1 +} + +// KeyAggOption is a functional option argument that allows callers to specify +// more or less information that has been pre-computed to the main routine. +type KeyAggOption func(*keyAggOption) + +// keyAggOption houses the set of functional options that modify key +// aggregation. +type keyAggOption struct { + // keyHash is the output of keyHashFingerprint for a given set of keys. + keyHash []byte + + // uniqueKeyIndex is the pre-computed index of the second unique key. + uniqueKeyIndex *int +} + +// WithKeysHash allows key aggregation to be optimize, by allowing the caller +// to specify the hash of all the keys. +func WithKeysHash(keyHash []byte) KeyAggOption { + return func(o *keyAggOption) { + o.keyHash = keyHash + } +} + +// WithUniqueKeyIndex allows the caller to specify the index of the second +// unique key. +func WithUniqueKeyIndex(idx int) KeyAggOption { + return func(o *keyAggOption) { + i := idx + o.uniqueKeyIndex = &i + } +} + +// defaultKeyAggOptions returns the set of default arguments for key +// aggregation. +func defaultKeyAggOptions() *keyAggOption { + return &keyAggOption{} +} // AggregateKeys takes a list of possibly unsorted keys and returns a single -// aggregated key as specified by the musig2 key aggregation algorithm. -func AggregateKeys(keys []*btcec.PublicKey, sort bool) *btcec.PublicKey { +// aggregated key as specified by the musig2 key aggregation algorithm. A nil +// value can be passed for keyHash, which causes this function to re-derive it. +func AggregateKeys(keys []*btcec.PublicKey, sort bool, + keyOpts ...KeyAggOption) *btcec.PublicKey { + + // First, parse the set of optional signing options. + opts := defaultKeyAggOptions() + for _, option := range keyOpts { + option(opts) + } + // Sort the set of public key so we know we're working with them in // sorted order for all the routines below. if sort { keys = sortKeys(keys) } + // The caller may provide the hash of all the keys as an optimization + // during signing, as it already needs to be computed. + if opts.keyHash == nil { + opts.keyHash = keyHashFingerprint(keys, sort) + } + + // A caller may also specify the unique key index themselves so we + // don't need to re-compute it. + if opts.uniqueKeyIndex == nil { + idx := secondUniqueKeyIndex(keys) + opts.uniqueKeyIndex = &idx + } + // For each key, we'll compute the intermediate blinded key: a_i*P_i, // where a_i is the aggregation coefficient for that key, and P_i is // the key itself, then accumulate that (addition) into the main final @@ -153,7 +215,9 @@ func AggregateKeys(keys []*btcec.PublicKey, sort bool) *btcec.PublicKey { // Compute the aggregation coefficient for the key, then // multiply it by the key itself: P_i' = a_i*P_i. var tweakedKeyJ btcec.JacobianPoint - a := aggregationCoefficient(keys, key, sort) + a := aggregationCoefficient( + keys, key, opts.keyHash, *opts.uniqueKeyIndex, + ) btcec.ScalarMultNonConst(a, &keyJ, &tweakedKeyJ) // Finally accumulate this into the final key in an incremental diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 8e3d3931c5..edbff0b838 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -85,7 +85,10 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { keys = append(keys, pub) } - combinedKey := AggregateKeys(keys, false) + uniqueKeyIndex := secondUniqueKeyIndex(keys) + combinedKey := AggregateKeys( + keys, false, WithUniqueKeyIndex(uniqueKeyIndex), + ) combinedKeyBytes := schnorr.SerializePubKey(combinedKey) if !bytes.Equal(combinedKeyBytes, testCase.expectedKey) { t.Fatalf("case: #%v, invalid aggregation: "+ @@ -248,7 +251,10 @@ func (s signerSet) pubNonces() [][PubNonceSize]byte { } func (s signerSet) combinedKey() *btcec.PublicKey { - return AggregateKeys(s.keys(), false) + uniqueKeyIndex := secondUniqueKeyIndex(s.keys()) + return AggregateKeys( + s.keys(), false, WithUniqueKeyIndex(uniqueKeyIndex), + ) } // TestMuSigMultiParty tests that for a given set of 100 signers, we're able to diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 3bce9f1561..11edcf8469 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -130,9 +130,17 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, return nil, err } + // Compute the hash of all the keys here as we'll need it do aggregrate + // the keys and also at the final step of signing. + keysHash := keyHashFingerprint(pubKeys, opts.sortKeys) + // Next we'll construct the aggregated public key based on the set of // signers. - combinedKey := AggregateKeys(pubKeys, opts.sortKeys) + uniqueKeyIndex := secondUniqueKeyIndex(pubKeys) + combinedKey := AggregateKeys( + pubKeys, opts.sortKeys, WithKeysHash(keysHash), + WithUniqueKeyIndex(uniqueKeyIndex), + ) // Next we'll compute the value b, that blinds our second public // nonce: @@ -220,7 +228,7 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, // Next, we'll compute mu, our aggregation coefficient for the key that // we're signing with. - mu := aggregationCoefficient(pubKeys, pubKey, opts.sortKeys) + mu := aggregationCoefficient(pubKeys, pubKey, keysHash, uniqueKeyIndex) // With mu constructed, we can finally generate our partial signature // as: s = (k1_1 + b*k_2 + e*mu*d) mod n. @@ -291,9 +299,18 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, return err } + // Compute the hash of all the keys here as we'll need it do aggregrate + // the keys and also at the final step of verification. + keysHash := keyHashFingerprint(keySet, opts.sortKeys) + + uniqueKeyIndex := secondUniqueKeyIndex(keySet) + // Next we'll construct the aggregated public key based on the set of // signers. - combinedKey := AggregateKeys(keySet, opts.sortKeys) + combinedKey := AggregateKeys( + keySet, opts.sortKeys, + WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + ) // Next we'll compute the value b, that blinds our second public // nonce: @@ -345,8 +362,6 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // If the combined nonce used in the challenge hash has an odd y // coordinate, then we'll negate our final public nonce. - // - // TODO(roasbeef): make into func if nonce.Y.IsOdd() { pubNonceJ.ToAffine() pubNonceJ.Y.Negate(1) @@ -375,7 +390,7 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // Next, we'll compute mu, our aggregation coefficient for the key that // we're signing with. - mu := aggregationCoefficient(keySet, signingKey, opts.sortKeys) + mu := aggregationCoefficient(keySet, signingKey, keysHash, uniqueKeyIndex) // If the combined key has an odd y coordinate, then we'll negate the // signer key. From 743cbc840313efc82241252ba7e350bdfdae39b7 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 11 Mar 2022 19:00:33 -0800 Subject: [PATCH 0678/1056] btcec/schnorr/musig2: add safer signing API with Session+Context In this commit, we introduce an easier to use API for musig2 signing in the Session and Context structs. The Context struct represents a particular musig2 signing context which is defined by the set of signers. The struct can be serialized to disk as it contains no volatile information. A given context can be kept for each signer in the final set. The Session struct represents an ephemeral musig2 signing session. It handles nonce generation, key aggregation, nonce combination, signature combination, and final sig verification all in one API. The API also protects against nonce generation by not exposing nonces to the end user and also attempting to catch nonce re-use (assuming no process forking) across sessions. --- btcec/schnorr/musig2/bench_test.go | 40 ++-- btcec/schnorr/musig2/context.go | 305 ++++++++++++++++++++++++++++ btcec/schnorr/musig2/keys.go | 8 +- btcec/schnorr/musig2/musig2_test.go | 126 ++++++++---- btcec/schnorr/musig2/nonces.go | 13 +- btcec/schnorr/musig2/sign.go | 45 +++- btcec/schnorr/signature.go | 5 +- 7 files changed, 459 insertions(+), 83 deletions(-) create mode 100644 btcec/schnorr/musig2/context.go diff --git a/btcec/schnorr/musig2/bench_test.go b/btcec/schnorr/musig2/bench_test.go index 6d008641a7..c02ccf3e41 100644 --- a/btcec/schnorr/musig2/bench_test.go +++ b/btcec/schnorr/musig2/bench_test.go @@ -1,4 +1,4 @@ -// Copyright 2013-2016 The btcsuite developers +// Copyright 2013-2022 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -11,7 +11,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/decred/dcrd/dcrec/secp256k1/v4" ) var ( @@ -74,19 +73,12 @@ var ( // signature factoring in if the keys are sorted and also if we're in fast sign // mode. func BenchmarkPartialSign(b *testing.B) { - privKey := secp256k1.NewPrivateKey(testPrivBytes) - for _, numSigners := range []int{10, 100} { for _, fastSign := range []bool{true, false} { for _, sortKeys := range []bool{true, false} { name := fmt.Sprintf("num_signers=%v/fast_sign=%v/sort=%v", numSigners, fastSign, sortKeys) - nonces, err := GenNonces() - if err != nil { - b.Fatalf("unable to generate nonces: %v", err) - } - signers := make(signerSet, numSigners) for i := 0; i < numSigners; i++ { signers[i] = genSigner(b) @@ -118,9 +110,12 @@ func BenchmarkPartialSign(b *testing.B) { for i := 0; i < b.N; i++ { sig, err = Sign( - nonces.SecNonce, privKey, combinedNonce, - keys, msg, signOpts..., + signers[0].nonces.SecNonce, signers[0].privKey, + combinedNonce, keys, msg, signOpts..., ) + if err != nil { + b.Fatalf("unable to generate sig: %v", err) + } } testSig = sig @@ -138,18 +133,11 @@ var sigOk bool // BenchmarkPartialVerify benchmarks how long it takes to verify a partial // signature. func BenchmarkPartialVerify(b *testing.B) { - privKey := secp256k1.NewPrivateKey(testPrivBytes) - for _, numSigners := range []int{10, 100} { for _, sortKeys := range []bool{true, false} { name := fmt.Sprintf("sort_keys=%v/num_signers=%v", sortKeys, numSigners) - nonces, err := GenNonces() - if err != nil { - b.Fatalf("unable to generate nonces: %v", err) - } - signers := make(signerSet, numSigners) for i := 0; i < numSigners; i++ { signers[i] = genSigner(b) @@ -172,12 +160,15 @@ func BenchmarkPartialVerify(b *testing.B) { b.ResetTimer() sig, err = Sign( - nonces.SecNonce, privKey, combinedNonce, - signers.keys(), msg, WithFastSign(), + signers[0].nonces.SecNonce, signers[0].privKey, + combinedNonce, signers.keys(), msg, ) + if err != nil { + b.Fatalf("unable to generate sig: %v", err) + } keys := signers.keys() - pubKey := privKey.PubKey() + pubKey := signers[0].pubKey b.Run(name, func(b *testing.B) { var signOpts []SignOption @@ -193,9 +184,12 @@ func BenchmarkPartialVerify(b *testing.B) { var ok bool for i := 0; i < b.N; i++ { ok = sig.Verify( - nonces.PubNonce, combinedNonce, + signers[0].nonces.PubNonce, combinedNonce, keys, pubKey, msg, ) + if !ok { + b.Fatalf("generated invalid sig!") + } } sigOk = ok }) @@ -301,7 +295,7 @@ func BenchmarkAggregateKeys(b *testing.B) { name := fmt.Sprintf("num_signers=%v/sort_keys=%v", numSigners, sortKeys) - uniqueKeyIndex := secondUniqueKeyIndex(signerKeys) + uniqueKeyIndex := secondUniqueKeyIndex(signerKeys, false) b.Run(name, func(b *testing.B) { b.ResetTimer() diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go new file mode 100644 index 0000000000..22bd2b236f --- /dev/null +++ b/btcec/schnorr/musig2/context.go @@ -0,0 +1,305 @@ +// Copyright (c) 2013-2022 The btcsuite developers + +package musig2 + +import ( + "fmt" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" +) + +var ( + // ErrSignerNotInKeySet is returned when a the private key for a signer + // isn't included in the set of signing public keys. + ErrSignerNotInKeySet = fmt.Errorf("signing key is not found in key" + + " set") + + // ErrAlredyHaveAllNonces is called when RegisterPubNonce is called too + // many times for a given signing session. + ErrAlredyHaveAllNonces = fmt.Errorf("already have all nonces") + + // ErrAlredyHaveAllSigs is called when CombineSig is called too many + // times for a given signing session. + ErrAlredyHaveAllSigs = fmt.Errorf("already have all sigs") + + // ErrSigningContextReuse is returned if a user attempts to sign using + // the same signing context more than once. + ErrSigningContextReuse = fmt.Errorf("nonce already used") + + // ErrFinalSigInvalid is returned when the combined signature turns out + // to be invalid. + ErrFinalSigInvalid = fmt.Errorf("final signature is invalid") + + // ErrCombinedNonceUnavailable is returned when a caller attempts to + // sign a partial signature, without first having collected all the + // required combined nonces. + ErrCombinedNonceUnavailable = fmt.Errorf("missing combined nonce") +) + +// Context is a managed signing context for musig2. It takes care of things +// like securely generating secret nonces, aggregating keys and nonces, etc. +type Context struct { + // signingKey is the key we'll use for signing. + signingKey *btcec.PrivateKey + + // pubKey is our even-y coordinate public key. + pubKey *btcec.PublicKey + + // keySet is the set of all signers. + keySet []*btcec.PublicKey + + // combinedKey is the aggregated public key. + combinedKey *btcec.PublicKey + + // uniqueKeyIndex is the index of the second unique key in the keySet. + // This is used to speed up signing and verification computations. + uniqueKeyIndex int + + // keysHash is the hash of all the keys as defined in musig2. + keysHash []byte + + // shouldSort keeps track of if the public keys should be sorted before + // any operations. + shouldSort bool +} + +// NewContext creates a new signing context with the passed singing key and set +// of public keys for each of the other signers. +// +// NOTE: This struct should be used over the raw Sign API whenever possible. +func NewContext(signingKey *btcec.PrivateKey, + signers []*btcec.PublicKey, shouldSort bool) (*Context, error) { + + // As a sanity check, make sure the signing key is actually amongst the sit + // of signers. + // + // TODO(roasbeef): instead have pass all the _other_ signers? + pubKey, err := schnorr.ParsePubKey( + schnorr.SerializePubKey(signingKey.PubKey()), + ) + if err != nil { + return nil, err + } + + var keyFound bool + for _, key := range signers { + if key.IsEqual(pubKey) { + keyFound = true + break + } + } + if !keyFound { + return nil, ErrSignerNotInKeySet + } + + // Now that we know that we're actually a signer, we'll generate the + // key hash finger print and second unique key index so we can speed up + // signing later. + keysHash := keyHashFingerprint(signers, shouldSort) + uniqueKeyIndex := secondUniqueKeyIndex(signers, shouldSort) + + // Next, we'll use this information to compute the aggregated public + // key that'll be used for signing in practice. + combinedKey := AggregateKeys( + signers, shouldSort, WithKeysHash(keysHash), + WithUniqueKeyIndex(uniqueKeyIndex), + ) + + return &Context{ + signingKey: signingKey, + pubKey: pubKey, + keySet: signers, + combinedKey: combinedKey, + uniqueKeyIndex: uniqueKeyIndex, + keysHash: keysHash, + shouldSort: shouldSort, + }, nil +} + +// CombinedKey returns the combined public key that will be used to generate +// multi-signatures against. +func (c *Context) CombinedKey() btcec.PublicKey { + return *c.combinedKey +} + +// PubKey returns the public key of the signer of this session. +func (c *Context) PubKey() btcec.PublicKey { + return *c.pubKey +} + +// SigningKeys returns the set of keys used for signing. +func (c *Context) SigningKeys() []*btcec.PublicKey { + keys := make([]*btcec.PublicKey, len(c.keySet)) + copy(keys, c.keySet) + + return keys +} + +// Session represents a musig2 signing session. A new instance should be +// created each time a multi-signature is needed. The session struct handles +// nonces management, incremental partial sig vitrifaction, as well as final +// signature combination. Errors are returned when unsafe behavior such as +// nonce re-use is attempted. +// +// NOTE: This struct should be used over the raw Sign API whenever possible. +type Session struct { + ctx *Context + + localNonces *Nonces + + pubNonces [][PubNonceSize]byte + + combinedNonce *[PubNonceSize]byte + + msg [32]byte + + ourSig *PartialSignature + sigs []*PartialSignature + + finalSig *schnorr.Signature +} + +// NewSession creates a new musig2 signing session. +func (c *Context) NewSession() (*Session, error) { + localNonces, err := GenNonces() + if err != nil { + return nil, err + } + + s := &Session{ + ctx: c, + localNonces: localNonces, + pubNonces: make([][PubNonceSize]byte, 0, len(c.keySet)), + sigs: make([]*PartialSignature, 0, len(c.keySet)), + } + + s.pubNonces = append(s.pubNonces, localNonces.PubNonce) + + return s, nil +} + +// PublicNonce returns the public nonce for a signer. This should be sent to +// other parties before signing begins, so they can compute the aggregated +// public nonce. +func (s *Session) PublicNonce() [PubNonceSize]byte { + return s.localNonces.PubNonce +} + +// NumRegisteredNonces returns the total number of nonces that have been +// regsitered so far. +func (s *Session) NumRegisteredNonces() int { + return len(s.pubNonces) +} + +// RegisterPubNonce should be called for each public nonce from the set of +// signers. This method returns true once all the public nonces have been +// accounted for. +func (s *Session) RegisterPubNonce(nonce [PubNonceSize]byte) (bool, error) { + // If we already have all the nonces, then this method was called too many + // times. + haveAllNonces := len(s.pubNonces) == len(s.ctx.keySet) + if haveAllNonces { + return false, nil + } + + // Add this nonce and check again if we already have tall the nonces we + // need. + s.pubNonces = append(s.pubNonces, nonce) + haveAllNonces = len(s.pubNonces) == len(s.ctx.keySet) + + // If we have all the nonces, then we can go ahead and combine them + // now. + if haveAllNonces { + combinedNonce, err := AggregateNonces(s.pubNonces) + if err != nil { + return false, err + } + + s.combinedNonce = &combinedNonce + } + + return haveAllNonces, nil +} + +// Sign generates a partial signature for the target message, using the target +// context. If this method is called more than once per context, then an error +// is returned, as that means a nonce was re-used. +func (s *Session) Sign(msg [32]byte, + signOpts ...SignOption) (*PartialSignature, error) { + + s.msg = msg + + switch { + // If no local nonce is present, then this means we already signed, so + // we'll return an error to prevent nonce re-use. + case s.localNonces == nil: + return nil, ErrSigningContextReuse + + // We also need to make sure we have the combined nonce, otherwise this + // funciton was called too early. + case s.combinedNonce == nil: + return nil, ErrCombinedNonceUnavailable + } + + partialSig, err := Sign( + s.localNonces.SecNonce, s.ctx.signingKey, *s.combinedNonce, + s.ctx.keySet, msg, signOpts..., + ) + + // Now that we've generated our signature, we'll make sure to blank out + // our signing nonce. + s.localNonces = nil + + if err != nil { + return nil, err + } + + s.ourSig = partialSig + s.sigs = append(s.sigs, partialSig) + + return partialSig, nil +} + +// CombineSigs buffers a partial signature received from a signing party. The +// method returns true once all the signatures are available, and can be +// combined into the final signature. +func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { + // First check if we already have all the signatures we need. We + // already accumulated our own signature when we generated the sig. + haveAllSigs := len(s.sigs) == len(s.ctx.keySet) + if haveAllSigs { + return false, ErrAlredyHaveAllSigs + } + + // TODO(roasbeef): incremental check for invalid sig, or just detect at + // the very end? + + // Accumulate this sig, and check again if we have all the sigs we + // need. + s.sigs = append(s.sigs, sig) + haveAllSigs = len(s.sigs) == len(s.ctx.keySet) + + // If we have all the signatures, then we can combine them all into the + // final signature. + if haveAllSigs { + finalSig := CombineSigs(s.ourSig.R, s.sigs) + + // We'll also verify the signature at this point to ensure it's + // valid. + // + // TODO(roasbef): allow skipping? + if !finalSig.Verify(s.msg[:], s.ctx.combinedKey) { + return false, ErrFinalSigInvalid + } + + s.finalSig = finalSig + } + + return haveAllSigs, nil +} + +// FinalSig returns the final combined multi-signature, if present. +func (s *Session) FinalSig() *schnorr.Signature { + return s.finalSig +} diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index 2d0f26e022..7c756697eb 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -118,7 +118,11 @@ func aggregationCoefficient(keySet []*btcec.PublicKey, // secondUniqueKeyIndex returns the index of the second unique key. If all keys // are the same, then a value of -1 is returned. -func secondUniqueKeyIndex(keySet []*btcec.PublicKey) int { +func secondUniqueKeyIndex(keySet []*btcec.PublicKey, sort bool) int { + if sort { + keySet = sortKeys(keySet) + } + // Find the first key that isn't the same as the very first key (second // unique key). for i := range keySet { @@ -197,7 +201,7 @@ func AggregateKeys(keys []*btcec.PublicKey, sort bool, // A caller may also specify the unique key index themselves so we // don't need to re-compute it. if opts.uniqueKeyIndex == nil { - idx := secondUniqueKeyIndex(keys) + idx := secondUniqueKeyIndex(keys, sort) opts.uniqueKeyIndex = &idx } diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index edbff0b838..0c8af2fca0 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -1,7 +1,4 @@ -// Copyright 2013-2016 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. +// Copyright 2013-2022 The btcsuite developers package musig2 @@ -10,6 +7,7 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "sync" "testing" "github.com/btcsuite/btcd/btcec/v2" @@ -85,7 +83,7 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { keys = append(keys, pub) } - uniqueKeyIndex := secondUniqueKeyIndex(keys) + uniqueKeyIndex := secondUniqueKeyIndex(keys, false) combinedKey := AggregateKeys( keys, false, WithUniqueKeyIndex(uniqueKeyIndex), ) @@ -194,7 +192,8 @@ func TestMuSig2SigningTestVectors(t *testing.T) { } partialSig, err := Sign( - secNonce, signSetPrivKey, aggregatedNonce, keySet, msg, + secNonce, signSetPrivKey, aggregatedNonce, + keySet, msg, ) if err != nil { t.Fatalf("unable to generate partial sig: %v", err) @@ -251,7 +250,7 @@ func (s signerSet) pubNonces() [][PubNonceSize]byte { } func (s signerSet) combinedKey() *btcec.PublicKey { - uniqueKeyIndex := secondUniqueKeyIndex(s.keys()) + uniqueKeyIndex := secondUniqueKeyIndex(s.keys(), false) return AggregateKeys( s.keys(), false, WithUniqueKeyIndex(uniqueKeyIndex), ) @@ -263,10 +262,11 @@ func (s signerSet) combinedKey() *btcec.PublicKey { func TestMuSigMultiParty(t *testing.T) { t.Parallel() - // First generate the private key, public key, and nonce for each - // signer. - numSigners := 100 - signers := make(signerSet, 0, numSigners) + const numSigners = 100 + + // First generate the set of signers along with their public keys. + signerKeys := make([]*btcec.PrivateKey, numSigners) + signSet := make([]*btcec.PublicKey, numSigners) for i := 0; i < numSigners; i++ { privKey, err := btcec.NewPrivateKey() if err != nil { @@ -280,55 +280,105 @@ func TestMuSigMultiParty(t *testing.T) { t.Fatalf("unable to gen key: %v", err) } - nonces, err := GenNonces() + signerKeys[i] = privKey + signSet[i] = pubKey + } + + var combinedKey *btcec.PublicKey + + // Now that we have all the signers, we'll make a new context, then + // generate a new session for each of them(which handles nonce + // generation). + signers := make([]*Session, numSigners) + for i, signerKey := range signerKeys { + signCtx, err := NewContext(signerKey, signSet, false) if err != nil { - t.Fatalf("unable to gen nonces: %v", err) + t.Fatalf("unable to generate context: %v", err) } - signers = append(signers, signer{ - privKey: privKey, - pubKey: pubKey, - nonces: nonces, - }) + if combinedKey == nil { + k := signCtx.CombinedKey() + combinedKey = &k + } + + session, err := signCtx.NewSession() + if err != nil { + t.Fatalf("unable to generate new session: %v", err) + } + signers[i] = session } - msg := sha256.Sum256([]byte("let's get taprooty")) + // Next, in the pre-signing phase, we'll send all the nonces to each + // signer. + var wg sync.WaitGroup + for i, signCtx := range signers { + signCtx := signCtx - // With the set of nonces generated, we can now generate our aggregate - // nonce. - combinedNonce, err := AggregateNonces(signers.pubNonces()) - if err != nil { - t.Fatalf("unable to gen nonces: %v", err) + wg.Add(1) + go func(idx int, signer *Session) { + defer wg.Done() + + for j, otherCtx := range signers { + if idx == j { + continue + } + + nonce := otherCtx.PublicNonce() + haveAll, err := signer.RegisterPubNonce(nonce) + if err != nil { + t.Fatalf("unable to add public nonce") + } + + if j == len(signers)-1 && !haveAll { + t.Fatalf("all public nonces should have been detected") + } + } + }(i, signCtx) } - signerKeys := signers.keys() - combinedKey := signers.combinedKey() + wg.Wait() + + msg := sha256.Sum256([]byte("let's get taprooty")) - // Now for the signing phase: each signer will generate their partial - // signature and stash that away. We'll also store the final nonce as - // well, since we'll need that to validate the signature. - var finalNonce *btcec.PublicKey + // In the final step, we'll use the first signer as our combiner, and + // generate a signature for each signer, and then accumulate that with + // the combiner. + combiner := signers[0] for i := range signers { signer := signers[i] - partialSig, err := Sign( - signer.nonces.SecNonce, signer.privKey, combinedNonce, - signerKeys, msg, - ) + partialSig, err := signer.Sign(msg) if err != nil { t.Fatalf("unable to generate partial sig: %v", err) } - signers[i].partialSig = partialSig + // We don't need to combine the signature for the very first + // signer, as it already has that partial signature. + if i != 0 { + haveAll, err := combiner.CombineSig(partialSig) + if err != nil { + t.Fatalf("unable to combine sigs: %v", err) + } - if finalNonce == nil { - finalNonce = partialSig.R + if i == len(signers)-1 && !haveAll { + t.Fatalf("final sig wasn't reconstructed") + } } } // Finally we'll combined all the nonces, and ensure that it validates // as a single schnorr signature. - finalSig := CombineSigs(finalNonce, signers.partialSigs()) + finalSig := combiner.FinalSig() if !finalSig.Verify(msg[:], combinedKey) { t.Fatalf("final sig is invalid!") } + + // Verify that if we try to sign again with any of the existing + // signers, then we'll get an error as the nonces have already been + // used. + for _, signer := range signers { + _, err := signer.Sign(msg) + if err != ErrSigningContextReuse { + t.Fatalf("expected to get signing context reuse") + } + } } diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index bebc327124..4fd76450d9 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -1,7 +1,4 @@ -// Copyright 2013-2016 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. +// Copyright 2013-2022 The btcsuite developers package musig2 @@ -22,6 +19,10 @@ const ( SecNonceSize = 64 ) +// zeroSecNonce is a secret nonce that's all zeroes. This is used to check that +// we're not attempting to re-use a nonce, and also protect callers from it. +var zeroSecNonce [SecNonceSize]byte + // Nonces holds the public and secret nonces required for musig2. // // TODO(roasbeef): methods on this to help w/ parsing, etc? @@ -37,7 +38,7 @@ type Nonces struct { // secNonceToPubNonce takes our two secrete nonces, and produces their two // corresponding EC points, serialized in compressed format. -func secNonceToPubNonce(secNonce *[SecNonceSize]byte) [PubNonceSize]byte { +func secNonceToPubNonce(secNonce [SecNonceSize]byte) [PubNonceSize]byte { var k1Mod, k2Mod btcec.ModNScalar k1Mod.SetByteSlice(secNonce[:btcec.PrivKeyBytesLen]) k2Mod.SetByteSlice(secNonce[btcec.PrivKeyBytesLen:]) @@ -117,7 +118,7 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { // Next, we'll generate R_1 = k_1*G and R_2 = k_2*G. Along the way we // need to map our nonce values into mod n scalars so we can work with // the btcec API. - nonces.PubNonce = secNonceToPubNonce(&nonces.SecNonce) + nonces.PubNonce = secNonceToPubNonce(nonces.SecNonce) return &nonces, nil } diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 11edcf8469..df3caf23ed 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -1,13 +1,11 @@ -// Copyright 2013-2016 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. +// Copyright 2013-2022 The btcsuite developers package musig2 import ( "bytes" "fmt" + "io" secp "github.com/decred/dcrd/dcrec/secp256k1/v4" @@ -64,6 +62,34 @@ func NewPartialSignature(s *btcec.ModNScalar, } } +// Encode writes a serialized version of the partial signature to the passed +// io.Writer +func (p *PartialSignature) Encode(w io.Writer) error { + var sBytes [32]byte + p.S.PutBytes(&sBytes) + + if _, err := w.Write(sBytes[:]); err != nil { + return err + } + + return nil +} + +// Decode attempts to parse a serialized PartialSignature stored in the passed +// io reader. +func (p *PartialSignature) Decode(r io.Reader) error { + p.S = new(btcec.ModNScalar) + + var sBytes [32]byte + if _, err := io.ReadFull(r, sBytes[:]); err != nil { + return nil + } + + p.S.SetBytes(&sBytes) + + return nil +} + // SignOption is a functional option argument that allows callers to modify the // way we generate musig2 schnorr signatures. type SignOption func(*signOptions) @@ -130,13 +156,13 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, return nil, err } - // Compute the hash of all the keys here as we'll need it do aggregrate + // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of signing. keysHash := keyHashFingerprint(pubKeys, opts.sortKeys) // Next we'll construct the aggregated public key based on the set of // signers. - uniqueKeyIndex := secondUniqueKeyIndex(pubKeys) + uniqueKeyIndex := secondUniqueKeyIndex(pubKeys, opts.sortKeys) combinedKey := AggregateKeys( pubKeys, opts.sortKeys, WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), @@ -240,7 +266,7 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, // If we're not in fast sign mode, then we'll also validate our partial // signature. if !opts.fastSign { - pubNonce := secNonceToPubNonce(&secNonce) + pubNonce := secNonceToPubNonce(secNonce) sigValid := sig.Verify( pubNonce, combinedNonce, pubKeys, pubKey, msg, signOpts..., @@ -299,11 +325,10 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, return err } - // Compute the hash of all the keys here as we'll need it do aggregrate + // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of verification. keysHash := keyHashFingerprint(keySet, opts.sortKeys) - - uniqueKeyIndex := secondUniqueKeyIndex(keySet) + uniqueKeyIndex := secondUniqueKeyIndex(keySet, opts.sortKeys) // Next we'll construct the aggregated public key based on the set of // signers. diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index ed4b9cb5bf..f4532c7d09 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -1,7 +1,4 @@ -// Copyright (c) 2013-2017 The btcsuite developers -// Copyright (c) 2015-2021 The Decred developers -// Use of this source code is governed by an ISC -// license that can be found in the LICENSE file. +// Copyright (c) 2013-2022 The btcsuite developers package schnorr From 08187eb78602d01e430ed31de70ba6e090c4ecb3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 30 Mar 2022 22:52:39 -0500 Subject: [PATCH 0679/1056] btcec/schnorr/musig2: add support for tweaked aggregated keys In this commit, we add support for signing with tweaked aggregated keys. Such signing is required when signing for a taproot output key that actually commits to a script tree root, or was generated using BIP 86. A series of new functional arguments (that can likely be de-dup'd using Go's new type params), have been added to allow callers to optionally flip on this new behavior. --- btcec/schnorr/musig2/bench_test.go | 2 +- btcec/schnorr/musig2/context.go | 61 +++++++++- btcec/schnorr/musig2/keys.go | 123 +++++++++++++++++++- btcec/schnorr/musig2/musig2_test.go | 102 +++++++++++++++-- btcec/schnorr/musig2/sign.go | 171 ++++++++++++++++++++++++---- 5 files changed, 417 insertions(+), 42 deletions(-) diff --git a/btcec/schnorr/musig2/bench_test.go b/btcec/schnorr/musig2/bench_test.go index c02ccf3e41..eaa6b21b3c 100644 --- a/btcec/schnorr/musig2/bench_test.go +++ b/btcec/schnorr/musig2/bench_test.go @@ -301,7 +301,7 @@ func BenchmarkAggregateKeys(b *testing.B) { b.ResetTimer() b.ReportAllocs() - aggKey := AggregateKeys( + aggKey, _, _, _ := AggregateKeys( signerKeys, sortKeys, WithUniqueKeyIndex(uniqueKeyIndex), ) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 22bd2b236f..3a3b29280c 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -59,17 +59,51 @@ type Context struct { // keysHash is the hash of all the keys as defined in musig2. keysHash []byte + // tweaks is a set of optional tweak values that affect the final + // combined public key. + tweaks []KeyTweakDesc + // shouldSort keeps track of if the public keys should be sorted before // any operations. shouldSort bool } +// ContextOption is a functional option argument that allows callers to modify +// the musig2 signing is done within a context. +type ContextOption func(*contextOptions) + +// contextOptions houses the set of functional options that can be used to +// musig2 signing protocol. +type contextOptions struct { + tweaks []KeyTweakDesc +} + +// defaultContextOptions returns the default context options. +func defaultContextOptions() *contextOptions { + return &contextOptions{} +} + +// WithTweakedContext specifies that within the context, the aggregated public +// key should be tweaked with the specified tweaks. +func WithTweakedContext(tweaks []KeyTweakDesc) ContextOption { + return func(o *contextOptions) { + o.tweaks = tweaks + } +} + // NewContext creates a new signing context with the passed singing key and set // of public keys for each of the other signers. // // NOTE: This struct should be used over the raw Sign API whenever possible. func NewContext(signingKey *btcec.PrivateKey, - signers []*btcec.PublicKey, shouldSort bool) (*Context, error) { + signers []*btcec.PublicKey, shouldSort bool, + ctxOpts ...ContextOption) (*Context, error) { + + // First, parse the set of optional context options. + opts := defaultContextOptions() + for _, option := range ctxOpts { + option(opts) + } // As a sanity check, make sure the signing key is actually amongst the sit // of signers. @@ -101,10 +135,14 @@ func NewContext(signingKey *btcec.PrivateKey, // Next, we'll use this information to compute the aggregated public // key that'll be used for signing in practice. - combinedKey := AggregateKeys( + combinedKey, _, _, err := AggregateKeys( signers, shouldSort, WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + WithKeyTweaks(opts.tweaks...), ) + if err != nil { + return nil, err + } return &Context{ signingKey: signingKey, @@ -113,6 +151,7 @@ func NewContext(signingKey *btcec.PrivateKey, combinedKey: combinedKey, uniqueKeyIndex: uniqueKeyIndex, keysHash: keysHash, + tweaks: opts.tweaks, shouldSort: shouldSort, }, nil } @@ -160,6 +199,8 @@ type Session struct { finalSig *schnorr.Signature } +// TODO(roasbeef): optional arg to allow parsing in pre-generated nonces + // NewSession creates a new musig2 signing session. func (c *Context) NewSession() (*Session, error) { localNonces, err := GenNonces() @@ -242,6 +283,10 @@ func (s *Session) Sign(msg [32]byte, return nil, ErrCombinedNonceUnavailable } + if len(s.ctx.tweaks) != 0 { + signOpts = append(signOpts, WithTweaks(s.ctx.tweaks...)) + } + partialSig, err := Sign( s.localNonces.SecNonce, s.ctx.signingKey, *s.combinedNonce, s.ctx.keySet, msg, signOpts..., @@ -283,7 +328,17 @@ func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { // If we have all the signatures, then we can combine them all into the // final signature. if haveAllSigs { - finalSig := CombineSigs(s.ourSig.R, s.sigs) + var combineOpts []CombineOption + if len(s.ctx.tweaks) != 0 { + combineOpts = append( + combineOpts, WithTweakedCombine( + s.msg, s.ctx.keySet, s.ctx.tweaks, + s.ctx.shouldSort, + ), + ) + } + + finalSig := CombineSigs(s.ourSig.R, s.sigs, combineOpts...) // We'll also verify the signature at this point to ensure it's // valid. diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index 7c756697eb..35c37d9309 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -4,8 +4,11 @@ package musig2 import ( "bytes" + "fmt" "sort" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -19,6 +22,10 @@ var ( // KeyAggTagCoeff is the tagged hash tag used to compute the key // aggregation coefficient for each key. KeyAggTagCoeff = []byte("KeyAgg coefficient") + + // ErrTweakedKeyIsInfinity is returned if while tweaking a key, we end + // up with the point at infinity. + ErrTweakedKeyIsInfinity = fmt.Errorf("tweaked key is infinity point") ) // sortableKeys defines a type of slice of public keys that implements the sort @@ -137,6 +144,18 @@ func secondUniqueKeyIndex(keySet []*btcec.PublicKey, sort bool) int { return -1 } +// KeyTweakDesc describes a tweak to be applied to the aggregated public key +// generation and signing process. The IsXOnly specifies if the target key +// should be converted to an x-only public key before tweaking. +type KeyTweakDesc struct { + // Tweak is the 32-byte value that will modify the public key. + Tweak [32]byte + + // IsXOnly if true, then the public key will be mapped to an x-only key + // before the tweaking operation is applied. + IsXOnly bool +} + // KeyAggOption is a functional option argument that allows callers to specify // more or less information that has been pre-computed to the main routine. type KeyAggOption func(*keyAggOption) @@ -149,6 +168,10 @@ type keyAggOption struct { // uniqueKeyIndex is the pre-computed index of the second unique key. uniqueKeyIndex *int + + // tweaks specifies a series of tweaks to be applied to the aggregated + // public key> + tweaks []KeyTweakDesc } // WithKeysHash allows key aggregation to be optimize, by allowing the caller @@ -168,17 +191,92 @@ func WithUniqueKeyIndex(idx int) KeyAggOption { } } +// WithKeyTweaks allows a caller to specify a series of 32-byte tweaks that +// should be applied to the final aggregated public key. +func WithKeyTweaks(tweaks ...KeyTweakDesc) KeyAggOption { + return func(o *keyAggOption) { + o.tweaks = tweaks + } +} + // defaultKeyAggOptions returns the set of default arguments for key // aggregation. func defaultKeyAggOptions() *keyAggOption { return &keyAggOption{} } +// hasEvenY returns true if the affine representation of the passed jacobian +// point has an even y coordinate. +// +// TODO(roasbeef): double check, can just check the y coord even not jacobian? +func hasEvenY(pJ btcec.JacobianPoint) bool { + pJ.ToAffine() + p := btcec.NewPublicKey(&pJ.X, &pJ.Y) + keyBytes := p.SerializeCompressed() + return keyBytes[0] == secp.PubKeyFormatCompressedEven +} + +// tweakKey applies a tweaks to the passed public key using the specified +// tweak. The parityAcc and tweakAcc are returned (in that order) which +// includes the accumulate ration of the parity factor and the tweak multiplied +// by the parity factor. The xOnly bool specifies if this is to be an x-only +// tweak or not. +func tweakKey(keyJ btcec.JacobianPoint, parityAcc btcec.ModNScalar, tweak [32]byte, + tweakAcc btcec.ModNScalar, + xOnly bool) (btcec.JacobianPoint, btcec.ModNScalar, btcec.ModNScalar, error) { + + // First we'll compute the new parity factor for this key. If the key has + // an odd y coordinate (not even), then we'll need to negate it (multiply + // by -1 mod n, in this case). + var parityFactor btcec.ModNScalar + if xOnly && !hasEvenY(keyJ) { + parityFactor.SetInt(1).Negate() + } else { + parityFactor.SetInt(1) + } + + // Next, map the tweak into a mod n integer so we can use it for + // manipulations below. + tweakInt := new(btcec.ModNScalar) + tweakInt.SetBytes(&tweak) + + // Next, we'll compute: Q_i = g*Q + t*G, where g is our parityFactor and t + // is the tweakInt above. We'll space things out a bit to make it easier to + // follow. + // + // First compute t*G: + var tweakedGenerator btcec.JacobianPoint + btcec.ScalarBaseMultNonConst(tweakInt, &tweakedGenerator) + + // Next compute g*Q: + btcec.ScalarMultNonConst(&parityFactor, &keyJ, &keyJ) + + // Finally add both of them together to get our final + // tweaked point. + btcec.AddNonConst(&tweakedGenerator, &keyJ, &keyJ) + + // As a sanity check, make sure that we didn't just end up with the + // point at infinity. + if keyJ == infinityPoint { + return keyJ, parityAcc, tweakAcc, ErrTweakedKeyIsInfinity + } + + // As a final wrap up step, we'll accumulate the parity + // factor and also this tweak into the final set of accumulators. + parityAcc.Mul(&parityFactor) + tweakAcc.Mul(&parityFactor).Add(tweakInt) + + return keyJ, parityAcc, tweakAcc, nil +} + // AggregateKeys takes a list of possibly unsorted keys and returns a single // aggregated key as specified by the musig2 key aggregation algorithm. A nil // value can be passed for keyHash, which causes this function to re-derive it. +// In addition to the combined public key, the parity accumulator and the tweak +// accumulator are returned as well. func AggregateKeys(keys []*btcec.PublicKey, sort bool, - keyOpts ...KeyAggOption) *btcec.PublicKey { + keyOpts ...KeyAggOption) ( + *btcec.PublicKey, *btcec.ModNScalar, *btcec.ModNScalar, error) { // First, parse the set of optional signing options. opts := defaultKeyAggOptions() @@ -229,6 +327,27 @@ func AggregateKeys(keys []*btcec.PublicKey, sort bool, btcec.AddNonConst(&finalKeyJ, &tweakedKeyJ, &finalKeyJ) } + var ( + err error + tweakAcc btcec.ModNScalar + parityAcc btcec.ModNScalar + ) + parityAcc.SetInt(1) + + // In this case we have a set of tweaks, so we'll incrementally apply + // each one, until we have our final tweaked key, and the related + // accumulators. + for i := 1; i <= len(opts.tweaks); i++ { + finalKeyJ, parityAcc, tweakAcc, err = tweakKey( + finalKeyJ, parityAcc, opts.tweaks[i-1].Tweak, tweakAcc, + opts.tweaks[i-1].IsXOnly, + ) + if err != nil { + return nil, nil, nil, err + } + } + finalKeyJ.ToAffine() - return btcec.NewPublicKey(&finalKeyJ.X, &finalKeyJ.Y) + key := btcec.NewPublicKey(&finalKeyJ.X, &finalKeyJ.Y) + return key, &parityAcc, &tweakAcc, nil } diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 0c8af2fca0..d64ca9e9b8 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -84,7 +84,7 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { } uniqueKeyIndex := secondUniqueKeyIndex(keys, false) - combinedKey := AggregateKeys( + combinedKey, _, _, _ := AggregateKeys( keys, false, WithUniqueKeyIndex(uniqueKeyIndex), ) combinedKeyBytes := schnorr.SerializePubKey(combinedKey) @@ -164,6 +164,7 @@ func TestMuSig2SigningTestVectors(t *testing.T) { testCases := []struct { keyOrder []int expectedPartialSig []byte + tweak *KeyTweakDesc }{ { keyOrder: []int{0, 1, 2}, @@ -173,27 +174,63 @@ func TestMuSig2SigningTestVectors(t *testing.T) { keyOrder: []int{1, 0, 2}, expectedPartialSig: mustParseHex("2DF67BFFF18E3DE797E13C6475C963048138DAEC5CB20A357CECA7C8424295EA"), }, - { keyOrder: []int{1, 2, 0}, expectedPartialSig: mustParseHex("0D5B651E6DE34A29A12DE7A8B4183B4AE6A7F7FBE15CDCAFA4A3D1BCAABC7517"), }, + { + keyOrder: []int{1, 2, 0}, + expectedPartialSig: mustParseHex("5e24c7496b565debc3b9639e6f1304a21597f9603d3ab05b4913641775e1375b"), + tweak: &KeyTweakDesc{ + Tweak: [32]byte{ + 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, + 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, + 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, + 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, + }, + IsXOnly: true, + }, + }, + { + keyOrder: []int{1, 2, 0}, + expectedPartialSig: mustParseHex("78408ddcab4813d1394c97d493ef1084195c1d4b52e63ecd7bc5991644e44ddd"), + tweak: &KeyTweakDesc{ + Tweak: [32]byte{ + 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, + 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, + 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, + 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, + }, + IsXOnly: false, + }, + }, } var msg [32]byte copy(msg[:], signTestMsg) for _, testCase := range testCases { - testName := fmt.Sprintf("%v", testCase.keyOrder) + testName := fmt.Sprintf("%v/tweak=%v", testCase.keyOrder, testCase.tweak != nil) + if testCase.tweak != nil { + testName += fmt.Sprintf("/x_only=%v", testCase.tweak.IsXOnly) + } + t.Run(testName, func(t *testing.T) { keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) for _, keyIndex := range testCase.keyOrder { keySet = append(keySet, signSetKeys[keyIndex]) } + var opts []SignOption + if testCase.tweak != nil { + opts = append( + opts, WithTweaks(*testCase.tweak), + ) + } + partialSig, err := Sign( secNonce, signSetPrivKey, aggregatedNonce, - keySet, msg, + keySet, msg, opts..., ) if err != nil { t.Fatalf("unable to generate partial sig: %v", err) @@ -251,17 +288,14 @@ func (s signerSet) pubNonces() [][PubNonceSize]byte { func (s signerSet) combinedKey() *btcec.PublicKey { uniqueKeyIndex := secondUniqueKeyIndex(s.keys(), false) - return AggregateKeys( + key, _, _, _ := AggregateKeys( s.keys(), false, WithUniqueKeyIndex(uniqueKeyIndex), ) + return key } -// TestMuSigMultiParty tests that for a given set of 100 signers, we're able to -// properly generate valid sub signatures, which ultimately can be combined -// into a single valid signature. -func TestMuSigMultiParty(t *testing.T) { - t.Parallel() - +// testMultiPartySign executes a multi-party signing context w/ 100 signers. +func testMultiPartySign(t *testing.T, tweaks ...KeyTweakDesc) { const numSigners = 100 // First generate the set of signers along with their public keys. @@ -286,12 +320,19 @@ func TestMuSigMultiParty(t *testing.T) { var combinedKey *btcec.PublicKey + var ctxOpts []ContextOption + if len(tweaks) != 0 { + ctxOpts = append(ctxOpts, WithTweakedContext(tweaks)) + } + // Now that we have all the signers, we'll make a new context, then // generate a new session for each of them(which handles nonce // generation). signers := make([]*Session, numSigners) for i, signerKey := range signerKeys { - signCtx, err := NewContext(signerKey, signSet, false) + signCtx, err := NewContext( + signerKey, signSet, false, ctxOpts..., + ) if err != nil { t.Fatalf("unable to generate context: %v", err) } @@ -382,3 +423,40 @@ func TestMuSigMultiParty(t *testing.T) { } } } + +// TestMuSigMultiParty tests that for a given set of 100 signers, we're able to +// properly generate valid sub signatures, which ultimately can be combined +// into a single valid signature. +func TestMuSigMultiParty(t *testing.T) { + t.Parallel() + + testTweak := [32]byte{ + 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, + 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, + 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, + 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, + } + + t.Run("no_tweak", func(t *testing.T) { + t.Parallel() + + testMultiPartySign(t) + }) + + t.Run("tweaked", func(t *testing.T) { + t.Parallel() + + testMultiPartySign(t, KeyTweakDesc{ + Tweak: testTweak, + }) + }) + + t.Run("tweaked_x_only", func(t *testing.T) { + t.Parallel() + + testMultiPartySign(t, KeyTweakDesc{ + Tweak: testTweak, + IsXOnly: true, + }) + }) +} diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index df3caf23ed..f7b7b13d55 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -104,6 +104,11 @@ type signOptions struct { // sortKeys determines if the set of keys should be sorted before doing // key aggregation. sortKeys bool + + // tweaks specifies a series of tweaks to be applied to the aggregated + // public key, which also partially carries over into the signing + // process. + tweaks []KeyTweakDesc } // defaultSignOptions returns the default set of signing operations. @@ -128,6 +133,14 @@ func WithSortedKeys() SignOption { } } +// WithTweaks determines if the aggregated public key used should apply a +// series of tweaks before key aggregation. +func WithTweaks(tweaks ...KeyTweakDesc) SignOption { + return func(o *signOptions) { + o.tweaks = tweaks + } +} + // Sign generates a musig2 partial signature given the passed key set, secret // nonce, public nonce, and private keys. This method returns an error if the // generated nonces are either too large, or end up mapping to the point at @@ -163,10 +176,14 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, // Next we'll construct the aggregated public key based on the set of // signers. uniqueKeyIndex := secondUniqueKeyIndex(pubKeys, opts.sortKeys) - combinedKey := AggregateKeys( + combinedKey, parityAcc, _, err := AggregateKeys( pubKeys, opts.sortKeys, WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + WithKeyTweaks(opts.tweaks...), ) + if err != nil { + return nil, err + } // Next we'll compute the value b, that blinds our second public // nonce: @@ -224,8 +241,6 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, return nil, ErrPrivKeyZero } - // If the y coordinate of the public key is odd xor the y coordinate of - // the combined public key is odd, then we'll negate the private key. pubKey := privKey.PubKey() pubKeyYIsOdd := func() bool { pubKeyBytes := pubKey.SerializeCompressed() @@ -235,13 +250,27 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, combinedKeyBytes := combinedKey.SerializeCompressed() return combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd }() - if pubKeyYIsOdd != combinedKeyYIsOdd { - privKeyScalar.Negate() + + // Next we'll compute our two parity factors for Q the combined public + // key, and P, the public key we're signing with. If the keys are odd, + // then we'll negate them. + parityCombinedKey := new(btcec.ModNScalar).SetInt(1) + paritySignKey := new(btcec.ModNScalar).SetInt(1) + if combinedKeyYIsOdd { + parityCombinedKey.Negate() } + if pubKeyYIsOdd { + paritySignKey.Negate() + } + + // Before we sign below, we'll multiply by our various parity factors + // to ensure that the signing key is properly negated (if necessary): + // * d = gv⋅gaccv⋅gp⋅d' + privKeyScalar.Mul(parityCombinedKey).Mul(paritySignKey).Mul(parityAcc) // Next we'll create the challenge hash that commits to the combined - // nonce, combined public key and also the message: * e = - // H(tag=ChallengeHashTag, R || Q || m) mod n + // nonce, combined public key and also the message: + // * e = H(tag=ChallengeHashTag, R || Q || m) mod n var challengeMsg bytes.Buffer challengeMsg.Write(schnorr.SerializePubKey(nonceKey)) challengeMsg.Write(schnorr.SerializePubKey(combinedKey)) @@ -252,14 +281,14 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, var e btcec.ModNScalar e.SetByteSlice(challengeBytes[:]) - // Next, we'll compute mu, our aggregation coefficient for the key that + // Next, we'll compute a, our aggregation coefficient for the key that // we're signing with. - mu := aggregationCoefficient(pubKeys, pubKey, keysHash, uniqueKeyIndex) + a := aggregationCoefficient(pubKeys, pubKey, keysHash, uniqueKeyIndex) // With mu constructed, we can finally generate our partial signature - // as: s = (k1_1 + b*k_2 + e*mu*d) mod n. + // as: s = (k1_1 + b*k_2 + e*a*d) mod n. s := new(btcec.ModNScalar) - s.Add(&k1).Add(k2.Mul(&nonceBlinder)).Add(e.Mul(mu).Mul(&privKeyScalar)) + s.Add(&k1).Add(k2.Mul(&nonceBlinder)).Add(e.Mul(a).Mul(&privKeyScalar)) sig := NewPartialSignature(s, nonceKey) @@ -332,10 +361,14 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // Next we'll construct the aggregated public key based on the set of // signers. - combinedKey := AggregateKeys( + combinedKey, parityAcc, _, err := AggregateKeys( keySet, opts.sortKeys, WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + WithKeyTweaks(opts.tweaks...), ) + if err != nil { + return err + } // Next we'll compute the value b, that blinds our second public // nonce: @@ -413,25 +446,33 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, return err } - // Next, we'll compute mu, our aggregation coefficient for the key that + // Next, we'll compute a, our aggregation coefficient for the key that // we're signing with. - mu := aggregationCoefficient(keySet, signingKey, keysHash, uniqueKeyIndex) + a := aggregationCoefficient(keySet, signingKey, keysHash, uniqueKeyIndex) - // If the combined key has an odd y coordinate, then we'll negate the - // signer key. - var signKeyJ btcec.JacobianPoint - signingKey.AsJacobian(&signKeyJ) + // If the combined key has an odd y coordinate, then we'll negate + // parity factor for the signing key. + paritySignKey := new(btcec.ModNScalar).SetInt(1) combinedKeyBytes := combinedKey.SerializeCompressed() if combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd { - signKeyJ.ToAffine() - signKeyJ.Y.Negate(1) - signKeyJ.Y.Normalize() + paritySignKey.Negate() } - // In the final set, we'll check that: s*G == R' + e*mu*P. + // Next, we'll construct the final parity factor by multiplying the + // sign key parity factor with the accumulated parity factor for all + // the keys. + finalParityFactor := paritySignKey.Mul(parityAcc) + + // Now we'll multiply the parity factor by our signing key, which'll + // take care of the amount of negation needed. + var signKeyJ btcec.JacobianPoint + signingKey.AsJacobian(&signKeyJ) + btcec.ScalarMultNonConst(finalParityFactor, &signKeyJ, &signKeyJ) + + // In the final set, we'll check that: s*G == R' + e*a*P. var sG, rP btcec.JacobianPoint btcec.ScalarBaseMultNonConst(s, &sG) - btcec.ScalarMultNonConst(e.Mul(mu), &signKeyJ, &rP) + btcec.ScalarMultNonConst(e.Mul(a), &signKeyJ, &rP) btcec.AddNonConst(&rP, &pubNonceJ, &rP) sG.ToAffine() @@ -444,16 +485,98 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, return nil } +// CombineOption is a functional option argument that allows callers to modify the +// way we combine musig2 schnorr signatures. +type CombineOption func(*combineOptions) + +// combineOptions houses the set of functional options that can be used to +// modify the method used to combine the musig2 partial signatures. +type combineOptions struct { + msg [32]byte + + combinedKey *btcec.PublicKey + + tweakAcc *btcec.ModNScalar +} + +// defaultCombineOptions returns the default set of signing operations. +func defaultCombineOptions() *combineOptions { + return &combineOptions{} +} + +// WithTweakedCombine is a functional option that allows callers to specify +// that the signature was produced using a tweaked aggregated public key. In +// order to properly aggregate the partial signatures, the caller must specify +// enough information to reconstruct the challenge, and also the final +// accumulated tweak value. +func WithTweakedCombine(msg [32]byte, keys []*btcec.PublicKey, + tweaks []KeyTweakDesc, sort bool) CombineOption { + + return func(o *combineOptions) { + combinedKey, _, tweakAcc, _ := AggregateKeys( + keys, sort, WithKeyTweaks(tweaks...), + ) + + o.msg = msg + o.combinedKey = combinedKey + o.tweakAcc = tweakAcc + } +} + // CombineSigs combines the set of public keys given the final aggregated // nonce, and the series of partial signatures for each nonce. func CombineSigs(combinedNonce *btcec.PublicKey, - partialSigs []*PartialSignature) *schnorr.Signature { + partialSigs []*PartialSignature, + combineOpts ...CombineOption) *schnorr.Signature { + // First, parse the set of optional combine options. + opts := defaultCombineOptions() + for _, option := range combineOpts { + option(opts) + } + + // If signer keys and tweaks are specified, then we need to carry out + // some intermediate steps before we can combine the signature. + var tweakProduct *btcec.ModNScalar + if opts.combinedKey != nil && opts.tweakAcc != nil { + // Next, we'll construct the parity factor of the combined key, + // negating it if the combined key has an even y coordinate. + parityFactor := new(btcec.ModNScalar).SetInt(1) + combinedKeyBytes := opts.combinedKey.SerializeCompressed() + if combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd { + parityFactor.Negate() + } + + // Next we'll reconstruct e the challenge has based on the + // nonce and combined public key. + // * e = H(tag=ChallengeHashTag, R || Q || m) mod n + var challengeMsg bytes.Buffer + challengeMsg.Write(schnorr.SerializePubKey(combinedNonce)) + challengeMsg.Write(schnorr.SerializePubKey(opts.combinedKey)) + challengeMsg.Write(opts.msg[:]) + challengeBytes := chainhash.TaggedHash( + ChallengeHashTag, challengeMsg.Bytes(), + ) + var e btcec.ModNScalar + e.SetByteSlice(challengeBytes[:]) + + tweakProduct = new(btcec.ModNScalar).Set(&e) + tweakProduct.Mul(opts.tweakAcc).Mul(parityFactor) + } + + // Finally, the tweak factor also needs to be re-computed as well. var combinedSig btcec.ModNScalar for _, partialSig := range partialSigs { combinedSig.Add(partialSig.S) } + // If the tweak product was set above, then we'll need to add the value + // at the very end in order to produce a valid signature under the + // final tweaked key. + if tweakProduct != nil { + combinedSig.Add(tweakProduct) + } + // TODO(roasbeef): less verbose way to get the x coord... var nonceJ btcec.JacobianPoint combinedNonce.AsJacobian(&nonceJ) From f7168c86633d4737a0e0c3af51d83a6e559199f7 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 31 Mar 2022 19:27:34 -0500 Subject: [PATCH 0680/1056] schnorr/musig2: add native support for taproot output key tweaking In this commit, we add a series of new options and methods to make it easier to use the package in the context of a taproot output that commits to a script root or some other value. Before this series of changes, the API was hard to use in this context as the taproot tweak actually includes the internal public key, which in this case is the aggregated public key. So you actually needed to call that API w/o the tweak, get that, then recompute the tweak itself. To make things easier in the taproot context, we've added a series of new options that'll return the aggregated key before any tweaks (to be used as the internal key), and also handle computing the BIP 341 tweak value for the caller. --- btcec/go.mod | 2 +- btcec/go.sum | 4 +- btcec/schnorr/musig2/bench_test.go | 2 +- btcec/schnorr/musig2/context.go | 93 +++++++++++++++++++++++------ btcec/schnorr/musig2/keys.go | 71 ++++++++++++++++++++-- btcec/schnorr/musig2/musig2_test.go | 30 ++++++---- btcec/schnorr/musig2/sign.go | 90 +++++++++++++++++++++++----- 7 files changed, 242 insertions(+), 50 deletions(-) diff --git a/btcec/go.mod b/btcec/go.mod index bc8cf721e3..8c7cc1d63c 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -3,7 +3,7 @@ module github.com/btcsuite/btcd/btcec/v2 go 1.17 require ( - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 ) diff --git a/btcec/go.sum b/btcec/go.sum index 00af17624d..0004a783bb 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -1,5 +1,5 @@ -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0 h1:MSskdM4/xJYcFzy0altH/C/xHopifpWzHUi1JeVI34Q= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= diff --git a/btcec/schnorr/musig2/bench_test.go b/btcec/schnorr/musig2/bench_test.go index eaa6b21b3c..70d7e931ce 100644 --- a/btcec/schnorr/musig2/bench_test.go +++ b/btcec/schnorr/musig2/bench_test.go @@ -306,7 +306,7 @@ func BenchmarkAggregateKeys(b *testing.B) { WithUniqueKeyIndex(uniqueKeyIndex), ) - testKey = aggKey + testKey = aggKey.FinalKey }) } } diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 3a3b29280c..bfb9d874e9 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -35,6 +35,10 @@ var ( // sign a partial signature, without first having collected all the // required combined nonces. ErrCombinedNonceUnavailable = fmt.Errorf("missing combined nonce") + + // ErrTaprootInternalKeyUnavailable is returned when a user attempts to + // obtain the + ErrTaprootInternalKeyUnavailable = fmt.Errorf("taproot tweak not used") ) // Context is a managed signing context for musig2. It takes care of things @@ -50,7 +54,7 @@ type Context struct { keySet []*btcec.PublicKey // combinedKey is the aggregated public key. - combinedKey *btcec.PublicKey + combinedKey *AggregateKey // uniqueKeyIndex is the index of the second unique key in the keySet. // This is used to speed up signing and verification computations. @@ -59,9 +63,8 @@ type Context struct { // keysHash is the hash of all the keys as defined in musig2. keysHash []byte - // tweaks is a set of optional tweak values that affect the final - // combined public key. - tweaks []KeyTweakDesc + // opts is the set of options for the context. + opts *contextOptions // shouldSort keeps track of if the public keys should be sorted before // any operations. @@ -75,7 +78,18 @@ type ContextOption func(*contextOptions) // contextOptions houses the set of functional options that can be used to // musig2 signing protocol. type contextOptions struct { + // tweaks is the set of optinoal tweaks to apply to the combined public + // key. tweaks []KeyTweakDesc + + // taprootTweak specifies the taproot tweak. If specified, then we'll + // use this as the script root for the BIP 341 taproot (x-only) tweak. + // Normally we'd just apply the raw 32 byte tweak, but for taproot, we + // first need to compute the aggregated key before tweaking, and then + // use it as the internal key. This is required as the taproot tweak + // also commits to the public key, which in this case is the aggregated + // key before the tweak. + taprootTweak []byte } // defaultContextOptions returns the default context options. @@ -85,12 +99,22 @@ func defaultContextOptions() *contextOptions { // WithTweakedContext specifies that within the context, the aggregated public // key should be tweaked with the specified tweaks. -func WithTweakedContext(tweaks []KeyTweakDesc) ContextOption { +func WithTweakedContext(tweaks ...KeyTweakDesc) ContextOption { return func(o *contextOptions) { o.tweaks = tweaks } } +// WithTaprootTweakCtx specifies that within this context, the final key should +// use the taproot tweak as defined in BIP 341: outputKey = internalKey + +// h_tapTweak(internalKey || scriptRoot). In this case, the aggreaged key +// before the tweak will be used as the internal key. +func WithTaprootTweakCtx(scriptRoot []byte) ContextOption { + return func(o *contextOptions) { + o.taprootTweak = scriptRoot + } +} + // NewContext creates a new signing context with the passed singing key and set // of public keys for each of the other signers. // @@ -133,12 +157,21 @@ func NewContext(signingKey *btcec.PrivateKey, keysHash := keyHashFingerprint(signers, shouldSort) uniqueKeyIndex := secondUniqueKeyIndex(signers, shouldSort) + keyAggOpts := []KeyAggOption{ + WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + } + if opts.taprootTweak != nil { + keyAggOpts = append( + keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak), + ) + } else if len(opts.tweaks) != 0 { + keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...)) + } + // Next, we'll use this information to compute the aggregated public // key that'll be used for signing in practice. combinedKey, _, _, err := AggregateKeys( - signers, shouldSort, WithKeysHash(keysHash), - WithUniqueKeyIndex(uniqueKeyIndex), - WithKeyTweaks(opts.tweaks...), + signers, shouldSort, keyAggOpts..., ) if err != nil { return nil, err @@ -151,15 +184,15 @@ func NewContext(signingKey *btcec.PrivateKey, combinedKey: combinedKey, uniqueKeyIndex: uniqueKeyIndex, keysHash: keysHash, - tweaks: opts.tweaks, + opts: opts, shouldSort: shouldSort, }, nil } // CombinedKey returns the combined public key that will be used to generate // multi-signatures against. -func (c *Context) CombinedKey() btcec.PublicKey { - return *c.combinedKey +func (c *Context) CombinedKey() *btcec.PublicKey { + return c.combinedKey.FinalKey } // PubKey returns the public key of the signer of this session. @@ -175,6 +208,19 @@ func (c *Context) SigningKeys() []*btcec.PublicKey { return keys } +// TaprootInternalKey returns the internal taproot key, which is the aggregated +// key _before_ the tweak is applied. If a taproot tweak was specified, then +// CombinedKey() will return the fully tweaked output key, with this method +// returning the internal key. If a taproot tweak wasn't speciifed, then this +// method will return an error. +func (c *Context) TaprootInternalKey() (*btcec.PublicKey, error) { + if c.opts.taprootTweak == nil { + return nil, ErrTaprootInternalKeyUnavailable + } + + return c.combinedKey.PreTweakedKey, nil +} + // Session represents a musig2 signing session. A new instance should be // created each time a multi-signature is needed. The session struct handles // nonces management, incremental partial sig vitrifaction, as well as final @@ -241,7 +287,7 @@ func (s *Session) RegisterPubNonce(nonce [PubNonceSize]byte) (bool, error) { // times. haveAllNonces := len(s.pubNonces) == len(s.ctx.keySet) if haveAllNonces { - return false, nil + return false, ErrAlredyHaveAllNonces } // Add this nonce and check again if we already have tall the nonces we @@ -283,8 +329,12 @@ func (s *Session) Sign(msg [32]byte, return nil, ErrCombinedNonceUnavailable } - if len(s.ctx.tweaks) != 0 { - signOpts = append(signOpts, WithTweaks(s.ctx.tweaks...)) + if s.ctx.opts.taprootTweak != nil { + signOpts = append( + signOpts, WithTaprootSignTweak(s.ctx.opts.taprootTweak), + ) + } else if len(s.ctx.opts.tweaks) != 0 { + signOpts = append(signOpts, WithTweaks(s.ctx.opts.tweaks...)) } partialSig, err := Sign( @@ -306,7 +356,7 @@ func (s *Session) Sign(msg [32]byte, return partialSig, nil } -// CombineSigs buffers a partial signature received from a signing party. The +// CombineSig buffers a partial signature received from a signing party. The // method returns true once all the signatures are available, and can be // combined into the final signature. func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { @@ -329,10 +379,17 @@ func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { // final signature. if haveAllSigs { var combineOpts []CombineOption - if len(s.ctx.tweaks) != 0 { + if s.ctx.opts.taprootTweak != nil { + combineOpts = append( + combineOpts, WithTaprootTweakedCombine( + s.msg, s.ctx.keySet, s.ctx.opts.taprootTweak, + s.ctx.shouldSort, + ), + ) + } else if len(s.ctx.opts.tweaks) != 0 { combineOpts = append( combineOpts, WithTweakedCombine( - s.msg, s.ctx.keySet, s.ctx.tweaks, + s.msg, s.ctx.keySet, s.ctx.opts.tweaks, s.ctx.shouldSort, ), ) @@ -344,7 +401,7 @@ func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { // valid. // // TODO(roasbef): allow skipping? - if !finalSig.Verify(s.msg[:], s.ctx.combinedKey) { + if !finalSig.Verify(s.msg[:], s.ctx.combinedKey.FinalKey) { return false, ErrFinalSigInvalid } diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index 35c37d9309..c13af98463 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -170,8 +170,12 @@ type keyAggOption struct { uniqueKeyIndex *int // tweaks specifies a series of tweaks to be applied to the aggregated - // public key> + // public key. tweaks []KeyTweakDesc + + // taprootTweak controls if the tweaks above should be applied in a BIP + // 340 style. + taprootTweak bool } // WithKeysHash allows key aggregation to be optimize, by allowing the caller @@ -199,6 +203,29 @@ func WithKeyTweaks(tweaks ...KeyTweakDesc) KeyAggOption { } } +// WithTaprootKeyTweak specifies that within this context, the final key should +// use the taproot tweak as defined in BIP 341: outputKey = internalKey + +// h_tapTweak(internalKey || scriptRoot). In this case, the aggregated key +// before the tweak will be used as the internal key. +// +// This option should be used instead of WithKeyTweaks when the aggregated key +// is intended to be used as a taproot output key that commits to a script +// root. +func WithTaprootKeyTweak(scriptRoot []byte) KeyAggOption { + return func(o *keyAggOption) { + var tweak [32]byte + copy(tweak[:], scriptRoot[:]) + + o.tweaks = []KeyTweakDesc{ + { + Tweak: tweak, + IsXOnly: true, + }, + } + o.taprootTweak = true + } +} + // defaultKeyAggOptions returns the set of default arguments for key // aggregation. func defaultKeyAggOptions() *keyAggOption { @@ -269,6 +296,19 @@ func tweakKey(keyJ btcec.JacobianPoint, parityAcc btcec.ModNScalar, tweak [32]by return keyJ, parityAcc, tweakAcc, nil } +// AggregateKey is a final aggregated key along with a possible version of the +// key without any tweaks applied. +type AggregateKey struct { + // FinalKey is the final aggregated key which may include one or more + // tweaks applied to it. + FinalKey *btcec.PublicKey + + // PreTweakedKey is the aggregated *before* any tweaks have been + // applied. This should be used as the internal key in taproot + // contexts. + PreTweakedKey *btcec.PublicKey +} + // AggregateKeys takes a list of possibly unsorted keys and returns a single // aggregated key as specified by the musig2 key aggregation algorithm. A nil // value can be passed for keyHash, which causes this function to re-derive it. @@ -276,7 +316,7 @@ func tweakKey(keyJ btcec.JacobianPoint, parityAcc btcec.ModNScalar, tweak [32]by // accumulator are returned as well. func AggregateKeys(keys []*btcec.PublicKey, sort bool, keyOpts ...KeyAggOption) ( - *btcec.PublicKey, *btcec.ModNScalar, *btcec.ModNScalar, error) { + *AggregateKey, *btcec.ModNScalar, *btcec.ModNScalar, error) { // First, parse the set of optional signing options. opts := defaultKeyAggOptions() @@ -327,6 +367,25 @@ func AggregateKeys(keys []*btcec.PublicKey, sort bool, btcec.AddNonConst(&finalKeyJ, &tweakedKeyJ, &finalKeyJ) } + // We'll copy over the key at this point, since this represents the + // aggregated key before any tweaks have been applied. This'll be used + // as the internal key for script path proofs. + combinedKey := btcec.NewPublicKey(&finalKeyJ.X, &finalKeyJ.Y) + + // At this point, if this is a taproot tweak, then we'll modify the + // base tweak value to use the BIP 341 tweak value. + if opts.taprootTweak { + // Compute the taproot key tagged hash of: + // h_tapTweak(internalKey || scriptRoot). We only do this for + // the first one, as you can only specify a single tweak when + // using the taproot mode with this API. + tapTweakHash := chainhash.TaggedHash( + chainhash.TagTapTweak, schnorr.SerializePubKey(combinedKey), + opts.tweaks[0].Tweak[:], + ) + opts.tweaks[0].Tweak = *tapTweakHash + } + var ( err error tweakAcc btcec.ModNScalar @@ -348,6 +407,10 @@ func AggregateKeys(keys []*btcec.PublicKey, sort bool, } finalKeyJ.ToAffine() - key := btcec.NewPublicKey(&finalKeyJ.X, &finalKeyJ.Y) - return key, &parityAcc, &tweakAcc, nil + finalKey := btcec.NewPublicKey(&finalKeyJ.X, &finalKeyJ.Y) + + return &AggregateKey{ + PreTweakedKey: combinedKey, + FinalKey: finalKey, + }, &parityAcc, &tweakAcc, nil } diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index d64ca9e9b8..bfd7c0818d 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -87,7 +87,7 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { combinedKey, _, _, _ := AggregateKeys( keys, false, WithUniqueKeyIndex(uniqueKeyIndex), ) - combinedKeyBytes := schnorr.SerializePubKey(combinedKey) + combinedKeyBytes := schnorr.SerializePubKey(combinedKey.FinalKey) if !bytes.Equal(combinedKeyBytes, testCase.expectedKey) { t.Fatalf("case: #%v, invalid aggregation: "+ "expected %x, got %x", i, testCase.expectedKey, @@ -291,11 +291,13 @@ func (s signerSet) combinedKey() *btcec.PublicKey { key, _, _, _ := AggregateKeys( s.keys(), false, WithUniqueKeyIndex(uniqueKeyIndex), ) - return key + return key.FinalKey } // testMultiPartySign executes a multi-party signing context w/ 100 signers. -func testMultiPartySign(t *testing.T, tweaks ...KeyTweakDesc) { +func testMultiPartySign(t *testing.T, taprootTweak []byte, + tweaks ...KeyTweakDesc) { + const numSigners = 100 // First generate the set of signers along with their public keys. @@ -321,8 +323,11 @@ func testMultiPartySign(t *testing.T, tweaks ...KeyTweakDesc) { var combinedKey *btcec.PublicKey var ctxOpts []ContextOption - if len(tweaks) != 0 { - ctxOpts = append(ctxOpts, WithTweakedContext(tweaks)) + switch { + case taprootTweak != nil: + ctxOpts = append(ctxOpts, WithTaprootTweakCtx(taprootTweak)) + case len(tweaks) != 0: + ctxOpts = append(ctxOpts, WithTweakedContext(tweaks...)) } // Now that we have all the signers, we'll make a new context, then @@ -338,8 +343,7 @@ func testMultiPartySign(t *testing.T, tweaks ...KeyTweakDesc) { } if combinedKey == nil { - k := signCtx.CombinedKey() - combinedKey = &k + combinedKey = signCtx.CombinedKey() } session, err := signCtx.NewSession() @@ -440,13 +444,13 @@ func TestMuSigMultiParty(t *testing.T) { t.Run("no_tweak", func(t *testing.T) { t.Parallel() - testMultiPartySign(t) + testMultiPartySign(t, nil) }) t.Run("tweaked", func(t *testing.T) { t.Parallel() - testMultiPartySign(t, KeyTweakDesc{ + testMultiPartySign(t, nil, KeyTweakDesc{ Tweak: testTweak, }) }) @@ -454,9 +458,15 @@ func TestMuSigMultiParty(t *testing.T) { t.Run("tweaked_x_only", func(t *testing.T) { t.Parallel() - testMultiPartySign(t, KeyTweakDesc{ + testMultiPartySign(t, nil, KeyTweakDesc{ Tweak: testTweak, IsXOnly: true, }) }) + + t.Run("taproot_tweaked_x_only", func(t *testing.T) { + t.Parallel() + + testMultiPartySign(t, testTweak[:]) + }) } diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index f7b7b13d55..16c5cd2fac 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -109,6 +109,14 @@ type signOptions struct { // public key, which also partially carries over into the signing // process. tweaks []KeyTweakDesc + + // taprootTweak specifies a taproot specific tweak. of the tweaks + // specified above. Normally we'd just apply the raw 32 byte tweak, but + // for taproot, we first need to compute the aggregated key before + // tweaking, and then use it as the internal key. This is required as + // the taproot tweak also commits to the public key, which in this case + // is the aggregated key before the tweak. + taprootTweak []byte } // defaultSignOptions returns the default set of signing operations. @@ -141,6 +149,21 @@ func WithTweaks(tweaks ...KeyTweakDesc) SignOption { } } +// WithTaprootSignTweak allows a caller to specify a tweak that should be used +// in a bip 340 manner when signing. This differs from WithTweaks as the tweak +// will be assumed to always be x-only and the intermediate aggregate key +// before tweaking will be used to generate part of the tweak (as the taproot +// tweak also commits to the internal key). +// +// This option should be used in the taproot context to create a valid +// signature for the keypath spend for taproot, when the output key is actually +// committing to a script path, or some other data. +func WithTaprootSignTweak(scriptRoot []byte) SignOption { + return func(o *signOptions) { + o.taprootTweak = scriptRoot + } +} + // Sign generates a musig2 partial signature given the passed key set, secret // nonce, public nonce, and private keys. This method returns an error if the // generated nonces are either too large, or end up mapping to the point at @@ -172,14 +195,23 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of signing. keysHash := keyHashFingerprint(pubKeys, opts.sortKeys) + uniqueKeyIndex := secondUniqueKeyIndex(pubKeys, opts.sortKeys) + + keyAggOpts := []KeyAggOption{ + WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + } + if opts.taprootTweak != nil { + keyAggOpts = append( + keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak), + ) + } else { + keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...)) + } // Next we'll construct the aggregated public key based on the set of // signers. - uniqueKeyIndex := secondUniqueKeyIndex(pubKeys, opts.sortKeys) combinedKey, parityAcc, _, err := AggregateKeys( - pubKeys, opts.sortKeys, WithKeysHash(keysHash), - WithUniqueKeyIndex(uniqueKeyIndex), - WithKeyTweaks(opts.tweaks...), + pubKeys, opts.sortKeys, keyAggOpts..., ) if err != nil { return nil, err @@ -193,7 +225,7 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, nonceBlinder btcec.ModNScalar ) nonceMsgBuf.Write(combinedNonce[:]) - nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey)) + nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey.FinalKey)) nonceMsgBuf.Write(msg[:]) nonceBlindHash := chainhash.TaggedHash( NonceBlindTag, nonceMsgBuf.Bytes(), @@ -247,7 +279,7 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, return pubKeyBytes[0] == secp.PubKeyFormatCompressedOdd }() combinedKeyYIsOdd := func() bool { - combinedKeyBytes := combinedKey.SerializeCompressed() + combinedKeyBytes := combinedKey.FinalKey.SerializeCompressed() return combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd }() @@ -273,7 +305,7 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, // * e = H(tag=ChallengeHashTag, R || Q || m) mod n var challengeMsg bytes.Buffer challengeMsg.Write(schnorr.SerializePubKey(nonceKey)) - challengeMsg.Write(schnorr.SerializePubKey(combinedKey)) + challengeMsg.Write(schnorr.SerializePubKey(combinedKey.FinalKey)) challengeMsg.Write(msg[:]) challengeBytes := chainhash.TaggedHash( ChallengeHashTag, challengeMsg.Bytes(), @@ -359,12 +391,21 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, keysHash := keyHashFingerprint(keySet, opts.sortKeys) uniqueKeyIndex := secondUniqueKeyIndex(keySet, opts.sortKeys) + keyAggOpts := []KeyAggOption{ + WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + } + if opts.taprootTweak != nil { + keyAggOpts = append( + keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak), + ) + } else { + keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...)) + } + // Next we'll construct the aggregated public key based on the set of // signers. combinedKey, parityAcc, _, err := AggregateKeys( - keySet, opts.sortKeys, - WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), - WithKeyTweaks(opts.tweaks...), + keySet, opts.sortKeys, keyAggOpts..., ) if err != nil { return err @@ -378,7 +419,7 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, nonceBlinder btcec.ModNScalar ) nonceMsgBuf.Write(combinedNonce[:]) - nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey)) + nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey.FinalKey)) nonceMsgBuf.Write(msg[:]) nonceBlindHash := chainhash.TaggedHash(NonceBlindTag, nonceMsgBuf.Bytes()) nonceBlinder.SetByteSlice(nonceBlindHash[:]) @@ -433,7 +474,7 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, challengeMsg.Write(schnorr.SerializePubKey(btcec.NewPublicKey( &nonce.X, &nonce.Y, ))) - challengeMsg.Write(schnorr.SerializePubKey(combinedKey)) + challengeMsg.Write(schnorr.SerializePubKey(combinedKey.FinalKey)) challengeMsg.Write(msg[:]) challengeBytes := chainhash.TaggedHash( ChallengeHashTag, challengeMsg.Bytes(), @@ -453,7 +494,7 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // If the combined key has an odd y coordinate, then we'll negate // parity factor for the signing key. paritySignKey := new(btcec.ModNScalar).SetInt(1) - combinedKeyBytes := combinedKey.SerializeCompressed() + combinedKeyBytes := combinedKey.FinalKey.SerializeCompressed() if combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd { paritySignKey.Negate() } @@ -518,7 +559,28 @@ func WithTweakedCombine(msg [32]byte, keys []*btcec.PublicKey, ) o.msg = msg - o.combinedKey = combinedKey + o.combinedKey = combinedKey.FinalKey + o.tweakAcc = tweakAcc + } +} + +// WithTaprootTweakedCombine is similar to the WithTweakedCombine option, but +// assumes a BIP 341 context where the final tweaked key is to be used as the +// output key, where the internal key is the aggregated key pre-tweak. +// +// This option should be used over WithTweakedCombine when attempting to +// aggregate signatures for a top-level taproot keysepnd, where the output key +// commits to a script root. +func WithTaprootTweakedCombine(msg [32]byte, keys []*btcec.PublicKey, + scriptRoot []byte, sort bool) CombineOption { + + return func(o *combineOptions) { + combinedKey, _, tweakAcc, _ := AggregateKeys( + keys, sort, WithTaprootKeyTweak(scriptRoot), + ) + + o.msg = msg + o.combinedKey = combinedKey.FinalKey o.tweakAcc = tweakAcc } } From 9d0d52708ac9a0cdc13b08e9c75df9e58905fbb4 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 1 Apr 2022 12:35:25 -0500 Subject: [PATCH 0681/1056] btcec/schnorr/musig2: add explicit support for BIP 86 multi-signing In this commit, we add a series of new functional optinos to make signing for an aggregated key where the final taproot output key was derived using BIP 86. This can be used in cases where no script path shuold be allowed, and only an n-of-n multi-sig should be used. --- btcec/schnorr/musig2/context.go | 45 +++++++++++++++++---- btcec/schnorr/musig2/keys.go | 41 ++++++++++++++++++- btcec/schnorr/musig2/musig2_test.go | 8 ++++ btcec/schnorr/musig2/sign.go | 61 ++++++++++++++++++++++++++--- 4 files changed, 141 insertions(+), 14 deletions(-) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index bfb9d874e9..2461f962ab 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -90,6 +90,10 @@ type contextOptions struct { // also commits to the public key, which in this case is the aggregated // key before the tweak. taprootTweak []byte + + // bip86Tweak if true, then the weak will just be + // h_tapTweak(internalKey) as there is no true script root. + bip86Tweak bool } // defaultContextOptions returns the default context options. @@ -115,6 +119,16 @@ func WithTaprootTweakCtx(scriptRoot []byte) ContextOption { } } +// WithBip86TweakCtx specifies that within this context, the final key should +// use the taproot tweak as defined in BIP 341, with the BIP 86 modification: +// outputKey = internalKey + h_tapTweak(internalKey)*G. In this case, the +// aggreaged key before the tweak will be used as the internal key. +func WithBip86TweakCtx() ContextOption { + return func(o *contextOptions) { + o.bip86Tweak = true + } +} + // NewContext creates a new signing context with the passed singing key and set // of public keys for each of the other signers. // @@ -160,11 +174,16 @@ func NewContext(signingKey *btcec.PrivateKey, keyAggOpts := []KeyAggOption{ WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), } - if opts.taprootTweak != nil { + switch { + case opts.bip86Tweak: + keyAggOpts = append( + keyAggOpts, WithBIP86KeyTweak(), + ) + case opts.taprootTweak != nil: keyAggOpts = append( keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak), ) - } else if len(opts.tweaks) != 0 { + case len(opts.tweaks) != 0: keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...)) } @@ -214,7 +233,7 @@ func (c *Context) SigningKeys() []*btcec.PublicKey { // returning the internal key. If a taproot tweak wasn't speciifed, then this // method will return an error. func (c *Context) TaprootInternalKey() (*btcec.PublicKey, error) { - if c.opts.taprootTweak == nil { + if c.opts.taprootTweak == nil && !c.opts.bip86Tweak { return nil, ErrTaprootInternalKeyUnavailable } @@ -329,11 +348,16 @@ func (s *Session) Sign(msg [32]byte, return nil, ErrCombinedNonceUnavailable } - if s.ctx.opts.taprootTweak != nil { + switch { + case s.ctx.opts.bip86Tweak: + signOpts = append( + signOpts, WithBip86SignTweak(), + ) + case s.ctx.opts.taprootTweak != nil: signOpts = append( signOpts, WithTaprootSignTweak(s.ctx.opts.taprootTweak), ) - } else if len(s.ctx.opts.tweaks) != 0 { + case len(s.ctx.opts.tweaks) != 0: signOpts = append(signOpts, WithTweaks(s.ctx.opts.tweaks...)) } @@ -379,14 +403,21 @@ func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { // final signature. if haveAllSigs { var combineOpts []CombineOption - if s.ctx.opts.taprootTweak != nil { + switch { + case s.ctx.opts.bip86Tweak: + combineOpts = append( + combineOpts, WithBip86TweakedCombine( + s.msg, s.ctx.keySet, s.ctx.shouldSort, + ), + ) + case s.ctx.opts.taprootTweak != nil: combineOpts = append( combineOpts, WithTaprootTweakedCombine( s.msg, s.ctx.keySet, s.ctx.opts.taprootTweak, s.ctx.shouldSort, ), ) - } else if len(s.ctx.opts.tweaks) != 0 { + case len(s.ctx.opts.tweaks) != 0: combineOpts = append( combineOpts, WithTweakedCombine( s.msg, s.ctx.keySet, s.ctx.opts.tweaks, diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index c13af98463..e61a22f2e5 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -176,6 +176,11 @@ type keyAggOption struct { // taprootTweak controls if the tweaks above should be applied in a BIP // 340 style. taprootTweak bool + + // bip86Tweak specifies that the taproot tweak should be done in a BIP + // 86 style, where we don't expect an actual tweak and instead just + // commit to the public key itself. + bip86Tweak bool } // WithKeysHash allows key aggregation to be optimize, by allowing the caller @@ -226,6 +231,22 @@ func WithTaprootKeyTweak(scriptRoot []byte) KeyAggOption { } } +// WithBIP86KeyTweak specifies that then during key aggregation, the BIP 86 +// tweak which just commits to the hash of the serialized public key should be +// used. This option should be used when signing with a key that was derived +// using BIP 86. +func WithBIP86KeyTweak() KeyAggOption { + return func(o *keyAggOption) { + o.tweaks = []KeyTweakDesc{ + { + IsXOnly: true, + }, + } + o.taprootTweak = true + o.bip86Tweak = true + } +} + // defaultKeyAggOptions returns the set of default arguments for key // aggregation. func defaultKeyAggOptions() *keyAggOption { @@ -370,18 +391,34 @@ func AggregateKeys(keys []*btcec.PublicKey, sort bool, // We'll copy over the key at this point, since this represents the // aggregated key before any tweaks have been applied. This'll be used // as the internal key for script path proofs. + finalKeyJ.ToAffine() combinedKey := btcec.NewPublicKey(&finalKeyJ.X, &finalKeyJ.Y) // At this point, if this is a taproot tweak, then we'll modify the // base tweak value to use the BIP 341 tweak value. if opts.taprootTweak { + // Emulate the same behavior as txscript.ComputeTaprootOutputKey + // which only operates on the x-only public key. + key, _ := schnorr.ParsePubKey(schnorr.SerializePubKey( + combinedKey, + )) + + // We only use the actual tweak bytes if we're not committing + // to a BIP-0086 key only spend output. Otherwise, we just + // commit to the internal key and an empty byte slice as the + // root hash. + tweakBytes := []byte{} + if !opts.bip86Tweak { + tweakBytes = opts.tweaks[0].Tweak[:] + } + // Compute the taproot key tagged hash of: // h_tapTweak(internalKey || scriptRoot). We only do this for // the first one, as you can only specify a single tweak when // using the taproot mode with this API. tapTweakHash := chainhash.TaggedHash( - chainhash.TagTapTweak, schnorr.SerializePubKey(combinedKey), - opts.tweaks[0].Tweak[:], + chainhash.TagTapTweak, schnorr.SerializePubKey(key), + tweakBytes, ) opts.tweaks[0].Tweak = *tapTweakHash } diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index bfd7c0818d..1ff3151300 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -324,6 +324,8 @@ func testMultiPartySign(t *testing.T, taprootTweak []byte, var ctxOpts []ContextOption switch { + case len(taprootTweak) == 0: + ctxOpts = append(ctxOpts, WithBip86TweakCtx()) case taprootTweak != nil: ctxOpts = append(ctxOpts, WithTaprootTweakCtx(taprootTweak)) case len(tweaks) != 0: @@ -469,4 +471,10 @@ func TestMuSigMultiParty(t *testing.T) { testMultiPartySign(t, testTweak[:]) }) + + t.Run("taproot_bip_86", func(t *testing.T) { + t.Parallel() + + testMultiPartySign(t, []byte{}) + }) } diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 16c5cd2fac..4f9439fe6a 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -117,6 +117,11 @@ type signOptions struct { // the taproot tweak also commits to the public key, which in this case // is the aggregated key before the tweak. taprootTweak []byte + + // bip86Tweak specifies that the taproot tweak should be done in a BIP + // 86 style, where we don't expect an actual tweak and instead just + // commit to the public key itself. + bip86Tweak bool } // defaultSignOptions returns the default set of signing operations. @@ -164,6 +169,20 @@ func WithTaprootSignTweak(scriptRoot []byte) SignOption { } } +// WithBip86SignTweak allows a caller to specify a tweak that should be used in +// a bip 340 manner when signing, factoring in BIP 86 as well. This differs +// from WithTaprootSignTweak as no true script root will be committed to, +// instead we just commit to the internal key. +// +// This option should be used in the taproot context to create a valid +// signature for the keypath spend for taproot, when the output key was +// generated using BIP 86. +func WithBip86SignTweak() SignOption { + return func(o *signOptions) { + o.bip86Tweak = true + } +} + // Sign generates a musig2 partial signature given the passed key set, secret // nonce, public nonce, and private keys. This method returns an error if the // generated nonces are either too large, or end up mapping to the point at @@ -200,11 +219,16 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, keyAggOpts := []KeyAggOption{ WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), } - if opts.taprootTweak != nil { + switch { + case opts.bip86Tweak: + keyAggOpts = append( + keyAggOpts, WithBIP86KeyTweak(), + ) + case opts.taprootTweak != nil: keyAggOpts = append( keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak), ) - } else { + case len(opts.tweaks) != 0: keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...)) } @@ -394,11 +418,16 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, keyAggOpts := []KeyAggOption{ WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), } - if opts.taprootTweak != nil { + switch { + case opts.bip86Tweak: + keyAggOpts = append( + keyAggOpts, WithBIP86KeyTweak(), + ) + case opts.taprootTweak != nil: keyAggOpts = append( keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak), ) - } else { + case len(opts.tweaks) != 0: keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...)) } @@ -569,7 +598,7 @@ func WithTweakedCombine(msg [32]byte, keys []*btcec.PublicKey, // output key, where the internal key is the aggregated key pre-tweak. // // This option should be used over WithTweakedCombine when attempting to -// aggregate signatures for a top-level taproot keysepnd, where the output key +// aggregate signatures for a top-level taproot keyspend, where the output key // commits to a script root. func WithTaprootTweakedCombine(msg [32]byte, keys []*btcec.PublicKey, scriptRoot []byte, sort bool) CombineOption { @@ -585,6 +614,28 @@ func WithTaprootTweakedCombine(msg [32]byte, keys []*btcec.PublicKey, } } +// WithBip86TweakedCombine is similar to the WithTaprootTweakedCombine option, +// but assumes a BIP 341 + BIP 86 context where the final tweaked key is to be +// used as the output key, where the internal key is the aggregated key +// pre-tweak. +// +// This option should be used over WithTaprootTweakedCombine when attempting to +// aggregate signatures for a top-level taproot keyspend, where the output key +// was generated using BIP 86. +func WithBip86TweakedCombine(msg [32]byte, keys []*btcec.PublicKey, + sort bool) CombineOption { + + return func(o *combineOptions) { + combinedKey, _, tweakAcc, _ := AggregateKeys( + keys, sort, WithBIP86KeyTweak(), + ) + + o.msg = msg + o.combinedKey = combinedKey.FinalKey + o.tweakAcc = tweakAcc + } +} + // CombineSigs combines the set of public keys given the final aggregated // nonce, and the series of partial signatures for each nonce. func CombineSigs(combinedNonce *btcec.PublicKey, From 65e4fc0dea1758ed5439b651aad4622135e23690 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 26 Apr 2022 21:33:10 -0700 Subject: [PATCH 0682/1056] btcec/schnorr/musig2: update nonce generation to support optional inputs In this commit, we update the nonce generation to support optional parameters defined in the latest BIP draft. These parameters are optional, but if specified my mitigate the effect of weak randomness when generating the nonce. Given the protocol doesn't require signers to prove how they generate their nonces, this update is mainly to ensure strict spec compliance, and is effectively optional. --- btcec/go.mod | 1 + btcec/go.sum | 2 + btcec/schnorr/musig2/nonces.go | 206 ++++++++++++++++++++++++++++++--- 3 files changed, 194 insertions(+), 15 deletions(-) diff --git a/btcec/go.mod b/btcec/go.mod index 8c7cc1d63c..a5e8c3abef 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -6,6 +6,7 @@ require ( github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 + golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 ) require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect diff --git a/btcec/go.sum b/btcec/go.sum index 0004a783bb..bd484d5ed4 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -6,3 +6,5 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 h1:rxKZ2gOnYxjfmakvUUqh9Gyb6KXfrj7JWTxORTYqb0E= +golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 4fd76450d9..c0ece86fa4 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -3,9 +3,14 @@ package musig2 import ( + "bytes" "crypto/rand" + "encoding/binary" + "io" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) const ( @@ -19,6 +24,18 @@ const ( SecNonceSize = 64 ) +var ( + // NonceAuxTag is the tag used to optionally mix in the secret key with + // the set of aux randomness. + NonceAuxTag = []byte("MuSig/aux") + + // NonceGenTag is used to generate the value (from a set of required an + // optional field) that will be used as the part of the secret nonce. + NonceGenTag = []byte("Musig/nonce") + + byteOrder = binary.BigEndian +) + // zeroSecNonce is a secret nonce that's all zeroes. This is used to check that // we're not attempting to re-use a nonce, and also protect callers from it. var zeroSecNonce [SecNonceSize]byte @@ -71,21 +88,173 @@ func secNonceToPubNonce(secNonce [SecNonceSize]byte) [PubNonceSize]byte { // generation happens. type NonceGenOption func(*nonceGenOpts) -// nonceGenOpts is the set of options that control how nonce generation happens. +// nonceGenOpts is the set of options that control how nonce generation +// happens. type nonceGenOpts struct { - randReader func(b []byte) (int, error) + // randReader is what we'll use to generate a set of random bytes. If + // unspecified, then the normal crypto/rand rand.Read method will be + // used in place. + randReader io.Reader + + // secretKey is an optional argument that's used to further augment the + // generated nonce by xor'ing it with this secret key. + secretKey []byte + + // combinedKey is an optional argument that if specified, will be + // combined along with the nonce generation. + combinedKey []byte + + // msg is an optional argument that will be mixed into the nonce + // derivation algorithm. + msg []byte + + // auxInput is an optional argument that will be mixed into the nonce + // derivation algorithm. + auxInput []byte +} + +// cryptoRandAdapter is an adapter struct that allows us to pass in the package +// level Read function from crypto/rand into a context that accepts an +// io.Reader. +type cryptoRandAdapter struct { +} + +// Read implements the io.Reader interface for the crypto/rand package. By +// default, we always use the crypto/rand reader, but the caller is able to +// specify their own generation, which can be useful for deterministic tests. +func (c *cryptoRandAdapter) Read(p []byte) (n int, err error) { + return rand.Read(p) } // defaultNonceGenOpts returns the default set of nonce generation options. func defaultNonceGenOpts() *nonceGenOpts { return &nonceGenOpts{ - // By default, we always use the crypto/rand reader, but the - // caller is able to specify their own generation, which can be - // useful for deterministic tests. - randReader: rand.Read, + randReader: &cryptoRandAdapter{}, + } +} + +// WithCustomRand allows a caller to use a custom random number generator in +// place for crypto/rand. This should only really be used to generate +// determinstic tests. +func WithCustomRand(r io.Reader) NonceGenOption { + return func(o *nonceGenOpts) { + o.randReader = r + } +} + +// WithNonceSecretKeyAux allows a caller to optionally specify a secret key +// that should be used to augment the randomness used to generate the nonces. +func WithNonceSecretKeyAux(secKey *btcec.PrivateKey) NonceGenOption { + return func(o *nonceGenOpts) { + o.secretKey = secKey.Serialize() + } +} + +// WithNonceCombinedKeyAux allows a caller to optionally specify the combined +// key used in this signing session to further augment the randomness used to +// generate nonces. +func WithNonceCombinedKeyAux(combinedKey *btcec.PublicKey) NonceGenOption { + return func(o *nonceGenOpts) { + o.combinedKey = schnorr.SerializePubKey(combinedKey) } } +// WithNonceMessageAux allows a caller to optionally specify a message to be +// mixed into the randomness generated to create the nonce. +func WithNonceMessageAux(msg [32]byte) NonceGenOption { + return func(o *nonceGenOpts) { + o.msg = msg[:] + } +} + +// WithNonceAuxInput is a set of auxiliary randomness, similar to BIP 340 that +// can be used to further augment the nonce generation process. +func WithNonceAuxInput(aux []byte) NonceGenOption { + return func(o *nonceGenOpts) { + o.auxInput = aux + } +} + +// lengthWriter is a function closure that allows a caller to control how the +// length prefix of a byte slice is written. +type lengthWriter func(w io.Writer, b []byte) error + +// uint8Writer is an implementation of lengthWriter that writes the length of +// the byte slice using 1 byte. +func uint8Writer(w io.Writer, b []byte) error { + return binary.Write(w, byteOrder, uint8(len(b))) +} + +// uint8Writer is an implementation of lengthWriter that writes the length of +// the byte slice using 4 bytes. +func uint32Writer(w io.Writer, b []byte) error { + return binary.Write(w, byteOrder, uint32(len(b))) +} + +// writeBytesPrefix is used to write out: len(b) || b, to the passed io.Writer. +// The lengthWriter function closure is used to allow the caller to specify the +// precise byte packing of the length. +func writeBytesPrefix(w io.Writer, b []byte, lenWriter lengthWriter) error { + // Write out the length of the byte first, followed by the set of bytes + // itself. + if err := lenWriter(w, b); err != nil { + return err + } + + if _, err := w.Write(b); err != nil { + return err + } + + return nil +} + +// genNonceAuxBytes writes out the full byte string used to derive a secret +// nonce based on some initial randomness as well as the series of optional +// fields. The byte string used for derivation is: +// * tagged_hash("MuSig/nonce", rand || len(aggpk) || aggpk || len(m) +// || m || len(in) || in || i). +// +// where i is the ith secret nonce being generated. +func genNonceAuxBytes(rand []byte, i int, + opts *nonceGenOpts) (*chainhash.Hash, error) { + + var w bytes.Buffer + + // First, write out the randomness generated in the prior step. + if _, err := w.Write(rand); err != nil { + return nil, err + } + + // Next, we'll write out: len(aggpk) || aggpk. + err := writeBytesPrefix(&w, opts.combinedKey, uint8Writer) + if err != nil { + return nil, err + } + + // Next, we'll write out the length prefixed message. + err = writeBytesPrefix(&w, opts.msg, uint8Writer) + if err != nil { + return nil, err + } + + // Finally we'll write out the auxiliary input. + err = writeBytesPrefix(&w, opts.auxInput, uint32Writer) + if err != nil { + return nil, err + } + + // Next we'll write out the interaction/index number which will + // uniquely generate two nonces given the rest of the possibly static + // parameters. + if err := binary.Write(&w, byteOrder, uint8(i)); err != nil { + return nil, err + } + + // With the message buffer complete, we'll now derive the tagged hash + // using our set of params. + return chainhash.TaggedHash(NonceGenTag, w.Bytes()), nil +} + // GenNonces generates the secret nonces, as well as the public nonces which // correspond to an EC point generated using the secret nonce as a private key. func GenNonces(options ...NonceGenOption) (*Nonces, error) { @@ -94,24 +263,31 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { opt(opts) } - // Generate two 32-byte random values that'll be the private keys to - // the public nonces. - var k1, k2 [32]byte - if _, err := opts.randReader(k1[:]); err != nil { + // First, we'll start out by generating 32 random bytes drawn from our + // CSPRNG. + var randBytes [32]byte + if _, err := opts.randReader.Read(randBytes[:]); err != nil { return nil, err } - if _, err := opts.randReader(k2[:]); err != nil { + + // Using our randomness and the set of optional params, generate our + // two secret nonces: k1 and k2. + k1, err := genNonceAuxBytes(randBytes[:], 1, opts) + if err != nil { + return nil, err + } + k2, err := genNonceAuxBytes(randBytes[:], 2, opts) + if err != nil { return nil, err } - - var nonces Nonces var k1Mod, k2Mod btcec.ModNScalar - k1Mod.SetBytes(&k1) - k2Mod.SetBytes(&k2) + k1Mod.SetBytes((*[32]byte)(k1)) + k2Mod.SetBytes((*[32]byte)(k2)) // The secret nonces are serialized as the concatenation of the two 32 // byte secret nonce values. + var nonces Nonces k1Mod.PutBytesUnchecked(nonces.SecNonce[:]) k2Mod.PutBytesUnchecked(nonces.SecNonce[btcec.PrivKeyBytesLen:]) From 55c8cab7694a55be8bd30975d2142ecdb5bb1615 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 26 Apr 2022 21:33:34 -0700 Subject: [PATCH 0683/1056] btcec/schnorr/musig2: add new key tweak combination test vectors --- btcec/schnorr/musig2/musig2_test.go | 106 ++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 23 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 1ff3151300..71378f61ba 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -142,6 +142,23 @@ var ( signSetKeys = []*btcec.PublicKey{signSetPubKey, signSetKey2, signSetKey3} ) +func formatTweakParity(tweaks []KeyTweakDesc) string { + var s string + for _, tweak := range tweaks { + s += fmt.Sprintf("%v/", tweak.IsXOnly) + } + + // Snip off that last '/'. + s = s[:len(s)-1] + + return s +} + +func genTweakParity(tweak KeyTweakDesc, isXOnly bool) KeyTweakDesc { + tweak.IsXOnly = isXOnly + return tweak +} + // TestMuSig2SigningTestVectors tests that the musig2 implementation produces // the same set of signatures. func TestMuSig2SigningTestVectors(t *testing.T) { @@ -161,10 +178,43 @@ func TestMuSig2SigningTestVectors(t *testing.T) { copy(secNonce[:], mustParseHex("508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61")) copy(secNonce[32:], mustParseHex("FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7")) + tweak1 := KeyTweakDesc{ + Tweak: [32]byte{ + 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, + 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, + 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, + 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, + }, + } + tweak2 := KeyTweakDesc{ + Tweak: [32]byte{ + 0xae, 0x2e, 0xa7, 0x97, 0xcc, 0xf, 0xe7, 0x2a, + 0xc5, 0xb9, 0x7b, 0x97, 0xf3, 0xc6, 0x95, 0x7d, + 0x7e, 0x41, 0x99, 0xa1, 0x67, 0xa5, 0x8e, 0xb0, + 0x8b, 0xca, 0xff, 0xda, 0x70, 0xac, 0x4, 0x55, + }, + } + tweak3 := KeyTweakDesc{ + Tweak: [32]byte{ + 0xf5, 0x2e, 0xcb, 0xc5, 0x65, 0xb3, 0xd8, 0xbe, + 0xa2, 0xdf, 0xd5, 0xb7, 0x5a, 0x4f, 0x45, 0x7e, + 0x54, 0x36, 0x98, 0x9, 0x32, 0x2e, 0x41, 0x20, + 0x83, 0x16, 0x26, 0xf2, 0x90, 0xfa, 0x87, 0xe0, + }, + } + tweak4 := KeyTweakDesc{ + Tweak: [32]byte{ + 0x19, 0x69, 0xad, 0x73, 0xcc, 0x17, 0x7f, 0xa0, + 0xb4, 0xfc, 0xed, 0x6d, 0xf1, 0xf7, 0xbf, 0x99, + 0x7, 0xe6, 0x65, 0xfd, 0xe9, 0xba, 0x19, 0x6a, + 0x74, 0xfe, 0xd0, 0xa3, 0xcf, 0x5a, 0xef, 0x9d, + }, + } + testCases := []struct { keyOrder []int expectedPartialSig []byte - tweak *KeyTweakDesc + tweaks []KeyTweakDesc }{ { keyOrder: []int{0, 1, 2}, @@ -178,30 +228,40 @@ func TestMuSig2SigningTestVectors(t *testing.T) { keyOrder: []int{1, 2, 0}, expectedPartialSig: mustParseHex("0D5B651E6DE34A29A12DE7A8B4183B4AE6A7F7FBE15CDCAFA4A3D1BCAABC7517"), }, + + // A single x-only tweak. { keyOrder: []int{1, 2, 0}, expectedPartialSig: mustParseHex("5e24c7496b565debc3b9639e6f1304a21597f9603d3ab05b4913641775e1375b"), - tweak: &KeyTweakDesc{ - Tweak: [32]byte{ - 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, - 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, - 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, - 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, - }, - IsXOnly: true, - }, + tweaks: []KeyTweakDesc{genTweakParity(tweak1, true)}, }, + + // A single ordinary tweak. { keyOrder: []int{1, 2, 0}, expectedPartialSig: mustParseHex("78408ddcab4813d1394c97d493ef1084195c1d4b52e63ecd7bc5991644e44ddd"), - tweak: &KeyTweakDesc{ - Tweak: [32]byte{ - 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, - 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, - 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, - 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, - }, - IsXOnly: false, + tweaks: []KeyTweakDesc{genTweakParity(tweak1, false)}, + }, + + // An ordinary tweak then an x-only tweak. + { + keyOrder: []int{1, 2, 0}, + expectedPartialSig: mustParseHex("C3A829A81480E36EC3AB052964509A94EBF34210403D16B226A6F16EC85B7357"), + tweaks: []KeyTweakDesc{ + genTweakParity(tweak1, false), + genTweakParity(tweak2, true), + }, + }, + + // Four tweaks, in the order: x-only, ordinary, x-only, ordinary. + { + keyOrder: []int{1, 2, 0}, + expectedPartialSig: mustParseHex("8C4473C6A382BD3C4AD7BE59818DA5ED7CF8CEC4BC21996CFDA08BB4316B8BC7"), + tweaks: []KeyTweakDesc{ + genTweakParity(tweak1, true), + genTweakParity(tweak2, false), + genTweakParity(tweak3, true), + genTweakParity(tweak4, false), }, }, } @@ -210,9 +270,9 @@ func TestMuSig2SigningTestVectors(t *testing.T) { copy(msg[:], signTestMsg) for _, testCase := range testCases { - testName := fmt.Sprintf("%v/tweak=%v", testCase.keyOrder, testCase.tweak != nil) - if testCase.tweak != nil { - testName += fmt.Sprintf("/x_only=%v", testCase.tweak.IsXOnly) + testName := fmt.Sprintf("%v/tweak=%v", testCase.keyOrder, len(testCase.tweaks) != 0) + if len(testCase.tweaks) != 0 { + testName += fmt.Sprintf("/x_only=%v", formatTweakParity(testCase.tweaks)) } t.Run(testName, func(t *testing.T) { @@ -222,9 +282,9 @@ func TestMuSig2SigningTestVectors(t *testing.T) { } var opts []SignOption - if testCase.tweak != nil { + if len(testCase.tweaks) != 0 { opts = append( - opts, WithTweaks(*testCase.tweak), + opts, WithTweaks(testCase.tweaks...), ) } From 953e2dd94aa7590d793cbf9c074c0ee6ebbdf6cc Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 27 Apr 2022 16:47:11 -0700 Subject: [PATCH 0684/1056] btcec/schnorr/musig2: enable early nonce generation w/ a context In this commit, we enable early nonce generation, allowing callers to obtain generated nonces before the total set of signers is actually known. This type of nonce generation is useful for contexts like LN funding when we want to minimize the round trips and send nonces before we know the pubkey of the other party. --- btcec/schnorr/musig2/context.go | 346 ++++++++++++++++++++++------ btcec/schnorr/musig2/musig2_test.go | 187 ++++++++++++++- btcec/schnorr/musig2/nonces.go | 2 +- 3 files changed, 467 insertions(+), 68 deletions(-) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 2461f962ab..298fe96179 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -10,6 +10,12 @@ import ( ) var ( + // ErrSignersNotSpecified is returned when a caller attempts to create + // a context without specifying either the total number of signers, or + // the complete set of singers. + ErrSignersNotSpecified = fmt.Errorf("total number of signers or all " + + "signers must be known") + // ErrSignerNotInKeySet is returned when a the private key for a signer // isn't included in the set of signing public keys. ErrSignerNotInKeySet = fmt.Errorf("signing key is not found in key" + @@ -19,6 +25,16 @@ var ( // many times for a given signing session. ErrAlredyHaveAllNonces = fmt.Errorf("already have all nonces") + // ErrNotEnoughSigners is returned when a caller attempts to create a + // session from a context, but before all the required signers are + // known. + ErrNotEnoughSigners = fmt.Errorf("not enough signers") + + // ErrAlredyHaveAllNonces is returned when a caller attempts to + // register a signer, once we already have the total set of known + // signers. + ErrAlreadyHaveAllSigners = fmt.Errorf("all signers registered") + // ErrAlredyHaveAllSigs is called when CombineSig is called too many // times for a given signing session. ErrAlredyHaveAllSigs = fmt.Errorf("already have all sigs") @@ -39,6 +55,10 @@ var ( // ErrTaprootInternalKeyUnavailable is returned when a user attempts to // obtain the ErrTaprootInternalKeyUnavailable = fmt.Errorf("taproot tweak not used") + + // ErrNotEnoughSigners is returned if a caller attempts to obtain an + // early nonce when it wasn't specified + ErrNoEarlyNonce = fmt.Errorf("no early nonce available") ) // Context is a managed signing context for musig2. It takes care of things @@ -50,9 +70,6 @@ type Context struct { // pubKey is our even-y coordinate public key. pubKey *btcec.PublicKey - // keySet is the set of all signers. - keySet []*btcec.PublicKey - // combinedKey is the aggregated public key. combinedKey *AggregateKey @@ -69,6 +86,10 @@ type Context struct { // shouldSort keeps track of if the public keys should be sorted before // any operations. shouldSort bool + + // sessionNonce will be populated if the earlyNonce option is true. + // After the first session is created, this nonce will be blanked out. + sessionNonce *Nonces } // ContextOption is a functional option argument that allows callers to modify @@ -94,6 +115,17 @@ type contextOptions struct { // bip86Tweak if true, then the weak will just be // h_tapTweak(internalKey) as there is no true script root. bip86Tweak bool + + // keySet is the complete set of signers for this context. + keySet []*btcec.PublicKey + + // numSigners is the total number of signers that will eventually be a + // part of the context. + numSigners int + + // earlyNonce determines if a nonce should be generated during context + // creation, to be automatically passed to the created session. + earlyNonce bool } // defaultContextOptions returns the default context options. @@ -129,12 +161,43 @@ func WithBip86TweakCtx() ContextOption { } } +// WithKnownSigners is an optional parameter that should be used if a session +// can be created as soon as all the singers are known. +func WithKnownSigners(signers []*btcec.PublicKey) ContextOption { + return func(o *contextOptions) { + o.keySet = signers + o.numSigners = len(signers) + } +} + +// WithNumSigners is a functional option used to specify that a context should +// be created without knowing all the signers. Instead the total number of +// signers is specified to ensure that a session can only be created once all +// the signers are known. +// +// NOTE: Either WithKnownSigners or WithNumSigners MUST be specified. +func WithNumSigners(n int) ContextOption { + return func(o *contextOptions) { + o.numSigners = n + } +} + +// WithEarlyNonceGen allow a caller to specify that a nonce should be generated +// early, before the session is created. This should be used in protocols that +// require some partial nonce exchange before all the signers are known. +// +// NOTE: This option must only be specified with the WithNumSigners option. +func WithEarlyNonceGen() ContextOption { + return func(o *contextOptions) { + o.earlyNonce = true + } +} + // NewContext creates a new signing context with the passed singing key and set // of public keys for each of the other signers. // // NOTE: This struct should be used over the raw Sign API whenever possible. -func NewContext(signingKey *btcec.PrivateKey, - signers []*btcec.PublicKey, shouldSort bool, +func NewContext(signingKey *btcec.PrivateKey, shouldSort bool, ctxOpts ...ContextOption) (*Context, error) { // First, parse the set of optional context options. @@ -143,10 +206,6 @@ func NewContext(signingKey *btcec.PrivateKey, option(opts) } - // As a sanity check, make sure the signing key is actually amongst the sit - // of signers. - // - // TODO(roasbeef): instead have pass all the _other_ signers? pubKey, err := schnorr.ParsePubKey( schnorr.SerializePubKey(signingKey.PubKey()), ) @@ -154,64 +213,156 @@ func NewContext(signingKey *btcec.PrivateKey, return nil, err } + ctx := &Context{ + signingKey: signingKey, + pubKey: pubKey, + opts: opts, + shouldSort: shouldSort, + } + + switch { + + // We know all the signers, so we can compute the aggregated key, along + // with all the other intermediate state we need to do signing and + // verification. + case opts.keySet != nil: + if err := ctx.combineSignerKeys(); err != nil { + return nil, err + } + + // The total signers are known, so we add ourselves, and skip key + // aggregation. + case opts.numSigners != 0: + // Otherwise, we'll add ourselves as the only known signer, and + // await further calls to RegisterSigner before a session can + // be created. + opts.keySet = make([]*btcec.PublicKey, 0, opts.numSigners) + opts.keySet = append(opts.keySet, pubKey) + + // If early nonce generation is specified, then we'll generate + // the nonce now to pass in to the session once all the callers + // are known. + if opts.earlyNonce { + ctx.sessionNonce, err = GenNonces() + if err != nil { + return nil, err + } + } + + default: + return nil, ErrSignersNotSpecified + } + + return ctx, nil +} + +// combineSignerKeys is used to compute the aggregated signer key once all the +// signers are known. +func (c *Context) combineSignerKeys() error { + // As a sanity check, make sure the signing key is actually + // amongst the sit of signers. var keyFound bool - for _, key := range signers { - if key.IsEqual(pubKey) { + for _, key := range c.opts.keySet { + if key.IsEqual(c.pubKey) { keyFound = true break } } if !keyFound { - return nil, ErrSignerNotInKeySet + return ErrSignerNotInKeySet } - // Now that we know that we're actually a signer, we'll generate the - // key hash finger print and second unique key index so we can speed up - // signing later. - keysHash := keyHashFingerprint(signers, shouldSort) - uniqueKeyIndex := secondUniqueKeyIndex(signers, shouldSort) + // Now that we know that we're actually a signer, we'll + // generate the key hash finger print and second unique key + // index so we can speed up signing later. + c.keysHash = keyHashFingerprint(c.opts.keySet, c.shouldSort) + c.uniqueKeyIndex = secondUniqueKeyIndex( + c.opts.keySet, c.shouldSort, + ) keyAggOpts := []KeyAggOption{ - WithKeysHash(keysHash), WithUniqueKeyIndex(uniqueKeyIndex), + WithKeysHash(c.keysHash), + WithUniqueKeyIndex(c.uniqueKeyIndex), } switch { - case opts.bip86Tweak: + case c.opts.bip86Tweak: keyAggOpts = append( keyAggOpts, WithBIP86KeyTweak(), ) - case opts.taprootTweak != nil: + case c.opts.taprootTweak != nil: keyAggOpts = append( - keyAggOpts, WithTaprootKeyTweak(opts.taprootTweak), + keyAggOpts, WithTaprootKeyTweak(c.opts.taprootTweak), ) - case len(opts.tweaks) != 0: - keyAggOpts = append(keyAggOpts, WithKeyTweaks(opts.tweaks...)) + case len(c.opts.tweaks) != 0: + keyAggOpts = append(keyAggOpts, WithKeyTweaks(c.opts.tweaks...)) } - // Next, we'll use this information to compute the aggregated public - // key that'll be used for signing in practice. - combinedKey, _, _, err := AggregateKeys( - signers, shouldSort, keyAggOpts..., + // Next, we'll use this information to compute the aggregated + // public key that'll be used for signing in practice. + var err error + c.combinedKey, _, _, err = AggregateKeys( + c.opts.keySet, c.shouldSort, keyAggOpts..., ) if err != nil { - return nil, err + return err } - return &Context{ - signingKey: signingKey, - pubKey: pubKey, - keySet: signers, - combinedKey: combinedKey, - uniqueKeyIndex: uniqueKeyIndex, - keysHash: keysHash, - opts: opts, - shouldSort: shouldSort, - }, nil + return nil +} + +// EarlySessionNonce returns the early session nonce, if available. +func (c *Context) EarlySessionNonce() (*Nonces, error) { + if c.sessionNonce == nil { + return nil, ErrNoEarlyNonce + } + + return c.sessionNonce, nil +} + +// RegisterSigner allows a caller to register a signer after the context has +// been created. This will be used in scenarios where the total number of +// signers is known, but nonce exchange needs to happen before all the signers +// are known. +// +// A bool is returned which indicates if all the signers have been registered. +// +// NOTE: If the set of keys are not to be sorted during signing, then the +// ordering each key is registered with MUST match the desired ordering. +func (c *Context) RegisterSigner(pub *btcec.PublicKey) (bool, error) { + haveAllSigners := len(c.opts.keySet) == c.opts.numSigners + if haveAllSigners { + return false, ErrAlreadyHaveAllSigners + } + + c.opts.keySet = append(c.opts.keySet, pub) + + // If we have the expected number of signers at this point, then we can + // generate the aggregated key and other necessary information. + haveAllSigners = len(c.opts.keySet) == c.opts.numSigners + if haveAllSigners { + if err := c.combineSignerKeys(); err != nil { + return false, err + } + } + + return haveAllSigners, nil +} + +// NumRegisteredSigners returns the total number of registered signers. +func (c *Context) NumRegisteredSigners() int { + return len(c.opts.keySet) } // CombinedKey returns the combined public key that will be used to generate // multi-signatures against. -func (c *Context) CombinedKey() *btcec.PublicKey { - return c.combinedKey.FinalKey +func (c *Context) CombinedKey() (*btcec.PublicKey, error) { + // If the caller hasn't registered all the signers at this point, then + // the combined key won't be available. + if c.combinedKey == nil { + return nil, ErrNotEnoughSigners + } + + return c.combinedKey.FinalKey, nil } // PubKey returns the public key of the signer of this session. @@ -221,8 +372,8 @@ func (c *Context) PubKey() btcec.PublicKey { // SigningKeys returns the set of keys used for signing. func (c *Context) SigningKeys() []*btcec.PublicKey { - keys := make([]*btcec.PublicKey, len(c.keySet)) - copy(keys, c.keySet) + keys := make([]*btcec.PublicKey, len(c.opts.keySet)) + copy(keys, c.opts.keySet) return keys } @@ -230,9 +381,15 @@ func (c *Context) SigningKeys() []*btcec.PublicKey { // TaprootInternalKey returns the internal taproot key, which is the aggregated // key _before_ the tweak is applied. If a taproot tweak was specified, then // CombinedKey() will return the fully tweaked output key, with this method -// returning the internal key. If a taproot tweak wasn't speciifed, then this +// returning the internal key. If a taproot tweak wasn't specified, then this // method will return an error. func (c *Context) TaprootInternalKey() (*btcec.PublicKey, error) { + // If the caller hasn't registered all the signers at this point, then + // the combined key won't be available. + if c.combinedKey == nil { + return nil, ErrNotEnoughSigners + } + if c.opts.taprootTweak == nil && !c.opts.bip86Tweak { return nil, ErrTaprootInternalKeyUnavailable } @@ -240,6 +397,30 @@ func (c *Context) TaprootInternalKey() (*btcec.PublicKey, error) { return c.combinedKey.PreTweakedKey, nil } +// SessionOption is a functional option argument that allows callers to modify +// the musig2 signing is done within a session. +type SessionOption func(*sessionOptions) + +// sessionOptions houses the set of functional options that can be used to +// modify the musig2 signing protocol. +type sessionOptions struct { + externalNonce *Nonces +} + +// defaultSessionOptions returns the default session options. +func defaultSessionOptions() *sessionOptions { + return &sessionOptions{} +} + +// WithPreGeneratedNonce allows a caller to start a session using a nonce +// they've generated themselves. This may be useful in protocols where all the +// signer keys may not be known before nonce exchange needs to occur. +func WithPreGeneratedNonce(nonce *Nonces) SessionOption { + return func(o *sessionOptions) { + o.externalNonce = nonce + } +} + // Session represents a musig2 signing session. A new instance should be // created each time a multi-signature is needed. The session struct handles // nonces management, incremental partial sig vitrifaction, as well as final @@ -248,6 +429,8 @@ func (c *Context) TaprootInternalKey() (*btcec.PublicKey, error) { // // NOTE: This struct should be used over the raw Sign API whenever possible. type Session struct { + opts *sessionOptions + ctx *Context localNonces *Nonces @@ -264,20 +447,52 @@ type Session struct { finalSig *schnorr.Signature } -// TODO(roasbeef): optional arg to allow parsing in pre-generated nonces - // NewSession creates a new musig2 signing session. -func (c *Context) NewSession() (*Session, error) { - localNonces, err := GenNonces() - if err != nil { - return nil, err +func (c *Context) NewSession(options ...SessionOption) (*Session, error) { + opts := defaultSessionOptions() + for _, opt := range options { + opt(opts) + } + + // At this point we verify that we know of all the signers, as + // otherwise we can't proceed with the session. This check is intended + // to catch misuse of the API wherein a caller forgets to register the + // remaining signers if they're doing nonce generation ahead of time. + if len(c.opts.keySet) != c.opts.numSigners { + return nil, ErrNotEnoughSigners + } + + // If an early nonce was specified, then we'll automatically add the + // corresponding session option for the caller. + var localNonces *Nonces + if c.sessionNonce != nil { + // Apply the early nonce to the session, and also blank out the + // session nonce on the context to ensure it isn't ever re-used + // for another session. + localNonces = c.sessionNonce + c.sessionNonce = nil + } else if opts.externalNonce != nil { + // Otherwise if there's a custom nonce passed in via the + // session options, then use that instead. + localNonces = opts.externalNonce + } + + // Now that we know we have enough signers, we'll either use the caller + // specified nonce, or generate a fresh set. + var err error + if localNonces == nil { + localNonces, err = GenNonces() + if err != nil { + return nil, err + } } s := &Session{ + opts: opts, ctx: c, localNonces: localNonces, - pubNonces: make([][PubNonceSize]byte, 0, len(c.keySet)), - sigs: make([]*PartialSignature, 0, len(c.keySet)), + pubNonces: make([][PubNonceSize]byte, 0, c.opts.numSigners), + sigs: make([]*PartialSignature, 0, c.opts.numSigners), } s.pubNonces = append(s.pubNonces, localNonces.PubNonce) @@ -302,9 +517,9 @@ func (s *Session) NumRegisteredNonces() int { // signers. This method returns true once all the public nonces have been // accounted for. func (s *Session) RegisterPubNonce(nonce [PubNonceSize]byte) (bool, error) { - // If we already have all the nonces, then this method was called too many - // times. - haveAllNonces := len(s.pubNonces) == len(s.ctx.keySet) + // If we already have all the nonces, then this method was called too + // many times. + haveAllNonces := len(s.pubNonces) == s.ctx.opts.numSigners if haveAllNonces { return false, ErrAlredyHaveAllNonces } @@ -312,7 +527,7 @@ func (s *Session) RegisterPubNonce(nonce [PubNonceSize]byte) (bool, error) { // Add this nonce and check again if we already have tall the nonces we // need. s.pubNonces = append(s.pubNonces, nonce) - haveAllNonces = len(s.pubNonces) == len(s.ctx.keySet) + haveAllNonces = len(s.pubNonces) == s.ctx.opts.numSigners // If we have all the nonces, then we can go ahead and combine them // now. @@ -334,8 +549,6 @@ func (s *Session) RegisterPubNonce(nonce [PubNonceSize]byte) (bool, error) { func (s *Session) Sign(msg [32]byte, signOpts ...SignOption) (*PartialSignature, error) { - s.msg = msg - switch { // If no local nonce is present, then this means we already signed, so // we'll return an error to prevent nonce re-use. @@ -363,7 +576,7 @@ func (s *Session) Sign(msg [32]byte, partialSig, err := Sign( s.localNonces.SecNonce, s.ctx.signingKey, *s.combinedNonce, - s.ctx.keySet, msg, signOpts..., + s.ctx.opts.keySet, msg, signOpts..., ) // Now that we've generated our signature, we'll make sure to blank out @@ -374,6 +587,8 @@ func (s *Session) Sign(msg [32]byte, return nil, err } + s.msg = msg + s.ourSig = partialSig s.sigs = append(s.sigs, partialSig) @@ -386,7 +601,7 @@ func (s *Session) Sign(msg [32]byte, func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { // First check if we already have all the signatures we need. We // already accumulated our own signature when we generated the sig. - haveAllSigs := len(s.sigs) == len(s.ctx.keySet) + haveAllSigs := len(s.sigs) == len(s.ctx.opts.keySet) if haveAllSigs { return false, ErrAlredyHaveAllSigs } @@ -397,7 +612,7 @@ func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { // Accumulate this sig, and check again if we have all the sigs we // need. s.sigs = append(s.sigs, sig) - haveAllSigs = len(s.sigs) == len(s.ctx.keySet) + haveAllSigs = len(s.sigs) == len(s.ctx.opts.keySet) // If we have all the signatures, then we can combine them all into the // final signature. @@ -407,21 +622,22 @@ func (s *Session) CombineSig(sig *PartialSignature) (bool, error) { case s.ctx.opts.bip86Tweak: combineOpts = append( combineOpts, WithBip86TweakedCombine( - s.msg, s.ctx.keySet, s.ctx.shouldSort, + s.msg, s.ctx.opts.keySet, + s.ctx.shouldSort, ), ) case s.ctx.opts.taprootTweak != nil: combineOpts = append( combineOpts, WithTaprootTweakedCombine( - s.msg, s.ctx.keySet, s.ctx.opts.taprootTweak, - s.ctx.shouldSort, + s.msg, s.ctx.opts.keySet, + s.ctx.opts.taprootTweak, s.ctx.shouldSort, ), ) case len(s.ctx.opts.tweaks) != 0: combineOpts = append( combineOpts, WithTweakedCombine( - s.msg, s.ctx.keySet, s.ctx.opts.tweaks, - s.ctx.shouldSort, + s.msg, s.ctx.opts.keySet, + s.ctx.opts.tweaks, s.ctx.shouldSort, ), ) } diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 71378f61ba..df3f78c93c 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -6,6 +6,7 @@ import ( "bytes" "crypto/sha256" "encoding/hex" + "errors" "fmt" "sync" "testing" @@ -392,20 +393,25 @@ func testMultiPartySign(t *testing.T, taprootTweak []byte, ctxOpts = append(ctxOpts, WithTweakedContext(tweaks...)) } + ctxOpts = append(ctxOpts, WithKnownSigners(signSet)) + // Now that we have all the signers, we'll make a new context, then // generate a new session for each of them(which handles nonce // generation). signers := make([]*Session, numSigners) for i, signerKey := range signerKeys { signCtx, err := NewContext( - signerKey, signSet, false, ctxOpts..., + signerKey, false, ctxOpts..., ) if err != nil { t.Fatalf("unable to generate context: %v", err) } if combinedKey == nil { - combinedKey = signCtx.CombinedKey() + combinedKey, err = signCtx.CombinedKey() + if err != nil { + t.Fatalf("combined key not available: %v", err) + } } session, err := signCtx.NewSession() @@ -538,3 +544,180 @@ func TestMuSigMultiParty(t *testing.T) { testMultiPartySign(t, []byte{}) }) } + +// TestMuSigEarlyNonce tests that for protocols where nonces need to be +// exchagned before all signers are known, the context API works as expected. +func TestMuSigEarlyNonce(t *testing.T) { + t.Parallel() + + privKey1, err := btcec.NewPrivateKey() + if err != nil { + t.Fatalf("unable to gen priv key: %v", err) + } + privKey2, err := btcec.NewPrivateKey() + if err != nil { + t.Fatalf("unable to gen priv key: %v", err) + } + + // If we try to make a context, with just the private key and sorting + // value, we should get an error. + _, err = NewContext(privKey1, true) + if !errors.Is(err, ErrSignersNotSpecified) { + t.Fatalf("unexpected ctx error: %v", err) + } + + numSigners := 2 + + ctx1, err := NewContext( + privKey1, true, WithNumSigners(numSigners), WithEarlyNonceGen(), + ) + if err != nil { + t.Fatalf("unable to make ctx: %v", err) + } + pubKey1 := ctx1.PubKey() + + ctx2, err := NewContext( + privKey2, true, WithNumSigners(numSigners), WithEarlyNonceGen(), + ) + if err != nil { + t.Fatalf("unable to make ctx: %v", err) + } + pubKey2 := ctx2.PubKey() + + // At this point, the combined key shouldn't be available for both + // signers, since we only know of the sole signers. + if _, err := ctx1.CombinedKey(); !errors.Is(err, ErrNotEnoughSigners) { + t.Fatalf("unepxected error: %v", err) + } + if _, err := ctx2.CombinedKey(); !errors.Is(err, ErrNotEnoughSigners) { + t.Fatalf("unepxected error: %v", err) + } + + // The early nonces _should_ be available at this point. + nonce1, err := ctx1.EarlySessionNonce() + if err != nil { + t.Fatalf("session nonce not available: %v", err) + } + nonce2, err := ctx2.EarlySessionNonce() + if err != nil { + t.Fatalf("session nonce not available: %v", err) + } + + // The number of registered signers should still be 1 for both parties. + if ctx1.NumRegisteredSigners() != 1 { + t.Fatalf("expected 1 signer, instead have: %v", + ctx1.NumRegisteredSigners()) + } + if ctx2.NumRegisteredSigners() != 1 { + t.Fatalf("expected 1 signer, instead have: %v", + ctx2.NumRegisteredSigners()) + } + + // If we try to make a session, we should get an error since we dn't + // have all the signers yet. + if _, err := ctx1.NewSession(); !errors.Is(err, ErrNotEnoughSigners) { + t.Fatalf("unexpected session key error: %v", err) + } + + // The combined key should also be unavailable as well. + if _, err := ctx1.CombinedKey(); !errors.Is(err, ErrNotEnoughSigners) { + t.Fatalf("unexpected combined key error: %v", err) + } + + // We'll now register the other signer for both parties. + done, err := ctx1.RegisterSigner(&pubKey2) + if err != nil { + t.Fatalf("unable to register signer: %v", err) + } + if !done { + t.Fatalf("signer 1 doesn't have all keys") + } + done, err = ctx2.RegisterSigner(&pubKey1) + if err != nil { + t.Fatalf("unable to register signer: %v", err) + } + if !done { + t.Fatalf("signer 2 doesn't have all keys") + } + + // If we try to register the signer again, we should get an error. + _, err = ctx2.RegisterSigner(&pubKey1) + if !errors.Is(err, ErrAlreadyHaveAllSigners) { + t.Fatalf("should not be able to register too many signers") + } + + // We should be able to create the session at this point. + session1, err := ctx1.NewSession() + if err != nil { + t.Fatalf("unable to create new session: %v", err) + } + session2, err := ctx2.NewSession() + if err != nil { + t.Fatalf("unable to create new session: %v", err) + } + + msg := sha256.Sum256([]byte("let's get taprooty, LN style")) + + // If we try to sign before we have the combined nonce, we shoudl get + // an error. + _, err = session1.Sign(msg) + if !errors.Is(err, ErrCombinedNonceUnavailable) { + t.Fatalf("unable to gen sig: %v", err) + } + + // Now we can exchange nonces to continue with the rest of the signing + // process as normal. + done, err = session1.RegisterPubNonce(nonce2.PubNonce) + if err != nil { + t.Fatalf("unable to register nonce: %v", err) + } + if !done { + t.Fatalf("signer 1 doesn't have all nonces") + } + done, err = session2.RegisterPubNonce(nonce1.PubNonce) + if err != nil { + t.Fatalf("unable to register nonce: %v", err) + } + if !done { + t.Fatalf("signer 2 doesn't have all nonces") + } + + // Registering the nonce again should error out. + _, err = session2.RegisterPubNonce(nonce1.PubNonce) + if !errors.Is(err, ErrAlredyHaveAllNonces) { + t.Fatalf("shouldn't be able to register nonces twice") + } + + // Sign the message and combine the two partial sigs into one. + _, err = session1.Sign(msg) + if err != nil { + t.Fatalf("unable to gen sig: %v", err) + } + sig2, err := session2.Sign(msg) + if err != nil { + t.Fatalf("unable to gen sig: %v", err) + } + done, err = session1.CombineSig(sig2) + if err != nil { + t.Fatalf("unable to combine sig: %v", err) + } + if !done { + t.Fatalf("all sigs should be known now: %v", err) + } + + // If we try to combine another sig, then we should get an error. + _, err = session1.CombineSig(sig2) + if !errors.Is(err, ErrAlredyHaveAllSigs) { + t.Fatalf("shouldn't be able to combine again") + } + + // Finally, verify that the final signature is valid. + combinedKey, err := ctx1.CombinedKey() + if err != nil { + t.Fatalf("unexpected combined key error: %v", err) + } + finalSig := session1.FinalSig() + if !finalSig.Verify(msg[:], combinedKey) { + t.Fatalf("final sig is invalid!") + } +} diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index c0ece86fa4..5a7fbd4b3d 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -185,7 +185,7 @@ func uint8Writer(w io.Writer, b []byte) error { return binary.Write(w, byteOrder, uint8(len(b))) } -// uint8Writer is an implementation of lengthWriter that writes the length of +// uint32Writer is an implementation of lengthWriter that writes the length of // the byte slice using 4 bytes. func uint32Writer(w io.Writer, b []byte) error { return binary.Write(w, byteOrder, uint32(len(b))) From ba20c75aaffee0e09cbfdd7b204add18485bd1a8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 27 Apr 2022 16:51:53 -0700 Subject: [PATCH 0685/1056] btcec/schnorr/musig2: pass in aux info during nonce generation --- btcec/schnorr/musig2/context.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 298fe96179..19cef34fa9 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -481,7 +481,13 @@ func (c *Context) NewSession(options ...SessionOption) (*Session, error) { // specified nonce, or generate a fresh set. var err error if localNonces == nil { - localNonces, err = GenNonces() + // At this point we need to generate a fresh nonce. We'll pass + // in some auxiliary information to strengthen the nonce + // generated. + localNonces, err = GenNonces( + WithNonceSecretKeyAux(c.signingKey), + WithNonceCombinedKeyAux(c.combinedKey.FinalKey), + ) if err != nil { return nil, err } From 1da361b04e7c4a90c719f56762fa556cce995201 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 Apr 2022 16:06:39 -0700 Subject: [PATCH 0686/1056] btcec/schnorr/musig2: add optional json dump command to gen test vectors --- btcec/schnorr/musig2/musig2_test.go | 118 ++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 7 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index df3f78c93c..c9ae74d7be 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -6,8 +6,11 @@ import ( "bytes" "crypto/sha256" "encoding/hex" + "encoding/json" "errors" + "flag" "fmt" + "io/ioutil" "sync" "testing" @@ -15,12 +18,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2/schnorr" ) -// TestMuSig2SgnTestVectors tests that this implementation of musig2 matches -// the secp256k1-zkp test vectors. -func TestMuSig2SignTestVectors(t *testing.T) { - t.Parallel() -} - var ( key1Bytes, _ = hex.DecodeString("F9308A019258C31049344F85F89D5229B53" + "1C845836F99B08601F113BCE036F9") @@ -37,11 +34,27 @@ var ( keyCombo4, _ = hex.DecodeString("2EB18851887E7BDC5E830E89B19DDBC28078F1FA88AAD0AD01CA06FE4F80210B") ) +const ( + keyAggTestVectorName = "key_agg_vectors.json" + + signTestVectorName = "sign_vectors.json" +) + +var dumpJson = flag.Bool("dumpjson", false, "if true, a JSON version of the "+ + "test vectors will be written to the cwd") + +type jsonKeyAggTestCase struct { + Keys []string `json:"keys"` + ExpectedKey string `json:"expected_key"` +} + // TestMuSig2KeyAggTestVectors tests that this implementation of musig2 key // aggregation lines up with the secp256k1-zkp test vectors. func TestMuSig2KeyAggTestVectors(t *testing.T) { t.Parallel() + var jsonCases []jsonKeyAggTestCase + testCases := []struct { keyOrder []int expectedKey []byte @@ -73,7 +86,10 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { for i, testCase := range testCases { testName := fmt.Sprintf("%v", testCase.keyOrder) t.Run(testName, func(t *testing.T) { - var keys []*btcec.PublicKey + var ( + keys []*btcec.PublicKey + strKeys []string + ) for _, keyIndex := range testCase.keyOrder { keyBytes := testKeys[keyIndex] pub, err := schnorr.ParsePubKey(keyBytes) @@ -82,8 +98,14 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { } keys = append(keys, pub) + strKeys = append(strKeys, hex.EncodeToString(keyBytes)) } + jsonCases = append(jsonCases, jsonKeyAggTestCase{ + Keys: strKeys, + ExpectedKey: hex.EncodeToString(testCase.expectedKey), + }) + uniqueKeyIndex := secondUniqueKeyIndex(keys, false) combinedKey, _, _, _ := AggregateKeys( keys, false, WithUniqueKeyIndex(uniqueKeyIndex), @@ -96,6 +118,22 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { } }) } + + if *dumpJson { + jsonBytes, err := json.Marshal(jsonCases) + if err != nil { + t.Fatalf("unable to encode json: %v", err) + } + + var formattedJson bytes.Buffer + json.Indent(&formattedJson, jsonBytes, "", "\t") + err = ioutil.WriteFile( + keyAggTestVectorName, formattedJson.Bytes(), 0644, + ) + if err != nil { + t.Fatalf("unable to write file: %v", err) + } + } } func mustParseHex(str string) []byte { @@ -160,11 +198,37 @@ func genTweakParity(tweak KeyTweakDesc, isXOnly bool) KeyTweakDesc { return tweak } +type jsonTweak struct { + Tweak string `json:"tweak"` + XOnly bool `json:"x_only"` +} + +type tweakSignCase struct { + Keys []string `json:"keys"` + Tweaks []jsonTweak `json:"tweaks,omitempty"` + + ExpectedSig string `json:"expected_sig"` +} + +type jsonSignTestCase struct { + SecNonce string `json:"secret_nonce"` + AggNonce string `json:"agg_nonce"` + SigningKey string `json:"signing_key"` + Msg string `json:"msg"` + + TestCases []tweakSignCase `json:"test_cases"` +} + // TestMuSig2SigningTestVectors tests that the musig2 implementation produces // the same set of signatures. func TestMuSig2SigningTestVectors(t *testing.T) { t.Parallel() + var jsonCases jsonSignTestCase + + jsonCases.SigningKey = hex.EncodeToString(signSetPrivKey.Serialize()) + jsonCases.Msg = hex.EncodeToString(signTestMsg) + var aggregatedNonce [PubNonceSize]byte copy( aggregatedNonce[:], @@ -175,10 +239,14 @@ func TestMuSig2SigningTestVectors(t *testing.T) { mustParseHex("037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9"), ) + jsonCases.AggNonce = hex.EncodeToString(aggregatedNonce[:]) + var secNonce [SecNonceSize]byte copy(secNonce[:], mustParseHex("508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61")) copy(secNonce[32:], mustParseHex("FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7")) + jsonCases.SecNonce = hex.EncodeToString(secNonce[:]) + tweak1 := KeyTweakDesc{ Tweak: [32]byte{ 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, @@ -277,9 +345,15 @@ func TestMuSig2SigningTestVectors(t *testing.T) { } t.Run(testName, func(t *testing.T) { + var strKeys []string keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) for _, keyIndex := range testCase.keyOrder { keySet = append(keySet, signSetKeys[keyIndex]) + strKeys = append( + strKeys, hex.EncodeToString( + schnorr.SerializePubKey(signSetKeys[keyIndex]), + ), + ) } var opts []SignOption @@ -289,6 +363,14 @@ func TestMuSig2SigningTestVectors(t *testing.T) { ) } + var jsonTweaks []jsonTweak + for _, tweak := range testCase.tweaks { + jsonTweaks = append(jsonTweaks, jsonTweak{ + Tweak: hex.EncodeToString(tweak.Tweak[:]), + XOnly: tweak.IsXOnly, + }) + } + partialSig, err := Sign( secNonce, signSetPrivKey, aggregatedNonce, keySet, msg, opts..., @@ -305,8 +387,30 @@ func TestMuSig2SigningTestVectors(t *testing.T) { testCase.expectedPartialSig, partialSigBytes, ) } + + jsonCases.TestCases = append(jsonCases.TestCases, tweakSignCase{ + Keys: strKeys, + Tweaks: jsonTweaks, + ExpectedSig: hex.EncodeToString(testCase.expectedPartialSig), + }) }) } + + if *dumpJson { + jsonBytes, err := json.Marshal(jsonCases) + if err != nil { + t.Fatalf("unable to encode json: %v", err) + } + + var formattedJson bytes.Buffer + json.Indent(&formattedJson, jsonBytes, "", "\t") + err = ioutil.WriteFile( + signTestVectorName, formattedJson.Bytes(), 0644, + ) + if err != nil { + t.Fatalf("unable to write file: %v", err) + } + } } type signer struct { From a336854e2785a26aa0b162dbe1c6c99944b42856 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 May 2022 16:25:09 +0200 Subject: [PATCH 0687/1056] psbt: fix typo, remove TODO --- btcutil/psbt/partialsig.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/btcutil/psbt/partialsig.go b/btcutil/psbt/partialsig.go index 71cb63cdbf..dfb7004999 100644 --- a/btcutil/psbt/partialsig.go +++ b/btcutil/psbt/partialsig.go @@ -2,7 +2,6 @@ package psbt import ( "bytes" - "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" ) @@ -43,11 +42,8 @@ func validateSignature(sig []byte) bool { return err == nil } -// checkValid checks that both the pbukey and sig are valid. See the methods +// checkValid checks that both the pubkey and sig are valid. See the methods // (PartialSig, validatePubkey, validateSignature) for more details. -// -// TODO(waxwing): update for Schnorr will be needed here if/when that -// activates. func (ps *PartialSig) checkValid() bool { return validatePubkey(ps.PubKey) && validateSignature(ps.Signature) } From a764afd44e25f0eaa6da7578d4e64a806e87d880 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 May 2022 16:25:11 +0200 Subject: [PATCH 0688/1056] psbt: rename receiver to match rest of code --- btcutil/psbt/updater.go | 84 ++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/btcutil/psbt/updater.go b/btcutil/psbt/updater.go index 56a33654b6..66c8d1d83c 100644 --- a/btcutil/psbt/updater.go +++ b/btcutil/psbt/updater.go @@ -14,9 +14,9 @@ import ( "bytes" "crypto/sha256" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // Updater encapsulates the role 'Updater' as specified in BIP174; it accepts @@ -40,14 +40,14 @@ func NewUpdater(p *Packet) (*Updater, error) { // non-witness. This requires provision of a full transaction (which is the // source of the corresponding prevOut), and the input index. If addition of // this key-value pair to the Psbt fails, an error is returned. -func (p *Updater) AddInNonWitnessUtxo(tx *wire.MsgTx, inIndex int) error { - if inIndex > len(p.Upsbt.Inputs)-1 { +func (u *Updater) AddInNonWitnessUtxo(tx *wire.MsgTx, inIndex int) error { + if inIndex > len(u.Upsbt.Inputs)-1 { return ErrInvalidPrevOutNonWitnessTransaction } - p.Upsbt.Inputs[inIndex].NonWitnessUtxo = tx + u.Upsbt.Inputs[inIndex].NonWitnessUtxo = tx - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return ErrInvalidPsbtFormat } @@ -59,14 +59,14 @@ func (p *Updater) AddInNonWitnessUtxo(tx *wire.MsgTx, inIndex int) error { // of the corresponding prevOut); not the full transaction because BIP143 means // the output information is sufficient, and the input index. If addition of // this key-value pair to the Psbt fails, an error is returned. -func (p *Updater) AddInWitnessUtxo(txout *wire.TxOut, inIndex int) error { - if inIndex > len(p.Upsbt.Inputs)-1 { +func (u *Updater) AddInWitnessUtxo(txout *wire.TxOut, inIndex int) error { + if inIndex > len(u.Upsbt.Inputs)-1 { return ErrInvalidPsbtFormat } - p.Upsbt.Inputs[inIndex].WitnessUtxo = txout + u.Upsbt.Inputs[inIndex].WitnessUtxo = txout - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return ErrInvalidPsbtFormat } @@ -81,7 +81,7 @@ func (p *Updater) AddInWitnessUtxo(txout *wire.TxOut, inIndex int) error { // rules are not satisfied, an ErrInvalidSignatureForInput is returned. // // NOTE: This function does *not* validate the ECDSA signature itself. -func (p *Updater) addPartialSignature(inIndex int, sig []byte, +func (u *Updater) addPartialSignature(inIndex int, sig []byte, pubkey []byte) error { partialSig := PartialSig{ @@ -93,7 +93,7 @@ func (p *Updater) addPartialSignature(inIndex int, sig []byte, return ErrInvalidPsbtFormat } - pInput := p.Upsbt.Inputs[inIndex] + pInput := u.Upsbt.Inputs[inIndex] // First check; don't add duplicates. for _, x := range pInput.PartialSigs { @@ -109,12 +109,12 @@ func (p *Updater) addPartialSignature(inIndex int, sig []byte, // Next, we perform a series of additional sanity checks. if pInput.NonWitnessUtxo != nil { - if len(p.Upsbt.UnsignedTx.TxIn) < inIndex+1 { + if len(u.Upsbt.UnsignedTx.TxIn) < inIndex+1 { return ErrInvalidPrevOutNonWitnessTransaction } if pInput.NonWitnessUtxo.TxHash() != - p.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Hash { + u.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Hash { return ErrInvalidSignatureForInput } @@ -123,7 +123,7 @@ func (p *Updater) addPartialSignature(inIndex int, sig []byte, // that with the P2SH scriptPubKey that is generated by // redeemScript. if pInput.RedeemScript != nil { - outIndex := p.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index + outIndex := u.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index scriptPubKey := pInput.NonWitnessUtxo.TxOut[outIndex].PkScript scriptHash := btcutil.Hash160(pInput.RedeemScript) @@ -212,11 +212,11 @@ func (p *Updater) addPartialSignature(inIndex int, sig []byte, } } - p.Upsbt.Inputs[inIndex].PartialSigs = append( - p.Upsbt.Inputs[inIndex].PartialSigs, &partialSig, + u.Upsbt.Inputs[inIndex].PartialSigs = append( + u.Upsbt.Inputs[inIndex].PartialSigs, &partialSig, ) - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return err } @@ -229,12 +229,12 @@ func (p *Updater) addPartialSignature(inIndex int, sig []byte, // sighash type is passed as a 32 bit unsigned integer, along with the index // for the input. An error is returned if addition of this key-value pair to // the Psbt fails. -func (p *Updater) AddInSighashType(sighashType txscript.SigHashType, +func (u *Updater) AddInSighashType(sighashType txscript.SigHashType, inIndex int) error { - p.Upsbt.Inputs[inIndex].SighashType = sighashType + u.Upsbt.Inputs[inIndex].SighashType = sighashType - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return err } return nil @@ -244,12 +244,12 @@ func (p *Updater) AddInSighashType(sighashType txscript.SigHashType, // redeem script is passed serialized, as a byte slice, along with the index of // the input. An error is returned if addition of this key-value pair to the // Psbt fails. -func (p *Updater) AddInRedeemScript(redeemScript []byte, +func (u *Updater) AddInRedeemScript(redeemScript []byte, inIndex int) error { - p.Upsbt.Inputs[inIndex].RedeemScript = redeemScript + u.Upsbt.Inputs[inIndex].RedeemScript = redeemScript - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return ErrInvalidPsbtFormat } @@ -260,12 +260,12 @@ func (p *Updater) AddInRedeemScript(redeemScript []byte, // witness script is passed serialized, as a byte slice, along with the index // of the input. An error is returned if addition of this key-value pair to the // Psbt fails. -func (p *Updater) AddInWitnessScript(witnessScript []byte, +func (u *Updater) AddInWitnessScript(witnessScript []byte, inIndex int) error { - p.Upsbt.Inputs[inIndex].WitnessScript = witnessScript + u.Upsbt.Inputs[inIndex].WitnessScript = witnessScript - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return err } @@ -279,7 +279,7 @@ func (p *Updater) AddInWitnessScript(witnessScript []byte, // // NOTE: This can be called multiple times for the same input. An error is // returned if addition of this key-value pair to the Psbt fails. -func (p *Updater) AddInBip32Derivation(masterKeyFingerprint uint32, +func (u *Updater) AddInBip32Derivation(masterKeyFingerprint uint32, bip32Path []uint32, pubKeyData []byte, inIndex int) error { bip32Derivation := Bip32Derivation{ @@ -293,17 +293,17 @@ func (p *Updater) AddInBip32Derivation(masterKeyFingerprint uint32, } // Don't allow duplicate keys - for _, x := range p.Upsbt.Inputs[inIndex].Bip32Derivation { + for _, x := range u.Upsbt.Inputs[inIndex].Bip32Derivation { if bytes.Equal(x.PubKey, bip32Derivation.PubKey) { return ErrDuplicateKey } } - p.Upsbt.Inputs[inIndex].Bip32Derivation = append( - p.Upsbt.Inputs[inIndex].Bip32Derivation, &bip32Derivation, + u.Upsbt.Inputs[inIndex].Bip32Derivation = append( + u.Upsbt.Inputs[inIndex].Bip32Derivation, &bip32Derivation, ) - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return err } @@ -317,7 +317,7 @@ func (p *Updater) AddInBip32Derivation(masterKeyFingerprint uint32, // // NOTE: That this can be called multiple times for the same output. An error // is returned if addition of this key-value pair to the Psbt fails. -func (p *Updater) AddOutBip32Derivation(masterKeyFingerprint uint32, +func (u *Updater) AddOutBip32Derivation(masterKeyFingerprint uint32, bip32Path []uint32, pubKeyData []byte, outIndex int) error { bip32Derivation := Bip32Derivation{ @@ -331,17 +331,17 @@ func (p *Updater) AddOutBip32Derivation(masterKeyFingerprint uint32, } // Don't allow duplicate keys - for _, x := range p.Upsbt.Outputs[outIndex].Bip32Derivation { + for _, x := range u.Upsbt.Outputs[outIndex].Bip32Derivation { if bytes.Equal(x.PubKey, bip32Derivation.PubKey) { return ErrDuplicateKey } } - p.Upsbt.Outputs[outIndex].Bip32Derivation = append( - p.Upsbt.Outputs[outIndex].Bip32Derivation, &bip32Derivation, + u.Upsbt.Outputs[outIndex].Bip32Derivation = append( + u.Upsbt.Outputs[outIndex].Bip32Derivation, &bip32Derivation, ) - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return err } @@ -350,12 +350,12 @@ func (p *Updater) AddOutBip32Derivation(masterKeyFingerprint uint32, // AddOutRedeemScript takes a redeem script as a byte slice and appends it to // the output at index outIndex. -func (p *Updater) AddOutRedeemScript(redeemScript []byte, +func (u *Updater) AddOutRedeemScript(redeemScript []byte, outIndex int) error { - p.Upsbt.Outputs[outIndex].RedeemScript = redeemScript + u.Upsbt.Outputs[outIndex].RedeemScript = redeemScript - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return ErrInvalidPsbtFormat } @@ -364,12 +364,12 @@ func (p *Updater) AddOutRedeemScript(redeemScript []byte, // AddOutWitnessScript takes a witness script as a byte slice and appends it to // the output at index outIndex. -func (p *Updater) AddOutWitnessScript(witnessScript []byte, +func (u *Updater) AddOutWitnessScript(witnessScript []byte, outIndex int) error { - p.Upsbt.Outputs[outIndex].WitnessScript = witnessScript + u.Upsbt.Outputs[outIndex].WitnessScript = witnessScript - if err := p.Upsbt.SanityCheck(); err != nil { + if err := u.Upsbt.SanityCheck(); err != nil { return err } From e6367b26b72e1642144b87e189aad443ddf07826 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 May 2022 16:25:12 +0200 Subject: [PATCH 0689/1056] psbt: remove invalid type from typo --- btcutil/psbt/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcutil/psbt/types.go b/btcutil/psbt/types.go index 1b4a26a4dc..2a74c9bfd6 100644 --- a/btcutil/psbt/types.go +++ b/btcutil/psbt/types.go @@ -138,7 +138,7 @@ const ( // The value is the witness script of this input, if it has one. WitnessScriptOutputType OutputType = 1 - j // Bip32DerivationOutputType is used to communicate derivation information + // Bip32DerivationOutputType is used to communicate derivation information // needed to spend this output. The key is ({0x02}|{public key}). // // The value is master key fingerprint concatenated with the derivation From db6cb69d845335051cb2c472e397c9bc62c6e681 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 May 2022 16:25:13 +0200 Subject: [PATCH 0690/1056] psbt: add new input/output types and structs --- btcutil/psbt/taproot.go | 206 ++++++++++++++++++++++++++++++++++++++++ btcutil/psbt/types.go | 54 +++++++++++ 2 files changed, 260 insertions(+) create mode 100644 btcutil/psbt/taproot.go diff --git a/btcutil/psbt/taproot.go b/btcutil/psbt/taproot.go new file mode 100644 index 0000000000..4d0619ec43 --- /dev/null +++ b/btcutil/psbt/taproot.go @@ -0,0 +1,206 @@ +package psbt + +import ( + "bytes" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +const ( + // schnorrSigMinLength is the minimum length of a Schnorr signature + // which is 64 bytes. + schnorrSigMinLength = schnorr.SignatureSize + + // schnorrSigMaxLength is the maximum length of a Schnorr signature + // which is 64 bytes plus one byte for the appended sighash flag. + schnorrSigMaxLength = schnorrSigMinLength + 1 +) + +// TaprootScriptSpendSig encapsulates an individual Schnorr signature for a +// given public key and leaf hash. +type TaprootScriptSpendSig struct { + XOnlyPubKey []byte + LeafHash []byte + Signature []byte + SigHash txscript.SigHashType +} + +// checkValid checks that both the pubkey and the signature are valid. +func (s *TaprootScriptSpendSig) checkValid() bool { + return validateXOnlyPubkey(s.XOnlyPubKey) && + validateSchnorrSignature(s.Signature) +} + +// EqualKey returns true if this script spend signature's key data is the same +// as the given script spend signature. +func (s *TaprootScriptSpendSig) EqualKey(other *TaprootScriptSpendSig) bool { + return bytes.Equal(s.XOnlyPubKey, other.XOnlyPubKey) && + bytes.Equal(s.LeafHash, other.LeafHash) +} + +// SortBefore returns true if this script spend signature's key is +// lexicographically smaller than the given other script spend signature's key +// and should come first when being sorted. +func (s *TaprootScriptSpendSig) SortBefore(other *TaprootScriptSpendSig) bool { + return bytes.Compare(s.XOnlyPubKey, other.XOnlyPubKey) < 0 && + bytes.Compare(s.LeafHash, other.LeafHash) < 0 +} + +// TaprootTapLeafScript represents a single taproot leaf script that is +// identified by its control block. +type TaprootTapLeafScript struct { + ControlBlock []byte + Script []byte + LeafVersion txscript.TapscriptLeafVersion +} + +// checkValid checks that the control block is valid. +func (s *TaprootTapLeafScript) checkValid() bool { + return validateControlBlock(s.ControlBlock) +} + +// SortBefore returns true if this leaf script's key is lexicographically +// smaller than the given other leaf script's key and should come first when +// being sorted. +func (s *TaprootTapLeafScript) SortBefore(other *TaprootTapLeafScript) bool { + return bytes.Compare(s.ControlBlock, other.ControlBlock) < 0 +} + +// TaprootBip32Derivation encapsulates the data for the input and output +// taproot specific BIP-32 derivation key-value fields. +type TaprootBip32Derivation struct { + // XOnlyPubKey is the raw public key serialized in the x-only BIP-340 + // format. + XOnlyPubKey []byte + + // LeafHashes is a list of leaf hashes that the given public key is + // involved in. + LeafHashes [][]byte + + // MasterKeyFingerprint is the fingerprint of the master pubkey. + MasterKeyFingerprint uint32 + + // Bip32Path is the BIP 32 path with child index as a distinct integer. + Bip32Path []uint32 +} + +// SortBefore returns true if this derivation info's key is lexicographically +// smaller than the given other derivation info's key and should come first when +// being sorted. +func (s *TaprootBip32Derivation) SortBefore(other *TaprootBip32Derivation) bool { + return bytes.Compare(s.XOnlyPubKey, other.XOnlyPubKey) < 0 +} + +// readTaprootBip32Derivation deserializes a byte slice containing the Taproot +// BIP32 derivation info that consists of a list of leaf hashes as well as the +// normal BIP32 derivation info. +func readTaprootBip32Derivation(xOnlyPubKey, + value []byte) (*TaprootBip32Derivation, error) { + + // The taproot key BIP 32 derivation path is defined as: + // * <4 byte fingerprint> <32-bit uint>* + // So we get at least 5 bytes for the length and the 4 byte fingerprint. + if len(value) < 5 { + return nil, ErrInvalidPsbtFormat + } + + // The first element is the number of hashes that will follow. + reader := bytes.NewReader(value) + numHashes, err := wire.ReadVarInt(reader, 0) + if err != nil { + return nil, ErrInvalidPsbtFormat + } + + // A hash is 32 bytes in size, so we need at least numHashes*32 + 5 + // bytes to be present. + if len(value) < (int(numHashes)*32)+5 { + return nil, ErrInvalidPsbtFormat + } + + derivation := TaprootBip32Derivation{ + XOnlyPubKey: xOnlyPubKey, + LeafHashes: make([][]byte, int(numHashes)), + } + + for i := 0; i < int(numHashes); i++ { + derivation.LeafHashes[i] = make([]byte, 32) + n, err := reader.Read(derivation.LeafHashes[i]) + if err != nil || n != 32 { + return nil, ErrInvalidPsbtFormat + } + } + + // Extract the remaining bytes from the reader (we don't actually know + // how many bytes we read due to the compact size integer at the + // beginning). + var leftoverBuf bytes.Buffer + _, err = reader.WriteTo(&leftoverBuf) + if err != nil { + return nil, err + } + + // Read the BIP32 derivation info. + fingerprint, path, err := readBip32Derivation(leftoverBuf.Bytes()) + if err != nil { + return nil, err + } + + derivation.MasterKeyFingerprint = fingerprint + derivation.Bip32Path = path + + return &derivation, nil +} + +// serializeTaprootBip32Derivation serializes a TaprootBip32Derivation to its +// raw byte representation. +func serializeTaprootBip32Derivation(d *TaprootBip32Derivation) ([]byte, + error) { + + var buf bytes.Buffer + + // The taproot key BIP 32 derivation path is defined as: + // * <4 byte fingerprint> <32-bit uint>* + err := wire.WriteVarInt(&buf, 0, uint64(len(d.LeafHashes))) + if err != nil { + return nil, ErrInvalidPsbtFormat + } + + for _, hash := range d.LeafHashes { + n, err := buf.Write(hash) + if err != nil || n != 32 { + return nil, ErrInvalidPsbtFormat + } + } + + _, err = buf.Write(SerializeBIP32Derivation( + d.MasterKeyFingerprint, d.Bip32Path, + )) + if err != nil { + return nil, ErrInvalidPsbtFormat + } + + return buf.Bytes(), nil +} + +// validateXOnlyPubkey checks if pubKey is *any* valid pubKey serialization in a +// BIP-340 context (x-only serialization). +func validateXOnlyPubkey(pubKey []byte) bool { + _, err := schnorr.ParsePubKey(pubKey) + return err == nil +} + +// validateSchnorrSignature checks that the passed byte slice is a valid Schnorr +// signature, _NOT_ including the sighash flag. It does *not* of course +// validate the signature against any message or public key. +func validateSchnorrSignature(sig []byte) bool { + _, err := schnorr.ParseSignature(sig) + return err == nil +} + +// validateControlBlock checks that the passed byte slice is a valid control +// block as it would appear in a BIP-341 witness stack as the last element. +func validateControlBlock(controlBlock []byte) bool { + _, err := txscript.ParseControlBlock(controlBlock) + return err == nil +} diff --git a/btcutil/psbt/types.go b/btcutil/psbt/types.go index 2a74c9bfd6..e833e1af35 100644 --- a/btcutil/psbt/types.go +++ b/btcutil/psbt/types.go @@ -114,6 +114,43 @@ const ( // scripts necessary for the input to pass validation. FinalScriptWitnessType InputType = 8 + // TaprootKeySpendSignatureType is an empty key ({0x13}). The value is + // a 64-byte Schnorr signature or a 65-byte Schnorr signature with the + // one byte sighash type appended to it. + TaprootKeySpendSignatureType InputType = 0x13 + + // TaprootScriptSpendSignatureType is a type that carries the + // x-only pubkey and leaf hash along with the key + // ({0x14}|{xonlypubkey}|{leafhash}). + // + // The value is a 64-byte Schnorr signature or a 65-byte Schnorr + // signature with the one byte sighash type appended to it. + TaprootScriptSpendSignatureType InputType = 0x14 + + // TaprootLeafScriptType is a type that carries the control block along + // with the key ({0x15}|{control block}). + // + // The value is a script followed by a one byte unsigned integer that + // represents the leaf version. + TaprootLeafScriptType InputType = 0x15 + + // TaprootBip32DerivationInputType is a type that carries the x-only + // pubkey along with the key ({0x16}|{xonlypubkey}). + // + // The value is a compact integer denoting the number of hashes, + // followed by said number of 32-byte leaf hashes. The rest of the value + // is then identical to the Bip32DerivationInputType value. + TaprootBip32DerivationInputType InputType = 0x16 + + // TaprootInternalKeyInputType is an empty key ({0x17}). The value is + // an x-only pubkey denoting the internal public key used for + // constructing a taproot key. + TaprootInternalKeyInputType InputType = 0x17 + + // TaprootMerkleRootType is an empty key ({0x18}). The value is a + // 32-byte hash denoting the root hash of a merkle tree of scripts. + TaprootMerkleRootType InputType = 0x18 + // ProprietaryInputType is a custom type for use by devs. // // The key ({0xFC}||{subtype}|{key data}), is a Variable length @@ -146,4 +183,21 @@ const ( // little endian unsigned integer indexes concatenated with each other. // Public keys are those needed to spend this output. Bip32DerivationOutputType OutputType = 2 + + // TaprootInternalKeyOutputType is an empty key ({0x05}). The value is + // an x-only pubkey denoting the internal public key used for + // constructing a taproot key. + TaprootInternalKeyOutputType OutputType = 5 + + // TaprootTapTreeType is an empty key ({0x06}). The value is a + // serialized taproot tree. + TaprootTapTreeType OutputType = 6 + + // TaprootBip32DerivationOutputType is a type that carries the x-only + // pubkey along with the key ({0x07}|{xonlypubkey}). + // + // The value is a compact integer denoting the number of hashes, + // followed by said number of 32-byte leaf hashes. The rest of the value + // is then identical to the Bip32DerivationInputType value. + TaprootBip32DerivationOutputType OutputType = 7 ) From 5cf346f14f9cf2f90e48e7c416b40b7e43c5b423 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 May 2022 16:25:15 +0200 Subject: [PATCH 0691/1056] psbt: add (de-)serialization for new types --- btcutil/psbt/partial_input.go | 264 +++++++++++++++++++++++++++++++-- btcutil/psbt/partial_output.go | 97 +++++++++++- 2 files changed, 348 insertions(+), 13 deletions(-) diff --git a/btcutil/psbt/partial_input.go b/btcutil/psbt/partial_input.go index 4783c74d31..7686c451cb 100644 --- a/btcutil/psbt/partial_input.go +++ b/btcutil/psbt/partial_input.go @@ -13,16 +13,22 @@ import ( // PInput is a struct encapsulating all the data that can be attached to any // specific input of the PSBT. type PInput struct { - NonWitnessUtxo *wire.MsgTx - WitnessUtxo *wire.TxOut - PartialSigs []*PartialSig - SighashType txscript.SigHashType - RedeemScript []byte - WitnessScript []byte - Bip32Derivation []*Bip32Derivation - FinalScriptSig []byte - FinalScriptWitness []byte - Unknowns []*Unknown + NonWitnessUtxo *wire.MsgTx + WitnessUtxo *wire.TxOut + PartialSigs []*PartialSig + SighashType txscript.SigHashType + RedeemScript []byte + WitnessScript []byte + Bip32Derivation []*Bip32Derivation + FinalScriptSig []byte + FinalScriptWitness []byte + TaprootKeySpendSig []byte + TaprootScriptSpendSig []*TaprootScriptSpendSig + TaprootLeafScript []*TaprootTapLeafScript + TaprootBip32Derivation []*TaprootBip32Derivation + TaprootInternalKey []byte + TaprootMerkleRoot []byte + Unknowns []*Unknown } // NewPsbtInput creates an instance of PsbtInput given either a nonWitnessUtxo @@ -209,6 +215,155 @@ func (pi *PInput) deserialize(r io.Reader) error { pi.FinalScriptWitness = value + case TaprootKeySpendSignatureType: + if pi.TaprootKeySpendSig != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + // The signature can either be 64 or 65 bytes. + switch { + case len(value) == schnorrSigMinLength: + if !validateSchnorrSignature(value) { + return ErrInvalidKeydata + } + + case len(value) == schnorrSigMaxLength: + if !validateSchnorrSignature( + value[0:schnorrSigMinLength], + ) { + return ErrInvalidKeydata + } + + default: + return ErrInvalidKeydata + } + + pi.TaprootKeySpendSig = value + + case TaprootScriptSpendSignatureType: + // The key data for the script spend signature is: + // + if len(keydata) != 32*2 { + return ErrInvalidKeydata + } + + newPartialSig := TaprootScriptSpendSig{ + XOnlyPubKey: keydata[:32], + LeafHash: keydata[32:], + } + + // The signature can either be 64 or 65 bytes. + switch { + case len(value) == schnorrSigMinLength: + newPartialSig.Signature = value + newPartialSig.SigHash = txscript.SigHashDefault + + case len(value) == schnorrSigMaxLength: + newPartialSig.Signature = value[0:schnorrSigMinLength] + newPartialSig.SigHash = txscript.SigHashType( + value[schnorrSigMinLength], + ) + + default: + return ErrInvalidKeydata + } + + if !newPartialSig.checkValid() { + return ErrInvalidKeydata + } + + // Duplicate keys are not allowed. + for _, x := range pi.TaprootScriptSpendSig { + if x.EqualKey(&newPartialSig) { + return ErrDuplicateKey + } + } + + pi.TaprootScriptSpendSig = append( + pi.TaprootScriptSpendSig, &newPartialSig, + ) + + case TaprootLeafScriptType: + if len(value) < 1 { + return ErrInvalidKeydata + } + + newLeafScript := TaprootTapLeafScript{ + ControlBlock: keydata, + Script: value[:len(value)-1], + LeafVersion: txscript.TapscriptLeafVersion( + value[len(value)-1], + ), + } + + if !newLeafScript.checkValid() { + return ErrInvalidKeydata + } + + // Duplicate keys are not allowed. + for _, x := range pi.TaprootLeafScript { + if bytes.Equal( + x.ControlBlock, + newLeafScript.ControlBlock, + ) { + return ErrDuplicateKey + } + } + + pi.TaprootLeafScript = append( + pi.TaprootLeafScript, &newLeafScript, + ) + + case TaprootBip32DerivationInputType: + if !validateXOnlyPubkey(keydata) { + return ErrInvalidKeydata + } + + taprootDerivation, err := readTaprootBip32Derivation( + keydata, value, + ) + if err != nil { + return err + } + + // Duplicate keys are not allowed. + for _, x := range pi.TaprootBip32Derivation { + if bytes.Equal(x.XOnlyPubKey, keydata) { + return ErrDuplicateKey + } + } + + pi.TaprootBip32Derivation = append( + pi.TaprootBip32Derivation, taprootDerivation, + ) + + case TaprootInternalKeyInputType: + if pi.TaprootInternalKey != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + if !validateXOnlyPubkey(value) { + return ErrInvalidKeydata + } + + pi.TaprootInternalKey = value + + case TaprootMerkleRootType: + if pi.TaprootMerkleRoot != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + pi.TaprootMerkleRoot = value + default: // A fall through case for any proprietary types. keyintanddata := []byte{byte(keyint)} @@ -328,6 +483,95 @@ func (pi *PInput) serialize(w io.Writer) error { return err } } + + if pi.TaprootKeySpendSig != nil { + err := serializeKVPairWithType( + w, uint8(TaprootKeySpendSignatureType), nil, + pi.TaprootKeySpendSig, + ) + if err != nil { + return err + } + } + + sort.Slice(pi.TaprootScriptSpendSig, func(i, j int) bool { + return pi.TaprootScriptSpendSig[i].SortBefore( + pi.TaprootScriptSpendSig[j], + ) + }) + for _, scriptSpend := range pi.TaprootScriptSpendSig { + keyData := append([]byte{}, scriptSpend.XOnlyPubKey...) + keyData = append(keyData, scriptSpend.LeafHash...) + value := append([]byte{}, scriptSpend.Signature...) + if scriptSpend.SigHash != txscript.SigHashDefault { + value = append(value, byte(scriptSpend.SigHash)) + } + err := serializeKVPairWithType( + w, uint8(TaprootScriptSpendSignatureType), + keyData, value, + ) + if err != nil { + return err + } + } + + sort.Slice(pi.TaprootLeafScript, func(i, j int) bool { + return pi.TaprootLeafScript[i].SortBefore( + pi.TaprootLeafScript[j], + ) + }) + for _, leafScript := range pi.TaprootLeafScript { + value := append([]byte{}, leafScript.Script...) + value = append(value, byte(leafScript.LeafVersion)) + err := serializeKVPairWithType( + w, uint8(TaprootLeafScriptType), + leafScript.ControlBlock, value, + ) + if err != nil { + return err + } + } + + sort.Slice(pi.TaprootBip32Derivation, func(i, j int) bool { + return pi.TaprootBip32Derivation[i].SortBefore( + pi.TaprootBip32Derivation[j], + ) + }) + for _, derivation := range pi.TaprootBip32Derivation { + value, err := serializeTaprootBip32Derivation( + derivation, + ) + if err != nil { + return err + } + err = serializeKVPairWithType( + w, uint8(TaprootBip32DerivationInputType), + derivation.XOnlyPubKey, value, + ) + if err != nil { + return err + } + } + + if pi.TaprootInternalKey != nil { + err := serializeKVPairWithType( + w, uint8(TaprootInternalKeyInputType), nil, + pi.TaprootInternalKey, + ) + if err != nil { + return err + } + } + + if pi.TaprootMerkleRoot != nil { + err := serializeKVPairWithType( + w, uint8(TaprootMerkleRootType), nil, + pi.TaprootMerkleRoot, + ) + if err != nil { + return err + } + } } if pi.FinalScriptSig != nil { diff --git a/btcutil/psbt/partial_output.go b/btcutil/psbt/partial_output.go index 64d1bd4cae..33b5ff9981 100644 --- a/btcutil/psbt/partial_output.go +++ b/btcutil/psbt/partial_output.go @@ -11,9 +11,12 @@ import ( // POutput is a struct encapsulating all the data that can be attached // to any specific output of the PSBT. type POutput struct { - RedeemScript []byte - WitnessScript []byte - Bip32Derivation []*Bip32Derivation + RedeemScript []byte + WitnessScript []byte + Bip32Derivation []*Bip32Derivation + TaprootInternalKey []byte + TaprootTapTree []byte + TaprootBip32Derivation []*TaprootBip32Derivation } // NewPsbtOutput creates an instance of PsbtOutput; the three parameters @@ -91,6 +94,53 @@ func (po *POutput) deserialize(r io.Reader) error { }, ) + case TaprootInternalKeyOutputType: + if po.TaprootInternalKey != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + if !validateXOnlyPubkey(value) { + return ErrInvalidKeydata + } + + po.TaprootInternalKey = value + + case TaprootTapTreeType: + if po.TaprootTapTree != nil { + return ErrDuplicateKey + } + if keydata != nil { + return ErrInvalidKeydata + } + + po.TaprootTapTree = value + + case TaprootBip32DerivationOutputType: + if !validateXOnlyPubkey(keydata) { + return ErrInvalidKeydata + } + + taprootDerivation, err := readTaprootBip32Derivation( + keydata, value, + ) + if err != nil { + return err + } + + // Duplicate keys are not allowed. + for _, x := range po.TaprootBip32Derivation { + if bytes.Equal(x.XOnlyPubKey, keydata) { + return ErrDuplicateKey + } + } + + po.TaprootBip32Derivation = append( + po.TaprootBip32Derivation, taprootDerivation, + ) + default: // Unknown type is allowed for inputs but not outputs. return ErrInvalidPsbtFormat @@ -135,5 +185,46 @@ func (po *POutput) serialize(w io.Writer) error { } } + if po.TaprootInternalKey != nil { + err := serializeKVPairWithType( + w, uint8(TaprootInternalKeyOutputType), nil, + po.TaprootInternalKey, + ) + if err != nil { + return err + } + } + + if po.TaprootTapTree != nil { + err := serializeKVPairWithType( + w, uint8(TaprootTapTreeType), nil, + po.TaprootTapTree, + ) + if err != nil { + return err + } + } + + sort.Slice(po.TaprootBip32Derivation, func(i, j int) bool { + return po.TaprootBip32Derivation[i].SortBefore( + po.TaprootBip32Derivation[j], + ) + }) + for _, derivation := range po.TaprootBip32Derivation { + value, err := serializeTaprootBip32Derivation( + derivation, + ) + if err != nil { + return err + } + err = serializeKVPairWithType( + w, uint8(TaprootBip32DerivationOutputType), + derivation.XOnlyPubKey, value, + ) + if err != nil { + return err + } + } + return nil } From 0572702ceccd9daad224735741c2a520550ea8ce Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 May 2022 16:25:16 +0200 Subject: [PATCH 0692/1056] psbt: add valid and invalid PSBTs for new types --- btcutil/psbt/go.mod | 4 ++ btcutil/psbt/go.sum | 2 + btcutil/psbt/psbt_test.go | 102 +++++++++++++++++++++++++++++--------- 3 files changed, 84 insertions(+), 24 deletions(-) diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index c2e36ff4fa..2c6dbbb7f8 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -8,13 +8,17 @@ require ( github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 + github.com/stretchr/testify v1.7.0 ) require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) replace github.com/btcsuite/btcd/btcutil => ../ diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index ccdbe0ae4f..a901223de4 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -62,6 +62,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -75,6 +76,7 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go index 8d66325ad2..1ce4780d84 100644 --- a/btcutil/psbt/psbt_test.go +++ b/btcutil/psbt/psbt_test.go @@ -9,6 +9,7 @@ import ( "encoding/base64" "encoding/binary" "encoding/hex" + "strings" "testing" "github.com/btcsuite/btcd/btcutil" @@ -16,6 +17,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/davecgh/go-spew/spew" + "github.com/stretchr/testify/require" ) // Test vectors from: @@ -55,7 +57,7 @@ func createPsbtFromSignedTx(serializedSignedTx []byte) ( return unsignedPsbt, scriptSigs, witnesses, nil } -// These are all valid PSBTs +// These are all valid PSBTs encoded as hex. var validPsbtHex = map[int]string{ 0: "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000", 1: "70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000", @@ -67,8 +69,18 @@ var validPsbtHex = map[int]string{ 7: "70736274ff01002001000000000100000000000000000d6a0b68656c6c6f20776f726c64000000000000", } -// These are all invalid PSBTs for the indicated -// reasons. +// These are additional valid PSBTs encoded as base64. +var validPsbtBase64 = map[int]string{ + 0: "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAIQ12pWrO2RXSUT3NhMLDeLLoqlzWMrW3HKLyrFsOOmSb2wIBAiENnBLP3ATHRYTXh6w9I3chMsGFJLx6so3sQhm4/FtCX3ABAQAAAA==", + 1: "cHNidP8BAFICAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAFgAUdo4e60z0IIZgM/gKzv8PlyB0SWkAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgAiAgNrdyptt02HU8mKgnlY3mx4qzMSEJ830+AwRIQkLs5z2Bh3Ky2nVAAAgAEAAIAAAACAAAAAAAAAAAAA", + 2: "cHNidP8BAFICAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAFgAUdo4e60z0IIZgM/gKzv8PlyB0SWkAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1cBE0C7U+yRe62dkGrxuocYHEi4as5aritTYFpyXKdGJWMUdvxvW67a9PLuD0d/NvWPOXDVuCc7fkl7l68uPxJcl680IRb+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMhkAdystp1YAAIABAACAAAAAgAEAAAAAAAAAARcg/jSQZMmNbiqFP6PJsSvYswShnBlcYO+n7iOTBG0/ojIAIgIDa3cqbbdNh1PJioJ5WN5seKszEhCfN9PgMESEJC7Oc9gYdystp1QAAIABAACAAAAAgAAAAAAAAAAAAA==", + 3: "cHNidP8BAF4CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgABBSARJNp67JLM0GyVRWJkf0N7E4uVchqEvivyJ2u92rPmcSEHESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEZAHcrLadWAACAAQAAgAAAAIAAAAAABQAAAAA=", + 4: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJiFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgjICyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSrMBCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wJfG5v6l/3FP9XJEmZkIEOQG6YqhD1v35fZ4S8HQqabOIyBDILC/FvARtT6nvmFZJKp/J+XSmtIOoRVdhIZ2w7rRsqzAYhXBUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsDNlw4V9T/AyC+VD9Vg/6kZt2FyvgFzaKiZE68HT0ALCRFfLkkK98xFxPeFEfNgV85cWlxWMlop+0TfwgPzVuH4IyD6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqazAIRYssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20jkBzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwl3Ky2nVgAAgAEAAIACAACAAAAAAAAAAAAhFkMgsL8W8BG1Pqe+YVkkqn8n5dKa0g6hFV2EhnbDutGyOQERXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+HcrLadWAACAAQAAgAEAAIAAAAAAAAAAACEWUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAFAHxGHl0hFvoPejzvOx0MCmzn0m4XraCy5cktGe+tSLQYWcuKRRypOQFvfWIFnpSXoaSiZ1admHbaYBAa/zjjUpubk5zn+RrpcHcrLadWAACAAQAAgAMAAIAAAAAAAAAAAAEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARgg8DYuL3Wm9CClvePrIh2WrmcgzyX4GJDJWx13WstRXmUAAQUgESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEhBxEk2nrskszQbJVFYmR/Q3sTi5VyGoS+K/Ina73as+ZxGQB3Ky2nVgAAgAEAAIAAAACAAAAAAAUAAAAA", + 5: "cHNidP8BAF4CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAIlEgCoy9yG3hzhwPnK6yLW33ztNoP+Qj4F0eQCqHk0HW9vUAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgABBSBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wAEGbwLAIiBzblcpAP4SUliaIUPI88efcaBBLSNTr3VelwHHgmlKAqwCwCIgYxxfO1gyuPvev7GXBM7rMjwh9A96JPQ9aO8MwmsSWWmsAcAiIET6pJoDON5IjI3//s37bzKfOAvVZu8gyN9tgT6rHEJzrCEHRPqkmgM43kiMjf/+zftvMp84C9Vm7yDI322BPqscQnM5AfBreYuSoQ7ZqdC7/Trxc6U7FhfaOkFZygCCFs2Fay4Odystp1YAAIABAACAAQAAgAAAAAADAAAAIQdQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wAUAfEYeXSEHYxxfO1gyuPvev7GXBM7rMjwh9A96JPQ9aO8MwmsSWWk5ARis5AmIl4Xg6nDO67jhyokqenjq7eDy4pbPQ1lhqPTKdystp1YAAIABAACAAgAAgAAAAAADAAAAIQdzblcpAP4SUliaIUPI88efcaBBLSNTr3VelwHHgmlKAjkBKaW0kVCQFi11mv0/4Pk/ozJgVtC0CIy5M8rngmy42Cx3Ky2nVgAAgAEAAIADAACAAAAAAAMAAAAA", + 6: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJBFCyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwlAv4GNl1fW/+tTi6BX+0wfxOD17xhudlvrVkeR4Cr1/T1eJVHU404z2G8na4LJnHmu0/A5Wgge/NLMLGXdfmk9eUEUQyCwvxbwEbU+p75hWSSqfyfl0prSDqEVXYSGdsO60bIRXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+EDh8atvq/omsjbyGDNxncHUKKt2jYD5H5mI2KvvR7+4Y7sfKlKfdowV8AzjTsKDzcB+iPhCi+KPbvZAQ8MpEYEaQRT6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqW99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwQOwfA3kgZGHIM0IoVCMyZwirAx8NpKJT7kWq+luMkgNNi2BUkPjNE+APmJmJuX4hX6o28S3uNpPS2szzeBwXV/ZiFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgjICyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSrMBCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wJfG5v6l/3FP9XJEmZkIEOQG6YqhD1v35fZ4S8HQqabOIyBDILC/FvARtT6nvmFZJKp/J+XSmtIOoRVdhIZ2w7rRsqzAYhXBUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsDNlw4V9T/AyC+VD9Vg/6kZt2FyvgFzaKiZE68HT0ALCRFfLkkK98xFxPeFEfNgV85cWlxWMlop+0TfwgPzVuH4IyD6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqazAIRYssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20jkBzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwl3Ky2nVgAAgAEAAIACAACAAAAAAAAAAAAhFkMgsL8W8BG1Pqe+YVkkqn8n5dKa0g6hFV2EhnbDutGyOQERXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+HcrLadWAACAAQAAgAEAAIAAAAAAAAAAACEWUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAFAHxGHl0hFvoPejzvOx0MCmzn0m4XraCy5cktGe+tSLQYWcuKRRypOQFvfWIFnpSXoaSiZ1admHbaYBAa/zjjUpubk5zn+RrpcHcrLadWAACAAQAAgAMAAIAAAAAAAAAAAAEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARgg8DYuL3Wm9CClvePrIh2WrmcgzyX4GJDJWx13WstRXmUAAQUgESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEhBxEk2nrskszQbJVFYmR/Q3sTi5VyGoS+K/Ina73as+ZxGQB3Ky2nVgAAgAEAAIAAAACAAAAAAAUAAAAA", +} + +// These are all invalid PSBTs for the indicated reasons. var invalidPsbtHex = map[int]string{ // wire format, not PSBT format 0: "0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300", @@ -113,51 +125,93 @@ var invalidPsbtHex = map[int]string{ 19: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba670000008000000080050000800000", } +// All following PSBTs are Taproot specific invalid packets taken from +// https://github.com/bitcoin/bitcoin/pull/22558. +var invalidPsbtBase64 = map[int]string{ + // Invalid input internal key length. + 0: "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXARchAv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyAAAA", + // Invalid input key spend schnorr signature. + 1: "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXARM/Fzuz02wHSvtxb+xjB6BpouRQuZXzyCeFlFq43w4kJg3NcDsMvzTeOZGEqUgawrNYbbZgHwJqd/fkk4SBvDR1AAAA", + // Invalid input key spend signature length. + 2: "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXARNCFzuz02wHSvtxb+xjB6BpouRQuZXzyCeFlFq43w4kJg3NcDsMvzTeOZGEqUgawrNYbbZgHwJqd/fkk4SBvDR1FwGqAAAA", + // Invalid input x-only pubkey in key. + 3: "cHNidP8BAHECAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Anh8AQAAAAAAFgAUg6fjS9mf8DpJYu+KGhAbspVGHs5gawQqAQAAABYAFHrDad8bIOAz1hFmI5V7CsSfPFLoAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXIhYC/jSQZMmNbiqFP6PJsSvYswShnBlcYO+n7iOTBG0/ojIZAHcrLadWAACAAQAAgAAAAIABAAAAAAAAAAAAAA==", + // Invalid output internal key length. + 4: "cHNidP8BAH0CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Aoh7AQAAAAAAFgAUI4KHHH6EIaAAk/dU2RKB5nWHS59gawQqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAABBSEC/jSQZMmNbiqFP6PJsSvYswShnBlcYO+n7iOTBG0/ojIA", + // Invalid output BIP32 derivation x-only pubkey in key. + 5: "cHNidP8BAH0CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////Aoh7AQAAAAAAFgAUI4KHHH6EIaAAk/dU2RKB5nWHS59gawQqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAAAAAABASsA8gUqAQAAACJRIFosLPW1LPMfg60ujaY/8DGD7Nj2CcdRCuikjgORCgdXAAAiBwL+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMhkAdystp1YAAIABAACAAAAAgAEAAAAAAAAAAA==", + // Invalid input script spend signature key length. + 6: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJCFAIssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20s2XDhX1P8DIL5UP1WD/qRm3YXK+AXNoqJkTrwdPQAsJQIl1aqNznMxonsD886NgvjLMC1mxbpOh6LtGBXJrLKej/3BsQXZkljKyzGjh+RK4pXjjcZzncQiFx6lm9JvNQ8sAAA==", + // Invalid input script spend signature length. + 7: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJBFCyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwlCiXVqo3OczGiewPzzo2C+MswLWbFuk6Hou0YFcmssp6P/cGxBdmSWMrLMaOH5ErileONxnOdxCIXHqWb0m81DywEBAAA=", + // Invalid encoding of base64 stream. + 8: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJBFCyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwk5iXVqo3OczGiewPzzo2C+MswLWbFuk6Hou0YFcmssp6P/cGxBdmSWMrLMaOH5ErileONxnOdxCIXHqWb0m81DywAA", + // Invalid input leaf script type control block. + 9: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJjFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgAIyAssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20qzAAAA=", + // Invalid input leaf script type control block. + 10: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgAw2k/OT32yjCyylRYx4ANxOFZZf+ljiCy1AOaBEsymMAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJhFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4SMgLLE6xoJI3oBqpqNlnPPAPraCHQnIEUpOho/r3oZbttKswAAA", +} + // This tests that valid PSBT serializations can be parsed // into Psbt structs. func TestReadValidPsbtAndReserialize(t *testing.T) { for key, v := range validPsbtHex { - PsbtBytes, err := hex.DecodeString(v) - if err != nil { - t.Fatalf("Unable to decode hex: %v", err) - } + psbtBytes, err := hex.DecodeString(v) + require.NoErrorf(t, err, "%d: hex decode", key) testPsbt, err := NewFromRawBytes( - bytes.NewReader(PsbtBytes), false, + bytes.NewReader(psbtBytes), false, ) + require.NoErrorf(t, err, "%d: parse", key) + + t.Logf("Successfully parsed test %d, got transaction: %v", + key, spew.Sdump(testPsbt.UnsignedTx)) + + var b bytes.Buffer + err = testPsbt.Serialize(&b) + require.NoErrorf(t, err, "%d: serialize", key) if err != nil { - t.Fatalf("unable to parse psbt: %v", err) + t.Fatalf("Unable to serialize created Psbt: %v", err) } + require.Equal(t, psbtBytes, b.Bytes(), "%d: serialized", key) + } + + for key, v := range validPsbtBase64 { + testPsbt, err := NewFromRawBytes( + strings.NewReader(v), true, + ) + require.NoErrorf(t, err, "%d: parse", key) + t.Logf("Successfully parsed test %d, got transaction: %v", key, spew.Sdump(testPsbt.UnsignedTx)) var b bytes.Buffer err = testPsbt.Serialize(&b) + require.NoErrorf(t, err, "%d: serialize", key) if err != nil { t.Fatalf("Unable to serialize created Psbt: %v", err) } - raw := b.Bytes() - if !bytes.Equal(raw, PsbtBytes) { - t.Fatalf("Serialized PSBT didn't match: %v", - hex.EncodeToString(raw)) - } + base64Packet := base64.StdEncoding.EncodeToString(b.Bytes()) + require.Equal(t, v, base64Packet, "%d: serialized", key) } } func TestReadInvalidPsbt(t *testing.T) { - for _, v := range invalidPsbtHex { - PsbtBytes, err := hex.DecodeString(v) - if err != nil { - t.Fatalf("Unable to decode hex: %v", err) - } + for key, v := range invalidPsbtHex { + psbtBytes, err := hex.DecodeString(v) + require.NoErrorf(t, err, "%d: hex decode", key) - _, err = NewFromRawBytes(bytes.NewReader(PsbtBytes), false) - if err == nil { - t.Fatalf("Incorrectly validated psbt: %v", - hex.EncodeToString(PsbtBytes)) - } + _, err = NewFromRawBytes(bytes.NewReader(psbtBytes), false) + require.Errorf(t, err, "%d: new from raw bytes", key) + + t.Logf("Correctly got error: %v", err) + } + + for key, v := range invalidPsbtBase64 { + _, err := NewFromRawBytes(strings.NewReader(v), true) + require.Errorf(t, err, "%d: new from raw bytes", key) t.Logf("Correctly got error: %v", err) } From 886a8f41db1e18dbe16082e15837d2c214e494ea Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 May 2022 16:25:17 +0200 Subject: [PATCH 0693/1056] psbt: make Taproot PSBT finalizable --- btcutil/psbt/finalizer.go | 136 +++++++++++++++++++++++++++++++++++--- btcutil/psbt/utils.go | 27 +++++++- 2 files changed, 153 insertions(+), 10 deletions(-) diff --git a/btcutil/psbt/finalizer.go b/btcutil/psbt/finalizer.go index 0bf9dbb56e..8c50a94b48 100644 --- a/btcutil/psbt/finalizer.go +++ b/btcutil/psbt/finalizer.go @@ -12,7 +12,10 @@ package psbt // multisig and no other custom script. import ( + "bytes" + "fmt" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" ) // isFinalized considers this input finalized if it contains at least one of @@ -32,16 +35,36 @@ func isFinalizableWitnessInput(pInput *PInput) bool { // If this is a native witness output, then we require both // the witness script, but not a redeem script. case txscript.IsWitnessProgram(pkScript): - if txscript.IsPayToWitnessScriptHash(pkScript) { + switch { + case txscript.IsPayToWitnessScriptHash(pkScript): if pInput.WitnessScript == nil || pInput.RedeemScript != nil { + return false } - } else { + + case txscript.IsPayToTaproot(pkScript): + if pInput.TaprootKeySpendSig == nil && + pInput.TaprootScriptSpendSig == nil { + + return false + } + + // For each of the script spend signatures we need a + // corresponding tap script leaf with the control block. + for _, sig := range pInput.TaprootScriptSpendSig { + _, err := FindLeafScript(pInput, sig.LeafHash) + if err != nil { + return false + } + } + + default: // A P2WKH output on the other hand doesn't need // neither a witnessScript or redeemScript. if pInput.WitnessScript != nil || pInput.RedeemScript != nil { + return false } } @@ -67,8 +90,8 @@ func isFinalizableWitnessInput(pInput *PInput) bool { return false } - // If this isn't a nested nested P2SH output or a native witness - // output, then we can't finalize this input as we don't understand it. + // If this isn't a nested P2SH output or a native witness output, then + // we can't finalize this input as we don't understand it. default: return false } @@ -106,8 +129,10 @@ func isFinalizableLegacyInput(p *Packet, pInput *PInput, inIndex int) bool { func isFinalizable(p *Packet, inIndex int) bool { pInput := p.Inputs[inIndex] - // The input cannot be finalized without any signatures - if pInput.PartialSigs == nil { + // The input cannot be finalized without any signatures. + if pInput.PartialSigs == nil && pInput.TaprootKeySpendSig == nil && + pInput.TaprootScriptSpendSig == nil { + return false } @@ -159,7 +184,6 @@ func MaybeFinalize(p *Packet, inIndex int) (bool, error) { // MaybeFinalizeAll attempts to finalize all inputs of the psbt.Packet that are // not already finalized, and returns an error if it fails to do so. func MaybeFinalizeAll(p *Packet) error { - for i := range p.UnsignedTx.TxIn { success, err := MaybeFinalize(p, i) if err != nil || !success { @@ -184,8 +208,18 @@ func Finalize(p *Packet, inIndex int) error { // witness or legacy UTXO. switch { case pInput.WitnessUtxo != nil: - if err := finalizeWitnessInput(p, inIndex); err != nil { - return err + pkScript := pInput.WitnessUtxo.PkScript + + switch { + case txscript.IsPayToTaproot(pkScript): + if err := finalizeTaprootInput(p, inIndex); err != nil { + return err + } + + default: + if err := finalizeWitnessInput(p, inIndex); err != nil { + return err + } } case pInput.NonWitnessUtxo != nil: @@ -460,3 +494,87 @@ func finalizeWitnessInput(p *Packet, inIndex int) error { p.Inputs[inIndex] = *newInput return nil } + +// finalizeTaprootInput attempts to create PsbtInFinalScriptWitness field for +// input at index inIndex, and removes all other fields except for the utxo +// field, for an input of type p2tr, or returns an error. +func finalizeTaprootInput(p *Packet, inIndex int) error { + // If this input has already been finalized, then we'll return an error + // as we can't proceed. + if checkFinalScriptSigWitness(p, inIndex) { + return ErrInputAlreadyFinalized + } + + // Any p2tr input will only have a witness script, no sig script. + var ( + serializedWitness []byte + err error + pInput = &p.Inputs[inIndex] + ) + + // What spend path did we take? + switch { + // Key spend path. + case len(pInput.TaprootKeySpendSig) > 0: + serializedWitness, err = writeWitness(pInput.TaprootKeySpendSig) + + // Script spend path. + case len(pInput.TaprootScriptSpendSig) > 0: + var witnessStack wire.TxWitness + + // If there are multiple script spend signatures, we assume they + // are from multiple signing participants for the same leaf + // script that uses OP_CHECKSIGADD for multi-sig. Signing + // multiple possible execution paths at the same time is + // currently not supported by this library. + targetLeafHash := pInput.TaprootScriptSpendSig[0].LeafHash + leafScript, err := FindLeafScript(pInput, targetLeafHash) + if err != nil { + return fmt.Errorf("control block for script spend " + + "signature not found") + } + + // The witness stack will contain all signatures, followed by + // the script itself and then the control block. + for idx, scriptSpendSig := range pInput.TaprootScriptSpendSig { + // Make sure that if there are indeed multiple + // signatures, they all reference the same leaf hash. + if !bytes.Equal(scriptSpendSig.LeafHash, targetLeafHash) { + return fmt.Errorf("script spend signature %d "+ + "references different target leaf "+ + "hash than first signature; only one "+ + "script path is supported", idx) + } + + sig := append([]byte{}, scriptSpendSig.Signature...) + if scriptSpendSig.SigHash != txscript.SigHashDefault { + sig = append(sig, byte(scriptSpendSig.SigHash)) + } + witnessStack = append(witnessStack, sig) + } + + // Complete the witness stack with the executed script and the + // serialized control block. + witnessStack = append(witnessStack, leafScript.Script) + witnessStack = append(witnessStack, leafScript.ControlBlock) + + serializedWitness, err = writeWitness(witnessStack...) + + default: + return ErrInvalidPsbtFormat + } + if err != nil { + return err + } + + // At this point, a witness has been constructed. Remove all fields + // other than witness utxo (01) and finalscriptsig (07), + // finalscriptwitness (08). + newInput := NewPsbtInput(nil, pInput.WitnessUtxo) + newInput.FinalScriptWitness = serializedWitness + + // Finally, we overwrite the entry in the input list at the correct + // index. + p.Inputs[inIndex] = *newInput + return nil +} diff --git a/btcutil/psbt/utils.go b/btcutil/psbt/utils.go index 494d04070f..94a5546a55 100644 --- a/btcutil/psbt/utils.go +++ b/btcutil/psbt/utils.go @@ -35,9 +35,14 @@ func WriteTxWitness(w io.Writer, wit [][]byte) error { // writePKHWitness writes a witness for a p2wkh spending input func writePKHWitness(sig []byte, pub []byte) ([]byte, error) { + return writeWitness(sig, pub) +} + +// writeWitness serializes a witness stack from the given items. +func writeWitness(stackElements ...[]byte) ([]byte, error) { var ( buf bytes.Buffer - witnessItems = [][]byte{sig, pub} + witnessItems = append([][]byte{}, stackElements...) ) if err := WriteTxWitness(&buf, witnessItems); err != nil { @@ -420,3 +425,23 @@ func NewFromSignedTx(tx *wire.MsgTx) (*Packet, [][]byte, } return unsignedPsbt, scriptSigs, witnesses, nil } + +// FindLeafScript attempts to locate the leaf script of a given target Tap Leaf +// hash in the list of leaf scripts of the given input. +func FindLeafScript(pInput *PInput, + targetLeafHash []byte) (*TaprootTapLeafScript, error) { + + for _, leaf := range pInput.TaprootLeafScript { + leafHash := txscript.TapLeaf{ + LeafVersion: leaf.LeafVersion, + Script: leaf.Script, + }.TapHash() + + if bytes.Equal(targetLeafHash, leafHash[:]) { + return leaf, nil + } + } + + return nil, fmt.Errorf("leaf script for target leaf hash %x not "+ + "found in input", targetLeafHash) +} From 4550049281fcfb09cd0bfd04aef14806ec4194bb Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Thu, 5 May 2022 19:43:14 -0700 Subject: [PATCH 0694/1056] fuzz: add ParsePubKey fuzzer Courtesy of the Cosmos Network security team, this change adds a fuzzer to ParsePubKey, given that Tendermint uses this code. --- btcec/fuzz_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 btcec/fuzz_test.go diff --git a/btcec/fuzz_test.go b/btcec/fuzz_test.go new file mode 100644 index 0000000000..ebbbb4261e --- /dev/null +++ b/btcec/fuzz_test.go @@ -0,0 +1,46 @@ +//go:build gofuzz || go1.18 + +// Copyright (c) 2013-2017 The btcsuite developers +// Copyright (c) 2015-2022 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package btcec + +import ( + "encoding/hex" + "testing" +) + +func FuzzParsePubKey(f *testing.F) { + // 1. Seeds from pubkey tests. + for _, test := range pubKeyTests { + if test.isValid { + f.Add(test.key) + } + } + + // 2. Seeds from recovery tests. + var recoveryTestPubKeys = []string{ + "04E32DF42865E97135ACFB65F3BAE71BDC86F4D49150AD6A440B6F15878109880A0A2B2667F7E725CEEA70C673093BF67663E0312623C8E091B13CF2C0F11EF652", + "04A7640409AA2083FDAD38B2D8DE1263B2251799591D840653FB02DBBA503D7745FCB83D80E08A1E02896BE691EA6AFFB8A35939A646F1FC79052A744B1C82EDC3", + } + for _, pubKey := range recoveryTestPubKeys { + seed, err := hex.DecodeString(pubKey) + if err != nil { + f.Fatal(err) + } + f.Add(seed) + } + + // Now run the fuzzer. + f.Fuzz(func(t *testing.T, input []byte) { + key, err := ParsePubKey(input) + if key == nil && err == nil { + panic("key==nil && err==nil") + } + if key != nil && err != nil { + panic("key!=nil yet err!=nil") + } + }) +} From ebed1927bfb1e03bf92a83d5c1d10a6dad775885 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Mon, 9 May 2022 18:50:12 +0200 Subject: [PATCH 0695/1056] rpcclient: fix formatting --- rpcclient/infrastructure.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 63874c1b4e..22430a2e1c 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -768,11 +768,14 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { } url := protocol + "://" + c.config.Host - var err error - var backoff time.Duration - var httpResponse *http.Response + var ( + err error + backoff time.Duration + httpResponse *http.Response + ) + tries := 10 - for i := 0; tries == 0 || i < tries; i++ { + for i := 0; i < tries; i++ { bodyReader := bytes.NewReader(jReq.marshalledJSON) httpReq, err := http.NewRequest("POST", url, bodyReader) if err != nil { @@ -799,7 +802,9 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { if backoff > time.Minute { backoff = time.Minute } - log.Debugf("Failed command [%s] with id %d attempt %d. Retrying in %v... \n", jReq.method, jReq.id, i, backoff) + log.Debugf("Failed command [%s] with id %d attempt %d."+ + " Retrying in %v... \n", jReq.method, jReq.id, + i, backoff) time.Sleep(backoff) continue } From 966511246dd03b9bf88fd6607e2449ea0cfd522a Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Mon, 9 May 2022 18:51:22 +0200 Subject: [PATCH 0696/1056] rpclient: fix masked error causing crash after max retries This commit fixes the error that is masked inside the for loop's scope. Previously after max retries the error didn't leave the for scope and therefore httpResponse remained nil which in turn resulted in a crash. --- rpcclient/infrastructure.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 22430a2e1c..93b036c0d6 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -776,8 +776,10 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { tries := 10 for i := 0; i < tries; i++ { + var httpReq *http.Request + bodyReader := bytes.NewReader(jReq.marshalledJSON) - httpReq, err := http.NewRequest("POST", url, bodyReader) + httpReq, err = http.NewRequest("POST", url, bodyReader) if err != nil { jReq.responseChan <- &Response{result: nil, err: err} return @@ -815,6 +817,15 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { return } + // We still want to return an error if for any reason the respone + // remains empty. + if httpResponse == nil { + jReq.responseChan <- &Response{ + err: fmt.Errorf("invalid http POST response (nil), "+ + "method: %s, id: %d", jReq.method, jReq.id), + } + } + // Read the raw bytes and close the response. respBytes, err := ioutil.ReadAll(httpResponse.Body) httpResponse.Body.Close() From 9babf1fa08364e4a58f1b222e5ef79c324070632 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Mon, 9 May 2022 18:58:49 +0200 Subject: [PATCH 0697/1056] rpcclient: fix backoff logic This commit removes Sleep() from the rety handler so that the shutdown request is always respected. Furthermore the maximum retry count is corrected. --- rpcclient/infrastructure.go | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 93b036c0d6..b7732bc6c5 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -761,7 +761,9 @@ out: // handleSendPostMessage handles performing the passed HTTP request, reading the // result, unmarshalling it, and delivering the unmarshalled result to the // provided response channel. -func (c *Client) handleSendPostMessage(jReq *jsonRequest) { +func (c *Client) handleSendPostMessage(jReq *jsonRequest, + shutdown chan struct{}) { + protocol := "http" if !c.config.DisableTLS { protocol = "https" @@ -799,18 +801,27 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { httpReq.SetBasicAuth(user, pass) httpResponse, err = c.httpClient.Do(httpReq) - if err != nil { - backoff = requestRetryInterval * time.Duration(i+1) - if backoff > time.Minute { - backoff = time.Minute - } - log.Debugf("Failed command [%s] with id %d attempt %d."+ - " Retrying in %v... \n", jReq.method, jReq.id, - i, backoff) - time.Sleep(backoff) - continue + + // Quit the retry loop on success or if we can't retry anymore. + if err == nil || i == tries-1 { + break + } + + // Backoff sleep otherwise. + backoff = requestRetryInterval * time.Duration(i+1) + if backoff > time.Minute { + backoff = time.Minute + } + log.Debugf("Failed command [%s] with id %d attempt %d."+ + " Retrying in %v... \n", jReq.method, jReq.id, + i, backoff) + + select { + case <-time.After(backoff): + + case <-shutdown: + return } - break } if err != nil { jReq.responseChan <- &Response{err: err} @@ -874,7 +885,7 @@ out: // is closed. select { case jReq := <-c.sendPostChan: - c.handleSendPostMessage(jReq) + c.handleSendPostMessage(jReq, c.shutdown) case <-c.shutdown: break out From 97313ac873eee4365fc1de253a538335defcfed7 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Thu, 12 May 2022 22:09:38 +0200 Subject: [PATCH 0698/1056] rpcclient: save the last error when retrying --- rpcclient/infrastructure.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index b7732bc6c5..f931b83501 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -771,7 +771,7 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest, url := protocol + "://" + c.config.Host var ( - err error + err, lastErr error backoff time.Duration httpResponse *http.Response ) @@ -807,6 +807,12 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest, break } + // Save the last error for the case where we backoff further, + // retry and get an invalid response but no error. If this + // happens the saved last error will be used to enrich the error + // message that we pass back to the caller. + lastErr = err + // Backoff sleep otherwise. backoff = requestRetryInterval * time.Duration(i+1) if backoff > time.Minute { @@ -833,7 +839,8 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest, if httpResponse == nil { jReq.responseChan <- &Response{ err: fmt.Errorf("invalid http POST response (nil), "+ - "method: %s, id: %d", jReq.method, jReq.id), + "method: %s, id: %d, last error=%v", + jReq.method, jReq.id, lastErr), } } From 2ce30699532ab4cd75efdace7763ae372a6e8a2e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 31 May 2022 17:52:31 -0700 Subject: [PATCH 0699/1056] build: bump version to v0.23.0 --- cmd/btcctl/version.go | 2 +- version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go index edb42dbe7d..a09cc10b68 100644 --- a/cmd/btcctl/version.go +++ b/cmd/btcctl/version.go @@ -17,7 +17,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 22 + appMinor uint = 23 appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet diff --git a/version.go b/version.go index d6ff9171aa..cc0a6502c0 100644 --- a/version.go +++ b/version.go @@ -17,7 +17,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 22 + appMinor uint = 23 appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet From b2af7770e97ba04f6ec3b964b4b0bd36eaeabb2e Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Fri, 3 Jun 2022 14:58:20 +0200 Subject: [PATCH 0700/1056] rpcclient: fix missing return --- rpcclient/infrastructure.go | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index f931b83501..fbc43a4568 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -842,6 +842,7 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest, "method: %s, id: %d, last error=%v", jReq.method, jReq.id, lastErr), } + return } // Read the raw bytes and close the response. From e6f6ba4593f3adcefcb2bb97e53b44a21e7acc4d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 6 Jun 2022 16:14:13 -0700 Subject: [PATCH 0701/1056] build: bump version to v0.23.1 Includes: * A fix in the RPC server: https://github.com/btcsuite/btcd/pull/1862 * Rolling back a breaking change fromteh PoV of the rpcclient: https://github.com/btcsuite/btcd/pull/1844 --- cmd/btcctl/version.go | 2 +- version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go index a09cc10b68..42f3f7d024 100644 --- a/cmd/btcctl/version.go +++ b/cmd/btcctl/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 23 - appPatch uint = 0 + appPatch uint = 1 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. diff --git a/version.go b/version.go index cc0a6502c0..49a2cd68de 100644 --- a/version.go +++ b/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 23 - appPatch uint = 0 + appPatch uint = 1 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. From d9c09e03153ad26061b4905780bfa234dac8425a Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Tue, 28 Jun 2022 17:21:46 -0700 Subject: [PATCH 0702/1056] Bump btcd version in btcutil package --- btcutil/go.mod | 2 +- btcutil/psbt/go.mod | 2 +- go.sum | 14 +++++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index 4f98f6939a..5265dbb201 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 - github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c + github.com/btcsuite/btcd v0.22.1 github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 2c6dbbb7f8..6dd7ed9fd7 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -3,7 +3,7 @@ module github.com/btcsuite/btcd/btcutil/psbt go 1.17 require ( - github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c + github.com/btcsuite/btcd v0.22.1 github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 diff --git a/go.sum b/go.sum index 15e6ac4b7c..69b2b1feeb 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= @@ -8,14 +9,19 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOF github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -41,6 +47,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= @@ -50,10 +57,12 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -64,7 +73,10 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= From f46068f38e7a92ee24976e90286d0722d6069d30 Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Thu, 30 Jun 2022 15:59:56 -0700 Subject: [PATCH 0703/1056] bump version to v0.23.0 --- btcutil/go.mod | 2 +- btcutil/psbt/go.mod | 2 +- go.sum | 19 +------------------ 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index 5265dbb201..b03318a461 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 - github.com/btcsuite/btcd v0.22.1 + github.com/btcsuite/btcd v0.23.0 github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 6dd7ed9fd7..80f57fc1b3 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -3,7 +3,7 @@ module github.com/btcsuite/btcd/btcutil/psbt go 1.17 require ( - github.com/btcsuite/btcd v0.22.1 + github.com/btcsuite/btcd v0.23.0 github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 diff --git a/go.sum b/go.sum index 69b2b1feeb..1e39ef3263 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,6 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= +github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= @@ -9,19 +8,12 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOF github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -47,7 +39,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= @@ -57,12 +48,9 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -73,13 +61,9 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -115,7 +99,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 3ec3acc6fbeb1820d0fa94a638b5d65dbbaa856c Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Mon, 11 Jul 2022 16:30:53 -0700 Subject: [PATCH 0704/1056] go mod tidy in btcutil/ --- btcutil/go.sum | 1 + 1 file changed, 1 insertion(+) diff --git a/btcutil/go.sum b/btcutil/go.sum index e4f26dfd1c..8d35bdaf86 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -68,6 +68,7 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= From 149b0f09aa9bf3a04a0793f6400fe37b9f69efc0 Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Mon, 11 Jul 2022 16:36:12 -0700 Subject: [PATCH 0705/1056] go mod tidy in btcetc/ --- btcec/go.mod | 1 - btcec/go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/btcec/go.mod b/btcec/go.mod index a5e8c3abef..8c7cc1d63c 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -6,7 +6,6 @@ require ( github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 - golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 ) require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect diff --git a/btcec/go.sum b/btcec/go.sum index bd484d5ed4..0004a783bb 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -6,5 +6,3 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5 h1:rxKZ2gOnYxjfmakvUUqh9Gyb6KXfrj7JWTxORTYqb0E= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= From 3376655b9cf5abd242b778304ae05cbfaeb4522a Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Fri, 24 Jun 2022 14:27:13 +0200 Subject: [PATCH 0706/1056] btcec/schnorr/musig2: XOR rand with secret key This commit XORs the secret key (if a secret key is specified) with the random bytes as per MuSig2 Spec (https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#nonce-generation-1) --- btcec/schnorr/musig2/nonces.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 5a7fbd4b3d..d22f18cd56 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -31,7 +31,7 @@ var ( // NonceGenTag is used to generate the value (from a set of required an // optional field) that will be used as the part of the secret nonce. - NonceGenTag = []byte("Musig/nonce") + NonceGenTag = []byte("MuSig/nonce") byteOrder = binary.BigEndian ) @@ -270,6 +270,16 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { return nil, err } + // If the options contain a secret key, we XOR it with with the tagged + // random bytes. + if len(opts.secretKey) == 32 { + taggedHash := chainhash.TaggedHash(NonceAuxTag, randBytes[:]) + + for i := 0; i < chainhash.HashSize; i++ { + randBytes[i] = opts.secretKey[i] ^ taggedHash[i] + } + } + // Using our randomness and the set of optional params, generate our // two secret nonces: k1 and k2. k1, err := genNonceAuxBytes(randBytes[:], 1, opts) From 4ad819e7af8210737c86215f97decb85b9429d18 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Fri, 24 Jun 2022 14:28:32 +0200 Subject: [PATCH 0707/1056] btcec/schnorr/musig2: Update to MuSig 0.3.0 This commit changes the i's in GenNonces to 0 and 1 as per https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#change-log 0.3 --- btcec/schnorr/musig2/nonces.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index d22f18cd56..9600c45b1a 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -282,11 +282,11 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { // Using our randomness and the set of optional params, generate our // two secret nonces: k1 and k2. - k1, err := genNonceAuxBytes(randBytes[:], 1, opts) + k1, err := genNonceAuxBytes(randBytes[:], 0, opts) if err != nil { return nil, err } - k2, err := genNonceAuxBytes(randBytes[:], 2, opts) + k2, err := genNonceAuxBytes(randBytes[:], 1, opts) if err != nil { return nil, err } From 478a2f78c4a26ea3b8fc9b0bcee4dd23adf4e3df Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Fri, 29 Jul 2022 10:16:35 +0200 Subject: [PATCH 0708/1056] btcec/schnorr/musig2: Add nonce generation testcases This commit adds the testcases specified under version 0.3.1 from https://github.com/jonasnick/bips/blob/musig2/bip-musig2.mediawiki#change-log and the fixes from https://github.com/jonasnick/bips/commit/79438fd604d327e252d011712e7a4e9588a4584f --- btcec/schnorr/musig2/musig2_test.go | 85 +++++++++++++++++++++++++++++ btcec/schnorr/musig2/nonces.go | 14 +++++ 2 files changed, 99 insertions(+) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index c9ae74d7be..309718ca67 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -825,3 +825,88 @@ func TestMuSigEarlyNonce(t *testing.T) { t.Fatalf("final sig is invalid!") } } + +// TestMusig2NonceGenTestVectors tests the nonce generation function with +// the testvectors defined in the Musig2 BIP. +func TestMusig2NonceGenTestVectors(t *testing.T) { + t.Parallel() + + msg := bytes.Repeat([]byte{0x01}, 32) + sk := bytes.Repeat([]byte{0x02}, 32) + aggpk := bytes.Repeat([]byte{0x07}, 32) + extra_in := bytes.Repeat([]byte{0x08}, 32) + + testCases := []struct { + opts nonceGenOpts + expectedNonce string + }{ + { + opts: nonceGenOpts{ + randReader: &memsetRandReader{i: 0}, + secretKey: sk[:], + combinedKey: aggpk[:], + auxInput: extra_in[:], + msg: msg[:], + }, + expectedNonce: "E8F2E103D86800F19A4E97338D371CB885DB2" + + "F19D08C0BD205BBA9B906C971D0D786A17718AAFAD6D" + + "E025DDDD99DC823E2DFC1AE1DDFE920888AD53FFF423FC4", + }, + { + opts: nonceGenOpts{ + randReader: &memsetRandReader{i: 0}, + secretKey: sk[:], + combinedKey: aggpk[:], + auxInput: extra_in[:], + msg: nil, + }, + expectedNonce: "8A633F5EECBDB690A6BE4921426F41BE78D50" + + "9DC1CE894C1215844C0E4C6DE7ABC9A5BE0A3BF3FE31" + + "2CCB7E4817D2CB17A7CEA8382B73A99A583E323387B3C32", + }, + { + opts: nonceGenOpts{ + randReader: &memsetRandReader{i: 0}, + secretKey: nil, + combinedKey: nil, + auxInput: nil, + msg: nil, + }, + expectedNonce: "7B3B5A002356471AF0E961DE2549C121BD0D4" + + "8ABCEEDC6E034BDDF86AD3E0A187ECEE674CEF7364B0" + + "BC4BEEFB8B66CAD89F98DE2F8C5A5EAD5D1D1E4BD7D04CD", + }, + } + + for _, testCase := range testCases { + nonce, err := GenNonces(withCustomOptions(testCase.opts)) + if err != nil { + t.Fatalf("err gen nonce aux bytes %v", err) + } + + expectedBytes, _ := hex.DecodeString(testCase.expectedNonce) + if !bytes.Equal(nonce.SecNonce[:], expectedBytes) { + + t.Fatalf("nonces don't match: expected %x, got %x", + expectedBytes, nonce.SecNonce[:]) + } + } + +} + +type memsetRandReader struct { + i int +} + +func (mr *memsetRandReader) Read(buf []byte) (n int, err error) { + for i := range buf { + buf[i] = byte(mr.i) + } + return len(buf), nil +} + +func memsetLoop(a []byte, v uint8) { + for i := range a { + a[i] = byte(v) + } +} diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 9600c45b1a..0ba100229a 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -175,6 +175,20 @@ func WithNonceAuxInput(aux []byte) NonceGenOption { } } +// withCustomOptions allows a caller to pass a complete set of custom +// nonceGenOpts, without needing to create custom and checked structs such as +// *btcec.PrivateKey. This is mainly used to match the testcases provided by +// the MuSig2 BIP. +func withCustomOptions(customOpts nonceGenOpts) NonceGenOption { + return func(o *nonceGenOpts) { + o.randReader = customOpts.randReader + o.secretKey = customOpts.secretKey + o.combinedKey = customOpts.combinedKey + o.msg = customOpts.msg + o.auxInput = customOpts.auxInput + } +} + // lengthWriter is a function closure that allows a caller to control how the // length prefix of a byte slice is written. type lengthWriter func(w io.Writer, b []byte) error From 1b85a60b6df59ffb02b21ab92d4d1af9ccfca77d Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Wed, 29 Jun 2022 18:29:55 +0200 Subject: [PATCH 0709/1056] btcec/schnorr/musig2: Add AggregateKeys testvectors This commit adds the testvectors from https://github.com/jonasnick/bips/commit/20f60b0f37c47b147e01816c934f149d139cb905 to the testcases --- btcec/btcec.go | 15 +++ btcec/schnorr/musig2/keys.go | 9 +- btcec/schnorr/musig2/musig2_test.go | 173 +++++++++++++++++++++++++--- 3 files changed, 177 insertions(+), 20 deletions(-) diff --git a/btcec/btcec.go b/btcec/btcec.go index efde8d6a81..f85baba8c7 100644 --- a/btcec/btcec.go +++ b/btcec/btcec.go @@ -39,3 +39,18 @@ type CurveParams = secp.CurveParams func Params() *CurveParams { return secp.Params() } + +// Generator returns the public key at the Generator Point. +func Generator() *PublicKey { + var ( + result JacobianPoint + k secp.ModNScalar + ) + + k.SetInt(1) + ScalarBaseMultNonConst(&k, &result) + + result.ToAffine() + + return NewPublicKey(&result.X, &result.Y) +} diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index e61a22f2e5..8c86c624fb 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -26,6 +26,10 @@ var ( // ErrTweakedKeyIsInfinity is returned if while tweaking a key, we end // up with the point at infinity. ErrTweakedKeyIsInfinity = fmt.Errorf("tweaked key is infinity point") + + // ErrTweakedKeyOverflows is returned if a tweaking key is larger than + // 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141. + ErrTweakedKeyOverflows = fmt.Errorf("tweaked key is to large") ) // sortableKeys defines a type of slice of public keys that implements the sort @@ -286,7 +290,10 @@ func tweakKey(keyJ btcec.JacobianPoint, parityAcc btcec.ModNScalar, tweak [32]by // Next, map the tweak into a mod n integer so we can use it for // manipulations below. tweakInt := new(btcec.ModNScalar) - tweakInt.SetBytes(&tweak) + overflows := tweakInt.SetBytes(&tweak) + if overflows == 1 { + return keyJ, parityAcc, tweakAcc, ErrTweakedKeyOverflows + } // Next, we'll compute: Q_i = g*Q + t*G, where g is our parityFactor and t // is the tweakInt above. We'll space things out a bit to make it easier to diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 309718ca67..a032618bb9 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -16,6 +16,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/decred/dcrd/dcrec/secp256k1/v4" ) var ( @@ -26,14 +27,50 @@ var ( key3Bytes, _ = hex.DecodeString("3590A94E768F8E1815C2F24B4D80A8E3149" + "316C3518CE7B7AD338368D038CA66") - testKeys = [][]byte{key1Bytes, key2Bytes, key3Bytes} - - keyCombo1, _ = hex.DecodeString("E5830140512195D74C8307E39637CBE5FB730EBEAB80EC514CF88A877CEEEE0B") - keyCombo2, _ = hex.DecodeString("D70CD69A2647F7390973DF48CBFA2CCC407B8B2D60B08C5F1641185C7998A290") - keyCombo3, _ = hex.DecodeString("81A8B093912C9E481408D09776CEFB48AEB8B65481B6BAAFB3C5810106717BEB") - keyCombo4, _ = hex.DecodeString("2EB18851887E7BDC5E830E89B19DDBC28078F1FA88AAD0AD01CA06FE4F80210B") + invalidPk1, _ = hex.DecodeString("00000000000000000000000000000000" + + "00000000000000000000000000000005") + invalidPk2, _ = hex.DecodeString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + + "FFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30") + invalidTweak, _ = hex.DecodeString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" + + "BAAEDCE6AF48A03BBFD25E8CD0364141") + + testKeys = [][]byte{key1Bytes, key2Bytes, key3Bytes, invalidPk1, + invalidPk2} + + keyCombo1, _ = hex.DecodeString("E5830140512195D74C8307E39637CBE5FB73" + + "0EBEAB80EC514CF88A877CEEEE0B") + keyCombo2, _ = hex.DecodeString("D70CD69A2647F7390973DF48CBFA2CCC407B" + + "8B2D60B08C5F1641185C7998A290") + keyCombo3, _ = hex.DecodeString("81A8B093912C9E481408D09776CEFB48AEB8" + + "B65481B6BAAFB3C5810106717BEB") + keyCombo4, _ = hex.DecodeString("2EB18851887E7BDC5E830E89B19DDBC28078" + + "F1FA88AAD0AD01CA06FE4F80210B") ) +// getInfinityTweak returns a tweak that, when tweaking the Generator, triggers +// the ErrTweakedKeyIsInfinity error. +func getInfinityTweak() KeyTweakDesc { + generator := btcec.Generator() + + keySet := []*btcec.PublicKey{generator} + + keysHash := keyHashFingerprint(keySet, true) + uniqueKeyIndex := secondUniqueKeyIndex(keySet, true) + + n := &btcec.ModNScalar{} + + n.SetByteSlice(invalidTweak) + + coeff := aggregationCoefficient( + keySet, generator, keysHash, uniqueKeyIndex, + ).Negate().Add(n) + + return KeyTweakDesc{ + Tweak: coeff.Bytes(), + IsXOnly: false, + } +} + const ( keyAggTestVectorName = "key_agg_vectors.json" @@ -44,8 +81,10 @@ var dumpJson = flag.Bool("dumpjson", false, "if true, a JSON version of the "+ "test vectors will be written to the cwd") type jsonKeyAggTestCase struct { - Keys []string `json:"keys"` - ExpectedKey string `json:"expected_key"` + Keys []string `json:"keys"` + Tweaks []jsonTweak `json:"tweaks"` + ExpectedKey string `json:"expected_key"` + ExpectedError string `json:"expected_error"` } // TestMuSig2KeyAggTestVectors tests that this implementation of musig2 key @@ -56,8 +95,11 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { var jsonCases []jsonKeyAggTestCase testCases := []struct { - keyOrder []int - expectedKey []byte + keyOrder []int + explicitKeys []*btcec.PublicKey + tweaks []KeyTweakDesc + expectedKey []byte + expectedError error }{ // Keys in backwards lexicographical order. { @@ -82,18 +124,58 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { keyOrder: []int{0, 0, 1, 1}, expectedKey: keyCombo4, }, + + // Invalid public key. + { + keyOrder: []int{0, 3}, + expectedError: secp256k1.ErrPubKeyNotOnCurve, + }, + + // Public key exceeds field size. + { + keyOrder: []int{0, 4}, + expectedError: secp256k1.ErrPubKeyXTooBig, + }, + + // Tweak is out of range. + { + keyOrder: []int{0, 1}, + tweaks: []KeyTweakDesc{ + KeyTweakDesc{ + Tweak: to32ByteSlice(invalidTweak), + IsXOnly: true, + }, + }, + expectedError: ErrTweakedKeyOverflows, + }, + + // Intermediate tweaking result is point at infinity. + { + explicitKeys: []*secp256k1.PublicKey{btcec.Generator()}, + tweaks: []KeyTweakDesc{ + getInfinityTweak(), + }, + expectedError: ErrTweakedKeyIsInfinity, + }, } for i, testCase := range testCases { testName := fmt.Sprintf("%v", testCase.keyOrder) t.Run(testName, func(t *testing.T) { var ( - keys []*btcec.PublicKey - strKeys []string + keys []*btcec.PublicKey + strKeys []string + strTweaks []jsonTweak + jsonError string ) for _, keyIndex := range testCase.keyOrder { keyBytes := testKeys[keyIndex] pub, err := schnorr.ParsePubKey(keyBytes) - if err != nil { + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + return + case err != nil: t.Fatalf("unable to parse pubkeys: %v", err) } @@ -101,15 +183,59 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { strKeys = append(strKeys, hex.EncodeToString(keyBytes)) } - jsonCases = append(jsonCases, jsonKeyAggTestCase{ - Keys: strKeys, - ExpectedKey: hex.EncodeToString(testCase.expectedKey), - }) + for _, explicitKey := range testCase.explicitKeys { + keys = append(keys, explicitKey) + strKeys = append( + strKeys, + hex.EncodeToString( + explicitKey.SerializeCompressed(), + )) + } + + for _, tweak := range testCase.tweaks { + strTweaks = append( + strTweaks, + jsonTweak{ + Tweak: hex.EncodeToString( + tweak.Tweak[:], + ), + XOnly: tweak.IsXOnly, + }) + } + + if testCase.expectedError != nil { + jsonError = testCase.expectedError.Error() + } + + jsonCases = append( + jsonCases, + jsonKeyAggTestCase{ + Keys: strKeys, + Tweaks: strTweaks, + ExpectedKey: hex.EncodeToString( + testCase.expectedKey), + ExpectedError: jsonError, + }) uniqueKeyIndex := secondUniqueKeyIndex(keys, false) - combinedKey, _, _, _ := AggregateKeys( - keys, false, WithUniqueKeyIndex(uniqueKeyIndex), + opts := []KeyAggOption{WithUniqueKeyIndex(uniqueKeyIndex)} + if len(testCase.tweaks) > 0 { + opts = append(opts, WithKeyTweaks(testCase.tweaks...)) + } + + combinedKey, _, _, err := AggregateKeys( + keys, false, opts..., ) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + return + + case err != nil: + t.Fatalf("case #%v, got error %v", i, err) + } + combinedKeyBytes := schnorr.SerializePubKey(combinedKey.FinalKey) if !bytes.Equal(combinedKeyBytes, testCase.expectedKey) { t.Fatalf("case: #%v, invalid aggregation: "+ @@ -910,3 +1036,12 @@ func memsetLoop(a []byte, v uint8) { a[i] = byte(v) } } + +func to32ByteSlice(input []byte) [32]byte { + if len(input) != 32 { + panic("input byte slice has invalid length") + } + var output [32]byte + copy(output[:], input) + return output +} From 8b59e7aa6bee3f8c8db496eb2bc2df20c526f3ec Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Fri, 29 Jul 2022 10:32:35 +0200 Subject: [PATCH 0710/1056] btcec/schnorr/musig2: Add AggregateNonce testvectors This commit adds the testvectors from https://github.com/jonasnick/bips/commit/0ec2aefdaaabcb48704ab4718373a05e148e920d to the testcases --- btcec/schnorr/musig2/musig2_test.go | 156 ++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index a032618bb9..8b3a267b3c 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -74,6 +74,8 @@ func getInfinityTweak() KeyTweakDesc { const ( keyAggTestVectorName = "key_agg_vectors.json" + nonceAggTestVectorName = "nonce_agg_vectors.json" + signTestVectorName = "sign_vectors.json" ) @@ -1020,6 +1022,142 @@ func TestMusig2NonceGenTestVectors(t *testing.T) { } +var ( + pNonce1, _ = hex.DecodeString("020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E666" + + "03BA47FBC1834437B3212E89A84D8425E7BF12E0245D98262268EBDCB385D50641") + pNonce2, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + + "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833") + + expectedNonce, _ = hex.DecodeString("035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B" + + "024725377345BDE0E9C33AF3C43C0A29A9249F2F2956FA8CFEB55C8573D0262DC8") + + invalidNonce1, _ = hex.DecodeString("04FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833") + invalidNonce2, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B831") + invalidNonce3, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30") +) + +type jsonNonceAggTestCase struct { + Nonces []string `json:"nonces"` + ExpectedNonce string `json:"expected_key"` + ExpectedError string `json:"expected_error"` +} + +func TestMusig2AggregateNoncesTestVectors(t *testing.T) { + t.Parallel() + + var jsonCases []jsonNonceAggTestCase + + testCases := []struct { + nonces [][]byte + expectedNonce []byte + expectedError error + }{ + // Vector 1: Valid. + { + nonces: [][]byte{pNonce1, pNonce2}, + expectedNonce: expectedNonce, + }, + + // Vector 2: Public nonce from signer 1 is invalid due wrong + // tag, 0x04, inthe first half. + { + nonces: [][]byte{pNonce1, invalidNonce1}, + expectedError: secp256k1.ErrPubKeyInvalidFormat, + }, + + // Vector 3: Public nonce from signer 0 is invalid because the + // second half does not correspond to an X coordinate. + { + nonces: [][]byte{invalidNonce2, pNonce2}, + expectedError: secp256k1.ErrPubKeyNotOnCurve, + }, + + // Vector 4: Public nonce from signer 0 is invalid because + // second half exceeds field size. + { + nonces: [][]byte{invalidNonce3, pNonce2}, + expectedError: secp256k1.ErrPubKeyXTooBig, + }, + + // Vector 5: Sum of second points encoded in the nonces would + // be point at infinity, therefore set sum to base point G. + { + nonces: [][]byte{ + append( + append([]byte{}, pNonce1[0:33]...), + getGBytes()..., + ), + append( + append([]byte{}, pNonce2[0:33]...), + getNegGBytes()..., + ), + }, + expectedNonce: append( + append([]byte{}, expectedNonce[0:33]...), + getGBytes()..., + ), + }, + } + for i, testCase := range testCases { + testName := fmt.Sprintf("Vector %v", i+1) + t.Run(testName, func(t *testing.T) { + var ( + nonces [][66]byte + strNonces []string + jsonError string + ) + for _, nonce := range testCase.nonces { + nonces = append(nonces, toPubNonceSlice(nonce)) + strNonces = append(strNonces, hex.EncodeToString(nonce)) + } + + if testCase.expectedError != nil { + jsonError = testCase.expectedError.Error() + } + + jsonCases = append(jsonCases, jsonNonceAggTestCase{ + Nonces: strNonces, + ExpectedNonce: hex.EncodeToString(expectedNonce), + ExpectedError: jsonError, + }) + + aggregatedNonce, err := AggregateNonces(nonces) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: + t.Fatalf("aggregating nonce error: %v", err) + } + + if !bytes.Equal(testCase.expectedNonce, aggregatedNonce[:]) { + t.Fatalf("case: #%v, invalid nonce aggregation: "+ + "expected %x, got %x", i, testCase.expectedNonce, + aggregatedNonce) + } + + }) + } + + if *dumpJson { + jsonBytes, err := json.Marshal(jsonCases) + if err != nil { + t.Fatalf("unable to encode json: %v", err) + } + + var formattedJson bytes.Buffer + json.Indent(&formattedJson, jsonBytes, "", "\t") + err = ioutil.WriteFile( + nonceAggTestVectorName, formattedJson.Bytes(), 0644, + ) + if err != nil { + t.Fatalf("unable to write file: %v", err) + } + } +} + type memsetRandReader struct { i int } @@ -1045,3 +1183,21 @@ func to32ByteSlice(input []byte) [32]byte { copy(output[:], input) return output } + +func toPubNonceSlice(input []byte) [PubNonceSize]byte { + var output [PubNonceSize]byte + copy(output[:], input) + + return output +} + +func getGBytes() []byte { + return btcec.Generator().SerializeCompressed() +} + +func getNegGBytes() []byte { + pk := getGBytes() + pk[0] = 0x3 + + return pk +} From 53f47d65f139dbe484af573d0b9c8c1fd6384cc1 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Thu, 4 Aug 2022 11:49:17 +0200 Subject: [PATCH 0711/1056] btcec/schnorr/musig2: Add Sign test vectors This commit adds the testvectors from https://github.com/jonasnick/bips/commit/4c06f31daf54f0fc614144c28fcc45f5a10c6590 to the testcases --- btcec/schnorr/musig2/musig2_test.go | 240 ++++++++++++++++++++-------- 1 file changed, 169 insertions(+), 71 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 8b3a267b3c..7ff6e2e2c3 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -291,22 +291,28 @@ func parseKey(xHex string) *btcec.PublicKey { var ( signSetPrivKey, _ = btcec.PrivKeyFromBytes( - mustParseHex("7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671"), + mustParseHex("7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DF" + + "E8D76D7F2D1007671"), ) - signSetPubKey, _ = schnorr.ParsePubKey(schnorr.SerializePubKey(signSetPrivKey.PubKey())) + signSetPubKey = schnorr.SerializePubKey(signSetPrivKey.PubKey()) - signTestMsg = mustParseHex("F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF") + signTestMsg = mustParseHex("F95466D086770E689964664219266FE5ED215C92A" + + "E20BAB5C9D79ADDDDF3C0CF") - signSetKey2, _ = schnorr.ParsePubKey( - mustParseHex("F9308A019258C31049344F85F89D5229B531C845836F99B086" + - "01F113BCE036F9"), - ) - signSetKey3, _ = schnorr.ParsePubKey( - mustParseHex("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843" + - "240F7B502BA659"), - ) + signSetKey2 = mustParseHex("F9308A019258C31049344F85F89D5229B531C8458" + + "36F99B08601F113BCE036F9") + + signSetKey3 = mustParseHex("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA" + + "2DECED843240F7B502BA659") - signSetKeys = []*btcec.PublicKey{signSetPubKey, signSetKey2, signSetKey3} + invalidSetKey1 = mustParseHex("00000000000000000000000000000000" + + "00000000000000000000000000000007") + + signSetKeys = [][]byte{signSetPubKey, signSetKey2, signSetKey3, invalidPk1} + + aggregatedNonce = toPubNonceSlice(mustParseHex("028465FCF0BBDBCF443AA" + + "BCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926" + + "D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9")) ) func formatTweakParity(tweaks []KeyTweakDesc) string { @@ -331,20 +337,21 @@ type jsonTweak struct { XOnly bool `json:"x_only"` } -type tweakSignCase struct { - Keys []string `json:"keys"` - Tweaks []jsonTweak `json:"tweaks,omitempty"` +type jsonTweakSignCase struct { + Keys []string `json:"keys"` + Tweaks []jsonTweak `json:"tweaks,omitempty"` + AggNonce string `json:"agg_nonce"` - ExpectedSig string `json:"expected_sig"` + ExpectedSig string `json:"expected_sig"` + ExpectedError string `json:"expected_error` } type jsonSignTestCase struct { SecNonce string `json:"secret_nonce"` - AggNonce string `json:"agg_nonce"` SigningKey string `json:"signing_key"` Msg string `json:"msg"` - TestCases []tweakSignCase `json:"test_cases"` + TestCases []jsonTweakSignCase `json:"test_cases"` } // TestMuSig2SigningTestVectors tests that the musig2 implementation produces @@ -357,21 +364,11 @@ func TestMuSig2SigningTestVectors(t *testing.T) { jsonCases.SigningKey = hex.EncodeToString(signSetPrivKey.Serialize()) jsonCases.Msg = hex.EncodeToString(signTestMsg) - var aggregatedNonce [PubNonceSize]byte - copy( - aggregatedNonce[:], - mustParseHex("028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61"), - ) - copy( - aggregatedNonce[33:], - mustParseHex("037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9"), - ) - - jsonCases.AggNonce = hex.EncodeToString(aggregatedNonce[:]) - var secNonce [SecNonceSize]byte - copy(secNonce[:], mustParseHex("508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61")) - copy(secNonce[32:], mustParseHex("FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7")) + copy(secNonce[:], mustParseHex("508B81A611F100A6B2B6B29656590898AF488B"+ + "CF2E1F55CF22E5CFB84421FE61")) + copy(secNonce[32:], mustParseHex("FA27FD49B1D50085B481285E1CA205D55C82"+ + "CC1B31FF5CD54A489829355901F7")) jsonCases.SecNonce = hex.EncodeToString(secNonce[:]) @@ -410,40 +407,105 @@ func TestMuSig2SigningTestVectors(t *testing.T) { testCases := []struct { keyOrder []int + aggNonce [66]byte expectedPartialSig []byte tweaks []KeyTweakDesc + expectedError error }{ + // Vector 1 + { + keyOrder: []int{0, 1, 2}, + aggNonce: aggregatedNonce, + expectedPartialSig: mustParseHex("68537CC5234E505BD14" + + "061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B"), + }, + + // Vector 2 + { + keyOrder: []int{1, 0, 2}, + aggNonce: aggregatedNonce, + expectedPartialSig: mustParseHex("2DF67BFFF18E3DE797E" + + "13C6475C963048138DAEC5CB20A357CECA7C8424295EA"), + }, + + // Vector 3 + { + keyOrder: []int{1, 2, 0}, + aggNonce: aggregatedNonce, + expectedPartialSig: mustParseHex("0D5B651E6DE34A29A12" + + "DE7A8B4183B4AE6A7F7FBE15CDCAFA4A3D1BCAABC7517"), + }, + + // Vector 4: Signer 2 provided an invalid public key + { + keyOrder: []int{1, 0, 3}, + aggNonce: aggregatedNonce, + expectedError: secp256k1.ErrPubKeyNotOnCurve, + }, + + // Vector 5: Aggregate nonce is invalid due wrong tag, 0x04, + // in the first half. { - keyOrder: []int{0, 1, 2}, - expectedPartialSig: mustParseHex("68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B"), + + keyOrder: []int{1, 2, 0}, + aggNonce: toPubNonceSlice( + mustParseHex("048465FCF0BBDBCF443AABCCE533D42" + + "B4B5A10966AC09A49655E8C42DAAB8FCD610" + + "37496A3CC86926D452CAFCFD55D25972CA16" + + "75D549310DE296BFF42F72EEEA8C9")), + expectedError: secp256k1.ErrPubKeyInvalidFormat, }, + + // Vector 6: Aggregate nonce is invalid because the second half + // does not correspond to an X coordinate. { - keyOrder: []int{1, 0, 2}, - expectedPartialSig: mustParseHex("2DF67BFFF18E3DE797E13C6475C963048138DAEC5CB20A357CECA7C8424295EA"), + + keyOrder: []int{1, 2, 0}, + aggNonce: toPubNonceSlice( + mustParseHex("028465FCF0BBDBCF443AABCCE533D42" + + "B4B5A10966AC09A49655E8C42DAAB8FCD610" + + "200000000000000000000000000000000000" + + "00000000000000000000000000009")), + expectedError: secp256k1.ErrPubKeyNotOnCurve, }, + + // Vector 7: Aggregate nonce is invalid because the second half + // exceeds field size. { - keyOrder: []int{1, 2, 0}, - expectedPartialSig: mustParseHex("0D5B651E6DE34A29A12DE7A8B4183B4AE6A7F7FBE15CDCAFA4A3D1BCAABC7517"), + + keyOrder: []int{1, 2, 0}, + aggNonce: toPubNonceSlice( + mustParseHex("028465FCF0BBDBCF443AABCCE533D42" + + "B4B5A10966AC09A49655E8C42DAAB8FCD610" + + "2FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + + "FFFFFFFFFFFFFFFFFFFFEFFFFFC30")), + expectedError: secp256k1.ErrPubKeyXTooBig, }, // A single x-only tweak. { - keyOrder: []int{1, 2, 0}, - expectedPartialSig: mustParseHex("5e24c7496b565debc3b9639e6f1304a21597f9603d3ab05b4913641775e1375b"), - tweaks: []KeyTweakDesc{genTweakParity(tweak1, true)}, + keyOrder: []int{1, 2, 0}, + aggNonce: aggregatedNonce, + expectedPartialSig: mustParseHex("5e24c7496b565debc3b" + + "9639e6f1304a21597f9603d3ab05b4913641775e1375b"), + tweaks: []KeyTweakDesc{genTweakParity(tweak1, true)}, }, // A single ordinary tweak. { - keyOrder: []int{1, 2, 0}, - expectedPartialSig: mustParseHex("78408ddcab4813d1394c97d493ef1084195c1d4b52e63ecd7bc5991644e44ddd"), - tweaks: []KeyTweakDesc{genTweakParity(tweak1, false)}, + keyOrder: []int{1, 2, 0}, + aggNonce: aggregatedNonce, + expectedPartialSig: mustParseHex("78408ddcab4813d1394c" + + "97d493ef1084195c1d4b52e63ecd7bc5991644e44ddd"), + tweaks: []KeyTweakDesc{genTweakParity(tweak1, false)}, }, // An ordinary tweak then an x-only tweak. { - keyOrder: []int{1, 2, 0}, - expectedPartialSig: mustParseHex("C3A829A81480E36EC3AB052964509A94EBF34210403D16B226A6F16EC85B7357"), + keyOrder: []int{1, 2, 0}, + aggNonce: aggregatedNonce, + expectedPartialSig: mustParseHex("C3A829A81480E36EC3A" + + "B052964509A94EBF34210403D16B226A6F16EC85B7357"), tweaks: []KeyTweakDesc{ genTweakParity(tweak1, false), genTweakParity(tweak2, true), @@ -452,8 +514,10 @@ func TestMuSig2SigningTestVectors(t *testing.T) { // Four tweaks, in the order: x-only, ordinary, x-only, ordinary. { - keyOrder: []int{1, 2, 0}, - expectedPartialSig: mustParseHex("8C4473C6A382BD3C4AD7BE59818DA5ED7CF8CEC4BC21996CFDA08BB4316B8BC7"), + keyOrder: []int{1, 2, 0}, + aggNonce: aggregatedNonce, + expectedPartialSig: mustParseHex("8C4473C6A382BD3C4AD" + + "7BE59818DA5ED7CF8CEC4BC21996CFDA08BB4316B8BC7"), tweaks: []KeyTweakDesc{ genTweakParity(tweak1, true), genTweakParity(tweak2, false), @@ -471,17 +535,22 @@ func TestMuSig2SigningTestVectors(t *testing.T) { if len(testCase.tweaks) != 0 { testName += fmt.Sprintf("/x_only=%v", formatTweakParity(testCase.tweaks)) } - t.Run(testName, func(t *testing.T) { - var strKeys []string keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) for _, keyIndex := range testCase.keyOrder { - keySet = append(keySet, signSetKeys[keyIndex]) - strKeys = append( - strKeys, hex.EncodeToString( - schnorr.SerializePubKey(signSetKeys[keyIndex]), - ), - ) + keyBytes := signSetKeys[keyIndex] + pub, err := schnorr.ParsePubKey(keyBytes) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: + t.Fatalf("unable to parse pubkeys: %v", err) + } + + keySet = append(keySet, pub) } var opts []SignOption @@ -491,19 +560,17 @@ func TestMuSig2SigningTestVectors(t *testing.T) { ) } - var jsonTweaks []jsonTweak - for _, tweak := range testCase.tweaks { - jsonTweaks = append(jsonTweaks, jsonTweak{ - Tweak: hex.EncodeToString(tweak.Tweak[:]), - XOnly: tweak.IsXOnly, - }) - } - partialSig, err := Sign( - secNonce, signSetPrivKey, aggregatedNonce, + secNonce, signSetPrivKey, testCase.aggNonce, keySet, msg, opts..., ) - if err != nil { + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: t.Fatalf("unable to generate partial sig: %v", err) } @@ -516,12 +583,43 @@ func TestMuSig2SigningTestVectors(t *testing.T) { ) } - jsonCases.TestCases = append(jsonCases.TestCases, tweakSignCase{ - Keys: strKeys, - Tweaks: jsonTweaks, - ExpectedSig: hex.EncodeToString(testCase.expectedPartialSig), - }) }) + + if *dumpJson { + var ( + strKeys []string + jsonError string + ) + + for _, keyIndex := range testCase.keyOrder { + keyBytes := signSetKeys[keyIndex] + strKeys = append(strKeys, hex.EncodeToString(keyBytes)) + } + + if testCase.expectedError != nil { + jsonError = testCase.expectedError.Error() + } + + tweakSignCase := jsonTweakSignCase{ + Keys: strKeys, + ExpectedSig: hex.EncodeToString(testCase.expectedPartialSig), + AggNonce: hex.EncodeToString(testCase.aggNonce[:]), + ExpectedError: jsonError, + } + + var jsonTweaks []jsonTweak + for _, tweak := range testCase.tweaks { + jsonTweaks = append( + jsonTweaks, + jsonTweak{ + Tweak: hex.EncodeToString(tweak.Tweak[:]), + XOnly: tweak.IsXOnly, + }) + } + tweakSignCase.Tweaks = jsonTweaks + + jsonCases.TestCases = append(jsonCases.TestCases, tweakSignCase) + } } if *dumpJson { From 85356e81740b03c73adc5b5edd57c52970926b19 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Wed, 29 Jun 2022 18:37:16 +0200 Subject: [PATCH 0712/1056] btcec/schnorr/musig2: Throw error on invalid partial sig --- btcec/schnorr/musig2/sign.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 4f9439fe6a..0529c53c9a 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -85,7 +85,10 @@ func (p *PartialSignature) Decode(r io.Reader) error { return nil } - p.S.SetBytes(&sBytes) + overflows := p.S.SetBytes(&sBytes) + if overflows == 1 { + return ErrPartialSigInvalid + } return nil } From 5e960074ea29b8af62d6def11eeda8ff13501224 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Thu, 4 Aug 2022 11:51:02 +0200 Subject: [PATCH 0713/1056] btcec/schnorr/musig2: Add PartialSigVerify testvectors Adds testvectors from https://github.com/jonasnick/bips/commit/ebb6a7454bfc852f405fb7efb198c7e919248316 and https://github.com/jonasnick/bips/commit/6788ee5412ccb394f20b0758227a916d8f1fa631 --- btcec/schnorr/musig2/musig2_test.go | 377 ++++++++++++++++++++++++---- 1 file changed, 332 insertions(+), 45 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 7ff6e2e2c3..9608fcad27 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -308,11 +308,60 @@ var ( invalidSetKey1 = mustParseHex("00000000000000000000000000000000" + "00000000000000000000000000000007") + signExpected1 = mustParseHex("68537CC5234E505BD14061F8DA9E90C220A1818" + + "55FD8BDB7F127BB12403B4D3B") + signExpected2 = mustParseHex("2DF67BFFF18E3DE797E13C6475C963048138DAE" + + "C5CB20A357CECA7C8424295EA") + signExpected3 = mustParseHex("0D5B651E6DE34A29A12DE7A8B4183B4AE6A7F7F" + + "BE15CDCAFA4A3D1BCAABC7517") + signSetKeys = [][]byte{signSetPubKey, signSetKey2, signSetKey3, invalidPk1} aggregatedNonce = toPubNonceSlice(mustParseHex("028465FCF0BBDBCF443AA" + "BCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926" + "D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9")) + verifyPnonce1 = mustParsePubNonce("0337C87821AFD50A8644D820A8F3E02E49" + + "9C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352A" + + "A9405D1428C15F4B75F04DAE642A95C2548480") + verifyPnonce2 = mustParsePubNonce("0279BE667EF9DCBBAC55A06295CE870B07" + + "029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE" + + "870B07029BFCDB2DCE28D959F2815B16F81798") + verifyPnonce3 = mustParsePubNonce("032DE2662628C90B03F5E720284EB52FF7" + + "D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1C" + + "A6BEB2090C93D930321071AD40B2F44E599046") + + tweak1 = KeyTweakDesc{ + Tweak: [32]byte{ + 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, + 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, + 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, + 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, + }, + } + tweak2 = KeyTweakDesc{ + Tweak: [32]byte{ + 0xae, 0x2e, 0xa7, 0x97, 0xcc, 0xf, 0xe7, 0x2a, + 0xc5, 0xb9, 0x7b, 0x97, 0xf3, 0xc6, 0x95, 0x7d, + 0x7e, 0x41, 0x99, 0xa1, 0x67, 0xa5, 0x8e, 0xb0, + 0x8b, 0xca, 0xff, 0xda, 0x70, 0xac, 0x4, 0x55, + }, + } + tweak3 = KeyTweakDesc{ + Tweak: [32]byte{ + 0xf5, 0x2e, 0xcb, 0xc5, 0x65, 0xb3, 0xd8, 0xbe, + 0xa2, 0xdf, 0xd5, 0xb7, 0x5a, 0x4f, 0x45, 0x7e, + 0x54, 0x36, 0x98, 0x9, 0x32, 0x2e, 0x41, 0x20, + 0x83, 0x16, 0x26, 0xf2, 0x90, 0xfa, 0x87, 0xe0, + }, + } + tweak4 = KeyTweakDesc{ + Tweak: [32]byte{ + 0x19, 0x69, 0xad, 0x73, 0xcc, 0x17, 0x7f, 0xa0, + 0xb4, 0xfc, 0xed, 0x6d, 0xf1, 0xf7, 0xbf, 0x99, + 0x7, 0xe6, 0x65, 0xfd, 0xe9, 0xba, 0x19, 0x6a, + 0x74, 0xfe, 0xd0, 0xa3, 0xcf, 0x5a, 0xef, 0x9d, + }, + } ) func formatTweakParity(tweaks []KeyTweakDesc) string { @@ -372,39 +421,6 @@ func TestMuSig2SigningTestVectors(t *testing.T) { jsonCases.SecNonce = hex.EncodeToString(secNonce[:]) - tweak1 := KeyTweakDesc{ - Tweak: [32]byte{ - 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, - 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, - 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, - 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, - }, - } - tweak2 := KeyTweakDesc{ - Tweak: [32]byte{ - 0xae, 0x2e, 0xa7, 0x97, 0xcc, 0xf, 0xe7, 0x2a, - 0xc5, 0xb9, 0x7b, 0x97, 0xf3, 0xc6, 0x95, 0x7d, - 0x7e, 0x41, 0x99, 0xa1, 0x67, 0xa5, 0x8e, 0xb0, - 0x8b, 0xca, 0xff, 0xda, 0x70, 0xac, 0x4, 0x55, - }, - } - tweak3 := KeyTweakDesc{ - Tweak: [32]byte{ - 0xf5, 0x2e, 0xcb, 0xc5, 0x65, 0xb3, 0xd8, 0xbe, - 0xa2, 0xdf, 0xd5, 0xb7, 0x5a, 0x4f, 0x45, 0x7e, - 0x54, 0x36, 0x98, 0x9, 0x32, 0x2e, 0x41, 0x20, - 0x83, 0x16, 0x26, 0xf2, 0x90, 0xfa, 0x87, 0xe0, - }, - } - tweak4 := KeyTweakDesc{ - Tweak: [32]byte{ - 0x19, 0x69, 0xad, 0x73, 0xcc, 0x17, 0x7f, 0xa0, - 0xb4, 0xfc, 0xed, 0x6d, 0xf1, 0xf7, 0xbf, 0x99, - 0x7, 0xe6, 0x65, 0xfd, 0xe9, 0xba, 0x19, 0x6a, - 0x74, 0xfe, 0xd0, 0xa3, 0xcf, 0x5a, 0xef, 0x9d, - }, - } - testCases := []struct { keyOrder []int aggNonce [66]byte @@ -414,26 +430,23 @@ func TestMuSig2SigningTestVectors(t *testing.T) { }{ // Vector 1 { - keyOrder: []int{0, 1, 2}, - aggNonce: aggregatedNonce, - expectedPartialSig: mustParseHex("68537CC5234E505BD14" + - "061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B"), + keyOrder: []int{0, 1, 2}, + aggNonce: aggregatedNonce, + expectedPartialSig: signExpected1, }, // Vector 2 { - keyOrder: []int{1, 0, 2}, - aggNonce: aggregatedNonce, - expectedPartialSig: mustParseHex("2DF67BFFF18E3DE797E" + - "13C6475C963048138DAEC5CB20A357CECA7C8424295EA"), + keyOrder: []int{1, 0, 2}, + aggNonce: aggregatedNonce, + expectedPartialSig: signExpected2, }, // Vector 3 { - keyOrder: []int{1, 2, 0}, - aggNonce: aggregatedNonce, - expectedPartialSig: mustParseHex("0D5B651E6DE34A29A12" + - "DE7A8B4183B4AE6A7F7FBE15CDCAFA4A3D1BCAABC7517"), + keyOrder: []int{1, 2, 0}, + aggNonce: aggregatedNonce, + expectedPartialSig: signExpected3, }, // Vector 4: Signer 2 provided an invalid public key @@ -639,6 +652,261 @@ func TestMuSig2SigningTestVectors(t *testing.T) { } } +func TestMusig2PartialSigVerifyTestVectors(t *testing.T) { + t.Parallel() + + testCases := []struct { + partialSig []byte + nonces [][66]byte + pubnonceIndex int + keyOrder []int + tweaks []KeyTweakDesc + expectedError error + }{ + // A single x-only tweak. + { + keyOrder: []int{1, 2, 0}, + nonces: [][66]byte{ + verifyPnonce2, + verifyPnonce3, + verifyPnonce1, + }, + pubnonceIndex: 2, + partialSig: mustParseHex("5e24c7496b565debc3b9639e" + + "6f1304a21597f9603d3ab05b4913641775e1375b"), + tweaks: []KeyTweakDesc{genTweakParity(tweak1, true)}, + }, + // A single ordinary tweak. + { + keyOrder: []int{1, 2, 0}, + nonces: [][66]byte{ + verifyPnonce2, + verifyPnonce3, + verifyPnonce1, + }, + pubnonceIndex: 2, + partialSig: mustParseHex("78408ddcab4813d1394c97d4" + + "93ef1084195c1d4b52e63ecd7bc5991644e44ddd"), + tweaks: []KeyTweakDesc{genTweakParity(tweak1, false)}, + }, + // An ordinary tweak then an x-only tweak. + { + keyOrder: []int{1, 2, 0}, + nonces: [][66]byte{ + verifyPnonce2, + verifyPnonce3, + verifyPnonce1, + }, + pubnonceIndex: 2, + partialSig: mustParseHex("C3A829A81480E36EC3AB0529" + + "64509A94EBF34210403D16B226A6F16EC85B7357"), + tweaks: []KeyTweakDesc{ + genTweakParity(tweak1, false), + genTweakParity(tweak2, true), + }, + }, + + // Four tweaks, in the order: x-only, ordinary, x-only, ordinary. + { + keyOrder: []int{1, 2, 0}, + nonces: [][66]byte{ + verifyPnonce2, + verifyPnonce3, + verifyPnonce1, + }, + pubnonceIndex: 2, + partialSig: mustParseHex("8C4473C6A382BD3C4AD7BE5" + + "9818DA5ED7CF8CEC4BC21996CFDA08BB4316B8BC7"), + tweaks: []KeyTweakDesc{ + genTweakParity(tweak1, true), + genTweakParity(tweak2, false), + genTweakParity(tweak3, true), + genTweakParity(tweak4, false), + }, + }, + // Vector 8. + { + + partialSig: signExpected1, + pubnonceIndex: 0, + keyOrder: []int{0, 1, 2}, + nonces: [][66]byte{ + verifyPnonce1, + verifyPnonce2, + verifyPnonce3, + }, + }, + // Vector 9. + { + + partialSig: signExpected2, + pubnonceIndex: 1, + keyOrder: []int{1, 0, 2}, + nonces: [][66]byte{ + verifyPnonce2, + verifyPnonce1, + verifyPnonce3, + }, + }, + // Vector 10. + { + + partialSig: signExpected3, + pubnonceIndex: 2, + keyOrder: []int{1, 2, 0}, + nonces: [][66]byte{ + verifyPnonce2, + verifyPnonce3, + verifyPnonce1, + }, + }, + // Vector 11: Wrong signature (which is equal to the negation + // of valid signature expected[0]). + { + + partialSig: mustParseHex("97AC833ADCB1AFA42EBF9E0" + + "725616F3C9A0D5B614F6FE283CEAAA37A8FFAF406"), + pubnonceIndex: 0, + keyOrder: []int{0, 1, 2}, + nonces: [][66]byte{ + verifyPnonce1, + verifyPnonce2, + verifyPnonce3, + }, + expectedError: ErrPartialSigInvalid, + }, + // Vector 12: Wrong signer. + { + + partialSig: signExpected1, + pubnonceIndex: 1, + keyOrder: []int{0, 1, 2}, + nonces: [][66]byte{ + verifyPnonce1, + verifyPnonce2, + verifyPnonce3, + }, + expectedError: ErrPartialSigInvalid, + }, + // Vector 13: Signature exceeds group size. + { + + partialSig: mustParseHex("FFFFFFFFFFFFFFFFFFFFFFFF" + + "FFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"), + pubnonceIndex: 0, + keyOrder: []int{0, 1, 2}, + nonces: [][66]byte{ + verifyPnonce1, + verifyPnonce2, + verifyPnonce3, + }, + expectedError: ErrPartialSigInvalid, + }, + // Vector 14: Invalid pubnonce. + { + + partialSig: signExpected1, + pubnonceIndex: 0, + keyOrder: []int{0, 1, 2}, + nonces: [][66]byte{ + canParsePubNonce("020000000000000000000000000" + + "000000000000000000000000000000000000009"), + verifyPnonce2, + verifyPnonce3, + }, + expectedError: secp256k1.ErrPubKeyNotOnCurve, + }, + // Vector 15: Invalid public key. + { + + partialSig: signExpected1, + pubnonceIndex: 0, + keyOrder: []int{3, 1, 2}, + nonces: [][66]byte{ + verifyPnonce1, + verifyPnonce2, + verifyPnonce3, + }, + expectedError: secp256k1.ErrPubKeyNotOnCurve, + }, + } + + for _, testCase := range testCases { + + // todo find name + testName := fmt.Sprintf("%v/tweak=%v", testCase.pubnonceIndex, testCase.keyOrder) + + t.Run(testName, func(t *testing.T) { + + combinedNonce, err := AggregateNonces(testCase.nonces) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: + t.Fatalf("unable to aggregate nonces %v", err) + } + + keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) + for _, keyIndex := range testCase.keyOrder { + keyBytes := signSetKeys[keyIndex] + pub, err := schnorr.ParsePubKey(keyBytes) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: + t.Fatalf("unable to parse pubkeys: %v", err) + } + + keySet = append(keySet, pub) + } + + ps := &PartialSignature{} + err = ps.Decode(bytes.NewBuffer(testCase.partialSig)) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: + t.Fatal(err) + } + + var opts []SignOption + if len(testCase.tweaks) != 0 { + opts = append( + opts, WithTweaks(testCase.tweaks...), + ) + } + + err = verifyPartialSig( + ps, + testCase.nonces[testCase.pubnonceIndex], + combinedNonce, + keySet, + signSetKeys[testCase.keyOrder[testCase.pubnonceIndex]], + to32ByteSlice(signTestMsg), + opts..., + ) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: + t.Fatalf("unable to aggregate nonces %v", err) + } + }) + } +} + type signer struct { privKey *btcec.PrivateKey pubKey *btcec.PublicKey @@ -1299,3 +1567,22 @@ func getNegGBytes() []byte { return pk } + +func mustParsePubNonce(str string) [PubNonceSize]byte { + b, err := hex.DecodeString(str) + if err != nil { + panic(fmt.Errorf("unable to parse hex: %v", err)) + } + if len(b) != PubNonceSize { + panic(fmt.Errorf("not a public nonce: %v", err)) + } + return toPubNonceSlice(b) +} + +func canParsePubNonce(str string) [PubNonceSize]byte { + b, err := hex.DecodeString(str) + if err != nil { + panic(fmt.Errorf("unable to parse hex: %v", err)) + } + return toPubNonceSlice(b) +} From 4b2fe9f83e6cfbf6b383caa51ea4637c0d2c19af Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Thu, 4 Aug 2022 11:55:19 +0200 Subject: [PATCH 0714/1056] btcec/schnorr/musig2: Add CombineSig testvectors This commit adds the testvectors from https://github.com/jonasnick/bips/commit/cdc3520c0726d73125f7dbf9826e3be9cffe1948 --- btcec/schnorr/musig2/musig2_test.go | 273 ++++++++++++++++++++++++++++ 1 file changed, 273 insertions(+) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 9608fcad27..1ff59a2ffa 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -16,6 +16,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/decred/dcrd/dcrec/secp256k1/v4" ) @@ -1535,6 +1536,266 @@ func (mr *memsetRandReader) Read(buf []byte) (n int, err error) { return len(buf), nil } +var ( + combineSigKey0 = mustParseHex("487D1B83B41B4CBBD07A111F1BBC7BDC8864CF" + + "EF5DBF96E46E51C68399B0BEF6") + combineSigKey1 = mustParseHex("4795C22501BF534BC478FF619407A7EC9E8D88" + + "83646D69BD43A0728944EA802F") + combineSigKey2 = mustParseHex("0F5BE837F3AB7E7FEFF1FAA44D673C2017206A" + + "E836D2C7893CDE4ACB7D55EDEB") + combineSigKey3 = mustParseHex("0FD453223E444FCA91FB5310990AE8A0C5DAA1" + + "4D2A4C8944E1C0BC80C30DF682") + + combineSigKeys = [][]byte{combineSigKey0, combineSigKey1, + combineSigKey2, combineSigKey3} + + combineSigAggNonce0 = mustParsePubNonce("024FA51009A56F0D6DF737131CE1" + + "FBBD833797AF3B4FE6BF0D68F4D49F68B0947E0248FB3BB9191F0CFF1380" + + "6A3A2F1429C23012654FCE4E41F7EC9169EAA6056B21") + combineSigAggNonce1 = mustParsePubNonce("023B11E63E2460E5E0F1561BB700" + + "FEA95B991DD9CA2CBBE92A3960641FA7469F6702CA4CD38375FE8BEB857C" + + "770807225BFC7D712F42BA896B83FC71138E56409B21") + combineSigAggNonce2 = mustParsePubNonce("03F98BEAA32B8A38FE3797C4E813" + + "DC9CE05ADBE32200035FB37EB0A030B735E9B6030E6118EC98EA2BA7A358" + + "C2E38E7E13E63681EEB683E067061BF7D52DCF08E615") + combineSigAggNonce3 = mustParsePubNonce("026491FBCFD47148043A0F7310E6" + + "2EF898C10F2D0376EE6B232EAAD36F3C2E29E303020CB17D168908E2904D" + + "E2EB571CD232CA805A6981D0F86CDBBD2F12BD91F6D0") + + psig0 = mustParseHex("E5C1CBD6E7E89FE9EE30D5F3B6D06B9C218846E4A1DEF4E" + + "E851410D51ABBD850") + psig1 = mustParseHex("9BC470F7F1C9BC848BDF179B0023282FFEF40908E0EF884" + + "59784A4355FC86D0C") + psig2 = mustParseHex("D5D8A09929BA264B2F5DF15ACA1CF2DEFA47C048DF0C323" + + "2E965FFE2F2831B1D") + psig3 = mustParseHex("A915197503C1051EA77DC91F01C3A0E60BFD64473BD536C" + + "B613F9645BD61C843") + psig4 = mustParseHex("99A144D7076A128022134E036B8BDF33811F7EAED9A1E48" + + "549B46D8A63D64DC9") + psig5 = mustParseHex("716A72A0C1E531EBB4555C8E29FD35C796F4F231C3B0391" + + "93D7E8D7AEFBDF5F7") + psig6 = mustParseHex("06B6DD04BC0F1EF740916730AD7DAC794255B1612217197" + + "65BDE9686A26633DC") + psig7 = mustParseHex("BF6D85D4930062726EBC6EBB184AFD68DBB3FED159C5019" + + "89690A62600D6FBAB") + + combineSigExpected0 = mustParseHex("4006D4D069F3B51E968762FF8074153E2" + + "78E5BCD221AABE0743CA001B77E79F581863CCED9B25C6E7A0FED8EB6F39" + + "3CD65CD7306D385DCF85CC6567DAA4E041B") + combineSigExpected1 = mustParseHex("98BCD40DFD94B47A3DA37D7B78EB6CCE8" + + "ABEACA23C3ADE6F4678902410EB35C67EEDBA0E2D7B2B69D6DBBA79CBE09" + + "3C64B9647A96B98C8C28AD3379BDFAEA21F") + combineSigExpected2 = mustParseHex("3741FEDCCDD7508B58DCB9A780FF5D974" + + "52EC8C0448D8C97004EA7175C14F2007A54D1DE356EBA6719278436EF111" + + "DFA8F1B832368371B9B7A25001709039679") + combineSigExpected3 = mustParseHex("F4B3DA3CF0D0F7CF5C1840593BF1A1A41" + + "5DA341619AE848F2210696DC8C7512540962C84EF7F0CEC491065F2D5772" + + "13CF10E8A63D153297361B3B172BE27B61F") + + combineSigTweak0 = mustParseHex32("B511DA492182A91B0FFB9A98020D55F260" + + "AE86D7ECBD0399C7383D59A5F2AF7C") + combineSigTweak1 = mustParseHex32("A815FE049EE3C5AAB66310477FBC8BCCCA" + + "C2F3395F59F921C364ACD78A2F48DC") + combineSigTweak2 = mustParseHex32("75448A87274B056468B977BE06EB1E9F65" + + "7577B7320B0A3376EA51FD420D18A8") + tweak0False = KeyTweakDesc{ + Tweak: combineSigTweak0, + IsXOnly: false, + } + tweak0True = KeyTweakDesc{ + Tweak: combineSigTweak0, + IsXOnly: true, + } + tweak1False = KeyTweakDesc{ + Tweak: combineSigTweak1, + IsXOnly: false, + } + tweak2True = KeyTweakDesc{ + Tweak: combineSigTweak2, + IsXOnly: true, + } + combineSigsMsg = mustParseHex32("599C67EA410D005B9DA90817CF03ED3B1C86" + + "8E4DA4EDF00A5880B0082C237869") +) + +func TestMusig2CombineSigsTestVectors(t *testing.T) { + + testCases := []struct { + partialSigs [][]byte + aggNonce [66]byte + keyOrder []int + expected []byte + tweaks []KeyTweakDesc + expectedError error + }{ + // Vector 1 + { + partialSigs: [][]byte{psig0, psig1}, + aggNonce: combineSigAggNonce0, + keyOrder: []int{0, 1}, + expected: combineSigExpected0, + }, + // Vector 2 + { + partialSigs: [][]byte{psig2, psig3}, + aggNonce: combineSigAggNonce1, + keyOrder: []int{0, 2}, + expected: combineSigExpected1, + }, + // Vector 3 + { + partialSigs: [][]byte{psig4, psig5}, + aggNonce: combineSigAggNonce2, + keyOrder: []int{0, 2}, + expected: combineSigExpected2, + tweaks: []KeyTweakDesc{tweak0False}, + }, + // Vector 4 + { + partialSigs: [][]byte{psig6, psig7}, + aggNonce: combineSigAggNonce3, + keyOrder: []int{0, 3}, + expected: combineSigExpected3, + tweaks: []KeyTweakDesc{ + tweak0True, + tweak1False, + tweak2True, + }, + }, + // Vector 5: Partial signature is invalid because it exceeds group size + { + partialSigs: [][]byte{ + psig7, + mustParseHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + + "EBAAEDCE6AF48A03BBFD25E8CD0364141"), + }, + aggNonce: combineSigAggNonce3, + expectedError: ErrPartialSigInvalid, + }, + } + + for _, testCase := range testCases { + var pSigs []*PartialSignature + for _, partialSig := range testCase.partialSigs { + pSig := &PartialSignature{} + err := pSig.Decode(bytes.NewReader(partialSig)) + + switch { + case testCase.expectedError != nil && + errors.Is(err, testCase.expectedError): + + return + case err != nil: + t.Fatal(err) + } + + pSigs = append(pSigs, pSig) + } + + keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) + for _, keyIndex := range testCase.keyOrder { + keyBytes := combineSigKeys[keyIndex] + pub, err := schnorr.ParsePubKey(keyBytes) + if err != nil { + t.Fatalf("unable to parse pubkeys: %v", err) + } + keySet = append(keySet, pub) + } + + uniqueKeyIndex := secondUniqueKeyIndex(keySet, false) + aggOpts := []KeyAggOption{ + WithUniqueKeyIndex(uniqueKeyIndex), + } + if len(testCase.tweaks) > 0 { + aggOpts = append(aggOpts, WithKeyTweaks(testCase.tweaks...)) + } + + combinedKey, _, _, err := AggregateKeys( + keySet, false, aggOpts..., + ) + if err != nil { + t.Fatal(err) + } + + aggPubkey, err := aggNonceToPubkey( + testCase.aggNonce, combinedKey, combineSigsMsg, + ) + if err != nil { + t.Fatal(err) + } + + var opts []CombineOption + if len(testCase.tweaks) > 0 { + opts = append(opts, WithTweakedCombine( + combineSigsMsg, keySet, testCase.tweaks, false, + )) + } + + sig := CombineSigs(aggPubkey, pSigs, opts...) + expectedSig, err := schnorr.ParseSignature(testCase.expected) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(sig.Serialize(), expectedSig.Serialize()) { + t.Fatalf("sigs not expected %x \n got %x", expectedSig.Serialize(), sig.Serialize()) + } + + if !sig.Verify(combineSigsMsg[:], combinedKey.FinalKey) { + t.Fatal("sig not valid for m") + } + } +} + +// aggNonceToPubkey gets a nonce as a public key for the TestMusig2CombineSigsTestVectors +// test. +// TODO(sputn1ck): build into intermediate routine. +func aggNonceToPubkey(combinedNonce [66]byte, combinedKey *AggregateKey, + msg [32]byte) (*btcec.PublicKey, error) { + + // b = int_from_bytes(tagged_hash('MuSig/noncecoef', aggnonce + bytes_from_point(Q) + msg)) % n + var ( + nonceMsgBuf bytes.Buffer + nonceBlinder btcec.ModNScalar + ) + nonceMsgBuf.Write(combinedNonce[:]) + nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey.FinalKey)) + nonceMsgBuf.Write(msg[:]) + nonceBlindHash := chainhash.TaggedHash(NonceBlindTag, nonceMsgBuf.Bytes()) + nonceBlinder.SetByteSlice(nonceBlindHash[:]) + + r1, err := btcec.ParsePubKey( + combinedNonce[:btcec.PubKeyBytesLenCompressed], + ) + if err != nil { + return nil, err + } + + r2, err := btcec.ParsePubKey( + combinedNonce[btcec.PubKeyBytesLenCompressed:], + ) + if err != nil { + return nil, err + } + + var nonce, r1J, r2J btcec.JacobianPoint + r1.AsJacobian(&r1J) + r2.AsJacobian(&r2J) + + // With our nonce blinding value, we'll now combine both the public + // nonces, using the blinding factor to tweak the second nonce: + // * R = R_1 + b*R_2 + btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) + btcec.AddNonConst(&r1J, &r2J, &nonce) + + nonce.ToAffine() + + return btcec.NewPublicKey( + &nonce.X, &nonce.Y, + ), nil + +} + func memsetLoop(a []byte, v uint8) { for i := range a { a[i] = byte(v) @@ -1568,6 +1829,18 @@ func getNegGBytes() []byte { return pk } +func mustParseHex32(str string) [32]byte { + b, err := hex.DecodeString(str) + if err != nil { + panic(fmt.Errorf("unable to parse hex: %v", err)) + } + if len(b) != 32 { + panic(fmt.Errorf("not a 32 byte slice: %v", err)) + } + + return to32ByteSlice(b) +} + func mustParsePubNonce(str string) [PubNonceSize]byte { b, err := hex.DecodeString(str) if err != nil { From 44eb8c64f8d0f0e3a84400e7f93b9eb16ea08873 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Wed, 29 Jun 2022 18:48:02 +0200 Subject: [PATCH 0715/1056] btcec/schnorr/musig2: Allow infinity nonces This commit updates the musig2 module to allow infinity nonces, as per Musig2 0.4.0. --- btcec/curve.go | 52 ++++++++++++++++++ btcec/error.go | 5 ++ btcec/schnorr/musig2/musig2_test.go | 6 ++- btcec/schnorr/musig2/nonces.go | 36 +++---------- btcec/schnorr/musig2/sign.go | 84 +++++++++++++++-------------- 5 files changed, 113 insertions(+), 70 deletions(-) diff --git a/btcec/curve.go b/btcec/curve.go index 5224e35c8e..70a9229f9a 100644 --- a/btcec/curve.go +++ b/btcec/curve.go @@ -4,6 +4,8 @@ package btcec import ( + "fmt" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) @@ -11,6 +13,9 @@ import ( // Jacobian projective coordinates and thus represents a point on the curve. type JacobianPoint = secp.JacobianPoint +// infinityPoint is the jacobian representation of the point at infinity. +var infinityPoint JacobianPoint + // MakeJacobianPoint returns a Jacobian point with the provided X, Y, and Z // coordinates. func MakeJacobianPoint(x, y, z *FieldVal) JacobianPoint { @@ -61,3 +66,50 @@ func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) { func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint) { secp.ScalarMultNonConst(k, point, result) } + +// ParseJacobian parses a byte slice point as a secp.Publickey and returns the +// pubkey as a JacobianPoint. If the nonce is a zero slice, the infinityPoint +// is returned. +func ParseJacobian(point []byte) (JacobianPoint, error) { + var result JacobianPoint + + if len(point) != 33 { + str := fmt.Sprintf("invalid nonce: invalid length: %v", + len(point)) + return JacobianPoint{}, makeError(secp.ErrPubKeyInvalidLen, str) + } + + if point[0] == 0x00 { + return infinityPoint, nil + } + + noncePk, err := secp.ParsePubKey(point) + if err != nil { + return JacobianPoint{}, err + } + noncePk.AsJacobian(&result) + + return result, nil +} + +// JacobianToByteSlice converts the passed JacobianPoint to a Pubkey +// and serializes that to a byte slice. If the JacobianPoint is the infinity +// point, a zero slice is returned. +func JacobianToByteSlice(point JacobianPoint) []byte { + if point.X == infinityPoint.X && point.Y == infinityPoint.Y { + return make([]byte, 33) + } + + point.ToAffine() + + return NewPublicKey( + &point.X, &point.Y, + ).SerializeCompressed() +} + +// GeneratorJacobian sets the passed JacobianPoint to the Generator Point. +func GeneratorJacobian(jacobian *JacobianPoint) { + var k ModNScalar + k.SetInt(1) + ScalarBaseMultNonConst(&k, jacobian) +} diff --git a/btcec/error.go b/btcec/error.go index 81ca2b044d..df6ec678a8 100644 --- a/btcec/error.go +++ b/btcec/error.go @@ -17,3 +17,8 @@ type Error = secp.Error // errors.As, so the caller can directly check against an error kind when // determining the reason for an error. type ErrorKind = secp.ErrorKind + +// makeError creates an secp.Error given a set of arguments. +func makeError(kind ErrorKind, desc string) Error { + return Error{Err: kind, Description: desc} +} diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 1ff59a2ffa..f7f84be3d9 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -1461,7 +1461,7 @@ func TestMusig2AggregateNoncesTestVectors(t *testing.T) { }, expectedNonce: append( append([]byte{}, expectedNonce[0:33]...), - getGBytes()..., + getInfinityBytes()..., ), }, } @@ -1829,6 +1829,10 @@ func getNegGBytes() []byte { return pk } +func getInfinityBytes() []byte { + return make([]byte, 33) +} + func mustParseHex32(str string) [32]byte { b, err := hex.DecodeString(str) if err != nil { diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 0ba100229a..66d2cb9c22 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -331,7 +331,7 @@ func AggregateNonces(pubNonces [][PubNonceSize]byte) ([PubNonceSize]byte, error) // function to extra 33 bytes at a time from the packed 2x public // nonces. type nonceSlicer func([PubNonceSize]byte) []byte - combineNonces := func(slicer nonceSlicer) (*btcec.PublicKey, error) { + combineNonces := func(slicer nonceSlicer) (btcec.JacobianPoint, error) { // Convert the set of nonces into jacobian coordinates we can // use to accumulate them all into each other. pubNonceJs := make([]*btcec.JacobianPoint, len(pubNonces)) @@ -339,14 +339,12 @@ func AggregateNonces(pubNonces [][PubNonceSize]byte) ([PubNonceSize]byte, error) // Using the slicer, extract just the bytes we need to // decode. var nonceJ btcec.JacobianPoint - pubNonce, err := btcec.ParsePubKey( - slicer(pubNonceBytes), - ) + + nonceJ, err := btcec.ParseJacobian(slicer(pubNonceBytes)) if err != nil { - return nil, err + return btcec.JacobianPoint{}, err } - pubNonce.AsJacobian(&nonceJ) pubNonceJs[i] = &nonceJ } @@ -359,27 +357,8 @@ func AggregateNonces(pubNonces [][PubNonceSize]byte) ([PubNonceSize]byte, error) ) } - // Now that we've aggregated all the points, we need to check - // if this point is the point at infinity, if so, then we'll - // just return the generator. At a later step, the malicious - // party will be detected. - if aggregateNonce == infinityPoint { - // TODO(roasbeef): better way to get the generator w/ - // the new API? -- via old curve params instead? - var generator btcec.JacobianPoint - one := new(btcec.ModNScalar).SetInt(1) - btcec.ScalarBaseMultNonConst(one, &generator) - - generator.ToAffine() - return btcec.NewPublicKey( - &generator.X, &generator.Y, - ), nil - } - aggregateNonce.ToAffine() - return btcec.NewPublicKey( - &aggregateNonce.X, &aggregateNonce.Y, - ), nil + return aggregateNonce, nil } // The final nonce public nonce is actually two nonces, one that @@ -392,6 +371,7 @@ func AggregateNonces(pubNonces [][PubNonceSize]byte) ([PubNonceSize]byte, error) if err != nil { return finalNonce, err } + combinedNonce2, err := combineNonces(func(n [PubNonceSize]byte) []byte { return n[btcec.PubKeyBytesLenCompressed:] }) @@ -399,10 +379,10 @@ func AggregateNonces(pubNonces [][PubNonceSize]byte) ([PubNonceSize]byte, error) return finalNonce, err } - copy(finalNonce[:], combinedNonce1.SerializeCompressed()) + copy(finalNonce[:], btcec.JacobianToByteSlice(combinedNonce1)) copy( finalNonce[btcec.PubKeyBytesLenCompressed:], - combinedNonce2.SerializeCompressed(), + btcec.JacobianToByteSlice(combinedNonce2), ) return finalNonce, nil diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 0529c53c9a..fce61aa8a8 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -200,20 +200,6 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, option(opts) } - // Next, we'll parse the public nonces into R1 and R2. - r1, err := btcec.ParsePubKey( - combinedNonce[:btcec.PubKeyBytesLenCompressed], - ) - if err != nil { - return nil, err - } - r2, err := btcec.ParsePubKey( - combinedNonce[btcec.PubKeyBytesLenCompressed:], - ) - if err != nil { - return nil, err - } - // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of signing. keysHash := keyHashFingerprint(pubKeys, opts.sortKeys) @@ -259,19 +245,31 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, ) nonceBlinder.SetByteSlice(nonceBlindHash[:]) - var nonce, r1J, r2J btcec.JacobianPoint - r1.AsJacobian(&r1J) - r2.AsJacobian(&r2J) + // Next, we'll parse the public nonces into R1 and R2. + r1J, err := btcec.ParseJacobian( + combinedNonce[:btcec.PubKeyBytesLenCompressed], + ) + if err != nil { + return nil, err + } + r2J, err := btcec.ParseJacobian( + combinedNonce[btcec.PubKeyBytesLenCompressed:], + ) + if err != nil { + return nil, err + } // With our nonce blinding value, we'll now combine both the public // nonces, using the blinding factor to tweak the second nonce: // * R = R_1 + b*R_2 + var nonce btcec.JacobianPoint btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) btcec.AddNonConst(&r1J, &r2J, &nonce) // If the combined nonce it eh point at infinity, then we'll bail out. if nonce == infinityPoint { - return nil, ErrNoncePointAtInfinity + G := btcec.Generator() + G.AsJacobian(&nonce) } // Next we'll parse out our two secret nonces, which we'll be using in @@ -375,6 +373,7 @@ func (p *PartialSignature) Verify(pubNonce [PubNonceSize]byte, signingKey *btcec.PublicKey, msg [32]byte, signOpts ...SignOption) bool { pubKey := schnorr.SerializePubKey(signingKey) + return verifyPartialSig( p, pubNonce, combinedNonce, keySet, pubKey, msg, signOpts..., ) == nil @@ -399,19 +398,6 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // Next we'll parse out the two public nonces into something we can // use. // - // TODO(roasbeef): consolidate, new method - r1, err := btcec.ParsePubKey( - combinedNonce[:btcec.PubKeyBytesLenCompressed], - ) - if err != nil { - return err - } - r2, err := btcec.ParsePubKey( - combinedNonce[btcec.PubKeyBytesLenCompressed:], - ) - if err != nil { - return err - } // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of verification. @@ -456,45 +442,61 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, nonceBlindHash := chainhash.TaggedHash(NonceBlindTag, nonceMsgBuf.Bytes()) nonceBlinder.SetByteSlice(nonceBlindHash[:]) - var nonce, r1J, r2J btcec.JacobianPoint - r1.AsJacobian(&r1J) - r2.AsJacobian(&r2J) + r1J, err := btcec.ParseJacobian( + combinedNonce[:btcec.PubKeyBytesLenCompressed], + ) + if err != nil { + return err + } + r2J, err := btcec.ParseJacobian( + combinedNonce[btcec.PubKeyBytesLenCompressed:], + ) + if err != nil { + return err + } // With our nonce blinding value, we'll now combine both the public // nonces, using the blinding factor to tweak the second nonce: // * R = R_1 + b*R_2 + + var nonce btcec.JacobianPoint btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) btcec.AddNonConst(&r1J, &r2J, &nonce) // Next, we'll parse out the set of public nonces this signer used to // generate the signature. - pubNonce1, err := btcec.ParsePubKey( + pubNonce1J, err := btcec.ParseJacobian( pubNonce[:btcec.PubKeyBytesLenCompressed], ) if err != nil { return err } - pubNonce2, err := btcec.ParsePubKey( + pubNonce2J, err := btcec.ParseJacobian( pubNonce[btcec.PubKeyBytesLenCompressed:], ) if err != nil { return err } + // If the nonce is the infinity point we set it to the Generator. + if nonce == infinityPoint { + btcec.GeneratorJacobian(&nonce) + } else { + nonce.ToAffine() + } + // We'll perform a similar aggregation and blinding operator as we did // above for the combined nonces: R' = R_1' + b*R_2'. - var pubNonceJ, pubNonce1J, pubNonce2J btcec.JacobianPoint - pubNonce1.AsJacobian(&pubNonce1J) - pubNonce2.AsJacobian(&pubNonce2J) + var pubNonceJ btcec.JacobianPoint + btcec.ScalarMultNonConst(&nonceBlinder, &pubNonce2J, &pubNonce2J) btcec.AddNonConst(&pubNonce1J, &pubNonce2J, &pubNonceJ) - nonce.ToAffine() + pubNonceJ.ToAffine() // If the combined nonce used in the challenge hash has an odd y // coordinate, then we'll negate our final public nonce. if nonce.Y.IsOdd() { - pubNonceJ.ToAffine() pubNonceJ.Y.Negate(1) pubNonceJ.Y.Normalize() } From 06ce9608aa3bd2de895b5c12e545e9e0f2935c42 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Wed, 29 Jun 2022 18:52:32 +0200 Subject: [PATCH 0716/1056] btcec/schnorr/musig2: add infinity testvectors This commit adds the testvectors from https://github.com/jonasnick/bips/commit/20ba03106d245d42375e65f739c58dd9074daf6e --- btcec/schnorr/musig2/musig2_test.go | 48 ++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index f7f84be3d9..e58a6d4328 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -316,6 +316,9 @@ var ( signExpected3 = mustParseHex("0D5B651E6DE34A29A12DE7A8B4183B4AE6A7F7F" + "BE15CDCAFA4A3D1BCAABC7517") + signExpected4 = mustParseHex("8D5E0407FB4756EEBCD86264C32D792EE36EEB6" + + "9E952BBB30B8E41BEBC4D22FA") + signSetKeys = [][]byte{signSetPubKey, signSetKey2, signSetKey3, invalidPk1} aggregatedNonce = toPubNonceSlice(mustParseHex("028465FCF0BBDBCF443AA" + @@ -330,6 +333,9 @@ var ( verifyPnonce3 = mustParsePubNonce("032DE2662628C90B03F5E720284EB52FF7" + "D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1C" + "A6BEB2090C93D930321071AD40B2F44E599046") + verifyPnonce4 = mustParsePubNonce("0237C87821AFD50A8644D820A8F3E02E49" + + "9C931865C2360FB43D0A0D20DAFE07EA0387BF891D2A6DEAEBADC909352A" + + "A9405D1428C15F4B75F04DAE642A95C2548480") tweak1 = KeyTweakDesc{ Tweak: [32]byte{ @@ -449,15 +455,21 @@ func TestMuSig2SigningTestVectors(t *testing.T) { aggNonce: aggregatedNonce, expectedPartialSig: signExpected3, }, + // Vector 4 Both halves of aggregate nonce correspond to point at infinity + { + keyOrder: []int{0, 1}, + aggNonce: mustNonceAgg([][66]byte{verifyPnonce1, verifyPnonce4}), + expectedPartialSig: signExpected4, + }, - // Vector 4: Signer 2 provided an invalid public key + // Vector 5: Signer 2 provided an invalid public key { keyOrder: []int{1, 0, 3}, aggNonce: aggregatedNonce, expectedError: secp256k1.ErrPubKeyNotOnCurve, }, - // Vector 5: Aggregate nonce is invalid due wrong tag, 0x04, + // Vector 6: Aggregate nonce is invalid due wrong tag, 0x04, // in the first half. { @@ -470,7 +482,7 @@ func TestMuSig2SigningTestVectors(t *testing.T) { expectedError: secp256k1.ErrPubKeyInvalidFormat, }, - // Vector 6: Aggregate nonce is invalid because the second half + // Vector 7: Aggregate nonce is invalid because the second half // does not correspond to an X coordinate. { @@ -483,7 +495,7 @@ func TestMuSig2SigningTestVectors(t *testing.T) { expectedError: secp256k1.ErrPubKeyNotOnCurve, }, - // Vector 7: Aggregate nonce is invalid because the second half + // Vector 8: Aggregate nonce is invalid because the second half // exceeds field size. { @@ -725,7 +737,7 @@ func TestMusig2PartialSigVerifyTestVectors(t *testing.T) { genTweakParity(tweak4, false), }, }, - // Vector 8. + // Vector 9. { partialSig: signExpected1, @@ -737,7 +749,7 @@ func TestMusig2PartialSigVerifyTestVectors(t *testing.T) { verifyPnonce3, }, }, - // Vector 9. + // Vector 10. { partialSig: signExpected2, @@ -749,7 +761,7 @@ func TestMusig2PartialSigVerifyTestVectors(t *testing.T) { verifyPnonce3, }, }, - // Vector 10. + // Vector 11. { partialSig: signExpected3, @@ -761,7 +773,19 @@ func TestMusig2PartialSigVerifyTestVectors(t *testing.T) { verifyPnonce1, }, }, - // Vector 11: Wrong signature (which is equal to the negation + // Vector 12: Both halves of aggregate nonce correspond to + // point at infinity. + { + + partialSig: signExpected4, + pubnonceIndex: 0, + keyOrder: []int{0, 1}, + nonces: [][66]byte{ + verifyPnonce1, + verifyPnonce4, + }, + }, + // Vector 13: Wrong signature (which is equal to the negation // of valid signature expected[0]). { @@ -1796,6 +1820,14 @@ func aggNonceToPubkey(combinedNonce [66]byte, combinedKey *AggregateKey, } +func mustNonceAgg(nonces [][66]byte) [66]byte { + aggNonce, err := AggregateNonces(nonces) + if err != nil { + panic("can't aggregate nonces") + } + return aggNonce +} + func memsetLoop(a []byte, v uint8) { for i := range a { a[i] = byte(v) From 571f9c69ec6023e57064aa72e53666b09b402b5d Mon Sep 17 00:00:00 2001 From: George Tsagkarelis Date: Tue, 16 Aug 2022 13:33:58 +0300 Subject: [PATCH 0717/1056] wire: add string parser to outpoint --- wire/msgtx.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/wire/msgtx.go b/wire/msgtx.go index 917a142e6e..9c79554fa4 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -6,9 +6,11 @@ package wire import ( "bytes" + "errors" "fmt" "io" "strconv" + "strings" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -215,6 +217,29 @@ func NewOutPoint(hash *chainhash.Hash, index uint32) *OutPoint { } } +// NewOutPointFromString returns a new bitcoin transaction outpoint parsed from +// the provided string, which should be in the format "hash:index". +func NewOutPointFromString(outpoint string) (*OutPoint, error) { + parts := strings.Split(outpoint, ":") + if len(parts) != 2 { + return nil, errors.New("outpoint should be of the form txid:index") + } + hash, err := chainhash.NewHashFromStr(parts[0]) + if err != nil { + return nil, err + } + + outputIndex, err := strconv.ParseUint(parts[1], 10, 32) + if err != nil { + return nil, fmt.Errorf("invalid output index: %v", err) + } + + return &OutPoint{ + Hash: *hash, + Index: uint32(outputIndex), + }, nil +} + // String returns the OutPoint in the human-readable form "hash:index". func (o OutPoint) String() string { // Allocate enough for hash string, colon, and 10 digits. Although From d827d0240ad199432d021dba361d34f1dbb4e96b Mon Sep 17 00:00:00 2001 From: George Tsagkarelis Date: Tue, 16 Aug 2022 16:58:48 +0300 Subject: [PATCH 0718/1056] wire: add outpoint string parser unit tests --- wire/msgtx_test.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/wire/msgtx_test.go b/wire/msgtx_test.go index 66965043e6..5ec753b62d 100644 --- a/wire/msgtx_test.go +++ b/wire/msgtx_test.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/davecgh/go-spew/spew" + "github.com/stretchr/testify/require" ) // TestTx tests the MsgTx API. @@ -778,6 +779,76 @@ func TestTxWitnessSize(t *testing.T) { } } +// TestTxOutPointFromString performs tests to ensure that the outpoint string +// parser works as expected. +func TestTxOutPointFromString(t *testing.T) { + hashFromStr := func(hash string) chainhash.Hash { + h, _ := chainhash.NewHashFromStr(hash) + return *h + } + + tests := []struct { + name string + input string + result *OutPoint + err bool + }{ + { + name: "normal outpoint 1", + input: "2ebd15a7e758d5f4c7c74181b99e5b8586f88e0682dc13e09d92612a2b2bb0a2:1", + result: &OutPoint{ + Hash: hashFromStr("2ebd15a7e758d5f4c7c74181b99e5b8586f88e0682dc13e09d92612a2b2bb0a2"), + Index: 1, + }, + err: false, + }, + { + name: "normal outpoint 2", + input: "94c7762a68ff164352bd31fd95fa875204e811c09acef40ba781787eb28e3b55:42", + result: &OutPoint{ + Hash: hashFromStr("94c7762a68ff164352bd31fd95fa875204e811c09acef40ba781787eb28e3b55"), + Index: 42, + }, + err: false, + }, + { + name: "big index outpoint", + input: "94c7762a68ff164352bd31fd95fa875204e811c09acef40ba781787eb28e3b55:2147484242", + result: &OutPoint{ + Hash: hashFromStr("94c7762a68ff164352bd31fd95fa875204e811c09acef40ba781787eb28e3b55"), + Index: 2147484242, + }, + err: false, + }, + { + name: "bad string", + input: "not_outpoint_not_outpoint_not_outpoint", + result: nil, + err: true, + }, + { + name: "empty string", + input: "", + result: nil, + err: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + outpoint, err := NewOutPointFromString(test.input) + + isErr := (err != nil) + require.Equal(t, isErr, test.err) + + if !isErr { + require.Equal(t, test.result, outpoint) + } + }) + + } +} + // multiTx is a MsgTx with an input and output and used in various tests. var multiTx = &MsgTx{ Version: 1, From ef4a8d310b18953718fc99fc536aa39ecf4d8ab7 Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Wed, 7 Sep 2022 16:09:46 -0300 Subject: [PATCH 0719/1056] doc: fix Tor hidden service setup link --- docs/configuring_tor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuring_tor.md b/docs/configuring_tor.md index ecb03bfc32..3225b9b541 100644 --- a/docs/configuring_tor.md +++ b/docs/configuring_tor.md @@ -49,7 +49,7 @@ proxy=127.0.0.1:9050 The first step is to configure Tor to provide a hidden service. Documentation for this can be found on the Tor project website -[here](https://www.torproject.org/docs/tor-hidden-service.html.en). However, +[here](https://community.torproject.org/onion-services/setup/). However, there is no need to install a web server locally as the linked instructions discuss since btcd will act as the server. From 38ee9a41c8f8aa24a079a28f5e8a86faecffdfe1 Mon Sep 17 00:00:00 2001 From: Tochi Obudulu Date: Sat, 3 Sep 2022 13:54:18 +0100 Subject: [PATCH 0720/1056] build: bump golang base image version to 1.17 Image fails to build on 1.16 --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index ec45ee64c3..58e4b59aec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,9 +19,9 @@ ARG ARCH=amd64 # https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests # https://cloud.google.com/architecture/using-container-images # https://github.com/google/go-containerregistry/blob/main/cmd/crane/README.md -# ➜ ~ crane digest golang:1.16-alpine3.12 -# sha256:db2475a1dbb2149508e5db31d7d77a75e6600d54be645f37681f03f2762169ba -FROM golang@sha256:db2475a1dbb2149508e5db31d7d77a75e6600d54be645f37681f03f2762169ba AS build-container +# ➜ ~ crane digest golang:1.17.13-alpine3.16 +# sha256:c80567372be0d486766593cc722d3401038e2f150a0f6c5c719caa63afb4026a +FROM golang@sha256:c80567372be0d486766593cc722d3401038e2f150a0f6c5c719caa63afb4026a AS build-container ARG ARCH ENV GO111MODULE=on From f523d4ccaa5f34a2f761f16a05f5d6e6665b1168 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 9 Oct 2022 17:03:31 -0700 Subject: [PATCH 0721/1056] wire: remove erroneous witness size check in wire parsing In this commit, we fix a bug that would cause nodes to be unable to parse a given block from the wire. The block would be properly accepted if fed in via other mechanisms. The issue here is that the old checks for the maximum witness size, circa segwit v0 where placed in the wire package _as well_ as the tx engine. This check should only be in the engine, since it's properly gated by other related scrip validation flags. The fix itself is simple: limit witnesses only based on the maximum block size in bytes, or ~4MB. --- blockchain/weight.go | 2 +- wire/msgtx.go | 30 ++++++++++++++++-------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/blockchain/weight.go b/blockchain/weight.go index 5a6f257be5..1b691f0086 100644 --- a/blockchain/weight.go +++ b/blockchain/weight.go @@ -7,9 +7,9 @@ package blockchain import ( "fmt" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/wire/msgtx.go b/wire/msgtx.go index 917a142e6e..c289cd7e0b 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -103,10 +103,9 @@ const ( maxWitnessItemsPerInput = 500000 // maxWitnessItemSize is the maximum allowed size for an item within - // an input's witness data. This number is derived from the fact that - // for script validation, each pushed item onto the stack must be less - // than 10k bytes. - maxWitnessItemSize = 11000 + // an input's witness data. This value is bounded by the largest + // possible block size, post segwit v1 (taproot). + maxWitnessItemSize = 4_000_000 ) // TxFlagMarker is the first byte of the FLAG field in a bitcoin tx @@ -114,16 +113,18 @@ const ( // transaction from one that would require a different parsing logic. // // Position of FLAG in a bitcoin tx message: -// ┌─────────┬────────────────────┬─────────────┬─────┐ -// │ VERSION │ FLAG │ TX-IN-COUNT │ ... │ -// │ 4 bytes │ 2 bytes (optional) │ varint │ │ -// └─────────┴────────────────────┴─────────────┴─────┘ +// +// ┌─────────┬────────────────────┬─────────────┬─────┐ +// │ VERSION │ FLAG │ TX-IN-COUNT │ ... │ +// │ 4 bytes │ 2 bytes (optional) │ varint │ │ +// └─────────┴────────────────────┴─────────────┴─────┘ // // Zooming into the FLAG field: -// ┌── FLAG ─────────────┬────────┐ -// │ TxFlagMarker (0x00) │ TxFlag │ -// │ 1 byte │ 1 byte │ -// └─────────────────────┴────────┘ +// +// ┌── FLAG ─────────────┬────────┐ +// │ TxFlagMarker (0x00) │ TxFlag │ +// │ 1 byte │ 1 byte │ +// └─────────────────────┴────────┘ const TxFlagMarker = 0x00 // TxFlag is the second byte of the FLAG field in a bitcoin tx message. @@ -586,8 +587,9 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error // item itself. txin.Witness = make([][]byte, witCount) for j := uint64(0); j < witCount; j++ { - txin.Witness[j], err = readScript(r, pver, - maxWitnessItemSize, "script witness item") + txin.Witness[j], err = readScript( + r, pver, maxWitnessItemSize, "script witness item", + ) if err != nil { returnScriptBuffers() return err From 1a4af39ab02a1a4fb1f2a01e12fafccea82aa442 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sun, 9 Oct 2022 18:22:27 -0700 Subject: [PATCH 0722/1056] build: bump version to v0.23.2 This includes the recent fix to the wire witness wire parsing bug. --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 49a2cd68de..7d321c5fdd 100644 --- a/version.go +++ b/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 23 - appPatch uint = 1 + appPatch uint = 2 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. From e563459b72df634ca5731ac6c93e9ffbfd36dd93 Mon Sep 17 00:00:00 2001 From: David Vennik Date: Sun, 18 Sep 2022 20:31:58 +0200 Subject: [PATCH 0723/1056] Fixed ban bug that doesn't print numTxns (cherry picked from commit 11c8d11a26d14a64fe6e412313624b6bfc5b4e2c) --- server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.go b/server.go index 5cef434292..5ef2e31942 100644 --- a/server.go +++ b/server.go @@ -1440,7 +1440,7 @@ func (sp *serverPeer) OnNotFound(p *peer.Peer, msg *wire.MsgNotFound) { } if numTxns > 0 { txStr := pickNoun(uint64(numTxns), "transaction", "transactions") - reason := fmt.Sprintf("%d %v not found", numBlocks, txStr) + reason := fmt.Sprintf("%d %v not found", numTxns, txStr) if sp.addBanScore(0, 10*numTxns, reason) { return } From a34e7779163e159a41774e26778a2abf788620c0 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 5 Oct 2022 20:05:29 -0700 Subject: [PATCH 0724/1056] btcec/schnorr/musig2: update musig2 impl to version 0.7.0 The two _concrete_ changes between version 0.4.0 (where we are before this commit), and version 0.7.0 are: 1. Variable length messages are now allowed, this comes with a new 8 byte prefix for the messages. * Our implementation was already using a `[]byte` for the message/hash, so no extra API changes are needed here. 2. The serialization for a blank message and a normal message (for nonce gen) is now distinct. A single byte is added (either 0 or 1) to indicate if a message was passed into nonce generation. --- btcec/schnorr/musig2/musig2_test.go | 6 ++--- btcec/schnorr/musig2/nonces.go | 40 ++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index e58a6d4328..94bb0ec16b 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -1367,9 +1367,9 @@ func TestMusig2NonceGenTestVectors(t *testing.T) { auxInput: extra_in[:], msg: msg[:], }, - expectedNonce: "E8F2E103D86800F19A4E97338D371CB885DB2" + - "F19D08C0BD205BBA9B906C971D0D786A17718AAFAD6D" + - "E025DDDD99DC823E2DFC1AE1DDFE920888AD53FFF423FC4", + expectedNonce: "BC6C683EBBCC39DCB3C29B3D010D2AAA7C86C" + + "FB562FC41ED9A460EE061013E75FB4AD2F0B81671326" + + "9800D018803906D5481E00A940EAB4F4AC49B4A372EB0F4", }, { opts: nonceGenOpts{ diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 66d2cb9c22..3866dc5438 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -191,6 +191,8 @@ func withCustomOptions(customOpts nonceGenOpts) NonceGenOption { // lengthWriter is a function closure that allows a caller to control how the // length prefix of a byte slice is written. +// +// TODO(roasbeef): use type params once we bump repo version type lengthWriter func(w io.Writer, b []byte) error // uint8Writer is an implementation of lengthWriter that writes the length of @@ -205,6 +207,12 @@ func uint32Writer(w io.Writer, b []byte) error { return binary.Write(w, byteOrder, uint32(len(b))) } +// uint32Writer is an implementation of lengthWriter that writes the length of +// the byte slice using 8 bytes. +func uint64Writer(w io.Writer, b []byte) error { + return binary.Write(w, byteOrder, uint64(len(b))) +} + // writeBytesPrefix is used to write out: len(b) || b, to the passed io.Writer. // The lengthWriter function closure is used to allow the caller to specify the // precise byte packing of the length. @@ -225,10 +233,12 @@ func writeBytesPrefix(w io.Writer, b []byte, lenWriter lengthWriter) error { // genNonceAuxBytes writes out the full byte string used to derive a secret // nonce based on some initial randomness as well as the series of optional // fields. The byte string used for derivation is: -// * tagged_hash("MuSig/nonce", rand || len(aggpk) || aggpk || len(m) -// || m || len(in) || in || i). +// - tagged_hash("MuSig/nonce", rand || len(aggpk) || aggpk || m_prefixed +// || len(in) || in || i). // -// where i is the ith secret nonce being generated. +// where i is the ith secret nonce being generated and m_prefixed is: +// - bytes(1, 0) if the message is blank +// - bytes(1, 1) || bytes(8, len(m)) || m if the message is present. func genNonceAuxBytes(rand []byte, i int, opts *nonceGenOpts) (*chainhash.Hash, error) { @@ -245,10 +255,26 @@ func genNonceAuxBytes(rand []byte, i int, return nil, err } - // Next, we'll write out the length prefixed message. - err = writeBytesPrefix(&w, opts.msg, uint8Writer) - if err != nil { - return nil, err + switch len(opts.msg) { + // If the message isn't present, then we'll just write out a single + // uint8 of a zero byte: m_prefixed = bytes(1, 0). + case 0: + if _, err := w.Write([]byte{0x00}); err != nil { + return nil, err + } + + // Otherwise, we'll write a single byte of 0x01 with a 1 byte length + // prefix, followed by the message itself with an 8 byte length prefix: + // m_prefixed = bytes(1, 1) || bytes(8, len(m)) || m. + default: + if _, err := w.Write([]byte{0x01}); err != nil { + return nil, err + } + + err = writeBytesPrefix(&w, opts.msg, uint64Writer) + if err != nil { + return nil, err + } } // Finally we'll write out the auxiliary input. From 1567f200557d22b81f0b5cdcf0a9986cb83445b2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 5 Oct 2022 21:06:50 -0700 Subject: [PATCH 0725/1056] btcec/schnorr/musig2: update to musig 1.0.0 The major change in musig 1.0.0 is that plain public keys are used as input to key aggregation. --- btcec/schnorr/musig2/context.go | 8 ++----- btcec/schnorr/musig2/keys.go | 31 +++++++++++-------------- btcec/schnorr/musig2/musig2_test.go | 7 +----- btcec/schnorr/musig2/nonces.go | 2 +- btcec/schnorr/musig2/sign.go | 36 +++++++++-------------------- 5 files changed, 29 insertions(+), 55 deletions(-) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 19cef34fa9..adbedb8bf3 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -206,12 +206,7 @@ func NewContext(signingKey *btcec.PrivateKey, shouldSort bool, option(opts) } - pubKey, err := schnorr.ParsePubKey( - schnorr.SerializePubKey(signingKey.PubKey()), - ) - if err != nil { - return nil, err - } + pubKey := signingKey.PubKey() ctx := &Context{ signingKey: signingKey, @@ -243,6 +238,7 @@ func NewContext(signingKey *btcec.PrivateKey, shouldSort bool, // the nonce now to pass in to the session once all the callers // are known. if opts.earlyNonce { + var err error ctx.sessionNonce, err = GenNonces() if err != nil { return nil, err diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index 8c86c624fb..7e84ba57e9 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -40,8 +40,8 @@ type sortableKeys []*btcec.PublicKey // with index j. func (s sortableKeys) Less(i, j int) bool { // TODO(roasbeef): more efficient way to compare... - keyIBytes := schnorr.SerializePubKey(s[i]) - keyJBytes := schnorr.SerializePubKey(s[j]) + keyIBytes := s[i].SerializeCompressed() + keyJBytes := s[j].SerializeCompressed() return bytes.Compare(keyIBytes, keyJBytes) == -1 } @@ -56,9 +56,9 @@ func (s sortableKeys) Len() int { return len(s) } -// sortKeys takes a set of schnorr public keys and returns a new slice that is -// a copy of the keys sorted in lexicographical order bytes on the x-only -// pubkey serialization. +// sortKeys takes a set of public keys and returns a new slice that is a copy +// of the keys sorted in lexicographical order bytes on the x-only pubkey +// serialization. func sortKeys(keys []*btcec.PublicKey) []*btcec.PublicKey { keySet := sortableKeys(keys) if sort.IsSorted(keySet) { @@ -72,7 +72,7 @@ func sortKeys(keys []*btcec.PublicKey) []*btcec.PublicKey { // keyHashFingerprint computes the tagged hash of the series of (sorted) public // keys passed as input. This is used to compute the aggregation coefficient // for each key. The final computation is: -// * H(tag=KeyAgg list, pk1 || pk2..) +// - H(tag=KeyAgg list, pk1 || pk2..) func keyHashFingerprint(keys []*btcec.PublicKey, sort bool) []byte { if sort { keys = sortKeys(keys) @@ -80,28 +80,25 @@ func keyHashFingerprint(keys []*btcec.PublicKey, sort bool) []byte { // We'll create a single buffer and slice into that so the bytes buffer // doesn't continually need to grow the underlying buffer. - keyAggBuf := make([]byte, 32*len(keys)) + keyAggBuf := make([]byte, 33*len(keys)) keyBytes := bytes.NewBuffer(keyAggBuf[0:0]) for _, key := range keys { - keyBytes.Write(schnorr.SerializePubKey(key)) + keyBytes.Write(key.SerializeCompressed()) } h := chainhash.TaggedHash(KeyAggTagList, keyBytes.Bytes()) return h[:] } -// keyBytesEqual returns true if two keys are the same from the PoV of BIP -// 340's 32-byte x-only public keys. +// keyBytesEqual returns true if two keys are the same based on the compressed +// serialization of each key. func keyBytesEqual(a, b *btcec.PublicKey) bool { - return bytes.Equal( - schnorr.SerializePubKey(a), - schnorr.SerializePubKey(b), - ) + return bytes.Equal(a.SerializeCompressed(), b.SerializeCompressed()) } // aggregationCoefficient computes the key aggregation coefficient for the // specified target key. The coefficient is computed as: -// * H(tag=KeyAgg coefficient, keyHashFingerprint(pks) || pk) +// - H(tag=KeyAgg coefficient, keyHashFingerprint(pks) || pk) func aggregationCoefficient(keySet []*btcec.PublicKey, targetKey *btcec.PublicKey, keysHash []byte, secondKeyIdx int) *btcec.ModNScalar { @@ -116,9 +113,9 @@ func aggregationCoefficient(keySet []*btcec.PublicKey, // Otherwise, we'll compute the full finger print hash for this given // key and then use that to compute the coefficient tagged hash: // * H(tag=KeyAgg coefficient, keyHashFingerprint(pks, pk) || pk) - var coefficientBytes [64]byte + var coefficientBytes [65]byte copy(coefficientBytes[:], keysHash[:]) - copy(coefficientBytes[32:], schnorr.SerializePubKey(targetKey)) + copy(coefficientBytes[32:], targetKey.SerializeCompressed()) muHash := chainhash.TaggedHash(KeyAggTagCoeff, coefficientBytes[:]) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 94bb0ec16b..8ab1725c7b 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -993,12 +993,7 @@ func testMultiPartySign(t *testing.T, taprootTweak []byte, t.Fatalf("unable to gen priv key: %v", err) } - pubKey, err := schnorr.ParsePubKey( - schnorr.SerializePubKey(privKey.PubKey()), - ) - if err != nil { - t.Fatalf("unable to gen key: %v", err) - } + pubKey := privKey.PubKey() signerKeys[i] = privKey signSet[i] = pubKey diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 3866dc5438..201ff49db6 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -184,8 +184,8 @@ func withCustomOptions(customOpts nonceGenOpts) NonceGenOption { o.randReader = customOpts.randReader o.secretKey = customOpts.secretKey o.combinedKey = customOpts.combinedKey - o.msg = customOpts.msg o.auxInput = customOpts.auxInput + o.msg = customOpts.msg } } diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index fce61aa8a8..0b8130a1a5 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -299,31 +299,22 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, } pubKey := privKey.PubKey() - pubKeyYIsOdd := func() bool { - pubKeyBytes := pubKey.SerializeCompressed() - return pubKeyBytes[0] == secp.PubKeyFormatCompressedOdd - }() combinedKeyYIsOdd := func() bool { combinedKeyBytes := combinedKey.FinalKey.SerializeCompressed() return combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd }() - // Next we'll compute our two parity factors for Q the combined public - // key, and P, the public key we're signing with. If the keys are odd, - // then we'll negate them. + // Next we'll compute the two parity factors for Q, the combined key. + // If the key is odd, then we'll negate it. parityCombinedKey := new(btcec.ModNScalar).SetInt(1) - paritySignKey := new(btcec.ModNScalar).SetInt(1) if combinedKeyYIsOdd { parityCombinedKey.Negate() } - if pubKeyYIsOdd { - paritySignKey.Negate() - } // Before we sign below, we'll multiply by our various parity factors // to ensure that the signing key is properly negated (if necessary): - // * d = gv⋅gaccv⋅gp⋅d' - privKeyScalar.Mul(parityCombinedKey).Mul(paritySignKey).Mul(parityAcc) + // * d = g⋅gacc⋅d' + privKeyScalar.Mul(parityCombinedKey).Mul(parityAcc) // Next we'll create the challenge hash that commits to the combined // nonce, combined public key and also the message: @@ -372,7 +363,7 @@ func (p *PartialSignature) Verify(pubNonce [PubNonceSize]byte, combinedNonce [PubNonceSize]byte, keySet []*btcec.PublicKey, signingKey *btcec.PublicKey, msg [32]byte, signOpts ...SignOption) bool { - pubKey := schnorr.SerializePubKey(signingKey) + pubKey := signingKey.SerializeCompressed() return verifyPartialSig( p, pubNonce, combinedNonce, keySet, pubKey, msg, signOpts..., @@ -398,7 +389,6 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // Next we'll parse out the two public nonces into something we can // use. // - // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of verification. keysHash := keyHashFingerprint(keySet, opts.sortKeys) @@ -458,7 +448,6 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // With our nonce blinding value, we'll now combine both the public // nonces, using the blinding factor to tweak the second nonce: // * R = R_1 + b*R_2 - var nonce btcec.JacobianPoint btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) btcec.AddNonConst(&r1J, &r2J, &nonce) @@ -516,7 +505,7 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, var e btcec.ModNScalar e.SetByteSlice(challengeBytes[:]) - signingKey, err := schnorr.ParsePubKey(pubKey) + signingKey, err := btcec.ParsePubKey(pubKey) if err != nil { return err } @@ -527,27 +516,24 @@ func verifyPartialSig(partialSig *PartialSignature, pubNonce [PubNonceSize]byte, // If the combined key has an odd y coordinate, then we'll negate // parity factor for the signing key. - paritySignKey := new(btcec.ModNScalar).SetInt(1) + parityCombinedKey := new(btcec.ModNScalar).SetInt(1) combinedKeyBytes := combinedKey.FinalKey.SerializeCompressed() if combinedKeyBytes[0] == secp.PubKeyFormatCompressedOdd { - paritySignKey.Negate() + parityCombinedKey.Negate() } // Next, we'll construct the final parity factor by multiplying the // sign key parity factor with the accumulated parity factor for all // the keys. - finalParityFactor := paritySignKey.Mul(parityAcc) + finalParityFactor := parityCombinedKey.Mul(parityAcc) - // Now we'll multiply the parity factor by our signing key, which'll - // take care of the amount of negation needed. var signKeyJ btcec.JacobianPoint signingKey.AsJacobian(&signKeyJ) - btcec.ScalarMultNonConst(finalParityFactor, &signKeyJ, &signKeyJ) - // In the final set, we'll check that: s*G == R' + e*a*P. + // In the final set, we'll check that: s*G == R' + e*a*g*P. var sG, rP btcec.JacobianPoint btcec.ScalarBaseMultNonConst(s, &sG) - btcec.ScalarMultNonConst(e.Mul(a), &signKeyJ, &rP) + btcec.ScalarMultNonConst(e.Mul(a).Mul(finalParityFactor), &signKeyJ, &rP) btcec.AddNonConst(&rP, &pubNonceJ, &rP) sG.ToAffine() From 3d9f4484dfd6d01d07cffa90498f7595467cc190 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 11 Oct 2022 15:29:24 -0700 Subject: [PATCH 0726/1056] btcec/schnorr/musig: update nonce test vectors to musig2 1.0.0 --- btcec/go.mod | 7 +- btcec/go.sum | 13 ++ .../musig2/data/nonce_agg_vectors.json | 54 +++++ .../musig2/data/nonce_gen_vectors.json | 36 +++ btcec/schnorr/musig2/musig2_test.go | 206 +----------------- btcec/schnorr/musig2/nonces.go | 6 +- btcec/schnorr/musig2/nonces_test.go | 164 ++++++++++++++ 7 files changed, 279 insertions(+), 207 deletions(-) create mode 100644 btcec/schnorr/musig2/data/nonce_agg_vectors.json create mode 100644 btcec/schnorr/musig2/data/nonce_gen_vectors.json create mode 100644 btcec/schnorr/musig2/nonces_test.go diff --git a/btcec/go.mod b/btcec/go.mod index 8c7cc1d63c..452399cfc6 100644 --- a/btcec/go.mod +++ b/btcec/go.mod @@ -6,6 +6,11 @@ require ( github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 + github.com/stretchr/testify v1.8.0 ) -require github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect +require ( + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/btcec/go.sum b/btcec/go.sum index 0004a783bb..73b8f2b5ac 100644 --- a/btcec/go.sum +++ b/btcec/go.sum @@ -1,8 +1,21 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/btcec/schnorr/musig2/data/nonce_agg_vectors.json b/btcec/schnorr/musig2/data/nonce_agg_vectors.json new file mode 100644 index 0000000000..597246dd72 --- /dev/null +++ b/btcec/schnorr/musig2/data/nonce_agg_vectors.json @@ -0,0 +1,54 @@ +{ + "pnonces": [ + "020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E66603BA47FBC1834437B3212E89A84D8425E7BF12E0245D98262268EBDCB385D50641", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833", + "020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E6660279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60379BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "04FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A60248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B831", + "03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A602FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30" + ], + "valid_test_cases": [ + { + "pnonce_indices": [0, 1], + "expected": "035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B024725377345BDE0E9C33AF3C43C0A29A9249F2F2956FA8CFEB55C8573D0262DC8" + }, + { + "pnonce_indices": [2, 3], + "expected": "035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B000000000000000000000000000000000000000000000000000000000000000000", + "comment": "Sum of second points encoded in the nonces is point at infinity which is serialized as 33 zero bytes" + } + ], + "error_test_cases": [ + { + "pnonce_indices": [0, 4], + "error": { + "type": "invalid_contribution", + "signer": 1, + "contrib": "pubnonce" + }, + "comment": "Public nonce from signer 1 is invalid due wrong tag, 0x04, in the first half", + "btcec_err": "invalid public key: unsupported format: 4" + }, + { + "pnonce_indices": [5, 1], + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubnonce" + }, + "comment": "Public nonce from signer 0 is invalid because the second half does not correspond to an X coordinate", + "btcec_err": "invalid public key: x coordinate 48c264cdd57d3c24d79990b0f865674eb62a0f9018277a95011b41bfc193b831 is not on the secp256k1 curve" + }, + { + "pnonce_indices": [6, 1], + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubnonce" + }, + "comment": "Public nonce from signer 0 is invalid because second half exceeds field size", + "btcec_err": "invalid public key: x >= field prime" + } + ] +} diff --git a/btcec/schnorr/musig2/data/nonce_gen_vectors.json b/btcec/schnorr/musig2/data/nonce_gen_vectors.json new file mode 100644 index 0000000000..9727cfe93b --- /dev/null +++ b/btcec/schnorr/musig2/data/nonce_gen_vectors.json @@ -0,0 +1,36 @@ +{ + "test_cases": [ + { + "rand_": "0000000000000000000000000000000000000000000000000000000000000000", + "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", + "msg": "0101010101010101010101010101010101010101010101010101010101010101", + "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", + "expected": "BC6C683EBBCC39DCB3C29B3D010D2AAA7C86CFB562FC41ED9A460EE061013E75FB4AD2F0B816713269800D018803906D5481E00A940EAB4F4AC49B4A372EB0F4" + }, + { + "rand_": "0000000000000000000000000000000000000000000000000000000000000000", + "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", + "msg": "", + "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", + "expected": "AAC4BFD707F4953B4063851D7E4AAD5C59D5D0BFB0E71012788A85698B5ACF8F11834D5051928424BA501C8CD064F3F942F8D4A07D8A2ED79F153E4ABD9EBBE9" + }, + { + "rand_": "0000000000000000000000000000000000000000000000000000000000000000", + "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", + "msg": "2626262626262626262626262626262626262626262626262626262626262626262626262626", + "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", + "expected": "DF54500DD2B503DBA3753C48A9D6B67E6C11EC4325EDD1DC256C7F75D6A85DBECA6D9857A6F3F292FB3B50DBCBF69FADB67B1CDDB0EA6EB693F6455C4C9088E1" + }, + { + "rand_": "0000000000000000000000000000000000000000000000000000000000000000", + "sk": null, + "aggpk": null, + "msg": null, + "extra_in": null, + "expected": "7B3B5A002356471AF0E961DE2549C121BD0D48ABCEEDC6E034BDDF86AD3E0A187ECEE674CEF7364B0BC4BEEFB8B66CAD89F98DE2F8C5A5EAD5D1D1E4BD7D04CD" + } + ] +} diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 8ab1725c7b..1b4a68fd55 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -46,6 +46,8 @@ var ( "B65481B6BAAFB3C5810106717BEB") keyCombo4, _ = hex.DecodeString("2EB18851887E7BDC5E830E89B19DDBC28078" + "F1FA88AAD0AD01CA06FE4F80210B") + + testVectorBaseDir = "data" ) // getInfinityTweak returns a tweak that, when tweaking the Generator, triggers @@ -1340,210 +1342,6 @@ func TestMuSigEarlyNonce(t *testing.T) { } } -// TestMusig2NonceGenTestVectors tests the nonce generation function with -// the testvectors defined in the Musig2 BIP. -func TestMusig2NonceGenTestVectors(t *testing.T) { - t.Parallel() - - msg := bytes.Repeat([]byte{0x01}, 32) - sk := bytes.Repeat([]byte{0x02}, 32) - aggpk := bytes.Repeat([]byte{0x07}, 32) - extra_in := bytes.Repeat([]byte{0x08}, 32) - - testCases := []struct { - opts nonceGenOpts - expectedNonce string - }{ - { - opts: nonceGenOpts{ - randReader: &memsetRandReader{i: 0}, - secretKey: sk[:], - combinedKey: aggpk[:], - auxInput: extra_in[:], - msg: msg[:], - }, - expectedNonce: "BC6C683EBBCC39DCB3C29B3D010D2AAA7C86C" + - "FB562FC41ED9A460EE061013E75FB4AD2F0B81671326" + - "9800D018803906D5481E00A940EAB4F4AC49B4A372EB0F4", - }, - { - opts: nonceGenOpts{ - randReader: &memsetRandReader{i: 0}, - secretKey: sk[:], - combinedKey: aggpk[:], - auxInput: extra_in[:], - msg: nil, - }, - expectedNonce: "8A633F5EECBDB690A6BE4921426F41BE78D50" + - "9DC1CE894C1215844C0E4C6DE7ABC9A5BE0A3BF3FE31" + - "2CCB7E4817D2CB17A7CEA8382B73A99A583E323387B3C32", - }, - { - opts: nonceGenOpts{ - randReader: &memsetRandReader{i: 0}, - secretKey: nil, - combinedKey: nil, - auxInput: nil, - msg: nil, - }, - expectedNonce: "7B3B5A002356471AF0E961DE2549C121BD0D4" + - "8ABCEEDC6E034BDDF86AD3E0A187ECEE674CEF7364B0" + - "BC4BEEFB8B66CAD89F98DE2F8C5A5EAD5D1D1E4BD7D04CD", - }, - } - - for _, testCase := range testCases { - nonce, err := GenNonces(withCustomOptions(testCase.opts)) - if err != nil { - t.Fatalf("err gen nonce aux bytes %v", err) - } - - expectedBytes, _ := hex.DecodeString(testCase.expectedNonce) - if !bytes.Equal(nonce.SecNonce[:], expectedBytes) { - - t.Fatalf("nonces don't match: expected %x, got %x", - expectedBytes, nonce.SecNonce[:]) - } - } - -} - -var ( - pNonce1, _ = hex.DecodeString("020151C80F435648DF67A22B749CD798CE54E0321D034B92B709B567D60A42E666" + - "03BA47FBC1834437B3212E89A84D8425E7BF12E0245D98262268EBDCB385D50641") - pNonce2, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + - "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833") - - expectedNonce, _ = hex.DecodeString("035FE1873B4F2967F52FEA4A06AD5A8ECCBE9D0FD73068012C894E2E87CCB5804B" + - "024725377345BDE0E9C33AF3C43C0A29A9249F2F2956FA8CFEB55C8573D0262DC8") - - invalidNonce1, _ = hex.DecodeString("04FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B833") - invalidNonce2, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "0248C264CDD57D3C24D79990B0F865674EB62A0F9018277A95011B41BFC193B831") - invalidNonce3, _ = hex.DecodeString("03FF406FFD8ADB9CD29877E4985014F66A59F6CD01C0E88CAA8E5F3166B1F676A6" + "02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30") -) - -type jsonNonceAggTestCase struct { - Nonces []string `json:"nonces"` - ExpectedNonce string `json:"expected_key"` - ExpectedError string `json:"expected_error"` -} - -func TestMusig2AggregateNoncesTestVectors(t *testing.T) { - t.Parallel() - - var jsonCases []jsonNonceAggTestCase - - testCases := []struct { - nonces [][]byte - expectedNonce []byte - expectedError error - }{ - // Vector 1: Valid. - { - nonces: [][]byte{pNonce1, pNonce2}, - expectedNonce: expectedNonce, - }, - - // Vector 2: Public nonce from signer 1 is invalid due wrong - // tag, 0x04, inthe first half. - { - nonces: [][]byte{pNonce1, invalidNonce1}, - expectedError: secp256k1.ErrPubKeyInvalidFormat, - }, - - // Vector 3: Public nonce from signer 0 is invalid because the - // second half does not correspond to an X coordinate. - { - nonces: [][]byte{invalidNonce2, pNonce2}, - expectedError: secp256k1.ErrPubKeyNotOnCurve, - }, - - // Vector 4: Public nonce from signer 0 is invalid because - // second half exceeds field size. - { - nonces: [][]byte{invalidNonce3, pNonce2}, - expectedError: secp256k1.ErrPubKeyXTooBig, - }, - - // Vector 5: Sum of second points encoded in the nonces would - // be point at infinity, therefore set sum to base point G. - { - nonces: [][]byte{ - append( - append([]byte{}, pNonce1[0:33]...), - getGBytes()..., - ), - append( - append([]byte{}, pNonce2[0:33]...), - getNegGBytes()..., - ), - }, - expectedNonce: append( - append([]byte{}, expectedNonce[0:33]...), - getInfinityBytes()..., - ), - }, - } - for i, testCase := range testCases { - testName := fmt.Sprintf("Vector %v", i+1) - t.Run(testName, func(t *testing.T) { - var ( - nonces [][66]byte - strNonces []string - jsonError string - ) - for _, nonce := range testCase.nonces { - nonces = append(nonces, toPubNonceSlice(nonce)) - strNonces = append(strNonces, hex.EncodeToString(nonce)) - } - - if testCase.expectedError != nil { - jsonError = testCase.expectedError.Error() - } - - jsonCases = append(jsonCases, jsonNonceAggTestCase{ - Nonces: strNonces, - ExpectedNonce: hex.EncodeToString(expectedNonce), - ExpectedError: jsonError, - }) - - aggregatedNonce, err := AggregateNonces(nonces) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatalf("aggregating nonce error: %v", err) - } - - if !bytes.Equal(testCase.expectedNonce, aggregatedNonce[:]) { - t.Fatalf("case: #%v, invalid nonce aggregation: "+ - "expected %x, got %x", i, testCase.expectedNonce, - aggregatedNonce) - } - - }) - } - - if *dumpJson { - jsonBytes, err := json.Marshal(jsonCases) - if err != nil { - t.Fatalf("unable to encode json: %v", err) - } - - var formattedJson bytes.Buffer - json.Indent(&formattedJson, jsonBytes, "", "\t") - err = ioutil.WriteFile( - nonceAggTestVectorName, formattedJson.Bytes(), 0644, - ) - if err != nil { - t.Fatalf("unable to write file: %v", err) - } - } -} - type memsetRandReader struct { i int } diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 201ff49db6..4b2509a754 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -255,10 +255,10 @@ func genNonceAuxBytes(rand []byte, i int, return nil, err } - switch len(opts.msg) { + switch { // If the message isn't present, then we'll just write out a single // uint8 of a zero byte: m_prefixed = bytes(1, 0). - case 0: + case opts.msg == nil: if _, err := w.Write([]byte{0x00}); err != nil { return nil, err } @@ -266,6 +266,8 @@ func genNonceAuxBytes(rand []byte, i int, // Otherwise, we'll write a single byte of 0x01 with a 1 byte length // prefix, followed by the message itself with an 8 byte length prefix: // m_prefixed = bytes(1, 1) || bytes(8, len(m)) || m. + case len(opts.msg) == 0: + fallthrough default: if _, err := w.Write([]byte{0x01}); err != nil { return nil, err diff --git a/btcec/schnorr/musig2/nonces_test.go b/btcec/schnorr/musig2/nonces_test.go new file mode 100644 index 0000000000..bdb76dbd35 --- /dev/null +++ b/btcec/schnorr/musig2/nonces_test.go @@ -0,0 +1,164 @@ +// Copyright 2013-2022 The btcsuite developers + +package musig2 + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "path" + "testing" + + "github.com/stretchr/testify/require" +) + +type nonceGenTestCase struct { + Rand string `json:"rand_"` + Sk string `json:"sk"` + AggPk string `json:"aggpk"` + Msg *string `json:"msg"` + ExtraIn string `json:"extra_in"` + + Expected string `json:"expected"` +} + +type nonceGenTestCases struct { + TestCases []nonceGenTestCase `json:"test_cases"` +} + +const ( + nonceGenTestVectorsFileName = "nonce_gen_vectors.json" + nonceAggTestVectorsFileName = "nonce_agg_vectors.json" +) + +// TestMusig2NonceGenTestVectors tests the nonce generation function with the +// testvectors defined in the Musig2 BIP. +func TestMusig2NonceGenTestVectors(t *testing.T) { + t.Parallel() + + testVectorPath := path.Join( + testVectorBaseDir, nonceGenTestVectorsFileName, + ) + testVectorBytes, err := os.ReadFile(testVectorPath) + require.NoError(t, err) + + var testCases nonceGenTestCases + require.NoError(t, json.Unmarshal(testVectorBytes, &testCases)) + + for i, testCase := range testCases.TestCases { + testCase := testCase + + customOpts := nonceGenOpts{ + randReader: &memsetRandReader{i: 0}, + secretKey: mustParseHex(testCase.Sk), + combinedKey: mustParseHex(testCase.AggPk), + auxInput: mustParseHex(testCase.ExtraIn), + } + if testCase.Msg != nil { + customOpts.msg = mustParseHex(*testCase.Msg) + } + + t.Run(fmt.Sprintf("test_case=%v", i), func(t *testing.T) { + nonce, err := GenNonces(withCustomOptions(customOpts)) + if err != nil { + t.Fatalf("err gen nonce aux bytes %v", err) + } + + expectedBytes, _ := hex.DecodeString(testCase.Expected) + if !bytes.Equal(nonce.SecNonce[:], expectedBytes) { + + t.Fatalf("nonces don't match: expected %x, got %x", + expectedBytes, nonce.SecNonce[:]) + } + }) + } +} + +type nonceAggError struct { + Type string `json:"type"` + Signer int `json:"signer"` + Contrib string `json:"contrib"` +} + +type nonceAggValidCase struct { + Indices []int `json:"pnonce_indices"` + + Expected string `json:"expected"` + + Comment string `json:"comment"` +} + +type nonceAggInvalidCase struct { + Indices []int `json:"pnonce_indices"` + + Error nonceAggError `json:"error"` + + Comment string `json:"comment"` + + ExpectedErr string `json:"btcec_err"` +} + +type nonceAggTestCases struct { + Nonces []string `json:"pnonces"` + + ValidCases []nonceAggValidCase `json:"valid_test_cases"` + + InvalidCases []nonceAggInvalidCase `json:"error_test_cases"` +} + +// TestMusig2AggregateNoncesTestVectors tests that the musig2 implementation +// passes the nonce aggregration test vectors for musig2 1.0. +func TestMusig2AggregateNoncesTestVectors(t *testing.T) { + t.Parallel() + + testVectorPath := path.Join( + testVectorBaseDir, nonceAggTestVectorsFileName, + ) + testVectorBytes, err := os.ReadFile(testVectorPath) + require.NoError(t, err) + + var testCases nonceAggTestCases + require.NoError(t, json.Unmarshal(testVectorBytes, &testCases)) + + nonces := make([][PubNonceSize]byte, len(testCases.Nonces)) + for i := range testCases.Nonces { + var nonce [PubNonceSize]byte + copy(nonce[:], mustParseHex(testCases.Nonces[i])) + + nonces[i] = nonce + } + + for i, testCase := range testCases.ValidCases { + testCase := testCase + + var testNonces [][PubNonceSize]byte + for _, idx := range testCase.Indices { + testNonces = append(testNonces, nonces[idx]) + } + + t.Run(fmt.Sprintf("valid_case=%v", i), func(t *testing.T) { + aggregatedNonce, err := AggregateNonces(testNonces) + require.NoError(t, err) + + var expectedNonce [PubNonceSize]byte + copy(expectedNonce[:], mustParseHex(testCase.Expected)) + + require.Equal(t, aggregatedNonce[:], expectedNonce[:]) + }) + } + + for i, testCase := range testCases.InvalidCases { + var testNonces [][PubNonceSize]byte + for _, idx := range testCase.Indices { + testNonces = append(testNonces, nonces[idx]) + } + + t.Run(fmt.Sprintf("invalid_case=%v", i), func(t *testing.T) { + _, err := AggregateNonces(testNonces) + require.True(t, err != nil) + require.Equal(t, testCase.ExpectedErr, err.Error()) + }) + } +} From 4e55273815ee5d33969fc371742dc0e43cd30bd5 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 19 Oct 2022 19:07:21 -0700 Subject: [PATCH 0727/1056] btcec/schnorr/musig2: update key agg test vectors to musig2 1.0.0 --- .../schnorr/musig2/data/key_agg_vectors.json | 88 ++++++ .../schnorr/musig2/data/key_sort_vectors.json | 16 ++ btcec/schnorr/musig2/keys_test.go | 257 ++++++++++++++++++ btcec/schnorr/musig2/musig2_test.go | 186 ------------- 4 files changed, 361 insertions(+), 186 deletions(-) create mode 100644 btcec/schnorr/musig2/data/key_agg_vectors.json create mode 100644 btcec/schnorr/musig2/data/key_sort_vectors.json create mode 100644 btcec/schnorr/musig2/keys_test.go diff --git a/btcec/schnorr/musig2/data/key_agg_vectors.json b/btcec/schnorr/musig2/data/key_agg_vectors.json new file mode 100644 index 0000000000..b2e623de60 --- /dev/null +++ b/btcec/schnorr/musig2/data/key_agg_vectors.json @@ -0,0 +1,88 @@ +{ + "pubkeys": [ + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66", + "020000000000000000000000000000000000000000000000000000000000000005", + "02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30", + "04F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9" + ], + "tweaks": [ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + "252E4BD67410A76CDF933D30EAA1608214037F1B105A013ECCD3C5C184A6110B" + ], + "valid_test_cases": [ + { + "key_indices": [0, 1, 2], + "expected": "90539EEDE565F5D054F32CC0C220126889ED1E5D193BAF15AEF344FE59D4610C" + }, + { + "key_indices": [2, 1, 0], + "expected": "6204DE8B083426DC6EAF9502D27024D53FC826BF7D2012148A0575435DF54B2B" + }, + { + "key_indices": [0, 0, 0], + "expected": "B436E3BAD62B8CD409969A224731C193D051162D8C5AE8B109306127DA3AA935" + }, + { + "key_indices": [0, 0, 1, 1], + "expected": "69BC22BFA5D106306E48A20679DE1D7389386124D07571D0D872686028C26A3E" + } + ], + "error_test_cases": [ + { + "key_indices": [0, 3], + "tweak_indices": [], + "is_xonly": [], + "error": { + "type": "invalid_contribution", + "signer": 1, + "contrib": "pubkey" + }, + "comment": "Invalid public key" + }, + { + "key_indices": [0, 4], + "tweak_indices": [], + "is_xonly": [], + "error": { + "type": "invalid_contribution", + "signer": 1, + "contrib": "pubkey" + }, + "comment": "Public key exceeds field size" + }, + { + "key_indices": [5, 0], + "tweak_indices": [], + "is_xonly": [], + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubkey" + }, + "comment": "First byte of public key is not 2 or 3" + }, + { + "key_indices": [0, 1], + "tweak_indices": [0], + "is_xonly": [true], + "error": { + "type": "value", + "message": "The tweak must be less than n." + }, + "comment": "Tweak is out of range" + }, + { + "key_indices": [6], + "tweak_indices": [1], + "is_xonly": [false], + "error": { + "type": "value", + "message": "The result of tweaking cannot be infinity." + }, + "comment": "Intermediate tweaking result is point at infinity" + } + ] +} diff --git a/btcec/schnorr/musig2/data/key_sort_vectors.json b/btcec/schnorr/musig2/data/key_sort_vectors.json new file mode 100644 index 0000000000..022f3417fa --- /dev/null +++ b/btcec/schnorr/musig2/data/key_sort_vectors.json @@ -0,0 +1,16 @@ +{ + "pubkeys": [ + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659", + "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8" + ], + "sorted_pubkeys": [ + "023590A94E768F8E1815C2F24B4D80A8E3149316C3518CE7B7AD338368D038CA66", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8", + "02DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659" + ] +} diff --git a/btcec/schnorr/musig2/keys_test.go b/btcec/schnorr/musig2/keys_test.go new file mode 100644 index 0000000000..f9a6e05665 --- /dev/null +++ b/btcec/schnorr/musig2/keys_test.go @@ -0,0 +1,257 @@ +// Copyright 2013-2022 The btcsuite developers + +package musig2 + +import ( + "encoding/json" + "fmt" + "os" + "path" + "strings" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/stretchr/testify/require" +) + +const ( + keySortTestVectorFileName = "key_sort_vectors.json" + + keyAggTestVectorFileName = "key_agg_vectors.json" +) + +type keySortTestVector struct { + PubKeys []string `json:"pubkeys"` + + SortedKeys []string `json:"sorted_pubkeys"` +} + +// TestMusig2KeySort tests that keys are properly sorted according to the +// musig2 test vectors. +func TestMusig2KeySort(t *testing.T) { + t.Parallel() + + testVectorPath := path.Join( + testVectorBaseDir, keySortTestVectorFileName, + ) + testVectorBytes, err := os.ReadFile(testVectorPath) + require.NoError(t, err) + + var testCase keySortTestVector + require.NoError(t, json.Unmarshal(testVectorBytes, &testCase)) + + keys := make([]*btcec.PublicKey, len(testCase.PubKeys)) + for i, keyStr := range testCase.PubKeys { + pubKey, err := btcec.ParsePubKey(mustParseHex(keyStr)) + require.NoError(t, err) + + keys[i] = pubKey + } + + sortedKeys := sortKeys(keys) + + expectedKeys := make([]*btcec.PublicKey, len(testCase.PubKeys)) + for i, keyStr := range testCase.SortedKeys { + pubKey, err := btcec.ParsePubKey(mustParseHex(keyStr)) + require.NoError(t, err) + + expectedKeys[i] = pubKey + } + + require.Equal(t, sortedKeys, expectedKeys) +} + +type keyAggValidTest struct { + Indices []int `json:"key_indices"` + Expected string `json:"expected"` +} + +type keyAggError struct { + Type string `json:"type"` + Signer int `json:"signer"` + Contring string `json:"contrib"` +} + +type keyAggInvalidTest struct { + Indices []int `json:"key_indices"` + + TweakIndices []int `json:"tweak_indices"` + + IsXOnly []bool `json:"is_xonly"` + + Comment string `json:"comment"` +} + +type keyAggTestVectors struct { + PubKeys []string `json:"pubkeys"` + + Tweaks []string `json:"tweaks"` + + ValidCases []keyAggValidTest `json:"valid_test_cases"` + + InvalidCases []keyAggInvalidTest `json:"error_test_cases"` +} + +func keysFromIndices(t *testing.T, indices []int, + pubKeys []string) ([]*btcec.PublicKey, error) { + + t.Helper() + + inputKeys := make([]*btcec.PublicKey, len(indices)) + for i, keyIdx := range indices { + var err error + inputKeys[i], err = btcec.ParsePubKey( + mustParseHex(pubKeys[keyIdx]), + ) + if err != nil { + return nil, err + } + } + + return inputKeys, nil +} + +func tweaksFromIndices(t *testing.T, indices []int, + tweaks []string, isXonly bool) []KeyTweakDesc { + + t.Helper() + + testTweaks := make([]KeyTweakDesc, len(indices)) + for i, idx := range indices { + var rawTweak [32]byte + copy(rawTweak[:], mustParseHex(tweaks[idx])) + + testTweaks[i] = KeyTweakDesc{ + Tweak: rawTweak, + IsXOnly: isXonly, + } + } + + return testTweaks +} + +// TestMuSig2KeyAggTestVectors tests that this implementation of musig2 key +// aggregation lines up with the secp256k1-zkp test vectors. +func TestMuSig2KeyAggTestVectors(t *testing.T) { + t.Parallel() + + testVectorPath := path.Join( + testVectorBaseDir, keyAggTestVectorFileName, + ) + testVectorBytes, err := os.ReadFile(testVectorPath) + require.NoError(t, err) + + var testCases keyAggTestVectors + require.NoError(t, json.Unmarshal(testVectorBytes, &testCases)) + + tweaks := make([][]byte, len(testCases.Tweaks)) + for i := range testCases.Tweaks { + tweaks[i] = mustParseHex(testCases.Tweaks[i]) + } + + for i, testCase := range testCases.ValidCases { + testCase := testCase + + // Assemble the set of keys we'll pass in based on their key + // index. We don't use sorting to ensure we send the keys in + // the exact same order as the test vectors do. + inputKeys, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + require.NoError(t, err) + + t.Run(fmt.Sprintf("test_case=%v", i), func(t *testing.T) { + uniqueKeyIndex := secondUniqueKeyIndex(inputKeys, false) + opts := []KeyAggOption{WithUniqueKeyIndex(uniqueKeyIndex)} + + combinedKey, _, _, err := AggregateKeys( + inputKeys, false, opts..., + ) + require.NoError(t, err) + + require.Equal( + t, schnorr.SerializePubKey(combinedKey.FinalKey), + mustParseHex(testCase.Expected), + ) + }) + } + + for _, testCase := range testCases.InvalidCases { + testCase := testCase + + testName := fmt.Sprintf("invalid_%v", + strings.ToLower(testCase.Comment)) + t.Run(testName, func(t *testing.T) { + // For each test, we'll extract the set of input keys + // as well as the tweaks since this set of cases also + // exercises error cases related to the set of tweaks. + inputKeys, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + + // In this set of test cases, we should only get this + // for the very first vector. + if err != nil { + switch testCase.Comment { + case "Invalid public key": + require.ErrorIs( + t, err, + secp.ErrPubKeyNotOnCurve, + ) + + case "Public key exceeds field size": + require.ErrorIs( + t, err, secp.ErrPubKeyXTooBig, + ) + + case "First byte of public key is not 2 or 3": + require.ErrorIs( + t, err, + secp.ErrPubKeyInvalidFormat, + ) + + default: + t.Fatalf("uncaught err: %v", err) + } + + return + } + + var tweaks []KeyTweakDesc + if len(testCase.TweakIndices) != 0 { + tweaks = tweaksFromIndices( + t, testCase.TweakIndices, testCases.Tweaks, + testCase.IsXOnly, + ) + } + + uniqueKeyIndex := secondUniqueKeyIndex(inputKeys, false) + opts := []KeyAggOption{ + WithUniqueKeyIndex(uniqueKeyIndex), + } + + if len(tweaks) != 0 { + opts = append(opts, WithKeyTweaks(tweaks...)) + } + + _, _, _, err = AggregateKeys( + inputKeys, false, opts..., + ) + require.Error(t, err) + + switch testCase.Comment { + case "Tweak is out of range": + require.ErrorIs(t, err, ErrTweakedKeyOverflows) + + case "Intermediate tweaking result is point at infinity": + + require.ErrorIs(t, err, ErrTweakedKeyIsInfinity) + + default: + t.Fatalf("uncaught err: %v", err) + } + }) + } +} diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 1b4a68fd55..501ef41a38 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -75,198 +75,12 @@ func getInfinityTweak() KeyTweakDesc { } const ( - keyAggTestVectorName = "key_agg_vectors.json" - - nonceAggTestVectorName = "nonce_agg_vectors.json" - signTestVectorName = "sign_vectors.json" ) var dumpJson = flag.Bool("dumpjson", false, "if true, a JSON version of the "+ "test vectors will be written to the cwd") -type jsonKeyAggTestCase struct { - Keys []string `json:"keys"` - Tweaks []jsonTweak `json:"tweaks"` - ExpectedKey string `json:"expected_key"` - ExpectedError string `json:"expected_error"` -} - -// TestMuSig2KeyAggTestVectors tests that this implementation of musig2 key -// aggregation lines up with the secp256k1-zkp test vectors. -func TestMuSig2KeyAggTestVectors(t *testing.T) { - t.Parallel() - - var jsonCases []jsonKeyAggTestCase - - testCases := []struct { - keyOrder []int - explicitKeys []*btcec.PublicKey - tweaks []KeyTweakDesc - expectedKey []byte - expectedError error - }{ - // Keys in backwards lexicographical order. - { - keyOrder: []int{0, 1, 2}, - expectedKey: keyCombo1, - }, - - // Keys in sorted order. - { - keyOrder: []int{2, 1, 0}, - expectedKey: keyCombo2, - }, - - // Only the first key. - { - keyOrder: []int{0, 0, 0}, - expectedKey: keyCombo3, - }, - - // Duplicate the first key and second keys. - { - keyOrder: []int{0, 0, 1, 1}, - expectedKey: keyCombo4, - }, - - // Invalid public key. - { - keyOrder: []int{0, 3}, - expectedError: secp256k1.ErrPubKeyNotOnCurve, - }, - - // Public key exceeds field size. - { - keyOrder: []int{0, 4}, - expectedError: secp256k1.ErrPubKeyXTooBig, - }, - - // Tweak is out of range. - { - keyOrder: []int{0, 1}, - tweaks: []KeyTweakDesc{ - KeyTweakDesc{ - Tweak: to32ByteSlice(invalidTweak), - IsXOnly: true, - }, - }, - expectedError: ErrTweakedKeyOverflows, - }, - - // Intermediate tweaking result is point at infinity. - { - explicitKeys: []*secp256k1.PublicKey{btcec.Generator()}, - tweaks: []KeyTweakDesc{ - getInfinityTweak(), - }, - expectedError: ErrTweakedKeyIsInfinity, - }, - } - for i, testCase := range testCases { - testName := fmt.Sprintf("%v", testCase.keyOrder) - t.Run(testName, func(t *testing.T) { - var ( - keys []*btcec.PublicKey - strKeys []string - strTweaks []jsonTweak - jsonError string - ) - for _, keyIndex := range testCase.keyOrder { - keyBytes := testKeys[keyIndex] - pub, err := schnorr.ParsePubKey(keyBytes) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - return - case err != nil: - t.Fatalf("unable to parse pubkeys: %v", err) - } - - keys = append(keys, pub) - strKeys = append(strKeys, hex.EncodeToString(keyBytes)) - } - - for _, explicitKey := range testCase.explicitKeys { - keys = append(keys, explicitKey) - strKeys = append( - strKeys, - hex.EncodeToString( - explicitKey.SerializeCompressed(), - )) - } - - for _, tweak := range testCase.tweaks { - strTweaks = append( - strTweaks, - jsonTweak{ - Tweak: hex.EncodeToString( - tweak.Tweak[:], - ), - XOnly: tweak.IsXOnly, - }) - } - - if testCase.expectedError != nil { - jsonError = testCase.expectedError.Error() - } - - jsonCases = append( - jsonCases, - jsonKeyAggTestCase{ - Keys: strKeys, - Tweaks: strTweaks, - ExpectedKey: hex.EncodeToString( - testCase.expectedKey), - ExpectedError: jsonError, - }) - - uniqueKeyIndex := secondUniqueKeyIndex(keys, false) - opts := []KeyAggOption{WithUniqueKeyIndex(uniqueKeyIndex)} - if len(testCase.tweaks) > 0 { - opts = append(opts, WithKeyTweaks(testCase.tweaks...)) - } - - combinedKey, _, _, err := AggregateKeys( - keys, false, opts..., - ) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - return - - case err != nil: - t.Fatalf("case #%v, got error %v", i, err) - } - - combinedKeyBytes := schnorr.SerializePubKey(combinedKey.FinalKey) - if !bytes.Equal(combinedKeyBytes, testCase.expectedKey) { - t.Fatalf("case: #%v, invalid aggregation: "+ - "expected %x, got %x", i, testCase.expectedKey, - combinedKeyBytes) - } - }) - } - - if *dumpJson { - jsonBytes, err := json.Marshal(jsonCases) - if err != nil { - t.Fatalf("unable to encode json: %v", err) - } - - var formattedJson bytes.Buffer - json.Indent(&formattedJson, jsonBytes, "", "\t") - err = ioutil.WriteFile( - keyAggTestVectorName, formattedJson.Bytes(), 0644, - ) - if err != nil { - t.Fatalf("unable to write file: %v", err) - } - } -} - func mustParseHex(str string) []byte { b, err := hex.DecodeString(str) if err != nil { From cc12483f0aae6d8f5e08bac15ceb8309b6589c8c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 19 Oct 2022 20:15:16 -0700 Subject: [PATCH 0728/1056] btcec/schnorr/musig2: add key tweak sign test vectors --- btcec/schnorr/musig2/data/tweak_vectors.json | 84 +++++++++++ btcec/schnorr/musig2/keys.go | 2 +- btcec/schnorr/musig2/keys_test.go | 139 ++++++++++++++++++- 3 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 btcec/schnorr/musig2/data/tweak_vectors.json diff --git a/btcec/schnorr/musig2/data/tweak_vectors.json b/btcec/schnorr/musig2/data/tweak_vectors.json new file mode 100644 index 0000000000..01ccb8b1b3 --- /dev/null +++ b/btcec/schnorr/musig2/data/tweak_vectors.json @@ -0,0 +1,84 @@ +{ + "sk": "7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671", + "pubkeys": [ + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659" + ], + "secnonce": "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7", + "pnonces": [ + "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "032DE2662628C90B03F5E720284EB52FF7D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1CA6BEB2090C93D930321071AD40B2F44E599046" + ], + "aggnonce": "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9", + "tweaks": [ + "E8F791FF9225A2AF0102AFFF4A9A723D9612A682A25EBE79802B263CDFCD83BB", + "AE2EA797CC0FE72AC5B97B97F3C6957D7E4199A167A58EB08BCAFFDA70AC0455", + "F52ECBC565B3D8BEA2DFD5B75A4F457E54369809322E4120831626F290FA87E0", + "1969AD73CC177FA0B4FCED6DF1F7BF9907E665FDE9BA196A74FED0A3CF5AEF9D", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" + ], + "msg": "F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF", + "valid_test_cases": [ + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0], + "is_xonly": [true], + "signer_index": 2, + "expected": "E28A5C66E61E178C2BA19DB77B6CF9F7E2F0F56C17918CD13135E60CC848FE91", + "comment": "A single x-only tweak" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0], + "is_xonly": [false], + "signer_index": 2, + "expected": "38B0767798252F21BF5702C48028B095428320F73A4B14DB1E25DE58543D2D2D", + "comment": "A single plain tweak" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0, 1], + "is_xonly": [false, true], + "signer_index": 2, + "expected": "408A0A21C4A0F5DACAF9646AD6EB6FECD7F7A11F03ED1F48DFFF2185BC2C2408", + "comment": "A plain tweak followed by an x-only tweak" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0, 1, 2, 3], + "is_xonly": [false, false, true, true], + "signer_index": 2, + "expected": "45ABD206E61E3DF2EC9E264A6FEC8292141A633C28586388235541F9ADE75435", + "comment": "Four tweaks: plain, plain, x-only, x-only." + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [0, 1, 2, 3], + "is_xonly": [true, false, true, false], + "signer_index": 2, + "expected": "B255FDCAC27B40C7CE7848E2D3B7BF5EA0ED756DA81565AC804CCCA3E1D5D239", + "comment": "Four tweaks: x-only, plain, x-only, plain. If an implementation prohibits applying plain tweaks after x-only tweaks, it can skip this test vector or return an error." + } + ], + "error_test_cases": [ + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "tweak_indices": [4], + "is_xonly": [false], + "signer_index": 2, + "error": { + "type": "value", + "message": "The tweak must be less than n." + }, + "comment": "Tweak is invalid because it exceeds group size" + } + ] +} diff --git a/btcec/schnorr/musig2/keys.go b/btcec/schnorr/musig2/keys.go index 7e84ba57e9..4ee63be2eb 100644 --- a/btcec/schnorr/musig2/keys.go +++ b/btcec/schnorr/musig2/keys.go @@ -29,7 +29,7 @@ var ( // ErrTweakedKeyOverflows is returned if a tweaking key is larger than // 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141. - ErrTweakedKeyOverflows = fmt.Errorf("tweaked key is to large") + ErrTweakedKeyOverflows = fmt.Errorf("tweaked key is too large") ) // sortableKeys defines a type of slice of public keys that implements the sort diff --git a/btcec/schnorr/musig2/keys_test.go b/btcec/schnorr/musig2/keys_test.go index f9a6e05665..941ab14c7a 100644 --- a/btcec/schnorr/musig2/keys_test.go +++ b/btcec/schnorr/musig2/keys_test.go @@ -3,6 +3,7 @@ package musig2 import ( + "encoding/hex" "encoding/json" "fmt" "os" @@ -20,6 +21,8 @@ const ( keySortTestVectorFileName = "key_sort_vectors.json" keyAggTestVectorFileName = "key_agg_vectors.json" + + keyTweakTestVectorFileName = "tweak_vectors.json" ) type keySortTestVector struct { @@ -114,7 +117,7 @@ func keysFromIndices(t *testing.T, indices []int, } func tweaksFromIndices(t *testing.T, indices []int, - tweaks []string, isXonly bool) []KeyTweakDesc { + tweaks []string, isXonly []bool) []KeyTweakDesc { t.Helper() @@ -125,7 +128,7 @@ func tweaksFromIndices(t *testing.T, indices []int, testTweaks[i] = KeyTweakDesc{ Tweak: rawTweak, - IsXOnly: isXonly, + IsXOnly: isXonly[i], } } @@ -255,3 +258,135 @@ func TestMuSig2KeyAggTestVectors(t *testing.T) { }) } } + +type keyTweakInvalidTest struct { + Indices []int `json:"key_indices"` + + NonceIndices []int `json:"nonce_indices"` + + TweakIndices []int `json:"tweak_indices"` + + IsXOnly []bool `json:"is_only"` + + SignerIndex int `json:"signer_index"` + + Comment string `json:"comment"` +} + +type keyTweakValidTest struct { + Indices []int `json:"key_indices"` + + NonceIndices []int `json:"nonce_indices"` + + TweakIndices []int `json:"tweak_indices"` + + IsXOnly []bool `json:"is_xonly"` + + SignerIndex int `json:"signer_index"` + + Expected string `json:"expected"` + + Comment string `json:"comment"` +} + +type keyTweakVector struct { + PrivKey string `json:"sk"` + + PubKeys []string `json:"pubkeys"` + + PrivNonce string `json:"secnonce"` + + PubNonces []string `json:"pnonces"` + + AggNnoce string `json:"aggnonce"` + + Tweaks []string `json:"tweaks"` + + Msg string `json:"msg"` + + ValidCases []keyTweakValidTest `json:"valid_test_cases"` + + InvalidCases []keyTweakInvalidTest `json:"error_test_cases"` +} + +func pubNoncesFromIndices(t *testing.T, nonceIndices []int, pubNonces []string) [][PubNonceSize]byte { + + nonces := make([][PubNonceSize]byte, len(nonceIndices)) + + for i, idx := range nonceIndices { + var pubNonce [PubNonceSize]byte + copy(pubNonce[:], mustParseHex(pubNonces[idx])) + + nonces[i] = pubNonce + } + + return nonces +} + +// TestMuSig2TweakTestVectors tests that we properly handle the various edge +// cases related to tweaking public keys. +func TestMuSig2TweakTestVectors(t *testing.T) { + t.Parallel() + + testVectorPath := path.Join( + testVectorBaseDir, keyTweakTestVectorFileName, + ) + testVectorBytes, err := os.ReadFile(testVectorPath) + require.NoError(t, err) + + var testCases keyTweakVector + require.NoError(t, json.Unmarshal(testVectorBytes, &testCases)) + + privKey, _ := btcec.PrivKeyFromBytes(mustParseHex(testCases.PrivKey)) + + var msg [32]byte + copy(msg[:], mustParseHex(testCases.Msg)) + + var secNonce [SecNonceSize]byte + copy(secNonce[:], mustParseHex(testCases.PrivNonce)) + + for _, testCase := range testCases.ValidCases { + testName := fmt.Sprintf("valid_%v", + strings.ToLower(testCase.Comment)) + t.Run(testName, func(t *testing.T) { + pubKeys, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + require.NoError(t, err) + + var tweaks []KeyTweakDesc + if len(testCase.TweakIndices) != 0 { + tweaks = tweaksFromIndices( + t, testCase.TweakIndices, + testCases.Tweaks, testCase.IsXOnly, + ) + } + + pubNonces := pubNoncesFromIndices( + t, testCase.NonceIndices, testCases.PubNonces, + ) + + combinedNonce, err := AggregateNonces(pubNonces) + require.NoError(t, err) + + var opts []SignOption + if len(tweaks) != 0 { + opts = append(opts, WithTweaks(tweaks...)) + } + + partialSig, err := Sign( + secNonce, privKey, combinedNonce, pubKeys, + msg, opts..., + ) + + var partialSigBytes [32]byte + partialSig.S.PutBytesUnchecked(partialSigBytes[:]) + + require.Equal( + t, hex.EncodeToString(partialSigBytes[:]), + hex.EncodeToString(mustParseHex(testCase.Expected)), + ) + + }) + } +} From ca28a98425aca171343ab6cb525ac3dbdf0bb397 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 20 Oct 2022 16:35:05 -0700 Subject: [PATCH 0729/1056] btcec/schnorr/musig2: add sig verify+sign test vectors --- .../musig2/data/sign_verify_vectors.json | 183 ++++++++++++ btcec/schnorr/musig2/keys_test.go | 2 + btcec/schnorr/musig2/sign_test.go | 267 ++++++++++++++++++ 3 files changed, 452 insertions(+) create mode 100644 btcec/schnorr/musig2/data/sign_verify_vectors.json create mode 100644 btcec/schnorr/musig2/sign_test.go diff --git a/btcec/schnorr/musig2/data/sign_verify_vectors.json b/btcec/schnorr/musig2/data/sign_verify_vectors.json new file mode 100644 index 0000000000..e2499c7fb6 --- /dev/null +++ b/btcec/schnorr/musig2/data/sign_verify_vectors.json @@ -0,0 +1,183 @@ +{ + "sk": "7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671", + "pubkeys": [ + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA661", + "020000000000000000000000000000000000000000000000000000000000000007" + ], + "secnonces": [ + "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + ], + "pnonces": [ + "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "032DE2662628C90B03F5E720284EB52FF7D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1CA6BEB2090C93D930321071AD40B2F44E599046", + "0237C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0387BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", + "020000000000000000000000000000000000000000000000000000000000000009" + ], + "aggnonces": [ + "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "048465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9", + "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61020000000000000000000000000000000000000000000000000000000000000009", + "028465FCF0BBDBCF443AABCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD6102FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30" + ], + "msgs": [ + "F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF", + "", + "2626262626262626262626262626262626262626262626262626262626262626262626262626" + ], + "valid_test_cases": [ + { + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 0, + "expected": "012ABBCB52B3016AC03AD82395A1A415C48B93DEF78718E62A7A90052FE224FB" + }, + { + "key_indices": [1, 0, 2], + "nonce_indices": [1, 0, 2], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 1, + "expected": "9FF2F7AAA856150CC8819254218D3ADEEB0535269051897724F9DB3789513A52" + }, + { + "key_indices": [1, 2, 0], + "nonce_indices": [1, 2, 0], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 2, + "expected": "FA23C359F6FAC4E7796BB93BC9F0532A95468C539BA20FF86D7C76ED92227900" + }, + { + "key_indices": [0, 1], + "nonce_indices": [0, 3], + "aggnonce_index": 1, + "msg_index": 0, + "signer_index": 0, + "expected": "AE386064B26105404798F75DE2EB9AF5EDA5387B064B83D049CB7C5E08879531", + "comment": "Both halves of aggregate nonce correspond to point at infinity" + } + ], + "sign_error_test_cases": [ + { + "key_indices": [1, 0, 3], + "aggnonce_index": 0, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": 2, + "contrib": "pubkey" + }, + "comment": "Signer 2 provided an invalid public key" + }, + { + "key_indices": [1, 2, 0], + "aggnonce_index": 2, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggnonce" + }, + "comment": "Aggregate nonce is invalid due wrong tag, 0x04, in the first half" + }, + { + "key_indices": [1, 2, 0], + "aggnonce_index": 3, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggnonce" + }, + "comment": "Aggregate nonce is invalid because the second half does not correspond to an X coordinate" + }, + { + "key_indices": [1, 2, 0], + "aggnonce_index": 4, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "invalid_contribution", + "signer": null, + "contrib": "aggnonce" + }, + "comment": "Aggregate nonce is invalid because second half exceeds field size" + }, + { + "key_indices": [0, 1, 2], + "aggnonce_index": 0, + "msg_index": 0, + "signer_index": 0, + "secnonce_index": 1, + "error": { + "type": "value", + "message": "first secnonce value is out of range." + }, + "comment": "Secnonce is invalid which may indicate nonce reuse" + } + ], + "verify_fail_test_cases": [ + { + "sig": "97AC833ADCB1AFA42EBF9E0725616F3C9A0D5B614F6FE283CEAAA37A8FFAF406", + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 0, + "comment": "Wrong signature (which is equal to the negation of valid signature)" + }, + { + "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B", + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 1, + "comment": "Wrong signer" + }, + { + "sig": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + "key_indices": [0, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 0, + "comment": "Signature exceeds group size" + } + ], + "verify_error_test_cases": [ + { + "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B", + "key_indices": [0, 1, 2], + "nonce_indices": [4, 1, 2], + "msg_index": 0, + "signer_index": 0, + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubnonce" + }, + "comment": "Invalid pubnonce" + }, + { + "sig": "68537CC5234E505BD14061F8DA9E90C220A181855FD8BDB7F127BB12403B4D3B", + "key_indices": [3, 1, 2], + "nonce_indices": [0, 1, 2], + "msg_index": 0, + "signer_index": 0, + "error": { + "type": "invalid_contribution", + "signer": 0, + "contrib": "pubkey" + }, + "comment": "Invalid pubkey" + } + ] +} diff --git a/btcec/schnorr/musig2/keys_test.go b/btcec/schnorr/musig2/keys_test.go index 941ab14c7a..9eb16b537f 100644 --- a/btcec/schnorr/musig2/keys_test.go +++ b/btcec/schnorr/musig2/keys_test.go @@ -346,6 +346,8 @@ func TestMuSig2TweakTestVectors(t *testing.T) { copy(secNonce[:], mustParseHex(testCases.PrivNonce)) for _, testCase := range testCases.ValidCases { + testCase := testCase + testName := fmt.Sprintf("valid_%v", strings.ToLower(testCase.Comment)) t.Run(testName, func(t *testing.T) { diff --git a/btcec/schnorr/musig2/sign_test.go b/btcec/schnorr/musig2/sign_test.go new file mode 100644 index 0000000000..07caad9c6e --- /dev/null +++ b/btcec/schnorr/musig2/sign_test.go @@ -0,0 +1,267 @@ +// Copyright 2013-2022 The btcsuite developers + +package musig2 + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "os" + "path" + "strings" + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" + "github.com/stretchr/testify/require" +) + +const ( + signVerifyTestVectorFileName = "sign_verify_vectors.json" +) + +type signVerifyValidCase struct { + Indices []int `json:"key_indices"` + + NonceIndices []int `json:"nonce_indices"` + + AggNonceIndex int `json:"aggnonce_index"` + + MsgIndex int `json:"msg_index"` + + SignerIndex int `json:"signer_index"` + + Expected string `json:"expected"` +} + +type signErrorCase struct { + Indices []int `json:"key_indices"` + + AggNonceIndex int `json:"aggnonce_index"` + + MsgIndex int `json:"msg_index"` + + SecNonceIndex int `json:"secnonce_index"` + + Comment string `json:"comment"` +} + +type verifyFailCase struct { + Sig string `json:"sig"` + + Indices []int `json:"key_indices"` + + NonceIndices []int `json:"nonce_indices"` + + MsgIndex int `json:"msg_index"` + + SignerIndex int `json:"signer_index"` + + Comment string `json:"comment"` +} + +type verifyErrorCase struct { + Sig string `json:"sig"` + + Indices []int `json:"key_indices"` + + NonceIndices []int `json:"nonce_indices"` + + MsgIndex int `json:"msg_index"` + + SignerIndex int `json:"signer_index"` + + Comment string `json:"comment"` +} + +type signVerifyTestVectors struct { + PrivKey string `json:"sk"` + + PubKeys []string `json:"pubkeys"` + + PrivNonces []string `json:"secnonces"` + + PubNonces []string `json:"pnonces"` + + AggNonces []string `json:"aggnonces"` + + Msgs []string `json:"msgs"` + + ValidCases []signVerifyValidCase `json:"valid_test_cases"` + + SignErrorCases []signErrorCase `json:"sign_error_test_cases"` + + VerifyFailCases []verifyFailCase `json:"verify_fail_test_cases"` + + VerifyErrorCases []verifyErrorCase `json:"verify_error_test_cases"` +} + +// TestMusig2SignVerify tests that we pass the musig2 verification tests. +func TestMusig2SignVerify(t *testing.T) { + t.Parallel() + + testVectorPath := path.Join( + testVectorBaseDir, signVerifyTestVectorFileName, + ) + testVectorBytes, err := os.ReadFile(testVectorPath) + require.NoError(t, err) + + var testCases signVerifyTestVectors + require.NoError(t, json.Unmarshal(testVectorBytes, &testCases)) + + privKey, _ := btcec.PrivKeyFromBytes(mustParseHex(testCases.PrivKey)) + + for i, testCase := range testCases.ValidCases { + testCase := testCase + + testName := fmt.Sprintf("valid_case_%v", i) + t.Run(testName, func(t *testing.T) { + pubKeys, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + require.NoError(t, err) + + pubNonces := pubNoncesFromIndices( + t, testCase.NonceIndices, testCases.PubNonces, + ) + + combinedNonce, err := AggregateNonces(pubNonces) + require.NoError(t, err) + + var msg [32]byte + copy(msg[:], mustParseHex(testCases.Msgs[testCase.MsgIndex])) + + var secNonce [SecNonceSize]byte + copy(secNonce[:], mustParseHex(testCases.PrivNonces[0])) + + partialSig, err := Sign( + secNonce, privKey, combinedNonce, pubKeys, + msg, + ) + + var partialSigBytes [32]byte + partialSig.S.PutBytesUnchecked(partialSigBytes[:]) + + require.Equal( + t, hex.EncodeToString(partialSigBytes[:]), + hex.EncodeToString(mustParseHex(testCase.Expected)), + ) + }) + } + + for _, testCase := range testCases.SignErrorCases { + testCase := testCase + + testName := fmt.Sprintf("invalid_case_%v", + strings.ToLower(testCase.Comment)) + + t.Run(testName, func(t *testing.T) { + pubKeys, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + if err != nil { + require.ErrorIs(t, err, secp.ErrPubKeyNotOnCurve) + return + } + + var aggNonce [PubNonceSize]byte + copy( + aggNonce[:], + mustParseHex( + testCases.AggNonces[testCase.AggNonceIndex], + ), + ) + + var msg [32]byte + copy(msg[:], mustParseHex(testCases.Msgs[testCase.MsgIndex])) + + var secNonce [SecNonceSize]byte + copy( + secNonce[:], + mustParseHex( + testCases.PrivNonces[testCase.SecNonceIndex], + ), + ) + + _, err = Sign( + secNonce, privKey, aggNonce, pubKeys, + msg, + ) + require.Error(t, err) + }) + } + + for _, testCase := range testCases.VerifyFailCases { + testCase := testCase + + testName := fmt.Sprintf("verify_fail_%v", + strings.ToLower(testCase.Comment)) + t.Run(testName, func(t *testing.T) { + pubKeys, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + require.NoError(t, err) + + pubNonces := pubNoncesFromIndices( + t, testCase.NonceIndices, testCases.PubNonces, + ) + + combinedNonce, err := AggregateNonces(pubNonces) + require.NoError(t, err) + + var msg [32]byte + copy( + msg[:], + mustParseHex(testCases.Msgs[testCase.MsgIndex]), + ) + + var secNonce [SecNonceSize]byte + copy(secNonce[:], mustParseHex(testCases.PrivNonces[0])) + + signerNonce := secNonceToPubNonce(secNonce) + + var partialSig PartialSignature + err = partialSig.Decode( + bytes.NewReader(mustParseHex(testCase.Sig)), + ) + if err != nil && strings.Contains(testCase.Comment, "group size") { + require.ErrorIs(t, err, ErrPartialSigInvalid) + } + + err = verifyPartialSig( + &partialSig, signerNonce, combinedNonce, + pubKeys, privKey.PubKey().SerializeCompressed(), + msg, + ) + require.Error(t, err) + }) + } + + for _, testCase := range testCases.VerifyErrorCases { + testCase := testCase + + testName := fmt.Sprintf("verify_error_%v", + strings.ToLower(testCase.Comment)) + t.Run(testName, func(t *testing.T) { + switch testCase.Comment { + case "Invalid pubnonce": + pubNonces := pubNoncesFromIndices( + t, testCase.NonceIndices, testCases.PubNonces, + ) + _, err := AggregateNonces(pubNonces) + require.ErrorIs(t, err, secp.ErrPubKeyNotOnCurve) + + case "Invalid pubkey": + _, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + require.ErrorIs(t, err, secp.ErrPubKeyNotOnCurve) + + default: + t.Fatalf("unhandled case: %v", testCase.Comment) + } + }) + } + +} From 5d895bbea5fa186712f61c4cbcbfdccd6de1cda8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 20 Oct 2022 17:54:22 -0700 Subject: [PATCH 0730/1056] btcec/schnorr/musig2: add sig combine test vectors --- .../schnorr/musig2/data/sig_agg_vectors.json | 86 ++++++++++++ btcec/schnorr/musig2/sign.go | 96 ++++++++------ btcec/schnorr/musig2/sign_test.go | 124 ++++++++++++++++++ 3 files changed, 268 insertions(+), 38 deletions(-) create mode 100644 btcec/schnorr/musig2/data/sig_agg_vectors.json diff --git a/btcec/schnorr/musig2/data/sig_agg_vectors.json b/btcec/schnorr/musig2/data/sig_agg_vectors.json new file mode 100644 index 0000000000..7ae9444fd5 --- /dev/null +++ b/btcec/schnorr/musig2/data/sig_agg_vectors.json @@ -0,0 +1,86 @@ +{ + "pubkeys": [ + "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "02D2DC6F5DF7C56ACF38C7FA0AE7A759AE30E19B37359DFDE015872324C7EF6E05", + "03C7FB101D97FF930ACD0C6760852EF64E69083DE0B06AC6335724754BB4B0522C", + "02352433B21E7E05D3B452B81CAE566E06D2E003ECE16D1074AABA4289E0E3D581" + ], + "pnonces": [ + "0300A32F8548F59C533F55DB9754E3C0BA3C2544F085649FDCE42B8BD3F244C2CA0384449BED61004E8863452A38534E91875516C3CC543122CE2BE1F31845025588", + "03F66B072A869BC2A57D776D487151D707E82B4F1B885066A589858C1BF3871DB603ED391C9658AB6031A96ACBD5E2D9FEC465EFDC8C0D0B765C9B9F3579D520FB6F", + "03A5791CA078E278126EF457C25B5C835F7282C0A47BDBF464BA35C3769427D5CD034D40350F8A5590985E38AAEFC3C695DF671C2E5498E2B60C082C546E06ECAF78", + "020DE6382B8C0550E8174D5263B981224EBCFEF7706588B6936177FEB68E639B8C02BA5F18DDB3487AD087F63CEF7D7818AC8ECA3D6B736113FF36FB25D113F514F6", + "031883080513BB69B31367F9A7B5F4E81246C627060A7414B7F137FA8459F261990345445505F158EDCFDF0D4BF26E04E018C143BF76B5D457AE57DF06CA41371DF0", + "0300028E83123E7FAB1E1F230547CE8B96CC23F13197312972DE72AACBA98EF9870274C2D8566E9E021AA7E2DDDA01B52AE670E0742418F147610528B65ACDB4D0B3" + ], + "tweaks": [ + "B511DA492182A91B0FFB9A98020D55F260AE86D7ECBD0399C7383D59A5F2AF7C", + "A815FE049EE3C5AAB66310477FBC8BCCCAC2F3395F59F921C364ACD78A2F48DC", + "75448A87274B056468B977BE06EB1E9F657577B7320B0A3376EA51FD420D18A8" + ], + "psigs": [ + "7918521F42E5727FE2E82D802876E0C8844336FDA1B58C82696A55B0188C8B3D", + "599044037AE15C4A99FB94F022B48E7AB215BF703954EC0B83D0E06230476001", + "F05BE3CA783AD1FAF68C5059B43F859BFD4EBB0242459DF2C6BF013F4217F7E7", + "BF85B2A751066466C24A5E7FA6C90DBAADAC2DF1F0BB48546AE239E340437CEB", + "142076B034A7401123EFB07E2317DF819B86B3FFA17180DDD093997D018270D0", + "B7A0C7F5B325B7993925E56B60F53EF8198169F31E1AF7E62BBEF1C5DCD1BA22", + "C717ECA32C148CE8EB8882CD9656DF9C64929DCAE9AF798E381B1E888DDF0F8F", + "5988823E78488D8005311E16E5EA67AF70514CB44F5A5CD51FFA262BEEAA21CE", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" + ], + "msg": "599C67EA410D005B9DA90817CF03ED3B1C868E4DA4EDF00A5880B0082C237869", + "valid_test_cases": [ + { + "aggnonce": "02BC34CDF6FA1298D7B6A126812FAD0739005BC44E45C21276EEFE41AAF841C86F03F3562AED52243BB99F43D1677DB59F0FEFB961633997F7AC924B78FBD0B0334F", + "nonce_indices": [0, 1], + "key_indices": [0, 1], + "tweak_indices": [], + "is_xonly": [], + "psig_indices": [0, 1], + "expected": "CA3C28729659E50F829F55DC5DB1DE88A05D1702B4165B85F95B627FC57733F8D2A89622BDC6CECA7CE3C2704B2B6F433658F66DDB0A788DED3B361248D3EB3E" + }, + { + "aggnonce": "035538518B8043CF4EACD0E701A80657B741C0E6445EC1D6C6177964D22C642971030CFE657EC882F4E08E751B883A78AC1491B30FC86CB57AF2DFF012C2BE6DF1F2", + "nonce_indices": [0, 2], + "key_indices": [0, 2], + "tweak_indices": [], + "is_xonly": [], + "psig_indices": [2, 3], + "expected": "3997A11DFF76349532CF25E761365EA1D4F24B62EB23A12A9DAABD5976C3DB9FAFE19671C9413661B8D6AED95B089357F04C0C0D83B8460B71CEDC95B2253391" + }, + { + "aggnonce": "024366775E6FFBEBBB954225936BAED71A3884C7933B18225088D19E7AF12D8D5D028D79A520B347B793FFE897A7EB79A4366A3FDCDC652C243FAC3976B3D6DF8AB2", + "nonce_indices": [0, 3], + "key_indices": [0, 2], + "tweak_indices": [0], + "is_xonly": [false], + "psig_indices": [4, 5], + "expected": "5AF759C2839B7FEE59D31DAB800F82FC21258457773A3B1F69F5228C80CAD4317EA39AD756601030E4D4051B7C9A25AB4DE7CB39BED26E0A03A1B2ED5B747F7F" + }, + { + "aggnonce": "03B25098C6D0B72DC5717314AF26C126609B4776AA468553DD4354EE20B216B227027D242E9203499173A74E286C1F796F2711E171EE937706BBEA2F4DB10C4E6809", + "nonce_indices": [0, 4], + "key_indices": [0, 3], + "tweak_indices": [0, 1, 2], + "is_xonly": [true, false, true], + "psig_indices": [6, 7], + "expected": "B495A478F91D6E10BF08A156E46D9E62B4C5399C1AEDDA1A9D306F06AFB8A52F2C078FD6B50DDBC33BFFE583C3C1E3D0D5E52891E190101C70D2278BCA943457" + } + ], + "error_test_cases": [ + { + "aggnonce": "03B25098C6D0B72DC5717314AF26C126609B4776AA468553DD4354EE20B216B227027D242E9203499173A74E286C1F796F2711E171EE937706BBEA2F4DB10C4E6809", + "nonce_indices": [0, 4], + "key_indices": [0, 3], + "tweak_indices": [0, 1, 2], + "is_xonly": [true, false, true], + "psig_indices": [7, 8], + "error": { + "type": "invalid_contribution", + "signer": 1 + }, + "comment": "Partial signature is invalid because it exceeds group size" + } + ] +} diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 0b8130a1a5..2028571137 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -186,6 +186,58 @@ func WithBip86SignTweak() SignOption { } } +// computeSigningNonce calculates the final nonce used for signing. This will +// be the R value used in the final signature. +func computeSigningNonce(combinedNonce [PubNonceSize]byte, + combinedKey *btcec.PublicKey, msg [32]byte) ( + *btcec.JacobianPoint, *btcec.ModNScalar, error) { + + // Next we'll compute the value b, that blinds our second public + // nonce: + // * b = h(tag=NonceBlindTag, combinedNonce || combinedKey || m). + var ( + nonceMsgBuf bytes.Buffer + nonceBlinder btcec.ModNScalar + ) + nonceMsgBuf.Write(combinedNonce[:]) + nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey)) + nonceMsgBuf.Write(msg[:]) + nonceBlindHash := chainhash.TaggedHash( + NonceBlindTag, nonceMsgBuf.Bytes(), + ) + nonceBlinder.SetByteSlice(nonceBlindHash[:]) + + // Next, we'll parse the public nonces into R1 and R2. + r1J, err := btcec.ParseJacobian( + combinedNonce[:btcec.PubKeyBytesLenCompressed], + ) + if err != nil { + return nil, nil, err + } + r2J, err := btcec.ParseJacobian( + combinedNonce[btcec.PubKeyBytesLenCompressed:], + ) + if err != nil { + return nil, nil, err + } + + // With our nonce blinding value, we'll now combine both the public + // nonces, using the blinding factor to tweak the second nonce: + // * R = R_1 + b*R_2 + var nonce btcec.JacobianPoint + btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) + btcec.AddNonConst(&r1J, &r2J, &nonce) + + // If the combined nonce is the point at infinity, we'll use the + // generator point instead. + if nonce == infinityPoint { + G := btcec.Generator() + G.AsJacobian(&nonce) + } + + return &nonce, &nonceBlinder, nil +} + // Sign generates a musig2 partial signature given the passed key set, secret // nonce, public nonce, and private keys. This method returns an error if the // generated nonces are either too large, or end up mapping to the point at @@ -230,48 +282,16 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, return nil, err } - // Next we'll compute the value b, that blinds our second public - // nonce: - // * b = h(tag=NonceBlindTag, combinedNonce || combinedKey || m). - var ( - nonceMsgBuf bytes.Buffer - nonceBlinder btcec.ModNScalar - ) - nonceMsgBuf.Write(combinedNonce[:]) - nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey.FinalKey)) - nonceMsgBuf.Write(msg[:]) - nonceBlindHash := chainhash.TaggedHash( - NonceBlindTag, nonceMsgBuf.Bytes(), - ) - nonceBlinder.SetByteSlice(nonceBlindHash[:]) - - // Next, we'll parse the public nonces into R1 and R2. - r1J, err := btcec.ParseJacobian( - combinedNonce[:btcec.PubKeyBytesLenCompressed], - ) - if err != nil { - return nil, err - } - r2J, err := btcec.ParseJacobian( - combinedNonce[btcec.PubKeyBytesLenCompressed:], + // We'll now combine both the public nonces, using the blinding factor + // to tweak the second nonce: + // * R = R_1 + b*R_2 + nonce, nonceBlinder, err := computeSigningNonce( + combinedNonce, combinedKey.FinalKey, msg, ) if err != nil { return nil, err } - // With our nonce blinding value, we'll now combine both the public - // nonces, using the blinding factor to tweak the second nonce: - // * R = R_1 + b*R_2 - var nonce btcec.JacobianPoint - btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) - btcec.AddNonConst(&r1J, &r2J, &nonce) - - // If the combined nonce it eh point at infinity, then we'll bail out. - if nonce == infinityPoint { - G := btcec.Generator() - G.AsJacobian(&nonce) - } - // Next we'll parse out our two secret nonces, which we'll be using in // the core signing process below. var k1, k2 btcec.ModNScalar @@ -336,7 +356,7 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, // With mu constructed, we can finally generate our partial signature // as: s = (k1_1 + b*k_2 + e*a*d) mod n. s := new(btcec.ModNScalar) - s.Add(&k1).Add(k2.Mul(&nonceBlinder)).Add(e.Mul(a).Mul(&privKeyScalar)) + s.Add(&k1).Add(k2.Mul(nonceBlinder)).Add(e.Mul(a).Mul(&privKeyScalar)) sig := NewPartialSignature(s, nonceKey) diff --git a/btcec/schnorr/musig2/sign_test.go b/btcec/schnorr/musig2/sign_test.go index 07caad9c6e..a7f5d79d5d 100644 --- a/btcec/schnorr/musig2/sign_test.go +++ b/btcec/schnorr/musig2/sign_test.go @@ -19,6 +19,8 @@ import ( const ( signVerifyTestVectorFileName = "sign_verify_vectors.json" + + sigCombineTestVectorFileName = "sig_agg_vectors.json" ) type signVerifyValidCase struct { @@ -265,3 +267,125 @@ func TestMusig2SignVerify(t *testing.T) { } } + +type sigCombineValidCase struct { + AggNonce string `json:"aggnonce"` + + NonceIndices []int `json:"nonce_indices"` + + Indices []int `json:"key_indices"` + + TweakIndices []int `json:"tweak_indices"` + + IsXOnly []bool `json:"is_xonly"` + + PSigIndices []int `json:"psig_indices"` + + Expected string `json:"expected"` +} + +type sigCombineTestVectors struct { + PubKeys []string `json:"pubkeys"` + + PubNonces []string `json:"pnonces"` + + Tweaks []string `json:"tweaks"` + + Psigs []string `json:"psigs"` + + Msg string `json:"msg"` + + ValidCases []sigCombineValidCase `json:"valid_test_cases"` +} + +func pSigsFromIndicies(t *testing.T, sigs []string, indices []int) []*PartialSignature { + pSigs := make([]*PartialSignature, len(indices)) + for i, idx := range indices { + var pSig PartialSignature + err := pSig.Decode(bytes.NewReader(mustParseHex(sigs[idx]))) + require.NoError(t, err) + + pSigs[i] = &pSig + } + + return pSigs +} + +// TestMusig2SignCombine tests that we pass the musig2 sig combination tests. +func TestMusig2SignCombine(t *testing.T) { + t.Parallel() + + testVectorPath := path.Join( + testVectorBaseDir, sigCombineTestVectorFileName, + ) + testVectorBytes, err := os.ReadFile(testVectorPath) + require.NoError(t, err) + + var testCases sigCombineTestVectors + require.NoError(t, json.Unmarshal(testVectorBytes, &testCases)) + + var msg [32]byte + copy(msg[:], mustParseHex(testCases.Msg)) + + for i, testCase := range testCases.ValidCases { + testCase := testCase + + testName := fmt.Sprintf("valid_case_%v", i) + t.Run(testName, func(t *testing.T) { + pubKeys, err := keysFromIndices( + t, testCase.Indices, testCases.PubKeys, + ) + require.NoError(t, err) + + pubNonces := pubNoncesFromIndices( + t, testCase.NonceIndices, testCases.PubNonces, + ) + + partialSigs := pSigsFromIndicies( + t, testCases.Psigs, testCase.PSigIndices, + ) + + var ( + combineOpts []CombineOption + keyOpts []KeyAggOption + ) + if len(testCase.TweakIndices) > 0 { + tweaks := tweaksFromIndices( + t, testCase.TweakIndices, + testCases.Tweaks, testCase.IsXOnly, + ) + + combineOpts = append(combineOpts, WithTweakedCombine( + msg, pubKeys, tweaks, false, + )) + + keyOpts = append(keyOpts, WithKeyTweaks(tweaks...)) + } + + combinedKey, _, _, err := AggregateKeys( + pubKeys, false, keyOpts..., + ) + require.NoError(t, err) + + combinedNonce, err := AggregateNonces(pubNonces) + require.NoError(t, err) + + finalNonceJ, _, err := computeSigningNonce( + combinedNonce, combinedKey.FinalKey, msg, + ) + + finalNonceJ.ToAffine() + finalNonce := btcec.NewPublicKey( + &finalNonceJ.X, &finalNonceJ.Y, + ) + + combinedSig := CombineSigs( + finalNonce, partialSigs, combineOpts..., + ) + require.Equal(t, + strings.ToLower(testCase.Expected), + hex.EncodeToString(combinedSig.Serialize()), + ) + }) + } +} From 323871ff16408b4cb03c3f43faa3daa57541ee24 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 20 Oct 2022 17:54:49 -0700 Subject: [PATCH 0731/1056] btcec/musig2: remove old canned test vector code --- btcec/schnorr/musig2/musig2_test.go | 1060 +-------------------------- 1 file changed, 1 insertion(+), 1059 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 501ef41a38..6842e911d9 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -3,84 +3,20 @@ package musig2 import ( - "bytes" "crypto/sha256" "encoding/hex" - "encoding/json" "errors" - "flag" "fmt" - "io/ioutil" "sync" "testing" "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/decred/dcrd/dcrec/secp256k1/v4" ) -var ( - key1Bytes, _ = hex.DecodeString("F9308A019258C31049344F85F89D5229B53" + - "1C845836F99B08601F113BCE036F9") - key2Bytes, _ = hex.DecodeString("DFF1D77F2A671C5F36183726DB2341BE58F" + - "EAE1DA2DECED843240F7B502BA659") - key3Bytes, _ = hex.DecodeString("3590A94E768F8E1815C2F24B4D80A8E3149" + - "316C3518CE7B7AD338368D038CA66") - - invalidPk1, _ = hex.DecodeString("00000000000000000000000000000000" + - "00000000000000000000000000000005") - invalidPk2, _ = hex.DecodeString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + - "FFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30") - invalidTweak, _ = hex.DecodeString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" + - "BAAEDCE6AF48A03BBFD25E8CD0364141") - - testKeys = [][]byte{key1Bytes, key2Bytes, key3Bytes, invalidPk1, - invalidPk2} - - keyCombo1, _ = hex.DecodeString("E5830140512195D74C8307E39637CBE5FB73" + - "0EBEAB80EC514CF88A877CEEEE0B") - keyCombo2, _ = hex.DecodeString("D70CD69A2647F7390973DF48CBFA2CCC407B" + - "8B2D60B08C5F1641185C7998A290") - keyCombo3, _ = hex.DecodeString("81A8B093912C9E481408D09776CEFB48AEB8" + - "B65481B6BAAFB3C5810106717BEB") - keyCombo4, _ = hex.DecodeString("2EB18851887E7BDC5E830E89B19DDBC28078" + - "F1FA88AAD0AD01CA06FE4F80210B") - - testVectorBaseDir = "data" -) - -// getInfinityTweak returns a tweak that, when tweaking the Generator, triggers -// the ErrTweakedKeyIsInfinity error. -func getInfinityTweak() KeyTweakDesc { - generator := btcec.Generator() - - keySet := []*btcec.PublicKey{generator} - - keysHash := keyHashFingerprint(keySet, true) - uniqueKeyIndex := secondUniqueKeyIndex(keySet, true) - - n := &btcec.ModNScalar{} - - n.SetByteSlice(invalidTweak) - - coeff := aggregationCoefficient( - keySet, generator, keysHash, uniqueKeyIndex, - ).Negate().Add(n) - - return KeyTweakDesc{ - Tweak: coeff.Bytes(), - IsXOnly: false, - } -} - const ( - signTestVectorName = "sign_vectors.json" + testVectorBaseDir = "data" ) -var dumpJson = flag.Bool("dumpjson", false, "if true, a JSON version of the "+ - "test vectors will be written to the cwd") - func mustParseHex(str string) []byte { b, err := hex.DecodeString(str) if err != nil { @@ -90,664 +26,6 @@ func mustParseHex(str string) []byte { return b } -func parseKey(xHex string) *btcec.PublicKey { - xB, err := hex.DecodeString(xHex) - if err != nil { - panic(err) - } - - var x, y btcec.FieldVal - x.SetByteSlice(xB) - if !btcec.DecompressY(&x, false, &y) { - panic("x not on curve") - } - y.Normalize() - - return btcec.NewPublicKey(&x, &y) -} - -var ( - signSetPrivKey, _ = btcec.PrivKeyFromBytes( - mustParseHex("7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DF" + - "E8D76D7F2D1007671"), - ) - signSetPubKey = schnorr.SerializePubKey(signSetPrivKey.PubKey()) - - signTestMsg = mustParseHex("F95466D086770E689964664219266FE5ED215C92A" + - "E20BAB5C9D79ADDDDF3C0CF") - - signSetKey2 = mustParseHex("F9308A019258C31049344F85F89D5229B531C8458" + - "36F99B08601F113BCE036F9") - - signSetKey3 = mustParseHex("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA" + - "2DECED843240F7B502BA659") - - invalidSetKey1 = mustParseHex("00000000000000000000000000000000" + - "00000000000000000000000000000007") - - signExpected1 = mustParseHex("68537CC5234E505BD14061F8DA9E90C220A1818" + - "55FD8BDB7F127BB12403B4D3B") - signExpected2 = mustParseHex("2DF67BFFF18E3DE797E13C6475C963048138DAE" + - "C5CB20A357CECA7C8424295EA") - signExpected3 = mustParseHex("0D5B651E6DE34A29A12DE7A8B4183B4AE6A7F7F" + - "BE15CDCAFA4A3D1BCAABC7517") - - signExpected4 = mustParseHex("8D5E0407FB4756EEBCD86264C32D792EE36EEB6" + - "9E952BBB30B8E41BEBC4D22FA") - - signSetKeys = [][]byte{signSetPubKey, signSetKey2, signSetKey3, invalidPk1} - - aggregatedNonce = toPubNonceSlice(mustParseHex("028465FCF0BBDBCF443AA" + - "BCCE533D42B4B5A10966AC09A49655E8C42DAAB8FCD61037496A3CC86926" + - "D452CAFCFD55D25972CA1675D549310DE296BFF42F72EEEA8C9")) - verifyPnonce1 = mustParsePubNonce("0337C87821AFD50A8644D820A8F3E02E49" + - "9C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352A" + - "A9405D1428C15F4B75F04DAE642A95C2548480") - verifyPnonce2 = mustParsePubNonce("0279BE667EF9DCBBAC55A06295CE870B07" + - "029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE" + - "870B07029BFCDB2DCE28D959F2815B16F81798") - verifyPnonce3 = mustParsePubNonce("032DE2662628C90B03F5E720284EB52FF7" + - "D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1C" + - "A6BEB2090C93D930321071AD40B2F44E599046") - verifyPnonce4 = mustParsePubNonce("0237C87821AFD50A8644D820A8F3E02E49" + - "9C931865C2360FB43D0A0D20DAFE07EA0387BF891D2A6DEAEBADC909352A" + - "A9405D1428C15F4B75F04DAE642A95C2548480") - - tweak1 = KeyTweakDesc{ - Tweak: [32]byte{ - 0xE8, 0xF7, 0x91, 0xFF, 0x92, 0x25, 0xA2, 0xAF, - 0x01, 0x02, 0xAF, 0xFF, 0x4A, 0x9A, 0x72, 0x3D, - 0x96, 0x12, 0xA6, 0x82, 0xA2, 0x5E, 0xBE, 0x79, - 0x80, 0x2B, 0x26, 0x3C, 0xDF, 0xCD, 0x83, 0xBB, - }, - } - tweak2 = KeyTweakDesc{ - Tweak: [32]byte{ - 0xae, 0x2e, 0xa7, 0x97, 0xcc, 0xf, 0xe7, 0x2a, - 0xc5, 0xb9, 0x7b, 0x97, 0xf3, 0xc6, 0x95, 0x7d, - 0x7e, 0x41, 0x99, 0xa1, 0x67, 0xa5, 0x8e, 0xb0, - 0x8b, 0xca, 0xff, 0xda, 0x70, 0xac, 0x4, 0x55, - }, - } - tweak3 = KeyTweakDesc{ - Tweak: [32]byte{ - 0xf5, 0x2e, 0xcb, 0xc5, 0x65, 0xb3, 0xd8, 0xbe, - 0xa2, 0xdf, 0xd5, 0xb7, 0x5a, 0x4f, 0x45, 0x7e, - 0x54, 0x36, 0x98, 0x9, 0x32, 0x2e, 0x41, 0x20, - 0x83, 0x16, 0x26, 0xf2, 0x90, 0xfa, 0x87, 0xe0, - }, - } - tweak4 = KeyTweakDesc{ - Tweak: [32]byte{ - 0x19, 0x69, 0xad, 0x73, 0xcc, 0x17, 0x7f, 0xa0, - 0xb4, 0xfc, 0xed, 0x6d, 0xf1, 0xf7, 0xbf, 0x99, - 0x7, 0xe6, 0x65, 0xfd, 0xe9, 0xba, 0x19, 0x6a, - 0x74, 0xfe, 0xd0, 0xa3, 0xcf, 0x5a, 0xef, 0x9d, - }, - } -) - -func formatTweakParity(tweaks []KeyTweakDesc) string { - var s string - for _, tweak := range tweaks { - s += fmt.Sprintf("%v/", tweak.IsXOnly) - } - - // Snip off that last '/'. - s = s[:len(s)-1] - - return s -} - -func genTweakParity(tweak KeyTweakDesc, isXOnly bool) KeyTweakDesc { - tweak.IsXOnly = isXOnly - return tweak -} - -type jsonTweak struct { - Tweak string `json:"tweak"` - XOnly bool `json:"x_only"` -} - -type jsonTweakSignCase struct { - Keys []string `json:"keys"` - Tweaks []jsonTweak `json:"tweaks,omitempty"` - AggNonce string `json:"agg_nonce"` - - ExpectedSig string `json:"expected_sig"` - ExpectedError string `json:"expected_error` -} - -type jsonSignTestCase struct { - SecNonce string `json:"secret_nonce"` - SigningKey string `json:"signing_key"` - Msg string `json:"msg"` - - TestCases []jsonTweakSignCase `json:"test_cases"` -} - -// TestMuSig2SigningTestVectors tests that the musig2 implementation produces -// the same set of signatures. -func TestMuSig2SigningTestVectors(t *testing.T) { - t.Parallel() - - var jsonCases jsonSignTestCase - - jsonCases.SigningKey = hex.EncodeToString(signSetPrivKey.Serialize()) - jsonCases.Msg = hex.EncodeToString(signTestMsg) - - var secNonce [SecNonceSize]byte - copy(secNonce[:], mustParseHex("508B81A611F100A6B2B6B29656590898AF488B"+ - "CF2E1F55CF22E5CFB84421FE61")) - copy(secNonce[32:], mustParseHex("FA27FD49B1D50085B481285E1CA205D55C82"+ - "CC1B31FF5CD54A489829355901F7")) - - jsonCases.SecNonce = hex.EncodeToString(secNonce[:]) - - testCases := []struct { - keyOrder []int - aggNonce [66]byte - expectedPartialSig []byte - tweaks []KeyTweakDesc - expectedError error - }{ - // Vector 1 - { - keyOrder: []int{0, 1, 2}, - aggNonce: aggregatedNonce, - expectedPartialSig: signExpected1, - }, - - // Vector 2 - { - keyOrder: []int{1, 0, 2}, - aggNonce: aggregatedNonce, - expectedPartialSig: signExpected2, - }, - - // Vector 3 - { - keyOrder: []int{1, 2, 0}, - aggNonce: aggregatedNonce, - expectedPartialSig: signExpected3, - }, - // Vector 4 Both halves of aggregate nonce correspond to point at infinity - { - keyOrder: []int{0, 1}, - aggNonce: mustNonceAgg([][66]byte{verifyPnonce1, verifyPnonce4}), - expectedPartialSig: signExpected4, - }, - - // Vector 5: Signer 2 provided an invalid public key - { - keyOrder: []int{1, 0, 3}, - aggNonce: aggregatedNonce, - expectedError: secp256k1.ErrPubKeyNotOnCurve, - }, - - // Vector 6: Aggregate nonce is invalid due wrong tag, 0x04, - // in the first half. - { - - keyOrder: []int{1, 2, 0}, - aggNonce: toPubNonceSlice( - mustParseHex("048465FCF0BBDBCF443AABCCE533D42" + - "B4B5A10966AC09A49655E8C42DAAB8FCD610" + - "37496A3CC86926D452CAFCFD55D25972CA16" + - "75D549310DE296BFF42F72EEEA8C9")), - expectedError: secp256k1.ErrPubKeyInvalidFormat, - }, - - // Vector 7: Aggregate nonce is invalid because the second half - // does not correspond to an X coordinate. - { - - keyOrder: []int{1, 2, 0}, - aggNonce: toPubNonceSlice( - mustParseHex("028465FCF0BBDBCF443AABCCE533D42" + - "B4B5A10966AC09A49655E8C42DAAB8FCD610" + - "200000000000000000000000000000000000" + - "00000000000000000000000000009")), - expectedError: secp256k1.ErrPubKeyNotOnCurve, - }, - - // Vector 8: Aggregate nonce is invalid because the second half - // exceeds field size. - { - - keyOrder: []int{1, 2, 0}, - aggNonce: toPubNonceSlice( - mustParseHex("028465FCF0BBDBCF443AABCCE533D42" + - "B4B5A10966AC09A49655E8C42DAAB8FCD610" + - "2FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + - "FFFFFFFFFFFFFFFFFFFFEFFFFFC30")), - expectedError: secp256k1.ErrPubKeyXTooBig, - }, - - // A single x-only tweak. - { - keyOrder: []int{1, 2, 0}, - aggNonce: aggregatedNonce, - expectedPartialSig: mustParseHex("5e24c7496b565debc3b" + - "9639e6f1304a21597f9603d3ab05b4913641775e1375b"), - tweaks: []KeyTweakDesc{genTweakParity(tweak1, true)}, - }, - - // A single ordinary tweak. - { - keyOrder: []int{1, 2, 0}, - aggNonce: aggregatedNonce, - expectedPartialSig: mustParseHex("78408ddcab4813d1394c" + - "97d493ef1084195c1d4b52e63ecd7bc5991644e44ddd"), - tweaks: []KeyTweakDesc{genTweakParity(tweak1, false)}, - }, - - // An ordinary tweak then an x-only tweak. - { - keyOrder: []int{1, 2, 0}, - aggNonce: aggregatedNonce, - expectedPartialSig: mustParseHex("C3A829A81480E36EC3A" + - "B052964509A94EBF34210403D16B226A6F16EC85B7357"), - tweaks: []KeyTweakDesc{ - genTweakParity(tweak1, false), - genTweakParity(tweak2, true), - }, - }, - - // Four tweaks, in the order: x-only, ordinary, x-only, ordinary. - { - keyOrder: []int{1, 2, 0}, - aggNonce: aggregatedNonce, - expectedPartialSig: mustParseHex("8C4473C6A382BD3C4AD" + - "7BE59818DA5ED7CF8CEC4BC21996CFDA08BB4316B8BC7"), - tweaks: []KeyTweakDesc{ - genTweakParity(tweak1, true), - genTweakParity(tweak2, false), - genTweakParity(tweak3, true), - genTweakParity(tweak4, false), - }, - }, - } - - var msg [32]byte - copy(msg[:], signTestMsg) - - for _, testCase := range testCases { - testName := fmt.Sprintf("%v/tweak=%v", testCase.keyOrder, len(testCase.tweaks) != 0) - if len(testCase.tweaks) != 0 { - testName += fmt.Sprintf("/x_only=%v", formatTweakParity(testCase.tweaks)) - } - t.Run(testName, func(t *testing.T) { - keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) - for _, keyIndex := range testCase.keyOrder { - keyBytes := signSetKeys[keyIndex] - pub, err := schnorr.ParsePubKey(keyBytes) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatalf("unable to parse pubkeys: %v", err) - } - - keySet = append(keySet, pub) - } - - var opts []SignOption - if len(testCase.tweaks) != 0 { - opts = append( - opts, WithTweaks(testCase.tweaks...), - ) - } - - partialSig, err := Sign( - secNonce, signSetPrivKey, testCase.aggNonce, - keySet, msg, opts..., - ) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatalf("unable to generate partial sig: %v", err) - } - - var partialSigBytes [32]byte - partialSig.S.PutBytesUnchecked(partialSigBytes[:]) - - if !bytes.Equal(partialSigBytes[:], testCase.expectedPartialSig) { - t.Fatalf("sigs don't match: expected %x, got %x", - testCase.expectedPartialSig, partialSigBytes, - ) - } - - }) - - if *dumpJson { - var ( - strKeys []string - jsonError string - ) - - for _, keyIndex := range testCase.keyOrder { - keyBytes := signSetKeys[keyIndex] - strKeys = append(strKeys, hex.EncodeToString(keyBytes)) - } - - if testCase.expectedError != nil { - jsonError = testCase.expectedError.Error() - } - - tweakSignCase := jsonTweakSignCase{ - Keys: strKeys, - ExpectedSig: hex.EncodeToString(testCase.expectedPartialSig), - AggNonce: hex.EncodeToString(testCase.aggNonce[:]), - ExpectedError: jsonError, - } - - var jsonTweaks []jsonTweak - for _, tweak := range testCase.tweaks { - jsonTweaks = append( - jsonTweaks, - jsonTweak{ - Tweak: hex.EncodeToString(tweak.Tweak[:]), - XOnly: tweak.IsXOnly, - }) - } - tweakSignCase.Tweaks = jsonTweaks - - jsonCases.TestCases = append(jsonCases.TestCases, tweakSignCase) - } - } - - if *dumpJson { - jsonBytes, err := json.Marshal(jsonCases) - if err != nil { - t.Fatalf("unable to encode json: %v", err) - } - - var formattedJson bytes.Buffer - json.Indent(&formattedJson, jsonBytes, "", "\t") - err = ioutil.WriteFile( - signTestVectorName, formattedJson.Bytes(), 0644, - ) - if err != nil { - t.Fatalf("unable to write file: %v", err) - } - } -} - -func TestMusig2PartialSigVerifyTestVectors(t *testing.T) { - t.Parallel() - - testCases := []struct { - partialSig []byte - nonces [][66]byte - pubnonceIndex int - keyOrder []int - tweaks []KeyTweakDesc - expectedError error - }{ - // A single x-only tweak. - { - keyOrder: []int{1, 2, 0}, - nonces: [][66]byte{ - verifyPnonce2, - verifyPnonce3, - verifyPnonce1, - }, - pubnonceIndex: 2, - partialSig: mustParseHex("5e24c7496b565debc3b9639e" + - "6f1304a21597f9603d3ab05b4913641775e1375b"), - tweaks: []KeyTweakDesc{genTweakParity(tweak1, true)}, - }, - // A single ordinary tweak. - { - keyOrder: []int{1, 2, 0}, - nonces: [][66]byte{ - verifyPnonce2, - verifyPnonce3, - verifyPnonce1, - }, - pubnonceIndex: 2, - partialSig: mustParseHex("78408ddcab4813d1394c97d4" + - "93ef1084195c1d4b52e63ecd7bc5991644e44ddd"), - tweaks: []KeyTweakDesc{genTweakParity(tweak1, false)}, - }, - // An ordinary tweak then an x-only tweak. - { - keyOrder: []int{1, 2, 0}, - nonces: [][66]byte{ - verifyPnonce2, - verifyPnonce3, - verifyPnonce1, - }, - pubnonceIndex: 2, - partialSig: mustParseHex("C3A829A81480E36EC3AB0529" + - "64509A94EBF34210403D16B226A6F16EC85B7357"), - tweaks: []KeyTweakDesc{ - genTweakParity(tweak1, false), - genTweakParity(tweak2, true), - }, - }, - - // Four tweaks, in the order: x-only, ordinary, x-only, ordinary. - { - keyOrder: []int{1, 2, 0}, - nonces: [][66]byte{ - verifyPnonce2, - verifyPnonce3, - verifyPnonce1, - }, - pubnonceIndex: 2, - partialSig: mustParseHex("8C4473C6A382BD3C4AD7BE5" + - "9818DA5ED7CF8CEC4BC21996CFDA08BB4316B8BC7"), - tweaks: []KeyTweakDesc{ - genTweakParity(tweak1, true), - genTweakParity(tweak2, false), - genTweakParity(tweak3, true), - genTweakParity(tweak4, false), - }, - }, - // Vector 9. - { - - partialSig: signExpected1, - pubnonceIndex: 0, - keyOrder: []int{0, 1, 2}, - nonces: [][66]byte{ - verifyPnonce1, - verifyPnonce2, - verifyPnonce3, - }, - }, - // Vector 10. - { - - partialSig: signExpected2, - pubnonceIndex: 1, - keyOrder: []int{1, 0, 2}, - nonces: [][66]byte{ - verifyPnonce2, - verifyPnonce1, - verifyPnonce3, - }, - }, - // Vector 11. - { - - partialSig: signExpected3, - pubnonceIndex: 2, - keyOrder: []int{1, 2, 0}, - nonces: [][66]byte{ - verifyPnonce2, - verifyPnonce3, - verifyPnonce1, - }, - }, - // Vector 12: Both halves of aggregate nonce correspond to - // point at infinity. - { - - partialSig: signExpected4, - pubnonceIndex: 0, - keyOrder: []int{0, 1}, - nonces: [][66]byte{ - verifyPnonce1, - verifyPnonce4, - }, - }, - // Vector 13: Wrong signature (which is equal to the negation - // of valid signature expected[0]). - { - - partialSig: mustParseHex("97AC833ADCB1AFA42EBF9E0" + - "725616F3C9A0D5B614F6FE283CEAAA37A8FFAF406"), - pubnonceIndex: 0, - keyOrder: []int{0, 1, 2}, - nonces: [][66]byte{ - verifyPnonce1, - verifyPnonce2, - verifyPnonce3, - }, - expectedError: ErrPartialSigInvalid, - }, - // Vector 12: Wrong signer. - { - - partialSig: signExpected1, - pubnonceIndex: 1, - keyOrder: []int{0, 1, 2}, - nonces: [][66]byte{ - verifyPnonce1, - verifyPnonce2, - verifyPnonce3, - }, - expectedError: ErrPartialSigInvalid, - }, - // Vector 13: Signature exceeds group size. - { - - partialSig: mustParseHex("FFFFFFFFFFFFFFFFFFFFFFFF" + - "FFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"), - pubnonceIndex: 0, - keyOrder: []int{0, 1, 2}, - nonces: [][66]byte{ - verifyPnonce1, - verifyPnonce2, - verifyPnonce3, - }, - expectedError: ErrPartialSigInvalid, - }, - // Vector 14: Invalid pubnonce. - { - - partialSig: signExpected1, - pubnonceIndex: 0, - keyOrder: []int{0, 1, 2}, - nonces: [][66]byte{ - canParsePubNonce("020000000000000000000000000" + - "000000000000000000000000000000000000009"), - verifyPnonce2, - verifyPnonce3, - }, - expectedError: secp256k1.ErrPubKeyNotOnCurve, - }, - // Vector 15: Invalid public key. - { - - partialSig: signExpected1, - pubnonceIndex: 0, - keyOrder: []int{3, 1, 2}, - nonces: [][66]byte{ - verifyPnonce1, - verifyPnonce2, - verifyPnonce3, - }, - expectedError: secp256k1.ErrPubKeyNotOnCurve, - }, - } - - for _, testCase := range testCases { - - // todo find name - testName := fmt.Sprintf("%v/tweak=%v", testCase.pubnonceIndex, testCase.keyOrder) - - t.Run(testName, func(t *testing.T) { - - combinedNonce, err := AggregateNonces(testCase.nonces) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatalf("unable to aggregate nonces %v", err) - } - - keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) - for _, keyIndex := range testCase.keyOrder { - keyBytes := signSetKeys[keyIndex] - pub, err := schnorr.ParsePubKey(keyBytes) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatalf("unable to parse pubkeys: %v", err) - } - - keySet = append(keySet, pub) - } - - ps := &PartialSignature{} - err = ps.Decode(bytes.NewBuffer(testCase.partialSig)) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatal(err) - } - - var opts []SignOption - if len(testCase.tweaks) != 0 { - opts = append( - opts, WithTweaks(testCase.tweaks...), - ) - } - - err = verifyPartialSig( - ps, - testCase.nonces[testCase.pubnonceIndex], - combinedNonce, - keySet, - signSetKeys[testCase.keyOrder[testCase.pubnonceIndex]], - to32ByteSlice(signTestMsg), - opts..., - ) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatalf("unable to aggregate nonces %v", err) - } - }) - } -} - type signer struct { privKey *btcec.PrivateKey pubKey *btcec.PublicKey @@ -1166,339 +444,3 @@ func (mr *memsetRandReader) Read(buf []byte) (n int, err error) { } return len(buf), nil } - -var ( - combineSigKey0 = mustParseHex("487D1B83B41B4CBBD07A111F1BBC7BDC8864CF" + - "EF5DBF96E46E51C68399B0BEF6") - combineSigKey1 = mustParseHex("4795C22501BF534BC478FF619407A7EC9E8D88" + - "83646D69BD43A0728944EA802F") - combineSigKey2 = mustParseHex("0F5BE837F3AB7E7FEFF1FAA44D673C2017206A" + - "E836D2C7893CDE4ACB7D55EDEB") - combineSigKey3 = mustParseHex("0FD453223E444FCA91FB5310990AE8A0C5DAA1" + - "4D2A4C8944E1C0BC80C30DF682") - - combineSigKeys = [][]byte{combineSigKey0, combineSigKey1, - combineSigKey2, combineSigKey3} - - combineSigAggNonce0 = mustParsePubNonce("024FA51009A56F0D6DF737131CE1" + - "FBBD833797AF3B4FE6BF0D68F4D49F68B0947E0248FB3BB9191F0CFF1380" + - "6A3A2F1429C23012654FCE4E41F7EC9169EAA6056B21") - combineSigAggNonce1 = mustParsePubNonce("023B11E63E2460E5E0F1561BB700" + - "FEA95B991DD9CA2CBBE92A3960641FA7469F6702CA4CD38375FE8BEB857C" + - "770807225BFC7D712F42BA896B83FC71138E56409B21") - combineSigAggNonce2 = mustParsePubNonce("03F98BEAA32B8A38FE3797C4E813" + - "DC9CE05ADBE32200035FB37EB0A030B735E9B6030E6118EC98EA2BA7A358" + - "C2E38E7E13E63681EEB683E067061BF7D52DCF08E615") - combineSigAggNonce3 = mustParsePubNonce("026491FBCFD47148043A0F7310E6" + - "2EF898C10F2D0376EE6B232EAAD36F3C2E29E303020CB17D168908E2904D" + - "E2EB571CD232CA805A6981D0F86CDBBD2F12BD91F6D0") - - psig0 = mustParseHex("E5C1CBD6E7E89FE9EE30D5F3B6D06B9C218846E4A1DEF4E" + - "E851410D51ABBD850") - psig1 = mustParseHex("9BC470F7F1C9BC848BDF179B0023282FFEF40908E0EF884" + - "59784A4355FC86D0C") - psig2 = mustParseHex("D5D8A09929BA264B2F5DF15ACA1CF2DEFA47C048DF0C323" + - "2E965FFE2F2831B1D") - psig3 = mustParseHex("A915197503C1051EA77DC91F01C3A0E60BFD64473BD536C" + - "B613F9645BD61C843") - psig4 = mustParseHex("99A144D7076A128022134E036B8BDF33811F7EAED9A1E48" + - "549B46D8A63D64DC9") - psig5 = mustParseHex("716A72A0C1E531EBB4555C8E29FD35C796F4F231C3B0391" + - "93D7E8D7AEFBDF5F7") - psig6 = mustParseHex("06B6DD04BC0F1EF740916730AD7DAC794255B1612217197" + - "65BDE9686A26633DC") - psig7 = mustParseHex("BF6D85D4930062726EBC6EBB184AFD68DBB3FED159C5019" + - "89690A62600D6FBAB") - - combineSigExpected0 = mustParseHex("4006D4D069F3B51E968762FF8074153E2" + - "78E5BCD221AABE0743CA001B77E79F581863CCED9B25C6E7A0FED8EB6F39" + - "3CD65CD7306D385DCF85CC6567DAA4E041B") - combineSigExpected1 = mustParseHex("98BCD40DFD94B47A3DA37D7B78EB6CCE8" + - "ABEACA23C3ADE6F4678902410EB35C67EEDBA0E2D7B2B69D6DBBA79CBE09" + - "3C64B9647A96B98C8C28AD3379BDFAEA21F") - combineSigExpected2 = mustParseHex("3741FEDCCDD7508B58DCB9A780FF5D974" + - "52EC8C0448D8C97004EA7175C14F2007A54D1DE356EBA6719278436EF111" + - "DFA8F1B832368371B9B7A25001709039679") - combineSigExpected3 = mustParseHex("F4B3DA3CF0D0F7CF5C1840593BF1A1A41" + - "5DA341619AE848F2210696DC8C7512540962C84EF7F0CEC491065F2D5772" + - "13CF10E8A63D153297361B3B172BE27B61F") - - combineSigTweak0 = mustParseHex32("B511DA492182A91B0FFB9A98020D55F260" + - "AE86D7ECBD0399C7383D59A5F2AF7C") - combineSigTweak1 = mustParseHex32("A815FE049EE3C5AAB66310477FBC8BCCCA" + - "C2F3395F59F921C364ACD78A2F48DC") - combineSigTweak2 = mustParseHex32("75448A87274B056468B977BE06EB1E9F65" + - "7577B7320B0A3376EA51FD420D18A8") - tweak0False = KeyTweakDesc{ - Tweak: combineSigTweak0, - IsXOnly: false, - } - tweak0True = KeyTweakDesc{ - Tweak: combineSigTweak0, - IsXOnly: true, - } - tweak1False = KeyTweakDesc{ - Tweak: combineSigTweak1, - IsXOnly: false, - } - tweak2True = KeyTweakDesc{ - Tweak: combineSigTweak2, - IsXOnly: true, - } - combineSigsMsg = mustParseHex32("599C67EA410D005B9DA90817CF03ED3B1C86" + - "8E4DA4EDF00A5880B0082C237869") -) - -func TestMusig2CombineSigsTestVectors(t *testing.T) { - - testCases := []struct { - partialSigs [][]byte - aggNonce [66]byte - keyOrder []int - expected []byte - tweaks []KeyTweakDesc - expectedError error - }{ - // Vector 1 - { - partialSigs: [][]byte{psig0, psig1}, - aggNonce: combineSigAggNonce0, - keyOrder: []int{0, 1}, - expected: combineSigExpected0, - }, - // Vector 2 - { - partialSigs: [][]byte{psig2, psig3}, - aggNonce: combineSigAggNonce1, - keyOrder: []int{0, 2}, - expected: combineSigExpected1, - }, - // Vector 3 - { - partialSigs: [][]byte{psig4, psig5}, - aggNonce: combineSigAggNonce2, - keyOrder: []int{0, 2}, - expected: combineSigExpected2, - tweaks: []KeyTweakDesc{tweak0False}, - }, - // Vector 4 - { - partialSigs: [][]byte{psig6, psig7}, - aggNonce: combineSigAggNonce3, - keyOrder: []int{0, 3}, - expected: combineSigExpected3, - tweaks: []KeyTweakDesc{ - tweak0True, - tweak1False, - tweak2True, - }, - }, - // Vector 5: Partial signature is invalid because it exceeds group size - { - partialSigs: [][]byte{ - psig7, - mustParseHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + - "EBAAEDCE6AF48A03BBFD25E8CD0364141"), - }, - aggNonce: combineSigAggNonce3, - expectedError: ErrPartialSigInvalid, - }, - } - - for _, testCase := range testCases { - var pSigs []*PartialSignature - for _, partialSig := range testCase.partialSigs { - pSig := &PartialSignature{} - err := pSig.Decode(bytes.NewReader(partialSig)) - - switch { - case testCase.expectedError != nil && - errors.Is(err, testCase.expectedError): - - return - case err != nil: - t.Fatal(err) - } - - pSigs = append(pSigs, pSig) - } - - keySet := make([]*btcec.PublicKey, 0, len(testCase.keyOrder)) - for _, keyIndex := range testCase.keyOrder { - keyBytes := combineSigKeys[keyIndex] - pub, err := schnorr.ParsePubKey(keyBytes) - if err != nil { - t.Fatalf("unable to parse pubkeys: %v", err) - } - keySet = append(keySet, pub) - } - - uniqueKeyIndex := secondUniqueKeyIndex(keySet, false) - aggOpts := []KeyAggOption{ - WithUniqueKeyIndex(uniqueKeyIndex), - } - if len(testCase.tweaks) > 0 { - aggOpts = append(aggOpts, WithKeyTweaks(testCase.tweaks...)) - } - - combinedKey, _, _, err := AggregateKeys( - keySet, false, aggOpts..., - ) - if err != nil { - t.Fatal(err) - } - - aggPubkey, err := aggNonceToPubkey( - testCase.aggNonce, combinedKey, combineSigsMsg, - ) - if err != nil { - t.Fatal(err) - } - - var opts []CombineOption - if len(testCase.tweaks) > 0 { - opts = append(opts, WithTweakedCombine( - combineSigsMsg, keySet, testCase.tweaks, false, - )) - } - - sig := CombineSigs(aggPubkey, pSigs, opts...) - expectedSig, err := schnorr.ParseSignature(testCase.expected) - if err != nil { - t.Fatal(err) - } - - if !bytes.Equal(sig.Serialize(), expectedSig.Serialize()) { - t.Fatalf("sigs not expected %x \n got %x", expectedSig.Serialize(), sig.Serialize()) - } - - if !sig.Verify(combineSigsMsg[:], combinedKey.FinalKey) { - t.Fatal("sig not valid for m") - } - } -} - -// aggNonceToPubkey gets a nonce as a public key for the TestMusig2CombineSigsTestVectors -// test. -// TODO(sputn1ck): build into intermediate routine. -func aggNonceToPubkey(combinedNonce [66]byte, combinedKey *AggregateKey, - msg [32]byte) (*btcec.PublicKey, error) { - - // b = int_from_bytes(tagged_hash('MuSig/noncecoef', aggnonce + bytes_from_point(Q) + msg)) % n - var ( - nonceMsgBuf bytes.Buffer - nonceBlinder btcec.ModNScalar - ) - nonceMsgBuf.Write(combinedNonce[:]) - nonceMsgBuf.Write(schnorr.SerializePubKey(combinedKey.FinalKey)) - nonceMsgBuf.Write(msg[:]) - nonceBlindHash := chainhash.TaggedHash(NonceBlindTag, nonceMsgBuf.Bytes()) - nonceBlinder.SetByteSlice(nonceBlindHash[:]) - - r1, err := btcec.ParsePubKey( - combinedNonce[:btcec.PubKeyBytesLenCompressed], - ) - if err != nil { - return nil, err - } - - r2, err := btcec.ParsePubKey( - combinedNonce[btcec.PubKeyBytesLenCompressed:], - ) - if err != nil { - return nil, err - } - - var nonce, r1J, r2J btcec.JacobianPoint - r1.AsJacobian(&r1J) - r2.AsJacobian(&r2J) - - // With our nonce blinding value, we'll now combine both the public - // nonces, using the blinding factor to tweak the second nonce: - // * R = R_1 + b*R_2 - btcec.ScalarMultNonConst(&nonceBlinder, &r2J, &r2J) - btcec.AddNonConst(&r1J, &r2J, &nonce) - - nonce.ToAffine() - - return btcec.NewPublicKey( - &nonce.X, &nonce.Y, - ), nil - -} - -func mustNonceAgg(nonces [][66]byte) [66]byte { - aggNonce, err := AggregateNonces(nonces) - if err != nil { - panic("can't aggregate nonces") - } - return aggNonce -} - -func memsetLoop(a []byte, v uint8) { - for i := range a { - a[i] = byte(v) - } -} - -func to32ByteSlice(input []byte) [32]byte { - if len(input) != 32 { - panic("input byte slice has invalid length") - } - var output [32]byte - copy(output[:], input) - return output -} - -func toPubNonceSlice(input []byte) [PubNonceSize]byte { - var output [PubNonceSize]byte - copy(output[:], input) - - return output -} - -func getGBytes() []byte { - return btcec.Generator().SerializeCompressed() -} - -func getNegGBytes() []byte { - pk := getGBytes() - pk[0] = 0x3 - - return pk -} - -func getInfinityBytes() []byte { - return make([]byte, 33) -} - -func mustParseHex32(str string) [32]byte { - b, err := hex.DecodeString(str) - if err != nil { - panic(fmt.Errorf("unable to parse hex: %v", err)) - } - if len(b) != 32 { - panic(fmt.Errorf("not a 32 byte slice: %v", err)) - } - - return to32ByteSlice(b) -} - -func mustParsePubNonce(str string) [PubNonceSize]byte { - b, err := hex.DecodeString(str) - if err != nil { - panic(fmt.Errorf("unable to parse hex: %v", err)) - } - if len(b) != PubNonceSize { - panic(fmt.Errorf("not a public nonce: %v", err)) - } - return toPubNonceSlice(b) -} - -func canParsePubNonce(str string) [PubNonceSize]byte { - b, err := hex.DecodeString(str) - if err != nil { - panic(fmt.Errorf("unable to parse hex: %v", err)) - } - return toPubNonceSlice(b) -} From eef9fbc5c9f517d8bc03d79ce96854e151d735cf Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 25 Oct 2022 16:33:21 -0700 Subject: [PATCH 0732/1056] btcec/schnorr/musig2: always pass in priv key for early nonce gen This helps mitigate an issue discovered in musig2 under certain scenarios: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-October/021000.html. --- btcec/schnorr/musig2/context.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index adbedb8bf3..0dfc6f38af 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -239,7 +239,9 @@ func NewContext(signingKey *btcec.PrivateKey, shouldSort bool, // are known. if opts.earlyNonce { var err error - ctx.sessionNonce, err = GenNonces() + ctx.sessionNonce, err = GenNonces( + WithNonceSecretKeyAux(signingKey), + ) if err != nil { return nil, err } From fc47c31b458b52a059a178c076b1499e200d4b34 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 27 Oct 2022 16:19:32 -0700 Subject: [PATCH 0733/1056] txscript: modify TweakTaprootPrivKey to operate on private key copy In this commit, we fix an inadvertent mutation bug that would at times cause the private key passed into the tweak function to actually be *modified* in place. We fix this by accepting the value instead of a pointer. The actual private key struct itself contains no pointer fields, so this is effectively a deep copy via dereference. We also add a new unit test that fails w/o this change, to show that the private key was indeed being modified. --- txscript/sign.go | 2 +- txscript/taproot.go | 4 ++-- txscript/taproot_test.go | 42 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/txscript/sign.go b/txscript/sign.go index fc89312f20..f3001d8939 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -82,7 +82,7 @@ func RawTxInTaprootSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, // Before we sign the sighash, we'll need to apply the taptweak to the // private key based on the tapScriptRootHash. - privKeyTweak := TweakTaprootPrivKey(key, tapScriptRootHash) + privKeyTweak := TweakTaprootPrivKey(*key, tapScriptRootHash) // With the sighash constructed, we can sign it with the specified // private key. diff --git a/txscript/taproot.go b/txscript/taproot.go index 2e452f92d7..cd73aff4d8 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -296,12 +296,12 @@ func ComputeTaprootKeyNoScript(internalKey *btcec.PublicKey) *btcec.PublicKey { // but on the private key instead. The final key is derived as: privKey + // h_tapTweak(internalKey || merkleRoot) % N, where N is the order of the // secp256k1 curve, and merkleRoot is the root hash of the tapscript tree. -func TweakTaprootPrivKey(privKey *btcec.PrivateKey, +func TweakTaprootPrivKey(privKey btcec.PrivateKey, scriptRoot []byte) *btcec.PrivateKey { // If the corresponding public key has an odd y coordinate, then we'll // negate the private key as specified in BIP 341. - privKeyScalar := &privKey.Key + privKeyScalar := privKey.Key pubKeyBytes := privKey.PubKey().SerializeCompressed() if pubKeyBytes[0] == secp.PubKeyFormatCompressedOdd { privKeyScalar.Negate() diff --git a/txscript/taproot_test.go b/txscript/taproot_test.go index 178405b526..01b3780e9c 100644 --- a/txscript/taproot_test.go +++ b/txscript/taproot_test.go @@ -166,8 +166,8 @@ func TestControlBlockParsing(t *testing.T) { // key, then generating a public key from that. This test a quickcheck test to // assert the following invariant: // -// * taproot_tweak_pubkey(pubkey_gen(seckey), h)[1] == -// pubkey_gen(taproot_tweak_seckey(seckey, h)) +// - taproot_tweak_pubkey(pubkey_gen(seckey), h)[1] == +// pubkey_gen(taproot_tweak_seckey(seckey, h)) func TestTaprootScriptSpendTweak(t *testing.T) { t.Parallel() @@ -186,7 +186,7 @@ func TestTaprootScriptSpendTweak(t *testing.T) { tweakedPub := ComputeTaprootOutputKey(privKey.PubKey(), x[:]) // Now we'll generate the corresponding tweaked private key. - tweakedPriv := TweakTaprootPrivKey(privKey, x[:]) + tweakedPriv := TweakTaprootPrivKey(*privKey, x[:]) // The public key for this private key should be the same as // the tweaked public key we generate above. @@ -204,6 +204,42 @@ func TestTaprootScriptSpendTweak(t *testing.T) { } +// TestTaprootTweakNoMutation tests that the underlying private key passed into +// TweakTaprootPrivKey is never mutated. +func TestTaprootTweakNoMutation(t *testing.T) { + t.Parallel() + + // Assert that given a random tweak, and a random private key, that if + // we tweak the private key it remains unaffected. + f := func(privBytes, tweak [32]byte) bool { + privKey, _ := btcec.PrivKeyFromBytes(privBytes[:]) + + // Now we'll generate the corresponding tweaked private key. + tweakedPriv := TweakTaprootPrivKey(*privKey, tweak[:]) + + // The tweaked private key and the original private key should + // NOT be the same. + if *privKey == *tweakedPriv { + t.Logf("private key was mutated") + return false + } + + // We shuold be able to re-derive the private key from raw + // bytes and have that match up again. + privKeyCopy, _ := btcec.PrivKeyFromBytes(privBytes[:]) + if *privKey != *privKeyCopy { + t.Logf("private doesn't match") + return false + } + + return true + } + + if err := quick.Check(f, nil); err != nil { + t.Fatalf("private key modified: %v", err) + } +} + // TestTaprootConstructKeyPath tests the key spend only taproot construction. func TestTaprootConstructKeyPath(t *testing.T) { checkPath := func(branch uint32, expectedAddresses []string) { From 6a03eb372bb89c7f8e1ff6332def8fdf86919e08 Mon Sep 17 00:00:00 2001 From: Elle Mouton Date: Tue, 1 Nov 2022 13:42:09 +0200 Subject: [PATCH 0734/1056] wire: increase max witness items per input --- wire/msgtx.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index c289cd7e0b..80a5fcc674 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -96,11 +96,13 @@ const ( // maxWitnessItemsPerInput is the maximum number of witness items to // be read for the witness data for a single TxIn. This number is - // derived using a possble lower bound for the encoding of a witness + // derived using a possible lower bound for the encoding of a witness // item: 1 byte for length + 1 byte for the witness item itself, or two // bytes. This value is then divided by the currently allowed maximum - // "cost" for a transaction. - maxWitnessItemsPerInput = 500000 + // "cost" for a transaction. We use this for an upper bound for the + // buffer and consensus makes sure that the weight of a transaction + // cannot be more than 4000000. + maxWitnessItemsPerInput = 4_000_000 // maxWitnessItemSize is the maximum allowed size for an item within // an input's witness data. This value is bounded by the largest From 4f0ae90c88ada974ece636b5faf6651e059dda7d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 1 Nov 2022 13:02:18 +0100 Subject: [PATCH 0735/1056] build: bump version to v0.23.3 --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 7d321c5fdd..19af5b8bd0 100644 --- a/version.go +++ b/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 23 - appPatch uint = 2 + appPatch uint = 3 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. From f6279eabbe36622718e008c5ca5918651cc35a24 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Tue, 1 Nov 2022 23:37:16 +0100 Subject: [PATCH 0736/1056] btcec/schnorr/musig2: add pk option to NonceGen This commit adds the pk option to NonceGen and makes it mandatory. Reference: https://github.com/jonasnick/bips/pull/74/commits/a89f8578e1d9cbee4af4009d824e277d99c84733 --- btcec/schnorr/musig2/bench_test.go | 4 +- btcec/schnorr/musig2/context.go | 2 + .../musig2/data/nonce_gen_vectors.json | 14 +- .../schnorr/musig2/data/sig_agg_vectors.json | 155 +++++++++++++----- btcec/schnorr/musig2/nonces.go | 43 ++++- btcec/schnorr/musig2/nonces_test.go | 2 + 6 files changed, 161 insertions(+), 59 deletions(-) diff --git a/btcec/schnorr/musig2/bench_test.go b/btcec/schnorr/musig2/bench_test.go index 70d7e931ce..751ee737b8 100644 --- a/btcec/schnorr/musig2/bench_test.go +++ b/btcec/schnorr/musig2/bench_test.go @@ -52,7 +52,7 @@ func genSigner(t *testing.B) signer { t.Fatalf("unable to gen key: %v", err) } - nonces, err := GenNonces() + nonces, err := GenNonces(WithPublicKey(pubKey)) if err != nil { t.Fatalf("unable to gen nonces: %v", err) } @@ -185,7 +185,7 @@ func BenchmarkPartialVerify(b *testing.B) { for i := 0; i < b.N; i++ { ok = sig.Verify( signers[0].nonces.PubNonce, combinedNonce, - keys, pubKey, msg, + keys, pubKey, msg, signOpts..., ) if !ok { b.Fatalf("generated invalid sig!") diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 0dfc6f38af..44ed69c8ee 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -240,6 +240,7 @@ func NewContext(signingKey *btcec.PrivateKey, shouldSort bool, if opts.earlyNonce { var err error ctx.sessionNonce, err = GenNonces( + WithPublicKey(ctx.pubKey), WithNonceSecretKeyAux(signingKey), ) if err != nil { @@ -483,6 +484,7 @@ func (c *Context) NewSession(options ...SessionOption) (*Session, error) { // in some auxiliary information to strengthen the nonce // generated. localNonces, err = GenNonces( + WithPublicKey(c.pubKey), WithNonceSecretKeyAux(c.signingKey), WithNonceCombinedKeyAux(c.combinedKey.FinalKey), ) diff --git a/btcec/schnorr/musig2/data/nonce_gen_vectors.json b/btcec/schnorr/musig2/data/nonce_gen_vectors.json index 9727cfe93b..e8fc1388cf 100644 --- a/btcec/schnorr/musig2/data/nonce_gen_vectors.json +++ b/btcec/schnorr/musig2/data/nonce_gen_vectors.json @@ -3,34 +3,38 @@ { "rand_": "0000000000000000000000000000000000000000000000000000000000000000", "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "pk": "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", "msg": "0101010101010101010101010101010101010101010101010101010101010101", "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", - "expected": "BC6C683EBBCC39DCB3C29B3D010D2AAA7C86CFB562FC41ED9A460EE061013E75FB4AD2F0B816713269800D018803906D5481E00A940EAB4F4AC49B4A372EB0F4" + "expected": "227243DCB40EF2A13A981DB188FA433717B506BDFA14B1AE47D5DC027C9C3B9EF2370B2AD206E724243215137C86365699361126991E6FEC816845F837BDDAC3" }, { "rand_": "0000000000000000000000000000000000000000000000000000000000000000", "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "pk": "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", "msg": "", "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", - "expected": "AAC4BFD707F4953B4063851D7E4AAD5C59D5D0BFB0E71012788A85698B5ACF8F11834D5051928424BA501C8CD064F3F942F8D4A07D8A2ED79F153E4ABD9EBBE9" + "expected": "CD0F47FE471D6788FF3243F47345EA0A179AEF69476BE8348322EF39C2723318870C2065AFB52DEDF02BF4FDBF6D2F442E608692F50C2374C08FFFE57042A61C" }, { "rand_": "0000000000000000000000000000000000000000000000000000000000000000", "sk": "0202020202020202020202020202020202020202020202020202020202020202", + "pk": "024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766", "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", "msg": "2626262626262626262626262626262626262626262626262626262626262626262626262626", "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", - "expected": "DF54500DD2B503DBA3753C48A9D6B67E6C11EC4325EDD1DC256C7F75D6A85DBECA6D9857A6F3F292FB3B50DBCBF69FADB67B1CDDB0EA6EB693F6455C4C9088E1" + "expected": "011F8BC60EF061DEEF4D72A0A87200D9994B3F0CD9867910085C38D5366E3E6B9FF03BC0124E56B24069E91EC3F162378983F194E8BD0ED89BE3059649EAE262" }, { "rand_": "0000000000000000000000000000000000000000000000000000000000000000", "sk": null, + "pk": "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", "aggpk": null, "msg": null, "extra_in": null, - "expected": "7B3B5A002356471AF0E961DE2549C121BD0D48ABCEEDC6E034BDDF86AD3E0A187ECEE674CEF7364B0BC4BEEFB8B66CAD89F98DE2F8C5A5EAD5D1D1E4BD7D04CD" + "expected": "890E83616A3BC4640AB9B6374F21C81FF89CDDDBAFAA7475AE2A102A92E3EDB29FD7E874E23342813A60D9646948242646B7951CA046B4B36D7D6078506D3C94" } ] -} +} \ No newline at end of file diff --git a/btcec/schnorr/musig2/data/sig_agg_vectors.json b/btcec/schnorr/musig2/data/sig_agg_vectors.json index 7ae9444fd5..afe9eaf3f4 100644 --- a/btcec/schnorr/musig2/data/sig_agg_vectors.json +++ b/btcec/schnorr/musig2/data/sig_agg_vectors.json @@ -6,12 +6,12 @@ "02352433B21E7E05D3B452B81CAE566E06D2E003ECE16D1074AABA4289E0E3D581" ], "pnonces": [ - "0300A32F8548F59C533F55DB9754E3C0BA3C2544F085649FDCE42B8BD3F244C2CA0384449BED61004E8863452A38534E91875516C3CC543122CE2BE1F31845025588", - "03F66B072A869BC2A57D776D487151D707E82B4F1B885066A589858C1BF3871DB603ED391C9658AB6031A96ACBD5E2D9FEC465EFDC8C0D0B765C9B9F3579D520FB6F", - "03A5791CA078E278126EF457C25B5C835F7282C0A47BDBF464BA35C3769427D5CD034D40350F8A5590985E38AAEFC3C695DF671C2E5498E2B60C082C546E06ECAF78", - "020DE6382B8C0550E8174D5263B981224EBCFEF7706588B6936177FEB68E639B8C02BA5F18DDB3487AD087F63CEF7D7818AC8ECA3D6B736113FF36FB25D113F514F6", - "031883080513BB69B31367F9A7B5F4E81246C627060A7414B7F137FA8459F261990345445505F158EDCFDF0D4BF26E04E018C143BF76B5D457AE57DF06CA41371DF0", - "0300028E83123E7FAB1E1F230547CE8B96CC23F13197312972DE72AACBA98EF9870274C2D8566E9E021AA7E2DDDA01B52AE670E0742418F147610528B65ACDB4D0B3" + "036E5EE6E28824029FEA3E8A9DDD2C8483F5AF98F7177C3AF3CB6F47CAF8D94AE902DBA67E4A1F3680826172DA15AFB1A8CA85C7C5CC88900905C8DC8C328511B53E", + "03E4F798DA48A76EEC1C9CC5AB7A880FFBA201A5F064E627EC9CB0031D1D58FC5103E06180315C5A522B7EC7C08B69DCD721C313C940819296D0A7AB8E8795AC1F00", + "02C0068FD25523A31578B8077F24F78F5BD5F2422AFF47C1FADA0F36B3CEB6C7D202098A55D1736AA5FCC21CF0729CCE852575C06C081125144763C2C4C4A05C09B6", + "031F5C87DCFBFCF330DEE4311D85E8F1DEA01D87A6F1C14CDFC7E4F1D8C441CFA40277BF176E9F747C34F81B0D9F072B1B404A86F402C2D86CF9EA9E9C69876EA3B9", + "023F7042046E0397822C4144A17F8B63D78748696A46C3B9F0A901D296EC3406C302022B0B464292CF9751D699F10980AC764E6F671EFCA15069BBE62B0D1C62522A", + "02D97DDA5988461DF58C5897444F116A7C74E5711BF77A9446E27806563F3B6C47020CBAD9C363A7737F99FA06B6BE093CEAFF5397316C5AC46915C43767AE867C00" ], "tweaks": [ "B511DA492182A91B0FFB9A98020D55F260AE86D7ECBD0399C7383D59A5F2AF7C", @@ -19,63 +19,128 @@ "75448A87274B056468B977BE06EB1E9F657577B7320B0A3376EA51FD420D18A8" ], "psigs": [ - "7918521F42E5727FE2E82D802876E0C8844336FDA1B58C82696A55B0188C8B3D", - "599044037AE15C4A99FB94F022B48E7AB215BF703954EC0B83D0E06230476001", - "F05BE3CA783AD1FAF68C5059B43F859BFD4EBB0242459DF2C6BF013F4217F7E7", - "BF85B2A751066466C24A5E7FA6C90DBAADAC2DF1F0BB48546AE239E340437CEB", - "142076B034A7401123EFB07E2317DF819B86B3FFA17180DDD093997D018270D0", - "B7A0C7F5B325B7993925E56B60F53EF8198169F31E1AF7E62BBEF1C5DCD1BA22", - "C717ECA32C148CE8EB8882CD9656DF9C64929DCAE9AF798E381B1E888DDF0F8F", - "5988823E78488D8005311E16E5EA67AF70514CB44F5A5CD51FFA262BEEAA21CE", + "B15D2CD3C3D22B04DAE438CE653F6B4ECF042F42CFDED7C41B64AAF9B4AF53FB", + "6193D6AC61B354E9105BBDC8937A3454A6D705B6D57322A5A472A02CE99FCB64", + "9A87D3B79EC67228CB97878B76049B15DBD05B8158D17B5B9114D3C226887505", + "66F82EA90923689B855D36C6B7E032FB9970301481B99E01CDB4D6AC7C347A15", + "4F5AEE41510848A6447DCD1BBC78457EF69024944C87F40250D3EF2C25D33EFE", + "DDEF427BBB847CC027BEFF4EDB01038148917832253EBC355FC33F4A8E2FCCE4", + "97B890A26C981DA8102D3BC294159D171D72810FDF7C6A691DEF02F0F7AF3FDC", + "53FA9E08BA5243CBCB0D797C5EE83BC6728E539EB76C2D0BF0F971EE4E909971", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141" ], "msg": "599C67EA410D005B9DA90817CF03ED3B1C868E4DA4EDF00A5880B0082C237869", "valid_test_cases": [ { - "aggnonce": "02BC34CDF6FA1298D7B6A126812FAD0739005BC44E45C21276EEFE41AAF841C86F03F3562AED52243BB99F43D1677DB59F0FEFB961633997F7AC924B78FBD0B0334F", - "nonce_indices": [0, 1], - "key_indices": [0, 1], + "aggnonce": "0341432722C5CD0268D829C702CF0D1CBCE57033EED201FD335191385227C3210C03D377F2D258B64AADC0E16F26462323D701D286046A2EA93365656AFD9875982B", + "nonce_indices": [ + 0, + 1 + ], + "key_indices": [ + 0, + 1 + ], "tweak_indices": [], "is_xonly": [], - "psig_indices": [0, 1], - "expected": "CA3C28729659E50F829F55DC5DB1DE88A05D1702B4165B85F95B627FC57733F8D2A89622BDC6CECA7CE3C2704B2B6F433658F66DDB0A788DED3B361248D3EB3E" + "psig_indices": [ + 0, + 1 + ], + "expected": "041DA22223CE65C92C9A0D6C2CAC828AAF1EEE56304FEC371DDF91EBB2B9EF0912F1038025857FEDEB3FF696F8B99FA4BB2C5812F6095A2E0004EC99CE18DE1E" }, { - "aggnonce": "035538518B8043CF4EACD0E701A80657B741C0E6445EC1D6C6177964D22C642971030CFE657EC882F4E08E751B883A78AC1491B30FC86CB57AF2DFF012C2BE6DF1F2", - "nonce_indices": [0, 2], - "key_indices": [0, 2], + "aggnonce": "0224AFD36C902084058B51B5D36676BBA4DC97C775873768E58822F87FE437D792028CB15929099EEE2F5DAE404CD39357591BA32E9AF4E162B8D3E7CB5EFE31CB20", + "nonce_indices": [ + 0, + 2 + ], + "key_indices": [ + 0, + 2 + ], "tweak_indices": [], "is_xonly": [], - "psig_indices": [2, 3], - "expected": "3997A11DFF76349532CF25E761365EA1D4F24B62EB23A12A9DAABD5976C3DB9FAFE19671C9413661B8D6AED95B089357F04C0C0D83B8460B71CEDC95B2253391" + "psig_indices": [ + 2, + 3 + ], + "expected": "1069B67EC3D2F3C7C08291ACCB17A9C9B8F2819A52EB5DF8726E17E7D6B52E9F01800260A7E9DAC450F4BE522DE4CE12BA91AEAF2B4279219EF74BE1D286ADD9" }, { - "aggnonce": "024366775E6FFBEBBB954225936BAED71A3884C7933B18225088D19E7AF12D8D5D028D79A520B347B793FFE897A7EB79A4366A3FDCDC652C243FAC3976B3D6DF8AB2", - "nonce_indices": [0, 3], - "key_indices": [0, 2], - "tweak_indices": [0], - "is_xonly": [false], - "psig_indices": [4, 5], - "expected": "5AF759C2839B7FEE59D31DAB800F82FC21258457773A3B1F69F5228C80CAD4317EA39AD756601030E4D4051B7C9A25AB4DE7CB39BED26E0A03A1B2ED5B747F7F" + "aggnonce": "0208C5C438C710F4F96A61E9FF3C37758814B8C3AE12BFEA0ED2C87FF6954FF186020B1816EA104B4FCA2D304D733E0E19CEAD51303FF6420BFD222335CAA402916D", + "nonce_indices": [ + 0, + 3 + ], + "key_indices": [ + 0, + 2 + ], + "tweak_indices": [ + 0 + ], + "is_xonly": [ + false + ], + "psig_indices": [ + 4, + 5 + ], + "expected": "5C558E1DCADE86DA0B2F02626A512E30A22CF5255CAEA7EE32C38E9A71A0E9148BA6C0E6EC7683B64220F0298696F1B878CD47B107B81F7188812D593971E0CC" }, { - "aggnonce": "03B25098C6D0B72DC5717314AF26C126609B4776AA468553DD4354EE20B216B227027D242E9203499173A74E286C1F796F2711E171EE937706BBEA2F4DB10C4E6809", - "nonce_indices": [0, 4], - "key_indices": [0, 3], - "tweak_indices": [0, 1, 2], - "is_xonly": [true, false, true], - "psig_indices": [6, 7], - "expected": "B495A478F91D6E10BF08A156E46D9E62B4C5399C1AEDDA1A9D306F06AFB8A52F2C078FD6B50DDBC33BFFE583C3C1E3D0D5E52891E190101C70D2278BCA943457" + "aggnonce": "02B5AD07AFCD99B6D92CB433FBD2A28FDEB98EAE2EB09B6014EF0F8197CD58403302E8616910F9293CF692C49F351DB86B25E352901F0E237BAFDA11F1C1CEF29FFD", + "nonce_indices": [ + 0, + 4 + ], + "key_indices": [ + 0, + 3 + ], + "tweak_indices": [ + 0, + 1, + 2 + ], + "is_xonly": [ + true, + false, + true + ], + "psig_indices": [ + 6, + 7 + ], + "expected": "839B08820B681DBA8DAF4CC7B104E8F2638F9388F8D7A555DC17B6E6971D7426CE07BF6AB01F1DB50E4E33719295F4094572B79868E440FB3DEFD3FAC1DB589E" } ], "error_test_cases": [ { - "aggnonce": "03B25098C6D0B72DC5717314AF26C126609B4776AA468553DD4354EE20B216B227027D242E9203499173A74E286C1F796F2711E171EE937706BBEA2F4DB10C4E6809", - "nonce_indices": [0, 4], - "key_indices": [0, 3], - "tweak_indices": [0, 1, 2], - "is_xonly": [true, false, true], - "psig_indices": [7, 8], + "aggnonce": "02B5AD07AFCD99B6D92CB433FBD2A28FDEB98EAE2EB09B6014EF0F8197CD58403302E8616910F9293CF692C49F351DB86B25E352901F0E237BAFDA11F1C1CEF29FFD", + "nonce_indices": [ + 0, + 4 + ], + "key_indices": [ + 0, + 3 + ], + "tweak_indices": [ + 0, + 1, + 2 + ], + "is_xonly": [ + true, + false, + true + ], + "psig_indices": [ + 7, + 8 + ], "error": { "type": "invalid_contribution", "signer": 1 @@ -83,4 +148,4 @@ "comment": "Partial signature is invalid because it exceeds group size" } ] -} +} \ No newline at end of file diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 4b2509a754..347254ffab 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -6,6 +6,7 @@ import ( "bytes" "crypto/rand" "encoding/binary" + "errors" "io" "github.com/btcsuite/btcd/btcec/v2" @@ -34,6 +35,10 @@ var ( NonceGenTag = []byte("MuSig/nonce") byteOrder = binary.BigEndian + + // ErrPubkeyInvalid is returned when the pubkey of the WithPublicKey + // option is not passed or of invalid length. + ErrPubkeyInvalid = errors.New("nonce generation requires a valid pubkey") ) // zeroSecNonce is a secret nonce that's all zeroes. This is used to check that @@ -96,6 +101,10 @@ type nonceGenOpts struct { // used in place. randReader io.Reader + // publicKey is the mandatory public key that will be mixed into the nonce + // generation. + publicKey []byte + // secretKey is an optional argument that's used to further augment the // generated nonce by xor'ing it with this secret key. secretKey []byte @@ -142,6 +151,14 @@ func WithCustomRand(r io.Reader) NonceGenOption { } } +// WithPublicKey is the mandatory public key that will be mixed into the nonce +// generation. +func WithPublicKey(pubKey *btcec.PublicKey) NonceGenOption { + return func(o *nonceGenOpts) { + o.publicKey = pubKey.SerializeCompressed() + } +} + // WithNonceSecretKeyAux allows a caller to optionally specify a secret key // that should be used to augment the randomness used to generate the nonces. func WithNonceSecretKeyAux(secKey *btcec.PrivateKey) NonceGenOption { @@ -186,6 +203,7 @@ func withCustomOptions(customOpts nonceGenOpts) NonceGenOption { o.combinedKey = customOpts.combinedKey o.auxInput = customOpts.auxInput o.msg = customOpts.msg + o.publicKey = customOpts.publicKey } } @@ -233,13 +251,13 @@ func writeBytesPrefix(w io.Writer, b []byte, lenWriter lengthWriter) error { // genNonceAuxBytes writes out the full byte string used to derive a secret // nonce based on some initial randomness as well as the series of optional // fields. The byte string used for derivation is: -// - tagged_hash("MuSig/nonce", rand || len(aggpk) || aggpk || m_prefixed -// || len(in) || in || i). +// - tagged_hash("MuSig/nonce", rand || len(pk) || pk || +// len(aggpk) || aggpk || m_prefixed || len(in) || in || i). // // where i is the ith secret nonce being generated and m_prefixed is: // - bytes(1, 0) if the message is blank // - bytes(1, 1) || bytes(8, len(m)) || m if the message is present. -func genNonceAuxBytes(rand []byte, i int, +func genNonceAuxBytes(rand []byte, pubkey []byte, i int, opts *nonceGenOpts) (*chainhash.Hash, error) { var w bytes.Buffer @@ -249,8 +267,14 @@ func genNonceAuxBytes(rand []byte, i int, return nil, err } + // Next, we'll write out: len(pk) || pk + err := writeBytesPrefix(&w, pubkey, uint8Writer) + if err != nil { + return nil, err + } + // Next, we'll write out: len(aggpk) || aggpk. - err := writeBytesPrefix(&w, opts.combinedKey, uint8Writer) + err = writeBytesPrefix(&w, opts.combinedKey, uint8Writer) if err != nil { return nil, err } @@ -305,6 +329,11 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { opt(opts) } + // We require the pubkey option. + if opts.publicKey == nil || len(opts.publicKey) != 33 { + return nil, ErrPubkeyInvalid + } + // First, we'll start out by generating 32 random bytes drawn from our // CSPRNG. var randBytes [32]byte @@ -322,13 +351,13 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { } } - // Using our randomness and the set of optional params, generate our + // Using our randomness, pubkey and the set of optional params, generate our // two secret nonces: k1 and k2. - k1, err := genNonceAuxBytes(randBytes[:], 0, opts) + k1, err := genNonceAuxBytes(randBytes[:], opts.publicKey, 0, opts) if err != nil { return nil, err } - k2, err := genNonceAuxBytes(randBytes[:], 1, opts) + k2, err := genNonceAuxBytes(randBytes[:], opts.publicKey, 1, opts) if err != nil { return nil, err } diff --git a/btcec/schnorr/musig2/nonces_test.go b/btcec/schnorr/musig2/nonces_test.go index bdb76dbd35..7105d83b30 100644 --- a/btcec/schnorr/musig2/nonces_test.go +++ b/btcec/schnorr/musig2/nonces_test.go @@ -20,6 +20,7 @@ type nonceGenTestCase struct { AggPk string `json:"aggpk"` Msg *string `json:"msg"` ExtraIn string `json:"extra_in"` + Pk string `json:"pk"` Expected string `json:"expected"` } @@ -55,6 +56,7 @@ func TestMusig2NonceGenTestVectors(t *testing.T) { secretKey: mustParseHex(testCase.Sk), combinedKey: mustParseHex(testCase.AggPk), auxInput: mustParseHex(testCase.ExtraIn), + publicKey: mustParseHex(testCase.Pk), } if testCase.Msg != nil { customOpts.msg = mustParseHex(*testCase.Msg) From c5b3ed699f9b9153abd8a15747e791ca8eb4da8b Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Tue, 1 Nov 2022 23:49:33 +0100 Subject: [PATCH 0737/1056] btcec/schnorr/musig2: add public key to secnonce This commit adds the public key to the sec nonce and ensures that we're signing with the right key. Reference: https://github.com/jonasnick/bips/pull/74/0e3cfaa52620135eeef9c371f4c3cdd7883ad2cb --- btcec/schnorr/musig2/data/nonce_gen_vectors.json | 8 ++++---- btcec/schnorr/musig2/data/sign_verify_vectors.json | 4 ++-- btcec/schnorr/musig2/data/tweak_vectors.json | 2 +- btcec/schnorr/musig2/nonces.go | 5 +++-- btcec/schnorr/musig2/sign.go | 11 +++++++++++ 5 files changed, 21 insertions(+), 9 deletions(-) diff --git a/btcec/schnorr/musig2/data/nonce_gen_vectors.json b/btcec/schnorr/musig2/data/nonce_gen_vectors.json index e8fc1388cf..450234974c 100644 --- a/btcec/schnorr/musig2/data/nonce_gen_vectors.json +++ b/btcec/schnorr/musig2/data/nonce_gen_vectors.json @@ -7,7 +7,7 @@ "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", "msg": "0101010101010101010101010101010101010101010101010101010101010101", "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", - "expected": "227243DCB40EF2A13A981DB188FA433717B506BDFA14B1AE47D5DC027C9C3B9EF2370B2AD206E724243215137C86365699361126991E6FEC816845F837BDDAC3" + "expected": "227243DCB40EF2A13A981DB188FA433717B506BDFA14B1AE47D5DC027C9C3B9EF2370B2AD206E724243215137C86365699361126991E6FEC816845F837BDDAC3024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766" }, { "rand_": "0000000000000000000000000000000000000000000000000000000000000000", @@ -16,7 +16,7 @@ "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", "msg": "", "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", - "expected": "CD0F47FE471D6788FF3243F47345EA0A179AEF69476BE8348322EF39C2723318870C2065AFB52DEDF02BF4FDBF6D2F442E608692F50C2374C08FFFE57042A61C" + "expected": "CD0F47FE471D6788FF3243F47345EA0A179AEF69476BE8348322EF39C2723318870C2065AFB52DEDF02BF4FDBF6D2F442E608692F50C2374C08FFFE57042A61C024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766" }, { "rand_": "0000000000000000000000000000000000000000000000000000000000000000", @@ -25,7 +25,7 @@ "aggpk": "0707070707070707070707070707070707070707070707070707070707070707", "msg": "2626262626262626262626262626262626262626262626262626262626262626262626262626", "extra_in": "0808080808080808080808080808080808080808080808080808080808080808", - "expected": "011F8BC60EF061DEEF4D72A0A87200D9994B3F0CD9867910085C38D5366E3E6B9FF03BC0124E56B24069E91EC3F162378983F194E8BD0ED89BE3059649EAE262" + "expected": "011F8BC60EF061DEEF4D72A0A87200D9994B3F0CD9867910085C38D5366E3E6B9FF03BC0124E56B24069E91EC3F162378983F194E8BD0ED89BE3059649EAE262024D4B6CD1361032CA9BD2AEB9D900AA4D45D9EAD80AC9423374C451A7254D0766" }, { "rand_": "0000000000000000000000000000000000000000000000000000000000000000", @@ -34,7 +34,7 @@ "aggpk": null, "msg": null, "extra_in": null, - "expected": "890E83616A3BC4640AB9B6374F21C81FF89CDDDBAFAA7475AE2A102A92E3EDB29FD7E874E23342813A60D9646948242646B7951CA046B4B36D7D6078506D3C94" + "expected": "890E83616A3BC4640AB9B6374F21C81FF89CDDDBAFAA7475AE2A102A92E3EDB29FD7E874E23342813A60D9646948242646B7951CA046B4B36D7D6078506D3C9402F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9" } ] } \ No newline at end of file diff --git a/btcec/schnorr/musig2/data/sign_verify_vectors.json b/btcec/schnorr/musig2/data/sign_verify_vectors.json index e2499c7fb6..f1bc29ba99 100644 --- a/btcec/schnorr/musig2/data/sign_verify_vectors.json +++ b/btcec/schnorr/musig2/data/sign_verify_vectors.json @@ -7,8 +7,8 @@ "020000000000000000000000000000000000000000000000000000000000000007" ], "secnonces": [ - "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F703935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9" ], "pnonces": [ "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", diff --git a/btcec/schnorr/musig2/data/tweak_vectors.json b/btcec/schnorr/musig2/data/tweak_vectors.json index 01ccb8b1b3..d0a7cfe832 100644 --- a/btcec/schnorr/musig2/data/tweak_vectors.json +++ b/btcec/schnorr/musig2/data/tweak_vectors.json @@ -5,7 +5,7 @@ "02F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659" ], - "secnonce": "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7", + "secnonce": "508B81A611F100A6B2B6B29656590898AF488BCF2E1F55CF22E5CFB84421FE61FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F703935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9", "pnonces": [ "0337C87821AFD50A8644D820A8F3E02E499C931865C2360FB43D0A0D20DAFE07EA0287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480", "0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F817980279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 347254ffab..988b199471 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -22,7 +22,7 @@ const ( // SecNonceSize is the size of the secret nonces for musig2. The secret // nonces are the corresponding private keys to the public nonce points. - SecNonceSize = 64 + SecNonceSize = 97 ) var ( @@ -367,10 +367,11 @@ func GenNonces(options ...NonceGenOption) (*Nonces, error) { k2Mod.SetBytes((*[32]byte)(k2)) // The secret nonces are serialized as the concatenation of the two 32 - // byte secret nonce values. + // byte secret nonce values and the pubkey. var nonces Nonces k1Mod.PutBytesUnchecked(nonces.SecNonce[:]) k2Mod.PutBytesUnchecked(nonces.SecNonce[btcec.PrivKeyBytesLen:]) + copy(nonces.SecNonce[btcec.PrivKeyBytesLen*2:], opts.publicKey) // Next, we'll generate R_1 = k_1*G and R_2 = k_2*G. Along the way we // need to map our nonce values into mod n scalars so we can work with diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 2028571137..842eb0180f 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -38,6 +38,10 @@ var ( // ErrSecretNonceZero is returned when a secret nonce is passed in a // zero. ErrSecretNonceZero = fmt.Errorf("secret nonce is blank") + + // ErrSecNoncePubkey is returned when the signing key does not match the + // sec nonce pubkey + ErrSecNoncePubkey = fmt.Errorf("public key does not match secnonce") ) // infinityPoint is the jacobian representation of the point at infinity. @@ -252,6 +256,13 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, option(opts) } + // Check that our signing key belongs to the secNonce + if !bytes.Equal(secNonce[btcec.PrivKeyBytesLen*2:], + privKey.PubKey().SerializeCompressed()) { + + return nil, ErrSecNoncePubkey + } + // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of signing. keysHash := keyHashFingerprint(pubKeys, opts.sortKeys) From d99a1696632de4ce2afdfb5ed9062b5b2290f7e8 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Tue, 1 Nov 2022 23:53:48 +0100 Subject: [PATCH 0738/1056] btcec/schnorr/musig2: add pubkey check to Sign This commit adds a check that the public key of the private key that is passed to the Sign function is included in the slice of public keys. Reference https://github.com/jonasnick/bips/pull/74/commits/ea47d52e2d48a97914ac171daff88d6a216d31f1 --- .../musig2/data/sign_verify_vectors.json | 11 +++++++++++ btcec/schnorr/musig2/sign.go | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/btcec/schnorr/musig2/data/sign_verify_vectors.json b/btcec/schnorr/musig2/data/sign_verify_vectors.json index f1bc29ba99..324537168b 100644 --- a/btcec/schnorr/musig2/data/sign_verify_vectors.json +++ b/btcec/schnorr/musig2/data/sign_verify_vectors.json @@ -65,6 +65,17 @@ } ], "sign_error_test_cases": [ + { + "key_indices": [1, 2], + "aggnonce_index": 0, + "msg_index": 0, + "secnonce_index": 0, + "error": { + "type": "value", + "message": "The signer's pubkey must be included in the list of pubkeys." + }, + "comment": "The signers pubkey is not in the list of pubkeys" + }, { "key_indices": [1, 0, 3], "aggnonce_index": 0, diff --git a/btcec/schnorr/musig2/sign.go b/btcec/schnorr/musig2/sign.go index 842eb0180f..9204611dd6 100644 --- a/btcec/schnorr/musig2/sign.go +++ b/btcec/schnorr/musig2/sign.go @@ -42,6 +42,11 @@ var ( // ErrSecNoncePubkey is returned when the signing key does not match the // sec nonce pubkey ErrSecNoncePubkey = fmt.Errorf("public key does not match secnonce") + + // ErrPubkeyNotIncluded is returned when the signers pubkey is not included + // in the list of pubkeys. + ErrPubkeyNotIncluded = fmt.Errorf("signer's pubkey must be included" + + " in the list of pubkeys") ) // infinityPoint is the jacobian representation of the point at infinity. @@ -263,6 +268,18 @@ func Sign(secNonce [SecNonceSize]byte, privKey *btcec.PrivateKey, return nil, ErrSecNoncePubkey } + // Check that the key set contains the public key to our private key. + var containsPrivKey bool + for _, pk := range pubKeys { + if privKey.PubKey().IsEqual(pk) { + containsPrivKey = true + } + } + + if !containsPrivKey { + return nil, ErrPubkeyNotIncluded + } + // Compute the hash of all the keys here as we'll need it do aggregate // the keys and also at the final step of signing. keysHash := keyHashFingerprint(pubKeys, opts.sortKeys) From 586729ca070da5f6467093df2b32d9b05a7a6d7f Mon Sep 17 00:00:00 2001 From: Robyn Date: Thu, 3 Nov 2022 20:34:07 +0000 Subject: [PATCH 0739/1056] btcutil/psbt: add method Packet.GetTxFee This commit adds a GetTxFee method to the psbt.Packet structure. The method returns the PSBT's fee. --- btcutil/psbt/psbt.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go index 5ea51eead0..7241bdb685 100644 --- a/btcutil/psbt/psbt.go +++ b/btcutil/psbt/psbt.go @@ -11,9 +11,9 @@ import ( "bytes" "encoding/base64" "errors" - "io" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" ) @@ -30,7 +30,7 @@ var ( // MaxPsbtValueLength is the size of the largest transaction serialization // that could be passed in a NonWitnessUtxo field. This is definitely -//less than 4M. +// less than 4M. const MaxPsbtValueLength = 4000000 // MaxPsbtKeyLength is the length of the largest key that we'll successfully @@ -395,3 +395,20 @@ func (p *Packet) SanityCheck() error { return nil } + +// GetTxFee returns the transaction fee. An error is returned if a transaction +// input does not contain any UTXO information. +func (p *Packet) GetTxFee() (btcutil.Amount, error) { + sumInputs, err := SumUtxoInputValues(p) + if err != nil { + return 0, err + } + + var sumOutputs int64 + for _, txOut := range p.UnsignedTx.TxOut { + sumOutputs += txOut.Value + } + + fee := sumInputs - sumOutputs + return btcutil.Amount(fee), nil +} From a8244f587cfb69c44aa7a01f0f543b013ce5a385 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 8 Nov 2022 17:43:07 -0800 Subject: [PATCH 0740/1056] btcec/schnorr: use private key copy for BIP-340 signatures This is a fix similar to https://github.com/btcsuite/btcd/pull/1905. We'll always make a copy of the key in the local scope before passing it around elsewhere. Depending on the parity of the public key, the private key itself might need to be negated. A similar test is added here that fails without the patch to the signature.go file. --- btcec/schnorr/signature.go | 12 ++++++----- btcec/schnorr/signature_test.go | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index f4532c7d09..8f58d52b4f 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -51,8 +51,9 @@ func NewSignature(r *btcec.FieldVal, s *btcec.ModNScalar) *Signature { // Serialize returns the Schnorr signature in the more strict format. // // The signatures are encoded as -// sig[0:32] x coordinate of the point R, encoded as a big-endian uint256 -// sig[32:64] s, encoded also as big-endian uint256 +// +// sig[0:32] x coordinate of the point R, encoded as a big-endian uint256 +// sig[32:64] s, encoded also as big-endian uint256 func (sig Signature) Serialize() []byte { // Total length of returned signature is the length of r and s. var b [SignatureSize]byte @@ -441,7 +442,8 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, // Step 1. // // d' = int(d) - privKeyScalar := &privKey.Key + var privKeyScalar btcec.ModNScalar + privKeyScalar.Set(&privKey.Key) // Step 2. // @@ -512,7 +514,7 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, return nil, signatureError(ecdsa_schnorr.ErrSchnorrHashValue, str) } - sig, err := schnorrSign(privKeyScalar, &kPrime, pub, hash, opts) + sig, err := schnorrSign(&privKeyScalar, &kPrime, pub, hash, opts) kPrime.Zero() if err != nil { return nil, err @@ -535,7 +537,7 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, ) // Steps 10-15. - sig, err := schnorrSign(privKeyScalar, k, pub, hash, opts) + sig, err := schnorrSign(&privKeyScalar, k, pub, hash, opts) k.Zero() if err != nil { // Try again with a new nonce. diff --git a/btcec/schnorr/signature_test.go b/btcec/schnorr/signature_test.go index b99614ff6c..2f96b7e4d5 100644 --- a/btcec/schnorr/signature_test.go +++ b/btcec/schnorr/signature_test.go @@ -10,8 +10,10 @@ import ( "errors" "strings" "testing" + "testing/quick" "github.com/btcsuite/btcd/btcec/v2" + "github.com/davecgh/go-spew/spew" secp_ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4" ecdsa_schnorr "github.com/decred/dcrd/dcrec/secp256k1/v4/schnorr" ) @@ -254,3 +256,38 @@ func TestSchnorrVerify(t *testing.T) { } } } + +// TestSchnorrSignNoMutate tests that generating a schnorr signature doesn't +// modify/mutate the underlying private key. +func TestSchnorrSignNoMutate(t *testing.T) { + t.Parallel() + + // Assert that given a random private key and message, we can generate + // a signature from that w/o modifying the underlying private key. + f := func(privBytes, msg [32]byte) bool { + privBytesCopy := privBytes + privKey, _ := btcec.PrivKeyFromBytes(privBytesCopy[:]) + + // Generate a signature for private key with our message. + _, err := Sign(privKey, msg[:]) + if err != nil { + t.Logf("unable to gen sig: %v", err) + return false + } + + // We should be able to re-derive the private key from raw + // bytes and have that match up again. + privKeyCopy, _ := btcec.PrivKeyFromBytes(privBytes[:]) + if *privKey != *privKeyCopy { + t.Logf("private doesn't match: expected %v, got %v", + spew.Sdump(privKeyCopy), spew.Sdump(privKey)) + return false + } + + return true + } + + if err := quick.Check(f, nil); err != nil { + t.Fatalf("private key modified: %v", err) + } +} From 55e40f45368bdd838e825fce441c013d2963d521 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Wed, 9 Nov 2022 12:47:05 -0800 Subject: [PATCH 0741/1056] btcec/schnorr/musig2: fix BenchmarkPartialVerify In this commit, we fix the `BenchmarkPartialVerify` test. When we moved to musig 1.0, we stopped requiring the input as an x-only key. So we need to remove the round trip serialization to force the key to be x-only. --- btcec/schnorr/musig2/bench_test.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/btcec/schnorr/musig2/bench_test.go b/btcec/schnorr/musig2/bench_test.go index 751ee737b8..aac298aa28 100644 --- a/btcec/schnorr/musig2/bench_test.go +++ b/btcec/schnorr/musig2/bench_test.go @@ -45,12 +45,7 @@ func genSigner(t *testing.B) signer { t.Fatalf("unable to gen priv key: %v", err) } - pubKey, err := schnorr.ParsePubKey( - schnorr.SerializePubKey(privKey.PubKey()), - ) - if err != nil { - t.Fatalf("unable to gen key: %v", err) - } + pubKey := privKey.PubKey() nonces, err := GenNonces(WithPublicKey(pubKey)) if err != nil { From 866b3dc0a38ae35095f1550e24c0bbe0913cbdfa Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 18 Nov 2022 20:55:50 +0100 Subject: [PATCH 0742/1056] base58: fix decoding issue --- btcutil/base58/base58.go | 4 ++++ btcutil/base58/base58_test.go | 2 ++ 2 files changed, 6 insertions(+) diff --git a/btcutil/base58/base58.go b/btcutil/base58/base58.go index 8ee5956718..bd0ea47cd9 100644 --- a/btcutil/base58/base58.go +++ b/btcutil/base58/base58.go @@ -55,6 +55,10 @@ func Decode(b string) []byte { total := uint64(0) for _, v := range t[:n] { + if v > 255 { + return []byte("") + } + tmp := b58[v] if tmp == 255 { return []byte("") diff --git a/btcutil/base58/base58_test.go b/btcutil/base58/base58_test.go index b868d1d401..eb7e4d4bcf 100644 --- a/btcutil/base58/base58_test.go +++ b/btcutil/base58/base58_test.go @@ -43,6 +43,8 @@ var invalidStringTests = []struct { {"4kl8", ""}, {"0OIl", ""}, {"!@#$%^&*()-_=+~`", ""}, + {"abcd\xd80", ""}, + {"abcd\U000020BF", ""}, } var hexTests = []struct { From 6c93f9f9f22d4e132d3d75d69f2e7d9054c064cc Mon Sep 17 00:00:00 2001 From: Guillaume A Date: Sun, 20 Nov 2022 12:47:34 +0800 Subject: [PATCH 0743/1056] Update Dockerfile to Alpine 3.16 Alpine 3.12 is EOL and contains multiple vulnerabilites. Deploying on Alpine 3.16 works fine. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 58e4b59aec..e5e349a820 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ RUN set -ex \ && echo "Compiling for $GOARCH" \ && go install -v . ./cmd/... -FROM $ARCH/alpine:3.12 +FROM $ARCH/alpine:3.16 COPY --from=build-container /go/bin /bin From 52b6eb46f142f77797e3fc92a3bce0438ded448b Mon Sep 17 00:00:00 2001 From: Guillaume A Date: Sun, 20 Nov 2022 13:04:58 +0800 Subject: [PATCH 0744/1056] Update Docker documentation towards building your own image As DockerHub image non existant, update the documentation for Compose to build your own image instead. --- docs/using_docker.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/using_docker.md b/docs/using_docker.md index 0809abc1c8..6cd41b9d7c 100644 --- a/docs/using_docker.md +++ b/docs/using_docker.md @@ -93,7 +93,7 @@ services: btcd: container_name: btcd hostname: btcd - image: btcsuite/btcd:latest + build: https://github.com/btcsuite/btcd.git#master restart: unless-stopped volumes: - btcd-data:/root/.btcd @@ -115,7 +115,7 @@ services: btcd: container_name: btcd hostname: btcd - image: btcsuite/btcd:latest + build: https://github.com/btcsuite/btcd.git#master restart: unless-stopped volumes: - btcd-data:/root/.btcd @@ -142,7 +142,7 @@ services: btcd: container_name: btcd hostname: btcd - image: btcsuite/btcd:latest + build: https://github.com/btcsuite/btcd.git#master restart: unless-stopped volumes: - btcd-data:/root/.btcd From 1d6e578c2180a6ee45755270dd938894fb93d661 Mon Sep 17 00:00:00 2001 From: ffranr Date: Fri, 2 Dec 2022 19:30:41 +0000 Subject: [PATCH 0745/1056] chainhash: JSON marshal hash as string --- chaincfg/chainhash/hash.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index 764ec3c40a..d2c562ae6a 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -8,6 +8,7 @@ package chainhash import ( "crypto/sha256" "encoding/hex" + "encoding/json" "fmt" ) @@ -110,6 +111,11 @@ func (hash *Hash) IsEqual(target *Hash) bool { return *hash == *target } +// MarshalJSON serialises the hash as a JSON appropriate string value. +func (hash Hash) MarshalJSON() ([]byte, error) { + return json.Marshal(hash.String()) +} + // NewHash returns a new Hash from a byte slice. An error is returned if // the number of bytes passed in is not HashSize. func NewHash(newHash []byte) (*Hash, error) { From 1d77730e9a92eafadb9f1ef86d2522c36ca4db38 Mon Sep 17 00:00:00 2001 From: Christopher Hall Date: Wed, 13 May 2020 15:05:35 +0800 Subject: [PATCH 0746/1056] [connmgr] remove pending entry on failed connection fix memory leak in connmanager caused by: * pending entries are not removed on error * new connection always allocates new struct * capture id value for callback Fix by calling Remove in both handleFailedConn callbacks to delete the item from the pending hash map Signed-off-by: Christopher Hall --- connmgr/connmanager.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go index 9a68190267..b487bd1ba1 100644 --- a/connmgr/connmanager.go +++ b/connmgr/connmanager.go @@ -210,11 +210,16 @@ func (cm *ConnManager) handleFailedConn(c *ConnReq) { log.Debugf("Max failed connection attempts reached: [%d] "+ "-- retrying connection in: %v", maxFailedAttempts, cm.cfg.RetryDuration) + theId := c.id time.AfterFunc(cm.cfg.RetryDuration, func() { + cm.Remove(theId) cm.NewConnReq() }) } else { - go cm.NewConnReq() + go func(theId uint64) { + cm.Remove(theId) + cm.NewConnReq() + }(c.id) } } } From 016b3adb3688651d13af7cbafb514d8947e68440 Mon Sep 17 00:00:00 2001 From: Jens Schendel <30713344+jagottsicher@users.noreply.github.com> Date: Fri, 20 Jan 2023 22:00:37 +0800 Subject: [PATCH 0747/1056] Update mining.md (#1938) minor changes to increase readability. --- docs/mining.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/mining.md b/docs/mining.md index 29a3e89858..e6218bed84 100644 --- a/docs/mining.md +++ b/docs/mining.md @@ -21,9 +21,9 @@ certificate into the default system Certificate Authority list. ## Ubuntu -1. Copy rpc.cert to /usr/share/ca-certificates: `# cp /home/user/.btcd/rpc.cert /usr/share/ca-certificates/btcd.crt` -2. Add btcd.crt to /etc/ca-certificates.conf: `# echo btcd.crt >> /etc/ca-certificates.conf` -3. Update the CA certificate list: `# update-ca-certificates` +1. Copy rpc.cert to /usr/share/ca-certificates: `cp /home/user/.btcd/rpc.cert /usr/share/ca-certificates/btcd.crt` +2. Add btcd.crt to /etc/ca-certificates.conf: `echo btcd.crt >> /etc/ca-certificates.conf` +3. Update the CA certificate list: `update-ca-certificates` ## Set your mining software url to use https From f6e8292402f5c4466b3f8b41f259d0457d5ec715 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 23 Jan 2023 20:16:44 -0800 Subject: [PATCH 0748/1056] txscript: fix sighash bug in RawTxInTaprootSignature In this commit, we fix a bug in RawTxInTaprootSignature that would cause the function to not properly apply the sighash flag for non-default sighash signatures. The logic would end up applying `0x00` as a mask, which will always be `0x00` on the other end. The RawTxInTapscriptSignature function was correct, though it had the ordering switched as it applies the sighash if the type doesn't equal default. --- txscript/sign.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/sign.go b/txscript/sign.go index f3001d8939..0a11e1b197 100644 --- a/txscript/sign.go +++ b/txscript/sign.go @@ -95,7 +95,7 @@ func RawTxInTaprootSignature(tx *wire.MsgTx, sigHashes *TxSigHashes, idx int, // If this is sighash default, then we can just return the signature // directly. - if hashType&SigHashDefault == SigHashDefault { + if hashType == SigHashDefault { return sig, nil } From 5e0de1c539b5430d580afca7a8157326bffb5da0 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 24 Jan 2023 18:43:02 -0800 Subject: [PATCH 0749/1056] txscript: add new PayToTaprootScript function --- txscript/taproot.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/txscript/taproot.go b/txscript/taproot.go index cd73aff4d8..003eb19ae3 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -774,3 +774,11 @@ func AssembleTaprootScriptTree(leaves ...TapLeaf) *IndexedTapScriptTree { return scriptTree } + +// PayToTaprootScript creates a pk script for a pay-to-taproot output key. +func PayToTaprootScript(taprootKey *btcec.PublicKey) ([]byte, error) { + return NewScriptBuilder(). + AddOp(OP_1). + AddData(schnorr.SerializePubKey(taprootKey)). + Script() +} From d6efaa720823e534bb6583773c8cf30a378f09a2 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 23 Jan 2023 20:14:53 -0800 Subject: [PATCH 0750/1056] txscript: add tests for RawTxInTaprootSignature and RawTxInTapscriptSignature In this commit, we add tests for the public functions used to generate keyspend and tapscript signatures. Without the prior commit, these tests will fail as the keyspend function won't properly add the sighash bytes for things that aren't sighash default. --- txscript/sign_test.go | 204 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) diff --git a/txscript/sign_test.go b/txscript/sign_test.go index ae10ba17d8..b3cf5119d3 100644 --- a/txscript/sign_test.go +++ b/txscript/sign_test.go @@ -10,10 +10,12 @@ import ( "testing" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/stretchr/testify/require" ) type addressToKey struct { @@ -1692,3 +1694,205 @@ nexttest: } } } + +// TestRawTxInTaprootSignature tests that the RawTxInTaprootSignature function +// generates valid signatures for all relevant sighash types. +func TestRawTxInTaprootSignature(t *testing.T) { + t.Parallel() + + privKey, err := btcec.NewPrivateKey() + require.NoError(t, err) + + pubKey := ComputeTaprootKeyNoScript(privKey.PubKey()) + + pkScript, err := PayToTaprootScript(pubKey) + require.NoError(t, err) + + // We'll reuse this simple transaction for the tests below. It ends up + // spending from a bip86 P2TR output. + testTx := wire.NewMsgTx(2) + testTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: wire.OutPoint{ + Index: 1, + }, + }) + txOut := &wire.TxOut{ + Value: 1e8, PkScript: pkScript, + } + testTx.AddTxOut(txOut) + + tests := []struct { + sigHashType SigHashType + }{ + { + sigHashType: SigHashDefault, + }, + { + sigHashType: SigHashAll, + }, + { + sigHashType: SigHashNone, + }, + { + sigHashType: SigHashSingle, + }, + { + sigHashType: SigHashSingle | SigHashAnyOneCanPay, + }, + { + sigHashType: SigHashNone | SigHashAnyOneCanPay, + }, + { + sigHashType: SigHashAll | SigHashAnyOneCanPay, + }, + } + for _, test := range tests { + name := fmt.Sprintf("sighash=%v", test.sigHashType) + t.Run(name, func(t *testing.T) { + prevFetcher := NewCannedPrevOutputFetcher( + txOut.PkScript, txOut.Value, + ) + sigHashes := NewTxSigHashes(testTx, prevFetcher) + + sig, err := RawTxInTaprootSignature( + testTx, sigHashes, 0, txOut.Value, txOut.PkScript, + nil, test.sigHashType, privKey, + ) + require.NoError(t, err) + + // If this isn't sighash default, then a sighash should be + // applied. Otherwise, it should be a normal sig. + expectedLen := schnorr.SignatureSize + if test.sigHashType != SigHashDefault { + expectedLen += 1 + } + require.Len(t, sig, expectedLen) + + // Finally, ensure that the signature produced is valid. + txCopy := testTx.Copy() + txCopy.TxIn[0].Witness = wire.TxWitness{sig} + vm, err := NewEngine( + txOut.PkScript, txCopy, 0, StandardVerifyFlags, + nil, sigHashes, txOut.Value, prevFetcher, + ) + require.NoError(t, err) + + require.NoError(t, vm.Execute()) + }) + } +} + +// TestRawTxInTapscriptSignature thats that we're able to produce valid schnorr +// signatures for a simple tapscript spend, for various sighash types. +func TestRawTxInTapscriptSignature(t *testing.T) { + t.Parallel() + + privKey, err := btcec.NewPrivateKey() + require.NoError(t, err) + + internalKey := privKey.PubKey() + + // Our script will be a simple OP_CHECKSIG as the sole leaf of a + // tapscript tree. We'll also re-use the internal key as the key in the + // leaf. + builder := NewScriptBuilder() + builder.AddData(schnorr.SerializePubKey(internalKey)) + builder.AddOp(OP_CHECKSIG) + pkScript, err := builder.Script() + require.NoError(t, err) + + tapLeaf := NewBaseTapLeaf(pkScript) + tapScriptTree := AssembleTaprootScriptTree(tapLeaf) + + ctrlBlock := tapScriptTree.LeafMerkleProofs[0].ToControlBlock( + internalKey, + ) + + tapScriptRootHash := tapScriptTree.RootNode.TapHash() + outputKey := ComputeTaprootOutputKey( + internalKey, tapScriptRootHash[:], + ) + p2trScript, err := PayToTaprootScript(outputKey) + require.NoError(t, err) + + // We'll reuse this simple transaction for the tests below. It ends up + // spending from a bip86 P2TR output. + testTx := wire.NewMsgTx(2) + testTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: wire.OutPoint{ + Index: 1, + }, + }) + txOut := &wire.TxOut{ + Value: 1e8, PkScript: p2trScript, + } + testTx.AddTxOut(txOut) + + tests := []struct { + sigHashType SigHashType + }{ + { + sigHashType: SigHashDefault, + }, + { + sigHashType: SigHashAll, + }, + { + sigHashType: SigHashNone, + }, + { + sigHashType: SigHashSingle, + }, + { + sigHashType: SigHashSingle | SigHashAnyOneCanPay, + }, + { + sigHashType: SigHashNone | SigHashAnyOneCanPay, + }, + { + sigHashType: SigHashAll | SigHashAnyOneCanPay, + }, + } + for _, test := range tests { + name := fmt.Sprintf("sighash=%v", test.sigHashType) + t.Run(name, func(t *testing.T) { + prevFetcher := NewCannedPrevOutputFetcher( + txOut.PkScript, txOut.Value, + ) + sigHashes := NewTxSigHashes(testTx, prevFetcher) + + sig, err := RawTxInTapscriptSignature( + testTx, sigHashes, 0, txOut.Value, + txOut.PkScript, tapLeaf, test.sigHashType, + privKey, + ) + require.NoError(t, err) + + // If this isn't sighash default, then a sighash should + // be applied. Otherwise, it should be a normal sig. + expectedLen := schnorr.SignatureSize + if test.sigHashType != SigHashDefault { + expectedLen += 1 + } + require.Len(t, sig, expectedLen) + + // Now that we have the sig, we'll make a valid witness + // including the control block. + ctrlBlockBytes, err := ctrlBlock.ToBytes() + require.NoError(t, err) + txCopy := testTx.Copy() + txCopy.TxIn[0].Witness = wire.TxWitness{ + sig, pkScript, ctrlBlockBytes, + } + + // Finally, ensure that the signature produced is valid. + vm, err := NewEngine( + txOut.PkScript, txCopy, 0, StandardVerifyFlags, + nil, sigHashes, txOut.Value, prevFetcher, + ) + require.NoError(t, err) + + require.NoError(t, vm.Execute()) + }) + } +} From 734ab735b94ea399446bb1febc89b7a2d9acd1d7 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 27 Jan 2023 15:30:41 +0100 Subject: [PATCH 0751/1056] psbt: export Bip32 encode/decode functions --- btcutil/psbt/bip32.go | 4 ++-- btcutil/psbt/partial_input.go | 8 +++++--- btcutil/psbt/partial_output.go | 8 +++++--- btcutil/psbt/taproot.go | 11 ++++++----- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/btcutil/psbt/bip32.go b/btcutil/psbt/bip32.go index 6b22dc0654..2fe6afa2c0 100644 --- a/btcutil/psbt/bip32.go +++ b/btcutil/psbt/bip32.go @@ -36,10 +36,10 @@ func (s Bip32Sorter) Less(i, j int) bool { return bytes.Compare(s[i].PubKey, s[j].PubKey) < 0 } -// readBip32Derivation deserializes a byte slice containing chunks of 4 byte +// ReadBip32Derivation deserializes a byte slice containing chunks of 4 byte // little endian encodings of uint32 values, the first of which is the // masterkeyfingerprint and the remainder of which are the derivation path. -func readBip32Derivation(path []byte) (uint32, []uint32, error) { +func ReadBip32Derivation(path []byte) (uint32, []uint32, error) { // BIP-0174 defines the derivation path being encoded as // "<32-bit uint> <32-bit uint>*" // with the asterisk meaning 0 to n times. Which in turn means that an diff --git a/btcutil/psbt/partial_input.go b/btcutil/psbt/partial_input.go index 7686c451cb..5128f1fc60 100644 --- a/btcutil/psbt/partial_input.go +++ b/btcutil/psbt/partial_input.go @@ -174,7 +174,9 @@ func (pi *PInput) deserialize(r io.Reader) error { if !validatePubkey(keydata) { return ErrInvalidPsbtFormat } - master, derivationPath, err := readBip32Derivation(value) + master, derivationPath, err := ReadBip32Derivation( + value, + ) if err != nil { return err } @@ -322,7 +324,7 @@ func (pi *PInput) deserialize(r io.Reader) error { return ErrInvalidKeydata } - taprootDerivation, err := readTaprootBip32Derivation( + taprootDerivation, err := ReadTaprootBip32Derivation( keydata, value, ) if err != nil { @@ -538,7 +540,7 @@ func (pi *PInput) serialize(w io.Writer) error { ) }) for _, derivation := range pi.TaprootBip32Derivation { - value, err := serializeTaprootBip32Derivation( + value, err := SerializeTaprootBip32Derivation( derivation, ) if err != nil { diff --git a/btcutil/psbt/partial_output.go b/btcutil/psbt/partial_output.go index 33b5ff9981..f0e90406db 100644 --- a/btcutil/psbt/partial_output.go +++ b/btcutil/psbt/partial_output.go @@ -74,7 +74,9 @@ func (po *POutput) deserialize(r io.Reader) error { if !validatePubkey(keydata) { return ErrInvalidKeydata } - master, derivationPath, err := readBip32Derivation(value) + master, derivationPath, err := ReadBip32Derivation( + value, + ) if err != nil { return err } @@ -123,7 +125,7 @@ func (po *POutput) deserialize(r io.Reader) error { return ErrInvalidKeydata } - taprootDerivation, err := readTaprootBip32Derivation( + taprootDerivation, err := ReadTaprootBip32Derivation( keydata, value, ) if err != nil { @@ -211,7 +213,7 @@ func (po *POutput) serialize(w io.Writer) error { ) }) for _, derivation := range po.TaprootBip32Derivation { - value, err := serializeTaprootBip32Derivation( + value, err := SerializeTaprootBip32Derivation( derivation, ) if err != nil { diff --git a/btcutil/psbt/taproot.go b/btcutil/psbt/taproot.go index 4d0619ec43..b9df860c95 100644 --- a/btcutil/psbt/taproot.go +++ b/btcutil/psbt/taproot.go @@ -2,6 +2,7 @@ package psbt import ( "bytes" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -92,10 +93,10 @@ func (s *TaprootBip32Derivation) SortBefore(other *TaprootBip32Derivation) bool return bytes.Compare(s.XOnlyPubKey, other.XOnlyPubKey) < 0 } -// readTaprootBip32Derivation deserializes a byte slice containing the Taproot +// ReadTaprootBip32Derivation deserializes a byte slice containing the Taproot // BIP32 derivation info that consists of a list of leaf hashes as well as the // normal BIP32 derivation info. -func readTaprootBip32Derivation(xOnlyPubKey, +func ReadTaprootBip32Derivation(xOnlyPubKey, value []byte) (*TaprootBip32Derivation, error) { // The taproot key BIP 32 derivation path is defined as: @@ -141,7 +142,7 @@ func readTaprootBip32Derivation(xOnlyPubKey, } // Read the BIP32 derivation info. - fingerprint, path, err := readBip32Derivation(leftoverBuf.Bytes()) + fingerprint, path, err := ReadBip32Derivation(leftoverBuf.Bytes()) if err != nil { return nil, err } @@ -152,9 +153,9 @@ func readTaprootBip32Derivation(xOnlyPubKey, return &derivation, nil } -// serializeTaprootBip32Derivation serializes a TaprootBip32Derivation to its +// SerializeTaprootBip32Derivation serializes a TaprootBip32Derivation to its // raw byte representation. -func serializeTaprootBip32Derivation(d *TaprootBip32Derivation) ([]byte, +func SerializeTaprootBip32Derivation(d *TaprootBip32Derivation) ([]byte, error) { var buf bytes.Buffer From 2dbc98bdf3dc3f72a749c246cd0171bdd7abafd2 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 27 Jan 2023 15:30:42 +0100 Subject: [PATCH 0752/1056] psbt: fix formatting and typos --- btcutil/psbt/bip32.go | 2 +- btcutil/psbt/extractor.go | 5 +- btcutil/psbt/finalizer.go | 5 +- btcutil/psbt/partial_input.go | 120 ++++++++++++++++----------------- btcutil/psbt/partial_output.go | 44 ++++++------ btcutil/psbt/psbt.go | 67 +++++++++--------- btcutil/psbt/signer.go | 24 ++++--- btcutil/psbt/utils.go | 2 +- 8 files changed, 134 insertions(+), 135 deletions(-) diff --git a/btcutil/psbt/bip32.go b/btcutil/psbt/bip32.go index 2fe6afa2c0..96a3f67274 100644 --- a/btcutil/psbt/bip32.go +++ b/btcutil/psbt/bip32.go @@ -13,7 +13,7 @@ type Bip32Derivation struct { // PubKey is the raw pubkey serialized in compressed format. PubKey []byte - // MasterKeyFingerprint is the finger print of the master pubkey. + // MasterKeyFingerprint is the fingerprint of the master pubkey. MasterKeyFingerprint uint32 // Bip32Path is the BIP 32 path with child index as a distinct integer. diff --git a/btcutil/psbt/extractor.go b/btcutil/psbt/extractor.go index dc7f10fddb..365e2f1bba 100644 --- a/btcutil/psbt/extractor.go +++ b/btcutil/psbt/extractor.go @@ -61,13 +61,14 @@ func Extract(p *Packet) (*wire.MsgTx, error) { return nil, err } - // Now that we know how may inputs we'll need, we'll + // Now that we know how many inputs we'll need, we'll // construct a packing slice, then read out each input // (with a varint prefix) from the witnessReader. tin.Witness = make(wire.TxWitness, witCount) for j := uint64(0); j < witCount; j++ { wit, err := wire.ReadVarBytes( - witnessReader, 0, txscript.MaxScriptSize, "witness", + witnessReader, 0, + txscript.MaxScriptSize, "witness", ) if err != nil { return nil, err diff --git a/btcutil/psbt/finalizer.go b/btcutil/psbt/finalizer.go index 8c50a94b48..a215aa5948 100644 --- a/btcutil/psbt/finalizer.go +++ b/btcutil/psbt/finalizer.go @@ -14,6 +14,7 @@ package psbt import ( "bytes" "fmt" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" ) @@ -462,7 +463,9 @@ func finalizeWitnessInput(p *Packet, inIndex int) error { return ErrNotFinalizable } - serializedWitness, err = writePKHWitness(sigs[0], pubKeys[0]) + serializedWitness, err = writePKHWitness( + sigs[0], pubKeys[0], + ) if err != nil { return err } diff --git a/btcutil/psbt/partial_input.go b/btcutil/psbt/partial_input.go index 5128f1fc60..73595d2513 100644 --- a/btcutil/psbt/partial_input.go +++ b/btcutil/psbt/partial_input.go @@ -37,9 +37,7 @@ type PInput struct { // NOTE: Only one of the two arguments should be specified, with the other // being `nil`; otherwise the created PsbtInput object will fail IsSane() // checks and will not be usable. -func NewPsbtInput(nonWitnessUtxo *wire.MsgTx, - witnessUtxo *wire.TxOut) *PInput { - +func NewPsbtInput(nonWitnessUtxo *wire.MsgTx, witnessUtxo *wire.TxOut) *PInput { return &PInput{ NonWitnessUtxo: nonWitnessUtxo, WitnessUtxo: witnessUtxo, @@ -57,7 +55,6 @@ func NewPsbtInput(nonWitnessUtxo *wire.MsgTx, // IsSane returns true only if there are no conflicting values in the Psbt // PInput. For segwit v0 no checks are currently implemented. func (pi *PInput) IsSane() bool { - // TODO(guggero): Implement sanity checks for segwit v1. For segwit v0 // it is unsafe to only rely on the witness UTXO so we don't check that // only one is set anymore. @@ -69,12 +66,12 @@ func (pi *PInput) IsSane() bool { // deserialize attempts to deserialize a new PInput from the passed io.Reader. func (pi *PInput) deserialize(r io.Reader) error { for { - keyint, keydata, err := getKey(r) + keyCode, keyData, err := getKey(r) if err != nil { return err } - if keyint == -1 { - // Reached separator byte + if keyCode == -1 { + // Reached separator byte, this section is done. break } value, err := wire.ReadVarBytes( @@ -84,14 +81,14 @@ func (pi *PInput) deserialize(r io.Reader) error { return err } - switch InputType(keyint) { + switch InputType(keyCode) { case NonWitnessUtxoType: if pi.NonWitnessUtxo != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } tx := wire.NewMsgTx(2) @@ -105,8 +102,8 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.WitnessUtxo != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } txout, err := readTxOut(value) if err != nil { @@ -116,7 +113,7 @@ func (pi *PInput) deserialize(r io.Reader) error { case PartialSigType: newPartialSig := PartialSig{ - PubKey: keydata, + PubKey: keyData, Signature: value, } @@ -124,7 +121,7 @@ func (pi *PInput) deserialize(r io.Reader) error { return ErrInvalidPsbtFormat } - // Duplicate keys are not allowed + // Duplicate keys are not allowed. for _, x := range pi.PartialSigs { if bytes.Equal(x.PubKey, newPartialSig.PubKey) { return ErrDuplicateKey @@ -137,27 +134,27 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.SighashType != 0 { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } - // Bounds check on value here since the sighash type must be a - // 32-bit unsigned integer. + // Bounds check on value here since the sighash type + // must be a 32-bit unsigned integer. if len(value) != 4 { - return ErrInvalidKeydata + return ErrInvalidKeyData } - shtype := txscript.SigHashType( + sighashType := txscript.SigHashType( binary.LittleEndian.Uint32(value), ) - pi.SighashType = shtype + pi.SighashType = sighashType case RedeemScriptInputType: if pi.RedeemScript != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } pi.RedeemScript = value @@ -165,13 +162,13 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.WitnessScript != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } pi.WitnessScript = value case Bip32DerivationInputType: - if !validatePubkey(keydata) { + if !validatePubkey(keyData) { return ErrInvalidPsbtFormat } master, derivationPath, err := ReadBip32Derivation( @@ -183,7 +180,7 @@ func (pi *PInput) deserialize(r io.Reader) error { // Duplicate keys are not allowed for _, x := range pi.Bip32Derivation { - if bytes.Equal(x.PubKey, keydata) { + if bytes.Equal(x.PubKey, keyData) { return ErrDuplicateKey } } @@ -191,7 +188,7 @@ func (pi *PInput) deserialize(r io.Reader) error { pi.Bip32Derivation = append( pi.Bip32Derivation, &Bip32Derivation{ - PubKey: keydata, + PubKey: keyData, MasterKeyFingerprint: master, Bip32Path: derivationPath, }, @@ -201,8 +198,8 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.FinalScriptSig != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } pi.FinalScriptSig = value @@ -211,8 +208,8 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.FinalScriptWitness != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } pi.FinalScriptWitness = value @@ -221,26 +218,26 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.TaprootKeySpendSig != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } // The signature can either be 64 or 65 bytes. switch { case len(value) == schnorrSigMinLength: if !validateSchnorrSignature(value) { - return ErrInvalidKeydata + return ErrInvalidKeyData } case len(value) == schnorrSigMaxLength: if !validateSchnorrSignature( value[0:schnorrSigMinLength], ) { - return ErrInvalidKeydata + return ErrInvalidKeyData } default: - return ErrInvalidKeydata + return ErrInvalidKeyData } pi.TaprootKeySpendSig = value @@ -248,13 +245,13 @@ func (pi *PInput) deserialize(r io.Reader) error { case TaprootScriptSpendSignatureType: // The key data for the script spend signature is: // - if len(keydata) != 32*2 { - return ErrInvalidKeydata + if len(keyData) != 32*2 { + return ErrInvalidKeyData } newPartialSig := TaprootScriptSpendSig{ - XOnlyPubKey: keydata[:32], - LeafHash: keydata[32:], + XOnlyPubKey: keyData[:32], + LeafHash: keyData[32:], } // The signature can either be 64 or 65 bytes. @@ -270,11 +267,11 @@ func (pi *PInput) deserialize(r io.Reader) error { ) default: - return ErrInvalidKeydata + return ErrInvalidKeyData } if !newPartialSig.checkValid() { - return ErrInvalidKeydata + return ErrInvalidKeyData } // Duplicate keys are not allowed. @@ -290,11 +287,11 @@ func (pi *PInput) deserialize(r io.Reader) error { case TaprootLeafScriptType: if len(value) < 1 { - return ErrInvalidKeydata + return ErrInvalidKeyData } newLeafScript := TaprootTapLeafScript{ - ControlBlock: keydata, + ControlBlock: keyData, Script: value[:len(value)-1], LeafVersion: txscript.TapscriptLeafVersion( value[len(value)-1], @@ -302,7 +299,7 @@ func (pi *PInput) deserialize(r io.Reader) error { } if !newLeafScript.checkValid() { - return ErrInvalidKeydata + return ErrInvalidKeyData } // Duplicate keys are not allowed. @@ -320,12 +317,12 @@ func (pi *PInput) deserialize(r io.Reader) error { ) case TaprootBip32DerivationInputType: - if !validateXOnlyPubkey(keydata) { - return ErrInvalidKeydata + if !validateXOnlyPubkey(keyData) { + return ErrInvalidKeyData } taprootDerivation, err := ReadTaprootBip32Derivation( - keydata, value, + keyData, value, ) if err != nil { return err @@ -333,7 +330,7 @@ func (pi *PInput) deserialize(r io.Reader) error { // Duplicate keys are not allowed. for _, x := range pi.TaprootBip32Derivation { - if bytes.Equal(x.XOnlyPubKey, keydata) { + if bytes.Equal(x.XOnlyPubKey, keyData) { return ErrDuplicateKey } } @@ -346,12 +343,12 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.TaprootInternalKey != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } if !validateXOnlyPubkey(value) { - return ErrInvalidKeydata + return ErrInvalidKeyData } pi.TaprootInternalKey = value @@ -360,25 +357,27 @@ func (pi *PInput) deserialize(r io.Reader) error { if pi.TaprootMerkleRoot != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } pi.TaprootMerkleRoot = value default: // A fall through case for any proprietary types. - keyintanddata := []byte{byte(keyint)} - keyintanddata = append(keyintanddata, keydata...) + keyCodeAndData := append( + []byte{byte(keyCode)}, keyData..., + ) newUnknown := &Unknown{ - Key: keyintanddata, + Key: keyCodeAndData, Value: value, } - // Duplicate key+keydata are not allowed + // Duplicate key+keyData are not allowed. for _, x := range pi.Unknowns { if bytes.Equal(x.Key, newUnknown.Key) && bytes.Equal(x.Value, newUnknown.Value) { + return ErrDuplicateKey } } @@ -392,7 +391,6 @@ func (pi *PInput) deserialize(r io.Reader) error { // serialize attempts to serialize the target PInput into the passed io.Writer. func (pi *PInput) serialize(w io.Writer) error { - if !pi.IsSane() { return ErrInvalidPsbtFormat } @@ -595,7 +593,7 @@ func (pi *PInput) serialize(w io.Writer) error { } // Unknown is a special case; we don't have a key type, only a key and - // a value field + // a value field. for _, kv := range pi.Unknowns { err := serializeKVpair(w, kv.Key, kv.Value) if err != nil { diff --git a/btcutil/psbt/partial_output.go b/btcutil/psbt/partial_output.go index f0e90406db..9b4cd182f7 100644 --- a/btcutil/psbt/partial_output.go +++ b/btcutil/psbt/partial_output.go @@ -34,12 +34,12 @@ func NewPsbtOutput(redeemScript []byte, witnessScript []byte, // deserialize attempts to recode a new POutput from the passed io.Reader. func (po *POutput) deserialize(r io.Reader) error { for { - keyint, keydata, err := getKey(r) + keyCode, keyData, err := getKey(r) if err != nil { return err } - if keyint == -1 { - // Reached separator byte + if keyCode == -1 { + // Reached separator byte, this section is done. break } @@ -50,14 +50,14 @@ func (po *POutput) deserialize(r io.Reader) error { return err } - switch OutputType(keyint) { + switch OutputType(keyCode) { case RedeemScriptOutputType: if po.RedeemScript != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } po.RedeemScript = value @@ -65,14 +65,14 @@ func (po *POutput) deserialize(r io.Reader) error { if po.WitnessScript != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } po.WitnessScript = value case Bip32DerivationOutputType: - if !validatePubkey(keydata) { - return ErrInvalidKeydata + if !validatePubkey(keyData) { + return ErrInvalidKeyData } master, derivationPath, err := ReadBip32Derivation( value, @@ -81,16 +81,16 @@ func (po *POutput) deserialize(r io.Reader) error { return err } - // Duplicate keys are not allowed + // Duplicate keys are not allowed. for _, x := range po.Bip32Derivation { - if bytes.Equal(x.PubKey, keydata) { + if bytes.Equal(x.PubKey, keyData) { return ErrDuplicateKey } } po.Bip32Derivation = append(po.Bip32Derivation, &Bip32Derivation{ - PubKey: keydata, + PubKey: keyData, MasterKeyFingerprint: master, Bip32Path: derivationPath, }, @@ -100,12 +100,12 @@ func (po *POutput) deserialize(r io.Reader) error { if po.TaprootInternalKey != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } if !validateXOnlyPubkey(value) { - return ErrInvalidKeydata + return ErrInvalidKeyData } po.TaprootInternalKey = value @@ -114,19 +114,19 @@ func (po *POutput) deserialize(r io.Reader) error { if po.TaprootTapTree != nil { return ErrDuplicateKey } - if keydata != nil { - return ErrInvalidKeydata + if keyData != nil { + return ErrInvalidKeyData } po.TaprootTapTree = value case TaprootBip32DerivationOutputType: - if !validateXOnlyPubkey(keydata) { - return ErrInvalidKeydata + if !validateXOnlyPubkey(keyData) { + return ErrInvalidKeyData } taprootDerivation, err := ReadTaprootBip32Derivation( - keydata, value, + keyData, value, ) if err != nil { return err @@ -134,7 +134,7 @@ func (po *POutput) deserialize(r io.Reader) error { // Duplicate keys are not allowed. for _, x := range po.TaprootBip32Derivation { - if bytes.Equal(x.XOnlyPubKey, keydata) { + if bytes.Equal(x.XOnlyPubKey, keyData) { return ErrDuplicateKey } } diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go index 7241bdb685..7b3b5800ea 100644 --- a/btcutil/psbt/psbt.go +++ b/btcutil/psbt/psbt.go @@ -22,7 +22,7 @@ import ( const psbtMagicLength = 5 var ( - // psbtMagic is the separator + // psbtMagic is the separator. psbtMagic = [psbtMagicLength]byte{0x70, 0x73, 0x62, 0x74, 0xff, // = "psbt" + 0xff sep } @@ -34,7 +34,7 @@ var ( const MaxPsbtValueLength = 4000000 // MaxPsbtKeyLength is the length of the largest key that we'll successfully -// deserialize from the wire. Anything more will return ErrInvalidKeydata. +// deserialize from the wire. Anything more will return ErrInvalidKeyData. const MaxPsbtKeyLength = 10000 var ( @@ -47,40 +47,41 @@ var ( // due to having the same key repeated in the same key-value pair. ErrDuplicateKey = errors.New("Invalid Psbt due to duplicate key") - // ErrInvalidKeydata indicates that a key-value pair in the PSBT + // ErrInvalidKeyData indicates that a key-value pair in the PSBT // serialization contains data in the key which is not valid. - ErrInvalidKeydata = errors.New("Invalid key data") + ErrInvalidKeyData = errors.New("Invalid key data") - // ErrInvalidMagicBytes indicates that a passed Psbt serialization is invalid - // due to having incorrect magic bytes. - ErrInvalidMagicBytes = errors.New("Invalid Psbt due to incorrect magic bytes") + // ErrInvalidMagicBytes indicates that a passed Psbt serialization is + // invalid due to having incorrect magic bytes. + ErrInvalidMagicBytes = errors.New("Invalid Psbt due to incorrect " + + "magic bytes") - // ErrInvalidRawTxSigned indicates that the raw serialized transaction in the - // global section of the passed Psbt serialization is invalid because it - // contains scriptSigs/witnesses (i.e. is fully or partially signed), which - // is not allowed by BIP174. - ErrInvalidRawTxSigned = errors.New("Invalid Psbt, raw transaction must " + - "be unsigned.") + // ErrInvalidRawTxSigned indicates that the raw serialized transaction + // in the global section of the passed Psbt serialization is invalid + // because it contains scriptSigs/witnesses (i.e. is fully or partially + // signed), which is not allowed by BIP174. + ErrInvalidRawTxSigned = errors.New("Invalid Psbt, raw transaction " + + "must be unsigned.") // ErrInvalidPrevOutNonWitnessTransaction indicates that the transaction // hash (i.e. SHA256^2) of the fully serialized previous transaction - // provided in the NonWitnessUtxo key-value field doesn't match the prevout - // hash in the UnsignedTx field in the PSBT itself. - ErrInvalidPrevOutNonWitnessTransaction = errors.New("Prevout hash does " + - "not match the provided non-witness utxo serialization") + // provided in the NonWitnessUtxo key-value field doesn't match the + // prevout hash in the UnsignedTx field in the PSBT itself. + ErrInvalidPrevOutNonWitnessTransaction = errors.New("Prevout hash " + + "does not match the provided non-witness utxo serialization") // ErrInvalidSignatureForInput indicates that the signature the user is // trying to append to the PSBT is invalid, either because it does // not correspond to the previous transaction hash, or redeem script, // or witness script. // NOTE this does not include ECDSA signature checking. - ErrInvalidSignatureForInput = errors.New("Signature does not correspond " + - "to this input") + ErrInvalidSignatureForInput = errors.New("Signature does not " + + "correspond to this input") - // ErrInputAlreadyFinalized indicates that the PSBT passed to a Finalizer - // already contains the finalized scriptSig or witness. - ErrInputAlreadyFinalized = errors.New("Cannot finalize PSBT, finalized " + - "scriptSig or scriptWitnes already exists") + // ErrInputAlreadyFinalized indicates that the PSBT passed to a + // Finalizer already contains the finalized scriptSig or witness. + ErrInputAlreadyFinalized = errors.New("Cannot finalize PSBT, " + + "finalized scriptSig or scriptWitnes already exists") // ErrIncompletePSBT indicates that the Extractor object // was unable to successfully extract the passed Psbt struct because @@ -99,8 +100,8 @@ var ( ErrInvalidSigHashFlags = errors.New("Invalid Sighash Flags") // ErrUnsupportedScriptType indicates that the redeem script or - // scriptwitness given is not supported by this codebase, or is otherwise - // not valid. + // script witness given is not supported by this codebase, or is + // otherwise not valid. ErrUnsupportedScriptType = errors.New("Unsupported script type") ) @@ -148,7 +149,6 @@ func validateUnsignedTX(tx *wire.MsgTx) bool { // NewFromUnsignedTx creates a new Psbt struct, without any signatures (i.e. // only the global section is non-empty) using the passed unsigned transaction. func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) { - if !validateUnsignedTX(tx) { return nil, ErrInvalidRawTxSigned } @@ -157,14 +157,12 @@ func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) { outSlice := make([]POutput, len(tx.TxOut)) unknownSlice := make([]Unknown, 0) - retPsbt := Packet{ + return &Packet{ UnsignedTx: tx, Inputs: inSlice, Outputs: outSlice, Unknowns: unknownSlice, - } - - return &retPsbt, nil + }, nil } // NewFromRawBytes returns a new instance of a Packet struct created by reading @@ -175,7 +173,6 @@ func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) { // NOTE: To create a Packet from one's own data, rather than reading in a // serialization from a counterparty, one should use a psbt.New. func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { - // If the PSBT is encoded in bas64, then we'll create a new wrapper // reader that'll allow us to incrementally decode the contents of the // io.Reader. @@ -197,11 +194,11 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { // Next we parse the GLOBAL section. There is currently only 1 known // key type, UnsignedTx. We insist this exists first; unknowns are // allowed, but only after. - keyint, keydata, err := getKey(r) + keyCode, keyData, err := getKey(r) if err != nil { return nil, err } - if GlobalType(keyint) != UnsignedTxType || keydata != nil { + if GlobalType(keyCode) != UnsignedTxType || keyData != nil { return nil, ErrInvalidPsbtFormat } @@ -278,7 +275,7 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { outSlice[i] = output } - // Populate the new Packet object + // Populate the new Packet object. newPsbt := Packet{ UnsignedTx: msgTx, Inputs: inSlice, @@ -298,7 +295,6 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { // Serialize creates a binary serialization of the referenced Packet struct // with lexicographical ordering (by key) of the subsections. func (p *Packet) Serialize(w io.Writer) error { - // First we write out the precise set of magic bytes that identify a // valid PSBT transaction. if _, err := w.Write(psbtMagic[:]); err != nil { @@ -382,7 +378,6 @@ func (p *Packet) IsComplete() bool { // SanityCheck checks conditions on a PSBT to ensure that it obeys the // rules of BIP174, and returns true if so, false if not. func (p *Packet) SanityCheck() error { - if !validateUnsignedTX(p.UnsignedTx) { return ErrInvalidRawTxSigned } diff --git a/btcutil/psbt/signer.go b/btcutil/psbt/signer.go index 588265317f..dcbcf93fa3 100644 --- a/btcutil/psbt/signer.go +++ b/btcutil/psbt/signer.go @@ -22,12 +22,12 @@ const ( // attached. SignSuccesful = 0 - // SignFinalized indicates that this input is already finalized, so the provided - // signature was *not* attached + // SignFinalized indicates that this input is already finalized, so the + // provided signature was *not* attached SignFinalized = 1 - // SignInvalid indicates that the provided signature data was not valid. In this case - // an error will also be returned. + // SignInvalid indicates that the provided signature data was not valid. + // In this case an error will also be returned. SignInvalid = -1 ) @@ -73,9 +73,10 @@ func (u *Updater) Sign(inIndex int, sig []byte, pubKey []byte, // // Case 1: if witnessScript is present, it must be of type witness; // if not, signature insertion will of course fail. + pInput := u.Upsbt.Inputs[inIndex] switch { - case u.Upsbt.Inputs[inIndex].WitnessScript != nil: - if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil { + case pInput.WitnessScript != nil: + if pInput.WitnessUtxo == nil { err := nonWitnessToWitness(u.Upsbt, inIndex) if err != nil { return SignInvalid, err @@ -89,12 +90,12 @@ func (u *Updater) Sign(inIndex int, sig []byte, pubKey []byte, // Case 2: no witness script, only redeem script; can be legacy p2sh or // p2sh-wrapped p2wkh. - case u.Upsbt.Inputs[inIndex].RedeemScript != nil: + case pInput.RedeemScript != nil: // We only need to decide if the input is witness, and we don't // rely on the witnessutxo/nonwitnessutxo in the PSBT, instead // we check the redeemScript content. if txscript.IsWitnessProgram(redeemScript) { - if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil { + if pInput.WitnessUtxo == nil { err := nonWitnessToWitness(u.Upsbt, inIndex) if err != nil { return SignInvalid, err @@ -113,9 +114,10 @@ func (u *Updater) Sign(inIndex int, sig []byte, pubKey []byte, // non-p2sh. To check if it's segwit, check the scriptPubKey of the // output. default: - if u.Upsbt.Inputs[inIndex].WitnessUtxo == nil { - outIndex := u.Upsbt.UnsignedTx.TxIn[inIndex].PreviousOutPoint.Index - script := u.Upsbt.Inputs[inIndex].NonWitnessUtxo.TxOut[outIndex].PkScript + if pInput.WitnessUtxo == nil { + txIn := u.Upsbt.UnsignedTx.TxIn[inIndex] + outIndex := txIn.PreviousOutPoint.Index + script := pInput.NonWitnessUtxo.TxOut[outIndex].PkScript if txscript.IsWitnessProgram(script) { err := nonWitnessToWitness(u.Upsbt, inIndex) diff --git a/btcutil/psbt/utils.go b/btcutil/psbt/utils.go index 94a5546a55..65b597d59d 100644 --- a/btcutil/psbt/utils.go +++ b/btcutil/psbt/utils.go @@ -245,7 +245,7 @@ func getKey(r io.Reader) (int, []byte, error) { // Check that we don't attempt to decode a dangerously large key. if count > MaxPsbtKeyLength { - return -1, nil, ErrInvalidKeydata + return -1, nil, ErrInvalidKeyData } // Next, we ready out the designated number of bytes, which may include From 19c7c3d853656fd0b47a6df0f3e7260e20fc85cf Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 27 Jan 2023 15:30:43 +0100 Subject: [PATCH 0753/1056] psbt: allow Unknowns in outputs --- btcutil/psbt/partial_output.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/btcutil/psbt/partial_output.go b/btcutil/psbt/partial_output.go index 9b4cd182f7..86e476457d 100644 --- a/btcutil/psbt/partial_output.go +++ b/btcutil/psbt/partial_output.go @@ -17,6 +17,7 @@ type POutput struct { TaprootInternalKey []byte TaprootTapTree []byte TaprootBip32Derivation []*TaprootBip32Derivation + Unknowns []*Unknown } // NewPsbtOutput creates an instance of PsbtOutput; the three parameters @@ -144,8 +145,25 @@ func (po *POutput) deserialize(r io.Reader) error { ) default: - // Unknown type is allowed for inputs but not outputs. - return ErrInvalidPsbtFormat + // A fall through case for any proprietary types. + keyCodeAndData := append( + []byte{byte(keyCode)}, keyData..., + ) + newUnknown := &Unknown{ + Key: keyCodeAndData, + Value: value, + } + + // Duplicate key+keyData are not allowed. + for _, x := range po.Unknowns { + if bytes.Equal(x.Key, newUnknown.Key) && + bytes.Equal(x.Value, newUnknown.Value) { + + return ErrDuplicateKey + } + } + + po.Unknowns = append(po.Unknowns, newUnknown) } } @@ -228,5 +246,14 @@ func (po *POutput) serialize(w io.Writer) error { } } + // Unknown is a special case; we don't have a key type, only a key and + // a value field + for _, kv := range po.Unknowns { + err := serializeKVpair(w, kv.Key, kv.Value) + if err != nil { + return err + } + } + return nil } From 5ebbb1bb9163e5dce38d2f1441a316a989c9d7d1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 27 Jan 2023 15:30:44 +0100 Subject: [PATCH 0754/1056] psbt: encode global unknowns --- btcutil/psbt/psbt.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go index 7b3b5800ea..00332d67ef 100644 --- a/btcutil/psbt/psbt.go +++ b/btcutil/psbt/psbt.go @@ -319,6 +319,15 @@ func (p *Packet) Serialize(w io.Writer) error { return err } + // Unknown is a special case; we don't have a key type, only a key and + // a value field + for _, kv := range p.Unknowns { + err := serializeKVpair(w, kv.Key, kv.Value) + if err != nil { + return err + } + } + // With that our global section is done, so we'll write out the // separator. separator := []byte{0x00} From 6c81c664bb25af53cb18c8449c32d2c1d7d1f64a Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 27 Jan 2023 15:30:45 +0100 Subject: [PATCH 0755/1056] psbt: use pointer slice for global unknowns To unify the way the unknown fields are handled, we change the global ones to a slice of pointers as well. This makes it easier to add generic handler code for unknown fields, if they are uniform across the levels (global, input, output). --- btcutil/psbt/psbt.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go index 00332d67ef..964061bdc5 100644 --- a/btcutil/psbt/psbt.go +++ b/btcutil/psbt/psbt.go @@ -113,7 +113,7 @@ type Unknown struct { Value []byte } -// Packet is the actual psbt repreesntation. It is a is a set of 1 + N + M +// Packet is the actual psbt representation. It is a set of 1 + N + M // key-value pair lists, 1 global, defining the unsigned transaction structure // with N inputs and M outputs. These key-value pairs can contain scripts, // signatures, key derivations and other transaction-defining data. @@ -130,7 +130,7 @@ type Packet struct { Outputs []POutput // Unknowns are the set of custom types (global only) within this PSBT. - Unknowns []Unknown + Unknowns []*Unknown } // validateUnsignedTx returns true if the transaction is unsigned. Note that @@ -155,7 +155,7 @@ func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) { inSlice := make([]PInput, len(tx.TxIn)) outSlice := make([]POutput, len(tx.TxOut)) - unknownSlice := make([]Unknown, 0) + unknownSlice := make([]*Unknown, 0) return &Packet{ UnsignedTx: tx, @@ -224,7 +224,7 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { // Next we parse any unknowns that may be present, making sure that we // break at the separator. - var unknownSlice []Unknown + var unknownSlice []*Unknown for { keyint, keydata, err := getKey(r) if err != nil { @@ -244,7 +244,7 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { keyintanddata := []byte{byte(keyint)} keyintanddata = append(keyintanddata, keydata...) - newUnknown := Unknown{ + newUnknown := &Unknown{ Key: keyintanddata, Value: value, } From bb0a2f3790eebcf9aad402df3bb3f53d9142f358 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 27 Jan 2023 15:30:46 +0100 Subject: [PATCH 0756/1056] psbt: add unit test for unknowns --- btcutil/psbt/psbt_test.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go index 1ce4780d84..6ed154f895 100644 --- a/btcutil/psbt/psbt_test.go +++ b/btcutil/psbt/psbt_test.go @@ -1502,3 +1502,28 @@ func TestWitnessForNonWitnessUtxo(t *testing.T) { t.Fatalf("unable to extract funding TX: %v", err) } } + +// TestUnknowns tests that we can parse and serialize unknown fields on all +// three levels (global, input, output). +func TestUnknowns(t *testing.T) { + packetWithUnknowns := "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" + + packet, err := NewFromRawBytes( + strings.NewReader(packetWithUnknowns), true, + ) + require.NoError(t, err) + + require.Len(t, packet.Unknowns, 2) + + require.Len(t, packet.Inputs, 1) + require.Len(t, packet.Inputs[0].Unknowns, 10) + + require.Len(t, packet.Outputs, 2) + require.Len(t, packet.Outputs[0].Unknowns, 7) + + // Convert it to base64 again to make sure the fields are also + // serialized. + encoded, err := packet.B64Encode() + require.NoError(t, err) + require.Equal(t, packetWithUnknowns, encoded) +} From 52082fcbf9273b28e152fa27a29c7f63863b1518 Mon Sep 17 00:00:00 2001 From: Hristo Georgiev Date: Fri, 10 Feb 2023 23:22:37 +0200 Subject: [PATCH 0757/1056] docs: Update Go version as per the Readme. --- docs/code_contribution_guidelines.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/code_contribution_guidelines.md b/docs/code_contribution_guidelines.md index c0a7eecc5f..05d630b3c5 100644 --- a/docs/code_contribution_guidelines.md +++ b/docs/code_contribution_guidelines.md @@ -297,7 +297,7 @@ Rejoice as you will now be listed as a [contributor](https://github.com/btcsuite ## Contribution Checklist -- [  ] All changes are Go version 1.3 compliant +- [  ] All changes are Go version 1.16 compliant - [  ] The code being submitted is commented according to the [Code Documentation and Commenting](#CodeDocumentation) section - [  ] For new code: Code is accompanied by tests which exercise both From 902f797b0c4b3af3f7196d2f5d2343931d1b2bdf Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 13 Feb 2023 17:33:00 +0900 Subject: [PATCH 0758/1056] txscript: Fix typo in IsUnspendable() comment IsUnspendable allows outputs, not inputs to be pruned instantly. --- txscript/script.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/script.go b/txscript/script.go index 602c1fced1..70589180f7 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -504,7 +504,7 @@ func checkScriptParses(scriptVersion uint16, script []byte) error { } // IsUnspendable returns whether the passed public key script is unspendable, or -// guaranteed to fail at execution. This allows inputs to be pruned instantly +// guaranteed to fail at execution. This allows outputs to be pruned instantly // when entering the UTXO set. // // NOTE: This function is only valid for version 0 scripts. Since the function From e1e4196fbc2444deb16fc0221a8142691198872c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 27 Feb 2023 12:38:11 +0100 Subject: [PATCH 0759/1056] txscript: allow script builder capacity to be specified The default script builder allocates 500 bytes of memory for each script. That is quite large for most applications and therefore wastes a lot of memory when only small scripts are created. To avoid breaking backward compatibility, we add a new functional option to the NewScriptBuilder function that allows the user to specify the initial allocation size. --- txscript/scriptbuilder.go | 64 ++++++++++++++++++++++++++-------- txscript/scriptbuilder_test.go | 30 ++++++++++++++++ 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/txscript/scriptbuilder.go b/txscript/scriptbuilder.go index 7984dd9661..fa2bc073f0 100644 --- a/txscript/scriptbuilder.go +++ b/txscript/scriptbuilder.go @@ -13,11 +13,41 @@ const ( // defaultScriptAlloc is the default size used for the backing array // for a script being built by the ScriptBuilder. The array will // dynamically grow as needed, but this figure is intended to provide - // enough space for vast majority of scripts without needing to grow the - // backing array multiple times. + // enough space for the vast majority of scripts without needing to grow + // the backing array multiple times. Can be overwritten with the + // WithScriptAllocSize functional option where expected script sizes are + // known. defaultScriptAlloc = 500 ) +// scriptBuilderConfig is a configuration struct that can be used to modify the +// initialization of a ScriptBuilder. +type scriptBuilderConfig struct { + // allocSize specifies the initial size of the backing array for the + // script builder. + allocSize int +} + +// defaultScriptBuilderConfig returns a new scriptBuilderConfig with the +// default values set. +func defaultScriptBuilderConfig() *scriptBuilderConfig { + return &scriptBuilderConfig{ + allocSize: defaultScriptAlloc, + } +} + +// ScriptBuilderOpt is a functional option type which is used to modify the +// initialization of a ScriptBuilder. +type ScriptBuilderOpt func(*scriptBuilderConfig) + +// WithScriptAllocSize specifies the initial size of the backing array for the +// script builder. +func WithScriptAllocSize(size int) ScriptBuilderOpt { + return func(cfg *scriptBuilderConfig) { + cfg.allocSize = size + } +} + // ErrScriptNotCanonical identifies a non-canonical script. The caller can use // a type assertion to detect this error type. type ErrScriptNotCanonical string @@ -37,16 +67,17 @@ func (e ErrScriptNotCanonical) Error() string { // For example, the following would build a 2-of-3 multisig script for usage in // a pay-to-script-hash (although in this situation MultiSigScript() would be a // better choice to generate the script): -// builder := txscript.NewScriptBuilder() -// builder.AddOp(txscript.OP_2).AddData(pubKey1).AddData(pubKey2) -// builder.AddData(pubKey3).AddOp(txscript.OP_3) -// builder.AddOp(txscript.OP_CHECKMULTISIG) -// script, err := builder.Script() -// if err != nil { -// // Handle the error. -// return -// } -// fmt.Printf("Final multi-sig script: %x\n", script) +// +// builder := txscript.NewScriptBuilder() +// builder.AddOp(txscript.OP_2).AddData(pubKey1).AddData(pubKey2) +// builder.AddData(pubKey3).AddOp(txscript.OP_3) +// builder.AddOp(txscript.OP_CHECKMULTISIG) +// script, err := builder.Script() +// if err != nil { +// // Handle the error. +// return +// } +// fmt.Printf("Final multi-sig script: %x\n", script) type ScriptBuilder struct { script []byte err error @@ -267,8 +298,13 @@ func (b *ScriptBuilder) Script() ([]byte, error) { // NewScriptBuilder returns a new instance of a script builder. See // ScriptBuilder for details. -func NewScriptBuilder() *ScriptBuilder { +func NewScriptBuilder(opts ...ScriptBuilderOpt) *ScriptBuilder { + cfg := defaultScriptBuilderConfig() + for _, opt := range opts { + opt(cfg) + } + return &ScriptBuilder{ - script: make([]byte, 0, defaultScriptAlloc), + script: make([]byte, 0, cfg.allocSize), } } diff --git a/txscript/scriptbuilder_test.go b/txscript/scriptbuilder_test.go index 89f2b861ab..baf9526a26 100644 --- a/txscript/scriptbuilder_test.go +++ b/txscript/scriptbuilder_test.go @@ -7,8 +7,38 @@ package txscript import ( "bytes" "testing" + + "github.com/stretchr/testify/require" ) +// TestScriptBuilderAlloc tests that the pre-allocation for a script via the +// NewScriptBuilder function works as expected. +func TestScriptBuilderAlloc(t *testing.T) { + // Using the default value, we should get a script with a capacity of + // 500 bytes, which is quite large for most scripts. + defaultBuilder := NewScriptBuilder() + require.EqualValues(t, defaultScriptAlloc, cap(defaultBuilder.script)) + + const allocSize = 23 + builder := NewScriptBuilder(WithScriptAllocSize(allocSize)) + + // The initial capacity of the script should be set to the explicit + // value. + require.EqualValues(t, allocSize, cap(builder.script)) + + builder.AddOp(OP_HASH160) + builder.AddData(make([]byte, 20)) + builder.AddOp(OP_EQUAL) + script, err := builder.Script() + require.NoError(t, err) + + require.Len(t, script, allocSize) + + // The capacity shouldn't have changed, as the script should've fit just + // fine. + require.EqualValues(t, allocSize, cap(builder.script)) +} + // TestScriptBuilderAddOp tests that pushing opcodes to a script via the // ScriptBuilder API works as expected. func TestScriptBuilderAddOp(t *testing.T) { From a18c2cfbf8929b7950da34b09c1dec27646a61d6 Mon Sep 17 00:00:00 2001 From: martonp Date: Fri, 3 Mar 2023 14:08:04 -0500 Subject: [PATCH 0760/1056] Export MakeScritpNum, AsSmallInt, and IsSmallInt --- txscript/opcode.go | 4 ++-- txscript/script.go | 12 ++++++------ txscript/scriptnum.go | 8 ++++---- txscript/scriptnum_test.go | 6 +++--- txscript/stack.go | 4 ++-- txscript/standard.go | 22 +++++++++++----------- 6 files changed, 28 insertions(+), 28 deletions(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 6e0434423e..943ac506a2 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1073,7 +1073,7 @@ func opcodeCheckLockTimeVerify(op *opcode, data []byte, vm *Engine) error { if err != nil { return err } - lockTime, err := makeScriptNum(so, vm.dstack.verifyMinimalData, 5) + lockTime, err := MakeScriptNum(so, vm.dstack.verifyMinimalData, 5) if err != nil { return err } @@ -1147,7 +1147,7 @@ func opcodeCheckSequenceVerify(op *opcode, data []byte, vm *Engine) error { if err != nil { return err } - stackSequence, err := makeScriptNum(so, vm.dstack.verifyMinimalData, 5) + stackSequence, err := MakeScriptNum(so, vm.dstack.verifyMinimalData, 5) if err != nil { return err } diff --git a/txscript/script.go b/txscript/script.go index 70589180f7..ec213dd663 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -40,13 +40,13 @@ const ( MaxScriptElementSize = 520 // Max bytes pushable to the stack. ) -// isSmallInt returns whether or not the opcode is considered a small integer, +// IsSmallInt returns whether or not the opcode is considered a small integer, // which is an OP_0, or OP_1 through OP_16. // // NOTE: This function is only valid for version 0 opcodes. Since the function // does not accept a script version, the results are undefined for other script // versions. -func isSmallInt(op byte) bool { +func IsSmallInt(op byte) bool { return op == OP_0 || (op >= OP_1 && op <= OP_16) } @@ -294,9 +294,9 @@ func removeOpcodeByData(script []byte, dataToRemove []byte) []byte { return result } -// asSmallInt returns the passed opcode, which must be true according to -// isSmallInt(), as an integer. -func asSmallInt(op byte) int { +// AsSmallInt returns the passed opcode, which must be true according to +// IsSmallInt(), as an integer. +func AsSmallInt(op byte) int { if op == OP_0 { return 0 } @@ -342,7 +342,7 @@ func countSigOpsV0(script []byte, precise bool) int { // operations in new script versions should move to // aggregated schemes such as Schnorr instead. if precise && prevOp >= OP_1 && prevOp <= OP_16 { - numSigOps += asSmallInt(prevOp) + numSigOps += AsSmallInt(prevOp) } else { numSigOps += MaxPubKeysPerMultiSig } diff --git a/txscript/scriptnum.go b/txscript/scriptnum.go index 81f2636121..b951fd8537 100644 --- a/txscript/scriptnum.go +++ b/txscript/scriptnum.go @@ -51,7 +51,7 @@ const ( // method to get the serialized representation (including values that overflow). // // Then, whenever data is interpreted as an integer, it is converted to this -// type by using the makeScriptNum function which will return an error if the +// type by using the MakeScriptNum function which will return an error if the // number is out of range or not minimally encoded depending on parameters. // Since all numeric opcodes involve pulling data from the stack and // interpreting it as an integer, it provides the required behavior. @@ -151,7 +151,7 @@ func (n scriptNum) Bytes() []byte { // provide this behavior. // // In practice, for most opcodes, the number should never be out of range since -// it will have been created with makeScriptNum using the defaultScriptLen +// it will have been created with MakeScriptNum using the defaultScriptLen // value, which rejects them. In case something in the future ends up calling // this function against the result of some arithmetic, which IS allowed to be // out of range before being reinterpreted as an integer, this will provide the @@ -168,7 +168,7 @@ func (n scriptNum) Int32() int32 { return int32(n) } -// makeScriptNum interprets the passed serialized bytes as an encoded integer +// MakeScriptNum interprets the passed serialized bytes as an encoded integer // and returns the result as a script number. // // Since the consensus rules dictate that serialized bytes interpreted as ints @@ -194,7 +194,7 @@ func (n scriptNum) Int32() int32 { // overflows. // // See the Bytes function documentation for example encodings. -func makeScriptNum(v []byte, requireMinimal bool, scriptNumLen int) (scriptNum, error) { +func MakeScriptNum(v []byte, requireMinimal bool, scriptNumLen int) (scriptNum, error) { // Interpreting data requires that it is not larger than // the the passed scriptNumLen value. if len(v) > scriptNumLen { diff --git a/txscript/scriptnum_test.go b/txscript/scriptnum_test.go index 668f912f6f..9aba3a7062 100644 --- a/txscript/scriptnum_test.go +++ b/txscript/scriptnum_test.go @@ -195,15 +195,15 @@ func TestMakeScriptNum(t *testing.T) { for _, test := range tests { // Ensure the error code is of the expected type and the error // code matches the value specified in the test instance. - gotNum, err := makeScriptNum(test.serialized, test.minimalEncoding, + gotNum, err := MakeScriptNum(test.serialized, test.minimalEncoding, test.numLen) if e := tstCheckScriptError(err, test.err); e != nil { - t.Errorf("makeScriptNum(%#x): %v", test.serialized, e) + t.Errorf("MakeScriptNum(%#x): %v", test.serialized, e) continue } if gotNum != test.num { - t.Errorf("makeScriptNum(%#x): did not get expected "+ + t.Errorf("MakeScriptNum(%#x): did not get expected "+ "number - got %d, want %d", test.serialized, gotNum, test.num) continue diff --git a/txscript/stack.go b/txscript/stack.go index 923047d93e..900a030b2d 100644 --- a/txscript/stack.go +++ b/txscript/stack.go @@ -86,7 +86,7 @@ func (s *stack) PopInt() (scriptNum, error) { return 0, err } - return makeScriptNum(so, s.verifyMinimalData, maxScriptNumLen) + return MakeScriptNum(so, s.verifyMinimalData, maxScriptNumLen) } // PopBool pops the value off the top of the stack, converts it into a bool, and @@ -123,7 +123,7 @@ func (s *stack) PeekInt(idx int32) (scriptNum, error) { return 0, err } - return makeScriptNum(so, s.verifyMinimalData, maxScriptNumLen) + return MakeScriptNum(so, s.verifyMinimalData, maxScriptNumLen) } // PeekBool returns the Nth item on the stack as a bool without removing it. diff --git a/txscript/standard.go b/txscript/standard.go index aa7a7970d7..5ef2ad167f 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -238,10 +238,10 @@ func extractMultisigScriptDetails(scriptVersion uint16, script []byte, extractPu // The first opcode must be a small integer specifying the number of // signatures required. tokenizer := MakeScriptTokenizer(scriptVersion, script) - if !tokenizer.Next() || !isSmallInt(tokenizer.Opcode()) { + if !tokenizer.Next() || !IsSmallInt(tokenizer.Opcode()) { return multiSigDetails{} } - requiredSigs := asSmallInt(tokenizer.Opcode()) + requiredSigs := AsSmallInt(tokenizer.Opcode()) // The next series of opcodes must either push public keys or be a small // integer specifying the number of public keys. @@ -251,7 +251,7 @@ func extractMultisigScriptDetails(scriptVersion uint16, script []byte, extractPu pubKeys = make([][]byte, 0, MaxPubKeysPerMultiSig) } for tokenizer.Next() { - if isSmallInt(tokenizer.Opcode()) { + if IsSmallInt(tokenizer.Opcode()) { break } @@ -271,7 +271,7 @@ func extractMultisigScriptDetails(scriptVersion uint16, script []byte, extractPu // The next opcode must be a small integer specifying the number of public // keys required. op := tokenizer.Opcode() - if !isSmallInt(op) || asSmallInt(op) != numPubKeys { + if !IsSmallInt(op) || AsSmallInt(op) != numPubKeys { return multiSigDetails{} } @@ -422,11 +422,11 @@ func extractWitnessProgramInfo(script []byte) (int, []byte, bool) { // The first opcode must be a small int. if !tokenizer.Next() || - !isSmallInt(tokenizer.Opcode()) { + !IsSmallInt(tokenizer.Opcode()) { return 0, nil, false } - version := asSmallInt(tokenizer.Opcode()) + version := AsSmallInt(tokenizer.Opcode()) // The second opcode must be a canonical data push, the length of the // data push is bounded to 40 by the initial check on overall script @@ -520,7 +520,7 @@ func isNullDataScript(scriptVersion uint16, script []byte) bool { // OP_RETURN followed by data push up to MaxDataCarrierSize bytes. tokenizer := MakeScriptTokenizer(scriptVersion, script[1:]) return tokenizer.Next() && tokenizer.Done() && - (isSmallInt(tokenizer.Opcode()) || tokenizer.Opcode() <= OP_PUSHDATA4) && + (IsSmallInt(tokenizer.Opcode()) || tokenizer.Opcode() <= OP_PUSHDATA4) && len(tokenizer.Data()) <= MaxDataCarrierSize } @@ -627,7 +627,7 @@ func expectedInputs(script []byte, class ScriptClass) int { // the original bitcoind bug where OP_CHECKMULTISIG pops an // additional item from the stack, add an extra expected input // for the extra push that is required to compensate. - return asSmallInt(script[0]) + 1 + return AsSmallInt(script[0]) + 1 case NullDataTy: fallthrough @@ -1119,14 +1119,14 @@ func ExtractAtomicSwapDataPushes(version uint16, pkScript []byte) (*AtomicSwapDa if tplEntry.expectCanonicalInt { switch { case data != nil: - val, err := makeScriptNum(data, true, tplEntry.maxIntBytes) + val, err := MakeScriptNum(data, true, tplEntry.maxIntBytes) if err != nil { return nil, err } tplEntry.extractedInt = int64(val) - case isSmallInt(op): - tplEntry.extractedInt = int64(asSmallInt(op)) + case IsSmallInt(op): + tplEntry.extractedInt = int64(AsSmallInt(op)) // Not an atomic swap script if the opcode does not push an int. default: From d628705118faae4083f42eb30cbb14ed451998b2 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 27 Jul 2021 21:44:57 +0900 Subject: [PATCH 0761/1056] btcd: Add memory profiling flag Enables Go memory profiling. If the cpuprofile shows a lot of time spent on gc, it's useful to then do a memory profile to see where the memory alloctions happen. Unlike the --profile flag, this allows for easy generation of a memory profile for the entire duration of which btcd has been running for in various readble graphs. --- btcd.go | 12 ++++++++++++ config.go | 1 + 2 files changed, 13 insertions(+) diff --git a/btcd.go b/btcd.go index aec55e06eb..8f85311734 100644 --- a/btcd.go +++ b/btcd.go @@ -88,6 +88,18 @@ func btcdMain(serverChan chan<- *server) error { defer pprof.StopCPUProfile() } + // Write mem profile if requested. + if cfg.MemoryProfile != "" { + f, err := os.Create(cfg.MemoryProfile) + if err != nil { + btcdLog.Errorf("Unable to create memory profile: %v", err) + return err + } + defer f.Close() + defer pprof.WriteHeapProfile(f) + defer runtime.GC() + } + // Perform upgrades to btcd as new versions require it. if err := doUpgrades(); err != nil { btcdLog.Errorf("%v", err) diff --git a/config.go b/config.go index 5eca3f2174..656e94df2a 100644 --- a/config.go +++ b/config.go @@ -111,6 +111,7 @@ type config struct { ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"` CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"` + MemoryProfile string `long:"memprofile" description:"Write memory profile to the specified file"` DataDir string `short:"b" long:"datadir" description:"Directory to store data"` DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify =,=,... to set the log level for individual subsystems -- Use show to list available subsystems"` From b554add7161ca7d851d2d584a619857389d5748d Mon Sep 17 00:00:00 2001 From: ziggie Date: Mon, 20 Mar 2023 12:10:18 +0100 Subject: [PATCH 0762/1056] psbt: add verification method for psbt input data the new InputsReadyToSign method makes sure that inputs have either the nonWitnessUtxo or the witnessUtxo data set. --- btcutil/psbt/utils.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/btcutil/psbt/utils.go b/btcutil/psbt/utils.go index 65b597d59d..85bc82f529 100644 --- a/btcutil/psbt/utils.go +++ b/btcutil/psbt/utils.go @@ -398,6 +398,30 @@ func VerifyInputOutputLen(packet *Packet, needInputs, needOutputs bool) error { return nil } +// InputsReadyToSign makes sure that all input data have the previous output +// specified meaning that either nonwitness UTXO or the witness UTXO data is +// specified in the psbt package. This check is necessary because of 2 reasons. +// The sighash calculation is now different for witnessV0 and witnessV1 inputs +// this means we need to check the previous output pkScript for the specific +// type and the second reason is that the sighash calculation for taproot inputs +// include the previous output pkscripts. +func InputsReadyToSign(packet *Packet) error { + err := VerifyInputOutputLen(packet, true, true) + if err != nil { + return err + } + + for i := range packet.UnsignedTx.TxIn { + input := packet.Inputs[i] + if input.NonWitnessUtxo == nil && input.WitnessUtxo == nil { + return fmt.Errorf("invalid PSBT, input with index %d "+ + "missing utxo information", i) + } + } + + return nil +} + // NewFromSignedTx is a utility function to create a packet from an // already-signed transaction. Returned are: an unsigned transaction // serialization, a list of scriptSigs, one per input, and a list of witnesses, From 72ea23ed1e17a95e0379a0c7ec5856c889fb0cd8 Mon Sep 17 00:00:00 2001 From: RycCheen Date: Tue, 21 Feb 2023 19:53:42 +0800 Subject: [PATCH 0763/1056] chainhash: JSON Unmarshal hash from appropriate string. --- chaincfg/chainhash/hash.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index d2c562ae6a..fc059787db 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -116,6 +116,21 @@ func (hash Hash) MarshalJSON() ([]byte, error) { return json.Marshal(hash.String()) } +// UnmarshalJSON parses the hash with JSON appropriate string value. +func (hash *Hash) UnmarshalJSON(input []byte) error { + var sh string + err := json.Unmarshal(input, &sh) + if err != nil { + return err + } + newHash, err := NewHashFromStr(sh) + if err != nil { + return err + } + + return hash.SetBytes(newHash[:]) +} + // NewHash returns a new Hash from a byte slice. An error is returned if // the number of bytes passed in is not HashSize. func NewHash(newHash []byte) (*Hash, error) { From e0e4916afb0814c7fc762dd1652fbc791cbe2f55 Mon Sep 17 00:00:00 2001 From: RycCheen Date: Fri, 24 Feb 2023 10:57:36 +0800 Subject: [PATCH 0764/1056] Supplementary chainhash test cases --- chaincfg/chainhash/hash_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/chaincfg/chainhash/hash_test.go b/chaincfg/chainhash/hash_test.go index 07f54c7763..19f34e3a93 100644 --- a/chaincfg/chainhash/hash_test.go +++ b/chaincfg/chainhash/hash_test.go @@ -7,6 +7,7 @@ package chainhash import ( "bytes" "encoding/hex" + "encoding/json" "testing" ) @@ -194,3 +195,28 @@ func TestNewHashFromStr(t *testing.T) { } } } + +// TestHashJsonMarshal tests json marshal and unmarshal. +func TestHashJsonMarshal(t *testing.T) { + hashStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506" + + hash, err := NewHashFromStr(hashStr) + if err != nil { + t.Errorf("NewHashFromStr error:%v, hashStr:%s", err, hashStr) + } + + hashBytes, err := json.Marshal(hash) + if err != nil { + t.Errorf("Marshal json error:%v, hash:%v", err, hashBytes) + } + + var newHash Hash + err = json.Unmarshal(hashBytes, &newHash) + if err != nil { + t.Errorf("Unmarshal json error:%v, hash:%v", err, hashBytes) + } + + if !hash.IsEqual(&newHash) { + t.Errorf("String: wrong hash string - got %v, want %v", newHash.String(), hashStr) + } +} From 42653cdcd217962b0c6b0a35434ee025dc224408 Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Sat, 4 Mar 2023 22:24:28 +0100 Subject: [PATCH 0765/1056] txscript: fix script typos --- txscript/script.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index ec213dd663..18723067ee 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -74,19 +74,19 @@ func IsPayToScriptHash(script []byte) bool { return isScriptHashScript(script) } -// IsPayToWitnessScriptHash returns true if the is in the standard +// IsPayToWitnessScriptHash returns true if the script is in the standard // pay-to-witness-script-hash (P2WSH) format, false otherwise. func IsPayToWitnessScriptHash(script []byte) bool { return isWitnessScriptHashScript(script) } -// IsPayToWitnessPubKeyHash returns true if the is in the standard +// IsPayToWitnessPubKeyHash returns true if the script is in the standard // pay-to-witness-pubkey-hash (P2WKH) format, false otherwise. func IsPayToWitnessPubKeyHash(script []byte) bool { return isWitnessPubKeyHashScript(script) } -// IsPayToTaproot returns true if if the passed script is a standard +// IsPayToTaproot returns true if the passed script is a standard // pay-to-taproot (PTTR) scripts, and false otherwise. func IsPayToTaproot(script []byte) bool { return isWitnessTaprootScript(script) From 52ede324beb9502f4acf59d24219663bcd14d566 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 14 Apr 2023 17:45:49 +0900 Subject: [PATCH 0766/1056] chaincfg: Update checkpoints The latest checkpoints were from a few years back and hurts ibd. The updated checkpoints are based off of bitcoin core's past assumvalid blocks. --- chaincfg/params.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/chaincfg/params.go b/chaincfg/params.go index 2387c203ae..f0a7a83b79 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -328,6 +328,13 @@ var MainNetParams = Params{ {520000, newHashFromStr("0000000000000000000d26984c0229c9f6962dc74db0a6d525f2f1640396f69c")}, {550000, newHashFromStr("000000000000000000223b7a2298fb1c6c75fb0efc28a4c56853ff4112ec6bc9")}, {560000, newHashFromStr("0000000000000000002c7b276daf6efb2b6aa68e2ce3be67ef925b3264ae7122")}, + {563378, newHashFromStr("0000000000000000000f1c54590ee18d15ec70e68c8cd4cfbadb1b4f11697eee")}, + {597379, newHashFromStr("00000000000000000005f8920febd3925f8272a6a71237563d78c2edfdd09ddf")}, + {623950, newHashFromStr("0000000000000000000f2adce67e49b0b6bdeb9de8b7c3d7e93b21e7fc1e819d")}, + {654683, newHashFromStr("0000000000000000000b9d2ec5a352ecba0592946514a92f14319dc2b367fc72")}, + {691719, newHashFromStr("00000000000000000008a89e854d57e5667df88f1cdef6fde2fbca1de5b639ad")}, + {724466, newHashFromStr("000000000000000000052d314a259755ca65944e68df6b12a067ea8f1f5a7091")}, + {751565, newHashFromStr("00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd")}, }, // Consensus rule change deployments. @@ -565,6 +572,13 @@ var TestNet3Params = Params{ {1100007, newHashFromStr("00000000000abc7b2cd18768ab3dee20857326a818d1946ed6796f42d66dd1e8")}, {1200007, newHashFromStr("00000000000004f2dc41845771909db57e04191714ed8c963f7e56713a7b6cea")}, {1300007, newHashFromStr("0000000072eab69d54df75107c052b26b0395b44f77578184293bf1bb1dbd9fa")}, + {1354312, newHashFromStr("0000000000000037a8cd3e06cd5edbfe9dd1dbcc5dacab279376ef7cfc2b4c75")}, + {1580000, newHashFromStr("00000000000000b7ab6ce61eb6d571003fbe5fe892da4c9b740c49a07542462d")}, + {1692000, newHashFromStr("000000000000056c49030c174179b52a928c870e6e8a822c75973b7970cfbd01")}, + {1864000, newHashFromStr("000000000000006433d1efec504c53ca332b64963c425395515b01977bd7b3b0")}, + {2010000, newHashFromStr("0000000000004ae2f3896ca8ecd41c460a35bf6184e145d91558cece1c688a76")}, + {2143398, newHashFromStr("00000000000163cfb1f97c4e4098a3692c8053ad9cab5ad9c86b338b5c00b8b7")}, + {2344474, newHashFromStr("0000000000000004877fa2d36316398528de4f347df2f8a96f76613a298ce060")}, }, // Consensus rule change deployments. From cfb39f790f8e45fa6d49a3bf6c9e4ff81b392c68 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 27 Apr 2023 21:20:29 +0900 Subject: [PATCH 0767/1056] blockchain: Use slices when fetching utxos Maps have a higher overhead than slices. As slices can be used instead of maps, we avoid the overhead of making a map. --- blockchain/utxoviewpoint.go | 38 ++++++++++++++++++++----------------- blockchain/validate.go | 20 +++++++++---------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 3d1d513a3f..a030c9a9ff 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -503,7 +503,7 @@ func (view *UtxoViewpoint) commit() { // Upon completion of this function, the view will contain an entry for each // requested outpoint. Spent outputs, or those which otherwise don't exist, // will result in a nil entry in the view. -func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints map[wire.OutPoint]struct{}) error { +func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints []wire.OutPoint) error { // Nothing to do if there are no requested outputs. if len(outpoints) == 0 { return nil @@ -517,13 +517,13 @@ func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints map[wire.Out // so other code can use the presence of an entry in the store as a way // to unnecessarily avoid attempting to reload it from the database. return db.View(func(dbTx database.Tx) error { - for outpoint := range outpoints { - entry, err := dbFetchUtxoEntry(dbTx, outpoint) + for i := range outpoints { + entry, err := dbFetchUtxoEntry(dbTx, outpoints[i]) if err != nil { return err } - view.entries[outpoint] = entry + view.entries[outpoints[i]] = entry } return nil @@ -533,25 +533,25 @@ func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints map[wire.Out // fetchUtxos loads the unspent transaction outputs for the provided set of // outputs into the view from the database as needed unless they already exist // in the view in which case they are ignored. -func (view *UtxoViewpoint) fetchUtxos(db database.DB, outpoints map[wire.OutPoint]struct{}) error { +func (view *UtxoViewpoint) fetchUtxos(db database.DB, outpoints []wire.OutPoint) error { // Nothing to do if there are no requested outputs. if len(outpoints) == 0 { return nil } // Filter entries that are already in the view. - neededSet := make(map[wire.OutPoint]struct{}) - for outpoint := range outpoints { + needed := make([]wire.OutPoint, 0, len(outpoints)) + for i := range outpoints { // Already loaded into the current view. - if _, ok := view.entries[outpoint]; ok { + if _, ok := view.entries[outpoints[i]]; ok { continue } - neededSet[outpoint] = struct{}{} + needed = append(needed, outpoints[i]) } // Request the input utxos from the database. - return view.fetchUtxosMain(db, neededSet) + return view.fetchUtxosMain(db, needed) } // fetchInputUtxos loads the unspent transaction outputs for the inputs @@ -572,7 +572,7 @@ func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) // Loop through all of the transaction inputs (except for the coinbase // which has no inputs) collecting them into sets of what is needed and // what is already known (in-flight). - neededSet := make(map[wire.OutPoint]struct{}) + needed := make([]wire.OutPoint, 0, len(transactions)) for i, tx := range transactions[1:] { for _, txIn := range tx.MsgTx().TxIn { // It is acceptable for a transaction input to reference @@ -601,12 +601,12 @@ func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) continue } - neededSet[txIn.PreviousOutPoint] = struct{}{} + needed = append(needed, txIn.PreviousOutPoint) } } // Request the input utxos from the database. - return view.fetchUtxosMain(db, neededSet) + return view.fetchUtxosMain(db, needed) } // NewUtxoViewpoint returns a new empty unspent transaction output view. @@ -626,15 +626,19 @@ func (b *BlockChain) FetchUtxoView(tx *btcutil.Tx) (*UtxoViewpoint, error) { // Create a set of needed outputs based on those referenced by the // inputs of the passed transaction and the outputs of the transaction // itself. - neededSet := make(map[wire.OutPoint]struct{}) + neededLen := len(tx.MsgTx().TxOut) + if !IsCoinBase(tx) { + neededLen += len(tx.MsgTx().TxIn) + } + needed := make([]wire.OutPoint, 0, neededLen) prevOut := wire.OutPoint{Hash: *tx.Hash()} for txOutIdx := range tx.MsgTx().TxOut { prevOut.Index = uint32(txOutIdx) - neededSet[prevOut] = struct{}{} + needed = append(needed, prevOut) } if !IsCoinBase(tx) { for _, txIn := range tx.MsgTx().TxIn { - neededSet[txIn.PreviousOutPoint] = struct{}{} + needed = append(needed, txIn.PreviousOutPoint) } } @@ -642,7 +646,7 @@ func (b *BlockChain) FetchUtxoView(tx *btcutil.Tx) (*UtxoViewpoint, error) { // chain. view := NewUtxoViewpoint() b.chainLock.RLock() - err := view.fetchUtxosMain(b.db, neededSet) + err := view.fetchUtxosMain(b.db, needed) b.chainLock.RUnlock() return view, err } diff --git a/blockchain/validate.go b/blockchain/validate.go index 89971e7fd6..dc7f0abe8e 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -302,8 +302,8 @@ func CheckTransactionSanity(tx *btcutil.Tx) error { // target difficulty as claimed. // // The flags modify the behavior of this function as follows: -// - BFNoPoWCheck: The check to ensure the block hash is less than the target -// difficulty is not performed. +// - BFNoPoWCheck: The check to ensure the block hash is less than the target +// difficulty is not performed. func checkProofOfWork(header *wire.BlockHeader, powLimit *big.Int, flags BehaviorFlags) error { // The target difficulty must be larger than zero. target := CompactToBig(header.Bits) @@ -637,8 +637,8 @@ func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int32) error { // which depend on its position within the block chain. // // The flags modify the behavior of this function as follows: -// - BFFastAdd: All checks except those involving comparing the header against -// the checkpoints are not performed. +// - BFFastAdd: All checks except those involving comparing the header against +// the checkpoints are not performed. // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode *blockNode, flags BehaviorFlags) error { @@ -716,8 +716,8 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode // on its position within the block chain. // // The flags modify the behavior of this function as follows: -// - BFFastAdd: The transaction are not checked to see if they are finalized -// and the somewhat expensive BIP0034 validation is not performed. +// - BFFastAdd: The transaction are not checked to see if they are finalized +// and the somewhat expensive BIP0034 validation is not performed. // // The flags are also passed to checkBlockHeaderContext. See its documentation // for how the flags modify its behavior. @@ -832,22 +832,22 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode func (b *BlockChain) checkBIP0030(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error { // Fetch utxos for all of the transaction ouputs in this block. // Typically, there will not be any utxos for any of the outputs. - fetchSet := make(map[wire.OutPoint]struct{}) + fetch := make([]wire.OutPoint, 0, len(block.Transactions())) for _, tx := range block.Transactions() { prevOut := wire.OutPoint{Hash: *tx.Hash()} for txOutIdx := range tx.MsgTx().TxOut { prevOut.Index = uint32(txOutIdx) - fetchSet[prevOut] = struct{}{} + fetch = append(fetch, prevOut) } } - err := view.fetchUtxos(b.db, fetchSet) + err := view.fetchUtxos(b.db, fetch) if err != nil { return err } // Duplicate transactions are only allowed if the previous transaction // is fully spent. - for outpoint := range fetchSet { + for _, outpoint := range fetch { utxo := view.LookupEntry(outpoint) if utxo != nil && !utxo.IsSpent() { str := fmt.Sprintf("tried to overwrite transaction %v "+ From 5ede256f663fb84f22213a83796b96d4a8a62b1d Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 5 May 2023 22:19:54 +0900 Subject: [PATCH 0768/1056] blockchain: Add benchmark for using a map vs a slice Benchmark added to compare the performance of a map vs a slice when fetching utxos. The benchmark shows roughly 25% performance improvement when using slices instead of a map. --- blockchain/bench_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/blockchain/bench_test.go b/blockchain/bench_test.go index eee4340bc8..9ecc834241 100644 --- a/blockchain/bench_test.go +++ b/blockchain/bench_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/wire" ) // BenchmarkIsCoinBase performs a simple benchmark against the IsCoinBase @@ -29,3 +30,33 @@ func BenchmarkIsCoinBaseTx(b *testing.B) { IsCoinBaseTx(tx) } } + +func BenchmarkUtxoFetchMap(b *testing.B) { + block := Block100000 + transactions := block.Transactions + b.ResetTimer() + + for i := 0; i < b.N; i++ { + needed := make(map[wire.OutPoint]struct{}, len(transactions)) + for _, tx := range transactions[1:] { + for _, txIn := range tx.TxIn { + needed[txIn.PreviousOutPoint] = struct{}{} + } + } + } +} + +func BenchmarkUtxoFetchSlices(b *testing.B) { + block := Block100000 + transactions := block.Transactions + b.ResetTimer() + + for i := 0; i < b.N; i++ { + needed := make([]wire.OutPoint, 0, len(transactions)) + for _, tx := range transactions[1:] { + for _, txIn := range tx.TxIn { + needed = append(needed, txIn.PreviousOutPoint) + } + } + } +} From 218c4754c6982c4b148decc7a947144d4810c857 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Sat, 6 May 2023 01:26:54 +0900 Subject: [PATCH 0769/1056] main: Update README.md's minimum go version The readme suggests a minimum version of 1.16 but the go.mod requires go 1.17. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ec1454fcc..fabf07698e 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ which are both under active development. ## Requirements -[Go](http://golang.org) 1.16 or newer. +[Go](http://golang.org) 1.17 or newer. ## Installation From c1a713e4ba42fb4ebb9a995a4c6def311c7e465b Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 22 May 2023 15:53:52 +0900 Subject: [PATCH 0770/1056] docs: Update minimum Go version --- docs/code_contribution_guidelines.md | 2 +- docs/installation.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/code_contribution_guidelines.md b/docs/code_contribution_guidelines.md index 05d630b3c5..da775878da 100644 --- a/docs/code_contribution_guidelines.md +++ b/docs/code_contribution_guidelines.md @@ -297,7 +297,7 @@ Rejoice as you will now be listed as a [contributor](https://github.com/btcsuite ## Contribution Checklist -- [  ] All changes are Go version 1.16 compliant +- [  ] All changes are Go version 1.17 compliant - [  ] The code being submitted is commented according to the [Code Documentation and Commenting](#CodeDocumentation) section - [  ] For new code: Code is accompanied by tests which exercise both diff --git a/docs/installation.md b/docs/installation.md index a74db56022..b340c2f620 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -5,7 +5,7 @@ details on how to install on the supported operating systems. ## Requirements -[Go](http://golang.org) 1.16 or newer. +[Go](http://golang.org) 1.17 or newer. ## GPG Verification Key From e4c88c3a3ecb1813529bf3dddc7a865bd418a6b8 Mon Sep 17 00:00:00 2001 From: Mikael Lindlof Date: Thu, 19 May 2022 18:14:26 +0100 Subject: [PATCH 0771/1056] rpc: Add ScriptPubKeyResult address field --- btcjson/chainsvrresults.go | 10 ++++++---- rpcserver.go | 24 ++++++++++++++++++++++++ rpcserverhelp.go | 10 ++++++---- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 4feaeda338..ff5d56908b 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -139,9 +139,10 @@ type CreateMultiSigResult struct { // DecodeScriptResult models the data returned from the decodescript command. type DecodeScriptResult struct { Asm string `json:"asm"` - ReqSigs int32 `json:"reqSigs,omitempty"` + ReqSigs int32 `json:"reqSigs,omitempty"` // Deprecated: removed in Bitcoin Core Type string `json:"type"` - Addresses []string `json:"addresses,omitempty"` + Address string `json:"address,omitempty"` + Addresses []string `json:"addresses,omitempty"` // Deprecated: removed in Bitcoin Core P2sh string `json:"p2sh,omitempty"` } @@ -429,9 +430,10 @@ type GetRawMempoolVerboseResult struct { type ScriptPubKeyResult struct { Asm string `json:"asm"` Hex string `json:"hex,omitempty"` - ReqSigs int32 `json:"reqSigs,omitempty"` + ReqSigs int32 `json:"reqSigs,omitempty"` // Deprecated: removed in Bitcoin Core Type string `json:"type"` - Addresses []string `json:"addresses,omitempty"` + Address string `json:"address,omitempty"` + Addresses []string `json:"addresses,omitempty"` // Deprecated: removed in Bitcoin Core } // GetTxOutResult models the data from the gettxout command. diff --git a/rpcserver.go b/rpcserver.go index b917263df5..ad25e4ee0a 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -738,6 +738,13 @@ func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap vout.ScriptPubKey.Type = scriptClass.String() vout.ScriptPubKey.ReqSigs = int32(reqSigs) + // Address is defined when there's a single well-defined + // receiver address. To spend the output a signature for this, + // and only this, address is required. + if len(encodedAddrs) == 1 && reqSigs <= 1 { + vout.ScriptPubKey.Address = encodedAddrs[0] + } + voutList = append(voutList, vout) } @@ -857,6 +864,13 @@ func handleDecodeScript(s *rpcServer, cmd interface{}, closeChan <-chan struct{} if scriptClass != txscript.ScriptHashTy { reply.P2sh = p2sh.EncodeAddress() } + + // Address is defined when there's a single well-defined + // receiver address. To spend the output a signature for this, + // and only this, address is required. + if len(addresses) == 1 && reqSigs <= 1 { + reply.Address = addresses[0] + } return reply, nil } @@ -2725,6 +2739,7 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i var value int64 var pkScript []byte var isCoinbase bool + var address string includeMempool := true if c.IncludeMempool != nil { includeMempool = *c.IncludeMempool @@ -2798,6 +2813,13 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i addresses[i] = addr.EncodeAddress() } + // Address is defined when there's a single well-defined + // receiver address. To spend the output a signature for this, + // and only this, address is required. + if len(addresses) == 1 && reqSigs <= 1 { + address = addresses[0] + } + txOutReply := &btcjson.GetTxOutResult{ BestBlock: bestBlockHash, Confirmations: int64(confirmations), @@ -2807,10 +2829,12 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i Hex: hex.EncodeToString(pkScript), ReqSigs: int32(reqSigs), Type: scriptClass.String(), + Address: address, Addresses: addresses, }, Coinbase: isCoinbase, } + return txOutReply, nil } diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 16bbb62a2b..a42804e9c0 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -84,9 +84,10 @@ var helpDescsEnUS = map[string]string{ // ScriptPubKeyResult help. "scriptpubkeyresult-asm": "Disassembly of the script", "scriptpubkeyresult-hex": "Hex-encoded bytes of the script", - "scriptpubkeyresult-reqSigs": "The number of required signatures", + "scriptpubkeyresult-reqSigs": "(DEPRECATED) The number of required signatures", "scriptpubkeyresult-type": "The type of the script (e.g. 'pubkeyhash')", - "scriptpubkeyresult-addresses": "The bitcoin addresses associated with this script", + "scriptpubkeyresult-address": "The bitcoin address associated with this script (only if a well-defined address exists)", + "scriptpubkeyresult-addresses": "(DEPRECATED) The bitcoin addresses associated with this script", // Vout help. "vout-value": "The amount in BTC", @@ -106,9 +107,10 @@ var helpDescsEnUS = map[string]string{ // DecodeScriptResult help. "decodescriptresult-asm": "Disassembly of the script", - "decodescriptresult-reqSigs": "The number of required signatures", + "decodescriptresult-reqSigs": "(DEPRECATED) The number of required signatures", "decodescriptresult-type": "The type of the script (e.g. 'pubkeyhash')", - "decodescriptresult-addresses": "The bitcoin addresses associated with this script", + "decodescriptresult-address": "The bitcoin address associated with this script (only if a well-defined address exists)", + "decodescriptresult-addresses": "(DEPRECATED) The bitcoin addresses associated with this script", "decodescriptresult-p2sh": "The script hash for use in pay-to-script-hash transactions (only present if the provided redeem script is not already a pay-to-script-hash script)", // DecodeScriptCmd help. From ba5407615dd38b368742650d0dcf4a0de9ade71d Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 13:05:07 +0900 Subject: [PATCH 0772/1056] multi: Run gofmt on the entire repository The doc formatting changes introduced in the recent go version is increasing the diff for all of the new commits. Formatting it all in this commit will help the readability of future PRs by reducing the diff. --- addrmgr/doc.go | 2 +- blockchain/accept.go | 2 +- blockchain/chain.go | 51 ++-- blockchain/chain_test.go | 2 +- blockchain/chainio.go | 2 +- blockchain/chainview.go | 24 +- blockchain/checkpoints.go | 18 +- blockchain/difficulty.go | 9 +- blockchain/doc.go | 66 ++--- blockchain/example_test.go | 2 +- blockchain/fullblocks_test.go | 2 +- blockchain/fullblocktests/generate.go | 8 +- blockchain/indexers/blocklogger.go | 7 +- blockchain/indexers/cfindex.go | 6 +- blockchain/indexers/common.go | 2 +- blockchain/indexers/manager.go | 2 +- blockchain/indexers/txindex.go | 2 +- blockchain/merkle.go | 4 +- blockchain/notifications.go | 6 +- blockchain/process.go | 2 +- blockchain/upgrade.go | 123 ++++---- blockchain/validate_test.go | 2 +- btcec/btcec_test.go | 4 +- btcec/modnscalar.go | 2 +- btcjson/doc.go | 36 +-- btcjson/help.go | 26 +- btcjson/walletsvrcmds.go | 3 +- btcjson/walletsvrresults.go | 10 +- btcutil/appdata.go | 11 +- btcutil/base58/doc.go | 4 +- btcutil/base58/genalphabet.go | 3 +- btcutil/block_test.go | 2 +- btcutil/bloom/example_test.go | 2 +- btcutil/bloom/filter.go | 2 +- btcutil/bloom/filter_test.go | 4 +- btcutil/bloom/merkleblock.go | 2 +- btcutil/bloom/merkleblock_test.go | 4 +- btcutil/coinset/coins.go | 5 +- btcutil/coinset/coins_test.go | 4 +- btcutil/doc.go | 6 +- btcutil/gcs/builder/builder.go | 2 +- btcutil/gcs/doc.go | 4 +- btcutil/gcs/gcs.go | 2 +- btcutil/hdkeychain/doc.go | 19 +- btcutil/hdkeychain/example_test.go | 2 +- btcutil/hdkeychain/extendedkey.go | 5 +- btcutil/hdkeychain/extendedkey_test.go | 3 +- btcutil/net.go | 1 + btcutil/net_noop.go | 1 + btcutil/tx_test.go | 2 +- btcutil/txsort/doc.go | 2 +- btcutil/txsort/txsort_test.go | 2 +- btcutil/wif.go | 16 +- chaincfg/doc.go | 52 ++-- chaincfg/params.go | 5 +- cmd/addblock/config.go | 2 +- cmd/addblock/import.go | 2 +- cmd/btcctl/config.go | 10 +- cmd/findcheckpoint/config.go | 2 +- config.go | 10 +- connmgr/doc.go | 2 +- database/cmd/dbtool/globalconfig.go | 2 +- database/cmd/dbtool/insecureimport.go | 2 +- database/doc.go | 28 +- database/ffldb/bench_test.go | 2 +- database/ffldb/blockio.go | 4 +- database/ffldb/db.go | 2 +- database/ffldb/doc.go | 2 +- database/ffldb/driver_test.go | 2 +- database/ffldb/interface_test.go | 2 +- database/ffldb/whitebox_test.go | 2 +- database/interface.go | 2 +- database/internal/treap/treapiter.go | 15 +- doc.go | 268 +++++++++--------- integration/bip0009_test.go | 20 +- integration/csv_fork_test.go | 38 +-- integration/rpctest/blockgen.go | 2 +- integration/rpctest/node.go | 2 +- integration/rpctest/rpc_harness_test.go | 2 +- limits/limits_unix.go | 1 + mempool/doc.go | 58 ++-- mempool/estimatefee.go | 2 +- mempool/estimatefee_test.go | 2 +- mining/cpuminer/cpuminer.go | 2 +- mining/mining.go | 42 +-- mining/policy.go | 2 +- mining/policy_test.go | 2 +- netsync/blocklogger.go | 7 +- netsync/interface.go | 2 +- netsync/manager.go | 2 +- peer/doc.go | 86 +++--- peer/peer.go | 30 +- rpcadapters.go | 2 +- rpcclient/doc.go | 62 ++-- rpcclient/examples/btcdwebsockets/main.go | 2 +- .../examples/btcwalletwebsockets/main.go | 2 +- rpcclient/extensions.go | 5 +- rpcclient/mining.go | 2 +- rpcclient/notify.go | 2 +- rpcclient/rawtransactions.go | 2 +- rpcclient/wallet.go | 8 +- rpcwebsocket.go | 2 +- signalsigterm.go | 1 + txscript/doc.go | 4 +- txscript/error.go | 8 +- txscript/opcode.go | 2 +- txscript/scriptnum.go | 25 +- wire/doc.go | 20 +- 108 files changed, 719 insertions(+), 685 deletions(-) diff --git a/addrmgr/doc.go b/addrmgr/doc.go index 8ddc8bfdfb..c500fbb5be 100644 --- a/addrmgr/doc.go +++ b/addrmgr/doc.go @@ -5,7 +5,7 @@ /* Package addrmgr implements concurrency safe Bitcoin address manager. -Address Manager Overview +# Address Manager Overview In order maintain the peer-to-peer Bitcoin network, there needs to be a source of addresses to connect to as nodes come and go. The Bitcoin protocol provides diff --git a/blockchain/accept.go b/blockchain/accept.go index 44ccbf997a..935963148f 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -7,8 +7,8 @@ package blockchain import ( "fmt" - "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/database" ) // maybeAcceptBlock potentially accepts a block into the block chain and, if diff --git a/blockchain/chain.go b/blockchain/chain.go index 4d1a839441..f29455b17a 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -34,8 +34,9 @@ const ( // from the block being located. // // For example, assume a block chain with a side chain as depicted below: -// genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 -// \-> 16a -> 17a +// +// genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 +// \-> 16a -> 17a // // The block locator for block 17a would be the hashes of blocks: // [17a 16a 15 14 13 12 11 10 9 8 7 6 4 genesis] @@ -386,7 +387,7 @@ func (b *BlockChain) calcSequenceLock(node *blockNode, tx *btcutil.Tx, utxoView // return sequence lock values of -1 indicating that this transaction // can be included within a block at any given height or time. mTx := tx.MsgTx() - sequenceLockActive := mTx.Version >= 2 && csvSoftforkActive + sequenceLockActive := uint32(mTx.Version) >= 2 && csvSoftforkActive if !sequenceLockActive || IsCoinBase(tx) { return sequenceLock, nil } @@ -468,7 +469,7 @@ func (b *BlockChain) calcSequenceLock(node *blockNode, tx *btcutil.Tx, utxoView // LockTimeToSequence converts the passed relative locktime to a sequence // number in accordance to BIP-68. // See: https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki -// * (Compatibility) +// - (Compatibility) func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 { // If we're expressing the relative lock time in blocks, then the // corresponding sequence number is simply the desired input age. @@ -1067,8 +1068,8 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // a reorganization to become the main chain). // // The flags modify the behavior of this function as follows: -// - BFFastAdd: Avoids several expensive transaction validation operations. -// This is useful when using checkpoints. +// - BFFastAdd: Avoids several expensive transaction validation operations. +// This is useful when using checkpoints. // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, flags BehaviorFlags) (bool, error) { @@ -1207,8 +1208,8 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // isCurrent returns whether or not the chain believes it is current. Several // factors are used to guess, but the key factors that allow the chain to // believe it is current are: -// - Latest block height is after the latest checkpoint (if enabled) -// - Latest block has a timestamp newer than 24 hours ago +// - Latest block height is after the latest checkpoint (if enabled) +// - Latest block has a timestamp newer than 24 hours ago // // This function MUST be called with the chain state lock held (for reads). func (b *BlockChain) isCurrent() bool { @@ -1231,8 +1232,8 @@ func (b *BlockChain) isCurrent() bool { // IsCurrent returns whether or not the chain believes it is current. Several // factors are used to guess, but the key factors that allow the chain to // believe it is current are: -// - Latest block height is after the latest checkpoint (if enabled) -// - Latest block has a timestamp newer than 24 hours ago +// - Latest block height is after the latest checkpoint (if enabled) +// - Latest block has a timestamp newer than 24 hours ago // // This function is safe for concurrent access. func (b *BlockChain) IsCurrent() bool { @@ -1467,11 +1468,11 @@ func (b *BlockChain) IntervalBlockHashes(endHash *chainhash.Hash, interval int, // // In addition, there are two special cases: // -// - When no locators are provided, the stop hash is treated as a request for -// that block, so it will either return the node associated with the stop hash -// if it is known, or nil if it is unknown -// - When locators are provided, but none of them are known, nodes starting -// after the genesis block will be returned +// - When no locators are provided, the stop hash is treated as a request for +// that block, so it will either return the node associated with the stop hash +// if it is known, or nil if it is unknown +// - When locators are provided, but none of them are known, nodes starting +// after the genesis block will be returned // // This is primarily a helper function for the locateBlocks and locateHeaders // functions. @@ -1555,11 +1556,11 @@ func (b *BlockChain) locateBlocks(locator BlockLocator, hashStop *chainhash.Hash // // In addition, there are two special cases: // -// - When no locators are provided, the stop hash is treated as a request for -// that block, so it will either return the stop hash itself if it is known, -// or nil if it is unknown -// - When locators are provided, but none of them are known, hashes starting -// after the genesis block will be returned +// - When no locators are provided, the stop hash is treated as a request for +// that block, so it will either return the stop hash itself if it is known, +// or nil if it is unknown +// - When locators are provided, but none of them are known, hashes starting +// after the genesis block will be returned // // This function is safe for concurrent access. func (b *BlockChain) LocateBlocks(locator BlockLocator, hashStop *chainhash.Hash, maxHashes uint32) []chainhash.Hash { @@ -1600,11 +1601,11 @@ func (b *BlockChain) locateHeaders(locator BlockLocator, hashStop *chainhash.Has // // In addition, there are two special cases: // -// - When no locators are provided, the stop hash is treated as a request for -// that header, so it will either return the header for the stop hash itself -// if it is known, or nil if it is unknown -// - When locators are provided, but none of them are known, headers starting -// after the genesis block will be returned +// - When no locators are provided, the stop hash is treated as a request for +// that header, so it will either return the header for the stop hash itself +// if it is known, or nil if it is unknown +// - When locators are provided, but none of them are known, headers starting +// after the genesis block will be returned // // This function is safe for concurrent access. func (b *BlockChain) LocateHeaders(locator BlockLocator, hashStop *chainhash.Hash) []wire.BlockHeader { diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index 34356326b9..6569b7ec86 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -9,10 +9,10 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // TestHaveBlock tests the HaveBlock API to ensure proper functionality. diff --git a/blockchain/chainio.go b/blockchain/chainio.go index fa41254da6..e7a7c30c76 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -12,10 +12,10 @@ import ( "sync" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/chainview.go b/blockchain/chainview.go index a4c3692cd6..dd70ab2d01 100644 --- a/blockchain/chainview.go +++ b/blockchain/chainview.go @@ -36,11 +36,13 @@ func fastLog2Floor(n uint32) uint8 { // for comparing chains. // // For example, assume a block chain with a side chain as depicted below: -// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -// \-> 4a -> 5a -> 6a +// +// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 +// \-> 4a -> 5a -> 6a // // The chain view for the branch ending in 6a consists of: -// genesis -> 1 -> 2 -> 3 -> 4a -> 5a -> 6a +// +// genesis -> 1 -> 2 -> 3 -> 4a -> 5a -> 6a type chainView struct { mtx sync.Mutex nodes []*blockNode @@ -258,12 +260,14 @@ func (c *chainView) next(node *blockNode) *blockNode { // view. // // For example, assume a block chain with a side chain as depicted below: -// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -// \-> 4a -> 5a -> 6a +// +// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 +// \-> 4a -> 5a -> 6a // // Further, assume the view is for the longer chain depicted above. That is to // say it consists of: -// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 +// +// genesis -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 // // Invoking this function with block node 5 would return block node 6 while // invoking it with block node 5a would return nil since that node is not part @@ -321,12 +325,14 @@ func (c *chainView) findFork(node *blockNode) *blockNode { // the chain view. It will return nil if there is no common block. // // For example, assume a block chain with a side chain as depicted below: -// genesis -> 1 -> 2 -> ... -> 5 -> 6 -> 7 -> 8 -// \-> 6a -> 7a +// +// genesis -> 1 -> 2 -> ... -> 5 -> 6 -> 7 -> 8 +// \-> 6a -> 7a // // Further, assume the view is for the longer chain depicted above. That is to // say it consists of: -// genesis -> 1 -> 2 -> ... -> 5 -> 6 -> 7 -> 8. +// +// genesis -> 1 -> 2 -> ... -> 5 -> 6 -> 7 -> 8. // // Invoking this function with block node 7a would return block node 5 while // invoking it with block node 7 would return itself since it is already part of diff --git a/blockchain/checkpoints.go b/blockchain/checkpoints.go index dbfa9d146d..74fc23bacb 100644 --- a/blockchain/checkpoints.go +++ b/blockchain/checkpoints.go @@ -8,10 +8,10 @@ import ( "fmt" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/btcutil" ) // CheckpointConfirmations is the number of blocks before the end of the current @@ -184,14 +184,14 @@ func isNonstandardTransaction(tx *btcutil.Tx) bool { // checkpoint candidate. // // The factors used to determine a good checkpoint are: -// - The block must be in the main chain -// - The block must be at least 'CheckpointConfirmations' blocks prior to the -// current end of the main chain -// - The timestamps for the blocks before and after the checkpoint must have -// timestamps which are also before and after the checkpoint, respectively -// (due to the median time allowance this is not always the case) -// - The block must not contain any strange transaction such as those with -// nonstandard scripts +// - The block must be in the main chain +// - The block must be at least 'CheckpointConfirmations' blocks prior to the +// current end of the main chain +// - The timestamps for the blocks before and after the checkpoint must have +// timestamps which are also before and after the checkpoint, respectively +// (due to the median time allowance this is not always the case) +// - The block must not contain any strange transaction such as those with +// nonstandard scripts // // The intent is that candidates are reviewed by a developer to make the final // decision and then manually added to the list of checkpoints for a network. diff --git a/blockchain/difficulty.go b/blockchain/difficulty.go index 05f78a3ed1..0eb66f3241 100644 --- a/blockchain/difficulty.go +++ b/blockchain/difficulty.go @@ -42,9 +42,9 @@ func HashToBig(hash *chainhash.Hash) *big.Int { // Like IEEE754 floating point, there are three basic components: the sign, // the exponent, and the mantissa. They are broken out as follows: // -// * the most significant 8 bits represent the unsigned base 256 exponent -// * bit 23 (the 24th bit) represents the sign bit -// * the least significant 23 bits represent the mantissa +// - the most significant 8 bits represent the unsigned base 256 exponent +// - bit 23 (the 24th bit) represents the sign bit +// - the least significant 23 bits represent the mantissa // // ------------------------------------------------- // | Exponent | Sign | Mantissa | @@ -53,7 +53,8 @@ func HashToBig(hash *chainhash.Hash) *big.Int { // ------------------------------------------------- // // The formula to calculate N is: -// N = (-1^sign) * mantissa * 256^(exponent-3) +// +// N = (-1^sign) * mantissa * 256^(exponent-3) // // This compact form is only used in bitcoin to encode unsigned 256-bit numbers // which represent difficulty targets, thus there really is not a need for a diff --git a/blockchain/doc.go b/blockchain/doc.go index 244175414a..d57acc29c9 100644 --- a/blockchain/doc.go +++ b/blockchain/doc.go @@ -26,42 +26,42 @@ caller a high level of flexibility in how they want to react to certain events such as orphan blocks which need their parents requested and newly connected main chain blocks which might result in wallet updates. -Bitcoin Chain Processing Overview +# Bitcoin Chain Processing Overview Before a block is allowed into the block chain, it must go through an intensive series of validation rules. The following list serves as a general outline of those rules to provide some intuition into what is going on under the hood, but is by no means exhaustive: - - Reject duplicate blocks - - Perform a series of sanity checks on the block and its transactions such as - verifying proof of work, timestamps, number and character of transactions, - transaction amounts, script complexity, and merkle root calculations - - Compare the block against predetermined checkpoints for expected timestamps - and difficulty based on elapsed time since the checkpoint - - Save the most recent orphan blocks for a limited time in case their parent - blocks become available - - Stop processing if the block is an orphan as the rest of the processing - depends on the block's position within the block chain - - Perform a series of more thorough checks that depend on the block's position - within the block chain such as verifying block difficulties adhere to - difficulty retarget rules, timestamps are after the median of the last - several blocks, all transactions are finalized, checkpoint blocks match, and - block versions are in line with the previous blocks - - Determine how the block fits into the chain and perform different actions - accordingly in order to ensure any side chains which have higher difficulty - than the main chain become the new main chain - - When a block is being connected to the main chain (either through - reorganization of a side chain to the main chain or just extending the - main chain), perform further checks on the block's transactions such as - verifying transaction duplicates, script complexity for the combination of - connected scripts, coinbase maturity, double spends, and connected - transaction values - - Run the transaction scripts to verify the spender is allowed to spend the - coins - - Insert the block into the block database + - Reject duplicate blocks + - Perform a series of sanity checks on the block and its transactions such as + verifying proof of work, timestamps, number and character of transactions, + transaction amounts, script complexity, and merkle root calculations + - Compare the block against predetermined checkpoints for expected timestamps + and difficulty based on elapsed time since the checkpoint + - Save the most recent orphan blocks for a limited time in case their parent + blocks become available + - Stop processing if the block is an orphan as the rest of the processing + depends on the block's position within the block chain + - Perform a series of more thorough checks that depend on the block's position + within the block chain such as verifying block difficulties adhere to + difficulty retarget rules, timestamps are after the median of the last + several blocks, all transactions are finalized, checkpoint blocks match, and + block versions are in line with the previous blocks + - Determine how the block fits into the chain and perform different actions + accordingly in order to ensure any side chains which have higher difficulty + than the main chain become the new main chain + - When a block is being connected to the main chain (either through + reorganization of a side chain to the main chain or just extending the + main chain), perform further checks on the block's transactions such as + verifying transaction duplicates, script complexity for the combination of + connected scripts, coinbase maturity, double spends, and connected + transaction values + - Run the transaction scripts to verify the spender is allowed to spend the + coins + - Insert the block into the block database -Errors +# Errors Errors returned by this package are either the raw errors provided by underlying calls or of type blockchain.RuleError. This allows the caller to differentiate @@ -70,12 +70,12 @@ violations through type assertions. In addition, callers can programmatically determine the specific rule violation by examining the ErrorCode field of the type asserted blockchain.RuleError. -Bitcoin Improvement Proposals +# Bitcoin Improvement Proposals This package includes spec changes outlined by the following BIPs: - BIP0016 (https://en.bitcoin.it/wiki/BIP_0016) - BIP0030 (https://en.bitcoin.it/wiki/BIP_0030) - BIP0034 (https://en.bitcoin.it/wiki/BIP_0034) + BIP0016 (https://en.bitcoin.it/wiki/BIP_0016) + BIP0030 (https://en.bitcoin.it/wiki/BIP_0030) + BIP0034 (https://en.bitcoin.it/wiki/BIP_0034) */ package blockchain diff --git a/blockchain/example_test.go b/blockchain/example_test.go index 7f15e59bc6..8db570273d 100644 --- a/blockchain/example_test.go +++ b/blockchain/example_test.go @@ -11,10 +11,10 @@ import ( "path/filepath" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" - "github.com/btcsuite/btcd/btcutil" ) // This example demonstrates how to create a new chain instance and use diff --git a/blockchain/fullblocks_test.go b/blockchain/fullblocks_test.go index 3cc7c87b70..d6bcf799af 100644 --- a/blockchain/fullblocks_test.go +++ b/blockchain/fullblocks_test.go @@ -14,13 +14,13 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain/fullblocktests" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 964986dbcf..c491242ecd 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -20,11 +20,11 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -466,9 +466,9 @@ func createSpendTxForTx(tx *wire.MsgTx, fee btcutil.Amount) *wire.MsgTx { // - A coinbase that pays the required subsidy to an OP_TRUE script // - When a spendable output is provided: // - A transaction that spends from the provided output the following outputs: -// - One that pays the inputs amount minus 1 atom to an OP_TRUE script -// - One that contains an OP_RETURN output with a random uint64 in order to -// ensure the transaction has a unique hash +// - One that pays the inputs amount minus 1 atom to an OP_TRUE script +// - One that contains an OP_RETURN output with a random uint64 in order to +// ensure the transaction has a unique hash // // Additionally, if one or more munge functions are specified, they will be // invoked with the block prior to solving it. This provides callers with the diff --git a/blockchain/indexers/blocklogger.go b/blockchain/indexers/blocklogger.go index 3671c0162a..960a51d2c1 100644 --- a/blockchain/indexers/blocklogger.go +++ b/blockchain/indexers/blocklogger.go @@ -8,8 +8,8 @@ import ( "sync" "time" - "github.com/btcsuite/btclog" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btclog" ) // blockProgressLogger provides periodic logging for other services in order @@ -27,8 +27,9 @@ type blockProgressLogger struct { // newBlockProgressLogger returns a new block progress logger. // The progress message is templated as follows: -// {progressAction} {numProcessed} {blocks|block} in the last {timePeriod} -// ({numTxs}, height {lastBlockHeight}, {lastBlockTimeStamp}) +// +// {progressAction} {numProcessed} {blocks|block} in the last {timePeriod} +// ({numTxs}, height {lastBlockHeight}, {lastBlockTimeStamp}) func newBlockProgressLogger(progressMessage string, logger btclog.Logger) *blockProgressLogger { return &blockProgressLogger{ lastBlockLogTime: time.Now(), diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index fa0ee3c0a6..21b4bf4632 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -8,13 +8,13 @@ import ( "errors" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/gcs" + "github.com/btcsuite/btcd/btcutil/gcs/builder" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/btcutil/gcs" - "github.com/btcsuite/btcd/btcutil/gcs/builder" ) const ( diff --git a/blockchain/indexers/common.go b/blockchain/indexers/common.go index 07b2feca5d..89ce6720b5 100644 --- a/blockchain/indexers/common.go +++ b/blockchain/indexers/common.go @@ -12,8 +12,8 @@ import ( "errors" "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/database" ) var ( diff --git a/blockchain/indexers/manager.go b/blockchain/indexers/manager.go index 8c87ca0771..b4487e60fd 100644 --- a/blockchain/indexers/manager.go +++ b/blockchain/indexers/manager.go @@ -9,10 +9,10 @@ import ( "fmt" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/blockchain/indexers/txindex.go b/blockchain/indexers/txindex.go index f1d734e06b..f7d4bf60a3 100644 --- a/blockchain/indexers/txindex.go +++ b/blockchain/indexers/txindex.go @@ -9,10 +9,10 @@ import ( "fmt" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/blockchain/merkle.go b/blockchain/merkle.go index d7e567b283..48d57b8a2e 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -9,9 +9,9 @@ import ( "fmt" "math" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -86,7 +86,7 @@ func HashMerkleBranches(left *chainhash.Hash, right *chainhash.Hash) *chainhash. // // The above stored as a linear array is as follows: // -// [h1 h2 h3 h4 h12 h34 root] +// [h1 h2 h3 h4 h12 h34 root] // // As the above shows, the merkle root is always the last element in the array. // diff --git a/blockchain/notifications.go b/blockchain/notifications.go index 25cc4f1f03..5139e89edf 100644 --- a/blockchain/notifications.go +++ b/blockchain/notifications.go @@ -50,9 +50,9 @@ func (n NotificationType) String() string { // Notification defines notification that is sent to the caller via the callback // function provided during the call to New and consists of a notification type // as well as associated data that depends on the type as follows: -// - NTBlockAccepted: *btcutil.Block -// - NTBlockConnected: *btcutil.Block -// - NTBlockDisconnected: *btcutil.Block +// - NTBlockAccepted: *btcutil.Block +// - NTBlockConnected: *btcutil.Block +// - NTBlockDisconnected: *btcutil.Block type Notification struct { Type NotificationType Data interface{} diff --git a/blockchain/process.go b/blockchain/process.go index c367b4ceff..64d5c1e14f 100644 --- a/blockchain/process.go +++ b/blockchain/process.go @@ -8,9 +8,9 @@ import ( "fmt" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" - "github.com/btcsuite/btcd/btcutil" ) // BehaviorFlags is a bitmask defining tweaks to the normal behavior when diff --git a/blockchain/upgrade.go b/blockchain/upgrade.go index 253ca62e1e..34149e44a8 100644 --- a/blockchain/upgrade.go +++ b/blockchain/upgrade.go @@ -232,24 +232,25 @@ func determineMainChainBlocks(blocksMap map[chainhash.Hash]*blockChainContext, t // // The legacy format is as follows: // -//
[,...] +//
[,...] // -// Field Type Size -// version VLQ variable -// block height VLQ variable -// header code VLQ variable -// unspentness bitmap []byte variable -// compressed txouts -// compressed amount VLQ variable -// compressed script []byte variable +// Field Type Size +// version VLQ variable +// block height VLQ variable +// header code VLQ variable +// unspentness bitmap []byte variable +// compressed txouts +// compressed amount VLQ variable +// compressed script []byte variable // // The serialized header code format is: -// bit 0 - containing transaction is a coinbase -// bit 1 - output zero is unspent -// bit 2 - output one is unspent -// bits 3-x - number of bytes in unspentness bitmap. When both bits 1 and 2 -// are unset, it encodes N-1 since there must be at least one unspent -// output. +// +// bit 0 - containing transaction is a coinbase +// bit 1 - output zero is unspent +// bit 2 - output one is unspent +// bits 3-x - number of bytes in unspentness bitmap. When both bits 1 and 2 +// are unset, it encodes N-1 since there must be at least one unspent +// output. // // The rationale for the header code scheme is as follows: // - Transactions which only pay to a single output and a change output are @@ -269,65 +270,65 @@ func determineMainChainBlocks(blocksMap map[chainhash.Hash]*blockChainContext, t // From tx in main blockchain: // Blk 1, 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 // -// 010103320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52 -// <><><><------------------------------------------------------------------> -// | | \--------\ | -// | height | compressed txout 0 -// version header code +// 010103320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52 +// <><><><------------------------------------------------------------------> +// | | \--------\ | +// | height | compressed txout 0 +// version header code // -// - version: 1 -// - height: 1 -// - header code: 0x03 (coinbase, output zero unspent, 0 bytes of unspentness) -// - unspentness: Nothing since it is zero bytes -// - compressed txout 0: -// - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) -// - 0x04: special script type pay-to-pubkey -// - 0x96...52: x-coordinate of the pubkey +// - version: 1 +// - height: 1 +// - header code: 0x03 (coinbase, output zero unspent, 0 bytes of unspentness) +// - unspentness: Nothing since it is zero bytes +// - compressed txout 0: +// - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) +// - 0x04: special script type pay-to-pubkey +// - 0x96...52: x-coordinate of the pubkey // // Example 2: // From tx in main blockchain: // Blk 113931, 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f // -// 0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58 -// <><----><><><------------------------------------------><--------------------------------------------> -// | | | \-------------------\ | | -// version | \--------\ unspentness | compressed txout 2 -// height header code compressed txout 0 +// 0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58 +// <><----><><><------------------------------------------><--------------------------------------------> +// | | | \-------------------\ | | +// version | \--------\ unspentness | compressed txout 2 +// height header code compressed txout 0 // -// - version: 1 -// - height: 113931 -// - header code: 0x0a (output zero unspent, 1 byte in unspentness bitmap) -// - unspentness: [0x01] (bit 0 is set, so output 0+2 = 2 is unspent) -// NOTE: It's +2 since the first two outputs are encoded in the header code -// - compressed txout 0: -// - 0x12: VLQ-encoded compressed amount for 20000000 (0.2 BTC) -// - 0x00: special script type pay-to-pubkey-hash -// - 0xe2...8a: pubkey hash -// - compressed txout 2: -// - 0x8009: VLQ-encoded compressed amount for 15000000 (0.15 BTC) -// - 0x00: special script type pay-to-pubkey-hash -// - 0xb8...58: pubkey hash +// - version: 1 +// - height: 113931 +// - header code: 0x0a (output zero unspent, 1 byte in unspentness bitmap) +// - unspentness: [0x01] (bit 0 is set, so output 0+2 = 2 is unspent) +// NOTE: It's +2 since the first two outputs are encoded in the header code +// - compressed txout 0: +// - 0x12: VLQ-encoded compressed amount for 20000000 (0.2 BTC) +// - 0x00: special script type pay-to-pubkey-hash +// - 0xe2...8a: pubkey hash +// - compressed txout 2: +// - 0x8009: VLQ-encoded compressed amount for 15000000 (0.15 BTC) +// - 0x00: special script type pay-to-pubkey-hash +// - 0xb8...58: pubkey hash // // Example 3: // From tx in main blockchain: // Blk 338156, 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620 // -// 0193d06c100000108ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6 -// <><----><><----><--------------------------------------------------> -// | | | \-----------------\ | -// version | \--------\ unspentness | -// height header code compressed txout 22 +// 0193d06c100000108ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6 +// <><----><><----><--------------------------------------------------> +// | | | \-----------------\ | +// version | \--------\ unspentness | +// height header code compressed txout 22 // -// - version: 1 -// - height: 338156 -// - header code: 0x10 (2+1 = 3 bytes in unspentness bitmap) -// NOTE: It's +1 since neither bit 1 nor 2 are set, so N-1 is encoded. -// - unspentness: [0x00 0x00 0x10] (bit 20 is set, so output 20+2 = 22 is unspent) -// NOTE: It's +2 since the first two outputs are encoded in the header code -// - compressed txout 22: -// - 0x8ba5b9e763: VLQ-encoded compressed amount for 366875659 (3.66875659 BTC) -// - 0x01: special script type pay-to-script-hash -// - 0x1d...e6: script hash +// - version: 1 +// - height: 338156 +// - header code: 0x10 (2+1 = 3 bytes in unspentness bitmap) +// NOTE: It's +1 since neither bit 1 nor 2 are set, so N-1 is encoded. +// - unspentness: [0x00 0x00 0x10] (bit 20 is set, so output 20+2 = 22 is unspent) +// NOTE: It's +2 since the first two outputs are encoded in the header code +// - compressed txout 22: +// - 0x8ba5b9e763: VLQ-encoded compressed amount for 366875659 (3.66875659 BTC) +// - 0x01: special script type pay-to-script-hash +// - 0x1d...e6: script hash func deserializeUtxoEntryV0(serialized []byte) (map[uint32]*UtxoEntry, error) { // Deserialize the version. // diff --git a/blockchain/validate_test.go b/blockchain/validate_test.go index d5d17781d3..1963a41590 100644 --- a/blockchain/validate_test.go +++ b/blockchain/validate_test.go @@ -10,10 +10,10 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // TestSequenceLocksActive tests the SequenceLockActive function to ensure it diff --git a/btcec/btcec_test.go b/btcec/btcec_test.go index 3113a1b553..f5d9395274 100644 --- a/btcec/btcec_test.go +++ b/btcec/btcec_test.go @@ -527,7 +527,7 @@ type baseMultTest struct { x, y string } -//TODO: add more test vectors +// TODO: add more test vectors var s256BaseMultTests = []baseMultTest{ { "AA5E28D6A97A2479A65527F7290311A3624D4CC0FA1578598EE3C2613BF99522", @@ -556,7 +556,7 @@ var s256BaseMultTests = []baseMultTest{ }, } -//TODO: test different curves as well? +// TODO: test different curves as well? func TestBaseMult(t *testing.T) { s256 := S256() for i, e := range s256BaseMultTests { diff --git a/btcec/modnscalar.go b/btcec/modnscalar.go index b18b2c1d43..939b0c17a7 100644 --- a/btcec/modnscalar.go +++ b/btcec/modnscalar.go @@ -11,7 +11,7 @@ import ( // arithmetic over the secp256k1 group order. This means all arithmetic is // performed modulo: // -// 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 +// 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 // // It only implements the arithmetic needed for elliptic curve operations, // however, the operations that are not implemented can typically be worked diff --git a/btcjson/doc.go b/btcjson/doc.go index 165b9ef91c..d31b6c0a6b 100644 --- a/btcjson/doc.go +++ b/btcjson/doc.go @@ -5,7 +5,7 @@ /* Package btcjson provides primitives for working with the bitcoin JSON-RPC API. -Overview +# Overview When communicating via the JSON-RPC protocol, all of the commands need to be marshalled to and from the the wire in the appropriate format. This package @@ -14,7 +14,7 @@ provides data structures and primitives to ease this process. In addition, it also provides some additional features such as custom command registration, command categorization, and reflection-based help generation. -JSON-RPC Protocol Overview +# JSON-RPC Protocol Overview This information is not necessary in order to use this package, but it does provide some intuition into what the marshalling and unmarshalling that is @@ -47,39 +47,39 @@ with it) doesn't always follow the spec and will sometimes return an error string in the result field with a null error for certain commands. However, for the most part, the error field will be set as described on failure. -Marshalling and Unmarshalling +# Marshalling and Unmarshalling Based upon the discussion above, it should be easy to see how the types of this package map into the required parts of the protocol - Request Objects (type Request) - - Commands (type Cmd) - - Notifications (type Ntfn) + 1. Commands (type Cmd) + 2. Notifications (type Ntfn) - Response Objects (type Response) - - Result (type Result) + 1. Result (type Result) To simplify the marshalling of the requests and responses, the MarshalCmd and MarshalResponse functions are provided. They return the raw bytes ready to be sent across the wire. Unmarshalling a received Request object is a two step process: - 1) Unmarshal the raw bytes into a Request struct instance via json.Unmarshal - 2) Use UnmarshalCmd on the Result field of the unmarshalled Request to create - a concrete command or notification instance with all struct fields set - accordingly + 1. Unmarshal the raw bytes into a Request struct instance via json.Unmarshal + 2. Use UnmarshalCmd on the Result field of the unmarshalled Request to create + a concrete command or notification instance with all struct fields set + accordingly This approach is used since it provides the caller with access to the additional fields in the request that are not part of the command such as the ID. Unmarshalling a received Response object is also a two step process: - 1) Unmarhsal the raw bytes into a Response struct instance via json.Unmarshal - 2) Depending on the ID, unmarshal the Result field of the unmarshalled - Response to create a concrete type instance + 1. Unmarhsal the raw bytes into a Response struct instance via json.Unmarshal + 2. Depending on the ID, unmarshal the Result field of the unmarshalled + Response to create a concrete type instance As above, this approach is used since it provides the caller with access to the fields in the response such as the ID and Error. -Command Creation +# Command Creation This package provides two approaches for creating a new command. This first, and preferred, method is to use one of the NewCmd functions. This allows @@ -93,7 +93,7 @@ obviously, run-time which means any mistakes won't be found until the code is actually executed. However, it is quite useful for user-supplied commands that are intentionally dynamic. -Custom Command Registration +# Custom Command Registration The command handling of this package is built around the concept of registered commands. This is true for the wide variety of commands already provided by the @@ -104,7 +104,7 @@ function for this purpose. A list of all registered methods can be obtained with the RegisteredCmdMethods function. -Command Inspection +# Command Inspection All registered commands are registered with flags that identify information such as whether the command applies to a chain server, wallet server, or is a @@ -112,7 +112,7 @@ notification along with the method name to use. These flags can be obtained with the MethodUsageFlags flags, and the method can be obtained with the CmdMethod function. -Help Generation +# Help Generation To facilitate providing consistent help to users of the RPC server, this package exposes the GenerateHelp and function which uses reflection on registered @@ -122,7 +122,7 @@ generate the final help text. In addition, the MethodUsageText function is provided to generate consistent one-line usage for registered commands and notifications using reflection. -Errors +# Errors There are 2 distinct type of errors supported by this package: diff --git a/btcjson/help.go b/btcjson/help.go index f502d09fd8..2cc55b8410 100644 --- a/btcjson/help.go +++ b/btcjson/help.go @@ -476,11 +476,12 @@ func isValidResultType(kind reflect.Kind) bool { // an error will use the key in place of the description. // // The following outlines the required keys: -// "--synopsis" Synopsis for the command -// "-" Description for each command argument -// "-" Description for each object field -// "--condition<#>" Description for each result condition -// "--result<#>" Description for each primitive result num +// +// "--synopsis" Synopsis for the command +// "-" Description for each command argument +// "-" Description for each object field +// "--condition<#>" Description for each result condition +// "--result<#>" Description for each primitive result num // // Notice that the "special" keys synopsis, condition<#>, and result<#> are // preceded by a double dash to ensure they don't conflict with field names. @@ -492,16 +493,17 @@ func isValidResultType(kind reflect.Kind) bool { // For example, consider the 'help' command itself. There are two possible // returns depending on the provided parameters. So, the help would be // generated by calling the function as follows: -// GenerateHelp("help", descs, (*string)(nil), (*string)(nil)). +// +// GenerateHelp("help", descs, (*string)(nil), (*string)(nil)). // // The following keys would then be required in the provided descriptions map: // -// "help--synopsis": "Returns a list of all commands or help for ...." -// "help-command": "The command to retrieve help for", -// "help--condition0": "no command provided" -// "help--condition1": "command specified" -// "help--result0": "List of commands" -// "help--result1": "Help for specified command" +// "help--synopsis": "Returns a list of all commands or help for ...." +// "help-command": "The command to retrieve help for", +// "help--condition0": "no command provided" +// "help--condition1": "command specified" +// "help--result0": "List of commands" +// "help--result1": "Help for specified command" func GenerateHelp(method string, descs map[string]string, resultTypes ...interface{}) (string, error) { // Look up details about the provided method and error out if not // registered. diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 5983d3f783..979ab0c25b 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -875,7 +875,8 @@ func (s *ScriptPubKey) UnmarshalJSON(data []byte) error { // // Descriptors are typically ranged when specified in the form of generic HD // chain paths. -// Example of a ranged descriptor: pkh(tpub.../*) +// +// Example of a ranged descriptor: pkh(tpub.../*) // // The value can be an int to specify the end of the range, or the range // itself, as []int{begin, end}. diff --git a/btcjson/walletsvrresults.go b/btcjson/walletsvrresults.go index 78a6e647f5..d85db0a6fa 100644 --- a/btcjson/walletsvrresults.go +++ b/btcjson/walletsvrresults.go @@ -48,11 +48,11 @@ type embeddedAddressInfo struct { // Reference: https://bitcoincore.org/en/doc/0.20.0/rpc/wallet/getaddressinfo // // The GetAddressInfoResult has three segments: -// 1. General information about the address. -// 2. Metadata (Timestamp, HDKeyPath, HDSeedID) and wallet fields -// (IsMine, IsWatchOnly). -// 3. Information about the embedded address in case of P2SH or P2WSH. -// Same structure as (1). +// 1. General information about the address. +// 2. Metadata (Timestamp, HDKeyPath, HDSeedID) and wallet fields +// (IsMine, IsWatchOnly). +// 3. Information about the embedded address in case of P2SH or P2WSH. +// Same structure as (1). type GetAddressInfoResult struct { embeddedAddressInfo IsMine bool `json:"ismine"` diff --git a/btcutil/appdata.go b/btcutil/appdata.go index e36cf7c4a4..b6c63b9a29 100644 --- a/btcutil/appdata.go +++ b/btcutil/appdata.go @@ -95,11 +95,12 @@ func appDataDir(goos, appName string, roaming bool) string { // (%LOCALAPPDATA%) that is used by default. // // Example results: -// dir := AppDataDir("myapp", false) -// POSIX (Linux/BSD): ~/.myapp -// Mac OS: $HOME/Library/Application Support/Myapp -// Windows: %LOCALAPPDATA%\Myapp -// Plan 9: $home/myapp +// +// dir := AppDataDir("myapp", false) +// POSIX (Linux/BSD): ~/.myapp +// Mac OS: $HOME/Library/Application Support/Myapp +// Windows: %LOCALAPPDATA%\Myapp +// Plan 9: $home/myapp func AppDataDir(appName string, roaming bool) string { return appDataDir(runtime.GOOS, appName, roaming) } diff --git a/btcutil/base58/doc.go b/btcutil/base58/doc.go index 9a2c0e6e3d..d657f050f7 100644 --- a/btcutil/base58/doc.go +++ b/btcutil/base58/doc.go @@ -6,7 +6,7 @@ Package base58 provides an API for working with modified base58 and Base58Check encodings. -Modified Base58 Encoding +# Modified Base58 Encoding Standard base58 encoding is similar to standard base64 encoding except, as the name implies, it uses a 58 character alphabet which results in an alphanumeric @@ -17,7 +17,7 @@ The modified base58 alphabet used by Bitcoin, and hence this package, omits the 0, O, I, and l characters that look the same in many fonts and are therefore hard to humans to distinguish. -Base58Check Encoding Scheme +# Base58Check Encoding Scheme The Base58Check encoding scheme is primarily used for Bitcoin addresses at the time of this writing, however it can be used to generically encode arbitrary diff --git a/btcutil/base58/genalphabet.go b/btcutil/base58/genalphabet.go index 010cbee39e..959f34d4e2 100644 --- a/btcutil/base58/genalphabet.go +++ b/btcutil/base58/genalphabet.go @@ -2,7 +2,8 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -//+build ignore +//go:build ignore +// +build ignore package main diff --git a/btcutil/block_test.go b/btcutil/block_test.go index e24b9842f7..06e0ad2803 100644 --- a/btcutil/block_test.go +++ b/btcutil/block_test.go @@ -11,9 +11,9 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "github.com/davecgh/go-spew/spew" ) diff --git a/btcutil/bloom/example_test.go b/btcutil/bloom/example_test.go index bcd5d0190b..e5a148a5ba 100644 --- a/btcutil/bloom/example_test.go +++ b/btcutil/bloom/example_test.go @@ -9,9 +9,9 @@ import ( "math/rand" "time" + "github.com/btcsuite/btcd/btcutil/bloom" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil/bloom" ) // This example demonstrates how to create a new bloom filter, add a transaction diff --git a/btcutil/bloom/filter.go b/btcutil/bloom/filter.go index 8c4527ea29..2eca228570 100644 --- a/btcutil/bloom/filter.go +++ b/btcutil/bloom/filter.go @@ -9,10 +9,10 @@ import ( "math" "sync" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // ln2Squared is simply the square of the natural log of 2. diff --git a/btcutil/bloom/filter_test.go b/btcutil/bloom/filter_test.go index 1811dbf57e..c4b839ad17 100644 --- a/btcutil/bloom/filter_test.go +++ b/btcutil/bloom/filter_test.go @@ -9,10 +9,10 @@ import ( "encoding/hex" "testing" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/bloom" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" ) // TestFilterLarge ensures a maximum sized filter can be created. diff --git a/btcutil/bloom/merkleblock.go b/btcutil/bloom/merkleblock.go index 101a8f9194..5e18682d2a 100644 --- a/btcutil/bloom/merkleblock.go +++ b/btcutil/bloom/merkleblock.go @@ -6,9 +6,9 @@ package bloom import ( "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // merkleBlock is used to house intermediate information needed to generate a diff --git a/btcutil/bloom/merkleblock_test.go b/btcutil/bloom/merkleblock_test.go index 15e21a4bb7..ae7b1f3430 100644 --- a/btcutil/bloom/merkleblock_test.go +++ b/btcutil/bloom/merkleblock_test.go @@ -9,10 +9,10 @@ import ( "encoding/hex" "testing" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/bloom" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" ) func TestMerkleBlock3(t *testing.T) { diff --git a/btcutil/coinset/coins.go b/btcutil/coinset/coins.go index 9d813418b6..a0e680d8d6 100644 --- a/btcutil/coinset/coins.go +++ b/btcutil/coinset/coins.go @@ -9,9 +9,9 @@ import ( "errors" "sort" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // Coin represents a spendable transaction outpoint @@ -75,7 +75,7 @@ func (cs *CoinSet) TotalValue() (value btcutil.Amount) { } // TotalValueAge returns the total value * number of confirmations -// of the coins in the set. +// of the coins in the set. func (cs *CoinSet) TotalValueAge() (valueAge int64) { return cs.totalValueAge } @@ -238,7 +238,6 @@ func (s MaxValueAgeCoinSelector) CoinSelect(targetValue btcutil.Amount, coins [] // input priority over the threshold, but no guarantees will be made as to // minimality of the selection. The selection below is almost certainly // suboptimal. -// type MinPriorityCoinSelector struct { MaxInputs int MinChangeAmount btcutil.Amount diff --git a/btcutil/coinset/coins_test.go b/btcutil/coinset/coins_test.go index 874dc6c6d6..035a40cb99 100644 --- a/btcutil/coinset/coins_test.go +++ b/btcutil/coinset/coins_test.go @@ -11,10 +11,10 @@ import ( "fmt" "testing" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/coinset" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" ) type TestCoin struct { diff --git a/btcutil/doc.go b/btcutil/doc.go index 36cda1c782..c4a4441201 100644 --- a/btcutil/doc.go +++ b/btcutil/doc.go @@ -5,21 +5,21 @@ /* Package btcutil provides bitcoin-specific convenience functions and types. -Block Overview +# Block Overview A Block defines a bitcoin block that provides easier and more efficient manipulation of raw wire protocol blocks. It also memoizes hashes for the block and its transactions on their first access so subsequent accesses don't have to repeat the relatively expensive hashing operations. -Tx Overview +# Tx Overview A Tx defines a bitcoin transaction that provides more efficient manipulation of raw wire protocol transactions. It memoizes the hash for the transaction on its first access so subsequent accesses don't have to repeat the relatively expensive hashing operations. -Address Overview +# Address Overview The Address interface provides an abstraction for a Bitcoin address. While the most common type is a pay-to-pubkey-hash, Bitcoin already supports others and diff --git a/btcutil/gcs/builder/builder.go b/btcutil/gcs/builder/builder.go index 6f15ec7a68..af05f819a5 100644 --- a/btcutil/gcs/builder/builder.go +++ b/btcutil/gcs/builder/builder.go @@ -10,10 +10,10 @@ import ( "fmt" "math" + "github.com/btcsuite/btcd/btcutil/gcs" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil/gcs" ) const ( diff --git a/btcutil/gcs/doc.go b/btcutil/gcs/doc.go index 780fd76631..8e67e369a6 100644 --- a/btcutil/gcs/doc.go +++ b/btcutil/gcs/doc.go @@ -6,14 +6,14 @@ /* Package gcs provides an API for building and using a Golomb-coded set filter. -Golomb-Coded Set +# Golomb-Coded Set A Golomb-coded set is a probabilistic data structure used similarly to a Bloom filter. A filter uses constant-size overhead plus on average n+2 bits per item added to the filter, where 2^-n is the desired false positive (collision) probability. -GCS use in Bitcoin +# GCS use in Bitcoin GCS filters are a proposed mechanism for storing and transmitting per-block filters in Bitcoin. The usage is intended to be the inverse of Bloom filters: diff --git a/btcutil/gcs/gcs.go b/btcutil/gcs/gcs.go index fbffb06131..fca315d6db 100644 --- a/btcutil/gcs/gcs.go +++ b/btcutil/gcs/gcs.go @@ -44,7 +44,7 @@ const ( // described in: // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ // -// * v * N >> log_2(N) +// v * N >> log_2(N) // // In our case, using 64-bit integers, log_2 is 64. As most processors don't // support 128-bit arithmetic natively, we'll be super portable and unfold the diff --git a/btcutil/hdkeychain/doc.go b/btcutil/hdkeychain/doc.go index dcf74f6b51..094bcdd646 100644 --- a/btcutil/hdkeychain/doc.go +++ b/btcutil/hdkeychain/doc.go @@ -6,7 +6,7 @@ Package hdkeychain provides an API for bitcoin hierarchical deterministic extended keys (BIP0032). -Overview +# Overview The ability to implement hierarchical deterministic wallets depends on the ability to create and derive hierarchical deterministic extended keys. @@ -16,19 +16,19 @@ deterministic extended keys by providing an ExtendedKey type and supporting functions. Each extended key can either be a private or public extended key which itself is capable of deriving a child extended key. -Determining the Extended Key Type +# Determining the Extended Key Type Whether an extended key is a private or public extended key can be determined with the IsPrivate function. -Transaction Signing Keys and Payment Addresses +# Transaction Signing Keys and Payment Addresses In order to create and sign transactions, or provide others with addresses to send funds to, the underlying key and address material must be accessible. This package provides the ECPubKey, ECPrivKey, and Address functions for this purpose. -The Master Node +# The Master Node As previously mentioned, the extended keys are hierarchical meaning they are used to form a tree. The root of that tree is called the master node and this @@ -36,7 +36,7 @@ package provides the NewMaster function to create it from a cryptographically random seed. The GenerateSeed function is provided as a convenient way to create a random seed for use with the NewMaster function. -Deriving Children +# Deriving Children Once you have created a tree root (or have deserialized an extended key as discussed later), the child extended keys can be derived by using the Derive @@ -46,7 +46,7 @@ the HardenedKeyStart constant + the hardened key number as the index to the Derive function. This provides the ability to cascade the keys into a tree and hence generate the hierarchical deterministic key chains. -Normal vs Hardened Derived Extended Keys +# Normal vs Hardened Derived Extended Keys A private extended key can be used to derive both hardened and non-hardened (normal) child private and public extended keys. A public extended key can only @@ -59,22 +59,23 @@ the reason for the existence of hardened keys, and why they are used for the account level in the tree. This way, a leak of an account-specific (or below) private key never risks compromising the master or other accounts." -Neutering a Private Extended Key +# Neutering a Private Extended Key A private extended key can be converted to a new instance of the corresponding public extended key with the Neuter function. The original extended key is not modified. A public extended key is still capable of deriving non-hardened child public extended keys. -Serializing and Deserializing Extended Keys +# Serializing and Deserializing Extended Keys Extended keys are serialized and deserialized with the String and NewKeyFromString functions. The serialized key is a Base58-encoded string which looks like the following: + public key: xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw private key: xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 -Network +# Network Extended keys are much like normal Bitcoin addresses in that they have version bytes which tie them to a specific network. The SetNet and IsForNet functions diff --git a/btcutil/hdkeychain/example_test.go b/btcutil/hdkeychain/example_test.go index 7489d387a7..8ea4244df1 100644 --- a/btcutil/hdkeychain/example_test.go +++ b/btcutil/hdkeychain/example_test.go @@ -7,8 +7,8 @@ package hdkeychain_test import ( "fmt" - "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/btcutil/hdkeychain" + "github.com/btcsuite/btcd/chaincfg" ) // This example demonstrates how to generate a cryptographically random seed diff --git a/btcutil/hdkeychain/extendedkey.go b/btcutil/hdkeychain/extendedkey.go index c44e6a18b4..0bbb1e7d19 100644 --- a/btcutil/hdkeychain/extendedkey.go +++ b/btcutil/hdkeychain/extendedkey.go @@ -517,8 +517,9 @@ func (k *ExtendedKey) Neuter() (*ExtendedKey, error) { // on the SLIP132 standard (serializable to yprv/ypub, zprv/zpub, etc.). // // References: -// [SLIP132]: SLIP-0132 - Registered HD version bytes for BIP-0032 -// https://github.com/satoshilabs/slips/blob/master/slip-0132.md +// +// [SLIP132]: SLIP-0132 - Registered HD version bytes for BIP-0032 +// https://github.com/satoshilabs/slips/blob/master/slip-0132.md func (k *ExtendedKey) CloneWithVersion(version []byte) (*ExtendedKey, error) { if len(version) != 4 { // TODO: The semantically correct error to return here is diff --git a/btcutil/hdkeychain/extendedkey_test.go b/btcutil/hdkeychain/extendedkey_test.go index 0721b92480..05ec2d6d37 100644 --- a/btcutil/hdkeychain/extendedkey_test.go +++ b/btcutil/hdkeychain/extendedkey_test.go @@ -1095,7 +1095,8 @@ func TestMaximumDepth(t *testing.T) { // extended keys. // // The following tool was used for generating the tests: -// https://jlopp.github.io/xpub-converter +// +// https://jlopp.github.io/xpub-converter func TestCloneWithVersion(t *testing.T) { tests := []struct { name string diff --git a/btcutil/net.go b/btcutil/net.go index bf11733c64..ec5638622b 100644 --- a/btcutil/net.go +++ b/btcutil/net.go @@ -2,6 +2,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. +//go:build !appengine // +build !appengine package btcutil diff --git a/btcutil/net_noop.go b/btcutil/net_noop.go index b0b7c2e40a..ae9c1f5fb9 100644 --- a/btcutil/net_noop.go +++ b/btcutil/net_noop.go @@ -2,6 +2,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. +//go:build appengine // +build appengine package btcutil diff --git a/btcutil/tx_test.go b/btcutil/tx_test.go index 828fc065b1..71b7488e9d 100644 --- a/btcutil/tx_test.go +++ b/btcutil/tx_test.go @@ -10,8 +10,8 @@ import ( "reflect" "testing" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/davecgh/go-spew/spew" ) diff --git a/btcutil/txsort/doc.go b/btcutil/txsort/doc.go index e89c4d23d3..9f5095ce8b 100644 --- a/btcutil/txsort/doc.go +++ b/btcutil/txsort/doc.go @@ -5,7 +5,7 @@ /* Package txsort provides the transaction sorting according to BIP 69. -Overview +# Overview BIP 69 defines a standard lexicographical sort order of transaction inputs and outputs. This is useful to standardize transactions for faster multi-party diff --git a/btcutil/txsort/txsort_test.go b/btcutil/txsort/txsort_test.go index 7d5c2d3eaf..dd2149294e 100644 --- a/btcutil/txsort/txsort_test.go +++ b/btcutil/txsort/txsort_test.go @@ -11,8 +11,8 @@ import ( "path/filepath" "testing" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil/txsort" + "github.com/btcsuite/btcd/wire" ) // TestSort ensures the transaction sorting works according to the BIP. diff --git a/btcutil/wif.go b/btcutil/wif.go index a28cc8ba8d..26316dd7ff 100644 --- a/btcutil/wif.go +++ b/btcutil/wif.go @@ -68,14 +68,14 @@ func (w *WIF) IsForNet(net *chaincfg.Params) bool { // The WIF string must be a base58-encoded string of the following byte // sequence: // -// * 1 byte to identify the network, must be 0x80 for mainnet or 0xef for -// either testnet3 or the regression test network -// * 32 bytes of a binary-encoded, big-endian, zero-padded private key -// * Optional 1 byte (equal to 0x01) if the address being imported or exported -// was created by taking the RIPEMD160 after SHA256 hash of a serialized -// compressed (33-byte) public key -// * 4 bytes of checksum, must equal the first four bytes of the double SHA256 -// of every byte before the checksum in this sequence +// - 1 byte to identify the network, must be 0x80 for mainnet or 0xef for +// either testnet3 or the regression test network +// - 32 bytes of a binary-encoded, big-endian, zero-padded private key +// - Optional 1 byte (equal to 0x01) if the address being imported or exported +// was created by taking the RIPEMD160 after SHA256 hash of a serialized +// compressed (33-byte) public key +// - 4 bytes of checksum, must equal the first four bytes of the double SHA256 +// of every byte before the checksum in this sequence // // If the base58-decoded byte sequence does not match this, DecodeWIF will // return a non-nil error. ErrMalformedPrivateKey is returned when the WIF diff --git a/chaincfg/doc.go b/chaincfg/doc.go index 1595b2769f..65efb54f66 100644 --- a/chaincfg/doc.go +++ b/chaincfg/doc.go @@ -18,40 +18,40 @@ // When a network parameter is needed, it may then be looked up through this // variable (either directly, or hidden in a library call). // -// package main +// package main // -// import ( -// "flag" -// "fmt" -// "log" +// import ( +// "flag" +// "fmt" +// "log" // -// "github.com/btcsuite/btcd/btcutil" -// "github.com/btcsuite/btcd/chaincfg" -// ) +// "github.com/btcsuite/btcd/btcutil" +// "github.com/btcsuite/btcd/chaincfg" +// ) // -// var testnet = flag.Bool("testnet", false, "operate on the testnet Bitcoin network") +// var testnet = flag.Bool("testnet", false, "operate on the testnet Bitcoin network") // -// // By default (without -testnet), use mainnet. -// var chainParams = &chaincfg.MainNetParams +// // By default (without -testnet), use mainnet. +// var chainParams = &chaincfg.MainNetParams // -// func main() { -// flag.Parse() +// func main() { +// flag.Parse() // -// // Modify active network parameters if operating on testnet. -// if *testnet { -// chainParams = &chaincfg.TestNet3Params -// } +// // Modify active network parameters if operating on testnet. +// if *testnet { +// chainParams = &chaincfg.TestNet3Params +// } // -// // later... +// // later... // -// // Create and print new payment address, specific to the active network. -// pubKeyHash := make([]byte, 20) -// addr, err := btcutil.NewAddressPubKeyHash(pubKeyHash, chainParams) -// if err != nil { -// log.Fatal(err) -// } -// fmt.Println(addr) -// } +// // Create and print new payment address, specific to the active network. +// pubKeyHash := make([]byte, 20) +// addr, err := btcutil.NewAddressPubKeyHash(pubKeyHash, chainParams) +// if err != nil { +// log.Fatal(err) +// } +// fmt.Println(addr) +// } // // If an application does not use one of the three standard Bitcoin networks, // a new Params struct may be created which defines the parameters for the diff --git a/chaincfg/params.go b/chaincfg/params.go index f0a7a83b79..38034ac204 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -1007,8 +1007,9 @@ func IsBech32SegwitPrefix(prefix string) bool { // ErrInvalidHDKeyID error will be returned. // // Reference: -// SLIP-0132 : Registered HD version bytes for BIP-0032 -// https://github.com/satoshilabs/slips/blob/master/slip-0132.md +// +// SLIP-0132 : Registered HD version bytes for BIP-0032 +// https://github.com/satoshilabs/slips/blob/master/slip-0132.md func RegisterHDKeyID(hdPublicKeyID []byte, hdPrivateKeyID []byte) error { if len(hdPublicKeyID) != 4 || len(hdPrivateKeyID) != 4 { return ErrInvalidHDKeyID diff --git a/cmd/addblock/config.go b/cmd/addblock/config.go index c638196534..ffcc0eca79 100644 --- a/cmd/addblock/config.go +++ b/cmd/addblock/config.go @@ -9,11 +9,11 @@ import ( "os" "path/filepath" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" flags "github.com/jessevdk/go-flags" ) diff --git a/cmd/addblock/import.go b/cmd/addblock/import.go index 4875ce11cb..7f4b9bb0f5 100644 --- a/cmd/addblock/import.go +++ b/cmd/addblock/import.go @@ -13,10 +13,10 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/blockchain/indexers" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) var zeroHash = chainhash.Hash{} diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index 3db735c5d8..5d99c43e6f 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -14,8 +14,8 @@ import ( "strings" "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" flags "github.com/jessevdk/go-flags" ) @@ -176,10 +176,10 @@ func cleanAndExpandPath(path string) string { // line options. // // The configuration proceeds as follows: -// 1) Start with a default config with sane settings -// 2) Pre-parse the command line to check for an alternative config file -// 3) Load configuration file overwriting defaults with any specified options -// 4) Parse CLI options and overwrite/add any specified options +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options // // The above results in functioning properly without any config settings // while still allowing the user to override settings with config files and diff --git a/cmd/findcheckpoint/config.go b/cmd/findcheckpoint/config.go index 5671b5b186..203ed27faf 100644 --- a/cmd/findcheckpoint/config.go +++ b/cmd/findcheckpoint/config.go @@ -9,11 +9,11 @@ import ( "os" "path/filepath" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" flags "github.com/jessevdk/go-flags" ) diff --git a/config.go b/config.go index 656e94df2a..881123f5e9 100644 --- a/config.go +++ b/config.go @@ -22,6 +22,7 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/connmgr" @@ -30,7 +31,6 @@ import ( "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/go-socks/socks" flags "github.com/jessevdk/go-flags" ) @@ -403,10 +403,10 @@ func newConfigParser(cfg *config, so *serviceOptions, options flags.Options) *fl // line options. // // The configuration proceeds as follows: -// 1) Start with a default config with sane settings -// 2) Pre-parse the command line to check for an alternative config file -// 3) Load configuration file overwriting defaults with any specified options -// 4) Parse CLI options and overwrite/add any specified options +// 1. Start with a default config with sane settings +// 2. Pre-parse the command line to check for an alternative config file +// 3. Load configuration file overwriting defaults with any specified options +// 4. Parse CLI options and overwrite/add any specified options // // The above results in btcd functioning properly without any config settings // while still allowing the user to override settings with config files and diff --git a/connmgr/doc.go b/connmgr/doc.go index acb90c31a9..d101c4347f 100644 --- a/connmgr/doc.go +++ b/connmgr/doc.go @@ -5,7 +5,7 @@ /* Package connmgr implements a generic Bitcoin network connection manager. -Connection Manager Overview +# Connection Manager Overview Connection Manager handles all the general connection concerns such as maintaining a set number of outbound connections, sourcing peers, banning, diff --git a/database/cmd/dbtool/globalconfig.go b/database/cmd/dbtool/globalconfig.go index 2ec746a43d..4e58168a33 100644 --- a/database/cmd/dbtool/globalconfig.go +++ b/database/cmd/dbtool/globalconfig.go @@ -10,11 +10,11 @@ import ( "os" "path/filepath" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" _ "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/database/cmd/dbtool/insecureimport.go b/database/cmd/dbtool/insecureimport.go index a01c74bb55..744e29f57b 100644 --- a/database/cmd/dbtool/insecureimport.go +++ b/database/cmd/dbtool/insecureimport.go @@ -12,10 +12,10 @@ import ( "sync" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // importCmd defines the configuration options for the insecureimport command. diff --git a/database/doc.go b/database/doc.go index 497206713f..80a2669da1 100644 --- a/database/doc.go +++ b/database/doc.go @@ -5,7 +5,7 @@ /* Package database provides a block and metadata storage database. -Overview +# Overview As of Feb 2016, there are over 400,000 blocks in the Bitcoin block chain and and over 112 million transactions (which turns out to be over 60GB of data). @@ -18,15 +18,15 @@ storage, and strict checksums in key areas to ensure data integrity. A quick overview of the features database provides are as follows: - - Key/value metadata store - - Bitcoin block storage - - Efficient retrieval of block headers and regions (transactions, scripts, etc) - - Read-only and read-write transactions with both manual and managed modes - - Nested buckets - - Supports registration of backend databases - - Comprehensive test coverage + - Key/value metadata store + - Bitcoin block storage + - Efficient retrieval of block headers and regions (transactions, scripts, etc) + - Read-only and read-write transactions with both manual and managed modes + - Nested buckets + - Supports registration of backend databases + - Comprehensive test coverage -Database +# Database The main entry point is the DB interface. It exposes functionality for transactional-based access and storage of metadata and block data. It is @@ -43,14 +43,14 @@ The Begin function provides an unmanaged transaction while the View and Update functions provide a managed transaction. These are described in more detail below. -Transactions +# Transactions The Tx interface provides facilities for rolling back or committing changes that took place while the transaction was active. It also provides the root metadata bucket under which all keys, values, and nested buckets are stored. A transaction can either be read-only or read-write and managed or unmanaged. -Managed versus Unmanaged Transactions +# Managed versus Unmanaged Transactions A managed transaction is one where the caller provides a function to execute within the context of the transaction and the commit or rollback is handled @@ -63,7 +63,7 @@ call Commit or Rollback when they are finished with it. Leaving transactions open for long periods of time can have several adverse effects, so it is recommended that managed transactions are used instead. -Buckets +# Buckets The Bucket interface provides the ability to manipulate key/value pairs and nested buckets as well as iterate through them. @@ -73,7 +73,7 @@ CreateBucket, CreateBucketIfNotExists, and DeleteBucket functions work with buckets. The ForEach function allows the caller to provide a function to be called with each key/value pair and nested bucket in the current bucket. -Metadata Bucket +# Metadata Bucket As discussed above, all of the functions which are used to manipulate key/value pairs and nested buckets exist on the Bucket interface. The root metadata @@ -81,7 +81,7 @@ bucket is the upper-most bucket in which data is stored and is created at the same time as the database. Use the Metadata function on the Tx interface to retrieve it. -Nested Buckets +# Nested Buckets The CreateBucket and CreateBucketIfNotExists functions on the Bucket interface provide the ability to create an arbitrary number of nested buckets. It is diff --git a/database/ffldb/bench_test.go b/database/ffldb/bench_test.go index f4a0eb32e5..95e498b274 100644 --- a/database/ffldb/bench_test.go +++ b/database/ffldb/bench_test.go @@ -9,9 +9,9 @@ import ( "path/filepath" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" - "github.com/btcsuite/btcd/btcutil" ) // BenchmarkBlockHeader benchmarks how long it takes to load the mainnet genesis diff --git a/database/ffldb/blockio.go b/database/ffldb/blockio.go index 8fb27ab283..50e853f6dc 100644 --- a/database/ffldb/blockio.go +++ b/database/ffldb/blockio.go @@ -622,8 +622,8 @@ func (s *blockStore) syncBlocks() error { // were partially written. // // There are effectively two scenarios to consider here: -// 1) Transient write failures from which recovery is possible -// 2) More permanent failures such as hard disk death and/or removal +// 1. Transient write failures from which recovery is possible +// 2. More permanent failures such as hard disk death and/or removal // // In either case, the write cursor will be repositioned to the old block file // offset regardless of any other errors that occur while attempting to undo diff --git a/database/ffldb/db.go b/database/ffldb/db.go index f571d3889b..c0e2bb3a6a 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -14,11 +14,11 @@ import ( "sort" "sync" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database/internal/treap" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "github.com/syndtr/goleveldb/leveldb" "github.com/syndtr/goleveldb/leveldb/comparer" ldberrors "github.com/syndtr/goleveldb/leveldb/errors" diff --git a/database/ffldb/doc.go b/database/ffldb/doc.go index 96a2992cb9..0001196746 100644 --- a/database/ffldb/doc.go +++ b/database/ffldb/doc.go @@ -10,7 +10,7 @@ This driver is the recommended driver for use with btcd. It makes use leveldb for the metadata, flat files for block storage, and checksums in key areas to ensure data integrity. -Usage +# Usage This package is a driver to the database package and provides the database type of "ffldb". The parameters the Open and Create functions take are the diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index ef35f07840..29d31eafc4 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -11,10 +11,10 @@ import ( "reflect" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database/ffldb" - "github.com/btcsuite/btcd/btcutil" ) // dbType is the database type name for this driver. diff --git a/database/ffldb/interface_test.go b/database/ffldb/interface_test.go index af26faccab..58b4ab15e5 100644 --- a/database/ffldb/interface_test.go +++ b/database/ffldb/interface_test.go @@ -25,11 +25,11 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/database/ffldb/whitebox_test.go b/database/ffldb/whitebox_test.go index f2eae8ce09..cc7c13d45f 100644 --- a/database/ffldb/whitebox_test.go +++ b/database/ffldb/whitebox_test.go @@ -17,10 +17,10 @@ import ( "path/filepath" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "github.com/syndtr/goleveldb/leveldb" ldberrors "github.com/syndtr/goleveldb/leveldb/errors" ) diff --git a/database/interface.go b/database/interface.go index aa88cc3723..d4f1d89d2e 100644 --- a/database/interface.go +++ b/database/interface.go @@ -8,8 +8,8 @@ package database import ( - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) // Cursor represents a cursor over key/value pairs and nested buckets of a diff --git a/database/internal/treap/treapiter.go b/database/internal/treap/treapiter.go index d6981aafd8..ae7ed853b8 100644 --- a/database/internal/treap/treapiter.go +++ b/database/internal/treap/treapiter.go @@ -318,13 +318,14 @@ func (iter *Iterator) ForceReseek() { // unexpected keys and/or values. // // For example: -// iter := t.Iterator(nil, nil) -// for iter.Next() { -// if someCondition { -// t.Delete(iter.Key()) -// iter.ForceReseek() -// } -// } +// +// iter := t.Iterator(nil, nil) +// for iter.Next() { +// if someCondition { +// t.Delete(iter.Key()) +// iter.ForceReseek() +// } +// } func (t *Mutable) Iterator(startKey, limitKey []byte) *Iterator { iter := &Iterator{ t: t, diff --git a/doc.go b/doc.go index 70d0d9e45c..d78e09f7e3 100644 --- a/doc.go +++ b/doc.go @@ -18,143 +18,145 @@ on Windows. The -C (--configfile) flag, as shown below, can be used to override this location. Usage: - btcd [OPTIONS] + + btcd [OPTIONS] Application Options: - --addcheckpoint= Add a custom checkpoint. Format: - ':' - -a, --addpeer= Add a peer to connect with at startup - --addrindex Maintain a full address-based transaction index - which makes the searchrawtransactions RPC - available - --banduration= How long to ban misbehaving peers. Valid time - units are {s, m, h}. Minimum 1 second (default: - 24h0m0s) - --banthreshold= Maximum allowed ban score before disconnecting - and banning misbehaving peers. (default: 100) - --blockmaxsize= Maximum block size in bytes to be used when - creating a block (default: 750000) - --blockminsize= Mininum block size in bytes to be used when - creating a block - --blockmaxweight= Maximum block weight to be used when creating a - block (default: 3000000) - --blockminweight= Mininum block weight to be used when creating a - block - --blockprioritysize= Size in bytes for high-priority/low-fee - transactions when creating a block (default: - 50000) - --blocksonly Do not accept transactions from remote peers. - -C, --configfile= Path to configuration file - --connect= Connect only to the specified peers at startup - --cpuprofile= Write CPU profile to the specified file - -b, --datadir= Directory to store data - --dbtype= Database backend to use for the Block Chain - (default: ffldb) - -d, --debuglevel= Logging level for all subsystems {trace, debug, - info, warn, error, critical} -- You may also - specify - =,=,... to - set the log level for individual subsystems -- - Use show to list available subsystems (default: - info) - --dropaddrindex Deletes the address-based transaction index from - the database on start up and then exits. - --dropcfindex Deletes the index used for committed filtering - (CF) support from the database on start up and - then exits. - --droptxindex Deletes the hash-based transaction index from the - database on start up and then exits. - --externalip= Add an ip to the list of local addresses we claim - to listen on to peers - --generate Generate (mine) bitcoins using the CPU - --limitfreerelay= Limit relay of transactions with no transaction - fee to the given amount in thousands of bytes per - minute (default: 15) - --listen= Add an interface/port to listen for connections - (default all interfaces port: 8333, testnet: - 18333, signet: 38333) - --logdir= Directory to log output - --maxorphantx= Max number of orphan transactions to keep in - memory (default: 100) - --maxpeers= Max number of inbound and outbound peers - (default: 125) - --miningaddr= Add the specified payment address to the list of - addresses to use for generated blocks -- At least - one address is required if the generate option is - set - --minrelaytxfee= The minimum transaction fee in BTC/kB to be - considered a non-zero fee. (default: 1e-05) - --nobanning Disable banning of misbehaving peers - --nocfilters Disable committed filtering (CF) support - --nocheckpoints Disable built-in checkpoints. Don't do this - unless you know what you're doing. - --nodnsseed Disable DNS seeding for peers - --nolisten Disable listening for incoming connections -- - NOTE: Listening is automatically disabled if the - --connect or --proxy options are used without - also specifying listen interfaces via --listen - --noonion Disable connecting to tor hidden services - --nopeerbloomfilters Disable bloom filtering support - --norelaypriority Do not require free or low-fee transactions to - have high priority for relaying - --norpc Disable built-in RPC server -- NOTE: The RPC - server is disabled by default if no - rpcuser/rpcpass or rpclimituser/rpclimitpass is - specified - --notls Disable TLS for the RPC server -- NOTE: This is - only allowed if the RPC server is bound to - localhost - --onion= Connect to tor hidden services via SOCKS5 proxy - (eg. 127.0.0.1:9050) - --onionpass= Password for onion proxy server - --onionuser= Username for onion proxy server - --profile= Enable HTTP profiling on given port -- NOTE port - must be between 1024 and 65536 - --proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050) - --proxypass= Password for proxy server - --proxyuser= Username for proxy server - --regtest Use the regression test network - --rejectnonstd Reject non-standard transactions regardless of - the default settings for the active network. - --relaynonstd Relay non-standard transactions regardless of the - default settings for the active network. - --rpccert= File containing the certificate file - --rpckey= File containing the certificate key - --rpclimitpass= Password for limited RPC connections - --rpclimituser= Username for limited RPC connections - --rpclisten= Add an interface/port to listen for RPC - connections (default port: 8334, testnet: 18334) - --rpcmaxclients= Max number of RPC clients for standard - connections (default: 10) - --rpcmaxconcurrentreqs= Max number of concurrent RPC requests that may be - processed concurrently (default: 20) - --rpcmaxwebsockets= Max number of RPC websocket connections (default: - 25) - --rpcquirks Mirror some JSON-RPC quirks of Bitcoin Core -- - NOTE: Discouraged unless interoperability issues - need to be worked around - -P, --rpcpass= Password for RPC connections - -u, --rpcuser= Username for RPC connections - --sigcachemaxsize= The maximum number of entries in the signature - verification cache (default: 100000) - --simnet Use the simulation test network - --testnet Use the test network - --torisolation Enable Tor stream isolation by randomizing user - credentials for each connection. - --trickleinterval= Minimum time between attempts to send new - inventory to a connected peer (default: 10s) - --txindex Maintain a full hash-based transaction index - which makes all transactions available via the - getrawtransaction RPC - --uacomment= Comment to add to the user agent -- See BIP 14 - for more information. - --upnp Use UPnP to map our listening port outside of NAT - -V, --version Display version information and exit - --whitelist= Add an IP network or IP that will not be banned. - (eg. 192.168.1.0/24 or ::1) + + --addcheckpoint= Add a custom checkpoint. Format: + ':' + -a, --addpeer= Add a peer to connect with at startup + --addrindex Maintain a full address-based transaction index + which makes the searchrawtransactions RPC + available + --banduration= How long to ban misbehaving peers. Valid time + units are {s, m, h}. Minimum 1 second (default: + 24h0m0s) + --banthreshold= Maximum allowed ban score before disconnecting + and banning misbehaving peers. (default: 100) + --blockmaxsize= Maximum block size in bytes to be used when + creating a block (default: 750000) + --blockminsize= Mininum block size in bytes to be used when + creating a block + --blockmaxweight= Maximum block weight to be used when creating a + block (default: 3000000) + --blockminweight= Mininum block weight to be used when creating a + block + --blockprioritysize= Size in bytes for high-priority/low-fee + transactions when creating a block (default: + 50000) + --blocksonly Do not accept transactions from remote peers. + -C, --configfile= Path to configuration file + --connect= Connect only to the specified peers at startup + --cpuprofile= Write CPU profile to the specified file + -b, --datadir= Directory to store data + --dbtype= Database backend to use for the Block Chain + (default: ffldb) + -d, --debuglevel= Logging level for all subsystems {trace, debug, + info, warn, error, critical} -- You may also + specify + =,=,... to + set the log level for individual subsystems -- + Use show to list available subsystems (default: + info) + --dropaddrindex Deletes the address-based transaction index from + the database on start up and then exits. + --dropcfindex Deletes the index used for committed filtering + (CF) support from the database on start up and + then exits. + --droptxindex Deletes the hash-based transaction index from the + database on start up and then exits. + --externalip= Add an ip to the list of local addresses we claim + to listen on to peers + --generate Generate (mine) bitcoins using the CPU + --limitfreerelay= Limit relay of transactions with no transaction + fee to the given amount in thousands of bytes per + minute (default: 15) + --listen= Add an interface/port to listen for connections + (default all interfaces port: 8333, testnet: + 18333, signet: 38333) + --logdir= Directory to log output + --maxorphantx= Max number of orphan transactions to keep in + memory (default: 100) + --maxpeers= Max number of inbound and outbound peers + (default: 125) + --miningaddr= Add the specified payment address to the list of + addresses to use for generated blocks -- At least + one address is required if the generate option is + set + --minrelaytxfee= The minimum transaction fee in BTC/kB to be + considered a non-zero fee. (default: 1e-05) + --nobanning Disable banning of misbehaving peers + --nocfilters Disable committed filtering (CF) support + --nocheckpoints Disable built-in checkpoints. Don't do this + unless you know what you're doing. + --nodnsseed Disable DNS seeding for peers + --nolisten Disable listening for incoming connections -- + NOTE: Listening is automatically disabled if the + --connect or --proxy options are used without + also specifying listen interfaces via --listen + --noonion Disable connecting to tor hidden services + --nopeerbloomfilters Disable bloom filtering support + --norelaypriority Do not require free or low-fee transactions to + have high priority for relaying + --norpc Disable built-in RPC server -- NOTE: The RPC + server is disabled by default if no + rpcuser/rpcpass or rpclimituser/rpclimitpass is + specified + --notls Disable TLS for the RPC server -- NOTE: This is + only allowed if the RPC server is bound to + localhost + --onion= Connect to tor hidden services via SOCKS5 proxy + (eg. 127.0.0.1:9050) + --onionpass= Password for onion proxy server + --onionuser= Username for onion proxy server + --profile= Enable HTTP profiling on given port -- NOTE port + must be between 1024 and 65536 + --proxy= Connect via SOCKS5 proxy (eg. 127.0.0.1:9050) + --proxypass= Password for proxy server + --proxyuser= Username for proxy server + --regtest Use the regression test network + --rejectnonstd Reject non-standard transactions regardless of + the default settings for the active network. + --relaynonstd Relay non-standard transactions regardless of the + default settings for the active network. + --rpccert= File containing the certificate file + --rpckey= File containing the certificate key + --rpclimitpass= Password for limited RPC connections + --rpclimituser= Username for limited RPC connections + --rpclisten= Add an interface/port to listen for RPC + connections (default port: 8334, testnet: 18334) + --rpcmaxclients= Max number of RPC clients for standard + connections (default: 10) + --rpcmaxconcurrentreqs= Max number of concurrent RPC requests that may be + processed concurrently (default: 20) + --rpcmaxwebsockets= Max number of RPC websocket connections (default: + 25) + --rpcquirks Mirror some JSON-RPC quirks of Bitcoin Core -- + NOTE: Discouraged unless interoperability issues + need to be worked around + -P, --rpcpass= Password for RPC connections + -u, --rpcuser= Username for RPC connections + --sigcachemaxsize= The maximum number of entries in the signature + verification cache (default: 100000) + --simnet Use the simulation test network + --testnet Use the test network + --torisolation Enable Tor stream isolation by randomizing user + credentials for each connection. + --trickleinterval= Minimum time between attempts to send new + inventory to a connected peer (default: 10s) + --txindex Maintain a full hash-based transaction index + which makes all transactions available via the + getrawtransaction RPC + --uacomment= Comment to add to the user agent -- See BIP 14 + for more information. + --upnp Use UPnP to map our listening port outside of NAT + -V, --version Display version information and exit + --whitelist= Add an IP network or IP that will not be banned. + (eg. 192.168.1.0/24 or ::1) Help Options: - -h, --help Show this help message + -h, --help Show this help message */ package main diff --git a/integration/bip0009_test.go b/integration/bip0009_test.go index 67b15f3a5b..5b64480410 100644 --- a/integration/bip0009_test.go +++ b/integration/bip0009_test.go @@ -320,19 +320,20 @@ func testBIP0009(t *testing.T, forkKey string, deploymentID uint32) { // - Assert the chain height is 0 and the state is ThresholdDefined // - Generate 1 fewer blocks than needed to reach the first state transition // - Assert chain height is expected and state is still ThresholdDefined +// // - Generate 1 more block to reach the first state transition // - Assert chain height is expected and state moved to ThresholdStarted -// - Generate enough blocks to reach the next state transition window, but only -// signal support in 1 fewer than the required number to achieve -// ThresholdLockedIn +// - Generate enough blocks to reach the next state transition window, but only +// signal support in 1 fewer than the required number to achieve +// ThresholdLockedIn // - Assert chain height is expected and state is still ThresholdStarted -// - Generate enough blocks to reach the next state transition window with only -// the exact number of blocks required to achieve locked in status signalling -// support. +// - Generate enough blocks to reach the next state transition window with only +// the exact number of blocks required to achieve locked in status signalling +// support. // - Assert chain height is expected and state moved to ThresholdLockedIn -// - Generate 1 fewer blocks than needed to reach the next state transition +// - Generate 1 fewer blocks than needed to reach the next state transition // - Assert chain height is expected and state is still ThresholdLockedIn -// - Generate 1 more block to reach the next state transition +// - Generate 1 more block to reach the next state transition // - Assert chain height is expected and state moved to ThresholdActive func TestBIP0009(t *testing.T) { t.Parallel() @@ -348,11 +349,14 @@ func TestBIP0009(t *testing.T) { // Overview: // - Generate block 1 // - Assert bit is NOT set (ThresholdDefined) +// // - Generate enough blocks to reach first state transition // - Assert bit is NOT set for block prior to state transition // - Assert bit is set for block at state transition (ThresholdStarted) +// // - Generate enough blocks to reach second state transition // - Assert bit is set for block at state transition (ThresholdLockedIn) +// // - Generate enough blocks to reach third state transition // - Assert bit is set for block prior to state transition (ThresholdLockedIn) // - Assert bit is NOT set for block at state transition (ThresholdActive) diff --git a/integration/csv_fork_test.go b/integration/csv_fork_test.go index 45ab8ad1aa..6b03af95de 100644 --- a/integration/csv_fork_test.go +++ b/integration/csv_fork_test.go @@ -17,12 +17,12 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/integration/rpctest" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -95,17 +95,18 @@ func makeTestOutput(r *rpctest.Harness, t *testing.T, // them. // // Overview: -// - Pre soft-fork: -// - Transactions with non-final lock-times from the PoV of MTP should be -// rejected from the mempool. -// - Transactions within non-final MTP based lock-times should be accepted -// in valid blocks. // -// - Post soft-fork: -// - Transactions with non-final lock-times from the PoV of MTP should be -// rejected from the mempool and when found within otherwise valid blocks. -// - Transactions with final lock-times from the PoV of MTP should be -// accepted to the mempool and mined in future block. +// - Pre soft-fork: +// 1. Transactions with non-final lock-times from the PoV of MTP should be +// rejected from the mempool. +// 2. Transactions within non-final MTP based lock-times should be accepted +// in valid blocks. +// +// - Post soft-fork: +// 1. Transactions with non-final lock-times from the PoV of MTP should be +// rejected from the mempool and when found within otherwise valid blocks. +// 2. Transactions with final lock-times from the PoV of MTP should be +// accepted to the mempool and mined in future block. func TestBIP0113Activation(t *testing.T) { t.Parallel() @@ -391,13 +392,14 @@ func assertTxInBlock(r *rpctest.Harness, t *testing.T, blockHash *chainhash.Hash // 112 and BIP 68 rule-set after the activation of the CSV-package soft-fork. // // Overview: -// - Pre soft-fork: -// - A transaction spending a CSV output validly should be rejected from the -// mempool, but accepted in a valid generated block including the -// transaction. -// - Post soft-fork: -// - See the cases exercised within the table driven tests towards the end -// of this test. +// - Pre soft-fork: +// 1. A transaction spending a CSV output validly should be rejected from the +// mempool, but accepted in a valid generated block including the +// transaction. +// +// - Post soft-fork: +// 1. See the cases exercised within the table driven tests towards the end +// of this test. func TestBIP0068AndBIP0112Activation(t *testing.T) { t.Parallel() diff --git a/integration/rpctest/blockgen.go b/integration/rpctest/blockgen.go index a35c66e6ac..8a95f1d975 100644 --- a/integration/rpctest/blockgen.go +++ b/integration/rpctest/blockgen.go @@ -12,12 +12,12 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // solveBlock attempts to find a nonce which makes the passed block header hash diff --git a/integration/rpctest/node.go b/integration/rpctest/node.go index be52a15404..f9e0d4c152 100644 --- a/integration/rpctest/node.go +++ b/integration/rpctest/node.go @@ -14,8 +14,8 @@ import ( "runtime" "time" - rpc "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/btcutil" + rpc "github.com/btcsuite/btcd/rpcclient" ) // nodeConfig contains all the args, and data required to launch a btcd process diff --git a/integration/rpctest/rpc_harness_test.go b/integration/rpctest/rpc_harness_test.go index baadd35f5e..978f8d8290 100644 --- a/integration/rpctest/rpc_harness_test.go +++ b/integration/rpctest/rpc_harness_test.go @@ -14,11 +14,11 @@ import ( "testing" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) func testSendOutputs(r *Harness, t *testing.T) { diff --git a/limits/limits_unix.go b/limits/limits_unix.go index 7ebf866789..7972b05e20 100644 --- a/limits/limits_unix.go +++ b/limits/limits_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. +//go:build !windows && !plan9 // +build !windows,!plan9 package limits diff --git a/mempool/doc.go b/mempool/doc.go index 3adad018ba..22fb2a06a0 100644 --- a/mempool/doc.go +++ b/mempool/doc.go @@ -31,40 +31,40 @@ proceed. Typically, this will involve things such as relaying the transactions to other peers on the network and notifying the mining process that new transactions are available. -Feature Overview +# Feature Overview The following is a quick overview of the major features. It is not intended to be an exhaustive list. - - Maintain a pool of fully validated transactions - - Reject non-fully-spent duplicate transactions - - Reject coinbase transactions - - Reject double spends (both from the chain and other transactions in pool) - - Reject invalid transactions according to the network consensus rules - - Full script execution and validation with signature cache support - - Individual transaction query support - - Orphan transaction support (transactions that spend from unknown outputs) - - Configurable limits (see transaction acceptance policy) - - Automatic addition of orphan transactions that are no longer orphans as new - transactions are added to the pool - - Individual orphan transaction query support - - Configurable transaction acceptance policy - - Option to accept or reject standard transactions - - Option to accept or reject transactions based on priority calculations - - Rate limiting of low-fee and free transactions - - Non-zero fee threshold - - Max signature operations per transaction - - Max orphan transaction size - - Max number of orphan transactions allowed - - Additional metadata tracking for each transaction - - Timestamp when the transaction was added to the pool - - Most recent block height when the transaction was added to the pool - - The fee the transaction pays - - The starting priority for the transaction - - Manual control of transaction removal - - Recursive removal of all dependent transactions + - Maintain a pool of fully validated transactions + 1. Reject non-fully-spent duplicate transactions + 2. Reject coinbase transactions + 3. Reject double spends (both from the chain and other transactions in pool) + 4. Reject invalid transactions according to the network consensus rules + 5. Full script execution and validation with signature cache support + 6. Individual transaction query support + - Orphan transaction support (transactions that spend from unknown outputs) + 1. Configurable limits (see transaction acceptance policy) + 2. Automatic addition of orphan transactions that are no longer orphans as new + transactions are added to the pool + 3. Individual orphan transaction query support + - Configurable transaction acceptance policy + 1. Option to accept or reject standard transactions + 2. Option to accept or reject transactions based on priority calculations + 3. Rate limiting of low-fee and free transactions + 4. Non-zero fee threshold + 5. Max signature operations per transaction + 6. Max orphan transaction size + 7. Max number of orphan transactions allowed + - Additional metadata tracking for each transaction + 1. Timestamp when the transaction was added to the pool + 2. Most recent block height when the transaction was added to the pool + 3. The fee the transaction pays + 4. The starting priority for the transaction + - Manual control of transaction removal + 1. Recursive removal of all dependent transactions -Errors +# Errors Errors returned by this package are either the raw errors provided by underlying calls or of type mempool.RuleError. Since there are two classes of rules diff --git a/mempool/estimatefee.go b/mempool/estimatefee.go index a71ce42f12..2d1794b797 100644 --- a/mempool/estimatefee.go +++ b/mempool/estimatefee.go @@ -16,9 +16,9 @@ import ( "strings" "sync" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" - "github.com/btcsuite/btcd/btcutil" ) // TODO incorporate Alex Morcos' modifications to Gavin's initial model diff --git a/mempool/estimatefee_test.go b/mempool/estimatefee_test.go index c5ea85c635..c1e0906096 100644 --- a/mempool/estimatefee_test.go +++ b/mempool/estimatefee_test.go @@ -9,10 +9,10 @@ import ( "math/rand" "testing" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // newTestFeeEstimator creates a feeEstimator with some different parameters diff --git a/mining/cpuminer/cpuminer.go b/mining/cpuminer/cpuminer.go index 038e6645bb..2c07f2ee1f 100644 --- a/mining/cpuminer/cpuminer.go +++ b/mining/cpuminer/cpuminer.go @@ -13,11 +13,11 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/mining/mining.go b/mining/mining.go index 4ed61f3f32..8ac388c263 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -11,11 +11,11 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -420,26 +420,26 @@ func NewBlkTmplGenerator(policy *Policy, params *chaincfg.Params, // // Given the above, a block generated by this function is of the following form: // -// ----------------------------------- -- -- -// | Coinbase Transaction | | | -// |-----------------------------------| | | -// | | | | ----- policy.BlockPrioritySize -// | High-priority Transactions | | | -// | | | | -// |-----------------------------------| | -- -// | | | -// | | | -// | | |--- policy.BlockMaxSize -// | Transactions prioritized by fee | | -// | until <= policy.TxMinFreeFee | | -// | | | -// | | | -// | | | -// |-----------------------------------| | -// | Low-fee/Non high-priority (free) | | -// | transactions (while block size | | -// | <= policy.BlockMinSize) | | -// ----------------------------------- -- +// ----------------------------------- -- -- +// | Coinbase Transaction | | | +// |-----------------------------------| | | +// | | | | ----- policy.BlockPrioritySize +// | High-priority Transactions | | | +// | | | | +// |-----------------------------------| | -- +// | | | +// | | | +// | | |--- policy.BlockMaxSize +// | Transactions prioritized by fee | | +// | until <= policy.TxMinFreeFee | | +// | | | +// | | | +// | | | +// |-----------------------------------| | +// | Low-fee/Non high-priority (free) | | +// | transactions (while block size | | +// | <= policy.BlockMinSize) | | +// ----------------------------------- -- func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*BlockTemplate, error) { // Extend the most recently known best block. best := g.chain.BestSnapshot() diff --git a/mining/policy.go b/mining/policy.go index f8ce411602..6213c2b336 100644 --- a/mining/policy.go +++ b/mining/policy.go @@ -6,8 +6,8 @@ package mining import ( "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/wire" ) const ( diff --git a/mining/policy_test.go b/mining/policy_test.go index 0a362f5471..cc2fdfbfb2 100644 --- a/mining/policy_test.go +++ b/mining/policy_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // newHashFromStr converts the passed big-endian hex string into a diff --git a/netsync/blocklogger.go b/netsync/blocklogger.go index 788192ccb2..10f83d57b7 100644 --- a/netsync/blocklogger.go +++ b/netsync/blocklogger.go @@ -8,8 +8,8 @@ import ( "sync" "time" - "github.com/btcsuite/btclog" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btclog" ) // blockProgressLogger provides periodic logging for other services in order @@ -27,8 +27,9 @@ type blockProgressLogger struct { // newBlockProgressLogger returns a new block progress logger. // The progress message is templated as follows: -// {progressAction} {numProcessed} {blocks|block} in the last {timePeriod} -// ({numTxs}, height {lastBlockHeight}, {lastBlockTimeStamp}) +// +// {progressAction} {numProcessed} {blocks|block} in the last {timePeriod} +// ({numTxs}, height {lastBlockHeight}, {lastBlockTimeStamp}) func newBlockProgressLogger(progressMessage string, logger btclog.Logger) *blockProgressLogger { return &blockProgressLogger{ lastBlockLogTime: time.Now(), diff --git a/netsync/interface.go b/netsync/interface.go index 2ce479bf2d..6a873bd888 100644 --- a/netsync/interface.go +++ b/netsync/interface.go @@ -6,12 +6,12 @@ package netsync import ( "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // PeerNotifier exposes methods to notify peers of status changes to diff --git a/netsync/manager.go b/netsync/manager.go index a297bb3f24..523437a0c5 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -13,13 +13,13 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/mempool" peerpkg "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/peer/doc.go b/peer/doc.go index 88fae8e850..d2c66ff3cd 100644 --- a/peer/doc.go +++ b/peer/doc.go @@ -6,7 +6,7 @@ Package peer provides a common base for creating and managing Bitcoin network peers. -Overview +# Overview This package builds upon the wire package, which provides the fundamental primitives necessary to speak the bitcoin wire protocol, in order to simplify @@ -16,41 +16,41 @@ Payment Verification (SPV) nodes, proxies, etc. A quick overview of the major features peer provides are as follows: - - Provides a basic concurrent safe bitcoin peer for handling bitcoin - communications via the peer-to-peer protocol - - Full duplex reading and writing of bitcoin protocol messages - - Automatic handling of the initial handshake process including protocol - version negotiation - - Asynchronous message queuing of outbound messages with optional channel for - notification when the message is actually sent - - Flexible peer configuration - - Caller is responsible for creating outgoing connections and listening for - incoming connections so they have flexibility to establish connections as - they see fit (proxies, etc) - - User agent name and version - - Bitcoin network - - Service support signalling (full nodes, bloom filters, etc) - - Maximum supported protocol version - - Ability to register callbacks for handling bitcoin protocol messages - - Inventory message batching and send trickling with known inventory detection - and avoidance - - Automatic periodic keep-alive pinging and pong responses - - Random nonce generation and self connection detection - - Proper handling of bloom filter related commands when the caller does not - specify the related flag to signal support - - Disconnects the peer when the protocol version is high enough - - Does not invoke the related callbacks for older protocol versions - - Snapshottable peer statistics such as the total number of bytes read and - written, the remote address, user agent, and negotiated protocol version - - Helper functions pushing addresses, getblocks, getheaders, and reject - messages - - These could all be sent manually via the standard message output function, - but the helpers provide additional nice functionality such as duplicate - filtering and address randomization - - Ability to wait for shutdown/disconnect - - Comprehensive test coverage - -Peer Configuration + - Provides a basic concurrent safe bitcoin peer for handling bitcoin + communications via the peer-to-peer protocol + - Full duplex reading and writing of bitcoin protocol messages + - Automatic handling of the initial handshake process including protocol + version negotiation + - Asynchronous message queuing of outbound messages with optional channel for + notification when the message is actually sent + - Flexible peer configuration + 1. Caller is responsible for creating outgoing connections and listening for + incoming connections so they have flexibility to establish connections as + they see fit (proxies, etc) + 2. User agent name and version + 3. Bitcoin network + 4. Service support signalling (full nodes, bloom filters, etc) + 5. Maximum supported protocol version + 6. Ability to register callbacks for handling bitcoin protocol messages + - Inventory message batching and send trickling with known inventory detection + and avoidance + - Automatic periodic keep-alive pinging and pong responses + - Random nonce generation and self connection detection + - Proper handling of bloom filter related commands when the caller does not + specify the related flag to signal support + 1. Disconnects the peer when the protocol version is high enough + 2. Does not invoke the related callbacks for older protocol versions + - Snapshottable peer statistics such as the total number of bytes read and + written, the remote address, user agent, and negotiated protocol version + - Helper functions pushing addresses, getblocks, getheaders, and reject + messages + 1. These could all be sent manually via the standard message output function, + but the helpers provide additional nice functionality such as duplicate + filtering and address randomization + - Ability to wait for shutdown/disconnect + - Comprehensive test coverage + +# Peer Configuration All peer configuration is handled with the Config struct. This allows the caller to specify things such as the user agent name and version, the bitcoin @@ -58,7 +58,7 @@ network to use, which services it supports, and callbacks to invoke when bitcoin messages are received. See the documentation for each field of the Config struct for more details. -Inbound and Outbound Peers +# Inbound and Outbound Peers A peer can either be inbound or outbound. The caller is responsible for establishing the connection to remote peers and listening for incoming peers. @@ -73,7 +73,7 @@ Disconnect to disconnect from the peer and clean up all resources. WaitForDisconnect can be used to block until peer disconnection and resource cleanup has completed. -Callbacks +# Callbacks In order to do anything useful with a peer, it is necessary to react to bitcoin messages. This is accomplished by creating an instance of the MessageListeners @@ -92,7 +92,7 @@ It is often useful to use closures which encapsulate state when specifying the callback handlers. This provides a clean method for accessing that state when callbacks are invoked. -Queuing Messages and Inventory +# Queuing Messages and Inventory The QueueMessage function provides the fundamental means to send messages to the remote peer. As the name implies, this employs a non-blocking queue. A done @@ -106,7 +106,7 @@ QueueInventory function. It employs batching and trickling along with intelligent known remote peer inventory detection and avoidance through the use of a most-recently used algorithm. -Message Sending Helper Functions +# Message Sending Helper Functions In addition to the bare QueueMessage function previously described, the PushAddrMsg, PushGetBlocksMsg, PushGetHeadersMsg, and PushRejectMsg functions @@ -128,13 +128,13 @@ appropriate reject message based on the provided parameters as well as optionally provides a flag to cause it to block until the message is actually sent. -Peer Statistics +# Peer Statistics A snapshot of the current peer statistics can be obtained with the StatsSnapshot function. This includes statistics such as the total number of bytes read and written, the remote address, user agent, and negotiated protocol version. -Logging +# Logging This package provides extensive logging capabilities through the UseLogger function which allows a btclog.Logger to be specified. For example, logging at @@ -142,7 +142,7 @@ the debug level provides summaries of every message sent and received, and logging at the trace level provides full dumps of parsed messages as well as the raw message bytes using a format similar to hexdump -C. -Bitcoin Improvement Proposals +# Bitcoin Improvement Proposals This package supports all BIPS supported by the wire package. (https://pkg.go.dev/github.com/btcsuite/btcd/wire#hdr-Bitcoin_Improvement_Proposals) diff --git a/peer/peer.go b/peer/peer.go index 6d34c5f822..aa66cea98f 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -2206,14 +2206,14 @@ func (p *Peer) waitToFinishNegotiation(pver uint32) error { // peer. The events should occur in the following order, otherwise an error is // returned: // -// 1. Remote peer sends their version. -// 2. We send our version. -// 3. We send sendaddrv2 if their version is >= 70016. -// 4. We send our verack. -// 5. Wait until sendaddrv2 or verack is received. Unknown messages are -// skipped as it could be wtxidrelay or a different message in the future -// that btcd does not implement but bitcoind does. -// 6. If remote peer sent sendaddrv2 above, wait until receipt of verack. +// 1. Remote peer sends their version. +// 2. We send our version. +// 3. We send sendaddrv2 if their version is >= 70016. +// 4. We send our verack. +// 5. Wait until sendaddrv2 or verack is received. Unknown messages are +// skipped as it could be wtxidrelay or a different message in the future +// that btcd does not implement but bitcoind does. +// 6. If remote peer sent sendaddrv2 above, wait until receipt of verack. func (p *Peer) negotiateInboundProtocol() error { if err := p.readRemoteVersionMsg(); err != nil { return err @@ -2245,13 +2245,13 @@ func (p *Peer) negotiateInboundProtocol() error { // peer. The events should occur in the following order, otherwise an error is // returned: // -// 1. We send our version. -// 2. Remote peer sends their version. -// 3. We send sendaddrv2 if their version is >= 70016. -// 4. We send our verack. -// 5. We wait to receive sendaddrv2 or verack, skipping unknown messages as -// in the inbound case. -// 6. If sendaddrv2 was received, wait for receipt of verack. +// 1. We send our version. +// 2. Remote peer sends their version. +// 3. We send sendaddrv2 if their version is >= 70016. +// 4. We send our verack. +// 5. We wait to receive sendaddrv2 or verack, skipping unknown messages as +// in the inbound case. +// 6. If sendaddrv2 was received, wait for receipt of verack. func (p *Peer) negotiateOutboundProtocol() error { if err := p.writeLocalVersionMsg(); err != nil { return err diff --git a/rpcadapters.go b/rpcadapters.go index 487574a81c..5a6800c532 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -8,12 +8,12 @@ import ( "sync/atomic" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/netsync" "github.com/btcsuite/btcd/peer" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // rpcPeer provides a peer for use with the RPC server and implements the diff --git a/rpcclient/doc.go b/rpcclient/doc.go index b682ba10f2..8057dd240c 100644 --- a/rpcclient/doc.go +++ b/rpcclient/doc.go @@ -5,7 +5,7 @@ /* Package rpcclient implements a websocket-enabled Bitcoin JSON-RPC client. -Overview +# Overview This client provides a robust and easy to use client for interfacing with a Bitcoin RPC server that uses a btcd/bitcoin core compatible Bitcoin JSON-RPC @@ -24,7 +24,7 @@ btcd or btcwallet by default. However, configuration options are provided to fall back to HTTP POST and disable TLS to support talking with inferior bitcoin core style RPC servers. -Websockets vs HTTP POST +# Websockets vs HTTP POST In HTTP POST-based JSON-RPC, every request creates a new HTTP connection, issues the call, waits for the response, and closes the connection. This adds @@ -40,7 +40,7 @@ can be invoked without having to go through a connect/disconnect cycle for every call. In addition, the websocket interface provides other nice features such as the ability to register for asynchronous notifications of various events. -Synchronous vs Asynchronous API +# Synchronous vs Asynchronous API The client provides both a synchronous (blocking) and asynchronous API. @@ -57,7 +57,7 @@ the Receive method on the returned instance will either return the result immediately if it has already arrived, or block until it has. This is useful since it provides the caller with greater control over concurrency. -Notifications +# Notifications The first important part of notifications is to realize that they will only work when connected via websockets. This should intuitively make sense @@ -67,7 +67,7 @@ All notifications provided by btcd require registration to opt-in. For example, if you want to be notified when funds are received by a set of addresses, you register the addresses via the NotifyReceived (or NotifyReceivedAsync) function. -Notification Handlers +# Notification Handlers Notifications are exposed by the client through the use of callback handlers which are setup via a NotificationHandlers instance that is specified by the @@ -83,7 +83,7 @@ will cause a deadlock as more server responses won't be read until the callback returns, but the callback would be waiting for a response. Thus, any additional RPCs must be issued an a completely decoupled manner. -Automatic Reconnection +# Automatic Reconnection By default, when running in websockets mode, this client will automatically keep trying to reconnect to the RPC server should the connection be lost. There @@ -116,7 +116,7 @@ chain services will be available. Depending on your application, you might only need chain-related RPCs. In contrast, btcwallet provides pass through treatment for chain-related RPCs, so it supports them in addition to wallet-related RPCs. -Errors +# Errors There are 3 categories of errors that will be returned throughout this package: @@ -144,35 +144,35 @@ The third category of errors, that is errors returned by the server, can be detected by type asserting the error in a *btcjson.RPCError. For example, to detect if a command is unimplemented by the remote RPC server: - amount, err := client.GetBalance("") - if err != nil { - if jerr, ok := err.(*btcjson.RPCError); ok { - switch jerr.Code { - case btcjson.ErrRPCUnimplemented: - // Handle not implemented error + amount, err := client.GetBalance("") + if err != nil { + if jerr, ok := err.(*btcjson.RPCError); ok { + switch jerr.Code { + case btcjson.ErrRPCUnimplemented: + // Handle not implemented error - // Handle other specific errors you care about - } - } + // Handle other specific errors you care about + } + } - // Log or otherwise handle the error knowing it was not one returned - // from the remote RPC server. - } + // Log or otherwise handle the error knowing it was not one returned + // from the remote RPC server. + } -Example Usage +# Example Usage The following full-blown client examples are in the examples directory: - - bitcoincorehttp - Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled - and gets the current block count - - btcdwebsockets - Connects to a btcd RPC server using TLS-secured websockets, registers for - block connected and block disconnected notifications, and gets the current - block count - - btcwalletwebsockets - Connects to a btcwallet RPC server using TLS-secured websockets, registers - for notifications about changes to account balances, and gets a list of - unspent transaction outputs (utxos) the wallet can sign + - bitcoincorehttp + Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled + and gets the current block count + - btcdwebsockets + Connects to a btcd RPC server using TLS-secured websockets, registers for + block connected and block disconnected notifications, and gets the current + block count + - btcwalletwebsockets + Connects to a btcwallet RPC server using TLS-secured websockets, registers + for notifications about changes to account balances, and gets a list of + unspent transaction outputs (utxos) the wallet can sign */ package rpcclient diff --git a/rpcclient/examples/btcdwebsockets/main.go b/rpcclient/examples/btcdwebsockets/main.go index 1f18b9aab4..e3f4c13e40 100644 --- a/rpcclient/examples/btcdwebsockets/main.go +++ b/rpcclient/examples/btcdwebsockets/main.go @@ -10,9 +10,9 @@ import ( "path/filepath" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) func main() { diff --git a/rpcclient/examples/btcwalletwebsockets/main.go b/rpcclient/examples/btcwalletwebsockets/main.go index 7f177e0b1f..3cbd9a3667 100644 --- a/rpcclient/examples/btcwalletwebsockets/main.go +++ b/rpcclient/examples/btcwalletwebsockets/main.go @@ -10,8 +10,8 @@ import ( "path/filepath" "time" - "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/rpcclient" "github.com/davecgh/go-spew/spew" ) diff --git a/rpcclient/extensions.go b/rpcclient/extensions.go index efb6c1c710..b7517cf26e 100644 --- a/rpcclient/extensions.go +++ b/rpcclient/extensions.go @@ -13,9 +13,9 @@ import ( "fmt" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // FutureDebugLevelResult is a future promise to deliver the result of a @@ -56,7 +56,8 @@ func (c *Client) DebugLevelAsync(levelSpec string) FutureDebugLevelResult { // specification. // // The levelspec can be either a debug level or of the form: -// =,=,... +// +// =,=,... // // Additionally, the special keyword 'show' can be used to get a list of the // available subsystems. diff --git a/rpcclient/mining.go b/rpcclient/mining.go index 680a63b6d5..9de2f27ed6 100644 --- a/rpcclient/mining.go +++ b/rpcclient/mining.go @@ -10,8 +10,8 @@ import ( "errors" "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) // FutureGenerateResult is a future promise to deliver the result of a diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 225af281cf..1c2814c313 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -14,9 +14,9 @@ import ( "time" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) var ( diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 3643f2b0ca..1df6195220 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -10,9 +10,9 @@ import ( "encoding/json" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 64f1e40afa..b590a7963f 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -1016,10 +1016,10 @@ func (c *Client) CreateWalletAsync(name string, opts ...CreateWalletOpt) FutureC // // Optional parameters can be specified using functional-options pattern. The // following functions are available: -// * WithCreateWalletDisablePrivateKeys -// * WithCreateWalletBlank -// * WithCreateWalletPassphrase -// * WithCreateWalletAvoidReuse +// - WithCreateWalletDisablePrivateKeys +// - WithCreateWalletBlank +// - WithCreateWalletPassphrase +// - WithCreateWalletAvoidReuse func (c *Client) CreateWallet(name string, opts ...CreateWalletOpt) (*btcjson.CreateWalletResult, error) { return c.CreateWalletAsync(name, opts...).Receive() } diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 4d140b4825..aedbcf90b6 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -22,12 +22,12 @@ import ( "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/websocket" "golang.org/x/crypto/ripemd160" ) diff --git a/signalsigterm.go b/signalsigterm.go index 831655010e..63bdb9c01d 100644 --- a/signalsigterm.go +++ b/signalsigterm.go @@ -2,6 +2,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris // +build darwin dragonfly freebsd linux netbsd openbsd solaris package main diff --git a/txscript/doc.go b/txscript/doc.go index 7da521615a..179cb227b3 100644 --- a/txscript/doc.go +++ b/txscript/doc.go @@ -12,7 +12,7 @@ overview to provide information on how to use the package. This package provides data structures and functions to parse and execute bitcoin transaction scripts. -Script Overview +# Script Overview Bitcoin transaction scripts are written in a stack-base, FORTH-like language. @@ -30,7 +30,7 @@ is used to prove the the spender is authorized to perform the transaction. One benefit of using a scripting language is added flexibility in specifying what conditions must be met in order to spend bitcoins. -Errors +# Errors Errors returned by this package are of type txscript.Error. This allows the caller to programmatically determine the specific error by examining the diff --git a/txscript/error.go b/txscript/error.go index 072778a268..1f046b9612 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -506,10 +506,10 @@ func (e ErrorCode) String() string { // Error identifies a script-related error. It is used to indicate three // classes of errors: -// 1) Script execution failures due to violating one of the many requirements -// imposed by the script engine or evaluating to false -// 2) Improper API usage by callers -// 3) Internal consistency check failures +// 1. Script execution failures due to violating one of the many requirements +// imposed by the script engine or evaluating to false +// 2. Improper API usage by callers +// 3. Internal consistency check failures // // The caller can use type assertions on the returned errors to access the // ErrorCode field to ascertain the specific reason for the error. As an diff --git a/txscript/opcode.go b/txscript/opcode.go index 943ac506a2..4918b991c5 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1171,7 +1171,7 @@ func opcodeCheckSequenceVerify(op *opcode, data []byte, vm *Engine) error { // Transaction version numbers not high enough to trigger CSV rules must // fail. - if vm.tx.Version < 2 { + if uint32(vm.tx.Version) < 2 { str := fmt.Sprintf("invalid transaction version: %d", vm.tx.Version) return scriptError(ErrUnsatisfiedLockTime, str) diff --git a/txscript/scriptnum.go b/txscript/scriptnum.go index b951fd8537..0b8b50d8b2 100644 --- a/txscript/scriptnum.go +++ b/txscript/scriptnum.go @@ -89,18 +89,19 @@ func checkMinimalDataEncoding(v []byte) error { // Bytes returns the number serialized as a little endian with a sign bit. // // Example encodings: -// 127 -> [0x7f] -// -127 -> [0xff] -// 128 -> [0x80 0x00] -// -128 -> [0x80 0x80] -// 129 -> [0x81 0x00] -// -129 -> [0x81 0x80] -// 256 -> [0x00 0x01] -// -256 -> [0x00 0x81] -// 32767 -> [0xff 0x7f] -// -32767 -> [0xff 0xff] -// 32768 -> [0x00 0x80 0x00] -// -32768 -> [0x00 0x80 0x80] +// +// 127 -> [0x7f] +// -127 -> [0xff] +// 128 -> [0x80 0x00] +// -128 -> [0x80 0x80] +// 129 -> [0x81 0x00] +// -129 -> [0x81 0x80] +// 256 -> [0x00 0x01] +// -256 -> [0x00 0x81] +// 32767 -> [0xff 0x7f] +// -32767 -> [0xff 0xff] +// 32768 -> [0x00 0x80 0x00] +// -32768 -> [0x00 0x80 0x80] func (n scriptNum) Bytes() []byte { // Zero encodes as an empty byte slice. if n == 0 { diff --git a/wire/doc.go b/wire/doc.go index b8b8c56fff..5e03ff20a1 100644 --- a/wire/doc.go +++ b/wire/doc.go @@ -14,7 +14,7 @@ supported bitcoin messages to and from the wire. This package does not deal with the specifics of message handling such as what to do when a message is received. This provides the caller with a high level of flexibility. -Bitcoin Message Overview +# Bitcoin Message Overview The bitcoin protocol consists of exchanging messages between peers. Each message is preceded by a header which identifies information about it such as @@ -30,7 +30,7 @@ messages, all of the details of marshalling and unmarshalling to and from the wire using bitcoin encoding are handled so the caller doesn't have to concern themselves with the specifics. -Message Interaction +# Message Interaction The following provides a quick summary of how the bitcoin messages are intended to interact with one another. As stated above, these interactions are not @@ -62,13 +62,13 @@ interactions in no particular order. in BIP0031. The BIP0031Version constant can be used to detect a recent enough protocol version for this purpose (version > BIP0031Version). -Common Parameters +# Common Parameters There are several common parameters that arise when using this package to read and write bitcoin messages. The following sections provide a quick overview of these parameters so the next sections can build on them. -Protocol Version +# Protocol Version The protocol version should be negotiated with the remote peer at a higher level than this package via the version (MsgVersion) message exchange, however, @@ -77,7 +77,7 @@ latest protocol version this package supports and is typically the value to use for all outbound connections before a potentially lower protocol version is negotiated. -Bitcoin Network +# Bitcoin Network The bitcoin network is a magic number which is used to identify the start of a message and which bitcoin network the message applies to. This package provides @@ -88,7 +88,7 @@ the following constants: wire.TestNet3 (Test network version 3) wire.SimNet (Simulation test network) -Determining Message Type +# Determining Message Type As discussed in the bitcoin message overview section, this package reads and writes bitcoin messages using a generic interface named Message. In @@ -106,7 +106,7 @@ switch or type assertion. An example of a type switch follows: fmt.Printf("Number of tx in block: %v", msg.Header.TxnCount) } -Reading Messages +# Reading Messages In order to unmarshall bitcoin messages from the wire, use the ReadMessage function. It accepts any io.Reader, but typically this will be a net.Conn to @@ -121,7 +121,7 @@ a remote node running a bitcoin peer. Example syntax is: // Log and handle the error } -Writing Messages +# Writing Messages In order to marshall bitcoin messages to the wire, use the WriteMessage function. It accepts any io.Writer, but typically this will be a net.Conn to @@ -139,7 +139,7 @@ from a remote peer is: // Log and handle the error } -Errors +# Errors Errors returned by this package are either the raw errors provided by underlying calls to read/write from streams such as io.EOF, io.ErrUnexpectedEOF, and @@ -147,7 +147,7 @@ io.ErrShortWrite, or of type wire.MessageError. This allows the caller to differentiate between general IO errors and malformed messages through type assertions. -Bitcoin Improvement Proposals +# Bitcoin Improvement Proposals This package includes spec changes outlined by the following BIPs: From 599d3619e8ed5fce9fd2f3478e402496e23a456d Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 23 May 2023 15:33:55 +0200 Subject: [PATCH 0773/1056] blockchain+chaincfg: disable retargeting for regtest This commit emulates the behavior of Bitcoin Core introduced in https://github.com/bitcoin/bitcoin/pull/6853 that disables retargeting of the required proof of work for regtest. --- blockchain/difficulty.go | 10 +++++++++- chaincfg/params.go | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/blockchain/difficulty.go b/blockchain/difficulty.go index 0eb66f3241..1fdc8999a1 100644 --- a/blockchain/difficulty.go +++ b/blockchain/difficulty.go @@ -219,7 +219,15 @@ func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) uint32 { // This function differs from the exported CalcNextRequiredDifficulty in that // the exported version uses the current best chain as the previous block node // while this function accepts any block node. -func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, newBlockTime time.Time) (uint32, error) { +func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, + newBlockTime time.Time) (uint32, error) { + + // Emulate the same behavior as Bitcoin Core that for regtest there is + // no difficulty retargeting. + if b.chainParams.PoWNoRetargeting { + return b.chainParams.PowLimitBits, nil + } + // Genesis block. if lastNode == nil { return b.chainParams.PowLimitBits, nil diff --git a/chaincfg/params.go b/chaincfg/params.go index 38034ac204..f11bcf2640 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -183,6 +183,11 @@ type Params struct { // block in compact form. PowLimitBits uint32 + // PoWNoRetargeting defines whether the network has difficulty + // retargeting enabled or not. This should only be set to true for + // regtest like networks. + PoWNoRetargeting bool + // These fields define the block heights at which the specified softfork // BIP became active. BIP0034Height int32 @@ -432,6 +437,7 @@ var RegressionNetParams = Params{ GenesisHash: ®TestGenesisHash, PowLimit: regressionPowLimit, PowLimitBits: 0x207fffff, + PoWNoRetargeting: true, CoinbaseMaturity: 100, BIP0034Height: 100000000, // Not active - Permit ver 1 blocks BIP0065Height: 1351, // Used by regression tests From e160bb6922ad94bbd40a470ab85fae2e5a3fe7c5 Mon Sep 17 00:00:00 2001 From: cui fliter Date: Mon, 26 Jun 2023 11:14:15 +0800 Subject: [PATCH 0774/1056] multi: remove repetitive the Signed-off-by: cui fliter --- addrmgr/network.go | 2 +- blockchain/chainio.go | 4 ++-- blockchain/fullblocktests/generate.go | 2 +- btcec/privkey.go | 2 +- btcec/pubkey.go | 2 +- btcjson/cmdparse.go | 2 +- btcjson/doc.go | 2 +- btcutil/bloom/merkleblock.go | 2 +- cmd/btcctl/version.go | 2 +- config.go | 2 +- database/driver.go | 4 ++-- database/ffldb/blockio.go | 2 +- database/ffldb/db.go | 2 +- database/ffldb/interface_test.go | 2 +- database/internal/treap/immutable_test.go | 2 +- mining/mining.go | 2 +- rpcclient/wallet.go | 2 +- txscript/doc.go | 2 +- txscript/scriptnum.go | 2 +- wire/msgtx.go | 2 +- 20 files changed, 22 insertions(+), 22 deletions(-) diff --git a/addrmgr/network.go b/addrmgr/network.go index 7f30901b21..95555a69c5 100644 --- a/addrmgr/network.go +++ b/addrmgr/network.go @@ -20,7 +20,7 @@ var ( ipNet("192.168.0.0", 16, 32), } - // rfc2544Net specifies the the IPv4 block as defined by RFC2544 + // rfc2544Net specifies the IPv4 block as defined by RFC2544 // (198.18.0.0/15) rfc2544Net = ipNet("198.18.0.0", 15, 32) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index e7a7c30c76..c29201c5f8 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -243,10 +243,10 @@ type SpentTxOut struct { // Amount is the amount of the output. Amount int64 - // PkScipt is the the public key script for the output. + // PkScipt is the public key script for the output. PkScript []byte - // Height is the height of the the block containing the creating tx. + // Height is the height of the block containing the creating tx. Height int32 // Denotes if the creating tx is a coinbase. diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index c491242ecd..58a53c526e 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -423,7 +423,7 @@ func replaceCoinbaseSigScript(script []byte) func(*wire.MsgBlock) { } // additionalTx returns a function that itself takes a block and modifies it by -// adding the the provided transaction. +// adding the provided transaction. func additionalTx(tx *wire.MsgTx) func(*wire.MsgBlock) { return func(b *wire.MsgBlock) { b.AddTransaction(tx) diff --git a/btcec/privkey.go b/btcec/privkey.go index 4efa806c5f..d0dbd8d9f9 100644 --- a/btcec/privkey.go +++ b/btcec/privkey.go @@ -9,7 +9,7 @@ import ( ) // PrivateKey wraps an ecdsa.PrivateKey as a convenience mainly for signing -// things with the the private key without having to directly import the ecdsa +// things with the private key without having to directly import the ecdsa // package. type PrivateKey = secp.PrivateKey diff --git a/btcec/pubkey.go b/btcec/pubkey.go index 7968ed042a..c4b0680a7a 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -19,7 +19,7 @@ const ( pubkeyHybrid byte = 0x6 // y_bit + x coord + y coord ) -// IsCompressedPubKey returns true the the passed serialized public key has +// IsCompressedPubKey returns true the passed serialized public key has // been encoded in compressed format, and false otherwise. func IsCompressedPubKey(pubKey []byte) bool { // The public key is only compressed if it is the correct length and diff --git a/btcjson/cmdparse.go b/btcjson/cmdparse.go index 4fb8dd6260..5cf3215e52 100644 --- a/btcjson/cmdparse.go +++ b/btcjson/cmdparse.go @@ -495,7 +495,7 @@ func assignField(paramNum int, fieldName string, dest reflect.Value, src reflect // by this package are already registered by default. // // The arguments are most efficient when they are the exact same type as the -// underlying field in the command struct associated with the the method, +// underlying field in the command struct associated with the method, // however this function also will perform a variety of conversions to make it // more flexible. This allows, for example, command line args which are strings // to be passed unaltered. In particular, the following conversions are diff --git a/btcjson/doc.go b/btcjson/doc.go index d31b6c0a6b..f0456716b9 100644 --- a/btcjson/doc.go +++ b/btcjson/doc.go @@ -8,7 +8,7 @@ Package btcjson provides primitives for working with the bitcoin JSON-RPC API. # Overview When communicating via the JSON-RPC protocol, all of the commands need to be -marshalled to and from the the wire in the appropriate format. This package +marshalled to and from the wire in the appropriate format. This package provides data structures and primitives to ease this process. In addition, it also provides some additional features such as custom command diff --git a/btcutil/bloom/merkleblock.go b/btcutil/bloom/merkleblock.go index 5e18682d2a..68ee477d3e 100644 --- a/btcutil/bloom/merkleblock.go +++ b/btcutil/bloom/merkleblock.go @@ -21,7 +21,7 @@ type merkleBlock struct { bits []byte } -// calcTreeWidth calculates and returns the the number of nodes (width) or a +// calcTreeWidth calculates and returns the number of nodes (width) or a // merkle tree at the given depth-first height. func (m *merkleBlock) calcTreeWidth(height uint32) uint32 { return (m.numTx + (1 << height) - 1) >> height diff --git a/cmd/btcctl/version.go b/cmd/btcctl/version.go index 42f3f7d024..8da196bea8 100644 --- a/cmd/btcctl/version.go +++ b/cmd/btcctl/version.go @@ -66,7 +66,7 @@ func normalizeVerString(str string) string { for _, r := range str { if strings.ContainsRune(semanticAlphabet, r) { // Ignoring the error here since it can only fail if - // the the system is out of memory and there are much + // the system is out of memory and there are much // bigger issues at that point. _, _ = result.WriteRune(r) } diff --git a/config.go b/config.go index 881123f5e9..2d8c67e62d 100644 --- a/config.go +++ b/config.go @@ -813,7 +813,7 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } - // Validate the the minrelaytxfee. + // Validate the minrelaytxfee. cfg.minRelayTxFee, err = btcutil.NewAmount(cfg.MinRelayTxFee) if err != nil { str := "%s: invalid minrelaytxfee: %v" diff --git a/database/driver.go b/database/driver.go index 2999b61157..cb76d2fc62 100644 --- a/database/driver.go +++ b/database/driver.go @@ -62,7 +62,7 @@ func SupportedDrivers() []string { // arguments are specific to the database type driver. See the documentation // for the database driver for further details. // -// ErrDbUnknownType will be returned if the the database type is not registered. +// ErrDbUnknownType will be returned if the database type is not registered. func Create(dbType string, args ...interface{}) (DB, error) { drv, exists := drivers[dbType] if !exists { @@ -77,7 +77,7 @@ func Create(dbType string, args ...interface{}) (DB, error) { // specific to the database type driver. See the documentation for the database // driver for further details. // -// ErrDbUnknownType will be returned if the the database type is not registered. +// ErrDbUnknownType will be returned if the database type is not registered. func Open(dbType string, args ...interface{}) (DB, error) { drv, exists := drivers[dbType] if !exists { diff --git a/database/ffldb/blockio.go b/database/ffldb/blockio.go index 50e853f6dc..94d2665e03 100644 --- a/database/ffldb/blockio.go +++ b/database/ffldb/blockio.go @@ -133,7 +133,7 @@ type blockStore struct { // openBlocksLRU tracks how the open files are refenced by pushing the // most recently used files to the front of the list thereby trickling // the least recently used files to end of the list. When a file needs - // to be closed due to exceeding the the max number of allowed open + // to be closed due to exceeding the max number of allowed open // files, the one at the end of the list is closed. // // fileNumToLRUElem is a mapping between a specific block file number diff --git a/database/ffldb/db.go b/database/ffldb/db.go index c0e2bb3a6a..b796c3ae92 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -1015,7 +1015,7 @@ func (tx *transaction) notifyActiveIters() { tx.activeIterLock.RUnlock() } -// checkClosed returns an error if the the database or transaction is closed. +// checkClosed returns an error if the database or transaction is closed. func (tx *transaction) checkClosed() error { // The transaction is no longer valid if it has been closed. if tx.closed { diff --git a/database/ffldb/interface_test.go b/database/ffldb/interface_test.go index 58b4ab15e5..b0f275c5de 100644 --- a/database/ffldb/interface_test.go +++ b/database/ffldb/interface_test.go @@ -1212,7 +1212,7 @@ func testFetchBlockIOMissing(tc *testContext, tx database.Tx) bool { // testFetchBlockIO ensures all of the block retrieval API functions work as // expected for the provide set of blocks. The blocks must already be stored in -// the database, or at least stored into the the passed transaction. It also +// the database, or at least stored into the passed transaction. It also // tests several error conditions such as ensuring the expected errors are // returned when fetching blocks, headers, and regions that don't exist. func testFetchBlockIO(tc *testContext, tx database.Tx) bool { diff --git a/database/internal/treap/immutable_test.go b/database/internal/treap/immutable_test.go index e8952c3846..e0a1cb4af6 100644 --- a/database/internal/treap/immutable_test.go +++ b/database/internal/treap/immutable_test.go @@ -344,7 +344,7 @@ func TestImmutableDuplicatePut(t *testing.T) { testTreap = testTreap.Put(key, key) expectedSize += nodeFieldsSize + uint64(len(key)+len(key)) - // Put a duplicate key with the the expected final value. + // Put a duplicate key with the expected final value. testTreap = testTreap.Put(key, expectedVal) // Ensure the key still exists and is the new value. diff --git a/mining/mining.go b/mining/mining.go index 8ac388c263..99ef5d761d 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -42,7 +42,7 @@ type TxDesc struct { // Added is the time when the entry was added to the source pool. Added time.Time - // Height is the block height when the entry was added to the the source + // Height is the block height when the entry was added to the source // pool. Height int32 diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index b590a7963f..7b7e7212c9 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2661,7 +2661,7 @@ func (c *Client) WalletCreateFundedPsbt( type FutureWalletProcessPsbtResult chan *Response // Receive waits for the Response promised by the future and returns an updated -// PSBT with signed inputs from the wallet and a boolen indicating if the the +// PSBT with signed inputs from the wallet and a boolen indicating if the // transaction has a complete set of signatures. func (r FutureWalletProcessPsbtResult) Receive() (*btcjson.WalletProcessPsbtResult, error) { res, err := ReceiveFuture(r) diff --git a/txscript/doc.go b/txscript/doc.go index 179cb227b3..d6eddd5a65 100644 --- a/txscript/doc.go +++ b/txscript/doc.go @@ -25,7 +25,7 @@ to right and intentionally do not provide loops. The vast majority of Bitcoin scripts at the time of this writing are of several standard forms which consist of a spender providing a public key and a signature which proves the spender owns the associated private key. This information -is used to prove the the spender is authorized to perform the transaction. +is used to prove the spender is authorized to perform the transaction. One benefit of using a scripting language is added flexibility in specifying what conditions must be met in order to spend bitcoins. diff --git a/txscript/scriptnum.go b/txscript/scriptnum.go index 0b8b50d8b2..550b01e1ff 100644 --- a/txscript/scriptnum.go +++ b/txscript/scriptnum.go @@ -197,7 +197,7 @@ func (n scriptNum) Int32() int32 { // See the Bytes function documentation for example encodings. func MakeScriptNum(v []byte, requireMinimal bool, scriptNumLen int) (scriptNum, error) { // Interpreting data requires that it is not larger than - // the the passed scriptNumLen value. + // the passed scriptNumLen value. if len(v) > scriptNumLen { str := fmt.Sprintf("numeric value encoded as %x is %d bytes "+ "which exceeds the max allowed of %d", v, len(v), diff --git a/wire/msgtx.go b/wire/msgtx.go index 3c888deb86..7705504cc8 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -292,7 +292,7 @@ func NewTxIn(prevOut *OutPoint, signatureScript []byte, witness [][]byte) *TxIn // a slice of byte slices, or a stack with one or many elements. type TxWitness [][]byte -// SerializeSize returns the number of bytes it would take to serialize the the +// SerializeSize returns the number of bytes it would take to serialize the // transaction input's witness. func (t TxWitness) SerializeSize() int { // A varint to signal the number of elements the witness has. From 00d0edd5c47d8d2bb455250442d93365b47f7722 Mon Sep 17 00:00:00 2001 From: eugene Date: Mon, 28 Nov 2022 12:54:47 -0500 Subject: [PATCH 0775/1056] blockchain: intro HeaderCtx, ChainCtx + refactor CheckBlockHeaderContext This change will allow an external program to provide its own HeaderCtx and ChainCtx and be able to perform contextual block header checks. --- blockchain/blockindex.go | 64 ++++++++++++++++- blockchain/chain.go | 7 +- blockchain/chain_test.go | 4 +- blockchain/chainio.go | 2 +- blockchain/difficulty.go | 73 ++++++++++--------- blockchain/interfaces.go | 55 +++++++++++++++ blockchain/thresholdstate.go | 2 +- blockchain/validate.go | 131 ++++++++++++++++++++++++++++------- 8 files changed, 265 insertions(+), 73 deletions(-) create mode 100644 blockchain/interfaces.go diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 2ff2fa27c4..aa2db6a755 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -169,6 +169,60 @@ func (node *blockNode) Ancestor(height int32) *blockNode { return n } +// Height returns the blockNode's height in the chain. +// +// NOTE: Part of the HeaderCtx interface. +func (node *blockNode) Height() int32 { + return node.height +} + +// Bits returns the blockNode's nBits. +// +// NOTE: Part of the HeaderCtx interface. +func (node *blockNode) Bits() uint32 { + return node.bits +} + +// Timestamp returns the blockNode's timestamp. +// +// NOTE: Part of the HeaderCtx interface. +func (node *blockNode) Timestamp() int64 { + return node.timestamp +} + +// Parent returns the blockNode's parent. +// +// NOTE: Part of the HeaderCtx interface. +func (node *blockNode) Parent() HeaderCtx { + if node.parent == nil { + // This is required since node.parent is a *blockNode and if we + // do not explicitly return nil here, the caller may fail when + // nil-checking this. + return nil + } + + return node.parent +} + +// RelativeAncestorCtx returns the blockNode's ancestor that is distance blocks +// before it in the chain. This is equivalent to the RelativeAncestor function +// below except that the return type is different. +// +// This function is safe for concurrent access. +// +// NOTE: Part of the HeaderCtx interface. +func (node *blockNode) RelativeAncestorCtx(distance int32) HeaderCtx { + ancestor := node.RelativeAncestor(distance) + if ancestor == nil { + // This is required since RelativeAncestor returns a *blockNode + // and if we do not explicitly return nil here, the caller may + // fail when nil-checking this. + return nil + } + + return ancestor +} + // RelativeAncestor returns the ancestor block node a relative 'distance' blocks // before this node. This is equivalent to calling Ancestor with the node's // height minus provided distance. @@ -182,17 +236,17 @@ func (node *blockNode) RelativeAncestor(distance int32) *blockNode { // prior to, and including, the block node. // // This function is safe for concurrent access. -func (node *blockNode) CalcPastMedianTime() time.Time { +func CalcPastMedianTime(node HeaderCtx) time.Time { // Create a slice of the previous few block timestamps used to calculate // the median per the number defined by the constant medianTimeBlocks. timestamps := make([]int64, medianTimeBlocks) numNodes := 0 iterNode := node for i := 0; i < medianTimeBlocks && iterNode != nil; i++ { - timestamps[i] = iterNode.timestamp + timestamps[i] = iterNode.Timestamp() numNodes++ - iterNode = iterNode.parent + iterNode = iterNode.Parent() } // Prune the slice to the actual number of available timestamps which @@ -217,6 +271,10 @@ func (node *blockNode) CalcPastMedianTime() time.Time { return time.Unix(medianTimestamp, 0) } +// A compile-time assertion to ensure blockNode implements the HeaderCtx +// interface. +var _ HeaderCtx = (*blockNode)(nil) + // blockIndex provides facilities for keeping track of an in-memory index of the // block chain. Although the name block chain suggests a single chain of // blocks, it is actually a tree-shaped structure where any node can have diff --git a/blockchain/chain.go b/blockchain/chain.go index f29455b17a..c013ff3b15 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -437,7 +437,7 @@ func (b *BlockChain) calcSequenceLock(node *blockNode, tx *btcutil.Tx, utxoView prevInputHeight = 0 } blockNode := node.Ancestor(prevInputHeight) - medianTime := blockNode.CalcPastMedianTime() + medianTime := CalcPastMedianTime(blockNode) // Time based relative time-locks as defined by BIP 68 // have a time granularity of RelativeLockSeconds, so @@ -595,7 +595,8 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, blockSize := uint64(block.MsgBlock().SerializeSize()) blockWeight := uint64(GetBlockWeight(block)) state := newBestState(node, blockSize, blockWeight, numTxns, - curTotalTxns+numTxns, node.CalcPastMedianTime()) + curTotalTxns+numTxns, CalcPastMedianTime(node), + ) // Atomically insert info into the database. err = b.db.Update(func(dbTx database.Tx) error { @@ -708,7 +709,7 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view blockWeight := uint64(GetBlockWeight(prevBlock)) newTotalTxns := curTotalTxns - uint64(len(block.MsgBlock().Transactions)) state := newBestState(prevNode, blockSize, blockWeight, numTxns, - newTotalTxns, prevNode.CalcPastMedianTime()) + newTotalTxns, CalcPastMedianTime(prevNode)) err = b.db.Update(func(dbTx database.Tx) error { // Update best block state. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index 6569b7ec86..8d6ca89174 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -163,13 +163,13 @@ func TestCalcSequenceLock(t *testing.T) { // Obtain the median time past from the PoV of the input created above. // The MTP for the input is the MTP from the PoV of the block *prior* // to the one that included it. - medianTime := node.RelativeAncestor(5).CalcPastMedianTime().Unix() + medianTime := CalcPastMedianTime(node.RelativeAncestor(5)).Unix() // The median time calculated from the PoV of the best block in the // test chain. For unconfirmed inputs, this value will be used since // the MTP will be calculated from the PoV of the yet-to-be-mined // block. - nextMedianTime := node.CalcPastMedianTime().Unix() + nextMedianTime := CalcPastMedianTime(node).Unix() nextBlockHeight := int32(numBlocksToActivate) + 1 // Add an additional transaction which will serve as our unconfirmed diff --git a/blockchain/chainio.go b/blockchain/chainio.go index c29201c5f8..4914da6859 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1236,7 +1236,7 @@ func (b *BlockChain) initChainState() error { blockWeight := uint64(GetBlockWeight(btcutil.NewBlock(&block))) numTxns := uint64(len(block.Transactions)) b.stateSnapshot = newBestState(tip, blockSize, blockWeight, - numTxns, state.totalTxns, tip.CalcPastMedianTime()) + numTxns, state.totalTxns, CalcPastMedianTime(tip)) return nil }) diff --git a/blockchain/difficulty.go b/blockchain/difficulty.go index 1fdc8999a1..1fa850cc37 100644 --- a/blockchain/difficulty.go +++ b/blockchain/difficulty.go @@ -193,88 +193,87 @@ func (b *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration) // findPrevTestNetDifficulty returns the difficulty of the previous block which // did not have the special testnet minimum difficulty rule applied. -// -// This function MUST be called with the chain state lock held (for writes). -func (b *BlockChain) findPrevTestNetDifficulty(startNode *blockNode) uint32 { +func findPrevTestNetDifficulty(startNode HeaderCtx, c ChainCtx) uint32 { // Search backwards through the chain for the last block without // the special rule applied. iterNode := startNode - for iterNode != nil && iterNode.height%b.blocksPerRetarget != 0 && - iterNode.bits == b.chainParams.PowLimitBits { + for iterNode != nil && iterNode.Height()%c.BlocksPerRetarget() != 0 && + iterNode.Bits() == c.ChainParams().PowLimitBits { - iterNode = iterNode.parent + iterNode = iterNode.Parent() } // Return the found difficulty or the minimum difficulty if no // appropriate block was found. - lastBits := b.chainParams.PowLimitBits + lastBits := c.ChainParams().PowLimitBits if iterNode != nil { - lastBits = iterNode.bits + lastBits = iterNode.Bits() } return lastBits } // calcNextRequiredDifficulty calculates the required difficulty for the block -// after the passed previous block node based on the difficulty retarget rules. +// after the passed previous HeaderCtx based on the difficulty retarget rules. // This function differs from the exported CalcNextRequiredDifficulty in that -// the exported version uses the current best chain as the previous block node -// while this function accepts any block node. -func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, - newBlockTime time.Time) (uint32, error) { +// the exported version uses the current best chain as the previous HeaderCtx +// while this function accepts any block node. This function accepts a ChainCtx +// parameter that gives the necessary difficulty context variables. +func calcNextRequiredDifficulty(lastNode HeaderCtx, newBlockTime time.Time, + c ChainCtx) (uint32, error) { // Emulate the same behavior as Bitcoin Core that for regtest there is // no difficulty retargeting. - if b.chainParams.PoWNoRetargeting { - return b.chainParams.PowLimitBits, nil + if c.ChainParams().PoWNoRetargeting { + return c.ChainParams().PowLimitBits, nil } // Genesis block. if lastNode == nil { - return b.chainParams.PowLimitBits, nil + return c.ChainParams().PowLimitBits, nil } // Return the previous block's difficulty requirements if this block // is not at a difficulty retarget interval. - if (lastNode.height+1)%b.blocksPerRetarget != 0 { + if (lastNode.Height()+1)%c.BlocksPerRetarget() != 0 { // For networks that support it, allow special reduction of the // required difficulty once too much time has elapsed without // mining a block. - if b.chainParams.ReduceMinDifficulty { + if c.ChainParams().ReduceMinDifficulty { // Return minimum difficulty when more than the desired // amount of time has elapsed without mining a block. - reductionTime := int64(b.chainParams.MinDiffReductionTime / + reductionTime := int64(c.ChainParams().MinDiffReductionTime / time.Second) - allowMinTime := lastNode.timestamp + reductionTime + allowMinTime := lastNode.Timestamp() + reductionTime if newBlockTime.Unix() > allowMinTime { - return b.chainParams.PowLimitBits, nil + return c.ChainParams().PowLimitBits, nil } // The block was mined within the desired timeframe, so // return the difficulty for the last block which did // not have the special minimum difficulty rule applied. - return b.findPrevTestNetDifficulty(lastNode), nil + return findPrevTestNetDifficulty(lastNode, c), nil } // For the main network (or any unrecognized networks), simply // return the previous block's difficulty requirements. - return lastNode.bits, nil + return lastNode.Bits(), nil } // Get the block node at the previous retarget (targetTimespan days // worth of blocks). - firstNode := lastNode.RelativeAncestor(b.blocksPerRetarget - 1) + firstNode := lastNode.RelativeAncestorCtx(c.BlocksPerRetarget() - 1) if firstNode == nil { return 0, AssertError("unable to obtain previous retarget block") } // Limit the amount of adjustment that can occur to the previous // difficulty. - actualTimespan := lastNode.timestamp - firstNode.timestamp + actualTimespan := lastNode.Timestamp() - firstNode.Timestamp() adjustedTimespan := actualTimespan - if actualTimespan < b.minRetargetTimespan { - adjustedTimespan = b.minRetargetTimespan - } else if actualTimespan > b.maxRetargetTimespan { - adjustedTimespan = b.maxRetargetTimespan + if actualTimespan < c.MinRetargetTimespan() { + adjustedTimespan = c.MinRetargetTimespan() + } else if actualTimespan > c.MaxRetargetTimespan() { + adjustedTimespan = c.MaxRetargetTimespan() } // Calculate new target difficulty as: @@ -282,14 +281,14 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, // The result uses integer division which means it will be slightly // rounded down. Bitcoind also uses integer division to calculate this // result. - oldTarget := CompactToBig(lastNode.bits) + oldTarget := CompactToBig(lastNode.Bits()) newTarget := new(big.Int).Mul(oldTarget, big.NewInt(adjustedTimespan)) - targetTimeSpan := int64(b.chainParams.TargetTimespan / time.Second) + targetTimeSpan := int64(c.ChainParams().TargetTimespan / time.Second) newTarget.Div(newTarget, big.NewInt(targetTimeSpan)) // Limit new value to the proof of work limit. - if newTarget.Cmp(b.chainParams.PowLimit) > 0 { - newTarget.Set(b.chainParams.PowLimit) + if newTarget.Cmp(c.ChainParams().PowLimit) > 0 { + newTarget.Set(c.ChainParams().PowLimit) } // Log new target difficulty and return it. The new target logging is @@ -297,13 +296,13 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, // newTarget since conversion to the compact representation loses // precision. newTargetBits := BigToCompact(newTarget) - log.Debugf("Difficulty retarget at block height %d", lastNode.height+1) - log.Debugf("Old target %08x (%064x)", lastNode.bits, oldTarget) + log.Debugf("Difficulty retarget at block height %d", lastNode.Height()+1) + log.Debugf("Old target %08x (%064x)", lastNode.Bits(), oldTarget) log.Debugf("New target %08x (%064x)", newTargetBits, CompactToBig(newTargetBits)) log.Debugf("Actual timespan %v, adjusted timespan %v, target timespan %v", time.Duration(actualTimespan)*time.Second, time.Duration(adjustedTimespan)*time.Second, - b.chainParams.TargetTimespan) + c.ChainParams().TargetTimespan) return newTargetBits, nil } @@ -315,7 +314,7 @@ func (b *BlockChain) calcNextRequiredDifficulty(lastNode *blockNode, // This function is safe for concurrent access. func (b *BlockChain) CalcNextRequiredDifficulty(timestamp time.Time) (uint32, error) { b.chainLock.Lock() - difficulty, err := b.calcNextRequiredDifficulty(b.bestChain.Tip(), timestamp) + difficulty, err := calcNextRequiredDifficulty(b.bestChain.Tip(), timestamp, b) b.chainLock.Unlock() return difficulty, err } diff --git a/blockchain/interfaces.go b/blockchain/interfaces.go new file mode 100644 index 0000000000..cae9b3b9f0 --- /dev/null +++ b/blockchain/interfaces.go @@ -0,0 +1,55 @@ +package blockchain + +import ( + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +// ChainCtx is an interface that abstracts away blockchain parameters. +type ChainCtx interface { + // ChainParams returns the chain's configured chaincfg.Params. + ChainParams() *chaincfg.Params + + // BlocksPerRetarget returns the number of blocks before retargeting + // occurs. + BlocksPerRetarget() int32 + + // MinRetargetTimespan returns the minimum amount of time to use in the + // difficulty calculation. + MinRetargetTimespan() int64 + + // MaxRetargetTimespan returns the maximum amount of time to use in the + // difficulty calculation. + MaxRetargetTimespan() int64 + + // VerifyCheckpoint returns whether the passed height and hash match + // the checkpoint data. Not all instances of VerifyCheckpoint will use + // this function for validation. + VerifyCheckpoint(height int32, hash *chainhash.Hash) bool + + // FindPreviousCheckpoint returns the most recent checkpoint that we + // have validated. Not all instances of FindPreviousCheckpoint will use + // this function for validation. + FindPreviousCheckpoint() (HeaderCtx, error) +} + +// HeaderCtx is an interface that describes information about a block. This is +// used so that external libraries can provide their own context (the header's +// parent, bits, etc.) when attempting to contextually validate a header. +type HeaderCtx interface { + // Height returns the header's height. + Height() int32 + + // Bits returns the header's bits. + Bits() uint32 + + // Timestamp returns the header's timestamp. + Timestamp() int64 + + // Parent returns the header's parent. + Parent() HeaderCtx + + // RelativeAncestorCtx returns the header's ancestor that is distance + // blocks before it in the chain. + RelativeAncestorCtx(distance int32) HeaderCtx +} diff --git a/blockchain/thresholdstate.go b/blockchain/thresholdstate.go index 35653bf8fc..d62c2de3c2 100644 --- a/blockchain/thresholdstate.go +++ b/blockchain/thresholdstate.go @@ -153,7 +153,7 @@ func (b *BlockChain) PastMedianTime(blockHeader *wire.BlockHeader) (time.Time, e blockNode := newBlockNode(blockHeader, prevNode) - return blockNode.CalcPastMedianTime(), nil + return CalcPastMedianTime(blockNode), nil } // thresholdStateTransition given a state, a previous node, and a toeholds diff --git a/blockchain/validate.go b/blockchain/validate.go index dc7f0abe8e..662eb41b72 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -633,22 +633,30 @@ func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int32) error { return nil } -// checkBlockHeaderContext performs several validation checks on the block header +// CheckBlockHeaderContext performs several validation checks on the block header // which depend on its position within the block chain. // // The flags modify the behavior of this function as follows: // - BFFastAdd: All checks except those involving comparing the header against // the checkpoints are not performed. // +// The skipCheckpoint boolean is used so that libraries can skip the checkpoint +// sanity checks. +// // This function MUST be called with the chain state lock held (for writes). -func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode *blockNode, flags BehaviorFlags) error { +// NOTE: Ignore the above lock requirement if this function is not passed a +// *Blockchain instance as the ChainCtx argument. +func CheckBlockHeaderContext(header *wire.BlockHeader, prevNode HeaderCtx, + flags BehaviorFlags, c ChainCtx, skipCheckpoint bool) error { + fastAdd := flags&BFFastAdd == BFFastAdd if !fastAdd { // Ensure the difficulty specified in the block header matches // the calculated difficulty based on the previous block and // difficulty retarget rules. - expectedDifficulty, err := b.calcNextRequiredDifficulty(prevNode, - header.Timestamp) + expectedDifficulty, err := calcNextRequiredDifficulty( + prevNode, header.Timestamp, c, + ) if err != nil { return err } @@ -661,7 +669,7 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode // Ensure the timestamp for the block header is after the // median time of the last several blocks (medianTimeBlocks). - medianTime := prevNode.CalcPastMedianTime() + medianTime := CalcPastMedianTime(prevNode) if !header.Timestamp.After(medianTime) { str := "block timestamp of %v is not after expected %v" str = fmt.Sprintf(str, header.Timestamp, medianTime) @@ -671,11 +679,30 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode // The height of this block is one more than the referenced previous // block. - blockHeight := prevNode.height + 1 + blockHeight := prevNode.Height() + 1 + + // Reject outdated block versions once a majority of the network + // has upgraded. These were originally voted on by BIP0034, + // BIP0065, and BIP0066. + params := c.ChainParams() + if header.Version < 2 && blockHeight >= params.BIP0034Height || + header.Version < 3 && blockHeight >= params.BIP0066Height || + header.Version < 4 && blockHeight >= params.BIP0065Height { + + str := "new blocks with version %d are no longer valid" + str = fmt.Sprintf(str, header.Version) + return ruleError(ErrBlockVersionTooOld, str) + } + + if skipCheckpoint { + // If the caller wants us to skip the checkpoint checks, we'll + // return early. + return nil + } // Ensure chain matches up to predetermined checkpoints. blockHash := header.BlockHash() - if !b.verifyCheckpoint(blockHeight, &blockHash) { + if !c.VerifyCheckpoint(blockHeight, &blockHash) { str := fmt.Sprintf("block at height %d does not match "+ "checkpoint hash", blockHeight) return ruleError(ErrBadCheckpoint, str) @@ -685,30 +712,17 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode // chain before it. This prevents storage of new, otherwise valid, // blocks which build off of old blocks that are likely at a much easier // difficulty and therefore could be used to waste cache and disk space. - checkpointNode, err := b.findPreviousCheckpoint() + checkpointNode, err := c.FindPreviousCheckpoint() if err != nil { return err } - if checkpointNode != nil && blockHeight < checkpointNode.height { + if checkpointNode != nil && blockHeight < checkpointNode.Height() { str := fmt.Sprintf("block at height %d forks the main chain "+ "before the previous checkpoint at height %d", - blockHeight, checkpointNode.height) + blockHeight, checkpointNode.Height()) return ruleError(ErrForkTooOld, str) } - // Reject outdated block versions once a majority of the network - // has upgraded. These were originally voted on by BIP0034, - // BIP0065, and BIP0066. - params := b.chainParams - if header.Version < 2 && blockHeight >= params.BIP0034Height || - header.Version < 3 && blockHeight >= params.BIP0066Height || - header.Version < 4 && blockHeight >= params.BIP0065Height { - - str := "new blocks with version %d are no longer valid" - str = fmt.Sprintf(str, header.Version) - return ruleError(ErrBlockVersionTooOld, str) - } - return nil } @@ -726,7 +740,7 @@ func (b *BlockChain) checkBlockHeaderContext(header *wire.BlockHeader, prevNode func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode, flags BehaviorFlags) error { // Perform all block header related validation checks. header := &block.MsgBlock().Header - err := b.checkBlockHeaderContext(header, prevNode, flags) + err := CheckBlockHeaderContext(header, prevNode, flags, b, false) if err != nil { return err } @@ -746,7 +760,7 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode // timestamps for all lock-time based checks. blockTime := header.Timestamp if csvState == ThresholdActive { - blockTime = prevNode.CalcPastMedianTime() + blockTime = CalcPastMedianTime(prevNode) } // The height of this block is one more than the referenced @@ -1186,7 +1200,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi // We obtain the MTP of the *previous* block in order to // determine if transactions in the current block are final. - medianTime := node.parent.CalcPastMedianTime() + medianTime := CalcPastMedianTime(node.parent) // Additionally, if the CSV soft-fork package is now active, // then we also enforce the relative sequence number based @@ -1288,3 +1302,68 @@ func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error { newNode := newBlockNode(&header, tip) return b.checkConnectBlock(newNode, block, view, nil) } + +// ChainParams returns the Blockchain's configured chaincfg.Params. +// +// NOTE: Part of the ChainCtx interface. +func (b *BlockChain) ChainParams() *chaincfg.Params { + return b.chainParams +} + +// BlocksPerRetarget returns the number of blocks before retargeting occurs. +// +// NOTE: Part of the ChainCtx interface. +func (b *BlockChain) BlocksPerRetarget() int32 { + return b.blocksPerRetarget +} + +// MinRetargetTimespan returns the minimum amount of time to use in the +// difficulty calculation. +// +// NOTE: Part of the ChainCtx interface. +func (b *BlockChain) MinRetargetTimespan() int64 { + return b.minRetargetTimespan +} + +// MaxRetargetTimespan returns the maximum amount of time to use in the +// difficulty calculation. +// +// NOTE: Part of the ChainCtx interface. +func (b *BlockChain) MaxRetargetTimespan() int64 { + return b.maxRetargetTimespan +} + +// VerifyCheckpoint checks that the height and hash match the stored +// checkpoints. +// +// NOTE: Part of the ChainCtx interface. +func (b *BlockChain) VerifyCheckpoint(height int32, + hash *chainhash.Hash) bool { + + return b.verifyCheckpoint(height, hash) +} + +// FindPreviousCheckpoint finds the checkpoint we've encountered during +// validation. +// +// NOTE: Part of the ChainCtx interface. +func (b *BlockChain) FindPreviousCheckpoint() (HeaderCtx, error) { + checkpoint, err := b.findPreviousCheckpoint() + if err != nil { + return nil, err + } + + if checkpoint == nil { + // This check is necessary because if we just return the nil + // blockNode as a HeaderCtx, a caller performing a nil-check + // will fail. This is a quirk of go where a nil value stored in + // an interface is different from the actual nil interface. + return nil, nil + } + + return checkpoint, err +} + +// A compile-time assertion to ensure BlockChain implements the ChainCtx +// interface. +var _ ChainCtx = (*BlockChain)(nil) From ee6c0e19626f221ab6fd516c72c3f30421d62001 Mon Sep 17 00:00:00 2001 From: eugene Date: Mon, 28 Nov 2022 12:57:33 -0500 Subject: [PATCH 0776/1056] blockchain: export CheckBlockHeaderSanity as a library function --- blockchain/validate.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/blockchain/validate.go b/blockchain/validate.go index 662eb41b72..e686175aad 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -421,13 +421,15 @@ func CountP2SHSigOps(tx *btcutil.Tx, isCoinBaseTx bool, utxoView *UtxoViewpoint) return totalSigOps, nil } -// checkBlockHeaderSanity performs some preliminary checks on a block header to +// CheckBlockHeaderSanity performs some preliminary checks on a block header to // ensure it is sane before continuing with processing. These checks are // context free. // // The flags do not modify the behavior of this function directly, however they // are needed to pass along to checkProofOfWork. -func checkBlockHeaderSanity(header *wire.BlockHeader, powLimit *big.Int, timeSource MedianTimeSource, flags BehaviorFlags) error { +func CheckBlockHeaderSanity(header *wire.BlockHeader, powLimit *big.Int, + timeSource MedianTimeSource, flags BehaviorFlags) error { + // Ensure the proof of work bits in the block header is in min/max range // and the block hash is less than the target value described by the // bits. @@ -467,7 +469,7 @@ func checkBlockHeaderSanity(header *wire.BlockHeader, powLimit *big.Int, timeSou func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource MedianTimeSource, flags BehaviorFlags) error { msgBlock := block.MsgBlock() header := &msgBlock.Header - err := checkBlockHeaderSanity(header, powLimit, timeSource, flags) + err := CheckBlockHeaderSanity(header, powLimit, timeSource, flags) if err != nil { return err } From 725b36bf09ea65e0daa8f02969c177a8cb28176a Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Sun, 18 Jun 2023 10:15:20 +0200 Subject: [PATCH 0777/1056] btcutil: format BTC amounts with trailing zeroes so that sat amounts can be read without counting zeroes before: 350sat = 0.0000035 BTC 3500sat = 0.000035 BTC after: 350sat = 0.00000350 BTC 3500sat = 0.00003500 BTC fixes #1995 --- btcutil/amount.go | 15 +++++++++++++-- btcutil/amount_test.go | 25 +++++++++++++++++++++++-- btcutil/example_test.go | 4 ++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/btcutil/amount.go b/btcutil/amount.go index 71714153aa..bb70c9b11d 100644 --- a/btcutil/amount.go +++ b/btcutil/amount.go @@ -6,8 +6,10 @@ package btcutil import ( "errors" + "fmt" "math" "strconv" + "strings" ) // AmountUnit describes a method of converting an Amount to something @@ -101,11 +103,20 @@ func (a Amount) ToBTC() float64 { // Format formats a monetary amount counted in bitcoin base units as a // string for a given unit. The conversion will succeed for any unit, -// however, known units will be formated with an appended label describing +// however, known units will be formatted with an appended label describing // the units with SI notation, or "Satoshi" for the base unit. func (a Amount) Format(u AmountUnit) string { units := " " + u.String() - return strconv.FormatFloat(a.ToUnit(u), 'f', -int(u+8), 64) + units + formatted := strconv.FormatFloat(a.ToUnit(u), 'f', -int(u+8), 64) + + // When formatting full BTC, add trailing zeroes for numbers + // with decimal point to ease reading of sat amount. + if u == AmountBTC { + if strings.Contains(formatted, ".") { + return fmt.Sprintf("%.8f%s", a.ToUnit(u), units) + } + } + return formatted + units } // String is the equivalent of calling Format with AmountBTC. diff --git a/btcutil/amount_test.go b/btcutil/amount_test.go index 2b6c3f753d..69498b07e2 100644 --- a/btcutil/amount_test.go +++ b/btcutil/amount_test.go @@ -136,8 +136,29 @@ func TestAmountUnitConversions(t *testing.T) { name: "BTC", amount: 44433322211100, unit: AmountBTC, - converted: 444333.22211100, - s: "444333.222111 BTC", + converted: 444333.222111, + s: "444333.22211100 BTC", + }, + { + name: "a thousand satoshi as BTC", + amount: 1000, + unit: AmountBTC, + converted: 0.00001, + s: "0.00001000 BTC", + }, + { + name: "a single satoshi as BTC", + amount: 1, + unit: AmountBTC, + converted: 0.00000001, + s: "0.00000001 BTC", + }, + { + name: "amount with trailing zero but no decimals", + amount: 1000000000, + unit: AmountBTC, + converted: 10, + s: "10 BTC", }, { name: "mBTC", diff --git a/btcutil/example_test.go b/btcutil/example_test.go index 6b62fdd44f..90be77b073 100644 --- a/btcutil/example_test.go +++ b/btcutil/example_test.go @@ -20,7 +20,7 @@ func ExampleAmount() { // Output: // Zero Satoshi: 0 BTC // 100,000,000 Satoshis: 1 BTC - // 100,000 Satoshis: 0.001 BTC + // 100,000 Satoshis: 0.00100000 BTC } func ExampleNewAmount() { @@ -69,7 +69,7 @@ func ExampleAmount_unitConversions() { // Output: // Satoshi to kBTC: 444.333222111 kBTC - // Satoshi to BTC: 444333.222111 BTC + // Satoshi to BTC: 444333.22211100 BTC // Satoshi to MilliBTC: 444333222.111 mBTC // Satoshi to MicroBTC: 444333222111 μBTC // Satoshi to Satoshi: 44433322211100 Satoshi From 8f84bb0e9bcbdc1dfc00c5d35382927a8a6edd8e Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Mon, 10 Jul 2023 16:40:26 +0200 Subject: [PATCH 0778/1056] musig2: fix early nonce gen option Previously the early nonce generation option was not being respected when creating the context, with the WithKnownSigners option being used. This commit fixes that. --- btcec/schnorr/musig2/context.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 44ed69c8ee..7ed759cd0a 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -234,24 +234,23 @@ func NewContext(signingKey *btcec.PrivateKey, shouldSort bool, opts.keySet = make([]*btcec.PublicKey, 0, opts.numSigners) opts.keySet = append(opts.keySet, pubKey) - // If early nonce generation is specified, then we'll generate - // the nonce now to pass in to the session once all the callers - // are known. - if opts.earlyNonce { - var err error - ctx.sessionNonce, err = GenNonces( - WithPublicKey(ctx.pubKey), - WithNonceSecretKeyAux(signingKey), - ) - if err != nil { - return nil, err - } - } - default: return nil, ErrSignersNotSpecified } + // If early nonce generation is specified, then we'll generate the + // nonce now to pass in to the session once all the callers are known. + if opts.earlyNonce { + var err error + ctx.sessionNonce, err = GenNonces( + WithPublicKey(ctx.pubKey), + WithNonceSecretKeyAux(signingKey), + ) + if err != nil { + return nil, err + } + } + return ctx, nil } From 883a03da999fc290f577bcf2ddaa070be2335f21 Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Mon, 10 Jul 2023 21:36:30 +0200 Subject: [PATCH 0779/1056] musig2: add early nonce gen KnownSigners test This commit changes the early nonce gen test to use the KnownSigners Option for one of the contexts. --- btcec/schnorr/musig2/musig2_test.go | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 6842e911d9..b2101021dd 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -278,7 +278,8 @@ func TestMuSigEarlyNonce(t *testing.T) { t.Fatalf("unexpected ctx error: %v", err) } - numSigners := 2 + signers := []*btcec.PublicKey{privKey1.PubKey(), privKey2.PubKey()} + numSigners := len(signers) ctx1, err := NewContext( privKey1, true, WithNumSigners(numSigners), WithEarlyNonceGen(), @@ -289,20 +290,21 @@ func TestMuSigEarlyNonce(t *testing.T) { pubKey1 := ctx1.PubKey() ctx2, err := NewContext( - privKey2, true, WithNumSigners(numSigners), WithEarlyNonceGen(), + privKey2, true, WithKnownSigners(signers), WithEarlyNonceGen(), ) if err != nil { t.Fatalf("unable to make ctx: %v", err) } pubKey2 := ctx2.PubKey() - // At this point, the combined key shouldn't be available for both - // signers, since we only know of the sole signers. + // At this point, the combined key shouldn't be available for signer 1, + // but should be for signer 2, as they know about all signers. if _, err := ctx1.CombinedKey(); !errors.Is(err, ErrNotEnoughSigners) { t.Fatalf("unepxected error: %v", err) } - if _, err := ctx2.CombinedKey(); !errors.Is(err, ErrNotEnoughSigners) { - t.Fatalf("unepxected error: %v", err) + _, err = ctx2.CombinedKey() + if err != nil { + t.Fatalf("unable to get combined key: %v", err) } // The early nonces _should_ be available at this point. @@ -320,8 +322,8 @@ func TestMuSigEarlyNonce(t *testing.T) { t.Fatalf("expected 1 signer, instead have: %v", ctx1.NumRegisteredSigners()) } - if ctx2.NumRegisteredSigners() != 1 { - t.Fatalf("expected 1 signer, instead have: %v", + if ctx2.NumRegisteredSigners() != 2 { + t.Fatalf("expected 2 signers, instead have: %v", ctx2.NumRegisteredSigners()) } @@ -336,7 +338,7 @@ func TestMuSigEarlyNonce(t *testing.T) { t.Fatalf("unexpected combined key error: %v", err) } - // We'll now register the other signer for both parties. + // We'll now register the other signer for party 1. done, err := ctx1.RegisterSigner(&pubKey2) if err != nil { t.Fatalf("unable to register signer: %v", err) @@ -344,13 +346,6 @@ func TestMuSigEarlyNonce(t *testing.T) { if !done { t.Fatalf("signer 1 doesn't have all keys") } - done, err = ctx2.RegisterSigner(&pubKey1) - if err != nil { - t.Fatalf("unable to register signer: %v", err) - } - if !done { - t.Fatalf("signer 2 doesn't have all keys") - } // If we try to register the signer again, we should get an error. _, err = ctx2.RegisterSigner(&pubKey1) From b84f084ce781fa430276db412fe03e5fa7bba294 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Sun, 6 Nov 2022 18:56:24 +0900 Subject: [PATCH 0780/1056] blockchain: Add InactiveTips() to blockindex InactiveTips() returns all the tips of the branches of the blockchain tree that are not in the best chain. This function is useful for supporting the getchaintips rpc call. --- blockchain/blockindex.go | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index aa2db6a755..7412aa1129 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -377,6 +377,44 @@ func (bi *blockIndex) UnsetStatusFlags(node *blockNode, flags blockStatus) { bi.Unlock() } +// InactiveTips returns all the block nodes that aren't in the best chain. +// +// This function is safe for concurrent access. +func (bi *blockIndex) InactiveTips(bestChain *chainView) []*blockNode { + bi.RLock() + defer bi.RUnlock() + + // Look through the entire blockindex and look for nodes that aren't in + // the best chain. We're gonna keep track of all the orphans and the parents + // of the orphans. + orphans := make(map[chainhash.Hash]*blockNode) + orphanParent := make(map[chainhash.Hash]*blockNode) + for hash, node := range bi.index { + found := bestChain.Contains(node) + if !found { + orphans[hash] = node + orphanParent[node.parent.hash] = node.parent + } + } + + // If an orphan isn't pointed to by another orphan, it is a chain tip. + // + // We can check this by looking for the orphan in the orphan parent map. + // If the orphan exists in the orphan parent map, it means that another + // orphan is pointing to it. + tips := make([]*blockNode, 0, len(orphans)) + for hash, orphan := range orphans { + _, found := orphanParent[hash] + if !found { + tips = append(tips, orphan) + } + + delete(orphanParent, hash) + } + + return tips +} + // flushToDB writes all dirty block nodes to the database. If all writes // succeed, this clears the dirty set. func (bi *blockIndex) flushToDB() error { From 46bfb784a6a9256d13cc148fd81f044f2017182d Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 7 Nov 2022 14:55:37 +0900 Subject: [PATCH 0781/1056] blockchain: Add ChainTips() method to BlockChain ChainTips method allows for callers to get all the chain tips the node is aware of. This is useful for supporting the getchaintips rpc call. --- blockchain/chain.go | 113 +++++++++++++++++++++++ blockchain/chain_test.go | 191 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 304 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index c013ff3b15..77680ba9f1 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1256,6 +1256,119 @@ func (b *BlockChain) BestSnapshot() *BestState { return snapshot } +// TipStatus is the status of a chain tip. +type TipStatus byte + +const ( + // StatusUnknown indicates that the tip status isn't any of the defined + // statuses. + StatusUnknown TipStatus = iota + + // StatusActive indicates that the tip is considered active and is in + // the best chain. + StatusActive + + // StatusInvalid indicates that this tip or any of the ancestors of this + // tip are invalid. + StatusInvalid + + // StatusValidFork is given if: + // 1: Not a part of the best chain. + // 2: Is not invalid. + // 3: Has the block data stored to disk. + StatusValidFork +) + +// String returns the status flags as string. +func (ts TipStatus) String() string { + switch ts { + case StatusActive: + return "active" + case StatusInvalid: + return "invalid" + case StatusValidFork: + return "valid-fork" + } + return fmt.Sprintf("unknown: %b", ts) +} + +// ChainTip represents the last block in a branch of the block tree. +type ChainTip struct { + // Height of the tip. + Height int32 + + // BlockHash hash of the tip. + BlockHash chainhash.Hash + + // BranchLen is length of the fork point of this chain from the main chain. + // Returns 0 if the chain tip is a part of the best chain. + BranchLen int32 + + // Status is the validity status of the branch this tip is in. + Status TipStatus +} + +// ChainTips returns all the chain tips the node itself is aware of. Each tip is +// represented by its height, block hash, branch length, and status. +// +// This function is safe for concurrent access. +func (b *BlockChain) ChainTips() []ChainTip { + b.chainLock.RLock() + defer b.chainLock.RUnlock() + + // Grab all the inactive tips. + tips := b.index.InactiveTips(b.bestChain) + + // Add the current tip. + tips = append(tips, b.bestChain.Tip()) + + chainTips := make([]ChainTip, 0, len(tips)) + + // Go through all the tips and grab the height, hash, branch length, and the block + // status. + for _, tip := range tips { + var status TipStatus + switch { + // The tip is considered active if it's in the best chain. + case b.bestChain.Contains(tip): + status = StatusActive + + // This block or any of the ancestors of this block are invalid. + case tip.status.KnownInvalid(): + status = StatusInvalid + + // If the tip meets the following criteria: + // 1: Not a part of the best chain. + // 2: Is not invalid. + // 3: Has the block data stored to disk. + // + // The tip is considered a valid fork. + // + // We can check if a tip is a valid-fork by checking that + // its data is available. Since the behavior is to give a + // block node the statusDataStored status once it passes + // the proof of work checks and basic chain validity checks. + // + // We can't use the KnownValid status since it's only given + // to blocks that passed the validation AND were a part of + // the bestChain. + case tip.status.HaveData(): + status = StatusValidFork + } + + chainTip := ChainTip{ + Height: tip.height, + BlockHash: tip.hash, + BranchLen: tip.height - b.bestChain.FindFork(tip).height, + Status: status, + } + + chainTips = append(chainTips, chainTip) + } + + return chainTips +} + // HeaderByHash returns the block header identified by the given hash or an // error if it doesn't exist. Note that this will return headers from both the // main and side chains. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index 8d6ca89174..1ac08f9a76 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -5,6 +5,7 @@ package blockchain import ( + "fmt" "reflect" "testing" "time" @@ -964,3 +965,193 @@ func TestIntervalBlockHashes(t *testing.T) { } } } + +func TestChainTips(t *testing.T) { + tests := []struct { + name string + chainTipGen func() (*BlockChain, map[chainhash.Hash]ChainTip) + }{ + { + name: "one active chain tip", + chainTipGen: func() (*BlockChain, map[chainhash.Hash]ChainTip) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> 3 + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 3) + for _, node := range branch0Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branch0Nodes)) + + activeTip := ChainTip{ + Height: 3, + BlockHash: (tip(branch0Nodes)).hash, + BranchLen: 0, + Status: StatusActive, + } + chainTips := make(map[chainhash.Hash]ChainTip) + chainTips[activeTip.BlockHash] = activeTip + + return chain, chainTips + }, + }, + { + name: "one active chain tip, one unknown chain tip", + chainTipGen: func() (*BlockChain, map[chainhash.Hash]ChainTip) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> 3 ... -> 10 -> 11 -> 12 -> 13 (active) + // \-> 11a -> 12a (unknown) + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 13) + for _, node := range branch0Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branch0Nodes)) + + branch1Nodes := chainedNodes(branch0Nodes[9], 2) + for _, node := range branch1Nodes { + chain.index.AddNode(node) + } + + activeTip := ChainTip{ + Height: 13, + BlockHash: (tip(branch0Nodes)).hash, + BranchLen: 0, + Status: StatusActive, + } + unknownTip := ChainTip{ + Height: 12, + BlockHash: (tip(branch1Nodes)).hash, + BranchLen: 2, + Status: StatusUnknown, + } + chainTips := make(map[chainhash.Hash]ChainTip) + chainTips[activeTip.BlockHash] = activeTip + chainTips[unknownTip.BlockHash] = unknownTip + + return chain, chainTips + }, + }, + { + name: "1 inactive tip, 1 invalid tip, 1 active tip", + chainTipGen: func() (*BlockChain, map[chainhash.Hash]ChainTip) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 3) + for _, node := range branch0Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branch0Nodes)) + + branch1Nodes := chainedNodes(chain.bestChain.Genesis(), 1) + for _, node := range branch1Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + + branch2Nodes := chainedNodes(chain.bestChain.Genesis(), 1) + for _, node := range branch2Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValidateFailed) + chain.index.AddNode(node) + } + + activeTip := ChainTip{ + Height: tip(branch0Nodes).height, + BlockHash: (tip(branch0Nodes)).hash, + BranchLen: 0, + Status: StatusActive, + } + + inactiveTip := ChainTip{ + Height: tip(branch1Nodes).height, + BlockHash: (tip(branch1Nodes)).hash, + BranchLen: 1, + Status: StatusValidFork, + } + + invalidTip := ChainTip{ + Height: tip(branch2Nodes).height, + BlockHash: (tip(branch2Nodes)).hash, + BranchLen: 1, + Status: StatusInvalid, + } + + chainTips := make(map[chainhash.Hash]ChainTip) + chainTips[activeTip.BlockHash] = activeTip + chainTips[inactiveTip.BlockHash] = inactiveTip + chainTips[invalidTip.BlockHash] = invalidTip + + return chain, chainTips + }, + }, + } + + for _, test := range tests { + chain, expectedChainTips := test.chainTipGen() + gotChainTips := chain.ChainTips() + if len(gotChainTips) != len(expectedChainTips) { + t.Errorf("TestChainTips Failed test %s. Expected %d "+ + "chain tips, got %d", test.name, len(expectedChainTips), len(gotChainTips)) + } + + for _, gotChainTip := range gotChainTips { + testChainTip, found := expectedChainTips[gotChainTip.BlockHash] + if !found { + t.Errorf("TestChainTips Failed test %s. Couldn't find an expected "+ + "chain tip with height %d, hash %s, branchlen %d, status \"%s\"", + test.name, testChainTip.Height, testChainTip.BlockHash.String(), + testChainTip.BranchLen, testChainTip.Status.String()) + } + + if !reflect.DeepEqual(testChainTip, gotChainTip) { + t.Errorf("TestChainTips Failed test %s. Expected chain tip with "+ + "height %d, hash %s, branchlen %d, status \"%s\" but got "+ + "height %d, hash %s, branchlen %d, status \"%s\"", test.name, + testChainTip.Height, testChainTip.BlockHash.String(), + testChainTip.BranchLen, testChainTip.Status.String(), + gotChainTip.Height, gotChainTip.BlockHash.String(), + gotChainTip.BranchLen, gotChainTip.Status.String()) + } + + switch testChainTip.Status { + case StatusActive: + if testChainTip.Status.String() != "active" { + t.Errorf("TestChainTips Fail: Expected string of \"active\", got \"%s\"", + testChainTip.Status.String()) + } + case StatusInvalid: + if testChainTip.Status.String() != "invalid" { + t.Errorf("TestChainTips Fail: Expected string of \"invalid\", got \"%s\"", + testChainTip.Status.String()) + } + case StatusValidFork: + if testChainTip.Status.String() != "valid-fork" { + t.Errorf("TestChainTips Fail: Expected string of \"valid-fork\", got \"%s\"", + testChainTip.Status.String()) + } + case StatusUnknown: + if testChainTip.Status.String() != fmt.Sprintf("unknown: %b", testChainTip.Status) { + t.Errorf("TestChainTips Fail: Expected string of \"unknown\", got \"%s\"", + testChainTip.Status.String()) + } + } + } + } +} From 892ae679b3950addb96eedca7922a290c32e3878 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 7 Nov 2022 15:00:05 +0900 Subject: [PATCH 0782/1056] btcjson, main: Implement the getchaintips call getchaintips call is implemented and the behavior mimics that of Bitcoin Core. Resolves https://github.com/btcsuite/btcd/issues/1912. --- btcjson/chainsvrresults.go | 8 ++++++++ rpcserver.go | 25 ++++++++++++++++++++++++- rpcserverhelp.go | 10 ++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 4feaeda338..fe28e25324 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -117,6 +117,14 @@ type GetBlockVerboseTxResult struct { NextHash string `json:"nextblockhash,omitempty"` } +// GetChainTipsResult models the data from the getchaintips command. +type GetChainTipsResult struct { + Height int32 `json:"height"` + Hash string `json:"hash"` + BranchLen int32 `json:"branchlen"` + Status string `json:"status"` +} + // GetChainTxStatsResult models the data from the getchaintxstats command. type GetChainTxStatsResult struct { Time int64 `json:"time"` diff --git a/rpcserver.go b/rpcserver.go index b917263df5..cd9ac04802 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -146,6 +146,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "getblockhash": handleGetBlockHash, "getblockheader": handleGetBlockHeader, "getblocktemplate": handleGetBlockTemplate, + "getchaintips": handleGetChainTips, "getcfilter": handleGetCFilter, "getcfilterheader": handleGetCFilterHeader, "getconnectioncount": handleGetConnectionCount, @@ -231,7 +232,6 @@ var rpcAskWallet = map[string]struct{}{ // Commands that are currently unimplemented, but should ultimately be. var rpcUnimplemented = map[string]struct{}{ "estimatepriority": {}, - "getchaintips": {}, "getmempoolentry": {}, "getnetworkinfo": {}, "getwork": {}, @@ -266,6 +266,7 @@ var rpcLimited = map[string]struct{}{ "getblockcount": {}, "getblockhash": {}, "getblockheader": {}, + "getchaintips": {}, "getcfilter": {}, "getcfilterheader": {}, "getcurrentnet": {}, @@ -2192,6 +2193,28 @@ func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan stru } } +// handleGetChainTips implements the getchaintips command. +func handleGetChainTips(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + chainTips := s.cfg.Chain.ChainTips() + + ret := make([]btcjson.GetChainTipsResult, 0, len(chainTips)) + for _, chainTip := range chainTips { + ret = append(ret, struct { + Height int32 "json:\"height\"" + Hash string "json:\"hash\"" + BranchLen int32 "json:\"branchlen\"" + Status string "json:\"status\"" + }{ + Height: chainTip.Height, + Hash: chainTip.BlockHash.String(), + BranchLen: chainTip.BranchLen, + Status: chainTip.Status.String(), + }) + } + + return ret, nil +} + // handleGetCFilter implements the getcfilter command. func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { if s.cfg.CfIndex == nil { diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 16bbb62a2b..262660962b 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -347,6 +347,15 @@ var helpDescsEnUS = map[string]string{ "getblocktemplate--condition2": "mode=proposal, accepted", "getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted", + // GetChainTipsResult help. + "getchaintipsresult-chaintips": "The chaintips that this node is aware of", + "getchaintipsresult-height": "The height of the chain tip", + "getchaintipsresult-hash": "The block hash of the chain tip", + "getchaintipsresult-branchlen": "Returns zero for main chain. Otherwise is the length of branch connecting the tip to the main chain", + "getchaintipsresult-status": "Status of the chain. Returns \"active\" for the main chain", + // GetChainTipsCmd help. + "getchaintips--synopsis": "Returns information about all known tips in the block tree, including the main chain as well as orphaned branches.", + // GetCFilterCmd help. "getcfilter--synopsis": "Returns a block's committed filter given its hash.", "getcfilter-filtertype": "The type of filter to return (0=regular)", @@ -728,6 +737,7 @@ var rpcResultTypes = map[string][]interface{}{ "getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)}, "getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil}, "getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)}, + "getchaintips": {(*[]btcjson.GetChainTipsResult)(nil)}, "getcfilter": {(*string)(nil)}, "getcfilterheader": {(*string)(nil)}, "getconnectioncount": {(*int32)(nil)}, From e2d9e2092b088f96ea40d41173b686c0dc2b77ac Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 11 Nov 2022 14:37:38 +0900 Subject: [PATCH 0783/1056] docs: Update json_rpc_api.md for getchaintips rpc --- docs/json_rpc_api.md | 53 +++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index d1b43ce8c4..2c7d455457 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -168,26 +168,27 @@ the method name for further details such as parameter and return information. |8|[getblockcount](#getblockcount)|Y|Returns the number of blocks in the longest block chain.| |9|[getblockhash](#getblockhash)|Y|Returns hash of the block in best block chain at the given height.| |10|[getblockheader](#getblockheader)|Y|Returns the block header of the block.| -|11|[getconnectioncount](#getconnectioncount)|N|Returns the number of active connections to other peers.| -|12|[getdifficulty](#getdifficulty)|Y|Returns the proof-of-work difficulty as a multiple of the minimum difficulty.| -|13|[getgenerate](#getgenerate)|N|Return if the server is set to generate coins (mine) or not.| -|14|[gethashespersec](#gethashespersec)|N|Returns a recent hashes per second performance measurement while generating coins (mining).| -|15|[getinfo](#getinfo)|Y|Returns a JSON object containing various state info.| -|16|[getmempoolinfo](#getmempoolinfo)|N|Returns a JSON object containing mempool-related information.| -|17|[getmininginfo](#getmininginfo)|N|Returns a JSON object containing mining-related information.| -|18|[getnettotals](#getnettotals)|Y|Returns a JSON object containing network traffic statistics.| -|19|[getnetworkhashps](#getnetworkhashps)|Y|Returns the estimated network hashes per second for the block heights provided by the parameters.| -|20|[getpeerinfo](#getpeerinfo)|N|Returns information about each connected network peer as an array of json objects.| -|21|[getrawmempool](#getrawmempool)|Y|Returns an array of hashes for all of the transactions currently in the memory pool.| -|22|[getrawtransaction](#getrawtransaction)|Y|Returns information about a transaction given its hash.| -|23|[help](#help)|Y|Returns a list of all commands or help for a specified command.| -|24|[ping](#ping)|N|Queues a ping to be sent to each connected peer.| -|25|[sendrawtransaction](#sendrawtransaction)|Y|Submits the serialized, hex-encoded transaction to the local peer and relays it to the network.
btcd does not yet implement the `allowhighfees` parameter, so it has no effect| -|26|[setgenerate](#setgenerate) |N|Set the server to generate coins (mine) or not.
NOTE: Since btcd does not have the wallet integrated to provide payment addresses, btcd must be configured via the `--miningaddr` option to provide which payment addresses to pay created blocks to for this RPC to function.| -|27|[stop](#stop)|N|Shutdown btcd.| -|28|[submitblock](#submitblock)|Y|Attempts to submit a new serialized, hex-encoded block to the network.| -|29|[validateaddress](#validateaddress)|Y|Verifies the given address is valid. NOTE: Since btcd does not have a wallet integrated, btcd will only return whether the address is valid or not.| -|30|[verifychain](#verifychain)|N|Verifies the block chain database.| +|11|[getchaintips](#getchaintips)|Y|Returns information about all known tips in the block tree, including the main chain as well as orphaned branches.| +|12|[getconnectioncount](#getconnectioncount)|N|Returns the number of active connections to other peers.| +|13|[getdifficulty](#getdifficulty)|Y|Returns the proof-of-work difficulty as a multiple of the minimum difficulty.| +|14|[getgenerate](#getgenerate)|N|Return if the server is set to generate coins (mine) or not.| +|15|[gethashespersec](#gethashespersec)|N|Returns a recent hashes per second performance measurement while generating coins (mining).| +|16|[getinfo](#getinfo)|Y|Returns a JSON object containing various state info.| +|17|[getmempoolinfo](#getmempoolinfo)|N|Returns a JSON object containing mempool-related information.| +|18|[getmininginfo](#getmininginfo)|N|Returns a JSON object containing mining-related information.| +|19|[getnettotals](#getnettotals)|Y|Returns a JSON object containing network traffic statistics.| +|20|[getnetworkhashps](#getnetworkhashps)|Y|Returns the estimated network hashes per second for the block heights provided by the parameters.| +|21|[getpeerinfo](#getpeerinfo)|N|Returns information about each connected network peer as an array of json objects.| +|22|[getrawmempool](#getrawmempool)|Y|Returns an array of hashes for all of the transactions currently in the memory pool.| +|23|[getrawtransaction](#getrawtransaction)|Y|Returns information about a transaction given its hash.| +|24|[help](#help)|Y|Returns a list of all commands or help for a specified command.| +|25|[ping](#ping)|N|Queues a ping to be sent to each connected peer.| +|26|[sendrawtransaction](#sendrawtransaction)|Y|Submits the serialized, hex-encoded transaction to the local peer and relays it to the network.
btcd does not yet implement the `allowhighfees` parameter, so it has no effect| +|27|[setgenerate](#setgenerate) |N|Set the server to generate coins (mine) or not.
NOTE: Since btcd does not have the wallet integrated to provide payment addresses, btcd must be configured via the `--miningaddr` option to provide which payment addresses to pay created blocks to for this RPC to function.| +|28|[stop](#stop)|N|Shutdown btcd.| +|29|[submitblock](#submitblock)|Y|Attempts to submit a new serialized, hex-encoded block to the network.| +|30|[validateaddress](#validateaddress)|Y|Verifies the given address is valid. NOTE: Since btcd does not have a wallet integrated, btcd will only return whether the address is valid or not.| +|31|[verifychain](#verifychain)|N|Verifies the block chain database.|
@@ -319,6 +320,18 @@ the method name for further details such as parameter and return information. |Example Return (verbose=true)|`{`
  `"hash": "00000000009e2958c15ff9290d571bf9459e93b19765c6801ddeccadbb160a1e",`
  `"confirmations": 392076,`
  `"height": 100000,`
  `"version": 2,`
  `"merkleroot": "d574f343976d8e70d91cb278d21044dd8a396019e6db70755a0a50e4783dba38",`
  `"time": 1376123972,`
  `"nonce": 1005240617,`
  `"bits": "1c00f127",`
  `"difficulty": 271.75767393,`
  `"previousblockhash": "000000004956cc2edd1a8caa05eacfa3c69f4c490bfc9ace820257834115ab35",`
  `"nextblockhash": "0000000000629d100db387f37d0f37c51118f250fb0946310a8c37316cbc4028"`
`}`| [Return to Overview](#MethodOverview)
+*** +
+ +| | | +|---|---| +|Method|getchaintips| +|Parameters|None| +|Description|Returns information about all known tips in the block tree, including the main chain as well as orphaned branches| +|Returns|`(A json object array)`
`height`: `(numeric)` The height of the chain tip.
`hash`: `(string)` The block hash of the chain tip.
`branchlen`: `(numeric)` Returns zero for main chain. Otherwise is the length of branch connecting the tip to the main chain.
`status`: `(string)` Status of the chain. Returns "active" for the main chain.`| +|Example Return|`["{"height": 1, "hash": "78b945a390c561cf8b9ccf0598be15d7d85c67022bf71083c0b0bd8042fc30d7", "branchlen": 1, "status": "valid-fork"}, {"height": 1, "hash": "584c830a4783c6331e59cb984686cfec14bccc596fe8bbd1660b90cda359b42a", "branchlen": 0, "status": "active"}"]`| +[Return to Overview](#MethodOverview)
+ ***
From fc99e96b595f3798c3fd391d244f14c931c2c26c Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Sat, 12 Nov 2022 20:34:53 +0900 Subject: [PATCH 0784/1056] rpcclient, integration: Add test for getchaintips call rpcclient now support calling the getchaintips rpc call. getchaintips_test.go adds test for the getchaintips rpc call. The test includes hard-coded blocks which the test will feed the node via rpc and it'll check that the returned chain tips from the getchaintips call are chaintips that we expect to be returned. --- integration/getchaintips_test.go | 350 +++++++++++++++++++++++++++++++ rpcclient/chain.go | 38 ++++ 2 files changed, 388 insertions(+) create mode 100644 integration/getchaintips_test.go diff --git a/integration/getchaintips_test.go b/integration/getchaintips_test.go new file mode 100644 index 0000000000..1570ba740c --- /dev/null +++ b/integration/getchaintips_test.go @@ -0,0 +1,350 @@ +package integration + +import ( + "encoding/hex" + "fmt" + "testing" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/integration/rpctest" + "github.com/stretchr/testify/require" +) + +func getBlockFromString(t *testing.T, hexStr string) *btcutil.Block { + t.Helper() + + serializedBlock, err := hex.DecodeString(hexStr) + if err != nil { + t.Fatalf("couldn't decode hex string of %s", hexStr) + } + + block, err := btcutil.NewBlockFromBytes(serializedBlock) + if err != nil { + t.Fatalf("couldn't make a new block from bytes. "+ + "Decoded hex string: %s", hexStr) + } + + return block +} + +// compareMultipleChainTips checks that all the expected chain tips are included in got chain tips and +// verifies that the got chain tip matches the expected chain tip. +func compareMultipleChainTips(t *testing.T, gotChainTips, expectedChainTips []*btcjson.GetChainTipsResult) error { + if len(gotChainTips) != len(expectedChainTips) { + return fmt.Errorf("Expected %d chaintips but got %d", len(expectedChainTips), len(gotChainTips)) + } + + gotChainTipsMap := make(map[string]btcjson.GetChainTipsResult) + for _, gotChainTip := range gotChainTips { + gotChainTipsMap[gotChainTip.Hash] = *gotChainTip + } + + for _, expectedChainTip := range expectedChainTips { + gotChainTip, found := gotChainTipsMap[expectedChainTip.Hash] + if !found { + return fmt.Errorf("Couldn't find expected chaintip with hash %s", expectedChainTip.Hash) + } + + require.Equal(t, gotChainTip, *expectedChainTip) + } + + return nil +} + +func TestGetChainTips(t *testing.T) { + // block1Hex is a block that builds on top of the regtest genesis block. + // Has blockhash of "36c056247e8c0589f6307995e4e13acf2b2b79cad9ecd5a4eeab2131ed0ecde5". + block1Hex := "0000002006226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf18891" + + "0f71881025ae0d41ce8748b79ac40e5f3197af3bb83a594def7943aff0fce504c638ea6d63f" + + "fff7f2000000000010200000000010100000000000000000000000000000000000000000000" + + "00000000000000000000ffffffff025100ffffffff0200f2052a010000001600149b0f9d020" + + "8b3b425246e16830562a63bf1c701180000000000000000266a24aa21a9ede2f61c3f71d1de" + + "fd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000" + + "000000000000000000000000000000000000000000000000000" + + // block2Hex is a block that builds on top of block1Hex. + // Has blockhash of "664b51334782a4ad16e8471b530dcd0027c75b8c25187b41dfc85ecd353295c6". + block2Hex := "00000020e5cd0eed3121abeea4d5ecd9ca792b2bcf3ae1e4957930f689058c7e2456c0" + + "362a78a11b875d31af2ea493aa5b6b623e0d481f11e69f7147ab974be9da087f3e24696f63f" + + "fff7f2001000000010200000000010100000000000000000000000000000000000000000000" + + "00000000000000000000ffffffff025200ffffffff0200f2052a0100000016001470fea1feb" + + "4969c1f237753ae29c0217c6637835c0000000000000000266a24aa21a9ede2f61c3f71d1de" + + "fd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000" + + "000000000000000000000000000000000000000000000000000" + + // block3Hex is a block that builds on top of block2Hex. + // Has blockhash of "17a5c5cb90ecde5a46dd195d434eea46b653e35e4517070eade429db3ac83944". + block3Hex := "00000020c6953235cd5ec8df417b18258c5bc72700cd0d531b47e816ada4824733514b" + + "66c3ad4d567a36c20df07ea0b7fce1e4b4ee5be3eaf0b946b0ae73f3a74d47f0cf99696f63f" + + "fff7f2000000000010200000000010100000000000000000000000000000000000000000000" + + "00000000000000000000ffffffff025300ffffffff0200f2052a010000001600140e835869b" + + "154f647d11376634b5e8c785e7d21060000000000000000266a24aa21a9ede2f61c3f71d1de" + + "fd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000" + + "000000000000000000000000000000000000000000000000000" + + // block4Hex is a block that builds on top of block3Hex. + // Has blockhash of "7b357f3073c4397d6d069a32a09141c32560f3c62233ca138eb5e03c5991f45c". + block4Hex := "000000204439c83adb29e4ad0e0717455ee353b646ea4e435d19dd465adeec90cbc5a5" + + "17ab639a5dd622e90f5f9feffc1c7c28f47a2caf85c21d7dd52cd223a7164619e37a6a6f63f" + + "fff7f2004000000010200000000010100000000000000000000000000000000000000000000" + + "00000000000000000000ffffffff025400ffffffff0200f2052a01000000160014a157c74b4" + + "42a3e11b45cf5273f8c0c032c5a40ed0000000000000000266a24aa21a9ede2f61c3f71d1de" + + "fd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000" + + "000000000000000000000000000000000000000000000000000" + + // block2aHex is a block that builds on top of block1Hex. + // Has blockhash of "5181a4e34cc23ed95c69749dedf4cc7ebd659243bc1683372f8940c8cd8f9b68". + block2aHex := "00000020e5cd0eed3121abeea4d5ecd9ca792b2bcf3ae1e4957930f689058c7e2456c" + + "036f7d4ebe524260c9b6c2b5e3d105cad0b7ddfaeaa29971363574fc1921a3f2f7ad66b6f63" + + "ffff7f200100000001020000000001010000000000000000000000000000000000000000000" + + "000000000000000000000ffffffff025200ffffffff0200f2052a0100000016001466fca22d" + + "0e4679d119ea1e127c984746a1f7e66c0000000000000000266a24aa21a9ede2f61c3f71d1d" + + "efd3fa999dfa36953755c690689799962b48bebd836974e8cf9012000000000000000000000" + + "0000000000000000000000000000000000000000000000000000" + + // block3aHex is a block that builds on top of block2aHex. + // Has blockhash of "0b0216936d1a5c01362256d06a9c9a2b13768fa2f2748549a71008af36dd167f". + block3aHex := "00000020689b8fcdc840892f378316bc439265bd7eccf4ed9d74695cd93ec24ce3a48" + + "15161a430ce5cae955b1254b753bc95854d942947855d3ae59002de9773b7fe65fdf16b6f63" + + "ffff7f200100000001020000000001010000000000000000000000000000000000000000000" + + "000000000000000000000ffffffff025300ffffffff0200f2052a0100000016001471da0afb" + + "883c228b18af6bd0cabc471aebe8d1750000000000000000266a24aa21a9ede2f61c3f71d1d" + + "efd3fa999dfa36953755c690689799962b48bebd836974e8cf9012000000000000000000000" + + "0000000000000000000000000000000000000000000000000000" + + // block4aHex is a block that builds on top of block3aHex. + // Has blockhash of "65a00a026eaa83f6e7a7f4a920faa090f3f9d3565a56df2362db2ab2fa14ccec". + block4aHex := "000000207f16dd36af0810a7498574f2a28f76132b9a9c6ad0562236015c1a6d93160" + + "20b951fa5ee5072d88d6aef9601999307dbd8d96dad067b80bfe04afe81c7a8c21beb706f63" + + "ffff7f200000000001020000000001010000000000000000000000000000000000000000000" + + "000000000000000000000ffffffff025400ffffffff0200f2052a01000000160014fd1f118c" + + "95a712b8adef11c3cc0643bcb6b709f10000000000000000266a24aa21a9ede2f61c3f71d1d" + + "efd3fa999dfa36953755c690689799962b48bebd836974e8cf9012000000000000000000000" + + "0000000000000000000000000000000000000000000000000000" + + // block5aHex is a block that builds on top of block4aHex. + // Has blockhash of "5c8814bc034a4c37fa5ccdc05e09b45a771bd7505d68092f21869a912737ee10". + block5aHex := "00000020eccc14fab22adb6223df565a56d3f9f390a0fa20a9f4a7e7f683aa6e020aa" + + "0656331bd4fcd3db611de7fbf72ef3dff0b85b244b5a983d5c0270e728214f67f9aaa766f63" + + "ffff7f200600000001020000000001010000000000000000000000000000000000000000000" + + "000000000000000000000ffffffff025500ffffffff0200f2052a0100000016001438335896" + + "ad1d087e3541436a5b293c0d23ad27e60000000000000000266a24aa21a9ede2f61c3f71d1d" + + "efd3fa999dfa36953755c690689799962b48bebd836974e8cf9012000000000000000000000" + + "0000000000000000000000000000000000000000000000000000" + + // block4bHex is a block that builds on top of block3aHex. + // Has blockhash of "130458e795cc46f2759195e92737426fb0ada2a07f98434551ffb7500b23c161". + block4bHex := "000000207f16dd36af0810a7498574f2a28f76132b9a9c6ad0562236015c1a6d93160" + + "20b14f9ce93d0144c383fea72f408b06b268a1523a029b825a1edfa15b367f6db2cfd7d6f63" + + "ffff7f200200000001020000000001010000000000000000000000000000000000000000000" + + "000000000000000000000ffffffff025400ffffffff0200f2052a0100000016001405b5ba2d" + + "1e549c4c84a623de3575948d3ef8a27f0000000000000000266a24aa21a9ede2f61c3f71d1d" + + "efd3fa999dfa36953755c690689799962b48bebd836974e8cf9012000000000000000000000" + + "0000000000000000000000000000000000000000000000000000" + + // Set up regtest chain. + r, err := rpctest.New(&chaincfg.RegressionNetParams, nil, nil, "") + if err != nil { + t.Fatal("TestGetChainTips fail. Unable to create primary harness: ", err) + } + if err := r.SetUp(true, 0); err != nil { + t.Fatalf("TestGetChainTips fail. Unable to setup test chain: %v", err) + } + defer r.TearDown() + + // Immediately call getchaintips after setting up regtest. + gotChainTips, err := r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + // We expect a single genesis block. + expectedChainTips := []*btcjson.GetChainTipsResult{ + { + Height: 0, + Hash: chaincfg.RegressionNetParams.GenesisHash.String(), + BranchLen: 0, + Status: "active", + }, + } + err = compareMultipleChainTips(t, gotChainTips, expectedChainTips) + if err != nil { + t.Fatalf("TestGetChainTips fail. Error: %v", err) + } + + // Submit 4 blocks. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2 -> 3 -> 4 + blockStrings := []string{block1Hex, block2Hex, block3Hex, block4Hex} + for _, blockString := range blockStrings { + block := getBlockFromString(t, blockString) + err = r.Client.SubmitBlock(block, nil) + if err != nil { + t.Fatal(err) + } + } + + gotChainTips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + expectedChainTips = []*btcjson.GetChainTipsResult{ + { + Height: 4, + Hash: getBlockFromString(t, blockStrings[len(blockStrings)-1]).Hash().String(), + BranchLen: 0, + Status: "active", + }, + } + err = compareMultipleChainTips(t, gotChainTips, expectedChainTips) + if err != nil { + t.Fatalf("TestGetChainTips fail. Error: %v", err) + } + + // Submit 2 blocks that don't build on top of the current active tip. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2 -> 3 -> 4 (active) + // \ -> 2a -> 3a (valid-fork) + blockStrings = []string{block2aHex, block3aHex} + for _, blockString := range blockStrings { + block := getBlockFromString(t, blockString) + err = r.Client.SubmitBlock(block, nil) + if err != nil { + t.Fatal(err) + } + } + + gotChainTips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + expectedChainTips = []*btcjson.GetChainTipsResult{ + { + Height: 4, + Hash: getBlockFromString(t, block4Hex).Hash().String(), + BranchLen: 0, + Status: "active", + }, + { + Height: 3, + Hash: getBlockFromString(t, block3aHex).Hash().String(), + BranchLen: 2, + Status: "valid-fork", + }, + } + err = compareMultipleChainTips(t, gotChainTips, expectedChainTips) + if err != nil { + t.Fatalf("TestGetChainTips fail. Error: %v", err) + } + + // Submit a single block that don't build on top of the current active tip. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2 -> 3 -> 4 (active) + // \ -> 2a -> 3a -> 4a (valid-fork) + block := getBlockFromString(t, block4aHex) + err = r.Client.SubmitBlock(block, nil) + if err != nil { + t.Fatal(err) + } + + gotChainTips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + expectedChainTips = []*btcjson.GetChainTipsResult{ + { + Height: 4, + Hash: getBlockFromString(t, block4Hex).Hash().String(), + BranchLen: 0, + Status: "active", + }, + { + Height: 4, + Hash: getBlockFromString(t, block4aHex).Hash().String(), + BranchLen: 3, + Status: "valid-fork", + }, + } + err = compareMultipleChainTips(t, gotChainTips, expectedChainTips) + if err != nil { + t.Fatalf("TestGetChainTips fail. Error: %v", err) + } + + // Submit a single block that changes the active branch to 5a. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2 -> 3 -> 4 (valid-fork) + // \ -> 2a -> 3a -> 4a -> 5a (active) + block = getBlockFromString(t, block5aHex) + err = r.Client.SubmitBlock(block, nil) + if err != nil { + t.Fatal(err) + } + gotChainTips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + expectedChainTips = []*btcjson.GetChainTipsResult{ + { + Height: 4, + Hash: getBlockFromString(t, block4Hex).Hash().String(), + BranchLen: 3, + Status: "valid-fork", + }, + { + Height: 5, + Hash: getBlockFromString(t, block5aHex).Hash().String(), + BranchLen: 0, + Status: "active", + }, + } + err = compareMultipleChainTips(t, gotChainTips, expectedChainTips) + if err != nil { + t.Fatalf("TestGetChainTips fail. Error: %v", err) + } + + // Submit a single block that builds on top of 3a. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2 -> 3 -> 4 (valid-fork) + // \ -> 2a -> 3a -> 4a -> 5a (active) + // \ -> 4b (valid-fork) + block = getBlockFromString(t, block4bHex) + err = r.Client.SubmitBlock(block, nil) + if err != nil { + t.Fatal(err) + } + gotChainTips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + expectedChainTips = []*btcjson.GetChainTipsResult{ + { + Height: 4, + Hash: getBlockFromString(t, block4Hex).Hash().String(), + BranchLen: 3, + Status: "valid-fork", + }, + { + Height: 5, + Hash: getBlockFromString(t, block5aHex).Hash().String(), + BranchLen: 0, + Status: "active", + }, + { + Height: 4, + Hash: getBlockFromString(t, block4bHex).Hash().String(), + BranchLen: 1, + Status: "valid-fork", + }, + } + + err = compareMultipleChainTips(t, gotChainTips, expectedChainTips) + if err != nil { + t.Fatalf("TestGetChainTips fail. Error: %v", err) + } +} diff --git a/rpcclient/chain.go b/rpcclient/chain.go index a97543fd3c..b21665991f 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -685,6 +685,44 @@ func (c *Client) GetBlockHeaderVerbose(blockHash *chainhash.Hash) (*btcjson.GetB return c.GetBlockHeaderVerboseAsync(blockHash).Receive() } +// FutureGetChainTipsResult is a future promise to deliver the result of a +// GetChainTips RPC invocation (or an applicable error). +type FutureGetChainTipsResult chan *Response + +// Receive waits for the Response promised by the future and returns the +// data structure of all the chain tips the node is aware of. +func (r FutureGetChainTipsResult) Receive() ([]*btcjson.GetChainTipsResult, error) { + res, err := ReceiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal result as a string. + var chainTips []*btcjson.GetChainTipsResult + err = json.Unmarshal(res, &chainTips) + if err != nil { + return nil, err + } + + return chainTips, nil +} + +// GetChainTipsAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See GetChainTips for the blocking version and more details. +func (c *Client) GetChainTipsAsync() FutureGetChainTipsResult { + cmd := btcjson.NewGetChainTipsCmd() + return c.SendCmd(cmd) +} + +// GetChainTips returns a slice of data structure with information about all the +// current chain tips that this node is aware of. +func (c *Client) GetChainTips() ([]*btcjson.GetChainTipsResult, error) { + return c.GetChainTipsAsync().Receive() +} + // FutureGetMempoolEntryResult is a future promise to deliver the result of a // GetMempoolEntryAsync RPC invocation (or an applicable error). type FutureGetMempoolEntryResult chan *Response From 7f0fb2ad3bd69fe092a17b4af96ad1cd3d9b7c0b Mon Sep 17 00:00:00 2001 From: 0xEclair <38656355+0xEclair@users.noreply.github.com> Date: Fri, 14 Jul 2023 17:20:42 +0800 Subject: [PATCH 0785/1056] psbt: finalizer add proper sighash flag psbt: fix missing sighash flag when finalizing psbt: test finalizer add proper sighash flag --- btcutil/psbt/finalizer.go | 16 +++++++++++++- btcutil/psbt/psbt_test.go | 46 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/btcutil/psbt/finalizer.go b/btcutil/psbt/finalizer.go index a215aa5948..3c2edd5557 100644 --- a/btcutil/psbt/finalizer.go +++ b/btcutil/psbt/finalizer.go @@ -15,6 +15,7 @@ import ( "bytes" "fmt" + "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" ) @@ -519,7 +520,20 @@ func finalizeTaprootInput(p *Packet, inIndex int) error { switch { // Key spend path. case len(pInput.TaprootKeySpendSig) > 0: - serializedWitness, err = writeWitness(pInput.TaprootKeySpendSig) + sig := pInput.TaprootKeySpendSig + + // Make sure TaprootKeySpendSig is equal to size of signature, + // if not, we assume that sighash flag was appended to the + // signature. + if len(pInput.TaprootKeySpendSig) == schnorr.SignatureSize { + // Append to the signature if flag is not equal to the + // default sighash (that can be omitted). + if pInput.SighashType != txscript.SigHashDefault { + sigHashType := byte(pInput.SighashType) + sig = append(sig, sigHashType) + } + } + serializedWitness, err = writeWitness(sig) // Script spend path. case len(pInput.TaprootScriptSpendSig) > 0: diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go index 6ed154f895..2309b07e40 100644 --- a/btcutil/psbt/psbt_test.go +++ b/btcutil/psbt/psbt_test.go @@ -749,6 +749,52 @@ func TestPsbtExtractor(t *testing.T) { } } +func TestFinalizerAddSigHashFlags(t *testing.T) { + var signedPsbtData = map[string]string{ + "Default": "70736274ff01005e0200000001f1aabce974f1b242b36913f4f8a9f138a8042914dddc4117a578813a4dc32ee10000000000ffffffff017b0a0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1000000000001012b430b0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1011340e80246ac1955def419572514e50e4be47f56ccd51beae41ec80ad30cb77ed59ebca3c38dd8506e1b7c28fafa4bdf7d821464be1ee152416bdaf2c056fb4fb3290117206b1a4876464d6bfc6a7c106dd4c5a0f08af94b45a8200e47e02a7dc6148fd7b00000", + "All": "70736274ff01005e020000000193e988e9eebfe51c0f362741aaab1e0699175c83cfd8087c4a06e24e3b80bc220000000000ffffffff019b0d0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1000000000001012b630e0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad101030401000000011340ee0a03b010e515e38553d4d96c65a9d6092d06756c47c16c5674c3bde6ad0c151f6d4074601f3c2967f12c3b624b4013591e65458a8b5f80b96a613132cee3bb0117206b1a4876464d6bfc6a7c106dd4c5a0f08af94b45a8200e47e02a7dc6148fd7b00000", + "None": "70736274ff01005e02000000013cfe0f5fd1b9a73230b003d336b5e4d7abf3452f6a5c4f266c434648a161eb170000000000ffffffff01d30c0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1000000000001012b9b0d0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad10103040200000001134032573ce8ee8a9afac2008bcb45ce7f96ac95ee7ffad26d10388c97fb87f76f77dc414224ca98b01cbec361488ac29d11e018be412d2725be85dfe5c3fd3b6b4c0117206b1a4876464d6bfc6a7c106dd4c5a0f08af94b45a8200e47e02a7dc6148fd7b00000", + "Single": "70736274ff01005e02000000013173659bb6be7474b8d00efd3b38f2a225f5591bd4edd873170a1e0ff0ef15990000000000ffffffff01630e0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1000000000001012b2b0f0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad101030403000000011340251ce90a8b36cd90bf430f9522772b09bd3ef90039e53cddc5bda6abb61f1c11db6505683d0b7778d4444549ae71df5012edb859251abca13bd819fa6ac9d6ac0117206b1a4876464d6bfc6a7c106dd4c5a0f08af94b45a8200e47e02a7dc6148fd7b00000", + "AllAnyOneCanPay": "70736274ff01005e020000000130ac25ec34af987b9e0518ff05cd491bd2d339660a4bfeea49a580c9233fbd9d0000000000ffffffff010b0c0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1000000000001012bd30c0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad101030481000000011340e86b7ea8d6fc2cbd99b1091c25a2a37b333b5d82ea559579553cf7ba08c0fe3bead26c458f4917a6e069a3712c15f0999adb243603c783133676c1a09cc574b20117206b1a4876464d6bfc6a7c106dd4c5a0f08af94b45a8200e47e02a7dc6148fd7b00000", + "NoneAnyOneCanPay": "70736274ff01005e02000000015499da1d93851a8add52fcab05acab60eaaf16571e0015f678b68775937d11200000000000ffffffff01430b0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1000000000001012b0b0c0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1010304820000000113402d42b46429b739786020e52b69b969468aa69ca40af390ba13441c8e6dc9e53f679c2bd2ff0ef912f48922cd64f4a7bfe7e492e5ecc8603b63e0ea772385faab0117206b1a4876464d6bfc6a7c106dd4c5a0f08af94b45a8200e47e02a7dc6148fd7b00000", + "SingleAnyOneCanPay": "70736274ff01005e02000000011bbe693ee5b3d75a5c8ad190e151c81e5b1ff1090982ea712c375e7d4a6069ce0100000000ffffffff012b0f0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1000000000001012bf30f0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1010304830000000113408e018d0ae9cd730f7eae428a456e920b4ded67c9a7500a82ba25dd23f98418c1f060680daa4352b262fdffab691a4a67fc603352c1d21ace7cc6d83490facde70117206b1a4876464d6bfc6a7c106dd4c5a0f08af94b45a8200e47e02a7dc6148fd7b00000", + } + + var expectedTx = map[string]string{ + "Default": "02000000000101f1aabce974f1b242b36913f4f8a9f138a8042914dddc4117a578813a4dc32ee10000000000ffffffff017b0a0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad10140e80246ac1955def419572514e50e4be47f56ccd51beae41ec80ad30cb77ed59ebca3c38dd8506e1b7c28fafa4bdf7d821464be1ee152416bdaf2c056fb4fb32900000000", + "All": "0200000000010193e988e9eebfe51c0f362741aaab1e0699175c83cfd8087c4a06e24e3b80bc220000000000ffffffff019b0d0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad10141ee0a03b010e515e38553d4d96c65a9d6092d06756c47c16c5674c3bde6ad0c151f6d4074601f3c2967f12c3b624b4013591e65458a8b5f80b96a613132cee3bb0100000000", + "None": "020000000001013cfe0f5fd1b9a73230b003d336b5e4d7abf3452f6a5c4f266c434648a161eb170000000000ffffffff01d30c0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad1014132573ce8ee8a9afac2008bcb45ce7f96ac95ee7ffad26d10388c97fb87f76f77dc414224ca98b01cbec361488ac29d11e018be412d2725be85dfe5c3fd3b6b4c0200000000", + "Single": "020000000001013173659bb6be7474b8d00efd3b38f2a225f5591bd4edd873170a1e0ff0ef15990000000000ffffffff01630e0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad10141251ce90a8b36cd90bf430f9522772b09bd3ef90039e53cddc5bda6abb61f1c11db6505683d0b7778d4444549ae71df5012edb859251abca13bd819fa6ac9d6ac0300000000", + "AllAnyOneCanPay": "0200000000010130ac25ec34af987b9e0518ff05cd491bd2d339660a4bfeea49a580c9233fbd9d0000000000ffffffff010b0c0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad10141e86b7ea8d6fc2cbd99b1091c25a2a37b333b5d82ea559579553cf7ba08c0fe3bead26c458f4917a6e069a3712c15f0999adb243603c783133676c1a09cc574b28100000000", + "NoneAnyOneCanPay": "020000000001015499da1d93851a8add52fcab05acab60eaaf16571e0015f678b68775937d11200000000000ffffffff01430b0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad101412d42b46429b739786020e52b69b969468aa69ca40af390ba13441c8e6dc9e53f679c2bd2ff0ef912f48922cd64f4a7bfe7e492e5ecc8603b63e0ea772385faab8200000000", + "SingleAnyOneCanPay": "020000000001011bbe693ee5b3d75a5c8ad190e151c81e5b1ff1090982ea712c375e7d4a6069ce0100000000ffffffff012b0f0000000000002251209c1f4b7970d790c99b7265b53adec03551708fd7d67db78359f9c472fe642ad101418e018d0ae9cd730f7eae428a456e920b4ded67c9a7500a82ba25dd23f98418c1f060680daa4352b262fdffab691a4a67fc603352c1d21ace7cc6d83490facde78300000000", + } + + for key, signedPsbtStr := range signedPsbtData { + signedPsbtBytes, err := hex.DecodeString(signedPsbtStr) + require.NoErrorf(t, err, "Failed to decode signed psbt string") + + signedPsbt, err := NewFromRawBytes(bytes.NewReader(signedPsbtBytes), false) + require.NoErrorf(t, err, "Failed to parse psbt") + + // There is only one input in each psbt. + err = Finalize(signedPsbt, 0) + require.NoErrorf(t, err, "Failed to finalize") + + tx, err := Extract(signedPsbt) + require.NoErrorf(t, err, "Failed to extract") + + var b bytes.Buffer + err = tx.Serialize(&b) + require.NoErrorf(t, err, "Failed to serialize tx into buffer") + + expectedTxBytes, err := hex.DecodeString(expectedTx[key]) + require.NoErrorf(t, err, "Unable to decode expected tx") + require.Equal(t, expectedTxBytes, b.Bytes()) + } + +} + func TestImportFromCore1(t *testing.T) { // This example #1 was created manually using Bitcoin Core 0.17 regtest. // It contains two inputs, one p2wkh and one p2pkh (non-witness). From 3ba9feeeee77cda47705b601ed06a799ea2e5a3a Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 3 Aug 2023 15:21:11 +0900 Subject: [PATCH 0786/1056] blockchain, btcutil/bloom: BuildMerkleTreeStore returns chainhash.Hash BuildMerkleTreeStore used to return a pointer, but it is changed to return a chainhash.Hash directly. This allows the compiler to make optimizations in some cases and avoids a memory allocation. --- blockchain/merkle.go | 9 ++++----- btcutil/bloom/merkleblock.go | 5 +++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/blockchain/merkle.go b/blockchain/merkle.go index d7e567b283..b8e309ae4d 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -58,14 +58,13 @@ func nextPowerOfTwo(n int) int { // HashMerkleBranches takes two hashes, treated as the left and right tree // nodes, and returns the hash of their concatenation. This is a helper // function used to aid in the generation of a merkle tree. -func HashMerkleBranches(left *chainhash.Hash, right *chainhash.Hash) *chainhash.Hash { +func HashMerkleBranches(left, right *chainhash.Hash) chainhash.Hash { // Concatenate the left and right nodes. var hash [chainhash.HashSize * 2]byte copy(hash[:chainhash.HashSize], left[:]) copy(hash[chainhash.HashSize:], right[:]) - newHash := chainhash.DoubleHashH(hash[:]) - return &newHash + return chainhash.DoubleHashH(hash[:]) } // BuildMerkleTreeStore creates a merkle tree from a slice of transactions, @@ -140,13 +139,13 @@ func BuildMerkleTreeStore(transactions []*btcutil.Tx, witness bool) []*chainhash // hashing the concatenation of the left child with itself. case merkles[i+1] == nil: newHash := HashMerkleBranches(merkles[i], merkles[i]) - merkles[offset] = newHash + merkles[offset] = &newHash // The normal case sets the parent node to the double sha256 // of the concatentation of the left and right children. default: newHash := HashMerkleBranches(merkles[i], merkles[i+1]) - merkles[offset] = newHash + merkles[offset] = &newHash } offset++ } diff --git a/btcutil/bloom/merkleblock.go b/btcutil/bloom/merkleblock.go index 101a8f9194..88dd274f27 100644 --- a/btcutil/bloom/merkleblock.go +++ b/btcutil/bloom/merkleblock.go @@ -6,9 +6,9 @@ package bloom import ( "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // merkleBlock is used to house intermediate information needed to generate a @@ -41,7 +41,8 @@ func (m *merkleBlock) calcHash(height, pos uint32) *chainhash.Hash { } else { right = left } - return blockchain.HashMerkleBranches(left, right) + res := blockchain.HashMerkleBranches(left, right) + return &res } // traverseAndBuild builds a partial merkle tree using a recursive depth-first From 2bb682406730eda6d7306cadf5bfe281e806d42d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 17 Jan 2019 02:14:26 -0800 Subject: [PATCH 0787/1056] blockchain: Add RollingMerkleTree RollingMerkleTree is a much more memory efficient way of calculating the merkle root of a tx commitment inside the bitcoin block header. The current way of calculating the merkle root allocates 2*N elements. With the RollingMerkleTree, we are able to reduce the memory allocated to log2(N). This results in significant memory savings (99.9% in an average block), allowing for a faster block verification. --- blockchain/rolling_merkle.go | 136 +++++++++++++++++++++++ blockchain/rolling_merkle_test.go | 174 ++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 blockchain/rolling_merkle.go create mode 100644 blockchain/rolling_merkle_test.go diff --git a/blockchain/rolling_merkle.go b/blockchain/rolling_merkle.go new file mode 100644 index 0000000000..6233596614 --- /dev/null +++ b/blockchain/rolling_merkle.go @@ -0,0 +1,136 @@ +package blockchain + +import ( + "math/bits" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +// rollingMerkleTreeStore calculates the merkle root by only allocating O(logN) +// memory where N is the total amount of leaves being included in the tree. +type rollingMerkleTreeStore struct { + // roots are where the temporary merkle roots get stored while the + // merkle root is being calculated. + roots []chainhash.Hash + + // numLeaves is the total leaves the store has processed. numLeaves + // is required for the root calculation algorithm to work. + numLeaves uint64 +} + +// newRollingMerkleTreeStore returns a rollingMerkleTreeStore with the roots +// allocated based on the passed in size. +// +// NOTE: If more elements are added in than the passed in size, there will be +// additional allocations which in turn hurts performance. +func newRollingMerkleTreeStore(size uint64) rollingMerkleTreeStore { + var alloc int + if size != 0 { + alloc = bits.Len64(size - 1) + } + return rollingMerkleTreeStore{roots: make([]chainhash.Hash, 0, alloc)} +} + +// add adds a single hash to the merkle tree store. Refer to algorithm 1 "AddOne" in +// the utreexo paper (https://eprint.iacr.org/2019/611.pdf) for the exact algorithm. +func (s *rollingMerkleTreeStore) add(add chainhash.Hash) { + // We can tell where the roots are by looking at the binary representation + // of the numLeaves. Wherever there's a 1, there's a root. + // + // numLeaves of 8 will be '1000' in binary, so there will be one root at + // row 3. numLeaves of 3 will be '11' in binary, so there's two roots. One at + // row 0 and one at row 1. Row 0 is the leaf row. + // + // In this loop below, we're looking for these roots by checking if there's + // a '1', starting from the LSB. If there is a '1', we'll hash the root being + // added with that root until we hit a '0'. + newRoot := add + for h := uint8(0); (s.numLeaves>>h)&1 == 1; h++ { + // Pop off the last root. + var root chainhash.Hash + root, s.roots = s.roots[len(s.roots)-1], s.roots[:len(s.roots)-1] + + // Calculate the hash of the new root and append it. + newRoot = HashMerkleBranches(&root, &newRoot) + } + s.roots = append(s.roots, newRoot) + s.numLeaves++ +} + +// calcMerkleRoot returns the merkle root for the passed in transactions. +func (s *rollingMerkleTreeStore) calcMerkleRoot(adds []*btcutil.Tx, witness bool) chainhash.Hash { + for i := range adds { + // If we're computing a witness merkle root, instead of the + // regular txid, we use the modified wtxid which includes a + // transaction's witness data within the digest. Additionally, + // the coinbase's wtxid is all zeroes. + switch { + case witness && i == 0: + var zeroHash chainhash.Hash + s.add(zeroHash) + case witness: + s.add(*adds[i].WitnessHash()) + default: + s.add(*adds[i].Hash()) + } + } + + // If we only have one leaf, then the hash of that tx is the merkle root. + if s.numLeaves == 1 { + return s.roots[0] + } + + // Add on the last tx again if there's an odd number of txs. + if len(adds) > 0 && len(adds)%2 != 0 { + switch { + case witness: + s.add(*adds[len(adds)-1].WitnessHash()) + default: + s.add(*adds[len(adds)-1].Hash()) + } + } + + // If we still have more than 1 root after adding on the last tx again, + // we need to do the same for the upper rows. + // + // For exmaple, the below tree has 6 leaves. For row 1, you'll need to + // hash 'F' with itself to create 'C' so you have something to hash with + // 'B'. For bigger trees we may need to do the same in rows 2 or 3 as + // well. + // + // row :3 A + // / \ + // row :2 B C + // / \ / \ + // row :1 D E F F + // / \ / \ / \ + // row :0 1 2 3 4 5 6 + for len(s.roots) > 1 { + // If we have to keep adding the last node in the set, bitshift + // the num leaves right by 1. This effectively moves the row up + // for calculation. We do this until we reach a row where there's + // an odd number of leaves. + // + // row :3 A + // / \ + // row :2 B C D + // / \ / \ / \ + // row :1 E F G H I J + // / \ / \ / \ / \ / \ / \ + // row :0 1 2 3 4 5 6 7 8 9 10 11 12 + // + // In the above tree, 12 leaves were added and there's an odd amount + // of leaves at row 2. Because of this, we'll bitshift right twice. + currentLeaves := s.numLeaves + for h := uint8(0); (currentLeaves>>h)&1 == 0; h++ { + s.numLeaves >>= 1 + } + + // Add the last root again so that it'll get hashed with itself. + h := s.roots[len(s.roots)-1] + s.add(h) + } + + return s.roots[0] +} diff --git a/blockchain/rolling_merkle_test.go b/blockchain/rolling_merkle_test.go new file mode 100644 index 0000000000..e425278bdd --- /dev/null +++ b/blockchain/rolling_merkle_test.go @@ -0,0 +1,174 @@ +package blockchain + +import ( + "testing" + + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/stretchr/testify/require" +) + +func TestRollingMerkleAdd(t *testing.T) { + tests := []struct { + leaves []chainhash.Hash + expectedRoots []chainhash.Hash + expectedNumLeaves uint64 + }{ + // 00 (00 is also a root) + { + leaves: []chainhash.Hash{ + {0x00}, + }, + expectedRoots: []chainhash.Hash{ + {0x00}, + }, + expectedNumLeaves: 1, + }, + + // root + // |---\ + // 00 01 + { + leaves: []chainhash.Hash{ + {0x00}, + {0x01}, + }, + expectedRoots: []chainhash.Hash{ + func() chainhash.Hash { + hash, err := chainhash.NewHashFromStr( + "c2bf026e62af95cd" + + "7b785e2cd5a5f1ec" + + "01fafda85886a8eb" + + "d34482c0b05dc2c2") + require.NoError(t, err) + return *hash + }(), + }, + expectedNumLeaves: 2, + }, + + // root + // |---\ + // 00 01 02 + { + leaves: []chainhash.Hash{ + {0x00}, + {0x01}, + {0x02}, + }, + expectedRoots: []chainhash.Hash{ + func() chainhash.Hash { + hash, err := chainhash.NewHashFromStr( + "c2bf026e62af95cd" + + "7b785e2cd5a5f1ec" + + "01fafda85886a8eb" + + "d34482c0b05dc2c2") + require.NoError(t, err) + return *hash + }(), + {0x02}, + }, + expectedNumLeaves: 3, + }, + + // root + // |-------\ + // br br + // |---\ |---\ + // 00 01 02 03 + { + leaves: []chainhash.Hash{ + {0x00}, + {0x01}, + {0x02}, + {0x03}, + }, + expectedRoots: []chainhash.Hash{ + func() chainhash.Hash { + hash, err := chainhash.NewHashFromStr( + "270714425ea73eb8" + + "5942f0f705788f25" + + "1fefa3f533410a3f" + + "338de46e641082c4") + require.NoError(t, err) + return *hash + }(), + }, + expectedNumLeaves: 4, + }, + + // root + // |-------\ + // br br + // |---\ |---\ + // 00 01 02 03 04 + { + leaves: []chainhash.Hash{ + {0x00}, + {0x01}, + {0x02}, + {0x03}, + {0x04}, + }, + expectedRoots: []chainhash.Hash{ + func() chainhash.Hash { + hash, err := chainhash.NewHashFromStr( + "270714425ea73eb8" + + "5942f0f705788f25" + + "1fefa3f533410a3f" + + "338de46e641082c4") + require.NoError(t, err) + return *hash + }(), + {0x04}, + }, + expectedNumLeaves: 5, + }, + + // root + // |-------\ + // br br root + // |---\ |---\ |---\ + // 00 01 02 03 04 05 + { + leaves: []chainhash.Hash{ + {0x00}, + {0x01}, + {0x02}, + {0x03}, + {0x04}, + {0x05}, + }, + expectedRoots: []chainhash.Hash{ + func() chainhash.Hash { + hash, err := chainhash.NewHashFromStr( + "270714425ea73eb8" + + "5942f0f705788f25" + + "1fefa3f533410a3f" + + "338de46e641082c4") + require.NoError(t, err) + return *hash + }(), + func() chainhash.Hash { + hash, err := chainhash.NewHashFromStr( + "e5c2407ba454ffeb" + + "28cf0c50c5c293a8" + + "4c9a75788f8a8f35" + + "ccb974e606280377") + require.NoError(t, err) + return *hash + }(), + }, + expectedNumLeaves: 6, + }, + } + + for _, test := range tests { + s := newRollingMerkleTreeStore(uint64(len(test.leaves))) + for _, leaf := range test.leaves { + s.add(leaf) + } + + require.Equal(t, s.roots, test.expectedRoots) + require.Equal(t, s.numLeaves, test.expectedNumLeaves) + } +} From 2d23f94002ed9a9d311080abef9d1a3e32dce238 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Thu, 17 Jan 2019 02:13:54 -0800 Subject: [PATCH 0788/1056] blockchain: Add benchmarks for Merkle root calculation --- blockchain/merkle_test.go | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/blockchain/merkle_test.go b/blockchain/merkle_test.go index 1a224586fa..0a9824765e 100644 --- a/blockchain/merkle_test.go +++ b/blockchain/merkle_test.go @@ -5,9 +5,12 @@ package blockchain import ( + "fmt" "testing" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" ) // TestMerkle tests the BuildMerkleTreeStore API. @@ -21,3 +24,81 @@ func TestMerkle(t *testing.T) { "got %v, want %v", calculatedMerkleRoot, wantMerkle) } } + +func makeHashes(size int) []*chainhash.Hash { + var hashes = make([]*chainhash.Hash, size) + for i := range hashes { + hashes[i] = new(chainhash.Hash) + } + return hashes +} + +func makeTxs(size int) []*btcutil.Tx { + var txs = make([]*btcutil.Tx, size) + for i := range txs { + tx := btcutil.NewTx(wire.NewMsgTx(2)) + tx.Hash() + txs[i] = tx + } + return txs +} + +// BenchmarkRollingMerkle benches the RollingMerkleTree while varying the number +// of leaves pushed to the tree. +func BenchmarkRollingMerkle(b *testing.B) { + sizes := []int{ + 1000, + 2000, + 4000, + 8000, + 16000, + 32000, + } + + for _, size := range sizes { + txs := makeTxs(size) + name := fmt.Sprintf("%d", size) + b.Run(name, func(b *testing.B) { + benchmarkRollingMerkle(b, txs) + }) + } +} + +// BenchmarkMerkle benches the BuildMerkleTreeStore while varying the number +// of leaves pushed to the tree. +func BenchmarkMerkle(b *testing.B) { + sizes := []int{ + 1000, + 2000, + 4000, + 8000, + 16000, + 32000, + } + + for _, size := range sizes { + txs := makeTxs(size) + name := fmt.Sprintf("%d", size) + b.Run(name, func(b *testing.B) { + benchmarkMerkle(b, txs) + }) + } +} + +func benchmarkRollingMerkle(b *testing.B, txs []*btcutil.Tx) { + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + CalcMerkleRoot(txs, false) + } +} + +func benchmarkMerkle(b *testing.B, txs []*btcutil.Tx) { + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + BuildMerkleTreeStore(txs, false) + } +} From 025fa65c931d45e35d1c06fcdbbd14a21000204f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 22 Apr 2019 18:28:59 -0700 Subject: [PATCH 0789/1056] blockchain: Add CalcMerkleRoot CalcMerkleRoot uses the rolling merkle root algorithm to calculate the merkle root commitment inside the Bitcoin block header. It allocates significantly less memory than the BuildMerkleTreeStore function that's currently in use (99.9% in an average block with 2000 txs). --- blockchain/merkle.go | 34 ++++++++++++++++++++++++++++++++-- blockchain/merkle_test.go | 13 +++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/blockchain/merkle.go b/blockchain/merkle.go index b8e309ae4d..cb502826ad 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -9,9 +9,9 @@ import ( "fmt" "math" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -85,7 +85,7 @@ func HashMerkleBranches(left, right *chainhash.Hash) chainhash.Hash { // // The above stored as a linear array is as follows: // -// [h1 h2 h3 h4 h12 h34 root] +// [h1 h2 h3 h4 h12 h34 root] // // As the above shows, the merkle root is always the last element in the array. // @@ -153,6 +153,36 @@ func BuildMerkleTreeStore(transactions []*btcutil.Tx, witness bool) []*chainhash return merkles } +// CalcMerkleRoot computes the merkle root over a set of hashed leaves. The +// interior nodes are computed opportunistically as the leaves are added to the +// abstract tree to reduce the total number of allocations. Throughout the +// computation, this computation only requires storing O(log n) interior +// nodes. +// +// This method differs from BuildMerkleTreeStore in that the interior nodes are +// discarded instead of being returned along with the root. CalcMerkleRoot is +// slightly faster than BuildMerkleTreeStore and requires significantly less +// memory and fewer allocations. +// +// A merkle tree is a tree in which every non-leaf node is the hash of its +// children nodes. A diagram depicting how this works for bitcoin transactions +// where h(x) is a double sha256 follows: +// +// root = h1234 = h(h12 + h34) +// / \ +// h12 = h(h1 + h2) h34 = h(h3 + h4) +// / \ / \ +// h1 = h(tx1) h2 = h(tx2) h3 = h(tx3) h4 = h(tx4) +// +// The additional bool parameter indicates if we are generating the merkle tree +// using witness transaction id's rather than regular transaction id's. This +// also presents an additional case wherein the wtxid of the coinbase transaction +// is the zeroHash. +func CalcMerkleRoot(transactions []*btcutil.Tx, witness bool) chainhash.Hash { + s := newRollingMerkleTreeStore(uint64(len(transactions))) + return s.calcMerkleRoot(transactions, witness) +} + // ExtractWitnessCommitment attempts to locate, and return the witness // commitment for a block. The witness commitment is of the form: // SHA256(witness root || witness nonce). The function additionally returns a diff --git a/blockchain/merkle_test.go b/blockchain/merkle_test.go index 0a9824765e..06eb7012a2 100644 --- a/blockchain/merkle_test.go +++ b/blockchain/merkle_test.go @@ -11,17 +11,22 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/stretchr/testify/require" ) // TestMerkle tests the BuildMerkleTreeStore API. func TestMerkle(t *testing.T) { block := btcutil.NewBlock(&Block100000) - merkles := BuildMerkleTreeStore(block.Transactions(), false) - calculatedMerkleRoot := merkles[len(merkles)-1] + calcMerkleRoot := CalcMerkleRoot(block.Transactions(), false) + merkleStoreTree := BuildMerkleTreeStore(block.Transactions(), false) + merkleStoreRoot := merkleStoreTree[len(merkleStoreTree)-1] + + require.Equal(t, *merkleStoreRoot, calcMerkleRoot) + wantMerkle := &Block100000.Header.MerkleRoot - if !wantMerkle.IsEqual(calculatedMerkleRoot) { + if !wantMerkle.IsEqual(&calcMerkleRoot) { t.Errorf("BuildMerkleTreeStore: merkle root mismatch - "+ - "got %v, want %v", calculatedMerkleRoot, wantMerkle) + "got %v, want %v", calcMerkleRoot, wantMerkle) } } From ecfbb7e5d8128e44f74695027605b9e9736993bc Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 22 Apr 2019 18:29:34 -0700 Subject: [PATCH 0790/1056] blockchain, rpctest, mining, main: replace usage of BuildMerkleTreeStore with CalcMerkleRoot --- blockchain/fullblocktests/generate.go | 3 +- blockchain/merkle.go | 3 +- blockchain/validate.go | 7 ++-- integration/rpctest/blockgen.go | 6 +-- mining/mining.go | 53 +++++++++++++-------------- rpcserver.go | 4 +- 6 files changed, 35 insertions(+), 41 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 964986dbcf..8d791a36b7 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -309,8 +309,7 @@ func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash { for _, tx := range txns { utilTxns = append(utilTxns, btcutil.NewTx(tx)) } - merkles := blockchain.BuildMerkleTreeStore(utilTxns, false) - return *merkles[len(merkles)-1] + return blockchain.CalcMerkleRoot(utilTxns, false) } // solveBlock attempts to find a nonce which makes the passed block header hash diff --git a/blockchain/merkle.go b/blockchain/merkle.go index cb502826ad..a1a50a2bd5 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -275,8 +275,7 @@ func ValidateWitnessCommitment(blk *btcutil.Block) error { // the extracted witnessCommitment is equal to: // SHA256(witnessMerkleRoot || witnessNonce). Where witnessNonce is the // coinbase transaction's only witness item. - witnessMerkleTree := BuildMerkleTreeStore(blk.Transactions(), true) - witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1] + witnessMerkleRoot := CalcMerkleRoot(blk.Transactions(), true) var witnessPreimage [chainhash.HashSize * 2]byte copy(witnessPreimage[:], witnessMerkleRoot[:]) diff --git a/blockchain/validate.go b/blockchain/validate.go index 89971e7fd6..90562aaca8 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -527,12 +527,11 @@ func checkBlockSanity(block *btcutil.Block, powLimit *big.Int, timeSource Median // checks. Bitcoind builds the tree here and checks the merkle root // after the following checks, but there is no reason not to check the // merkle root matches here. - merkles := BuildMerkleTreeStore(block.Transactions(), false) - calculatedMerkleRoot := merkles[len(merkles)-1] - if !header.MerkleRoot.IsEqual(calculatedMerkleRoot) { + calcMerkleRoot := CalcMerkleRoot(block.Transactions(), false) + if !header.MerkleRoot.IsEqual(&calcMerkleRoot) { str := fmt.Sprintf("block merkle root is invalid - block "+ "header indicates %v, but calculated value is %v", - header.MerkleRoot, calculatedMerkleRoot) + header.MerkleRoot, calcMerkleRoot) return ruleError(ErrBadMerkleRoot, str) } diff --git a/integration/rpctest/blockgen.go b/integration/rpctest/blockgen.go index a35c66e6ac..07371fb8a1 100644 --- a/integration/rpctest/blockgen.go +++ b/integration/rpctest/blockgen.go @@ -12,12 +12,12 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) // solveBlock attempts to find a nonce which makes the passed block header hash @@ -197,12 +197,12 @@ func CreateBlock(prevBlock *btcutil.Block, inclusionTxs []*btcutil.Tx, _ = mining.AddWitnessCommitment(coinbaseTx, blockTxns) } - merkles := blockchain.BuildMerkleTreeStore(blockTxns, false) + merkleRoot := blockchain.CalcMerkleRoot(blockTxns, false) var block wire.MsgBlock block.Header = wire.BlockHeader{ Version: blockVersion, PrevBlock: *prevHash, - MerkleRoot: *merkles[len(merkles)-1], + MerkleRoot: merkleRoot, Timestamp: ts, Bits: net.PowLimitBits, } diff --git a/mining/mining.go b/mining/mining.go index 4ed61f3f32..6c056c626b 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -11,11 +11,11 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) const ( @@ -420,26 +420,26 @@ func NewBlkTmplGenerator(policy *Policy, params *chaincfg.Params, // // Given the above, a block generated by this function is of the following form: // -// ----------------------------------- -- -- -// | Coinbase Transaction | | | -// |-----------------------------------| | | -// | | | | ----- policy.BlockPrioritySize -// | High-priority Transactions | | | -// | | | | -// |-----------------------------------| | -- -// | | | -// | | | -// | | |--- policy.BlockMaxSize -// | Transactions prioritized by fee | | -// | until <= policy.TxMinFreeFee | | -// | | | -// | | | -// | | | -// |-----------------------------------| | -// | Low-fee/Non high-priority (free) | | -// | transactions (while block size | | -// | <= policy.BlockMinSize) | | -// ----------------------------------- -- +// ----------------------------------- -- -- +// | Coinbase Transaction | | | +// |-----------------------------------| | | +// | | | | ----- policy.BlockPrioritySize +// | High-priority Transactions | | | +// | | | | +// |-----------------------------------| | -- +// | | | +// | | | +// | | |--- policy.BlockMaxSize +// | Transactions prioritized by fee | | +// | until <= policy.TxMinFreeFee | | +// | | | +// | | | +// | | | +// |-----------------------------------| | +// | Low-fee/Non high-priority (free) | | +// | transactions (while block size | | +// | <= policy.BlockMinSize) | | +// ----------------------------------- -- func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*BlockTemplate, error) { // Extend the most recently known best block. best := g.chain.BestSnapshot() @@ -823,12 +823,11 @@ mempoolLoop: } // Create a new block ready to be solved. - merkles := blockchain.BuildMerkleTreeStore(blockTxns, false) var msgBlock wire.MsgBlock msgBlock.Header = wire.BlockHeader{ Version: nextBlockVersion, PrevBlock: best.Hash, - MerkleRoot: *merkles[len(merkles)-1], + MerkleRoot: blockchain.CalcMerkleRoot(blockTxns, false), Timestamp: ts, Bits: reqDifficulty, } @@ -875,9 +874,7 @@ func AddWitnessCommitment(coinbaseTx *btcutil.Tx, // Next, obtain the merkle root of a tree which consists of the // wtxid of all transactions in the block. The coinbase // transaction will have a special wtxid of all zeroes. - witnessMerkleTree := blockchain.BuildMerkleTreeStore(blockTxns, - true) - witnessMerkleRoot := witnessMerkleTree[len(witnessMerkleTree)-1] + witnessMerkleRoot := blockchain.CalcMerkleRoot(blockTxns, true) // The preimage to the witness commitment is: // witnessRoot || coinbaseWitness @@ -953,8 +950,8 @@ func (g *BlkTmplGenerator) UpdateExtraNonce(msgBlock *wire.MsgBlock, blockHeight // Recalculate the merkle root with the updated extra nonce. block := btcutil.NewBlock(msgBlock) - merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false) - msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1] + merkleRoot := blockchain.CalcMerkleRoot(block.Transactions(), false) + msgBlock.Header.MerkleRoot = merkleRoot return nil } diff --git a/rpcserver.go b/rpcserver.go index b917263df5..ed9e1bd809 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1651,8 +1651,8 @@ func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bo // Update the merkle root. block := btcutil.NewBlock(template.Block) - merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false) - template.Block.Header.MerkleRoot = *merkles[len(merkles)-1] + merkleRoot := blockchain.CalcMerkleRoot(block.Transactions(), false) + template.Block.Header.MerkleRoot = merkleRoot } // Set locals for convenience. From 880d9f9026bdcbf459f44b3a2b12eb433266f135 Mon Sep 17 00:00:00 2001 From: wydengyre Date: Thu, 3 Aug 2023 18:46:55 +0100 Subject: [PATCH 0791/1056] schnorr: correct rfc reference in docs The RFC used for deterministic nonce generation is rfc6979, not rfc6679. This commit fixes documentation in two places accordingly. --- btcec/schnorr/signature.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index 8f58d52b4f..dff09128b0 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -283,7 +283,7 @@ func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash // // Note that the set of functional options passed in may modify the // above algorithm. Namely if CustomNonce is used, then steps 6-8 are - // replaced with a process that generates the nonce using rfc6679. If + // replaced with a process that generates the nonce using rfc6979. If // FastSign is passed, then we skip set 14. // NOTE: Steps 1-9 are performed by the caller. @@ -436,7 +436,7 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, // // Note that the set of functional options passed in may modify the // above algorithm. Namely if CustomNonce is used, then steps 6-8 are - // replaced with a process that generates the nonce using rfc6679. If + // replaced with a process that generates the nonce using rfc6979. If // FastSign is passed, then we skip set 14. // Step 1. From f258d0c8d2b17e9c6e54e68aa0585e1db34fdd78 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 24 Jan 2023 15:53:26 +0900 Subject: [PATCH 0792/1056] database/ffldb: Change scanBlockFiles behavior This change is part of the effort to add pruning support to btcd. scanBlockFiles nows supports scanning files from an arbitrary block number. When blocks are pruned, the file number may not start from 0. To account for this, scanBlockFiles now scans and retreives the start and the end block file numbers and scans those files. --- database/ffldb/blockio.go | 72 +++++++++++++++++++++++++++------------ database/ffldb/db.go | 5 ++- 2 files changed, 54 insertions(+), 23 deletions(-) diff --git a/database/ffldb/blockio.go b/database/ffldb/blockio.go index 94d2665e03..2b415a17b0 100644 --- a/database/ffldb/blockio.go +++ b/database/ffldb/blockio.go @@ -15,6 +15,9 @@ import ( "io" "os" "path/filepath" + "sort" + "strconv" + "strings" "sync" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -23,6 +26,10 @@ import ( ) const ( + // blockFileExtension is the extension that's used to store the block + // files on the disk. + blockFileExtension = ".fdb" + // The Bitcoin protocol encodes block height as int32, so max number of // blocks is 2^31. Max block size per the protocol is 32MiB per block. // So the theoretical max at the time this comment was written is 64PiB @@ -32,7 +39,7 @@ const ( // 512MiB each for a total of ~476.84PiB (roughly 7.4 times the current // theoretical max), so there is room for the max block size to grow in // the future. - blockFilenameTemplate = "%09d.fdb" + blockFilenameTemplate = "%09d" + blockFileExtension // maxOpenFiles is the max number of open files to maintain in the // open blocks cache. Note that this does not include the current @@ -713,36 +720,57 @@ func (s *blockStore) handleRollback(oldBlockFileNum, oldBlockOffset uint32) { } // scanBlockFiles searches the database directory for all flat block files to -// find the end of the most recent file. This position is considered the -// current write cursor which is also stored in the metadata. Thus, it is used -// to detect unexpected shutdowns in the middle of writes so the block files -// can be reconciled. -func scanBlockFiles(dbPath string) (int, uint32) { - lastFile := -1 - fileLen := uint32(0) - for i := 0; ; i++ { - filePath := blockFilePath(dbPath, uint32(i)) - st, err := os.Stat(filePath) - if err != nil { - break - } - lastFile = i +// find the first file, last file, and the end of the most recent file. The +// position at the last file is considered the current write cursor which is +// also stored in the metadata. Thus, it is used to detect unexpected shutdowns +// in the middle of writes so the block files can be reconciled. +func scanBlockFiles(dbPath string) (int, int, uint32, error) { + firstFile, lastFile, lastFileLen, err := int(-1), int(-1), uint32(0), error(nil) + + files, err := filepath.Glob(filepath.Join(dbPath, "*"+blockFileExtension)) + if err != nil { + return 0, 0, 0, err + } + sort.Strings(files) - fileLen = uint32(st.Size()) + // Return early if there's no block files. + if len(files) == 0 { + return firstFile, lastFile, lastFileLen, nil } - log.Tracef("Scan found latest block file #%d with length %d", lastFile, - fileLen) - return lastFile, fileLen + // Grab the first and last file's number. + firstFile, err = strconv.Atoi(strings.TrimSuffix(filepath.Base(files[0]), blockFileExtension)) + if err != nil { + return 0, 0, 0, fmt.Errorf("scanBlockFiles error: %v", err) + } + lastFile, err = strconv.Atoi(strings.TrimSuffix(filepath.Base(files[len(files)-1]), blockFileExtension)) + if err != nil { + return 0, 0, 0, fmt.Errorf("scanBlockFiles error: %v", err) + } + + // Get the last file's length. + filePath := blockFilePath(dbPath, uint32(lastFile)) + st, err := os.Stat(filePath) + if err != nil { + return 0, 0, 0, err + } + lastFileLen = uint32(st.Size()) + + log.Tracef("Scan found latest block file #%d with length %d", lastFile, lastFileLen) + + return firstFile, lastFile, lastFileLen, err } // newBlockStore returns a new block store with the current block file number // and offset set and all fields initialized. -func newBlockStore(basePath string, network wire.BitcoinNet) *blockStore { +func newBlockStore(basePath string, network wire.BitcoinNet) (*blockStore, error) { // Look for the end of the latest block to file to determine what the // write cursor position is from the viewpoing of the block files on // disk. - fileNum, fileOff := scanBlockFiles(basePath) + _, fileNum, fileOff, err := scanBlockFiles(basePath) + if err != nil { + return nil, err + } if fileNum == -1 { fileNum = 0 fileOff = 0 @@ -765,5 +793,5 @@ func newBlockStore(basePath string, network wire.BitcoinNet) *blockStore { store.openFileFunc = store.openFile store.openWriteFileFunc = store.openWriteFile store.deleteFileFunc = store.deleteFile - return store + return store, nil } diff --git a/database/ffldb/db.go b/database/ffldb/db.go index b796c3ae92..e8b1ce9f2f 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -2016,7 +2016,10 @@ func openDB(dbPath string, network wire.BitcoinNet, create bool) (database.DB, e // according to the data that is actually on disk. Also create the // database cache which wraps the underlying leveldb database to provide // write caching. - store := newBlockStore(dbPath, network) + store, err := newBlockStore(dbPath, network) + if err != nil { + return nil, convertErr(err.Error(), err) + } cache := newDbCache(ldb, store, defaultCacheSize, defaultFlushSecs) pdb := &db{store: store, cache: cache} From 6d38900304448e5c18a2607cf995fdeae1f62882 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 9 May 2023 11:02:54 +0200 Subject: [PATCH 0793/1056] txscript/engine: add execution stepCallback We add a new stepCallback as optional function closure on the Engine that will be called every time a step has been performed during script execution. It is accessed by calling the NewDebugEngine constructor. This is only meant to be used in debugging. --- txscript/engine.go | 98 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/txscript/engine.go b/txscript/engine.go index 7dfd092eae..30206152b8 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -285,6 +285,33 @@ type Engine struct { witnessProgram []byte inputAmount int64 taprootCtx *taprootExecutionCtx + + // stepCallback is an optional function that will be called every time + // a step has been performed during script execution. + // + // NOTE: This is only meant to be used in debugging, and SHOULD NOT BE + // USED during regular operation. + stepCallback func(*StepInfo) error +} + +// StepInfo houses the current VM state information that is passed back to the +// stepCallback during script execution. +type StepInfo struct { + // ScriptIndex is the index of the script currently being executed by + // the Engine. + ScriptIndex int + + // OpcodeIndex is the index of the next opcode that will be executed. + // In case the execution has completed, the opcode index will be + // incrementet beyond the number of the current script's opcodes. This + // indicates no new script is being executed, and execution is done. + OpcodeIndex int + + // Stack is the Engine's current content on the stack: + Stack [][]byte + + // AltStack is the Engine's current content on the alt stack. + AltStack [][]byte } // hasFlag returns whether the script engine instance has the passed flag set. @@ -1023,6 +1050,17 @@ func (vm *Engine) Step() (done bool, err error) { return false, nil } +// copyStack makes a deep copy of the provided slice. +func copyStack(stk [][]byte) [][]byte { + c := make([][]byte, len(stk)) + for i := range stk { + c[i] = make([]byte, len(stk[i])) + copy(c[i][:], stk[i][:]) + } + + return c +} + // Execute will execute all scripts in the script engine and return either nil // for successful validation or an error if one occurred. func (vm *Engine) Execute() (err error) { @@ -1033,6 +1071,22 @@ func (vm *Engine) Execute() (err error) { return nil } + // If the stepCallback is set, we start by making a call back with the + // initial engine state. + var stepInfo *StepInfo + if vm.stepCallback != nil { + stepInfo = &StepInfo{ + ScriptIndex: vm.scriptIdx, + OpcodeIndex: vm.opcodeIdx, + Stack: copyStack(vm.dstack.stk), + AltStack: copyStack(vm.astack.stk), + } + err := vm.stepCallback(stepInfo) + if err != nil { + return err + } + } + done := false for !done { log.Tracef("%v", newLogClosure(func() string { @@ -1060,6 +1114,31 @@ func (vm *Engine) Execute() (err error) { return dstr + astr })) + + if vm.stepCallback != nil { + scriptIdx := vm.scriptIdx + opcodeIdx := vm.opcodeIdx + + // In case the execution has completed, we keep the + // current script index while increasing the opcode + // index. This is to indicate that no new script is + // being executed. + if done { + scriptIdx = stepInfo.ScriptIndex + opcodeIdx = stepInfo.OpcodeIndex + 1 + } + + stepInfo = &StepInfo{ + ScriptIndex: scriptIdx, + OpcodeIndex: opcodeIdx, + Stack: copyStack(vm.dstack.stk), + AltStack: copyStack(vm.astack.stk), + } + err := vm.stepCallback(stepInfo) + if err != nil { + return err + } + } } return vm.CheckErrorCondition(true) @@ -1549,3 +1628,22 @@ func NewEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, flags ScriptFlags return &vm, nil } + +// NewEngine returns a new script engine with a script execution callback set. +// This is useful for debugging script execution. +func NewDebugEngine(scriptPubKey []byte, tx *wire.MsgTx, txIdx int, + flags ScriptFlags, sigCache *SigCache, hashCache *TxSigHashes, + inputAmount int64, prevOutFetcher PrevOutputFetcher, + stepCallback func(*StepInfo) error) (*Engine, error) { + + vm, err := NewEngine( + scriptPubKey, tx, txIdx, flags, sigCache, hashCache, + inputAmount, prevOutFetcher, + ) + if err != nil { + return nil, err + } + + vm.stepCallback = stepCallback + return vm, nil +} From 5c5bef0308943d18653c3e2fe4e53c8ce1d4c2f0 Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Tue, 1 Aug 2023 14:54:44 +0200 Subject: [PATCH 0794/1056] txscript/engine_debug_test: add TestDebugEngine Add a simple test that make sure the stack and alt stack is correctly set in the callback from script execution. --- txscript/engine_debug_test.go | 178 ++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 txscript/engine_debug_test.go diff --git a/txscript/engine_debug_test.go b/txscript/engine_debug_test.go new file mode 100644 index 0000000000..5ebfe3f3cf --- /dev/null +++ b/txscript/engine_debug_test.go @@ -0,0 +1,178 @@ +// Copyright (c) 2013-2023 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package txscript + +import ( + "testing" + + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/wire" + "github.com/stretchr/testify/require" +) + +// TestDebugEngine checks that the StepCallbck called during debug script +// execution contains the expected data. +func TestDebugEngine(t *testing.T) { + t.Parallel() + + // We'll generate a private key and a signature for the tx. + privKey, err := btcec.NewPrivateKey() + require.NoError(t, err) + + internalKey := privKey.PubKey() + + // We use a simple script that will utilize both the stack and alt + // stack in order to test the step callback, and wrap it in a taproot + // witness script. + builder := NewScriptBuilder() + builder.AddData([]byte{0xab}) + builder.AddOp(OP_TOALTSTACK) + builder.AddData(schnorr.SerializePubKey(internalKey)) + builder.AddOp(OP_CHECKSIG) + builder.AddOp(OP_VERIFY) + builder.AddOp(OP_1) + pkScript, err := builder.Script() + require.NoError(t, err) + + tapLeaf := NewBaseTapLeaf(pkScript) + tapScriptTree := AssembleTaprootScriptTree(tapLeaf) + + ctrlBlock := tapScriptTree.LeafMerkleProofs[0].ToControlBlock( + internalKey, + ) + + tapScriptRootHash := tapScriptTree.RootNode.TapHash() + outputKey := ComputeTaprootOutputKey( + internalKey, tapScriptRootHash[:], + ) + p2trScript, err := PayToTaprootScript(outputKey) + require.NoError(t, err) + + testTx := wire.NewMsgTx(2) + testTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: wire.OutPoint{ + Index: 1, + }, + }) + txOut := &wire.TxOut{ + Value: 1e8, PkScript: p2trScript, + } + testTx.AddTxOut(txOut) + + prevFetcher := NewCannedPrevOutputFetcher( + txOut.PkScript, txOut.Value, + ) + sigHashes := NewTxSigHashes(testTx, prevFetcher) + + sig, err := RawTxInTapscriptSignature( + testTx, sigHashes, 0, txOut.Value, + txOut.PkScript, tapLeaf, + SigHashDefault, privKey, + ) + require.NoError(t, err) + + // Now that we have the sig, we'll make a valid witness + // including the control block. + ctrlBlockBytes, err := ctrlBlock.ToBytes() + require.NoError(t, err) + txCopy := testTx.Copy() + txCopy.TxIn[0].Witness = wire.TxWitness{ + sig, pkScript, ctrlBlockBytes, + } + + expCallback := []StepInfo{ + // First callback is looking at the OP_1 witness version. + { + ScriptIndex: 1, + OpcodeIndex: 0, + Stack: [][]byte{}, + AltStack: [][]byte{}, + }, + // The OP_1 witness version is pushed to stack, + { + ScriptIndex: 1, + OpcodeIndex: 1, + Stack: [][]byte{{0x01}}, + AltStack: [][]byte{}, + }, + // Then the taproot script is being executed, starting with + // only the signature on the stacks. + { + ScriptIndex: 2, + OpcodeIndex: 0, + Stack: [][]byte{sig}, + AltStack: [][]byte{}, + }, + // 0xab is pushed to the stack. + { + ScriptIndex: 2, + OpcodeIndex: 1, + Stack: [][]byte{sig, {0xab}}, + AltStack: [][]byte{}, + }, + // 0xab is moved to the alt stack. + { + ScriptIndex: 2, + OpcodeIndex: 2, + Stack: [][]byte{sig}, + AltStack: [][]byte{{0xab}}, + }, + // The public key is pushed to the stack. + { + ScriptIndex: 2, + OpcodeIndex: 3, + Stack: [][]byte{ + sig, + schnorr.SerializePubKey(internalKey), + }, + AltStack: [][]byte{{0xab}}, + }, + // OP_CHECKSIG is executed, resulting in 0x01 on the stack. + { + ScriptIndex: 2, + OpcodeIndex: 4, + Stack: [][]byte{ + {0x01}, + }, + AltStack: [][]byte{{0xab}}, + }, + // OP_VERIFY pops and checks the top stack element. + { + ScriptIndex: 2, + OpcodeIndex: 5, + Stack: [][]byte{}, + AltStack: [][]byte{{0xab}}, + }, + // A single OP_1 push completes the script execution (note that + // the alt stack is cleared when the script is "done"). + { + ScriptIndex: 2, + OpcodeIndex: 6, + Stack: [][]byte{{0x01}}, + AltStack: [][]byte{}, + }, + } + + stepIndex := 0 + callback := func(s *StepInfo) error { + require.Less( + t, stepIndex, len(expCallback), "unexpected callback", + ) + + require.Equal(t, &expCallback[stepIndex], s) + stepIndex++ + return nil + } + + // Run the debug engine. + vm, err := NewDebugEngine( + txOut.PkScript, txCopy, 0, StandardVerifyFlags, + nil, sigHashes, txOut.Value, prevFetcher, + callback, + ) + require.NoError(t, err) + require.NoError(t, vm.Execute()) +} From ab9338ddbf0543515ce32cb2d112d483bc23680f Mon Sep 17 00:00:00 2001 From: wydengyre Date: Sat, 12 Aug 2023 10:09:27 +0100 Subject: [PATCH 0795/1056] schnorr: bip-340 compliant verification fixes https://github.com/btcsuite/btcd/issues/2017 --- btcec/schnorr/signature.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index dff09128b0..83ab44c743 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -91,10 +91,7 @@ func ParseSignature(sig []byte) (*Signature, error) { return nil, signatureError(ecdsa_schnorr.ErrSigRTooBig, str) } var s btcec.ModNScalar - if overflow := s.SetByteSlice(sig[32:64]); overflow { - str := "invalid signature: s >= group order" - return nil, signatureError(ecdsa_schnorr.ErrSigSTooBig, str) - } + s.SetByteSlice(sig[32:64]) // Return the signature. return NewSignature(&r, &s), nil From 1c0bc470e8a0a295a58492d67c0de1b6c0aafa87 Mon Sep 17 00:00:00 2001 From: wydengyre Date: Tue, 15 Aug 2023 14:58:15 +0100 Subject: [PATCH 0796/1056] schnorr: bip-340 compliant signing fixes https://github.com/btcsuite/btcd/issues/2021 --- btcec/schnorr/signature.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index 83ab44c743..95cad532a0 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -174,10 +174,7 @@ func schnorrVerify(sig *Signature, hash []byte, pubKeyBytes []byte) error { ) var e btcec.ModNScalar - if overflow := e.SetBytes((*[32]byte)(commitment)); overflow != 0 { - str := "hash of (r || P || m) too big" - return signatureError(ecdsa_schnorr.ErrSchnorrHashValue, str) - } + e.SetBytes((*[32]byte)(commitment)) // Negate e here so we can use AddNonConst below to subtract the s*G // point from e*P. From 5c1dd21e793c869cdf81e8fb0dd82f0349931d93 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 24 Jan 2023 16:52:06 +0900 Subject: [PATCH 0797/1056] database/ffldb: Add PruneBlocks to db interface This change is part of the effort to add pruning support to btcd. PruneBlocks will prune the earliest block files until it reaches the given target size. The returned hashes are the hashes of the blocks that were pruned. --- database/ffldb/db.go | 95 ++++++++++++++++++++++++ database/ffldb/driver_test.go | 131 ++++++++++++++++++++++++++++++++++ database/ffldb/export_test.go | 4 +- database/interface.go | 15 ++++ 4 files changed, 244 insertions(+), 1 deletion(-) diff --git a/database/ffldb/db.go b/database/ffldb/db.go index e8b1ce9f2f..f8ac1e07e1 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -1669,6 +1669,101 @@ func (tx *transaction) writePendingAndCommit() error { return tx.db.cache.commitTx(tx) } +// PruneBlocks deletes the block files until it reaches the target size +// (specified in bytes). Throws an error if the target size is below +// the maximum size of a single block file. +// +// This function is part of the database.Tx interface implementation. +func (tx *transaction) PruneBlocks(targetSize uint64) ([]chainhash.Hash, error) { + // Ensure transaction state is valid. + if err := tx.checkClosed(); err != nil { + return nil, err + } + + // Ensure the transaction is writable. + if !tx.writable { + str := "prune blocks requires a writable database transaction" + return nil, makeDbErr(database.ErrTxNotWritable, str, nil) + } + + // Make a local alias for the maxBlockFileSize. + maxSize := uint64(tx.db.store.maxBlockFileSize) + if targetSize < maxSize { + return nil, fmt.Errorf("got target size of %d but it must be greater "+ + "than %d, the max size of a single block file", + targetSize, maxSize) + } + + first, last, lastFileSize, err := scanBlockFiles(tx.db.store.basePath) + if err != nil { + return nil, err + } + + // If we have no files on disk or just a single file on disk, return early. + if first == last { + return nil, nil + } + + // Last file number minus the first file number gives us the count of files + // on disk minus 1. We don't want to count the last file since we can't assume + // that it is of max size. + maxSizeFileCount := last - first + + // If the total size of block files are under the target, return early and + // don't prune. + totalSize := uint64(lastFileSize) + (maxSize * uint64(maxSizeFileCount)) + if totalSize <= targetSize { + return nil, nil + } + + log.Tracef("Using %d more bytes than the target of %d MiB. Pruning files...", + totalSize-targetSize, + targetSize/(1024*1024)) + + deletedFiles := make(map[uint32]struct{}) + + // We use < not <= so that the last file is never deleted. There are other checks in place + // but setting it to < here doesn't hurt. + for i := uint32(first); i < uint32(last); i++ { + err = tx.db.store.deleteFileFunc(i) + if err != nil { + return nil, fmt.Errorf("PruneBlocks: Failed to delete block file "+ + "number %d: %v", i, err) + } + + // Add the file index to the deleted files map so that we can later + // delete the block location index. + deletedFiles[i] = struct{}{} + + // If we're already at or below the target usage, break and don't + // try to delete more files. + totalSize -= maxSize + if totalSize <= targetSize { + break + } + } + + // Delete the indexed block locations for the files that we've just deleted. + var deletedBlockHashes []chainhash.Hash + cursor := tx.blockIdxBucket.Cursor() + for ok := cursor.First(); ok; ok = cursor.Next() { + loc := deserializeBlockLoc(cursor.Value()) + + _, found := deletedFiles[loc.blockFileNum] + if found { + deletedBlockHashes = append(deletedBlockHashes, *(*chainhash.Hash)(cursor.Key())) + err := cursor.Delete() + if err != nil { + return nil, err + } + } + } + + log.Tracef("Finished pruning. Database now at %d bytes", totalSize) + + return deletedBlockHashes, nil +} + // Commit commits all changes that have been made to the root metadata bucket // and all of its sub-buckets to the database cache which is periodically synced // to persistent storage. In addition, it commits all new blocks directly to diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index 29d31eafc4..5b9a7533be 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -5,6 +5,7 @@ package ffldb_test import ( + "bytes" "fmt" "os" "path/filepath" @@ -13,6 +14,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database/ffldb" ) @@ -253,6 +255,135 @@ func TestPersistence(t *testing.T) { } } +// TestPrune tests that the older .fdb files are deleted with a call to prune. +func TestPrune(t *testing.T) { + t.Parallel() + + // Create a new database to run tests against. + dbPath := t.TempDir() + db, err := database.Create(dbType, dbPath, blockDataNet) + if err != nil { + t.Errorf("Failed to create test database (%s) %v", dbType, err) + return + } + defer db.Close() + + blockFileSize := uint64(2048) + + testfn := func(t *testing.T, db database.DB) { + // Load the test blocks and save in the test context for use throughout + // the tests. + blocks, err := loadBlocks(t, blockDataFile, blockDataNet) + if err != nil { + t.Errorf("loadBlocks: Unexpected error: %v", err) + return + } + err = db.Update(func(tx database.Tx) error { + for i, block := range blocks { + err := tx.StoreBlock(block) + if err != nil { + return fmt.Errorf("StoreBlock #%d: unexpected error: "+ + "%v", i, err) + } + } + return nil + }) + if err != nil { + t.Fatal(err) + } + + blockHashMap := make(map[chainhash.Hash][]byte, len(blocks)) + for _, block := range blocks { + bytes, err := block.Bytes() + if err != nil { + t.Fatal(err) + } + blockHashMap[*block.Hash()] = bytes + } + + err = db.Update(func(tx database.Tx) error { + _, err := tx.PruneBlocks(1024) + if err == nil { + return fmt.Errorf("Expected an error when attempting to prune" + + "below the maxFileSize") + } + + _, err = tx.PruneBlocks(0) + if err == nil { + return fmt.Errorf("Expected an error when attempting to prune" + + "below the maxFileSize") + } + + return nil + }) + if err != nil { + t.Fatal(err) + } + + var deletedBlocks []chainhash.Hash + + // This should leave 3 files on disk. + err = db.Update(func(tx database.Tx) error { + deletedBlocks, err = tx.PruneBlocks(blockFileSize * 3) + return err + }) + if err != nil { + t.Fatal(err) + } + + // The only error we can get is a bad pattern error. Since we're hardcoding + // the pattern, we should not have an error at runtime. + files, _ := filepath.Glob(filepath.Join(dbPath, "*.fdb")) + if len(files) != 3 { + t.Fatalf("Expected to find %d files but got %d", + 3, len(files)) + } + + // Check that all the blocks that say were deleted are deleted from the + // block index bucket as well. + err = db.View(func(tx database.Tx) error { + for _, deletedBlock := range deletedBlocks { + _, err := tx.FetchBlock(&deletedBlock) + if dbErr, ok := err.(database.Error); !ok || + dbErr.ErrorCode != database.ErrBlockNotFound { + + return fmt.Errorf("Expected ErrBlockNotFound "+ + "but got %v", dbErr) + } + } + + return nil + }) + if err != nil { + t.Fatal(err) + } + + // Check that the not deleted blocks are present. + for _, deletedBlock := range deletedBlocks { + delete(blockHashMap, deletedBlock) + } + err = db.View(func(tx database.Tx) error { + for hash, wantBytes := range blockHashMap { + gotBytes, err := tx.FetchBlock(&hash) + if err != nil { + return err + } + if !bytes.Equal(gotBytes, wantBytes) { + return fmt.Errorf("got bytes %x, want bytes %x", + gotBytes, wantBytes) + } + } + return nil + }) + if err != nil { + t.Fatal(err) + } + } + ffldb.TstRunWithMaxBlockFileSize(db, uint32(blockFileSize), func() { + testfn(t, db) + }) +} + // TestInterface performs all interfaces tests for this database driver. func TestInterface(t *testing.T) { t.Parallel() diff --git a/database/ffldb/export_test.go b/database/ffldb/export_test.go index 2d8e4d2a2b..cbb6dc9465 100644 --- a/database/ffldb/export_test.go +++ b/database/ffldb/export_test.go @@ -11,7 +11,9 @@ The functions are only exported while the tests are being run. package ffldb -import "github.com/btcsuite/btcd/database" +import ( + "github.com/btcsuite/btcd/database" +) // TstRunWithMaxBlockFileSize runs the passed function with the maximum allowed // file size for the database set to the provided value. The value will be set diff --git a/database/interface.go b/database/interface.go index d4f1d89d2e..789c823a66 100644 --- a/database/interface.go +++ b/database/interface.go @@ -389,6 +389,21 @@ type Tx interface { // implementations. FetchBlockRegions(regions []BlockRegion) ([][]byte, error) + // PruneBlocks deletes the block files until it reaches the target size + // (specificed in bytes). + // + // The interface contract guarantees at least the following errors will + // be returned (other implementation-specific errors are possible): + // - ErrTxNotWritable if attempted against a read-only transaction + // - ErrTxClosed if the transaction has already been closed + // + // NOTE: The data returned by this function is only valid during a + // database transaction. Attempting to access it after a transaction + // has ended results in undefined behavior. This constraint prevents + // additional data copies and allows support for memory-mapped database + // implementations. + PruneBlocks(targetSize uint64) ([]chainhash.Hash, error) + // ****************************************************************** // Methods related to both atomic metadata storage and block storage. // ****************************************************************** From 57ec43fedc30971ffa924d5fc682cf1a79a4f306 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 27 Apr 2023 13:31:14 +0900 Subject: [PATCH 0798/1056] blockchain: Add pruning support This change is part of the effort to add pruning support to btcd. A field for pruning is added and the BlockChain struct is now able to be configured with pruning. Prune is called on every block connect and the prune target field is passed to PruneBlocks func. There's no check to keep the latest 288 blocks to abide by the NODE_NETWORK_LIMITED rule. That'll have to be enforced by the caller creating the BlockChain struct. --- blockchain/chain.go | 30 ++++++++++++++++++++++++++++++ blockchain/chainio.go | 15 +++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index c013ff3b15..3ead971f0d 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -115,6 +115,10 @@ type BlockChain struct { // fields in this struct below this point. chainLock sync.RWMutex + // pruneTarget is the size in bytes the database targets for when the node + // is pruned. + pruneTarget uint64 + // These fields are related to the memory block index. They both have // their own locks, however they are often also protected by the chain // lock to help prevent logic races when blocks are being processed. @@ -600,6 +604,26 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, // Atomically insert info into the database. err = b.db.Update(func(dbTx database.Tx) error { + // If the pruneTarget isn't 0, we should attempt to delete older blocks + // from the database. + if b.pruneTarget != 0 { + // When the total block size is under the prune target, prune blocks is + // a no-op and the deleted hashes are nil. + deletedHashes, err := dbTx.PruneBlocks(b.pruneTarget) + if err != nil { + return err + } + + // Only attempt to delete if we have any deleted blocks. + if len(deletedHashes) != 0 { + // Delete the spend journals of the pruned blocks. + err = dbPruneSpendJournalEntry(dbTx, deletedHashes) + if err != nil { + return err + } + } + } + // Update best block state. err := dbPutBestState(dbTx, state, node.workSum) if err != nil { @@ -1702,6 +1726,11 @@ type Config struct { // This field can be nil if the caller is not interested in using a // signature cache. HashCache *txscript.HashCache + + // Prune specifies the target database usage (in bytes) the database + // will target for with block files. Prune at 0 specifies that no + // blocks will be deleted. + Prune uint64 } // New returns a BlockChain instance using the provided configuration details. @@ -1757,6 +1786,7 @@ func New(config *Config) (*BlockChain, error) { prevOrphans: make(map[chainhash.Hash][]*orphanBlock), warningCaches: newThresholdCaches(vbNumBits), deploymentCaches: newThresholdCaches(chaincfg.DefinedDeployments), + pruneTarget: config.Prune, } // Ensure all the deployments are synchronized with our clock if diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 4914da6859..21f0d5baf1 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -494,6 +494,21 @@ func dbRemoveSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash) erro return spendBucket.Delete(blockHash[:]) } +// dbPruneSpendJournalEntry uses an existing database transaction to remove all +// the spend journal entries for the pruned blocks. +func dbPruneSpendJournalEntry(dbTx database.Tx, blockHashes []chainhash.Hash) error { + spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) + + for _, blockHash := range blockHashes { + err := spendBucket.Delete(blockHash[:]) + if err != nil { + return err + } + } + + return nil +} + // ----------------------------------------------------------------------------- // The unspent transaction output (utxo) set consists of an entry for each // unspent output using a format that is optimized to reduce space using domain From 0212c334ce901991395d973fd900996de3312115 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 26 Jan 2023 14:29:16 +0900 Subject: [PATCH 0799/1056] wire, main: Add SFNodeNetworkLimited flag This change is part of the effort to add pruning support to btcd. Wire now supports the ability to signal NODE_NETWORK_LIMITED which signals to peers that the node is able to serve the last 288 blocks. Since archival nodes have all blocks, they can also signal for NODE_NETWORK_LIMITED. SFNodeNetworkLimited flag is added to the default services. --- server.go | 4 ++-- wire/protocol.go | 22 ++++++++++++++-------- wire/protocol_test.go | 3 ++- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/server.go b/server.go index 5ef2e31942..932363c14f 100644 --- a/server.go +++ b/server.go @@ -44,8 +44,8 @@ import ( const ( // defaultServices describes the default services that are supported by // the server. - defaultServices = wire.SFNodeNetwork | wire.SFNodeBloom | - wire.SFNodeWitness | wire.SFNodeCF + defaultServices = wire.SFNodeNetwork | wire.SFNodeNetworkLimited | + wire.SFNodeBloom | wire.SFNodeWitness | wire.SFNodeCF // defaultRequiredServices describes the default services that are // required to be supported by outbound peers. diff --git a/wire/protocol.go b/wire/protocol.go index 3b414ec3f1..be6fc4adea 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -93,18 +93,23 @@ const ( // SFNode2X is a flag used to indicate a peer is running the Segwit2X // software. SFNode2X + + // SFNodeNetWorkLimited is a flag used to indicate a peer supports serving + // the last 288 blocks. + SFNodeNetworkLimited = 1 << 10 ) // Map of service flags back to their constant names for pretty printing. var sfStrings = map[ServiceFlag]string{ - SFNodeNetwork: "SFNodeNetwork", - SFNodeGetUTXO: "SFNodeGetUTXO", - SFNodeBloom: "SFNodeBloom", - SFNodeWitness: "SFNodeWitness", - SFNodeXthin: "SFNodeXthin", - SFNodeBit5: "SFNodeBit5", - SFNodeCF: "SFNodeCF", - SFNode2X: "SFNode2X", + SFNodeNetwork: "SFNodeNetwork", + SFNodeGetUTXO: "SFNodeGetUTXO", + SFNodeBloom: "SFNodeBloom", + SFNodeWitness: "SFNodeWitness", + SFNodeXthin: "SFNodeXthin", + SFNodeBit5: "SFNodeBit5", + SFNodeCF: "SFNodeCF", + SFNode2X: "SFNode2X", + SFNodeNetworkLimited: "SFNodeNetworkLimited", } // orderedSFStrings is an ordered list of service flags from highest to @@ -118,6 +123,7 @@ var orderedSFStrings = []ServiceFlag{ SFNodeBit5, SFNodeCF, SFNode2X, + SFNodeNetworkLimited, } // String returns the ServiceFlag in human-readable form. diff --git a/wire/protocol_test.go b/wire/protocol_test.go index 60bd0533e5..4a57c30c8c 100644 --- a/wire/protocol_test.go +++ b/wire/protocol_test.go @@ -21,7 +21,8 @@ func TestServiceFlagStringer(t *testing.T) { {SFNodeBit5, "SFNodeBit5"}, {SFNodeCF, "SFNodeCF"}, {SFNode2X, "SFNode2X"}, - {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|SFNodeXthin|SFNodeBit5|SFNodeCF|SFNode2X|0xffffff00"}, + {SFNodeNetworkLimited, "SFNodeNetworkLimited"}, + {0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|SFNodeXthin|SFNodeBit5|SFNodeCF|SFNode2X|SFNodeNetworkLimited|0xfffffb00"}, } t.Logf("Running %d tests", len(tests)) From 02469e16a6b0591dafeafc8a2cd42a973d82781f Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 26 Jan 2023 14:58:57 +0900 Subject: [PATCH 0800/1056] main: Add prune flag This change is part of the effort to add pruning support to btcd. Pruning is now available to the end user via --prune flag. There are checks in place so that the user doesn't go below the minimum prune target of 1536 MiB. The minimum is set so that we keep at least 288 blocks per the requirement for NODE_NETWORK_LIMITED nodes specified by BIP0159. The default value of 0 will disable pruning. --- config.go | 10 ++++++++++ server.go | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/config.go b/config.go index 2d8c67e62d..4597acfec6 100644 --- a/config.go +++ b/config.go @@ -66,6 +66,7 @@ const ( sampleConfigFilename = "sample-btcd.conf" defaultTxIndex = false defaultAddrIndex = false + pruneMinSize = 1536 ) var ( @@ -146,6 +147,7 @@ type config struct { Proxy string `long:"proxy" description:"Connect via SOCKS5 proxy (eg. 127.0.0.1:9050)"` ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` ProxyUser string `long:"proxyuser" description:"Username for proxy server"` + Prune uint64 `long:"prune" description:"Prune already validated blocks from the database. Must specify a target size in MiB (minimum value of 1536, default value of 0 will disable pruning)"` RegressionTest bool `long:"regtest" description:"Use the regression test network"` RejectNonStd bool `long:"rejectnonstd" description:"Reject non-standard transactions regardless of the default settings for the active network."` RejectReplacement bool `long:"rejectreplacement" description:"Reject transactions that attempt to replace existing transactions within the mempool through the Replace-By-Fee (RBF) signaling policy."` @@ -1137,6 +1139,14 @@ func loadConfig() (*config, []string, error) { } } + if cfg.Prune != 0 && cfg.Prune < pruneMinSize { + err := fmt.Errorf("%s: the minimum value for --prune is %d. Got %d", + funcName, pruneMinSize, cfg.Prune) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + // Warn about missing config file only after all other configuration is // done. This prevents the warning on help messages and invalid // options. Note this should go directly before the return. diff --git a/server.go b/server.go index 932363c14f..4e88d36cb3 100644 --- a/server.go +++ b/server.go @@ -2730,6 +2730,9 @@ func newServer(listenAddrs, agentBlacklist, agentWhitelist []string, if cfg.NoCFilters { services &^= wire.SFNodeCF } + if cfg.Prune != 0 { + services &^= wire.SFNodeNetwork + } amgr := addrmgr.New(cfg.DataDir, btcdLookup) @@ -2831,6 +2834,7 @@ func newServer(listenAddrs, agentBlacklist, agentWhitelist []string, SigCache: s.sigCache, IndexManager: indexManager, HashCache: s.hashCache, + Prune: cfg.Prune * 1024 * 1024, }) if err != nil { return nil, err From a1736b42678aab5e2157b98abc3f64df7c0be358 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 2 Mar 2023 15:07:22 +0900 Subject: [PATCH 0801/1056] main: Disable enabling both --prune and --txindex You can have a txindex but with the actual blocks gone, they won't be much of a help. Consider allowing these option to be both on in the future where the txindex is only indexing the non-pruned blocks. --- config.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.go b/config.go index 4597acfec6..f754d70c1c 100644 --- a/config.go +++ b/config.go @@ -1147,6 +1147,14 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } + if cfg.Prune != 0 && cfg.TxIndex { + err := fmt.Errorf("%s: the --prune and --txindex options may "+ + "not be activated at the same time", funcName) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + // Warn about missing config file only after all other configuration is // done. This prevents the warning on help messages and invalid // options. Note this should go directly before the return. From 57903c71c902f757e593266bbb8889bde17debc3 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 3 Apr 2023 11:54:47 +0900 Subject: [PATCH 0802/1056] main: Disable enabling both --prune and --addrindex You can have a addrindex but with the actual blocks gone, they won't be much of a help. Consider allowing these option to be both on in the future where the addrindex is only indexing the non-pruned blocks. --- config.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.go b/config.go index f754d70c1c..67c47dbd6c 100644 --- a/config.go +++ b/config.go @@ -1155,6 +1155,14 @@ func loadConfig() (*config, []string, error) { return nil, nil, err } + if cfg.Prune != 0 && cfg.AddrIndex { + err := fmt.Errorf("%s: the --prune and --addrindex options may "+ + "not be activated at the same time", funcName) + fmt.Fprintln(os.Stderr, err) + fmt.Fprintln(os.Stderr, usageMessage) + return nil, nil, err + } + // Warn about missing config file only after all other configuration is // done. This prevents the warning on help messages and invalid // options. Note this should go directly before the return. From aaedc11887a0347041208f935d544fd861a92430 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 22 Aug 2023 15:49:48 +0900 Subject: [PATCH 0803/1056] database, database/ffldb: add BeenPruned() method This change is part of the effort to add pruning support to btcd. BeenPruned will return true if the database has ever been pruned. This allows for accurate prune status to be reported as well as ux improvements by disallowing the user to accidently remove or enable indexes. --- database/ffldb/db.go | 15 +++++++++++++++ database/ffldb/driver_test.go | 31 +++++++++++++++++++++++++++++++ database/interface.go | 5 +++++ 3 files changed, 51 insertions(+) diff --git a/database/ffldb/db.go b/database/ffldb/db.go index f8ac1e07e1..1751c936a9 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -1764,6 +1764,21 @@ func (tx *transaction) PruneBlocks(targetSize uint64) ([]chainhash.Hash, error) return deletedBlockHashes, nil } +// BeenPruned returns if the block storage has ever been pruned. +// +// This function is part of the database.Tx interface implementation. +func (tx *transaction) BeenPruned() (bool, error) { + first, last, _, err := scanBlockFiles(tx.db.store.basePath) + if err != nil { + return false, err + } + + // If the database is pruned, then the first .fdb will not be there. + // We also check that there isn't just 1 file on disk or if there are + // no files on disk by checking if first != last. + return first != 0 && (first != last), nil +} + // Commit commits all changes that have been made to the root metadata bucket // and all of its sub-buckets to the database cache which is periodically synced // to persistent storage. In addition, it commits all new blocks directly to diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index 5b9a7533be..794e8e1912 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -319,6 +319,21 @@ func TestPrune(t *testing.T) { if err != nil { t.Fatal(err) } + err = db.View(func(tx database.Tx) error { + pruned, err := tx.BeenPruned() + if err != nil { + return err + } + + if pruned { + err = fmt.Errorf("The database hasn't been pruned but " + + "BeenPruned returned true") + } + return err + }) + if err != nil { + t.Fatal(err) + } var deletedBlocks []chainhash.Hash @@ -339,6 +354,22 @@ func TestPrune(t *testing.T) { 3, len(files)) } + err = db.View(func(tx database.Tx) error { + pruned, err := tx.BeenPruned() + if err != nil { + return err + } + + if !pruned { + err = fmt.Errorf("The database has been pruned but " + + "BeenPruned returned false") + } + return err + }) + if err != nil { + t.Fatal(err) + } + // Check that all the blocks that say were deleted are deleted from the // block index bucket as well. err = db.View(func(tx database.Tx) error { diff --git a/database/interface.go b/database/interface.go index 789c823a66..7efc7c55f6 100644 --- a/database/interface.go +++ b/database/interface.go @@ -404,6 +404,11 @@ type Tx interface { // implementations. PruneBlocks(targetSize uint64) ([]chainhash.Hash, error) + // BeenPruned returns if the block storage has ever been pruned. + // + // Implementation specific errors are possible. + BeenPruned() (bool, error) + // ****************************************************************** // Methods related to both atomic metadata storage and block storage. // ****************************************************************** From 56f3463d9d1f1f73ed93eb334c28ad7439416d54 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 23 Aug 2023 00:21:19 +0900 Subject: [PATCH 0804/1056] main: force user to enable pruning if database is already pruned This change is part of the effort to add pruning support to btcd. Allowing the user to not pass in the --prune flag after pruning results in inaccurate reporting of the prune status for getblockchaininfo and for signaling NODE_NETWORK_LIMITED to peers. Anything that relies on cfg.Prune to be accurate is at risk of being incorrect. To solve the current problems and to prevent potential future problems, just force the user to keep the prune flag on like bitcoind. In terms of UX, there isn't that much of a loss since if the user wants to keep more blocks than they previously did, they can just increase the size passed to --prune. --- btcd.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/btcd.go b/btcd.go index 8f85311734..457288b7dd 100644 --- a/btcd.go +++ b/btcd.go @@ -157,6 +157,25 @@ func btcdMain(serverChan chan<- *server) error { return nil } + // Check if the database had previously been pruned. If it had been, it's + // not possible to newly generate the tx index and addr index. + var beenPruned bool + db.View(func(dbTx database.Tx) error { + beenPruned, err = dbTx.BeenPruned() + return err + }) + if err != nil { + btcdLog.Errorf("%v", err) + return err + } + if beenPruned && cfg.Prune == 0 { + err = fmt.Errorf("--prune cannot be disabled as the node has been "+ + "previously pruned. You must delete the files in the datadir: \"%s\" "+ + "and sync from the beginning to disable pruning", cfg.DataDir) + btcdLog.Errorf("%v", err) + return err + } + // The config file is already created if it did not exist and the log // file has already been opened by now so we only need to allow // creating rpc cert and key files if they don't exist. From 47261ef205e606f11cddcce3cc4ce4b4b6f8f9aa Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 22 Aug 2023 15:54:08 +0900 Subject: [PATCH 0805/1056] main: fetch prune status from db for handleGetBlockChainInfo This change is part of the effort to add pruning support to btcd. Now that pruning is allowed in btcd, accurately report the prune status back to the user. --- rpcserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcserver.go b/rpcserver.go index b917263df5..616adcb61e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1200,7 +1200,7 @@ func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan str BestBlockHash: chainSnapshot.Hash.String(), Difficulty: getDifficultyRatio(chainSnapshot.Bits, params), MedianTime: chainSnapshot.MedianTime.Unix(), - Pruned: false, + Pruned: cfg.Prune != 0, SoftForks: &btcjson.SoftForks{ Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription), }, From e27fcac9cd51acb9bd8082b6b74b89204d3130da Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 22 Aug 2023 15:56:24 +0900 Subject: [PATCH 0806/1056] blockchain/indexers: add functions to report init status This change is part of the effort to add pruning support to btcd. The added *Initialized() functions to each of the indexers allow for callers to check if each of the indexes have been created. It's useful for ux improvements where we force the user to manually drop indexes that aren't compatible with pruning when the user enables pruning. --- blockchain/indexers/addrindex.go | 12 ++++++++++++ blockchain/indexers/cfindex.go | 12 ++++++++++++ blockchain/indexers/txindex.go | 12 ++++++++++++ 3 files changed, 36 insertions(+) diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 7e9f36f104..a4db729498 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -991,3 +991,15 @@ func NewAddrIndex(db database.DB, chainParams *chaincfg.Params) *AddrIndex { func DropAddrIndex(db database.DB, interrupt <-chan struct{}) error { return dropIndex(db, addrIndexKey, addrIndexName, interrupt) } + +// AddrIndexInitialized returns true if the address index has been created previously. +func AddrIndexInitialized(db database.DB) bool { + var exists bool + db.View(func(dbTx database.Tx) error { + bucket := dbTx.Metadata().Bucket(addrIndexKey) + exists = bucket != nil + return nil + }) + + return exists +} diff --git a/blockchain/indexers/cfindex.go b/blockchain/indexers/cfindex.go index 21b4bf4632..1af1d0a421 100644 --- a/blockchain/indexers/cfindex.go +++ b/blockchain/indexers/cfindex.go @@ -355,3 +355,15 @@ func NewCfIndex(db database.DB, chainParams *chaincfg.Params) *CfIndex { func DropCfIndex(db database.DB, interrupt <-chan struct{}) error { return dropIndex(db, cfIndexParentBucketKey, cfIndexName, interrupt) } + +// CfIndexInitialized returns true if the cfindex has been created previously. +func CfIndexInitialized(db database.DB) bool { + var exists bool + db.View(func(dbTx database.Tx) error { + bucket := dbTx.Metadata().Bucket(cfIndexParentBucketKey) + exists = bucket != nil + return nil + }) + + return exists +} diff --git a/blockchain/indexers/txindex.go b/blockchain/indexers/txindex.go index f7d4bf60a3..3d4e914677 100644 --- a/blockchain/indexers/txindex.go +++ b/blockchain/indexers/txindex.go @@ -481,3 +481,15 @@ func DropTxIndex(db database.DB, interrupt <-chan struct{}) error { return dropIndex(db, txIndexKey, txIndexName, interrupt) } + +// TxIndexInitialized returns true if the tx index has been created previously. +func TxIndexInitialized(db database.DB) bool { + var exists bool + db.View(func(dbTx database.Tx) error { + bucket := dbTx.Metadata().Bucket(txIndexKey) + exists = bucket != nil + return nil + }) + + return exists +} From f161a31a93e9e721544782d2533e90bf70b74f25 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 22 Aug 2023 16:05:54 +0900 Subject: [PATCH 0807/1056] main: force the user to drop tx and addr indexes for pruning This change is part of the effort to add pruning support to btcd. The addr and tx indexes are not useful when the node is pruned as the actual block data that the indexes point to are gone. If the user had previously enabled them, then explicitly require an action from the user to remove the indexes before letting the user enable pruning. --- btcd.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/btcd.go b/btcd.go index 457288b7dd..3d0dafda79 100644 --- a/btcd.go +++ b/btcd.go @@ -176,6 +176,28 @@ func btcdMain(serverChan chan<- *server) error { return err } + // Enforce removal of txindex and addrindex if user requested pruning. + // This is to require explicit action from the user before removing + // indexes that won't be useful when block files are pruned. + // + // NOTE: The order is important here because dropping the tx index also + // drops the address index since it relies on it. We explicitly make the + // user drop both indexes if --addrindex was enabled previously. + if cfg.Prune != 0 && indexers.AddrIndexInitialized(db) { + err = fmt.Errorf("--prune flag may not be given when the address index " + + "has been initialized. Please drop the address index with the " + + "--dropaddrindex flag before enabling pruning") + btcdLog.Errorf("%v", err) + return err + } + if cfg.Prune != 0 && indexers.TxIndexInitialized(db) { + err = fmt.Errorf("--prune flag may not be given when the transaction index " + + "has been initialized. Please drop the transaction index with the " + + "--droptxindex flag before enabling pruning") + btcdLog.Errorf("%v", err) + return err + } + // The config file is already created if it did not exist and the log // file has already been opened by now so we only need to allow // creating rpc cert and key files if they don't exist. From 8f8040e596aa267c5cbad8a815e872f569cf413b Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 22 Aug 2023 16:09:04 +0900 Subject: [PATCH 0808/1056] main: return error if user requests addr or tx index while pruned This change is part of the effort to add pruning support to btcd. It's not possible to generate the addr or tx indexes from scratch if the block storage had been pruned previously as it's missing the block data. When the user asks to create these indexes, tell them it's not possible and the only way it's possible is if they delete and start anew. --- btcd.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/btcd.go b/btcd.go index 3d0dafda79..0ac2f1bf8e 100644 --- a/btcd.go +++ b/btcd.go @@ -175,6 +175,20 @@ func btcdMain(serverChan chan<- *server) error { btcdLog.Errorf("%v", err) return err } + if beenPruned && cfg.TxIndex { + err = fmt.Errorf("--txindex cannot be enabled as the node has been "+ + "previously pruned. You must delete the files in the datadir: \"%s\" "+ + "and sync from the beginning to enable the desired index", cfg.DataDir) + btcdLog.Errorf("%v", err) + return err + } + if beenPruned && cfg.AddrIndex { + err = fmt.Errorf("--addrindex cannot be enabled as the node has been "+ + "previously pruned. You must delete the files in the datadir: \"%s\" "+ + "and sync from the beginning to enable the desired index", cfg.DataDir) + btcdLog.Errorf("%v", err) + return err + } // Enforce removal of txindex and addrindex if user requested pruning. // This is to require explicit action from the user before removing From 65c729960ae13c9b26aec8c5918b791a66886a04 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 22 Aug 2023 16:12:05 +0900 Subject: [PATCH 0809/1056] main: cfindex related sanity checks when enabled with pruning This change is part of the effort to add pruning support to btcd. cfIndex is a useful index even if the node has been pruned so it's allowed to be enabled together with pruning. However, if the user had disabled cfindex and enabled pruning, it's not possible to generate them. In this case, we tell the user that it's impossible unless the user deletes and start anew. Additionally, if the user had enabled cfindex and also enabled pruning from the start, don't let the user turn the cfindex off without dropping it explicitly. This is to make sure that the user isn't left at an inconsistent state where the cfindex isn't able to catch up to the tip because the blocks have already been pruned. --- btcd.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/btcd.go b/btcd.go index 0ac2f1bf8e..c7f292cbc9 100644 --- a/btcd.go +++ b/btcd.go @@ -189,6 +189,33 @@ func btcdMain(serverChan chan<- *server) error { btcdLog.Errorf("%v", err) return err } + // If we've previously been pruned and the cfindex isn't present, it means that the + // user wants to enable the cfindex after the node has already synced up and been + // pruned. + if beenPruned && !indexers.CfIndexInitialized(db) && !cfg.NoCFilters { + err = fmt.Errorf("compact filters cannot be enabled as the node has been "+ + "previously pruned. You must delete the files in the datadir: \"%s\" "+ + "and sync from the beginning to enable the desired index. You may "+ + "use the --nocfilters flag to start the node up without the compact "+ + "filters", cfg.DataDir) + btcdLog.Errorf("%v", err) + return err + } + // If the user wants to disable the cfindex and is pruned or has enabled pruning, force + // the user to either drop the cfindex manually or restart the node without the --nocfilters + // flag. + if (beenPruned || cfg.Prune != 0) && indexers.CfIndexInitialized(db) && cfg.NoCFilters { + err = fmt.Errorf("--nocfilters flag was given but the compact filters have " + + "previously been enabled on this node and the index data currently " + + "exists in the database. The node has also been previously pruned and " + + "the database would be left in an inconsistent state if the compact " + + "filters don't get indexed now. To disable compact filters, please drop the " + + "index completely with the --dropcfindex flag and restart the node. " + + "To keep the compact filters, restart the node without the --nocfilters " + + "flag") + btcdLog.Errorf("%v", err) + return err + } // Enforce removal of txindex and addrindex if user requested pruning. // This is to require explicit action from the user before removing From 36278166e534fe6ae9420501f57a531b7598e892 Mon Sep 17 00:00:00 2001 From: beerosagos Date: Wed, 23 Aug 2023 11:46:25 +0200 Subject: [PATCH 0810/1056] chainhash: add support to legacy-marshaled hashes Recent commits 1d6e578 and 72ea23e introduced a change in the way Hashes are serialized and deserialized. This change could cause errors in downstream applications that persisted hashes serialized using the previous methods. This introduces support for legacy-serialized hashes unmarshaling and restores the compatibility with previous versions. --- chaincfg/chainhash/hash.go | 20 ++++++++++++++++++++ chaincfg/chainhash/hash_test.go | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/chaincfg/chainhash/hash.go b/chaincfg/chainhash/hash.go index fc059787db..4aa7aeb64c 100644 --- a/chaincfg/chainhash/hash.go +++ b/chaincfg/chainhash/hash.go @@ -118,6 +118,12 @@ func (hash Hash) MarshalJSON() ([]byte, error) { // UnmarshalJSON parses the hash with JSON appropriate string value. func (hash *Hash) UnmarshalJSON(input []byte) error { + // If the first byte indicates an array, the hash could have been marshalled + // using the legacy method and e.g. persisted. + if len(input) > 0 && input[0] == '[' { + return decodeLegacy(hash, input) + } + var sh string err := json.Unmarshal(input, &sh) if err != nil { @@ -217,3 +223,17 @@ func Decode(dst *Hash, src string) error { return nil } + +// decodeLegacy decodes an Hash that has been encoded with the legacy method +// (i.e. represented as a bytes array) to a destination. +func decodeLegacy(dst *Hash, src []byte) error { + var hashBytes []byte + err := json.Unmarshal(src, &hashBytes) + if err != nil { + return err + } + if len(hashBytes) != HashSize { + return ErrHashStrSize + } + return dst.SetBytes(hashBytes) +} diff --git a/chaincfg/chainhash/hash_test.go b/chaincfg/chainhash/hash_test.go index 19f34e3a93..85738a66c3 100644 --- a/chaincfg/chainhash/hash_test.go +++ b/chaincfg/chainhash/hash_test.go @@ -199,6 +199,7 @@ func TestNewHashFromStr(t *testing.T) { // TestHashJsonMarshal tests json marshal and unmarshal. func TestHashJsonMarshal(t *testing.T) { hashStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506" + legacyHashStr := []byte("[6,229,51,253,26,218,134,57,31,63,108,52,50,4,176,210,120,212,170,236,28,11,32,170,39,186,3,0,0,0,0,0]") hash, err := NewHashFromStr(hashStr) if err != nil { @@ -219,4 +220,13 @@ func TestHashJsonMarshal(t *testing.T) { if !hash.IsEqual(&newHash) { t.Errorf("String: wrong hash string - got %v, want %v", newHash.String(), hashStr) } + + err = newHash.UnmarshalJSON(legacyHashStr) + if err != nil { + t.Errorf("Unmarshal legacy json error:%v, hash:%v", err, legacyHashStr) + } + + if !hash.IsEqual(&newHash) { + t.Errorf("String: wrong hash string - got %v, want %v", newHash.String(), hashStr) + } } From 87552ddca789a1becc55b6df23060e0b89311b02 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 30 Aug 2023 18:45:39 +0800 Subject: [PATCH 0811/1056] gitignore: ignore vim files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index a92c3ab39d..460a711bc9 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,6 @@ coverage.txt btcec/coverage.txt btcutil/coverage.txt btcutil/psbt/coverage.txt + +# vim +*.swp From d4f519f5dc05db026882c0597e30eb728df66ddc Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 30 Aug 2023 18:46:48 +0800 Subject: [PATCH 0812/1056] gomod: clean go mod files Resulted from running `go mod tify`. --- btcutil/go.sum | 1 + 1 file changed, 1 insertion(+) diff --git a/btcutil/go.sum b/btcutil/go.sum index 8d35bdaf86..58e469abe6 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -60,6 +60,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From d62d537fb55341c772f8214c2d8a91f147caa44e Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 30 Aug 2023 20:42:16 +0800 Subject: [PATCH 0813/1056] rpcclient: remove redundant params used in `handleSendPostMessage` --- rpcclient/infrastructure.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index fbc43a4568..ef29b826f0 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -761,9 +761,7 @@ out: // handleSendPostMessage handles performing the passed HTTP request, reading the // result, unmarshalling it, and delivering the unmarshalled result to the // provided response channel. -func (c *Client) handleSendPostMessage(jReq *jsonRequest, - shutdown chan struct{}) { - +func (c *Client) handleSendPostMessage(jReq *jsonRequest) { protocol := "http" if !c.config.DisableTLS { protocol = "https" @@ -825,7 +823,7 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest, select { case <-time.After(backoff): - case <-shutdown: + case <-c.shutdown: return } } @@ -893,7 +891,7 @@ out: // is closed. select { case jReq := <-c.sendPostChan: - c.handleSendPostMessage(jReq, c.shutdown) + c.handleSendPostMessage(jReq) case <-c.shutdown: break out @@ -917,7 +915,6 @@ cleanup: } c.wg.Done() log.Tracef("RPC client send handler done for %s", c.config.Host) - } // sendPostRequest sends the passed HTTP request to the RPC server using the From 3a8b851aaf728a2717e422a2bb78c3f45ff88166 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 31 Aug 2023 16:54:23 +0800 Subject: [PATCH 0814/1056] rpcclient: catch shutdown signal when sending requests --- rpcclient/infrastructure.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index ef29b826f0..7192a171e7 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -928,9 +928,13 @@ func (c *Client) sendPostRequest(jReq *jsonRequest) { default: } - log.Tracef("Sending command [%s] with id %d", jReq.method, jReq.id) + select { + case c.sendPostChan <- jReq: + log.Tracef("Sent command [%s] with id %d", jReq.method, jReq.id) - c.sendPostChan <- jReq + case <-c.shutdown: + return + } } // newFutureError returns a new future result channel that already has the From 1012f1e4ba3176c29c18843c01246a9fe1ae5acf Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 25 Sep 2023 18:39:52 +0900 Subject: [PATCH 0815/1056] wire: add NodeNetworkLimitedBlockThreshold const NodeNetworkLimitedBlockThreshold is a constant representing how many blocks from tip a node signaling NODE_NETWORK_LIMITED must serve. --- wire/protocol.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wire/protocol.go b/wire/protocol.go index be6fc4adea..d6618e6f68 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -151,6 +151,12 @@ func (f ServiceFlag) String() string { return s } +const ( + // NodeNetworkLimitedBlockThreshold is the number of blocks that a node + // broadcasting SFNodeNetworkLimited MUST be able to serve from the tip. + NodeNetworkLimitedBlockThreshold = 288 +) + // BitcoinNet represents which bitcoin network a message belongs to. type BitcoinNet uint32 From d3d0682dd3d5743048430b296f534a93033689e1 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 12 Oct 2023 15:24:42 +0900 Subject: [PATCH 0816/1056] integration: add test to check prune status Adds a check to make sure that prune status on getblockchaininfo returns true for pruned nodes. --- integration/prune_test.go | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 integration/prune_test.go diff --git a/integration/prune_test.go b/integration/prune_test.go new file mode 100644 index 0000000000..884862ffb8 --- /dev/null +++ b/integration/prune_test.go @@ -0,0 +1,41 @@ +// Copyright (c) 2023 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// This file is ignored during the regular tests due to the following build tag. +//go:build rpctest +// +build rpctest + +package integration + +import ( + "testing" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/integration/rpctest" +) + +func TestPrune(t *testing.T) { + t.Parallel() + + // Boilerplate code to make a pruned node. + btcdCfg := []string{"--prune=1536"} + r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg, "") + if err != nil { + t.Fatal("unable to create primary harness: ", err) + } + if err := r.SetUp(false, 0); err != nil { + t.Fatalf("unable to setup chain: %v", err) + } + defer r.TearDown() + + // Check that the rpc call for block chain info comes back correctly. + chainInfo, err := r.Client.GetBlockChainInfo() + if err != nil { + t.Fatalf("unable to query for chain info: %v", err) + } + if !chainInfo.Pruned { + t.Fatalf("expected the node to be pruned but the pruned "+ + "boolean was %v", chainInfo.Pruned) + } +} From 520d45e3b19c3533a946fbb6ef1761d496eb6b59 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 16 Oct 2023 16:34:49 +0900 Subject: [PATCH 0817/1056] fixup! integration: add test to check prune status --- integration/prune_test.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/integration/prune_test.go b/integration/prune_test.go index 884862ffb8..ac363cb8ca 100644 --- a/integration/prune_test.go +++ b/integration/prune_test.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/integration/rpctest" + "github.com/stretchr/testify/require" ) func TestPrune(t *testing.T) { @@ -21,19 +22,17 @@ func TestPrune(t *testing.T) { // Boilerplate code to make a pruned node. btcdCfg := []string{"--prune=1536"} r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg, "") - if err != nil { - t.Fatal("unable to create primary harness: ", err) - } + require.NoError(t, err) + if err := r.SetUp(false, 0); err != nil { - t.Fatalf("unable to setup chain: %v", err) + require.NoError(t, err) } - defer r.TearDown() + t.Cleanup(func() { r.TearDown() }) // Check that the rpc call for block chain info comes back correctly. chainInfo, err := r.Client.GetBlockChainInfo() - if err != nil { - t.Fatalf("unable to query for chain info: %v", err) - } + require.NoError(t, err) + if !chainInfo.Pruned { t.Fatalf("expected the node to be pruned but the pruned "+ "boolean was %v", chainInfo.Pruned) From 8677a140eb42dbc4b7f6e801436c26fa2581038e Mon Sep 17 00:00:00 2001 From: Kevin Heavey Date: Fri, 20 Oct 2023 15:54:37 +0400 Subject: [PATCH 0818/1056] fix typos in sighash.go --- txscript/sighash.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/txscript/sighash.go b/txscript/sighash.go index eaae070d5c..7dc19ab5bd 100644 --- a/txscript/sighash.go +++ b/txscript/sighash.go @@ -348,7 +348,7 @@ type taprootSigHashOptions struct { codeSepPos uint32 } -// writeDigestExtensions writes out the sighah mesage extensiosn defined by the +// writeDigestExtensions writes out the sighash message extension defined by the // current active sigHashExtFlags. func (t *taprootSigHashOptions) writeDigestExtensions(w io.Writer) error { switch t.extFlag { @@ -588,7 +588,7 @@ func calcTaprootSignatureHashRaw(sigHashes *TxSigHashes, hType SigHashType, // CalcTaprootSignatureHash computes the sighash digest of a transaction's // taproot-spending input using the new sighash digest algorithm described in -// BIP 341. As the new digest algoriths may require the digest to commit to the +// BIP 341. As the new digest algorithms may require the digest to commit to the // entire prev output, a PrevOutputFetcher argument is required to obtain the // needed information. The TxSigHashes pre-computed sighash midstate MUST be // specified. From ad26585576912588d213dbe973b222fcec621546 Mon Sep 17 00:00:00 2001 From: David Cardenas <47157243+davidcardenasus@users.noreply.github.com> Date: Tue, 17 Oct 2023 02:47:09 -0700 Subject: [PATCH 0819/1056] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 23190babb7..46dcd39508 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ ISC License -Copyright (c) 2013-2022 The btcsuite developers +Copyright (c) 2013-2023 The btcsuite developers Copyright (c) 2015-2016 The Decred developers Permission to use, copy, modify, and distribute this software for any From 1a615550b764bff04465b3ff6acdab8a717ab9f7 Mon Sep 17 00:00:00 2001 From: eugene Date: Tue, 6 Jun 2023 10:35:04 -0400 Subject: [PATCH 0820/1056] blockchain: export CheckSerializedHeight, reduce allocs for cb height parsing Some callers only want to check the coinbase height rather than be given the height. --- blockchain/validate.go | 48 +++++++++++++++++++++++++++++++------ blockchain/validate_test.go | 8 +++---- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/blockchain/validate.go b/blockchain/validate.go index d0dbf6b4dc..438f455428 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -5,6 +5,7 @@ package blockchain import ( + "bytes" "encoding/binary" "fmt" "math" @@ -41,6 +42,10 @@ const ( // baseSubsidy is the starting subsidy amount for mined blocks. This // value is halved every SubsidyHalvingInterval blocks. baseSubsidy = 50 * btcutil.SatoshiPerBitcoin + + // coinbaseHeightAllocSize is the amount of bytes that the + // ScriptBuilder will allocate when validating the coinbase height. + coinbaseHeightAllocSize = 5 ) var ( @@ -610,16 +615,25 @@ func ExtractCoinbaseHeight(coinbaseTx *btcutil.Tx) (int32, error) { return 0, ruleError(ErrMissingCoinbaseHeight, str) } - serializedHeightBytes := make([]byte, 8) - copy(serializedHeightBytes, sigScript[1:serializedLen+1]) - serializedHeight := binary.LittleEndian.Uint64(serializedHeightBytes) + // We use 4 bytes here since it saves us allocations. We use a stack + // allocation rather than a heap allocation here. + var serializedHeightBytes [4]byte + copy(serializedHeightBytes[:], sigScript[1:serializedLen+1]) + + serializedHeight := int32( + binary.LittleEndian.Uint32(serializedHeightBytes[:]), + ) + + if err := compareScript(serializedHeight, sigScript); err != nil { + return 0, err + } - return int32(serializedHeight), nil + return serializedHeight, nil } -// checkSerializedHeight checks if the signature script in the passed +// CheckSerializedHeight checks if the signature script in the passed // transaction starts with the serialized block height of wantHeight. -func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int32) error { +func CheckSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int32) error { serializedHeight, err := ExtractCoinbaseHeight(coinbaseTx) if err != nil { return err @@ -634,6 +648,26 @@ func checkSerializedHeight(coinbaseTx *btcutil.Tx, wantHeight int32) error { return nil } +func compareScript(height int32, script []byte) error { + scriptBuilder := txscript.NewScriptBuilder( + txscript.WithScriptAllocSize(coinbaseHeightAllocSize), + ) + scriptHeight, err := scriptBuilder.AddInt64( + int64(height), + ).Script() + if err != nil { + return err + } + + if !bytes.HasPrefix(script, scriptHeight) { + str := fmt.Sprintf("the coinbase signature script does not "+ + "minimally encode the height %d", height) + return ruleError(ErrBadCoinbaseHeight, str) + } + + return nil +} + // CheckBlockHeaderContext performs several validation checks on the block header // which depend on its position within the block chain. // @@ -787,7 +821,7 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode blockHeight >= b.chainParams.BIP0034Height { coinbaseTx := block.Transactions()[0] - err := checkSerializedHeight(coinbaseTx, blockHeight) + err := CheckSerializedHeight(coinbaseTx, blockHeight) if err != nil { return err } diff --git a/blockchain/validate_test.go b/blockchain/validate_test.go index 1963a41590..ddd59130c1 100644 --- a/blockchain/validate_test.go +++ b/blockchain/validate_test.go @@ -169,7 +169,7 @@ func TestCheckBlockSanity(t *testing.T) { } } -// TestCheckSerializedHeight tests the checkSerializedHeight function with +// TestCheckSerializedHeight tests the CheckSerializedHeight function with // various serialized heights and also does negative tests to ensure errors // and handled properly. func TestCheckSerializedHeight(t *testing.T) { @@ -215,9 +215,9 @@ func TestCheckSerializedHeight(t *testing.T) { msgTx.TxIn[0].SignatureScript = test.sigScript tx := btcutil.NewTx(msgTx) - err := checkSerializedHeight(tx, test.wantHeight) + err := CheckSerializedHeight(tx, test.wantHeight) if reflect.TypeOf(err) != reflect.TypeOf(test.err) { - t.Errorf("checkSerializedHeight #%d wrong error type "+ + t.Errorf("CheckSerializedHeight #%d wrong error type "+ "got: %v <%T>, want: %T", i, err, err, test.err) continue } @@ -225,7 +225,7 @@ func TestCheckSerializedHeight(t *testing.T) { if rerr, ok := err.(RuleError); ok { trerr := test.err.(RuleError) if rerr.ErrorCode != trerr.ErrorCode { - t.Errorf("checkSerializedHeight #%d wrong "+ + t.Errorf("CheckSerializedHeight #%d wrong "+ "error code got: %v, want: %v", i, rerr.ErrorCode, trerr.ErrorCode) continue From 0e795fbbfbd269c05cb8dadafcb10ddd0897ef3a Mon Sep 17 00:00:00 2001 From: 0xEclair <38656355+0xEclair@users.noreply.github.com> Date: Tue, 3 Oct 2023 01:37:12 +0800 Subject: [PATCH 0821/1056] fix: default forward port --- cmd/btcctl/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index 5d99c43e6f..13342e6295 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -143,7 +143,7 @@ func normalizeAddress(addr string, chain *chaincfg.Params, useWallet bool) (stri if useWallet { defaultPort = "38332" } else { - defaultPort = "38332" + defaultPort = "38334" } default: if useWallet { From 208800c5f47e4177bcba4ff7291ed6af74b2bacd Mon Sep 17 00:00:00 2001 From: ClaytonNorthey92 Date: Thu, 26 Oct 2023 09:21:30 -0400 Subject: [PATCH 0822/1056] Added tests for FutureGetBestBlockHashResult.Receive --- rpcclient/chain_test.go | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/rpcclient/chain_test.go b/rpcclient/chain_test.go index e32d547ce3..16344ff9c0 100644 --- a/rpcclient/chain_test.go +++ b/rpcclient/chain_test.go @@ -1,6 +1,9 @@ package rpcclient -import "testing" +import ( + "errors" + "testing" +) // TestUnmarshalGetBlockChainInfoResult ensures that the SoftForks and // UnifiedSoftForks fields of GetBlockChainInfoResult are properly unmarshaled @@ -90,3 +93,39 @@ func TestUnmarshalGetBlockChainInfoResultSoftForks(t *testing.T) { } } } + +func TestFutureGetBlockCountResultReceiveErrors(t *testing.T) { + responseChan := FutureGetBlockCountResult(make(chan *Response)) + response := Response{ + result: []byte{}, + err: errors.New("blah blah something bad happened"), + } + go func() { + responseChan <- &response + }() + + _, err := responseChan.Receive() + if err == nil || err.Error() != "blah blah something bad happened" { + t.Fatalf("unexpected error: %s", err.Error()) + } +} + +func TestFutureGetBlockCountResultReceiveMarshalsResponseCorrectly(t *testing.T) { + responseChan := FutureGetBlockCountResult(make(chan *Response)) + response := Response{ + result: []byte{0x36, 0x36}, + err: nil, + } + go func() { + responseChan <- &response + }() + + res, err := responseChan.Receive() + if err != nil { + t.Fatalf("unexpected error: %s", err.Error()) + } + + if res != 66 { + t.Fatalf("unexpected response: %d (0x%X)", res, res) + } +} From d988b860279428367e621199865bccb1dac32f4d Mon Sep 17 00:00:00 2001 From: ClaytonNorthey92 Date: Thu, 26 Oct 2023 11:23:59 -0400 Subject: [PATCH 0823/1056] Added test for client.GetChainTxStatsAsync() in rpcclient. This sets up a test websocket server to run the tests. Also, ensure these are run within a timeout, since they rely on concurrency --- btcutil/go.sum | 2 + go.mod | 1 + go.sum | 2 + rpcclient/chain_test.go | 121 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+) diff --git a/btcutil/go.sum b/btcutil/go.sum index 58e469abe6..5bd6215f1f 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -34,6 +34,8 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= diff --git a/go.mod b/go.mod index 2e3333acc1..4a05d30857 100644 --- a/go.mod +++ b/go.mod @@ -23,6 +23,7 @@ require ( github.com/aead/siphash v1.0.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect diff --git a/go.sum b/go.sum index 1e39ef3263..e77dfa2f5f 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/rpcclient/chain_test.go b/rpcclient/chain_test.go index 16344ff9c0..cc29f99bfc 100644 --- a/rpcclient/chain_test.go +++ b/rpcclient/chain_test.go @@ -2,9 +2,16 @@ package rpcclient import ( "errors" + "github.com/gorilla/websocket" + "net/http" + "net/http/httptest" + "strings" "testing" + "time" ) +var upgrader = websocket.Upgrader{} + // TestUnmarshalGetBlockChainInfoResult ensures that the SoftForks and // UnifiedSoftForks fields of GetBlockChainInfoResult are properly unmarshaled // when using the expected backend version. @@ -129,3 +136,117 @@ func TestFutureGetBlockCountResultReceiveMarshalsResponseCorrectly(t *testing.T) t.Fatalf("unexpected response: %d (0x%X)", res, res) } } + +func TestClientConnectedToWSServerRunner(t *testing.T) { + type TestTableItem struct { + Name string + TestCase func(t *testing.T) + } + + testTable := []TestTableItem{ + TestTableItem{ + Name: "TestGetChainTxStatsAsyncSuccessTx", + TestCase: func(t *testing.T) { + client, serverReceivedChannel, cleanup := makeClient(t) + defer cleanup() + client.GetChainTxStatsAsync() + + message := <-serverReceivedChannel + if message != "{\"jsonrpc\":\"1.0\",\"method\":\"getchaintxstats\",\"params\":[],\"id\":1}" { + t.Fatalf("received unexpected message: %s", message) + } + }, + }, + TestTableItem{ + Name: "TestGetChainTxStatsAsyncShutdownError", + TestCase: func(t *testing.T) { + client, _, cleanup := makeClient(t) + defer cleanup() + + // a bit of a hack here: since there are multiple places where we read + // from the shutdown channel, and it is not buffered, ensure that a shutdown + // message is sent every time it is read from, this will ensure that + // when client.GetChainTxStatsAsync() gets called, it hits the non-blocking + // read from the shutdown channel + go func() { + type shutdownMessage struct{} + for { + client.shutdown <- shutdownMessage{} + } + }() + + var response *Response = nil + + for response == nil { + respChan := client.GetChainTxStatsAsync() + select { + case response = <-respChan: + default: + } + } + + if response.err == nil || response.err.Error() != "the client has been shutdown" { + t.Fatalf("unexpected error: %s", response.err.Error()) + } + }, + }, + } + + // since these tests rely on concurrency, ensure there is a resonable timeout + // that they should run within + for _, testCase := range testTable { + done := make(chan bool) + + go func() { + t.Run(testCase.Name, testCase.TestCase) + done <- true + }() + + select { + case <-done: + case <-time.After(5 * time.Second): + t.Fatalf("timeout exceeded for: %s", testCase.Name) + } + } +} + +func makeClient(t *testing.T) (*Client, chan string, func()) { + serverReceivedChannel := make(chan string) + s := httptest.NewServer(http.HandlerFunc(makeUpgradeOnConnect(serverReceivedChannel))) + url := strings.TrimPrefix(s.URL, "http://") + + config := ConnConfig{ + DisableTLS: true, + User: "username", + Pass: "password", + Host: url, + } + + client, err := New(&config, nil) + if err != nil { + t.Fatalf("error when creating new client %s", err.Error()) + } + return client, serverReceivedChannel, func() { + s.Close() + } +} + +func makeUpgradeOnConnect(ch chan string) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + c, err := upgrader.Upgrade(w, r, nil) + if err != nil { + return + } + defer c.Close() + for { + _, message, err := c.ReadMessage() + if err != nil { + break + } + + go func() { + ch <- string(message) + }() + } + } +} From d15dd7108765d4ae810dae6c5446b81ee76f3fbf Mon Sep 17 00:00:00 2001 From: ClaytonNorthey92 Date: Mon, 6 Nov 2023 12:08:54 -0500 Subject: [PATCH 0824/1056] added tests for GetBestBlockHashAsync now testing that GetBestBlockHashAsync sends the getbestblockhash command via websocket connection and that the channel returned can be used to send the response when it is received --- rpcclient/chain_test.go | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/rpcclient/chain_test.go b/rpcclient/chain_test.go index cc29f99bfc..de8d3a740e 100644 --- a/rpcclient/chain_test.go +++ b/rpcclient/chain_test.go @@ -6,6 +6,7 @@ import ( "net/http" "net/http/httptest" "strings" + "sync" "testing" "time" ) @@ -190,6 +191,48 @@ func TestClientConnectedToWSServerRunner(t *testing.T) { } }, }, + TestTableItem{ + Name: "TestGetBestBlockHashAsync", + TestCase: func(t *testing.T) { + client, serverReceivedChannel, cleanup := makeClient(t) + defer cleanup() + ch := client.GetBestBlockHashAsync() + + message := <-serverReceivedChannel + if message != "{\"jsonrpc\":\"1.0\",\"method\":\"getbestblockhash\",\"params\":[],\"id\":1}" { + t.Fatalf("received unexpected message: %s", message) + } + + expectedResponse := Response{} + + wg := sync.WaitGroup{} + + wg.Add(1) + go func() { + defer wg.Done() + for { + client.requestLock.Lock() + if client.requestList.Len() > 0 { + r := client.requestList.Back() + r.Value.(*jsonRequest).responseChan <- &expectedResponse + client.requestLock.Unlock() + return + } + client.requestLock.Unlock() + } + }() + + response := <-ch + + if &expectedResponse != response { + t.Fatalf("received unexepcted response") + } + + // ensure the goroutine created in this test exists, + // the test is ran with a timeout + wg.Wait() + }, + }, } // since these tests rely on concurrency, ensure there is a resonable timeout From 375f79dcd098690e4b512301c560d84611d0e254 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Sat, 6 May 2023 01:12:24 +0900 Subject: [PATCH 0825/1056] chainhash: Add DoubleHashRaw DoubleHashRaw provides a simple function for doing double hashes. Since it uses the digest instead of making the caller allocate a byte slice, it can be more memory efficient vs other double hash functions. --- chaincfg/chainhash/hashfuncs.go | 26 +++++++++++++++++++++++++- chaincfg/chainhash/hashfuncs_test.go | 17 +++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/chaincfg/chainhash/hashfuncs.go b/chaincfg/chainhash/hashfuncs.go index bf74f73c39..5be8a4d467 100644 --- a/chaincfg/chainhash/hashfuncs.go +++ b/chaincfg/chainhash/hashfuncs.go @@ -5,7 +5,10 @@ package chainhash -import "crypto/sha256" +import ( + "crypto/sha256" + "io" +) // HashB calculates hash(b) and returns the resulting bytes. func HashB(b []byte) []byte { @@ -31,3 +34,24 @@ func DoubleHashH(b []byte) Hash { first := sha256.Sum256(b) return Hash(sha256.Sum256(first[:])) } + +// DoubleHashRaw calculates hash(hash(w)) where w is the resulting bytes from +// the given serialize function and returns the resulting bytes as a Hash. +func DoubleHashRaw(serialize func(w io.Writer) error) Hash { + // Encode the transaction into the hash. Ignore the error returns + // since the only way the encode could fail is being out of memory + // or due to nil pointers, both of which would cause a run-time panic. + h := sha256.New() + _ = serialize(h) + + // This buf is here because Sum() will append the result to the passed + // in byte slice. Pre-allocating here saves an allocation on the second + // hash as we can reuse it. This allocation also does not escape to the + // heap, saving an allocation. + buf := make([]byte, 0, HashSize) + first := h.Sum(buf) + h.Reset() + h.Write(first) + res := h.Sum(buf) + return *(*Hash)(res) +} diff --git a/chaincfg/chainhash/hashfuncs_test.go b/chaincfg/chainhash/hashfuncs_test.go index bcd6f22200..6b9ff9a97f 100644 --- a/chaincfg/chainhash/hashfuncs_test.go +++ b/chaincfg/chainhash/hashfuncs_test.go @@ -6,6 +6,7 @@ package chainhash import ( "fmt" + "io" "testing" ) @@ -133,4 +134,20 @@ func TestDoubleHashFuncs(t *testing.T) { continue } } + + // Ensure the hash function which accepts a hash.Hash returns the expected + // result when given a hash.Hash that is of type SHA256. + for _, test := range tests { + serialize := func(w io.Writer) error { + w.Write([]byte(test.in)) + return nil + } + hash := DoubleHashRaw(serialize) + h := fmt.Sprintf("%x", hash[:]) + if h != test.out { + t.Errorf("DoubleHashRaw(%q) = %s, want %s", test.in, h, + test.out) + continue + } + } } From a09e7b224a63f00e4347af957efd9985795f1c80 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 7 Nov 2023 10:57:45 +0900 Subject: [PATCH 0826/1056] wire: add HasFlag method --- wire/protocol.go | 5 +++++ wire/protocol_test.go | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/wire/protocol.go b/wire/protocol.go index d6618e6f68..7e2de3deda 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -126,6 +126,11 @@ var orderedSFStrings = []ServiceFlag{ SFNodeNetworkLimited, } +// HasFlag returns a bool indicating if the service has the given flag. +func (f ServiceFlag) HasFlag(s ServiceFlag) bool { + return f&s == s +} + // String returns the ServiceFlag in human-readable form. func (f ServiceFlag) String() string { // No flags are set. diff --git a/wire/protocol_test.go b/wire/protocol_test.go index 4a57c30c8c..eeeffb600a 100644 --- a/wire/protocol_test.go +++ b/wire/protocol_test.go @@ -4,7 +4,11 @@ package wire -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/require" +) // TestServiceFlagStringer tests the stringized output for service flag types. func TestServiceFlagStringer(t *testing.T) { @@ -59,3 +63,19 @@ func TestBitcoinNetStringer(t *testing.T) { } } } + +func TestHasFlag(t *testing.T) { + tests := []struct { + in ServiceFlag + check ServiceFlag + want bool + }{ + {0, SFNodeNetwork, false}, + {SFNodeNetwork | SFNodeNetworkLimited | SFNodeWitness, SFNodeBloom, false}, + {SFNodeNetwork | SFNodeNetworkLimited | SFNodeWitness, SFNodeNetworkLimited, true}, + } + + for _, test := range tests { + require.Equal(t, test.want, test.in.HasFlag(test.check)) + } +} From b4992febff11fefc1940c67edfbcac97b627efd1 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 25 Sep 2023 18:33:58 +0900 Subject: [PATCH 0827/1056] netsync: change isSyncCandidate behavior to include pruned nodes isSyncCandidate is now changed to return true even if the peer is a pruned node if and only if our chaintip is within 288 blocks of the peer. Rationale: Pruned nodes that signal NODE_NETWORK_LIMITED MUST serve 288 blocks from their chaintip. If our chaintip is within that range, this peer can be a sync candidate even if they aren't an archival node. --- netsync/manager.go | 61 ++++++++++++++++++++++++++++++++++++---------- wire/protocol.go | 12 ++++----- 2 files changed, 54 insertions(+), 19 deletions(-) diff --git a/netsync/manager.go b/netsync/manager.go index 523437a0c5..fa3cf3d061 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -397,20 +397,55 @@ func (sm *SyncManager) isSyncCandidate(peer *peerpkg.Peer) bool { if host != "127.0.0.1" && host != "localhost" { return false } - } else { - // The peer is not a candidate for sync if it's not a full - // node. Additionally, if the segwit soft-fork package has - // activated, then the peer must also be upgraded. - segwitActive, err := sm.chain.IsDeploymentActive(chaincfg.DeploymentSegwit) - if err != nil { - log.Errorf("Unable to query for segwit "+ - "soft-fork state: %v", err) - } - nodeServices := peer.Services() - if nodeServices&wire.SFNodeNetwork != wire.SFNodeNetwork || - (segwitActive && !peer.IsWitnessEnabled()) { + + // Candidate if all checks passed. + return true + } + + // If the segwit soft-fork package has activated, then the peer must + // also be upgraded. + segwitActive, err := sm.chain.IsDeploymentActive( + chaincfg.DeploymentSegwit, + ) + if err != nil { + log.Errorf("Unable to query for segwit soft-fork state: %v", + err) + } + + if segwitActive && !peer.IsWitnessEnabled() { + return false + } + + var ( + nodeServices = peer.Services() + fullNode = nodeServices.HasFlag(wire.SFNodeNetwork) + prunedNode = nodeServices.HasFlag(wire.SFNodeNetworkLimited) + ) + + switch { + case fullNode: + // Node is a sync candidate if it has all the blocks. + + case prunedNode: + // Even if the peer is pruned, if they have the node network + // limited flag, they are able to serve 2 days worth of blocks + // from the current tip. Therefore, check if our chaintip is + // within that range. + bestHeight := sm.chain.BestSnapshot().Height + peerLastBlock := peer.LastBlock() + + // bestHeight+1 as we need the peer to serve us the next block, + // not the one we already have. + if bestHeight+1 <= + peerLastBlock-wire.NodeNetworkLimitedBlockThreshold { + return false } + + default: + // If the peer isn't an archival node, and it's not signaling + // NODE_NETWORK_LIMITED, we can't sync off of this node. + return false } // Candidate if all checks passed. @@ -428,7 +463,7 @@ func (sm *SyncManager) handleNewPeerMsg(peer *peerpkg.Peer) { log.Infof("New valid peer %s (%s)", peer, peer.UserAgent()) - // Initialize the peer state + // Initialize the peer state. isSyncCandidate := sm.isSyncCandidate(peer) sm.peerStates[peer] = &peerSyncState{ syncCandidate: isSyncCandidate, diff --git a/wire/protocol.go b/wire/protocol.go index 7e2de3deda..baeec05369 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -60,6 +60,12 @@ const ( AddrV2Version uint32 = 70016 ) +const ( + // NodeNetworkLimitedBlockThreshold is the number of blocks that a node + // broadcasting SFNodeNetworkLimited MUST be able to serve from the tip. + NodeNetworkLimitedBlockThreshold = 288 +) + // ServiceFlag identifies services supported by a bitcoin peer. type ServiceFlag uint64 @@ -156,12 +162,6 @@ func (f ServiceFlag) String() string { return s } -const ( - // NodeNetworkLimitedBlockThreshold is the number of blocks that a node - // broadcasting SFNodeNetworkLimited MUST be able to serve from the tip. - NodeNetworkLimitedBlockThreshold = 288 -) - // BitcoinNet represents which bitcoin network a message belongs to. type BitcoinNet uint32 From f396b3d3d9eddc0cdb4eea29e39ef734e44c89f9 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 17 Nov 2023 16:32:55 +0900 Subject: [PATCH 0828/1056] blockchain: better Ancestor with skiplists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On startup, Ancestor call was taking a lot of time when the node was loading the blockindex onto memory. This change speeds up the Ancestor function significantly and speeds up the node during startup. On testnet3 at blockheight ~2,500,000, the startup was around 30seconds on current main and was 5 seconds with this change. Below is a benchstat result showing the significant speedup. goos: darwin goarch: arm64 pkg: github.com/utreexo/utreexod/blockchain │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ Ancestor-8 120819.301µ ± 5% 7.013µ ± 19% -99.99% (p=0.000 n=10) │ old.txt │ new.txt │ │ B/op │ B/op vs base │ Ancestor-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ¹ all samples are equal │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ Ancestor-8 0.000 ± 0% 0.000 ± 0% ~ (p=1.000 n=10) ¹ ¹ all samples are equal --- blockchain/bench_test.go | 13 +++++++++++ blockchain/blockindex.go | 41 ++++++++++++++++++++++++++++++++-- blockchain/blockindex_test.go | 42 +++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 blockchain/blockindex_test.go diff --git a/blockchain/bench_test.go b/blockchain/bench_test.go index 9ecc834241..db6f415013 100644 --- a/blockchain/bench_test.go +++ b/blockchain/bench_test.go @@ -60,3 +60,16 @@ func BenchmarkUtxoFetchSlices(b *testing.B) { } } } + +func BenchmarkAncestor(b *testing.B) { + height := 1 << 19 + blockNodes := chainedNodes(nil, height) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + blockNodes[len(blockNodes)-1].Ancestor(0) + for j := 0; j <= 19; j++ { + blockNodes[len(blockNodes)-1].Ancestor(1 << j) + } + } +} diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 7412aa1129..ca3235f79f 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -74,6 +74,9 @@ type blockNode struct { // parent is the parent block for this node. parent *blockNode + // ancestor is a block that is more than one block back from this node. + ancestor *blockNode + // hash is the double sha 256 of the block. hash chainhash.Hash @@ -119,6 +122,7 @@ func initBlockNode(node *blockNode, blockHeader *wire.BlockHeader, parent *block node.parent = parent node.height = parent.height + 1 node.workSum = node.workSum.Add(parent.workSum, node.workSum) + node.buildAncestor() } } @@ -150,6 +154,26 @@ func (node *blockNode) Header() wire.BlockHeader { } } +// invertLowestOne turns the lowest 1 bit in the binary representation of a number into a 0. +func invertLowestOne(n int32) int32 { + return n & (n - 1) +} + +// getAncestorHeight returns a suitable ancestor for the node at the given height. +func getAncestorHeight(height int32) int32 { + // We pop off two 1 bits of the height. + // This results in a maximum of 330 steps to go back to an ancestor + // from height 1<<29. + return invertLowestOne(invertLowestOne(height)) +} + +// buildAncestor sets an ancestor for the given blocknode. +func (node *blockNode) buildAncestor() { + if node.parent != nil { + node.ancestor = node.parent.Ancestor(getAncestorHeight(node.height)) + } +} + // Ancestor returns the ancestor block node at the provided height by following // the chain backwards from this node. The returned block will be nil when a // height is requested that is after the height of the passed node or is less @@ -161,9 +185,22 @@ func (node *blockNode) Ancestor(height int32) *blockNode { return nil } + // Traverse back until we find the desired node. n := node - for ; n != nil && n.height != height; n = n.parent { - // Intentionally left blank + for n != nil && n.height != height { + // If there's an ancestor available, use it. Otherwise, just + // follow the parent. + if n.ancestor != nil { + // Calculate the height for this ancestor and + // check if we can take the ancestor skip. + if getAncestorHeight(n.height) >= height { + n = n.ancestor + continue + } + } + + // We couldn't take the ancestor skip so traverse back to the parent. + n = n.parent } return n diff --git a/blockchain/blockindex_test.go b/blockchain/blockindex_test.go new file mode 100644 index 0000000000..cd08969f14 --- /dev/null +++ b/blockchain/blockindex_test.go @@ -0,0 +1,42 @@ +// Copyright (c) 2023 The utreexo developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "math/rand" + "testing" +) + +func TestAncestor(t *testing.T) { + height := 500_000 + blockNodes := chainedNodes(nil, height) + + for i, blockNode := range blockNodes { + // Grab a random node that's a child of this node + // and try to fetch the current blockNode with Ancestor. + randNode := blockNodes[rand.Intn(height-i)+i] + got := randNode.Ancestor(blockNode.height) + + // See if we got the right one. + if got.hash != blockNode.hash { + t.Fatalf("expected ancestor at height %d "+ + "but got a node at height %d", + blockNode.height, got.height) + } + + // Gensis doesn't have ancestors so skip the check below. + if blockNode.height == 0 { + continue + } + + // The ancestors are deterministic so check that this node's + // ancestor is the correct one. + if blockNode.ancestor.height != getAncestorHeight(blockNode.height) { + t.Fatalf("expected anestor at height %d, but it was at %d", + getAncestorHeight(blockNode.height), + blockNode.ancestor.height) + } + } +} From 4171854739fa2590a99c486341209d3aea8404dc Mon Sep 17 00:00:00 2001 From: xiaolou86 <20718693+xiaolou86@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:48:08 +0800 Subject: [PATCH 0829/1056] Fix typos --- blockchain/indexers/addrindex.go | 2 +- blockchain/rolling_merkle.go | 2 +- btcec/schnorr/musig2/context.go | 2 +- btcec/schnorr/musig2/musig2_test.go | 2 +- rpcclient/infrastructure.go | 2 +- wire/netaddressv2.go | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index a4db729498..7eaaab06b7 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -64,7 +64,7 @@ const ( addrKeyTypeWitnessScriptHash = 3 // addrKeyTypeTaprootPubKey is the address type in an address key that - // represnts a pay-to-taproot adress. We use this to denote addresses + // represnts a pay-to-taproot address. We use this to denote addresses // related to the segwit v1 that are encoded in the bech32m format. addrKeyTypeTaprootPubKey = 4 diff --git a/blockchain/rolling_merkle.go b/blockchain/rolling_merkle.go index 6233596614..cd2c2ec7e6 100644 --- a/blockchain/rolling_merkle.go +++ b/blockchain/rolling_merkle.go @@ -94,7 +94,7 @@ func (s *rollingMerkleTreeStore) calcMerkleRoot(adds []*btcutil.Tx, witness bool // If we still have more than 1 root after adding on the last tx again, // we need to do the same for the upper rows. // - // For exmaple, the below tree has 6 leaves. For row 1, you'll need to + // For example, the below tree has 6 leaves. For row 1, you'll need to // hash 'F' with itself to create 'C' so you have something to hash with // 'B'. For bigger trees we may need to do the same in rows 2 or 3 as // well. diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 7ed759cd0a..8f4521502a 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -561,7 +561,7 @@ func (s *Session) Sign(msg [32]byte, return nil, ErrSigningContextReuse // We also need to make sure we have the combined nonce, otherwise this - // funciton was called too early. + // function was called too early. case s.combinedNonce == nil: return nil, ErrCombinedNonceUnavailable } diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index b2101021dd..91dad90b3e 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -365,7 +365,7 @@ func TestMuSigEarlyNonce(t *testing.T) { msg := sha256.Sum256([]byte("let's get taprooty, LN style")) - // If we try to sign before we have the combined nonce, we shoudl get + // If we try to sign before we have the combined nonce, we should get // an error. _, err = session1.Sign(msg) if !errors.Is(err, ErrCombinedNonceUnavailable) { diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 7192a171e7..cf683db0ca 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -832,7 +832,7 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { return } - // We still want to return an error if for any reason the respone + // We still want to return an error if for any reason the response // remains empty. if httpResponse == nil { jReq.responseChan <- &Response{ diff --git a/wire/netaddressv2.go b/wire/netaddressv2.go index 15f7916456..ccad266ace 100644 --- a/wire/netaddressv2.go +++ b/wire/netaddressv2.go @@ -48,7 +48,7 @@ func maxNetAddressV2Payload() uint32 { plen += 1 // The largest address is 512 bytes. Even though it will not be a valid - // address, we should read and ignore it. The preceeding varint to + // address, we should read and ignore it. The preceding varint to // store 512 bytes is 3 bytes long. This gives us a total of 515 bytes. plen += 515 From 6ea604df63ec3c7278bbfb537bad302875bb8140 Mon Sep 17 00:00:00 2001 From: Evan Tedesco Date: Tue, 28 Nov 2023 14:00:54 -0700 Subject: [PATCH 0830/1056] Fix typos on signature.go --- btcec/schnorr/signature.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index 95cad532a0..70f00024f1 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -124,8 +124,7 @@ func schnorrVerify(sig *Signature, hash []byte, pubKeyBytes []byte) error { // 7. Fail if is_infinite(R) // 8. Fail if not hash_even_y(R) // 9. Fail is x(R) != r. - // 10. Return success iff not failure occured before reachign this - // point. + // 10. Return success if failure did not occur before reaching this point. // Step 1. // @@ -238,14 +237,14 @@ func zeroArray(a *[scalarSize]byte) { } } -// schnorrSign generates an BIP-340 signature over the secp256k1 curve for the +// schnorrSign generates a BIP-340 signature over the secp256k1 curve for the // provided hash (which should be the result of hashing a larger message) using // the given nonce and private key. The produced signature is deterministic // (same message, nonce, and key yield the same signature) and canonical. // // WARNING: The hash MUST be 32 bytes and both the nonce and private keys must // NOT be 0. Since this is an internal use function, these preconditions MUST -// be satisified by the caller. +// be satisfied by the caller. func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash []byte, opts *signOptions) (*Signature, error) { @@ -256,7 +255,7 @@ func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash // n = curve order // d = private key // m = message - // a = input randmoness + // a = input randomness // r, s = signature // // 1. d' = int(d) @@ -342,8 +341,8 @@ func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash return sig, nil } -// SignOption is a functional option arguemnt that allows callers to modify the -// way we generate BIP-340 schnorr signatues. +// SignOption is a functional option argument that allows callers to modify the +// way we generate BIP-340 schnorr signatures. type SignOption func(*signOptions) // signOptions houses the set of functional options that can be used to modify @@ -364,7 +363,7 @@ func defaultSignOptions() *signOptions { } // FastSign forces signing to skip the extra verification step at the end. -// Peformance sensitive applications may opt to use this option to speed up the +// Performance sensitive applications may opt to use this option to speed up the // signing operation. func FastSign() SignOption { return func(o *signOptions) { @@ -409,7 +408,7 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, // n = curve order // d = private key // m = message - // a = input randmoness + // a = input randomness // r, s = signature // // 1. d' = int(d) @@ -471,7 +470,7 @@ func Sign(privKey *btcec.PrivateKey, hash []byte, // At this point, we check to see if a CustomNonce has been passed in, // and if so, then we'll deviate from the main routine here by - // generating the nonce value as specifid by BIP-0340. + // generating the nonce value as specified by BIP-0340. if opts.authNonce != nil { // Step 6. // From a4236c5010c13eede059d113233384b30ca7492d Mon Sep 17 00:00:00 2001 From: wydengyre Date: Thu, 12 Oct 2023 16:26:27 +0100 Subject: [PATCH 0831/1056] schnorr: simplify some signing math We reuse the Bytes() function rather than duplicating its logic. --- btcec/schnorr/signature.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index 70f00024f1..9a60e0d8ac 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -302,13 +302,9 @@ func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash // Step 12. // // e = tagged_hash("BIP0340/challenge", bytes(R) || bytes(P) || m) mod n - var rBytes [32]byte - r := &R.X - r.PutBytesUnchecked(rBytes[:]) pBytes := SerializePubKey(pubKey) - commitment := chainhash.TaggedHash( - chainhash.TagBIP0340Challenge, rBytes[:], pBytes, hash, + chainhash.TagBIP0340Challenge, R.X.Bytes()[:], pBytes, hash, ) var e btcec.ModNScalar @@ -324,7 +320,7 @@ func schnorrSign(privKey, nonce *btcec.ModNScalar, pubKey *btcec.PublicKey, hash s := new(btcec.ModNScalar).Mul2(&e, privKey).Add(&k) k.Zero() - sig := NewSignature(r, s) + sig := NewSignature(&R.X, s) // Step 14. // From 7520523a9a54aff213f5455b048a55f818118a84 Mon Sep 17 00:00:00 2001 From: "John C. Vernaleo" Date: Wed, 29 Nov 2023 11:29:53 -0500 Subject: [PATCH 0832/1056] Correct comments in singature.go --- btcec/schnorr/signature.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/btcec/schnorr/signature.go b/btcec/schnorr/signature.go index 9a60e0d8ac..8876a6070d 100644 --- a/btcec/schnorr/signature.go +++ b/btcec/schnorr/signature.go @@ -124,7 +124,7 @@ func schnorrVerify(sig *Signature, hash []byte, pubKeyBytes []byte) error { // 7. Fail if is_infinite(R) // 8. Fail if not hash_even_y(R) // 9. Fail is x(R) != r. - // 10. Return success if failure did not occur before reaching this point. + // 10. Return success iff failure did not occur before reaching this point. // Step 1. // @@ -219,7 +219,7 @@ func schnorrVerify(sig *Signature, hash []byte, pubKeyBytes []byte) error { // Step 10. // - // Return success iff not failure occured before reachign this + // Return success iff failure did not occur before reaching this point. return nil } From 909106575e67a251b04bc47a563eb522bb3e755b Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 8 Dec 2023 10:59:13 +0000 Subject: [PATCH 0833/1056] Update petertodd seed DNS to .net Also, add mainnet seed. --- chaincfg/params.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chaincfg/params.go b/chaincfg/params.go index f11bcf2640..3b38878b4a 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -287,6 +287,7 @@ var MainNetParams = Params{ {"seed.bitcoinstats.com", true}, {"seed.bitnodes.io", false}, {"seed.bitcoin.jonasschnelli.ch", true}, + {"seed.btc.petertodd.net", true}, }, // Chain parameters @@ -541,7 +542,7 @@ var TestNet3Params = Params{ DNSSeeds: []DNSSeed{ {"testnet-seed.bitcoin.jonasschnelli.ch", true}, {"testnet-seed.bitcoin.schildbach.de", false}, - {"seed.tbtc.petertodd.org", true}, + {"seed.tbtc.petertodd.net", true}, {"testnet-seed.bluematt.me", false}, }, From c9cda537091686eeb57190d65cb1a061d0a63f45 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 27 Sep 2022 22:04:18 +0200 Subject: [PATCH 0834/1056] multi: remove use of GO111MODULE The use of the GO111MODULE environment variable doesn't have any effect anymore and hasn't for a couple of versions. The default was set to "on" a while back, so we can remove that variable everywhere. --- Dockerfile | 1 - Makefile | 10 +++++----- README.md | 4 ++-- docs/installation.md | 2 +- docs/update.md | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index e5e349a820..5ed3e63c10 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,6 @@ ARG ARCH=amd64 FROM golang@sha256:c80567372be0d486766593cc722d3401038e2f150a0f6c5c719caa63afb4026a AS build-container ARG ARCH -ENV GO111MODULE=on ADD . /app WORKDIR /app diff --git a/Makefile b/Makefile index 2e967ba0f6..3f228a3d33 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,12 @@ GOACC_BIN := $(GO_BIN)/go-acc LINT_COMMIT := v1.18.0 GOACC_COMMIT := 80342ae2e0fcf265e99e76bcc4efd022c7c3811b -DEPGET := cd /tmp && GO111MODULE=on go get -v -GOBUILD := GO111MODULE=on go build -v -GOINSTALL := GO111MODULE=on go install -v +DEPGET := cd /tmp && go get -v +GOBUILD := go build -v +GOINSTALL := go install -v DEV_TAGS := rpctest -GOTEST_DEV = GO111MODULE=on go test -v -tags=$(DEV_TAGS) -GOTEST := GO111MODULE=on go test -v +GOTEST_DEV = go test -v -tags=$(DEV_TAGS) +GOTEST := go test -v GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*") diff --git a/README.md b/README.md index fabf07698e..f70f3f9145 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ recommended that `GOPATH` is set to a directory in your home directory such as ```bash $ cd $GOPATH/src/github.com/btcsuite/btcd -$ GO111MODULE=on go install -v . ./cmd/... +$ go install -v . ./cmd/... ``` - btcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did @@ -79,7 +79,7 @@ $ GO111MODULE=on go install -v . ./cmd/... ```bash $ cd $GOPATH/src/github.com/btcsuite/btcd $ git pull -$ GO111MODULE=on go install -v . ./cmd/... +$ go install -v . ./cmd/... ``` ## Getting Started diff --git a/docs/installation.md b/docs/installation.md index b340c2f620..f6670bd50a 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -54,7 +54,7 @@ recommended that `GOPATH` is set to a directory in your home directory such as ```bash git clone https://github.com/btcsuite/btcd $GOPATH/src/github.com/btcsuite/btcd cd $GOPATH/src/github.com/btcsuite/btcd -GO111MODULE=on go install -v . ./cmd/... +go install -v . ./cmd/... ``` * btcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did diff --git a/docs/update.md b/docs/update.md index 1fb847cf9f..3e411a628b 100644 --- a/docs/update.md +++ b/docs/update.md @@ -4,5 +4,5 @@ ```bash cd $GOPATH/src/github.com/btcsuite/btcd -git pull && GO111MODULE=on go install -v . ./cmd/... +git pull && go install -v . ./cmd/... ``` From 36637f9ff9a7d355964423ca226adb8b19071c96 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 27 Sep 2022 22:05:39 +0200 Subject: [PATCH 0835/1056] git: add binaries to .gitignore file --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 460a711bc9..5c29ccd9b5 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,10 @@ btcutil/psbt/coverage.txt # vim *.swp + +# Binaries produced by "make build" +/addblock +/btcctl +/btcd +/findcheckpoint +/gencerts From 4f72645a8a5ee0e8e93cb089dc2a81d4fd7a01ea Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 27 Sep 2022 22:09:30 +0200 Subject: [PATCH 0836/1056] make: add install and release-install goals To simplify building the release-grade (stripped and reproducible) binaries from source, we add the install and release-install make goals. Running either of the commands will create binaries in the $GOPATH/bin directories. The main difference between the two goals is that the release-install will not contain any local paths and no debug information. --- Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Makefile b/Makefile index 3f228a3d33..5bfb1aa6a5 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,19 @@ build: $(GOBUILD) $(PKG)/cmd/findcheckpoint $(GOBUILD) $(PKG)/cmd/addblock +install: + @$(call print, "Installing all binaries") + $(GOINSTALL) $(PKG) + $(GOINSTALL) $(PKG)/cmd/btcctl + $(GOINSTALL) $(PKG)/cmd/gencerts + $(GOINSTALL) $(PKG)/cmd/findcheckpoint + $(GOINSTALL) $(PKG)/cmd/addblock + +release-install: + @$(call print, "Installing btcd and btcctl release binaries") + env CGO_ENABLED=0 $(GOINSTALL) -trimpath -ldflags="-s -w -buildid=" $(PKG) + env CGO_ENABLED=0 $(GOINSTALL) -trimpath -ldflags="-s -w -buildid=" $(PKG)/cmd/btcctl + # ======= # TESTING # ======= From e31855153851cb3c07e8f2424fc619e51454884c Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 14:18:15 +0900 Subject: [PATCH 0837/1056] blockchain: Add sizehelper This change is part of the effort to add utxocache support to btcd. sizehelper introduces code for 2 main things: 1: Calculating how many entries to allocate for a map given a size in bytes. 2: Calculating how much a map takes up in memory given the entries were allocated for the map. These functionality are useful for allocating maps so that they'll be allocating below a certain number of bytes. Since go maps will always allocate in powers of B (where B is the bucket size for the given map), it may allocate too much memory. For example, for a map that can store 8GB of entries, the map will grow to be 16GB once the map is full and the caller puts an extra entry onto the map. If we want to give a memory guarantee to the user, we can either: 1: Limit the cache size to fixed sizes (4GB, 8GB, ...). 2: Allocate a slice of maps. The sizehelper code helps with (2). --- blockchain/sizehelper.go | 221 ++++++++++++++++++++++++++++++++++ blockchain/sizehelper_test.go | 71 +++++++++++ 2 files changed, 292 insertions(+) create mode 100644 blockchain/sizehelper.go create mode 100644 blockchain/sizehelper_test.go diff --git a/blockchain/sizehelper.go b/blockchain/sizehelper.go new file mode 100644 index 0000000000..15a9ccd8a9 --- /dev/null +++ b/blockchain/sizehelper.go @@ -0,0 +1,221 @@ +// Copyright (c) 2023 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. +package blockchain + +import ( + "math" +) + +// These constants are related to bitcoin. +const ( + // outpointSize is the size of an outpoint. + // + // This value is calculated by running the following: + // unsafe.Sizeof(wire.OutPoint{}) + outpointSize = 36 + + // uint64Size is the size of an uint64 allocated in memory. + uint64Size = 8 + + // bucketSize is the size of the bucket in the cache map. Exact + // calculation is (16 + keysize*8 + valuesize*8) where for the map of: + // map[wire.OutPoint]*UtxoEntry would have a keysize=36 and valuesize=8. + // + // https://github.com/golang/go/issues/34561#issuecomment-536115805 + bucketSize = 16 + uint64Size*outpointSize + uint64Size*uint64Size + + // This value is calculated by running the following on a 64-bit system: + // unsafe.Sizeof(UtxoEntry{}) + baseEntrySize = 40 + + // pubKeyHashLen is the length of a P2PKH script. + pubKeyHashLen = 25 + + // avgEntrySize is how much each entry we expect it to be. Since most + // txs are p2pkh, we can assume the entry to be more or less the size + // of a p2pkh tx. We add on 7 to make it 32 since 64 bit systems will + // align by 8 bytes. + avgEntrySize = baseEntrySize + (pubKeyHashLen + 7) +) + +// The code here is shamelessely taken from the go runtime package. All the relevant +// code and variables are copied to here. These values are only correct for a 64 bit +// system. + +const ( + _MaxSmallSize = 32768 + smallSizeDiv = 8 + smallSizeMax = 1024 + largeSizeDiv = 128 + _NumSizeClasses = 68 + _PageShift = 13 + _PageSize = 1 << _PageShift + + MaxUintptr = ^uintptr(0) + + // Maximum number of key/elem pairs a bucket can hold. + bucketCntBits = 3 + bucketCnt = 1 << bucketCntBits + + // Maximum average load of a bucket that triggers growth is 6.5. + // Represent as loadFactorNum/loadFactorDen, to allow integer math. + loadFactorNum = 13 + loadFactorDen = 2 + + // maxAlloc is the maximum size of an allocation. On 64-bit, + // it's theoretically possible to allocate 1< maxAlloc { + hint = 0 + } + + // Find the size parameter B which will hold the requested # of elements. + // For hint < 0 overLoadFactor returns false since hint < bucketCnt. + B := uint8(0) + for overLoadFactor(hint, B) { + B++ + } + + // This code is copied from makeBucketArray() in runtime/map.go. + // + // TODO check once in a while to see if this algorithm gets + // changed. + // + // For small b, overflow buckets are unlikely. + // Avoid the overhead of the calculation. + base := bucketShift(B) + numBuckets := base + if B >= 4 { + // Add on the estimated number of overflow buckets + // required to insert the median number of elements + // used with this value of b. + numBuckets += bucketShift(B - 4) + sz := bucketSize * numBuckets + up := roundupsize(sz) + if up != sz { + numBuckets = up / bucketSize + } + } + total, _ := mulUintptr(bucketSize, numBuckets) + + if base != numBuckets { + // Add 24 for mapextra struct overhead. Refer to + // runtime/map.go in the std library for the struct. + total += 24 + } + + // 48 is the number of bytes needed for the map header in a + // 64 bit system. Refer to hmap in runtime/map.go in the go + // standard library. + total += 48 + return int(total) +} + +// calculateMinEntries returns the minimum number of entries that will make the +// map allocate the given total bytes. -1 on the returned entry count will +// make the map allocate half as much total bytes (for returned entry count that's +// greater than 0). +func calculateMinEntries(totalBytes int, bucketSize int) int { + // 48 is the number of bytes needed for the map header in a + // 64 bit system. Refer to hmap in runtime/map.go in the go + // standard library. + totalBytes -= 48 + + numBuckets := totalBytes / bucketSize + B := uint8(math.Log2(float64(numBuckets))) + if B < 4 { + switch B { + case 0: + return 0 + case 1: + return 9 + case 2: + return 14 + default: + return 27 + } + } + + B -= 1 + + return (int(loadFactorNum * (bucketShift(B) / loadFactorDen))) + 1 +} + +// mulUintptr returns a * b and whether the multiplication overflowed. +// On supported platforms this is an intrinsic lowered by the compiler. +func mulUintptr(a, b uintptr) (uintptr, bool) { + if a|b < 1<<(4*8) || a == 0 { + return a * b, false + } + overflow := b > MaxUintptr/a + return a * b, overflow +} + +// divRoundUp returns ceil(n / a). +func divRoundUp(n, a uintptr) uintptr { + // a is generally a power of two. This will get inlined and + // the compiler will optimize the division. + return (n + a - 1) / a +} + +// alignUp rounds n up to a multiple of a. a must be a power of 2. +func alignUp(n, a uintptr) uintptr { + return (n + a - 1) &^ (a - 1) +} + +// Returns size of the memory block that mallocgc will allocate if you ask for the size. +func roundupsize(size uintptr) uintptr { + if size < _MaxSmallSize { + if size <= smallSizeMax-8 { + return uintptr(class_to_size[size_to_class8[divRoundUp(size, smallSizeDiv)]]) + } else { + return uintptr(class_to_size[size_to_class128[divRoundUp(size-smallSizeMax, largeSizeDiv)]]) + } + } + if size+_PageSize < size { + return size + } + return alignUp(size, _PageSize) +} + +// overLoadFactor reports whether count items placed in 1< bucketCnt && uintptr(count) > loadFactorNum*(bucketShift(B)/loadFactorDen) +} + +// bucketShift returns 1< 0 { + gotMinRoughMapSizeWrong := calculateRoughMapSize(minEntries-1, bucketSize) + if gotMinRoughMapSize == gotMinRoughMapSizeWrong { + t.Errorf("For hint %d decremented by 1, expected %v, got %v\n", + i, gotRoughMapSizeWrong/2, gotRoughMapSizeWrong) + } + } + } +} From e22513c237d96dae737771a6b034db2b44a1fac8 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 15 Dec 2023 14:21:01 -0800 Subject: [PATCH 0838/1056] btcutil: update to chaincfg/chainhash/v1.1.0 --- btcutil/go.mod | 6 ++---- btcutil/go.sum | 31 ++++++++++++++++++++++++++++--- go.mod | 4 ++-- go.sum | 5 +++-- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index b03318a461..9718e6d5fd 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -4,13 +4,11 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 - github.com/btcsuite/btcd v0.23.0 + github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd github.com/btcsuite/btcd/btcec/v2 v2.1.3 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) - -replace github.com/btcsuite/btcd => ../ diff --git a/btcutil/go.sum b/btcutil/go.sum index 5bd6215f1f..a57a5dd920 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -1,17 +1,34 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= +github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -19,6 +36,7 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -34,17 +52,22 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -54,15 +77,16 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -88,6 +112,7 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/go.mod b/go.mod index 4a05d30857..977682aae2 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/btcsuite/btcd require ( github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/btcutil v1.1.0 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 @@ -11,6 +11,7 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 github.com/decred/dcrd/lru v1.0.0 + github.com/gorilla/websocket v1.5.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 github.com/stretchr/testify v1.7.0 @@ -23,7 +24,6 @@ require ( github.com/aead/siphash v1.0.1 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/websocket v1.5.0 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect diff --git a/go.sum b/go.sum index e77dfa2f5f..9944f70ec3 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,12 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= From 7745cbb679dc9057e31ae625004fdc3c46aa327a Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 15 Dec 2023 14:25:11 -0800 Subject: [PATCH 0839/1056] btcutl/gcs: update filter logic to use new DoubleHashRaw --- btcutil/gcs/builder/builder.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/btcutil/gcs/builder/builder.go b/btcutil/gcs/builder/builder.go index af05f819a5..3a85ad0519 100644 --- a/btcutil/gcs/builder/builder.go +++ b/btcutil/gcs/builder/builder.go @@ -8,6 +8,7 @@ package builder import ( "crypto/rand" "fmt" + "io" "math" "github.com/btcsuite/btcd/btcutil/gcs" @@ -348,7 +349,10 @@ func GetFilterHash(filter *gcs.Filter) (chainhash.Hash, error) { return chainhash.Hash{}, err } - return chainhash.DoubleHashH(filterData), nil + return chainhash.DoubleHashRaw(func(w io.Writer) error { + _, err := w.Write(filterData) + return err + }), nil } // MakeHeaderForFilter makes a filter chain header for a filter, given the @@ -367,5 +371,8 @@ func MakeHeaderForFilter(filter *gcs.Filter, prevHeader chainhash.Hash) (chainha // The final filter hash is the double-sha256 of the hash computed // above. - return chainhash.DoubleHashH(filterTip), nil + return chainhash.DoubleHashRaw(func(w io.Writer) error { + _, err := w.Write(filterTip) + return err + }), nil } From 28a816f050a245e64c6fd16536f070a53082a19e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 15 Dec 2023 14:55:10 -0800 Subject: [PATCH 0840/1056] btcutil/psbt: update to chaincfg/chainhash/v1.1.0 + btcutil/v1.1.3 We also remove the replace directives in place. --- btcutil/psbt/go.mod | 8 ++------ btcutil/psbt/go.sum | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index 80f57fc1b3..b5c4461d86 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -5,8 +5,8 @@ go 1.17 require ( github.com/btcsuite/btcd v0.23.0 github.com/btcsuite/btcd/btcec/v2 v2.1.3 - github.com/btcsuite/btcd/btcutil v1.1.0 - github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 + github.com/btcsuite/btcd/btcutil v1.1.3 + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/stretchr/testify v1.7.0 ) @@ -20,7 +20,3 @@ require ( golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) - -replace github.com/btcsuite/btcd/btcutil => ../ - -replace github.com/btcsuite/btcd => ../.. diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index a901223de4..c9d8388f8e 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -1,14 +1,30 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= +github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -31,13 +47,17 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -46,9 +66,11 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -80,6 +102,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= From b43408072752c9ebc71936db3207983ec09ae11e Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:03 -0800 Subject: [PATCH 0841/1056] wire/bench_test: report allocs in benchmarks --- wire/bench_test.go | 138 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/wire/bench_test.go b/wire/bench_test.go index 5176c962e8..ec07031c8b 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -63,6 +63,8 @@ var genesisCoinbaseTx = MsgTx{ // BenchmarkWriteVarInt1 performs a benchmark on how long it takes to write // a single byte variable length integer. func BenchmarkWriteVarInt1(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { WriteVarInt(ioutil.Discard, 0, 1) } @@ -71,6 +73,8 @@ func BenchmarkWriteVarInt1(b *testing.B) { // BenchmarkWriteVarInt3 performs a benchmark on how long it takes to write // a three byte variable length integer. func BenchmarkWriteVarInt3(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { WriteVarInt(ioutil.Discard, 0, 65535) } @@ -79,6 +83,8 @@ func BenchmarkWriteVarInt3(b *testing.B) { // BenchmarkWriteVarInt5 performs a benchmark on how long it takes to write // a five byte variable length integer. func BenchmarkWriteVarInt5(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { WriteVarInt(ioutil.Discard, 0, 4294967295) } @@ -87,6 +93,8 @@ func BenchmarkWriteVarInt5(b *testing.B) { // BenchmarkWriteVarInt9 performs a benchmark on how long it takes to write // a nine byte variable length integer. func BenchmarkWriteVarInt9(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { WriteVarInt(ioutil.Discard, 0, 18446744073709551615) } @@ -95,6 +103,8 @@ func BenchmarkWriteVarInt9(b *testing.B) { // BenchmarkReadVarInt1 performs a benchmark on how long it takes to read // a single byte variable length integer. func BenchmarkReadVarInt1(b *testing.B) { + b.ReportAllocs() + buf := []byte{0x01} r := bytes.NewReader(buf) for i := 0; i < b.N; i++ { @@ -106,6 +116,8 @@ func BenchmarkReadVarInt1(b *testing.B) { // BenchmarkReadVarInt3 performs a benchmark on how long it takes to read // a three byte variable length integer. func BenchmarkReadVarInt3(b *testing.B) { + b.ReportAllocs() + buf := []byte{0x0fd, 0xff, 0xff} r := bytes.NewReader(buf) for i := 0; i < b.N; i++ { @@ -117,6 +129,8 @@ func BenchmarkReadVarInt3(b *testing.B) { // BenchmarkReadVarInt5 performs a benchmark on how long it takes to read // a five byte variable length integer. func BenchmarkReadVarInt5(b *testing.B) { + b.ReportAllocs() + buf := []byte{0xfe, 0xff, 0xff, 0xff, 0xff} r := bytes.NewReader(buf) for i := 0; i < b.N; i++ { @@ -128,6 +142,8 @@ func BenchmarkReadVarInt5(b *testing.B) { // BenchmarkReadVarInt9 performs a benchmark on how long it takes to read // a nine byte variable length integer. func BenchmarkReadVarInt9(b *testing.B) { + b.ReportAllocs() + buf := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} r := bytes.NewReader(buf) for i := 0; i < b.N; i++ { @@ -139,6 +155,8 @@ func BenchmarkReadVarInt9(b *testing.B) { // BenchmarkReadVarStr4 performs a benchmark on how long it takes to read a // four byte variable length string. func BenchmarkReadVarStr4(b *testing.B) { + b.ReportAllocs() + buf := []byte{0x04, 't', 'e', 's', 't'} r := bytes.NewReader(buf) for i := 0; i < b.N; i++ { @@ -150,6 +168,8 @@ func BenchmarkReadVarStr4(b *testing.B) { // BenchmarkReadVarStr10 performs a benchmark on how long it takes to read a // ten byte variable length string. func BenchmarkReadVarStr10(b *testing.B) { + b.ReportAllocs() + buf := []byte{0x0a, 't', 'e', 's', 't', '0', '1', '2', '3', '4', '5'} r := bytes.NewReader(buf) for i := 0; i < b.N; i++ { @@ -161,6 +181,8 @@ func BenchmarkReadVarStr10(b *testing.B) { // BenchmarkWriteVarStr4 performs a benchmark on how long it takes to write a // four byte variable length string. func BenchmarkWriteVarStr4(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { WriteVarString(ioutil.Discard, 0, "test") } @@ -169,6 +191,8 @@ func BenchmarkWriteVarStr4(b *testing.B) { // BenchmarkWriteVarStr10 performs a benchmark on how long it takes to write a // ten byte variable length string. func BenchmarkWriteVarStr10(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { WriteVarString(ioutil.Discard, 0, "test012345") } @@ -177,6 +201,8 @@ func BenchmarkWriteVarStr10(b *testing.B) { // BenchmarkReadOutPoint performs a benchmark on how long it takes to read a // transaction output point. func BenchmarkReadOutPoint(b *testing.B) { + b.ReportAllocs() + buf := []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -195,6 +221,8 @@ func BenchmarkReadOutPoint(b *testing.B) { // BenchmarkWriteOutPoint performs a benchmark on how long it takes to write a // transaction output point. func BenchmarkWriteOutPoint(b *testing.B) { + b.ReportAllocs() + op := &OutPoint{ Hash: chainhash.Hash{}, Index: 0, @@ -207,6 +235,8 @@ func BenchmarkWriteOutPoint(b *testing.B) { // BenchmarkReadTxOut performs a benchmark on how long it takes to read a // transaction output. func BenchmarkReadTxOut(b *testing.B) { + b.ReportAllocs() + buf := []byte{ 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount 0x43, // Varint for length of pk script @@ -234,6 +264,8 @@ func BenchmarkReadTxOut(b *testing.B) { // BenchmarkWriteTxOut performs a benchmark on how long it takes to write // a transaction output. func BenchmarkWriteTxOut(b *testing.B) { + b.ReportAllocs() + txOut := blockOne.Transactions[0].TxOut[0] for i := 0; i < b.N; i++ { WriteTxOut(ioutil.Discard, 0, 0, txOut) @@ -243,6 +275,8 @@ func BenchmarkWriteTxOut(b *testing.B) { // BenchmarkReadTxIn performs a benchmark on how long it takes to read a // transaction input. func BenchmarkReadTxIn(b *testing.B) { + b.ReportAllocs() + buf := []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -265,6 +299,8 @@ func BenchmarkReadTxIn(b *testing.B) { // BenchmarkWriteTxIn performs a benchmark on how long it takes to write // a transaction input. func BenchmarkWriteTxIn(b *testing.B) { + b.ReportAllocs() + txIn := blockOne.Transactions[0].TxIn[0] for i := 0; i < b.N; i++ { writeTxIn(ioutil.Discard, 0, 0, txIn) @@ -302,6 +338,9 @@ func BenchmarkDeserializeTxSmall(b *testing.B) { 0x00, 0x00, 0x00, 0x00, // Lock time } + b.ReportAllocs() + b.ResetTimer() + r := bytes.NewReader(buf) var tx MsgTx for i := 0; i < b.N; i++ { @@ -313,6 +352,7 @@ func BenchmarkDeserializeTxSmall(b *testing.B) { // BenchmarkDeserializeTxLarge performs a benchmark on how long it takes to // deserialize a very large transaction. func BenchmarkDeserializeTxLarge(b *testing.B) { + // tx bb41a757f405890fb0f5856228e23b715702d714d59bf2b1feb70d8b2b4e3e08 // from the main block chain. fi, err := os.Open("testdata/megatx.bin.bz2") @@ -325,6 +365,9 @@ func BenchmarkDeserializeTxLarge(b *testing.B) { b.Fatalf("Failed to read transaction data: %v", err) } + b.ReportAllocs() + b.ResetTimer() + r := bytes.NewReader(buf) var tx MsgTx for i := 0; i < b.N; i++ { @@ -336,6 +379,8 @@ func BenchmarkDeserializeTxLarge(b *testing.B) { // BenchmarkSerializeTx performs a benchmark on how long it takes to serialize // a transaction. func BenchmarkSerializeTx(b *testing.B) { + b.ReportAllocs() + tx := blockOne.Transactions[0] for i := 0; i < b.N; i++ { tx.Serialize(ioutil.Discard) @@ -343,9 +388,79 @@ func BenchmarkSerializeTx(b *testing.B) { } } +// BenchmarkSerializeTxSmall performs a benchmark on how long it takes to +// serialize a transaction. +func BenchmarkSerializeTxSmall(b *testing.B) { + buf := []byte{ + 0x01, 0x00, 0x00, 0x00, // Version + 0x01, // Varint for number of input transactions + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // // Previous output hash + 0xff, 0xff, 0xff, 0xff, // Prevous output index + 0x07, // Varint for length of signature script + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script + 0xff, 0xff, 0xff, 0xff, // Sequence + 0x01, // Varint for number of output transactions + 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount + 0x43, // Varint for length of pk script + 0x41, // OP_DATA_65 + 0x04, 0x96, 0xb5, 0x38, 0xe8, 0x53, 0x51, 0x9c, + 0x72, 0x6a, 0x2c, 0x91, 0xe6, 0x1e, 0xc1, 0x16, + 0x00, 0xae, 0x13, 0x90, 0x81, 0x3a, 0x62, 0x7c, + 0x66, 0xfb, 0x8b, 0xe7, 0x94, 0x7b, 0xe6, 0x3c, + 0x52, 0xda, 0x75, 0x89, 0x37, 0x95, 0x15, 0xd4, + 0xe0, 0xa6, 0x04, 0xf8, 0x14, 0x17, 0x81, 0xe6, + 0x22, 0x94, 0x72, 0x11, 0x66, 0xbf, 0x62, 0x1e, + 0x73, 0xa8, 0x2c, 0xbf, 0x23, 0x42, 0xc8, 0x58, + 0xee, // 65-byte signature + 0xac, // OP_CHECKSIG + 0x00, 0x00, 0x00, 0x00, // Lock time + } + + var tx MsgTx + tx.Deserialize(bytes.NewReader(buf)) + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + tx.Serialize(ioutil.Discard) + } +} + +// BenchmarkSerializeTxLarge performs a benchmark on how long it takes to +// serialize a transaction. +func BenchmarkSerializeTxLarge(b *testing.B) { + // tx bb41a757f405890fb0f5856228e23b715702d714d59bf2b1feb70d8b2b4e3e08 + // from the main block chain. + fi, err := os.Open("testdata/megatx.bin.bz2") + if err != nil { + b.Fatalf("Failed to read transaction data: %v", err) + } + defer fi.Close() + buf, err := ioutil.ReadAll(bzip2.NewReader(fi)) + if err != nil { + b.Fatalf("Failed to read transaction data: %v", err) + } + + var tx MsgTx + tx.Deserialize(bytes.NewReader(buf)) + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + tx.Serialize(ioutil.Discard) + } +} + // BenchmarkReadBlockHeader performs a benchmark on how long it takes to // deserialize a block header. func BenchmarkReadBlockHeader(b *testing.B) { + b.ReportAllocs() + buf := []byte{ 0x01, 0x00, 0x00, 0x00, // Version 1 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, @@ -372,6 +487,8 @@ func BenchmarkReadBlockHeader(b *testing.B) { // BenchmarkWriteBlockHeader performs a benchmark on how long it takes to // serialize a block header. func BenchmarkWriteBlockHeader(b *testing.B) { + b.ReportAllocs() + header := blockOne.Header for i := 0; i < b.N; i++ { writeBlockHeader(ioutil.Discard, 0, &header) @@ -381,6 +498,8 @@ func BenchmarkWriteBlockHeader(b *testing.B) { // BenchmarkDecodeGetHeaders performs a benchmark on how long it takes to // decode a getheaders message with the maximum number of block locator hashes. func BenchmarkDecodeGetHeaders(b *testing.B) { + b.ReportAllocs() + // Create a message with the maximum number of block locators. pver := ProtocolVersion var m MsgGetHeaders @@ -411,6 +530,8 @@ func BenchmarkDecodeGetHeaders(b *testing.B) { // BenchmarkDecodeHeaders performs a benchmark on how long it takes to // decode a headers message with the maximum number of headers. func BenchmarkDecodeHeaders(b *testing.B) { + b.ReportAllocs() + // Create a message with the maximum number of headers. pver := ProtocolVersion var m MsgHeaders @@ -441,6 +562,8 @@ func BenchmarkDecodeHeaders(b *testing.B) { // BenchmarkDecodeGetBlocks performs a benchmark on how long it takes to // decode a getblocks message with the maximum number of block locator hashes. func BenchmarkDecodeGetBlocks(b *testing.B) { + b.ReportAllocs() + // Create a message with the maximum number of block locators. pver := ProtocolVersion var m MsgGetBlocks @@ -471,6 +594,8 @@ func BenchmarkDecodeGetBlocks(b *testing.B) { // BenchmarkDecodeAddr performs a benchmark on how long it takes to decode an // addr message with the maximum number of addresses. func BenchmarkDecodeAddr(b *testing.B) { + b.ReportAllocs() + // Create a message with the maximum number of addresses. pver := ProtocolVersion ip := net.ParseIP("127.0.0.1") @@ -516,6 +641,9 @@ func BenchmarkDecodeInv(b *testing.B) { } buf := bb.Bytes() + b.ReportAllocs() + b.ResetTimer() + r := bytes.NewReader(buf) var msg MsgInv b.ResetTimer() @@ -528,6 +656,8 @@ func BenchmarkDecodeInv(b *testing.B) { // BenchmarkDecodeNotFound performs a benchmark on how long it takes to decode // a notfound message with the maximum number of entries. func BenchmarkDecodeNotFound(b *testing.B) { + b.ReportAllocs() + // Create a message with the maximum number of entries. pver := ProtocolVersion var m MsgNotFound @@ -558,6 +688,8 @@ func BenchmarkDecodeNotFound(b *testing.B) { // BenchmarkDecodeMerkleBlock performs a benchmark on how long it takes to // decode a reasonably sized merkleblock message. func BenchmarkDecodeMerkleBlock(b *testing.B) { + b.ReportAllocs() + // Create a message with random data. pver := ProtocolVersion var m MsgMerkleBlock @@ -596,6 +728,8 @@ func BenchmarkDecodeMerkleBlock(b *testing.B) { // BenchmarkTxHash performs a benchmark on how long it takes to hash a // transaction. func BenchmarkTxHash(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { genesisCoinbaseTx.TxHash() } @@ -604,6 +738,8 @@ func BenchmarkTxHash(b *testing.B) { // BenchmarkDoubleHashB performs a benchmark on how long it takes to perform a // double hash returning a byte slice. func BenchmarkDoubleHashB(b *testing.B) { + b.ReportAllocs() + var buf bytes.Buffer if err := genesisCoinbaseTx.Serialize(&buf); err != nil { b.Errorf("Serialize: unexpected error: %v", err) @@ -620,6 +756,8 @@ func BenchmarkDoubleHashB(b *testing.B) { // BenchmarkDoubleHashH performs a benchmark on how long it takes to perform // a double hash returning a chainhash.Hash. func BenchmarkDoubleHashH(b *testing.B) { + b.ReportAllocs() + var buf bytes.Buffer if err := genesisCoinbaseTx.Serialize(&buf); err != nil { b.Errorf("Serialize: unexpected error: %v", err) From a9edc326fba6a1eac917c4cbc1d52fe85ae646cb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:05 -0800 Subject: [PATCH 0842/1056] wire/bench: add witness block --- wire/bench_test.go | 53 ++++++++++++++++++ ...c49862a7bca9d00f7f402db20b7be2f5de59d2.blk | Bin 0 -> 1245250 bytes ...efc52a480d173c849412fe81c4e5ab806f94ab.blk | Bin 0 -> 2259447 bytes 3 files changed, 53 insertions(+) create mode 100644 wire/testdata/block-0000000000000000001602407ac49862a7bca9d00f7f402db20b7be2f5de59d2.blk create mode 100644 wire/testdata/block-00000000000000000021868c2cefc52a480d173c849412fe81c4e5ab806f94ab.blk diff --git a/wire/bench_test.go b/wire/bench_test.go index ec07031c8b..296d1f4624 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -376,6 +376,59 @@ func BenchmarkDeserializeTxLarge(b *testing.B) { } } +func BenchmarkDeserializeBlock(b *testing.B) { + f, err := os.Open( + "testdata/block-00000000000000000021868c2cefc52a480d173c849412fe81c4e5ab806f94ab.blk", + ) + if err != nil { + b.Fatalf("Failed to open block file: %v", err) + } + defer f.Close() + + buf, err := ioutil.ReadAll(f) + if err != nil { + b.Fatalf("Failed to read block data: %v", err) + } + + b.ReportAllocs() + b.ResetTimer() + + r := bytes.NewReader(buf) + var block MsgBlock + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + block.Deserialize(r) + } +} + +func BenchmarkSerializeBlock(b *testing.B) { + f, err := os.Open( + "testdata/block-00000000000000000021868c2cefc52a480d173c849412fe81c4e5ab806f94ab.blk", + ) + if err != nil { + b.Fatalf("Failed to open block file: %v", err) + } + defer f.Close() + + buf, err := ioutil.ReadAll(f) + if err != nil { + b.Fatalf("Failed to read block data: %v", err) + } + + var block MsgBlock + err = block.Deserialize(bytes.NewReader(buf)) + if err != nil { + panic(err.Error()) + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + block.Serialize(ioutil.Discard) + } +} + // BenchmarkSerializeTx performs a benchmark on how long it takes to serialize // a transaction. func BenchmarkSerializeTx(b *testing.B) { diff --git a/wire/testdata/block-0000000000000000001602407ac49862a7bca9d00f7f402db20b7be2f5de59d2.blk b/wire/testdata/block-0000000000000000001602407ac49862a7bca9d00f7f402db20b7be2f5de59d2.blk new file mode 100644 index 0000000000000000000000000000000000000000..aacdb7aa99410065a13274b93beab17960309f04 GIT binary patch literal 1245250 zcmd3ObyStxw>E52K)ORV-Q6YKDIq8+-6cp1k{eJ!L{U8KAk<*vwmezD>@mrI(c&$@nc@6Oj$=T z5e)Q5;Co}sSFYauhUPe8fU#kl7hRnP9gGd1>lZry_?azN+UFdw!<}9ej5#Xe<+XHC z>zD1djMsy=#PFs1+TC%vWv_xloBxR{-;`0!h{LauABGQveD!vSG#=%4`zso%zF(d> zW6oTO|DVVLrL0lG@JM8Z#0O>a;EbfW1mqMH6dNg2?lph3%_z0A2Q)vQ6Xl!;9cyRw z^5RDl@5ii^FM)hTqEL~Pc@;ol>67*!n#9Z^!`74}Yz^e^UR5U z00KKWNrQ!+K2la1EvjE@3@_eMTxjot@US622o5Y+cLgECz}|sy+wayyQKDk>&Ruy**zh?fIfZL9=fTg5{X{;D4h-kb!=O->f1YmSs@j3 z;!`Bjj)}ZCRjymxm}zkypOpD#=s;s2mTf(C{}6}tW4k95*`rEN&kE}ygJ>Q2-TF7?3cq?lej{T3g(@7#hU;@TR{5Limob=)w zzcMv%Fi=@i+~Z$;;f{vPzhm$~p6}9jU8&=$B%fQ!c^w7e3Z+KYv!RP4;Sz5*<*}IC z7hJy;fxze!)idaYQq(DxKA^~A2xIcxolxoCDNlpBa!)OKbnO3o+tq}Y8S@kMas)?{ z3^`EG%Czhs$dHZfAlI2>_PA^*5rM#-<&>@@v_`MgM&|FKv9J0j1nj(09e%0A_o8Eh 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

3^?Ix;QzC4`>Mq;4QnEB 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�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୶ZDV;7i0YeIbs+C0mx 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

gw!W> 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 z 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

KDd1VZ?M6MZSxJRL<(tq<2LUq&FD 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

D`n zwbD}?!Lo!~ZZ*&p(=&s|1f*2;xO)W~M^Ze$iisb`aMP8#69zndD+6eJ<)Ov!ocCb% zArd0$&-JZ+&LPy*cGemMjSZI$w1xaT6F?@+8=^l%*IZ}#`7pLcU@K5i+gjOPz+{J% z;%$)O@4flUAXGv5OZI$ptCH?;bHxxJRV|(j1RwN$g?Tv<(L(+@XArsc#ZrJt*zoln z1zb96Z5guojLEaL(PcT}cGE+`&nt2OgC1WmqJ#;fi+wZ?jc=7RxOceUV@h7cNbnK$ z9ruTjLW-wymx#y>y9{=(+w{|uWrQ!{I*4^EsUi(nLfFQZWM9mKIr~THL>5NMxAGhg zumgkoY&@t$`;?Kp2_(G{=~UDeC76LqC1wK*Dw?ePerBbiN=!wv`(@Vbqco}BBkiIL z8ya~QaGga@!gm_+1i9<4nT}ybfjYeg{S1oZu=HpOAmmE5VvB zlM{c~FM~JX^g*aDbOb1;&#ZrRZ^dzM>)4ni=FG^*cLP)Ki|dNDRqy}(hO zx<)rz?$>?mf!KyL6gYJbW-!V8_?iH1B>P12WGXGP%qu-h^VOI04xW0V(BX>QOh|a@ z5fUBFrKfYZ>L+1^B;Wp#?1n}GOJOYXy-*dT9}R`l2|(%(T{Q;xuXxT*q!)T#WNsOS zzhf7ci^`_2om9}>4o}|<{g;rI@N=KNAl>3LQsjGW{T1ju-utokC8dCQf)jeuNM23} zcsL#*x%0bR-ZvPiDYkJqdtJ;o5vbrV!inoxy)0KpB1~xqlIiS5sGm_4<0ACh7TWKLIUY z7t_GF9u*~-Y2bi5!yhy@Fa9fDfC0hy<}l`8YEV_jmq*A&6`Gs{t$Ges)BCR8&8}HP ztOzq!o7K;Q1+t<)GWe?bWrv>1eb~8(M==92I~5DcS3_;Qj`{Q9ZmzXLnF=5s0nsCw zk4u9yZ7z+7&S5=HA#h{YI~(sjt+^`xB0A;}V6bir4oe8tsKV`fE-D*lf2&EhI!t*CsCQTJE|0N{7%Z6;cjvQ~SZu&WY@`a8Mfi($ftDm-~0>;Uga}XB)LZaV2 zbleNv;(eyg@8q{P^YGfd|LX@smN0cyCYzfwwG>!*`e!Ba^6 zv>Fw50ch(NS2K0a1{;f zo=WSd^2qLH=vbw*B}yoUQ<;LuaiI3DUkp>>F~*Ji!GWBoO6+aSi;F%|qBo{7G$^A3 z4&Z-<2?HcZ_lhuf@&L1L=RThm7jfLWSLO$9dVyn;6JiZz1UOPiNKTtm~<7 zitKFv>H+j;SV|+rhs%sjw>XD>L9#JdvO8FElI>T4sKhp^@*ZS=8ML9dHE;4&S!-ps z>&Cr(n5=Tiou|FNw_9sSxF7GM_68U%8SKQ{YI;Hygt_x_^n}JHEvzCt3F>odT&S{# zq=Y`;YgF-1$P*ztq@tCxCfv=Llx4B_M6L7_BEX#zs3(zk?9Cx$U}|Us7!J|G7bn4 zep8e;w_DZq2RHTl0PAy=wW5^Iqg-98`g%Bf$WY)*BL1AcfM$X*IzD6P^fP`y7fvkk z`_lfpCBu*=s(Ric>%E*zedq^Nw-1e5BO{Byute)}R?%WklTI-5=e`(+BDMn%0(Eus#X(rv;44IXBQDSX|p{@qX1JtEzLsw)$QE8go@J|0Lm z^nus+?J^h=h<@Qwg@FMU4Rbi|tM70E;iG0wGn}NZP+io8-1a>F4-AXjupdtH-IvfK zFQj>9JDU5aBdZO63VJK*kZJmf68TEXnSV}M2(a%@B0O`t)ND-?y+?48LIFYtJkp?X zHpCyifk{z6nV21}Ol$4+?yHh%O~0c81qgQF{EH8I%8B>peIqA+WLZ8b?iU$_8-*Fi z-z#9a%1YT#Pujp@{O7z2dgF=PLSnmH87xg9;(ICLJVutEIN`SM^-6Fzs7~-Y!Hdq z2qA75B%|r)5aP6hH~;FEVw*(Ygr<0rm{Zh0mrz`m!o3lT&62ofNF?qPaLmQ(j-~cr z<0s>u!2g}EYXfxkV^0xp>@I8{hnkIx*jgouzZ+xN#K$&M;?*wgdXFFtv=D`fF=+Ny zZ;is-H$kF4$9_Qn%53Y|tMqo48gsXpdHn$#WrT1J9V~s)>^puDb;8#h+H@7 zRyIK{JO6!6((2bvFA@>KE}TLf5kGOXSHBBJ>l^@F#n|uIy@WVJQE6k5Z9<@2bHmdO zp{kvzc7(lL?%X|h!J>pV%aj1)1E+p%8*<@SNJ_V6fP$s!#0IN;S17TmNz)=|7TU1^$f9K7?j?&i1x<6Fv+l{ z+il74n2cmk*O14b^;la4F1d0({Go|&F|@TA=rBiU+!ydNMGF z89m_VxDrK;U zM|@4;%)@v{^RER1<-9fHZP-Gs_W!7fkGR2nIe~Ss0ZlI?P)$FMK}ZnO@pt}0f4pcH z5u);l;r-Z}i(lFBqeji#2g^ea~QjJo2y-rv{1;d9eMIk8g z_1OGTxu#WRX1Bc;}pEjpc1RhHLlwNjeyhwh6Hok1kP!BlxT)}v#<Fpib!H*f z52^QBnSWCKz)$?I00fkP3w*=>2tfSbAAqQohh}bw=DZy7DtatcYQ=e|M_XmMCC*QI zv^23VZmcH|JMhRqZbEu2NbtkE;~ev``m}$fnYFz9nBE7x_jnOzf8c2b2hbdH=8AgCF`cBYN(v ze(XC3(0^da(Q3&ZDf8RT$xaMd#%UGIerm;$00s1=Cq4`OQ3q`ZT1g7^mAf>L;|lg# zyrQbYU8>cArnjE}@WUb`+cLEs`tbWh#WQ^4k6u|=--&bNloB_MijeoIf^2o6K~R5- zYyNNi5FVkSb);gMHmZ78K!XjEQlsy*8QA9XpTBO4vT9QB&bNVk364d94KdG>cINB6 z-YhKED>mM%x1XDNIXA(%!mt#4^sq&WpaIWVbY_%>CtBu&j{V}2 zZrYrs+HV(`W-rTtz8(t3m~>ABDLH%V3F)t7gd3VSjF$!9t8pK*>A+UVf`B<|BR}c< z{vZM8+Vmhu)i4B(zGx+z*Sbdf{sytXaAs zb1wcGQu6@jQ8{Ug`!{NxU6)60VQn}N}Z8ZH^;UtYEXHi4n ziYq^a7Jr<13>yMpz~-GP*I%y5iE@n|&tpP~p8G;x^-s!%`?gcObV^&V0E# zrHRfHCjv!Ai@adJtMDk`!XR&-v*<{x8EBd-oc8#|GDR!w>X+w5wb#d@hPXzt6^hW1 z{6X$MwJvV6_v~S%T>v)q` z83nZ7o|eCD!xY>V9*&1)1ZQl(WIKgYq*Ud5lJ7D&!(Bz;#a)vquhtd0?7 zp@8A_-ZE1>OoDCZRdRGnj`b`P3`vPacUhsMFYg-5&pDug(J8R6fwu5pSFNE_D%Vgf z7SwkA;K4*o8${gkQ=V|N^j{ep=0J0dfb7Z1>w9g%de|@{E+>sxoXTEG$u^^`zsk||+JA+?-0pWkP7|4(bao050uw zQ2t85Q<=4y%lHLe`m4|_P|TZ-WS=^pyV4+Fz`cV9n45!m-M#4Q#Yv5yTP%yGlU^Qr z9*5s_p^}Slzn5RTw!}j4dzt;k|9@wkfF%p#N=4DC6GvRCe}`oG1>T9|cI`=f4jVpF ze~2ejoKmkNSPp;8WpZ?JRyxYU12bH%pxlVY3{E=A-Sla7V!T}7g-)Y6a7(5kt~HAd zE&Q|dkQHm_h}%~K3rU@R%h#?%3K|TTh6cX?`G4Og7B0T)TDLJfv_P5cqA|lcW7Oi~YeA=J@=R zHkOsdiL`m-R`;b!c|>kyf0|BXg#NCeFq4^yfNGToby3 zZO70Iiu`R54Cww#OcD;UBWfSl++pZ_-Vubx+%Xx1;h@0{?WlTEGN!wjzXF?<$5rvw zlXLplEIY_ODM_nR3gbeC?mm~v;#_nz$eV~M9|S&v$SH2m?Xvu-;zO7O=W|5u-*wr( z2HUzwSq*IzG6$^S1QfnEzjifbWu{GPE833FMOnyb)A2hVG*ahk9ADNqpw!S%-z zdke3&kS@E}+>a;|`_9T8E*hYx|7Jigg}CN_Fm<-@8{6Aq zlN29?QX9LX{$`?q-FGCddw=-NRGqoRn+nJ;bg%uAu;eFa@Eh&7T_p^uZ~*KO>bHut z(G*eL6Dd5q{}K~)M_t>6enRjof1@zR5}qTo>oqrF>X2=W`+#7&o-Mn7`4{C6+IC5* z)Y3y=4DfEam7(hnCW>~ebWSX`(r34tUjVyiq^W9((`i_z-<{+pb48XaNvY~_`Ev(Q zJn}_9LYjwG|4U4uLA$^H1+kKwOY&6T)KPu=ew#1dxE9?8R%o%_z~3iYI`yarZb+as z=nOHbzloip=|184s|lcyli2XWECwNGrTCP4EU!FF(SnM#QI@e{ zgxI+uB-sQsnO53mfU1jyeE9dq@5S%q7ZoJJd!caG*Wy#L}bW7Tk|3Cqx?A3fE{ zNrY*6urqr}Z&&Tyi_Ff&Ji{Mo;K%HfZyJT(%j7#kZh(P97~2s0D|xGe`DwXx%gD^a ziynZ(1G^|3p`4A^0~ATWnyeZYijbx%;mtAGM~_{+5ObYBfu-Jd4HeRxuwdgRUoR%M zfvZ+T`pt>mTvnimB0}jFBO2qcBDhKR8rnTUza88PU{?H{FG zECV7((2l7?bXwEc{Mj;H|7Nc{&mYjXDRs+hTm4I@fi-fS5;1_ox}uFbHvBJ*v{S?P zrt0{grQ`&(+j9nnMd9KUNDs*R!5l*S68v4Z2D;TUT?Rv~FZ1f&>Y19(qqVM&Ot>QFs5W=fX>0^q zGJxhAj3V#(^wSM}Rw$T#Xr!ryD{ejA>Gg-H9Y|QtIw6;gfdpPYZpHz(zBL6&^%Q0L zRpwI}LjE59+4G^|&mo+a2H@d=jNone0K&2WigQP@7X0-(OS)dHQrW-w(~1gqcE#@< zB*rVdCw?~AZx`I7FD8`Zd_&3->#((j^;ZEk4p%OImTHw_jnoa;+Tp;ohv}0wyl>aU zLvS>8;nx64_TNW3hl|;7^*tNQ6u5(N)VOY3o$y{B*h$AVN1S5y-UG8YnYirbQubZ6 zPUs+&S)XJ>y=k4)K&LQzzj39+pW_&!fD`{(OGM}AtI9A+hZz%^;iMO|#?{)60OuD? z1gtlY4C48}Kcq7q4N89bQE;r|K*`{q+xTA$?ibZA{ zA^nLx2>oQ{;4g#T@*?>(@z#cX7fbm40!q7|3BG=WdOeE0lggf(k%sjJh|hkbAl2b0 z*Niov0>qf0XI4O ztIw!4X0y_tAq*N1{#^=ZXXV7=-SI6A@XC_mjtc!0N-)D4AI1N8POip&+nliJq2yJhEN%5{}4*`q~ec4G9H$a*8dLFl)orfY| zq6fpkNF?nblvq_3Sx1%MeH=U&^kWqQ4(zgeZE6;JqY{rC|VZW*KtHaerkH*3oteEncRSa}OG9nz4{!=k< z3cj)&|&XB#*_4HYOyk=!%C~NrYHHrY!yB%%x61ZK` z4Can%hFZoO3ciESwp4blF60Ceiq2o_v(_(+aP}DrnDbBS_)D!p?saPSP}V!z50gd3 z@kf2eY1$DM3LJee`;<%nluNu|xs@s;`0lXu+LRlieACkPX1GK`Ur3bGJQIr-(^LpZ zF+ryW(KWhIkdwkHzAL#oRsGRWbX{W`^iiUb#qqUT{2%7m%ri~))6BSvNy*ITzE2Pp znf&Ch%s290TvUzsL&h!ys-ozIzbz=R#Pbjwzy4<4d8SW0vo2oogfm<9>8Orq2Q-BF zb&59?i*7$W-14upY1Z*;b&QB~V|j5{jRO)y0ue~@C}3WxHrY#(btUe)S2k*DuiR9b z?>Dd2Kh}e4g^eNX}@hL{#l0 zd^w~<>912F+tH7AZEI}IzdPb-et_FM%!sxZS{%D2LkT7U$f;1(!HgH<>FJ9bt4tg| zcb4x?^Vfe4;@&WOb7h8F*QXp!NK;Su6spz7gj3~^!XIJOOa?0`NCSR|nEuko%vxch zlH+Irf49%C4+GXBSL7FYz3+B$h)sczE6k6yO?m^a3K!RR{QRiDwfZm=!XKi}CdK=X za$BEg=|GO6AJv1x=ADWdCPjE(%CnP@rVr4SGa_P^2@S7o5kY4W@kT>7V6Gpxy~y>{ z2s9!w^9s{AioBbnx3~CBSV@^a_#3UzCeWCd!XR=gGg1an^h0#| zsR!uAU_}$Ww9mfJK6~=H=*ZEWUb`+u39d>A>~cRsg6A>+?oldkImN4%@a5I*qOX=h z@#%gSYRsBWuPYV`9Ee;kUaV8+S?18Ng2!r!^2RXE=?=U<%LYEsz~!?bVkNlwHqp+_ zfvdDu)-yo|Qz$N!u{ALdY@29}b-puyg-_}{b6`lizG#)uHp^%MEPDtHT;Ub4; z^50Sn!mOF-^$g9P{Rfi3rAy%zb0}c~Du^t4T5lfXUelnjA|Yv-2dTCJI^h!7omhS9 z?bzo|Orb$j6=^NWqEY-f1S$i4S~Jc!L!3oJ1R&8UY(BK?`I!HtVJ81d-@c9blp1#7 zX<=|c^V`^|78g=5q&;$_O4Se8we$59!RD20R!5h%Pjf^})KQCTtKXkS8iB_bJg*0% zG?~YR5WSuxcW52KndM+e@IqJ$n`7bQ_SH-ms1>(ti?Y~0yw%M4G4;A<4HIQ3L`OIF zAG-iLg`bJ!ibK9{pl5G-FV^}p%Ks8fKP+gdy1+5nnyKd2>;Yrp9ql$0*{1=HYD>m2 z3OaRjV=(>4QF`)ft|8glpFrW)H^(a9iiTP5sg?q)L2s!971V%!=yo8*gm{xSORez% z&0rj=vQmSPq0{>?iM6~!7lneJ&Q_Eh@N9ODiYkMfQk1%X50)jCL2sr0FcE|sFu2yI z77lZn{pt&bBs$kV_4}cPKhu!}uOk=|4TFI85pTt>zbBiHE(WNu#_JmQG6-=xs8yGnky|G9ABbDwPYP$jZuHV zqZ+tZ^1|Q#7DUda8<)I3QGfyiGT`A|c}C+i%$4SK9_Nd|fMzd~`~-aY(AO&SQEESV zQiqse+BhLgO~T|Q-n4-nL__*UjEjyE1~8;uw~y015>0}h&2nP(%_~<%IoUGd`hp4- zY$_Megivq+M1LSX_3vAtUeb(wg1k5#H}qChnLHe`TMTz8Kb^xKR$UOtKZW_yr9Q_W z?Dk~TdXpwes}aFfzh+4+Dmtw>?hVx98&Lofzm})Xb#>&{guviiIMIbfehD}FC)3SR zMd^uQN;=9}U`S7%AbANWfumZ13RETi*4OFWfDoOr3mR~)|nlhRisW`*4mA8odqANiDKB73C#YtG6Fd;p{uhRK}pPx{P_ z;rVMwUk;05+( zCCl3V5hTwHJmZZif9Tc-Ad&GrOJ%EkIpQvICB_bZ|NqO>gBRgPU6itCK0be%wQCon z6`|y|-Kggg3SH-WGZTAHpGFg^50qEAYDJ`Zei?_lvUYIXw?Jwv+fE*RaT+)$wN^5^ zk~{=XSIkLK_n`BqJ$X(qjfxQDBTfhX2Cci@id_UDDaXGd2qI;;Zd1kX67wkbD46B% zI}@7E?rZy|gAvY`u`Yv)xA-9keqff$g%dI(c}GbH<1XA1zq&No$+tjsSvb3DsP|=N zTaQlEYVr|}$-1%xoBgO1e_~Y#Qsw0wB(E3ze%T8RGv)N(##-puv}u+|(!Z8pwSz^1 zRV6$n%lUO}%U5%U8!^*oXk&32|Mk)Qr;FKEmCq`W7OIaT;YsXEXDeaRK9V+<=X;Kl zhGoh4oA@EIp>`T&oP~qK9mqw09*D)mnz=-CHjrrBYTgCQXfyc0JZPv(RpMVn4|^RznYsRfhjCLEZg>XyLbY zS>Az{8S?lW4NJ$qS~?TpxgaL6F4SLCN?M&M(;jzkjWc|ABdH%%Jv>O3^V{XQOd1%H zl4-IRrUP55=aG!)b3QG6$?C}n7bPoLNjtn`({#FO&^Vlj$kG>9xk5h zx1##=%(2qaub!Ke0fXd+5UPRBzmQ2tiQy2emsnJ}Z0;8%7Z$21%R`6rdVw2^i1}=X zV(ItL$?^oFk;VIsCq#FeVjdM=V4>)XDunD8s{Y|9R2N1;`)SDj0eI?g_Ia#DclhNn}>r z#zxrB_3o$7NxjI5bAXdSPb_RZD%?Hf@$%^GtPe#5ZrlT%I)@|myUw$@ri4I`e2`aR z)JWCS^F#MAGL_e*k>s-_9(mU?JF=QiY6rDFJi=f|@&}?aSX?Bn;#-z}cI9Jx0`G6R zOs1$2UbYlI+y1Vq17_)Ql+>`1Y9-}wk?O20^h;=x<`@14l2?tyJEDqltmo)KWMrH#JMWT!>BQKm`R6=7~TMl zQN&YwZFOD5mmB7Fw@(giNdjnQ!V27e)!0_#?XY6vH31?`yWy@~pV;F&c(EW7rMcaY z%@-i&5L4qalB}TLX=nQj4C(S6TOH2;xrm4S%(2%t{>M*Y^E;#(3>y4*yPuKsGB3eJ z6OWMKpTspwL)(=Wx^Qa{BB#yBj^CmokNK54&PO23(onDiE&kE)mktUHs^1(x5so$! z=NO>6yWnTfX!@E~YR7oz%mqN2z3SNbIX2aa@jbx{bWz}4D9TFHNC(`@#5M3z%$70- z42kA-QfF;Yo5|bnyo5i(Y-1C7IQ&u{G}Zi1s0dFyTk`+<)_9?x%j7k2vv|{kvfF}m z4lTUKdXt0hE=wm|5iL(%p95{s>m~eKBQ5x8eXEfA2Ju|p6VVcqgu=XP9H}Qc8Yuz- znJ{YfjXP-}EF7_I6mFS;k*~wfUX?k>c@;WGYPTtN_Z5O6LAQ>)gB%ruqXMl(O^3^^ zsojd{(NYb}KQ;9b8p0r9%ExANJ}GO+<$h{sabcI<4y`#H@CAtn^SdvV&T-Yy_D1h zk;54o@j1WP+qP$86MSZ#RW-ofzepp|`^8D?vZl16LEBmZ?DiP2!uo zlJn>|^2wW+x9`LHU|(84CZ<3=5_H&d*!i7bE5xy&`{W|qEt57%@yM+%cUeX5nWh$r zByi&mf7TLLXg6Zkitj1`qX{kPMIANrK2OEp<2EeEKI2MmQ~Y#1q(t-!oA@VS zzzE=$gq1R)WkA}Uej*xgG{Ra)pg+x)k2DnpqB9aiG6H&3Jm$h64)3FmP9F53i@DB? zwGNhp-w*zqh&x@r2#pC?eIBV<>#bJ6ElR`Ex}6Ry7F?Gnxo52MzE^ASPa0$2Eqh82 zD98jg{=V+wYV~PrGxO=s{8mPey56_^W5@}m_aCj!bOFXb1pGh5y=7Qc-PSM+o9^!J z?oR2DZV3S?5ox4B>29UFB&8JT?gl|h3F%O}%XjUK-rmpkeCN6D^Zhty|D9{EHENDI z#+W0veN&JT0`_@7z-GbRwlO{RD7sVNaU|nfCnvSfQo8??CNqgZg-CQUkG^U;ElB!_ z@lW~9MkQtvXA5{Ff3#}AVR$xIt~yQkx`eDr`vIzn0O34)asovdLV^-kC2SgT7#e`s z$DQ$-;|JCnw{c}{?H>joK7n@NlW<3#E8V}67|5tc_=T2ML|yL!IpHKeM+jpLkeUj` zL{rMo>^xt-l)%INYa(~&g4-nODTxak8-BMLC<6?9ut4yGv_HKcIHd&0lsC^ z?N}BmtDp$4Fl@wlTfFV6fBemu?%;r-ybbN&|`VO zB&O4QvSPfahAS3(^$9tx-DI(gz447pYPCP14_Ik24K?%C}N&`h7WrxhN`NCqfP2mR?Cy z?1h;If0Id(u4Q{?JSpO?)gB+-YlBurM~%OJ1*Px#%Xff=&8)uQ2Wt zJPqSO^a=dr&+QECvEekV+XAn7aG!KO>V%uR{}fb5YaIOyhkJB0YgEbWgeXI<=C-~i z=jY}f(W+W#z8WA(`;)sgJ_?Jc{I~v~ZFsjCgb(n8=L2*;``wpfez$q609I_2@mx_+ z=LStbhz4$uNtLLXw$gcv!gf<zyY#}OTO;w$(Bs?P6c z;|bAF_%n6A=+8e7H9;m;f;>|GM4rbt6@?~Vu28g`KSd-?=@1Hevo;x4Ua=tpK>>Wm zOv>DpyggJ!$f-YCRAtL<=`c|(zrP9t!wz~stDB~sAnp3)?W=H@W5Qt)#du|p-mbyv zpqOQ~ZF0Ro5wQn22<4M*m6MzXY`)X3Euxcajg6Bw>77DdYea@JR*B$-DarBk3b}?8 zG~QeT#djkfs^SdEP7KePx}IO9KG-n?5VT5bhl1ODDT*BXvfJoUPlUvk>rrYyYOBmk z<1;E$Ds1o(smj7j1&yg^^*~hT^P7*?{RY;bRV5k^h-lNk4G48y_kvOTb-kL#4SP8V zvl{qC^?T5bnYYpAHz}3Owo!P}2LYX3(b0f|D_N)iM9We_fn;`WFiC&xfP8x2(}#SR zx+GPC_Te{@IzS#mux#w)UyKCgzxz=MT;2fzesXoNTu zkn2^nrVfFl1D??AX*l=_}~l7d0|-?`41Q}FCU;3Wvf^JHD9TbdNcgsg8* z-v@MxGA@16!(H6b2+Ds?dQ8p(ao>NT7aj$hEX;`mEw{6~)kIivc?+T!Z)6+`Ye6_g zt9)tzl>a!F+j^q0B4izw3u1-c@&`{u5sUU*2c5X4d*H)YB2573AqS~1Sbs|zq2V<) zB5k%be_c4><*i15^Hn@ZUiF|$08H}ykhw{n$1J9j;R-C4H<7OMsq3l>p6J2hE@DL6 ztpx30;D5oCO_u}rU4J3`;j=b5i{Lt1L|7W>RN^l8v8Tn=%VWBDKtAWF2=80OpF-Oa z7)M4;$znL8E8QgYUbs#ka?nfA*FZ|sKO;HZrYV?U|G!91py0Lz{x2kp3PUEJpK;QDoNlZPA=H}d^)AWDB?0e71MHmy_(NcOJD2jYa8PbO}$P<+r$j?PQ9Z&zCQ{Wtg$F9>RiaP;{KGJ{??(x-Dr$Y>*Mw;}bPC z43#BoJu2vYW98<+@)ZOL0T^4#BpMe!3ZIXtVAyG|rKn|Mo)!_B(cr$*qi;JZ2T@vT zS`F{?=jHdHQaLzhb;$%G48%MZpg$(Gby?&?UIrJUzQCh(@)PaJ399WZV{WzA=1p5B zE$yRZ4nnPVMtDh?{X0n-)CBq>{U~CDW%{`M8}c;4#oD00DlmI~ z$zN-;`)Q(7Au7f=)BA_AE}goq6_0ij1L}zP?E?{tWi&yQ&-uv>H9gkUSg^I6&&W$( zpW;X>Yba7<UBpZVFYv zdxBtdg(mAXKG1;XCc-nJ%rMDY2k&L!&tqsAZik|7e6V8t4O8MLns65J(9aYL>eQFcb(4_F}a0AoR z|LLA^4@`l47_8aZajoy}m5jM(K5w zIpNRqfvUZv3@iV-jRScCkos&VHrFrtP&aBkA>W>fUt#(+$SD4jYSA_GSu2qlbwwk> z)x%C@+|Os>IjrqOeYW)4H(z1xuYu;(wC@?pPhjj9ta1+#M4Ar@yy#npdfwK_y>gAs zYaIvr!h@j2-mxT|$epuiJiiLJ4Ma3FqpyPr8klgi{y~Jc89DM>)?iO3dS)+GAHKA9 zowql{4Y1~tuD$91IhG%JOF}}y>VpLa_}))NH6>^N&$wLOS@F88PEggAA+RZXdx!z@o?Da0G<@qPbL2wlEr9K(SxA^ zQP7;(LRZ-zkbHZWbxL6frBr$`2sv$UE4uR9mL3{qgFb3+6{z*P6@w^M+uwJ^?kyi~ zZ%BC`l|~Xl4dWmmTi1kwK)=RhA7AZHZhka}&rz_jYX>b$2uk>Fy& zJ%401dKy+9UwnTF58kpILvEtq4A=+Wpt|N(@nB8Z*E{^JhZAsg4q8O|&bof6aVc52 zz_emrl~~ZP+T@di(iWccJ%OY>{KD`{@lp9FKLTU358>#!CxQBn^(V3I??~nN9)%;R zt4RR)++uIuzTpqDZ1!{@#I>BS@uqdDU;8n#LS1#Q5Phsx_`o2(9%n@(6; zc%EED`#w-6%f)aw0zo(xk4mnKz_N)ZoFRsy3O64L6tmwXq`9qXgX7b`?1wnOe~z3UCQAPdYk%NAlX^OG%nbxett;a zQgHZVLa&jmF@HaIGHOnNQ&Ux6{|(rc`XZVtzQxq|{y|EJ(OdPgykkc5f+i z5*=E>UQ@See3#+lFofCtF~}mx^|R}5=Su$t6~CYe^Bi)}`|r7O=eVlg*M5(8&d_d@ zv*NaKw1BcX6vA-T&Ltv`+O>)dp#Wxmn9gSt4_&zwIuRR%D?VL{00d>joGHo}+l0^6 zSP&lA$1mbba$X|g^>2PjS$9ah3kMnLeXlbC=>E5%2nBcg4eEz3LZ{lmyF>Ao zLKymWR&%$TXg&#u4j6d^QQ*Ha-5i+eIvA%~r}2ig)7V@p4=r4AH%xd%0ukhU}!3h9F&2`cy815ri9evEev<6MuhPB&rPy@=I_UrXA^ zu_^4*ehgo-3Zk^}Cc%F<`C9Tqh?ZEv^B8t+b;I>}$e5Y3|KpZ~uv9Yex$3Z(03}M1 z!BLNoJf3j=BmUHMGtJLgd|H)s>jOq79)x>RlP&=E5L2jy3P}x>+S|S~f$G^Ct<86} z%+GBh+ygTPI_pwp^HrMGRBeo<3$n?jMSXU65dFDfNsiunyUGPKqz*}j(2q&|W zMc~mok2vwH*l?!ttqL5x@I>i7u78Fx-vW5ME_*llmDVK!B^>JfN2%{Lfrb6DT)i9E@ior&JD0vG!e+Ei>Z|S*R zF$cH6_NAW3dbf?b(wALK*&C@rxdNm&jaCs6U~1UAW^P~0R-<1sNJk+mBs7GjpnA3& zZz2!zte`g%aDPKD{ZN3&27Y{Py&c4BPIMVbsuAq|2l`!l7j;+Y4&c^?p8gw_2aJyr|(P@vE4Omg%w|HeTR{C7_&ZiVt(E`J#g@P* zsM7o4(MvO0Vb4XOL=GXnBH^D(?x_hgTbt7#y-_mb?Ss#SH99jxN&hDH2r$qYJOq`s za#eO;C}8Vrpr$(Q%w&mpN2_M?SsGsHfWeOk3fq7d)&|A4s^JTd6QbS;Y+%b!c?rGA zJlP2~mwLfb=Ov8%7|0M}calFU{T#fDWTjIB7cgvaTLw&uG*K6;5e*G^_9ge97GF*tIVg&`aS zpC(YQi65a?gDB}&CN8`s<4+Y0G8)3l1s_5l04ql=Y=^=soM1A_1 z^0>$UY9qA@0V_l6aRRFW#iPk?pjqlGs0h7|_0yf2MdXEc`9}&RbOop7XxQCKKPZ@` zb+R-7CR3BuOO)sLb$kd*#VzirrL8AlAn#CUKlA=ZaAWrU?HCw+ej2zhXooVu7 z(a&7Yz4KP{#HH~<%-8!Zue)7~K>jjSD$e(-T&$?BH*?dwp2d2`=624H zpzW2sH-I0&qSG_8soN_uw)AO2HzEvm{{rs``X<750(w{6_HFSzvD`6zbe}}b#}XRj`_K~5^`Yh(Rw>8(D{=SYfyRn&Gln@9`$;RzJVIwe2Wz=TP~FFqLNnPPJrPsTouHGsiYezmLd>9PVJ((U{yU6u<=CVDuP8r_!Hf)skhVfj(w`;(h#*T0}x%@*@snM9A0Mlxa6Isu3urXHQB2fToQ{! zUAk^pGh8WyIR~AMIs!S`z>@hdFE$_{5GZI6y$^3~KyrXb`bC)FSU-rKI&6{M0)JvU z>(J+7FZl5>7y)ofvA84rxp>MCF_IT6wU*^u9TuC9rUwE)aC%>|F?mnZLTX}hpv%6_ zhE_{28IGWQ_X?BoJl@X26kE}FX{qg#;2(tj`(1k+_{l3mn4h#_+exl6H`Q~7=?O(; z#6HXHl%~om#zSsjp&wg=b;JGHS}*AS-prfCq|g5)^dO5DIh*Vv(D&(Aj;>wd`i`j+ zp>ph;@bz}|+l7#3V=)56H$L25xW=2(@LS-P=87}NrSCP6pZF}6O>c4_bRxnB%|!DB zup5-0xREs9*T+8g72$M!yumQe`rh!{w1S6~^PZW0l8k-}q z$s3Gm=<}H#gLmm(f!GOSl9dRc}5b4Z(ltY>!OPc_pjpaQG(rSAKFY_Oae- zS2hosQGm;fI$Y{h+5?{?xxs14oOcfCA%!f!I3>xOB?J6N(I1OJ6TKXxJS2ErVrgh5 z?BNjz0qW0~u_5`%gEgqgqd%I?joYsaq`GY*G?odJ_so`)r6?wzQ`g@?0a>OJ~H-*ell#bCp3R0Y9wN57EKf?_9WR za@knFCDth;T>Ln4u|#2wTH15=0#!Jrk;2o#_s@YXuK2#4G_PRF2dcVofQpZV{MGka z7>7@|9BEp*DZs|;xT1s8dq(Q407ljvOk6Nl?N^S zFkPhjg>F&)+9uj8-<4sm|5zI!&kPfdUGAnA2x+V5T zFTTu!5?4;rN@o-0OQndHsw=BTjPRh(sxrM@^{P{N-&3bQanm_!0=!MteGo7Y| z-VHV;J%r*zH6^^kGx$r6D4+!k8JU;rm&-2^v(F=+H}J4^ESu&A3ECIs={n`=yS%~p$K15d6Zh{O9 z?4|eFuA*l(Q|6NYOCUh*oq78(x5aZlHE?uQHvw3WWij13kYangF_RwT2u!4cUvhuG zN%{GN$yyf{(JFt_U3{;CP3I;w0 zTIE;?%k7)&F%M%J;fRJ&)sIe#M3C8X2}Q1=Oit?zq>9Ogf>8bcZu79G=+i2nz}Eh0iU@AY76c^W zFy)EGkM{ZWnx%lUJTRredmlPgvHo>HAEio zcTFrg1%BzH&lVyQ`IG}4{T8@(0EG+1SD1-p; zjD!fp3j%WRcOky+zusi`@k$Vs&$o6W&OB*7+tiSgn`byz)-Sla0oRAgKlH`&K#CVQ zfDVpV61V0#aAR`TL2sQQAapdf`Wh`CJ~grhi@V=As40K&r7@B-G6uet z#{~yNmEyrKb=Hw)*YLvgv3zkre zXYBXWLoXZyMuMq|AcD~WYrIsuw|?_;8KeI8(m7}^Qy4io+DJo%om+mdFAyk8jwG6% zQXDm!z3bvYT=r=HJ#!b6ZHEEc9;?{To~CYYA2y~Ted$?O!|QJI&JFTS_prGDbJtH}%`1aE<(C-(g^nnM)#-h*tOb+k6@G`go8$|Rw7(qY|3)TRPgyA4y!cVeMoa>#m9iH=!Eh7b$7=p z_%X2EXE}x69pUG^T&~eMfwfDd29;59z(Xt7(MFlfWqa@nqE5(bG3nT(Y7^fY>|0L+ zSnwf*#9ro%A@n>Kp)db&Ty+NK=RbXyL;;N;BEobh%v*1U&pfy*$lRaUl5p4C(W-g! z*BR;|K0o+flzf{J&v`!wzC#XG^4pWlQTI+5LwSm?iy5o0{K|C@qI#Fbc-*rj71d*W z^PegXcRv?ueb^@?IZJ0L6BHsP^p@w}!Lf6>Uj5tR#tO7y0UD8I@rjV+sV;S5Ran=j z_Z&>f*s1>xju{LpHBq4WeMVmKqa6^+0Xp6F+8foox8HyCate2_5Bxjt!m^b}ZFJ{m zZ3sFgn%PYMs6Yjuf=A!fthbt&kF_yj`1@V|gkCQsm>;7AAGyji%^9N!ta!}9pH-;@AlrW2y&-L%{5tK8}Kn4CdSW^!?X6=6? z7WME!X#Z%KVQ9F6I&^ASdCxmJ@EgIpgD5QTr6}9U!rrTQ1~f3^Aq45noIqjZ{RF`1 z_l$}G^}Ef72no}C&^WA7dV$Y-x)a%(mF1 zo_=gxK<&QM;;bhLXSjDf+^uX9DA{chI`xBXOPR~hZc$_?JzFZMalS9i#8XnZ`C2Cjw zA+pHI`qS9g<9Z|oC4&lPKt}W!*85{;KL-h_OxF{nk*@J+=m|Tl@LW@ti;0{ZDwwvd zr*H``Bx$ji!zy*08>p;1_Z5xqY}375g`u+E`zU}Nk9*`7#2(_tTO&3zO{`}3tS$2h zGd=H~_cp0!Oj>N&Mnc2};yLKgp#q~4S@c-?3wFgUh`p*3zgP959#Co6nlpPbyZ`b$ zcHPH%zBr3MmG`|Ef1KJ3=P~pOKj~wEp@GomsN9u18qk^JmA1a*S;eY=Y&HGyy6Ls4 z^@DtVg!PTr9WRnuM+mF`qu4`2RiF!Q!;r}QuCVFPWN+G_ri zh(BeoqaOX#iSN5pvHu2$1W5d4V%7DP<)?a3IsWlnz5;&8mDAhegGeh}F3J1c)`P@l z2=4JP6H85dS%tJ&%T=Oow{V5h{@NY-q&QNv#HEDS=p}lM)*(o@a7@ zxt#V@Lgp8+bx#gSr&>|p`4xzsvvr^uzVVexqZ)K7PPu>g>R_ zvvr+(7~ooA@l{v2Qh2Jw_ZQ>CijCm6`X&d<4cwtZFA9C~b!Mrb3@1|Aq|vw|lAa|4 zpG)=WovQ6X*~UllBy*#A7^Uu3>iI%gzXrtm^^#^6t< z35S8=TT%SP3rut7icl-?1SSW$TOyd79u=^;M)jT8YMVhNj!T>sYvD$48xppacqQI5 zUS@}U&qzeMQ#8f>#jSBW)fbkybUySN-K>@|ryp-&h5*A<$;1-1+r&V{>UlH^VF)s8 zJi(g4r_2bd{UXQ72S1+w=W#doHq6fvl;0lh;5^jhes?i^L|7YnaRl;XyVK^w<_68@W{Izj}(09$sy0?ae&BztBdn^&dt4 zUf-qCYZBi)puadtSP05(D8j62oW&Y&)CeToZfO@i{J9G>f;Q`pEh-i18_Rt95cce_ z0^6V{aEYDW6EBEWh8izM7S9RG&E?ky z3chIF{0L-89KzC$SG65aaM4R*Vtbh42&_liT?nMk-Tw1?-UnBw3*EucM<6d*xH0;x z8xm8Ri1yqL+3n7Gy;t}MFMzz@)5FZ@?0yoqs87<*ZRcZsXauB(zbnE<^+=?Oob>-f z{*&h0G3ya{?oEoAUd_k($HC<8&*x-*L_WiCv*Crs1q^E9AcFT!U-*24H-#941Tqm} zoG5kDhHY*~)}x!(3p{|{r$CJDKYP^Gmv=j4`A|P?x8cCoHbghEf9=_Te^MprR{pG_ z-cKd~D9^ZEkr((0pMuh25qaL8_I_H)e!YRbyu`r3ypcBIw)hwJtLh`?DEdkiH<}bG z57xJ5GgE_{YwUel!zcvPj$X|H88gJ8#Eljn>`d=B*_K< zf4%WvzPhx((_~OW0Z>`W-`pZw^bi3;{*}m9#{5e8F~^2;^|J)$;kwKGPhk|Up#?~QvGxzl z*a5tWC&IIKy$V}V4R@Cm>2Fi(uCt*LkHh$kwQGwi7l7PGxXngWP7ayr&yq!610up) zdb;F_uJa*NN9GM0LV9`k3}!X9d?QMu5=TOSjV)daLX==kH z;Ymd{{xb{7}wMR!&a(VYmgVEFehCI~{BX~N7LK=<#n?2CnL}&F&Kn+^Hd7Zyi zJO^fnNyP(AW3y?KI07mAt#kSR%LrmNohLi-(@~CN#MMVYqu})mt$4z zpKVa_Ac`9=HD}XLB(%#`2B*?tXtCSL)b5N8MZ*CY>?!Y)iIV?$c(e>>dDowm#$o== zDYn6MC8|V~?i@~j_q{~I_Xa}Kl}Ah~a^-P&k_Df=dnIE@o)G>$JQf14YuH1>bki7- z$f;WS-)(@{jcTsRV+xr#_%t8MWhQfehz=!7IeeHV#KWV(2K(I`xV{vDs)47x>UsOn z!t4T3pPUXurQdBrksbz?fB#W-gX}#|xUZ@h$r;jkINs;zQ52{(D$3QHuC7}1D|5fH z5YezU1Lo?=8zGC%B)w)HMbK^v2$U6s#UT1{C$MKX)N&D1@^bDP0JX-4>k} z8r68nGcPTu;6tm)^3vm~H;`s8ef}+;{Eg<9t9TzJbkh-g^i)d~MbA^&I#-GiNg zFy&uuq+d6m%90J7eg~iO=6s}@sUGTeooi$iN#KUDQUv$q)cy@n@@g7 z=IR@jz;x2YqRxXb;g%oD7fh#Wq<+s6Ebn(ekl$ABsEG36*_$)x*j2{tHa#!t+vjxm zh!5rmZa%#~u`v*Jk*-UcJ{-nAtCsX8Qi5K7J0~<$dSF@ojOf9CXP*7rjwJK+9 zv}w|aRj7Q)s-tSj@DF~I*&3ab;m2d;-zFP$`xkkFoAapIJ%E-VbJOhFXsf$(dAFLA7psY z#S5tj2IYi+AAxABm~!IMxWKPF{%4g{WK=2g%f@trp>!yJt&8&SHd2;XlX`5etTdN~ z&pRoFk^IVKmbsBfAxIm`(jNJ2Df5_dy^h*wQ^hFca4LYdk_UzjFl!#`#;hP$X`lTx zQ6u%|6_JA_HP@-jF~wg&J;tl`oZf||f_X=Y)GOL55a?ZvZ5hm@tzvdFm-CZ{LbH!K zh%FH5T^1Nj2r$slA{cF}DQidU4O%Tz3m=05-0}CM?Z>NoV-UX3g+HcU1aIhnEQ|pX ze^L*>j4XMqmI_5YR>s=gVg8$AmDncT|5W?zSAoQFXL%odQ-4NT4$2&05e zFC1g9Il#ik*b^7Jg3m^Za7`&#hP_wa`YjA!;GG0ZDSGXXrxXRM&?_@Im~MMcvV3uC zvW^Xdff)+{@821dPgvP_{{r*g|id* zuHwzWYJqz9~|Kv95FFg+4EeKO)mSQKGh)b>Hd#vdv8%EqUK!#*xLec+e zoBn1?%*RK>+aB;uu*~-R-0NpwIODzR^`qXDSB6-d8C?tsfhZAPBAhD)4f?_I$0Ldv zZNGc9f?Ymb(2C&hcyv>)=_l|@i>1A@(aBUGe_yW!0I#UUa zb9|i4zO0DRpTCzV{MlGn3*92!+7Mc}0QvXf@=y2z!-sxf3k2p1o`n)44*uqK*W}X! z@~fMsY$ZaV>wA%s)o(5K|9JzZ=m_aB47o$=D!GMmUQSXV#@)P}M8xUk)?fstN&n`Y zU#hoLD04lwD2ajSb%w7NGw6~CYsQyohqSSW$$}&s=y5LJmp3!tJKGrDS(X~K0F^8B zP?O%SHh12D6w_K%FX9*HmYiQ#3bE~04P)$%wM*J6Fz`0Sa3gZ)ewjs*DiQ2B1TNcf zQL!9eYIWEzCQY%ib$b@6xEN(CC{BBkvwUjVY+(N{a1Ji$y3Mi%f6dHB9Jx#Tt)IqK z!g9cL^*{tmz{6*64$L7l&F<4@d`CMS7YUjJ(&3MG^>@O)G2rMu%_W!Lkexqp;BHjo z0SGnNhko?2TRJvEg*5$yrs5J>%Fq$g3MD$w~4WR=}t;2&$xW-!!j)x+A_ z~WAPrm!M_|5p%NvEA_(MtmyYX|= zN1Jp_ir*NYCE;JGJdOM?za`HKz@+mwi&GZ&OBll&8r>;cHf~z1-TK@JS?!}EoAzR8 zXAv+=bE@5Xh98Q*ck^g|u<-A0f8n)FYKnzR(91QieP;rb1KtVuWa2vR@9AE=eK&*@ z^oCk)u5Hw?Dby(blR(9*l{6R?@Qf{kjG1JZrM^yR^I83;D(z1$mmm4FcX((I$ZWBH z74eJ#K(bX-KeXTdCIF3Sxl8#`$ljjsTUFH?ZmczVYIH7YQAmzSgwaWK$d-uUMfiJ^ zZ2O&%7k$NA=Adk-ciN%65jf>jMQGhv+97 zR53+kKq?&Jm<}v=i6$x4g2;QH(i0KC42BjoL3Jsu0Gn5@hGoA1Fv-EdOCniBg6h&N z2&Gms%PdAV4DujSx|pSn!1QCoGwu3aR@O4*5&& zR?KA!Fig--o9=T9!P*2Jn8_qs9P@4B;9-Wx6-N}b-6hW7GN0x`cRt~Bu_UIjpCBim zDAm@nC--#z;8bkufRfNzr0o8~X4D#O4b!K6gZ_#GEI(Xb9MaZMRok&1NZX($-A>0U zodap^nn!u>vxoCKLy^9tH{+z?y%p6$y3T(UtJC8=fNTdYsyf16aMP53z3|R)-uhkc zmy3;>1#G!I!(bnk6pvW=5>7DqAauw9bZ;9h4dqsa&y1{`6QS1+USWP0WW&P>E6eYO;1L>FEtW#d~$Z$5-74I1;{j)H-0WwBk-I*6jQ|6r3HIm0^og);#Tejo{})VQF=#5o zgBzB!tR8;Yqbe1(j-4wdhC_`i2|w>nod+s_XhQ2;bLRFYTG7k}vUll{h2x|0lf#8l z5w2Jg0`vtkYQSN-dR#KPb2@>P+;CiRp%aC1u$N1!^~ruA`WR^mq;{zTra8oK0rUEQ z*IoG;AwPqnrH=%Y3Ua#i;)!0IZwA-s6{I+zb6RxH^-`Js&$_DqxUjl62d3 zrH6$x_2(sjWDW`%)@eX6$so)IPJ!#db6nL@zb?u8wNL_Vb6U&-_246KD)6U%kzjf= zsS;hWVlie}5Pag<8?(7#d_Te@vg^!{h)hB)4$HgIV zF9W6e_xF-;Ra&+IBoOf8KuGYKKVzp`H%MDVdBmebcNfWP&N?%*yu^7@kpd>POGe-@-+o#?nLnVy*Nf>Wh z!2f?iVGFggDLo$~LB+kOc85ZTmaC$?S8_syQ)v(thy+PC{DspnBD0sFv%0r>O#f(b zjlJ@dUd+5tg(x?v23@A?R2D$vd!Mg*N1m?FQ-7ND9H%O7zsO(3@#(2b3$m|V9G1Nl z18*f>EN1J_BI_7w&aRbBV-q_Zd9j^kstDXr{Pe?#h66@0OhMC>elR~XK2Y_2>DLjz zD9TO7l1|6>diDgq=i7A!`5u_gV4RqJaw+|z{BI`wDM#n?-FmpDMBTvu2e~tVAA$J& z6iJrTnq1cnLtYj55nsMi>eNjbhC+L*{az;^2te^-!>#fhn7g{G*YBBy@;VKL`ZXFe z9#L?4fAJAD4Pn7+>60*w(vPl9FJzYq>|kNa%KI>Zig^paJ1VSgQ7xI%4>9kV5JvVm z4`J1k{dxOf%Eyy}PQkVL#RYwNAfp`2F~R8_4_1!~X|&H*NTs8ns?~&2yi~G2{_0wz z$Rc99G_6WDrm5G{qDpzp_acRHdI0{}0wt-gLrsqj1ZhKmPg_OX%Rf zWuk2OE5nnH&zytaVfFxZ37;;FU=L&J_N1dSA?{$fPg;vKp43j6uhb|7h<*+uc+3;_Xxk3_;QcvCy8Tv9?PGE4{PPgM z+EoI@j6_9Wbm>8q@?DI?r4H1OK)6C?D@ilwnjS{o$s`3W6?NCAx3N+t{Ds={9&{nN6G=pI}laMz0rG2Px} zv(a9874}7g&{uafbj7ty?GwQu{gT9dkU@WOep{~VN@4TMX1|Hi<{>*?O}v=rkus}s z4{fo41cDq*Jn9f?z3X=bUvOwXuy7Ys$5SdhYPag?@Ga^-xA})KbxtL8jS&e~Aop5j z-@cA!AG+Ato%9dj6DA=^|#P=9`QqCoxHWOPGbnw2R^RbCH zAGZPltx7w_(p6vPH|i5Jlqy#o?Ng0qhW6!~HQ}@MZbb#E`~O3bl!*v>3E{*~<9ME> zzL%=RM26ajCUtsCEFOnH##9+K`ZqEyh~O0IR^|QRjq0i>DK@>EUe-=>_Yv(>Y~q{S zd(6=XndKZ$_$LkjVSZX!30)|5KO_lsQCAr|V|+o3CKu zR+t7Ef1>8o z{AE`2lcMJn-S4<5Ps=vvga7Az=iKeLb2QV=3Y_+tE|<8B5to&->VH@M(1kC0SbEX2 zC}a`kZBH}LoGLD5Dn~^)`fnJmU<@(tpuuMm*r9zuDg0As5MAB04m;Tc>suT1@|V|Q zG97v0Iz`ci`AM)~1%;@t#sWFJfZ&dG1UZM&Ls^D;^a~+U3GQQwVVm|Oz zCeP>WkV#r~(1MTrb9+ygcS9wFAt{vLs~G$ij#2$B&jkAr*UxOFA=hW0D*8eXI58jx zAFvKv!r{T%%9eRz7>sVRhtM!qPGuZAzGLwF{p&r**Sr%fhhrn9_#;yJB3mO%(4m-g zC%o_coxDAdI2=eHHYC(IT3jmb)s1c`7OOd?F$F16=zN z_6T}{+#dfEmO(P0V;t_t!IlOk6^T-#(b(M~7Zs&6M!mQIqyNmuv7GC@n)@IL%<4-u z-t^uL`=2ht%7l?z*E3{&*p28M%7SlYMb>`o0d2Tomi-c!9Cv=)#6|A!rl0K-O$d~A z{k&DFDGgtEOXdM_>7K3g6EjmZF*`YEAS770Fb84r%9kqpuYEiu@Vx@tj!8q9BHOMKtJu1N>!gASiJp71+%_3YRUY4MzP zO{k0h=30S6%DI71^^Wa&FmAxQ zJ5IvIS;|ytq5az1%sA@e__C_zP}t9qx=Qf6?&kTIO?0ZOu7{Y@a=I#91n#-Je+4vK zi2~!e0@io-C{7b})B^+-AhZN>Tb}QkB}jkwP3057IO!KC>_osO z)>!AIkjftQsj>e!9rMf4A5|5XSM~Pf4=R*lSrTm8ld&gi$bq4xSfyPL3^^eIu03>u z$#tV_X6fPBr#VpK4qi32-7-#m=`oo=6^G*~{Z0jz3YdO18V6gvSTnI(^V4BH)R#S& z!D+;2D=%G_`c+d=_ByttC5O%e(DLFB;&L^$Rvv>~ltXD`Wo;sR$oYpyshD(oAkE`XVUAo5H=z zj2~Z>)jZX^Sf2p93uz<@mI}Hj)wpo9%2@-V8vgdY$BwhrDJQEM-B`jTj~$XPdbh!v z27w_BGWrI>)nU;->z`%wnR$7m5_vY?9OX^oL+jeSfA7?1$1j{%tD+rt*mBXDQdzz; zX`(@ezELZOtb?7hez!WD3#;OV%k%yM5oKi0crq!;uyRN8H89)3UwC%x@)I5V6b;=L zYkEg2>aDVKyL)H{OWN=CFN<=UJSo)(^mFgRx`wO6M7XU@LUV$&A@^ax|K~j?WGzHy zqcK%XnnKo_1f~Z+Rfay`qbL6Lem@)1$WlJcQ7pb!Dfvj8gt(-h=D&3b`vlJ$*5s1U z2tEGL+YG9KxD$3KPtclBHvJ={g;5KD5Q9_^EKpOp;@6GAKQO=f(Nl&P=K7fwCWX^t zr;ZPQIP$$Nd9gxw+xSQ*~l+QYBrQosB5$7*C%$lv9J~lFryyA7w~6j5o+I5;%=c{3-|fkh7l46*pl_>Pw~cDHvA1d(66`#$4Ua+i?!P#Ib|fB{(ti&nRX#`4ST z-0Os1K3xkAQJ2;AOD%L3c-t=gF#cb;F`i@|zBgwNcIb%0xRlR>#eWTvF1I z{H?*y(Rs5`@3dla3Ep@uQ}<%_-For`_FJ zV^?+m+iWLjqc=)0Xsp_aj5%uF{(a@`Hf=gz{5sR8at12VJ+by?0uz6g+J6M9YwIUZ8Jl6)bgWN4AN^I6ea^H@`0F7 zm1@eHU#>25l1=M(>HOFuxyG@8JmmnP`>REO0ErJ*rt@C#sD%maWxfarhE?lgE&3~* z0nK``xxpZ`7V4b_DnqkuQ3z^#e^A+dmBRBg*fd6*zw-}z%pBOb``ze8tDeEAY~%}) zl8;wX84sU)lau#=CstA+0h|pa)`i%sfV5zK#kSRrRO22?{;HvvGj3&r>a)l1g?Pc- zYxAF@zU`0Ke>Im9ge2a4NBb&z>e0dqwP@W52LIPJh;UXzIxyXb24WSzr^b3`X;f(J zzwkbkK-(&I)eI|_zF~pz4?u6i2lHxYp=*PX#y$0?w)~Usg=51%=sgP84w;o;Q+gzz5- zP=?BJkG6?l*E`aw%=7zLV54x5oj1@z&@0SG{tbL<@o6WzOvjr~m^$l;DJI7B4CVBp z1XK4Zf8f0*EnnSZahaWr%M@;q>f!m|<`_%yZ+p)on{7cB?d;*BK>jt~Xj*Ggnsf{d zir%*I=d|d2dLqn!xW`C^A*y0EX|}$ldDJ>PvWFu7a8Fi2Rf%73-}h3OcWXNVi}j1BiN?lpxdbNd(`*g?$B<&i zd+s^MX`%4O@n1W5Xh%wF?4cJGK9G&jD^-Lm74{|V8)yTp%&OA9f*)I!D1*0>tA;V_ zA%t=8O>d6YpQCQ}IZ=dwhma0@{h<&g(LU{smZ2DDv&KrVJiRYLHx`dd#fjB_zzS}{ z_7kMcdapVF(aUt68t~a)M;}CfSoWd%DHRXvJas53uFzlTPl7m7rkMMlHh0>($w}Z& zJy$j``WyGM*{|cTgVY7!qB=(6aTaO=d{EWm?B3kQf4peU2@c}>Bb-jCc$u;#l18oa zYit(Sn|ai)4qJmX1cRJKtx}Iqlo~*k#)I86!Tl}rB34)xH3J!Goa|YowcA_!ri4jr zc0??ufN)|McPhCH8emW$)rFy;mg?vVJS}z(Bfq$Ot$H2tEHD#-Udf)oU*In<1|48_ zIEH-61(n(wl16@THl_w_ia)7jjoAEbX<4Rmt1H;{yy{Eit$AbZf4B#_AzW3l;CQXp zaDyeZ<(KPhYFU=;MLlW9afLqXmI^T(?zyK*X!MwVH!M)0t>73nk%#TQt?oAh=C1x? zXWa#le%S!v+Gps<_?hIM$_(pQy19@I8MCvxyH}pmTSykJngmHlg8=thdBWE|Jx?2c zB>evf`|7ADyytCLK#&lSl4c1B>F$&U=|(`hyIVn)5+tQdkVd+@B&9o~8>Ca=-Ca~Z z-*et`et+-o-8=W0JM-MRGjl2G$DUzUQ%D#4U5UYq2_mO3(z3KlL&f_KQ4W*#b*T?N znv06#nnxpRmnKzzrVT>>cAvZmQQobf`eNQKW0;wNw74Hy)jv4Kku3j%URxsD?47SG zW?NvQiLsWy!R4v>L^oEQ{#IxHcX)OG^#}B5PX%Iitv>_ML5o!!Nwk>oVJ_X&boH-G zHo!?S#e0k3_Z?2+i!sf?*(nj6R(x(fpZ#m!a=cZ?<$BcQs_Pf|2-1m|eA4Rz)yW`Y z^IW~Qg*<0V*}Vg?rFDS*8UD03=eK@nuP4A{)BW_p%1M!D7gHzj`dWg{rg#r+&hm(M zg&vd(geD6^9S30TQ{CR6&8JlR`t)EViK!0a(4PN@C(?>V&}oxD9H(j_Xq5be1=lnk zB>*?OJoZtLW|gvZ8brM4KV@R2uh1R1V5Xd(&C5?mS)XcMrpOLAO1;XFsX&i*5bWOo zzqq50+^&@7RpmbSL^@J;?)R~=rS!0biGy-_?wPgVrwV9OAHui$Fg2vVsRq4WM!%^= zG_r^I(dB;S^?<*%J+NCZNd^M!qBaZ0alHJCEP71E+;f88aWzo91y$Uny(gpOZ&Uny z-_!>X+Iuf1cp19HskbAT;a}CY!KplM#|nmjLpuQy4u$GCgcj3v4#H}tc(x_%dD5XJ zw>q}T%&z}aVHj9g%AY#oL7T6m4HgoeVeLwshl{=nwjPb;er`p-W83a%hx`$Q@Oy8# zEe>=uneeEaFdbJjM`B+69G#&hy?Jp|>83P;4t)>=k!vsl2lCJ0|CN9A-GgK{4Yez) zL-rFwK8$>W(FN$Jg$lB)kk2=LjjKy{FQ=?lZ%}^T`0(~!jRb;VhMz(&bs^g6D{736 zVqqEkF;-{hEk@p+j;k>!xafW89%KN>2>)L~AKdj0O8mf|OMci~W0^Nkm?6+cYo4BO zQPaZ*f($sy{{9~0D4OG%ulTDs=KKN|@r?MX{ICm%?3o8NxB!{K8`A}yY${dyuJ5k5 z&IwH~9?^bmf4CEF+}{RZ2D5a<7T6}NlPNg3kJ&{??V*SWTNDqWEKPu$^N=Lz(%OBE zD2wEIA0YOl_k5vlo`NdwRw!f$)3mnfL*SpIVqkw(Mv-qC!>5zw?t|80)+pO8O1nB`ken z)8<^MUvTA%PN`Ye5_ch= z6H_Y__-+XW0pZ*|-rMfpU0{9ip<8}}UYJ{2BR%*Q7UXQN>>5Eh`*!Am^n*3$TZ&|H z@t9|H{p;CjyXOS5EdDY@u!`1sILT%5WQ7fi5TqfRQ|(*eMZxuMO{1S6?mX0-Dl*6H zIvyS${;Yi177LgLCA4rwzT(gx(_q|AMh#1L%SAGLYLMYzN3Y18DShQYLATKUQ4riS zeI%O$X1K#9k%A5lh}pvW4zI^SrU&;gCWAi*9|ZT`l|OFHVyiS$375Nj{pqLZ--8-i zLfIP8Zai7EV-QlwF|evtO4#wc(LV>X z*o=h5%AGIcnEbVZ?fpRww-Jr4uP-XK9+M(cQMt0%eEc*<9Y^MC)0l8l%1%QJIJ&t} zbe@`2^lkM6Pw7wuZ=7`y8VgrSLZd2W#b6b$iUkxipNmnkX(2?TmpLRTmY7<_>ccRj z@&x$`sax+qY4PKt0O3+xVCU?&nZJIQN~k@kn4giF7{8F(mL<}Qe)U;w6y_8NNDq4U z)1_oK+sw<+#N6!SExy}`fS`%kX&6Waz5lUVi|y=M*cj$_(_ad1>@$12nIlKFB zfU%YP>?$#O?v-XJCkz|7W55`bQK9wEn!(y?z&0GTo8lUG&x{vZRETy`Wy&}ZCOG`c zU zfIO%Duq%m-XmA^O5-Vp6WgGSN9Wdv zCfP3?KHL+I(~$@HJ}+Gw6>1EOH&Z0ZzHX5*SJ_Kq3oeq{`X`@yxxDte9!Q30e$tH9 z>2sP-sJ8Qid|v@t`92@-mgG9)gqbprowj8-DS(@sbNGA&q#pJWMh4u7!O-8<=c$&?BS}V8*9l|$v5(KMG$m!Z z_)Kr%GN(zwZH?iw3RDwG5)XYi=<*p`=F|*twS=z~P~-TF%HLL&Q(Eaj@mtosKZ-&u zW)u9?Ba^TwG!kb~e9E1+@3 z$!ou1Ztryb3WLtXUy|1yq@uakiN5j_>qQouOk)DFGh~_m$hSvX2aFsxGRA8r zeDwIH+OJg;XQk-};_Gwlsy6^KSLPzcT?e0fGC8?pPF;uNm4TVPQo|?%EWd`&%j|y9 zV9LSdQj>GhQkRhU6eg72nthG2r6$&htsV2z94vd(Y}S1w;gIkFzcVI(!br@t?3dHd zrhByvkEWlOxdj(JE0cj}7DT@DF$Z;?VWgxD(HK}d(OwUmQPi0S`C@vlwc?-6k7bKR z9rz`MixYX;T1vVs+n@7i0muV5+cfZ5(wUqOx z>-Ugywy#7FyOexuUR$HUG63W5+y9q3p!}UZ@=gBkZbu0(`+~7-tJ=7}_9ep!=K4CVJ{LD*)ZENpEru$FY&E-&sZ*m<3 z%X8dJv`HoTlVlL~2Js1DIQqwZErPmKo<8LyTTz(g3Bf-ZLcX*+TctIW{Un5eXcipK z(LbBNr9IDLU2)0(9K@F;_CiRu9DlnWghs0UcjjH_#&Aznn`&}3ocM^ZUF~P-2faH}RZ@qpQ(W-J?Ccf&L5pxk?>z*c%Zu9X3k zZi-}c$?;9|lWWV(&^GhSmezx&O{;IA(cq$xaM0`eVk^!!(L5bEbRm87NH4TRDH>TV zsJZqIcv}!4P62LHLcex!S37aXXWnUwk<-Mn_gQCIMo6Dg9D>Zc2}aJQm&{(#+T45o&oqm3m{-*S#a#IGJ}+RRwul7Yd_(&MC8j zh>tCI77u$wvIQcQO1EiIuw%wQQPvwxCCM=z*h4^@ezUH{0!)n0bCP_VO{Pad+dVYh zbQX^F!2|Pd)nK*Z?^tS&$3M3?_*>NmzE64=lWLiI@FDsoa)+6?DNTb|d9Vp&EP#LD zLxSF;qp!(SVc88NA*WZxVba}Jy`i1KMd+DOwg%aHwUHS<+%I_DQLR%Z1ITh!#$RVG z{&o8@cM?&>6dr6(M}CDYiAyE4aX+0S*bD72HYh8}_MK?}kSVTu1URgI+BWdDC3jyo z2=^8%1f6s<+uHgDd2^=_VBRAv{Y1WLO8H9HXS~0<-5)mGZ;HIaE6LU>wxy0$yXP0U zwH2`4C7dW?D{x@0bd#+^M3{pTp?DFo3Fi^ ziPEZurEd!QI7F$Um%p_Y0^!Uj70`GbPHbH)tNqPs&cEMTiXj-kvP&-@Fx|A*1R#T- zVL+|_Vaja8^qkraXFGyp(S16iRv|4c59=xUujF=0*MFT3Jci!dDqb;|t`6|*Yg3}R zfynEyj?Z^am$Z<}%j^~fz}?W(?dH)$R)335f9W9zlqU`jP_rQ17@5p=&s??slI46a z`>V9aMOoFoypy8NMiyi*t|cEah%NDbHN4hbifa3&Vu2NJw)H~$$Q z^hyk(-2|?BNY0{!AN$fMf(GWja~xDpIxCtti7J3A7`sffOc0F(!PKdmz3-i>`E{<- z%$13M<-i>*&y(1ph8Ps)E~<6{@f47;bj)_lg@*+q(wf}#1hk6ES9iOEQCdu3zh9&N zM2DL~hm18fKlJ-|iuO5Dmg7onre@Rm?T`zlDr>MreZY&GfPARwgN#N0f%{C>v*8^z zt1Epb3{Of_ln_0ygm46079Cv3Sg>_;_ofo!ghQRT^Rh?7-eHJtPQbtLwGZgA zee|!*q+6#%7H!(h%loX=A@k`jO8s zn4aV9JSmwe@!{iYjT}C=Lf@c2r>m|F(`nX>(Dcve8*s7#0r9y5u7 z=jkZQDo?;LwV9Dxtb$F!n|9%MxIF?z_w; zflJI9v+!5bcWYW}@<0GzMoD;WKXUrzgvV&XvJPrthpT}PO{}h$jXz~kroHTgC4fDY zcB*|u(}*H(bmy4@WTJz&i@5uA&OcWXCPG)c`$+_{ckiQhei^pP<&Os3qtw5RZKw!E zN}8EG|DH;*z?tIN6?2LLUMQdIH=KGc*o>UXcZHqfojK1X!(um+uGrgbElH5&_F7?q zaE%Q%@0-$4B{J6Z@{$5nNi|DW4g0=j3h5T+baf$|VL-MmTyfsNYaC6MQ0HEsq=cX4 z37x+M<6T?XmGeOLG5>BkcD0_+GptHr##1 zSuT87@wvqlu6F07Coad{ictdjGfDL(M>tV{XLRZu!`5owf_x;qjZHRC1jX; z@sYJRhAiL2-0{|sgBvxHFgxKtw+xi5MaKom9iUtnPJ$oBQsbuHmTis~aCQ#R)In(4 zXu)DWn$}Xpr%b65|1@?9rk<~8)L=qFy9XWZ9y@v(sRWIgDNbZX-Gmvy;0{lnz5fak zAMg$7;pk9PsP*ef_DGiyMIHRN>1&nd#F72rBIYL;kcr)21X&UTqpGmJJa>LY?8CB8 zE!}2F^B)1bBBhvggC(9H#} zYdLiHzV>i9x3#Xsv!ePtFE6H)GZ(}c#E#r=0y@;P{O6ta&G6MOmNb+Hh}g_rpy%bL z)Ew5V>nfJKijvvn<^mz*Lp#Fq7-?i%OH+cXXvWQpH5J`H{j2TNwhsO*p+wZn+>w63lKeomthoJXkz z2Zy>MHC3{d#4hj98V%|{cDFX#3}DhN#EDWV;%b6g#_rgv82`}aPTg@8Q}ZgpM6 zLa2jakHs?jER!q>qm74Q--X1K{&yIX=ZX1Z#)DIg>jfRo#OOcEB9qnn~fRY95KXPb&E$Y4Z2mHQ@@5ujBa6D%P$AQExu+* zPbtgaw%6wo#Fxhn@NRvB?;CDVgRmj0LN!kO1>BOCwUjosojKFst5h^Wne0ptoj57^ zH%IPK2~B2vzgH;#oFdooW&A75dAseZ_&i&!GmO1)b2vr4mwn9k6sXRG{+ax7T8-(e#W=3UQtKp>&$RFKCF7rtL z6nBwQ_~q;)N;vTKnW5TKkEbcVffeYZKb^r9^Bi?v4z{W<{RE1&4HZ4;gIoHhf&3n>6~8h?M>BX#iEfXWJy`0I&P zzj=yAE82K;KKlrKG;kZEa-F#lHsUiO8&rC9pLYp_9FNw@pKt&4encDVHWMH2_QRuM zgmwm-1rgjR6yP0UHCFLEH^AdXI&GlmfrmMJ8TNqp#=sG=BygckOw3IRI^m;bfo&*IA zn%|%6uOl@-FapW~5gMv!i@>4fYtr!d@zqbB8=QHc#DsvD?y zCvir576A8m=jwL%iEy`eNkWFXqT>{Dw{gc1?({jUP5gexsNy)H@@lGuRH5&*7VbS4jJP#r6KA?0;ku9Axb$TEVi^3DqqcLj`-LS zs|K8VJDPcz-&&;v+JhfB0ssfMLx>VqPSTZb0_vg+H)Jij56f=Kt-eNpihp4#c|v`@ zLLRh%KGdVX*J?S{#J7=Z#&@dhgl}(em$wFod+liv{|T7J?`%z)$W(wA*+wAFF{CB< zB=5ghlrP!3EoeW`SQCUw5cw3IOl`?^w8CIirS$dQ;0DUjEkee*_xU6@d|1>I&wp1Q zde<-UzHJa2)>X!JpfdN1oYh4-5YhIc8#Xuph7l$iBeAR|HiVZMmMk@@WPt6zRc{H5n8BOBEc zbOm&Q{m%yhVgu1z=Q*wDn75w$M@`ZScGVxcd2;V$>6Ygd>?CM z*dClt^-KJ?73=IL!O@tvGGu{OT>Nh@v4rL0 zK)2r;p=qh$&t2TwG8T2Nstc^d7OKZoOLT{|nf|JrzMq*fxCvOz@ece6YLC>sM>H|@ z-f^rVm&?l~cv?tCE=!W;N#(0AV*!K2hoy4G86uSgijo$-^-e919a7LMp8j!mS-IPW z-{(AJuGu1|3 zVM3x`jVfL`BKDwjVAvcDD{4c|b_O2%nAX>P(9mq#tkPSQEAn|8zA}n(t*!xygh61_ zf6<$$VaIRb_^pH}0mjyVTBgpF=d<~00jqnC8jrgX)Qm6vzCX8s7yY{X>m6rd5b%^D zFgsBsl8uNx3mx>M<6mI5BB}Pq<$3I6c%U|4BX!VMg^zkte?fUx^dTo$AZ{{YL9Gjb z_v<_*iraqHa8y4n$R8jSY77;)|kmt_bbZ*s|JesE-%Ys3prF9BW@L6<3c z%b=ljujk@Jc@}KXIE_JT=9PaxPxH7vwErFt+Du~9c3#`a4zO<;`3s767$Dd|n!Pj( z&%eAq`={{DdyisW1N6YO?16d`cpES9fk5P!PKfUO)(@$yR00BO&p}6vwNJ(?JF4Fg zaMah)5$}yNfEsH?r4D13Q(bH7!#{N`41<0>_+BGla3b6@qx!#q%W%k608y3c)X;R=*59>l%a{WkFp`YZ-4=xHDgqk$yH$He|T_1bKr82M)M-w5w)sD~YrT^b=BK?4ce4j32kF5+g?3{y(x&{9k z19mK!iNK{7NcQ+9YOXGTTZ=2caZuud>R-LgD=pD2(fv+j2RqKEX-Wj@t2HqNDOUcw z$ZJ$2D>0OATQ-Y9$lf)KPp3SN7yHh9{y~l@}WFj@4tY%Fz796!AUqrHx zKy$0T%mW~M{H9x5`^HyZAn;UZsyImOSssw5!2%w~33;TEFGu+onB(#C;gROVoUS(K z0c}dcvK?05HS5s~qwD;1Jtkdd>g$C}6tW_)sjVyQOhy7*P1{QsMV-^=^7{^Lha8c) zwqsPj5FXc%@H(a`|bzSWD;e#7wb0cuB z_;T1%<#RK2TmtPxdWD82ibD$|$_#@>_)N&a6U#!sF0<7y_a5-j*1x1*ge7m5eu?<$ z%B~=U^!H+wvj)@xI9nk@mkNRf^QP@sZ6b;o!eFjbMoDiKEw(qfwNHb+D75|*@{MdY zx0UxS8F*@+TP^9SY2gV!#Pt6U`MgLamIFx9-=d7>a2;Z88XleX6WM+Bw`>h5Kx2xv zvw*+~u}+|hYte8?BDzEw)VSKbq2RCZ6ODuJz&4+*%T zZnq}a8(g?joNHAeeF9A%Xg(gYv7pqGw|>|x#r>u7P{1@sw4A`pm*g{}f31_E@3ZPs ztY0O$v1Q|Rs(fUqZ6<5I9@OE#-kjNGDRutaAv^w1Rt*2OM4``F$94?x8__y*Scgb@OPeqDMXC99|Igw4pu+2shF2wh)%+%Ph`3FVXG!~1S z5ar;pDPdA~aQ}a_uIh@=CHC}fW-O1&JJtHmg1|WHFC)n-%C~));~%BlD*$8&u?4-m zIdtR5?b?ZU)8~^&k)hFSo}`c7jRc$ z@Qq(eRB+XV?4At#tww<8R5-TYJhv5*WuP)gFlF7Wn8_{)*oqi@zfUrNe1nfwg_5g* zQS{fryN0|cjbG+CsbC+p4z}s>bUc}TX4kCXWBWHr=cI~p<2qhjnkp~dhdA&E11}&d z@-NASUjXxZHEk1|*5?v^xA~kt!$Ie^8#e7Jyi!hqcpJEn`OjCD!P9kG2OvtzefW@g z_o#YN6RGZZE4lll%7{G>3Exo`;_eNF5X@@f9lmx+-hZ_wAV|uO`csq~R(uriGc|Ny zeJrAf{4dmA=Shnf=O0bqW>d({wR6v;&MdiulR*0N9s;?TBABylf;LoBOciMbuQR9^ zv%O>=Bm`42%xe5gv^LlSeB)c5_%pdc$|>%%k9HWREr=dRQ3G`>f0HgHCzlJj6rRB& zY-@KqI|O{uzF{kQXQR5^nJ|Rp^)fUZI=8_O!q7KB!27DCx9HkBH`XD6G`%96Y{axh zNb~{}ft2@m-{D%s;d&^Cd%hthw3I9@CJFRE{S4k$_r1ZF#`hcx3@Lus|LS@3Ls<%W z#?AEzpsR&CJIj=Zt0%(?Aj2@KV9x8SuiUFkUd)JdWLFv9fkdDk`?#jRZ&9U zoq~Aa6Xf@M3vtAbYWH!#tfqRi1_gVWfa$zq_aX(AkRb0@UAsk|awZfgcW;BMfNyH@%zag`{YAC@x;m*8`Q9L`2~OgxDcKmLcQ>(;!|q}-cGSBohrB#fh}Bfly&c!Cx;2Lpy7!75-afM5}$d!_ey9`N28)0A#4I)|ghj zHG_98ERkdg1wbrpG5)B*1@CWw8Lh|0uFxB4xW&Hn6CwkD$E1vuEW4!XfMwNS zF{4CV;OJsttDtcMX+{ijvbe2U7%Z>P1;rXc!v4t%zl*uEBW7J>C*I$g2^mSCLrX3J zhp6*^L797VEEA!Im;W}FKuv7hx7xO^)&Nx7_K%9SWj`_KF24xP|I#re0`#uAZ6$g2 z50rHJzL`o>)ioh{{nTkAN+dpTE+G&Ww~C-9(jGs-0DMRGh2Z= zxfa%gkPOkwN^ zLV-)Q=`7zNo>z)*G$EE75MXG;?L?g*Rxs<-=40fokS)`Top@J~(MgqF1CxYe3kL+` zt|b_zMf;*YUE+I;op57OC8#M|%R}jqUc-bRrT+eZ%cK9VtpZtP2rBCwkp_l0+KHx# zM?#-`>ck0#Qn<4U^DFa@D@3%ewthgjitwj@)Fzojl>2){ljR5tbq#J2=eTrxY#In@ z5gMw5MBPgF8ZKq96sko|AN5-snm98~1e*M%KJM8*zr5;Z?BJa#XeobSySIOp9Gl=n zejeC7jt#QC15+PF-l2C5na3(M%4|Q3yD1V@bf-z?_uoV*tF*C6JfcUs-ziwX%8UC5 z6zvlIiVm-)^5<3uVURS+Y#NspXy?;kb;SY5tlwGB^lB0`MsmSgIQA=2knc^c$&$Av zk!bn2&{eD0K`?=vE#|37>m;@gUdi;-HxVMVDt}>1=;fo@l906V(mYWc95st19@Wf4 zBvbwg`21A{FXls`QhBh5{m2(0Ns|S@QY8@Z;XnbwS^zzq7qhy_7}Ez)dGopN*hE}0 z*Imn#Zz^?&4?6|6z|kZcn_KQN>&>ex=H1s%i%vhgi4*MT`N@9!Dj2;&@gDdfgY`?IF@gH&@6}CB z+Ozg6&w%~yX`*0az;d3|nOygI&!^#AuN@~xyr6$0u1&))>2;cC$i952jZkDs0QdU| zLTqlim14+;xGV@tmI|MH3~`7fRlEu=f{nfJ1p)a+Du=RL{1efi^y0DA>Qeynz>KT2 z2Llc3aFSB3-Lcs*(9f=q=bbGZ&9IP=N7E;5LogTgEJz3%>-|H0PSR4Q)KhVHW5&I! zC~HuBHGz-0>tFeX)cC`i%JR;KQ&Ui4IyEqAVt=?9LuFOT#tr)iBBhr^By1ysV~;rnVu$o#D@p4eEC zCY2x(tBuMuU46Nc*K`8+*(-Ud2otj!YT?)R1F#>RhE+;2UC@kMfkXO`%>v~huyCKV zAaC{U65AuP#|W|1(X5_#ret8pn(vd%ZH@8jszZFn@82+gILR@Ra6fT(+((XeEk`a# zg5P1;b&PwqQ?-^A0vD5fFTqDTt!+3R3l%1rCFi$Qw)j&TJ>7Cl2V(GJEfgnxaPR5$gC$;=p7Jgv zr2Q->pSBmb8F2gf3>|)<0v%Qktnz^Cfv=H^l6m1;-{e9SAKx%n#O$bD0Kbw>C~>rN z2gfx60SoR%`o!_CGbCHr0PkYn%%aU53I z(_D25;8Pyq4WyZgm1AYyv%c(6DS@oJdv{7YCbh4skEL}OiQ|!)QoyDmCmXs)9uqFg zB?DSGWJw|RhwylKzYK7=kKRYR+ls>@C%C_AS6GKUR8asNREwM!gN!94`8(*Ka4CH{ z+*fb)d+FG^aDHK5vW-JO6P!Ch%)I<>kV)(%#stMUcgt*W`Q#3qO9daf2pKEBJ4MYkqniPN*0YR*pY=~TEUDT@> z#Vd^u5)?4vaOdiUpw=UMXx;}zqpUn_jkpN-x(V8;@+6AbF43Ht!D*e}*AgM}K}K)} zI-$_0Qi~k%nfcXbrRvJO310!}AwabW^7--dh@Q)%la&nn+(4!of)&o+j3uBe{(sbi zfkq2l=-~TEV4-c&@Z4D|f7WXj)cfcmF9XkLm4=@;{Pu* zCrs=*e!n75&lV>IqkHF844reU4dluCuf#KeoY=Skm7J0zr5iM5bwrgSX{QA`d_f64 zh=XUCz}RbRyRG?QlVga_K)TU=k^(Lrl%P=zl@PK9SK%Y5A)yk_zFql9`kPSZlQ`0X zE1fVr@2|liGBUpfUnYFG82>IZO@eCrsr%n^DpitnGArwZfN z4CdYE8_HyQ>Phq%e4|7dMDZ6(qG-Cbl$(^f9PZbtEngIW)c1@=fb^&y!bgd1>)OwB zJ?!AJSF&~S&Q``g1yKbTiO)P-2+A+o7e=_TR#yi}ek#9JN@hu?LhWVqylV#qNub>4fwtuUwm^;y*ce_5gMT!tyMue5iynNOiT*T09|96&& zlv06p9kss|D%hkYbxhVR{fX>Bip}>#9K2G~5ojAN!L=;})nO7@2=jvBd*FMqrn>uk zTkz+GL`fZEE7Q{z+9HT?eDt#%upkZ43%>^|+8MuAwBsRepF2QfX1H&~)KE!q1=jgL znLywX_*y_O$l95o`PW332Kn_rc$)GQqe98Iyw~v&0*7pz_9N=8eb^2RWyX8t}Y{u)Vzab(tnTN+f{)# z-3J8gqhgzHImBMh(SMT)ovc_9e=n?J77@*AP2~?DV{P!JEGF}aRh?4s^+-H1#9k_U zf-(73_z;l@vHzU_29!x?ld%b}`naDelk4c~ue78K1xU=A4JcSQayEqW2!+Q30kk#} zjnSsgKcr>@yWKr{ZP(szOe^+nkf12)zVx~=;|FJfChb1;4YIGVZskicLOo@=*-@Xc zkft&b@h9>e(i4IGm-1oU?#Apm{B?}&v2KBn#7BjqPeaW=Lj3wTg!a=J#xMH8QG<6z zY*PyirbRv!h4Y}i0);VE%YwL%(WC8@Gz0od|7VL--ah> z1CB4302D-Cf}WCsWiNhVFBJaHPgXOvkh7*Ls@tRBFsSTpx+DS5 zvTa;nwt3nfaxCP|7g;mm%-OI^ozyhl&0vxM;hw?XJj1WVw~|Oq#|SxZOGkBp>(%kg z%jTzA$-T)f#00{T;bt)YlREtSO4o=f?hiUYX(Dj4=oqI*N%O9O5kW$jXpPit}H7`W( zXD{-m8u@MB#%9#(Z{VtW8i%i@$c^D~Vy^=~s(xCX(&pb`#KuoeF#qAU&l$UQzgE6@ z#Npb&3Vs4VM?Eo=o2lY2YP}8(6*IE0@T9NLOu)f5(*YGex=YePa97y~!8!d+!DvaRxf!)#X}GZEql4D!Lw7N@;15_FIldyxMV_&2}Yq zps$jI(PiftB_{CV-v6F!guYP;%_;GxZSp1D7+lzrMmHg<8|1Xn=%hFf6KLRTXo8Ld1mJ0VED%FK+eDs& zGWk|1#)O{f9BupYq8pF2;Gfe{LhQ*cFmoJcR^>5bNX5H_rVUyiIG(T4O|7+nZ_66s zWPN+ig93|fQl{hg3Vb_NxGgjc)pDx4^8oHjBvd8G+sF6o6!%TBY}e^cLgc362Q@<~ zlk`+M(PyN-a2WnAyR$?}pMY=?pFI@P)aI>_NgX>f#KJf}Fl2R=@HGp-@6GdQEFZN4 z;f&yaO~verf4=)+YkGv=nWRijo7I@?Gs}INQ_0Syos#hp_ zKlb;ei+fDXZShO>!6J(ie1 z;op6h&x$&s&q^d`Oe|mk@kQSIYp|3b_amtMCL_CcI}^?tN1_TjK2aHfGMFCzA#nU0 ziQ@@;U*>|HOb48rq`j!nNN|yMKla~$Pp~~AfPPD>HZ*|bRE7I8#jP{z&v;m zmTmVUw02n}Riaixr^margQR5OIZ*dKc%gj;%;!?+O9mr#mD>7XVo1l~Fr1~2L< zvGJRTIl{rw9<@9|S8(q98}j$8#i6YUdnaMq1mufWH>1-G)Ui>g3WGC-G<#T{u#(_& zh$Z&SO3ab2sePM$b#71#ClXsoEB4fDt|B{3EZbcMS|H$~r)u+bv2(?VI(IiLb{{1& zb9i0Q$??e}ykLvGV3araodnU$nke zm6433B$G?i-CC`+z{4<0>=uJ`Q|{4*?7gVbeXrQ@J-_FiKycO}CZSD=`}V`x5B^SJ zrz#X?=xea=q~T?O<|Ld13!-tNRuf%WJuJVmKedJ4;ZB1?04VK*c(i8k#fxhQP;3}`*$L)yLEStr=IDzKnXK)) z%^_3r2hn5F3?BX#y^`BQ&-3a@N$h&6jRh}@$l95*q(1R$kt!MdZ z_<5Xa<=O_f%tS8gQ5vi3ks-DVuEgNvr4IUs8VIU@@F{s3En;pxb07QfcQESTQojPUNC6#z$I zuYDEWsUI^|?a$`13dj_@_xITkBGDkF*VePEo_+~lc>^8>a@MB9b2n5hj(fa66HxU& ze(pN?QG8vR1N{#+@Ec zonRXZeovdky7yW3Sqrmhg{)sQoQ-^^#VV0_et%luT&;h!u#{wBm6RxK`t`(&n~Sq!DxQah%|gwVC@_UJ|X+R?hiz zVQml5sMO#AtO*k+6;hrGvgc|!FR1Cjc<7V$nWum=~ z_uCMPJ)z*+F4~e56FP;73QDNhM1$&!e$x|(GC;He@v7lC@P`qnOaHcD@|8D&ndb%o z6iV{%yl2E?IYeXOXoW|9OSr?zy{4 zIUPOYH!!Q<)EM$M0Sgsd`R4ZsmDozDz=bMFROz9^&p{qkdPu193EKB=z%c>7`Gs$A z#83P6uH5+jk4Nc@cG+rKRAOIb6PF|FMPrBge30Dhx z*+q>{cz%OoV)<1R^V?%4acOTWrq_jG8SQ$i?>o+-2Z5BYNNH0{ZGdpmR0Sh$L9t6c z0My+v_aiD2_7$c2RWHV6q@{CvnZmC?xH9atGOs4PgZ-=(`=ZvDuzB>f_OPb~T86TgxFyaeI;v1pdLqYq)%0WU=aM zYK92OG!({#Gq#XnR^2O%Jhx@D^q?pmiph7Gf4onR%Vc{fPx3vB5C$6&r2^K>hHD+j zOdaDdWkC2Chu1WE#Gd%c3f&rtc!Kvb9+9UT!-3%WY@m5X z9|k5(bvB4y$&tu!aTmV)ppKxQ&3`t&jRQ_Ba1E6-a#8>rcdhASr#GoiJQX)ubEXah z)1N{>vV)jVOzLJm=oNfo3bo$DYV>PXMq$=OUc@#J38-i-y|AD%1pomJI{E8EGdvPF z{z;pL1KSxWY?wZnAEMFG7x&+5y`(t=0%9hfA!N5Ci#ot16Cl~%*aZ^SJxXQPx}N8$ zkv%5RYxy5c{x9ow`3DnK?wr~Q*oANS!P*;$dXqsRmAT)0IZy?ff51$Q6F(#ie>)=-Wc*>n7S*yRelX@QCgML8 z?*tOwv10gZnC+$39-;Fsnu(=dF7MtDqw(0xLMjXDZqS}7=OxH(>ezcA-yy778M2tu z6c(|?Gn^@`O>+LBOMztX9D>$m?dQna={keM5)+ENUL93?s11+8(sZDmg7X72WT%y! zYAbx3r_PM}GNYY~w&NQ59fr_P=H+S|`aGWm1}xg~=qSa2I0z zl)3>-ufT9@00M;K=btY!$;BRLysbDf5js|v*gH|38BEdXV&|s*r6dUiC~>R`HTFHt zADx~>w@3>{5!1XB`kC48=MMVe#-SMsW+@P5g^(qH1oku6bd*rbz5u+`*1<@!&r3N6 zl(ZX@Y?!$zw!&|q3Gnw06Mdh`@#3nl(xdGto2~kHut)|D*<@5R(D2ceL{^{|IKLMY zaZFzeeo{_Cf;rup*0!&JwNB{=ucV}tFEb8|nZX9wVXDwRGV@xEBm&WP#vX<_Y*sU2 zGd3TX^<}e*;?|T5(Ly#`->324cBP^8d!Z=BX)kj$aP^{x+S=a5AD1hhv z=W5|AjGnX$(yN7ZgPtD~7dszY6JX3ws6>{DO0dF(qdIy4WIP0eSt^#OE@!kT4(dB? zBF?ekwq!_(sb3KhK?ep)U%*tSgN{ilJ<0L=7@M8i2zAl_*c<#(j+e&o~I&N!r1gJ;~u{|NK zfGrb6JMr%d3m!gq#+ude#p!Z*Q2g2-kwZIjp?(l1OWw+*nEiHk@k9wGMum+`lEn)e zV>UaAy)6dJF+R?((KxW4oyuKe^t0VLjOB0yN)Yca6F3KnH+gr9)RPTBP!ZDK{D+1` z94Z7u>3YsF@4v8HP)+6FsVrW-O<*))Bt8bo+%4Za19OdlGnlxO5XO|2)nB>7%ugJS z8fuiX6aESc5^fJ*d+IEOU4~lGbu;?C&f@z&E`8NRR8%;iI`J|+`D-)E7 zct)dm7Xi&u2n zdAui}Ln^03uOEB6o8Qxby?JJi$PBx6$!nY*oNsqotbzt-#VL@~Awsx)dIB~3fq!wYqq7u=_ zeFkKH9r@?^^TJkoq;H(+e0LliwjUN5{WDbrfOxF`Jj>CA5mc?XR4v+yAN8tCZdK-t zxgZ7={O@3ugH|j4w9T58YLA?h!7f~Nk0lPx(?_EA`bc9+T{jZxTowGGM{!f*uZt6^ z^c6H_8A>W*cn=9U=Wgl`qpf?xn#ina})R#ZYseMxz_TfK@+d$660C&nw!_Wf5GGc~8V&f?9gRG(2 zhB}NavmYf^)orNsr{|&;aT7V?{s~RIEhy zg!D{t`LIqvE6O?Md%4R@$zTXi%QYhLY3xpTuP5@s353)ql5{ljzU#|l3Zjk_ciZ_@9Z-( zqZPLi*PinE=ado*Q#4tfM!2&f6XD5!Ap^_`mc24R`ZY+Agh2fS$0jJz>#XEr)Xpj0ZD@lQ1v{=dZ^zEU1hU{tT;v zSC$n`X*t?|^e z<{tpC#C+Q;SU&y5kzYrf(Krd{&;n5{uoM!L6T|)SFK9H}VSz@JqnB~K6GfnV*azkp z^n7La+m3#Dyu7fgP`cPh_uw)uQYRqklrzM}06h=7o_c|ycPy=7@9nb?!d_Wy1IGj; zuK4@=m7myAhUm9~VaJ?mE0k#N#QWQefL#-kkW~PK9CM=K@GT;LW%-D68(MS=Pq@ys0MvL-pNtKRPtPW zf7lC9!XwKVq@f*nmR1bu2RVCUKJViz@zGaFI!7`^Pk|@ue?6&=`Qg4FAEVC;=cOpM z!xdL>lCztE+Py-MqYpev_}8pKgH%R1gr*j$SRY8OvxkzHLy9zIAVUEEf{CK^A&w8e zCv?>3TAi=JA7RmfkwB=of5BdiJXtAPY^gsmvcsEde?TF_$E^b>neuO?=aTKbC}k7w zit=z{!vZ;l{4T-w*^k}6wJea8D4`OL31}tn{Glk9sE`fEK8yM)U%ztJ?k=b}29UD+ zBx)Rk`h{%8C2qWo>YH7o_4|0hL&kkhWshzgdY8=k3A%)T8P_c= zGS8WvJ%)gmm6xT_E47hO8}EMMuWv_L7CgV&acTtJJ=zjRVKUtLv5WWgOsMd0Vv0z5 zneH}Tjsn787T>+gel!-=9aGrrBmA+0b)ua5qG<-nv8v9gyb4oU8k^tYrfGm;Y<1;b z$#Y^256DW>+NiEYT>Gqyxm(X)NC}8^RXL zukn~6iKsYsRbnKr z3PsGa@=bfA?;OOf0zsaI;svZxOSn`jnvn29lKk@U$ZSo{#}8e~zG)M3lHaI@AJE#1 zghC?XX%}>n$hb|mU~6H&)9S69ti(6dVck#kRI62>{oC zI~ly;Ce_xAGC2LvUO<)}Z?5ttzniBb*!uDn&Ln17`Nh_>Bf3c1(I5qNgN?j88BBCm zN?z|Sr>Mk!+=BFS{q7QKq5hqG^;_IzAqujT{7f=HhHar~3v3oe>kSl#88IKzX25aS z6tE=QE8|2PhP8$8!7GFql~B-t>ODs^O#J75EcGevpwLxcxON#&5-}K=L3*wX>yUj(D08*>ZQ(GW zOx9)1mAQ_B$H)pDR~ou?6@Si{?;Lq2 zXc_vYQIJHPB2bAWfd)K$(DOrT&8sJ+-bSmasL(a;&$LK9#*+WinrHO#QJO!rIMPL1 zIuEg;mOOgCk;?YJdB^gSPF>PQX9<)PCiGq-mG-LM)zI;o-V=}FX1MR3`HkbULR6L` z-@UZ|)EtD-hW{U-bIadF1`^Vyx(v)Pa90s@+ zujITwpS%0G)vKc;9TW!7kD{+yZm(w~7TQo_ z!kMo+;z_ID5JoMDdhCQ@>SM`}&&U8aM*EANy2hE7hs<5qy6}Z+^6%q@k$%(g^;^oY zcbWM84=)nYxz}G2m~;svwoAGpS^QQ@t2S$cA0ydl@Rc3!nEqGrN&I-<_B5!NK?H99 z^9usnD}m}6-DzZ69ZcfeFb6r=L7bU}Yyhb@-@DzVaCQ_RDk7a5&BicWj#|dXJ3f`x z_)A?ZpDEJ^sIap;;MC%{i7q$+}I+%6kAQ(|nomwdg#_ zi$M9>xY~`#S+p-1+cNMai>6geL34B<0}*uJ_J8}ZQIiK_uVU_q6?vRLQF4{j7}lgEJ~&nQ=Y+TFX~NTC(7x_fiK3k;>dvDd8%;2T8NWx5z4a{sOW=VS z()aq(lzKEfto1|6J5O|KOd(rf6Qc-j-tR3_yy~(PD5QX-MZRWJ(_<8ENNm*@ZSh6h zH<-$CL%h(q=*G>f()Xp%WH4XrNBw zKA@ud!7T>u+@0$A3KT6$Hku#fxw2_&y|T!*NccI^>2DQ%RIhM_)x6y z!Ybi4U2f?vG{wSdL$S0NsnS#vpH#bnrgvcZ{UzC(eR1Y5e7UQ{Kdb z-};Qq`KDN*O(z? zcz8#x%>7y`NLlcY`65KQP}n^ry$7rJvlwbJPVYY=inl$x?QdZ7P1AVXo(s@p?f6$O zBV_QB__v)LxH%(4)zy_E51UO5XrHYeS%N}?-Y@Og13v^ez%A{hD^(J$m=e$J;+rSK zhjr&xMDa`hN3C;5u@I$4RQ&9tVWd@_Ec!9`N>)fR`(tHm#qx@kQEK<2D=*de5TyrN zVs{73&MRgk(Pa!kSb@8ko4{_w2(bI^uL@+lwgv4!y$~d;>9{Iy&LFmLM~?>1B!Hv@ z`U4*is_CK=aiihV=~dVoPty=a{e(J||3?M*DBwbyC6^+I@(=~wnS9MsldrL2d?^9L zTXTt|o0VDM&pZ-wEhc5(lSK?kO(K5XXppe5WOw}R1{h+X68p7$q8_SP1?^3%=A+W0 zj>2QdzG&4G1hy=nvSlk&yt2L@sPH#z%gZ1gu*{y%4f1pG`GVhg`M!}kM8EPv%l;bQ zn2bH-c}gnLJXi;Yj6&-Kvq51*%4`1G+Qb^LS8uWif1#lPtOqBc#l;{F<>QzZ0cUa= zY4i%;-15ydK=(|=H!96R<4JTU+#b+_Bl@69FS06pLzLaZb{)bg7GWM-eQf)9jh5Ry z6&HKB9GjzbN}w^#1r_#{;>&)A4mqbse3fZ?CtqQWa2h07P&aBveq->E+M_!Bu&qFA zvK@2BI=%7K*jlNE)H>yB`%L*AGLX^X-?nRVYvwiUS|XP4H(P1mp-QIisN((~neVTg z=J!d#laU!O`1x6k@#X}yRMD5%Io1?)$;;$rnEa2-%cWomdX>th;JdfGSF!DSK3(pZ zPYEu2iWxW!t=wEXfC?9?kLrD67x3QNz@y-ek+n=UTG7K8@>LxQIKkXx&d!TK|#pYXP3WyUAq};XpFsivNjH4~{ey54KlT`Kn z`_PJV15$Qo9#y@1uygq+^Urei<_N6#&}FDI@5#s8YLf^PPHvrafA!Ew@eC*TtpG^v z50)n=(V_dXH>J)MKgg&pR%XW<9c$tGkRT4QTpZM)7{J8JvG9g7{S0s=( zK&zrj6u8H^^-L9AgJ_bV+cABMfXL(@A$vmEluIBgt!LjA!+Bh=S!a89yD7#`%fC%^ z^Fl^pco_VZ$Ft0*t>Qh_VK$WR5&a7Js!p%?@I1?{2=jE|p5m^yH{2|MRQi=1ArFFj zvdp00lM5#MA_7Tn^!<+p7c-_>{vFGlNe^e4`8wbW`Mr#zF&^2>5NdH~s>`?A@Z%wY zFICNwBs_*7vg0}6iKa_aFZ9Rl-+iR^!^;sX7*}GSkplZ)xDl2c8UH2y$)cM<^Nku;~T}U2L<(OySkF4}ibd%M&)X{bW*;wCv8b>6g$dLbmqX570ysq~maA2#FA((l0 zSsmaEoEqByr{gfcbI0`31=ciw%n46~!J2X9ZO2zH8B{(``O4y?gff&09?8SWiTnj_ z8|XEhaC|cSi!qiAHm|o_)n+R0md(uD#*;7@*!4TD{pYkluyj5f*kz98Lq8qP;q&-EvME>L$T5qGQc0W3!XEO(k1t4&GYXg z(UY5eq+bzuH$`&Ktl|8^3(ZLGJz>7-+z-n6HzWnyw+_X$dQl2X0PFA)#ot%b7q1Qy zbLx!((uhPwF*|E zdw`w0EcGB8=o%-QOa|Ri=`{uA5(S~#cqmxI6Ys4(Q}Zvdt|qyG8L}gm-xQ{$6fQ|S zBNPcmYoW`U!9#l7bt%*@lWJ?czfJkgE{t!%(VeKu$rd@i5QW*kspJ|70f21Lmx{^K z9@))iQ>R;>RwW412G_DAx=K`3w`UQ{5RXbgV=CV%%|1;tkob!F%W7U~Z?C4K{4Bwn zbV3Rj_b%fS-VZz`Xfsn;@b5x)U8qV*_S@>3ps!)e!|*%-us5Fb|HHe3Y8*PAFo*t3 z5_~@;v>iIZFB)DPfrXCis4plt?uzm|^9y91{}HZR2AJ}YC@df-sXlNrbpUy(EspLzPRg2jNl*7xWnl-wskXnot4;I`gSjYe?6;0tS zjk7tD8hD~QPYfewH;Wz3H9}kKa3$K0$juxCTT+LqGsn}^=`ep zn-vYZN0^`LQ9tm1b8OHZmy_PkLGyNMRXH1YZB!l?`?jC<*z%L@&6V5Vg9ZLiPHTkA zgo?U$fKMD}66I{_xvXXzl38f=14Js6Ey4T|o>whLnfQHPN4 zvL^g;oM>eU^b8FF%-u{oOCqp_;v76S$gbHCNw&eRtTKw7&r8>4G;MaYMV$;O z^7d4L;4A10-*n|O7PyhPxxJ+HdA?P8Bk`eb08f)bslZY- z+4?mF17cxGSV6IUSK%vv5x$l()ltDR!|W-aRm`YHqSWYDaY8VD|4BJW5!1hRB*9%9 zesx8VDq4;BMsAiN@XlwFFY;KHrpOf(L1|@8hOo$Dy_8cb5OB6gyIyQv-z%DU&zu{v z_ViqccI(l&ZbJ_fGm8(ALt_n?0>1hVqy5}NUu1A!;uzl0Go;!Z6u+<0P6%&zBuvKL zrQFtF8HHq>1Zx5%CghoB{(J&fn7Rbw_*dZLU$gxbwvUN&=^eC6LvFEtlJionW@9ll z5eKv9l9dcbEAQDS!A4%_#6hyj5mQUb=>|2kU(k!>ELn&KzPoeR{ zM8xw=b8P*=LxF{?LDcFuQ1@ltZkc}_f4V!u47wJ5bhgBZDukvuxru^Q0gAOF6Cx+~ zbHW`&4FD-QCaJG%R@u*YK2+Wc|8Wpr5?P!hhp{(WAc$*d3N~T7Zdb(`v z@+I)Q3nKwnZ zT~a2g&pe+I+)&t`0JeO0R(e3uUUFmv9hWirEI&d&7^GExTu`U*~D<%kj$BxM<48VAD-{0s^(W{ zGxinB&}uRgQRziu7`9BHsGgL<*-acMH#Ow*#qTVBgf&;)jcvNarjgtwfI%6VE(roF zNp0ENk_V*1X2YYzr@Cs*aJj@H_$l`NEYn+dUujmtech9PhCL8e3XIR{w&WWcpxbH| z>V~u9gncxY>w*OpIIZcOcTM8`;qpHkONo55=jrhHur8#iFt8SR`TO=IalJ?kfMV%a z`W&Szzz1WACmemd>s=tF$2wuH5xcfa&PMCuD=xgY&%=(W`InrmLYI3-XHz_lr0a$L~xnR$P^V&1g~CDXS|lg0UT zX3Np1IjU(f4-#-vLKks~9!Q6e)>ra;zei88tQ0t4X(*j&AMfiF;tmT6Syow&e{Ja= zgvFid=9PxRsl4Au@=?fdkp2zBqR6G6@_&@TI&2(EuN$2}f!9x1;8_sDv)3lPaN_S4 zqh<6y&c7FHc#r_CYNL=pi;Y$zFwqZrmbcJ3?p2pWoQ-AWq;M1X3y75M5<5o*g|Fb8~4C~3cNc+g+O9l;eaX8}*C)!pKfq=0 z9?E*G0o?kwv3P-vvJ|FE)t%>|09mik_)C_ATcgft{cyb?vi#$WC@#m_1YfinK4&a} z??+QC+|K-7G3U@Ufk8SrJde0r71(W|1Lsm*s2i>zNyBH-t#^%bvgMM*D9Pj)8}%s} z6qUV4dz?k8A2GMLZ?w$mHrZH^oOGDKPQzpmxLq#?J~5UVZQIuqgX%b)aq1Hj~Nrn|RYiXUIak z$uSH-O62M9JPHut2xK`CIrg^NPIp3+lpDK8E#o5jJfKt71X8c zMt(KMYP`!(mN~u|DdyFHA?^_H;%;U-(tjq!;t&NAC5+5Mw{3c&ygo``zEq(n5`(I+S;i1Hv#WR^c+=wr6CdppMJf|Ah1K3& z+v|c#mZ%+bF27Sgr9m$Z-GQAd!zzhTo+`M4k(poBPFvf63 za^w%cJf>BKCY*9c7kgvBVZC^E@_#d>4`2Ww#Qj$WHdI}Da5k8!>N8z!%ui&R3LNi* zuOUTRZvXb)ClQ0_Nwr_UcL^nLdGr|spN0v63Xg%+AN&sB|KgRwFFt~+UTUAZ9I^Wd zL(bbT6~e?M@Y7+v>-}G$&m7FeISQ3WK!$$2h5YA=F)M)43aRf?cj9k#i5@YFm#qD~ zQ@`E{>&QQVs|ApH`Kk@CNj!jB>N$s3=0eR1i+eGS@hbkny^QS*==Q+}1MS|B8_N}c zV?HmopNPEUdAOX6r4MP1vb$IW@QUm|f~(SJybBmXT@&bFFTUV3%dff!ZCgJk`cHTE zj4uttI}IM>nXr>dGYDn-jXadimiJ}X05AXMNGCKfIY*TH)OU{*QaRv3%jJeuI1nUx zac|aiT}bIv`VA3z23dsC9VL6cbXjT%%0Lm7-?fL<&~JP+7@4FEKHxL9jrQ+IO_}~8 z2wb40`$&iaa{EZ*9Z@I*Dx_mRNYMhC>a zbox3Xz?P1jvefpP$eAaewCdIu3wUq;Z-Kpa#CYMAl5X&{?|Oh&_b~a9Bt-uf7sQgdC59DOedsBY5AXyzqp`mU%0^C>kTaqT1C%$4rp|S`JV}9BWl}6_s0JM5q#T2 zuu9e9pVKGIG?@PXq&xkic#EpbwzKSP8-J zsbOo3$drkrbni3VoCAF(I-q{kKY@QoXfH?hw5!a*`^t#&YKif>Jp(46UZ|QH!#gF5$cF)~>6P__4$Wp2j2^|A z_b(dKctYu?_;-q=I7i#Cima@S$;yfdpfAn?=MVPo*oz1$5aUh=QOhyM^YPOxRV-)F z|A`auO-wL|4J%PVtbD&Y+;aVxSTXFA$af7*f%yYvw)j(UBE}z9saP>7dUBax(zxvT zMFL*Q>#SryIH%IppU;*~@Mo*n_d$IXv(zKTQagTJLb==i7DA7YLJjEg)+ZOg+>oe! zvD@+ybclXm(z;~i%ru-YMD3OJ0Njd7b4$_phle<8j~X@?ut9?S)@b1OJi!_)NWdw=4GbJ2GB5LdZf?nv20wEfWC z)^^028$`c8l}%wl?E`LRNlu8ylIAWLnZWjkg(ue41n4N4Wu;JqhSYM0jTT;?XX}KB z7psjQmvY1t+%>lwS`+m}#9NQHodygE&?RCJfBS*x!Xg-F%-?eb8xYQNs%i0uG@*f)i!8$DrcQgCD+*M~?D4LSQmXZ0rh(s^sj z5rFs^VP3?}Z&W6izRIrzIBraA{U247h(~62d!2s>RFHOOru8cahIs6|#pc_CH(wmX zysjmjA5=7?q$04KH&%`Rib=F{9*X@_*I1qM3Oc0k z`<2{ha?ld~RFY6}RIeE~@0WY6EozjOx1R*XJ$k{LHfN(txZMGSpn7~R99VO}oCs3R zPo})c*$%RHkrng$L*P;a514BDn#f(g3pohPdmbz8w+OtBy!MGh%E?y4eSw27erK5??DH%@f6sw z(C&nEZGTl6hwVNnUm@C^CoqKc*~Cc}R=?i>Sn=vy7F#7ykwhc0yCkH!RPHI|7c zj$uc3$pFt1mC)I!f@n=~(7)HFC*{Vy7-hu_D(^!|uNtbI&y0H@Mg6@GlQ;6;yn)YC zAXDrhQ=(=LI6xS<;Lq;H#uYpX^7$k1Yg&2}rISgn{DgkwuByRdfBj!SrQRV7G>&Rh zv<#0!=zW(oZ=W^O3%P8iC^s`>vhyyCa%!4f=21!+)1(`=?h)`h-`@QxRMgv&fGVkl zEVHfaQWHG zf8iGH&{QS|8DQZHQ|fBFq2d0qyz!>4=**eW_aA#x=0w{2j4w6;yVg%@g%ZqugyZsQx)i@VwENqg5B1m1tBxgLM- zl%zDydn0=B#S(~fvGBi2uEhkk4ggE|5y66oKqkyT+4aBSxePjGHhOc2`yziZ_ zY^bh?&XoAF=-$(Q^8pSbLIS)XazM#zKVVDksedy3#0KxUNQSbnh8L8Fza8=C3t`P- zQrri~^Ua)FQ^yT+^$3GzAAllHA7%+T|2Oj!bx_}Vx!YiL5sT3J_hp)cinhw~KV+wX zuy8O7Wf^VFvYk49jc>w&^^gv$-V#{gfCm9O(DMrl?9odh(jLG||8K6@eeIKg&b+@2 zMCXeJsDRqI?GHHjGe-b5wTq-1i&|m$tL)0ImI@x@NdPJJT9{{YpUzzUmLwUYVab5B zp|%Re6ozq)PGFOq8j9%S-nfn&A0&Fh<$%pzi=(eMxnE19uA;vOM>;f#rax^K`w~EE zqw%iTMQ$~P1^5^d>NkByX)qgU zsr>3zMn;dG#%yo=Y)fqflpjKimnS%1iey~E*ZGu^)f%>hNpsijXfqS}^zbER%iG7R z7n!PJTr@e#llNCl-jioNYZ!ui3>}zE5?<+gBx_ofM4(Xj0ugaj=w{N}j)j%$`jJn| ztedGWIDN0o^BW>QU}Ggfs9%e-#QE!pz?$_j-=_ei4Km~^L&qwj(x??ej=posa zcl-8y&8vKE6;C-*au*?!e_)@w268VhUwGgcZuN5Vm8(xSS`Z;q-TOze!T4;a!N1A{ zRay2|!iRtAcJ%V%6ZA>6Fh8dBAS(TDZ2NWkBtoQOW$MSZUkYp18D^7>FV;Bm!Rq+- z)I;~V_l#6cu>|lUV;3IsZk4Q4^-mU@2Scc2$Y8bdkb-pIN}j5zb6iunIy zpP=zy?8NOTosbCZx;oK`(;Z0+7W)DO*D7Q}gqcx8eGb7}@Q)*sS7A`V4s59Oee=f8 zE{5Uhk`HtwA` ze2a%;8%FQEv>~yX_=U_04fX!%iEGDb~JFSs|f$^-f1E4I5D+H*(K*X#slBX2){R_Zj zArpSMV+V!FmMx^{ZViGn5U|s92*P2q<&hw;&)jIfdg}SBX5!$V(FG_cN6!_iST_yA z^X!l7-)U)-#;N!f%M~SBTvjnI$qVUC^LPQ?T61kD#IQQgv zVufZOp4#OR=uXt4S_6*R!rlB+BJ!40C>b5+OYEB^hE=lbSXM>9uM zez59Z(}E_4B%ljl@k~M|vwl?ds~U!4Kc%R5^Oi)`)t^h#Q4I~FSUE3({-YASB2O8X z(b(nKjzpX;8`y|%m)cpeNw<4BzrbQ{*dHMKs04S;#E?Y>DS;@GF!vV=GL-A*vn90+ zc}UE@EHS_qz{7K}60~BF(eDMhrph7;=t%#g1oW5jJT@c+BUMHLSjgue8-(5^5H)qk&ah!Bz#?;OsDZWV!LhK! zv-SF@)g$EB&#P;ScT2~)}eqeS{@oudsrw?~SSHy~?fh485hW=nYEod$(e z+)yM_S4n?wPL9yKGe3A6P*0;pnu%y8THJz|ZZ-qKCpe`;dL`FCklvg{h;1>46+Gs% z8(4gRF%TOdqFZd;+>F#&360nIa*Mo@*MRM3IZn?AGD%G*Scs9c;G<0o17NL&cHMdW zzXIxAWH3G-5@xu{`Yir86#x`ob9}WfH`+Pm@8ZGBf}7`Q)yK5+K|jH_-mY`G{XJly2cv z)&DH9T&z`J#WQ-lFr~A+2_gL>sr=D3=Se#ribMNUAJqThhaxjN~*8NhB z!OZ6YSJkYEYDC$-6I$(8*VKQ-d6jxaGIT4LkK7L5R8kJOdzMM=)kxt+tnP|4G9|dCJqv-ZGi+P-Yb)ZcH~Ys-k&A15GDV^AmoP-g(98W;NW!I z#Zk0!g_&Isw70Uvbz4?a0vNM#p+J=3i)_Yzu4p!aUYM^tr72@h&(p{GgL|%!_}6() zSi^cBPvH>1viWkWoDpqO*|Lb?wz5qDfGT}^X&4!X80ruanLX$po2E(kb8GpLxTgXU zQyb#Fx|!W;VV)C0g{U*-12areBlZ6jPEDhAd;PjSBoLiZt%l%A zwo1l(gZf9EQcLuJpaKY1GDR%!IT>Nu+@;1SnzBRrI2l8Tfc+T%ie&04*bdY454)@w z!C67~;7Iacz9}1__-H+RXKlim)XX4W@ zA4OBKt~5qjhr~e#2O|&;E$D5BAhI+S?IxAA1)>icmj*X4SH_P{)t@6HkXkY^d@|4E zy-a<^d}Ur*p0Kavk8nP7|H4(=C3w_tZsgw#4qkaYIOx&61eRkF4fY&-&GlN*8XfHh z?amrc6RT~6v!d=}K=(V|Llu*#{0mAVB?U$;Bwn8Izm%N`m>rbz)oUDI0o}(uxZa~8sBveDX;3u{ZG<;9a$&x{Ab(i!N{t42C4&>2 z`U;7JA_q~+ED*-*zpXGJMQv}p2yncOGvHRWl{5n0}yiOxAh89LAqPt(_PuEkF zbDz5IM~V7scDZXKRIo_*T^-nm7rRLZEEQs6MnN@X)-qD2(_aHf-Ch-#T>CyFbo&-j zN(@*pjLpmJLtxLxb2%*{Ot(tg{BIJ4c^_~cE^izBR70u%@G1jyenHyjFkHs0(xqc2 zPdVI+`B9<=OH5#afGMuB9X*cfdKK5wvVlOjrQx_munuZGv%r6;y#2){;5w2%%GonL}3|f zn)vmd=f^E?DurZR6cOoa^JX{uB*nf~VS0-UM1bnRs|Ev^nFTu7<|xJMcIgB}F{$ho z^=8%Q+88^p@nx#c^`AVUpaD09JJ&nPp9pY=UTQSbC!*v(IX&e@Wooo( zvp@Oalpq0K8Zeo%S~|Xp{-Q2Wx5lMYZrn8Y7tAM7B9q1pJJa|N5ji!GR>~(K);spd zj5QUNzEv$v$o$PrMIUmP3YwzGc5F4iG|YlW1^$-q{=uYSt>&n|>I|Y5l9n0fz?B9i zmUWWNMXh2@2F@7RegQz6Le5mM*6?X(91XPHi33jsmc=xRRdW52hk?YZe~D9}!>)<; zZa8ad*aS{rOJ|~t`8F8iz~(2c4t&!j=E zR9gV{v#&EEX<$+&OgIE&3bGXWjV1fn)+Y_Hq!j%yAM}8A0CRA?f3H)U#KNZHw@r7iA&M`6RB2~?GdcGJC^aUJ%3Rz%)!?5EZTGqX~~x#rj_BK1B_h*es(a(cdUA zcz=AP3R92BA?K@uuqUp^qGa+89@}H@h>qprJ(F-jkv)iS-aD3|z69PEcus=uV8yiHHU^_VQzy}wh<7#ny=5tMMEehfmI6eg{iCwXv#EgT=-VeTc(mu*f)$c zyA)x!aXBw!E}eGd4aoqiNjIGv$PCXz$|HAIWa5#UikIU@4fq8DHTUBKGKE0xb`$&I z{XJ#}0541exwi28pzcrlJ&5pH`|pgAmOT!Y4gR&;1u3^XG&M6X6l*xz3NhP^IMb4I zo~qlxL4#zH2TtnqTV$<23Q6;wExWOkK`HM;CiY&(Z*|Q`PP4YS@t+gJD!+?G=^$-y zGTBWy50$guV_I(bx}dqmCtyKI4!NJ8<@{>0X`2!`__I+^Jm6LA=cgG3vu9#|yN}UW z1bZFkZ>gAT-b$^ewfH@>_d#X&n;$c}s`Kp27MGZ}+UZ_BS4(2q@Es)8m+xgpW9Vy3AxYS${5;S@N^+Os%b=9VNmr>0g~S4Z{< zFSsy3MFQX2`5WUlU#*_Cex5Fh+=LFS;(aSSSQkjBAdTJmyRYo=$Vl=|f#bdQq;xKE z{N1kQIDc~?&MKZOF-#x{16u z!(vDsqTJ78vv1z+^NQ2(_MQc@loo;##0q~7IUZLk&)Aux z0tXi+FH@gmc)qh8V?Iy#2M?}X&P6a?3YfVo3B$0uNN zTB8hBZYdT}P(8lFD*aHbnN&n2RI;>H*1HyU?c+?T7aa~IA;O89IgtPo<^@MNGz+hF z^1y(;^g1P=t~rL4lKL~L4k;E-s{ot_-NyO-#OgzF{j;*$M%f}3%|Kn@Jk3|Z8v{z) zYPeE9(V$34gVfYYb^dn|F?>BBvzNP;<---l?6cj=R`P+eIxbx@h;Ap-P*_H}w%Jvf ziFF8v_~6wx|G-|#vi4*+uNX}(DJBNBV_qToaP-3ghL-ay{=s3(D)pG>)j39I!dzv+ zkUl-e3COpvYo7M|b&qCFvx3ieKwQyE`QGYO)YT>xCub+Yrh)zcrQ0u_@xY>EuKGRI zDn&oycfeT^VE&RU;zB;-qi#NUyi)K-w?B^IR;E=LqgU2stgtrS7;aHAEXU(OduBB_ zA#fE>r-H#2jSn+8l^ZHYproOYH<*%6D(U3}2jVh~y7!=p%502vcZ!ehqut z@SiBBEE1}6vDHR41`?JS#M6gelw%LT?TPxg0)jqL8iEY=TBXQAMw2BETiRw)raW*= z4ouKP%z=xS9x*G(jX5oP z0BCYw6vcBPVOYoWbnw|#xGJ1^dZ$ReG6f*@G|(4Dl?;#Y?6if8{=sHaCd};!{M|B& zShwIz_occRqS_fTuD$i8+8@XXlbkTeO4xj^O)eIOe@qI+RK2#$|A<2dP!KEA+*L;! zWm16h*a@M@3VlMPmkR}q9MC{en^ zRu^IFf1&uR+Tx*si}&s0NvB+Hj zVI$)<+bfT?YON8lg4;L44`g?R{*uEU?8TO!Bbf zH}`R;7of<_?bWB->$2jcTI?-hFC~nmzQ=KkTOTQxpvCG}Z; z(oJ-rR5j9X&l)|JWpn&pQCtFjTVXOlC$_<4m|@)#(tSSBoAQxQCx+Pwcr?$=PVAy& zrv0wC$pB`XBtr93Kep9qOPlV9w!-`up4UO42zKB~cH#=^@@ zX9o|dhRXrNda!Pzw~YK!$tTr(r&4*O-t*dUZw*h+(lvHC8$+G%=XNN>Z3Ta8d|*=Q zx>Tk9W0#O8+UGJ)W5LV@f)}sa!fq`wN+@$4+8v&A{>5eSP-~WNVi5wT=w59OOLXa9 z>JZU@@f?3yCul9%8uAUxp_{0Wa`SU(0jII%o4ot$GvkIV)ag4Sgljx;*3wBkZotZUBYKg3}|s zSCT>v`H0zj@^?+%M5|3G2RANj!#3?pWb?@_r+hI4MTM1E77?(IjnW}CVw{XxeEnKT z+`78@Q~Kv|I$N`^^DSh7j|mU)H(;@~sXczXl)fb^Vh%KsXUSrk$%emJqCz1$1a+b1 z24wG{wS4XgflBKg7TR!y&JZjWN!u_h__&;_$ji{!Y2??AD$GlrBlDrM;C0AZ3<0 zird3GwkCN(-^Af}@QJ0ZNJgdiZe$y|f)rq{`?#@Qn1 zxz^$6bTjlFfC`@gq!_H6yz0wz9!CzRk=3vKeBrBkaWthdhB0s&;>sh>5+QRZI~^CD zD)eZ#B>A#)lh+^Th?MX}Ckcy*f1e1wZ>b+th)-SaiO(Vi)BErRNiPIN*=lDFUHE6I zORYRR`@}rvDdc2;+b$8-g2vM{sWqM7yZ6-jr6%!6;lQ1JbyXPv-ojzgKi~$`cf-!H zj$G0X?x}EkoD=1ZjkDiVP296|Pw6yd3BrtMdP0>@35g>b{2!Gjw;?Ac%B>(p^$YNq4t2NJ@8iDUF0Q zNQ2TH(jeU((!2wR&(BZ)_wzZ|VOaNGYwf*i(|O5uXf|ARl6i8cWbvfCsBdtZ*RKM@k_6 z!bn1im}fPOOK=&FC|m!SgW(1}b`=G9IKxPV40CosTfC+3DkM@j+h?AG3SC_tYI=hj z6>J;Mn+v{-=KpG2e>}siPJ~VCD@=+8WYGyJ%u{*W8qTZer$@523Iw$9dk z%)7YB+q^8}{Q;Ro!*5m?yBu3EF3QA}A{GZ;DSGvO0LLb!MZcCg&HdDISas(XRk}RG zgRg=W6`hjgkAL|CeA_l8IP`&pWFye3NsK@8W>R0M{yj3wxPfTKn=k#bt`Og{R%2}L z%>tk5O+@156 z@%k99w_y!Cli}7U&jLPQVZQfX-oF3Ty;&j>9E$u!He#P#t%!F+kZOG;E1M$fq2&lrDp>jOZ-C`+-k>AGO(EV&qLo12?SLw} zv{Q~75RW18@cdp5)iA>p0Mnb5S>hj|tZ|OQsOOw__k(vHQ*mdBEfnY!suWdUy0Fs5 z1@YgTkW0Yx9#@C89prAxexC;y(NI>tFD?!~w`svmg~!c>UObS053L-O7_iz2P)Lh5 z|FeAkkqaQNUUua;a8j#AThMII;%`F9y);zNN^Dwz<7@)EG2Ux5Ze6DIB2>%J4+zm7 zyUfN;84F9ad9XR{cjS5l4_h>Vkb|!>`FZ$T9O)lNix?vbltMYhvm>U@nm)e>R~Xbn z1OZj4cRs%pEWJz33;41s$is6IW~_C!XM^P=@qR$b?kzj`3Nl^$Fe!5QW=C}T#h2)I z-sEx{3C`K^$5#`U+dl=SZvR?2y`w%z^@GYjVam=*WG|we(oEI_)Y_0ymhx0-I6`yq z)?6lh+FH$&zlhR(_uTTMphHI%2}>C{f=2Oj^=fki-TOxiZ^=j>`g&kh;V0kq82>)Q zSPnltI$-r>HX^wHdGP#?AWXfWrNG&76^X&e4g0x@zCF$su1hLpixy)Oo?**crHGW_Rov7*&v%0;&!Gq6wExd;m zKaUP!m;K2s zvvOb;9t7k}pGBex=nnxLe9PY+mH2$w=hNY)IUJ6t1!ujVcOTunU*9jnCYs4+;%U|l zVhcm>vXgzXS}t9-aasVbOu`qFAC&IbcQ0Ca5g#mHuj&gp=)v`AnV+%5@7^{;UqgEU z{Trqkckb8Y{kOiy%LLGb9w<6B;5RK_*ZcP{as>7;Cud~X`{dz{Kn&e~3!v?N`Vcs{ zU%xeW*?}lRa0>N3oD*4NO%rn_@kxP2hO{yF8gp+6%vmun1-6h$u1&zx|&hi9+ifJvDG4@e^m-h#QaR*bH5M}6(f%rkEnKror z*QW{iQ+AaY&>rt;Tfx@~@Fq`tH>0WwhV41TK#94qFZHijnzluP$|E+Iel{p|EexOTFsKLZukB!_%3JY(xODlHSTbGoU=!QBQ z=0GyP^*&rD%zs-5T!GYv1OYS`>I@9i9eEUa`YEu*21y75-Pa^+Vd}ObLVeUko5}B2 zHbua#OF9c@38tjKPf>G4xb$gM6#V{aXB}Uw$}8jFX7~L)e}0o6>_F&Ob{CB4P7#w5 zId_v@ZWcIZyOj$l``wynuQ9;M+Lx_w9k6vQXn<4n1F|w`QKI@8wMikr_BETvwKvwP zA|OG)&}dETGmnz7uqx5qt3@1*uU{@vDcq6rdK}?dTHUoCYVxZ@P@`VtPsqCkDK2rF z!BBqdwFG7vwcZ3}EWfk&gzmX7NBHxbn#pSw(wgN{n-W!yt-r2US^iw0wO$Ol2|>#f zsCiR(1iq+(zl=F+ju%sk27(5Yeoq#wtT)S}ME4oeuQh#Z*Xt~>oU9Uyt2Uzy)Qp6_ zs^f{u4=d(jEaU?)*zPu!ofYhs+3w{8gfM&PgMIMR;;)jv(df=K9fxd)gp(6&Gd2vth;SFlsc>}uP_%D|SMR{6i{(^n>?cfOi@Iw;)@r|ilmV9@Do|3EsBo2Kq z>E0d&wYL9!JtT^a`*3WNiB>uP7xJY&A)ORno zX1-1Sczz}bBT)Oj`m*XMtW$;T=V~q-^}=ef(@XOD7sS)XzB_8&yoFm{F z`f%$(P83>>9#{rHgx~x=kQ5kw9T;96BPX5B;24zws|ML}4PhvlMl-Ai)=bxuDL>s(83<#_tGI-N?=UY`>2U^{ zkhyMMVID$R_x9I6;ex9o=4GcCycy)dh8wY6IUgck)X(Uj_hqJf5s; z*Y2Io%Sht#n~6k+p)?4g7n=k)0SVnU53&ba-$}D8aTd0*Z~c@>y<U;I5n z?b@yy>OXhJ^FJ1zRTX^O=t8X;LLk?EV6*T1NjYeU8bBs*GA-Bf;uAOfAx@>}PKGZ8 z`_AII)3gS>k3v*E)3=UC2g}3Z{pu8Q>vt_8vv~MVTXHfuM*QL5?y3B+-Cw-(t-z(e z)DcMTXhE$IgCWVDtUXlfR%xAnSx~}w{$uIac}pxG9vp1>Vtl#*5zY_p%$*d%!_00m z_guv1URV0rwy!j(7pn+CfTm-U!O#~m0}b9jhhIY!tgV1qFXXr}N8|5WQ3CZS2tWW> zqZ+^>YjZR&6Fn3@F?Nj&^Ggx!_(_-wW{`3h6;u<|u3E*r^U2$rmA2)DBOk0idaqOop&!rQ$ zgG>bhnTGOlm%@ehzC(}AFh-)j-M4k%?r(&DEt*py9+CBI_8%scwsq$PxAI3i{+$Bo zv#;xlDQ(_i535P!lEL&29Gtg5F~PypXz?36chfhJ4C65#mfxC_60Q)ifkXlD;|dJ= z$2>4eR-(S&B;9XAyoto2yeD-CzR}>3L{Im``?RM(2Y644Naj-TgEPbf>G z)KRH`^@uoW8+ogpTj8@_J^29&SrDM4FW4bdIQ3ndCd$~FEhbEj-+0CBAP1MmCHImB z0qr*sP|{j-;|3WW&O%g;o<~o&I4&a6U&pBjbwJ};n>2MT^*>O0%OSQiY-m+^$lM`xp+Tr?40q9w@s9XIsXnPNhg!hue_1L0fKPr2G$$iTf~avXe+x+@-_vY9QzGXciqEzzdG-(7E>@bvxXxi^`MZ zvn3BTW5BxDrQ>E~c*-kXA+A%KFC7BblJRa>aQw>$byY#b&%Z@IFp-Kj0>NDhdBJMdZS-{r zAePRFG4i7sB;V}GN(s7pHGu%AQx$=VNzyThX;LZf+_81oO4h)NoLDz;rXn(yzEtBsR^ zh;hVO&*X^4l<3==j&%7Rf^7H3i|>Qddn@#hbo?)<-G_Yoaz3PSU7H{H4vcb&HjkU# znm#Cs{><7F6JlfS(#ap@!2^rW(nGD+66q&u4+Dh$V$>C(9Pw7ZCVTPc6!PYrm1q9kN6R`hDLL=x!pA2 zt5z&FwSE+yUuZys|H^?-RACsOQFK9+j8Q}NZcbN-FO|h`X46I7hMqnvCh4DS7mY{sD@-& zrKpe{3}n_NW9aFG&qE&qoA*rQu^86KJ*g!Ul9u?0zP}c(2QVLIn7NKe180|QJSZP8 zac=T|EEfkGFENzl4>*qdJ7W3+%{XOs&s2`z^8~a=%{(zfS~dN4EfA*f_u*EQE$KP{ zXjEPF#6)?=1PPkEx?q)RfRd@JwRzwxErot)7@vhrcL_g+3b=XHxih;6z_pPjKtSj3 zxwWcfm6?_4uz_#Z6f&703=tyr$OK_s?5^7c=&Cke@1$G4nx%}IK;Fkxub4 z_yi#153!jP|8<7Xmg_Q-Jc*i-&h}v#t0gof-EeZ32`e=9o(Vv35YX&nUBoycUx%<} zZuA*mlf@QpB;_03SVsiw6^3PG;X54UDc;3}>%W@hTa z2DhGY>gfXK`G|1N8O(*S?tpVlsQl$Z zwP;|rmUfE?slCFXV_BGo+KY#uHyAewg9Cm0ffgKzQlg>X(#v8lwMdby>=vP1ym6jXH zDEMVHLmIDJUG z0h%2iiiPf-JixK*#|Pdu5qD(>$0?7gYrMim#Q>VQ$IGw5&!fw4B{wOq4}^dj3A$+=@d(>=TP|m0ZruX6?Q^|)Cwhl#VGVV~ zl1 zK;6CwAajQd^;uflQWmK175xySge;zs6<0mOx$^Eq6GoohXzYXSvKpop)tf;LT>D+n z5$e_PB`;WHCjm$nE|7;x65L~f1OnDpN_Zl19Vuy?sc!DX_rjeTUdg_>V|l$(%|a(H z6=?wi#*~QJM;i2zSZa#KwJb{tzqQ{POQEiJ7m>__lI_?F`iBY46@crtMF$+`Dq2N~ z0rU$XFA^}j7dl0f6qUy9dza+>KI&dij6r&M-_TE#tz-7BJEL|{5aVKlOiK%Fp6gPi zKoHMAo=`#+%J1L5XF_j-BJ}3hro92(N_71T1;@b|z)FC`?PDVg`1#kl7b|=^B}49pzH2+yJf-8+hA2ivat0`+k@ zG&?+-{)EKFo~XPy7%uq42#BkFwgv_PpmKmlUu9Q9-8 z4EuJ@84W8D5^G5YdE&*?cg^$M#_VJ(%YlHNc^SvhE4rmi^86DgqPa)w*zeEeO0S?AT97>Yg^6dIF6 zDMuTL%jdSkm>^c!b(P9N^mA&Wjn# z?RIwJLg63@EYd`iU9>J|U+ZHJ{miD-hVrOCP!iQUsapiT@TW<1EhtKz(P1wMU1_mU zHl@))@-aXzOn^fuF{p-DXML0!A9C-kDxwkIu}2@v7rlR$Z{I4rC6w_v6l%8Iwojx@Mo)HQ zy`fk3BuLy71QaQCj;HP>9Fuf_)K zjm}1m*Npp)RMSRA3=Jt*h<|Tri%SA=+%NolP5CaMpKLo>qe!Cvc_@NewuXHERKWEZ zrEvMizCR=gE}^h-_>2xKt#9rKkTok=>|ciV~f?yS4lW%6TkL(LnDhM;pS6#h=Auad)c% zADKhh!%>q@L_D2yz}p2XtM1b;UL%LGFBdTjp;O9qOioE}!>RgfIY-oGTyY6ybTaw%Q{JAp(bHSs))fYZ8EwTZVqZe zq&;&&@Oj&~nT9raV$79VW&>W!1fIpGMM{Low}}lYiFXtXrj;M*@O8a~vA_HS#c~jX zltU5!C1}W@A9S6u1){(*)#=t0D!a4?%Bjgcw0_=03FDF~%F&ssu;3r+X+H-lPy3c# zpu@pn^VsYO7Ij#|K0tv$c)Z;KEOa51$=5>*SB|6XH(po1vKpXUqfY_6YgP~T3;cWp zE_(2r;P9t+nEPnJd2D5S)a8LED9rB?+U;KFLnm+M2)==8r4g@3ssA0;_W5FLHCx6z z5uCu#(K&{^TyLG)8RTeJ=6_!H=5(TbZ+Krz2!=d`UcD6Q50ne9L2Sy*DeQRmT;Iau zxmz4B>ax|QBj%+>df;++!Bf6|da=yT3v<(6!=1TE&MoD;4my!jAR}uD`Nu`6 z2S4BIJgGu7$3R>xnt71M^d)v(4aY&l$v_y0{^k#rjxX5m&q6Q1k1VRz zSlMr|vZGk++Q097uBjFuSW3`^1@7^u3}8+F)qTz^JTswfKGEj&f&hBDQi?UGZmIZp+&^FaKw!9?hF8<^JD%ps>F8H|kH`DcB3u7Xj2Rkf_o}|UC8=vV2uq~T8aoRovkuTyH+ph9 zCiKAVsMvsyqckxR_R$QsjyfWMCskpOANTYNM9QpsEz_v0|0VMLx6-&M5yNRd3N1!< zo<4Zj#IHM$m7`!+E+ewfnJ4dVcGCEQ*&^eu;s?l`@xV2B*2mqKvXC$~$IHvpu9Kdt z&Y7dxU$m$O8Mjxz)I?8DJ}3sOfotB*=3?8LpW`%^^TXI@cde$QmzaC- zAxJ+kiThGGr`PduTy-`JIR63d`od#dw!OewE-mBJxDhkmEcpHqCK+Vs_6_7On3oBg z!<7AXPUg+C(fd?zh48+D1Q1T(T;I~vX%XsN>5AigcJdKprbcb(72Vtkg>iVth4*!_ z!$0P0$xVhtO9)zPCU~I_g+eEnR*cUN+vyGdsthi#AX8WS)Oy-vv2kPgNn}Gib zRYrM!$ljTiX|%hlP5&`b1aY`SH1td4$`dpUUx5PFM90(}wR=WkDTbD2SRbKbIgt znb~*M=umnk|5>d6%E2m56+uxj<^vRSoWDYMJ&wElD*P77+sA%JjMz5y2s#-%K(`;| z3EBo4nh}fhShqk%J?vd#nblP^BI;jN2^kwW^l{)3B8)(DA@r0QIGAFa`2e@#^~I)q z|3haEGPsgT_aemFmC@dgF1$20@g!GnDddGIal!fYH!rK&#{)Wk&6 zt#dyf>7V=ged$0wR=}&H&@IvDSZIB75pkEu5wgMuXHo(y0M1jxL$17X#XK>P!yCqa zw#3A;=ah?Mvug(LO)L!oaY1ze0=`t4It#7DG{IBX%27jH0lV32>GX2~0T3U~51*17&mCC9|`ww+Y^kBzsgc4*Vd^ zjV9=OT>(zq%=?+IwDk~g(|_^(+!bCcVNul@d5M^+c=bCl8Vg(?;x#?Ng*F~(8*+0? z^c~@OkkQPupSvDqN#Be&_2S!|eWNriro+9RgGym!%JcxFE^ zCS3}?z399R?$0zENEcRUV{61Fs<18U;^5QTtZtadi`JPr(b6s)VSDDDswV?B<`(yD z#9#%*mXb)_N-u|b=4jm$X<1^pum;od4k77b&Ih2n3GhUP*Wr~)!Ju!1#UhXtO|A78 zZnUBQ{|4^07%EM7lR^(fD}mw4c?UsS=hTr;2Fw)2Q|=3v8^^~H%lh#NoS{f2jCWBk zN6S*59A-(;%|gJkMBn+aki0C(`k4y?7|9~#>UDvDS}e^rZm2ax$xW&A=;}>;Or#RH zNr&2^YG1i-+M@tv8++iY1kyca*hR{ha=^XdB=4w48tKaSll_v1NodCpAx+^JPm=F) zgk@F*Ddr$0k@o+5X0QxqB0gDHr;Oj+ z()Eq?%XN(~a^~vd2uTAzUDXfRSI^?FK|tJ$JViQ44w*Nm38gK^P-v}FJgX*#BuB?w zBw8M)75`?q40d>!3dyNG0HPphMbs`{o;L45`|ldWz)F9PtZ+NICnjmFCjvuXw_dGA zw0u-D(CIk6)Kbe@+9Hkczq65!^ZoQ-zo3qOKe_r4Xirr4?c8A7j7f~wMK@Mu)Bvb} z{38Hny^FUtN8-O`e!gd_ahRFj(p&o1o~4G;^tbQ)#p{do0t# zbS*7~nhXnW6<{HSIh|p_npJkk{B}}=Uaia?X)+zHp5aBm){bccW%I{;)g%+4+K`9t z+s6|KGVJ16)V$Uf3SuN^Fh%me4s$Pc04FBDk{_j`bg!kPUm@3*!&7o}TvnJNo18pb zNn5-+^LV%<9r&D4I%y3z3i`WJ_npS8w2^&s83b=|UmaP=b@#ImZ_GeI4QtO6xk0=9 zBt~qg!D`(as}LwS_!$UuovekH?<@AMAiyvy1Sg8~W=IQSf($_eu~mZ+R-D-R zyWi^x5TXAliX;2GwhX@3c;lruqY2R>V6e1(M;CZMg7sy6euaDJ)e{s6OUsIGw;(TH ziAV$T<6}~h_^^_%yU%X0KBvb!Ho-m26a#Q@9X&yjDPrMcm;ONJJ4m;R?jXCuZ*L3{ zuvz@K?@D%t6&qPHf39mO&-jZp8~fhAJ?UTbm3wEOAY8dz23L5*PTDA~ddxETzI=CJ zzCy7~NPN-=T;^*DCmk=3-+`tV$}c%0v85fvSY<6cDawZ1HF~c8ISBqyQ_$f$I4DF} zuhj=^nxH(eI~Uw#eYo((d4-3W-*Of2KLe*zDEUHhu747kr!~-Pr7nIUK1paKfxYez zMI2BWXv)lb@bviYHPw3d`rIP#3o1fpXJOu98M_{Me<)MM`(;O=V>$u?^uzZ+)+8Kx ze*Zu_^qj&~&IKIYCu&N)G3D6T%ujf9IWY{cpHW-EGQ&U;)F;R4QyTK=b6rzZK^=+lsGWvw55t!1x-miTzOO^4UDRHd3Pf!}xdz&P4wQb0`oXw6X!fyF7(JcZR zuKxyNPP7*|hAM20-0dZQy{I@q0s>R@{z3`NH>R?uNdCzR&|qeeXu@|n;$IV%@M%4m zJ5%1PT$chDm{@6PiB5P&#YW^@B)+b>9v&|bv&?h?Q5i^mj5XEbe1u|&E$H+XEgS-h zn;ry$l#I%X))*ueBw{BCqYqMIipiKYp-eWz-0GbmfMI_f`e5aq$*9WO z1vj2{XCe5$V+&|vN*g<6RN<&*R}e5|G41D&pezz`|TIv@|2gid(=-l zatv7E7I{uQGRk4`daQFQId%sMM%~9IuDV|%O82UDA4u5|QeAprDh>NI2G%gQDsB&?8;9S<1>)AHPe(I`J40!(+_PU#O38jaKNM32MOg600B~h z^p_KFceR&Vy!kLtq#%^oW7vF&YB~ZWK|mrqLBaRE1IwvPQO~W?j>jdS`Vj?xGALVB z)2enmHoy6Yis5&iE!~_P{NMup9}{B(4%gq>UlSufUx2e6vVt|7{_E(Aw9@Nk#p)ap z;nz+vXqDa%$IZ$g6b&@~Qcn_GV+hiIP?et(>rblUH0T5M`CwI>^84?%6qoM}p(oS^ z1E$~nwO@6#E)15!SX=ZgUH(76zYmFZ|F!hwR9x2a`HK2I;#S09)W3a3fONH$d#5*f zAj^;By-ZCz^b_1fotBIs3-uM(*X%81KdgY5ve~IL&aSxw9j-=(WeLV$wgc_|C16(yh@M)GX_-kKbX2O!_wroQv%j;YGi^N+9u6aYUNrn!mM_Ry7`wMczK3YbRy*#^|0&5Rbh@ zZ6;xjN!Y?0qO67(K6In|vFD(ZQm3x?1Cwvq8c$3ZAddiVOGA8a&LE47ox)Uw zT+W{b*s%RQrd&ej+wtay0|`7R=v{PEdEND5+W%Uws49FW-B|-T!`)VG=Yt70E~vp_ zSSrc0GNgiYqGTKi@J?2pcG_Ab$8F6kGeI}TZ0nPT2u3`c<7r&&+X49w{+355)}o5U zVR_w-rHH_{SsrB~?-W_6^7BG3FmR0^+Qdp$z=M?YDzfTqSI|})TTm;c`xJ5eXacwB zWDQnXF`i4J4nOXQe>iLqNvHaD!%m2dKKp$Q*Gk({5($LU8?p0lV)oM$00FlSID0|F zs+wHRA&A6uo+T*IUYgR=zwkHTr9p{sP7i>9T%w5$2%^g5tH?Hm?nLKN>{PKWlE{H+ zy2A>$=cVue-F(?!Ss#&!PL`a&w+z2kf|E}ux&tu`JYS#8PG{+#q57K+*6NOiD1Y0y=I9OTiuI*DjVZ0#Dn znM%iX94J^OF3P&sApq)>!nmm%wl3_C6--`O+!OYyh9n{H8OZ z0jHQI_Qqz=h;%fA*${wCDBxJSwj~dxRk>Kyc3HSIq;Cp4)h+b3vPgqd71r?2KYrd< zrY=tVlmS3a42WGSY~Ro72xq5)G{S(%$ha<%vt|U_!3K+&h`OFZ?eyY+Bn8W2TUCB- zh>MFGfT*r$76Q~G6w7OC!t3V)7R%R(-(DJ_~&KTNrp=zp090YL_|bt3-L@$Vz$_&;6E7>P`KAf&xW z?PrUVc7be6I{60*0p+|ks=GT!jGUPa58nhlg!E08D|n>Q&0=63P^0(Ze!_eEWoe&w zBNJunzP%oyQ7K8cc zGPo+MQ*1+G%?XMJO=*rX#_JrHDW}IJ%XvoXP&G$Efd$C+*YUAF<8y$wg8~7ZX3w&J z<;ldXE#U1c0`fyEeZ-yrufcoEUBxjI0VVQPDP< zkpgfM8I_d#a`6uo37B_10X(VnOWP!)*UW+)IF!nCCFip#qSPO1s$oTapEQMuH`98b zV%y_&Xu(NJW^@|21Vp^Hy&KbS^hQXR@ZXPRUuP=xPf?bT8tA6vTo0Lp&LgSl?>~=e zBx%zBe>H`O)%56F!uN_#YA@*t<5LSiOjVq3qjS`b*QGe3!7GC&XrqT{1>XV5=TU54 zLE_6LDOInUC>O&cLQ##p zgGj}-WO}>F#Mk;z3OkK{08bTqo7%X(+G#30gmfHI zg^>pxJ{xEyp8K-Ib1@7$G1GA6kD>%oLl?;mmtNcu*lFYn2t6;^kWpfYZU@6Mo+aj@LWxY-BUUn`wPV3_9zB zZe1o~ZWsJNk}oCdr7gQm*%v>CNq4VuM72^={7&!cQ}_ApW*1wZDIU0E?c!W=79>;U z1PQ13rbly^X2w<`EFSghx>@Wsv}8H`?27`c}dvC&uO+c#s{mI*fy>)fgO(BT`!d;mmM z@(_=#(mCa(`-S^w2)RV5z&@Y-n38Aw=i1Uie+qNxCc59Jy(**Z zhf|^geWS#4w+`)xpf)-|9ctRT&q~Oe$In9}4X#&6y#`T+z2lD=@F*m-o5uM! z4A7PY4BM|*rqGJ#9BP4(mnLMN5^)n~E%&aU_bjTTS2+L!fmlegJB9l8qx)c5IrG2L%J>^CAV zPd$<1$zq$SmKgCIY|nO&@E7@!e6T}ss~qea?iVK7TVat?z+FF-EM|yYW%`uKoUR)|v>qk|hvGv;{Im#g`9-CV!2ASTHN>9oIP8ZGdD2RPZ}m zil)o$)z6002j4v^*&@clT^OeGv0}Z_rHvTALDCALjm3Bt{^q{nDN7Y^stkjr{Sp4~ zi#{_upkmh|jrVQmA2!u6AYhp`RA(1>VXrKZYUr2y3G8D5s6nCKyBwGDvBz4YK*a=TkCE#k= zu!)ejG&M$Qra(*nk741MBb}29tcT4Id$l3vp83+)$S?2=yvRY@E%C8T5!raPSfn^;J6n{LYaRhGFX2msmV8FeN%>&VjrFUsDyNwTH9oNKr2 zTOcx&31@hT2Cn10EoOBu4kVPpz5brt^(Jg-uCAJ4&ZD9E28y3ikvj_QQQ)7>%VI#Z zHeVNO&(MWrq+Fg&aC}}>F#LFTQVz*|&iycA=)W5Y78{e3Y{H>!`{=d7`9q|*XYY$g zM!DfLu_HL~+1bv90c7w!-H{OSFId0>6;{^|d9N{TTUPnAhU-zt*V%Ht%2EHU%+2@t zlO2eFeD6XoBHr65A)MUpAw+?`-x7IDVsC~C!@%L0n>OZp=wJ4k=VK+y-|1634@C~> zhdY$ygLo9@7K)A@1toXpm-mK)uV`AT(BW#Oyd}dkK3ibeDOn7}wv5g_kAS{cz^&sm$>x>r%G<2@o|+-Uq9JdC5l%f3t3*rL@?+Y3ULz?+T) zYl2GGQkDq@t;T3l&-0I*Mspf(j%d;1{PPE1;GWwsyHA;)Z-Xf8)?UyKo?fR#f_G$i z{6AuqqE}zDkmYeF1H&V`hF5xo>4ps(&7o#+u`eIx#0Mj!x>!UZqC+PW1gAdS<_~3E zG<0fiC`A#in8|p5^bYE`+?_V_6!e~PYD^_+r(v#Xcx5T8tw>P-eMDFi0-n$=@B`X= zvrZv>aqbvU;x)#F78SwGY6bdeqH-2wfUOqzw(y!JGEhdgLY(|vpg7U*&3tpn+~cQjN$=@9*Yk4eiuFYLt4I;2z**u$)tw?Xr@7vRd_wDV{js0tMOI3Vg)24s;0^R& zerzS9;)C!-aW@AdG@Mf<>3wgxxlhKs)qnD{Lt zrw!=@H4C2lFruO_e6WcakA&+@Vn42y;|iTkf*kkAug2Ia3EfA~{skoroynTy3-XST z%0brK!f|^Kmmd6`hl>R7`E_f4h}@+@+|$;TQ+IL3sUK}Cb4ab^jy=}?5^+-5S9C9P zJBXqk9u3W}oH?(}+`A2%7!f}B3~2cAV+zg6+=_x{8h`=*+1kmPbQa^CA6-x;u!ibl z9IQ4f6k8E@MjA^$ zmy8qP7#Yoj@$9MC<`b89#UBL@!bpucjmCH-7aL3Qh29wYxl+}MKlKs!?P%ahtIh-m z2v`{;682Tk&D?%b&22ZB4fcdM`9TNilN5G4?YhT+(a(+I*YTjBx4QUY^9}X z#lfcCctybtSs^H%^W%amA?}5w-vix9{Oj#x-{DbyG}7_r9<`qhUegId*@H z`-9zo7C22hn^=0P6pw0AU9(4(7t>rHlUWAKZ9LWN(sx^vtrhrm=e^zEC3Z9Zz1R)%s^aihT7;*&pM|{h-sK^S1dcm-f z)Hv<{GB!BWm{6$PjRY2VJQh*dJM&#b#Eac5`|!i}{`oSx@sF0J%uv3P1sQoRg9=9- zQ-m*v?(I(m10L*U@to`LM<02CAYe}4ue=enz9iMN5gr1zkfTxQ%SwGz4X>M7QO|V(2o%Oo@5;&|_G-CZ9|c9M%aQv^>!JZSe@0)U zsWkTkKwcbl<8;7uC9o`Mw(%t(lEWhH+9| zrrQQ!%c*y*!?2O9SjlIVvdH0OqOj^BZtO4pk}w38`u^EER+{g^kWKDd%5cQeagq>uVqqcz#f2oS>FGv z?W@_Npen3PP!dlTTiV&Y%y@n$3V87E_p8}($)RHU;l4ygX#oLx@HXE6Ao;reZB=dH zmG#bW5Za*8g1@*Mdb1J+^p;)~2)J@RW*b(u?q&j+k8B@wh>FD&Yt7_O$Ia<~#&Khk zsPX@|qV5HCufkYM3-I(}C~tX`!xBeKCa3dR`U>WIokW6+oKEZEp&m+|{x7qs49@D@ zo6X141Vg`=`(m~C~;kIzUK>rX) z4%wnK@saa&ieoYjT3k*tN_RW+qZY%GijXel6WCUZwEaKc-YTr>ZhHfTMR#{DN*a`I zknS!~q(NG`Q@Rn5?(XiAknR+a6cMDmIcoua-`+Rpzc0>ny!|aFbM%~Jj`0p*4ZAkm ziLK4%ci(6i1x~mVKcbg_-kwqU8%sZU9jkh%732mX32SxD7-(W~K2-OoG+Gc%TJk+v zakZj_XZRj>Zp90Y^ah;c1;q}7>;zWMY$2Ov~=%cagyZK&;!9T^&R!W;cb zw~{gn58>)xu`WGWC4DPEz|SQ!H)fOZnTqeqG~w?!vkWoXYbX_jS#^#|ZguUEKraPg zD<;5#OWT6_HojmN<>{S9Qiz~C14%Lxb2f{$<|r(%qy1mU1H=9rOU`AfR7$GqB1h2) zMuTN<=hox5c7(K6_-^<@>!1m&fpYI-=B%D5$RtOdUpLgFAtR1lKj`c9^=;Q8l1 z>*o0;lHTqR^9c2h#BSh=(L0z`g~s*03p_S7#;S{%&pe>Id(&DzIv5K}3?~s-l_{|Y zGj@e50Un4nqT!2ATd)GbPr7-Yj6r(d_Q2i~(I$JY?IP+$IBH(xsJ~Z2nHXzQwHA<@+kg z6YM!z81w>$Li9GYl^TJ^02o#SnahLL+l;-(;JH4&?eud8K-(j3?dPL&?4tg0$CZ$_o6#me+ zt|)_R{XSe^fBaCZ(pyY=uw47<$|4FhwwgLFMz2Xm`p?ODNy%4F;mtdoiY3hub=`1R z6sqZo>L)%4|#iY!=!4$x1B*kPD_{6$7z$&vBXI2Gj!egwm#@&-N$l$c7 zkg~AgK#I^^j)SO8$p)2I4b9!C&7qSQ!q9WJ)TRQ0K~LggpT&wM_K_<1 zV-qte%srF1d%GtC=+`qy(|;kX91T4&>Svi;s906^X+x^3)h@F)$#4W6+P4r%A1gni zA})F(T_7Oekl@W*A%aokxHi#Zdcsxis)yIYB#yNu?-c@sCCNZQbEbk@1`{oSUj7>Q zU_0dqy-AyV$kVEES9}JPQT*C7P<=XBp;&Pd ztr{3vrqm~4`X9fz4a=PE@%!l{Pvg_8(mXTj00G4&M;6JcWmBayRBKK@_`Tzq4B}lm zf;=)V@w;!mpr_1Fan3a38G&d831|~c&58KQY*zsmaTHk($zvQ0KIu;$3fbbN0t`FV z@sJGNV8?#aSHHq(O$ywPuC<$;FLC5wg6?sw>%oJ5a<4E4(6KJj(*{`_XsU?%sBnsvphdns!0LjRdX z);z;6&ev|HieRSmevUgD?B}|$3u37==TaR&;-LQ8-okRa5QOsz_QY|=kWHQ%>{+km%SM=1EQ~a?D}3&gNyk|X!E60r5#~E+WB&@UaiTyTn+rBM?A)cp z2w9R-1Kr^Bakr5d-@HWW4h$Wr5KtqwN__Gt;_cRt=+TzGB7)X_XqzRxukDT<^{l&7c!j5p(E>v0i6ZV}A zen%i|NiTNO>kqw3Ub~lKK0uzeFBN7Nsii^XxGEu-%r7E*;z~x0DI{c@RK+-@y@iEfI^954xwT*P9>I(_A$}7I3n6 zprWF`LZ^H`gL?sCYUu<)!hG~Rp5#4h)LMOC5zhFEt+|!h^>-nZD}#=`&^m6sVzn`` zAD{-Y_exz#qgSG+!%=gCD95@K^$~`J<xcAX3ekpDhZOEhQQ(YW%S-s*tceq~;G)!sm@fh8A5V$SK> z4hU7|EBawg?>!R~_Sos0_U#PZU_d03u0t*@!f_q`Snl={lcWQ#<-SQYl2+gF7C1s% zZlUnH^)~G;^&C{ceCvR`_6X?&*35B?X?90!e%~Z+wD5=ScOjxIs!D;1H&fsFPOKV; z6A{3gNgu!`EmgyN5%Ul+2;l*H)})yA)};CB)&d5NM>(9}pFYasFzJd~vOjZUtHlo) zksu*(BQLr}4zN*(r{cA@1;NeXm7SSbZ74Ex{ zFoB_hjO(&X@LEHqdqiC{oG2>3fepaA)04O{iIW%T2VQ9w`&a}P*j8Zc`zMBqM5WP; zEn*TfwF0F-AK-H5qoo)GPn^yp9;Uu^3bkkeJ$`C!Lxl+7^q=|E+j!84bCWPMAgF>c zH4WI{iAoh+#-0sk{PaRXd8dZG4Er>NZ+7w!W%3~1jZ&#={_{sR_lM4JAb|KI-tw%} zGqkA|mHD8xh)_+`i(>z1eQ#_DyDm18Cg79DE8K7=i-3jG;a^Ywsb2aD{VZU$FW4>@ z`g+OZfN?Zd2M866m`{-9_e<=C!l8L&sGBL}W~QY09fy_G8fr4HP#DOhhUb|R+NP#} z^sBU0E#4pEyLG;w4w-$-d|M1J^E)kl=t&pQI<%?2!r=rGUT60f%$LIJ$-4K(Njb;v zDA~ZinE&?fug4>?3*RM}!KFP%gVbOVubr(;k9QI4xrDimWIN(mEVcmiyrzhJWC^l- zm|gfs`?eM?Hth_>?uv<}j8YUy7M$V+^?&gk+pQTQ(A(BOp7++r?EHq2Z943G*8qU# zv)SaB?@bLffLsO^4~U~0VZoK!;d_>#HZJ$pc#Dg3H(ux?@!?w$lzI`76zWoT!9 zW?$R50H&VoZ`Rr_@g0%)4M*1Wx~AZGdouLTZ+%zsZt9NcR=B?v^P?c2QwP~guGV0%CSoYjzKJ56Z}EYc_enw^^|LO(H8u7Mx3Q z>uy+-G^raCRO!Y}R42hSq6m;)RHJR|f_a{xrWN}6b0t9e(wkc2N)@Q85#$3R;fq zY%-#(QhUKLsQpmX5lV7_75_?{&ZWt)OaI`~Tllas4E@c;G(4BH2OQGV117q@UEG)zB>HYp&MZxr!B*dN>`7~-nwJBFhtn=$U(+@DK2Tv5FPSQdtF zYaQhHllz{SM47!VhKY-@4h%*QahbLtr$gbz(a;@TX>zleF%=MdthoX!rk1J2P6W;Ygu*d}- z@;^3tKZ`#WpZ?>3(Ntr2X0Kk1ug4CLG|c5)FFRq99C2B|Vlc3lpcNr$fO6){i-x_U z=fBkvO_wSEe51&r2}8em2h;w0XGXC@=&RYYGZ+e0P#&MU$fv(OTgRUrzCNIS`;nMi+Gl$AQP~P=qYg9WfzGbI4 z#%2W)Nnw3LKq!jeqJ_dINdey{g%VS_@p@+%YTKB&72=wFh_DxdeB)0%2aL$XS%9?< zR5gXPw!m| zw=Tgcxwz`>m;9GIUZR&I6 zxF`CFpwB)}YG-#<~9k1e%MHKcs8HiYsCsb+asQvLNIy~dodw~3NldLwYM`o|Zjx^H+L9A=z! zYr(`r86WuOZeRDyggL_G+?CSw>1j+<)p5+?f$B2yyrJmhflz_`h@_Z{AGZ=zcr&D{ zJ|3$bFZ^;ahATR1)O5L$>;eHt`16$p{ZMpu;#0fXE1mt0OYHo%0PWY2Pamsd5Ktku z79{*<>Y+Ei@Q5-3MW?!;WxLyauXCz%_c2@31+oW*vAYzCKmao+9Jlf^Xq!+;(*>w& zOmI_OXfgY2Vs0;zAh6?!lv8}3sb5p2{T`xT)${&`)%7A;Ct^pXy4bNiJV1!SVc7v_ zY7L5NgqG;(y7RfX8q1Ppia66ulymkY1T<@g%1{`_MjJ05sej|j?A4N8`2{(g?~O3J zjGaABis+ zu~^^_Z)Qlm9skLjUwb6qnHeYLujhG-YuZU^C|VB$Uttc*AqYRop=wwT_ zPCm$gL`55x{aI)t)u3m-1OtHg(>Mnj(QGN$>yh{h!4b4z$m<$7m>@2n<3oArv($(< z<`*&RIkW=%J=5brC|OdoY5R7g(|yK0nz^`EJB?dg_U-P}UCi%T#>Wz7py@viB*9E@ z%?j4*a}VFl&F}-Sfh2@qhP3t_nmzq-!&?7a^^1RZcbm0Fmg*EiGna_6%Vgb2)?;6( zcbb>0_@jJq0QI517lf5^l!yJ~DuqTaUa7m_+$$YZ-HKcECP!-x0zQ@*xZs`O(N)b2xso-vqgJoSr|k4rl@7;=6BPu_Iy2vNul2Uu!^^3f~+$#PeKA zu9M^^O&N}XTkuk(tBZUB9s4)sK!Hw~?YvYBytZr{4-1ix`pm25}VlzQp^-{l}wi+D8pg!7PM$ zQ#rKL@udw36+f|#KfJjIw$un;<~<182}!nd<=8*@D$0nLY{=qrbJ^9!?5ZDi6D_5B|v7vyT4 z(e;=15yEyP&oO@^|Ei|T@oIwLvnsT{fWZExoPYf-t8jvsBha}1n=UBkE1Cv#P!yQI z?BiXkUk{Pt_ceae8cB`>v2CI74mb7D@dGmCA?@1|;Hg%$*-TQa;q6{$5zZF3w%4k0 zUqfcGcf0}u^ysu)t?lxC$6fv?&j*ATJ6ien+1%|!jh$hrgL>3J1q6zT1179j1z|31 zG0989G93Z<1N5cAc>WD#w?B+F<@>?H|9j*Kmory@X=bsg6ST9p|8vK$qLyX$g|O!H zykC0L9}k^I0J+}nW`)qnigjIbchv45v5Kvu{mV&Vi5FN#DW`)Rn$NQp?A9sf_y;ws zsk4RN`Q|S6(S71tkAr2_n)W=^?qz8KK}cK9^JHINUMQS9510iJV{u}wN$>H-`V@36 zPkGCx!q7eH{@foEjMg7+Hs!+3RVN*GC$e~K=$#=QyRP;fXq>JCsX)L@4*7sH46<2hOrhaRMdfWWGGI!jjlN1UVn+31%1Z$!-*YhG4mP$1$ z%5u@F+Vj{4(T=P=S`jC8rVU%tumlv*2saw}n0=KNQf(PtLX+lps*Zlgcwrlu2)Q#9jH~3EJvNEfW=9RfZCgFFQiLpeCHt zR|pu))*{#=9Ui;iN5VioJkj4AkD}kOWKfc)UK%_Y?t$(0Q*nze(!(pmFmbd= zL#r|YI=<%jJ5mdS{_N?>Bf#@-&_m+7xm&q5C4B9gAzeI0M1B%V_Y2E%ohq8k=?y}T zEgMMmLLWR}#o46}KA6!7Hpf}HD&NchKJ)l^uxup)mAqZ`OnuAN;cCcSWF)HUw<^21 zOLS$SuNGYt0du^X$qzLR+*+VS`G}*sG-MaQne8tx6#@iU#AYcP%|ZFEKcS5duW25T z9(~^MsLKZ5_Tce^JyqX5GAaTiyVS>Z!vhj6ieDHI?)Te3z~QHFfZwnUq?5bOY5h%$ z!M^^jT8`|qWKdb$Stz3hX+VG`N%YSRa?>osX{2*6_r)U&XzyMvubcz!@D3>%6PKDt z>Yp_Km$Z^{7BfvSziu-}7e-nFWseF`ziD%WuGEgFe=8I!fL!wRyX2BR4gfw|$TG}% zhXYF%@_B$V7uiqe-?`b;vHMS&Zx(z!km=-T`6C7CHzDCyN9GiqqEoHmzHM~0ssrE* zXr|B${{RRPNPR?!{c+@d%@>0|qRFLrKktjnA*)H4DcnAF1;i9j+}LXea5|q)Ac$=Y z7@n4oWu}%hHQzNDj!UM!BL)Ie<{p$Qj3IYEyrq>5>S=k|Ex2NPDZtOrKl7&4=+$U0 z5K76ShFa9$7uuUp%~GPcx+FI$neEa=wu8YtS`%Wz_1BZvd#nOid0RfTTC0;L^T&ke z_dBgKfe0D=pH(6%SybK+w)?pV0CF5mwQ`Ywi){Y+S%>mrC#7|=Zn$5;%#1>&VIjX5 z&03$R*Ngjs8fF(?7OIj%*Y(+Snzr(`DPpG1=-pmqniy9_4uD(})UNsy7oHVzMlkU$ zQeEwrej0>917)hs6~xK(2Meu7%^%QT!H^-t#+&9QWMbHhk0Elqiza-({2|F#lMgN- z282A3E+SbHlY0E~EL>%(+`8zvcvh>-5ZKGHHD@a*=k5%u5)ZoGT<604Q}IPf)<~CF zb&{qA)OBD*MeygrzE&_8f076K9y*-s->#>0guO6--JYlOr#b`nq&*AdTv z&HhxiP9Odn{3~#hhB=MTzfp=CmLyvY3%fKApHi&Av;MQ|vTKRp%;*3qBRG2q;Hi1) zI0a9E$&@D}WV5msSU^f{x=;Ukg-xc)6kK{k)${m=LFoswsOFIFGRV2ipR3)bxM8di zFmPp{^uv=@2F|1f0Z(>{$3|=UAe--3?O(%Oh3UxaUsfK)1ZH=Eo{t@x9Ttqe0k&cN znHxUe{4WW!H6e9HYhjCOA{~-Y)g7MXg7rgSTk`mmEjLOejqS@EL*h|(`XyvXSaA$^ zMb$!$dH}gau9;KXiv5X|Q(Ic#$-@iwYX+r^{X>O9g9wd1yNSZ;2&}9o+4+o z%-mlK=pM!5zWF%J2b}Z4qFZ#R;EVAbJQx$v|XE-YG}Aa!tQlUbN}orzoA{IqCxK`PXHpbuV4o=dMyLG zaa~3?9O>vv{Z8CLi8aCj|6>~0b^c%(%kLbz)akvvVX+E#X%b(ZVI!5U?eibSqB&|; zLT%sVKyB2;kz(7|mF9ITt>U;yLuoVR*KIfj8V^yA(eh(tW6T3!5mtsLQ|q62blH^Z zHrw~}_@bZp0#g_Wz?2&Z96d?Iq+7D{LJy3p3jB3U73ChSty=2*v0T*J^}obYYyNvV z5I>t}8P?28wS_^Ini)C_fO(YDJd%`GwI3^Hcl}H|2CO)eIp=7}@4Y!aX0(HfI#cnnj~tW}imPqfxQSXW|&fBSk%JH%=+&+rD6jo~7yi^yb0CJPMnfKa(C zmMpRqVML$b{t?pO{M+k;8a@z8!8P)mpx!djA4MVQlyB^s|JSFG&(r(-O3_+}g&Ym(JEZG{n_**Mh|_K&fU5f2VqA<#Q0_7bC7kV|a!nbB22H*0KQ z--M+E(6KlJ$gxtF<03`PT?~ede-K)pSK>mJsNg6)Jj`G349i;$JVUkc>KVfnZAT5W zIPVnA^~zKg8h;mNW;Hi`QB&2m^(qOJj^h;Tdv7?~UHgri6MMy0Q7dB4+*6)`Lu%10 zI{OH6L-tWBkRk!o%M^r4@?i}m=lPVi5HFw{XpF8-H|0IXdJMMYK6w4Kw^uG26Y@ zj;$o<5%52Nro=LFobyGAVaD#h(7b=0&VSJZLPO=`wxsA->h2lj7yRqO6eYS22Tg+* zsL;aRU?Rwb(?fok?ELOE#eW%9s^-u6gkSh~bTimR5rlomZfUa^DSO{X2yLL0>hS{E zG`O^Mvg@zhyqAD(jtgpsbCg(461PU68Mfp;+hP|HEbP=vQWSF0f%$m>t7NZVN7$u23?b(HG(3UQ_ zR@V2rL@A^gJ}Adn?RFycon~Esoi&3iL(vC4TA}Ktd}*Spu?Hv~r-L%|X zn!ouvY)Re}@&wibR5=g28k(y9fi<#UqKy;0OFY*!@(q!w6E|5zE+=XOR1If|irr!Y zDFBs#nf!WAOrLZg6`#`v#uuoke`czHI&Ab)5CXmq?#4=|1}u%N0_`gg2h{9JVYg>3Ip9;MD3`S(pG zZ#TEzz;06Q^$IbVL)k`xAVHOvbd^&aC#K)#pUQkhVFnE24)b3j+URSqfRmZ6;pb7@>^zO zh(H8JrBXQg9)kgmRd7S?-GXJ9b{)sb)R)hu(7@W1p5ofs!LWRF# zd7~8Hutc-lFa7cZS)p0?lq_|u(IjCYwvaQNvT%r)>Z4dNp9h_T*$z_+!PYzYW6|&s z)lZz6$&<8t8^rb$MEAeevi^=9GrlaO^lqKIR{A<&&#Zd^JSpPo9JZN-b+uquea>C~ zRyw#d)Vx1O7{$26%7k~uZ0EQ*ViI&Uq<5XR6=+V1LdLl;=g`xDSRrd<4!#{Lf;+cZ zdbi{DY%b}d-@aMoS!T>6@mXQ9ZB&-{xP=s^X1Rthr4;vCBZF>Pj%p-WRP91&AC~RJ z>(Ay?TY}UZvWQtm#hP=kmY%a1MA4@;n zQahQE&fPR^kYmAHirfVKDeMNX_ZVC7xEmbEy)T^3GY^Pjb?Iq+nVCV;MzTf;A4-?GHN9VN2isgLhSp9 zbK5%E51v-1XhSZFthfeV=ndi6j0Lu_>PM+W_My*3?7it-wZ|3|3YNfjz-8<1kHd*= z>#WT|$WjMY7D_>*F&)<^{KnbeU_C;apUbyHE?{v%fVH0N4?SvYv;{?c_BN^5Md?6I zN!o}VYT8MP0XHe#8ZW+SCCAmzgXKy8C6#Y=W3)?rbeR_B`B=SKv~bXG2+Rl;0S}AK zBGHb#iI3BSz)p;-1pYSBy!z5fWu#nmou!%(&xRkG)S8Q4HPRb%XCUWMDy@l6fS+J% z5i_h>?Ek4goz{ef+YE$gX!r;x8C)u=4H^dy`UjHRPJ_8=3M?hOwVCRTQR7%bR%h(L zKwycn0yC_5FAbQgsNSkIp??fnuTTCJq8q*GMYFbQoDYJK&|YePZPQ1#r1_ymQphAm z?v5}x6!#M$!NdEPN-eiTu%vrP9O9M!w>vJsYDZ++VFD z_N<~ZOqll^mWaH{VN*J+0|G2}y?~=sNh#b4dMXV!dBke;YisUIEf+6%(N{P3_g{lv z4{m4f3DB^~h%e5|;>OtOV$>`q-kMaF+)J|y%H)*w8m&WtHsa<=gX z@^R~4%$6t*d<(eVD5`iLatUz6f1b$~aZ#^aU($9iT0)$xJRHAM{ZpD_cL2p0J%4>v z<*ZZ`)MXWon$Vd}5;=1in^#t@$k``s?)!F7V<+k^HSW{&p*LtI-)u2-xaXz(5Zrhg z^o&S9YX;{`!+>NNDYUjL-HO@!?MLZuR7gEm2Y{vf6~k-;OZ?N0N~=7d|7b!v9PiCk za4ADH_M>#czi_kY@En(x9V!tXt4ofc0mM1>gU;dL&yUwuNXQ60?p6$r(%&d_CpLiy zQ7su9~BlP*q_<_*_Y$t-XY@E!88gfbeY?a$umFkj2e zDgf^dx+VMRFN5?-Jcs7DUo>mezRPF2J8vy}`%KyFpo3kG$DM(`*Gv6uSH9iwwS?>n z5MSl`G9<{p90bjF`M536cW8kxod6#EXmvzy${C%Kg;ceD%^-9e*1!Lskz@K5VRUY? z7qywae5 z5ug4&uzpqaMn*V4iX0h9z!0cH=0*>R-^Xte?t1s+O-P8)dRX_y!tB(5sQFycQj(6u z&WUREg|GIs39Kw%ih$IA1gXk=?yW`o6$}070B`KK#Z%}HRr;J+Lq}FqXk1TV9SgG} zYW635J{VQY8SdXrgm{FK1U<51$&z6+MR0R=u0VpP-B@2UxNFAJ5Ft0v)=UDHp~N!s z5Yy-0o+KP|2fP6S;(paNj61w#zWAWX+mw`~av&2D zi9BZ0*{^3dtuL~h4+^*R0}<+?U-I&J^tOj(dsvaZmQcD3kzFR zBaP5AKnFVGBb%T6_J?SW%r`WA2M4b#0o_RTF<(W(gG*IRL1h%+Ws0x^uY7LXhBi8h z-zr1PIIU85)MWYv0iMF`l#w$W2VWaHJQYC;ySQw~*kCkyANi%Td`D?|UEBevMM%U! z|7VE6H;8caty(3;^kc7h8etk%OX&rtE624^X^Y)2 zykLJ!>tdwWi;HNOK90V5)@Ht4>bh74vG<=)UE+RAp)WS74=W-GrlriRsQ=kFJ6ius zd3)-D&(>k#ajQl_#Wrr!YV!TNn@8*Vg#Ld~o(z1-34tijnF{DwQ<#GLlZ#T#GWDmJ z!$MIm2=J(a#)MeCLBaC{FW9byVUzS=UJN;F^_+aGN zxnJHIAd6}^m@}RH5bMelp3zzZ5X%Dj0|)y*`@%*2vD&V8g=*<`)+4#iKSNN4Fohw8 zH4^3RT)|rfQv?9scnwwS+pAp+Z%f-hn1(p-_L8FzwrvDOKvK{?h#rA|_-~8NQvArQ zCk31EO^iwJB3-TM@#+b#m@&p@#hMTKywN(KhkX0~Y9Ts*jbGdvJcd#(ow>F%qug^k zqanASJCK#uXr4#?AxEvO%qdbvFAxy>>z*ev!nn9*im!FE$gmJ^7YHKggJ2?O_jO*G zp8B$>c-We%QeLui!saPpo}R+~+$cKXr{)i)<$c@B8i1t5nG@pT`R zd1=bCM?pYW+~b4*FS-Z6nGeg1+IoBEnD6m zg+o`&kSC6VKnbX?dUpw5m=U!ZSZmqDr3iJ-ayO=)Eqp08rRF98;V-}3Ax8?uDNGso zWb}@-Rw0A_Ya{-BI`0`Sp6&uiz9^(5=(#%DO|5;t%%SE)gZmpK_8=7^Yj{)O$?*v+ zUhs#)U?hDY6lmxM;;lRNL!vD8B}1a2!M4s1FL9>QF6*%Pt0e@=FqOv!6TlW6(IY>> z5n1m>ew9eI0e|99MVj60{~)9r1pQ8y30tE0p9Jt&0xzElVHU<*%y(AZx8vQg_UFwalb z{TQ9WRldBiFCh*YRwr64Qghf9#0PUx;RMh?0G~7^cmgWmEMQNv8jaj$BksLoC{xZs zao+R!?T^{P+XPu1ahLvS=&^SsOhJhSsrna0bIBSp?Ls=x=AcIv7Ca&z|45)+#h7Vh zsz=pH;!mO4NVYRVhMALyM<~pC}^S0G~f3?pwTi99-(~`|*_Y$k2Ol(we;yrqr)+ znEMQK6{(X(&^G_UP%l@py3Mxls8Ukt7-uLXb%d~Y!370sUQ{c6pHXBQ4#0ounW6k9 z+5}`QCCWB-xrNS?7O9HjQjInK-KaQ}5LG&XfnPI=eQVkR9}fUcCPo4_9!Ta{l}L`= ze?n-DL^}WedOi5&g-P-xCr)z@=zu`y9jP}LI_zhp`1&n+t)m5PqHR;qn{Kb@%P;B& zv+sN!Bm3dVzx&Uu2|8LyE1L}zGeU#eT!#2~sQf9o)ZG2)-UM=bwpSpSpzCAH6dJDs z@lTgI)NIvlLEvpahTFk`&g{wpQSU^FT>FCE#p+5orN1EgZS+o`0-Nwi-Fg(@Oi2wT#(8 zb>4<^4MbA)*8OZ(CFYntkjAx=d>1f;th>=>4}G8D{Ga5Ubxk};XUfMs2R{gOJ$zZ7 z+K##Hbnh1VPJrd*%tY4X$?$pSZ-g>~%F!l~HXMc*m+~`y7027{*8*~L=1SF$34R-V z0zD&7mhzNC#4b-a0z-=ICo*yF5JpZTjP2*jQnCv+DiHra-8o>@?8~DM1xe?`hj?@9 z`~KFD7ye20JC1#CCEk)CWV^@D;E-k6+OM$NtrOF;`$vND6kWzggZ|)O>0wRnuYW)k zW}?E~{B*SG&n=lO>U-W8(fs2wy942z?=c&0{&u-@VdVy2P`68BC&1ZZ zG;ZI`@Ul+_lB_!pg!Ha|dF&fUmmD2UBq%Q^JYj-@ncLQA*gmB0L(s~YA_qFe5x|Yv zmKc&ig%a;>nbI^LpaJWv{rbA8DXYt&$qeU8z{>eMiu&t!Exn#Iebr4(c&V@OL3O6n ztEAr=X9G`0;%>vils#<;v+s-4Wx!s{+f`lJ?X*q{xa9S=$rb#`S9RO8AgD9YMVkCw z(QrQmiTg_?oTP~(uix~7erhf6ty;WhIt)%2F%$pCEddJk!TSDq!vBHDOC1kUdx-sw z9mCcZ)vsZ5h$iSY&Epu7M+aN-P1|3__8Owy2|rJKUFpo-ctqzv`~iizKOw)XizV&& z3QPbSJSj&N<##s5m47S2EFa&Y+C zDz)rSaYUpFF^5(`&JZ_CZ;&8V(j)m`clZBJ9sqy+>?@P6bNG^>CVUrN{%-a)H_n;j z+;-Uz+$`T*rW_S$p~dGDPF|FC1Z+QhF*>eNrw-Nogs;Q+u7u?Bi(L$Um^OvJpgJ-P zpS@tWKWgDnsga?fv{L}efACAM6~5s5BT4?;p|fX#{i;Q zjpLI1Qi`Ck`J8u&3h*1M0QY5Yz`S?rBLRRV;S6NDA;;kk6Td?sb?ZV6+PBj z-x>h8Imc7{u&>6n{n#k=?D7u~v_k~um|m+Nv{jM(e)(1?iUTpWWU-TgxHDyisCyPv zSV0$lv-%1|Srl0m(Q(iuDw^P%^nc^TV`>#P=oE z$dO4ZFZuin8#c{}??nrbF8}DmlZ?SKeDw`cpqJQVS!Nljpe`^lI{;FQEVy*g_1|A; z*ahG*+i;5!eN6w=afRY>TtBn_uMz{evvbOkKj*@HK!f|O4K)aazBV_5e8>*nSRiLl zaY3L2FZ4{|ioDa7q_mk6pBzO1Bs6U<4nsv;97*gHByAS4oEYa~Zq52UV! z6$a6v@!P=#VBO1kBy1u>R#q4!>PApdW6bs>g^DVbmA$f4AQd)|`f`aL-6ACR@Mhir zs|DYd1DHa0Qo)OiWF}v7NuD93YyuBw?O=g6gs6@x8je2748g|))nCo~`6U8?yN`}H zz&N8W=APAt8ZV=c2B)_1C9aqYC3yx^4oCP6+CeL1rY<%C0rB8Z8ey!TsPNk893j6K zk$xca50mGkONSUU%HenC90@D#c%qVHVY8T1?pROd6#BN3Op2MlMNk=ZzVTWIEw>5b zq?~AT^w!)^pGx;w4KKa$SG~!XY+;~MhX3hsEdW3tXpS}b3I9_aJFlZPBSv3&ZCnW- zV$TNh=GK!q@%iX7_WtS44wiB>j>FHS8f$uUDG6K2Qg&#}_Z~aJr6MW+N?Fmdi?dC- zprdOz)`|xZG^fb8d;PDJAs_+%cD3;wLCo?zJsYQT^ZN`NL(>9Wv$If{OK+BLT2pes zUICnn4LDZC*wkCgn&#Gdqh0Q?7{Rt}mr3i^!FC?3jW1C84lEy?{@ofvt7Bt*8gF0Ih$9llB~QC zb%dD*s#XOv3efHd2WBiddc%!Ha;K<_b2m&fEd4TL!{rQmU1f7V!%hpp8Ws_Y)`TwPWK`$z9f1+r z==O80@}GG^(H4QqH_MIo)gxEq?caS<|IZ9{muFi>fK7hPJ-IQ zKg|?IkG@M2p6)T50|E3Zekp}lNeq8DdKx#0hwcCTjCUX15VEn*$k%4MalrwVKmAQu zLqH-N&fkPLQmo{@+~pd@K7sliv98=P%N!99J&DhX{t5N*a0Axf`b}<`g<}dMdG1Re z^E!hGXXJA@1Aplt{Z;vy3A6X2V4?h9Yk@O>;I)J{Qsf^H9U{~N_}j%e$Wi1KZmAG< zIa(2mI!j_&jY9vIwZJ(w@LDPQO16xYRB5~;1B(OA2?l(VENOz2UU;fPFChw(fRE3C z|JT02#tvRKnC&_1FZu?Qt_!b@RZFW6ILcd=5wQ|I5A*p4akzmmGp# zJ515@@V54gOb0i8W!nCIUm$ks21H6_%w0$^iSz8d{;aPr3G=jioE{s+=d{Vp#hs`mw z;-SX>vKH9#z-w*qBS9yurFGj-@5`|}{-N|WzU+DPz@)U_x%Y*{!BPUe)kw2w$2e zzcj-Tp(9m%UI=(CfYh%i$N`YiN7n%Ly!Gd{YtZ}&N=tu0xi=)h2e}HTfR=l73VZ>_ z(PFSh)iOs!u7(e9O?Eys%>47HI}>9X7$bAHNxW_e`N+B&2%ts?zay?cJK?f9wlhwH6`4Y^H5@)61511fEhr5uLYdAi{3cm6y*(ES)~-_J zqcs;ca#Ah3`<9&)b=?K#Gxa;|mCI>AiHuRV`zk$9M>T9%#2xckLj(p3hV^sag>HjN z7M4nBff;J%{I&u5h&x(`ux=|;y*bES{cKr^bFfD>kJO7f?H(38eUh|-qJjQ6ar#~^ zgX`k%YacDDo(D_eKp3bY*N#pBr7Mm8SC8Ytx~+t8pQzhh2m*nS98fPGiCv@V81(49 zySC>IG#2t2Aa!Y9Xe$5OB3 zxAC@s4VJZjcwmD2U(r{zg|xX^;w)h5^^zEMN%POYr{o`$yIeH39@1oSrjP<1rE~6t zlMF>s3s!(m!i&gJZ9U_=T<;`el$F~wG9T{t{*ii4<_P30 zXzJ`$6tqvu%FgrFP`tXnS;{!Jp_a^uB~vXR+QK$vj+yK)@>XoqT1t zdtyh1s_E=N#m=)PB|ZU07!BrSA82~!270*MRpI?VZyl_To)a0uhk^QnpI`Zm3x4G) zpbJYl1f{Ba z4r|(Ayy3;%^GFf=j$AhuisV2k-_oz;{0&=4?e{+wVJcsr-q|6$z%HKw$UOm&{mq2a zGk)t{C&(BEH9fT1EzEz?pwCw1>uXeLgu%1}%wn6qBDLTVAtFK2$@7P3!Lr@opprND zI9F4d=JwW;0imMG&WF!84{Gsum<>0x-7RQ}29Z*E{j!tSyYA_C12uqv|A)7?jLK^J z-az36=`IDSmqzI>>F!XvK^g=EDe3NzZlt7bAaBQaS^)i{#esj0M+0H;U`wG(*$s6K` zdMrl4e-=P z=yiBn<*#jj`T?c&;CKPelxr#WO^spMqFP=Oop^DB$(vdF zEN@fwFXm3N=%PTzVr#HB2!Wc)S0VQ@DLGFa%U-tA5fH3lpqI>>6G!fYK@8V{LVOdt zeRT29W?9U|^60%6zO4As7BM;$jFDC-)c-T>11)L_(|qT}l+7)L;;QZMdJyFi{qYgv=9$v1 zws)pVI>#Ec=@__~2~I}O4v$-0dBgAp@EWOj$dmX{%JRPk>y1BUmE=-t^G|?ilP1*Z zd>MRev)TQCp2}AX^4hkOY{6(JMZN3nSk-_U78q3e#Vs0S( zqP*0_v4369kBj8NQ}0p|swrXdJc1H>d0pPYlxSY5Zfn4uy9oIe&@s=Cb7oe7e&;3P zv16cmEb`@TuWtK|S$C4mnLcfbZ>wtuM{@QIt!91xklIPm3QJwwR z!n-<13`ESy0X{Gr^j~86O7)4JzftTu|dnoMn*3p*h=nZRn4jLq5Qktk5#nfNy_C)F@6r_1vIa3WX zz1TtV}kK$z4) zJUNe!_t0-P)B7y{j6gJaZ2z@U$Q;iE4rLBXWADxtwKxwIAjcQMX^lU+fPf{#d7|L^ za#2Y-BGW{78DuGFeD34?MdWw0)3=f0+^v4&73VlJ(#H`c{93=31ZxAER;%^5)1Q-N z1%N@BrTK|rJeX)>&%hIbHgGaj>o0hDb#QruV|b>i9T(WapcpfCry2xEgCotkZT^f& zBd9h>P`%f3#Ie=dw53n)=(RZT~si%cJD1-2}j9fzPN z%Kx8;3hK4y@b$Eu6N7ztvX31y60?|(wU*6HAU2eEgP*GGXZZ=h%st~>$I6zJm6WC2 zd<{3&usiDy<*RJ6n5Mt1eko0{X~H#h&v;=>zwA=kd#W}(ugnv}VrNisfpmWFrj`1F z#4RHmf$2>Y}BYutlH=6 z&C#zzKUG4We7d&dt}SgJ-ye)@(;HmEz69I+ zWI(Ru+IQlKNV<2VdeHBnGG)8_Rd)HHi4mLkJRv_jaW^(S&bd|J>0LQZYO*7g$k970 zSoux&Wo@mGnwFPIE@JfK7E-{RYoN)JZ?zAwQna&A@79nj`VvSKMOq4! zH%Vn2A9y{ZELb+ANV33%CNSuYt{t|^(J~4H6}P?&^HP zeQAQ)gp!clUlyEnDC>odYq{W%JKf3eaPMLi8#vtMXvk?qBS~_@J;3bi&K@$= zZ2ioAiaM$sHA2UQFjn}7jtzQ9gn0XMsSlffP&>n%JV$r8d>2-*S%I1Ketg;t_XtF+ zxz|0bh^-_{s`mcLfhT6x)JsU0FOWZ}S)wHSyPh-IKA_)3^myTBTep8F2;i=kYadtl z(+u$aP#|r`k%&Zu$UFwhluN zA-NC1;%@Q1hDg3pcWXV{?a<~2Q)Ds7E~p1j0pUq)dan$ME!&~1lR#q^^SgyN!JZQR z%FlD@p)zyMvG(l#S)3stVZ;esg$-?B5YX-to4SJ=_XWqG@!+RlekW`WG-Vtq7=HHn zMW&p6CK@9~!=oB>TaIGhz}cmHD6$s}~K7?}IulUh|fh}qMG&;IV-7R9!?Q_NKf)C#Cy zZcgv)+k6zXdFT2x1!BT!Xczv+m%y+dZ1I%1MD!qtM?K|bJxLCzWTz#H@wOHijGZ>8 zXjL-5k-fJC9j!F_;{FeS)lS#dIX!8jElaUJqhw5`lYuE20SMNBdD_xnZk=Xn@+ zjeV1CUwYykmnSz~nz&og^{YRJnWEuvuC>_o0_JRxD;*#;ZLAM!u99yM)dPLKUng3v z7y_peh4OhiFUF`6B()Yh)=mbSl9F2LJLi}ziG)j_5nfIHW_koW#jnjTusssuRfHpm zIM*iFKY|v-A~fjoNXXd?oV$TLr{(G9C+dMN_|N5>Q@#C3WtL@hr2eG^X7}+aF|+J_fvvK7Mu6NcBgBeT*SYMzu^hxq`PYKx z+~J70oX0QjGJfD|)np3~Jf7rcNd)qD6A7Q)R+1Om(N=Kk9p9R4hw|clv*RcZpH~49 zL#%)OxQkG5XpdTTcs&=G7Bb_R<@%hVn8U&MIh`^g%LC1w-fFdYQ7I`_{!3{X-H`l6 zkfGL#=&Qo_W;Y53Dv9IFU??5l54T-4mLQww_AwL)s?JQ8XHmpC6hSGBbJGq5M0sE+ z6CjBo+(X&W2{t3o9F1pbD5d21oBlq&Gs=usm;cP#Kj6nUNnF>X6-s(me#D+AUmU%? zklPrzb}=BuJ%6p&NDCC>HRKclJ>i@*YA0f&WHBzRT-i@B^Jti*%d@(1964T`d)!9n zN7Nz3%oK7hc%;uv>k^VW=w!@^n!@*~Oosy-@jUZ@Bb^Vm8w+`CC~+1QNS7~!q&E-5 zM=kQkS5s70k`8Im6MnnicXfwg+Cd84ImnimOrumczVuKjQ&^2cp-c&ExXnt}pifrTahVQ#*#@XT6wmcGxKGZ_JS1jYgmPSwvJGUz!-HJ4U+#swMo?`d^2z zsRnzwi^egb?Mg6lFV;<_leMAvIr?x!D#?Gl9&?9vT9ZKXdK_BTe||Fh3u^47Cn#j| z1^q~eiV>&)*he&R_Ee`vGGKm4C6o-vpQuH5;gDL`E1k`7{ThN35d1yw;q8TjKDk3* zh=DpVv<*l;?TSP?YJ-_0KtJmE$Rx>pz)((%bT61jeu`WYKl$XCU>mk*@xmS_vbbT- z&Y06mO$2B?WOP>Pez;p+#2E6k9q-N1innV;(mCz$mYclCCsqSY&VRsrM4ZSc80V~t zuzF`59pVV7eOng_bj3-kSoU~kk$R0~Rf2X|j=HS#1Z^!iOA_@xcs!Z1GQ_Il8 zlPspj^GDa$q>Iw|h>BY-x=o%@ZNgJw#B`v1;HIGLE%n==D#W4%s@L~DBlz@wLwU;^ z{lKP1gG9CbRK9+MAI>xIEYN`sy#L^Ob#g@)n#!07!aFhe5IH8tDrwcAC0*v%3f1n7 zQt116K)veOvl?0&clCrU*027@$3wbG97gzkhEI{Xg|in;JygJ;IQgqi1=y52HkG5e z3u^bVFSYyl^kL+w!dXl>MFYsl_vjx47mj2ah+x$XZ1tdTetiNMH>!JM%E79{SKGM>z*2m4k)e#eNifN z?M~Zy06(~XcMSC^kU!h=`&*nzJ@PFIq}x}&&_z(S;!6>n*oMJSiD>?e2ZcfhOWr)F z`i{gm&q+-LBjSlqK3*~=2`wt`fk8;{EmvZO726xbFPT5^{Bmbg(|(^O-KsJFD}%SK z;QaqZA)q7J3l!(J)#vJQEOc)ug@tPR?A1kO^g_5;4tIH}$KTv5dGEKxtw}a2UfaWC z26v`mel9Pn`h*@)u#O&K6B&bpOglI3{WkV*w(hk|_qGTU77otef}Vb@mAZw{iJBUS zW)4+&Ph&hgKp5ZY)wBFxY^^+w3kr)PN>x(eU8s4uXi*gB%57I%Mv@=vE!L>fq6jZR z-@Pp?KGK*W7i%W6rV3Y^IPsl8QN}I35-@1wpp^BqGj;fvKel`>2cEjRa~pJu3z&aC z*(yc`4F(Z_#uLq+4ORV~2yW4KV$+ZfyTN z*P-cH3Qr)6^SxP#;IU{}Mw{dM@i%a(O47B@-RU(}y;7=dz>GZ|e4@?+H53qwKvsqy z*CPoWDZR#JMv*9Up{_yB^*2n2h|O_wD0c@I`qTFZwzl3f{7#xAmdp@2`ZL> zoH(5d(wM0g3HHfVZCt{=Rn1S*M?)!sIuM!430PY7heYed;r4l!|n8*hlbX zJx3M(rIoH%eNZ2wYSnzs-}g88adwVHM00EwNqqn=p|k|To8J}kYHCg^>ZOQD=WV6X zsn&kSX)4o_e>!+ww{Z_1G??aAvSMJJ`s!UcuV61!^82ns0SO8|$B%=-Hr%vzq+qBB zn8^ir?}}tI{v3hH&~#_d-fXf=H#bf-LH_MqZ1y3MU5A4 zm@`!PY*<(q{jf2JZ2p2LoHeeYw;kg^!_o^cP!L~DUq3odu2>4X1EXI^x4%9I>VbNd z51M(~Y`5YR3B;0&zD%RQm_dS4s}W{z<8qiMZKm5qaFO{x9Ag*0wlA7yS0lyE+PpXZxz z7Qo=QQq%3-0y**4HI!xv2QXGpGo}292JZH=Ocq&q^;X#jUHtdh*|6Ka_?ysv@o~(31{Msa+%<3|8L0lWK^OO zWe@*J!rNc_d#GNscs$UVDW|wxei&dL^NBap8l;bFQO9bcjqb^3v{(z6R{Y}J>B8X9 z(E%hSODov-1XN3v2KQ@GZa<5mJ|r(G&3BtEEM|-bou^dJ9rXg8tJ#Ff4k&qGnMYe< zeljM03G;4v;v8SQi;B4}ZWnjsC~<8vxRV`bcaO*ai!J^~TmL0A`nPfEJ=&T&{pMJJ z<{5XWo+e{^cuAuj)#>$Pa{^}sq;!`olk%X`IA!rf>{@D@SGQ>l8eJ6mDQu@uL3M!d z-U!u{WqEvaOZ;dn=*0?eu*vJHYQELQVahjHRfTV*#mVsE@)ufBa)z#$?lD5C77_wK ze+ZMl3B31(7xmL(frWT&#~|ziRd&dHX?OsLuy;t(`4-bJOL$q$qMajV&|2 z7f@(2`B$-vfHv6P7{h8Y9_UbZ7fWu(G^1qkCy;{SkE-}M%~jf2O~_9d!d=VgqW(;N zS1R7}8|N%tZ3hmBm`;Ql!VwukLUCavv0dn=&tM`FR@|3_sT3M}Db5}atKWo@6&788 z*fLzI%i8zuvr-wd!%oFhrc`NFL9^Q~9n8{n5HW>C>>^RciJ$#=$j;KPP^tBijUYVZ zlaCv1sT4ds5T74rd44=o+wmLNm*!W~w_k>nzimEE{{ex8mz-Id<{eo30s{ZJu4$k7dqSR1#ti2KnGA8Y&T?z!VeTS!J$31|@N2bD*2; zHUXzXD_Z=@55-S^r(jLbUx=xGpXatvco{fG{Gv>N>n#6cnawD3ym;zH(ll_?El~H0 zIqb{TKpLw32>usS$ZA@ZLx;WXjfL0`8kDcoUO#^0!~Dp6HKf5Ep|T=GgGTBV?zU89 zQ{^@6(YzxrY6;*#;LO}=Iw|&rA7zpwpX0!+AqRCBq-r3})1ef0E4AZR4)+K2QQQTP zeESFeInyrF>Jhu*q6vLP3Ua;>Npwnk3!S5Ywy%RMY49w#2veBaioyw-EK7suAWQYD zPqtBv66!OOrX4U;)yw?VI-Ay;kt{@^kOdwRt2CSA*^j$rRZgCZ^`E}e+%Isy(R)`g zAZMn!1S|S}FY5ehEt;d&XfcGMPIjodX0FLb0_^L$ksoU|)yy3bv*~a?%HN7~qDKPTrN>;u&)>n4@m|WQq42E2RSkQ49gk99(UF(;6NR1}$U)uk1{a(j}$Q6rXC;KUD4}oLXQ<005<^l1BoA+8|5KE0RK(_$| zwLpz}tWgCle^LaORd&he=2;obWQI@ejwbB6q_VkxyB_lWxO+C8Jfb@!=BrhH_Vf)q zT(;XJucdjKMT3gs`2%azaDubMItdqKR6auL1_y5ZSzk3tZ&CF9}Dn zqps%K`qp@;8S>Zy5cEtJyUjcZMOZV#gIEXY4p6`#!AVG>ISt|^+KU(2HaFHQG=6vk z==ftqI~MSpKNPc-!BDs;2q$(Pul;*Vr1Gz#C}Kf86ArB1Mrlv3wXP7)l7TiY_vw$mZ|Be4=0KdBD|A=K(ba)k(@~O)GyD7@F^6R`OqedKs%~tt3?}>%8^zPT{f8*>f zkG3!bOVih)Vrw0>GK_T8KAm1hq`#eG)t}QgVktc}>XrI0wkRIsl2M7&2+X6m$0#eU zvT2U8PS(?yu;EOQ!Ge0T(n_%{OZT?clQ(CKBc;8?g{E)R^+vZw8{qo`ZM9?UFMh5D z0QFe!FE#ElA{gv$=|5+b#n&TlkHLb+y0Gn$B1o+8G`+%+p0|Q}DE{$p?~DG?7OV0{ zYKB+2PYm9vOvEiGXQ&E#7BPo&KJ~^MpBX*T$G;!fzg^DU*RQ%Cm-=ii zNT&?Kijt9)29`R)W*CH12j9s?NAGR@+qnKn)P9i8F7XcLP&}9LlOI99%zbwhmb#%A z4p%C||8de=kMY0Qx>wTPk4tos>mpm8RX&|qzgeC}-u;xWpj?}&zI#pdrSB`-395Tr z|Aukn(Uxt5LT{zYjx!5M$QdYO15c8k_+v!=i37xvMys6#zw^B1x?t;0oU7U(+TOy8_$^f8)G*fw7dRQ(gZ`jde82vU9l0Xxh|wAY55L{pUjL z?2EI2Xar6iFWx&#&2h4%>_lxC=-U$}ri1dfMnJ*b;}>!6pCvJltT3vJ0`{5oUVLn~ zkS%+2!Kh5R^~!BQezeh7OlRP>!}^Zqs-|k(Y{cja*UQUu*E%Gn$pp!1o+l2C z|E2p#$cO$@H6FQYoCJf|1nEvZXYuIj^{}1cI_^DfMxnr|$Qz#CSSD9&_Bni(hz}{W zCm1Uxb;~fa7b_`6rPy3nQomP3xaO7CR_(M~aYj+-h)mv*uED%!_LEBp8?M(X7%o^q zaX{DdBC)9WVi=CRmHZ3jIGBD$JGKR=59+MU!9Pp{uk9YNFL8}w!Mc!tEZ55`=p^%l zFI@hB8D)`&&4JP&avqu00ft&&oP&tgfq`oW*toZumG1@giQFDT#0P?M25!T5YL{S8 z$VGvHDW~md-VH77yJy^Se$i9UVAwKL^Ln@ig9E_}Dn~d;Pvek=_;D{R zwWb%MPub(i{UoD$1Q$@&BIBdEIYwYs+>dqM^u+=&gi5W-c&#Y+VdVBWuj^MUQ@i35 zlH%@fZFYmzlEgdlPw&Bl2y_pji0$$!rh9w}AW=^!E8*S~(MgUq4GvnO-_?jofBdiF(^lKMPoc1qi>LcXX$cE(Oi%N7F#V^-anOV+7e>Zxqw|PwVUi>Sro^8OGNzbKfYMb}I7ggO63PX>%84=?mM4Fke zlh*l;xI_PG`1PwrNbhZS*f!cLnT0o!K4(N~8u;;o_CJ_)93B1Hbi4t{j2Qcej*7HI zaSA`v-MBa|4NpH}#qAC8Y_m*55Ndze1NfPSbfic((hcRaCszmtXk3hquwSimy?c(T zd=@T)a6baF`kD6zSh;;XNtRz5BQ6QWi+sKbfT>V1>_g7tSo`OU!64~Rv7{{yrF!3m zw-8LCr?pa6Xi!vx8&>r~Om0I$$fEvneapr(T9aKfJu2i{%+FumoshlhTS0^$+D9F) zq@H4pIsv*L#L$?oZh_6l>#`G#+v&f5Jl-!^&k=W^Fx09LO3ujp{n6uTUL4<|cP&Xw za7AEJVCC=AeU@^g@>csYE)bn#0eJyjZvTu+Bxu|UBAtgQ!$eFUHZ9Dtop|wlTpy)v zurw*s^8x%Pd8bM|lyb_mytvzNAJIzqn~znR3`-_>I|9$1Yro?I=s%9mM37$1BK%z* zf$rDg^b@@-SX?SB;}f8$@08~iAek}VAmW{y?A}tMF8TJ0U^B>T9;*fd=~eqP;XIi( z38~6|z>gLcXi!o7jG`<&D81I2Nv84Ycs2Gs0kQDYxLH0r{S?slW41^}L`#DQ{nNGP zpuOo2(}G0gmt|WisVb$>^cb#BeuL+i<99-Xd$%$3&9>K6&zF`D1@BvbH%orm9RpD% zc}X%*>R=W&N+f!I#M36q;I>NRd)T*Zj+};(1sCjuh@rpGo zDEbu-jD$#qXgOlh?KbC!hC+8^!Jwdq+oSl9v&;>n)K@g&7=qUuiBI!WtDGTGb9$e1 zu>l`O7N_7wWvox9dtsoj^wJd&3D+PXK>ev#uJ67YZ|=tEd(Xez5sa1W7vz%Cyv7NyN80Ri>wNE zb(zlk72{Dw5UQx1>Ck_{3nc7cJiT<(NeA~iLtv80V||j{juJ~q$2_w=pf*VX(&Grf zTDF}f9t3L*U~*o^1{k}lrfWqMlnb$&X_@wZ!LfP-KU|m@NceoAc=Gzn?zvS9*P?~9 zwh>o)NsDuFK1llsH&FOpvBF~Jjtn~)SHkYyG*v6o&F4NYoGuOX=lk_(37N$zvy)rr|zx!Lb&W-oGE5MAG_ zE>8N9MKxkE**)h6wC+Xk64h89-*Sp_cbH{;6^>5&V_m_%=v5Vtp$iLFf8jsuAA}H{ z`of)|p?W>royf#&?S!8vb+&Xj+}<G?I?>qjH*;s}*AJAywr@gk<91$Jxb<5HT*n6u;As^|FjVBB17ev|u$i=er!Tnp1bl+9)o?J(Tde5DXs-YqyC&ooV zb4eIw$8^NFeKus~7t1aC@bf{l@o(fB^)X1Ih!ufXXP7KQVH=MKt2Aj!fK-T}@)<1p zSnZi~$(l`f|K|T~Tz`~e1p!&LM}v6l!YGU`R;Ka2RngO=RZFICBdTkq?FZW)E^q#A zT&|B8>v`sA-;L@u2SN>tFIac%p}9s1IHk~i_c%`u;U>R!{V(Hkc(gUDgHbVDDx6^6 zG%{b!;ar>A(*;*STnAa^28ABRHKoKO<-gc6 zf3(%S-p3iFo;39t+suBXG)4U7M-VLh=RBge9&-V21uocoTOh4jO5o=YL6GY)!z)Pc zc08ntfjg4OPcHdh9#{UzkoT|u;W?g;M9h?m)dU%f<1d+zkaFL-)~-Ltp`z+UWh0Ya zD6^q?dxa<@OY`x0`*tLO(Ib1h&BkjZSHP8rt-y|x^t1xasM~(|?9I;$8DuG=#A1i- zw|y7>;!8unH%0eC=h%_ma81J^W5(1r9jtb}!`tnrAMmDFs|!@4lYkmWR!W>xVrqxx zPx1%Ux?9)1tUej z61p}S%r{n3zIu&|k6JR$!v?^uSxNrG2&Nq`w7Mdc_e*s;p|m%zPmF&U_SiN-$F^+D ztIUaR0ogJzrR}+1C{GtxGwEoe``$p=h3Uyjd1HlWDDNs)2d-N`ZVXFJoIo)(jT6UW z){4`y`kgH!LaD59(=pN&4CD8fl?NbV?s{=Um0CjIIYO*2KHeaOS1BftNk7u$XG;0t z%ritDl=GlaH;M1eMKwm=r+1KBqFMa)0;bX5R4i_>Z~W}! z+LAc8<+a@jxgySaHz_fVA!b|rBl>JLCgt~-#74^>i#VUEzamkMqkQV~v-Hb?Vm(1r zw=i(HrdBKBt>4hWuMqhP%cyQEFr?7B-^W#+G?XcwtYDDv@PQB+k0(^8)xL{UoX3n+ z?Iy316u((8+N!SigAxxW`*OYvBuzjX4I4cnzz|0c*mvCyJ4u)?Vi2l0oxJ1rd~#lD z0Vot-Sz+<~nqu)l{FwJE^Ob3C@19f(0-dvESVs-iaT z`v^Wb<3{@(i`lr4f-8=Ncy*<1a} z&t`AK(ay8a$i*gI{Wib-xP0IQH54erUJP0}PJ;vWKUkG&a{52#U0$tLZ9L6Pcl8>X z1cRKV8HJ)Fa&YkDek{Etr1|A5vZQ@lT=AXP)@YDbw6z@!r3_d7A)At6r=%1rnoJPB zGH6i0?Pmlp>;!y5#nF6*)IYBGL2+xjnagfeCRF}<0@ZM_@pj&wI4tkE<(waxlu|Sh zw<4Vn5tN5Ic2^0k4SI+6w21N9;@;7~ZgQIOtmL^Way_C?g1)LksO^3g_T@QZ)joPq zfzxWDlUSaQ_$j7$_|q>4Ky^LsI~q1G#PSF#$|@{del~b!bmq51Y3M>Mg&W<@Lwpae z*A2iqec^Nco)K|J!T{mpcY8f=BJl?Di)=zo^1_f$K$*4Sl_?Wns1)L_1Ve(Zw?>hel-xA`(F8&a=!v-SFq-OpJZM zF_~yoUS$0y^PL9LkIh0&_TPq@TzwE9(w3X(5Yn@B?Qc zVz?-ZHn^Z;E)63hM*oOyNuk%fuutEdwuGBB2}CZOBtE!)D_6kK`wKJ8kI{MwiKEid z$mhXUhSyWpss*0p{gyWjV34JB_qpQU5I* zB@*M#8y{#(?3|UrS2_m}(opL9_8n2G!4Xvy=DKStjOGHFCqrY2Bm7i0Y$Y@2AFB5S zIbVIoWPpQg9Y_WXCbPv8OEXJ=D=^m2%Cgf;EeX!VUGU-{gI6$2};GE7} zq}0k0rOa99Z6gtkI!X~T4SWS23q9ORxn+;_C8$@A)4oVPW3n$Wl`Ydul-%-TO$=>| zvl%qr_>ayREKlRRCp92q3F%u61j{3SNZC*>HV=VqVW!bBJ4G&oVUfty#P;fg2hV>p zl3b+{^7SO4ke~ZJRDkWsww@zdB_uwX%}|lVnwtg&S?vd39MWpMR9TA8#VN!HMT<`x zHY)vi)s1y`@t)AU08q-n5+n3hZC#BsRSVPoc!oezQXosz?o*KB^k#wZHU|EmKmY;~ z?%(nkpdOjzrNI^ep*PvT7m0&+mL`Zq(udj_Hs;u=uPM;fSf zM9&eKdOk`Yog3~we9fQsV}@P4gTnrgbjMaR49ileL}F+qBdw)jd##Q9+NSj_0WY`t zb6m0rzKVNW|2D1=fXLjlWnC2Uwrr854!xWdsc**7T7e^x%p#{o?@UV)ZKPq=9*Ux( za$))LuWg@#YDcJPVTVUsU$oc>8-%F!KrAgIfCE-q(GvhKHkj zYK4)m4HCxdF5Q!?S5+ROMseIVh!8(UYO=Sb-%fq_FXPI1w3SgxNfC=VWi!e+Uy&z% zj?Rp1*NPN2^GQi^)OnObxclA~NKoot*#5veVZRe~P5lhTz8yYCR-<$(mu4CM>Cewi z^blkLF_x2{@hFyJwZ;0)b13ic&8%1+={?|&27zH&#^-!m=1p%LxHT`!LDon=55A|3B3ep0y z*#m_?$Y^A=67}d#Ch{d0nEZXP-P*!w05ynM;Z6x%W*2>cxB93hOA7H#Sfqz%ieX#< z2f^nOW3a);hh@rkVM*xVn@f5#`wyG-c>Uow!X;-2Xk0N%?d@yxmqGSG_kbjof!tRV zTpG#D?Y-Kpsqn{y-)ZR~K33;bGDJaTI)Oorv%I{Ud3oNuvR?kljr}VPKVYk3!e%2k z*^#Z`)u(`7b&tZw_cW$WiSvtYL&>;r)OFj)nR9N-qm)ih5fxw3M!kyxC^=i}+-)^> zg!WB3Byt65@2f6$0hdIWV$tFiE0ZuQQnTMnG)SF>_fp_Ypt`_r?isI6aF}=lQy?2_ z(+e#|$(2uxJAjN09Y?5b=a>7%Vh}Y1kDl{toj<~PM08?ATR!~OsblE_c4zzk>NrFK z{T^Ct^5z*DZ;V7NjD(A1>ZkV9<7t{(wtxvu2pT%qB0+o0dy$U!mVg~#oYR7+~KDyj|L(E942mEyHO?+ z8;Z+5+RUFS(*;H&P4=4QZ-Zr#BI!R(sw5-?2|dY_^XL$Gj<4{RWgF0p8`*qDi(szV zk%}>J7tW^?5a`v2nwM8J8?K9y#yC5BSfWv`mRj)Rj!5i}83so67mQ<4zg9g#N5gwR z-#MBy?8O8IalLsvBf1~qG#IV|51tviP`K5t)M>j^vJ0)q&d0ziEkNFyu=|44|2!--5h*TG zPbxQ+2)IsI6Yn406fuAVjyyTo1^s%ih9EMGVK8RK3ZYA)V8tG%{f>JHa=%8SLB9wE z2{AG5O^NKw`8~7t5)5QjBSi>?INh4wVyWj4jxjt~;VnH? zL~rl_{(l>ftdQ^HOK;Yw>Y6?^CaNZm`-C0PuJBoQi4A1W!6}Bj3JB25m*E}b=7$J` z%_%;bG)sAZjaGOg+EQnwpz3h)Iw|(|ymyTpa*?vj=1rYTE51h4W=5;1c_o2mmn^Oe zjT1&J%LA0#C5#HLfPLGC3S$1cSN+O^MBX6nY3+&~WvcSx#*F*Jya&NZ6n`#72}>b~ zNhPS-Ym$`VUm!3b^}l0hBX)(6MIQh|;V;LVZ{G^qyroAqqe{EbY44=K&`qPa-I`Bp z*kF4p2c(NBI)=PHcc>konAUHTWK|;#tfbin)H_twXJQ~B2GOtlM z@tj8}M5{R4!V4$o6sEFO-d2>pQ+Jte@WK%JHaI&Wu5r`m3xS^DH94rjL~VHRT+U&;U zg3zc<9~U@zHv@unM2e59^eHgu9wA-2o@5b}+L3um@8{=D2~j#!2t z^Iv2tX)524yUCBw88q(2UtI&5)7A^E4d~}jNG;s@!U|XNMy?8wDPHqP%5FkaoHDE~ zK7gMPx!!6aan2)di;+WFMQNtf_jDb#knTG;TBEHqg$Fv5PR07A)A~)2uykh)&2**~ z2yyX7hXx`?eA>!aB$`8r1VafxyIXu%SGLSl@C)><^{39DD--y|kVMeK;6U(Vz+U?= zcug@fO&fkIe&k}-nX55!#*C*2d6orkmHagjP|;3vz-(2wDs=VzT8^PWyw^4o);7)A zpS)rbSq;_sTnDif<(=rG=PypmZ#A*PQ%ho3zV~(CZZH~`1XNb_J{^fxqgHG~fCmn3OGb#?!;Lm9PRRH>T{h6=(q zPa#Fdj(z&nKFy_;N-Z3$u{N^$y_a-d*2Dn16S#!F=Lio(021NfB#HCDPw%-5>(}F* zwz{^bevuMkmj&qL1G2fUka*?4_$px#lNe*Z-}8@ulW^Xb2fw%VU*wJdHm>_pu=lo9 z(gw4%yL|Ov8hp@e>Jy+A^ln8nW%meDhrKTHvTbee$MtWv;2(MS{~yxQsmF1}^2%b{ zF{d(5j7Rt21VEY#Ag#`tyjUjF=)&h>Nhg1JU;j3)KUIn#Ax??DdcQsmlsvd|=w#%O z*D8@0*Z(*jNz0%+2Q-8DFBpd&$EBpI@`{*anmgWy1xqdzVtI(3%|wVdwIsdnne!s+ z-O;_RfAb^XqpklUE&Vr)Paog?f3c+^#g5oIqX%O#AG4tCCqN{LKvV%}%Mxa*X_?bI9*U8O+wIzOMhy2~ZDgQl25cw+Tq0Sk=g*E({ zNRK69#6n+=8`TFAp@yTJnffze{pHFup7b!bF@&O2?c^yw)3#2r67UdzWh`DTFWL~3 zC&7tV+r+%owTEhQYcI@k=WcC>&G+`IoB$<(qe!iE)mD8*E>F>CHQliw_2#=}l)9>U`Z}&b@AOq+gg@=SN$>~6N zgXX-IE_Cg%QJ=%^wvL%5q_gtgZL0U=cfXXfGzud@t5B;oH-Yl64ft1U?N@pF#4rib z38#p8AFb_xpcW*=KkFfl>O*m($TDtr(z@v$fpi(;pzgok-2}z{4Gj9UUp^s@3310& zD|A+G7+D}+_a%3(zA|7>ggysd_+{ze)zh?@g|F7gGW#9+H}0?U>8{}y0(5uJkv-`| zdPnqI=(B-pPpLELJ(unf|E}@T_BfPjDn|iwk*$G6pp89QA zVJWPX@cCqH^dG4|mzv|zZrXUVC^`uuX1BMtU5T}?das)Qfp-IX<;M-~&MRq*-2FpL z(sn+A-wi(hSE9y;BN!e$G7ZCQ?^6lb9~sS7xi2A`cL6J@m6nery7XJlz~ zvs(>TG+AbZ3rLMi!@K;2d>&jzQ^YbX98G9o_Ckdz$cK4p`L$ZQyYhpKL`tx9k4=$Z#NYl#LZb0iM5n5Ls zl(lh*H`cr9=L3Gte`{Vr}zksbZp2$t5U(32(?PBOq6^>FYs<5<0+x1%j2O zpmUJ+@zrB-C6YVhHhXxwY4-#M>eo6TJE)^w!JsGJRvVSsKiB1#wAA}53Z+~*y{_SZ zI<0=fearkpmwoT=7th_>vM*7n1a*{b7B=bDl%}lZHZH>`h55GmEh}aBG(S+Cietup zl2?8wQ9Gr`=yUJk%$Ht$LmCGV>lZPiz(B2A)YQgI7R`yu5XrW=GS?~b4@`0sU~60bG&V56cDsh8W!h?hUD9z2g?<_s0R zG>kV0^y(B&lo<y1A-0+`Lr@&mad`wNvwmUC^3fNms%qBio>=lbYXo}8(&FVx z6t>pe;gQ-df}y60jUeXz_BE_BdcHCcTI|EuN7Nj31LuB`kinr{vcdP@e^2|E8MgqF zJfRct8(DjQ4T&Llw^2B4a5@}G{3w&u^tV8unk*v4oHI->s9N^V*zH+ z7Z0ZD`TkU*z(@2w#688R@WBL7de6ykpXJz69del zLk`|Ze29jwWwnnY&-$KvQyIm!&n|>+^gg&gD*d`iBN`QT){`=%-{1p5qImP2Ap9mK ziOFZ4YBvcW^f%lmw5=PPb>;=cgtR@+Tz%zd&NI4XaP?2rJKl)h0oy@9AAL$E_kxl6 z0^>!V#8)NnGdqR}`JEt1+F>0|!j|;Eu78i(x8UQ&b7zYx{E1wY;xq$ZqAUaI;Hlyh zACg_?v*!Dhvg56@n}cQ@l$uD6X`w{ab@J1KAq>+?_isq)UA!WX0b+CESJscF)mN(I zgV#Piuun=lRJw95#)P}3nB=`gZd&)G(J6gJ__IKU8y|daq`>Cw>-79^152~3=3M7?SWY% z-wXF#fP)ceDk7$(H^#jLL@%-Mwsv$YnX-N!0aGQVgG~vGX?MY zCU)@fkg(foEtkX%3BeKnyH^J$ytgljM>?kf*E_3Y;%G$b$&ySAW zOmAy67C0d>7yj*f8SOnRjoq@*n@P6UY~K(n3B_vb0?Lv-tbK9!jLi<9LBtGlqi6W+ z`|)dT6S6+6{^Z8sEQhtdDe3pPSHAK#8^8BDv&00SdcIJ&7`3uGzJ!`bpAYrf5nNm?qEy5JZV z{}m?jY~#kuu!DQ{8nK#{5cJdrDvFwc9wU~k8LP%MDpNIM()N979kan~|NW326+DGP zEy&Vi*73nO+D*>}UTk5nZ)N+s@@@8aB(+$#ya70xwz{HakV7^)I~Vw)V2PIv6g1+_ zAq?vrpBl@z7suaQ0aX$A${ng3<2LijTvJ?FQ4X733(W^h`8VQK9A{fPr70{AjG9>a z{=faL(7~7-_F)#A#-n|f0+Dlw7@5kUd>2sYK~M4!cHY;ACYtT#KM4ss=WZHlZ&elw zPLs*9`mN!)r}2QoG#(<8Z*ILB&_F*M&lYq)j(>El8vI3H|0*AV*XkQdyC7ojC3qk z5v(A56B0FpCB`A}($&vT1zsjx970CFI!wmGW6k|0W`3>}i5@tiCv3?Xn)d*ZU+}&w z(QkkPK&=Skkk5>67Sq;OvCFkDjHiHBC+m4o5A{v%0kY1I+BB7c0-e)qiB#MgpJlks z>Hi;qp}?haVbil8?6Wh+i;aCMcaoI@CvMi~ud$c31af*=?_bn!fZ89w3%DIN2w$rE zvMz5e&y8ERHryoc4qTrRp<$FF0ir)bJFVHg7LS%@t_n;JwCS<^W;mb0M=gJ2RJCj=hkgL)QHT8(;PK-B!`W9y zRoQfp($d`$hfa|W2|uBGn2q=fx_#;N+lcT13nS{f+=O94D0FgPIOF@zy=><>flE` zx_Z1ZfAqJxnvC`aPIoXMx%9gT?%K(hWTH)h!Jj+YZ97YJzR8XGEhn548B1%x0WfKg zn;g;R?hC!bez~2a1ph!lnpEn{%dajl|H$)ayr4Z8rc2IXW9$J|mn4REX^|cU5i`t- zgo|2RDd%bhV>=iGtA7PS{hBRsUI$4!-pf$y1a4L&!b(qNg8a&?@2FRZHhk8C<) zJFztw`J;|LeSKawl^pgwZ~E@wu!SSy`J`HLo5>3B{(z38{-k4JsxJbGuHC_WP3z|y z4cWD=BCB-mZybEE;JzGx!#Nl%L_vsb0_XMOEGmw1H}a~;&=A(eLX<_USYoYU3sFSK z?_kM1s+h%_>e?=0dFU}?E*&Fv%dQjlhh)|kigVx!>0T(6cHAO#%27vLR-(Iv+&uM3j)z6LKXPAMF4<=IF z_l<7Q%$EIdOYm!qt&769NU^ANWN@8i(hJ|Eb0CR#T-$9bRlBsM zsFo3of%h<`ESMhi*LR2~g54nGG{0T4>tc2)i~dXA!L(oT{T9s~F7B?)pQ;S)ih57* z6}vO~u8{qM$yy*kLtamFyL4;2sM8S2STBFi4M=slOSqXbzmz zGf7^2w3$F&oA~hcXOJt_=4=%PcyIhg^N#$h7QtnZb{=`kIP#Tw1TBTGA~n}tl8CN ze1D)<=+XzNmD(1_Y;x6XdFSV4IIei()Ho%sOD&8{+2(E-V{e08-w!AyddG%aGPXb5MgP@i3*xO@MdZ#d-0~Egw3Kh9C5LZga;BdO zkJyVU2_z=wew&N=*M>j)fcy4+3T*{$!+PAA&C)%tNRMHkgWC zXgo%wJlCBlw-;WY8x>Wh6Qcg`RdmN=7u3}ag-lR1J~FY+1R5INc}n6Q*BFlK|9GeF z{`?OK7&i5m6|BMSrcCWsSI+%dLX*T&@LeeY;VCr%EjEo474SMco=RnD&592lH=JAY z6{l>4;WJn6P=n&T{C9PIXXpF?en{?_nKbk4r;5(+80~6WIN5oeVqme|)kL(k66VI^ zhQSg5^G4^NcZ!7Ht%lp@y^&3|vE$}VtlsA4(>)KSM_GqR1sFfMLPuZME|QSJWRB@3 zWi%AAlUDgZ@T2#MeTXm)V;*80aDiLJ_)$>R++FiWw%NCD=bGdttQCLYcMwrZQRWhG zVvp$kO+2%X=QJF%2Xc}Be9cnwRz)7I|n~*-t1o5o5KJ(I?Hob|#2Bfp_FAWYwJ9l|U)G^p#klxZ=DO`rw zcRS(h%*tc&2-Yf<3sVZmsGT=B7H@^VN2F1y?-%gMU7>BIceIDm2}%hBeBT=Fxkguu9v*i5B5n>Y9?RGJ&J4 zVuC?nhFedeny}C_v@n^Xz}e;2cO1{ehvK9^U5S3@`CI(TT_EfMKWM^h*+tgW$Y^K&N&sL3I0mH@4#J;Qk?=pHsqpQtfz^U`{Ar(BTyxSE(}Q|iZm!~~0> z_6Pe449RVk3yGGAs^!0DdrGU9+*xv2M4jJ!f<=5KfP_&EH0Fs{(OX{0-_{iIDkBJT zd)^Z4w?3jAYk2fTE-pL(+Y?Z~88{{u>dORaH@33j{0WaoaF}LS37py-R@S_cD*BB_ z5cTtKxo02PeDuj0n<<&e4Ujw9Om`{*LB@}pF6{IN&JD~u2{&CLZMApK~V$R^7mAkuX6@bkHc;N(1KSAXYr=v%uA=c&a8ZM+q@ zLZ>3lH?e?#4jaBoTnG_)-9nh+qu^Y3kp78od>;EU*3?O+{9E@V0R%%$0|Qq_@7dnsO)SVc6mboiX$~cw|->9N&bcC7?L^6svp^6%)Wv zFQT=c4lj94C?#Z;QFU=#{Ab#WfzqlUGcxo~!j_UhfX^`sdupi`Oi?RqNEwShStjXf6q0)eD{48XMA7GI#B>tuQ?N33QJ3w#j z!@Ykd%a8P{ACFmagyyid*(hTeZqvg(<ZX)qmm=2m$DU2gn0@LR9}pxq z18LGetIdO-t_1ZpWpu^HDY()!LVwBIiG0@Q`_K*bFJXe}mY%2%ayk)p#tmt-FUo+6 zHVFuN%YVx2Ye&gm{^8`gE~HYPA?~NSe0nODBqE)A`&5k4(FZeHF%+}a zygn4j{iCmbyd-~71fPeJUsry9@WtRnEukvUz`Ez6lcC}?3urn1R}vmt_BE4|rL2pd z;z@qLzljGwUQ6WnuVfg~bxb?5m_C^?|4>Qhn*4-koM^BR#o{&XASis5v%yI$8?#te z|I@tQvwEPPGbzxoJ-Qu(hZ`#7;j2aisVCl1lUazb-il8^?agn&PyHoGAz?RXrOE9T zr+dO-2!&OQgKF(3qw}=Gy{33)F6}bae<+@@k%YLg`Nj3DW>g{Qxj{PM}bEX1cQe{UF z(^gk7uvxgS(hTxHAic&__{igKkP}46wN$PalIYN^I6%~1 zDnOV9-K87oVgOJ{q-M!ZD?cU%xM4IlXeM>Yz-x15u&Q7s&p~^yTgK%vpOnF!|y4#E?OmY&~ND;(3SorOfXQ(CxAt~ zcWur(^98&4F!Zcip$~Z1^fM>t-wOa8nimwn^;;lYEB@p(;pW=bfLoT2;T&tIL$u5l zOi0ODC*rRZEa*{Z3TJjppZNEWlLR|YvXi6f4;(dSQM>XPLt)LRp7Mh~1nDyXy}EQC zU%=%Z!ni` zE6A0z#s$;54g->4DPz;|xe1n2P#{o!x&>!l_7lU7y7T56n|af&Oy~*VBe_Qj58Eo| z>=h9RG~};SmKz`tuvsbTKdYS9MFWXgPMiYpL%bho7}u-7#4UR64CTz$nXL@QwgimL zsbMo;G{wivql@tEJYW}s008-|Q)KCv_c_m0sI>-b6V>@9-p(+Cx9LGY8Y9HRr|jLZ zY1;5l@`jty$5!Df9*@rD>D;xRu7EQxw{+M~-`LOxp z_`nb-C}0ff(jb&*)+WW{Frlby0v~8E+M#E^*#-PO_H_M8P`^o33n$jDmR$3M=nZX# zf<5GX0O3`MOnI-Z$1w5t#uVN7tq!;`wy1@W5*UbUtt#OiKj=%=xtLT`Q8(+cKH$LB z>ob(}?v~>gj_lS+6?k(~#I!y9dX~|Urp@KRdNjy}ZL=!q1u|D7Cd|9y$CQr%vc6<7 z_GfT)T5u=m6@xi4S!4`vl9${YRYB%Zt>DHmVZ2|8>cnQ=FznmHZB_B=8MYWoy?h`3UNxM&ed2F;K?uy+X)oa&Y}QOP7U1V zMr%x6TeMegCUy*IhqIH}Ijp?!e2BMGDV@dU^IHO;qnD9-%nAZlL3)Nyw5}0ZOA@J? zoo+9Zd||(i_Gq-GgZX!TUlrIIWq;tq9ofRr_ma(n%=dhK2At!G?uvRiyy1*70`w%n zU5hZegO6~?>IY&|VKOt)+wAZfVw1@$)qHL2o`QzshxZqOTJ}wB4qS+@WLtC|dt00$ z8oRMRn^9ZERgF}`c(LJ&3Ijs&dnc=+?WwM^+?l&Ayq^!UpZ5?P63><0i|zO@!Dj>M zV*=CJRJQoTI`L4;BrF0o^YX$HiX*NdnB_&j(?DAV zh_~FAdw*O7q$suddneI~xzy5Fut-n-tD};KXd(095&qLrbd6lD~@jY0^OW}t^9*-f$GT>{epuyi9Q%TXbmkE zh^r5rR$s0xvK`$G>!b}nA;&bQnR%xOlw||s1||Tspp`FW?`LgmY~?kERiz%Mw}#yO zj{ayUSvfc5~@)7%A7b z?mv7iUU1@L^UcNjHKg<~!X7dL7(Vb(JDE1M3eC#FtXoH&`sp#|YOX3dWw0>Xzh_bF zz)OD?1NWl`aalju)j8#?Rk*@KN{EJeA?yXdAmd}=aqyy`+qsExa$02hspLuki(<|oLhugOXSHW;YOf&eTl-CNqqjd5x^QLlbLA5EP{d=}! zQ%H%?0rl@Mq-%OuNv2vJEGJpQ_YKh>KTTJkf)E%Y9=km#Pp$MJvPiAYVvl`2Vg(rnHW|EzgEI)u{Nt zYuX-#lI*;bYaT#ev~INJOOD4Gyl(&uyXg)QBCsW9>df}-d2!@(Ap(WnFI|v*7NVX- zNKFNy0hmgg8hCzFm2-WXXA!rL{XrphTMv3dO1`l`27oyU3&)4RVqn1vbhGVzg{vQ2 zWoY65FO~XT@hh3 z%b)X}sd`EaR0tzD7jq-sNGVwbP{FFefZ#{<^nKo5-ljrvxCKFN8Fp(_vybCi@;+d~ zR!#qy!VHL^Q#6#sE7u&Wr-ZQ~2lnSY1>YhS8{3u!ll^&>$BV}1AUaga{?GHP>#iS- zJm;BM9QYK`efFbXj*WTJ|LV|?UrT;L4kf0z4|_j$*mywl!%=%nQDNe5xr~Pi0>@@x z;D1?wBGP&122c}wWXtRI_pL?Y*S0J1*~=HBW^Sm$H|^g6hm^B9NUD)>9uIoWfl-^H8H^v6EL0SI;TxOeHDxcZ+=oS!BI0 zVCe5P1X%e0j;PZJw+cgD!VS3W7u6+KVxmnoYUJ$g~hPMzc)R|o+LJP^hPY&d~`fbh{s z2O1d;m(Bqmpv|XIx9_yXEOH7@?hQB~T6n^jxN$M7-!^e7k$Nd>%nGlo8w;ZcvD|V%~}}g}07v1Vf!<3FTG{`O6QaS@%mJa$%#R zrS*z<+v6goCn1Px?zJ5@dkU?%R;)Zdy15;I0dc*w9d&WxTAdK%to3moomw9_eR)OQ zd9pZ}U3nNN4+R)^W&&v6Y(uCkmRN@)7N$33c^$>WY#(4T217O7pe^{S!2|)*5}Ld| zRd9^sE9Fe(&UTD|7M}3%=CPaNx&(2z_T~9!(D1(sBPMN&DbV6)x{89^?4R4yF1Vn# zIHR`bKY#W(T!@pJ6bNw-cE+FQ&&DVccp1M$Kya&1-fpKFIsB5q|5bC?`W-R=7t&H{ z%uP=V8_0>cNN)9!dok5@UN zU(4a!U^h+;rpl-IK=ujqle~x{gZFf}>?*Ur;p(^17pXEQZYE-4)MH4o?_iOQEjALWNyW4+0N|Y{elq zF`}*^i=>B|KT0@Vmj=HUKD5m=n)-ZRVx#I(wD!>l;ORZaib-A4Jl?kDA4mEK>m>I_ z>-TCNO_Es3QO!hk3f@lk$WOUyJ`klbWheUVozmW_p zAqGq2HeWM+VKRTAZ6irp4CL8>R{#qv&lc!I!WnK>pQoIirl_^c_S=YkR0xwqw_-h)Zj`&#e{L+ktcA?l7l;Yohxj?H>4ObR)KkWKTm}o^>kiAs} zEQ(Xssy$Ihi$o1lYNLnhGUFQ`{geufXaxv64m`D{Ps&Jxp*O|&*~X9jttYUA`xBDaKr!X?vrPD2slSBDAWip) z(~}83x!@<6czQ+4jyhEgi=R{5uY%(9L>09EOhdVf{sHT#*leoif%hh?_lM<;!}~IH zMJi>+`r-!TA18o!Zzb*Jd_>_H-FxxSPFmqs`&@8U8GE%CG0jYppy=^qtiP4r0cZk% z6#sv+3w@be`I|=oZEiUxFd6D&D()gKg<)yn51sD== zG(slAetzQS+)Gy2^^nLaIVbxQhB-JI0aA%M->iSuvKAc-;>>Mqg~OFM^@JM4^xoHu zF>1ik`8{8jDfZ%BO;99m#b}S*tM06|XzgI|e3;k2vJ3$~McW#Kkr@H+O>CdzW>cC-zXH^(nOMvqfpCiuxinFQ=z9X~}F zoK>-94fwIOzE?eOYm>a%3t>PHbOxr(WS0@@=tCspJvt8>Bwy}#J^#@DV(uc=Nckgh z_<~7gr=*;evvyZC=Vfj{xaZl_D#Q5OMLx8&f<}FnS1wv(ux1_-Q6*lJT7p02nCu4j?YtIA44rKh`xLH^bu}8$6>`k(F!4p_si8)J{FK@xBd~aO@)mat3JZ!lZ;~isfWIOTEl2v~Fg<3SqqAAdd zE{~uQ2%J9h*-uBG!}Kwwb-I$#FTEKH>ok-~>fZNY<9Y}4?U!`~Z)x9B*J84rjI0lb^iAN4JW?Omi9<5T=-3R`z1rnT(@|%E zXE@{+SVIX9N$(K9bv%IW-r7Fk(Rt+^JL@}4zZh8CO)l#Ti`vK@x|w{@6p9ON$8|fr*ls2&-^aPrV8$0Ou+1df`-Pzi>`OxajZh`FSv}y ztO4ma(D%pq_FI|>D^}lZ+U3sx#}lyDwbH*0bEJh03nQxJ8szEgRk?Lvg|MLXJ_HDM z{?9w*!~8@y`e;LtM%}TJngZ|}&7&~J9W}D#|Y~RUkOCuPL zdt(FbrJ~$*{ADwYsPqtS-qdY&ky!JxegguGQAm^xsz=g4FDUEiJ@OKji$ zD5dua{MxGr$<%~FW4~{^0hYYTxsl?K&W~ohOWPMV*;SJdsMeH2O3o$kla>L@#dkvD3>hROhvStM=QnyvP!qvTQEyd8Al zEaF=kT-{aF+&I5YM5(HMF)8###&pqV)$CmeH(l;6DIiI6Z?VXywF|k$BY!pz`0OxX zxb;}3tb{yo_8Q3|KZOhbt;0~z4~!;U8MH#Yctfh32)=zJhdR!EpHj9b$K`{Tk+Ui= ziwdR@B<3wDo*lpz3o@O&xpu;v^>~Q1$F^Um9n`mb#xL2IWPJ?|#DgicxY_L~l|l1> zeYc_OaZ0GESc3RxuwcA@%UUljNZ`n0N%?#@UzcC|C*MHM-eq8JS!Q8RAG-~B9q@cb z|5!f$Od@H24|w{|Y}WC%09sHb|=X z3wF8M(B`2caROnC+}TOwRY=IAN|?95=l>`8$+e>d9%zf}J2i}O!_(#d>_8tqm9ud= zo}ga56lF&a_&xtW!4LEL>%W?x$=oSoMO|5*9x^a4QQ)ad8{9P)QW6c>6Cvkrt={PO zvUj;QPq^^dG-)tcb2NTj-ER^E)Q|DGt}TZUOT zzn71hG{^dSuh4A)0UUWKZi~ zkWpo8&O{q@p<4|EdmG-PzKUeGhkJg7bbB}Fj(_5?H3g>~)?WN+-Wy4Wx(fU|@#q((S&8ieRhRm0~5zl93hm_!5{$?%6 zwF(P@sO~zn-0HSKb4L@_yadBon1D6{4`1UDotq{4Lo*lf5NixUIBfaf>238`o# zz~_m}!pF4t1WAU)zHkP#V(Skxekfwo3(D z5GLvtn`vw3-0!5(Hn_#y4O$y`=YKjVNRoO}H&eOVFjyEJ>nzdzrV<(hGI zKYX^$Z*Es+MH}R4gApfg%PQ%Dc@%c`dp=vtGkt;EUV|ycdhI9Q90<1^!;2vP{>xRK ze|ThmVCeP^y-hYhjkgn7>jmoPMFrsDLiqE4w(!~8lBaZ$T7Ges%9bl1mYf}Q!~%YA z;Yqm`Qg`TP*<6#YdnwcfpC!t2Kjkabs70aKxltH`t4el0Zvnb< z?y~{q<1Y1lt$4iR@OHR0U7?eaVt4H`XU7ufr!4ef3g6s9{kjr4KakS%Ebz>2#`K+h z9Mk^@hgJ#|>xpV*5UPhl2%Ircg+{oCQ5*XQ%Lp}oFe`leq4#pClryC<*@Fj>{THA6 zMSj;+JxF;l(AVz9Q-A^`>-!ayoIBMfT2)LesPl|L&^(047RZ?4md*qX4h9S}`L^R{ z$bNgejlSl6xEOVkBeWN;q91jCM;VGdSh~j_BA-Z%G;}daKou;TfTT&#;JijqyMz=I zT0;R7W#ONgi{fOrzywziwNNSa)ncZ3^+8?btQ+EsoH0X0pn>F9!8Xxn8V2VeQpAT# zdMlX~fgP(&_FCGjMBIQF>1@=Q#xi~6*;R_ND2MN zd)Eq3cY`bDJG1V0!peD4NxtshUFyzW>cRgi2He;ABJ>*kZPbNBs+xBmW`3y6A9Xi4 zZW^5#D_%ab*XsZaE!cC?-q7|L#Z6IeML|zmOV0~%Z0EWLL-SL-a(JNA4F9!z(Po+r zb{dvaS#Z=B(6bf246&e@)4t#HOCCNx|LHk1CZBn(X|3)NwnXHG44&U0VM)v+BTT2h zb3Kj4E4wdElC=G(wxQv&|BBX-R`~hv`5YD#4`Z&?7fv$Di`o#CU~Xoo!oc&z2(;$u5e@sb5=I|b}XS!(1e;EAwdX;ar}-sFA%t(c1hOLrfqE@BlY348oUuf>rICv?E` zq1(qvz+)h1o`ghY{bA-1C?cogMz)(k1Z$yjzy5t;VccY#@m2zbYDQiwm$TmYJAMF_p+N~va3y0WQJrxX2BLsl^YbtV8P-i+T< z`OWXK+C^rn&^}KtT835?)`Rkp!YCtteqFC!m;L41FpST2P8J#pKGkrZBHV1n|NQZ~ zyC|~X6O`33rp5pbM6QVwcG*ltyH?4eD~2CdkscnRcOq_Ksk5)lvAGg* z8CmRn)=I@k=^wETmZ_dh zAt!1dtsHFoy8!79x9A12WVe-J^>-x-#DV)dgp27NbV}@1>c-bCYz+!{(Xd1i z($A_V77p`p>H_op*ZF$7)XALi3GLGRNiodM7t=aQ5=w>k7=uFB!74I{dNXZ6X)N<6 z!>{HB<3G6~5fF_FG~xE9+@zX+$3~Rc7h*(n`T)@26G?Pti{XUATE>*vX`696(Ki>- zu)uy$W2zTp`TKeg@J9W=T)tsx#J)B7Gx}OAw26ou%Zco8JoCtYGA_cOS^#*8f|+y) zmQ{$b{=eh1zf~JrC`ME)N^9cW4yVgvl%SY}m0mb?c8y5T*dX=dSVcz34jGv--%ehC4(e zRsFRU@t=!mAa)Vo+rPN_GDtJ-3EmA{e)d9@IyHt8&%33ExDmEh3x+Vi4UKWViSHad z4xgzo2jK2N2R$Qod=2pa4hA3GOZpxbk{+EWf$WrI6B#;s;`?r5=!Vv9!6WxKuV7fo zX;`$a1(YP5bXW;a(zgU2>z9rE4ql}EtUSjH>t!;^Y)t1B z3xf#M<~VUXpHFR6@15cm%I+jyLf4-nvYK%&UnB0#+@7XA1=Q&E6Z&&HcUU|Jq2jfo zkgs=$qaR?d(BZ}-&A!@Ez3_Vth7*hs?4)Pz@JgET=@>pVei_<_K5JhhLv^p8`#&h@ z*`Sw=u)%}w<8b=kxn6IV2V3fVRw5dv(OnfWnp7|~+=ik@t`uG;`~c2KI&|v$ipC{N z3-}0|guR{P7=@RU9F-MBUa8WrkV-lY0WJDwPW%JqJ@K1}_gZ}Y`d+DaoPN13k{&E~ z#4VZ}No3q$LTRAKx5jIJTq1`$Ac~W=dk!kt^1GUKhMM-h=d_pID03 zW`L{LiBy|#_7f-L6VyCUN58>}vvqwtud@R{8jH>yyL@%=0-xH@dHCkNFmnk|BT}zD zmmMztVGA7=4S*ydGVR8yjk1%{8r&zv%1;`;jU#g^)m|Zu;olO>?F1=1``N8 zHTp)hm!Wn52D0hp1qpJmLj4#;5k8V2aiF`GtGqfNkj5f)=1c{&f!|@dfNiwzLeR>(?vkQ6BJ5tj~lYB92pn^_ilIj}AX! zKtf4n(BU9qa~BhD2Q{{`3^Z1b(UB_j9+}NRP;&`~0mOBKT?{ec_s45d#7d+^wOydD zUEIm6qrriD)55&<+}5kA5%8Bc*fmm0pP?n!(Aa$=9L(3%Lpb0A#q*F`zr$Pl?wUXW zHr+=T@O_c`&bcCE1oMB= zG=fV4(U3ICeTs}Ldv9>05d9@>?;1>e^sAij*zPR8?ZD<*n)v?dhe^yquhY9d(vEaR ztPspcLo{Sgd7MTc0^0NLX)1r2$Tu^~Jq-m)G!)mmh7-@fj7dHZTbS;~PUT7b3AArj zh$vr?eenH4mH2TImPstCOh2-9!?^mSoT_WT(Q0ezy*teG_A#Oe`_ya8wg_8><@YjA zu&U~kvaE=z8O^Y}h}T|I!1h>>Em>Ae44mZ@@2Ev`r-hds=2*N-e~;O=sW2jp=K#MNXd~H2vp{ zu`?0;W~+!36hiCOr}jxK6=%{dIVe4K5Y{r8h|&7+7|4*Yes##S^bS+~74-@d>`yOz z8#?izLh)tBt*<})*M{+a?TY>+n+=y+77mxK+SrrmC{8S62K32}M@-imYGFc7d~PtH zXWC}+yr#>K9DMSjrYsXu-L8BAXOqM-1;5b>dC_3`UQjJ+=w6QZ-Mn~^(r@;Qs0zdM{}43^ui&BL{)`96GBw#D zmWBa?j@R~IqQX;k55^t9(?3lT8;W{0)w#<|1^ZdPUl$Y@L;jN+)y@}8)L)*~i3*5B z{591M9~5)u%xw2qwx^w%^n{`v1JOs>cujiX4hgAzim+hA4m*G5)sgEHqp$t^p_?6u zfy4pIL(ll9n{xo`$FcQdD!kfWa9sLI0eNGZ0{L3jh8Xi%*K8FHNAkx_c(73Luy-@t zDc&N>2_H5d8d!J>vWmvLi86np;WL)0KN~UyTgG27Ey=R#DbhL`hgw9;u&6gn43d9& z$Y|uuR#buMy8_l@4~9f{u*UB9auXu6Tv&3OxeiA4g2 zU)LQ$O-pYV`*ZzV<*akiCZlSCGS`HDD>Nc91h=N^Hpe$~PyU1*OoKiTXRQ zCzlA~wrU8q@bdgyjFMCeuw4G)U4>WA=;pII&R0<*rAP_zgY)ilPn`R5>f{peoRs8n z4z^O8q zYv=^XZ7c`zx`GMt%jbGioQjxzh)4c8g4qE<+Eq|@$)!{jsalBY=sRdTBwAwVVs@C6%FM|gZSDk+@LT8IfKwMKg?Wjw1s zeHBsuYWd*e)`AHvyD;MS@k6k4nu&Xt5=ihqBB^o*-g|QBStd)jU+|9*G%#2YBRuq4 zLqk%FM?i)(c5Yhu#9^(Z*709^0l3ogGNiOUL#EjXiIxJc1)@?XUOE~K8-bGiIZD)& zX~JFL4^aVCUlB`fid|JqBCmzzgQcDls_O`ru@k7Lq~*1maXUBWO@SeU#k{xvV92EB zrtT=YH_zK#_S{`&b zJ^O__NmwWukjKOFH3rEr{()*kdzQ2U<0iQe4M~ed8K@jCb@~#IF(Rugoun|ZBaA%mwuXkJ4|DB@ zZXP_&lj{4PCI_1Wtl4g*+xBteuU_UX8pL0}2HEddV0W`mhgYr`B97Sb{FIo zyyxzRrF^akIl)4SYz`80>`Dgc8|6pOfGjMUq;+502s9ExY8$4n#Y+nDpKMmeN-WBh zBulZf{oKLXHRPV^WUyLWuI%U=A7;k!;toY+%WBC9dGaU>bs2g+njmr+1`m0o1ChIs z&Y6IvMmE~aB=c0i*2_jddarZfb!$Q~M0LR~*DxZ9gP0@#O^eykEede=RuP1zx;t=FvVS>aeZX)!T`qWIZX$} z^UA0SdQ!P-Em)JNP7)hV=pv(D9m(?~BuT1W{h$9>j17{loF7wKPo*J-IO+N1M;y55;?>yiIr2n7vuSJ6ZCXh80% zv|Vda^Zsz^5bXNfY!2&sP0Y`aPglgaA<6(=*j7#TITl4&e;VykaC10x^{nu7tE5Iz zJ0zHsh{RXJw%}}?dn;sl8cF2x-UL|-15VQ9(JO!R7t-BS$Wv-O-m@!5s34@A&Ig+)cm;p0q>tDr&;K!6oGxQw(mqyH52qbS5h)w#qi%l_lD z_N>xC!9}lU^=ImdV342@H>Q!m!~k^tMO|l`^4Dk4BK3BZq3WnRSMSSDe;<)2b}36#=;O^?v~*s!z}9l;0RKHjtNPDQP;s!B-mW3f4tAr31cErcl$YC%K8 z1ZSKqp_B=)qSl?&eLz_@9vd*$y}ce)aU*$8qn`;W3&jiiGZtXhQp5vc; zf}JlO_g_S=SG? z&DX_qKxCV}vx4kB)`D>g+ldkwD+<;d(qb4+TGl zZR;l`XADx~a)MxmNm8h{jrtv0{!=iZ#}(!vb}f#MlgnZFjgt!dE5_@lZVb$Z+8UBsDZ@Hb+uOmeLvZ$ys|K-l0OC8(T1BElVRb$A?L^^ zk}(SW*IEI)%#sbOQC%=vYdh6?tXvrT0TrSz%#lf+~~~lK%2b z=(6+pd^l4Dq1>^GT)uFV^KNdKL}*HGR|y@OQm9pgo`Z*hBllKKrD;+ky!(t)9D4`b zJi}i$CdD9v7IvR>4Y8dB<}qB^TD1K8`|MUQT_|<29U>7SC0&&NV4gb}*tRS;`Cumx zt?KdQP7#--yv(mFDYJ1O2|V}DiJ?|~_4>$h<(gCOA%q<3a-nV$dVEkxNH8Ea{4Lrx zcIR)+ZfzmyeU8DEaHp=I!CooP*78MfovY^n;^yjKpGVx8$2q8{kw;+N=;gV9T!~jc zRox}H~E zYB&)~lB=Uvv53tFb|mO~4RGy>OG~p6dKC%ps9~OYt>Q?zETBKQghTu>}GT; zn0Y#)Q8WWR%^gWhWzTM@DnLR3OC@(Z*wUSJOj9#I04gPCc!ji*aif2J*ILr@eVFg3 z$FFy6$;FW14>(aOa7_Jy(mDVA@69ATbK9s|FWwtw<0ze6{vOO2aBK&1&Hqw@ zm>{T_Oak%dY7!N3xD1HwQQ0A9H9yYf>PC4!(gy^RW3v3yj1l@@cqv|HeZs1v^?J;X zq-H~nFtbE|sHTIyVPTlXSr$;n1x zm@x-$aJ(ThqfTfm1uXf9x&9HkSaI}ccmG!&j8ij2*5vh$7lin07Pzzsc+kH{&fD}4 z$)PJP-#&<@+kFwH(ZAhY{?)|qo1WYQ3wkgv{HynOYg(FiPk*D}vl|Y*^|7UKX zypsR43fK4TH(}Qb?RTX z0ID}(+E1Hh{W&CEa%>CArs}rd8{eL%h_Q)Bu!FGY*+XLRH5m+4?lQQPBY5i-^?b=g zV^(A#aDsT*Slc!Ce~5eQu&kEvffrsn1Zn9;I+X5~?w0OWI;D|Nx>H&}Qo6fAq*EFM z38kdrzAxa>d(PwY<#!&>z5Cz2XV1)M)>^ao%vx(AT7!B5f|&WqLH9u)AwA!y56d0H z$RoC7SHU4f+qt8_aDK)@gB$vwYc+X2DVim#^$ieUT{~5pe7?1|r8mm9GIFl7Bm1*^ zM1-OSnT(z-FYrsezf=aXTo8(m1w-1i7}+A>S~aE%0{=N%U7p~&)709-*`a)A{Dhg& zG)nOGso@Yj6Y=tR(SafGD{E8+Iwgc?1gcN+ETyXaF}c5g!^X$CEzepqtjkfH=NQ+v z5Y%+grD!fC2L|pm3kJYj7-M}&5wuaE`3jk^+qG7SPecbx!F@wOlvs9>GYMw<5bvGN zn4^m9KPhf|_txm3xaKd4qkEM3 z5wb@@9)4q%eLKjmn!PsBFo17FO)Yrxe}@NpFR0hxZYE!M^6_*&Qagcf)L zVOK@0OAk&LgLbAWq#L{8fHl|02rvP`gCWgIuFf{myP^R#4s_j0%^&T!aMxY1U!!?p zx%zUN)o>uHFC11o`S9#XVYQWW0Z$2LhG*aLTv*Ldso`NF;AizKu!Ju8u13Ka3J?@j zBXk5a8j z-Ln|DFbxF0R_T$M9h*3VYYJ3QzHAS=Bp(gImfHR23RQgi6OHE=#ERfA2>3P0k9b+u z4xZyhyl?qMq25@1T30Hvyb?HbT<*Ac^~A9YJ57xM{T&YjcgAS?f;$M!?P5~>;4u=7 z!v=|w=u5?T421PV2c+6f#^xLz#q!}m174sv9E7QnGqVtagxE#s>W0F75xX1Pk=uYq1d%P+LU~#kO5T(qfaJbwq21K}&~mMZ54K zljotPyWSwaoo37dT4|PMLbdOc9He#vaoCuk67;_d@aT)kF?2ARWU>N(0YZBk321mu z?2*6^!}iXV?u`}fk_B(MNI>I!+IQgSxhon_<3QJcp;3XWcfo#*hM)9uJ_ojMM;KvV zVQf_0N8Z3@2bk98kv+^?5?$D!WKa`t#U^m8fsq72?aeYf*jU0xX@Qz58o7r|CSEuy z4sXT1ivu8fNE)QsWi6Z{4~vEuWcv8>EP9T-N!xPOfi3O5;fp~VptVVTjY+{9I=Kj? zq&4M$pMcr+dG3lCx^dTRK`diaBR~CGrGA}9PD;C27D`Xl8R&9CxGC?6;GS}Pyb=3f z=>5@I4D{Y>Hm`FYx{!`=Gq!f?W!G3ByfD6eWoR~`*W=ronpT4}#14A!#t;kmk(oA& z=dN(GmeOknpwTdsjnH1$y9h@CDaD=F zKlc{&;H}v7GVFv+a}!y;&2FYuPaTD8SLCEO@6$dv8DvVuf>)LV2E~;CYEv`7&C|^! z*k82u-xmek-y+I6bxY61bC8c9{d8A0ph`j4f1y&pPEx<;el0fLZ2?AO;2HG0r1G|; z4)7vup;^Wk?e-eh5zyQ-#|!D8Cf=43!?qnz^O&CZGo;R|!l zL=VNoPtwo*5f|(e39(gL9U%RU&j0gC>Q`+o%^sch4#$rQn*G3k|I$`HpPIM*mq{va zzizW0@M_ze*#?^bLg26pyDh}`p<);-)?yPnyR zUSgumxcG8l#N=h8mk9R4ra z{85GZRbBrFn-U3a+$wXf6^=!ci4N~j$zqeQ)5$EERV8|nBQjWay}z(2*vJ~-mR7e{ zBZLYXq~%Qq^9(>z5+9aXWRPBi3Mg!zYjkX%GTw~T0fP4AO8@QJ(jjOG`uemM- z%?W7l@g?>}ZRa04&LdL^x0Rc4G@1so0pNE4Mw&kqJGe|a_&=SN;mFif2frWV1!JXJ zY_*VW`HxvD&A>!vDIyqN#XEclb$F9Uv|HfzZ|4^_|II8#k4j3RIrtWZ+Dr|9(c&%X z2T3c~-s$lEvyZMW`P28VeXVZHjs2Bc-x1Ce|o60+Z&)X^4G?PTQS5A7BTDLTQg(DwDHL4}%%-z%1xEC^^RdVnU;@!h#9XP5Aurh7C z*wd@HA)=*WAJCGR0(AqeBl}UCD0>AV23$puw{QN&M6AZyiQJNT~U%xL{Qomf;1nX>Km z=v5u(G_+JGXA`ih#fgG_3`S}ZHk?9L*3ptHfn>w(d-tv3LIkvx*d@vMjw4((QL}*{IKak^@DI--$uwom|;5D6qA(CL5pzP=K0On zg!OfP?j=^Jh_^%sq6N+DR!Dkh3qK@R8Uos8cjLbpgMT_CoqS{jKW0Fq_z`Qmy}*Ry zM-U2X3fAaIkvo2w;Uy6#TvY}PHG@pp2)S5?x)mVI(eH!~r|5YPrI~d07;T`qGarZa1Kz&A=r5$vBMtM0II@@%C=# z&yE8mg>?PYH7_DEJ|WuZ&b*>W6Cz-Zc_C!MV7j2Q=H374N5|i-RBL+pO`il9YZ2%| z*deigC>#ZKTv?{TAB(9CQ6s@{HvSQuv_n-U1QJ2<>V4sJRBZGd0+2$2M0=v-WzP3? zbNLT5vExnOZPh>Wa#&o0D+&J#i>y6t@V(W2 zY}|WAjNoJGcq)BxZuWCObQ+$t%iHUjvkb)+>?8!#C$omd(d3gC2Oi|B$YRu3g@ZsB zf`Sbh%ugY$%s3u%ONNEpD z@$R>lfYJ!~D0?#QZN1y&Kf~na`c8|tu#wZ;4!86pFc}QQRJzUDY{T>PMw#vN}9 z!og0-wfaDWFCh={8OPjVei@_ZC+qbU&*S!$#NcG3R@@P7G1$0LhWA#RaZe1RVJ3`! zn2$>`mLspC`=)h)W-Pv>-Ay~P%A_F1vc2ik8S}!!Rcm@`^0kmFMx$^$^M6(UF-CCtkEzB?sORJZ?zfzm(>qI+ zg+x~h9(6?^TG#6vn`Quy1R_jCGvrPJA^+fYZ;7Nq_?6igDbK#==|uz1so&h zQF5;+qtjgTetcR7NS0V#4eEI?-DCa79Bpn}L=eI^V?-z1&$_EDM9pX%^-^UxjEpSA zS6{|i@rzB9&W1T;Tof=|)@pbFo+19!F$3i?mu)3`4IWpo)C*eh^IUxEhtSqY;233! z@+V8?>P~Ejy5D~UeQ5fQ1>ynhaL)_wBpehwci-y_khgPNT4Lu$@{x9qOl*DELs;}Y zv&RSLOPxlKtFX5%alhEL{TQPvl+G7k!6;J=7*wPTmXWcG^{Ies#;y=Q-7O~kD44BJ z;A=$=#Pnx<9Y)lAoq-8v;6(n?lmXq-DXo)wvGTxe*uupVEXOy3Ot(h*-dmD2MIyJ;IL~6W2Zosy_ft5*y_hUMn+;oS zf63%XZMLU7#6#{>9Y5nq%$P9iMIa zOSoPqCCEhaC}O{XM)S_d2nq(DSF{UAz1<@QP3odp-stJG6XV{rw%}41qvO*P?7${z$<#3bKx zJs0IB&=IJHYe$f2oOS0G6-;FzWsQzD;vAV1KX%JIhAKQTW|?MC)M8>%0Zd~owO_{z zl(zAGY#MMxeM2CCE<(-su}O;`kso-Hj6K_>DRg!BL>ENCY#ChAto|&dt_uVK^(vY; z>L4Z#Z~B2(Rpf9Z8;(eEK2{&HezFu1Y7JW8ZTR-*7=n%s6OTiiE%C{UBI@dl_cU&J zaI^QIrkcB>3Os;ra<0W`{QZDovjASd=6`cvbNLS13m? zVVfCYmCf6nW1;I}Tp#pM#Laf8QVSXES?6(?wpi<7dm4P4a=rxXM_G zRq5*cuD)5WL{k2R<61qlcG+#X%rDtbu{`+3J=eCj{K1WnkQBt`m)I1Ek01WrH8zuK zHrUTP*y4u}i91zKwemVn0Vdc4$;CBld6MVY!C#erQmJlHWfOF>aFQAOjEqp6NQyJ4-Dt zwus)h^Eas9?P_{9u2K|tR9{0_}7M2ovJj$V`Y{n z6B%I@f(RntfcsRLFc8R*6>wiIiA&@~175Z-8cur-qC{(>%x~Xl1;_vdT(n<(7Dw=U zAuVNYZr5%Z*lLFy)}2O1Ch+)jwOA0qn_p8g zx>EB|Gb3a%e6w0sKRj6!rI==((a+o~^(=iCroF)VfeRC3^)T{a;@zvA%|1`-_YZPj z8Cj8^qpYSk7bQ7$f`Wbj4Voh`z{^Y7l+Sw>MftAZ#r}z=z_7gTOK(U)b7J%AAQuuV z5KT1<1ap+k_Dsj$(PXUN84WcxHjL`i?~C7i(T?yw*-?Jl-VVXorEV@vXXYVj`SMG+ z5uHNjSCgesyqv@+Ki2ye)hoQI53pu}DKqHK>Q&FWPk^aRc)a>A5Z6EY`06W19t^U@ zA!jWRG2sjkCLv{V2hD)Op#BY-Q!oIlG()>no6q^=tfj+0(Xg*~xYM{JOQ(?aFn>c* ztkmqa<%fY_h38q_nfN;zqfd86^V($<`BY>Toz77Jx0eil+C$S|g^lGEIVI9}oGvxT zhd-sp;ep}yjGeK;E*OTe#%1{4rWu|w!lQ1t!?jZuzho=mi4r!SV4U-K6_|S(a26K~ z4E@lX?YJHv#2B9zB4fjjj(gk{4Z`SMnh(;tTa~*21Axy%9Ls_+Yh(G_<^B^M))&*u z)6POQZQO5?Xt3scKzQ0P5Td63U$OfC4iEI+Yh!~Wvoo@a|9r-&MLHBciPye8`~y=7 zs#;#MPF=WEH-HTE;H|M~?XgbCu%4i7eBEH0R~f;#|D_gVSSBn(67F!7;Pql6Fik9k zi1F95s-SpfUm@T3ts8J)YPfh3L zXs6Uad+wwv?-Qvjny2r2)s+E1UIFZRBMgKvW;-}N*x!3z+Itu7*KC$|!wBN<&D$kG zKEMffNjqwBW#}Tsx$lrEo_j7POMx3tJR^3B)5fMYB0rcx zcXLeZyicQf1Dumz*=O?zwwC*^J!0AXDzMwbc;d16&_~ABh?|B%tBClH(@~_TTp_>a zIVye2;Dg7~5z;<`#O30I5s%NX{49@FF~8nUM;|>vt-Joxc-pjLY)q$8>n72&hU{Kg zZwO@@)IC9ZeH&zQBlj!p6r|KsKU$4!?~sq4b-dYI`o-jqL{KN?9to(a96IcXED$$~ zf67gbbkA+s%dUgMfBOgmRL`x1Oy*j=5;`)aE>MYhs-#UF;Az*gLxN=x=49SDqZN(! z28W`RnOuN&DKF_1a}dE#5+Zxz^W98D*DqQe(N|?&H|+;? z@xPd`K<~YlkextMM@Oa2HPnh{lXIshr7T&-xXE2ZzOfTL8P!V{*FUzmY`(K#!NGm> zg=b{n$#O+t^^A&~j(Cm!+Ra%HzMgeZ9Jq?i$3>(pgVED%Xw8ciA@hMxN(`Gz3k8`Y zM}t5kjK~<`u53W916{X0|D*F!w#r?&U$c2(D58736RjL!cycWMS&4`x*paS=^dKd# z`DKAeh^ZCmp_{213GFEw0maT|#qw8GLW3={xwOz2L;_2?T@xXBF&T3Rz}zW=18Z;< z=zI_hBa+^w{IrqL4(o5os-h+u)xfH@+kn4vcM}^^nY%Rq7kGbk#sa8+dal?e%O~@{9hB!f8W`**)Lp@I8}*saYC@lfaNd;-sCA(0 zznE^2MDD`xTH-B2J z#mh%9HjE>c+OA*=(mAgELT>B2W!aCmj&@oT26|c z=TA=5#XeH0NP8~~S&!V)NQAzgMjpleWRD@efLi)7fwkyFC4-dobqlI>RpmdXkv%ZL zvoE{k3Qr}ag)Kzu|M@AhdVFv4gO=c!SjeI;M5Ej^@Z-J!1_I*Tk2og%@1G)np-B)E z;n%H!u#S-S4(N?I!D;B!v<%$nbneHnkzs;YxK0FfEAuC1Rrl-25YJ3qtnmm^nO;48 z-S1bF=j5#bnaC-RS_2FNRp%IV2v;V{-2EU`z(BGcfizBsgMYx*5U!`~flvR*{H|tS~y@O}#5&#=r1>6PuwMG#Jn?X7{4lW*Gz;o^hMH8^A;vFy^Qg?DtOGCZO;;H_{REF5TPX}9X z5Snl5V?b||6e6-4Yx`m$OTUQUa#TuyYz81A>Nj8znDl@eS1)iAdirFti+zWx(wS+I zDc{ZLa_J1TjB_WIx*_uyn=>%L)N^&Ny$KIOh<*kBf3lI4=ZPS0p{<4rdh*oXtxp`t zMg#_eY9S%zap>QLBHr`PY@&Rz3dm~IaUa*G&Iiz|?6X^}Mxa&@XT$aA2_K2Cy3`%&ew@JISk7U-rL~{uSXksi~4?eF(&gDe(_$Qk394UHV5-@M=?che)(6SUD z8Z{UQ$x?hQ@{zxz;dQ(-8j~{6vapy)p+BE^pdA~_d(OktU!zfF?6(G zugTkSFipCEqy9y5R+=Y;_eNPR`8~^2K&tXHwZ}m$3YcQ`v%{ywc4p5vQ1!yVR!~_d z_92lUbval8MhXE$((-F8iQn2pOLk%x?rXjc38nb@(G2dXp zfRu6oBWaNb8*?C=5AlkLZjTJVzqZoPP_?~bUI=1t3*EzLpLtb0yZy~=NNx#sFjtIkTw)3{OmabS%#mAu&Rt&bI`2u8* ze#*i-(ndF$80WqZ)Jiba1Z*5~rx~wu%Jx;O+akrGBu+H}L`YPFALAlgEz7OOIKi7V{NIZyIL;d5F&5xDi0=P{rcRKVj|05NbrjZ zFw!Bw!M)}rHWW5-m`usRr>z%7+sv|@&>J!^P!BDG5%ESAs_Rl(Jz80@z9jg?_EPSd z4)vBwHki7ePQ-KSf-y}KZb4!>!SnJBi>e4Q zK<{P8o|tRMQlBywiRjRG#U5%I&XS zT+q5JHI}Yj_%x43sZOj5vxytLr3@$o6O$lIZ zoC3b?CWvPoc4!lujIAM9d3j?I$$-sf00I~*Jx_>q{RHq!InCIG1G=j~>6@owTyl0? z$>v(vNrwAJ)kD+x;W_m!`u#Qi~ux+L8aKD&_)u8M@kD-0Tj1ER-iSXdT{}SF4PC3 zY*d8GjZivupR?Wp*L*5+Znk-WZ-8@0mK?%jBC=|xOz$TC(oC3ZXdggF7kga==nbFm zM|_kCe<9g($zD6``*F4O$|WSQfdBe4{)R&GCG=M4K+ToKd&NSgKD>din9XWGGXm^> zWd|$IMuKWF6uzpKxCkV-s6&C-ki&kQ^CS^VwiXq5igR|4(sO;$B*;&keAyL>VOERn z-+A@CRiQR{kT#tkzP=52%Nkj>%0Um3*OC8HVW^+_q$iAK@ik>@Bz6ZSD;D}EJK(Zp zk(3CkpnYF6vCzvj1`7m5_mZjpFWG0vY9Z?+Yklz7F}4#bhumI&T?FCh)ii^Frgf^a6nIQGX7Mxchr)7LaMis^7NdHmUDl}L0j&#<)$Z2-rgb}R zyPsm~INr|hG*yz4Ko$1{%Hr(sLNJ<}ZVp?QCP|pR2AFk74>gZtRa#ikLD(>O#zAydZmFY0_1*kd9qW) z5NxNWl5T#Ukp~@7L!{Z-n7JQzHiKJw0@Zc!hDIGoGH|oV29A z-PnwXhbKE-NjJdf97c|%SoEX!r6RntB=;t>u>o%cn4mwzQ3}g*Y(WE93BedN1z74lbdO^#cPWZ_yIp~re z#ESHtwW$IKf|qftWsA9@RKPG*Mb2_k5grZw7lii5Di}n=Z&dRga)QZeS3^ve-@tQU z_kPFpYW!@7r_7;kUyj*x#grbklFh}yD8gR?|GxdEXaq3?#c{ea^w`dU#(_%27diyb z=S^S4axTM1F`o!0VB_U{0_G1&p7x4IOf48u`QDi2a>?uHbgH;pwTri^-CO;XL?RT_ z`|ChYihEdU@7P0ErPg5+^ZoSNnii)<{6q|s$zt3ER|G&#lgxA$%_d`9F8-Sw=$w@J z%7`(REB?9FG@?aT?b)SFW;e#2HW*cC)b?noJyO)Cl=zECbSue3{v*dq_jIJ{P6=9B zpdhf(kW)Qnh`oD!Oqm`YuVWPk_{6qt8>hEkz`LMy265DcQkXMp&=4oi4U8_a~m zer|j0?OE&t*4{QMH!y?DTw;jHNxvyN*Y0;ctkhqmuOLXw=-dsI-?c!Lq*q*}Vsn-f zLlD{M#kwOJm2Q`}5WfiZ$s?<={~#A%RNY{+7|chha`cPfdl|08%7DE!F^~jQHfmJb zqrTbkdd(1(53jOk1M_Ga3YaA;$B$>L+?(gihcR7B_ct5_vGXZ&XKe-$GT$h`TDuk})*hJX3ZO4&T)_cWzT+Zf=yz-$QXLG=jM_?^S#;LV7l+ge9Zi5M) z(Wjzk4NT}E7{k*kv%1>n*CUU>_0C9gyx^iT3nR_z86@~9IIA9t624@GkEYL1nzkD; z0D!-5aX{vclJioBw_!fM!}UYI6j~}YthY-cJ=gI=Rbqe?8k&A{)Ka@ZRKiQM8ih4e zp$BqQOjA`g>O4~VfbKUx<$nLt$O}fbarWbJ-}kiXQVU+0o>eI6)uPP2Kr0>*r(B@( z7ea7!A6$m`LQU)CSPTP_t4SA$L;zu`L60__j=Q+bP3I9xvGk{-qQT{kdTqbr95ab< z58IFW*+_T>!uZq?LjfT^&TH*u;2Tq4ZApOsOi4FxXKQS!EbaQ4$U^nOQwKG&>!Ihp znt~Z3KZ=Vz8_B(7*=xE`!No;utu=f>oA1(FS+GD1A$4-e9PylKNknDviyko?`=fYK zH>0{OR(8^I?1OjCxIkAl+0L-_l(x*x8a1F_{o9U#$Z%)qwuo_j`be5rB^d7iue<_s z&zF{2g|-t{SB{6?aiU&!+n~iq1g6;#qxGY-O7mPhe}bIJ%(!JwhxT7?Uyx1Lev?1D zPl8+`2%3cfUzKiVVbBaj3W>K}#Ef_L(87zTW-b^|LCyX$ut3x3uUSyJvIO{Ft|}}2 zl*Wyuc42N4V9)!*ha#5)lUi`FU(i+S90`jiF^^VZ{S@l8-+}$=XOTIKzH}f#lMf=c z9;&O*``!2OtHmaXxb}#K6Zmjf$pb=Bu;=Q43uG7E)(HILuM^VedU>?$Y3VdRXa#+# zIl$%>svJn`@Kp!31Tm+dxe=`alLB>nnn1DTg!qikz?w#1@8!sG+6wj?{lj{0VncZO0&*0|NCu#M<9Cu9%m@ER zHh*+=4AkXojbigu<8}8Y&Y&5F%&goOtCKBe#{9OF_Jn>00UbMB>&q`}x@8_ie-n(7 z%g1E93TOdp3rw`|1b3Z=<*ooz1M75ClOZb zkML%X`v9iV+XWcr(-?ROQ3B9M^$UbLL2}p2$v@aUG8ISrhUA%o?yf5yh0MI+J&+Bi zS4*mp_1scjDb)>_0=FF3ME{$VsoUgxOq~zb(L1m?Jw0cDFu#3@qmEga*1NI+wGMRM z$jzT!{eu1FfQ#ST`D-?|$pMSQiOPad815Vtk~aL){uA3FB}Eh@`|A{IJzuY9shfpC zSi_gTIvAU+4E%~+s}o;5~s9>bXh^GFHI`nd=|Hhs5&u&{>2GG*QEl%d2Q*u0o~|bmWFFm z>A1~KC3OWorA4|F_Zre6h~Etw*RS&k{NSB&+>WhDUNR}t-{eB+%lOpOVB=#08$@e2 zfquyoVU?Rcj%eSAtJ6fId=PuMtq<8UWtKQlUg1&La6Y&znqvFAH2yob&3`jXDQ2Ha7e9T_T`)#~*wS_O9XshdlB#ElH zz-q}Kn#-!)l?`Y>K-YgUOR*T2?{OV^M#LxTo*!9Dw^yfpbk@tT8gq(!S2l)ncWM7m$@;VN80fv%vjI5N z#Q?)wRJWBfx6*-q+V)6%BVmlR&?Kk*+0h4ttJPJFAUdGG$cDD(c^x)f(?Z<9gpE7m zdtuUOtDuMkMH9+x8zl1yk5fs;#Y{2il%>wG`PycfabAAHS5&0hpsGOSF(#-#=VZa* zHKO2P505WsKy%|sfXa_2yi`EgK=o8(kkI{_O!vWpx7K5J=$mF$rOt7ga)>8rjT%&* z)mCT(Ir4+)s~KioI$7+%`tO^Dpz^^VIWz8?(^;<);~y3(M3fxE7;t}!v8!pqv5p0> zV5oy~Zi31?KjU&pDdBlwQ?FU?94OqUo+73VDlZ!(zv40qMvf^dnqh?|a0D-LplP7{ z4SUhvxeD8Bm=omS2r92Yl0G!tyd4}_cN9($K_;}cQgaC^55CHHbnOHQT<7(bQ@L+V z*;860wvm|&?iOn;&vkkmXkzuSM+ts^q;-NpUIL=ElaBiQTVJy41o$S^l(q(0Iw8>Y zUljW!o_Eng0Y;rOt{^F8^8Gmj$GV+iLp2g$Cr-`?C|N@_^a06?M!2g)GBkRPE*W7c zpTChn9kAmTutcOpwk+HRT)ALxdJJV*R>(^b9sz1RwXlTXYr>Ax$BbF=(CX~tnX8(PZ(HnUek%l9wP%c8pEUHo2EZ+4RFPar3}k)dCasn zF)?!b3_meh^8WC~t?Q;L=0HA4?VeX#eWr~k-~n+Y(1fv)uViWM3dGw!i1jo9!^oc8 zLwP<}Q11C^4s{FMHij1IQ~Hk9M1H2buYe~G0JQM;6A6)!CXANqy!f4D znF>3Hn^P^qoLF__lW(e$j(z`WwL92v;BvVbj#lPfWn*Y;cW)(&tF92AZh8nXu{>iy zA4Sxxf~w&>1R-ALuffNqfiD?{1aeR?=K-CaXn4J5&bAFBpE8k$KS{%NUKbBod^Y5DJKhhuV zjbk=EnK@CMz*HXiD@;R;17>oPfMEGGM z&#ygT0!(>BYR{wZur`Pvjve>kc+6K%R3{3N#618r%r?eAQ&st4Vqi9eT)~Y!%loyH z6}6(hl&JeosIObI5Czg=pdRL-4}$BWzpzs<`>YBpumq8+ZgJV`!|efHI5*zaz;4&6gN>MfgJcSQM|Ks^b>{#6 z6Qg=SK9c@57vO!KQ?-M~mv8qZ65AAsW<~{3HvF6z49yuMoOFq<&?*JVj43W#`w}zXYRP%TsizJ@M8#~ z@f+lvyTJ&64&b1ts92PYJM@txXVHXx`*9(mOaqcKsNbLtfv+)mP*9FyLWV?Zmy3P% zCXN`)1y6sH3XRlBuQ*dZDFAx#_Ddw_iC{1$Fp^~*L+eF`FOOniH(qZ8lu&6FT#MS4 zlmRgKj`Rhixqo^(vnSN^k*8psnMFMwCG9zH^k2nvIi^z(UikL(3&Ia zU9A2cO*`40(d-5s1s=cCZ~qv_i#=*2K93hOsvL2cDEG!uft2g@;`PzQw_@W*Ywj!s znZt2mS2jewqQ%M}y1c#~O}Dk!7`@l?v~vj7%(VuZI7t8ZQ%?^90}_|7>duB@)}#d=Yx!%P zq=z3&piQXkQ~yge=U@O%;Rq!7_ffi6D8!imM5E)-x9y%{#D7jw5Ud;kDG5X)4g@qbs1!JtSPAwo-|i-nobMPk2I&?^A4J?5uQOsu#ss zzA*s8dkX`hCkGuZ(f4R)rta`5pHyFy;d90$*E&13Vi;NR_E0; z;ro1!+@l}nb4=-z0~aYkA0FqYN`K1Bk?MmPN(?N^MKkR zY$WzX9)%(=JXE1fVW6&cyuAS`81&$+u{m_DXPIT0DkNx{U{G)!M^xCZgl$`!hj0aZ zJuI%r6m;FrQGe7B zvk2XV`?c8kBlUSbnSCW#j@9K$t!nkSoZ^C1&}%o}k zly_3$3~YT)o{l}iO2@xM^G6MFD$||O%yhh`77BJ8(izBlQ;;tp%t&MXEG7ZVcSVZm z%p(N7;uo>WyFbh%cX9e;`o)4&2cG<Qa$Kj7GuOtDS; zez&}n*`|hl3|lwI)O8&SZjuM*I?@DSUHNnUDK9vo6nkf_&D>na*|#SEL#Ag&@c$!A zth#loIFC_lc6K$lGs7$?)lxthdBT^ZD00-v7b?}~1{%RzYqP|%+U6XYjBPzC_<~}) z*t=(ZmqOkLi>hkJhJH@A8EA=#`TUuHC%&w44F(9%z7hTW6t|X}-WFDdweo#P=v){u z$|SFuPhQsW>*c-x_$hh&qk|?c6cvtf>+5Zj zTQ(h+$Y+^$0V3glABU4NB4QV6vjxvje8+;+mD6V>iuVZwBu+V?grg z@dEVci&w2J^X0X-Eowyb-IWc>+q<+MMDTVV`=hoR^xkVWeKY(FC8FI-qE2tD!CJ=Z z9uw-~?kep+p!oDSW(_Tr67=9Lo87o?@v+&sw6h;*p0&k>h`3~7ov!U7IK0-DGG9jn z1G@iWTR0;|o8B{hLu;MxbgGw?KUIwVg0;3szX=1!%--eeUD<#t1zop2|D&e3D&;QR zui5mX*E>9&-A7SvD=)`@qiY*8@v*P5s!CDhi(3;t?KA^DbYpIekUeI7#i{s|hZVo_ zj(LbGH>E!2m^Z4GKv*VuEfEEDbbzLRTi$3ARo5E9Ey||~OA0?IZWd(>$KS8TW#UHJ!bTx+jEQ|n^T@&@=uZKYus~{||JGL60)hit z?&YJ@v{((5&2WbHK&m-^IHg!>O$z#ib=^~htA#4hfai1Fcm&>Sjq~`DPA@(q(@K!# zOSBlO-;eTwU0RVZ6ijN3yzQx@dKL%JX{W?N<-wRYts$2^Bpr?6&Q2Bh71fF&|lY50%o$pC zqXmldIol3nJNdrqc(3rIyh_VO*CP|c0%BZwPCLa8q}6Qjx1jP70e+C2FBQvjXTP^U zb7@_$V_+S#qR&*$+sLLCwDtKbyOjv1%?Vm!-N{$XTGA+S;k_Zw_Ui);eO5F_wLenr zEk0pcPX;(Xu4ggHws~o~TeFv-JBhH|3zB~jzo&~w6tK_V1d*rU`CnBXdCxVE$ARi6 z!JEmQTj?vPwcAu9IevvUKN!>**hrAn9%TCHeD8(rkM=96)IS}f)Ze64+E{KDTHO_e z&36Kof4DG*%NuB6^BD1+oVhi=r6TlzfVJ(7PfGp{x8l9<_M>AEkbdd`U)6=o54GB@sOITgl#-c3L~E? zTm8}h-^uUrZhi6sF9Qa#J_?s9!vJAo`bb~G_cd<_&U}{Uuj?>B%KuJ&>1WekQS|d~ zyMetx`xqk~jFCAcwL6MT6+l67>( z4df72qHvxm(T5K{;D;zEFsdmy%nA)<7qd?QjZ>Cwb_ii%{t812o=+;or#aTmovlff zM1(`f00v(ee_0#uQ|Ur6?||RS7UC-yL2?3=zTh^O!(UrKjwMCALV~n zKT1GzLxf&xnI*xKs$(;#tEC_+-7nM6Y#^~m!P*m7+5Q(l_mYLM4f9n^(map#G<^vJ zyk!LMLethSp#%L5ou3Q2ew6>6NlkJ>L|n*TI~hs_52Vr{QQ2EvS+8L zy57J6sr2tu>LFVgR(m8ls!>eRAs|L-xlHzCCOP2@cpBF(0|%=dV+U|K2~?hfIweW? zUA|t`z@Wui+VOq;do`;dejF{vBIB7${uY)cE!^bH zGp-4Go?J343t3$kG~)AObzE9zey}H}L$Z6d_ZjiMX{>Rt zUXSG@9QnFLt<7YD>c25*Y@9UmYV&5FkkzxX1DgMy6KnBZpzNfd@P6r0z|&Z6jy`~%7F zkp3@`Tm=66f<%&%d!XdPpD|hWi`w+i)4u#tJ-iW6{jeop*|pPly4ZxS&e>67Y~ml1 zu%TLf_xp5+W>j+C^74mBnyrX04&2jT$wPnfh8TQfzhymwWXnBg zW?frR0~9-UJR>1Qyv5dqatCaL7P@=zVd8+oCG0-ec?uMsb1 zqX-Emhj(jJS5sE`NBzH3iFqOVHt4KEHpfo}0Ib^osr|g#S0|d@WG_myBA; zcnK}cEj1N}Y1%BziZU!@J?_)vMW5GT^3){&e$@Xvl~8QP`G078>!>QXt`8J8jdYi= z2`T9k1nCs%Qd;Tml$7pnX-O$TI;2EO8tIaf?ymc6IG*#4@BO@oG46NIAC7Ux*puHg ze`~I})|zXsIVIfrPf>?k^JKa96S$T>lJ$@p8S}Rd9nR3po!$0~hv5I|`@b#9wkj?$ zj%_LpeNxjQtN*mSt1(O$?mO>ZbAFBPge|hv_BHm|I8!*+Yo_cCsuM@lgv*O(j{K0o27$ zX}}7>QabG)+`zuOirNg}zwMWbV9ywPW4z?jcg5nMC5}XLxhNbWFOTy~1eSVW@B^A^ z=-06ehHq>iIt6iaZMM3xKh+#-X#JM2c)&Gf_dcsP_F`I1o(N+FypHq|BL8pWrvhZf zK==cN1#Ml>40PR8;Ver(^UhixVG4!Fi%@&BA4Ku6GM7zZ`b2okFrKl0fu2`rESN?+ z@yFdE{*C{qC6({PXI_)+&}VjYc&SwkGOU&8mtFQ$<2h*``#E3Wx;sJ+QxJR+t`db8 zWPZy;$?;c~1G(Oh6N+vt9L@+qe_)yxx=!V1yvT3)KiThE;aDd$8U|5i z>Gp}>cZ6*L*G{@vYhxLDL5UWG3XYGz<^SY=_FF-UA(?MAM2}y7W+Tbj$>m~4w{BQDe#3qJ)i9q=#hRAPZmMPDP-wjwGerRZqzEMl|%Rlt_H~A3PBWp4N z$8w=&of-r0Ca$0>@67yCu730pXq?FNkj3Bff0}=h+Z|y2vtYAN^ubS@4E<^=$c$c| zZAJ>}ZT8@8v?&k%mj4rf^Fe5iGk%Y}^Wfar( zh%WXKtvum6zZR8e9k|H$nMhtn?lsANZ9M&r|0n&&iwMA$+wNnS%PG0G7O{TJ( zNS@cvx-@ncSIC@yCzYW!!a`YuWX>s$9rnUo=tdS~_E$mhQRB90^jW#y>rKH%HP_9S zc+O6SP%(f?zw^D7M69g;J4*2<{503S)%1uc@59!?LLcFzKKX!ObjweTJjqh=kb>6F ztN-o$>E#JCs1+R(^(Xok1YB~^VWw_c`wo+T5)XxZtb#qbEg}G!|9|oyo>FhT`-H{K zNArHfx~{`!J|k@9`Vv)p*{>h;%%L**@o)S;t$(4qDM{5-50}?I6=6eDdP;d3JAsg} z)S%J4(KDqPfBn5B{}cXwCw8{77^#@H}K9diAa8uf-rhD=PFKmV;&0(Vc#{ZN3 zZO$TIpKVTsHv2Ze`DN=->@_E(P(L^x$*o%_<(K~*{9FD{{4bXsl`}Ll_IbOyog3u} zhFg1$sh?aOYe%lwxAlmCb|q^XXOHHU|Chw&tV*>bOD-HnlrcKb<*a>%7K z^6X#z-}e;KSJEFId(eXe3*d&&T?We8p5hN*m2^qHX6bp^RD=Y40A&2MRTvnAujEhq z%MQ*c`i&4iDo~D)-Qg|Zhhs<}Rw-@t0aZit4o}ASpXSFH59?lkvZaMn5_2b|0 zA$xKNzAx-n`PZS&Xvs~DUS9XMfltg6&Jg^`3-Lk!U}ifvqOvM3lcxtR+@iTLjRtJ* ztWDM>^>c3i4c}7vA^d`tOe&TEc{r7vjttFXQVdG7hYv(vzF+L=c+c{0{QLZpk-a=Y z#`?7@CW;kq{yrL2!ujJsWiP*u8n^O53CwT#KiRJnZt=~|4vhqz-`kJ!V>0Ed)ttQ# zS#EMK$clYBKK3>I+xM%ECLXsJ%zM3LJ>@g9SoOrzw{op7W%@q+%goNB$Kvn(3~c#(9A+Wh%(H1$(Dn+@0Gi3&G4C-dL-|EKwbb=k~-z{vZUbHD6$p$)12@^NUw#uGz9 zH&<|uj`&FSZ~Q;WJ6?olhDok4TbJd-f^l+$6e^ zj7aqAg87*uO?;od^zZNg6Mv_MXygH8wPTuPyC+JE?GI+Bh04s1(0<^HUFqJR{r<-<4^Nmx3mrAe)WmM;3V-k;7F}$Tx6g z&g+H+l+4TD@_!nCk0-@sni_Cl&DRd_k*SE?1iEOf&$Hf|FUJa{fw;;3PRjq2{;qkn zY0@=12_vPiEQ;Q}Uj)mq@d=|BV-)Hchq`ioSB1Qlf%soJHL$!5?z~k`Pc-f&y}X@P z`_nZD|EkcwtkQr-G3=(1 zPLeeImrA8*i2SBCua`9q35s}%jWvB-{={qfM^$Ycq8qL@$|jMrnYZ0eZ}I_*b4rAzF8NK8`(z2J($vR|G70KAwCD!$Yb~7u} z85AiH3cwDRU85kd;`;=6|3h_g!{+pQY_1NxY2lE#$t-P#dT5uiK-_oXKs@CIrM4L{ zeEZ(^mS@8ot4;Tkr*#c%@;a~vy~`AoPfDWia>Av=vdaT~WF7{Kx$Pjf4j&hm>r6j) z$kf~jMh#i8!-N8IUCz;9M?T@qCxvi!HZB-1a(C$KAnsDX=YOGo6p*F;5P+KIVvNcw zVKl`UlV!Fe7AJT)&fe{hnrZ$Ev#$>eU*Pf%iu;+L>mCyyduz=%r_7n{8wtkGl_%e0! zrdV0%>1A{;2y6uB{%Us@Hxqwg(fd7hjj;h*5VuN`75cN842&se zlr(xW4GnZNA<2!DuXBr;OU*q1Drmn-(u89ogU%_W zzqZuDcu>iXHTwlGDRnssePiVk_zp_sEI}z&h~4&rz^%0on!eH`<$8T{s@3hLfK58` z^A(VhubWdoEUilWN~}@&>|$OX#MAR4A|bM&X+7En(GsqV5r8TPDe&h+eNXpDs<&*? zdQ(ZE*{ZcUFFPFdLH{6;oz2!A6wTpld(U-#BB>zohmnmV?$~Lv74kA`iC+)FiM(`L zyC5(H+g5`0w~P8ks52^`OQH}6_Qu@bGaH=#cRRnjH36p zKoSIwZ{iiSvtVjV;V#a`J^8|ugF)DwCQbt>{`DCjzyd{{>IwRC3@>d{+u-o+s-8xO zCZ?Sx{?LjmCLcehb{D?)Sn1dN@;;-5q6i@iLl#UJG1fJm|M<O?q_9W0MtU=C7ZW}F(@3QE6beN--ZJf zDtaRHmGoxewO4GVFV)>x=`s=KWCxhonyQl4Tuq${>Rd6?`I>jdJ*{=24X+H31A)O< zR?-rM*#RD62QnlLODaa@Ha^Fj9wkG8UqE>*sN?r`Ot5E!6S)Q%yw9AZjUNyH${UjN zm*F+E$VfCTTmBI6;SvOPR{4NN3zSh43W^7dA+RMF|7`hn@`X8$H=?J#N-!TVi+egI z{SWUJA1NJqRQH&(Y*pcC9mz>{%IEmn4PEfSM5tD6g1@(M{!7XBy37z6p>B zNybm|V_fK~MhfpQeQ>=86x1Dq(EbE$GRKYn@0BypPdK8whJ1j6mnLv?f>v^<w@C|ve^27)GRMj{JrM%-lKr3TpUb*L6A5vdH>uuB% zcw8%V#XLvHtw(-I(HDg!oCn-B+|%EZ@CsUAkT{_RluW6Q@a-9QI@gpnPFySbdVN(R z7g+|nuyN5_qLu|NR?58_u@-w(9l4+_{i#c-p>g?(QJS;vG9WE%}3A z8~6r#>Hq@2Y+Tdsn>$M!xWaUvbrs%VbT3Nbj4Fy*tj)Hie-~%FGYf~usikWN#V(dD zZ5{f|L`GaPPNmFhho%_)<#z5~#K7wm9Mh8XtMo7@9S7c;(Yo&;qy(fJa2Rhpm4ih} zU{VyW@2wSaQLdgK?<=To<_g47$_(^_69I6|?)-!5#JBG&d5?f9lf;60P_0iT=o|H3 zv*&bC`0?{q8_$$gCpop;gvJ7{1D$R7k!6cREe7Tx$ zOZ;K=QgJ}5`)!#_iu;*4Z$&J=K(~;S*E~6X>Qm?Ily{!5cO#=#OfJhx*U&<=@ zdPK$Az4}d;eR4I+aMDi-xnUZ7IVl)ZlVt#^O}Bu90{OijIsyp8OkYpVf`6iO$><14 zOqgYPsD1qU&MYjyVLu!_A%D4<+UzpeU0YEJA59{O%*Svun1G*W@zWXb77r$tFnWlX z7JZRreFCWPvQjh*G_xxxuXgPaf}Q?1Uei@$hKD?`7NIuS3W6iPrO@9k1GH z)(#pz2|FZvt^;iybFqUxH-^d5OH5QZcyX}n!1*ct%&kE9TYxCUqZMdKbk8Zw-%Gn- z^GcAEf19BDyTU%+Kx_+A>awl5LM`=|oEIOlf$ePoa@EMILcx9~paGg=G(FCq{0sMX z{x-?zJ#zCKnfQBKAR*Q>c1Kf9rBzLTINoxdC zSbRBo9$~7QIzYu-=A?z5!ufU~axRvgeI__%QVpmas7G1#d{q_W0en{2s|k2aBXskCf&JQv~-rv+vCy%9`D%pb*a+GG9@QM%nzv ztf@TAJ)^;gPai^(X6DO*jm#PsmGoeFlQJ$b)Ym4aoK^hLCkvOgF!(JcEw!=FAp6@X zdbV2M_jL?bhEo}B3zmdA2T>wR43di?kDd|wYse1WO)SMX^TH*nRPYM0&}B5F*u^(P z9O^pbWt1%4nF!#l|I}Y*U52lBHdXNbE@( zDt?#m$gWDM;%Cx{1_C>j>*sAqP_sNsgE?hWB)cqU*$L8AsXKc^=enV)Pj`85yTED3 zS;?}_EjwT>QnVber*}Q?vz(IgO(@h7J9XY$A_0M+qF2qpf>Rz8pP=B{F?om(9Hepv zO4g!?5FW#a9TNjt%P_*mgs@37Ve9iP;HL(2njWY2ewUsmr(6OlwyiJ;%#3$hA;jXW zA__bDr+VnvM{dt!lI728aTL&fk=drjPMw0`1c9F!(zWdNtxH?2OR^5JZO*p^l(z0} z>Trmt9(Td{MggnHJ>7+sEND$vn$VomlM+mdnBCg~WvEgsBT{OwYYvy+nKkfu*@e6I z={PoQJmi;7E`n#>0)byr9C930S$+$K`&Q9HU1fGkd^S@euIq-qCd#o9Rrd&hy5E+` z`AM;3ZVYHIHF&&2N$2?{+OyEp+``4ExweDx7z^Oc4E9uha%4os787PHz=8M5?iZCF z;(IpGg}U4stw(jwn)%j~{+RI4>0 zF!nTgq{c7I+9r|Rw?bE%>*{B*&GDZbB&Qwo^UDjrJKUQk_tw+&J_;${)MWZa%WFE?S=g20v&4}xYXztmrHSPf}sWu~dC zg#KVmrzG?LiM>3QRm2KFjqr*SKsB{-B!<;H;BTCMcVd5r3szWRw%p+>3+w9exP#K# zr3w>Ye#)h_wU{+jI44qD1XQUr@Hr$YmGbJz;|A77C4-9)_8W2sYXsEELD`$C5Y<&eh8gEF+Id>gdIQ%k+3E}BN-O`YiGJ)_VBM6NA(tBP=m&9O5zN~Sw(RqWmul-US zbn>=$<#^xrCsQe)Rg@>jP(jE+!ZsEhCO?rMxB!}E3>pSUdpNNcCF*KA{toH|EZR)@ zdjfbf^XN6gJePohr0OqL9=82kB~dYgap__pu(TaX2BDu!>)@%g*A>o`!BV~VubCo* zFEf}~{86^1Vt&m}4+j|P1zs_Fm+kRJJ+o0-{LQQa}qxHC<`E{P*xjIk@Pf0;b zG4W;(?yXCy8Q~Lzog01>?Cr{9P(b3FHp_2Uh0ziM5%&q)YRIha^kg*ntJ>g=KJJ+Ek1h@P^$^h*m`kWp6lYeuy3*K(R& zA*jGLcBsN*R3d`F29F40@Y+ABafG2z5QT2XY#LKxYvx~CSbc@84S050QFI1VG~P|ko0n6>1Ps1(g63qa zWqXIR>C&fy)DoS*Slw@T=4>e5gUE~`^dnO@f@7;sZK!5)eAj)nEbo1`;+#!8gX`bcX5o)_~IM*Mqz69~y8w&Jk zWNm{+eB<-$a z4Zff!0c@8^mT@7Q2eIEd@*9)yl#Um=94%LL%Xl64HVf*HF|E~Tr7u>V%v-JqJXp^Y zdDQ>dP|3PHtq9@$U zTOZbxhc#&yb!D^4VDjv_7tLS}$`zw$(z`euhhn5KQ53)`enH{19XjwDsQt9(c#u(r z8W8t>Z`yHzw!&N^n$>^z-u%fx9ao`G(GePk)+D*$!4tDZ@^KRuKkf5L(kW<&@tf2p`VsLbEQX9YelTG=`A||j>E}X_AYrKvS(+a_JeU+ zbp`9}IKRtoYR|vSSWWECSul09u4fvgWGV-}fAI0JYsE`Rci!B)?ORy8D|yYji3|vg zZ@gkrYX~n`nCSOioiv2Bq=8YlPXwp-Wy|~N^9q!adk>X1Z2X%8Z3DxKdgH2EN$SWN zOHIB-7FaCNwRC|n8zP`10_PU*x)pna*Fa)T(dZC(C2pmFMof=A9Ut|wEbzr_69BcJ z$~5fjJ50&inKj&{RGwENKygJmD*oE1A4f!j#wqYlE4(S+yyhqPY)M%O8loHVxS_9U zy0qOi7N@UZKZd}5(Eyx9eI3`BzJ~yn)JJD7!%WBP0b~rgf^#mOz;0Pv?Ns2Z=bnDa zeqi!axC-iUu`>EI)I~{u$=CocAyHha>SX0>giTLXpr}zMQBXuZNy5Qf$DDa(O&zsy zrui;g+IU^1T9df&Ho!046AJ7LHJXL>GD(;e-PTqp@ZpEyFQ!@5AT$-y4)LC1=>{PB zEkPf^FFD@&+~T7hMz-o{u5&Z9#v^CcB)Z2#&Cjwk0I2%~6ZDH`ELK#mM6IXMN?4k{ zX%ey2ib%8B?fxjWDfj)todnbl8lZnH$R74X=-Tl$-#VP00u@k9g^@UlkCYg^jNehQM4Yb_n<-lzwc?YuC4~QTba; zwYF~>bw1SMnf;O=SNxhBNJ#*x|P9^dyd0?@s{K{ce?P4uW|0Y2OyS zh-~DnV2_J_=c53fRjAk?amv2r?)gRzSQ)9{B0j8T&e4@F+F5Eh5o6-U54?NJ=bb4a zj3m>&LVjieBYG$W!1KsyH%M0p$vH9ppN z)|vbC&mM2%DM&>c!9I|g9Ee803N-+pEZ%cvw4ZDfE}`4RK5wU-Vqx5W38%YG~4r4dKjW)?70uM0_7ko`LLgPd|xax|5XD<&a7>_?q5Gu|P zNsacoyb8AhpqLaFWsd5$K%FnrG=I7cUSYn-3;kioB0WV{n%kW|qjBdg2uI8o3e}rx zSAX;tr*nDivC3m=F23k7TTQlnUa@fsR4KNKF(VMZ7*Osx^VxclNUp_v)z4L(mbzUP zB@C90`y>lM-OmEeSM)xv;)%{Hx;iyLH*&zYR(Vz`fpd5_PdH_X(<(TCR-~jm%X?z* z+G84(me>Q_^Qd#;Ep<~171d{}~Rl28E95p9aYrj4qXbV}#Zk05B5GW&_QQtd^ zF_Kzr>aC~-ERfJOBRis@&_*QFR%uFBDjLm8qr&Uw7k9Jx?n>CGbewxzAY1M=ta!20 zn9Q4W-An^-MnVB}Yg@PP0Rg4NW=DGh5TkpnOFO3>=n#kUq9`e=s@fu+v>4|B zQlJHPVWMq3$kglJX5sX}o;q3Zqn-!o*;~7>pEj5+-{eoUe3E1=)1%`3f6rKBJ*k2|sd=K9MI%0f`XoIG_swB3!sU4q|AF1Fb#C--q6o_bFx zj`B7(zC`G^7QD?o!RnvoN6niDaF;MXYK%ysnnvz30P$2MzsZgFK94dHGyHWM(wpY} zi>ckBCCElaklIt;9ze9Z-&pC?<*C5XUY<<7a>YxHKsR@eO=GL~-)Q$<2~P}4Ho5^4 zE>u=4iXJuK$CI;o;XdhPd?@A`Tp3=kT+UcfZY^4mO?H(<`^e=ZBE;>+>Bjz zZ?oWdpwHzd80hL64Ub-hkDo9DBGKOCMw0QE3G(J9mr@1@41c-Jxr6gW7_9{;WlK`=HSprrS;@CY*$tQ=>h{rsrC=HcD6v(TYJb6w5V<8tEPVr~;w?zfBKt()Y)ot{`GZNh2W zX>oYcpH4G$IAWGPfwY+7Gstl z8k9@v(!#9w4QZO5KSm@CW$yzDRKGN_sgl-I@%c<4yj6Huu^TtWm@@d#^p~N@&gbN9 zLICQ1E|4BM(4ZL&{IUdzC;Qh!k^(cwt*yh?&3-Y^kkNvwKN9CNxWt=joD!BFz) z;YZ9S#2_&3BRh|lm5h&!yBtFqJT0v$${n6*R@%vNo}i*uhEzzellzU8Xvb+D+~?0% zfz0KtbZ)BXLGf`N)Xbz*-GrKJm=z%+K_Ln#0?mue4YgB#rzTS&wC=)(V=dVOCyGJ^XHAW?Z!F5Vk7hm%FLy6}P`kx`oqC7gS zH|bdl0bWdjsmV0nhKvy;zb{&>Uw@yuv8-uT2Y=XA868gi+E7Mm?jBH5~uUc zVMKl?i9_h4@U68%UF_W#hs8tSgoM}a%w=h12xBUi)8&$JOv5vttC zu?j5&J2B=hb@<|Ek^iG3gV{w^g(?)uW1=arKbow{Gj{NF=UXWwRlA~_O=FnDnrFzS zZ7Fm}n3hgaQ$6Nva_-P!VUV0qXvANT&jJ!p3vdb^UAA!@_;RB+YW9I=qpQ9i8dKdq zD!J9JURXvc!eQ>qDvdBv(&$8I_rO_RYsWXE8ZOo&{0ob9$dCTg?n1p@PuWA$IF^`* zlOHyKt9WT2;IKhYM9s;3?Oto^_0LCryd46iD?EElQjUZW^5NtCvI%riJFttIPpty2~d)4`AM z!Zvr{r}}&%aitvriu$P8ZTSTOM(Mz3S`g)^)I=OHaC!b0g4b4EE7on9r`w^=xr{Ds z3U;JOQtc{^-##oT!g7P5O8>&(qA)9*>wc!NMLCXUd{ADU_F>>VgZr>e6PWA#bpp+ zH1QhjY1jUz;;YQ%w}1ZsopwmNK2S&b{maK{#(}1!){08HTu!+cGI%Y6s;256x`ox> z6SkrJfcy%QRqZ+dEn}zRu@jvj3|q0VCs1F+{VAkWIVj5p4)U8@8%^@flQl4`gi4iI zGLee$d4foqmKa!+>-2YH&fY$T=F^*uX;|p*=#_otH!ex;N`K{Dt6Fl}a|D2n&~byt z=VrKM*M`sXjt78@)qz(yW0-es>NAxf3yyXvSnX|=ydy>$UVO#X8~N(zco+Y%)P&6lYn6bQQTrf zd3Xb#wX{AE%cOEx4j@8W7=ICmC_n9KwCBLxs8TM7MQ8)#Cp%T7;_j2m;7ClIBuWCD;Ne^P1iM7ieR5iH zF-bNQY(idIMWHxTKba=j`?z!J04V^_&1KIbXhr~>(r{eW_WPXuM{_xO(Z1LO z^t=wUy9J3y$O6wNY@n0w`jy{vhNseQ#1^UPHlr&`jA-p_fJe>1e~_s_?G`j0+w5+)Vps3t|Dd?X{g62`u;}^>>-HA_ z$2{aCbK0*ZzoMTb6r`L-7g8w2(Er6TS<|CwmMBq!z`juuwe!&3&`Q;>T&{#yVe=&% zq!z$U8(2tf=mQewJLtz7Im73&Yv@HdA$GD+wCiOkYS0zh(UE{-DD81Z{~=)Ak5}Z# zA&T^cwRHSCElFAY^gC_x14jmh>cW4Fvx~SUlS;7S179U?bOq)BQH{JJw1>WZwAx;FH#780Tus ztCcxO66fJ-q@00tLs5*pdbi_^^U%PmsXWgbxCp_n^dSUEX!bkPB&?=T$Pw6P&Ym&P zKGOKGNTRg7hkr&JAGey1=i3$>M)R4`a zdRhZOW#@LmFlqNllrezU5mZTK{XIhIv8`|%f#VlXEjj7EcTc{&&VMBbVOUVv(7!yH zO;L7AL8Qc2dcr*i^WB?KbY!e+sU&5wQrO?}e6_*xQpBPl4I=*!!!9q;OBa-lZ%4?m zhv1_8-?zjB6>@I$vXvD@Cl}qumR+;iD^x%PWA_1l8$pY(O1D?Cd$G%P> z71*V!ugS3Ae5?wnbqSemM*-rB=>+yEVCyi_1Vg{~9d~ms_Ud%Gf>4Ahucu=re~Fpi zjge851P{Fkul_W>5*%Yw2B-;{FVP>0MCj1;sp-1V6;Nc`fU)Jt9#o>hl9K<}^Z1gT z8>L<;Tk|ot%M-$bH`)^h092gOv{2RNPx|8KA8K(Kgn39w#S61?p$vP$U-XYS$l3oH zBY3MwtEhJGhYd3W`Xeb$ABApIUgTEb)Z?JKbq@-D7jpW|FE5Avn012pS z_O=YTB?!mVA<=mc#GgkZYYqn6fcB+Se@&;sM?#yj>==iNBPT!oE${S(6Z=ZVh1`Wt zzBVY{cfr2bz8fN6&})qTGulF{dIlc9)48PerhpT(f;cCf$B(kn=Z}|W!inuCu zw@Mcd^d7SfhEi}ui)vITm}zi07E zTa&}3JeuPxzN@neHvSIWh_OP5e5#bbXZ5+Q=`?f5fVC~jBRAUeN7K{N!^cEBUgW6sOlV?@BU%*S32JA|ms^cT$bbsYnh|wk_sXD_(FaO%y z9O|dk>Z48=t5aAURdzNM?$F?&+*I2&IUd-meZ#b-f3mYqW zf4l|ULjs+j)Gf$N7*@}_4S9VHw3rhf!!uA+aUID@VUGF$xiA3w@^rO8V7K&t0ubry%zV6N#;a_ENBb}y@Zl%?DA2xQIuW7DBQ zIrS|v@L@cN>V~BFV83A&Jsaf-98sbIDl_|JY0&T4nvbWQS@zoL*9(>Eh~vF6$2Wq* z*${kk>3P#_V{&QhrLnKve%M32zq&@+&6pC-XZiEPg65GT~?$5rcw(%EiB$7VQ={MC<^(045-H%Q=$1g z6MZESlMhE}v_!1~A@a~}>KM110$@+js~kZ>zNpU!H;b5FUQ`-$`AwhZui4IPNM+h$ z9Gl+}5<0EbF*@Mx);%K8gjgmjRZ@m$pNJ{LHY0jxtmGyzU*Dpr zsIHTDb2r%E(5>a)urMfO<|P+K_9h#@CIo>&FSvTGNE}3BZ?I&rxQO;ujI*T~JIz!t zze~iQsz3qplY4d&a!BWTZW-JXcx^m4Mo*xD?w1!Tol6#K#!(2jrvFpY1lZ}YA)Zl- zxpPjxV0gKV*cKaacjZaVs#?1j%onmkVgrPbL4(Kz$sBF`0!DM&L7Qi~w#4aY`#x6W zg%1N#Fi`~xO7FBnY+SMh=Pe<>J=>|QL&n_B9X`@xEMGJ3`$BCFW_&RRq}8K~^u83f z)|3@yh&-2nlPqgR_ty~0b%gRPYhqw7u8=@k9x=|ZoVc(LFl~Q&H$!%16?8U z;`V<4dyIiE5K@Bg`!+Gl4P|-wL3JT2c>H%8`!?=G?L8IFtCPwvFRLmnFp(#5!Tqq$ z1157;J_hGjTY|t0{?TGSbETX%+g*|1I=#ML7FFe#8^@{hVeivpk#6$ z7dLL{hXDbM*wX|p(}Q6(a@2y%W^G&BZklT+iX{-W|2n(7y!@7Af^mr=ugh92Vv4|> zpMnZK-C#`Lv(|axImmQd(FW?4t`O*Fzv-f%ZH-r}YKySKMKed}F|wkkH8uFF?>+CM zQn6TX@#I!AWY2G7I%?NJ<_UGVV=rIYO(hsN8Eyjs+X?^aZe-{FA72SYmj?4#sW2n! z-NwH6pDfmLzZtZ4guaUp{t9D$V&ooHQf;4~sh+p_Nm}+PQ5Sx=N`HtXX~npl01!GK zpDiWtj2XDlK0$A{YTIk*mWB#^rV#A;5oyfqp=Nutfc$ z=2bbtNqv1S{~ZPr5sfTsp@}XXF;pW)$fs}w!a%ABFnk9Z&52D;Dm_6y%PX3DgG`D- zAsDk_J5-QAeS7w0%FW^Z;ao$?K3ZWKF|+e=s9tU0KZ1u2n*Nr`KHo~bq}HJ90?cE@ zilz00vQ1P@gnOpLUxYt|5cn52SD6wox8Y}(A26EZQ>%bJR8a13O3yfbC}gmH{c}g{ z2n5!AJsB!Y)v$ET zwc&D3w;uB{-5RPlvjt{5kQ^n)0ag)PG(N7SDkP>%QpWB+za9ME|Ec-O z^nG~0<)*u*bQXJt($G%gT~CSn^7^9(uVu*khHy&KlIWQ=D=8sAx{Iuu3!x6uW<@F{SLH$!D4=3Q+8owAA39@>KP!@nItjHpY01^kZbA z9iV1+sBd(p6G?9o^;O(iwf6X1bH^x~jgC(ja_vepX(0eLDex^8wo9hey?!wc^4!Y5 zex>BeJbt;>eG=jFb4Y^hwzlB^bi{j5pjE7p|DH#G8%HyOtpZvC2suLH&Fd){tA~Iq zaYF#D?T(K*aQ;ul^^qtcD&1OSz*YOrs?-B7cbONa_7?BA{Fu!V{=*SFCG{^LVqhtr z$fN~!Q-QvTwmWbz6`H-=-mxo64HMP({|M7+4Km}EJ7C_Ct8lGGSf&c#e zd-YfP|7Sv}bizr}N$cP~Wlq;Z?_m}D**c#Z;d5bPECuxe7Cf{44>f2so%Qv5Pfemo zXxFb>f4#ClK%uli;QziF=P@GG(*-P1h;=@5_9EF&C@Rmft0h!&^GsM6cDR4B5}WKi zHR_DY0I1=w+_8eq8i;ITu%|9EQA!p0g_y;4S`rq|8UxQlbW9DIP|yQ8w*_S&0eW}I z7I01jk}x>c>lU%?dLzYk1{j0b6Gx<8qk&%0bh`pq^~9Xqc_|O2;Y*)@H66` z-}b%yYZ0l}U*gZ0_&K#3mY6W0x)v1ECBvm^`PQqbjG^FVuraXJR0!IhYqY?Gr=uKE z>(e*OZ|2}IPzY9BG^EFi>(6v~0eH%L^%T1uRp6h$HXr||!$uoQ@wd_ZO9MkA`?(?> zBHgv-k8s(;$&&7zBbS}v{J;{sMUJ?- zx`M32RJq|`33+9|#A9ru+am_i9h> zI{J^R{B!4dh>HIgTett|F(7{zV$aYYCJnsDVb|WT+JRl01Mw;sX34Eyz|xVMuPg0= z%;Ilj0)KIH>W+bv)|46c^lM(>lBBXq@9=hc#&y(DPAsSmdj*nRssCAemZ{shkHzP! zeaAD|4Aki5ujbLlbab2{YC==nkkl-1or?OHA+J_RWIT{5UtGU8K`=DVC9yLd!%suK zm_U*LZS(Pex=1XMfFa7?`bq`z&esH&C3NffA5J)=pa|yOe~SKxuVlW=(WyfFq}FE^ z0NWs&muBw*$Hmn+70kH%12NYDffz#IU)T+~KXy{SoFcI!j&@>uit&|-XGFM=A`MtzcVhw2y%NEA3T2En-=r@D>Em?JuQ3T@C@bSdCAb;j=_aPRhH}#&W zb5{A`?jYN#W4-qnE$64BCPqgql7OK>#s#3e1grQ`mTT{;Q34S3CoVEBCE&IAwE&sg#^I*Fc_hYsHjhbC3(0;Wy z8%`O*W@a9>;D6uskL=SHM#-Isc=(Q*_iUrP0!wTx0%#ZfrG-R+>aA75qLa+l$vZ(} zAjfr58yg;?(yiGz@G-7@I}WZeGhvnP{B`u8cU$4be^B!+&v2@+%v?lQ^^w@IXLYG& zk*{uLSC?}6h`p9@0=)M>>j-s^BkF~XzI8Y5i!_~A)q9yAVy>26w@kJ_j9^}1O!;Jhg2}Y%?M0s^Ssofi=~up+*v*Ima}c` zVq_@W$PG!+H>yvIo5vgeH){SrH7MK?W4T_&cldRBQ`39^*J&k)dT(l~4Fc+qYsaAR zJ+sq28bTe(s8FM1?SCMBsMt(dS1E zsl>kDL}P(YJYXE@O2ex}lDEfURE1l9FeEB-3a!V=;(1${XrNk=`d9a*CK2vFpAQ-P zzZ~%?6i9bd8$-IuqOPPmE8@TRaK^{s1>*R%eBxSKo4@)xae=cCF#?Q;#`X`-F^ADH z5(=wRq_WH9pIqXXx4ZOPM?9c8ZmxpGg?T7O^5*1`qSw_kac;YzbHfTLdb|<_AHuDRBlHEU+p=!YJp1u0vkqVx=NA1*BhIItKmNk06# z%AExw=UmW+pIaf`11h4e<%H4p!rA3 z#F!sKeJ2+unXQHgs1_j3B5=JBXs$t9R+S>NKD?UaGt~z*vAKuNCXIA-J_zHrryqU0 zA?L>K>~R0bkY!l2=746w=Hm0_#;Do!6FbA}@E7Uqt2-u0WQo8vvS|g40R^7^uW?D# zY%S-#xp9YxCJ77=;3byM3PKC}06Sd%ISr>WkF)MJu|*xahU8JJ*M*RuTYf9bwVdbC zDe)tSM)6|Pf;$K?2<5ev8eTd(s|4`6)d^pqAL>=dfBk6?z+c?a<{w#V`%HDxNAqHd zCw)7LE^2O3;Cdn0D4nGn;xAa_caEcx{}r0lH?rTvSu-1kd3}wu4eL0ad+voN)4kn~rI`3Ax9w;0Cp5&=NxTLE1OXK* z^vRDDj9oJ)JDuTMrnzA&8}K%KErA1TWOkxeWu)@rs2c=*WI%|)Ik8G<7f;|3mr%`VS& zcXRjm_i>LQv~j}v)7lK=DeTTs$xShZ+8`=2l}L&v;{40OgV=E~`u7+LBU=U(`0B8u zki`T9o0MVYfbQHQvf$`}`@h;=lHUa(+m3L1kX zF2NE*peZdI)nDdgs-iFpJ_li3U!{GhbtIGydbOK9X*Jx_^%?x(9c?nSk@MDQOlbH$ z+iD!R*zyA|8Dj@u))9-M>6%=ekX(YuCF(L$eD_^^EoPoS5|>zwekl;piIe`-sDD($ z&2Q?=4p6DqGISn>#XKI3VcS>4iq8q_ww&xHEbW{xQ#te6%NXut9-1{BeA=rF~Bze&Mtf9yY))Fm5FD;o+Jdmn1WBSR1bEDOU zm+I}{kABid`BP0r{V4arL!87#7;WCbfi1L1&Q2RU^=D-0ITVZfz(vzxcCwrK(9S9% zsfbSgR*Y8y57F_3PB}dh6;HaYv4;MCLi3NT%{$h5bEKlYow&-(*?P^&dvoWo5ZJ*7 z-~Kx#A<$rJC!dw&rgP|GPu3hQh!1wp#rQ3mw0^hfe?S);t1u3(=O;9jTdRXji6OEM zlU=Vd_b_e*UoEdXyBp6wPO4C!!cI{Dk?RY15wBosM=u!Wiz_|A{sKXo*Re<~*}< zvb>(7Jpf;Mzp|j18~+bzpzv>bK13DR4P#u+2KT_pkSud)sSWv~7dFJOsosyJ!T8;2R0+P{Sw^8%DGi453(l;E!w&)th7HuVELe#1 zXbR3NIzi;BiMB%1Q-qH*aw)Ivm2LUWWkTROSp}(3?)z$}O74L*>bI~lVEeQGfs1=Y zL8&`tt-eI&D7ciM%+r(+*fFq=|LjNc~$*c6IzT_npj z9CIa-3|TdOPYhKV%8?F%#g)0)DkVsysrWzf<{w!bXdHq~C&NrVo?z||2G5Cz3K@O} zcL+AdYp2K(qFf&7{7F#2&w+Bp}*v5ne*x1G;a#I+Y z-JKi13k@#m?{ptLy#I#xvxdscoPBUyO11nTuw6W{2V5@%n!xcLs5tWOly)+Kc^@GY z*;gO<>^N-sWkg}t#FXqW@W3Db@@@1r>v&RKAaVb`v*CZ8Hq2iIJg1_BpRMP`)da+ObJTD>2FnCliQIIrRc)m7 zHZT+O0te4l?W`?oivD75B1vAUtG8yEeMiuEZe;ni=_ZvfR-rU=;>*5(?E!`l&7ZW9 zBf7W$y~OY`NNNbj;bn{09D>7GF$2D{HdH%-$iprmWhrhYm#nVZZQ{+B!|2;jWl&$` zGTxocW$j3s4ndhc*;@smd0oz}_1xO!Sj=fA2~*ZjXqdQ#pE|1^+VOSRgI%1Pc?dM) zOuy58uz>#tZT=1(xLyct9BBsS1d8pPLnEmwv&)byKPsMMT|Cb>%C5D#T}{9h0Dp8x zn;iLwx}wZ4kJ0C7Xa?cOI~qu4%iqD1j$+$$dSWTA0Etg^HKxb%OT35oZ~Zx;a78~> zGOB#d!bnalRqZZ@N*7=OuyJ-r6jGW!ZRu2eJ!~ZFgobi8Y%I`RM6~%JUe-d?yX{}6 z&EI_+Viy*$@DSP{1qio&6FjyVe(r^7{6jozI*DudFSH?6JePh#BZ=W?y(Mx$M5{wz zTAzM zmmH3t@E7&wSmnqUI1JqoXdb=#o$iAL{5NRxckc&WFN8LXFKbcE^>q1+txM(S-*zuR%N4KTI&j)w5Q2?yF8Ha0pF=CoNXImJgBqL}fg_l>@meOdl_BgumJ7R3 zAhHMai?{yONNBuYL;f>VYW^}XavlBESy$Er!!2UnPOWa64tN+oRptR0mA`NAgIk7R zgS=07^ZI!6K62>Tlz?qx7;@%AXH7iHhX(g}R0VxrL(W&-VH1otrQvSo#ZT|q&8@6) z{`hmYk#9jV!A?}v501S_7h>RUPTbPj`XP(j6jbE%`;s5FuYy10i$-5!u;Y_OW;I$O z1K9XhFrq?LZ(EudYL?wULC?U#88V>SOgZZdrNp(dky-wUP5S?c%|D9U{8wyh?(%8959eMHGh70VWd zlSC7z5V3GATBX(iX7DH7>V5q5rYLDrJGeu5qbp++kGzN=?O^31f5a%qnL*g*gBKBqXb?!XF{$wWIryWW z&W(*cHsd&QADiJ%ne_QTe!fxhbUhSh+cmus49?gU?yU%1tI-LS^XR_?_** z((?eR4ZByiM|irw24MH={r`mKA1$T+4h=!XZ$mTPk}W^n%m&rf<}e(7MbEe8LS1SR zJ&7IV(m~)ax&e7L_>MMl?mp{P;`jV>YX*_l!!wYfJ2so|1GMFm3Lzi7E)S8Cpvyg=Xt~X^w~Qza1bguFiwd ze7rVFSzU|J1RR|Y`98x_UW!NAz=PyN)B7b}>r~eox3i_ap*>KuXyX!?!Fzhld3rO+ zL66qV@B1VZA+CP%?Ci?-&Wgp|3GI2Mi3!0bhxT{+4;JxG>5ia4??m^Dv!gwyncwbP z{^#yOt*Q(wr!trLcxGgUF!Hl~0KF`D81$G5#68QuqX(`RqEdwmFg79Ogn|vF{z{36 z?B`VV5h`(?K9q^VmtKoM9^3(cc!$l1(y8K$mY#`{FB~>&3@ITYOZu8J*ybOWgk?-` za?pW*pJQlxHTLS)?e63TFJTiUnO-Y8xYHBpGDi2L{CoHT;lGQGF7f|}&A+O3e_+G2 z%or0Dr8LR8So3|oP)uq^z>{y)Th5S<`l>I9aX0QS*d%78o$jlE5T5=3y;*#U6Z%ms zz&WbTgVVl^-tlRqQ#r62Kce(Gk|VAm_Bw(4z$k3c(?> z`-Z>^;w0#*Fo>e!Z~LeKdlOvmDVmV!^X>uSctfyBmQ;C)6nMS>)g#Jv($bCEfoEZ)!yqvD~>XiS|7LQ2S$SVV9b*Sz*T8mc?U%_f7|V`9b75 zTyKwH3Gl3`msCGDy-b#g-yZL2wf!j7y{rD9l}wKt;7xyw|Hyaf*nC^}<3%EaN)k5y zZ3#DM&t5y$Wm2Z+H}Vi{$S@$!97PJ%b2D~ELSD&Q@-HGd zf$%gx{|8S+>r!<05{RqQlxP;zgFf6?UCRY5{e>FJw;d)pMz9u?o>8o?U+hOik@ z4Sb3xH`b!jy1Cl&7qyB1)QqU+G%76j`h)*hMi+tcNmztZs2Qzi>18FGG|zH?Xz)RO zB%=PFfo^L9-fex9`bteyg$i`wftMJ8ovlJR6hIAH&MH+OrC2t9Jrtw|s@W9X((~Pn zGm6pEag)Rx_e|4&s?8DtL;&DM!*mS_n{ldkF=wx71WK>^X7iG2~?_?agr=`s!-Cco?^|a5&G4J((c3EjUAW6BXNtg!YC!zl!kZK z$jB4%YYeD0b9HE>W4R04Ea0oP)xMqY=8B(cBCQHO*rLO$fK{)M_QZ9K=r#}BPlSBmbA*OW1plF zM2=U<4=-v*e+Zysc1aghc7Vp+-T{9`MF~Y7RkG$NBQV?>!-GpMb`%*u@XUYNmxI3R zs_vU?_lLlVYd}OgSBH@pW-T=1hf29PvM;>U?SwxBu6=?d=A0eg4Q7YzAAsvR>~EsZ zBU0a6EaQClg2c>UyKhWOXKSVEu>eZ7J$)r1xUK{puS~crgWd4i<#!=PSuZn#S&??d z6nO*0zP3C@lac`U9$eS#IHHjCs${8)hHq|AxQOP#rt$Gip-JCmxUT6-a`|X*UCyE- z3yPYX&VdSzyq_F-adBM_cjRcg+0lq~@Ec%d6@S(BJN+Uas?kfm^#7_|`q0J-wzdHC zI5H_Ab%XP%C|MIB;?>aqQdb+2jeeyZE#@t&L%brT^ABOu*E5@>`uxEK9GK7Md?1fp z{w`ht0$t2%Uuk%{$fb^RY^AO*U-eF`)3$NM42x2PWL-k`qkgxp>2So+0nP8WKF_)l z7W{|5WEJHR>mv__`k^bb@9oHT*NE1HilK4#O09@(z!^xdoPV52Vk^W z(w%ZRe%19m{8~MpQwVkW5Fm4#qg#MOKQ@kP4gZ-Y?ivsAJ0-?>R@UHdZbn*8 zOPr6M`kzfHvL{lR1Y6l6hBqBS12u$ttr$U%ev}bn)K=E0kehMWJV!SXW0w`9)Vy zbiD*F7O{zf$mQ(kbBr>4!ZhMVZ+I9oZ;Sc`7P8c_urpd5Rz>ToqJV>>&S6P83mDVq zbvc)_1f)zX^w-S+{6w4CLWOP5@u!3#lDQ$DDsQ&eo8GEoMfAL_)QmYcJeltqjFk;) z{UU0#HU`|P)vpehfoo^=MjlIlfQKq-QD*_yYV-rzK3~rg#BQPfhhzwHa*J-}-#$U* zQZ3LJz&$}#uWRH*4|j+(4dit2vIdg)k+cqcWIiSo`h4Oy?5!pzPoosUm^~L3MpLc~ z%NTGw`cpFT`NvN=2My*}W3t09VxK*>PRA^Z6zmpc>9_f$(SZ#-iHJrvj?CcsCd69< z51PnHINt|mvTX&uPP1c)@FO$P*F~^oFouV7tQc>VEJA;!z ziY7;d>QI2J_;X1Hc5M(4_C60uZjF-RS0d96iL&S^ydf2b*?Bkqhh%)r;*ZblM)g2| za72glo(J3Jl7agyCwp^3>PEA1r@(_bOcG?NXR}mq5b#)H`X!jZjL?!Gb!jw%&{YyZ z$y)q(bWE8Y>*<(D86k%qJoS+-VmY;4$UZvX%3EA&240To#RHMEgbdV)3)=HrCQEj- zZ90Xsy2qx4kg=>hL&uT`W4Ofmw+HQYzdW=&`)N8Z;WvacHmW)M{eFO>!*n0nsN<%S#O28v940=`rj4}dF1nYOh5&k-0R!7 z1y128u8$-;8{auZYA%1W45gN81kz9>9u~RWVidpS8?1BbSXSi>5lJQG*KFqNadZQD zShPTcb2*Z8MhuZB?X2UmvblX31=R}>c{8I*y;G~RVS!E|nl2*(k?|ITwph-)iN2z> zS(c%wX76pgsvqUJ**nwWFmRQI{o8_J$rsjnTE#qB^Mfzh$00OTh&4xiY{5ql6Hp&@ zO)CMUPS<7S4#q2!#Ph=PQG6K6T5?}j;iin*jLORRJwa1h71Q0A`Cf3#zsWfxPcN=Q5zd(t#U(XFc}SLl*K|S{jGf$MPv@OvZ^z?--BR8VUc3mmEq~0X zaWnm7g}j?)^#ljwob5RqObkC*-+(29`F>)jqrc0Vcf_>@Ta+NHn`k1)?kH@5>{lDb zZ%6HNLjhxA*~eM#Y~Dk*^dx48u20Qo4H~xhwqh-cftfF`7eDLIJGW5KpeL+6mA2X= zNyZn81JByc)RdMZ%esxY`kypE5W1C zK?4I$56$iTni{Zwl=%Lt{{z)Ym*CFX%D|jc;qahv{)P_S^VfacA&po{d+a;jqKPE^XUWU;=niwupt&MOJi74?*YkAP2*ZGmcmA?)r0}Kp%Rq??cyTY&}>zTVLSzRC$jnC?8J?zu0r%F=D0<9$)!le(!7x*ewwRB9=UHI5P1}?}&&}i=%{j zSZFmWOI|m4B<6~%eo$E6{th7~RzJ53LW5?8ld{v!$cAW#Tf@@a6IdULJ-g`9@Bm3o z3Xtk}svy_Y!TWFf!vh6eHzZ%RHv7jGv4fqU_)h1ZX5}h={4>=6-2d%0`C(v{3C?x_ z|Nim@4$3rZMCu`b{QTtcWyW9?z{T7DTX{#YpAM84Fcrt-h$4t{vRP5hV5n#sQz3l( zJLM^Xr75^PjtS-a2i}+?nrXI%iWGB+Xu|uH;PRYsO?_U6-#p-Q6-lN#CRbtyt?F?$ zoIh6*4U9O$x)G_}wZD6|J^LQ*5!x}o!WX}Ot6 zgtAbu%6PDL3klyNyb?mE-gF2Mk%I{;Iy1Qs`2tWOayCBNPXmfm%1lxoy_24KZ9Tqq zchLoD8#ovRVZG=CasKdRcWlW)qMFa@$7-jGv0~IL-ALTP>0Z__FIA$q)^*_;Q5N5A zL~3k?Ia8A-rW!Dk?&G9lDFYD}3S%Z>ryhLm6bIK`>-Z%$7@NhCl^X+ktaerz`9Wfx zpXn@&(0w{KdgH=r-!HG{ttw@>HsLpAecWlwOt7vVwRZzvSF$jC9Ft*{`Zj7&6|C`6iF=NmaFbN@RH-??r1FhZ!WN&&!pgF`pThm4E&!aOZG^RMl z_Wf+?87rJXPRaXBalDf!25co!Fsf832;y_SS1)1J zsLRqbY#M0^J`$L6suam@mx_1{v^6Tq>O5URh*fqYFziGTZf`6LPlxQb2}^rfxrABN z?R?kPdVZh{JPrR#3gsu&G-fwWPd4QqqG)JQJ(+-S`D!h+1R{s?9;&{_LNDNz^!A4O zWk#7zdcuj6hFW*m>E)nru-8WbLZr(Y^U)LC4mGl)p@Hx9IrQ+b0d!hrc!Ft+`4NMN z5W5VykqZqIWE~~y95i$PKz+ODq4R9dd>%27dUAB^tjJo~sbIOv66PmOp^8i@{34lg zEU`3Xfp^<@=wha;!8Gll|GF@Rh@Ns8S@v|@3-@b#tzHm1nsw1RTynWEB^=~P6qx4k z=PUW2n#aEPIwS5vG_8SA6$%OgmtWOGnU@WVrFWPqdM`n@%Jtmy*@Smk(g2q;6k=)| zB0V@31ukz{sJ4%DWP$D07D7x{UGI`OYD48Cr2o1+_G#+N!s49+hyR>1DN;Xm4} zLI8lzH(Al$hbPse(m}5=d;M5@^mrcOq(@BnFjh?~XEuoOZjcW(Has|X&kS8>-Q8p} zGOO%H-AGv^2~4~7hzlP)aE%6$V-Ri#jwL{eFUSnBb4Fe|RY|CJOOBV;b{spSmm1k> z0Bw7f(Sl?lj N~x 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

meO%_?~nmjnF8K3#4weV#uf2LG&TmF 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 Dm4_!U literal 0 HcmV?d00001 diff --git a/wire/testdata/block-00000000000000000021868c2cefc52a480d173c849412fe81c4e5ab806f94ab.blk b/wire/testdata/block-00000000000000000021868c2cefc52a480d173c849412fe81c4e5ab806f94ab.blk new file mode 100644 index 0000000000000000000000000000000000000000..cff5e0f35fea517b9d39d25d5978bc4e4e960368 GIT binary patch literal 2259447 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

nuAUR=Lk$gT;9D*v)sZQd*&CuOKlgcV?Arj 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ν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≷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⪼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%0A6X5Fh<#1`up%iHp{JTMtGsMh9!B^~HZ8*I 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

  • x# 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�^j{~&dU*Lzhz+C@u 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

    V%4dnpMl%4dTn%fpT^yl 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%0DVE;&5(CGxv4*Wkm@SGv~P#4xHqVL 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%0A$CclR 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�mA_qis8(UQ-qhO(Ie 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

    Z`ivyGs4k&yot&zGlnN$~{n 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⪙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�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�TSLR7c2p%9S^R0(>S+m6iM1; Date: Fri, 24 Jan 2020 19:38:09 -0800 Subject: [PATCH 0843/1056] wire/common: optimize Read/WriteVarInt --- wire/common.go | 73 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/wire/common.go b/wire/common.go index 42c1797b32..63b5ee0ddc 100644 --- a/wire/common.go +++ b/wire/common.go @@ -474,19 +474,22 @@ func writeElements(w io.Writer, elements ...interface{}) error { // ReadVarInt reads a variable length integer from r and returns it as a uint64. func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { - discriminant, err := binarySerializer.Uint8(r) - if err != nil { + buf := binarySerializer.Borrow() + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return 0, err } + discriminant := buf[0] var rv uint64 switch discriminant { case 0xff: - sv, err := binarySerializer.Uint64(r, littleEndian) - if err != nil { + if _, err := io.ReadFull(r, buf); err != nil { + binarySerializer.Return(buf) return 0, err } - rv = sv + rv = littleEndian.Uint64(buf) + binarySerializer.Return(buf) // The encoding is not canonical if the value could have been // encoded using fewer bytes. @@ -497,11 +500,12 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { } case 0xfe: - sv, err := binarySerializer.Uint32(r, littleEndian) - if err != nil { + if _, err := io.ReadFull(r, buf[:4]); err != nil { + binarySerializer.Return(buf) return 0, err } - rv = uint64(sv) + rv = uint64(littleEndian.Uint32(buf[:4])) + binarySerializer.Return(buf) // The encoding is not canonical if the value could have been // encoded using fewer bytes. @@ -512,11 +516,12 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { } case 0xfd: - sv, err := binarySerializer.Uint16(r, littleEndian) - if err != nil { + if _, err := io.ReadFull(r, buf[:2]); err != nil { + binarySerializer.Return(buf) return 0, err } - rv = uint64(sv) + rv = uint64(littleEndian.Uint16(buf[:2])) + binarySerializer.Return(buf) // The encoding is not canonical if the value could have been // encoded using fewer bytes. @@ -528,6 +533,7 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { default: rv = uint64(discriminant) + binarySerializer.Return(buf) } return rv, nil @@ -536,31 +542,40 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { // WriteVarInt serializes val to w using a variable number of bytes depending // on its value. func WriteVarInt(w io.Writer, pver uint32, val uint64) error { - if val < 0xfd { - return binarySerializer.PutUint8(w, uint8(val)) - } + buf := binarySerializer.Borrow() + switch { + case val < 0xfd: + buf[0] = uint8(val) + _, err := w.Write(buf[:1]) + binarySerializer.Return(buf) + return err - if val <= math.MaxUint16 { - err := binarySerializer.PutUint8(w, 0xfd) - if err != nil { - return err - } - return binarySerializer.PutUint16(w, littleEndian, uint16(val)) - } + case val <= math.MaxUint16: + buf[0] = 0xfd + littleEndian.PutUint16(buf[1:3], uint16(val)) + _, err := w.Write(buf[:3]) + binarySerializer.Return(buf) + return err - if val <= math.MaxUint32 { - err := binarySerializer.PutUint8(w, 0xfe) - if err != nil { + case val <= math.MaxUint32: + buf[0] = 0xfe + littleEndian.PutUint32(buf[1:5], uint32(val)) + _, err := w.Write(buf[:5]) + binarySerializer.Return(buf) + return err + + default: + buf[0] = 0xff + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } - return binarySerializer.PutUint32(w, littleEndian, uint32(val)) - } - err := binarySerializer.PutUint8(w, 0xff) - if err != nil { + littleEndian.PutUint64(buf, val) + _, err := w.Write(buf) + binarySerializer.Return(buf) return err } - return binarySerializer.PutUint64(w, littleEndian, val) } // VarIntSerializeSize returns the number of bytes it would take to serialize From 6275db9970c63b6a4860edd6f826c25779664fe3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:13 -0800 Subject: [PATCH 0844/1056] wire: introduce Read/WriteVarIntBuf to reuse buffers between invocations --- wire/bench_test.go | 108 +++++++++++++++++++++++++++++++++++++++++++++ wire/common.go | 33 ++++++++------ 2 files changed, 128 insertions(+), 13 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 296d1f4624..d88d2f6ab7 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -152,6 +152,114 @@ func BenchmarkReadVarInt9(b *testing.B) { } } +// BenchmarkWriteVarIntBuf1 performs a benchmark on how long it takes to write +// a single byte variable length integer. +func BenchmarkWriteVarIntBuf1(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + for i := 0; i < b.N; i++ { + WriteVarIntBuf(ioutil.Discard, 0, 1, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkWriteVarIntBuf3 performs a benchmark on how long it takes to write +// a three byte variable length integer. +func BenchmarkWriteVarIntBuf3(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + for i := 0; i < b.N; i++ { + WriteVarIntBuf(ioutil.Discard, 0, 65535, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkWriteVarIntBuf5 performs a benchmark on how long it takes to write +// a five byte variable length integer. +func BenchmarkWriteVarIntBuf5(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + for i := 0; i < b.N; i++ { + WriteVarIntBuf(ioutil.Discard, 0, 4294967295, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkWriteVarIntBuf9 performs a benchmark on how long it takes to write +// a nine byte variable length integer. +func BenchmarkWriteVarIntBuf9(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + for i := 0; i < b.N; i++ { + WriteVarIntBuf(ioutil.Discard, 0, 18446744073709551615, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkReadVarIntBuf1 performs a benchmark on how long it takes to read +// a single byte variable length integer. +func BenchmarkReadVarIntBuf1(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{0x01} + r := bytes.NewReader(buf) + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + ReadVarIntBuf(r, 0, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkReadVarIntBuf3 performs a benchmark on how long it takes to read +// a three byte variable length integer. +func BenchmarkReadVarIntBuf3(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{0x0fd, 0xff, 0xff} + r := bytes.NewReader(buf) + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + ReadVarIntBuf(r, 0, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkReadVarIntBuf5 performs a benchmark on how long it takes to read +// a five byte variable length integer. +func BenchmarkReadVarIntBuf5(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{0xfe, 0xff, 0xff, 0xff, 0xff} + r := bytes.NewReader(buf) + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + ReadVarIntBuf(r, 0, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkReadVarIntBuf9 performs a benchmark on how long it takes to read +// a nine byte variable length integer. +func BenchmarkReadVarIntBuf9(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} + r := bytes.NewReader(buf) + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + ReadVarIntBuf(r, 0, buffer) + } + binarySerializer.Return(buffer) +} + // BenchmarkReadVarStr4 performs a benchmark on how long it takes to read a // four byte variable length string. func BenchmarkReadVarStr4(b *testing.B) { diff --git a/wire/common.go b/wire/common.go index 63b5ee0ddc..a469233921 100644 --- a/wire/common.go +++ b/wire/common.go @@ -475,8 +475,17 @@ func writeElements(w io.Writer, elements ...interface{}) error { // ReadVarInt reads a variable length integer from r and returns it as a uint64. func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { buf := binarySerializer.Borrow() + n, err := ReadVarIntBuf(r, pver, buf) + binarySerializer.Return(buf) + return n, err +} + +// ReadVarIntBuf reads a variable length integer from r using a preallocated +// scratch buffer and returns it as a uint64. +// +// NOTE: buf MUST at least an 8-byte slice. +func ReadVarIntBuf(r io.Reader, pver uint32, buf []byte) (uint64, error) { if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return 0, err } discriminant := buf[0] @@ -485,11 +494,9 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { switch discriminant { case 0xff: if _, err := io.ReadFull(r, buf); err != nil { - binarySerializer.Return(buf) return 0, err } rv = littleEndian.Uint64(buf) - binarySerializer.Return(buf) // The encoding is not canonical if the value could have been // encoded using fewer bytes. @@ -501,11 +508,9 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { case 0xfe: if _, err := io.ReadFull(r, buf[:4]); err != nil { - binarySerializer.Return(buf) return 0, err } rv = uint64(littleEndian.Uint32(buf[:4])) - binarySerializer.Return(buf) // The encoding is not canonical if the value could have been // encoded using fewer bytes. @@ -517,11 +522,9 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { case 0xfd: if _, err := io.ReadFull(r, buf[:2]); err != nil { - binarySerializer.Return(buf) return 0, err } rv = uint64(littleEndian.Uint16(buf[:2])) - binarySerializer.Return(buf) // The encoding is not canonical if the value could have been // encoded using fewer bytes. @@ -533,7 +536,6 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { default: rv = uint64(discriminant) - binarySerializer.Return(buf) } return rv, nil @@ -543,37 +545,42 @@ func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { // on its value. func WriteVarInt(w io.Writer, pver uint32, val uint64) error { buf := binarySerializer.Borrow() + err := WriteVarIntBuf(w, pver, val, buf) + binarySerializer.Return(buf) + return err +} + +// WriteVarIntBuf serializes val to w using a variable number of bytes depending +// on its value using a preallocated scratch buffer. +// +// NOTE: buf MUST at least an 8-byte slice. +func WriteVarIntBuf(w io.Writer, pver uint32, val uint64, buf []byte) error { switch { case val < 0xfd: buf[0] = uint8(val) _, err := w.Write(buf[:1]) - binarySerializer.Return(buf) return err case val <= math.MaxUint16: buf[0] = 0xfd littleEndian.PutUint16(buf[1:3], uint16(val)) _, err := w.Write(buf[:3]) - binarySerializer.Return(buf) return err case val <= math.MaxUint32: buf[0] = 0xfe littleEndian.PutUint32(buf[1:5], uint32(val)) _, err := w.Write(buf[:5]) - binarySerializer.Return(buf) return err default: buf[0] = 0xff if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } littleEndian.PutUint64(buf, val) _, err := w.Write(buf) - binarySerializer.Return(buf) return err } } From e58aadc7b47776f0206d60bcba666f08f1b0b938 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:17 -0800 Subject: [PATCH 0845/1056] wire/msgtx: use Read/WriteVarIntBuf in tx serialization --- wire/msgtx.go | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index 7705504cc8..be1a0ced20 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -461,13 +461,22 @@ func (msg *MsgTx) Copy() *MsgTx { // See Deserialize for decoding transactions stored to disk, such as in a // database, as opposed to decoding transactions from the wire. func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { + buf := binarySerializer.Borrow() + err := msg.btcDecode(r, pver, enc, buf) + binarySerializer.Return(buf) + return err +} + +func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, + buf []byte) error { + version, err := binarySerializer.Uint32(r, littleEndian) if err != nil { return err } msg.Version = int32(version) - count, err := ReadVarInt(r, pver) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { return err } @@ -491,7 +500,7 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error // With the Segregated Witness specific fields decoded, we can // now read in the actual txin count. - count, err = ReadVarInt(r, pver) + count, err = ReadVarIntBuf(r, pver, buf) if err != nil { return err } @@ -553,7 +562,7 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error totalScriptSize += uint64(len(ti.SignatureScript)) } - count, err = ReadVarInt(r, pver) + count, err = ReadVarIntBuf(r, pver, buf) if err != nil { returnScriptBuffers() return err @@ -593,7 +602,7 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error // For each input, the witness is encoded as a stack // with one or more items. Therefore, we first read a // varint which encodes the number of stack items. - witCount, err := ReadVarInt(r, pver) + witCount, err := ReadVarIntBuf(r, pver, buf) if err != nil { returnScriptBuffers() return err @@ -733,6 +742,15 @@ func (msg *MsgTx) DeserializeNoWitness(r io.Reader) error { // See Serialize for encoding transactions to be stored to disk, such as in a // database, as opposed to encoding transactions for the wire. func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { + buf := binarySerializer.Borrow() + err := msg.btcEncode(w, pver, enc, buf) + binarySerializer.Return(buf) + return err +} + +func (msg *MsgTx) btcEncode(w io.Writer, pver uint32, enc MessageEncoding, + buf []byte) error { + err := binarySerializer.PutUint32(w, littleEndian, uint32(msg.Version)) if err != nil { return err @@ -754,7 +772,7 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error } count := uint64(len(msg.TxIn)) - err = WriteVarInt(w, pver, count) + err = WriteVarIntBuf(w, pver, count, buf) if err != nil { return err } @@ -767,7 +785,7 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error } count = uint64(len(msg.TxOut)) - err = WriteVarInt(w, pver, count) + err = WriteVarIntBuf(w, pver, count, buf) if err != nil { return err } @@ -791,7 +809,8 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error } } - return binarySerializer.PutUint32(w, littleEndian, msg.LockTime) + err = binarySerializer.PutUint32(w, littleEndian, msg.LockTime) + return err } // HasWitness returns false if none of the inputs within the transaction From e12d32d41cba3f87ba26b7ccaa9b20857e8a6ffb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:21 -0800 Subject: [PATCH 0846/1056] wire/msgtx: reuse tx-level buffer for version and locktime --- wire/msgtx.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index be1a0ced20..d0584c6003 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -470,11 +470,10 @@ func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, buf []byte) error { - version, err := binarySerializer.Uint32(r, littleEndian) - if err != nil { + if _, err := io.ReadFull(r, buf[:4]); err != nil { return err } - msg.Version = int32(version) + msg.Version = int32(littleEndian.Uint32(buf[:4])) count, err := ReadVarIntBuf(r, pver, buf) if err != nil { @@ -635,11 +634,11 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, } } - msg.LockTime, err = binarySerializer.Uint32(r, littleEndian) - if err != nil { + if _, err := io.ReadFull(r, buf[:4]); err != nil { returnScriptBuffers() return err } + msg.LockTime = littleEndian.Uint32(buf[:4]) // Create a single allocation to house all of the scripts and set each // input signature script and output public key script to the @@ -751,8 +750,8 @@ func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error func (msg *MsgTx) btcEncode(w io.Writer, pver uint32, enc MessageEncoding, buf []byte) error { - err := binarySerializer.PutUint32(w, littleEndian, uint32(msg.Version)) - if err != nil { + littleEndian.PutUint32(buf[:4], uint32(msg.Version)) + if _, err := w.Write(buf[:4]); err != nil { return err } @@ -772,7 +771,7 @@ func (msg *MsgTx) btcEncode(w io.Writer, pver uint32, enc MessageEncoding, } count := uint64(len(msg.TxIn)) - err = WriteVarIntBuf(w, pver, count, buf) + err := WriteVarIntBuf(w, pver, count, buf) if err != nil { return err } @@ -809,7 +808,8 @@ func (msg *MsgTx) btcEncode(w io.Writer, pver uint32, enc MessageEncoding, } } - err = binarySerializer.PutUint32(w, littleEndian, msg.LockTime) + littleEndian.PutUint32(buf[:4], msg.LockTime) + _, err = w.Write(buf[:4]) return err } From 7951aa5a97d7b28397e9f03f40771e592a20728c Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:25 -0800 Subject: [PATCH 0847/1056] wire/common: add optimized Read/WriteVarBytesBuf --- wire/common.go | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/wire/common.go b/wire/common.go index a469233921..e009debf4e 100644 --- a/wire/common.go +++ b/wire/common.go @@ -659,7 +659,25 @@ func WriteVarString(w io.Writer, pver uint32, str string) error { func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { - count, err := ReadVarInt(r, pver) + buf := binarySerializer.Borrow() + b, err := ReadVarBytesBuf(r, pver, buf, maxAllowed, fieldName) + binarySerializer.Return(buf) + return b, err +} + +// ReadVarBytesBuf reads a variable length byte array. A byte array is encoded +// as a varInt containing the length of the array followed by the bytes +// themselves. An error is returned if the length is greater than the +// passed maxAllowed parameter which helps protect against memory exhaustion +// attacks and forced panics through malformed messages. The fieldName +// parameter is only used for the error message so it provides more context in +// the error. If b is non-nil, the provided buffer will be used for serializing +// small values. Otherwise a buffer will be drawn from the binarySerializer's +// pool and return when the method finishes. +func ReadVarBytesBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, + fieldName string) ([]byte, error) { + + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { return nil, err } @@ -673,19 +691,32 @@ func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, return nil, messageError("ReadVarBytes", str) } - b := make([]byte, count) - _, err = io.ReadFull(r, b) + bytes := make([]byte, count) + _, err = io.ReadFull(r, bytes) if err != nil { return nil, err } - return b, nil + return bytes, nil } // WriteVarBytes serializes a variable length byte array to w as a varInt // containing the number of bytes, followed by the bytes themselves. func WriteVarBytes(w io.Writer, pver uint32, bytes []byte) error { + buf := binarySerializer.Borrow() + err := WriteVarBytesBuf(w, pver, bytes, buf) + binarySerializer.Return(buf) + return err +} + +// WriteVarBytesBuf serializes a variable length byte array to w as a varInt +// containing the number of bytes, followed by the bytes themselves. If b is +// non-nil, the provided buffer will be used for serializing small values. +// Otherwise a buffer will be drawn from the binarySerializer's pool and return +// when the method finishes. +func WriteVarBytesBuf(w io.Writer, pver uint32, bytes, buf []byte) error { slen := uint64(len(bytes)) - err := WriteVarInt(w, pver, slen) + + err := WriteVarIntBuf(w, pver, slen, buf) if err != nil { return err } From b1710129f61d40c75ef481b08c14a6f0796da9ad Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:32 -0800 Subject: [PATCH 0848/1056] wire/msgtx: introduce optimized read/writeOutPointBuf --- wire/bench_test.go | 38 +++++++++++++++++++++++++++++++++++ wire/msgtx.go | 49 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index d88d2f6ab7..9bed977169 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -326,6 +326,28 @@ func BenchmarkReadOutPoint(b *testing.B) { } } +// BenchmarkReadOutPointBuf performs a benchmark on how long it takes to read a +// transaction output point. +func BenchmarkReadOutPointBuf(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash + 0xff, 0xff, 0xff, 0xff, // Previous output index + } + r := bytes.NewReader(buf) + var op OutPoint + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + readOutPointBuf(r, 0, 0, &op, buffer) + } + binarySerializer.Return(buffer) +} + // BenchmarkWriteOutPoint performs a benchmark on how long it takes to write a // transaction output point. func BenchmarkWriteOutPoint(b *testing.B) { @@ -340,6 +362,22 @@ func BenchmarkWriteOutPoint(b *testing.B) { } } +// BenchmarkWriteOutPointBuf performs a benchmark on how long it takes to write a +// transaction output point. +func BenchmarkWriteOutPointBuf(b *testing.B) { + b.ReportAllocs() + + buf := binarySerializer.Borrow() + op := &OutPoint{ + Hash: chainhash.Hash{}, + Index: 0, + } + for i := 0; i < b.N; i++ { + writeOutPointBuf(ioutil.Discard, 0, 0, op, buf) + } + binarySerializer.Return(buf) +} + // BenchmarkReadTxOut performs a benchmark on how long it takes to read a // transaction output. func BenchmarkReadTxOut(b *testing.B) { diff --git a/wire/msgtx.go b/wire/msgtx.go index d0584c6003..64e9099484 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -968,25 +968,66 @@ func NewMsgTx(version int32) *MsgTx { } // readOutPoint reads the next sequence of bytes from r as an OutPoint. +// +// DEPRECATED: Use readOutPointBuf instead. func readOutPoint(r io.Reader, pver uint32, version int32, op *OutPoint) error { + buf := binarySerializer.Borrow() + err := readOutPointBuf(r, pver, version, op, buf) + binarySerializer.Return(buf) + return err +} + +// readOutPointBuf reads the next sequence of bytes from r as an OutPoint. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func readOutPointBuf(r io.Reader, pver uint32, version int32, op *OutPoint, + buf []byte) error { + _, err := io.ReadFull(r, op.Hash[:]) if err != nil { return err } - op.Index, err = binarySerializer.Uint32(r, littleEndian) + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + op.Index = littleEndian.Uint32(buf[:4]) + + return nil +} + +// WriteOutPoint encodes op to the bitcoin protocol encoding for an OutPoint to +// w. +func WriteOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { + buf := binarySerializer.Borrow() + err := writeOutPointBuf(w, pver, version, op, buf) + binarySerializer.Return(buf) return err } -// WriteOutPoint encodes op to the bitcoin protocol encoding for an OutPoint +// writeOutPointBuf encodes op to the bitcoin protocol encoding for an OutPoint // to w. -func WriteOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func writeOutPointBuf(w io.Writer, pver uint32, version int32, op *OutPoint, + buf []byte) error { + _, err := w.Write(op.Hash[:]) if err != nil { return err } - return binarySerializer.PutUint32(w, littleEndian, op.Index) + littleEndian.PutUint32(buf[:4], op.Index) + _, err = w.Write(buf[:4]) + return err } // readScript reads a variable length byte array that represents a transaction From d43d9d57a93055e93a8e452c0e96d8135ec1647d Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:39 -0800 Subject: [PATCH 0849/1056] wire/msgtx: introduce optimized writeTxInBuf --- wire/bench_test.go | 13 +++++++++++++ wire/msgtx.go | 22 +++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 9bed977169..6d7a577727 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -453,6 +453,19 @@ func BenchmarkWriteTxIn(b *testing.B) { } } +// BenchmarkWriteTxInBuf performs a benchmark on how long it takes to write +// a transaction input. +func BenchmarkWriteTxInBuf(b *testing.B) { + b.ReportAllocs() + + buf := binarySerializer.Borrow() + txIn := blockOne.Transactions[0].TxIn[0] + for i := 0; i < b.N; i++ { + writeTxInBuf(ioutil.Discard, 0, 0, txIn, buf) + } + binarySerializer.Return(buf) +} + // BenchmarkDeserializeTx performs a benchmark on how long it takes to // deserialize a small transaction. func BenchmarkDeserializeTxSmall(b *testing.B) { diff --git a/wire/msgtx.go b/wire/msgtx.go index 64e9099484..b1cdabfad5 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1081,17 +1081,33 @@ func readTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { // writeTxIn encodes ti to the bitcoin protocol encoding for a transaction // input (TxIn) to w. func writeTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { - err := WriteOutPoint(w, pver, version, &ti.PreviousOutPoint) + buf := binarySerializer.Borrow() + err := writeTxInBuf(w, pver, version, ti, buf) + binarySerializer.Return(buf) + return err +} + +// writeTxInBuf encodes ti to the bitcoin protocol encoding for a transaction +// input (TxIn) to w. If b is non-nil, the provided buffer will be used for +// serializing small values. Otherwise a buffer will be drawn from the +// binarySerializer's pool and return when the method finishes. +func writeTxInBuf(w io.Writer, pver uint32, version int32, ti *TxIn, + buf []byte) error { + + err := writeOutPointBuf(w, pver, version, &ti.PreviousOutPoint, buf) if err != nil { return err } - err = WriteVarBytes(w, pver, ti.SignatureScript) + err = WriteVarBytesBuf(w, pver, ti.SignatureScript, buf) if err != nil { return err } - return binarySerializer.PutUint32(w, littleEndian, ti.Sequence) + littleEndian.PutUint32(buf[:4], ti.Sequence) + _, err = w.Write(buf[:4]) + + return err } // ReadTxOut reads the next sequence of bytes from r as a transaction output From 4829ff793b5222c908043c57903ab69c4d6e4633 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:38:43 -0800 Subject: [PATCH 0850/1056] wire/msgtx: use writeTxInBuf in txn encoding --- wire/msgtx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index b1cdabfad5..231d5f0607 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -777,7 +777,7 @@ func (msg *MsgTx) btcEncode(w io.Writer, pver uint32, enc MessageEncoding, } for _, ti := range msg.TxIn { - err = writeTxIn(w, pver, msg.Version, ti) + err = writeTxInBuf(w, pver, msg.Version, ti, buf) if err != nil { return err } From 99f6488fa0f67783edfd28df08491e4d4d85bf92 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 30 Apr 2019 15:42:54 -0700 Subject: [PATCH 0851/1056] wire/msgtx: introduce optimized readScriptBuf --- wire/msgtx.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index 231d5f0607..5e9f5ed408 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1037,8 +1037,30 @@ func writeOutPointBuf(w io.Writer, pver uint32, version int32, op *OutPoint, // memory exhaustion attacks and forced panics through malformed messages. The // fieldName parameter is only used for the error message so it provides more // context in the error. +// +// DEPRECATED: Use readScriptBuf instead. func readScript(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { - count, err := ReadVarInt(r, pver) + buf := binarySerializer.Borrow() + b, err := readScriptBuf(r, pver, buf, maxAllowed, fieldName) + binarySerializer.Return(buf) + return b, err +} + +// readScript reads a variable length byte array that represents a transaction +// script. It is encoded as a varInt containing the length of the array +// followed by the bytes themselves. An error is returned if the length is +// greater than the passed maxAllowed parameter which helps protect against +// memory exhaustion attacks and forced panics through malformed messages. The +// fieldName parameter is only used for the error message so it provides more +// context in the error. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func readScriptBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, fieldName string) ([]byte, error) { + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { return nil, err } From 6f4a7a142af7bae21008a9ff8005071a9e69bd6b Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 30 Apr 2019 15:49:07 -0700 Subject: [PATCH 0852/1056] wire/msgtx: introduce optimized readTxInBuf --- wire/bench_test.go | 26 ++++++++++++++++++++++++++ wire/msgtx.go | 31 ++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 6d7a577727..c988df2f7a 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -442,6 +442,32 @@ func BenchmarkReadTxIn(b *testing.B) { } } +// BenchmarkReadTxInBuf performs a benchmark on how long it takes to read a +// transaction input. +func BenchmarkReadTxInBuf(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash + 0xff, 0xff, 0xff, 0xff, // Previous output index + 0x07, // Varint for length of signature script + 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script + 0xff, 0xff, 0xff, 0xff, // Sequence + } + r := bytes.NewReader(buf) + var txIn TxIn + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + readTxInBuf(r, 0, 0, &txIn, buffer) + scriptPool.Return(txIn.SignatureScript) + } + binarySerializer.Return(buffer) +} + // BenchmarkWriteTxIn performs a benchmark on how long it takes to write // a transaction input. func BenchmarkWriteTxIn(b *testing.B) { diff --git a/wire/msgtx.go b/wire/msgtx.go index 5e9f5ed408..55d7b09be5 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1085,19 +1085,44 @@ func readScriptBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, fiel // readTxIn reads the next sequence of bytes from r as a transaction input // (TxIn). +// +// DEPRECATED: Use readTxInBuf instead. func readTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { - err := readOutPoint(r, pver, version, &ti.PreviousOutPoint) + buf := binarySerializer.Borrow() + err := readTxInBuf(r, pver, version, ti, buf) + binarySerializer.Return(buf) + return err +} + +// readTxInBuf reads the next sequence of bytes from r as a transaction input +// (TxIn). +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func readTxInBuf(r io.Reader, pver uint32, version int32, ti *TxIn, + buf []byte) error { + + err := readOutPointBuf(r, pver, version, &ti.PreviousOutPoint, buf) if err != nil { return err } - ti.SignatureScript, err = readScript(r, pver, MaxMessagePayload, + ti.SignatureScript, err = readScriptBuf(r, pver, buf, MaxMessagePayload, "transaction input signature script") if err != nil { return err } - return readElement(r, &ti.Sequence) + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + + ti.Sequence = littleEndian.Uint32(buf[:4]) + + return nil } // writeTxIn encodes ti to the bitcoin protocol encoding for a transaction From 607eea193f2ce726b49f81f4fc17a0185391995f Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:41:11 -0800 Subject: [PATCH 0853/1056] wire/msgtx: use readTxInBuf in txn serialization --- wire/msgtx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index 55d7b09be5..669bb86093 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -553,7 +553,7 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // and needs to be returned to the pool on error. ti := &txIns[i] msg.TxIn[i] = ti - err = readTxIn(r, pver, msg.Version, ti) + err = readTxInBuf(r, pver, msg.Version, ti, buf) if err != nil { returnScriptBuffers() return err From 7c8844f56f9b95a70f4f0f581bd20e2900acf461 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:41:18 -0800 Subject: [PATCH 0854/1056] wire/msgtx: introduce optimized WriteTxOutBuf --- wire/bench_test.go | 13 +++++++++++++ wire/msgtx.go | 21 +++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index c988df2f7a..7d4a1dec97 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -418,6 +418,19 @@ func BenchmarkWriteTxOut(b *testing.B) { } } +// BenchmarkWriteTxOutBuf performs a benchmark on how long it takes to write +// a transaction output. +func BenchmarkWriteTxOutBuf(b *testing.B) { + b.ReportAllocs() + + buf := binarySerializer.Borrow() + txOut := blockOne.Transactions[0].TxOut[0] + for i := 0; i < b.N; i++ { + WriteTxOutBuf(ioutil.Discard, 0, 0, txOut, buf) + } + binarySerializer.Return(buf) +} + // BenchmarkReadTxIn performs a benchmark on how long it takes to read a // transaction input. func BenchmarkReadTxIn(b *testing.B) { diff --git a/wire/msgtx.go b/wire/msgtx.go index 669bb86093..669a6d3731 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1176,12 +1176,29 @@ func ReadTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { // NOTE: This function is exported in order to allow txscript to compute the // new sighashes for witness transactions (BIP0143). func WriteTxOut(w io.Writer, pver uint32, version int32, to *TxOut) error { - err := binarySerializer.PutUint64(w, littleEndian, uint64(to.Value)) + buf := binarySerializer.Borrow() + err := WriteTxOutBuf(w, pver, version, to, buf) + binarySerializer.Return(buf) + return err +} + +// WriteTxOutBuf encodes to into the bitcoin protocol encoding for a transaction +// output (TxOut) to w. If b is non-nil, the provided buffer will be used for +// serializing small values. Otherwise a buffer will be drawn from the +// binarySerializer's pool and return when the method finishes. +// +// NOTE: This function is exported in order to allow txscript to compute the +// new sighashes for witness transactions (BIP0143). +func WriteTxOutBuf(w io.Writer, pver uint32, version int32, to *TxOut, + buf []byte) error { + + littleEndian.PutUint64(buf, uint64(to.Value)) + _, err := w.Write(buf) if err != nil { return err } - return WriteVarBytes(w, pver, to.PkScript) + return WriteVarBytesBuf(w, pver, to.PkScript, buf) } // writeTxWitness encodes the bitcoin protocol encoding for a transaction From 48d31e59262dc005910bcc6f00a25bf4e86bd7b8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:41:26 -0800 Subject: [PATCH 0855/1056] wire/msgtx: use WriteTxOutBuf in txn serialization --- wire/msgtx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index 669a6d3731..d7a243ee0e 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -790,7 +790,7 @@ func (msg *MsgTx) btcEncode(w io.Writer, pver uint32, enc MessageEncoding, } for _, to := range msg.TxOut { - err = WriteTxOut(w, pver, msg.Version, to) + err = WriteTxOutBuf(w, pver, msg.Version, to, buf) if err != nil { return err } From aebc74398aaf8e8333d379c2dd6efad720f82b30 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:41:33 -0800 Subject: [PATCH 0856/1056] wire/msgtx: introduce optimized readTxOutBuf --- wire/bench_test.go | 31 +++++++++++++++++++++++++++++++ wire/msgtx.go | 18 ++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 7d4a1dec97..67535aeb53 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -407,6 +407,37 @@ func BenchmarkReadTxOut(b *testing.B) { } } +// BenchmarkReadTxOutBuf performs a benchmark on how long it takes to read a +// transaction output. +func BenchmarkReadTxOutBuf(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{ + 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount + 0x43, // Varint for length of pk script + 0x41, // OP_DATA_65 + 0x04, 0x96, 0xb5, 0x38, 0xe8, 0x53, 0x51, 0x9c, + 0x72, 0x6a, 0x2c, 0x91, 0xe6, 0x1e, 0xc1, 0x16, + 0x00, 0xae, 0x13, 0x90, 0x81, 0x3a, 0x62, 0x7c, + 0x66, 0xfb, 0x8b, 0xe7, 0x94, 0x7b, 0xe6, 0x3c, + 0x52, 0xda, 0x75, 0x89, 0x37, 0x95, 0x15, 0xd4, + 0xe0, 0xa6, 0x04, 0xf8, 0x14, 0x17, 0x81, 0xe6, + 0x22, 0x94, 0x72, 0x11, 0x66, 0xbf, 0x62, 0x1e, + 0x73, 0xa8, 0x2c, 0xbf, 0x23, 0x42, 0xc8, 0x58, + 0xee, // 65-byte signature + 0xac, // OP_CHECKSIG + } + r := bytes.NewReader(buf) + var txOut TxOut + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + readTxOutBuf(r, 0, 0, &txOut, buffer) + scriptPool.Return(txOut.PkScript) + } + binarySerializer.Return(buffer) +} + // BenchmarkWriteTxOut performs a benchmark on how long it takes to write // a transaction output. func BenchmarkWriteTxOut(b *testing.B) { diff --git a/wire/msgtx.go b/wire/msgtx.go index d7a243ee0e..945070ab4e 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1160,12 +1160,26 @@ func writeTxInBuf(w io.Writer, pver uint32, version int32, ti *TxIn, // ReadTxOut reads the next sequence of bytes from r as a transaction output // (TxOut). func ReadTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { - err := readElement(r, &to.Value) + buf := binarySerializer.Borrow() + err := readTxOutBuf(r, pver, version, to, buf) + binarySerializer.Return(buf) + return err +} + +// readTxOutBuf reads the next sequence of bytes from r as a transaction output +// (TxOut). If b is non-nil, the provided buffer will be used for serializing +// small values. Otherwise a buffer will be drawn from the binarySerializer's +// pool and return when the method finishes. +func readTxOutBuf(r io.Reader, pver uint32, version int32, to *TxOut, + buf []byte) error { + + _, err := io.ReadFull(r, buf) if err != nil { return err } + to.Value = int64(littleEndian.Uint64(buf)) - to.PkScript, err = readScript(r, pver, MaxMessagePayload, + to.PkScript, err = readScriptBuf(r, pver, buf, MaxMessagePayload, "transaction output public key script") return err } From 24d42177a29462d6b74cbddef27e909ecece10d8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:41:40 -0800 Subject: [PATCH 0857/1056] wire/msgtx: use readTxOutBuf in txn serialization --- wire/msgtx.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index 945070ab4e..14b3980e70 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -586,7 +586,8 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // and needs to be returned to the pool on error. to := &txOuts[i] msg.TxOut[i] = to - err = ReadTxOut(r, pver, msg.Version, to) + + err = readTxOutBuf(r, pver, msg.Version, to, buf) if err != nil { returnScriptBuffers() return err From 3bfd0c6cb34ea198f36d702130e11170831048f8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:41:47 -0800 Subject: [PATCH 0858/1056] wire/msgtx: introduce optimized writeTxWitnessBuf --- wire/msgtx.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index 14b3980e70..d71024fb5d 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1218,16 +1218,32 @@ func WriteTxOutBuf(w io.Writer, pver uint32, version int32, to *TxOut, // writeTxWitness encodes the bitcoin protocol encoding for a transaction // input's witness into to w. +// +// DEPRECATED: Use writeTxWitnessBuf instead. func writeTxWitness(w io.Writer, pver uint32, version int32, wit [][]byte) error { - err := WriteVarInt(w, pver, uint64(len(wit))) + buf := binarySerializer.Borrow() + err := writeTxWitnessBuf(w, pver, version, wit, buf) + binarySerializer.Return(buf) + return err +} + +// writeTxWitnessBuf encodes the bitcoin protocol encoding for a transaction +// input's witness into to w. If b is non-nil, the provided buffer will be used +// for serializing small values. Otherwise a buffer will be drawn from the +// binarySerializer's pool and return when the method finishes. +func writeTxWitnessBuf(w io.Writer, pver uint32, version int32, wit [][]byte, + buf []byte) error { + + err := WriteVarIntBuf(w, pver, uint64(len(wit)), buf) if err != nil { return err } for _, item := range wit { - err = WriteVarBytes(w, pver, item) + err = WriteVarBytesBuf(w, pver, item, buf) if err != nil { return err } } + return nil } From 3a91303a1a0181004e92b860795a798995711bc0 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:41:54 -0800 Subject: [PATCH 0859/1056] wire/msgtx: use writeTxWitnessBuf in txn serialization --- wire/msgtx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index d71024fb5d..c2c82be7c7 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -802,7 +802,7 @@ func (msg *MsgTx) btcEncode(w io.Writer, pver uint32, enc MessageEncoding, // within the transaction. if doWitness { for _, ti := range msg.TxIn { - err = writeTxWitness(w, pver, msg.Version, ti.Witness) + err = writeTxWitnessBuf(w, pver, msg.Version, ti.Witness, buf) if err != nil { return err } From 0cf8c19d5a3668d429d479c8a63d51f31d0b9d61 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:01 -0800 Subject: [PATCH 0860/1056] wire/msgtx: use readScriptBuf in txn serialization --- wire/msgtx.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index c2c82be7c7..e89ad7cb56 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -623,8 +623,9 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // item itself. txin.Witness = make([][]byte, witCount) for j := uint64(0); j < witCount; j++ { - txin.Witness[j], err = readScript( - r, pver, maxWitnessItemSize, "script witness item", + txin.Witness[j], err = readScriptBuf( + r, pver, buf, maxWitnessItemSize, + "script witness item", ) if err != nil { returnScriptBuffers() From aa769e3da667646b122a61edf0c3a4ae32bf4644 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:09 -0800 Subject: [PATCH 0861/1056] wire/bench_test: introduce optimized readBlockHeaderBuf --- wire/bench_test.go | 30 ++++++++++++++++++++++++++ wire/blockheader.go | 51 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 67535aeb53..140e376536 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -766,6 +766,36 @@ func BenchmarkReadBlockHeader(b *testing.B) { } } +// BenchmarkReadBlockHeaderBuf performs a benchmark on how long it takes to +// deserialize a block header. +func BenchmarkReadBlockHeaderBuf(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{ + 0x01, 0x00, 0x00, 0x00, // Version 1 + 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, + 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, + 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, + 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, // PrevBlock + 0x3b, 0xa3, 0xed, 0xfd, 0x7a, 0x7b, 0x12, 0xb2, + 0x7a, 0xc7, 0x2c, 0x3e, 0x67, 0x76, 0x8f, 0x61, + 0x7f, 0xc8, 0x1b, 0xc3, 0x88, 0x8a, 0x51, 0x32, + 0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, // MerkleRoot + 0x29, 0xab, 0x5f, 0x49, // Timestamp + 0xff, 0xff, 0x00, 0x1d, // Bits + 0xf3, 0xe0, 0x01, 0x00, // Nonce + 0x00, // TxnCount Varint + } + r := bytes.NewReader(buf) + var header BlockHeader + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + readBlockHeaderBuf(r, 0, &header, buffer) + } + binarySerializer.Return(buffer) +} + // BenchmarkWriteBlockHeader performs a benchmark on how long it takes to // serialize a block header. func BenchmarkWriteBlockHeader(b *testing.B) { diff --git a/wire/blockheader.go b/wire/blockheader.go index 9c9c2237e6..f954d56ac4 100644 --- a/wire/blockheader.go +++ b/wire/blockheader.go @@ -113,9 +113,56 @@ func NewBlockHeader(version int32, prevHash, merkleRootHash *chainhash.Hash, // readBlockHeader reads a bitcoin block header from r. See Deserialize for // decoding block headers stored to disk, such as in a database, as opposed to // decoding from the wire. +// +// DEPRECATED: Use readBlockHeaderBuf instead. func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error { - return readElements(r, &bh.Version, &bh.PrevBlock, &bh.MerkleRoot, - (*uint32Time)(&bh.Timestamp), &bh.Bits, &bh.Nonce) + buf := binarySerializer.Borrow() + err := readBlockHeaderBuf(r, pver, bh, buf) + binarySerializer.Return(buf) + return err +} + +// readBlockHeaderBuf reads a bitcoin block header from r. See Deserialize for +// decoding block headers stored to disk, such as in a database, as opposed to +// decoding from the wire. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func readBlockHeaderBuf(r io.Reader, pver uint32, bh *BlockHeader, + buf []byte) error { + + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + bh.Version = int32(littleEndian.Uint32(buf[:4])) + + if _, err := io.ReadFull(r, bh.PrevBlock[:]); err != nil { + return err + } + + if _, err := io.ReadFull(r, bh.MerkleRoot[:]); err != nil { + return err + } + + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + bh.Timestamp = time.Unix(int64(littleEndian.Uint32(buf[:4])), 0) + + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + bh.Bits = littleEndian.Uint32(buf[:4]) + + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + bh.Nonce = littleEndian.Uint32(buf[:4]) + + return nil } // writeBlockHeader writes a bitcoin block header to w. See Serialize for From 3cee06eaeb41026ee8128662d0d6c08d90d377b9 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:16 -0800 Subject: [PATCH 0862/1056] wire/blockheader: introduce optimized writeBlockHeaderBuf --- wire/bench_test.go | 13 ++++++++++++ wire/blockheader.go | 52 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 140e376536..3efd13f50a 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -807,6 +807,19 @@ func BenchmarkWriteBlockHeader(b *testing.B) { } } +// BenchmarkWriteBlockHeaderBuf performs a benchmark on how long it takes to +// serialize a block header. +func BenchmarkWriteBlockHeaderBuf(b *testing.B) { + b.ReportAllocs() + + buf := binarySerializer.Borrow() + header := blockOne.Header + for i := 0; i < b.N; i++ { + writeBlockHeaderBuf(ioutil.Discard, 0, &header, buf) + } + binarySerializer.Return(buf) +} + // BenchmarkDecodeGetHeaders performs a benchmark on how long it takes to // decode a getheaders message with the maximum number of block locator hashes. func BenchmarkDecodeGetHeaders(b *testing.B) { diff --git a/wire/blockheader.go b/wire/blockheader.go index f954d56ac4..081630f72f 100644 --- a/wire/blockheader.go +++ b/wire/blockheader.go @@ -168,8 +168,54 @@ func readBlockHeaderBuf(r io.Reader, pver uint32, bh *BlockHeader, // writeBlockHeader writes a bitcoin block header to w. See Serialize for // encoding block headers to be stored to disk, such as in a database, as // opposed to encoding for the wire. +// +// DEPRECATED: Use writeBlockHeaderBuf instead. func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error { - sec := uint32(bh.Timestamp.Unix()) - return writeElements(w, bh.Version, &bh.PrevBlock, &bh.MerkleRoot, - sec, bh.Bits, bh.Nonce) + buf := binarySerializer.Borrow() + err := writeBlockHeaderBuf(w, pver, bh, buf) + binarySerializer.Return(buf) + return err +} + +// writeBlockHeaderBuf writes a bitcoin block header to w. See Serialize for +// encoding block headers to be stored to disk, such as in a database, as +// opposed to encoding for the wire. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func writeBlockHeaderBuf(w io.Writer, pver uint32, bh *BlockHeader, + buf []byte) error { + + littleEndian.PutUint32(buf[:4], uint32(bh.Version)) + if _, err := w.Write(buf[:4]); err != nil { + return err + } + + if _, err := w.Write(bh.PrevBlock[:]); err != nil { + return err + } + + if _, err := w.Write(bh.MerkleRoot[:]); err != nil { + return err + } + + littleEndian.PutUint32(buf[:4], uint32(bh.Timestamp.Unix())) + if _, err := w.Write(buf[:4]); err != nil { + return err + } + + littleEndian.PutUint32(buf[:4], bh.Bits) + if _, err := w.Write(buf[:4]); err != nil { + return err + } + + littleEndian.PutUint32(buf[:4], bh.Nonce) + if _, err := w.Write(buf[:4]); err != nil { + return err + } + + return nil } From 674c2202ea44f951e1bfe6d5c0f36dda7c795499 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:23 -0800 Subject: [PATCH 0863/1056] wire/invvect: add optimized readInvVectBuf and writeInvVectBuf --- wire/invvect.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/wire/invvect.go b/wire/invvect.go index 1e706642b4..fb21243f86 100644 --- a/wire/invvect.go +++ b/wire/invvect.go @@ -76,11 +76,56 @@ func NewInvVect(typ InvType, hash *chainhash.Hash) *InvVect { // readInvVect reads an encoded InvVect from r depending on the protocol // version. +// +// DEPRECATED: Use readInvVectBuf instead. func readInvVect(r io.Reader, pver uint32, iv *InvVect) error { - return readElements(r, &iv.Type, &iv.Hash) + buf := binarySerializer.Borrow() + err := readInvVectBuf(r, pver, iv, buf) + binarySerializer.Return(buf) + return err +} + +// readInvVectBuf reads an encoded InvVect from r depending on the protocol +// version. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func readInvVectBuf(r io.Reader, pver uint32, iv *InvVect, buf []byte) error { + if _, err := io.ReadFull(r, buf[:4]); err != nil { + return err + } + iv.Type = InvType(littleEndian.Uint32(buf[:4])) + + _, err := io.ReadFull(r, iv.Hash[:]) + return err } // writeInvVect serializes an InvVect to w depending on the protocol version. +// +// DEPRECATED: Use writeInvVectBuf instead. func writeInvVect(w io.Writer, pver uint32, iv *InvVect) error { - return writeElements(w, iv.Type, &iv.Hash) + buf := binarySerializer.Borrow() + err := writeInvVectBuf(w, pver, iv, buf) + binarySerializer.Return(buf) + return err +} + +// writeInvVectBuf serializes an InvVect to w depending on the protocol version. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func writeInvVectBuf(w io.Writer, pver uint32, iv *InvVect, buf []byte) error { + littleEndian.PutUint32(buf[:4], uint32(iv.Type)) + if _, err := w.Write(buf[:4]); err != nil { + return err + } + + _, err := w.Write(iv.Hash[:]) + return err } From 4ebc65168988422d4176f709d23c3366f86004f3 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:30 -0800 Subject: [PATCH 0864/1056] wire/msggetblocks: optimize by reusing small buffer --- wire/msggetblocks.go | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/wire/msggetblocks.go b/wire/msggetblocks.go index caf4400ca4..b6943be415 100644 --- a/wire/msggetblocks.go +++ b/wire/msggetblocks.go @@ -51,16 +51,21 @@ func (msg *MsgGetBlocks) AddBlockLocatorHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - err := readElement(r, &msg.ProtocolVersion) - if err != nil { + buf := binarySerializer.Borrow() + if _, err := io.ReadFull(r, buf[:4]); err != nil { + binarySerializer.Return(buf) return err } + msg.ProtocolVersion = littleEndian.Uint32(buf[:4]) // Read num block locator hashes and limit to max. - count, err := ReadVarInt(r, pver) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) + if count > MaxBlockLocatorsPerMsg { str := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) @@ -73,14 +78,15 @@ func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding msg.BlockLocatorHashes = make([]*chainhash.Hash, 0, count) for i := uint64(0); i < count; i++ { hash := &locatorHashes[i] - err := readElement(r, hash) + _, err := io.ReadFull(r, hash[:]) if err != nil { return err } msg.AddBlockLocatorHash(hash) } - return readElement(r, &msg.HashStop) + _, err = io.ReadFull(r, msg.HashStop[:]) + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -93,24 +99,29 @@ func (msg *MsgGetBlocks) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding return messageError("MsgGetBlocks.BtcEncode", str) } - err := writeElement(w, msg.ProtocolVersion) - if err != nil { + buf := binarySerializer.Borrow() + littleEndian.PutUint32(buf[:4], msg.ProtocolVersion) + if _, err := w.Write(buf[:4]); err != nil { + binarySerializer.Return(buf) return err } - err = WriteVarInt(w, pver, uint64(count)) + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) for _, hash := range msg.BlockLocatorHashes { - err = writeElement(w, hash) + _, err := w.Write(hash[:]) if err != nil { return err } } - return writeElement(w, &msg.HashStop) + _, err = w.Write(msg.HashStop[:]) + return err } // Command returns the protocol command string for the message. This is part From ee1f8077d81d3f8fc3418b26eafb16fadd3ea3ec Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:37 -0800 Subject: [PATCH 0865/1056] wire/msgblock: use only one small buffer per block encode/decode --- wire/msgblock.go | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/wire/msgblock.go b/wire/msgblock.go index 4172949dc3..31c9cfe403 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -62,13 +62,17 @@ func (msg *MsgBlock) ClearTransactions() { // See Deserialize for decoding blocks stored to disk, such as in a database, as // opposed to decoding blocks from the wire. func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - err := readBlockHeader(r, pver, &msg.Header) + buf := binarySerializer.Borrow() + + err := readBlockHeaderBuf(r, pver, &msg.Header, buf) if err != nil { + binarySerializer.Return(buf) return err } - txCount, err := ReadVarInt(r, pver) + txCount, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } @@ -76,6 +80,7 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) er // It would be possible to cause memory exhaustion and panics without // a sane upper bound on this count. if txCount > maxTxPerBlock { + binarySerializer.Return(buf) str := fmt.Sprintf("too many transactions to fit into a block "+ "[count %d, max %d]", txCount, maxTxPerBlock) return messageError("MsgBlock.BtcDecode", str) @@ -84,13 +89,16 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) er msg.Transactions = make([]*MsgTx, 0, txCount) for i := uint64(0); i < txCount; i++ { tx := MsgTx{} - err := tx.BtcDecode(r, pver, enc) + err := tx.btcDecode(r, pver, enc, buf) if err != nil { + binarySerializer.Return(buf) return err } msg.Transactions = append(msg.Transactions, &tx) } + binarySerializer.Return(buf) + return nil } @@ -174,23 +182,30 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { // See Serialize for encoding blocks to be stored to disk, such as in a // database, as opposed to encoding blocks for the wire. func (msg *MsgBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { - err := writeBlockHeader(w, pver, &msg.Header) + buf := binarySerializer.Borrow() + + err := writeBlockHeaderBuf(w, pver, &msg.Header, buf) if err != nil { + binarySerializer.Return(buf) return err } - err = WriteVarInt(w, pver, uint64(len(msg.Transactions))) + err = WriteVarIntBuf(w, pver, uint64(len(msg.Transactions)), buf) if err != nil { + binarySerializer.Return(buf) return err } for _, tx := range msg.Transactions { - err = tx.BtcEncode(w, pver, enc) + err = tx.btcEncode(w, pver, enc, buf) if err != nil { + binarySerializer.Return(buf) return err } } + binarySerializer.Return(buf) + return nil } From d8e08170bdb5469374fe810c7f2623f64c77146a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:44 -0800 Subject: [PATCH 0866/1056] wire/msgblock: optimize DeserializeTxLoc by reusing small buffers --- wire/msgblock.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/wire/msgblock.go b/wire/msgblock.go index 31c9cfe403..34b52f08ef 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -137,16 +137,20 @@ func (msg *MsgBlock) DeserializeNoWitness(r io.Reader) error { func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { fullLen := r.Len() + buf := binarySerializer.Borrow() + // At the current time, there is no difference between the wire encoding // at protocol version 0 and the stable long-term storage format. As // a result, make use of existing wire protocol functions. - err := readBlockHeader(r, 0, &msg.Header) + err := readBlockHeaderBuf(r, 0, &msg.Header, buf) if err != nil { + binarySerializer.Return(buf) return nil, err } - txCount, err := ReadVarInt(r, 0) + txCount, err := ReadVarIntBuf(r, 0, buf) if err != nil { + binarySerializer.Return(buf) return nil, err } @@ -154,6 +158,7 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { // It would be possible to cause memory exhaustion and panics without // a sane upper bound on this count. if txCount > maxTxPerBlock { + binarySerializer.Return(buf) str := fmt.Sprintf("too many transactions to fit into a block "+ "[count %d, max %d]", txCount, maxTxPerBlock) return nil, messageError("MsgBlock.DeserializeTxLoc", str) @@ -166,14 +171,17 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { for i := uint64(0); i < txCount; i++ { txLocs[i].TxStart = fullLen - r.Len() tx := MsgTx{} - err := tx.Deserialize(r) + err := tx.btcDecode(r, 0, WitnessEncoding, buf) if err != nil { + binarySerializer.Return(buf) return nil, err } msg.Transactions = append(msg.Transactions, &tx) txLocs[i].TxLen = (fullLen - r.Len()) - txLocs[i].TxStart } + binarySerializer.Return(buf) + return txLocs, nil } From c0d35e6d920662e3608907af1cc2d43f2487adcd Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:42:52 -0800 Subject: [PATCH 0867/1056] wire/msggetheaders: optimize serialization by reusing small buffers --- wire/msggetheaders.go | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/wire/msggetheaders.go b/wire/msggetheaders.go index 0bbe42cb03..dba6eebcc4 100644 --- a/wire/msggetheaders.go +++ b/wire/msggetheaders.go @@ -48,16 +48,20 @@ func (msg *MsgGetHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - err := readElement(r, &msg.ProtocolVersion) - if err != nil { + buf := binarySerializer.Borrow() + if _, err := io.ReadFull(r, buf[:4]); err != nil { + binarySerializer.Return(buf) return err } + msg.ProtocolVersion = littleEndian.Uint32(buf[:4]) // Read num block locator hashes and limit to max. - count, err := ReadVarInt(r, pver) + count, err := ReadVarIntBuf(r, pver, buf) + binarySerializer.Return(buf) if err != nil { return err } + if count > MaxBlockLocatorsPerMsg { str := fmt.Sprintf("too many block locator hashes for message "+ "[count %v, max %v]", count, MaxBlockLocatorsPerMsg) @@ -70,14 +74,15 @@ func (msg *MsgGetHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncodin msg.BlockLocatorHashes = make([]*chainhash.Hash, 0, count) for i := uint64(0); i < count; i++ { hash := &locatorHashes[i] - err := readElement(r, hash) + _, err := io.ReadFull(r, hash[:]) if err != nil { return err } msg.AddBlockLocatorHash(hash) } - return readElement(r, &msg.HashStop) + _, err = io.ReadFull(r, msg.HashStop[:]) + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -91,24 +96,28 @@ func (msg *MsgGetHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncodin return messageError("MsgGetHeaders.BtcEncode", str) } - err := writeElement(w, msg.ProtocolVersion) - if err != nil { + buf := binarySerializer.Borrow() + littleEndian.PutUint32(buf[:4], msg.ProtocolVersion) + if _, err := w.Write(buf[:4]); err != nil { + binarySerializer.Return(buf) return err } - err = WriteVarInt(w, pver, uint64(count)) + err := WriteVarIntBuf(w, pver, uint64(count), buf) + binarySerializer.Return(buf) if err != nil { return err } for _, hash := range msg.BlockLocatorHashes { - err := writeElement(w, hash) + _, err := w.Write(hash[:]) if err != nil { return err } } - return writeElement(w, &msg.HashStop) + _, err = w.Write(msg.HashStop[:]) + return err } // Command returns the protocol command string for the message. This is part From 83675cb393d9b76d776ef0bdd40fbffd89bfac99 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:00 -0800 Subject: [PATCH 0868/1056] wire/msgheaders: optimize serialization by reusing small buffers --- wire/msgheaders.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/wire/msgheaders.go b/wire/msgheaders.go index 7d18d930e0..d735c911c1 100644 --- a/wire/msgheaders.go +++ b/wire/msgheaders.go @@ -37,13 +37,16 @@ func (msg *MsgHeaders) AddBlockHeader(bh *BlockHeader) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - count, err := ReadVarInt(r, pver) + buf := binarySerializer.Borrow() + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } // Limit to max block headers per message. if count > MaxBlockHeadersPerMsg { + binarySerializer.Return(buf) str := fmt.Sprintf("too many block headers for message "+ "[count %v, max %v]", count, MaxBlockHeadersPerMsg) return messageError("MsgHeaders.BtcDecode", str) @@ -55,18 +58,21 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) msg.Headers = make([]*BlockHeader, 0, count) for i := uint64(0); i < count; i++ { bh := &headers[i] - err := readBlockHeader(r, pver, bh) + err := readBlockHeaderBuf(r, pver, bh, buf) if err != nil { + binarySerializer.Return(buf) return err } - txCount, err := ReadVarInt(r, pver) + txCount, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } // Ensure the transaction count is zero for headers. if txCount > 0 { + binarySerializer.Return(buf) str := fmt.Sprintf("block headers may not contain "+ "transactions [count %v]", txCount) return messageError("MsgHeaders.BtcDecode", str) @@ -74,6 +80,8 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) msg.AddBlockHeader(bh) } + binarySerializer.Return(buf) + return nil } @@ -88,14 +96,17 @@ func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) return messageError("MsgHeaders.BtcEncode", str) } - err := WriteVarInt(w, pver, uint64(count)) + buf := binarySerializer.Borrow() + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { + binarySerializer.Return(buf) return err } for _, bh := range msg.Headers { - err := writeBlockHeader(w, pver, bh) + err := writeBlockHeaderBuf(w, pver, bh, buf) if err != nil { + binarySerializer.Return(buf) return err } @@ -103,12 +114,15 @@ func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) // of transactions on header messages. This is really just an // artifact of the way the original implementation serializes // block headers, but it is required. - err = WriteVarInt(w, pver, 0) + err = WriteVarIntBuf(w, pver, 0, buf) if err != nil { + binarySerializer.Return(buf) return err } } + binarySerializer.Return(buf) + return nil } From d042fe0586fd9b74c342bd8717a265965200be41 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:09 -0800 Subject: [PATCH 0869/1056] wire/msggetcfheaders: use single small buffer for encode/decode --- wire/msggetcfheaders.go | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index 03a1caf72f..1b1a904b44 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -22,33 +22,43 @@ type MsgGetCFHeaders struct { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - err := readElement(r, &msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + msg.FilterType = FilterType(buf[0]) - err = readElement(r, &msg.StartHeight) - if err != nil { + if _, err := io.ReadFull(r, buf[:4]); err != nil { + binarySerializer.Return(buf) return err } + msg.StartHeight = littleEndian.Uint32(buf[:4]) + binarySerializer.Return(buf) - return readElement(r, &msg.StopHash) + _, err := io.ReadFull(r, msg.StopHash[:]) + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - err := writeElement(w, msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + buf[0] = byte(msg.FilterType) + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } - err = writeElement(w, &msg.StartHeight) - if err != nil { + littleEndian.PutUint32(buf[:4], msg.StartHeight) + if _, err := w.Write(buf[:4]); err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) - return writeElement(w, &msg.StopHash) + _, err := w.Write(msg.StopHash[:]) + return err } // Command returns the protocol command string for the message. This is part From 1c525dbd0e7aa3682051a2aa090d34a9276ba91a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:16 -0800 Subject: [PATCH 0870/1056] wire/msgcfheaders: optimize encode/decode by using one small buffer --- wire/msgcfheaders.go | 59 +++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 40d30f9b46..644cf36a94 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -48,29 +48,34 @@ func (msg *MsgCFHeaders) AddCFHash(hash *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + buf := binarySerializer.Borrow() + // Read filter type - err := readElement(r, &msg.FilterType) - if err != nil { + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + msg.FilterType = FilterType(buf[0]) // Read stop hash - err = readElement(r, &msg.StopHash) - if err != nil { + if _, err := io.ReadFull(r, msg.StopHash[:]); err != nil { + binarySerializer.Return(buf) return err } // Read prev filter header - err = readElement(r, &msg.PrevFilterHeader) - if err != nil { + if _, err := io.ReadFull(r, msg.PrevFilterHeader[:]); err != nil { + binarySerializer.Return(buf) return err } // Read number of filter headers - count, err := ReadVarInt(r, pver) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) // Limit to max committed filter headers per message. if count > MaxCFHeadersPerMsg { @@ -85,7 +90,7 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) msg.FilterHashes = make([]*chainhash.Hash, 0, count) for i := uint64(0); i < count; i++ { var cfh chainhash.Hash - err := readElement(r, &cfh) + _, err := io.ReadFull(r, cfh[:]) if err != nil { return err } @@ -98,40 +103,44 @@ func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + count := len(msg.FilterHashes) + if count > MaxCFHeadersPerMsg { + str := fmt.Sprintf("too many committed filter headers for "+ + "message [count %v, max %v]", count, + MaxBlockHeadersPerMsg) + return messageError("MsgCFHeaders.BtcEncode", str) + } + + buf := binarySerializer.Borrow() + // Write filter type - err := writeElement(w, msg.FilterType) - if err != nil { + buf[0] = byte(msg.FilterType) + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } // Write stop hash - err = writeElement(w, msg.StopHash) - if err != nil { + if _, err := w.Write(msg.StopHash[:]); err != nil { + binarySerializer.Return(buf) return err } // Write prev filter header - err = writeElement(w, msg.PrevFilterHeader) - if err != nil { + if _, err := w.Write(msg.PrevFilterHeader[:]); err != nil { + binarySerializer.Return(buf) return err } - // Limit to max committed headers per message. - count := len(msg.FilterHashes) - if count > MaxCFHeadersPerMsg { - str := fmt.Sprintf("too many committed filter headers for "+ - "message [count %v, max %v]", count, - MaxBlockHeadersPerMsg) - return messageError("MsgCFHeaders.BtcEncode", str) - } - - err = WriteVarInt(w, pver, uint64(count)) + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) for _, cfh := range msg.FilterHashes { - err := writeElement(w, cfh) + _, err := w.Write(cfh[:]) if err != nil { return err } From 1990555eee2fd1f5c006d4ba668b5c2156a10f93 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:23 -0800 Subject: [PATCH 0871/1056] wire/msggetcfcheckpt: optimize by removing read/writeElement --- wire/msggetcfcheckpt.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/wire/msggetcfcheckpt.go b/wire/msggetcfcheckpt.go index c30a86cecd..c503fa24e0 100644 --- a/wire/msggetcfcheckpt.go +++ b/wire/msggetcfcheckpt.go @@ -21,23 +21,31 @@ type MsgGetCFCheckpt struct { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - err := readElement(r, &msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + msg.FilterType = FilterType(buf[0]) + binarySerializer.Return(buf) - return readElement(r, &msg.StopHash) + _, err := io.ReadFull(r, msg.StopHash[:]) + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - err := writeElement(w, msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + buf[0] = byte(msg.FilterType) + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) - return writeElement(w, &msg.StopHash) + _, err := w.Write(msg.StopHash[:]) + return err } // Command returns the protocol command string for the message. This is part From f37f4750dcffda3e6be2929d35e59fa8ac3b2614 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:30 -0800 Subject: [PATCH 0872/1056] wire/msgcfcheckpt: optimize serialization by reusing small buffers --- wire/msgcfcheckpt.go | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/wire/msgcfcheckpt.go b/wire/msgcfcheckpt.go index fc3fd53295..da13666180 100644 --- a/wire/msgcfcheckpt.go +++ b/wire/msgcfcheckpt.go @@ -52,23 +52,28 @@ func (msg *MsgCFCheckpt) AddCFHeader(header *chainhash.Hash) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { + buf := binarySerializer.Borrow() + // Read filter type - err := readElement(r, &msg.FilterType) - if err != nil { + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + msg.FilterType = FilterType(buf[0]) // Read stop hash - err = readElement(r, &msg.StopHash) - if err != nil { + if _, err := io.ReadFull(r, msg.StopHash[:]); err != nil { + binarySerializer.Return(buf) return err } // Read number of filter headers - count, err := ReadVarInt(r, pver) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) // Refuse to decode an insane number of cfheaders. if count > maxCFHeadersLen { @@ -80,7 +85,7 @@ func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) msg.FilterHeaders = make([]*chainhash.Hash, count) for i := uint64(0); i < count; i++ { var cfh chainhash.Hash - err := readElement(r, &cfh) + _, err := io.ReadFull(r, cfh[:]) if err != nil { return err } @@ -93,27 +98,32 @@ func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { + buf := binarySerializer.Borrow() + // Write filter type - err := writeElement(w, msg.FilterType) - if err != nil { + buf[0] = byte(msg.FilterType) + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } // Write stop hash - err = writeElement(w, msg.StopHash) - if err != nil { + if _, err := w.Write(msg.StopHash[:]); err != nil { + binarySerializer.Return(buf) return err } // Write length of FilterHeaders slice count := len(msg.FilterHeaders) - err = WriteVarInt(w, pver, uint64(count)) + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) for _, cfh := range msg.FilterHeaders { - err := writeElement(w, cfh) + _, err := w.Write(cfh[:]) if err != nil { return err } From 2383a049775029a07253b760573620d767bd9dbb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:37 -0800 Subject: [PATCH 0873/1056] wire/msginv: optimize by reusing small buffers --- wire/msginv.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/wire/msginv.go b/wire/msginv.go index 5377b179c3..83216ea8c5 100644 --- a/wire/msginv.go +++ b/wire/msginv.go @@ -46,13 +46,16 @@ func (msg *MsgInv) AddInvVect(iv *InvVect) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - count, err := ReadVarInt(r, pver) + buf := binarySerializer.Borrow() + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } // Limit to max inventory vectors per message. if count > MaxInvPerMsg { + binarySerializer.Return(buf) str := fmt.Sprintf("too many invvect in message [%v]", count) return messageError("MsgInv.BtcDecode", str) } @@ -63,12 +66,14 @@ func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) erro msg.InvList = make([]*InvVect, 0, count) for i := uint64(0); i < count; i++ { iv := &invList[i] - err := readInvVect(r, pver, iv) + err := readInvVectBuf(r, pver, iv, buf) if err != nil { + binarySerializer.Return(buf) return err } msg.AddInvVect(iv) } + binarySerializer.Return(buf) return nil } @@ -83,17 +88,21 @@ func (msg *MsgInv) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) erro return messageError("MsgInv.BtcEncode", str) } - err := WriteVarInt(w, pver, uint64(count)) + buf := binarySerializer.Borrow() + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { + binarySerializer.Return(buf) return err } for _, iv := range msg.InvList { - err := writeInvVect(w, pver, iv) + err := writeInvVectBuf(w, pver, iv, buf) if err != nil { + binarySerializer.Return(buf) return err } } + binarySerializer.Return(buf) return nil } From d6594daa49163d01829eba11b4eab789b4818000 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:45 -0800 Subject: [PATCH 0874/1056] wire/msggetdata: optimize serialization by reusing small buffers --- wire/msggetdata.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/wire/msggetdata.go b/wire/msggetdata.go index 5837fac5ba..da4de87d95 100644 --- a/wire/msggetdata.go +++ b/wire/msggetdata.go @@ -38,13 +38,16 @@ func (msg *MsgGetData) AddInvVect(iv *InvVect) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetData) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - count, err := ReadVarInt(r, pver) + buf := binarySerializer.Borrow() + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } // Limit to max inventory vectors per message. if count > MaxInvPerMsg { + binarySerializer.Return(buf) str := fmt.Sprintf("too many invvect in message [%v]", count) return messageError("MsgGetData.BtcDecode", str) } @@ -55,12 +58,14 @@ func (msg *MsgGetData) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) msg.InvList = make([]*InvVect, 0, count) for i := uint64(0); i < count; i++ { iv := &invList[i] - err := readInvVect(r, pver, iv) + err := readInvVectBuf(r, pver, iv, buf) if err != nil { + binarySerializer.Return(buf) return err } msg.AddInvVect(iv) } + binarySerializer.Return(buf) return nil } @@ -75,17 +80,21 @@ func (msg *MsgGetData) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) return messageError("MsgGetData.BtcEncode", str) } - err := WriteVarInt(w, pver, uint64(count)) + buf := binarySerializer.Borrow() + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { + binarySerializer.Return(buf) return err } for _, iv := range msg.InvList { - err := writeInvVect(w, pver, iv) + err := writeInvVectBuf(w, pver, iv, buf) if err != nil { + binarySerializer.Return(buf) return err } } + binarySerializer.Return(buf) return nil } From ddeba6002692d2d51fae77de027b383e8e6a3918 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:43:54 -0800 Subject: [PATCH 0875/1056] wiree/msggetcfilters: optimize serialization by reusing small buffers --- wire/msggetcfilters.go | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/wire/msggetcfilters.go b/wire/msggetcfilters.go index 8002413826..ba76b653ba 100644 --- a/wire/msggetcfilters.go +++ b/wire/msggetcfilters.go @@ -26,33 +26,43 @@ type MsgGetCFilters struct { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgGetCFilters) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { - err := readElement(r, &msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + msg.FilterType = FilterType(buf[0]) - err = readElement(r, &msg.StartHeight) - if err != nil { + if _, err := io.ReadFull(r, buf[:4]); err != nil { + binarySerializer.Return(buf) return err } + msg.StartHeight = littleEndian.Uint32(buf[:4]) + binarySerializer.Return(buf) - return readElement(r, &msg.StopHash) + _, err := io.ReadFull(r, msg.StopHash[:]) + return err } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgGetCFilters) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { - err := writeElement(w, msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + buf[0] = byte(msg.FilterType) + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } - err = writeElement(w, &msg.StartHeight) - if err != nil { + littleEndian.PutUint32(buf[:4], msg.StartHeight) + if _, err := w.Write(buf[:4]); err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) - return writeElement(w, &msg.StopHash) + _, err := w.Write(msg.StopHash[:]) + return err } // Command returns the protocol command string for the message. This is part From 834febbb862a5727ec9079acc20eb83305c04ec9 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:02 -0800 Subject: [PATCH 0876/1056] wire/msgcfilter: optimize serialization by reusing small buffers --- wire/msgcfilter.go | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index 097590b2ce..d691013bda 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -38,20 +38,24 @@ type MsgCFilter struct { // This is part of the Message interface implementation. func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { // Read filter type - err := readElement(r, &msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + msg.FilterType = FilterType(buf[0]) // Read the hash of the filter's block - err = readElement(r, &msg.BlockHash) - if err != nil { + if _, err := io.ReadFull(r, msg.BlockHash[:]); err != nil { + binarySerializer.Return(buf) return err } // Read filter data - msg.Data, err = ReadVarBytes(r, pver, MaxCFilterDataSize, + var err error + msg.Data, err = ReadVarBytesBuf(r, pver, buf, MaxCFilterDataSize, "cfilter data") + binarySerializer.Return(buf) return err } @@ -65,17 +69,21 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) er return messageError("MsgCFilter.BtcEncode", str) } - err := writeElement(w, msg.FilterType) - if err != nil { + buf := binarySerializer.Borrow() + buf[0] = byte(msg.FilterType) + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } - err = writeElement(w, msg.BlockHash) - if err != nil { + if _, err := w.Write(msg.BlockHash[:]); err != nil { + binarySerializer.Return(buf) return err } - return WriteVarBytes(w, pver, msg.Data) + err := WriteVarBytesBuf(w, pver, msg.Data, buf) + binarySerializer.Return(buf) + return err } // Deserialize decodes a filter from r into the receiver using a format that is From efcf964be280505a25f6f984833ecbe36fe5d655 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:10 -0800 Subject: [PATCH 0877/1056] wire/msgnotfound: optimize serialization by reusing small buffers --- wire/msgnotfound.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/wire/msgnotfound.go b/wire/msgnotfound.go index e867681668..6be7ffb48b 100644 --- a/wire/msgnotfound.go +++ b/wire/msgnotfound.go @@ -35,13 +35,16 @@ func (msg *MsgNotFound) AddInvVect(iv *InvVect) error { // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - count, err := ReadVarInt(r, pver) + buf := binarySerializer.Borrow() + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } // Limit to max inventory vectors per message. if count > MaxInvPerMsg { + binarySerializer.Return(buf) str := fmt.Sprintf("too many invvect in message [%v]", count) return messageError("MsgNotFound.BtcDecode", str) } @@ -52,12 +55,14 @@ func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) msg.InvList = make([]*InvVect, 0, count) for i := uint64(0); i < count; i++ { iv := &invList[i] - err := readInvVect(r, pver, iv) + err := readInvVectBuf(r, pver, iv, buf) if err != nil { + binarySerializer.Return(buf) return err } msg.AddInvVect(iv) } + binarySerializer.Return(buf) return nil } @@ -72,17 +77,21 @@ func (msg *MsgNotFound) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) return messageError("MsgNotFound.BtcEncode", str) } - err := WriteVarInt(w, pver, uint64(count)) + buf := binarySerializer.Borrow() + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { + binarySerializer.Return(buf) return err } for _, iv := range msg.InvList { - err := writeInvVect(w, pver, iv) + err := writeInvVectBuf(w, pver, iv, buf) if err != nil { + binarySerializer.Return(buf) return err } } + binarySerializer.Return(buf) return nil } From 1cd5e02838ff25b0fcfcc7f7a02ed02c4b1723d8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:18 -0800 Subject: [PATCH 0878/1056] wire/invvect: remove unused readInvVect and writeInvVect --- wire/invvect.go | 21 --------------------- wire/invvect_test.go | 5 +++-- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/wire/invvect.go b/wire/invvect.go index fb21243f86..c0756a8f1c 100644 --- a/wire/invvect.go +++ b/wire/invvect.go @@ -74,17 +74,6 @@ func NewInvVect(typ InvType, hash *chainhash.Hash) *InvVect { } } -// readInvVect reads an encoded InvVect from r depending on the protocol -// version. -// -// DEPRECATED: Use readInvVectBuf instead. -func readInvVect(r io.Reader, pver uint32, iv *InvVect) error { - buf := binarySerializer.Borrow() - err := readInvVectBuf(r, pver, iv, buf) - binarySerializer.Return(buf) - return err -} - // readInvVectBuf reads an encoded InvVect from r depending on the protocol // version. // @@ -103,16 +92,6 @@ func readInvVectBuf(r io.Reader, pver uint32, iv *InvVect, buf []byte) error { return err } -// writeInvVect serializes an InvVect to w depending on the protocol version. -// -// DEPRECATED: Use writeInvVectBuf instead. -func writeInvVect(w io.Writer, pver uint32, iv *InvVect) error { - buf := binarySerializer.Borrow() - err := writeInvVectBuf(w, pver, iv, buf) - binarySerializer.Return(buf) - return err -} - // writeInvVectBuf serializes an InvVect to w depending on the protocol version. // // If b is non-nil, the provided buffer will be used for serializing small diff --git a/wire/invvect_test.go b/wire/invvect_test.go index 1d02c09817..cf29d0a2ff 100644 --- a/wire/invvect_test.go +++ b/wire/invvect_test.go @@ -238,10 +238,11 @@ func TestInvVectWire(t *testing.T) { } t.Logf("Running %d tests", len(tests)) + var b [8]byte for i, test := range tests { // Encode to wire format. var buf bytes.Buffer - err := writeInvVect(&buf, test.pver, &test.in) + err := writeInvVectBuf(&buf, test.pver, &test.in, b[:]) if err != nil { t.Errorf("writeInvVect #%d error %v", i, err) continue @@ -255,7 +256,7 @@ func TestInvVectWire(t *testing.T) { // Decode the message from wire format. var iv InvVect rbuf := bytes.NewReader(test.buf) - err = readInvVect(rbuf, test.pver, &iv) + err = readInvVectBuf(rbuf, test.pver, &iv, b[:]) if err != nil { t.Errorf("readInvVect #%d error %v", i, err) continue From 57daac345eb9e154680cb0d4a80fe044efb280cb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:26 -0800 Subject: [PATCH 0879/1056] wire/common: add optimized writeVarStrBuf an readVarStrBuf --- wire/bench_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++ wire/common.go | 46 ++++++++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 3efd13f50a..a5a7162524 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -306,6 +306,60 @@ func BenchmarkWriteVarStr10(b *testing.B) { } } +// BenchmarkReadVarStrBuf4 performs a benchmark on how long it takes to read a +// four byte variable length string. +func BenchmarkReadVarStrBuf4(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{0x04, 't', 'e', 's', 't'} + r := bytes.NewReader(buf) + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + readVarStringBuf(r, 0, buffer) + } + binarySerializer.Return(buffer) +} + +// BenchmarkReadVarStrBuf10 performs a benchmark on how long it takes to read a +// ten byte variable length string. +func BenchmarkReadVarStrBuf10(b *testing.B) { + b.ReportAllocs() + + buffer := binarySerializer.Borrow() + buf := []byte{0x0a, 't', 'e', 's', 't', '0', '1', '2', '3', '4', '5'} + r := bytes.NewReader(buf) + for i := 0; i < b.N; i++ { + r.Seek(0, 0) + readVarStringBuf(r, 0, buf) + } + binarySerializer.Return(buffer) +} + +// BenchmarkWriteVarStrBuf4 performs a benchmark on how long it takes to write a +// four byte variable length string. +func BenchmarkWriteVarStrBuf4(b *testing.B) { + b.ReportAllocs() + + buf := binarySerializer.Borrow() + for i := 0; i < b.N; i++ { + writeVarStringBuf(ioutil.Discard, 0, "test", buf) + } + binarySerializer.Return(buf) +} + +// BenchmarkWriteVarStrBuf10 performs a benchmark on how long it takes to write +// a ten byte variable length string. +func BenchmarkWriteVarStrBuf10(b *testing.B) { + b.ReportAllocs() + + buf := binarySerializer.Borrow() + for i := 0; i < b.N; i++ { + writeVarStringBuf(ioutil.Discard, 0, "test012345", buf) + } + binarySerializer.Return(buf) +} + // BenchmarkReadOutPoint performs a benchmark on how long it takes to read a // transaction output point. func BenchmarkReadOutPoint(b *testing.B) { diff --git a/wire/common.go b/wire/common.go index e009debf4e..8123e471b9 100644 --- a/wire/common.go +++ b/wire/common.go @@ -615,7 +615,26 @@ func VarIntSerializeSize(val uint64) int { // maximum block payload size since it helps protect against memory exhaustion // attacks and forced panics through malformed messages. func ReadVarString(r io.Reader, pver uint32) (string, error) { - count, err := ReadVarInt(r, pver) + buf := binarySerializer.Borrow() + str, err := readVarStringBuf(r, pver, buf) + binarySerializer.Return(buf) + return str, err +} + +// readVarStringBuf reads a variable length string from r and returns it as a Go +// string. A variable length string is encoded as a variable length integer +// containing the length of the string followed by the bytes that represent the +// string itself. An error is returned if the length is greater than the +// maximum block payload size since it helps protect against memory exhaustion +// attacks and forced panics through malformed messages. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func readVarStringBuf(r io.Reader, pver uint32, buf []byte) (string, error) { + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { return "", err } @@ -629,22 +648,39 @@ func ReadVarString(r io.Reader, pver uint32) (string, error) { return "", messageError("ReadVarString", str) } - buf := make([]byte, count) - _, err = io.ReadFull(r, buf) + str := make([]byte, count) + _, err = io.ReadFull(r, str) if err != nil { return "", err } - return string(buf), nil + return string(str), nil } // WriteVarString serializes str to w as a variable length integer containing // the length of the string followed by the bytes that represent the string // itself. func WriteVarString(w io.Writer, pver uint32, str string) error { - err := WriteVarInt(w, pver, uint64(len(str))) + buf := binarySerializer.Borrow() + err := writeVarStringBuf(w, pver, str, buf) + binarySerializer.Return(buf) + return err +} + +// writeVarStringBuf serializes str to w as a variable length integer containing +// the length of the string followed by the bytes that represent the string +// itself. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func writeVarStringBuf(w io.Writer, pver uint32, str string, buf []byte) error { + err := WriteVarIntBuf(w, pver, uint64(len(str)), buf) if err != nil { return err } + _, err = w.Write([]byte(str)) return err } From dc4fbb04b38fd87460751c5a1cd96099786c0e04 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:33 -0800 Subject: [PATCH 0880/1056] wire/msgreject: optimize serialization by reusing small buffers --- wire/msgreject.go | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/wire/msgreject.go b/wire/msgreject.go index a00eeff6f6..64c81d8b5b 100644 --- a/wire/msgreject.go +++ b/wire/msgreject.go @@ -81,30 +81,35 @@ func (msg *MsgReject) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) e } // Command that was rejected. - cmd, err := ReadVarString(r, pver) + buf := binarySerializer.Borrow() + cmd, err := readVarStringBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } msg.Cmd = cmd // Code indicating why the command was rejected. - err = readElement(r, &msg.Code) - if err != nil { + if _, err := io.ReadFull(r, buf[:1]); err != nil { + binarySerializer.Return(buf) return err } + msg.Code = RejectCode(buf[0]) // Human readable string with specific details (over and above the // reject code above) about why the command was rejected. - reason, err := ReadVarString(r, pver) + reason, err := readVarStringBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } msg.Reason = reason + binarySerializer.Return(buf) // CmdBlock and CmdTx messages have an additional hash field that // identifies the specific block or transaction. if msg.Cmd == CmdBlock || msg.Cmd == CmdTx { - err := readElement(r, &msg.Hash) + _, err := io.ReadFull(r, msg.Hash[:]) if err != nil { return err } @@ -123,28 +128,33 @@ func (msg *MsgReject) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) e } // Command that was rejected. - err := WriteVarString(w, pver, msg.Cmd) + buf := binarySerializer.Borrow() + err := writeVarStringBuf(w, pver, msg.Cmd, buf) if err != nil { + binarySerializer.Return(buf) return err } // Code indicating why the command was rejected. - err = writeElement(w, msg.Code) - if err != nil { + buf[0] = byte(msg.Code) + if _, err := w.Write(buf[:1]); err != nil { + binarySerializer.Return(buf) return err } // Human readable string with specific details (over and above the // reject code above) about why the command was rejected. - err = WriteVarString(w, pver, msg.Reason) + err = writeVarStringBuf(w, pver, msg.Reason, buf) if err != nil { + binarySerializer.Return(buf) return err } + binarySerializer.Return(buf) // CmdBlock and CmdTx messages have an additional hash field that // identifies the specific block or transaction. if msg.Cmd == CmdBlock || msg.Cmd == CmdTx { - err := writeElement(w, &msg.Hash) + _, err := w.Write(msg.Hash[:]) if err != nil { return err } From 8bf07cc0bf66cac4fc86b2ce5d947148f12c132a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:41 -0800 Subject: [PATCH 0881/1056] wire/netaddress: add optimiezed read/writeNetAddressBuf --- wire/netaddress.go | 80 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/wire/netaddress.go b/wire/netaddress.go index 5a2610bccc..9cef72cf10 100644 --- a/wire/netaddress.go +++ b/wire/netaddress.go @@ -5,7 +5,6 @@ package wire import ( - "encoding/binary" "io" "net" "time" @@ -89,31 +88,59 @@ func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress { // version and whether or not the timestamp is included per ts. Some messages // like version do not include the timestamp. func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { - var ip [16]byte + buf := binarySerializer.Borrow() + err := readNetAddressBuf(r, pver, na, ts, buf) + binarySerializer.Return(buf) + return err +} + +// readNetAddressBuf reads an encoded NetAddress from r depending on the +// protocol version and whether or not the timestamp is included per ts. Some +// messages like version do not include the timestamp. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func readNetAddressBuf(r io.Reader, pver uint32, na *NetAddress, ts bool, + buf []byte) error { + + var ( + timestamp time.Time + services ServiceFlag + ip [16]byte + port uint16 + ) // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will // stop working somewhere around 2106. Also timestamp wasn't added until // protocol version >= NetAddressTimeVersion if ts && pver >= NetAddressTimeVersion { - err := readElement(r, (*uint32Time)(&na.Timestamp)) - if err != nil { + if _, err := io.ReadFull(r, buf[:4]); err != nil { return err } + timestamp = time.Unix(int64(littleEndian.Uint32(buf[:4])), 0) + } + + if _, err := io.ReadFull(r, buf); err != nil { + return err } + services = ServiceFlag(littleEndian.Uint64(buf)) - err := readElements(r, &na.Services, &ip) - if err != nil { + if _, err := io.ReadFull(r, ip[:]); err != nil { return err } + // Sigh. Bitcoin protocol mixes little and big endian. - port, err := binarySerializer.Uint16(r, bigEndian) - if err != nil { + if _, err := io.ReadFull(r, buf[:2]); err != nil { return err } + port = bigEndian.Uint16(buf[:2]) *na = NetAddress{ - Timestamp: na.Timestamp, - Services: na.Services, + Timestamp: timestamp, + Services: services, IP: net.IP(ip[:]), Port: port, } @@ -124,26 +151,49 @@ func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { // version and whether or not the timestamp is included per ts. Some messages // like version do not include the timestamp. func writeNetAddress(w io.Writer, pver uint32, na *NetAddress, ts bool) error { + buf := binarySerializer.Borrow() + err := writeNetAddressBuf(w, pver, na, ts, buf) + binarySerializer.Return(buf) + return err +} + +// writeNetAddressBuf serializes a NetAddress to w depending on the protocol +// version and whether or not the timestamp is included per ts. Some messages +// like version do not include the timestamp. +// +// If b is non-nil, the provided buffer will be used for serializing small +// values. Otherwise a buffer will be drawn from the binarySerializer's pool +// and return when the method finishes. +// +// NOTE: b MUST either be nil or at least an 8-byte slice. +func writeNetAddressBuf(w io.Writer, pver uint32, na *NetAddress, ts bool, buf []byte) error { // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will // stop working somewhere around 2106. Also timestamp wasn't added until // until protocol version >= NetAddressTimeVersion. if ts && pver >= NetAddressTimeVersion { - err := writeElement(w, uint32(na.Timestamp.Unix())) - if err != nil { + littleEndian.PutUint32(buf[:4], uint32(na.Timestamp.Unix())) + if _, err := w.Write(buf[:4]); err != nil { return err } } + littleEndian.PutUint64(buf, uint64(na.Services)) + if _, err := w.Write(buf); err != nil { + return err + } + // Ensure to always write 16 bytes even if the ip is nil. var ip [16]byte if na.IP != nil { copy(ip[:], na.IP.To16()) } - err := writeElements(w, na.Services, ip) - if err != nil { + if _, err := w.Write(ip[:]); err != nil { return err } // Sigh. Bitcoin protocol mixes little and big endian. - return binary.Write(w, bigEndian, na.Port) + bigEndian.PutUint16(buf[:2], na.Port) + _, err := w.Write(buf[:2]) + + return err } From 72079671354a6aabedad1ac19f5b9e1d28d2ac2a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:49 -0800 Subject: [PATCH 0882/1056] wire/msgmerkleblock: optimize serialization by reusing small buffers --- wire/msgmerkleblock.go | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/wire/msgmerkleblock.go b/wire/msgmerkleblock.go index d2ee472178..be3f73b8b5 100644 --- a/wire/msgmerkleblock.go +++ b/wire/msgmerkleblock.go @@ -49,22 +49,27 @@ func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncodi return messageError("MsgMerkleBlock.BtcDecode", str) } - err := readBlockHeader(r, pver, &msg.Header) + buf := binarySerializer.Borrow() + err := readBlockHeaderBuf(r, pver, &msg.Header, buf) if err != nil { + binarySerializer.Return(buf) return err } - err = readElement(r, &msg.Transactions) - if err != nil { + if _, err := io.ReadFull(r, buf[:4]); err != nil { + binarySerializer.Return(buf) return err } + msg.Transactions = littleEndian.Uint32(buf[:4]) // Read num block locator hashes and limit to max. - count, err := ReadVarInt(r, pver) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { + binarySerializer.Return(buf) return err } if count > maxTxPerBlock { + binarySerializer.Return(buf) str := fmt.Sprintf("too many transaction hashes for message "+ "[count %v, max %v]", count, maxTxPerBlock) return messageError("MsgMerkleBlock.BtcDecode", str) @@ -76,15 +81,17 @@ func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncodi msg.Hashes = make([]*chainhash.Hash, 0, count) for i := uint64(0); i < count; i++ { hash := &hashes[i] - err := readElement(r, hash) + _, err := io.ReadFull(r, hash[:]) if err != nil { + binarySerializer.Return(buf) return err } msg.AddTxHash(hash) } - msg.Flags, err = ReadVarBytes(r, pver, maxFlagsPerMerkleBlock, + msg.Flags, err = ReadVarBytesBuf(r, pver, buf, maxFlagsPerMerkleBlock, "merkle block flags size") + binarySerializer.Return(buf) return err } @@ -111,28 +118,36 @@ func (msg *MsgMerkleBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncodi return messageError("MsgMerkleBlock.BtcDecode", str) } - err := writeBlockHeader(w, pver, &msg.Header) + buf := binarySerializer.Borrow() + err := writeBlockHeaderBuf(w, pver, &msg.Header, buf) if err != nil { + binarySerializer.Return(buf) return err } - err = writeElement(w, msg.Transactions) - if err != nil { + littleEndian.PutUint32(buf[:4], msg.Transactions) + if _, err := w.Write(buf[:4]); err != nil { + binarySerializer.Return(buf) return err } - err = WriteVarInt(w, pver, uint64(numHashes)) + err = WriteVarIntBuf(w, pver, uint64(numHashes), buf) if err != nil { + binarySerializer.Return(buf) return err } for _, hash := range msg.Hashes { - err = writeElement(w, hash) + _, err := w.Write(hash[:]) if err != nil { + binarySerializer.Return(buf) return err } } - return WriteVarBytes(w, pver, msg.Flags) + err = WriteVarBytesBuf(w, pver, msg.Flags, buf) + binarySerializer.Return(buf) + + return err } // Command returns the protocol command string for the message. This is part From 3698f2deab52a3a2a725786ad6e96a8bd8ebfebb Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:44:57 -0800 Subject: [PATCH 0883/1056] wire/msgping: remove usage for read/writeElement --- wire/msgping.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wire/msgping.go b/wire/msgping.go index b2f346e0e1..dd5e61e6bf 100644 --- a/wire/msgping.go +++ b/wire/msgping.go @@ -32,10 +32,11 @@ func (msg *MsgPing) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) err // NOTE: > is not a mistake here. The BIP0031 was defined as AFTER // the version unlike most others. if pver > BIP0031Version { - err := readElement(r, &msg.Nonce) + nonce, err := binarySerializer.Uint64(r, littleEndian) if err != nil { return err } + msg.Nonce = nonce } return nil @@ -48,7 +49,7 @@ func (msg *MsgPing) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) err // NOTE: > is not a mistake here. The BIP0031 was defined as AFTER // the version unlike most others. if pver > BIP0031Version { - err := writeElement(w, msg.Nonce) + err := binarySerializer.PutUint64(w, littleEndian, msg.Nonce) if err != nil { return err } From 80ae5d342c4dd0bc666d29e604188f735caa666c Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:45:05 -0800 Subject: [PATCH 0884/1056] wire/msgpong: remove usage of read/writeElement --- wire/msgpong.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/wire/msgpong.go b/wire/msgpong.go index eec80d8d5b..01e83792ef 100644 --- a/wire/msgpong.go +++ b/wire/msgpong.go @@ -31,7 +31,13 @@ func (msg *MsgPong) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) err return messageError("MsgPong.BtcDecode", str) } - return readElement(r, &msg.Nonce) + nonce, err := binarySerializer.Uint64(r, littleEndian) + if err != nil { + return err + } + msg.Nonce = nonce + + return nil } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. @@ -45,7 +51,7 @@ func (msg *MsgPong) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) err return messageError("MsgPong.BtcEncode", str) } - return writeElement(w, msg.Nonce) + return binarySerializer.PutUint64(w, littleEndian, msg.Nonce) } // Command returns the protocol command string for the message. This is part From da89ed68ffbe2555500401eabdb1d1ab8bfcd07a Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:45:13 -0800 Subject: [PATCH 0885/1056] wire/msgtx: remove unused writeTxWitness --- wire/msgtx.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index e89ad7cb56..954691c031 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1217,17 +1217,6 @@ func WriteTxOutBuf(w io.Writer, pver uint32, version int32, to *TxOut, return WriteVarBytesBuf(w, pver, to.PkScript, buf) } -// writeTxWitness encodes the bitcoin protocol encoding for a transaction -// input's witness into to w. -// -// DEPRECATED: Use writeTxWitnessBuf instead. -func writeTxWitness(w io.Writer, pver uint32, version int32, wit [][]byte) error { - buf := binarySerializer.Borrow() - err := writeTxWitnessBuf(w, pver, version, wit, buf) - binarySerializer.Return(buf) - return err -} - // writeTxWitnessBuf encodes the bitcoin protocol encoding for a transaction // input's witness into to w. If b is non-nil, the provided buffer will be used // for serializing small values. Otherwise a buffer will be drawn from the From f0184e58bab6c310d170d75f554a2af3e31d2731 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:45:28 -0800 Subject: [PATCH 0886/1056] wire/msgtx: remove unused writeTxIn --- wire/bench_test.go | 11 ----------- wire/msgtx.go | 9 --------- 2 files changed, 20 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index a5a7162524..43f6159b64 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -571,17 +571,6 @@ func BenchmarkReadTxInBuf(b *testing.B) { func BenchmarkWriteTxIn(b *testing.B) { b.ReportAllocs() - txIn := blockOne.Transactions[0].TxIn[0] - for i := 0; i < b.N; i++ { - writeTxIn(ioutil.Discard, 0, 0, txIn) - } -} - -// BenchmarkWriteTxInBuf performs a benchmark on how long it takes to write -// a transaction input. -func BenchmarkWriteTxInBuf(b *testing.B) { - b.ReportAllocs() - buf := binarySerializer.Borrow() txIn := blockOne.Transactions[0].TxIn[0] for i := 0; i < b.N; i++ { diff --git a/wire/msgtx.go b/wire/msgtx.go index 954691c031..e8f97fbb39 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1127,15 +1127,6 @@ func readTxInBuf(r io.Reader, pver uint32, version int32, ti *TxIn, return nil } -// writeTxIn encodes ti to the bitcoin protocol encoding for a transaction -// input (TxIn) to w. -func writeTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { - buf := binarySerializer.Borrow() - err := writeTxInBuf(w, pver, version, ti, buf) - binarySerializer.Return(buf) - return err -} - // writeTxInBuf encodes ti to the bitcoin protocol encoding for a transaction // input (TxIn) to w. If b is non-nil, the provided buffer will be used for // serializing small values. Otherwise a buffer will be drawn from the From e0fa866890e245fa569795c0d878218c233f7119 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:45:35 -0800 Subject: [PATCH 0887/1056] wire/msgtx: remove unused readTxIn --- wire/bench_test.go | 24 ------------------------ wire/msgtx.go | 11 ----------- 2 files changed, 35 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 43f6159b64..f02038b36c 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -521,30 +521,6 @@ func BenchmarkWriteTxOutBuf(b *testing.B) { func BenchmarkReadTxIn(b *testing.B) { b.ReportAllocs() - buf := []byte{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Previous output index - 0x07, // Varint for length of signature script - 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script - 0xff, 0xff, 0xff, 0xff, // Sequence - } - r := bytes.NewReader(buf) - var txIn TxIn - for i := 0; i < b.N; i++ { - r.Seek(0, 0) - readTxIn(r, 0, 0, &txIn) - scriptPool.Return(txIn.SignatureScript) - } -} - -// BenchmarkReadTxInBuf performs a benchmark on how long it takes to read a -// transaction input. -func BenchmarkReadTxInBuf(b *testing.B) { - b.ReportAllocs() - buffer := binarySerializer.Borrow() buf := []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/wire/msgtx.go b/wire/msgtx.go index e8f97fbb39..d73d1916e5 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1085,17 +1085,6 @@ func readScriptBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, fiel return b, nil } -// readTxIn reads the next sequence of bytes from r as a transaction input -// (TxIn). -// -// DEPRECATED: Use readTxInBuf instead. -func readTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { - buf := binarySerializer.Borrow() - err := readTxInBuf(r, pver, version, ti, buf) - binarySerializer.Return(buf) - return err -} - // readTxInBuf reads the next sequence of bytes from r as a transaction input // (TxIn). // From 4cc4f76c55be62e1bea6443825f672d84553acd4 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:45:43 -0800 Subject: [PATCH 0888/1056] wire/msgtx: remove unused readScript --- wire/msgtx.go | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/wire/msgtx.go b/wire/msgtx.go index d73d1916e5..0b961ab9d9 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -1032,22 +1032,6 @@ func writeOutPointBuf(w io.Writer, pver uint32, version int32, op *OutPoint, return err } -// readScript reads a variable length byte array that represents a transaction -// script. It is encoded as a varInt containing the length of the array -// followed by the bytes themselves. An error is returned if the length is -// greater than the passed maxAllowed parameter which helps protect against -// memory exhaustion attacks and forced panics through malformed messages. The -// fieldName parameter is only used for the error message so it provides more -// context in the error. -// -// DEPRECATED: Use readScriptBuf instead. -func readScript(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { - buf := binarySerializer.Borrow() - b, err := readScriptBuf(r, pver, buf, maxAllowed, fieldName) - binarySerializer.Return(buf) - return b, err -} - // readScript reads a variable length byte array that represents a transaction // script. It is encoded as a varInt containing the length of the array // followed by the bytes themselves. An error is returned if the length is From 2e6eefcab1771a8fa6dbf2b7ec05de29a4e25190 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:45:50 -0800 Subject: [PATCH 0889/1056] wire/msgtx: remove unused read/writeOutPoint --- wire/bench_test.go | 20 -------------------- wire/msgtx.go | 10 ---------- 2 files changed, 30 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index f02038b36c..0455052bb5 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -365,26 +365,6 @@ func BenchmarkWriteVarStrBuf10(b *testing.B) { func BenchmarkReadOutPoint(b *testing.B) { b.ReportAllocs() - buf := []byte{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Previous output index - } - r := bytes.NewReader(buf) - var op OutPoint - for i := 0; i < b.N; i++ { - r.Seek(0, 0) - readOutPoint(r, 0, 0, &op) - } -} - -// BenchmarkReadOutPointBuf performs a benchmark on how long it takes to read a -// transaction output point. -func BenchmarkReadOutPointBuf(b *testing.B) { - b.ReportAllocs() - buffer := binarySerializer.Borrow() buf := []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/wire/msgtx.go b/wire/msgtx.go index 0b961ab9d9..dd699f96d4 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -969,16 +969,6 @@ func NewMsgTx(version int32) *MsgTx { } } -// readOutPoint reads the next sequence of bytes from r as an OutPoint. -// -// DEPRECATED: Use readOutPointBuf instead. -func readOutPoint(r io.Reader, pver uint32, version int32, op *OutPoint) error { - buf := binarySerializer.Borrow() - err := readOutPointBuf(r, pver, version, op, buf) - binarySerializer.Return(buf) - return err -} - // readOutPointBuf reads the next sequence of bytes from r as an OutPoint. // // If b is non-nil, the provided buffer will be used for serializing small From d7396dc13d8021001ab05684c99f465ea16fedc8 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:46:53 -0800 Subject: [PATCH 0890/1056] wire/msgtx: use tx-level script slab --- wire/bench_test.go | 13 +++-- wire/msgtx.go | 124 ++++++++++++++++----------------------------- 2 files changed, 53 insertions(+), 84 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index 0455052bb5..d612728c6b 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -437,7 +437,6 @@ func BenchmarkReadTxOut(b *testing.B) { for i := 0; i < b.N; i++ { r.Seek(0, 0) ReadTxOut(r, 0, 0, &txOut) - scriptPool.Return(txOut.PkScript) } } @@ -446,6 +445,8 @@ func BenchmarkReadTxOut(b *testing.B) { func BenchmarkReadTxOutBuf(b *testing.B) { b.ReportAllocs() + scriptBuffer := scriptPool.Borrow() + sbuf := scriptBuffer[:] buffer := binarySerializer.Borrow() buf := []byte{ 0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount @@ -466,10 +467,10 @@ func BenchmarkReadTxOutBuf(b *testing.B) { var txOut TxOut for i := 0; i < b.N; i++ { r.Seek(0, 0) - readTxOutBuf(r, 0, 0, &txOut, buffer) - scriptPool.Return(txOut.PkScript) + readTxOutBuf(r, 0, 0, &txOut, buffer, sbuf) } binarySerializer.Return(buffer) + scriptPool.Return(scriptBuffer) } // BenchmarkWriteTxOut performs a benchmark on how long it takes to write @@ -501,6 +502,8 @@ func BenchmarkWriteTxOutBuf(b *testing.B) { func BenchmarkReadTxIn(b *testing.B) { b.ReportAllocs() + scriptBuffer := scriptPool.Borrow() + sbuf := scriptBuffer[:] buffer := binarySerializer.Borrow() buf := []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -516,10 +519,10 @@ func BenchmarkReadTxIn(b *testing.B) { var txIn TxIn for i := 0; i < b.N; i++ { r.Seek(0, 0) - readTxInBuf(r, 0, 0, &txIn, buffer) - scriptPool.Return(txIn.SignatureScript) + readTxInBuf(r, 0, 0, &txIn, buffer, sbuf) } binarySerializer.Return(buffer) + scriptPool.Return(scriptBuffer) } // BenchmarkWriteTxIn performs a benchmark on how long it takes to write diff --git a/wire/msgtx.go b/wire/msgtx.go index dd699f96d4..00a562eceb 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -94,7 +94,7 @@ const ( // scripts per transaction being simultaneously deserialized by 125 // peers. Thus, the peak usage of the free list is 12,500 * 512 = // 6,400,000 bytes. - freeListMaxItems = 12500 + freeListMaxItems = 125 // maxWitnessItemsPerInput is the maximum number of witness items to // be read for the witness data for a single TxIn. This number is @@ -147,6 +147,10 @@ const ( WitnessFlag TxFlag = 0x01 ) +const scriptSlabSize = 1 << 22 + +type scriptSlab [scriptSlabSize]byte + // scriptFreeList defines a free list of byte slices (up to the maximum number // defined by the freeListMaxItems constant) that have a cap according to the // freeListMaxScriptSize constant. It is used to provide temporary buffers for @@ -155,7 +159,7 @@ const ( // // The caller can obtain a buffer from the free list by calling the Borrow // function and should return it via the Return function when done using it. -type scriptFreeList chan []byte +type scriptFreeList chan *scriptSlab // Borrow returns a byte slice from the free list with a length according the // provided size. A new buffer is allocated if there are any items available. @@ -164,18 +168,14 @@ type scriptFreeList chan []byte // a new buffer of the appropriate size is allocated and returned. It is safe // to attempt to return said buffer via the Return function as it will be // ignored and allowed to go the garbage collector. -func (c scriptFreeList) Borrow(size uint64) []byte { - if size > freeListMaxScriptSize { - return make([]byte, size) - } - - var buf []byte +func (c scriptFreeList) Borrow() *scriptSlab { + var buf *scriptSlab select { case buf = <-c: default: - buf = make([]byte, freeListMaxScriptSize) + buf = new(scriptSlab) } - return buf[:size] + return buf } // Return puts the provided byte slice back on the free list when it has a cap @@ -183,13 +183,7 @@ func (c scriptFreeList) Borrow(size uint64) []byte { // the Borrow function. Any slices that are not of the appropriate size, such // as those whose size is greater than the largest allowed free list item size // are simply ignored so they can go to the garbage collector. -func (c scriptFreeList) Return(buf []byte) { - // Ignore any buffers returned that aren't the expected size for the - // free list. - if cap(buf) != freeListMaxScriptSize { - return - } - +func (c scriptFreeList) Return(buf *scriptSlab) { // Return the buffer to the free list when it's not full. Otherwise let // it be garbage collected. select { @@ -202,7 +196,7 @@ func (c scriptFreeList) Return(buf []byte) { // Create the concurrent safe free list to use for script deserialization. As // previously described, this free list is maintained to significantly reduce // the number of allocations. -var scriptPool scriptFreeList = make(chan []byte, freeListMaxItems) +var scriptPool = make(scriptFreeList, freeListMaxItems) // OutPoint defines a bitcoin data type that is used to track previous // transaction outputs. @@ -515,34 +509,8 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, return messageError("MsgTx.BtcDecode", str) } - // returnScriptBuffers is a closure that returns any script buffers that - // were borrowed from the pool when there are any deserialization - // errors. This is only valid to call before the final step which - // replaces the scripts with the location in a contiguous buffer and - // returns them. - returnScriptBuffers := func() { - for _, txIn := range msg.TxIn { - if txIn == nil { - continue - } - - if txIn.SignatureScript != nil { - scriptPool.Return(txIn.SignatureScript) - } - - for _, witnessElem := range txIn.Witness { - if witnessElem != nil { - scriptPool.Return(witnessElem) - } - } - } - for _, txOut := range msg.TxOut { - if txOut == nil || txOut.PkScript == nil { - continue - } - scriptPool.Return(txOut.PkScript) - } - } + scriptBuf := scriptPool.Borrow() + sbuf := scriptBuf[:] // Deserialize the inputs. var totalScriptSize uint64 @@ -553,17 +521,18 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // and needs to be returned to the pool on error. ti := &txIns[i] msg.TxIn[i] = ti - err = readTxInBuf(r, pver, msg.Version, ti, buf) + err = readTxInBuf(r, pver, msg.Version, ti, buf, sbuf) if err != nil { - returnScriptBuffers() + scriptPool.Return(scriptBuf) return err } totalScriptSize += uint64(len(ti.SignatureScript)) + sbuf = sbuf[len(ti.SignatureScript):] } count, err = ReadVarIntBuf(r, pver, buf) if err != nil { - returnScriptBuffers() + scriptPool.Return(scriptBuf) return err } @@ -571,7 +540,7 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // message. It would be possible to cause memory exhaustion and panics // without a sane upper bound on this count. if count > uint64(maxTxOutPerMessage) { - returnScriptBuffers() + scriptPool.Return(scriptBuf) str := fmt.Sprintf("too many output transactions to fit into "+ "max message size [count %d, max %d]", count, maxTxOutPerMessage) @@ -586,13 +555,13 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // and needs to be returned to the pool on error. to := &txOuts[i] msg.TxOut[i] = to - - err = readTxOutBuf(r, pver, msg.Version, to, buf) + err = readTxOutBuf(r, pver, msg.Version, to, buf, sbuf) if err != nil { - returnScriptBuffers() + scriptPool.Return(scriptBuf) return err } totalScriptSize += uint64(len(to.PkScript)) + sbuf = sbuf[len(to.PkScript):] } // If the transaction's flag byte isn't 0x00 at this point, then one or @@ -604,14 +573,14 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // varint which encodes the number of stack items. witCount, err := ReadVarIntBuf(r, pver, buf) if err != nil { - returnScriptBuffers() + scriptPool.Return(scriptBuf) return err } // Prevent a possible memory exhaustion attack by // limiting the witCount value to a sane upper bound. if witCount > maxWitnessItemsPerInput { - returnScriptBuffers() + scriptPool.Return(scriptBuf) str := fmt.Sprintf("too many witness items to fit "+ "into max message size [count %d, max %d]", witCount, maxWitnessItemsPerInput) @@ -624,20 +593,21 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, txin.Witness = make([][]byte, witCount) for j := uint64(0); j < witCount; j++ { txin.Witness[j], err = readScriptBuf( - r, pver, buf, maxWitnessItemSize, + r, pver, buf, sbuf, maxWitnessItemSize, "script witness item", ) if err != nil { - returnScriptBuffers() + scriptPool.Return(scriptBuf) return err } totalScriptSize += uint64(len(txin.Witness[j])) + sbuf = sbuf[len(txin.Witness[j]):] } } } if _, err := io.ReadFull(r, buf[:4]); err != nil { - returnScriptBuffers() + scriptPool.Return(scriptBuf) return err } msg.LockTime = littleEndian.Uint32(buf[:4]) @@ -671,9 +641,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, msg.TxIn[i].SignatureScript = scripts[offset:end:end] offset += scriptSize - // Return the temporary script buffer to the pool. - scriptPool.Return(signatureScript) - for j := 0; j < len(msg.TxIn[i].Witness); j++ { // Copy each item within the witness stack for this // input into the contiguous buffer at the appropriate @@ -687,10 +654,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, end := offset + witnessElemSize msg.TxIn[i].Witness[j] = scripts[offset:end:end] offset += witnessElemSize - - // Return the temporary buffer used for the witness stack - // item to the pool. - scriptPool.Return(witnessElem) } } for i := 0; i < len(msg.TxOut); i++ { @@ -705,11 +668,10 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, end := offset + scriptSize msg.TxOut[i].PkScript = scripts[offset:end:end] offset += scriptSize - - // Return the temporary script buffer to the pool. - scriptPool.Return(pkScript) } + scriptPool.Return(scriptBuf) + return nil } @@ -1035,7 +997,9 @@ func writeOutPointBuf(w io.Writer, pver uint32, version int32, op *OutPoint, // and return when the method finishes. // // NOTE: b MUST either be nil or at least an 8-byte slice. -func readScriptBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, fieldName string) ([]byte, error) { +func readScriptBuf(r io.Reader, pver uint32, buf, s []byte, maxAllowed uint32, + fieldName string) ([]byte, error) { + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { return nil, err @@ -1050,13 +1014,11 @@ func readScriptBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, fiel return nil, messageError("readScript", str) } - b := scriptPool.Borrow(count) - _, err = io.ReadFull(r, b) + _, err = io.ReadFull(r, s[:count]) if err != nil { - scriptPool.Return(b) return nil, err } - return b, nil + return s[:count], nil } // readTxInBuf reads the next sequence of bytes from r as a transaction input @@ -1068,14 +1030,14 @@ func readScriptBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, fiel // // NOTE: b MUST either be nil or at least an 8-byte slice. func readTxInBuf(r io.Reader, pver uint32, version int32, ti *TxIn, - buf []byte) error { + buf, s []byte) error { err := readOutPointBuf(r, pver, version, &ti.PreviousOutPoint, buf) if err != nil { return err } - ti.SignatureScript, err = readScriptBuf(r, pver, buf, MaxMessagePayload, + ti.SignatureScript, err = readScriptBuf(r, pver, buf, s, MaxMessagePayload, "transaction input signature script") if err != nil { return err @@ -1116,8 +1078,10 @@ func writeTxInBuf(w io.Writer, pver uint32, version int32, ti *TxIn, // ReadTxOut reads the next sequence of bytes from r as a transaction output // (TxOut). func ReadTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { + var s scriptSlab + buf := binarySerializer.Borrow() - err := readTxOutBuf(r, pver, version, to, buf) + err := readTxOutBuf(r, pver, version, to, buf, s[:]) binarySerializer.Return(buf) return err } @@ -1127,7 +1091,7 @@ func ReadTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { // small values. Otherwise a buffer will be drawn from the binarySerializer's // pool and return when the method finishes. func readTxOutBuf(r io.Reader, pver uint32, version int32, to *TxOut, - buf []byte) error { + buf, s []byte) error { _, err := io.ReadFull(r, buf) if err != nil { @@ -1135,8 +1099,10 @@ func readTxOutBuf(r io.Reader, pver uint32, version int32, to *TxOut, } to.Value = int64(littleEndian.Uint64(buf)) - to.PkScript, err = readScriptBuf(r, pver, buf, MaxMessagePayload, - "transaction output public key script") + to.PkScript, err = readScriptBuf( + r, pver, buf, s, MaxMessagePayload, + "transaction output public key script", + ) return err } From 8c4da83890c2bb1368503a13aca886cd7163df57 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Fri, 24 Jan 2020 19:47:00 -0800 Subject: [PATCH 0891/1056] wire/msgblock+msgtx: user block-level script slab --- wire/msgblock.go | 13 +++++++++---- wire/msgtx.go | 19 ++++--------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/wire/msgblock.go b/wire/msgblock.go index 34b52f08ef..6f63e0abd7 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -86,17 +86,19 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) er return messageError("MsgBlock.BtcDecode", str) } + scriptBuf := scriptPool.Borrow() msg.Transactions = make([]*MsgTx, 0, txCount) for i := uint64(0); i < txCount; i++ { tx := MsgTx{} - err := tx.btcDecode(r, pver, enc, buf) + err := tx.btcDecode(r, pver, enc, buf, scriptBuf[:]) if err != nil { + scriptPool.Return(scriptBuf) binarySerializer.Return(buf) return err } msg.Transactions = append(msg.Transactions, &tx) } - + scriptPool.Return(scriptBuf) binarySerializer.Return(buf) return nil @@ -164,6 +166,8 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { return nil, messageError("MsgBlock.DeserializeTxLoc", str) } + scriptBuf := scriptPool.Borrow() + // Deserialize each transaction while keeping track of its location // within the byte stream. msg.Transactions = make([]*MsgTx, 0, txCount) @@ -171,15 +175,16 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { for i := uint64(0); i < txCount; i++ { txLocs[i].TxStart = fullLen - r.Len() tx := MsgTx{} - err := tx.btcDecode(r, 0, WitnessEncoding, buf) + err := tx.btcDecode(r, 0, WitnessEncoding, buf, scriptBuf[:]) if err != nil { + scriptPool.Return(scriptBuf) binarySerializer.Return(buf) return nil, err } msg.Transactions = append(msg.Transactions, &tx) txLocs[i].TxLen = (fullLen - r.Len()) - txLocs[i].TxStart } - + scriptPool.Return(scriptBuf) binarySerializer.Return(buf) return txLocs, nil diff --git a/wire/msgtx.go b/wire/msgtx.go index 00a562eceb..3f91aaeb75 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -456,13 +456,15 @@ func (msg *MsgTx) Copy() *MsgTx { // database, as opposed to decoding transactions from the wire. func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() - err := msg.btcDecode(r, pver, enc, buf) + sbuf := scriptPool.Borrow() + err := msg.btcDecode(r, pver, enc, buf, sbuf[:]) + scriptPool.Return(sbuf) binarySerializer.Return(buf) return err } func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, - buf []byte) error { + buf, sbuf []byte) error { if _, err := io.ReadFull(r, buf[:4]); err != nil { return err @@ -509,9 +511,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, return messageError("MsgTx.BtcDecode", str) } - scriptBuf := scriptPool.Borrow() - sbuf := scriptBuf[:] - // Deserialize the inputs. var totalScriptSize uint64 txIns := make([]TxIn, count) @@ -523,7 +522,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, msg.TxIn[i] = ti err = readTxInBuf(r, pver, msg.Version, ti, buf, sbuf) if err != nil { - scriptPool.Return(scriptBuf) return err } totalScriptSize += uint64(len(ti.SignatureScript)) @@ -532,7 +530,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, count, err = ReadVarIntBuf(r, pver, buf) if err != nil { - scriptPool.Return(scriptBuf) return err } @@ -540,7 +537,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // message. It would be possible to cause memory exhaustion and panics // without a sane upper bound on this count. if count > uint64(maxTxOutPerMessage) { - scriptPool.Return(scriptBuf) str := fmt.Sprintf("too many output transactions to fit into "+ "max message size [count %d, max %d]", count, maxTxOutPerMessage) @@ -557,7 +553,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, msg.TxOut[i] = to err = readTxOutBuf(r, pver, msg.Version, to, buf, sbuf) if err != nil { - scriptPool.Return(scriptBuf) return err } totalScriptSize += uint64(len(to.PkScript)) @@ -573,14 +568,12 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, // varint which encodes the number of stack items. witCount, err := ReadVarIntBuf(r, pver, buf) if err != nil { - scriptPool.Return(scriptBuf) return err } // Prevent a possible memory exhaustion attack by // limiting the witCount value to a sane upper bound. if witCount > maxWitnessItemsPerInput { - scriptPool.Return(scriptBuf) str := fmt.Sprintf("too many witness items to fit "+ "into max message size [count %d, max %d]", witCount, maxWitnessItemsPerInput) @@ -597,7 +590,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, "script witness item", ) if err != nil { - scriptPool.Return(scriptBuf) return err } totalScriptSize += uint64(len(txin.Witness[j])) @@ -607,7 +599,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, } if _, err := io.ReadFull(r, buf[:4]); err != nil { - scriptPool.Return(scriptBuf) return err } msg.LockTime = littleEndian.Uint32(buf[:4]) @@ -670,8 +661,6 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, offset += scriptSize } - scriptPool.Return(scriptBuf) - return nil } From 1f2dfa2d6e2c90ae6770d08c2530625aa92523d4 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 17:37:44 +0900 Subject: [PATCH 0892/1056] blockchain: Add mapslice This change is part of the effort to add utxocache support to btcd. mapslice allows the caller to allocate a fixed amount of memory for the utxo cache maps without the mapslice going over that fixed amount of memory. This is useful as we can have variable sizes (1GB, 1.1GB, 2.3GB, etc) while guaranteeing a memory limit. --- blockchain/utxocache.go | 167 +++++++++++++++++++++++++++++++++++ blockchain/utxocache_test.go | 167 +++++++++++++++++++++++++++++++++++ 2 files changed, 334 insertions(+) create mode 100644 blockchain/utxocache.go create mode 100644 blockchain/utxocache_test.go diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go new file mode 100644 index 0000000000..0c2e99c5a2 --- /dev/null +++ b/blockchain/utxocache.go @@ -0,0 +1,167 @@ +// Copyright (c) 2023 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "sync" + + "github.com/btcsuite/btcd/wire" +) + +// mapSlice is a slice of maps for utxo entries. The slice of maps are needed to +// guarantee that the map will only take up N amount of bytes. As of v1.20, the +// go runtime will allocate 2^N + few extra buckets, meaning that for large N, we'll +// allocate a lot of extra memory if the amount of entries goes over the previously +// allocated buckets. A slice of maps allows us to have a better control of how much +// total memory gets allocated by all the maps. +type mapSlice struct { + // mtx protects against concurrent access for the map slice. + mtx sync.Mutex + + // maps are the underlying maps in the slice of maps. + maps []map[wire.OutPoint]*UtxoEntry + + // maxEntries is the maximum amount of elements that the map is allocated for. + maxEntries []int + + // maxTotalMemoryUsage is the maximum memory usage in bytes that the state + // should contain in normal circumstances. + maxTotalMemoryUsage uint64 +} + +// length returns the length of all the maps in the map slice added together. +// +// This function is safe for concurrent access. +func (ms *mapSlice) length() int { + ms.mtx.Lock() + defer ms.mtx.Unlock() + + var l int + for _, m := range ms.maps { + l += len(m) + } + + return l +} + +// size returns the size of all the maps in the map slice added together. +// +// This function is safe for concurrent access. +func (ms *mapSlice) size() int { + ms.mtx.Lock() + defer ms.mtx.Unlock() + + var size int + for _, num := range ms.maxEntries { + size += calculateRoughMapSize(num, bucketSize) + } + + return size +} + +// get looks for the outpoint in all the maps in the map slice and returns +// the entry. nil and false is returned if the outpoint is not found. +// +// This function is safe for concurrent access. +func (ms *mapSlice) get(op wire.OutPoint) (*UtxoEntry, bool) { + ms.mtx.Lock() + defer ms.mtx.Unlock() + + var entry *UtxoEntry + var found bool + + for _, m := range ms.maps { + entry, found = m[op] + if found { + return entry, found + } + } + + return nil, false +} + +// put puts the outpoint and the entry into one of the maps in the map slice. If the +// existing maps are all full, it will allocate a new map based on how much memory we +// have left over. Leftover memory is calculated as: +// maxTotalMemoryUsage - (totalEntryMemory + mapSlice.size()) +// +// This function is safe for concurrent access. +func (ms *mapSlice) put(op wire.OutPoint, entry *UtxoEntry, totalEntryMemory uint64) { + ms.mtx.Lock() + defer ms.mtx.Unlock() + + for i, maxNum := range ms.maxEntries { + m := ms.maps[i] + _, found := m[op] + if found { + // If the key is found, overwrite it. + m[op] = entry + return // Return as we were successful in adding the entry. + } + if len(m) >= maxNum { + // Don't try to insert if the map already at max since + // that'll force the map to allocate double the memory it's + // currently taking up. + continue + } + + m[op] = entry + return // Return as we were successful in adding the entry. + } + + // We only reach this code if we've failed to insert into the map above as + // all the current maps were full. We thus make a new map and insert into + // it. + m := ms.makeNewMap(totalEntryMemory) + m[op] = entry +} + +// delete attempts to delete the given outpoint in all of the maps. No-op if the +// outpoint doesn't exist. +// +// This function is safe for concurrent access. +func (ms *mapSlice) delete(op wire.OutPoint) { + ms.mtx.Lock() + defer ms.mtx.Unlock() + + for i := 0; i < len(ms.maps); i++ { + delete(ms.maps[i], op) + } +} + +// makeNewMap makes and appends the new map into the map slice. +// +// This function is NOT safe for concurrent access and must be called with the +// lock held. +func (ms *mapSlice) makeNewMap(totalEntryMemory uint64) map[wire.OutPoint]*UtxoEntry { + // Get the size of the leftover memory. + memSize := ms.maxTotalMemoryUsage - totalEntryMemory + for _, maxNum := range ms.maxEntries { + memSize -= uint64(calculateRoughMapSize(maxNum, bucketSize)) + } + + // Get a new map that's sized to house inside the leftover memory. + // -1 on the returned value will make the map allocate half as much total + // bytes. This is done to make sure there's still room left for utxo + // entries to take up. + numMaxElements := calculateMinEntries(int(memSize), bucketSize+avgEntrySize) + numMaxElements -= 1 + ms.maxEntries = append(ms.maxEntries, numMaxElements) + ms.maps = append(ms.maps, make(map[wire.OutPoint]*UtxoEntry, numMaxElements)) + + return ms.maps[len(ms.maps)-1] +} + +// deleteMaps deletes all maps except for the first one which should be the biggest. +// +// This function is safe for concurrent access. +func (ms *mapSlice) deleteMaps() { + ms.mtx.Lock() + defer ms.mtx.Unlock() + + size := ms.maxEntries[0] + ms.maxEntries = []int{size} + ms.maps = ms.maps[:1] +} diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go new file mode 100644 index 0000000000..41478efdbc --- /dev/null +++ b/blockchain/utxocache_test.go @@ -0,0 +1,167 @@ +// Copyright (c) 2023 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. +package blockchain + +import ( + "crypto/sha256" + "encoding/binary" + "reflect" + "sync" + "testing" + + "github.com/btcsuite/btcd/wire" +) + +func TestMapSlice(t *testing.T) { + tests := []struct { + keys []wire.OutPoint + }{ + { + keys: func() []wire.OutPoint { + outPoints := make([]wire.OutPoint, 1000) + for i := uint32(0); i < uint32(len(outPoints)); i++ { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], i) + hash := sha256.Sum256(buf[:]) + + op := wire.OutPoint{Hash: hash, Index: i} + outPoints[i] = op + } + return outPoints + }(), + }, + } + + for _, test := range tests { + m := make(map[wire.OutPoint]*UtxoEntry) + + maxSize := calculateRoughMapSize(1000, bucketSize) + + maxEntriesFirstMap := 500 + ms1 := make(map[wire.OutPoint]*UtxoEntry, maxEntriesFirstMap) + ms := mapSlice{ + maps: []map[wire.OutPoint]*UtxoEntry{ms1}, + maxEntries: []int{maxEntriesFirstMap}, + maxTotalMemoryUsage: uint64(maxSize), + } + + for _, key := range test.keys { + m[key] = nil + ms.put(key, nil, 0) + } + + // Put in the same elements twice to test that the map slice won't hold duplicates. + for _, key := range test.keys { + m[key] = nil + ms.put(key, nil, 0) + } + + if len(m) != ms.length() { + t.Fatalf("expected len of %d, got %d", len(m), ms.length()) + } + + for _, key := range test.keys { + expected, found := m[key] + if !found { + t.Fatalf("expected key %s to exist in the go map", key.String()) + } + + got, found := ms.get(key) + if !found { + t.Fatalf("expected key %s to exist in the map slice", key.String()) + } + + if !reflect.DeepEqual(got, expected) { + t.Fatalf("expected value of %v, got %v", expected, got) + } + } + } +} + +// TestMapsliceConcurrency just tests that the mapslice won't result in a panic +// on concurrent access. +func TestMapsliceConcurrency(t *testing.T) { + tests := []struct { + keys []wire.OutPoint + }{ + { + keys: func() []wire.OutPoint { + outPoints := make([]wire.OutPoint, 10000) + for i := uint32(0); i < uint32(len(outPoints)); i++ { + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], i) + hash := sha256.Sum256(buf[:]) + + op := wire.OutPoint{Hash: hash, Index: i} + outPoints[i] = op + } + return outPoints + }(), + }, + } + + for _, test := range tests { + maxSize := calculateRoughMapSize(1000, bucketSize) + + maxEntriesFirstMap := 500 + ms1 := make(map[wire.OutPoint]*UtxoEntry, maxEntriesFirstMap) + ms := mapSlice{ + maps: []map[wire.OutPoint]*UtxoEntry{ms1}, + maxEntries: []int{maxEntriesFirstMap}, + maxTotalMemoryUsage: uint64(maxSize), + } + + var wg sync.WaitGroup + + wg.Add(1) + go func(m *mapSlice, keys []wire.OutPoint) { + defer wg.Done() + for i := 0; i < 5000; i++ { + m.put(keys[i], nil, 0) + } + }(&ms, test.keys) + + wg.Add(1) + go func(m *mapSlice, keys []wire.OutPoint) { + defer wg.Done() + for i := 5000; i < 10000; i++ { + m.put(keys[i], nil, 0) + } + }(&ms, test.keys) + + wg.Add(1) + go func(m *mapSlice) { + defer wg.Done() + for i := 0; i < 10000; i++ { + m.size() + } + }(&ms) + + wg.Add(1) + go func(m *mapSlice) { + defer wg.Done() + for i := 0; i < 10000; i++ { + m.length() + } + }(&ms) + + wg.Add(1) + go func(m *mapSlice, keys []wire.OutPoint) { + defer wg.Done() + for i := 0; i < 10000; i++ { + m.get(keys[i]) + } + }(&ms, test.keys) + + wg.Add(1) + go func(m *mapSlice, keys []wire.OutPoint) { + defer wg.Done() + for i := 0; i < 5000; i++ { + m.delete(keys[i]) + } + }(&ms, test.keys) + + wg.Wait() + } +} From 35c42688d9a13a4f120693b3fdff6c2663449f13 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 16:46:05 +0900 Subject: [PATCH 0893/1056] blockchain: Add tfFresh to txoFlags This change is part of the effort to add utxocache support to btcd. The fresh flag indicates that the entry is fresh and that the parent view (the database) hasn't yet seen the entry. This is very useful as a performance optimization for the utxo cache as if a fresh entry is spent, we can simply remove it from the cache and don't bother trying to delete it from the database. --- blockchain/utxoviewpoint.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index a030c9a9ff..c66e9cdbb6 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -28,6 +28,13 @@ const ( // tfModified indicates that a txout has been modified since it was // loaded. tfModified + + // tfFresh indicates that the entry is fresh. This means that the parent + // view never saw this entry. Note that tfFresh is a performance + // optimization with which we can erase entries that are fully spent if we + // know we do not need to commit them. It is always safe to not mark + // tfFresh if that condition is not guaranteed. + tfFresh ) // UtxoEntry houses details about an individual transaction output in a utxo @@ -58,6 +65,12 @@ func (entry *UtxoEntry) isModified() bool { return entry.packedFlags&tfModified == tfModified } +// isFresh returns whether or not it's certain the output has never previously +// been stored in the database. +func (entry *UtxoEntry) isFresh() bool { + return entry.packedFlags&tfFresh == tfFresh +} + // IsCoinBase returns whether or not the output was contained in a coinbase // transaction. func (entry *UtxoEntry) IsCoinBase() bool { @@ -199,7 +212,7 @@ func (view *UtxoViewpoint) addTxOut(outpoint wire.OutPoint, txOut *wire.TxOut, i entry.amount = txOut.Value entry.pkScript = txOut.PkScript entry.blockHeight = blockHeight - entry.packedFlags = tfModified + entry.packedFlags = tfFresh | tfModified if isCoinBase { entry.packedFlags |= tfCoinBase } From 27cf70216f3d2be91be41c92194b812fb7c4795b Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 17:04:12 +0900 Subject: [PATCH 0894/1056] blockchain: Add memoryUsage() method on UtxoEntry This change is part of the effort to add utxocache support to btcd. Getting the memory usage of an entry is very useful for the utxo cache as we need to know how much memory all the cached entries are using to guarantee a cache usage limit for the end user. --- blockchain/utxoviewpoint.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index c66e9cdbb6..0a6b5552ac 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -71,6 +71,16 @@ func (entry *UtxoEntry) isFresh() bool { return entry.packedFlags&tfFresh == tfFresh } +// memoryUsage returns the memory usage in bytes of for the utxo entry. +// It returns 0 for a nil entry. +func (entry *UtxoEntry) memoryUsage() uint64 { + if entry == nil { + return 0 + } + + return baseEntrySize + uint64(cap(entry.pkScript)) +} + // IsCoinBase returns whether or not the output was contained in a coinbase // transaction. func (entry *UtxoEntry) IsCoinBase() bool { From fc6574413486ec39e9d2007cbcfca87f14577343 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 17:27:28 +0900 Subject: [PATCH 0895/1056] blockchain: Add utxoStateConsistency read and write functions This change is part of the effort to add utxocache support to btcd. The utxoStateConsistency indicates what the last block that the utxo cache got flush at. This is useful for recovery purposes as if the node is unexpectdly shut down, we know which block to start rebuilding the utxo state from. --- blockchain/chainio.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 21f0d5baf1..8c9ee28349 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -51,6 +51,10 @@ var ( // chain state. chainStateKeyName = []byte("chainstate") + // utxoStateConsistencyKeyName is the name of the db key used to store the + // consistency status of the utxo state. + utxoStateConsistencyKeyName = []byte("utxostateconsistency") + // spendJournalVersionKeyName is the name of the db key used to store // the version of the spend journal currently in the database. spendJournalVersionKeyName = []byte("spendjournalversion") @@ -1014,6 +1018,21 @@ func dbPutBestState(dbTx database.Tx, snapshot *BestState, workSum *big.Int) err return dbTx.Metadata().Put(chainStateKeyName, serializedData) } +// dbPutUtxoStateConsistency uses an existing database transaction to +// update the utxo state consistency status with the given parameters. +func dbPutUtxoStateConsistency(dbTx database.Tx, hash *chainhash.Hash) error { + // Store the utxo state consistency status into the database. + return dbTx.Metadata().Put(utxoStateConsistencyKeyName, hash[:]) +} + +// dbFetchUtxoStateConsistency uses an existing database transaction to retrieve +// the utxo state consistency status from the database. The code is 0 when +// nothing was found. +func dbFetchUtxoStateConsistency(dbTx database.Tx) []byte { + // Fetch the serialized data from the database. + return dbTx.Metadata().Get(utxoStateConsistencyKeyName) +} + // createChainState initializes both the database and the chain state to the // genesis block. This includes creating the necessary buckets and inserting // the genesis block, so it must only be called on an uninitialized database. From d86e79eb79264aeff8c94afc9db1da1d1974b715 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 21 Jul 2023 17:13:49 +0900 Subject: [PATCH 0896/1056] blockchain: Refactor dbPutUtxoView This change is part of the effort to add utxocache support to btcd. dbPutUtxoView handled putting and deleting new/spent utxos from the database. These two functinalities are refactored to their own functions: dbDeleteUtxoEntry and dbPutUtxoEntry. Refactoring these out allows the cache to call these two functions directly instead of having to create a view and saving that view to disk. --- blockchain/chainio.go | 60 +++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 8c9ee28349..33ed91f58d 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -799,32 +799,54 @@ func dbPutUtxoView(dbTx database.Tx, view *UtxoViewpoint) error { // Remove the utxo entry if it is spent. if entry.IsSpent() { - key := outpointKey(outpoint) - err := utxoBucket.Delete(*key) - recycleOutpointKey(key) + err := dbDeleteUtxoEntry(utxoBucket, outpoint) + if err != nil { + return err + } + } else { + err := dbPutUtxoEntry(utxoBucket, outpoint, entry) if err != nil { return err } - - continue } + } - // Serialize and store the utxo entry. - serialized, err := serializeUtxoEntry(entry) - if err != nil { - return err - } - key := outpointKey(outpoint) - err = utxoBucket.Put(*key, serialized) - // NOTE: The key is intentionally not recycled here since the - // database interface contract prohibits modifications. It will - // be garbage collected normally when the database is done with - // it. - if err != nil { - return err - } + return nil +} + +// dbDeleteUtxoEntry uses an existing database transaction to delete the utxo +// entry from the database. +func dbDeleteUtxoEntry(utxoBucket database.Bucket, outpoint wire.OutPoint) error { + key := outpointKey(outpoint) + err := utxoBucket.Delete(*key) + recycleOutpointKey(key) + return err +} + +// dbPutUtxoEntry uses an existing database transaction to update the utxo entry +// in the database. +func dbPutUtxoEntry(utxoBucket database.Bucket, outpoint wire.OutPoint, + entry *UtxoEntry) error { + + if entry == nil || entry.IsSpent() { + return AssertError("trying to store nil or spent entry") + } + + // Serialize and store the utxo entry. + serialized, err := serializeUtxoEntry(entry) + if err != nil { + return err + } + key := outpointKey(outpoint) + err = utxoBucket.Put(*key, serialized) + if err != nil { + return err } + // NOTE: The key is intentionally not recycled here since the + // database interface contract prohibits modifications. It will + // be garbage collected normally when the database is done with + // it. return nil } From 953d62afa720e489ff2456f20da21cbb341fc597 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 21 Jul 2023 17:14:24 +0900 Subject: [PATCH 0897/1056] blockchain: Return early on nil utxo view in dbPutUtxoView This change is part of the effort to add utxocache support to btcd. connectBlock may have an empty utxoviewpoint as the block verification process may be using the utxo cache directly. In that case, a nil utxo viewpoint will be passed in. Just return early on a nil utxoviewpoint. --- blockchain/chainio.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 33ed91f58d..3013be3dc1 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -790,6 +790,10 @@ func dbFetchUtxoEntry(dbTx database.Tx, outpoint wire.OutPoint) (*UtxoEntry, err // particular, only the entries that have been marked as modified are written // to the database. func dbPutUtxoView(dbTx database.Tx, view *UtxoViewpoint) error { + // Return early if the view is nil. + if view == nil { + return nil + } utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) for outpoint, entry := range view.entries { // No need to update the database if the entry was not modified. From bcd8f547fee62b1e1592ebe39d115adf4168b245 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 18:01:56 +0900 Subject: [PATCH 0898/1056] blockchain: Require utxoBucket in dbFetchUtxoEntry This change is part of the effort to add utxocache support to btcd. Require the caller to pass in the utxoBucket as the caller may be fetching many utxos in one loop. Having the caller pass it in removes the need for dbFetchUtxoEntry to grab the bucket on every single fetch. --- blockchain/chainio.go | 5 +++-- blockchain/utxoviewpoint.go | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 3013be3dc1..22aac08343 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -748,11 +748,12 @@ func dbFetchUtxoEntryByHash(dbTx database.Tx, hash *chainhash.Hash) (*UtxoEntry, // // When there is no entry for the provided output, nil will be returned for both // the entry and the error. -func dbFetchUtxoEntry(dbTx database.Tx, outpoint wire.OutPoint) (*UtxoEntry, error) { +func dbFetchUtxoEntry(dbTx database.Tx, utxoBucket database.Bucket, + outpoint wire.OutPoint) (*UtxoEntry, error) { + // Fetch the unspent transaction output information for the passed // transaction output. Return now when there is no entry. key := outpointKey(outpoint) - utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) serializedUtxo := utxoBucket.Get(*key) recycleOutpointKey(key) if serializedUtxo == nil { diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 0a6b5552ac..2ae8de910d 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -540,8 +540,9 @@ func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints []wire.OutPo // so other code can use the presence of an entry in the store as a way // to unnecessarily avoid attempting to reload it from the database. return db.View(func(dbTx database.Tx) error { + utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) for i := range outpoints { - entry, err := dbFetchUtxoEntry(dbTx, outpoints[i]) + entry, err := dbFetchUtxoEntry(dbTx, utxoBucket, outpoints[i]) if err != nil { return err } @@ -691,7 +692,8 @@ func (b *BlockChain) FetchUtxoEntry(outpoint wire.OutPoint) (*UtxoEntry, error) var entry *UtxoEntry err := b.db.View(func(dbTx database.Tx) error { var err error - entry, err = dbFetchUtxoEntry(dbTx, outpoint) + utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) + entry, err = dbFetchUtxoEntry(dbTx, utxoBucket, outpoint) return err }) if err != nil { From 053ef330f216c1c7a1e3f9073413ad57fcbf511f Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 19 May 2023 00:29:45 +0900 Subject: [PATCH 0899/1056] blockchain: Refactor fetchInputUtxos This change is part of the effort to add utxocache support to btcd. fetchInputUtxos had mainly 2 functions: 1: Figure out which outpoints to fetch 2: Call fetchUtxosMain to fetch those outpoints Functionality for (1) is refactored out to fetchInputsToFetch. This is done to allow fetchInputUtxos to use the cache to fetch the outpoints as well in a later commit. --- blockchain/utxoviewpoint.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 2ae8de910d..c5ff673b0a 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -578,12 +578,11 @@ func (view *UtxoViewpoint) fetchUtxos(db database.DB, outpoints []wire.OutPoint) return view.fetchUtxosMain(db, needed) } -// fetchInputUtxos loads the unspent transaction outputs for the inputs -// referenced by the transactions in the given block into the view from the -// database as needed. In particular, referenced entries that are earlier in -// the block are added to the view and entries that are already in the view are -// not modified. -func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) error { +// findInputsToFetch goes through all the blocks and returns all the outpoints of +// the entries that need to be fetched in order to validate the block. Outpoints +// for the entries that are already in the block are not included in the returned +// outpoints. +func (view *UtxoViewpoint) findInputsToFetch(block *btcutil.Block) []wire.OutPoint { // Build a map of in-flight transactions because some of the inputs in // this block could be referencing other transactions earlier in this // block which are not yet in the chain. @@ -629,8 +628,17 @@ func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) } } - // Request the input utxos from the database. - return view.fetchUtxosMain(db, needed) + return needed +} + +// fetchInputUtxos loads the unspent transaction outputs for the inputs +// referenced by the transactions in the given block into the view from the +// database as needed. In particular, referenced entries that are earlier in +// the block are added to the view and entries that are already in the view are +// not modified. +func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) error { + // Request the input utxos from the cache. + return view.fetchUtxosMain(db, view.findInputsToFetch(block)) } // NewUtxoViewpoint returns a new empty unspent transaction output view. From 3c11e48dd28ecaf215ed7288df722f730ea34701 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 18:09:31 +0900 Subject: [PATCH 0900/1056] blockchain: Add utxocache The implemented utxocache implements connectTransactions just like utxoviewpoint and can be used as a drop in replacement for connectTransactions. One thing to note is that unlike the utxoViewpoint, the utxocache immediately deletes the spent entry from the cache. This means that the utxocache is unfit for functions like checkConnectBlock where you expect the entry to still exist but be marked as spent. disconnectTransactions is purposely not implemented as using the cache during reorganizations may leave the utxo state inconsistent if there is an unexpected shutdown. The utxoViewpoint will still have to be used for reorganizations. --- blockchain/utxocache.go | 413 +++++++++++++++++++++++++++++++++++ blockchain/utxocache_test.go | 140 ++++++++++++ 2 files changed, 553 insertions(+) diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index 0c2e99c5a2..3f3c246e66 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -5,8 +5,14 @@ package blockchain import ( + "fmt" "sync" + "time" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" ) @@ -165,3 +171,410 @@ func (ms *mapSlice) deleteMaps() { ms.maxEntries = []int{size} ms.maps = ms.maps[:1] } + +const ( + // utxoFlushPeriodicInterval is the interval at which a flush is performed + // when the flush mode FlushPeriodic is used. This is used when the initial + // block download is complete and it's useful to flush periodically in case + // of unforseen shutdowns. + utxoFlushPeriodicInterval = time.Minute * 5 +) + +// FlushMode is used to indicate the different urgency types for a flush. +type FlushMode uint8 + +const ( + // FlushRequired is the flush mode that means a flush must be performed + // regardless of the cache state. For example right before shutting down. + FlushRequired FlushMode = iota + + // FlushPeriodic is the flush mode that means a flush can be performed + // when it would be almost needed. This is used to periodically signal when + // no I/O heavy operations are expected soon, so there is time to flush. + FlushPeriodic + + // FlushIfNeeded is the flush mode that means a flush must be performed only + // if the cache is exceeding a safety threshold very close to its maximum + // size. This is used mostly internally in between operations that can + // increase the cache size. + FlushIfNeeded +) + +// utxoCache is a cached utxo view in the chainstate of a BlockChain. +type utxoCache struct { + db database.DB + + // maxTotalMemoryUsage is the maximum memory usage in bytes that the state + // should contain in normal circumstances. + maxTotalMemoryUsage uint64 + + // cachedEntries keeps the internal cache of the utxo state. The tfModified + // flag indicates that the state of the entry (potentially) deviates from the + // state in the database. Explicit nil values in the map are used to + // indicate that the database does not contain the entry. + cachedEntries mapSlice + totalEntryMemory uint64 // Total memory usage in bytes. + + // Below fields are used to indicate when the last flush happened. + lastFlushHash chainhash.Hash + lastFlushTime time.Time +} + +// newUtxoCache initiates a new utxo cache instance with its memory usage limited +// to the given maximum. +func newUtxoCache(db database.DB, maxTotalMemoryUsage uint64) *utxoCache { + // While the entry isn't included in the map size, add the average size to the + // bucket size so we get some leftover space for entries to take up. + numMaxElements := calculateMinEntries(int(maxTotalMemoryUsage), bucketSize+avgEntrySize) + numMaxElements -= 1 + + log.Infof("Pre-alloacting for %d MiB: ", maxTotalMemoryUsage/(1024*1024)+1) + + m := make(map[wire.OutPoint]*UtxoEntry, numMaxElements) + + return &utxoCache{ + db: db, + maxTotalMemoryUsage: maxTotalMemoryUsage, + cachedEntries: mapSlice{ + maps: []map[wire.OutPoint]*UtxoEntry{m}, + maxEntries: []int{numMaxElements}, + maxTotalMemoryUsage: maxTotalMemoryUsage, + }, + } +} + +// totalMemoryUsage returns the total memory usage in bytes of the UTXO cache. +func (s *utxoCache) totalMemoryUsage() uint64 { + // Total memory is the map size + the size that the utxo entries are + // taking up. + size := uint64(s.cachedEntries.size()) + size += s.totalEntryMemory + + return size +} + +// fetchEntries returns the UTXO entries for the given outpoints. The function always +// returns as many entries as there are outpoints and the returns entries are in the +// same order as the outpoints. It returns nil if there is no entry for the outpoint +// in the UTXO set. +// +// The returned entries are NOT safe for concurrent access. +func (s *utxoCache) fetchEntries(outpoints []wire.OutPoint) ([]*UtxoEntry, error) { + entries := make([]*UtxoEntry, len(outpoints)) + var missingOps []wire.OutPoint + var missingOpsIdx []int + for i := range outpoints { + if entry, ok := s.cachedEntries.get(outpoints[i]); ok { + entries[i] = entry + continue + } + + // At this point, we have missing outpoints. Allocate them now + // so that we never allocate if the cache never misses. + if len(missingOps) == 0 { + missingOps = make([]wire.OutPoint, 0, len(outpoints)) + missingOpsIdx = make([]int, 0, len(outpoints)) + } + + missingOpsIdx = append(missingOpsIdx, i) + missingOps = append(missingOps, outpoints[i]) + } + + // Return early and don't attempt access the database if we don't have any + // missing outpoints. + if len(missingOps) == 0 { + return entries, nil + } + + // Fetch the missing outpoints in the cache from the database. + dbEntries := make([]*UtxoEntry, len(missingOps)) + err := s.db.View(func(dbTx database.Tx) error { + utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) + + for i := range missingOps { + entry, err := dbFetchUtxoEntry(dbTx, utxoBucket, missingOps[i]) + if err != nil { + return err + } + + dbEntries[i] = entry + } + + return nil + }) + if err != nil { + return nil, err + } + + // Add each of the entries to the UTXO cache and update their memory + // usage. + // + // NOTE: When the fetched entry is nil, it is still added to the cache + // as a miss; this prevents future lookups to perform the same database + // fetch. + for i := range dbEntries { + s.cachedEntries.put(missingOps[i], dbEntries[i], s.totalEntryMemory) + s.totalEntryMemory += dbEntries[i].memoryUsage() + } + + // Fill in the entries with the ones fetched from the database. + for i := range missingOpsIdx { + entries[missingOpsIdx[i]] = dbEntries[i] + } + + return entries, nil +} + +// addTxOut adds the specified output to the cache if it is not provably +// unspendable. When the cache already has an entry for the output, it will be +// overwritten with the given output. All fields will be updated for existing +// entries since it's possible it has changed during a reorg. +func (s *utxoCache) addTxOut( + outpoint wire.OutPoint, txOut *wire.TxOut, isCoinBase bool, blockHeight int32) error { + + // Don't add provably unspendable outputs. + if txscript.IsUnspendable(txOut.PkScript) { + return nil + } + + entry := new(UtxoEntry) + entry.amount = txOut.Value + // Deep copy the script when the script in the entry differs from the one in + // the txout. This is required since the txout script is a subslice of the + // overall contiguous buffer that the msg tx houses for all scripts within + // the tx. It is deep copied here since this entry may be added to the utxo + // cache, and we don't want the utxo cache holding the entry to prevent all + // of the other tx scripts from getting garbage collected. + entry.pkScript = make([]byte, len(txOut.PkScript)) + copy(entry.pkScript, txOut.PkScript) + + entry.blockHeight = blockHeight + entry.packedFlags = tfFresh | tfModified + if isCoinBase { + entry.packedFlags |= tfCoinBase + } + + s.cachedEntries.put(outpoint, entry, s.totalEntryMemory) + s.totalEntryMemory += entry.memoryUsage() + + return nil +} + +// addTxOuts adds all outputs in the passed transaction which are not provably +// unspendable to the view. When the view already has entries for any of the +// outputs, they are simply marked unspent. All fields will be updated for +// existing entries since it's possible it has changed during a reorg. +func (s *utxoCache) addTxOuts(tx *btcutil.Tx, blockHeight int32) error { + // Loop all of the transaction outputs and add those which are not + // provably unspendable. + isCoinBase := IsCoinBase(tx) + prevOut := wire.OutPoint{Hash: *tx.Hash()} + for txOutIdx, txOut := range tx.MsgTx().TxOut { + // Update existing entries. All fields are updated because it's + // possible (although extremely unlikely) that the existing + // entry is being replaced by a different transaction with the + // same hash. This is allowed so long as the previous + // transaction is fully spent. + prevOut.Index = uint32(txOutIdx) + err := s.addTxOut(prevOut, txOut, isCoinBase, blockHeight) + if err != nil { + return err + } + } + + return nil +} + +// addTxIn will add the given input to the cache if the previous outpoint the txin +// is pointing to exists in the utxo set. The utxo that is being spent by the input +// will be marked as spent and if the utxo is fresh (meaning that the database on disk +// never saw it), it will be removed from the cache. +func (s *utxoCache) addTxIn(txIn *wire.TxIn, stxos *[]SpentTxOut) error { + // Ensure the referenced utxo exists in the view. This should + // never happen unless there is a bug is introduced in the code. + entries, err := s.fetchEntries([]wire.OutPoint{txIn.PreviousOutPoint}) + if err != nil { + return err + } + if len(entries) != 1 || entries[0] == nil { + return AssertError(fmt.Sprintf("missing input %v", + txIn.PreviousOutPoint)) + } + + // Only create the stxo details if requested. + entry := entries[0] + if stxos != nil { + // Populate the stxo details using the utxo entry. + var stxo = SpentTxOut{ + Amount: entry.Amount(), + PkScript: entry.PkScript(), + Height: entry.BlockHeight(), + IsCoinBase: entry.IsCoinBase(), + } + + *stxos = append(*stxos, stxo) + } + + // Mark the entry as spent. + entry.Spend() + + // If an entry is fresh it indicates that this entry was spent before it could be + // flushed to the database. Because of this, we can just delete it from the map of + // cached entries. + if entry.isFresh() { + // If the entry is fresh, we will always have it in the cache. + s.cachedEntries.delete(txIn.PreviousOutPoint) + s.totalEntryMemory -= entry.memoryUsage() + } else { + // Can leave the entry to be garbage collected as the only purpose + // of this entry now is so that the entry on disk can be deleted. + entry = nil + s.totalEntryMemory -= entry.memoryUsage() + } + + return nil +} + +// addTxIns will add the given inputs of the tx if it's not a coinbase tx and if +// the previous output that the input is pointing to exists in the utxo set. The +// utxo that is being spent by the input will be marked as spent and if the utxo +// is fresh (meaning that the database on disk never saw it), it will be removed +// from the cache. +func (s *utxoCache) addTxIns(tx *btcutil.Tx, stxos *[]SpentTxOut) error { + // Coinbase transactions don't have any inputs to spend. + if IsCoinBase(tx) { + return nil + } + + for _, txIn := range tx.MsgTx().TxIn { + err := s.addTxIn(txIn, stxos) + if err != nil { + return err + } + } + + return nil +} + +// connectTransaction updates the cache by adding all new utxos created by the +// passed transaction and marking and/or removing all utxos that the transactions +// spend as spent. In addition, when the 'stxos' argument is not nil, it will +// be updated to append an entry for each spent txout. An error will be returned +// if the cache and the database does not contain the required utxos. +func (s *utxoCache) connectTransaction( + tx *btcutil.Tx, blockHeight int32, stxos *[]SpentTxOut) error { + + err := s.addTxIns(tx, stxos) + if err != nil { + return err + } + + // Add the transaction's outputs as available utxos. + return s.addTxOuts(tx, blockHeight) +} + +// connectTransactions updates the cache by adding all new utxos created by all +// of the transactions in the passed block, marking and/or removing all utxos +// the transactions spend as spent, and setting the best hash for the view to +// the passed block. In addition, when the 'stxos' argument is not nil, it will +// be updated to append an entry for each spent txout. +func (s *utxoCache) connectTransactions(block *btcutil.Block, stxos *[]SpentTxOut) error { + for _, tx := range block.Transactions() { + err := s.connectTransaction(tx, block.Height(), stxos) + if err != nil { + return err + } + } + + return nil +} + +// writeCache writes all the entries that are cached in memory to the database atomically. +func (s *utxoCache) writeCache(dbTx database.Tx, bestState *BestState) error { + // Update commits and flushes the cache to the database. + // NOTE: The database has its own cache which gets atomically written + // to leveldb. + utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) + for i := range s.cachedEntries.maps { + for outpoint, entry := range s.cachedEntries.maps[i] { + // If the entry is nil or spent, remove the entry from the database + // and the cache. + if entry == nil || entry.IsSpent() { + err := dbDeleteUtxoEntry(utxoBucket, outpoint) + if err != nil { + return err + } + delete(s.cachedEntries.maps[i], outpoint) + + continue + } + + // No need to update the cache if the entry was not modified. + if !entry.isModified() { + delete(s.cachedEntries.maps[i], outpoint) + continue + } + + // Entry is fresh and needs to be put into the database. + err := dbPutUtxoEntry(utxoBucket, outpoint, entry) + if err != nil { + return err + } + delete(s.cachedEntries.maps[i], outpoint) + } + } + s.cachedEntries.deleteMaps() + s.totalEntryMemory = 0 + + // When done, store the best state hash in the database to indicate the state + // is consistent until that hash. + err := dbPutUtxoStateConsistency(dbTx, &bestState.Hash) + if err != nil { + return err + } + + // The best state is the new last flush hash. + s.lastFlushHash = bestState.Hash + s.lastFlushTime = time.Now() + + return nil +} + +// flush flushes the UTXO state to the database if a flush is needed with the given flush mode. +// +// This function MUST be called with the chain state lock held (for writes). +func (s *utxoCache) flush(dbTx database.Tx, mode FlushMode, bestState *BestState) error { + var threshold uint64 + switch mode { + case FlushRequired: + threshold = 0 + + case FlushIfNeeded: + // If we performed a flush in the current best state, we have nothing to do. + if bestState.Hash == s.lastFlushHash { + return nil + } + + threshold = s.maxTotalMemoryUsage + + case FlushPeriodic: + // If the time since the last flush is over the periodic interval, + // force a flush. Otherwise just flush when the cache is full. + if time.Since(s.lastFlushTime) > utxoFlushPeriodicInterval { + threshold = 0 + } else { + threshold = s.maxTotalMemoryUsage + } + } + + if s.totalMemoryUsage() >= threshold { + // Add one to round up the integer division. + totalMiB := s.totalMemoryUsage() / ((1024 * 1024) + 1) + log.Infof("Flushing UTXO cache of %d MiB with %d entries to disk. For large sizes, "+ + "this can take up to several minutes...", totalMiB, s.cachedEntries.length()) + + return s.writeCache(dbTx, bestState) + } + + return nil +} diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 41478efdbc..aa748e50e9 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -165,3 +165,143 @@ func TestMapsliceConcurrency(t *testing.T) { wg.Wait() } } + +// getValidP2PKHScript returns a valid P2PKH script. Useful as unspendables cannot be +// added to the cache. +func getValidP2PKHScript() []byte { + validP2PKHScript := []byte{ + // OP_DUP + 0x76, + // OP_HASH160 + 0xa9, + // OP_DATA_20 + 0x14, + // <20-byte pubkey hash> + 0xf0, 0x7a, 0xb8, 0xce, 0x72, 0xda, 0x4e, 0x76, + 0x0b, 0x74, 0x7d, 0x48, 0xd6, 0x65, 0xec, 0x96, + 0xad, 0xf0, 0x24, 0xf5, + // OP_EQUALVERIFY + 0x88, + // OP_CHECKSIG + 0xac, + } + return validP2PKHScript +} + +// outpointFromInt generates an outpoint from an int by hashing the int and making +// the given int the index. +func outpointFromInt(i int) wire.OutPoint { + // Boilerplate to create an outpoint. + var buf [4]byte + binary.BigEndian.PutUint32(buf[:], uint32(i)) + hash := sha256.Sum256(buf[:]) + return wire.OutPoint{Hash: hash, Index: uint32(i)} +} + +func TestUtxoCacheEntrySize(t *testing.T) { + type block struct { + txOuts []*wire.TxOut + outOps []wire.OutPoint + txIns []*wire.TxIn + } + tests := []struct { + name string + blocks []block + expectedSize uint64 + }{ + { + name: "one entry", + blocks: func() []block { + return []block{ + { + txOuts: []*wire.TxOut{ + {Value: 10000, PkScript: getValidP2PKHScript()}, + }, + outOps: []wire.OutPoint{ + outpointFromInt(0), + }, + }, + } + }(), + expectedSize: pubKeyHashLen + baseEntrySize, + }, + { + name: "10 entries, 4 spend", + blocks: func() []block { + blocks := make([]block, 0, 10) + for i := 0; i < 10; i++ { + op := outpointFromInt(i) + + block := block{ + txOuts: []*wire.TxOut{ + {Value: 10000, PkScript: getValidP2PKHScript()}, + }, + outOps: []wire.OutPoint{ + op, + }, + } + + // Spend all outs in blocks less than 4. + if i < 4 { + block.txIns = []*wire.TxIn{ + {PreviousOutPoint: op}, + } + } + + blocks = append(blocks, block) + } + return blocks + }(), + // Multipled by 6 since we'll have 6 entries left. + expectedSize: (pubKeyHashLen + baseEntrySize) * 6, + }, + { + name: "spend everything", + blocks: func() []block { + blocks := make([]block, 0, 500) + for i := 0; i < 500; i++ { + op := outpointFromInt(i) + + block := block{ + txOuts: []*wire.TxOut{ + {Value: 1000, PkScript: getValidP2PKHScript()}, + }, + outOps: []wire.OutPoint{ + op, + }, + } + + // Spend all outs in blocks less than 4. + block.txIns = []*wire.TxIn{ + {PreviousOutPoint: op}, + } + + blocks = append(blocks, block) + } + return blocks + }(), + expectedSize: 0, + }, + } + + for _, test := range tests { + // Size is just something big enough so that the mapslice doesn't + // run out of memory. + s := newUtxoCache(nil, 1*1024*1024) + + for height, block := range test.blocks { + for i, out := range block.txOuts { + s.addTxOut(block.outOps[i], out, true, int32(height)) + } + + for _, in := range block.txIns { + s.addTxIn(in, nil) + } + } + + if s.totalEntryMemory != test.expectedSize { + t.Errorf("Failed test %s. Expected size of %d, got %d", + test.name, test.expectedSize, s.totalEntryMemory) + } + } +} From 16cd44f0e6c33e928193d8253c6b74c7dd088b7e Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 16 May 2023 23:27:01 +0900 Subject: [PATCH 0901/1056] blockchain, netsync, main, cmd/addblock: Use utxocache This change is part of the effort to add utxocache support to btcd. utxo cache is now used by the BlockChain struct. By default it's used and the minimum cache is set to 250MiB. The change made helps speed up block/tx validation as the cache allows for much faster lookup of utxos. The initial block download in particular is improved as the db i/o bottleneck is remedied by the cache. --- blockchain/chain.go | 123 +++++++++++---- blockchain/utxocache.go | 133 +++++++++++++++++ blockchain/utxocache_test.go | 282 +++++++++++++++++++++++++++++++++++ blockchain/utxoviewpoint.go | 60 ++++++-- blockchain/validate.go | 6 +- cmd/addblock/import.go | 10 ++ config.go | 3 + netsync/blocklogger.go | 9 +- netsync/manager.go | 14 +- server.go | 19 +-- 10 files changed, 600 insertions(+), 59 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 937b2fa1c0..84d4a0f395 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -131,6 +131,10 @@ type BlockChain struct { index *blockIndex bestChain *chainView + // The UTXO state holds a cached view of the UTXO state of the chain. + // It is protected by the chain lock. + utxoCache *utxoCache + // These fields are related to handling of orphan blocks. They are // protected by a combination of the chain lock and the orphan lock. orphanLock sync.RWMutex @@ -551,9 +555,14 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List // connectBlock handles connecting the passed node/block to the end of the main // (best) chain. // -// This passed utxo view must have all referenced txos the block spends marked -// as spent and all of the new txos the block creates added to it. In addition, -// the passed stxos slice must be populated with all of the information for the +// Passing in a utxo view is optional. If the passed in utxo view is nil, +// connectBlock will assume that the utxo cache has already connected all the +// txs in the block being connected. +// If a utxo view is passed in, this passed utxo view must have all referenced +// txos the block spends marked as spent and all of the new txos the block creates +// added to it. +// +// The passed stxos slice must be populated with all of the information for the // spent txos. This approach is used because the connection validation that // must happen prior to calling this function requires the same details, so // it would be inefficient to repeat it. @@ -602,6 +611,18 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, curTotalTxns+numTxns, CalcPastMedianTime(node), ) + // If a utxoviewpoint was passed in, we'll be writing that viewpoint + // directly to the database on disk. In order for the database to be + // consistent, we must flush the cache before writing the viewpoint. + if view != nil { + err = b.db.Update(func(dbTx database.Tx) error { + return b.utxoCache.flush(dbTx, FlushRequired, state) + }) + if err != nil { + return err + } + } + // Atomically insert info into the database. err = b.db.Update(func(dbTx database.Tx) error { // If the pruneTarget isn't 0, we should attempt to delete older blocks @@ -640,6 +661,8 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, // Update the utxo set using the state of the utxo view. This // entails removing all of the utxos spent and adding the new // ones created by the block. + // + // A nil viewpoint is a no-op. err = dbPutUtxoView(dbTx, view) if err != nil { return err @@ -670,7 +693,9 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, // Prune fully spent entries and mark all entries in the view unmodified // now that the modifications have been committed to the database. - view.commit() + if view != nil { + view.commit() + } // This node is now the end of the best chain. b.bestChain.SetTip(node) @@ -691,7 +716,11 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, b.sendNotification(NTBlockConnected, block) b.chainLock.Lock() - return nil + // Since we may have changed the UTXO cache, we make sure it didn't exceed its + // maximum size. If we're pruned and have flushed already, this will be a no-op. + return b.db.Update(func(dbTx database.Tx) error { + return b.utxoCache.flush(dbTx, FlushIfNeeded, b.BestSnapshot()) + }) } // disconnectBlock handles disconnecting the passed node/block from the end of @@ -840,6 +869,15 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error return nil } + // The rest of the reorg depends on all STXOs already being in the database + // so we flush before reorg. + err := b.db.Update(func(dbTx database.Tx) error { + return b.utxoCache.flush(dbTx, FlushRequired, b.BestSnapshot()) + }) + if err != nil { + return err + } + // Ensure the provided nodes match the current best chain. tip := b.bestChain.Tip() if detachNodes.Len() != 0 { @@ -901,7 +939,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the utxos referenced by the block that aren't // already in the view. - err = view.fetchInputUtxos(b.db, block) + err = view.fetchInputUtxos(b.db, nil, block) if err != nil { return err } @@ -968,7 +1006,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // checkConnectBlock gets skipped, we still need to update the UTXO // view. if b.index.NodeStatus(n).KnownValid() { - err = view.fetchInputUtxos(b.db, block) + err = view.fetchInputUtxos(b.db, nil, block) if err != nil { return err } @@ -1020,7 +1058,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the utxos referenced by the block that aren't // already in the view. - err := view.fetchInputUtxos(b.db, block) + err := view.fetchInputUtxos(b.db, nil, block) if err != nil { return err } @@ -1047,7 +1085,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the utxos referenced by the block that aren't // already in the view. - err := view.fetchInputUtxos(b.db, block) + err := view.fetchInputUtxos(b.db, nil, block) if err != nil { return err } @@ -1069,6 +1107,15 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error } } + // We call the flush at the end to update the last flush hash to the new + // best tip. + err = b.db.Update(func(dbTx database.Tx) error { + return b.utxoCache.flush(dbTx, FlushRequired, b.BestSnapshot()) + }) + if err != nil { + return err + } + // Log the point where the chain forked and old and new best chain // heads. if forkNode != nil { @@ -1121,11 +1168,21 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla // Perform several checks to verify the block can be connected // to the main chain without violating any rules and without // actually connecting the block. - view := NewUtxoViewpoint() - view.SetBestHash(parentHash) - stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) if !fastAdd { - err := b.checkConnectBlock(node, block, view, &stxos) + // We create a viewpoint here to avoid spending or adding new + // coins to the utxo cache. + // + // checkConnectBlock spends and adds utxos before doing the + // signature validation and if the signature validation fails, + // we would be forced to undo the utxo cache. + // + // TODO (kcalvinalvin): Doing all of the validation before connecting + // the tx inside check connect block would allow us to pass the utxo + // cache directly to the check connect block. This would save on the + // expensive memory allocation done by fetch input utxos. + view := NewUtxoViewpoint() + view.SetBestHash(parentHash) + err := b.checkConnectBlock(node, block, view, nil) if err == nil { b.index.SetStatusFlags(node, statusValid) } else if _, ok := err.(RuleError); ok { @@ -1141,23 +1198,16 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla } } - // In the fast add case the code to check the block connection - // was skipped, so the utxo view needs to load the referenced - // utxos, spend them, and add the new utxos being created by - // this block. - if fastAdd { - err := view.fetchInputUtxos(b.db, block) - if err != nil { - return false, err - } - err = view.connectTransactions(block, &stxos) - if err != nil { - return false, err - } + // Connect the transactions to the cache. All the txs are considered valid + // at this point as they have passed validation or was considered valid already. + stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) + err := b.utxoCache.connectTransactions(block, &stxos) + if err != nil { + return false, err } // Connect the block to the main chain. - err := b.connectBlock(node, block, view, stxos) + err = b.connectBlock(node, block, nil, stxos) if err != nil { // If we got hit with a rule error, then we'll mark // that status of the block as invalid and flush the @@ -1785,6 +1835,11 @@ type Config struct { // This field is required. DB database.DB + // The maximum size in bytes of the UTXO cache. + // + // This field is required. + UtxoCacheMaxSize uint64 + // Interrupt specifies a channel the caller can close to signal that // long running operations, such as catching up indexes or performing // database migrations, should be interrupted. @@ -1893,6 +1948,7 @@ func New(config *Config) (*BlockChain, error) { maxRetargetTimespan: targetTimespan * adjustmentFactor, blocksPerRetarget: int32(targetTimespan / targetTimePerBlock), index: newBlockIndex(config.DB, params), + utxoCache: newUtxoCache(config.DB, config.UtxoCacheMaxSize), hashCache: config.HashCache, bestChain: newChainView(nil), orphans: make(map[chainhash.Hash]*orphanBlock), @@ -1942,10 +1998,23 @@ func New(config *Config) (*BlockChain, error) { return nil, err } + // Make sure the utxo state is catched up if it was left in an inconsistent + // state. bestNode := b.bestChain.Tip() + if err := b.InitConsistentState(bestNode, config.Interrupt); err != nil { + return nil, err + } log.Infof("Chain state (height %d, hash %v, totaltx %d, work %v)", bestNode.height, bestNode.hash, b.stateSnapshot.TotalTxns, bestNode.workSum) return &b, nil } + +// CachedStateSize returns the total size of the cached state of the blockchain +// in bytes. +func (b *BlockChain) CachedStateSize() uint64 { + b.chainLock.Lock() + defer b.chainLock.Unlock() + return b.utxoCache.totalMemoryUsage() +} diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index 3f3c246e66..d36a36ff8c 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -5,6 +5,7 @@ package blockchain import ( + "container/list" "fmt" "sync" "time" @@ -578,3 +579,135 @@ func (s *utxoCache) flush(dbTx database.Tx, mode FlushMode, bestState *BestState return nil } + +// FlushUtxoCache flushes the UTXO state to the database if a flush is needed with the +// given flush mode. +// +// This function is safe for concurrent access. +func (b *BlockChain) FlushUtxoCache(mode FlushMode) error { + b.chainLock.Lock() + defer b.chainLock.Unlock() + + return b.db.Update(func(dbTx database.Tx) error { + return b.utxoCache.flush(dbTx, mode, b.BestSnapshot()) + }) +} + +// InitConsistentState checks the consistency status of the utxo state and +// replays blocks if it lags behind the best state of the blockchain. +// +// It needs to be ensured that the chainView passed to this method does not +// get changed during the execution of this method. +func (b *BlockChain) InitConsistentState(tip *blockNode, interrupt <-chan struct{}) error { + s := b.utxoCache + // Load the consistency status from the database. + var statusBytes []byte + s.db.View(func(dbTx database.Tx) error { + statusBytes = dbFetchUtxoStateConsistency(dbTx) + return nil + }) + + // If no status was found, the database is old and didn't have a cached utxo + // state yet. In that case, we set the status to the best state and write + // this to the database. + if statusBytes == nil { + err := s.db.Update(func(dbTx database.Tx) error { + return dbPutUtxoStateConsistency(dbTx, &tip.hash) + }) + + // Set the last flush hash as it's the default value of 0s. + s.lastFlushHash = tip.hash + + return err + } + + statusHash, err := chainhash.NewHash(statusBytes) + if err != nil { + return err + } + + // If state is consistent, we are done. + if statusHash.IsEqual(&tip.hash) { + log.Debugf("UTXO state consistent at (%d:%v)", tip.height, tip.hash) + + // The last flush hash is set to the default value of all 0s. Set + // it to the tip since we checked it's consistent. + s.lastFlushHash = tip.hash + + return nil + } + + lastFlushNode := b.index.LookupNode(statusHash) + log.Infof("Reconstructing UTXO state after an unclean shutdown. The UTXO state is "+ + "consistent at block %s (%d) but the chainstate is at block %s (%d), This may "+ + "take a long time...", statusHash.String(), lastFlushNode.height, + tip.hash.String(), tip.height) + + // Even though this should always be true, make sure the fetched hash is in + // the best chain. + fork := b.bestChain.FindFork(lastFlushNode) + if fork == nil { + return AssertError(fmt.Sprintf("last utxo consistency status contains "+ + "hash that is not in best chain: %v", statusHash)) + } + + // We never disconnect blocks as they cannot be inconsistent during a reorganization. + // This is because The cache is flushed before the reorganization begins and the utxo + // set at each block disconnect is written atomically to the database. + node := lastFlushNode + + // We replay the blocks from the last consistent state up to the best + // state. Iterate forward from the consistent node to the tip of the best + // chain. + attachNodes := list.New() + for n := tip; n.height >= 0; n = n.parent { + if n == fork { + break + } + attachNodes.PushFront(n) + } + + for e := attachNodes.Front(); e != nil; e = e.Next() { + node = e.Value.(*blockNode) + + var block *btcutil.Block + err := s.db.View(func(dbTx database.Tx) error { + block, err = dbFetchBlockByNode(dbTx, node) + if err != nil { + return err + } + + return err + }) + if err != nil { + return err + } + + err = b.utxoCache.connectTransactions(block, nil) + if err != nil { + return err + } + + // Flush the utxo cache if needed. This will in turn update the + // consistent state to this block. + err = s.db.Update(func(dbTx database.Tx) error { + return s.flush(dbTx, FlushIfNeeded, &BestState{Hash: node.hash, Height: node.height}) + }) + if err != nil { + return err + } + + if interruptRequested(interrupt) { + log.Warn("UTXO state reconstruction interrupted") + + return errInterruptRequested + } + } + log.Debug("UTXO state reconstruction done") + + // Set the last flush hash as it's the default value of 0s. + s.lastFlushHash = tip.hash + s.lastFlushTime = time.Now() + + return nil +} diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index aa748e50e9..7bad3b857f 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -6,10 +6,16 @@ package blockchain import ( "crypto/sha256" "encoding/binary" + "fmt" "reflect" "sync" "testing" + "time" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/wire" ) @@ -305,3 +311,279 @@ func TestUtxoCacheEntrySize(t *testing.T) { } } } + +// assertConsistencyState asserts the utxo consistency states of the blockchain. +func assertConsistencyState(chain *BlockChain, hash *chainhash.Hash) error { + var bytes []byte + err := chain.db.View(func(dbTx database.Tx) (err error) { + bytes = dbFetchUtxoStateConsistency(dbTx) + return + }) + if err != nil { + return fmt.Errorf("Error fetching utxo state consistency: %v", err) + } + actualHash, err := chainhash.NewHash(bytes) + if err != nil { + return err + } + if !actualHash.IsEqual(hash) { + return fmt.Errorf("Unexpected consistency hash: %v instead of %v", + actualHash, hash) + } + + return nil +} + +// assertNbEntriesOnDisk asserts that the total number of utxo entries on the +// disk is equal to the given expected number. +func assertNbEntriesOnDisk(chain *BlockChain, expectedNumber int) error { + var nb int + err := chain.db.View(func(dbTx database.Tx) error { + cursor := dbTx.Metadata().Bucket(utxoSetBucketName).Cursor() + nb = 0 + for b := cursor.First(); b; b = cursor.Next() { + nb++ + _, err := deserializeUtxoEntry(cursor.Value()) + if err != nil { + return fmt.Errorf("Failed to deserialize entry: %v", err) + } + } + return nil + }) + if err != nil { + return fmt.Errorf("Error fetching utxo entries: %v", err) + } + if nb != expectedNumber { + return fmt.Errorf("Expected %d elements in the UTXO set, but found %d", + expectedNumber, nb) + } + + return nil +} + +// utxoCacheTestChain creates a test BlockChain to be used for utxo cache tests. +// It uses the regression test parameters, a coin matutiry of 1 block and sets +// the cache size limit to 10 MiB. +func utxoCacheTestChain(testName string) (*BlockChain, *chaincfg.Params, func()) { + params := chaincfg.RegressionNetParams + chain, tearDown, err := chainSetup(testName, ¶ms) + if err != nil { + panic(fmt.Sprintf("error loading blockchain with database: %v", err)) + } + + chain.TstSetCoinbaseMaturity(1) + chain.utxoCache.maxTotalMemoryUsage = 10 * 1024 * 1024 + chain.utxoCache.cachedEntries.maxTotalMemoryUsage = chain.utxoCache.maxTotalMemoryUsage + + return chain, ¶ms, tearDown +} + +func TestUtxoCacheFlush(t *testing.T) { + chain, params, tearDown := utxoCacheTestChain("TestUtxoCacheFlush") + defer tearDown() + cache := chain.utxoCache + tip := btcutil.NewBlock(params.GenesisBlock) + + // The chainSetup init triggers the consistency status write. + err := assertConsistencyState(chain, params.GenesisHash) + if err != nil { + t.Fatal(err) + } + + err = assertNbEntriesOnDisk(chain, 0) + if err != nil { + t.Fatal(err) + } + + // LastFlushHash starts with genesis. + if cache.lastFlushHash != *params.GenesisHash { + t.Fatalf("lastFlushHash before first flush expected to be "+ + "genesis block hash, instead was %v", cache.lastFlushHash) + } + + // First, add 10 utxos without flushing. + outPoints := make([]wire.OutPoint, 10) + for i := range outPoints { + op := outpointFromInt(i) + outPoints[i] = op + + // Add the txout. + txOut := wire.TxOut{Value: 10000, PkScript: getValidP2PKHScript()} + cache.addTxOut(op, &txOut, true, int32(i)) + } + + if cache.cachedEntries.length() != len(outPoints) { + t.Fatalf("Expected 10 entries, has %d instead", cache.cachedEntries.length()) + } + + // All entries should be fresh and modified. + for _, m := range cache.cachedEntries.maps { + for outpoint, entry := range m { + if entry == nil { + t.Fatalf("Unexpected nil entry found for %v", outpoint) + } + if !entry.isModified() { + t.Fatal("Entry should be marked mofified") + } + if !entry.isFresh() { + t.Fatal("Entry should be marked fresh") + } + } + } + + // Spend the last outpoint and pop it off from the outpoints slice. + var spendOp wire.OutPoint + spendOp, outPoints = outPoints[len(outPoints)-1], outPoints[:len(outPoints)-1] + cache.addTxIn(&wire.TxIn{PreviousOutPoint: spendOp}, nil) + + if cache.cachedEntries.length() != len(outPoints) { + t.Fatalf("Expected %d entries, has %d instead", + len(outPoints), cache.cachedEntries.length()) + } + + // Not flushed yet. + err = assertConsistencyState(chain, params.GenesisHash) + if err != nil { + t.Fatal(err) + } + + err = assertNbEntriesOnDisk(chain, 0) + if err != nil { + t.Fatal(err) + } + + // Flush. + err = chain.db.Update(func(dbTx database.Tx) error { + return cache.flush(dbTx, FlushRequired, chain.stateSnapshot) + }) + if err != nil { + t.Fatalf("unexpected error while flushing cache: %v", err) + } + if cache.cachedEntries.length() != 0 { + t.Fatalf("Expected 0 entries, has %d instead", cache.cachedEntries.length()) + } + + err = assertConsistencyState(chain, tip.Hash()) + if err != nil { + t.Fatal(err) + } + err = assertNbEntriesOnDisk(chain, len(outPoints)) + if err != nil { + t.Fatal(err) + } + + // Fetch the flushed utxos. + entries, err := cache.fetchEntries(outPoints) + if err != nil { + t.Fatal(err) + } + + // Check that the returned entries are not marked fresh and modified. + for _, entry := range entries { + if entry.isFresh() { + t.Fatal("Entry should not be marked fresh") + } + if entry.isModified() { + t.Fatal("Entry should not be marked modified") + } + } + + // Check that the fetched entries in the cache are not marked fresh and modified. + for _, m := range cache.cachedEntries.maps { + for outpoint, elem := range m { + if elem == nil { + t.Fatalf("Unexpected nil entry found for %v", outpoint) + } + if elem.isFresh() { + t.Fatal("Entry should not be marked fresh") + } + if elem.isModified() { + t.Fatal("Entry should not be marked modified") + } + } + } + + // Spend 5 utxos. + prevLen := len(outPoints) + for i := 0; i < 5; i++ { + spendOp, outPoints = outPoints[len(outPoints)-1], outPoints[:len(outPoints)-1] + cache.addTxIn(&wire.TxIn{PreviousOutPoint: spendOp}, nil) + } + + // Should still have the entries in cache so they can be flushed to disk. + if cache.cachedEntries.length() != prevLen { + t.Fatalf("Expected 10 entries, has %d instead", cache.cachedEntries.length()) + } + + // Flush. + err = chain.db.Update(func(dbTx database.Tx) error { + return cache.flush(dbTx, FlushRequired, chain.stateSnapshot) + }) + if err != nil { + t.Fatalf("unexpected error while flushing cache: %v", err) + } + if cache.cachedEntries.length() != 0 { + t.Fatalf("Expected 0 entries, has %d instead", cache.cachedEntries.length()) + } + + err = assertConsistencyState(chain, tip.Hash()) + if err != nil { + t.Fatal(err) + } + err = assertNbEntriesOnDisk(chain, len(outPoints)) + if err != nil { + t.Fatal(err) + } + + // Add 5 utxos without flushing and test for periodic flushes. + outPoints1 := make([]wire.OutPoint, 5) + for i := range outPoints1 { + // i + prevLen here to avoid collision since we're just hashing + // the int. + op := outpointFromInt(i + prevLen) + outPoints1[i] = op + + // Add the txout. + txOut := wire.TxOut{Value: 10000, PkScript: getValidP2PKHScript()} + cache.addTxOut(op, &txOut, true, int32(i+prevLen)) + } + if cache.cachedEntries.length() != len(outPoints1) { + t.Fatalf("Expected %d entries, has %d instead", + len(outPoints1), cache.cachedEntries.length()) + } + + // Attempt to flush with flush periodic. Shouldn't flush. + err = chain.db.Update(func(dbTx database.Tx) error { + return cache.flush(dbTx, FlushPeriodic, chain.stateSnapshot) + }) + if err != nil { + t.Fatalf("unexpected error while flushing cache: %v", err) + } + if cache.cachedEntries.length() == 0 { + t.Fatalf("Expected %d entries, has %d instead", + len(outPoints1), cache.cachedEntries.length()) + } + + // Arbitrarily set the last flush time to 6 minutes ago. + cache.lastFlushTime = time.Now().Add(-time.Minute * 6) + + // Attempt to flush with flush periodic. Should flush now. + err = chain.db.Update(func(dbTx database.Tx) error { + return cache.flush(dbTx, FlushPeriodic, chain.stateSnapshot) + }) + if err != nil { + t.Fatalf("unexpected error while flushing cache: %v", err) + } + if cache.cachedEntries.length() != 0 { + t.Fatalf("Expected 0 entries, has %d instead", cache.cachedEntries.length()) + } + + err = assertConsistencyState(chain, tip.Hash()) + if err != nil { + t.Fatal(err) + } + err = assertNbEntriesOnDisk(chain, len(outPoints)+len(outPoints1)) + if err != nil { + t.Fatal(err) + } +} diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index c5ff673b0a..fdd165c095 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -554,10 +554,43 @@ func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints []wire.OutPo }) } +// fetchUtxosFromCache fetches unspent transaction output data about the provided +// set of outpoints from the point of view of the end of the main chain at the +// time of the call. It attempts to fetch them from the cache and whatever entries +// that were not in the cache will be attempted to be fetched from the database and +// it'll be cached. +// +// Upon completion of this function, the view will contain an entry for each +// requested outpoint. Spent outputs, or those which otherwise don't exist, +// will result in a nil entry in the view. +func (view *UtxoViewpoint) fetchUtxosFromCache(cache *utxoCache, outpoints []wire.OutPoint) error { + // Nothing to do if there are no requested outputs. + if len(outpoints) == 0 { + return nil + } + + // Load the requested set of unspent transaction outputs from the point + // of view of the end of the main chain. Any missing entries will be + // fetched from the database and be cached. + // + // NOTE: Missing entries are not considered an error here and instead + // will result in nil entries in the view. This is intentionally done + // so other code can use the presence of an entry in the store as a way + // to unnecessarily avoid attempting to reload it from the database. + entries, err := cache.fetchEntries(outpoints) + if err != nil { + return err + } + for i, entry := range entries { + view.entries[outpoints[i]] = entry.Clone() + } + return nil +} + // fetchUtxos loads the unspent transaction outputs for the provided set of // outputs into the view from the database as needed unless they already exist // in the view in which case they are ignored. -func (view *UtxoViewpoint) fetchUtxos(db database.DB, outpoints []wire.OutPoint) error { +func (view *UtxoViewpoint) fetchUtxos(cache *utxoCache, outpoints []wire.OutPoint) error { // Nothing to do if there are no requested outputs. if len(outpoints) == 0 { return nil @@ -575,7 +608,7 @@ func (view *UtxoViewpoint) fetchUtxos(db database.DB, outpoints []wire.OutPoint) } // Request the input utxos from the database. - return view.fetchUtxosMain(db, needed) + return view.fetchUtxosFromCache(cache, needed) } // findInputsToFetch goes through all the blocks and returns all the outpoints of @@ -633,10 +666,13 @@ func (view *UtxoViewpoint) findInputsToFetch(block *btcutil.Block) []wire.OutPoi // fetchInputUtxos loads the unspent transaction outputs for the inputs // referenced by the transactions in the given block into the view from the -// database as needed. In particular, referenced entries that are earlier in -// the block are added to the view and entries that are already in the view are -// not modified. -func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, block *btcutil.Block) error { +// database or the cache as needed. In particular, referenced entries that +// are earlier in the block are added to the view and entries that are already +// in the view are not modified. +func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, cache *utxoCache, block *btcutil.Block) error { + if cache != nil { + return view.fetchUtxosFromCache(cache, view.findInputsToFetch(block)) + } // Request the input utxos from the cache. return view.fetchUtxosMain(db, view.findInputsToFetch(block)) } @@ -678,7 +714,7 @@ func (b *BlockChain) FetchUtxoView(tx *btcutil.Tx) (*UtxoViewpoint, error) { // chain. view := NewUtxoViewpoint() b.chainLock.RLock() - err := view.fetchUtxosMain(b.db, needed) + err := view.fetchUtxosFromCache(b.utxoCache, needed) b.chainLock.RUnlock() return view, err } @@ -697,16 +733,10 @@ func (b *BlockChain) FetchUtxoEntry(outpoint wire.OutPoint) (*UtxoEntry, error) b.chainLock.RLock() defer b.chainLock.RUnlock() - var entry *UtxoEntry - err := b.db.View(func(dbTx database.Tx) error { - var err error - utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) - entry, err = dbFetchUtxoEntry(dbTx, utxoBucket, outpoint) - return err - }) + entries, err := b.utxoCache.fetchEntries([]wire.OutPoint{outpoint}) if err != nil { return nil, err } - return entry, nil + return entries[0], nil } diff --git a/blockchain/validate.go b/blockchain/validate.go index 438f455428..02d36134b1 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -889,7 +889,7 @@ func (b *BlockChain) checkBIP0030(node *blockNode, block *btcutil.Block, view *U fetch = append(fetch, prevOut) } } - err := view.fetchUtxos(b.db, fetch) + err := view.fetchUtxos(b.utxoCache, fetch) if err != nil { return err } @@ -1080,11 +1080,11 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi } // Load all of the utxos referenced by the inputs for all transactions - // in the block don't already exist in the utxo view from the database. + // in the block don't already exist in the utxo view from the cache. // // These utxo entries are needed for verification of things such as // transaction inputs, counting pay-to-script-hashes, and scripts. - err := view.fetchInputUtxos(b.db, block) + err := view.fetchInputUtxos(nil, b.utxoCache, block) if err != nil { return err } diff --git a/cmd/addblock/import.go b/cmd/addblock/import.go index 7f4b9bb0f5..8eda8f8c9b 100644 --- a/cmd/addblock/import.go +++ b/cmd/addblock/import.go @@ -287,6 +287,16 @@ func (bi *blockImporter) Import() chan *importResults { // the status handler when done. go func() { bi.wg.Wait() + + // Flush the changes made to the blockchain. + log.Info("Flushing blockchain caches to the disk...") + if err := bi.chain.FlushUtxoCache(blockchain.FlushRequired); err != nil { + log.Errorf("Error while flushing the blockchain state: %v", err) + bi.errChan <- err + return + } + log.Info("Done flushing blockchain caches to disk") + bi.doneChan <- true }() diff --git a/config.go b/config.go index 67c47dbd6c..1fe0767f63 100644 --- a/config.go +++ b/config.go @@ -63,6 +63,7 @@ const ( defaultMaxOrphanTransactions = 100 defaultMaxOrphanTxSize = 100000 defaultSigCacheMaxSize = 100000 + defaultUtxoCacheMaxSizeMiB = 250 sampleConfigFilename = "sample-btcd.conf" defaultTxIndex = false defaultAddrIndex = false @@ -171,6 +172,7 @@ type config struct { TestNet3 bool `long:"testnet" description:"Use the test network"` TorIsolation bool `long:"torisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."` TrickleInterval time.Duration `long:"trickleinterval" description:"Minimum time between attempts to send new inventory to a connected peer"` + UtxoCacheMaxSizeMiB uint `long:"utxocachemaxsize" description:"The maximum size in MiB of the UTXO cache"` TxIndex bool `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."` Upnp bool `long:"upnp" description:"Use UPnP to map our listening port outside of NAT"` @@ -439,6 +441,7 @@ func loadConfig() (*config, []string, error) { BlockPrioritySize: mempool.DefaultBlockPrioritySize, MaxOrphanTxs: defaultMaxOrphanTransactions, SigCacheMaxSize: defaultSigCacheMaxSize, + UtxoCacheMaxSizeMiB: defaultUtxoCacheMaxSizeMiB, Generate: defaultGenerate, TxIndex: defaultTxIndex, AddrIndex: defaultAddrIndex, diff --git a/netsync/blocklogger.go b/netsync/blocklogger.go index 10f83d57b7..31a6a4c509 100644 --- a/netsync/blocklogger.go +++ b/netsync/blocklogger.go @@ -5,9 +5,11 @@ package netsync import ( + "fmt" "sync" "time" + "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btclog" ) @@ -41,7 +43,7 @@ func newBlockProgressLogger(progressMessage string, logger btclog.Logger) *block // LogBlockHeight logs a new block height as an information message to show // progress to the user. In order to prevent spam, it limits logging to one // message every 10 seconds with duration and totals included. -func (b *blockProgressLogger) LogBlockHeight(block *btcutil.Block) { +func (b *blockProgressLogger) LogBlockHeight(block *btcutil.Block, chain *blockchain.BlockChain) { b.Lock() defer b.Unlock() @@ -67,9 +69,10 @@ func (b *blockProgressLogger) LogBlockHeight(block *btcutil.Block) { if b.receivedLogTx == 1 { txStr = "transaction" } - b.subsystemLogger.Infof("%s %d %s in the last %s (%d %s, height %d, %s)", + cacheSizeStr := fmt.Sprintf("~%d MiB", chain.CachedStateSize()/1024/1024) + b.subsystemLogger.Infof("%s %d %s in the last %s (%d %s, height %d, %s, %s cache)", b.progressAction, b.receivedLogBlocks, blockStr, tDuration, b.receivedLogTx, - txStr, block.Height(), block.MsgBlock().Header.Timestamp) + txStr, block.Height(), block.MsgBlock().Header.Timestamp, cacheSizeStr) b.receivedLogBlocks = 0 b.receivedLogTx = 0 diff --git a/netsync/manager.go b/netsync/manager.go index fa3cf3d061..41ba70aa6a 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -816,7 +816,7 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) { // When the block is not an orphan, log information about it and // update the chain state. - sm.progressLogger.LogBlockHeight(bmsg.block) + sm.progressLogger.LogBlockHeight(bmsg.block, sm.chain) // Update this peer's latest block height, for future // potential sync node candidacy. @@ -840,8 +840,13 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) { } } - // Nothing more to do if we aren't in headers-first mode. + // If we are not in headers first mode, it's a good time to periodically + // flush the blockchain cache because we don't expect new blocks immediately. + // After that, there is nothing more to do. if !sm.headersFirstMode { + if err := sm.chain.FlushUtxoCache(blockchain.FlushPeriodic); err != nil { + log.Errorf("Error while flushing the blockchain cache: %v", err) + } return } @@ -1414,6 +1419,11 @@ out: } } + log.Debug("Block handler shutting down: flushing blockchain caches...") + if err := sm.chain.FlushUtxoCache(blockchain.FlushRequired); err != nil { + log.Errorf("Error while flushing blockchain caches: %v", err) + } + sm.wg.Done() log.Trace("Block handler done") } diff --git a/server.go b/server.go index 4e88d36cb3..356326ab1c 100644 --- a/server.go +++ b/server.go @@ -2826,15 +2826,16 @@ func newServer(listenAddrs, agentBlacklist, agentWhitelist []string, // Create a new block chain instance with the appropriate configuration. var err error s.chain, err = blockchain.New(&blockchain.Config{ - DB: s.db, - Interrupt: interrupt, - ChainParams: s.chainParams, - Checkpoints: checkpoints, - TimeSource: s.timeSource, - SigCache: s.sigCache, - IndexManager: indexManager, - HashCache: s.hashCache, - Prune: cfg.Prune * 1024 * 1024, + DB: s.db, + Interrupt: interrupt, + ChainParams: s.chainParams, + Checkpoints: checkpoints, + TimeSource: s.timeSource, + SigCache: s.sigCache, + IndexManager: indexManager, + HashCache: s.hashCache, + Prune: cfg.Prune * 1024 * 1024, + UtxoCacheMaxSize: uint64(cfg.UtxoCacheMaxSizeMiB) * 1024 * 1024, }) if err != nil { return nil, err From d387d162f3e349ea2a4a3f05f2c6d46e5a69f02b Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 25 Aug 2023 16:39:42 +0900 Subject: [PATCH 0902/1056] database/ffldb: make PruneBlocks atomic PruneBlocks used to delete files immediately before the database transaction finished. By making the prune atomic, we can guarantee that the database flush will happen before the utxo cache is flushed, ensuring that the utxo cache is never in an irrecoverable state. --- database/ffldb/db.go | 28 ++++++++++++++++++++++++---- database/ffldb/driver_test.go | 13 +++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/database/ffldb/db.go b/database/ffldb/db.go index 1751c936a9..8fc4d32646 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -966,6 +966,10 @@ type transaction struct { pendingBlocks map[chainhash.Hash]int pendingBlockData []pendingBlock + // Files that need to be deleted on commit. These are the files that + // are marked as files to be deleted during pruning. + pendingDelFileNums []uint32 + // Keys that need to be stored or deleted on commit. pendingKeys *treap.Mutable pendingRemove *treap.Mutable @@ -1593,6 +1597,9 @@ func (tx *transaction) close() { tx.pendingBlocks = nil tx.pendingBlockData = nil + // Clear pending file deletions. + tx.pendingDelFileNums = nil + // Clear pending keys that would have been written or deleted on commit. tx.pendingKeys = nil tx.pendingRemove = nil @@ -1619,6 +1626,18 @@ func (tx *transaction) close() { // // This function MUST only be called when there is pending data to be written. func (tx *transaction) writePendingAndCommit() error { + // Loop through all the pending file deletions and delete them. + // We do this first before doing any of the writes as we can't undo + // deletions of files. + for _, fileNum := range tx.pendingDelFileNums { + err := tx.db.store.deleteFileFunc(fileNum) + if err != nil { + // Nothing we can do if we fail to delete blocks besides + // return an error. + return err + } + } + // Save the current block store write position for potential rollback. // These variables are only updated here in this function and there can // only be one write transaction active at a time, so it's safe to store @@ -1725,11 +1744,12 @@ func (tx *transaction) PruneBlocks(targetSize uint64) ([]chainhash.Hash, error) // We use < not <= so that the last file is never deleted. There are other checks in place // but setting it to < here doesn't hurt. for i := uint32(first); i < uint32(last); i++ { - err = tx.db.store.deleteFileFunc(i) - if err != nil { - return nil, fmt.Errorf("PruneBlocks: Failed to delete block file "+ - "number %d: %v", i, err) + // Add the block file to be deleted to the list of files pending deletion to + // delete when the transaction is committed. + if tx.pendingDelFileNums == nil { + tx.pendingDelFileNums = make([]uint32, 0, 1) } + tx.pendingDelFileNums = append(tx.pendingDelFileNums, i) // Add the file index to the deleted files map so that we can later // delete the block location index. diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index 794e8e1912..38a84ee2f9 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -340,6 +340,19 @@ func TestPrune(t *testing.T) { // This should leave 3 files on disk. err = db.Update(func(tx database.Tx) error { deletedBlocks, err = tx.PruneBlocks(blockFileSize * 3) + if err != nil { + return err + } + + pruned, err := tx.BeenPruned() + if err != nil { + return err + } + + if pruned { + err = fmt.Errorf("The database hasn't been commited yet " + + "but files were already deleted") + } return err }) if err != nil { From dd37dfa80b289439edbd14b90a50daec6d48cacd Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 25 Aug 2023 17:34:05 +0900 Subject: [PATCH 0903/1056] blockchain: add flushNeededAfterPrune flushNeededAfterPrune returns true if the utxocache needs to be flushed after the pruning of the given slice of block hashes. For the utxo cache to be recoverable while pruning is enabled, we need to make sure that there exists blocks since the last utxo cache flush. If there are blocks that are deleted after the last utxo cache flush, the utxo set is irrecoverable. The added method provides a way to tell if a flush is needed. --- blockchain/utxocache.go | 31 ++++++++++ blockchain/utxocache_test.go | 117 +++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index d36a36ff8c..0af6f25cab 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -711,3 +711,34 @@ func (b *BlockChain) InitConsistentState(tip *blockNode, interrupt <-chan struct return nil } + +// flushNeededAfterPrune returns true if the utxo cache needs to be flushed after a prune +// of the block storage. In the case of an unexpected shutdown, the utxo cache needs +// to be reconstructed from where the utxo cache was last flushed. In order for the +// utxo cache to be reconstructed, we always need to have the blocks since the utxo cache +// flush last happened. +// +// Example: if the last flush hash was at height 100 and one of the deleted blocks was at +// height 98, this function will return true. +func (b *BlockChain) flushNeededAfterPrune(deletedBlockHashes []chainhash.Hash) (bool, error) { + lastFlushHeight, err := b.BlockHeightByHash(&b.utxoCache.lastFlushHash) + if err != nil { + return false, err + } + + // Loop through all the block hashes and find out what the highest block height + // among the deleted hashes is. + highestDeletedHeight := int32(-1) + for _, deletedBlockHash := range deletedBlockHashes { + height, err := b.BlockHeightByHash(&deletedBlockHash) + if err != nil { + return false, err + } + + if height > highestDeletedHeight { + highestDeletedHeight = height + } + } + + return highestDeletedHeight >= lastFlushHeight, nil +} diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 7bad3b857f..536c2054a0 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -587,3 +587,120 @@ func TestUtxoCacheFlush(t *testing.T) { t.Fatal(err) } } + +func TestFlushNeededAfterPrune(t *testing.T) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + chain.utxoCache = newUtxoCache(nil, 0) + branchNodes := chainedNodes(chain.bestChain.Genesis(), 18) + for _, node := range branchNodes { + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branchNodes)) + + tests := []struct { + name string + lastFlushHash chainhash.Hash + delHashes []chainhash.Hash + expected bool + }{ + { + name: "deleted block up to height 9, last flush hash at block 10", + delHashes: func() []chainhash.Hash { + delBlockHashes := make([]chainhash.Hash, 0, 9) + for i := range branchNodes { + if branchNodes[i].height < 10 { + delBlockHashes = append(delBlockHashes, branchNodes[i].hash) + } + } + + return delBlockHashes + }(), + lastFlushHash: func() chainhash.Hash { + // Just some sanity checking to make sure the height is 10. + if branchNodes[9].height != 10 { + panic("was looking for height 10") + } + return branchNodes[9].hash + }(), + expected: false, + }, + { + name: "deleted blocks up to height 10, last flush hash at block 10", + delHashes: func() []chainhash.Hash { + delBlockHashes := make([]chainhash.Hash, 0, 10) + for i := range branchNodes { + if branchNodes[i].height < 11 { + delBlockHashes = append(delBlockHashes, branchNodes[i].hash) + } + } + return delBlockHashes + }(), + lastFlushHash: func() chainhash.Hash { + // Just some sanity checking to make sure the height is 10. + if branchNodes[9].height != 10 { + panic("was looking for height 10") + } + return branchNodes[9].hash + }(), + expected: true, + }, + { + name: "deleted block height 17, last flush hash at block 5", + delHashes: func() []chainhash.Hash { + delBlockHashes := make([]chainhash.Hash, 1) + delBlockHashes[0] = branchNodes[16].hash + // Just some sanity checking to make sure the height is 10. + if branchNodes[16].height != 17 { + panic("was looking for height 17") + } + return delBlockHashes + }(), + lastFlushHash: func() chainhash.Hash { + // Just some sanity checking to make sure the height is 10. + if branchNodes[4].height != 5 { + panic("was looking for height 5") + } + return branchNodes[4].hash + }(), + expected: true, + }, + { + name: "deleted block height 3, last flush hash at block 4", + delHashes: func() []chainhash.Hash { + delBlockHashes := make([]chainhash.Hash, 1) + delBlockHashes[0] = branchNodes[2].hash + // Just some sanity checking to make sure the height is 10. + if branchNodes[2].height != 3 { + panic("was looking for height 3") + } + return delBlockHashes + }(), + lastFlushHash: func() chainhash.Hash { + // Just some sanity checking to make sure the height is 10. + if branchNodes[3].height != 4 { + panic("was looking for height 4") + } + return branchNodes[3].hash + }(), + expected: false, + }, + } + + for _, test := range tests { + chain.utxoCache.lastFlushHash = test.lastFlushHash + got, err := chain.flushNeededAfterPrune(test.delHashes) + if err != nil { + t.Fatal(err) + } + + if got != test.expected { + t.Fatalf("for test %s, expected need flush to return %v but got %v", + test.name, test.expected, got) + } + } +} From ebc93a34ce31121bc6e9bf7c8feff66fbf5d7fa6 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 25 Aug 2023 17:57:04 +0900 Subject: [PATCH 0904/1056] blockchain: flush the utxo cache on prune if needed If the prune will delete block past the last flush hash of the utxocache, the cache will need to be flushed first to avoid a case where the utxocache is irrecoverable. The newly added code adds this flush logic to connectBlock. --- blockchain/chain.go | 20 +++++- blockchain/testdata/blk_0_to_14131.dat | Bin 0 -> 16777216 bytes blockchain/utxocache_test.go | 94 +++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 blockchain/testdata/blk_0_to_14131.dat diff --git a/blockchain/chain.go b/blockchain/chain.go index 84d4a0f395..60420022ac 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -642,6 +642,24 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, if err != nil { return err } + + // We may need to flush if the prune will delete blocks that + // are past our last flush block. + // + // NOTE: the database will never be inconsistent here as the + // actual blocks are not deleted until the db.Update returns. + needsFlush, err := b.flushNeededAfterPrune(deletedHashes) + if err != nil { + return err + } + if needsFlush { + // Since the deleted hashes are past our last + // flush block, flush the utxo cache now. + err = b.utxoCache.flush(dbTx, FlushRequired, state) + if err != nil { + return err + } + } } } @@ -719,7 +737,7 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, // Since we may have changed the UTXO cache, we make sure it didn't exceed its // maximum size. If we're pruned and have flushed already, this will be a no-op. return b.db.Update(func(dbTx database.Tx) error { - return b.utxoCache.flush(dbTx, FlushIfNeeded, b.BestSnapshot()) + return b.utxoCache.flush(dbTx, FlushIfNeeded, state) }) } diff --git a/blockchain/testdata/blk_0_to_14131.dat b/blockchain/testdata/blk_0_to_14131.dat new file mode 100644 index 0000000000000000000000000000000000000000..cc1a789e409130cd125656ea441f1dbfc84df701 GIT binary patch literal 16777216 zcmb5%byQVB-v@d+MG)!kZjcgb>5%U3MhR(=?oMf>yIUG0MY_8|y8AxI-e7H6e$qg~-^`Tb&Tm;)&3_Kk^goZ?S{PE@N%g0Wylk;D zqbvDXB43kLO@vhQDO|v}LL`wWJP=9ei#E5Kza&1yFmuoP-ldFuRXJP-x1&bR|I(nv z^zT7}TsKVqzaJ#{e+TI~FQJxuM@b>|lO;p+7EuQlMA_@8ue^pHrgx#+aqe4uigQlE zT=AF_D|s;27}#I8$l^Y|GHo*?awuSEBNy&dKLp`P=O!rI;PebF0X)&mPh|R0 zGdhihr+1Hfs0oPGf#vR-^>_7I&K|x5>B%~+!1Q2O4s5{Yy?oA#YaHLU*21FwbMxgX zembXluFs=WKe;s9+qCzIs1X;Pd^q@HTxR$SYN{T`FN8JeVK*VOsDhe|0Ok+xUN0lut6s# zlK1k+<6G<6g%5K;+Q%42=AW#BH@}WGb^6>p^Yxs9Z{9DG!PrUO^4O+ zQwo5`m3EhqyBGG={$);yRbtt$J@E-0YBI{=pn(CqcM>094j;MYSrC(~2j`QRDeN>p2bFi@T+u3=k(hSl3gVyvP zG$l$RWZNXyT0nT=pCcDAv&Zk8>(S}ns`#|#oDyrkuz16@oyp1q;0c%s!lJzuzVX9K z^@Q-XPwY3;?O49b$k&aYSh}x*JMQ>XlPVUK#j3KBl6;@i z9g#wu=8}grveB>xuJX&rH+HwKh93gI|>XUxvA0z6=0)G=lO< zVDmVh^Ipxzt}e`nKw3%qp@u275Y>fnGbL6^FbzysO5{a-)2>?CTfFldx^WaWzGlKg zzD)@=zL{tjNKOe5xm2w|{|>@~ML^INAM#6Ycv%QL!~-14g{lrV;$K6o}CYZ>Cf6nbQIWhLsr*gkU>ablm`~vc@x#6$D=DmH+v+lE5_#J@kafCHkH2ui>kktmyM>*&# zP`H7(eL+NP$5W?N*aw5eoZx`_#5ICZk&GXJ&0&~58Rb#eV;rjG48n6@nJzsw=uL{= zDn{V+jQ4V!fRXN*9fq4yZA}F58v2~%iz}Y?VFsvpUz>NO!lq_Ul(Q-{IG=jqdNn7! z?fVVn320cp0Gs#XInQN(tusJ>m^rHndkAJT+z8z)3O0XW^g%Vh{@e(88lq+1uOKK# zU^UwzBI|67g%IlY=#5v1_M3dTjWTG(yiyRJF1@$NkBsnI^-jN)m)Y_zfr*^wC8KDR z5fYu$0N%$c+N2nwhvlfBnq8O#C5MsTe&f4?#_SZ-e_(!28Yat(0(o4cW#IRme9w73 zd69bAxb&nSuzHrO{dm6dhzpqY~A^SHb;d0RA#X3H7phX1`(hby?}S1Hc-5Ty`L zU#SrKjF*LCcXD>-AiQ7}S?OG5Ich?8ixm$+ale>Q9_QoMJ>f^H=z?PrX#rq zt`Iwu*tKKIS8TJUSUX(%7RfDzMwe!qFWgSN0X!50DE(3RF^i$581a!_nRsTx*9y{- zyC>wxytrdyno` zdf}FHK4PZL$k-Ks7z0~1fG5hdi%*}NQK@5aSr9Qo8?@VZAaM*OZa}kTKR(xyu?(O=eK#5scRDT*-bJ^yP#4N&(G&0Pm23gOG{MtSUn)cjPcx+y zHh`yN7~Q2A^ze=MNL>V76e8BHjUn2URcdkI!Yo3ie&stV1CR%=?-vU;59N7!+TR=b zqaG9e9pvEqHjN)XWln{VAm6|rLe4eS`<1F=Uwjifzgm%7;7{=$;(9@Yk1A+e`! zdO3D!NUM&`7=(v-{a}@MTsPSXzjNPmfhrbgsdIE!A`UtI`$Pc1BOfqoP#9RAM*OxF zQAH~LJ2tMgp3Y^*%A%Wb-{zF^hKUKtW8)G!1)GQdoHxRiW5psTTZ+B%l@k-{_t7cR zX(i_icN`u%+MDB$%|gv=dH;C!x#m7~m87;X?T_s{GijVELEjF;Bp>1;H6B5DSg)v# z$J5(=Ht~PZW-Zqs3t5S3_HD#ohwa7&0C+5G-`DBdu#5_nk6KTv*n2&~7LHU^AK%K; zY?7jjrKgm!0C`xWHH={Mu%7cSj+S09vJ}&-&+ou=kEhMZr8`8ba(Sb^}S`#5&?VAnbymSufz&%1U>p}u5AoiuRKxfPlLcr|D- z4faEb`u0z3=$-KGK}5WCP51aQA6$iMj_ftCS7teZJo?|H;CC&Q&(otv*sm+ig!K~7 zqWqn`n>N;9O+qMCbX7#FZK%z_jGI`{V%<1D7nER;loF2aEh7kNzA25!`&;LgeGgXg zfF}(IPoDOS$fo4=N2F~=W$IAv#3ySkv0W|dQDGxUI{;5aaw=z69yXt|#1~$9+vefw zM6iqX3~MyoMZt@(oGIOk7s#W*Ks5wAJ(lOZvKv_MG&GnwddR>O1!FQ@)rxU z`c^H;C8JvX#PNh%EMGL|Rs@)ECdvNPkpA$}j97)nwQ2Lvs@juT28*!elyX7}APy9fDsDKO91nxE}BX(@pZ4i22EqJ9CVz z-u>fIYSyTL&0~Ge!=tD*N=2`#$U}!Ds`t+GfkHMycVRw4?)>I-xIJQ8{QE099GS6d`5DUckd!dm-JReM)LT)aqd@csRny#xI$C9MB?88)1z*Js05oQ@SGP< zUhb@uD;SO>pT=I!gvO`VP>u6BA=+U(zw31yVxjlDp~L>FG}K~oE^L0jx`htB`cw9q z%4tl;u$*bk&q!S$JUt;Il+V8R)Y9^M{)r@MtP{Dfb^>#Pe>D@s-UE28q~xU%(7vx5 z>Zx)GD!iLDL%()o8AD3Gh4f@(S42&L69DqaxlUNY<_SILwH+H}dbhh3&TK=6rQuI+ z!rOI*kMF|Pn_!p5N2Fcq`W7Dz{}^^aBgZQ`u~gb^q0k7T`c6xvQ_LRVWDxNM9fU_k z;%t}wUcFR&z0it&z*J$TpaPrv0xRmQu4%kpQq&}# z+Q@B|^MZ%W|8Uz}aV9d(D&i{(*=mSt+woT$+hE7tO+& zsOBr<@XMTstXOi<=2?sjCOKvh-dB=0Btq6)s7vo`#CDh_*y%sKX>0O}y!izG=I>m~ zkFpuL7ftnVf>6Ybvi2EI{!FHI8k~vRRJ$K&Sq~ItR6|M3-en~Toof25?nJzYvFz17eB5Vg=(Y@_rmI}-rSuQZ zpXJSx+&MsaqKNk2p71fXHm(YXjtodSK743(tZ5n@XNf~;2Bi1r^SDgawLFJ-msdxP zxGjuakhrf)a_FQEG_m^mnn9P|KOWm4PbSzrkbBMu2HtTDIxgK^i$8<>7~+T@XOddX z;J?t&vb}F~yX!$5_4dh-nZWHt=wqR#SyafI@r}7-$xP$#^c)kY;;?}R;SHwb<|ryw zzj+kTOzw--fqaTMV$ujBQ82=H>jCgsmE@g1*6t;Butprf#CqDDnD{h(>UpE6P9W$L zYQ1(b&;d*j0UC1$Y#!U<~;%sYJ6UnfYBTNi<9Yt@?=AC;F4-Bw7>5=lz?^T_=@t6fR$je>1Y zBk~$DbNIjD|B>QcFvrmb;dPH&)RT9Pq^$EDqwEv5?Y#&aM(@TvjpKNN_&e9q-~NEK zU7yG&e4qYqvEQt29Z?PW6Y7aFM!T=cF>EsZde6V~R@+g)=7G$VHA*HS*H|9DQh>#+ zDMz{Q8gewQK3LVmk@omXRTz3XwUxAYVig;Nfh`3=pDkMiz4^@pk($CEyY_2)`cG6+ zTM*v*rKzmunZ02n$Bpj+8v7a~zHonq_#0|#kHJkqdT8iH#r$ud#syW1veepKTp6`- zj{S{v=j_F1QV}xueysNad1PT^f?)HwpQq<7`|+}nASxu0ugvS5Q@}Y`5fZC0ek#_8 zW(lHI^@hG|Wv-2v;^oV+h3zxP6Nct|<0J${AI?FT9`$3IMS}wno}sIM`#s*r6~)~0 zIFkOxr1v6pE6JyB@Ae$*3jjPvN8I1oXfgO~uMXI}+n9JyJ5CBn;NFsb z8u-T(X$OCz)i(IYK~)Mo@Mc)r=5D~mz$*pd!~oNX?zqNX99 zi>ebz&S zL=*-0Moy3#sf6b`4@C8Q^&fVWI==~j19?nce#~I=K0N3BqV2S+O)tG{tPbJ-qG)XX zxn*Ix_B1NT&CS3xbdJHN??k|K$5i{#DQa;u^s7q#-e{x3AVxcgv`GV;nu{FWvN3f4U=! zcHC>KR*u7FZyd;jv~yBzeQ6huWd8OSnlBRRE8K2ya3jX;BjkL<&cVJ zA*|Vm`aOQwalBhI2abiI$XU$xTXox<3dhYKeX7|U{i}`!x^G+dC_s2c7NH5wxQ*J; zU-!pU?co%PvMBX7p)XQ+h>xoPJk9V-h}CS$0G35NsDQ;zY4?}ciD#l8x%~c}UA7=BQ;G@dgRzv)3;7i9)$Zh?RHeT|l1h$F022!CoiV zyNL^n?G&?AJcch3p|H`)Se$*Wqt0%bhY!XimBXTf35zltV-0{=%FJ{D~1S5hce8;K>F1=LgIf zpAw}ud;BFBluPO;-o-?L&H$UrP?E_Xj zBN;z4!3RRR6MRV~B!L%G*qPW#Jr{dF(lpfatEO!5g)f8h9(3q?k$z8SqUyulOK{)G zP=tW+K5WL0SCMdx^asga3-9Rgglh9We6B2_3pgeH`@MSQE2}=zjmdiGhc!6-MZ`-% z8SkTT38r{s^6-cbzlq$e0(mU#>9}AwPNL`O_3tN7H~;uHQf#3eQqaiSTEiA|`Z(N? z=4I}#D9gkUl7{sqWtYWBYHkHqSXvY>ZD*%LCzQg_l&Ibhr=U2`5QKLP@!~fX!NN4D zg5(o3L{$G<1hwNUlHWVShc2{$^k(x+b+AT6{s=K~mtEK=_18WbynVbU*voPu(nD}b zylmM3@<>}5bHV0;42V`FH+%1V9r+@T^8|-{_AqeKsEqmf=?MG|PRyGVqRu)Ye@n6S z>3=H}v?i)GS#7)}^~Ii3_zZ`#s(z|H6qp9WYvyc#cqN9|wg`dSPA7y7^&7W91!C*RyHQC!qkm%Om?{39;pe zqq@0#?Z9a$V#w(O*r>ZS7{plp)KvG;nSCISWJkCH?DRmUadUF`By*x$O4YN}!j}#p z4qun3ck#-8c&MnbVJLJri$?T9|ME?KZRSR?O8Dh9gK4VY_?C|RFG^2)uTBhA23io_ zSGS(1so@XXFRsw2Y}vUvK`I~G`8v%c5H1MosHPZrCL^+EKwANu$MrltmE&~fA!WG?gWo)|m970RSoVVZ!c>G3_Uj^2 zBcOWrzOY3r5-!$AweGw*;4)A=7UVIK+AgQpJyrkg%n^+^Bs6P`|e<$Re) z&C3!xcPQ~dWVmw|sDvN@PeZHp>50DbJ)24pa^~4P_bobRmAX^Y7OH?WYRp6#T+1UM zk3p*n{FyS|=ez*XxG%5Y#E48-ZHd@bNOz*fbR2LrDu=TAhR*9=k7Nz^*@~Ag zy9)$j&?~;5)lT_g%X!YClKjW8Q%h$7S(BcYFZ+12>%UN+greHb zjsZNx*EEFnEIlJPffzCFyGZd8l#f=}7y^xgmPJuioDVcX*rzh~7hd1|i z526DtY3zc5WU?qjD@!0nU0}}iG{j(?E<<{*oEL*2{mfpzU(8RBd z&gM6HAN+9pgM7)M9e)w%Vtd^gFthkEOeK$&mCYG!lV~u);>@F_(x>fa{{k(#GGe^T zA)He`{8=|2=~Sg@@jZw(TH9x96oN>B0Kk(+xS;x=)Nd_UOH?8?e$i{rCLnEubVg?y zt$VoTa#L+}1LW~!z@LE4Q+>|UCT0#5;8%E3$R|e`l0o!MvJClC>4Yx4XqY)LZ}K*( z)5vyIpvLtY)mtmauswW%#)#9Et@X|Z-gQ$46}%Qnc`Ss}i&D4a%e((~?#08B zfz2~`&KsCQcT#QMS5s==&FtU`%)grW%!eszg7&E|%R|R}!qu^^OaX^Onkr&Yanv~4 zV|L#9&qB>st7y>~RPhY1{{RRNw#n}F1)RVa@|skoX$VOn3ZhyLXRLELc7dh8ODMJW z&h4A$NqNV%r`Dg=D2BZ#UF4>QRnyfFgC;jq7RD_f{+)XZXZ2w744?CeuHXqonU7x8 z#UE7lsQl=Vs!ufMw@--wtoz0;1k%FdgNtw<{A;By-pNsm_(b$pg0VxL#!X}jmnFTC#Wl9-MmfTZWE=w@z9 z&Fv&Q=11un!`<`v?!$e$^}beksE8P#aY8{ZQ!AuQI)3$3mUN1AloOtk5Yl;VU+LB> z8frb1`bYu|Q`D4eAnqoSMGK5!P&mI!~9>*lL8cq%h0{tS*M^AgF zGkHLI8(gGVy!7*ZFtLRzbvh)Kzl{FK=-n>x>_M)+lY@PeFo6i<5i#SS|KE8Cf46Bs z`9M7Pac2ccAfYq~yNhl!w%j`W{Hfvg`*xW5mqn2!nWsN{Ga2ql-gL!^+6A+{)2M$W zUB)Nv#g%uRjOlsvXqVK2(ICDPrgaZYq8%i%R(ZP<6=TcAo}dwZIleRHHE$+5@Xb(q zi90}iQn_WwIKpdl-@ieo<5}O1u~?SbyF=^oZ+`rU3h*&PD5KUFXFqE>7VJpF_EBRj3xFCj_(a`n36wQOz!Bq7Iab=$H%lNN|?nL$?A)pH6r zx?!1x{i7YHH2bxi#}AIU26eY?fN%AY^@m*CFfW9JB)Vo#JT~;WH2YcMi>$?7w~gxq z+cL&iKp&TwnG)Ff#en$ek|HG;jzrG9gYWU|UKPWi4J!`tq1O2$caG!x&i8vbIgxNi z=az30ciGUmKM8-ZaNR(v!*dFmyH~gptC}hU@pVTjR-5&Ybil_HwZoSzCs}4~q0Tpa zj2)bE_&cOM{ChnN8Af!!4Tm$$^%B}Qv(}rSyywrtSA=!h*hgVNe)2D9=FOsg zI8^&x4?2k>5->Bly3uIAIqEUF9rK;B!uMeTePnCH)L{EEKztI&C>f^Ax#FTXb4fX7 z_`$R&<46Qj#j_98#@Lr;*!BxA-YyO}BOpJ>cX|4c_)($46%}M@VGuJX%?V>JrfB?+ zZ~8xfJD~rJF!ZPL*kH|N;y>%QJ?hR9y?7OW*5()77yYyk@a0U|^;E*J+&^HbL>P^x z7=JT3jIYPXAKI0uoP6Uuzh8_E^vSy&!TjHS|0a~+o_C+PO^_XF1m@*dKfP(vJ8~yF zzV4s}pE|K=+v2qlFpKtjCO4&QjyJY9LKm25`STfmbZ<3kVSQoTaP|Q zF0n6(;H>n6`!tnW(PTNN`&1|Hxlsg&&yg28cw?sj5@`aBvOe*Fa*YO^Pg=QlndAU! zAkl^Jm=7Q5BUSQp1KXDm;)^9}Pf%vX497VkD{e94L zetxAOzU0s6N1~NKyZq%8yX>ub6ELQe@W1Cz{LC`vNu^t-pkPQLBHJtue;Mh(sCuTP zqH7&CXn<9DZg+9tP8*p~`T&w2{S{+~j%{YpH!a203?(W*@+r~rsn^EX(*CK#0ADNl ztWR+I`+fNj@q-=R?-t_XcLhc_j+=Q&9>g%vdw#f)0(}_w;m2U-R|Db`MOlA1nvqHuJEA?%KG5ojn8)}lBfGy z`ASkH5TDFfhIzEli?ssZ=WyWF$5JGz7`nXnZjKxa%G&@wc#-|eIMjMN%wH{OtrA4} zhT8V7NUE*N_0w|51!OMX>tsM54m}4Lvo8P6zgiHV$hN4=*68O0V|H}mv&jATuMHdI zr6x1k-36iOmQYtW=ljWfa})I1D0BS{da@&y`orPYthM=gAW%2(UQ_;t0rBzdI#Iqf z!tolUjq*{53@-@8jmWO>l|l<1F8RCE*Wfmf<`jHwF~A}9-t!Oa>yK~fnYmkibfSfL zYRy^nio7U+K3?IiTd?zM0r7?QvbN7f7Q7w}>m1yP*MOCKt+gnnfyzsHZ~A1+#JGJD zsmBv$2a&~iC9mlN`}Tffs8(y@ly&Us&>-TISym^AZ)in+=oNR<{iWKC7i$+hY-6;K z{YUb5`%Gmp^j`WJ&q@Yu}dz zGzqh1VVL;(*>^kv1Q+CC|GU`t-~L4n^zU>*4Q&e$S>9O;MXGmPrxYLSXT}HL~!3baia0Cx(=5;2^)PX zY?{J&zJbnqx}m%Cy50D+7Lysf8>{vWZY_vpNA>CiRu#AZ-6&l1B(8Ltw)RKrXlSsW z{*{0aLY(@S>iQMZu)IOzuo|J?%s?N{cm2u#yYJuS9rF3*o%oD;6}L+CtQX_O>l^vS zEfMBSy8WW=Y$N{!Oav5&gq(MxZciO*OzhFqhD(|SMJ6xi0^Q%9GYw;UJW7`Og02_o zoC;UDK-rBblt|}}XlcAu?;M@BVnD3YR_y;<-8t0?1@m(AdXt$cM%T{%Cu;(neDWzo zRExvjM+Ix;PZKKaKpw3Y9QZ5k(9d~teHHf?Eb<694ic|lYNPjMFk`t?YNUN}sbJS| z6^&Ce9592xn?SlP(U3(Pq&#Bd&uYyMSs~ydPt5OiAkqKyKWE>6Z_ZRFC^RP4u{2m! zYHmk$rXd>n)0i5Qd&=#tgcQI(YT%uj3tni z+`rxcdE}j3Z^2IQKSSLA_ahc^PwMw13MQl9-m9kIry~-6X>Qh@Pb`NKK1W_vztz0- z!`}F@!FUV9X3K5xPMx>B_MpzGGM!CK*H8IjqE{FSgeSL&s1P?zkX8NuFoSx&?yL63 zVk_h!=io71IUkwdgSV^l#_^>GbB4KRBr(`{j{&4NT&U{=>nMQvrfSl{# z?Y20CXylYYj1iTK6aXViA_KxxcbUWpcx6=YQ!C9VV`ufFoNR-D0&@5IJ(+?gfcMgK zu;9%`Cyaj`#;GFCTcsGhU`Uwsyd$#XZ^F2$khLUlfjqKaw%1_uKne-^)#uLl4jAeQCiUN5XB@+Z-^H85R&IhRX@%u$?zCX+urYF;FYnV}CwiiC< z92?2K?-WJ}iA!yQ8{UOHeWy5_YdjG*`l-pAhB$k+Gkb?}x7)B4B@cwh9GWH@k!6@Q zw)sdC`U?3PDW=h=Y8+KC-a057z@xQY;{tD% ze3x$p5CKel;AE5~1zTNY{U^ zoZa@bQta*ag;L{o6V(-2ngW~9(_8Ijt53}!JW_~(fgZ^@PrAU=yQ7Y<61(PP*6BHk zt{t59zZ<4{mCKkV3k3A17;o=0>BtCDYcyvqwJViU$l%>?1IKhdZGb$s-#FkmPLQr; z$D+!6v2&j?Sx1aYE+uX@2IIJ^>#(cJzel>sS^eNw-1mjdR5G|fZeNS=j(nQW`IIAZ z9SFD_W$0%=3-1Uyfbb$GkYXAVv|Ynab%tknbT*EhPT|-+H?ShW*S0_&3%17**y(|k{U1*Y_p!&6eF@SV_{@`K zPIv>ImdtW~xRi0^?%{ujOI#|l>BpfP8pz;Bh0N2r8l%8eYJ}$7%I0QHd5fHDunEEo z7&*yENV|eTrCzdl>7XK_4>`!sN#qo)XbJBLXq>I@Mg2bfXSjT+$Mw4@w3__!y$1$f zEBE1W=Ozn=^xaoz2Oy8tpE&_+9!Sp_ZG^ej)>-~2jO^Daxyi~gn^2CHce$1GRDl@| z(d5X!H}m5+g@PAT?}r4vhwIC|(_9#9gy3o=GPp~vt!>MA5T25Pw2_+hWv`B!iOc06 z-S10Eo7MNiuNH5~$gluBhk?mVDmtBHBg;gW!T#rol+J~cqjgTv>-39zV1Y;?AKN776Mg0CODbTKk9vv2YAo=?YCjnjh5i8ZxRYwGWm&pPdWEbWD zfJewAZOr@*qf=h(lxsX>FhY{YUo$N4muIoW+OWUhyKl2@KpqyE1^9*IAT>(c1{zwX z(;Wy4e|$gDk!Q=SRE-Ek>eSpxyfyr8nXp+JYY{dEVcn90FC15{aA(lL2DSe!kRagt z7l-Sg;jG*DAnD16|Ej~Nbl2?f=M08>s^%`M|B$u3T3Tdwco7fa)o7ncd6ezz4bs@K zN_F1)Uxc4cV%imI`!aL!uq>r?ReJ$>oVy!qV5f)s{KCNAp!g2*7OMXVz5Z>@)zCI#^B>1P=3p{yD;& zw-7(MGE$=#c>{TbS|l@I^FW@xGa3A4+yXga%}yy_DGPte$$#UonTzp#I=m37FU-<RglWRc&$$M`$9Cv0pG9!6k)yb7R0La5>sR92186YKC^Yr&phvLUI znmeICjalQ6vX#BAnm9JvuJVTZ= zS!K2zGLUe-A#Xdvjq=s?GjGk-r80l#er>^Bo*s)*jbV4l(<3Hj2EPu%>trkcNY`g# z+rgsu@&FG?_R&)CRj|7gpZcF!X8^C)iQ1t0Y@UYkiAhFebVGt=QF!iL;+Q9l@>PuX zP+Ue?2#|+ysFntH;{%)%ls=kD&xHO) z_~mTLrSJ7!nzk~6&JuaF+Y?InVA=8^C@XegxCDg9+{|$18a4R6fVaQ8#)QJtMzsqe zso5Nnq{!q9z%wH}ZDx0FhJG@)@g95Xc9ogFBB@DDw?#aUb9~qD*P#*)Z}tL$iCxivdIr|dO{Vf=agVHM-G`xZ(Z9euxwEr7?U zhgGk6a6~rBj%RzrPFtPzegFL%<9=?#JEMTcgodwK5kMYn1I0Ml=`la&mD+`def0lU z&D3Dj7s+1OJ4I@gT3LrEw?*IkST0^(=_sol3(;oUi zn<)u>ks!RWRfUZ{T{icb5R{BVR4uNGdlZ*W^Kmhx7ZZp8o@UId+_bV*+tu0>a3B&~99dF2xEb!}4 z6~sb168PBj3cu@K_2%oAscvbq0Pv!ela^r*$B}cJF?7y|LUDBCzKo35oL6e9l9y}d zQ?aGR0C}`tC7-}fkL`JSJrFz#k&zNEXOlKTt&bPeSy@f{B|dL(=6}GATMpfRp^>mH zxGbm23gxZAq~=G1*dygrDqwbTb`U?wXR>%O1?4fKym;Jk8mpwC{=!p0?y|fx1TkA& zh)FzOKn&oudxo-B8u+5rUgCxavo~ikB&p(5Mh+WBm(+C5%rHd0hzIg0$3I7c%>yZa zY==N>N>#Uj3;In7aPt-Z7QsJEH~paH{gr9*vQfi%k&UZ43onXNwCL_F?z*=iQ(TOf)43 z4^AMac}0>(_if#bN!}8Y7S(xO1yR&_+b?eX&cBTli!RmpeU$zgNiMn)*H^e+aXRwC zg<063;~~V~D6&J!sX!hnlbJc#Jdj5V;WXg+r8L?KHnMs&%w4h%1;^#kGr8$#JR0P5 zz}+t3kB|gQV~8d>lEB|BiF20UGZiy;nkE*}D4VZuk#bj7f$)Z+`w$?i^L0#w8|Zsy zrlH;|+_Y5)9pWQ547>#JOhb(Cx74WCPcJYviyvufn322Vso=_RIwG z*yha!z~+fOKlfT`jk#*YR(rQmn3Gf(VoQ%9#_|T~%SYV~G+%fq?!(aXKz4Z-^on9< zQ77>D<+U<>Ag<<>CYcBy!pO(R7(eOwhdW7<0R1H|$*Y-}d2! z6kW08@+X1^J@?{qrTxtwnL>XQvX=kGa~tMKiKQG=Hs?1+Px-sZXNmyTABpq8@qjf& zU^F7?WX=UiQKI*Di>hY`jCD=FoYWtNh>e^loE zPd!ikDHhQxw2&TnM% zU&eGlerrn)8wtp0?pR~a$07Ufb-SY6;SOk=SGm8xn*07?mL<3Msd1O(wWLx`Gb#Bn zqv&o{EK|QVQd$J$VcrH_g3XhAo*oV%>ogX;>$W26mGPJ8&38uJJo~BZkBGKCWFJ#I z8t0(629t#{HPliLsVwNCI7G4GVx#klh{U`Ha@3LB8qYv@e#vRXnPn+n4fT2jrOw(m zVr~Z5km~vi8#5_&0N$^oa`Mtjh(sl2ZE_?o83}(Z=b`$kW0*Rdaj0LlqHpEOfIM8L zH1PL>DL>~y@JA-Pq1sYgU1K35MHCmgy&sS_l_w$oBOexjm#aN%5m9ja*zIw4{GXND z6>5uLDkzkXP*SMvVe@5l2qySMAUs@VLo`MIYdII^dgH}a?S5O%;Gyx1lh?#JFn{M- z&O)OLdA6@He6J(#&*lQ)A7Vlfxx_Nx>eeJkt>laaSylc^Psmpu?DSNg^JG3lWMr!| zRAl?UIyjD~Uti_i@fzLQ9p;sH`VcqpDc{L^c2NR`)d%wKN{%Co_?qd@zNb{-oEEv; znkT}aKp_yGlR$GQlCuHsV??ZYt@h>3=avLQ&nK}44_L&%*FEX_DY3^0Q~s6MYqnmIuC&q2Ix)*)Z1Te&0*(L&w^HXl zzSxg`t@>IZkFK*84eaz>pY!7Rl}Hy%xG&v09UkomAO3J#jR#k>z4)4~cJqe710}^S zta_tTew_?6_)UeV<7WAf1I)7n-9=a(OwMroKp4={~UUP;MwUg;l% zub;L*cR^~)`U800hiT2I>fNhk7TkP^Z;C5>k6BF4Q53oVSo7=s;SIt`YXtHjAm}o| z=7AKis>ai*i!WhG2Rl@1dnFP7+&bMqrMPLNvsG#c-VZ9RXeo}jQWgr6`rtUeZF;^F zc%t!cMZvYWy_ye(>w_Fj_5Y;z-_>V~&q%q3Q{O3AX`<9i@JGu3eAPOX9^2l>#PtXS z@O;SWI<&(BgqMS;A9ZMkcGt9){CQn`F{QPW5k5~Y9*9)g9zD8R#*Xpi;CC~}-i2lSq*>mmo^N>e zC6G!utk|YAw;btzpJ(}B-~MS9d%|Zb_*&OZR&JFUoqcQOi+$-}8|(@!FMtm!&eHo@ z<f2zi%Pa zC%3gfx*``f+=EpjqdkT+e_bu*@FI$`(y!> zEl7SN6mAu<1Dkmkkr@KHyFY?-FV!=cbhQ`Lrpo^o2eMSv+!mW>nWoFlnTgWko~jsJ zFH@0wZaBkGiU@px_|D%6^u0-Elmpur3F1Ry5}4|K`SV5fgy;AO8Nx*1-aIGkFUfD> z(vO{M=aLNr^S|l$IEd4d?KF>-uzU^sPlAl`#^O`o(!G>;>PGtC5$%8TD=Y3X>luY; zgfe91`s}ruo~GsW)xPA%O81b?--ibN^e);!%sEbGz8!Ue+dSj>Stm5ur^*2H;DCGY ztGiST-3#u2Hlr`yPlR`|*)))B__QxTxcH63 z`zOviIY%<(s{x}#f;!g@D374?Jx2Q0i4ozU0FeB&Hh-Bmyt!#aXg@JWf=J|u&X}{~ z{hFn2!1?m;WMHCP4i?KJ@8Wpkul8fxjiMdOo6f1};0m9~(_XQ)@7sm_|Jo<)H5d;? z{CEC=R?p?DK#iLrW7KaN!$#v0zy^dD2w9{l-Z;_OF9g5x&2G#@byJV!&Ul;18`87> zf&_+OaP}K_aDADZy(0AQWQ-&b-y3T@L`AyGZK6plEQZBJNnBxN_diQM4Kp^DvVili zl!!D%Wa#_Aiv?!vfy$g}DRZLAk518+*$an|_OG}(TnB+ZgcS~Vu=6Vd$*&o`%kXAH zxysq{X@P#BR5`4Eiwug3+~m8Tk!z^<{k=R18{WJ`hb1J+oye`WcZ=i{9r?J^L{A~X zX*?~J-3Ew{tIP5+vyf6T5XX$naTW^bP3hC-<$duz_+^D9l}7Q)ICpayr5OA z_=#<7oLJmYusU7Ui_)4ZinQ(5zx>?)vxW(%h6Q~7f4%@$ynp!>gZO6dahk8NmY26a z>-bhS;xAgR-@zkt1?}2!_G&+=qo3OACXIVK-k}6+u0#v7JOVfTG#uPUxUX~c-@nv@ywE1>BqTZncPmWqkVCol zcY0qau~A(=oVjv5l>30lDA31HlTrz`uMEUDjP^@|E>#jIE<{T%X4js{n)7fpk6J_C z49+a3I-B~}e12=%<<2YjLzv_>k&Wf3RsM&WRXJ>zH42ZHSf*%dAif_&{agqvj@C91 zjdo5y14P2l(IwdHx+z{vc25bA?kAI-Wh-QVeIp+Iq z$nd;Ur^5qJt|SA%SJ-N#6&bk1Ad$~~wnIY9uG9%53wtjAt++ck)dDs^dt(CVqfXid zNV`>X`>aSrJZa5(kX?}=Z4lW`(}>Ku@y z;fPounW9MUxxT3U14a3(hBDT?5G22keAXnZA-}#>WO#0HdPICJNPM+FwQIYg>wWrn z;^Tn^qQU2Iyi*MVut@-UV(8sv=@+a8&HGuf8PwH$X zvNJ|Cv(1FiLq{C2#IW$OpaU?eNUhQT@CT1okITGsbh{sZ5QoW3q*L(2BuriTY*|e1 zC3bGy@%|RHy0fqQZI~t0z-L|>>>qgpr@aUrQM=Fz;a(?fZOMTAI=>3{Hr+@Ew0e9f z$0*(~yv+$tOrrWMa9+rkojjr-8a4y;;X}-^fbDAo@ogP`S$z3fdJ6sO^|_Jn+&9ZK zG-6E#RDtPg`<3QnEGlKw6p2+oM0qBFvld}NZ*A3#!+Ty`K>0p;6MNR!F9yD?6wFyfYlgT4uokL#-59!vv z?NIE&9IZ^Ow!_Bn*O^C*)-Zbe*-*$mGdce~nN$QEh|f|iYOCqPT0lcDpN~;;UWr4i zfOrPBp!IT;*x&o>i>Y~qeupZyVpDv&?N-!PC5<1`WGBMx4j?F{yn7PrxCqb}Isixa!joBEX| zK6)sU0D^~11iic2x9Im6HCD4c$|B!G##%xbQ&A->^&8abfqZlW_{G5;jLU8|7_j}b zQef@s5Q#)clUv*)tCmmsJ$iTWal_Sxy`_aT@I<{4Hz_YmbGM`O%uSky9fq0Z@mL4= zNQ4*>K+f+wkS}W#FZ))G!qBnT`_&-^TqW2r z^vQQLpRuRQYUIUAFqL7ib{7}^8Y%y$_V=3xpTL3HFWgfDn*bki?A9pAzBwRYoTOBe z`zZ>?Cgzt&i1i;vig&MItEi6fn|y2%lopU(`19o6i!E10-%rA(&{(kIUT z(xVWvPBQ-~2IPAiD9dQThITukK?~K8fKLfI9O4Zvs-_YAJvrjZ2Uqq!-^f=jM!ct( z68vRjSh9xGiLWJf?s@ICTlkSggU>F&hf(5b+)Z%~gE!92(^_W{-fuMho?k~&bIEf_+TQeHn!>t9NS4dwnw{yCInZ~9 zZwV)f;2XWz2l${%PwheW?E?9Tzr}n#*5P=}_Jb_F66THPo@~C%$n;TvNdBoKUciL7 zS=wsN*QD*mtH~87DHu*%BJx=E$dDEf9S>(Z{nhBd>gvDOcTz3-2c3lw(`v~9z z(=g-#+4lp;$L0`#g-P9bVQeZnxt(CHO9j8|JZ#usfAJ586s`VSa0t9&?BK5W(vPLu?PXIoWg~tn!edj>F#fLg< zp)vR^t)on%sLo?rA8$xW4Vzi6E!IZ1UMLg=6%ZwSPA5-W3W7t?j2bzE=i8OraHNdB5Ta5j`_x(RDeyjR&)iJ$c=GKCe#pyYD z8x0SA?9Q{b(n|ytFHhsXYukNzce77_eTTW5YdBtbN5o=(1lA&w^R z)Xr>xaCBVFPklvy1K?5dIDlSf2Gpnx##pP}U#%{8##QIREId!r-}~cjdlx}8x96E; z2K~!`Be3@tS!3acKHeKh)>3y>r;c$_#$)^vnnsj6o?Fe3K)hodSjAqVJWW5H@ty3) zE9mfG17E}b*L&>mGJmhVY0dM0LDM2t^<$rH$od7D4*i?%Re40Xm%+goE!7 z52#Ae+Nxf1Adc>UIz4PPtTvzH)NccFGk2_{Os;$uPwAU8#SQh&B*x-G{B&;T*EnU_ z*nsF^DwLn~9JpX^-;zBJfOuKjo&kXfY6GcG&yMaoRoGuK=@)T*T0--V;mv>IT@!bE zm%?gKo?Yb#JKviYf43&hX|OwwP}zxlgOQS$>H-DeB`?z;gM91(?UsUG3I4+kdTx

    {9(`)Hgt)2QSE6kgbcQX9NJqkD9+4)RI@E- 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
    1. N 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�C=r|Sdpv}* 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�?>CIc|6ePdp9{5g^W5 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

      094ydrkvYO4ud&G1lJ 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 z zL%t&5N@@PZ*!%zKUs>Hm z=nbuz17JQK#TN5pbn#w)eEi_pFMoNb{crc6E%EKM$pK8G&xK2$ZS5ZKabOpa(yz$h zV_`G_A-qp_LAn`yc(ffD5mTxWDmruYAH=$6{C_%RWaKdFObb`Q1MsFx5em+7H4q*Q zEaeV>=FAlEec}o*sU*?70i9WE$wn% zH3$C{zFUs{)3(U;k9k~OXPVe6$Px`@;Ct+B?(b)pWs~gA+Nn9p{%x4bq-R>0^8m z>DVCn^fTU-4mHbPR78a%N>lBN7#;L@eO>2VqrEmiWk36f=2Kq&?tTQ|`$>jU7B!a6 zLsI4wcNyXgIY#qpTJ{EWzrQ0O_#UXTMxf)yz3ptgtJgi@W9~dPtbNP=g6rBnO9pZV zCj4p3FhG6@*Ubj ztWfjWmo%=gEV+srC@zR{-}C5>kbm?UxcSoqy8EBGi8!GDw!fYV=7NLhW(XPS6|ryx|C4w!5y#T(Tp2}T|NQVO z7%~%N8b>hTtldDa&tKJy++Z(MCK*y~?Q;`}(FqXGZdU<(emZkV5QU@nEAH-zAA;c( zN;v!Z5-wk0ynY#Wh-P%As)X0uckgR^dPOP=#%<3&$;vF{SV*X~}+=xx7N zKkzAy!l?xVJT>+>c3n0@&vhs23v`X9WX;6qK!h`Dl#lud5zrh*l@7M@*mEH%`O>+t zTN-LffTJ@hLT&>8L<6XAk=6OmNSGVF3LX=&LE;=(L7bkCzQl{<$kVOM(BznOs8R{y z{oI0NvkR`1Q_dK?`PNO65SyxJAKCc?>Wh6>0KUsbRPUo5$59f*Ps*WweOBLG+7VkX zkLQ~bhSYCe1R9Lq5E1o#uN(+<`vR%Rk)E3stj*>-16!!f7Q<^DCrJUApOe+pj(b|i zjjzB+AK4mxAwhSY5EQ+@;k-7VTi*(t}Ik%qEo=?jp3RUo^9;z2DddE>c58VhTCWv7T1*fScrNj3i+f%B{>GKk@* z-g?%^r&CErqsj6?_hA4%mI?R^%sJKvULGI-Ull>7XLK?m%RN~Qq?C)F)lOAHz8FiM zRs$34(}8?A6Ct=gq??~3jbw&`S0cX@n$>`4Y4|JWBfR1$n5WXsZhrRB{QUIt&#Hg` zE<+d;rlZRo{}w|k>Z$iJ(vxT2SQ;k*y)($NM;?N<`5@XiCq~45O^_@hLHzB*P%9sD z7D`G?#!?=Aw0D3$sTMPUuY@d zfN!_U`_5DldrtcnU=*zF8OBKqh6K)=Y6h&-v?iIJQ18p^ z8BF<4W4O{^Hce&cG4CL_EoGx&Y^cWFo6(GO_*P-U3%J+d8K3>j@9*fEZU{uIwQ(5k z-~rEFstlQ$)yGRIh-k1_`T2`~@Y}y0AyYZ5t+ra#ky+8PuUD}$8hGY0 z$_To=I6hQ>_(*o(KQAQa)`%AAEAMnFb%lB9ZGOTZ+eAb;jJE}iYXyzG$25`0Qibsy zDkpZqqfsG`i2~iS6Niw1^27N21@O3CU?XJf*P4siRbQ$mBuiKI;qm%J93@6nU12PK zKKc?rcHuRDW1RUEfi5?GVdRHlB{@Wg7fsx84bkF3WRs0C^z3`nZ6f+&A2xvR#x~|I zb9UhY%mq8+cC|6IBZ`-O!&FsZ0yGO7-}88A$E?ATSZlH7tAmDL&1qZds|d#3!JRI3 zkh_~;##nM!fc!ilc{n@wbiyNqd6d8^98#k6Kfu?w*>xL33Nb(WKDpqLF~It{b>3<9 zu|{IIb$JL}tQ^1rw;-^b4s}_^=Z-%6(Csy0U+g0U@NF!Q74Bv&6_8`X=hX$>;+G5C zIdRh5;qoz>8~ol{(;`)r3%3B=mL>5;M!BDE!hnO=D=xxn<^t`=wcRM?#0$WeLRM`J z>Q<=}MB?9?YfLwKj-I?6D46u7d?HWTL$L2dV3^N45|+7 zCo_(sldoyx&pwQgNXRetkplRF;zXkDr5v!#2WY_GmiE#?t)REu4}Z0+ekUhkAj&j zf+n*JXtoueGfW%8!!G-K|GvCS4GQq>Ho2NMg%+fFEXxLZstWyL<0F#OH zsrfm4D%=3CYufV}K%wBzkn8uyeHZr8ng9XQWapuW#qNFYN>N5%KKBCi-}v~~bu0(AE*w}xIjGSYy^7)6XdW2jOy{P zcK+=hUV*WD9|!d$Smj<&e+JLb2_i=eV6_^iiQLz(0tyJqkR^hdP|Dc@ z_OpygfkEYMG165VH;1O4Y{YhnMS4|y*l*0UxW_&+_s{pYdSW!E=K%ZZBf&d<%U#~@Vl#Ie zEuvGyn*;KF^K{}87Co(<{XC6s^MwP?Cd<^2ttSOFP%1wTu_hPz1G=Q<{2w2&o7c;~ zxdqs@>%+=xV`+FKYD=pa_ybKBk(k} zl2IeFW&7e}k~NE(byrk$TL(%XW)0)&wQSEe-$EqS5f2x1Uh)`6AT{U6mTUGbdcBfI zLZK~Q`xoEe<_G4$YqnAMnUn3C7L#}GoAHC?#oMATLPYU4n5X!tOAwP8dqc^Be3_ym zg7$<#tCtn`G1L z1P2k$-`8EH`jFaX85D|2%sV*ugKM=ge;3z*yGGnPNFXZF*FXe4BPofOSO)OjgP>O# z&KRg94Ss_Mm0>YYG+n5NRfwjDqWJc7O*nX`RmE~`Y!Gc1Bqh!@kyI3jkMJG3X|q+b zUe9}2MA80@XCFx?^2>K!^8xtExPCPpP=PAj7n&9|H2-+8Ws(D7Tj!tLMuE>4y=7|lVk(dzZlsoyN! zYeC{sLZ(*104LBq&Ak+*jcF1NjX3ZC?|pEX&>}fIwJZ4E?kYt>9Eu}sqg2ed_3Xnb zwto4pWPSkO7h%LZMHa zS$M{@Hk|1ZcPuBcvPh zf0`R4e`7jxhY(AST2;dd(y80XZ^ZSP8N*sB;%eyqic_nU#vdOl4%f?jKY(kP(=(mQ z=wjOmI{R-ks|g?_I6FPQ^e-nAC$04_4K0Dz$%g-$_Efw)A~2{DBO%nDsB%W?>BNSQ zhPl;&7RRp!ybFOx%)5_yVUMJ>u4X~FqJFh(;8ei?x(*wO`Blqf=RR#uBj?HxFT;Bw zGvxC=+XP?VqD3!7b}S^oi+TeYm@<9mIX(2 zZLqzRq74Lr&*dHd+Ff}}ShGT`yD#_YM0rO1qatPfRlIB0xsClmRF$_Od7 zB_7ycd(%NqxKGFC91joUX*B4y>BfG|r#EfGGW5|cCsWD>@D(+Hy;E^oL><9MkR3OA zV@TS7S)1lV73suL2KDHpPdq#Hj>W;_$MrHRfP|^i?mFnnyFh9X&7S*85E1$H{n4`z zcz@*uW9vUt*JS`x*UBp@#Pw=;hi(SiP5KSDllv(LdnW>ZvRY8Nd0&4Y0Cv`D07Yw`C->F*uVE)o{+?plxXTTqbV|FWqdcx+rhO)Aszxu z`&xIAq=u!5)XUi%_HOV|4?C|-p5uG`E07?Vvw;Nj*+12-L`|Vi9LmtJ;Yvi; zZ)b9=S1JL!eawEeiHR}_fxH4*vRjZ9hoJ{{Zl8Z;LzTrxq@zV`dy}4*eSuUQBx}73 zLZqQFjMvFGL)aB_^r>#Xn@=si{LAVl4o;w+$rL;N9rx39*~rIR zoPwj7zW1}W$d=8WwMz&ZkI!=;aWO{W-z6qv*ph;p50vzHI*G(@i0#&4i(55O+z|`$ zj%(f4AJG5)5r0&FHUY*Bkr?*T>{_>6(8wJ8WGwx)#Ju#v@-ov<_NO9MP}9G(Us6;D z9n6dpR=2TcPz^fSSW{b~I(AY~w}!I+LlS{jx%rlu@q#l|J*b;!=yC{bvJGFxqV&O- z@ZLW7;hg*~u{L>3#lpsc=3)@X-4gyV*IyeP;d! zcKQ`nY!cUt$T5Y*j?=hTv8c7nL3cjzuf$hCq2IznV8+=WIJ5L=8_gNZ#BPAo4RLWQ zI~b{9`Ovs4L5NHtG|LJxpd9OTmepMvR+O-zNxnsj#5G)e87al>aOiz1(X?A}@*SKK zYkab<9FstUTH;$0l#7lqrJ9M%(|6Ru5dY`jdeO*`oKb7FpM2!tW6N7LSe9m#(_Uiy?Kd($#x0pqm4x39?&iit1jtkj4>g0PL9Ab`LWviR4EP!8FkCNj`>8YT zYzq;&(at7$^9z~1S;u^#J-=`*wSfHR|5N0>+|GLDhZ8nn>DU7RYKbsow$FBHfkuAP-uR2SX;OyDn&{-pGlZ`fOC!(E8= zBXzg8+JOElvmq-`1y>2G2p$G02KRr9^u)?GsAMO%NvFEdVsSwAaR{TG5#jC?B=15o z{~Fm5_q)h`$bE+;E1!F`d{&r{Y6mf~JwLR}gnV8?-MYl|ODDOfB7@icNJdz{bStlq zAqH7II99(p2y)Ru@gn(EVK*Be|1>l5r-d9V@=qoU50E*XSTQXsE2_&mG`I0AAP<6m z#SPRwg%t-OLR7WiQatg-t;^cFSJJxc>M4d@2SLyO7I`JRL&>( zHHzTU&M2{C20$d8Dyl?qpwZ`9kum?b^7J!@6Suqk&;a(J5Twg54paj3|FFw;q|=6< z>TH`E?G8djCXp(0dl#u+T_poNd>hm1D^EKb|1ukAY+bgp->8Q)0C~VzXW+o6=;%2}nqnIz2s2wgWYo3RHm@ zC-;QeJtYW{hdga*{P539-GjYSrzDDM9ah(qcj0*1nPERwGU2MupGxc@{hXXB=;2Mo z(~mFxVLg_`uXeD8Olg*(uAz_%%n0LOi9}R`msG78&R02EAR74a?3PrR9|WSD3Tr7K*MuVC){ruL1*OYR&j*QsC_DNNc?ni*ela^ zA(Hi#PT*I9cFS;S*$|~hBFFK3P?N7uIf{xf3W5+}1WgZ*vSA)GaQp&hK%L7oQZ^j!F1wLbQ~m}fY;q`VANQ%i6;z~} z&4C6ICc>e-#MT&3?w-u`2;;)bEKl&xeJY-(HS#}?)=Ed)JNUV1qt#WMSejuUVRQc7 zang2hU2qL@nD5tv>c5RM_rh!AaE5kcpWRsYBT>a$UypbX&w2WPX2!QtD&@G<0? z!*NXg+1DbBka+XP9ug`LBBi7Rg;sA5@p|^jMA;y7FR+I7<)2IK5qnyKKA&@o6P^mZ z@?i;aEq7#>XV*4i;qS-@T1e%$`FQh#?2xEv;3KfhU~$BTf+Cus@H+(+WGacCQDfh%9<_pu2Bji zPbC5a5ox8P{C51lMI*1b>)pK5+h(^EVF%wKFHJ`8=1K+nC zhzOPkf4UZYx&w@e@nYMrVEYw_GT|Zh)`-PLl#xKyE8_jT+Hcjy9r}MZb)Bc#jYa>@SN;2X;Ku=m##sYDa|HQ&-{Xh7W>sw>9O5gm(;2LB zZHb4cEh*XA!>9HvDFVZ5>|(p75Z3}-1ZY^?mPutNW{Q?f61;0y&*LU4UbZ=~|L1Yj zpK+lnfX{MeV1UCJUFul$V~$8ae=5yjr*(lFt0cJrYJfIG@TN>CZa+O#hl2*)xR@`} z@Is+YZ zR_#y$zklZMBXhwIaRj&no30TpeQ`GUj5A03A%SERw730NNf;ea^Are?SbW@9qmLHe zt@?%gR#D#isK(0*#=Z*;o)9Qf_dNqkPxTN={;;VW)1)iyEoy5^*zCwu?c)9TJ!nN@ zpB^eqv=;JXiGNym9|ls__{ViyBO~1XZI_P>g&)DhkBJAE9YZ+c$n$S%-*qi9SMXTzoOe1{JS%i-wu0pBm4iae9`e2s>z;Uaq-FsPqHQO<`7aZ)k~ z?Lb=D25c6-IrtArgt>TUhNg#{B?tQ>9SCYok%CNG5n5PyQ!x>$qCabg^|7&u2Z~3t z!Pp+~qzo>GFfFr1iAS<+@!Pb)EcEsF^X@&B2n;lZ><;?-_x^5d8<2G3VE(Bs^P(79 zuBAmM!IFI9+lP%NEfk0%R*DNe&ZoiApZ=|lXS6hp+(E=o z6>Ls;mtgJfJX5T_Y3<;yi~cnPeQyB>5%bnghmXfSN=59)16h|5w5tY!n$Gl$##!uD zkZ(F0Y)=jlp!WTzlXQPOJTnBSN-4uG!*G;-UMDVmXRPI1F^h4Ljn*%z;Aqt__11pxi*4k*UhAoyAJvqjVzXoc;_y3DIcezQ&O9Hc z@c6sH!1-c#ONbDAF=-TlInPCyA+YY^w_FrYJpRz1|4BM_wOZ|m@3`+i z@{-@`h@BwtAmy_;Y?Bs>Yk+)-?>qq^QYrg&kJ)|BO>4z9ry(PO(oiO5NE>@P-%H`= zuroiM^z=VTHEStg&pJ{w(^%Qgfb^}wwn#CLL~z~2&e)AaNiXmFUEp(xM5en%_SLV3 zp^1;6-`)Q>H1@GngKyTej9NTS#RmJ~>;1bnWh^f0k23toO-F{AOjAxZD@&#~Q@MNh zVJI3ED#4*HYNa9#beAL~mz$=>U~3dJ+({}%8CID})f}syxeS)a5}$h~HRxAK zq4{iLxrLOQENk+hvMboLnXVtqC=TCm%qKs1{~p$~&^EmdyYx9onAN53VhhMe3$i^8 zLcx5ff##;gS$Q6X59l%b{lM{l&6$f9eSZka8R>xq@pBtQ?Ck{BdhC2a{y*X?pfGts z2V_?I*e@h(h=(e*oR+*Oxbhf^RbcsBQVj(`AAkQ-QLu^R31IQRA6{*Uz^ApcVebB{ zw-i{#yhij^m>^U7(_kQIlOIpj`CU0q=VC^NKG6jn9eRI9Bh^LdF)Z={k}C*aj4bNB z^go0kNZiZ+k>m-!I1raDSC+-#?_ig(-yFQAnQE>66Tx5S-_!eV@8rwsvwxYT^!;)} z#-m_qeLD=+1v<=TGGUjE5dV=zAwq)2;P(nTK9B%PxRb3UR8BX{bxljW35cBWfUtkhd?_Op}k+ou!D6us|T`fHOqJ z*Q}H4WpJeSu6~PD3&e*AIld^^bb;+NBEGZ#os;?3H?5j~XykW^)1MB}{f&4OyT`#0 z^NnHoFMT7Zq(`5cT=`SFA8+Ud;MY20V=C9tBBqhtT4-uzSqF3 z@BAoNilf!tphCt5;x2K(q4_0NVb>4qe7NDMg1LV^``93vv0vGHnm(h2^(szo%JE0+vSSif~Vw3-k2N-#Mcc->oOE&D9A?>&Hbko{D$`!t0? z08IWSf2$c6_;U47OnwKCFdlJJW#}=#cO@tG{=J-Y4K7pf1*e4x4n5znT~Dd5Wl2^U z!97GNn1Vd}Xr_9zU+nV+@FBaqzWs*7d-+C;*YG{CcaA6x@iGJc6N(ovX@`7W>P#_;6yjdt-I9L?RmVkK7gjFWyp7I_G6KL`KGPZ*}$U%d8T z^K?oLFhn)7RbwQ*kjD=EQ32}bd%J@MMVZ``cln~MAsEsMuRa-({YovE5$~!?e9UkC zeFzbHAUYXZK_`Fkc`z3=eMvmfwP*O=dmStam_ZZ_$Y&qZHTl;U`$7QnGvZ>yMl2U`>0RO19;GuTlq!5`|= z-YH-~${6cv{pJGK=ctEi@e1bI2ccc?@*Pdl06w7Y0%<)%-6J)rThGC{`72=YIcZL0 z`CROVVf~?u@32SdN=C(&={0B^%`=7=)3&ajlPaaKL7&4R)4TCuLjboNG!iq1cashG zAs7rGsb=G7@doNNi{twh#(~seKKe2{(wiIKqp^N&h(Fh0kB7Jdy;AOIZNivZb@wxN z0sSQh|LiN|=Y7GBpFgv{0K5X!T@GSKH*;WNq7PuecNX2WvIu>wXWwk(HGI~Xhw;~a zh3SSnf{c&M`R>p!B<&J}5RC&jk(;vw`IXtdG(G~vmorpzUYb2VMCUZYw>8dmwkH%9 zFP+}9s@jy``^a13U2==vJE&|B~U!s^gI&FImys_Hju7c1hH%&>BIKZs? z1r|DQT?>ViaB68dhZ3}58^E^>s=%_}Gef~M)_`!8rq>jnhn<@P)j7R`86)@To16I@ zPf)a31`bU+a)0P`>Q!%r@|i>mLr#>r`^}GL1zDtLA4x;)_ZRz80DMQ=j(x{kvR+83 zXDq<^uY;Tx_{xB5)ejn%eyGVRibi+*s#OJ=hdv+*V+$`hrcv2wDKa4l<;iN$cE+G^ z?Mwpj`NPtNYi~z=Rip9P133{!4jaYffhYUqDwI|A`}G?LNIRERE32z)M0is&(@uyI zn3r)1$0ALp^C;0RELEkxZW#I5hamKEt!5^#TN3QjB|Lb&{*1H8GX{}4B(=fnZo_NLJ#xI z&{spEvyi%iiYX{h7{vV>cDS;q$4fYOK1|uV%6H`|8Y3T51|2ePLT=XaU-~Q9)5yq< zddupl&pu+}h^80&vH^TlWQBYngfteSQ~5d)Fov*LV3MbM4|0c!$tg=4ywQ zCne}nd2}%npB4oJlf;2mHgf04;Z4~r4N_+`SUO@CM)C_LWTCCtn=qVC(Vl&h*5EJS zGD7y>MWq8b9|+S9EGq0Y5S)^2;(XScVb-By$mR#<8H}06;UmvpP;u?r(H--Nxtb6L z9V<8E+Ch6rw&Jz57@}@zf54+e#xt#;FVooDq-WcDSy){U)AsCKh}CFs-deLg&HcE8 z(!#gT5rUE8Ow+lg2950Mdm-?yGd+Zt!y+sN!I`|neCAB(YC(xjtwSYsP zL~yw*@-M!>Zx2(iU!hZtI6G%xa$^L7HV-8;^%k^>t&+B;f)G76KYy87hqyP+AgN;r zZKFtL3D|7yuJ~D5l50XA#siZF!A`NBeN@4oCNK6C1NiXZm-k3!Un@_#9HnGzDgQ!L zBIF8FfYfK~6X&P9uF`RE3RUX7N-O%X3;(GrztrSh(G)TBoDw``{uLLw%L36q-{0!l zfZs7?^@V249AZ1s_dV$m1-h`Y2tdUud!~M5S?pA1c2UG2;ik2|=>m zzKjt&#Y{-Bpbz>kpQ*tUx*vJ79!fa9=A2vn>t0GV-V5KlKUi6;9fSqBkiJ?oxC*fK z$A9M0#Y-f-IKEnd_^7D`$HQ@e2)y(HyZWZzdwVDAu1jJ!y%I5`gO^im|#-FY=9FGN?X{{5ftZ+xQI6u++^ziQZBv594EdkFVYc0a$O zu79g3b#eUY!{)4CD$Gucc1^U*$J4AkN@-#NJl&Ct7ShsMP^Kt}wcSVg+6CTI5@Vu+BQ5v)@jY+T z2xQf|AycI6qTmPUGs%Cvzwu3G*|F+-AidqhcSra(9DvWYXED=qlHJiA^#1ITS9vMq zG}WwN#jj-A*vFY5%@y~4Dl|dpT17>7-r_Q9#E9fMJ`n2)#}~)f2oPWCZtqE@&teiw zj|p$4sh*U8Z_y0uJ7u)=7$gzI{Re$m!lnj6sc(}jUk3!FV~(gSH<6(!eijfG^WYxI z=C=VJli5Bmm~qS@Mi-l?K*Y482nJQ7(*3$@3vT8|;nNjQ#AgWSCUg(onegc=lnW(x zX$ZFs-UUdg7Ng9J^zH6AvJ}rg1_D}%7yE_*d{#J+cxsH^q}1JBL#Bhdhayl`3H84c zh-n&Ve(sg$2I1fJdME6k;$&Ta)+QR~iPrwzk4QC^yz5BJ1tBIho&?Cx(khHIHl4#5 z$aDdCQh~4O8q3hdTfT5-;QVP?4#*HVt-yF)HJ{U2S6qZn=^Tp{9&5cR=#z|Il+o}A zO0Nm!v#;8{2;{{+XMls4?nowoq^0#^NuW$A#PEVh%O&nX2Mh_gcR#>d;|J&Vl<#1ADNO6!W;7Z?0 zB^$8-_wCTf`gyo^PjHbGj9@0|)4HEMm|cUAI3E-*T*lR~mTrQYv6K8^Z=5y(d{wVIafJ62uSDfl*CX{w8>(Ktg4=jt!(by>qS}$LI(Axxn&r_*OAY+@mZ*8ec zSjE-U)7y z90oe$uVJow-_>+Ba~w06pVl=^kF`E7b^=wc33FJXnX7QG8861X6NmlM1QRdZ)5Rjl z%2Pt9>&NfU^qe0Dt$g~6>*p*$enED)3qOV~MWMOlBUUb~rYNOKMVfjP;APM-dtUoh z7<`qHc4NoWGYQC+cIJ&sUY6kig(IenmDS;RJ2fzv#rUs&{_XxaT)A1D5}fP|O>#z5 zB9!*GXSHWo^eQzVx!ayT7XXJ7a8=Y-#lWGCqPGzhs`hPZhijlHu8vU*m!WEfh zcFo`P?kg^gW^rq5Z`QEVu{(Uv-f5w?{^R|PFC*8@m$hOS3eJ?eB%k~zfuh@4Sov7+ zNhcC8^J9GI`n^2!81KW9o?tr-?A;fkCI1B5bE=bt{+=au>E>&;r1h=;eOWB-`Iw!{`!_Uon`FRqGF(wg)Xw12UHU=u^g?gRYj; z7bzb`x(xNltQ#BlgwKJ<64WkhHBqda6L9B#_Cb7DYJ9P88^9Mov)Gq}nKiAtnO7^q zR&0waq37PDrbALNcAW(gECe?slyf`_)VwMwU0>2|_1^dQhouF_*D?t4z)Xgk@^$|^ zrS@-rA#0;UJ9l^axVV>l9*#;z?gG>{HPk$(?;Op8AAM1d5$kVhk^8=u+*Ngmxizm^ z9Wc)^u`*Ty`*>^w!N(i%KKqEdgxX&0+XL|RF}BtR8cm-~+YT1&ecDPfg!4N)HT7JK z?(aK3y^G3Czzeg&ZeICt;ZEB5pj-@wJ^gyCBGZXd0q?6jC~_#^e)E`Jq#Iq&c}j-H zpdOhM2vOJYNp{wdJ~PblDac2kWP97E)kyRzfmDL~^jp{;J@O+1;qNx1?Jn@x4}xMm zvjm@g3<~x;FZNvk_{264-P!FRJ|{wr61uD4n@ta5hGOQK>CGBX^@Ee|ZiggzPnh3f zsQA|pj^&Sb4KB@m`@P7;OI)m+j2x%fUwLgGIRnMsflHP86t+jBo-e%n=-|{d| zbGwZ_Jo*|Sm~84INpm$ooZd+1ut~=QpO0-galNJfC_AC21&<{n`s|}Bl)ihh?+UtQb8?JtnU%3_C|gn zpy{gZR`b8LI0Qj+^ zcys3up{nRtS{H=kGtR3gKFJwqYb_}$B=3+WAALf%K$kG0T`P#X@`)hB&bDFavBh{h zszV`p5fqXW-Mf_X&pzhJGvgQM_Y=TZl>5fIp(=GS@=Dj<6?z+21$k16!GQ!P25oJD zHw88UooqB7cx>+86k@aJD%nV%>T1cYK;_d^CoN5MiD3 z@P{!;teX9itMHxm1d%ocnjZ%Bpv?h%$)>ypjJNCyQD;A;?S61AWK^{F;|IyOxjbw< zZA&R-`sx`w6GgaSTC0Fzwnu4hK^;7{p4(_W4r@Hc?bErZ_NV>HO5?uR2L`Zo-BJ8K)i&;W*GKZKN0AsK_%JW+>r0e zOx4+JcEI*z+BSHU_LM87uoi+HZ>ecK`|1OfUNC(5GyDtycs&w)=#Ny@Q}?*t(8-Ud z;u<$DPdOw@H^O18besfYMR(pk>ngefI>`+_47ajqYe$AC=@g-OAZ|)rmL{a}r2zcg zkv`B@QkWuWQu~Crl$frkO*dVG6*GT{a$bJZ?9qpfVD%6!hT;9e=Z!d;xcaQfpr5o? zca8-94}PY)Zd}N8oo62uZokco^Me4$4`H?3?XCD~HKQGoG|Bphp1sjobJ5_`iMjR8 zl}7dMaFxp2s>;jhr9E`wx&6yirRqjCJ_gB)+6MdDthzBb^ndyN9e&!}Tv*3d)SdcT zc3GcK{3?UQH?pfK)9N+PcX--P`{5T_(5(hHbD?H>2&}<7<4W&b@2#`=O*iFty~C0c zlxMonKJJF07rZ|FSvunQ@9=YrhDWJiNJj?+1sEN=?r=ck1ZHlFI=ts6fp2n`|IqlEmM@N5W4}hgfx<9{bwHe zL2dPmYPZtnbV*gqaW119_BBQ>xjP0Hp52UQ4>EzQN^=>~}e^%0N0cS}FRNZ7;Pl2w*f z!fwkFig|{eoswG}T-NIR6lqkhJ~w{$5lQAizc@c6fc(%H@ZX5WjCvp(f42KvQW(lv z8=V9(F zI3I&SIP3Z=mpxwc>cYcSjN>=%2v37N0lufVKfw}xF?%ZFIwoiFL~cEKJ9au14qSNi z#as9vuCKU!5=$-r_+RU`4QqPQhIYU6jl8Y z%|~CgUnxh)rA?hQ2#vXLdep~0`(TU4L{%$Z=@bJDr-0pqv2Bt|pzrkgj+Bd{rlxIe z-ee;znF+zsfri@kV}7PWQJ3~dgoC1uN;5xxgk+9rQV+j29Ypm-sy8MOV+=X8e)dtL z*S~!20UyBkYC%udl3PN8FK+u2v=`My76lC-Jw2|8Lc2W*&9u!q8ASE2s7ASutM=(s zbDe*Fab`*%f8u%_sZ@dcl))t#K>HI(V0l%jC&G@9473)F8FPDLMh)bQmxKbX%dzz6 zOEf4IT^x77berH~U2u9$yT=jNS$k<79dYcCUIakd$a_KLG{0+I4p@wa?K@n0==Y>zmoWW8$=HuHD;L zoH||0;W!2G9o*zA_|s&HF%y4@&IC^9aJzsbJ^}f@T(wL4*n!=`dGmVXguQy(s^)+`3oh@Oa$>G_D{oqmm;`Rr4Lpm)i5+~W#36&m4lboI^$_nGe zVnDut-2M{JDJDzXCDq6tsuM8NB_pU}q^x2-2_jdqF)0CMnF2H zL_)fyJEa>Wq)Sq|ySqz}?rs6;ZV>K4@O)>^bMKws z$7JX==CrlQ^<_#lk8B7I1^?&mu@QeUf&d(R3P-kP9rNX{9hRq5MzEv5E#8w%k; z0P*!T@g~KOXJu@+YLzXw!e<8AIoHBs1leQZ*g+C1B}TE?7#_ zCPYvej$iPw5ZqpC_q_19h*W_e9x4HbhcIi%=-h@9)ezOu;!|I#8fUw_p`sxt`00_Y z>W@5HV3NH9NpXcc+UlP3;VQCXX{_NtuDME&BOcNoY9ZZ;0dHCyyit$MiDeT%`EIRH zMChgIZ+4w@zKKwxSWRL3V7k zj*s~xiy+YD$pz5-aEws`%O51R_TA4?ykc5|>O(-YwEgDo%Ej^s8SN$8t_)}6Px`7= zG{}F*>q7fUNPJFLlABaRWx1f@<}gKw2FUL??h_1{VqSWRLt9}QAFs6VaJXjC8Q(AE zGO$03yYnT5(&DJ1Uon%{#Z=k9U+3N)BNu_`C#nAYJeF4}KO^Y*>|+v+=LOow2jJso z_|Dd9lJ(7pj0@a>} z&3Hy0xM)4q;=Tvq`*@pfTYq2m%YwxftW9aR`EWE6@7k~=&sWes{VBf%gIK50G*+F# zi>opsOyNegjxi?wnOWds zfCefsaefK@gzanrzph45Wjld6IG@f*rfeUwXKOfNCQ^^-EA(M2CG;eF#g8a%g|frn z7r>W78)yqF9Z6E@W%THArpBPnz8cTtqPfPD#Pnx#%wX(eVFmYO$E1tB4Y-d1;yhl2 z32sq=WUhx=x8O2D5u(qtPi;#b_?t2l0DQ2jo@3;T>wAmagYlBQkeWehq~`pSXO2Hc z>*;s;y@M8|3bK^VohyHB{V-SXbTk|f2?3iXuv{Ozg-H3$?G3p485S&aa?r)J%KAB=J%-5KwI)&5xm-~l3DOld`kSOAURNfS)QH;^;jx^ zKvR-dL0y>_>(zL1RH)3$U!Tu?h9gAzf4Rw({^RlS?sA5bLL)i^eGS^xDCBzFiCT%~ zx1H(pr~1sl6L&;RhRZbvK}l=KzKruhe*89LfQ%wU+0E{Tt9U-?|Lo)VtOb1glL7F_ ztAH7q6(=9B26>}UGfMYRLUAuU3`waL7G+syRBP+cTF>TJ_CCaO!FRPY-{#u5tqh6y zvo~HoTG^?}a*;Lw)F*^Om4KoiAN(&#&i4oGl=tD9mEPd76P!|_B7ILjov*I#kt`k- z1q>pNGS&#^96!A7C+d)YHKle5*bke-L4`c~NG#i!fX+`Az^BcZfj@ex5ltd!VFw9K zML#6Jt2vsiWB4kHvkq0q{BP=#}WI_22uDbX|olCc#d8MQF`(%@fUNEQ5CW^?_n;RpW2_$ghsrsHhe}w zu_f$rD#Acqf}ciAveR2Fl3F1icP*Lx7vByh2@tC11`RZ)D5Iv1nS9P*X_hnJ?blPvC=E@!^hu8cP#<;T5yw$rrmU;l^ zpCH-vC$wYyri$a+1+9xsWUEML@O8M|J)tOBAy2*#uPx8!wl<8asnu2ptXW@K_0H6j z%znSJ7_z3^^x(9__?P}gBNr3s`ZNH@k6p`P3^$v+guCD1B#{l_dM|R%6KKR68iq(6^ zQk+IEVQZ&IB0<5G7+j$HPoBQ8=U5O`FL+yB3tT>m~EB|+hDKQ6f{94Q9xsEp-y6DR8Cb)`h5 z;+C5J`HlefzE%WDx{S;_Hw_#|njbLKvB6|gVoOo73cDWnzFCJ5sn5RnrCcCZcV8Zl zaQ?eGh}3`=Hp(@U+obJWy*J!qx`%lFo^UoHVe1jG;tGxvNA?22b`q?*FJH2ZeW6hs z{WViTj{l<1h6SM{l8rwv5P#tNr4wc3%|%S3bw#OQ+1xIq_Y^Bl`TYXzG&lm7U@se^v(9mi#j# zND0yYpy-zqswrthw;P}aRjYwCi!4$u^FS|lRlU;k2-F3hEwstP>;kB*J zLmoOu<%_R6ED(t9^QAn+|688FuZ6Xd8Y00OkU@-3NNRTvolT^LVJYxk1cq5tv_1qYea6Nq z#v*@pI_bU)ZI1U~00P(EYwhme`2H?_mZ8zg$+t@U6yP*xF$iYhK=bC>3m?41qq5dR zfATq4&h;Jf4z3dIuk_z8V7pv*;4Xh@N1ESyc!!dWVaOns_w2KdCxHUm*AC!AAZ1k3 z?Om?ZQZD9S)xB27VL)Rl1MjR;KNBx;ehZG~+9Ls86&td{8x7gzBUiAuE$+kL?Q>{w zOp$P@0w*d7;QK(|FtPt8M*)GBq(ofB3Rkvjjb6)2r8B%8UE;~d3jH&9hpPSSU_aI6 zU539_^(BNMcrvldAe`plr@HAruYzYEdjIrmpnVPizK=)@c8r02;Vy&$!qQ|?16YJ% zS1~mW!&U(W@ZI8HpntXshwjKZ&$R^iR@)Ph?QyV5d)lZ=ANNFynY9@)TLbucBXmx6CzIC#``^jrzxBCSi#5!ZB{kzzL1*na znC;Ifv(E~fWj9Y8KkNSF%QK5X_JupT`%%`S&6htkEw?X7!R0lWr1Z=3y(PLmYft5~ zkJ5F{7wG%~0rD$oxpZ=#KgJpV0kS99y%58EEgBnwZt~fmozKOeULv@^tD|!+!E-d* z)=mQffnEM9s4e-R>=;5S8+^!S?Zs<={1mpZl%S zKK&Pf*e48I9D?>CUI!*o61cthkl_5FaF1bC=5h$%hA1qI>{9pa<7P2f0ooS?;A7r( zhCEtDU=PhTu^KRhz0Z(ozcQf`;(RE`=xqU=ezg~0?e;N%K!yujnGMkeE=l<{quUsV z+1`z!L4BO}CXHwkRE`k;}W|zFWz)pQsm&({o9yPGUKDIyoGYu*EpeGJ{6L7O2 zmtE_f;iZJ;iqIcXyfEIaw`rIZQQ|c{=SMH}P7`Qf7(jltbiIx)7Q0n?*P>s;zVFGs zsQ^#A{Y3}4$29dAH+_;E5OnBxDFiKzVLI4>cHRSuy5h55rRI&(&m<=5j_wY)HysQA z)o;KXpKkM3Bx>G5`bSKBpLQg#1~OVl=%3Yz%gL`@Z&#G_2#Io-$|j~juR3F7iN-pp z%X}_wE*yu&h?}2%Amdg*^e->NJL-Rj_nuL6sU7*(l<X72ATw;G42+4a3}?Vpr?}8E7y`uSzdc7oY7jzfHQJYH z)6$TC&y|Z)apgzFESvgg_L8pz=9N&@=0U+&?tafQU*UowjfYF2ri$^#$mgqco|k0H zGY`XK4EU4D;Q;YVEap!w zG8}FEBz-E+x2<+mixP>yhJ(I*&CLmAZ@+>P(OMWMd$mq_zwyXNOV{<%y;w>*0$rXl z0KU}KJFI!cJ5J~@1X-`vSxlwhYitQj2M5Z($>sgOe40(F$>csi`CMM;$Cg<+)IH=0 zLs?04dmk*ZOK+5e(l-l`A8V0Q%qw>9A6-EaRP(cXi?~jZUkOYot?g#+1D||($wdJe z?w|=bHZiL7hRJkR;r$&G3rLPDG z1(-y!pc`ZQi^A}TI9M@YzWJWrBUXg|v+_+z*r2?AT{uprgTp`PeI&8&d<+{C+KX}V zK>>WShYUNAKeawp2T3Kx`q&BH#+v4FJ>Y1dF7}H(`TRM9v4oru1qR@6IWXW!%vPM1 zkH0qw@z+B}<`&Xe!~cBog~w+B-+fjBEM6CXu0oAkcvYEn97FeQHuK)2esky>UN%vU zq#PEEA1K%Hca`Yqc!5iFxkW^E(FT-wqzt}yvcuwN8VgLpIyWc)KAG`}pb$L{Ur=U> znl#O^qjQFCQ_cCB4k)nDkx%saWj`H)HvSx zg!iAL*I3`6UGa1HUJI1z*%C8UTg>D8Mk(xX7IG1OYUIzR=II}O_Q6<;Cj(udNdUfP zEqLpr3U|J-UrM3>`D z`NM0Urg)l=T0y47*cJ2BfzgAlPk<}08oJ1Q-cmqd3?kj-jW%vZ-LZ-mzD7pz+ZBXu zor>5?K^<3^e|>+SZjI2{N;bXhabMSQD}*ddIf0&HiBg;1Pvs-eEj`sINl+f?c?7zC zYXc9B6|6=RGs}SOCHWeP%m_`KV|Z)q>#1iSnuHAS!ym(chd^=go3Hi2j%iEH6bAmPdh!jAzzJIoRjpg z`f_|;y9v4e7`ELxRj4+vx%d~u*GSE^ijitQyh)^3-Y?c{D73ib1MppWei@HoL<+A# zVs+bzl;^H>mBsuZT!bN2-}m9kx3|X;Q9XFn4c6#ns@Jf9v=bV)jztGiGk_*(jT|7^ z!9DlvqjM;%1KO7c;1jvyM8k%<6XhkRRfQTPK}MQ&-;Dp$mwApMB)rjKe_tasYf7 zK@?hQjH)wSC_~v*R6g0&$`p=YCtD68b3#FWHNd`GEvjXD&%1XZ(EGiiabEzg0R2^% z);vb3=TQn{E+Zx2-b0=Lox40C`8&5=3GScVMaooq>7G9ggz@52^);V-YbDO7eaG)m zr8C2*9FqrF2$7^pa=}a6?6nTQTy!KOiLXEV&_8V30qrXU@Xc>!j&vz+GtV`y|7?|v zlv*Z`D3o+sL%89!ZCVS5ldo88p%p`}LcIZNA@^%*aDj88@=>G> zC6Zv7AYDxKNlwh>vu|cG7>MrW<>_b+;OU52LI3si_dFf(V62GAi-3~fB+OyursLw> zPLbf$j%{~Q?^jp9^q*2Wq6zLfy`Hod%(DqcPnl}1<8Xlq8xIf#s82fBM98gEeiR0_ zwfxV!h|C=FeHmN(Gd1_cYvrqA(ds4dg1t7z%AM$|C9`V~ z`L~{Zl?6<|pDmaI$nO!1U7^D&bU8&v-gcbzbsz+Z3A?cua#|7>uHx75By1j{@DU6T zZ)UV`E86q<8zQ3bNs~ra+Z)3jJnBo0yS@MV{tgdZR<^67@|d}w8n15_6=yhg?ngR* zv8f5Qeg%2@5fFS;4Q<@Jekg72_%IX@YopjA4gtb-6G21q*C74~N|fF&zAQHzAf{(8 zPe&yG9Ui2;!WJJfdx_qH(+KCxR;UV0Z-+q@xlI-e@7oCvNcXHRPJ%aInR%Wh58M>efk4&g;#zmVx+k88 ziX%oZc$_Ce`ktwxVje+aF=fQweGi)DCCU5z+`)IO+t2acy4C={wyW`9UbV-@eh>+_ z9_axB&rc@4ix{#Z407}mbf)8<$uyN^*I$0q({n2h5L{bytmyx!dZS~2#1g#Y5dEpw z-F|1f74=`<-_g&v#;T*3)sG#HoNn6mO{#G({e)aK1#@nas^#<(@4;2z1DW?`=||(p za2Ngu(${(B!+r#x`E%GEtK~^GHsB7Qd4wN=|B3IPUjSxpq5+^fd3i{FjA%?<(Zu<4#{ug%_8CAs+sjTHyS^J`3z0@@(8&I6j*OplStz7`?UXu%y+bKQRd z@Vy+Bf+jEy7lW+9Z2sSDJJ6zKSFdP^SkU8vJjp=`*5bD@qzX=0r)(2V5+^Hv|r!Y$~$h@zlnx$mX}&#rq|dp zxFifZI0!+%7@HBD%Oi6FN6H7=mD=!$*}Y@=%F51an_l6qLb?r*AI!tX0Hm9x5rK)W z`GXmIoo&XgLwU;>f6C`CtJ4P!nlEYnpccXi!;N8sgZM6Nw2vQ64 z){_+cYt(8(ea*CLDJq!_c<1S?t;_NS;8(ixem7;!NBiLzrvPke)}(7vuN((A{ns!>fXb7%GSUgzoH z38P285}{`KAj!}F=J&Vvl)1X|!2RhVobdvvP#)4llDez)TZ z=gmCED5<5wCxwgG|L0>#P&YAE$O)k!*P~XoFTR}tUf{bI!~b?KvRDj!tv&Ur8KH;h z0%6^wJ8yzuZXz+!@=VXgHUbG}Et!-WNJXci8lfXX7puLw&pjO!Q{O6qu=(WZRf3<~ z{LA~>z1)Y+L}_~Aamhe-`i)U0vGyXQ@uZuT?d^xQWj)2mK|8(HY>-OjfU`5^f_!0|CFfsU^gAU;%j5AKrrY6&IGl3xU_<3GP!?O+&D ztkx9FMj0X-hQt`CYCgPON(LK~`%DP0C6#}LNtn|LQ0PCb^FJ5&$gJEk1TCNyhH zQ0uFeUGy;US;8?>L&0+%r^zJybM6|aQWuGVKujg5N0hoU!=BJngex>%h^|GjRMWRy zHkGRU;o0X(9s6ZDVrjvr-Cl}v(2-cP~faNC{qieIytT>voAhUqyQkw z^Tme?@N65#G$%mNO>lgWixS?iVk35tANN==z;$37jm-;cP^GS&)ji{6lo08H2E%)3 zCx&!7gBy3%g_Kyv;sI*pxzZ2d+X$ViUBi_oS?p+5iK0h+gU2e5gmYxYoIu^G_~gT# z_I($9#v3uh8Ezwo9h$z2y;@!N`<<*5h30NY7N3zFX!xHSF{#}UD}b)gUV!>UU!Em& zb@nHtzBI@GI1Hz4%Qdv`TI!kY)LI}xq!66)3v>^uS;0cCzF&}|CN>jK4RQd4e4)}k z6fZCxZP$L|U*F&ErBf+Xm=+U1dfYR>;u;@goV?m&=n(!x6aH=ZpHCP=30ZDOneGE2w@B?<9*KcC=!Ifq3>+YuW&@w)8SNqx*07vOI5y2!g@6Vc(QO zJ3mpm)4I#Fo(qcgRFQogzy9Ok!_SFgON zCI038?Or&XT}2jAzKOgW6}A!0hI_@tDrJv#UJ)UFk!AK2-2>Oc5oqg|N7MBeTF0y9^foU%TB)!mpyL|^h;M$ix(&r$MZ(J6Obg1zpP7RCJ!a$; zT86lx6&3ZV4y0GydJvD)EOkAU4IehKq?~2hy^WG38cGd}y#EfL9N=p!@dYwQhuOMq z-aYvp@uRRu$JH5mVXzb*Rs8~(o_t25ExPAPdb8hLXkYn^2wnCnuvscX6jtCMS*DKW zeyewZeU1;@!m$r%-w1%uV%K^Cb%}m8AFN);hjNJe6(RvalgBweQB(vw7-ktW73jpc ztx4AM)cau=oMvRM9}?&VB&g|D@y&GxAURWjv(I)>EKlvop#lXNbaLD8K|9)=pglKBTbb9aEQ5dcQSI%W0qq+F z@FDYj--|GqK8$#1V1ZnB$eP1EJ2r}z3KwALTfp1XaX0y3r7EUq=i|c0Uqk5bI41=Y zd)cM%joWl)63wM=jqKn0{M-EC$FJPCh*BWDB2==q0^T)pZ)>f_f*`W2@YFm!2*(Y6B4Do;Wy)-|7PpJMLz!nHc zVM;u91APVa8d5bVQ+&lPnQYKru4%4LBer>t*-Ag9;tLVG4p*@GoYq}1O|YlY{dZaz zRJ?TX_YT?r^8PlzSmAxhe3oO%@zh!sh+^o+(PRk0ZPnuO4I(+IC*BpbvYx{>hDN|S z0n>^rr$EfR2BtjQu*%_+ri#D|@M{^=XCC2O_3QsT?`3qD0EiDH)lf;8B{9<6E8mCZ z5|oCuf|<9GA>@#P>QF9dny|z%e;Qsz7H+#rogEhxyF1_n<9gGuoxiJLLQP5<9I^ty zH}~q>fglOUo0?fGYpx`cdyrs5BjQFDRn9n{UfyqIjeSnYd-Ssoh7LJ>t6CjPA1yd;>h}aL`O7FZP!6GvX z!7}4y2{|`W{1ky0I%1A=Vi#p0ZxN8A(7fpUp30NU2%LVA4Z!!nwtm*M0K!gGPbO}_ zljIaJ7#YHeXt)`TM@0GL!<3d$SlZW*u+PSjq_BtHZMw{7&6Mk6x9lEWpVx{Zvch`y zdBKANQJ#NiF97+OK<(8d1=#)b5dLx2KAr2P0FG|;=a0@CZ5x;yxQF%McW-8UZ2q}Y z2aR^!f8w=N*?6Ws$;d4qIBEMbq2h{sAAm3KTZu%M8;{5vq-e9ax7q2ptNMz*eEdSU z=Qn>|DyBQf$b;9_CH&2-e|`XZ+>@3u&MsinLkA6t)Kk33kuKY zf3b>(DftsW>}T=+ZjAify+mj&&DDSF^gCm}LHJ=jMX4I%5pv6=o9JZ+f%udk{}9T9 zlAm1G&74O7K7$L4$1aLAMg(*+23nwkMP9lTGvTxE)vJGA`ujgWy#If7FB6&EwN0>e zDEAT!D6FX=ov7k#a!cNXGRejNd_uY=WYjbhHOgb2m4al+Inud~_!GXyruxIj-sAKN zI>-14&hmfb`^)ne3gPKd%Y2-iE1}7($S1UD{L=XgGp21bLMii!XZ%KD+O+p~ao#V1 ztX9dK`I^9yK}#DD9x36;Ox7=>mba0sL zJwiI@D<7S3LSF5;n-kB&+O_4T%@H0@c`uMJDq=&H)AAJ~^Ca+5s$7w(h6pS0t9(Hw z9+AhtyuZCC{Oz#jB>9@418ZtlMAYo%C{!2;odOkTp)9(^6VJ-%-hMyr6B^jS$EgJY^wrg0&@8t%*hN8)=95Im7nGyA>*)Rzdl2rp`g5X_BZ*0H4#) zMwiMir&$V9etg@;oH!6<+e94^H>Ib_qErzy$y4QX=xIa<`roe5Wzhchq!*LLl&Fgolm}G zP`at0`;Z;1#vyYouiWF$yEr9PnXvp#1HN36vHH-50%mc`>MgTZ$ z(=Ak1dZy+ehy8Wu#f9)vSk;B?@++J~4@$uXR-PRX(#$DQ@(*DX)joh5n`T%$T&LXG z+AL}2+HtZch@-G$h#gB;N4#CX?xQu0*u|ud!!MRf0)E0U3f=K#y>`k`($0U?d zX9vhc2yme!5AtRzWzug3P}Osu+mfLrA7s)d1~JaB zXktCH#z{U|ur-{6-TZKuXmPMTww zw{dml^bfX#`vQ$B{&*Hmb6Yk+S*ehFI&h4@r#rA}mf!DKzh$;MOpkFbKwFgZp%h1O zq~z$0OHQ!WzrMf2I~mkh39dv)>~~)v<#1)^-tQ;|L1(7)GHcWe{&{Ir6TPT})kO|Y zSHE09y3+&?P2=F9AdKQ8^{j6>|9&JP4d=7Z3ZDarjlY-So$tTAUL%%~$86Fa6RubJ znwODdp4Z{VHHdkW)x^`HTOyl=nXVBtk!i8TNJEqoLzjk17br&H;uE*L86d(EA#n_w z|MLD0?{gvem$O+{bp1X~cTQu?u1Op}2H{EI?0QpD{~TL-JMik7TV)U8!Gu*-ej$u` zhK!`<#Djcc!Y~~}XBE3Q>CH2bHI)bW;T;MfK0IM!8A#FCqeXI~;q9J#DSi;JMvLY! z2|3YIQxeSg<_yY44i+u5=Mbjo z?sTFWlE!ZtNv$fKc0ttpOGwL}%2NblaN24<0Um#9G|+gNb}|(fJNWqV%Vwl>j_3L? zQF{^3vkyODGz#eQgazWfo2%MNgwyp0ygv4bHEFiqMgoCnAIp*16wp3I z0N6s3$t#zl&>*_1(4#( zEBgdrsa#$4g9^Aelkxz3-T3d-mhg9ti8@(ZC}5Xd3;Q$Nnj<;7#ir%{?BRjosm@qu zM`(SbJB%1w7(5A6z33Tn&owlIl86{c!LcV0e)iF)QiTKU!vOGoZ!u;wzJ@Xa%Om14 z{dx2HH(Yv7tI8Bta0A2Q{=Xy0iWOb>(Jjy;RMMBb5Qc1g!mBak>b}qJa4=l7Y z(&)e}OGq|*C)Z3y%zpdkkdBEFh61gtJ1m(POE|6V05O#Ri#v58$H?85HsD(wa{DN+ zjjKdCcN51lvr!SpS`lRPMmCreyWzQHqQ2Eu5{|$eChXG2zuRm``6qfTTpOLR~D3;Vb1SA>q48z!CjUbfZry(z-7m%Cqy9K=7_MtB$#I19@> z`_2@3fjCz8GCZjLcX&Xl6xGaA^cimL)<3zx3knZN5!4ess_rG+mSsk@Qq7$jq9%hx z944hHOxH6unXDrCbw=5CLB|%fCHZsK*yj|W`4O2j71R_7S|SjjWYUKuDt6x(W`(!- zA}L-saX#@*v)}FdY&+JM{NV2)18t~z7}@~EW2E%XF^bR~i5G-plYQoq2{W+)U7q*= z@sXZ7DLVLeruS3tH%FYS#<>LE*!hX7*JE65UEHa0o|e(;VA(KBy(N6hfO`Xxbai~k zuGm@>em851*7uGP^?!%v|2Dt=$MbvQ=+BL&RgDs5iE-uIzk01X8gE7=m&HFn`E+pv zu;|F;0&1kbIdq0HVRRRqmC_M2NGKWyYgbkjj`k})`)E*Dse$$p0{He51=sOLF@_ym zxCVR4$o7@X_a~O-(GzjL1=sTr5f<7-HS?wD7X!nUCl5r-Wgy z;l}iT^ZQ$##LN_AG!{y zdJu8bT359V(hrS_!mve;Vc~$I_UwBvfRFKi_q~*-=6}l*WV#6jd-RC-gCoTDPmNE^ z`l#M=gbp`bno4)~5;Y;7I+5(MhFAAJP=&tnPBVchqSJ3TDK40{6Vb?SRNeOi{^k9R zk9~gu13b4}v*KrWkFu;#hEP`R)EoF77pXG{->3K-9~(dx z5VMS9nnuPMX*V{HiH4y*NI1mc)`PqfsN`|W&-BD%h6p+@^|@35#5a>cp3Rj<<6ihc$aco!afq;T z1CHyfJ*rWL)v#a?y!u4$q!TLfXTGis$4rbyOj?VXD(hI+Uce8D5)xjD5>F2C_x7x< zgw-zG&ehF{DBUh998|u6e&W%(2+G&&S&WZWu{raEXK$t+t9~zUGuUxyI~7ERPQ!k0 z_{?Ky@&W$YhzlUT#8}l^K^QobsUv=)AAT13}-iF}>&v&SOBS$kD4Ki}++Te4q zA$sXqYf?$dV322_Lr*)Vb55ke53y_Y{*CYN=)kXI09xvk)7ky8`h87N>F>$v*ITv! zOw)0yu}hwOpFp*TK||g&fj0?sM-b->*kc*2hvwxLmab;0TlzPK)*3zgh|XMri0`F$ zc>~}R;Yu;QuQtTv-%H+*qtTPBnYegsaS$@mqIvph4Qx+lH^iNmO%a9>4Xt@g^Ve%+ z{}Zo7n}g}K(bWAYaQtOi0G~wVZx{xnCJAJ#S>z(anUvnwtOTu0b+0+UC;r*D6$dBX zr;0}q`7*P$(#K9CsDJofa`Tm#D>&6`J-_|p`kKkJkE5*L8tCRH4&c)sb8uI#IMP_r zT~EA60HLO~xL2I4s4t32h>(Jol-)gOzqjF%_-)m)sN0S=^q^cucC^f$ynqsUU44Sr ziRuI3b8u49M%EJXE8*N4gtQu+i7#c1UE3ObB{^4Z`IH|csDvH)`?OKyKD`6N0^@q5 z95;fxLdbRPb=`dbn+MQw^JgFD6{sZ8K4}0S9|^i7F?NNPDVyqvVXt5>Ck(|WOg@$% zdsca6>%lE^EB~<|esJqg?h&%=>PR$&$~z|k#D&CrP+DCTLb_alXRfzBuem97!--NO zaqO4#TR#6>@c%|k$7{M;l6Las%acJ=rY&0fe1_DyXEC{=^4T|LY1zyOw~H7-VNhAy z#?|uKheMTD3baoKz^6xuBbY(!tMJI{V(Jw$$7hBrDfd8sUQQ#a*0{9q{?QOjkFXMN z6TRe%(pywn^|FI?+XuYgrzDwMO~mEa?@a;nTf8S~76TD2itjphT5k%COW-CVPc}6N z3E%Y|c=B23{wNbB!spn|YRjf)AY@p(lY_mRo#t?JWZW6b7FV6JdiLEI_W-}Niv(~i ztN-Zq%V?tBb#uaZ1?j8@NQFy$@1P|23NFpAQc(%V{mjLV8l`v9b}EQ9mu(wKw_$0m z1|WH&RM*G&o}>I^|GSUx@8}+j6jHB&`)RYPHQ4|PwG-T}UxFjZZzju-4)f1_OEjp; zrL|&4ku9SKT)Qq0Bdk^^=f>~fk+I2%9!Eews@PgT`(lYVfWHn?{=dTm{$O@BZ}bdf z??DPAi=KhlzHv)=tHPbVL^5`gd6WFMP60?WHTMo|_M@p$p^n*PdoxB-{_APp?=fi3 zgpOxm0P&fv5|c$6#`D$5l7JdlhAi^LJM%iL=-w-Qc>J?3U1*x7_9X!7-i`i{h~ws~ zTKbapNM#Fs&l{K=N@5urg(=%-9)9N;@RKuHfb#q?5~d^pDrq?}ANU%TD3|G;y$;Ph zy53|oj;>d=+AdeEPppavE%H}ArMQ|0hu2Mx;jf7vDqcz7YJq>g=XYNU;FEOiPHui3 zZ@(0ON}01piX;0wNa46-gp#*;=g-o_Jk(@hV=mK{aQ?h%L2-!bTe^O1q=3BGgTg+q zJ=l-NdydaOQs`lJpqt+Z03Tc z?b878ftri?jbx_7T;e46C-b342B_^Nk*{w3`r?_B`HE!u1C5wE`uEJ(T3vg(y28oU zMy8R(`lBN+{(#BN0P}YlfEO0T$^Gi;E79T->ANXP=D{x6SZ5J_^kpeMV^#d~#^#*f zjX6cs!tz_P(*)|%*ZgI!W4004WD8PrAny~X?%j{wUg~p6`VnZK7Jx5lo-(yd{Z?2D z^-7#VZVKtQ98cswA66R?sG4D09AO5*pU?b_4`yR(L-}hH4P2lZsqNIne}LdX@n(f_ zs{+{*AU__;*zqe^qG6U@y<6EIO$2tj8n5cf4+XG9q34cg44Cz zzx2ZSJj`a81*=KO7$j&K)$H}``#Jg^i0>4?Okb`5-YDL`i$W2nXV`jo_c?`vB+(!G zF@>3VYzO;_fiqjVI6u!4sr4bVVYmZ3QJp&5cpkq5obWr;8@V0|QpT07?*o9x2D@yr zKDY0h$=Xcd!%u2mctMOce%M)kjm>v(P5e}!rd~5r%TCeq>`u{p+=85|9|(*DT}-fh z-A_?dD+84*7`&f-uU?rb0G*#cKz=>Zy=Tgn%43i33z6kH2|sRixFHd^AvlpVRCaH2 zV%Ydwmb+Xqw#1ucNT{kG50xnRoV7G_z9}+p$IVcw+&Kcs?{?MW6XykTNN-^0i2-ti!Y7p z4e+Oue*r8`q+>Bo{*0T6(_zn^J@Z-(#E9k=^(-5`tJ{EjJT!gZJi$?VFJlob-l42h zlYP^82Hn~+vYNOvWT9^|2#Y}Uzk@G-r`NHc1F-Bc%B!`jyN$eWI4+duwX4HdH%D2m zwf>yz=|~_PoaNS-KN`3#VPC7r+!YViuc{Z$sNVc$rje%_E#mi_AE+1WIneoe0OY4` zL3ov`l9j*Z?RqbrF8pDv$*y^Z7hi}zz!WB9KBluyVFnagc;L)WAxP3_XrZ4ZnZ0T& zkD@=zvvn<8D-rOORCBf8^OI#OefdV2g6#Ph*CLdJ&Pb>SQ3Yoo%%AELtk$_XPu~1^ z`GI}qY<(yYw14UmLOvE|5c`C5@%FKA#Q)jH^>xS#XrDiTPf>V{2Gj*U5x$mnRF1rx zip52nsPAx^lcbIDVT(%|+%B5UH7EEh`LHFcEHDh6C(ED<1HgO}MQV8Fd7E`p zuHki^#UG(aA(;c8eF+fG!0${0Zml@>hF_^8&RAhhU0a>mX_h#GmZ@jD>%0w&7`-4) zg@f4F)r71!Y2e%_UH5a8{e*pBW_!V*Osz|*_>Lw_R_uS%v%mFepV2m=RfV1wp&=~w zPN~Qh>bD>ziu8Nd#;VG>Cm-)j%-W#kTm; zJp1M^7=c)PdFemp0j8hl#bRWuoS=a%byCDinZi}+gqrLMD5kwr+EO z^FUyGf*Qt9apiI(aZ1kieeCCJyg%tmeK^IW3Ko+QifU9GkZmw?DzR zB(7uhf}9+KD(h}>jwThLXQq)DjqpqRjg|}__3XovZv_6Ou|NRd6#T^5D5UzYeLZ}N z%tcOgx@5?W&^}@3MTxr6a3jS_=zAz@n~EW1i~ND*J^oqMinufT3>(63OOeD)UADL9 z0KOL4I5hp`q@;@9?UoGEkS6&HQG2fV$3Y~caEDL%CFc+gv)dhjU1-10&E{Q28EyH} z__>?isF+c7hw%r&E=tU^kKQyJ`0Jp<0DNQ$tY`!lY3-^Xn$_wo-{nWHcYiyM(_<4V zswCRecjA0y3nRn?H@h^wM{gbZ$+1;tKr}4#Izmo?`1EHnk1R5P&k|echpr_uI_l#9 zu_eP=(;K*{xmV~ql1)3`q@R3e40GlVOEw=azopTWd6Ou2!mmYK$8_$C+ZXlBH*<78 z#6J7J(qjX$HTKf}Z~=TgBR-6E9A~8bWb9v1f>=E@I!7$ee13;72bC(BN_^8)Cp#F| zsQSd!l`Qd--ud1wvrd)QQ{f}5Ch14)&QHCN0KNsAC>Nsnv(}@-0Wh_e`$`us%$x6A zUAs;atb8YT`;$%SGZL%N?g@L%J}AO@(~k6trg&aew!db*y`MXphL_O-+wn{qj%UiLH?2$N0> zoqV5*FQ=6ssgI0W%Pj-&=?AfVmx0WFw>g_0lSpeK;+q$hqi_d_p-P+nXL+#fQ<%t< z!nd}cK9&eyt0+;6#6GEIYBXgJZJAVjw1}dNOnmm?%qUC%?TZHRdH1!Kh?{-y9i<*g znZW)9apusT=<6KugS;s}Be1lXF7>9fHcyNc0$Ccts%6V>u)9b7=wn?)3v4UwHz6k- zz#FB&Swu(ltNV(tbN%ss-_?zD!cODCDUN?-O-%NA%8v%K3+C6U(k0=cI%pUE1K+wr z!w$%Bd`G+ z*zaNioa7*G?GwRSfp&Y7qA}PG=&DRdO0{=yJSq-z9Jrc0!c^i}0rKlvu!59AF{z4z zk7{9aB7$M$DYU0{x|r#NT#OcV&<>pMbW8z5_q6HQDHiojPMF)PQWD?a;C z@CNkDpZSZ7vMrQ7VZoN%!DlKdey5~>RLHU(^}r3I0yFWCK^4<)vz~p-QgWO?`!WE0 z_`du8y78Q5x{aSHTURraarrOJWwI@kJ047u>*U$Uz#1AeP&e?r0hcYR4JHTe<-RyZO& z+fDj|P0H|Y4AM48%NfEBqjBfSYe?S$Y~LAcX>C75)QZoMlh$%pnnM>!D z-JxEMpRB!E^;)@QH+A|3Y^5z5sv6jnFTa9Cjl)X7cn(8{L1Lh@#CqdrAG@W?$cO3& zP(;_&IhdRm-vrwn(Dhje;B%SAZ$YY`Fqac3@#{aLg{j->pgv5olX)}j1YUu4d6v?_ zUO{IE^J!;u%W%^%DtRt<9c7#cc@%Zleb20T?+PG4>_qznJ81;5xzstbOrpTn(i8VP zC<%nGt|CAF%+Cm#2%*B9?j!4xao4i?XhU^Agyfa-%3fQ%72U(ud&jn!_v`~5BaQ*u zR|?>p*gX|$l~obgUmw%1UD*9j*8esK8#x(qLX{nw;SGV15lTK$$jx~4PVz^hb)<4x z<4|2vYjHZQvZXrIJn!pH0N;432=c+)JCNEfIC+TQI1{6!C0XEw_;XSi^M5vPry)JH ziVOI)v2+IokYuFFM7+-JkiEMF3Sdh$yP>K_E#)t5NKnrlkOY|}aWs>CSmAq*q1Tli8{@&0y#@BiWKu7k4L-nik@B`qD&A>G}b(w)*F z-6h@KptN)eNJ&eJgwjZN2+|?>h_~mQnctrGndg3;;ZJAy@LhZDwO3qA*^9sDv3;uJ zkTaDf?*vHzsEFG3D~D^#_t z`;JZ+y1iLpSn^OH8^y~0>W2*CnvIVg;>VQ{JtgCHOY`|-g|hfYZBNeA*JolPjLB^k zU&r$Ps|fbb^JjmXWMMW7kuscMa2fx>9VaHQ>pfNmdY2l_@}I4BUl8s_4@2%PHJ%s3 z{FJ3RGsD4lni7~ZIoHSRZXDM$o2v%-lA7OxF+Kmc|D*?e|J?_Bq*1LUia{{#Ke2Qp z&~=rZri6Q57GouN+dz;c8%1*TDk+?j)}D* z7?#x>;Q|Fzz2oyi9=Li92$F>sOml3BtipZRo5ucSDg1A0RscS^y5TGWT68}Geu)Ib zuchezZd9VO0;PITX@k9wzPQ{Di%dR}52tz#x2k@%4CYg~v0XTV5q0QJ()4YeOVafq zAN@~F@Rx6C0lsfD+A9{Cie$1U8PySmQ@5ylW&+8+lUGOtkUkuzPcVDPE#fla-@y=v zG;MRdQe*9h?z)=!^b>8P_*K^$D$CE2(LlWvG$`|KUkhRV~c3yo9fccLk}s} zpYh9iS$+1~6z-5;@np0X;@UjeCwNbGPgrZ|?cNwypKBWT{q+e4+k*do2aZ3>X$-Q- z@3dgA%~s85RAhS@_V~m!c@ckD8VXTr1e+_UkJcif z-6UYmw!SO2ooLxHavc4#Z@<)_hU}r>@S9&FZfpv~t8;p(pjB!-7hAEfr`*83gN?G$ z5b*Tob=NAy>&?$1_|S1;E@m0_*wDp8?jC(ju1xo;UxK!$&}vLkP6kW4jRV$C_oaKK z*}HwGHx>3=nm|4)rd04ZpV0$+SF|Hk3a@C3jx`>&cO2>-!Xx#eHMR)1Tr3YIsO+|S5N*7tvkb9J7kPoh~ z%^U3eIsm@1pY|EDZAlpU6ma&TA7Dghp^N8cQ)wrR!taAC%sZkfQehTJVI@LDu*uEZsPb_Z6bS1p8 zs!L~41|5f(yj+O*m2K1O;px0V7R$H6%~UU;8h>AqkoYw=_wG1^f#U`T;&$nbNX#kvVs>0q;5 zR39kXIn>4SrB3$P`A&jf8)3s3Wf|o*b<-B>sg?-@*dV{mZ`z7MqG7=N?#^VYm(|ja zYfIpkNl|!gr*BN9s|faR6-ng!9(`*gadg%(lqj5LPt>8DTbr+1N59y}UrgYVIIX)2 z>SoLIgM3izB45DHZxG-cC5A3?Zf_bxp>-7ZD4AYFA|cSNn4PM|QZ30BCMGE4*m+i^ z!dQU2tVl;tW>ly`?zDqu8Ih^FeZ)e1ophe_Z+?%1%g3_~f@l0X>cI|%68WA?k-d?|*qu{`c#) zcK-L)h#ANnNmI7NH1+6N4;W9s&F2B9{NYR9&ki-Db4`89N;IUfc(4dDYP};~THxOG zo;}Hgd4g@7$mirt zs@;HFclAlpUc#PT(YoM5PC%wb@q1i+$yoi&-~L=<@XzX>RXh5Us*NL_i%g3Ucg6O> z`c;^i9VASQlAjq1S>K=|#~8>*h2QxOY~L2ZhX>Uyk~-F%?;{-aY(oO-1oLOwr27~a z635yH&o5%T;+0a<+^(Ydi>^`a+&jLkFx%9hUL@mnHVJcWKnKCWyanWEjhN%cqE50q zh!;Ha(aR-U(?#Y2(!e|iax(hQ!LdSvmXIYOFHd&#*I|tK)b5XG%_j&>?D4wp?W|`ng;%L{1YdBuNsrcM@m*`le!rz|QX& z;G=n+J57!b8R6N{2~GPd`gKi$VMKwcQuE$^eZG=}J6Wg*%J&euWg7`!Y=>W4GOGm( zn);sVcPH`+(lfP^<-n4IpGvbn=P8LJyn23FnyI2LUxH=U^sQlYLfN$XPrZ4#SW88# zG|F#oiTOv*`1%;(8(F1~2OaF-G87rS92G5|&Vzhd!gthQ`%VD9%N@Bs|G>Ic4k-8p z4`l6QZQCh^9Y%6N$MBtp1*cFEynARx7#RGl!KVgsh7|F7*{a0dJCJTYwxs@)q**fd zfcAM|l)Fg-XB@f*{UDr_DwmC0v6C?5RNutQ!EFDS9|rPDsHNR5e|MJP38CSIY&3EP zLhrX-arx+Cf0%1>=a%@E%c^nCArMP z#_&dn6L>yq#zotaZ->iRcl2yX8}~nsmyzfpuP)F1&^V7N3D+gt1o^D57{Fhh76Qyp zJQRlb>gc#08+2S9S7$G-2(rwDmZ7*yp6X0_aK9Cgk#sDQenG(7M^6}VG$$_08Iv_uFz6A@O9)f_4*YS+Q zQ_ZFC@PuV8+E8Hnc2?FfOf9|KI>;dSP4V@{G%aA&Ke-ON+ss4+8lsp)#!%FdaSoD_4*8mNN^}7GR8+4k0279 zisC0A?2^aiGNPF6c0fMzc3ALN$FP9Djk01DJ}PAOJC$8T_NOEAQ%8q1mcOb@GI0)K z^Sb#j2MWW>G0X{XSZ2a1+J@n9oy(Lqju&4jKlzqOVgvEt=<}cP3zgVXEydm8WHb`o z?GwM|1pi=1(-KqIqEwc{+ecqDu>v∋{Vx7S*F6gF80a4FcRvI12vWkSDrt{5%m7 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̓c-pz`1lWdv>P@0Sl=}Dk9n=A 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


      (xvgL;5o{ zMw@(9AA{nlm>pjh=!9Gbb50QO)p|Z6eWJ%`iH#+uPk0^RV{?Ag0@=q0^)V(Gh%3&miI_jc$;hm0EB$BaB7`fn) z&^^+l;SKHN7QlzkRRH?bJ3o*wii>{nbsP_aY+6lM5^G$3Q5Q0y zDyQj4{3#+uM|cqX9v3z(C!)Y<)%Wg2gF*LFAw3>Fm}dneQ;-(Xvsi6hVN$m)XfRzYe=y?I9W@t zaNfsQmzE0@k=n0BJm-g|;OQ@2u8B%I22%e6h zKej_Al3{@lIvnUQ&xxza7fziH?s<^JkL92acN?o)QEkxquE=J;CEdw*U6!_NuFHtI zoRB5?o)suRjbuF{iWoLJvZITLw#sxa4n;csp(wmal{&Of&pwh16sdb@x6CAObFXY8 z$x%{C@8PJ1Z5m|R5hjebaZa)(BCRv zKB}Q*w~|t1vn)bI99|UC&~DEjSD>a2weE&4Qz&#b%oVKI-`JBCIf(=S_iy*Fx_NUc zwo^21Rt>(mV}#I)?&(&JMEHKha~*j0VK?VZf{C~4EO;tQa3GGD!#54i96=;DUE9|1 zQp{>t8lC`rvD%s-41fNue>6b8mxMkVhiL}(%2oR1Q{s3%mLDWOPxzVjclBJnQnsab zT%>u(>fS!!N{x(7n#{rx#rH_>E9A{ku@T053h}0%0?LnXBCDV#dCpgW=RpOM3F96c zt_8}}8FgBba988m$He}$qvfKRe@k(!!GRGTXi!ca{H~@K`ZTXvE%Vjahn~Ma&X<88 z97FKehXVBdY2R#AFm30`P6yW;?k+AJ8{&;dZ=%|q^9$Fv5wkw;{__}kV^a$RxLN1S zKKbl55SuxUwxnTqa^hsQuXUE<1AklIgQeN`8SEbfup){`UigGbq8qiyC+qvn)VE8(cN zR$8(nj%p+9U*A8&^Ku_jM4Fa@l~~CS8izj$%p50qgwA{|vzT0j|8q+4)c3dOxEWg) zU_K4!p(b}{xUXd)alqa^szN{Nd8GV!6ukoYrY0IdxFqfG@I20cyASbUwT0@z{!-R% zP_hBsk48Vdm;_Vu){f?5986I(Y#*C7*$FQD4BV(`Xsk%N9==~PT8|dvOCTkQG|a7P zkEQ*~`)7F9x17&N1*}MaC11{@`BC751~gBC*GbG7VX~*_b9`dpZXLQFLkd5wbMy^e ztRN9=S3Of?0yO4`zlyjcMYhHKQIH{Jqm@8b8{|m_kcx@kn2y15P?-4*Zi8knb*5VOy0b z*%vK6$Ci{W_F?UDv-S3lLr=bS|IhH}3kv^wPt$ZRUKR!KS`6QTMjr0?Hz^vu$JPd~ z(%QaysNDeKBPl-u;SjpN)ei%x`YBt~OJzÖl<_SQdoE0v~H4(DM}9$#td5fQJh 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

      X7wy)U=wdB6{7S3V})O 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%0DK9MJ81O?rRz@zFcB6^r{vYb zET$|3V}01yU#cqQn+wZuP(#<)brDe7@SX0~jUvGwa22pTfh-7hfowxzSAvpVg>w{ILPx$AMbje=dRh=sD@&EHi~T5_(W* zk`nU%%JXNz4O#7De!;Jg)^O;&Jy9dP~|7|C$cw0RI!OKD$}^r?G{S%Kpy#@8x;; zO1KS6W!f=3q>)07++G)~tP-Fz=l}P7Wi(r6rF0&S%E3`BeVr}l^VKEcJyuKeY4KA( zpGV(!cuLvONcZ2Ba@Ni8g!kV;!#vXP$piTJCz1i{cg4?a zHAE89f>l9{A2bP8(W&>2TyHrNvTDA0)@k(Ih528~Zuoo87HFUHrM(3U@s{(f_q z$&H%yY-GAL5BPrCkVfw~=S};k&uw_WqH6RaC%sD08Rnubv`g^3#V}4GOgzfN{{+X5r*t8D;83DOl z(FY`(kO<22%(AUvBVibBARiqsEBMvEq6LCHVK|k@aix7W zmWlkqA^FdhcC$Y84=ppEOWo zzM2cMt&`=s-~yDlu2xkB{Tl~c#Za^SYmoq7_@?Q`4^b*>7qKszy^~I`lmgn%C0AbN zBpi?ZdB0iBjyHgaR)$l4l^G)LlHAEN2Z+b10$ zzn$7l-`jY~pJKIWN7auSLCbKQak$;u_h+5sKR2Y!(TRcstlC{TKQuetZPxC!$ zkV!L#!!^xM(njziK?3-?r%!hIHslGDkqTp%@#mDMWS(kjKV?O08Y29&zxzr&%_9ZD zP!4vZQPDSl&smu;)&SlB;ToE|L*ryq5tGape!I?kNn^jJ1iJLVd-i3Bp6{csAdh5XZ zS=ARL3a1Hv=h^&C<(-S&zqIh#?Cm8FgWL*?xgXo7l+*?3C}BzSv^bjFv45!B6OSEi zv~!OBSGzxNk_qOi56Z#@Gaz2m ze~Ixx`;M|HEzgyHB(Yxi=)=);G}Sj+piGA!+oh%F<#{5)DbYzRh~@VtFeEMqkp@2) z0Th@*+UNOdXw(p4l=xbG5(wgKSOHGV1^Elkbytx60*J5ga4gl7#-Go z^LKsf@*bu!m9c>Qh-Kq_E1Yp4ULP9oz0ThBT$!^FQVD=}&yy9Xf?d_C(z^#9Dh0<12a z+QW7lq%Q28CNj`%s^76%-XQlDZLAWGQhM;Q0wY8h=W9Yzh}k1kJLzl+I`>7XpbLyR zqtk7@mfgmhE$EHVD3H%j`x^Z7l?_0C{eB{l@TBRDMw_LV5?5hQc8X2dXA)w>l=E__f4rZ55%2?KH!W?AE0Kq23^p1t>en&>V-3rxnnt zvt^eROb%J`(uEJrU%t^+Ocu)J8?ETO*5VRtF4*Rnczyx!I(>&S<+3qmAv}-LQrh0e zZuVuR#{`yc$l)meDb7y+13LuL@ktS{Ei#JLG<&$wlfd1F{m_@BW8A6*??62G z*r_qFd1(J#y&vL8?NpWay)OTGuo=oO#CfY-=W+W64`aEcIqm&G?0b@fO9>J#^C=eT z^qf<{qmd11(lw~(+piqN>n-sPzfc2s(bXc`z6e~MYv*ss>?w9kdv!<=WORv|M1F#1 z0+Ni?!aTTE)(Zo^%8AT|oQTPDk{RzNTug0uj9F)df3jzTcy#lEV9Z|rribxgo**Bx zpn4jN(!1Hnl@tF%V@wSeT6p3so3Dn^M<&PKa2Klj%p0FQ2>9gE?ua*1rIF-hjq7sG zaj6>==XU3+>;Sw_^eW_y3F&Sfn>=2t)aV!9((I0#hkN4Dc|81&olob-32)c!(Tqe1 zWkD=5&Hzb?PM_?;iAx@D6IM}~Apj0xF6Q`6y-L1__THmdCWI81IB;61I_XiP0uCZHK3?WSs~=F>rBDWtED3*0+% z-FA|ii8>Al?Z}nQL7!XYbae4DqZ0XwIyCv|kw+`1SGgoo#;sZc8)J*DfU_QI(^B!xnG zErZVf2(C2fh)ww&9H%ML(-+eLlXF9M^jq~rf&ubqaMaJ<1||L*-{ZjeIJT7eGBl|5 zg+khPa=)BK+1@m)q@6*^)g$`|pYZ2r!!Xg0&9c;(b8db+Zshwa3oH{(+i8qwW2(N- zfi?MlK5hk|_K)F6cgr2FaE>dCgaNL_O-;{F5l%o|mweBh> z_v}R$8IMcN(DE(CRg_YgPLBjI^}cgCtKu<>r{|)>X1M=vZS>FBxh=N*MxdH5MwS!h zEH0BewhQN`>i!-wdWMoA@HZbqWLRms_4QLWk->X(QqLMc^6qP!oMO)0B`cdGySHnE zGk^O8Z+XYw^Jw3977&4jO4mMxlQsah2r0WTmv+NT7+JcguxOcg3b6ykq)678?1 z>(Cbu6+SKU@{#8~RpRRM)Sdf)`ALH}bgR63!Z8L)5oGQ-nxUKP0wmH<35ch!>Re<;F`x!u&Ofp!PDkk1ZLUtB-nG+mu51K*Kj9e5a@% zgWJr}S#fHwD;=_>)iH@s0-|o=U*A9RZ6uDaMm_CMf_wJ7X?792G~eO(hEYSsvo5_I z#z&tsweR?ucH8u|{e0lVC0QMM2ZJ1%@o=*c#yiiVB{z4WGLVn9kV^Ld?)w`b{eR<| zU&s7-&?h>ZjZj%ae-bYxftfWJE}!(XnjuoQ-ee^ZM-XG;)4;E>!OMD*x{jW8`fIAi zQ63E|o+rA5cna7E0AB2-^Eh37k3a}ZISgVi>pd5(EHfiYEGrJtK=LE+60!ZWUF5jh zUbJoZ>hAZrP!zIRKMJdNQjCS7FPRpWs(l&z8Y(6oj&fmc+;wCt`0Xm8V<4GMB*SMxMUw3(bFd z{|qiGxLfHM$vZ>p#rI@kBzZ}CiCbaw0b8_Pl+XWMEWgs-)}Pac#xve%T5N$}J1KqZ zkAi(A&hJz9eHyD2L1MES#G8(61Ak+_2{3p*%xaO)AWKbWCw`=s&O}$lrfEv4g3M`a zn&4syGX10qv(sVKI4UJmt$B8~TJ`6^_XFPlm+F=%th(&|=CqCdvRIC;OA)s>rI8HBnMEykY3KdWejVYNVZ3?ar$ zMZ&_*R15Mwdsh(vc6?m_jZZep+9Mc(+TL)bD zcODd%G`$uWO0f#o7+<*tmoZY6otNdc+5Gn+?f&=f?;jol&vxkA`iTJb5)3x+NK z&#?*&0&8k8tbk&rj@h8z)PSp6z%1h_0{w9l)oH1WW7qP5ct=YjsVMs2eFz@ zei4&xxtDC3JkBg>`B(-W zZ#g$G?>=>|lvBWq=k43Dj%Eu~IxA=e#b?SC2!2)X3c$~X*71s=T-qek@)Sj3^mxs- zt)&{9k^~fY!*Lac~fmc>CykfaEh=MuLgt+PO)9Zmh3kz7^rWACcd!@$)XFBb4l6$ zuWIB!JpN$Jl_HF+*%Iy12%TpQPd9?KzZgQlv;RPd_or$yA+xf-g`0RCk>k|1rE&?( zvC0n(|8JVIOXyKT$Y$e&9i1Q^y&2ORuz6Phs6M;_0GZgFo>+1@yj<+YD1z%cmg>q0P_+`%)Mdq~!QNkk-Aq%N!2Zx;EX~ z2pOsBu*>XI#Be#-xdjNJ5t^4}+UHn2s}irj>Dh(c!pXT`=)=gM4Ir zXJA~K|Jyq4{u|#D8=RxqU%0MQf$UNK7tr40pCMAW#iPF!EW$rvCYTTi{`?uOr@>#o{TtsuyvV~N{^qx}uw~Y;}!!7!0qPEPodb?pvg~aYWQYf+Y91h!TW+Sc>d+N z{+G9#7x;3{Ae#^?MoC%hx+}&+V_egjckjfmh0KNN=mb_7^Ui$a#cRHIh?{1gC`*s- zs`dFL-7dz05_2pxApC>@yhFRM)_hh}qB$99+_jlQF3Fv&mSTfYPct3viUMDDEDel8; zIm&ff!rkgFaJ}~UaN6nIc6%M;mZ~%R^Zr2HM)=t1B6-8Gesz}+1@$}Mpzx^_z$XGx zhl*A6D!_5tbP-KE&7&n~cA>YHhVJ|;1kGc7em4Hzw$S|LnK87RlNh7fqd72aS!wAM ztdhZW9R`Zk37azd_Nxg-Bl6>$h8-#RQ7@^& z{G>LecN&kp=%*sOYzZis_VQMl8YFp&=PU*Y=FCKcT>Yuoaza^7W|JTu6Bqmq*v&Hq z5T6X;c5CY!_II|9%9I=Lh>nVIu#1Yk)!ibW4eGzw&}~)f4e%gKu}*dHa3Qi4RXtMh zaw6z}YJZkMjz%9yz(@sXp5$m5;c+i(SFuC?bqGvzCk-7C-(#a>h|T8!J1_#Uz!^Mm+s-P149sst&E+iH3j$RF|y z_YQXzD+5nIMD>@a1FPI;kPm?t28`zUcX+u23@;xGnb3SIbTMqixL%gV;`9|H75SRr zexM}Ha#zu!*V3U)mHKY%_nMR$_YnEjz9xk*smPF>x~w5>hu&G{aRWCXKd&EM)#(q0 zPBMJMqHKP9`cIcANKX3{{b(TBi640nmjaz}5gKl1vTu3(H(M}DT7o!!f212zqM$wp z)n1FEVg}^nUV{ezz~~;}E0<+&VSWq!@_?(%!#`;hPGzr~@C(B}4{8z}X?8D!;Q|}3 z5h->GWO=DqC5yc1n|;2vDQ2x8En=d`CysT!zzZ(|_|2-6$(lTk)ZsXS=B3@li@~xC zpSc{?R_?SF42jw%vJc*VLtHGye6sY{=g;*5{7uhK zfOWgZD1SDQ6aES3W`YkQBzjG)*m&O7P9jCFXys=mX^a&M2I`gZOa7D%u8E0UW>?IV zAa3KJnNs;(K8h;Fp<&>Kv&<`E0_+p>=Sa6TJ?GGMb8|kpS|7d0{3Yha|6EAM)7NV- zahLB!zo_=TAXoiJiCA%Gkx+M=Mc_Z@z=JjtJ_pK=?c2T;*!?dX(ElKd^=|21bE4c7dAR*2u5ZZgcY+y zJL3b}r&1ceu;LaAp-E#if^?=o)YQO2CbxH50Y4?npMtF(xwb)Kze1_)wh3sUUtdHm zQoib%r@Gtv;&-3FYe09cwFL4}xtxLjprZ)jV_@D1s~Du(tT0$@gt(QZ;iY`nd$4@y zcNH921-CllHO-~v0p3V=`afE87*tc-AHD0_t`QnNtDY#!Z`z`A(M?a>FW>PW8s1l zC-hc_3mLN+TkY-5mX?VA$f~KHclvDytY|9$pY1i8)0uK!sM2$B@%-HgZyw@=8ZDFW zZ^I();vf5;=n|1`2hL!URW{8~FCXGd&!u!Pml}8vTSeAYi~&^B>#ram3;xtT*uH9j zPid+@jO~>9ve%|1N4OG^@8}~JSso7mV#o-hirq*4Qa^SPNp3lR*jW-RBeg=JdVv@h zJ}UcOQ)PY?MQb6IL~^tIQTdsv+u0k?e*OQbYDI4*f)%XMaOS$SVYl@ z;4Kt{e?EEA;v2xUDRkxFyeWdZ61)ZCF;U5pgB@QDAU@IOZY>$Cqgcv33!(Gx`n7Lp z)TXk9nLlzZ_2wArsMcLd-LD|5BWnEw*EFn&8G2?pwhn!&H*Ey?Ajx-( z8s$Uxp6XcF2|aKoM5@1M0Z&|Cx6&CjVE9fIl{Cm2YwM)k3rKFiQTj>g7~!!$2o7tbmd!~ z#ua_J0ec5)g+J5Jj}_HnJ5!Fz7Vs%+L>Ap2DZ z)0aJfFE9Rn2KHr8!F;|^SCS+bg;AT)FDzEWVOZW%$p>I@X~#%Qf_= zA1vdbI0h>(iGO&-y%KlGPXXlDhQKMJ#^8`z7gRc+$CZV*ad%`RoBIi3&{B`~F+YVY zr#r79jT|2MYSgK`IKg1D^@sqv*C=(l6@&cU37_Zw`j|hjV1nH~M*zNKQTRUUWJhRX zs_a= za<0oRz^C~9OrC>9w<2RzkUpBuM<+*2gEzb{Jh?@f`_GYdp&_h(rH$`+Ot1_>QlgnM zOH#OmIOTG+GV?M$C#BH3#u+F-hu@Y~-MMkxnf}U*%|f%tp0})_ zmNZmOzsZfgg0X}h?=dcPXWS$C_ytu9I=s}TI$!v^4QkxY(5H*9RlxUtimiJEI&(}{ zfy!znflXO9tWZro_>jom&j)z^)cb5+oK{OFnMAbw`r31+ZS%;w;#`y~l>N|JgtcpU zF>1B$8suX$<=zC_w*$zJcL>I}E=KO7zk4%lE3{B44MutSlwW2JMf$fXJ+1L*W(Om`&pVMj_dUY1B_4$J@!C-^9frKWb<}AB-*W_Aqn^2j_Fq$or6;lYxjaRUf}0sg zp4;CPYyLAmD_RoDC>~OZqHgGfIk8kfx8G^|c~SmCO<-rf@Jr_%hVUK8$4nXp{(apq zfazz`GKGQcmWcBf3|mF@2+~ECC-KMlu{H&!J7v@{s(kSiJ+>AR#4-(JKS{lskutml zth+Tk;iseYh%_39mEM(r_Gz_R=3V+;aZdrILdN3u3rTNu)}6m&uGY*B3-4q9TNtbF zvuG~brmq&o7|y&`={3{HskE@&g&41v*(2+h6aEGAVKJ@;ft}wWAV033;%eIvX6s)B zdS0L02Ju+3@#s(p&gxvi_AIVB9mV+J;S{@;seM>e5?%qeZgaZkLjyGYI{cjCwEcknRbHqdT4j>nOQx8 z)6?e%;$^xJop*O%gR>ZZscp&IN0epsX(?mihMRr$S@tpLbxTJ~!@p96nr zcQkcX#3|)a4+UqW97a*%CrPG1-wXIWNF;&h<3+nCjwQFOUXSG{!N5Lv*lcmuc2Nsg z%P}JjGbQ&}&lHMg^V$DL*!^jc=w*-Sx|8B7?ubDutUZB+UQBR$E-z?={(j?K@XADsmzMhqlkOglD6V@kcoxGkfMCPio7hav{>tO-h0 zkRcQ}7yRp0!rT9mha?Ux${ zicYY%JV8%BR?A`mZ^1i$mNCyO|^c!7~tNPq&kt;pHHb~o1C-t8{Qp{5bP^;Yx!k=0k^h6&UM1TapVP#o3^PQc^?5UEGw~UZ}KrFv{$&dBi9r*6E8vtLtFBJ?!OX~PG!teYU z2n<9t0@R??-cYFNbj5XZ76PXbv5pZCJZLmN@5|7)mkIM=Uo^9L;@?DQsq`z%q@MEv z_*5+_@|L!QT{9n0{C4r^6}~M+?=9AdZH~N))_(H6Iv8idp2em{47A2QP1gUUpCp;y z*cgAx!udM(Egp?O1>%d3VEGOn==>l6*85Qm<`aA{d&tf&zNv=~R7@OfwyMvWnt(CZ z4sB2W(FDOuJ9cC9E>shz>laV$RXqOA_XgER+bpDB!z@P;k+A>tUjOrX)G_+r9A*7; zWG12`!B_#ff0m52tR4$nM+jBY(v#12e65l;RqbHUqeqI660Oxr#hAcPF;3Ie6wdD; zE4x_)>BSe_g$u;{_217U!vF5wz2xASeY9yc3&pm-#TUOMrOVc~X@e;K@_=Lf8T z{Aw@X6%=irVPxp+RHN6&i%QYV)7lM1R^-uif(2P51%UXnM!B$l``VW=#P^Tzw`t$5 zR9S$ZMx!K~Nrf3b@!Ac^WN!97(%olBF+g;#x|a`5cH4Icg=ih|t`qJC2l0_#c-%Sf zt$~gY8X&&)^O0!%n@3pOp^RQfGN!lrD_8{fBUx;N%MI^x`O`<8>NXMgg+ zD{Lx96tZmTJ<5Uy@J#V}9vD*XdIldEroVkF7$VlZf&Sv-#0513+6N2ZE7;wxBJ=0I zrFtCO2ufvEi?~wL5Nvc}TzbeLXZsa?I6&1q{VS6Hlmj_pXtwlmTP5j&N*9%apGebe z0dC0D2EbPt9H7#U(W`W#?me|4*CX3sb+p0F1flaIB_j68mt}YDQA*PSKa9?4^7_IL zPp}|ept{$cS;CUa_KLR6HWcT@#}@7n{C0!z06zE5;_ptLbv5hr0!gHHb}=dDU1NxE z9rVc|_8FFldse>Avm&H!4Vnv^&{zEFUY5L<8H-EB3JeXKU;t@$yWj`#!Bff^>lWg~ z4rz=Cb4bC29Q97xkUGa?jY!J0KKXFfFU!O0G#~BT#9(%ERLnB`YLR{^K|}1XVAenv z@p!-yy!a?JdW(V14*|fpYdBg6$|v2QAjH5{SM{2?N^)hp(lA4Yjd8z@kKrwwkl0=U z$80!#m=PVQt7B8pHbIG%T+7d)dyB2CiL$C40H5(URbOpJXYfRROPQH^)C*p2na4OC zEx*@pw3$!7*Qz1!{XbiocjO>NewG`$2*5F6gw6zU5-1W{D|FiX+(`K1>;2Kr6PSl-mFLT5wh$OjeH}x z{gh0py+-}DzWPm1BH;bSub=AiQ?g`U9M_*i6(qf0p7Y4f3Ld?+ki>Yt#e?T!ctbdbTN0E+^E9n_e%vrR_t;t#1g6zG zJ##3B+_X%XNV##@ywjBjll;Yp?;1-3bbX=%5x!&RO>~|=y8XVh?ysD!IRevur7K10y6K|q5ghB|uzUcYpMQ5V%-o~+ zfo%or(09;o_Ii=*wTjjCy|Vzedw;;)DfhE_CLt+0tD zZqUJ~|N1hpwt)7b1Na0KDJLWj?;Ot_&kpb+>V%D#rWqEWq7@Xw&`vOp}+| zI}Qsf*Sf|XvM8UCx4h%oU{mFjT?MO|hz8uwMy<#A^?(sfWlIQ?z5pv`4%%*4AedEH zSXVF6^Sm=*Xpe>#qP4DMU50f-zYbd}UcZ&t! zBXPE%5Bi1o;da-o_nw}OM0z!`Duyl?0r%$>(aJfl#~XN?=CA`N@lgVLxsEXCx{z|( zW(N<**P{1$qZNCJq5%1Qfr#57%$s4*5C!pwZqqg_9(Ys8|HF^1ac#cyDZgO(&$tK# z>$jlpE|KguHD5WpI62-i8smO|OrlI9jlhCue(`bDxm5t29}$4B5U1n93%cEF&8jG3 zYxq(UMxgg$*J-plq*hW1cVWKBw*0y=dV;JhruPI~3PNTv8W~6MOR6uP_-Y!2+jRC4 zfG>d@v`*2zDa}0j+^pkaBMhxBSUBBSr4fwxc-5Z9VA}ZNlr`2aaTp zYe7&q{ljz;|3Sd|J==?q6`zh1Xdf+ruXLVDg0IY87?qkDgNgGMC>8xKYa-8Ka~UMs z`)lmsk4w|4dYnHAV`u9n2|&8RA?p6@=7T2?SpkP0xBxN5EDhj`;&nP>0$qo1e{IVS zDlt;DL<2rqOc_OtOcGo0y$zb$&du8l>{ zukL<~Zh{m~tBpXJiujFYbLCSA!FvV(A807`_>LyNj_k$NoGty-S~K&j-O1nl=R5eS zEKfdy)EihM#VzJ<4D~(@{!6y@*g4;gOI%sHX%nnC-lyHX=Kq_YfFux00{)Ip3j+8& zKGwV0^N4e)Wh3Lr3*}J5&rn#%9ysAr2U;7-x}y$TTN8Y~C$jztLz}vPyoN-uj0;8F z#1(|`X9MJqb{s_iIgaF?&xbwdL9U5`1e?dRvWfNhhPxJ(5~)*DQyOFwM$9K4_$6PG zfr>rmK9houlTPMdp1cK!Gngo|d1|s5- zmDL{=I0D4?Ztu%c+3-lu9=Qd?fnkD<7PXoJaeGsF_3lA#B5QxE}zwwCz#HS&--PDKWTtQc{G*byjQUpec zp_bp#@uM0Pxq^5PmcEr*=i*IjA8TLc2Af|DRX)Bq#o~?8 zmydIV6F_6ow^jeL_2d({#^5iu9PH2vuOS!BBh;=C~boohB^2JBq zQ4W0XE*Ze<8C^e&9UJ6=k5#bN*(zQBY>U6*Ydji>_dguBm%DA}M?AJ`?q=*D7 zzN^Xd`=v7I*Iq#@&w74`^J9s?-~;e|RWC}9?c?vMsd&KWpc?&D%BUjj`t6aPqM-kI zQNTzYd&J~mW-~5-!+ynJ&qMNJ3#l}Fw!nqQ6t}GZSh<$$iw~VxqZa7=6aez8It&40 zclacvX=U4(P!)$~^yjdXA706qBo89Q927x0@)l9pTk@w1SYJ_pwj_MRfN-Lb6CZ4} zS$JqAnbIyq1Mpo%(yqb3iAL+q97yp3YXpt_T7#mLXBqwzvFz1Te!kbzdY;UXLXQi` z(FU$rjK1$K6G@6+o0p~ETNf%;e@IYx@$FvP1Akfv1wej3DJ>Jm6q?;4W04y;HbpN2 zq%Bmuf*}^>!CiWGKX%s0)$YA|h=>thwYzL(r^%^AXBj%Fi+bZ8?-Z^?!3FW3B}e~^ z-u~=3g`mpVtMuZdlwSq@@t_EhA6l3XQG9PD-N@aw0gQcum5V%wQgYc(FC!kJ z_fE8P+CAxFC9yoXSeCD4f(9DB6?R;AYe?B*bFfP`$YH~;07qB87aQi_Xq~gfbT_+) z1*a!op^Y+c7KD9|8hTav6zOH5l>LCWC#`TLXq;?S9ieZh ztQ?+v>_!-+EfFRnsr-Ga@HrHO7eyx_nZ*mdTRbR|MqrDwrJ653VvIZBSG#Kg_$(mF zwan$?wU3Ux$I#gjN(gl4ggF+=DdJU`K{l+u=s>UJvyTXtsHZ#H3G<(qRuP9fQJgg# znp6e!@NaTiW&!wSJ4Nkb7JtJoWY#1ENUBzcZEd1;#SDwZGo1B3`Qqzv2|8*81tZ_^8a{m4VJr55U)Bxx-*Fjn^?Ozy(eQxgUec zzn)GpIrW>r!B;{j{0FFUm_wh4Q+}uo=LA#q=NXcOupi5Niu3{Ij{T*2Vx<-UzB#nX zjmkAo(+31er%@})FiLw=){wrrSM>Wm&y&wgnuO$k8xGYQ>P&YR4*vMm?e`YF*w%xY zdxg-;3msQD>aVZgT@m=_J1xNd<#_aGm8SdNXJ4;6XQj#Lrk?LEA;!HcL(bv%EM&sT zrq1p<`3tg+@O=0)niNL6Z!R$*kJ-l_MO!YdX1h-%=>UBFvI7Xvafi9a&Q+7&c-Pp5 zFWo@NoenTUWxskp<@X_~X@9XM+(Z)VSjlSS1|&fCC}z2hg} zl`MR6oKPj}@VGOw0J$j)Aus_&N!dpkQyo2jdqXI7oRW&^{XgAE@B%($y;y zi=Tv27CS4V)$O^S6<+?!CSX|N9OO--#^%~QdibWah4RjBK1D5(;`?rEbr!V<7|JY- z$N3MbfcKXn-&tHYts}orUTLo6yLs4TTWu$gyioSBOyB9Ae5WG;ppcfoIYM_+qo5eB z@ez(OiBpfvt~@>q*>fr>VlJEgy}vY_=mPC~3*fs^st6wnZuL06g+cAgyi$6^xm!wGj{-A`7Iu{E13-PMz>|sGPYLMU^|=ogHAV`v zPYAaR20mJe&e1)Ot`ObLaCS#A$zOH`il3K9ENlD4N-Y&yVV?Ta#cLGaa*Emh^&Ni^ z2ioTg;8Q5vHNBzJD-{`b*`-#QS<`Ey)!RWj*n>393SJiR{|^)}vmufK2nnHbZyG8m>?TRarR^m-HAsql#h3tlbn zW|^GF$BvPdbMcU^BFh)ZMKV*tp~eE?5v7wl;rzm*yfPsHI=*Ot_(DoOe~WxMHb6*N zXw_&X{hz~d&tqPF zJDr+>xi}8k=h3wG3rqJuyufgK@e$Mc0zdaN2Ef-5A0E`kFzhfR0pdlOfU_%kKxvWD zFdCN=*zA<*Mn_&9(B=cc=esX7i6vDS6>n z(oUUIhFkTlu=4jKWz^ued&jTyUUye}Jo$=7RZip&a1zd5xi=cWPMc6lQuXWx|Jd<< z(`X1EI>Pk(+ZP|CgJ>_%`NaeHX4x#ijJUC|aLk?@?Y#Bpl8BNvsc;U|fp0A-(mAor zN7rbP=x48kur!u)ciqzs9{TCy*SfjMg{et7cBrn81CSq1q-Wj9qEvbPE8IrfSNPfk zpzMS}j^;}#61yBvz6j^)kd}TENSI&)+Dw*;X0Q$>6tyqaMm(u;S~mhCs!hHxKKxP+ zN}zp-06yM61^ZjI0xFfnRRU$#Vf1gReni; zVKKy!9MoN3br@oD5;$xGF5gPv<0_3`UtG*XXU$0Gs(ek34?i9uG{Lntb>s39fSF>j zh}=L62FMR1VtcsRU+`3{5bX$j+oozc0X92V$Q$fRT9)A{zZLKaTNz&7a!|C+Z3lgH zfzM!yjIZyVxfI8W)-hRj^J;@%d~~*?20-VR4&ck&5buUfJaCizrBwY9WsxhK+Uela zO5Ih`>oG3-2g$L=%2`vhR+u`+HOJ$3_xuvS-aw#VZl6LiH?MswGztLpk>_Z6yKy(9 z#omM=t$a|i86m5Gi;rWxsU+9r^yD)>e?-Vx4A;et=%{f?N&RI!gbAHDbhK?d(v6FBibKoc1}FHaX4xb|A4y zBVxjhssi_Y1w^07Bi(%LNdxGSH|dCjaT441rgc46NFZJJx%VEaMc)^Gu#YVZ3JuzT zhp9C?#0g2{PJi#h#a~agXlHlz+X0aww@rRU@c7(4F*^-8ZSd~Xt7ZC_bN>Nu?xp<1 z+0pxaO|B}<8Mz00IQjS&A1{0u@UtgM0DOkkr*?X0!4+s+*>gXC=|d~MSAiFLr`$oH zk5`j@31v7`j_UH2m#>`z)h6*LSi{lVUn|>J2|?YC`<1?jJHF2U=J(I**;T!ss7Z?^ z=CY}y5l@_({OKYaOOKyzqH*<~t-t^LllnbQFhIkvXe%^ijSI3|K;3GEH&aJ&d>>eM zGHJ^t@+tAfw}NC3eDA!}f4`pP^C`!7>R!)Q@y22Zyrb_qDUV4S3#5gQqgQBCy7OR) z!E6-cLz9{+sV3C=(8gZb{o@`gjyW=8np;OsqIngtcS$^65ZUzn5lUX?g97n%h+sSo zxPI(yEU1|jS=kd$Jg>Mn%v{u%A#iPDi_hBxqmy|0y3eH1!TYz-Oml9HD2fI&81} ztaZM6dQNmdvXo9lbSZNVjEH~Z`{(uLz=Yk7jB8&Hi)#+)28Y{~$T$Yh;ls?NcV^=A z+(-!)cFef^ye&e9f;<&Fb#3Ci$+RUW(0e%fPt8)RmMY3=FFwj-PG+EeUjckMxJcA( z3iVVMfelE>dQ_dzHNUw)@Y40rc4^hij7pOse9sOk{5^NG>m06s^h_CuRVCpY{B*JO zdK_o{%`pp*);%_)@T>X8!@Sk3McvkLdK>I2HeD7?&lq`of%%%{~EYH)XEf+W` zsukG{vQse#6y1oM6C*T=8o#D`3;RpM0hHgm@yc=oV?Ww01g3M-3x)^b9T9*J(J8iQ z&m{>5N{{!eDSQbkm5*fSaNHN(ox6kmr~0gW_c~gp7_UZ08vXkxi&#l}3;Pd&EQq|H zF^dQ&NLZyz|N0`F8-O2uxC7V}1&)`vnk`E)iz)pRGU?92_q#L35d=C0bm zUaCnp?wg|d6uHeZeJIThGX5#(XTI9hX8s_7b4d88TmWBUY!}tQ#LXrNbHHv*a^xRUwCE8vXHK-5?>J@IFEg9RYj-YA25(rq!HjcX^24{N z1b#2*I)MBZNJteYVjg^pYq&rWs4cFL^ODl^9+Th7A&1@ClEcXM>d1FT!ul6#$nzQ9 zCJ5ip6j%w<7^AjhjQm`=!YqXDWY7bd9WBIPDSCBV~ORe?1_%3;&cK z6;TW}On+|4&{#VvYG2fr?}d(V9Dbm$YVDY60#6&odBKY>a$pDr==yvB$j>a)DEWiB zg=_2?o#oz^i>lK681(n`w)nXSMr*|k;yFwjFPmNY4?K=r{!aaA1iaGnD<~F(uq)sV zjHZMrWk>+|WgU~UVx^+PxA+MSMk~<8w{=q=W#YUtbJUfSc=Cl-P@GJf!YyEHe)mzF z%FObe^;cA2%o`0<1rrI0-p-sZe(}NDBuD`5>jlUUy>*$2pHlf}Sm?JakOZUJ(<|Q} z*OZNE*cde2Tn4bLwi~egRM)+U_HF6VH20^3H9tfglM6hSZp-aPb6Pxe0DNEKAPY7X z&sSu42;_I1vH}ZR)m~R-_gvhTEZsl(ZYK(due^{UCqH_8k*Z_I4y}Oh`<~%t34^ER z{R1sIU8&^7$J0Fi8ff1TfbZMFYuW4JLSYXVol8g5Hh0PdWq#G^)t|4WG5ujfBd^+K zBYCD-qSBNgaomx0snoZ~%dy`~``w{deH3Y^r)C83@!5{i6LMC_fPUWB;eT61Ak8%2 zaiSDg>8cO9{p9Of$*I)D;D`R0(vD=RDm#!FZqrM)yKL6E0iXL*3Oo@0+lvpXjI$qT z-#CDeurvLQbH>b`*;-oN}Y`H8{5atUdbY_2m(HvyA^9@@O^DW`wI};$-a?pO$E5b1LK)kGv-z z+WA)>u}O;=ZBr&Ee2R{l-$AqMa=D?RSEl+G>%_#r4=-AQNfY! z>);!M`HDlUn$N2_u=d55$=`(hzx)2i$NS&$kt|b``xG3j?)}&$66lr#eVDo8m2|-> zAA9WKPTA?85#d5iz$?k?zxx1sqJzeLQZ{4c?Gm#k*3i3^{Thn9`Cr~YZ)YO64dRML zqjVa47IFok%GEP@+MXG;HYJ%}%wA9NRS%=t!OBH4EZi&b6m4*O=B)>>_JG7TB`rfTQb+l zNf#oGO6O>o^yJIhY0+C$lKjfytPrTx{_W1u=0b3~i1+ic0T{xLye%bK{fiHT?8oZ= z9^c=&A=3cmxm{jmR!}anHxpx+X4ZsVZKc|nk@ualYQPSz5Xpx;c29~i*kbL>&_tj; zf{i@F&J}NBF&^BhAM>qFM;otNHGq%MPLTaeK9oS2tM$8wC{MHoLPrl9l@E4vgyITM zzMSJy^G_ed>lG!rLR;l$5bQJ5vX1v{vX_`6-l-BTFOoFB_{f9K4}kWq0r+~OK*og! z7VAHUj5sl%JKqKw^B>sn9F4W0(nM>oDQ;;Q&L`1yJbWbymx`QDX(U|X&9WH}-hW4u zMzn}+kn|nEC#CnZ*U*PO08JeMX3^KJ{~EMKoAp=JuVKlek54}PVk1F)ewsFcB>hMJ z=I@ZZ1Xy2NaryTqEEXR|f1xveZ-4QzpuYnC?Q;Xb2O@a}yDYo0d4kAT5I$UP9iZeO z7mYh8YSMI?Xy19@mN|Cic)A?3A%G$855YEw|DG&%?@aDjSqfi(cNyxO4uCK7Hk+3E z;4@P0X zh|5QzkM^SEbVSGm{>sS89R4_XQZ#}X464hIG#wSVfF~W1Pg4&k%Soxu>KNfl{Wk2Z zqPw-j(&Vv4mpYGr@+qAhG@qSoZg7M>*vk(du&oM)(#SYUCBHI9Zt!lN&Fk)Y@j-Ok z0>85H7Qi>1iII#HZ9{eI`a$KWIzZF-)Pa%%A(dk~zs{BE*A5Q?jm07U)pvAj3P{Th zE@B;X&_ZrHjtksQ!HtKEqc#tK{6@coLA%U$br+D*?Q&+ZdLg2KU9u|@vM|guD?j;~ zYJYxqWq>_Zkt1BJ_BU&O3xq);gEuK&fyV7`e1^zZK#*ndACN`+W= zY!@`lcLRgN3FfIcz7(B{625E0U(T(+VWFf((MW3(%*58W_meV{V%9y_v#33u^<((4 zGNIy?zjy8ShF{M{O+mvhE{PI9fZ7+e-kMuk@#NAHt22)jL zo1-)9&XLra#OGuSF+2pDG3(y5B>UsE&iufOul4p55cT=@@u&CSJP{O60#nCWr=Y0b zH8nAO#jjV#Bl-HJs+H6HD*fPhKI6C=G(Ptdtk^!nD#a`u2Z(BioL6+1CHdW3)fa=i z2>|h>w9V1$vR?JYFX0=$h05CYpg2nyB2Q5{=%O2cif=PF3Pd@sbZD|9M0jSWlc*XP+;i%m|q+}+$J7WK(bfYAI5Qa|;w^mI^oP&t z;G{~!JN?$as(7V3)pp`GgKv4noCWF1W>a z7@|A!;-jLS#RIxLQ2@$Q|Hm)R;l%~hO~%~U^IAvXLsVsM9%SKZSr^yuiiAlyIJVhH zBiMI?z_?l?5<%){z9z-|G6n18+lS@SjCJtN2FR~(t2Nv2?Zg;PL-EdMXZ0Ew?N{z6 z53*g?q501%bFj(OQ1)l^4ZQ~qe1nr;kpv_Bl*7a)8a*M0+oN9Z5qz|`<@6}1<^^e_FJA(RoqR-LAHj?#Z!Ln z!XQV)Q_W3qMj6`uKQqfn9k6>Lj5a9My1+D2zOvgQ&b;_o%~2nK&W{4X*Me+Q&JKbg zs`87`6SBjNvzmyU($m#4kZBs+5@N`fG+kJV1Vn(`thP3Jg+~A7q)Cr8_AZirDTkj@$VI9*_2(d=~w&0kwH^2SVj0_!|tY zA*nd5rP@Alzck;1A7*?#vfrM4@iG0LGzHp63E=x-(%$d^N?nz~AK#&+m`3L(mREkb z$#10v`!f@m3HcbP64Ot+kM_h4YX^HeH>7VGB8x>rU~+t~=s}?HJ2C)Qb|^WtiPlwN zB`}AVQ7Mj+ju39o?ygsqWfMwnSUve>mtb>9bvabbIMI3=x{VK%A}{=ld#l5$V9zBu zC!iShcV2w2VKISNnELnet^x3R%~mcNp!{Rh0KJ!`MeWZvbuzQ*=LiC$QLj2Qo7d58 zqbS%!+^m>$eb%mP_xqU^I8L1l=EKk*Xe$}YlfS;N0$e!FHFG6tv|)_DXVxN&3LY!^ zTD7RqUeH`mMU@Ee$%o|Tpx6~B5adc_=H?0CZsqH{6EUTP3ps$Iwlw|0(iL?1#mB`l zy9RWA%mDedlMBMq${|{DJ23{GveaWB=jsfUJz_`MCBPvw@G+P4B7{vx zUAIr1Zbw+LwNaW$@H9(@HxaD^)Mp(5o@^)!jA}90kayqsSDV>{iUFN=f814^kfJBw z^|icnoVnBKjq1&)WDH9~swG<(^QY~fw)(gcOGvks9qTVX+#5CE$2K_ue5bKtXLD+c z@yk{3l&p45KC-huFjf10r_j90%HiYX9aLzMAfHpU>~&!V*^CZhGc>6Zu-vBmk%T!s z#GO$S0Q8$RPv~*B=2kr?2Kh?^=11*L1m4qMVscC=rMkZL;$zc%5B%H$ZU7&t%=l18;NI+aMB9FP?#FBuy2;b1 zaa!e%&VzMOJ{^`&TKaqYQTDRmjq_1-uPSFtZ7LSNP{BkR8TvbY- zSB=%Qe}8{0(_z3*t>Xdk5oPJ_kUE5?_o2GxXZpP*)I;niYA=qb@+4*0a8)q`V*(+z z`?_b^u3hEt|0bUKbFX|(*ya7yJ7lnyGjRT;GXURwljPPNE15iGc6X{xfc+PaZhM?C zL=gx2cJ1etW8p_Ol?N`Q7^3aI!dVk$+#0QcWC-wGj~bXgwT9Tfm(d3=`4M$f06+DN z7r=-6K-8pZDwV4sm^QEI?suFPw^n7deHqgiLzRnh<(ZrN!pj> z+}^&4IGK5D|K2-1rY?5uBfVf7Cy_b&L6n9$_37XGWMz2=^!-H)z=xe=gO&-0>>E~~ zxm%5>)J*QA-b4uT_Ty$Au5riux58P%`y?#q;w)NMAuexAN-$|jj=Ke=UyyyyA>ip? z^?*C-&(q_G_ys~@#OGTa&+nUY1o~^eA;+NF zb0kCVyUmbPmv8POH0kpC;A77lqx6%3VF2yZ2Y5cbE#ceNjBzAanlEF}#7*0vFhW)h z|CU~u`rV&UmF+x)VJLR)laGWFRBY;HO5_QBy~ma#0(Q|a`;pGYlL8eyfcnG`iT|RV zwumHkLr06R6(LU+^6g-+{ns^Xa@+IgU(Tsg09CbZn40Tiy)5k7@Mx76$(OgfuIupS zOE&5<=Q&p|`C)2E3jytu2FR}l8ma7&%(T5>@jlV_JdL1E@K$4I8A}U92;e#SK*%IH3%Xu%A-@!OmS6WtUK-8OD`vxHg`R1Bh z?^@$~u$wtU2&{vZ+|z(U!2GI}yPOnY_Bp!@P(g5Umq1FZV>s)7e%|(H8k>9a^;g91 zGpz7YUPVVbT)1gPWh>S3c1xihRDPRqMQqo*czgfiqZdn61=?o>;A39hb$Pwha`}<& z>lc3wD$tyK1&JdjcdqnV&X_Py!GW<(>2evTpe42#V$X{=R0uNsTv{gfFlN*EYuH-) z!t4O~so-vL>MH9&*IbCcZ>y#vu0&6fc^ig4Wcs_9>B$%7vR)Ug<3|e$r>j0^I8xDS zm?c-T=4eZE88J96`EW%6^78v*LT0W3+Gh&jV?-v_Me#|=iQ8`?TvzXOJN%5mL|79y znpHdJvHO#egF0|5E_9(3Bt7?gmy}Mwm*`aJU?XRSC_^B$_+x5oDuB-cta1mpX}@+Z zE-o~uaVB$ztJafMH1W!+N9lQGqcTLI)vG?k0*Gun;~FDArqu{W35$)GVM7x=HTqWv z9SvYFK4>k*RG@t}0KVv1LXGTw9j%^F%DmQ!WSsOdWWRy@s1K4?kL_8KXyhhQ`K%a_ z-%Q}L&fEJO5>-xHUq_majl05E(rCGO#v1|n`jFZZ-6pGJv8k`Dg|*9nTCQFos<59Q znoHq5Pu-pFF+U_lMMZWfYTGxQ!j_<*q?t)>$uJ}MDm|5bxfALK@#4d?$=n3mX9wWR zVWS-G4}yS>shz0cH&&q^KKQwD7yTG;K|#SULvK{zF$hNR&7E=$OxJnbCfE?3w-!o5 zZ-IigSKHD%vxE_FW4;rD57c?=I{Z|WYQMzxne(~@i5GfPB>Ok_SBIYJ)80x5)x?9Q z{1fjd)+4|2u~s5G#{v5|wl89zCzl?i(YByod^iamz<(dv1NiJ_SWvZ`*H{}ZI&QFC7*NJzNdD4Z9*ZeYr;BpVIHf6;5Hz#=cKBFCOR8apM`tb;m zAIbg#+6~q8?^pyU`88@ddUehoa-{l>_3gFRh&lp3Gu>03U){qYE=nKsjWZYL|N) zEss*GDz6BEU<9@v-@ub^G?I9XLqR2d1f^dj7!6t8V2UL3BDgObMUD~-YRum}>93C? z%M1AKYXX3MuOsK9khh?9C|R58n-5AY7_%Tr)zZd%_DSm~jb!m3$YR^*Hg6h3`f~)0 z2K_2#biDk%l8?zNGqe*VzwF8{&ja|vaOZ5*Nq0(w=ytK_o%NbgAw4}AmH_kF4H)$h_oI?l+MD$gLT5&K(a>;ptJD}z6+(A5W2scJ3F_GX9(K$%B) z(^Bb!or=d+c`#fk@oMP6CI9RDr~9+5m&e#PkG~Gi;J~hj@D?xiu?_0cqJh>oobIWM z286Ag{5?`F^_PAhVZi`(hst(8ns?A_hI^sGXirLY&Q`7mijfnTfjJ|YE5i1Sgzv3Ir7^^rR=|c5+MVgFj z)X!$ft1;-B1+UV)`7iIE?j_6q_Zt2w2q7_Jt}`?^5L;3Q6m@K$f2Y;#elUCD<-3_S zW0!tw_-rF_k^9I@#I0!D9DTfBHFV`rOr8^hb%^@HW6@tq06M-vfcUH*8e$@+SvbHr zWir`i5q9CRx`g8Q_4x-WRD6Cx%58+>Zz2)IH8*S7g$F@8%1=ADH7?MQo=rCtrKI#~ znE~ED^($cK-LY3vcJiDT<=IIk!?HzO5(%_3@WEnNo_x$78Vt`y;V?!mU-=RIzD4)B zF`oZEp!4V4DBdpax@LC*@)uv17XuK3w|~pi3gGqn4Mt!oS0PJ?-S>gRWgCa=^x9_5 zg)_OYs~Tukkp|qi1NOQii0`bDj;ufPopoBy!`ys5A=x2reD7kMgTJ@=pMzlk$?v@- z1L>z(EO81S%EdjB5ge$Z_}EEfp%t*|Yr-d=z1GK|s{Ok=#zdS5C$`cQm9;pDlQ;8K zgi7DxKdA*yBxAq$h*T!dfzIy(Kz`Eml?dFdTHbgA+lBn)i3)RSid{+BRrOf?o5A`b z^Keq29j(>-Q_Qk7$blIKHg9qU@&4?sVgKP8<8&KEp2r2CJ~L(Qz?FX?1*Gvz*zugP zHoC+bW3C`Q*7`lBJ=f<}@OR#;p?epIfe}?QrU-#}G6%hn-7@Uenszq{bMR2B1TQ{_ ziY4IZE`l{Gjlv9xfH`Cro=BGG0NirMOvuo@yJ~p?~?7< z$+yL{122d%r*RqmzKw&Xxcz1C|DVGs*UC4|`q3oIZ(ZMz&RiAliu@Y3k45iR#U`77 z%Fm^~SB4clo7W?D;vr!kr(|Fyxt$+JRSnftRsx~HnCJ`9i;wIQ0{GXL1OT5J!Kmhi z?*3bWIv9ka;#t@B&2CD4;e0*KS!_5A`drANA6<~wgH0vi%Sxv8!A%rSuaPNV)m2@! zA(j@p8ez!;x()&KOy=x4Fhe(LiEt-v3Nr|~)kQb$5^DDDqm-&PCWrb^K|TEy z)tj5)7RaE#_ZOT1mR@lFIUF&cv}TD>Mch6tTZqAL0u>T zKf3t|z!xeNtMZQLDkRS z=mtC<_|*H#)3jz8veo>2SLZ%G&1@Rh#r}ODj`Snoy2N>-Y1+5TAYJ3xpE2>rQ5q4@ zw>>@w0r=MSJEG7g8yqLO+mJfHq~dd`zGI-l)>zKI)I@yp(Td#CD=)ay*_-igBE)Gf zCq+}=sB{_K{$35_S{BX$uVQ@hv0%yoe}5?i@MX0z7EY^Q(&2-nS6Z+{S3~s>-XS8N zwNkFi=;9jMUdW*oXi-?)gdv!&JwyK{03U{th;@u9*Yj(1cV+HWZ7Ji_>g81#{ zBRV=8yV`4ykm~t~(>j5ne2^mQ$>$dpyut<_fY34=A!s!#P;;G&4%ciYiJ2Z;FJg3A zoL_zHA>MF75)>%f>o0V}iErWMONg@yQwaI@j2QB7?*BhQ1v)eljvkw5(Lxzdg(io#&fq<@{Tp2LiJ|`-%a4 zek!1cIb%x@tr@Uyt_|NbhrG}ITH1Ib5>hBs-Sng&Hp`bUMWI9e}S1r%a{XW!GG zK&-aD$&X8pKN<6gPIP`eBZP*4#l?r{FldIkOJvAvK%`5>%Eb>4= zSfW5MDfI5329+!4{H|B)+K2g%+bVnqY{G;8Pm2fpGKA8mdgMjK*9bH1Hm^i4$Lo;5 z4TFi87_>Js4qmn_W{}=!Qu)%3dodC55fPp*aPC(wTxdOdAkohmKjq!Uqkmf@0g1bF z$hXOh)vTp6mY~^7NBZq%7xJDx>8|hrTMu@Ddl`(FP}by?F3%*J5bf%ZY7@6+GxK=f z9VVHjZ(T9%Z5}g+&r_A8Xv=kEZ^6+`4X+U>2)a^dJ5AW&u5>Js+T{kZ_Ya55i9mqh89MZn4mIq{;1;* zElg_cAiYJ^e;gPEjiVs??f%?gmzJmm?T?M$PD$7Js(5TZUFPqsX?+kjwKUT*kw3CM z&w+WlsCENB6N4aqV(EfDxvS0R*C{B}%W#;cqWiAIJW=*uVt+2`OrA}$TR2-{$2YF8 zsvuoC7NOR+h;lqva^BD>sBHFB&n*UIYSD0nu658_NT^s(?iE!Nql--qhp_cdHh z>#)@M@>FmJ+hLR}4pT>rMiX*#VKHMA2 zCL3}+ANlh4*ReU_;r7XU&k$`;I*UFKD>V5gXzyEnsHhR8Nu#nv@A01|BSW&?E}XZK zIu};tc^>=a3^qCUZ@iO_7YbokPHp3upPS52IH>JzQ%Ra1omO_%Fp(sG9AEdz+&!I? zQWUI`OSSzMNdodQ(X$eC=hhLHE;W0OieGqI3|7{gHfaEYTFmyArvMd<*o%R=j{Xvf zE3VH1Q+b-|KFQE8%_{`?~FHo!R(bSScCP`-MlJNozMRKDTI{=sD+Kvtu;^J3)QE&1b?BpzCs1O~U}H z5qK1qO!7S6_3ve!eY9NV$D1cWd222?{(iCG=-qJfR-NF?kU|P^(iRr(pUYZRm6{Nf zPI$PeZ4J9vnjKngM8_|*(!aGm8&$fCQfTztB20=f>eChX{PXD zo~b4GM5;c{=LJyD)k*?VYL`PS_}jd}qb$gy0>(8g@7JzEgk1hmT(iqS?A?kI7%_Mz zikTL1ueHPBW<{-mn;m&K#rPV$6AJA|CcopynCj;idkBZKo0&)qU^wLvUN5sk;s0s; z5`$XzUKm&HRqh+&|8rS0FzA}=Q`y8DL%b*`j$OQ+ajP6!cu=A@+o{yB-M*QF5i3A0 zdTC6l#Cxh5D?8H)csW%gyX+qM(7SW>x*HD***>>uQ#kG5PAg3t74N=ZlCky)9p2C9D{zUSw3|%4ecSe!a>!Bb!mV7J}xY@XdVe z5!oTAsgZV%R&2;?!^!8z)!!Dk)fYxV%;dP!+lISM_393>o9b2`SKk+PE7ap}6eF^O z5xa*Sk=(~kiTmdyFSW39k0nqSz7ueu_VH>wP04s@NO^9tz+9z?m$9gV{~hPG43uU~ zA*3!?{@Gi>nyV>KR zBW7KR%nHY#4TN#wcesa0PvM#h7jf#&2$ddXmcGdh?ugx)Ap(mKe^L9QQ@O%;t4Lrkt-fOfI#m zEHO!*H1iMD7_V%qf92daeLlJC?^P}8mrZ7MW2)4f4r+?&#iz2nww#8`4UE zl5Gb@EG?+EBHB=W*dZ`!kQ=Ea$b4@~gMN{37$yNvUP`WD{%mYzkHI4bnLK`NC7DG= z<2ol1aE1EO;CxG`aks8=6MXeQrAi!Zv#%sfa&vGn{KEncM(bDM`!|cQ18T-PRNBI0 zC2zop)sxG>cn()R4at0XPn6$sy2lPnbV{Fm?My4KtNj4>vT*zVb?)XT;2>$~h&_;Xe3%FW|MXe0gOsqVEkI%4rm420l( z1ae6tTMyu5bX1(4jS#TRNr8}j@?W)#dvr#-om6}$>Ca(lPwFYozew4(F8o_L#F$^u zq>g8Jkp-6ALT^i8h3bhpA3PfMItxWvI76ru=0{_sc9l7yJzeo~PH1P2(!EPwx`^t1Is~}*hL_wfVtG4YW$;+%}xqOfeiDP=d zMEd87`(MJurLR8($tRFZBQHYB7JTyqn{wiNcwDAEBq4?3f4<^hk;6!#dg2@b62G3w*&>HrG1a53WD9m*0K3n1VPIO_}dZHq_wa zaS77@b4mZyyhTNNM$B%S482+F#uT?1?MqU9mrB%OrZo*I*8eNk-!J*Y5-UzQEawv&@Okj1x23XyuUHl1b|t&)RBh}86p4(C+nA>S_MRT-`PIX)9`Ulo`?Cl)2w zT(V3U78#Sg*(D(^QSEFvdCw=BEPhG%Ir{g1>WQsM`1lmjZpgf=T%Mt_478%p zJ;8%%YC$V|hqS6`d3-$N;lclYO#d_3L6rh)UF9@=-Z1Pp!0}KT0=YO)in(|`94L#4 z`TP$QzC8Fz>XYzki9lx>QPfS7N}d9Z#)BDd9l7VJ3YNB$k{|Ffjnnk%8syH9a-fgt zwtculntA$a`5LeS$>3KXup47vq+U8?U~heAu%o>~8u9#e3sr=EIUF=PE>3jzqJ8pU zw~SHfOkl&MIIwW_9>|yU!#w032O1J5|E`wqsA4w4pwWhPyU&41t_Anm_f$uur5?X+ zNl&UQ3htP$qXO&1XgBn=rBQ;y2CG&l8cZ1AqY(jRrQzSfstO=qjf70qvWD6l&fSJX z0$q_b9T8OPhFosa;79wGmdqFna7zjzb z@s5A~Dl~Dkrz5kT5(W4kf-XQ`YUl*C)*{fU!)MVx*J}$!i`j*fD)v6b8lSc9#m{#C znvr(V-k;z7H-47fP>fKW^^jJKF0>6=GH6_z$F*@Qjij8BzX3i&SY%cqjgs8{N!N2H z-20}tsdO!qal;{Su-UV#?%AhrVS_6++>3ezO^wc_yAU+!&%Fm#!$-STqQ2!hzHNdk z0`S$1?SSrk1vJ(__cpq#<#hq(*M}CPkGOq~nt2J6=!xZ7wmX6qh~iE6^jMU2Ia3(Y ztZA?`mZ_1bLsEKUO8i~MPT1#yowr{V2+TU&wb}-8{A}*oW67rAydRf%%NQaG6!JR0LkgezZq6fVBpxeb7 z)rtF;o6pI=em$QYJ4*A;i^=1NhOUjYmX!qfm`EctLH2b4wZGlklc5sAH>R8EsAX^3 z4Q;MI3BQ0JPkoi!H!~(t%r$t`vsKcS@`=#jA-1=^rC2=F?eWMjRw=DT&~}lUB<&jX@HLhN|qaBUoViakZqD-^9q(x54YjC6IYtfq2B4IWrqHu4R~9g z8dxLa8$!`BSbSEni_}c80qp9;jRvpu(*j}=>O$dP-+Ezy*E${KtG0|6?ARuRj9*5# zGR$^^F`{$ImkO4RpnZMz(U-2dQ$Y=Jw~qa&%4g;wAdhc)O^xT>G275HYQ9dQdM^j? z(G;2wf$ZxC^3kO6tgi9pOj~WdP~Y|ZwB?NX`_X$AEjaig3Y|kUG1vQ`h6*-t90y^j zZwIgs!zdBuS8t43C_583wF6TX_EZu7EzYHq&1LqYo`;6>m) z{p{1PIv6;?gyI3s88-{2&v<`2i)5ZlM%4R7uY*-8y;0&ONpDZ zw@HYh&ddUDGb%=>(Dq5u0y5-&O)8lsYNC|1c<7sCs;fEsklC}(71K)~z4qkIcCZTb zmQ4t3DJorS)eglw%~kcr6I4RIE>(b!w(kcB8zuZRmk8+jpp;$oULQ+gJl8MsV~R_T zo0E|_T|Nh?ro^Z3j2~sbly&xc+{lfIHU3(k#pU3jvs-8DBYl&bG~#g*I+-b$4+)f? zNIjdos_0tLkLu0e`%S}}NYOysHt#3tFSQfbKl>uBB;t5}A(iD7p~tG!_;_7SdPL&gk{Rt4dJAN zo+rVUl-q6|U(#$#&G@rXN!0*4v?80MgJq{bjgUS8?d*V2`$TQW}8~>YPC-htH-F}h?XC?z{<`4 z^plTF)AnF&_nD|(*%xtp8F^S)Vtol_8h#wTBOR;6f8U{|2k@~JHXuo`_iiO7_LL{y%ifoJuf=4jNERmqf?G9Z zkR9-N-7g*|1NjJtDBSLOQf7@T;#}<(D+XV9c%!5RSG?v5Q?sRNMS3~I}`fPPc%96|~FeJ{q5CH?m z65(bSm5M>c9T~omiW#nJ_=>!mW|@CmgGNC_1tUKO$aew5iMxC%q#-o6fi2{>cACIr zOH108)p1;v=p|zhA58}oKG9j8zLdKg=2qxY#m=fUrTualwbHZsX6A7 z&RrRr(zN$rHtxMZONAJ^3);t zK7Fb4eTE;%2g9=}j~L_FUv^g@;N;TMh=s_ZZ07J&Tdv#~&5OL7e4(-*4TL~X+XGo!B#?Dfzc4UaKT zAimIoIi`D{(YLt%=@VQnHMsGui{NRd#|YK2S|GZ5%esg%MKY4E5?9OwFj#!sTD|bk z_dEGir`RhR_PF4tguvqNlzDWCLXxUx%Hcw2L;Y0BZwKe(uRx_kx+)BIs|# zR1aH^?TYoO!O##luLpeize^YAabUFnUnH#{J&mXKHaMHaGCzy4al9 zN;?32a9-~yK=$1L`9!deZkfjFIL#|gKl)Z4xmXU=hY2ty|CrWW8dvYXzEDw%WviV%+NUF$AZ%66gTFC?Qj=8TE-0%9 z4{fwxtnbIO@A_M~4^uR|4>3h2ZDW{Omo(BeWftzp=a?-R{oma~DqYS1AA7kS==+SK zLjLb$=<$(-k~=Ehc|vI!3AVjM=AwU!;V77g_pW8tF3FQ922MA_*gh+5O1cr&ePHXzXrfDbLjcLSs-43jn_$N9#TFbHB;-3MqBtZ(eUR&CRZ?)$-M}i0! zF|QCv9J%60`)!O`SJRDMM7;n$LX-Y^kbN{jzB|&w-$&~P#FS_jR*{{+@M}v(uwa&! zatv@{F>w{)W^d#v*h01JR?o`F&H0nSWQuIujFTWYDm|_0hDof`0QXNQoZOZ?NFILl zEMY#uw@&(kKpc7&PC-*qP}yeloZq09u0C9tngku>ioxef9rQh11jgTIs9h@|@ih`S z7`}Y)`J3O3+#<+6ZXn;bz%SPUU!*O1BNj97DLcH$-0)-j8jRyHlj0|dy`*8j7P{Pz zLc&OCun%wLvYJq+6Qu%~X2@0CuJ+6|`Pk}!@-s)U6kprnNB6l@l1rADyRM+oe??LG zjeg8T)cDz#QeGPDgDIP3sAVB6ZI&SEYdz2M>)zTL|DtWkeaKLSIuPK)RdFB$+4ly> z7X_Zy2d~AX({Si)?<&sF(-^A^wYX8cSxx&UU33OgjYN9KVSpSyUv%+x#GMxW$p+Tj z{qlnow--L>`E0P?$$@-(ntAb>u?W%?;wzB71rP`#-(@e9%%m(&BbJYzeOa_he7h}i zBX{MMV3?G@7e+yj5aOUgsL8_<-{Cfvy?Ye`@DZW+Q-bW10P;1@mib-5F~WHx%^*Ma zR`I4EPi&>)_}S~iW%!?xWjAL_PkFnEd(;74;$A-}0{dp!J!)IZAX3U4Dn)2bG^F># zaF`}{vNE+{OkBWILEG&GG!@$Vs3K5(a*Vt?!4^tY@7zZG#Ax0flS#L`4Tyw|ynd9N%t;5Sjd2nfO$N|mH#LUTX18!rT3*}8ecx!SyZ*VI|A32ts>8!VZTfR-&3lo>~-7g{9q?y^(C!CrYnpN`4^%plGm8V3Rwog2NS5W z2eQu;$fryuaxCw@l`CY9)i`V0Z9p$)!#mC^VstBnaPg}NYxVawNurzAEhhn2n1c?- z8Ll_Xz4P5)tae%q{j{|mT!6Q#Y}$G8t%KI+BbsDxFt#8{|A(HLcOTFAV-gK^5}ti* zT+WndvkV3G_!%|cSxwoIqrW$Dv$?Aml(Jd#Pj6kz$_DsgvmmuW_L&3uOx(V!&spFZ ze3Rm=uDBeSD0`pZQ%DV#qr?X1=903It@|`tBe+SM*B0sj!spk|y~`Uo~6;!vS^03T6)tP99KD*2J^hTm zVy4N(vPRw1={awJN~?l*H`lZ0Cq`9?AedW?V7QzaN}{ zd`Ansz54H^rnAXL;8P2ToZ=T0T3c>h$}4Pw*S0b--P3p9Zu|F>8u?@~Swj02Fi`p} zd)(;gm7Fv+R(?8OmICq(X<}|Lgy=mIH%G+U;M~$=C@!WSJQ>%$IPD61_QA=N5$y>i zjy|rgx#8$)8zNZ=p9BW!^z5jO%ov?OjtN!*d}Q|3-5}@Z4CG5~>AU4;y<83=;4C%P z;Ol(}&o$txWq~Z^OWD_No;`R9cS?wFk>OX{tdSACJQ=nMZ{*J%uz$r~Es8ffv$O%^ zds99hEup0O@|X0{Ydw6{#ho2`13byycPG*#bI(4seI7R4p&!%D=Lu_--yO>zB6KyC z?&CS2+U^%#xJQ4#sRH;gtx-WA|8oKIorWq*+FuKD$zjOU77|hTO2(j*%=I!7eQ#@M zs?JP>DS33HZXY;H5>lE@B#}HzY=?qWUi-RXRTV9E((J7Cu2Uc4YsuD6Ce}O}A zD9NDFLC((~$Tt9~Sk#K^m+8k<=Bcip#b@w7A%W4gxd7d?zvfJxI|um*LUldbgnU6$ zIQp2zxj|5r`^u)Rlx*XGW;g$*2_BHo@jPb6Go!u$5xllAy){pEhiTf}IqPIn0_^wC z-#-KiZAxxZ*N!I4N4tq?GV~)}cKO{hz2vua6F26CnR#E`1n^- z4hbIBg`v^}HbqwUeOVYuoh-~fXDh&m-mRPhvM&h8ha4w4h_4uqF&$%>@=9##Q$fen zD#{l~iYpJ78g6uIRT@84B`W$-E46-i<$R}v&$9JDPZOROHQ0LqGkWH!cc~Z#As;YraBx87+9Po9T zM+$*_)E#+WXItrru!g2q7L5JA8-?{7`3QQJti1C1Gu7GQ+Aq*PujZZ^vY|c2D5%x* z;=SLJmc3*3b$fA+Q)4m3Aizg3$_M&EJ^4WS4KIn-F_N8$8>ReYt3Md#a;Lbib@5MM z{q6#vL``U;fVS?$gs8#sk7Goz25wmo0n9uoR_nzb!w` zI-TSgz=x}bBMEYSegpD#d8~hA4G#X5);^PDP@W3!ea~yVRazc5Z zYLD!g^x@gp8v3HLcI$_K3W*@n5@%)^SGJ2~Qz!pCHT((zo&1MaF4F)XtMx4Ci+wAB zd=qDVsWt7LezIIFa)t6==m{3s~CEfPo}N~ zpzug^10wWK|M{-{#D<34A@^+W_ znAvsByF$Y_CU|Ab5V{L`^*O)bvIxznqVXLsYT~)I*NRu{pSz(+VjMF~z+O&!L*0cO ztN?uUpI%&ooL?tUe&c;X5hFy|@X-(!xKB;2hZ9den6D72}-BA3- z=uW8@Px?sSn}wtQ+w9``i6+lh!NTJL&SZyYp)(+KLz+uO6-20Rq*#O{r$`T_mAfx zvA=r-=|2A+9PAvL?)gs&3qox;o0FQqUNfuZYLf7rccV)*B#BzlT|bda*U+7Hb!LQ_ zSJ#KElnkZrjH0=3@0~j8>)m%^_f@E}E-O@roB|%+lz3_M>1CIoYyF!9qwwKIyrUa-&nkw=h7ZuAnLhM!Lv7D##wkDAYJ{zF`LW}gCcd@X(e#L zC6o;Y{PcmBoO7ao%Q%p4hK@Of`z;l7 z2UQ$Ka@WG-@Y~o{sVUDHL<-K~{m4TXB<4}K>!_D#cW$x)jSTH0`4!o&{#@ev%d`qU zVAO*&K)x!I3s>Fpip7<;DG;ZGyb1jtD1s+wA|}Wh-s;c32&7U>u$Cw-nnU891K*En z6m>XnYsnkrkb-^+^&I0M?fd}vASQ#y|9g4=Ni6)`mx1u+ zx6T%}PaGC!03Y4#jR(lSIUwJ+0$rB4!U0Eqh5L^d%-^uDZCTJ%K6^d(x5u9E;A->P z9y>&G!iuf&Yt*mdng3AfLQvF^5iwQRFH%eSr2DW2jQdRPGrooWs4u$4J4}eu$Kl=AH7~Yx*nD4*UgpJUYg__+c#~Yx zAp2H;e3~;8LA#iKLboBvg^@bLYQ%ITQkHLQ-n0vnfpcRt?5Z9Z92a(ALwDq9IsERH zPAUHqdWw7YdoPRD2y9^~orQmW|J**OoMoZ}-|~43iiAqiivD`dXX;>$6Yoj7=x9;? zoZrM#Dr+=y@$PpLC>+(&zk2H$oKg|> zda|1fAfIUa=te%Q7-_WMCl%{jHbX(D3Ytj`TxZgu=s%;ITN|7E(dQm0w~Hl1^9))0 zqXD-4E6$8s6#SwYjIhWJcMkv`Wm{$#$i6)wpT3L`C)Nmx2|v$+P`g-$mO#iaeqppE zVGAXv2Tt;@nCnIb4=O~XA4;Nxwhi~q7h-;I%UCEP)pz-^ec^*yUIvhl)luWDR0ir$ zp=f0{0cy`SLzT;Wy$;*Gw^{`HIY0jV{miqtjm%49Qs~MAp^=|e%HP}@tj`&~T)I;Z zggd)D0em!HcB4V|9Rm5Z?2AOwmRe4-_3W?cWr^fCry5=x)G6ja4achc?>B6B2S?hO zESHGRTZS(?_$}UyX>y|`0SHfwOkz{FO@8h4bw$RwhcBcEZWH>z7p) zA!|6R8>TRXx+i{V%5^g!pX@<$$F>v8c8uE{2e<_h&D#cJZElp7=bqvrI3&C9Xq_Qc+yu1Apm| zRnNUNBGPXBbbAj@(q=$L)))Q52m0u{0KhpDn2q%nf3k>*%X`S z7l!glRlVFEk*#7LPx4nYCQ9_%oAsA@At8+LBFPA4E96B8V$alE!^HxtpKdh^>tg z0Y3WAdlex2u7G@4Bjr$4W+)s#&g|_QDeIPg)cGc1JiU&yS`8Owwv$jCenR+H9t4#=eds!v9vs%YD?YrHj=Gi?8sJQjHqv1ij9Y_Elg$_38t8;FFd|N?l zEgtIMsFj#&4tt^eQc&M&FX{%6U?CSO_iQW_^2>NjrhYh!W>S&_8`o39D)}B(J8wR( z-xc=qGm*&$2?rowjn9gDiWZcLt)FO^1wF<6aC74&2WgM>BRR{T)s5PSsN6F#aDzCS zZ^_AqrNNWjIlt{ROwZm0ElE$YH20yQ0eoDah(Mnm`3uPBvV_b`c3*j2g!?{<=>&-r8@GEqpkF=bXQA*I56`{N&EP#B+*NqOe~UC=^A2Vc zH<(9)23|SFkpTnXqt!Y#1Gzr$fqb$a`BgaltLe#Knl=`(`-fJdj?o{FR~U8dd6NrN z>CnSyHROm*Ym^gLEDmPMX|>iqxT)r>WwyPeNiw(8QuqPnTL?2_<$5o7WH`V`s@o@YgTfUki`0M)45UsUt}+1fwa{qVqwxKhJ*fog2e_J3*f^! z;RXHq_WVzbz`=$t5vPR_G{e1Jk zub;@|h`TrP@`91|$9ph)B=}q$(SrF%9jbRWGhb51SyMv@oH&Y1w0p^>TC&7n`5q(1 zJ6mYl@%o06ZwY9oGNO`}_I{4Ri`L%M~Z~ zq6(U5F;VV$`TT;M*JOh6&+@=9tM1V_!%AU~+X@32)F8S3LzZoLBKF?e_L{SVW^+|b z473~Hm(G`y+V@wN{R=V7$*g`4)kc%o_%_PvKLg{rJ@eDPJvt#i%#2`Quxtu;Nyi_ zvVsKtpT1?00DSkS@gS7v-~7Um|F=Hj)ag>=QQgoLeHf~(BFOzQKlZ|CCnAto$sb9Y zt7`<<4kN9@*hfZf;JZ4-&0Jpf=b;G;fWH#zMlvF9hTEtI$`7i0dLBlm_5vrSRy&vu z#*aomv0yVvc55-6!lQHhd2e>K#nZE+#z2DYfgIpt z91rOMIX`Tm{1R5r(^gsOP<%!=tL(pD*f8`a`xeGRA%|_YvzAMFOOZC0yeWRVg?o?5 zWf)K6G-w`&N|^nUR$08c2ekxW4|wt*Q(*hgIm)maPvx*~K3jr2IH|>hmagTd^Bl}S zy)Q{};c9Y(_>;8#C)Hnz4Vs`oS9-eMjTFt7ikO?Bky97Z0(@|Mrl3z=A_Vf;R`$HA zNNU6T=)%*TP_xB3U_YmUn~n({rs}K5k*`Q7496xD6Iyh;c3%DAp!2d0V=u%VX9G}B-j!ei3f`5zxV4Szo;!P_9JW_K+rE=7UrQ&xc2 zbl>YI71q)cDI>&-pjpvJ4aDKscviknCC|P|&EVu+yi03otkxA~2FQ^}D=E~_jC8ec zWY*ztNG16O7)G2Ux|2@OJ2mXs>j;9>qJt zEB$32`wR6eS?>ioX9j^@euZn=cUS!^!9NJOlMu~;2UoD(l8_N3c8o&Z zWGwUGW&I|i%sE=a8~^R6mvcb*MYKOkW9Ox?)uvYYL}0z2nRptaC&#lJ+Na#G&R-YjKKqQE!G(%7r@5}B?tQ8tqhP)3=2~t9**Up zjJZ+}>vLz&VbjLFu#AqwjkYP;u*)HDW-!0K!h?haX&Q`e6035%_knNY&yRD)Mu|^y zT#z5vfqVzxSw>4iYq(+RWtPFF{-3(NNAplyr8Xx};KQGN1*DiF?8B0NuK6R<8|7GP z3L(OK83_2-vpn_M;CS@gczggK7oh>@=UgiS`Jl}%UWkcIKbpzk2{-PfTF5dUn>o7s zaAd0pU5+k5Q_B1@hV|*ls{43k_gOBa&`q0@@Sf(paPx3hwmrR?O&Q2%$6iR`wl2n1 zn!QpBzhaOhd~?J6HF$UhZmvx9*~iS&8Z;VhL!Q%RbITP;G~>O8_S37`gvjZ@e-9pgjngP0BB$eqA{Uj-R^-*%e`=MURQwQVk85Xl@cC&f5ySk@0a5#Vs0>c>Avyq_coR<(P6(`^p;-pQ6li z3Zc}3S2O8t)|SX=NO`OAEr{Oesp(Z_W_gJuz{l_r7lgf0{>CT$zwzNB#Q2DZNO!+9v!#TdqH(y#GIp=l zh6=oN4ATESJJ}bS(%Mj$DJ;?br6%iaqT0~@8cz*Z=VxA7Q8a}3&qHwI`1M?V_si3fp=L zRujtKGA(eEaCQW0{zFTAX@P))~WM5>hHq<){^DmBKZ`cV*S5%#x z5WZQf)St=$e9)-Wl_2}9fqVqATc^T9_p`+X9z5s=g33j!=Z7xEI(mp-x5y^DZ8BBS z^on{Z&5iT2>%$@048A#>uxI&JRM_rj}G@B?p~fAq&ut zAxZ-JddR9j@?c95#8>z7fVD5Ame|m6@C<}nwLC{^kkpHkYVhV zH*>0LS6hHt=~)Jh-seoqiIjhR|1>{0+)vTW$5>{aiUdn&;OW~;yE%&!CU`0Q^MKA5 z#36cozZAte?M}*R5q$APo2&XwA2Kg%J1mx?Qg$C097TXn+YpqkL;f~DuK#U*>M1-Q zV?xKScI(4!HumfIDAhZTDYahrgj1GN^OXn^9pAxD33h2;oxV<8AI~#*)VH)D!1}Uz zKwY-I@o5DEc;;?p<0;~-i!XKaW@&*7Q+N;W9h_dpI=xtA0~5w`c|P^hj-(IQy{>13 zSAZ_Kz0FB1GY5h6G$Dw-6-lA1QoOKg3uZ^ip9UHBPM|R0>40v_{ zUnEU{4|V~`2xMO{kdKtPg>T&m%Lj#UcJ{T3A2+TB^z@7MDJGt^OZx7cX3M@TZW9@$ zMvGefv+|2_(*PgO#E875Ym$8(@dk&1P7WZSmo`z|9SZrxYXvSJeN+1Ecm^01MxukW z+N0|~D~qi>%g0NloQ{$a_KTG+Omo1&7Jawx8ZTwu(I$Ns(C?zq2Ka~+RzdF@3<2`l zxkuI)ZLKsz9D<3Y*A0D7I}v716b)OZWa=1^5fgw z9}`|O7@I`@EW#TB2ap!6d&{enAC#NK+4%j+AU*O(vv+Mt@&)6eKkn;-z@>vnUNqB7KorUbX5OXIf z@{4i!Ch?AoPvwL|Ts6}>aYb_pnt5N1QkD5jKT?vDDWz$#NNuGO1$l9gu2b>OgaG+& z*jVqA0_ya_vkCGGY+`88A#HsiMIwh!RDb;0sQCJ^djo+XSOJzLwuPlrlawI6iv1speolwK` zO#nU}7%I?DaZ~-@$3vcOE2^a@Q?~D_ViaoXyx2=o282q#^v`osEsb6Am@qcHNVf{p z1Q-7HLB^zTfhkepkqS}Q$>kj;^cUD#hF1Ub{<*zmPR%Ws?FZqhWuE+)|5orcSRdR{ z6$LFFw5ZSZ%*!vFdAV4^s-EXpuxW#<(85mW&p;T|q9- zIH33zB$zdGEiE?)8O}tI?cUzE?v{#Dk?=D|BFK0z&WfE5d;FBzs#mc@6lMzPlevUx zFyp*m)$8?tSSiaHHby1?*Y{6+^O7V&M3?TNUuUA#%EX8?g-GMAwnxW&f8vY$c{_tD zi@MEMugG5MsG70k*pMVx`Ec@0dGk^^Ew-nj&<$8TjF3|3cNU|$d zgv)AZI1qmk#vh@B?~Kes`#Amn_4tB~ssSs)47+d(GGb$q6Gkot%!^@{X&yf^R^WNp z{G~NUkPBr-jmVKm7VS#M^5HsPd-sb^GP#uNo_(ZG^4v^5jw3=QD3V-)OAaq^!*c4T zS4(_YuceO4g)M780DK&LnV>)YGJt$MFBbVA8W$0SF^;LhX=^#>t>5_f*@L%R&a_&I zAZNck`1<<*>?eY6C%kEKlYz6e{U!an^VOJ+;zqt0QNSCNtBSbi`yZ2 z_d}QuHPrlQ_%Yj|P`UoI@8iWJ=cK$IF)Rt@4tQ!uqS)T4*Y#R@51CQg zs7RW9bYO=Gy}yuTvwJHZ?Z?bGhZzsl{9069R(#~}hiA^U{YpIywDpWh3pk@bT!+G+ zxIFvFij{h%M>gO83TD8|BGQy0&C?uut8epSeYHDfck0^@#lODYgx3)N-S@ZoQT=c8 zLz%$o*$NNtuF^796cb|_iHu{PI1Zt)!3K)M}@ zsdwtE>`MX&WVi%r_&@hc#S!-rb6O_SOc^lv;e&XCuQ-=bX=~gaeCIgaOPNym-y&FWkJ@Wemg)iG| zjQAy=$e4kA;RR$<+?lBbT7|U%Df$z~WT|v=hkk4FXILc_&+*|GAj7$`aM=?4^ENp`?oxK#qL1%RRH-|p~6NfQX4kRAz+FhV|0 z3e-QXzGY|-SQZsJ>M7Sl^9fXJuKd|{$!z4!?^nMLgsZrED-qiE(~o6m{MLJXA@-++ zgw83-y*mB?A1tP{1IWH=Am5;}D7=K!*ry-E>7TLuoZ}R0Z86iV_9ywJ10{`lTn|{L zM_+6@z0-)_N9=;FhsiarbV{=z(N1NOk8%h9?ke|he*ZlE-juMhgU9yFkCUip)~B8d zG`O~*sGv}i22+peJ?F>4zFy(Cj8wcV(q8p+OQST3%RBr6b#*c^z(w^!YU?365a2V! zLxuY9zQ4^6sAq5vl@1G{)cc!*fPRNq#Rpv+^y$u=vyN`&ly1hltc*OxcZ{$&Se;nA zuO)>`-F$wIV4vx}TwXW+D)q6S@`r8Xzr25%AC_<)(yvF^>5ybG?8`D_lipuEv^9-s z@ALz?2%mZA7I4z>OWSf8@~abylSeB%*K5&uEN^yH@Gq4<>P2+n1^;b+T5ci#o%gr- z)d0oEl+)Q346k0-t!y%Hxy~fe%jHz?UVi+52Jd}*7y{jETb~zlK4t+b@R2e)5Fh0Y zGL1zQB;VtWO?@#6)N8AM3FJfkPREr~dPD!~wZJQ^iHH8&fiMF??MSZSJKXqZAJ^Jb z%MoP2EQd=e^jGwnMuXn=&>85pQsepogk6%9U8-<^k4~+$6J%cc4HniSwGhn zf}2azpP=pSzM24i%%OROX1sU)bIt>4yg?>+TJMbYd@T>q z)CnYYqh7&uqHu7x^l|6F3ZQ967)VzmkbS(=D|%oV&C zfDgf974%KZ*MT?kMNE)I#9w{y{^JX+< zYKq{!flrvdc^J4^gI47%IkVz0Iwt?nG>~st_Hvsi8Mc7jYL=A}arNb5a+v?4I+rdr ze#4)qL#I&wPYxM1?1wocY-`AuJcy?fx@Wl+-%0gezLSf~3}A`{_~_x{CjNVQ{=L04 z0_9gdjw*|8{pRRlw&GH*(^inE{i$b;MM7k987|Tf)6L^+;^(PwBp-kN3jX=8C`L+` z2!%^Ze#&Pp)E~gdzrIWV*Y{8J8!i$*CJ;S}-O@y6Ewu^Sv_Q$VpKBeKkAl15c+Rh= zN8Hr?g2W(j>4*nX@QVn7iM;j){rq0tE~SdLPt#3QaR6V%s0!#$2bTYBeiv%X&PNlF zcp=zWL+UER(A@QH5LQ2SoLiljUspLxGo%#Km)pK!K1e#Fp;P4VQ}4A@wJy}a;=Kte zsN0j`bpMz4PxBjv$7QaMnF=aXV0&%SmX{MjJK}3)f;B|NHq89YQ)CytvT?O>68i7}mtlwjZO3{PnRs#)7`*L=RATzOl>_U#3)-=P$MtiRG&jpE^pewYASCrO~=3a2!3o zj5{~FL~rK%B|jWsb3U6gVlc?m=RDN#4aM`9L@U>e|9d+8lV824M`%<5JN$_q4_ve0 zT7M0i-^a|(GwZO4i$Akk6NPbWUqR8pKgHG%F*dmoc+G9q3N;Fe!T2i9NJ`G|D5L`N zBMI&O2y*iq2lBDv1P$A|MY@F^LwH8iMnAmHu~F!Rh$=Z6vKNqeSfMLajsAZqyUU=e zw!aVHAT8a}Eg;<~-6<_0-Q5k+9n#&1ba!{Bgn%?ihja?h#iRE>bI&|44)4zlpZWgw zs=e0Qxou58OKZ#@MN0?aim{7F+~F7ettCikp^j-If$uDkri8cWJ%NGSdV$_hCA%=4 zZ)`hxLSj&xK#}%)SMpF;FNC1;2dM5w*_#RWgGTsyj#fVhMw9E1#j3$sN!W`VfR8!j z$_r%QHz4081&-d)TMLeSbiri-?$g9K#7n%DByVjN$>(lGo59{4gr{(WG+Y{YThobUve-??bvPa&cD3*i{+dYgLH7OQlbM1Bq5JzYdI4G)Bp0VvBIl1u^v3f*PS$>` z+TXRAJzLMi`V_)J^sH#sP2zf_7kItli%?iEVN^8VE0 z3(S35b&3Nj!0DgL-)-S4HBBSXGe z=mqWB1pOans?-mNwj(^I+J!Hb6n4gb8M~oeM%My-#5idFAh#~ZK)&Q%gA<4^fx0Dk zNH#icv&m5=k~MfXUM-Gc^txC#mRgU@Ny8!KNSN-ES98RAJ0EescZuYt!l;`zZ-0nB z;rrivhrjvtXOU@}qxG@}`{Xd19sla}BglPG536#7gl+tL@X4eSFekX6`8^}(#SUHA zODi_gw4k_nJ6*e154R-yr+bPm03UlPSs2JZNT3@F2=dA#-->{RVfaCwdPXF@5IF8q z8R9CFj+J{DK3t^l9nb!O^s5{89GvW>T;=*qE!IWs49a@}_E(HZ3O%us%s}5N2MgrO;Q#7H0jEms!9{>YAj~K(<(X_pn)?@S8hCNl+?3NWsHzveXqpn>;U-CV>_Kd z_Q3=BmK@Tc#D1=d?u#8jV?nG+#(Q8&8KH@Ub6jW1&TSH za)Q#}I;n*e`=PoqB~trP_seg(Ld?rmGS|L!X>|j99C#25Ap6jOeER{t*-@=_vzo5! z{aINf5-eXns31$quDmspgBD2beR_{kI^ubXR`2D;?Il7M4$lk)^8+J>^hIRjMdyaQ z5%8wLo>s*w%MsK7fzYXhRfa9|4fBy_Q<_u_;@wfoWl&)z8@fA}+HGT0xoI zcZRjS&16GojV!Ni#IEmYmEh@;q@`m6d)iN!VjH5`;4BSRgB^jzcsSPb_ zBWF~2r-fdufV=a(9w@(g{be3r__F95J59C@tS^z?j=g^5kwg~Ist_a3`T5foiRv5| z3K}EU1n-4>E}Sx=e^W_wG>70Gd1*5|sEaoF$Jd^O1hS6~$j1%&!-GS;jnJD3)ud+vGC91*$uBpBV{au+Dnab}tnJk9E(S5fe!F$>U$AEq4 zI5T+~mM~)8BAdO&nNre5=Q-ftq89iE;Od`mDFMUgB^J>rKqI%1N4^Mz{~?q5amtIa z)5=i3#PWw^*4!(yX@Kva-AMJRv8jzkzmLCB zeyzg9_-5?JCyTpjc8eJ1I(h5;mIS?;23p6_WNISB_7Ai+AE5l~SkWkgJSTIROi^sW zr<{pU_eM=&iE7VO=5Ie-!#SwZzmM z!1qE-1N1`yVnDv~57=VidG8>GUIlJ8Vj^z(SDK7}xf0}QRmmSAvVKTp1v5D}5XtPs z>=c?v(m1}jf{$h$^ih2He*3|>B}@Vl$T!49EGeliger7Nh$pFtZ3Ul`s@>sLaPf7x zA?rCmmJ_Bb@DGodhlT%a!4Ul{T@cdFG*X6Df&sHI?@4FR$MOT- z*1a`MNq}S&>}v4vWi`tO@~J1_(^168PEr|43@Fq&>#(G63y1MJsK^oetv&mKlJ#ly zANsr>bWDfyeX)o_G^S)+1vX#nFuvP1Ob!jNUjX>P1mt}{e*PqY@?#qplp7{8_j(Ke z9VO&AXgJDo>aIh@3vA^lL7r(1VZt<9C#!Zbsc1{Ziw#?;W+;}+5IiT8El)#_(4X}2 z9sk>v{CE8MovTRG9Z&?}5UQ(XbMX)P2VI*_VsY&@PqawyQaR*pKML znI4rxVUMykS(ooYNlmkC+KIjd@R16>JpJ9fX&K-nbXb7~*(VR=V~6N})p-)RAfg1NLlDKr?5Cux(~3Yhjp*^&3Ww}2`L)w~ zg9h14y~K%jQMV>RpXR_$95@I3LxuxFOGsI8PoVk~9iI{1*O#yg3)8T&4AiE6j0bPx zzjr|+5exa<|A`>t6J(!x&Z}HcxE2-IiT3IGokjZ6fSs^xVV76vTu!e7e0b|upwEvK zfPA|H_v`3f5{=*`FSIM~YDjIk2>M;vNUFd#vk(mYICX#O(hOlzW1jr5>k0GFrMtr% z{WUJRZS+kWjPj!{lZwdqlJsCK4=7F=m3Qo$03YKJ5h}>}DFXR6l_gso_EFh`N?-i* zU0ao9eVl*@LPSOlL4(J!gb*yTaMq8@zCtq{J06{m&{CWOIN~YR5Sv+61`K!J-EcC% z^LK^CIHf9ETY7VngnwG(huWleL~`{bCas6A$@1stZ{b%X0R=Y3fE6A}$MCRHbBzaj zr4H&V>Bx(Bo`S2m%-Db0Pq-ir(7*Vn2jputz0zxKtT^6A^bZRmpI5v!f>f!3QqgnN z9_H0;uy8$juPUziRo-4s^m;2g(<|Y}s9YqBUD=y48{LaH#$~|EOYntzm7liOw+FU& z$1Vh?A7CABg4@Ie7V{FFeji#P@cxR4c`Hwg8HAu3>!}rwp8txBW+Js>LS;OBd0UBg zeh-iz{v#44$oZK7`4qyn5kJr|D8ASGWNt9r#Q>4M^CY$G8knxUena-4qfl<1cpQXH zFF%6v`9fiQC>DUJS@$K~rgRuVc zXLV5azuljDVXiDnK*H*#3K~p*6CIg=crdKGj!8J4EJ<#9XFE@wk(Sd8auAuc!f1ep z((Z|4+L0sYRT{YLYEO^d=L+BtcIZZTI*Tan_6YuBFO&3wa;bUQ#rumnA=(#?9`Bi_ z;HGga-}Sj}(Yd{}zw*Jrf&Hp)J~4fj_*db8h+&;>f8Dq}1gO1zIhuGu>%@7k=rH0~ zbft{LZ&NwOw*PN@f4jdb$+QiUjBd2EY{&&~Lt}@}eBy7;7TRaeD=mIsSx_GrWwOYZ zYP0O^aAhtqU{@}6W_u}j=vH-ALByAC4k2~|@G-?mfPSTh8Blq?U{?~kLOIYX#rQcX z`RKm&<|>#FWmOSZ{04Ski^#bkPccaar%StObn2b3;$chy>(cEAZ839o&BtZ=HP?DS zARqWhB57`+AAEg)M}kLezD_~EJ`u74oj5sKI{R~e7tVCV_0?XEv2_IAaaRpwjxFywQ&@ z06w-lXCaWA7fT>tx-FGS`AOIf_OWWRmr$x$v7)9;Ab1^5fujSJ5mnKyRE__j9kd@l z9zQ8{HOkhHk!~A2-2As!xxKik7`oX1TVDFxywnAteip@k8w2mZB<@_HboxfB=<`|p zYvIfk+0W0u!#+`u)j$FZI%;DhnE3w_mJ1bIhCSa!YIBXP(r3PIX}k z%STZZjV_Yrrgl~9geGMw$(}2UxoYm7)`Ff}0FPZR^`Dow|NP+hobmaW|KHzpi}|N{ zu>y*3*}5>b@^iC*K{wuSXxYS8lY)Jc`WZ2$q60;?OLykN&@XUe)qr z+fB|5Q~t18jgBff%^;KBk5|r0omsOBZTv z9TPylSiPz$oMgl|HK#N$P%n$=)sWUb{9b-^h2v^g||)eU3oBlwAm^44m=!2{TVw7eouvN?CVtU%nvITw2!rtwFX>A zZrO6&BMADdM>FKe5?w`aKL^tqF^Ja&NYTEF^8eq~p1;jYmghxY8jTD19TuC7iqqgk zxZYRA{LB>ayu8WZ_X$^}wARKYzzYr~K2SDxe3=?iWi0FSwSz0wMl;WXR2;~J0r=u$ zw?S`S2>v^I`KG$RZ>O8{*yGn%=%*CB;zuv@So_}njUWvIYi6ObUS!Th=WQ5O(c{F8 zCynT^X=$TNUOKYE8g2jw+CDvIHBfw=o*m(7C92Er8An^6`AuL@=W?~>-iopCn zbfnot#YP|)O#`7Y;()B}*zwEGf}t6my(J3nlr24|@e@8AfX8L7`x4~%+<@X6uk5Q4 zDr5YS*`=4cv258Yx2B%CA`{seymqC|~z8xe`TKH!2HjS`BevJPtfwi2p!lT8BTDK_fM|s9ZNSyZARmORQ`2UV< z{vDiAHPO?_2z_^h{bx6FZDjC+}`3GN6SRBC?{{aZJa586%!0 z!FV-4bk7(P5UNQ$(yhOZKYC%P38NqiNzu-8n)}MXPajG8CL0zGs63N;A`EWrI8eUj z9T4ehOoZVxzl%_YI{EdTIPcwaeA<%!U1{1QT|*1jD=$Tmx{gJ^`1Q*a)3+wQa*@=> zY2-u!_^8Ea*g^Jr0{I5i(!w zP3CLe?0o7Ib|Q!dA_Ht5?;$dW8)q`eB(qRRuHzZE)BUy`v*D0b!RFk2hOx{Q)I@`$ z&>n)QVb~Re^^^X$Gvsf5qUHX)*+g?%!!@mG`f6+l#FJ{4D_&2n+lu~sNbs;EU7AJwpk1mN?u=!XH>hYs`K=Z_5qN`~@CU$e^% zS3{bC3IWeeqTPR(u#>4lic)OKfs8|?>Jy7bnpI#Evw!C0wm)>1j2GLE++bX>REGBB z8Y@tK3u7X~Ta5`ye#>BKdSQ)9JU?9fdyEy`!&FM|o_&Tk{os{{N9OIKfx5RRkg}yl zrZSI4qHHspE^PBKc8IQ|0H3KL66j|dF@Sum<{`-;U0LG$1SzLKx}*H?egwgocBGQX z2KM3)hLgqWvcZNgb$lX#P0!gt;kP*q@8S;rDTq~V$_1tfNw^5Sb5H@U9=Uu8k7M-l z*U3kEBrdq(+2LIkYR7J;wX|oSkqUjfoEr z1skVXdDOj)RzZ$+FUd}gic_6OE-e?4XHEpl4?gwPTSgHVZFF{LE;)y0>{J30p;&+2 z#<4`G{%7BS+eMP6u?DJ@MR@1igmeVTY|%p9V9K*?Hl15s`hP<7qO6AERo?Q{?A!Td??q>D3diMa#n9{OkMM zy(iFTyiC;~Ns}u{o9b?2c5vgm97J|(HHy`WjCl5Keg9T~g(XuJ*1hE}V9SN%|1=k{ zSZr;a;3As#SXeNx`KNsm(%uH4efhJtMD^e1MHEqT_LP}Yai7-iJImUnl%4h2Lm-Og zc(_)W)a@hqCsAuzry!R1nhpDp%iq8p2;#maV23$?zeC;=XFV?i2R`=Tui%yWnN=7^KRE0~I>Jb*`@# z$#tLpG%pOTRD&SL7Y`KQI02L3)rd<~NMomSq+zF}X-ikm2djQ!{hS*?L?|-ZCqsQ? z2cH-E$FAQs?&&N%c*7VW(vjlVeVOH=OzVpFEarUyr0_}Mq` zWswl-771+uax}Td9ex{kWK6efm^-3$fi9JITZTHa8`vEEeR1+CPJvLZ$_VwEfgP0wcFdWJ!3#wpoq^RG#1PaEs8~ z8^!Sagih^_)5O7A`Gji?6p*A0R(|1wiE)mjOPT*PoS}<}?~Xfhx<)#iKvd*USIQ+TtGiUERg3 zu`G`AGD*Y`362N;8s{6jlgJ4T(>xg{G{M)5|9rO{_{=RBSRKL7iKDuDF!Q%tV?WH4 zpyPjiJs&%LfstwSoL{fSIApHN4|x*L&Laj#u&4>rdUt#D=p`x!>UwR4>w`d|dJw!;ULZ?3n6!|M)_kWk7%Y%>MiM_3ZD{ zkl{g^TBfae@s}ilX%YT&C#`zH9NJ#NxfyiIx_2hp0$I5eS+_>HO?jz=0qtw(Z=aWq za&GfSNL{B!-T&qNZ9TuKU9n1@yt-LBY;LZ37T@hU* zWw4vce@@tyQdK@BnkHni0(=UbHy~`B_|v&t{5QUBfeR(qFQNBD>YoG%X73<6)g*o5 zhbxZea9aA_?K9p~gs8CgK_`K|Qe`BhK`3*o zQa>lZjBge)^uj!lub+KrKTI+dy05V780Z>xVLz*OK(`lxdA>f zdLkB(eN{ldVHW=4qp^DyOC5ZeX4Z^3;!hcHkE$IqekUFj4h)&6vaG+9&6&xCg|uECv9uxf+MX~S2fb+_4aqyhQB3E4~(JiTlMM=*?BaI4WJEQl`k2_ayP2Rh*5Yz z+bVaPOR^WG{+IW+JU<@B24o}Mj7&K~IlMX-Fx;Ay7Gf+8ia(pj|Gn@zJ)yFiIDnV? z0?WndR?uR_Y3_D?ChS77zj|#RQKjm-NwBa5_ErL(ODFv__;6LIy*SwPmlcZ+QrQt#z@c*G~|ZC=S1vxp;3Yu3z0xR zX~iaKI0CS4aMIZ-b)omUSfN41@abz-Vhdg<&*h0!i4LdczzZ(~Uf&Q49tzVIXnkFu zE?DS!(jTu#rCCMC5AYS9q=G(mKLdJkG+&t*BM>uv+-bpop0;M57jWTcpGC+*4QIn# zC*BCr?0GW z(J^Ulsma{WM#wdEv!dU3(Qeki(hy=P_wIlSE2U^6|I#_`LGG||T7YC&NaswXwsa@} z@DbSC27{d65Kw-iS{_N4oETqFAr0P7kEXMcQ}%4bcM-SMvBUG-pQfyxGK0M`p5Mr4 zY1wtgU`P0*VK~9C+7fE;vo9(-6g?DpX<`*AcEd?P+sUz=bMq?VHmdv^Y4NhYSuG9| zHraE2;SDj|Js~jamYT^4D>xGFqR1*rWz2ufOM#wPJ|0$aS@14}hXiXcb57 zOjUyABacq?z5F-7zs<|nM0*db(|w=G^*2YUZdksS(~sb21SOMhjKTrWzIUCeigxrf z4l&b+6pblNxW63kZ*JD&3!?KR8I0a>4o!;#d z(2fTBWHm2;=;$2Ijbs{d;(AXj8kUQ$Xi`x*-_qyzBFhkVNQLf7cNEGDxx=ehZn?3l zu=sx~yMK8stPa6k)Rz2GC_h@k!(A1kh(pWbo9|2Qty!U-c?8r0HDzH=7+)3WrXX!T zLlQ$!tqDdc`YT#0L{#PMeG-)b@Q4B%Ksb~7hv)cT-gHxdrU;u3geVw-m35UbApt6y zD-UU8A~gbDaGD>=cAXF#ji?`6DiPR)P@zJwr^SOLL{g9sqk}vg9ASm#@W1K(Z9Pjy z;F#^JnPyMFoz8B*>CVPjKlamK5Jh#t3jF<g-D9^AN`~-8TFE+Ass9c<#NMk0qR?`_cg4 z;i^9fo!_6=(lU#QG^2SM zFq@pie&lrNHO+A2Toe9I{csdk?(NWLM;jm?=MR*pR#Z3KoR{4Y<|bhWSiF`dDDN3a zml-3mpMCk*_##Y}@5HI9hr$sXV_%=_z`+f+dnfYlD*cq+Ce6Wk2k_DAeB=YUby)$* zFX6Z&Zdty_9qz+0r=UIUnfx9(i;e+7gJkH=%FUE7)(iE*k45|8yav{RFPzMgA$U1c zR<9Qi5b0p`?^A=ffv4^dlwG9~^;7+JT5hQ-{nzdQ)XgIn`;N_(Ta681=;2Jpo)QiA^4*6qK|%dK?}VhR~!5RUcOf|Ic_j|9Q+C5!Z- z=op&wxEqp!=~#QfM!yZb%U=6idFw$X)tplV8<1!%q& zxpleontKo6;p|c-gB;%$P<#X$+sYq}c-{=~jGy9V5bCWm5>|C0orMtalQ|IBCvsn4 zf6evzQb;)cUMs$mbn7v6cMs)JxK3M%Q_K} za+u~i!X_s!yEX5<;zUR^@D&NL70$ucswI0C7z!+8nvhNVccW@#S)av#PI`6|N zT(9D5DOmhaum0|zgIe6DT^-P&7v#&gpI{)b_)qVUznx^uQYpFN()E(4e=nOAcOpi} zTnF+o=)Pq9H298*kpw@A%pR^Qex+y0P?*%Drm_6@;QCz&INO`{?ATeo_a6|bf@|m0 zuuj4`H)aqcezptcI;QFw0DNTRydVr-{&WwwKt6RDHo3ISPtIHOO$WD)GJSn5GsiA9 z_T7Tw7Vx&r;Io<-#soRUx^^y&U9oh0C`UaQ%~(OsMrt9*tjNgRM#MnAr8Q-)Oe~Mm zXl8zR-?vK0;}&RDY?`0w^|ya@J=bRe>kDUjnsz97+99Tq*9}D9PN@dU} z1$+sh)i1Iz&W26mW=Yf^0`eJ9oBdk1(k)3f1q(c&%!R;{#25ET&BY$64Q6}J?-#Be z4SIvrlJlmz!Ejwq>j9ORn#(SF!{i(aJ8T`YbB8U!$NpaNpW){}KLBM{9So4~=|dGR z_bTT>0+$5SrrVw64&!1r=RmGG$#vmgQWcg-3p&+q4~}?Rq=^P zKTIXlmJeJi$SzjL&+>N+=SlzE)^G;+IF(;Nf$W0?^0{h@v>X+W*Kv3Ax+wKNm3h4F zn8@T1+dE+S9A&CBUg9+82-Wq?tTwTi`N$Tn9R*uo=lqW1t94S^r3!L#$0ljn3DX86s>{{%i@nX> zo4)B_aOpjB1Na~v=|SH!4+rFn>79QyC%_NUO<8Dui8dPj$S2IBPlpY~uD!g`%FLck zhj3k13~nt2L3tV_{;BN>wTv)JrG@&yn3W7NSu-*aD8KFjxM&GO6sd^D+1x%xhDuep z&{H4sPq&>Ptk$1>%TuB&<}%Gbi#Yf;@D1gX6mE?e?WtX(mUk6lkYANck30cB(y=>p zkn?*9K4BDSEx+*~b`m zRbN?=J$-8R(uN2zm+N~zn>pT5vwf4e8PUoC7PXrKI|yqMS<)v@>@N>N(k-ms#%&NA9wZ2Q50)A5qL6Ni zcjdTFV7)*-7z_ot%_JFlw6Du4b*%$I@odg*ByWc*2)y zuAo)al=LV}q+Xg|Vd$q2B5t(!1AI)Ry_+EChX>?K@>3(QBY6>U&_T&aJ#khq7s$f*?m&us>kKI03HHT_H$ z7NiPfpOC~83PJ%s*5$4=kbSR#d_Q7V2?a=k;2-@Z&rqXCBU5&y4Rs)4hOwbyKjwpTm3-#VdCre~C{eu;sh84?6tV_Z8HGUyvRxK+1)r46$@iOg89OCR7{G^i z+7J5lHU#Xy^9M%4?=+DuLT%x1C50ohrcOs-kkP&i_QMQZM?u)R?G2kxTX%lB?^ob9 z=^zWnrL}<@Ug9^Slx9V}__TyqGd>37i_NuvMVdd5Vx4NZ@0myqbI4P;*OOOh)N1eY z%mXVtma)T^c9phuZ!E~{`Lfozr64Igg?^kEzB+7J3~87g4)8&PJFkG89|KT+d1h_n zuW)?r?)Vpi{c43TT26UVK1W2oe^ih6a$k#+Skb|{AfPZdA zVDL)HQ(){qJWzk#`UPKHn@1Lgiy}n?z&EOD1p4A`7*Kw#2njRN(&#i^X&(Fy?$~B7 zq37~tb~t6o1o#n=@0?+1SL?(+y)GeZTqRHAyW3IQ7@m41#|BjZj(vu`AFuJhGk<@l zw}H}Vj9?a}YNN^S^s`+SUm4LQTy4wyaPLoKe(zga<>L|~I$rbBI^{q+6~Zuxw^$$8 zxlV{|KTdmiW9wnN6$$XY-GT+7{rt0fCjQ^@bV(`Y#8jJGqR36*2pRTI;pDgR4)iY| zdKW$P!@}{=cUk?^-}g%Lx_z^-C@f^(aykcpT%9piht3fy(m(*f8c~3*Iz)3ZonEj(^k3$}IJi$;cdv1o?Tdv#Ter$PDtp zjI32}e8%XmZAJ9gUnwL5QQ-n32QYS8dE@?fX60}5DIUv@j-oXMrMcD>y03nZX+||3 ztwcPy;Ehu*@cj6pZc=*Dn<^Z!xEjJ8P-M+N`B=Y@%pBjE(bKwYYSB``jtBVIT+P@( ze*CzAd`mQ!2|2z}S))PcYnUw>yhdvstRd3AsSq22Fjhy`Zn6wKk}P=I!6$38iupc~ z<9NzG(=pp?1^dQF2iOYfHgL6TOTz(M9>_+_gsKegc1vrjPn zl?K<)vAVnrX=zTF*RG!yX~X)>OjJw^9SIgywv=B2z_*`33HsxQjPl?5>~(ub^XRx_ zVKw6C!8#lz)3os^L zTb~I$;NhoQ4rIoJ}pmB2qkb-fI!K zek$g0TWH@i>fReKdM}R(^aTRkZw-{ zAfK~+SpBD>A7g$)R{|zg;47VU)A9#*mwQ_hlvqTs3s5=}?z>>@s|X6_Avbq73C@2> z-x$c}YgbekjVy+9-AYMW=fsRExo>M0QxK#7-94Dh@Ic-| z*|HFybKoo=cnR-*O~R4WCAaB+xjPoXmoDd+2k?PqhJgMlAZZ|3 zv=k3+JX~p^E4Hx%tW^+3kO_B%{55Hr0=cTI7h~wN$X0F`8{RtLXencKfN}NA(h6(> zPmic%Z+TODV;uBcULrU|ov;T{m@+EEj^riBrTy;S;pvm|XAkGAZnsuw_fI^CxDL}$ z&zzlnNWt8ymJ(UriVFcg2$>Pkr?-kgzC8O$Mr7_<0@eAiD6~tLbT500Axj)dWpK-J zCS9$;h5O$IMvxU8QaTl5eCLd=8H)L}E1^TN?(aB(>qEKhWDk_z_;~<<-iB6(f8OU& zrKnyj*`#eq$1Jfd>E!<3pV5Xhc?z7)Ndvo?h3DRp@=CqHW$24y=}r8Ep{ui~oicw~ z4DgXxm4LqSOdZIlGZq6$CxgxOOEw-;Vuv8Tz2AV}U#|qumis%IDjz9jd@j#1cCtZAYTC&m4WT>wbO*1KI?!vWMeM6w(do@adkOd z^zSPRJ zk?4r+4r%JWYG8>@Z0fOvs4f$i&kRJ%w}Q=kqo1heVn}6oolj907!Eefv>zd~vofiG zeA$ZJ_QXktN!eVEY^iV2c)9s%=6~EsZZ(j~#XS4s1}+7CYkM1;6FD`k!Xz3OcN%Ef zU}RnI>AkqoIKwHk>i|C3HcimK7GMeFqo^l1WDhc+EmKQoA_l{ea|@up$9Y5a`B8W^ z3?}af%TFIB_j6~OMSuS0?%{W0DuiUPw%80ClmT7SwJWSiz*oL-G5)ibbC-GD;dt_f zG{q6&>@izh0?bvT*Ei|+nP~_mxyIwrAA_?Hkk#K$9Zldzrt1&64roZPWi&38A4#D}g zO8ez!Z2NP5{sWOMIVwinp1Rsm@i%Mx{O7?rR>AHWXjNeIb63Ha3@w2CUU{j2UY}7w z`MuO9*?PTVI{AV&Dq(8IcjAgEG#KF^iT@`bk1u%uxyO{l(-(JTL>D)lSGBcFlli^k zdd@d0cWRSZ`j}Cb(kno|7x-t)_PGZLkKk1bpH<1|&d;CF@OIxt`+ipXeX8;21OcRk zBa+-zJsKoDc$iN8*ED6_vRKp*zTk#=V{O#7R)CMWYZ`>Ne}D3e2J(eN7kYDeU>`4I zCBP*Ms%>iYu82IKB2emwu;mEkjMWMIcPOm1?RPDtlLF zOIriv6X6ed;Snv>NWINjv@%Iu9%e1Ga(ObcB{gaA%&X1sFjZkBxxWw-bq0N`a(5jV{&!{8-{~#JuQ?I# z&nR%@CC#+~;n{7dB4KHSB3DJWkME41eT6nn*0L%gV|g0TtO0W=f`*y(n7YY+$i>jz zmXcXqoaujjk#*jnZw}G>@AP5U+g70}^OimG(I?ID2kZM?*AUpIyr;deibm0~oKqU* z7!FnKW%GU%=>pALTuUj8q>aFl+%Jw5W68VwC+}#0;zRUlZ<|i~EMxjII3ew(BVZuI z1+s&mPQ&GH5AKxu)~AAekuSdg63%67`IvBi1Q7@$FS=J-jHbXq8AV!ZrvUx z$lXH%P<-T{#fAR4wfbaIsX0dab&Q67Z9t}agT1hZQ{u{a*mo__)KUw~E;H@re0iIR z;fa?f{s&WuVe|0v+$bs`m(J-xJ|#`v9bp;wHm-#iV#xK&vg-FA9)+&xuq9p8|@vb^x?g4HI z+8J{iK)!<8NcuEA#~2GIEm_w$AMh0<+0~(yf-tV6g~OhGR1pnudxN3McG-{QwF`=B z-&lNMiZk9b%?WZla1a9dazEQC zOc>6Mj8HnmRI`2Zc^Hd@W`o?sg?HIZe)dJBoJ8W@+v^UEEh&pRD16fwp2Teo3Tk+; zR8XtvlP5150{H&fwqFQxei=adp?UM>NRLTpcO`;C^T2*Vnb!I_?K?7&XEE)M&)>MS%RFL5eFzE03S=R zB`e6jEFfP6-4xjhcGXXL*u_9PD;GqCPu0>d%h)pbuZeePdpAD0(pRJk&F^P9jlL?t zaeDZK*s8NR0H&UiBJ-ME2@(N#b+=mMptdbXGRQ7f&DW2dD;$yqLQ%Bv>rB~7mBn*@ zKa$j!+I{NCwv9F|S{(N-yPgPevC!qjsrDg_qsA%FDkcFw+-7G~Yhw7s%YglKYX{J~Hmf#OqKK{XwaX;vjQ6G{(u~ zTRfA^XPQ6l3q`uj70CG&1NjPacr|o9)NRGbTq)p;3FWs#M?8LzOhnET|EiONu|@jD z=@gX`dQ+o!qQL+=CFYgYqj&6<6(5+Dd1j;I_3MAf;^zPP-=ANUul;kuJVmH2t3&KJ z5hWhqxGpdSI0}LmF1)4k7tcN#IvdY?OBExfZgoWES_kxwS4Q8x1=N3W!^dDDVNDkp zECBK&Y9F=&*;fYS%hQQ(m_(RsG1?e;2T_M%2i?i}L@etygk^P<^m)@R9Upc!jMEO? z7Twy0NeB8TPAu3hDwgbdW82+;LV?B;xEo;jP^_2cS5VNAa!6juoiw!5Fdh5 z!W#Y_p23fBQC}JNy*+-ReZg}Z#gH&*`?VE%zCAd)Xq!W1*_v+|;CsbV2>S9%J&=!U z|Im`%l0YK)%@8!%4$)Kl&|Ah}LHToHhDO^yR6KEE1o>jG$1h!X?UQVVTE1>PKJ@L@OG&uHh$6w}HR4 z**F>O{b_WRuiA#ok7QJ-a8a~Qm(jeTH>OM=;kiD~6H2DD@SaM_{m4vxxT<`kamTJ& z`J8hf=lvkIG1p}LHUT~cctJUk>vIsu_i>uqNha8YU}yL+s(%nlNZ0dIW z%z&F!McYdP7hZ4#xxwE*7mZIuQTIj@JHN?IMC5K^QkkGW2`In8*}FvW9IrH32_@gh zuYD<&LCS<`C`K64iZ{{EK5{YoMf1UJA2k+pD&`9{t%Ak=Lvyx{yR}TIQq>RSn!Gyz zADw8t8pys$AfI&rDeIg&3xc-X;Mnc8UCR=+?1wuWqbhp-We;1l9~jIv2Z@h3pOyOoa%gLkQ$W>=A%lw!qSs>2VLYSJ(bZF(Xuf^SexmcuCdYxr{ zwnk5{WxdoDf5+6vh8ebw`_D6JM3P=!9T1m zH6D;Wdf>!NCVwD>yQD$OFGc!-3t#eU+m6>WD!9z4ch9yQ!G|F8U7iwBF6<#tem+o6 z9SIXy0b8%kEE5Mm;$OlkKnbb&VG*Ll|GqOTQh-@n7l*F%N|&}GX(7K5u^%&;Gd57GNKjn<8)G@$^-SU|TWZxo?uQMr3hfy`{8a`lF9j6f5UffSYD2!QmI-+Ru>PO|7 ze)sZpmSvPa)vk%6-oE>bbc99oyKJLQbz7Zge`Ux=RUn^6d4*-g>aHSzQ1iV=VqtDw zaI5&rD>8wabA=dUQbwbY)IG?;ap;d_5t;(5iP`-6x_8b2K3b>u z10egBfP5ioRNa=-DV|1_;1)59;B+nsfdD`A_q`_`h$xUujXFlo$tGW9K&%V_H zfwO|aZwI#j$Jt$QW!1I)!UyT@?(UM3Zjf&225BUu8wBa@5~Mq&Q;=??LsCGxLxFwa zdENIj#i{1`rwg~x;1^nh%BSWnUn7jN%*`NCn((fTZ$p;Q3-kr?)~Qxb`ak4fzCwL< zT|CHbgGK4fzkRJ*RQ|KEA@xjWJxhfm@ke2X%w#)O|_vi@>LgUZA z-X_iZl{a&xiBRt7?B{0GX=h1!%bPzWJVLS6Zwc$)N&E)+=ndW9f$cj0_-dW)R}xD14q#z0k>H>=;%$wHDjVNN#!Nig(*?c|j0W)>DPk z=vS^+{|VrOGhxD&vzgIF+LiDle18V#yyFU0vFPLdMi5Q;*%$cw4x)YQEN1KHmocNW zJn?!PmV1hXnlF-^Hw|??Z-(cdKtA$_;aRYK7XaV1a!x9faSX(-w2HJ!J~`SrZMuV~ zOoa>Rt$sJik*u3XII(c0uK~$x!#1Km^?8fx@}=;8dX@2%wMu$tgI}TmzN8&AL6rdB ztAsFV{?V3H;_}8{3O9Q++Nj(7^v^zdVU9D?E(Cs9m5-Axo3w-wv0(vCql%iZ*#<9) z!(DP5AZP!cSx5d!2@P!DEx=c#`dxXtvgzrEk>#jEd`C+sf0dV0d-N$<=E4`visR&c z#oa(A2jWnUbL%pGUY*_?wabu<`B4fR^DC3rc#@a^Us!Pu(TU-8_UB~FO}#_X_`OY| zinw|67dN^e{w{AuFBOxcW9u3neKa#oK@5bdFY6DBD*AlU#=uaQdzCD4`2ys7$r2g} zw(kz$!|$g@Z_?VGr7ZW;wz8u(Ws%r+5IL#*JWPig=^vUoB5j9$b}c)}E_W0mgm3P? zAyT%z8(M_tBNq(M#w&T>3Gm6j7J=xX;4H-6o3Yp~*+eM~%$e0QYQY(pIQe@j(aKBP z8I-TEwvnq=QEAmI>dd@nNz~U;iFh;}1;QaSVLUJ(AM27O_{-A>fbaVzsc3e<`H^!~ zqMv8$KRwDN@X$^YW;=6JlLw1IUS*U86OfPYvX2=tXw*u{L2k%bKN57?x8b0+UsUvE z@cxbm_#V=wRthIzP`b8<&Q8i`Yj{TUN{)$mk#H9-|JLWy=hv!2aO7`U4apaGzjKEv zoDOtMR49pZxK#LjHB-y7fCu^DYNBYt&JPjbBj4#h(zWyd==jmm+~r-S?zfpchE0bQ z)|uR=T{inrRf?(6B%bdqt3SPe&l=k+Mtm9U&i73U)4(BZ7E~ik0Jeu5J-MOzuV+wx zu~F@}+2C41!zsUa2^_~If~vfIe*UmIE7MDsr@XdGm@YN)ZFiwc-tzgH*$nnIQ-li@ z9$xMu{hMFT8x631$N(Q6iB;}E-Ut5oS|yx;d3+;VZ{Ya7%8oyJ&v)kuX6GcN{eE=a zVEtlG&md%Wb|Z6FieJ(C81M1>?8EZ>&lEISKz`{~CEZa|P}ZWH>HAIYu-QAYA*XJ7 z<@#zzy@<~~(%j&0{*uw&ps-8hcp|O z;>V5-hRV7!48Hu7wt%5C)Q7itXja359?WD|ARh!fvmn?$9Dr}DM7>~?I7#s`{&TWM z0BpZBv9U2a9!{r~$$P4if%1Cl{I?KM=!IO#jT9InSKo?q;2}MDL#aa3uqnA*F0_DK z-;={NID9GXAy@l*&94z&ewxjHueXw`uU@y#^!L~v?-PO_H|kY~I~d_k*gkxKZ>%kb^VgSyM1QrS^x+bOdKP9IxgRZMB2|CzUGMb^!VHUy1mI1tg)r`|M|! z@e6aqhT`&VD?R#Cljrx3*Mbx$Qa!m03<(!thxZDtHJ=YfJ0^zt!{7&;-y z#}Oe>54I0@ZV!xN8X}otV5MT9Amn!fMcud4jj4<#JbN8qgyPc;kTW`UQs6R05ba#( zdJ8u@APDSiO(d)3v{Rx>Bx#`sdVt;KJF&CNKhA^u3$YiXiywbZ>h*}v){nCY-wv-z zJ=bU2%ZkQxtBVC8w)52*H9J`^=cp*3wW2Nvtvd|PC;`+^5|EECEe`zu2Ut@tRJjiSsisr<|SUvE=BZoAV^R#K5N~}AS3cMYH=#FyQoyB_gZEQKa(5*Ta7qehN zS#8g2SIHTqAsHGaREyKWs~!!>=Td@vL~Co{-}t}*@WJ=Qz+x9P*n0CSxre=#%8&Qa zGj7^%3yy;S#pfJbF&a-TQ=QS_$XaD*z|TG;HncyHu^qX7+e>9U4)fpo{Lk{A zIb=b-N3M4yzcnKD?ajHmX8t8zlVG5*8XI)pvyUc7+rjmhHDPm3{Xgk3>Lp`bQl(4r(!vgY4=eh10-Y@8Rc=J>}`PlEQ6tJOM@~C*}SN7x8v+pK5#SCH3 zQQej=|MBMi*DE#>=F;p>jbym9U)`avCHRIIKt7(un4s?O?zKB7!#l%1Vm zKgh+&ld?)ZlOHcBh({0iE9ng!li87b7q))gNqlj~jn3&HWZF~EO;fhBpnZtu9TvF< z_$V|lPPFkszC9Ca=)vMi)Hq(|!=Yc>vet<4u?8wbQhp zd%9Iv=jV0()fvk?3BY2e6B3E zf9rFH`wZ;*1a_Yd+C2$l@K@vs3G;>SD)UfqCe>Umr4U$UvEV;^KRK!0Hz759+DSyG?NxKJLjUZb+YXYvOKpv1b*I0Xiq=GS$@yj)#0BzEpkjc3XsbLRKZ44_ zzDT{F1a};`umU;!A2;VQ7^%J2D!s|Ho3QTQTZEqUNJ0{PFY!^et{ZX~S1X<~5K%{A zQ|U)|Qy$RC1@vJ$RqYxvAWNxZHIT?#aZ&^$Ese4(61c2JeZP73mBW12xn^^;d!*9! zWR>hG6(L14Au`r`8>W@o>pSZj(8~kzu|Ue@fSsQrz^BL&ipwN|e?82^xR47S#V7__ zWUkic?uB~kZ)Q&r&ITzTEH0c%=xNt6S7~jD{3(aLFUUz)CY#h8TN3gHR}GNgdp~wO zv(zRH9%%Vh{!U8nmfW}peMDLPU+EZsj~(pzY9l%xpvGH@lgpm<20||XZ4}oLd+3i= zdtUiNJDUw70gw;U5915iJ|%!J7t7%bb&4H?Mq^-nLIOD-fi#D(qWT4^cJS}e5P4tw z$Oq9DB(f|K9+r;nRqtf^tyE?S`z5Y6iL1~8%^9~W#Q z0oXn@fN$SyREg)LQ?3g2UBit!7PiDT=^xj$Kxn(_c}YZvm@C&})#{jZ64XAUP_lIE zEx~G$&`(vD!|gv)j0aKnpk4#=v&-ndO>A*sv?o=yGx>`9kdmzOZDT!u4dchi-}V9y zT$w9AC)--eFw6F(Gpsc+h!yW*ZmQgmh$1Q|Y916*Z!!pAPE(i8poG;QiHt|N z_44=s=f3d&j9)_69&%3DM|*mRx7cqSVkD9zsD@NqMAHQR=?+eusyK0rUD)i)O z)zSksKb#5%)V~}z|6Lx-Wu}jTL$_PczYHuezhvkv#ALwaq_WRVxi8;})RvGb{1R{(3iPs3>JE8HSwU)K>Cr*WlA;arvGuKOgY7c|_@3DBEMyevxpqy3nD3|vBfnAq zzD!JRrS%TLFeu5DG`86^$sLp;o``^4KhC1cO($GE*qP_ATN$;IeczyhX$|$VU{aN({E|Ex>29czM^a7prEJ5ykN41-XX)A6p{SL?4)|Ss3QUV^U_C z6Wf#JE{Bx1Lj>|*2M*C9?+hISOO5@#=Bm++7-!(}QL&pf?c}|M+9Y>v9^zSe8=vyG zHe9>v)(`eC{4od6r@$CTUCU3EaMr}D7lw^X}iCb>_Sy7_dI9S)(83AF=N3W zU)KY=%U`v{+zWk?ZL(vsRH&EshjK()H!Nnbn@ME9NzckN66bGnd=W`fP0pQauNH{KWSQ0LW zunG{fks_yex;q+TzrSdld#cCrXMqe#(Q_FOc}UseNh| zX*3Ps6ZXQxAf82>&-K1puH%=^{+=k%Yy;btsU1=AuRzA`d^yg)h5D6^sc=7=wJc9mzvr`|JSq8H48h?NJ0Bo^_%i9s%L*a7?{+pDZnr z|GNOCd! z^KRp())`+F4UO^&kZSPFZC(96eX4o863ex8K?_{|qy18Q+)IXW&OZ1tLc4hE)m%dz zrBDi9s8uG>-z%#ulV;b?6yaRp=;T(nyjTq&J<>+Ze1AHb>bytyUq6X5GzaN1`v4U4!{H5J6A5_BhaulKyA=h(xazO%|b`$`=8Ps&FnO(baa_lFp% zliZLwYOPA`@`$cBsn?Bh$0uw-K8xdc@DG>z2&m6#UI7;(gaT8?7T#Z5roWMD1@WuJ zbyX62%^Gs4+WK6dLeGMRnqZiXVL58@eRzg zPU)+mLpzX3e{J<)#p zj6<@EJip0nVTV4*kzX6Vo4(~DbUY%wn}|PiDclD5*53zRN-xC1Qxz3;$6C^!KQ@UY zOuXZlFq+hgeD)P2qTNi3X{M7={yx?-MrX0&_X0o*+mvkQbo;@|eB2~#lezI0I%FSXS?HecoYO=L@5jT*J`N9bNORK^GzJ`p<(=UG{v|gLK zT_3PT{P~pRVJ{7_H1g^nW?|uP;`05d7W!k$~q9Lskr8zv3Jc|0)i?2u6d3SaSU#BJM}; zmXwHcX1}MO)o#3z&|-_4(??wc8o>77kJ6O_r7+cbzn4697ca4NF zQ*gaN`O$SrgWsMU0mx5-F8usUf7ao8Xvp<1UAU@+WyEG;RhVFNRf8XOY484sQXDQV z*`RkNcx@a%Ir>IwP{)M&rr6Ra&&M8qPAmJLOLPA7|CdW+WSD!SIg*t!v_!Ao9h6&q z<7i#;Qm?93h4I-pc$VoL1y{}wp7=@Y7d9$qOvY5UJormocb>g|V-$pwVH4oP}r^UC!nU%dISlS_H z%>rqd+WM{y-QV&fhBL1nQvloRBvJ6<=a2ciPwU2W75C4huHJ2=-OfQK${3>1KKsb; zOisLRfaoUPoKS{;M-YJSdR*&b-CC9P%U{c!ogM6});^6Q8>jBiK1^q_7>9VaY zNy>-ol#f{?D3yE};^iU6IiKzFGQx$wb2$__0|*Ok#{12&^RhsYk7l}39qjxP0QuRO+2nWZOd-g$!@bF^k~PR8wBC90 zK-v;;@Mwn-`{WrEpgKT9ONGYKDI^_v#Gy`TK~yq60eQ}zO*?WmuK;|1R@|50G41(B z+?DR4aznu#Xdq-h&I!*&_a<5V-5o9_L3x=s?9pf7ywLh`xKhl%e`p{$_&T|*TFXSW zS)#`;6y&2W{m2fsFA3nIg#0D#*>_+nrwP@{vHoM~)OBT}0k7CutifepYMO3}Q{W&> zMGe^qBh7U@OMdcISF*CQ_^Agw-nG=A8=^TcAioZeuWzy5VbtggEmF^V*Pbsx2|_0p zOk9|<=afC?cNgue`=!94SIb5e&zI&s@IhU zg=w!UkPxFcR=YQ?K>)D6Q>={R3 z=;OM8EoW?n?M+{1!C1?$s$zmdzB6!Yyl58{1@b{SeNO>9zZ8J)sO}f)1`jI_IqDp| z5f*K`KwjXWlk&Hd5G{zwuRl6%GU9d^W{?lZmrFq0witvrx_`{m!$=H9u459G< z0r;@5I7~ZWF1{RQr5wDi6M2YYkPcAB{ikD|!zAL_C$#~|MQPWxOw;0ixTLHKRSYw# zcbuZHH8iWQ^1}FVG3{U97LOwsyHo%DKk5U#Uyg{^s;Q^XL>;7+&Zx{`vps^XTUHKM zhW6u*lLG~zjkJvIB=Bg&x022=&Yx&iV_>Xy54*W3nY$Pw4kpK{7XZHB_xWV%^as4X zuH*ZB{V`0ev&`n}uiu}yp?UsYU+IPj;p{KKM%R?k@AhOsr5*~pZTF&DOZdEj=H5?+ z{h1^Vl%G-UZxpce`v&k4z>$phh{HSNzKA{;QQxx9QeS+B=`yY^N*&`7v>gW57~$pb zA;w&%plM(;ZxJrcT>f)xd4+(Ine&fa<7gM~(oLi}caPp8EmGK0!uq5ydQenRb`*gn zsfwO`EyK_Gp#_Fc?x72Yczi;?JyOUBx;WiFe4|~uw(ex@4bMZzIuj4_k!$}>2HTeo zsLv1Li+q{3QF`n8+^OO0TNDg~%+r|4<-t~m9^aL2OtGAnS(_J_;^QuY-%=vqvyef$ z=I-gJP`#4sgGA!vMcfDE_Xp=IN4iEWnm~#4llWxeL^IEe00yQpN0LtYzw@61_KML` zMsLtRoC?LCuGX^pA3ovUWWim|(r^x6KNCo+rP#k`N?aKoAN{irP`-h~Qi&~MO zT=k(27}9$9+9=DT8J%?E*~O@Q?NgW|S+H9cWfis21Y?stcWn2=yYobIgIyPV4^HE3 z0lv>vl-tdPiGwZ~Ra+Eo`+1)P97%{^L(;1dXa%10I~rkBqNm_cae!R7?$ECeD?GDz zJ;IQ?a&KEYyW@(eoy`RKNEdGw!S-bXd=e#jR5YrxffynFC|?fl8S0I+|844($>{?o-CDc6D_ zy4UjJI!|$L3|urXULm6Iv(G4Eu$-?#x>%hmdNNxcGry1T@_1{i!}a2}UWlfurBN^! z^WKSq8_-uaxxPntr0D8~MhNnP8nGez3X+lh!ywM8&*-Yt(WEdcqjmOT@|&aVRCGYHA? z|49|Y=7T=jDO-vMH6I5_TJRZBPR%LtSgMds#HW1W`?8RBR({H%o2H>VZl zcCr$Wcc9C;6I+AN#XaSw%Q6VWSB@9rWkw}p)y6@gX zzop2$$;c$PHEAAq$b z%!Kozk^3QODDja#G``J)2T$sINkmcO5X&ACz_%TH)L<&kkNeK$F`vz_LoE7m_$s1H zleW(-Hro1F`rflB*`8t6=$FY;J^a^G0QnV~8+>AQ* zZM%5^Mb1VG7iTuAFYxz$TtRiJk*ukm2>9(2Z2;fOz-gyz)29JXB_RaP zwsSL9IL0)0ZdhGE{U0-;HVPFXQF%Gi4f|G2LpQO8x)MW$&4E0yEHAEG&e8E%SYQYN z`6YObG(V=JyQq2?QrSV|;KU29BYvYe;Jx@Nukh@9m}L*6>A&B{tZOX%jNhF94w3^Vf3f)-tboGIa&8M{_+1U#pj# z<`adfp@n?wcjFLvj83KV{4DmB@i?)$43GPfX7$*g=F0!DPaf!dSoz2wrMwf|Xn`54 z_$eD^zl7hK{OJH&R5#?=ciQCD(yMJ55w$4mTT%d}G}5PU{!{SD9w}1*o}39o@Te8! z!`V$s1pE2x2KYDxi?w4lFjTZC5H_DIdzX4;UvUrB6$m`yJP$E*rNOy{pKwpD%T!2 zAI)w?$atPMfUn+ogwL+lvFffN_kGY-rk#}{*1|%;&$xOnoxitk#zr$pr2T+mTy&K- zCJQ5=?(K6^binR5*%Odd;FPRT$mzRl137nE=8?U`Vb@Zmb#4sWm|CblU-K41Ng8vY*4!$Lw7w6rwkK5;wWae zcJq;}otBHz$%6;45#be6U3GcuGTPeCyxt5R&c@qckQ&_*kl%|M={y z<%Modjn9Ed1c!@>v4^Pz*;lSQIu!C{D{zdCt@8)V!-_H?1Kx8k(e8n+3gL} zN^5rh0z^KoEho3C}d-&-M{iL=iosg_Zs3aTQt8Z+*q-RNIN@IDlL(jZbJw!Xg?>q5mSg@_s$yN$^Q!E1! z1j{N7cHuWyQpiT|-$3zk3?se+`}Hygh>z+8gdb0B@sCO+&PdKAqsgmWo3k*pb6c$x zpLL5PsXsrtp>xJ~WSldwTFAFkex#1SiQ&^c)ltydhBH?bK>==VJT^S-rLyTG89~FJ zdgy)XN2A@egQ_qwoJ2JK+kN&fO_@!@4^e}!Xvyj;oZpA4M)uvu1*#W&Pn-;#gpj3| zLm(gaHzV*@$0h*2%~i+L)>GndjmS-s6N<^TSliyLa`o(m2Mw0~2N^-j4Fe8#?>!~8 zxL{!gXekuJ6fdSbQFddM(CPKb91*U7SFdz^YVaDR33i{{Z1xAn8gO9cd1>v$O9Om>gO9|fQkJXlmt_%cFyF&b9qwZ&AibLTX_0VJM{kIuY2$Eqj(=Mp zVL78=yf$k33+=y;-+xwD@G2hkHzU)p{iPUmKjY-?Q>_-Q{mdu1$sfJie)jEl`x~N| zCqr(G;Z0Jhg&GEZLHS5dvqV8e*_=Q8=@lOO6v)T$5eNLkLuLTJSbbkB(Yguk-dOUH z?%VJoAqo8D1V|3wSwd-Q(#i~ebVEKqlHoh>>oOLNPRdpQ zp56LVF!TgbO66Cd8g!phY$wg@@>nw*YCr2c#1Xk?A8CSpi)2CtWbeDY=m?B7DXq@$ zDc0qY8mVq(*0R(Tm{zkOAAeHKPq3fAS%43jaohM%r(+P;B3=i@0O4~hUcArczFG}r zV|NTIAu*iP>kD_=vje0l-&X+nq3k{wU7ojNuIQ3+ z;VZn?S1g-8Kkjexha@$(C}}-4DqcQ!uN04pvnNv`f|j;7u+^<0&rUOAS;bn4PGQRc zZk~Q3V&gPeDnK18LbiV+Ic>}{(RlLnGB}Aow^{T#zs`A64eT3FrHXNvOHC2k8YA|0 zM&CFWx_Qzu8-|&FF^Dygk0CGw{NJNZfUhr{_;?oTI!_EHpSKmKO_Mic8k?{ncm290 zB^SGrl$}>!6gmyTyJCgTUSPUo`|!w{3!7Qik>m$6)iha2g(4t7MED>9GTZ&8om|WM zOLQbkf$-I{-6P)s?9>j+XJ6`JL@Y8gxPWDOLs{1Mn55043^nK`mKak&$^$R zARn}F9{AnYM*ttJaOm=}VK+*ODPNiSG>ZSZWFdpWzI3ACpcWqj%UylrBDxFZj>9pk z$X1tzq+y|5zAC3J48*p)=l!tx4#*e9V+j868XNHZl{h1m zaIFnFJMalQSo?Wjm~3cqjkBFR_zu}oYm|9W36-4JafoDQ8V~DI$~A~fBtt`OMXpE= z2wLVPB38z{2ly_PGs(Yb5A<{2eTJfiC3etL8__^@l1xX2Jovl2k+0Z-_b265B9gAyD&cG^ix>|Gb$5-7%i?+g()a+kmmQB#PL~*d>vMF>|-3o=bl5 zbf=>n_YUi-aO)SyM~eNb6l~uGz-Mt}grEamo0>V*LhWgmVI+*dpwK6#3-*MK}5<_ID5RY>MH}^089>747Ex3!|(13!JzKRVW{9!hGVq;&pAe!@> zpCX?KwfowU@>c@25ml&r1!Yy(&MuP_hCoOOImJWTc*ZM`kER@R0_^;*0Y1p~G%6>m z0eSqA_iE&nYssdsZY@rlT9|MVKFn(I&m)O@Ue9GVLX5HVv6#xVAYP(ooV$3MvSIG> z^^7n?1GboX=(P+4*G7wl^$vHD|Rks#fZorH7n_xIMsjG58BchA90bCX&D zcavibUwUXWlUKc@o<>?_c-k=T7UaVfaR+~Q00jL1{=O@B2C8FJMsBc_1ke{H&tCFp zIx9MBvT^XwlM>ZbdLUix2a3N=F>imJ@?G8|f!=3!hu!b;X(NPa-H?TD9JUp4Fr?k3)+i<`bXsSf4pUwTu635xA>thrfS z;fIX%BhVoScmLL>ixK$amk)sHmw_4?{p<+rj_?A_m~W{#^A)FFx4L-DJIlG@B{B?% zpU8&AiwEON62T@-$oW0H^1rS9Sw9`uOv=sL-`B50Y`b zh}LF_7NYcKShzEuecwLJ#8AHdgmzbwxsqhL*L|R;+EvGo?jA_TPEL`p6Q2G6@dpeE3OVEkr#R(T?EdSByw~wYSOdM z3AZ<|)NTQqwa~NC&Z5rHbtg7GC7Cm1qcuf`+0_4i2Grc&!O3ErcaPXFB{J|F#D4S(=Uqgwg?qA<3j96Xjk6s3)<>QE`GqxL z4uf=KgZkZ#LuSqVb(HP5Bf63_9vG1CVJ-xW)xUqcLs|jTXA*D}5vl1s14j25vJ1Ic zXWl24{K&U>?|ROsTHY@fmxsS0l6RZ1Xb2Yj=SDx*zG&5PjMvK{+uGYsB{dSG<;Y~I;OS=0V@^eem#|JD}VXd1-A{G4AxhY3+B4pX`VrU$v5sj0iSA`E@F z3qk{Bepx#qMrn*YJjh3T7LNgTec}T0vn*}UU~+9pm18!;6`~e^&`RDF&C6QxiffaY zpz!|8wKPC|J_ING=f%A>qXDK9JXb!2n-?Su}OohUOzr@9%bs zD@kJgW|@q|C_Na76n)(4l-@v`4xkjUW8Hkng zw!4sVB0R9WoQ2>g4bIgiz0+qHi6jW(54ff@I?PnBd&?eC z{@yL)C0JR8zGgIrtXYv`@cV&70)NdU|I~V8d{f*7f(7#70S)9M8gc}`d!7{FlOGwm zh23#43E-?w?xGmEk}psr-2 zY~cCwu4alKxV#b}O~wWF8uP5>_Az8FsDXp(;;1SO$?p7@-}Sra`gH%kc98iew%qTy zkLwCiBg>U6v<#_>Jr`mGtr+Xa_gphLXjD8ZLxE}9dGDs?j*w+X_PsDO2qw}|-slvtlqR|KXeA^RbTxR%+As=`YE^{LJl z>MMt+J91b&?(yvto&j-&8)~D^fV?ItM*g$!&cJX||CA_Prg~<4`p5pQc&V$#A9E@= zc#UN(8Ev`g?>HbIjLh66*!4*P@TqFG)Ldc}bq_{vEZ_HkiEL5(p_Z+OQ6Dch7TBF-@mrSR?m@imtgQAMLk{%b z;pmq3lvkT^PSlI*XP-k&E%7M2$(88K;(6Oy_g9VfY<@nh?u_pn?arWO-2Ea5Kt4hw zD)0}#rUUq_v;Cb#9@8;GN2g3fkLP_V0^YU+L6DGc7O6@1U`wSx;dn=~_U0eVtT!Y` zJ!u4L4rkV&<%B_BY|f1Zyb`ViTU6 zG1np} zCh}DNO#t6;Kx;;jSoGpu>bmS_7epAZEsxt8lnYAS@OZIjA75CZ#v4)JrR{1h zKZkg3GpcXehJTC?-eG)1j~?>&?}@%_s&EbgZs|lOavU3qYhKbMBt+#}xEl)C}h09r?-9 z`C_d*bPgdU$hWAn0>=3B-{lq5|2@18n#Op9S1A+1+xzvSeZbpFgo9}^KoP(BG|LcX zt8scUgeAAyv^zoZIw#=r@q#AdaDcw9#Sq3I)76|>x6WJozr6oUUsLSjrQhr5yxqqR zTT~|>`+(@pJqXPm8Aomt@ama2S3sHe{<9I;;xDq8l_oJuZ;XZO6g{(ofi?X`344t! zaViiGk~<0p?D(nx!xwy5m^}rp=*+^2opk@Cn-@>|Eb(pEP=?N8zNoFP-^=BKJFl4C zD7qUl!iXipno^c;hVxgTh{?62x`sBs7^VVzO(+KpGDSOdXUlxMPhD@cE*}xae(@%^ z*1yPFeD-N)8OI;MCbFOo-)2qf_9>HnvYAS_htMZJ-`y+`ikYUM0r{9$&rHDf2?EL! z7FrE5`|-3*A@&2O;GPcE#?I>$&6k52#7w_JZ zZ$GIKODqg}!$At*0DKsoa!o?}&N_`VYB}8)xqZTQ+d6V}aaPdZt2eR@xmSLO%w7MRGP{!55|zbfT^k$;z>M_65MTSUC)JA;9&QCl1#NA~$NQYUe?e zL`V-@?eSHv@M(K&@--+8v=ozrr8v)Xyg@)^H~L>XkglLeIWhI}GF=vCcS&dMT$fsj(C|>keq6%g=W2ZI-eNilcre{p<4% zDFpxOF($zDph~X$sXM!$*kTBK$n+&H>Arcrk+|7m3*q{Q_zz^9RJ2MYYm-Nelij5jSS~UBIzwMAvbu>P$n&Lq z_Eo4=9okNQa&27sM7dWzH=wjmNjB^AGt0X9-VYP5r-+&blpoD<5F*(5DFX5fyPrGK z)hBUibW{%W5s?kL8;c#k4qm~JIL=udSS}E)kqorY3iN+Ye|3)ab#UQ zp=b@ts}23|lY%wl$ECY1NH49`j*k|d&-t~-y^p86tVx`SIv`TR_+miLq0_%@9F^Di zHS5f*P2g#a1LPz04m}6k_Xd!k23E*^1kUfFyeBM*Z$?dFGL?O#c#@tpPUfo6(YY;Q zKMY)7t=yiX#Xm8m1`}9Ki4&k%h2tUyT`r>A-a}{thi7y%G>yA(5*q;w1)2!~A=;SD zH)Ng5Sbb-MI8@I*!CG8tc?1Z@IvmXQ4pzo5S$Yq0%m`x3?=L=M^?bn)li&vVptsd< z!1ieae2sx0(U0H;D|9P})8l#qmT4VysE1e%9254A`-G+y=!qJN7ZmVS%=b@_wcd)X6QfmyX>y|wVGTVY z(qd!X%yvgIEIs!&yb_{SJb(9{3V?jI=XKyuzl;OMFXsJ1wY?qA>Ew(Gqq{GTVUprf zkHp-7G5aGi-aRc&W2_IiV z_%Xd%+7NZc6;rLPwApfU--kRDML3O2t<&vZF0H*G z?^9>P6))WCO1ff(Ys^e#VZ zP0VGko$Qw)_J`x@Lf!dE1Zx^Krtf2j)!nyJ?~&Q{!wKvu-}dhux))+~Lg%Ejj@4cB z`V=`2@B!-c(`_s=QM7#G`E224oVq)vEx0_#JkICDgGV40nAUx;i`XbFEK6))Y_(R|3J<_)iW5JWDCYiTpRX}Vu{rFTP(zr6kQ5l>027yDOgo4fbc z1L(ZF@vzr~xgGqtR~;BlG+=E7)vNY`TAgn7m;gRM#G^j1Xmf+Jux|Q`yX{BZlRfSO z&(9O{IhIOfE-fwsI(j+y>i2T#8j>VhGA0A76XN71+K| zfNx@siM&pdG@rQL(sQ)Ws`<71pa+SSCaWgS8VUSF@ZK=1|D@b9-xB7!pQ3!uZXfTx zNf3^y<kZxY4U%4|M`7yM^K9WmNx#>a86!V{6;RihB6l+QV7%NbGpFCXCIRq z7eO3+ZOC8%L7NL{u6Hx);q`3qimLISyk>_?`Lb(OkPo8U3i#1U>o>0ab6Nq`RePc(%^e@MpRCJMN#Ns|7KyM6hYTgiQW_ zeExE?$?ipR{KyHyEnh1HP85dVV1$#TY=112v3T~`xVh;!%-F{)*d<6eDf)3CG?rPc zo1hIU@4Wc7wl>(cp$YO$wWA>X-^cgw=V2c3c~2Wd_c^!rNR05&Z^y=imCk4kDjO1V zQFwn4Zt-e}asbIbL?LQ<2;R+;@$Ifzb%cDzHVkyh4VjZCix)f`6mWH{TZKa=^oNKz zr$Op=La|@`#~uQpm!5XVZ+j zwwU%hARpnuIThHxI6!{y=vCY&EWVM|Qcr}A(d@e=Gz#jZi59yU&*tLej8C%3Our$4 z)^hcQB|XU?n_N;svSJ%$kczEoHM#9w;+q7nZrWj)!=mcYC?U@kMFirxi-=bhuvLi6 zbz!%vGClh?f3p=s(WcSYR|HF(iJeNOzjU!it!VF>c!t7(A0x|s~{ zG4>7Xu%VzykDeK#&Zua8mDsH{Zl3PZ_qJUGV3s83B4x2R02FCc*=eb4uc%?NMSXwHq=8`L>DZ!CxI)0@PU-Z8vu|fx2P@ z@O@cMO6ncZ1R;NOws~{KTX0&x~j8d%lMm|C1RXKKI()YxlK#!QZk2 z@7`vUj#3EphN-=C);;ZOfk3*^&c+oZkKdv;yvQR^AY zUsw3i{J~SgY?j$2GOPV2*P2IZV8PG$2O>#FN!Q?FjV7;auC9_!rxnVav9 zR)|8k6;*_YWj+r3TG9&O!+tdk`rU(lK-?SNpFQ39qJA2U;xV)g?LD% zC$}VmSQ}kc$ss;O(vnk8%C(*{1i!KbRu6=@tCXyQOQW5~JSA{-IR#R){7&mi)Gm z2k_w%T@rwtUn@|4_&3!#L4N73N#aE>1C^mkLnGFm%XVq4n@zNIlgjd_U_A<-?YdTY zi^XaCMrJWL@79%Ja-~=B3zI}Hs^=4k|Cit2=}UHV^_fZy%yahl>f~XDPMk9PTLQ*} zIm9i{xWB7gncvYs=b_nI(A?^xYmZW*osN!M*b;6!frV^&6u^I#33~(Zd6=JpF#i3S zzL@HHL4f&g%2BXVk8DyfZ31Fsbh_x-$MDs`0b? z=_%5;!b@V|hHVLDO;1Qi_YcNBy*-Srz0|Q-gX>|;vt{FR2Jpzh)|fz!ZviMiA(ftV z_fD5?mD+Vo?XQ(6XTc$FsX~N9PGh9XUpSmNXuQE>mjP?2Khb%4qDAtUA@>aujmPU@ zjYl;#Zp+Yp7sz+DL<%jrfOioyf1a@0n0J_++}kvZ*UF()s|o$&E0vSt85v`@6kBsw ze&s>>LU@U2A zbP5l;xhPIUF^8=Wc;PCcaCAdxOpvz)dZ~ip3HY|B0r|2hY*T{p7x$o}_;bI)&Sfw~ z$ab5^mqHdD!Sy})C>^`Z5I6>7qmn;F-QBI1TSa)?_Cn7jWaidmMRjIEih2Wl(0IS@ zvI2E@SOdxr2kgLJUGmLLw^$E@I`ssD=O?!EpEJ@dJp;7qbYDAOTU`myTj^dI!t2Dn zSItP`>)h)l42Ge844ncm>MG=f0`ieFDfS@}7d4g;1@UYb=bwq%HJMYr(N%s?*zkMx zQzBTJKApiOEfp*8XTKfIjy)e8NlQf7d_>;R@&coNK4}2JN6ZIN39@ek$ajP#_Yr>@ z(-Mrl^VE1QAnS|QCb%Dj#%V0q7^~Z-cP(!_yT&UZbJzxaGk@logjjHm!j7}qRg=Oj zXvS=GMFJnL5}!vN&BaguGFGa(_QS>MtECo&VMima*UgLo_EUbVoAHPZ9+JCpg%`ME zQ?J)J4p1J<$LUjsyKiczJfvjr0s%hkp^+aT`*whQejY`olo0ldgmcPXMQ}+qDyuz3 z3#cdNN+XD^Du3u7MwLM?ifCIEr+0)eitFP5(wKDG%rWu@nba!_{&EGtq?u| zlsX3+^ST;KN>0<|belKG9lIw;!hW|;K6@}}2&mAo@$Wa~xl7sl+JUinq)7X$u%T8i zHsg++ZIPjWeC4UWAp3TKeB8=~Jgp51m>mg^bSqsP#R#dZN9(ICG?!>v&x7Y2%c)1r zz36Hu17SId7G76@dm+7^INGsg7rXYRDHW_z2j0CU!DmT#zfokZf5T|=!9&)5V-DhG z+Ugi)@5jOKy9*ZU-uaRWvOecsiY%uMJX%7PkIOK9d%v|yj@i}r0pdMdB)|uTVFCK5 zbGCt|FVqER6FWVU$w|E4{5p=+@jP)(OZir&y z(UM**-51{otaMql^CW&OwF7$o-VRB-35xBxO?JX+KX;voLDrsNWOqqAegDiw`6<80 z3OE}ANTKn?&!3!P2hxbbnDW+5E3%c@6?9+rwyHI-L;-v(-#K&Lu)V5o@7Xz0F%6H@zbY`WrYwK=FGx4@hHl=&$w;!;In9%b z&N7_@h`raWI02keqDPs<+ov%AAL$axTabOXKt3E;Z8S}G<5W%v=nJx2`y`?y&1~8} zA8_CIU6SIIsXfw-Fh_3@F_vm6^Gb)-U|?=7SUg_YiW}d{bQWkzehvOFzrWM78l*wA z>^CV~TAG>k7Z$!w?^tIV`ADwQI)n?upYrR+7H1};?JIXaa=KoF!t$XHK0^o{M8cH8 zV7eVx@BU623-HaNj)Sm!`)7LQ@bC1jjJLxrl8Gx;z}2`&5&6)N&7H4bpj2p=uY_TO zDf>{!e(+?X8Cd|m6hl=ww*&g!9kcSLJbdOQdF@^;tML!^|9F3=XOuw$!I%oB#hq5M z>`NKC`{{6EE99mW>)wzvIZr&YQcE}z$-BZ}%I`h>YcCE1&bT?Uo_AD9kt{cUF;?1Q zj|1??mcC+u9N!&Kd;x1lGe-1!*+Pa!Q3a;XUmuacM+LUe~PIC105HVZ5K&lD7v503QeH%nHapXt;m# zliTYW+3ZAx`ij?CrUIGtknVwnMwN9*V!n1g&a2kCQlkDMG*P){HO4$pN*NpFV-OTy zuY1&nc!13NF&ZTS7a*S#`+*2&hzPT=4G+w{ps&5IRp+T==O&}Uo9W-vGo?gRTgpJR zB7#Po;T=dFw|!>bo^H)V2KX;!`?o<|0m&% z6w%*R#%igbd{4-AJFBz5kSgDcF0)e&=^D3h}?0c8GDRGQK3; zF3z1+;tJ|`%5TatV93GN|21yNE$UXfRFOMw*kmL zG9X`hsC~EH;A0!!th=AOSun}S28`Sq8kJ%0k2(zT&YBVYWN7sTnHZEZiC;I}q@$L+ zO&&teL0z<#C14FXobg-+%Fo+hdY+W$@h|Vf-i?1NR$p?;e^_D%b+-2#k zlm6%XJN&h9#f}l}=cDDv{G8D8O)kGN>|qaldodlX(f<4F-zP32<{w8A9}o&`v0Xnw zj(WT{-`nOwKe6^@6cCw(?ia}i_|9p;LD;8Z#{ zHy-(ICH)!B`+L@2Twv3Dc6{5fmO4#?rpclPYEXy>SS>2B{^R`}-RTUmV8Q5TmsQtw zD2Mz?c5}mugr3tFspy#XA3gEbIH*3j@1k744<@-MD-&eG&7FwfC|BqC9Qhi0Gm#%s zumr$knym+Y?|}oTb*jp~uPB|XFz0MW{Tv~v+Jzfj+CtlfKH*4NgOk%+u1)*;3tI(Wk)~xCW=a(@!e*= zy)uAjqlVzTBqtMsn1E;EFlTxXneGWs8?DWm>~CR#J2r=dck1te zd^J+eqKzDnFrq`mn?vxgB+9PsN54&mAZ<2&ZhZ0)rpB6CDW1aoo(Z!Axf6?lh4oFVQp6e;^NMjX?k=!t-D}kL!vE20^%Lw+aO!U+ZKo# zfDa0Z8uZd+OCVn{B{?5wLXB%^(UxkeQqa4wgXcurEX_10SuH-UP8vdYA4$$nw~$Y- ziYkU;w#O4bU%zA-c`=D*Ed*;y(t+mzlwSx1XRD#CuyRTv(=$CI^iIEPJkEET(xgU~ zbpubnXIg49TgHZ-B|k3VuqaYTiCB+6-TBm-QMYi{Bh3VUg=hl!xa1~yK+ew|$fq<~ zrI5AZPWlc-s5lg_lG>bv$mKl5Apz$RF((9qHUfjxPI!SX$ffK34{ReM!gsX{Gwm}L zt+spuIY@8arhsRk&tBig*h`H;&BpRO5FQ%IAf)$oV~c~)wOA9bJ^4mXTD@g(OxsNm z<5cS@j&N1K3EPhGu73`H2;pxHM$;qvzV| zqoU7)zZ}$o5qMF0DWsTdApNo2UloUYMt8_^bvc24>Sb~o0?ncGXVueOra{3Tp!{6e z8xFtGY)IE?oLh@Un`zOTlUt@)YG76y7oR=(#`6M(OsW#Ee2J;GQ^(-;u}k=?1j)_^ z7*#AzlQSXl7h3`Ov1y`#KD%}T%1@DpfM#Pz-UBN_h6Q^0IrmURKmX11j6*}3XWWE7 zud|Hwd4`77Ss$c31`;H;ZP~dIs&=Vlc8;k}R*;qwDLR0BFW1VQBEVV9wTN#R@x(&`eh2dh48Z(<6%Ybz44w0>+XJum65Jkd642lzPB z+kRc_{p%M%+52+`^2M{JSwvq)Jr-Z~PV*9k=buRtE{%QghPvs6yenW#Q}+fj_l4Z={vPMo{5-_V`5zp#)QhAo7Fxq zPZW^)WOu)((_AADG`xO|kvx>Q=Phlo_=0rO*4*RI?^mGK2-z*2|uB>5onGT9lu=nh%+1 zHS7k-m7C7&H}iOaeBYQ}uFw0P;ZtbIcQE|u8>ot$KIN1Q2zZpGzkBixw8g3{zJI3t zqL&)|vrm4GTFmfA<41oEM@ zX7G4)xb}gswfTB4M!K;G3VsdlHwza_=3094z5Xm!ax6isJXpRyR!2>#;)Yz%AkiAe zfA(c`Me8NbWBo9|2XSHZtAqLV3!t>mI3OQO)UdJon4aT#1_qgJA6*op`SyuQP-gFo-)!%tKi~qF4x00pAev$vA zj(Gm$)20p%xK!NEYb&?AMtSDW(*DL2o+)Ol4P4LU^gH6&=h;bsk5&z09b{h)kniO; zDikVvjcP@cw0>*fPeCH~9{KSn6m`4bzoXk?1ojciIiV1Dy*f(XSQh~c-h$#VE19^! zZ^CNX+Q4{WnF@ULp+a(+HtA(hg+z%p63#)uccnpHCI$ZRl$1^8-!08B*+^^S`Z=On z){Idh-dRM9er|99KMF6;OZn%fi~R@g^8g>6J=trJebqp|LsW0kxYg&Kr4mM_u#P34 z=4D@-$t^dj6FjGsINbgQ7VsVMrJ3dO%)Y?P=?pX$Z*&Ts+*aMgHz_LYg_rJ#mq7V3 zA&|mpSSb~fADWcmKvB($GqRZ-KI|U+Ftgcx$}hW{pm%ZcVcCPN-;H#bXbmw>tR!}1 z)A5myKRVX87{6`6VuwJK7VB z-umB5I7Cw3tnx|8{62bA$*Wwq+ZZr26%=(BEm@%yvQ@aHfAkt`UR7fYRkNu=Z57~S z6aLl!vabio$J6zVW#NYshUv-yFW61v!^_DY7{DLGrMmdC0Bd zrT64;%>jcIQsZNry}RP80!6wC*fxp-6AMU%JA!;xg@c(Np~1 zJo+h|c9HZYb;8o+qwC|9fBrs$^Rs!hz7jv;uT8VO@qHW{fATAxU0=Nrs#&xH%`6A^M$4(hY;xI8Sc@YRqkciQRs1N@3EChH z^1?fLlkc)X`5CmofW3yKr*Wu8Hm!*=Er+~G&EZErP5O+#KKRr=bvtWHU0UhHK0t(j zMf-SvFkJ>=eT3SfNO+GYz03DH=i?T@M_S1RLTT%t)z2fK`De$`;QdHd1#T=Q zfBhtQYAz_5QmOn$FQ|Q2)ORPCNDwb^n}wkDhoWf(qyuU`Jx@BAzE=yf3uk42i4R;` zmuaZ}OmZ;)SnARqdd6dIV(0uQ(uK^B228~L_xw6$;tr3tlJ7&t3AE$~v4BTyNV==Y zP4U}CrQ_o?;S7JV9e@wtt6dP}{APjj3t&(4f`tz6(lU3lwC&iB*PDR-0ezM8&7$;t zgvm^2h~H{%v8kg^$tmgi@p7Tx^>%Is^Ij9vo95itt?42{z&9%jdK|vKoJW-5DU(6b zgIk>1$L8tuFYRKt!|B_4%8xZnqApcNaq)vUtm`Vm8d6p?1*hCP4&=AZ)HuS8*_6s7 zfbT`&9q1?Dw}E`x0elds5+C-fB-|WZg8DxaT`~#YBeZAReR6My$5K5T8Fq+IRJ&w? z%`ih44ROW!a-P^ne_5fpL{ewXC(fA;)IKR>%rClDqwklluRr5emLGp+vhJiTk2yUz zV{dx$Sz+oyHi0o3wh$;j_*<|YI3_$Br8c~1eUbJdQHLNNZsHW+qe#X9{pi>pknc{+ zK-9WgDLnr)Q=p?G`knITi-Wq188^vd2uBixae|vf(=XKG2r|0tDNtCc8gQo60?$QT z(_#4(F*=XGj7I_aYE5yY$9L@PlOmwn1|UQotjbu|@~(%(7N#{mJ^6NgvvGYIV-pyG65siYXG0Q|?KT%Rrs~FoiSbo@x|L(Y?;E4B1n@GGS>U*)Q8`P*(A{>D$aP8;D zVBwqRorMLbFpDHpKMTVcKdlp7vyAWAS@Zn9SlFt)qBI)+V3@Etrh|0XtP9-ct-a)R z&AaM=DPr^8A%xgVfbS4C0QC3UIiU3=h3vS!+z?-BvhnE$Ek|jeHt8}?;cB5M=b*$E ze3lF1@g9tOz1q7*aqj6_erSoi_CW|X&s@3oK#Ud}(bn$+K>0~HA3z;F~HWnLC&*sqE&Wohq0=8Pm22 z9^};=EYWGHsN8aqPDP?x&pah05ZtZY^xvZ}0k7{$sKCEWz>wv0Tit)8KrOekEv`XM z9XP|&a6(&sYM%kw`0$0-=5eWZbt)DrXVfWpbAG!)mlmkioG*lRvA$#)8VQCWg z6D;kt&o|vmTYWtM=fvN%5WBf%$LmXKBycK$gPi@HA3M|t=tsk0fPBIF`>sg74x^o5 zCQ_NFmSNwJ=aEq%k#`S9E->%aO&(hGz4ArqyFLaW^Hp1oZ2JzGK`Gp!>qSp zVx$m+?FC2V;yN;B-3J)d)op3*MbK?3p#p)0D1Z+?Glm#!f8E%u(3djYpk$Cunp;pw>2 z_$~xHqGS&uw%(<)*Z1|Ci37a~LM|bAF{q!y{Tneoh+Zk1K)z}5f~HkMQ|rrym)fh- ztY*-32c+gig}ZDGfTOqjjcol+Lg??FeYVvtadzMI*{)WH$VUt`;+<7X|6=T=fDG_q znFZd0+`pgz`PSf2^3zf7M3BbN@~s~0Ep{%#(H(~{Jv6vkr%z{)tMkN@IJPVJx;sw7 zi@xj!6a6@n9@LPhhko!p*ja792?6po?`#P|V(G9Vm_?vjF~=X#<#Q|=Qyb4mjyioFvS>omUx##b8!FvV0X~j=NzjYWP=S22G!YfH z!wB_d8e!A|RE(d<^Ki_43j3yU{BGp+FG|Jk)`gAKQ_*amxxIMPPd6-z zG)+w!{Y3@%X0VP|UAYCJrmg&S)KCs^+eane_|JovNe0wsp;4ZE(K4Bm4OC1ufpsN3 z-9)7vNT&KX+#ME?Zn+9*AKBb|oG<`BFwW_1kn_U@^6j4>;WyzP#~(ShH~OqA6T2qg z$s?1=e6qS8P#Hp)ajbpa!S6Ua>na1+b__kH8!`nsF_5aPT)NleeCg-$4fy7)OEhqc z`f(y6qZa1U_i_4!(%$6*5*pbWgDL19Prl}qFT34X@S5++zSHW`H;!X9)euXf;&q|l zEyR!%zvoEB0r;37?Abu}5d!(XV;4+`pO9YR3q^6Yt<`fmt`+^<^TAoby3a5Se5oB= ztjN9zt;oA_UCX_N@22G=R!YmUeAUXAbzk3ff9?gm{(^fv&N~>L`17qadB}FF3B3~+ z&#Y08y&Z>n>F?sYCZ}ZC7 zkZJ3y%t9QfnB51_r(HZBl#Q^9Gc)Apgum8i(rgX%gtx)z%Mr$?A3ut6NV;)ru!sk9a>IYv48eRTgpKl&~mKH>~hr%gty2Tfc ztIxzX4O4ic z9M1!q?HGEkn?)&}DX^UVIKyNL_dR&Z&pg$5vPmXWDgw^6H;np$-^T zzMv@QqJ0uC(UXs!g>LwCDbw|kWMFzbN~m5GCgsA#GceQxbCN||#Y3~72H*n+Zw7sR zmjcL#vhL_k*r|Hz=*9~(Li)fidIW3s-P%XUA~luHN-L{%clBX>Xz%{++7s2on_cPx zCx^qlO^=CGp`Y1oPD%fN^UuH4FAv5J&6NWLH;OyHCzZ;|%psm17u9>huRd0By?FBZ zQfHxtHd@tUB#X~NQXIW9L${Tt77oCNUZQGY!JI_FqXqarx%+{zKlZ0Qg!tdr2M(m# z^Q=D2e%8K_rrf3!?JI~hN2*dr)Qwy3d4(1pB7vwv2D#%YF4Ar0Y!W2?Q@wFsy6OD9 z(_O+cND3#&QlQ80!2^cIKM+5Xub-C`*`&?T5}v35d*j-4FO}5oiHF+GTxR$VB#GjlSR~>SwWsg1K#o57v?r0Cq$3O z2wPWBCx|aFDyge}zrI6vk136pHy-$)GdILr+Mr&l>=mu#DXaXfBt18~t)Dt!2KdPE zbsItUF$4J~>)PiTWCn!fHhPV{bT!;;yl9~!dJL5`ABp^LQnm$^WuSCp$PVVZD+%v8 zWfaQcZm2aCq=<+;B7IdftCw1U@)Mp=UYIm;j9^8Itvowm^smdg2~XJnfZbPS_xttz zbGDvc09@Z4f!1;Y{2OesP5H?_%^un&Mn_KPWr8*aIWB;2;BXG~o9hS={(b(84P)JW zKFsP%3E?%4_w*twm}Aq}7okIZ8YC{pITcjHiK|A=ENl9)Fs2%WmS}mSx^^A!M1)s-TLl2VCb&*Akn<}7THbwr=sVafAL@i<$@3U90mqIm z_KZ<$3MMJR1Ntt1s}0i)Nd$XQ5o&e+P&)a&vZPi}Z|fUbY~}?$FD8YFi?RQehy3k6 z8^@p@HBR48`Sxhm)Y)i0Hnwma%ahQkt(z!|Jo$=TqDF&1Ks=*Mgk^4Ur7Z=2cAFD~ z!(~uit9?H$WG4+R0`L*1*82S4eSf-7sDI;QnSK6}lBa*OXk+q|ksyKkOKj3Nk28p8 zMp+rWRzYoT!K|wN%f7?hfdM0sXZ|D;4royC!L}vlSqX_11}Z)Ow|o1SC)IXc?`0>q z?}a^7*~)J}WbD}PVJd2sLFG7E`NZSwi0%xFc;Mf+ZD^a1jROz;>DVHt4&ScT%QTAj zd864}^3UT(7YoAb*&iOpzr0Cp)Z}ZP2%-R7qf=AbElUA>l8WPA%EYi2(RNwy>)|xN z;YJ^#r>{T}@==pRJhr`YDqzIK=sT>f9G>{3Rw^E`6oo2J~3oDV~bFmjW9qEuUdbf9#UK0`N#k zKU0F79?rkKneT%tP~41TCI}KTc)2-|IvqRwP(TGeImq|c?dC3Typ`!0>rO-X4 zM`CBVr77#DH`#vX=O>nZ=q^ha3dzN;%wFK~B`go^R$CUp!)HQ%1eu5bFVEqH`8|w* zhF$0-IxiSauiN(mMJUMge50NRMFwgqv^Gf<@kz~F+^e?X>S8NWv*7zhND|eXh*sCG$ zz`#&SbdhVm$A)|8bob^na!$dza7xY*f9=Fhzz$DAc0i?5t&Mu*IP;~mUx6DCuU#ir z8tnVZ(5uo%|Crl5rgYpzMT7d*sk;wdzwgvf7e^CJ;81iZrU?}8u!kvaSQ*X|<6miJ z=I(Y8>}~#-s083qaP5O|>EIt8$-g|#{X7{I=;;t5@R|4N{8|>zzQgA5F=Mg$(<;5ia$& zeCv+;dgrrUB7u!Otsvi#*Hh!1pRKm8m47t`bEC^44jrcx%Gcq8!6JPB;w3M>!`#r& zoGO6laYBsre{Y+14%QwX$v1`dL7#A7X3a9Q|r3!!6E!#0Q#9R?`id5eY5|3fBTjzUD_@UNoIJ14s@pVJ|8;Y zjB{c`<4>Uj%*NGEz9h}^N2gBkvm49Uv)G3l=9yQ`fmZ>u{3Zf;@i0Uh9@T09A0ufx z2n$Pp;(PvYeC}&sCMoem+EgWVxi?F>T=6r>5}jHz9iYjNPolP9wG(E#vfBgY^?j_(3!UE)LM zg}IHlfP?vl59Zm0zgT{azqUVoLM+SB@NHkBhC*7=+1!RD|Sy=OkRG=rhR=0gZgG<;45Lz>#*Uo&gK06-}|<@dlZu{nSuB4k562J`Bc_vORdQa=&e?s{JQ z?|Zj@Tc-=1(wB#Nyq`hO$BTE_^*R^|VUW%>Q&tL&#F?Jr>%CsukXp3;s;Ud$ZJ)W< z1D9F!Pun!!%kKt|h zxVCJ}vZ?g$s)#F^_4OjI+3{rkj?S}3Che#hFuz{t@Y{YBZM#VR8f7)kCCQstCFakCWrglnek#ank zf!BTihiB(b1A6NOzL0jPbvk+IEU3l3j(m8~(V)6v(9}>aAOP#jh7Fjk|HD}I#0cl7 zcQs<|9juvE&Qr?x0i)Btru9?hBX4j_X3Qw7UcL? z|81Rbc=@m|kNK2kQY$IePB*xT;Sz@od`g)7@mTB+&*!PEl&~L9RRaKfvY(2`y;r}wM2jAj6yZU-^wYr4Q+Q%kgiZwI$BdNnc<>0YD~HQuBBR>{_E zL-nOzz93WSa{lBkJP+eh$uPk;Tzu+6Y?b|;V9a{@wbR=lXHD-qUjDBp>u=|xu~a1} za$AxGD>~t~@1R?rH{+3fJ88L?<9ICf6kq0!fS*pF3FpK>mV&HP)3T_EULN-$HE;PC z%aB^A>Bbk!KdqD06ZADDpd&}gi>#sWw+y7JPa3j~ZyrWFJq;@JXtdA)j| zzq2O*9oP)R&Qwf%C#BL~CSNN*Zr;g3Sx3v%MYl81XLL{v{p~_JUu>sQ8T?HsF=PVD zCEeHOTLirJN5)C`q1x{B9NYhUr~TVJvwhrkyAw&LEo;EUUKD2kWq6&(bnLN0!^=KR;j6S20IIFN)y$ok0! z@*K#e4ukUV#!tcj%kOXVbR5tjNpjap?JOdre<&lCh7Sy?5ccoEf5g(hdCD)yDxR>B zQq9HEp0Y4SMtiRfT7IEstC*lzYR??ogrd5}4v-(SE14e1y^G+#y-Uu`C)>utR#jHo zsutaRKDx}ylhzMEr4~|O-JWy^c15Cn(_eA>IorcO{xZv&?=|KWNfT=Ub}2v9l2giH z`Lr$&Z?bm5-ic0?JBVGpcD3O98#(T?-VPsvk4RyPsZTsiM8ddaL%+~|_Vo=kcJeLb z4{JkhxhmfXVoBK-ZO7+xod7(p?PMB|c|!m4G~XFrMB%U=_yl(fznC59zA{RGfXaxk zrDXUTr?ihOCz%KL7f$l@nD4A`lpAcLL5{|e|ur2!RM zKopOG;S0S}M?#E*Dn%x~=Y&l{Bk>dOjiXe{x>fW&j^^9tGKYj^BA- zeb17rnQ;N|IQDG=LFS46%iGV;Ul#&*fz|d*ei;nsK`J^@g^ezlgIXBO>WmN}=b-PE z8v$E1IV6BImDxScs7ZB1B}3M64t^b<)g?m>W&o5PxGHqflIwDU%&Wagu-8&*Q(=g1 zoSx`fP;C;wc~kYb)@vvRytkIJ-)V&`MvJ_g)S5ln6(dPTi!0VAw_!X1JXl8jc941c z|MFUdJI;+Yh|-ce_P1P!5u(Sp16rFJ^h$B9VlEs5Q^`NdtGxJuEPR1p;x)S!GJm}l z#VT5ACSgimPV9mb)%3p)`Tk8$77VNhUv(#<&Oyge++XiUF6oU$N%nG>#IP{+Q+gGQ zHaF7g?HDslUbzOMVlekHj*v|W`p%jQz8}Jt$xqLG0X(J#f?<$(Kv#ib#LsAM;D?{-SB#db6^_WS*b^q))3ia8_Q#5jp zuuWVr|E2f0>)b(v&ZJR}q^@ZbAL6Oopqz!Sn>gVj^T|@o!h7Novq^|3ix6%5Fn*}z z0+X*#u*ULD%6OY_t8mJS8q{KxXZa-B#F+SE1kzd7C z$irAYI9w`}1ZDXHd=vF8pkI~61vK;_h!WX(xQVbOmw|OhFh)0o>@3?=-f>UxNCt_h zxUiE;$(r;lM$R7dIah;cIB7@})@J69{vQLV@WRL zLzApOeYT}f9^tn@o&V&6i8f933voM}nG$a6(a`@nWA%Xy^1UuYa7;34l`+1hb^yR9 zV>JZ&&_@E~!*<|<(vXMV!PbQXX8 zW3tQ^4<;(g2pO-PnclW>f9jpCGmy`uoI$^ARzDL>mZMS%$5SI>Wj$_orLUAC#moMB7`plCD$VV{9*Eb{) zc?wO!0n<=QcOHCsmR1VB`tAH{SAfH!ROJKVmw6I6HhNEkjWpU_^z~<`JA;Okc;Q`K z3w`xjjkEvx{&p{~Y$z+pblngZK1;hgy$UG`qQle^bz&6s+chdfrtq|7+=a9wR)5jM6^)MIH6O8!jd*Sj6=W-l8@!`!`rIXf*SAWv2293|XgNN314F2Bqa&dKGcKP^iJ^PEPZ zZo~^NnB4RoM2s62bFVZVvH0q~v7i3GZUcUb`NQM4w$ye zNSvS*xVMJ`+rGaCKM6Ioo28U^y5qRg(L^&@{_U;=wj|a~It1lB;UvWG)ee7nrBfmx zj1GU+l#u@A>B*ApAjda~ES@d&c{GgIRoKIr;eI~uD{cw@Ox#rtRa)uT#M9ZR8urSD zop9iFD)VVBNuj3-3dJXSs`s5S|NBbLUmnZhvwo}88sjB8L>%e(S(;6+#Z#Oc#g30Z zzB)YpS2UwM#9+O*hQ}G$z1dYp7+xidP!WY&X7FB3QlCc%a7PRWq(}cvEDz-LT>s^D zee2{dCUQsmiHI_aiotmW}S8-|3j z&m+p%7QZg7wL@lO1xioek2y^I?WE4|Y!N4~v68Qf>EvmyweCB47MoKMkt|PJzh7Z-(ZMI6?5S7tE7E!$Yv*vB_kCx(uA9<`yE&f-? z`ZqnNn*>sKdRDnQH&TjfB`Y=~>R#UK2d1r~8d~Nj9>GdUUvIdKqY!#FQQ%fAa`(eL z?`?vA-{YAr)?T78N?**MuG5Ec2V|b-zv*={cv=>_IGCa%ia!4LA0Q?g#gsSDSPLb$;>HVFV70HF*)h%7v z2h#HT63=_rXK?yzrF8SQ?JVT@KJn(g?Zb~AYgBVm7&RXTm(17ljCyFqL_`g%VbBN0 zwM!Xzg``jXdCK6 ztr%6QUHoWZIEOo)xTiX{@tt-kfh~gxjE`q)z{Mg3$hWGIdl%kYm|11?zy_cH0yolv z`iT29F0WL{#rDZpj165)NH3{M6g}sI_x8kuiNPdR4AP#5kYv^15+jrKAsyhOWoJbI z*%t}qt3(auw-{k%rAjZ9u$z|QTUQYdY#W~v1dNg&fI%|Zyx;~?z1mieXou209(P<`jW6`9gwt@G7O$%LM6qRnUT_w5N(adXh!r(ndUa~t` zhuIOt;Ja3!_@2vgEUViE`f^rVn~x;KS;xJUo3NhRUJWAa_zz-xo{Lb#siKON=f^d!LVr)d*pQO+R^#YLv2no#_5V80zmFdu z4)s<={?aLxd>hGb%islhl95I`e4;VWbII_h_&TXe;YlOOFQwpbiO&u*S{p>~a~TY$ zt!&`Vx>!|RrcZJJJ|>Af(Ce_`fqWlO2J~6t&bbxJHS}+Z&%A>deoZEC@fx*{X|&#A4ZUe7 z7R1OLLGG5Bens&r==Y1?t&Mt~&^-H>hVoGsgHq%Yj|0ieLfH$v28kfGxng~mrb2*^ zsw*1wYeEu%e2)!*Hw%h~c$>je0>ahWac(-gxclyAwRNoa*ams|E;_GlqCREw$1ziK z*avTl_*ZCCN{NkmGe8y?%dPC`XaV{5vevJd8g{V~PlZsZ*;ID#nKMb1bmIf34UT?) zVTEka7>PviZPv5hy%e3PokIi!YUUemtICjWvIZ3nd$_wQ7nE~YM{B_yg zH$F{qE-UK%VsSzIih<_`q%RR{+9m1QA34JyN>XY^NO4KsTZ4%9R%!?Wlc%n8r)Zfq z-WiP)1T!rGzqmJR_~{O^zR_F_iP}!~c1fqVu#qGeH+7=q75jaMH(a>p-oeTXl%LfU z#01xuJEXCeXF6#OBMBvzo9Aq?TwlupKIpm7evo~IKt4B`zMbxnK0Fo&@RCN9Z94Qg z%QGG|ePRT`fVWW=<@CT^bI=>x4cmm3h;sQ+iaP; zelgT~?uL7sUFTQr&Tk`D>&}CI5ww4m^z{7I4iTZ8JnOki6V|OQ^pg(V(g&kKOb>k^ z`?2ECHJ;>ORRQolBPa)9QSi_32V94BX?yf&u+x84AWUdUCD)Rh=@hZYE{8Q<1I1w} zjxO+ij9Dto&<;$jq~=qyZ%tL9yBzlWt4?d_xGj``*XUpjK)&)v&%~Vz-=B^bXsL#N z;F`3QW^yv(3#L)Weoaq4Uu$pcBThU2sAezr{Yw>%PhLzM!6AOJ@nZRD=mk8M?`i-( z=4QlS_elNvh2QTRPrv#9_471i`QrnwCJ3)|f!EjgR!!&0TO#k1UnUNJFoES~GjRRI z7QK-lo-l%`lFrHEVd0Z6q7`m}G#&EnSu85wfi5-#+8t?r-v=OHn={p>vPEoG+~G1W ziuAINF)iT(#Q^X(Js|WRlcJnsUhSW#t<2j zdVmk>cmfM#UkgzC9OJmx66qeVx9*tgU)-S0cS`JaWv9U!H%&1fkgg(=?)67Dm={_Z zh2A~zMU)|B3JTA-u9`AB=|(4!)knb)1M($ZJ+296;K6!j|JWqeD6=^hwCs3$f|al< zdkyjAE4b%RxY&wBIHV#zCrAw-%?IB%AnyAKRm5i;^pp1@2ca3@qxR4Ty-fZqkgtzf zZzb#^Q<*5hAE#eOpEODQGY4daT<-#!qVZ_*Cu8l%8;S>7Xf7pgO!#gX2G|6_J_Ft9 z3bm@MvX57`&k%up&^q9$S#Ut&stE^Q=VzO6g^ zcxg+W_v6GHE05<#LP&3c-eS#&m9A!D%OBsq`3cDR0e@mey$s_EYSA#VHrX|Jg25^$ zh4BO3rm{Igj4=Az#k+@oQ*(T?Po3;y+D0zH2EO0pkx?`&){5hy4A#|f=M^rAfP9-O zlRZmKfd>2>?+_>`rMgiz;;eQsiX&-!_aUG1D_i9XPphI-o9N`GZ3rX2~?o! zefI?!$7K_g+4GReDXDAxu-F8O_eODd<7e}gK(yc(J)-R)UdKIBG8W`@Dlpg0r0hN z8-l*@Sqrpq)^y$Vm|lW;NMPFl1!hZ^v_+jXqui4bOsI6GBYoy)S5@U>07Aadd&Lv{wyNGl~VGbr4PtI?wG7BGh)-CCZ6Z%WYQX4NuG59d^A~xpnrjK3n;(BY8tf6 z8yCs(YlJ?1Z1N%b#vH;KhF{BL=ll_<$TD+7TEzSA5=QKhzRSxb;w>M&N`hb8ou#-y zM^W*cm=FNJ{&Doa{8k7-X!Qc2GqZwe$>nb0W;r zarYhDr|S>pFaqy`IAM{f4F>sYoO%I1w%kTHklW`4knbvi0L(O0ocPj+J8`CWo!Z88 zhzK1|Mrzh1_@`L)S;KMUBixPX=8<2Z;nuf%9vY}7ay6J|0!pNmjKkdBZ;yeVzZN8X zSnkde{?NUIBBFi&9-EVj(6ds^nM7mJ;ivp!wL3}oEUqxo5spUhsylJ$z7TtmeRrhU zyoHS@%vOPO8UXmXX*rQW_HhHX&zKfMGVo8^aO_aqPE70W>`im_ClHP(c6-*2Ln5>a zEnUUU*Layj&?{Lbo(G%Z&^WZh-21xqnppvq)(UXX?|^)>VIyOglReXu@X!;9`WmB` zFfGx%Q^5qA{a(3GK2IDphucd@N-Ww<_wX+6A@%_zAHqPd%+g*u=Z}NV^f^NSAE%iG z2z$1F#&_Ur>L5r|bp=JqzZ{1twGNF&1-K6&+>4H->+5AW5V$@L)RPqzYsf?)YL*Ir z7WSAiNMW%|4ktBDB$E72>l?`D zk@^e#>+dZfKUTZ3*Li8?M9a|Yr1>VhtnAY;$0U~1@L}JuiOys)dKk_GlO%C9zSkn!RmQ!|9f91N#FgpXaw{Z}Kdy@R6&+Xvv z`;om?U96crhqj@Eh2ETaljEmDZmfX&U2{^E#N;4*g-JGVgSaVD?0!iGG++8up znrC77e2h``rkC(P&u8?Hg$$H8-Mr3c{zC4-y|u$HV5)?^0U!_o!Q+0SmY&tB>{^2ZkyrPe?}jHd>Slh z;4jU;_}|sfxC<0fn$&^9y@eS(+h9?SeA z?%v{adB(M0`t+^49}Z*J!y%sE)Q?(b9zUo|J0xt<_%$Im6=yGjc(6>mKf#Xg5fI;- zf&jmL5?_bz_bp2{MOAQh!zfpO4qvo;`b*m5(IeUzv~_fnHoqr35>sXC{PBSb%DUMP zL2{$hSKy5E;k7&ppgeobcnenyUm+Z+AFqT{riXHjDZKfj%#|U4cOU-js~{>6A;+iJ zxe2G7*=Dx2RNPQMB=J!>7N-(kMq|~$PhI)f7j={cwht2U^I3DX+x5fBF&nzUAtby* zL^`#ivad+wJ%oH8j4NL?lh#h+pRUhuRFTevG&w?wJ@T*G%b|GW^t$htXIMLygn(ZW zlUr;>Poc3^|7l9rmD7S_8t9u~QCde`xbK&Eju@h_ocuaUQ#mA8X&w1Mm*F!xdz~lA z8&&=9kAdhg6E5}LKmWb_7=Gn}?SljO$O(PcKA~Pn5fNvt3pS9)6R$XA=z9%m{icq4 zuZ)Q%REaItI=H@&vw4fpVr4{US5Es@0D{Gx*ZTJqX+*@FAt1j1{-OC8sPtQ*{y+XT z>Nnqvzljg zkPkAoT@`E}JirIFKblTd@9-nSN2?moWWk3*mCN8G>vRk3CLAWr?r-tKq(?peP0x}7 zUf(nBH??7HM+1(KQ!pmgZ(jy{#*ESYzrO#hUZbg#t-VsndW*_l#0I;ndJ@bp7O?q~ z;Bx-_>&~;!y-%7yzQcxzI8LhQOD-eX;gbBmq~#jRX8k~dZoAC6=`P4eGK+-&|L*&D z=MQiMiPy-aje=Ab$B>TokUyP#xoblPTs17kMP^C4Pu8B-X{qkp72ks!xK)`;OZbWJh)c=?FpPv^A1`8vMeqmaPZ&>_>Zr>n9#E1MI(cexIh#Lhx z^Yq+(Jm+dt%|&JrIN_otqCYkWJ3GqQaftKav9*@7>ysRSc=X%+Pyg?{f1l2PZ4=^a ze)PzFnpqr~8LVB8_d$FY$!ryd^IV-igO{~iNJjnXb7xfA$$iCy{#ZY1lS@JjR*O8& zg*jEnh=izw>7xNYy|-5B$tW4C+Aoz2 zHSr98gOf;WBTlTNKJh;9_BgFSUHAd>_}|O#ZUX!xEXV-mnG4~)U6s_N(oZQ4ue4ET z6T7RhVLHIfgOpu(BDw!!=8%y`%O{Aq`+jZWeavh4e0;WygCDvm(9|@!Uou!yumHaE zsFuo*K_b;R5qxg?#m&=b#>o!Gx@l}1tn9GQ`4QBFN#Mi>FID6Q@U9)PhdIaa>uT_= z39wnkytuUfq5g0J@)5CbOMsmp3&7W3Rvg-0ed(8AXuXbmPb1at&2@9AC5z-eIh4vh z{n-v0iUigmqhbJV|J;el5cbuy931n)XMfVY8>#VkunoW=HsS2NcajD_OHSaBn)C#m zvVH}IEAU#u@7MdU{@pyX{D>Eei!t{7>Rm1N0=-wBk%(b9&ZmB3w}8H*J_u8~m@|+M z%W(+&A$9Bk-wrP(bxNh|o02AHrz44$8km@VwJOFxW;8IL&(d-YcWPYR6=g3>kc-dk zxudAJ&}To}-%8=iPie#0Ox5kd0dId1F-#H*Z#4gO_M|r<=CLy~lj1b3bx4>=)#X|~ z=SRw3EL!@K6{1tGJSqhuU!pY~S*@hYSFrX5jRYd`oTcyrIC_Z=9HkJvlFR27Vfw zi(7u7NaE5|hG5)pM}k&`HQXgRb-4rim^~`U!1e*(j+_Z?T?SB!rtd3jpER}Dx|l!Y zPJ~1x-fC||a8iswyfoo|vL*;bl%1VV_R z#@UcNm5mP%ARmQ^5%>o%O9Jwvg78i^+URxa$3iQHGzzgA7<>mWR8+LO)p2aJQvGFK ztk-u_igJ}0ahYGML?<`Am`3P_jzSokaj%ixiNE!0fRDw?rKPd}8)GWh^mm|W{yOF) zp42Puu&4FXtiMBSUM!UeYQY}kV^HKs(4T$?{n3>SJE}Kc8yHgC&fNdb;u2#1?~pU9 z10nE-KuZC9xzM$z!4t381?{IRf33e!oPZgsF(@a}AK=WeQ(W9_uVh@JtkINs_o)u) zWZ%a#zZ1VYcR69f*?%m-HH0)e0^oy@Gf3c*pYWUd)Atr{*4QVffh?Fae$A*8r$gyE zKmU@kr|${%`0lPkB06xRpSZuyr zw5uOe%FwS#><|bx0wg*^P$Cztc+<0_pSCJusOMz!H{^)5>QErU_VV_yCJ_}2dblv; zzjBtF1p-$;s~gBGWW&RlSxY8;Vm$~2%?nu?M=Jbikd^oU_MLUja&Vv^{&=;;QzzdA0pv3ZS_J=#2M+ZAeLX_+blo2}dnaDbXSMl38Ai~7 z-ZctUwNF(2yZ`HRBGIUwFD9l(Ue;MGlWyYy^j#H75cM~G82*Ig5bnU;KRU%Y zAF7nNIE#v&W8pvO`uG0h)-W`pcrPdmzdz^qsv<7n@agiyiQ3R+>FVHdSKr-(3JfXz zwB@)yen2nu)W1Huj2-ZY%qsx$bAEt(os6t52FsXk*LHavFn}7daP9kk*4OrKTU4~t ztKwa^JT|-JH`o#{mk+Flv9I*o_BiG^?l9bmsyo&q|NHp)pXW1;4i&374eg(2*Viqv zq%M+lWvq5?7h$gxM8^Mqkdr*su;QP~g&U!wzeRUM!1ksMGb_St?+c1XHVQ$TD`~|` zP<~L93TR;0rvbnhtYC8Oxw!n3G!KneLC7GfKu*~X71ui@(627QmogTf#cyg&AT{oN zNvCrzK`}aw^-Qac80QipM=;JS%M>gG!1d=Hj$b1WAFT(DHueC2`x^3hMsV1Vsg0leNm z70*EB6`2MWmxYfs^@%qyeJHs3jhv{HC3;Lzg+TUOBDUMTC2D=WOE;)|fXsL{-_lHb zJEE*jR`>O1wKytffbS{xV#Ej*YhI!aQaUt@gK_OC-J?Wth?-5DwD`F`j|o{`#0Q+~ zhl~@r(_`rK(@W*y&oiREiDxV;4l!Em%>UPy_gD>n-zV^hI44^cDnyKyve|U0Q^t-` z0cQgJ7nEoetM2LiYv)GMfgY7jfs)RB2^)a{RHO5Zh|2GU@8k}izPnvv_hk82*Z_RL zy8U_K4F)r|R@mj+v1s?+4{#BJio|H+G>@T%Nfpp zrtdtgD{oJ_#-n0_@`HKpbqRKU#(?@f4#4ax{pirOKigvJ1g94RlkudT`2*#H9Rs%0 zo|?e^pcP5SDN@B961Ouw^)DEb%8e_s89Ge{iR=L>{`Vqk0AK9~ftzWPHi+**R4u}Y z-kt)PmV+rzY358^7=QE2GSv_g<=KaVRQ_lO_0~~m6%Lv5&E5E<#B#o)HjWCR6Bft^ zm+S)m@8>T-eeMhEFxk?`&DnY-j&&$^Ixpd?)O_S*6>QC;CKa}wCmu@1B6FThaHnd@ zp?_oD?f4xVVSB{xpVMzC42H}gXS4ynpD8pRR0jEYJ?jil?ZtTUHP^}h8}(DNPen|B zzo<%-KUb=NU7Y0capWD)Ub^7PGAP=6Iq3UYY%;2S6YYD#zdlk?C-7GXO#%7!`?0i& z45vT!|2QDYYKOv1fA6;2%V*fUqIcXTAKMv>ea`aHaiS7Q;~QP((U<#b2shOrL+#v* z*%3XBT0An~kiq!^`s%0<3)V6i8pW0`)7-G43`?U^wQ&%&C3liA z+)T1Jaca^%^J{+2Pl;vv;zAeh{DK)mb;55#fj*zFLk;;Um^&U?>oE29hbWMW^oR(iuImHx_ZBUUrz$V|tZpCxFFBcI{hq7YJm5NlaR>e(isfP-c zr#;$6t1UmvzXCUX>?vSe;~wC9P^m-LrZ1R>emc*glr$h6kfUmIpElpF9`*n8?E4mQ zU~pu5M3j*INoEt`W7sxH4wo+C_#DN)j00PGa>A;UpmE8<2lvxpwX1mH0b6WI+(afmCn>2Bp!nTPeZ zPOpI7b<(M)8Wo*JxGxRc(8Bz5hW^a_z#LUV$V|zlRekn_28ehwTZ=}hbxkgJGMO>) zl?aFI7l+{rhh`fp4#i!|(Sm%AN=jD%hkX9JV>;sfX*+9? zYKo7!_{~deP2Vl@D2Aq<>vamcP%=hT<7G$#^>NQ@A(kJOpEhsgEL@^=n$AypW9P@OkCF_><{I5bbo_w&OsagOm8OqhXtp%WR=l{HacVMb$aLvM zUbIa6JB}gzRtHYN+2*im(&9z-Z);0gYOWQ3pXoleGf58W7rha;!1Nd7DwMbVVi`Ck*+?m5-?XbyWw3(+E(Q8U(sjUXNWt zDRj1z&0>eGmhJGwQdlwo-=utHqBL)or#`qx*(^-pgyxZP*Ffcrb7x|wR8HwlhP z>`CO~`0|zW>F~+N-aWNy5vJ)z^JD8RHg3)^DX7;Xyr-@j!w{}BC_GyeEOzlbF~96I z<#rYTJ{X@CNv9SJetWkR$D|)oE&}NhVx3!15k!Gsm!InshEcaGZ%VLc=BegYSYo4j z8Xaj+7VSsx)bd+i)lns*Aa+oGIF+N|ch}_u@-t;x&)OnfD|b_sIZ+`03Bwkix7&ez zj@O_z^tvs(6qotw7{)lZZx!| zDXV-I`VaV2+Ar#e80YH_Z4b_W>$7$4QY4eOn^Ho7d-Cji;rr4&TcPA3#ekPszo1Mh z=RK?5fP7^U4B&V7>;v+vctZJew3~?(g3?ub^HEHCF(voms;1sv?-cu=l~H7ogSq2^ z8Lw-#iI*39CkHBMsbg&?Sp*-A*?-=YGoo%60rJy>(<6v;K?;253M;#@7mhzgClRl=FE&KB~Y`@Vh5U z0r?Gfm}@2AXMK`F<2(z+KscZu#>mt9j8YnhY&!=N0J%kglLXl>-?WLv^-g!Se7vWR zylB26YjN`~=+xSYzvRE`yZ_l_f}{_x(@p z&PwBbq^o?sK&G5_9}{bA1D+{?S*vQHWU&bhB<{Q1e|;ghk6^qX{ky#)^S{dzk+PFU zrZMbzzL_z1TNl~*nj8+~LuuZj$bJq?!bS zKe#L*Wz58Q0P(3x?WrrYK@w0uC~^c~2C(fDjWNQxjpTVvJ^pPjApRsrJ2tw6j%|N4 z`U2jn=Eo`BtG?tL*(P{>;WdsjYE(W@e6LO{kiq_W`3i_{$;67*wXy+2y!AVp!vvzN z1O(BiBL(Gqm7_98`EDKdNz*y>!Ht4-KN%rr8cjR1xlY@Ii1CU($x45Gw1-~cXN`rA z%fplS2@ta@#8TZMtW8m_-+hM3?u!mO%Kt9!+Tx+ZcnUUUd^nbhsZ*~Jt}nH~seSpm zU)L?GMyO4~K2-?hqto?n2HRH+@Rj8MNp;>K5TC2p;T!wv`08X~fE~4k-~}{8jn!M) zd&M2Bq%}L~syIFZ9_9-isnPCw(II6K&giTbFF3!D9}R%~2)@Y-3({1LU?NcOBA}b$ zqUp_&#xJSi?!fK*JtOD+-TlvNWAF7{;7f|9#wWbu(6i zZ@$5sL26?T3vuoC!|SbAcPFB>Bfy6~OJa9cUrOC+Ft>IkY8B^W3>}JV24|9hOZj)k zJoD;KP*%a(;dII?C)OxzWUHIKMG0Z4=8wYif6{&x$)JdVd_DI5U^Gwsdwcf=bF+T z6x`Hr@9&=@N0k2QqniB2>zY<{qsy^d=ltI#UW*-Drs|Tpp+ttjk8^O5 zJXlLQFqwDv1l zvPgTH2%<-he-+v`y~fkNb>%C2|2r>W{Xpp(`BP0Nhet0UKSmc%H>P&3w%r_AyLo%@ zREFR-f5f1!H_d}s`_I0v9>$j&wllCp8Yrrtl@lh3cts&UDfCs363^TAlphjS(do%;$RW60AKLTw|bve8vK5+xifl0Zh{)x_=ddS;=;~DvmSf6US64QtJ80(! zlQmAqIflq%Ut45&!&#$w<96KhU?^1CSy#g47&5930DyNYM0wXy$jmIoWaoeizu#`~OKY+h2%>5X1+Bpf{} zX>j`y%MJr$rtruy9tM>Az(6rvw*tsFhJpqD)B+{I_JgRRmqOIQXA|;QwjoQOr*~== z90d>`38rC5=ZS1RMUHX}{OModrcJ$K4k&<0^x}lNwWu?Lc3x>TbaJKY?FTN;2fjn6 zaodWG)QzDY{u)puMI)Y8Z9$`#LHI-e@AAt!yu3MQIbserZ9)^ew^X+o0uidL*}EOM zd3i4AMO+9>C6EuBuxV72|IVTP&-Q~&DKkL?W@6ij@fFtM zp2lgm3Re1pc$4Z!#{ItorQFzMq8>Q3h?y-zU+Zf)7fNNdH*Su2eP+jYw>2LY(yLGf z`MBM;)WP;m0DNEK8NB~n^XgGU0ITHA;{dOLU!Xo$vbGf-JoFqn)V~=TsPo$yRSRLdexIM`M+cyR9rRvR> z%j$0hUhnI#VE{LARooX(>&O|8GtVjb)c?nGR^&g|1(~~q}ast zloYT0W|xK#-_($YeXiY^a@6L_xGq&L`!>_V_nNRaEQqngGe3^B&}b@BEz(wr>I8o1PwKwJ50&!ELH%HjGFK3|sT8d`;xH!opzdRzCjH z0|wCv0X}AR^Yx`Sot4Jj_aZ1?Wn^q&@lMwP%5lu%96)|fbVd+u`IoxOU3X#iCf@YA z^#tr?g-wc_^3_?-fFloG`VVDe!HD8-(S9*>J6MDtc~C*9;1NfSyQa~V)fpyS){hS z9}o8DtNeygrHG1`LrpE-o|fZ%2*zih zqVnuf_ius&m1^DlKKq%=NDjea>9=WW+F=J z%HM}cP0kjC#bM%oJiog4blXSBSvc0Wa4<99e*1$n*iCPeN|diKtc~9NK%{V~VB|G3 z^0SN}_P?*U|M~qaT%JLkqRu1HCB?N~3fV+%$5*QIj< zLS{9^Y(5*Q%e&A)y1nH=?3bNc<{`7TkKfuC%a|-t^0p1xA&h7F4D8M3e)8oi0rTTN zpOF6W(FbGcdQ;J^*0vt^OcRUPH@Tu!mUl;RW^@NkWbj@{E6Sv79`9k|J(!=n z_y<+XONS}GVD+9|&NS`#HWLGJIRAc$@{z~>^L?IS17rfg=e}V@x;f#RNIh26&nOxB zi50EO%nQn3?0p^i-!o(cWAIV!hys=8m4|ti>Abe7ImULQ6Wf=m-O1|Xf_{GKF$Vc? zLb%?7o!1(5~K1J~vO0`Re_!Cn~3T zhoE@raVK~P$d7W^07or&@=&dIUIp)dwB^$c9>)0nl(V|L-rwu*jmxq6Xn`~<2Q#BX ztDmqyazWHFO@oIY9t00z?w!?w+eeV^%V!Mm+Y6ilzL({X%JgKYr_*8D+x@un8<5}n z=O9iEzwRV$exOTGj8x?JRx*vW6qNDf+@&=UvG~@z%@wm0I>J4`H9@JLvJUWJvL#NL z3dW%F_lDQ!wo=U;+4A&w$Ce)NYkwzs&Tl!7ECBZ2XQCfE!_ecO!L%Dpu&s&@QD1EF z!jJ1~n2%Tg^>HN;9D<$SHNdA#uyizm1Z~k?zT*9!BIXrkPjF!07ia$K$RXs#$)Emn zdp)n5L_*-l_GB<6x$GS-Hn_0JP3zKr6@GKFdB+57pTKBk`TkZYwNs0aRK0?0PVN+q zAtM2h3x^skqx-5`;5&jVI>YL&Fy~Qb@|(g532RV(R3cR1 zZ@=FFe0AoHSZk5IS%eh#Bo@Y8_lF-h?LTz58oZRVAYgIAH)+?X9}jLlr1F$2lZV*; zym{x%n|mfEfpG*wSyW>>90bVk5a*>aDXrC^vO(3aB*Hr)@zK%-uia34kJFKqXWyzV zU&w{Z?aV`*gc3gtpJeJ%=E|9mk#l{vAfL3%0Qj?CTme3@xgxy4V4GCd z{Whi=KP+0y=o{Bq-z)}RDi=akq+vv+=wl^!B%^Xp*SLz=>@C&&d=`8IxBh6Kk*>je z=ZO~pUnQPa{qO|z#?pk;>QmGog0>}-g`~Pg?0VyMoo8R?DCY7;YJUmz5Y93iYf`1m z(n?8Tk<9oP59`1#8i?>Edyvoj^$i%aU;bTRiU;_N3qKiH@R@EDlA&mJF4A10jds@x z`X(PH(Y~+xr?WL|ObnI*s+z?;^SA`!9D0yy2J}x3fKQphpfvun z`pav@SLIG|_nZu)Q&bh`iAU_EbhFRC3|+azc{)7WS4%X3CdSFb*lze8Xth`~2L~HQ zikSy%V-6tSKh3q^uYbZo{qOoUI^C*)w=DgdvZzH>muKUzJsY)09j$P7sb7p=kz)tX z4Dy>@I4X(G?98ZVM5%r!{V9cLn)y_N7w5_Td72Tnr+3XrA5@ zP@_JvNXK6Sug>3y_Jo!BTqTv*LE6?o!KJYz%9So;BG)~HAN#}RILs2>?JkDy9oEb2 zD7lf>0rI1Oi%?!%uvY5RiES&^i+D^v8nNaG(|?6v+wyn#%iYq?0SICoG;1oI(+nQ; z#+Q`6gbOJ1uzY!K62cG!_rsq-zLbb?@IOv91+2gL^UeHbLt;yznWqgAxO7U7YbRe9 zUyF#{(hOx(p=GRVshj)RjK)PFiV?Ng*5qHVYx=02O@YyW={Yxbz1sL4;4`f*m1{*b z-}^KarPDW*(th(a7wZxnhtx!n{=CBk5g2`qYx7iP5tGzH5F4^ov%_Y4bLQ#WKb+Kk zcPiD$Oz#QuvGz2B|MB!|Kz>co)zyqwgLa3X6+(AVP$J#9{k2A$+e5!h-aH8C_>Y_p zVgzjCiZ=Ec+&hgg-<;;&7)lHUvAvs8W4B0yOKb-CRwY+hETA7`WqEEOL>0#l=w?>S zm95BUy}CmFw!bW5pAXBdR{P2iI38T|_zY1MFkn$7k2>+B_P#t;`g&yI2lA03^#5~= z(?9@APr#mQ|IhQ=qD)aTtAR ziRPy2Quh>Ic}KFqs29SZhx86($Yc=UYh(*gP^P9!zM9IITiCtsrwUtA>lzD)>MA}P zf6lLyJJ9F5`vYZ>&69Z^aR-q{(&A{3ouQ=ZVsu#v#T`;!){=GkZ0MutQ zGiNY|n|HZjs;@NM({SUxwt2WdvR)~kX*~h_=_8*jYA;Nsz>V_ni0cEdKOUM0-*+8O zx#gJLD&^k9jobeO_>Rx(YD%DL@sbk`zM{QVuq&ckFSk%LeA)jwIP}>^*GfM@(b5}j zy#Iy|ntsJqVh(-R zWSP<|Ns#@O_ys~J28BA7-I93RQRrv@y+%6p!CfFQH59I&eD~30=ygS6URKVb%sb%6 z{XgPz%$dGYgrip(p zAiF_^pr`#Bb`x8E9{}<(MX$Ah?PCDcCwgPi`3F}Rv(2eRq1MwLfxPRQV1^fQeF=W3 z(%b1OQ_VYc$&iMqVL*R z&9ULY{nLG7CgW6hH8+cg2YdbO)4N+i?S)i6yAZKQvXy0KA{lNuLp1n%@xrv*6pCrE{ReIb`x9i=g zgajXd*Ig~sYIbCRnF8eb}0Gukq5Q3UT{pD%fYyPl~jTqj0Q2ZMOjemP2D z$HxnZPgcJUnpf54%GiyK3=CmV^#WTDardLt~UE5#x1aPvSeVLpu zYM)lgki6p7B3Wd(&J-22SXRz>&N9#8XF zSdR(t4b(!r#@J$D(=hgbj=JGXb&b({oh4ZIB{kyg@A7qJdBC4j_II}z`I4u>Az#fx zN<cw`mMS*;fuD;-ZTr3Rmso;6+t+mW=YQ&^gMp+sbOkql|h5WvQ zg!#$gXz=r*JDz^G{G-?YPS+lFiKtYDx6s6tVmV3R<6Dxv+@71>R)Eh$4HD_5Z7M<| zO3e8Jd39CucXca89@MB%R?6RxZ!PG2hF|!TM>#U;C>5Ykr6e7`oXxR~pxz&exJjyN zD=Uiu`Cu_3z@J?w4)AR?c|qxV9#B&}A>=j}vORnxBjc+~wLlM%4CUL24E)q3cGlbg ztIxXW1pf_da%4B;gKE`GUBx$%9aWvojYHsUFv#7v-VeDSmX7g+V4GD&xI1b~vfiEC zyECEw`a4!ww;q?#o=AiyUP)Mdk^;r#iOzIf%2%TD%bqSIw*YY)h-7I^aq*e%MXHwf{z|M z9O0RvSY@lWwjLiMYg7-2o5G(=|4!jt>ic#x0$b0#y`K52k&gGAaYo4vojv!=YV zMnOlSh!0l#&2K|>20xz}5Awa)r3H;aqdXG|-c2Nu8i?8C4WIAGM!-{dfAMI7|{Z%M-gla?B2U`k-4I zN{>^$+xWMhoGVMYcO%KRD}|_-}qXG*eu@#843OQ3d#L>A%(rQHH9?h(1m{ zE`Rz3;gQ8YW`ZbjB8X4??7Q6jhPmyiM6FHp1fRorgeaaXof0K^I-G{(D5_&qgsGSU z@|7#{fdBYX2zY#f*9h~=pCLjg#or_>{26`i93+#)H2oTfuLSQ~b1!l*@safgd?W(I zDRFAM3y(<}WLci!w5p<^g1t}2yID-&*JE<#&?@;+%OxJyvBu?thc9K?Rx!DxCpwUB zLiC?~?G}CE@pyr(n?mP`Y$&-4xB1_P^?xWwVh#lctsR#!eMklQa2ede_k{s`{mlog zMP~{cf_~n-8ClwjxE>Bov}miyJSlMs8xai`=%W|RIE3C${A8b{I5ZwwkhmQN>OXVPEy^6NNENFQJhzRek>` z^W9SCsayQ5$v!+p)PuZQs3Yh49&HB5$AUfy{{2rDP@fqj)?NEwy9~cmuN@bbo6{cE z!re)6-M(IN3p>8t6^^vsFUVAqy_8?6OJI>|eWmw(5Q0x?`l{(li2v)S(pli_v(K$) zF&g=NCx~w2sCl8dcAYSRZ9RXr+gNi?RPBngjzH`1@&%Hb=zA?9r8d_NQ%NyBOlS z@;0@>CY#jSQ7`w|N4jE%0ZCtvjsY*JJx~GlVl6P898Ci$o5MHvz4h{`LRB8fry#or ze*0h~pgseg`o0pTgt)2}*XSZ{Ob$T!v{IvnnUrPDbyT(@Qbu4lM=~v%8w#xyqeaZi zd;OuMdGF?XpsD1q(`qU{_X-_QpKa8i%EklHSU$~*z<*k6pQFGDa+mz0yW6gwtoZDs zaCn`LpH*zx{|g#fQml7Ksk52VGkaUGn{hlT^=I*xZ$8NPXX5{3HXpD(5(2LPD>{vf z#w3=zxvp@De-UF&>aJ78ugum{@}wn$dpDbg5{~0QIRrZV2nQ*dMQMUSv2fjDZA|oqIHY zxW3=*T&~vO9K%_Zvy_kA{C9JGyMPT+v8*HaMXGK61%P)Zmle zxOY`Gf_Brg4B~^mt`E=z1}5vhozFh6jd25;*8>YrX=+nufAo=Ae{mO)A@zl{kLaNy zeREZDF9!Kuv`aaGeg88D_`aiZNK{w}Xt=Zq^zUK5vg*C_b7X8}Gs2WBBp8%wXLzWl zjB+H67L@)jTG}c$d_(8>NFt*9CLsHdqsEl!bOyj@Ai#kY?pdssf@7*uSMKoU#dv6o z=FQn_p+32mXCFZ>S9hhUB-|f7YJmw%izN$zdCgxc`8Q>d_pQe*>GNHsARkLf;6B*C zj{x88R~V;Cv08uKJ*8~!F^!6Q)=zy_hlr86(Ao8_5a83rz60JwO}QJl(97(wL%0d z^2oheIC>!4*lcKPZ?F>+f)g&{ZM6594o*qYeS22Rgttzefn?^^H>YfMN2Ii+zBOYJ z;Cr>gZ;ev?(r|bn&jwi!Q=($~_icIHlbTd!&!=bK(@ANlb-uC#DLw9)0>hdiOrp8> zr0pDzw}?85Z8!bAXEn%&U1fa^c79F(-^AJ_es1uN8KF(~(A>Ta(I2}X9*#%v$PW0z zGu@zJ-6WPphxFzvl+r5OD{1@%c2D{2i_0vxLUe7OwBCi70cY2_MC|da2m21WuCLuX z5aty@TY2F0NTQRkrnLAx``(I(e+XL+rovyMM&m)N5^AF6-EJb4dz*x=$UyAFK)6>2 z^5IS6{Bz*nKYswu@}LXAcW&+uCw;x8V~o+9PlIap(}qFDPp*xEz#ZZC@XR>$7xMxI zm7dkrej^T@&g+%-;0so5sIjfu8Qd;USJ}6>4}knO6mbaZ(cfWmhB5EP6c=fg1>xBU zc=+*Nu;W}j`|zUnj}@vDlXLux3llALPFiikjz}c6=TYJNCa(hgbL^WzKDLio;4d$^ z0(_Frd~fSW1w;Hx)gn8Y30gz?L@hY3zc@s6-#6wGRdPen!S5klQ6_41;#(A9eMP|C zf1nqZUB$p$Zs;S=r2@V`kY&1$3dD7qCH~R9O7ZYAh2qw%jXwIl|AZBb@$8HIa`4?e zZz;~!SJUhoT|t$LE?!4M?ot55K8beK&yHBP9ps}lhAaR(zs~?)|2F@HF?#o#TTB{L zSX;t_*Ni8s19|DScInLSRPa;sVTDa*XwD37RU(B`tpR39o04DQyxPQR*GqUZJ{!18 z0`e=wzA_9|dEafpIirM2*1U!H_2;&ueX*{YsnpT4uU}#bbFnBW$lW(sZJT^y4H*mG zwAW!b*v_hv;>~ci6harsN9PFd2e!`(;QJOyUDIGEg7O|zqfP=D{FbFje@ABa zA_e2&nCHgGhlt|-k9aF?^coM$rlR9{o3+$t&WTrIej5LeVc_<=RzvO3x1}^p__qac z@_Q3}f_*H()#u7NPY>Ec&%Tb34Vj9@g)3_d2mEbPM@O)w~61d9Oyg zLB0{rJMiBhd;!bXd;*5QF2D4=6Q|TdrD}+I>=$pvpAy&Fg0qS2X3nJ~X;%17$u6yC z*;aL!la(BB5$EsH&ohlnwz#QM6yapC56BM=$u{Oyu zP&7}b6M#;NzIiJ;^5JcC<&W@6^ZpB&docG6S-AG8KQVUw=3jj?Y2KATB(h6L6M)Xo_+fps6z@S4o^~0 zc**NH{e9U^M5D4@In9|B*Fi0;e&f^qARm)vVma9L83^#52}#d2TE9~Z6|3t0nxM!p2=X5jTFvrx}ueCL~$AtlsvckW3| zmdB{$Tf{EKrmjKwoFC~%`vB$aXX9r2a?*IeS;nPivZIUsudktH=;3PNYhCQeKtASC zF))sL|9AT+4B*4*NZGDtXOP8No3RyJz2U6dTA?hF3vE#7aDLY?v5LaB^U~!TxhYc3 zU{tma>2<8PkzAjsnM>eD_d3Q3otO#0_2)G}jbfzQrNH%K4kdX$vSVhVR*Zjuic0V5 zP296@`o&4ek*UdQpCs2AtkxdqRWzLaBfJPDY4@b(Nvb(?+BnEp-FpZA_89O`%EyvO zln&`zggluw!ud1n9;AQ%y9F~!YZ=5ey+GzjRp85igi#a$tmm>$mBu?Fd&JXY^uFX5?fC{r1Zae_TBc;xRH_?PCn^d zc5wvrb*%ClE1T+OaNE>>_{LeP<%~Q5@^R^!fIodA3XmT})Xz-p&@@A~0nArMb zmpvIQks28plX!|x)x+4m!&w6=&aepAMi*w{{Go@-uL0LiyZ%r>eve%7J+_Yc-JIP)Wr)N+s?Ek$P{tZ(A<-hyr9p;Dj-EwZ+dXLj zCdMK$M~{056VW6;2bSQnq+#&WCG1xWY=AFHJfNe`xqZz!f(DCd*{Fnn+ywP0Fvhz^ znvwL`_hKo8J<6ESVl!R+C>}{ix0P6Q-;DcR*E0Xp9g-$$c)~QuN0vB_2e$7Ez(;yw zWe6>xxhPDG(#Mls7ianTHr}%^x!2Y~wn-|~blnlf{O#*yw>4HY#<3jyX;~d7HNNZD z)K2-Tr)HAt!NAY|4s*4_F1-&o$QGVh?yBra7mv7~Qd1|U&G}xEJ^Sb@ zliq}5BJxexJNI)pJGD+2YSUU3aD%Y6@P78KepdOShrE~Iu!=W8+E1Fz9Z7%<7q5Dk zb}cd)8gPTkya4hAQ?0PrkFLFH?@}=A25qZh9-mjr$m)7j-ydBI0HIw$};$ z22ZLNujEuL7g}8@e&+0+i?nw)Y_$`1dav;5Q(n8Uye`1^<^FpPwqsipW-R7=ZTlt# z3WveB%dE`wG{VgV&%W7WY6-5`?<_p0LKtGK$Cii@d$f>@p1%v8NP{q5z)fc?fqalE zILTn=mj=jhJuxn>@0}L+MdZZHu|Le4*JNZohOag$zY*@g9xuZ?77zNC@!MHMS3Kuv zf%X$NL&E_cqIs8w!N(X>HV(^b;QMWh+4lq@HzKQ{obBUPre>?-@Ue3As)i>WJ)+BJ zUt~k&7{x=6aQJ#7`uWFcWTO}KZiQ)>#SA#bPe*01ZVEt3xBO-Fw zeRRGTlBu7V2)l{E3rS{zZc^x=Td<~7SHdYfJzD7?-=bO{7G2|3L8Kigc`e&Q6Vi`# z$SwcG{S9z9G;0s%T0MuSA5wxE6aTPW=vdRe8AlZjk*o6V+OzLa_*UV~O63w)>8oib zHK>71^Zn5cMAE7K@(p(C8T$~6HIR=><|X*|_bfnuw6TgN{QY*8l+EAiRDW0D&%VCr zK(=w?%%mS?Lb{>jvwIj1`ccxL2a%19!bGBtDT<^-*vyc0IZHUXw74(M>cn|SQskd0I7WR*@r!McU zg%;GmReO4DfqV=^pYOr0&m4en`YAmv&r5K~;!6$9BD|Y%32VBwkJ&`Q6BpY%CnIwQ z37bsq&ZtN!X(0rMwOa8l*M-9eNYzfkKWjE_q5{yH0AKWpe1Z38MlQrG`b^=+m-s<9 zV_uL|S?nlW)oRbayQR0k<9=V*_vU^mP2IM&81}nPvK)en&@Z3Xgzzk(rQQBFzhn4H zuzk4zAM{d~$)#s_ADQB$gs$H|78+wVvY5>0R*DqT=Y$=~AKN0)hwxVQEx@y#kQrC3ZvGS8V`(|I` z4B3yxPg$9K$-94-Cd?FVIwouQs-+pWejDR5gFbr?vto3}+ol zPgkW_6@o-;RkF9K{M}uk%TdIt3V%ey&n%J0I&^M1Gwf?Z!4v%6R}=?{wa(w@7FlsC zsLu}IyMqZwAVoFi!%f#S+!*mT<4Jlg!p^mXFYT&C_v|z4Zk%a3jkMTUag6Q_bFy!w z8~LW++-)|GURO_-BgRO30`f6Q$1sBJD**U%Ut+w0#4rDdb?SJUe=DBQK>e+)XG+XW zzm}BcSjIqq!Y-_eU2YGaOwZE9BaVHLA#||D(Npl%h@nu=7X_zofRB2auQ>D@XNbaB zx{t0I+0^$b;Vcz7eZ}{`d;jhq$>rkK9GUv8t(~9{!K~$=7c}2QkMv7_^H;G?y_qJWr2gi)lT5`@8T{=gTnD01;(%gD9tPf zk1DsP=lpcguf=~{9Zc>ZB`ys!_h{^#qjba4W%hDyYvraV5xAz_f_y=T5}07;mjt-K zE9(&dQLA9K4&#!tNPtL{sq87_N6hZ$ZCR7A&_?@m5sz>)_%dgouOealTCBkLCEu?L z#^XfO93qwr+2J*IR)Eh!WgsaAx5?O0c96z7>$fytW|8z7RdD+xLFwPmbC^)4Nfb@+ z(9K1X+L&@O;(xp$i79KR3h~Waz!UYun9IEb`4G$rKY;Bk0pw>nGC>4 zzBATtzIOz}tOi;0$$|I&{~SQ$gp3NQWb2y#sqHzx_^^VD75|z0Dz46{z92G#IZof1 z(FQH|Csd2rSDR};XP^G9&(Df9VEd{7z7aKQ+;Kv(X@!+ZL!>)7*wnmqODInbHO`~J z4EhyCEZL;B&Cuj^3x4NPF=U?o*)17SbJ&Gy0iF#++d|U8Wy6g2b2^w&gmdw<%4LLWd`eb< zj~a31*>}XEV&vg@(K|9O`bMn#(*-i6WlYIY^`v;&?}t5ZMG{+RkWViS75vY01Od-y zi%D?bd_$%1Fp*sniiL=AadEU5J)7;E9*bwb-~blgT>D)26a zXR1{w>iV0cCBm!o1M>4lt%S^Q?I4WDBODm`^De2&^XsZWi_t{Y-PqQ%Z>xDfbk3I2 z#&l4+E|gSExL3W0^Mk5GrMMXbb@z}^{unICN8v|M19pA30P@RBt`mHLIThyfVabSB zw)!ViwoA}@7Y9n)%h#^B)l;yqcnN-$nrxwEh3S1#Q{I?Z^77Bv)9h85r=Mf*Qam~X z_@e#~Wp^D_Mb!5VpYD+EmTr*l?nWAT+$gy#$i5CBUu7>X2NbNEHk)Zq zSO2j=Yp>a6jFHC1+W<)}Xq?z-Q);Eo7_r`|h60&pmG7)gG#?d0bgE+%!|CGFzJ(ct z053n$UcKe!TcX_S3C->ml9z#B)Lg*-Nv$p%OMVOLIX@5H4Z_5#seq>X-`~38aIFH; ztJ^{bw2ORcZ}?MxfR{TV0DPR=u!$i1dVzc*Jk36AUVoQ|@Vh}OA=d3ku|FW-=ijtv z@-o-k@DIMvi;jEi8;ib>Cthoik4cfmX(Vsp;UOHl$CMv~aQ=6S{_|(PX{-JDpZ=u< zb1|kr7q8}A;}@@ugJ5c>1dd8fAi?sCUrp#d|LzL>dZvS&90qPp&HGjgQpDT67?Y}t zcM5r~(IG-xXjr3&0AB{%YtWb10A8LbyoAm$yY8YJ+a8M>Q%(sEx@fdY08Nz{*0O*n zf`6BR?e`fLiJE@riUMtBAA zk?+wZfSlhDP=1Yj4xg!Jpl2;jg6oHAel!ZYK=ruYN*GvH@OwQ1NrN7i~08AQ z(47YO|7roQuZyN7gU@MWFP!<+#y}x~k&E6|5G@+txAInf-~Ks2Qt8eaOe(-qmigI+T_XY+PgXjcSG zr`eH3Q{p)8YsfHmajanBpIoNj@rG^2;xm^r2$rsrk%yxm`*hO)-w)3p1ERX3Ds*?k zM$rWJ(<-3}xtp6%T-Nc85|ZdaMfp?d^~=Mxv=oat1gVQ@Q(y{x)Nu)f5F3nRrWRLRt+q*7b>=XDO@O+C z6ScY}GPx6ec77Y_abSe|VK<|pTC%8aS2_Eh-PY;(Y|2QpNI;NM#Ql^aj-BV620tb- z3n@?5qJyPJqsvwg%QPMqKOu>OAOp*Ne<_K`)`S`%TR-1i{8Rsh1GD$ z^!R@YFEU3lff=qjh}|5ifB+pAJ+=HO22oky`^Z zkWe*q>?t`X#xA$U$>e@vh|Am_RJJ*Pf9Kz)b4MgzR!3$`PN{Tbu;%$y#M3xmq%$bv zzT4k@MpOTVvf@tt@>qjBOivJ; zp*pA6ML8`_AeCZw`F$gh+~3v#o8_?bO(4wk5di`4FepPqrFC-~{*e?Dg2m}*jj%Zd zyFuD|i2JEDaLXM8LHb6lr$%*-a_~UA%sVRV)FjUXQt`_1Dhm5TxGfs1WJuIC^deVQXV!9GB`-QlCveegD8Pat7|EX=VFzKnAZw zuvmjj{s7b{4~B2epPA(eRev?-Bjbn+%|~V|zsx^*Nt_I(d0*|&bnG))*aUuKbWx)zr85YUE8Kr=!H6$ctoE%K+ z^LK6|%ULPV#rMy@)`tMUJB(*+!~FXzC;W;VE3vYIn#GE2`h)A#-wP$Tp`FfIY4OZ3 z`>|mbUk)iZDRe-UrGoF9b0w~NaTl^uR{16`F#UdYk8IpEuIWJ7!HX`H zFM#U%g%qHkQQnMU2U9Ljk=pn1=r^Z;?yPy&TW*pANBDPN9XlPHUmnZt`#cG%|Sh^EJp9kpkLH_g15guM&$lolh@cW!+2=z>9GQfURDFQse$g8W3AOhdjD zcaqf{2@RgD84C3kW#wcgv(Tba!KyGHY6eIuzTl7+zh;7I-yu44(Mk*apUZ=L<20ea zY4gb(>MY_If>j;n&hd*>$L^p8`fbq!@%Rt~she(r{zbV)&0@vlP#(C_qfnB8(b>>A ziLLpO{V@6vU{|JU8#JU&k+zRw-y|GQB}S8BEnA`9UF6xgSS@506o1(MZ_6PA+dgFL zqyrCV(23&Psqe%07Z-9WBAbNt#<0yVoEt8Qf*=(k@-3t(X?s|}jAy|LzZm>9e(&N# zofN!;%ZjQYt#Tdgkta?1TJ9Jk+&06&;>->34RrklYN8V)*Bw>bc8D0+A8h;yJLC1bj`UDoZKVaq~U9JRh@B5;FN|0c}@&wRA$oX)%H^8efhG4#uSIhW7XG z{@=gY{^xrH>Sg7;r*!~|ktQWI_6nFW=B7%iqN$*y=7!n3=MTskf^L|b6UENGzHe$2 zZ;9}c(ovf+++K<2aH2NCI_z^IKHxcq;loWa$j_mhK+iEMjRjYZ;vY<+87*;l0=+*D z@K7K8@ZFPgul{-7Y!Y88Lasw9ce%}1FWh@Z87Y2R`hD!6Z2MfKZ}mI3?@}u8G6soX zhUBIs7iuqQqZ@p|Xs>N2BKyCq}gNxudwB^v9`Wkojcn2(} z<$**eK24Y2J(J|$b2eDM1jxQ^AfL@1S&7IcQij0;=NGsZZH+C)ez959%4o?@yZuVv zfiDUl(hDWYZ6MZT?tL|$_Vam)k=6yrrdc7E%oPX^va2RkicvK7}lef>nHl4RMI zv3l22!};*@Pi>p;e$V;++|UWSL2cf3M8>!DsvunZz?+OaQ#fmUsukHt5NQRALILn` zZLER5i`)*7&vU*rgg`d`ikH>E4*JpYP3@x|LbmXSczvvT#mTQhnJuu|!|ukl8vz+Y zyHY7p%$E=oJFYuI_ZqktYY4h%F8_Vb{?B_ZQMuk))#pi7DRI|J_d$qyTMQXpc6d>! zakHjZ&%Szr*y1qcdmJ62CPe+`s&ubna zGPG&C?+FnWkm-nNKdZbCL-jZ$xJoBZD;%Sd zkd~V6QDi258=FXv$~sir?$s6HMZ)JG@TDDB1PSy8eud5?h70piPV(OOL5ZIfr#BL< z{DFLB<#T{%g*MK^;W5s<5UDB( z&L^~Zoce`~UwF*qAIum4J}{2+FChD_fqbt8Yt`5SV92X1g%sL43JGN9d-6M5_sSTs z$~=^%iRkcST6C5LqD3bT(oB`DD&QcHm%PQu7;~U3Wk1wMq>%&p>Y5VK?$<{;fAwnC zr_#Mg08`$meaCEQ_I`|j;W@v+PJ78ALM~DED(be!_ItaJY9vrk*|X=vH03{Zpmc3@ znE}2xSwDY)?7Ic>jpcoE#JIc3aW%2P$&m~v{}%ohCIG|FSq^Nvm-%}h;R;;YQY1`KGoT5{mS{U z)+_t6427$^MdUw*7NIL*D2Aad4;m7_-Dsa7cXdo;1^D3QE~G&A-2wR= zCf|f#mqwnhPq7bz5yynGkZk6ap=gAgzt?A=@8Wn5W8x6{b^5oNW z;Eg|;!uiu9;aj5Dxd1-mRIFZ*^MeH1B%OVkb~++WQ&~M1KE6nKPJL16az5rFPGO12 zWl&p!1SRvz9{P$|=$^!vG;HIwlBn^TQfQd>ic4)l;uqw$87LrML(jMw*N^TYTAY!9 zOn$T^&QEX`xG07zv;6tphhA%4y)rD3df+<3)Ih?8Q|Q!&rMcMY$KZZB zGb(YOx~;r#*9iqLFFVxlH_A>dZng_HY3NM(!Dp+vE&Y}Gq+febLyHa&lGq;d0(`Jd z`|Kd+2LqI!Svnt#8<~~1CCeuSvHqEK|5$rQFHQM%zVYB6T2-{a2JuZ48QdU8+rj_b zHqmWz{dR-h`KN=_%e_@97e4#3emG40;0@;o=Ahyd3jyJe19c?$JPN0;KbEh)W3*&j zVinNatPibY1Fj={Y?{QpedOc zzRhP)IMG_k;{|OtrX)zs7GF#es788P@UTJ6on}kX-Z-bEq;9V!E*3_;s?i7Tr#H_T zzCt(UJnrCiv_Ze1VSlAJg#A_qhC!BxZ2dXE6o(vJ#z~vQv{z+ogIN*edOqmsjkx8u z?Qz<7Tc4!+8pQ!VYJ))#mPz?nhm8*8bMs})jvpC|tfL#j%hX{_ijw(=a$iD!k#HGy6fl=51H$-J59Qc}S^@vUq z;2Tw;1$~)XZJ_%LT%q(zw8`z&$ndMRupnfpwQIjw&5QvFeD(p)cowad8gs>srt(8A zm(MGM=m}n>yi@Z?W@MI^HUkWvBG{W^K)$DveGDY#FKK2qmQ+0hyk!`j(+6NK(c_+! z%s$V)%jGXTIhtWO3mYWdBvZI3tde6fjQdNl`GH!Ilw-Mv8~=O<`iG!DU+Vz*2peqt z!231qXHhT3RT#NDL{-%>^N>v!kTmInI8Sgmjl4|!#t0yF7tU?T|cZ+tjMo{+%Psr|j<8_fh{sRLuy1UO4vf z)pwRJVd_gCKBG7Rfh zJwbhRx1qAkFW`Nx`G-K55N5MH_pKS!YMfJKu?z%k<>cBZ*(Xl^hxeO%33t)Nz;#T- zL?UJk6tF$DkmeL-Rs>c?6Y%VPt^{Cl3f2|Rz9=VB;it3Wxph-wsKiB0bWhjN(=3dY zQiJaU%-b5$&FV4$ADPu}(C?o+K=;p%HnNA4H8N4U*qr^DyhE*l=FnmMNm-Khuh|Xs zC-(;q4IwZ$2m2y)Xw^G%{BUb1`=7!iIg%~U*ZZt75q=~CwNGZKt@mGJe{3_mOE zzHb_q`SYmxBc?hq(PZG+cc4houme>!I_uqBVh{F;ivI6Y(ec#pUwcUpQK<)K%1-}$ zlvj5 zV+-t0%9xWC9A8U{M-q1iow32mo&W<2|Fi$a%U7VZMY}}P2R}aV9GM0y(yi+9!IcwD zm~dP8*{95e^SJD_3O&i*I!K|{rxEWJadeoK_qY8}+qD;+dSWjp6vdK4ht%gpM?bVHYY|74 zlU@Uj7uWoOv?2p2KZCedF*NNRh?TYvD_bMz@t*YIG#kFI4NyOwQ=Wa2TKy)B>~uC9 zjX`rycGFjkZgw!l5W5$pP9YdlSufkgq=?pzH5|jhB(o83u?;cOr>k3Dv2gTIN8WGz0Kz6OQSLB7N`UaolE%lMl&Z@*ktbmY=VTS7jBbTliCknePmYw z_`r5g7D4tg0QoqSsK<`+Q`Rh{RnKRJ6&W>;#0$68`Bid zmvQ)9LTg0h#TF97yK&T%nFON-GrKAu)oS7IuaOpwvdWQK-vWGuYL}q5Pi7#W3m%+s zVj#B>y3DC0BRSiZ8G`@`N_?eZLOjK0C=+95fV9NzWIlT*{`~4kb z)ZYp&k=Een3!TH{-uNiA5NT_EUB=Y}_}s)@K(7;-1iF8=GTu`bN{hUP;LU#Z`b*A6 zGJe65p9c9p+!wO>Kq7UL@}Dh1h$$?;;^Fz()fP6HZ z+99l!rc0wcw_NHowZXQOI-Ntx&nyAn8})fRbT|*Y@dR_Z>RZ$Mj;KirEN{U5|FO zebwqfTRVIOG0bY5Cjo`Jxwr3BfP6W7)_sY@X7HMo8(`z9j`j!%iOQi_xESnqJcc%SnV`JO0nA{s53Ck=O* z;?{*&6wyeJSM{0h2yU=`%RAUZ#0=nLJRd>;+4l$N`YWx~G`WVUXvNmrHyOBtAhXL_gv)i zd;@v9@;6#|2xhVG?o6=?)Y(7Htqu-+Y8!npjeD7=Gq!L%={Fkwr*y`IM<`=(snB}Z zL0^IC@3w+^QBo$B#pdq;zU(tf2(!o+ujj=MM;y~Q z5D9)d9Cj}7{qY|UuP4R&|DE^m^;QQ`{sslFRqC9Xez-WhL1k_U zh);fz7xdS^9-wKe;*U_IRgR%B6zPxnbYvuX@JXiIkwk;+ER!sFS!~P=r`XwdlD%K4 z_c9|5@p#sHF_fmOE4Ntda5tdn$oZRqcR}*~qZz9~OZhuhJA8G}F*JY^a)o#IZe8Se zmg4JYU+`8+9M9Ph3q&8*{c^Fpuf0)Pe_R-}-hmNhi*&VO9I+L^$JMp519E6W< zp^vV<88OATMykTx;)+gY#BrX}PGH8OuwZasDGY&`^y5h3Xm`J&5K$vW)=;euQ5B%HF)b}^|rC3{r2CvggzrG|qdp_-xj{_M-~H6V}jH$AFH z=y5g=8^$qS+1_|~-|LZ*l*j=oBX>My5AZQaGYy06GX(OyS$e`8`Kv=WbItjok&767mZQ;v0ZY%7*OFW9~smZ4-#6`uIbgCU7 z6A#?KgGERF=I8V;zhwc?cM$+oD}jUkpYGkQ4&0`$tV#$$`J1n>w|$2cT@E5MHOr<= z!jbo1%0Gb1TXF5W($(y6!Aioz*q3R1*NSu&m_fHhd+XoWzFY}B{0ILf#@nbXjGAVB z?{Vq9LM{qR$r|>2z@>40lyd0>2&=chhD~N*NH@75>JZY2OedmtB7S`A1rB zpU>b+_lqH+a~K_h6ZbE-ixdz3*pa+3qkp3ilzfc$v%*Ze{D*#r5Q zB^lWyCeL%Qu5Ogyxe2brA(e6B5y4hwnZaKX)JNbtX4%&gf@fSrtrJRAy`FYk&#*Lk z#lLIn-}&xHg%1mO74u=k?br$z2>r3?c1h>+D+1#8(R+Q{TJI#p`(JkP=)a)fxfWbL z15{e{g|s54nS$6ZGN3Hi^HBdRn-^a;oVzAkRimpeS6Aw9$^~@& zSqB)9CX89SM7}>LIdwaZ^TKA0vHd~cyLd`;@_hYq1YB~ESy|Xuw2rZeuW9PApEPlj zc83&75&jVf_Rnc<_4()PA^?3C9d{rf)0oUkwUP$Jm?TyhKW8@O$DnC2Sbrwg zXk)@|AO@4QlF!r;HzK+5K2i*6{tQlM$%+xroX2EC+)6M9UItqmJ(?+<(2kp-gz%~& zKFG?(fKbx67;C7fj??kk$9Q?BNqLx|!O|IFNECl$FkJ{c8n{P!oE4AsW4g?jF6N8vCPo^s&OLfhOVECwRqOFzI%(mn&e! zvWC&8l67AAyW;rOK@W=58|5bhwAx^RkBCir17u$)kdG&|%`#>2T@e{Y0Q%cT*5XC3 zAEb#M_A~V0iHP$v*WNmB2XT6{YbMAJdQtAV)e0ip`&>$^tE0;a6aNG}g#s^wHg+>N zpT#LbEGr8uioXNHg3K%aE;fHse>5;Z``JgoJ~Y3D8&)W369xC1OV={aSze?>1j3vM zMolqVN3~fw9N?qk`w05*W+afWO0<^Z=R$#pY^2CiRTX&@xKrK%FYypj?Wz5@7zQ7Y z#3`KH#~-B-tzK>4|Sy)&$%B={b)((@h?myd06 zW$T0xhOOizMd;VFPfp4XHaY=E66E1=!*DfZPtQ19gl{s8b{PB}S%+&&Y4@^cP8rasjZ zl37`k3SkxbwmPZ$E90VZUUNF;wfMab`xVZtgq>^4V%{wa)iMnQ^o?p15O1)3Y=)$es`9Hv&U6kk8|x1Yccq zdBgi6_9FYou;Q72NiU^tWZ2N=&C4_^$=TVwIUcTE;jzVDSK7^FRXV*WVOS_dFLWijV^(4Fe~*fd3v?9%?%yB`JpX=FIHP$i;LqgUlxZ z7uZ#X%3WQTPf(pF3k?}#>_)X+3JP}-aJ6sDIl6#+XGl~nl!L^CUQ{JW%q&05S}lsO ze<6I*SL`K0c#e-(;Vqcg+v#TO_(vg3a-Q}+BGPhi4eE*AT(z-SOyAhzB!G`Zw(U9-v=bfI`W^w!7D8Wh;`kL}vd!EpZBwFbJ9~&zi=*y&J1Nn{+X2jJ~S%(zm z<|Qo$jS(D+7R@?pdJ7mO|%A{sS zSubF3zQHb(a^Q#-&zfLI&jk30j9%G-oZlB9pQcL*_!`a^+tW-s8^6fGHD4GU#ll9+ z9QBU)3HQ{dOw8u^KSqt}Y?D1o(NbedIP)p8&5lgOL6?$bn^yirY(V*$__~GW?t%?< zFl0OM_l~^|%=B~b>oU2a%!x92&d>PZR^n&3Q@ZvPz9JWR&cP}=(#Op3;PLt6rsP)I z1#a0~fRD*Q9Q5n249ItTVJ^KnDID)!u5{h{#LtF|CNafX`mHeqn$|)h7pw$N^OmSg zd9fw>psOwm?NPHk{YWh)h{13xXpB8_X%~3-Zz-obLIkQ5LvFCZlXEHT5Ql$0cJD*e za3a>+OL;37qxW!$^sE{Ew

      Wxa)WcIB^r`FySN5m_f~E#JbYxe1H#fa0~SBzu!RJ zgPb?$@zwX>#V%)flDyLclyAo@p$Z#il%spJj7S<4{%EJDjXN=XZ{_PMb&W ze-FFP_tCIIY?`b%Ew`Q$q6DlAhabFYZf36t;G>-MbppA4Rs!X>qK$Fd)xrm&B;qZk94@YNzlN{>S|WDTQ>v#6D9hMRMKiw z%VPSHn?W->ZQe%ReTsNxnpsG}<8VbWkPq7_xph2mX!*$t*XM4)(q<1 zjBnJtnNG;Qq`}c#;p%RRWtDTLOEXmEYG@ER8f{Gb34W+w{ra7Ae#^tYtOPxfuj9Hj z_PV)_KNGVTE|3Y*pH|=#;{p!R_HXZzm;S-h_1OBKCghn|GAbxkECEVazfhjE6Yf=W z)2Wcs`K2qaTL0yjEDiem`znwxTKYXAS!og&b+VaVE9(bI})S7)WspURCXlrFw*y(}|4 zvSIi(JEkzb%c|?|&Z&eg8n#n9_$Q>?7`|ji>9d(#%{>4gbfhNe<14#BKC%Y0>+&B( z_<@5AMB>>lTjBLO;KDSGB6m-Mt3QJYal-h7IjiRH1%n=2pr!`!oj&g74f5RM_ns5I zNi+&R3Ig(FYb;9^ezd-tPI0adxpfHgAxrsVFEnlz?DIhToL^rfyjV}a7kz7{>MMuY zl9~?{YEB{5SeWYsiDt3O;0ELa03SQsH++!udjj%(A9q%j{>4j1<|h3mBB#~cd@B!p zN)Ww%IDcl_D9LqNo+T_{?o~BD$C5bzo+ewqZsA3}$(QHrjLO1FU$!X?0=)8%>oYDpCd%Yy>K2lYtv|8{ z66Wg9N=E=b3cMp5kbMYH|9kxJ(>XGAGa6|UHoO8UKFd9$&?`zSO^pQ%25&s$Wdle?dtp9`_KH*#|5l>)XRnhQBqvf+~eA2GEz z=-WJ@0QpLo`RMRPp*{_s;tzO9z=A<>Cu@=>W@#W;d9pxN?wUbPGIzseI8+hkcj9b0 z`G6_8r*Uj?Fm4C+TvaLM4tfIlz~(Czm&YL;2WB>0H@a^t1B)1mbC=95;zE}l`X%S1^7sx^07hAj{wN02(zU_z3`=9 zpu7gvL1Arwe^=B@!8v365T?>)R+oc(~bs$RzOeZmH{b7i#;*!c8y}=OJkUk%*Z`Jk_@Cv2uwKHs zJ;PFVY{f~oG7ho$iJL__Mr^4b#yJ+u&+RibBf*rC!Vep57g{`n@uY;R?mWl4c11TK zOU^jXkN`Du72tybqf`Ug_ZrBzRP2Q@O;|siEFYm(f2|S8i9J3 zpxNr%WuL5C$J|!36Q!Qz1~IEMiF-2hl}8~ODF@RKsC{xuPswMa(fW%M4#H+_CZa~5Mv$Sqm!ru zz5Im=$Y*|2y(|koHQ>n|x(?^LrnmV?%;70$Th^ZHVt-1?psiE4lEpn3hQfS<|3*rc{Qp#w0Yema2=<#pNx_V%|)MKNT&1!sRhana;Ql;W5 zapHx5d;>HiPwtx^zEO9;Tdz}^lg8FyK7=m}H)wvX7kTzgFZDVHgQcNHbY>I?u9bU@ zgeYJgC&HOBTVY;kV1_!090GipS_;A-w@*eOU*lbI9R6L&LrL%VZJA0P3^Et35(17W zF2nb6@%8!d@xqU>@Pf?O3{^vhFr$R-I|(x92@TnjpdKP;m=Vxf$bfw1Q3!to5x#$N zNK!ve)Y&0VxDU11W^g)q{CueW>?>H`qn&qO(K)zOY$k5VE-S^5Fi1@7m|hVYuf>bi z_zHIh@KGx-g1(I^E0E7YzKcmb!=5%-swp=5{(XPkho-&iBRa2=ObSu`$EJNv0oZ2C zxF{nNied5V0KXOYK}58Zd@r=5cWNq`ot-5>zTl*kEcO;hmAm)1>tbpL@}GI%FX-XA z;nFA*Ej{}x?66zZKWw*r@H`~$?sw;T`h<3&&Hf?(SM=H^H3V+BoJ)X@-bgqX1I0jr#W$g0^ z-nthHl53q47wF<9z{|W>B(~v-_Y@@=`wkA^uz7GSq~rL?eL>`<~sa^;8wo zUzEYoR+H_LlKtjE>|hHo%Mg+naUz23;|KCJ6Qd9~mx2?QeICdsGnE)m{t0fC#72T< zCHC`#Lv!%>Y52&zKy?r&!hyuOv7xi*&s}g%q0WMFQ}Jr2^6dk@+5D{^Lvk;PU+TWv%-qe$B%c1v@!5I>*85i^r+hSgd=zIrDL* z5M&5|kBh3Z1Z1BOkZ*z{e4jTj2$>ifUkKzd*LxqU{~lp53SiefSL!Q@x2(tZ}#_AUBC6Pu>SUm;rU7OVO8pYOw*5eU;C z{*~7${_n?Y%Fqx&F(_!ZP;QaXF9J^`k;+!QiU9(J5TpOkswOyjSS8YotjY}`G@j#q6W7o?&)IBkklywLl5LgvE@InFNqy8Gh3UYkHK=H{y z^pckGH@#|YYhC@L?qqkv84z@X)HIGCfCWRQ_zI?et-fq2$whljt z-;ui9OA?rSNUR9tvyOaa5e`vm5QO1+Qo$8^I$E&=Mvr{!5B3@&{n;nrXtQ^R(0(B* zu5lfzdqMp>N!iZ_OUyHbh;u^qEvZF49Kd(Ub%qMEF9oQ3H-g=q0)@PRi3F{5fTLZ1 zXhrV>4EyAwGPTY5GL47^xDUTX(j=<&@i3!`$B|CmM|X~jp}jrh``7$2x^d>CD?mPT znTC*MussaCqCp5Ox}!@MILw1|3sf=ISLMUcK3lUpy6Hm8m+E8>uUv3wLPRsmVa=7$Vi9U7^GR$fBy-q_-E?rJx{|&OB!G`+ zrVsS)Pca~0&f=_oKW3=??_P$dZ4p(M>fwlwPVc*#l760!qCJ+QK1zJ%HH+pCL?nJ! z9j3lnkKWJ3i-2=2EtKoSF4nwr1>~dS{Z3AP)hN>pXB-!pro19hrEkMMnYQ#zEkXS` zzwa2?Yphm0rc)5uL&K%ocgao$DvBjrlVYf>wYoJaqu#FozBkp0f2WWA{SVLo{;xmJ zx0HY7t&%`K*G@NI1~-J`Nh)<*Mf0sm*SIOyYBTqGYCLCKkFA^uSh<2EC`;|(>{p>8 z_JJFzGdqO-d~d5c9>?jK)hD$0fPAH`u}gMMRcibOrwYLcX}falvLacR^%!4bh3lU` z=G3on4$N;{8EKrzjt=}%xkOgqQk`FC{UZGKM=V_v*PaOj;3M5S$pYCY1LQ+B5#ke- zD{-V{zXn$(Ice_UZ{BY~aAOF3!mhWOol#AzYI$--MY6x2;Z+Q*VFXjKy=>`Zgv6Vg zSo;CZbpibNdEv%-J1(vcF$#-|vlF~Ok<+H9fB5hVJd>xE``M@RU5p%y^rS$wMY^_O z_i46_GHrFD(TR;ikvpdW8%O;B7vOs>YykT3yDX4TaZ1VJ`(^#by5cOwjapWVMqmHx zxRNFJUX+)mN$=(x=JOggM=nf6JCeS%567u;%g`c z(05f`@xe21TpP4+X| zpWN*btH+;OlIWD(DqY`Q+~dB7DE+D1weV$b3~L0)_dYZqCb}VT+yD;T6QyB_k!|gY z{;fjq_qMZvr)M8zlaKDX!8-D5_tgnHUs)QdcP2fy*a;swkZuv!!kotVne3W9oogglt&Syi>OE0(xMx|Z&Dp9mZGrO^C&QOTVhnp^te1O`4m11 z=R!7Y6LYg>*V&l=_S!rG9{zKn!WwO=cU%QmEHjOKj7PHG&D67js}SGZ;eYq+8!e)L zRot(At^TJ~M4Ts%Q#w0FJT7=P!MX6M2W%FJwBR+s$92P04zf=b$R}ac8S<&sRr*sZ zy{UYNfoftQA0%w-H?W0h<)W`RmCWLi3rcxgUxg_STn>@9%*`De_!k(CVytGJcWPMf z9)XA7`NrbN#@tmD8QOU%9-fFf;@>noa{ju~Ag=>^8 z!XKs9Kc`K8?^1rBF=X>XT7dx^Q9~*2XbKANTDBE1>pS30LF6k-ZYp z@TWSwl}-tTIq1@aX{3lBhH_)?IX{De(s(m2hNylL^|A)7_*Dim*G+Rcqud6XH8fi~ z0~=@>fDf}t8uao44WRru%8yBRT28_smCsy`Cu{lMWs-jIXJ#H?6m2JfxBd2JuGEZI zexdVA5Hq8EiT0#PTtRL0L^(smdsoxAdrD;)AYV2ISRL|>VWbKN|Br?;&8loVt<($% zZ#6>)J+EhTXIt5*|9HM1>*{j>ld+v*1p9 z|7imGQZ}t>ey-CKl6!0#`zT)~i|D-nVuP(qYYG*O*Zs(@h?*n_OXmN_LTgSfhHg#n zjqTm%Vb6Bm*^IK@?d(FcZ$Lh(4xVOJoZLM_I%XQ4Qlk=u2A?Ahk-(2grB*N9pFM1$ z?=@)5>&ftlL~k$RRBl7<;6D~h=C9w3pPR&3wp`Hzd<0UvgCJjj+CV-Qnq-BuJ8Mri z{3EA}unPz-akQ4;u$45J9aeo$gRiW(V=Y}Hu)Ubf&fEK71r1#J;Z*K!2Sy78V~ee& zH%Y+VgKtWpdd^ziRjlb5re72CcK_gwC`QCK)O-jO|VxAm%2%ax$`9tzha0 ziBja#z`j#-vU&G551x{-AQQm%yMPY#=_|}g|NH%@fX(!jM*gi3RO>}-kh_p0rQ^IB zQWxV-@2GkK^f!}1yX}&Q5ZQ3nM!J)n7g7Z8hy%{4;X?BKbmjMM{A$*J0Oe;P%Z!)5 z868JBg2*1?vtwZ~sOIydrO31UM6mkV_qI`S9_hQ~YnGknfb!yOF2DIe!DeT}K`LR1 zQ|uunIZ?N*HrTn&7 zZF@93YEN0B$s?OxC395}DK{pfmVi_c~D2TE7)G)a9ak~~QqqC_NXZ_{*C1o*a zvDq;K7OV2(v`@h-?)9YFT|D`QmgD2&inr&c@Bur(_vmZ{difF<(EA_wFl*x6gNj8{ za}Me8Z}fnmFf80YFNyu!ksi0-E$zuVjjh{|67{3rDc43H%#EiMFw-&9S zjJM{1e8nNbf^l0$4qA_2cL}bsm-zd%q7!F!ro+mT$e!D$%j4+VvzFrpVdDbW>0DQ> zFlhRH8i_vzDp-mnO4**=8E*i-N~|Z)uRm}gpU|{Y^hZbJN7CulRbQzH4TqVs*l)yr z%d=+T9XhE6oIA^3$}>DDMk^krdjuxne%2u4ZXenrmo16@=sB6s83yt}EeY1d6}BL8 zsY3BXww1m~v-8YgBKz%oDmn z!)3z>@WFsV7e2r$P1#70;`KA{q&oyy5fZfjeGAzAfL^n$R~&9D2?K z4i`=#C}4~i6(^2Ok5#9`(TS8(1vL4976P>BP-$s_`oke>4WTx z1oAb-NM|&{AeZqrA;X3B+i>BhUh(H*`vwJOv4EBIxZVp4V(+SS1U8xt&77!T`eEIp zp9eGcsiM7Wci{Uw(fa}@KTkb4kvpT7tU(6d@89#qG>5!-{50DWgHA@6BA$JBK6`Zw z9_EV7D<$S+b77|iX3bJIU1YT^vJ^Dt{;&>b`~V*ZX1N{6zE42DKIKd(B)5->G@CR= z7*V;0-NyIiQkThW@M?<52IflLRcq?~GASSEb*ExYQ16yVCBpGmo1u;k9Spx0PRjp4 z1@isynj#XTwRex~1cSkjTho|(lT63jlfw;>_}2H?$AmaURQ+1e><>nLZ_Ig%*G>hk z8aH>~H9K7(UmAK6<$Do;4`R%&0Ayb>kPizINyfCbxheZGV?CrcW#_IJo#M7>Rc|ei zu7_DFjO(rydnF={vPW200`4;h>@eeFTUhMjp{F4@oW$yoCGhNb_Ws4dLFy)K(&*cr zklXO?rw?si1aYc4e=^)(hNmUx+%k}$Sv$7k|G*tu3`46njm==Qwb!|JZ(J4Su;=87 z1AHl+Hz3R|{`Y(a19X3RNTQEB*qK#J4B0c%!9-)#iZX18gvJ6_n~YM$w_C4_&I>g3 zt0%pMJ^FI}YhQvE{12nLVw3;d#dlEs-}jIIP7we5^FN1gGmhWif2$7i^9rJ_qxqn% z#w6=N&MzG(zrX`#eYVRFP-GUJYhev3ySGq$zmgH(e5rjGcbdgJ#neJ8%@-Vdylzq z&%U9f;?%&duKvC(>8T%9gbQ$%p63ru%=Rcb16M;VN7o)w03RG>Su)7J&p^Ij_@LQ7 zzpFihl%PIq^AhjfER%;!X&=(I{k|RLE4joIy5-yEY){) zh#!|<1n@0S!=8hi$V<;p5-&g8w?u3vy z_`Iv_(_9w~!*6KxH@?Qw{CN}}UN8B%ITOf;FWDQGv0?~>ePEbW^Bc;e;Ke)F+SZ{W z2@ZOvqXzQf_zU=h?W+U$`hUk(+&d+hQw=Q?s`kXl%Tty5Gn1^dKQ|dxU*Za<4&bOX z6s-R?Eh8vZ{)A+Be}T=8@E0e$hzc2!g<4y=0pPoCK7seU2^WuDK7!oU%)RuEhQGNY zRs3K)BH{buBT84)s@6~0_u~HXRj!gl;(KO@_4g@tq;7GdAQo4}(G@L_54J5U25es= z!1p>Q+_9kjwBYF*w*JVn?2jGtp1i4b19XP{pS`8i!V}8%4;A@07y3r7;&oTZzhq!! zamQt*9b;4bIH;Zw+6@7|&-(lOnXdlkH8nhwhv+)Q>0bP33U;CAhCiMDy}uu7HOYSC zGqwC+K*rdPiv5~}p1AUzV-;pxLpyZ*^*>^Yn)Gx`hMF`6z~?bvbZ)+JY5c1b zx&3<@l_PPPphBWY?`bDSh+x@o7ilS+>}a6mwg=r-$=l`$9(er34GD`{Y>1&HE-{*| z>utVS-C0!ZC++ukkuF3iFFuhD(d#Abv2Gg=c}@)`c7%sq$asAzhKLJgtqY?2OFA(V zknctd8T|D#G{En>n#UnS&8^a+3D4qd-K3wLgAW(?3%@qw86=^wNa_h_LTC>t=D9rm zqur3Jef@CwnwNRcl`;F{aTzQOhBS^{0r|0Ugd?r`|I%_>)U(8#F?HrD55-G{hDj}h z&gyybao@g<_?#{?gLjJ`-wuhK*>Wpyq)n~%vvanr*C$Hj1B)rh$CI1>0qp$R0r_bN z_RnDL#;DU=*BGQMN!M9Mk;zePgcg$p2y{b3qr2=Gn~&fzo9X3XnJ-Y$CsFG)TbBLu zHq`pqgEX2%4H*jXc@}?XhjU_F^c2xYC%a5k_tyhkOyk=i zXLXjH{my~}56hJ@YkxMEMrzEETVon765iCt$v1X;l=FMbEtMgON^2GCdh1IAeBtDK zR*|p9qD zmJ4Hl=n`yOvH|&UwMM`{USj~@qlnAQ<0^eSoDxrsF_cF_#xdL9scZp`E;Tu%ql!liV(6=R+q0+{W=Xv1Sz2K!1IW(j9 z;jgnruiMtudjE^By%Hn6;{$o}r7B;vR%h%1zdFfWV1oku!(64r9Bzrousz7fK4S^~ z{`3&Q_x_TMU}`$J4__rjQUzl2qwfn9b@5p$M{oq|w69l=}R@a^{J_Dv@ zDR9AH^Mg3{kr| z8(ra)WqTbO<*R4r-{VcHDRgBp*t(EJy_Y_TQ;=&$gsq4&(?t5tFb?hS9LhD$cN0j6 zp_3edFDV|2mhp_TGTSf1NQ}2mn!)kdBq5Ej_>Ql#_Ql5s&Dc4?TBNof5Hop#*z;Ki zBKQ`26jz`jwB(ufdyaaJJIMD6GhYvE-x9!Qhl53oe$p9)p%{gMG@dMyicEOfo2S=- z^}ciBhdO%N<}7r~0G9b)a<*Dk0FObXC)Wf99Bx-*@#S5fZKxrzeeiV{;UB8j#WN`7 zP4`Ho0!$uwcvTNe5lJ2nT+A0Ame$Q}vp}ZHG;HfpoA$VL#%Vbl6akK#I^B-Oe}~3) zTYG?fj&Lc^VEdQ=`zx}hSnooZcASEkD4m2(AKzU#XImw?Zsc7eM+qbfRNi!W+AtI4 zQp0T}*Y5R{eAc&vym>WwGU;yV5h>wkoQea;ue_VOwgaO4fo5L;CyvW;G7;JM@f9Y) z7y>HO)QgXfF>U7eBfKdCLfF)jE0&xY-zp%# z2&gHM;IoUG($L$&=H~{(3altD?OPI3aR>SJ<$F(ZBxY>!S|3(|_zQkW{5SvI!r@=D z{fF-`GNV)aCZGJI3E-0{d$;YP?~NV#S-KLkKEYs*4F6queghYSB2w0iuVHTfBBg3^ zA)4zzM2?QYIuph0RO?GA8_(AZs^;$_SeAYupP;Za`1|i$0N+;+!HPdybK2wZx}LBJ zwJVEKcQE^JytLt37KPzIUKsy(R#reTyE+~kwpt#qK@9!q=TCv8BgI6pBqoA{$Q;1i zS2VS>U{-oRQPneet;LO$Be#4#xhcaF z5<6!-84^8)))F%r3kLbqfA%G=g;m4EtV0m!eBI4_i{AkKyw-ce=B z#bV+juqU(87t1p^A5yAsC}bl+ zKI%?d@NcO+0{A?--aDGDwe5G%B0R4eykB;n%^F1L2(9TiBIm_n<0Ejoed??I!(P~L zq&(9!^0hZIx9hX~Zs>;qPsF*z-Bdw<&jOO+itn_d0j22^M?Y)K|<-#2T7fPxuDY8mHRS4n}=- z|6R@|KT~fE@dw}&+*8RjdLI%#`@>GuiGHaBKqUEf=K1jed>=>l zwsrH2j%mrrl?EgItaYNJ8GX2538LrA|FvH~7t{Y<)cPzN6mk?MI7x%^5c*`4dC_Tj zUQ_fLzxn7y%Xa8+7(&BNOr^{dTM40d>G`c75&BA)ttAjnaP^Qd~ zIfGX`cdx4)j5J&yFz}5XvxrLJ)oQ=Y^~G7GKQ_1J>XHsNh)Utc6+~}-F z(270h3oW@Z%41mek{_!@s3SUW2?bQ0{ZBj->Q@@NG0}@G7`YT}Z;JarY@o5Ff_%LG zihscNJpp`V#zxfGeI;4kMPq0ytAeK9zR`Ant*{!2BHpsVMdvCr1w-b{md+qwurkhb z;MEi!PWjDuZk;~!GkqISouFq2P>S0caI13pUW8Tj4lCTzv8dqoV`eBLmQt!K4L5?da!+vfa4=i6E4^1 zG##u<8SUeFZkYB+bnnp+052^Pr zL=cJ8>{QwTKBI?=sW&hQx7t_z9vl7xGVrjGMe&cVNPOd$|Hh}cElhEh$mzP4$mb)A1>%L4g$j3F(+_7MSmTE7^inNOz(smALLu4cwXSuc(% zQ#4pOmgO0j%QH%&OT#|Ep}acNjzUb#a;M&Wj8ttrBJ)i>my9vrxnrLK_P;1>sl3v^4wxeNst-4bdX%8CCe+#g^!$J_kq-MpOc7%~Hg3WU?{NV%g)5)ypw{b*1_W zBPT6rsO{&1e0aH!OT652)#nSqOsXm2_Ue*ec}? zNIByJ2c*(+3!eYP|FqS0E zjTMFnj4w&%`sv*6VJaf?F2JWnmr(E1U^KY-2ZCpkHoveadqm$>(W6Zw0cP*TXNM1) zN&%sp`|4xMkch`U+Z{(>g;MP3bbu#DwN}ej0aG!^$NmRL9c&*Jzz0JBK`fIEh3zLX zAhVI;d4Kg@%yV}wS9mK4MfrBk=oq66N4YtB_xNp*Ju-4=Gv#8ld`wpPA1FxD4w<*5 zGgAN`soWPIJrdH(s-2`xAJ|kWd%^j&%L{xKT8r}^FFwd~UU@i?P}q7(o-#b`qb#8b z4+&k8Y~OiA3P{|!dY0NUkdM!vDI9DcFTl49uWR_Vr=*}9Zk!HwvXM2-l*k}554m}0 ze0^2+%T_Iqw&wBSPx#c&chUv0_bTd*yfmkH`RXB@cfV89SgGd#zBWTi=I@gI| zRUlspLN@sOV`G5zv!#R@T8!7bRY|vyfflCpM0h`%uQbd!vv9t#CAR6brmT0{hUfli z39C4WhoJP2{%E*!^)s7u9SX~)3_&pT6R>|N_${0_ui>vA95yBVx^`BB_a+M!%IB)2 z(t{X{FFt)a>?c_#-4V#IENeN={4g!jtLNl;CNww~l*_z)1Cv|-^FfjMgWn$_3dpaB z>w4=q3mcYr;`Q_fExKT8DSki}*6&^3C=Tb?+;|_=Y;hPtSorrS*tLy z{0@){rqRcHE>{l$>yc=zx;8x7?C?2CML<@n?frU?$V2|V?F`H@?P(x zI=4T}2~*Za>B5+lGT?1SFZ_zCNEs3Bm#?7w5JEybz^+dzfRFA5`bc}4p+I9tkZAAR zZQ&dAft1OIXt|chun2fa?JNKKtwOeIF)d|BD-z560!p<7vm}fNOCPtQT_L*PMOgr! zGKyh0$2b5d7RtARjY29r*nPssJBmbh4f%$4Qg#o3JAF_n%LZ#OCNjV$|SxUh$6? zdO4l<7sX}}q1efyUI{0r*ZEZmh?)=dG}E2GgKbe!XM_Uw&*%Kg9eoZ^KwD;eF4xl+ z`)x|^$$Adg8TA2v1JOps;g)dpE! z@o#m~|^w^T}C>*3;W-BvX6F><9{r`qu1xlE)Jt~`&{d)Iwo>%+Pa}h>5ij<#5O(3Zy+6Tyrj2+0`M7}xmjzc z?x7K0RrdU^K3DZ6!Tx@+0Qe3~sUFwRN{0faNaz?|QSco0lW`l*5k@rPALm4U@O4tC z(fWdNyBsZQf`{w1laV8%Rmn?AtgqhUh5tBg$%X*%;o-weM7m1_FMRj*_hFrhqTr#X z8T4--BuDO6e#vhlIfn{zKx#4pnrkx%{*m-k!We;uQ_JwGU`A7nGVXR&KgdVNGKB)R z&kEo>Dp6|+fAgSUnq1ky&{Q%#?<)V{ht?!hyciW`s~YkOeX^BIZ@KhjNX_Q;`=;!L zTgG6`+UGjs?k`Vw>F<)h1AI<=DdRm6Iz;^E1;M<0g&nzF;gKnw!e0HEHJ@I5^`Rkg zRvTt@PjYJ)K`7@!Im_o-OmQnWJ6eYWOqB_%uSY;W0mESM_it?gK1{g4pPUqi=;1n> zklptb!;c|Y22hm+wsZW5Uru#XFm07@NDc7H4F_mlE)jk2N|%ZpCn1QM=G5U7xdIw#g#kGxPLOfk|1 zUFxSp+Bmr|5^qP$zrq|7ARn&8JT=()xd42)_l;poHXL8e$QPOROR=3hwcj@f!N%3|OR`f3G2kC#iDOv;9m)@-e4fi39%Ki*f z(Z}DjW|DD|%-OYt>fV-+`PaXTGTv)GWya~miSDS-;#9;bTtSKd82u%d8@j1!{b2Mt zViM#Nim`wL+b0QFzs5%V$n_-(M|*%K%ZpyM-i7Pyg}>~uwQaBpWzGgYnl(hpNA9j~ zE+cUFYdtpIxki~f0bvbwsDj~?BZzqA0S|!sJPVhv-lY$(@(rrZvEWUtea=%|GcDfTX(!mwVEHmtrVuT29X;M}x8>G!IYP1*M>V;c2d#+L25P1WYW{i(awt*9^$V561xh^QRxcXURn!Un4HTDav@P)}OK= ziLMRtd7a{-mYbYc@^z-X=O?~$s3e23;Y=TGMT^2jy@T7_lypf)gj^LA`Y~@=yR}fpPoT|Hg~q|8M&|B9FJikW#%dbK*hgh^E}N zqMxmhJL5yDzETvco$9Mb(XUa`l zf4tHs6j%EJL7FLqQ6>Jd+0^InoQJiUgv66EhyPA@yKgF**CAk|6;Gc-fI)nCy2Yxl z%3#Z$c?;oOBv5L7+Bgs5!P>=wzx@{sh)-nnbKTvqLGgp%qgQ${RQcJx{EsO0ELhQY zye*fm)%mZ9)j};XWV~1=UO>|E6U{ z4)pj+UA&L_ZFB7PT~YS*zxKKU%ZQU*${O7Fk7bJ$+-x=3HoE#n2#5AvJr%W!;RKhh ziy$AnlnD5*x1j*vTQ{|35fS*_3c7`HX_+e%m9sT!pEtuHlX6uX=%Sv9$(OxVDU@vL z|F!T2sQDG_YPPnHwUsvv=ITVJz?DWw0(|3P!%Dt?cBXVp{qASa*2OOPdKD!kk8YfdZ zn}^G#(X>oL9ah=;)?Ew&0p%3&MtWY+dmZG1i)@<$`|C3j;0qzWWmdTl3pH}Ui2C!& zcYt`qC6vUNi>5Vr7;V;<5cdZ!n1z+hJN&& zF=wgq{)Um86qE+jrYqKp&HLjE+@HyxXpn|3X3~nJ5e{yEm;0U|#BRE?KA^^lU{*w= zln*tEQ(4R4W&NrP&M$rOr5v)-w!ddHEIN{gW-pGhKSIHKho0AJk}7<5S?;ud@39N= zQAh5VgYAm}_-3^z3$bm|CG*Uj4AtH3T(XiZCHYDOXbJ_-~4d zq6uwPS&JA0eCBITu?A)a%KdSbCHU7zg+}a0#Kb*EN#awL|CX-_E5tM=aP0}gr*nQh z|DJD(FFh(MlOl3Vj(i^{DYq>~eFX9`r+>T#+m{IN*{1coeqlZI^Fzl%Ocq?^^l0AO z?lH(T-W?x7+2|gbW%vMD-G!Dm(}c`BCdoFDdo^jYF%-!gh8q!!)c90L4e(L6o^+v8 z7(m~ClbyKEAbWPHXZN$OnV}5&Y%d3_yOg9EdvRUi45> zxE)B@96x4w+FakQ?N^R>YY<@{Av98lOK z)4wHk;T|@4en8XU-O#{^RxxY5Qy?XvsEb+8s1up}+XIp9e z^ou?A-}uAWxse-3#ZUFYeD55^{>Rr_%kqh0bL8@45yAv*dG+oMk02kf{|E5f3mO2v zj=@c+WR6}4NhCYd&+iA<$$OIOj7NE)n@$jyk7!*Qji=qsO}y8R+qa^Sn@9iNv%3+n zuUVv`kVHCda~Yjh0O}KZ&(}!y+q3#9F~sa;AC8VSxhpdP(yCS|dAP|-em>uOdu5t# zi9Q`Kv1z@XVLy`OK_W{uT~LIbMJSjGcQk@p{&#v7bAhZ0*!9^8@V$0foD}|ga9}=} zIUSk4InppYtBVEgHEPgHz9dqo27SKgs=E>cxMere>{=B!rrlRP_6 zoa+}1)v__(5p;#?wf5%P!Y}!G-C9xNMz!uZ4vcoPN;X)SRqgVjPfhP|*Y2k|>vpCR zpn!aM{!-w#*L4AW%=Vkhl3xOeOMe_=lbevHXMQ&yyt{LFpgNPvqCq*dBJ_|?7@*&f z9(~e#{2+}HvQA1SlDvTZ_3iQ&DrVkc2EdmffxTg6!J!nK#92p6U+AhOUp-qE$qpm0 zn4$mT(-H4$+9e-kL_eU9lS^wlK64;0Pa#D^yqIZYv3n>VcEAAn5O@T^Z@-=c_)rIv zhe>Mpo9QwzY}}|aM&S>w9kG1~B-XG5YH=HniLczps0ENmguN2nK6|00PkFg;l>Ijk zB35%}r)uF$V+-(Io_F@G2^1+qz&&J*5hL>I{Bnf}Ne_!L&X&n}@wFtce%}$F*E=-W z$_$EawwpZ)^ke}jhu@|9rqVuD?tdVuA#eU!d&qe_S6meHH#3(t9{ z-R;lu9ZF4VOFZ%V>(L?NlrA5+TppGK;1R2`c1KT`0$-dF1bNboTTHl1nztRqszDAnf%xg%nemReaZpmiI1=In2HGK=njPz-5q9!+`U7%P- z!z3XmEeoJoo6MH~wfD?*3Z<~wj?6}s^j_JWDzqa<)#UQ8aGP_P=X$j6gwW9wfqcZA z_u#)DZ2^4Z-)iS}M(Qnp?B~a@M+KMox(H?0tEwXA@giUg3(4&AZ%4Av9&C}IuPoI$ z^CfOSiWDT6j>{YU7`yV$6>Zc3_~N}TwM(X6LtBn^IF6?sXEr(p z3^iYjG~56_JauNm3r>l5zv}l=^T%Bdt=KNUs8b2FP_KnczxWob2yNL6X?#^0ySDU; ze<(V`M=*=VvYNU%*@_F~6&bBjf_zYsli+XvodJA8K4Gcfz9B^r$C0~YCoxC=`LXwV z5&H0Ht1PuC>`m@0{%hBEIx@18p@emf&4WezewX_P+C6bN)~)p7X?v#60H4EjdiU@r zhwXCg4)!u{w;r7NgbeipBOpKD#( zO}xSJilYVj=)P=&zkPcR@RcR){}6N~ixA`2&Rdk8`uvrVG9G!cXF2oyT6k4*p{RXb z{SyVMtz<#E>fM*|rN{h%*+6_kKR4Av0IE{{GGGqq%j*4$!!S*R*{onQL?Kp+92sNvx zQqF8r8>q0NLI&NUwQ@fiTb6eU6HP6@7uM`?$fXa$opJ4}eX+GC-@~T-JcdbY>1Zwx zY4wMN0{G09koz2`#L0gy8tOBg2dswJYdaXgrw<8?D`vm=Y>}}2J}7a+PSOoXndN%H+DP!jmK5^lVS?+!?kOH9b>}^HSZx z?!QE0VJcgpNwmEGZl9*B%6>3o@tJlHU?61VtrA)r%F>vUQb;I0Ac)r+MO)$E0{NJ6 z#@E62!2^6szk`;D4<|X~qX=zsb`{7zmP}mbz$pZB4HDgLMtb)W8eS}auP$VQyAESQ z>ngKu9NJwCZs{@f`}y-zC~YJSz=vHtw${lSABd^#`{Q?*6>WGtc??edNdbN7q~A+@ zYUZ|mu<2Q6x979+4*%Xo^xJtK_E#?cgZg$GV3mN+YyGQmZ9%S?Pct(!;k89p1CMb&G<1zNM(PntU~O8;-!HL&ElcK0xAlC} zMJh;BZrW5WpDwCk)WK8>lVyyIMWM587EC@K6Q`3Dd zP9-nY?kr#mKggSHK`*$T`|yMF&d7_qN@gXDXA)2t)T}Iu9qbHuf$IxbDTz?64k%so+ z+ZVij^sP<$66KZ6GxZ*-9NoxOwEP$;7?P2V)!GJV6iwS$j(G_El7-wN)3e=sDC zXIQdUibT*g%-&Dhw zJ#i$!RoeJo?}x*sOT{iV*+_jgc$eBvIM$ndxK4T}q7AJwC5y-&W|RzAe%V`l73?$q+L1yBA%OJln;) zP~!nYM+$>T=cC}MzCn$&&B8!kORb;{x)i_%mA1KI7M$uF%UwDxStv?%6DlKf9e_kR zLve5O;#-#5;YvTofUH-9y=H!IYnR=S`KdleQAOl+puc(wTnUaA$cMYH2mbMO0stQ; zsktpXm&eqtJsc)gBIAhy-xOK&;3W4Zv?#%bLyIF6=VO(1^w)?L>I8f{NE7uhsN>3n zGJzvj$bDH7*NMROc{B=5RPN3TzK@LvvA^6=-jMD}GWjfNoL?V>)4%w#a?Oox%f92% zp)SnTScmO77be)9PKBM6j;|ek_sm~k(*gPL60}6Y&QA#78yytED!%d_iY@LkKZ?Iy zo#b4Hb>{5ukN$XFOf5HpZyMmcU11#hiarFbV{GoIIUbd0i?)>SZcm}wMvN;;43J-N zfO~241sC*gK>JPtZMmH3iHjwAt;o9xf|`G~Yri794xpgSho|&KR!3#9Ahk2ec5$Cf zi;$q3VLXZ&@i2c2@^R&%je+fx1o$-T2|l4X?KV7gwN*x25VZ;23ctx3#m@8mR_xGh zWCC}zQ8%h{%=$Ay9J)T2UnrSku+IA8RNeaNIzWp1)dniSM@-ii^pSUs{In2}U+NJ- z<16nTXBJ}(ozW$|)=PfjoVlk%o!n2zbY8tLD=TsJoRB|>zCFHkHk6A*DcZU_^}~x z6`~F?*Rl9_Ch^v@%Sg(1wfoGj58yNROK;`>ZDzSnQ`J+pvlH%{ZL&6+!36)I1|=l#06f5$PuAS!}Wh7}M;FvMtb@ z$I47y!4u}=he{Wm4+|~z?Z{z!@?}7H-7_}oUj_yEvXGS+w_}O??I{5G3b!I;m!enO#bd_c&hKGAr~2yL z#w&3JkJ3JQUrQCoq((cQyIQ@QHgBzj8PF&P{yrQuXEXLb-MZl)-46Y!S4lQ((zB&I z#Qzj+T1WVjAJwoUdL2b`7|tK5+UlScu80o2+_@)B#iXHZMqvaezZy8FeqFlB(LT_5Vq;Q0OkW}f%+g_y95 zTONc1Y9L-f3;QU1ltP^M=Cp|eUn$WXcznUZ!x`OSM0w!F?D8-R zEMp9wf~}@5cA{EnA41=Y?+bz8X{Y(;2qayhs-)be6Myj)^Ts&LFu!-sPus$^CqIKg zKJEs@eXxDr0N((jOoA1f_Yn*_uivC_qFw@Sm!YP|pWm=p--z_zvHdoMV0*_l6B2su zMrac5Y_i-j<3L+lwbc~5ic|h1p99P#rrqBk20qx!b;tKv;uQ*k`F4>LfgA0!OGs$&jd1? z)d@41jmE6{fco@W>=@q8N%t9qF@A?hk}v6Csbt3C9~Pv)UG(N9zuy{DzP0Z*u3i%w z*+oHYZ^;T9U>I!5UMFe~OC6M}?(Ii_e9#}N!9Sih0Fd98zYU09j<-3)7dUPf42w;T z32sKAGCJHQ(;hPfxFPmDwx3-7)|d^gGw5oVwe&2AMrz-5n?tjsIUSd-P2> zk(IX%1-RE*)n$K?+R8igBZ)Dk(_3NhL|%L=LnbO((`P)fonN&H*hu`kJJqM}gSQiMsax#^nMCmlS0I#GkNeU#!AON%VgG$|GBDd&RBkvBt-9B|j(?5%v%Z^6@FD zE`eR2kpLfgiVu=_o@@0lt{m!dapb6miJUY--gbflHqLfd!GMa}j}1H!tPmDHXPeJB ztXf7t4?ovbsJ3z>qZLqDiq!z$A12UHPd;6|;uBqN(5M{2&wX%*vP&`>TBQR(f@qV#ZO3J`;q|ptqM%8dbpyR-2LPmCVINA?k?D} zX)fQ1j>q!66-TvEmP4%g?XZN;gQi7a!g|3DTG92Z)RuQPGvYwk)uG@x^)L>397qPWceo2J24s@cs>_eek#Uy@$kw zR9kOSbOPTbgYpxkz5)OC@HBw0ga=6v$>c&f|5^|wmGJ&S);r;$p;eq`KXx)GekdJ;l3jF@o9DuL%zRU4e?kT4e zTfC0{{CWD-p$t(}MqO(zM#ayvG@61j!#EKeBlE&x{k`QlUx{!hW_d33z$Vd}dR@}O zghV2MFXg=4^H{!Ylyo$0WSvo*n4nmyc07EAIL3+k-|=<(R5~%YIzk@;1pjNpkX2ay z>_4{djU0tEen81RsP&-zItSz(&!>9lS>sOEb-=4`{M>!B#S5$IYXofhLoORYUug6?zOlJmJJpewwXu3CnmpR(Q z?X$af5Kyy{HG1UE&7Hns=OX{sm-rxX>WcC00lpI^q)&F&i1D8WO3l>LzjSnO+whAeUkT3YrZwB9VODOC^wIOH z6RMpgrJ=*AKChC{E&KEfye_s<@72g#!~ymv-@H54sz<*=*nJ!76i3z&C7<<#aP5oA zeEtlF`%<6iC)*~r<2SQEC(&~KKMC+VRvE(%ntk)v(@0+YMe*kwPcg^`i}Drx{;Xnv z&jM=J=|Q%^IgVdTyos@Vj~}WL-Ee*^NThL$&N8#F3X1V2o$X!AE%Y$O=N^SY-s$73 z@dj6&lP=gs_Gv`%TtI%m;RDQ8Clm>vQbnGZ^C%@so;Ug$xTJlHK!08S5xOIb`Ln>_9|9nn4;J-hV1ATI2O`|#p3>WhkJ3Z(W z*o_d~7%PPfvKU_OX8Ld+nVts71s&ryDLE99CB9;y6n+irz&5PM%P-RW@z?0Id>Y^r zUVo2eAO1}lWg%Wdb8Ey^8 z$MTsF{O9XtfUk+*QGNNnMx<#8GIIT)h*FQk1V-e(z*8Mo{R$Rm(5aH3oIaNg+2r^a zw=XaT0|?XaPSMA#3gZ7f*|CO-1p&wVA@T!AJ>RmTar1B(5m`VXWRL!7i1f}&MH?GH zdGYZ(_~`jZja_cgNN=(%#C`lN9^uKREYovpPZW^)*1mSN7UZK6{T2&$e(eBXC*7oX zocj9axbYOPl$VLDRL?mg*9C$W+Oj|PowH8;*>%{4|6oIvXlelLXP-V_+b#6e=cY&G zD&O2OENi+dKz?sI#&ff$Wg{bloN{iws4&eY$t&&?wr(wjtTU8h@ z)99?y>`tYlxD=HSPv-)=Kvqm_mt6<)aiCL5g6-=9`u^(8ef~Sc`7rUItYS-hRlE6G zs`N}-Bpiyp_I!B%>pzTfBbP?C`znUc zE+uYRo!)4fxhS>wT?Ff>MHZLJXl|&;A1ZzOQjqKk@O8qBg=*^NDRlQ;=>M_IRZ*!u zaT=y6#w3Nq`1Ru3QBRDeN`m0xxMT8i6HWe%Lb>oK!|#JQYMHvXzH-5oV-v{7`IHF$ z`ouCIKc4QP9eTa&ihX?8tu1%d=RUKKfuoKH^4{#x*Su$vE3(bS|69I#mqZeOR(Y8xd``4P|^pdEJ@*i=K zOsJMahEOCnbr+M87;4fZ-5?*slXWN9zB7Pt!*6Twdr&Au$!GYwKABB>vN0b6!Y#t# zw_@Urur!5L1EQFwbkrW>Gwj^okMuZk$i7EM-IqmXB(#&KeEOLSyq(z&Tbq)BhHSww zBtHqIZ;_Y`StEVhq9=%l#b52kw^U$LMf_Fnue;yf)k0Ii$iSGsrin_AYh z^(uWJA5$yE1K7TMfUnyK6JkGfQfGB#9=-?8Z$t4sHjrMfXQCuldpW_hTh?mUdkUo( zW6ZH>8#RcJ>#aNaJ+eQ&#^g3MD!sNdA@F!_GNmD06KG_wp)*%1qu-fja+5b z-3m*LVI&>^mg%0CV?0<%Zj9K3;UEoqfN5uYHpKnar#PwBc z@hnLBx961{ej3-d3H;NKkDz<12B;*8~P$ z(PMe!!60n^R5(8~nFRUhf}X%XULOVEduSheRc{-zdPx2?RP_xKdBlKG0(QngTrXNW zH2L4~#IZ)%uk(U7^UY-(2GsA*4mrfn+rqRw2^rsZdge>G0oPv)BY*Oxm%Exoe4Niw zfGUT{GUDL+%_z?4@ofCB|C(~O=EgK@PeDmTH{-&?m+WJHd?=|%lA8AYO6GBCJ~!74 z$VbJ6NDg*=q5*v6glds)_szy)+KBDX0S)x0rOgAr(J)^^?O27OKDpN*Ll;pb$Tyll zKjz}cewM6YW~V>r7A?h{DsS!;p{ard)Mu^?E+;+}W6Y6OPjK}gS&4np^y$;R*+B1R z#)6mp3`)o1Zn|1w=pvoW{4TE5VW?M9C&E!-(-~UeXpWK%w-!M@W+moiuzh#{UtzK7 zDS@QQpI_GoueykT?DBpeGO3A;Qzb;T%es->B|7~crD(2^k!>cWqSmg#G~arD;Ds-r z`FW(Kb%t#19Qgb2_gl#XEE2!!uyRebFZz|tpWQGK#@tKa_L^CZu%vT$L5pE%R!ZK|X?vx8Tno(E@z%>WWYTzdm`e>!pOQC0Y&4 z%TBJH?WQvK&g|xDRw}2Och_%oZ&I9g#@mK%`^JhzEklapY4IXDB@C51rf+-%mF_CY;9qX{KCS z2D(R{EIVk3a~<5AMDQ<13m|`jV21mbMRUpuUOy;p z(=~OSq4(Z*DBa^|@eA9?>ynu(xlP1@6*`@(at5vqz5SSE=x{{Y$g}UKI96s2o};3? zrM=%k1M1Utc>;s)V6w^DYIZn{Q>72*WSuIn=l@Z5S5Z}M@87^_5Tv`iyBkDWO1itd zLApyo5b18|?nXL9x+D~k?rz_M`*-zUW4vSRGlqBP!jIo)?zPs8XO7hvrQgB6l*#4 z4KHbck1EzaXf^)lPWzu|T(-A(K1fIky=#%hlHx7qIWN9DUF>VIyBa+;s{zj`=pS^R zs$sb+6r1hs_=m+x;)xgN`yd}b0d@}9J~@EzC%&ibO`AQ3reZN~M8ikT?vN(cAwA|@ z9@+%oseWZmp?7xM5yFS`G*LxDgoYc}@+=>&ABw|}r1yg9d03{R0lpuNS@i?r*-qY~ zpMSRxylMS|fDrEMQ674ky;FH^2c`(SrXkk?jOMQ2cLk1rS3*WuC!Y#K7vM0s}K9b zRX81Mq}BfG|MtJsX=vxhZdz5|ytZC(d@E5@L8^&nW~F1y zgAF&|01fWPwhVHQu=9AiL!f|i>ne47pSI)#Nl+H_|8B*szE%hGI+Ucuq~>)*pZ zxs_;y?{sZPsfr4%rs1`&A@`TME<|ICx-=Mno&ciq8033J>`z^?a6IJ~cY@a#6moho~S7yD+g%R;upEzNt0(M^YM&0vTR*agM@o+9ze9Bek z6AfW_e~_!A*2jn{xX^RlFEY!I^DaR?b;d=>!2KbaR5{KJ2_k=$UK2iUk&L|eST2qU zdqv;T%|-e5#n&RcX_Z(Uy3-%zI~?5G*q42)IleEB%aZ5Lg_do(GK2F7@-a6>f#1H> z5#T$u^Q~)QyBIX>nZwpC;LfQCDKu6sKfN~>f+uX)*y*}0?l>{J$9v%U72Mu7y;_t# zORh1pq}4ZVx|cyMqXOJNFO)0>J+syRN$jX90`B7z2_tM=`DbtAvnTt*fBRpG)@?|F ze$znWg}dnUkeTz^MaO8@nP9cP(q49L+)sIv^%vwL4ORgEdQoS9uei{q36VQpZ48@I zg}+c#F!3Fi;_>kb@pF`DyC6N|dy+7ok)E?TmV=IL(M1Kz!BvFQfkj3WDmuo1<{O-Nn|a=U3|S zC0?5{_&}y&Zx37S;!gy%^6&f+Q)W*+*!AfO@WG)tT(HjGr5ZE9$iUhR^f{5@m9DMr zUG$8jH+^B_H-dfu#bhE%3nx{f~re^>zfZUb{M~8_dl13-TQgjiXyx#5TE)BF9y%9c@>Dv3VsR4?q)>tPJe&N^2a4HuYTA7)&un=F-HGTn(*GAPT( zWB&=y9F3D*PN+*`0{mh?e(E#Vha^7^WmgZsF&laK%4lQz#uvnAk!#G0RKEC9lh@K$ zGlD1-bXKtvR#bDkzpQno3?Ag;oHn`zyFR@DzEOlJL!`3WeunXq zsazu4&tGbMAMQME1Sp-bpY)Mj1hIL1ehzr{icjL6d{~Fh`kUn5+*z7Eoger(?L2iB z06hOtChHkS{2(Z_L4@y(IsSADjme~Z$@1z$PJ(szi*H=7=8lcS!Kt0|?u`ko5Y_E? z*s#w)m(Tq^Cja;-twR`qqj#ELHL&8R9Ot?*Mrpz!#AC2OO=J>`loH1n%foe4C$1>_ScC6ef(^z#}uf6 zI2bL{u6ohnAzq!~5o5|ialwjZfj15Wf28K3u1&=OSr#MD$VwZ?4E8(rT7;XPzfPCaa@4#F23aug5%Fz_P_S?BNaiI#bLw; z*Tt9VPoh|aGA!xdMqcT9N$xSw81oi#syHAY(YXrv?aSi;K2!-PojF6&j(7MT7_i!_ z!FTJ~qc(!d4)}x)id`oDt-Wx%uAM?P>WrP^@fT=3q|iJIEEm1w+}O!TdRDXw!1E7Y z5z&vg5c zT?Sv_0@KGl?v+&qQ>B;sR2j#Yf_+UDML5Rzhw#z>>W@+Px;O!u?9;{7{GqkY95gA& z2k9J#1GcXW;OoUu(KME-R*nZsQA)5YkZ1dkm3Xl)$&(A8beU$(o8Uc3H zU<)VT@A~YkuO-_C5h|Wx)%2$Pfs(Zl?=jP?4yS*Gj(2j0|Mu;+wiznOPHeF4c$^im zPU&S!!myzD4ajdp=Aw)P0-=A9E{@xeOoc-kzjU4fAjziRF!KW&f4&EM;08&U{&ie|@J5`+Fi$J3@Tv?2TmK49()rYP?5WNEKd|vQuk~aLZ}=+!_M#SqD*l zUH&N4#}~kecFlZzV866pptj5w@)RrWm5 zafM*Ly4EB2`?~|@(IAAYh*;msONkq^_jIuqq2d;V4)AgO$(+Gsea+0Z3sZ(^8J+fN z>Q^Qrh4krTp2@%Yv!fw9emXZt#G?F+Chq>9{ZwR*BbL`@j7=*oL!-ALwC(I59}VW7 z1lYb-fbU}oZN+a^s|8|&OJropH}Y2n9&eYA-a1Q+FC9b=GH?q`ZY?5@(|IZQHqWrL zla9Tfpn`a#K0L$~X*xR=mIR!?)}}TM$(p%MvlW5yeygl_GKjRMMa9Q38CrkJ|5BgS zmUus$I^T{&Q5cGknn3yZmzuiv`g2|Nd|%pjBBDgs;syEmq<#Cr_VodLCuVLx^O`f8 z&4NRAtMRT$&8CAFjq_(eRJz?V^_I#8hbS#zz7BL5AcuobqrCr+7aKa`k7pCLxjOHh z`b{ME8j#<7N=xBFn!lxpkqEIGUwy^aT1Z>kBPWB7qSe3m&p;un(~2YMuVoXtu#3^i zdtH+$1>bNlbl%cq9h9wJ{YB#g`Bb=Uz@I-81H7MEZ+)DH%viSxQsnW3w6!LX|Dx&j z?pkHYF>Y&qo4)eruJ1j)x`Or3XoTz9j#K||2@z(Z2I~HR=wIKH^`$-m_qURh>9}_e zC)v_&}DSH$h?n}v_wSn+WF70wVbYQw+2K(@*Z&S=zl z7wNS-!UR9aClJ4Y4R(H$fc&JyG&#=R3gbmuebmGEG*8m@_KEavqy>1cSWNT`Izd0T@Tn_E#l+*odiKX^K4!4 zzyC4;-+#>>!`g`*o-z3gs*ovodUK1AJpQH#o1=c?SR7=Z9|u4g|q}7u%2#CV8{# z;K{=9B3PX-${o*;)|?L)Qz+bNuSyb>Ig=2&r=$GckFe#oC-M+ zJhIjfO+^^w!-2^719pDPfc(m-qL6cMApg|infVPcQrD+j-umQyLxZ`~fbsQr*r}O< zETSWuJz8`Oi^w zvqjI2)OuSf&I_+1Dej$Bq-$iqWXMX#t74>1uY!|@aY7_ccu~q%(3V+^Ff z??+z7G>J^`Saf}>hV|oAQ18jz&wA#v{!^q3BFa!Ty#|d|s+#$SNq|oXNpWL?H#4q@ zlfS~HEgw=4I;X&^6%D;6Q*-#mCoG8H=C(W{Ks}f+Z6b8Hr_A?2$;@vp81%jNw1?u| zw`*CD4-yw=2<-Yi0Qg))?A(d0S~ijSq!b`yL@_<>XGF?7^ z)<7iaBu&U)uv)m>v-g$~97YjtZ^C!}uWuB<=cB$~p5o~L)ROj9VWOH~KggVjl2lkm zk=F0>-}@P&L1T{q5@P*4%3P%E`ZBURzX)VK6PFyi0Zq5EBbkJrJjloO(UJ;m-!Z^f z3cI=2r~^TUBQva1*x>+4-oQU%SU0m0iuhR`DS(u6O@5Pv&~swqh&oy!U`@0}7L`(e zV1jC3H?Ipxrh^;U|I{>*v*QlAMarI=02D^0i%?4G}E18y_wkl#1? zLn%8ql8o$d_vdJyOdaX2fXF*sJr@dbB!MtN3W`ZE~sD9YeTk*sNg z3$NBtiVS$~iW1J=tkqOS)kT&1mt+?g9k{f9ZQihwZFWls_}*u&NWiGlE<Fk+@<2c^s3!0}gpT23~~XYW1T$NoUIu37R}1|_kC<1s0nlYa5y zGd@f-^%N9O4wQ_$@wnllp*C0ca93RnM)l8GdTrFxQO4euo&-a`n2LAI87SMk_@KD3-QzH}qj8OIOH+JNzgaNyibFT(1Y>|XV8yKCYe z@~7l^dq!DW!WbLHi!W`be8#G%eh(2xP1wyLC3^N3JoXru3oIu&U9|PoeX*Gt$cLwd zs0g+X4&bxPfyup8#ZjC3^h`PF?tfNfiZnhwoVlp962`Z*75v?pIdWq_x}ovvjrkx2 z3q3Mp7=^c7_CagV#Pk{Jop=DicY&CZJbyxCtslGGh{tAvzGM>IUt`((kt`(T-}{S+ zQc#o_%Za$0YO4gS-ZS@X<$21j`kLH>^6N~Q`j#?78;}ob*vJiRA3DIdx<90hSoK9- zuhL9XY=`u;eN@hXaC>oanGkVxSZn@m^b;0CzlM{s< z44$3*ZF|w4Ypq8+jlgLYczl@j5wC@Ox$1LIImxnXL zREqTYG|anxJ)U8Xl9~7_vN?c!sf8sNVEcLi@1Ng2X`E+uo8SCQ-qIWAXf=^1C0u!h zbi=nuO3h-4(^;XgBf>HyOwU;{ZuOfAPr+3G=%PQA+7ZpA1QNv!%^x^Fu`PKnzxvoO z!uK5cK^oP5N7wIG>i^X~|C<(j?)xZACkGX}#N8_xv0rG21Fgq!&MX&Y3)-3Qi7f}5rjEz(U z8BO~-`uyMj>kUy0fibn;yn|I%jJ|(Ew`&p7xvy=dF-cV|#fawLBVi_CZl6tg=Wd`|>o4S|2_E5rwl=aYYkGr0nnEEh*cuPdJu z+2c-*{;+8C7s$TuaN_X*`KXlsD^JM({y|>;{D1#@c_jRAe_cOd{EcFTzmC+>ak=Oc zenzfE3P4s_ueern&P(BmvI7q77bK)Y5(whD-g@?q8D{tu}gzx0eNd z-XI^Ds&XaRJ~BXkD&KMyi%#&fmKnAcab!;V4fB0CfRVLzWIn<3hBz?%_+Cz$YvHx* zzQK1Q}( z<5pzI{x#H7LO#ItP2(UF{8#>hJC9nJUlaLUNVIz!iK-S_VJT+a{*Ax6z4?y1-yQ)b zB-KZmK_9}|MQrH_F!J4;ZR7NP{8|c78%y)A#7<#+mehJs#gd};>0;o?D zn#Z4kZeM>&-)X`eEWOD$?}SjgY{ZH9+|pS8k{>-Rkzp%5mC!zFYSS}zja2&Yzr>F- zE?()zJhLIRc`;oGWhd@oB&^XFY34Nk#(gEGCuC@w%Kr&ZQZ_PWe-T1bl(px znaWzPO_gl5`$CbneW?vkgVbGJPBea=xe>9LI+9(?8TG^gd@IONjl!;Eon|;ws<)J~ zVOo4d9_-kZ_GQR=|N29d{)Cl9u|j9oQ~j3W$U?vW#=lfDzx3B=C$eUDKE1!o{O+x!1iO&stBx8K5C6%O>)dtU`>^D%vnD~pH=?uaJkzxk z?a|%KqainM;QCmrSDT@7?cBQ3roe+U>x}~extCgwY!*p(rOCjHuht-dm?{AgZa-Bh zs04{2D1dcJCAX(L5a#oJ-m@d^q5Vfte$e_Bl3@D;06sbt%;rxIgW}-=(*eB;idi3g zzn&T-eKgaJdz*-fuYhU*TN-)bbCRNl(d_LfCCP;6%f4WL^(QFG{79wS@@5#2-@Q~Sm(_3*B#r)VxH!t?poDn z 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 z zfwdicCzEq}N$&&Gcn^>-8ijYmuW{;;iQ$7o=B^rnaxsLrK*ZaxU^`F}Pre$eA2Oy6 zcdna*^PD)<+*)$03TEojWNhRDj*-UM(651U;G!Ee4LJy znqqdPJ3G1H4KIEXn1nO%-9^^@uN~eS$@FcVFR=|@DQ@!rnit4P&m<&rkyh)`98s$W z@)2}>Wj8PGRkOar(pI?JxT=C|o|!@Fqro8|d0v_&i)zWOb~NY}EH6E4O-}wu*nwxN zh#*Jz8msRLW}?G+o)F-}m)~Oo*+&iJOUE68-|!tJy8|Ci$qrw3(Vp4s5SJ(#l=gnF zN8_;4`IWEL^OeoGOVf3r)A^E+6Et*+^f>8Rv=ZLiTr*Nh;GI=AwWUI~vum+ad(b8n zZ}xt5eQao;yVMuTqVafGZ>AQ&>liv4M`7E>}>Ms;|(=<5Q-*HP|-itu+NvxLh0JS-6s<1r>b(-EGMbKi}nigWyyW7p;sv5wAO z%m2#I&Widd;s@m8kKZtD+3EBnDX~~?vJvXSqWth}NT9Sjc7~7q$%n|4%tcNns$CJV z^Zm|gF#jFYul!4Q3(=S>k?Lqv)vGBofRA;KHxgtYFOaWgJXV`F#F+j4SmTl~0vpPH zK2zV$Fo)wVf=vMr!w!+IY&=E0xRJM#U0Bz8`RIm;-K9>xt3t0_JbA4*R6NSRzJG?F zIq_MEe1YyW_ARN_lbO_%6x--h+doT_G+P&IKV@F6IHO>^(8F<-F}eX)`j_|5RK1qXWnn*3>02N7V-*$V;ZnvbLv$5@(L2!ITP- zl6KesoK^`5VBKH|w&$8kOrqWUI8 z#M3{4Ki*RMLy9V`iM;arj}lh2Zz_mis51e4xQ;(SFI?~v$d_e_9vp~P@8qAyPRreR z>c6#fpM}qY*?dH_nO@t~S!pkw(0KOMhOCWq&`8&Ke0P;1iSn1W9#gM3GX3&)jZ9@9_{iIFtZKr@C zo)aie)0JYyC;{)u&i@9rs04rKU?dx+BQqw|fH*B>@mq)8K1CA9XWb@i#0@^hCx(~6 z*?lBl?vMOsj`&XBclwq?{K?m7Qn=`h=Y~5PS>L*MINmG@9zRnEtIgD<=h=hz^((|6 zC%{K%ZUp+Nh9*Ehl0%+1cbQs*avOKiOKsA59U})fS!h5w(OtZpR}> zbbMY}_vw@NV8XU^6Gx-y97P|4Y7pgR#)fCu>oSGYc?~M7955b$k3~^&8|3@X49JH_ z=xd0IcZ;M%T#??Fd;ZPawYZ8;j0i0A1l!@qTxggZr-5DeK@B;a0iz%kNf~Q_ES{=j zyxhb4quc(A3HMtdAFc`XM{}r2YFpH^J*f4lPxh^tIm#=O&}j&xub%RYw)2jfc9^lO z7F!5ykTM^?mF97htS9NEA>@x@QHC<4I55>1NntOS14_O2`OI+SK}UkC$RttyBxZ<7+t*r8zW5-poPa~2`D|P0!TO&yiXplKu848g z+T^?`y9rC#367!wA4LdpFvz~QKt5>N?rWowP&5Z2d>etnq?#Y9O?{e^GO_YK1Q3E@ zhVC^dP48;;gL?V#dS1Z4R1)6m|J1Di27OB8YOdZcL#XIq-#?G{nP7<)-pKLtLFuSA z2&cInws#icD_JNEa9^)gpL~-6vEvspMiP8j!PFL4WYoGcc2gd+y7AcJwpQJbnU|4& zeQ;cHVE=dD-`ORgZx6V>e1d2SnjKz*-o;+Vp9s0|{crTF2eh}|(`Kt5tbB+W9@)L1 z@*S7^ZQ^WVs83(d*Q;Q~fAE_Q@0VKZVbk2dyctNq#zsZL)R*&kdVDJjVg1|*kj3Aa zmFGOfi_Q}>IHsO>64IzL&FRfKP}c_$2IZstC=)w{C)8CQ8jD%)PkLog*rWjQkuFwJ zLOiYIdiwkS{qrS>8g6ZR*xoRQTN*kd8T#OXfqPnH!@Gb6v z1y0s*Yx@v>3ypa5MPDZ?$aA5%ZpSV zaV}V<$r3?(I|-T`)1tb4tEc}X;23*tUlKo-WQBo`F()28pN}*vzdGO-+EM1pHk<8O zx#zA!keXJSdC`KsZF1Yg{gh^zVs&sBZmu9gsQv0|=u!L!R_f>d4L&p<(Lx%nYB7_g zrXeX0<;^i{hF37{9KTiCEBP@gUcIN%+&_Y8jn!MG#-S3TQxE!^V#qvK$Y(j%ET zVd9$~(pBAmPFr7U5~k{>6LBXG87n)dy*LjY$(~ITZ@zX=&+9@pxp{oPqF1smwN=+8 zNnHiC`)_<5*}Vg+5pVR8FjBHv;rteE_opk$%dtxT`FVk}2C_n4L>fk|zwODe`ojz` zq>$@?F$R;bf;W3HpdIPkC`krPnQJzR$DxO2rb}HiJf|?ad)${XunrG!;#6ec#=VZyEuj8)L1F!|R}F!R`U#VGfl%w2 z{ENHY?my3wOAAfnzc$<`^gxip5Sgfr&6Wk2MMdVw*dnlSb9?u^e_PfJ* zzFYLn8KDg@)4MnJMl9Z+TLI47UiF)c@}9KR@s3KHyo>qoDsqn&yOJFI*Fh zRf^v;-Zp_xiY^~H^;{QL&}QXxZ3qH_u5qx)dn6t+q{N)8)~)UqzTbGqBER5z*kl0r zH{IuH(Cc#90^Q#viE9%Mg!szxk2mA-q^)i5QAkw}G&^8kmRQKC@~QsxwlEK`U(}g{ zToYATtZnAkW^#6*;16VT>#`w#{UIB;?rnb3v9)O~Y{^V%u-eac2&9q$)h_JbSS)Yq znCFG-v3b2ZJaqEhfm^gZxhZ||VsV8;L-;H*#1=Tmt7CR<&yT{O8pjHaUZ|esQ6*igCV4BS+!-Y61Y%WY< zJ6}HdYvGWQ0Uv6uK)w9XgBRtBo=^&z;$h8`aqGiz6p1Lor+L-*CtfhJz*C=eFFK}j z+nUV@wTtPTcwescC~ZBhaw<@;};bLpS1M$7#ehgQQ>o%Dbm5ybeJw9vkWSrRF z7pQ%{Z@niTrk4`z7O*JlXJ1n<*|KvaVKU>~&PtMf^3l$_No+WSBQClM5FVAb-_i)` zXB&Ndz0vk&rPJbFt@(p0z{hve!wRy`6Ua9?o+N->pGF^wK)DbQ$9efyQQ_m*#0#&j zPxRYeLCT_;!(HEg(0XnVVZSHWO6hP6CFATwr}DRuT4EZKZ%Yja@==X^XnWjN2nv9j zR-$E|^YZX^?$YNX-~UygOwn-Bl^==sSr}0In2QIclSHE z5_N!&N16=ujiJ6kK4lB+qtALPy3q_@)>O7#V|MrE_M9lg-atI^>PFF>kmlMuYRI`o z_`@vL(bWycg4KNC4&|%;N^o!vuc|GN^}pGVf2Ien3RR95^R=2Pl6zxNuP_F->8BeU zLRUps16iKyjy<%wVtGPr;X9geH;k`~W3wxhs6=M{%1c~Yc~qdU>{8PL_}EB#LEo4i z2;}oT8paVtfK@x>+9Um)ZmPtxl9gCp9l=rCTc(2+;1_AQpKQic_6hZ2^MUF_JY|i zjyV4H{WHAXdQpcryDB#l$$(f1`}TJ+HaG;KmemcyG0aEpr}hcA?qV9VX0|N(Eo$R1 znoW$N)caDChp?dW%lO^Jw1LmcUtj5{7U;uU`2WscEl`o=f)Rbgj9b=lp!n?a=YR}X zg33F>psGpowi6qL9Iq?tvAtbszV|aBvSaD~e6vQrqxJ7qlkH@iDiGK2bb)w!G#rrO zkVbf$DyELVq_pd0vx77R{ofv5<&T;_@y6p9henx=*+*EQS>^PWUy{)A!r#f2)oVOV zM5xCPDB9@);?v&XhW)>HFMmhxT>s@IpIAeS!tu#-EwAHq5+j`OCk?zARpZB7-BEP# zc-(63Jwc^hvoKW$%NvOgEFi_F<;DE2Kw!5S+@Ra)@H*J$U*11=-&9KpTUn~rx)p0O zNvt%(kHOJbhPHfMemgRXFP?adjTcv_KGQSiHV{0DUoj8Mgy&7Zxci!KpLj=&>*YB@)g<^ci>i~E3z3aH};MbH77!Qse1m;1rhn~`-az;ER zWDVnaOV(`Tj{_o)d)v-ONe0}mgqC;M`zhh9zzg@>4H8J(EE8U;QhhB5IB0Kt306nJ zgV821laT!O$wv_LK}LDzVB2-^%W*^qpV+~-l@AM((T$1FY_--yd*f1u03WL(e>=#& zNFW~rE9SV>3%!6pr}vUmeyC=_w5`$(WGJES-qMO!2J2f zt%pz`V{ES?lY}MRIFuE5TRjzj90tM=55lm^r!Cgn$H%+w&oiIifb5F_^0BvT)c@vaGqPGq zt}+;L^KRj$mblUVaHkZv+H=xXTvDowa~SWer>WgsW~j*&(m!Ibh`73gIcINMawE^!hm zj0Yon(EHOUs|+(kq1E7YWM>^T`k&}#03Y7)jXKD0mx(~Wiq=+YKh>B4|FaZKzZ7W` zIiBGc9@lYtL4}BTjgW4xoQ*ORKa3k53t(yZFJhp@Z$k8g?55e0GVs<8Uh`dkfA&4O zAQT=@xP8~9*_w$}-{MH3f0{!3iZE+_P$p?Z67uHs`McEL_aMtz4=YON65IP}t7046 zPdz*Y3S@gaNJV(pm56#yc#{yM5NlAk@dY6e`WKQM+o)S=4ZQg>JZWgP6pU)ZC?%Ch z&o2q>gC}yCHEct^^a_PlhT)<@`(RsL6Z1UIP0TDs{kqS)0G?k<$iVK6*$+rKDr%X{ zjB#C>>$a2rRHUrXBGHa0C8v7}9V-Aqiss+9HP0`L(T(cqPp%;!<0Imi!M?a0GWPu= zm1)5P;C&VxOkR=v>8%ytxdcm>r85nTn&V}pT}{)Rl!Mz)eNSlUzj6Q59mNq38|KhA zq$EIRk<6S%Y7>53M@@OT>Bsnb|GA0~_a&mV(u~1PaTU&S#>dD^ir!ewDX@z z5^Agtx0ZmoJwu2=_!RQDJIclSZ+A<#i%5S||5C&gPL?_KRh|a9(2UCk5B{<_E0u9V zk#dPJ9zId0?Wax^i75rh04x0WOkHNe-DR6rZ#4>y*B*v|e2jK~%Cg#P1}k^gFY@4` z@uAV=2{=Dgm@&_wH~jfUfoVF_VU=i}7(1e-4}VSE%?d5d&F(gjK`)xq|AaWp7;^B} z$9Zl~2J-Ei3e=ogCfDTg>9>M{FeDBuN5MaCWA2Z=%hp#G5t;Wm9;;0NPdqlglnZEl zCs8_FiB)#%o88NWu5h$DKr_)9`C%IPQyn(H3i;}5Ck1e-J)8nwCYZy!=})w=YeI%B z;A2ld(sOwl=m0_LcI#9&o&fg5oDK3&6oCs=J_c)L5&u2*H7h`V&BH%I7!3T)j}zs; z`Kd-2Ij-BiBMAN#+9kFfB+AmvA%auNBqBX=P>>;wk|EITL$(09Wr3*>@8Y~VZM)H( zhcs<47`NowsA->E|Gy(@|7oAmU(ePp=MiJvkE{hbQkda+UDZjecT>x(Z~eTUd^1$h zFYd!#^l~;geq*uKmSfP*Qsg1^A-Gw4A|H8gSb)6)_;_)CO@o|YCQyE;WHXO1Pp1=Z z3pJybRN!E*1MBw`UI!H!f9t`~Z@57xF7SU*#JMfxstUe@2PEHSC5*y?&H|yfcD5 z!yYN2(`OLSWRT-kNMW+mVNhSu^>F`IP*@R8? zO4i2tqY<41cTf-6srgj`x*-ccMV=c5A4CP6;#y74B!-8Qjrq=U1JA`~uV0#21Rh4i zzBJsakj>jwA2Hb>YvNsFrf;w^Wdmn$BV4QoXJv-6cPL?XA`Yp?g}!9 zEy*(KeHNr=`wYLiBO|IQohFb2`E2m`=aY0SOod8*mPk{a5}!w>X6=F}-{2Iyd>-xm zIhQG|r$diow1Po))M9bzI4r22aPj+Hvz*_B2CLHOKuN+rIo&}9Avt^ zSa^()G3w@SE=$g;ZjLi~->3ZAWcf#44)}*xD`2Dbb5P}IW%)B{dFrBN{yBAyKt8-l z-FX3Z&WaUJVk^ynkES^nnPJYF{NndZtoKjtvm2+{$lC2C7(yV8+7Rk##Bt>w2IYUonuQmMQT3NTuJoiqc zRjjqsm(^KkcDk)#w7!%O>{VNjk-k0s$XPSlP(ulBC3`lIZ&Z?V-ZKyZVP3w&)!pt? zyy$FLCrYk5D(+2N`;%|~F@v@=lax}xAy`qwGZ{s=1oxf7XMvLr)ESX1k>rIlRH&-L$RF zGFW_s6~7Y5hn7cY?KtzDgE#1QQ3+e_;}lb|xcWoUoZs-e@RJV)2KOtYWc1iFSRS=y zl^b!;+MRw-B(nL%MMHt1z4Ccr5Wq*%`3dxm7#%=9a2E;14J9*P#84!%-beKbu09lB z@(FZeUQ}1w*xdcbspTl-Brn&)p-Xq6&=?o@H^+mf?@s&Gq;lp_?AgEF1NmAnLsin# z$6N6T$%Z!U6tNKx*n90emi2XMuI8V7S@SJ-ZePBI*}n!8!1c{StFS^?Y0rTP=qV~G zp4fb>oD2i_uwo4HLC)_Rknil4jyT%Ko%+_g_eh~#z1|=8^JHw7yCQbdyK3k#R8A-A zMiH)BMx^C|InSX_hs=S=hQIROirtfBj}0E@pZ)KM=zoT1O6M&sh7`*Rh)8zdFir&F zdSB5!hE0bg#rDX5c=F*$<11#J-Fanav<&*Odq3#oFnxH~BK@6rr#WS@ps2AM1@Msz z_NRjE8v^pBzP~&yRUD6lmk5VK3&R96Ro0{@gYm3|p=@fUl8&S4R|#svlVLKuz9-wB z*Lz=Uq!)cO*mwY~30C@jlZOR(sY9AehaBqt^*{hG?yO(o_Yd|be1Re1SDNo3^=+Pf zE>r$cZ24&+(?=0}VVrh;c>~D3ue8Su?^4JlBl#HMwBrCi0^*+oAo~`8e5RE581RS? zaN#k#g>Rf+t}!8;ne_@dqh}!Ip03bL6P2P?Eub;>sK#FxDtZ^nNC!tG=&f~nP);6K zM&NH#A_BEf^vp4yCL>hLMz_*3KVHccRhX`d#PTu}H;?JjC*Nc!RBMg{bb!-cg<>~G zI5klX9drFoa?~M_&I?i+cw?=2fUhs;&qCCv*X*ai|KC4PL$bfm_iCWmzp@oN4Z$3{ z<#1)um6&b%j}M2}lT>$js7##jqOVsvAlgyNg%vO$kYD8l5GRbXsH>pMItV(w)q^5y z;F3DU;|B8mcGR_A)8kR84;k&QbDe~zdeydI(A&gnY3y;%@}XQY{v0YX z9q05U>Fjh{7^iGy-9e!_D+h8j0pR;$Zw?2tPvY;l!v7V~JL*0*f4i$*K6kefux3T@ znXk26rz5EimN@6(hvPh{oVr%ZpIQ4BHL07LW4_f=0rZAK!hM&Z<&$8A`jdBctUx}f zZU{41tZ)5vgN@-;7Q0v-(YU_9#aKUb+RjBj`3ef&8{Ez&j%+sX$GC5UC&qKSq<)LV zR1y35VJd$sgIqre;A2j?1O1G}b)fbsV3{GM+Z#kPj45};tH+}}Jz-H#%vh6MlUbes zZ{`RC6MM2<8~XF%_$5CtB!N=C)VsppKXFK*WEnIK2_EV7x55-xIC{qAF ztZ_*Y_F4XIpTI?~T0YsY&V(FYOzs_m_aIr^X;sc$Yy18*+BG$bLZVXd6ANI@;x4#l&Imnai|t9o7;z{x56eYWdtWeq9h&Q!-+yN0l9r10_Asl zn8Fj>=TR38$$42zaQ?RYuU9 zJ>2AsK6&2?5auE`%O9XQOSyUReo5U08;e5W%l4orItqS~1@d*Y8t8>0izBaLrf#=m zd1&;0uuOJfGSP1N-beS;J_C__GI|t-S1GYv;<8gdrff*5v{)U^;;c1m$+3bO<3Qkw@p=_lFFlu z>n;<?zSH zx^$j=7%iHa*x9od{q4Nshwx=DhoK~fR$PshtCLLUo9WM}&GG;~HdIJskbU<+zEB?* zHi(}bWlGE>9(o+n_(M1=?@xoZQEXC#Gu>d;=iF?TR>E{)B%^R2s@;CrVnLb~pngGJ zk4VUB5W;0k3j)foSae|Ri#*O0`QxPQpcd9|iyMOEZrk6@x2uR`Pd@Y%K@oBiD$%&3 zFJeeFO?KK`6X>5lnK8Cd&UrDrAd|AzCgs@kgVI_Q8yj}VXaheObgOEN4x2k49kt>)zB<2pdMFLmx z^7v3UkxB4PXn}G4$JdKQvM-hFtHw0iH4!_6&QHD9Bb26s7eX*QVX##S4T(q?}nc26heV2w|Up)qQ~~uRx3OlorIIkSL~-a%u$YF%wm^ff9*OZ z|8BQ=We9PWouo+zU!2St@+i2XLG>K)M(403`>mfV0}YQ^1HP{vBMK-86+`93>OXZ* zGf+R}hmn+epkZMNjrHbDI9JTC!XAu>1uHFW`cGKXyeQyp)3H?mAMe}G_8{kn2bABZ z`09MKLlpei8JtWeFvsVd<0+)sg#|YdNQq%oL6*iF!ffu@9)1w71I^)SI}7$koB6Zf zqMBvs$%nmTq(K8-i{O!%=rClH5FLgHmgiCpt~nyMI#HueaH-91^89&aY?Rjm`YXgG z9hY?RGJ&T6@p01W%;tozcgWZ7*vZTb^t!+8)94%MOQi{ce1lgMBP}6XVJ%)6as+B> z(jQ#|L`k$bcJJ(r8wQ%9J9E+Ns#?M*G3spD`o1j*WLOk3@byhk+;6=anc%XzegAL& z^3Pg?qDp#9kE)gLQGGnR*;C4StHSgO2;D|vT_g7kFJh2jTtU@AR(jf4i5t#AXv+gu;%^*fS~InY$fucL6E2 zp@e<)-M2j2>+fjKe}4Ro%Z+(f;v~T9t@L2bFMuP2pr>5c%jKCj3FZkr{fQamz%f-S zi#T2!ulT)gdPT*@!{bQF;`8fpLzO39(pF$t>5N_DRK{f<#yV+X^4Y0cH{2p;FXE5V z;Y>-vwnjjF_}G`(ADSt<_lMO_;%3abUeIY)j;a z71`Xcdr&TkV^Xewq=Qyd_3s$B&+$yKTG$wtVg%j@Op5psDOk3c_4=fHIOW-~F3d}i zeY8Nn`WKv`9lU!lAqpJRQfN@vY189r7sd`rT_o#r70o!fZ}1zx{=nAE)N@GIv#a4A ztXk6z(p6!nSuM_$g5eQG{g|U!WgB&=1i!UpN$xlBF;&X_pM`%u zxWRSvR`4#-DDNR~i` zKL=04N82+-OWW>4`aJufDa9cB_P{LIR8&^x~P zFoy9;@H2ZzdWGY7p?1QVcL|Q#WEa2(k(vkkQanB&-_aE$i5R?>(YXAmEwU(^h7W=# z4@Bh}#XNCx`v-l7;bY~{3eF`M#N0AI9}>?!oMIxVcc}TF_SM^CAd*Z?oq+PwL)Sa0 zq}%rYX3wh;zR>5h)4ld(5W6+#BZc|oQ+~=HjlJfYyjNBl)F(lfUgcucPY@;v z8yHJckLmyJ1Na!n#cn{(PZ-E&9Vqz0+o$La;sOqjgFMeLc8fKKe*L;^LR?ja|E}qE z3p}%(cT27uRdO}=Cwr`^`u=%5{0P(eMeY|)0z)0xBPqV!el2$ajql_Tk^b%D zuc!P>HqSDkMBY`xSC(Bh(r6)8S~(Efh`7%D^h&)q{6bK0F$nPa)1HFx`u_LvVEo_5 z1BPkxHJJah^gS&q&r$jeQ7dA@c(d~D#?<$TJ<0moYx)YoDoQe(FL>f_FFxhU54rgL zMCMXEE3`#x&5c`!1Ky~&5A(T4i3K$pMhE+>v}ie$p# zwmPfFWd4%Y8Z^dAO`>La^QZdUQE7$TwYDV@9%*KnZkLOklqh!Gh)<+Vic0J9O>i6I zzw!OkeU5qVM8)w}B-3QSaChwvX6;0v_oriH>&v{SKzzRapsdf>?RO3s6)Lf?hTG>G zAOyPS@;|u!z`(7*)a!~Mp8)ts^;A|szWr2zeEGzc$-D(VYz)EoAyscvQ;1;}8WEek z;sPW)$~#Z)TaQI8N?uW>4TsL3mdkyCX&rzlI7PNW^7QFxQVp zt#asthD?H-ECXdn3n!8AOONx@lkd#Er-A4d^*i;%`2bkMRg2w2_wBAppEGS01Ly8) z6_{T?0Y1(_$qJBtmOwu7n7dXu@8YCp5AAVpNwQ9G-N~0bNK@1*+Apd0LYCgDn;mLe za0$u?5_a+oxZy`U-s%8xY5V~>lDtdRmq-t!gxY>1zfYS+1qkd2s-`uI4`2*xt(Jb=JK{>k?%-=Wta zR2z?|LrhjHw6p=rF9xp1;Xd?FjX*3? ze}W>%D>r)E{kc3leLY$+;b^LlpwX}X# z(g4cugYv_x>KGITof7U0XW|Z2dh;Z$D1pm))6tCQx7!_*NeQ$v=`QQAreXDuHq|A$ z9@UFNeoL(1(Q6l$J4~RK0X{6Wco~q}r!9~Vej@bEFKhKVgw9(|38Kj>%$uzL9lRD)e z3c#pOBD7F6D!LavKZ@;WWC%UwSB19BvifT=S+)Ubrv)ECMG<$+H)oph8EORHTlQ1nfkHz57;UVc5t2BFxU ztLnn(`SH#Y8t1i3suC3TP~bxL0YmN=`o2TCdTEvh2EGDS-+2A+O@NPY{gp7tK6fA= z4|e)kFZk@(^()(>6PQGO!lP2?-(Jm$G4Y)*);H?z2Q7A&5=AP;|uAA)K$%P zf428xT=7hy!Pa8}?^HsUpkp9z9>-sei>Yt`OP^G+xvcYmSS>|}o_VgLAOTfpLxGrB zxI8+Q`XC?$VKpAAmo@M6D*z)l9fdKk;K zx+&a~n8Oa@U+>#Tu!iGEBB#!ee4&_|lzB|75C41dPM9>B-?`wH~ehftvWXq}{c559l#q9V&ouqzH833&8NL_4TR z8JwdQmlj!ye6{OcH$d@vfjPgy7;aWok_2h8xk+&1H=9hb+LZ*iHPHRnd>b^oBH;Zi zsKX9i2b|&zuYKNk`>mBU{84TAlP?CXXE^0Iry4vuz4syYK%i$}+m?y}h8$}1nDbA{ zD6Y$WfDa934)ocj5TFyxQ@&eR!=r!NXD5@h(rGTWkCGl3s6v}(CX9LOh8Lm*J1ipc z@@8HFBZO;cxF*tyzu=or$SvZ1an7U0$u`GVG9cduY3#~U0753FsLu2l!d<3)3zr^# zYa3bf<8H;1udw-ZEbPFLWf+8+5aMB6q#XX?8z)_%;z>`e(phllw>Sp?AIC%&BFOh& z1W(?Vw$>W*RDL&^kSD$Wl*?s@eY;+u=9 zR;m_m@da|fI{V_D_EJRru^;){Af` z0TsyC6GeVh#G8s`ux$|9p4n=Iyv9Na?e!~5a?H)|DZhsL(p27TCCi7Y^Zp#}^?PfS z!Tp4{846?dl3{qr=TxR_5fO)mA(u%%lAOZGo&3HGidT9`I`!3Xk44I ztfc2YnqEkG=y`G3P+^^r$j5;}f!QnnuBBM^j6RzV!i*&hL1$?Gb0D8kvmWiyz35KV zBfq%3VojCMuK&N61(b)A(w)_By-i`xwavBXlg zqwq6;53E&l66E%o36$Ubns$if!HcTv-~Q3xoG`4t(p8046g-VA^k!#M&0AXkA8S>q;J_T*P>LQb&v3FRCsG{qDA7m;1wjd}V{;HJtepeG~|NZhToa0&2HM5l{@?8^f3 zQSHNL5?a|2gpGe6WKpI(Qor&S812}FjFiigrvKR~S`tJ1i{Ao0>R@}=E)W@y_WrO- zBquy56tg!0DQTDbe><`Mc|VHUKPbk*vucjqksA%mlq|9r4xJJiTy|}5OUr-qZI%fH zE$M*I(!_|k#K@X|sn4@#Q(gmq>tdfsSJ}1kuzC&fF~byteuPgRkZ)s!7{Yw$dvsR0 z+Aw~IajSW$m>||0G_lY|`o90i+Fb`_)%9_sr$aiVq@+Q*8zdy88wsU5q@=q+I+RAb zySqV3KpH_hr8|#!c|Z4=XU{qBbIrWY_^)$){I0!M?B80en$T34JV|Q-BegwAW6aWs z)Lf;0?d;T_;8wiCzl}7QTEZWA&RmvlPfAY3j8Mo&e97IFhM9@<`&4~%W5|ya<$vCv zLbUaw1Bn%#W+G2H@gxuQWv(PYZC>u5jp_PY$BvF)vVCR<)@C~W`x=Arh zd0?r0s&AeNONp3J^kEIT=l*I#iES;3DOH~=et(pmVltu9m+y13x?x}@=iU#YC)0-a zW4`5E*1~}HsXE%ho*bnr3^M_ZahxXMbAh>vLhhy}KH2D;@|Yh(_v=6k(w{{bd~Bj7 z0jd<MZ(5-4!4-xk)oAy@w#v&zsi@E&Ym9l(dZB1<9XYag*mdcN=tmN=7s z^rTF=s?T6c>p&{ziy=J2{Z0j|^q7d&Ne5Z^ATD3tht!A7W@oY@+2U=O^tONdzkilr zc9LGcrTmG_*WE2q$b=q8yT)KL9K`~!+0PdIXZg$*)|{!E^4$ZhF052oSA|&b#RrAL zD2SXlr=0y34iIU_P#~WeRtp%_$$yt$9R7Rx#gajN2NRX2;Cg~#v^=t&l4Ri_6(AE9p48@Cy_o0*@2qcEGsX!~)yMc%xu6);5J<597G zTU;HA8$rAg>_Mu_2QfDz;>7)@8(hX5wiPh|AETEYYF)*RX@C!QMJbvcj&dpQTZJ;0 zuq5M}KgA(6MeMvmnqT;dStyabitGaxc%kC1wk;>|i#|$@oEqs**=V`1Ha>C4_#1Zi0`rUlVRwvwsnug%;<#cZx?*BA&p zO=#@MFeCD4Kk`BVecCs=R`CvjLFlklf+I#YI+jqbkw#y93BIr|R6XX`_Boys3!$1R z7Q$8S?MFRGX*ShiW}ed^|NOSsPM6&}HpqW{%zGwa`}zUCmGb?b69b`qt8orYzJ!iT zErCek3#28VpAetE@ZA)O?~QOAI88;~C& zWjZ@`vD#blR`nZC($S9t7A=z+jX%=$25$c>PcU1eoQ*tvjzSz#do+0J=5p&(O-E-W z1%EhvD3M}?v&N1A@==lgJ|*|Dup2NAB#D>?q)s|r_EE+TqE;vlMVnYF==90s&qQG{X2kM{C34T_ZnBSjZhLHXZ_n>)~NZHf3Ys*e5iVj5L8;S>J?|Lh6s~tMC)0%Ne%0 z(dZib|Jt^A|G!m46EI zA!NPj1v|ejfUmSrISF|^F?Ql(xRoq9CI6e*g)PSGb`Cg%OpD~_Zpm-INq@DGmwd>h zbhTd0+S`m6dwZX$7M|(Es^`kpyO;oIpD2-bss2Z;G>bx^0%3P}bLWiTOsG?SC`={H zFFodGg&Xq3-A<$mT?P#&-CcO1?i*F+uA4h?ahGevJ{eul4KBz>UTy>a`{fwmOGbQS z;Q4~%P9-%Wd+IgomzJu9`~G(^tVDb)>=;f|bgwqg^!>Gte8T*7;5GHsPrQz(5rh^J z&=xvz?^wLhfW@EKGI=(o=*^MYq~D#-exgLZO2ydLdLLHbL{ji)bB8(Mi!g2+|6e%Y zVaNk1&wrRKz9n!NGbX~ZvM1}6bG|H-fO z_j};+RX|?LG>{!qmMK1KfI7)Y?IC$ou5l)<9+U5lTlAP;lx=yKL(gB#=>HR)=! zB(<-w)shq$UnMqEr6m`^5-G?>Gmbw5_Ez01fN#zDhLB&esu(I{V_encdri^9o(YnU zrlOcotfx1evD2%&H%2gs0u(%wjcAu|8ct-!(_!y(nC0}xP&cYQOb7q?{=DY?Pgg@e z;y?%bpsA8EQlHnBod~js@~oTH$ayb0ozu*H>9amF(r7k9{(Yd&K*%01T8Rb019}iw z`17dfMcc-K={CW(y!WA&@_D6of0mJ;AigH?J^r(gJ7+H^j#bTP)FS;cYMEX^R~uu! zsCM|hbC$;9&)pZlkNo++ewk$KuZv^DG7O=B2f4!0LVNxvgmFn)G8#&F*E}yDe^u$r ziZuHcA$9d~4p-;V7rgCDQbo#@t2E*P^Wil3Enf(Bk+#LeqxjS*<^$M3VKf(5BH5(X&bZ_z;=IH5x*nJF7?95w}9Tn5|_+dNK_s z@qzQ3m)DW(v3V>V$Vbb3#R7JIP=NeAggo8|tKJvg7IvX2;9?Sv2mC^(rmWP*B+u@3 zERa@QE?>gvj4Ev1^izO%YWoCkWG}L~jl^)`N&Unf#fdO*modT@0t<4pw_8fjC;c)b zoE2(n!cK3YuPtLlc;uYy!JX!DFWTP0(2!~88c2!f6ml|Sf*Y_Iv6Xgsb z-_w|_5U_nu0KQv=7MYz5*?lUc9EVF9gaDO-cLh>biQ9AH6F-Tbm9nkoHWVkZ@sL&{ zM>`~IWC;s!Nx>_ey3ijNGQXNStE>9YoAjUdDRIPMl-XDIE|MG8|2ptmamC19O9|_B z^6jYepF=CqR|e(VShU@h!&}|e2p$4<`j+F{M7O@{vRlWc^?QHNWd!*o`yIew zP_;J?ycI;XG;aI*q z#WTO6`~-9OR}Ad$qyWB{b;4lO3F+qW2fkRY2kY}tcojlixbxJ&Pm5lU`Q80^6Uz1S zvvf}>lh@D^qZ#=ZA{RuPrfireq3s$KKYW{+K|XeqZSc#mQ2_bb^6-R4n<2_x5Z}hl zG$iDGpLWD`?1$=5q5U9KP)+I61bO;&3O=n_5yH5;s(#_aZUVL!q)T+TZsx|PY@fAS zfKT*9;85l?xRX)jo47QbVVwI%3aCPBjOL$ppu0!PSxX^(P>&9u^?HX%OC=KVJ^1u$ z^_w|=B_*mm@{%Rt=K%S5X(p|}Zl7oXp8@OQz+%@=`fTOzSC@5e@WYN?pW1CQs87~} zk>a&XURzzw;uRIPQBuI?Kg-(ebu8U7^f2GMty~gY)HKkD2G(hr9h|0cQ$#(-WH@S& z&O{O~u@;PI_`dDQ>~Deim>*sylxPC!n4>nTYJrI#_NJiFa#Q^Jv|bw%y(UkAP{1(P z-{()S?i_3%F2Lv3SmjZI5F(e9WFQj4zW*_0c)IE9&qx}NtXr-U;h$_{bX4kO%F4qZ zF6YoiOte*@KTuWr^bzh*r(Mct{WMVkb#LCvUmb&>&?VMFe>+6T z)ArGKl9c;XBIym$J>&V)qBG3|GiX}eI#yLtt|fg7TiY=_2?3Dr8O1LZuzh#{AB~S! z(H=okZg|2uMF&er-FZ+`6q$OhHH><(Pmw6U{7DAn?)Ow{z?1n6h zqIGd&?SHYb+oi#N7lMNg9I1Cos;3DQ0r_B_f4l|TM*#3$EGiXLC&m)i^)=(@jZmvP zZ(s9LbIu7q`^T?W zk&<;JG<&;e8=9i}`8!19h_O=(%-BMTgF{*5}LXJHTv4IyhSUl@f9%p%ys>#g7Oh5`ki)+|=EsQqw1cptaq6p{ z2Q;k~arNLPbBt)f()08dFv<#>-&g_rPJd<^cOMf&;93t{^jBM8)B-ZUzhL$@;{Ls=w;E7ET5;CcO3E+=+DQZm5Fk0^p0LLL_2Lyy5{-mslicv-*8xYWS9c$JN%ib1u@eRuxc z{?UhKS^3kl0^<3hb&q#A1}bi>_t}~ zuz@?d5#WN8CDp{Efv`EDuWDm%jTpI@=iC52)b2&Fy^{nVwN}X!e&HvAE2`-!A%>f* z02eT$&V}{wHi&;dM0|7^^cNf%DLor{CZqV?vtb;!()7jPo=2MSSEEN?Uy1V&Q~C9! zy-D%(8ylWG;_Lnfw377@;_e&KSTiTd$Y%9dM@hed@$WGW^ea# z{P}AR4=?y5tmu=nC?WVbgD1+oT_ei)OoA_tgF0OGTcc&E$%|)i>JQHTg9e>yRl<}d z_wVOhi>2|Z-^JT|y#?{eO-&uaj_)NPzPI00`2!RBB~c~v-DyZ<>F#{sSP@XEZ^o!M zJjdM1=bbd;E@qrFOLTIo`rcsjaKwt#)2d}K#T#73XgAb}=l-X8{u7@_e1X20Y32i- zsQOKQ;63)qO9+AiId`LLOC_Jj_)=@vDLPz~+p{6n(`1X<_~nWYna4h$uVrHWzTEFL zT14CcHb%Nu`Xw9=L_*%T@mb~7KO zk7u2j7SvPr>r1*fTuPml{W|g~aa$fW1Y5QCb4>yg|Ka`f_EgexJEo36wd^J{?zuD8 zcV{hf=Gw17=t7+MsQ1WoNXQx6LN(aUR!hLecjZg;e?>)dHqwbRTiIn@c>erNfDwrI ztlE+t?D!-A@$D;w>}BX@pC$R5h@(K{hmZndei zBKk2*jBZ_}9H||7DWQ2YwuH=hI|=Z$K@1Zhon_A-tyo|CI`F;Cokn>XhtCjv*09+1 z=woV&;a)cwhU98vDU4)6U7C^lK}|*2oT|AToI)|zX=H57P47wJv4>)pBf2X`J|tm7WDjid-^25GUB~}d4F9@>(z;HRP z{t}o-${&l1mlt>_E#`%~vO*z~EZdeZfmJpbg-IWAvsok)}-gmZO+iML(zJe7K*m ztAy*f0(1HEv3)Fmjz8%;gBZ87l>iHRwMzX&M+CVYC7bLImf^4)0hYRGG!BhZ*+1pX`dm-WjWG^ zU`J~j&ZRjNZwbz=A}p!W)jF0B1I78=Xn*QOnHe?HwNDj!g#X^d0g+1rlkf zunhZs@pusI1*1#9uhx#fP?XsqHaVn)foGT$vF?-@}T#m1&Ra!oP!jZhEEN z3=xCx@~Yk%Ivg`PO#TA^zkk=bddU_3x@6 zW}GV|oV3=YpT>U<*`Nx~T$7;4R8gD}ut;xiwn~-H3zNx;Z@uTi3HDTYp(^PE^3mJ) z9)az%1Nh1n@b6zfWMi!Gm=~Xicjk@oHy$9Ov$tSYVBR-7?hU_mX35a82%ZbtXUdJ7 zBe-iDuB~GZZX(CXMnFqn#y?9t*x_gJhO^K_)Mcrw$w1q(FhA9-le*vpGj{iRUN(tF3J zsw@A!F7uz^nZXyP#M19wO^T3GIm0Ng8ey00Qif&}2Q{$NU>@7&n*>`Sono(T8XH$W z^P&04BGWEb)yYoPb8EL@YU}sXUj8886Nygv|K0a@ct-Z$!!xcq0#Wx@^+KsmSkC13 z`N`PwM8?i}E1Z;H%T5#1pzbjmey&U1xA^Dh68o4a6Q4R=vXS_uRWQ5O(3r3Ch86;v zXV%O-0Z$F2)OVV$m%CZVGgUtWoPCqCcy4lpHy(MzndNCkq$!<>=JJDnDir<{3K2EAp+wEVv$Vf)w54P*cPyx2Sl*QBPS>mmmmEQNxo-H#1_l{DmjW{P z{gQ@0dkobl;xjs8cVXG<kmvHGTybx#CdZ8HD6RUFM2V!lj}i$iKKZQqL#~$<{Y# z9~dAS0+Anmzpu_*d``(;P9wLzs^7)0ibZ`5KgNV}JNzzVIYx0jJoc}TO$1W_Y@ZJx zzqIcB`pMVrq~%^>X-em%d7}qrp=wXPy7VTp2pyvWlaQ%7cjcpJiCJ(4^!IQv(!Qm$ z*X?YbR&e7KQ&8aCnFI2p*Ok9vQKksYtiy8bpq#8if1@`2oW*5kB(L7&(I+}K^n5;e z(GtIDa9zFIPjXtT#9~<$X?Q7b#(Eo5zjk_^VMxzhSiuF5%7;mLy?(Pi+DE z41d*HJ^Rn}NbNX~$IdvN10jZ;)X|>CSTDc^=e$?Bfaod8*`tqfZkBZ0IeamGKhd$SYsFXXPYVjL#|FM1p)wnlh_k=NAabua`I%5u+{^(l5lA=50vtM6s6b z+;vE$eRv$+=9)8Pgg3hyOluqdx9!vRp{YCgNLk#P{MnQ;NNzU{cicgb6hMA0vG-pF zcZq^jQ1}abF`#L2uJ{^$n4R|1p`3ku^cml0)jGbe8bupvDMV5=-Cky!4Se5c-l@D9 z*|=swHSZe-@-ZJB&w=fW2KbJ7@+~(wJqtz6dOIqDa(^NxH4$V&<}NzBzz?M=OC=mD z|I+0veb*S)W0(WKHmYDV_M`I9gwbaz*RwTk!|n~hw{Vbj*Qp6Z4O! zX$FnRQUTWwxFMAcO2&r3kJBQX4d+7!5K1Ze^-j295(w1fxVcs52!(yL=Hrh(8R<21 za|gyj1E2a=@~LsW3naO>m&7@XG0qeT=_ae)x=A1(g!jra*uKvIpEz0jy;|0^zrlW6 zGcToYAXII{ZJVs4vUOm0nmN*_7-d^Hid9x6uJKic#Lyg;{9sC{zI9+zpsPikB0QNn z@Z-u0P0f=r-XGp3iAI51OK3GG6V6KFIfBQQzk6noW{9R}e&9L=8OV=Of@21lJZ0i5N_Be2xK$s$7TZ8N-JcG|X?pJdU=* zE}jnZJ;;fHF?{*kzjpx^=Qr~eI;Xwa*GOS*P>k-2Y9rC>DNQ5DwN8dFFu!Oq89Eig z;-}adQvQN`(2UhuQeK-p;*H&@FN`!5i)WKr0PgZ|&n~4|{W{_-cw90ffI;U>D+*0y zs?*5yc@FF6qi^&nbfuYLaw++FNpzUJ6=8ncFDX4$pHWTTU!okLTOWG=`h-k+!Tj}J)K*n%*WR-Mj7XJ`(A9mPDK&Qz6+SO_2*BR2$XtX+P@ZqpP6#3M&{Z0OES5%7~&T($T(GGxWyKRXT@JY`Qh>nfqw?t7eM>mc&>vO zb+jxq0{ceHhWF;(%OI4@2d`w!m2?9=;jd6F%s)!a9A^VGULNC(a5+6eYx!}dZ*0wDXQ>a>qI3PeZ-m2QD)iv5uV+LTj56N8!)vDh9$t%J${^aQ!xLlR zz-Prnuoo&_kxKqto7k+)FR5e{Z!ITuH_28yYapBL#8(i{O)ImfG~INDe4InkFGyuwO6PfcTWZ>6LxBPSeK!eGI17Q>IarYrd|# z14X0+wjt`t{oLD`UX|?!^!n5n@f^anM2kD*FmI;(L#Ulgi`2B5JyRe6zE=di2c30& zHGH_e=7VY2l3J_w2qit4ys4e#VUNC?;4%7kor?jvN;xLixzU$B_@GDiNzOb1%>>s@pc-E(2s&lxzk73UbsD~fgLu;oE0J4PBVv! zN}MkZ18H7C>*V|r^7*X8KZzrpbZ8Ngl!dJQ72xy6d>+O@$6h%VJdo<8V@1z<@~j=L zHp8J93XSK{=g217rjnJ*zZKZ57F$HZ#B$ziL1DD&M0u8ib3C`>VqFUIv9*mvfbFXU z_>Qe8d7hk;Ua|FxB8!pszlc`sL6FL?M0+=Sd5*4f#@Z$6y|D*-aZ8*%bZ_$nhIQa; zI3?owdMvNH#K(Jf#z26tjimODfjuXErpsIe<-WAnrJ}{N+AjXO)5P!=0U71Byy3K_ZNf;kdORJZVlMJT7d66Ti<8rymr>OCY<8q zD&e)-hIA3;!Z-EF>@X2s{Y7`$c)QF7EQc)i1|M*w6t89M2W8&DeX*E&G05?t~tW+#+zDp$M+NTU8(*aooNo*uHvzFHx%&&yX_;PhRcAr)M6p^}>`Hspz+R_jBhd z9o&Lb&Zg0_TF*4(po`YeGtTmRD37f~%<>3BM1uN{jJcu+r~&ycAzo+%VN*>+Qa2>A zRrMIl!|{Fm{O)6F@4o8DqmK$w6ib}o_n|j2n@-W?4Qpy@!(9Hyr59HtIB_~Ov^uRd zARj{QUK-fGMu5*%@yST6ZcXshLTTym*^9*tdu{1VEDoN>J`J98;m?*okH0lI!%3Xg ziwyaRHM{unoOSo!x(O-2_YJcQSBX6EjIdhLtT(7VWEy5giMutow=X0c9Q6E7VEdW@zL|#4 z?#U?qpO3FK0zy(Ti1jv9tm9yrU9K7=erYLh(+o4r!38CTCU>YMc0vrbIY)eqM(|rU zn)}3zN2eXOWeUizK({>K?*0YRW<3OV(MbjTNH~KCjEF2%;p@{sM|^kSdc0LeHuJ}V zo(LLfDXWN2uL^EVy7I}us1&d#^y*Fh>r*QGeS+j;hxw<|eEgsJ|N8UT<^3I=jR1yc zr;EqiEz_G)+ypCM*+^N^0_*Zf=(79#QL4%l&Sh@-x@|g*epeRsVPCuBXAr=<(eHaR zQ2G%?Rut{Ey_#W12Kbsu2-i3+j4kbu+u}bTQg}v6nQpQfVO3GMy&`)2h5ma(L@M^A zV&g@lD)DZt;^UwBY09YuN67<=vT*~J(+Jx@`LT-+yad}f0LU+k!C(1gW6c?%!eB}B z3^%DVJhJesA#;=U#X*q7Gc+V_P0o{h6+9`jNa>n7`}L2EUpnqk$_nZQyJWA{gLo$Z zK0n9xfaP*QKB_f;8MIB0*_hAF?-XtXpR2jW|9bSPQ8H4d2AdSgxJ(2`aZbiBP*La& z35G;qP`&T-BWSFG>jL?pM)<+__Wn1&L4c1=Z18r%E_=d#Z^@()?^3|m?&0UG@wnbl zkYU?V(QL}6qRy|R_)iQM?BH^-&~3F6LdAPtsDH5T*2(h23Hy-`@Fm3#I=od%sAdtk zpa{AzPt=?yyS4LZiecVeoO|>MYgN7}>AO#IE_SeaGx*8VhqF1`r*1VfQHzy2&*q}e zwg=>cNt%@gJHK&&FHcslm;FZ?H<8xQu5z*KOcs=q?KNh-zUDN?OLO(snhQV`Cc&e@Ph4|1^8SM zqPIQ7oYpK*pT&KX5-eo2B`IbjS8_OUND|B`CI3x>@pJpeo+mafgda^aOcv3W?3o2c^;zBhQ^Gh?x^G9D?Jo}G{o>4Q= z;11>Tsyl>5xG)tS$S2Ani%REfQj=r{10Ww{)!G2qzD0nq*4WVF=sm2jUlqgY_!-9w z8XK&soIQ@iSF%N$C$>1n@vA!v3NXo3>0h(X*=wYjGw@FEik=1EtV%Hwb10JF|Ht>w z^x-ldGU9^pB0GI$E55>U#!sc^!^Bg*jj=`@ypl)X$V&|6XqQhJNv}>sq2-h>)gStc znY6zdU-&`s3iCAbR}F%ENc>e`9K!T>`XKP%(}$!I{Nynj{)&7AZq zh;j0^^0JU-t-Pgmd>4>4?au5mSK;seX}-_P7k zyUwDZyRzC2gLrr{gy7$Bu>pv$wDA%RF99L${mttZEE>a3+USoFHT`VkULN9ks+nKR zQ1&1epbOq9c90XW40TC<3E=mfY&Mb(wH`z{+Nim>1Nfj9<8@!87iC_%;{O^IqDpPu z2vydB$`SRGF#1#5qkzQoOe5Rf+@S0yJOwdjW%iyRG_Cw+i7fdk_M`sjYn%y?uWwly z{MFq)z!?-@qRRVAHM@YerN`91ghy_ z^k~{{Xd-VmNX%eMC-s;+P1s7T7Vr@y8y9omX@(84)S4!&rMyZT%IMXPs?w+KUghEw z%ljPd1^jws^?>U(-#)~`KQt~Pd-CBES011L!X-rAdeu4cqfa+O2j#UwthMMcT%R{Z zT4bqL$ZB*|(@*g&o}P!jv?}&VP<|P6Yv6Z(1AzP%LLY`_iIE}9q&kfHIQSk2b@8u> zQ?c--*Ryd>(md2zk@-!t)oH2(C0d#gk0SB&&LP~sn{D)@aw%RYDg+h)@{7n>$H3=1 z@$mob!1oe%2U@~wSVfW6LE}eC(<2Y!7Dahzcq0I!P9p_gV){p?9scRrN`h86MnPaE zY^zYS{S?SYD)kh6Um4)*1JC`Ii=(10A~t^APGV(Mf9`2`jm|bcQn*s0Ioc7L2pl&| zW82KK`O+7AX`@($rp39_QpRqTjJ;_zm_&|iR)BB5OMrD&Yd+&#V;5gD!UM;~()|2g z)cqm7eg2;fdrIsCoUGYv)}=%AC9Lh#KQGQ5f@;f_xmD4Mh2zfI=&ol#KKR3V@Ncj> z1hh{&MB1W7yNqgUj;Aef{T-fe=qB9z9Y`ifT#Wi{KVE7Ytq-|So(dqp_5Pfb*yO!3 z)h_rxGRXnoM;Kk<8;xWMz(qLOqW0Y~z6!2}>*xAR$q*;lZ+phzj`RXx0OYg$X zQj5H+Pw(vE;CA7ZEH%GtJV;geG33qR)nY~Y&@X~~T<*^IGf91&PYXY|IC&sZJ_kG|!ZGJ`os*xk^LyaNrc8jMph zD>unkloq*SBf|(j#k_c{ARi&K;Uw6;3xF?)f>`6d<2S#l;lv_-)*l4&Q&^{3Yb-s~ z;gmW^i%?qTNJX+}+niyZ56ylEW0+*i(L&F%g+sj~W`E+t`;F29@*_NV*g>mKbj%$_ zyHXx~2pJO0=ohe=vf?d8wR-eP|6ok6bc@QtOWZ@Y+eS+Jj;|78Fhn#@5%!#bmP*0U zX#?b=!#Gp|+jj@>;c)tf#2*-$~fAB|93huf>Z!k#&g0Qhpm8Om;<7-7G0?!+H^cnO&7NZM)`eGB9# ztBij1>51Ia9c5GwD1LNcByZ@CNv=N$@g1nd+gNIgQ^6oq5#9v(s7_kJU%jRQ)b7&T z`f~Xwd>ooQFr^rzS7^MNxJ~Ct-t+7>n%vM%6=Cpwzi(ycYq#WV3^fsn$VTmsg9*t^&7;qxIAu$l zZ0kko0CF#?XeR%XV$M0<{#m?qcfAv_Jo~We7RdKW9~%7OndE;D&m8MY&=4eSO7_tA z(T^fhL&E1|3x%4KZ370bKJ`($I(|GGO?HEJkJC_z(-Hq1;#+JSg?h$J+OLkFWel5X z8w-dJdebaO%v%rNLg2-?o|&X=N1H@O?2CW@B$5IuxBi<|ITl9M>gn!JZ{o8>GlPrV5^uu(o{dJCtV~S$!BXUe-ijUp*D_R zr{SzVex2)WiRgDrys^qs>*iv+hgT2#*k0KH-|3q1L;N%4DJ3Z_iL)5QjGP2l+_u^x zC8AR7KefA#6Gj+{Tw88Ri-XN~r$*^IcjKas>^uElUUZaGbWH7#M<5?5lj%3GeJB7Q z1xwHeOYA6y`4LALuZw(7;-Zai8^4=ov6AlOU3wYWJx-_Qle>*)Ud4ZX)%*e6z_rJYHV;ev{UHC_xP1 zdzotg!O1Pl=t8n3R#BoqF`yptC|*f2WPQZ&^s#+jTA8y{`r_u49x?Ye)Y3rZ1_ow| z34feZRC#?yCaI`)`PcXU={fkX&ozMW0*%bTUpH z_1!U|i@7lOqx>^FIkK}I#@kz1{>9w2XQL}qt`9z4c`l9q|MC6v`h4Rq_PuMhxcX*w zj^5*f*7rjHlW=6Ui^3P~vR9A3gOAH4XVJLaGhg>nd|I=uDdHQv>%H_Uj#|ITjZ{`>Lc&!9K#hVy1*&lKD}RC6{)CA7rg$HM2W>>;)^wvnSA zwS?UBs1RAbo2fP3&pD%hl9*v^=9o!~&)^?GdN`@{AKpK+TQ(mH?Qc*Qr-N(v4z=I; z&IO0(xCr5MwE7o&K0oqyHON08+o$lON;J}99&wv!zYGlE>qT?ikGk=ZwUN(@JO}Y` zE2Cxqci!K{GZMh#C)cD$vtnkqS+j&VAru!&(2RO~LaOT+nM5*VFv7{_TxNZQ5z8zU zo)cNX4$WpgwJFG%>ZRQ#a49I?G?PRB3E-m)S46}Xoy>*X36~gkd-8VTf|W^Xc3-Fp z5!&$4*E{G2lf<~fcWy%?XN5JoDnmQT-m00L?o%&ByAW`TLw5=CVcR^70oz9n@RfKb z%*P44HF=m8+(JCnh2&no`zqP|>D{x7lr{(`p(s-VcmwEghi}h<#AzbqDKH^77&+AC z=oek%f)M*o_5M8~<)8f2`_3UQ8;)Mb|B!K^=C8Z@+6GDD!+)gs!R+hsqp#=W^O6r) z-@B{{V^n`%OWHM`3WdJ$Z>DeDYZyOAytzmIy{_}{06_$`1PlKCGBf}mJCU!{RlvGh z6DI5%+?0tJg5-}PNjh|dd>qhZU29lj|N327fZv#~$?)M0}0T?Dt~t$SK6`jJg%~OG{5a+PhoP6gdkI$(-UGyezbSu&5n+2i7;<$$wSopzX zF*@&Fjy-^UL}ljS@2uhg_~N~{6-_0_VFhYy5=@r7d4)ND-o11^-j&d%ikLwl<$(G) zqm;moKc^nS$yP&|*t@669zBMYO5HC`@1+o<3#@%Hc*`;8gROF6`Gp!ejC}30LY9W! z_9%p_o10brqb~|mvI`!Wq=)sI0F#d-)+K*m@hS!FMDf1&nbHA^?}#e5ZynZB%!gMWxxIUt$$>~mwN>2 zmA=lCl}*cEYQt|!5vN^s$aetw1#G?R^}$E0TMWE#jPs!rKp`j~;IEa$5GjB4XLclY zuQ^-cZBy%*(9wgg_70P|M&T(bhiAca^X0<$Nmiq5c#w}A(!~dCpBTXButk0@rP(S0Vm$g&)_x_`Q-Y?Y&FhO6Z(&`|q7qs>EhK+VrSomu)mND^@6@ESD=V7e3%PZ+GSKZrQ z)VRm4)F<4g07dPjX5~zGFY{ArnjI13!==2c2HPhE@KIoDz6gA)zIfwJVkwS(C&!^= zr)v8_C3IJU%^?Z%yJL-{MQQUZ)=3D=VgZNczG`80^EF=J;Z4GhN@V?EARdh`uKjq!R{xK|_99w$YVCf_Xa$Og9BD z)c#ydbHlsI*cRUNmY=5UxC9?}E@AWNa6G&3*413N!8Kz@_U&-qxpoY=gpDT1dHnPc?Lg754O1+MS?rS^NsSj*9ViKLyL^-nDe zFSZ7*5BywKF>d8FF!$w-O(;| z5g-!8?br`qoCAFRBasFL6z@=q!^UmOw^wp)zuQol^EIw?E zjt=)~e+@U5Gv<9(Sl8Gy^!5W(Wg$B{$VX)r1Pyk6eSp!! z{@3(i`*Z=mBI3TC7(A0Mp9bCXZ|5oRW>VeSb)J_y%Saj<>w0KSwr{sQl% znk4pq#X~O<$kXEVSx6V)H$k5~O>ybQ&wEya374op!|=5{DEYZaIg=9Mf^l!mYY0uO zZhUOr#H_~u`2LyxrQyPDvL;)Ps%6(Lwv|D1M4UaSO-<|glRow7d-O>Y?>Pok_HgG3 z|0qb^JIi3nVdzkeb|BX#7oib*sj<3A2=ZOHxFi1WzQ5By-T$8cg{4E^t7pA;8GF)7 z0sA_5TV7}BDd+6V+n{TMA+wsWz~>b2x+#n!gDqq4BKG~i3Btug?4`RfU6OoQ5*%`5 z1eVVG`L~ntu?SCVh^whYy3}^0+cQPMBYIEv^ql;ey(3`s_1SL~*Fv{tlfy$rq!5yS zX~5MDDU4Yf>sxYsfCwfA@z|ABz~6dg0En-PiGtaZPwW?QUH(&68;&U0_h%XBLzM|7 zu-GsX(tNV&qRlDTh)V5l?WZs)>kd)llZaE>?7A5uYU=C-Z-{^wcoeV+G+wdT++ax~ zR;^F%;E?BdReRl@<)T!JYd^-AYsTIUCuKE_xoz zlnmq}iI4C3-{bq+y&D32%6?OEFHw${3}Dec{L*UjPiV4~osr!y^ZO4MF*=xWaT6uI z-{~&!Fus*%Q^SN!%f)& zzc$hm;Ddg4Qf+J+mA`X|U`j6PttxK$bZ2BpdDH*!Ru|cbJuPg{ce&ZPQEY%!mHKI= zxGwI(JbCVn(PwOOdCGeC8(``6aPtJqdn1HrTJHXIaA9woY(k$ftgO1vIy7tjX`gvb z9_d->0vD)0`Km3iIqIsJIRq`ngq>uvp2Z1Kbrr+B0QqQ?8!N!h&lcd*%&7E=-#5OK zIw%_YSinw9^`rKxyf_iJvSw(rg=Q zmz^oUa&UZTz6Og@kUV0s6t4W#;HT+b(}IeD>#y%JEA+H^X5|`{YCcLslVu$MA7h>g zZ2^2KEQB>T{3@b}?kdXR(S=)w%B|c_)JGp%+KOy~IqhB0!ki}w{pVB7uHnd@+2vqK zAyI0K{%f!}8KQ`mrFfxOD&{L`4 zpDX1G@Of;AjEl^jwnBxAY)77LD{wHXOF>;}5JT{9;mU;iCc10VOt3MR_X`bY9?(G( zU=avJ7-uK0rTW}qI>_1h*IRCa!CN=PdCld;t?Dq>eelBI7E>n@ zU+RI`ySGbUJ>&BB8-Gd;a~uck%qa?Uj(z(64B)HSNjODS$GI_R$V_n#Es^nqJ04*s|CSuze8#UoJG_e)s|l`mOLhv6L<0&@_n62#AB;ZW`^9*SfWhR1i+l`X)>h zi1~e4-fRh)ac9@11EHoL-J;{&;!Hg;Z73~VwE@07k0)3a6W4F<4a8pHZqxp>*>=dv ze;*nBx9b$DnWVjWP8mhIjWHf8AW#BxH)Jencd-;|eM9b2|4 z1NdUehKH7JZJG7jDOJmD2pOt}At4 zOx+oI!)nWqk3E(vEtEh(?$I|+Z}`O#X)~UTB5Ud?53>Np|HIi|2Gxh^y6by>ROJ~D^5WgyGt<-8 zH3!~h=qd&rfwhA80&!D*%qjpMnfNK_rSI85KA(_qz4!3#N(C9uqcs$c;a8U|Ep>T_ zNtFR^uVvg+zt`A((-UdH@SV?;$S(NN_>gNg%4rY(sY)d%hLsX)1o-ueImOZzRxt5M zpUU$V2LB=x41}@WXYXpY9O&zq7hiZ=+pL5FE_8N+F_cKA&wF#sM}8IaC8+e z|CP^?&@i8S`ReM&nDT~D^k*b7yfUF?#fmfj&F`P>7ym%Nc8;z5*Kzu}NtXR9*M);% zK1q8)yz@&$FPBI#(cY>q*NSS3=4Z-F&N)roN|LSX`k4&}Wsgc7NveQqv%h^8Y*^s` z_x0uP?H8B-Zok+Chmjl3Vf+YXKAr83UZ+uP-s#!WAbXtusD}P^XK{Z;xWE?C+Z`*z zvODFIk>jtDs;sDuz_?x89E>XbkNArJ^8UHJw~C~chMqZkaPFo5G-%$;FoPX%|IvdH zUGi7+l^0&z*qhPoPfT5D{H4u8ly5)QiV11zh`MZDJrT%B8PN^7=m6q-UE>OR+vIYf z_+SZBZMW#o;mX?T-|gZs`{wx6ev~i|8+Iisc)hdu#k?W&1J#4MVBx}-c2tPq5jpHR zy0&rD-)flKQVua9q`+;V)7APv$JQ_~S?MZSL*I5&FwX7lBOrQ2#1s|%`Ti}A3{w2L z-B4PPoK2+qdu+>FtzBAZvw!R*0gjFMZMVQMbxV-}f9XJV-^ zHDxVTpW6LP&Z^BwUA4hh<7kD~;AMP{;zUdTRV%hYsN6%dk~L~HiI@`Zn;^|cfoutueqieJ&3J^7M26@AMOUzvJ$0vaN!N{7xt}+WGW0E_9|oZYdR+_DwKP-Vv$S zmkt9g9cowxsJsWv+jmy;^|#9+(L?mZVUaGCSdX{=^8T5A`2_e3Tb=U5=jNDnyQ%+6Mk1K)zgW&e|t=-r|-bF(KA13~d>#INkPGV~1(_V4W9V z##<{>jYYR>5wZ<7Y59|$yjEIKzC_|imxJ%oXvXumdgcHh0ah63XV1W(|C=9IVd*#Y z%gDD>wd;=P5tzw6#Zy`7MfJoYzccb%CvQcd5vCQ66g-t>1Q~Iq-|*syC7!fYoHZwY zCR|C0M_kwg^4&4a$SW9%!y&@>A!SH9;}TD=pzGl$M&F{}%pMw);FGT|xBa#MR2I_-&QLPI<-V%>HJyKBFk*$JyK#*S ztMs~kM9aI_q)LO_4&dWp(XRv9*9PQk3>`8^)we)F;bYgWr})4Xlb<92DRbCdCmBiR zUMZD*%YY^9Zo1s@M(_f$SkJ{t?;zU2mR7uEFqr)JtLnK9ARmsrh*Zqii!YOlwt?0Z zo-9|f$g@pzON-dAQC(lg=abnko9Z+4ejE$A?&oYSSZuLIjZdi~9Ld#8N$i40wU{md zAKXJbGswP9AYV5Fqmo!MjBgWO>Df>ygTYvD_0Hwn5ACCGB^U|1L(*`UAcYvLa2pvb ziglJ8MsdkkE&US2A+FjkTT(7pegRibU-0vOb1)00eHO93>Zz70mT7NQn1O5AwpHMW zeDNt#)@Dm^nj%G{D%vHr%;Q?im@%M@4^X+CQ*;TVt8`Sj0esBeQA{BF`ha{CZ{~N` z2a#9~^r45W_CS;XFOct#vS=(9s42YHv(>63prnJ}k6AMIBz?=z^j-Yc3DaloL zqKb4fEl(AI@)L5y_R^^@#W#c*3S~}UeJd_AIrMQ4sjW?4&iTdHhuluG;*2RT*#j{X zkj8<`E44y;tszP7pc2Q7cT0}^!5!cWAu|X4>Gl9<_Y8SOvZWE~f>sdcTIh7Qxjo`N zL?8U~7i5j9{TrrnOjTO}=?yZH{dO1Oup!o9$$}I*R|N^ig>QrTAE+P$!_RTxK`P)I7am#xNgjUVN*!a0w=LeRTpeRf-|-)olC-Hn;iZwa5`` zp_AXOHY64GHAKni&DpUfr#DM*Sh?eue9b;b%Z)U> zj?%jy&z4@?OZhvK%?~?d7Wx-o>=+1m=gOeUa6(Rj&+cONvs)1xGktBFfTH3@EA@P^ zw7hhilQ_`nANljQ5KhQvH4h`_jNf*$jOIF7gnU4KQsPavXK^Gwev67JHsb^EK{n1& zfb5$9@>xhGKQ{`OPJgyt36yKF&1j#)vOR1|$9CqS>9PLKEO&^i@FcD1_U^HO!EXy? z<1Ie+SC@d7Ryf%q0%n?lz+Lrg7d+)Z+2{v4?nqu~P0FpHPEjro&8dgjR+s&$(T6DW zI!H0j)a0PagciQg0`H*5aHBCLJCDyw=$81XA28()@NqX`fqu4p6UbNoqx0M0^)uWD z^&ApI+>@QU#+j(x&<#c!@C>??nIajzGt;D3l~t%pF%1_8hwpPStOTj3@Da%ySsAwp z_MlyW#wQ1I`=%tb9MPTvl};+iHQ4b~PIa@V$=S9RWGN10Y{b?^H~dq<(^sUY`#C9NHXl?qm0% z8GMrG;1S0eWub(N{RzImKhoU^(%0xp^u9K!J15-9Ie3wc%{9Q6jQ)Qc^DS+7 zhZy^129srolf>4OuXa47T3LRIdbed0HT~i{${^(vMCe>nwOU$}GW=QF#)KV6zy*Kn^l69yZt`Xv8oyj|03xDC4* zx&CILU&Ka#vXa%Ceb3MT)GqFj8XRkLbM$Fj0#z*FEpT6G8-XK?7S>Z-%hHdpS4m{a z<0&bc1$i8$^4p&bUwk&hs;CaOE2S=<+9o04n6W$z`K9@2O}{1du*IV}rO^-t1AN1- zP@wzpfqZg4tN}eRqID=?;kHZLQ)a!zYxH}_db5?=`p5o zy6asnEzYNAa4m^qd+>i{{Ra5$%FWCknCpi_B!3ix&}A~Xo__6jT-hA6A6W@`{&Zd< zAvNfDR`&HouBH2|;fVd9uoDl%(riuhPBp=Zxlg5Z;S<1zl~P0v^7uRi8lSq(BM8Vb zVsDfqyG(fyp)C!Eww(+hu%kjXO6ieHT{=!@Oj}}B!ZQ0&vrd;efBGh0&}e@^Zg+-ceq9!{ zs%v=oEZWDb=B5e;Hy5w%NHDD@76$Mg4WA)`>ykcm~_GNsYZK+6?F(XAnXFz0;YFmHdfYHqp9@?et zG2UZ-!m(8$`3&&E&^LnKnc)a1KRJk|55)0dh(^ytr!A@$VxkV2{W0683v-Pw5bnzd z6e+*(_yj&GymJ?>ZABY2Zd^WjeMjDH*xSZbzQ9@9mjL8rbUDt+bUX|dg5Am2to`MK zImSzf_Qj%pqvV3+#W&vx1OD#jyRAeAdk*-1qp&7H?eFcMb+5Z@Y<19FP(Z-B(PDQ_>ZE$YPFq= ziwh0a=?>%@-qYpVmh(>X(kznkHl@;_u8d*dY<@^FWEWa`$uGHd|C~>|_SF#Ew*IQ! z^v3LUqQ{53!f@YtyC$*NwK}8}fKRN22K3eiS3v9M+Pfx#);5vysUak5sHN2;AG9Ck zPI!d2=LSRs7Q{L_Ni!$Pha9$?c~e7ZGwTHVBoX<7JlGmUjXzgpM7}cspUz6OE|!Fn zx@RyyC8UyVZtoi-FgdN?pFaC-6;1oS$uN6WOk7G0+NE zT+%xSSvgOCiaSVi@dJg`rN0alF`cJZd2kCQZ$f5x36((^YnuoKhIBvx-**D=Zu)3Mb(^XCawFZB{I-!l z*`hUnZq=UomM-%+CKgZdHeYj^OB#j3ohA$uF)TX^;3KJJf`^Xxu!+)JuDLj0EvJZu-dL22ohL=)a{r)At6=ouT)KAWK^lJt)6S?dm4u$Dg!mUX^xt{l9 zjOTrIj=ur&E2?G!{d5Qz%763gJ^o;pZU!X}H#RB016i*jX|iL#&@Z5Jxh(!7aa zX&7~%he_`;K39D41z@4E5>0ViQd?6~RyurSZpK8ai!Z$ib>KgfrU)Ji9LWRt;Nbrs zI-fxTjnBtVLXE%1FR{DqbOLT|Z>jx{B2RCpM-Ek%;(dzL`C?`^wc(tlY2jnC>NpQn zBon^b!7u4^f~N$GNTMzdeB=l6#ieeMd?!uVES0KnkK1-FojAE_s)gAiA$y1Yr})9f z1|crj_AAaq`^2q{MaDi-G87^FJxkTS|C-i2|3X%dVt@~N>OchK`9}rh+s6rXCRTC1 zbxu0oF;6@603!~~?bCegNT|Vf)-Gznv;=u(0!E@*wWv}^y6_u9QgMY%gU3Q4A;_`@ zGctD`xHwMdsB7g`isq2!x9})@P2VYY5kfxx;`dfJs42Synv(bk<1U z(=}LjMq3cvsIRC#ntVby!uW<9;q~G}6~uKb01FrRRLKh`6n6(xQL8O?8;WpYWp=H% zK!AyhR0i-NApSoz7Jdf0zGL@sR~i`xu~6Muq_;|f(GJ@E6q+Y^=wDT{Ch)Y7Ohc$D zxvHYOtiXO#wm*yS|2=~!849nl^!?~U!CI3q0r2=VRe9V&cbcAh3eJGgwtnpVI*t_q zKJlCXvO(t0=>qF%uA>sjJXD{iSC2yS6ZK-ztZQVRcY0d%2wUX5cg&pS03W4Qw=T%} z(E{a1r^@pyPEMOWxu(-s*%MMP{;27@IuDNV-FKn_afk5MS@AY3eKG?^{k~nZcKA?A zv{HXGZZ*LOqjU|~zL@1Zp!tUaog3Lp`~G?x`LC+wY8p&;H;xqTDAV!u@`*q5uS0d* z_wDk82Hk$*BqYW#rpKcs%oIjQWHI!8OJ@L5EO;%zN4pINdg~VkAfK+3!Ivv+{llvo zH~$qFugy1QbJ_H2`!izD21OE7u^cy>9DBd5ZNztCr<1QA&*HQe@>Aq+BrC3WjjX(b zQGr{dz!1V|^*}H^31Y#MnQ@&*S!6=PXcYf|Z^0M4dl{eL>$Ftp#SHCjOSNwpVR3aT z@2QS8B+|iT*8_YoYighuZ?XaTusi~lNGIUL$se$B)UHx=Gfc){4Z_?! zzQj+cqz()ul269v)fQ|cHp3=jDu1Te8Z@gR@`HjIiRX{X_UbPJZahzVkhXgDQCNMi z=V~CP@p(U++UVX>_;rAi=J}uRa*63CX0)_fywS(q9e=BMyazVr@9|7uIxApP3Q45D z^f{^t;A44D0(x;cH<0fum~XN8J4R1&T?5o!r&R$7BWN|Tpe69)uh8-dHXizDAycvv z$V@b)WWXv7l^pc4OCzkA{p`vb&a4`OE874*ux6Yvkmnx{ zkngqN;X($qp8ik>f1jB<*gQL_5&r|GzD?U_+xNWhVq>|cTO}YA@!JOqMwBz>GdR&q zj=ALVa`N>~?@Hk~plyMCTUe==A7nEIBhw*Iak?${@y1QXJFy4}S0}Ome092{Xfur? zxRZfF?7b!n?c_ipbdfry60YYnu|4VS0GRi?E`X2tN5MYGK0YAd4-M4}hO>mWxsbI$ z)%n5#GHi?h)Q%}xMXv8VuHX+}Plr+94ojXRP*=2h{ETb8v!T|Bs7uqZqIogEWpiS9R?jSu?^G+?~s=c)HsxgpQwful;erJI9_(03th z^K?rOQI5#hZ7e@{I)4A{<5VvP;dIE~@BdhUt`A#c!5C$4s4L;-8uXD?+rraElgJeb zcancD=f(4!ckEEn?n|X|ewxV|IYpRTPs@1{w4~jwnxl!2Z=#!V`2yS-lRxq9O6ASv zZ``+O(V9XMf<(KSdc~}Ew<@FyEib-xTpBM+WJO$TZt6frvDBK#DDNRmLe}X!&LazM zl_!Xn9zcFj-X-cF=f@9}AF2g)#4pP1xt1gQYdsIHn#r%&W_$+iv_)r<+*j_1yd@T& z5Go$K4UvPW2*a(0BMxXnqoKR^es4j0I;tk?0QW{Ixg;JKgA(ov-C@0^S~FIbIeb;L zNDn?1M)|rwFSL;G@F#vIW^E z1mvT}pu0sP_h}a;LC`&&*{nAFWs=4eKDpz0W5}u$eLbU4_^QG1;w~zeEm+6@DfIpL zkW<-*Z@N2RJf)IoKjZCz=AY`Q({+7u%*UXhhL-TF#hsDjckYrUw%k98z$9LLV+d%x zU)Xr;yW`vs@t;KUzt7s;4p^_$zSk`!LF-0aWE}wbI3lGDLG}p)`5dwQC8-_rDCcTf zmXSlg=s?iXTzqc%zxi?wtMWpk|bN%JtJv?i=Z8 zq(dNIIs_c$;Bg{cDFbSDje~o$XGxJeSK7&A&rj|@#nV+;+GHEMb#awGxO1;iE+(dq zWI|G=3L>f6CZESLC*sJ5|H;p14P>7JkPkj1%X?6E6THHO*mc^bCk6uftV#29H{0HL&!aF_FW;;_zvRb)gK1z{LRWl?-F$Lepm+KcIbWsc^Cnl-N&FDf-1{TT zDS!{Nc{v$mpAwKyWHwhtwS{C`n>~>5j;@HM(UR=Cws8N;)OzX4{h7ufJGN;1N_wT* znctK&mg-jDE@v-4mDv*^C-qttU2re(`)P|`5gWu<*wZoa6zE&5`&?~h<_lmpWfuv} zwFNIeCf4KQbMs?Wj+p>gf{svxr!D>sJDWf-)Ut? z&LlZoXlA;J3BzctqQ5mFi9|^voCpGoR z+|P^!CkX*(AnKN)FXqx1EzM@PN*G!M_-OjjWkJqQ3&?ks<04ei@#Xw7Zm-o=qt)S9 zd{2MSrIEL>B|M!c%U(Ug|81$Xf}HSVtx0I9PLw6@rdnK%<#EPc zwxdqQJ=w6z&d z-Ffwm^LGu7Y~G*eBM3E;S6>ogc@azZYD3Ii?jv2ER|?Bk*kN-cjhQ-KG>2X z(68@VK<`&X3U7<(b~Y6`6(2G^?AiCs7oQ^A2b$2BjP@P{B?6*?zV$Ek7VAk=Z|!XD z32~ETZs%}TK2?EPA6yv}5A=Qp^7-6DBwtVnEq)qNw8Nb;YFN%$#+)lmxGYF2{nI>z z#X|x!+>Po0=e3?JlZzETfsfd-HqE8*`o&>uE3S9b{TjfB{Fw&y`Ns!z|02hpke!k; zQy+Qk!m}xqf(47J`^nPf+qjtUGSZj?>4?daI2%@7Sdp@J(10ZhccaSS1xK876vOxG7Wm%xatI)s}W zRsyrTq^)2q*jy6<$X`q!f*9pKetdpqJK2)XHE~UqW$s>GycX!@0_`{rync!salK>d zKFgZ6_-Nge75|eS5zUo&cV+>dk^0w*@7Ap4;yre73DUe@4)gm`Fp8TnCud0N=siw$ z6At;wXoD?)4`$K%C&=rIC6G^~q@lHW_)0zm#ru8j`h)VhTw-WOh!2+P85FZjyW|L; zt7-T_M(F|a8ty64U?5$Dr5rW!3|+G7EuD1HmMZX;QbYpK1?5 z_E`b>a@Hm?4SL4s^N>4^V*;4oF9>AG>PnKQ-NOwZ;~FEWd(oGcDMZa=lz(#s|U43tnT|+fBJYq%y2bS zb?4F{D8%oUkv?d@dMP>|j{&|&{OA9N^94Zr*RPS3MT@5iAVsQ+L$15nHzxb>6t^=* zqHaYckY}gaxtawGBN3UQLou+A8R(JQw9xQSu%}e#`js=a!tlg zynnq@4EqJ}VgGnc1UWxvp!@`3`WRM>0{lvw^?O<4ep%Ui330C1;q^Qlz+beT#5KK7 z{oGrywAp<(e^E-LmFjT))3onh3T~LW^S^_DYnDL8!L>FYUXDV(wNLtH?-+1&ZZo$Jxg3;VxvpSbAWFhV-NHX z#}xuy|DH#l%fGt8Xi!g~8zZdrFxL_a|g=#n)qT7J_?YMxmO%D-0{QZ4-zc+3D8b@Koa_l0RP7Xp zU28F{r<3Gr+!?5c2QsCl)Kxd;qk6)Gr%seNuUC>O!cI_6;+q!6`pgQ^eW2n|xw*Lw-4+G2#3Vh*Bybe<5~f5s>F z4I$|JXF))|-n^`D-kQVVZ&nyq5m7d|t{p|KuYxempD{d-$+5gyWwQ;2k!g40EI%`9 z+8)io&y!{|!7rHLjP2U+BrCv)0OcopA2(Fp3nSn5DUS5;%f`;+?PmEpgso|chjx$k`YKcVM3ht(NE%O&RIy@1WHZ68;_|@zmhsa zl9s#j$;Oxg@=bA<(|b{bbxOOh*4uB@;$`%@h!lx09o@TMM0PnW}Q zJkzJKI7D@wGufo(?)}!!`TU#7a+?stpo<#d|{@O>EvcnyGO?>m_?dm!~?;`Ib!YH#j9%F?V z>;k#JWUvAXz(?1me+05G4#*e(bV$`pwf%NlhaEMuR2(B5|B1#X{9<=m_Otn}(tE57 z#6@9QCXcn^)x=_EfdFOVn+gjuOy*g^_ugPlZfhh!KD!vS2i7l3pE2y^@_7t8RZ@ro zv&9?wi+`$Dv%k#0@X}R(wZP0*Q1n9R94vX}!vtjJi?ZHVx&$jBK5FUNyQlykCsu(E z$i5UH-?2k_{hCa{_hsAYa~s#+j0$b{!f#Hn3ANXAC>0Mvk~>Jg6?`9HvZ{l~nr3U3 zn;&os*di0rnBLny?|gM+4*Y&av`q|L)1ZF7_mLiv$I7~;F@;m?vwYaq4_g$u7hmC< zo?ohZ5DRQvje~7kAAIAx8m`8f!h{d3HgWhU67x0D0Y0k+MbNvy$N@e7MeCy4&eeb7 zL0CCWBi616#YbD@p0aQ%cs?j27wA3h>qkChrWQt~=MX2pP)~2yH10*hNav8n6ZnoW zaYy#x2$Uc7G$t#O_pXAW-sq)f4=XFubH^M)b~u`G;3RAY%wZb z@?P`%Gd808o>iNYE{!V0v^plhhqJN-`udU!lwV=5EQW%h&!F(PebazGccmM~)5wdP z9!-k_bys&5pV!at3_fv>>WqH3e>=lHsP!efE&+*dbqdb7DsF(FT6+`7#~YuM(=gom zS+pD}Ka|2W!TU-&CD2Ypd<4t<&-+ckP@DbRJZ`DSSF?&7$uX74mspt@M^+mnu7qOK zv3Y(SxBwr1VG0PX_5XhVkOb6wo`mztgp~eA;*Vu09^Wo6EdR=YSHo_FSuDp?irkP$siWymQ#vdVAl6IrCK2^k@y?}gmOJgb*4=PKjTG2Zik2*9` z+j3#S-jaJz8@aDv@07bw3L*fUa!J~1w0I%2}v*W36RQBnmZ&t6H)Y9W8le`-LKTQ_;Jw?0^)=7;L1 z3;N>vWV|(?&Asp7Ml%ZQiR2;y_`nL&LBBsM1@cwN9~cM@{q@M>_{Cjr16%-0N{un- zH(2A_YkFy{MuIgM@8WB5(_O-LcnGlbrQtA@4lQv$9p;!h<-qabV1llHegBlFLSwU+ z-#j^S@^{A32e#sAG9eb=dVFH`kRlHGiX**O^vyhzEn6a4P<^ISi5-?$|l&nJ3Yc z%@0+YIuc|xL_C>GsuK1Xe%JNp_*Mx_5XJ`rYBWfA|949D@xQ!(%2O?LPlL7Vl%vp} zdlcVOhWZqIjY^ev;6xlHAGUkpeHD1elH6QZ%fG(z@t`%~vKdVot4Li}kvYBMzQO&}w)(8bj%SmF zJUwaf^~0&YPr99l*CQpo-^u%j;wBPluXt33 z9jpzX>WeS+WUyX)o`Ra=Ocs6Ia@=XNMLw-vT)UiTRm<^ns{VZIXXoxpG4S!2fP5}d&J#4^8I|86qVnr>zKp2+^>vkghC=v(hi9`FUjavBvGh5E zi@xnw)Y?{xK!usbRbxH0UTO40@G91W?r>^=4|A1t4rE_FkPl@kIokvbzqc2QZpA$d zRqTq3%XKroCjL75ry4@EVfIuJ(|Q|RZ8_6EQ3D>4f)I4Uwnn|=*&wEY$1D9Z#}gbUFf0WOfBW92gI<2r4CG^{WUi#BAYu;HVYAW!hgDRxKY+j-Q-!7a#mD_b ztrz0Jax%zW9o{YJ5?GG(>!DAl>&Zs`yICr{?;$L)?R@e!! z0DRo8W9a|){Qh2EaR0l!oChvygr?Sz?&6R6@6+mj<9kGz6FpxP^}8a%t5MmiC*D#! zJ02%cQl|P2JI90hw4@9^Bku!YhD*byV6C^n3^Y9TA{q>hQs@)!rqGv%YZi+Yz@xP~b^gEe z{=R!@1&WWri$h~P+$X#qgU~!~5ix=GV>gpyxYIa{msthRk(Sre4-J!6c803U@12X* zC?CLnJE1q0x;uYJtdge{W!ggq@>%`b7m?$*7EWk*UD0932v$mb`0;h-^2yX2$i0{N zU~VF=Lkvxze&;WmHg#W6jXVC3dp~%~E`=E;8m`%D7{Lkfk)vyaes|piz^M5ry)>lzRf zHT+fym0^b0V!)p=3z3N!9A4bO3-GaLPhf+bUoVhP=XjNMiPvRW+OkkeXNZ_C=ZE_- zhST=8b;{XB5xF;v+z-AkEg1b}rsv72G3DgcWmG9%`Sl1T8vIPL&Zk0pp!`_o6i1uG zg<#4G4mAlW8sS? z9M{g7>1k8VpVPaqAPDR)sg%Axkm9PmRbH4g29~XaE|2-;?ZW^p| z#(8MD{;nfa!FJTlH(@B;XQ2ELrPTVqVfROII!?a5U7cfoWa4Ub!IT}th&w}j$uFsv z*l|%67asv}98QCpJ`%aFq7i+QDkr#$FOltnwxV4G;G?cB0R8D<5Xi^fOlfQJdiFb> zAUbrh3WY{=nj_m?8M|===2b9ZyHcI_X1iJXdA>R$sncl4V8Q|?(VKJZD*Nqm<10OYbd1DTJFo7{C&Y1 zav-pNUH25k!`Q|OnG5wq7zysapZ;UL-fhl+{&s>V0`~l-yFmxn*S2Nw;*hFS`&3%_}G1U@IlUR z8YsUnXmHY!Yf>K%O;tiDi@~r31gk}!RSJc@xY^Z<-!Rs&AF$d_92Q(HF|a+{qRXwB ztS#f;4Zh*U(0yOtG^(BqG(N$+dK)A@9V_z(;`B%Y) zQBn3W88HcVq9@?=InZoj$64OQgk`Z223`TTs7pW|;CoH14|?_HERZkJTq1lyUmY_g zUPNd&kxWz$93iQ+R0vEsSX(T-^#Xb@qj{Ye6@fQDgW87a zb*F`mXw6K8u)oYsdEi1Od5KS@RDxd+`(p3a-i*>fuC**Xu~`NnO7|n@xfz9esPXDDqk+Qt@HS}jSQgQ1@NxhWpkM8lIqrReWvHV2$er{~2~AxSWU z()qNFF;_{+coebd`6=VNW!@ zYQ4RmoRLkkIxJ$zy%Qw~HE|qiFO2K4#pybdY^}K)xVpZsw>j^=$_iTAy*rek){8G|dkwCVLG+{R?M;pGaXKkFZ`;9YYzC*-yY#ZL8vK0Y^Q zMOAfT#GG+whl% zE{9}u$H|oRaXm^W5zSLa9NO3XRdUiSZy7}zC&bTa2Jq4Sls*I5_Xy;Z8Ls*{hwZd} zgd(W2!2KYTVB=^aCTaa~2W7GX{b$Z6eGBQ^<)WTXR52~dfsYs6&YN~$MRR8iS}3YQ z;q&(ufqe77&@(8}x_Vz3q1K6sm}Pa$@0>1#Y`O~^9knyUoRCZ3~zu8G!i@FljPPUC;xV5I@vOm&`3*K-7`2=R#qtjZt z#DD3}9QTT9pmQ1!9$zhSlHWb8^2O4ALjeU{jKt5KSqH}PnP}YoL_{-yp?e0 z1nH9$?4+-1;qvolc{n1x$HV@kWufD3*suV&1O^ZA^+9ShMq-piOVL&qC9}Iyz>R}d zEj!tvO#Wgxuk9s2x6izSX_$psbxI>a>bvz+6GM6icp@?A3L%*LH!5E3 zeow?pK;yF_ZIZ27ps84Ku9w>H-I{NSOqIOecw#eF*TA3cCHre9VNbzV4fo_XcjRP` z-m_Ca0p4nhwTv34;$G_WRSFIOACoXU1IRu?ARi_CHyM9l3A1NuE!!*GG%H%FSCScT z6b(_eGr4r&=e8qlN+d@TbWiMYNLh)Pn{x!{> z61~gpJAe=8wFMQ(J{lk&%T*1{s-t!$X4!PIwNUu+5XZy{c+=Z$vv4RXRAOp`>( zj~z648Ui)zBsC}!d2VBv>k3TP-TZ++5td|uw_h%$e|E0__K#e8ibAN^U4qJ}bi?AY zhvg!yBCL4v!J}Dl?v>DR@{X2=^BOWSdbp%yaS8swk^GK(JtEJsmFNNR!I+4kfb8Q0 z@?{3v{{l0|vJW%$)qE_)2_;8>dMqP(%N~}z=98a8_igF~GE|0MXT@reYpk$Lyp|4q zaC$@6sBv?)KRJMyhhX*lF_1e{Y z`ej%?gwSHsE^DfMMP?wmI3U#ITN#ySFjmh91o)s9(m;Rwn*(}$53|G!TWE|gtdw55 zl_Lo*pk^b#jq5^&r_LJb3 z!GC@KJpQ#xIq81o=VEzFTgbw^;^EDQe6WV$wx}L~S@oy+ryw_hi61d_Q;Y=EtWD>S zcx!n1kwg>9Jb7)iMAr@eG0Px;kF*mXg!S|9-Ff!^ULH^aN1sT9t0UJQ;Tr7s3u8H0 zAa4ni0d(@SDg<;qlGf)SXtw53%eQ+B^0uq!hQpE~OWJ^$~^Isfn! z`vubVbA6=Q3u61F=&JL?Mt|fYDiFF$DV1lu3{NGMA_&0=PNZL}V|+|NvEUe>& z77pNnd7FxX%tQNcdOy{mL>LViiM0gaKWco2CcjX>DdpONguAuBW139*L_O<4!eZ7a z7VlZ~8*d0@N2}4qyiQT%yo0r~UKpe7oCS#YlSgCmV`nvQ4;NaYLKJq53-}XbznlE` z-#%VjFT5!GEfL=P4ki31rm3^|w9wGSAby;DT1X+4dDAvY(&>ztzXvDNT?5EG?Ems^ zNOG^_m823481_Q9;2JU{!BP6lteAJ_-NJF6+X^z}X+Fg*wh}h0(Gq`nFigUu zj_#W$MG3f@Ssa4{;txdpG|)cL$Df8C*_-6{^~*%%bQU23C{)QXHN|K;SyxG81fLdS4|I3Tv!)D6Vb zxUS%7^Ep(2UlMWZ%qsKC&@@x|O0b9M3QOJalAfF6!M4ITSuTqV3`hkTJ@m`o?OV=H zy@^zAC1%d}Emijv01y8oWIxC}!vFFnAK%|kJo?s~Ln`i4VI+w<*7-^JFEf3BG#!z;lKJt*`LEw$T49EiI?T-`{XBzl~+# zLR^L#t-h4oPQP{C;|5EV`m-@OetfKMlA_(k|6DU#HufYfunB?J(27ZI=KG^TJNh?w zc^ZI63!4i<+v~rV7P9~HSmMm(DVdPvV&#iY2oDVzNsX(@nadn>Cn~5`9CsUR*=;s!7aPZuYZPBo~$;cN;7?% z7-rSBW9t~azk9Xf&(VVUzou^g@EQ?N!Xt@r-H#2qG`R8JeNH<2h2gQS<0`}r1@Xdj z&wkpQu=-52=Q=UfpC~70R-uWP$dWiHUeZOu`z_VTFvt|glHZW zlkson5@?cNbK+h@U=uxKn2&_L##yUx8@!6=n=WWB&r#zkid3#U(o^L#{z(;wE7j34 zySoH&H1zM>`)AuM+=AZW-iF(Ov_qxEtCt;2M-m23H??auR>wVHA-8XLN zchMP-NFaIl*GC{m)YK*W1DALvmeg8D@$b9A#NKL49zl`*utL|{B|BH2P@7VFQ$YQji@B>*IrBDBil1QZN&nAn3!B0I+1p*@J|y zC4@62B>*04Z0Q}yqf_#~JnHMgY45N7=1*`wjL|vtlREQ~46?2>n%gn^?5W-k-zb~o z$8?{bhDBQ`7nRc^4>jgSP_>aK5<#96u@K2?grte z^Y1egZ9oqV)k+YIcIvo3A19o%x8wvfet_f2=VXq+4TQ>#N=d?0R?87Ne-Q4pDbgAW zH_8ON7t0mvdz=0XQQn-Vid1lo@n7FR@!=D;WMbWXOT8%-d@31pkJKUe|M>v6QgZ3{ zKgnJdBX&^Ebsb@uzyH>2ZWas%;bJg>^hkeUYf%95vBpm^Pt}?3g7~ubF`1ud->1dt#xt%X!2~!v9=CIM2({=uY_jc>kWdZKXuYgTmJjCr0 zMw%e-r(Dd`m+789s!2=C-Q%HkAJ~18zgQrt2k^jB<(oj}$^Mt;_oEl(ho0qSchK~R z6G40fO-O4Ojo!7xa8G|KVzeS>?t&);Hr9hgGH*U&j10sp9a1`fEWIh%ek9lTzIo$0 z|EBlP+Q}M=k##h#BK`gCgY7Fq-y_a@)hvO1B41-0!?hRQ^Mc|AeB!w|A)Wcx3QULV zE^u+=zZz7+$*#|nuzCtjzX zn3l6P!wv3>!~)-6b)pzTOjOp~W-l=;@&VyJE}KebY05ofze8 z&HDJS@1OWayl5lJ(sa#@Cw$%r9%UA`ng$i3mVJcJOwJ;G`ES-hD-XQ|m$xJ|m=sW- z@Zxhsb;85(dq=dmy?kIpL(lV}1>l42i=X_z`~JRhQT}gy4wHS$H~sQSHwbiWqX(7Y z8(4{Dd2P&U+goYSe0o#6eMv0laB_S!@-HkL7f}~1IcXxMpHwZ{eHz*|_UD6$bAky94UvYcR`<`>nJ@eUr!2aPe z&(~hp>XpIE1>nv4)xu@@pM3AkL_&mtIkDXrH8k*{-hm6?UJH2SEzk8L()u7$r2T$< zZ+|`Nf<{XSqYO#fwDroQ60-zHJggnWqjh`N1vXFazdVAvut4bE#cq1r?w+65mS{U!dg<++TchF;LR4>}2Qq|gWqqE_j`(~c`5i|VD`=>gq zKAf7G{$T$2R)bXV38pfJ!q)p5^_cFLcqY9akvNjRpa1iccvPa>v$ zuhr#hyw)hL5Cls9@=C}vApY;Xzt!0VXgg`FU#O8DIAHK>FoZl`5D4m3O}75|c55dk z%q1x{-(V`?1z5( zbG9>&R8ctEBcVKwI=S%7Fa+AEN1rZDehBH?(q5IY^=mb>=Zr)L9_#sp{P;^~(7B2+ z6bf%TLGd9l^}7DweSfP{;lJ^<_J$)&YOo_%OYcxJitVh@!NTOCHMqheWpS*uLA$$z zJ&Z~E#xeByNMOPI*j_mh_v4|rr9#1NvUGV7V}thn-}wIFeY)8=h-nmNYwRV7l=p7 z*N_V~Pw~Gz^U5NGQ*5}9nbv6H;t?qOz7!}`-E>^UwRe&@R*Z3^tw97_x0iID4IiGM zB);BIdW(V{mY}bpboBGK+lK~P7Qma$V^+u|fSg5b;jH-X(X780l6bB$E0_BVV)M^* zwbW0OPf@ny>Gr#B{QBJk7gQ%?b1oO(MZDp$p(43+K9Px^MN=huS!(Q|6zfmbtE@vJ z^8$9sXs>3U=N;c*lAn;C%j^Pc2x9kUt7SM z8w4T4mDMmXpRvCS7p8MN;0tt_$@-OaV7sxTt7HFyZ8P&?b@1Qx{%JbN-6X^U=Szs> zu@4-!-I2an;B;_a#o0h|V@GE^^5QD!Lw7t(7p~4~pE4_FkH4&Wlb!M;O3vuE{&Rr$ z=Doorh*#(x0LE6AzfI>RU@kWgZ>cY>vgerYdXdCrTCO8d?}Y3XK5o!ymP&8`^?(W# z--} zMF_{Z?$6%8-dU!CdGsx|*GUWxe?6;$D>^Mf>}?|;Kfc0Vl6z1lSe+DS$>tsT>tn#T zKnA-yE&dzdBDBY|r|Hij6WULx&Aoqd@pC26sABRYT96rG*FBUO+mhH%%GyK*v+48W z&TU?~>0BX0+7oF@q6sx|C;K7;KkPDxc-jk1iPf77Gx23{?cqOtYzbXLVK;u6KmW7S z(_ysA#ri5|12>|_Q<>H5xdGajls7SkUmeXzwrzrq6~BB3#rGsN9E^Kf|5m5%e|bqz z6+Ig+f>4LG=knJBv0Uw4qxvj486Tjdx;A7`R8zIfuxAy9Io#RxTnmm+Wt~3;8;@S+ z?BX!D?~e+cLHzHU!GF@LIMIS>CloQ1v&d`hea#WHt323NiQz2?gvP`#UyWwi7$tK*2%RT5mYXPpMJ zuVtTiVx*ZXe*40!@x}+9jL-HxwD7aw(CH^{V!Z~-@K$eU3m*PAV*jUYLF$Mgou6)u zUrG&BhE=dU_Hr>~95L;yY?H9~bBJFlaYDM1?(ofry04if6uIl0OZ(I~<0}!C*088X zSA9OOHbJ}{l_kpmJMVAXG6Lw9;ZNW%v$-T0x%_Y-j1<}%AebL!Y#eB@%eThJzeKBO z$!YUnt@rWM7W_p&0L3=(Rw`uii5e2lZ8~Ja**y{&@DlwhHx(j_%$PJ>WNH>o_vpIA zuG~c(2j${DK~MC@>hv@oQ@cjVx}neItLKE0!E@%NPw_xQulh+RJ;3nI>dWb0A0~mG zDcHVHK-;N}XSynf8Sa#1CWxxWnZwqtm727;@WX*PS(;|;^dlCfh*O;m#Fx^PkwF`m z=Oyc*>3K$G+PwG*d2$tlwa31I^4yrk{=jLrDa#T3)ka1zZbYmwEZ12K8O2VL;!nS9 zTQQxWW{IXEc~0!PaKix_#KR$KnfTykrF}z1f#b#P-WDjoxZ)NtrX>FVx}611tFA}9 zhcrz*)(=5(M!M$l>_R33XX@kHnT(h(YwnJ+!g9%8JB?rp?8$2w9#y$~%Db2niVNSC zr4D$fgGl@@@1OFtbsEo|VSvVhlq8QS9bw+M8}vTD2}G%xzBOQZjPE)fjtl-*J7N`G zm25S#mTsHc=g`iJ{FHbF$KU4569i?G;+Hfyc6=opS#QLSC#ssC zqSnWYXcvfzZ`P6bEgGd$^*|dHqL~v*X>!d}L_)1azkVujAK+8t$SE10V3sdZSrZfAX{21}H!9U~|2k^ny ze7=F4y$K2a(kcV7=;V(UeS{PN3e?e4v_yvhQzZLGeSF_?Ga>bXdn^ zg!D~ZOuoH=-Rmd_&b9bNuOh2pyi;}ohR6z~zH`snx_8}75;+Ovfp>AdfwXn8DgWzw z{?op|yq`17rjvegxIbU!=z|6Q#xjX#VpN{^%%p=kP}Dv24(bHkiuKC%;U_^+|E+zNrVQ2-v zk%h@U`Wi)f-2@4Ls`sWo(i4v8fTk+?COEe)pp+bfann>S<6tahojE)i{4jFkz>#d9Y>;y^4Ht;^)R>3V?y@YFMju_G%Y2cDslTz@p@(4g?{!%!@xN3#|zK0H&Q(R zg$F246AepL2Zf^9;S5ze_PxSq=I+T_cnHkl5u)O(kGy{70p!Co35F3mRXdtqNW*5ERDx;bq)_>2dLl80SKp2A^-)BI4UrW$V#!9sCun`2PXW!wPR6z_L6Z5ys6_yAN7aVPI{^Of^X1Ikyk96pxy`GLDjmpHS&1aipT)J*}m-Xn0Q0wAigqy|LqM7&MU!bj`J@(B% z^bD9KQJq+E+UWtPp5 z*EY^!_03u}c=WYI6i6ths}QwkcfEh#)N~2!dLuEM+#iDSid{oNp!u5aDagkIq3{)K z-xq+dL2yHj#6yJ^PH!tN9!3;LG#k@tI&3pE$;3w29`{2)B}3VVNV&*)tlPsYI_EHi z_yEG62NezQ%As+db$&(&0H4EY!?CXBK6RH;bj{#V?9`x^0%qO@kvAd+=&$N;@&sqT zfG=+9sg(2CVb>KwrTu^tl2TlwfK%D#(Z5TJZ*KUkAX~h(_SUbzVbAZMb5$ z)okYN;-<7B7>C(=#jM;ST=0T;p&&W3b}@KI2jO{p!}|uq9MOHIhTaziKRv&gv`2dw z{_Fc^?B3(J9ASyw$2g3uudltIT3{f~f|Ce?I3aoG@Mk%C_y(m}F~DTyst7rh)F2hx zs2eeWJu2#s_f4dHo8*Ig`7@9Y8CDaFC8NL1i`{>l7q0Fts;J?T(LG_)yG1^ffljN~ z3mA-L^hj;nY;gyEZ!8$YvkZc;;W9~a&8}RJZCwfot{wjOuFrCJs=UW=gMY(rCm=o#UDkP&WTAppFRp3B_2cy$?ezM2Zra_Y*;pYX z1X{(A&@`%f^*$Eu1rrC++|Z+M7x_L!Bv{jFd2PqCo`%31FwIyreXFRZmQYU2yQ{7% zdEiiedQIV>ksh!Jaj(={-S(u25RjjCGX|H1`g)@ebPg$cu22`mbW-qh!+~w~>!3eh zzhD_5T!GX>mq5aavT#8LKdW_y0`V%U^jht^imjv-i9JkEe#{t$ZeaiY`T+S6z7V=Q z=6;F6qp9=~fhY8*wMC!9cuIVn;V2@q;J{*Hi_J8|w+(|lgD%-qOC=4Xx-(p(tl-T% z31(iq{mB0R%?$oipRbZ{*^Z-DSs`qS&Px-+0Wg$Nd#@nv>Dgpf>W(GX14KIFMK z_MRiku(PPECZ@g3rX+bv4F&(HPMD}s;aH+stb0DM16R_n(sGPbz*zspZ(4r32H1QW zOig7$aa(=7Dn82pC^wbmwD-*yONxVW_Pe3QqtB1H#)@HIs7}OwA+$aE4f1e_^aLdEYT!N?kj_VYcICQf+YE5=s0kQ;=HPTdlxr+1TjLl^E_VRpnI-|)#>Fs?xPJ9=LS%)X#6 zTU+~-(jcJ5@C=qMB9aicEK^NvkcjKiE2Jz9BWVS0HcCm*M_Z-sRWa}2uOnBA&1rm2 zLl7^E&FRuGr4a$-cg}pbzxEWX%D$0PRQ>2IP|!oC0E##`EWS7W&*WJ=xp*4~UPbCJ zUaNYgcnV`NO%J65tMkBo99So5)~8M5q#z${fFt;4_GLTjCE&M~zwtdXg|3-<~4=MU3CR zM4Li=swH*fbDCXWGJB50_g}JFJ;FuAB*e%fdbupWyvn!%K8n*<{l^)7>KhUnMWy$4 zzS4oHd8g2L97%g}e2=~f;zDOlX$MVT^%jf^#)Xn{SnapC)E_%GNIg|)#$|MI=s`XP zWPcQ}eG32|de^%0(0VfmEFKITbMWuyqEIBNmPqS2;lq0^f306ik_{!A4@X_79fvpC z&VP4mLwB_sAJ{vBo+#n^A!+3f9Nkt-4}ayKlB2Euaadt37tZ<-ZvE7&U<=-%!+Gn` zS3Wibt%e`S%*&zd12Z7xMS@$GB3)_F_~BMZ zA_QafvkZ>bYx$3j_iTtC)=fO}X~kd#p*Qz9KS;AIBW4#G2)k{jNa{GR()&Iq$VObe zhnaZl##JX;0lY$LCyGrcjchNXCy^>h!czCP)rogYt(pRY6rU^n(I?wp(lg}9g!Hk} z6V1&0_pyc!?+X{73x+5HJXxp@EFEsoK|bEVbmryw)E#2qi<~vNu-YKAU?BTNfp~ce2~t*=Pcbt7mxf2s87Py z1X-1g6!z~aZ67n+<}5OPws-af_wK|X(bzot=B#DqCpWyJyVVZIr40^0`-_`bjAMDGaybsCBKiS! z+77iupM;ElrAvLK4STt;p)b&uhLNyl-;Rmh!RPzK~(eTp*vp zMK1XLmp#Duq08L5tMdfZfQ1Ts*zv2wgat(G^dm#sE2{0>kL&1Shv{Qjx`;F5{maiVSx%D{S0GxQ zg+wO|tUM5mSQP>JrHsCo{ZWhWto+2>-q;oz0<%?j%*UZE@42~4++%&7Vq$qG5R%wk zN^8!A@IcSwW!@v7Zd2L+YSQYwu_0_H;05_qzp;XUN7ex#Kl%4oof<>ir`6W`$t6v5_3sKZ42Q0 zrC?k6LJommJz7C$-$xWtCIbR@HdjtD!J3v z#7O7SC^afws5_G37L45k6Zu@fEc|u#64JPf(pGm!nOD0o$OpF;JOj252jHWcZ`hO$ zuH>xPqrWRn^m`RvI80j8jxd#z!Bdg}{f^xGdGuZ4s0?4jNZ*U`OP`W#M75|81Kbg| zhi|$S#yr3mNIJEP^6;7>%CpbA>3Y?b-u|kSAmGAT@d+ML4t~t9=}k5+_MvV`&6rpZ z1bJ0T9rfkuc+UxWuA1hILOioV+AENc62dJEY#%b}ZZbSaZYq@ynWHC}f3H-S3YeUS(swVblL?hC*3To)Ce(2s$y#e(p)JDV- z_DOKyw!@EBN@1!<%rx575cQi@$2tGYM<4o29jvTP6-80n2*X-g2bQq8Q^*T6&l8rd zZD+RhLs)JJkgxTo9Q@VID8PY(P|u# zFBvv}&w9CVK_3>38!g($;+FBmrWh}TMDM06tbQre72tcZJlcZu%EOpea~2V;M% z_?y;c3kXy0B{8u_p9B+QcHTl;qK5<$!%AHAvyM0W^6^?J!H_gH+ihfz{M&X>}$>!kH!tB!beUn5O{i% zTNj`!JVgyqGX7=kw7!drUC=07-4YQ2@NvaMJ_zGLRzGR4+p64;=^TbZd7bF!Eo`k% zp!?|CdG8h;`m(9-xsM?+BR+*A(($J&3Sp}0Pb`h)EjszuRZ^h*o~+`RfbAmz_>_sH zBDa&$@jb?zI1rZt@QT^SzI4*#896A_Dfk%8W6T^6y57CR`F){m_E$8_gAvyihwZ`d z&8ODd?Qmmp|DPS@|9s!co)|%fnN7hsoUzrG&n5BoC!9bZ#|epNqg32H`f#Tygl1?D zzNSrL<}}3bHpNk`h?3Z73Wh4rM)s!1yw80D^4&zvg0Z^tw|`v=@QsMCupjIqR?%`Z ze1vkAKv5AD6>LdKA{*?clxNB7IH{yu7MrGCj`bC*p9trVq$n&h{MxJQsEAqF1f!K; z4SeB!SEk{$$;l!a!}M4jw@d2?cI}ivfQqkm!rC>$qpzW~m7~sQf7AG&4?|*)SxlZz z!x^%WYW7HQJuZSQNzF$ZY> zD*8m7x3T8CgtBO^y{qvTzbMIVKVR6$;CA0_Whs>m|5EO2{c(5$s87zI`0C*UPQq@< z#&bE4ulB43{10lp8n`OG=DDhc7}kMA7G2V4 zbHZfx--7~WxAb#93X`DS{+eJ*I!Tbt$6KhlQ8ZLK2LxBw~|7R5zzrJ^@`)ERWso)&I zcZYsx3vr}Uc`Hmilo^IXELUay>b zwqr`@CTMy+t72?ck<40?E@DkljLQB8H?icXhC@VycKp#&5x~cY83WxVqivu&pKKkC ze<A>B6uZY^iY9hT;)WAfNU+E}>6WMewf6uTqM%PDpBi zeDs2OHelx`2=INiOxNJ28pdw)-OBVHjB3H5gSLr{DE86sif7E;)RCZ1Kk#+x5r+yl z->%K{R2$1vRJ1@mpPKoUL-DDf_viz__ns{@gHx*()+)zazhYBS_&Hw!cZtGBRSvY1VqLfb(~)=Iv_U=?_(<@_e?kBs+_KTU zO7pTGG~T zQ{NpVZ1bcOD0^aaZ0Z{g6HJS?5|r+G(uql~|=EoWaUK$t;2g6^Q~y$9X_{XXUU zp2Yc3O;1Jc#0v!`J^92h)Jr-?!JLgvq>sM6@+dvHVe)!baV`z@)tzyx?0?c|=i|myjvXE?k?zCs+?Yj5BN|YH2fHh)Mylo@AKh*; z4%j|LfbW%L#8$DAGWQ_F*!svWeBm&Wq4U?Zd`CO&QY9NKq-JI6&pG8UkPfcZHB6HV zq}55O$9~Lp=TrL#Ee!3QJ~ao_C;1O~BSQ-r&gs@9sKyZqA*U{yY_!bV;+8HQ?#KK* z8_DL$IEcOTOb!jiueagn=|5oMo|IzAL7bqIrZeVdh%rEhD?X|G(J9L$H0oJFaWrED@R;XHvhv=Y7%$<#p>cQCsR( zsc#itu4Uh@^R0Gv_(y%JfhX39SV|sYez&&9XGGb$ zLgg6;zgF{Q0`)nyRjpK><;g@{{aJq?ETa^|r`5sIx=>Fkg#U?JaU1AM-`Ze59B9y; z`!kLZ#R23yPMrgPeyIbHAFKVGGn?8ERWnsIU2ZkA#sJk5A!$y-xO$1;Q%1>SX?(&B}tf+wN2g}z%@K{N>$7MY~{J-#xExz`TiZB z7?ST9@;sWT@K>u2c@^Bn|6SAb&-lnPj-BCUeHfMf4pkS0Fb9PgqlpXY+XLLPYYg&7 zUmzEY%*<2X*_uSM{K0R#&>wXYQYX1^2w|h3T2xk-i=N_wOUu9*;g~S(s!z>B~k=+)Pn! zYqqPXeTDlAD{t(A3VL?oCF_)5ZlL@iUj~73qWJIlPZ!{OAsl{j;qi$uIgjx@yKIry zP4*lGRM%={8l`J~ZXO4gG@-a8=K2R&->PB`Tg>8;UAW$OQlLTz zDSEOry9^qoT-`yw1yyP=w)gz?g#p%Ao_swE`mLs8d{HfQ*51MwumB%twOhf>E_FkX_4alE zTgu)uugeVLb7_uG1?cOKKGX1`w2jwZ@|IFUUr~lTDeS+09QW%cr;+5IxizX(=3Ddt z`KXwL9Ko(neL#M7H+rHiMC=IN~wXWhk4 zIg*JS(dSA0?8*h*g`(}I+Y@Y$Zw?)v| zDTla;ayK!rL`=QDczr3={q)V#DU}T)^5~0GY@4{w!fk#5Vg@oLLh{#HRrgn8_OIiv zu`<<87S55>{^$E=``MhZl5VQ!JCpDppP+*jf5y(TTPZ^oqxZFI-`F1WYMgp3?~2p7 z-rASi!=DC4nw13jpy7UM8KqnH2gS!FJ_-Kk-4GC84;Q~~G3+sZ?3d9(40oCEL})KI zleKBF@BNHkQY%^c5^ZR|PVa-&k|*MW$|dffD?&89^kV-#DQd$%qD~h9?4G%#L_@K& zUD|GoMq)a63kxEYc%4vv`H4`}5dGuPSIS;sA|h7POH3H^rIYVgsPVe}M&|QUbe*0c z3wdKRQC%R&N6KZc0(N=Y1AHN<1dCRu^z11Igpg6juV?yWt9bU>&9E;9IUew2tCZ200NTAkv$I4kJQIF=@iv*q#b_vRzO-w(&OU!Hc*y=^s2K@D06H#|l_OPT$}d zY@ZXrm#|M!niY3turRlK+6YtJmwG0ur3%ZhkMdO*GcoOK~Vu(UR8ZNVfdR?`-Mg z2dFE5@{YzL-E?0KKl$uJ=MX!#rL?6j$fJ*#r~(lnAJw-=@V6Iu1AJa6kUx|7&igNz zg7CV%V++FiWb>fsy_vGP=?xs-Y%d6It4QLnCM(jM!LNRDzMZ#ddO1gtatk@1`ruF- z#|Ug*^mr+doR7CF5SV;uxoFwKX|=_zl)iMd5n&)GKIZosU2BM}z(ncpq3F3!WyEHX zbAIuizg!%ZaK~qz-4(r!sK5U|FAp$=e}9`7zyop6L${3Afj?31%*dF=NwIfE1_qP?;>%diNiBKH z^+4@d#2f}K)YkXlR>67RvvhJh5%kE*&mm^Z=3VWavMn;PHYNYnFxSA~1;Lu&KH3W5 z{VNbjAqK>IV$s(Pc6o*X;#(ast8%b^kdpW)6_<>!f{VMtIymv<$$@+U|1Fa{X{g%o zGvMxe_fsySt~WP55OSZ;Yo0|j4Zf~5g1r}_@tOko@DMh}2A$ORo23}#qy4R-M{49b zex%!N=uPd7Jo=nRSsRBw%1Bn^`%y`g?H0sam-n;TuARq5vl3g>o((^Z1^Ec=!oc`C z{O!Hq1A5mVaTJ;PE3f<5%jT+M?z74u@6WUX;=+#=+eZBY_?%|TgFm{j_oq0l#xbiL*&1ip66DA?hFBK9__I4Q z-1&&Vua?&|DF=t~6=N4WQHvbodK88Ce$N3^9AEq*-+Pdcl3B(M?EJz2`H5Ldg=}Qp z%x<5zhdPfZ{9I6#6BNbnqk)o*k$p#xePj?ry+z@Q#57tC>ppk1Y4YM7*4L38h87~! z-SqvBXJY_gkZ2MDvLEHUBsj-C$`vb=UQdifrKvJ9e`C%+C#T;AVKH>@M3Y_#GwM=U z(owA`4m}IQGR1y?6=6tXAi{)A0{Qr&y};kS8wv204%9H5W5`R?OdA9TjO_SwNL=$( zWK>XUyMGI5Ox*EKuVANz5_yS)D=ve$k>_w?YZ9;+U~?;!1>xiWiY>nn;Nz*fOq)z{ ztt^vHb#1L^9_UbexiHELD;uKf@#kz@=Eyzi53Q;v4kYwz7G!WnDi)-r2^VKOI&fs% z`ioG9cgY~%E2&8EN4L`e-zgNun<`(P4t#aI0T=qvqu}Y(QqnrpvhNXU+xG1*ciq=u zn><2VPKtZA711X`i=>S*Nak;O{G24ecyv$j7vSs|a>| z#sGX}C~wHDsB6tmq|yk}A|*Pi6|LO#NmzvHrk2ilLSqxWm|zORVWpAmbu7ZMMbM&| z@iGL9VU(=sIm;^7AU|LLe5(_8lhUtoBu(LiQnj>OdTbHVrFuP?1|j_z{#-kufo^sl zS%T(2jB%*B_AF{gYsI+FR7^34DXfwrnx5&DA`|4pt#v8}+m{OPt!3%H>NpAyF?#u> zXv_}V`y;WEMHG&@PPvNO#N>{4C)2lEABRTf3Bh!+4qp*hs}>D1#>IF2xvl8h$n4@e zWdHj9>0OJrRkyn?m5KL=I(%mcueg zTOVdHEHS4@%NeGn=YV*$6paI5$CnO>Z!i=m#Z8cNj`jT0XiUmC+t$%e>~o|2XLi2s ze4+u%Jn59ecJ++cD2yTw@MvF;mS#+%$34G&?>9~wK(S92bq4ql$``wnsD;)w+U}U+ ziR(3Hp1V%+Q3}dD^j0@L`e23m0{WSRS}pK9pC{|S!eWL8Si7{`yL$6_Wo#J$DetGlVHfM}uFzim6(!2k*4@58RA=xdf( zn}|2_wXyz0(uinZIzQJ`OBs=73kA6O(@wt|s(Or#Y?4-i2q*izlH@btohYv2cP_q? zpN~HGMGwW|`M{@SaK=ww7iCw$*-Rjp4+=SXQm}5vga8l^GRVnY^-RmfwD3(9GAp+!I88 zz4R0=;&~=}#CkEv2mb~V{Kda~fGxMC64})Z%PT& zgzs+Ng{4uT1=}unZ)LC^*ONV52M7yy(9+BhwO;))Q}6@$N;k>8&j$O0ec-Qza7wba zu4qa#6+Bft-Q3ZQAAQ#}1;LQZSScl5ki1(nngkWENm6j8IiAk==`wsSdi(lE8OTSr zvBCv*ew6@UV54Z}&M-xEl}2MGg0~(=l5Vih(s(^AZH~NteE2?@VIt&f_7HxSf={-} z7CM&swlU{E(WiVD$XUT|O~^*T&mTV2(k#pte`<0)u4T1&@OU4xD|_O^YG*i0=AR4e z%qGlyKff$A>xr1g%w`d_s1OsgrDc!t<&xacm&k3Vl=}qoVeM0CfbFXR_^zX96tXgM z?)|CRZl~OJ@AJ|bpYS+j~Q#9qZygC_b;p+FwxbHh(rX4 zCA%=0c|J)Mu9jZX@Zr5%(elRf z(AwQ>_e6_PK{j>!VXxGD`drAN5Ao6G%Noj(--7%rylk7>Ac0mb#L$Pj-?a^qy~>#Gwxtz8|xfF9h8!o+;Hb21Ah=#A|a%RAh1a5w*=6w|}R;^mrw{S9vHb)J8k5S_9 z+*6LI-nKFE=xf8q!Wx56XLoCQjii0)M$>-v!?N!1Oy`GlHuJ`qMioLM$j9c*0sad> z4FF%u3yJEsbm;OI`@Mx<4L0ItD8wqD8r}@F;EYyVM*4HVOEA7i7f0y4ShlFcZRi%R zHQtpORsW7c%|>4WGo=|1$nVrcoIbvuD7og28$zBTVs`;|kNFxpVEUXaH|^24kUjIk zOj7Xyb4|nWmwAAssDd*Zl!5XEqCi{+v@@rURx`-QZgK?1eV>1ax4_LI@B4?o3tT1l z`FDPnd(q3)g|mkCVvT2QbH9}HrDI;yj=p3_k@Bx!T^1%5J4Cwry*9j*#wUWe6qeXoSX&)u&Xb9)!Vw=3;$ zF?zb?vRHU&9nVb@VAlBFA5eCJd}OQX;BVgT2IOb1L7}{iAgpsDEoinC#7HK- zD{s@|J6$uudqEv!^QwyfT+A-!3l_q%s6l$rm~I)INUq>82m7qi)5}(Xukc)e)FCWv zRx3phdi#r0mR>{rS$0vIGfY2>#-lHtvHuo7D3y%0@6-3p;CkJS&!tZ@Lc-M^w2VIY zD#xzl^!@ckl1_mA|LX(zb_ZKXg^85~Wg4)hVpK89mkz|g++c_yw;N6|vk*c@QwCyk zr>!Iz3b!TYJivJgIf$6+2x)R1Ogw#!+;i0&2=ILqVxFvLN>shZ8(u@a|3L{c-7#4w z+5MxqaWUu7_q147P6w z;7hj{Bbw?F5X#3c?Ihm1R8PX+EaF(*dfJsGL4!8FY~u)RKt57;G#{{iz~OsKNjitq>Vk&b&uxnJ z$}AV-P>!!WaAw-pI5N2~XK-JQD!ycNI^jWmX0IL!r)1K=p3ZvpJ@S;MX>3Knzi0?} z_*VOkyzetprz_06PWEtvSQgq5WEgD)6ZQs;D0?e-3)rA%&V= zL7{dhh;_d`ie`AdKQJaP_~=U^Ll$d`z*dKMR}(6byiU8%tI}`SZvPozejv$c#`h{< z4&-D1OacDprA>fuy!E8cAwt8>(p}Xe)s4mOtp-nWOmZVKvCmAV_N}s3TJYpZC&>hx3DQRO~qpJ^tTdXkF&@8yyu8;2G~-& zsfrE+h{7SP3tinuwFCuQ`$v*%o|DHG3od|sTL}y>VAp3EU~xKW#V<0TxrM~+Ypci| zMaB<@+t7$R=r4!wUxy`6yX*`QFw?;X2;6yEV=``}4N)Ln?IYr*DE)ZnKk*TN?qC23 z;Jcj6cd~7)r&j1ivLRYircz1!8q(jxGD%~9^=EZu{qTznPTTPPqTT~VWqk3fssr3b zCqp!|xZsUj=Ah_!?k|uJ8}ls~&&d4!zC%O(cmC!2J*FBJmv8gPHdNmG$nemCg8^u_ z^S$QGJc(AionH)C?(P&a6cWnFnuNmbue?}oF6{um5Nk9(T`iJ!7ymY%B%I2f<;Yhy zR0k_l73GzGUWk*8;Z`@w%e%fmvA!K+b*ue3(qAO_{=32c3Nwf7OX!~Ej#=oTTn3r`LS_=Aecnteh zeU6btB{XJAhRO$C4vNr8vS&sOayY}tU*ES5XC%DZ1o`*~+O)v-!2*0X@>4tmdT6L^ zvoQxOmS#IdR~l{kjfv)74C$%c$H_L=4z0k4MAx;8_@vu&VpZ571KZ~~|8NJcAa zG+vMbeD~7%Ul2vxz8I*AN)PRn#KqZWGAK3g*|IgxmDCi3)G)6W`; z4K<71eh_3)dkSXWq96olQ@AiHUo(!k?1kM?=Mk7)5O*&iOeFawN=A4w&3rsxdJbKZ< z5CcD*sURuv1#b3*vr?Pp+%F4fDFQ{mu!hyqdVnv>lfhbBkF`_3X@`;`T;uY|gOH&R z`p#(pQt0)guY@v9V5mm25kb7N9ReO-3C;@Y|OY zK>Ol?N7c%qJ3+3P+H;4)G+Vn5ud5KC=(Lx6mhUfF zioZa2UA-vUe6sd~Vw2t<;9KpDmmmA^f$D`+niem0Tek!y%P%)E_a`%77XK`-99|rk zHMA>Ae)Bq7L*|4!j#+=^$yT{0mG%4hT2)zCAKo#@2V+}90(O3gfczY0HI51w%=O}O zwqoIXR7rxaUWK5&9#xJ}vEbm!j~;|SbW*3%yAj82^>bWJF~cyus;R>jL^66R3DcnU zRS4LA_H&QGq-2xQKqNY8eEvf6CK~N*)q&*Tm`rm*mYvzYmRFx03tG zZiFw1&}P?Sp5k!L8U0YIIRW`_c!<2f_MrlNvdYpOZ2235Td`CZFQL`t^Lfp*9H5Gw z>uW{U{kL03Vy5rRa%h81{i1wH+r6WxBe1yxiwqCSx{{a*fu#U)Hi zt=lt@PpfGd{LP;Nfc7P!KZT7r;rS+u(;i=C{?eX%U>a=Y$i=&rA%zB^qah)JP{|%Nl_W`tJOumq^Ab9FVTiiWVC0~3wYY$$Wv6yPn9z%Mg(y+ zuiXsAj~;zzV>vb}N21Ga!lv&;+Rn41P_xhDa3P;cguJ$Zae-Nsy8`(bhAsrb&JPQa zpOD58{#)2riW8mzq}FCyZ9nVfUQ;-a(Xlg7p>o6OHiJN1P{i)G<- zE&XtR^`>%>h3ux6@eGh(A(|6X3^F4`R*eMZESqudlC_Zd=jD*)Wr^88^ApBCm{W}&A@u1SQjoWZ(MkSTkMC&n$FJ}JX^piSFa;Y z#eca{5!h2>)~hjQ0=4nyZbj_<#&xiLBmke1%Ehi7c9Xk>%w78xF{~$gc~-u`G8VF_ z@;U8S*;u-WMO>b!o+V>9@rc+(%yc(+m@ zZe1|h=Fi_P#0M-~MV7``|G8Rt(jV28bM|#MdlW3a-|&kMT=3bah?v;Dfg{p6MGBRd zp-(_QR+Te(uzjQeU;Xn8$AI4t&0}B|XLIz8_aoMc>f`I}qcy>;@~xBn^4w29;SILb z>L=6qYEw8YTZECIio{${g~A-FwzAL?z69`bZ5;BXy~RrToZH2v4dsbEgGtfWVn5B9 z`#s{%_(&^rVekvD@e$j-oEiM>qI#g4;rM`pgt~btWZ!KK0ev$Z$QSaU3I5^6OThO} z{=UAlke#roDtIJ&GKij&`1~cq`^@(0+O8MaL1%~irBv*0;p{V4=`SFOEt_M49HAO- z`R#V)TtW^HYiKUR0luKQw;hWI<^*u-gfD|n>5lh{^N)16(O$C4QQ<$0-9}MBi-mos@L!!AJWle> z@~w~M9hT&4nhsXg^P}8oq<*R1`ycm&^mhE?3sO6+jlp#6MV+0$r{#TMg?HbxO=koF zd~x-OUT@A+_7nRud_VYH#237cOQZGGyI&VOseAP0XF;U$Kg#YhsOqf&7dRo^-QC??(uhcRh;%p7 zohscSoq}|CBi-Gh(jeX76}O)E&e?PCob3$XbjBagTI;`h@t4{UJ*c4b){MWYESNC9 zne?CwL8~LwZMI?O;!`Q1tilKp4#51V)#^zpBW_n@x#b%rEsm<&ZGanxzzyW9b|xeY zm|Aq8@^!|IePxfkv@qz2&q~xmSgrm0`%u3z6GbIP-1Sai@d9Ne49%;u_QuTPm82VI z@V8WS_^;p406qxvJ!6o4TtGf5nV?M_wo2sA*Do?U4(a<%YS`^2DGek94imMUY_3ZS zmb-0-&n+bu&0?QwC-J}-{>dx)fKPjmRs#_3HDpM2XN zPL&qnH!gUvZh6TlVr5G*UU+3Y{{X!QzJPBvHtsV8wb%3!*6BG`)uwA>^)j9 zu^>2JWr#!nYP$kY_*1HL`h^JqK5!V+5|DiYKt5J-+LLzVLasm;NT;^(_AXOL3N86$ zf^;jK=|%G#SmK|hTzhY`dhsmzhOa+V>xE&gxaqZGVp(V>Ql@Tr+VBD8r-9przh3Hs z%)0=)rt(!hhmJY5)M*_fxP9H6_bI>3XZ2qxsVPYq(MDw!8-xS)Y3?Wqm44DcjAqDN znOC*fkpO&z5yxyG`^15K(29cdI^ZQpfA z)oiTjYvuOjQ}k@9noIDcdac~9I^im7qgG|=PHsU?P!jT5{y4^n6^abtn@Y|Heg0Dx zsDGV;7@csApJ#-?FTYNCUnj7@!TFr95GDtfh67DbX&D`b_S3f zVg^yfz>8X{DYma^m?Pj@$zFZvCjx$%t{n}RNlw8oa)8h8tvCFC&+pInEX;pT4;qgt z5X4F^`R!H&#(VPB9=<8)S{>gghpo+rS;_+Y>R`zJQe*4kL?9qu-(sll-l5u}rW)>ZQCp751+s=_cL-vueJhzc564aH=H zW;^iNBV0p+*qzx3GX3B$3lKWFi+OVI?MlD7Zs;+VYCIKBac{)HJ@UdRuDKmcUnFH` z*bg`OL=*GO$%%$|$ZtDHKhgkvXK&j;c(m%z^zIj+>1(y)X==mkJ>{GBW#h=^>9$^n z5c_WWrO-z12+n#99xnNS+S=*S`Kjz+bhb$`R2zth7^~~rSo>!PfhkK9cPBvkdAhS7 zy+1A3k`1#<(iG8TtW+6?!KqBvv)E)Uc=AQvN{-+oLf~Jex@K7@*c#rb@R>$-o%QvG z@9Ha0B$oO8@liK^zyI&W^N&voD8DasZ&2?qCX<8MnVCd>-7)`l_S)2em`tVF9z3eW zmMM(OJsWz9V`0AlEAjKr8D6?K^@`go+>y?}(0tBplV`xwFS>Tsg{RRT^Vyjrg1kxE ztXHQOFsts>%ciNvzke6Httpteqhpc zz-d>2?2`ua(Xw5V(SNn~`3!&Bh;?%{Iq?ZrA*CrZ;Bj?c;Qd)uVUl|V>&JP;z}IJN zL5E;|rhIeQFj&4V7Cb3EN5qtYz=t1F*is=nO@g&r6=WQ6?(J+2!0tbp-(z6Yo0yS5 z<=3O{GyfTSaFEFBqNmGTdhrDHeLPC@JE15fh7px5Jkt;cfRCr>CkV?cf0`G(e>X33 z*b$^0EjFR4#Y^m#FvUM?D>Lr7Szq%t+I~Z6I3`YW^KyxcPjMDG-ma~t8-Zugs2a}? zonsW=WY;acCPjb#Px1WQdKQdIXt5nWdxL6kB7kb@r{;P%ekAF#UDx;XQ^ymJN#$Mo z7YfVQIJ%`NTMD*=-36CK3Q~S}EIcd$D*B3Ow~PSZ3qcpqd5Hh!K~Q>9^seRnm;n38 zSht!DC&12+TohABgdMh)B%bIa_bAOgu|29^RI#^eB$e8suY_umHuDn*3>bl?=l}CxsTq~u| z;>ij3LJZ=@VpeE67b-it$~h$mLtDl# z3mN5jC!BXVwU-LlBC3EfezoNi4jk|8g-A*RzS(Vfx06*D)6ijgimAV2&UZ#+Tv z$pZPzz03J|=uZ5m@VC*di5o~!DA|am>=h&>`M!sw>M3@@n6ha4rSxv-Vl?9WLs;Q& z(FZLu4KPDA<;i@-E};grh&OFD3xCUJT?3lIH!Z@~H+U|sOsSI63A;vh^XsOL%5+(a7Th^(!913+vOP+!+>x$N5e`c2)w&wzZX8{D4U0d)FN+`&vL!To%5C5kI?+Pu8;r`BJdd<`#EX}w%bRy6~8 z(M+X6N?>Wq=&V=9AfCB3vuh8%xKt7Z_#ig-K)-oc7s!{l*V>ypH^o}1CVoDGi#iL* znyOY^`y&c(1sXjidIqw=+~8iw%B=)5pN9gyObr3fkk|Vf#%y4mS$p-kI`cD-FM<|r zUCq{5iS0dSHAh&db;l?)LwJD*-uK#PzZV}8wAT&`zg9Neb6nnR%;aLSPIJI9Of$Te zqoeGOf0={YC<5@|1zmtXcrXU?C6M|l>q?6k1|g-H7sRZH5pNvG3dVnn$kzC7E--24 z&+NM9p3UW8wcVZm7_$);eeaNTwWlOC1$*8*{764u3gk;F;}g(&*WoF{_gx4PoAxm| zL+rL$^Aqv7$Lr#!{1R)CgvRnzFVm*(xy3&rQ!~#hQ&cEXyxLx_v7^?L3x=rwCuz@!J zOO}vKtjUTBy1?9C7SS#X*h%mI9wzzQzJ$18^LKn{^JB9N=;6Q{NciE2!UoW4qb3IjODtQOK$ewr8Taz{H3yz@$*By@b22mfCUJdip(5zei3&U&v;8l7`@pdVIk40cS1Z1Bzkk6oh)~K$~*Lh{28MDFs zz*p+|2~Y6#bH{lB44K##LH?t;P%$z`op^D}V^k zaO^KhtFSA@-H(XhjPvBP(ue;vE(DWvK(rF0<&E%onBv2qM0j4gxJ=lQET&?+BM0zd z4aUQQ>~jP1-E_F%R~BA6-e9W@s_Mm)WYStv1#B_5KZ6BpHq^^$mumje&`Go!Iye<4V>d^mTkUosdG<&jiFOvgDHWr0K43 zFrE)qD!`l1LVFt+qUKg)Nc1t#;4#LJ@NdUa^S>mrw6X5Ke)0tzVKUd}$GEu7$QZ{q zZI|nzY!Bj5Tf{)TlakI2x_<7b2JrEA4SfVTzd#^gZZl1pDUxapPJLScySDol9|*_# zEGT_vJ7t?5;rP8i%!{C8Sqb}~>hAgS5X!bvjnAC#tK?riC-C>}eC0t1e0b#z$3qbR z<)z@mI;Wbc0lLg3j!%DMQBJ^cNFT+M52{*W=%yW-j=eI{uy_l(DvHp1%=y-!b&ETj zdKFUi9kMpS$NZDj17zPjARl;Kf5GfQ8ebP&KVeN+Y>{5$+heCs@G)l<+}rQ&u6)0axL z_k)bjjmOllu;%dHlkc5m6fEX&<#LTKPgTnFw<%{Rr~|3Yd5r1^>!tmd4qCH%0AIeg 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

      ?<0p%BS(>t7` zqNzYHAhW%xE%J~a-SAbg2_fZF6;|xg_cG+taKoC<3&(8dyN+U_z%uW2<5g+#zUaHu zU1+Fb@Yg>8KJb94HIRLyK=~c6d6q>?t>Z&js+mc|qDRd4fZs22>7A!8dLp8bLR*XZ zDZ}2R{{Cckqdc(fy*$AFf z&}-lFcdyS&OCEhlAKc3K*uO$s`K*rDzb0k43NlZJ`10R5VG86iBm>i7k%Wgy1)jQbf|xXR;cg30^|pS^uiA0{HB2Nt6#FQnr_J2 zm&bnQx1G<$c<_P^5q?j^+)3XhZS77LIr}3^mD=fLJ(Jj$K3Os~R?DHnk01$WqHnY^ zLr4eo#6Z47xQe1)3>f)V1eaY;`XP4D6EyDZuy&EA3tZgC{AQRB*dxf5&@Ur|^hnjV zm$n%>;)0Xkib*UL85;dmiVOMm=l(K`1$u?3XF&NelVrAz9~srUyl_;A{hkhY`W08H z13RAKWz&S#+Hzb<)G{je1zP)^$StIe^3ri;zcdq+yRJf(yrN)mW8kH+Y*k#pV&i>D>yo!UE41!y%IW&`y4VRi;_WM>f`$BzDIX=m9k zjv~j_ly?9hg!h6!$oZ`T>}ljSzg(Dwn3J)w7?a9 zVX~FDhiVHd;RNOBzD~}h#*hzI*c-Z{Rh##o1;Eo6WF*LBBbt-8r3WWQuPVvJHg}e9 z$eWk@K5HcHkNH_{ew51T2pk;AM2 zls`fC?Ev}eoq|!?4Jc+z3mi}mWRd4z?k(n-`V#k{r3GHJ>#GKk?O^kv`L=372pmj` zrMz^WE3$WESDY*%v1fTXHQ@_fqg*VPpYWM3qZkEJn*p3#ME zw;?}{SGticu{_Gn&Rb+f&nl^IikDUqftp?a0>Q6#^VRxi%<%Rf-^awbl@M&9?J106 zx=Q-g>w)?wS&j0dlO^LOtDKHH`xw?k8NciZlr8iw61!~hZ_usieQ zXjeAO&~VC2wbks4dhIVK*yZdn03ZF4{uIc*Lm=O)K$*0zCU%cO#dzsC54kyU@Zw^_ z%?U^@B@>+Fv7MhAc&gg|U*F-2brX-p(mT66i{EZM;Jg~TJN>$4j!B&MkMHmFb1^$R zrMLj0U*oO7C_YAYUccyRt5re2g)6kC^kaV053i|KW|E1`rFa}glnJNm*M6Kq3)iz# zQM_X?Ru$_#_~Y}2iUDDK_){ta=D)*(UYOVVTjBPDNemuyYLy9^Gt z^AaAj#H4O^4LWI&cQS)m1(wO<^Q>mDS;O)dZkY5HTSYkA2fSj5X} zqkcT0TY|S=xG1h)e&a6@ecE6EhM%iQPep{$E;fEv+@ak(4=HMWnG%gF;{Ks?ZFqRyKVV1xiSMs3-il*ima%4-E~V{Q{Z*xL$FsXK zWbx_7KKSsb=_g-Is~vGV9$%&26yFa6@Gmi{#a%NiFZ@0Z`f%qc8TR6%0DObJ1ehTE z(1C^rYr2`D7`IoSbDHp`>3T_!CNlQJKf!0fezie9s-fm=&1>|c%qbT`#^qTuXucU`(tPpLd7pjb%pFnrAITYcsd#X^! zP6rOBTurF%aI~%ZW7LI5&inayaj+WgJ}eSNiO>G=F*W)zf$aMQl%LsRz4a?T{pt3P z?pnKjj(OZ#c1U!u53xeb8_5?;Gcybv=kc=F(kow>tE}{O7p%rCYuxmqzn6;Nw^^4C zE-?l2so%fqf8E`R&_of;rY7}Dv3+WY4K4h8FgIzq$)k@G!{7soth@iZnbsAP>fq9m ze_o_Y^Zupm{^)0?kdg~7G(dh8Oux$!fV!jTC)$6nKb9ZGSxViw8sCN#r_Hh?mOc}s zyi{YAHp@#6wB1!6(Kbd_d#Mpu+{3#D_rQ{=brw#KD|<-yzPR2(<;7rMq&AR`xM;xY zc6t?`deSLE{Q{PP5e1CBmwC+S`HS-d>uTpYYJ zqT+h`0r{pbM`aPgMwX4(HgO3N;>;YJaZPf)zOh{s$agO8?%konw#E|s%)4! zB{w@E_9rJPY2u>~pYlb?+h1wiaKEGph!Up-cMuEI7pp5hFIdm1zc^w+ieUnL;N4rw zAm;}K^!CM)KWnNk&sP@wOR!$2GHs2#t! zBt%xO9`74g%9*;=f{;E0{zWh#-}CRmO42!R3&CA%ZIx==B4!)9cZ3RmF2*meUqAY; z^*tR}*A)>k>A-)H6d|+Z@hf(p2l3~5_~TgeVgr1z``#c_xcsx@4X}FZ-;aN| zR%Xn_iQ4+(;WQQNv$(HzJdskx51jf&O}ymNp};?dbzFAVM)mWdysc}YCKt`%l|-8W z`vs?|H<6vg?zMaeGp7YmKEj>dK3XP?&cyL?O0=0XH zKt91AnT!zqZ|Tej;j!6^MyNA{~VX zp*a|Lv9BY7;i(j1J3|cc(OU;pgY3fw>Ysa_$wNyX?KbQ=P2nFR>)Wi@4+O+hk06F2 z+FB)YLUfCp=Eka^G)OzoM1`OCU=4jR!t~up>+}i114r7ZC*TC~%@I1Sb*-y7(im+? zmdQFFhs}>e?Pom4NTnKlI(q|miyjh9hf$=;UAlI>M)ITLg~gEZG=twuBf2$v2$!;U zQh<*qvM�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⁢%2D#IiW}qlZes=mCnq>|R!10}UGGQ@!K* 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�*r_?6&(nY?JXgp~ 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
    2. tX?<%$5abg;dnXUJPY&RF!HG3n^>Hu~<>MI&z06?&1PlRFfwQ79xpdUS00XP0AD}WShTD~V(VcRwhY{% zb6maj^I`QYaeO@9<4rBO5xt#4|DY>Mb7$h3)Y};s&Mp;mSWgMeP5F(-jZ_zEDWo zu0<8=^I^o;IxYPMof^J`GB3^#n|bK>4NC)*@h6UUzjH)8O(xdytIDKSyIZ7*9B{S6 zAH;1h`#OW#fV+p@QeBF_<{}TKg%oFS?<7#$*VSSaEpwp7DWJZ3%CDHmr?Fe|#e{uA zr{w*jL9s1o*%#c z@B$H%RkYKZkGW3@wybQ=k z4&l@bwoen_>vK^{@_*o(Vru8RU;gdkzr)`X7_U~Lge?{6rvD7NbGz~;M3XLHt^zf^ zj!N?9NFJ2QvB%erFndE2rCrUGK0tn cEySurPZG2!G6j>455$Dcpo>mp*e@2c25 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

      ed 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 z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNCfFFSM~000000ObGL2nh}xIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!1K6Ph0RR9103iR@Mo4hrz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede z;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQq zIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n? z4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj! z0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^` zz<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!K zaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB) z95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c z2M!!KaNxj!0|yQqIB?*=fddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*= zfddB)95`^`z<~n?4jede;J|?c2M!!KaNxj!0|yQqIB?*=fddB)9MBFO2mk;800`Qj zdXYlNfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM O7%*VKfB^#r3>auVv3$n> literal 0 HcmV?d00001 diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 536c2054a0..aa58c021e9 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -16,6 +16,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/database" + "github.com/btcsuite/btcd/database/ffldb" "github.com/btcsuite/btcd/wire" ) @@ -704,3 +705,96 @@ func TestFlushNeededAfterPrune(t *testing.T) { } } } + +func TestFlushOnPrune(t *testing.T) { + chain, tearDown, err := chainSetup("TestFlushOnPrune", &chaincfg.MainNetParams) + if err != nil { + panic(fmt.Sprintf("error loading blockchain with database: %v", err)) + } + defer tearDown() + + chain.utxoCache.maxTotalMemoryUsage = 10 * 1024 * 1024 + chain.utxoCache.cachedEntries.maxTotalMemoryUsage = chain.utxoCache.maxTotalMemoryUsage + + // Set the maxBlockFileSize and the prune target small so that we can trigger a + // prune to happen. + maxBlockFileSize := uint32(8192) + chain.pruneTarget = uint64(maxBlockFileSize) * 2 + + // Read blocks from the file. + blocks, err := loadBlocks("blk_0_to_14131.dat") + if err != nil { + t.Fatalf("failed to read block from file. %v", err) + } + + syncBlocks := func() { + for i, block := range blocks { + if i == 0 { + // Skip the genesis block. + continue + } + isMainChain, _, err := chain.ProcessBlock(block, BFNone) + if err != nil { + t.Fatal(err) + } + + if !isMainChain { + t.Fatalf("expected block %s to be on the main chain", block.Hash()) + } + } + } + + // Sync the chain. + ffldb.TstRunWithMaxBlockFileSize(chain.db, maxBlockFileSize, syncBlocks) + + // Function that errors out if the block that should exist doesn't exist. + shouldExist := func(dbTx database.Tx, blockHash *chainhash.Hash) { + bytes, err := dbTx.FetchBlock(blockHash) + if err != nil { + t.Fatal(err) + } + block, err := btcutil.NewBlockFromBytes(bytes) + if err != nil { + t.Fatalf("didn't find block %v. %v", blockHash, err) + } + + if !block.Hash().IsEqual(blockHash) { + t.Fatalf("expected to find block %v but got %v", + blockHash, block.Hash()) + } + } + + // Function that errors out if the block that shouldn't exist exists. + shouldNotExist := func(dbTx database.Tx, blockHash *chainhash.Hash) { + bytes, err := dbTx.FetchBlock(chaincfg.MainNetParams.GenesisHash) + if err == nil { + t.Fatalf("expected block %s to be pruned", blockHash) + } + if len(bytes) != 0 { + t.Fatalf("expected block %s to be pruned but got %v", + blockHash, bytes) + } + } + + // The below code checks that the correct blocks were pruned. + chain.db.View(func(dbTx database.Tx) error { + exist := false + for _, block := range blocks { + // Blocks up to the last flush hash should not exist. + // The utxocache is big enough so that it shouldn't flush + // on it being full. It should only flush on prunes. + if block.Hash().IsEqual(&chain.utxoCache.lastFlushHash) { + exist = true + } + + if exist { + shouldExist(dbTx, block.Hash()) + } else { + shouldNotExist(dbTx, block.Hash()) + } + + } + + return nil + }) +} From 84bdd0180ec5ff291f5cc6be8a3c9eefb89c56a0 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 13 Oct 2023 15:43:28 +0900 Subject: [PATCH 0905/1056] ffldb: change export_test.go to export.go The testing function in export_test.go is changed to just export.go so that callers outside the ffldb package will be able to call the function. The main use for this is so that the prune code can be triggered from the blockchain package. This allows testing code to have less than 1.5GB worth of blocks to trigger the prune. --- database/ffldb/{export_test.go => export.go} | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) rename database/ffldb/{export_test.go => export.go} (68%) diff --git a/database/ffldb/export_test.go b/database/ffldb/export.go similarity index 68% rename from database/ffldb/export_test.go rename to database/ffldb/export.go index cbb6dc9465..0802167ee0 100644 --- a/database/ffldb/export_test.go +++ b/database/ffldb/export.go @@ -2,13 +2,6 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -/* -This test file is part of the ffldb package rather than than the ffldb_test -package so it can bridge access to the internals to properly test cases which -are either not possible or can't reliably be tested via the public interface. -The functions are only exported while the tests are being run. -*/ - package ffldb import ( @@ -18,6 +11,8 @@ import ( // TstRunWithMaxBlockFileSize runs the passed function with the maximum allowed // file size for the database set to the provided value. The value will be set // back to the original value upon completion. +// +// Callers should only use this for testing. func TstRunWithMaxBlockFileSize(idb database.DB, size uint32, fn func()) { ffldb := idb.(*db) origSize := ffldb.store.maxBlockFileSize From 26b2e9d9de07d18706a5a021c91691201af7a28b Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Sun, 15 Oct 2023 17:53:14 +0900 Subject: [PATCH 0906/1056] blockchain: add test for InitConsistentState --- blockchain/utxocache_test.go | 115 +++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index aa58c021e9..20b2a5b34a 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -7,6 +7,7 @@ import ( "crypto/sha256" "encoding/binary" "fmt" + "path/filepath" "reflect" "sync" "testing" @@ -798,3 +799,117 @@ func TestFlushOnPrune(t *testing.T) { return nil }) } + +func TestInitConsistentState(t *testing.T) { + // Boilerplate for creating a chain. + dbName := "TestFlushOnPrune" + chain, tearDown, err := chainSetup(dbName, &chaincfg.MainNetParams) + if err != nil { + panic(fmt.Sprintf("error loading blockchain with database: %v", err)) + } + defer tearDown() + chain.utxoCache.maxTotalMemoryUsage = 10 * 1024 * 1024 + chain.utxoCache.cachedEntries.maxTotalMemoryUsage = chain.utxoCache.maxTotalMemoryUsage + + // Read blocks from the file. + blocks, err := loadBlocks("blk_0_to_14131.dat") + if err != nil { + t.Fatalf("failed to read block from file. %v", err) + } + + // Sync up to height 13,000. Flush the utxocache at height 11_000. + cacheFlushHeight := 9000 + initialSyncHeight := 12_000 + for i, block := range blocks { + if i == 0 { + // Skip the genesis block. + continue + } + + isMainChain, _, err := chain.ProcessBlock(block, BFNone) + if err != nil { + t.Fatal(err) + } + + if !isMainChain { + t.Fatalf("expected block %s to be on the main chain", block.Hash()) + } + + if i == cacheFlushHeight { + err = chain.FlushUtxoCache(FlushRequired) + if err != nil { + t.Fatal(err) + } + } + if i == initialSyncHeight { + break + } + } + + // Sanity check. + if chain.BestSnapshot().Height != int32(initialSyncHeight) { + t.Fatalf("expected the chain to sync up to height %d", initialSyncHeight) + } + + // Close the database without flushing the utxocache. This leaves the + // chaintip at height 13,000 but the utxocache consistent state at 11,000. + err = chain.db.Close() + if err != nil { + t.Fatal(err) + } + chain.db = nil + + // Re-open the database and pass the re-opened db to internal structs. + dbPath := filepath.Join(testDbRoot, dbName) + ndb, err := database.Open(testDbType, dbPath, blockDataNet) + if err != nil { + t.Fatal(err) + } + chain.db = ndb + chain.utxoCache.db = ndb + chain.index.db = ndb + + // Sanity check to see that the utxo cache was flushed before the + // current chain tip. + var statusBytes []byte + ndb.View(func(dbTx database.Tx) error { + statusBytes = dbFetchUtxoStateConsistency(dbTx) + return nil + }) + statusHash, err := chainhash.NewHash(statusBytes) + if err != nil { + t.Fatal(err) + } + if !statusHash.IsEqual(blocks[cacheFlushHeight].Hash()) { + t.Fatalf("expected the utxocache to be flushed at "+ + "block hash %s but got %s", + blocks[cacheFlushHeight].Hash(), statusHash) + } + + // Call InitConsistentState. This will make the utxocache catch back + // up to the tip. + err = chain.InitConsistentState(chain.bestChain.tip(), nil) + if err != nil { + t.Fatal(err) + } + + // Sync the reset of the blocks. + for i, block := range blocks { + if i <= initialSyncHeight { + continue + } + isMainChain, _, err := chain.ProcessBlock(block, BFNone) + if err != nil { + t.Fatal(err) + } + + if !isMainChain { + t.Fatalf("expected block %s to be on the main chain", block.Hash()) + } + } + + if chain.BestSnapshot().Height != blocks[len(blocks)-1].Height() { + t.Fatalf("expected the chain to sync up to height %d", + blocks[len(blocks)-1].Height()) + } +} From 87a81f14fc268e06680ec4275284cacfe0cccdc7 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 13 Dec 2023 23:48:26 +0900 Subject: [PATCH 0907/1056] blockchain: address nit comments --- blockchain/chainio.go | 1 + blockchain/utxocache.go | 36 ++++++++++++++++++------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 22aac08343..75474021f8 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -795,6 +795,7 @@ func dbPutUtxoView(dbTx database.Tx, view *UtxoViewpoint) error { if view == nil { return nil } + utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) for outpoint, entry := range view.entries { // No need to update the database if the entry was not modified. diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index 0af6f25cab..af7a3b7b6f 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -262,8 +262,10 @@ func (s *utxoCache) totalMemoryUsage() uint64 { // The returned entries are NOT safe for concurrent access. func (s *utxoCache) fetchEntries(outpoints []wire.OutPoint) ([]*UtxoEntry, error) { entries := make([]*UtxoEntry, len(outpoints)) - var missingOps []wire.OutPoint - var missingOpsIdx []int + var ( + missingOps []wire.OutPoint + missingOpsIdx []int + ) for i := range outpoints { if entry, ok := s.cachedEntries.get(outpoints[i]); ok { entries[i] = entry @@ -330,8 +332,8 @@ func (s *utxoCache) fetchEntries(outpoints []wire.OutPoint) ([]*UtxoEntry, error // unspendable. When the cache already has an entry for the output, it will be // overwritten with the given output. All fields will be updated for existing // entries since it's possible it has changed during a reorg. -func (s *utxoCache) addTxOut( - outpoint wire.OutPoint, txOut *wire.TxOut, isCoinBase bool, blockHeight int32) error { +func (s *utxoCache) addTxOut(outpoint wire.OutPoint, txOut *wire.TxOut, isCoinBase bool, + blockHeight int32) error { // Don't add provably unspendable outputs. if txscript.IsUnspendable(txOut.PkScript) { @@ -340,6 +342,7 @@ func (s *utxoCache) addTxOut( entry := new(UtxoEntry) entry.amount = txOut.Value + // Deep copy the script when the script in the entry differs from the one in // the txout. This is required since the txout script is a subslice of the // overall contiguous buffer that the msg tx houses for all scripts within @@ -406,7 +409,7 @@ func (s *utxoCache) addTxIn(txIn *wire.TxIn, stxos *[]SpentTxOut) error { entry := entries[0] if stxos != nil { // Populate the stxo details using the utxo entry. - var stxo = SpentTxOut{ + stxo := SpentTxOut{ Amount: entry.Amount(), PkScript: entry.PkScript(), Height: entry.BlockHeight(), @@ -498,29 +501,25 @@ func (s *utxoCache) writeCache(dbTx database.Tx, bestState *BestState) error { utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) for i := range s.cachedEntries.maps { for outpoint, entry := range s.cachedEntries.maps[i] { + switch { // If the entry is nil or spent, remove the entry from the database // and the cache. - if entry == nil || entry.IsSpent() { + case entry == nil || entry.IsSpent(): err := dbDeleteUtxoEntry(utxoBucket, outpoint) if err != nil { return err } - delete(s.cachedEntries.maps[i], outpoint) - - continue - } // No need to update the cache if the entry was not modified. - if !entry.isModified() { - delete(s.cachedEntries.maps[i], outpoint) - continue + case !entry.isModified(): + default: + // Entry is fresh and needs to be put into the database. + err := dbPutUtxoEntry(utxoBucket, outpoint, entry) + if err != nil { + return err + } } - // Entry is fresh and needs to be put into the database. - err := dbPutUtxoEntry(utxoBucket, outpoint, entry) - if err != nil { - return err - } delete(s.cachedEntries.maps[i], outpoint) } } @@ -600,6 +599,7 @@ func (b *BlockChain) FlushUtxoCache(mode FlushMode) error { // get changed during the execution of this method. func (b *BlockChain) InitConsistentState(tip *blockNode, interrupt <-chan struct{}) error { s := b.utxoCache + // Load the consistency status from the database. var statusBytes []byte s.db.View(func(dbTx database.Tx) error { From b2f340d9d94a9d0bcb5b67301356ae8aba022ccf Mon Sep 17 00:00:00 2001 From: Afanti <127061691+threewebcode@users.noreply.github.com> Date: Tue, 19 Dec 2023 23:40:37 +0800 Subject: [PATCH 0908/1056] fix: enhance code comments (#2074) * fix: enhance code comments --- mining/mining.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mining/mining.go b/mining/mining.go index efc0ae235a..7905dade76 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -520,7 +520,7 @@ mempoolLoop: continue } - // Fetch all of the utxos referenced by the this transaction. + // Fetch all of the utxos referenced by this transaction. // NOTE: This intentionally does not fetch inputs from the // mempool since a transaction which depends on other // transactions in the mempool must come after those From 4126760706a04c9e39a6c1ed988e49ba17721da6 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 18 Dec 2023 16:41:58 -0800 Subject: [PATCH 0909/1056] btcutil/psbt: update to btcutil btcutil/v1.1.4 --- btcutil/psbt/go.mod | 4 ++-- btcutil/psbt/go.sum | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/btcutil/psbt/go.mod b/btcutil/psbt/go.mod index b5c4461d86..81ccca266b 100644 --- a/btcutil/psbt/go.mod +++ b/btcutil/psbt/go.mod @@ -3,9 +3,9 @@ module github.com/btcsuite/btcd/btcutil/psbt go 1.17 require ( - github.com/btcsuite/btcd v0.23.0 + github.com/btcsuite/btcd v0.23.5-0.20231219003633-4c2ce6daed8f github.com/btcsuite/btcd/btcec/v2 v2.1.3 - github.com/btcsuite/btcd/btcutil v1.1.3 + github.com/btcsuite/btcd/btcutil v1.1.4 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/stretchr/testify v1.7.0 diff --git a/btcutil/psbt/go.sum b/btcutil/psbt/go.sum index c9d8388f8e..74a2ce8a3d 100644 --- a/btcutil/psbt/go.sum +++ b/btcutil/psbt/go.sum @@ -1,15 +1,16 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= -github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.23.5-0.20231219003633-4c2ce6daed8f h1:E+dQ8sNtK/lOdfeflUKkRLXe/zW7I333C7HhaoASjZA= +github.com/btcsuite/btcd v0.23.5-0.20231219003633-4c2ce6daed8f/go.mod h1:KVEB81PybLGYzpf1db/kKNi1ZEbUsiVGeTGhKuOl5AM= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= -github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/btcutil v1.1.4 h1:mWvWRLRIPuoeZsVRpc0xNCkfeNxWy1E4jIZ06ZpGI1A= +github.com/btcsuite/btcd/btcutil v1.1.4/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= @@ -46,6 +47,7 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= From c3c3545f9be953553efdb69d4c4809769c0ce4b5 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 18 Dec 2023 16:53:51 -0800 Subject: [PATCH 0910/1056] multi: update main package to chainhash/v1.1.0, use optimized dsha256 In this commit, we update the top-level btcd package to use the latest version of btcutil and also the chainhash package. With this version bump, we can now use the new optimized dsha256 routine where applicable. With this commit, I've covered most of the areas we'll hash an entire transaction/block/header, but we may want to optimize some other areas further, in particular, the witness sighash calc. --- blockchain/merkle.go | 6 +++++- go.mod | 4 +--- go.sum | 20 ++++++++++++++++++++ txscript/sighash.go | 25 ++++++++++++++++++++----- wire/blockheader.go | 12 +++--------- wire/msgtx.go | 13 ++----------- 6 files changed, 51 insertions(+), 29 deletions(-) diff --git a/blockchain/merkle.go b/blockchain/merkle.go index a1a50a2bd5..b89b518505 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -7,6 +7,7 @@ package blockchain import ( "bytes" "fmt" + "io" "math" "github.com/btcsuite/btcd/btcutil" @@ -64,7 +65,10 @@ func HashMerkleBranches(left, right *chainhash.Hash) chainhash.Hash { copy(hash[:chainhash.HashSize], left[:]) copy(hash[chainhash.HashSize:], right[:]) - return chainhash.DoubleHashH(hash[:]) + return chainhash.DoubleHashRaw(func(w io.Writer) error { + _, err := w.Write(hash[:]) + return err + }) } // BuildMerkleTreeStore creates a merkle tree from a slice of transactions, diff --git a/go.mod b/go.mod index 977682aae2..36d4aa21bd 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/btcsuite/btcd require ( github.com/btcsuite/btcd/btcec/v2 v2.1.3 - github.com/btcsuite/btcd/btcutil v1.1.0 + github.com/btcsuite/btcd/btcutil v1.1.4 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd @@ -29,8 +29,6 @@ require ( gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) -replace github.com/btcsuite/btcd/btcutil => ./btcutil - // The retract statements below fixes an accidental push of the tags of a btcd // fork. retract ( diff --git a/go.sum b/go.sum index 9944f70ec3..6a2ee39cd8 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,33 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.4 h1:mWvWRLRIPuoeZsVRpc0xNCkfeNxWy1E4jIZ06ZpGI1A= +github.com/btcsuite/btcd/btcutil v1.1.4/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -42,6 +55,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= @@ -51,9 +65,12 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -64,9 +81,11 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -102,6 +121,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/txscript/sighash.go b/txscript/sighash.go index 7dc19ab5bd..486a937765 100644 --- a/txscript/sighash.go +++ b/txscript/sighash.go @@ -169,10 +169,18 @@ func calcSignatureHash(sigScript []byte, hashType SigHashType, tx *wire.MsgTx, i // The final hash is the double sha256 of both the serialized modified // transaction and the hash type (encoded as a 4-byte little-endian // value) appended. - wbuf := bytes.NewBuffer(make([]byte, 0, txCopy.SerializeSizeStripped()+4)) - txCopy.SerializeNoWitness(wbuf) - binary.Write(wbuf, binary.LittleEndian, hashType) - return chainhash.DoubleHashB(wbuf.Bytes()) + sigHashBytes := chainhash.DoubleHashRaw(func(w io.Writer) error { + if err := txCopy.SerializeNoWitness(w); err != nil { + return err + } + err := binary.Write(w, binary.LittleEndian, hashType) + if err != nil { + return err + } + return nil + }) + + return sigHashBytes[:] } // calcWitnessSignatureHashRaw computes the sighash digest of a transaction's @@ -289,7 +297,14 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType)) sigHash.Write(bHashType[:]) - return chainhash.DoubleHashB(sigHash.Bytes()), nil + sigHashBytes := chainhash.DoubleHashRaw(func(w io.Writer) error { + // TODO(rosabeef): put entire calc func into this? then no + // intermediate buffer + _, err := sigHash.WriteTo(w) + return err + }) + + return sigHashBytes[:], nil } // CalcWitnessSigHash computes the sighash digest for the specified input of diff --git a/wire/blockheader.go b/wire/blockheader.go index 9c9c2237e6..7af9a3788e 100644 --- a/wire/blockheader.go +++ b/wire/blockheader.go @@ -5,7 +5,6 @@ package wire import ( - "bytes" "io" "time" @@ -46,14 +45,9 @@ const blockHeaderLen = 80 // BlockHash computes the block identifier hash for the given block header. func (h *BlockHeader) BlockHash() chainhash.Hash { - // Encode the header and double sha256 everything prior to the number of - // transactions. Ignore the error returns since there is no way the - // encode could fail except being out of memory which would cause a - // run-time panic. - buf := bytes.NewBuffer(make([]byte, 0, MaxBlockHeaderPayload)) - _ = writeBlockHeader(buf, 0, h) - - return chainhash.DoubleHashH(buf.Bytes()) + return chainhash.DoubleHashRaw(func(w io.Writer) error { + return writeBlockHeader(w, 0, h) + }) } // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. diff --git a/wire/msgtx.go b/wire/msgtx.go index 7705504cc8..d2b52dba24 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -5,7 +5,6 @@ package wire import ( - "bytes" "errors" "fmt" "io" @@ -357,13 +356,7 @@ func (msg *MsgTx) AddTxOut(to *TxOut) { // TxHash generates the Hash for the transaction. func (msg *MsgTx) TxHash() chainhash.Hash { - // Encode the transaction and calculate double sha256 on the result. - // Ignore the error returns since the only way the encode could fail - // is being out of memory or due to nil pointers, both of which would - // cause a run-time panic. - buf := bytes.NewBuffer(make([]byte, 0, msg.SerializeSizeStripped())) - _ = msg.SerializeNoWitness(buf) - return chainhash.DoubleHashH(buf.Bytes()) + return chainhash.DoubleHashRaw(msg.SerializeNoWitness) } // WitnessHash generates the hash of the transaction serialized according to @@ -373,9 +366,7 @@ func (msg *MsgTx) TxHash() chainhash.Hash { // is the same as its txid. func (msg *MsgTx) WitnessHash() chainhash.Hash { if msg.HasWitness() { - buf := bytes.NewBuffer(make([]byte, 0, msg.SerializeSize())) - _ = msg.Serialize(buf) - return chainhash.DoubleHashH(buf.Bytes()) + return chainhash.DoubleHashRaw(msg.Serialize) } return msg.TxHash() From adfb641a3626a3cca02a33676c7b1b0ab62c1c2b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 18 Dec 2023 17:01:02 -0800 Subject: [PATCH 0911/1056] txscript: use DoubleHashRaw to write directly crypto.Hash for segwit sighash In this commit, we optimize the sighash calc further by writing directly into the buffer used for serialization by the sha256.New() instance rather than to an intermediate buffer, which is then write to the hash buffer. --- txscript/sighash.go | 186 ++++++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 92 deletions(-) diff --git a/txscript/sighash.go b/txscript/sighash.go index 486a937765..32b776afef 100644 --- a/txscript/sighash.go +++ b/txscript/sighash.go @@ -205,103 +205,105 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, return nil, fmt.Errorf("idx %d but %d txins", idx, len(tx.TxIn)) } - // We'll utilize this buffer throughout to incrementally calculate - // the signature hash for this transaction. - var sigHash bytes.Buffer - - // First write out, then encode the transaction's version number. - var bVersion [4]byte - binary.LittleEndian.PutUint32(bVersion[:], uint32(tx.Version)) - sigHash.Write(bVersion[:]) - - // Next write out the possibly pre-calculated hashes for the sequence - // numbers of all inputs, and the hashes of the previous outs for all - // outputs. - var zeroHash chainhash.Hash - - // If anyone can pay isn't active, then we can use the cached - // hashPrevOuts, otherwise we just write zeroes for the prev outs. - if hashType&SigHashAnyOneCanPay == 0 { - sigHash.Write(sigHashes.HashPrevOutsV0[:]) - } else { - sigHash.Write(zeroHash[:]) - } + sigHashBytes := chainhash.DoubleHashRaw(func(w io.Writer) error { + // First write out, then encode the transaction's version + // number. + var bVersion [4]byte + binary.LittleEndian.PutUint32(bVersion[:], uint32(tx.Version)) + w.Write(bVersion[:]) + + // Next write out the possibly pre-calculated hashes for the + // sequence numbers of all inputs, and the hashes of the + // previous outs for all outputs. + var zeroHash chainhash.Hash + + // If anyone can pay isn't active, then we can use the cached + // hashPrevOuts, otherwise we just write zeroes for the prev + // outs. + if hashType&SigHashAnyOneCanPay == 0 { + w.Write(sigHashes.HashPrevOutsV0[:]) + } else { + w.Write(zeroHash[:]) + } - // If the sighash isn't anyone can pay, single, or none, the use the - // cached hash sequences, otherwise write all zeroes for the - // hashSequence. - if hashType&SigHashAnyOneCanPay == 0 && - hashType&sigHashMask != SigHashSingle && - hashType&sigHashMask != SigHashNone { - sigHash.Write(sigHashes.HashSequenceV0[:]) - } else { - sigHash.Write(zeroHash[:]) - } + // If the sighash isn't anyone can pay, single, or none, the + // use the cached hash sequences, otherwise write all zeroes + // for the hashSequence. + if hashType&SigHashAnyOneCanPay == 0 && + hashType&sigHashMask != SigHashSingle && + hashType&sigHashMask != SigHashNone { - txIn := tx.TxIn[idx] - - // Next, write the outpoint being spent. - sigHash.Write(txIn.PreviousOutPoint.Hash[:]) - var bIndex [4]byte - binary.LittleEndian.PutUint32(bIndex[:], txIn.PreviousOutPoint.Index) - sigHash.Write(bIndex[:]) - - if isWitnessPubKeyHashScript(subScript) { - // The script code for a p2wkh is a length prefix varint for - // the next 25 bytes, followed by a re-creation of the original - // p2pkh pk script. - sigHash.Write([]byte{0x19}) - sigHash.Write([]byte{OP_DUP}) - sigHash.Write([]byte{OP_HASH160}) - sigHash.Write([]byte{OP_DATA_20}) - sigHash.Write(extractWitnessPubKeyHash(subScript)) - sigHash.Write([]byte{OP_EQUALVERIFY}) - sigHash.Write([]byte{OP_CHECKSIG}) - } else { - // For p2wsh outputs, and future outputs, the script code is - // the original script, with all code separators removed, - // serialized with a var int length prefix. - wire.WriteVarBytes(&sigHash, 0, subScript) - } + w.Write(sigHashes.HashSequenceV0[:]) + } else { + w.Write(zeroHash[:]) + } - // Next, add the input amount, and sequence number of the input being - // signed. - var bAmount [8]byte - binary.LittleEndian.PutUint64(bAmount[:], uint64(amt)) - sigHash.Write(bAmount[:]) - var bSequence [4]byte - binary.LittleEndian.PutUint32(bSequence[:], txIn.Sequence) - sigHash.Write(bSequence[:]) - - // If the current signature mode isn't single, or none, then we can - // re-use the pre-generated hashoutputs sighash fragment. Otherwise, - // we'll serialize and add only the target output index to the signature - // pre-image. - if hashType&sigHashMask != SigHashSingle && - hashType&sigHashMask != SigHashNone { - sigHash.Write(sigHashes.HashOutputsV0[:]) - } else if hashType&sigHashMask == SigHashSingle && idx < len(tx.TxOut) { - var b bytes.Buffer - wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx]) - sigHash.Write(chainhash.DoubleHashB(b.Bytes())) - } else { - sigHash.Write(zeroHash[:]) - } + txIn := tx.TxIn[idx] + + // Next, write the outpoint being spent. + w.Write(txIn.PreviousOutPoint.Hash[:]) + var bIndex [4]byte + binary.LittleEndian.PutUint32( + bIndex[:], txIn.PreviousOutPoint.Index, + ) + w.Write(bIndex[:]) + + if isWitnessPubKeyHashScript(subScript) { + // The script code for a p2wkh is a length prefix + // varint for the next 25 bytes, followed by a + // re-creation of the original p2pkh pk script. + w.Write([]byte{0x19}) + w.Write([]byte{OP_DUP}) + w.Write([]byte{OP_HASH160}) + w.Write([]byte{OP_DATA_20}) + w.Write(extractWitnessPubKeyHash(subScript)) + w.Write([]byte{OP_EQUALVERIFY}) + w.Write([]byte{OP_CHECKSIG}) + } else { + // For p2wsh outputs, and future outputs, the script + // code is the original script, with all code + // separators removed, serialized with a var int length + // prefix. + wire.WriteVarBytes(w, 0, subScript) + } - // Finally, write out the transaction's locktime, and the sig hash - // type. - var bLockTime [4]byte - binary.LittleEndian.PutUint32(bLockTime[:], tx.LockTime) - sigHash.Write(bLockTime[:]) - var bHashType [4]byte - binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType)) - sigHash.Write(bHashType[:]) + // Next, add the input amount, and sequence number of the input + // being signed. + var bAmount [8]byte + binary.LittleEndian.PutUint64(bAmount[:], uint64(amt)) + w.Write(bAmount[:]) + var bSequence [4]byte + binary.LittleEndian.PutUint32(bSequence[:], txIn.Sequence) + w.Write(bSequence[:]) + + // If the current signature mode isn't single, or none, then we + // can re-use the pre-generated hashoutputs sighash fragment. + // Otherwise, we'll serialize and add only the target output + // index to the signature pre-image. + if hashType&sigHashMask != SigHashSingle && + hashType&sigHashMask != SigHashNone { + + w.Write(sigHashes.HashOutputsV0[:]) + } else if hashType&sigHashMask == SigHashSingle && + idx < len(tx.TxOut) { + + var b bytes.Buffer + wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx]) + w.Write(chainhash.DoubleHashB(b.Bytes())) + } else { + w.Write(zeroHash[:]) + } - sigHashBytes := chainhash.DoubleHashRaw(func(w io.Writer) error { - // TODO(rosabeef): put entire calc func into this? then no - // intermediate buffer - _, err := sigHash.WriteTo(w) - return err + // Finally, write out the transaction's locktime, and the sig + // hash type. + var bLockTime [4]byte + binary.LittleEndian.PutUint32(bLockTime[:], tx.LockTime) + w.Write(bLockTime[:]) + var bHashType [4]byte + binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType)) + w.Write(bHashType[:]) + + return nil }) return sigHashBytes[:], nil From 046a70121a6d33d20038d4b9ea5905e0dd29cc1b Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Dec 2023 14:40:18 -0800 Subject: [PATCH 0912/1056] txscript: use DoubleHashRaw for segwit sighash single calc We can write direly into the hash writer vs serializing into a buffer, then writing that into the hash writer. --- txscript/sighash.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/txscript/sighash.go b/txscript/sighash.go index 32b776afef..65a38a1e36 100644 --- a/txscript/sighash.go +++ b/txscript/sighash.go @@ -287,9 +287,11 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, } else if hashType&sigHashMask == SigHashSingle && idx < len(tx.TxOut) { - var b bytes.Buffer - wire.WriteTxOut(&b, 0, 0, tx.TxOut[idx]) - w.Write(chainhash.DoubleHashB(b.Bytes())) + h := chainhash.DoubleHashRaw(func(tw io.Writer) error { + wire.WriteTxOut(tw, 0, 0, tx.TxOut[idx]) + return nil + }) + w.Write(h[:]) } else { w.Write(zeroHash[:]) } From 19008edd0faaa12938895b54aad83af820d703dc Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Tue, 19 Dec 2023 14:56:57 -0800 Subject: [PATCH 0913/1056] txscript: use a single shared scratch buffer in segwit sighash calc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We used to use a lot of small buffers for serialization, but now we'll use one buffer large enough, and slice into it when needed. `` name old time/op new time/op delta CalcWitnessSigHash-8 31.5µs ± 0% 29.2µs ± 0% -7.05% (p=0.000 n=10+10) name old alloc/op new alloc/op delta CalcWitnessSigHash-8 19.9kB ± 0% 18.5kB ± 0% -7.14% (p=0.000 n=10+10) name old allocs/op new allocs/op delta CalcWitnessSigHash-8 801 ± 0% 445 ± 0% -44.44% (p=0.000 n=10+10) ``` --- txscript/sighash.go | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/txscript/sighash.go b/txscript/sighash.go index 65a38a1e36..16c3c19c18 100644 --- a/txscript/sighash.go +++ b/txscript/sighash.go @@ -206,11 +206,12 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, } sigHashBytes := chainhash.DoubleHashRaw(func(w io.Writer) error { + var scratch [8]byte + // First write out, then encode the transaction's version // number. - var bVersion [4]byte - binary.LittleEndian.PutUint32(bVersion[:], uint32(tx.Version)) - w.Write(bVersion[:]) + binary.LittleEndian.PutUint32(scratch[:], uint32(tx.Version)) + w.Write(scratch[:4]) // Next write out the possibly pre-calculated hashes for the // sequence numbers of all inputs, and the hashes of the @@ -269,12 +270,10 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, // Next, add the input amount, and sequence number of the input // being signed. - var bAmount [8]byte - binary.LittleEndian.PutUint64(bAmount[:], uint64(amt)) - w.Write(bAmount[:]) - var bSequence [4]byte - binary.LittleEndian.PutUint32(bSequence[:], txIn.Sequence) - w.Write(bSequence[:]) + binary.LittleEndian.PutUint64(scratch[:], uint64(amt)) + w.Write(scratch[:]) + binary.LittleEndian.PutUint32(scratch[:], txIn.Sequence) + w.Write(scratch[:4]) // If the current signature mode isn't single, or none, then we // can re-use the pre-generated hashoutputs sighash fragment. @@ -298,12 +297,10 @@ func calcWitnessSignatureHashRaw(subScript []byte, sigHashes *TxSigHashes, // Finally, write out the transaction's locktime, and the sig // hash type. - var bLockTime [4]byte - binary.LittleEndian.PutUint32(bLockTime[:], tx.LockTime) - w.Write(bLockTime[:]) - var bHashType [4]byte - binary.LittleEndian.PutUint32(bHashType[:], uint32(hashType)) - w.Write(bHashType[:]) + binary.LittleEndian.PutUint32(scratch[:], tx.LockTime) + w.Write(scratch[:4]) + binary.LittleEndian.PutUint32(scratch[:], uint32(hashType)) + w.Write(scratch[:4]) return nil }) From 4af0ca8c303319bf7755e3909b82e4fdffab74e4 Mon Sep 17 00:00:00 2001 From: alex <152680487+bodhi-crypo@users.noreply.github.com> Date: Wed, 20 Dec 2023 14:26:18 +0000 Subject: [PATCH 0914/1056] doc: correct comments --- cmd/btcctl/config.go | 2 +- cmd/gencerts/gencerts.go | 2 +- config.go | 4 ++-- doc.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go index 13342e6295..f6ca8846ec 100644 --- a/cmd/btcctl/config.go +++ b/cmd/btcctl/config.go @@ -158,7 +158,7 @@ func normalizeAddress(addr string, chain *chaincfg.Params, useWallet bool) (stri return addr, nil } -// cleanAndExpandPath expands environement variables and leading ~ in the +// cleanAndExpandPath expands environment variables and leading ~ in the // passed path, cleans the result, and returns it. func cleanAndExpandPath(path string) string { // Expand initial ~ to OS specific home directory. diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index c0a27ad37b..27c9ae385c 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -76,7 +76,7 @@ func main() { } } -// cleanAndExpandPath expands environement variables and leading ~ in the +// cleanAndExpandPath expands environment variables and leading ~ in the // passed path, cleans the result, and returns it. func cleanAndExpandPath(path string) string { // Expand initial ~ to OS specific home directory. diff --git a/config.go b/config.go index 1fe0767f63..18620a008c 100644 --- a/config.go +++ b/config.go @@ -105,9 +105,9 @@ type config struct { BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"` - BlockMinSize uint32 `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"` + BlockMinSize uint32 `long:"blockminsize" description:"Minimum block size in bytes to be used when creating a block"` BlockMaxWeight uint32 `long:"blockmaxweight" description:"Maximum block weight to be used when creating a block"` - BlockMinWeight uint32 `long:"blockminweight" description:"Mininum block weight to be used when creating a block"` + BlockMinWeight uint32 `long:"blockminweight" description:"Minimum block weight to be used when creating a block"` BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"` BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."` ConfigFile string `short:"C" long:"configfile" description:"Path to configuration file"` diff --git a/doc.go b/doc.go index d78e09f7e3..47e4e626b7 100644 --- a/doc.go +++ b/doc.go @@ -36,11 +36,11 @@ Application Options: and banning misbehaving peers. (default: 100) --blockmaxsize= Maximum block size in bytes to be used when creating a block (default: 750000) - --blockminsize= Mininum block size in bytes to be used when + --blockminsize= Minimum block size in bytes to be used when creating a block --blockmaxweight= Maximum block weight to be used when creating a block (default: 3000000) - --blockminweight= Mininum block weight to be used when creating a + --blockminweight= Minimum block weight to be used when creating a block --blockprioritysize= Size in bytes for high-priority/low-fee transactions when creating a block (default: From 83605e476cbe8a2782af721c20c88eba19a2c744 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 22 Aug 2023 07:22:06 +0900 Subject: [PATCH 0915/1056] btcutil: reuse serialized tx during TxHash btcutil.Block caches the serialized raw bytes of the block during ibd. This serialized block bytes includes the serialized tx. The current tx hash generation will re-serialized the de-serialized tx to create the raw bytes and it'll only then hash that. This commit changes the code so that the re-serialization never happens, saving tons of cpu and memory overhead. --- btcutil/block.go | 23 +++++++++++++++- btcutil/tx.go | 68 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/btcutil/block.go b/btcutil/block.go index 7d38abc4a0..52c909192b 100644 --- a/btcutil/block.go +++ b/btcutil/block.go @@ -154,12 +154,26 @@ func (b *Block) Transactions() []*Tx { b.transactions = make([]*Tx, len(b.msgBlock.Transactions)) } + // Offset of each tx. 80 accounts for the block header size. + offset := 80 + wire.VarIntSerializeSize(uint64(len(b.msgBlock.Transactions))) + // Generate and cache the wrapped transactions for all that haven't // already been done. for i, tx := range b.transactions { if tx == nil { newTx := NewTx(b.msgBlock.Transactions[i]) newTx.SetIndex(i) + + size := b.msgBlock.Transactions[i].SerializeSize() + + // The block may not always have the serializedBlock. + if len(b.serializedBlock) > 0 { + // This allows for the reuse of the already serialized tx. + newTx.setBytes(b.serializedBlock[offset : offset+size]) + + // Increment offset for this block. + offset += size + } b.transactions[i] = newTx } } @@ -234,6 +248,9 @@ func NewBlockFromBytes(serializedBlock []byte) (*Block, error) { return nil, err } b.serializedBlock = serializedBlock + // This initializes []btcutil.Tx to have the serialized raw transactions cached. + // Helps speed up things like generating the txhash. + b.Transactions() return b, nil } @@ -257,9 +274,13 @@ func NewBlockFromReader(r io.Reader) (*Block, error) { // NewBlockFromBlockAndBytes returns a new instance of a bitcoin block given // an underlying wire.MsgBlock and the serialized bytes for it. See Block. func NewBlockFromBlockAndBytes(msgBlock *wire.MsgBlock, serializedBlock []byte) *Block { - return &Block{ + b := &Block{ msgBlock: msgBlock, serializedBlock: serializedBlock, blockHeight: BlockHeightUnknown, } + // This initializes []btcutil.Tx to have the serialized raw transactions cached. + // Helps speed up things like generating the txhash. + b.Transactions() + return b } diff --git a/btcutil/tx.go b/btcutil/tx.go index 5633fef90e..abc055acbe 100644 --- a/btcutil/tx.go +++ b/btcutil/tx.go @@ -27,6 +27,7 @@ type Tx struct { txHashWitness *chainhash.Hash // Cached transaction witness hash txHasWitness *bool // If the transaction has witness data txIndex int // Position within a block or TxIndexUnknown + rawBytes []byte // Raw bytes for the tx in the raw block. } // MsgTx returns the underlying wire.MsgTx for the transaction. @@ -37,22 +38,68 @@ func (t *Tx) MsgTx() *wire.MsgTx { // Hash returns the hash of the transaction. This is equivalent to // calling TxHash on the underlying wire.MsgTx, however it caches the -// result so subsequent calls are more efficient. +// result so subsequent calls are more efficient. If the Tx has the +// raw bytes of the tx cached, it will use that and skip serialization. func (t *Tx) Hash() *chainhash.Hash { // Return the cached hash if it has already been generated. if t.txHash != nil { return t.txHash } - // Cache the hash and return it. - hash := t.msgTx.TxHash() + // If the rawBytes aren't available, call msgtx.TxHash. + if t.rawBytes == nil { + hash := t.msgTx.TxHash() + t.txHash = &hash + return &hash + } + + // If we have the raw bytes, then don't call msgTx.TxHash as that has the + // overhead of serialization. + var hash chainhash.Hash + if t.HasWitness() { + // If the raw bytes contain the witness, we must strip it out before + // calculating the hash. + baseSize := t.msgTx.SerializeSizeStripped() + nonWitnessBytes := make([]byte, 0, baseSize) + + // Append the version bytes. + offset := 4 + nonWitnessBytes = append(nonWitnessBytes, t.rawBytes[:offset]...) + + // Append the input and output bytes. -8 to account for the + // version bytes and the locktime bytes. + // + // Skip the 2 bytes for the witness encoding. + offset += 2 + nonWitnessBytes = append(nonWitnessBytes, t.rawBytes[offset:offset+baseSize-8]...) + + // Append the last 4 bytes which are the locktime bytes. + nonWitnessBytes = append(nonWitnessBytes, t.rawBytes[len(t.rawBytes)-4:]...) + + // We purposely call doublehashh here instead of doublehashraw as we don't have the + // serialization overhead and avoiding the 1 alloc is better in this case. + hash = chainhash.DoubleHashRaw(func(w io.Writer) error { + _, err := w.Write(nonWitnessBytes) + return err + }) + } else { + // If the raw bytes don't have the witness, we can use it directly. + // + // We purposely call doublehashh here instead of doublehashraw as we don't have the + // serialization overhead and avoiding the 1 alloc is better in this case. + hash = chainhash.DoubleHashRaw(func(w io.Writer) error { + _, err := w.Write(t.rawBytes) + return err + }) + } t.txHash = &hash return &hash } // WitnessHash returns the witness hash (wtxid) of the transaction. This is // equivalent to calling WitnessHash on the underlying wire.MsgTx, however it -// caches the result so subsequent calls are more efficient. +// caches the result so subsequent calls are more efficient. If the Tx has the +// raw bytes of the tx cached, it will use that and skip serialization. func (t *Tx) WitnessHash() *chainhash.Hash { // Return the cached hash if it has already been generated. if t.txHashWitness != nil { @@ -60,7 +107,13 @@ func (t *Tx) WitnessHash() *chainhash.Hash { } // Cache the hash and return it. - hash := t.msgTx.WitnessHash() + var hash chainhash.Hash + if len(t.rawBytes) > 0 { + hash = chainhash.DoubleHashH(t.rawBytes) + } else { + hash = t.msgTx.WitnessHash() + } + t.txHashWitness = &hash return &hash } @@ -99,6 +152,11 @@ func NewTx(msgTx *wire.MsgTx) *Tx { } } +// setBytes sets the raw bytes of the tx. +func (t *Tx) setBytes(bytes []byte) { + t.rawBytes = bytes +} + // NewTxFromBytes returns a new instance of a bitcoin transaction given the // serialized bytes. See Tx. func NewTxFromBytes(serializedTx []byte) (*Tx, error) { From 6e7680ad15358d50c9eb911aabd6f58f8840c6ed Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 15 Dec 2023 15:21:21 +0100 Subject: [PATCH 0916/1056] rpctest: fix formatting --- integration/rpctest/rpc_harness.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 2cb7e56d26..c4b63ba1e3 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -272,8 +272,8 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { // Create a test chain with the desired number of mature coinbase // outputs. if createTestChain && numMatureOutputs != 0 { - numToGenerate := (uint32(h.ActiveNet.CoinbaseMaturity) + - numMatureOutputs) + coinbaseMaturity := uint32(h.ActiveNet.CoinbaseMaturity) + numToGenerate := coinbaseMaturity + numMatureOutputs _, err := h.Client.Generate(numToGenerate) if err != nil { return err @@ -351,15 +351,18 @@ func (h *Harness) connectRPCClient() error { batchConf.HTTPPostMode = true for i := 0; i < h.MaxConnRetries; i++ { fail := false + timeout := time.Duration(i) * h.ConnectionRetryTimeout if client == nil { - if client, err = rpcclient.New(&rpcConf, h.handlers); err != nil { - time.Sleep(time.Duration(i) * h.ConnectionRetryTimeout) + client, err = rpcclient.New(&rpcConf, h.handlers) + if err != nil { + time.Sleep(timeout) fail = true } } if batchClient == nil { - if batchClient, err = rpcclient.NewBatch(&batchConf); err != nil { - time.Sleep(time.Duration(i) * h.ConnectionRetryTimeout) + batchClient, err = rpcclient.NewBatch(&batchConf) + if err != nil { + time.Sleep(timeout) fail = true } } From 323cf1e0b15d19b4fda25a65e0df7bbdb58d31b0 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 15 Dec 2023 15:22:46 +0100 Subject: [PATCH 0917/1056] rpctest: fix test node directory --- integration/rpctest/node.go | 52 +++++++++--------------------- integration/rpctest/rpc_harness.go | 6 ++-- 2 files changed, 17 insertions(+), 41 deletions(-) diff --git a/integration/rpctest/node.go b/integration/rpctest/node.go index f9e0d4c152..8dddc75001 100644 --- a/integration/rpctest/node.go +++ b/integration/rpctest/node.go @@ -6,7 +6,6 @@ package rpctest import ( "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -31,7 +30,7 @@ type nodeConfig struct { profile string debugLevel string extra []string - prefix string + nodeDir string exe string endpoint string @@ -41,7 +40,7 @@ type nodeConfig struct { } // newConfig returns a newConfig with all default values. -func newConfig(prefix, certFile, keyFile string, extra []string, +func newConfig(nodeDir, certFile, keyFile string, extra []string, customExePath string) (*nodeConfig, error) { var btcdPath string @@ -61,7 +60,7 @@ func newConfig(prefix, certFile, keyFile string, extra []string, rpcUser: "user", rpcPass: "pass", extra: extra, - prefix: prefix, + nodeDir: nodeDir, exe: btcdPath, endpoint: "ws", certFile: certFile, @@ -77,17 +76,9 @@ func newConfig(prefix, certFile, keyFile string, extra []string, // temporary data, and log directories which must be cleaned up with a call to // cleanup(). func (n *nodeConfig) setDefaults() error { - datadir, err := ioutil.TempDir("", n.prefix+"-data") - if err != nil { - return err - } - n.dataDir = datadir - logdir, err := ioutil.TempDir("", n.prefix+"-logs") - if err != nil { - return err - } - n.logDir = logdir - cert, err := ioutil.ReadFile(n.certFile) + n.dataDir = filepath.Join(n.nodeDir, "data") + n.logDir = filepath.Join(n.nodeDir, "logs") + cert, err := os.ReadFile(n.certFile) if err != nil { return err } @@ -163,22 +154,7 @@ func (n *nodeConfig) rpcConnConfig() rpc.ConnConfig { // String returns the string representation of this nodeConfig. func (n *nodeConfig) String() string { - return n.prefix -} - -// cleanup removes the tmp data and log directories. -func (n *nodeConfig) cleanup() error { - dirs := []string{ - n.logDir, - n.dataDir, - } - var err error - for _, dir := range dirs { - if err = os.RemoveAll(dir); err != nil { - log.Printf("Cannot remove dir %s: %v", dir, err) - } - } - return err + return n.nodeDir } // node houses the necessary state required to configure, launch, and manage a @@ -213,8 +189,7 @@ func (n *node) start() error { return err } - pid, err := os.Create(filepath.Join(n.dataDir, - fmt.Sprintf("%s.pid", n.config))) + pid, err := os.Create(filepath.Join(n.dataDir, "btcd.pid")) if err != nil { return err } @@ -258,7 +233,10 @@ func (n *node) cleanup() error { } } - return n.config.cleanup() + // Since the node's main data directory is passed in to the node config, + // it isn't our responsibility to clean it up. So we're done after + // removing the pid file. + return nil } // shutdown terminates the running btcd process, and cleans up all @@ -283,11 +261,11 @@ func genCertPair(certFile, keyFile string) error { } // Write cert and key files. - if err = ioutil.WriteFile(certFile, cert, 0666); err != nil { + if err = os.WriteFile(certFile, cert, 0666); err != nil { return err } - if err = ioutil.WriteFile(keyFile, key, 0600); err != nil { - os.Remove(certFile) + if err = os.WriteFile(keyFile, key, 0600); err != nil { + _ = os.Remove(certFile) return err } diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index c4b63ba1e3..506d6847fa 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -6,7 +6,6 @@ package rpctest import ( "fmt" - "io/ioutil" "net" "os" "path/filepath" @@ -152,8 +151,7 @@ func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers, return nil, err } - harnessID := strconv.Itoa(numTestInstances) - nodeTestData, err := ioutil.TempDir(testDir, "harness-"+harnessID) + nodeTestData, err := os.MkdirTemp(testDir, "rpc-node") if err != nil { return nil, err } @@ -173,7 +171,7 @@ func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers, extraArgs = append(extraArgs, miningAddr) config, err := newConfig( - "rpctest", certFile, keyFile, extraArgs, customExePath, + nodeTestData, certFile, keyFile, extraArgs, customExePath, ) if err != nil { return nil, err From d33ac28be1745875d397f6090ab464382d73a9f1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 15 Dec 2023 15:22:52 +0100 Subject: [PATCH 0918/1056] rpctest: add more context to errors --- integration/rpctest/rpc_harness.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 506d6847fa..b6c054e16b 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -246,10 +246,10 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { // Start the btcd node itself. This spawns a new process which will be // managed if err := h.node.start(); err != nil { - return err + return fmt.Errorf("error starting node: %w", err) } if err := h.connectRPCClient(); err != nil { - return err + return fmt.Errorf("error connecting RPC client: %w", err) } h.wallet.Start() @@ -370,7 +370,9 @@ func (h *Harness) connectRPCClient() error { } if client == nil || batchClient == nil { - return fmt.Errorf("connection timeout") + return fmt.Errorf("connection timeout, tried %d times with "+ + "timeout %v, last err: %w", h.MaxConnRetries, + h.ConnectionRetryTimeout, err) } h.Client = client From dd5f3bd513a3a60974c6a68721886f93f731e6b2 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Fri, 15 Dec 2023 15:23:04 +0100 Subject: [PATCH 0919/1056] rpctest: make test TCP ports unique per process This commit adds a new NextAvailablePortForProcess function that takes a process ID and then assures unique (non-occupied) port numbers are returned per process. This uses a temporary file that contains the latest used port and a secondary temporary lock file to assure only a single goroutine can request a new port at a time. The GenerateProcessUniqueListenerAddresses is intened to be used as a package-level override for the ListenAddressGenerator variable. We don't use it by default to make sure we don't break any existing assumptions. --- integration/rpctest/rpc_harness.go | 105 +++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index b6c054e16b..0b85232868 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -561,6 +561,111 @@ func NextAvailablePort() int { panic("no ports available for listening") } +// NextAvailablePortForProcess returns the first port that is available for +// listening by a new node, using a lock file to make sure concurrent access for +// parallel tasks within the same process don't re-use the same port. It panics +// if no port is found and the maximum available TCP port is reached. +func NextAvailablePortForProcess(pid int) int { + lockFile := filepath.Join( + os.TempDir(), fmt.Sprintf("rpctest-port-pid-%d.lock", pid), + ) + timeout := time.After(time.Second) + + var ( + lockFileHandle *os.File + err error + ) + for { + // Attempt to acquire the lock file. If it already exists, wait + // for a bit and retry. + lockFileHandle, err = os.OpenFile( + lockFile, os.O_CREATE|os.O_EXCL, 0600, + ) + if err == nil { + // Lock acquired. + break + } + + // Wait for a bit and retry. + select { + case <-timeout: + panic("timeout waiting for lock file") + case <-time.After(10 * time.Millisecond): + } + } + + // Release the lock file when we're done. + defer func() { + // Always close file first, Windows won't allow us to remove it + // otherwise. + _ = lockFileHandle.Close() + err := os.Remove(lockFile) + if err != nil { + panic(fmt.Errorf("couldn't remove lock file: %w", err)) + } + }() + + portFile := filepath.Join( + os.TempDir(), fmt.Sprintf("rpctest-port-pid-%d", pid), + ) + port, err := os.ReadFile(portFile) + if err != nil { + if !os.IsNotExist(err) { + panic(fmt.Errorf("error reading port file: %w", err)) + } + port = []byte(strconv.Itoa(int(defaultNodePort))) + } + + lastPort, err := strconv.Atoi(string(port)) + if err != nil { + panic(fmt.Errorf("error parsing port: %w", err)) + } + + // We take the next one. + lastPort++ + for lastPort < 65535 { + // If there are no errors while attempting to listen on this + // port, close the socket and return it as available. While it + // could be the case that some other process picks up this port + // between the time the socket is closed and it's reopened in + // the harness node, in practice in CI servers this seems much + // less likely than simply some other process already being + // bound at the start of the tests. + addr := fmt.Sprintf(ListenerFormat, lastPort) + l, err := net.Listen("tcp4", addr) + if err == nil { + err := l.Close() + if err == nil { + err := os.WriteFile( + portFile, + []byte(strconv.Itoa(lastPort)), 0600, + ) + if err != nil { + panic(fmt.Errorf("error updating "+ + "port file: %w", err)) + } + + return lastPort + } + } + lastPort++ + } + + // No ports available? Must be a mistake. + panic("no ports available for listening") +} + +// GenerateProcessUniqueListenerAddresses is a function that returns two +// listener addresses with unique ports per the given process id and should be +// used to overwrite rpctest's default generator which is prone to use colliding +// ports. +func GenerateProcessUniqueListenerAddresses(pid int) (string, string) { + port1 := NextAvailablePortForProcess(pid) + port2 := NextAvailablePortForProcess(pid) + return fmt.Sprintf(ListenerFormat, port1), + fmt.Sprintf(ListenerFormat, port2) +} + // baseDir is the directory path of the temp directory for all rpctest files. func baseDir() (string, error) { dirPath := filepath.Join(os.TempDir(), "btcd", "rpctest") From 7644d14078db276c31ab8f304e5edbbfd2699e4c Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 21 Dec 2023 09:14:06 +0100 Subject: [PATCH 0920/1056] blockchain: fix compilation issues with 32bit systems --- blockchain/sizehelper.go | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/blockchain/sizehelper.go b/blockchain/sizehelper.go index 15a9ccd8a9..4904a8e4c3 100644 --- a/blockchain/sizehelper.go +++ b/blockchain/sizehelper.go @@ -63,14 +63,32 @@ const ( loadFactorNum = 13 loadFactorDen = 2 - // maxAlloc is the maximum size of an allocation. On 64-bit, - // it's theoretically possible to allocate 1<> 63) / 2 + + // PtrSize is the size of a pointer in bytes - unsafe.Sizeof(uintptr(0)) + // but as an ideal constant. It is also the size of the machine's native + // word size (that is, 4 on 32-bit systems, 8 on 64-bit). + PtrSize = 4 << (^uintptr(0) >> 63) + + // heapAddrBits is the number of bits in a heap address that's actually + // available for memory allocation. // - // NOTE (kcalvinalvin): I just took the constant for a 64 bit system. - maxAlloc = 281474976710656 + // NOTE (guggero): For 64-bit systems, we just assume 40 bits of address + // space available, as that seems to be the lowest common denominator. + // See heapAddrBits in runtime/malloc.go of the standard library for + // more details + heapAddrBits = 32 + (_64bit * 8) + + // maxAlloc is the maximum size of an allocation on the heap. + // + // NOTE(guggero): With the somewhat simplified heapAddrBits calculation + // above, this will currently limit the maximum allocation size of the + // UTXO cache to around 300GiB on 64-bit systems. This should be more + // than enough for the foreseeable future, but if we ever need to + // increase it, we should probably use the same calculation as the + // standard library. + maxAlloc = (1 << heapAddrBits) - (1-_64bit)*1 ) var class_to_size = [_NumSizeClasses]uint16{0, 8, 16, 24, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 256, 288, 320, 352, 384, 416, 448, 480, 512, 576, 640, 704, 768, 896, 1024, 1152, 1280, 1408, 1536, 1792, 2048, 2304, 2688, 3072, 3200, 3456, 4096, 4864, 5376, 6144, 6528, 6784, 6912, 8192, 9472, 9728, 10240, 10880, 12288, 13568, 14336, 16384, 18432, 19072, 20480, 21760, 24576, 27264, 28672, 32768} @@ -175,7 +193,7 @@ func calculateMinEntries(totalBytes int, bucketSize int) int { // mulUintptr returns a * b and whether the multiplication overflowed. // On supported platforms this is an intrinsic lowered by the compiler. func mulUintptr(a, b uintptr) (uintptr, bool) { - if a|b < 1<<(4*8) || a == 0 { + if a|b < 1<<(4*PtrSize) || a == 0 { return a * b, false } overflow := b > MaxUintptr/a From 56de9ca878e797869553efd720846087a88e7434 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 Dec 2023 17:47:11 -0800 Subject: [PATCH 0921/1056] btcutil: align new serialization caching logic w/ codebase style --- btcutil/block.go | 30 ++++++++++++++++++++++-------- btcutil/tx.go | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/btcutil/block.go b/btcutil/block.go index 52c909192b..7f8d8786e3 100644 --- a/btcutil/block.go +++ b/btcutil/block.go @@ -155,7 +155,9 @@ func (b *Block) Transactions() []*Tx { } // Offset of each tx. 80 accounts for the block header size. - offset := 80 + wire.VarIntSerializeSize(uint64(len(b.msgBlock.Transactions))) + offset := 80 + wire.VarIntSerializeSize( + uint64(len(b.msgBlock.Transactions)), + ) // Generate and cache the wrapped transactions for all that haven't // already been done. @@ -168,12 +170,16 @@ func (b *Block) Transactions() []*Tx { // The block may not always have the serializedBlock. if len(b.serializedBlock) > 0 { - // This allows for the reuse of the already serialized tx. - newTx.setBytes(b.serializedBlock[offset : offset+size]) + // This allows for the reuse of the already + // serialized tx. + newTx.setBytes( + b.serializedBlock[offset : offset+size], + ) // Increment offset for this block. offset += size } + b.transactions[i] = newTx } } @@ -248,9 +254,12 @@ func NewBlockFromBytes(serializedBlock []byte) (*Block, error) { return nil, err } b.serializedBlock = serializedBlock - // This initializes []btcutil.Tx to have the serialized raw transactions cached. - // Helps speed up things like generating the txhash. + + // This initializes []btcutil.Tx to have the serialized raw + // transactions cached. Helps speed up things like generating the + // txhash. b.Transactions() + return b, nil } @@ -273,14 +282,19 @@ func NewBlockFromReader(r io.Reader) (*Block, error) { // NewBlockFromBlockAndBytes returns a new instance of a bitcoin block given // an underlying wire.MsgBlock and the serialized bytes for it. See Block. -func NewBlockFromBlockAndBytes(msgBlock *wire.MsgBlock, serializedBlock []byte) *Block { +func NewBlockFromBlockAndBytes(msgBlock *wire.MsgBlock, + serializedBlock []byte) *Block { + b := &Block{ msgBlock: msgBlock, serializedBlock: serializedBlock, blockHeight: BlockHeightUnknown, } - // This initializes []btcutil.Tx to have the serialized raw transactions cached. - // Helps speed up things like generating the txhash. + + // This initializes []btcutil.Tx to have the serialized raw + // transactions cached. Helps speed up things like generating the + // txhash. b.Transactions() + return b } diff --git a/btcutil/tx.go b/btcutil/tx.go index abc055acbe..4f26befe32 100644 --- a/btcutil/tx.go +++ b/btcutil/tx.go @@ -36,10 +36,10 @@ func (t *Tx) MsgTx() *wire.MsgTx { return t.msgTx } -// Hash returns the hash of the transaction. This is equivalent to -// calling TxHash on the underlying wire.MsgTx, however it caches the -// result so subsequent calls are more efficient. If the Tx has the -// raw bytes of the tx cached, it will use that and skip serialization. +// Hash returns the hash of the transaction. This is equivalent to calling +// TxHash on the underlying wire.MsgTx, however it caches the result so +// subsequent calls are more efficient. If the Tx has the raw bytes of the tx +// cached, it will use that and skip serialization. func (t *Tx) Hash() *chainhash.Hash { // Return the cached hash if it has already been generated. if t.txHash != nil { @@ -53,45 +53,57 @@ func (t *Tx) Hash() *chainhash.Hash { return &hash } - // If we have the raw bytes, then don't call msgTx.TxHash as that has the - // overhead of serialization. + // If we have the raw bytes, then don't call msgTx.TxHash as that has + // the overhead of serialization. Instead, we can take the existing + // serialized bytes and hash them to speed things up. var hash chainhash.Hash if t.HasWitness() { - // If the raw bytes contain the witness, we must strip it out before - // calculating the hash. + // If the raw bytes contain the witness, we must strip it out + // before calculating the hash. baseSize := t.msgTx.SerializeSizeStripped() nonWitnessBytes := make([]byte, 0, baseSize) // Append the version bytes. offset := 4 - nonWitnessBytes = append(nonWitnessBytes, t.rawBytes[:offset]...) + nonWitnessBytes = append( + nonWitnessBytes, t.rawBytes[:offset]..., + ) // Append the input and output bytes. -8 to account for the // version bytes and the locktime bytes. // // Skip the 2 bytes for the witness encoding. offset += 2 - nonWitnessBytes = append(nonWitnessBytes, t.rawBytes[offset:offset+baseSize-8]...) + nonWitnessBytes = append( + nonWitnessBytes, + t.rawBytes[offset:offset+baseSize-8]..., + ) // Append the last 4 bytes which are the locktime bytes. - nonWitnessBytes = append(nonWitnessBytes, t.rawBytes[len(t.rawBytes)-4:]...) + nonWitnessBytes = append( + nonWitnessBytes, t.rawBytes[len(t.rawBytes)-4:]..., + ) - // We purposely call doublehashh here instead of doublehashraw as we don't have the - // serialization overhead and avoiding the 1 alloc is better in this case. + // We purposely call doublehashh here instead of doublehashraw + // as we don't have the serialization overhead and avoiding the + // 1 alloc is better in this case. hash = chainhash.DoubleHashRaw(func(w io.Writer) error { _, err := w.Write(nonWitnessBytes) return err }) } else { - // If the raw bytes don't have the witness, we can use it directly. + // If the raw bytes don't have the witness, we can use it + // directly. // - // We purposely call doublehashh here instead of doublehashraw as we don't have the - // serialization overhead and avoiding the 1 alloc is better in this case. + // We purposely call doublehashh here instead of doublehashraw + // as we don't have the serialization overhead and avoiding the + // 1 alloc is better in this case. hash = chainhash.DoubleHashRaw(func(w io.Writer) error { _, err := w.Write(t.rawBytes) return err }) } + t.txHash = &hash return &hash } From e102a81268be375eb74092fb7416108269f50fc4 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 Dec 2023 18:07:03 -0800 Subject: [PATCH 0922/1056] btcutil: add benchmarks for Hash + WitnessHash --- btcutil/bench_test.go | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 btcutil/bench_test.go diff --git a/btcutil/bench_test.go b/btcutil/bench_test.go new file mode 100644 index 0000000000..c1f52da5b7 --- /dev/null +++ b/btcutil/bench_test.go @@ -0,0 +1,80 @@ +package btcutil_test + +import ( + "testing" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +var ( + bencHash *chainhash.Hash +) + +// BenchmarkTxHash benchmarks the performance of calculating the hash of a +// transaction. +func BenchmarkTxHash(b *testing.B) { + // Make a new block from the test block, we'll then call the Bytes + // function to cache the serialized block. Afterwards we all + // Transactions to populate the serialization cache. + testBlock := btcutil.NewBlock(&Block100000) + _, _ = testBlock.Bytes() + + // The second transaction in the block has no witness data. The first + // does however. + testTx := testBlock.Transactions()[1] + testTx2 := testBlock.Transactions()[0] + + // Run a benchmark for the portion that needs to strip the non-witness + // data from the transaction. + b.Run("tx_hash_has_witness", func(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + + var txHash *chainhash.Hash + for i := 0; i < b.N; i++ { + txHash = testTx2.Hash() + } + + bencHash = txHash + }) + + // Next, run it for the portion that can just hash the bytes directly. + b.Run("tx_hash_no_witness", func(b *testing.B) { + b.ResetTimer() + b.ReportAllocs() + + var txHash *chainhash.Hash + for i := 0; i < b.N; i++ { + txHash = testTx.Hash() + } + + bencHash = txHash + }) + +} + +// BenchmarkTxWitnessHash benchmarks the performance of calculating the hash of +// a transaction. +func BenchmarkTxWitnessHash(b *testing.B) { + // Make a new block from the test block, we'll then call the Bytes + // function to cache the serialized block. Afterwards we all + // Transactions to populate the serialization cache. + testBlock := btcutil.NewBlock(&Block100000) + _, _ = testBlock.Bytes() + + // The first transaction in the block has been modified to have witness + // data. + testTx := testBlock.Transactions()[0] + + b.ResetTimer() + b.ReportAllocs() + + var txHash *chainhash.Hash + for i := 0; i < b.N; i++ { + txHash = testTx.WitnessHash() + } + + bencHash = txHash + +} From b0e9636689d9283e034f548a55e60342b5742b3f Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 Dec 2023 18:37:43 -0800 Subject: [PATCH 0923/1056] wire: consistently use defer for returning scratch buffers --- wire/bench_test.go | 63 +++++++++++++++++------------------------ wire/common.go | 54 +++++++++++++++++++++++------------ wire/msgblock.go | 25 ++++------------ wire/msgcfcheckpt.go | 10 ++----- wire/msgcfheaders.go | 12 ++------ wire/msgcfilter.go | 10 +++---- wire/msggetblocks.go | 10 +++---- wire/msggetcfcheckpt.go | 8 +++--- wire/msggetcfheaders.go | 10 +++---- wire/msggetcfilters.go | 10 +++---- wire/msggetdata.go | 11 +++---- wire/msggetheaders.go | 8 +++--- wire/msgheaders.go | 16 +++-------- wire/msginv.go | 11 +++---- wire/msgmerkleblock.go | 16 +++-------- wire/msgnotfound.go | 11 +++---- wire/msgreject.go | 12 +++----- wire/msgtx.go | 22 ++++++++------ wire/netaddress.go | 6 ++-- 19 files changed, 138 insertions(+), 187 deletions(-) diff --git a/wire/bench_test.go b/wire/bench_test.go index d612728c6b..d19dd775f2 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -8,6 +8,7 @@ import ( "bytes" "compress/bzip2" "fmt" + "io" "io/ioutil" "net" "os" @@ -66,7 +67,7 @@ func BenchmarkWriteVarInt1(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - WriteVarInt(ioutil.Discard, 0, 1) + WriteVarInt(io.Discard, 0, 1) } } @@ -76,7 +77,7 @@ func BenchmarkWriteVarInt3(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - WriteVarInt(ioutil.Discard, 0, 65535) + WriteVarInt(io.Discard, 0, 65535) } } @@ -86,7 +87,7 @@ func BenchmarkWriteVarInt5(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - WriteVarInt(ioutil.Discard, 0, 4294967295) + WriteVarInt(io.Discard, 0, 4294967295) } } @@ -96,7 +97,7 @@ func BenchmarkWriteVarInt9(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - WriteVarInt(ioutil.Discard, 0, 18446744073709551615) + WriteVarInt(io.Discard, 0, 18446744073709551615) } } @@ -159,7 +160,7 @@ func BenchmarkWriteVarIntBuf1(b *testing.B) { buffer := binarySerializer.Borrow() for i := 0; i < b.N; i++ { - WriteVarIntBuf(ioutil.Discard, 0, 1, buffer) + WriteVarIntBuf(io.Discard, 0, 1, buffer) } binarySerializer.Return(buffer) } @@ -171,7 +172,7 @@ func BenchmarkWriteVarIntBuf3(b *testing.B) { buffer := binarySerializer.Borrow() for i := 0; i < b.N; i++ { - WriteVarIntBuf(ioutil.Discard, 0, 65535, buffer) + WriteVarIntBuf(io.Discard, 0, 65535, buffer) } binarySerializer.Return(buffer) } @@ -183,7 +184,7 @@ func BenchmarkWriteVarIntBuf5(b *testing.B) { buffer := binarySerializer.Borrow() for i := 0; i < b.N; i++ { - WriteVarIntBuf(ioutil.Discard, 0, 4294967295, buffer) + WriteVarIntBuf(io.Discard, 0, 4294967295, buffer) } binarySerializer.Return(buffer) } @@ -195,7 +196,7 @@ func BenchmarkWriteVarIntBuf9(b *testing.B) { buffer := binarySerializer.Borrow() for i := 0; i < b.N; i++ { - WriteVarIntBuf(ioutil.Discard, 0, 18446744073709551615, buffer) + WriteVarIntBuf(io.Discard, 0, 18446744073709551615, buffer) } binarySerializer.Return(buffer) } @@ -292,7 +293,7 @@ func BenchmarkWriteVarStr4(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - WriteVarString(ioutil.Discard, 0, "test") + WriteVarString(io.Discard, 0, "test") } } @@ -302,7 +303,7 @@ func BenchmarkWriteVarStr10(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { - WriteVarString(ioutil.Discard, 0, "test012345") + WriteVarString(io.Discard, 0, "test012345") } } @@ -343,7 +344,7 @@ func BenchmarkWriteVarStrBuf4(b *testing.B) { buf := binarySerializer.Borrow() for i := 0; i < b.N; i++ { - writeVarStringBuf(ioutil.Discard, 0, "test", buf) + writeVarStringBuf(io.Discard, 0, "test", buf) } binarySerializer.Return(buf) } @@ -355,7 +356,7 @@ func BenchmarkWriteVarStrBuf10(b *testing.B) { buf := binarySerializer.Borrow() for i := 0; i < b.N; i++ { - writeVarStringBuf(ioutil.Discard, 0, "test012345", buf) + writeVarStringBuf(io.Discard, 0, "test012345", buf) } binarySerializer.Return(buf) } @@ -392,7 +393,7 @@ func BenchmarkWriteOutPoint(b *testing.B) { Index: 0, } for i := 0; i < b.N; i++ { - WriteOutPoint(ioutil.Discard, 0, 0, op) + WriteOutPoint(io.Discard, 0, 0, op) } } @@ -407,7 +408,7 @@ func BenchmarkWriteOutPointBuf(b *testing.B) { Index: 0, } for i := 0; i < b.N; i++ { - writeOutPointBuf(ioutil.Discard, 0, 0, op, buf) + writeOutPointBuf(io.Discard, 0, 0, op, buf) } binarySerializer.Return(buf) } @@ -480,7 +481,7 @@ func BenchmarkWriteTxOut(b *testing.B) { txOut := blockOne.Transactions[0].TxOut[0] for i := 0; i < b.N; i++ { - WriteTxOut(ioutil.Discard, 0, 0, txOut) + WriteTxOut(io.Discard, 0, 0, txOut) } } @@ -492,7 +493,7 @@ func BenchmarkWriteTxOutBuf(b *testing.B) { buf := binarySerializer.Borrow() txOut := blockOne.Transactions[0].TxOut[0] for i := 0; i < b.N; i++ { - WriteTxOutBuf(ioutil.Discard, 0, 0, txOut, buf) + WriteTxOutBuf(io.Discard, 0, 0, txOut, buf) } binarySerializer.Return(buf) } @@ -533,7 +534,7 @@ func BenchmarkWriteTxIn(b *testing.B) { buf := binarySerializer.Borrow() txIn := blockOne.Transactions[0].TxIn[0] for i := 0; i < b.N; i++ { - writeTxInBuf(ioutil.Discard, 0, 0, txIn, buf) + writeTxInBuf(io.Discard, 0, 0, txIn, buf) } binarySerializer.Return(buf) } @@ -608,15 +609,9 @@ func BenchmarkDeserializeTxLarge(b *testing.B) { } func BenchmarkDeserializeBlock(b *testing.B) { - f, err := os.Open( + buf, err := os.ReadFile( "testdata/block-00000000000000000021868c2cefc52a480d173c849412fe81c4e5ab806f94ab.blk", ) - if err != nil { - b.Fatalf("Failed to open block file: %v", err) - } - defer f.Close() - - buf, err := ioutil.ReadAll(f) if err != nil { b.Fatalf("Failed to read block data: %v", err) } @@ -633,15 +628,9 @@ func BenchmarkDeserializeBlock(b *testing.B) { } func BenchmarkSerializeBlock(b *testing.B) { - f, err := os.Open( + buf, err := os.ReadFile( "testdata/block-00000000000000000021868c2cefc52a480d173c849412fe81c4e5ab806f94ab.blk", ) - if err != nil { - b.Fatalf("Failed to open block file: %v", err) - } - defer f.Close() - - buf, err := ioutil.ReadAll(f) if err != nil { b.Fatalf("Failed to read block data: %v", err) } @@ -656,7 +645,7 @@ func BenchmarkSerializeBlock(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - block.Serialize(ioutil.Discard) + block.Serialize(io.Discard) } } @@ -667,7 +656,7 @@ func BenchmarkSerializeTx(b *testing.B) { tx := blockOne.Transactions[0] for i := 0; i < b.N; i++ { - tx.Serialize(ioutil.Discard) + tx.Serialize(io.Discard) } } @@ -710,7 +699,7 @@ func BenchmarkSerializeTxSmall(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - tx.Serialize(ioutil.Discard) + tx.Serialize(io.Discard) } } @@ -736,7 +725,7 @@ func BenchmarkSerializeTxLarge(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - tx.Serialize(ioutil.Discard) + tx.Serialize(io.Discard) } } @@ -805,7 +794,7 @@ func BenchmarkWriteBlockHeader(b *testing.B) { header := blockOne.Header for i := 0; i < b.N; i++ { - writeBlockHeader(ioutil.Discard, 0, &header) + writeBlockHeader(io.Discard, 0, &header) } } @@ -817,7 +806,7 @@ func BenchmarkWriteBlockHeaderBuf(b *testing.B) { buf := binarySerializer.Borrow() header := blockOne.Header for i := 0; i < b.N; i++ { - writeBlockHeaderBuf(ioutil.Discard, 0, &header, buf) + writeBlockHeaderBuf(io.Discard, 0, &header, buf) } binarySerializer.Return(buf) } diff --git a/wire/common.go b/wire/common.go index 8123e471b9..d3a82c46c0 100644 --- a/wire/common.go +++ b/wire/common.go @@ -73,12 +73,13 @@ func (l binaryFreeList) Return(buf []byte) { // free list and returns it as a uint8. func (l binaryFreeList) Uint8(r io.Reader) (uint8, error) { buf := l.Borrow()[:1] + defer l.Return(buf) + if _, err := io.ReadFull(r, buf); err != nil { - l.Return(buf) return 0, err } rv := buf[0] - l.Return(buf) + return rv, nil } @@ -87,12 +88,13 @@ func (l binaryFreeList) Uint8(r io.Reader) (uint8, error) { // the resulting uint16. func (l binaryFreeList) Uint16(r io.Reader, byteOrder binary.ByteOrder) (uint16, error) { buf := l.Borrow()[:2] + defer l.Return(buf) + if _, err := io.ReadFull(r, buf); err != nil { - l.Return(buf) return 0, err } rv := byteOrder.Uint16(buf) - l.Return(buf) + return rv, nil } @@ -101,12 +103,13 @@ func (l binaryFreeList) Uint16(r io.Reader, byteOrder binary.ByteOrder) (uint16, // the resulting uint32. func (l binaryFreeList) Uint32(r io.Reader, byteOrder binary.ByteOrder) (uint32, error) { buf := l.Borrow()[:4] + defer l.Return(buf) + if _, err := io.ReadFull(r, buf); err != nil { - l.Return(buf) return 0, err } rv := byteOrder.Uint32(buf) - l.Return(buf) + return rv, nil } @@ -115,12 +118,13 @@ func (l binaryFreeList) Uint32(r io.Reader, byteOrder binary.ByteOrder) (uint32, // the resulting uint64. func (l binaryFreeList) Uint64(r io.Reader, byteOrder binary.ByteOrder) (uint64, error) { buf := l.Borrow()[:8] + defer l.Return(buf) + if _, err := io.ReadFull(r, buf); err != nil { - l.Return(buf) return 0, err } rv := byteOrder.Uint64(buf) - l.Return(buf) + return rv, nil } @@ -128,9 +132,11 @@ func (l binaryFreeList) Uint64(r io.Reader, byteOrder binary.ByteOrder) (uint64, // writes the resulting byte to the given writer. func (l binaryFreeList) PutUint8(w io.Writer, val uint8) error { buf := l.Borrow()[:1] + defer l.Return(buf) + buf[0] = val _, err := w.Write(buf) - l.Return(buf) + return err } @@ -139,9 +145,11 @@ func (l binaryFreeList) PutUint8(w io.Writer, val uint8) error { // writer. func (l binaryFreeList) PutUint16(w io.Writer, byteOrder binary.ByteOrder, val uint16) error { buf := l.Borrow()[:2] + defer l.Return(buf) + byteOrder.PutUint16(buf, val) _, err := w.Write(buf) - l.Return(buf) + return err } @@ -150,9 +158,11 @@ func (l binaryFreeList) PutUint16(w io.Writer, byteOrder binary.ByteOrder, val u // writer. func (l binaryFreeList) PutUint32(w io.Writer, byteOrder binary.ByteOrder, val uint32) error { buf := l.Borrow()[:4] + defer l.Return(buf) + byteOrder.PutUint32(buf, val) _, err := w.Write(buf) - l.Return(buf) + return err } @@ -161,9 +171,11 @@ func (l binaryFreeList) PutUint32(w io.Writer, byteOrder binary.ByteOrder, val u // writer. func (l binaryFreeList) PutUint64(w io.Writer, byteOrder binary.ByteOrder, val uint64) error { buf := l.Borrow()[:8] + defer l.Return(buf) + byteOrder.PutUint64(buf, val) _, err := w.Write(buf) - l.Return(buf) + return err } @@ -475,8 +487,9 @@ func writeElements(w io.Writer, elements ...interface{}) error { // ReadVarInt reads a variable length integer from r and returns it as a uint64. func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + n, err := ReadVarIntBuf(r, pver, buf) - binarySerializer.Return(buf) return n, err } @@ -545,8 +558,9 @@ func ReadVarIntBuf(r io.Reader, pver uint32, buf []byte) (uint64, error) { // on its value. func WriteVarInt(w io.Writer, pver uint32, val uint64) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := WriteVarIntBuf(w, pver, val, buf) - binarySerializer.Return(buf) return err } @@ -616,8 +630,9 @@ func VarIntSerializeSize(val uint64) int { // attacks and forced panics through malformed messages. func ReadVarString(r io.Reader, pver uint32) (string, error) { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + str, err := readVarStringBuf(r, pver, buf) - binarySerializer.Return(buf) return str, err } @@ -661,8 +676,9 @@ func readVarStringBuf(r io.Reader, pver uint32, buf []byte) (string, error) { // itself. func WriteVarString(w io.Writer, pver uint32, str string) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := writeVarStringBuf(w, pver, str, buf) - binarySerializer.Return(buf) return err } @@ -696,8 +712,9 @@ func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + b, err := ReadVarBytesBuf(r, pver, buf, maxAllowed, fieldName) - binarySerializer.Return(buf) return b, err } @@ -739,8 +756,9 @@ func ReadVarBytesBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, // containing the number of bytes, followed by the bytes themselves. func WriteVarBytes(w io.Writer, pver uint32, bytes []byte) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := WriteVarBytesBuf(w, pver, bytes, buf) - binarySerializer.Return(buf) return err } diff --git a/wire/msgblock.go b/wire/msgblock.go index 6f63e0abd7..77585e3fb6 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -63,16 +63,15 @@ func (msg *MsgBlock) ClearTransactions() { // opposed to decoding blocks from the wire. func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) err := readBlockHeaderBuf(r, pver, &msg.Header, buf) if err != nil { - binarySerializer.Return(buf) return err } txCount, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } @@ -80,26 +79,23 @@ func (msg *MsgBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) er // It would be possible to cause memory exhaustion and panics without // a sane upper bound on this count. if txCount > maxTxPerBlock { - binarySerializer.Return(buf) str := fmt.Sprintf("too many transactions to fit into a block "+ "[count %d, max %d]", txCount, maxTxPerBlock) return messageError("MsgBlock.BtcDecode", str) } scriptBuf := scriptPool.Borrow() + defer scriptPool.Return(scriptBuf) + msg.Transactions = make([]*MsgTx, 0, txCount) for i := uint64(0); i < txCount; i++ { tx := MsgTx{} err := tx.btcDecode(r, pver, enc, buf, scriptBuf[:]) if err != nil { - scriptPool.Return(scriptBuf) - binarySerializer.Return(buf) return err } msg.Transactions = append(msg.Transactions, &tx) } - scriptPool.Return(scriptBuf) - binarySerializer.Return(buf) return nil } @@ -140,19 +136,18 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { fullLen := r.Len() buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) // At the current time, there is no difference between the wire encoding // at protocol version 0 and the stable long-term storage format. As // a result, make use of existing wire protocol functions. err := readBlockHeaderBuf(r, 0, &msg.Header, buf) if err != nil { - binarySerializer.Return(buf) return nil, err } txCount, err := ReadVarIntBuf(r, 0, buf) if err != nil { - binarySerializer.Return(buf) return nil, err } @@ -160,13 +155,13 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { // It would be possible to cause memory exhaustion and panics without // a sane upper bound on this count. if txCount > maxTxPerBlock { - binarySerializer.Return(buf) str := fmt.Sprintf("too many transactions to fit into a block "+ "[count %d, max %d]", txCount, maxTxPerBlock) return nil, messageError("MsgBlock.DeserializeTxLoc", str) } scriptBuf := scriptPool.Borrow() + defer scriptPool.Return(scriptBuf) // Deserialize each transaction while keeping track of its location // within the byte stream. @@ -177,15 +172,11 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { tx := MsgTx{} err := tx.btcDecode(r, 0, WitnessEncoding, buf, scriptBuf[:]) if err != nil { - scriptPool.Return(scriptBuf) - binarySerializer.Return(buf) return nil, err } msg.Transactions = append(msg.Transactions, &tx) txLocs[i].TxLen = (fullLen - r.Len()) - txLocs[i].TxStart } - scriptPool.Return(scriptBuf) - binarySerializer.Return(buf) return txLocs, nil } @@ -196,29 +187,25 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) { // database, as opposed to encoding blocks for the wire. func (msg *MsgBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) err := writeBlockHeaderBuf(w, pver, &msg.Header, buf) if err != nil { - binarySerializer.Return(buf) return err } err = WriteVarIntBuf(w, pver, uint64(len(msg.Transactions)), buf) if err != nil { - binarySerializer.Return(buf) return err } for _, tx := range msg.Transactions { err = tx.btcEncode(w, pver, enc, buf) if err != nil { - binarySerializer.Return(buf) return err } } - binarySerializer.Return(buf) - return nil } diff --git a/wire/msgcfcheckpt.go b/wire/msgcfcheckpt.go index da13666180..397a3c137a 100644 --- a/wire/msgcfcheckpt.go +++ b/wire/msgcfcheckpt.go @@ -53,27 +53,24 @@ func (msg *MsgCFCheckpt) AddCFHeader(header *chainhash.Hash) error { // This is part of the Message interface implementation. func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) // Read filter type if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return err } msg.FilterType = FilterType(buf[0]) // Read stop hash if _, err := io.ReadFull(r, msg.StopHash[:]); err != nil { - binarySerializer.Return(buf) return err } // Read number of filter headers count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) // Refuse to decode an insane number of cfheaders. if count > maxCFHeadersLen { @@ -99,17 +96,16 @@ func (msg *MsgCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) // This is part of the Message interface implementation. func (msg *MsgCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) // Write filter type buf[0] = byte(msg.FilterType) if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } // Write stop hash if _, err := w.Write(msg.StopHash[:]); err != nil { - binarySerializer.Return(buf) return err } @@ -117,10 +113,8 @@ func (msg *MsgCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) count := len(msg.FilterHeaders) err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) for _, cfh := range msg.FilterHeaders { _, err := w.Write(cfh[:]) diff --git a/wire/msgcfheaders.go b/wire/msgcfheaders.go index 644cf36a94..e1af2c324d 100644 --- a/wire/msgcfheaders.go +++ b/wire/msgcfheaders.go @@ -49,33 +49,29 @@ func (msg *MsgCFHeaders) AddCFHash(hash *chainhash.Hash) error { // This is part of the Message interface implementation. func (msg *MsgCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) // Read filter type if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return err } msg.FilterType = FilterType(buf[0]) // Read stop hash if _, err := io.ReadFull(r, msg.StopHash[:]); err != nil { - binarySerializer.Return(buf) return err } // Read prev filter header if _, err := io.ReadFull(r, msg.PrevFilterHeader[:]); err != nil { - binarySerializer.Return(buf) return err } // Read number of filter headers count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) // Limit to max committed filter headers per message. if count > MaxCFHeadersPerMsg { @@ -112,32 +108,28 @@ func (msg *MsgCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) // Write filter type buf[0] = byte(msg.FilterType) if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } // Write stop hash if _, err := w.Write(msg.StopHash[:]); err != nil { - binarySerializer.Return(buf) return err } // Write prev filter header if _, err := w.Write(msg.PrevFilterHeader[:]); err != nil { - binarySerializer.Return(buf) return err } err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) for _, cfh := range msg.FilterHashes { _, err := w.Write(cfh[:]) diff --git a/wire/msgcfilter.go b/wire/msgcfilter.go index d691013bda..d7cf16378a 100644 --- a/wire/msgcfilter.go +++ b/wire/msgcfilter.go @@ -39,15 +39,15 @@ type MsgCFilter struct { func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { // Read filter type buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return err } msg.FilterType = FilterType(buf[0]) // Read the hash of the filter's block if _, err := io.ReadFull(r, msg.BlockHash[:]); err != nil { - binarySerializer.Return(buf) return err } @@ -55,7 +55,6 @@ func (msg *MsgCFilter) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) er var err error msg.Data, err = ReadVarBytesBuf(r, pver, buf, MaxCFilterDataSize, "cfilter data") - binarySerializer.Return(buf) return err } @@ -70,19 +69,18 @@ func (msg *MsgCFilter) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) er } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + buf[0] = byte(msg.FilterType) if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } if _, err := w.Write(msg.BlockHash[:]); err != nil { - binarySerializer.Return(buf) return err } err := WriteVarBytesBuf(w, pver, msg.Data, buf) - binarySerializer.Return(buf) return err } diff --git a/wire/msggetblocks.go b/wire/msggetblocks.go index b6943be415..da8bb878d2 100644 --- a/wire/msggetblocks.go +++ b/wire/msggetblocks.go @@ -52,8 +52,9 @@ func (msg *MsgGetBlocks) AddBlockLocatorHash(hash *chainhash.Hash) error { // This is part of the Message interface implementation. func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + if _, err := io.ReadFull(r, buf[:4]); err != nil { - binarySerializer.Return(buf) return err } msg.ProtocolVersion = littleEndian.Uint32(buf[:4]) @@ -61,10 +62,8 @@ func (msg *MsgGetBlocks) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding // Read num block locator hashes and limit to max. count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) if count > MaxBlockLocatorsPerMsg { str := fmt.Sprintf("too many block locator hashes for message "+ @@ -100,18 +99,17 @@ func (msg *MsgGetBlocks) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + littleEndian.PutUint32(buf[:4], msg.ProtocolVersion) if _, err := w.Write(buf[:4]); err != nil { - binarySerializer.Return(buf) return err } err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) for _, hash := range msg.BlockLocatorHashes { _, err := w.Write(hash[:]) diff --git a/wire/msggetcfcheckpt.go b/wire/msggetcfcheckpt.go index c503fa24e0..c57aa5adaf 100644 --- a/wire/msggetcfcheckpt.go +++ b/wire/msggetcfcheckpt.go @@ -22,12 +22,12 @@ type MsgGetCFCheckpt struct { // This is part of the Message interface implementation. func (msg *MsgGetCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return err } msg.FilterType = FilterType(buf[0]) - binarySerializer.Return(buf) _, err := io.ReadFull(r, msg.StopHash[:]) return err @@ -37,12 +37,12 @@ func (msg *MsgGetCFCheckpt) BtcDecode(r io.Reader, pver uint32, _ MessageEncodin // This is part of the Message interface implementation. func (msg *MsgGetCFCheckpt) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + buf[0] = byte(msg.FilterType) if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) _, err := w.Write(msg.StopHash[:]) return err diff --git a/wire/msggetcfheaders.go b/wire/msggetcfheaders.go index 1b1a904b44..e26f439808 100644 --- a/wire/msggetcfheaders.go +++ b/wire/msggetcfheaders.go @@ -23,18 +23,17 @@ type MsgGetCFHeaders struct { // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return err } msg.FilterType = FilterType(buf[0]) if _, err := io.ReadFull(r, buf[:4]); err != nil { - binarySerializer.Return(buf) return err } msg.StartHeight = littleEndian.Uint32(buf[:4]) - binarySerializer.Return(buf) _, err := io.ReadFull(r, msg.StopHash[:]) return err @@ -44,18 +43,17 @@ func (msg *MsgGetCFHeaders) BtcDecode(r io.Reader, pver uint32, _ MessageEncodin // This is part of the Message interface implementation. func (msg *MsgGetCFHeaders) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + buf[0] = byte(msg.FilterType) if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } littleEndian.PutUint32(buf[:4], msg.StartHeight) if _, err := w.Write(buf[:4]); err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) _, err := w.Write(msg.StopHash[:]) return err diff --git a/wire/msggetcfilters.go b/wire/msggetcfilters.go index ba76b653ba..1e6e225587 100644 --- a/wire/msggetcfilters.go +++ b/wire/msggetcfilters.go @@ -27,18 +27,17 @@ type MsgGetCFilters struct { // This is part of the Message interface implementation. func (msg *MsgGetCFilters) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return err } msg.FilterType = FilterType(buf[0]) if _, err := io.ReadFull(r, buf[:4]); err != nil { - binarySerializer.Return(buf) return err } msg.StartHeight = littleEndian.Uint32(buf[:4]) - binarySerializer.Return(buf) _, err := io.ReadFull(r, msg.StopHash[:]) return err @@ -48,18 +47,17 @@ func (msg *MsgGetCFilters) BtcDecode(r io.Reader, pver uint32, _ MessageEncoding // This is part of the Message interface implementation. func (msg *MsgGetCFilters) BtcEncode(w io.Writer, pver uint32, _ MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + buf[0] = byte(msg.FilterType) if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } littleEndian.PutUint32(buf[:4], msg.StartHeight) if _, err := w.Write(buf[:4]); err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) _, err := w.Write(msg.StopHash[:]) return err diff --git a/wire/msggetdata.go b/wire/msggetdata.go index da4de87d95..f306845677 100644 --- a/wire/msggetdata.go +++ b/wire/msggetdata.go @@ -39,15 +39,15 @@ func (msg *MsgGetData) AddInvVect(iv *InvVect) error { // This is part of the Message interface implementation. func (msg *MsgGetData) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } // Limit to max inventory vectors per message. if count > MaxInvPerMsg { - binarySerializer.Return(buf) str := fmt.Sprintf("too many invvect in message [%v]", count) return messageError("MsgGetData.BtcDecode", str) } @@ -60,12 +60,10 @@ func (msg *MsgGetData) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) iv := &invList[i] err := readInvVectBuf(r, pver, iv, buf) if err != nil { - binarySerializer.Return(buf) return err } msg.AddInvVect(iv) } - binarySerializer.Return(buf) return nil } @@ -81,20 +79,19 @@ func (msg *MsgGetData) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { - binarySerializer.Return(buf) return err } for _, iv := range msg.InvList { err := writeInvVectBuf(w, pver, iv, buf) if err != nil { - binarySerializer.Return(buf) return err } } - binarySerializer.Return(buf) return nil } diff --git a/wire/msggetheaders.go b/wire/msggetheaders.go index dba6eebcc4..f49e4c0dd4 100644 --- a/wire/msggetheaders.go +++ b/wire/msggetheaders.go @@ -49,15 +49,15 @@ func (msg *MsgGetHeaders) AddBlockLocatorHash(hash *chainhash.Hash) error { // This is part of the Message interface implementation. func (msg *MsgGetHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + if _, err := io.ReadFull(r, buf[:4]); err != nil { - binarySerializer.Return(buf) return err } msg.ProtocolVersion = littleEndian.Uint32(buf[:4]) // Read num block locator hashes and limit to max. count, err := ReadVarIntBuf(r, pver, buf) - binarySerializer.Return(buf) if err != nil { return err } @@ -97,14 +97,14 @@ func (msg *MsgGetHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncodin } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + littleEndian.PutUint32(buf[:4], msg.ProtocolVersion) if _, err := w.Write(buf[:4]); err != nil { - binarySerializer.Return(buf) return err } err := WriteVarIntBuf(w, pver, uint64(count), buf) - binarySerializer.Return(buf) if err != nil { return err } diff --git a/wire/msgheaders.go b/wire/msgheaders.go index d735c911c1..46edc59395 100644 --- a/wire/msgheaders.go +++ b/wire/msgheaders.go @@ -38,15 +38,15 @@ func (msg *MsgHeaders) AddBlockHeader(bh *BlockHeader) error { // This is part of the Message interface implementation. func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } // Limit to max block headers per message. if count > MaxBlockHeadersPerMsg { - binarySerializer.Return(buf) str := fmt.Sprintf("too many block headers for message "+ "[count %v, max %v]", count, MaxBlockHeadersPerMsg) return messageError("MsgHeaders.BtcDecode", str) @@ -60,19 +60,16 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) bh := &headers[i] err := readBlockHeaderBuf(r, pver, bh, buf) if err != nil { - binarySerializer.Return(buf) return err } txCount, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } // Ensure the transaction count is zero for headers. if txCount > 0 { - binarySerializer.Return(buf) str := fmt.Sprintf("block headers may not contain "+ "transactions [count %v]", txCount) return messageError("MsgHeaders.BtcDecode", str) @@ -80,8 +77,6 @@ func (msg *MsgHeaders) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) msg.AddBlockHeader(bh) } - binarySerializer.Return(buf) - return nil } @@ -97,16 +92,16 @@ func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { - binarySerializer.Return(buf) return err } for _, bh := range msg.Headers { err := writeBlockHeaderBuf(w, pver, bh, buf) if err != nil { - binarySerializer.Return(buf) return err } @@ -116,13 +111,10 @@ func (msg *MsgHeaders) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) // block headers, but it is required. err = WriteVarIntBuf(w, pver, 0, buf) if err != nil { - binarySerializer.Return(buf) return err } } - binarySerializer.Return(buf) - return nil } diff --git a/wire/msginv.go b/wire/msginv.go index 83216ea8c5..4be528dec6 100644 --- a/wire/msginv.go +++ b/wire/msginv.go @@ -47,15 +47,15 @@ func (msg *MsgInv) AddInvVect(iv *InvVect) error { // This is part of the Message interface implementation. func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } // Limit to max inventory vectors per message. if count > MaxInvPerMsg { - binarySerializer.Return(buf) str := fmt.Sprintf("too many invvect in message [%v]", count) return messageError("MsgInv.BtcDecode", str) } @@ -68,12 +68,10 @@ func (msg *MsgInv) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) erro iv := &invList[i] err := readInvVectBuf(r, pver, iv, buf) if err != nil { - binarySerializer.Return(buf) return err } msg.AddInvVect(iv) } - binarySerializer.Return(buf) return nil } @@ -89,20 +87,19 @@ func (msg *MsgInv) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) erro } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { - binarySerializer.Return(buf) return err } for _, iv := range msg.InvList { err := writeInvVectBuf(w, pver, iv, buf) if err != nil { - binarySerializer.Return(buf) return err } } - binarySerializer.Return(buf) return nil } diff --git a/wire/msgmerkleblock.go b/wire/msgmerkleblock.go index be3f73b8b5..eacbdc5847 100644 --- a/wire/msgmerkleblock.go +++ b/wire/msgmerkleblock.go @@ -50,14 +50,14 @@ func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncodi } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := readBlockHeaderBuf(r, pver, &msg.Header, buf) if err != nil { - binarySerializer.Return(buf) return err } if _, err := io.ReadFull(r, buf[:4]); err != nil { - binarySerializer.Return(buf) return err } msg.Transactions = littleEndian.Uint32(buf[:4]) @@ -65,11 +65,9 @@ func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncodi // Read num block locator hashes and limit to max. count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } if count > maxTxPerBlock { - binarySerializer.Return(buf) str := fmt.Sprintf("too many transaction hashes for message "+ "[count %v, max %v]", count, maxTxPerBlock) return messageError("MsgMerkleBlock.BtcDecode", str) @@ -83,7 +81,6 @@ func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncodi hash := &hashes[i] _, err := io.ReadFull(r, hash[:]) if err != nil { - binarySerializer.Return(buf) return err } msg.AddTxHash(hash) @@ -91,7 +88,6 @@ func (msg *MsgMerkleBlock) BtcDecode(r io.Reader, pver uint32, enc MessageEncodi msg.Flags, err = ReadVarBytesBuf(r, pver, buf, maxFlagsPerMerkleBlock, "merkle block flags size") - binarySerializer.Return(buf) return err } @@ -119,34 +115,30 @@ func (msg *MsgMerkleBlock) BtcEncode(w io.Writer, pver uint32, enc MessageEncodi } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := writeBlockHeaderBuf(w, pver, &msg.Header, buf) if err != nil { - binarySerializer.Return(buf) return err } littleEndian.PutUint32(buf[:4], msg.Transactions) if _, err := w.Write(buf[:4]); err != nil { - binarySerializer.Return(buf) return err } err = WriteVarIntBuf(w, pver, uint64(numHashes), buf) if err != nil { - binarySerializer.Return(buf) return err } for _, hash := range msg.Hashes { _, err := w.Write(hash[:]) if err != nil { - binarySerializer.Return(buf) return err } } err = WriteVarBytesBuf(w, pver, msg.Flags, buf) - binarySerializer.Return(buf) - return err } diff --git a/wire/msgnotfound.go b/wire/msgnotfound.go index 6be7ffb48b..23486d48b6 100644 --- a/wire/msgnotfound.go +++ b/wire/msgnotfound.go @@ -36,15 +36,15 @@ func (msg *MsgNotFound) AddInvVect(iv *InvVect) error { // This is part of the Message interface implementation. func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + count, err := ReadVarIntBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } // Limit to max inventory vectors per message. if count > MaxInvPerMsg { - binarySerializer.Return(buf) str := fmt.Sprintf("too many invvect in message [%v]", count) return messageError("MsgNotFound.BtcDecode", str) } @@ -57,12 +57,10 @@ func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) iv := &invList[i] err := readInvVectBuf(r, pver, iv, buf) if err != nil { - binarySerializer.Return(buf) return err } msg.AddInvVect(iv) } - binarySerializer.Return(buf) return nil } @@ -78,20 +76,19 @@ func (msg *MsgNotFound) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) } buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := WriteVarIntBuf(w, pver, uint64(count), buf) if err != nil { - binarySerializer.Return(buf) return err } for _, iv := range msg.InvList { err := writeInvVectBuf(w, pver, iv, buf) if err != nil { - binarySerializer.Return(buf) return err } } - binarySerializer.Return(buf) return nil } diff --git a/wire/msgreject.go b/wire/msgreject.go index 64c81d8b5b..ea16dd19f4 100644 --- a/wire/msgreject.go +++ b/wire/msgreject.go @@ -82,16 +82,16 @@ func (msg *MsgReject) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) e // Command that was rejected. buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + cmd, err := readVarStringBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } msg.Cmd = cmd // Code indicating why the command was rejected. if _, err := io.ReadFull(r, buf[:1]); err != nil { - binarySerializer.Return(buf) return err } msg.Code = RejectCode(buf[0]) @@ -100,11 +100,9 @@ func (msg *MsgReject) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) e // reject code above) about why the command was rejected. reason, err := readVarStringBuf(r, pver, buf) if err != nil { - binarySerializer.Return(buf) return err } msg.Reason = reason - binarySerializer.Return(buf) // CmdBlock and CmdTx messages have an additional hash field that // identifies the specific block or transaction. @@ -129,16 +127,16 @@ func (msg *MsgReject) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) e // Command that was rejected. buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := writeVarStringBuf(w, pver, msg.Cmd, buf) if err != nil { - binarySerializer.Return(buf) return err } // Code indicating why the command was rejected. buf[0] = byte(msg.Code) if _, err := w.Write(buf[:1]); err != nil { - binarySerializer.Return(buf) return err } @@ -146,10 +144,8 @@ func (msg *MsgReject) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) e // reject code above) about why the command was rejected. err = writeVarStringBuf(w, pver, msg.Reason, buf) if err != nil { - binarySerializer.Return(buf) return err } - binarySerializer.Return(buf) // CmdBlock and CmdTx messages have an additional hash field that // identifies the specific block or transaction. diff --git a/wire/msgtx.go b/wire/msgtx.go index 3f91aaeb75..f297f10ddb 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -456,10 +456,12 @@ func (msg *MsgTx) Copy() *MsgTx { // database, as opposed to decoding transactions from the wire. func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + sbuf := scriptPool.Borrow() + defer scriptPool.Return(sbuf) + err := msg.btcDecode(r, pver, enc, buf, sbuf[:]) - scriptPool.Return(sbuf) - binarySerializer.Return(buf) return err } @@ -695,8 +697,9 @@ func (msg *MsgTx) DeserializeNoWitness(r io.Reader) error { // database, as opposed to encoding transactions for the wire. func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := msg.btcEncode(w, pver, enc, buf) - binarySerializer.Return(buf) return err } @@ -947,8 +950,9 @@ func readOutPointBuf(r io.Reader, pver uint32, version int32, op *OutPoint, // w. func WriteOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := writeOutPointBuf(w, pver, version, op, buf) - binarySerializer.Return(buf) return err } @@ -986,8 +990,8 @@ func writeOutPointBuf(w io.Writer, pver uint32, version int32, op *OutPoint, // and return when the method finishes. // // NOTE: b MUST either be nil or at least an 8-byte slice. -func readScriptBuf(r io.Reader, pver uint32, buf, s []byte, maxAllowed uint32, - fieldName string) ([]byte, error) { +func readScriptBuf(r io.Reader, pver uint32, buf, s []byte, + maxAllowed uint32, fieldName string) ([]byte, error) { count, err := ReadVarIntBuf(r, pver, buf) if err != nil { @@ -1070,8 +1074,9 @@ func ReadTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { var s scriptSlab buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := readTxOutBuf(r, pver, version, to, buf, s[:]) - binarySerializer.Return(buf) return err } @@ -1102,8 +1107,9 @@ func readTxOutBuf(r io.Reader, pver uint32, version int32, to *TxOut, // new sighashes for witness transactions (BIP0143). func WriteTxOut(w io.Writer, pver uint32, version int32, to *TxOut) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := WriteTxOutBuf(w, pver, version, to, buf) - binarySerializer.Return(buf) return err } diff --git a/wire/netaddress.go b/wire/netaddress.go index 9cef72cf10..e5c8eeea17 100644 --- a/wire/netaddress.go +++ b/wire/netaddress.go @@ -89,8 +89,9 @@ func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress { // like version do not include the timestamp. func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) + err := readNetAddressBuf(r, pver, na, ts, buf) - binarySerializer.Return(buf) return err } @@ -152,8 +153,9 @@ func readNetAddressBuf(r io.Reader, pver uint32, na *NetAddress, ts bool, // like version do not include the timestamp. func writeNetAddress(w io.Writer, pver uint32, na *NetAddress, ts bool) error { buf := binarySerializer.Borrow() + defer binarySerializer.Return(buf) err := writeNetAddressBuf(w, pver, na, ts, buf) - binarySerializer.Return(buf) + return err } From d64de4a905b5b5b62559e9359dddfba801b26ff4 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 Dec 2023 19:00:00 -0800 Subject: [PATCH 0924/1056] build: update to btcutil v1.1.5 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 36d4aa21bd..425e6d7f2b 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/btcsuite/btcd require ( github.com/btcsuite/btcd/btcec/v2 v2.1.3 - github.com/btcsuite/btcd/btcutil v1.1.4 + github.com/btcsuite/btcd/btcutil v1.1.5 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd diff --git a/go.sum b/go.sum index 6a2ee39cd8..158e868092 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJ github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= -github.com/btcsuite/btcd/btcutil v1.1.4 h1:mWvWRLRIPuoeZsVRpc0xNCkfeNxWy1E4jIZ06ZpGI1A= -github.com/btcsuite/btcd/btcutil v1.1.4/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= From bf23715f9090e4d1386a54409262021f6624cb90 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 30 Dec 2023 16:08:34 -0800 Subject: [PATCH 0925/1056] btcd: add SECURITY.md --- SECURITY.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..e06625c87a --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,15 @@ +# Security Policy + +## Supported Versions + +The last major `btcd` release is to be considered the current support version. +Given an issue severe enough, a backport will be issued either to the prior +major release or the set of releases considered utilized enough. + +## Reporting a Vulnerability + +To report security issues, send an email to security@lightning.engineering +(this list isn't to be used for support). + +The following key can be used to communicate sensitive information: `91FE 464C +D751 01DA 6B6B AB60 555C 6465 E5BC B3AF`. From 3c2478514f224b14721499386c8efc35c412dba3 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 Dec 2023 19:01:08 -0800 Subject: [PATCH 0926/1056] chaincfg: update mainnet block hashes --- chaincfg/params.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chaincfg/params.go b/chaincfg/params.go index 3b38878b4a..3a7f7661e1 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -341,6 +341,9 @@ var MainNetParams = Params{ {691719, newHashFromStr("00000000000000000008a89e854d57e5667df88f1cdef6fde2fbca1de5b639ad")}, {724466, newHashFromStr("000000000000000000052d314a259755ca65944e68df6b12a067ea8f1f5a7091")}, {751565, newHashFromStr("00000000000000000009c97098b5295f7e5f183ac811fb5d1534040adb93cabd")}, + {781565, newHashFromStr("00000000000000000002b8c04999434c33b8e033f11a977b288f8411766ee61c")}, + {800000, newHashFromStr("00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054")}, + {810000, newHashFromStr("000000000000000000028028ca82b6aa81ce789e4eb9e0321b74c3cbaf405dd1")}, }, // Consensus rule change deployments. From 8d2ab63e36fd6a58967fa53aa4a1df8b9abe09fd Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 28 Dec 2023 19:01:42 -0800 Subject: [PATCH 0927/1056] build: bump version to btcd v0.24 --- version.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.go b/version.go index 19af5b8bd0..d7835910f8 100644 --- a/version.go +++ b/version.go @@ -17,8 +17,8 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr // versioning 2.0.0 spec (http://semver.org/). const ( appMajor uint = 0 - appMinor uint = 23 - appPatch uint = 3 + appMinor uint = 24 + appPatch uint = 0 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. From 4ec8f016b99d7295313c1d2b094033daf447ab11 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 30 Dec 2023 16:43:07 -0800 Subject: [PATCH 0928/1056] rpcclient: fix race condition in `doDisconnect` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In this commit, we fix the following race condition: ``` ================== WARNING: DATA RACE Write at 0x00c000216018 by goroutine 31: github.com/btcsuite/btcd/rpcclient.(*Client).wsReconnectHandler() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:736 +0x2aa github.com/btcsuite/btcd/rpcclient.New·dwrap·13() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:1496 +0x39 Previous read at 0x00c000216018 by goroutine 29: github.com/btcsuite/btcd/rpcclient.(*Client).doDisconnect() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:1079 +0x247 github.com/btcsuite/btcd/rpcclient.(*Client).Disconnect() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:1111 +0x47 github.com/btcsuite/btcd/rpcclient.(*Client).wsInHandler() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:491 +0x1eb github.com/btcsuite/btcd/rpcclient.(*Client).start·dwrap·11() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:1181 +0x39 Goroutine 31 (running) created at: github.com/btcsuite/btcd/rpcclient.New() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:1496 +0xd77 github.com/btcsuite/btcd/rpcclient.makeClient() /home/runner/work/btcd/btcd/rpcclient/chain_test.go:268 +0x1f9 github.com/btcsuite/btcd/rpcclient.TestClientConnectedToWSServerRunner.func2() /home/runner/work/btcd/btcd/rpcclient/chain_test.go:164 +0x47 testing.tRunner() /opt/hostedtoolcache/go/1.17.5/x64/src/testing/testing.go:1259 +0x22f testing.(*T).Run·dwrap·21() /opt/hostedtoolcache/go/1.17.5/x64/src/testing/testing.go:1306 +0x47 Goroutine 29 (finished) created at: github.com/btcsuite/btcd/rpcclient.(*Client).start() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:1181 +0x2e4 github.com/btcsuite/btcd/rpcclient.New() /home/runner/work/btcd/btcd/rpcclient/infrastructure.go:1493 +0xc51 github.com/btcsuite/btcd/rpcclient.makeClient() /home/runner/work/btcd/btcd/rpcclient/chain_test.go:268 +0x1f9 github.com/btcsuite/btcd/rpcclient.TestClientConnectedToWSServerRunner.func2() /home/runner/work/btcd/btcd/rpcclient/chain_test.go:164 +0x47 testing.tRunner() /opt/hostedtoolcache/go/1.17.5/x64/src/testing/testing.go:1259 +0x22f testing.(*T).Run·dwrap·21() /opt/hostedtoolcache/go/1.17.5/x64/src/testing/testing.go:1306 +0x47 ``` This arises as in `wsReconnectHandler`, the mutex isn't held while the `conn` pointer is modified. --- rpcclient/infrastructure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index cf683db0ca..eddfb77700 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -733,10 +733,10 @@ out: // Reset the connection state and signal the reconnect // has happened. + c.mtx.Lock() c.wsConn = wsConn c.retryCount = 0 - c.mtx.Lock() c.disconnect = make(chan struct{}) c.disconnected = false c.mtx.Unlock() From e307ad122f08d86d5ee3cb0cebd556cae9a40f66 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 3 Jan 2024 14:24:36 +0900 Subject: [PATCH 0929/1056] blockchain: set the lastflushtime when setting the lastflushhash On startup when the headers-first mode is off, when receiving the first block, the periodic flush will trigger. The lastflushtime wasn't set which resulted in the flush being triggered on the first block on restart. --- blockchain/utxocache.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index af7a3b7b6f..d6a9f7eaa0 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -634,6 +634,10 @@ func (b *BlockChain) InitConsistentState(tip *blockNode, interrupt <-chan struct // it to the tip since we checked it's consistent. s.lastFlushHash = tip.hash + // Set the last flush time as now since we know the state is consistent + // at this time. + s.lastFlushTime = time.Now() + return nil } From a4df044cfd41318552b8064cc34eaadc3eeade59 Mon Sep 17 00:00:00 2001 From: Thabokani <149070269+Thabokani@users.noreply.github.com> Date: Thu, 4 Jan 2024 05:36:49 +0800 Subject: [PATCH 0930/1056] Fix some typos (#2085) * Dockerfile: fix typo * blockchain: fix typos * sample-btcd.conf: fix typos * server: fix typos * txscript: fix typos --- Dockerfile | 2 +- blockchain/sizehelper.go | 2 +- blockchain/utxocache.go | 2 +- blockchain/utxocache_test.go | 2 +- sample-btcd.conf | 2 +- server.go | 6 +++--- txscript/error.go | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5ed3e63c10..a715e89ba6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # # docker build . -t yourregistry/btcd # -# You can use the following command to buid an arm64v8 container: +# You can use the following command to build an arm64v8 container: # # docker build . -t yourregistry/btcd --build-arg ARCH=arm64v8 # diff --git a/blockchain/sizehelper.go b/blockchain/sizehelper.go index 4904a8e4c3..8330549dd6 100644 --- a/blockchain/sizehelper.go +++ b/blockchain/sizehelper.go @@ -39,7 +39,7 @@ const ( avgEntrySize = baseEntrySize + (pubKeyHashLen + 7) ) -// The code here is shamelessely taken from the go runtime package. All the relevant +// The code here is shamelessly taken from the go runtime package. All the relevant // code and variables are copied to here. These values are only correct for a 64 bit // system. diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index af7a3b7b6f..b6ad0bd765 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -177,7 +177,7 @@ const ( // utxoFlushPeriodicInterval is the interval at which a flush is performed // when the flush mode FlushPeriodic is used. This is used when the initial // block download is complete and it's useful to flush periodically in case - // of unforseen shutdowns. + // of unforeseen shutdowns. utxoFlushPeriodicInterval = time.Minute * 5 ) diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 20b2a5b34a..45116655e3 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -260,7 +260,7 @@ func TestUtxoCacheEntrySize(t *testing.T) { } return blocks }(), - // Multipled by 6 since we'll have 6 entries left. + // Multiplied by 6 since we'll have 6 entries left. expectedSize: (pubKeyHashLen + baseEntrySize) * 6, }, { diff --git a/sample-btcd.conf b/sample-btcd.conf index 0a765fcabe..74b20e1660 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -48,7 +48,7 @@ ; Use Universal Plug and Play (UPnP) to automatically open the listen port ; and obtain the external IP address from supported devices. NOTE: This option -; will have no effect if exernal IP addresses are specified. +; will have no effect if external IP addresses are specified. ; upnp=1 ; Specify the external IP addresses your node is listening on. One address per diff --git a/server.go b/server.go index 356326ab1c..0aa84d1f9c 100644 --- a/server.go +++ b/server.go @@ -478,7 +478,7 @@ func (sp *serverPeer) OnVersion(_ *peer.Peer, msg *wire.MsgVersion) *wire.MsgRej addrManager.SetServices(remoteAddr, msg.Services) } - // Ignore peers that have a protcol version that is too old. The peer + // Ignore peers that have a protocol version that is too old. The peer // negotiation logic will disconnect it after this callback returns. if msg.ProtocolVersion < int32(peer.MinAcceptableProtocolVersion) { return nil @@ -2204,7 +2204,7 @@ func (s *server) outboundPeerConnected(c *connmgr.ConnReq, conn net.Conn) { go s.peerDoneHandler(sp) } -// peerDoneHandler handles peer disconnects by notifiying the server that it's +// peerDoneHandler handles peer disconnects by notifying the server that it's // done along with other performing other desirable cleanup. func (s *server) peerDoneHandler(sp *serverPeer) { sp.WaitForDisconnect() @@ -2231,7 +2231,7 @@ func (s *server) peerDoneHandler(sp *serverPeer) { func (s *server) peerHandler() { // Start the address manager and sync manager, both of which are needed // by peers. This is done here since their lifecycle is closely tied - // to this handler and rather than adding more channels to sychronize + // to this handler and rather than adding more channels to synchronize // things, it's easier and slightly faster to simply start and stop them // in this handler. s.addrManager.Start() diff --git a/txscript/error.go b/txscript/error.go index 1f046b9612..68bea7e879 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -309,9 +309,9 @@ const ( ErrMinimalIf // ErrDiscourageUpgradableWitnessProgram is returned if - // ScriptVerifyWitness is set and the versino of an executing witness + // ScriptVerifyWitness is set and the version of an executing witness // program is outside the set of currently defined witness program - // vesions. + // versions. ErrDiscourageUpgradableWitnessProgram // ---------------------------------------- @@ -363,7 +363,7 @@ const ( ErrTapscriptCheckMultisig // ErrDiscourageUpgradeableTaprootVersion is returned if during - // tapscript execution, we encoutner a public key that isn't 0 or 32 + // tapscript execution, we encounter a public key that isn't 0 or 32 // bytes. ErrDiscourageUpgradeablePubKeyType From 7fdd92c3a0a3f532548665062fc30a74bb226aa3 Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 17:11:59 +0800 Subject: [PATCH 0931/1056] docs: fix typo --- docs/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.md b/docs/configuration.md index c6f95b274c..cc1d0dbe44 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -175,7 +175,7 @@ and we prefer to keep the daemon itself as lightweight as possible. access the database used by btcd and it will be locked if btcd is using it. 2. Note the path to the downloaded bootstrap.dat file. 3. Run the addblock utility with the `-i` argument pointing to the location of - boostrap.dat: + bootstrap.dat: **Windows:** From 048a7ef40b09359ac9a316d2537bce7cff672ed9 Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 17:12:09 +0800 Subject: [PATCH 0932/1056] database: fix typo --- database/ffldb/driver_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index 38a84ee2f9..0b2f452032 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -350,7 +350,7 @@ func TestPrune(t *testing.T) { } if pruned { - err = fmt.Errorf("The database hasn't been commited yet " + + err = fmt.Errorf("The database hasn't been committed yet " + "but files were already deleted") } return err From 7df46516b7ef2c77cfe577a8c4eb4f80dfc9544c Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 17:12:23 +0800 Subject: [PATCH 0933/1056] btcutil: fix typo --- btcutil/hdkeychain/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcutil/hdkeychain/README.md b/btcutil/hdkeychain/README.md index eaf57d7c58..33eba3ce16 100644 --- a/btcutil/hdkeychain/README.md +++ b/btcutil/hdkeychain/README.md @@ -26,7 +26,7 @@ report. - Obtaining the underlying EC pubkeys, EC privkeys, and associated bitcoin addresses ties in seamlessly with existing btcec and btcutil types which provide powerful tools for working with them to do things like sign - transations and generate payment scripts + transactions and generate payment scripts - Uses the btcec package which is highly optimized for secp256k1 - Code examples including: - Generating a cryptographically secure random seed and deriving a From 6ed54f3bf274fa5927781be6430e967acc568ef1 Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 17:12:36 +0800 Subject: [PATCH 0934/1056] btcec: fix typo --- btcec/schnorr/signature_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcec/schnorr/signature_test.go b/btcec/schnorr/signature_test.go index 2f96b7e4d5..9e99bbe233 100644 --- a/btcec/schnorr/signature_test.go +++ b/btcec/schnorr/signature_test.go @@ -245,7 +245,7 @@ func TestSchnorrVerify(t *testing.T) { verify := err == nil if test.verifyResult != verify { - t.Fatalf("test #%v: verificaiton mismatch: expected "+ + t.Fatalf("test #%v: verification mismatch: expected "+ "%v, got %v", i, test.verifyResult, verify) } From 44abf0a53c15f2fb25ea428dc956e3529d0b6f3c Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 4 Jan 2024 18:31:48 +0800 Subject: [PATCH 0935/1056] gitignore: ignore vim files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 5c29ccd9b5..1e5a40ca27 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,8 @@ btcutil/psbt/coverage.txt # vim *.swp +*.swo +/.vim # Binaries produced by "make build" /addblock From 2ad8026a388c40d5ab57324733e945d26c7c789c Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Sat, 4 Nov 2023 07:40:47 +0800 Subject: [PATCH 0936/1056] mempool: add new method `checkMempoolAcceptance` This commit breaks the `maybeAcceptTransaction` into two parts - the first is reading the mempool to validate the transaction, and the relevant logic has been moved into the new method `checkMempoolAcceptance`. The second part is writing to the mempool, and is kept in the method `maybeAcceptTransaction`. --- mempool/mempool.go | 772 ++++++++++++++++++++++++++++----------------- 1 file changed, 485 insertions(+), 287 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index a80d8ee4f4..f6e81b6d90 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -21,6 +21,7 @@ import ( "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/davecgh/go-spew/spew" ) const ( @@ -924,313 +925,39 @@ func (mp *TxPool) validateReplacement(tx *btcutil.Tx, // more details. // // This function MUST be called with the mempool lock held (for writes). -func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, rejectDupOrphans bool) ([]*chainhash.Hash, *TxDesc, error) { - txHash := tx.Hash() - - // If a transaction has witness data, and segwit isn't active yet, If - // segwit isn't active yet, then we won't accept it into the mempool as - // it can't be mined yet. - if tx.MsgTx().HasWitness() { - segwitActive, err := mp.cfg.IsDeploymentActive(chaincfg.DeploymentSegwit) - if err != nil { - return nil, nil, err - } - - if !segwitActive { - simnetHint := "" - if mp.cfg.ChainParams.Net == wire.SimNet { - bestHeight := mp.cfg.BestHeight() - simnetHint = fmt.Sprintf(" (The threshold for segwit activation is 300 blocks on simnet, "+ - "current best height is %d)", bestHeight) - } - str := fmt.Sprintf("transaction %v has witness data, "+ - "but segwit isn't active yet%s", txHash, simnetHint) - return nil, nil, txRuleError(wire.RejectNonstandard, str) - } - } - - // Don't accept the transaction if it already exists in the pool. This - // applies to orphan transactions as well when the reject duplicate - // orphans flag is set. This check is intended to be a quick check to - // weed out duplicates. - if mp.isTransactionInPool(txHash) || (rejectDupOrphans && - mp.isOrphanInPool(txHash)) { - - str := fmt.Sprintf("already have transaction %v", txHash) - return nil, nil, txRuleError(wire.RejectDuplicate, str) - } - - // Perform preliminary sanity checks on the transaction. This makes - // use of blockchain which contains the invariant rules for what - // transactions are allowed into blocks. - err := blockchain.CheckTransactionSanity(tx) - if err != nil { - if cerr, ok := err.(blockchain.RuleError); ok { - return nil, nil, chainRuleError(cerr) - } - return nil, nil, err - } - - // A standalone transaction must not be a coinbase transaction. - if blockchain.IsCoinBase(tx) { - str := fmt.Sprintf("transaction %v is an individual coinbase", - txHash) - return nil, nil, txRuleError(wire.RejectInvalid, str) - } - - // Get the current height of the main chain. A standalone transaction - // will be mined into the next block at best, so its height is at least - // one more than the current height. - bestHeight := mp.cfg.BestHeight() - nextBlockHeight := bestHeight + 1 - - medianTimePast := mp.cfg.MedianTimePast() - - // Don't allow non-standard transactions if the network parameters - // forbid their acceptance. - if !mp.cfg.Policy.AcceptNonStd { - err = CheckTransactionStandard(tx, nextBlockHeight, - medianTimePast, mp.cfg.Policy.MinRelayTxFee, - mp.cfg.Policy.MaxTxVersion) - if err != nil { - // Attempt to extract a reject code from the error so - // it can be retained. When not possible, fall back to - // a non standard error. - rejectCode, found := extractRejectCode(err) - if !found { - rejectCode = wire.RejectNonstandard - } - str := fmt.Sprintf("transaction %v is not standard: %v", - txHash, err) - return nil, nil, txRuleError(rejectCode, str) - } - } - - // The transaction may not use any of the same outputs as other - // transactions already in the pool as that would ultimately result in a - // double spend, unless those transactions signal for RBF. This check is - // intended to be quick and therefore only detects double spends within - // the transaction pool itself. The transaction could still be double - // spending coins from the main chain at this point. There is a more - // in-depth check that happens later after fetching the referenced - // transaction inputs from the main chain which examines the actual - // spend data and prevents double spends. - isReplacement, err := mp.checkPoolDoubleSpend(tx) - if err != nil { - return nil, nil, err - } - - // Fetch all of the unspent transaction outputs referenced by the inputs - // to this transaction. This function also attempts to fetch the - // transaction itself to be used for detecting a duplicate transaction - // without needing to do a separate lookup. - utxoView, err := mp.fetchInputUtxos(tx) - if err != nil { - if cerr, ok := err.(blockchain.RuleError); ok { - return nil, nil, chainRuleError(cerr) - } - return nil, nil, err - } +func (mp *TxPool) maybeAcceptTransaction(tx *btcutil.Tx, isNew, rateLimit, + rejectDupOrphans bool) ([]*chainhash.Hash, *TxDesc, error) { - // Don't allow the transaction if it exists in the main chain and is - // already fully spent. - prevOut := wire.OutPoint{Hash: *txHash} - for txOutIdx := range tx.MsgTx().TxOut { - prevOut.Index = uint32(txOutIdx) - entry := utxoView.LookupEntry(prevOut) - if entry != nil && !entry.IsSpent() { - return nil, nil, txRuleError(wire.RejectDuplicate, - "transaction already exists") - } - utxoView.RemoveEntry(prevOut) - } - - // Transaction is an orphan if any of the referenced transaction outputs - // don't exist or are already spent. Adding orphans to the orphan pool - // is not handled by this function, and the caller should use - // maybeAddOrphan if this behavior is desired. - var missingParents []*chainhash.Hash - for outpoint, entry := range utxoView.Entries() { - if entry == nil || entry.IsSpent() { - // Must make a copy of the hash here since the iterator - // is replaced and taking its address directly would - // result in all the entries pointing to the same - // memory location and thus all be the final hash. - hashCopy := outpoint.Hash - missingParents = append(missingParents, &hashCopy) - } - } - if len(missingParents) > 0 { - return missingParents, nil, nil - } - - // Don't allow the transaction into the mempool unless its sequence - // lock is active, meaning that it'll be allowed into the next block - // with respect to its defined relative lock times. - sequenceLock, err := mp.cfg.CalcSequenceLock(tx, utxoView) - if err != nil { - if cerr, ok := err.(blockchain.RuleError); ok { - return nil, nil, chainRuleError(cerr) - } - return nil, nil, err - } - if !blockchain.SequenceLockActive(sequenceLock, nextBlockHeight, - medianTimePast) { - return nil, nil, txRuleError(wire.RejectNonstandard, - "transaction's sequence locks on inputs not met") - } - - // Perform several checks on the transaction inputs using the invariant - // rules in blockchain for what transactions are allowed into blocks. - // Also returns the fees associated with the transaction which will be - // used later. - txFee, err := blockchain.CheckTransactionInputs(tx, nextBlockHeight, - utxoView, mp.cfg.ChainParams) - if err != nil { - if cerr, ok := err.(blockchain.RuleError); ok { - return nil, nil, chainRuleError(cerr) - } - return nil, nil, err - } - - // Don't allow transactions with non-standard inputs if the network - // parameters forbid their acceptance. - if !mp.cfg.Policy.AcceptNonStd { - err := checkInputsStandard(tx, utxoView) - if err != nil { - // Attempt to extract a reject code from the error so - // it can be retained. When not possible, fall back to - // a non-standard error. - rejectCode, found := extractRejectCode(err) - if !found { - rejectCode = wire.RejectNonstandard - } - str := fmt.Sprintf("transaction %v has a non-standard "+ - "input: %v", txHash, err) - return nil, nil, txRuleError(rejectCode, str) - } - } - - // NOTE: if you modify this code to accept non-standard transactions, - // you should add code here to check that the transaction does a - // reasonable number of ECDSA signature verifications. + txHash := tx.Hash() - // Don't allow transactions with an excessive number of signature - // operations which would result in making it impossible to mine. Since - // the coinbase address itself can contain signature operations, the - // maximum allowed signature operations per transaction is less than - // the maximum allowed signature operations per block. - // TODO(roasbeef): last bool should be conditional on segwit activation - sigOpCost, err := blockchain.GetSigOpCost(tx, false, utxoView, true, true) + // Check for mempool acceptance. + r, err := mp.checkMempoolAcceptance( + tx, isNew, rateLimit, rejectDupOrphans, + ) if err != nil { - if cerr, ok := err.(blockchain.RuleError); ok { - return nil, nil, chainRuleError(cerr) - } return nil, nil, err } - if sigOpCost > mp.cfg.Policy.MaxSigOpCostPerTx { - str := fmt.Sprintf("transaction %v sigop cost is too high: %d > %d", - txHash, sigOpCost, mp.cfg.Policy.MaxSigOpCostPerTx) - return nil, nil, txRuleError(wire.RejectNonstandard, str) - } - // Don't allow transactions with fees too low to get into a mined block. - // - // Most miners allow a free transaction area in blocks they mine to go - // alongside the area used for high-priority transactions as well as - // transactions with fees. A transaction size of up to 1000 bytes is - // considered safe to go into this section. Further, the minimum fee - // calculated below on its own would encourage several small - // transactions to avoid fees rather than one single larger transaction - // which is more desirable. Therefore, as long as the size of the - // transaction does not exceed 1000 less than the reserved space for - // high-priority transactions, don't require a fee for it. - serializedSize := GetTxVirtualSize(tx) - minFee := calcMinRequiredTxRelayFee(serializedSize, - mp.cfg.Policy.MinRelayTxFee) - if serializedSize >= (DefaultBlockPrioritySize-1000) && txFee < minFee { - str := fmt.Sprintf("transaction %v has %d fees which is under "+ - "the required amount of %d", txHash, txFee, - minFee) - return nil, nil, txRuleError(wire.RejectInsufficientFee, str) - } - - // Require that free transactions have sufficient priority to be mined - // in the next block. Transactions which are being added back to the - // memory pool from blocks that have been disconnected during a reorg - // are exempted. - if isNew && !mp.cfg.Policy.DisableRelayPriority && txFee < minFee { - currentPriority := mining.CalcPriority(tx.MsgTx(), utxoView, - nextBlockHeight) - if currentPriority <= mining.MinHighPriority { - str := fmt.Sprintf("transaction %v has insufficient "+ - "priority (%g <= %g)", txHash, - currentPriority, mining.MinHighPriority) - return nil, nil, txRuleError(wire.RejectInsufficientFee, str) - } - } - - // Free-to-relay transactions are rate limited here to prevent - // penny-flooding with tiny transactions as a form of attack. - if rateLimit && txFee < minFee { - nowUnix := time.Now().Unix() - // Decay passed data with an exponentially decaying ~10 minute - // window - matches bitcoind handling. - mp.pennyTotal *= math.Pow(1.0-1.0/600.0, - float64(nowUnix-mp.lastPennyUnix)) - mp.lastPennyUnix = nowUnix - - // Are we still over the limit? - if mp.pennyTotal >= mp.cfg.Policy.FreeTxRelayLimit*10*1000 { - str := fmt.Sprintf("transaction %v has been rejected "+ - "by the rate limiter due to low fees", txHash) - return nil, nil, txRuleError(wire.RejectInsufficientFee, str) - } - oldTotal := mp.pennyTotal - - mp.pennyTotal += float64(serializedSize) - log.Tracef("rate limit: curTotal %v, nextTotal: %v, "+ - "limit %v", oldTotal, mp.pennyTotal, - mp.cfg.Policy.FreeTxRelayLimit*10*1000) - } - - // If the transaction has any conflicts, and we've made it this far, then - // we're processing a potential replacement. - var conflicts map[chainhash.Hash]*btcutil.Tx - if isReplacement { - conflicts, err = mp.validateReplacement(tx, txFee) - if err != nil { - return nil, nil, err - } - } - - // Verify crypto signatures for each input and reject the transaction if - // any don't verify. - err = blockchain.ValidateTransactionScripts(tx, utxoView, - txscript.StandardVerifyFlags, mp.cfg.SigCache, - mp.cfg.HashCache) - if err != nil { - if cerr, ok := err.(blockchain.RuleError); ok { - return nil, nil, chainRuleError(cerr) - } - return nil, nil, err + // Exit early if this transaction is missing parents. + if len(r.MissingParents) > 0 { + return r.MissingParents, nil, nil } // Now that we've deemed the transaction as valid, we can add it to the // mempool. If it ended up replacing any transactions, we'll remove them // first. - for _, conflict := range conflicts { + for _, conflict := range r.Conflicts { log.Debugf("Replacing transaction %v (fee_rate=%v sat/kb) "+ "with %v (fee_rate=%v sat/kb)\n", conflict.Hash(), mp.pool[*conflict.Hash()].FeePerKB, tx.Hash(), - txFee*1000/serializedSize) + int64(r.TxFee)*1000/r.TxSize) // The conflict set should already include the descendants for // each one, so we don't need to remove the redeemers within // this call as they'll be removed eventually. mp.removeTransaction(conflict, false) } - txD := mp.addTransaction(utxoView, tx, bestHeight, txFee) + txD := mp.addTransaction(r.utxoView, tx, r.bestHeight, int64(r.TxFee)) log.Debugf("Accepted transaction %v (pool size: %v)", txHash, len(mp.pool)) @@ -1545,6 +1272,477 @@ func (mp *TxPool) LastUpdated() time.Time { return time.Unix(atomic.LoadInt64(&mp.lastUpdated), 0) } +// MempoolAcceptResult holds the result from mempool acceptance check. +type MempoolAcceptResult struct { + // TxFee is the fees paid in satoshi. + TxFee btcutil.Amount + + // TxSize is the virtual size(vb) of the tx. + TxSize int64 + + // conflicts is a set of transactions whose inputs are spent by this + // transaction(RBF). + Conflicts map[chainhash.Hash]*btcutil.Tx + + // MissingParents is a set of outpoints that are used by this + // transaction which cannot be found. Transaction is an orphan if any + // of the referenced transaction outputs don't exist or are already + // spent. + // + // NOTE: this field is mutually exclusive with other fields. If this + // field is not nil, then other fields must be empty. + MissingParents []*chainhash.Hash + + // utxoView is a set of the unspent transaction outputs referenced by + // the inputs to this transaction. + utxoView *blockchain.UtxoViewpoint + + // bestHeight is the best known height by the mempool. + bestHeight int32 +} + +// CheckMempoolAcceptance behaves similarly to bitcoind's `testmempoolaccept` +// RPC method. It will perform a series of checks to decide whether this +// transaction can be accepted to the mempool. If not, the specific error is +// returned and the caller needs to take actions based on it. +func (mp *TxPool) CheckMempoolAcceptance(tx *btcutil.Tx) ( + *MempoolAcceptResult, error) { + + mp.mtx.RLock() + defer mp.mtx.RUnlock() + + // Call checkMempoolAcceptance with isNew=true and rateLimit=true, + // which has the effect that we always check the fee paid from this tx + // is greater than min relay fee. We also reject this tx if it's + // already an orphan. + result, err := mp.checkMempoolAcceptance(tx, true, true, true) + if err != nil { + log.Errorf("CheckMempoolAcceptance: %v", err) + return nil, err + } + + log.Tracef("Tx %v passed mempool acceptance check: %v", tx.Hash(), + spew.Sdump(result)) + + return result, nil +} + +// checkMempoolAcceptance performs a series of validations on the given +// transaction. It returns an error when the transaction fails to meet the +// mempool policy, otherwise a `mempoolAcceptResult` is returned. +func (mp *TxPool) checkMempoolAcceptance(tx *btcutil.Tx, + isNew, rateLimit, rejectDupOrphans bool) (*MempoolAcceptResult, error) { + + txHash := tx.Hash() + + // Check for segwit activeness. + if err := mp.validateSegWitDeployment(tx); err != nil { + return nil, err + } + + // Don't accept the transaction if it already exists in the pool. This + // applies to orphan transactions as well when the reject duplicate + // orphans flag is set. This check is intended to be a quick check to + // weed out duplicates. + if mp.isTransactionInPool(txHash) || (rejectDupOrphans && + mp.isOrphanInPool(txHash)) { + + str := fmt.Sprintf("already have transaction %v", txHash) + return nil, txRuleError(wire.RejectDuplicate, str) + } + + // Perform preliminary sanity checks on the transaction. This makes use + // of blockchain which contains the invariant rules for what + // transactions are allowed into blocks. + err := blockchain.CheckTransactionSanity(tx) + if err != nil { + if cerr, ok := err.(blockchain.RuleError); ok { + return nil, chainRuleError(cerr) + } + + return nil, err + } + + // A standalone transaction must not be a coinbase transaction. + if blockchain.IsCoinBase(tx) { + str := fmt.Sprintf("transaction %v is an individual coinbase", + txHash) + + return nil, txRuleError(wire.RejectInvalid, str) + } + + // Get the current height of the main chain. A standalone transaction + // will be mined into the next block at best, so its height is at least + // one more than the current height. + bestHeight := mp.cfg.BestHeight() + nextBlockHeight := bestHeight + 1 + + medianTimePast := mp.cfg.MedianTimePast() + + // The transaction may not use any of the same outputs as other + // transactions already in the pool as that would ultimately result in + // a double spend, unless those transactions signal for RBF. This check + // is intended to be quick and therefore only detects double spends + // within the transaction pool itself. The transaction could still be + // double spending coins from the main chain at this point. There is a + // more in-depth check that happens later after fetching the referenced + // transaction inputs from the main chain which examines the actual + // spend data and prevents double spends. + isReplacement, err := mp.checkPoolDoubleSpend(tx) + if err != nil { + return nil, err + } + + // Fetch all of the unspent transaction outputs referenced by the + // inputs to this transaction. This function also attempts to fetch the + // transaction itself to be used for detecting a duplicate transaction + // without needing to do a separate lookup. + utxoView, err := mp.fetchInputUtxos(tx) + if err != nil { + if cerr, ok := err.(blockchain.RuleError); ok { + return nil, chainRuleError(cerr) + } + + return nil, err + } + + // Don't allow the transaction if it exists in the main chain and is + // already fully spent. + prevOut := wire.OutPoint{Hash: *txHash} + for txOutIdx := range tx.MsgTx().TxOut { + prevOut.Index = uint32(txOutIdx) + + entry := utxoView.LookupEntry(prevOut) + if entry != nil && !entry.IsSpent() { + return nil, txRuleError(wire.RejectDuplicate, + "transaction already exists") + } + + utxoView.RemoveEntry(prevOut) + } + + // Transaction is an orphan if any of the referenced transaction + // outputs don't exist or are already spent. Adding orphans to the + // orphan pool is not handled by this function, and the caller should + // use maybeAddOrphan if this behavior is desired. + var missingParents []*chainhash.Hash + for outpoint, entry := range utxoView.Entries() { + if entry == nil || entry.IsSpent() { + // Must make a copy of the hash here since the iterator + // is replaced and taking its address directly would + // result in all the entries pointing to the same + // memory location and thus all be the final hash. + hashCopy := outpoint.Hash + missingParents = append(missingParents, &hashCopy) + } + } + + // Exit early if this transaction is missing parents. + if len(missingParents) > 0 { + log.Debugf("Tx %v is an orphan with missing parents: %v", + txHash, missingParents) + + return &MempoolAcceptResult{ + MissingParents: missingParents, + }, nil + } + + // Perform several checks on the transaction inputs using the invariant + // rules in blockchain for what transactions are allowed into blocks. + // Also returns the fees associated with the transaction which will be + // used later. + // + // NOTE: this check must be performed before `validateStandardness` to + // make sure a nil entry is not returned from `utxoView.LookupEntry`. + txFee, err := blockchain.CheckTransactionInputs( + tx, nextBlockHeight, utxoView, mp.cfg.ChainParams, + ) + if err != nil { + if cerr, ok := err.(blockchain.RuleError); ok { + return nil, chainRuleError(cerr) + } + return nil, err + } + + // Don't allow non-standard transactions or non-standard inputs if the + // network parameters forbid their acceptance. + err = mp.validateStandardness( + tx, nextBlockHeight, medianTimePast, utxoView, + ) + if err != nil { + return nil, err + } + + // Don't allow the transaction into the mempool unless its sequence + // lock is active, meaning that it'll be allowed into the next block + // with respect to its defined relative lock times. + sequenceLock, err := mp.cfg.CalcSequenceLock(tx, utxoView) + if err != nil { + if cerr, ok := err.(blockchain.RuleError); ok { + return nil, chainRuleError(cerr) + } + + return nil, err + } + + if !blockchain.SequenceLockActive( + sequenceLock, nextBlockHeight, medianTimePast, + ) { + + return nil, txRuleError(wire.RejectNonstandard, + "transaction's sequence locks on inputs not met") + } + + // Don't allow transactions with an excessive number of signature + // operations which would result in making it impossible to mine. + if err := mp.validateSigCost(tx, utxoView); err != nil { + return nil, err + } + + txSize := GetTxVirtualSize(tx) + + // Don't allow transactions with fees too low to get into a mined + // block. + err = mp.validateRelayFeeMet( + tx, txFee, txSize, utxoView, nextBlockHeight, isNew, rateLimit, + ) + if err != nil { + return nil, err + } + + // If the transaction has any conflicts, and we've made it this far, + // then we're processing a potential replacement. + var conflicts map[chainhash.Hash]*btcutil.Tx + if isReplacement { + conflicts, err = mp.validateReplacement(tx, txFee) + if err != nil { + return nil, err + } + } + + // Verify crypto signatures for each input and reject the transaction + // if any don't verify. + err = blockchain.ValidateTransactionScripts(tx, utxoView, + txscript.StandardVerifyFlags, mp.cfg.SigCache, + mp.cfg.HashCache) + if err != nil { + if cerr, ok := err.(blockchain.RuleError); ok { + return nil, chainRuleError(cerr) + } + return nil, err + } + + result := &MempoolAcceptResult{ + TxFee: btcutil.Amount(txFee), + TxSize: txSize, + Conflicts: conflicts, + utxoView: utxoView, + bestHeight: bestHeight, + } + + return result, nil +} + +// validateSegWitDeployment checks that when a transaction has witness data, +// segwit must be active. +func (mp *TxPool) validateSegWitDeployment(tx *btcutil.Tx) error { + // Exit early if this transaction doesn't have witness data. + if !tx.MsgTx().HasWitness() { + return nil + } + + // If a transaction has witness data, and segwit isn't active yet, then + // we won't accept it into the mempool as it can't be mined yet. + segwitActive, err := mp.cfg.IsDeploymentActive( + chaincfg.DeploymentSegwit, + ) + if err != nil { + return err + } + + // Exit early if segwit is active. + if segwitActive { + return nil + } + + simnetHint := "" + if mp.cfg.ChainParams.Net == wire.SimNet { + bestHeight := mp.cfg.BestHeight() + simnetHint = fmt.Sprintf(" (The threshold for segwit "+ + "activation is 300 blocks on simnet, current best "+ + "height is %d)", bestHeight) + } + str := fmt.Sprintf("transaction %v has witness data, "+ + "but segwit isn't active yet%s", tx.Hash(), simnetHint) + + return txRuleError(wire.RejectNonstandard, str) +} + +// validateStandardness checks the transaction passes both transaction standard +// and input standard. +func (mp *TxPool) validateStandardness(tx *btcutil.Tx, nextBlockHeight int32, + medianTimePast time.Time, utxoView *blockchain.UtxoViewpoint) error { + + // Exit early if we accept non-standard transactions. + // + // NOTE: if you modify this code to accept non-standard transactions, + // you should add code here to check that the transaction does a + // reasonable number of ECDSA signature verifications. + if mp.cfg.Policy.AcceptNonStd { + return nil + } + + // Check the transaction standard. + err := CheckTransactionStandard( + tx, nextBlockHeight, medianTimePast, + mp.cfg.Policy.MinRelayTxFee, mp.cfg.Policy.MaxTxVersion, + ) + if err != nil { + // Attempt to extract a reject code from the error so it can be + // retained. When not possible, fall back to a non standard + // error. + rejectCode, found := extractRejectCode(err) + if !found { + rejectCode = wire.RejectNonstandard + } + str := fmt.Sprintf("transaction %v is not standard: %v", + tx.Hash(), err) + + return txRuleError(rejectCode, str) + } + + // Check the inputs standard. + err = checkInputsStandard(tx, utxoView) + if err != nil { + // Attempt to extract a reject code from the error so it can be + // retained. When not possible, fall back to a non-standard + // error. + rejectCode, found := extractRejectCode(err) + if !found { + rejectCode = wire.RejectNonstandard + } + str := fmt.Sprintf("transaction %v has a non-standard "+ + "input: %v", tx.Hash(), err) + + return txRuleError(rejectCode, str) + } + + return nil +} + +// validateSigCost checks the cost to run the signature operations to make sure +// the number of singatures are sane. +func (mp *TxPool) validateSigCost(tx *btcutil.Tx, + utxoView *blockchain.UtxoViewpoint) error { + + // Since the coinbase address itself can contain signature operations, + // the maximum allowed signature operations per transaction is less + // than the maximum allowed signature operations per block. + // + // TODO(roasbeef): last bool should be conditional on segwit activation + sigOpCost, err := blockchain.GetSigOpCost( + tx, false, utxoView, true, true, + ) + if err != nil { + if cerr, ok := err.(blockchain.RuleError); ok { + return chainRuleError(cerr) + } + + return err + } + + // Exit early if the sig cost is under limit. + if sigOpCost <= mp.cfg.Policy.MaxSigOpCostPerTx { + return nil + } + + str := fmt.Sprintf("transaction %v sigop cost is too high: %d > %d", + tx.Hash(), sigOpCost, mp.cfg.Policy.MaxSigOpCostPerTx) + + return txRuleError(wire.RejectNonstandard, str) +} + +// validateRelayFeeMet checks that the min relay fee is covered by this +// transaction. +func (mp *TxPool) validateRelayFeeMet(tx *btcutil.Tx, txFee, txSize int64, + utxoView *blockchain.UtxoViewpoint, nextBlockHeight int32, + isNew, rateLimit bool) error { + + txHash := tx.Hash() + + // Most miners allow a free transaction area in blocks they mine to go + // alongside the area used for high-priority transactions as well as + // transactions with fees. A transaction size of up to 1000 bytes is + // considered safe to go into this section. Further, the minimum fee + // calculated below on its own would encourage several small + // transactions to avoid fees rather than one single larger transaction + // which is more desirable. Therefore, as long as the size of the + // transaction does not exceed 1000 less than the reserved space for + // high-priority transactions, don't require a fee for it. + minFee := calcMinRequiredTxRelayFee(txSize, mp.cfg.Policy.MinRelayTxFee) + + if txSize >= (DefaultBlockPrioritySize-1000) && txFee < minFee { + str := fmt.Sprintf("transaction %v has %d fees which is under "+ + "the required amount of %d", txHash, txFee, minFee) + + return txRuleError(wire.RejectInsufficientFee, str) + } + + // Exit early if the min relay fee is met. + if txFee >= minFee { + return nil + } + + // Exit early if this is neither a new tx or rate limited. + if !isNew && !rateLimit { + return nil + } + + // Require that free transactions have sufficient priority to be mined + // in the next block. Transactions which are being added back to the + // memory pool from blocks that have been disconnected during a reorg + // are exempted. + if isNew && !mp.cfg.Policy.DisableRelayPriority { + currentPriority := mining.CalcPriority( + tx.MsgTx(), utxoView, nextBlockHeight, + ) + if currentPriority <= mining.MinHighPriority { + str := fmt.Sprintf("transaction %v has insufficient "+ + "priority (%g <= %g)", txHash, + currentPriority, mining.MinHighPriority) + + return txRuleError(wire.RejectInsufficientFee, str) + } + } + + // We can only end up here when the rateLimit is true. Free-to-relay + // transactions are rate limited here to prevent penny-flooding with + // tiny transactions as a form of attack. + nowUnix := time.Now().Unix() + + // Decay passed data with an exponentially decaying ~10 minute window - + // matches bitcoind handling. + mp.pennyTotal *= math.Pow( + 1.0-1.0/600.0, float64(nowUnix-mp.lastPennyUnix), + ) + mp.lastPennyUnix = nowUnix + + // Are we still over the limit? + if mp.pennyTotal >= mp.cfg.Policy.FreeTxRelayLimit*10*1000 { + str := fmt.Sprintf("transaction %v has been rejected "+ + "by the rate limiter due to low fees", txHash) + + return txRuleError(wire.RejectInsufficientFee, str) + } + + oldTotal := mp.pennyTotal + mp.pennyTotal += float64(txSize) + log.Tracef("rate limit: curTotal %v, nextTotal: %v, limit %v", + oldTotal, mp.pennyTotal, mp.cfg.Policy.FreeTxRelayLimit*10*1000) + + return nil +} + // New returns a new memory pool for validating and storing standalone // transactions until they are mined into a block. func New(cfg *Config) *TxPool { From ca4261f028ff648bbd6d9c8786f311daac62c272 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Sat, 4 Nov 2023 02:08:38 +0800 Subject: [PATCH 0937/1056] btcjson: add `TestMempoolAcceptCmd` --- btcjson/chainsvrcmds.go | 22 ++++++++++++++++++++++ btcjson/chainsvrcmds_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index aa1d4415da..e314f35c32 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -1042,6 +1042,27 @@ func NewVerifyTxOutProofCmd(proof string) *VerifyTxOutProofCmd { } } +// TestMempoolAcceptCmd defines the testmempoolaccept JSON-RPC command. +type TestMempoolAcceptCmd struct { + // An array of hex strings of raw transactions. + RawTxns []string + + // Reject transactions whose fee rate is higher than the specified + // value, expressed in BTC/kvB, optional, default="0.10". + MaxFeeRate float64 `json:"omitempty"` +} + +// NewTestMempoolAcceptCmd returns a new instance which can be used to issue a +// testmempoolaccept JSON-RPC command. +func NewTestMempoolAcceptCmd(rawTxns []string, + maxFeeRate float64) *TestMempoolAcceptCmd { + + return &TestMempoolAcceptCmd{ + RawTxns: rawTxns, + MaxFeeRate: maxFeeRate, + } +} + func init() { // No special flags for commands in this file. flags := UsageFlag(0) @@ -1102,4 +1123,5 @@ func init() { MustRegisterCmd("verifychain", (*VerifyChainCmd)(nil), flags) MustRegisterCmd("verifymessage", (*VerifyMessageCmd)(nil), flags) MustRegisterCmd("verifytxoutproof", (*VerifyTxOutProofCmd)(nil), flags) + MustRegisterCmd("testmempoolaccept", (*TestMempoolAcceptCmd)(nil), flags) } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 99983288b1..eddfb03788 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1472,6 +1472,34 @@ func TestChainSvrCmds(t *testing.T) { marshalled: `{"jsonrpc":"1.0","method":"getzmqnotifications","params":[],"id":1}`, unmarshalled: &btcjson.GetZmqNotificationsCmd{}, }, + { + name: "testmempoolaccept", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("testmempoolaccept", []string{"rawhex"}, 0.1) + }, + staticCmd: func() interface{} { + return btcjson.NewTestMempoolAcceptCmd([]string{"rawhex"}, 0.1) + }, + marshalled: `{"jsonrpc":"1.0","method":"testmempoolaccept","params":[["rawhex"],0.1],"id":1}`, + unmarshalled: &btcjson.TestMempoolAcceptCmd{ + RawTxns: []string{"rawhex"}, + MaxFeeRate: 0.1, + }, + }, + { + name: "testmempoolaccept with maxfeerate", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("testmempoolaccept", []string{"rawhex"}, 0.01) + }, + staticCmd: func() interface{} { + return btcjson.NewTestMempoolAcceptCmd([]string{"rawhex"}, 0.01) + }, + marshalled: `{"jsonrpc":"1.0","method":"testmempoolaccept","params":[["rawhex"],0.01],"id":1}`, + unmarshalled: &btcjson.TestMempoolAcceptCmd{ + RawTxns: []string{"rawhex"}, + MaxFeeRate: 0.01, + }, + }, } t.Logf("Running %d tests", len(tests)) From 889cdb4f663a8c6f07afac120672b3ebe161a3d3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 5 Jan 2024 19:12:09 +0800 Subject: [PATCH 0938/1056] multi: add more bitcoind versions to the `BackendVersion` This commit adds bitcoind version 22.0 and 25.0 to our `BackendVersion` set to handle the `testmempoolaccept` RPC calls. A unit test is added to make sure the parser works as expected. --- rpcclient/chain.go | 7 ++-- rpcclient/chain_test.go | 9 +++-- rpcclient/infrastructure.go | 52 ++++++++++++++++++++++++-- rpcclient/infrastructure_test.go | 64 ++++++++++++++++++++++++++++++++ rpcclient/rawtransactions.go | 8 ++-- 5 files changed, 123 insertions(+), 17 deletions(-) create mode 100644 rpcclient/infrastructure_test.go diff --git a/rpcclient/chain.go b/rpcclient/chain.go index b21665991f..f2ce1ea626 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -440,17 +440,16 @@ func unmarshalPartialGetBlockChainInfoResult(res []byte) (*btcjson.GetBlockChain func unmarshalGetBlockChainInfoResultSoftForks(chainInfo *btcjson.GetBlockChainInfoResult, version BackendVersion, res []byte) error { - switch version { // Versions of bitcoind on or after v0.19.0 use the unified format. - case BitcoindPost19: + if version > BitcoindPre19 { var softForks btcjson.UnifiedSoftForks if err := json.Unmarshal(res, &softForks); err != nil { return err } chainInfo.UnifiedSoftForks = &softForks + } else { - // All other versions use the original format. - default: + // All other versions use the original format. var softForks btcjson.SoftForks if err := json.Unmarshal(res, &softForks); err != nil { return err diff --git a/rpcclient/chain_test.go b/rpcclient/chain_test.go index de8d3a740e..ba76078a16 100644 --- a/rpcclient/chain_test.go +++ b/rpcclient/chain_test.go @@ -2,13 +2,14 @@ package rpcclient import ( "errors" - "github.com/gorilla/websocket" "net/http" "net/http/httptest" "strings" "sync" "testing" "time" + + "github.com/gorilla/websocket" ) var upgrader = websocket.Upgrader{} @@ -33,7 +34,7 @@ func TestUnmarshalGetBlockChainInfoResultSoftForks(t *testing.T) { }, { name: "bitcoind >= 0.19.0 with separate softforks", - version: BitcoindPost19, + version: BitcoindPre22, res: []byte(`{"softforks": [{"version": 2}]}`), compatible: false, }, @@ -45,7 +46,7 @@ func TestUnmarshalGetBlockChainInfoResultSoftForks(t *testing.T) { }, { name: "bitcoind >= 0.19.0 with unified softforks", - version: BitcoindPost19, + version: BitcoindPre22, res: []byte(`{"softforks": {"segwit": {"type": "bip9"}}}`), compatible: true, }, @@ -87,7 +88,7 @@ func TestUnmarshalGetBlockChainInfoResultSoftForks(t *testing.T) { // If the version is compatible with the response, we // should expect to see the proper softforks field set. - if test.version == BitcoindPost19 && + if test.version == BitcoindPre22 && info.SoftForks != nil { t.Fatal("expected SoftForks to be empty") } diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index eddfb77700..1ddfa356dc 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -110,14 +110,45 @@ const ( // BitcoindPre19 represents a bitcoind version before 0.19.0. BitcoindPre19 BackendVersion = iota - // BitcoindPost19 represents a bitcoind version equal to or greater than - // 0.19.0. - BitcoindPost19 + // BitcoindPre22 represents a bitcoind version equal to or greater than + // 0.19.0 and smaller than 22.0.0. + BitcoindPre22 + + // BitcoindPre25 represents a bitcoind version equal to or greater than + // 22.0.0 and smaller than 25.0.0. + BitcoindPre25 + + // BitcoindPre25 represents a bitcoind version equal to or greater than + // 25.0.0. + BitcoindPost25 // Btcd represents a catch-all btcd version. Btcd ) +// String returns a human-readable backend version. +func (b BackendVersion) String() string { + switch b { + case BitcoindPre19: + return "bitcoind 0.19 and below" + + case BitcoindPre22: + return "bitcoind v0.19.0-v22.0.0" + + case BitcoindPre25: + return "bitcoind v22.0.0-v25.0.0" + + case BitcoindPost25: + return "bitcoind v25.0.0 and above" + + case Btcd: + return "btcd" + + default: + return "unknown" + } +} + // Client represents a Bitcoin RPC client which allows easy access to the // various RPC methods available on a Bitcoin RPC server. Each of the wrapper // functions handle the details of converting the passed and return types to and @@ -1579,6 +1610,12 @@ const ( // bitcoind19Str is the string representation of bitcoind v0.19.0. bitcoind19Str = "0.19.0" + // bitcoind22Str is the string representation of bitcoind v22.0.0. + bitcoind22Str = "22.0.0" + + // bitcoind25Str is the string representation of bitcoind v25.0.0. + bitcoind25Str = "25.0.0" + // bitcoindVersionPrefix specifies the prefix included in every bitcoind // version exposed through GetNetworkInfo. bitcoindVersionPrefix = "/Satoshi:" @@ -1600,8 +1637,15 @@ func parseBitcoindVersion(version string) BackendVersion { switch { case version < bitcoind19Str: return BitcoindPre19 + + case version < bitcoind22Str: + return BitcoindPre22 + + case version < bitcoind25Str: + return BitcoindPre25 + default: - return BitcoindPost19 + return BitcoindPost25 } } diff --git a/rpcclient/infrastructure_test.go b/rpcclient/infrastructure_test.go new file mode 100644 index 0000000000..e97fa275c0 --- /dev/null +++ b/rpcclient/infrastructure_test.go @@ -0,0 +1,64 @@ +package rpcclient + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// TestParseBitcoindVersion checks that the correct version from bitcoind's +// `getnetworkinfo` RPC call is parsed. +func TestParseBitcoindVersion(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + rpcVersion string + parsedVersion BackendVersion + }{ + { + name: "parse version 0.19 and below", + rpcVersion: "/Satoshi:0.18.0/", + parsedVersion: BitcoindPre19, + }, + { + name: "parse version 0.19", + rpcVersion: "/Satoshi:0.19.0/", + parsedVersion: BitcoindPre22, + }, + { + name: "parse version 0.19 - 22.0", + rpcVersion: "/Satoshi:0.20.1/", + parsedVersion: BitcoindPre22, + }, + { + name: "parse version 22.0", + rpcVersion: "/Satoshi:22.0.0/", + parsedVersion: BitcoindPre25, + }, + { + name: "parse version 22.0 - 25.0", + rpcVersion: "/Satoshi:23.0.0/", + parsedVersion: BitcoindPre25, + }, + { + name: "parse version 25.0", + rpcVersion: "/Satoshi:25.0.0/", + parsedVersion: BitcoindPost25, + }, + { + name: "parse version 25.0 and above", + rpcVersion: "/Satoshi:26.0.0/", + parsedVersion: BitcoindPost25, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + version := parseBitcoindVersion(tc.rpcVersion) + require.Equal(t, tc.parsedVersion, version) + }) + } +} diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 1df6195220..b49ec41d8c 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -358,9 +358,8 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut } var cmd *btcjson.SendRawTransactionCmd - switch version { // Starting from bitcoind v0.19.0, the MaxFeeRate field should be used. - case BitcoindPost19: + if version > BitcoindPre19 { // Using a 0 MaxFeeRate is interpreted as a maximum fee rate not // being enforced by bitcoind. var maxFeeRate int32 @@ -368,9 +367,8 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut maxFeeRate = defaultMaxFeeRate } cmd = btcjson.NewBitcoindSendRawTransactionCmd(txHex, maxFeeRate) - - // Otherwise, use the AllowHighFees field. - default: + } else { + // Otherwise, use the AllowHighFees field. cmd = btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees) } From c7e40280d56eca20394e938ef0c2e82df17e54e5 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Sat, 4 Nov 2023 02:26:39 +0800 Subject: [PATCH 0939/1056] rpcclient: support `testmempoolaccept` for `bitcoind` --- btcjson/chainsvrresults.go | 60 +++++++++++++++- rpcclient/errors.go | 13 ++++ rpcclient/rawtransactions.go | 132 +++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 rpcclient/errors.go diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 41b93f8570..8f59f77676 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -304,8 +304,8 @@ type GetBlockTemplateResult struct { NonceRange string `json:"noncerange,omitempty"` // Block proposal from BIP 0023. - Capabilities []string `json:"capabilities,omitempty"` - RejectReasion string `json:"reject-reason,omitempty"` + Capabilities []string `json:"capabilities,omitempty"` + RejectReason string `json:"reject-reason,omitempty"` } // GetMempoolEntryResult models the data returned from the getmempoolentry's @@ -855,3 +855,59 @@ type LoadWalletResult struct { type DumpWalletResult struct { Filename string `json:"filename"` } + +// TestMempoolAcceptResult models the data from the testmempoolaccept command. +// The result of the mempool acceptance test for each raw transaction in the +// input array. Returns results for each transaction in the same order they +// were passed in. Transactions that cannot be fully validated due to failures +// in other transactions will not contain an 'allowed' result. +type TestMempoolAcceptResult struct { + // Txid is the transaction hash in hex. + Txid string `json:"txid"` + + // Wtxid is the transaction witness hash in hex. + Wtxid string `json:"wtxid"` + + // PackageError is the package validation error, if any (only possible + // if rawtxs had more than 1 transaction). + PackageError string `json:"package-error"` + + // Allowed specifies whether this tx would be accepted to the mempool + // and pass client-specified maxfeerate. If not present, the tx was not + // fully validated due to a failure in another tx in the list. + Allowed bool `json:"allowed,omitempty"` + + // Vsize is the virtual transaction size as defined in BIP 141. This is + // different from actual serialized size for witness transactions as + // witness data is discounted (only present when 'allowed' is true) + Vsize int32 `json:"vsize,omitempty"` + + // Fees specifies the transaction fees (only present if 'allowed' is + // true). + Fees *TestMempoolAcceptFees `json:"fees,omitempty"` + + // RejectReason is the rejection string (only present when 'allowed' is + // false). + RejectReason string `json:"reject-reason,omitempty"` +} + +// TestMempoolAcceptFees models the `fees` section from the testmempoolaccept +// command. +type TestMempoolAcceptFees struct { + // Base is the transaction fee in BTC. + Base float64 `json:"base"` + + // EffectiveFeeRate specifies the effective feerate in BTC per KvB. May + // differ from the base feerate if, for example, there are modified + // fees from prioritisetransaction or a package feerate was used. + // + // NOTE: this field only exists in bitcoind v25.0 and above. + EffectiveFeeRate float64 `json:"effective-feerate"` + + // EffectiveIncludes specifies transactions whose fees and vsizes are + // included in effective-feerate. Each item is a transaction wtxid in + // hex. + // + // NOTE: this field only exists in bitcoind v25.0 and above. + EffectiveIncludes []string `json:"effective-includes"` +} diff --git a/rpcclient/errors.go b/rpcclient/errors.go new file mode 100644 index 0000000000..62de9b3806 --- /dev/null +++ b/rpcclient/errors.go @@ -0,0 +1,13 @@ +package rpcclient + +import "errors" + +var ( + // ErrBitcoindVersion is returned when running against a bitcoind that + // is older than the minimum version supported by the rpcclient. + ErrBitcoindVersion = errors.New("bitcoind version too low") + + // ErrInvalidParam is returned when the caller provides an invalid + // parameter to an RPC method. + ErrInvalidParam = errors.New("invalid param") +) diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index b49ec41d8c..a683021946 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/hex" "encoding/json" + "fmt" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/btcutil" @@ -880,3 +881,134 @@ func (c *Client) DecodeScriptAsync(serializedScript []byte) FutureDecodeScriptRe func (c *Client) DecodeScript(serializedScript []byte) (*btcjson.DecodeScriptResult, error) { return c.DecodeScriptAsync(serializedScript).Receive() } + +// FutureTestMempoolAcceptResult is a future promise to deliver the result +// of a TestMempoolAccept RPC invocation (or an applicable error). +type FutureTestMempoolAcceptResult chan *Response + +// Receive waits for the Response promised by the future and returns the +// response from TestMempoolAccept. +func (r FutureTestMempoolAcceptResult) Receive() ( + []*btcjson.TestMempoolAcceptResult, error) { + + response, err := ReceiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal as an array of TestMempoolAcceptResult items. + var results []*btcjson.TestMempoolAcceptResult + + err = json.Unmarshal(response, &results) + if err != nil { + return nil, err + } + + return results, nil +} + +// TestMempoolAcceptAsync returns an instance of a type that can be used to get +// the result of the RPC at some future time by invoking the Receive function +// on the returned instance. +// +// See TestMempoolAccept for the blocking version and more details. +func (c *Client) TestMempoolAcceptAsync(txns []*wire.MsgTx, + maxFeeRate float64) FutureTestMempoolAcceptResult { + + // Due to differences in the testmempoolaccept API for different + // backends, we'll need to inspect our version and construct the + // appropriate request. + version, err := c.BackendVersion() + if err != nil { + return newFutureError(err) + } + + log.Debugf("TestMempoolAcceptAsync: backend version %s", version) + + // Exit early if the version is below 22.0.0. + // + // Based on the history of `testmempoolaccept` in bitcoind, + // - introduced in 0.17.0 + // - unchanged in 0.18.0 + // - allowhighfees(bool) param is changed to maxfeerate(numeric) in + // 0.19.0 + // - unchanged in 0.20.0 + // - added fees and vsize fields in its response in 0.21.0 + // - allow more than one txes in param rawtx and added package-error + // and wtxid fields in its response in 0.22.0 + // - unchanged in 0.23.0 + // - unchanged in 0.24.0 + // - added effective-feerate and effective-includes fields in its + // response in 0.25.0 + // + // We decide to not support this call for versions below 22.0.0. as the + // request/response formats are very different. + if version < BitcoindPre22 { + err := fmt.Errorf("%w: %v", ErrBitcoindVersion, version) + return newFutureError(err) + } + + // The maximum number of transactions allowed is 25. + if len(txns) > 25 { + err := fmt.Errorf("%w: too many transactions provided", + ErrInvalidParam) + return newFutureError(err) + } + + // Exit early if an empty array of transactions is provided. + if len(txns) == 0 { + err := fmt.Errorf("%w: no transactions provided", + ErrInvalidParam) + return newFutureError(err) + } + + // Iterate all the transactions and turn them into hex strings. + rawTxns := make([]string, 0, len(txns)) + for _, tx := range txns { + // Serialize the transaction and convert to hex string. + buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) + + // TODO(yy): add similar checks found in `BtcDecode` to + // `BtcEncode` - atm it just serializes bytes without any + // bitcoin-specific checks. + if err := tx.Serialize(buf); err != nil { + err = fmt.Errorf("%w: %v", ErrInvalidParam, err) + return newFutureError(err) + } + + rawTx := hex.EncodeToString(buf.Bytes()) + rawTxns = append(rawTxns, rawTx) + + // Sanity check the provided tx is valid, which can be removed + // once we have similar checks added in `BtcEncode`. + // + // NOTE: must be performed after buf.Bytes is copied above. + // + // TODO(yy): remove it once the above TODO is addressed. + if err := tx.Deserialize(buf); err != nil { + err = fmt.Errorf("%w: %v", ErrInvalidParam, err) + return newFutureError(err) + } + } + + cmd := btcjson.NewTestMempoolAcceptCmd(rawTxns, maxFeeRate) + + return c.SendCmd(cmd) +} + +// TestMempoolAccept returns result of mempool acceptance tests indicating if +// raw transaction(s) would be accepted by mempool. +// +// If multiple transactions are passed in, parents must come before children +// and package policies apply: the transactions cannot conflict with any +// mempool transactions or each other. +// +// If one transaction fails, other transactions may not be fully validated (the +// 'allowed' key will be blank). +// +// The maximum number of transactions allowed is 25. +func (c *Client) TestMempoolAccept(txns []*wire.MsgTx, + maxFeeRate float64) ([]*btcjson.TestMempoolAcceptResult, error) { + + return c.TestMempoolAcceptAsync(txns, maxFeeRate).Receive() +} From 4842b23247096e08327e8ff1447ee89e1617cf9d Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 29 Nov 2023 16:47:18 +0800 Subject: [PATCH 0940/1056] mempool+rpcserver: add interface `TxMempool` This commit adds a new interface `TxMempool` which defines how other subsystems interact with `TxPool`. --- mempool/interface.go | 71 ++++++++++++++++++++++++++++++++++++++++++++ mempool/mempool.go | 3 ++ rpcserver.go | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 mempool/interface.go diff --git a/mempool/interface.go b/mempool/interface.go new file mode 100644 index 0000000000..f6fe1f059a --- /dev/null +++ b/mempool/interface.go @@ -0,0 +1,71 @@ +package mempool + +import ( + "time" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" +) + +// TxMempool defines an interface that's used by other subsystems to interact +// with the mempool. +type TxMempool interface { + // LastUpdated returns the last time a transaction was added to or + // removed from the source pool. + LastUpdated() time.Time + + // TxDescs returns a slice of descriptors for all the transactions in + // the pool. + TxDescs() []*TxDesc + + // RawMempoolVerbose returns all the entries in the mempool as a fully + // populated btcjson result. + RawMempoolVerbose() map[string]*btcjson.GetRawMempoolVerboseResult + + // Count returns the number of transactions in the main pool. It does + // not include the orphan pool. + Count() int + + // FetchTransaction returns the requested transaction from the + // transaction pool. This only fetches from the main transaction pool + // and does not include orphans. + FetchTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error) + + // HaveTransaction returns whether or not the passed transaction + // already exists in the main pool or in the orphan pool. + HaveTransaction(hash *chainhash.Hash) bool + + // ProcessTransaction is the main workhorse for handling insertion of + // new free-standing transactions into the memory pool. It includes + // functionality such as rejecting duplicate transactions, ensuring + // transactions follow all rules, orphan transaction handling, and + // insertion into the memory pool. + // + // It returns a slice of transactions added to the mempool. When the + // error is nil, the list will include the passed transaction itself + // along with any additional orphan transactions that were added as a + // result of the passed one being accepted. + ProcessTransaction(tx *btcutil.Tx, allowOrphan, + rateLimit bool, tag Tag) ([]*TxDesc, error) + + // RemoveTransaction removes the passed transaction from the mempool. + // When the removeRedeemers flag is set, any transactions that redeem + // outputs from the removed transaction will also be removed + // recursively from the mempool, as they would otherwise become + // orphans. + RemoveTransaction(tx *btcutil.Tx, removeRedeemers bool) + + // CheckMempoolAcceptance behaves similarly to bitcoind's + // `testmempoolaccept` RPC method. It will perform a series of checks + // to decide whether this transaction can be accepted to the mempool. + // If not, the specific error is returned and the caller needs to take + // actions based on it. + CheckMempoolAcceptance(tx *btcutil.Tx) (*MempoolAcceptResult, error) + + // CheckSpend checks whether the passed outpoint is already spent by + // a transaction in the mempool. If that's the case the spending + // transaction will be returned, if not nil will be returned. + CheckSpend(op wire.OutPoint) *btcutil.Tx +} diff --git a/mempool/mempool.go b/mempool/mempool.go index f6e81b6d90..6913ac9e78 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -196,6 +196,9 @@ type TxPool struct { // Ensure the TxPool type implements the mining.TxSource interface. var _ mining.TxSource = (*TxPool)(nil) +// Ensure the TxPool type implements the TxMemPool interface. +var _ TxMempool = (*TxPool)(nil) + // removeOrphan is the internal function which implements the public // RemoveOrphan. See the comment for RemoveOrphan for more details. // diff --git a/rpcserver.go b/rpcserver.go index 94980c463f..f74705c52f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4633,7 +4633,7 @@ type rpcserverConfig struct { DB database.DB // TxMemPool defines the transaction memory pool to interact with. - TxMemPool *mempool.TxPool + TxMemPool mempool.TxMempool // These fields allow the RPC server to interface with mining. // From 6c9f7fe7b91072987c3ba54c3d22f8735fd8a1a6 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Sun, 5 Nov 2023 06:59:30 +0800 Subject: [PATCH 0941/1056] btcd: add new RPC method `testmempoolaccept` --- mempool/mocks.go | 121 ++++++++++++++ rpcserver.go | 124 ++++++++++++++ rpcserver_test.go | 413 ++++++++++++++++++++++++++++++++++++++++++++++ rpcserverhelp.go | 18 ++ 4 files changed, 676 insertions(+) create mode 100644 mempool/mocks.go create mode 100644 rpcserver_test.go diff --git a/mempool/mocks.go b/mempool/mocks.go new file mode 100644 index 0000000000..5f50bb0730 --- /dev/null +++ b/mempool/mocks.go @@ -0,0 +1,121 @@ +package mempool + +import ( + "time" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/wire" + "github.com/stretchr/testify/mock" +) + +// MockTxMempool is a mock implementation of the TxMempool interface. +type MockTxMempool struct { + mock.Mock +} + +// Ensure the MockTxMempool implements the TxMemPool interface. +var _ TxMempool = (*MockTxMempool)(nil) + +// LastUpdated returns the last time a transaction was added to or removed from +// the source pool. +func (m *MockTxMempool) LastUpdated() time.Time { + args := m.Called() + return args.Get(0).(time.Time) +} + +// TxDescs returns a slice of descriptors for all the transactions in the pool. +func (m *MockTxMempool) TxDescs() []*TxDesc { + args := m.Called() + return args.Get(0).([]*TxDesc) +} + +// RawMempoolVerbose returns all the entries in the mempool as a fully +// populated btcjson result. +func (m *MockTxMempool) RawMempoolVerbose() map[string]*btcjson. + GetRawMempoolVerboseResult { + + args := m.Called() + return args.Get(0).(map[string]*btcjson.GetRawMempoolVerboseResult) +} + +// Count returns the number of transactions in the main pool. It does not +// include the orphan pool. +func (m *MockTxMempool) Count() int { + args := m.Called() + return args.Get(0).(int) +} + +// FetchTransaction returns the requested transaction from the transaction +// pool. This only fetches from the main transaction pool and does not include +// orphans. +func (m *MockTxMempool) FetchTransaction( + txHash *chainhash.Hash) (*btcutil.Tx, error) { + + args := m.Called(txHash) + + if args.Get(0) == nil { + return nil, args.Error(1) + } + + return args.Get(0).(*btcutil.Tx), args.Error(1) +} + +// HaveTransaction returns whether or not the passed transaction already exists +// in the main pool or in the orphan pool. +func (m *MockTxMempool) HaveTransaction(hash *chainhash.Hash) bool { + args := m.Called(hash) + return args.Get(0).(bool) +} + +// ProcessTransaction is the main workhorse for handling insertion of new +// free-standing transactions into the memory pool. It includes functionality +// such as rejecting duplicate transactions, ensuring transactions follow all +// rules, orphan transaction handling, and insertion into the memory pool. +func (m *MockTxMempool) ProcessTransaction(tx *btcutil.Tx, allowOrphan, + rateLimit bool, tag Tag) ([]*TxDesc, error) { + + args := m.Called(tx, allowOrphan, rateLimit, tag) + + if args.Get(0) == nil { + return nil, args.Error(1) + } + + return args.Get(0).([]*TxDesc), args.Error(1) +} + +// RemoveTransaction removes the passed transaction from the mempool. When the +// removeRedeemers flag is set, any transactions that redeem outputs from the +// removed transaction will also be removed recursively from the mempool, as +// they would otherwise become orphans. +func (m *MockTxMempool) RemoveTransaction(tx *btcutil.Tx, + removeRedeemers bool) { + + m.Called(tx, removeRedeemers) +} + +// CheckMempoolAcceptance behaves similarly to bitcoind's `testmempoolaccept` +// RPC method. It will perform a series of checks to decide whether this +// transaction can be accepted to the mempool. If not, the specific error is +// returned and the caller needs to take actions based on it. +func (m *MockTxMempool) CheckMempoolAcceptance( + tx *btcutil.Tx) (*MempoolAcceptResult, error) { + + args := m.Called(tx) + + if args.Get(0) == nil { + return nil, args.Error(1) + } + + return args.Get(0).(*MempoolAcceptResult), args.Error(1) +} + +// CheckSpend checks whether the passed outpoint is already spent by a +// transaction in the mempool. If that's the case the spending transaction will +// be returned, if not nil will be returned. +func (m *MockTxMempool) CheckSpend(op wire.OutPoint) *btcutil.Tx { + args := m.Called(op) + + return args.Get(0).(*btcutil.Tx) +} diff --git a/rpcserver.go b/rpcserver.go index f74705c52f..36c00be18f 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -75,6 +75,10 @@ const ( // maxProtocolVersion is the max protocol version the server supports. maxProtocolVersion = 70002 + + // defaultMaxFeeRate is the default value to use(0.1 BTC/kvB) when the + // `MaxFee` field is not set when calling `testmempoolaccept`. + defaultMaxFeeRate = 0.1 ) var ( @@ -179,6 +183,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "verifychain": handleVerifyChain, "verifymessage": handleVerifyMessage, "version": handleVersion, + "testmempoolaccept": handleTestMempoolAccept, } // list of commands that we recognize, but for which btcd has no support because @@ -3806,6 +3811,125 @@ func handleVersion(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (in return result, nil } +// handleTestMempoolAccept implements the testmempoolaccept command. +func handleTestMempoolAccept(s *rpcServer, cmd interface{}, + closeChan <-chan struct{}) (interface{}, error) { + + c := cmd.(*btcjson.TestMempoolAcceptCmd) + + // Create txns to hold the decoded tx. + txns := make([]*btcutil.Tx, 0, len(c.RawTxns)) + + // Iterate the raw hex slice and decode them. + for _, rawTx := range c.RawTxns { + rawBytes, err := hex.DecodeString(rawTx) + if err != nil { + return nil, rpcDecodeHexError(rawTx) + } + + tx, err := btcutil.NewTxFromBytes(rawBytes) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCDeserialization, + Message: "TX decode failed: " + err.Error(), + } + } + + txns = append(txns, tx) + } + + results := make([]*btcjson.TestMempoolAcceptResult, 0, len(txns)) + for _, tx := range txns { + // Create a test result item. + item := &btcjson.TestMempoolAcceptResult{ + Txid: tx.Hash().String(), + Wtxid: tx.WitnessHash().String(), + } + + // Check the mempool acceptance. + result, err := s.cfg.TxMemPool.CheckMempoolAcceptance(tx) + + // If an error is returned, this tx is not allow, hence we + // record the reason. + if err != nil { + item.Allowed = false + + // TODO(yy): differentiate the errors and put package + // error in `PackageError` field. + item.RejectReason = err.Error() + + results = append(results, item) + + // Move to the next transaction. + continue + } + + // If this transaction is an orphan, it's not allowed. + if result.MissingParents != nil { + item.Allowed = false + + // NOTE: "missing-inputs" is what bitcoind returns + // here, so we mimic the same error message. + item.RejectReason = "missing-inputs" + + results = append(results, item) + + // Move to the next transaction. + continue + } + + // Otherwise this tx is allowed if its fee rate is below the + // max fee rate, we now patch the fields in + // `TestMempoolAcceptItem` as much as possible. + // + // Calculate the fee field and validate its fee rate. + item.Fees, item.Allowed = validateFeeRate( + result.TxFee, result.TxSize, c.MaxFeeRate, + ) + + // If the fee rate check passed, assign the corresponding + // fields. + if item.Allowed { + item.Vsize = int32(result.TxSize) + } else { + // NOTE: "max-fee-exceeded" is what bitcoind returns + // here, so we mimic the same error message. + item.RejectReason = "max-fee-exceeded" + } + + results = append(results, item) + } + + return results, nil +} + +// validateFeeRate checks that the fee rate used by transaction doesn't exceed +// the max fee rate specified. +func validateFeeRate(feeSats btcutil.Amount, txSize int64, + maxFeeRate float64) (*btcjson.TestMempoolAcceptFees, bool) { + + // Calculate fee rate in sats/kvB. + feeRateSatsPerKVB := feeSats * 1e3 / btcutil.Amount(txSize) + + // Convert sats/vB to BTC/kvB. + feeRate := feeRateSatsPerKVB.ToBTC() + + // Get the max fee rate, if not provided, default to 0.1 BTC/kvB. + if maxFeeRate == 0 { + maxFeeRate = defaultMaxFeeRate + } + + // If the fee rate is above the max fee rate, this tx is not accepted. + if feeRate > maxFeeRate { + return nil, false + } + + return &btcjson.TestMempoolAcceptFees{ + Base: feeSats.ToBTC(), + EffectiveFeeRate: feeRate, + }, true +} + // rpcServer provides a concurrent safe RPC server to a chain server. type rpcServer struct { started int32 diff --git a/rpcserver_test.go b/rpcserver_test.go new file mode 100644 index 0000000000..6ca15766c3 --- /dev/null +++ b/rpcserver_test.go @@ -0,0 +1,413 @@ +package main + +import ( + "encoding/hex" + "errors" + "testing" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/mempool" + "github.com/stretchr/testify/require" +) + +// TestHandleTestMempoolAcceptFailDecode checks that when invalid hex string is +// used as the raw txns, the corresponding error is returned. +func TestHandleTestMempoolAcceptFailDecode(t *testing.T) { + t.Parallel() + + require := require.New(t) + + // Create a testing server. + s := &rpcServer{} + + testCases := []struct { + name string + txns []string + expectedErrCode btcjson.RPCErrorCode + }{ + { + name: "hex decode fail", + txns: []string{"invalid"}, + expectedErrCode: btcjson.ErrRPCDecodeHexString, + }, + { + name: "tx decode fail", + txns: []string{"696e76616c6964"}, + expectedErrCode: btcjson.ErrRPCDeserialization, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + // Create a request that uses invalid raw txns. + cmd := btcjson.NewTestMempoolAcceptCmd(tc.txns, 0) + + // Call the method under test. + closeChan := make(chan struct{}) + result, err := handleTestMempoolAccept( + s, cmd, closeChan, + ) + + // Ensure the expected error is returned. + require.Error(err) + rpcErr, ok := err.(*btcjson.RPCError) + require.True(ok) + require.Equal(tc.expectedErrCode, rpcErr.Code) + + // No result should be returned. + require.Nil(result) + }) + } +} + +var ( + // TODO(yy): make a `btctest` package and move these testing txns there + // so they be used in other tests. + // + // txHex1 is taken from `txscript/data/tx_valid.json`. + txHex1 = "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b" + + "49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3" + + "000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507a" + + "c48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0" + + "140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271a" + + "d504b88ac00000000" + + // txHex2 is taken from `txscript/data/tx_valid.json`. + txHex2 = "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b" + + "49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3" + + "000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507a" + + "c48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01fffffff" + + "f0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c27" + + "1ad504b88ac00000000" + + // txHex3 is taken from `txscript/data/tx_valid.json`. + txHex3 = "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b" + + "49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621e" + + "f3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc350" + + "7ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01fffffff" + + "f0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c27" + + "1ad504b88ac00000000" +) + +// decodeTxHex decodes the given hex string into a transaction. +func decodeTxHex(t *testing.T, txHex string) *btcutil.Tx { + rawBytes, err := hex.DecodeString(txHex) + require.NoError(t, err) + tx, err := btcutil.NewTxFromBytes(rawBytes) + require.NoError(t, err) + + return tx +} + +// TestHandleTestMempoolAcceptMixedResults checks that when different txns get +// different responses from calling the mempool method `CheckMempoolAcceptance` +// their results are correctly returned. +func TestHandleTestMempoolAcceptMixedResults(t *testing.T) { + t.Parallel() + + require := require.New(t) + + // Create a mock mempool. + mm := &mempool.MockTxMempool{} + + // Create a testing server with the mock mempool. + s := &rpcServer{cfg: rpcserverConfig{ + TxMemPool: mm, + }} + + // Decode the hex so we can assert the mock mempool is called with it. + tx1 := decodeTxHex(t, txHex1) + tx2 := decodeTxHex(t, txHex2) + tx3 := decodeTxHex(t, txHex3) + + // Create a slice to hold the expected results. We will use three txns + // so we expect threeresults. + expectedResults := make([]*btcjson.TestMempoolAcceptResult, 3) + + // We now mock the first call to `CheckMempoolAcceptance` to return an + // error. + dummyErr := errors.New("dummy error") + mm.On("CheckMempoolAcceptance", tx1).Return(nil, dummyErr).Once() + + // Since the call failed, we expect the first result to give us the + // error. + expectedResults[0] = &btcjson.TestMempoolAcceptResult{ + Txid: tx1.Hash().String(), + Wtxid: tx1.WitnessHash().String(), + Allowed: false, + RejectReason: dummyErr.Error(), + } + + // We mock the second call to `CheckMempoolAcceptance` to return a + // result saying the tx is missing inputs. + mm.On("CheckMempoolAcceptance", tx2).Return( + &mempool.MempoolAcceptResult{ + MissingParents: []*chainhash.Hash{}, + }, nil, + ).Once() + + // We expect the second result to give us the missing-inputs error. + expectedResults[1] = &btcjson.TestMempoolAcceptResult{ + Txid: tx2.Hash().String(), + Wtxid: tx2.WitnessHash().String(), + Allowed: false, + RejectReason: "missing-inputs", + } + + // We mock the third call to `CheckMempoolAcceptance` to return a + // result saying the tx allowed. + const feeSats = btcutil.Amount(1000) + mm.On("CheckMempoolAcceptance", tx3).Return( + &mempool.MempoolAcceptResult{ + TxFee: feeSats, + TxSize: 100, + }, nil, + ).Once() + + // We expect the third result to give us the fee details. + expectedResults[2] = &btcjson.TestMempoolAcceptResult{ + Txid: tx3.Hash().String(), + Wtxid: tx3.WitnessHash().String(), + Allowed: true, + Vsize: 100, + Fees: &btcjson.TestMempoolAcceptFees{ + Base: feeSats.ToBTC(), + EffectiveFeeRate: feeSats.ToBTC() * 1e3 / 100, + }, + } + + // Create a mock request with default max fee rate of 0.1 BTC/KvB. + cmd := btcjson.NewTestMempoolAcceptCmd( + []string{txHex1, txHex2, txHex3}, 0.1, + ) + + // Call the method handler and assert the expected results are + // returned. + closeChan := make(chan struct{}) + results, err := handleTestMempoolAccept(s, cmd, closeChan) + require.NoError(err) + require.Equal(expectedResults, results) + + // Assert the mocked method is called as expected. + mm.AssertExpectations(t) +} + +// TestValidateFeeRate checks that `validateFeeRate` behaves as expected. +func TestValidateFeeRate(t *testing.T) { + t.Parallel() + + const ( + // testFeeRate is in BTC/kvB. + testFeeRate = 0.1 + + // testTxSize is in vb. + testTxSize = 100 + + // testFeeSats is in sats. + // We have 0.1BTC/kvB = + // 0.1 * 1e8 sats/kvB = + // 0.1 * 1e8 / 1e3 sats/vb = 0.1 * 1e5 sats/vb. + testFeeSats = btcutil.Amount(testFeeRate * 1e5 * testTxSize) + ) + + testCases := []struct { + name string + feeSats btcutil.Amount + txSize int64 + maxFeeRate float64 + expectedFees *btcjson.TestMempoolAcceptFees + allowed bool + }{ + { + // When the fee rate(0.1) is above the max fee + // rate(0.01), we expect a nil result and false. + name: "fee rate above max", + feeSats: testFeeSats, + txSize: testTxSize, + maxFeeRate: testFeeRate / 10, + expectedFees: nil, + allowed: false, + }, + { + // When the fee rate(0.1) is no greater than the max + // fee rate(0.1), we expect a result and true. + name: "fee rate below max", + feeSats: testFeeSats, + txSize: testTxSize, + maxFeeRate: testFeeRate, + expectedFees: &btcjson.TestMempoolAcceptFees{ + Base: testFeeSats.ToBTC(), + EffectiveFeeRate: testFeeRate, + }, + allowed: true, + }, + { + // When the fee rate(1) is above the default max fee + // rate(0.1), we expect a nil result and false. + name: "fee rate above default max", + feeSats: testFeeSats, + txSize: testTxSize / 10, + expectedFees: nil, + allowed: false, + }, + { + // When the fee rate(0.1) is no greater than the + // default max fee rate(0.1), we expect a result and + // true. + name: "fee rate below default max", + feeSats: testFeeSats, + txSize: testTxSize, + expectedFees: &btcjson.TestMempoolAcceptFees{ + Base: testFeeSats.ToBTC(), + EffectiveFeeRate: testFeeRate, + }, + allowed: true, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + require := require.New(t) + + result, allowed := validateFeeRate( + tc.feeSats, tc.txSize, tc.maxFeeRate, + ) + + require.Equal(tc.expectedFees, result) + require.Equal(tc.allowed, allowed) + }) + } +} + +// TestHandleTestMempoolAcceptFees checks that the `Fees` field is correctly +// populated based on the max fee rate and the tx being checked. +func TestHandleTestMempoolAcceptFees(t *testing.T) { + t.Parallel() + + // Create a mock mempool. + mm := &mempool.MockTxMempool{} + + // Create a testing server with the mock mempool. + s := &rpcServer{cfg: rpcserverConfig{ + TxMemPool: mm, + }} + + const ( + // Set transaction's fee rate to be 0.2BTC/kvB. + feeRate = defaultMaxFeeRate * 2 + + // txSize is 100vb. + txSize = 100 + + // feeSats is 2e6 sats. + feeSats = feeRate * 1e8 * txSize / 1e3 + ) + + testCases := []struct { + name string + maxFeeRate float64 + txHex string + rejectReason string + allowed bool + }{ + { + // When the fee rate(0.2) used by the tx is below the + // max fee rate(2) specified, the result should allow + // it. + name: "below max fee rate", + maxFeeRate: feeRate * 10, + txHex: txHex1, + allowed: true, + }, + { + // When the fee rate(0.2) used by the tx is above the + // max fee rate(0.02) specified, the result should + // disallow it. + name: "above max fee rate", + maxFeeRate: feeRate / 10, + txHex: txHex1, + allowed: false, + rejectReason: "max-fee-exceeded", + }, + { + // When the max fee rate is not set, the default + // 0.1BTC/kvB is used and the fee rate(0.2) used by the + // tx is above it, the result should disallow it. + name: "above default max fee rate", + txHex: txHex1, + allowed: false, + rejectReason: "max-fee-exceeded", + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + require := require.New(t) + + // Decode the hex so we can assert the mock mempool is + // called with it. + tx := decodeTxHex(t, txHex1) + + // We mock the call to `CheckMempoolAcceptance` to + // return the result. + mm.On("CheckMempoolAcceptance", tx).Return( + &mempool.MempoolAcceptResult{ + TxFee: feeSats, + TxSize: txSize, + }, nil, + ).Once() + + // We expect the third result to give us the fee + // details. + expected := &btcjson.TestMempoolAcceptResult{ + Txid: tx.Hash().String(), + Wtxid: tx.WitnessHash().String(), + Allowed: tc.allowed, + } + + if tc.allowed { + expected.Vsize = txSize + expected.Fees = &btcjson.TestMempoolAcceptFees{ + Base: feeSats / 1e8, + EffectiveFeeRate: feeRate, + } + } else { + expected.RejectReason = tc.rejectReason + } + + // Create a mock request with specified max fee rate. + cmd := btcjson.NewTestMempoolAcceptCmd( + []string{txHex1}, tc.maxFeeRate, + ) + + // Call the method handler and assert the expected + // result is returned. + closeChan := make(chan struct{}) + r, err := handleTestMempoolAccept(s, cmd, closeChan) + require.NoError(err) + + // Check the interface type. + results, ok := r.([]*btcjson.TestMempoolAcceptResult) + require.True(ok) + + // Expect exactly one result. + require.Len(results, 1) + + // Check the result is returned as expected. + require.Equal(expected, results[0]) + + // Assert the mocked method is called as expected. + mm.AssertExpectations(t) + }) + } +} diff --git a/rpcserverhelp.go b/rpcserverhelp.go index f1203de8d9..0ee8485180 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -717,6 +717,23 @@ var helpDescsEnUS = map[string]string{ "versionresult-patch": "The patch component of the JSON-RPC API version", "versionresult-prerelease": "Prerelease info about the current build", "versionresult-buildmetadata": "Metadata about the current build", + + // TestMempoolAcceptCmd help. + "testmempoolaccept--synopsis": "Returns result of mempool acceptance tests indicating if raw transaction(s) would be accepted by mempool.", + "testmempoolaccept-rawtxns": "Serialized transactions to test.", + "testmempoolaccept-maxfeerate": "Maximum acceptable fee rate in BTC/kB", + + // TestMempoolAcceptCmd result help. + "testmempoolacceptresult-txid": "The transaction hash in hex.", + "testmempoolacceptresult-wtxid": "The transaction witness hash in hex.", + "testmempoolacceptresult-package-error": "Package validation error, if any (only possible if rawtxs had more than 1 transaction).", + "testmempoolacceptresult-allowed": "Whether the transaction would be accepted to the mempool.", + "testmempoolacceptresult-vsize": "Virtual transaction size as defined in BIP 141.(only present when 'allowed' is true)", + "testmempoolacceptresult-reject-reason": "Rejection string (only present when 'allowed' is false).", + "testmempoolacceptresult-fees": "Transaction fees (only present if 'allowed' is true).", + "testmempoolacceptfees-base": "Transaction fees (only present if 'allowed' is true).", + "testmempoolacceptfees-effective-feerate": "The effective feerate in BTC per KvB.", + "testmempoolacceptfees-effective-includes": "Transactions whose fees and vsizes are included in effective-feerate. Each item is a transaction wtxid in hex.", } // rpcResultTypes specifies the result types that each RPC command can return. @@ -772,6 +789,7 @@ var rpcResultTypes = map[string][]interface{}{ "verifychain": {(*bool)(nil)}, "verifymessage": {(*bool)(nil)}, "version": {(*map[string]btcjson.VersionResult)(nil)}, + "testmempoolaccept": {(*[]btcjson.TestMempoolAcceptResult)(nil)}, // Websocket commands. "loadtxfilter": nil, From ef54c49df443815d50765e8c4f31a87944d950a6 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 5 Dec 2023 14:41:02 +0800 Subject: [PATCH 0942/1056] multi: map `btcd` mempool acceptance errors to bitcoind's `testmempoolaccept` This commit creates a `RejectReasonMap` to map the errors returned from `btcd` to bitcoind's `testmempoolaccept` so the `RejectReason` is unified at the RPC level. To make sure the map keys are unique, the error strings are modified in `btcd`. --- blockchain/validate.go | 10 +-- mempool/mempool.go | 21 ++--- mempool/mempool_test.go | 4 +- mempool/policy.go | 12 +-- rpcclient/errors.go | 165 +++++++++++++++++++++++++++++++++++++++- rpcserver.go | 5 +- 6 files changed, 192 insertions(+), 25 deletions(-) diff --git a/blockchain/validate.go b/blockchain/validate.go index 02d36134b1..83929810ee 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -243,9 +243,9 @@ func CheckTransactionSanity(tx *btcutil.Tx) error { return ruleError(ErrBadTxOutValue, str) } if satoshi > btcutil.MaxSatoshi { - str := fmt.Sprintf("transaction output value of %v is "+ - "higher than max allowed value of %v", satoshi, - btcutil.MaxSatoshi) + str := fmt.Sprintf("transaction output value is "+ + "higher than max allowed value: %v > %v ", + satoshi, btcutil.MaxSatoshi) return ruleError(ErrBadTxOutValue, str) } @@ -968,8 +968,8 @@ func CheckTransactionInputs(tx *btcutil.Tx, txHeight int32, utxoView *UtxoViewpo return 0, ruleError(ErrBadTxOutValue, str) } if originTxSatoshi > btcutil.MaxSatoshi { - str := fmt.Sprintf("transaction output value of %v is "+ - "higher than max allowed value of %v", + str := fmt.Sprintf("transaction output value is "+ + "higher than max allowed value: %v > %v ", btcutil.Amount(originTxSatoshi), btcutil.MaxSatoshi) return 0, ruleError(ErrBadTxOutValue, str) diff --git a/mempool/mempool.go b/mempool/mempool.go index 6913ac9e78..db04f619a5 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -592,9 +592,9 @@ func (mp *TxPool) checkPoolDoubleSpend(tx *btcutil.Tx) (bool, error) { // transactions or if it doesn't signal replacement. if mp.cfg.Policy.RejectReplacement || !mp.signalsReplacement(conflict, nil) { - str := fmt.Sprintf("output %v already spent by "+ - "transaction %v in the memory pool", - txIn.PreviousOutPoint, conflict.Hash()) + str := fmt.Sprintf("output already spent in mempool: "+ + "output=%v, tx=%v", txIn.PreviousOutPoint, + conflict.Hash()) return false, txRuleError(wire.RejectDuplicate, str) } @@ -842,7 +842,7 @@ func (mp *TxPool) validateReplacement(tx *btcutil.Tx, // exceed the maximum allowed. conflicts := mp.txConflicts(tx) if len(conflicts) > MaxReplacementEvictions { - str := fmt.Sprintf("replacement transaction %v evicts more "+ + str := fmt.Sprintf("%v: replacement transaction evicts more "+ "transactions than permitted: max is %v, evicts %v", tx.Hash(), MaxReplacementEvictions, len(conflicts)) return nil, txRuleError(wire.RejectNonstandard, str) @@ -855,7 +855,7 @@ func (mp *TxPool) validateReplacement(tx *btcutil.Tx, if _, ok := conflicts[ancestorHash]; !ok { continue } - str := fmt.Sprintf("replacement transaction %v spends parent "+ + str := fmt.Sprintf("%v: replacement transaction spends parent "+ "transaction %v", tx.Hash(), ancestorHash) return nil, txRuleError(wire.RejectInvalid, str) } @@ -876,7 +876,7 @@ func (mp *TxPool) validateReplacement(tx *btcutil.Tx, ) for hash, conflict := range conflicts { if txFeeRate <= mp.pool[hash].FeePerKB { - str := fmt.Sprintf("replacement transaction %v has an "+ + str := fmt.Sprintf("%v: replacement transaction has an "+ "insufficient fee rate: needs more than %v, "+ "has %v", tx.Hash(), mp.pool[hash].FeePerKB, txFeeRate) @@ -897,7 +897,7 @@ func (mp *TxPool) validateReplacement(tx *btcutil.Tx, // which is determined by our minimum relay fee. minFee := calcMinRequiredTxRelayFee(txSize, mp.cfg.Policy.MinRelayTxFee) if txFee < conflictsFee+minFee { - str := fmt.Sprintf("replacement transaction %v has an "+ + str := fmt.Sprintf("%v: replacement transaction has an "+ "insufficient absolute fee: needs %v, has %v", tx.Hash(), conflictsFee+minFee, txFee) return nil, txRuleError(wire.RejectInsufficientFee, str) @@ -1350,7 +1350,8 @@ func (mp *TxPool) checkMempoolAcceptance(tx *btcutil.Tx, if mp.isTransactionInPool(txHash) || (rejectDupOrphans && mp.isOrphanInPool(txHash)) { - str := fmt.Sprintf("already have transaction %v", txHash) + str := fmt.Sprintf("already have transaction in mempool %v", + txHash) return nil, txRuleError(wire.RejectDuplicate, str) } @@ -1368,7 +1369,7 @@ func (mp *TxPool) checkMempoolAcceptance(tx *btcutil.Tx, // A standalone transaction must not be a coinbase transaction. if blockchain.IsCoinBase(tx) { - str := fmt.Sprintf("transaction %v is an individual coinbase", + str := fmt.Sprintf("transaction is an individual coinbase %v", txHash) return nil, txRuleError(wire.RejectInvalid, str) @@ -1418,7 +1419,7 @@ func (mp *TxPool) checkMempoolAcceptance(tx *btcutil.Tx, entry := utxoView.LookupEntry(prevOut) if entry != nil && !entry.IsSpent() { return nil, txRuleError(wire.RejectDuplicate, - "transaction already exists") + "transaction already exists in blockchain") } utxoView.RemoveEntry(prevOut) diff --git a/mempool/mempool_test.go b/mempool/mempool_test.go index f0f8404cc7..e31b6043bd 100644 --- a/mempool/mempool_test.go +++ b/mempool/mempool_test.go @@ -1491,7 +1491,7 @@ func TestRBF(t *testing.T) { return tx, nil }, - err: "already spent by transaction", + err: "already spent in mempool", }, { // A transaction cannot replace another if we don't @@ -1522,7 +1522,7 @@ func TestRBF(t *testing.T) { return tx, nil }, - err: "already spent by transaction", + err: "already spent in mempool", }, { // A transaction cannot replace another if doing so diff --git a/mempool/policy.go b/mempool/policy.go index 758f7e06a9..862767d0c8 100644 --- a/mempool/policy.go +++ b/mempool/policy.go @@ -308,8 +308,8 @@ func CheckTransactionStandard(tx *btcutil.Tx, height int32, // attacks. txWeight := blockchain.GetTransactionWeight(tx) if txWeight > maxStandardTxWeight { - str := fmt.Sprintf("weight of transaction %v is larger than max "+ - "allowed weight of %v", txWeight, maxStandardTxWeight) + str := fmt.Sprintf("weight of transaction is larger than max "+ + "allowed: %v > %v", txWeight, maxStandardTxWeight) return txRuleError(wire.RejectNonstandard, str) } @@ -320,8 +320,8 @@ func CheckTransactionStandard(tx *btcutil.Tx, height int32, sigScriptLen := len(txIn.SignatureScript) if sigScriptLen > maxStandardSigScriptSize { str := fmt.Sprintf("transaction input %d: signature "+ - "script size of %d bytes is large than max "+ - "allowed size of %d bytes", i, sigScriptLen, + "script size is larger than max allowed: "+ + "%d > %d bytes", i, sigScriptLen, maxStandardSigScriptSize) return txRuleError(wire.RejectNonstandard, str) } @@ -359,8 +359,8 @@ func CheckTransactionStandard(tx *btcutil.Tx, height int32, if scriptClass == txscript.NullDataTy { numNullDataOutputs++ } else if IsDust(txOut, minRelayTxFee) { - str := fmt.Sprintf("transaction output %d: payment "+ - "of %d is dust", i, txOut.Value) + str := fmt.Sprintf("transaction output %d: payment is "+ + "dust: %v", i, txOut.Value) return txRuleError(wire.RejectDust, str) } } diff --git a/rpcclient/errors.go b/rpcclient/errors.go index 62de9b3806..78f34bef2e 100644 --- a/rpcclient/errors.go +++ b/rpcclient/errors.go @@ -1,6 +1,9 @@ package rpcclient -import "errors" +import ( + "errors" + "strings" +) var ( // ErrBitcoindVersion is returned when running against a bitcoind that @@ -10,4 +13,164 @@ var ( // ErrInvalidParam is returned when the caller provides an invalid // parameter to an RPC method. ErrInvalidParam = errors.New("invalid param") + + // RejectReasonMap takes the error returned from + // `CheckMempoolAcceptance` in `btcd` and maps it to the reject reason + // that's returned from calling `testmempoolaccept` in `bitcoind`. + // references: + // - https://github.com/bitcoin/bitcoin/blob/master/test/functional/data/invalid_txs.py + // - https://github.com/bitcoin/bitcoin/blob/master/test/functional/mempool_accept.py + // - https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp + // + // Errors not mapped in `btcd`: + // - deployment error from `validateSegWitDeployment`. + // - the error when total inputs is higher than max allowed value from + // `CheckTransactionInputs`. + // - the error when total outputs is higher than total inputs from + // `CheckTransactionInputs`. + // - errors from `CalcSequenceLock`. + // + // NOTE: This is not an exhaustive list of errors, but it covers the + // usage case of LND. + // + //nolint:lll + RejectReasonMap = map[string]string{ + // BIP125 related errors. + // + // When fee rate used or fees paid doesn't meet the + // requirements. + "replacement transaction has an insufficient fee rate": "insufficient fee", + "replacement transaction has an insufficient absolute fee": "insufficient fee", + + // When a transaction causes too many transactions being + // replaced. This is set by `MAX_REPLACEMENT_CANDIDATES` in + // `bitcoind` and defaults to 100. + "replacement transaction evicts more transactions than permitted": "too many potential replacements", + + // When a transaction adds new unconfirmed inputs. + "replacement transaction spends new unconfirmed input": "replacement-adds-unconfirmed", + + // A transaction that spends conflicting tx outputs that are + // rejected. + "replacement transaction spends parent transaction": "bad-txns-spends-conflicting-tx", + + // A transaction that conflicts with an unconfirmed tx. Happens + // when RBF is not enabled. + "output already spent in mempool": "txn-mempool-conflict", + + // A transaction with no outputs. + "transaction has no outputs": "bad-txns-vout-empty", + + // A transaction with no inputs. + "transaction has no inputs": "bad-txns-vin-empty", + + // A tiny transaction(in non-witness bytes) that is disallowed. + // TODO(yy): find/return this error in `btcd`. + // "": "tx-size-small", + + // A transaction with duplicate inputs. + "transaction contains duplicate inputs": "bad-txns-inputs-duplicate", + + // A non-coinbase transaction with coinbase-like outpoint. + "transaction input refers to previous output that is null": "bad-txns-prevout-null", + + // A transaction pays too little fee. + "fees which is under the required amount": "bad-txns-in-belowout", + "has insufficient priority": "bad-txns-in-belowout", + "has been rejected by the rate limiter due to low fees": "bad-txns-in-belowout", + + // A transaction with negative output value. + "transaction output has negative value": "bad-txns-vout-negative", + + // A transaction with too large output value. + "transaction output value is higher than max allowed value": "bad-txns-vout-toolarge", + + // A transaction with too large sum of output values. + "total value of all transaction outputs exceeds max allowed value": "bad-txns-txouttotal-toolarge", + + // TODO(yy): find/return this error in `btcd`. + // "": "mandatory-script-verify-flag-failed (Invalid OP_IF construction)", + + // A transaction with too many sigops. + "sigop cost is too hight": "bad-txns-too-many-sigops", + + // A transaction with invalid OP codes. + // TODO(yy): find/return this error in `btcd`. + // "": "disabled opcode", + + // A transaction already in the blockchain. + "database contains entry for spent tx output": "txn-already-known", + "transaction already exists in blockchain": "txn-already-known", + + // A transaction in the mempool. + "already have transaction in mempool": "txn-already-in-mempool", + + // A transaction with missing inputs, that never existed or + // only existed once in the past. + "either does not exist or has already been spent": "missing-inputs", + + // A really large transaction. + "serialized transaction is too big": "bad-txns-oversize", + + // A coinbase transaction. + "transaction is an invalid coinbase": "coinbase", + + // Some nonstandard transactions - a version currently + // non-standard. + "transaction version": "version", + + // Some nonstandard transactions - non-standard script. + "non-standard script form": "scriptpubkey", + "has a non-standard input": "scriptpubkey", + + // Some nonstandard transactions - bare multisig script + // (2-of-3). + "milti-signature script": "bare-multisig", + + // Some nonstandard transactions - not-pushonly scriptSig. + "signature script is not push only": "scriptsig-not-pushonly", + + // Some nonstandard transactions - too large scriptSig (>1650 + // bytes). + "signature script size is larger than max allowed": "scriptsig-size", + + // Some nonstandard transactions - too large tx size. + "weight of transaction is larger than max allowed": "tx-size", + + // Some nonstandard transactions - output too small. + "payment is dust": "dust", + + // Some nonstandard transactions - muiltiple OP_RETURNs. + "more than one transaction output in a nulldata script": "multi-op-return", + + // A timelocked transaction. + "transaction is not finalized": "non-final", + "tried to spend coinbase transaction output": "non-final", + + // A transaction that is locked by BIP68 sequence logic. + "transaction's sequence locks on inputs not met": "non-BIP68-final", + + // Minimally-small transaction(in non-witness bytes) that is + // allowed. + // TODO(yy): find/return this error in `btcd`. + // "": "txn-same-nonwitness-data-in-mempools", + } ) + +// MapBtcdErrToRejectReason takes an error returned from +// `CheckMempoolAcceptance` and maps the error to a bitcoind reject reason. +func MapBtcdErrToRejectReason(err error) string { + // Get the error string and turn it into lower case. + btcErr := strings.ToLower(err.Error()) + + // Iterate the map and find the matching error. + for keyErr, rejectReason := range RejectReasonMap { + // Match the substring. + if strings.Contains(btcErr, keyErr) { + return rejectReason + } + } + + // If there's no match, return the error string directly. + return btcErr +} diff --git a/rpcserver.go b/rpcserver.go index 36c00be18f..2433286ac7 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -39,6 +39,7 @@ import ( "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/mining/cpuminer" "github.com/btcsuite/btcd/peer" + "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/websocket" @@ -3856,7 +3857,9 @@ func handleTestMempoolAccept(s *rpcServer, cmd interface{}, // TODO(yy): differentiate the errors and put package // error in `PackageError` field. - item.RejectReason = err.Error() + item.RejectReason = rpcclient.MapBtcdErrToRejectReason( + err, + ) results = append(results, item) From c104e72151df12ac0952ddbcad3c17bcc24b4120 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 29 Nov 2023 15:31:51 +0800 Subject: [PATCH 0943/1056] rpctest: add itest for `testmempoolaccept` --- integration/rawtx_test.go | 203 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 integration/rawtx_test.go diff --git a/integration/rawtx_test.go b/integration/rawtx_test.go new file mode 100644 index 0000000000..f27f5176cf --- /dev/null +++ b/integration/rawtx_test.go @@ -0,0 +1,203 @@ +//go:build rpctest +// +build rpctest + +package integration + +import ( + "encoding/hex" + "testing" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/integration/rpctest" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/stretchr/testify/require" +) + +// TestTestMempoolAccept checks that `TestTestMempoolAccept` behaves as +// expected. It checks that, +// - an error is returned when invalid params are used. +// - orphan tx is rejected. +// - fee rate above the max is rejected. +// - a mixed of both allowed and rejected can be returned in the same response. +func TestTestMempoolAccept(t *testing.T) { + t.Parallel() + + // Boilerplate codetestDir to make a pruned node. + btcdCfg := []string{"--rejectnonstd", "--debuglevel=debug"} + r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg, "") + require.NoError(t, err) + + // Setup the node. + require.NoError(t, r.SetUp(true, 100)) + t.Cleanup(func() { + require.NoError(t, r.TearDown()) + }) + + // Create testing txns. + invalidTx := decodeHex(t, missingParentsHex) + validTx := createTestTx(t, r) + + // Create testing constants. + const feeRate = 10 + + testCases := []struct { + name string + txns []*wire.MsgTx + maxFeeRate float64 + expectedErr error + expectedResult []*btcjson.TestMempoolAcceptResult + }{ + { + // When too many txns are provided, the method should + // return an error. + name: "too many txns", + txns: make([]*wire.MsgTx, 26), + maxFeeRate: 0, + expectedErr: rpcclient.ErrInvalidParam, + expectedResult: nil, + }, + { + // When no txns are provided, the method should return + // an error. + name: "empty txns", + txns: nil, + maxFeeRate: 0, + expectedErr: rpcclient.ErrInvalidParam, + expectedResult: nil, + }, + { + // When a corrupted txn is provided, the method should + // return an error. + name: "corrupted tx", + txns: []*wire.MsgTx{{}}, + maxFeeRate: 0, + expectedErr: rpcclient.ErrInvalidParam, + expectedResult: nil, + }, + { + // When an orphan tx is provided, the method should + // return a test mempool accept result which says this + // tx is not allowed. + name: "orphan tx", + txns: []*wire.MsgTx{invalidTx}, + maxFeeRate: 0, + expectedResult: []*btcjson.TestMempoolAcceptResult{{ + Txid: invalidTx.TxHash().String(), + Wtxid: invalidTx.TxHash().String(), + Allowed: false, + RejectReason: "missing-inputs", + }}, + }, + { + // When a valid tx is provided but it exceeds the max + // fee rate, the method should return a test mempool + // accept result which says it's not allowed. + name: "valid tx but exceeds max fee rate", + txns: []*wire.MsgTx{validTx}, + maxFeeRate: 1e-5, + expectedResult: []*btcjson.TestMempoolAcceptResult{{ + Txid: validTx.TxHash().String(), + Wtxid: validTx.TxHash().String(), + Allowed: false, + RejectReason: "max-fee-exceeded", + }}, + }, + { + // When a valid tx is provided and it doesn't exceeds + // the max fee rate, the method should return a test + // mempool accept result which says it's allowed. + name: "valid tx and sane fee rate", + txns: []*wire.MsgTx{validTx}, + expectedResult: []*btcjson.TestMempoolAcceptResult{{ + Txid: validTx.TxHash().String(), + Wtxid: validTx.TxHash().String(), + Allowed: true, + // TODO(yy): need to calculate the fees, atm + // there's no easy way. + // Fees: &btcjson.TestMempoolAcceptFees{}, + }}, + }, + { + // When multiple txns are provided, the method should + // return the correct results for each of the txns. + name: "multiple txns", + txns: []*wire.MsgTx{invalidTx, validTx}, + expectedResult: []*btcjson.TestMempoolAcceptResult{{ + Txid: invalidTx.TxHash().String(), + Wtxid: invalidTx.TxHash().String(), + Allowed: false, + RejectReason: "missing-inputs", + }, { + Txid: validTx.TxHash().String(), + Wtxid: validTx.TxHash().String(), + Allowed: true, + }}, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + require := require.New(t) + + results, err := r.Client.TestMempoolAccept( + tc.txns, tc.maxFeeRate, + ) + + require.ErrorIs(err, tc.expectedErr) + require.Len(results, len(tc.expectedResult)) + + // Check each item is returned as expected. + for i, r := range results { + expected := tc.expectedResult[i] + + // TODO(yy): check all the fields? + require.Equal(expected.Txid, r.Txid) + require.Equal(expected.Wtxid, r.Wtxid) + require.Equal(expected.Allowed, r.Allowed) + require.Equal(expected.RejectReason, + r.RejectReason) + } + }) + } +} + +var ( + //nolint:lll + missingParentsHex = "0100000003bcb2054607a921b3c6df992a9486776863b28485e731a805931b6feb14221acff2000000001c75619cdff9d694a434b13abfbbd618e2ece4460f24b4821cf47d5afc481a386c59565c4900000000cff75994dceb5f5568f8ada45d428630f512fb8efacd46682b4367b4edaf1985c5e4af4b07010000003c029216047236f3000000000017a9141d5a2c690c3e2dacb3cead240f0ce4a273b9d0e48758020000000000001600149d38710eb90e420b159c7a9263994c88e6810bc758020000000000001976a91490770ceff2b1c32e9dbf952fbe65b04a54d1949388ac580200000000000017a914f017945d4d088c7d42ab3bcbc1adce51d74fbd9f8784d7ee4b" +) + +// createTestTx creates a `wire.MsgTx` and asserts its creation. +func createTestTx(t *testing.T, h *rpctest.Harness) *wire.MsgTx { + addr, err := h.NewAddress() + require.NoError(t, err) + + script, err := txscript.PayToAddrScript(addr) + require.NoError(t, err) + + output := &wire.TxOut{ + PkScript: script, + Value: 1e6, + } + + tx, err := h.CreateTransaction([]*wire.TxOut{output}, 10, true) + require.NoError(t, err) + + return tx +} + +// decodeHex takes a tx hexstring and asserts it can be decoded into a +// `wire.MsgTx`. +func decodeHex(t *testing.T, txHex string) *wire.MsgTx { + serializedTx, err := hex.DecodeString(txHex) + require.NoError(t, err) + + tx, err := btcutil.NewTxFromBytes(serializedTx) + require.NoError(t, err) + + return tx.MsgTx() +} From 8817ebdd3947c052acf98e2f032cc14e92f16e21 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 5 Dec 2023 16:26:18 +0800 Subject: [PATCH 0944/1056] integration: print logs to console --- integration/log.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 integration/log.go diff --git a/integration/log.go b/integration/log.go new file mode 100644 index 0000000000..26d6217454 --- /dev/null +++ b/integration/log.go @@ -0,0 +1,26 @@ +//go:build rpctest +// +build rpctest + +package integration + +import ( + "os" + + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btclog" +) + +type logWriter struct{} + +func (logWriter) Write(p []byte) (n int, err error) { + os.Stdout.Write(p) + return len(p), nil +} + +func init() { + backendLog := btclog.NewBackend(logWriter{}) + testLog := backendLog.Logger("ITEST") + testLog.SetLevel(btclog.LevelDebug) + + rpcclient.UseLogger(testLog) +} From fbe65bfc014f372e73621f72ea63809f75ae1922 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 29 Nov 2023 17:07:26 +0800 Subject: [PATCH 0945/1056] gomod: run `go mod tidy` for all modules Also add the `make tidy-module` copied from `lnd`. --- Makefile | 4 ++++ btcutil/go.sum | 8 -------- go.mod | 5 +++-- go.sum | 11 +++++++++-- scripts/tidy_modules.sh | 17 +++++++++++++++++ 5 files changed, 33 insertions(+), 12 deletions(-) create mode 100755 scripts/tidy_modules.sh diff --git a/Makefile b/Makefile index 5bfb1aa6a5..e9aa6894ba 100644 --- a/Makefile +++ b/Makefile @@ -133,6 +133,10 @@ lint: $(LINT_BIN) clean: @$(call print, "Cleaning source.$(NC)") $(RM) coverage.txt btcec/coverage.txt btcutil/coverage.txt btcutil/psbt/coverage.txt + +tidy-module: + echo "Running 'go mod tidy' for all modules" + scripts/tidy_modules.sh .PHONY: all \ default \ diff --git a/btcutil/go.sum b/btcutil/go.sum index a57a5dd920..5ee4cd5207 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -2,8 +2,6 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.23.4 h1:IzV6qqkfwbItOS/sg/aDfPDsjPP8twrCOE2R93hxMlQ= -github.com/btcsuite/btcd v0.23.4/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= @@ -18,15 +16,12 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -36,7 +31,6 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/decred/dcrd/lru v1.0.0 h1:Kbsb1SFDsIlaupWPwsPp+dkxiBY1frcS07PCPgotKz8= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -55,9 +49,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= diff --git a/go.mod b/go.mod index 425e6d7f2b..6eea83508e 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gorilla/websocket v1.5.0 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed @@ -26,7 +26,8 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + github.com/stretchr/objx v0.5.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) // The retract statements below fixes an accidental push of the tags of a btcd diff --git a/go.sum b/go.sum index 158e868092..ddd7e1ebd0 100644 --- a/go.sum +++ b/go.sum @@ -77,8 +77,14 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -125,5 +131,6 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/scripts/tidy_modules.sh b/scripts/tidy_modules.sh new file mode 100755 index 0000000000..3fa5bfb252 --- /dev/null +++ b/scripts/tidy_modules.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +SUBMODULES=$(find . -mindepth 2 -name "go.mod" | cut -d'/' -f2) + + +# Run 'go mod tidy' for root. +go mod tidy + +# Run 'go mod tidy' for each module. +for submodule in $SUBMODULES +do + pushd $submodule + + go mod tidy + + popd +done From e8a5a5537947ff90616176b00e715b5f0f029491 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 19 Jan 2024 18:56:22 +0800 Subject: [PATCH 0946/1056] rpcclient: make sure batch requests are GCed This commit makes sure the batch requests are always GCed before sending back the responses for them. In particular, - `removeRequest` didn't remove the item from `batchList`, which is now fixed. - `Send` didn't remove the request from `requestMap`, which is now fixed by using `removeRequest`. --- rpcclient/infrastructure.go | 58 ++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 1ddfa356dc..258ed130f9 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -270,14 +270,21 @@ func (c *Client) removeRequest(id uint64) *jsonRequest { c.requestLock.Lock() defer c.requestLock.Unlock() - element := c.requestMap[id] - if element != nil { - delete(c.requestMap, id) - request := c.requestList.Remove(element).(*jsonRequest) - return request + element, ok := c.requestMap[id] + if !ok { + return nil } - return nil + delete(c.requestMap, id) + + var request *jsonRequest + if c.batch { + request = c.batchList.Remove(element).(*jsonRequest) + } else { + request = c.requestList.Remove(element).(*jsonRequest) + } + + return request } // removeAllRequests removes all the jsonRequests which contain the response @@ -1733,28 +1740,38 @@ func (c *Client) Send() error { return nil } - // clear batchlist in case of an error - defer func() { + batchResp, err := c.sendAsync().Receive() + if err != nil { + // Clear batchlist in case of an error. + // + // TODO(yy): need to double check to make sure there's no + // concurrent access to this batch list, otherwise we may miss + // some batched requests. c.batchList = list.New() - }() - result, err := c.sendAsync().Receive() - - if err != nil { return err } - for iter := c.batchList.Front(); iter != nil; iter = iter.Next() { - var requestError error - request := iter.Value.(*jsonRequest) - individualResult := result[request.id] - fullResult, err := json.Marshal(individualResult.Result) + // Iterate each response and send it to the corresponding request. + for id, resp := range batchResp { + // Perform a GC on batchList and requestMap before moving + // forward. + request := c.removeRequest(id) + + // If there's an error, we log it and continue to the next + // request. + fullResult, err := json.Marshal(resp.Result) if err != nil { - return err + log.Errorf("Unable to marshal result: %v for req=%v", + err, request.id) + + continue } - if individualResult.Error != nil { - requestError = individualResult.Error + // If there's a response error, we send it back the request. + var requestError error + if resp.Error != nil { + requestError = resp.Error } result := Response{ @@ -1763,5 +1780,6 @@ func (c *Client) Send() error { } request.responseChan <- &result } + return nil } From 9cda0f7e95c02dac888c49569fcaffdb9cc1e970 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Sun, 21 Jan 2024 18:43:15 +0800 Subject: [PATCH 0947/1056] wire: add `Copy` method to `MsgBlock` --- wire/msgblock.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/wire/msgblock.go b/wire/msgblock.go index 77585e3fb6..d065e85c52 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -45,6 +45,20 @@ type MsgBlock struct { Transactions []*MsgTx } +// Copy creates a deep copy of MsgBlock. +func (msg *MsgBlock) Copy() *MsgBlock { + block := &MsgBlock{ + Header: msg.Header, + Transactions: make([]*MsgTx, len(msg.Transactions)), + } + + for i, tx := range msg.Transactions { + block.Transactions[i] = tx.Copy() + } + + return block +} + // AddTransaction adds a transaction to the message. func (msg *MsgBlock) AddTransaction(tx *MsgTx) error { msg.Transactions = append(msg.Transactions, tx) From c17cf800dceff7984f898029fa8fc03efd6b5f3d Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 22 Jan 2024 13:20:18 +0900 Subject: [PATCH 0948/1056] netsync: don't update mempool/fee estimator unless we're synced up Noticed during ibd that there's a slight overhead for handleBlockchainNotification on mempool/fee estimator updates. Since there's no reason to be looking at this while we're not caught up, return early and avoid the calls. --- netsync/manager.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/netsync/manager.go b/netsync/manager.go index 41ba70aa6a..b1a4db4d13 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -1454,6 +1454,13 @@ func (sm *SyncManager) handleBlockchainNotification(notification *blockchain.Not // A block has been connected to the main block chain. case blockchain.NTBlockConnected: + // Don't attempt to update the mempool if we're not current. + // The mempool is empty and the fee estimator is useless unless + // we're caught up. + if !sm.current() { + return + } + block, ok := notification.Data.(*btcutil.Block) if !ok { log.Warnf("Chain connected notification is not a block.") From 2a55ff4884224b7aab6f802de262ae4857da269e Mon Sep 17 00:00:00 2001 From: Halimao <1065621723@qq.com> Date: Mon, 22 Jan 2024 16:23:43 +0800 Subject: [PATCH 0949/1056] refactor: add `make help` command that describes goals --- Makefile | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Makefile b/Makefile index e9aa6894ba..e17e6446d7 100644 --- a/Makefile +++ b/Makefile @@ -39,8 +39,10 @@ define print echo $(GREEN)$1$(NC) endef +#? default: Run `make build` default: build +#? all: Run `make build` and `make check` all: build check # ============ @@ -55,6 +57,7 @@ $(GOACC_BIN): @$(call print, "Fetching go-acc") $(DEPGET) $(GOACC_PKG)@$(GOACC_COMMIT) +#? goimports: Install goimports goimports: @$(call print, "Installing goimports.") $(DEPGET) $(GOIMPORTS_PKG) @@ -63,6 +66,7 @@ goimports: # INSTALLATION # ============ +#? build: Build all binaries, place them in project directory build: @$(call print, "Building all binaries") $(GOBUILD) $(PKG) @@ -71,6 +75,7 @@ build: $(GOBUILD) $(PKG)/cmd/findcheckpoint $(GOBUILD) $(PKG)/cmd/addblock +#? install: Install all binaries, place them in $GOPATH/bin install: @$(call print, "Installing all binaries") $(GOINSTALL) $(PKG) @@ -79,6 +84,7 @@ install: $(GOINSTALL) $(PKG)/cmd/findcheckpoint $(GOINSTALL) $(PKG)/cmd/addblock +#? release-install: Install btcd and btcctl release binaries, place them in $GOPATH/bin release-install: @$(call print, "Installing btcd and btcctl release binaries") env CGO_ENABLED=0 $(GOINSTALL) -trimpath -ldflags="-s -w -buildid=" $(PKG) @@ -88,8 +94,10 @@ release-install: # TESTING # ======= +#? check: Run `make unit` check: unit +#? unit: Run unit tests unit: @$(call print, "Running unit tests.") $(GOTEST_DEV) ./... -test.timeout=20m @@ -97,6 +105,7 @@ unit: cd btcutil; $(GOTEST_DEV) ./... -test.timeout=20m cd btcutil/psbt; $(GOTEST_DEV) ./... -test.timeout=20m +#? unit-cover: Run unit coverage tests unit-cover: $(GOACC_BIN) @$(call print, "Running unit coverage tests.") $(GOACC_BIN) ./... @@ -109,6 +118,7 @@ unit-cover: $(GOACC_BIN) cd btcutil/psbt; $(GOACC_BIN) ./... +#? unit-race: Run unit race tests unit-race: @$(call print, "Running unit race tests.") env CGO_ENABLED=1 GORACE="history_size=7 halt_on_errors=1" $(GOTEST) -race -test.timeout=20m ./... @@ -120,20 +130,24 @@ unit-race: # UTILITIES # ========= +#? fmt: Fix imports and formatting source fmt: goimports @$(call print, "Fixing imports.") goimports -w $(GOFILES_NOVENDOR) @$(call print, "Formatting source.") gofmt -l -w -s $(GOFILES_NOVENDOR) +#? lint: Lint source lint: $(LINT_BIN) @$(call print, "Linting source.") $(LINT) +#? clean: Clean source clean: @$(call print, "Cleaning source.$(NC)") $(RM) coverage.txt btcec/coverage.txt btcutil/coverage.txt btcutil/psbt/coverage.txt +#? tidy-module: Run 'go mod tidy' for all modules tidy-module: echo "Running 'go mod tidy' for all modules" scripts/tidy_modules.sh @@ -148,3 +162,10 @@ tidy-module: fmt \ lint \ clean + +#? help: Get more info on make commands +help: Makefile + @echo " Choose a command run in btcd:" + @sed -n 's/^#?//p' $< | column -t -s ':' | sort | sed -e 's/^/ /' + +.PHONY: help From c4b144821204f7f76e1d63bea4af628baf150276 Mon Sep 17 00:00:00 2001 From: ly <58056533+devlzcode@users.noreply.github.com> Date: Thu, 25 Jan 2024 19:24:23 -0800 Subject: [PATCH 0950/1056] feat: Expose newFutureError for developer friendliness --- rpcclient/infrastructure.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 258ed130f9..8543106b15 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -984,6 +984,11 @@ func newFutureError(err error) chan *Response { return responseChan } +// Expose newFutureError for developer usage when creating custom commands. +func NewFutureError(err error) chan *Response { + return newFutureError(err) +} + // ReceiveFuture receives from the passed futureResult channel to extract a // reply or any errors. The examined errors include an error in the // futureResult and the error in the reply from the server. This will block From 069a0eca2946df5c9ddf9bff0f34561c041efba1 Mon Sep 17 00:00:00 2001 From: Nikolay Bryskin Date: Mon, 5 Feb 2024 14:55:17 +0200 Subject: [PATCH 0951/1056] Added 'include_unsafe' option to FundRawTransaction --- btcjson/chainsvrcmds.go | 1 + 1 file changed, 1 insertion(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index e314f35c32..58fa8cd1b6 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -147,6 +147,7 @@ type FundRawTransactionOpts struct { Replaceable *bool `json:"replaceable,omitempty"` ConfTarget *int `json:"conf_target,omitempty"` EstimateMode *EstimateSmartFeeMode `json:"estimate_mode,omitempty"` + IncludeUnsafe *bool `json:"include_unsafe,omitempty"` } // FundRawTransactionCmd defines the fundrawtransaction JSON-RPC command From 8836219a0202e6d7f58d4d6d8be9fd1b4c615638 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 16 Feb 2024 16:15:27 +0900 Subject: [PATCH 0952/1056] blockchain: return error in db.View instead of t.Fatal Calling t.Fatal inside db.View makes the test hang on failures. Return the error and call t.Fatal outside of db.View avoids this. --- blockchain/utxocache_test.go | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 45116655e3..64d517b09a 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -749,36 +749,40 @@ func TestFlushOnPrune(t *testing.T) { ffldb.TstRunWithMaxBlockFileSize(chain.db, maxBlockFileSize, syncBlocks) // Function that errors out if the block that should exist doesn't exist. - shouldExist := func(dbTx database.Tx, blockHash *chainhash.Hash) { + shouldExist := func(dbTx database.Tx, blockHash *chainhash.Hash) error { bytes, err := dbTx.FetchBlock(blockHash) if err != nil { - t.Fatal(err) + return err } block, err := btcutil.NewBlockFromBytes(bytes) if err != nil { - t.Fatalf("didn't find block %v. %v", blockHash, err) + return fmt.Errorf("didn't find block %v. %v", blockHash, err) } if !block.Hash().IsEqual(blockHash) { - t.Fatalf("expected to find block %v but got %v", + return fmt.Errorf("expected to find block %v but got %v", blockHash, block.Hash()) } + + return nil } // Function that errors out if the block that shouldn't exist exists. - shouldNotExist := func(dbTx database.Tx, blockHash *chainhash.Hash) { + shouldNotExist := func(dbTx database.Tx, blockHash *chainhash.Hash) error { bytes, err := dbTx.FetchBlock(chaincfg.MainNetParams.GenesisHash) if err == nil { - t.Fatalf("expected block %s to be pruned", blockHash) + return fmt.Errorf("expected block %s to be pruned", blockHash.String()) } if len(bytes) != 0 { - t.Fatalf("expected block %s to be pruned but got %v", + return fmt.Errorf("expected block %s to be pruned but got %v", blockHash, bytes) } + + return nil } // The below code checks that the correct blocks were pruned. - chain.db.View(func(dbTx database.Tx) error { + err = chain.db.View(func(dbTx database.Tx) error { exist := false for _, block := range blocks { // Blocks up to the last flush hash should not exist. @@ -789,15 +793,23 @@ func TestFlushOnPrune(t *testing.T) { } if exist { - shouldExist(dbTx, block.Hash()) + err = shouldExist(dbTx, block.Hash()) + if err != nil { + return err + } } else { - shouldNotExist(dbTx, block.Hash()) + err = shouldNotExist(dbTx, block.Hash()) + if err != nil { + return err + } } - } return nil }) + if err != nil { + t.Fatal(err) + } } func TestInitConsistentState(t *testing.T) { From a0c9e3b384ec6c2e54f91f00da5dccfea971504a Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 16 Feb 2024 15:49:11 +0900 Subject: [PATCH 0953/1056] blockchain: add case for pruning stale blocks Pruning stale blocks will make the block validation fail for the block that the prune was triggered on as BlockHeightByHash will not return the height for blocks that are not in the main chain. We add a test case to ensure that the test fails in the above case. --- blockchain/utxocache_test.go | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 64d517b09a..2e055ea5db 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -729,18 +729,33 @@ func TestFlushOnPrune(t *testing.T) { } syncBlocks := func() { + // Modify block 1 to be a different hash. This is to artificially + // create a stale branch in the chain. + staleMsgBlock := blocks[1].MsgBlock().Copy() + staleMsgBlock.Header.Nonce = 0 + staleBlock := btcutil.NewBlock(staleMsgBlock) + + // Add the stale block here to create a chain view like so. The + // block will be the main chain at first but become stale as we + // keep adding blocks. BFNoPoWCheck is given as the pow check will + // fail. + // + // (genesis block) -> 1 -> 2 -> 3 -> ... + // \-> 1a + _, _, err = chain.ProcessBlock(staleBlock, BFNoPoWCheck) + if err != nil { + t.Fatal(err) + } + for i, block := range blocks { if i == 0 { // Skip the genesis block. continue } - isMainChain, _, err := chain.ProcessBlock(block, BFNone) + _, _, err = chain.ProcessBlock(block, BFNone) if err != nil { - t.Fatal(err) - } - - if !isMainChain { - t.Fatalf("expected block %s to be on the main chain", block.Hash()) + t.Fatalf("Failed to process block %v(%v). %v", + block.Hash().String(), block.Height(), err) } } } From 5a91ea23ca9a702310eb2ef788928c7f6d8ccba5 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 21 Feb 2024 18:14:26 +0900 Subject: [PATCH 0954/1056] blockchain_test, fullblocktests: add test to check for utxo existance/non-existance New test instance BlockDisconnectExpectUTXO tests that a utxo exists/doesn't exist after a specific block has been disconnected. --- blockchain/fullblocks_test.go | 66 +++++++++++++++++++++++ blockchain/fullblocktests/generate.go | 77 ++++++++++++++++++++++++++- 2 files changed, 141 insertions(+), 2 deletions(-) diff --git a/blockchain/fullblocks_test.go b/blockchain/fullblocks_test.go index d6bcf799af..591414d1d0 100644 --- a/blockchain/fullblocks_test.go +++ b/blockchain/fullblocks_test.go @@ -146,6 +146,70 @@ func TestFullBlocks(t *testing.T) { } defer teardownFunc() + testBlockDisconnectExpectUTXO := func(item fullblocktests.BlockDisconnectExpectUTXO) { + expectedCallBack := func(notification *blockchain.Notification) { + switch notification.Type { + + case blockchain.NTBlockDisconnected: + block, ok := notification.Data.(*btcutil.Block) + if !ok { + t.Fatalf("expected a block") + } + + // Return early if the block we get isn't the relevant + // block. + if !block.Hash().IsEqual(&item.BlockHash) { + return + } + + entry, err := chain.FetchUtxoEntry(item.OutPoint) + if err != nil { + t.Fatal(err) + } + + if entry == nil || entry.IsSpent() { + t.Logf("expected utxo %v to exist but it's "+ + "nil or spent\n", item.OutPoint.String()) + t.Fatalf("expected utxo %v to exist but it's "+ + "nil or spent", item.OutPoint.String()) + } + } + } + unexpectedCallBack := func(notification *blockchain.Notification) { + switch notification.Type { + case blockchain.NTBlockDisconnected: + block, ok := notification.Data.(*btcutil.Block) + if !ok { + t.Fatalf("expected a block") + } + + // Return early if the block we get isn't the relevant + // block. + if !block.Hash().IsEqual(&item.BlockHash) { + return + } + + entry, err := chain.FetchUtxoEntry(item.OutPoint) + if err != nil { + t.Fatal(err) + } + + if entry != nil && !entry.IsSpent() { + t.Logf("unexpected utxo %v to exist but it's "+ + "not nil and not spent", item.OutPoint.String()) + t.Fatalf("unexpected utxo %v exists but it's "+ + "not nil and not spent\n", item.OutPoint.String()) + } + } + } + + if item.Expected { + chain.Subscribe(expectedCallBack) + } else { + chain.Subscribe(unexpectedCallBack) + } + } + // testAcceptedBlock attempts to process the block in the provided test // instance and ensures that it was accepted according to the flags // specified in the test. @@ -300,6 +364,8 @@ func TestFullBlocks(t *testing.T) { testOrphanOrRejectedBlock(item) case fullblocktests.ExpectedTip: testExpectedTip(item) + case fullblocktests.BlockDisconnectExpectUTXO: + testBlockDisconnectExpectUTXO(item) default: t.Fatalf("test #%d, item #%d is not one of "+ "the supported test instance types -- "+ diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 4c551c05e0..15b92540b5 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -150,6 +150,21 @@ type RejectedNonCanonicalBlock struct { // This implements the TestInstance interface. func (b RejectedNonCanonicalBlock) FullBlockTestInstance() {} +// BlockDisconnectExpectUTXO defines a test instance that tests an utxo to exist or not +// exist after a specified block has been disconnected. +type BlockDisconnectExpectUTXO struct { + Name string + Expected bool + BlockHash chainhash.Hash + OutPoint wire.OutPoint +} + +// FullBlockTestInstance only exists to allow BlockDisconnectExpectUTXO to be treated as +// a TestInstance. +// +// This implements the TestInstance interface. +func (b BlockDisconnectExpectUTXO) FullBlockTestInstance() {} + // spendableOut represents a transaction output that is spendable along with // additional metadata such as the block its in and how much it pays. type spendableOut struct { @@ -878,6 +893,9 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // // orphanedOrRejected creates and appends a single orphanOrRejectBlock // test instance for the current tip. + // + // blockDisconnectExpectUTXO creates and appends a BlockDisconnectExpectUTXO test + // instance with the passed in values. accepted := func() { tests = append(tests, []TestInstance{ acceptBlock(g.tipName, g.tip, true, false), @@ -904,6 +922,12 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { orphanOrRejectBlock(g.tipName, g.tip), }) } + blockDisconnectExpectUTXO := func(name string, expected bool, op wire.OutPoint, + hash chainhash.Hash) { + tests = append(tests, []TestInstance{ + BlockDisconnectExpectUTXO{name, expected, hash, op}, + }) + } // --------------------------------------------------------------------- // Generate enough blocks to have mature coinbase outputs to work with. @@ -2044,6 +2068,55 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { } accepted() + // Create a chain where the utxo created in b82a is spent in b83a. + // + // b81() -> b82a(28) -> b83a(b82.tx[1].out[0]) + // + g.nextBlock("b82a", outs[28]) + accepted() + + b82aTx1Out0 := makeSpendableOut(g.tip, 1, 0) + g.nextBlock("b83a", &b82aTx1Out0) + accepted() + + // Now we'll build a side-chain where we don't spend any of the outputs. + // + // b81() -> b82a(28) -> b83a(b82.tx[1].out[0]) + // \-> b82() -> b83() + // + g.setTip("b81") + g.nextBlock("b82", nil) + acceptedToSideChainWithExpectedTip("b83a") + + g.nextBlock("b83", nil) + acceptedToSideChainWithExpectedTip("b83a") + + // At this point b83a is still the tip. When we add block 84, the tip + // will change. Pre-load up the expected utxos test before the reorganization. + // + // We expect b82a output to now be a utxo since b83a was spending it and it was + // removed from the main chain. + blockDisconnectExpectUTXO("b82aTx1Out0", + true, b82aTx1Out0.prevOut, g.blocksByName["b83a"].BlockHash()) + + // We expect the output from b82 to not exist once b82a itself has been removed + // from the main chain. + blockDisconnectExpectUTXO("b82aTx1Out0", + false, b82aTx1Out0.prevOut, g.blocksByName["b82a"].BlockHash()) + + // The output that was being spent in b82a should exist after the removal of + // b82a. + blockDisconnectExpectUTXO("outs[28]", + true, outs[28].prevOut, g.blocksByName["b82a"].BlockHash()) + + // Create block 84 and reorg out the sidechain with b83a as the tip. + // + // b81() -> b82a(28) -> b83a(b82.tx[1].out[0]) + // \-> b82() -> b83() -> b84() + // + g.nextBlock("b84", nil) + accepted() + // --------------------------------------------------------------------- // Large block re-org test. // --------------------------------------------------------------------- @@ -2054,8 +2127,8 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // Ensure the tip the re-org test builds on is the best chain tip. // - // ... -> b81(27) -> ... - g.setTip("b81") + // ... -> b84() -> ... + g.setTip("b84") // Collect all of the spendable coinbase outputs from the previous // collection point up to the current tip. From 3d1150a1a853ea57059ca1ad41c558d5343a31bd Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 27 Feb 2024 14:32:42 +0900 Subject: [PATCH 0955/1056] blockchain: always relock chainLock for subscription callbacks For various b.sendNotifcation() callbacks, if a runtime panic happens, we don't get any useful debugging information since the error that happens first is the "unlock of unlocked mutex" error. This is because we temporarily unlock the chainLock for callbacks and then relock them. However, since the relocking code is executed after the completion of the callback, if an error happens during that callback, we never relock the chainLock. Switching to an anonymous function and having the unlock code as a defer will ensure that the lock always relocks. --- blockchain/accept.go | 8 +++++--- blockchain/chain.go | 16 ++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/blockchain/accept.go b/blockchain/accept.go index 935963148f..4adc2f6127 100644 --- a/blockchain/accept.go +++ b/blockchain/accept.go @@ -84,9 +84,11 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags) // Notify the caller that the new block was accepted into the block // chain. The caller would typically want to react by relaying the // inventory to other peers. - b.chainLock.Unlock() - b.sendNotification(NTBlockAccepted, block) - b.chainLock.Lock() + func() { + b.chainLock.Unlock() + defer b.chainLock.Lock() + b.sendNotification(NTBlockAccepted, block) + }() return isMainChain, nil } diff --git a/blockchain/chain.go b/blockchain/chain.go index 60420022ac..416ed92931 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -730,9 +730,11 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, // Notify the caller that the block was connected to the main chain. // The caller would typically want to react with actions such as // updating wallets. - b.chainLock.Unlock() - b.sendNotification(NTBlockConnected, block) - b.chainLock.Lock() + func() { + b.chainLock.Unlock() + defer b.chainLock.Lock() + b.sendNotification(NTBlockConnected, block) + }() // Since we may have changed the UTXO cache, we make sure it didn't exceed its // maximum size. If we're pruned and have flushed already, this will be a no-op. @@ -853,9 +855,11 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view // Notify the caller that the block was disconnected from the main // chain. The caller would typically want to react with actions such as // updating wallets. - b.chainLock.Unlock() - b.sendNotification(NTBlockDisconnected, block) - b.chainLock.Lock() + func() { + b.chainLock.Unlock() + defer b.chainLock.Lock() + b.sendNotification(NTBlockDisconnected, block) + }() return nil } From dd31767617daa87effd0fc784c7d92c824d4c178 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 23 Feb 2024 14:44:24 +0800 Subject: [PATCH 0956/1056] btcjson: add new command `GetTxSpendingPrevOutCmd` --- btcjson/chainsvrcmds.go | 33 +++++++++++++++++++++++++++++++++ btcjson/chainsvrcmds_test.go | 24 ++++++++++++++++++++++++ btcjson/chainsvrresults.go | 14 ++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 58fa8cd1b6..956b4db604 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -1064,6 +1064,38 @@ func NewTestMempoolAcceptCmd(rawTxns []string, } } +// GetTxSpendingPrevOutCmd defines the gettxspendingprevout JSON-RPC command. +type GetTxSpendingPrevOutCmd struct { + // Outputs is a list of transaction outputs to query. + Outputs []*GetTxSpendingPrevOutCmdOutput +} + +// GetTxSpendingPrevOutCmdOutput defines the output to query for the +// gettxspendingprevout JSON-RPC command. +type GetTxSpendingPrevOutCmdOutput struct { + Txid string `json:"txid"` + Vout uint32 `json:"vout"` +} + +// NewGetTxSpendingPrevOutCmd returns a new instance which can be used to issue +// a gettxspendingprevout JSON-RPC command. +func NewGetTxSpendingPrevOutCmd( + outpoints []wire.OutPoint) *GetTxSpendingPrevOutCmd { + + outputs := make([]*GetTxSpendingPrevOutCmdOutput, 0, len(outpoints)) + + for _, op := range outpoints { + outputs = append(outputs, &GetTxSpendingPrevOutCmdOutput{ + Txid: op.Hash.String(), + Vout: op.Index, + }) + } + + return &GetTxSpendingPrevOutCmd{ + Outputs: outputs, + } +} + func init() { // No special flags for commands in this file. flags := UsageFlag(0) @@ -1125,4 +1157,5 @@ func init() { MustRegisterCmd("verifymessage", (*VerifyMessageCmd)(nil), flags) MustRegisterCmd("verifytxoutproof", (*VerifyTxOutProofCmd)(nil), flags) MustRegisterCmd("testmempoolaccept", (*TestMempoolAcceptCmd)(nil), flags) + MustRegisterCmd("gettxspendingprevout", (*GetTxSpendingPrevOutCmd)(nil), flags) } diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index eddfb03788..d3143a528c 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -13,6 +13,7 @@ import ( "testing" "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" ) @@ -1500,6 +1501,29 @@ func TestChainSvrCmds(t *testing.T) { MaxFeeRate: 0.01, }, }, + { + name: "gettxspendingprevout", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd( + "gettxspendingprevout", + []*btcjson.GetTxSpendingPrevOutCmdOutput{ + {Txid: "0000000000000000000000000000000000000000000000000000000000000001", Vout: 0}, + }) + }, + staticCmd: func() interface{} { + outputs := []wire.OutPoint{ + {Hash: chainhash.Hash{1}, Index: 0}, + } + return btcjson.NewGetTxSpendingPrevOutCmd(outputs) + }, + marshalled: `{"jsonrpc":"1.0","method":"gettxspendingprevout","params":[[{"txid":"0000000000000000000000000000000000000000000000000000000000000001","vout":0}]],"id":1}`, + unmarshalled: &btcjson.GetTxSpendingPrevOutCmd{ + Outputs: []*btcjson.GetTxSpendingPrevOutCmdOutput{{ + Txid: "0000000000000000000000000000000000000000000000000000000000000001", + Vout: 0, + }}, + }, + }, } t.Logf("Running %d tests", len(tests)) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 8f59f77676..11c0483d31 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -911,3 +911,17 @@ type TestMempoolAcceptFees struct { // NOTE: this field only exists in bitcoind v25.0 and above. EffectiveIncludes []string `json:"effective-includes"` } + +// GetTxSpendingPrevOutResult defines a single item returned from the +// gettxspendingprevout command. +type GetTxSpendingPrevOutResult struct { + // Txid is the transaction id of the checked output. + Txid string `json:"txid"` + + // Vout is the vout value of the checked output. + Vout uint32 `json:"vout"` + + // SpendingTxid is the transaction id of the mempool transaction + // spending this output (omitted if unspent). + SpendingTxid string `json:"spendingtxid,omitempty"` +} From 72bbdd55a6e40e0723b56f8e50440fd49f461ead Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 23 Feb 2024 15:29:57 +0800 Subject: [PATCH 0957/1056] rpcserver+mempool: implement `gettxspendingprevout` for `btcd` This commit adds the RPC method `gettxspendingprevout` for btcd. --- mempool/mocks.go | 4 +++ rpcserver.go | 44 +++++++++++++++++++++++++ rpcserver_test.go | 84 +++++++++++++++++++++++++++++++++++++++++++++++ rpcserverhelp.go | 12 +++++++ 4 files changed, 144 insertions(+) diff --git a/mempool/mocks.go b/mempool/mocks.go index 5f50bb0730..e81309c51a 100644 --- a/mempool/mocks.go +++ b/mempool/mocks.go @@ -117,5 +117,9 @@ func (m *MockTxMempool) CheckMempoolAcceptance( func (m *MockTxMempool) CheckSpend(op wire.OutPoint) *btcutil.Tx { args := m.Called(op) + if args.Get(0) == nil { + return nil + } + return args.Get(0).(*btcutil.Tx) } diff --git a/rpcserver.go b/rpcserver.go index 2433286ac7..d6f3167f1e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -185,6 +185,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "verifymessage": handleVerifyMessage, "version": handleVersion, "testmempoolaccept": handleTestMempoolAccept, + "gettxspendingprevout": handleGetTxSpendingPrevOut, } // list of commands that we recognize, but for which btcd has no support because @@ -3906,6 +3907,49 @@ func handleTestMempoolAccept(s *rpcServer, cmd interface{}, return results, nil } +// handleGetTxSpendingPrevOut implements the gettxspendingprevout command. +func handleGetTxSpendingPrevOut(s *rpcServer, cmd interface{}, + closeChan <-chan struct{}) (interface{}, error) { + + c := cmd.(*btcjson.GetTxSpendingPrevOutCmd) + + // Convert the outpoints. + ops := make([]wire.OutPoint, 0, len(c.Outputs)) + for _, o := range c.Outputs { + hash, err := chainhash.NewHashFromStr(o.Txid) + if err != nil { + return nil, err + } + + ops = append(ops, wire.OutPoint{ + Hash: *hash, + Index: o.Vout, + }) + } + + // Check mempool spend for all the outpoints. + results := make([]*btcjson.GetTxSpendingPrevOutResult, 0, len(ops)) + for _, op := range ops { + // Create a result entry. + result := &btcjson.GetTxSpendingPrevOutResult{ + Txid: op.Hash.String(), + Vout: op.Index, + } + + // Check the mempool spend. + spendingTx := s.cfg.TxMemPool.CheckSpend(op) + + // Set the spending txid if found. + if spendingTx != nil { + result.SpendingTxid = spendingTx.Hash().String() + } + + results = append(results, result) + } + + return results, nil +} + // validateFeeRate checks that the fee rate used by transaction doesn't exceed // the max fee rate specified. func validateFeeRate(feeSats btcutil.Amount, txSize int64, diff --git a/rpcserver_test.go b/rpcserver_test.go index 6ca15766c3..0aa9391321 100644 --- a/rpcserver_test.go +++ b/rpcserver_test.go @@ -9,6 +9,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/mempool" + "github.com/btcsuite/btcd/wire" "github.com/stretchr/testify/require" ) @@ -411,3 +412,86 @@ func TestHandleTestMempoolAcceptFees(t *testing.T) { }) } } + +// TestGetTxSpendingPrevOut checks that handleGetTxSpendingPrevOut handles the +// cmd as expected. +func TestGetTxSpendingPrevOut(t *testing.T) { + t.Parallel() + + require := require.New(t) + + // Create a mock mempool. + mm := &mempool.MockTxMempool{} + defer mm.AssertExpectations(t) + + // Create a testing server with the mock mempool. + s := &rpcServer{cfg: rpcserverConfig{ + TxMemPool: mm, + }} + + // First, check the error case. + // + // Create a request that will cause an error. + cmd := &btcjson.GetTxSpendingPrevOutCmd{ + Outputs: []*btcjson.GetTxSpendingPrevOutCmdOutput{ + {Txid: "invalid"}, + }, + } + + // Call the method handler and assert the error is returned. + closeChan := make(chan struct{}) + results, err := handleGetTxSpendingPrevOut(s, cmd, closeChan) + require.Error(err) + require.Nil(results) + + // We now check the normal case. Two outputs will be tested - one found + // in mempool and other not. + // + // Decode the hex so we can assert the mock mempool is called with it. + tx := decodeTxHex(t, txHex1) + + // Create testing outpoints. + opInMempool := wire.OutPoint{Hash: chainhash.Hash{1}, Index: 1} + opNotInMempool := wire.OutPoint{Hash: chainhash.Hash{2}, Index: 1} + + // We only expect to see one output being found as spent in mempool. + expectedResults := []*btcjson.GetTxSpendingPrevOutResult{ + { + Txid: opInMempool.Hash.String(), + Vout: opInMempool.Index, + SpendingTxid: tx.Hash().String(), + }, + { + Txid: opNotInMempool.Hash.String(), + Vout: opNotInMempool.Index, + }, + } + + // We mock the first call to `CheckSpend` to return a result saying the + // output is found. + mm.On("CheckSpend", opInMempool).Return(tx).Once() + + // We mock the second call to `CheckSpend` to return a result saying the + // output is NOT found. + mm.On("CheckSpend", opNotInMempool).Return(nil).Once() + + // Create a request with the above outputs. + cmd = &btcjson.GetTxSpendingPrevOutCmd{ + Outputs: []*btcjson.GetTxSpendingPrevOutCmdOutput{ + { + Txid: opInMempool.Hash.String(), + Vout: opInMempool.Index, + }, + { + Txid: opNotInMempool.Hash.String(), + Vout: opNotInMempool.Index, + }, + }, + } + + // Call the method handler and assert the expected result is returned. + closeChan = make(chan struct{}) + results, err = handleGetTxSpendingPrevOut(s, cmd, closeChan) + require.NoError(err) + require.Equal(expectedResults, results) +} diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 0ee8485180..0cc384db2c 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -734,6 +734,17 @@ var helpDescsEnUS = map[string]string{ "testmempoolacceptfees-base": "Transaction fees (only present if 'allowed' is true).", "testmempoolacceptfees-effective-feerate": "The effective feerate in BTC per KvB.", "testmempoolacceptfees-effective-includes": "Transactions whose fees and vsizes are included in effective-feerate. Each item is a transaction wtxid in hex.", + + // GetTxSpendingPrevOutCmd help. + "gettxspendingprevout--synopsis": "Scans the mempool to find transactions spending any of the given outputs", + "gettxspendingprevout-outputs": "The transaction outputs that we want to check, and within each, the txid (string) vout (numeric).", + "gettxspendingprevout-txid": "The transaction id", + "gettxspendingprevout-vout": "The output number", + + // GetTxSpendingPrevOutCmd result help. + "gettxspendingprevoutresult-txid": "The transaction hash in hex.", + "gettxspendingprevoutresult-vout": "The output index.", + "gettxspendingprevoutresult-spendingtxid": "The hash of the transaction that spends the output.", } // rpcResultTypes specifies the result types that each RPC command can return. @@ -790,6 +801,7 @@ var rpcResultTypes = map[string][]interface{}{ "verifymessage": {(*bool)(nil)}, "version": {(*map[string]btcjson.VersionResult)(nil)}, "testmempoolaccept": {(*[]btcjson.TestMempoolAcceptResult)(nil)}, + "gettxspendingprevout": {(*[]btcjson.GetTxSpendingPrevOutResult)(nil)}, // Websocket commands. "loadtxfilter": nil, From 5f71df165e53d8bb0b9a1f7f0b1c8c4c0e7a4781 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 23 Feb 2024 16:43:04 +0800 Subject: [PATCH 0958/1056] rpcclient: track bitcoind version 24.0.0 We need this for `gettxspendingprevout`. --- rpcclient/infrastructure.go | 17 +++++++++++++++-- rpcclient/infrastructure_test.go | 11 ++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 8543106b15..ad2b391a22 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -114,8 +114,12 @@ const ( // 0.19.0 and smaller than 22.0.0. BitcoindPre22 + // BitcoindPre24 represents a bitcoind version equal to or greater than + // 22.0.0 and smaller than 24.0.0. + BitcoindPre24 + // BitcoindPre25 represents a bitcoind version equal to or greater than - // 22.0.0 and smaller than 25.0.0. + // 24.0.0 and smaller than 25.0.0. BitcoindPre25 // BitcoindPre25 represents a bitcoind version equal to or greater than @@ -135,8 +139,11 @@ func (b BackendVersion) String() string { case BitcoindPre22: return "bitcoind v0.19.0-v22.0.0" + case BitcoindPre24: + return "bitcoind v22.0.0-v24.0.0" + case BitcoindPre25: - return "bitcoind v22.0.0-v25.0.0" + return "bitcoind v24.0.0-v25.0.0" case BitcoindPost25: return "bitcoind v25.0.0 and above" @@ -1625,6 +1632,9 @@ const ( // bitcoind22Str is the string representation of bitcoind v22.0.0. bitcoind22Str = "22.0.0" + // bitcoind24Str is the string representation of bitcoind v24.0.0. + bitcoind24Str = "24.0.0" + // bitcoind25Str is the string representation of bitcoind v25.0.0. bitcoind25Str = "25.0.0" @@ -1653,6 +1663,9 @@ func parseBitcoindVersion(version string) BackendVersion { case version < bitcoind22Str: return BitcoindPre22 + case version < bitcoind24Str: + return BitcoindPre24 + case version < bitcoind25Str: return BitcoindPre25 diff --git a/rpcclient/infrastructure_test.go b/rpcclient/infrastructure_test.go index e97fa275c0..bf09831a2e 100644 --- a/rpcclient/infrastructure_test.go +++ b/rpcclient/infrastructure_test.go @@ -34,11 +34,16 @@ func TestParseBitcoindVersion(t *testing.T) { { name: "parse version 22.0", rpcVersion: "/Satoshi:22.0.0/", - parsedVersion: BitcoindPre25, + parsedVersion: BitcoindPre24, + }, + { + name: "parse version 22.0 - 24.0", + rpcVersion: "/Satoshi:23.1.0/", + parsedVersion: BitcoindPre24, }, { - name: "parse version 22.0 - 25.0", - rpcVersion: "/Satoshi:23.0.0/", + name: "parse version 24.0", + rpcVersion: "/Satoshi:24.0.0/", parsedVersion: BitcoindPre25, }, { From a033b0d6e70353d3a6f33b3bdeca08088b9dd22a Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 23 Feb 2024 16:30:14 +0800 Subject: [PATCH 0959/1056] rpcclient+integration: add new method `GetTxSpendingPrevOut` --- integration/chain_test.go | 146 +++++++++++++++++++++++++++++++++++ rpcclient/rawtransactions.go | 68 ++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 integration/chain_test.go diff --git a/integration/chain_test.go b/integration/chain_test.go new file mode 100644 index 0000000000..0f5cd94c83 --- /dev/null +++ b/integration/chain_test.go @@ -0,0 +1,146 @@ +//go:build rpctest +// +build rpctest + +package integration + +import ( + "testing" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/integration/rpctest" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/stretchr/testify/require" +) + +// TestGetTxSpendingPrevOut checks that `GetTxSpendingPrevOut` behaves as +// expected. +// - an error is returned when invalid params are used. +// - orphan tx is rejected. +// - fee rate above the max is rejected. +// - a mixed of both allowed and rejected can be returned in the same response. +func TestGetTxSpendingPrevOut(t *testing.T) { + t.Parallel() + + // Boilerplate codetestDir to make a pruned node. + btcdCfg := []string{"--rejectnonstd", "--debuglevel=debug"} + r, err := rpctest.New(&chaincfg.SimNetParams, nil, btcdCfg, "") + require.NoError(t, err) + + // Setup the node. + require.NoError(t, r.SetUp(true, 100)) + t.Cleanup(func() { + require.NoError(t, r.TearDown()) + }) + + // Create a tx and testing outpoints. + tx := createTxInMempool(t, r) + opInMempool := tx.TxIn[0].PreviousOutPoint + opNotInMempool := wire.OutPoint{ + Hash: tx.TxHash(), + Index: 0, + } + + testCases := []struct { + name string + outpoints []wire.OutPoint + expectedErr error + expectedResult []*btcjson.GetTxSpendingPrevOutResult + }{ + { + // When no outpoints are provided, the method should + // return an error. + name: "empty outpoints", + expectedErr: rpcclient.ErrInvalidParam, + expectedResult: nil, + }, + { + // When there are outpoints provided, check the + // expceted results are returned. + name: "outpoints", + outpoints: []wire.OutPoint{ + opInMempool, opNotInMempool, + }, + expectedErr: nil, + expectedResult: []*btcjson.GetTxSpendingPrevOutResult{ + { + Txid: opInMempool.Hash.String(), + Vout: opInMempool.Index, + SpendingTxid: tx.TxHash().String(), + }, + { + Txid: opNotInMempool.Hash.String(), + Vout: opNotInMempool.Index, + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + require := require.New(t) + + results, err := r.Client.GetTxSpendingPrevOut( + tc.outpoints, + ) + + require.ErrorIs(err, tc.expectedErr) + require.Len(results, len(tc.expectedResult)) + + // Check each item is returned as expected. + for i, r := range results { + e := tc.expectedResult[i] + + require.Equal(e.Txid, r.Txid) + require.Equal(e.Vout, r.Vout) + require.Equal(e.SpendingTxid, r.SpendingTxid) + } + }) + } +} + +// createTxInMempool creates a tx and puts it in the mempool. +func createTxInMempool(t *testing.T, r *rpctest.Harness) *wire.MsgTx { + // Create a fresh output for usage within the test below. + const outputValue = btcutil.SatoshiPerBitcoin + outputKey, testOutput, testPkScript, err := makeTestOutput( + r, t, outputValue, + ) + require.NoError(t, err) + + // Create a new transaction with a lock-time past the current known + // MTP. + tx := wire.NewMsgTx(1) + tx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: *testOutput, + }) + + // Fetch a fresh address from the harness, we'll use this address to + // send funds back into the Harness. + addr, err := r.NewAddress() + require.NoError(t, err) + + addrScript, err := txscript.PayToAddrScript(addr) + require.NoError(t, err) + + tx.AddTxOut(&wire.TxOut{ + PkScript: addrScript, + Value: outputValue - 1000, + }) + + sigScript, err := txscript.SignatureScript( + tx, 0, testPkScript, txscript.SigHashAll, outputKey, true, + ) + require.NoError(t, err) + tx.TxIn[0].SignatureScript = sigScript + + // Send the tx. + _, err = r.Client.SendRawTransaction(tx, true) + require.NoError(t, err) + + return tx +} diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index a683021946..4737aee5b9 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -1012,3 +1012,71 @@ func (c *Client) TestMempoolAccept(txns []*wire.MsgTx, return c.TestMempoolAcceptAsync(txns, maxFeeRate).Receive() } + +// FutureGetTxSpendingPrevOut is a future promise to deliver the result of a +// GetTxSpendingPrevOut RPC invocation (or an applicable error). +type FutureGetTxSpendingPrevOut chan *Response + +// Receive waits for the Response promised by the future and returns the +// response from GetTxSpendingPrevOut. +func (r FutureGetTxSpendingPrevOut) Receive() ( + []*btcjson.GetTxSpendingPrevOutResult, error) { + + response, err := ReceiveFuture(r) + if err != nil { + return nil, err + } + + // Unmarshal as an array of GetTxSpendingPrevOutResult items. + var results []*btcjson.GetTxSpendingPrevOutResult + + err = json.Unmarshal(response, &results) + if err != nil { + return nil, err + } + + return results, nil +} + +// GetTxSpendingPrevOutAsync returns an instance of a type that can be used to +// get the result of the RPC at some future time by invoking the Receive +// function on the returned instance. +// +// See GetTxSpendingPrevOut for the blocking version and more details. +func (c *Client) GetTxSpendingPrevOutAsync( + outpoints []wire.OutPoint) FutureGetTxSpendingPrevOut { + + // Due to differences in the testmempoolaccept API for different + // backends, we'll need to inspect our version and construct the + // appropriate request. + version, err := c.BackendVersion() + if err != nil { + return newFutureError(err) + } + + log.Debugf("GetTxSpendingPrevOutAsync: backend version %s", version) + + // Exit early if the version is below 24.0.0. + if version < BitcoindPre24 { + err := fmt.Errorf("%w: %v", ErrBitcoindVersion, version) + return newFutureError(err) + } + + // Exit early if an empty array of outpoints is provided. + if len(outpoints) == 0 { + err := fmt.Errorf("%w: no outpoints provided", ErrInvalidParam) + return newFutureError(err) + } + + cmd := btcjson.NewGetTxSpendingPrevOutCmd(outpoints) + + return c.SendCmd(cmd) +} + +// GetTxSpendingPrevOut returns the result from calling `gettxspendingprevout` +// RPC. +func (c *Client) GetTxSpendingPrevOut(outpoints []wire.OutPoint) ( + []*btcjson.GetTxSpendingPrevOutResult, error) { + + return c.GetTxSpendingPrevOutAsync(outpoints).Receive() +} From 0d52a890f26c3aef21a38f7a8ad349a22aa5984a Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 23 Feb 2024 18:51:34 +0800 Subject: [PATCH 0960/1056] rpcclient: handle backend versioning in one file --- rpcclient/backend_version.go | 106 ++++++++++++++++++ ...ucture_test.go => backend_version_test.go} | 0 rpcclient/infrastructure.go | 104 ----------------- 3 files changed, 106 insertions(+), 104 deletions(-) create mode 100644 rpcclient/backend_version.go rename rpcclient/{infrastructure_test.go => backend_version_test.go} (100%) diff --git a/rpcclient/backend_version.go b/rpcclient/backend_version.go new file mode 100644 index 0000000000..70037e150b --- /dev/null +++ b/rpcclient/backend_version.go @@ -0,0 +1,106 @@ +package rpcclient + +import "strings" + +// BackendVersion represents the version of the backend the client is currently +// connected to. +type BackendVersion uint8 + +const ( + // BitcoindPre19 represents a bitcoind version before 0.19.0. + BitcoindPre19 BackendVersion = iota + + // BitcoindPre22 represents a bitcoind version equal to or greater than + // 0.19.0 and smaller than 22.0.0. + BitcoindPre22 + + // BitcoindPre24 represents a bitcoind version equal to or greater than + // 22.0.0 and smaller than 24.0.0. + BitcoindPre24 + + // BitcoindPre25 represents a bitcoind version equal to or greater than + // 24.0.0 and smaller than 25.0.0. + BitcoindPre25 + + // BitcoindPre25 represents a bitcoind version equal to or greater than + // 25.0.0. + BitcoindPost25 + + // Btcd represents a catch-all btcd version. + Btcd +) + +// String returns a human-readable backend version. +func (b BackendVersion) String() string { + switch b { + case BitcoindPre19: + return "bitcoind 0.19 and below" + + case BitcoindPre22: + return "bitcoind v0.19.0-v22.0.0" + + case BitcoindPre24: + return "bitcoind v22.0.0-v24.0.0" + + case BitcoindPre25: + return "bitcoind v24.0.0-v25.0.0" + + case BitcoindPost25: + return "bitcoind v25.0.0 and above" + + case Btcd: + return "btcd" + + default: + return "unknown" + } +} + +const ( + // bitcoind19Str is the string representation of bitcoind v0.19.0. + bitcoind19Str = "0.19.0" + + // bitcoind22Str is the string representation of bitcoind v22.0.0. + bitcoind22Str = "22.0.0" + + // bitcoind24Str is the string representation of bitcoind v24.0.0. + bitcoind24Str = "24.0.0" + + // bitcoind25Str is the string representation of bitcoind v25.0.0. + bitcoind25Str = "25.0.0" + + // bitcoindVersionPrefix specifies the prefix included in every bitcoind + // version exposed through GetNetworkInfo. + bitcoindVersionPrefix = "/Satoshi:" + + // bitcoindVersionSuffix specifies the suffix included in every bitcoind + // version exposed through GetNetworkInfo. + bitcoindVersionSuffix = "/" +) + +// parseBitcoindVersion parses the bitcoind version from its string +// representation. +func parseBitcoindVersion(version string) BackendVersion { + // Trim the version of its prefix and suffix to determine the + // appropriate version number. + version = strings.TrimPrefix( + strings.TrimSuffix(version, bitcoindVersionSuffix), + bitcoindVersionPrefix, + ) + switch { + case version < bitcoind19Str: + return BitcoindPre19 + + case version < bitcoind22Str: + return BitcoindPre22 + + case version < bitcoind24Str: + return BitcoindPre24 + + case version < bitcoind25Str: + return BitcoindPre25 + + default: + return BitcoindPost25 + } +} diff --git a/rpcclient/infrastructure_test.go b/rpcclient/backend_version_test.go similarity index 100% rename from rpcclient/infrastructure_test.go rename to rpcclient/backend_version_test.go diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index ad2b391a22..404a7b4a04 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -20,7 +20,6 @@ import ( "net/http" "net/url" "os" - "strings" "sync" "sync/atomic" "time" @@ -102,60 +101,6 @@ type jsonRequest struct { responseChan chan *Response } -// BackendVersion represents the version of the backend the client is currently -// connected to. -type BackendVersion uint8 - -const ( - // BitcoindPre19 represents a bitcoind version before 0.19.0. - BitcoindPre19 BackendVersion = iota - - // BitcoindPre22 represents a bitcoind version equal to or greater than - // 0.19.0 and smaller than 22.0.0. - BitcoindPre22 - - // BitcoindPre24 represents a bitcoind version equal to or greater than - // 22.0.0 and smaller than 24.0.0. - BitcoindPre24 - - // BitcoindPre25 represents a bitcoind version equal to or greater than - // 24.0.0 and smaller than 25.0.0. - BitcoindPre25 - - // BitcoindPre25 represents a bitcoind version equal to or greater than - // 25.0.0. - BitcoindPost25 - - // Btcd represents a catch-all btcd version. - Btcd -) - -// String returns a human-readable backend version. -func (b BackendVersion) String() string { - switch b { - case BitcoindPre19: - return "bitcoind 0.19 and below" - - case BitcoindPre22: - return "bitcoind v0.19.0-v22.0.0" - - case BitcoindPre24: - return "bitcoind v22.0.0-v24.0.0" - - case BitcoindPre25: - return "bitcoind v24.0.0-v25.0.0" - - case BitcoindPost25: - return "bitcoind v25.0.0 and above" - - case Btcd: - return "btcd" - - default: - return "unknown" - } -} - // Client represents a Bitcoin RPC client which allows easy access to the // various RPC methods available on a Bitcoin RPC server. Each of the wrapper // functions handle the details of converting the passed and return types to and @@ -1625,55 +1570,6 @@ func (c *Client) Connect(tries int) error { return err } -const ( - // bitcoind19Str is the string representation of bitcoind v0.19.0. - bitcoind19Str = "0.19.0" - - // bitcoind22Str is the string representation of bitcoind v22.0.0. - bitcoind22Str = "22.0.0" - - // bitcoind24Str is the string representation of bitcoind v24.0.0. - bitcoind24Str = "24.0.0" - - // bitcoind25Str is the string representation of bitcoind v25.0.0. - bitcoind25Str = "25.0.0" - - // bitcoindVersionPrefix specifies the prefix included in every bitcoind - // version exposed through GetNetworkInfo. - bitcoindVersionPrefix = "/Satoshi:" - - // bitcoindVersionSuffix specifies the suffix included in every bitcoind - // version exposed through GetNetworkInfo. - bitcoindVersionSuffix = "/" -) - -// parseBitcoindVersion parses the bitcoind version from its string -// representation. -func parseBitcoindVersion(version string) BackendVersion { - // Trim the version of its prefix and suffix to determine the - // appropriate version number. - version = strings.TrimPrefix( - strings.TrimSuffix(version, bitcoindVersionSuffix), - bitcoindVersionPrefix, - ) - switch { - case version < bitcoind19Str: - return BitcoindPre19 - - case version < bitcoind22Str: - return BitcoindPre22 - - case version < bitcoind24Str: - return BitcoindPre24 - - case version < bitcoind25Str: - return BitcoindPre25 - - default: - return BitcoindPost25 - } -} - // BackendVersion retrieves the version of the backend the client is currently // connected to. func (c *Client) BackendVersion() (BackendVersion, error) { From 9e6070a70713c63877353685e183a9e7bf575895 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 23 Feb 2024 21:57:33 +0800 Subject: [PATCH 0961/1056] rpcclient: start tracking `btcd` version --- rpcclient/backend_version.go | 50 +++++++++++++++++++++++++++---- rpcclient/backend_version_test.go | 37 +++++++++++++++++++++++ 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/rpcclient/backend_version.go b/rpcclient/backend_version.go index 70037e150b..e2d56b0dc6 100644 --- a/rpcclient/backend_version.go +++ b/rpcclient/backend_version.go @@ -25,9 +25,6 @@ const ( // BitcoindPre25 represents a bitcoind version equal to or greater than // 25.0.0. BitcoindPost25 - - // Btcd represents a catch-all btcd version. - Btcd ) // String returns a human-readable backend version. @@ -48,9 +45,6 @@ func (b BackendVersion) String() string { case BitcoindPost25: return "bitcoind v25.0.0 and above" - case Btcd: - return "btcd" - default: return "unknown" } @@ -104,3 +98,47 @@ func parseBitcoindVersion(version string) BackendVersion { return BitcoindPost25 } } + +// BtcdVersion represents the version of the btcd the client is currently +// connected to. +type BtcdVersion int32 + +const ( + // BtcdPre2401 describes a btcd version before 0.24.1, which doesn't + // include the `testmempoolaccept` and `gettxspendingprevout` RPCs. + BtcdPre2401 BtcdVersion = iota + + // BtcdPost2401 describes a btcd version equal to or greater than + // 0.24.1. + BtcdPost2401 +) + +// String returns a human-readable backend version. +func (b BtcdVersion) String() string { + switch b { + case BtcdPre2401: + return "btcd 24.0.0 and below" + + case BtcdPost2401: + return "btcd 24.1.0 and above" + + default: + return "unknown" + } +} + +const ( + // btcd2401Val is the int representation of btcd v0.24.1. + btcd2401Val = 240100 +) + +// parseBtcdVersion parses the btcd version from its string representation. +func parseBtcdVersion(version int32) BtcdVersion { + switch { + case version < btcd2401Val: + return BtcdPre2401 + + default: + return BtcdPost2401 + } +} diff --git a/rpcclient/backend_version_test.go b/rpcclient/backend_version_test.go index bf09831a2e..91c84ad4f2 100644 --- a/rpcclient/backend_version_test.go +++ b/rpcclient/backend_version_test.go @@ -67,3 +67,40 @@ func TestParseBitcoindVersion(t *testing.T) { }) } } + +// TestParseBtcdVersion checks that the correct version from btcd's `getinfo` +// RPC call is parsed. +func TestParseBtcdVersion(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + rpcVersion int32 + parsedVersion BtcdVersion + }{ + { + name: "parse version 0.24 and below", + rpcVersion: 230000, + parsedVersion: BtcdPre2401, + }, + { + name: "parse version 0.24.1", + rpcVersion: 240100, + parsedVersion: BtcdPost2401, + }, + { + name: "parse version 0.24.1 and above", + rpcVersion: 250000, + parsedVersion: BtcdPost2401, + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + version := parseBtcdVersion(tc.rpcVersion) + require.Equal(t, tc.parsedVersion, version) + }) + } +} From 4cf49bd72c7da1e095bc3c8a992678e81fc03333 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 23 Feb 2024 22:09:44 +0800 Subject: [PATCH 0962/1056] multi: turn `BackendVersion` into an interface This commit adds a new interface, `BackendVersion`, to support checking versions for multiple both btcd and bitcoind. Once neutrino version is also pinned here, it should also be checked. --- rpcclient/backend_version.go | 76 ++++++++++++++++++++++++++++--- rpcclient/backend_version_test.go | 44 +++++++++++++++++- rpcclient/chain.go | 2 +- rpcclient/infrastructure.go | 19 ++++---- rpcclient/rawtransactions.go | 8 ++-- 5 files changed, 129 insertions(+), 20 deletions(-) diff --git a/rpcclient/backend_version.go b/rpcclient/backend_version.go index e2d56b0dc6..cb2a46fc5e 100644 --- a/rpcclient/backend_version.go +++ b/rpcclient/backend_version.go @@ -2,13 +2,32 @@ package rpcclient import "strings" -// BackendVersion represents the version of the backend the client is currently -// connected to. -type BackendVersion uint8 +// BackendVersion defines an interface to handle the version of the backend +// used by the client. +type BackendVersion interface { + // String returns a human-readable backend version. + String() string + + // SupportUnifiedSoftForks returns true if the backend supports the + // unified softforks format. + SupportUnifiedSoftForks() bool + + // SupportTestMempoolAccept returns true if the backend supports the + // testmempoolaccept RPC. + SupportTestMempoolAccept() bool + + // SupportGetTxSpendingPrevOut returns true if the backend supports the + // gettxspendingprevout RPC. + SupportGetTxSpendingPrevOut() bool +} + +// BitcoindVersion represents the version of the bitcoind the client is +// currently connected to. +type BitcoindVersion uint8 const ( // BitcoindPre19 represents a bitcoind version before 0.19.0. - BitcoindPre19 BackendVersion = iota + BitcoindPre19 BitcoindVersion = iota // BitcoindPre22 represents a bitcoind version equal to or greater than // 0.19.0 and smaller than 22.0.0. @@ -28,7 +47,7 @@ const ( ) // String returns a human-readable backend version. -func (b BackendVersion) String() string { +func (b BitcoindVersion) String() string { switch b { case BitcoindPre19: return "bitcoind 0.19 and below" @@ -50,6 +69,29 @@ func (b BackendVersion) String() string { } } +// SupportUnifiedSoftForks returns true if the backend supports the unified +// softforks format. +func (b BitcoindVersion) SupportUnifiedSoftForks() bool { + // Versions of bitcoind on or after v0.19.0 use the unified format. + return b > BitcoindPre19 +} + +// SupportTestMempoolAccept returns true if bitcoind version is 22.0.0 or +// above. +func (b BitcoindVersion) SupportTestMempoolAccept() bool { + return b > BitcoindPre22 +} + +// SupportGetTxSpendingPrevOut returns true if bitcoind version is 24.0.0 or +// above. +func (b BitcoindVersion) SupportGetTxSpendingPrevOut() bool { + return b > BitcoindPre24 +} + +// Compile-time checks to ensure that BitcoindVersion satisfy the +// BackendVersion interface. +var _ BackendVersion = BitcoindVersion(0) + const ( // bitcoind19Str is the string representation of bitcoind v0.19.0. bitcoind19Str = "0.19.0" @@ -74,7 +116,7 @@ const ( // parseBitcoindVersion parses the bitcoind version from its string // representation. -func parseBitcoindVersion(version string) BackendVersion { +func parseBitcoindVersion(version string) BitcoindVersion { // Trim the version of its prefix and suffix to determine the // appropriate version number. version = strings.TrimPrefix( @@ -127,6 +169,28 @@ func (b BtcdVersion) String() string { } } +// SupportUnifiedSoftForks returns true if the backend supports the unified +// softforks format. +// +// NOTE: always true for btcd as we didn't track it before. +func (b BtcdVersion) SupportUnifiedSoftForks() bool { + return true +} + +// SupportTestMempoolAccept returns true if btcd version is 24.1.0 or above. +func (b BtcdVersion) SupportTestMempoolAccept() bool { + return b > BtcdPre2401 +} + +// SupportGetTxSpendingPrevOut returns true if btcd version is 24.1.0 or above. +func (b BtcdVersion) SupportGetTxSpendingPrevOut() bool { + return b > BtcdPre2401 +} + +// Compile-time checks to ensure that BtcdVersion satisfy the BackendVersion +// interface. +var _ BackendVersion = BtcdVersion(0) + const ( // btcd2401Val is the int representation of btcd v0.24.1. btcd2401Val = 240100 diff --git a/rpcclient/backend_version_test.go b/rpcclient/backend_version_test.go index 91c84ad4f2..3a4baec1db 100644 --- a/rpcclient/backend_version_test.go +++ b/rpcclient/backend_version_test.go @@ -14,7 +14,7 @@ func TestParseBitcoindVersion(t *testing.T) { testCases := []struct { name string rpcVersion string - parsedVersion BackendVersion + parsedVersion BitcoindVersion }{ { name: "parse version 0.19 and below", @@ -104,3 +104,45 @@ func TestParseBtcdVersion(t *testing.T) { }) } } + +// TestVersionSupports checks all the versions of bitcoind and btcd to ensure +// that the RPCs are supported correctly. +func TestVersionSupports(t *testing.T) { + t.Parallel() + + require := require.New(t) + + // For bitcoind, unified softforks format is supported in 19.0 and + // above. + require.False(BitcoindPre19.SupportUnifiedSoftForks()) + require.True(BitcoindPre22.SupportUnifiedSoftForks()) + require.True(BitcoindPre24.SupportUnifiedSoftForks()) + require.True(BitcoindPre25.SupportUnifiedSoftForks()) + require.True(BitcoindPost25.SupportUnifiedSoftForks()) + + // For bitcoind, `testmempoolaccept` is supported in 22.0 and above. + require.False(BitcoindPre19.SupportTestMempoolAccept()) + require.False(BitcoindPre22.SupportTestMempoolAccept()) + require.True(BitcoindPre24.SupportTestMempoolAccept()) + require.True(BitcoindPre25.SupportTestMempoolAccept()) + require.True(BitcoindPost25.SupportTestMempoolAccept()) + + // For bitcoind, `gettxspendingprevout` is supported in 24.0 and above. + require.False(BitcoindPre19.SupportGetTxSpendingPrevOut()) + require.False(BitcoindPre22.SupportGetTxSpendingPrevOut()) + require.False(BitcoindPre24.SupportGetTxSpendingPrevOut()) + require.True(BitcoindPre25.SupportGetTxSpendingPrevOut()) + require.True(BitcoindPost25.SupportGetTxSpendingPrevOut()) + + // For btcd, unified softforks format is supported in all versions. + require.True(BtcdPre2401.SupportUnifiedSoftForks()) + require.True(BtcdPost2401.SupportUnifiedSoftForks()) + + // For btcd, `testmempoolaccept` is supported in 24.1 and above. + require.False(BtcdPre2401.SupportTestMempoolAccept()) + require.True(BtcdPost2401.SupportTestMempoolAccept()) + + // For btcd, `gettxspendingprevout` is supported in 24.1 and above. + require.False(BtcdPre2401.SupportGetTxSpendingPrevOut()) + require.True(BtcdPost2401.SupportGetTxSpendingPrevOut()) +} diff --git a/rpcclient/chain.go b/rpcclient/chain.go index f2ce1ea626..e65c40b3a8 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -441,7 +441,7 @@ func unmarshalGetBlockChainInfoResultSoftForks(chainInfo *btcjson.GetBlockChainI version BackendVersion, res []byte) error { // Versions of bitcoind on or after v0.19.0 use the unified format. - if version > BitcoindPre19 { + if version.SupportUnifiedSoftForks() { var softForks btcjson.UnifiedSoftForks if err := json.Unmarshal(res, &softForks); err != nil { return err diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 404a7b4a04..39cfa3f474 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -134,7 +134,7 @@ type Client struct { // backendVersion is the version of the backend the client is currently // connected to. This should be retrieved through GetVersion. backendVersionMu sync.Mutex - backendVersion *BackendVersion + backendVersion BackendVersion // mtx is a mutex to protect access to connection related fields. mtx sync.Mutex @@ -1577,7 +1577,7 @@ func (c *Client) BackendVersion() (BackendVersion, error) { defer c.backendVersionMu.Unlock() if c.backendVersion != nil { - return *c.backendVersion, nil + return c.backendVersion, nil } // We'll start by calling GetInfo. This method doesn't exist for @@ -1589,20 +1589,20 @@ func (c *Client) BackendVersion() (BackendVersion, error) { // Parse the btcd version and cache it. case nil: log.Debugf("Detected btcd version: %v", info.Version) - version := Btcd - c.backendVersion = &version - return *c.backendVersion, nil + version := parseBtcdVersion(info.Version) + c.backendVersion = version + return c.backendVersion, nil // Inspect the RPC error to ensure the method was not found, otherwise // we actually ran into an error. case *btcjson.RPCError: if err.Code != btcjson.ErrRPCMethodNotFound.Code { - return 0, fmt.Errorf("unable to detect btcd version: "+ + return nil, fmt.Errorf("unable to detect btcd version: "+ "%v", err) } default: - return 0, fmt.Errorf("unable to detect btcd version: %v", err) + return nil, fmt.Errorf("unable to detect btcd version: %v", err) } // Since the GetInfo method was not found, we assume the client is @@ -1610,7 +1610,8 @@ func (c *Client) BackendVersion() (BackendVersion, error) { // GetNetworkInfo. networkInfo, err := c.GetNetworkInfo() if err != nil { - return 0, fmt.Errorf("unable to detect bitcoind version: %v", err) + return nil, fmt.Errorf("unable to detect bitcoind version: %v", + err) } // Parse the bitcoind version and cache it. @@ -1618,7 +1619,7 @@ func (c *Client) BackendVersion() (BackendVersion, error) { version := parseBitcoindVersion(networkInfo.SubVersion) c.backendVersion = &version - return *c.backendVersion, nil + return c.backendVersion, nil } func (c *Client) sendAsync() FutureGetBulkResult { diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 4737aee5b9..3197808f36 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -360,7 +360,9 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut var cmd *btcjson.SendRawTransactionCmd // Starting from bitcoind v0.19.0, the MaxFeeRate field should be used. - if version > BitcoindPre19 { + // + // When unified softforks format is supported, it's 0.19 and above. + if version.SupportUnifiedSoftForks() { // Using a 0 MaxFeeRate is interpreted as a maximum fee rate not // being enforced by bitcoind. var maxFeeRate int32 @@ -943,7 +945,7 @@ func (c *Client) TestMempoolAcceptAsync(txns []*wire.MsgTx, // // We decide to not support this call for versions below 22.0.0. as the // request/response formats are very different. - if version < BitcoindPre22 { + if !version.SupportTestMempoolAccept() { err := fmt.Errorf("%w: %v", ErrBitcoindVersion, version) return newFutureError(err) } @@ -1057,7 +1059,7 @@ func (c *Client) GetTxSpendingPrevOutAsync( log.Debugf("GetTxSpendingPrevOutAsync: backend version %s", version) // Exit early if the version is below 24.0.0. - if version < BitcoindPre24 { + if !version.SupportGetTxSpendingPrevOut() { err := fmt.Errorf("%w: %v", ErrBitcoindVersion, version) return newFutureError(err) } From 34721f02c16d71d493fa7b6055f45772ee0b60c8 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 28 Feb 2024 03:38:48 +0800 Subject: [PATCH 0963/1056] rpcclient: replace `ErrBitcoindVersion` with `ErrBackendVersion` --- rpcclient/errors.go | 7 ++++--- rpcclient/rawtransactions.go | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/rpcclient/errors.go b/rpcclient/errors.go index 78f34bef2e..09e1cb3c22 100644 --- a/rpcclient/errors.go +++ b/rpcclient/errors.go @@ -6,9 +6,10 @@ import ( ) var ( - // ErrBitcoindVersion is returned when running against a bitcoind that - // is older than the minimum version supported by the rpcclient. - ErrBitcoindVersion = errors.New("bitcoind version too low") + // ErrBackendVersion is returned when running against a bitcoind or + // btcd that is older than the minimum version supported by the + // rpcclient. + ErrBackendVersion = errors.New("backend version too low") // ErrInvalidParam is returned when the caller provides an invalid // parameter to an RPC method. diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 3197808f36..9c95041fd4 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -946,7 +946,7 @@ func (c *Client) TestMempoolAcceptAsync(txns []*wire.MsgTx, // We decide to not support this call for versions below 22.0.0. as the // request/response formats are very different. if !version.SupportTestMempoolAccept() { - err := fmt.Errorf("%w: %v", ErrBitcoindVersion, version) + err := fmt.Errorf("%w: %v", ErrBackendVersion, version) return newFutureError(err) } @@ -1060,7 +1060,7 @@ func (c *Client) GetTxSpendingPrevOutAsync( // Exit early if the version is below 24.0.0. if !version.SupportGetTxSpendingPrevOut() { - err := fmt.Errorf("%w: %v", ErrBitcoindVersion, version) + err := fmt.Errorf("%w: %v", ErrBackendVersion, version) return newFutureError(err) } From 0d4ed16ed7bcae516480d24f326d8dd3b8e8975c Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 28 Feb 2024 16:40:11 +0800 Subject: [PATCH 0964/1056] btcd: increase version number to `0.24.1` --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index d7835910f8..999dfd95b2 100644 --- a/version.go +++ b/version.go @@ -18,7 +18,7 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 24 - appPatch uint = 0 + appPatch uint = 1 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. From f9da3387f1766a5c8e30662710b48915f3549bda Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 5 Mar 2024 16:23:24 +0900 Subject: [PATCH 0965/1056] addrmgr: fix intermittent addrmanager_internal_test bug Sometimes the tests in the addrmanager_internal_test will fail with: "addrmanager_internal_test.go: expected to find 5 addresses, found 4" This is because the generated address with randAddr() may not always generate an address that's routable. If the address is not routable, that address will not be added to the manager when calling AddAddress(). This bug is fixed by creating a new function routableRandAddr() that always creates a routable random address. --- addrmgr/addrmanager_internal_test.go | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/addrmgr/addrmanager_internal_test.go b/addrmgr/addrmanager_internal_test.go index 1d13f78e6e..b58ff4b469 100644 --- a/addrmgr/addrmanager_internal_test.go +++ b/addrmgr/addrmanager_internal_test.go @@ -12,7 +12,7 @@ import ( ) // randAddr generates a *wire.NetAddressV2 backed by a random IPv4/IPv6 -// address. +// address. Some of the returned addresses may not be routable. func randAddr(t *testing.T) *wire.NetAddressV2 { t.Helper() @@ -40,6 +40,23 @@ func randAddr(t *testing.T) *wire.NetAddressV2 { ) } +// routableRandAddr generates a *wire.NetAddressV2 backed by a random IPv4/IPv6 +// address that is always routable. +func routableRandAddr(t *testing.T) *wire.NetAddressV2 { + t.Helper() + + var addr *wire.NetAddressV2 + + // If the address is not routable, try again. + routable := false + for !routable { + addr = randAddr(t) + routable = IsRoutable(addr) + } + + return addr +} + // assertAddr ensures that the two addresses match. The timestamp is not // checked as it does not affect uniquely identifying a specific address. func assertAddr(t *testing.T, got, expected *wire.NetAddressV2) { @@ -104,9 +121,9 @@ func TestAddrManagerSerialization(t *testing.T) { expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs) for i := 0; i < numAddrs; i++ { - addr := randAddr(t) + addr := routableRandAddr(t) expectedAddrs[NetAddressKey(addr)] = addr - addrMgr.AddAddress(addr, randAddr(t)) + addrMgr.AddAddress(addr, routableRandAddr(t)) } // Now that the addresses have been added, we should be able to retrieve @@ -149,9 +166,9 @@ func TestAddrManagerV1ToV2(t *testing.T) { expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs) for i := 0; i < numAddrs; i++ { - addr := randAddr(t) + addr := routableRandAddr(t) expectedAddrs[NetAddressKey(addr)] = addr - addrMgr.AddAddress(addr, randAddr(t)) + addrMgr.AddAddress(addr, routableRandAddr(t)) } // Then, we'll persist these addresses to disk and restart the address From f2caa8fadcb21ab7656975f750f51c4222d64e41 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 15 Feb 2024 18:13:52 +0900 Subject: [PATCH 0966/1056] blockchain: don't rely on BlockHeightByHash for prune height calculations Since BlockHeightByHash only returns the heights for blocks that are in the main chain, when a block that is stale gets pruned, this will cause an error in the block height lookup and cause an error in block processing. Look up the node directly from the index and if the node isn't found, just skip that node. For utxoCache.lastFlushHash, if that isn't found, just force a flush. --- blockchain/utxocache.go | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index 07dc698a91..3261f057e5 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -617,6 +617,7 @@ func (b *BlockChain) InitConsistentState(tip *blockNode, interrupt <-chan struct // Set the last flush hash as it's the default value of 0s. s.lastFlushHash = tip.hash + s.lastFlushTime = time.Now() return err } @@ -725,22 +726,35 @@ func (b *BlockChain) InitConsistentState(tip *blockNode, interrupt <-chan struct // Example: if the last flush hash was at height 100 and one of the deleted blocks was at // height 98, this function will return true. func (b *BlockChain) flushNeededAfterPrune(deletedBlockHashes []chainhash.Hash) (bool, error) { - lastFlushHeight, err := b.BlockHeightByHash(&b.utxoCache.lastFlushHash) - if err != nil { - return false, err + node := b.index.LookupNode(&b.utxoCache.lastFlushHash) + if node == nil { + // If we couldn't find the node where we last flushed at, have the utxo cache + // flush to be safe and that will set the last flush hash again. + // + // This realistically should never happen as nodes are never deleted from + // the block index. This happening likely means that there's a hardware + // error which is something we can't recover from. The best that we can + // do here is to just force a flush and hope that the newly set + // lastFlushHash doesn't error. + return true, nil } + lastFlushHeight := node.Height() + // Loop through all the block hashes and find out what the highest block height // among the deleted hashes is. highestDeletedHeight := int32(-1) for _, deletedBlockHash := range deletedBlockHashes { - height, err := b.BlockHeightByHash(&deletedBlockHash) - if err != nil { - return false, err + node := b.index.LookupNode(&deletedBlockHash) + if node == nil { + // If we couldn't find this node, just skip it and try the next + // deleted hash. This might be a corruption in the database + // but there's nothing we can do here to address it except for + // moving onto the next block. + continue } - - if height > highestDeletedHeight { - highestDeletedHeight = height + if node.height > highestDeletedHeight { + highestDeletedHeight = node.height } } From a254998bc5e348a227cdb454ffca0e9e3857c4a1 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 20 Feb 2024 17:08:49 +0900 Subject: [PATCH 0967/1056] blockchain: change reorg utxo cache behavior The assumption in the previous code was incorrect in that we were assuming that the chainLock is held throughout the entire chain reorg. This is not the case since the chainLock is let go of during the callback to the subscribers. Because of this, we need to ensure that the utxo set is consistent on each block disconnect. To achieve this, additional flushes are added during block disconnects. Also the utxocache is no longer avoided during block connects and when we're checking for the validity of the block connects and disconnects as we can just use the cache instead of trying to avoid it. --- blockchain/chain.go | 69 +++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 60420022ac..19de74ab83 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -796,6 +796,15 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view return err } + // Flush the cache on every disconnect. Since the code for + // reorganization modifies the database directly, the cache + // will be left in an inconsistent state if we don't flush it + // prior to the dbPutUtxoView that happends below. + err = b.utxoCache.flush(dbTx, FlushRequired, state) + if err != nil { + return err + } + // Update the utxo set using the state of the utxo view. This // entails restoring all of the utxos spent and removing the new // ones created by the block. @@ -880,6 +889,9 @@ func countSpentOutputs(block *btcutil.Block) int { // // This function may modify node statuses in the block index without flushing. // +// This function never leaves the utxo set in an inconsistent state for block +// disconnects. +// // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error { // Nothing to do if no reorganize nodes were provided. @@ -887,15 +899,6 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error return nil } - // The rest of the reorg depends on all STXOs already being in the database - // so we flush before reorg. - err := b.db.Update(func(dbTx database.Tx) error { - return b.utxoCache.flush(dbTx, FlushRequired, b.BestSnapshot()) - }) - if err != nil { - return err - } - // Ensure the provided nodes match the current best chain. tip := b.bestChain.Tip() if detachNodes.Len() != 0 { @@ -957,7 +960,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the utxos referenced by the block that aren't // already in the view. - err = view.fetchInputUtxos(b.db, nil, block) + err = view.fetchInputUtxos(nil, b.utxoCache, block) if err != nil { return err } @@ -1024,7 +1027,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // checkConnectBlock gets skipped, we still need to update the UTXO // view. if b.index.NodeStatus(n).KnownValid() { - err = view.fetchInputUtxos(b.db, nil, block) + err = view.fetchInputUtxos(nil, b.utxoCache, block) if err != nil { return err } @@ -1061,11 +1064,21 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error newBest = n } + // Flush the utxo cache for the block disconnect below. The disconnect + // code assumes that it's directly modifying the database so the cache + // will be left in an inconsistent state. It needs to be flushed beforehand + // in order for that to not happen. + err := b.db.Update(func(dbTx database.Tx) error { + return b.utxoCache.flush(dbTx, FlushRequired, b.BestSnapshot()) + }) + if err != nil { + return err + } + // Reset the view for the actual connection code below. This is // required because the view was previously modified when checking if // the reorg would be successful and the connection code requires the - // view to be valid from the viewpoint of each block being connected or - // disconnected. + // view to be valid from the viewpoint of each block being disconnected. view = NewUtxoViewpoint() view.SetBestHash(&b.bestChain.Tip().hash) @@ -1076,7 +1089,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the utxos referenced by the block that aren't // already in the view. - err := view.fetchInputUtxos(b.db, nil, block) + err := view.fetchInputUtxos(nil, b.utxoCache, block) if err != nil { return err } @@ -1089,51 +1102,39 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error return err } - // Update the database and chain state. + // Update the database and chain state. The cache will be flushed + // here before the utxoview modifications happen to the database. err = b.disconnectBlock(n, block, view) if err != nil { return err } } - // Connect the new best chain blocks. + // Connect the new best chain blocks using the utxocache directly. It's more + // efficient and since we already checked that the blocks are correct and that + // the transactions connect properly, it's ok to access the cache. If we suddenly + // crash here, we are able to recover as well. for i, e := 0, attachNodes.Front(); e != nil; i, e = i+1, e.Next() { n := e.Value.(*blockNode) block := attachBlocks[i] - // Load all of the utxos referenced by the block that aren't - // already in the view. - err := view.fetchInputUtxos(b.db, nil, block) - if err != nil { - return err - } - // Update the view to mark all utxos referenced by the block // as spent and add all transactions being created by this block // to it. Also, provide an stxo slice so the spent txout // details are generated. stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) - err = view.connectTransactions(block, &stxos) + err := b.utxoCache.connectTransactions(block, &stxos) if err != nil { return err } // Update the database and chain state. - err = b.connectBlock(n, block, view, stxos) + err = b.connectBlock(n, block, nil, stxos) if err != nil { return err } } - // We call the flush at the end to update the last flush hash to the new - // best tip. - err = b.db.Update(func(dbTx database.Tx) error { - return b.utxoCache.flush(dbTx, FlushRequired, b.BestSnapshot()) - }) - if err != nil { - return err - } - // Log the point where the chain forked and old and new best chain // heads. if forkNode != nil { From 78b158dc566ef7773c823ac5dd8d363cd86eb19a Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 6 Mar 2024 02:42:33 +0900 Subject: [PATCH 0968/1056] blockchain: get rid of database as an argument in fetchInputUtxos Allowing the caller to fetch from either the database or the cache resulted in inconsistencies if the cache were ever to be dirty. Removing this option eliminates this problem. --- blockchain/chain.go | 6 +++--- blockchain/utxoviewpoint.go | 14 +++++--------- blockchain/validate.go | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 19de74ab83..fd07575a1d 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -960,7 +960,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the utxos referenced by the block that aren't // already in the view. - err = view.fetchInputUtxos(nil, b.utxoCache, block) + err = view.fetchInputUtxos(b.utxoCache, block) if err != nil { return err } @@ -1027,7 +1027,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // checkConnectBlock gets skipped, we still need to update the UTXO // view. if b.index.NodeStatus(n).KnownValid() { - err = view.fetchInputUtxos(nil, b.utxoCache, block) + err = view.fetchInputUtxos(b.utxoCache, block) if err != nil { return err } @@ -1089,7 +1089,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // Load all of the utxos referenced by the block that aren't // already in the view. - err := view.fetchInputUtxos(nil, b.utxoCache, block) + err := view.fetchInputUtxos(b.utxoCache, block) if err != nil { return err } diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index fdd165c095..1e687431ae 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -666,15 +666,11 @@ func (view *UtxoViewpoint) findInputsToFetch(block *btcutil.Block) []wire.OutPoi // fetchInputUtxos loads the unspent transaction outputs for the inputs // referenced by the transactions in the given block into the view from the -// database or the cache as needed. In particular, referenced entries that -// are earlier in the block are added to the view and entries that are already -// in the view are not modified. -func (view *UtxoViewpoint) fetchInputUtxos(db database.DB, cache *utxoCache, block *btcutil.Block) error { - if cache != nil { - return view.fetchUtxosFromCache(cache, view.findInputsToFetch(block)) - } - // Request the input utxos from the cache. - return view.fetchUtxosMain(db, view.findInputsToFetch(block)) +// cache as needed. In particular, referenced entries that are earlier in +// the block are added to the view and entries that are already in the view +// are not modified. +func (view *UtxoViewpoint) fetchInputUtxos(cache *utxoCache, block *btcutil.Block) error { + return view.fetchUtxosFromCache(cache, view.findInputsToFetch(block)) } // NewUtxoViewpoint returns a new empty unspent transaction output view. diff --git a/blockchain/validate.go b/blockchain/validate.go index 83929810ee..641967fbf2 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -1084,7 +1084,7 @@ func (b *BlockChain) checkConnectBlock(node *blockNode, block *btcutil.Block, vi // // These utxo entries are needed for verification of things such as // transaction inputs, counting pay-to-script-hashes, and scripts. - err := view.fetchInputUtxos(nil, b.utxoCache, block) + err := view.fetchInputUtxos(b.utxoCache, block) if err != nil { return err } From 99846b08055b018eb83a489c679621bcedac4a56 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 6 Mar 2024 02:44:51 +0900 Subject: [PATCH 0969/1056] blockchain: remove unused fetchUtxosMain() --- blockchain/utxoviewpoint.go | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 1e687431ae..702f99507c 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -519,41 +519,6 @@ func (view *UtxoViewpoint) commit() { } } -// fetchUtxosMain fetches unspent transaction output data about the provided -// set of outpoints from the point of view of the end of the main chain at the -// time of the call. -// -// Upon completion of this function, the view will contain an entry for each -// requested outpoint. Spent outputs, or those which otherwise don't exist, -// will result in a nil entry in the view. -func (view *UtxoViewpoint) fetchUtxosMain(db database.DB, outpoints []wire.OutPoint) error { - // Nothing to do if there are no requested outputs. - if len(outpoints) == 0 { - return nil - } - - // Load the requested set of unspent transaction outputs from the point - // of view of the end of the main chain. - // - // NOTE: Missing entries are not considered an error here and instead - // will result in nil entries in the view. This is intentionally done - // so other code can use the presence of an entry in the store as a way - // to unnecessarily avoid attempting to reload it from the database. - return db.View(func(dbTx database.Tx) error { - utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) - for i := range outpoints { - entry, err := dbFetchUtxoEntry(dbTx, utxoBucket, outpoints[i]) - if err != nil { - return err - } - - view.entries[outpoints[i]] = entry - } - - return nil - }) -} - // fetchUtxosFromCache fetches unspent transaction output data about the provided // set of outpoints from the point of view of the end of the main chain at the // time of the call. It attempts to fetch them from the cache and whatever entries From 8d1aa01c69aba6d5c0d2ce09711f2c1c1aa0cadd Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 7 Mar 2024 15:24:00 +0900 Subject: [PATCH 0970/1056] blockchain: add another mapslice duplicate entry case Duplicate entries are currently possible in the following scenario: 1: Add entries to the mapslice. 2: 1st map is full. Move onto the 2nd map. 3: Delete any entry in the first map. 4: Attempt to add an entry in the 2nd map. When attempting (4), the entry should just be overwritten but a duplicate gets added. --- blockchain/utxocache_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index 45116655e3..a66d6dc578 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -69,6 +69,26 @@ func TestMapSlice(t *testing.T) { t.Fatalf("expected len of %d, got %d", len(m), ms.length()) } + // Delete the first element in the first map. + ms.delete(test.keys[0]) + delete(m, test.keys[0]) + + // Try to insert the last element in the mapslice again. + ms.put(test.keys[len(test.keys)-1], &UtxoEntry{}, 0) + m[test.keys[len(test.keys)-1]] = &UtxoEntry{} + + // Check that the duplicate didn't make it in. + if len(m) != ms.length() { + t.Fatalf("expected len of %d, got %d", len(m), ms.length()) + } + + ms.put(test.keys[0], &UtxoEntry{}, 0) + m[test.keys[0]] = &UtxoEntry{} + + if len(m) != ms.length() { + t.Fatalf("expected len of %d, got %d", len(m), ms.length()) + } + for _, key := range test.keys { expected, found := m[key] if !found { From 059a668e888fd1d9a06d1c53d91117997ca51c4d Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 7 Mar 2024 15:27:44 +0900 Subject: [PATCH 0971/1056] blockchain: check all the maps first before adding an entry When attempting to insert an entry to the mapslice, we check all the underlying maps to ensure that the entry doesn't exist. --- blockchain/utxocache.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index 07dc698a91..ebc9dc73de 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -99,7 +99,8 @@ func (ms *mapSlice) put(op wire.OutPoint, entry *UtxoEntry, totalEntryMemory uin ms.mtx.Lock() defer ms.mtx.Unlock() - for i, maxNum := range ms.maxEntries { + // Look for the key in the maps. + for i := range ms.maxEntries { m := ms.maps[i] _, found := m[op] if found { @@ -107,6 +108,10 @@ func (ms *mapSlice) put(op wire.OutPoint, entry *UtxoEntry, totalEntryMemory uin m[op] = entry return // Return as we were successful in adding the entry. } + } + + for i, maxNum := range ms.maxEntries { + m := ms.maps[i] if len(m) >= maxNum { // Don't try to insert if the map already at max since // that'll force the map to allocate double the memory it's From 078815bcbccf34a43e6f92ca1644459cbac7e1b8 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Thu, 7 Mar 2024 15:43:48 +0900 Subject: [PATCH 0972/1056] blockchain: remove utxoview from the argument in connectBlock Since no code is now depending on accepting new blocks without the cache, we get rid of the option to do so. --- blockchain/chain.go | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index fd07575a1d..dc47fbd71f 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -569,7 +569,7 @@ func (b *BlockChain) getReorganizeNodes(node *blockNode) (*list.List, *list.List // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, - view *UtxoViewpoint, stxos []SpentTxOut) error { + stxos []SpentTxOut) error { // Make sure it's extending the end of the best chain. prevHash := &block.MsgBlock().Header.PrevBlock @@ -611,18 +611,6 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, curTotalTxns+numTxns, CalcPastMedianTime(node), ) - // If a utxoviewpoint was passed in, we'll be writing that viewpoint - // directly to the database on disk. In order for the database to be - // consistent, we must flush the cache before writing the viewpoint. - if view != nil { - err = b.db.Update(func(dbTx database.Tx) error { - return b.utxoCache.flush(dbTx, FlushRequired, state) - }) - if err != nil { - return err - } - } - // Atomically insert info into the database. err = b.db.Update(func(dbTx database.Tx) error { // If the pruneTarget isn't 0, we should attempt to delete older blocks @@ -676,16 +664,6 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, return err } - // Update the utxo set using the state of the utxo view. This - // entails removing all of the utxos spent and adding the new - // ones created by the block. - // - // A nil viewpoint is a no-op. - err = dbPutUtxoView(dbTx, view) - if err != nil { - return err - } - // Update the transaction spend journal by adding a record for // the block that contains all txos spent by it. err = dbPutSpendJournalEntry(dbTx, block.Hash(), stxos) @@ -709,12 +687,6 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, return err } - // Prune fully spent entries and mark all entries in the view unmodified - // now that the modifications have been committed to the database. - if view != nil { - view.commit() - } - // This node is now the end of the best chain. b.bestChain.SetTip(node) @@ -1118,18 +1090,18 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error n := e.Value.(*blockNode) block := attachBlocks[i] - // Update the view to mark all utxos referenced by the block + // Update the cache to mark all utxos referenced by the block // as spent and add all transactions being created by this block // to it. Also, provide an stxo slice so the spent txout // details are generated. stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) - err := b.utxoCache.connectTransactions(block, &stxos) + err = b.utxoCache.connectTransactions(block, &stxos) if err != nil { return err } // Update the database and chain state. - err = b.connectBlock(n, block, nil, stxos) + err = b.connectBlock(n, block, stxos) if err != nil { return err } @@ -1226,7 +1198,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla } // Connect the block to the main chain. - err = b.connectBlock(node, block, nil, stxos) + err = b.connectBlock(node, block, stxos) if err != nil { // If we got hit with a rule error, then we'll mark // that status of the block as invalid and flush the From 9d2184eb2d29846b087857168c248610cf6d2c12 Mon Sep 17 00:00:00 2001 From: SulaimanAminuBarkindo Date: Thu, 7 Mar 2024 08:45:10 +0100 Subject: [PATCH 0973/1056] Add check for maximum signature length in ecdsa.ParseDERSignature * Updated the `ecdsa.ParseDERSignature` to include the MaxSigLen constant, which defines the maximum length of a DER encoded signature. * The MaxSigLen constant is set to 72 bytes, as per the explanation in the comment. * A new test case has been added to test the functionality with a long signature. * The test case checks if signatures longer than the specified maximum length are properly handled. * The test ensures that signatures exceeding the maximum length are correctly identified as invalid. --- btcec/ecdsa/signature.go | 26 +++++++++++++++++++++----- btcec/ecdsa/signature_test.go | 15 +++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/btcec/ecdsa/signature.go b/btcec/ecdsa/signature.go index 092e4ceb1c..44b84a78c9 100644 --- a/btcec/ecdsa/signature.go +++ b/btcec/ecdsa/signature.go @@ -37,10 +37,20 @@ var ( oneInitializer = []byte{0x01} ) -// MinSigLen is the minimum length of a DER encoded signature and is when both R -// and S are 1 byte each. -// 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + -const MinSigLen = 8 +const ( + // MinSigLen is the minimum length of a DER encoded signature and is when both R + // and S are 1 byte each. + // 0x30 + <1-byte> + 0x02 + 0x01 + + 0x2 + 0x01 + + MinSigLen = 8 + + // MaxSigLen is the maximum length of a DER encoded signature and is + // when both R and S are 33 bytes each. It is 33 bytes because a + // 256-bit integer requires 32 bytes and an additional leading null byte + // might be required if the high bit is set in the value. + // + // 0x30 + <1-byte> + 0x02 + 0x21 + <33 bytes> + 0x2 + 0x21 + <33 bytes> + MaxSigLen = 72 +) // canonicalPadding checks whether a big-endian encoded integer could // possibly be misinterpreted as a negative number (even though OpenSSL @@ -68,9 +78,15 @@ func parseSig(sigStr []byte, der bool) (*Signature, error) { // 0x30 <0x02> 0x2 // . - if len(sigStr) < MinSigLen { + // The signature must adhere to the minimum and maximum allowed length. + totalSigLen := len(sigStr) + if totalSigLen < MinSigLen { return nil, errors.New("malformed signature: too short") } + if der && totalSigLen > MaxSigLen { + return nil, errors.New("malformed signature: too long") + } + // 0x30 index := 0 if sigStr[index] != 0x30 { diff --git a/btcec/ecdsa/signature_test.go b/btcec/ecdsa/signature_test.go index d2eebdc788..f36e15db89 100644 --- a/btcec/ecdsa/signature_test.go +++ b/btcec/ecdsa/signature_test.go @@ -333,6 +333,21 @@ var signatureTests = []signatureTest{ der: false, isValid: false, }, + { + name: "Long signature.", + sig: []byte{0x30, 0x44, 0x02, 0x20, 0x4e, 0x45, 0xe1, 0x69, + 0x32, 0xb8, 0xaf, 0x51, 0x49, 0x61, 0xa1, 0xd3, 0xa1, + 0xa2, 0x5f, 0xdf, 0x3f, 0x4f, 0x77, 0x32, 0xe9, 0xd6, + 0x24, 0xc6, 0xc6, 0x15, 0x48, 0xab, 0x5f, 0xb8, 0xcd, + 0x41, 0x02, 0x20, 0x18, 0x15, 0x22, 0xec, 0x8e, 0xca, + 0x07, 0xde, 0x48, 0x60, 0xa4, 0xac, 0xdd, 0x12, 0x90, + 0x9d, 0x83, 0x1c, 0xc5, 0x6c, 0xbb, 0xac, 0x46, 0x22, + 0x08, 0x22, 0x21, 0xa8, 0x76, 0x8d, 0x1d, 0x09, 0x91, + 0x17, 0x90, 0xda, 0x42, 0xca, 0xaf, 0x19, 0x7d, 0xb4, + }, + der: true, + isValid: false, + }, } func TestSignatures(t *testing.T) { From b66f5b837916252a9da959955ca340451e4c1855 Mon Sep 17 00:00:00 2001 From: theedtron Date: Sat, 9 Mar 2024 04:41:41 +0300 Subject: [PATCH 0974/1056] multi: fix ioutil deprecated function update i/o functions to use os / io package functions instead --- addrmgr/addrmanager_internal_test.go | 5 ++--- btcutil/txsort/txsort_test.go | 4 ++-- cmd/btcctl/httpclient.go | 7 ++++--- cmd/gencerts/gencerts.go | 5 ++--- config_test.go | 9 ++++----- database/example_test.go | 3 +-- docs/json_rpc_api.md | 6 +++--- rpcclient/examples/btcdwebsockets/main.go | 4 ++-- rpcclient/examples/btcwalletwebsockets/main.go | 4 ++-- rpcserver.go | 4 ++-- txscript/bench_test.go | 4 ++-- txscript/reference_test.go | 12 ++++++------ 12 files changed, 32 insertions(+), 35 deletions(-) diff --git a/addrmgr/addrmanager_internal_test.go b/addrmgr/addrmanager_internal_test.go index b58ff4b469..ff19eae1d1 100644 --- a/addrmgr/addrmanager_internal_test.go +++ b/addrmgr/addrmanager_internal_test.go @@ -1,7 +1,6 @@ package addrmgr import ( - "io/ioutil" "math/rand" "net" "os" @@ -108,7 +107,7 @@ func TestAddrManagerSerialization(t *testing.T) { // We'll start by creating our address manager backed by a temporary // directory. - tempDir, err := ioutil.TempDir("", "addrmgr") + tempDir, err := os.MkdirTemp("", "addrmgr") if err != nil { t.Fatalf("unable to create temp dir: %v", err) } @@ -148,7 +147,7 @@ func TestAddrManagerV1ToV2(t *testing.T) { // We'll start by creating our address manager backed by a temporary // directory. - tempDir, err := ioutil.TempDir("", "addrmgr") + tempDir, err := os.MkdirTemp("", "addrmgr") if err != nil { t.Fatalf("unable to create temp dir: %v", err) } diff --git a/btcutil/txsort/txsort_test.go b/btcutil/txsort/txsort_test.go index dd2149294e..16a3e61c83 100644 --- a/btcutil/txsort/txsort_test.go +++ b/btcutil/txsort/txsort_test.go @@ -7,7 +7,7 @@ package txsort_test import ( "bytes" "encoding/hex" - "io/ioutil" + "os" "path/filepath" "testing" @@ -64,7 +64,7 @@ func TestSort(t *testing.T) { for _, test := range tests { // Load and deserialize the test transaction. filePath := filepath.Join("testdata", test.hexFile) - txHexBytes, err := ioutil.ReadFile(filePath) + txHexBytes, err := os.ReadFile(filePath) if err != nil { t.Errorf("ReadFile (%s): failed to read test file: %v", test.name, err) diff --git a/cmd/btcctl/httpclient.go b/cmd/btcctl/httpclient.go index 2a0f6dffd4..c7b4b7e3a1 100644 --- a/cmd/btcctl/httpclient.go +++ b/cmd/btcctl/httpclient.go @@ -6,9 +6,10 @@ import ( "crypto/x509" "encoding/json" "fmt" - "io/ioutil" + "io" "net" "net/http" + "os" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/go-socks/socks" @@ -37,7 +38,7 @@ func newHTTPClient(cfg *config) (*http.Client, error) { // Configure TLS if needed. var tlsConfig *tls.Config if !cfg.NoTLS && cfg.RPCCert != "" { - pem, err := ioutil.ReadFile(cfg.RPCCert) + pem, err := os.ReadFile(cfg.RPCCert) if err != nil { return nil, err } @@ -95,7 +96,7 @@ func sendPostRequest(marshalledJSON []byte, cfg *config) ([]byte, error) { } // Read the raw bytes and close the response. - respBytes, err := ioutil.ReadAll(httpResponse.Body) + respBytes, err := io.ReadAll(httpResponse.Body) httpResponse.Body.Close() if err != nil { err = fmt.Errorf("error reading json reply: %v", err) diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index 27c9ae385c..328d5ea714 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -6,7 +6,6 @@ package main import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -65,11 +64,11 @@ func main() { } // Write cert and key files. - if err = ioutil.WriteFile(certFile, cert, 0666); err != nil { + if err = os.WriteFile(certFile, cert, 0666); err != nil { fmt.Fprintf(os.Stderr, "cannot write cert: %v\n", err) os.Exit(1) } - if err = ioutil.WriteFile(keyFile, key, 0600); err != nil { + if err = os.WriteFile(keyFile, key, 0600); err != nil { os.Remove(certFile) fmt.Fprintf(os.Stderr, "cannot write key: %v\n", err) os.Exit(1) diff --git a/config_test.go b/config_test.go index e54a9f5f20..42a0cd4b90 100644 --- a/config_test.go +++ b/config_test.go @@ -1,7 +1,6 @@ package main import ( - "io/ioutil" "os" "path/filepath" "regexp" @@ -23,14 +22,14 @@ func TestCreateDefaultConfigFile(t *testing.T) { sampleConfigFile := filepath.Join(filepath.Dir(path), "sample-btcd.conf") // Setup a temporary directory - tmpDir, err := ioutil.TempDir("", "btcd") + tmpDir, err := os.MkdirTemp("", "btcd") if err != nil { t.Fatalf("Failed creating a temporary directory: %v", err) } testpath := filepath.Join(tmpDir, "test.conf") // copy config file to location of btcd binary - data, err := ioutil.ReadFile(sampleConfigFile) + data, err := os.ReadFile(sampleConfigFile) if err != nil { t.Fatalf("Failed reading sample config file: %v", err) } @@ -39,7 +38,7 @@ func TestCreateDefaultConfigFile(t *testing.T) { t.Fatalf("Failed obtaining app path: %v", err) } tmpConfigFile := filepath.Join(appPath, "sample-btcd.conf") - err = ioutil.WriteFile(tmpConfigFile, data, 0644) + err = os.WriteFile(tmpConfigFile, data, 0644) if err != nil { t.Fatalf("Failed copying sample config file: %v", err) } @@ -57,7 +56,7 @@ func TestCreateDefaultConfigFile(t *testing.T) { t.Fatalf("Failed to create a default config file: %v", err) } - content, err := ioutil.ReadFile(testpath) + content, err := os.ReadFile(testpath) if err != nil { t.Fatalf("Failed to read generated default config file: %v", err) } diff --git a/database/example_test.go b/database/example_test.go index b64baf2c8e..1110d0dbc3 100644 --- a/database/example_test.go +++ b/database/example_test.go @@ -7,7 +7,6 @@ package database_test import ( "bytes" "fmt" - "io/ioutil" "os" "path/filepath" @@ -123,7 +122,7 @@ func Example_blockStorageAndRetrieval() { // Typically you wouldn't want to remove the database right away like // this, nor put it in the temp directory, but it's done here to ensure // the example cleans up after itself. - dbPath, err := ioutil.TempDir("", "exampleblkstorage") + dbPath, err := os.MkdirTemp("", "exampleblkstorage") if err != nil { fmt.Println(err) return diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index 2c7d455457..fc32040da7 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -1121,7 +1121,7 @@ func main() { // generated by btcd when it starts the RPC server and doesn't already // have one. btcdHomeDir := btcutil.AppDataDir("btcd", false) - certs, err := ioutil.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) + certs, err := os.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) if err != nil { log.Fatal(err) } @@ -1185,7 +1185,7 @@ func main() { // generated by btcd when it starts the RPC server and doesn't already // have one. btcdHomeDir := btcutil.AppDataDir("btcd", false) - certs, err := ioutil.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) + certs, err := os.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) if err != nil { log.Fatal(err) } @@ -1288,7 +1288,7 @@ func main() { // generated by btcd when it starts the RPC server and doesn't already // have one. btcdHomeDir := btcutil.AppDataDir("btcd", false) - certs, err := ioutil.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) + certs, err := os.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) if err != nil { log.Fatal(err) } diff --git a/rpcclient/examples/btcdwebsockets/main.go b/rpcclient/examples/btcdwebsockets/main.go index e3f4c13e40..878526b076 100644 --- a/rpcclient/examples/btcdwebsockets/main.go +++ b/rpcclient/examples/btcdwebsockets/main.go @@ -5,7 +5,7 @@ package main import ( - "io/ioutil" + "os" "log" "path/filepath" "time" @@ -33,7 +33,7 @@ func main() { // Connect to local btcd RPC server using websockets. btcdHomeDir := btcutil.AppDataDir("btcd", false) - certs, err := ioutil.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) + certs, err := os.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert")) if err != nil { log.Fatal(err) } diff --git a/rpcclient/examples/btcwalletwebsockets/main.go b/rpcclient/examples/btcwalletwebsockets/main.go index 3cbd9a3667..a63ef3db91 100644 --- a/rpcclient/examples/btcwalletwebsockets/main.go +++ b/rpcclient/examples/btcwalletwebsockets/main.go @@ -5,7 +5,7 @@ package main import ( - "io/ioutil" + "os" "log" "path/filepath" "time" @@ -29,7 +29,7 @@ func main() { // Connect to local btcwallet RPC server using websockets. certHomeDir := btcutil.AppDataDir("btcwallet", false) - certs, err := ioutil.ReadFile(filepath.Join(certHomeDir, "rpc.cert")) + certs, err := os.ReadFile(filepath.Join(certHomeDir, "rpc.cert")) if err != nil { log.Fatal(err) } diff --git a/rpcserver.go b/rpcserver.go index d6f3167f1e..eaa5f05633 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -4650,10 +4650,10 @@ func genCertPair(certFile, keyFile string) error { } // Write cert and key files. - if err = ioutil.WriteFile(certFile, cert, 0666); err != nil { + if err = os.WriteFile(certFile, cert, 0666); err != nil { return err } - if err = ioutil.WriteFile(keyFile, key, 0600); err != nil { + if err = os.WriteFile(keyFile, key, 0600); err != nil { os.Remove(certFile) return err } diff --git a/txscript/bench_test.go b/txscript/bench_test.go index 0d1aa91468..60b0d9e12e 100644 --- a/txscript/bench_test.go +++ b/txscript/bench_test.go @@ -7,7 +7,7 @@ package txscript import ( "bytes" "fmt" - "io/ioutil" + "os" "testing" "github.com/btcsuite/btcd/chaincfg" @@ -25,7 +25,7 @@ var ( func init() { // tx 620f57c92cf05a7f7e7f7d28255d5f7089437bc48e34dcfebf7751d08b7fb8f5 - txHex, err := ioutil.ReadFile("data/many_inputs_tx.hex") + txHex, err := os.ReadFile("data/many_inputs_tx.hex") if err != nil { panic(fmt.Sprintf("unable to read benchmark tx file: %v", err)) } diff --git a/txscript/reference_test.go b/txscript/reference_test.go index 59acdb8da7..16f06c4f70 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -11,7 +11,7 @@ import ( "errors" "fmt" "io/fs" - "io/ioutil" + "os" "path/filepath" "strconv" "strings" @@ -490,7 +490,7 @@ func testScripts(t *testing.T, tests [][]interface{}, useSigCache bool) { // TestScripts ensures all of the tests in script_tests.json execute with the // expected results as defined in the test data. func TestScripts(t *testing.T) { - file, err := ioutil.ReadFile("data/script_tests.json") + file, err := os.ReadFile("data/script_tests.json") if err != nil { t.Fatalf("TestScripts: %v\n", err) } @@ -521,7 +521,7 @@ func testVecF64ToUint32(f float64) uint32 { // TestTxInvalidTests ensures all of the tests in tx_invalid.json fail as // expected. func TestTxInvalidTests(t *testing.T) { - file, err := ioutil.ReadFile("data/tx_invalid.json") + file, err := os.ReadFile("data/tx_invalid.json") if err != nil { t.Fatalf("TestTxInvalidTests: %v\n", err) } @@ -679,7 +679,7 @@ testloop: // TestTxValidTests ensures all of the tests in tx_valid.json pass as expected. func TestTxValidTests(t *testing.T) { - file, err := ioutil.ReadFile("data/tx_valid.json") + file, err := os.ReadFile("data/tx_valid.json") if err != nil { t.Fatalf("TestTxValidTests: %v\n", err) } @@ -836,7 +836,7 @@ testloop: // in sighash.json. // https://github.com/bitcoin/bitcoin/blob/master/src/test/data/sighash.json func TestCalcSignatureHash(t *testing.T) { - file, err := ioutil.ReadFile("data/sighash.json") + file, err := os.ReadFile("data/sighash.json") if err != nil { t.Fatalf("TestCalcSignatureHash: %v\n", err) } @@ -1044,7 +1044,7 @@ func TestTaprootReferenceTests(t *testing.T) { return nil } - testJson, err := ioutil.ReadFile(path) + testJson, err := os.ReadFile(path) if err != nil { return fmt.Errorf("unable to read file: %v", err) } From aee2705f701ae88a2de1035cd7bbec0debce602c Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 8 Mar 2024 17:58:53 -0800 Subject: [PATCH 0975/1056] build: bump version to v0.24.2-beta.rc1 --- version.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.go b/version.go index 999dfd95b2..0fd06fde6c 100644 --- a/version.go +++ b/version.go @@ -18,11 +18,11 @@ const semanticAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr const ( appMajor uint = 0 appMinor uint = 24 - appPatch uint = 1 + appPatch uint = 2 // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - appPreRelease = "beta" + appPreRelease = "beta.rc1" ) // appBuild is defined as a variable so it can be overridden during the build From 36683e0b967f367b5781f0d28e4e242c7d17c9f6 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 15 Mar 2024 04:56:22 +0800 Subject: [PATCH 0976/1056] rpcclient: define specific errors for chain backends This commit adds detailed errors for all possible errors returned from `sendrawtransaction` or `testmempoolaccept`, enabling upstream callers to have refined control over the actions to be taken. --- rpcclient/errors.go | 572 +++++++++++++++++++++++++++++++-------- rpcclient/errors_test.go | 122 +++++++++ 2 files changed, 577 insertions(+), 117 deletions(-) create mode 100644 rpcclient/errors_test.go diff --git a/rpcclient/errors.go b/rpcclient/errors.go index 09e1cb3c22..68c0780dff 100644 --- a/rpcclient/errors.go +++ b/rpcclient/errors.go @@ -2,6 +2,7 @@ package rpcclient import ( "errors" + "fmt" "strings" ) @@ -15,163 +16,500 @@ var ( // parameter to an RPC method. ErrInvalidParam = errors.New("invalid param") - // RejectReasonMap takes the error returned from - // `CheckMempoolAcceptance` in `btcd` and maps it to the reject reason - // that's returned from calling `testmempoolaccept` in `bitcoind`. - // references: - // - https://github.com/bitcoin/bitcoin/blob/master/test/functional/data/invalid_txs.py - // - https://github.com/bitcoin/bitcoin/blob/master/test/functional/mempool_accept.py - // - https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp + // ErrUndefined is used when an error returned is not recognized. We + // should gradually increase our error types to avoid returning this + // error. + ErrUndefined = errors.New("undefined") +) + +// BitcoindRPCErr represents an error returned by bitcoind's RPC server. +type BitcoindRPCErr uint32 + +// This section defines all possible errors or reject reasons returned from +// bitcoind's `sendrawtransaction` or `testmempoolaccept` RPC. +const ( + // ErrMissingInputsOrSpent is returned when calling + // `sendrawtransaction` with missing inputs. + ErrMissingInputsOrSpent BitcoindRPCErr = iota + + // ErrMaxBurnExceeded is returned when calling `sendrawtransaction` + // with exceeding, falling short of, and equaling maxburnamount. + ErrMaxBurnExceeded + + // ErrMaxFeeExceeded can happen when passing a signed tx to + // `testmempoolaccept`, but the tx pays more fees than specified. + ErrMaxFeeExceeded + + // ErrTxAlreadyKnown is used in the `reject-reason` field of + // `testmempoolaccept` when a transaction is already in the blockchain. + ErrTxAlreadyKnown + + // ErrTxAlreadyConfirmed is returned as an error from + // `sendrawtransaction` when a transaction is already in the + // blockchain. + ErrTxAlreadyConfirmed + + // ErrMempoolConflict happens when RBF is not enabled yet the + // transaction conflicts with an unconfirmed tx. . // - // Errors not mapped in `btcd`: - // - deployment error from `validateSegWitDeployment`. - // - the error when total inputs is higher than max allowed value from - // `CheckTransactionInputs`. - // - the error when total outputs is higher than total inputs from - // `CheckTransactionInputs`. - // - errors from `CalcSequenceLock`. + // NOTE: RBF rule 1. + ErrMempoolConflict + + // ErrReplacementAddsUnconfirmed is returned when a transaction adds + // new unconfirmed inputs. // - // NOTE: This is not an exhaustive list of errors, but it covers the - // usage case of LND. + // NOTE: RBF rule 2. + ErrReplacementAddsUnconfirmed + + // ErrInsufficientFee is returned when fee rate used or fees paid + // doesn't meet the requirements. // - //nolint:lll - RejectReasonMap = map[string]string{ - // BIP125 related errors. - // - // When fee rate used or fees paid doesn't meet the - // requirements. - "replacement transaction has an insufficient fee rate": "insufficient fee", - "replacement transaction has an insufficient absolute fee": "insufficient fee", + // NOTE: RBF rule 3 or 4. + ErrInsufficientFee - // When a transaction causes too many transactions being - // replaced. This is set by `MAX_REPLACEMENT_CANDIDATES` in - // `bitcoind` and defaults to 100. - "replacement transaction evicts more transactions than permitted": "too many potential replacements", + // ErrTooManyReplacements is returned when a transaction causes too + // many transactions being replaced. This is set by + // `MAX_REPLACEMENT_CANDIDATES` in `bitcoind` and defaults to 100. + // + // NOTE: RBF rule 5. + ErrTooManyReplacements - // When a transaction adds new unconfirmed inputs. - "replacement transaction spends new unconfirmed input": "replacement-adds-unconfirmed", + // ErrMempoolMinFeeNotMet is returned when the transaction doesn't meet + // the minimum relay fee. + ErrMempoolMinFeeNotMet - // A transaction that spends conflicting tx outputs that are - // rejected. - "replacement transaction spends parent transaction": "bad-txns-spends-conflicting-tx", + // ErrConflictingTx is returned when a transaction that spends + // conflicting tx outputs that are rejected. + ErrConflictingTx - // A transaction that conflicts with an unconfirmed tx. Happens - // when RBF is not enabled. - "output already spent in mempool": "txn-mempool-conflict", + // ErrEmptyOutput is returned when a transaction has no outputs. + ErrEmptyOutput - // A transaction with no outputs. - "transaction has no outputs": "bad-txns-vout-empty", + // ErrEmptyInput is returned when a transaction has no inputs. + ErrEmptyInput - // A transaction with no inputs. - "transaction has no inputs": "bad-txns-vin-empty", + // ErrTxTooSmall is returned when spending a tiny transaction(in + // non-witness bytes) that is disallowed. + // + // NOTE: ErrTxTooLarge must be put after ErrTxTooSmall because it's a + // subset of ErrTxTooSmall. Otherwise, if bitcoind returns + // `tx-size-small`, it will be matched to ErrTxTooLarge. + ErrTxTooSmall - // A tiny transaction(in non-witness bytes) that is disallowed. - // TODO(yy): find/return this error in `btcd`. - // "": "tx-size-small", + // ErrDuplicateInput is returned when a transaction has duplicate + // inputs. + ErrDuplicateInput - // A transaction with duplicate inputs. - "transaction contains duplicate inputs": "bad-txns-inputs-duplicate", + // ErrEmptyPrevOut is returned when a non-coinbase transaction has + // coinbase-like outpoint. + ErrEmptyPrevOut - // A non-coinbase transaction with coinbase-like outpoint. - "transaction input refers to previous output that is null": "bad-txns-prevout-null", + // ErrBelowOutValue is returned when a transaction's output value is + // greater than its input value. + ErrBelowOutValue - // A transaction pays too little fee. - "fees which is under the required amount": "bad-txns-in-belowout", - "has insufficient priority": "bad-txns-in-belowout", - "has been rejected by the rate limiter due to low fees": "bad-txns-in-belowout", + // ErrNegativeOutput is returned when a transaction has negative output + // value. + ErrNegativeOutput - // A transaction with negative output value. - "transaction output has negative value": "bad-txns-vout-negative", + // ErrLargeOutput is returned when a transaction has too large output + // value. + ErrLargeOutput - // A transaction with too large output value. - "transaction output value is higher than max allowed value": "bad-txns-vout-toolarge", + // ErrLargeTotalOutput is returned when a transaction has too large sum + // of output values. + ErrLargeTotalOutput - // A transaction with too large sum of output values. - "total value of all transaction outputs exceeds max allowed value": "bad-txns-txouttotal-toolarge", + // ErrScriptVerifyFlag is returned when there is invalid OP_IF + // construction. + ErrScriptVerifyFlag - // TODO(yy): find/return this error in `btcd`. - // "": "mandatory-script-verify-flag-failed (Invalid OP_IF construction)", + // ErrTooManySigOps is returned when a transaction has too many sigops. + ErrTooManySigOps - // A transaction with too many sigops. - "sigop cost is too hight": "bad-txns-too-many-sigops", + // ErrInvalidOpcode is returned when a transaction has invalid OP + // codes. + ErrInvalidOpcode - // A transaction with invalid OP codes. - // TODO(yy): find/return this error in `btcd`. - // "": "disabled opcode", + // ErrTxAlreadyInMempool is returned when a transaction is in the + // mempool. + ErrTxAlreadyInMempool - // A transaction already in the blockchain. - "database contains entry for spent tx output": "txn-already-known", - "transaction already exists in blockchain": "txn-already-known", + // ErrMissingInputs is returned when a transaction has missing inputs, + // that never existed or only existed once in the past. + ErrMissingInputs - // A transaction in the mempool. - "already have transaction in mempool": "txn-already-in-mempool", + // ErrOversizeTx is returned when a transaction is too large. + ErrOversizeTx - // A transaction with missing inputs, that never existed or - // only existed once in the past. - "either does not exist or has already been spent": "missing-inputs", + // ErrCoinbaseTx is returned when the transaction is coinbase tx. + ErrCoinbaseTx - // A really large transaction. - "serialized transaction is too big": "bad-txns-oversize", + // ErrNonStandardVersion is returned when the transactions are not + // standard - a version currently non-standard. + ErrNonStandardVersion - // A coinbase transaction. - "transaction is an invalid coinbase": "coinbase", + // ErrNonStandardScript is returned when the transactions are not + // standard - non-standard script. + ErrNonStandardScript - // Some nonstandard transactions - a version currently - // non-standard. - "transaction version": "version", + // ErrBareMultiSig is returned when the transactions are not standard - + // bare multisig script (2-of-3). + ErrBareMultiSig - // Some nonstandard transactions - non-standard script. - "non-standard script form": "scriptpubkey", - "has a non-standard input": "scriptpubkey", + // ErrScriptSigNotPushOnly is returned when the transactions are not + // standard - not-pushonly scriptSig. + ErrScriptSigNotPushOnly - // Some nonstandard transactions - bare multisig script - // (2-of-3). - "milti-signature script": "bare-multisig", + // ErrScriptSigSize is returned when the transactions are not standard + // - too large scriptSig (>1650 bytes). + ErrScriptSigSize - // Some nonstandard transactions - not-pushonly scriptSig. - "signature script is not push only": "scriptsig-not-pushonly", + // ErrTxTooLarge is returned when the transactions are not standard - + // too large tx size. + ErrTxTooLarge - // Some nonstandard transactions - too large scriptSig (>1650 - // bytes). - "signature script size is larger than max allowed": "scriptsig-size", + // ErrDust is returned when the transactions are not standard - output + // too small. + ErrDust - // Some nonstandard transactions - too large tx size. - "weight of transaction is larger than max allowed": "tx-size", + // ErrMultiOpReturn is returned when the transactions are not standard + // - muiltiple OP_RETURNs. + ErrMultiOpReturn - // Some nonstandard transactions - output too small. - "payment is dust": "dust", + // ErrNonFinal is returned when spending a timelocked transaction that + // hasn't expired yet. + ErrNonFinal - // Some nonstandard transactions - muiltiple OP_RETURNs. - "more than one transaction output in a nulldata script": "multi-op-return", + // ErrNonBIP68Final is returned when a transaction that is locked by + // BIP68 sequence logic and not expired yet. + ErrNonBIP68Final - // A timelocked transaction. - "transaction is not finalized": "non-final", - "tried to spend coinbase transaction output": "non-final", + // ErrSameNonWitnessData is returned when another tx with the same + // non-witness data is already in the mempool. For instance, these two + // txns share the same `txid` but different `wtxid`. + ErrSameNonWitnessData - // A transaction that is locked by BIP68 sequence logic. - "transaction's sequence locks on inputs not met": "non-BIP68-final", + // ErrNonMandatoryScriptVerifyFlag is returned when passing a raw tx to + // `testmempoolaccept`, which gives the error followed by (Witness + // program hash mismatch). + ErrNonMandatoryScriptVerifyFlag - // Minimally-small transaction(in non-witness bytes) that is - // allowed. - // TODO(yy): find/return this error in `btcd`. - // "": "txn-same-nonwitness-data-in-mempools", - } + // errSentinel is used to indicate the end of the error list. This + // should always be the last error code. + errSentinel ) -// MapBtcdErrToRejectReason takes an error returned from -// `CheckMempoolAcceptance` and maps the error to a bitcoind reject reason. -func MapBtcdErrToRejectReason(err error) string { - // Get the error string and turn it into lower case. - btcErr := strings.ToLower(err.Error()) +// Error implements the error interface. It returns the error message defined +// in `bitcoind`. + +// Some of the dashes used in the original error string is removed, e.g. +// "missing-inputs" is now "missing inputs". This is ok since we will normalize +// the errors before matching. +// +// references: +// - https://github.com/bitcoin/bitcoin/blob/master/test/functional/rpc_rawtransaction.py#L342 +// - https://github.com/bitcoin/bitcoin/blob/master/test/functional/data/invalid_txs.py +// - https://github.com/bitcoin/bitcoin/blob/master/test/functional/mempool_accept.py +// - https://github.com/bitcoin/bitcoin/blob/master/test/functional/mempool_accept_wtxid.py +// - https://github.com/bitcoin/bitcoin/blob/master/test/functional/mempool_dust.py +// - https://github.com/bitcoin/bitcoin/blob/master/test/functional/mempool_limit.py +// - https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp +func (r BitcoindRPCErr) Error() string { + switch r { + case ErrMissingInputsOrSpent: + return "bad-txns-inputs-missingorspent" + + case ErrMaxBurnExceeded: + return "Unspendable output exceeds maximum configured by user (maxburnamount)" + + case ErrMaxFeeExceeded: + return "max-fee-exceeded" + + case ErrTxAlreadyKnown: + return "txn-already-known" + + case ErrTxAlreadyConfirmed: + return "Transaction already in block chain" + + case ErrMempoolConflict: + return "txn mempool conflict" + + case ErrReplacementAddsUnconfirmed: + return "replacement adds unconfirmed" + + case ErrInsufficientFee: + return "insufficient fee" + + case ErrTooManyReplacements: + return "too many potential replacements" + + case ErrMempoolMinFeeNotMet: + return "mempool min fee not met" + + case ErrConflictingTx: + return "bad txns spends conflicting tx" + + case ErrEmptyOutput: + return "bad txns vout empty" + + case ErrEmptyInput: + return "bad txns vin empty" + + case ErrTxTooSmall: + return "tx size small" + + case ErrDuplicateInput: + return "bad txns inputs duplicate" + + case ErrEmptyPrevOut: + return "bad txns prevout null" + + case ErrBelowOutValue: + return "bad txns in belowout" + + case ErrNegativeOutput: + return "bad txns vout negative" + + case ErrLargeOutput: + return "bad txns vout toolarge" + + case ErrLargeTotalOutput: + return "bad txns txouttotal toolarge" + + case ErrScriptVerifyFlag: + return "mandatory script verify flag failed" + + case ErrTooManySigOps: + return "bad txns too many sigops" + + case ErrInvalidOpcode: + return "disabled opcode" + + case ErrTxAlreadyInMempool: + return "txn already in mempool" + + case ErrMissingInputs: + return "missing inputs" + + case ErrOversizeTx: + return "bad txns oversize" + + case ErrCoinbaseTx: + return "coinbase" + + case ErrNonStandardVersion: + return "version" + + case ErrNonStandardScript: + return "scriptpubkey" + + case ErrBareMultiSig: + return "bare multisig" + + case ErrScriptSigNotPushOnly: + return "scriptsig not pushonly" + + case ErrScriptSigSize: + return "scriptsig size" + + case ErrTxTooLarge: + return "tx size" + + case ErrDust: + return "dust" + case ErrMultiOpReturn: + return "multi op return" + + case ErrNonFinal: + return "non final" + + case ErrNonBIP68Final: + return "non BIP68 final" + + case ErrSameNonWitnessData: + return "txn-same-nonwitness-data-in-mempool" + + case ErrNonMandatoryScriptVerifyFlag: + return "non-mandatory-script-verify-flag" + } + + return "unknown error" +} + +// BtcdErrMap takes the errors returned from btcd's `testmempoolaccept` and +// `sendrawtransaction` RPCs and map them to the errors defined above, which +// are results from calling either `testmempoolaccept` or `sendrawtransaction` +// in `bitcoind`. +// +// Errors not mapped in `btcd`: +// - deployment error from `validateSegWitDeployment`. +// - the error when total inputs is higher than max allowed value from +// `CheckTransactionInputs`. +// - the error when total outputs is higher than total inputs from +// `CheckTransactionInputs`. +// - errors from `CalcSequenceLock`. +// +// NOTE: This is not an exhaustive list of errors, but it covers the +// usage case of LND. +// +//nolint:lll +var BtcdErrMap = map[string]error{ + // BIP125 related errors. + // + // When fee rate used or fees paid doesn't meet the requirements. + "replacement transaction has an insufficient fee rate": ErrInsufficientFee, + "replacement transaction has an insufficient absolute fee": ErrInsufficientFee, + + // When a transaction causes too many transactions being replaced. This + // is set by `MAX_REPLACEMENT_CANDIDATES` in `bitcoind` and defaults to + // 100. + "replacement transaction evicts more transactions than permitted": ErrTooManyReplacements, + + // When a transaction adds new unconfirmed inputs. + "replacement transaction spends new unconfirmed input": ErrReplacementAddsUnconfirmed, + + // A transaction that spends conflicting tx outputs that are rejected. + "replacement transaction spends parent transaction": ErrConflictingTx, + + // A transaction that conflicts with an unconfirmed tx. Happens when + // RBF is not enabled. + "output already spent in mempool": ErrMempoolConflict, + + // A transaction with no outputs. + "transaction has no outputs": ErrEmptyOutput, + + // A transaction with no inputs. + "transaction has no inputs": ErrEmptyInput, + + // A transaction with duplicate inputs. + "transaction contains duplicate inputs": ErrDuplicateInput, + + // A non-coinbase transaction with coinbase-like outpoint. + "transaction input refers to previous output that is null": ErrEmptyPrevOut, + + // A transaction pays too little fee. + "fees which is under the required amount": ErrMempoolMinFeeNotMet, + "has insufficient priority": ErrInsufficientFee, + "has been rejected by the rate limiter due to low fees": ErrInsufficientFee, + + // A transaction with negative output value. + "transaction output has negative value": ErrNegativeOutput, + + // A transaction with too large output value. + "transaction output value is higher than max allowed value": ErrLargeOutput, + + // A transaction with too large sum of output values. + "total value of all transaction outputs exceeds max allowed value": ErrLargeTotalOutput, + + // A transaction with too many sigops. + "sigop cost is too hight": ErrTooManySigOps, + + // A transaction already in the blockchain. + "database contains entry for spent tx output": ErrTxAlreadyKnown, + "transaction already exists in blockchain": ErrTxAlreadyConfirmed, + + // A transaction in the mempool. + "already have transaction in mempool": ErrTxAlreadyInMempool, + + // A transaction with missing inputs, that never existed or only + // existed once in the past. + "either does not exist or has already been spent": ErrMissingInputs, + "orphan transaction": ErrMissingInputs, + + // A really large transaction. + "serialized transaction is too big": ErrOversizeTx, + + // A coinbase transaction. + "transaction is an invalid coinbase": ErrCoinbaseTx, + + // Some nonstandard transactions - a version currently non-standard. + "transaction version": ErrNonStandardVersion, + + // Some nonstandard transactions - non-standard script. + "non-standard script form": ErrNonStandardScript, + "has a non-standard input": ErrNonStandardScript, + + // Some nonstandard transactions - bare multisig script + // (2-of-3). + "milti-signature script": ErrBareMultiSig, + + // Some nonstandard transactions - not-pushonly scriptSig. + "signature script is not push only": ErrScriptSigNotPushOnly, + + // Some nonstandard transactions - too large scriptSig (>1650 + // bytes). + "signature script size is larger than max allowed": ErrScriptSigSize, + + // Some nonstandard transactions - too large tx size. + "weight of transaction is larger than max allowed": ErrTxTooLarge, + + // Some nonstandard transactions - output too small. + "payment is dust": ErrDust, + + // Some nonstandard transactions - muiltiple OP_RETURNs. + "more than one transaction output in a nulldata script": ErrMultiOpReturn, + + // A timelocked transaction. + "transaction is not finalized": ErrNonFinal, + "tried to spend coinbase transaction output": ErrNonFinal, + + // A transaction that is locked by BIP68 sequence logic. + "transaction's sequence locks on inputs not met": ErrNonBIP68Final, + + // TODO(yy): find/return the following errors in `btcd`. + // + // A tiny transaction(in non-witness bytes) that is disallowed. + // "unmatched btcd error 1": ErrTxTooSmall, + // "unmatched btcd error 2": ErrScriptVerifyFlag, + // // A transaction with invalid OP codes. + // "unmatched btcd error 3": ErrInvalidOpcode, + // // Minimally-small transaction(in non-witness bytes) that is + // // allowed. + // "unmatched btcd error 4": ErrSameNonWitnessData, +} + +// MapRPCErr takes an error returned from calling RPC methods from various +// chain backend and map it to an defined error here. It uses the `BtcdErrMap` +// defined above, whose keys are btcd error strings and values are errors made +// from bitcoind error strings. +// +// NOTE: we assume neutrino shares the same error strings as btcd. +func MapRPCErr(rpcErr error) error { // Iterate the map and find the matching error. - for keyErr, rejectReason := range RejectReasonMap { - // Match the substring. - if strings.Contains(btcErr, keyErr) { - return rejectReason + for btcdErr, err := range BtcdErrMap { + // Match it against btcd's error first. + if matchErrStr(rpcErr, btcdErr) { + return err } } - // If there's no match, return the error string directly. - return btcErr + // If not found, try to match it against bitcoind's error. + for i := uint32(0); i < uint32(errSentinel); i++ { + err := BitcoindRPCErr(i) + if matchErrStr(rpcErr, err.Error()) { + return err + } + } + + // If not matched, return the original error wrapped. + return fmt.Errorf("%w: %v", ErrUndefined, rpcErr) +} + +// matchErrStr takes an error returned from RPC client and matches it against +// the specified string. If the expected string pattern is found in the error +// passed, return true. Both the error strings are normalized before matching. +func matchErrStr(err error, s string) bool { + // Replace all dashes found in the error string with spaces. + strippedErrStr := strings.ReplaceAll(err.Error(), "-", " ") + + // Replace all dashes found in the error string with spaces. + strippedMatchStr := strings.ReplaceAll(s, "-", " ") + + // Match against the lowercase. + return strings.Contains( + strings.ToLower(strippedErrStr), + strings.ToLower(strippedMatchStr), + ) } diff --git a/rpcclient/errors_test.go b/rpcclient/errors_test.go new file mode 100644 index 0000000000..e074622b11 --- /dev/null +++ b/rpcclient/errors_test.go @@ -0,0 +1,122 @@ +package rpcclient + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestMatchErrStr checks that `matchErrStr` can correctly replace the dashes +// with spaces and turn title cases into lowercases for a given error and match +// it against the specified string pattern. +func TestMatchErrStr(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + bitcoindErr error + matchStr string + matched bool + }{ + { + name: "error without dashes", + bitcoindErr: errors.New("missing input"), + matchStr: "missing input", + matched: true, + }, + { + name: "match str without dashes", + bitcoindErr: errors.New("missing-input"), + matchStr: "missing input", + matched: true, + }, + { + name: "error with dashes", + bitcoindErr: errors.New("missing-input"), + matchStr: "missing input", + matched: true, + }, + { + name: "match str with dashes", + bitcoindErr: errors.New("missing-input"), + matchStr: "missing-input", + matched: true, + }, + { + name: "error with title case and dash", + bitcoindErr: errors.New("Missing-Input"), + matchStr: "missing input", + matched: true, + }, + { + name: "match str with title case and dash", + bitcoindErr: errors.New("missing-input"), + matchStr: "Missing-Input", + matched: true, + }, + { + name: "unmatched error", + bitcoindErr: errors.New("missing input"), + matchStr: "missingorspent", + matched: false, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + matched := matchErrStr(tc.bitcoindErr, tc.matchStr) + require.Equal(t, tc.matched, matched) + }) + } +} + +// TestMapRPCErr checks that `MapRPCErr` can correctly map a given error to +// the corresponding error in the `BtcdErrMap` or `BitcoindErrors` map. +func TestMapRPCErr(t *testing.T) { + t.Parallel() + + require := require.New(t) + + // Get all known bitcoind errors. + bitcoindErrors := make([]error, 0, errSentinel) + for i := uint32(0); i < uint32(errSentinel); i++ { + err := BitcoindRPCErr(i) + bitcoindErrors = append(bitcoindErrors, err) + } + + // An unknown error should be mapped to ErrUndefined. + errUnknown := errors.New("unknown error") + err := MapRPCErr(errUnknown) + require.ErrorIs(err, ErrUndefined) + + // A known error should be mapped to the corresponding error in the + // `BtcdErrMap` or `bitcoindErrors` map. + for btcdErrStr, mappedErr := range BtcdErrMap { + err := MapRPCErr(errors.New(btcdErrStr)) + require.ErrorIs(err, mappedErr) + + err = MapRPCErr(mappedErr) + require.ErrorIs(err, mappedErr) + } + + for _, bitcoindErr := range bitcoindErrors { + err = MapRPCErr(bitcoindErr) + require.ErrorIs(err, bitcoindErr) + } +} + +// TestBitcoindErrorSentinel checks that all defined BitcoindRPCErr errors are +// added to the method `Error`. +func TestBitcoindErrorSentinel(t *testing.T) { + t.Parallel() + + rt := require.New(t) + + for i := uint32(0); i < uint32(errSentinel); i++ { + err := BitcoindRPCErr(i) + rt.NotEqualf(err.Error(), "unknown error", "error code %d is "+ + "not defined, make sure to update it inside the Error "+ + "method", i) + } +} From 8abf969c3cdc8d38cbfc522d05a01513f8917eee Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 15 Mar 2024 04:57:59 +0800 Subject: [PATCH 0977/1056] rpcserver: return the plain reject reason from `btcd` This commit changes the `RejectReason` resulted from calling btcd's `testmempoolaccept` to be un-matched, leaving it to the caller to decide when and where to match it. --- rpcserver.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index eaa5f05633..e5b8aac949 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -39,7 +39,6 @@ import ( "github.com/btcsuite/btcd/mining" "github.com/btcsuite/btcd/mining/cpuminer" "github.com/btcsuite/btcd/peer" - "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/websocket" @@ -3858,9 +3857,7 @@ func handleTestMempoolAccept(s *rpcServer, cmd interface{}, // TODO(yy): differentiate the errors and put package // error in `PackageError` field. - item.RejectReason = rpcclient.MapBtcdErrToRejectReason( - err, - ) + item.RejectReason = err.Error() results = append(results, item) From 2a225e9d36a1c70b45313aeef99774aa2d0c2f8b Mon Sep 17 00:00:00 2001 From: ffranr Date: Mon, 6 Nov 2023 15:07:04 +0000 Subject: [PATCH 0978/1056] wire: add method TxID to MsgTx This commit adds a method to MsgTx called TxID. This method returns the transaction ID (txid) of the subject transaction. --- wire/msgtx.go | 5 +++++ wire/msgtx_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/wire/msgtx.go b/wire/msgtx.go index eab265c35d..a86061a95e 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -353,6 +353,11 @@ func (msg *MsgTx) TxHash() chainhash.Hash { return chainhash.DoubleHashRaw(msg.SerializeNoWitness) } +// TxID generates the transaction ID of the transaction. +func (msg *MsgTx) TxID() string { + return msg.TxHash().String() +} + // WitnessHash generates the hash of the transaction serialized according to // the new witness serialization defined in BIP0141 and BIP0144. The final // output is used within the Segregated Witness commitment of all the witnesses diff --git a/wire/msgtx_test.go b/wire/msgtx_test.go index 5ec753b62d..1b3bfd4eec 100644 --- a/wire/msgtx_test.go +++ b/wire/msgtx_test.go @@ -756,6 +756,34 @@ func TestTxSerializeSizeStripped(t *testing.T) { } } +// TestTxID performs tests to ensure the serialize size for various transactions +// is accurate. +func TestTxID(t *testing.T) { + // Empty tx message. + noTx := NewMsgTx(1) + noTx.Version = 1 + + tests := []struct { + in *MsgTx // Tx to encode. + txid string // Expected transaction ID. + }{ + // No inputs or outputs. + {noTx, "d21633ba23f70118185227be58a63527675641ad37967e2aa461559f577aec43"}, + + // Transaction with an input and an output. + {multiTx, "0100d15a522ff38de05c164ca0a56379a1b77dd1e4805a6534dc9b3d88290e9d"}, + + // Transaction with an input which includes witness data, and + // one output. + {multiWitnessTx, "0f167d1385a84d1518cfee208b653fc9163b605ccf1b75347e2850b3e2eb19f3"}, + } + + for i, test := range tests { + txid := test.in.TxID() + require.Equal(t, test.txid, txid, "test #%d", i) + } +} + // TestTxWitnessSize performs tests to ensure that the serialized size for // various types of transactions that include witness data is accurate. func TestTxWitnessSize(t *testing.T) { From 75fe7e479030fdb4c2dfa0293e44afc74025fb00 Mon Sep 17 00:00:00 2001 From: ffranr Date: Fri, 9 Jun 2023 18:31:00 +0100 Subject: [PATCH 0979/1056] wire: make witnessToHex a TxWitness method called ToHexStrings --- rpcserver.go | 23 +++-------------------- wire/msgtx.go | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index e5b8aac949..09b5e48821 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -646,23 +646,6 @@ func handleDebugLevel(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return "Done.", nil } -// witnessToHex formats the passed witness stack as a slice of hex-encoded -// strings to be used in a JSON response. -func witnessToHex(witness wire.TxWitness) []string { - // Ensure nil is returned when there are no entries versus an empty - // slice so it can properly be omitted as necessary. - if len(witness) == 0 { - return nil - } - - result := make([]string, 0, len(witness)) - for _, wit := range witness { - result = append(result, hex.EncodeToString(wit)) - } - - return result -} - // createVinList returns a slice of JSON objects for the inputs of the passed // transaction. func createVinList(mtx *wire.MsgTx) []btcjson.Vin { @@ -672,7 +655,7 @@ func createVinList(mtx *wire.MsgTx) []btcjson.Vin { txIn := mtx.TxIn[0] vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript) vinList[0].Sequence = txIn.Sequence - vinList[0].Witness = witnessToHex(txIn.Witness) + vinList[0].Witness = txIn.Witness.ToHexStrings() return vinList } @@ -692,7 +675,7 @@ func createVinList(mtx *wire.MsgTx) []btcjson.Vin { } if mtx.HasWitness() { - vinEntry.Witness = witnessToHex(txIn.Witness) + vinEntry.Witness = txIn.Witness.ToHexStrings() } } @@ -3052,7 +3035,7 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P } if len(txIn.Witness) != 0 { - vinEntry.Witness = witnessToHex(txIn.Witness) + vinEntry.Witness = txIn.Witness.ToHexStrings() } // Add the entry to the list now if it already passed the filter diff --git a/wire/msgtx.go b/wire/msgtx.go index a86061a95e..61dbbe8995 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -5,6 +5,7 @@ package wire import ( + "encoding/hex" "errors" "fmt" "io" @@ -302,6 +303,22 @@ func (t TxWitness) SerializeSize() int { return n } +// ToHexStrings formats the witness stack as a slice of hex-encoded strings. +func (t TxWitness) ToHexStrings() []string { + // Ensure nil is returned when there are no entries versus an empty + // slice so it can properly be omitted as necessary. + if len(t) == 0 { + return nil + } + + result := make([]string, len(t)) + for idx, wit := range t { + result[idx] = hex.EncodeToString(wit) + } + + return result +} + // TxOut defines a bitcoin transaction output. type TxOut struct { Value int64 From 3cb9f602e825660078fd5d2035cbbf3ea5381f0c Mon Sep 17 00:00:00 2001 From: mattn Date: Mon, 25 Mar 2024 22:44:25 +0900 Subject: [PATCH 0980/1056] fix typos (#2100) --- CHANGES | 2 +- addrmgr/addrmanager_internal_test.go | 2 +- blockchain/chain_test.go | 8 ++++---- blockchain/chainio.go | 2 +- blockchain/chainio_test.go | 2 +- blockchain/common_test.go | 2 +- blockchain/difficulty_test.go | 2 +- blockchain/error.go | 2 +- blockchain/fullblocktests/generate.go | 4 ++-- blockchain/indexers/addrindex.go | 6 +++--- blockchain/merkle.go | 2 +- blockchain/upgrade_test.go | 2 +- blockchain/utxocache_test.go | 2 +- blockchain/utxoviewpoint.go | 4 ++-- blockchain/validate.go | 2 +- btcec/README.md | 2 +- btcec/ecdsa/signature.go | 2 +- btcec/field_test.go | 2 +- btcec/schnorr/musig2/context.go | 2 +- btcec/schnorr/musig2/musig2_test.go | 2 +- btcec/schnorr/musig2/nonces.go | 2 +- btcec/schnorr/musig2/sign_test.go | 4 ++-- btcjson/btcdextcmds.go | 2 +- btcjson/btcdextresults_test.go | 2 +- btcjson/chainsvrresults_test.go | 2 +- btcjson/chainsvrwsresults_test.go | 2 +- btcjson/cmdinfo_test.go | 2 +- btcjson/cmdparse.go | 2 +- btcjson/error.go | 2 +- btcutil/bech32/bech32.go | 2 +- btcutil/bech32/bech32_test.go | 4 ++-- btcutil/bloom/example_test.go | 2 +- btcutil/coinset/coins_test.go | 2 +- btcutil/gcs/builder/builder.go | 4 ++-- btcutil/psbt/finalizer.go | 8 ++++---- config.go | 2 +- connmgr/connmanager.go | 4 ++-- connmgr/seed.go | 2 +- database/error.go | 2 +- database/ffldb/driver.go | 2 +- database/ffldb/interface_test.go | 4 ++-- database/ffldb/whitebox_test.go | 2 +- database/interface.go | 2 +- docs/json_rpc_api.md | 2 +- log.go | 2 +- mining/mining.go | 2 +- mining/policy.go | 2 +- peer/example_test.go | 2 +- peer/peer.go | 2 +- rpcclient/chain_test.go | 6 +++--- rpcclient/infrastructure.go | 6 +++--- rpcclient/notify.go | 8 ++++---- rpcclient/rawtransactions.go | 2 +- rpcclient/wallet.go | 2 +- rpcserver.go | 12 ++++++------ rpcserverhelp.go | 2 +- rpcwebsocket.go | 12 ++++++------ service_windows.go | 2 +- txscript/data/script_tests.json | 2 +- txscript/data/tx_invalid.json | 2 +- txscript/engine.go | 2 +- txscript/engine_debug_test.go | 2 +- txscript/engine_test.go | 4 ++-- txscript/error.go | 2 +- txscript/script.go | 2 +- txscript/sigvalidate.go | 2 +- txscript/standard_test.go | 2 +- txscript/taproot.go | 2 +- txscript/taproot_test.go | 2 +- wire/bench_test.go | 4 ++-- wire/fixedIO_test.go | 4 ++-- wire/msgalert.go | 4 ++-- wire/msgblock.go | 2 +- wire/msgblock_test.go | 2 +- wire/msggetheaders.go | 2 +- wire/msgtx_test.go | 8 ++++---- wire/msgversion.go | 2 +- 77 files changed, 116 insertions(+), 116 deletions(-) diff --git a/CHANGES b/CHANGES index fd59a88672..4e359222b8 100644 --- a/CHANGES +++ b/CHANGES @@ -782,7 +782,7 @@ Changes in 0.8.0-beta (Sun May 25 2014) recent reference client changes (https://github.com/conformal/btcd/issues/100) - Raise the maximum signature script size to support standard 15-of-15 - multi-signature pay-to-sript-hash transactions with compressed pubkeys + multi-signature pay-to-script-hash transactions with compressed pubkeys to remain compatible with the reference client (https://github.com/conformal/btcd/issues/128) - Reduce max bytes allowed for a standard nulldata transaction to 40 for diff --git a/addrmgr/addrmanager_internal_test.go b/addrmgr/addrmanager_internal_test.go index ff19eae1d1..38218b15f7 100644 --- a/addrmgr/addrmanager_internal_test.go +++ b/addrmgr/addrmanager_internal_test.go @@ -184,7 +184,7 @@ func TestAddrManagerV1ToV2(t *testing.T) { addrMgr.loadPeers() addrs := addrMgr.getAddresses() if len(addrs) != len(expectedAddrs) { - t.Fatalf("expected to find %d adddresses, found %d", + t.Fatalf("expected to find %d addresses, found %d", len(expectedAddrs), len(addrs)) } for _, addr := range addrs { diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index 1ac08f9a76..cd5c761bc4 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -782,7 +782,7 @@ func TestLocateInventory(t *testing.T) { &test.hashStop) } if !reflect.DeepEqual(headers, test.headers) { - t.Errorf("%s: unxpected headers -- got %v, want %v", + t.Errorf("%s: unexpected headers -- got %v, want %v", test.name, headers, test.headers) continue } @@ -795,7 +795,7 @@ func TestLocateInventory(t *testing.T) { hashes := chain.LocateBlocks(test.locator, &test.hashStop, maxAllowed) if !reflect.DeepEqual(hashes, test.hashes) { - t.Errorf("%s: unxpected hashes -- got %v, want %v", + t.Errorf("%s: unexpected hashes -- got %v, want %v", test.name, hashes, test.hashes) continue } @@ -888,7 +888,7 @@ func TestHeightToHashRange(t *testing.T) { } if !reflect.DeepEqual(hashes, test.hashes) { - t.Errorf("%s: unxpected hashes -- got %v, want %v", + t.Errorf("%s: unexpected hashes -- got %v, want %v", test.name, hashes, test.hashes) } } @@ -960,7 +960,7 @@ func TestIntervalBlockHashes(t *testing.T) { } if !reflect.DeepEqual(hashes, test.hashes) { - t.Errorf("%s: unxpected hashes -- got %v, want %v", + t.Errorf("%s: unexpected hashes -- got %v, want %v", test.name, hashes, test.hashes) } } diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 75474021f8..3340dd14a0 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -247,7 +247,7 @@ type SpentTxOut struct { // Amount is the amount of the output. Amount int64 - // PkScipt is the public key script for the output. + // PkScript is the public key script for the output. PkScript []byte // Height is the height of the block containing the creating tx. diff --git a/blockchain/chainio_test.go b/blockchain/chainio_test.go index 630af14e1c..a9e19b6f01 100644 --- a/blockchain/chainio_test.go +++ b/blockchain/chainio_test.go @@ -403,7 +403,7 @@ func TestSpendJournalErrors(t *testing.T) { } // TestUtxoSerialization ensures serializing and deserializing unspent -// trasaction output entries works as expected. +// transaction output entries works as expected. func TestUtxoSerialization(t *testing.T) { t.Parallel() diff --git a/blockchain/common_test.go b/blockchain/common_test.go index 1973689ea1..5037c1828e 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -343,7 +343,7 @@ func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) { b.chainParams.CoinbaseMaturity = maturity } -// newFakeChain returns a chain that is usable for syntetic tests. It is +// newFakeChain returns a chain that is usable for synthetic tests. It is // important to note that this chain has no database associated with it, so // it is not usable with all functions and the tests must take care when making // use of it. diff --git a/blockchain/difficulty_test.go b/blockchain/difficulty_test.go index 6fed37f136..c4d8fb6ef5 100644 --- a/blockchain/difficulty_test.go +++ b/blockchain/difficulty_test.go @@ -32,7 +32,7 @@ func TestBigToCompact(t *testing.T) { } // TestCompactToBig ensures CompactToBig converts numbers using the compact -// representation to the expected big intergers. +// representation to the expected big integers. func TestCompactToBig(t *testing.T) { tests := []struct { in uint32 diff --git a/blockchain/error.go b/blockchain/error.go index 1e7c879ba0..dc40222235 100644 --- a/blockchain/error.go +++ b/blockchain/error.go @@ -70,7 +70,7 @@ const ( // ErrUnexpectedDifficulty indicates specified bits do not align with // the expected value either because it doesn't match the calculated - // valued based on difficulty regarted rules or it is out of the valid + // valued based on difficulty regarded rules or it is out of the valid // range. ErrUnexpectedDifficulty diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 15b92540b5..fe36bfe136 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -960,7 +960,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // --------------------------------------------------------------------- // The comments below identify the structure of the chain being built. // - // The values in parenthesis repesent which outputs are being spent. + // The values in parenthesis represent which outputs are being spent. // // For example, b1(0) indicates the first collected spendable output // which, due to the code above to create the correct number of blocks, @@ -1218,7 +1218,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { accepted() // --------------------------------------------------------------------- - // Multisig[Verify]/ChecksigVerifiy signature operation count tests. + // Multisig[Verify]/ChecksigVerify signature operation count tests. // --------------------------------------------------------------------- // Create block with max signature operations as OP_CHECKMULTISIG. diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 7eaaab06b7..271e1665a7 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -64,7 +64,7 @@ const ( addrKeyTypeWitnessScriptHash = 3 // addrKeyTypeTaprootPubKey is the address type in an address key that - // represnts a pay-to-taproot address. We use this to denote addresses + // represents a pay-to-taproot address. We use this to denote addresses // related to the segwit v1 that are encoded in the bech32m format. addrKeyTypeTaprootPubKey = 4 @@ -158,7 +158,7 @@ func serializeAddrIndexEntry(blockID uint32, txLoc wire.TxLoc) []byte { // deserializeAddrIndexEntry decodes the passed serialized byte slice into the // provided region struct according to the format described in detail above and -// uses the passed block hash fetching function in order to conver the block ID +// uses the passed block hash fetching function in order to convert the block ID // to the associated block hash. func deserializeAddrIndexEntry(serialized []byte, region *database.BlockRegion, fetchBlockHash fetchBlockHashFunc) error { @@ -734,7 +734,7 @@ func (idx *AddrIndex) indexBlock(data writeIndexData, block *btcutil.Block, idx.indexPkScript(data, pkScript, txIdx) // With an input indexed, we'll advance the - // stxo coutner. + // stxo counter. stxoIndex++ } } diff --git a/blockchain/merkle.go b/blockchain/merkle.go index b89b518505..086c3643f6 100644 --- a/blockchain/merkle.go +++ b/blockchain/merkle.go @@ -146,7 +146,7 @@ func BuildMerkleTreeStore(transactions []*btcutil.Tx, witness bool) []*chainhash merkles[offset] = &newHash // The normal case sets the parent node to the double sha256 - // of the concatentation of the left and right children. + // of the concatenation of the left and right children. default: newHash := HashMerkleBranches(merkles[i], merkles[i+1]) merkles[offset] = &newHash diff --git a/blockchain/upgrade_test.go b/blockchain/upgrade_test.go index 97e7f55c35..9a060b3e8e 100644 --- a/blockchain/upgrade_test.go +++ b/blockchain/upgrade_test.go @@ -9,7 +9,7 @@ import ( "testing" ) -// TestDeserializeUtxoEntryV0 ensures deserializing unspent trasaction output +// TestDeserializeUtxoEntryV0 ensures deserializing unspent transaction output // entries from the legacy version 0 format works as expected. func TestDeserializeUtxoEntryV0(t *testing.T) { tests := []struct { diff --git a/blockchain/utxocache_test.go b/blockchain/utxocache_test.go index c19850e4bf..0f410cc99e 100644 --- a/blockchain/utxocache_test.go +++ b/blockchain/utxocache_test.go @@ -445,7 +445,7 @@ func TestUtxoCacheFlush(t *testing.T) { t.Fatalf("Unexpected nil entry found for %v", outpoint) } if !entry.isModified() { - t.Fatal("Entry should be marked mofified") + t.Fatal("Entry should be marked modified") } if !entry.isFresh() { t.Fatal("Entry should be marked fresh") diff --git a/blockchain/utxoviewpoint.go b/blockchain/utxoviewpoint.go index 702f99507c..f62f4b915f 100644 --- a/blockchain/utxoviewpoint.go +++ b/blockchain/utxoviewpoint.go @@ -163,13 +163,13 @@ type UtxoViewpoint struct { } // BestHash returns the hash of the best block in the chain the view currently -// respresents. +// represents. func (view *UtxoViewpoint) BestHash() *chainhash.Hash { return &view.bestHash } // SetBestHash sets the hash of the best block in the chain the view currently -// respresents. +// represents. func (view *UtxoViewpoint) SetBestHash(hash *chainhash.Hash) { view.bestHash = *hash } diff --git a/blockchain/validate.go b/blockchain/validate.go index 641967fbf2..6c49bd565d 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -879,7 +879,7 @@ func (b *BlockChain) checkBlockContext(block *btcutil.Block, prevNode *blockNode // // This function MUST be called with the chain state lock held (for reads). func (b *BlockChain) checkBIP0030(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error { - // Fetch utxos for all of the transaction ouputs in this block. + // Fetch utxos for all of the transaction outputs in this block. // Typically, there will not be any utxos for any of the outputs. fetch := make([]wire.OutPoint, 0, len(block.Transactions())) for _, tx := range block.Transactions() { diff --git a/btcec/README.md b/btcec/README.md index cbf63dd045..533917736e 100644 --- a/btcec/README.md +++ b/btcec/README.md @@ -10,7 +10,7 @@ Bitcoin (secp256k1 only for now). It is designed so that it may be used with the standard crypto/ecdsa packages provided with go. A comprehensive suite of test is provided to ensure proper functionality. Package btcec was originally based on work from ThePiachu which is licensed under the same terms as Go, but it has -signficantly diverged since then. The btcsuite developers original is licensed +significantly diverged since then. The btcsuite developers original is licensed under the liberal ISC license. Although this package was primarily written for btcd, it has intentionally been diff --git a/btcec/ecdsa/signature.go b/btcec/ecdsa/signature.go index 44b84a78c9..11c6267caf 100644 --- a/btcec/ecdsa/signature.go +++ b/btcec/ecdsa/signature.go @@ -212,7 +212,7 @@ func parseSig(sigStr []byte, der bool) (*Signature, error) { } // ParseSignature parses a signature in BER format for the curve type `curve' -// into a Signature type, perfoming some basic sanity checks. If parsing +// into a Signature type, performing some basic sanity checks. If parsing // according to the more strict DER format is needed, use ParseDERSignature. func ParseSignature(sigStr []byte) (*Signature, error) { return parseSig(sigStr, false) diff --git a/btcec/field_test.go b/btcec/field_test.go index 6ade97a1eb..0844dc1d67 100644 --- a/btcec/field_test.go +++ b/btcec/field_test.go @@ -952,7 +952,7 @@ func TestFieldSquareRoot(t *testing.T) { input := setHex(test.in).Normalize() want := setHex(test.want).Normalize() - // Calculate the square root and enusre the validity flag matches the + // Calculate the square root and ensure the validity flag matches the // expected value. var result FieldVal isValid := result.SquareRootVal(input) diff --git a/btcec/schnorr/musig2/context.go b/btcec/schnorr/musig2/context.go index 8f4521502a..8e6b7154d3 100644 --- a/btcec/schnorr/musig2/context.go +++ b/btcec/schnorr/musig2/context.go @@ -513,7 +513,7 @@ func (s *Session) PublicNonce() [PubNonceSize]byte { } // NumRegisteredNonces returns the total number of nonces that have been -// regsitered so far. +// registered so far. func (s *Session) NumRegisteredNonces() int { return len(s.pubNonces) } diff --git a/btcec/schnorr/musig2/musig2_test.go b/btcec/schnorr/musig2/musig2_test.go index 91dad90b3e..dfd48f3e82 100644 --- a/btcec/schnorr/musig2/musig2_test.go +++ b/btcec/schnorr/musig2/musig2_test.go @@ -258,7 +258,7 @@ func TestMuSigMultiParty(t *testing.T) { } // TestMuSigEarlyNonce tests that for protocols where nonces need to be -// exchagned before all signers are known, the context API works as expected. +// exchanged before all signers are known, the context API works as expected. func TestMuSigEarlyNonce(t *testing.T) { t.Parallel() diff --git a/btcec/schnorr/musig2/nonces.go b/btcec/schnorr/musig2/nonces.go index 988b199471..dbe39ef3db 100644 --- a/btcec/schnorr/musig2/nonces.go +++ b/btcec/schnorr/musig2/nonces.go @@ -144,7 +144,7 @@ func defaultNonceGenOpts() *nonceGenOpts { // WithCustomRand allows a caller to use a custom random number generator in // place for crypto/rand. This should only really be used to generate -// determinstic tests. +// deterministic tests. func WithCustomRand(r io.Reader) NonceGenOption { return func(o *nonceGenOpts) { o.randReader = r diff --git a/btcec/schnorr/musig2/sign_test.go b/btcec/schnorr/musig2/sign_test.go index a7f5d79d5d..a967cfe476 100644 --- a/btcec/schnorr/musig2/sign_test.go +++ b/btcec/schnorr/musig2/sign_test.go @@ -298,7 +298,7 @@ type sigCombineTestVectors struct { ValidCases []sigCombineValidCase `json:"valid_test_cases"` } -func pSigsFromIndicies(t *testing.T, sigs []string, indices []int) []*PartialSignature { +func pSigsFromIndices(t *testing.T, sigs []string, indices []int) []*PartialSignature { pSigs := make([]*PartialSignature, len(indices)) for i, idx := range indices { var pSig PartialSignature @@ -341,7 +341,7 @@ func TestMusig2SignCombine(t *testing.T) { t, testCase.NonceIndices, testCases.PubNonces, ) - partialSigs := pSigsFromIndicies( + partialSigs := pSigsFromIndices( t, testCases.Psigs, testCase.PSigIndices, ) diff --git a/btcjson/btcdextcmds.go b/btcjson/btcdextcmds.go index a3ca46ba71..768dca4d3d 100644 --- a/btcjson/btcdextcmds.go +++ b/btcjson/btcdextcmds.go @@ -20,7 +20,7 @@ const ( // persistent peer. NRemove NodeSubCmd = "remove" - // NDisconnect indicates the specified peer should be disonnected. + // NDisconnect indicates the specified peer should be disconnected. NDisconnect NodeSubCmd = "disconnect" ) diff --git a/btcjson/btcdextresults_test.go b/btcjson/btcdextresults_test.go index 478f088cd3..9a8b9eedf7 100644 --- a/btcjson/btcdextresults_test.go +++ b/btcjson/btcdextresults_test.go @@ -13,7 +13,7 @@ import ( ) // TestBtcdExtCustomResults ensures any results that have custom marshalling -// work as inteded. +// work as intended. // and unmarshal code of results are as expected. func TestBtcdExtCustomResults(t *testing.T) { t.Parallel() diff --git a/btcjson/chainsvrresults_test.go b/btcjson/chainsvrresults_test.go index 8a11197af2..2566e65f62 100644 --- a/btcjson/chainsvrresults_test.go +++ b/btcjson/chainsvrresults_test.go @@ -17,7 +17,7 @@ import ( ) // TestChainSvrCustomResults ensures any results that have custom marshalling -// work as inteded. +// work as intended. // and unmarshal code of results are as expected. func TestChainSvrCustomResults(t *testing.T) { t.Parallel() diff --git a/btcjson/chainsvrwsresults_test.go b/btcjson/chainsvrwsresults_test.go index b1e17450c1..9e8c7676c1 100644 --- a/btcjson/chainsvrwsresults_test.go +++ b/btcjson/chainsvrwsresults_test.go @@ -13,7 +13,7 @@ import ( ) // TestChainSvrWsResults ensures any results that have custom marshalling -// work as inteded. +// work as intended. func TestChainSvrWsResults(t *testing.T) { t.Parallel() diff --git a/btcjson/cmdinfo_test.go b/btcjson/cmdinfo_test.go index 61a693e404..9dc4567840 100644 --- a/btcjson/cmdinfo_test.go +++ b/btcjson/cmdinfo_test.go @@ -11,7 +11,7 @@ import ( "github.com/btcsuite/btcd/btcjson" ) -// TestCmdMethod tests the CmdMethod function to ensure it retunrs the expected +// TestCmdMethod tests the CmdMethod function to ensure it returns the expected // methods and errors. func TestCmdMethod(t *testing.T) { t.Parallel() diff --git a/btcjson/cmdparse.go b/btcjson/cmdparse.go index 5cf3215e52..3b0473b865 100644 --- a/btcjson/cmdparse.go +++ b/btcjson/cmdparse.go @@ -232,7 +232,7 @@ func baseType(arg reflect.Type) (reflect.Type, int) { // assignField is the main workhorse for the NewCmd function which handles // assigning the provided source value to the destination field. It supports // direct type assignments, indirection, conversion of numeric types, and -// unmarshaling of strings into arrays, slices, structs, and maps via +// unmarshalling of strings into arrays, slices, structs, and maps via // json.Unmarshal. func assignField(paramNum int, fieldName string, dest reflect.Value, src reflect.Value) error { // Just error now when the types have no chance of being compatible. diff --git a/btcjson/error.go b/btcjson/error.go index 3d72329f91..66be0214d1 100644 --- a/btcjson/error.go +++ b/btcjson/error.go @@ -30,7 +30,7 @@ const ( // embedded type which is not not supported. ErrEmbeddedType - // ErrUnexportedField indiciates the provided command struct contains an + // ErrUnexportedField indicates the provided command struct contains an // unexported field which is not supported. ErrUnexportedField diff --git a/btcutil/bech32/bech32.go b/btcutil/bech32/bech32.go index c1e00106e6..a7b056bd7a 100644 --- a/btcutil/bech32/bech32.go +++ b/btcutil/bech32/bech32.go @@ -18,7 +18,7 @@ const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3} // toBytes converts each character in the string 'chars' to the value of the -// index of the correspoding character in 'charset'. +// index of the corresponding character in 'charset'. func toBytes(chars string) ([]byte, error) { decoded := make([]byte, 0, len(chars)) for i := 0; i < len(chars); i++ { diff --git a/btcutil/bech32/bech32_test.go b/btcutil/bech32/bech32_test.go index 1e04905a61..354ba7a17a 100644 --- a/btcutil/bech32/bech32_test.go +++ b/btcutil/bech32/bech32_test.go @@ -297,9 +297,9 @@ func TestMixedCaseEncode(t *testing.T) { } } -// TestCanDecodeUnlimtedBech32 tests whether decoding a large bech32 string works +// TestCanDecodeUnlimitedBech32 tests whether decoding a large bech32 string works // when using the DecodeNoLimit version -func TestCanDecodeUnlimtedBech32(t *testing.T) { +func TestCanDecodeUnlimitedBech32(t *testing.T) { input := "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq5kx0yd" // Sanity check that an input of this length errors on regular Decode() diff --git a/btcutil/bloom/example_test.go b/btcutil/bloom/example_test.go index e5a148a5ba..2be2b67a74 100644 --- a/btcutil/bloom/example_test.go +++ b/btcutil/bloom/example_test.go @@ -26,7 +26,7 @@ func ExampleNewFilter() { filter := bloom.NewFilter(10, tweak, 0.0001, wire.BloomUpdateNone) // Create a transaction hash and add it to the filter. This particular - // trasaction is the first transaction in block 310,000 of the main + // transaction is the first transaction in block 310,000 of the main // bitcoin block chain. txHashStr := "fd611c56ca0d378cdcd16244b45c2ba9588da3adac367c4ef43e808b280b8a45" txHash, err := chainhash.NewHashFromStr(txHashStr) diff --git a/btcutil/coinset/coins_test.go b/btcutil/coinset/coins_test.go index 035a40cb99..c1984623f6 100644 --- a/btcutil/coinset/coins_test.go +++ b/btcutil/coinset/coins_test.go @@ -252,7 +252,7 @@ func TestSimpleCoin(t *testing.T) { t.Error("Different value of coin pkScript than expected") } if testSimpleCoin.NumConfs() != 1 { - t.Error("Differet value of num confs than expected") + t.Error("Different value of num confs than expected") } if testSimpleCoin.ValueAge() != testSimpleCoinTxValueAge0 { t.Error("Different value of coin value * age than expected") diff --git a/btcutil/gcs/builder/builder.go b/btcutil/gcs/builder/builder.go index 3a85ad0519..4e952996c1 100644 --- a/btcutil/gcs/builder/builder.go +++ b/btcutil/gcs/builder/builder.go @@ -60,7 +60,7 @@ func RandomKey() ([gcs.KeySize]byte, error) { } // DeriveKey is a utility function that derives a key from a chainhash.Hash by -// truncating the bytes of the hash to the appopriate key size. +// truncating the bytes of the hash to the appropriate key size. func DeriveKey(keyHash *chainhash.Hash) [gcs.KeySize]byte { var key [gcs.KeySize]byte copy(key[:], keyHash.CloneBytes()) @@ -207,7 +207,7 @@ func (b *GCSBuilder) Build() (*gcs.Filter, error) { return nil, b.err } - // We'll ensure that all the parmaters we need to actually build the + // We'll ensure that all the paramaters we need to actually build the // filter properly are set. if b.p == 0 { return nil, fmt.Errorf("p value is not set, cannot build") diff --git a/btcutil/psbt/finalizer.go b/btcutil/psbt/finalizer.go index 3c2edd5557..b1bf12d131 100644 --- a/btcutil/psbt/finalizer.go +++ b/btcutil/psbt/finalizer.go @@ -404,7 +404,7 @@ func finalizeWitnessInput(p *Packet, inIndex int) error { } containsRedeemScript := pInput.RedeemScript != nil - cointainsWitnessScript := pInput.WitnessScript != nil + containsWitnessScript := pInput.WitnessScript != nil // If there's no redeem script, then we assume that this is native // segwit input. @@ -413,7 +413,7 @@ func finalizeWitnessInput(p *Packet, inIndex int) error { // If we have only a sigley pubkey+sig pair, and no witness // script, then we assume this is a P2WKH input. if len(pubKeys) == 1 && len(sigs) == 1 && - !cointainsWitnessScript { + !containsWitnessScript { serializedWitness, err = writePKHWitness( sigs[0], pubKeys[0], @@ -430,7 +430,7 @@ func finalizeWitnessInput(p *Packet, inIndex int) error { // TODO(roasbeef): need to add custom finalize for // non-multisig P2WSH outputs (HTLCs, delay outputs, // etc). - if !cointainsWitnessScript { + if !containsWitnessScript { return ErrNotFinalizable } @@ -457,7 +457,7 @@ func finalizeWitnessInput(p *Packet, inIndex int) error { // If don't have a witness script, then we assume this is a // nested p2wkh output. - if !cointainsWitnessScript { + if !containsWitnessScript { // Assumed p2sh-p2wkh Here the witness is just (sig, // pub) as for p2pkh case if len(sigs) != 1 || len(pubKeys) != 1 { diff --git a/config.go b/config.go index 18620a008c..f8aad70cf8 100644 --- a/config.go +++ b/config.go @@ -275,7 +275,7 @@ func parseAndSetDebugLevels(debugLevel string) error { // Validate subsystem. if _, exists := subsystemLoggers[subsysID]; !exists { str := "The specified subsystem [%v] is invalid -- " + - "supported subsytems %v" + "supported subsystems %v" return fmt.Errorf(str, subsysID, supportedSubsystems()) } diff --git a/connmgr/connmanager.go b/connmgr/connmanager.go index b487bd1ba1..e88f8af0cb 100644 --- a/connmgr/connmanager.go +++ b/connmgr/connmanager.go @@ -525,9 +525,9 @@ func (cm *ConnManager) Start() { // Start all the listeners so long as the caller requested them and // provided a callback to be invoked when connections are accepted. if cm.cfg.OnAccept != nil { - for _, listner := range cm.cfg.Listeners { + for _, listener := range cm.cfg.Listeners { cm.wg.Add(1) - go cm.listenHandler(listner) + go cm.listenHandler(listener) } } diff --git a/connmgr/seed.go b/connmgr/seed.go index 4c26160d8f..705618f778 100644 --- a/connmgr/seed.go +++ b/connmgr/seed.go @@ -23,7 +23,7 @@ const ( ) // OnSeed is the signature of the callback function which is invoked when DNS -// seeding is succesfull. +// seeding is successful. type OnSeed func(addrs []*wire.NetAddressV2) // LookupFunc is the signature of the DNS lookup function. diff --git a/database/error.go b/database/error.go index 49c250eef5..3470c49749 100644 --- a/database/error.go +++ b/database/error.go @@ -87,7 +87,7 @@ const ( // should be relatively, so this should rarely be an issue. ErrKeyTooLarge - // ErrValueTooLarge indicates an attmpt to insert a value that is larger + // ErrValueTooLarge indicates an attempt to insert a value that is larger // than max allowed value size. The max key size depends on the // specific backend driver being used. ErrValueTooLarge diff --git a/database/ffldb/driver.go b/database/ffldb/driver.go index 28ab8277e9..01290bf09a 100644 --- a/database/ffldb/driver.go +++ b/database/ffldb/driver.go @@ -78,7 +78,7 @@ func init() { UseLogger: useLogger, } if err := database.RegisterDriver(driver); err != nil { - panic(fmt.Sprintf("Failed to regiser database driver '%s': %v", + panic(fmt.Sprintf("Failed to register database driver '%s': %v", dbType, err)) } } diff --git a/database/ffldb/interface_test.go b/database/ffldb/interface_test.go index b0f275c5de..36db769b01 100644 --- a/database/ffldb/interface_test.go +++ b/database/ffldb/interface_test.go @@ -255,7 +255,7 @@ func testDeleteValues(tc *testContext, bucket database.Bucket, values []keyPair) return true } -// testCursorInterface ensures the cursor itnerface is working properly by +// testCursorInterface ensures the cursor interface is working properly by // exercising all of its functions on the passed bucket. func testCursorInterface(tc *testContext, bucket database.Bucket) bool { // Ensure a cursor can be obtained for the bucket. @@ -639,7 +639,7 @@ func rollbackOnPanic(t *testing.T, tx database.Tx) { func testMetadataManualTxInterface(tc *testContext) bool { // populateValues tests that populating values works as expected. // - // When the writable flag is false, a read-only tranasction is created, + // When the writable flag is false, a read-only transaction is created, // standard bucket tests for read-only transactions are performed, and // the Commit function is checked to ensure it fails as expected. // diff --git a/database/ffldb/whitebox_test.go b/database/ffldb/whitebox_test.go index cc7c13d45f..cac4984077 100644 --- a/database/ffldb/whitebox_test.go +++ b/database/ffldb/whitebox_test.go @@ -218,7 +218,7 @@ func TestCornerCases(t *testing.T) { ldb := idb.(*db).cache.ldb ldb.Close() - // Ensure initilization errors in the underlying database work as + // Ensure initialization errors in the underlying database work as // expected. testName = "initDB: reinitialization" wantErrCode = database.ErrDbNotOpen diff --git a/database/interface.go b/database/interface.go index 7efc7c55f6..7c4dd85122 100644 --- a/database/interface.go +++ b/database/interface.go @@ -390,7 +390,7 @@ type Tx interface { FetchBlockRegions(regions []BlockRegion) ([][]byte, error) // PruneBlocks deletes the block files until it reaches the target size - // (specificed in bytes). + // (specified in bytes). // // The interface contract guarantees at least the following errors will // be returned (other implementation-specific errors are possible): diff --git a/docs/json_rpc_api.md b/docs/json_rpc_api.md index fc32040da7..1999a6c245 100644 --- a/docs/json_rpc_api.md +++ b/docs/json_rpc_api.md @@ -472,7 +472,7 @@ Example Return|`{`
        `"bytes": 310768,`
        `"size": |---|---| |Method|help| |Parameters|1. command (string, optional) - the command to get help for| -|Description|Returns a list of all commands or help for a specified command.
      When no `command` parameter is specified, a list of avaialable commands is returned
      When `command` is a valid method, the help text for that method is returned.| +|Description|Returns a list of all commands or help for a specified command.
      When no `command` parameter is specified, a list of available commands is returned
      When `command` is a valid method, the help text for that method is returned.| |Returns|string| |Example Return|getblockcount
      Returns a numeric for the number of blocks in the longest block chain.| [Return to Overview](#MethodOverview)
      diff --git a/log.go b/log.go index 71accc7c9c..5707d7c23a 100644 --- a/log.go +++ b/log.go @@ -36,7 +36,7 @@ func (logWriter) Write(p []byte) (n int, err error) { return len(p), nil } -// Loggers per subsystem. A single backend logger is created and all subsytem +// Loggers per subsystem. A single backend logger is created and all subsystem // loggers created from it will write to the backend. When adding new // subsystems, add the subsystem logger variable here and to the // subsystemLoggers map. diff --git a/mining/mining.go b/mining/mining.go index 7905dade76..131c1207df 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -861,7 +861,7 @@ mempoolLoop: }, nil } -// AddWitnessCommitment adds the witness commitment as an OP_RETURN outpout +// AddWitnessCommitment adds the witness commitment as an OP_RETURN output // within the coinbase tx. The raw commitment is returned. func AddWitnessCommitment(coinbaseTx *btcutil.Tx, blockTxns []*btcutil.Tx) []byte { diff --git a/mining/policy.go b/mining/policy.go index 6213c2b336..8ddd575462 100644 --- a/mining/policy.go +++ b/mining/policy.go @@ -112,7 +112,7 @@ func CalcPriority(tx *wire.MsgTx, utxoView *blockchain.UtxoViewpoint, nextBlockH // A compressed pubkey pay-to-script-hash redemption with a maximum len // signature is of the form: // [OP_DATA_73 <73-byte sig> + OP_DATA_35 + {OP_DATA_33 - // <33 byte compresed pubkey> + OP_CHECKSIG}] + // <33 byte compressed pubkey> + OP_CHECKSIG}] // // Thus 1 + 73 + 1 + 1 + 33 + 1 = 110 overhead := 0 diff --git a/peer/example_test.go b/peer/example_test.go index d4662a2b4c..850557b877 100644 --- a/peer/example_test.go +++ b/peer/example_test.go @@ -16,7 +16,7 @@ import ( ) // mockRemotePeer creates a basic inbound peer listening on the simnet port for -// use with Example_peerConnection. It does not return until the listner is +// use with Example_peerConnection. It does not return until the listener is // active. func mockRemotePeer() error { // Configure peer to act as a simnet node that offers no services. diff --git a/peer/peer.go b/peer/peer.go index aa66cea98f..195fc0b4fe 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -744,7 +744,7 @@ func (p *Peer) LastRecv() time.Time { // LocalAddr returns the local address of the connection. // -// This function is safe fo concurrent access. +// This function is safe for concurrent access. func (p *Peer) LocalAddr() net.Addr { var localAddr net.Addr if atomic.LoadInt32(&p.connected) != 0 { diff --git a/rpcclient/chain_test.go b/rpcclient/chain_test.go index ba76078a16..ad1fb7aa2a 100644 --- a/rpcclient/chain_test.go +++ b/rpcclient/chain_test.go @@ -54,7 +54,7 @@ func TestUnmarshalGetBlockChainInfoResultSoftForks(t *testing.T) { for _, test := range tests { success := t.Run(test.name, func(t *testing.T) { - // We'll start by unmarshaling the JSON into a struct. + // We'll start by unmarshalling the JSON into a struct. // The SoftForks and UnifiedSoftForks field should not // be set yet, as they are unmarshaled within a // different function. @@ -226,7 +226,7 @@ func TestClientConnectedToWSServerRunner(t *testing.T) { response := <-ch if &expectedResponse != response { - t.Fatalf("received unexepcted response") + t.Fatalf("received unexpected response") } // ensure the goroutine created in this test exists, @@ -236,7 +236,7 @@ func TestClientConnectedToWSServerRunner(t *testing.T) { }, } - // since these tests rely on concurrency, ensure there is a resonable timeout + // since these tests rely on concurrency, ensure there is a reasonable timeout // that they should run within for _, testCase := range testTable { done := make(chan bool) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 39cfa3f474..67f908efaa 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -116,7 +116,7 @@ type jsonRequest struct { type Client struct { id uint64 // atomic, so must stay 64-bit aligned - // config holds the connection configuration assoiated with this client. + // config holds the connection configuration associated with this client. config *ConnConfig // chainParams holds the params for the chain that this client is using, @@ -351,7 +351,7 @@ type Response struct { } // result checks whether the unmarshaled response contains a non-nil error, -// returning an unmarshaled btcjson.RPCError (or an unmarshaling error) if so. +// returning an unmarshaled btcjson.RPCError (or an unmarshalling error) if so. // If the response is not an error, the raw bytes of the request are // returned for further unmashaling into specific result types. func (r rawResponse) result() (result []byte, err error) { @@ -433,7 +433,7 @@ func (c *Client) handleMessage(msg []byte) { // to have come from reading from the websocket connection in wsInHandler, // should be logged. func (c *Client) shouldLogReadError(err error) bool { - // No logging when the connetion is being forcibly disconnected. + // No logging when the connection is being forcibly disconnected. select { case <-c.shutdown: return false diff --git a/rpcclient/notify.go b/rpcclient/notify.go index 1c2814c313..1f5cd48075 100644 --- a/rpcclient/notify.go +++ b/rpcclient/notify.go @@ -472,13 +472,13 @@ func (c *Client) handleNotification(ntfn *rawNotification) { } } -// wrongNumParams is an error type describing an unparseable JSON-RPC -// notificiation due to an incorrect number of parameters for the +// wrongNumParams is an error type describing an unparsable JSON-RPC +// notification due to an incorrect number of parameters for the // expected notification type. The value is the number of parameters // of the invalid notification. type wrongNumParams int -// Error satisifies the builtin error interface. +// Error satisfies the builtin error interface. func (e wrongNumParams) Error() string { return fmt.Sprintf("wrong number of parameters (%d)", e) } @@ -599,7 +599,7 @@ func parseFilteredBlockDisconnectedParams(params []json.RawMessage) (int32, return 0, nil, err } - // Unmarshal second parmeter as a slice of bytes. + // Unmarshal second parameter as a slice of bytes. blockHeaderBytes, err := parseHexParam(params[1]) if err != nil { return 0, nil, err diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 9c95041fd4..86073c464f 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -719,7 +719,7 @@ func (c *Client) SignRawTransactionWithWallet3Async(tx *wire.MsgTx, // // This function should only used if a non-default signature hash type is // desired. Otherwise, see SignRawTransactionWithWallet if the RPC server already -// knows the input transactions, or SignRawTransactionWihWallet2 if it does not. +// knows the input transactions, or SignRawTransactionWithWallet2 if it does not. func (c *Client) SignRawTransactionWithWallet3(tx *wire.MsgTx, inputs []btcjson.RawTxWitnessInput, hashType SigHashType) (*wire.MsgTx, bool, error) { diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index 7b7e7212c9..b8063c136d 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2661,7 +2661,7 @@ func (c *Client) WalletCreateFundedPsbt( type FutureWalletProcessPsbtResult chan *Response // Receive waits for the Response promised by the future and returns an updated -// PSBT with signed inputs from the wallet and a boolen indicating if the +// PSBT with signed inputs from the wallet and a boolean indicating if the // transaction has a complete set of signatures. func (r FutureWalletProcessPsbtResult) Receive() (*btcjson.WalletProcessPsbtResult, error) { res, err := ReceiveFuture(r) diff --git a/rpcserver.go b/rpcserver.go index e5b8aac949..8fbb3e7352 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -846,7 +846,7 @@ func handleDecodeScript(s *rpcServer, cmd interface{}, closeChan <-chan struct{} // Get information about the script. // Ignore the error here since an error means the script couldn't parse - // and there is no additinal information about it anyways. + // and there is no additional information about it anyways. scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(script, s.cfg.ChainParams) addresses := make([]string, len(addrs)) @@ -3220,7 +3220,7 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan addressTxns := make([]retrievedTx, 0, numRequested) if reverse { // Transactions in the mempool are not in a block header yet, - // so the block header field in the retieved transaction struct + // so the block header field in the retrieved transaction struct // is left nil. mpTxns, mpSkipped := fetchMempoolTxnsForAddress(s, addr, uint32(numToSkip), uint32(numRequested)) @@ -3274,7 +3274,7 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan // order and the number of results is still under the number requested. if !reverse && len(addressTxns) < numRequested { // Transactions in the mempool are not in a block header yet, - // so the block header field in the retieved transaction struct + // so the block header field in the retrieved transaction struct // is left nil. mpTxns, mpSkipped := fetchMempoolTxnsForAddress(s, addr, uint32(numToSkip)-numSkipped, uint32(numRequested- @@ -4336,7 +4336,7 @@ func (s *rpcServer) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin // change the read deadline for the new connection and having one breaks // long polling. However, not having a read deadline on the initial // connection would mean clients can connect and idle forever. Thus, - // hijack the connecton from the HTTP server, clear the read deadline, + // hijack the connection from the HTTP server, clear the read deadline, // and handle writing the response manually. hj, ok := w.(http.Hijacker) if !ok { @@ -4359,7 +4359,7 @@ func (s *rpcServer) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin // Attempt to parse the raw body into a JSON-RPC request. // Setup a close notifier. Since the connection is hijacked, - // the CloseNotifer on the ResponseWriter is not available. + // the CloseNotifier on the ResponseWriter is not available. closeChan := make(chan struct{}, 1) go func() { _, err = conn.Read(make([]byte, 1)) @@ -4409,7 +4409,7 @@ func (s *rpcServer) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin // Btcd does not respond to any request without and "id" or "id":null, // regardless the indicated JSON-RPC protocol version unless RPC quirks // are enabled. With RPC quirks enabled, such requests will be responded - // to if the reqeust does not indicate JSON-RPC version. + // to if the request does not indicate JSON-RPC version. // // RPC quirks can be enabled by the user to avoid compatibility issues // with software relying on Core's behavior. diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 0cc384db2c..1f8451a530 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -376,7 +376,7 @@ var helpDescsEnUS = map[string]string{ // GetCurrentNetCmd help. "getcurrentnet--synopsis": "Get bitcoin network the server is running on.", - "getcurrentnet--result0": "The network identifer", + "getcurrentnet--result0": "The network identifier", // GetDifficultyCmd help. "getdifficulty--synopsis": "Returns the proof-of-work difficulty as a multiple of the minimum difficulty.", diff --git a/rpcwebsocket.go b/rpcwebsocket.go index aedbcf90b6..592ad1f398 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -132,8 +132,8 @@ type wsNotificationManager struct { queueNotification chan interface{} // notificationMsgs feeds notificationHandler with notifications - // and client (un)registeration requests from a queue as well as - // registeration and unregisteration requests from clients. + // and client (un)registration requests from a queue as well as + // registration and unregistration requests from clients. notificationMsgs chan interface{} // Access channel for current number of connected clients. @@ -1236,7 +1236,7 @@ type wsResponse struct { // requested notifications to all connected websocket clients. Inbound // messages are read via the inHandler goroutine and generally dispatched to // their own handler. However, certain potentially long-running operations such -// as rescans, are sent to the asyncHander goroutine and are limited to one at a +// as rescans, are sent to the asyncHandler goroutine and are limited to one at a // time. There are two outbound message types - one for responding to client // requests and another for async notifications. Responses to client requests // use SendMessage which employs a buffered channel thereby limiting the number @@ -2144,7 +2144,7 @@ func handleNotifySpent(wsc *wsClient, icmd interface{}) (interface{}, error) { return nil, nil } -// handleNotifyNewTransations implements the notifynewtransactions command +// handleNotifyNewTransactions implements the notifynewtransactions command // extension for websocket connections. func handleNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface{}, error) { cmd, ok := icmd.(*btcjson.NotifyNewTransactionsCmd) @@ -2157,7 +2157,7 @@ func handleNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface{}, return nil, nil } -// handleStopNotifyNewTransations implements the stopnotifynewtransactions +// handleStopNotifyNewTransactions implements the stopnotifynewtransactions // command extension for websocket connections. func handleStopNotifyNewTransactions(wsc *wsClient, icmd interface{}) (interface{}, error) { wsc.server.ntfnMgr.UnregisterNewMempoolTxsUpdates(wsc) @@ -2724,7 +2724,7 @@ fetchRange: // was any) still exists in the database. If it // doesn't, we error. // - // A goto is used to branch executation back to + // A goto is used to branch execution back to // before the range was evaluated, as it must be // reevaluated for the new hashList. minBlock += int32(i) diff --git a/service_windows.go b/service_windows.go index 378c9204f8..01edf3db77 100644 --- a/service_windows.go +++ b/service_windows.go @@ -153,7 +153,7 @@ func installService() error { // Support events to the event log using the standard "standard" Windows // EventCreate.exe message file. This allows easy logging of custom - // messges instead of needing to create our own message catalog. + // messages instead of needing to create our own message catalog. eventlog.Remove(svcName) eventsSupported := uint32(eventlog.Error | eventlog.Warning | eventlog.Info) return eventlog.InstallAsEventCreate(svcName, eventsSupported) diff --git a/txscript/data/script_tests.json b/txscript/data/script_tests.json index 5c054ed3e8..bd3b4e3125 100644 --- a/txscript/data/script_tests.json +++ b/txscript/data/script_tests.json @@ -666,7 +666,7 @@ ["0 0x02 0x0000 0", "CHECKMULTISIGVERIFY 1", "", "OK"], ["While not really correctly DER encoded, the empty signature is allowed by"], -["STRICTENC to provide a compact way to provide a delibrately invalid signature."], +["STRICTENC to provide a compact way to provide a deliberately invalid signature."], ["0", "0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 CHECKSIG NOT", "STRICTENC", "OK"], ["0 0", "1 0x21 0x02865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac0 1 CHECKMULTISIG NOT", "STRICTENC", "OK"], diff --git a/txscript/data/tx_invalid.json b/txscript/data/tx_invalid.json index db465109aa..85ceac145f 100644 --- a/txscript/data/tx_invalid.json +++ b/txscript/data/tx_invalid.json @@ -199,7 +199,7 @@ [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], -["By-time locks, with argument just beyond txin.nSequence (but within numerical boundries)"], +["By-time locks, with argument just beyond txin.nSequence (but within numerical boundaries)"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194305 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], diff --git a/txscript/engine.go b/txscript/engine.go index 30206152b8..1458728f72 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -1414,7 +1414,7 @@ func (vm *Engine) checkSignatureEncoding(sig []byte) error { func getStack(stack *stack) [][]byte { array := make([][]byte, stack.Depth()) for i := range array { - // PeekByteArry can't fail due to overflow, already checked + // PeekByteArray can't fail due to overflow, already checked array[len(array)-i-1], _ = stack.PeekByteArray(int32(i)) } return array diff --git a/txscript/engine_debug_test.go b/txscript/engine_debug_test.go index 5ebfe3f3cf..aa7283e22f 100644 --- a/txscript/engine_debug_test.go +++ b/txscript/engine_debug_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" ) -// TestDebugEngine checks that the StepCallbck called during debug script +// TestDebugEngine checks that the StepCallback called during debug script // execution contains the expected data. func TestDebugEngine(t *testing.T) { t.Parallel() diff --git a/txscript/engine_test.go b/txscript/engine_test.go index 51a899be33..c88d27a60e 100644 --- a/txscript/engine_test.go +++ b/txscript/engine_test.go @@ -123,12 +123,12 @@ func TestCheckErrorCondition(t *testing.T) { t.Fatalf("failed to step %dth time: %v", i, err) } if done { - t.Fatalf("finshed early on %dth time", i) + t.Fatalf("finished early on %dth time", i) } err = vm.CheckErrorCondition(false) if !IsErrorCode(err, ErrScriptUnfinished) { - t.Fatalf("got unexepected error %v on %dth iteration", + t.Fatalf("got unexpected error %v on %dth iteration", err, i) } } diff --git a/txscript/error.go b/txscript/error.go index 68bea7e879..a5ad0f2c4d 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -267,7 +267,7 @@ const ( ErrPubKeyType // ErrCleanStack is returned when the ScriptVerifyCleanStack flag - // is set, and after evalution, the stack does not contain only a + // is set, and after evaluation, the stack does not contain only a // single element. ErrCleanStack diff --git a/txscript/script.go b/txscript/script.go index 18723067ee..13d6c42711 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -244,7 +244,7 @@ func isCanonicalPush(opcode byte, data []byte) bool { // removeOpcodeByData will return the script minus any opcodes that perform a // canonical push of data that contains the passed data to remove. This // function assumes it is provided a version 0 script as any future version of -// script should avoid this functionality since it is unncessary due to the +// script should avoid this functionality since it is unnecessary due to the // signature scripts not being part of the witness-free transaction hash. // // WARNING: This will return the passed script unmodified unless a modification diff --git a/txscript/sigvalidate.go b/txscript/sigvalidate.go index 0bd00c326d..bda612a4e0 100644 --- a/txscript/sigvalidate.go +++ b/txscript/sigvalidate.go @@ -331,7 +331,7 @@ func newTaprootSigVerifier(pkBytes []byte, fullSigBytes []byte, // key and signature, and the passed sigHash as the message digest. func (t *taprootSigVerifier) verifySig(sigHash []byte) bool { // At this point, we can check to see if this signature is already - // included in the sigCcahe and is valid or not (if one was passed in). + // included in the sigCache and is valid or not (if one was passed in). cacheKey, _ := chainhash.NewHash(sigHash) if t.sigCache != nil { if t.sigCache.Exists(*cacheKey, t.fullSigBytes, t.pkBytes) { diff --git a/txscript/standard_test.go b/txscript/standard_test.go index 283e2ccb7b..4993a65260 100644 --- a/txscript/standard_test.go +++ b/txscript/standard_test.go @@ -884,7 +884,7 @@ func TestMultiSigScript(t *testing.T) { } } -// TestCalcMultiSigStats ensures the CalcMutliSigStats function returns the +// TestCalcMultiSigStats ensures the CalcMultiSigStats function returns the // expected errors. func TestCalcMultiSigStats(t *testing.T) { t.Parallel() diff --git a/txscript/taproot.go b/txscript/taproot.go index 003eb19ae3..3776bf37a3 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -255,7 +255,7 @@ func ComputeTaprootOutputKey(pubKey *btcec.PublicKey, scriptRoot, ) - // With the tap tweek computed, we'll need to convert the merkle root + // With the tap tweak computed, we'll need to convert the merkle root // into something in the domain we can manipulate: a scalar value mod // N. var tweakScalar btcec.ModNScalar diff --git a/txscript/taproot_test.go b/txscript/taproot_test.go index 01b3780e9c..9c5bb573a4 100644 --- a/txscript/taproot_test.go +++ b/txscript/taproot_test.go @@ -224,7 +224,7 @@ func TestTaprootTweakNoMutation(t *testing.T) { return false } - // We shuold be able to re-derive the private key from raw + // We should be able to re-derive the private key from raw // bytes and have that match up again. privKeyCopy, _ := btcec.PrivKeyFromBytes(privBytes[:]) if *privKey != *privKeyCopy { diff --git a/wire/bench_test.go b/wire/bench_test.go index d19dd775f2..2f63fa30a6 100644 --- a/wire/bench_test.go +++ b/wire/bench_test.go @@ -549,7 +549,7 @@ func BenchmarkDeserializeTxSmall(b *testing.B) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Prevous output index + 0xff, 0xff, 0xff, 0xff, // Previous output index 0x07, // Varint for length of signature script 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script 0xff, 0xff, 0xff, 0xff, // Sequence @@ -671,7 +671,7 @@ func BenchmarkSerializeTxSmall(b *testing.B) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Prevous output index + 0xff, 0xff, 0xff, 0xff, // Previous output index 0x07, // Varint for length of signature script 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script 0xff, 0xff, 0xff, 0xff, // Sequence diff --git a/wire/fixedIO_test.go b/wire/fixedIO_test.go index ccd67ae411..0952a9b476 100644 --- a/wire/fixedIO_test.go +++ b/wire/fixedIO_test.go @@ -9,7 +9,7 @@ import ( "io" ) -// fixedWriter implements the io.Writer interface and intentially allows +// fixedWriter implements the io.Writer interface and intentionally allows // testing of error paths by forcing short writes. type fixedWriter struct { b []byte @@ -44,7 +44,7 @@ func newFixedWriter(max int) io.Writer { return &fw } -// fixedReader implements the io.Reader interface and intentially allows +// fixedReader implements the io.Reader interface and intentionally allows // testing of error paths by forcing short reads. type fixedReader struct { buf []byte diff --git a/wire/msgalert.go b/wire/msgalert.go index 71c4e220fe..b99ac89de9 100644 --- a/wire/msgalert.go +++ b/wire/msgalert.go @@ -83,7 +83,7 @@ const maxAlertSize = MaxMessagePayload - maxSignatureSize - MaxVarIntPayload - 1 // fit into a maximum size alert. // // maxAlertSize = fixedAlertSize + max(SetCancel) + max(SetSubVer) + 3*(string) -// for caculating maximum number of cancel IDs, set all other var sizes to 0 +// for calculating maximum number of cancel IDs, set all other var sizes to 0 // maxAlertSize = fixedAlertSize + (MaxVarIntPayload-1) + x*sizeOf(int32) // x = (maxAlertSize - fixedAlertSize - MaxVarIntPayload + 1) / 4 const maxCountSetCancel = (maxAlertSize - fixedAlertSize - MaxVarIntPayload + 1) / 4 @@ -92,7 +92,7 @@ const maxCountSetCancel = (maxAlertSize - fixedAlertSize - MaxVarIntPayload + 1) // fit into a maximum size alert. // // maxAlertSize = fixedAlertSize + max(SetCancel) + max(SetSubVer) + 3*(string) -// for caculating maximum number of subversions, set all other var sizes to 0 +// for calculating maximum number of subversions, set all other var sizes to 0 // maxAlertSize = fixedAlertSize + (MaxVarIntPayload-1) + x*sizeOf(string) // x = (maxAlertSize - fixedAlertSize - MaxVarIntPayload + 1) / sizeOf(string) // subversion would typically be something like "/Satoshi:0.7.2/" (15 bytes) diff --git a/wire/msgblock.go b/wire/msgblock.go index d065e85c52..59dbbb1c06 100644 --- a/wire/msgblock.go +++ b/wire/msgblock.go @@ -245,7 +245,7 @@ func (msg *MsgBlock) Serialize(w io.Writer) error { // SerializeNoWitness encodes a block to w using an identical format to // Serialize, with all (if any) witness data stripped from all transactions. -// This method is provided in additon to the regular Serialize, in order to +// This method is provided in addition to the regular Serialize, in order to // allow one to selectively encode transaction witness data to non-upgraded // peers which are unaware of the new encoding. func (msg *MsgBlock) SerializeNoWitness(w io.Writer) error { diff --git a/wire/msgblock_test.go b/wire/msgblock_test.go index 2a861b208b..f0e938697c 100644 --- a/wire/msgblock_test.go +++ b/wire/msgblock_test.go @@ -562,7 +562,7 @@ var blockOneBytes = []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Prevous output index + 0xff, 0xff, 0xff, 0xff, // Previous output index 0x07, // Varint for length of signature script 0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script (coinbase) 0xff, 0xff, 0xff, 0xff, // Sequence diff --git a/wire/msggetheaders.go b/wire/msggetheaders.go index f49e4c0dd4..38e5c6bfcd 100644 --- a/wire/msggetheaders.go +++ b/wire/msggetheaders.go @@ -23,7 +23,7 @@ import ( // // The algorithm for building the block locator hashes should be to add the // hashes in reverse order until you reach the genesis block. In order to keep -// the list of locator hashes to a resonable number of entries, first add the +// the list of locator hashes to a reasonable number of entries, first add the // most recent 10 block hashes, then double the step each loop iteration to // exponentially decrease the number of hashes the further away from head and // closer to the genesis block you get. diff --git a/wire/msgtx_test.go b/wire/msgtx_test.go index 1b3bfd4eec..beba569b0f 100644 --- a/wire/msgtx_test.go +++ b/wire/msgtx_test.go @@ -672,7 +672,7 @@ func TestTxOverflowErrors(t *testing.T) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Prevous output index + 0xff, 0xff, 0xff, 0xff, // Previous output index 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Varint for length of signature script }, pver, BaseEncoding, txVer, &MessageError{}, @@ -688,7 +688,7 @@ func TestTxOverflowErrors(t *testing.T) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Prevous output index + 0xff, 0xff, 0xff, 0xff, // Previous output index 0x00, // Varint for length of signature script 0xff, 0xff, 0xff, 0xff, // Sequence 0x01, // Varint for number of output transactions @@ -733,7 +733,7 @@ func TestTxSerializeSizeStripped(t *testing.T) { in *MsgTx // Tx to encode size int // Expected serialized size }{ - // No inputs or outpus. + // No inputs or outputs. {noTx, 10}, // Transcaction with an input and an output. @@ -938,7 +938,7 @@ var multiTxEncoded = []byte{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash - 0xff, 0xff, 0xff, 0xff, // Prevous output index + 0xff, 0xff, 0xff, 0xff, // Previous output index 0x07, // Varint for length of signature script 0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62, // Signature script 0xff, 0xff, 0xff, 0xff, // Sequence diff --git a/wire/msgversion.go b/wire/msgversion.go index 3077f12760..957bae395a 100644 --- a/wire/msgversion.go +++ b/wire/msgversion.go @@ -46,7 +46,7 @@ type MsgVersion struct { // connections. Nonce uint64 - // The user agent that generated messsage. This is a encoded as a varString + // The user agent that generated message. This is a encoded as a varString // on the wire. This has a max length of MaxUserAgentLen. UserAgent string From 6ae24a06936a6ffaa8d01e6fc416e85c3574616d Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Thu, 4 Jan 2024 11:40:16 +0800 Subject: [PATCH 0981/1056] mining: remove trailing continue --- mining/mining.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/mining/mining.go b/mining/mining.go index 7905dade76..bdfc8763fa 100644 --- a/mining/mining.go +++ b/mining/mining.go @@ -563,9 +563,6 @@ mempoolLoop: } prioItem.dependsOn[*originHash] = struct{}{} - // Skip the check below. We already know the - // referenced transaction is available. - continue } } From bbb6967247309eca4024c14c39f702940cc7d664 Mon Sep 17 00:00:00 2001 From: bruwbird Date: Thu, 21 Mar 2024 13:08:18 +0900 Subject: [PATCH 0982/1056] btcclient+btcjson: feeRate to BTC/kvB defaultMaxFeeRate was set to 1e8 / 10(sat/kb) as a parameter. But BTC/kvB is the expected value, so the units was wrong. This commit updates defaultMaxFeeRate to BTC/kvB and sets it to 0.1, which is the default value of Bitcoin Core. This commit also updates the comment to reflect the change. Because maxFeeRate sanity check has been added in bitcoin core v27.0 or later, sendrawtransaction cannot be executed without this change. --- btcjson/chainsvrcmds.go | 5 +++-- btcjson/chainsvrcmds_test.go | 8 ++++---- rpcclient/rawtransactions.go | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 956b4db604..fb690a19c3 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -862,7 +862,7 @@ func (a *AllowHighFeesOrMaxFeeRate) UnmarshalJSON(data []byte) error { case bool: a.Value = Bool(v) case float64: - a.Value = Int32(int32(v)) + a.Value = Float64(v) default: return fmt.Errorf("invalid allowhighfees or maxfeerate value: "+ "%v", unmarshalled) @@ -893,9 +893,10 @@ func NewSendRawTransactionCmd(hexTx string, allowHighFees *bool) *SendRawTransac // NewSendRawTransactionCmd returns a new instance which can be used to issue a // sendrawtransaction JSON-RPC command to a bitcoind node. +// maxFeeRate is the maximum fee rate for the transaction in BTC/kvB. // // A 0 maxFeeRate indicates that a maximum fee rate won't be enforced. -func NewBitcoindSendRawTransactionCmd(hexTx string, maxFeeRate int32) *SendRawTransactionCmd { +func NewBitcoindSendRawTransactionCmd(hexTx string, maxFeeRate float64) *SendRawTransactionCmd { return &SendRawTransactionCmd{ HexTx: hexTx, FeeSetting: &AllowHighFeesOrMaxFeeRate{ diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index d3143a528c..38113a687e 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -1257,16 +1257,16 @@ func TestChainSvrCmds(t *testing.T) { { name: "sendrawtransaction optional, bitcoind >= 0.19.0", newCmd: func() (interface{}, error) { - return btcjson.NewCmd("sendrawtransaction", "1122", &btcjson.AllowHighFeesOrMaxFeeRate{Value: btcjson.Int32(1234)}) + return btcjson.NewCmd("sendrawtransaction", "1122", &btcjson.AllowHighFeesOrMaxFeeRate{Value: btcjson.Float64(0.1234)}) }, staticCmd: func() interface{} { - return btcjson.NewBitcoindSendRawTransactionCmd("1122", 1234) + return btcjson.NewBitcoindSendRawTransactionCmd("1122", 0.1234) }, - marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122",1234],"id":1}`, + marshalled: `{"jsonrpc":"1.0","method":"sendrawtransaction","params":["1122",0.1234],"id":1}`, unmarshalled: &btcjson.SendRawTransactionCmd{ HexTx: "1122", FeeSetting: &btcjson.AllowHighFeesOrMaxFeeRate{ - Value: btcjson.Int32(1234), + Value: btcjson.Float64(0.1234), }, }, }, diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 9c95041fd4..5834ccf202 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -17,9 +17,9 @@ import ( ) const ( - // defaultMaxFeeRate is the default maximum fee rate in sat/KB enforced + // defaultMaxFeeRate is the default maximum fee rate in BTC/kvB enforced // by bitcoind v0.19.0 or after for transaction broadcast. - defaultMaxFeeRate = btcutil.SatoshiPerBitcoin / 10 + defaultMaxFeeRate float64 = 0.1 ) // SigHashType enumerates the available signature hashing types that the @@ -365,7 +365,7 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut if version.SupportUnifiedSoftForks() { // Using a 0 MaxFeeRate is interpreted as a maximum fee rate not // being enforced by bitcoind. - var maxFeeRate int32 + var maxFeeRate float64 if !allowHighFees { maxFeeRate = defaultMaxFeeRate } From 80b27f547157399c64b1717a4a528871bbfb7f5b Mon Sep 17 00:00:00 2001 From: bruwbird Date: Sat, 23 Mar 2024 11:14:22 +0900 Subject: [PATCH 0983/1056] btcclient+btcjson: add type alias for BTC/kvB Added type alias BTC/kvB to explicitly indicate that it represents the fee in BTC for a transaction size of 1 kB. Because bitcoind uses its own fee rate type (BTC/kvB instead of sat/kWU we use in lnd), define the type in btcjson package, as it's the only place where we actually use BTC/kvB. --- btcjson/chainsvrcmds.go | 14 +++++++++----- rpcclient/rawtransactions.go | 8 ++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index fb690a19c3..22552e7bcd 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -16,6 +16,10 @@ import ( "github.com/btcsuite/btcd/wire" ) +// BTCPerkvB is the units used to represent Bitcoin transaction fees. +// This unit represents the fee in BTC for a transaction size of 1 kB. +type BTCPerkvB = float64 + // AddNodeSubCmd defines the type used in the addnode JSON-RPC command for the // sub command field. type AddNodeSubCmd string @@ -142,7 +146,7 @@ type FundRawTransactionOpts struct { ChangeType *ChangeType `json:"change_type,omitempty"` IncludeWatching *bool `json:"includeWatching,omitempty"` LockUnspents *bool `json:"lockUnspents,omitempty"` - FeeRate *float64 `json:"feeRate,omitempty"` // BTC/kB + FeeRate *BTCPerkvB `json:"feeRate,omitempty"` // BTC/kB SubtractFeeFromOutputs []int `json:"subtractFeeFromOutputs,omitempty"` Replaceable *bool `json:"replaceable,omitempty"` ConfTarget *int `json:"conf_target,omitempty"` @@ -822,7 +826,7 @@ func NewSearchRawTransactionsCmd(address string, verbose, skip, count *int, vinE } // AllowHighFeesOrMaxFeeRate defines a type that can either be the legacy -// allowhighfees boolean field or the new maxfeerate int field. +// allowhighfees boolean field or the new maxfeerate float64 field. type AllowHighFeesOrMaxFeeRate struct { Value interface{} } @@ -896,7 +900,7 @@ func NewSendRawTransactionCmd(hexTx string, allowHighFees *bool) *SendRawTransac // maxFeeRate is the maximum fee rate for the transaction in BTC/kvB. // // A 0 maxFeeRate indicates that a maximum fee rate won't be enforced. -func NewBitcoindSendRawTransactionCmd(hexTx string, maxFeeRate float64) *SendRawTransactionCmd { +func NewBitcoindSendRawTransactionCmd(hexTx string, maxFeeRate BTCPerkvB) *SendRawTransactionCmd { return &SendRawTransactionCmd{ HexTx: hexTx, FeeSetting: &AllowHighFeesOrMaxFeeRate{ @@ -1051,13 +1055,13 @@ type TestMempoolAcceptCmd struct { // Reject transactions whose fee rate is higher than the specified // value, expressed in BTC/kvB, optional, default="0.10". - MaxFeeRate float64 `json:"omitempty"` + MaxFeeRate BTCPerkvB `json:"omitempty"` } // NewTestMempoolAcceptCmd returns a new instance which can be used to issue a // testmempoolaccept JSON-RPC command. func NewTestMempoolAcceptCmd(rawTxns []string, - maxFeeRate float64) *TestMempoolAcceptCmd { + maxFeeRate BTCPerkvB) *TestMempoolAcceptCmd { return &TestMempoolAcceptCmd{ RawTxns: rawTxns, diff --git a/rpcclient/rawtransactions.go b/rpcclient/rawtransactions.go index 5834ccf202..609d2a5100 100644 --- a/rpcclient/rawtransactions.go +++ b/rpcclient/rawtransactions.go @@ -19,7 +19,7 @@ import ( const ( // defaultMaxFeeRate is the default maximum fee rate in BTC/kvB enforced // by bitcoind v0.19.0 or after for transaction broadcast. - defaultMaxFeeRate float64 = 0.1 + defaultMaxFeeRate btcjson.BTCPerkvB = 0.1 ) // SigHashType enumerates the available signature hashing types that the @@ -365,7 +365,7 @@ func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) Fut if version.SupportUnifiedSoftForks() { // Using a 0 MaxFeeRate is interpreted as a maximum fee rate not // being enforced by bitcoind. - var maxFeeRate float64 + var maxFeeRate btcjson.BTCPerkvB if !allowHighFees { maxFeeRate = defaultMaxFeeRate } @@ -915,7 +915,7 @@ func (r FutureTestMempoolAcceptResult) Receive() ( // // See TestMempoolAccept for the blocking version and more details. func (c *Client) TestMempoolAcceptAsync(txns []*wire.MsgTx, - maxFeeRate float64) FutureTestMempoolAcceptResult { + maxFeeRate btcjson.BTCPerkvB) FutureTestMempoolAcceptResult { // Due to differences in the testmempoolaccept API for different // backends, we'll need to inspect our version and construct the @@ -1010,7 +1010,7 @@ func (c *Client) TestMempoolAcceptAsync(txns []*wire.MsgTx, // // The maximum number of transactions allowed is 25. func (c *Client) TestMempoolAccept(txns []*wire.MsgTx, - maxFeeRate float64) ([]*btcjson.TestMempoolAcceptResult, error) { + maxFeeRate btcjson.BTCPerkvB) ([]*btcjson.TestMempoolAcceptResult, error) { return c.TestMempoolAcceptAsync(txns, maxFeeRate).Receive() } From 95330bc1bb33eaf21dd850b99bb3d84bcfa03237 Mon Sep 17 00:00:00 2001 From: xiaoxiangxianzi <164908047+xiaoxiangxianzi@users.noreply.github.com> Date: Wed, 27 Mar 2024 21:45:48 +0800 Subject: [PATCH 0984/1056] chore: fix some comments (#2146) Signed-off-by: xiaoxiangxianzi --- blockchain/chain.go | 2 +- btcutil/gcs/builder/builder.go | 2 +- btcutil/psbt/creator.go | 2 +- btcutil/psbt/utils.go | 2 +- mempool/mempool.go | 2 +- netsync/manager.go | 2 +- rpcwebsocket.go | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index c7e8b3c36e..7e06e5c77c 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -773,7 +773,7 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view // Flush the cache on every disconnect. Since the code for // reorganization modifies the database directly, the cache // will be left in an inconsistent state if we don't flush it - // prior to the dbPutUtxoView that happends below. + // prior to the dbPutUtxoView that happens below. err = b.utxoCache.flush(dbTx, FlushRequired, state) if err != nil { return err diff --git a/btcutil/gcs/builder/builder.go b/btcutil/gcs/builder/builder.go index 4e952996c1..8e257b39fc 100644 --- a/btcutil/gcs/builder/builder.go +++ b/btcutil/gcs/builder/builder.go @@ -207,7 +207,7 @@ func (b *GCSBuilder) Build() (*gcs.Filter, error) { return nil, b.err } - // We'll ensure that all the paramaters we need to actually build the + // We'll ensure that all the parameters we need to actually build the // filter properly are set. if b.p == 0 { return nil, fmt.Errorf("p value is not set, cannot build") diff --git a/btcutil/psbt/creator.go b/btcutil/psbt/creator.go index a5f832e0dd..58b9a54488 100644 --- a/btcutil/psbt/creator.go +++ b/btcutil/psbt/creator.go @@ -17,7 +17,7 @@ const MinTxVersion = 1 // within the unsigned transaction. The values of nLockTime, nSequence (per // input) and transaction version (must be 1 of 2) must be specified here. Note // that the default nSequence value is wire.MaxTxInSequenceNum. Referencing -// the PSBT BIP, this function serves the roles of teh Creator. +// the PSBT BIP, this function serves the roles of the Creator. func New(inputs []*wire.OutPoint, outputs []*wire.TxOut, version int32, nLockTime uint32, nSequences []uint32) (*Packet, error) { diff --git a/btcutil/psbt/utils.go b/btcutil/psbt/utils.go index 85bc82f529..0a9002798e 100644 --- a/btcutil/psbt/utils.go +++ b/btcutil/psbt/utils.go @@ -226,7 +226,7 @@ func serializeKVPairWithType(w io.Writer, kt uint8, keydata []byte, // getKey retrieves a single key - both the key type and the keydata (if // present) from the stream and returns the key type as an integer, or -1 if -// the key was of zero length. This integer is is used to indicate the presence +// the key was of zero length. This integer is used to indicate the presence // of a separator byte which indicates the end of a given key-value pair list, // and the keydata as a byte slice or nil if none is present. func getKey(r io.Reader) (int, []byte, error) { diff --git a/mempool/mempool.go b/mempool/mempool.go index db04f619a5..af3830aeb3 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -1635,7 +1635,7 @@ func (mp *TxPool) validateStandardness(tx *btcutil.Tx, nextBlockHeight int32, } // validateSigCost checks the cost to run the signature operations to make sure -// the number of singatures are sane. +// the number of signatures are sane. func (mp *TxPool) validateSigCost(tx *btcutil.Tx, utxoView *blockchain.UtxoViewpoint) error { diff --git a/netsync/manager.go b/netsync/manager.go index b1a4db4d13..3215a86ace 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -1136,7 +1136,7 @@ func (sm *SyncManager) haveInventory(invVect *wire.InvVect) (bool, error) { return false, nil } - // The requested inventory is is an unsupported type, so just claim + // The requested inventory is an unsupported type, so just claim // it is known to avoid requesting it. return true, nil } diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 592ad1f398..02f59d58bf 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -228,7 +228,7 @@ func (m *wsNotificationManager) NotifyBlockDisconnected(block *btcutil.Block) { // NotifyMempoolTx passes a transaction accepted by mempool to the // notification manager for transaction notification processing. If -// isNew is true, the tx is is a new transaction, rather than one +// isNew is true, the tx is a new transaction, rather than one // added to the mempool during a reorg. func (m *wsNotificationManager) NotifyMempoolTx(tx *btcutil.Tx, isNew bool) { n := ¬ificationTxAcceptedByMempool{ From 9851d96c0696a11aa211d6d54b76aa7fa87f7b13 Mon Sep 17 00:00:00 2001 From: snoppy Date: Fri, 29 Mar 2024 10:21:29 +0800 Subject: [PATCH 0985/1056] chore: fix typos --- btcutil/hdkeychain/README.md | 2 +- mempool/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/btcutil/hdkeychain/README.md b/btcutil/hdkeychain/README.md index 33eba3ce16..2101ed4d81 100644 --- a/btcutil/hdkeychain/README.md +++ b/btcutil/hdkeychain/README.md @@ -17,7 +17,7 @@ report. - Full BIP0032 implementation - Single type for private and public extended keys -- Convenient cryptograpically secure seed generation +- Convenient cryptographically secure seed generation - Simple creation of master nodes - Support for multi-layer derivation - Easy serialization and deserialization for both private and public extended diff --git a/mempool/README.md b/mempool/README.md index 5f1e4a4cd1..85c03993c2 100644 --- a/mempool/README.md +++ b/mempool/README.md @@ -7,7 +7,7 @@ mempool Package mempool provides a policy-enforced pool of unmined bitcoin transactions. -A key responsbility of the bitcoin network is mining user-generated transactions +A key responsibility of the bitcoin network is mining user-generated transactions into blocks. In order to facilitate this, the mining process relies on having a readily-available source of transactions to include in a block that is being solved. From 31647e46ecbac0dfc4b6432bd3d3cc0136193740 Mon Sep 17 00:00:00 2001 From: ffranr Date: Tue, 2 Apr 2024 19:27:10 +0100 Subject: [PATCH 0986/1056] btcec: add missing doc comments --- btcec/pubkey.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index c4b0680a7a..bff1b24b5f 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -10,6 +10,8 @@ import ( // These constants define the lengths of serialized public keys. const ( + // PubKeyBytesLenCompressed is the bytes length of a serialized compressed + // public key. PubKeyBytesLenCompressed = 33 ) From 665eeb52b19fce48a025afcde01ffdd781672299 Mon Sep 17 00:00:00 2001 From: ffranr Date: Tue, 2 Apr 2024 19:36:47 +0100 Subject: [PATCH 0987/1056] btcec: add new type `SerializedKey` This commit adds a new type called `SerializedKey`. A serialized type is useful when using public keys as map keys. This is because functionally identical public keys can have different internal representations. These differences would cause the map to treat them as different keys. --- btcec/pubkey.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/btcec/pubkey.go b/btcec/pubkey.go index bff1b24b5f..2c3a5ccbef 100644 --- a/btcec/pubkey.go +++ b/btcec/pubkey.go @@ -51,3 +51,38 @@ type PublicKey = secp.PublicKey func NewPublicKey(x, y *FieldVal) *PublicKey { return secp.NewPublicKey(x, y) } + +// SerializedKey is a type for representing a public key in its compressed +// serialized form. +// +// NOTE: This type is useful when using public keys as keys in maps. +type SerializedKey [PubKeyBytesLenCompressed]byte + +// ToPubKey returns the public key parsed from the serialized key. +func (s SerializedKey) ToPubKey() (*PublicKey, error) { + return ParsePubKey(s[:]) +} + +// SchnorrSerialized returns the Schnorr serialized, x-only 32-byte +// representation of the serialized key. +func (s SerializedKey) SchnorrSerialized() [32]byte { + var serializedSchnorr [32]byte + copy(serializedSchnorr[:], s[1:]) + return serializedSchnorr +} + +// CopyBytes returns a copy of the underlying array as a byte slice. +func (s SerializedKey) CopyBytes() []byte { + c := make([]byte, PubKeyBytesLenCompressed) + copy(c, s[:]) + + return c +} + +// ToSerialized serializes a public key into its compressed form. +func ToSerialized(pubKey *PublicKey) SerializedKey { + var serialized SerializedKey + copy(serialized[:], pubKey.SerializeCompressed()) + + return serialized +} From c9c87951608158a5cb75c37bfa96a60eefcdb6eb Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 8 Apr 2024 17:45:24 +0900 Subject: [PATCH 0988/1056] blockchain: add Equals method to blockNode Helper function for the added IsAncestor in the follow up commit. Returns true if all the fields (except for parent and ancestor) are equal. --- blockchain/blockindex.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index ca3235f79f..9bfa3348cd 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -135,6 +135,20 @@ func newBlockNode(blockHeader *wire.BlockHeader, parent *blockNode) *blockNode { return &node } +// Equals compares all the fields of the block node except for the parent and +// ancestor and returns true if they're equal. +func (node *blockNode) Equals(other *blockNode) bool { + return node.hash == other.hash && + node.workSum.Cmp(other.workSum) == 0 && + node.height == other.height && + node.version == other.version && + node.bits == other.bits && + node.nonce == other.nonce && + node.timestamp == other.timestamp && + node.merkleRoot == other.merkleRoot && + node.status == other.status +} + // Header constructs a block header from the node and returns it. // // This function is safe for concurrent access. From bc6396ddfd097f93e2eaf0d1346ab80735eaa169 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 19 Dec 2022 14:57:33 +0900 Subject: [PATCH 0989/1056] blockchain: Add IsAncestor method to blockNode IsAncestor() provides functionality for testing if a block node is an ancestor of anther block node. --- blockchain/blockindex.go | 22 ++++++ blockchain/chain_test.go | 156 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/blockchain/blockindex.go b/blockchain/blockindex.go index 9bfa3348cd..5273cb488b 100644 --- a/blockchain/blockindex.go +++ b/blockchain/blockindex.go @@ -274,6 +274,28 @@ func (node *blockNode) RelativeAncestorCtx(distance int32) HeaderCtx { return ancestor } +// IsAncestor returns if the other node is an ancestor of this block node. +func (node *blockNode) IsAncestor(otherNode *blockNode) bool { + // Return early as false if the otherNode is nil. + if otherNode == nil { + return false + } + + ancestor := node.Ancestor(otherNode.height) + if ancestor == nil { + return false + } + + // If the otherNode has the same height as me, then the returned + // ancestor will be me. Return false since I'm not an ancestor of me. + if node.height == ancestor.height { + return false + } + + // Return true if the fetched ancestor is other node. + return ancestor.Equals(otherNode) +} + // RelativeAncestor returns the ancestor block node a relative 'distance' blocks // before this node. This is equivalent to calling Ancestor with the node's // height minus provided distance. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index cd5c761bc4..259a643f3c 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -1155,3 +1155,159 @@ func TestChainTips(t *testing.T) { } } } + +func TestIsAncestor(t *testing.T) { + // Construct a synthetic block chain with a block index consisting of + // the following structure. + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + tip := tstTip + chain := newFakeChain(&chaincfg.MainNetParams) + branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 3) + for _, node := range branch0Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + chain.bestChain.SetTip(tip(branch0Nodes)) + + branch1Nodes := chainedNodes(chain.bestChain.Genesis(), 1) + for _, node := range branch1Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValid) + chain.index.AddNode(node) + } + + branch2Nodes := chainedNodes(chain.bestChain.Genesis(), 1) + for _, node := range branch2Nodes { + chain.index.SetStatusFlags(node, statusDataStored) + chain.index.SetStatusFlags(node, statusValidateFailed) + chain.index.AddNode(node) + } + + // Is 1 an ancestor of 3? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue := branch0Nodes[2].IsAncestor(branch0Nodes[0]) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. Node %s is an ancestor of node %s but got false", + branch0Nodes[0].hash.String(), branch0Nodes[2].hash.String()) + } + + // Is 1 an ancestor of 2? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch0Nodes[1].IsAncestor(branch0Nodes[0]) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. Node %s is an ancestor of node %s but got false", + branch0Nodes[0].hash.String(), branch0Nodes[1].hash.String()) + } + + // Is the genesis an ancestor of 1? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch0Nodes[0].IsAncestor(chain.bestChain.Genesis()) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. The genesis block is an ancestor of all blocks "+ + "but got false for node %s", + branch0Nodes[0].hash.String()) + } + + // Is the genesis an ancestor of 1a? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch1Nodes[0].IsAncestor(chain.bestChain.Genesis()) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. The genesis block is an ancestor of all blocks "+ + "but got false for node %s", + branch1Nodes[0].hash.String()) + } + + // Is the genesis an ancestor of 1b? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeTrue = branch2Nodes[0].IsAncestor(chain.bestChain.Genesis()) + if !shouldBeTrue { + t.Errorf("TestIsAncestor fail. The genesis block is an ancestor of all blocks "+ + "but got false for node %s", + branch2Nodes[0].hash.String()) + } + + // Is 1 an ancestor of 1a? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse := branch1Nodes[0].IsAncestor(branch0Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different branch than "+ + "node %s but got true", branch1Nodes[0].hash.String(), + branch0Nodes[0].hash.String()) + } + + // Is 1 an ancestor of 1b? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = branch2Nodes[0].IsAncestor(branch0Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different branch than "+ + "node %s but got true", branch2Nodes[0].hash.String(), + branch0Nodes[0].hash.String()) + } + + // Is 1a an ancestor of 1b? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = branch2Nodes[0].IsAncestor(branch1Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different branch than "+ + "node %s but got true", branch2Nodes[0].hash.String(), + branch1Nodes[0].hash.String()) + } + + // Is 1 an ancestor of 1? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = branch0Nodes[0].IsAncestor(branch0Nodes[0]) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node is not an ancestor of itself but got true for node %s", + branch0Nodes[0].hash.String()) + } + + // Is the geneis an ancestor of genesis? + // + // genesis -> 1 -> 2 -> 3 (active) + // \ -> 1a (valid-fork) + // \ -> 1b (invalid) + shouldBeFalse = chain.bestChain.Genesis().IsAncestor(chain.bestChain.Genesis()) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node is not an ancestor of itself but got true for node %s", + chain.bestChain.Genesis().hash.String()) + } + + // Is a block from another chain an ancestor of 1b? + fakeChain := newFakeChain(&chaincfg.TestNet3Params) + shouldBeFalse = branch2Nodes[0].IsAncestor(fakeChain.bestChain.Genesis()) + if shouldBeFalse { + t.Errorf("TestIsAncestor fail. Node %s is in a different chain than "+ + "node %s but got true", fakeChain.bestChain.Genesis().hash.String(), + branch2Nodes[0].hash.String()) + } +} From 2f4ff8447d51872bc2704bd31fe3b13bfb9a0143 Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Wed, 10 Apr 2024 22:08:30 +0800 Subject: [PATCH 0990/1056] fix some typos and make OP_DATA_20 explicit in comment (#2080) --- txscript/doc.go | 2 +- txscript/engine.go | 2 +- txscript/script.go | 2 +- txscript/sigvalidate.go | 2 +- txscript/standard.go | 4 ++-- txscript/taproot.go | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/txscript/doc.go b/txscript/doc.go index d6eddd5a65..957c91947c 100644 --- a/txscript/doc.go +++ b/txscript/doc.go @@ -17,7 +17,7 @@ bitcoin transaction scripts. Bitcoin transaction scripts are written in a stack-base, FORTH-like language. The bitcoin script language consists of a number of opcodes which fall into -several categories such pushing and popping data to and from the stack, +several categories such as pushing and popping data to and from the stack, performing basic and bitwise arithmetic, conditional branching, comparing hashes, and checking cryptographic signatures. Scripts are processed from left to right and intentionally do not provide loops. diff --git a/txscript/engine.go b/txscript/engine.go index 1458728f72..3725845104 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -605,7 +605,7 @@ func (vm *Engine) verifyWitnessProgram(witness wire.TxWitness) error { return scriptError(ErrWitnessProgramWrongLength, errStr) } - // We're attempting to to verify a taproot input, and the witness + // We're attempting to verify a taproot input, and the witness // program data push is of the expected size, so we'll be looking for a // normal key-path spend, or a merkle proof for a tapscript with // execution afterwards. diff --git a/txscript/script.go b/txscript/script.go index 13d6c42711..1448c57e2f 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -178,7 +178,7 @@ func DisasmString(script []byte) (string, error) { // removeOpcodeRaw will return the script after removing any opcodes that match // `opcode`. If the opcode does not appear in script, the original script will // be returned unmodified. Otherwise, a new script will be allocated to contain -// the filtered script. This metehod assumes that the script parses +// the filtered script. This method assumes that the script parses // successfully. // // NOTE: This function is only valid for version 0 scripts. Since the function diff --git a/txscript/sigvalidate.go b/txscript/sigvalidate.go index bda612a4e0..7b56ff6971 100644 --- a/txscript/sigvalidate.go +++ b/txscript/sigvalidate.go @@ -385,7 +385,7 @@ func (t *taprootSigVerifier) Verify() bool { var _ signatureVerifier = (*taprootSigVerifier)(nil) // baseTapscriptSigVerifier verifies a signature for an input spending a -// tapscript leaf from the prevoous output. +// tapscript leaf from the previous output. type baseTapscriptSigVerifier struct { *taprootSigVerifier diff --git a/txscript/standard.go b/txscript/standard.go index 5ef2ad167f..a25e32df92 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -153,7 +153,7 @@ func isPubKeyScript(script []byte) bool { // is a standard pay-to-pubkey-hash script. It will return nil otherwise. func extractPubKeyHash(script []byte) []byte { // A pay-to-pubkey-hash script is of the form: - // OP_DUP OP_HASH160 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG + // OP_DUP OP_HASH160 OP_DATA_20 <20-byte hash> OP_EQUALVERIFY OP_CHECKSIG if len(script) == 25 && script[0] == OP_DUP && script[1] == OP_HASH160 && @@ -181,7 +181,7 @@ func isPubKeyHashScript(script []byte) bool { // versions. func extractScriptHash(script []byte) []byte { // A pay-to-script-hash script is of the form: - // OP_HASH160 <20-byte scripthash> OP_EQUAL + // OP_HASH160 OP_DATA_20 <20-byte scripthash> OP_EQUAL if len(script) == 23 && script[0] == OP_HASH160 && script[1] == OP_DATA_20 && diff --git a/txscript/taproot.go b/txscript/taproot.go index 3776bf37a3..9e95e0a81f 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -65,7 +65,7 @@ func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, // program. rawKey := witnessProgram - // Extract the annex if it exists, so we can compute the proper proper + // Extract the annex if it exists, so we can compute the proper // sighash below. var annex []byte witness := tx.TxIn[inputIndex].Witness From 9f93dc1842557e03387d2856c51c589a494d2737 Mon Sep 17 00:00:00 2001 From: goodfirm <166383463+goodfirm@users.noreply.github.com> Date: Thu, 11 Apr 2024 00:59:42 +0800 Subject: [PATCH 0991/1056] chore: fix function names in comment (#2163) Signed-off-by: goodfirm --- cmd/addblock/config.go | 2 +- cmd/gencerts/gencerts.go | 2 +- config.go | 2 +- database/ffldb/db.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/addblock/config.go b/cmd/addblock/config.go index ffcc0eca79..d49df0a11d 100644 --- a/cmd/addblock/config.go +++ b/cmd/addblock/config.go @@ -45,7 +45,7 @@ type config struct { TxIndex bool `long:"txindex" description:"Build a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"` } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { diff --git a/cmd/gencerts/gencerts.go b/cmd/gencerts/gencerts.go index 328d5ea714..0c91b6fb85 100644 --- a/cmd/gencerts/gencerts.go +++ b/cmd/gencerts/gencerts.go @@ -90,7 +90,7 @@ func cleanAndExpandPath(path string) string { return filepath.Clean(os.ExpandEnv(path)) } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { diff --git a/config.go b/config.go index f8aad70cf8..a566f79e3d 100644 --- a/config.go +++ b/config.go @@ -384,7 +384,7 @@ func parseCheckpoints(checkpointStrings []string) ([]chaincfg.Checkpoint, error) return checkpoints, nil } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { diff --git a/database/ffldb/db.go b/database/ffldb/db.go index 8fc4d32646..3e96bfc738 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -2071,7 +2071,7 @@ func (db *db) Close() error { return closeErr } -// filesExists reports whether the named file or directory exists. +// fileExists reports whether the named file or directory exists. func fileExists(name string) bool { if _, err := os.Stat(name); err != nil { if os.IsNotExist(err) { From 64c9011d727a1e5110f8a867051d96ada1dbcea8 Mon Sep 17 00:00:00 2001 From: youngxhui Date: Wed, 10 Apr 2024 10:00:23 -0700 Subject: [PATCH 0992/1056] Update developer_resources.md (#2158) fix btcutil link error --- docs/developer_resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer_resources.md b/docs/developer_resources.md index c595c8330e..328e1b225a 100644 --- a/docs/developer_resources.md +++ b/docs/developer_resources.md @@ -28,7 +28,7 @@ * [mempool](https://github.com/btcsuite/btcd/tree/master/mempool) - Package mempool provides a policy-enforced pool of unmined bitcoin transactions. - * [btcutil](https://github.com/btcsuite/btcd/btcutil) - Provides Bitcoin-specific + * [btcutil](https://github.com/btcsuite/btcd/tree/master/btcutil) - Provides Bitcoin-specific convenience functions and types * [chainhash](https://github.com/btcsuite/btcd/tree/master/chaincfg/chainhash) - Provides a generic hash type and associated functions that allows the From 569155bc6a502f45b4a514bc6b9d5f814a980b6c Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <5462944+youngjoon-lee@users.noreply.github.com> Date: Wed, 10 Apr 2024 22:37:44 +0300 Subject: [PATCH 0993/1056] doc: fix config documentation for `AgentWhitelist` (#2140) --- config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.go b/config.go index a566f79e3d..486ce293a3 100644 --- a/config.go +++ b/config.go @@ -101,7 +101,7 @@ type config struct { AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"` AddrIndex bool `long:"addrindex" description:"Maintain a full address-based transaction index which makes the searchrawtransactions RPC available"` AgentBlacklist []string `long:"agentblacklist" description:"A comma separated list of user-agent substrings which will cause btcd to reject any peers whose user-agent contains any of the blacklisted substrings."` - AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the blacklist, and an empty whitelist will allow all agents that do not fail the blacklist."` + AgentWhitelist []string `long:"agentwhitelist" description:"A comma separated list of user-agent substrings which will cause btcd to require all peers' user-agents to contain one of the whitelisted substrings. The blacklist is applied before the whitelist, and an empty whitelist will allow all agents that do not fail the blacklist."` BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"` BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."` BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"` From 597b68c79e40c3e6bb63b5d5a0622273222c52f2 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 13:41:52 +0900 Subject: [PATCH 0994/1056] blockchain, workmath: refactor functions to workmath package Some of the functions in difficulty.go are not dependent on any external functions and they are needed to introduce testing code for the invalidateblock and reconsiderblock methods that are to be added on in later commits. Having the workmath package let's us reuse the code and avoid dependency cycles. The existing functions that were exported already (HashToBig, CompactToBig, BigToCompact, CalcWork) are still kept in difficulty.go to avoid breaking external code that depends on those exported functions. --- blockchain/difficulty.go | 95 +---------- blockchain/internal/workmath/README.md | 15 ++ blockchain/internal/workmath/difficulty.go | 153 ++++++++++++++++++ .../workmath}/difficulty_test.go | 2 +- 4 files changed, 174 insertions(+), 91 deletions(-) create mode 100644 blockchain/internal/workmath/README.md create mode 100644 blockchain/internal/workmath/difficulty.go rename blockchain/{ => internal/workmath}/difficulty_test.go (98%) diff --git a/blockchain/difficulty.go b/blockchain/difficulty.go index 1fa850cc37..b1e39b9d62 100644 --- a/blockchain/difficulty.go +++ b/blockchain/difficulty.go @@ -8,31 +8,14 @@ import ( "math/big" "time" + "github.com/btcsuite/btcd/blockchain/internal/workmath" "github.com/btcsuite/btcd/chaincfg/chainhash" ) -var ( - // bigOne is 1 represented as a big.Int. It is defined here to avoid - // the overhead of creating it multiple times. - bigOne = big.NewInt(1) - - // oneLsh256 is 1 shifted left 256 bits. It is defined here to avoid - // the overhead of creating it multiple times. - oneLsh256 = new(big.Int).Lsh(bigOne, 256) -) - // HashToBig converts a chainhash.Hash into a big.Int that can be used to // perform math comparisons. func HashToBig(hash *chainhash.Hash) *big.Int { - // A Hash is in little-endian, but the big package wants the bytes in - // big-endian, so reverse them. - buf := *hash - blen := len(buf) - for i := 0; i < blen/2; i++ { - buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i] - } - - return new(big.Int).SetBytes(buf[:]) + return workmath.HashToBig(hash) } // CompactToBig converts a compact representation of a whole number N to an @@ -60,31 +43,7 @@ func HashToBig(hash *chainhash.Hash) *big.Int { // which represent difficulty targets, thus there really is not a need for a // sign bit, but it is implemented here to stay consistent with bitcoind. func CompactToBig(compact uint32) *big.Int { - // Extract the mantissa, sign bit, and exponent. - mantissa := compact & 0x007fffff - isNegative := compact&0x00800000 != 0 - exponent := uint(compact >> 24) - - // Since the base for the exponent is 256, the exponent can be treated - // as the number of bytes to represent the full 256-bit number. So, - // treat the exponent as the number of bytes and shift the mantissa - // right or left accordingly. This is equivalent to: - // N = mantissa * 256^(exponent-3) - var bn *big.Int - if exponent <= 3 { - mantissa >>= 8 * (3 - exponent) - bn = big.NewInt(int64(mantissa)) - } else { - bn = big.NewInt(int64(mantissa)) - bn.Lsh(bn, 8*(exponent-3)) - } - - // Make it negative if the sign bit is set. - if isNegative { - bn = bn.Neg(bn) - } - - return bn + return workmath.CompactToBig(compact) } // BigToCompact converts a whole number N to a compact representation using @@ -92,41 +51,7 @@ func CompactToBig(compact uint32) *big.Int { // of precision, so values larger than (2^23 - 1) only encode the most // significant digits of the number. See CompactToBig for details. func BigToCompact(n *big.Int) uint32 { - // No need to do any work if it's zero. - if n.Sign() == 0 { - return 0 - } - - // Since the base for the exponent is 256, the exponent can be treated - // as the number of bytes. So, shift the number right or left - // accordingly. This is equivalent to: - // mantissa = mantissa / 256^(exponent-3) - var mantissa uint32 - exponent := uint(len(n.Bytes())) - if exponent <= 3 { - mantissa = uint32(n.Bits()[0]) - mantissa <<= 8 * (3 - exponent) - } else { - // Use a copy to avoid modifying the caller's original number. - tn := new(big.Int).Set(n) - mantissa = uint32(tn.Rsh(tn, 8*(exponent-3)).Bits()[0]) - } - - // When the mantissa already has the sign bit set, the number is too - // large to fit into the available 23-bits, so divide the number by 256 - // and increment the exponent accordingly. - if mantissa&0x00800000 != 0 { - mantissa >>= 8 - exponent++ - } - - // Pack the exponent, sign bit, and mantissa into an unsigned 32-bit - // int and return it. - compact := uint32(exponent<<24) | mantissa - if n.Sign() < 0 { - compact |= 0x00800000 - } - return compact + return workmath.BigToCompact(n) } // CalcWork calculates a work value from difficulty bits. Bitcoin increases @@ -140,17 +65,7 @@ func BigToCompact(n *big.Int) uint32 { // potential division by zero and really small floating point numbers, the // result adds 1 to the denominator and multiplies the numerator by 2^256. func CalcWork(bits uint32) *big.Int { - // Return a work value of zero if the passed difficulty bits represent - // a negative number. Note this should not happen in practice with valid - // blocks, but an invalid block could trigger it. - difficultyNum := CompactToBig(bits) - if difficultyNum.Sign() <= 0 { - return big.NewInt(0) - } - - // (1 << 256) / (difficultyNum + 1) - denominator := new(big.Int).Add(difficultyNum, bigOne) - return new(big.Int).Div(oneLsh256, denominator) + return workmath.CalcWork(bits) } // calcEasiestDifficulty calculates the easiest possible difficulty that a block diff --git a/blockchain/internal/workmath/README.md b/blockchain/internal/workmath/README.md new file mode 100644 index 0000000000..879b2dcfd7 --- /dev/null +++ b/blockchain/internal/workmath/README.md @@ -0,0 +1,15 @@ +workmath +========== + +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/workmath) + +Package workmath provides utility functions that are related with calculating +the work from difficulty bits. This package was introduced to avoid import +cycles in btcd. + +## License + +Package workmath is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/blockchain/internal/workmath/difficulty.go b/blockchain/internal/workmath/difficulty.go new file mode 100644 index 0000000000..8ff7adad1c --- /dev/null +++ b/blockchain/internal/workmath/difficulty.go @@ -0,0 +1,153 @@ +// Copyright (c) 2013-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package workmath + +import ( + "math/big" + + "github.com/btcsuite/btcd/chaincfg/chainhash" +) + +var ( + // bigOne is 1 represented as a big.Int. It is defined here to avoid + // the overhead of creating it multiple times. + bigOne = big.NewInt(1) + + // oneLsh256 is 1 shifted left 256 bits. It is defined here to avoid + // the overhead of creating it multiple times. + oneLsh256 = new(big.Int).Lsh(bigOne, 256) +) + +// HashToBig converts a chainhash.Hash into a big.Int that can be used to +// perform math comparisons. +func HashToBig(hash *chainhash.Hash) *big.Int { + // A Hash is in little-endian, but the big package wants the bytes in + // big-endian, so reverse them. + buf := *hash + blen := len(buf) + for i := 0; i < blen/2; i++ { + buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i] + } + + return new(big.Int).SetBytes(buf[:]) +} + +// CompactToBig converts a compact representation of a whole number N to an +// unsigned 32-bit number. The representation is similar to IEEE754 floating +// point numbers. +// +// Like IEEE754 floating point, there are three basic components: the sign, +// the exponent, and the mantissa. They are broken out as follows: +// +// - the most significant 8 bits represent the unsigned base 256 exponent +// - bit 23 (the 24th bit) represents the sign bit +// - the least significant 23 bits represent the mantissa +// +// ------------------------------------------------- +// | Exponent | Sign | Mantissa | +// ------------------------------------------------- +// | 8 bits [31-24] | 1 bit [23] | 23 bits [22-00] | +// ------------------------------------------------- +// +// The formula to calculate N is: +// +// N = (-1^sign) * mantissa * 256^(exponent-3) +// +// This compact form is only used in bitcoin to encode unsigned 256-bit numbers +// which represent difficulty targets, thus there really is not a need for a +// sign bit, but it is implemented here to stay consistent with bitcoind. +func CompactToBig(compact uint32) *big.Int { + // Extract the mantissa, sign bit, and exponent. + mantissa := compact & 0x007fffff + isNegative := compact&0x00800000 != 0 + exponent := uint(compact >> 24) + + // Since the base for the exponent is 256, the exponent can be treated + // as the number of bytes to represent the full 256-bit number. So, + // treat the exponent as the number of bytes and shift the mantissa + // right or left accordingly. This is equivalent to: + // N = mantissa * 256^(exponent-3) + var bn *big.Int + if exponent <= 3 { + mantissa >>= 8 * (3 - exponent) + bn = big.NewInt(int64(mantissa)) + } else { + bn = big.NewInt(int64(mantissa)) + bn.Lsh(bn, 8*(exponent-3)) + } + + // Make it negative if the sign bit is set. + if isNegative { + bn = bn.Neg(bn) + } + + return bn +} + +// BigToCompact converts a whole number N to a compact representation using +// an unsigned 32-bit number. The compact representation only provides 23 bits +// of precision, so values larger than (2^23 - 1) only encode the most +// significant digits of the number. See CompactToBig for details. +func BigToCompact(n *big.Int) uint32 { + // No need to do any work if it's zero. + if n.Sign() == 0 { + return 0 + } + + // Since the base for the exponent is 256, the exponent can be treated + // as the number of bytes. So, shift the number right or left + // accordingly. This is equivalent to: + // mantissa = mantissa / 256^(exponent-3) + var mantissa uint32 + exponent := uint(len(n.Bytes())) + if exponent <= 3 { + mantissa = uint32(n.Bits()[0]) + mantissa <<= 8 * (3 - exponent) + } else { + // Use a copy to avoid modifying the caller's original number. + tn := new(big.Int).Set(n) + mantissa = uint32(tn.Rsh(tn, 8*(exponent-3)).Bits()[0]) + } + + // When the mantissa already has the sign bit set, the number is too + // large to fit into the available 23-bits, so divide the number by 256 + // and increment the exponent accordingly. + if mantissa&0x00800000 != 0 { + mantissa >>= 8 + exponent++ + } + + // Pack the exponent, sign bit, and mantissa into an unsigned 32-bit + // int and return it. + compact := uint32(exponent<<24) | mantissa + if n.Sign() < 0 { + compact |= 0x00800000 + } + return compact +} + +// CalcWork calculates a work value from difficulty bits. Bitcoin increases +// the difficulty for generating a block by decreasing the value which the +// generated hash must be less than. This difficulty target is stored in each +// block header using a compact representation as described in the documentation +// for CompactToBig. The main chain is selected by choosing the chain that has +// the most proof of work (highest difficulty). Since a lower target difficulty +// value equates to higher actual difficulty, the work value which will be +// accumulated must be the inverse of the difficulty. Also, in order to avoid +// potential division by zero and really small floating point numbers, the +// result adds 1 to the denominator and multiplies the numerator by 2^256. +func CalcWork(bits uint32) *big.Int { + // Return a work value of zero if the passed difficulty bits represent + // a negative number. Note this should not happen in practice with valid + // blocks, but an invalid block could trigger it. + difficultyNum := CompactToBig(bits) + if difficultyNum.Sign() <= 0 { + return big.NewInt(0) + } + + // (1 << 256) / (difficultyNum + 1) + denominator := new(big.Int).Add(difficultyNum, bigOne) + return new(big.Int).Div(oneLsh256, denominator) +} diff --git a/blockchain/difficulty_test.go b/blockchain/internal/workmath/difficulty_test.go similarity index 98% rename from blockchain/difficulty_test.go rename to blockchain/internal/workmath/difficulty_test.go index c4d8fb6ef5..bed4d1f13f 100644 --- a/blockchain/difficulty_test.go +++ b/blockchain/internal/workmath/difficulty_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. -package blockchain +package workmath import ( "math/big" From 337d7f6be8cddca2c75589e5d9c5edcc5cce42fb Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 13:54:53 +0900 Subject: [PATCH 0995/1056] fullblocktests, testhelper: refactor out spendableOut spendableOut and the functions related to it are is moved to package testhelper and are exported. This is done to make the code reusable without introducing an import cycle when the testing code for invalidateblock and reconsiderblock are added in follow up commits. --- blockchain/fullblocktests/generate.go | 68 ++++++++---------------- blockchain/internal/testhelper/README.md | 16 ++++++ blockchain/internal/testhelper/common.go | 31 +++++++++++ 3 files changed, 69 insertions(+), 46 deletions(-) create mode 100644 blockchain/internal/testhelper/README.md create mode 100644 blockchain/internal/testhelper/common.go diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index fe36bfe136..5f35d3e72b 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -19,6 +19,7 @@ import ( "time" "github.com/btcsuite/btcd/blockchain" + "github.com/btcsuite/btcd/blockchain/internal/testhelper" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" @@ -165,31 +166,6 @@ type BlockDisconnectExpectUTXO struct { // This implements the TestInstance interface. func (b BlockDisconnectExpectUTXO) FullBlockTestInstance() {} -// spendableOut represents a transaction output that is spendable along with -// additional metadata such as the block its in and how much it pays. -type spendableOut struct { - prevOut wire.OutPoint - amount btcutil.Amount -} - -// makeSpendableOutForTx returns a spendable output for the given transaction -// and transaction output index within the transaction. -func makeSpendableOutForTx(tx *wire.MsgTx, txOutIndex uint32) spendableOut { - return spendableOut{ - prevOut: wire.OutPoint{ - Hash: tx.TxHash(), - Index: txOutIndex, - }, - amount: btcutil.Amount(tx.TxOut[txOutIndex].Value), - } -} - -// makeSpendableOut returns a spendable output for the given block, transaction -// index within the block, and transaction output index within the transaction. -func makeSpendableOut(block *wire.MsgBlock, txIndex, txOutIndex uint32) spendableOut { - return makeSpendableOutForTx(block.Transactions[txIndex], txOutIndex) -} - // testGenerator houses state used to easy the process of generating test blocks // that build from one another along with housing other useful things such as // available spendable outputs used throughout the tests. @@ -203,7 +179,7 @@ type testGenerator struct { blockHeights map[string]int32 // Used for tracking spendable coinbase outputs. - spendableOuts []spendableOut + spendableOuts []testhelper.SpendableOut prevCollectedHash chainhash.Hash // Common key for any tests which require signed transactions. @@ -449,14 +425,14 @@ func additionalTx(tx *wire.MsgTx) func(*wire.MsgBlock) { // transaction ends up with a unique hash. The script is a simple OP_TRUE // script which avoids the need to track addresses and signature scripts in the // tests. -func createSpendTx(spend *spendableOut, fee btcutil.Amount) *wire.MsgTx { +func createSpendTx(spend *testhelper.SpendableOut, fee btcutil.Amount) *wire.MsgTx { spendTx := wire.NewMsgTx(1) spendTx.AddTxIn(&wire.TxIn{ - PreviousOutPoint: spend.prevOut, + PreviousOutPoint: spend.PrevOut, Sequence: wire.MaxTxInSequenceNum, SignatureScript: nil, }) - spendTx.AddTxOut(wire.NewTxOut(int64(spend.amount-fee), + spendTx.AddTxOut(wire.NewTxOut(int64(spend.Amount-fee), opTrueScript)) spendTx.AddTxOut(wire.NewTxOut(0, uniqueOpReturnScript())) @@ -469,7 +445,7 @@ func createSpendTx(spend *spendableOut, fee btcutil.Amount) *wire.MsgTx { // is a simple OP_TRUE script which avoids the need to track addresses and // signature scripts in the tests. The signature script is nil. func createSpendTxForTx(tx *wire.MsgTx, fee btcutil.Amount) *wire.MsgTx { - spend := makeSpendableOutForTx(tx, 0) + spend := testhelper.MakeSpendableOutForTx(tx, 0) return createSpendTx(&spend, fee) } @@ -492,7 +468,7 @@ func createSpendTxForTx(tx *wire.MsgTx, fee btcutil.Amount) *wire.MsgTx { // applied after all munge functions have been invoked: // - The merkle root will be recalculated unless it was manually changed // - The block will be solved unless the nonce was changed -func (g *testGenerator) nextBlock(blockName string, spend *spendableOut, mungers ...func(*wire.MsgBlock)) *wire.MsgBlock { +func (g *testGenerator) nextBlock(blockName string, spend *testhelper.SpendableOut, mungers ...func(*wire.MsgBlock)) *wire.MsgBlock { // Create coinbase transaction for the block using any additional // subsidy if specified. nextHeight := g.tipHeight + 1 @@ -594,7 +570,7 @@ func (g *testGenerator) setTip(blockName string) { // oldestCoinbaseOuts removes the oldest coinbase output that was previously // saved to the generator and returns the set as a slice. -func (g *testGenerator) oldestCoinbaseOut() spendableOut { +func (g *testGenerator) oldestCoinbaseOut() testhelper.SpendableOut { op := g.spendableOuts[0] g.spendableOuts = g.spendableOuts[1:] return op @@ -603,7 +579,7 @@ func (g *testGenerator) oldestCoinbaseOut() spendableOut { // saveTipCoinbaseOut adds the coinbase tx output in the current tip block to // the list of spendable outputs. func (g *testGenerator) saveTipCoinbaseOut() { - g.spendableOuts = append(g.spendableOuts, makeSpendableOut(g.tip, 0, 0)) + g.spendableOuts = append(g.spendableOuts, testhelper.MakeSpendableOut(g.tip, 0, 0)) g.prevCollectedHash = g.tip.BlockHash() } @@ -947,7 +923,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { tests = append(tests, testInstances) // Collect spendable outputs. This simplifies the code below. - var outs []*spendableOut + var outs []*testhelper.SpendableOut for i := uint16(0); i < coinbaseMaturity; i++ { op := g.oldestCoinbaseOut() outs = append(outs, &op) @@ -985,7 +961,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // \-> b3(1) g.setTip("b1") g.nextBlock("b3", outs[1]) - b3Tx1Out := makeSpendableOut(g.tip, 1, 0) + b3Tx1Out := testhelper.MakeSpendableOut(g.tip, 1, 0) acceptedToSideChainWithExpectedTip("b2") // Extend b3 fork to make the alternative chain longer and force reorg. @@ -1300,7 +1276,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { g.setTip("b35") doubleSpendTx := createSpendTx(outs[11], lowFee) g.nextBlock("b37", outs[11], additionalTx(doubleSpendTx)) - b37Tx1Out := makeSpendableOut(g.tip, 1, 0) + b37Tx1Out := testhelper.MakeSpendableOut(g.tip, 1, 0) rejected(blockchain.ErrMissingTxOut) g.setTip("b35") @@ -1356,7 +1332,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { for i := 0; i < txnsNeeded; i++ { // Create a signed transaction that spends from the // associated p2sh output in b39. - spend := makeSpendableOutForTx(b39.Transactions[i+2], 2) + spend := testhelper.MakeSpendableOutForTx(b39.Transactions[i+2], 2) tx := createSpendTx(&spend, lowFee) sig, err := txscript.RawTxInSignature(tx, 0, redeemScript, txscript.SigHashAll, g.privKey) @@ -1387,7 +1363,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { g.nextBlock("b41", outs[12], func(b *wire.MsgBlock) { txnsNeeded := (maxBlockSigOps / redeemScriptSigOps) for i := 0; i < txnsNeeded; i++ { - spend := makeSpendableOutForTx(b39.Transactions[i+2], 2) + spend := testhelper.MakeSpendableOutForTx(b39.Transactions[i+2], 2) tx := createSpendTx(&spend, lowFee) sig, err := txscript.RawTxInSignature(tx, 0, redeemScript, txscript.SigHashAll, g.privKey) @@ -1719,7 +1695,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // \-> b59(17) g.setTip("b57") g.nextBlock("b59", outs[17], func(b *wire.MsgBlock) { - b.Transactions[1].TxOut[0].Value = int64(outs[17].amount) + 1 + b.Transactions[1].TxOut[0].Value = int64(outs[17].Amount) + 1 }) rejected(blockchain.ErrSpendTooHigh) @@ -2003,14 +1979,14 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // NOTE: The createSpendTx func adds the OP_RETURN output. zeroFee := btcutil.Amount(0) for i := uint32(0); i < numAdditionalOutputs; i++ { - spend := makeSpendableOut(b, 1, i+2) + spend := testhelper.MakeSpendableOut(b, 1, i+2) tx := createSpendTx(&spend, zeroFee) b.AddTransaction(tx) } }) g.assertTipBlockNumTxns(6) g.assertTipBlockTxOutOpReturn(5, 1) - b75OpReturnOut := makeSpendableOut(g.tip, 5, 1) + b75OpReturnOut := testhelper.MakeSpendableOut(g.tip, 5, 1) accepted() // Reorg to a side chain that does not contain the OP_RETURNs. @@ -2043,7 +2019,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // An OP_RETURN output doesn't have any value and the default behavior // of nextBlock is to assign a fee of one, so increment the amount here // to effective negate that behavior. - b75OpReturnOut.amount++ + b75OpReturnOut.Amount++ g.nextBlock("b80", &b75OpReturnOut) rejected(blockchain.ErrMissingTxOut) @@ -2075,7 +2051,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { g.nextBlock("b82a", outs[28]) accepted() - b82aTx1Out0 := makeSpendableOut(g.tip, 1, 0) + b82aTx1Out0 := testhelper.MakeSpendableOut(g.tip, 1, 0) g.nextBlock("b83a", &b82aTx1Out0) accepted() @@ -2097,17 +2073,17 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // We expect b82a output to now be a utxo since b83a was spending it and it was // removed from the main chain. blockDisconnectExpectUTXO("b82aTx1Out0", - true, b82aTx1Out0.prevOut, g.blocksByName["b83a"].BlockHash()) + true, b82aTx1Out0.PrevOut, g.blocksByName["b83a"].BlockHash()) // We expect the output from b82 to not exist once b82a itself has been removed // from the main chain. blockDisconnectExpectUTXO("b82aTx1Out0", - false, b82aTx1Out0.prevOut, g.blocksByName["b82a"].BlockHash()) + false, b82aTx1Out0.PrevOut, g.blocksByName["b82a"].BlockHash()) // The output that was being spent in b82a should exist after the removal of // b82a. blockDisconnectExpectUTXO("outs[28]", - true, outs[28].prevOut, g.blocksByName["b82a"].BlockHash()) + true, outs[28].PrevOut, g.blocksByName["b82a"].BlockHash()) // Create block 84 and reorg out the sidechain with b83a as the tip. // diff --git a/blockchain/internal/testhelper/README.md b/blockchain/internal/testhelper/README.md new file mode 100644 index 0000000000..40b339bf79 --- /dev/null +++ b/blockchain/internal/testhelper/README.md @@ -0,0 +1,16 @@ +testhelper +========== + +[![Build Status](https://github.com/btcsuite/btcd/workflows/Build%20and%20Test/badge.svg)](https://github.com/btcsuite/btcd/actions) +[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org) +[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/btcsuite/btcd/blockchain/testhelper) + +Package testhelper provides functions that are used internally in the +btcd/blockchain and btcd/blockchain/fullblocktests package to test consensus +validation rules. Mainly provided to avoid dependency cycles internally among +the different packages in btcd. + +## License + +Package testhelper is licensed under the [copyfree](http://copyfree.org) ISC +License. diff --git a/blockchain/internal/testhelper/common.go b/blockchain/internal/testhelper/common.go new file mode 100644 index 0000000000..e7f5a2622e --- /dev/null +++ b/blockchain/internal/testhelper/common.go @@ -0,0 +1,31 @@ +package testhelper + +import ( + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/wire" +) + +// SpendableOut represents a transaction output that is spendable along with +// additional metadata such as the block its in and how much it pays. +type SpendableOut struct { + PrevOut wire.OutPoint + Amount btcutil.Amount +} + +// MakeSpendableOutForTx returns a spendable output for the given transaction +// and transaction output index within the transaction. +func MakeSpendableOutForTx(tx *wire.MsgTx, txOutIndex uint32) SpendableOut { + return SpendableOut{ + PrevOut: wire.OutPoint{ + Hash: tx.TxHash(), + Index: txOutIndex, + }, + Amount: btcutil.Amount(tx.TxOut[txOutIndex].Value), + } +} + +// MakeSpendableOut returns a spendable output for the given block, transaction +// index within the block, and transaction output index within the transaction. +func MakeSpendableOut(block *wire.MsgBlock, txIndex, txOutIndex uint32) SpendableOut { + return MakeSpendableOutForTx(block.Transactions[txIndex], txOutIndex) +} From d4644dff10faf9fea7de02f219c0490723985394 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 14:01:05 +0900 Subject: [PATCH 0996/1056] fullblocktests, testhelper: move solveBlock to testhelper solveBlock is moved to testhelper and is exported. This is done so that the code can be reused without introducing import cycles. The testing code to be added in alter commits for invalidateblock and reconsider block will use SolveBlock. --- blockchain/fullblocktests/generate.go | 68 +---------------------- blockchain/internal/testhelper/common.go | 69 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 67 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 5f35d3e72b..00beedaaa2 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -14,7 +14,6 @@ import ( "encoding/binary" "errors" "fmt" - "math" "runtime" "time" @@ -303,71 +302,6 @@ func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash { return blockchain.CalcMerkleRoot(utilTxns, false) } -// solveBlock attempts to find a nonce which makes the passed block header hash -// to a value less than the target difficulty. When a successful solution is -// found true is returned and the nonce field of the passed header is updated -// with the solution. False is returned if no solution exists. -// -// NOTE: This function will never solve blocks with a nonce of 0. This is done -// so the 'nextBlock' function can properly detect when a nonce was modified by -// a munge function. -func solveBlock(header *wire.BlockHeader) bool { - // sbResult is used by the solver goroutines to send results. - type sbResult struct { - found bool - nonce uint32 - } - - // solver accepts a block header and a nonce range to test. It is - // intended to be run as a goroutine. - targetDifficulty := blockchain.CompactToBig(header.Bits) - quit := make(chan bool) - results := make(chan sbResult) - solver := func(hdr wire.BlockHeader, startNonce, stopNonce uint32) { - // We need to modify the nonce field of the header, so make sure - // we work with a copy of the original header. - for i := startNonce; i >= startNonce && i <= stopNonce; i++ { - select { - case <-quit: - return - default: - hdr.Nonce = i - hash := hdr.BlockHash() - if blockchain.HashToBig(&hash).Cmp( - targetDifficulty) <= 0 { - - results <- sbResult{true, i} - return - } - } - } - results <- sbResult{false, 0} - } - - startNonce := uint32(1) - stopNonce := uint32(math.MaxUint32) - numCores := uint32(runtime.NumCPU()) - noncesPerCore := (stopNonce - startNonce) / numCores - for i := uint32(0); i < numCores; i++ { - rangeStart := startNonce + (noncesPerCore * i) - rangeStop := startNonce + (noncesPerCore * (i + 1)) - 1 - if i == numCores-1 { - rangeStop = stopNonce - } - go solver(*header, rangeStart, rangeStop) - } - for i := uint32(0); i < numCores; i++ { - result := <-results - if result.found { - close(quit) - header.Nonce = result.nonce - return true - } - } - - return false -} - // additionalCoinbase returns a function that itself takes a block and // modifies it by adding the provided amount to coinbase subsidy. func additionalCoinbase(amount btcutil.Amount) func(*wire.MsgBlock) { @@ -523,7 +457,7 @@ func (g *testGenerator) nextBlock(blockName string, spend *testhelper.SpendableO // Only solve the block if the nonce wasn't manually changed by a munge // function. - if block.Header.Nonce == curNonce && !solveBlock(&block.Header) { + if block.Header.Nonce == curNonce && !testhelper.SolveBlock(&block.Header) { panic(fmt.Sprintf("Unable to solve block at height %d", nextHeight)) } diff --git a/blockchain/internal/testhelper/common.go b/blockchain/internal/testhelper/common.go index e7f5a2622e..518a679218 100644 --- a/blockchain/internal/testhelper/common.go +++ b/blockchain/internal/testhelper/common.go @@ -1,6 +1,10 @@ package testhelper import ( + "math" + "runtime" + + "github.com/btcsuite/btcd/blockchain/internal/workmath" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" ) @@ -29,3 +33,68 @@ func MakeSpendableOutForTx(tx *wire.MsgTx, txOutIndex uint32) SpendableOut { func MakeSpendableOut(block *wire.MsgBlock, txIndex, txOutIndex uint32) SpendableOut { return MakeSpendableOutForTx(block.Transactions[txIndex], txOutIndex) } + +// SolveBlock attempts to find a nonce which makes the passed block header hash +// to a value less than the target difficulty. When a successful solution is +// found true is returned and the nonce field of the passed header is updated +// with the solution. False is returned if no solution exists. +// +// NOTE: This function will never solve blocks with a nonce of 0. This is done +// so the 'nextBlock' function can properly detect when a nonce was modified by +// a munge function. +func SolveBlock(header *wire.BlockHeader) bool { + // sbResult is used by the solver goroutines to send results. + type sbResult struct { + found bool + nonce uint32 + } + + // solver accepts a block header and a nonce range to test. It is + // intended to be run as a goroutine. + targetDifficulty := workmath.CompactToBig(header.Bits) + quit := make(chan bool) + results := make(chan sbResult) + solver := func(hdr wire.BlockHeader, startNonce, stopNonce uint32) { + // We need to modify the nonce field of the header, so make sure + // we work with a copy of the original header. + for i := startNonce; i >= startNonce && i <= stopNonce; i++ { + select { + case <-quit: + return + default: + hdr.Nonce = i + hash := hdr.BlockHash() + if workmath.HashToBig(&hash).Cmp( + targetDifficulty) <= 0 { + + results <- sbResult{true, i} + return + } + } + } + results <- sbResult{false, 0} + } + + startNonce := uint32(1) + stopNonce := uint32(math.MaxUint32) + numCores := uint32(runtime.NumCPU()) + noncesPerCore := (stopNonce - startNonce) / numCores + for i := uint32(0); i < numCores; i++ { + rangeStart := startNonce + (noncesPerCore * i) + rangeStop := startNonce + (noncesPerCore * (i + 1)) - 1 + if i == numCores-1 { + rangeStop = stopNonce + } + go solver(*header, rangeStart, rangeStop) + } + for i := uint32(0); i < numCores; i++ { + result := <-results + if result.found { + close(quit) + header.Nonce = result.nonce + return true + } + } + + return false +} From 62790ac065fc4da5e09da89fce9f9e93ae78f0eb Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 14:06:13 +0900 Subject: [PATCH 0997/1056] fullblocktests, testhelper: move opTrueScript and lowFee to testhelper The variables are moved to testhelper so that they can be reused in the blockchain package without introducing an import cycle. The testing code for invalidateblock and reconsiderblock that will be added in later commits will be using these variables. --- blockchain/fullblocktests/generate.go | 46 ++++++++++-------------- blockchain/internal/testhelper/common.go | 11 ++++++ 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 00beedaaa2..2416bd1b31 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -43,16 +43,6 @@ const ( numLargeReorgBlocks = 1088 ) -var ( - // opTrueScript is simply a public key script that contains the OP_TRUE - // opcode. It is defined here to reduce garbage creation. - opTrueScript = []byte{txscript.OP_TRUE} - - // lowFee is a single satoshi and exists to make the test code more - // readable. - lowFee = btcutil.Amount(1) -) - // TestInstance is an interface that describes a specific test instance returned // by the tests generated in this package. It should be type asserted to one // of the concrete test instance types in order to test accordingly. @@ -283,7 +273,7 @@ func (g *testGenerator) createCoinbaseTx(blockHeight int32) *wire.MsgTx { }) tx.AddTxOut(&wire.TxOut{ Value: blockchain.CalcBlockSubsidy(blockHeight, g.params), - PkScript: opTrueScript, + PkScript: testhelper.OpTrueScript, }) return tx } @@ -367,7 +357,7 @@ func createSpendTx(spend *testhelper.SpendableOut, fee btcutil.Amount) *wire.Msg SignatureScript: nil, }) spendTx.AddTxOut(wire.NewTxOut(int64(spend.Amount-fee), - opTrueScript)) + testhelper.OpTrueScript)) spendTx.AddTxOut(wire.NewTxOut(0, uniqueOpReturnScript())) return spendTx @@ -1208,7 +1198,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // \-> b38(b37.tx[1]) // g.setTip("b35") - doubleSpendTx := createSpendTx(outs[11], lowFee) + doubleSpendTx := createSpendTx(outs[11], testhelper.LowFee) g.nextBlock("b37", outs[11], additionalTx(doubleSpendTx)) b37Tx1Out := testhelper.MakeSpendableOut(g.tip, 1, 0) rejected(blockchain.ErrMissingTxOut) @@ -1246,7 +1236,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { txnsNeeded := (maxBlockSigOps / redeemScriptSigOps) + 1 prevTx := b.Transactions[1] for i := 0; i < txnsNeeded; i++ { - prevTx = createSpendTxForTx(prevTx, lowFee) + prevTx = createSpendTxForTx(prevTx, testhelper.LowFee) prevTx.TxOut[0].Value -= 2 prevTx.AddTxOut(wire.NewTxOut(2, p2shScript)) b.AddTransaction(prevTx) @@ -1267,7 +1257,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // Create a signed transaction that spends from the // associated p2sh output in b39. spend := testhelper.MakeSpendableOutForTx(b39.Transactions[i+2], 2) - tx := createSpendTx(&spend, lowFee) + tx := createSpendTx(&spend, testhelper.LowFee) sig, err := txscript.RawTxInSignature(tx, 0, redeemScript, txscript.SigHashAll, g.privKey) if err != nil { @@ -1283,7 +1273,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // the block one over the max allowed. fill := maxBlockSigOps - (txnsNeeded * redeemScriptSigOps) + 1 finalTx := b.Transactions[len(b.Transactions)-1] - tx := createSpendTxForTx(finalTx, lowFee) + tx := createSpendTxForTx(finalTx, testhelper.LowFee) tx.TxOut[0].PkScript = repeatOpcode(txscript.OP_CHECKSIG, fill) b.AddTransaction(tx) }) @@ -1298,7 +1288,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { txnsNeeded := (maxBlockSigOps / redeemScriptSigOps) for i := 0; i < txnsNeeded; i++ { spend := testhelper.MakeSpendableOutForTx(b39.Transactions[i+2], 2) - tx := createSpendTx(&spend, lowFee) + tx := createSpendTx(&spend, testhelper.LowFee) sig, err := txscript.RawTxInSignature(tx, 0, redeemScript, txscript.SigHashAll, g.privKey) if err != nil { @@ -1317,7 +1307,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { return } finalTx := b.Transactions[len(b.Transactions)-1] - tx := createSpendTxForTx(finalTx, lowFee) + tx := createSpendTxForTx(finalTx, testhelper.LowFee) tx.TxOut[0].PkScript = repeatOpcode(txscript.OP_CHECKSIG, fill) b.AddTransaction(tx) }) @@ -1347,7 +1337,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // ... -> b43(13) // \-> b44(14) g.nextBlock("b44", nil, func(b *wire.MsgBlock) { - nonCoinbaseTx := createSpendTx(outs[14], lowFee) + nonCoinbaseTx := createSpendTx(outs[14], testhelper.LowFee) b.Transactions[0] = nonCoinbaseTx }) rejected(blockchain.ErrFirstTxNotCoinbase) @@ -1552,7 +1542,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { g.setTip("b55") b57 := g.nextBlock("b57", outs[16], func(b *wire.MsgBlock) { tx2 := b.Transactions[1] - tx3 := createSpendTxForTx(tx2, lowFee) + tx3 := createSpendTxForTx(tx2, testhelper.LowFee) b.AddTransaction(tx3) }) g.assertTipBlockNumTxns(3) @@ -1597,7 +1587,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // in the block. spendTx := b.Transactions[1] for i := 0; i < 4; i++ { - spendTx = createSpendTxForTx(spendTx, lowFee) + spendTx = createSpendTxForTx(spendTx, testhelper.LowFee) b.AddTransaction(spendTx) } @@ -1734,7 +1724,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // ... b64(18) -> b65(19) g.setTip("b64") g.nextBlock("b65", outs[19], func(b *wire.MsgBlock) { - tx3 := createSpendTxForTx(b.Transactions[1], lowFee) + tx3 := createSpendTxForTx(b.Transactions[1], testhelper.LowFee) b.AddTransaction(tx3) }) accepted() @@ -1744,8 +1734,8 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // ... -> b65(19) // \-> b66(20) g.nextBlock("b66", nil, func(b *wire.MsgBlock) { - tx2 := createSpendTx(outs[20], lowFee) - tx3 := createSpendTxForTx(tx2, lowFee) + tx2 := createSpendTx(outs[20], testhelper.LowFee) + tx3 := createSpendTxForTx(tx2, testhelper.LowFee) b.AddTransaction(tx3) b.AddTransaction(tx2) }) @@ -1759,8 +1749,8 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { g.setTip("b65") g.nextBlock("b67", outs[20], func(b *wire.MsgBlock) { tx2 := b.Transactions[1] - tx3 := createSpendTxForTx(tx2, lowFee) - tx4 := createSpendTxForTx(tx2, lowFee) + tx3 := createSpendTxForTx(tx2, testhelper.LowFee) + tx4 := createSpendTxForTx(tx2, testhelper.LowFee) b.AddTransaction(tx3) b.AddTransaction(tx4) }) @@ -1883,7 +1873,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { txscript.OP_ELSE, txscript.OP_TRUE, txscript.OP_ENDIF} g.nextBlock("b74", outs[23], replaceSpendScript(script), func(b *wire.MsgBlock) { tx2 := b.Transactions[1] - tx3 := createSpendTxForTx(tx2, lowFee) + tx3 := createSpendTxForTx(tx2, testhelper.LowFee) tx3.TxIn[0].SignatureScript = []byte{txscript.OP_FALSE} b.AddTransaction(tx3) }) @@ -1904,7 +1894,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { const zeroCoin = int64(0) spendTx := b.Transactions[1] for i := 0; i < numAdditionalOutputs; i++ { - spendTx.AddTxOut(wire.NewTxOut(zeroCoin, opTrueScript)) + spendTx.AddTxOut(wire.NewTxOut(zeroCoin, testhelper.OpTrueScript)) } // Add transactions spending from the outputs added above that diff --git a/blockchain/internal/testhelper/common.go b/blockchain/internal/testhelper/common.go index 518a679218..15fc5fd75c 100644 --- a/blockchain/internal/testhelper/common.go +++ b/blockchain/internal/testhelper/common.go @@ -6,9 +6,20 @@ import ( "github.com/btcsuite/btcd/blockchain/internal/workmath" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" ) +var ( + // OpTrueScript is simply a public key script that contains the OP_TRUE + // opcode. It is defined here to reduce garbage creation. + OpTrueScript = []byte{txscript.OP_TRUE} + + // LowFee is a single satoshi and exists to make the test code more + // readable. + LowFee = btcutil.Amount(1) +) + // SpendableOut represents a transaction output that is spendable along with // additional metadata such as the block its in and how much it pays. type SpendableOut struct { From 9093243d8bcc40c46ad612e1921e7556cecd636f Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 14:13:07 +0900 Subject: [PATCH 0998/1056] fullblocktests, testhelper: move uniqueOpReturnScript to testhelper uniqueOpReturnScript is moved to testhelper and is exported so that the code and be reused in package blockchain without introducing import cycles. The test code for invalidateblock and reconsiderblock that are gonna be added in later commits uses the functions. --- blockchain/fullblocktests/generate.go | 35 ++++++------------------ blockchain/internal/testhelper/common.go | 25 +++++++++++++++++ 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 2416bd1b31..242de64734 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -228,30 +228,6 @@ func standardCoinbaseScript(blockHeight int32, extraNonce uint64) ([]byte, error AddInt64(int64(extraNonce)).Script() } -// opReturnScript returns a provably-pruneable OP_RETURN script with the -// provided data. -func opReturnScript(data []byte) []byte { - builder := txscript.NewScriptBuilder() - script, err := builder.AddOp(txscript.OP_RETURN).AddData(data).Script() - if err != nil { - panic(err) - } - return script -} - -// uniqueOpReturnScript returns a standard provably-pruneable OP_RETURN script -// with a random uint64 encoded as the data. -func uniqueOpReturnScript() []byte { - rand, err := wire.RandomUint64() - if err != nil { - panic(err) - } - - data := make([]byte, 8) - binary.LittleEndian.PutUint64(data[0:8], rand) - return opReturnScript(data) -} - // createCoinbaseTx returns a coinbase transaction paying an appropriate // subsidy based on the passed block height. The coinbase signature script // conforms to the requirements of version 2 blocks. @@ -358,7 +334,11 @@ func createSpendTx(spend *testhelper.SpendableOut, fee btcutil.Amount) *wire.Msg }) spendTx.AddTxOut(wire.NewTxOut(int64(spend.Amount-fee), testhelper.OpTrueScript)) - spendTx.AddTxOut(wire.NewTxOut(0, uniqueOpReturnScript())) + opRetScript, err := testhelper.UniqueOpReturnScript() + if err != nil { + panic(err) + } + spendTx.AddTxOut(wire.NewTxOut(0, opRetScript)) return spendTx } @@ -1959,7 +1939,10 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { const zeroCoin = int64(0) spendTx := b.Transactions[1] for i := 0; i < numAdditionalOutputs; i++ { - opRetScript := uniqueOpReturnScript() + opRetScript, err := testhelper.UniqueOpReturnScript() + if err != nil { + panic(err) + } spendTx.AddTxOut(wire.NewTxOut(zeroCoin, opRetScript)) } }) diff --git a/blockchain/internal/testhelper/common.go b/blockchain/internal/testhelper/common.go index 15fc5fd75c..49f80347e1 100644 --- a/blockchain/internal/testhelper/common.go +++ b/blockchain/internal/testhelper/common.go @@ -1,6 +1,7 @@ package testhelper import ( + "encoding/binary" "math" "runtime" @@ -20,6 +21,30 @@ var ( LowFee = btcutil.Amount(1) ) +// OpReturnScript returns a provably-pruneable OP_RETURN script with the +// provided data. +func OpReturnScript(data []byte) ([]byte, error) { + builder := txscript.NewScriptBuilder() + script, err := builder.AddOp(txscript.OP_RETURN).AddData(data).Script() + if err != nil { + return nil, err + } + return script, nil +} + +// UniqueOpReturnScript returns a standard provably-pruneable OP_RETURN script +// with a random uint64 encoded as the data. +func UniqueOpReturnScript() ([]byte, error) { + rand, err := wire.RandomUint64() + if err != nil { + return nil, err + } + + data := make([]byte, 8) + binary.LittleEndian.PutUint64(data[0:8], rand) + return OpReturnScript(data) +} + // SpendableOut represents a transaction output that is spendable along with // additional metadata such as the block its in and how much it pays. type SpendableOut struct { From 59c7d105073717a9f1b7363c673a49496d76cfdd Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 16:09:50 +0900 Subject: [PATCH 0999/1056] fullblocktests, testhelper: move standardCoinbaseScript to testhelper standardCoinbaseScript is moved to testhelper and is exported. This allows test code in package blockchain to reuse the code without introducing an import cycle. This code is used in the testing code for invalidateblock and reconsiderblock that's added in the later commits. --- blockchain/fullblocktests/generate.go | 10 +--------- blockchain/internal/testhelper/common.go | 8 ++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 242de64734..7bd838a5e0 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -220,20 +220,12 @@ func pushDataScript(items ...[]byte) []byte { return script } -// standardCoinbaseScript returns a standard script suitable for use as the -// signature script of the coinbase transaction of a new block. In particular, -// it starts with the block height that is required by version 2 blocks. -func standardCoinbaseScript(blockHeight int32, extraNonce uint64) ([]byte, error) { - return txscript.NewScriptBuilder().AddInt64(int64(blockHeight)). - AddInt64(int64(extraNonce)).Script() -} - // createCoinbaseTx returns a coinbase transaction paying an appropriate // subsidy based on the passed block height. The coinbase signature script // conforms to the requirements of version 2 blocks. func (g *testGenerator) createCoinbaseTx(blockHeight int32) *wire.MsgTx { extraNonce := uint64(0) - coinbaseScript, err := standardCoinbaseScript(blockHeight, extraNonce) + coinbaseScript, err := testhelper.StandardCoinbaseScript(blockHeight, extraNonce) if err != nil { panic(err) } diff --git a/blockchain/internal/testhelper/common.go b/blockchain/internal/testhelper/common.go index 49f80347e1..7d16c2f49d 100644 --- a/blockchain/internal/testhelper/common.go +++ b/blockchain/internal/testhelper/common.go @@ -21,6 +21,14 @@ var ( LowFee = btcutil.Amount(1) ) +// StandardCoinbaseScript returns a standard script suitable for use as the +// signature script of the coinbase transaction of a new block. In particular, +// it starts with the block height that is required by version 2 blocks. +func StandardCoinbaseScript(blockHeight int32, extraNonce uint64) ([]byte, error) { + return txscript.NewScriptBuilder().AddInt64(int64(blockHeight)). + AddInt64(int64(extraNonce)).Script() +} + // OpReturnScript returns a provably-pruneable OP_RETURN script with the // provided data. func OpReturnScript(data []byte) ([]byte, error) { From 8ab27b92451d8aff04f1da62ac80daa796202641 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 16:32:28 +0900 Subject: [PATCH 1000/1056] fullblocktests, testhelper: move createCoinbaseTx to testhelper createCoinbaseTx's code is refactored out and placed in testhelper package and is exported so that callers in package blockchain can reuse the code without introducing import cycles. The test code for invalidateblock and reconsiderblock that'll be added in later commits make use of this code. --- blockchain/fullblocktests/generate.go | 22 ++----------------- blockchain/internal/testhelper/common.go | 27 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 7bd838a5e0..2f092fdea1 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -224,26 +224,8 @@ func pushDataScript(items ...[]byte) []byte { // subsidy based on the passed block height. The coinbase signature script // conforms to the requirements of version 2 blocks. func (g *testGenerator) createCoinbaseTx(blockHeight int32) *wire.MsgTx { - extraNonce := uint64(0) - coinbaseScript, err := testhelper.StandardCoinbaseScript(blockHeight, extraNonce) - if err != nil { - panic(err) - } - - tx := wire.NewMsgTx(1) - tx.AddTxIn(&wire.TxIn{ - // Coinbase transactions have no inputs, so previous outpoint is - // zero hash and max index. - PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{}, - wire.MaxPrevOutIndex), - Sequence: wire.MaxTxInSequenceNum, - SignatureScript: coinbaseScript, - }) - tx.AddTxOut(&wire.TxOut{ - Value: blockchain.CalcBlockSubsidy(blockHeight, g.params), - PkScript: testhelper.OpTrueScript, - }) - return tx + return testhelper.CreateCoinbaseTx( + blockHeight, blockchain.CalcBlockSubsidy(blockHeight, g.params)) } // calcMerkleRoot creates a merkle tree from the slice of transactions and diff --git a/blockchain/internal/testhelper/common.go b/blockchain/internal/testhelper/common.go index 7d16c2f49d..0c45122c6d 100644 --- a/blockchain/internal/testhelper/common.go +++ b/blockchain/internal/testhelper/common.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/blockchain/internal/workmath" "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" ) @@ -21,6 +22,32 @@ var ( LowFee = btcutil.Amount(1) ) +// CreateCoinbaseTx returns a coinbase transaction paying an appropriate +// subsidy based on the passed block height and the block subsidy. The +// coinbase signature script conforms to the requirements of version 2 blocks. +func CreateCoinbaseTx(blockHeight int32, blockSubsidy int64) *wire.MsgTx { + extraNonce := uint64(0) + coinbaseScript, err := StandardCoinbaseScript(blockHeight, extraNonce) + if err != nil { + panic(err) + } + + tx := wire.NewMsgTx(1) + tx.AddTxIn(&wire.TxIn{ + // Coinbase transactions have no inputs, so previous outpoint is + // zero hash and max index. + PreviousOutPoint: *wire.NewOutPoint(&chainhash.Hash{}, + wire.MaxPrevOutIndex), + Sequence: wire.MaxTxInSequenceNum, + SignatureScript: coinbaseScript, + }) + tx.AddTxOut(&wire.TxOut{ + Value: blockSubsidy, + PkScript: OpTrueScript, + }) + return tx +} + // StandardCoinbaseScript returns a standard script suitable for use as the // signature script of the coinbase transaction of a new block. In particular, // it starts with the block height that is required by version 2 blocks. From 5df14376c11aa6e043a6832df206a9cc4b4a091f Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 16:42:41 +0900 Subject: [PATCH 1001/1056] fullblocktests, testhelper: move createSpendTx to testhelper createSpendTx is moved to testhelper so that the function can be used for callers in package blockchain without introducing import cycles. The test code for invalidateblock and reconsiderblock that are going to be added in later commits make use of this code. --- blockchain/fullblocktests/generate.go | 39 +++++------------------- blockchain/internal/testhelper/common.go | 23 ++++++++++++++ 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index 2f092fdea1..3f53c2b9f1 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -294,29 +294,6 @@ func additionalTx(tx *wire.MsgTx) func(*wire.MsgBlock) { } } -// createSpendTx creates a transaction that spends from the provided spendable -// output and includes an additional unique OP_RETURN output to ensure the -// transaction ends up with a unique hash. The script is a simple OP_TRUE -// script which avoids the need to track addresses and signature scripts in the -// tests. -func createSpendTx(spend *testhelper.SpendableOut, fee btcutil.Amount) *wire.MsgTx { - spendTx := wire.NewMsgTx(1) - spendTx.AddTxIn(&wire.TxIn{ - PreviousOutPoint: spend.PrevOut, - Sequence: wire.MaxTxInSequenceNum, - SignatureScript: nil, - }) - spendTx.AddTxOut(wire.NewTxOut(int64(spend.Amount-fee), - testhelper.OpTrueScript)) - opRetScript, err := testhelper.UniqueOpReturnScript() - if err != nil { - panic(err) - } - spendTx.AddTxOut(wire.NewTxOut(0, opRetScript)) - - return spendTx -} - // createSpendTxForTx creates a transaction that spends from the first output of // the provided transaction and includes an additional unique OP_RETURN output // to ensure the transaction ends up with a unique hash. The public key script @@ -324,7 +301,7 @@ func createSpendTx(spend *testhelper.SpendableOut, fee btcutil.Amount) *wire.Msg // signature scripts in the tests. The signature script is nil. func createSpendTxForTx(tx *wire.MsgTx, fee btcutil.Amount) *wire.MsgTx { spend := testhelper.MakeSpendableOutForTx(tx, 0) - return createSpendTx(&spend, fee) + return testhelper.CreateSpendTx(&spend, fee) } // nextBlock builds a new block that extends the current tip associated with the @@ -364,7 +341,7 @@ func (g *testGenerator) nextBlock(blockName string, spend *testhelper.SpendableO // add it to the list of transactions to include in the block. // The script is a simple OP_TRUE script in order to avoid the // need to track addresses and signature scripts in the tests. - txns = append(txns, createSpendTx(spend, fee)) + txns = append(txns, testhelper.CreateSpendTx(spend, fee)) } // Use a timestamp that is one second after the previous block unless @@ -1152,7 +1129,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // \-> b38(b37.tx[1]) // g.setTip("b35") - doubleSpendTx := createSpendTx(outs[11], testhelper.LowFee) + doubleSpendTx := testhelper.CreateSpendTx(outs[11], testhelper.LowFee) g.nextBlock("b37", outs[11], additionalTx(doubleSpendTx)) b37Tx1Out := testhelper.MakeSpendableOut(g.tip, 1, 0) rejected(blockchain.ErrMissingTxOut) @@ -1211,7 +1188,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // Create a signed transaction that spends from the // associated p2sh output in b39. spend := testhelper.MakeSpendableOutForTx(b39.Transactions[i+2], 2) - tx := createSpendTx(&spend, testhelper.LowFee) + tx := testhelper.CreateSpendTx(&spend, testhelper.LowFee) sig, err := txscript.RawTxInSignature(tx, 0, redeemScript, txscript.SigHashAll, g.privKey) if err != nil { @@ -1242,7 +1219,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { txnsNeeded := (maxBlockSigOps / redeemScriptSigOps) for i := 0; i < txnsNeeded; i++ { spend := testhelper.MakeSpendableOutForTx(b39.Transactions[i+2], 2) - tx := createSpendTx(&spend, testhelper.LowFee) + tx := testhelper.CreateSpendTx(&spend, testhelper.LowFee) sig, err := txscript.RawTxInSignature(tx, 0, redeemScript, txscript.SigHashAll, g.privKey) if err != nil { @@ -1291,7 +1268,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // ... -> b43(13) // \-> b44(14) g.nextBlock("b44", nil, func(b *wire.MsgBlock) { - nonCoinbaseTx := createSpendTx(outs[14], testhelper.LowFee) + nonCoinbaseTx := testhelper.CreateSpendTx(outs[14], testhelper.LowFee) b.Transactions[0] = nonCoinbaseTx }) rejected(blockchain.ErrFirstTxNotCoinbase) @@ -1688,7 +1665,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { // ... -> b65(19) // \-> b66(20) g.nextBlock("b66", nil, func(b *wire.MsgBlock) { - tx2 := createSpendTx(outs[20], testhelper.LowFee) + tx2 := testhelper.CreateSpendTx(outs[20], testhelper.LowFee) tx3 := createSpendTxForTx(tx2, testhelper.LowFee) b.AddTransaction(tx3) b.AddTransaction(tx2) @@ -1858,7 +1835,7 @@ func Generate(includeLargeReorg bool) (tests [][]TestInstance, err error) { zeroFee := btcutil.Amount(0) for i := uint32(0); i < numAdditionalOutputs; i++ { spend := testhelper.MakeSpendableOut(b, 1, i+2) - tx := createSpendTx(&spend, zeroFee) + tx := testhelper.CreateSpendTx(&spend, zeroFee) b.AddTransaction(tx) } }) diff --git a/blockchain/internal/testhelper/common.go b/blockchain/internal/testhelper/common.go index 0c45122c6d..681097480c 100644 --- a/blockchain/internal/testhelper/common.go +++ b/blockchain/internal/testhelper/common.go @@ -22,6 +22,29 @@ var ( LowFee = btcutil.Amount(1) ) +// CreateSpendTx creates a transaction that spends from the provided spendable +// output and includes an additional unique OP_RETURN output to ensure the +// transaction ends up with a unique hash. The script is a simple OP_TRUE +// script which avoids the need to track addresses and signature scripts in the +// tests. +func CreateSpendTx(spend *SpendableOut, fee btcutil.Amount) *wire.MsgTx { + spendTx := wire.NewMsgTx(1) + spendTx.AddTxIn(&wire.TxIn{ + PreviousOutPoint: spend.PrevOut, + Sequence: wire.MaxTxInSequenceNum, + SignatureScript: nil, + }) + spendTx.AddTxOut(wire.NewTxOut(int64(spend.Amount-fee), + OpTrueScript)) + opRetScript, err := UniqueOpReturnScript() + if err != nil { + panic(err) + } + spendTx.AddTxOut(wire.NewTxOut(0, opRetScript)) + + return spendTx +} + // CreateCoinbaseTx returns a coinbase transaction paying an appropriate // subsidy based on the passed block height and the block subsidy. The // coinbase signature script conforms to the requirements of version 2 blocks. From ea39fe090dddf45e3a91aaecd0dd6323ed5e5dc2 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 17:52:34 +0900 Subject: [PATCH 1002/1056] blockchain: add block generating functions in test code The block generating functions here allow for a test to create mock blocks. This is useful for testing invalidateblock and reconsiderblock methods on blockchain that will be added in later commits. --- blockchain/common_test.go | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/blockchain/common_test.go b/blockchain/common_test.go index 5037c1828e..12badd3ec0 100644 --- a/blockchain/common_test.go +++ b/blockchain/common_test.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "github.com/btcsuite/btcd/blockchain/internal/testhelper" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -396,3 +397,96 @@ func newFakeNode(parent *blockNode, blockVersion int32, bits uint32, timestamp t } return newBlockNode(header, parent) } + +// addBlock adds a block to the blockchain that succeeds the previous block. +// The blocks spends all the provided spendable outputs. The new block and +// the new spendable outputs created in the block are returned. +func addBlock(chain *BlockChain, prev *btcutil.Block, spends []*testhelper.SpendableOut) ( + *btcutil.Block, []*testhelper.SpendableOut, error) { + + block, outs, err := newBlock(chain, prev, spends) + if err != nil { + return nil, nil, err + } + + _, _, err = chain.ProcessBlock(block, BFNone) + if err != nil { + return nil, nil, err + } + + return block, outs, nil +} + +// calcMerkleRoot creates a merkle tree from the slice of transactions and +// returns the root of the tree. +func calcMerkleRoot(txns []*wire.MsgTx) chainhash.Hash { + if len(txns) == 0 { + return chainhash.Hash{} + } + + utilTxns := make([]*btcutil.Tx, 0, len(txns)) + for _, tx := range txns { + utilTxns = append(utilTxns, btcutil.NewTx(tx)) + } + return CalcMerkleRoot(utilTxns, false) +} + +// newBlock creates a block to the blockchain that succeeds the previous block. +// The blocks spends all the provided spendable outputs. The new block and the +// newly spendable outputs created in the block are returned. +func newBlock(chain *BlockChain, prev *btcutil.Block, + spends []*testhelper.SpendableOut) (*btcutil.Block, []*testhelper.SpendableOut, error) { + + blockHeight := prev.Height() + 1 + txns := make([]*wire.MsgTx, 0, 1+len(spends)) + + // Create and add coinbase tx. + cb := testhelper.CreateCoinbaseTx(blockHeight, CalcBlockSubsidy(blockHeight, chain.chainParams)) + txns = append(txns, cb) + + // Spend all txs to be spent. + for _, spend := range spends { + cb.TxOut[0].Value += int64(testhelper.LowFee) + + spendTx := testhelper.CreateSpendTx(spend, testhelper.LowFee) + txns = append(txns, spendTx) + } + + // Use a timestamp that is one second after the previous block unless + // this is the first block in which case the current time is used. + var ts time.Time + if blockHeight == 1 { + ts = time.Unix(time.Now().Unix(), 0) + } else { + ts = prev.MsgBlock().Header.Timestamp.Add(time.Second) + } + + // Create the block. The nonce will be solved in the below code in + // SolveBlock. + block := btcutil.NewBlock(&wire.MsgBlock{ + Header: wire.BlockHeader{ + Version: 1, + PrevBlock: *prev.Hash(), + MerkleRoot: calcMerkleRoot(txns), + Bits: chain.chainParams.PowLimitBits, + Timestamp: ts, + Nonce: 0, // To be solved. + }, + Transactions: txns, + }) + block.SetHeight(blockHeight) + + // Solve the block. + if !testhelper.SolveBlock(&block.MsgBlock().Header) { + return nil, nil, fmt.Errorf("Unable to solve block at height %d", blockHeight) + } + + // Create spendable outs to return. + outs := make([]*testhelper.SpendableOut, len(txns)) + for i, tx := range txns { + out := testhelper.MakeSpendableOutForTx(tx, 0) + outs[i] = &out + } + + return block, outs, nil +} From f93f8501e3a45fc8cc8beb84c09047d09e4b62bc Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 23 Apr 2024 04:30:25 +0900 Subject: [PATCH 1003/1056] release: add darwin-arm64 to target binaries (#2173) All currently released Apple computers have arm architecture and it's good to release something native for these computers. --- release/release.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/release/release.sh b/release/release.sh index de49f64122..49dee89638 100755 --- a/release/release.sh +++ b/release/release.sh @@ -40,6 +40,7 @@ cd $MAINDIR # for a subset of systems/architectures. SYS=${BTCDBUILDSYS:-" darwin-amd64 + darwin-arm64 dragonfly-amd64 freebsd-386 freebsd-amd64 From f1bded4ff65ff3fdbceb351cd62426e5d0a4c1d2 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 24 Apr 2024 00:11:15 +0900 Subject: [PATCH 1004/1056] chaincfg: update dnsseeds (#2174) * chaincfg: remove unresponsive dnsseed on testnet testnet-seed.bitcoin.schildbach.de is unresponsive and doesn't return any ips. Bitcoin Core has already removed it and we don't also be getting rid of it as well. * chaincfg: add dnsseeds from Sjors Provoost His seeds work well and we don't have any for signet and it's good to replace the lost dns seed on testnet. * chaincfg: remove bad dnsseed (seed.bitcoinstats.com) seed.bitcoinstats.com doesn't respect filter requests even though it's advertised as it does. Plus it often returns nodes that are unreachable. In my testing over the past week, it's been the most unreliable dns seed and since we have plenty of mainnet seeds, it's better to do away with this. I documented my findings for this in a Bitcoin Core issue: https://github.com/bitcoin/bitcoin/issues/29911 * chaincfg: add dnsseed from wiz It's the same infrastructure that mempool . space runs on and has been reliable. The same seed is also included in Bitcoin Core as well. --- chaincfg/params.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/chaincfg/params.go b/chaincfg/params.go index 3a7f7661e1..1c329cb50f 100644 --- a/chaincfg/params.go +++ b/chaincfg/params.go @@ -59,6 +59,7 @@ var ( // DefaultSignetDNSSeeds is the list of seed nodes for the default // (public, Taproot enabled) signet network. DefaultSignetDNSSeeds = []DNSSeed{ + {"seed.signet.bitcoin.sprovoost.nl", true}, {"178.128.221.177", false}, {"2a01:7c8:d005:390::5", false}, {"v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333", false}, @@ -284,10 +285,11 @@ var MainNetParams = Params{ {"seed.bitcoin.sipa.be", true}, {"dnsseed.bluematt.me", true}, {"dnsseed.bitcoin.dashjr.org", false}, - {"seed.bitcoinstats.com", true}, {"seed.bitnodes.io", false}, {"seed.bitcoin.jonasschnelli.ch", true}, {"seed.btc.petertodd.net", true}, + {"seed.bitcoin.sprovoost.nl", true}, + {"seed.bitcoin.wiz.biz", true}, }, // Chain parameters @@ -544,8 +546,8 @@ var TestNet3Params = Params{ DefaultPort: "18333", DNSSeeds: []DNSSeed{ {"testnet-seed.bitcoin.jonasschnelli.ch", true}, - {"testnet-seed.bitcoin.schildbach.de", false}, {"seed.tbtc.petertodd.net", true}, + {"seed.testnet.bitcoin.sprovoost.nl", true}, {"testnet-seed.bluematt.me", false}, }, From 126b0ecff1c15a3fc365fdf77f51201ab469347a Mon Sep 17 00:00:00 2001 From: oftenoccur <166520808+oftenoccur@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:08:05 +0800 Subject: [PATCH 1005/1056] chore: fix some typos in comments (#2164) Signed-off-by: oftenoccur --- blockchain/fullblocktests/generate.go | 2 +- blockchain/timesorter.go | 2 +- blockchain/validate.go | 2 +- btcec/schnorr/musig2/nonces_test.go | 2 +- mempool/doc.go | 2 +- txscript/engine.go | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/blockchain/fullblocktests/generate.go b/blockchain/fullblocktests/generate.go index fe36bfe136..e8fad241fa 100644 --- a/blockchain/fullblocktests/generate.go +++ b/blockchain/fullblocktests/generate.go @@ -608,7 +608,7 @@ func (g *testGenerator) saveTipCoinbaseOut() { } // saveSpendableCoinbaseOuts adds all coinbase outputs from the last block that -// had its coinbase tx output colleted to the current tip. This is useful to +// had its coinbase tx output collected to the current tip. This is useful to // batch the collection of coinbase outputs once the tests reach a stable point // so they don't have to manually add them for the right tests which will // ultimately end up being the best chain. diff --git a/blockchain/timesorter.go b/blockchain/timesorter.go index d0288e1d30..4a5498b258 100644 --- a/blockchain/timesorter.go +++ b/blockchain/timesorter.go @@ -20,7 +20,7 @@ func (s timeSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -// Less returns whether the timstamp with index i should sort before the +// Less returns whether the timestamp with index i should sort before the // timestamp with index j. It is part of the sort.Interface implementation. func (s timeSorter) Less(i, j int) bool { return s[i] < s[j] diff --git a/blockchain/validate.go b/blockchain/validate.go index 6c49bd565d..5e24405ef9 100644 --- a/blockchain/validate.go +++ b/blockchain/validate.go @@ -761,7 +761,7 @@ func CheckBlockHeaderContext(header *wire.BlockHeader, prevNode HeaderCtx, return nil } -// checkBlockContext peforms several validation checks on the block which depend +// checkBlockContext performs several validation checks on the block which depend // on its position within the block chain. // // The flags modify the behavior of this function as follows: diff --git a/btcec/schnorr/musig2/nonces_test.go b/btcec/schnorr/musig2/nonces_test.go index 7105d83b30..074fe7363a 100644 --- a/btcec/schnorr/musig2/nonces_test.go +++ b/btcec/schnorr/musig2/nonces_test.go @@ -111,7 +111,7 @@ type nonceAggTestCases struct { } // TestMusig2AggregateNoncesTestVectors tests that the musig2 implementation -// passes the nonce aggregration test vectors for musig2 1.0. +// passes the nonce aggregation test vectors for musig2 1.0. func TestMusig2AggregateNoncesTestVectors(t *testing.T) { t.Parallel() diff --git a/mempool/doc.go b/mempool/doc.go index 22fb2a06a0..8c6c0bc1ea 100644 --- a/mempool/doc.go +++ b/mempool/doc.go @@ -5,7 +5,7 @@ /* Package mempool provides a policy-enforced pool of unmined bitcoin transactions. -A key responsbility of the bitcoin network is mining user-generated transactions +A key responsibility of the bitcoin network is mining user-generated transactions into blocks. In order to facilitate this, the mining process relies on having a readily-available source of transactions to include in a block that is being solved. diff --git a/txscript/engine.go b/txscript/engine.go index 3725845104..d4bedc956b 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -450,7 +450,7 @@ func checkMinimalDataPush(op *opcode, data []byte) error { return nil } -// executeOpcode peforms execution on the passed opcode. It takes into account +// executeOpcode performs execution on the passed opcode. It takes into account // whether or not it is hidden by conditionals, but some rules still must be // tested in this case. func (vm *Engine) executeOpcode(op *opcode, data []byte) error { From 6b197d38d745048c5fe2a895010c9c0a4d9ab2a6 Mon Sep 17 00:00:00 2001 From: MarkDaveny <168091250+MarkDaveny@users.noreply.github.com> Date: Mon, 29 Apr 2024 23:45:39 +0800 Subject: [PATCH 1006/1056] chore: fix some function names (#2180) Signed-off-by: MarkDaveny --- btcutil/address.go | 4 ++-- btcutil/bech32/bech32_test.go | 2 +- btcutil/gcs/gcsbench_test.go | 4 ++-- btcutil/hdkeychain/extendedkey.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/btcutil/address.go b/btcutil/address.go index d0367abfc8..95d3e6c301 100644 --- a/btcutil/address.go +++ b/btcutil/address.go @@ -686,8 +686,8 @@ func NewAddressTaproot(witnessProg []byte, return newAddressTaproot(net.Bech32HRPSegwit, witnessProg) } -// newAddressWitnessScriptHash is an internal helper function to create an -// AddressWitnessScriptHash with a known human-readable part, rather than +// newAddressTaproot is an internal helper function to create an +// AddressTaproot with a known human-readable part, rather than // looking it up through its parameters. func newAddressTaproot(hrp string, witnessProg []byte) (*AddressTaproot, error) { diff --git a/btcutil/bech32/bech32_test.go b/btcutil/bech32/bech32_test.go index 354ba7a17a..3f637c4034 100644 --- a/btcutil/bech32/bech32_test.go +++ b/btcutil/bech32/bech32_test.go @@ -668,7 +668,7 @@ func BenchmarkConvertBitsDown(b *testing.B) { } } -// BenchmarkConvertBitsDown benchmarks the speed and memory allocation behavior +// BenchmarkConvertBitsUp benchmarks the speed and memory allocation behavior // of ConvertBits when converting from a lower base into a higher base (e.g. 5 // => 8). // diff --git a/btcutil/gcs/gcsbench_test.go b/btcutil/gcs/gcsbench_test.go index 14125a16c0..69ce7708b3 100644 --- a/btcutil/gcs/gcsbench_test.go +++ b/btcutil/gcs/gcsbench_test.go @@ -158,7 +158,7 @@ var matchAnyBenchmarks = []struct { {"q10M-f10K", randElems10000000, filter10000}, } -// BenchmarkGCSFilterMatchAny benchmarks the sort-and-zip MatchAny impl. +// BenchmarkGCSFilterZipMatchAny benchmarks the sort-and-zip MatchAny impl. func BenchmarkGCSFilterZipMatchAny(b *testing.B) { for _, test := range matchAnyBenchmarks { test := test @@ -184,7 +184,7 @@ func BenchmarkGCSFilterZipMatchAny(b *testing.B) { } } -// BenchmarkGCSFilterMatchAny benchmarks the hash-join MatchAny impl. +// BenchmarkGCSFilterHashMatchAny benchmarks the hash-join MatchAny impl. func BenchmarkGCSFilterHashMatchAny(b *testing.B) { for _, test := range matchAnyBenchmarks { test := test diff --git a/btcutil/hdkeychain/extendedkey.go b/btcutil/hdkeychain/extendedkey.go index 0bbb1e7d19..8bbcdceef4 100644 --- a/btcutil/hdkeychain/extendedkey.go +++ b/btcutil/hdkeychain/extendedkey.go @@ -467,7 +467,7 @@ func (k *ExtendedKey) DeriveNonStandard(i uint32) (*ExtendedKey, error) { k.depth+1, i, isPrivate), nil } -// ChildNum returns the index at which the child extended key was derived. +// ChildIndex returns the index at which the child extended key was derived. // // Extended keys with ChildNum value between 0 and 2^31-1 are normal child // keys, and those with a value between 2^31 and 2^32-1 are hardened keys. From 635ae689578399e2d6e867468f93188fdc52a368 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 2 Apr 2024 17:56:12 +0900 Subject: [PATCH 1007/1056] blockchain: Add InvalidateBlock() method to BlockChain InvalidateBlock() invalidates a given block and marks all its descendents as invalid as well. The active chain tip changes if the invalidated block is part of the best chain. --- blockchain/chain.go | 138 +++++++++++++++++ blockchain/chain_test.go | 311 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 449 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index 7e06e5c77c..8e75b447e9 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1798,6 +1798,144 @@ func (b *BlockChain) LocateHeaders(locator BlockLocator, hashStop *chainhash.Has return headers } +// InvalidateBlock invalidates the requested block and all its descedents. If a block +// in the best chain is invalidated, the active chain tip will be the parent of the +// invalidated block. +// +// This function is safe for concurrent access. +func (b *BlockChain) InvalidateBlock(hash *chainhash.Hash) error { + b.chainLock.Lock() + defer b.chainLock.Unlock() + + node := b.index.LookupNode(hash) + if node == nil { + // Return an error if the block doesn't exist. + return fmt.Errorf("Requested block hash of %s is not found "+ + "and thus cannot be invalidated.", hash) + } + if node.height == 0 { + return fmt.Errorf("Requested block hash of %s is a at height 0 "+ + "and is thus a genesis block and cannot be invalidated.", + node.hash) + } + + // Nothing to do if the given block is already invalid. + if node.status.KnownInvalid() { + return nil + } + + // Set the status of the block being invalidated. + b.index.SetStatusFlags(node, statusValidateFailed) + b.index.UnsetStatusFlags(node, statusValid) + + // If the block we're invalidating is not on the best chain, we simply + // mark the block and all its descendants as invalid and return. + if !b.bestChain.Contains(node) { + // Grab all the tips excluding the active tip. + tips := b.index.InactiveTips(b.bestChain) + for _, tip := range tips { + // Continue if the given inactive tip is not a descendant of the block + // being invalidated. + if !tip.IsAncestor(node) { + continue + } + + // Keep going back until we get to the block being invalidated. + // For each of the parent, we'll unset valid status and set invalid + // ancestor status. + for n := tip; n != nil && n != node; n = n.parent { + // Continue if it's already invalid. + if n.status.KnownInvalid() { + continue + } + b.index.SetStatusFlags(n, statusInvalidAncestor) + b.index.UnsetStatusFlags(n, statusValid) + } + } + + if writeErr := b.index.flushToDB(); writeErr != nil { + return fmt.Errorf("Error flushing block index "+ + "changes to disk: %v", writeErr) + } + + // Return since the block being invalidated is on a side branch. + // Nothing else left to do. + return nil + } + + // If we're here, it means a block from the active chain tip is getting + // invalidated. + // + // Grab all the nodes to detach from the active chain. + detachNodes := list.New() + for n := b.bestChain.Tip(); n != nil && n != node; n = n.parent { + // Continue if it's already invalid. + if n.status.KnownInvalid() { + continue + } + + // Change the status of the block node. + b.index.SetStatusFlags(n, statusInvalidAncestor) + b.index.UnsetStatusFlags(n, statusValid) + detachNodes.PushBack(n) + } + + // Push back the block node being invalidated. + detachNodes.PushBack(node) + + // Reorg back to the parent of the block being invalidated. + // Nothing to attach so just pass an empty list. + err := b.reorganizeChain(detachNodes, list.New()) + if err != nil { + return err + } + + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", writeErr) + } + + // Grab all the tips. + tips := b.index.InactiveTips(b.bestChain) + tips = append(tips, b.bestChain.Tip()) + + // Here we'll check if the invalidation of the block in the active tip + // changes the status of the chain tips. If a side branch now has more + // worksum, it becomes the active chain tip. + var bestTip *blockNode + for _, tip := range tips { + // Skip invalid tips as they cannot become the active tip. + if tip.status.KnownInvalid() { + continue + } + + // If we have no best tips, then set this tip as the best tip. + if bestTip == nil { + bestTip = tip + } else { + // If there is an existing best tip, then compare it + // against the current tip. + if tip.workSum.Cmp(bestTip.workSum) == 1 { + bestTip = tip + } + } + } + + // Return if the best tip is the current tip. + if bestTip == b.bestChain.Tip() { + return nil + } + + // Reorganize to the best tip if a side branch is now the most work tip. + detachNodes, attachNodes := b.getReorganizeNodes(bestTip) + err = b.reorganizeChain(detachNodes, attachNodes) + + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", writeErr) + } + + return err +} + // IndexManager provides a generic interface that the is called when blocks are // connected and disconnected to and from the tip of the main chain for the // purpose of supporting optional indexes. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index 259a643f3c..57bbd6246c 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -6,10 +6,12 @@ package blockchain import ( "fmt" + "math/rand" "reflect" "testing" "time" + "github.com/btcsuite/btcd/blockchain/internal/testhelper" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -1311,3 +1313,312 @@ func TestIsAncestor(t *testing.T) { branch2Nodes[0].hash.String()) } } + +// randomSelect selects random amount of random elements from a slice and returns a +// new slice. The selected elements are removed. +func randomSelect(input []*testhelper.SpendableOut) ( + []*testhelper.SpendableOut, []*testhelper.SpendableOut) { + + selected := []*testhelper.SpendableOut{} + + // Select random elements from the input slice + amount := rand.Intn(len(input)) + for i := 0; i < amount; i++ { + // Generate a random index + randIdx := rand.Intn(len(input)) + + // Append the selected element to the new slice + selected = append(selected, input[randIdx]) + + // Remove the selected element from the input slice. + // This ensures that each selected element is unique. + input = append(input[:randIdx], input[randIdx+1:]...) + } + + return input, selected +} + +// addBlocks generates new blocks and adds them to the chain. The newly generated +// blocks will spend from the spendable outputs passed in. The returned hases are +// the hashes of the newly generated blocks. +func addBlocks(count int, chain *BlockChain, prevBlock *btcutil.Block, + allSpendableOutputs []*testhelper.SpendableOut) ( + []*chainhash.Hash, [][]*testhelper.SpendableOut, error) { + + blockHashes := make([]*chainhash.Hash, 0, count) + spendablesOuts := make([][]*testhelper.SpendableOut, 0, count) + + // Always spend everything on the first block. This ensures we get unique blocks + // every time. The random select may choose not to spend any and that results + // in getting the same block. + nextSpends := allSpendableOutputs + allSpendableOutputs = allSpendableOutputs[:0] + for b := 0; b < count; b++ { + newBlock, newSpendableOuts, err := addBlock(chain, prevBlock, nextSpends) + if err != nil { + return nil, nil, err + } + prevBlock = newBlock + + blockHashes = append(blockHashes, newBlock.Hash()) + spendablesOuts = append(spendablesOuts, newSpendableOuts) + allSpendableOutputs = append(allSpendableOutputs, newSpendableOuts...) + + // Grab utxos to be spent in the next block. + allSpendableOutputs, nextSpends = randomSelect(allSpendableOutputs) + } + + return blockHashes, spendablesOuts, nil +} + +func TestInvalidateBlock(t *testing.T) { + tests := []struct { + name string + chainGen func() (*BlockChain, []*chainhash.Hash, func()) + }{ + { + name: "one branch, invalidate once", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain( + "TestInvalidateBlock-one-branch-" + + "invalidate-once") + // Grab the tip of the chain. + tip := btcutil.NewBlock(params.GenesisBlock) + + // Create a chain with 11 blocks. + _, _, err := addBlocks(11, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Invalidate block 5. + block, err := chain.BlockByHeight(5) + if err != nil { + t.Fatal(err) + } + invalidateHash := block.Hash() + + return chain, []*chainhash.Hash{invalidateHash}, tearDown + }, + }, + { + name: "invalidate twice", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain("TestInvalidateBlock-invalidate-twice") + // Grab the tip of the chain. + tip := btcutil.NewBlock(params.GenesisBlock) + + // Create a chain with 11 blocks. + _, spendableOuts, err := addBlocks(11, chain, tip, []*testhelper.SpendableOut{}) + //_, _, err := addBlocks(11, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Set invalidateHash as block 5. + block, err := chain.BlockByHeight(5) + if err != nil { + t.Fatal(err) + } + invalidateHash := block.Hash() + + // Create a side chain with 7 blocks that builds on block 1. + b1, err := chain.BlockByHeight(1) + if err != nil { + t.Fatal(err) + } + altBlockHashes, _, err := addBlocks(6, chain, b1, spendableOuts[0]) + if err != nil { + t.Fatal(err) + } + + // Grab block at height 5: + // + // b2, b3, b4, b5 + // 0, 1, 2, 3 + invalidateHash2 := altBlockHashes[3] + + // Sanity checking that we grabbed the correct hash. + node := chain.index.LookupNode(invalidateHash) + if node == nil || node.height != 5 { + t.Fatalf("wanted to grab block at height 5 but got height %v", + node.height) + } + + return chain, []*chainhash.Hash{invalidateHash, invalidateHash2}, tearDown + }, + }, + { + name: "invalidate a side branch", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain("TestInvalidateBlock-invalidate-side-branch") + tip := btcutil.NewBlock(params.GenesisBlock) + + // Grab the tip of the chain. + tip, err := chain.BlockByHash(&chain.bestChain.Tip().hash) + if err != nil { + t.Fatal(err) + } + + // Create a chain with 11 blocks. + _, spendableOuts, err := addBlocks(11, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Create a side chain with 7 blocks that builds on block 1. + b1, err := chain.BlockByHeight(1) + if err != nil { + t.Fatal(err) + } + altBlockHashes, _, err := addBlocks(6, chain, b1, spendableOuts[0]) + if err != nil { + t.Fatal(err) + } + + // Grab block at height 4: + // + // b2, b3, b4 + // 0, 1, 2 + invalidateHash := altBlockHashes[2] + + // Sanity checking that we grabbed the correct hash. + node := chain.index.LookupNode(invalidateHash) + if node == nil || node.height != 4 { + t.Fatalf("wanted to grab block at height 4 but got height %v", + node.height) + } + + return chain, []*chainhash.Hash{invalidateHash}, tearDown + }, + }, + } + + for _, test := range tests { + chain, invalidateHashes, tearDown := test.chainGen() + func() { + defer tearDown() + for _, invalidateHash := range invalidateHashes { + chainTipsBefore := chain.ChainTips() + + // Mark if we're invalidating a block that's a part of the best chain. + var bestChainBlock bool + node := chain.index.LookupNode(invalidateHash) + if chain.bestChain.Contains(node) { + bestChainBlock = true + } + + // Actual invalidation. + err := chain.InvalidateBlock(invalidateHash) + if err != nil { + t.Fatal(err) + } + + chainTipsAfter := chain.ChainTips() + + // Create a map for easy lookup. + chainTipMap := make(map[chainhash.Hash]ChainTip, len(chainTipsAfter)) + activeTipCount := 0 + for _, chainTip := range chainTipsAfter { + chainTipMap[chainTip.BlockHash] = chainTip + + if chainTip.Status == StatusActive { + activeTipCount++ + } + } + if activeTipCount != 1 { + t.Fatalf("TestInvalidateBlock fail. Expected "+ + "1 active chain tip but got %d", activeTipCount) + } + + bestTip := chain.bestChain.Tip() + + validForkCount := 0 + for _, tip := range chainTipsBefore { + // If the chaintip was an active tip and we invalidated a block + // in the active tip, assert that it's invalid now. + if bestChainBlock && tip.Status == StatusActive { + gotTip, found := chainTipMap[tip.BlockHash] + if !found { + t.Fatalf("TestInvalidateBlock fail. Expected "+ + "block %s not found in chaintips after "+ + "invalidateblock", tip.BlockHash.String()) + } + + if gotTip.Status != StatusInvalid { + t.Fatalf("TestInvalidateBlock fail. "+ + "Expected block %s to be invalid, got status: %s", + gotTip.BlockHash.String(), gotTip.Status) + } + } + + if !bestChainBlock && tip.Status != StatusActive { + gotTip, found := chainTipMap[tip.BlockHash] + if !found { + t.Fatalf("TestInvalidateBlock fail. Expected "+ + "block %s not found in chaintips after "+ + "invalidateblock", tip.BlockHash.String()) + } + + if gotTip.BlockHash == *invalidateHash && gotTip.Status != StatusInvalid { + t.Fatalf("TestInvalidateBlock fail. "+ + "Expected block %s to be invalid, got status: %s", + gotTip.BlockHash.String(), gotTip.Status) + } + } + + // If we're not invalidating the branch with an active tip, + // we expect the active tip to remain the same. + if !bestChainBlock && tip.Status == StatusActive && tip.BlockHash != bestTip.hash { + t.Fatalf("TestInvalidateBlock fail. Expected block %s as the tip but got %s", + tip.BlockHash.String(), bestTip.hash.String()) + } + + // If this tip is not invalid and not active, it should be + // lighter than the current best tip. + if tip.Status != StatusActive && tip.Status != StatusInvalid && + tip.Height > bestTip.height { + + tipNode := chain.index.LookupNode(&tip.BlockHash) + if bestTip.workSum.Cmp(tipNode.workSum) == -1 { + t.Fatalf("TestInvalidateBlock fail. Expected "+ + "block %s to be the active tip but block %s "+ + "was", tipNode.hash.String(), bestTip.hash.String()) + } + } + + if tip.Status == StatusValidFork { + validForkCount++ + } + } + + // If there are no other valid chain tips besides the active chaintip, + // we expect to have one more chain tip after the invalidate. + if validForkCount == 0 && len(chainTipsAfter) != len(chainTipsBefore)+1 { + t.Fatalf("TestInvalidateBlock fail. Expected %d chaintips but got %d", + len(chainTipsBefore)+1, len(chainTipsAfter)) + } + } + + // Try to invaliate the already invalidated hash. + err := chain.InvalidateBlock(invalidateHashes[0]) + if err != nil { + t.Fatal(err) + } + + // Try to invaliate a genesis block + err = chain.InvalidateBlock(chain.chainParams.GenesisHash) + if err == nil { + t.Fatalf("TestInvalidateBlock fail. Expected to err when trying to" + + "invalidate a genesis block.") + } + + // Try to invaliate a block that doesn't exist. + err = chain.InvalidateBlock(chaincfg.MainNetParams.GenesisHash) + if err == nil { + t.Fatalf("TestInvalidateBlock fail. Expected to err when trying to" + + "invalidate a block that doesn't exist.") + } + }() + } +} From 689ac6b6de176fa153b3f7579a1d1a23e3b5c668 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 1 May 2024 17:58:42 +0900 Subject: [PATCH 1008/1056] blockchain: remove trailing ":" and space on utxocache log --- blockchain/utxocache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockchain/utxocache.go b/blockchain/utxocache.go index 1902ade679..550d8c5602 100644 --- a/blockchain/utxocache.go +++ b/blockchain/utxocache.go @@ -234,7 +234,7 @@ func newUtxoCache(db database.DB, maxTotalMemoryUsage uint64) *utxoCache { numMaxElements := calculateMinEntries(int(maxTotalMemoryUsage), bucketSize+avgEntrySize) numMaxElements -= 1 - log.Infof("Pre-alloacting for %d MiB: ", maxTotalMemoryUsage/(1024*1024)+1) + log.Infof("Pre-alloacting for %d MiB", maxTotalMemoryUsage/(1024*1024)+1) m := make(map[wire.OutPoint]*UtxoEntry, numMaxElements) From d65999e4a18171bde2be9c015ba68ed3e9c175d9 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Wed, 1 May 2024 17:59:18 +0900 Subject: [PATCH 1009/1056] main: add logging if the node is pruned For debug purposes down the road, log that the node is pruned if it's set to pruned. --- server.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server.go b/server.go index 0aa84d1f9c..9fca2db20c 100644 --- a/server.go +++ b/server.go @@ -2823,6 +2823,11 @@ func newServer(listenAddrs, agentBlacklist, agentWhitelist []string, checkpoints = mergeCheckpoints(s.chainParams.Checkpoints, cfg.addCheckpoints) } + // Log that the node is pruned. + if cfg.Prune != 0 { + btcdLog.Infof("Prune set to %d MiB", cfg.Prune) + } + // Create a new block chain instance with the appropriate configuration. var err error s.chain, err = blockchain.New(&blockchain.Config{ From 2492b01f69ea8d44f73b059afedf1c58374b8dbe Mon Sep 17 00:00:00 2001 From: marcoezekiel Date: Thu, 9 May 2024 11:24:30 -0600 Subject: [PATCH 1010/1056] btcutil/bech32: Added DecodeNoLimitWithVersion This exposes publicly the ability to decode arbitrary-length bech32 strings and return the bech32 version that was used in the encoding. It provides the underlying functionality for both DecodeNoLimit and DecodeGeneric. --- btcutil/bech32/bech32.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/btcutil/bech32/bech32.go b/btcutil/bech32/bech32.go index a7b056bd7a..92994b2881 100644 --- a/btcutil/bech32/bech32.go +++ b/btcutil/bech32/bech32.go @@ -165,11 +165,14 @@ func bech32VerifyChecksum(hrp string, data []byte) (Version, bool) { return VersionUnknown, false } -// DecodeNoLimit is a bech32 checksum version aware arbitrary string length -// decoder. This function will return the version of the decoded checksum -// constant so higher level validation can be performed to ensure the correct -// version of bech32 was used when encoding. -func decodeNoLimit(bech string) (string, []byte, Version, error) { +// DecodeNoLimitWithVersion is a bech32 checksum version aware arbitrary string +// length decoder. This function will return the version of the decoded +// checksum constant so higher level validation can be performed to ensure the +// correct version of bech32 was used when encoding. +// +// Note that the returned data is 5-bit (base32) encoded and the human-readable +// part will be lowercase. +func DecodeNoLimitWithVersion(bech string) (string, []byte, Version, error) { // The minimum allowed size of a bech32 string is 8 characters, since it // needs a non-empty HRP, a separator, and a 6 character checksum. if len(bech) < 8 { @@ -262,7 +265,7 @@ func decodeNoLimit(bech string) (string, []byte, Version, error) { // Note that the returned data is 5-bit (base32) encoded and the human-readable // part will be lowercase. func DecodeNoLimit(bech string) (string, []byte, error) { - hrp, data, _, err := decodeNoLimit(bech) + hrp, data, _, err := DecodeNoLimitWithVersion(bech) return hrp, data, err } @@ -277,7 +280,7 @@ func Decode(bech string) (string, []byte, error) { return "", nil, ErrInvalidLength(len(bech)) } - hrp, data, _, err := decodeNoLimit(bech) + hrp, data, _, err := DecodeNoLimitWithVersion(bech) return hrp, data, err } @@ -291,7 +294,7 @@ func DecodeGeneric(bech string) (string, []byte, Version, error) { return "", nil, VersionUnknown, ErrInvalidLength(len(bech)) } - return decodeNoLimit(bech) + return DecodeNoLimitWithVersion(bech) } // encodeGeneric is the base bech32 encoding function that is aware of the From 04469e600e7d4a58881e2e5447d19024e49800f5 Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Wed, 10 Apr 2024 13:58:44 -0400 Subject: [PATCH 1011/1056] txscript: make OP_CODESEPARATOR non-standard in non-segwit scripts --- txscript/data/tx_invalid.json | 26 +++++++++++++++ txscript/data/tx_valid.json | 12 ++++--- txscript/engine.go | 4 +++ txscript/error.go | 10 ++++++ txscript/error_test.go | 2 ++ txscript/opcode.go | 26 ++++++++++++--- txscript/reference_test.go | 2 ++ txscript/script.go | 58 +++++++++++++++++++++------------ txscript/script_test.go | 27 ++++++++++++---- txscript/sigvalidate.go | 60 ++++++++++++++++++++++------------- txscript/standard.go | 3 +- txscript/taproot.go | 4 +-- 12 files changed, 172 insertions(+), 62 deletions(-) diff --git a/txscript/data/tx_invalid.json b/txscript/data/tx_invalid.json index db465109aa..5e7f5607ae 100644 --- a/txscript/data/tx_invalid.json +++ b/txscript/data/tx_invalid.json @@ -333,6 +333,32 @@ ["BIP143: wrong sighash (with FindAndDelete) = 17c50ec2181ecdfdc85ca081174b248199ba81fff730794d4f69b8ec031f2dce"], [[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]], "010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601010221023cb6055f4b57a1580c5a753e19610cafaedf7e0ff377731c77837fd666eae1712102c1b1db303ac232ffa8e5e7cc2cf5f96c6e40d3e6914061204c0541cb2043a0969552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS"], +[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], +"01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], +"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]], +"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], +"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]], +"01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH,CONST_SCRIPTCODE"], +[[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], +["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]], +"0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH,CONST_SCRIPTCODE"], +[[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"], +["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]], +"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH,CONST_SCRIPTCODE"], ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/txscript/data/tx_valid.json b/txscript/data/tx_valid.json index d70fa54333..a2de155383 100644 --- a/txscript/data/tx_valid.json +++ b/txscript/data/tx_valid.json @@ -471,17 +471,17 @@ ["BIP143 example: P2WSH with OP_CODESEPARATOR and out-of-range SIGHASH_SINGLE."], [[["6eb316926b1c5d567cd6f5e6a84fec606fc53d7b474526d1fff3948020c93dfe", 0, "0x21 0x036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8 CHECKSIG", 156250000], ["f825690aee1b3dc247da796cacb12687a5e802429fd291cfd63e010f02cf1508", 0, "0x00 0x20 0x5d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0", 4900000000]], -"01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", "P2SH,WITNESS"], +"01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", "P2SH,WITNESS,CONST_SCRIPTCODE"], ["BIP143 example: P2WSH with unexecuted OP_CODESEPARATOR and SINGLE|ANYONECANPAY"], [[["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215], ["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215]], -"01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"], +"01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS,CONST_SCRIPTCODE"], ["BIP143 example: Same as the previous example with input-output pairs swapped"], [[["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215], ["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215]], -"0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"], +"0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS,CONST_SCRIPTCODE"], ["BIP143 example: P2SH-P2WSH 6-of-6 multisig signed with 6 different SIGHASH types"], [[["6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", 1, "HASH160 0x14 0x9993a429037b5d912407a71c252019287b8d27a5 EQUAL", 987654321]], @@ -498,7 +498,7 @@ "010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0121037a3fb04bcdb09eba90f69961ba1692a3528e45e67c85b200df820212d7594d334aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"], ["BIP143: correct sighash (without FindAndDelete) = 71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"], [[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7500, "0x00 0x20 0x9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", 200000]], -"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS"], +"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS,CONST_SCRIPTCODE"], ["This is multisig version of the FindAndDelete tests"], ["Script is 2 CHECKMULTISIGVERIFY DROP"], ["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"], @@ -508,7 +508,9 @@ "01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601522102cd74a2809ffeeed0092bc124fd79836706e41f048db3f6ae9df8708cefb83a1c2102e615999372426e46fd107b76eaf007156a507584aa2cc21de9eee3bdbd26d36c4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"], ["BIP143: correct sighash (without FindAndDelete) = c1628a1e7c67f14ca0c27c06e4fdeec2e6d1a73c7a91d7c046ff83e835aebb72"], [[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]], -"010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960101022102966f109c54e85d3aee8321301136cedeb9fc710fdef58a9de8a73942f8e567c021034ffc99dd9a79dd3cb31e2ab3e0b09e0e67db41ac068c625cd1f491576016c84e9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS"], +"010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960101022102966f109c54e85d3aee8321301136cedeb9fc710fdef58a9de8a73942f8e567c021034ffc99dd9a79dd3cb31e2ab3e0b09e0e67db41ac068c625cd1f491576016c84e9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS,CONST_SCRIPTCODE"], +[[["7a554c397846f025738965683b8448d79458c54b869f6391ece95145c962e65f", 0, "OP_HASH160 0x149512447916448e4193c321f2d599dff2538973f3 OP_EQUAL", 0]], +"02000000015fe662c94551e9ec91639f864bc55894d748843b6865897325f04678394c557a0000000039093006020101020101012103f0665be3ccc59a592608790e84bcf117349fc76c77d06cd3fb323548c310ff340cad0a09300602010102010101ffffffff010000000000000000015100000000", "CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,CLEANSTACK,DERSIG,DISCOURAGE_UPGRADABLE_NOPS,LOW_S,MINIMALDATA,NULLDUMMY,NULLFAIL,P2SH,SIGPUSHONLY,STRICTENC,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM,MINIMALIF,WITNESS_PUBKEYTYPE,TAPROOT"], ["Make diffs cleaner by leaving a comment here without comma at the end"] ] diff --git a/txscript/engine.go b/txscript/engine.go index 30206152b8..710553f090 100644 --- a/txscript/engine.go +++ b/txscript/engine.go @@ -114,6 +114,10 @@ const ( // ScriptVerifyDiscourageUpgradeablePubkeyType defines if unknown // public key versions (during tapscript execution) is non-standard. ScriptVerifyDiscourageUpgradeablePubkeyType + + // ScriptVerifyConstScriptCode fails non-segwit scripts if a signature + // match is found in the script code or if OP_CODESEPARATOR is used. + ScriptVerifyConstScriptCode ) const ( diff --git a/txscript/error.go b/txscript/error.go index 68bea7e879..29649cfcc7 100644 --- a/txscript/error.go +++ b/txscript/error.go @@ -408,6 +408,14 @@ const ( // is exceeded during taproot execution. ErrTaprootMaxSigOps + // ErrNonConstScriptCode is returned when a signature match is found when + // calling removeOpcodeByData in a non-segwit script. + ErrNonConstScriptCode + + // ErrCodeSeparator is returned when OP_CODESEPARATOR is used in a + // non-segwit script. + ErrCodeSeparator + // numErrorCodes is the maximum error code number used in tests. This // entry MUST be the last entry in the enum. numErrorCodes @@ -494,6 +502,8 @@ var errorCodeStrings = map[ErrorCode]string{ ErrInvalidTaprootSigLen: "ErrInvalidTaprootSigLen", ErrTaprootPubkeyIsEmpty: "ErrTaprootPubkeyIsEmpty", ErrTaprootMaxSigOps: "ErrTaprootMaxSigOps", + ErrNonConstScriptCode: "ErrNonConstScriptCode", + ErrCodeSeparator: "ErrCodeSeparator", } // String returns the ErrorCode as a human-readable name. diff --git a/txscript/error_test.go b/txscript/error_test.go index accdf11a8c..bb1f73e92e 100644 --- a/txscript/error_test.go +++ b/txscript/error_test.go @@ -96,6 +96,8 @@ func TestErrorCodeStringer(t *testing.T) { {ErrInvalidTaprootSigLen, "ErrInvalidTaprootSigLen"}, {ErrTaprootPubkeyIsEmpty, "ErrTaprootPubkeyIsEmpty"}, {ErrTaprootMaxSigOps, "ErrTaprootMaxSigOps"}, + {ErrNonConstScriptCode, "ErrNonConstScriptCode"}, + {ErrCodeSeparator, "ErrCodeSeparator"}, {0xffff, "Unknown ErrorCode (65535)"}, } diff --git a/txscript/opcode.go b/txscript/opcode.go index 4918b991c5..1cd3ba24fb 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1953,6 +1953,12 @@ func opcodeCodeSeparator(op *opcode, data []byte, vm *Engine) error { if vm.taprootCtx != nil { vm.taprootCtx.codeSepPos = uint32(vm.tokenizer.OpcodePosition()) + } else if vm.witnessProgram == nil && + vm.hasFlag(ScriptVerifyConstScriptCode) { + + // Disable OP_CODESEPARATOR for non-segwit scripts. + str := "OP_CODESEPARATOR used in non-segwit script" + return scriptError(ErrCodeSeparator, str) } return nil @@ -2073,7 +2079,13 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { // TODO(roasbeef): return an error? } - valid := sigVerifier.Verify() + result := sigVerifier.Verify() + valid := result.sigValid + + if vm.hasFlag(ScriptVerifyConstScriptCode) && result.sigMatch { + str := "non-const script code" + return scriptError(ErrNonConstScriptCode, str) + } switch { // For tapscript, and prior execution with null fail active, if the @@ -2166,11 +2178,11 @@ func opcodeCheckSigAdd(op *opcode, data []byte, vm *Engine) error { return err } - valid := sigVerifier.Verify() + result := sigVerifier.Verify() // If the signature is invalid, this we fail execution, as it should // have been an empty signature. - if !valid { + if !result.sigValid { str := "signature not empty on failed checksig" return scriptError(ErrNullFail, str) } @@ -2303,7 +2315,13 @@ func opcodeCheckMultiSig(op *opcode, data []byte, vm *Engine) error { // no way for a signature to sign itself. if !vm.isWitnessVersionActive(0) { for _, sigInfo := range signatures { - script = removeOpcodeByData(script, sigInfo.signature) + var match bool + script, match = removeOpcodeByData(script, sigInfo.signature) + if vm.hasFlag(ScriptVerifyConstScriptCode) && match { + str := fmt.Sprintf("got match of %v in %v", sigInfo.signature, + script) + return scriptError(ErrNonConstScriptCode, str) + } } } diff --git a/txscript/reference_test.go b/txscript/reference_test.go index 16f06c4f70..b3f90cd5ba 100644 --- a/txscript/reference_test.go +++ b/txscript/reference_test.go @@ -196,6 +196,8 @@ func parseScriptFlags(flagStr string) (ScriptFlags, error) { flags |= ScriptVerifyWitnessPubKeyType case "TAPROOT": flags |= ScriptVerifyTaproot + case "CONST_SCRIPTCODE": + flags |= ScriptVerifyConstScriptCode default: return flags, fmt.Errorf("invalid flag: %s", flag) } diff --git a/txscript/script.go b/txscript/script.go index 18723067ee..3e8ca0ea1c 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -255,10 +255,10 @@ func isCanonicalPush(opcode byte, data []byte) bool { // NOTE: This function is only valid for version 0 scripts. Since the function // does not accept a script version, the results are undefined for other script // versions. -func removeOpcodeByData(script []byte, dataToRemove []byte) []byte { +func removeOpcodeByData(script []byte, dataToRemove []byte) ([]byte, bool) { // Avoid work when possible. if len(script) == 0 || len(dataToRemove) == 0 { - return script + return script, false } // Parse through the script looking for a canonical data push that contains @@ -266,32 +266,48 @@ func removeOpcodeByData(script []byte, dataToRemove []byte) []byte { const scriptVersion = 0 var result []byte var prevOffset int32 + var match bool tokenizer := MakeScriptTokenizer(scriptVersion, script) for tokenizer.Next() { - // In practice, the script will basically never actually contain the - // data since this function is only used during signature verification - // to remove the signature itself which would require some incredibly - // non-standard code to create. - // - // Thus, as an optimization, avoid allocating a new script unless there - // is actually a match that needs to be removed. - op, data := tokenizer.Opcode(), tokenizer.Data() - if isCanonicalPush(op, data) && bytes.Contains(data, dataToRemove) { - if result == nil { - fullPushLen := tokenizer.ByteIndex() - prevOffset - result = make([]byte, 0, int32(len(script))-fullPushLen) - result = append(result, script[0:prevOffset]...) - } - } else if result != nil { - result = append(result, script[prevOffset:tokenizer.ByteIndex()]...) + var found bool + result, prevOffset, found = removeOpcodeCanonical( + &tokenizer, script, dataToRemove, prevOffset, result, + ) + if found { + match = true } - - prevOffset = tokenizer.ByteIndex() } if result == nil { result = script } - return result + return result, match +} + +func removeOpcodeCanonical(t *ScriptTokenizer, script, dataToRemove []byte, + prevOffset int32, result []byte) ([]byte, int32, bool) { + + var found bool + + // In practice, the script will basically never actually contain the + // data since this function is only used during signature verification + // to remove the signature itself which would require some incredibly + // non-standard code to create. + // + // Thus, as an optimization, avoid allocating a new script unless there + // is actually a match that needs to be removed. + op, data := t.Opcode(), t.Data() + if isCanonicalPush(op, data) && bytes.Equal(data, dataToRemove) { + if result == nil { + fullPushLen := t.ByteIndex() - prevOffset + result = make([]byte, 0, int32(len(script))-fullPushLen) + result = append(result, script[0:prevOffset]...) + } + found = true + } else if result != nil { + result = append(result, script[prevOffset:t.ByteIndex()]...) + } + + return result, t.ByteIndex(), found } // AsSmallInt returns the passed opcode, which must be true according to diff --git a/txscript/script_test.go b/txscript/script_test.go index a90e1940e5..7842565c6c 100644 --- a/txscript/script_test.go +++ b/txscript/script_test.go @@ -357,6 +357,12 @@ func TestRemoveOpcodeByData(t *testing.T) { remove: []byte{1, 2, 3, 4}, after: []byte{OP_NOP}, }, + { + name: "", + before: []byte{OP_NOP, OP_DATA_8, 1, 2, 3, 4, 5, 6, 7, 8, OP_DATA_4, 1, 2, 3, 4}, + remove: []byte{1, 2, 3, 4}, + after: []byte{OP_NOP, OP_DATA_8, 1, 2, 3, 4, 5, 6, 7, 8}, + }, { name: "simple case", before: []byte{OP_DATA_4, 1, 2, 3, 4}, @@ -376,7 +382,9 @@ func TestRemoveOpcodeByData(t *testing.T) { bytes.Repeat([]byte{0}, 72)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, - after: nil, + after: append(append([]byte{OP_PUSHDATA1, 76}, + bytes.Repeat([]byte{0}, 72)...), + []byte{1, 2, 3, 4}...), }, { name: "simple case (pushdata1 miss)", @@ -400,7 +408,9 @@ func TestRemoveOpcodeByData(t *testing.T) { bytes.Repeat([]byte{0}, 252)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, - after: nil, + after: append(append([]byte{OP_PUSHDATA2, 0, 1}, + bytes.Repeat([]byte{0}, 252)...), + []byte{1, 2, 3, 4}...), }, { name: "simple case (pushdata2 miss)", @@ -425,7 +435,9 @@ func TestRemoveOpcodeByData(t *testing.T) { bytes.Repeat([]byte{0}, 65532)...), []byte{1, 2, 3, 4}...), remove: []byte{1, 2, 3, 4}, - after: nil, + after: append(append([]byte{OP_PUSHDATA4, 0, 0, 1, 0}, + bytes.Repeat([]byte{0}, 65532)...), + []byte{1, 2, 3, 4}...), }, { name: "simple case (pushdata4 miss noncanonical)", @@ -465,16 +477,17 @@ func TestRemoveOpcodeByData(t *testing.T) { // tstRemoveOpcodeByData is a convenience function to ensure the provided // script parses before attempting to remove the passed data. const scriptVersion = 0 - tstRemoveOpcodeByData := func(script []byte, data []byte) ([]byte, error) { + tstRemoveOpcodeByData := func(script []byte, data []byte) ([]byte, bool, error) { if err := checkScriptParses(scriptVersion, script); err != nil { - return nil, err + return nil, false, err } - return removeOpcodeByData(script, data), nil + result, match := removeOpcodeByData(script, data) + return result, match, nil } for _, test := range tests { - result, err := tstRemoveOpcodeByData(test.before, test.remove) + result, _, err := tstRemoveOpcodeByData(test.before, test.remove) if e := tstCheckScriptError(err, test.err); e != nil { t.Errorf("%s: %v", test.name, e) continue diff --git a/txscript/sigvalidate.go b/txscript/sigvalidate.go index 0bd00c326d..ee1a5388a3 100644 --- a/txscript/sigvalidate.go +++ b/txscript/sigvalidate.go @@ -20,9 +20,14 @@ import ( // pre-segwit, segwit v0, segwit v1 (taproot key spend validation), and the // base tapscript verification. type signatureVerifier interface { - // Verify returns true if the signature verifier context deems the + // Verify returns whether or not the signature verifier context deems the // signature to be valid for the given context. - Verify() bool + Verify() verifyResult +} + +type verifyResult struct { + sigValid bool + sigMatch bool } // baseSigVerifier is used to verify signatures for the _base_ system, meaning @@ -147,20 +152,23 @@ func (b *baseSigVerifier) verifySig(sigHash []byte) bool { return valid } -// Verify returns true if the signature verifier context deems the signature to -// be valid for the given context. +// Verify returns whether or not the signature verifier context deems the +// signature to be valid for the given context. // // NOTE: This is part of the baseSigVerifier interface. -func (b *baseSigVerifier) Verify() bool { +func (b *baseSigVerifier) Verify() verifyResult { // Remove the signature since there is no way for a signature // to sign itself. - subScript := removeOpcodeByData(b.subScript, b.fullSigBytes) + subScript, match := removeOpcodeByData(b.subScript, b.fullSigBytes) sigHash := calcSignatureHash( subScript, b.hashType, &b.vm.tx, b.vm.txIdx, ) - return b.verifySig(sigHash) + return verifyResult{ + sigValid: b.verifySig(sigHash), + sigMatch: match, + } } // A compile-time assertion to ensure baseSigVerifier implements the @@ -192,7 +200,7 @@ func newBaseSegwitSigVerifier(pkBytes, fullSigBytes []byte, // be valid for the given context. // // NOTE: This is part of the baseSigVerifier interface. -func (s *baseSegwitSigVerifier) Verify() bool { +func (s *baseSegwitSigVerifier) Verify() verifyResult { var sigHashes *TxSigHashes if s.vm.hashCache != nil { sigHashes = s.vm.hashCache @@ -208,10 +216,12 @@ func (s *baseSegwitSigVerifier) Verify() bool { // TODO(roasbeef): this doesn't need to return an error, should // instead be further up the stack? this only returns an error // if the input index is greater than the number of inputs - return false + return verifyResult{} } - return s.verifySig(sigHash) + return verifyResult{ + sigValid: s.verifySig(sigHash), + } } // A compile-time assertion to ensure baseSegwitSigVerifier implements the @@ -356,11 +366,11 @@ func (t *taprootSigVerifier) verifySig(sigHash []byte) bool { return false } -// Verify returns true if the signature verifier context deems the signature to -// be valid for the given context. +// Verify returns whether or not the signature verifier context deems the +// signature to be valid for the given context. // // NOTE: This is part of the baseSigVerifier interface. -func (t *taprootSigVerifier) Verify() bool { +func (t *taprootSigVerifier) Verify() verifyResult { var opts []TaprootSigHashOption if t.annex != nil { opts = append(opts, WithAnnex(t.annex)) @@ -374,10 +384,12 @@ func (t *taprootSigVerifier) Verify() bool { ) if err != nil { // TODO(roasbeef): propagate the error here? - return false + return verifyResult{} } - return t.verifySig(sigHash) + return verifyResult{ + sigValid: t.verifySig(sigHash), + } } // A compile-time assertion to ensure taprootSigVerifier implements the @@ -439,16 +451,18 @@ func newBaseTapscriptSigVerifier(pkBytes, rawSig []byte, } } -// Verify returns true if the signature verifier context deems the signature to -// be valid for the given context. +// Verify returns whether or not the signature verifier context deems the +// signature to be valid for the given context. // // NOTE: This is part of the baseSigVerifier interface. -func (b *baseTapscriptSigVerifier) Verify() bool { +func (b *baseTapscriptSigVerifier) Verify() verifyResult { // If the public key is blank, then that means it wasn't 0 or 32 bytes, // so we'll treat this as an unknown public key version and return - // true. + // that it's valid. if b.pubKey == nil { - return true + return verifyResult{ + sigValid: true, + } } var opts []TaprootSigHashOption @@ -468,10 +482,12 @@ func (b *baseTapscriptSigVerifier) Verify() bool { ) if err != nil { // TODO(roasbeef): propagate the error here? - return false + return verifyResult{} } - return b.verifySig(sigHash) + return verifyResult{ + sigValid: b.verifySig(sigHash), + } } // A compile-time assertion to ensure baseTapscriptSigVerifier implements the diff --git a/txscript/standard.go b/txscript/standard.go index 5ef2ad167f..4b04f9a63e 100644 --- a/txscript/standard.go +++ b/txscript/standard.go @@ -46,7 +46,8 @@ const ( ScriptVerifyTaproot | ScriptVerifyDiscourageUpgradeableTaprootVersion | ScriptVerifyDiscourageOpSuccess | - ScriptVerifyDiscourageUpgradeablePubkeyType + ScriptVerifyDiscourageUpgradeablePubkeyType | + ScriptVerifyConstScriptCode ) // ScriptClass is an enumeration for the list of standard types of script. diff --git a/txscript/taproot.go b/txscript/taproot.go index 003eb19ae3..0a3d8531ae 100644 --- a/txscript/taproot.go +++ b/txscript/taproot.go @@ -84,8 +84,8 @@ func VerifyTaprootKeySpend(witnessProgram []byte, rawSig []byte, tx *wire.MsgTx, return err } - valid := keySpendVerifier.Verify() - if valid { + result := keySpendVerifier.Verify() + if result.sigValid { return nil } From da2f3b1e5f25b18ddeefb5bd435e43d5c4ddb924 Mon Sep 17 00:00:00 2001 From: Keagan McClelland Date: Wed, 10 Apr 2024 14:00:14 -0400 Subject: [PATCH 1012/1056] mempool: make txn's below 65 non-witness bytes non-standard This is to mitigate CVE-2017-12842. Along the way, also error when deserializing transactions that have the witness marker flag set but have no witnesses. This matches Bitcoin Core's behaviour initially introduced here https://github.com/bitcoin/bitcoin/pull/14039. Allowing such transactions is benign, but this makes sure that our parsing code matches Core's exactly. --- mempool/mempool.go | 10 ++++++++++ wire/msgtx.go | 31 ++++++++++++++++++++++--------- wire/msgtx_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index db04f619a5..4b713a18dd 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -49,6 +49,10 @@ const ( // can be evicted from the mempool when accepting a transaction // replacement. MaxReplacementEvictions = 100 + + // Transactions smaller than 65 non-witness bytes are not relayed to + // mitigate CVE-2017-12842. + MinStandardTxNonWitnessSize = 65 ) // Tag represents an identifier to use for tagging orphan transactions. The @@ -1355,6 +1359,12 @@ func (mp *TxPool) checkMempoolAcceptance(tx *btcutil.Tx, return nil, txRuleError(wire.RejectDuplicate, str) } + // Disallow transactions under the minimum standardness size. + if tx.MsgTx().SerializeSizeStripped() < MinStandardTxNonWitnessSize { + str := fmt.Sprintf("tx %v is too small", txHash) + return nil, txRuleError(wire.RejectNonstandard, str) + } + // Perform preliminary sanity checks on the transaction. This makes use // of blockchain which contains the invariant rules for what // transactions are allowed into blocks. diff --git a/wire/msgtx.go b/wire/msgtx.go index eab265c35d..e62f8fbb4f 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -111,6 +111,14 @@ const ( maxWitnessItemSize = 4_000_000 ) +var ( + // errSuperfluousWitnessRecord is returned during tx deserialization when + // a tx has the witness marker flag set but has no witnesses. + errSuperfluousWitnessRecord = fmt.Errorf( + "witness flag set but tx has no witnesses", + ) +) + // TxFlagMarker is the first byte of the FLAG field in a bitcoin tx // message. It allows decoders to distinguish a regular serialized // transaction from one that would require a different parsing logic. @@ -579,8 +587,7 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, txin.Witness = make([][]byte, witCount) for j := uint64(0); j < witCount; j++ { txin.Witness[j], err = readScriptBuf( - r, pver, buf, sbuf, maxWitnessItemSize, - "script witness item", + r, pver, buf, sbuf, "script witness item", ) if err != nil { return err @@ -589,6 +596,12 @@ func (msg *MsgTx) btcDecode(r io.Reader, pver uint32, enc MessageEncoding, sbuf = sbuf[len(txin.Witness[j]):] } } + + // Check that if the witness flag is set that we actually have + // witnesses. This check is also done by bitcoind. + if !msg.HasWitness() { + return errSuperfluousWitnessRecord + } } if _, err := io.ReadFull(r, buf[:4]); err != nil { @@ -982,7 +995,7 @@ func writeOutPointBuf(w io.Writer, pver uint32, version int32, op *OutPoint, // // NOTE: b MUST either be nil or at least an 8-byte slice. func readScriptBuf(r io.Reader, pver uint32, buf, s []byte, - maxAllowed uint32, fieldName string) ([]byte, error) { + fieldName string) ([]byte, error) { count, err := ReadVarIntBuf(r, pver, buf) if err != nil { @@ -992,9 +1005,9 @@ func readScriptBuf(r io.Reader, pver uint32, buf, s []byte, // Prevent byte array larger than the max message size. It would // be possible to cause memory exhaustion and panics without a sane // upper bound on this count. - if count > uint64(maxAllowed) { + if count > maxWitnessItemSize { str := fmt.Sprintf("%s is larger than the max allowed size "+ - "[count %d, max %d]", fieldName, count, maxAllowed) + "[count %d, max %d]", fieldName, count, maxWitnessItemSize) return nil, messageError("readScript", str) } @@ -1021,8 +1034,9 @@ func readTxInBuf(r io.Reader, pver uint32, version int32, ti *TxIn, return err } - ti.SignatureScript, err = readScriptBuf(r, pver, buf, s, MaxMessagePayload, - "transaction input signature script") + ti.SignatureScript, err = readScriptBuf( + r, pver, buf, s, "transaction input signature script", + ) if err != nil { return err } @@ -1085,8 +1099,7 @@ func readTxOutBuf(r io.Reader, pver uint32, version int32, to *TxOut, to.Value = int64(littleEndian.Uint64(buf)) to.PkScript, err = readScriptBuf( - r, pver, buf, s, MaxMessagePayload, - "transaction output public key script", + r, pver, buf, s, "transaction output public key script", ) return err } diff --git a/wire/msgtx_test.go b/wire/msgtx_test.go index 5ec753b62d..4eb28943f9 100644 --- a/wire/msgtx_test.go +++ b/wire/msgtx_test.go @@ -6,6 +6,7 @@ package wire import ( "bytes" + "errors" "fmt" "io" "reflect" @@ -849,6 +850,17 @@ func TestTxOutPointFromString(t *testing.T) { } } +// TestTxSuperfluousWitnessRecord ensures that btcd fails to parse a tx with +// the witness marker flag set but without any actual witnesses. +func TestTxSuperfluousWitnessRecord(t *testing.T) { + m := &MsgTx{} + rbuf := bytes.NewReader(multiWitnessFlagNoWitness) + err := m.BtcDecode(rbuf, ProtocolVersion, WitnessEncoding) + if !errors.Is(err, errSuperfluousWitnessRecord) { + t.Fatalf("should have failed with %v", errSuperfluousWitnessRecord) + } +} + // multiTx is a MsgTx with an input and output and used in various tests. var multiTx = &MsgTx{ Version: 1, @@ -1001,6 +1013,33 @@ var multiWitnessTx = &MsgTx{ }, } +// multiWitnessFlagNoWitness is the wire encoded bytes for multiWitnessTx with +// the witness flag set but with witnesses omitted. +var multiWitnessFlagNoWitness = []byte{ + 0x1, 0x0, 0x0, 0x0, // Version + TxFlagMarker, // Marker byte indicating 0 inputs, or a segwit encoded tx + WitnessFlag, // Flag byte + 0x1, // Varint for number of inputs + 0xa5, 0x33, 0x52, 0xd5, 0x13, 0x57, 0x66, 0xf0, + 0x30, 0x76, 0x59, 0x74, 0x18, 0x26, 0x3d, 0xa2, + 0xd9, 0xc9, 0x58, 0x31, 0x59, 0x68, 0xfe, 0xa8, + 0x23, 0x52, 0x94, 0x67, 0x48, 0x1f, 0xf9, 0xcd, // Previous output hash + 0x13, 0x0, 0x0, 0x0, // Little endian previous output index + 0x0, // No sig script (this is a witness input) + 0xff, 0xff, 0xff, 0xff, // Sequence + 0x1, // Varint for number of outputs + 0xb, 0x7, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, // Output amount + 0x16, // Varint for length of pk script + 0x0, // Version 0 witness program + 0x14, // OP_DATA_20 + 0x9d, 0xda, 0xc6, 0xf3, 0x9d, 0x51, 0xe0, 0x39, + 0x8e, 0x53, 0x2a, 0x22, 0xc4, 0x1b, 0xa1, 0x89, + 0x40, 0x6a, 0x85, 0x23, // 20-byte pub key hash + 0x00, // No item on the witness stack for the first input + 0x00, // No item on the witness stack for the second input + 0x0, 0x0, 0x0, 0x0, // Lock time +} + // multiWitnessTxEncoded is the wire encoded bytes for multiWitnessTx including inputs // with witness data using protocol version 70012 and is used in the various // tests. From cccaa5f9b06761c23797974fbd4cd25218f89ace Mon Sep 17 00:00:00 2001 From: lilasxie Date: Mon, 3 Jun 2024 18:28:21 +0800 Subject: [PATCH 1013/1056] refactor: specify strconv.ParseFloat bitsize to 64 --- btcjson/cmdparse.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcjson/cmdparse.go b/btcjson/cmdparse.go index 3b0473b865..c9b248e389 100644 --- a/btcjson/cmdparse.go +++ b/btcjson/cmdparse.go @@ -451,7 +451,7 @@ func assignField(paramNum int, fieldName string, dest reflect.Value, src reflect // String -> float of varying size. case reflect.Float32, reflect.Float64: - srcFloat, err := strconv.ParseFloat(src.String(), 0) + srcFloat, err := strconv.ParseFloat(src.String(), 64) if err != nil { str := fmt.Sprintf("parameter #%d '%s' must "+ "parse to a %v", paramNum, fieldName, From eabc9bf50c93d155e67dc10bebab8789e06b6bf8 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 30 Apr 2024 18:46:48 +0900 Subject: [PATCH 1014/1056] blockchain: Refactor reorganizeChain to exclude verification reorganizeChain() used to handle the following: 1: That the blocknodes being disconnected/connected indeed to connect properly without errors. 2: Perform the actual disconnect/connect of the blocknodes. The functionality of 1, the validation that the disconnects/connects can happen without errors are now refactored out into verifyReorganizationValidity. This is an effort made so that ReconsiderBlock() can call verifyReorganizationValidity and set the block status of the reconsidered chain and return nil even when an error returns as it's ok to get an error when reconsidering an invalid branch. --- blockchain/chain.go | 252 +++++++++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 119 deletions(-) diff --git a/blockchain/chain.go b/blockchain/chain.go index 8e75b447e9..7242e3571a 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -870,9 +870,118 @@ func countSpentOutputs(block *btcutil.Block) int { // // This function MUST be called with the chain state lock held (for writes). func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error { + // Check first that the detach and the attach nodes are valid and they + // pass verification. + detachBlocks, attachBlocks, detachSpentTxOuts, + err := b.verifyReorganizationValidity(detachNodes, attachNodes) + if err != nil { + return err + } + + // Track the old and new best chains heads. + tip := b.bestChain.Tip() + oldBest := tip + newBest := tip + + // Reset the view for the actual connection code below. This is + // required because the view was previously modified when checking if + // the reorg would be successful and the connection code requires the + // view to be valid from the viewpoint of each block being disconnected. + view := NewUtxoViewpoint() + view.SetBestHash(&b.bestChain.Tip().hash) + + // Disconnect blocks from the main chain. + for i, e := 0, detachNodes.Front(); e != nil; i, e = i+1, e.Next() { + n := e.Value.(*blockNode) + block := detachBlocks[i] + + // Load all of the utxos referenced by the block that aren't + // already in the view. + err := view.fetchInputUtxos(b.utxoCache, block) + if err != nil { + return err + } + + // Update the view to unspend all of the spent txos and remove + // the utxos created by the block. + err = view.disconnectTransactions( + b.db, block, detachSpentTxOuts[i], + ) + if err != nil { + return err + } + + // Update the database and chain state. The cache will be flushed + // here before the utxoview modifications happen to the database. + err = b.disconnectBlock(n, block, view) + if err != nil { + return err + } + + newBest = n.parent + } + + // Set the fork point only if there are nodes to attach since otherwise + // blocks are only being disconnected and thus there is no fork point. + var forkNode *blockNode + if attachNodes.Len() > 0 { + forkNode = newBest + } + + // Connect the new best chain blocks using the utxocache directly. It's more + // efficient and since we already checked that the blocks are correct and that + // the transactions connect properly, it's ok to access the cache. If we suddenly + // crash here, we are able to recover as well. + for i, e := 0, attachNodes.Front(); e != nil; i, e = i+1, e.Next() { + n := e.Value.(*blockNode) + block := attachBlocks[i] + + // Update the cache to mark all utxos referenced by the block + // as spent and add all transactions being created by this block + // to it. Also, provide an stxo slice so the spent txout + // details are generated. + stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) + err = b.utxoCache.connectTransactions(block, &stxos) + if err != nil { + return err + } + + // Update the database and chain state. + err = b.connectBlock(n, block, stxos) + if err != nil { + return err + } + + newBest = n + } + + // Log the point where the chain forked and old and new best chain + // heads. + if forkNode != nil { + log.Infof("REORGANIZE: Chain forks at %v (height %v)", forkNode.hash, + forkNode.height) + } + log.Infof("REORGANIZE: Old best chain head was %v (height %v)", + &oldBest.hash, oldBest.height) + log.Infof("REORGANIZE: New best chain head is %v (height %v)", + newBest.hash, newBest.height) + + return nil +} + +// verifyReorganizationValidity will verify that the disconnects and the connects +// that are in the list are able to be processed without mutating the chain. +// +// For the attach nodes, it'll check that each of the blocks are valid and will +// change the status of the block node in the list to invalid if the block fails +// to pass verification. For the detach nodes, it'll check that the blocks being +// detached and their spend journals are present on the database. +func (b *BlockChain) verifyReorganizationValidity(detachNodes, attachNodes *list.List) ( + []*btcutil.Block, []*btcutil.Block, [][]SpentTxOut, error) { + // Nothing to do if no reorganize nodes were provided. if detachNodes.Len() == 0 && attachNodes.Len() == 0 { - return nil + return nil, nil, nil, nil } // Ensure the provided nodes match the current best chain. @@ -880,9 +989,10 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error if detachNodes.Len() != 0 { firstDetachNode := detachNodes.Front().Value.(*blockNode) if firstDetachNode.hash != tip.hash { - return AssertError(fmt.Sprintf("reorganize nodes to detach are "+ - "not for the current best chain -- first detach node %v, "+ - "current chain %v", &firstDetachNode.hash, &tip.hash)) + return nil, nil, nil, + AssertError(fmt.Sprintf("reorganize nodes to detach are "+ + "not for the current best chain -- first detach node %v, "+ + "current chain %v", &firstDetachNode.hash, &tip.hash)) } } @@ -891,17 +1001,14 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error firstAttachNode := attachNodes.Front().Value.(*blockNode) lastDetachNode := detachNodes.Back().Value.(*blockNode) if firstAttachNode.parent.hash != lastDetachNode.parent.hash { - return AssertError(fmt.Sprintf("reorganize nodes do not have the "+ - "same fork point -- first attach parent %v, last detach "+ - "parent %v", &firstAttachNode.parent.hash, - &lastDetachNode.parent.hash)) + return nil, nil, nil, + AssertError(fmt.Sprintf("reorganize nodes do not have the "+ + "same fork point -- first attach parent %v, last detach "+ + "parent %v", &firstAttachNode.parent.hash, + &lastDetachNode.parent.hash)) } } - // Track the old and new best chains heads. - oldBest := tip - newBest := tip - // All of the blocks to detach and related spend journal entries needed // to unspend transaction outputs in the blocks being disconnected must // be loaded from the database during the reorg check phase below and @@ -916,7 +1023,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error // database and using that information to unspend all of the spent txos // and remove the utxos created by the blocks. view := NewUtxoViewpoint() - view.SetBestHash(&oldBest.hash) + view.SetBestHash(&tip.hash) for e := detachNodes.Front(); e != nil; e = e.Next() { n := e.Value.(*blockNode) var block *btcutil.Block @@ -926,19 +1033,20 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error return err }) if err != nil { - return err + return nil, nil, nil, err } if n.hash != *block.Hash() { - return AssertError(fmt.Sprintf("detach block node hash %v (height "+ - "%v) does not match previous parent block hash %v", &n.hash, - n.height, block.Hash())) + return nil, nil, nil, AssertError( + fmt.Sprintf("detach block node hash %v (height "+ + "%v) does not match previous parent block hash %v", + &n.hash, n.height, block.Hash())) } // Load all of the utxos referenced by the block that aren't // already in the view. err = view.fetchInputUtxos(b.utxoCache, block) if err != nil { - return err + return nil, nil, nil, err } // Load all of the spent txos for the block from the spend @@ -949,7 +1057,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error return err }) if err != nil { - return err + return nil, nil, nil, err } // Store the loaded block and spend journal entry for later. @@ -958,17 +1066,8 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error err = view.disconnectTransactions(b.db, block, stxos) if err != nil { - return err + return nil, nil, nil, err } - - newBest = n.parent - } - - // Set the fork point only if there are nodes to attach since otherwise - // blocks are only being disconnected and thus there is no fork point. - var forkNode *blockNode - if attachNodes.Len() > 0 { - forkNode = newBest } // Perform several checks to verify each block that needs to be attached @@ -993,7 +1092,7 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error return err }) if err != nil { - return err + return nil, nil, nil, err } // Store the loaded block for later. @@ -1005,14 +1104,13 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error if b.index.NodeStatus(n).KnownValid() { err = view.fetchInputUtxos(b.utxoCache, block) if err != nil { - return err + return nil, nil, nil, err } err = view.connectTransactions(block, nil) if err != nil { - return err + return nil, nil, nil, err } - newBest = n continue } @@ -1033,96 +1131,12 @@ func (b *BlockChain) reorganizeChain(detachNodes, attachNodes *list.List) error b.index.SetStatusFlags(dn, statusInvalidAncestor) } } - return err + return nil, nil, nil, err } b.index.SetStatusFlags(n, statusValid) - - newBest = n - } - - // Flush the utxo cache for the block disconnect below. The disconnect - // code assumes that it's directly modifying the database so the cache - // will be left in an inconsistent state. It needs to be flushed beforehand - // in order for that to not happen. - err := b.db.Update(func(dbTx database.Tx) error { - return b.utxoCache.flush(dbTx, FlushRequired, b.BestSnapshot()) - }) - if err != nil { - return err - } - - // Reset the view for the actual connection code below. This is - // required because the view was previously modified when checking if - // the reorg would be successful and the connection code requires the - // view to be valid from the viewpoint of each block being disconnected. - view = NewUtxoViewpoint() - view.SetBestHash(&b.bestChain.Tip().hash) - - // Disconnect blocks from the main chain. - for i, e := 0, detachNodes.Front(); e != nil; i, e = i+1, e.Next() { - n := e.Value.(*blockNode) - block := detachBlocks[i] - - // Load all of the utxos referenced by the block that aren't - // already in the view. - err := view.fetchInputUtxos(b.utxoCache, block) - if err != nil { - return err - } - - // Update the view to unspend all of the spent txos and remove - // the utxos created by the block. - err = view.disconnectTransactions(b.db, block, - detachSpentTxOuts[i]) - if err != nil { - return err - } - - // Update the database and chain state. The cache will be flushed - // here before the utxoview modifications happen to the database. - err = b.disconnectBlock(n, block, view) - if err != nil { - return err - } - } - - // Connect the new best chain blocks using the utxocache directly. It's more - // efficient and since we already checked that the blocks are correct and that - // the transactions connect properly, it's ok to access the cache. If we suddenly - // crash here, we are able to recover as well. - for i, e := 0, attachNodes.Front(); e != nil; i, e = i+1, e.Next() { - n := e.Value.(*blockNode) - block := attachBlocks[i] - - // Update the cache to mark all utxos referenced by the block - // as spent and add all transactions being created by this block - // to it. Also, provide an stxo slice so the spent txout - // details are generated. - stxos := make([]SpentTxOut, 0, countSpentOutputs(block)) - err = b.utxoCache.connectTransactions(block, &stxos) - if err != nil { - return err - } - - // Update the database and chain state. - err = b.connectBlock(n, block, stxos) - if err != nil { - return err - } } - // Log the point where the chain forked and old and new best chain - // heads. - if forkNode != nil { - log.Infof("REORGANIZE: Chain forks at %v (height %v)", forkNode.hash, - forkNode.height) - } - log.Infof("REORGANIZE: Old best chain head was %v (height %v)", - &oldBest.hash, oldBest.height) - log.Infof("REORGANIZE: New best chain head is %v (height %v)", - newBest.hash, newBest.height) - - return nil + return detachBlocks, attachBlocks, detachSpentTxOuts, nil } // connectBestChain handles connecting the passed block to the chain while From 52a8a2a06ee263c7ce1cbaa7ed0859fd325000aa Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 30 Apr 2024 19:48:48 +0900 Subject: [PATCH 1015/1056] blockchain: Add ReconsiderBlock to BlockChain ReconsiderBlock reconsiders the validity of the block for the passed in blockhash. The behavior of the function mimics that of Bitcoin Core. The invalid status of the block nodes are reset and if the chaintip that is being reconsidered has more cumulative work, then we'll validate the blocks and reorganize to it. If the cumulative work is lesser than the current active chain tip, then nothing else will be done. --- blockchain/chain.go | 90 ++++++++++++++++ blockchain/chain_test.go | 226 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 316 insertions(+) diff --git a/blockchain/chain.go b/blockchain/chain.go index 7242e3571a..952d0bc279 100644 --- a/blockchain/chain.go +++ b/blockchain/chain.go @@ -1950,6 +1950,96 @@ func (b *BlockChain) InvalidateBlock(hash *chainhash.Hash) error { return err } +// ReconsiderBlock reconsiders the validity of the block with the given hash. +// +// This function is safe for concurrent access. +func (b *BlockChain) ReconsiderBlock(hash *chainhash.Hash) error { + b.chainLock.Lock() + defer b.chainLock.Unlock() + + log.Infof("Reconsidering block_hash=%v", hash[:]) + + reconsiderNode := b.index.LookupNode(hash) + if reconsiderNode == nil { + // Return an error if the block doesn't exist. + return fmt.Errorf("requested block hash of %s is not found "+ + "and thus cannot be reconsidered", hash) + } + + // Nothing to do if the given block is already valid. + if reconsiderNode.status.KnownValid() { + log.Infof("block_hash=%x is valid, nothing to reconsider", hash[:]) + return nil + } + + // Clear the status of the block being reconsidered. + b.index.UnsetStatusFlags(reconsiderNode, statusInvalidAncestor) + b.index.UnsetStatusFlags(reconsiderNode, statusValidateFailed) + + // Grab all the tips. + tips := b.index.InactiveTips(b.bestChain) + tips = append(tips, b.bestChain.Tip()) + + log.Debugf("Examining %v inactive chain tips for reconsideration") + + // Go through all the tips and unset the status for all the descendents of the + // block being reconsidered. + var reconsiderTip *blockNode + for _, tip := range tips { + // Continue if the given inactive tip is not a descendant of the block + // being invalidated. + if !tip.IsAncestor(reconsiderNode) { + // Set as the reconsider tip if the block node being reconsidered + // is a tip. + if tip == reconsiderNode { + reconsiderTip = reconsiderNode + } + continue + } + + // Mark the current tip as the tip being reconsidered. + reconsiderTip = tip + + // Unset the status of all the parents up until it reaches the block + // being reconsidered. + for n := tip; n != nil && n != reconsiderNode; n = n.parent { + b.index.UnsetStatusFlags(n, statusInvalidAncestor) + } + } + + // Compare the cumulative work for the branch being reconsidered. + bestTipWork := b.bestChain.Tip().workSum + if reconsiderTip.workSum.Cmp(bestTipWork) <= 0 { + log.Debugf("Tip to reconsider has less cumulative work than current "+ + "chain tip: %v vs %v", reconsiderTip.workSum, bestTipWork) + return nil + } + + // If the reconsider tip has a higher cumulative work, then reorganize + // to it after checking the validity of the nodes. + detachNodes, attachNodes := b.getReorganizeNodes(reconsiderTip) + + // We're checking if the reorganization that'll happen is actually valid. + // While this is called in reorganizeChain, we call it beforehand as the error + // returned from reorganizeChain doesn't differentiate between actual disconnect/ + // connect errors or whether the branch we're trying to fork to is invalid. + // + // The block status changes here without being flushed so we immediately flush + // the blockindex after we call this function. + _, _, _, err := b.verifyReorganizationValidity(detachNodes, attachNodes) + if writeErr := b.index.flushToDB(); writeErr != nil { + log.Warnf("Error flushing block index changes to disk: %v", writeErr) + } + if err != nil { + // If we errored out during the verification of the reorg branch, + // it's ok to return nil as we reconsidered the block and determined + // that it's invalid. + return nil + } + + return b.reorganizeChain(detachNodes, attachNodes) +} + // IndexManager provides a generic interface that the is called when blocks are // connected and disconnected to and from the tip of the main chain for the // purpose of supporting optional indexes. diff --git a/blockchain/chain_test.go b/blockchain/chain_test.go index 57bbd6246c..b3bccf56f7 100644 --- a/blockchain/chain_test.go +++ b/blockchain/chain_test.go @@ -1622,3 +1622,229 @@ func TestInvalidateBlock(t *testing.T) { }() } } + +func TestReconsiderBlock(t *testing.T) { + tests := []struct { + name string + chainGen func() (*BlockChain, []*chainhash.Hash, func()) + }{ + { + name: "one branch, invalidate once and revalidate", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain("TestInvalidateBlock-one-branch-invalidate-once") + + // Create a chain with 101 blocks. + tip := btcutil.NewBlock(params.GenesisBlock) + _, _, err := addBlocks(101, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Invalidate block 5. + block, err := chain.BlockByHeight(5) + if err != nil { + t.Fatal(err) + } + invalidateHash := block.Hash() + + return chain, []*chainhash.Hash{invalidateHash}, tearDown + }, + }, + { + name: "invalidate the active branch with a side branch present and revalidate", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain("TestReconsiderBlock-invalidate-with-side-branch") + + // Create a chain with 101 blocks. + tip := btcutil.NewBlock(params.GenesisBlock) + _, spendableOuts, err := addBlocks(101, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Invalidate block 5. + block, err := chain.BlockByHeight(5) + if err != nil { + t.Fatal(err) + } + invalidateHash := block.Hash() + + // Create a side chain with 7 blocks that builds on block 1. + b1, err := chain.BlockByHeight(1) + if err != nil { + t.Fatal(err) + } + _, _, err = addBlocks(6, chain, b1, spendableOuts[0]) + if err != nil { + t.Fatal(err) + } + + return chain, []*chainhash.Hash{invalidateHash}, tearDown + }, + }, + { + name: "invalidate a side branch and revalidate it", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain("TestReconsiderBlock-invalidate-a-side-branch") + + // Create a chain with 101 blocks. + tip := btcutil.NewBlock(params.GenesisBlock) + _, spendableOuts, err := addBlocks(101, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Create a side chain with 7 blocks that builds on block 1. + b1, err := chain.BlockByHeight(1) + if err != nil { + t.Fatal(err) + } + altBlockHashes, _, err := addBlocks(6, chain, b1, spendableOuts[0]) + if err != nil { + t.Fatal(err) + } + // Grab block at height 4: + // + // b2, b3, b4, b5 + // 0, 1, 2, 3 + invalidateHash := altBlockHashes[2] + + return chain, []*chainhash.Hash{invalidateHash}, tearDown + }, + }, + { + name: "reconsider an invalid side branch with a higher work", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain("TestReconsiderBlock-reconsider-an-invalid-side-branch-higher") + + tip := btcutil.NewBlock(params.GenesisBlock) + _, spendableOuts, err := addBlocks(6, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Select utxos to be spent from the best block and + // modify the amount so that the block will be invalid. + nextSpends, _ := randomSelect(spendableOuts[len(spendableOuts)-1]) + nextSpends[0].Amount += testhelper.LowFee + + // Make an invalid block that best on top of the current tip. + bestBlock, err := chain.BlockByHash(&chain.BestSnapshot().Hash) + if err != nil { + t.Fatal(err) + } + invalidBlock, _, _ := newBlock(chain, bestBlock, nextSpends) + invalidateHash := invalidBlock.Hash() + + // The block validation will fail here and we'll mark the + // block as invalid in the block index. + chain.ProcessBlock(invalidBlock, BFNone) + + // Modify the amount again so it's valid. + nextSpends[0].Amount -= testhelper.LowFee + + return chain, []*chainhash.Hash{invalidateHash}, tearDown + }, + }, + { + name: "reconsider an invalid side branch with a lower work", + chainGen: func() (*BlockChain, []*chainhash.Hash, func()) { + chain, params, tearDown := utxoCacheTestChain("TestReconsiderBlock-reconsider-an-invalid-side-branch-lower") + + tip := btcutil.NewBlock(params.GenesisBlock) + _, spendableOuts, err := addBlocks(6, chain, tip, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + // Select utxos to be spent from the best block and + // modify the amount so that the block will be invalid. + nextSpends, _ := randomSelect(spendableOuts[len(spendableOuts)-1]) + nextSpends[0].Amount += testhelper.LowFee + + // Make an invalid block that best on top of the current tip. + bestBlock, err := chain.BlockByHash(&chain.BestSnapshot().Hash) + if err != nil { + t.Fatal(err) + } + invalidBlock, _, _ := newBlock(chain, bestBlock, nextSpends) + invalidateHash := invalidBlock.Hash() + + // The block validation will fail here and we'll mark the + // block as invalid in the block index. + chain.ProcessBlock(invalidBlock, BFNone) + + // Modify the amount again so it's valid. + nextSpends[0].Amount -= testhelper.LowFee + + // Add more blocks to make the invalid block a + // side chain and not the most pow. + _, _, err = addBlocks(3, chain, bestBlock, []*testhelper.SpendableOut{}) + if err != nil { + t.Fatal(err) + } + + return chain, []*chainhash.Hash{invalidateHash}, tearDown + }, + }, + } + + for _, test := range tests { + chain, invalidateHashes, tearDown := test.chainGen() + func() { + defer tearDown() + for _, invalidateHash := range invalidateHashes { + // Cache the chain tips before the invalidate. Since we'll reconsider + // the invalidated block, we should come back to these tips in the end. + tips := chain.ChainTips() + expectedChainTips := make(map[chainhash.Hash]ChainTip, len(tips)) + for _, tip := range tips { + expectedChainTips[tip.BlockHash] = tip + } + + // Invalidation. + err := chain.InvalidateBlock(invalidateHash) + if err != nil { + t.Fatal(err) + } + + // Reconsideration. + err = chain.ReconsiderBlock(invalidateHash) + if err != nil { + t.Fatal(err) + } + + // Compare the tips aginst the tips we've cached. + gotChainTips := chain.ChainTips() + for _, gotChainTip := range gotChainTips { + testChainTip, found := expectedChainTips[gotChainTip.BlockHash] + if !found { + t.Errorf("TestReconsiderBlock Failed test \"%s\". Couldn't find an expected "+ + "chain tip with height %d, hash %s, branchlen %d, status \"%s\"", + test.name, testChainTip.Height, testChainTip.BlockHash.String(), + testChainTip.BranchLen, testChainTip.Status.String()) + } + + // If the invalid side branch is a lower work, we'll never + // actually process the block again until the branch becomes + // a greater work chain so it'll show up as valid-fork. + if test.name == "reconsider an invalid side branch with a lower work" && + testChainTip.BlockHash == *invalidateHash { + + testChainTip.Status = StatusValidFork + } + + if !reflect.DeepEqual(testChainTip, gotChainTip) { + t.Errorf("TestReconsiderBlock Failed test \"%s\". Expected chain tip with "+ + "height %d, hash %s, branchlen %d, status \"%s\" but got "+ + "height %d, hash %s, branchlen %d, status \"%s\"", test.name, + testChainTip.Height, testChainTip.BlockHash.String(), + testChainTip.BranchLen, testChainTip.Status.String(), + gotChainTip.Height, gotChainTip.BlockHash.String(), + gotChainTip.BranchLen, gotChainTip.Status.String()) + } + } + } + }() + } +} From 588b2e58cf4c4f8da539bfa6785989894d72716e Mon Sep 17 00:00:00 2001 From: yujinpark Date: Thu, 20 Jun 2024 00:36:16 +0900 Subject: [PATCH 1016/1056] fix: typo (#2184) --- rpcclient/zmq.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcclient/zmq.go b/rpcclient/zmq.go index 1a5405eb77..52adeed76b 100644 --- a/rpcclient/zmq.go +++ b/rpcclient/zmq.go @@ -24,7 +24,7 @@ func (r FutureGetZmqNotificationsResult) Receive() (btcjson.GetZmqNotificationRe return notifications, nil } -// GetZmqNotificationsAsync returns an instance ofa type that can be used to get +// GetZmqNotificationsAsync returns an instance of a type that can be used to get // the result of a custom RPC request at some future time by invoking the Receive // function on the returned instance. // From 976cbebd09e395bc866f2a6e4a012549a3f7f6cf Mon Sep 17 00:00:00 2001 From: veth <162897869+VitalikButerinEth@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:37:10 +0800 Subject: [PATCH 1017/1056] chore: fix some comments (#2191) --- blockchain/chainio_test.go | 2 +- blockchain/indexers/addrindex.go | 2 +- config.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blockchain/chainio_test.go b/blockchain/chainio_test.go index a9e19b6f01..e9e2c0b616 100644 --- a/blockchain/chainio_test.go +++ b/blockchain/chainio_test.go @@ -23,7 +23,7 @@ func TestErrNotInMainChain(t *testing.T) { // Ensure the stringized output for the error is as expected. if err.Error() != errStr { - t.Fatalf("errNotInMainChain retuned unexpected error string - "+ + t.Fatalf("errNotInMainChain returned unexpected error string - "+ "got %q, want %q", err.Error(), errStr) } diff --git a/blockchain/indexers/addrindex.go b/blockchain/indexers/addrindex.go index 271e1665a7..2a56574acd 100644 --- a/blockchain/indexers/addrindex.go +++ b/blockchain/indexers/addrindex.go @@ -36,7 +36,7 @@ const ( // consumes. It consists of the address key + 1 byte for the level. levelKeySize = addrKeySize + 1 - // levelOffset is the offset in the level key which identifes the level. + // levelOffset is the offset in the level key which identifies the level. levelOffset = levelKeySize - 1 // addrKeyTypePubKeyHash is the address type in an address key which diff --git a/config.go b/config.go index 486ce293a3..9bbce7f69a 100644 --- a/config.go +++ b/config.go @@ -244,7 +244,7 @@ func supportedSubsystems() []string { // the levels accordingly. An appropriate error is returned if anything is // invalid. func parseAndSetDebugLevels(debugLevel string) error { - // When the specified string doesn't have any delimters, treat it as + // When the specified string doesn't have any delimiters, treat it as // the log level for all subsystems. if !strings.Contains(debugLevel, ",") && !strings.Contains(debugLevel, "=") { // Validate debug log level. From 11bd614171406a5e88cea2955617d5762c7fd7f8 Mon Sep 17 00:00:00 2001 From: coderwander <166724773+coderwander@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:38:54 +0800 Subject: [PATCH 1018/1056] Fix struct names (#2169) Signed-off-by: coderwander <770732124@qq.com> --- btcjson/walletsvrcmds.go | 2 +- rpcclient/chain.go | 2 +- rpcclient/wallet.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 979ab0c25b..9b787f60c4 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -978,7 +978,7 @@ type ImportMultiRequest struct { KeyPool *bool `json:"keypool,omitempty"` } -// ImportMultiRequest defines the options struct, provided to the +// ImportMultiOptions defines the options struct, provided to the // ImportMultiCmd as a pointer argument. type ImportMultiOptions struct { Rescan bool `json:"rescan"` // Rescan the blockchain after all imports diff --git a/rpcclient/chain.go b/rpcclient/chain.go index e65c40b3a8..1d0a8be2a9 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -890,7 +890,7 @@ func (c *Client) EstimateFee(numBlocks int64) (float64, error) { return c.EstimateFeeAsync(numBlocks).Receive() } -// FutureEstimateFeeResult is a future promise to deliver the result of a +// FutureEstimateSmartFeeResult is a future promise to deliver the result of a // EstimateSmartFeeAsync RPC invocation (or an applicable error). type FutureEstimateSmartFeeResult chan *Response diff --git a/rpcclient/wallet.go b/rpcclient/wallet.go index b8063c136d..f43c20074a 100644 --- a/rpcclient/wallet.go +++ b/rpcclient/wallet.go @@ -2610,7 +2610,7 @@ func (c *Client) GetInfo() (*btcjson.InfoWalletResult, error) { return c.GetInfoAsync().Receive() } -// FutureImportPubKeyResult is a future promise to deliver the result of an +// FutureWalletCreateFundedPsbtResult is a future promise to deliver the result of an // WalletCreateFundedPsbt RPC invocation (or an applicable error). type FutureWalletCreateFundedPsbtResult chan *Response From 1cb4d3a5039b6043a2c53fe34575ce6a5699bde9 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 9 Jan 2023 17:47:08 +0900 Subject: [PATCH 1019/1056] rpcclient, integration: Add invalidateblock and reconsiderblock invalidateblock and reconsiderblock are added to the rpcclient package and an integration test is added to test the added functions. --- .../invalidate_reconsider_block_test.go | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 integration/invalidate_reconsider_block_test.go diff --git a/integration/invalidate_reconsider_block_test.go b/integration/invalidate_reconsider_block_test.go new file mode 100644 index 0000000000..4fe6ff0012 --- /dev/null +++ b/integration/invalidate_reconsider_block_test.go @@ -0,0 +1,244 @@ +package integration + +import ( + "testing" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/integration/rpctest" +) + +func TestInvalidateAndReconsiderBlock(t *testing.T) { + // Set up regtest chain. + r, err := rpctest.New(&chaincfg.RegressionNetParams, nil, nil, "") + if err != nil { + t.Fatalf("TestInvalidateAndReconsiderBlock fail."+ + "Unable to create primary harness: %v", err) + } + if err := r.SetUp(true, 0); err != nil { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Unable to setup test chain: %v", err) + } + defer r.TearDown() + + // Generate 4 blocks. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2 -> 3 -> 4 + _, err = r.Client.Generate(4) + if err != nil { + t.Fatal(err) + } + + // Cache the active tip hash. + block4ActiveTipHash, err := r.Client.GetBestBlockHash() + if err != nil { + t.Fatal(err) + } + + // Cache block 1 hash as this will be our chaintip after we invalidate block 2. + block1Hash, err := r.Client.GetBlockHash(1) + if err != nil { + t.Fatal(err) + } + + // Invalidate block 2. + // + // Our chain view looks like so: + // (genesis block) -> 1 (active) + // \ -> 2 -> 3 -> 4 (invalid) + block2Hash, err := r.Client.GetBlockHash(2) + if err != nil { + t.Fatal(err) + } + err = r.Client.InvalidateBlock(block2Hash) + if err != nil { + t.Fatal(err) + } + + // Assert that block 1 is the active chaintip. + bestHash, err := r.Client.GetBestBlockHash() + if *bestHash != *block1Hash { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected the "+ + "best block hash to be block 1 with hash %s but got %s", + block1Hash.String(), bestHash.String()) + } + + // Generate 2 blocks. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2a -> 3a (active) + // \ -> 2 -> 3 -> 4 (invalid) + _, err = r.Client.Generate(2) + if err != nil { + t.Fatal(err) + } + + // Cache the active tip hash for the current active tip. + block3aActiveTipHash, err := r.Client.GetBestBlockHash() + if err != nil { + t.Fatal(err) + } + + tips, err := r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + + // Assert that there are two branches. + if len(tips) != 2 { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Expected 2 chaintips but got %d", len(tips)) + } + + for _, tip := range tips { + if tip.Hash == block4ActiveTipHash.String() && + tip.Status != "invalid" { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ + "invalidated branch tip of %s to be invalid but got %s", + tip.Hash, tip.Status) + } + } + + // Reconsider the invalidated block 2. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2a -> 3a (valid-fork) + // \ -> 2 -> 3 -> 4 (active) + err = r.Client.ReconsiderBlock(block2Hash) + if err != nil { + t.Fatal(err) + } + + tips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + // Assert that there are two branches. + if len(tips) != 2 { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Expected 2 chaintips but got %d", len(tips)) + } + + var checkedTips int + for _, tip := range tips { + if tip.Hash == block4ActiveTipHash.String() { + if tip.Status != "active" { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ + "the reconsidered branch tip of %s to be active but got %s", + tip.Hash, tip.Status) + } + + checkedTips++ + } + + if tip.Hash == block3aActiveTipHash.String() { + if tip.Status != "valid-fork" { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ + "invalidated branch tip of %s to be valid-fork but got %s", + tip.Hash, tip.Status) + } + checkedTips++ + } + } + + if checkedTips != 2 { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Expected to check %d chaintips, checked %d", 2, checkedTips) + } + + // Invalidate block 3a. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2a -> 3a (invalid) + // \ -> 2 -> 3 -> 4 (active) + err = r.Client.InvalidateBlock(block3aActiveTipHash) + if err != nil { + t.Fatal(err) + } + + tips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + + // Assert that there are two branches. + if len(tips) != 2 { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Expected 2 chaintips but got %d", len(tips)) + } + + checkedTips = 0 + for _, tip := range tips { + if tip.Hash == block4ActiveTipHash.String() { + if tip.Status != "active" { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ + "an active branch tip of %s but got %s", + tip.Hash, tip.Status) + } + + checkedTips++ + } + + if tip.Hash == block3aActiveTipHash.String() { + if tip.Status != "invalid" { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ + "the invalidated tip of %s to be invalid but got %s", + tip.Hash, tip.Status) + } + checkedTips++ + } + } + + if checkedTips != 2 { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Expected to check %d chaintips, checked %d", 2, checkedTips) + } + + // Reconsider block 3a. + // + // Our chain view looks like so: + // (genesis block) -> 1 -> 2a -> 3a (valid-fork) + // \ -> 2 -> 3 -> 4 (active) + err = r.Client.ReconsiderBlock(block3aActiveTipHash) + if err != nil { + t.Fatal(err) + } + + tips, err = r.Client.GetChainTips() + if err != nil { + t.Fatal(err) + } + + // Assert that there are two branches. + if len(tips) != 2 { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Expected 2 chaintips but got %d", len(tips)) + } + + checkedTips = 0 + for _, tip := range tips { + if tip.Hash == block4ActiveTipHash.String() { + if tip.Status != "active" { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ + "an active branch tip of %s but got %s", + tip.Hash, tip.Status) + } + + checkedTips++ + } + + if tip.Hash == block3aActiveTipHash.String() { + if tip.Status != "valid-fork" { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. Expected "+ + "the reconsidered tip of %s to be a valid-fork but got %s", + tip.Hash, tip.Status) + } + checkedTips++ + } + } + + if checkedTips != 2 { + t.Fatalf("TestInvalidateAndReconsiderBlock fail. "+ + "Expected to check %d chaintips, checked %d", 2, checkedTips) + } +} From 0aa80ea8f7f4abbc4358a9b71479bb9fc59c88e4 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 3 Jan 2023 18:52:25 +0900 Subject: [PATCH 1020/1056] main: Add invalidateblock and reconsiderblock rpc commands The rpc calls and the rpchelp is added for the invalidateblock and reconsiderblock methods on BlockChain. --- rpcclient/chain.go | 35 +++++++++++++++++++++++++++++++++++ rpcserver.go | 40 ++++++++++++++++++++++++++++++++++++++-- rpcserverhelp.go | 10 ++++++++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/rpcclient/chain.go b/rpcclient/chain.go index 1d0a8be2a9..c8562b8e65 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -1419,3 +1419,38 @@ func (c *Client) GetDescriptorInfoAsync(descriptor string) FutureGetDescriptorIn func (c *Client) GetDescriptorInfo(descriptor string) (*btcjson.GetDescriptorInfoResult, error) { return c.GetDescriptorInfoAsync(descriptor).Receive() } + +// FutureReconsiderBlockResult is a future promise to deliver the result of a +// ReconsiderBlockAsync RPC invocation (or an applicable error). +type FutureReconsiderBlockResult chan *Response + +// Receive waits for the Response promised by the future and returns the raw +// block requested from the server given its hash. +func (r FutureReconsiderBlockResult) Receive() error { + _, err := ReceiveFuture(r) + return err +} + +// ReconsiderBlockAsync returns an instance of a type that can be used to get the +// result of the RPC at some future time by invoking the Receive function on the +// returned instance. +// +// See ReconsiderBlock for the blocking version and more details. +func (c *Client) ReconsiderBlockAsync( + blockHash *chainhash.Hash) FutureReconsiderBlockResult { + + hash := "" + if blockHash != nil { + hash = blockHash.String() + } + + cmd := btcjson.NewReconsiderBlockCmd(hash) + return c.SendCmd(cmd) +} + +// ReconsiderBlock reconsiders an verifies a specific block and the branch that +// the block is included in. If the block is valid on reconsideration, the chain +// will reorg to that block if it has more PoW than the current tip. +func (c *Client) ReconsiderBlock(blockHash *chainhash.Hash) error { + return c.ReconsiderBlockAsync(blockHash).Receive() +} diff --git a/rpcserver.go b/rpcserver.go index f82b95ca63..a3c4062bcc 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -170,8 +170,10 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "getrawtransaction": handleGetRawTransaction, "gettxout": handleGetTxOut, "help": handleHelp, + "invalidateblock": handleInvalidateBlock, "node": handleNode, "ping": handlePing, + "reconsiderblock": handleReconsiderBlock, "searchrawtransactions": handleSearchRawTransactions, "sendrawtransaction": handleSendRawTransaction, "setgenerate": handleSetGenerate, @@ -241,9 +243,7 @@ var rpcUnimplemented = map[string]struct{}{ "getmempoolentry": {}, "getnetworkinfo": {}, "getwork": {}, - "invalidateblock": {}, "preciousblock": {}, - "reconsiderblock": {}, } // Commands that are available to a limited user @@ -284,6 +284,8 @@ var rpcLimited = map[string]struct{}{ "getrawmempool": {}, "getrawtransaction": {}, "gettxout": {}, + "invalidateblock": {}, + "reconsiderblock": {}, "searchrawtransactions": {}, "sendrawtransaction": {}, "submitblock": {}, @@ -2850,6 +2852,23 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i return txOutReply, nil } +// handleInvalidateBlock implements the invalidateblock command. +func handleInvalidateBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.InvalidateBlockCmd) + + invalidateHash, err := chainhash.NewHashFromStr(c.BlockHash) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCDeserialization, + Message: fmt.Sprintf("Failed to deserialize blockhash from string of %s", + invalidateHash), + } + } + + err = s.cfg.Chain.InvalidateBlock(invalidateHash) + return nil, err +} + // handleHelp implements the help command. func handleHelp(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { c := cmd.(*btcjson.HelpCmd) @@ -3123,6 +3142,23 @@ func fetchMempoolTxnsForAddress(s *rpcServer, addr btcutil.Address, numToSkip, n return mpTxns[numToSkip:rangeEnd], numToSkip } +// handleReconsiderBlock implements the reconsiderblock command. +func handleReconsiderBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.ReconsiderBlockCmd) + + reconsiderHash, err := chainhash.NewHashFromStr(c.BlockHash) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCDeserialization, + Message: fmt.Sprintf("Failed to deserialize blockhash from string of %s", + reconsiderHash), + } + } + + err = s.cfg.Chain.ReconsiderBlock(reconsiderHash) + return nil, err +} + // handleSearchRawTransactions implements the searchrawtransactions command. func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { // Respond with an error if the address index is not enabled. diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 1f8451a530..71f96e99fd 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -544,6 +544,10 @@ var helpDescsEnUS = map[string]string{ "gettxout-vout": "The index of the output", "gettxout-includemempool": "Include the mempool when true", + // InvalidateBlockCmd help. + "invalidateblock--synopsis": "Invalidates the block of the given block hash. To re-validate the invalidated block, use the reconsiderblock rpc", + "invalidateblock-blockhash": "The block hash of the block to invalidate", + // HelpCmd help. "help--synopsis": "Returns a list of all commands or help for a specified command.", "help-command": "The command to retrieve help for", @@ -681,6 +685,10 @@ var helpDescsEnUS = map[string]string{ "loadtxfilter-addresses": "Array of addresses to add to the transaction filter", "loadtxfilter-outpoints": "Array of outpoints to add to the transaction filter", + // ReconsiderBlockCmd help. + "reconsiderblock--synopsis": "Reconsiders the block of the given block hash. Can be used to re-validate blocks invalidated with invalidateblock", + "reconsiderblock-blockhash": "The block hash of the block to reconsider", + // Rescan help. "rescan--synopsis": "Rescan block chain for transactions to addresses.\n" + "When the endblock parameter is omitted, the rescan continues through the best block in the main chain.\n" + @@ -788,7 +796,9 @@ var rpcResultTypes = map[string][]interface{}{ "gettxout": {(*btcjson.GetTxOutResult)(nil)}, "node": nil, "help": {(*string)(nil), (*string)(nil)}, + "invalidateblock": nil, "ping": nil, + "reconsiderblock": nil, "searchrawtransactions": {(*string)(nil), (*[]btcjson.SearchRawTransactionsResult)(nil)}, "sendrawtransaction": {(*string)(nil)}, "setgenerate": nil, From cc4b27cdd9e5624827668eba3254a6077000a977 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 20 Jun 2024 15:35:00 -0700 Subject: [PATCH 1021/1056] build: bump version to v0.24.2-beta --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 0fd06fde6c..e02315d434 100644 --- a/version.go +++ b/version.go @@ -22,7 +22,7 @@ const ( // appPreRelease MUST only contain characters from semanticAlphabet // per the semantic versioning spec. - appPreRelease = "beta.rc1" + appPreRelease = "beta" ) // appBuild is defined as a variable so it can be overridden during the build From 4bff77856409dafc4d8caca6f6e82b7084cdb7da Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 25 Jun 2024 13:54:58 +0200 Subject: [PATCH 1022/1056] psbt: decode keytype as compact size Fixes #2199. Previous to this fix the keytype was only interpreted as a single byte, even though BIP-0174 states it is to be parsed as a CompactSize/VarInt. --- btcutil/psbt/psbt.go | 6 ++++++ btcutil/psbt/psbt_test.go | 5 +++++ btcutil/psbt/utils.go | 25 +++++++++++++++++-------- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go index 964061bdc5..a72b7fc551 100644 --- a/btcutil/psbt/psbt.go +++ b/btcutil/psbt/psbt.go @@ -37,6 +37,12 @@ const MaxPsbtValueLength = 4000000 // deserialize from the wire. Anything more will return ErrInvalidKeyData. const MaxPsbtKeyLength = 10000 +// MaxPsbtKeyValue is the maximum value of a key type in a PSBT. This maximum +// isn't specified by the BIP but used by bitcoind in various places to limit +// the number of items processed. So we use it to validate the key type in order +// to have a consistent behavior. +const MaxPsbtKeyValue = 0x02000000 + var ( // ErrInvalidPsbtFormat is a generic error for any situation in which a diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go index 2309b07e40..a39f52923a 100644 --- a/btcutil/psbt/psbt_test.go +++ b/btcutil/psbt/psbt_test.go @@ -123,6 +123,8 @@ var invalidPsbtHex = map[int]string{ 18: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a01220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", // Invalid duplicate BIP32 derivation (different derivs, same key) 19: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba670000008000000080050000800000", + // Invalid var int for key type + 20: "70736274ff01001c000000000002000000000000000000000000736210ff01000001010010ff70ff01001c00000000000000000000000000000000000000000000", } // All following PSBTs are Taproot specific invalid packets taken from @@ -682,6 +684,9 @@ func TestFinalize2of3(t *testing.T) { t.Fatalf("Error decoding hex: %v", err) } p, err := NewFromRawBytes(bytes.NewReader(b), false) + if err != nil { + t.Fatalf("Error parsing PSBT: %v", err) + } if p.IsComplete() { t.Fatalf("Psbt is complete") } diff --git a/btcutil/psbt/utils.go b/btcutil/psbt/utils.go index 0a9002798e..c47f6afd4d 100644 --- a/btcutil/psbt/utils.go +++ b/btcutil/psbt/utils.go @@ -250,23 +250,32 @@ func getKey(r io.Reader) (int, []byte, error) { // Next, we ready out the designated number of bytes, which may include // a type, key, and optional data. - keyTypeAndData := make([]byte, count) - if _, err := io.ReadFull(r, keyTypeAndData[:]); err != nil { - return -1, nil, err + keyTypeReader := io.LimitReader(r, int64(count)) + keyType, err := wire.ReadVarInt(keyTypeReader, 0) + if err != nil { + return -1, nil, ErrInvalidPsbtFormat } - keyType := int(string(keyTypeAndData)[0]) + // The maximum value of a compact size int is capped in bitcoind, do the + // same here to mimic the behavior. + if keyType > MaxPsbtKeyValue { + return -1, nil, ErrInvalidPsbtFormat + } + + keyData, err := io.ReadAll(keyTypeReader) + if err != nil { + return -1, nil, ErrInvalidPsbtFormat + } // Note that the second return value will usually be empty, since most // keys contain no more than the key type byte. - if len(keyTypeAndData) == 1 { - return keyType, nil, nil + if len(keyData) == 0 { + return int(keyType), nil, nil } // Otherwise, we return the key, along with any data that it may // contain. - return keyType, keyTypeAndData[1:], nil - + return int(keyType), keyData, nil } // readTxOut is a limited version of wire.ReadTxOut, because the latter is not From cc26860b40265e1332cca8748c5dbaf3c81cc094 Mon Sep 17 00:00:00 2001 From: Yong Date: Tue, 25 Jun 2024 22:27:44 +0800 Subject: [PATCH 1023/1056] rpcclient: update error str to match both versions (#2205) This commit updates the error str to match the same error returned from `btcd` for both pre-0.24.2 and post-0.24.2. --- rpcclient/errors.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rpcclient/errors.go b/rpcclient/errors.go index 68c0780dff..928881f1da 100644 --- a/rpcclient/errors.go +++ b/rpcclient/errors.go @@ -411,7 +411,10 @@ var BtcdErrMap = map[string]error{ "transaction already exists in blockchain": ErrTxAlreadyConfirmed, // A transaction in the mempool. - "already have transaction in mempool": ErrTxAlreadyInMempool, + // + // NOTE: For btcd v0.24.2 and beyond, the error message is "already + // have transaction in mempool". + "already have transaction": ErrTxAlreadyInMempool, // A transaction with missing inputs, that never existed or only // existed once in the past. From 139669066ca7631559d45efe25ab5518bb692554 Mon Sep 17 00:00:00 2001 From: Robert <104002271+robertmin1@users.noreply.github.com> Date: Wed, 26 Jun 2024 23:42:49 +0300 Subject: [PATCH 1024/1056] Sending RPC requests through unix sockets (#2168) Sending RPC requests through unix sockets --- go.mod | 1 + go.sum | 4 + .../examples/bitcoincoreunixsocket/README.md | 41 +++++++ .../examples/bitcoincoreunixsocket/main.go | 39 +++++++ rpcclient/infrastructure.go | 106 +++++++++++++++++- 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 rpcclient/examples/bitcoincoreunixsocket/README.md create mode 100644 rpcclient/examples/bitcoincoreunixsocket/main.go diff --git a/go.mod b/go.mod index 6eea83508e..e678d13bcb 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.5.0 // indirect + golang.org/x/net v0.24.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ddd7e1ebd0..777cf82469 100644 --- a/go.sum +++ b/go.sum @@ -91,12 +91,15 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -108,6 +111,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= diff --git a/rpcclient/examples/bitcoincoreunixsocket/README.md b/rpcclient/examples/bitcoincoreunixsocket/README.md new file mode 100644 index 0000000000..6ef9774647 --- /dev/null +++ b/rpcclient/examples/bitcoincoreunixsocket/README.md @@ -0,0 +1,41 @@ +Bitcoin Core HTTP POST Over Unix Socket Example +============================== + +This example shows how to use the rpcclient package to connect to a Bitcoin +Core RPC server using HTTP POST mode over a Unix Socket with TLS disabled +and gets the current block count. + +## Running the Example + +The first step is to use `go get` to download and install the rpcclient package: + +```bash +$ go get github.com/btcsuite/btcd/rpcclient +``` + +Next, modify the `main.go` source to specify the correct RPC username and +password for the RPC server: + +```Go + User: "yourrpcuser", + Pass: "yourrpcpass", +``` + +As Bitcoin Core supports only TCP/IP, we'll redirect RPC requests from the +Unix Socket to Bitcoin Core. For this example, we'll use the `socat` command: + +```bash +$ socat -d UNIX-LISTEN:"my-unix-socket-path",fork TCP:"host-address" +$ socat -d UNIX-LISTEN:/tmp/test.XXXX,fork TCP:localhost:8332 +``` + +Finally, navigate to the example's directory and run it with: + +```bash +$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/bitcoincorehttp +$ go run *.go +``` + +## License + +This example is licensed under the [copyfree](http://copyfree.org) ISC License. diff --git a/rpcclient/examples/bitcoincoreunixsocket/main.go b/rpcclient/examples/bitcoincoreunixsocket/main.go new file mode 100644 index 0000000000..db6bd3e8d0 --- /dev/null +++ b/rpcclient/examples/bitcoincoreunixsocket/main.go @@ -0,0 +1,39 @@ +// Copyright (c) 2014-2017 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package main + +import ( + "log" + + "github.com/btcsuite/btcd/rpcclient" +) + +func main() { + // Connect to local bitcoin core RPC server using HTTP POST mode over a + // Unix Socket. + connCfg := &rpcclient.ConnConfig{ + // For unix sockets, use unix:// + "your unix socket path". + Host: "unix:///tmp/test.XXXX", + User: "yourrpcuser", + Pass: "yourrpcpass", + HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode. + DisableTLS: true, // Bitcoin core does not provide TLS by default. + } + + // Notice the notification parameter is nil since notifications are + // not supported in HTTP POST mode. + client, err := rpcclient.New(connCfg, nil) + if err != nil { + log.Fatal(err) + } + defer client.Shutdown() + + // Get the current block count. + blockCount, err := client.GetBlockCount() + if err != nil { + log.Fatal(err) + } + log.Printf("Block count: %d", blockCount) +} diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 67f908efaa..c051087487 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -7,6 +7,7 @@ package rpcclient import ( "bytes" "container/list" + "context" "crypto/tls" "crypto/x509" "encoding/base64" @@ -20,6 +21,8 @@ import ( "net/http" "net/url" "os" + "strconv" + "strings" "sync" "sync/atomic" "time" @@ -756,7 +759,6 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { if !c.config.DisableTLS { protocol = "https" } - url := protocol + "://" + c.config.Host var ( err, lastErr error @@ -764,6 +766,24 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { httpResponse *http.Response ) + parsedAddr, err := ParseAddressString(c.config.Host) + if err != nil { + jReq.responseChan <- &Response{ + err: fmt.Errorf("failed to parse address %v", err), + } + return + } + + var url string + switch parsedAddr.Network(){ + case "unix", "unixpacket": + // Using a placeholder URL because a non-empty URL is required. + // The Unix domain socket is specified in the DialContext. + url = protocol + "://unix" + default: + url = protocol + "://" + c.config.Host + } + tries := 10 for i := 0; i < tries; i++ { var httpReq *http.Request @@ -1331,10 +1351,17 @@ func newHTTPClient(config *ConnConfig) (*http.Client, error) { } } + parsedAddr, err := ParseAddressString(config.Host) + if err != nil { + return nil, err + } client := http.Client{ Transport: &http.Transport{ Proxy: proxyFunc, TLSClientConfig: tlsConfig, + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial(parsedAddr.Network(), parsedAddr.String()) + }, }, } @@ -1698,3 +1725,80 @@ func (c *Client) Send() error { return nil } + +// ParseAddressString converts an address in string format to a net.Addr that is +// compatible with btcd. UDP is not supported because btcd needs reliable +// connections. We accept a custom function to resolve any TCP addresses so +// that caller is able control exactly how resolution is performed. +func ParseAddressString(strAddress string) (net.Addr, error) { + var parsedNetwork, parsedAddr string + + // Addresses can either be in network://address:port format, + // network:address:port, address:port, or just port. We want to support + // all possible types. + if strings.Contains(strAddress, "://") { + parts := strings.Split(strAddress, "://") + parsedNetwork, parsedAddr = parts[0], parts[1] + } else if strings.Contains(strAddress, ":") { + parts := strings.Split(strAddress, ":") + parsedNetwork = parts[0] + parsedAddr = strings.Join(parts[1:], ":") + } else { + parsedAddr = strAddress + } + + // Only TCP and Unix socket addresses are valid. We can't use IP or + // UDP only connections for anything we do in lnd. + switch parsedNetwork { + case "unix", "unixpacket": + return net.ResolveUnixAddr(parsedNetwork, parsedAddr) + + case "tcp", "tcp4", "tcp6": + return net.ResolveTCPAddr(parsedNetwork, verifyPort(parsedAddr)) + + case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram": + return nil, fmt.Errorf("only TCP or unix socket "+ + "addresses are supported: %s", parsedAddr) + + default: + // We'll now possibly use the local host short circuit + // or parse out an all interfaces listen. + addrWithPort := verifyPort(strAddress) + + // Otherwise, we'll attempt to resolve the host. + return net.ResolveTCPAddr("tcp", addrWithPort) + } +} + +// verifyPort makes sure that an address string has both a host and a port. +// If the address is just a port, then we'll assume that the user is using the +// short cut to specify a localhost:port address. +func verifyPort(address string) string { + host, port, err := net.SplitHostPort(address) + if err != nil { + // If the address itself is just an integer, then we'll assume + // that we're mapping this directly to a localhost:port pair. + // This ensures we maintain the legacy behavior. + if _, err := strconv.Atoi(address); err == nil { + return net.JoinHostPort("localhost", address) + } + + // Otherwise, we'll assume that the address just failed to + // attach its own port, so we'll leave it as is. In the + // case of IPv6 addresses, if the host is already surrounded by + // brackets, then we'll avoid using the JoinHostPort function, + // since it will always add a pair of brackets. + if strings.HasPrefix(address, "[") { + return address + } + return net.JoinHostPort(address, "") + } + + // In the case that both the host and port are empty, we'll use the + // an empty port. + if host == "" && port == "" { + return ":" + } + + return address +} From d881c686e61db35e332fb0309178152dac589b03 Mon Sep 17 00:00:00 2001 From: cec489 <173723251+cec489@users.noreply.github.com> Date: Thu, 27 Jun 2024 12:36:29 -0500 Subject: [PATCH 1025/1056] Fix the btcctl uptime command commit 0b2998b7f279d3aef4d83415dae26948f5a6bdf4 Author: cec489 <173723251+cec489@users.noreply.github.com> Date: Mon Jun 24 20:01:13 2024 +0000 A cleaner fix is to set the startTime in the server Start() function which is where the server is actually started. commit ae6c1256981befb43972e83a086ea663df629873 Author: cec489 <173723251+cec489@users.noreply.github.com> Date: Mon Jun 24 19:15:23 2024 +0000 Fix the btcctl uptime command by moving the setting of startupTime --- server.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server.go b/server.go index 9fca2db20c..66794e4bb7 100644 --- a/server.go +++ b/server.go @@ -2483,6 +2483,7 @@ func (s *server) Start() { // the RPC server are rebroadcast until being included in a block. go s.rebroadcastHandler() + s.rpcServer.cfg.StartupTime = s.startupTime s.rpcServer.Start() } From 4712e20049ebc24c4902049c47aadac27ffdc549 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 1 Jul 2024 21:50:30 +0900 Subject: [PATCH 1026/1056] ffldb: throw error when attempting to delete an open file This change lets us test that we don't attempt to delete open files with unit tests. On Windows this behavior is not allowed which results in an error but on linux and osx it's allowed. To better test Windows compatibilty adding this explicit check in is useful. --- database/ffldb/blockio.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/database/ffldb/blockio.go b/database/ffldb/blockio.go index 2b415a17b0..2272ba1658 100644 --- a/database/ffldb/blockio.go +++ b/database/ffldb/blockio.go @@ -307,6 +307,11 @@ func (s *blockStore) openFile(fileNum uint32) (*lockableFile, error) { // other state cleanup necessary. func (s *blockStore) deleteFile(fileNum uint32) error { filePath := blockFilePath(s.basePath, fileNum) + blockFile := s.openBlockFiles[fileNum] + if blockFile != nil { + err := fmt.Errorf("attempted to delete open file at %v", filePath) + return makeDbErr(database.ErrDriverSpecific, err.Error(), err) + } if err := os.Remove(filePath); err != nil { return makeDbErr(database.ErrDriverSpecific, err.Error(), err) } From 8b5f2aa6f2cbd6c73d51d3f6c7251c7f48288175 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 1 Jul 2024 22:01:36 +0900 Subject: [PATCH 1027/1056] ffldb: add check for deleting files that are open This check let's us ensure that attempting to delete open files are caught during unit tests. --- database/ffldb/driver_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/database/ffldb/driver_test.go b/database/ffldb/driver_test.go index 0b2f452032..e48491a12d 100644 --- a/database/ffldb/driver_test.go +++ b/database/ffldb/driver_test.go @@ -335,6 +335,20 @@ func TestPrune(t *testing.T) { t.Fatal(err) } + // Open the first block file before the pruning happens in the + // code snippet below. This let's us test that block files are + // properly closed before attempting to delete them. + err = db.View(func(tx database.Tx) error { + _, err := tx.FetchBlock(blocks[0].Hash()) + if err != nil { + return err + } + return nil + }) + if err != nil { + t.Fatal(err) + } + var deletedBlocks []chainhash.Hash // This should leave 3 files on disk. From 8ed8ef134067e8af529996c4d027913b5945bf13 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 1 Jul 2024 22:10:42 +0900 Subject: [PATCH 1028/1056] ffldb: refactor out file close code into its own method The existing file close code is refactored out into it's own method closeFile() so that it can be reused elsewhere. --- database/ffldb/blockio.go | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/database/ffldb/blockio.go b/database/ffldb/blockio.go index 2272ba1658..77f97f592e 100644 --- a/database/ffldb/blockio.go +++ b/database/ffldb/blockio.go @@ -281,17 +281,7 @@ func (s *blockStore) openFile(fileNum uint32) (*lockableFile, error) { lruList := s.openBlocksLRU if lruList.Len() >= maxOpenFiles { lruFileNum := lruList.Remove(lruList.Back()).(uint32) - oldBlockFile := s.openBlockFiles[lruFileNum] - - // Close the old file under the write lock for the file in case - // any readers are currently reading from it so it's not closed - // out from under them. - oldBlockFile.Lock() - _ = oldBlockFile.file.Close() - oldBlockFile.Unlock() - - delete(s.openBlockFiles, lruFileNum) - delete(s.fileNumToLRUElem, lruFileNum) + s.closeFile(lruFileNum) } s.fileNumToLRUElem[fileNum] = lruList.PushFront(fileNum) s.lruMutex.Unlock() @@ -302,6 +292,26 @@ func (s *blockStore) openFile(fileNum uint32) (*lockableFile, error) { return blockFile, nil } +// closeFile checks that the file corresponding to the file number is open and +// if it is, it closes it in a concurrency safe manner and cleans up associated +// data in the blockstore struct. +func (s *blockStore) closeFile(fileNum uint32) { + blockFile := s.openBlockFiles[fileNum] + if blockFile == nil { + return + } + + // Close the old file under the write lock for the file in case + // any readers are currently reading from it so it's not closed + // out from under them. + blockFile.Lock() + _ = blockFile.file.Close() + blockFile.Unlock() + + delete(s.openBlockFiles, fileNum) + delete(s.fileNumToLRUElem, fileNum) +} + // deleteFile removes the block file for the passed flat file number. The file // must already be closed and it is the responsibility of the caller to do any // other state cleanup necessary. From c9fae1ac7cca6e6d55baec913286e483e28923a9 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Mon, 1 Jul 2024 20:15:18 +0900 Subject: [PATCH 1029/1056] ffldb: close block files before deleting them The block files may be open when deleteFile is called. This resulted in files not being deleted and erroring out on windows. Properly closing the files closing the files avoids this error. --- database/ffldb/db.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/ffldb/db.go b/database/ffldb/db.go index 3e96bfc738..60103aaa58 100644 --- a/database/ffldb/db.go +++ b/database/ffldb/db.go @@ -1630,6 +1630,9 @@ func (tx *transaction) writePendingAndCommit() error { // We do this first before doing any of the writes as we can't undo // deletions of files. for _, fileNum := range tx.pendingDelFileNums { + // Make sure the file is closed before attempting to delete it. + tx.db.store.closeFile(fileNum) + err := tx.db.store.deleteFileFunc(fileNum) if err != nil { // Nothing we can do if we fail to delete blocks besides From e5d15fddb9c486dfe382bc95dc38d2fd247813bf Mon Sep 17 00:00:00 2001 From: zhiqiangxu <652732310@qq.com> Date: Wed, 10 Jul 2024 20:43:15 +0800 Subject: [PATCH 1030/1056] btcec/ecdsa: remove error return value for SignCompact (#2211) --- btcec/ecdsa/bench_test.go | 2 +- btcec/ecdsa/signature.go | 4 ++-- btcec/ecdsa/signature_test.go | 6 +----- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/btcec/ecdsa/bench_test.go b/btcec/ecdsa/bench_test.go index 3e27994cd4..57864af9fd 100644 --- a/btcec/ecdsa/bench_test.go +++ b/btcec/ecdsa/bench_test.go @@ -170,7 +170,7 @@ func BenchmarkSignCompact(b *testing.B) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - _, _ = SignCompact(privKey, msgHash, true) + _ = SignCompact(privKey, msgHash, true) } } diff --git a/btcec/ecdsa/signature.go b/btcec/ecdsa/signature.go index 11c6267caf..a2574f8794 100644 --- a/btcec/ecdsa/signature.go +++ b/btcec/ecdsa/signature.go @@ -233,9 +233,9 @@ func ParseDERSignature(sigStr []byte) (*Signature, error) { // <(byte of 27+public key solution)+4 if compressed >< padded bytes for signature R> // where the R and S parameters are padde up to the bitlengh of the curve. func SignCompact(key *btcec.PrivateKey, hash []byte, - isCompressedKey bool) ([]byte, error) { + isCompressedKey bool) []byte { - return secp_ecdsa.SignCompact(key, hash, isCompressedKey), nil + return secp_ecdsa.SignCompact(key, hash, isCompressedKey) } // RecoverCompact verifies the compact signature "signature" of "hash" for the diff --git a/btcec/ecdsa/signature_test.go b/btcec/ecdsa/signature_test.go index f36e15db89..7a457b1e66 100644 --- a/btcec/ecdsa/signature_test.go +++ b/btcec/ecdsa/signature_test.go @@ -479,11 +479,7 @@ func testSignCompact(t *testing.T, tag string, curve *btcec.KoblitzCurve, priv, _ := btcec.NewPrivateKey() hashed := []byte("testing") - sig, err := SignCompact(priv, hashed, isCompressed) - if err != nil { - t.Errorf("%s: error signing: %s", tag, err) - return - } + sig := SignCompact(priv, hashed, isCompressed) pk, wasCompressed, err := RecoverCompact(sig, hashed) if err != nil { From ff2e03e11233fa25c01cf4acbf76501fc008b31f Mon Sep 17 00:00:00 2001 From: linghuying <1599935829@qq.com> Date: Tue, 16 Jul 2024 22:02:23 +0900 Subject: [PATCH 1031/1056] chore: fix some comments for struct field (#2214) Signed-off-by: linghuying <1599935829@qq.com> --- mempool/mempool.go | 2 +- mining/policy.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mempool/mempool.go b/mempool/mempool.go index cc0ec10fe0..84e583f4af 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -105,7 +105,7 @@ type Config struct { // This can be nil if the address index is not enabled. AddrIndex *indexers.AddrIndex - // FeeEstimatator provides a feeEstimator. If it is not nil, the mempool + // FeeEstimator provides a feeEstimator. If it is not nil, the mempool // records all new transactions it observes into the feeEstimator. FeeEstimator *FeeEstimator } diff --git a/mining/policy.go b/mining/policy.go index 8ddd575462..b92df27796 100644 --- a/mining/policy.go +++ b/mining/policy.go @@ -29,7 +29,7 @@ type Policy struct { // generating a block template. BlockMaxWeight uint32 - // BlockMinWeight is the minimum block size to be used when generating + // BlockMinSize is the minimum block size to be used when generating // a block template. BlockMinSize uint32 From cefeeaa6b6a3d950eff894814e8a45adc898a0f8 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 23 Jul 2024 10:57:08 +0200 Subject: [PATCH 1032/1056] mod+rpcserver: bump to latest version of btcec --- go.mod | 6 +++--- go.sum | 45 ++++++++++++++++++++++++++++++++++++++++----- rpcserver.go | 9 +-------- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index e678d13bcb..1f445d9065 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/btcsuite/btcd require ( - github.com/btcsuite/btcd/btcec/v2 v2.1.3 + github.com/btcsuite/btcd/btcec/v2 v2.3.4 github.com/btcsuite/btcd/btcutil v1.1.5 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f @@ -16,8 +16,8 @@ require ( github.com/jrick/logrotate v1.0.0 github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 - golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed + golang.org/x/crypto v0.22.0 + golang.org/x/sys v0.19.0 ) require ( diff --git a/go.sum b/go.sum index 777cf82469..bb666c89de 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,9 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= -github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ= +github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= @@ -87,20 +88,33 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -109,14 +123,35 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/rpcserver.go b/rpcserver.go index a3c4062bcc..363661d787 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3595,14 +3595,7 @@ func handleSignMessageWithPrivKey(s *rpcServer, cmd interface{}, closeChan <-cha wire.WriteVarString(&buf, 0, c.Message) messageHash := chainhash.DoubleHashB(buf.Bytes()) - sig, err := ecdsa.SignCompact(wif.PrivKey, - messageHash, wif.CompressPubKey) - if err != nil { - return nil, &btcjson.RPCError{ - Code: btcjson.ErrRPCInvalidAddressOrKey, - Message: "Sign failed", - } - } + sig := ecdsa.SignCompact(wif.PrivKey, messageHash, wif.CompressPubKey) return base64.StdEncoding.EncodeToString(sig), nil } From 3eda1a58a24336c4c1aabe953f84b32a03da62cb Mon Sep 17 00:00:00 2001 From: Eugene Siegel Date: Tue, 6 Aug 2024 11:49:23 -0400 Subject: [PATCH 1033/1056] blockchain: copy utxo status bytes to avoid UB It is undefined behavior if we directly use the value from a Get call after the transaction has completed. --- blockchain/chainio.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/blockchain/chainio.go b/blockchain/chainio.go index 3340dd14a0..27028eac90 100644 --- a/blockchain/chainio.go +++ b/blockchain/chainio.go @@ -1058,7 +1058,14 @@ func dbPutUtxoStateConsistency(dbTx database.Tx, hash *chainhash.Hash) error { // nothing was found. func dbFetchUtxoStateConsistency(dbTx database.Tx) []byte { // Fetch the serialized data from the database. - return dbTx.Metadata().Get(utxoStateConsistencyKeyName) + statusBytes := dbTx.Metadata().Get(utxoStateConsistencyKeyName) + if statusBytes != nil { + result := make([]byte, len(statusBytes)) + copy(result, statusBytes) + return result + } + + return nil } // createChainState initializes both the database and the chain state to the From 8791081be361769c4d0b06764f96814570e78317 Mon Sep 17 00:00:00 2001 From: lencap Date: Fri, 9 Aug 2024 16:51:11 +0800 Subject: [PATCH 1034/1056] chore: fix some comments Signed-off-by: lencap --- rpcadapters.go | 2 +- upnp.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcadapters.go b/rpcadapters.go index 5a6800c532..03905c7b16 100644 --- a/rpcadapters.go +++ b/rpcadapters.go @@ -277,7 +277,7 @@ func (b *rpcSyncMgr) SyncPeerID() int32 { return b.syncMgr.SyncPeerID() } -// LocateBlocks returns the hashes of the blocks after the first known block in +// LocateHeaders returns the hashes of the blocks after the first known block in // the provided locators until the provided stop hash or the current tip is // reached, up to a max of wire.MaxBlockHeadersPerMsg hashes. // diff --git a/upnp.go b/upnp.go index c74e4ed79a..d06cf52f0d 100644 --- a/upnp.go +++ b/upnp.go @@ -201,7 +201,7 @@ func getChildDevice(d *device, deviceType string) *device { return nil } -// getChildDevice searches the service list of device for a service with the +// getChildService searches the service list of device for a service with the // given type. func getChildService(d *device, serviceType string) *service { for i := range d.ServiceList.Service { From b00cec6d3904820e94d9d1675a6f98160830c797 Mon Sep 17 00:00:00 2001 From: Matt Leon Date: Tue, 13 Aug 2024 10:13:49 -0400 Subject: [PATCH 1035/1056] rpcclient: signet support --- rpcclient/infrastructure.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index c051087487..891b517195 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -1502,6 +1502,8 @@ func New(config *ConnConfig, ntfnHandlers *NotificationHandlers) (*Client, error client.chainParams = &chaincfg.TestNet3Params case chaincfg.RegressionNetParams.Name: client.chainParams = &chaincfg.RegressionNetParams + case chaincfg.SigNetParams.Name: + client.chainParams = &chaincfg.SigNetParams case chaincfg.SimNetParams.Name: client.chainParams = &chaincfg.SimNetParams default: From ee7cf5e5645fa0aa8fe934b3a4f99a5b0ee6f2f8 Mon Sep 17 00:00:00 2001 From: Jonathan Harvey-Buschel Date: Wed, 14 Aug 2024 16:29:08 -0400 Subject: [PATCH 1036/1056] wire: check TXID length before creating outpoint --- wire/msgtx.go | 5 +++++ wire/msgtx_test.go | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/wire/msgtx.go b/wire/msgtx.go index 1864ec6e36..e4f3051c47 100644 --- a/wire/msgtx.go +++ b/wire/msgtx.go @@ -229,6 +229,11 @@ func NewOutPointFromString(outpoint string) (*OutPoint, error) { if len(parts) != 2 { return nil, errors.New("outpoint should be of the form txid:index") } + + if len(parts[0]) != chainhash.MaxHashStringSize { + return nil, errors.New("outpoint txid should be 64 hex chars") + } + hash, err := chainhash.NewHashFromStr(parts[0]) if err != nil { return nil, err diff --git a/wire/msgtx_test.go b/wire/msgtx_test.go index e6b7bae44c..62d57098f3 100644 --- a/wire/msgtx_test.go +++ b/wire/msgtx_test.go @@ -849,6 +849,15 @@ func TestTxOutPointFromString(t *testing.T) { }, err: false, }, + { + name: "normal outpoint 2 with 31-byte txid", + input: "c7762a68ff164352bd31fd95fa875204e811c09acef40ba781787eb28e3b55:42", + result: &OutPoint{ + Hash: hashFromStr("c7762a68ff164352bd31fd95fa875204e811c09acef40ba781787eb28e3b55"), + Index: 42, + }, + err: true, + }, { name: "bad string", input: "not_outpoint_not_outpoint_not_outpoint", From 913f95b2b258afac7b0139c4a1bef9f7e3c5bddc Mon Sep 17 00:00:00 2001 From: Alexsandro Date: Thu, 15 Aug 2024 08:56:15 -0300 Subject: [PATCH 1037/1056] Updated github.com/btcsuite/btcd to address CVE-2024-34478 synchronize dependencies --- btcutil/go.mod | 2 +- btcutil/go.sum | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/btcutil/go.mod b/btcutil/go.mod index 9718e6d5fd..79e6511f28 100644 --- a/btcutil/go.mod +++ b/btcutil/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/aead/siphash v1.0.1 - github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd + github.com/btcsuite/btcd v0.24.2 github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/davecgh/go-spew v1.1.1 diff --git a/btcutil/go.sum b/btcutil/go.sum index 5ee4cd5207..b607077b86 100644 --- a/btcutil/go.sum +++ b/btcutil/go.sum @@ -2,13 +2,15 @@ github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= @@ -65,8 +67,13 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -107,5 +114,6 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 1a1dd2a2b30b0599e7200a8239f20ebf99bafb6e Mon Sep 17 00:00:00 2001 From: Bruno Garcia Date: Fri, 23 Aug 2024 16:22:54 -0300 Subject: [PATCH 1038/1056] btcjson: check if both begin and end are numbers in `UnmarshalJSON` --- btcjson/walletsvrcmds.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/btcjson/walletsvrcmds.go b/btcjson/walletsvrcmds.go index 9b787f60c4..2613acf8a4 100644 --- a/btcjson/walletsvrcmds.go +++ b/btcjson/walletsvrcmds.go @@ -903,9 +903,14 @@ func (r *DescriptorRange) UnmarshalJSON(data []byte) error { if len(v) != 2 { return fmt.Errorf("expected [begin,end] integer range, got: %v", unmarshalled) } + begin, ok1 := v[0].(float64) + end, ok2 := v[1].(float64) + if !ok1 || !ok2 { + return fmt.Errorf("expected both begin and end to be numbers, got: %v", v) + } r.Value = []int{ - int(v[0].(float64)), - int(v[1].(float64)), + int(begin), + int(end), } default: return fmt.Errorf("invalid descriptor range value: %v", unmarshalled) From ed879eac20ec02a0780c5f941612740082b58ffa Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Mon, 2 Sep 2024 09:30:25 +0200 Subject: [PATCH 1039/1056] btcjson: turn warnings into StringOrArray type Fixes #2224 and lightningnetwork/lnd#9053. Depending on the version of Bitcoin Core, the "warnings" field in the response to getnetworkinfo is either a single string value or an array of strings. We can easily parse those two variants with a custom type that implements an UnmarshalJSON method. --- btcjson/chainsvrresults.go | 46 ++++++++++++++++++++++++++++++- btcjson/chainsvrresults_test.go | 48 +++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 11c0483d31..433bdda8eb 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/hex" "encoding/json" + "fmt" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -363,6 +364,49 @@ type LocalAddressesResult struct { Score int32 `json:"score"` } +// StringOrArray defines a type that can be used as type that is either a single +// string value or a string array in JSON-RPC commands, depending on the version +// of the chain backend. +type StringOrArray []string + +// MarshalJSON implements the json.Marshaler interface. +func (h StringOrArray) MarshalJSON() ([]byte, error) { + return json.Marshal(h) +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (h *StringOrArray) UnmarshalJSON(data []byte) error { + var unmarshalled interface{} + if err := json.Unmarshal(data, &unmarshalled); err != nil { + return err + } + + switch v := unmarshalled.(type) { + case string: + *h = []string{v} + + case []interface{}: + s := make([]string, len(v)) + for i, e := range v { + str, ok := e.(string) + if !ok { + return fmt.Errorf("invalid string_or_array "+ + "value: %v", unmarshalled) + } + + s[i] = str + } + + *h = s + + default: + return fmt.Errorf("invalid string_or_array value: %v", + unmarshalled) + } + + return nil +} + // GetNetworkInfoResult models the data returned from the getnetworkinfo // command. type GetNetworkInfoResult struct { @@ -380,7 +424,7 @@ type GetNetworkInfoResult struct { RelayFee float64 `json:"relayfee"` IncrementalFee float64 `json:"incrementalfee"` LocalAddresses []LocalAddressesResult `json:"localaddresses"` - Warnings string `json:"warnings"` + Warnings StringOrArray `json:"warnings"` } // GetNodeAddressesResult models the data returned from the getnodeaddresses diff --git a/btcjson/chainsvrresults_test.go b/btcjson/chainsvrresults_test.go index 2566e65f62..122af3dccc 100644 --- a/btcjson/chainsvrresults_test.go +++ b/btcjson/chainsvrresults_test.go @@ -215,3 +215,51 @@ func TestChainSvrMiningInfoResults(t *testing.T) { } } } + +// TestGetNetworkInfoWarnings tests that we can use both a single string value +// and an array of string values for the warnings field in GetNetworkInfoResult. +func TestGetNetworkInfoWarnings(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + result string + expected btcjson.GetNetworkInfoResult + }{ + { + name: "network info with single warning", + result: `{"warnings": "this is a warning"}`, + expected: btcjson.GetNetworkInfoResult{ + Warnings: btcjson.StringOrArray{ + "this is a warning", + }, + }, + }, + { + name: "network info with array of warnings", + result: `{"warnings": ["a", "or", "b"]}`, + expected: btcjson.GetNetworkInfoResult{ + Warnings: btcjson.StringOrArray{ + "a", "or", "b", + }, + }, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + var infoResult btcjson.GetNetworkInfoResult + err := json.Unmarshal([]byte(test.result), &infoResult) + if err != nil { + t.Errorf("Test #%d (%s) unexpected error: %v", i, + test.name, err) + continue + } + if !reflect.DeepEqual(infoResult, test.expected) { + t.Errorf("Test #%d (%s) unexpected marhsalled data - "+ + "got %+v, want %+v", i, test.name, infoResult, + test.expected) + continue + } + } +} From 35df8015bad47f6e346a9f99dcbb97e446b5d9d7 Mon Sep 17 00:00:00 2001 From: huochexizhan Date: Wed, 25 Sep 2024 17:56:44 +0800 Subject: [PATCH 1040/1056] Formatting code with gofmt Signed-off-by: huochexizhan --- .../examples/bitcoincoreunixsocket/main.go | 10 +- rpcclient/examples/btcdwebsockets/main.go | 2 +- .../examples/btcwalletwebsockets/main.go | 2 +- rpcclient/infrastructure.go | 130 +++++++++--------- 4 files changed, 72 insertions(+), 72 deletions(-) diff --git a/rpcclient/examples/bitcoincoreunixsocket/main.go b/rpcclient/examples/bitcoincoreunixsocket/main.go index db6bd3e8d0..b061d19ff8 100644 --- a/rpcclient/examples/bitcoincoreunixsocket/main.go +++ b/rpcclient/examples/bitcoincoreunixsocket/main.go @@ -15,11 +15,11 @@ func main() { // Unix Socket. connCfg := &rpcclient.ConnConfig{ // For unix sockets, use unix:// + "your unix socket path". - Host: "unix:///tmp/test.XXXX", - User: "yourrpcuser", - Pass: "yourrpcpass", - HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode. - DisableTLS: true, // Bitcoin core does not provide TLS by default. + Host: "unix:///tmp/test.XXXX", + User: "yourrpcuser", + Pass: "yourrpcpass", + HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode. + DisableTLS: true, // Bitcoin core does not provide TLS by default. } // Notice the notification parameter is nil since notifications are diff --git a/rpcclient/examples/btcdwebsockets/main.go b/rpcclient/examples/btcdwebsockets/main.go index 878526b076..fe3fc81b7c 100644 --- a/rpcclient/examples/btcdwebsockets/main.go +++ b/rpcclient/examples/btcdwebsockets/main.go @@ -5,8 +5,8 @@ package main import ( - "os" "log" + "os" "path/filepath" "time" diff --git a/rpcclient/examples/btcwalletwebsockets/main.go b/rpcclient/examples/btcwalletwebsockets/main.go index a63ef3db91..c41b4414d0 100644 --- a/rpcclient/examples/btcwalletwebsockets/main.go +++ b/rpcclient/examples/btcwalletwebsockets/main.go @@ -5,8 +5,8 @@ package main import ( - "os" "log" + "os" "path/filepath" "time" diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 891b517195..bc7ac2d2a5 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -775,7 +775,7 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { } var url string - switch parsedAddr.Network(){ + switch parsedAddr.Network() { case "unix", "unixpacket": // Using a placeholder URL because a non-empty URL is required. // The Unix domain socket is specified in the DialContext. @@ -1733,74 +1733,74 @@ func (c *Client) Send() error { // connections. We accept a custom function to resolve any TCP addresses so // that caller is able control exactly how resolution is performed. func ParseAddressString(strAddress string) (net.Addr, error) { - var parsedNetwork, parsedAddr string - - // Addresses can either be in network://address:port format, - // network:address:port, address:port, or just port. We want to support - // all possible types. - if strings.Contains(strAddress, "://") { - parts := strings.Split(strAddress, "://") - parsedNetwork, parsedAddr = parts[0], parts[1] - } else if strings.Contains(strAddress, ":") { - parts := strings.Split(strAddress, ":") - parsedNetwork = parts[0] - parsedAddr = strings.Join(parts[1:], ":") - } else { - parsedAddr = strAddress - } - - // Only TCP and Unix socket addresses are valid. We can't use IP or - // UDP only connections for anything we do in lnd. - switch parsedNetwork { - case "unix", "unixpacket": - return net.ResolveUnixAddr(parsedNetwork, parsedAddr) - - case "tcp", "tcp4", "tcp6": - return net.ResolveTCPAddr(parsedNetwork, verifyPort(parsedAddr)) - - case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram": - return nil, fmt.Errorf("only TCP or unix socket "+ - "addresses are supported: %s", parsedAddr) - - default: - // We'll now possibly use the local host short circuit - // or parse out an all interfaces listen. - addrWithPort := verifyPort(strAddress) - - // Otherwise, we'll attempt to resolve the host. - return net.ResolveTCPAddr("tcp", addrWithPort) - } + var parsedNetwork, parsedAddr string + + // Addresses can either be in network://address:port format, + // network:address:port, address:port, or just port. We want to support + // all possible types. + if strings.Contains(strAddress, "://") { + parts := strings.Split(strAddress, "://") + parsedNetwork, parsedAddr = parts[0], parts[1] + } else if strings.Contains(strAddress, ":") { + parts := strings.Split(strAddress, ":") + parsedNetwork = parts[0] + parsedAddr = strings.Join(parts[1:], ":") + } else { + parsedAddr = strAddress + } + + // Only TCP and Unix socket addresses are valid. We can't use IP or + // UDP only connections for anything we do in lnd. + switch parsedNetwork { + case "unix", "unixpacket": + return net.ResolveUnixAddr(parsedNetwork, parsedAddr) + + case "tcp", "tcp4", "tcp6": + return net.ResolveTCPAddr(parsedNetwork, verifyPort(parsedAddr)) + + case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram": + return nil, fmt.Errorf("only TCP or unix socket "+ + "addresses are supported: %s", parsedAddr) + + default: + // We'll now possibly use the local host short circuit + // or parse out an all interfaces listen. + addrWithPort := verifyPort(strAddress) + + // Otherwise, we'll attempt to resolve the host. + return net.ResolveTCPAddr("tcp", addrWithPort) + } } // verifyPort makes sure that an address string has both a host and a port. // If the address is just a port, then we'll assume that the user is using the // short cut to specify a localhost:port address. func verifyPort(address string) string { - host, port, err := net.SplitHostPort(address) - if err != nil { - // If the address itself is just an integer, then we'll assume - // that we're mapping this directly to a localhost:port pair. - // This ensures we maintain the legacy behavior. - if _, err := strconv.Atoi(address); err == nil { - return net.JoinHostPort("localhost", address) - } - - // Otherwise, we'll assume that the address just failed to - // attach its own port, so we'll leave it as is. In the - // case of IPv6 addresses, if the host is already surrounded by - // brackets, then we'll avoid using the JoinHostPort function, - // since it will always add a pair of brackets. - if strings.HasPrefix(address, "[") { - return address - } - return net.JoinHostPort(address, "") - } - - // In the case that both the host and port are empty, we'll use the - // an empty port. - if host == "" && port == "" { - return ":" - } - - return address + host, port, err := net.SplitHostPort(address) + if err != nil { + // If the address itself is just an integer, then we'll assume + // that we're mapping this directly to a localhost:port pair. + // This ensures we maintain the legacy behavior. + if _, err := strconv.Atoi(address); err == nil { + return net.JoinHostPort("localhost", address) + } + + // Otherwise, we'll assume that the address just failed to + // attach its own port, so we'll leave it as is. In the + // case of IPv6 addresses, if the host is already surrounded by + // brackets, then we'll avoid using the JoinHostPort function, + // since it will always add a pair of brackets. + if strings.HasPrefix(address, "[") { + return address + } + return net.JoinHostPort(address, "") + } + + // In the case that both the host and port are empty, we'll use the + // an empty port. + if host == "" && port == "" { + return ":" + } + + return address } From 019988b6961477128a62c5dd1e06891203570c4e Mon Sep 17 00:00:00 2001 From: omahs <73983677+omahs@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:41:44 +0200 Subject: [PATCH 1041/1056] multi: fix typos --- database/ffldb/blockio.go | 6 +++--- docs/code_contribution_guidelines.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/database/ffldb/blockio.go b/database/ffldb/blockio.go index 77f97f592e..c4952373db 100644 --- a/database/ffldb/blockio.go +++ b/database/ffldb/blockio.go @@ -137,7 +137,7 @@ type blockStore struct { // lruMutex protects concurrent access to the least recently used list // and lookup map. // - // openBlocksLRU tracks how the open files are refenced by pushing the + // openBlocksLRU tracks how the open files are referenced by pushing the // most recently used files to the front of the list thereby trickling // the least recently used files to end of the list. When a file needs // to be closed due to exceeding the max number of allowed open @@ -224,7 +224,7 @@ func serializeBlockLoc(loc blockLocation) []byte { return serializedData[:] } -// blockFilePath return the file path for the provided block file number. +// blockFilePath returns the file path for the provided block file number. func blockFilePath(dbPath string, fileNum uint32) string { fileName := fmt.Sprintf(blockFilenameTemplate, fileNum) return filepath.Join(dbPath, fileName) @@ -780,7 +780,7 @@ func scanBlockFiles(dbPath string) (int, int, uint32, error) { // and offset set and all fields initialized. func newBlockStore(basePath string, network wire.BitcoinNet) (*blockStore, error) { // Look for the end of the latest block to file to determine what the - // write cursor position is from the viewpoing of the block files on + // write cursor position is from the viewpoint of the block files on // disk. _, fileNum, fileOff, err := scanBlockFiles(basePath) if err != nil { diff --git a/docs/code_contribution_guidelines.md b/docs/code_contribution_guidelines.md index da775878da..0fc0f74de3 100644 --- a/docs/code_contribution_guidelines.md +++ b/docs/code_contribution_guidelines.md @@ -223,8 +223,8 @@ commit messages. Here are some of the reasons why wrapping your commit messages to 72 columns is a good thing. -- git log doesn’t do any special special wrapping of the commit messages. With - the default pager of less -S, this means your paragraphs flow far off the edge +- git log doesn’t do any special wrapping of the commit messages. With the + default pager of less -S, this means your paragraphs flow far off the edge of the screen, making them difficult to read. On an 80 column terminal, if we subtract 4 columns for the indent on the left and 4 more for symmetry on the right, we’re left with 72 columns. From 433781aaffe3cdb27cd2cf571b0b6ceb26e03995 Mon Sep 17 00:00:00 2001 From: Afanti <127061691+threewebcode@users.noreply.github.com> Date: Tue, 8 Oct 2024 20:47:41 +0800 Subject: [PATCH 1042/1056] multi: fix typos --- txscript/opcode.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/txscript/opcode.go b/txscript/opcode.go index 1cd3ba24fb..770e5b470d 100644 --- a/txscript/opcode.go +++ b/txscript/opcode.go @@ -1989,7 +1989,7 @@ func opcodeCheckSig(op *opcode, data []byte, vm *Engine) error { return err } - // The signature actually needs needs to be longer than this, but at + // The signature actually needs to be longer than this, but at // least 1 byte is needed for the hash type below. The full length is // checked depending on the script flags and upon parsing the signature. // From b513ac2da7854b4a0be1bb36d9d1c33c32adfaad Mon Sep 17 00:00:00 2001 From: Santiago Rincon Date: Tue, 8 Oct 2024 08:05:33 -0500 Subject: [PATCH 1043/1056] docs: correct link to redirect to btcutil docs From ee68dc66a835bf2c9333f3d7b33791841f561c84 Mon Sep 17 00:00:00 2001 From: Abirdcfly Date: Tue, 8 Oct 2024 21:09:20 +0800 Subject: [PATCH 1044/1056] btcec+mempool: delete minor unreachable code caused by t.Fatal Signed-off-by: Abirdcfly --- btcec/btcec_test.go | 3 --- mempool/policy_test.go | 2 -- 2 files changed, 5 deletions(-) diff --git a/btcec/btcec_test.go b/btcec/btcec_test.go index f5d9395274..b08155e2f0 100644 --- a/btcec/btcec_test.go +++ b/btcec/btcec_test.go @@ -651,14 +651,12 @@ func TestScalarMultRand(t *testing.T) { _, err := rand.Read(data) if err != nil { t.Fatalf("failed to read random data at %d", i) - break } x, y = s256.ScalarMult(x, y, data) exponent.Mul(exponent, new(big.Int).SetBytes(data)) xWant, yWant := s256.ScalarBaseMult(exponent.Bytes()) if x.Cmp(xWant) != 0 || y.Cmp(yWant) != 0 { t.Fatalf("%d: bad output for %X: got (%X, %X), want (%X, %X)", i, data, x, y, xWant, yWant) - break } } } @@ -814,7 +812,6 @@ func TestSplitKRand(t *testing.T) { _, err := rand.Read(bytesK) if err != nil { t.Fatalf("failed to read random data at %d", i) - break } k := new(big.Int).SetBytes(bytesK) k1, k2, k1Sign, k2Sign := splitK(bytesK) diff --git a/mempool/policy_test.go b/mempool/policy_test.go index 1b29d71f1f..29c0956a0e 100644 --- a/mempool/policy_test.go +++ b/mempool/policy_test.go @@ -190,7 +190,6 @@ func TestCheckPkScriptStandard(t *testing.T) { if err != nil { t.Fatalf("TestCheckPkScriptStandard test '%s' "+ "failed: %v", test.name, err) - continue } scriptClass := txscript.GetScriptClass(script) got := checkPkScriptStandard(script, scriptClass) @@ -272,7 +271,6 @@ func TestDust(t *testing.T) { if res != test.isDust { t.Fatalf("Dust test '%s' failed: want %v got %v", test.name, test.isDust, res) - continue } } } From 44c874f9f6ed650f288269a34108e1cbf755b89e Mon Sep 17 00:00:00 2001 From: ziggie Date: Thu, 10 Oct 2024 10:05:01 +0200 Subject: [PATCH 1045/1056] rpcclient: add http timeout --- rpcclient/infrastructure.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 891b517195..eaa050a735 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -92,6 +92,10 @@ const ( // requestRetryInterval is the initial amount of time to wait in between // retries when sending HTTP POST requests. requestRetryInterval = time.Millisecond * 500 + + // defaultHTTPTimeout is the default timeout for an http request, so the + // request does not block indefinitely. + defaultHTTPTimeout = time.Minute ) // jsonRequest holds information about a json request that is used to properly @@ -1363,6 +1367,7 @@ func newHTTPClient(config *ConnConfig) (*http.Client, error) { return net.Dial(parsedAddr.Network(), parsedAddr.String()) }, }, + Timeout: defaultHTTPTimeout, } return &client, nil From 684d64ad74fed203fb846c032f2b55b3e3c36734 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Wed, 6 Nov 2024 13:03:27 +0000 Subject: [PATCH 1046/1056] Add support for wtxidrelay message. (#2272) * Add support for wtxidrelay message. This adds support for the wtxidrelay (BIP339) message in wire. While here, add tests for sendaddrv2 and rename AddrV2Version to SendAddrV2Version in order to make the code consistent with all other messages. This diff does keep the old AddrV2Version constant for backwards compatibility. * Bump copyrights --- LICENSE | 2 +- peer/peer.go | 21 ++-- wire/message.go | 14 ++- wire/msgsendaddrv2.go | 13 +++ wire/msgsendaddrv2_test.go | 193 +++++++++++++++++++++++++++++++++++++ wire/msgwtxidrelay.go | 59 ++++++++++++ wire/msgwtxidrelay_test.go | 193 +++++++++++++++++++++++++++++++++++++ wire/protocol.go | 18 ++-- 8 files changed, 490 insertions(+), 23 deletions(-) create mode 100644 wire/msgsendaddrv2_test.go create mode 100644 wire/msgwtxidrelay.go create mode 100644 wire/msgwtxidrelay_test.go diff --git a/LICENSE b/LICENSE index 46dcd39508..8005b8652d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ ISC License -Copyright (c) 2013-2023 The btcsuite developers +Copyright (c) 2013-2024 The btcsuite developers Copyright (c) 2015-2016 The Decred developers Permission to use, copy, modify, and distribute this software for any diff --git a/peer/peer.go b/peer/peer.go index 195fc0b4fe..5767cbbf66 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -18,18 +18,19 @@ import ( "sync/atomic" "time" + "github.com/btcsuite/go-socks/socks" + "github.com/davecgh/go-spew/spew" + "github.com/decred/dcrd/lru" + "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/go-socks/socks" - "github.com/davecgh/go-spew/spew" - "github.com/decred/dcrd/lru" ) const ( // MaxProtocolVersion is the max protocol version the peer supports. - MaxProtocolVersion = wire.AddrV2Version + MaxProtocolVersion = wire.SendAddrV2Version // DefaultTrickleInterval is the min time between attempts to send an // inv message to a peer. @@ -877,8 +878,8 @@ func (p *Peer) PushAddrMsg(addresses []*wire.NetAddress) ([]*wire.NetAddress, er // // This function is safe for concurrent access. func (p *Peer) PushAddrV2Msg(addrs []*wire.NetAddressV2) ( - []*wire.NetAddressV2, error) { - + []*wire.NetAddressV2, error, +) { count := len(addrs) // Nothing to send. @@ -1900,8 +1901,8 @@ func (p *Peer) QueueMessage(msg wire.Message, doneChan chan<- struct{}) { // // This function is safe for concurrent access. func (p *Peer) QueueMessageWithEncoding(msg wire.Message, doneChan chan<- struct{}, - encoding wire.MessageEncoding) { - + encoding wire.MessageEncoding, +) { // Avoid risk of deadlock if goroutine already exited. The goroutine // we will be sending to hangs around until it knows for a fact that // it is marked as disconnected and *then* it drains the channels. @@ -2152,7 +2153,7 @@ func (p *Peer) writeLocalVersionMsg() error { // writeSendAddrV2Msg writes our sendaddrv2 message to the remote peer if the // peer supports protocol version 70016 and above. func (p *Peer) writeSendAddrV2Msg(pver uint32) error { - if pver < wire.AddrV2Version { + if pver < wire.SendAddrV2Version { return nil } @@ -2180,7 +2181,7 @@ func (p *Peer) waitToFinishNegotiation(pver uint32) error { switch m := remoteMsg.(type) { case *wire.MsgSendAddrV2: - if pver >= wire.AddrV2Version { + if pver >= wire.SendAddrV2Version { p.flagsMtx.Lock() p.sendAddrV2 = true p.flagsMtx.Unlock() diff --git a/wire/message.go b/wire/message.go index 1f412fa6fa..a90fb62733 100644 --- a/wire/message.go +++ b/wire/message.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2013-2024 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -59,6 +59,7 @@ const ( CmdCFHeaders = "cfheaders" CmdCFCheckpt = "cfcheckpt" CmdSendAddrV2 = "sendaddrv2" + CmdWTxIdRelay = "wtxidrelay" ) // MessageEncoding represents the wire message encoding format to be used. @@ -111,6 +112,9 @@ func makeEmptyMessage(command string) (Message, error) { case CmdSendAddrV2: msg = &MsgSendAddrV2{} + case CmdWTxIdRelay: + msg = &MsgWTxIdRelay{} + case CmdGetAddr: msg = &MsgGetAddr{} @@ -276,8 +280,8 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) erro // to specify the message encoding format to be used when serializing wire // messages. func WriteMessageWithEncodingN(w io.Writer, msg Message, pver uint32, - btcnet BitcoinNet, encoding MessageEncoding) (int, error) { - + btcnet BitcoinNet, encoding MessageEncoding, +) (int, error) { totalBytes := 0 // Enforce max command size. @@ -353,8 +357,8 @@ func WriteMessageWithEncodingN(w io.Writer, msg Message, pver uint32, // allows the caller to specify which message encoding is to to consult when // decoding wire messages. func ReadMessageWithEncodingN(r io.Reader, pver uint32, btcnet BitcoinNet, - enc MessageEncoding) (int, Message, []byte, error) { - + enc MessageEncoding, +) (int, Message, []byte, error) { totalBytes := 0 n, hdr, err := readMessageHeader(r) totalBytes += n diff --git a/wire/msgsendaddrv2.go b/wire/msgsendaddrv2.go index d6d19efb27..8348b815ba 100644 --- a/wire/msgsendaddrv2.go +++ b/wire/msgsendaddrv2.go @@ -1,6 +1,7 @@ package wire import ( + "fmt" "io" ) @@ -14,12 +15,24 @@ type MsgSendAddrV2 struct{} // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgSendAddrV2) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { + if pver < SendAddrV2Version { + str := fmt.Sprintf("sendaddrv2 message invalid for protocol "+ + "version %d", pver) + return messageError("MsgSendAddrV2.BtcDecode", str) + } + return nil } // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgSendAddrV2) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { + if pver < SendAddrV2Version { + str := fmt.Sprintf("sendaddrv2 message invalid for protocol "+ + "version %d", pver) + return messageError("MsgSendAddrV2.BtcEncode", str) + } + return nil } diff --git a/wire/msgsendaddrv2_test.go b/wire/msgsendaddrv2_test.go new file mode 100644 index 0000000000..db6be1d21f --- /dev/null +++ b/wire/msgsendaddrv2_test.go @@ -0,0 +1,193 @@ +// Copyright (c) 2024 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "bytes" + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +// TestSendAddrV2 tests the MsgSendAddrV2 API against the latest protocol +// version. +func TestSendAddrV2(t *testing.T) { + pver := ProtocolVersion + enc := BaseEncoding + + // Ensure the command is expected value. + wantCmd := "sendaddrv2" + msg := NewMsgSendAddrV2() + if cmd := msg.Command(); cmd != wantCmd { + t.Errorf("NewMsgSendAddrV2: wrong command - got %v want %v", + cmd, wantCmd) + } + + // Ensure max payload is expected value. + wantPayload := uint32(0) + maxPayload := msg.MaxPayloadLength(pver) + if maxPayload != wantPayload { + t.Errorf("MaxPayloadLength: wrong max payload length for "+ + "protocol version %d - got %v, want %v", pver, + maxPayload, wantPayload) + } + + // Test encode with latest protocol version. + var buf bytes.Buffer + err := msg.BtcEncode(&buf, pver, enc) + if err != nil { + t.Errorf("encode of MsgSendAddrV2 failed %v err <%v>", msg, + err) + } + + // Older protocol versions should fail encode since message didn't + // exist yet. + oldPver := SendAddrV2Version - 1 + err = msg.BtcEncode(&buf, oldPver, enc) + if err == nil { + s := "encode of MsgSendAddrV2 passed for old protocol " + + "version %v err <%v>" + t.Errorf(s, msg, err) + } + + // Test decode with latest protocol version. + readmsg := NewMsgSendAddrV2() + err = readmsg.BtcDecode(&buf, pver, enc) + if err != nil { + t.Errorf("decode of MsgSendAddrV2 failed [%v] err <%v>", buf, + err) + } + + // Older protocol versions should fail decode since message didn't + // exist yet. + err = readmsg.BtcDecode(&buf, oldPver, enc) + if err == nil { + s := "decode of MsgSendAddrV2 passed for old protocol " + + "version %v err <%v>" + t.Errorf(s, msg, err) + } +} + +// TestSendAddrV2BIP0130 tests the MsgSendAddrV2 API against the protocol +// prior to version SendAddrV2Version. +func TestSendAddrV2BIP0130(t *testing.T) { + // Use the protocol version just prior to SendAddrV2Version changes. + pver := SendAddrV2Version - 1 + enc := BaseEncoding + + msg := NewMsgSendAddrV2() + + // Test encode with old protocol version. + var buf bytes.Buffer + err := msg.BtcEncode(&buf, pver, enc) + if err == nil { + t.Errorf("encode of MsgSendAddrV2 succeeded when it should " + + "have failed") + } + + // Test decode with old protocol version. + readmsg := NewMsgSendAddrV2() + err = readmsg.BtcDecode(&buf, pver, enc) + if err == nil { + t.Errorf("decode of MsgSendAddrV2 succeeded when it should " + + "have failed") + } +} + +// TestSendAddrV2CrossProtocol tests the MsgSendAddrV2 API when encoding with +// the latest protocol version and decoding with SendAddrV2Version. +func TestSendAddrV2CrossProtocol(t *testing.T) { + enc := BaseEncoding + msg := NewMsgSendAddrV2() + + // Encode with latest protocol version. + var buf bytes.Buffer + err := msg.BtcEncode(&buf, ProtocolVersion, enc) + if err != nil { + t.Errorf("encode of MsgSendAddrV2 failed %v err <%v>", msg, + err) + } + + // Decode with old protocol version. + readmsg := NewMsgSendAddrV2() + err = readmsg.BtcDecode(&buf, SendAddrV2Version, enc) + if err != nil { + t.Errorf("decode of MsgSendAddrV2 failed [%v] err <%v>", buf, + err) + } +} + +// TestSendAddrV2Wire tests the MsgSendAddrV2 wire encode and decode for +// various protocol versions. +func TestSendAddrV2Wire(t *testing.T) { + msgSendAddrV2 := NewMsgSendAddrV2() + msgSendAddrV2Encoded := []byte{} + + tests := []struct { + in *MsgSendAddrV2 // Message to encode + out *MsgSendAddrV2 // Expected decoded message + buf []byte // Wire encoding + pver uint32 // Protocol version for wire encoding + enc MessageEncoding // Message encoding format + }{ + // Latest protocol version. + { + msgSendAddrV2, + msgSendAddrV2, + msgSendAddrV2Encoded, + ProtocolVersion, + BaseEncoding, + }, + + // Protocol version SendAddrV2Version+1 + { + msgSendAddrV2, + msgSendAddrV2, + msgSendAddrV2Encoded, + SendAddrV2Version + 1, + BaseEncoding, + }, + + // Protocol version SendAddrV2Version + { + msgSendAddrV2, + msgSendAddrV2, + msgSendAddrV2Encoded, + SendAddrV2Version, + BaseEncoding, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + // Encode the message to wire format. + var buf bytes.Buffer + err := test.in.BtcEncode(&buf, test.pver, test.enc) + if err != nil { + t.Errorf("BtcEncode #%d error %v", i, err) + continue + } + if !bytes.Equal(buf.Bytes(), test.buf) { + t.Errorf("BtcEncode #%d\n got: %s want: %s", i, + spew.Sdump(buf.Bytes()), spew.Sdump(test.buf)) + continue + } + + // Decode the message from wire format. + var msg MsgSendAddrV2 + rbuf := bytes.NewReader(test.buf) + err = msg.BtcDecode(rbuf, test.pver, test.enc) + if err != nil { + t.Errorf("BtcDecode #%d error %v", i, err) + continue + } + if !reflect.DeepEqual(&msg, test.out) { + t.Errorf("BtcDecode #%d\n got: %s want: %s", i, + spew.Sdump(msg), spew.Sdump(test.out)) + continue + } + } +} diff --git a/wire/msgwtxidrelay.go b/wire/msgwtxidrelay.go new file mode 100644 index 0000000000..480c711dee --- /dev/null +++ b/wire/msgwtxidrelay.go @@ -0,0 +1,59 @@ +// Copyright (c) 2024 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "fmt" + "io" +) + +// MsgWTxIdRelay defines a bitcoin wtxidrelay message which is used for a peer +// to signal support for relaying witness transaction id (BIP141). It +// implements the Message interface. +// +// This message has no payload. +type MsgWTxIdRelay struct{} + +// BtcDecode decodes r using the bitcoin protocol encoding into the receiver. +// This is part of the Message interface implementation. +func (msg *MsgWTxIdRelay) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { + if pver < WTxIdRelayVersion { + str := fmt.Sprintf("wtxidrelay message invalid for protocol "+ + "version %d", pver) + return messageError("MsgWTxIdRelay.BtcDecode", str) + } + + return nil +} + +// BtcEncode encodes the receiver to w using the bitcoin protocol encoding. +// This is part of the Message interface implementation. +func (msg *MsgWTxIdRelay) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { + if pver < WTxIdRelayVersion { + str := fmt.Sprintf("wtxidrelay message invalid for protocol "+ + "version %d", pver) + return messageError("MsgWTxIdRelay.BtcEncode", str) + } + + return nil +} + +// Command returns the protocol command string for the message. This is part +// of the Message interface implementation. +func (msg *MsgWTxIdRelay) Command() string { + return CmdWTxIdRelay +} + +// MaxPayloadLength returns the maximum length the payload can be for the +// receiver. This is part of the Message interface implementation. +func (msg *MsgWTxIdRelay) MaxPayloadLength(pver uint32) uint32 { + return 0 +} + +// NewMsgWTxIdRelay returns a new bitcoin wtxidrelay message that conforms +// to the Message interface. +func NewMsgWTxIdRelay() *MsgWTxIdRelay { + return &MsgWTxIdRelay{} +} diff --git a/wire/msgwtxidrelay_test.go b/wire/msgwtxidrelay_test.go new file mode 100644 index 0000000000..e7cde73a7b --- /dev/null +++ b/wire/msgwtxidrelay_test.go @@ -0,0 +1,193 @@ +// Copyright (c) 2024 The btcsuite developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package wire + +import ( + "bytes" + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +// TestWTxIdRelay tests the MsgWTxIdRelay API against the latest protocol +// version. +func TestWTxIdRelay(t *testing.T) { + pver := ProtocolVersion + enc := BaseEncoding + + // Ensure the command is expected value. + wantCmd := "wtxidrelay" + msg := NewMsgWTxIdRelay() + if cmd := msg.Command(); cmd != wantCmd { + t.Errorf("NewMsgWTxIdRelay: wrong command - got %v want %v", + cmd, wantCmd) + } + + // Ensure max payload is expected value. + wantPayload := uint32(0) + maxPayload := msg.MaxPayloadLength(pver) + if maxPayload != wantPayload { + t.Errorf("MaxPayloadLength: wrong max payload length for "+ + "protocol version %d - got %v, want %v", pver, + maxPayload, wantPayload) + } + + // Test encode with latest protocol version. + var buf bytes.Buffer + err := msg.BtcEncode(&buf, pver, enc) + if err != nil { + t.Errorf("encode of MsgWTxIdRelay failed %v err <%v>", msg, + err) + } + + // Older protocol versions should fail encode since message didn't + // exist yet. + oldPver := WTxIdRelayVersion - 1 + err = msg.BtcEncode(&buf, oldPver, enc) + if err == nil { + s := "encode of MsgWTxIdRelay passed for old protocol " + + "version %v err <%v>" + t.Errorf(s, msg, err) + } + + // Test decode with latest protocol version. + readmsg := NewMsgWTxIdRelay() + err = readmsg.BtcDecode(&buf, pver, enc) + if err != nil { + t.Errorf("decode of MsgWTxIdRelay failed [%v] err <%v>", buf, + err) + } + + // Older protocol versions should fail decode since message didn't + // exist yet. + err = readmsg.BtcDecode(&buf, oldPver, enc) + if err == nil { + s := "decode of MsgWTxIdRelay passed for old protocol " + + "version %v err <%v>" + t.Errorf(s, msg, err) + } +} + +// TestWTxIdRelayBIP0130 tests the MsgWTxIdRelay API against the protocol +// prior to version WTxIdRelayVersion. +func TestWTxIdRelayBIP0130(t *testing.T) { + // Use the protocol version just prior to WTxIdRelayVersion changes. + pver := WTxIdRelayVersion - 1 + enc := BaseEncoding + + msg := NewMsgWTxIdRelay() + + // Test encode with old protocol version. + var buf bytes.Buffer + err := msg.BtcEncode(&buf, pver, enc) + if err == nil { + t.Errorf("encode of MsgWTxIdRelay succeeded when it should " + + "have failed") + } + + // Test decode with old protocol version. + readmsg := NewMsgWTxIdRelay() + err = readmsg.BtcDecode(&buf, pver, enc) + if err == nil { + t.Errorf("decode of MsgWTxIdRelay succeeded when it should " + + "have failed") + } +} + +// TestWTxIdRelayCrossProtocol tests the MsgWTxIdRelay API when encoding with +// the latest protocol version and decoding with WTxIdRelayVersion. +func TestWTxIdRelayCrossProtocol(t *testing.T) { + enc := BaseEncoding + msg := NewMsgWTxIdRelay() + + // Encode with latest protocol version. + var buf bytes.Buffer + err := msg.BtcEncode(&buf, ProtocolVersion, enc) + if err != nil { + t.Errorf("encode of MsgWTxIdRelay failed %v err <%v>", msg, + err) + } + + // Decode with old protocol version. + readmsg := NewMsgWTxIdRelay() + err = readmsg.BtcDecode(&buf, WTxIdRelayVersion, enc) + if err != nil { + t.Errorf("decode of MsgWTxIdRelay failed [%v] err <%v>", buf, + err) + } +} + +// TestWTxIdRelayWire tests the MsgWTxIdRelay wire encode and decode for +// various protocol versions. +func TestWTxIdRelayWire(t *testing.T) { + msgWTxIdRelay := NewMsgWTxIdRelay() + msgWTxIdRelayEncoded := []byte{} + + tests := []struct { + in *MsgWTxIdRelay // Message to encode + out *MsgWTxIdRelay // Expected decoded message + buf []byte // Wire encoding + pver uint32 // Protocol version for wire encoding + enc MessageEncoding // Message encoding format + }{ + // Latest protocol version. + { + msgWTxIdRelay, + msgWTxIdRelay, + msgWTxIdRelayEncoded, + ProtocolVersion, + BaseEncoding, + }, + + // Protocol version WTxIdRelayVersion+1 + { + msgWTxIdRelay, + msgWTxIdRelay, + msgWTxIdRelayEncoded, + WTxIdRelayVersion + 1, + BaseEncoding, + }, + + // Protocol version WTxIdRelayVersion + { + msgWTxIdRelay, + msgWTxIdRelay, + msgWTxIdRelayEncoded, + WTxIdRelayVersion, + BaseEncoding, + }, + } + + t.Logf("Running %d tests", len(tests)) + for i, test := range tests { + // Encode the message to wire format. + var buf bytes.Buffer + err := test.in.BtcEncode(&buf, test.pver, test.enc) + if err != nil { + t.Errorf("BtcEncode #%d error %v", i, err) + continue + } + if !bytes.Equal(buf.Bytes(), test.buf) { + t.Errorf("BtcEncode #%d\n got: %s want: %s", i, + spew.Sdump(buf.Bytes()), spew.Sdump(test.buf)) + continue + } + + // Decode the message from wire format. + var msg MsgWTxIdRelay + rbuf := bytes.NewReader(test.buf) + err = msg.BtcDecode(rbuf, test.pver, test.enc) + if err != nil { + t.Errorf("BtcDecode #%d error %v", i, err) + continue + } + if !reflect.DeepEqual(&msg, test.out) { + t.Errorf("BtcDecode #%d\n got: %s want: %s", i, + spew.Sdump(msg), spew.Sdump(test.out)) + continue + } + } +} diff --git a/wire/protocol.go b/wire/protocol.go index baeec05369..e1344f3aa7 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -1,4 +1,4 @@ -// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2013-2024 The btcsuite developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. @@ -52,12 +52,16 @@ const ( // feefilter message. FeeFilterVersion uint32 = 70013 - // AddrV2Version is the protocol version which added two new messages. - // sendaddrv2 is sent during the version-verack handshake and signals - // support for sending and receiving the addrv2 message. In the future, - // new messages that occur during the version-verack handshake will not - // come with a protocol version bump. - AddrV2Version uint32 = 70016 + // SendAddrV2Version is the protocol version which added two new + // messages. sendaddrv2 is sent during the version-verack handshake + // and signals support for sending and receiving the addrv2 message. In + // the future, new messages that occur during the version-verack + // handshake will not come with a protocol version bump. + // In addition, wtxidrelay was also added as an optional message in the + // same protocol version. + SendAddrV2Version uint32 = 70016 + WTxIdRelayVersion uint32 = SendAddrV2Version + AddrV2Version uint32 = SendAddrV2Version // Keep for upstream compatibility ) const ( From 10ef9cc0429394f09726749c8f262e1b739e095c Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Tue, 6 Aug 2024 14:51:08 +0900 Subject: [PATCH 1047/1056] main: add flag to write execution traces Execution traces are part of the go runtime tooling and is useful to check what is slowing down the ibd. For example, a slow ibd because of slow block downloads from peers won't show up on cpu profiling but will on a trace. --- btcd.go | 13 +++++++++++++ config.go | 1 + 2 files changed, 14 insertions(+) diff --git a/btcd.go b/btcd.go index c7f292cbc9..1d9a1e5f6b 100644 --- a/btcd.go +++ b/btcd.go @@ -14,6 +14,7 @@ import ( "runtime" "runtime/debug" "runtime/pprof" + "runtime/trace" "github.com/btcsuite/btcd/blockchain/indexers" "github.com/btcsuite/btcd/database" @@ -100,6 +101,18 @@ func btcdMain(serverChan chan<- *server) error { defer runtime.GC() } + // Write execution trace if requested. + if cfg.TraceProfile != "" { + f, err := os.Create(cfg.TraceProfile) + if err != nil { + btcdLog.Errorf("Unable to create execution trace: %v", err) + return err + } + trace.Start(f) + defer f.Close() + defer trace.Stop() + } + // Perform upgrades to btcd as new versions require it. if err := doUpgrades(); err != nil { btcdLog.Errorf("%v", err) diff --git a/config.go b/config.go index 9bbce7f69a..2d2e9c98a6 100644 --- a/config.go +++ b/config.go @@ -114,6 +114,7 @@ type config struct { ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"` CPUProfile string `long:"cpuprofile" description:"Write CPU profile to the specified file"` MemoryProfile string `long:"memprofile" description:"Write memory profile to the specified file"` + TraceProfile string `long:"traceprofile" description:"Write execution trace to the specified file"` DataDir string `short:"b" long:"datadir" description:"Directory to store data"` DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"` DebugLevel string `short:"d" long:"debuglevel" description:"Logging level for all subsystems {trace, debug, info, warn, error, critical} -- You may also specify =,=,... to set the log level for individual subsystems -- Use show to list available subsystems"` From 38af045ab12e1c2fc3bac9abfe224fe68fdb48e5 Mon Sep 17 00:00:00 2001 From: Boris Nagaev Date: Thu, 21 Nov 2024 12:47:26 -0300 Subject: [PATCH 1048/1056] wire: add bitcoin network magic for default SigNet Added constant wire.SigNet, added it to stringer for BitcoinNet type. Added a test in chaincfg to compare calculated magic value with the constant. --- chaincfg/params_test.go | 9 +++++++++ wire/doc.go | 1 + wire/protocol.go | 7 ++++++- wire/protocol_test.go | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/chaincfg/params_test.go b/chaincfg/params_test.go index 4166ce0a23..4d3f4d2273 100644 --- a/chaincfg/params_test.go +++ b/chaincfg/params_test.go @@ -9,6 +9,9 @@ import ( "encoding/hex" "math/big" "testing" + + "github.com/btcsuite/btcd/wire" + "github.com/stretchr/testify/require" ) // TestInvalidHashStr ensures the newShaHashFromStr function panics when used to @@ -104,6 +107,12 @@ func TestSigNetPowLimit(t *testing.T) { } } +// TestSigNetMagic makes sure that the default signet has the expected bitcoin +// network magic. +func TestSigNetMagic(t *testing.T) { + require.Equal(t, wire.SigNet, SigNetParams.Net) +} + // compactToBig is a copy of the blockchain.CompactToBig function. We copy it // here so we don't run into a circular dependency just because of a test. func compactToBig(compact uint32) *big.Int { diff --git a/wire/doc.go b/wire/doc.go index 5e03ff20a1..e05bb93552 100644 --- a/wire/doc.go +++ b/wire/doc.go @@ -86,6 +86,7 @@ the following constants: wire.MainNet wire.TestNet (Regression test network) wire.TestNet3 (Test network version 3) + wire.SigNet (Signet, default) wire.SimNet (Simulation test network) # Determining Message Type diff --git a/wire/protocol.go b/wire/protocol.go index e1344f3aa7..26d74bb66f 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -169,7 +169,7 @@ func (f ServiceFlag) String() string { // BitcoinNet represents which bitcoin network a message belongs to. type BitcoinNet uint32 -// Constants used to indicate the message bitcoin network. They can also be +// Constants used to indicate the message bitcoin network. They can also be // used to seek to the next message when a stream's state is unknown, but // this package does not provide that functionality since it's generally a // better idea to simply disconnect clients that are misbehaving over TCP. @@ -183,6 +183,10 @@ const ( // TestNet3 represents the test network (version 3). TestNet3 BitcoinNet = 0x0709110b + // SigNet represents the public default SigNet. For custom signets, + // see CustomSignetParams. + SigNet BitcoinNet = 0x40CF030A + // SimNet represents the simulation test network. SimNet BitcoinNet = 0x12141c16 ) @@ -193,6 +197,7 @@ var bnStrings = map[BitcoinNet]string{ MainNet: "MainNet", TestNet: "TestNet", TestNet3: "TestNet3", + SigNet: "SigNet", SimNet: "SimNet", } diff --git a/wire/protocol_test.go b/wire/protocol_test.go index eeeffb600a..5ab5b9dd56 100644 --- a/wire/protocol_test.go +++ b/wire/protocol_test.go @@ -49,6 +49,7 @@ func TestBitcoinNetStringer(t *testing.T) { {MainNet, "MainNet"}, {TestNet, "TestNet"}, {TestNet3, "TestNet3"}, + {SigNet, "SigNet"}, {SimNet, "SimNet"}, {0xffffffff, "Unknown BitcoinNet (4294967295)"}, } From 48c02954d2bc1f5bcba8bf374d2983497b551a5b Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 29 Nov 2024 15:00:11 +0900 Subject: [PATCH 1049/1056] wire, peer: fix broken ibd IBD for new nodes were broken due to the version handshake failing between nodes that recognized wtxid based relays. Reverting the changes that were made so that the node is able to connect to those nodes. --- peer/peer.go | 21 ++++++++++----------- wire/message.go | 11 ++++------- wire/msgsendaddrv2.go | 4 ++-- wire/msgsendaddrv2_test.go | 20 ++++++++++---------- wire/msgwtxidrelay.go | 4 ++-- wire/msgwtxidrelay_test.go | 20 ++++++++++---------- wire/protocol.go | 16 ++++++---------- 7 files changed, 44 insertions(+), 52 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index 5767cbbf66..195fc0b4fe 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -18,19 +18,18 @@ import ( "sync/atomic" "time" - "github.com/btcsuite/go-socks/socks" - "github.com/davecgh/go-spew/spew" - "github.com/decred/dcrd/lru" - "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/go-socks/socks" + "github.com/davecgh/go-spew/spew" + "github.com/decred/dcrd/lru" ) const ( // MaxProtocolVersion is the max protocol version the peer supports. - MaxProtocolVersion = wire.SendAddrV2Version + MaxProtocolVersion = wire.AddrV2Version // DefaultTrickleInterval is the min time between attempts to send an // inv message to a peer. @@ -878,8 +877,8 @@ func (p *Peer) PushAddrMsg(addresses []*wire.NetAddress) ([]*wire.NetAddress, er // // This function is safe for concurrent access. func (p *Peer) PushAddrV2Msg(addrs []*wire.NetAddressV2) ( - []*wire.NetAddressV2, error, -) { + []*wire.NetAddressV2, error) { + count := len(addrs) // Nothing to send. @@ -1901,8 +1900,8 @@ func (p *Peer) QueueMessage(msg wire.Message, doneChan chan<- struct{}) { // // This function is safe for concurrent access. func (p *Peer) QueueMessageWithEncoding(msg wire.Message, doneChan chan<- struct{}, - encoding wire.MessageEncoding, -) { + encoding wire.MessageEncoding) { + // Avoid risk of deadlock if goroutine already exited. The goroutine // we will be sending to hangs around until it knows for a fact that // it is marked as disconnected and *then* it drains the channels. @@ -2153,7 +2152,7 @@ func (p *Peer) writeLocalVersionMsg() error { // writeSendAddrV2Msg writes our sendaddrv2 message to the remote peer if the // peer supports protocol version 70016 and above. func (p *Peer) writeSendAddrV2Msg(pver uint32) error { - if pver < wire.SendAddrV2Version { + if pver < wire.AddrV2Version { return nil } @@ -2181,7 +2180,7 @@ func (p *Peer) waitToFinishNegotiation(pver uint32) error { switch m := remoteMsg.(type) { case *wire.MsgSendAddrV2: - if pver >= wire.SendAddrV2Version { + if pver >= wire.AddrV2Version { p.flagsMtx.Lock() p.sendAddrV2 = true p.flagsMtx.Unlock() diff --git a/wire/message.go b/wire/message.go index a90fb62733..95f7013ebb 100644 --- a/wire/message.go +++ b/wire/message.go @@ -112,9 +112,6 @@ func makeEmptyMessage(command string) (Message, error) { case CmdSendAddrV2: msg = &MsgSendAddrV2{} - case CmdWTxIdRelay: - msg = &MsgWTxIdRelay{} - case CmdGetAddr: msg = &MsgGetAddr{} @@ -280,8 +277,8 @@ func WriteMessage(w io.Writer, msg Message, pver uint32, btcnet BitcoinNet) erro // to specify the message encoding format to be used when serializing wire // messages. func WriteMessageWithEncodingN(w io.Writer, msg Message, pver uint32, - btcnet BitcoinNet, encoding MessageEncoding, -) (int, error) { + btcnet BitcoinNet, encoding MessageEncoding) (int, error) { + totalBytes := 0 // Enforce max command size. @@ -357,8 +354,8 @@ func WriteMessageWithEncodingN(w io.Writer, msg Message, pver uint32, // allows the caller to specify which message encoding is to to consult when // decoding wire messages. func ReadMessageWithEncodingN(r io.Reader, pver uint32, btcnet BitcoinNet, - enc MessageEncoding, -) (int, Message, []byte, error) { + enc MessageEncoding) (int, Message, []byte, error) { + totalBytes := 0 n, hdr, err := readMessageHeader(r) totalBytes += n diff --git a/wire/msgsendaddrv2.go b/wire/msgsendaddrv2.go index 8348b815ba..7be30d118d 100644 --- a/wire/msgsendaddrv2.go +++ b/wire/msgsendaddrv2.go @@ -15,7 +15,7 @@ type MsgSendAddrV2 struct{} // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgSendAddrV2) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - if pver < SendAddrV2Version { + if pver < AddrV2Version { str := fmt.Sprintf("sendaddrv2 message invalid for protocol "+ "version %d", pver) return messageError("MsgSendAddrV2.BtcDecode", str) @@ -27,7 +27,7 @@ func (msg *MsgSendAddrV2) BtcDecode(r io.Reader, pver uint32, enc MessageEncodin // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgSendAddrV2) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { - if pver < SendAddrV2Version { + if pver < AddrV2Version { str := fmt.Sprintf("sendaddrv2 message invalid for protocol "+ "version %d", pver) return messageError("MsgSendAddrV2.BtcEncode", str) diff --git a/wire/msgsendaddrv2_test.go b/wire/msgsendaddrv2_test.go index db6be1d21f..9161c08acc 100644 --- a/wire/msgsendaddrv2_test.go +++ b/wire/msgsendaddrv2_test.go @@ -45,7 +45,7 @@ func TestSendAddrV2(t *testing.T) { // Older protocol versions should fail encode since message didn't // exist yet. - oldPver := SendAddrV2Version - 1 + oldPver := AddrV2Version - 1 err = msg.BtcEncode(&buf, oldPver, enc) if err == nil { s := "encode of MsgSendAddrV2 passed for old protocol " + @@ -72,10 +72,10 @@ func TestSendAddrV2(t *testing.T) { } // TestSendAddrV2BIP0130 tests the MsgSendAddrV2 API against the protocol -// prior to version SendAddrV2Version. +// prior to version AddrV2Version. func TestSendAddrV2BIP0130(t *testing.T) { - // Use the protocol version just prior to SendAddrV2Version changes. - pver := SendAddrV2Version - 1 + // Use the protocol version just prior to AddrV2Version changes. + pver := AddrV2Version - 1 enc := BaseEncoding msg := NewMsgSendAddrV2() @@ -98,7 +98,7 @@ func TestSendAddrV2BIP0130(t *testing.T) { } // TestSendAddrV2CrossProtocol tests the MsgSendAddrV2 API when encoding with -// the latest protocol version and decoding with SendAddrV2Version. +// the latest protocol version and decoding with AddrV2Version. func TestSendAddrV2CrossProtocol(t *testing.T) { enc := BaseEncoding msg := NewMsgSendAddrV2() @@ -113,7 +113,7 @@ func TestSendAddrV2CrossProtocol(t *testing.T) { // Decode with old protocol version. readmsg := NewMsgSendAddrV2() - err = readmsg.BtcDecode(&buf, SendAddrV2Version, enc) + err = readmsg.BtcDecode(&buf, AddrV2Version, enc) if err != nil { t.Errorf("decode of MsgSendAddrV2 failed [%v] err <%v>", buf, err) @@ -142,21 +142,21 @@ func TestSendAddrV2Wire(t *testing.T) { BaseEncoding, }, - // Protocol version SendAddrV2Version+1 + // Protocol version AddrV2Version+1 { msgSendAddrV2, msgSendAddrV2, msgSendAddrV2Encoded, - SendAddrV2Version + 1, + AddrV2Version + 1, BaseEncoding, }, - // Protocol version SendAddrV2Version + // Protocol version AddrV2Version { msgSendAddrV2, msgSendAddrV2, msgSendAddrV2Encoded, - SendAddrV2Version, + AddrV2Version, BaseEncoding, }, } diff --git a/wire/msgwtxidrelay.go b/wire/msgwtxidrelay.go index 480c711dee..ab131bc5bd 100644 --- a/wire/msgwtxidrelay.go +++ b/wire/msgwtxidrelay.go @@ -19,7 +19,7 @@ type MsgWTxIdRelay struct{} // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. // This is part of the Message interface implementation. func (msg *MsgWTxIdRelay) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error { - if pver < WTxIdRelayVersion { + if pver < AddrV2Version { str := fmt.Sprintf("wtxidrelay message invalid for protocol "+ "version %d", pver) return messageError("MsgWTxIdRelay.BtcDecode", str) @@ -31,7 +31,7 @@ func (msg *MsgWTxIdRelay) BtcDecode(r io.Reader, pver uint32, enc MessageEncodin // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. // This is part of the Message interface implementation. func (msg *MsgWTxIdRelay) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error { - if pver < WTxIdRelayVersion { + if pver < AddrV2Version { str := fmt.Sprintf("wtxidrelay message invalid for protocol "+ "version %d", pver) return messageError("MsgWTxIdRelay.BtcEncode", str) diff --git a/wire/msgwtxidrelay_test.go b/wire/msgwtxidrelay_test.go index e7cde73a7b..7f519b4e93 100644 --- a/wire/msgwtxidrelay_test.go +++ b/wire/msgwtxidrelay_test.go @@ -45,7 +45,7 @@ func TestWTxIdRelay(t *testing.T) { // Older protocol versions should fail encode since message didn't // exist yet. - oldPver := WTxIdRelayVersion - 1 + oldPver := AddrV2Version - 1 err = msg.BtcEncode(&buf, oldPver, enc) if err == nil { s := "encode of MsgWTxIdRelay passed for old protocol " + @@ -72,10 +72,10 @@ func TestWTxIdRelay(t *testing.T) { } // TestWTxIdRelayBIP0130 tests the MsgWTxIdRelay API against the protocol -// prior to version WTxIdRelayVersion. +// prior to version AddrV2Version. func TestWTxIdRelayBIP0130(t *testing.T) { - // Use the protocol version just prior to WTxIdRelayVersion changes. - pver := WTxIdRelayVersion - 1 + // Use the protocol version just prior to AddrV2Version changes. + pver := AddrV2Version - 1 enc := BaseEncoding msg := NewMsgWTxIdRelay() @@ -98,7 +98,7 @@ func TestWTxIdRelayBIP0130(t *testing.T) { } // TestWTxIdRelayCrossProtocol tests the MsgWTxIdRelay API when encoding with -// the latest protocol version and decoding with WTxIdRelayVersion. +// the latest protocol version and decoding with AddrV2Version. func TestWTxIdRelayCrossProtocol(t *testing.T) { enc := BaseEncoding msg := NewMsgWTxIdRelay() @@ -113,7 +113,7 @@ func TestWTxIdRelayCrossProtocol(t *testing.T) { // Decode with old protocol version. readmsg := NewMsgWTxIdRelay() - err = readmsg.BtcDecode(&buf, WTxIdRelayVersion, enc) + err = readmsg.BtcDecode(&buf, AddrV2Version, enc) if err != nil { t.Errorf("decode of MsgWTxIdRelay failed [%v] err <%v>", buf, err) @@ -142,21 +142,21 @@ func TestWTxIdRelayWire(t *testing.T) { BaseEncoding, }, - // Protocol version WTxIdRelayVersion+1 + // Protocol version AddrV2Version+1 { msgWTxIdRelay, msgWTxIdRelay, msgWTxIdRelayEncoded, - WTxIdRelayVersion + 1, + AddrV2Version + 1, BaseEncoding, }, - // Protocol version WTxIdRelayVersion + // Protocol version AddrV2Version { msgWTxIdRelay, msgWTxIdRelay, msgWTxIdRelayEncoded, - WTxIdRelayVersion, + AddrV2Version, BaseEncoding, }, } diff --git a/wire/protocol.go b/wire/protocol.go index e1344f3aa7..4ed0922b3d 100644 --- a/wire/protocol.go +++ b/wire/protocol.go @@ -52,16 +52,12 @@ const ( // feefilter message. FeeFilterVersion uint32 = 70013 - // SendAddrV2Version is the protocol version which added two new - // messages. sendaddrv2 is sent during the version-verack handshake - // and signals support for sending and receiving the addrv2 message. In - // the future, new messages that occur during the version-verack - // handshake will not come with a protocol version bump. - // In addition, wtxidrelay was also added as an optional message in the - // same protocol version. - SendAddrV2Version uint32 = 70016 - WTxIdRelayVersion uint32 = SendAddrV2Version - AddrV2Version uint32 = SendAddrV2Version // Keep for upstream compatibility + // AddrV2Version is the protocol version which added two new messages. + // sendaddrv2 is sent during the version-verack handshake and signals + // support for sending and receiving the addrv2 message. In the future, + // new messages that occur during the version-verack handshake will not + // come with a protocol version bump. + AddrV2Version uint32 = 70016 ) const ( From 814a1fc1981dcfc8eac0d981065934aba95366a3 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Tue, 26 Nov 2024 22:15:35 +0800 Subject: [PATCH 1050/1056] rpctest: make sure to `WaitForShutdown` --- integration/rpctest/rpc_harness.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/integration/rpctest/rpc_harness.go b/integration/rpctest/rpc_harness.go index 0b85232868..0e8c53dbe9 100644 --- a/integration/rpctest/rpc_harness.go +++ b/integration/rpctest/rpc_harness.go @@ -303,10 +303,12 @@ func (h *Harness) SetUp(createTestChain bool, numMatureOutputs uint32) error { func (h *Harness) tearDown() error { if h.Client != nil { h.Client.Shutdown() + h.Client.WaitForShutdown() } if h.BatchClient != nil { h.BatchClient.Shutdown() + h.BatchClient.WaitForShutdown() } if err := h.node.shutdown(); err != nil { @@ -570,10 +572,10 @@ func NextAvailablePortForProcess(pid int) int { os.TempDir(), fmt.Sprintf("rpctest-port-pid-%d.lock", pid), ) timeout := time.After(time.Second) - + var ( lockFileHandle *os.File - err error + err error ) for { // Attempt to acquire the lock file. If it already exists, wait From 42d6eba84bf9dc23b1182a35570bcd8f7f25616f Mon Sep 17 00:00:00 2001 From: Sam Eiderman Date: Sun, 27 Oct 2024 14:19:17 +0200 Subject: [PATCH 1051/1056] Fix non-root hosts failing on resolving DNS A fix for a bug introduced by #2168 Previously, config.Host worked in the following way: 1. Documented as supporting ip addresses only 2. In fact supported "host/path" syntax 3. Did not support "scheme" prefixes, i.e. https:// Not sure this is the desired approach, probably the best thing would have been to extend config to contain "Scheme" and "Path" fields as well. However, this was the way it worked. 1. Now Host can contain scheme prefixes "unix://..." 2. Host can no longer contain ".../path" This PR solves this behavior while maintaining support of the "unix://" flow as well. For some reason, "scheme" is named "network" in #2168 - I did not change that. Also remove disambiguation in "network:address:port", where it parsed "myhost:8888" as network:address instead address:port. --- rpcclient/infrastructure.go | 127 +++++++++++++++++-------------- rpcclient/infrastructure_test.go | 110 ++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 58 deletions(-) create mode 100644 rpcclient/infrastructure_test.go diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index 4fe1d894df..ca039023f1 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -759,18 +759,13 @@ out: // result, unmarshalling it, and delivering the unmarshalled result to the // provided response channel. func (c *Client) handleSendPostMessage(jReq *jsonRequest) { - protocol := "http" - if !c.config.DisableTLS { - protocol = "https" - } - var ( - err, lastErr error + lastErr error backoff time.Duration httpResponse *http.Response ) - parsedAddr, err := ParseAddressString(c.config.Host) + httpURL, err := c.config.httpURL() if err != nil { jReq.responseChan <- &Response{ err: fmt.Errorf("failed to parse address %v", err), @@ -778,22 +773,12 @@ func (c *Client) handleSendPostMessage(jReq *jsonRequest) { return } - var url string - switch parsedAddr.Network() { - case "unix", "unixpacket": - // Using a placeholder URL because a non-empty URL is required. - // The Unix domain socket is specified in the DialContext. - url = protocol + "://unix" - default: - url = protocol + "://" + c.config.Host - } - tries := 10 for i := 0; i < tries; i++ { var httpReq *http.Request bodyReader := bytes.NewReader(jReq.marshalledJSON) - httpReq, err = http.NewRequest("POST", url, bodyReader) + httpReq, err = http.NewRequest("POST", httpURL, bodyReader) if err != nil { jReq.responseChan <- &Response{result: nil, err: err} return @@ -1355,7 +1340,7 @@ func newHTTPClient(config *ConnConfig) (*http.Client, error) { } } - parsedAddr, err := ParseAddressString(config.Host) + parsedDialAddr, err := ParseAddressString(config.Host) if err != nil { return nil, err } @@ -1363,8 +1348,13 @@ func newHTTPClient(config *ConnConfig) (*http.Client, error) { Transport: &http.Transport{ Proxy: proxyFunc, TLSClientConfig: tlsConfig, - DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { - return net.Dial(parsedAddr.Network(), parsedAddr.String()) + DialContext: func(_ context.Context, _, + _ string) (net.Conn, error) { + + return net.Dial( + parsedDialAddr.Network(), + parsedDialAddr.String(), + ) }, }, Timeout: defaultHTTPTimeout, @@ -1373,6 +1363,32 @@ func newHTTPClient(config *ConnConfig) (*http.Client, error) { return &client, nil } +// httpURL returns the URL to use for HTTP POST requests. +func (config *ConnConfig) httpURL() (string, error) { + protocol := "http" + if !config.DisableTLS { + protocol = "https" + } + + parsedAddr, err := ParseAddressString(config.Host) + if err != nil { + return "", fmt.Errorf("error parsing host '%v': %v", + config.Host, err) + } + + var httpURL string + switch parsedAddr.Network() { + case "unix", "unixpacket": + // Using a placeholder URL because a non-empty URL is required. + // The Unix domain socket is specified in the DialContext. + httpURL = protocol + "://unix" + default: + httpURL = protocol + "://" + config.Host + } + + return httpURL, nil +} + // dial opens a websocket connection using the passed connection configuration // details. func dial(config *ConnConfig) (*websocket.Conn, error) { @@ -1733,53 +1749,48 @@ func (c *Client) Send() error { return nil } +// cutPrefix returns s without the provided leading prefix string +// and reports whether it found the prefix. +// If s doesn't start with prefix, cutPrefix returns s, false. +// If prefix is the empty string, cutPrefix returns s, true. +// Copied from go1.20 version. +func cutPrefix(s, prefix string) (after string, found bool) { + if !strings.HasPrefix(s, prefix) { + return s, false + } + return s[len(prefix):], true +} + // ParseAddressString converts an address in string format to a net.Addr that is // compatible with btcd. UDP is not supported because btcd needs reliable -// connections. We accept a custom function to resolve any TCP addresses so -// that caller is able control exactly how resolution is performed. +// connections. func ParseAddressString(strAddress string) (net.Addr, error) { - var parsedNetwork, parsedAddr string + // Addresses can either be in unix://address, unixpacket://address URL + // format, or just address:port host format for tcp. + if after, ok := cutPrefix(strAddress, "unix://"); ok { + return net.ResolveUnixAddr("unix", after) + } + if after, ok := cutPrefix(strAddress, "unixpacket://"); ok { + return net.ResolveUnixAddr("unixpacket", after) + } - // Addresses can either be in network://address:port format, - // network:address:port, address:port, or just port. We want to support - // all possible types. if strings.Contains(strAddress, "://") { - parts := strings.Split(strAddress, "://") - parsedNetwork, parsedAddr = parts[0], parts[1] - } else if strings.Contains(strAddress, ":") { - parts := strings.Split(strAddress, ":") - parsedNetwork = parts[0] - parsedAddr = strings.Join(parts[1:], ":") - } else { - parsedAddr = strAddress + // Not supporting :// anywhere in the host or path. + return nil, fmt.Errorf("unsupported protocol in address: %s", + strAddress) } - // Only TCP and Unix socket addresses are valid. We can't use IP or - // UDP only connections for anything we do in lnd. - switch parsedNetwork { - case "unix", "unixpacket": - return net.ResolveUnixAddr(parsedNetwork, parsedAddr) - - case "tcp", "tcp4", "tcp6": - return net.ResolveTCPAddr(parsedNetwork, verifyPort(parsedAddr)) - - case "ip", "ip4", "ip6", "udp", "udp4", "udp6", "unixgram": - return nil, fmt.Errorf("only TCP or unix socket "+ - "addresses are supported: %s", parsedAddr) - - default: - // We'll now possibly use the local host short circuit - // or parse out an all interfaces listen. - addrWithPort := verifyPort(strAddress) - - // Otherwise, we'll attempt to resolve the host. - return net.ResolveTCPAddr("tcp", addrWithPort) + // Parse it as a dummy URL to get the host and port. + u, err := url.Parse("dummy://" + strAddress) + if err != nil { + return nil, err } + return net.ResolveTCPAddr("tcp", verifyPort(u.Host)) } // verifyPort makes sure that an address string has both a host and a port. // If the address is just a port, then we'll assume that the user is using the -// short cut to specify a localhost:port address. +// shortcut to specify a localhost:port address. func verifyPort(address string) string { host, port, err := net.SplitHostPort(address) if err != nil { @@ -1801,8 +1812,8 @@ func verifyPort(address string) string { return net.JoinHostPort(address, "") } - // In the case that both the host and port are empty, we'll use the - // an empty port. + // In the case that both the host and port are empty, we'll use an empty + // port. if host == "" && port == "" { return ":" } diff --git a/rpcclient/infrastructure_test.go b/rpcclient/infrastructure_test.go new file mode 100644 index 0000000000..8416b7ad3c --- /dev/null +++ b/rpcclient/infrastructure_test.go @@ -0,0 +1,110 @@ +package rpcclient + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// TestParseAddressString checks different variation of supported and +// unsupported addresses. +func TestParseAddressString(t *testing.T) { + t.Parallel() + + // Using localhost only to avoid network calls. + testCases := []struct { + name string + addressString string + expNetwork string + expAddress string + expErrStr string + }{ + { + name: "localhost", + addressString: "localhost", + expNetwork: "tcp", + expAddress: "127.0.0.1:0", + }, + { + name: "localhost ip", + addressString: "127.0.0.1", + expNetwork: "tcp", + expAddress: "127.0.0.1:0", + }, + { + name: "localhost ipv6", + addressString: "::1", + expNetwork: "tcp", + expAddress: "[::1]:0", + }, + { + name: "localhost and port", + addressString: "localhost:80", + expNetwork: "tcp", + expAddress: "127.0.0.1:80", + }, + { + name: "localhost ipv6 and port", + addressString: "[::1]:80", + expNetwork: "tcp", + expAddress: "[::1]:80", + }, + { + name: "colon and port", + addressString: ":80", + expNetwork: "tcp", + expAddress: ":80", + }, + { + name: "colon only", + addressString: ":", + expNetwork: "tcp", + expAddress: ":0", + }, + { + name: "localhost and path", + addressString: "localhost/path", + expNetwork: "tcp", + expAddress: "127.0.0.1:0", + }, + { + name: "localhost port and path", + addressString: "localhost:80/path", + expNetwork: "tcp", + expAddress: "127.0.0.1:80", + }, + { + name: "unix prefix", + addressString: "unix://the/rest/of/the/path", + expNetwork: "unix", + expAddress: "the/rest/of/the/path", + }, + { + name: "unix prefix", + addressString: "unixpacket://the/rest/of/the/path", + expNetwork: "unixpacket", + expAddress: "the/rest/of/the/path", + }, + { + name: "error http prefix", + addressString: "http://localhost:1010", + expErrStr: "unsupported protocol in address", + }, + } + + for _, tc := range testCases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + addr, err := ParseAddressString(tc.addressString) + if tc.expErrStr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErrStr) + return + } + require.NoError(t, err) + require.Equal(t, tc.expNetwork, addr.Network()) + require.Equal(t, tc.expAddress, addr.String()) + }) + } +} From db5318b356b939e46e0556a2fd5e454fc793e051 Mon Sep 17 00:00:00 2001 From: Yevhen Date: Thu, 28 Nov 2024 12:13:23 +0200 Subject: [PATCH 1052/1056] rpcclient: safe read and write to batch --- rpcclient/infrastructure.go | 40 +++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/rpcclient/infrastructure.go b/rpcclient/infrastructure.go index ca039023f1..9a9c2bb878 100644 --- a/rpcclient/infrastructure.go +++ b/rpcclient/infrastructure.go @@ -74,6 +74,9 @@ var ( // client having already connected to the RPC server. ErrClientAlreadyConnected = errors.New("websocket client has already " + "connected") + + // ErrEmptyBatch is an error to describe that there is nothing to send. + ErrEmptyBatch = errors.New("batch is empty") ) const ( @@ -151,6 +154,7 @@ type Client struct { // whether or not to batch requests, false unless changed by Batch() batch bool + batchLock sync.Mutex batchList *list.List // retryCount holds the number of times the client has tried to @@ -214,7 +218,10 @@ func (c *Client) addRequest(jReq *jsonRequest) error { element := c.requestList.PushBack(jReq) c.requestMap[jReq.id] = element } else { + c.batchLock.Lock() element := c.batchList.PushBack(jReq) + c.batchLock.Unlock() + c.requestMap[jReq.id] = element } return nil @@ -238,7 +245,9 @@ func (c *Client) removeRequest(id uint64) *jsonRequest { var request *jsonRequest if c.batch { + c.batchLock.Lock() request = c.batchList.Remove(element).(*jsonRequest) + c.batchLock.Unlock() } else { request = c.requestList.Remove(element).(*jsonRequest) } @@ -1672,7 +1681,15 @@ func (c *Client) BackendVersion() (BackendVersion, error) { return c.backendVersion, nil } -func (c *Client) sendAsync() FutureGetBulkResult { +func (c *Client) sendAsync() (FutureGetBulkResult, error) { + c.batchLock.Lock() + defer c.batchLock.Unlock() + + // If batchList is empty, there's nothing to send. + if c.batchList.Len() == 0 { + return nil, ErrEmptyBatch + } + // convert the array of marshalled json requests to a single request we can send responseChan := make(chan *Response, 1) marshalledRequest := []byte("[") @@ -1694,25 +1711,24 @@ func (c *Client) sendAsync() FutureGetBulkResult { responseChan: responseChan, } c.sendPostRequest(&request) - return responseChan + return responseChan, nil } // Marshall's bulk requests and sends to the server // creates a response channel to receive the response func (c *Client) Send() error { - // if batchlist is empty, there's nothing to send - if c.batchList.Len() == 0 { - return nil + future, err := c.sendAsync() + if err != nil { + return err } - batchResp, err := c.sendAsync().Receive() + batchResp, err := future.Receive() if err != nil { // Clear batchlist in case of an error. - // - // TODO(yy): need to double check to make sure there's no - // concurrent access to this batch list, otherwise we may miss - // some batched requests. + + c.batchLock.Lock() c.batchList = list.New() + c.batchLock.Unlock() return err } @@ -1722,6 +1738,10 @@ func (c *Client) Send() error { // Perform a GC on batchList and requestMap before moving // forward. request := c.removeRequest(id) + if request == nil { + // Perhaps another goroutine has already processed this request. + continue + } // If there's an error, we log it and continue to the next // request. From bdb0b3d8215d69406e10625d45a9acf5af94925e Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 26 Dec 2024 11:13:32 +0100 Subject: [PATCH 1053/1056] psbt: cleanup code --- btcutil/psbt/bip32.go | 27 +++++++++++++++++---------- btcutil/psbt/types.go | 16 ++++++++-------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/btcutil/psbt/bip32.go b/btcutil/psbt/bip32.go index 96a3f67274..ef1ffac310 100644 --- a/btcutil/psbt/bip32.go +++ b/btcutil/psbt/bip32.go @@ -5,6 +5,11 @@ import ( "encoding/binary" ) +const ( + // uint32Size is the size of a uint32 in bytes. + uint32Size = 4 +) + // Bip32Derivation encapsulates the data for the input and output // Bip32Derivation key-value fields. // @@ -38,21 +43,23 @@ func (s Bip32Sorter) Less(i, j int) bool { // ReadBip32Derivation deserializes a byte slice containing chunks of 4 byte // little endian encodings of uint32 values, the first of which is the -// masterkeyfingerprint and the remainder of which are the derivation path. +// MasterKeyFingerprint and the remainder of which are the derivation path. func ReadBip32Derivation(path []byte) (uint32, []uint32, error) { // BIP-0174 defines the derivation path being encoded as // "<32-bit uint> <32-bit uint>*" // with the asterisk meaning 0 to n times. Which in turn means that an // empty path is valid, only the key fingerprint is mandatory. - if len(path)%4 != 0 { + if len(path)%uint32Size != 0 { return 0, nil, ErrInvalidPsbtFormat } - masterKeyInt := binary.LittleEndian.Uint32(path[:4]) + masterKeyInt := binary.LittleEndian.Uint32(path[:uint32Size]) var paths []uint32 - for i := 4; i < len(path); i += 4 { - paths = append(paths, binary.LittleEndian.Uint32(path[i:i+4])) + for i := uint32Size; i < len(path); i += uint32Size { + paths = append(paths, binary.LittleEndian.Uint32( + path[i:i+uint32Size], + )) } return masterKeyInt, paths, nil @@ -65,15 +72,15 @@ func ReadBip32Derivation(path []byte) (uint32, []uint32, error) { func SerializeBIP32Derivation(masterKeyFingerprint uint32, bip32Path []uint32) []byte { - var masterKeyBytes [4]byte + var masterKeyBytes [uint32Size]byte binary.LittleEndian.PutUint32(masterKeyBytes[:], masterKeyFingerprint) - derivationPath := make([]byte, 0, 4+4*len(bip32Path)) + derivationPath := make([]byte, 0, uint32Size+uint32Size*len(bip32Path)) derivationPath = append(derivationPath, masterKeyBytes[:]...) for _, path := range bip32Path { - var pathbytes [4]byte - binary.LittleEndian.PutUint32(pathbytes[:], path) - derivationPath = append(derivationPath, pathbytes[:]...) + var pathBytes [uint32Size]byte + binary.LittleEndian.PutUint32(pathBytes[:], path) + derivationPath = append(derivationPath, pathBytes[:]...) } return derivationPath diff --git a/btcutil/psbt/types.go b/btcutil/psbt/types.go index e833e1af35..ca555101b9 100644 --- a/btcutil/psbt/types.go +++ b/btcutil/psbt/types.go @@ -13,22 +13,22 @@ const ( // invalid. UnsignedTxType GlobalType = 0 - // XpubType houses a global xpub for the entire PSBT packet. + // XPubType houses a global xPub for the entire PSBT packet. // - // The key ({0x01}|{xpub}) is he 78 byte serialized extended public key - // as defined by BIP 32. Extended public keys are those that can be + // The key ({0x01}|{xpub}) is the 78 byte serialized extended public key + // as defined by BIP-0032. Extended public keys are those that can be // used to derive public keys used in the inputs and outputs of this // transaction. It should be the public key at the highest hardened - // derivation index so that - // the unhardened child keys used in the transaction can be derived. + // derivation index so that the unhardened child keys used in the + // transaction can be derived. // - // The value is the master key fingerprint as defined by BIP 32 + // The value is the master key fingerprint as defined by BIP-0032 // concatenated with the derivation path of the public key. The // derivation path is represented as 32-bit little endian unsigned - // integer indexes concatenated with each other. The number of 32 bit + // integer indexes concatenated with each other. The number of 32-bit // unsigned integer indexes must match the depth provided in the // extended public key. - XpubType GlobalType = 1 + XPubType GlobalType = 1 // VersionType houses the global version number of this PSBT. There is // no key (only contains the byte type), then the value if omitted, is From c2b47e014983654c1326f8ae2525ba49bc9e0182 Mon Sep 17 00:00:00 2001 From: Calvin Kim Date: Fri, 3 Jan 2025 00:20:37 +0900 Subject: [PATCH 1054/1056] main: add prune documentation to sample-btcd.conf (#2299) --- sample-btcd.conf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sample-btcd.conf b/sample-btcd.conf index 74b20e1660..0fb688fbfc 100644 --- a/sample-btcd.conf +++ b/sample-btcd.conf @@ -13,6 +13,12 @@ ; $VARIABLE here. Also, ~ is expanded to $LOCALAPPDATA on Windows. ; datadir=~/.btcd/data +; The prune option removes old blocks from disk after they're downloaded and +; verified. The smallest value is 1536 which will limit the block data to 1536 +; mebibytes. +; NOTE: This limit does not apply to indexes and the UTXO set which are both +; larger than 1536 mebibytes as of December 2024. +; prune=1536 ; ------------------------------------------------------------------------------ ; Network settings From 821114285b263a6833900c6dbd9faa2188e9a989 Mon Sep 17 00:00:00 2001 From: Romashka Date: Thu, 9 Jan 2025 15:32:50 +0200 Subject: [PATCH 1055/1056] typo-Update register_test.go (#2291) --- btcjson/register_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/btcjson/register_test.go b/btcjson/register_test.go index 2d3ab10f3e..18e2ea0040 100644 --- a/btcjson/register_test.go +++ b/btcjson/register_test.go @@ -231,7 +231,7 @@ func TestMustRegisterCmdPanic(t *testing.T) { t.Parallel() // Setup a defer to catch the expected panic to ensure it actually - // paniced. + // panicked. defer func() { if err := recover(); err == nil { t.Error("MustRegisterCmd did not panic as expected") From bda0481701fd348a591e8c6db477517c531b9da1 Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Thu, 26 Dec 2024 11:14:21 +0100 Subject: [PATCH 1056/1056] psbt: add global XPubs to packet Adds support for the PSBT_GLOBAL_XPUB type as defined in BIP-0174. --- btcutil/psbt/bip32.go | 69 +++++++++++++++++++++++++++++++++++++++ btcutil/psbt/psbt.go | 60 +++++++++++++++++++++++++++++----- btcutil/psbt/psbt_test.go | 32 ++++++++++++++++-- 3 files changed, 151 insertions(+), 10 deletions(-) diff --git a/btcutil/psbt/bip32.go b/btcutil/psbt/bip32.go index ef1ffac310..09c5fdff57 100644 --- a/btcutil/psbt/bip32.go +++ b/btcutil/psbt/bip32.go @@ -3,6 +3,10 @@ package psbt import ( "bytes" "encoding/binary" + + "github.com/btcsuite/btcd/btcutil/base58" + "github.com/btcsuite/btcd/btcutil/hdkeychain" + "github.com/btcsuite/btcd/chaincfg/chainhash" ) const ( @@ -85,3 +89,68 @@ func SerializeBIP32Derivation(masterKeyFingerprint uint32, return derivationPath } + +// XPub is a struct that encapsulates an extended public key, as defined in +// BIP-0032. +type XPub struct { + // ExtendedKey is the serialized extended public key as defined in + // BIP-0032. + ExtendedKey []byte + + // MasterFingerprint is the fingerprint of the master pubkey. + MasterKeyFingerprint uint32 + + // Bip32Path is the derivation path of the key, with hardened elements + // having the 0x80000000 offset added, as defined in BIP-0032. The + // number of path elements must match the depth provided in the extended + // public key. + Bip32Path []uint32 +} + +// ReadXPub deserializes a byte slice containing an extended public key and a +// BIP-0032 derivation path. +func ReadXPub(keyData []byte, path []byte) (*XPub, error) { + xPub, err := DecodeExtendedKey(keyData) + if err != nil { + return nil, ErrInvalidPsbtFormat + } + numPathElements := xPub.Depth() + + // The path also contains the master key fingerprint, + expectedSize := int(uint32Size * (numPathElements + 1)) + if len(path) != expectedSize { + return nil, ErrInvalidPsbtFormat + } + + masterKeyFingerprint, bip32Path, err := ReadBip32Derivation(path) + if err != nil { + return nil, err + } + + return &XPub{ + ExtendedKey: keyData, + MasterKeyFingerprint: masterKeyFingerprint, + Bip32Path: bip32Path, + }, nil +} + +// EncodeExtendedKey serializes an extended key to a byte slice, without the +// checksum. +func EncodeExtendedKey(key *hdkeychain.ExtendedKey) []byte { + serializedKey := key.String() + decodedKey := base58.Decode(serializedKey) + return decodedKey[:len(decodedKey)-uint32Size] +} + +// DecodeExtendedKey deserializes an extended key from a byte slice that does +// not contain the checksum. +func DecodeExtendedKey(encodedKey []byte) (*hdkeychain.ExtendedKey, error) { + checkSum := chainhash.DoubleHashB(encodedKey)[:uint32Size] + serializedBytes := append(encodedKey, checkSum...) + xPub, err := hdkeychain.NewKeyFromString(base58.Encode(serializedBytes)) + if err != nil { + return nil, err + } + + return xPub, nil +} diff --git a/btcutil/psbt/psbt.go b/btcutil/psbt/psbt.go index a72b7fc551..5249aad4e1 100644 --- a/btcutil/psbt/psbt.go +++ b/btcutil/psbt/psbt.go @@ -135,6 +135,13 @@ type Packet struct { // produced by this PSBT. Outputs []POutput + // XPubs is a list of extended public keys that can be used to derive + // public keys used in the inputs and outputs of this transaction. It + // should be the public key at the highest hardened derivation index so + // that the unhardened child keys used in the transaction can be + // derived. + XPubs []XPub + // Unknowns are the set of custom types (global only) within this PSBT. Unknowns []*Unknown } @@ -161,12 +168,14 @@ func NewFromUnsignedTx(tx *wire.MsgTx) (*Packet, error) { inSlice := make([]PInput, len(tx.TxIn)) outSlice := make([]POutput, len(tx.TxOut)) + xPubSlice := make([]XPub, 0) unknownSlice := make([]*Unknown, 0) return &Packet{ UnsignedTx: tx, Inputs: inSlice, Outputs: outSlice, + XPubs: xPubSlice, Unknowns: unknownSlice, }, nil } @@ -230,7 +239,10 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { // Next we parse any unknowns that may be present, making sure that we // break at the separator. - var unknownSlice []*Unknown + var ( + xPubSlice []XPub + unknownSlice []*Unknown + ) for { keyint, keydata, err := getKey(r) if err != nil { @@ -247,14 +259,32 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { return nil, err } - keyintanddata := []byte{byte(keyint)} - keyintanddata = append(keyintanddata, keydata...) - - newUnknown := &Unknown{ - Key: keyintanddata, - Value: value, + switch GlobalType(keyint) { + case XPubType: + xPub, err := ReadXPub(keydata, value) + if err != nil { + return nil, err + } + + // Duplicate keys are not allowed + for _, x := range xPubSlice { + if bytes.Equal(x.ExtendedKey, keyData) { + return nil, ErrDuplicateKey + } + } + + xPubSlice = append(xPubSlice, *xPub) + + default: + keyintanddata := []byte{byte(keyint)} + keyintanddata = append(keyintanddata, keydata...) + + newUnknown := &Unknown{ + Key: keyintanddata, + Value: value, + } + unknownSlice = append(unknownSlice, newUnknown) } - unknownSlice = append(unknownSlice, newUnknown) } // Next we parse the INPUT section. @@ -286,6 +316,7 @@ func NewFromRawBytes(r io.Reader, b64 bool) (*Packet, error) { UnsignedTx: msgTx, Inputs: inSlice, Outputs: outSlice, + XPubs: xPubSlice, Unknowns: unknownSlice, } @@ -325,6 +356,19 @@ func (p *Packet) Serialize(w io.Writer) error { return err } + // Serialize the global xPubs. + for _, xPub := range p.XPubs { + pathBytes := SerializeBIP32Derivation( + xPub.MasterKeyFingerprint, xPub.Bip32Path, + ) + err := serializeKVPairWithType( + w, uint8(XPubType), xPub.ExtendedKey, pathBytes, + ) + if err != nil { + return err + } + } + // Unknown is a special case; we don't have a key type, only a key and // a value field for _, kv := range p.Unknowns { diff --git a/btcutil/psbt/psbt_test.go b/btcutil/psbt/psbt_test.go index a39f52923a..c8d93f3e90 100644 --- a/btcutil/psbt/psbt_test.go +++ b/btcutil/psbt/psbt_test.go @@ -57,20 +57,42 @@ func createPsbtFromSignedTx(serializedSignedTx []byte) ( return unsignedPsbt, scriptSigs, witnesses, nil } -// These are all valid PSBTs encoded as hex. +// These are all valid PSBTs encoded as hex. The items with a comment are taken +// from the BIP174 test vectors: +// https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#test-vectors var validPsbtHex = map[int]string{ + // Case: PSBT with one P2PKH input. Outputs are empty. 0: "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000", + // Case: PSBT with one P2PKH input and one P2SH-P2WPKH input. First + // input is signed and finalized. Outputs are empty. 1: "70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000", + // Case: PSBT with one P2PKH input which has a non-final scriptSig and + // has a sighash type specified. Outputs are empty. 2: "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001030401000000000000", + // Case: PSBT with one P2PKH input and one P2SH-P2WPKH input both with + // non-final scriptSigs. P2SH-P2WPKH input's redeemScript is available. + // Outputs filled. 3: "70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000", + // Case: PSBT with one P2SH-P2WSH input of a 2-of-2 multisig, + // redeemScript, witnessScript, and keypaths are available. Contains one + // signature. 4: "70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000", 5: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000", 6: "70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000002206030d097466b7f59162ac4d90bf65f2a31a8bad82fcd22e98138dcf279401939bd104ffffffff0a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000", 7: "70736274ff01002001000000000100000000000000000d6a0b68656c6c6f20776f726c64000000000000", + // Case: PSBT with one P2WSH input of a 2-of-2 multisig. witnessScript, + // keypaths, and global xpubs are available. Contains no signatures. + // Outputs filled. + 8: "70736274ff01005202000000019dfc6628c26c5899fe1bd3dc338665bfd55d7ada10f6220973df2d386dec12760100000000ffffffff01f03dcd1d000000001600147b3a00bfdc14d27795c2b74901d09da6ef133579000000004f01043587cf02da3fd0088000000097048b1ad0445b1ec8275517727c87b4e4ebc18a203ffa0f94c01566bd38e9000351b743887ee1d40dc32a6043724f2d6459b3b5a4d73daec8fbae0472f3bc43e20cd90c6a4fae000080000000804f01043587cf02da3fd00880000001b90452427139cd78c2cff2444be353cd58605e3e513285e528b407fae3f6173503d30a5e97c8adbc557dac2ad9a7e39c1722ebac69e668b6f2667cc1d671c83cab0cd90c6a4fae000080010000800001012b0065cd1d000000002200202c5486126c4978079a814e13715d65f36459e4d6ccaded266d0508645bafa6320105475221029da12cdb5b235692b91536afefe5c91c3ab9473d8e43b533836ab456299c88712103372b34234ed7cf9c1fea5d05d441557927be9542b162eb02e1ab2ce80224c00b52ae2206029da12cdb5b235692b91536afefe5c91c3ab9473d8e43b533836ab456299c887110d90c6a4fae0000800000008000000000220603372b34234ed7cf9c1fea5d05d441557927be9542b162eb02e1ab2ce80224c00b10d90c6a4fae0000800100008000000000002202039eff1f547a1d5f92dfa2ba7af6ac971a4bd03ba4a734b03156a256b8ad3a1ef910ede45cc500000080000000800100008000", + // Case: PSBT with `PSBT_GLOBAL_XPUB`. + 9: "70736274ff01009d0100000002710ea76ab45c5cb6438e607e59cc037626981805ae9e0dfd9089012abb0be5350100000000ffffffff190994d6a8b3c8c82ccbcfb2fba4106aa06639b872a8d447465c0d42588d6d670000000000ffffffff0200e1f505000000001976a914b6bc2c0ee5655a843d79afedd0ccc3f7dd64340988ac605af405000000001600141188ef8e4ce0449eaac8fb141cbf5a1176e6a088000000004f010488b21e039e530cac800000003dbc8a5c9769f031b17e77fea1518603221a18fd18f2b9a54c6c8c1ac75cbc3502f230584b155d1c7f1cd45120a653c48d650b431b67c5b2c13f27d7142037c1691027569c503100008000000080000000800001011f00e1f5050000000016001433b982f91b28f160c920b4ab95e58ce50dda3a4a220203309680f33c7de38ea6a47cd4ecd66f1f5a49747c6ffb8808ed09039243e3ad5c47304402202d704ced830c56a909344bd742b6852dccd103e963bae92d38e75254d2bb424502202d86c437195df46c0ceda084f2a291c3da2d64070f76bf9b90b195e7ef28f77201220603309680f33c7de38ea6a47cd4ecd66f1f5a49747c6ffb8808ed09039243e3ad5c1827569c5031000080000000800000008000000000010000000001011f00e1f50500000000160014388fb944307eb77ef45197d0b0b245e079f011de220202c777161f73d0b7c72b9ee7bde650293d13f095bc7656ad1f525da5fd2e10b11047304402204cb1fb5f869c942e0e26100576125439179ae88dca8a9dc3ba08f7953988faa60220521f49ca791c27d70e273c9b14616985909361e25be274ea200d7e08827e514d01220602c777161f73d0b7c72b9ee7bde650293d13f095bc7656ad1f525da5fd2e10b1101827569c5031000080000000800000008000000000000000000000220202d20ca502ee289686d21815bd43a80637b0698e1fbcdbe4caed445f6c1a0a90ef1827569c50310000800000008000000080000000000400000000", } -// These are additional valid PSBTs encoded as base64. +// These are additional valid PSBTs encoded as base64. The items with a comment +// are taken from the BIP174 test vectors: +// https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#test-vectors var validPsbtBase64 = map[int]string{ + // PSBT with one P2PKH input. Outputs are empty. 0: "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAIQ12pWrO2RXSUT3NhMLDeLLoqlzWMrW3HKLyrFsOOmSb2wIBAiENnBLP3ATHRYTXh6w9I3chMsGFJLx6so3sQhm4/FtCX3ABAQAAAA==", 1: "cHNidP8BAFICAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAFgAUdo4e60z0IIZgM/gKzv8PlyB0SWkAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgAiAgNrdyptt02HU8mKgnlY3mx4qzMSEJ830+AwRIQkLs5z2Bh3Ky2nVAAAgAEAAIAAAACAAAAAAAAAAAAA", 2: "cHNidP8BAFICAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAFgAUdo4e60z0IIZgM/gKzv8PlyB0SWkAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1cBE0C7U+yRe62dkGrxuocYHEi4as5aritTYFpyXKdGJWMUdvxvW67a9PLuD0d/NvWPOXDVuCc7fkl7l68uPxJcl680IRb+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMhkAdystp1YAAIABAACAAAAAgAEAAAAAAAAAARcg/jSQZMmNbiqFP6PJsSvYswShnBlcYO+n7iOTBG0/ojIAIgIDa3cqbbdNh1PJioJ5WN5seKszEhCfN9PgMESEJC7Oc9gYdystp1QAAIABAACAAAAAgAAAAAAAAAAAAA==", @@ -78,6 +100,12 @@ var validPsbtBase64 = map[int]string{ 4: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJiFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgjICyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSrMBCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wJfG5v6l/3FP9XJEmZkIEOQG6YqhD1v35fZ4S8HQqabOIyBDILC/FvARtT6nvmFZJKp/J+XSmtIOoRVdhIZ2w7rRsqzAYhXBUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsDNlw4V9T/AyC+VD9Vg/6kZt2FyvgFzaKiZE68HT0ALCRFfLkkK98xFxPeFEfNgV85cWlxWMlop+0TfwgPzVuH4IyD6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqazAIRYssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20jkBzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwl3Ky2nVgAAgAEAAIACAACAAAAAAAAAAAAhFkMgsL8W8BG1Pqe+YVkkqn8n5dKa0g6hFV2EhnbDutGyOQERXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+HcrLadWAACAAQAAgAEAAIAAAAAAAAAAACEWUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAFAHxGHl0hFvoPejzvOx0MCmzn0m4XraCy5cktGe+tSLQYWcuKRRypOQFvfWIFnpSXoaSiZ1admHbaYBAa/zjjUpubk5zn+RrpcHcrLadWAACAAQAAgAMAAIAAAAAAAAAAAAEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARgg8DYuL3Wm9CClvePrIh2WrmcgzyX4GJDJWx13WstRXmUAAQUgESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEhBxEk2nrskszQbJVFYmR/Q3sTi5VyGoS+K/Ina73as+ZxGQB3Ky2nVgAAgAEAAIAAAACAAAAAAAUAAAAA", 5: "cHNidP8BAF4CAAAAASd0Srq/MCf+DWzyOpbu4u+xiO9SMBlUWFiD5ptmJLJCAAAAAAD/////AUjmBSoBAAAAIlEgCoy9yG3hzhwPnK6yLW33ztNoP+Qj4F0eQCqHk0HW9vUAAAAAAAEBKwDyBSoBAAAAIlEgWiws9bUs8x+DrS6Npj/wMYPs2PYJx1EK6KSOA5EKB1chFv40kGTJjW4qhT+jybEr2LMEoZwZXGDvp+4jkwRtP6IyGQB3Ky2nVgAAgAEAAIAAAACAAQAAAAAAAAABFyD+NJBkyY1uKoU/o8mxK9izBKGcGVxg76fuI5MEbT+iMgABBSBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wAEGbwLAIiBzblcpAP4SUliaIUPI88efcaBBLSNTr3VelwHHgmlKAqwCwCIgYxxfO1gyuPvev7GXBM7rMjwh9A96JPQ9aO8MwmsSWWmsAcAiIET6pJoDON5IjI3//s37bzKfOAvVZu8gyN9tgT6rHEJzrCEHRPqkmgM43kiMjf/+zftvMp84C9Vm7yDI322BPqscQnM5AfBreYuSoQ7ZqdC7/Trxc6U7FhfaOkFZygCCFs2Fay4Odystp1YAAIABAACAAQAAgAAAAAADAAAAIQdQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wAUAfEYeXSEHYxxfO1gyuPvev7GXBM7rMjwh9A96JPQ9aO8MwmsSWWk5ARis5AmIl4Xg6nDO67jhyokqenjq7eDy4pbPQ1lhqPTKdystp1YAAIABAACAAgAAgAAAAAADAAAAIQdzblcpAP4SUliaIUPI88efcaBBLSNTr3VelwHHgmlKAjkBKaW0kVCQFi11mv0/4Pk/ozJgVtC0CIy5M8rngmy42Cx3Ky2nVgAAgAEAAIADAACAAAAAAAMAAAAA", 6: "cHNidP8BAF4CAAAAAZvUh2UjC/mnLmYgAflyVW5U8Mb5f+tWvLVgDYF/aZUmAQAAAAD/////AUjmBSoBAAAAIlEgg2mORYxmZOFZXXXaJZfeHiLul9eY5wbEwKS1qYI810MAAAAAAAEBKwDyBSoBAAAAIlEgwiR++/2SrEf29AuNQtFpF1oZ+p+hDkol1/NetN2FtpJBFCyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwlAv4GNl1fW/+tTi6BX+0wfxOD17xhudlvrVkeR4Cr1/T1eJVHU404z2G8na4LJnHmu0/A5Wgge/NLMLGXdfmk9eUEUQyCwvxbwEbU+p75hWSSqfyfl0prSDqEVXYSGdsO60bIRXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+EDh8atvq/omsjbyGDNxncHUKKt2jYD5H5mI2KvvR7+4Y7sfKlKfdowV8AzjTsKDzcB+iPhCi+KPbvZAQ8MpEYEaQRT6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqW99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwQOwfA3kgZGHIM0IoVCMyZwirAx8NpKJT7kWq+luMkgNNi2BUkPjNE+APmJmJuX4hX6o28S3uNpPS2szzeBwXV/ZiFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wG99YgWelJehpKJnVp2YdtpgEBr/OONSm5uTnOf5GulwEV8uSQr3zEXE94UR82BXzlxaXFYyWin7RN/CA/NW4fgjICyxOsaCSN6AaqajZZzzwD62gh0JyBFKToaP696GW7bSrMBCFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wJfG5v6l/3FP9XJEmZkIEOQG6YqhD1v35fZ4S8HQqabOIyBDILC/FvARtT6nvmFZJKp/J+XSmtIOoRVdhIZ2w7rRsqzAYhXBUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsDNlw4V9T/AyC+VD9Vg/6kZt2FyvgFzaKiZE68HT0ALCRFfLkkK98xFxPeFEfNgV85cWlxWMlop+0TfwgPzVuH4IyD6D3o87zsdDAps59JuF62gsuXJLRnvrUi0GFnLikUcqazAIRYssTrGgkjegGqmo2Wc88A+toIdCcgRSk6Gj+vehlu20jkBzZcOFfU/wMgvlQ/VYP+pGbdhcr4Bc2iomROvB09ACwl3Ky2nVgAAgAEAAIACAACAAAAAAAAAAAAhFkMgsL8W8BG1Pqe+YVkkqn8n5dKa0g6hFV2EhnbDutGyOQERXy5JCvfMRcT3hRHzYFfOXFpcVjJaKftE38ID81bh+HcrLadWAACAAQAAgAEAAIAAAAAAAAAAACEWUJKbdMGgSVS3i0tgNel6XgeKWg8o7JbVR7/ums6AOsAFAHxGHl0hFvoPejzvOx0MCmzn0m4XraCy5cktGe+tSLQYWcuKRRypOQFvfWIFnpSXoaSiZ1admHbaYBAa/zjjUpubk5zn+RrpcHcrLadWAACAAQAAgAMAAIAAAAAAAAAAAAEXIFCSm3TBoElUt4tLYDXpel4HiloPKOyW1Ue/7prOgDrAARgg8DYuL3Wm9CClvePrIh2WrmcgzyX4GJDJWx13WstRXmUAAQUgESTaeuySzNBslUViZH9DexOLlXIahL4r8idrvdqz5nEhBxEk2nrskszQbJVFYmR/Q3sTi5VyGoS+K/Ina73as+ZxGQB3Ky2nVgAAgAEAAIAAAACAAAAAAAUAAAAA", + // Case: PSBT with one P2WSH input of a 2-of-2 multisig. witnessScript, + // keypaths, and global xpubs are available. Contains no signatures. + // Outputs filled. + 7: "cHNidP8BAFICAAAAAZ38ZijCbFiZ/hvT3DOGZb/VXXraEPYiCXPfLTht7BJ2AQAAAAD/////AfA9zR0AAAAAFgAUezoAv9wU0neVwrdJAdCdpu8TNXkAAAAATwEENYfPAto/0AiAAAAAlwSLGtBEWx7IJ1UXcnyHtOTrwYogP/oPlMAVZr046QADUbdDiH7h1A3DKmBDck8tZFmztaTXPa7I+64EcvO8Q+IM2QxqT64AAIAAAACATwEENYfPAto/0AiAAAABuQRSQnE5zXjCz/JES+NTzVhgXj5RMoXlKLQH+uP2FzUD0wpel8itvFV9rCrZp+OcFyLrrGnmaLbyZnzB1nHIPKsM2QxqT64AAIABAACAAAEBKwBlzR0AAAAAIgAgLFSGEmxJeAeagU4TcV1l82RZ5NbMre0mbQUIZFuvpjIBBUdSIQKdoSzbWyNWkrkVNq/v5ckcOrlHPY5DtTODarRWKZyIcSEDNys0I07Xz5wf6l0F1EFVeSe+lUKxYusC4ass6AIkwAtSriIGAp2hLNtbI1aSuRU2r+/lyRw6uUc9jkO1M4NqtFYpnIhxENkMak+uAACAAAAAgAAAAAAiBgM3KzQjTtfPnB/qXQXUQVV5J76VQrFi6wLhqyzoAiTACxDZDGpPrgAAgAEAAIAAAAAAACICA57/H1R6HV+S36K6evaslxpL0DukpzSwMVaiVritOh75EO3kXMUAAACAAAAAgAEAAIAA", + // Case: PSBT with `PSBT_GLOBAL_XPUB`. + 8: "cHNidP8BAJ0BAAAAAnEOp2q0XFy2Q45gflnMA3YmmBgFrp4N/ZCJASq7C+U1AQAAAAD/////GQmU1qizyMgsy8+y+6QQaqBmObhyqNRHRlwNQliNbWcAAAAAAP////8CAOH1BQAAAAAZdqkUtrwsDuVlWoQ9ea/t0MzD991kNAmIrGBa9AUAAAAAFgAUEYjvjkzgRJ6qyPsUHL9aEXbmoIgAAAAATwEEiLIeA55TDKyAAAAAPbyKXJdp8DGxfnf+oVGGAyIaGP0Y8rmlTGyMGsdcvDUC8jBYSxVdHH8c1FEgplPEjWULQxtnxbLBPyfXFCA3wWkQJ1acUDEAAIAAAACAAAAAgAABAR8A4fUFAAAAABYAFDO5gvkbKPFgySC0q5XljOUN2jpKIgIDMJaA8zx9446mpHzU7NZvH1pJdHxv+4gI7QkDkkPjrVxHMEQCIC1wTO2DDFapCTRL10K2hS3M0QPpY7rpLTjnUlTSu0JFAiAthsQ3GV30bAztoITyopHD2i1kBw92v5uQsZXn7yj3cgEiBgMwloDzPH3jjqakfNTs1m8fWkl0fG/7iAjtCQOSQ+OtXBgnVpxQMQAAgAAAAIAAAACAAAAAAAEAAAAAAQEfAOH1BQAAAAAWABQ4j7lEMH63fvRRl9CwskXgefAR3iICAsd3Fh9z0LfHK57nveZQKT0T8JW8dlatH1Jdpf0uELEQRzBEAiBMsftfhpyULg4mEAV2ElQ5F5rojcqKncO6CPeVOYj6pgIgUh9JynkcJ9cOJzybFGFphZCTYeJb4nTqIA1+CIJ+UU0BIgYCx3cWH3PQt8crnue95lApPRPwlbx2Vq0fUl2l/S4QsRAYJ1acUDEAAIAAAACAAAAAgAAAAAAAAAAAAAAiAgLSDKUC7iiWhtIYFb1DqAY3sGmOH7zb5MrtRF9sGgqQ7xgnVpxQMQAAgAAAAIAAAACAAAAAAAQAAAAA", } // These are all invalid PSBTs for the indicated reasons.

    3. =fmkDHJ*O?3^{X*q3gwKgJjKQ8 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 +&TV`1gm>>0Fz)W<| z%az&rS~i)z;EIrw51G#IoC$VwXx+0%VLkFgV4b1T73r;qK9KLg`UGLUMUG|)tcz*EmdqHbg-EiLjBs{u~esBK<)w zoD;ug;UyvA_HmCR_=tS;uB9JA7#{;@Gb0aH*d9ptBd*&PVV z^Uu~*m+M-o(JAZ6m$o`O?b|9XTF^urdy%o^RmkrkHMS*c0DO4vQd=+fDFXR^oTd(B zt{kDTHsjQM)0&d`_KIlBXqAXlEikA$sp4V_Oq> z=h@C~o0e4kxAUDHrL`a3^2d~&L_l^mejv2wg0FxxVEGBhS9M^N?PFe=B>?$Yn~Noy zdgLifvW$@m-{1^me1Jz2!o|iVUG?MYm$h?<#XJP` zxw%F;Q7<}ufRDl8>&sUUssQZ2lBz{jX3|3bsr=JRz*wYCf zUYwsQkWamb^8exNuA{R0;(x)@-Q8W%Dc#cDr8Lsg-AFemN=tWlOGqOjozjgUEji-z z{oR>$&&*o)8UKIQ;^lkqbIz{MMhTHjf;!AT=JKbJt`UsXV`)l!lyEOz{c-^FJ+h!g zz&V2(ucDTj_k`}-w(9Djl~0!T%x79CWUf7E+!=sR3cD^!hM)HGP&~{|zQY6Ng%9~w zrLh(v4nMEQbNj?)H=en^FZ8TVsDUlkd7as)p}!GXWfTxik}g7E2-P3-pU(jS4*cys z1%TzT%6Ee!GAXSS{l4AwQvF!t6+bRF&m68ujdUh<$FqzELwT(L>XXD5Bwd!TR&rmvj$} zCe8OK5lNa+Q7@eDd>s)v?F|`4zVV9c@*;6S#Mm5^-%g1(7{jCg#t*W9?Mpcxqcleu z+2f}0O2nys%Ual`pDXlJJj45bv)efpa*lM#q}WI}Rzc2bAKW)9Atsqn6tN_Qbq7IR z9Z(*#AIt&r6X$$E;86QhD&gsIUq)3CP6krH+;1xRg~yKLzry{!ZXwl4fxk%Jn@$W1 zoQd8Dyq)kt2yvO5=^boMH?3?}eGBq2EB^m@e(D3-XV7bAmzL6k&-2JHn!GNhHxKZX z5hRUT|ern++X|nlkBDFi$nl--;vH|&IzC(a< zvhlz6Spw*PcS#5NN{Q!YVfV>8Sq_OOCvb9^hDfAGUn%^=@?dA%k(?MPl7rmmGO-|B zmN^_`XNl+Pj7d;2^T#;jR(@7n0rHD$nbm#AA!AM}!5QiQ!A$;h*QdoBvh_*Xb@+eJ zmtpZu?ma|E5@P;dL@VP{-58Q)$$PYm@u&~NB?&1hEcJFEA74pTCD_kTb3lHL z?%(gWC@|pC!5|T)U#<{e(V^-@+A%G_eh@X0{zRX|)S|Bvn@Ge1_4230`R^4V7J{QO>?MnUyw--Cg95WR?=b~mXA`CFNv1Mj*00`mvGCw3Di z;@VYFA(mW0K73md@QVuD0DM9wyP|V_pG_J#*lj{6vOUkIJa`HWW=nr7x(dvV=l(`= zGq!B&WLd}wN=R#XEHVBjdsMqUJ8cp>i^Rdvnxz2ng}LM)erPU1Ny_Qf$r6WYE|Pw4 zefWoE=VJ{&%Ck?i@RcBA=pAR*rl!)5cqcu=odDR#rYn@AmJ)?HlgI63caV<^*Eb04 z{9FM(${Wb9q^d-ri$@t9bEcY&@HWZSU))_+2RmckENGD(iTm^jf#zQl=9fwdhq;1JVIR?H zV0&?dry@QUX~8h^h0(IcP{5}xHQ1J$>_mD+c5pL1x6+0y*9dd#I&*BX5{U>7CUD6y3 zd5J7BT%j+_a`Qo0tNNpM+IVC93$f??;-agPkIZ&lUhiR~1kv|@7$%z+e8`!5;)SJI z^Y2Jeg9`@vnEXmx!1nn7eDu&$p4UW;Ei*H7=+-=F=${z5y1SL0LS$=^5D-Xe3Nz&C zokv^c%C5036;cIIVu%tr_Z`AC8|3c&XH z1AHP2tcV_1E-z41*HC#Dsx-N7N%^#+8oG|`ClYq%ftj6u_&5LAmY)0z z!aeOUbZXbzMOiU(T;v@Q%2fWk6vxkRqYV3!?I1p=K$4NMLd#e}TX3)=5D9oL~NsX!(V}`ZLcnr{D+w^jIRmw~DSFQ-ps{GB`=ha;}41M^|zi0JCuDN{<#9^nK8b$5IF7xOTk* z`iA)li=sx3gwH}_N6l*=+@bvazK7%ua|J3eQ!_#9}|T|6e-?&8Ibf&X2@m`1UioP6>RKH;q`IZOfA>54LSJhDDr?q`rok8I0>kkPm?ud6s7ZLejZUy%e>;~4sex`n7Q1{d~K`Qmh$YQFHxK=#?Zx& ze`8$EPm?1SVd(y6VkMWWBusWIy_N7scPhxoKeq|~_#qYG+m4`}|ETb8!B^)VGuw8u zL$*zItL>~)x+zH~Wh;<5CKkDsZnk}1kBU$cKS3dcueRY+pyx1$5n~TS{|tS7DZqyW z<>JvmfBSy*eHjjMi(B803j;sQo^wyBqQ}4aUCNzuRa2z=$-dZRT^o1b?3`Ca-^$}@& zB#kuuEn!*@ndTk#Z~lx1rJ0f{TRB>*YO*7G@=xP%7#yt*3Wsh$8Tltie{m<_JdlrW zq?!!u_L&9nmGq%Lee}(MI92G+Yx+LW*pLy_<8!UFa--YXuJ${-Cef-@z{HUG%k9YC z9l`~b{&kbf2y;LjbrfN!-MhU#E2K8Hecsrh8Ez6G7?&T%|leb>&j;LW@_KZ-5Xo^nrshSWEL)4(*$Xe`b%_?E%CF@pB2HFdi+A;R@$lownv5}62^qf%CfLQ zfulaW8np?7tr+B+r1t}(Fy?>b_cp-zT{=34wkeFerL1v5h*iCUX+CRG(%IzCgtl#G zrI+Z8@rIUby?xk_+srY8`AH&=)m6~wpD1U{p#&-}L)LY4;QU$lTg8ZA?!`b+F1V!c zm=TtwSMGtl9~optAehjfeH|Wj!!L=XUJR8syXM5IB+;@`93NUIb_E;_^fHhSf6G`1Y+nb!H#3=D zGmyXLvxnRs=e5Q{nx|&}c&PC6Z$%GLlHaym3?k@E-}Gy|6E9_aOlbN`ZsDpTsraUa zg$PYs{U~aC}j@$N-nrnKl~22l7k1NDLDCG|{-=2e?UhI<;P0ziy9LP{vC_X!d3RUpm9D zi%tz0;rNm(qEO6b0e2Hj8SdsiDFJhpf7iU@(UW}0k*cA&fVl{$q!=|b)3-$oOK3&r z>DP7t(%ZJqKwVUz>t5%ZDt1B++gr`u6#PT$yxCpPn&2{jk~6ubA-i=PSa@HQV<(JKFIKo z7GV2+0DQ$~{2iK+w=hh}X8zPWaot^+!;m4;eCeD=1CCbN=@y)8w^BFuiq$>Jm5kq* zQvM{uMG|07&}B_MNjRf_eL@BJIR75=_G>eUvACZwo}3p&4(*i=o_JfGP98Yw{``EA zf0xMje&#pQT@OadH>vxqZ{vhnHw&@Cf}uw-WmnS=UCsaHXHyIQ@v&)uPi#%`Fqks( z@BJh8q7aV9Oj(hI&8EEHY+H3nc5a8W%i|iyNjT?!oXBqII~3C$4qUYPywu9}Dy!sD zVrQ*$Gy(W*)vedzVH^c}H zp<5}2&<*lI=gzQ#?OOx*n2jymMFSUXUnEyZ$3MNZq8&6s-a$fc|NZ{+ckQjJ!3izc zWe+AQ-MXVAV%-jt(d?N5vh&)Dnh`S9pCh$SYk>R|yNvC3IrDvgbqmen%H~YqwUyW( z|E_OE4?z`M4p>~0B&u7R^#}lOL=|)xkW`Zx|R(;{cpl0+)V9(qlQ?jf5%^RAV zZycNMH;8taO0PRUTYQjb0{E8Wu9Z@gaFiogar*Ht89D?utS8V++WnnNk={Q0+NGCZ zsF%Y;!@Qzv^e*PK4LkgdpnaVQcG(2K1>xFs^9+D|slDXjAAbk|e18%Tx{ix?1PKJ? zO}meY67aUJnSPQO#^+cv(cugnuivzwGmtuX9DwrBP++a5+i;qV!CX&6+6X47S$E*a zm<876TUs)hZRKg)Xw#PJHXK2N!QlGS;eX>Utj5~;{@EuiLFMtjWnuW%#d_mA!aY~= zhy7`p(zT8IQ0>p&f?2$k!yq3HqB|+r`TYXqSE|-uMy!_o_O))a?0n#zfAhub8q%Fh z_L9%4{Q4mu?g}11$#ezM`Y6O?{>kToU6=0Bt+hu-ERC5 zXfgRQkPkK-CKPPnDZqE(NeZ=}a$?k(O!Jb9eYm{gmqO|Gl|$n=%a?E`;v1avluh#H znIin2WR}1mb#!uDxjEOF?*09mfky2?2=b?Z_9@vQ!C6-7O=iDeZhsI_oKZ@&NVYXGJ4v&_+lcxU+gvmsopb{J?DolWUBnCv6VEcXp zd<_zfv7aw<>mmc3(1j~rb`^4w1@&#*(J0x&-pf6k1e2gvNxfYC2X>XuaW*hOe!_9NAYDAyqR}_uT)`Mr%LXi_t*zT^bgRSbADkGk(*# zuFx=O@Ky4oxg5?!ngRLN@HN06-^K#QN983aN|(YHBXANPoR>*|rs#2f<(Tx~JcO5t z#t?&$PBZrYbbJdq85Txxw|eT)H(9+7a1V#Rh!G7#K%f5|4LtttvDfm)gd7gpYan98 zAG_gGOguZgeGGI#s0`vipXKi;VO-_T+2aN|4XqB58d*`)#WCV5cKDjW43W!o|qNkr}XvNnY)rx>4U&} z1eQnO?UN|k(CBIT$Wv?n;Z^bK)%vfb^Bh3`V|FBD3a4W4UF9BAIKg{RqrjB>wlz69 zQSjY7{y9IhT+9^*iC1K-koUDg-)reIu!pT5!ZQV=i(|6V^71i~j2je;Ego|<_tIR}iJ?)BxL;a^=YzXY`=hlO1R9$M0Gw>x-+V(K#zbH75Gov@HmHMRZgz;Ps>0Zd;#yGnNzSs0F-r z`+Pj)jfZ8EyA2ow!=W`yXy(jTHdNLgwkseXPC(8k*giynultDQnzZJ(*erR_Ys~=> z_KRbvYClJ2+cV9_eR~&CGb9>LpjP{E2(;Rd~2mx9gZq zcOwV-wTs@uafTExZC?AqWs(g!tPd+L6mIx4bn^K83|5l>UqyPCbLcUjh-h$NuNO*1 z{oQ$&luG7#_nF@A*|QG|IrE#ZFPVyb?Ep^EJXI^_p$@A#W=aeTuk68EpTk(>4#>xQ z=$Qm|e%JsX)XAT?6t{tz@{ZcukOEx!)VCsURVJC%lbpX`*llIu(QNRfno}$U&=8sx zrO6|A38T4jMX=tE=j`#fQX_vr0Ql?@Ei4BI#a((J_tSqVe*cP|X8X3%>CG)f3k~+O z?;+o-4xYSzEILRd*Tm$+-u`KfL}CJxr+07>(pUW*)94<^$9Ovk{`mkrfX{jzxna*A z^}(DR7ga`4Y+m0^O#S7f^x2Lct4Wjbb{>+vZcu3S?ZD!e1Ra0Yy#fJ$0rs{9YO6>b z*P%rpX)M53F*R^C68C0p|N8utJ2i;PTg|(EfJN0>usXx|+2;YZ@$(g*%Dl+2Z7LCl zpaOGTesJtQzUlP)lH^D&wkd@JkdM0z5B%fBL;&9~my7B4ph4s_O3=mb3!isWc-cL!;~(d5i#$$H90U`n&a^ zZ6yiI3lXeNUA`nTN1^WB#WG?{>V5W6w2@WAuhZYTdc7{w!HBz^Fc;TdYYezwMno2~ zRIrDHI0pG>Aqrc;Zl4qYpWQJJmVl+!VB68K@}=yHR^d}j^OQ&b7w{qFG2axJhC8H4 zAGc}eh2Ye7QCso8CiNRn5@=yEbT~Fd{z!Fi)CT0I(`s`5{i;qfN6T5AQKT$#Ib+U} za2lgm=srvN*{3ww|G?YD;-wQ9et(8yDr6BtyKiaEyJYrm*-=LOa@+nC?jiUxV{x;L3&3wR*NTN6XZOD-w2){$D;iRMKgkn~XC*`9*GDj)Ha`2fvEs+y z47L#wAqRP%x-=TJ&d@u!s=LgorU)(_ZeV4_pMiYZNAuu6KR*M$Uv8*5ea{|?@g(Oz z{GciQe?C9ou5ODshngzN0Ty*+r4gykvdwSy;(Lz88C z;{wQ!du}n%5~;1nsD{iRR~VPBc)0UDg(lWFx9FwqXCID+*=%cE5r!LliSWW6b%?#P zZ7~jENdHHzB1)+?1tZgQkdJMi#vJVYxB&Sn@3qM~i{wo7>p(#wDQ}gDqA8|Va~>V* z2a~DJxyoFa&YsXjP=tNxg52^Y9rx4jRzmb_dT@^!)b|tQVMcTY_;|?3zvoeF^KDVx z_xIN2-QJWYhn?{Van3;C|GPPd`DoBs4zCA84YhcE4k2JXTSyOMpk&U8Z7e@+Nt3j` z;R58V{3#9#wyzCvzC%F!t>nDWbbA{zE2QZd6UKZyk8&M`We~#f?(|f?uOZ)-4gVK+ zJN+BV$VL9!cBAFN*rAzuz779$vq$V)&lrHOdPP>!>C2-BrKub@#?t3V^KGQS=Ds$s zS{=EV=lrHJTQyT{gn~}TbmfkejvNZSgh)8yYrexZKR({1>YIgJfqYOzOhsV(cmVkc zYRQPZH3){==&jf}PDgvb9TxBnZq2NT<{D2R?dRZvo?cNy%E&S*BMz`lR;r%KeT{&S ztGS%BUf%h^fFYz6;FGQRY5c>j0eX^z6_wJ8C$w4DjNz(?sUhn4;nTD4F?f%abDquO z2s*dvkEr|O;aT-eXN=b`$3}AQCk2!{gBy_VB?C?@*uIwlpBus#{a!J0VZQ~;JsZKH zQdTUDQBT;04{~yOsXq1|Nnx1LOHqHkUBgFmM)MVwn2oHVN`d`TJPq)P zI=h8yCd)u(y>ZPO)5;5B4P{8JNs>^YRDH|&>@#8QcR3WXC6=uo3BhRRO}mYi5qGF( zK8aFA&)c?bovpkD`82+;gK;bDf9ppJfaeR_FS!du3-zTvcKAKdxeCO7vDRdAVxA^B zYHw#KF***n0qm8N!bfCF`)}q$tNgqpNx_yZg##w_Fs{ocDA~*a-vYkpgqE$-)4(qK zjd1<1ke}3iqF)4cr5fb6|IH7^?i_Y!=LNG(nYW%aP1jQH4fW;cS}9V{Z9%r}yL2tG z-hq5osOsQ9KNkT$ydIZe3v$P`U?iT1N}7w4hiMZ#v)5PQO#;EM8m<-|9H4FqxRs)) z6FXcBK3+WG+b6)H=RX=6x(}3}p*MUP1^A#oiy(2nd2_$=X+DeLtG-$=DW`~8Rxy65 z`8)XM{M0dmpP*M{+b%HhJjzPl@Moe6o<@)xUW1b>CMYh^FmK3(A2j772Vv9*3VM0mrQHq&ZkWMIK{O&}T>3u8+eaRZC@wP72Se7){yi(%}5JFM`QV&>avPAq%A8me8R*t zu-6WiUO>^n+kVE&Nu&9+t)A{BncN>q;Pb^l_COyw<|cd{Cb?|oedMQ)-Tj?7sAn3{ z+fQT9KKQ2O!pYE--w|ZcJsS}2$*>N0{pJjd8+Jp*r~wJTuGEo1K3K|Y@b?!e0es$5 z@rXZ5gz;>oO`MW4IBN~se-LHcDC}V+>AVtnQfBhWsAJGup}Br}PCX(+)=k%iTRhAW z1`~UV=7Twn8vrbSjgKFP>OuJpZ+F!D2a^T4{=01CtJH5CGsPpT|MvG}x)886p9c3DkhT@anZKuA{i1ovdb}KY-M+f=H9X{@Wou3N8m*Ja>-k%U8mS2g4{;LT^ z;>Bjm6fz6na?Gj*-eB{HE#I3gxCv}3h;H?Q9H_(%;^}kxOuV?HB+a{oL8`53;QTzs z+?kKyH|_%=v=xF&OACrP{wxAPmLS5q2tkAA{Fo`(>`WpoUa3kf&^!K7FAd)?`xy2z zuUj-4cQDIkb0-uNGe}#LMJQvyl^sd zV28Z>M>dF%CxcL4_>_O^E7sk?>}6b$JR`rbf7M;wK&BUbpj@PsYcO`d>5Uz2y+XkP z`4|=4!9QQD56F*kn{zKK)k8v9#gwUD3tAkpNReL0?M)%JK^v^m8R7NUN23q<(8z1kWwg*yQI8)W@@*D z6`u3k>bXJ5VE-JpvtP{b;=D(b)ghAb)%_#Qta3M0(c$on`G3C24+`MV?+yaKuOkMR zpiL@<%CHs)P`R`gAl0tFLN7>_b6wNlchmdDEj%5iJP%EyDfj*Y%;&@$iml z3b?_I)QdLG1D=md@qlQ$#_aj%k%zzC-5gepk zoOrK&T9_rsm6)QvG2U(DurjM9lHX?*zm(w5UUkhX?q>pg^2dy72nE(tBFFyFjJ&^Z z?(tC@T0C-N+#(JB?XN4*s?lf+CK(RIeS_1X^W~A#KE`>D-LJNPD_2ZrX{DtTI zC`*E8`FNdLI-8}tvupW<@Ox8mNRLlb5`0pH7^wFPTF61Z7vfX$VEe29zLecVX5)7b zjPLxC#p4Cq#l4sZR46j)wR3bwm(1}Wq_P=?gm#l~6@|TX?iB4dk$n_l^FE#uTV1}C zD`ZFz6a@Hgt)=jkM1MLE$}69TDSq0ZayTMS=3aDUv*GwxUUAIXxkK&3EQp zAJ#9jJyU*<)oZF7x4aEK9LgY5#x%ImC!eCLxWO2i_zH0+#RK6$tI!Lazs`=ewML{b zgUHz978OCWAI&K!mz|KqA&?{d^Yolw_jwp8A}dwKHr4y}S{v?OB|PMehR(t{6t4C- zRVMrRBLYD=V@=0=0`l*ed8c&= zi7Dk`P5TG`$`gg#1%)ePvdE}yzhrcPTyn`Ipt&ZiTb%orn5@h2JJ93}3&;oS^&R~6 zO(%eFU&Prk8`*ayro`aQ5iR5}T+L^*Q0IwXJ2>Mh<(>qzw#RTU_+SbDpt$GTd2d($ zU9HD4$TI6Tzw^D_DzSzGexId&+`!f$TAxu&Cagi-i~hh09lvSiWA6Qp@9N+AKYyaZ zJlEE4Lu>RWrhr5}9Rr1Pa>uXSuLtJId8Vu?VdyzPKH6F~9^WqTD1Fba z|LeT-t3ymnb2(55>&f?r!!RVn5p0z7{Ac<4YKX7BF8r_yPfc zxUqu=$nV;T9jVe$yvL7f=PM+Uzk=+R3Xi%4F?rd}Z|>*zxwFc8t1qBJEm5W`TDZsJ z?Im|p-A3|AJt}UW#g^zGaKZgw|MT_$|9p5Q;QQ>Xu^($IcLvVtv1q@JvVGLs7RvDr z>o-*j|CFJz15p%FSoR~U93u;LQZ+k^L@+^o1T3MmefvRQ8R@MKmQBR#_N{b9M8wm%Vw5Wqif*!OLC>^ zwG`>``VY$2`MkT5s6&Npk{}->^x+}c`6U5-LzQ(krG-N8JT0k>tW(@POiSLVc@xnU zl2TZ9#nSVJe(LA-d`fghpVjh6uxjM{SoS%sjd7sQ;!lP&Yx^v*2p~VZmqX@|BF*_& zd(2uJPCsy}{vdGHg{r)rPc{B`K0Jy+F+lG^xZ+Hx%Gi;O^{0691H7zCwbDO`P+8SJQlTofZIe`g%A;J*ACtV)q;&VK*rH;re%eJ=b5CKnR6pt2;;It25CYo}suEyP6+A4lqpFcv#6`6hJ;s@)2sVeV+k7 zVI<#A37z`BMlzbyDcrCx16!3PXYUWH(HlAaq~wj58ZA^j<}W|dnETiF+sN2Oy&OWT zDJ4`UEIj3ewa%?R0Qi{Su|zfcIXVV?&Vn@MwdQ-sgfq!Of7y}ss{CJheYymJ9Xh=j zNvPEKYl|(1SgL5&BRnoc=;A5x!bv0TgW^j6<20ge8vD zeIv=)sBvhI(AP^y<*uam?TDx1PbkOxpD^}BGx!dnVGV4KMps{$>RihPsvdRqF2G=l+MCgm*5BXhK$L{sBdm^!;N6Qe~Q0 z)^z7DQl;P%n@Bk-6_Ag$M_e3iUoOD6u1)$OH9_Q1XfYgEbzEX)_P6Qnr^+oV#cF_j z@F%3;ufOL3dRjp*MXE4&@m=SSREb^|TJ&zb_QJc$oZ=(4tJD zF7r)h;cy8*hExyk(_FGJvBGyRG~oN;UJSpHWYR>^$vR!^L8}q&tm}B|N2!P(Q<(YB zXP^5w&x+7>b4?fobyFOUx)@TZHN7kx_1V6hInonNYF80$kdH$3Jsa5h6##ssclR?T zgCs$|rMMQl3j4%`!uJ*%*-`8x1_JQh%pcii`Eq^dy?@#dsTa1w;SK8H+kC-EY!%bm zKIbhnNzhOM^gmbZChRcQM*5nZ&lxDcx<0ZN{S<6MacK;BkvDAwUm7^L`$1} z#3<)(e5ipqfOFrN5)f0c6SjQ*Q$!Es!yVfMzkbLvVE$z_L^QH=viuJhq7h5;S(U+W ztD$LkES_7PX$e!^%a`9v;bGt;DT|aO(+R>b#<3sLA3spV;p>JKjIeS5^I>()* zDtEf+KM~=gM0ftXoia`$RoP9`WZ@&!&_VK;p|$6Zb4|0{A=ZTN(3jrAM?4H8P=1VA z2$Ep8&pLoleywY^V_w!(euB+&kUOs3yKAe;9$nqYw5df#_mG8JXP zy!;IM`x-Vh144XS7|uo|%_GG{K>O@&7W|-caAR$ZSe;$Qu)m1 z{0b92E1n`v)Hw4ESH?-5bs17=Odz1$Yww3!Z?z5wg}(gfbDR1A{`~GA!1#e(i=U!= zaok>d5TZnz>#0guaBrS)bkl3I5{2@!09-jUNxK(geCwXRG8Uod<-26E$RY=?nXoDN zv*}e0&+$0yB z1aHOmvg<0F+xTBmu#`ZyL+N5n9li5=_Wix=Wi(AQGO6fJQAqp6>(Lfggejg&rheq& zi6$g>c=BpfkWcgNJowjhWdZ7EA=(`Fa}wtsx(UG)_9sEWli{a(WinV;d&MC}v++oV zy8KF>(%$Ssd6jk45{QF&O!kXB{wsfeeySRsXRlGk5x^Hbm;td3QOMBEq*7=Bv#{Fh zfS%2M<7%Xl^Ktpv*ATD#GrFcBJKmdlC^e@VE>MaNIvsUt*akYT2SXJH!lgG`DONuPZ1K*d#Wkx8IQWlq7&*lo_$z3 zO*;JFkjBa+uDZ&NU*jP(!?m?j8S2d?tu>@PEamfCgM3iN4&d((=?3_OEp`2^3-^3S zJhAB@b{8I9-5pnU6&Z*HKOd&pR9hj}Lq)W{y1GwdbtXaZ#(j(tTjh+~G5hB2E%N#S zEibVH;Oi22EHNvN+OkZiX}zYfsCn2%Wp==L>0e^xoBr(M{=Iq*ab45@1)I;Wt69b# zBW)Fq_e))G&d5SVmz$hpm<`Csh4G>n?Ecpa@RjU+;&3BS5+GR5pMUZD)7<;t6_Vm* zSU#^p#KVh>?TQ%1f4jnSaX41ao__g7g%dFTixd_)I=0J^QIILMe*t*C3=Q0qNMY}0 z68?#;yJ7c;QODLBU!p3g)YZpY^JgDwewhrhivpempEvgD3$d5qBHkVqF$l&|-L-ft z%8?Azy#x6mOt8VPZ!-w+J)kXCs18aoSkQbaJ*DRPYBEYiS+v}4=!+h`XPwwKGAtc~ zG*zV?T7bEoPIb|qPd6lzFsu42l=tifi!WgZ$N$Q2?(g6JT#6g^^VoW*na%{#aRrND zc2mY|W>R-3y>KM&X!O7Rg9buS%I{^YEtkR%NIWqboY`n>>un286)fp$4#BEO2<4J19{5HewLOo$Z1+?RI`(I1K4 zta0=$%K5v>MZStjN}+lu%Is-}`k@Xu{DZFUnv$2b=uiub{aF~VpOklDfj|3WYsC>p zAoRI;{;ik15RO>kOiQHyBWupw)CfA2JtDfVC=OfNIl_aTy3-TnQz=mZe|ZHGaJ$TW z%VURvWfda@&6PeRf+Du3P@shdtAbr=}1`$P>tBZf8>3I#l-Zcl($FiXRB0W(!b+5tIl6Ip^yER z_{!jO9LXX&8u^u8pp@`^?3-f$Quvykqst5ABV{cCe|l*QkYAN7gB*X9%3BdI2y=Uf2z3Cq6}7wgZD80 zq29%x%i1RM%jnrBB$>e29oxp#f+@1fo=mVWAM)Lw_Eg+o!^lJoEe2}!DGKB}-VXy~ z`^0~*2jc(z^{~_6&}8YRE?=4#M5!_S{kVy?&a6j`EFrki)a;hotFU;7-I*cW8q1+R zA1V&@X}IB7;3b>#8WcyMXi#PjHSqM2h4QUDQOLT6mq|IvNJ;LIs=3NN=l}W!S6L$T#`aY^nvX!j~ zqpno=-eabjPT7uTsa>Y|>L(kABI^@l%d%Pw$Vd6=Ne67-37~m4ioX%~oR}{e{tkUi zlFIgRj#7QhiH2tSklO>s&#dG8+T)Crq7#RGK*Yu&Kujr4=3f5hyQUA?OFiGNc!s@SgoIx~ABS9T7{mhHC zc>hCK(J?rbv44KOg(3;$BTeb00^4^9@YQP14JZ#kEzq9F(uQbDoOTFecjOn<65v~( zQ*#FJdHqn!#KuR5HW8(4q=0$V41}A_A*pvc!4a+Qw(7SR_?lI?cE=aQcct`wFpr zjP=C+cl*N!V!o%zFRQap0T0I<^=C`uW42>2e#igauP#qq=;0Xb_!;Em4JvsLwhsp2 zI}1gIvy{rjT--hl{(AFSI!#@$_SHS^1I=bL%n0n^FTG4G1Xsf_gxCSe3?e1oeKe7<%{QV80|hvu^&PzT^7k`T6o^N_MTs zW*rfGO0<)w<`ZTYl>_RTbit`^LT$cy{UXwR#(({fhY9@ZpRfQQK{litd^d3^w)zjY zno@0HqhD+1txAQvT91)_B$H4jm$~M>F9(@h^~}j4E!*eD41}@i_Z=W|rp}sYtvO>U}zLx{?vHWgh06RYvfbWLDJ^J%in*LeG%vPQHd4uqY9A(;q^{$Rt z9GgqEYMdd$z6?dd8oDEAoZL?uj0%WucFYrmE?cD8yS}r;dEo5lja&TRRqB+sQ}_2mESdHO5bQhxNoVtjNZ?bh!T(wS4yD)Y#%njM>yxe z5jFpS)ZMWJ?T{dEg$myxj{XY$>(H_$ZwdDAwBw>rODml!*6m0qLo8wsH|BfWrsUy>c-%jGoIvL+XHO7yRISowGWzcel6&9ufa`hbY~%wm&j)!DOP9 z;}jfN5?fmN{2_HO^;oe*HcqMj&Hzyc@+E|>ga3Z72h5)7DO=8(WYf>0mknMdsd&ap zh>c+_pt4|}2i?RmD48T-$!W9Z z`ocPmdGEMxiHM-&-{)tmJ}IeR6dOu!o16N0^n0v|)pWw}41PIy?&u=lD@w%KYLE}c zq4EIi_Q?$JnY17e(b{xsen!%MD=(+9uDd599xP|LdF2p`9`u&~EhL_|PHMe9cGJ|? zkBL_}oU*!?f){UXQVuO@kX(XUKsT!V>8xM)pYJn?+|Ti-DEMy-TadNj&Lg>5{VWfh z+G%|X5<4EB^V_F8B_=(svb5zP7^42!^@!#cJZ<-1&LwZW{WbSAItl^rRO50`lCqq#yIq0D;bMyc{Gty zGOL}b8mUpH`fEUL%VY&0Kf@D~Y~^k$WK2n^edp3+dN@d=&Vyl1dCXzge*>MH`)St9 zn=iCN5M}qfF$EnEME(wADnaPeGHvCf^wdG{jUXS>u}T8iK5l?dQ<7!0gk_%Yy_2>` z3m$a)#&FG{NjZZa|8#@_uVw}RO0vUe-CGA|A1bv_Wf6*NPxX*S(tAtEqmf%5 zuP?6RXXjY3A^wO*wzPqK#5j%jVEcpsJ{7N!q2yLrIbrkk?l+2d+z1p6AGEum+vJJf z9q4FhdSoZU8)@6-2ED+pN-zH&G|PbPRk~3bg;ngF)!8C)0lfWh@ZiXLta5tfjZ&j2 zU9$9&CWp-a2hQygL6;XOm&DZrcL;{8_f!ka$N1=h?7dhy(N6?25kZ zLp}S>X^v9Q<{WRS{yW>4NSRs zTUqEv8v0e~2PX1CCDezvOW1pU3tF-aF#GjeVpQ?gNvf~jtgH^*e_fJiehdNl5<@Dw zF3!m7Q0Q~D$EugqVnv<5lnW9qT&(E)s~(bgYpD2AzNiB>v)W;9c@Q(@p+hB;jBqnp z53BD_%p+3C5Xgs!8sP|bewqNE*27516W3hzhTkoDqMJdoa-R@PHh}TfQkWZw9VJ*a(mknhfKN@UJ5@0(I9=LSvo1!OsVcPd zFp9TAalGcFdHp%R*Q0glCE<8M^uet9)2-SI=9TjkNMB#fiz8)c8MU|F*o=XEyhDWG zuRdr4d?!h31m>f+UgyN7{_R|$*y)jH&0Au+IjG8?l}23p*ive0Wnq|aj*lKmUU_|b zBDy!Zhc@K9B2wsB@{C&0+XDD(J?{AC((vM%UT#LN8gwk^^;(^~%v_qXQmi{Y`yiw^ zDNp#y76iGf6=aL}%(|)&x()P`Kjx6@UF#7WWAsdce1x6I*kI>p0q_M#46`E&9L5@z zq`vXhIAog-gSQM2_Sz~sM&1z~;xkIsB7*7b6g%K*6X+X>-B~ns<=hr4?%?W`zh_JR ziSrBKE79%?m2FowiEQMD90^F&;AmZM;vKT*cP?*+dFH7iCH-HV-BnoC%lkikx;v!1 zQ$Ubz5RmTf2I=l@knTph5$Td{l$4h42BqQIxVHOuUEg)`U(fkEd0p>`HJ_Qe=hdbx z|2hW3r)wq+YujhxAHF2}h4_!t*yKv4>;Qd^ATFFC(chvz+^h(v z{<7uOO6SG8?*|(%Oj&y{ys&yj#Bh!hLT%r;Z8H|ZHTOCf0Y8q;9BO`M#u11~N;)7veH)S!f3OD#?_i$~&Dm!9bf>`9k-1inct(zMeQ6JG| zfDi8S|HtV_Zy+Bcmst(x7RuCGjFREnN;^Gy@@NjFe9<*j4n*D9DfHb<{2UL>QooS} z7&G)3-HFuQ@|*eus2I#VQMch+$=F1o{OnnI$yplemM*bR7-B?9FDbaFdiycxf3O?c z{uw`i_XKdfwV5C&$l&Lg3WiHEtMR?mrmqjdZC6Z4+zqNvUkCUo(CtBA9|Z#WytSd@ zviO|7RV*_=o;RQN;G-wY&>`YIe34M}wFh5HovByQ5Bcr|u8ld;Yz89}_$2|^(PB7? zJP0X1MJ-_649I6Vb@LoBogbG?OGOI%n~FH^zQMIXeLH#gs08UHKXpgRd8~w0F=^{W zcfqSg*9wk+b+!5JI0QcPrGT~Cd)6(05A4253FQ743gk16ulrysNzZLEVxxh^H6df# zaGaR7dhAZN>9kWkuxD}$em>6+X(0#c)jbEkVQgn2`;mjzjO@WB8L69@=??hz-_XzL z%hiuAkURB5Ne~%^c22E@#*ivv>x}-yUN643g6K}7ADuA$)sd{OTKfkfl&TM3C3C(W zp3Q^=z6sMMJ^=V26b@KG_C)~sB4W;*6I+Kno)VUM<+ui5C-3az65v8BZqr<(Pp@+q zKAFHNw?5q|<#%$!!G=uZ?^g{-APjzSZ0%Oiu$eIfULUzhm0=@l3%>gu-|ZU?h`ZN#8J=$!zro87CU^w!(d9FN z{`yKZkPjTuPmrkeo$8_}A!R0p@<%JXyLZ@%0=k&EVUc`IO)-({6)jy-aC+9}U9mmN zT%Af&zf46l++z4O)+gA04+5Aua+!uxgHIPw#cR-b8HRNmP<4_VVHJ>Q(vyOLrq z#A~1fczZfrt_pkmqbt>WDuhTk*3oZ}0{TUrW`kg&^R9os55BuuvEv$=NM++!aG(>; zmpe!7+NK@3XXvS>Aw(vBtFo zE1ug^M}ekJYmM_W40)pbrQCF~z595QLH81u!Vj3!BlL!eV zwDelm&Mm(b_3jbbQd3Tw0J!XB6&$fgwQsg1;V19il;E{vK5ap znrG3L+;)y4WL$2IXMM{ZijteO53xjA!=~HGD3FhNM5@C4dq0i(9(zS#W_))#*vUhg zYy{j`$%uakgs=v3fzGikzH(5du1?oJ*eqM@2%!HuR856tJ4?XE#gT{ zA?jst(%8=t%Y3;NUJqDd5BjU>YDq9EI(B7ZZ?M8Y)ivH!R zC1Kbg@16pIsLf|I6maXmrfJi_(DyVr>j?jD-{Su7_R-4b99Yo!;ZmWP5#bCh zXD^%@b?0hn*f%-FBFC_wzI?jN*46y>`tUsdUgGp---K$OoXK+-KCyh%e|Qq|?==38 z_xJM|OKL^Yln$aTmT;@ic)BtZ@*K6@WfdVY>gdNmhd&<~5#o$*%94yus#Wwy+D4Kj zNvy!DWe4}I1DT?(G_c*F06eUOpm31m>jR2U#mu>kyRm&VdX%m0(g*ea$~>dR0lnSG z@zM9{k+N_^67%lMbclaK+H-!&qO5RPy8;Qc-TOuLnVLIpY9zB>ARond)b4BPr=_G$&)ld`{?*`Aud#E-XgOs~sH#fR7)V}X6K8YKOkzwYY4#=_q;>HpHHmSe znKyDK?+ms+bzB24|L{1d)LbB#ptWh4%D}d%5^PgVy>q+x?bgSWyI*_>@v#)sRDkBLRHeu^ZkX`=)_>@gAgB-B@Oki}g`mxKNmg zpRzr$@^kEDFQUmT@rZBd11Bw+9!&2vglUSTkC+5c&~Y^vnl9~u zln4C#MPpKISSq34k72CF&cgn$c){Q4Vc#6>eU8bL$5t^om3X^pfZGPlPN)kw4hvW1 z(2I}Zp4+0+rrju-L=L|6*LAmdaf5&UUEd)=p-0{0 zbBw!iKEZ05f0RAyJo@21%EngeW3nRBIn+-C;ISe)j{d*%{yqG81Qegl$#O>9q4&HX z>^p9YQFrrxx>K9WA1hgr^A^knd-^}q3(q#ai@xH`srY!=%Cv6bxU)P;!vve9Xpt=i z5`7-|&-XVzL!DkQm(i{r((*7clGVtDi6~521Dv()gCeazhd-&1`8ZaQ=g(jkLTGG< z=w@hKnJeh^b;2cs5!x1%!+2_l0lw6eL=aZ*|HcQzYn`c=W=G$VCzzlqqiPZMDhgE2 zq_(9==zGnMh@`~_`F!b~SiMwwXWLLLOkmT8c0#I4(er6KzwzsLMH_L_kN@%h&h9*g zjRC3`E=k!~Z5!OIcH*7ysh$HN920SW{VsWFomV|cdl}U<&d>yK)g7=y--%~L@8GEM z%jfJN6iyxelkdm?Jg_>yCXnO%1>_@K;2b>{F)01W+nr zDvL<`j%r%wTYoYkzZqf3D|hSysyB2w#|lf6tWn*E+AXF)J}vXz#NUBsxcI??_KG$! zD~-Ibui8&T#IMA}n_hgR)VUH0iyApHa=-294+C5iUni~Xx+1LV5YlwJ@!iR}Q38BP zw|9sj`&fa_?lN&&Zc~JZHxDKVh2BvnxH;&{k&1OelyQr3k|VG2P-qw_{Sv5_sTs6? z*M!jX4Y4!oER3MWOe`-J@E9ov^M%S^|f| zm$}__=51WJ450kd_^1g-pU3YsS97H5nmUdu7R|W}##06S_gDX%Er-Q7dioiPo1_dM zD%?nZc`5ShM?7cdQ1Y6P&?*lSk&Y_1^`E*rbb)~T*q(4vpnJiR9nq+2@D4Mb+5nezIpvkHpWDWZ` zbSSC6<>~Nyqf7_Lk1Qv{7v%gPf%2nOg%O&m@!U{-6_-cvESqwZHX6U#fG#Y^kij=( zeVC2z^NthdJjlLvOZ1}!?OamNFCFf}@>C1qv+Nu1%8UBF=Sz?rtYN3nxr{2ccBS`3TPPuRS} zXXv3C{q_HRf2Y5X<#jefZBpXnyzHCF3Lle`8zM^v36KZY{;4drfA*6u|1~sR-kll-ff%B;h@0x0 z_%54|a{;o7`@eR5zx>N1yOnVVxp^W2#plemV|^D^_msY#>it$g)#pKJij!_hSYS1= z@Y1aXnU0CTJOy^fZKs#J#Ydx-c#-4rr~&CM^8DcTdkj@;IpE3~&x0J~U81Pmh>mYw z3Bt+5Lxyc$xkLSBSAc&_v-FN(9XA5x{Cw6Qm5&s#=oYEgrs&Yuw|E zWe3E^$qOC|*z6q!3xx$H!*oCZR^q_w zRn_oFFm6W`VaW;w4`t=T@SCBe(Xo>nvj3Xr-@h-bJ@g?)ZioB1WQAYqwo1-7+74@vSs&r&hyRYmDwJ5nr7ud2tw&1>MQn-L?JZxF%n$CiCS4_}Hy{L9gtF z2jsibMra;>e*!})kpHGTOx7ZjAjm@I)te|Vkt~X<(0@vOXBE3ncE(Q3;R}AK?zvrv z?wU#67xt?|pEOVGxp^%Gf-|Q*`)eniBrg>S?zDHkd}+s#&)8y_vdWuq^i2s z>@fBcg8F+&@>j2dAtb{5?e)#A1fIpZsG-HilKB8WM)Uwlkn_U_@@c)Mt20+M)BQwG zldpZ$@qSoPjIUX;){e%LW=6CRoLa7Kb^N&SqG7a2>LZl$n>;Nn7q()*akQ;ZzAVdc zwSX&^gOhR429tl#&kx(X{3g)Gv>A|&H&#r@Srf5n|B_!S&Fm7gaAHg!a!Ls~IwW+pD32a{ zwi8_gtB=D5vfg^-VZ`#xML0a~f6EV8*VX`^eYp|;@Hn=n4b6qhin|2czCVm>epH9` zC5nKL?S>pB#mR~8lk z`g^8)E$r93!QVSXVEVk4SfSi_KdQ7yNvuVzbOR<UU!8I99^Tcgj4U3b9f5VYzb??-oLa@Pn*e_ zwRQZgVYxTV#ox}iT1uEFIxPv@jJrpg_h2q~F~k8r@_a5iknRIqI@tf6-vi|aza2hHso+VGzu7(I6HyhvK%9C2 zzs2Cp(j1=N<2=ZPc`M*3B5zk%4Gx{0`jPjyB3cYi!?mBGM)w}a0`S=v-8;SbDie!V zX~e2H3uU7ZDQYaAne1;L2zK`Ve48&hKc)2i^2JW)?YYmD5)xfjY5#kv5B|S&v5zUh zUGiX?r2g%Hj^v=9ZDj|_@4GCP90n8>dRt9Gg0ZvaFT@;diLb6X@2;uEKaeQ2Tj@@= z|6cU0C#bJ)hoIn_qQLiTXHvs&DJO-;e@FjY0{CtRyuqn&dU^9Oq*ZG?>(!Tt?8k_# zphP;gjzycXm;A=ap%O!VYhLNLOKcr#NK$-oxN=%^YP`J7X{2Dj>k$7S1Mul+9D-gM zMFgn-4R-M!Otsb*l;Cqo$w@&;4VtKx&R6en|ZU#6J#X0nEZ4awuqpWX$$g0mh8 zp4!Y-K{o6r=;imT#0nMzt~~D#IMnGbSsGFrmr6fyM`MgkSh!DxxmeUKE8+o`Q&YEO`tgjj%GB} z1|pvZoISutFp_3XTgVdO@cKD=Njf_m?$3}*-({(|Wh9~o$Q`|obmB#Pmwx7TX^`BK ztq#=xPHC1e5y)oVE#%{ftJ$N16EUw#PUk&k95Cg=y!bd;#RneT6mbz7B!Y%#ZscD7 zka%V)IXX7cDLfz%0H445*M}p`cnk9Q!U@zqQ-pneoKQ%JCp`^@W;Kt_g^MOT{Gsx6 z{HYtfc3CJirX5LW?B4DcN}DQQYht4ZlMb1jcv~d|-7RuuiY9ndoV6-Ylhwgl{g3;G_r%Qp2fyl_G3UR z={2#6yRtRTtE1lmf1F>V62WBMCtxs2?2PYmg&up1Myd|}GD(BuM^yCU>l8(u)(~vi z^637I#4veF zL^Nms;4u&44uae~wSeNg)c&>DxM=ELm-le0oV9=@9UM%h)3!$}^gOlOHn0{6bs4*Y zK3jm)QZ8zax1WHF<}(hnC7DeB8hjIR{-XotfARfY{{2E+L2VcnWhPtL0So*jLn_o| zeLk6Q)V^ylg=57JZbPp8B_XbbYU{n}i*<3Ar8)A}5UQV}F%GNj^k{;VRWWLr=;oXOYQP)G~kR1|E=a^d!*rDgQ>I8@~{C_=Dgl4I>*Z zQ%~&jB_^u!7azJegXCu#hCpMEaxv1ocD#E8wJ%d?2pQA1ux`ZygG^ek03Q_VGU!LM zEP#BxRV~R^vbTJ`+hpQ2$k5#(uP8iF_GAYtul5^Vqm=GG+y69qO0D}`d0(FG-@JYD zVP*BXKwhSRd}P0ou?;WC_9 zC~4{g=cAws(_Vnt;bu4iv|{r~=$BO+v`pi|2@imelM6~7wuJF+X(9g0jF*eZrQ;$4MWd`rO`r-SZt2xljs7FO@3PR&N?}N?CUw2?N zi!Xl;goH@u%q+cwkh|{k2KXR3rrbdGc?0=AFCvZwFdP=Qo!Du3PKp@G4X8I-QkMmM z3LOmeOUoF}5+RvVhZ2TYW%{VX*%@n@5iL;jjg0(rs3IawGPL+lAfGGDE8CArixav% zR}ywB=3yw`sy=WKrU%NqMO44!hsZEVGt$(A(G)|Hcv%)gfQ2yB=YHnO0kdYczy_uC z?lA!1BgN>M2iX@2KQ$Xt{P<_(du<|!HYXSD`baGSCa zL?)_U7#Mg`w5)~n#l04WO6tD$_ezOG0C4GoD{-f6KFMc=QJC=>AIQ@dg!40ZWc2>R zBcYk47hlnv^}~r-w>A4OIU?bPUKs+Ylq&2C_l?q?u0LD9xLu&W^ZB7l5G zU?^5&vJNo@>^M%0=KQE|W2((MKbgij?jhXbZQ$Y;ve3geQx{w5=cfjHy36tuw=r2X zhKJ{Z&CLmpaiwg5@`K#;hqAQB!@fE2vn5C6RUjr>bk%!jGn|V}U;N^O{!G^Hwv+5T znw{eWJFc`+J`u9BZ={Jr7G@Gd0Dmbj7!L5kQAdJa*gFo$_kc3O^6~ZK?cJq>lU$O3 z-b{7uM+PtmTdk_GutH4U4PptUi2>gnW~a>Ac`EKv5wzY}$96CwtMd0;8nIdv_CUT5 z6K!z2yjDHIBOXS2@}0~Nu&`jM77ak?_PQ7(E+{`?&nAKp_ylSSL7IDij4 z5-J{KUm=k1b%Q`ELwr)UX~gfU!8#N2dtMZx297rAfV}fIghU+Ll+InULRp3M#;9c` z0eL(~aB|a?j*hDfe^_zl1`S@|!ul=uJP0wex(inWv6TeL^t@?s!&7wHJIB6>@PDq3 zmH+dAr~W64(Ku~ULPq+_rb6zi0ETd)!=idwI_P%Sl(0mAk0z-P^oQ|^fP9v%OjN%f zWU{H;cfQzYx0IyM-&;M_zV?A6@kZKSkD&2F@%$PzejhwVb)UtXZFi#a&s)=C-txYt z9_9u(-q11s<@a}aL@{|GSXU5KN450Gx-sLy{7lAUgz=YI46y)& z-}mmfrvgP>^b#J?f*2-UlA;Rk>QP6^ep@`80|or1j_g>=>C(h!T=g3H-{ATjD*ogB zT|USuOU>r`7w-}?89exl;1#!wcsLGz3*1b3HHG}bOEEE-R^}GYMsepM4mrhQ!N8f? z8=y%%wwf0{+DN#cP)Y~zNUN_EKyIGpK=JXDB7Q53yjwaNDDw-4aQ-UzJ*H_Oo@&}gGDJT=SKtZM9w(_hTL3kM%%)IUjeO9d|;jc+RzMA;)16mrMt}ALV zKaxvU1E1OpSOjdYRMjx2;TNA!I5Xvi&DW^w(YZ2l44wOiQAcK%Y?6)t>TyKdc5S`{)gC&juI)V(fEtJCcW#~|W*@!?Po@|&0@DW0Md;-~559HI#A3zNwtlTyoX`(k<;vc)0 zO-gq~vt(0kl7*c_zJfBI`#q{4TBe-zPpHi-&uMy03 zv{yG1JC(n$wnL$vW_h5YgO zJs|AYpMRfZ3h#$Ax-{f|C$VeEPy8e}B}r13ZKGOPGM13a%c$^FD+T!Ic(67>_6-90 z@N)w23@x_U*Ayz|hp}wlAQJ(;4)|>9_4&14VeK)+(AIT zb7RZc1-8Nmgw;k*p`Y_%5En-7#xn1@Od1IjUwllz>3G=D)i(tz<{|`rwrCv=E`~#E zpAkpu2&@yb-77xT0(_)quI3=;Hv{CG*LkC>yHphaE#E}GtX_MW@_Qb$+|V_%{Fk|_ z0&@p{tdE*+=iYDe=O2w6C1*>16jo608g$v7jFvq)_nR96Ui~%R&Ik@h`W5}EPNtNo zA&8jhZma(S>%CkvY4KDi?T|x6Y7;0cH~Ic5ioAQPR`?30xX%$jKHCijQ}GkMcJaXR zaEa72OT!Z1w3mm4oxwml%@BC29Ps9m?y6gHIgP3qBB=y140@p~ks zm;8Q2-h`yfHERbdxPK+I_jTVLXO2e{kF9l>umv15PJ0PqpUFYAEpTLto!IoZ)- zgghJJ`BZFUlQJ1qo+;+6=P*&9b{>@>-Cq09U1)W>p;U~_OcU~}9Gkt>M# zDFCIVt*Cs%_h^_z6>F9DV?f8CVAfWe|Kwg{IAzUeTP(|FP^<&c~_9VPbe)+)EhndV%M*7dQ+PjpGqcoJ9jc-%<-73q8kr$JST z<*{%(06Zvg4A3vG{055eag;P8g_dl)f(7eCEhJ@q^T{cKKz$sQ?md`2x8gP}3ma1d z(cH>aIYqWD$`DcBjHf!0SM2M$SLk|t3M;GlKt9N29*Rae+4GBFdlxjc_|xl;HuYWF z?WfsGv484jeNurLJ{&8lN|_f&;&*ax*~5EqzQC9tt($Q^#jHD66zv80;Ktf1KyIF3 zKy^)TWrXnZOA^b>9E~lRjD{n*k7p2*JvR~_u)FS|+ygZ(YE`68xiGAMo3}9P9J!up zLFli_i|YjwGrp&XPAA9x&-b@^<|UE6dEoMEYRW7}0GsQ1sw}D_jU+x;k8oT@dC9Lj zB~8^W_!o*^;g_Tc3loXC^k5PgqcQ_DT@-p9h=e53K7g;kco2kF5&k{;iSxhz&Ym5# z3=LHKgU=uocZC{!Ctop(5MvMV#R<35oHh$_HucKeJ)FDwC9(b*yJ$@*ATgfbS-=+p!l$z zO5_|nHy4?@lH+wcKds5u6ejz}PXvX)s4~9zB91oBj1pxtcMK7K)YK;PhP~;HB)#dX zE_j84F&ID8*)t6AVcAWBUUXjUf8(njlD2fua9Tin7n;2&l3Nl&x8F~N<$A|_fZDe^ zN_Eb1;{sj@9r?YgGp+-A7W~ZKrFPsdI(H*^t!sXj=TiSa-rvz>v=rBaJxbPjbWyYF zJ9qf4&?Su_RcU~S_(}Mmt+Bo|m9SFu&bjBjqv|lJk3UroG>G!UI^L9f99LX?0Jq{E z1@NH$DJ>0h??VHMPhFk4L0~&)@cNuHWon4wz(SK^wH(nx2`m5LS6hK@A65GXXDwtr z9HAe?T&|oQWtAAGaSLTE8=p(t^h_k>bP-$?+x)K=<&V# z-}ru_1bvR>D88J&?WGV=LHwdKvKKmaV$DD---tEF78eHX>LEUMR@LTSkRLsD5pAI> z`2>5z6i9KlsU2!h=)VRO-^06CctvwwEYwYF#u+1@)jvdaR0)LcFd>F8V!rUI2wi2y zB6=9^KTRjaSt;v|>5?h`xT|ZDb;MV|(iOP=^c}!sjP?Qj$y*Gd_zZLh-slKA^Qh@a zdSi5igd5O@AtZmoS0-3P`Ye(JUR^OWWWLP|&jV*G7Ux3uDp{7A_Z+t>lyw7{Ysh2N zg&oMZ5We_S`PTbK?$8;IG1=QQu;*CFn^ruEh4s)^FFx+d0&iM`+2pk%H+n2RukBk4 zn`sO_D_p6CkYF61W`d+yfR6>%0`#JF_&~m?WtmPQ$puUw@qz(HR#Z-naYg_7S>fs) zO32B}qrSKRFBognxN#i80zJcC{PW{$@tK)+IO5=I)m%p#u?gUvu`uXW51pE~?`S_Q z47TQAdVVneFwteiD6SkfpZ4ObUZ3ZWOB7UL#T$inB(vfrq5NW5?QC)79&?G1 zgu6+%vlIPTLyP=Qfu_r!ns{q26kD)Q?B*v}>JWZ?F^#_6$*=+)W6 z85XsU_xvMYe2USl&A79%z1~P>9I@l2MBiasQ`mnNQSRWp3wW;=Gn9`ll7E-0Hjd-+Ul%JpqAc_q88sLB?`q9})fQ91?siIhbR zd?!Q&@_nPivVL8QU>Y)1c$?SM2s?O-EoeeR^6CA;XSWw0$6`4&NnG?KPSk^P0M7-> z<=4IwbftwNxbZ~WQRyNEzMFW|L)WP zsIAs0os2P`5LUzpE#F{SALWF=UmHbZ2fo(FN4?`%4AGftM?1>FUx0jXVH)Ua;SXyu zBPmPLLl{usZC~g~L)lWxLHPZ-7Z4{R4e`7=9_B!*x27%$n{i@JUx5}KYe-G)!0+bT z{)=i4;G^E}?Ety^F#`FAMlRSf?F;Tt_4v<0m@sY*^AKqgRV8>-24lv4_<|rLG8U^| zKhYl{&Vy`$8e3VNlD`Q>jd+}|m<|RPe zrG?;spYL3FYT+$1^~^JA8OL^0|CWW8Y`OmH0N^8SY^w*^#|-3CwCqInMu>(NRkd42 ztiu<-OVpmC*V$r`mkwSQ`h*OLA9*72R^TpMc{KcCt@-yuOQ4#@at=$}K8GI-2~2AN zkZ%EVQ!(;;%j;sN>t9YY+*)D2@P?$uiXv!}>W;QN`l-8a*kz1*F_rtpqt#sJP zxR~)lw<-||*-~F8heLp`ymc2GWS<_;x$-6ChK)B<1Bq%{98yfPFvW3h4kMC;IF?4&L}wdyCM>nm6fjHHpyh@wzcn!fs6+4$-?6Ezw5(~|H#vJs3u}mnN5yI+US&=0yPat6<_U{OMM(J+u|C$1(6rCi&*jmiipv!yDHCy(Xpzkk6^r zgqH=E>(yoPrf4?`Pa&T(Vd#Smd5mlkW)5m`kY?rj<>5^nyLfCsPc7j&`~Z#DgCeVM z5F-OdKpa`Kc^y#uTqP*B`Y_$cvol48bgb%i44?R$gz(L4!L`NAo|pV2uYY7!CU%+y zwVS`Q!-IJY&$NV{`hY1Gn?S*kZc(D6cLnfq-d9|M+&AO?XZ++D`Y?eJCIH;j6@MpS%S@y)~^2lbu5(n}P z3=n{wtZHQx>>Grwl!*p@mLcvC6AQ7kn=~SP@eLWUHOx@IT5o2C7c`P?%9D{1R6lRx z5yf0UmPkr*U~akv_`u51vq1LA1Nji!)7E5{TCbXwFf#NAW4@6zO`Ue}pF0^n3=24M zL4H^toyRTv*@yaF#VCx5DI%*VsTj?w4Gq~jKQGTk={NA-YdbgamAkMdvJI`7wb@&` zY3`bU?Ys8nZmqeyrWap-Jyy~SSQq4qk5Lhz45_`Es;3WOYm)FT;Wsm?LzOIBK$UZ|LUk+C;5!46)xG0XKkZ@4# zp6Z9Op5y*ad=Y1}Rf_7Znm_`i$c#Jj(mGpfR^IG@w=9o)XMHW-e_`d*)#c?*R^IE`J!Xh4Q&b@w()x__^7 zP*))2k(57HhUFlE*k*>^bEUJI1$g}2>{!d~K+}9&bj7SV!3G0Q?nu{S(qXUsR%yif z;;SW!wW47%k=2)v;b$KIL0iR&w4^hHh{)@E0~V40qa?B#`XuJ{xLC0;+UXxatNrtthH?f}Xcd!su*xudc^T zf2}=aW7KIuH7yMoce=Y|2y~AJ28)vr; zMA%zX5@|YKma+>?bDvb#VpWzlf--4g7=eQ&pWx+G<{FY%(Mj< zIpqKG{w{9~eiV?7pVG68zk@+%t!W?#Yx`~d{hc?BF%jIKYyHe7E8b%fJT)*-8Mm|& zTZ3QrZy~-AEeHKivv%`Sl4{cM5ayT0&37!|C0pIl&wI-e;|2mh9s znv5-Yi*QS?hCIhcA3TMf&28aJ-j7vbmrA-yEi(S?H`Cx=RLWBkg~hA=5I{b}^cMPr zU6S2Z1CkLf#|&%36tt(5_E7H%rdJOy%~Nhj4B7;V*e;E^vnl3>ccvwkCxl!z6e=c`J%f6g_$RY*Ziky=5?-aJJ+gm9*s?2!5~f3 z{L<*2M=|1agAI7pnkGjo#qN(SRZVT@HNuRW(!^3AU&EXFRl8?8=uT2C*f#KFww+%` zErQ5`E{@f?f2vLhXma4$Lq*ykb#I*{Z?kAQEL@*U*4u_TFD?*O<8+mllK$%pD5nD1 z7Xaj2FuFs#)pOVG{lJ)-i(jhYxAZM*+_qdW0XI~N2TKll=9i^;w~VCXNr0(}Bnv?= zPN#CgQ7c@i)o7=2&ZeIHf4;xnZ*WrB`BeL%J6c0ZYW$PgPm;3fb-dT)4RWdpFFyf` z5{4$)+GO?_p(#$JO2yE!3)uQCkbmJ-IQ>?XR7{E_mki*uZHNPXYlZ!PyWfllC-%usV7HWFG6ghhVHrp>;U_&h-)a=|8|O`+$r|9@2W0ovLm9=j?cry4=pfPTvE1dq!eu^xQnxA_xc5j{( z^L`|mGr1TO{PRF^)&k1c(W6H3S|4L70FSBP8}tVogMs2}YMnVD?TT!^9W?N=H) zUm}aJ8{jSSmJW=4J4f_{&8`yo>tn4_((7-Q$v+!QS-AXI5F|anyIqKFW}s~n0{PUv zzkUx`**Skm@XO?;GbDQ6$Ow_fD?oEC%H4a3kLw)`xF1QMNe~_)>XA;4U9P|K?#0#D zov~&uiNZVjeK{I{Px@dK7Ubq>2ei6P&8o$zR_wv{s&i1|Jo@FyIH8|?OOo2EYm$aE z*x$-gaV>GkHom{=TYq&aqplL{9k&*tv9W2}%*z#^^f8_V$k!!*MPG z3>ww11`EV3WXBs3Jh>NN^WvKK{S^A~e&1K0E1G11gyA4*)dUGsQ}Ev^Z+WCGzR?4G zu*UVE7tM+Q%5OJxhO88yHdJ5Ky`Tub+3aIx6!=-KB_+ih5;2u{edY;H;ttoe3q+~* zB)hc>qQ~@~`4P@h*@i5k->}mR-vdt%zii_tJoG#!z0Tz|y;7@%ukCc7kP+!0X`Ti#%hrBO91jQLrK8- z7nU&$68qiy_B-5~sTY{tdAQ}&>9sxF;I8^o<={e|6Q_^9mg1wOZlqyNU+&#v94=u`mS8*4){ta8cD+d2_GUR^1xu}#a0q#L0`PEo4&I)Cw{c-7`_mEfgqKN0Xb zsYJ{-<|0dK^HFlZy-{3f|M5#5`3=BFLFWVd!Iu;u-&GbAwq}R!N>P!LksC>Vc(T*g z9bwWS;giQuC!Nb!1luAa|E}tf_1oUDYMXIvJh~r3{w~N#$n_^R$qODA<3R0mSShqj zvBc#8<9g+XM|E6BxOs?8Y2Gk27g)uggA*29nHjQ}>wCfrBA2VE`wnjMxkI4JiEC#K0gwn)fT z#ab@sB!dD&!s}f0x~9hOkv1XjaR_e~-k2R=seZo?6923y`xd*FR7n9IU&$rrVuc~ zP*!!Q=--zn@64+w4^t*asqC3~1OYy{%X`od_7ns8a;K5OI&;9t zA=xHWG&o+aYc)H!6^`jLO2e({0h9M6Il=hzhNocP732|re=))zDtO{%Jf z72a5kRz%SfF-=^fhDqaW`5l{MP{k`(atyOLruHB2 z@ATfvZ5!m5g;=c(jopj`HBfL%zX>~>NlKZyHM{o0>&iV+R;ZfpaZ&GKOxpX6X?4Zd zHv2&%QF>Lp2}xunWbI!bjk}^Z$j!3?D83=j%&u)U`y?@4nB={jhsMUxinG#PBZK4H z$E>$9arY*tCaGePIXn#~UPu!Ej{R++Adjn`e(25S z`sd@)P6!5R*E)VWN3p*#ZbejccT@{l5r_W*(~2n+cqnh5l`O!AWB5)5WM3nY4@#6- zl;NV0#n14&^cQ`vs_k5uLE(vxUVfxOJBSbb2;aL5NT+92H-6%MhIcGjB2>LemvhW* zvAa4&e=vCC>*lX|i4PuOI=MV@4++vb zH~jP{gIX&EE(paCp>;Yc6(aDA$~amc;KQmq%>mih4CE`B`E68|w*K+BY?FmXCuPtc zNs{uF3)+ffWtgeSVEm!uHhOr+pmzCOeojS^y}&-x{j^=@!bF;a;BlTqi|p`!zQ4mu zePYhi(Da%g0hHr?wBKfr+n9>>RDK-K&tMs<7vGZ0>PU{65IEFKQoFQ_(3Z$>wx+3y z8T323JT?Bz&dGO503Q;zBM5&#{~caz{&#qx6*K2RrbWg{+wfkQ9CEso)YcQFq>dL5 z5ld6RXO*F)NvHGGZb``GC=Be&_WEqlGzBRoHt6}Y{TsNmSuLX0f4slL3yo9HKb7J? z--P^b4~vQkPWsedKJc#lqQv;!Lc|L%T+FMS6m19I;)2z8xH?33i*g9N!#JeCwZ3px?*(rPC*)VC8z2B(-5ScSAff47OA&7Iw~re(1lp z`u`}qtEj5l^?&$uNrNCD-67pbcM3>%gLF62UDDkMNFyoTozfs7NJzId?}O{v|2@W@ z@4;_z%*khbuQ}(s>$+FUL_#Uz1GgMjO}oN>)kEGhIJI1+oztfl5K8~|zK;LICz87* zQ@L02_DyD0=61j<8LZ@;<-LeUeSHRnl4qX@q4Bs^A#?|S)y>c+Rc-EWci2xM4mF0M zv~pF{dr0I$G*9Xv z9wWY!0od{V0L15BUo1Z&l^xo!Ol@cog%|*B6M4M>{T{($*y`jF8H@HjInYT{tNatH zQs~Dww1g$Zvm2JOAHCJroty*&!g$C5<%u?gH-;=NPXaxz8aN?JrmhSlJCxGVHhQ-h z`S-`QbegS4Xp)1icmRS6MR!@HY45nQgZC8A@8$-?iMso$4IPk=Yy|fhY~L@S&z&M? zb(GpDBoG;n9!lZ#WumUIxA2ElMrBN=;NI^Fd@nY(sbid75G-&)EsWM7@^gjecA76s z-qgTX68a1Q=a#Ap<)Ke=xZp$=h6d> zz0Ye#U1@f-_Vjaq3}}=lGv971K?fRwd^`sM;5YQ%1Nb8F{F;?x^T^?99Ms?9mdAg2 zl_9YB7V6tzWv^l=4OgnYKOY1?G0&>wb{VEoZ=K9~BOGMDj=_{x_n7Cr?Ytl$zu&XX zza6Mgf9L8WC~=H@>p+CVakUKIQxQaCf_e6l@&)+5efmS)()o7TC$!6W%1{Ie0*V(& z^KR#`|g zAshI{+s9g^is!yPAjIVMRF`6=W|Y%R+ak$ee5n z@+lYega3MQ{@>S2(7|leJ@m=yR9EXzd#6sDLy8b>g7>ZPy8u%JP5&70^CAk?u|A|+ z=w>=0^dFsTH;>dCW@<<&y%|(QJU_>QV?Uze`}X%FW`{_BVRNn*c`uq0)hRV9r0 zcDA2+D~jAETg+EJo$i-Uzom2bA$DYxt}uAxzkhRdmneU45MvJFQU31L0Xx16Kzw&~ zN-EKp-kvvJd^lsx8@Mpp$lieo1*k#S=-!hV96@H=Sx4QH46v1^(}qK}eJ}imC;AyP z26MX>?}Wwfjx7M?sc78%cBgJmC3V|sv{Gq7oZw0;RhKL`j`a;0{a>FHRK;v~-KSld zzG0NG{ECLkVu6RcTl%{fm9V3yIU4jIKt3z>8Zf2?|6SP(0?aKn^Rt>l|8RI4+(j(o zhHB>^z)gWL_#-5!ge~&wEFG$DMYL#yqMeVA-;ELTs}EZvm!;B4$icqqG?5tv8*$-( z%kw{7y_v{9FQlq-`1+mZ&>oXL#PkR_{x+O%ad5*QU!BR8GvF+3T01;i zKNRfxWirP)A=FDievK}J3-Ebw zf7T*OSQZ%{8BYsbN^GF@$H#nc4t&nfjk9@V9j2#);mYlijDs+VZ0x*sfH5@x&wD+ZO^!pj-w5+b-)fRWuv@$t;8M_ ziSSfl*6hunWL2uFM#`uTH&*>YEIQR#LGY9WGCzGm`6!?VxP5;JG7vtuRhR6TQ7 zC~&ZXdt;nQn_Zmsg$&cTG5Iyh(j5QvwnuMm z1Fn|;n44n%=@(7eFix&fvYbEBUeCZkj}eGoIsei}iSgOT2J9&s(de zyIaj<1?LOdbl?N>U2wP~{oj564vx_N_w&~w>KU8sAa7M=`hkSf{+h6b<^&Gc!FSpB z5T}CE8skjxW4n72t8Z~Lsb3lH>YwlyhuFK2kBO$6x6Tyf)3BKTkN2PQ^dU*0AoH|# zl};tI6CI(pj3u|Pd+#)0EHhZ~w;|t+#d*+sly3UB6np;ZO#Y+_jomM=9Bpzjd;}^y zQB~6n{Xjf&<88zLJMZ7uCmSHX0=cr5xPh(~#_Plntx`JauuSi#n3t)3uNk+z=0*Rf zWAOJMbma~MZ;_qqt0LT~6n<&hk#7;ZtOW|6=imwGzX$lH&HGUACsG`$3W0rv4e8u>#vf{*t=nG-fmLxyVS-h9z)s+v1^ zvl*lRN;jrE@QN(vkj3XM8Y{42B#(5fc(OyOPF;ZA2ikj{1J;`9hKZb$snr4h&1WA~ zif3))sB`-2;LGo8A2_5+p+m=Y8C_wMA)|=-sb-{KhJt*AoqnNU`*;98%DkOETFKyK zp^ebX_DAdwVfqkV3qn?}c>Kti!Vx+{t+z-7*U_vz;$y`U1nr#dq6v*Wcf}?WZV6XN zz2ES~0`fz5bZu*cuCZjMMx9|2p%8<2ZNd7mZe66cMfUggNhdK@!4+1iHMA+MiGdi6 zh)G3xDt`AiorZK;AV9jy$2A<}gTN8T0Nck0@OfiI5V-B4e6X}Ci|>AwP0=Hi{_RY$ zuzV42zb4GbXY!0zgGC|xxBYwEZxPmqF6A_)%0acGoj!(#M=kA{B6 zRtayxH5%Bd)hZ_BX)W#-P)#W|J?HmRXSIoiJy>;f@JZUzGRB#1ubtJ8oRBN*5pACp zBPIym4 zvh9ffbAie~e?I(N)CFpJ52Jm3`r-JTQ4dL69uOvIHq2Us-+5@ge?Y~8d{k7>17PQ; z1n|*Ksz5Ydg-Y@3E*sbGmO+yctiBLOZRd&H<1UX?$>yT+O6#$+5a<&3+-7`VDo-lv zv5D5sKf2XOUrTZo?&1Te&ui}k7<%a0e)yd1*p30?BFjPL{Le8MtOxhSf0w4|VT2gg z75PPBoJWVbc+WBdBh`c#2Vf1%|7n2qRmdYrGY;hAkSPS?%rcael78{^bh*pG5aA5Jn;K6hjJ7+m=VPpG=X!Kr%h>%pG{~s|b+lU^qsZRR4x*45 zMNR)d8zZO4KJmt1HB$))lK!E8IHYG&KULZ;GhkwvX-#|1PnNd^iEevpb&*X^_C1C|&lT|?9}L|P`1g^h0eoZ-GoB4J{9>PezCKM>b8aj9;^NSh ztxt5@YGUy^clV5h&GI~>I&R@8K1E)ciDWn!pZyg@&;3Tf6Xc47w=}Rmg9=PFQmvED zoi2V031-V*a9~nHyHI>H6p`IOeDLS0nFtT($6Wi@YL{D}_B z_4fThBFKl(ddv)VeQE%FujLe+|7oU3aKn&QZU}pZn?ZD;qUw0Bzm%^B3%MV3+n5?b z7lCpbLlNvdST%95zo$wS!`I;POE>4pojCFF9iTqBF>g*BzU7)|6pdVswP_ypbI!r& zjRtjz9HReSdY^qs|0UjA*ssW#Lx&@#jDBuepd>-$dpX2H!8~T5)jmqfzx5eIaSygn z7vRhLT$S+$FBgky*k|)n6CdZ&Wj1o4FjaH_jU0yjr$Cyw!`m}jf}Az-ji5JA!&v^~ zQK$3EyK_<5?0qTTT%o{oW9Lr(C*!z3s;4#ykUkq(`&~zwWu2rMAE2dt-FVKg^1fxv z0lOJB1G`=fU*fYKXRXf%T_4OZyfhAwTY*>OJ*glc+sCh?VEYUKK2%(>2X-r~kHxtb z|NO`}`#juQ-t4;QVrgYu8tM0RKFrX;kv;P!SAebP({u=dux)Bp%9}#gaQIjAr^kI2 zhV+2^EZML2*u+bH(O+n{I!8Oa56OwbZ$c=eagt5@_3Se=#&A&2dB-71LHb?tr3@9! zk9xg>OVifciKI%n-%Rsp=^!6vxm7>dJ|lonT0Y{7({2*o*M@}?e6;rvpLB0!?u}Q* z3lU0ecSyw(0!8`5n-+~V_R^`>=1xl`Q$7s2PPX0lC(6bL>eojX0(=A8xHr2rbR`7B z{0&f41|Pkx3J%&d1IiP*?@XV4{-o+5DGU*H3Usv6#Iex2%e?6R$EdHryY6Iv)_@;e z%*q1!UfsDffbBB__@pAu+m+WkkxbH1oBBsK(pH1Q&hXi?OfgB|47_NplRiRa&oG~u zGpVS=)oiGXTn#bZG}=752UyW|G?!xmH8BFF?r-Q?*CW8=`kgK-Zr zgudi5h=wQdSaLb7-+k?f^p{ph<)%iiYTrKl;2eY;jO9~)q#ikr@pHXJ6|*Ake`#>+ z>AH78MMwA&H>?EYW69^s1G_%m0lwd`ohq3zhM_-@=N%T8KAU;JM;{7*LCCKcV8JLK zkdJ9%?wnqCD1SUunc;dohLd#RNS4O9W{a=eHC@kg_%^*ivvc0>$}218N|28< z9-#ni-$#J2aJdp$)I0*FIV|q0=_lc@(k+*EIoq$llX-hme5ZU>OVFd--;eRdT${P5 z8b!P7vI98~>eC9VRrO2QmwkbXPJrhRc9BO4Qn7_+-H{Qh@sy0P^~4Yj92OO?8dyS-W;M>Kn+%_`XjSY+o9{NBhU?lMJ3)NK4pH_I9%c8;`RPk)%@Vn_yznBa96_upB1OA?0nU@m=NY|L?~6|IEMaVnR0&f57xDYjMI* z@PoW++G1uvdT`3rr1^94?6Xy;TqL}8dazLWINO&L!QOjwPK~w}fctIGL+k=&v^T9C z6N3%a zU+u!F$IhZs5EwnxrJ6*Aik`kY?o!Qw{CfQ4gU!;Q?7R3)pzdDhetRMJWH5nhNk`KX zLig;er041Fm-Hjj4RuLm@o(LP$8j6*;4JgI9@u#ORTiPvsOMjw9~t=5pVF|PV&5$b&7V7X20mX^o;U~*oSR~thsOi4G>)q}7&+HEK z`0*vC^H%Q$0Y3AHb*plIH~$XQ=K75B(gf!1pDT^5?rZzzp?`PI!r&x=4*%E7s$bA zC^tIG$@Sv};?5p%#=$W zGKc;YO;7#95XgrIRSEuue|Z2OwNac6LqBti>pQV03O&lmuj*f?h%jCxMPediTW5V2 z9p|p0C*7?I@kQw2?*B8bxb(XNsU*+ffOLo`SPR+N7LZ>s7AekWe_DkOBiVp1ncEnp z&sQT9Iljyyn*saJK7!*F<_YZenjC4R%shNMT&jHHs}jKt0%eYGT=04ysoN(&K9=y~ zX|VGv0{HwIy^D;-3pckrr&%l8@*Dm1QVIyQHC^6Jx*hZV!lp)JCJJs+gpFWMyY7zv z`VvF(Gn!2xoJy{v;2Fy{^NUD;Z~f@;qG4INs6FD+2DK1340)gw%jRSCspA@xtb#TG@z~ zqA9U4;FA=$KrLAi7M2e++NShUJ^M7R*ORCBt_eIJcC!xB46%qjQfo?G1wI!+%2v7P zHm6Gc0Qne2beqBU)dGAe1*YHAJzpUYZ@gewdaBHE!?^Xroe(2cHfC-N6B=W*ogymYEFfc#WrW$36=8-mADt%W;sFUhD)5$5q~k zTIo$#@Zb4s$1=l!@Yt(gcS;ZVCUz!e=w(bP2=a)VG@ez)!h?;KMnC_pPn$sS$G43D zAFH%rvVqmd{_r9N0&@4a?%eAuCmA+o1L!nXTBUj2P5qWLI5p0h#N7`9W3~6!Z0S13 z@`@>}1q+%Kwa3y?`GEYK-QeF)3-5L-s%hCUv#c4bpEUa_=JB826`1_p{nBbGi?y$~ zp#d4CnaW*^R4vocaFtA)XE$`S%RsmqRIc?4lZuM(-=w#&_+GXnc70zKf=R$EsQ1kEO z7vc<6%JlJ{UdfgEFK;A1`?~KsSL8Y55_xhw2@9J31oF0`r*EN=yhamer235YB&@gx z^0D_&f!`RV6X3&>?ipml$EH1?2F}`Ke+}0pR50`b1#&1N(FeMCTVvh#$9&5V5=y;jSqC5=r$0Emd;Xoj?gIGO zf2U1JsoL=08;&(=;bSy=-f=Tkms#*4fA+*cR-C8sf*K)cmC9l@;D1@$o_2PD8)C(r z=B}zk|E{&AH)OdF@cg|je&GmVK<^>^La8v0HV-mS;04JWCgSVQce#Jpk6wx?vGA<5 zwpT5=xr}!}r-{&gA^p{xt#)*S$Nu%CTtHbMUyKp#((vBZ~Lk;G^_RRr&C6?xP zk@8hYA~rfR=TQvmwYF8V`g>dfnccE6si95WejrZ z*PAR+ftCC(a*D5h!{S!wy@96ep`Y;5^Wsn~s z{b!ASk|DTh-P|v~+ItCI&b+%`f!7vmI9YVg^myD+KXv-g(vkn=H>_-Jt_+FuFUc(c zU*ggEt98cfK@GR0ed-8%igCL3kLE=&TLw*)NYDAr!m#LA(W7bh86pd!$1ku<%(q|s zLE^)vmSX+hlyO}#@dWY_>-vGeeQ+O;pQy<rR6&M|%_Pih zGWeME$?xrm!mllwYNo3_(`2wcEwA#XCH_4JXfDX^p=Oxp?1ANpuiS=?G7Vs&I=vPf?c1N0ACbp*TYeSF~n1!P6m?A=lh_wS68M&FNS&E@-@rp@%{G0Y4YMe zAULr5GEmd%DPN)<=tn9}oGp-xuNAC|rFIU;??iylMlYu1MrHfkE?x0{>@Yj-O1NBG zx{iSx^0O}i=`}G5Oom%0c2mI{CnzPnruQ$uy`ZWIv(-KxbME+)4GZ$ow=RRf{`Uy* z38+}_vM)y+1~nr7m=kd%c^nE)qwDtAomHtBq)Bz1l7FvSDpzcbkW`&knx}f=F)2}e zA5Lu1THxf%k-WU20`R4E7of^ypy0iKuSz=zOR{vx(Yq8G{fw@ZvPpPcRSgVCUI+r3s)N97&g+J-& z0o8_IfnNOW)4Lpwx1Gor=s$@i8I+~Wj~Ay5>eRmf-gabR6b_KQM)?|kPJidGo0ol>2@{2GV9ifiI z1Y(a~SuP4o!2B6q?Y0?o2-YYY>kVC33k3L{&IZ=hCNh7hF8{I>n>SpX!g<=Dbk%ndTixBwO$kdI;m9gOXD|Nj2O z2KdHCcrTWNXD3pwsUlit9mZU%s2*!xC309$h)f|?X zQ$2ge=(^~-F(G&af%y&KOEK6zl>TItniz{fUhrqc>#TMWzi>*s`Z&0U^TP%B9xP3Jb;d?To4NTy zW2ZGVP^KW~jGt~^Ec|vMJe8$~9Vc%s6`JniZ*x-tgMA%hXtfi*!`;D6!tm_(Q#GW$EAV11ns*lxq(wGZdpQ^2wK2TE_K# zd#flzCt}*lpqv5gG8!U~kEzXw1#I7IfUi6*lVO$fN8_y+Y~lSf!|X)9LS4ed0nc{k zq+Zzvs2T0#de2}=wmbU}#-7A@LOtdX*+2}%H;#AOAw_|1ziaUZp( zNxM@@Dz}YmKiQ>_*w|Y9y>aZ#OrMDC{Re_to8a|ld6pCz#wTvBS}A;~s4D9}R|NY85EK{!8!=svRR% zx2ak%;fAwwShw1fqr9cGhi!S4x*X>`03R*MJFo1Dw#7fNGkS)b@y-m8;_K#+`O7up zp?@0>T4uFf?XJU|RCM^b>`)2Tk)2HOz5CHdfGWKzTkDax4@U;_af$GqfbAm(_zH{6 zTzQv|dtWFaPA$XE%)B{2b^EG~)JR5@Bg`0PVn(W#ZI3OuJtH%HQ|Hd~@lBMWd8Bsm zW8hEc#5eS)?tcJ2$GOi8_1iQ&*$sOiaF`!C7jQ_w+v}|VHs@wrd4B%X+19&B2avjA z1%;n^x?m)L%a|YIm~bvxL#z7o%Hx6+T=&#d4)r} z=Df{*yd)p;+jge~`DjYrCBXL41AJ<$1Kp2>;yj}ihh#B^_}KORjx5n0-%|Dv=Mzv` zZOn&YUdPmH24(kt99`#smyC(H{1%4!&b!9B{>^7_$gS9im zilR#_S*6%B>Q~Wcsn7X!*}#VFR zJ*r?gMCVlhTvG=4`Z1bQZc#`aD;rd_XdA9Vf&xh}15=Uvt|#ICu5UgyoZeNhoAak4 zNLBGyuG)FtbVaGDM=~N5U}Bn`UArW){QLYZRN{bLpKk#95gx2@KDy>cwpixoYSdEJ z5hy+WWZx-kKt*2Fk%<+E>rTigeidOANrfMK=|GXBm!8Aut;a4>m3B+!SYpLH3-Hl# z*IMS!=36MFJ=sA%;32r;o6)<8w;dQRIVwHpXOqfU;4M*pY`wEvwzbE$5bC=>Pc}%o zEA#s?(|SzLKZ+CNcE(ng8EBaLcj_y~Qjs@OG!m&T_ zq)D{6g8u|P=lqn5C=w8Yd3;lU zn*K>Gdf%kO$+D^SjzN$J%a@rG;Coxx=0K)5ULcu*>UT;+@R?!1Yw3bBGF5&rCidCa ztYe}jKgklOl$D+|ah9cNojm&$li60U>NuuwpU(fYsUXM)c{^PJw(lLlcj7oyvd8>c zBqJfLaSQ8GZ3sD?U{@v}Q&bfdsXc-1(*yW4P+SQY{DLaiW>}Zr_GukyuG4rJ z`{GG0LBO0|O*y+PU_0Z6S?|z$+R{hBPbyW~D%d=|PR-DnS{qU+!-Z@I_&g-F%72%T zm~cNCBIY%{)5V%(P<5O`7Epn`WP8p}D~LenN87RdtIz=#l!g6dIYgzZAov8rn?>r^ z&=hCTe$pVH;K(34*uGrA`}0m}_VEF4k9yeQ-Le}WMSxtvh^sn=+RzufLb2*_Ef~(y zb!+*plIvfRQItd9cNM?A7c6{v*5}17r}~71i~;;Uz}a=Ee09h$nwI?7eN_wtt@5FV zt-p6f`@-jd;@S659C|+XD>kIIvzL@SS&y6^xwPhGM>Tr9m}`o-q2omUzdo45H{f5{ zs1L}Gkcxdw1r94tQ5VklTQ~p97Z`jSVh+r`8-b?83I~@V-M0otPlgdKg)ct2V(oDE z9!71n>2YNwlhZ=y2nH~%0rHF6L~z=fO4n0eA*;Nbc3za?YJvO}(yCUcy~HtT>fd%Y|uKc0_n4q)eJ3h;41d{6hv(sU+f zOTAVOg4T?+c2cpZZst}3`Md-n_Qv4i0T4%_e6Su2= zR5lgh%Z0Q)ZJ_MH4#1A+jomJ9GUV)uro-O7C0i6Tc=jP}W)meb<%JLh*Gpa*=y_tEW-`jifo>(Hazwn zOmFTRr!g7-(*T7}H(>c*i9g}ge0B25Nad}`FeAsXZ8}`ZDc{0>TTA`tcpO9UO-@u? z1S=$pNM1DL7e#6Fy%e3sd=ANNr@!-`&82HE_f=)zm%ZDQ9QuL*^~u|v4fz&L%)>AO zJ?R*JZT4TE$qGNj|K0cR@i?0QonE?4h{{>5NSQXOR*;2?Y?3I(%Nwb;#~JhD!0_Ee z<|C_&KtvFj#Ube!(S)rQNX#WbEiT}4{IZGNV~inpJRc8;kIC)(YBNtM{uj*!m-408 zSU5`29C;}h)#hnB7SHh^z@9YMOFGD}H3pOw?^r#|GQ-cnnncTpxE|NH^xbyXDud!< z6e>IXzw`e6d1ecU?|13^#J4T}cHyuRmIQrI@y4|@S%J6pA0NCoxl=P69*wIf%?U#b zG=!)*2#b+yMX>dl@r^eJ;&w94%@O=E{@Xj`Kikj#(8y2UlOQb{Jux;7HSpmt)^@;p zT|M5%V*NsR_6_v!qYCj%qC~#EiHufHX#a>TTZHGjLE`l3cjlXo_z!dHARkedZWGu( zM}RNMab(as4Occ8SxQ5=#?s~d%e!1X9K+oSrxZsh_t-_>d|KTL_%v_sh>`yEme4nK zbIrT4NtGLeGB9yDzIDJ$xzIDI`pE7|q6UISJ76LDVYRKD5u^9qYFL?Sxt@LL7%~1A zjTA!3Un=+$vW0`_(Y2q-D2y(xM>M1oh^r8FwElhk%AdgR>+J&YwJaa?kKM!DWBQ&$ zy;aG>`J=UZIHV}nX6X1Q7YT-X-I2GWddoQB*Iv&ws{6b;lYLJ1L6}9p$0zENe;Sgv ztN`khB?-Is_6Y9r811RO0=mK{LnZ)^S7gfeA%I}++1KkQx0Tb{C~HT{c(?KL@$qXX zaz$s(BjNa2Nf(1SagO!Er)MXW~r zh9DmsHy$O&C z7JPcn&$(5g%;lC$=uPCVq+3lccKmtM*Zi8dOZq!!?UfgA8DlN$&W8zp@qlHl4uIOW9|U$Z(nxq5mXbIZpWk-AM#Fh49809rQA6tE93y=@d6PgQbUogPOqAz;mvqweH%C{1>+9Jlw zTYDcJoZ`mgxQu9(nX2nQl6zazBf_E;g+O0QXG-9T0HukNH;yr8Z0gATtIJ#w;L}b{ z-a1HHW2MuS(f;H(3p13uQM#FYNK}$mL-L$olTzV0j>nE&sve)Xvp~v5>(I-Q*%&)J zllD5R)3x#}Ok0o->Qg!R@6TL-Z-GO;__y1gL)m)$D+KpLuSV%q!xL(6iD@1hc3s-^ zaBjNgDq*9~$urh5Pwb^CJnBQHl_j!cXH>{^!CXj{M*yGNJ(j(r)heR&W(o7@FjteWj>t)GZ*~@gBm^$GnO8QoAE45;@l?jRpUW}`CLzEXfMyvT3j;I3oW zzLvM$d+g4ondZp_UTx`?I8@bQGU9i7S5RelcxvddM@M;fxDHEnS3wcR8o6>veIlFB zAL>|UfKQCwFsAk63s(p4gbONDO5UIKB)?qarLa;CAjF^R(}L>wo zWO%OM8glu}Y0)CbZjw;U!?+j7#}ms2{_|G}@Euf8y!4V6=EmL-R;gb9BWh)ipiEG= zeLiY^jac0k_`3=d)=Tm|PPlyptS!a>w#`Oe686BT%CxilaF98g#v{Nd{0)<9=NN60 z56;~6YoIO(ZD8_*iv%BUtqx zwa4VXARm$0CHQy3Rsno0f+3z~6h@`K?Ea^h%+%K+J)LMhvk-i)He<;$B27F|QY6B; z@eyxz9s5wZSn~t+**l_s-tSq87M2^UVKwFfd^~uxz4;&8GN=EbuSVMxNZg=!P;SId>+4`zZt{Za$) z(M?tdpTboPZFv*3bMQo6@CBnIBt_OK$jj)5v;0}cc*j!X{Hf%V5~3}lAU^De*YWML z-_h7AOCmlxIC^|H!U6cS#i8n@;zlwq(y!}VoXc8ujfTG^c_&^1ZT@lmYwss|EPrM4%{)zZ4g7XP={QZjXktl=|oT)V}GM(1R{kwEky5y`da&uFHb* z(wm+4twc%goSem1e$cp{G?W-_Zj(e5-83i)DGEKiTIb9o{3g>N+T;jg{VhNhitC zHPsOb@-g8y6M~&zE5MfrZ4f9d)J}E=>DUFO_p&Tz&L9icZ{8;C;uXo1m{L!Pq&P^f`Bs`NDr+E1H*{)b3` zY0}Z_^4VwTGeCjo5+?u3V)JbTbooe|)4=q;N;52uo35xubxW#bEXemp?Mw@7UoXJd z&awPNZ~NVx6>=})#%bn;gs>YG(;{z*V<195R&~E4Y>(=_nY7ZKDqD(r_bxSLZ&&j4 zw*+|c;!=IjQm;?L0G~aFBr1b7oWK_zSKbfjA}_gMzw}#L2Koh8U{yc+Qu5!a^3Bf& zsJA<1PW-XB!?314XG8axA*c2zizj}&=$ioY(eDqOg6$gx_;#C{%@Ivx!-To9%GBY{ z^aft7mhNju+~>SJ7U>r*TZ@-#m|HyxG&{hXxJR%-QCK9=#wF%5sr{9}+vpy&5(Mx; zVD^Q5kHxOh7YW>)uh>o~xJlTSk2byWut-mQ_PLKM5bI}WM9TbPCHDF}w{{wGS8ZRXfAINIP#bZ@<9_(DuC@92l(7e;;tK8y4Yfe&_wW;Te9>Q?I}?fdCU02tNQHX zqiRRGKHcgkqI%Y$B0Q4)I9sJ(kc&ZMvghY8|I^!JEZzg~Rcj%p>Yid|=u$$sG#bsu z=AC4X%3x(r_$epLKl^?V;qJnBlqDe5(|7o-irTeUJ9+9;dD`?We3X=t%0JW3`Zqr@ z3-Fi!rT{*T+C37E_-5pFzAP+epK&$y&}Lc#KwxH$zOq{jfe;Sur=Te|iYZBVO{N9u|OnIMQi+VEdK;z9dMBT;HK!Xene1U1OpC_}435#lvcS zk=_FNgTG$Z@A%2}zW9bLaTu?z*y1t*YlXgkl(fWu3KeSJ@Zmc@*2 z1fm$qQU+hXuOiV|kYb%d-Rryc8;zX{MAxWAn<33nM=&y&Z*OwLFX3sHOpcYz zlH=~q{{F9bNaiP4*hCXCeIf~b-0~%bPPF`wvT}%1GO2Sn~D*vrdN^E1WeVYKE zi7e+>cyujilEri)DWpKqg#Vs}{@{Ly{Ok zd3RE}3VBwi#!zPf?~S`wZV~U%duya#=;I(4OL_jdS=hm$OjYH|cKCODmJ{lr+>ML` z7W?ZNpH_s*bhyd1?IvXQ(V}x#d6qWaSiY|yA3GreGT6S~0N+CzCmbt&lIL>g(UbVl z94urFk6J>P=tup4RnBlGuE_5q?Kt|038xz0O-*sx8H_fGCIfDSI;J+gx+zY_2>-jh z@}KGJwH6M&($P@TtamaayLVoVSmBg9JY^A-s&M>p&ySx|e(do|tmUe-T?sVPtF}J#X#3c$l@W6? zC`22+9k!CTFA^L_W4e~-dp#)Z^!xn?&Z>&sjQ?cxP?xD6B9a=j8yagPCa^r+nU?Hh z;NiDe(-DqsRciyGraz#G%^UAz7;OTgj$xq1)*Xs>z<;Bz1 z1ts%D{+`W1jqFtHZV*xeJ^Y%_Y1tnvYIJ*eGEr;b>ie-`8*4`~*{~|c!NE9$V)bFv z(NC^C#CtI^?Z3XhbY^#6Sv?KB-)S){R|Q-)b6+2_Q!=mx8EAju(SKk1*$DC>V8wy& z+XIwm@@IDh5k!mW#rz3G)EM8Qiqlu5(#07&-ScjEA{%AInWw}ii~6xMipj^(x)`CW z*FVIUbd7xz`lCmSc37i40k4;?qxn|LEqMSA&m~KL%o4 z&>7CBU3mXgd>uihLi}XfPLPjNuWuLo%K)#MboD+yQUh+fUy3kdDF$l3oM5JV7r1@Ni;Q{LWXEZ74y z#dMpnFeTp7*Mqd#)D>8gutCp0LS_ydUQT~UsZUHND$PsYh6iJbPj$-pKg(DXh`qE} zj=MoV@*mRRpT0c-_$Yt!O!^P04;j9hTZuz7VWe_wiX!Of`=JD&YT=-3_p zDZ)omYuHY#jYZttLugI{>)o2Lr#40LEnx3!Nu6!=xF*+@`_*-vD|NCieW+QSPMgh) zxzK{7XJ3WbwqRVR^I(IpUm~LL$ICZEGt_l@C^J-0P7Pd2s9O!aARoL@^l81)WO5J803csWsUMWC`*M&5>%pRK^zH#Ux;^4W4#iy>6 zfdTkz-oPa!c7@KSARejZ)*s(~v|PPt64TTz`8@OYbbwa-cns(AgwS|Y!23X$5+s~n zfnA=BuqEt>a9)W7B?`w;kdN($#T&4FR{)>%E#f1-{nJnj{-+G5`~s3)A%}2l z)>WdS%I$uh5~~*N_d0y02%C&`u2CNzlBhUzRdeDhn-ufURz^(#K8+s35ri{K7Mt%% z8Lw)2HLjKnrRUY-=F#fD|2_R@o5*<~8)2vg--CIvu$)CI!jTx^C4Z`}sNX80&rPvD zI|cGF3H||p`V#{2f4}dcs_$81)xRVJ>!>#7L(d`$)HYI&`oHOB5OL}xH0jVsfEX9D z+uKM+zG#qZD?WpbV(hPGLvAx0bzH1Rb8<| zjHb?R!NhZYUToheR(l!C$}84U_xf@-7n5|A+dsltO)OO(P``oS`!Ngh!Hs4aft?>B zz?ay@H9~0h`>KB8ip7tB{EboCjRY2=+UD7~ivuIC)h$<`wWz;|$QJoz+rdSqR@XOs zNGucRzKS}6d6Ln~Djh(6p_EhR70QM}V)ziLT-h8lu7&&9@{=6xlD&n(&%QsBt=;Qi zAJODI^e)sc*1okEUPqMdpOO?CAV~)JF-$1UgM0+(gy7dFGQd}ya^B+Q^qTUtgy+Mz z0PYrrVsqhlyfIb?k`g7PN_e#_#_6B^+LrC7MLsvF9~4xh%r^a!V#hUm-U3Q$WB4X`1fL`vqhUUWZO4%PEd~cu!l{%nq_Qi zUVqqZnl8Ryg%-u}?fd}wAc<$dKi!WB@U3wXdDptJ=j}KUNmEK_J{&i;p)iMw^!E5+ z!PzM?hxtwiZYQPjKA7&2taAtM-iir$;G13yo0XVPBnv^ZkOA^j)LX)}Cs>)6XK##6 zbj~Q)j^QWj?|`|(v<`pwoF5F`KmAjig4dbe^{FQ2Um!b>n<&JWQCnFNsxxieIK>&S zf_zZ658&TzfeY}NpjDou?=PSHcR?uxj8WI;F*}^XJ%8Vxd!&Nl_QOZQSJsY?1$!A?a{km88_<4=%}ZX~@7?Dq=+AiwEcrd$Wa1mA%7H?Sqt z86^-A1;l!`59gl0s1=|J*x8JEQgG-fx|jo3BwTYozLrxQ$DNXZ(556_;}aFpItO-7 z9(-43z(r^y`R-NnqT0@~)|1ns)wtP?(wMKk-m}kI=;r5_QllHaW5np*c%4lDm!>ra zF?z>Gb=`ig%(D61zd%0LX7cY~`$zyjAw_mkqy2tsv7wqWOaVsy=_ zoQMM`6t`c5Fv9q1q@}~38c*9#aud%2o6oNrOdAuJ|FE&0aY&$u zKF%^HUNeGh650uGLH@ga;-BU>KL4DmqRlq!c$8gk_|}qTk+GkpNBQc(bDX{_G$w5e zh*tz@Bi7pME-mCN1CxgTD+Dpx4gu7>QN4b-3AZO zyCK2vz0dh=uTSg{^D~4kZ+%)c4I`JMnEO!X~*#EQadu$gLzYX#k(^12K?E{`p zHTjL{lq3Cds&D>(Yi-Qd#e z$uid`u4bwXD<7_J!0uVaLMFN=8(|CEU2RCof_UR{d`=@ql9S3KQVpfgzJ0&lUg+;} zK4h#=MTKHG7nV}*6ba*(KMM&7y8M5X-E~k^-`h7}Lb|(=lm_W8>27JHMY^R+y1P-j zyGuHyB&EAkQb6JrkA8nMo|$)^!;F72!{z7RYpuOk$v;A%4DJGatR?(oAp0nR^6MZh z@Mn=il$I*iYKv3Df-ciwd6+*SjZ0r#OJgD zIfziP4Z`RTw!k<4(ORwJ&PbJgcY1|DvD*(BTDNq6SC=1+bqBX?@Z?hmN3DWL^@n@2 zF4+%@h@85X1Mjb{Rj@Arb}QukI+WJ;5a6Rp=T!vR_X5c0*X{v1AZlk65RezkcNBRU z7&oB(xDQU}jM>|E?**wtvsRS)8k;g9Nl>kjFOZ@gk!@4&i_E-46T#UtmMI%Kp!V}3 zozVKN2&eN~9Cuj+R{7I)$@fC;45Mog=eWN=Uk{GyR=Rj^V}AdTI`-T#rT^|GT zV~0h*201?(p!~*Fe5P5e3+qA*(n3cud?NX_llz)vDM^z5LRs zkWW6>R170-$Vozp&j{;;IuiUkar@S`g=_jsTZFb|M>Z-kX8_-`FSi{a`(6V1sHF$h zjw-+HAs&5!+<g02Bg>?S zpifmlkupP2Oc1lb2GKT%tj13%`MT{2;3LabJOJ6p2IO;4{N6u+%aC@hGl~PX2(O|O7?N9)mgI*I@8yShW#lzGv$O*G|wmZdSja2gGePkg@D z$(6L<7EJ7m;3Ve$gfY#x)u<`sUl(i(|K7b)C7#@fCckdmyQAr#2Op<2+wj_S4tGJ9 znn1Y#c|NDm<`&?C*vgCq*(U_#qi}ERT({bkWgBQ)u-{;*J(}zHvG;cX zA8Q*b=;N1HK)$heEy@`3@BwlT(GcLuaMzH2f{0OU(HP&qQsE;!pS?dbl-Lp^EP%9t z+O11&M`{;*SwmiU^#%R5Apx@cLm(Vbet3gN-3e&0U)cw`V{Pnt?TV4hPOuIp%U5N> zLZ5sRW8M>S;!Hu=Nb5zERWp~TA}w%9VutrRKYU{8_!)ZF9{@gR)ZJc?^OFYhy;p!V z|FrSW6ZYGS(;eZKhJ})#TwEO2$_&*xIGn;)QvH+t245Ki_d8#il2dG3sz=o$RH3T8 z_AJ?O;vJa30)BtrJN1$fL0b%chLfOw`r5QtVQE-kwmiKnkIr7@$rpeaZO#j&GxR1p zns^&Ebkfw>@UYF5*ecV$iD$)*&6yIcKpFa&ziH=;e=0d+_Q6 zY0Y^vI<4zrB29TawO0n;GY}OTPF_{L?QtVatWzbMH_+fa*ihIor?Hn&{qdOc-8~oh z?!P@(e=e==;SZ0w7J)MY{E+2Iw?{htinTM=B)?C;7C-QMNr}heEDVnOrXW@s3Ovw2 zCozB3(m(BvxuS9B02cz_gN2-;1KFnusCoN% zA0)ts`;iv(-Hlp6zFn{u$-(c+#6;YO5hK=L$vmkMyKXM8i3t(9g-K*Hcu(hMQ`)=i z5jnc73v?}bqii5}t41+RD!rB3;f6GifR`5tex%jDd*8_LjcQgui6YQOK0$}cF?UBH z6KWm($#*knWxkw!HB$1{sYi>CT_1%Zz}6)`k_?L)&MwTpD-9kR-~+dK3HtX>T_9h3 z@w2s)h&|=QhMzDpfkHkk@U~|-N3Xri!s&YW`XrMMURJJeqFU?=HGnDNz$gz5 zp6FZ6@@%jVV|oSn^nz39>D+3s=T$1(GU38M7h*&OYRfd^s4yYFaVS3dN+9@~-H(a( z!Nx;=7~Pf}_Q8RL-Mpp5{;4jiH;zB%e*4Eq)#(HJ`$Hel`0Pk6_;w~))q?9q4SG## zgdfl6I9uedN~p9D@lld;DVvoUe&#;Wvp1^9-lYhMuPlbEDCq);SZ2h$+}J;-wE%B_ z&||7X10R?^*7s^)>KKIim@JJQA&~QSQcP>J{K-eKt!+!`GnQ>9HHh8dzHGut)3tBa zu3)ayMP}7ya31Z00LYK5eZ?N+=g$-WGvATM$dI;u}Bn+c)?%hhK>)O@GnT1Zzn5rDs8pZ3KG$khJ_&j}v_|g_1sM z*h1h|Q`0i(X^_0`aT2fbe)3UcM$B33%Prp|VD7UDYAzO~(=XH*BVcDae?8{1J**o+ z1o)hfKZJU8`sWue9>T0&;ln^haGn z(Z(q_l9p`EoHMvEQ1IAL{rz5NsG(mh3QlJ%Z+(5VjLPGHPfuR_ zQL0)rXSvF>YvM`m|7f)gF!V>|yq3UYpqK)$mV8BUKZ;wb3qHPon9P@Hkk61DsC^nQY)HnMQO zN35YtEzl8|zuMX-k(~{gzr`ckH@a$B>=VKXsQX^e+VQ{n+rP^vTyt6OA*hD=HC%#y z-K%G>gS67odCh4tFpuU%o_x{b1k7fX4$rn}UEbNWt)0mwKpx7Ciln5a%&TJHej#qc z0{HG>c|bUQ{?GCWAYQ%R$S7xWSgZc!`|<6gfm8zyVqEv65h+R2RXY{?f}K71?5cGV zw4gMY6(=gh2=M%`?X*{wtezc_(O(vAWPlH+{njew{S}N#qbNxTLXye5GeT3ak{r`T zi)YXL_w*QD!{b0~{-nQc$cHLshItQ^O+=qiSfmDA^n}vl=RC{WH~=2EICK%n@i_tc zUW!6j`%CZ=50Ff{Nx)9$Zg^uA!upR-wld|Bwpx&D+^j@*(z@jQB(46wRE2F;IY;(0 z_|h#_w-DN)(wk-L7O43|K2*~>CAA&Rq%JYzpHenVQfH4JmF=B75ooM>iZAgc|F%F& zEPh><4Ag2M*ZK8eT5xO*#m*7)S87)$aHv8efR9E_$Qoo{Fpw{|g`sh48vc7BmDPoC zF(sI_Rw%16RoG)Q|G5}c+?`vWl<2phSULaoxf0Q7UK_#%Ut$H}+jec9oHr?hj)lO> zCv-f(C*gi*L#gMp=E%4mhumV;Ve5Z2r+rUzs{Q1%=jcz;V$`9G?++~Qw}pFLki#h@ z{G{27F*?|^vvDaNP6qHXj~CQ{>L6=1iu?s}C_ z8|7|loQ;+4+BgJPBBOsFuBfV;@vP#NSVQ5WAGWHg4TT>)S;_5HoCe|i&U66g`H?#X zzy~H=8w;{83dnbw`MM=qWUpMFl*eEVvgW(TS$4@mzw&GxX^RF`OvN!3wA$IUJ7=Y% zGpuZCjlE-;Q}ThUffjTY{hPD#P66QEISw7y0}B(~cHy6c9bYvqKn332@P9&%4T!U? zdU(n&SQdkDC`+P%j`u`k99cZp@8bY#SE6@jyO3!KN>o?II?~2U6LUisnqa z3Tz3)gxBO_&i#_cU1oiVo~I;{>Pfg|3gM`h$n*C-o1V19Y8aeGLoa9nWRFsJN-tYosS+pL{aUsIEJ}zC=U)%sY&@HJF#k>mCTX z=}P>J%9-LXFB29_5AZ>T4uNp^=b!EY_21d|Vz5>@a|yhn|a43*}JQ?7T?0Rv*wfd#2L7*Uu?R`5*7^*OwDpD5NM1 zfdzs^{yKJ~MZDl2^Tj;)Vy=C~xM@#3xv66~x&{Y+F{_c9)}wP&uXm+yp3{hMZ&h}* ziL$su>AnQ;r~_}#L5?pKD8AjjoU6sJrJ{{-yS#GJv1Vb9EK_@@nuIGKdxO2&=~vZG z%+xZSqd3o7dOF^H`r>b0r>je8@sJt7~X6Ow6clK|Wk*1+SSpYt^&@s?` zX+S=vJl-L7N?AM|Yt;Q{N=v$5J7r~wYkIKNZqOgP1E=(;4XWRipceedpy)3RU=#8f*s()jNk=*bwL)8&&K590ZgId^)Wp@ zT(ce(VV8*7d_!1f*!3~^;V9xU%ue&r+TMRzRZ4-+Rw zlE{PFIwq9-?M_Qfsz2&Fs&##gk|sC+K1<&m5JuO39zXSeA3ug+RD~;T@p2Mq&`rTL*_0Yf7c0-7A_UKy|4!= z&-(C~2BV=^Y=%Pr@=%-a1Y?(#q6H(J_WYtOE>FB!lrQ(A#2m4w`lDRsIj_0~0(1}( z(%%r1FI?nv5ssOMaRYeZLAs#tP0a_2FINIg4DG$&53*3(FjOxJ<;BAKm{I0pbi!qc z2@zqFJ?3vW_3RBhQgPocp#%x%gHm;phtxOAeO8HJ((cRdVS#+xrkR^m0^v->+bZ2b zi=XtsT^9YkL)%Lj!4Tg*`Kml5=h=ilCkj_hd>k^Fc3R2s3QxpoKF^WQc_V7DYJtZG z@L>;fY>o-RVQS2$)tbe zfVuH__;x%6_u6WM_k=n26Ath2je0Ne=&UP#0)G@|66J75NXR3o$d?*gCP!nm#P5xE zebH5}%}Q*k21e^RA9S5+GP%rjh@n)XO|yAY#z>@`bh`o)h)V4x4_W9=90 zv74Vs7_@fxw!ow7h)OQWOSx|F-Pb|BrIE+pb`v*z&)w8-23O{OFK&gA*v~Bm&r3u& zu4iD!^d1mJ^=(PjrZzfK?@ySVQD4_987*At$2M*2=r z@W#Bp3>33jCimfv6i3Fj(1r(Z!Bcj@Wq$y~B=hIGGn4Bi5qa0uv@PRh4xo zsyl}&c(dm+PfulV1TWwdzp$%vgu-}WKz&Zp-uiH{vTOIhm)pPH`x+RtghBDF8N6A8 zOOtk&qDb4#9vXOxGX2%$@5M{(wa{YBB+qhbk0XQO${hAvuG#IR3|=apt*;~H4~rBb z$pCyTOe5SN`v!n~EQ2_>)ImXrxX;4S^~j!hgFzN=&J_in@r1JDTIyUm0xk#nFD~<*mw%pSFcl8%yf6nqM9$+te?Fu;lmJ$dXrZd|42~Y)j8D&*C8_ ze;UOVeizYM`l4hRRpv3w0sHe0k6^tSCl z8p?_NUR|XQO5K&oi>`s^LoKR?*puO?v90#CeqfND&|aVh^b4AgRxK0vn~IIr{*QpZmWZEk@cBuJHdK;12xuof^POBe8_nC zXUOJe%bUntWk7se(paEx&GGyKE(-rXE;8mZVk)b)o+q(I~OZEMA zuOaxaUwHcW|NVI){i)99|MHYR7ZP%C{N!jyxTJhmL*E{jQmd;tz+s(Z<~+08tLch$ z4n};B%hFk5q#L%sqtcV5?Uz2CXpqPBxNUp#`YYIfyuXd7S*uv$zPyDMpN1v*Y7F7H zb@ZUyO%l2>Nr%Dw(_e|xv3|!rBZ!C3r-#gFJC21Im=>);OBi3g+WCD)s4GWQ1&|)} z68Z7}o%d(u{1{Mm-lYdMlzo(;=-6)8H5O0WD3)`e$aoG>XdylD!3fnWQoD!I{6{UU zwbMA|4gV6acTgEBB3vbz$h$7JkRh!V;F-U1tncn(ikqJseoEtJcSB!&%97J^Vl7by zC%^yrQ=!Z9TisM?hR}p(HLuk13aq>uz(*6GzYnr+8puc8 zMUs-$635XKCn>g(wLp7w!rkq8Cu!e-YDT*4(%ZCcDK%8D@W2lnuq@PjEk`fjn@bP2 zxVT!W{ADyA*<=(bKdyl>6||f?^Q0g<(JVA@<;XL|H4VlZI+&j6{U@K~Yuu!{=83sS z^R;>o&7ozIaNZ^rl>YfW)|Qnc6B0>14SO28t-x84TS>$^g6u4^$?8DcZ8D7AFOObH$JAp3TJd?zv2p`qkTsvE>5{@)Z>?fW1XAT=2q4d=p$6sLOj zEe=#xh}Oz*TzUo|oOG>R(c2wtxL4o&72))fw81YRCcz3!Sb)! zOeJEJH2SCqC)=9egO}KJsg&3)FNP7v7gZ&vZ6(TU*Ltd-3|t7&z4lekBWRl60DP2> z8a5#N_JDjlY~5D43(w!njqYi|!lObz-WeTiqu=IUwsAJzk3^Nq-!M%JKD8JS&<%<`-UTG@3UZW9m5M`6B$3OWW5*HGzf9;I< z^~2lFBS6FBu*o)JCNuhT!fBzcxfPY~w0<#~;&~TGiASvQpZqKXL2qA9fP8y0J~}}% zD0QD*=y6GS+{PhB-h79HX-nM<$%~oPeR5ExAck0cow~6rj3D*KNn1=5 zosP13bOHEYnex{!=(yCsd3#`fh>)Bct-8u;@0E5|!OO{v$$Ro;rZ7%<#g_&4du#vT z4xo47W_&R%X|G56c|z`%Pai6c(iGq$@VChXIlogNU-Hlo?$hIV&5&+!LaWY-vx0R6 ziwPF|w>Y!QlRmv_XxsrGel6I7OGZ}2(GAe<@lz5(5u5+8TVufUDliZZrx_@}tONrg z+tp%OTryNdEUQm1SC-kE=5j6h?9Z;EpM3K>=mp-HxO5a@W#FIVJc8o1^y|?kc8&v8 z?Aj1TQMs`!0X}9{NEDEL=RiI;Nwn);L|aUP3WD2UZvOAjD_L0?k^* z{o>o+_0vINq}07&`@QqXo?Ep$#zr14ehVH9@8J%^DIjNMd9j>PiGwfYN3h*b`9Hn~ zWFgSIce8)H_jGTrSl1mg1pz4@JAA#MOEuk)MWxmO9xmn!lIp`#EWVBRF_h)UyNGh1 z^8$J{aO!#t!A`;Hi{BmWJ`s;>=XqV&m{>ztdtmO0)Hr5z(Dp2K^ zpW=J{XloJsTv*=lu58vK_rgNj>O);wINSOF9fm1vcJKqe9U#7EA{DwI$9D}BU)k5M z7Q)8e`lOylavjQZtv>Zvj41eW0)_qbdH2!clBCF=tz1+-#62^*4cbJrv#w2loyVzN zg6Syt*?r5TjS0y2(S+&&$AmNR2&|EXk0LnD)iE9lTx7tsrZ)ck$)_C9$W*n{dk|sb zUGnxwf=zvKtZiD2!}>MXqASxDnB=GMxj!2k!7|UC;k{^!aCa77FCMsMW-1=Q{K9X*?qe!D?*ApRjghv6BjF zT{&MSnKbfXzUW!=r+i4{sm_%TA@j#Le6oS^T^15+<;atdFkZVFO^~%V#i#_4_bnlnX~$sgZoAnX(g=&6wMXa0 zwiCd|@KqxWWFG?jzt7*og6eRBv#t)JP;|m$_w>QngaPUhnTUlY(2!$+e70s5M0@nBL}pYNjpM4l`+bRbN;i!3 z*adC3zu#@iu*xol6}^8Q%^wDy9xx_Z5L;P*>_Y+a zMQ01!?vZVuAMeL^hp}r$8A=iCOp-0M(KXQr6gfL3aX5HRV0Uu68jJ1t?#-Y;gwLql zKr*0xVJtMw@Q4kK0rL6Qd^oQXk&vhg6nnX}Ij?Z}J+9A2&(jmG_8}h{$YUy%LSs2>83xrpHYrzi)W}e8jS4pdXuz1?1ygsJ?KomaNoew+lWS zGVX?R4X3Qk!LZUE1YbIDG9<8Dn;V+BF)CeOmx~J<)Zngd0E@4&4mugUYyIGYR&b`{*8{nf+k6Z#dKN29HSsAT|VL*CPH4L7S|EV5%PBwST*?Z1r<*;KY zor97Gz372=so1_>Prh}}yV<@GBDJsD)$B4O4#b-g840yR2J-0;pAU;wpD}Ls1y#!5 zEyeAfuZ+~LLG>>MvEn@W?3crTLOQ0K+AZgws#YrI#v6Kj@<-ErgK|MUN}fs0_WJ4X=TGN3@Tr%l!8j>#Tz{O>k|N6!)5m&#T&4;Hz3- zo_rYdk>M4c_=#Uq!4X3t1~m02m^=;x?R!>~c*z7YvwedD0Y2`$7!W>A{AoX_fP7|Y z;a@BrM@P4(=}+ltI7)9JGzco?LIJfUtMsw#7EaKND8LGbX{p>Gd?+NyK z>ArCjYDLNu;?^C=7o@mf`guLml0D#)|LV_2GR4IM`##tF+9t%U+9zLs^C6ZN4TV_c z(Pycso8FPd>X*5v>B--+_ALW~sb00_2LXKYZ%sg$I{Lfu9jJe3_)sd==IM}jy-Y>d zkAj&_L^SWkv{yd~t7x79#nU8X=&#&5K6f5!87#EVN#mxt6cqQW)W=|*#?_)!N^d;76e?9?gZwSDLyRHLz`$7klp91^$geoVBMKFfq`Tk$`{1$vM z6(;&T(y#lq0c9kPvZkS|6LM6aR?xLCpN!tb2?c4m^PKuB6ZqOLf3Ie}2L6bOYyL*}lOyoaSB7&<2ZvTZfs2*w=U! z3GjhEUiX9i{JjM7ZB3(RvisA*G7>Eo1e&j%3utrP>(PqIh7WVEQ&5*@g?z~>I;nAdGgXESDwC(R6al^5%_E;NrJHHg4q zCCm;yT`$t{iQ1hfzr!GR&-8Y)%AP9cHDM2*E|W!mcLQhz+u`+telw7mYa*wRIEi2(9 zpHN=Osi6dX7iBxXD{j@8;NrZ6mlH2+_H{BMSb%tA4zCRQLWhYPla=4xn-vv`R$5An zZHFAZi_GJH;!UT8EfQ%2T4~uSDzYIhFDz7zcxP;e@SL|hrGrsGSe+ICcmx8JTOjig z{vBOYhn}jLh%z{JqU@|?Q};4)z9NQG<|zx9A?msd6xV(itB+7AXov@=+oqW@oDegG zX&!1encA&W9`H7U_QqTrh$pvFY{`=-)wrjrww_&3*>Z$v4_S+DJSrP@2-}rqP-rS21UYyNr>ZJf)$&V@!p1wcn0i6maCQG|XWZvI( zOXv(!F0JO9VXeI&lX@^ zWmZUE0P$8)Fhww8gQK-~J5=62Os%<2np%joZ>vsZ2Sq&b9#kGYQb_aFX{1a%&|iP* zx&BD8i&peq2l8wDg+p}<@4GSp4-+Tq*VNIkUjSw50qNiLG7y&!tK9WdQaJ?(b-NWO zA$ZGs9l7SmtYM&LOZBvywg{%5}*S=tZ=ha0pjql%1 zKVCIldWS)6%5qfzc<#vFppRYBfW|KCJ=CnjA4Eh=m8EbIPE?6RHmJvy)jvwK1mc=; zR2jALpm))2zw6*0ujG&It=bbzGx>7(jZmB~$58xwn!iI2D83oP^0J>N&-AI0$edPJ z-zn?4i{__HHM8($byPgXxBrgS+4SDclqkUMrd>}^F3iK0EabB@azeRtXT&+vw56Bmjlr?~l@z2kx zl(lOx#UFHlFkG9qHwY{o{op2|7oA@X#4G-SfYss3C-sd}tWj|RBl~Khu4y zLGy`6OB;Pozrpu9Umu3CN4j)Dc{)*1ZX+|8kSx1+eU$Ohr3S#`x*H1snMeFDPf&ox z566*j&eK=<9F5-6yQvB7GxF>ZlWZb>U*G~U#247ParT1Hh9QjIexCh96TDpfnCP%* znR}OW(i!W`|6Mr!w`WKyrSWx(#$?M#T1v_xiC{nnCkfGI;%dgPss4T9^#k?gom1ck zy5gnRn7qF#9CJPRqzdA(Ap_jxV^ak66jLLBXMq3#LeKZ7Z4vyJC-=%vBQ%9$sa%&_ zhf#K{#)pzEpD>Zm>mNN{6r7=E;rhjmhD5Fl=hFy0r3alxe<4vZ=+4mrCxCYzlL}cy zjxS_KT+*UJ-9G7h=ePBTN2yo=!j7XqJd%HT*=CM-6QOshRw)-IO%RlVaxP{O8%;i= zYc?VlGDG50L_=_h{nrE6BeBl8>0z;DD)VTDCSFnpgw~lj@bISp+c5n%Jw2DTx2y$& zJ(3fXVt(wnzP^%%Q#*y};k+LaJf3(`F=Ag_bn%UhqOxXGqckz7N-npWTflcOUlAE{ z^dzW%YXPM9!h=o%mj60WQ=~v=2^q zi~NpSJNcWip(WOfqoFM}M5Z!3=1uKtc~%xb5ow_G2DFG7jhsxC=pQTmIp{Z1cnCZKCaM5nnCdLMW#ZF;gd6Pju_EKvi=3149R%}!~ zh+Seb2Eojl@7NtHN!KqEVIH-IN!e24IVPw&rLtq9Pl zvt@8r9XkkPe6I3iZalP-4Tkz_X|~Dk1~8peoLuE~lA6zgP%mB1hTzU~bTG$Y7-l5p zQzpm7YGu0i%-ywHtN!!-txh?z?Bm|EWSFV|Q*7aec78f={l(pa{EM%gX1~8GU4Awv zfsE~QG{w53NOv{xz=@r-Y+*Y3l%`SVM+qe*0oMcYk+m{`aNOCS_!$0;?;%Pu_HL5C zeQ%SME*Ify>A8T#yO&Ld>nIWAXfH6EBb8pN@XQmvULS+uhp}hg{UPz}OQox@ZiaFo z4iy@0LIDu(L_izT9=7;>(t&#^^w_?j{?w*ac__!Sw2;u(r-yI!Ik}}MwsA?GBXcE! zGL=&kKQqS2mzt<^61T>MY6TdUJ^&9_MHu)09^W6{%YS)&#n#^UIXC6~r!`8nr8r1E zdZl`F#v06d=V!34)U1Xj*k3DgZGzA!3sR`txWMd(Pu6G;!$NO8I zgdJYLt_IEiiKX{^z9sA%r;&42i+n{S#`c)E;uEh}6b1?d+)IsBc4^PKO<#u-cZ8tr z>N?{3UXCT&;^5QvAKqER4CvpK#DS_aR%l87dcp>_%Fp9on_R42A2xFmip3$VaEsJP ziWrufT-x`Cf?S6?*m;Zn5)<=#WodIx+vuD9eBETf=&umU|M~t_C&o^0ijwHB74ry? z*AvF)y)-fEbUFv?2RSA5AD($(%K}V`opYOTj zz~#+MED)Y}?F{jC71eUwx;GCMZ8^*Jq-g#PI7V>O`y=duJ?|Pqb%y~wOm+%!ka-;c z@`$%444K4>F~-imWyJcTy0_KvzsUtBMfTRp$W%n}7+ySzh_p#=>m4Su#BTlE>GH#{ z%;!1t0iJ;+OL(^N`yHV4UO0X4?735Zk0+Ks8>p7zUN9O2J+TOgMg)rx<-GVP<_h!9tS05AIIDm(Z!UMuhB!3=0-hX+=(me$DMCI>q z1|IEN?FEF`QQ6_dV7_rS{JN`={>Mj1IbB1w0cpzvgtI^qo2ax`8Z#H+HRkxpDJGSa zgVoBw#c3DN!l5niD5Opv^(s_!I9n_e4rU^v;7WxbM(BwLscnGIYjmlgZ^BcwM;w7jVKXj$(|!EA$w>f@9%loD38Oze{(pH*BSC3|2DR<*=>E7v6KtM-v*5k@ z*q$y!P5xCI@$wnz5d>yIKl%OYzGb%MEksjbeL$xLO0UpQecdw5 z;)`$bj7Qrq#2kRf9{2GR$i*r4FYjH1?tE;Vn_Mc>N?+OzEH%X?9-S>i387jaYHIt?Il9drKEpeaYvl}%ss5oryW+@6#CvQe zsw{o%Lei6W+BoL}QtSd;V`=vPmg@d(Ta@H#vP#jq$$Ric*~rcz8D;SC?V1-vOUZHv zeoto(sA54^yDQNZ1NN9TJbhGt?fI$!;$#@p`mV)td>}{MCd0i zqounv$lNa^2MNU-|Hb#02aa6e_bKD&9JsA#AwHb@7Mh)}wwllNfN2N`+EaWMYGs$^ z*p~^Xx6=6dsO;psi-f7Yj=0@B-!6%+=0*c@*8V(v^v2IYu1?i|d2gr}=Ha2O_&Bxd zVb{JaqZ3@Tayfsxnz}$$&~Q7Q7jT2uI1%G`o#5J|o%rl{B0|r|2WBi6aaMP{450YTyX-9;DR9W~ z9_fr=(bv4yD2*&CQIg}9BfArye0+8v9Ja0^S(s(vU;R}2PPCbZRyB7H8CB5RalQnf zr%12?@G({2{95et>lZ-zo}~6~e1YKmtgf$La+jABc`21?Zi&rywf0!4$(i3ckMkF1@ae9)KakB>+V{iCL|`Ca3vw8oNy4$QCPr}p-?06g{( z!C#9dK;&ut%R^?Zn0?b)wa-VC_uNL$&f91F8`bNK1uG(35_>`fS`Un|3{*+3h%JcK zcW)YddJ6|h;229|RLkQ#am3zq?E$Y;QZHM2J@q)f)wLcrVb@k&KcQeJGk~ULFIh;h z^u&{u$fgmW5XEp!z0=XDfAqX3bQFhmQ4%2;nEsxsE@NW058&ahA8LZk)BBefV6ACU zz>>NZ;NDoKMc3TKo0QVt#7vsInM|+?UQ<{o#OhiB{x9SSys!j6Y(6siSxvxCH55%_<022LH?LR0-5*jU*4U`tQur$=g?NG?X>0F z*nXv!+5P4wI+#U7B7_G;uW*s0JFK7B<+5aCO0W7+2o?1Dh!;h!+R&jBdSPHvvzGrW z&c8k1p}cK#n$wR`#_EL+3f1v(?{<60S-laQo6;7uWV13c}Mn5z)Zn#=XPt*!znv`LY~?#1av=H@0()6 zJD)Rv56j#QgcBzIys~2hwVgLz6yHQhRrO6wD22ZC)}b-YAI*PqN5t@i?nS|f~P97w`kZ9FjAYQ^mo*VYrgNk$SkkeP6ULkr~VIiAMnf(`8iofqS zI{V4&`^`ItoSlSXvjv}3T)pDpBnJaqu9418vIeL0iMry0!F_JO9WN#~C{Wj1fLY1&V;{*K+oe zlN&>cBd9(go{`AxD5rr)o9=|Sn45h`bO%0mr=$HFgb#=&zjqK5O*f|{e0&rgvBG;$ zWf{Zu%!d0hv{HoY+e+di-#b;#c=x9|X|xPL=DGaKt5YK^dVGdN=xsxIg=@qbvva*x zvq3jtjg|fOyvRju#(MD*0wRL*5zF{NKJ`xMOuc6dJdWMb1c*ocEctT2 zs%lHpCc(FRoKF+W$IylNecI7f9RcZ6akB9_q|(xub}6NocqliV_Au9R+l`Z) zgtKrsSm$M}HihezI1Lu&ON`wXV{q)LN-NvxV+r74r^BRT_FEcVmijzOTuTz)Xh>rF z_{7=156hhCzyB+Y)l2#Y%87_#gSc+w_qo?iZ)f<4pBEi(bIDgnmJVfSK^96qoxb-n zFfbY9^xXgD33$8Q)j)PnuF~i)O_2BbiwPxoNb0~TL z;onP;EB%*+DkIz%1p~+2E#1tt*TN*}9xQ4L6uRD!61dYjeuf3`FeWzG|L?p%O{X8w zJlM=T-}(ar7uG|#ZV}mNM{2XXI}>&1VvW5cWurtMRD#TLL%cGVi04Q`FO6ctco9)> z>B_Pib|0@f(pM0Lr~dav;;-*nF5cxDwEu|uHkALYR{ZiCGx(iq2qpIreS(2 zLbbNR0sFMA>U|8yuoEKF(8s+|6#?Rolt9o?XD_btv@JkvfRS)HC__td$WZ!MNMZb zrH&+^{IJ@~qopBnc?+-^~DRGsVelo z-J_X$Zq}*sY0$XY8Q-9`9}(cAB(bOi*%u7tdlQ`v5x(@2{zdWpM#3P0!830GVWlh9 zAcIu5{vS~A<9axY8GF!iQS68wkA#Uhk(Nq{J1pf%I#&b2wiJ}OVL(0vlsOubFnK2g48Sm_SCMCZoA9h9HsrpOD{d};6AG$3&E9=&Ma+?r}-7vi#ij{eR zG!>|SeA{k(Ap3yVSa-U8Oze`SxeJMzW+(AtlI$hia6BD`XdSBD37-is&8d%@*LmF+ zB9{h9?oUvA*)!DMT&-qdRsEo&ooN;`aRB7gsjpwA%j}0J8A~lzRWYuf9TL?Mcd!V` zmig)XpuxGjt__X`@ToXKgMsX81IiCQ z`E&mn>A5t{b3EeSnnv@B!%qeG_pGMtCJy76o41OGywqjiS(VdRSCcuc1V*Dp@Wd!K zy2_x?_7T4-UEv7>`A$T-5*1h8$m}~W(Ze@Mn3S)*e|52K*Y?h}@aL27*DbmV0<@0B zbvn6FXv3N_KNZ~2%1&EwQ7!P&#K0&~bg%$E%y)MuAp0VLd=;AMcS7z4k!%$L)RCS> zCZCu5Sd~gwXTfSm{q(625)9r9ld@$;>4%it$ZBSMgfvYNXj#Y?i_wY9_R*y)&2)=HHmn)X$T6KZ8w}rnZhg40&}n94No%Gb0DFa8p)c z=b|h$yjjDO*EfxLtF};^Y+k=VOPFQ(;~%_ktdUX9Np_-ig~b}+f?`A*jWhIm^O>Y# z={Oo6;L{WFK?B)G4m7lG3`fdgTnJw0J;y)Hi#l35Nf=>5uDrz2xAeld#YjE!;d2V0m`2NT-)ny18Rrf{WYb{A-CqjUa$d?U- zHCTW0O9aaAyN%AHZlCx8`3;5vP3${rLR57(zxhY;#~!f8K+dxmF7d2e<%#-OEy~SO z7y)DHR+G;c&G5E8BjHZ*)X!?Rfb#n|tS2bCm8)`pj`I=$0_swm@eXHJ-FccqAx-+J zK3!^=y^qi(2waeaW3T6W&rnJkY>wn3!b1-2yg%;InQssSd}9;ApwDJf0_AtjR(OQS z6=@xTZLY64@6gbZ)8%^p0R6BFbJ%=%T9L*2>8y`OFrR)F`qE6Pgw;%XL&@yrM9^yT z;rq~M>;DXq8w zg;~Owio=xdMv|$P@vZueo7(FRc2a;3>*FK{D<%HqmjaaEyp6eWIHdu(qf`KT$)(80 zciM-~4hA=dgip2xSuR;M+w_m4so6K(&NH47nDjreIf*yYD{PRLg_SIOIT+;h0OeQl zc$A#l9ZBZi8!utq9Z_ZcaDygk zbUk@k@>YFp9Fb0th=lP=z|-;*GEE$kg6w1-k`B~$omEH!^1VpU#$W8JzQMj?fIgTZ z5smyv4@3RBcgYv7vh~U5OYw5%s|}N>RXPG$r4V;9`HH8f>xM#cDd&zx+Y6Q#VKe}r zB2z!;^$C2quBx@RMkkJ6&gueH_lqV{9o+Xb^j;GA$G%udhTr=cg#7Yn+D6p8{AA*l zpR0ZfywPpQ54D3Gqr9dQsGD=X0`C8cSfOUnMH+6orlPv!RaAGZH<}jIQf=QQgtx3d z`LNsFwRqmk4q3Qm-3nB^tI3Z^oAQPn59MgVp@r9-@s*$j_{d#@LBIPo4=BGL={qAO zZ=#g1>7Kz3&n;E=8S}?tT%6U{M8K4S@i`jH_=FMNY4&3aZ;!GGu(P%_izWj9#1|y!AtXLu zn+wZw#-4;$r!YpmJ(B_sap|lgOb_twhf2VJT%XB6zFA?ljj$Hdn&o{0c2Rxh=BzW4&Ycd-%O?=D(u#IGo%Ee;n6#ZPhy$olrJQwYIY>dsR|4sS*?H>*r zw|S6Y`%7eJi-{2UMJII`4pvv>M~3*k7B8NBP;v-n!xLhId9U?-bQy!!Gv?LI@D1J7 zSlHM0&4W19ikJXC*jErAK=u^@`GjP?PR<(S7Cm#kc3;oq%8$CDmu#(nY0L;IgY165 zr@U;Vrd!^7vVxlIP+LTq+Qi>7a6sPzADR7LdWZOG-d|z7@eJZgXdg{c2vU znRVJaa5;`e1+H)O2QNg|&7XV?KZ92N@mZ|!`n`H)7sn|!@fgJdlI+?Nage2Wf^MuE znE&`@0zu!SSqtP_7B5D~X~Bx!5}ofp#2h#e;%dN__|BG#;`qI|Q;MXQ^X8U}cBdS2 zZJp+dnT2gu8{&=W%m*p(GJV^ZcOfXVK=paI|IMJtFLJHW{5=xg*rZQL5uE?0kcb7x zWWK>CU$N({9W+|sNGWT|@Rm=@BZ@!T^Na&67_(bHa6vA!g*g zdpF+4;m~yIx}$5B@|(KiF`eWBu7z+IHh?dGw+8e*nhZew`%m=!4a7nVh}C;3sBdu` zt)d~B&#EO7(cN}ysyQ|6e{Oz}*$y@AT6+JQ0#h*^Oa%^I8MEdOESDnV#-=dK8yo!zlC`>f`k9MdZqS#k6{9(cwIT*9s1mZSWQKMl5eo z5;)vEqLieQ*{N390X`^4raq9LzYd`K9Q7>n%w@B!g~N*BnBdpYZ!e%R9iTUo%YiZP zp_uFue$-j+7rtZscvvhu_Fl`;=UfF2i3D+7P5gm${tkr$2FN$^LPWdQo>71Wf^Oj9 z#R#RvE+vWh+9G5ZxB2h!iKhop3eba!`4cb8JqEe+CL($Xm<-Q5C5c>L|X=R9Z5JG{>DAH(J6{;s>$ zy+X@r1s%RE=}DEAQZ(#Bx7zBsR(*1LpSYL-WbTg?Vl$BM29$TY+LoG*?y}^Q|cFH?8R6VWPK`Bsg7EqxK-u`G7deMs7te*k^A9SC~E5=Oxd;a_h=bufXqYa_U?3Q$*sj2Nb7F-szz5q&cn$X2_uDZbA83SKM{)>= zCK1ERI?`t-lY9QI))Xk>p@*x*Fs;!Dq}X93%2ja&j}616E|7dE*QXSp6QtpWT#1{H zKSLVj0$zO2{|$=S!Y=2ZcL*0emndXj$Hls-OTB0bo`{fEma%IS!8c6LjZ;FLNfe9( z^*kG+>meE%Y|Bdein4SoM%hoU}e)`wXr*ry@QCMIc0U_h5Qe-cXapg<&eXtnIE4k zihp1d0V6>UYC5SW6lz8C=6HYjz3irm1@$ifsfIVxY`!RRt7{F6gy$%IpimIoFXdOs zH{HOFsmfyPe1DMbZ@TfrQ-Ta{{9Xz++q>e8E>C4h>#>(KtQ;P#9tw0e8j%V1nO|?B zwD!sVhe!&t`e=Q#bBpAjZy53ehHDi(UAvj+h#UXC!tjS{F()*hYr;;@X zZL^r#DV<@7{1T`*I7jC^O|pZ@L+F=^8s%QlcP%}Y9f|Bvs?+pJt=WdqV8md*tldfX zyP79a{!@{}hmhYoX4 z3MQvVNzjF6!A&65{&QGKL2k;^iMi`TiPveHp#`T9)v(7`hX|ZJZte%|-C;>-8^K6S zZ(QFC5$CU-B;)wSR)B8!(oTNR5Z@ci0tBKn%xEgT~+L*z1MMf zsZpkYOA%+^eN#XQ_^JwMtH#X<47$`4c$#bj)S;d_IP?9VtIV@pGd=RM?tQxtIlxGG zZxl84geg>N6DNz^pz_i&K+CCqk>t4`;U2Ttl#@li6#V+hHcOjs6D2m4VwaKoCvWPP z51WQmlGap7VllfSH!qVqUUDP_sc8P@u0jRDFE2(%T?Ne z2pEYIeB}Nynhurdl|GbXwTzxnsn7U|3g`B&^JzY#Dv~CLaUt zLdRu@g@04D|Ae`77?uE`@O{~A<=;X5(Ozd`)(juckp0Cm-bx7H(o(nI<4ozp@^o0` zZodo|3Fh+UPajW&3?hbY<9@Kn73)3rPz=7Vd5XdKAbgpNm6w9TOn=(OkRMEh0=WfS zb_bK$N6|624Di}hNt2`0uG?N7@c%W{=z%`S8Za2mdId-lp21;H9>1+W-s}QwI*Ke} zM7LzPH(XbfbaT(@ZX^WURNA;`#K)KvIZ6E!=}$`Hx_u-I6(Lr;_Dd^J^% zLehipZ^io1^$3LRc1#E+m{!Lovmahgxq6?5e?n0aD@R1Q%$>Yc6noDY-d>CtG+PyM zU&*O?Wb+Z;jR6{n^Tym|9^tmG7sM??t=q3DgpK%pbC2_!_DkRqbf^E;@j7q(B z-)R2_Ob(1h11F3*^-KNKr?2yt7fcn?ycV%gSceJ4Rod_s^VN#~r8fXFK@uglJ2 zV`^bq^4D0~qsn{*5d`VY%BGCuCE(q8o8dzC>mYUKCPdyAlXdLHIKNtt{*2oCl$S)sX{*|oB5Nk$g#reP@m{lP{djEhI_dWV*&n|~c z$$pu&&VmZ;~c=8iik}H5mf*nZW;8D`!(V7xtD|+0fUY z9i{NWSxAAApw9=Cg|(sK9QJ)(T!hPP(p#LiwVpm<$TECFOTz&5eks^VR&!53iVT@o z5m1wgMHi!GEDnyl3_WDdL~<_}{UhSJAmHW!*M*!7kAh0N^H!?50A`M;?b>Y1s40IU zJ45iMrF78lFEQ4@p4_vIZm=92q4bAkBiPjO$DDrA5gPQuJ*Ov%g4~yi^auTV5?Ea* z3W!B(voJnCvv}1}eiYBzGmhq^E-DkgOfdO(RDTgRuJ?VlI)Go0UwW!y->!?`7j4?A zS&!ap{K>MbIr&_2!`k5V1IWRQu*h2vT8%7_n!#95-%Nu>4M(KVx{~OZk{ew&2^Ofg{|B!#W{^-oTlmA3J(E&HEzUq4o+bA%3 zoi;+gD*Y?x7ca+O1C=UKXrRG_7^1f?zbef zW@@A@abomtFXyJ@3M&+7)Ml{WP#}aK`u1Ndt}w24YIs5wV1+|v9uV8Zjnxp zlz3w`P?Tm5#|}n9^JW-A`}fWe|I(2gy&o3C?o({wUKoM#UZ#sj=Uz_LOGN^j$M;TG zjqNkV2CoLCl;%UyY`u~8#GT+4*WWr{w% z?9TUpH)Xf9Eb9!EkVFL?o zN&hv{;A3Sv%VOnoSc+KR{vHt6o=({eX!W(Btv#udxdH-dWUwZtV&ozv39O z(#|^dg)iT;Ttks_gND9fY=`JH%G1&qYL5NbL^A*>`wt zH-2Gb*S!?&M`Bh`Fw?_C(N)JwMW}48Zm>t)@SKP_7zb`C*tOzZr%6SBD>H=kQhq0TS3)_@RYcIpgf zpA!m)ubF{Ae(Dw~7G{T6HHu3Lyi{!U)heX=Q6n}B*NF%To1q^#DiK5Gb?N&H^%qu^ zZ@K9I7<1I9rJH|``)HCFi9~02l3epeltK#NWbE+PqK@{K`hbzRGb2%#F@8NK+0T5# z5MDCDciUb#?l}&Nv-W^XeDBlrQt|f)^hwF*Jy#uilP){=k^Yn||1c(qniOsbMVd}7DZ5=zM~v}uh}bI9MW8U(#5)PoDfu7&!G$kM#9u8lFQznqA%a~ zMfyfOe*5o6H#(;km)v6Sex7Kk;sBmlHIUfLbwl_&=+?`&s1S|sq{Y5SY*YC;Q$>4| zD9)_3|Ia}Uz~Sa8aX0gP8{-U?oFZqdx+2L@3XiAMnbN1<6N8zQ)C%x zo-2#lw_`WZkf0)_vXJ3_;a!H~WF_vt>tGPmAs@%IP3=4N6YQA6 zPDj4~y^;?kZ*@86e^r;7S zdBS@2Hucn5&3)MO>|TC}o@62mZtBhBNms}vQKY+T< zyzTBQ`5$CRH8Fq6?7Vq$A{S#xF;AfGgT5X7@dR<3pv$PLMZ5zTiPmJh*##ryRpdct z(B%&tkT~c+%QGcgr@vjvr!xFX!e1(ag22q|(Ek0qxGu#QXy2lGLkGXAg)D9F)2eQd4E;~9$p7`4tA1Y&G^BN`-!u?RkF+@HORF3bW&crz9VPdKYKuL35>DVKr=BULlPe3M1PdMn z@}c`8Fi#wKU%Hj>Dk$LD&6}$Fbo6(6U&42)9!YoVLX(9zfzDQlX zXvfSpZ5Wi8MI5>{{fyVkxWA4*)g=Su0~gKwUD8uxc(`af`+G)SW66?kR+h?(7GC@f z-Lvo0wy1xRN<&Coi}XO46S!}tF4Q^kBSWpP9b}obm-Ps|BEScB$a42;-#(BpAcO|VdeB|Y+;BOt+h@2z;g|^m^M2X#^6LzbG0_mAbVoF$ z=O4xv3q!HepK1w78g1FR1c$`gbZp81A0DIY?yG&rK)$~VGWt8au2wbid~+K2AyR;b z;5UXMBpB$&BzPA?>tb&+a|2FB21? zwn-c-V5`bs$OpEawGa{k>}MSK90(NebAFY_;i_>~N1}L~C1St%1+7Fs2_+paSa))o z5cNGoL!{cO0etM_wW_c7T>$xfZj2%6y+^}q8$r&Cdf@GjY2otbpHKoh-{kN zg!^NUWwf5m`CQ<AYU`2Dj3>^f&~S182^#1V%}WK z)WqdGAI)9@q?caF3PLCtXh_SXX^J;z(dx__A0JKp%OtWRtHJpvJ#LFVMzTac-Uk+eAy`LszT_Jq`bsM%FTXyC487kW5kk4swX0es9KWNTlYANaq!+8N}V=bmn1 zK?q|)7GK$&;PtkU)>?!6j=c7TG5Zebsd!1T?@(cvS5F&^6ZeHecRgz7kCge$Z%wZf z;VL1xIoc6d%XkeG9Du(Xr`#d%MNFLwL^%8RTCc{9a8d`q6-qxMf&3#;_S`-#8;B|* zJ5Zr_Q%q2>?)|eETvZ4tCcWJXxV>_Bf2!{K8v%UAe1ospv+dtkk42#TES$`FWn(#0 zQ0_oHLx(%4vif|k#HYrr9S{%eD)2J7)-Oii_-NR;!d`Xp1cBF&O`qFd#U+2N-%%wI zHeZ+c?-~jJcYo*ES?u1Iz64=v`u1@d-VbjO4W=cpnJgeKRq&;k?jVdK(ljy#kFD8` zr+-i%BYp&qIt1aUl9jM~-8)UDe#Z)AM4c?t zY>HZ8?!F;B&W-=VhX5hKBGRh(ITA~+Ax zDE~imYK}43iRJ(w)f)w#SNpJmeD;{!>@k@aYgyQPJVaS3P?#;YYrkwwD`8wYH%Abi zaog}Yp$$X>g*ZXo)Xxd%S>xX%gL5^gPMX-HF+03UH_ z>Ff7oB>?i_%qQ8sU&4#@tM8!v(VzPvs~#`1=lA@==v!4?R@Sq_XpuQaSp6vEE z*qCVK)dZqeC$of+E7}mOTqy~J0Oi-w!FpicGaG*r5DRbXc2T8fN;RKh=B*|b+41r+ z2b~WlM(7NJI1{X?*jy5(f=GAXFKmClMU3a*QSYfNU}*#JZHhR&{;M(I4G$FLzt@+G zvpJ}xe8oNHij z7pnCF;KLt{A6(CgK?cO`CtJ3^?Y|APQ?~>7h%!fnU)?@Qf%4m$TIIY)bkC%`J*l2W zz{Q+IF4NvMcN(K>JjrI-o*&9nreC9@7`HZn4w^}>Ga;|dh@(UH)QhJR^EbDhEh`4{ zVai4Rxmc0=tXd&G0JD<}3iY@|ENO!Qg(LRn_p`4CmsKYyi|NBy&EdjXZ^}>I^z(B4 z@#@^mL9OCYY)5V|M}QA64D0pxKUN^0F(e$a$5Uq;G5NGmCQq(NP*a*14H*b2lCaw10!T!2+muVk;iJ+ z6j8RGTdz~v>7K?VAARY<2}Y8UMp&`q-Ky!P2o<>r{CLSSWhfP7-7nOzYSk4y(upx%N`>jfdR-|YnCgFlbX!RcuE`E~53M|7kz?d`#MDWBD8jFuB7 zpsUgUEBBdt*NCTz%Me#x!w-*)$CcjVGr46jN?yvEgdetE03U7bFZNgafX_b&vq*cMPgVlsfY}>(7BEV$|QFKs@xZ6yZGEb{RsnUa3gKOcz>U3 zxRGxW*Q8bIlGT8`A6lyfktnZAqVoaxu&O&zUhR_x$}e93Q|Kc*j#(O0tg6H~e)m-* zlx-)oiqidhM1hkFSyk&$lQI;yjB@CK#>3ZdGd17UYS&CT6Gox`z%BU=Z2+%)TViI7 ztT<{v9d8zi7|BoDws>;?;e7b6^DEI%*t2h*Z-3IhVD#PByGhPN+u+MdP4IV|Ka>f- zSHVeC^0!6!`T~4(5C1PlZO8)ovg{2H4!l0B-OuzpovsW?l+Ak}!V*`NjH`@7hlL~e zqPuFmjVbkN5z(d^yq@27EpYp_JqE<>|fi4X{GflCnNQ6{;vw7Ecl4+kQ0e}zUWH^dbK075ACLH4PMltjufSgL7``wcwgNBgbCoK;IBmGT0?9V$ zlQobfI;+Q0YBAjUP3w=@c=-}7H#Nj@XFha|wP)X> z(6Y^?gwJEz!Emf`cR^KZyoTuhkiTC@t>$7`v{uLaaDWed2;&tKV*fpVY6AI0Hk=<2 zU1_L(W@;=2@vv{P93dxg1UG*1+&2QX9my3cJ}2G6H9K3HkouJ}d2wveov$GH8)+*T zPh@nH=SaC0$Vb<^r?UW(WM@=i8re(@Qm-wXnZeU|W<&Ea=VjEla(bTl+lKFVpw^)> z*tH^Wd0j)j^y`#;Z6-HrcQ$9wrlSEq3d#HKSLde(2qvnY(&(ylbDXJ z*1S-1gh!LTG=X@U49YdOTiLlteDl%i?G1Yl3?TrZjYYaa8>pM*0+DG{jf+{WSV!JHGXlK?)32Ju%+iv4%~nF0Cg4jl8p z7g*|wbyrv}=!x&Jf)o)R*w9x%qqh-<_fE#?Xn~02))Ha{guKCU)RrdOk3G=;dM$uY zi4;D6c1i`@e>P2P5flD-tQ;{3ydOMhPzh~ll^M?DcpK%YwD{RK>IPy&UnfAxu`ng& zS){6D!UxB@hr!%wZSn~Z;z!r=aSFhPd0`#(>ilehd}Q?>XFp|FW|A;f`>FOkbd`oP zQGg~vGiX^fbZ`}KcfO^@j4Qlj!1h%z>Fl-V9G7b3yL&?dW{|)Bdlsw zMW`!7w`{8U$5aG-=ku$`rtZ?~A%~vy;jl7UyXJu3AMU+{=sjdbRM?3XXzg{(@W)_M zhgnLlD{7nyp1VXqI{N~Tc|x*6nALv-T(~;v9rRaNqm&qU;%(^0MwGLbDP;nD@BU~h zzB)fUp#0nqbnESD1!(wIK6xoIGiclsO=vGM$w)S6%ms5YQRU5`I?ZHRV60|$(rkpn z_xh356dWEAFUlFn7USKikM06pU%pKk`isTI^B9yoITZD~QR-r}%FPyUbV<$JU_JZ1 z{@C%xM^e((LD^3Iuw?rpxkRzX>Wl!5Gd^8nbkkD3mJ9H4N;5LQ+UEr1tFC6?%5T*x zeEXEY*La(IY@W}EA1PKB&Qk6kQ9WC7qX*yUby_Ao(o!bGo>7KrSv@e2i~X&#pFgQl zW)4sLH;@lq&SAT1yl;&}%;Ta(4}FL#j@#x_$K013Bfz&950{jktIT&tWN#T|>RI>y zZXm*MHNRfCrjAl<=3H+zCxC?j=;luW_i8m>E_-`8@ONNsh)**hX!Y~2(OpGgL@o=jo zkaf!%g6-?EpbLM^;~>&d=)XZVd(LlF<4e4$<~lr?Ex`bdlh8656`_ChuGyE1X^7)b z(JSeRrT^Mzx{bxFeI7tQ@}g8vXEQx_*Xuz_l=6svK_0(T%jinFR$ zK#}W?g^oY_Y&zR;76gA6YQ(Cz^?Z)u*-MeboJfREV7-VpF5ZERIIjZu@KPSRUhVS* z@)`7oNQAaK8sJBW&5C6#Ix)$}Tv<_mRss#jYSb(o1x0PF;O>Y!K)W%sz-1FEpefSy zgOBwsdZgn!YA8Gx{_ko}|JOg*FTgMusuI%o6PvNAjKTR`7UR}(Tv7{FQ44PTvoDmb zt}7<8J+AS+YE%sz{q%5z&XTu9^+R7<5^A*~54>3|zy~YP82@S?U~upM_P@a3o}(Gz z>c2B1FGJ95su*2NwB;L z(vx||)skG-Zh~MP*Dn-sX7y#Tr5@np@MU~>wJ!uHzkW>7&*`(qyt^8bV`7LVT7hGz zZw;NMc*KwC#<1JH=gsb`!;G$rbZH5kSz$S>)>O%&3MU1A32wkHSQU;pM*;alT~MZ+ zyXV@vp(KLWCyWG`*~|0FeZBG0oVvQ7eF3IYpmzz^BSeunFe{G=ni6=@`e-T1asx^r zCkj0{9)FquJ|^Dr$5;CR1780(Kb#IJo4PZU+MNlRVYJq0nd8kK)$+wYs=x*kh_ zv9*KRX?!Tk!eV{tpIF{Va$!k^_h9wXDtE8Oc{*J0EmmsG1j(BD9o4wRn3K{B@Qs`o zy?&Kg6`=fl@I@IS(y)*Y$a8cXNytbDtl%f$j1vlBBJYT`%nyHu_6PTk-FG4ECPnIQ zm|Vs8FH+vdxa_?{WiQ4SfXM)!b>FFDR5K2G3XbHc3KhqzVdwRzVt?InWL8v9dnmzuK1yQW9I6%Jn|ek6E)|oR{I2b8VE~-XYye;575@fUl*3WPNM&C%{KerjhGrXEl-@ zD8CREYQu8Bv%_fyQCzVu-TNIe!{lvTK|)jrJ;i6=&&&F5a4Kt(H`?D1WQ(RQqSWO_ zSSr=GdQb93zW-e>>V5*?BkDE!{A%AYkgs|KAMLE5-HhhPL`{_#NnT^h_!xX)AZ*TA zypgm!srr`+z18s;!t^qh;{jQD^QdAZx(;;<{Y_Ajp|~T_@0LKmHzL`+NfuN_Sdz%| zE!)_L8^UPsJP$q_^!h=)e1C^VjWFP&n?F6MRT4o-PO*iMA?5`;%<7AmaYFM`$8FY{ z1NhicDqi3J0vKQZzxTgy5fMjy!*>kB3JhNwaKHI)!^=T+2ON|6RJ^ZTJWT_o;8P7A z0gn?tnr$E@q@AW08+nW&-~Buh6RDc>o4}|8$X8Q{{FWuUf?gdOcKF?$yp0mEGKnaA z0CF%2U}wnEBvVfkR?jiV$LM8{~70DNp!#a~{X-#$=&G_0ibr8gA04JE`f?X-+xh&(u| z_4PG{YoELiBwL#9r@YllD=iGW<*MK@sTqq1{rFVVd&_GJXe$=R%(c~kuP^UEidpPq z_mQqWZu3==lt9YFI(Hgz7JE?>Ju*J~SVH-awV=Ql;6%-KT||gy58bSKW~T(K z*E=%saM%9%3@_|o?YjW-g~f9Sb#UA|G*{!>qb|Ia6*RxmK5Ku3Ulv)Tmz{_$5(t5lcEZ1@)NTZ4tWzcxT89}Ot%>gvm3{M>k;E%w6N@!jz#+E*J{HgPrdRtQ z!T!Hj&2u@07~77vES+8ZQGQK~+?1pjF8Z)qDT`ZdRh3J^13fbndHY8EfCLd8Ss#Q9 ztNACVtji8BHw^jlg7vL@a1qe;#c3P7>c=A&OxED3%r9h4(_{qy4xP_a;B+Xpqt8Ap zqqPl}bgn9Age#5EH}EZJ5L@H82~{JeUlklR?5t0o_5eOw%{I4J`=Ee)5>1XFhxDB$ z@TK?Fd) z`vrDf!yms3^ZN>)j=bp{9ucpUCQ`-CKd6-r;mBBfyQ|#jfDg2+IY)kRtjlqjbD8P^ z@2@Eki&ig;#F@%O0P?X#V)6Unm!+co2>6IkEX^tx`sPm1K!IC*6O{Zpza{@;$pIgJ zEzK3yaT_qnUurO6{bt* zgqS+=+qBAuu+uEwNR++j)4fM{Laht)r&cgFlJrX!e%^ZazA%$7%M&^(lFs`(=oF@^ zLcrgTyzPEAIE&OoZ9)5%JNX~UjGD-~;e)TVl$r*->@3fQTh@Y5TA|rqX=|NMer11s zSeB8s3|}fiBq`@VOgff!4e+t7Iy%0(eZB?qS!vM*jabQljt~er#?W_1F1Q};hBV>H zF^OQEK{kBq9_~o&$Emj|TsgqD`3XXfahGiAT(fY8X{N!~6n+u~Jbu?rj;@cw!obeo zyI4M?gx~Q~pCxy?r7;_fWA4iwaX**IueDC~U!}ykqRtqwx1Ez_drqb%Cb6;v9aa}O znL+LVKK47u*N=~61oG){1)N%-7@3kQ5B4|(3iat)=h8(OX%rz}T`oRI71@0u(|sRn z8!DxCY5g5892?~C?EUITyPA<}JN}dYzB?A6_F3hHpow;KsYr$W{ zGAzgqgGI54Osl4T95_He)01X*D@et9er`~$nRYU^5KxH2lV~m!$u+8%`-7xFYpii> zi@%0?Z&gW8`eMNS(k6_eYXkw7{Y-f{RqSB6r>^LBx}hl$E?3-Xt! zIwaJMZ5X5NudDok{`))_oJ5Nyq~;4WaKw&JrP5pR@OM$)Y&Um+e5`1Hj^G^B`OnHz z*&!GnUD0)iJFm+w&Y9>95uSZBkRC^9j8h*Yii>sncP5vq?ar;w^WWi=)M0ULA~YF7 zLl(a*YE0BqiT!FHFOUyOn2VI4^N*#E|2Byx7p;locSBRbyARkpATHKeXv)fL8VfAl zq(z@C5XHVFIQ=Lcf!T>xMR@=zv@A~CM?U~wl_erc3QN&>-jZl9y;8$?%r)j?DnqP2d?ed*jBW>bW0b4ctWIPCY6TBMhhJtg|4#^_rWOdX1aWef}fDMZ?tB zpVIAf0RyGL_HYV?b^(;%jUSdy)#OI5lfsl%|E&i$&xQq$2%-f|z=yI9+BVKY#k_)a5(4DiA78NYt~*#{usA#6SWfrvMPbD9fY z#=%Yw#Kq(MC&+gg)Xl|qoubI@0u6JJZTKg@ueNu;vr!tTDY4THk!3WlzTMnXj9aOz z1M-Rg_L_IfLi)mgqjbH_VhL4`bdxx@g!jvYry=dx$0BH-kNY&JQ~(N>%p4*-=o|{i z^99K}vgN@7no>u8KMx(?qu)cKd3F0#1M-oq%#)1s!LWOIO652PSd`f_-K>`R8s`c= zQhg`PL8P3~f#j@CA#Qc+wR6ZZYe-kgVy4jd)<}m7SK}U#_5=s=mD>bK&c$!0#eWg0 zn@^>;adi2C7*IvAOrs?A{@J&qAb<#;yUgX_jWGLWcxgD-c=r0cPFUKPOlfUwE$p-w zT!4?@!AAVmK3yQ6v;#BqMZ4boT&2e;X8KX2Ey!e!X^7?>yh({PLyF_iBHeM+F|Cr> z>#xpI4UypP^ON{6{@EAmpQtfE8gMFK0r^&I2gcZ_w4KbnVpp9#QQ7YKiO5ph&KPd>^g8dB_)@+IsA~6Ekz_r7X>h`b)RE&yypYtPA7DbM)#&Qt> zC*WJ5Q^5*5zls@lUr3=QgSS`KqsSH|1NfjjZuMU6^8xa?p4~NOEG)u(J49hcjdj7U z|1PH&x2uFLhHJ`GuD1V3e;*#SNj5id|w(+u?Dr-F#^#bPjT!ZP5mUxld%uFO_xb4V9>DN z^<2JbK94j(d)q|oiA{c*;*xSTCRb(-*#Ix}{!dciohy(p#ql^{W%ZNI6KBikDGN-j z3EAskWmA|J)Oujq&pxEZj*Qg1gvpd|2tD4SHv!Bpe#zW~{=VC%`8lntM6%Yj03X@U zKG|3MqJex}Ch5qn-@%}h;ny(svl1PDcKWi{?7YFDw3gGmg01j>ul>n%)>foQakXl) z$?lTlSEvNf8d}$WRs{pwL{bzFkguB(=`6oLVmwRcJZ-u9q*|@uJBtg+NX;n=V$id1 z3yf7q(iH0L*oRsepVoXp8&SBP5^)OVi?U)hDou-vtncqy<5UYNPd^eRB`uyEAS#5I+NZ+*d8{ zWFbCZ^DGr$!B70X zS!(=ojFoDkrFUhwG5fvS?@9^Im;QOOE2hffh|k*`M}JC_pI9`e(M;6cCFaZJa3{h3 zV5Tf6u>gEDhS0RH_T>TjR*2wiD^62`I?fZ=uXASt-Ht+VDH{}P;Z%r-eePSK4iPFJ zhz2)(f2DW~?0mb`sR@#={rW-2oBJ0`vEa?SG9Vufaw|=;6sOyspWnW7uSkcNbJdB< z4>+YHL_+uH{0un}Qr6)aGa^b)Ko-T|Wf3gv*~x?^4Fo3&M3+lou_)L9K5pMQtXKQ; zfqc@HJz(%&Fy@gO&8(2`DIgNOXqlSWV8?bWhJ0YV#xhhyq1v1IH{`d2zdJRxTbcGF zsEVcUpyMHi)fBWvbO!?YK5AQVP*IcPL53l~x7aUKns!NR9Og7WsSCnkJp0-_%%HQ_ zrW$K^cc7-_vhDf|SbwGEimUs?W!(AJFCC?Kh3>1G`RS}Z1){>boh%U(VBO$t5LP&kW6+Kz+p%J}cV9h12+>)-(;5`lBvGiIYM zARh-WOj}nk*oUyh^UFIah>Z!z+*vBvOT2e;u#nF_?BQ9q=s|Tml1|M@7G}-5y@52y z!6fOL{pPCqn@l{I0DgcEV}oV+)%leG`4SjY7)dm;X;I$`IMNe*5L5y$`LvJ-PB>Y_ z7jAs2N`$|F?Fl!CgVss3G`Ng`1%EiSmH7!``m`-ns!GdvJPyc*ag;4joE9MISp>1O zjw*%2OgcJqX1T?AsZjqie{=T!@X?hVTpOtyDGSY5kG&DI!)a%5iI5kLJk94Y0 z+cBC8x;IF^x7h;udTNUcAF6@!OEVsFSVwb3YJP*)@u_T^ zSiD~$jqUU)XOoAazV3)HwAy@7-Iyl0HDduyG~wd?CTJKo*VDa-8gWf#o@HXGIgpPK zTvZV&(kTpl+c4LhGy6eFXW*!^dGZSDYZUGC`M1oiqsrdt6P1|bZdRL2a&1DEg&RY| z$|1_RKxlbWJ98uf@DZnOaDEaX@0t~u`l-RFqoA|i@l0^Y{jOX3H8q6>7LW7n z(~N3~C^EX`ja#C0c#7@!^qAat9D=m8!O42G78^3Qa8UsGU<0!|U+wD#@`0!_E`$4{ zW-R7qAWH||RH%JHD$;ioxuW+G>L9V~8&hMW)lpz7HFHaq#7?cha-_O^fEvNN?l;*Q z@GVY>0M5^n^rOHBaTccfZF*uF_0_q<$HHQ5>(2B8rgZUE!bS1l=svbNz zc5K^*=lpbW;rL@98forP6Sy2wPJVHtzw4QlggkuQ?fVK*OaWchc|oE=p!4r-=N(J% zZ_G5R8JHGPlMlE%JKCPuWwv_qp%>=QJ{m+_FQptP%+BS_0(vb)H5NKx_4w}o2cu%a)74Y6O zA9eGJIT^?MW7O@Tl!087C6e5tqA#XiU(X>^UH*5~-~Sumy5umvZs5*RyR|`E;|JPH z)s2s`(ph-Z7fDI}{3{@hrw$5m_(D(|kdiIdymK~$6sVnyocNi=xL&zAq2GwcRRH;6 z1W8c7+Sd!@8-E(MMM*qDxoC0SdupPYu$S64QWBjVxQJ_K5KNiCj4P)*V67*_6EdT2 zB4_RUoT_r}#dQyP;=BU!tMFS0aQ{Tj@S(uBBL_x7J>g*3vw~Zw$U^aqbE1*jgzcC6 z-=x}pEZdT#N$x7?j}PL%_p|h}QoTtEQ6>W6S8uMY4{S97KALf3xL5o7fqdW7a~?3U zvdtxt9d(1@u!(T>WaXyD5rrg9ZK4|NZKg*U3WANKe#V=(mmCvQ2V`lEwrZ-kHi(|E zRS<>u?qLG8&&a7W)mxWT?pT(x%>oTK>>5%PND z?|M?%_Bf`oK{=HTNa^Aq`@K~8=??knzc-zJoo1nc5b1%six#o9MB62V2Ohs`_$M^m zs*q?WmSohm9o8H=KDIjo5lotMbIKCt*_YP+xM5(I8*)|q7(~u)*i6T2DFzSDcT*iv zDtd=+(u=AG@NpAt!@fGdpFln^c&nrfF-9k`z-+sw#MFg#%Yv0ax!uqN52b!*u)MRT z+ki{qu5U;BR3*_Yq^OL^$O8kiYGs=?WB~B7)tm~v z+P4biGxFH)v$ChGO&H6GB5xYxk&W*e?%GVw@bXS2j>N(`C4!ZJ^crh_L;#m_+?8Lw zZlh1ntMmvb>$+=e2dT>kzJ8LzORz=H5}$wzmWklo@6y8DF|RVYMhoiF(sk(1gu)>L)3ZmDKRAUlP|hYp+81CQKN z)ZIY&c@g9(vYxF_c=}gSNR~+~iQB`aDhF6=xn`)ptkoK1=1XeFn18x@i0?;{H1oMa z{M>gTh9X6a-~T>!nRS1}4B#tR{d@TY{d+*3fBygedmi%g@B8!{p!*+2M2xT0_kt{R zMp^WRy8t&D;qC6tDz6r&#^0F8;q@~nsX{CvAaH=*<6lLOM zh7t7CSIyhm=*EV=DulbjR?C0w^N(Nqt9>Ux`C+Qx3`Z%9(#Z#B;$4vs#&xT;v#3Mp zv9*Sp{NPiNN~(jQ%IJkUBq6bvtyxTTZ0OrN3n%~HsshbSUh+Zw9(eo&n&Wh^eZOIa zR!xH*e~HLgO466dFMQ;~>r=5WN%))e?teGbqElCV8Q*w^~Qv*%sg5o?{V;e@~a}x{T21lGFpRhg;9dD(dg~ysP!vV zt8u}7;N|+cx1I^BtG6x_I-~FQfq+W0$L9ysrve7(uO|?YO~t>$EL;FSaN;koA76eA zhu>;uLn__W(IQ=@7Qt$VZU9hIsP&<`)+Zukkyd4Gm2s_|dIpIEX5%8{O`NT34eZu! zh;!AywkpH@ol1Uf!{{z!#+_;Y7?%$fCjb9XcGp2!weP;b=@yU%=|(!FM7kU4?(Xi8 zM(J(|5$W!d?vn132I&%n^WyXF-`TU*nKS!wM*ngKKYp*Z*1gsp7lpd2C&>4DHURwj zF$n1Yx&BP>=jq#4iiZ%2<8LP(`w72>Ak(y=RTp1`jo#(t{6dbpu^>(9i;dwDEhBX# z36rEDkk>TEEFH#|UZ&|pus8vB1uHV0J6 zdEZyuZ0abpeWFE|2;&uCUtIR7VGB9vs^BGMV5M*BV3x&;*qRsa~3^+C$bALK)j^Zg0-^#>2|RXRsSkZBFd%&o7f+phPEu=qf$ znwFH={O02RpnH^)pZ~IS(I{8><22TihYxJBfM1GIWIZwV>%cSKBvVX^B!Evs-HEFU zRoVWjICK&pZ~ucNvOy1gDKk+T_1NaK4`&70MggjKvHgubsmzL?*{F>1<@WS?tb?L` z-T8U~#_J%EkG4DQHP}96fNw4+@=WI$ndtBAb(Wy zdJDA|ck}M-@B6KY^ni?$0+H4*5ni49fsc<6i{xPimt~BxT5DmIIi>lvj6eZX{GC1 zrGa(U(#>?#`rcP@Hd*^W@BrTpzKft*S3~q_G*g3Ow=ou7(9IZ+eH#r2qE2lC>Rjv4)SfnSmd-LrK(%_3fcq1hEDK1vN(4OZ>^L1L9GB;FdNd%PS zmV=T2pG!4!E~2KA=x<$Z^!pQ+FF9CRinH}f$ufKWh0i|NSfv+2S+#nQFRkQmNH~x) zH-G&YV;!fFF%YtqFY7-_hz9v0ED7Pj_O$`VFB@mK!dr%uO(L@+j=tS0p7&y;A|hwi zRS(4y(AXSWd9tD$F>LAb5{8Uc4%b8)2jHM}+acdv_{71(WHQq0fw)tXO1rlj;(&ARj@3G5F&b z0ziF|nx=kQiG;Mpb-o=kq%;_8NT79-uG~TYlEiLoVnZHFMOMyHGQY-LHZ#Gt=P&2I z_Su-XOf~s{CukmeqQG?=;6r^_^OUP6rRKJSJ_%y_K*YT@L1K0%8OU7m74bPgXS&yv zqcNkl@5%G)2UC_SD?FTwX9FtHjSOU*Uh8-$*~No=M0|egVCP2)@L3;Q_+%g=(B?$X zTs~51L3rMKaVQCRT__?ogrz&;ZR6=}32h;&<8#h<)4o-b;!D*3v4>9|q&g$3-Uw5) z0^DC*vyMFRY&+A`cVcKfg!Jid=BFA2<5d1;Uj+O9;#pk61FmVB=FnKmW^~*l(1^l9T6uH z*Rv3Sz?VC27?7TH_o@Nb@9+CVF7M^{&eVbXg%aI`>7eGY>bjhW48p0GG`R{qpPSe$ z*wR2gHUy&(uzgejUs@n{X1KkjQlttzsYH3V@H?o{AN@|em7!VXp@^Yc>gf_z2t8vK z7k&(QgI%}piP|c*RSadN_XKiS;qb~s2LL{nfz?J7gic&avgVr_ZNd@W!>G!WpShWP zgC2k1A9(zd@IP5!X@2VcZRUn4-oH_XYW}11=<2QV{SQp;Rwd z$6ecCtDf%EBlM|_-;ihmHMA41(D1hj{Z3o5KF#||?sv0$zV8dzm4dNQuPRQV8=;q! zo!6dPJ#%zK1ww%5CkGi(KDe&)cj4l7wMI$4somWYPF&Lu#5x;$q<*eXX~zuF-<^D@ z22d48j)N5ST%p3TDY~y!%I^w4;_SyhX6J%@uORWkpMQ7*@MVAg0J|=&cRP1GC83h! zXeRQtce4ij^!vI#-ySatvI>3d^}*vj!GvnbNoxn~%)IRh>0sKb=tNsfLB4R_VJaZM zCi(WCS?gK{QH|fwF+{Ed5(k<@qhY*TjhKT?pMAaV5{b-Tyx(sIUL`nrH-%v3{c|2_ z?D1Ldrm)Y@`$uB40+5ehf&>rj{6qo13|J~MB+YqNT8WPgxv*+CR3GPcOdQJYX0+aE z>vdEsp}mdDGZD0Wo6h(r3uRF{Ia#Yud$K8fh1ARjC7o*vjfC4f)Q^p4=T zTlKZ~I2RTKY@mKz;E1AeQsn+XqJ>M}FSY3kk<=CX@B74L$}UZXcv*~b7d#YFX*2z| zn#jmplia}le_K2x$U>o%S4 zixBJWu6{EJ?NdQa?Lj@;pRl6vt3W<%zQA>`eeVH2F>~U42--=HMyT4f`#Z76kRtmlT1pF%BpG|XV%cvj725D`SJrxyOiZm&m_MTd7#$*wRTZUd z?IFKVkn`HkI?VVCt}(N`e0R*NlQDrD1pc+?&{vW@inG~zg`>$U zVPa5?E;~@9a$l?j*!d-CR95Swz8!9q1eIww$cRRsFfYG{5?k8`^*3Q4W4192Hx*SB zUZ8QfdtV&3X`C3!ncpe!340*hd28pnT>kBEQs-tu7zj`FyOnAyc>14}sjJwE*j+!EdJvSn1S07s^D=F}qSWHkFv_1eudH1;m6y+>Dr7RSJiy0`?>bEr2-D4MZq8T?6z8@giDe_s}K zi#}Ma4rAveJLeR`G-qh_k9o_f=;Cu9G$v_q?QLrRH)K{~>(H!5EQCgo@EaFLhqcjn z?2aul(yfvxyO;I+oMTX=%JaqW!!$Y@w#05PJ|l&h(8>};FPCl@W=qFsz24pcbvpEC z7;@DP{pdeTAqSh2Q5*ANa;4NdCJkd7O9 zKW7aIaP_`q2GAY@Yi#NDPS;Dv{}{`KVT-95e0BYlU(I;i$V}^QH2N)CT3Ixbe9f^* ztXuf^tuLF7`uP*&b1x1}=I%5IYIfO3`|74eF-OnQy1sDG_5a^HSfk_T@73LUT1=0G zPTWm-8^a_RnrfszynA5!E%=;!<9Z+!D!15H|5uz@M7XT@O;+#UDYjP zHO>D%%OF)%!M+!o1MU^=O?+{-Vr5hR9848`2|;!|)Nn)>pY@H|%b$Iw{w4a{F{2lZ z3CmPPgQa?&UDw;OBSGqJ7}}t8E4412n)qelSuR~pumlINN4$?~B_)1cP)rT~@!!8f#%%@pxMfx$+*fpQPJznqLKs(ZTLuTd-!$J zE%sG3#SvOAz?Zz&GNj;atrEcr7mytK4V!e!0eRAkIjUhUROs1U;@GQg+BBFeK# z^1>{j_uwstlTaN~U~0fA57FzER%HBVUt&!A)2e@3)qQ z;i(%{F?T~CAKv+AcCdYc0G}dF1%z` zvW52ngSgpstmIuMS;6I-pld{>!knpUaZADIB(d{bUL;phuiiv_u<+Vl;Q49AwS zks1Ty)Z?DNXPw+j`n!y(9r2e_I@A;|XJq1HAu;ClkK{M=GVPs3<=^oYP-|D4 zL!$R?-tm^?hs9yN`%ZiiT=)Io9{#d#xNNqCbv$#`~JzM#Rlq2J(1dqcTK6TV`;Gjv;hZDh%Kvf_JJ z;9T?7Q#1sb=&sPblo(${Pll97ihh<)3&T^qo_6?ieX=5saKN3qt@mYc{!TV^wclNt zk@dM(ZP#fowfRC=)7v@=^5J{Tw}9=-0QfpRLY%ENUY(=eMt-(RDqg6hTME3oxmB_B zbi$b_Z@B&O&T#FBEw-7y{tw2xpUB^M;XfxuOA&Vs1lt6lT^Rz`3S^F6ui!FM+=W~7 zzs;hRVeIv(;N2Sam!fnW`+Jr|Dh2Gm(8+=q0SktJQzrQw_b2_v9B53^83r^u`-_^nShUmOq4#ZRTwmB~## z1S=l=J!`>$S}lv-ZdaikGl7%?ZuC*ZMEI@DcTda$$GB<-1{ zIJRT^&p`grbnKL9`HyezpW1tV{yFwYecnmWhamC0eqFpj#grH*MR_|xzp0X#f3=8hZhx7Gp>Mq35Mvf|NHuchk1H}AcFko z&!?yV{wdmIeCDRW=Fp+}>`rl&`qDO6YEH&kL<|=TA-CEFy5pL8rkbMlRDOH-ZC0X* zHUh)m<%DG#G#{ziVj_CARSEZhc>ncy_wzf?6AQ2m$D-t)cpyvLX^6o&qsNg^PFg(w z`*`nD;pblXVv#+#=$q+AwBima(L6iPP?O0JL>Bwg%sW+P1H^+#G6jDtLjfSZigeF6 z8a(v!J}>?Z3F{fZ5{`|L?jB6Dqe^?I^2|pcZFha=Kl(iu#%s4kfjGoh`urSza`$GV zbK?BvvO7J&vp-UQ9=qghW0d1z+*RpaYZh9@%H%pWW=w@%jDKLFd_dda2tk zpvBUFPwvzfAs8J&YITD!6@kN!D2T8N^1Wi(0smFJ2;hT1C#|oS<&AS^TpflpiD}e- zp?_?CRbiZ2X;NUIf_c6E@>IFv6tet-e<}X55WdQ{f&PrpYoGDRbp|p{&+n7~Ur#t% z$i!lj+Z%J1&uz-8XN6*#??h>uGeZcXGoO93lvs(upA;~3mV+}P887Hb-*%%8!xYqQ zZ-0w%*QBnj-vjwr`z=fV_vQKTQkD{cFJ^CB=&cV`+njK{gzpknk(d__hotCp46DO^31;9sa$OWy|n&(lzR<>*QmQ zkB&$X{HdUFfUj|3%2VH$1;VeUjUTUGheHzaTVpx<{FZ)qaYDwIBc&g@@9C15GB|7B zJkUS>;^AeXs|b7VBSaWVaGNn>`IHFoX`EMP$!(>t=&CoZdWKH@i8Rl96Q0OwlacuF z^*KMCi=m61Jnl0^%k!&-{3M)47f7C7E!rYC>s|KW=puh=&Otsh7xp}`^Q#5;7-VxU zMr;4X<+QKxw6{Vk8_Hy$<-pRXFxyHm%sc8^|0pOSF!(myh24frGErZjR3RqOyTIw| zCthEnll|fi@cPT~bNrRk{NdfZx>K(SRKq6$=|`KGiHQ0^!J@yfM?FIpxF5sg=tE#J zz8?E4LCx2NZs`#IT+E)Ze4UzykBWN*@-e)jve6`V|vZ9ppD>-o}QoOrF|SHktlV+I&?cAzbML= z*6O`KM}mmQAzNs7!*YXv(&)K8umpcs`@7Vm>U)3pt$DNEgUFWo*m0+tqpzqXLCRJ7 zcJ-mP-Uo@Op5Gwf8;v~!uzh0y9}&uvYt~4036~)UoX~CWmRtTJ9Ao!T(E14e6UU2q zl5=OKSPAivMu)`+rzDx8;g7!Mn727mf?lZH?q&#D!2HVLeD^ z%4_)A^>I#wV8HjeKKnoWWK^@nipWdUjA2IsEoG>wni6bi^sEC)KLD@+wT-{Q|3aXN*5T3+41(sjo#;LU5j16D-Li0qi7tYUrbY6R4?t;h@dSJ?< zt!sS@)1nwbtC+w9_#DXPozH|mKOr1^MET{EsiJ=_Wmwe*xu4k1^X1v+L1^@wtjp~H z!C?cAcVd|hJn_Xe8=!B9ML4PbvTfZ@zXi@tpHX4J`bk|UbjL~J{{}U&taN( zDfa=kY_@xaEnngT=+XI0Ev;c>5|eg~jyYAi*eT9RgabRN%D!`Cf8;*&V%(-|xCi*0 z*sm-IwV~Lpy#)jrtf}gVuJGJThsQ3seVwkJeZ)Beu?VuqzJGf9DvMLwV zB3rt2ojuKdIP$@Re7g4c;6ESM|NSWTe_L%)Rk$%rx(CINU>veQ4#B~avkwyFvB~b3 zXnzt#BV#pEHjg?@sIp`f%ahT_MacE4b>cR1yw+WqoHF^`Z)glWD&yR34Z@)m`#sW- zk3xXz)Q%}9F1_))Je)cq2E}KeJbv*$F;;KH){z88m$0|%rG@ec(~>B8IhzH?rApKG zCKAX;&8vnDc73h_@(XgALxFYvRxaL$Y$}e&G4jJIAHj0>@Cva(EdDz3;)-xX^)7NQ zxSEagt}es&$KG9uDMEAySsz}PQ5vVkH)243Of5wylRLZPFX!h%Zh5M$$0LX%F+A^R zZGVReJp1^nKDjSzj%Yz2AcgPMiuHgVx+hJIC_76NAr|DMynk2KicJ%_z7cm?nw>+e9$TP<4+DV;9 zIi0#rS6!hW+?e}E>zt!y+Yo6kmi36tnmJk5G52eJr<_o&Y3CxL{EUxX$PeNU1Wx7E zbHTn&q4Xs*mVC-6J^ij*kI%hL^#w{C!Fw<4Ilq|S8FAsiBk~s_-RhBkx6v}x6M5Lx zOD3cHDs|^t*_A5bfP7rvy%)gtZ2^3C4enoUkhed=bLY$0*Z1C~FY6DIkW)69zQu#} zaf#%JTi+f=4{DTz$p6MVtM_U^D))7Faz!EGPA@5@T97IXAiuth-2j8kGk7)jc_R3| z1*sF3*AS+Y#FsWd&i}TGIlnNfFaI%CqiO83sI#t5YDUb-UDf6OUJNCM@ThX_TRASs z7eSZ}#_Qj|B`1}kTz?3wE2|?Zb&|#1pUsMruRy-T(kAei0@eZU zpK5wtP;?yS=|8b$JdSTIvN|!5NpdH4lS`Vs*l$VbzO{SEB;+y~UBFN4qb3W}H71k&DG zrcX6IZA+(SX9=Zn?KPuCjzO^KEDjUbH+gGx8Z)?V%d}bg`1kHy6cSz~6I{6(%XCG+ zt@?q&kr$RyU+GtvzwON`ru3;U&0qW;Ct6c=f9w71Ll&u6ui>nIiqIbIJg=B?BTa=? z;kMs9vaX;)TSaDs*Che@a9v-!f$cj6_#oR9YoChclHWw^o#Lv9s25pbR~ji~XD=w> z!Y{_^$}Xr3(dQp=6%z^-LOBWx^_swC>%1VNARDP;J~UsO0k(RDo;DA)3U<|g(LXKq z;EC#;w7;wBOAg6%phc$h>~r9@Yzell`l(v;>jebuY(gd<|bt!X7 zkdM&|0}5>4HNXcCJy1?CJE9;f(4%SO*~C%dWjS&~A+$UanPtbXFM3DR<9XCZ{{cb4 z-|0BUq8}QMd|%OFyO44Hj`*Nly8;eye^J)Mp1K#$vc1Bbykv|QY%EbIul2QO`Bu0P zpYZJCYgdTd^&P=lJtrT4kfujJ4WQ>F+|Kvw^$UAJuw0ETK@0M+``DL*?Yjf`*7fOU zO8Jl?gdQGt>PR9Ed>YdE&zI0yxd=_|*cpN)pm?fSCI&R@{maQ44brgI@0(1r5L&j% z%@6WLv?gc50KT&(<5|ea*l)3B(8oB!PiwppMCHOmV}p)dXCI$^-PvPy41b_=N89>x z2PO8xR=-Wq#zd#8PTCjiTo8!(s=NmIC^1VC!S+1@eB-$`nh}x4Q~Gn6^6F|S26UO1 zJVTq@7rH;>T_+In#NwvJTzEHAz4nO$uTk}&tY9mQqOe*;Hc=nmzicmoIRyAB8LV%u zXl90?4bm!Dvna`m8}HhnrUfn-4fWqW`vP@^DWZNR&|{qQoJCNpvgpIC2+}0rg$f7c zmnnoUiM?k4`6y&dz~4#){60u&60O{r0WWTBQ#A5=E#eNQB>TZ2;S!Be4E6V?s7r$1 zLR*FWaDzir<+P@FFBw=WsG+e98erO1^UcjLgWCQ8d=uN4nknDYwJW|zpCuTJTuL`a z;fm=N5=NP~5Z&>>d^P6Ve@FGxZk~?YZQC3g0+aXXZqLoV;uaW zJkbH)KatIQu}~Jck#!~elik?YI78Um_H^&Bag8eE!)?`<`I^}b@R?R<8LD3UJ6~?E z>|);OdpLCENLioxy}lgIso`M(`6>}Kz<<8~0zChk{RSK{ANqbX z(6@zRY4pfmSx);k3`me{qyXDoc#nhQV)HO^+(904baLcUF*(9o858{9Xd`v(K^mAONwZB&;1GDlLATDK|g@xvcWT ztfk?fDdI)iM$99R#jckz8tMXJdr1Y3-WB*!r@ll9}4)cgVp*H#MUtLtR!YL zdIp>zA2%)<_|wz)0H26Jm$hWD@M9D0=Z^22mEV!by5J|7^w?j85K;Hn_u)ntxRm{{ zH4e|KD2l62-M1r;KiE7+H`QBjU~ph<^+f~th~dLLM;EMk$4lB_)%=3c2o#CGCNKzO z^|EqFJ^QXC;*o8IkRZMjcXc&(RoHFlIpZ?s4a8q+$zf!>^u-19f_y}uB*9p9lC6&(0RlbQ`>d?AZ!|no)RxrB)yHi0Q!&Hfh^} zurn8d+Y(&JZ6|bKD*#!qiGMzEjBhm*6}NBZs2>y^C3C(k(59|Z>ioNv!Q6@3vA?f< zy`wL__Pb17b6ALyh*&EoO#J-K(=&=n0)& zYvhJxmOovD?0$r}oc1$7Ir7U|+ivqk9`e!sLOm5CjqK*3#d+AIwHWf65Uwe?2!kvj zzYD?%v^h&5D>$trY@|7hcQrbn_A6P^W`!S(f}isXspB=~;@i97J2oKC!FSO}*^YBKinmvF zOP7<|i*8cYn%#_sL)xhkIi!`@t}=gSY{+B+EW%M1=-z?NBIbLKE}AZ-TR4s0$9pl5 zkCA2!{8n460N-J~YweEZs&<93rVBf2`@~~8sU=YeYSy3pqCw5md8-UKG&#;!54<1m zRr;kf579`;$k6Fciu7xyimQZE8^r)VH>%A`N_ZN_4#o0@&f)UjHa6nuZu^7n_cst+$`vJ#k|=YK_*2v6EiWWrU>dW749LeO>xTk%es2LjYU=)< zLa|jD$oJ9I<}d zBp6Fn#+tLM1Ni!TcA*=-$EIsUuWkq1nAlv5oJ&?5J{tXmLHK+9Z5D^jmNr>Wqx~K} ze&iG;)7dXsm=KN@vwaKEDC)qae)z91=j90a;}=xK|M`7)Urd8OCV^hL%j+qFztJ+v z^8ky*{`aRkucCZ~nXHp_a!P9m0R>ok=I}~N{6gkONI5*jUxtMKQ=g5R8y^kd1AGP5 z-uX#Gg^WVb;&V)l=ph0po-b(FjP5UF$$O^r2( zBpJdB=dnXOe<%;i5C6Lz_~UCnKz`!|-b@-Pp)qhurHO-GB~MTozWMdDE!#7UBM=aPj+j zndNmLO*he7e59xGkM%4}1X~?cZh?UO-dM#GA>Avk^EnZBiwRN-dk1eFAGbVAoH@D2 zKKqasC%Dt1-VC1pKKiV>+)sX6GNEbvL4IdL11?d*Lg;soGRQ}io;d)vPZZ#rv*=Vs z2)mYqri>_3e!5aFsm7>|nrbzj@2@}I67NDPd?K=FD?j_9pUE+SP~NR%sT5)x5n7Zu`&_)c}w>Yr65aBAK1L33aA+asQRP1*QQNf;RpgGKbc zQ&we@VJ(jJUri{WC+4Qd>ZmpM48<6WFMUFb7cuNTO13xx1eQo_Zjg^mg{X+%&pf4kdf;bY#M7LWljMSWozePms|8(l`J5sEZ5V zfnA@OTk!!qiy)mzOf&eeoeYuKJj;%H_GR`(`|K7FaqU=ZCM};woeD()7`1Jhw9E3 z9O_@KSGU&-%pe`vzE40T`;b%c6H!$BV@|EEP0sIvX;F>aCL7+OmRf=~!_U$D-ENGo z+63-H8UUXZE*AajMpzG7@E^ky>fa-E43kH%x6f=gC^7!NAGIYE%9nb&uZnHJwtk2w zV9~^(^p(_5yB@EL!c8Jv(6BNC`CtbT>cRHu0(?t!*=t7iI*YR-d`QsUalyvBEF4}@ zoqwXAR$^g>rQj+&d|OWu+#awB`G@eYbo;)U5g6!SdtyM$a6?LGFyjM!Nqk24I)YOU z+qxKu-S}3o`HvM-Xhl3=pWbBM`IrKzW?2S<0I*!u2`*N6`T zSD8Mg79byu8%H?UK0Sc1h7k8kz7;`36&k~N1u0YwA7>|X-z2Sjfi_Oir(-7<6Lph} zaG*^1i<}h%%l8GA#d#qy7A%|9?fzGXt@Hl>k5)0*$dqvQF-eBM=nkH+5W}2}8e$zp z(A5=Zhkc)YZzPtbObo22HmPIrsB2S#mT!a0Cv_Zd>y!=3p?YH7Icz{aR@|amuzmUf zpL)2waigrpNp{A-go1~?^%vr?F{wE`j)q;|%tQiTbb~fG_ZnDgNlv%h*IGQJdx(LC zxIbw^1e_2nknY{hf%g}^)C_!HxAOq1_V5>XEQNuo=2r_jYkQ3k(~5t06r}vH#g^Ku zY>hiUDf`t=W5PI&>iJODXZJek)p(^}IN6yk$On}na|yQ30N^{8mgB%`VLrW)C8Umv z5zCl;>o*^YR*J;JzYyDZgH?iLybNmRCKQsDw}iX$#($f0B=Dug=e{#Q zebzP({&|>zcr(GZTgaF+{Gv|mIA?F`mG76?r{(AT1Zm!Q~uR3$|G*UXCzr8Dbu=lAPs? zIDveUZzmAJ_Pqi;|M-RzA}LjM^cB&)rBgb2q~U`YM!1p=VFk5g1v)<3!xLGOjS}}@ zdR@Er-+qeKDI{`yy7oOj5PXF591K^a&;16KpuG&6bRlTYLb2(vUtfIu zb!Kk;>`TFf^1Fm@;aC5WkK*_VCQtH5`X<>KuJ8+~riO`oKl^BxfAi~F0Kb)y9Uwoy z+N!Zb*TLzk(mx z5^XH57>gCcpef7&zC+6q-gfc!f^DfrqI^hG)eZTld!6gfw_fD*e|Ji;IW1X_R(&VK z?Av2Ln^_;S<2s?jV3mbJCsV!P@Qy!}@&NhhgfYNhUhW3)eR^q6>(Pj!@(Kxw8M&vL zY+qXTVAUVp;Us-!__Ik%WDOs`RMA8vB(*L5W0j~5=|@GRL~^Z3>x8=Ml5vMTe}FGs z9dfO4V-+sKjD}J^?pi6Y{M9!IwpYBaCDfwN`RPxEQH0}DD|a@p&IMPL*ahWAFI5?* zS@lbyZ{o#Xbgy`We3Trfzre0fKY))Tj@FE(3ZZn=g(#-blGPe!tI982@F(p$%y&9( znQk5v9kZ_CUB&m@-!+5xA$DYv$*EGG2=_P;cZ^fW`>(PAJ~ixPqh;LRiyYL-8lLmz z_{hC$+CCj8D`y>4)z7}q`fcv!-hD-s3YF4=PzHg&Xv^s`sye2l#38osFWxwo`+oNH)SfBlxVx89y+WGOU4xS0O*2zL zkTMt?HppEaosLy0W3Ls3hDrDZY{ht)-LU4Uaj3$-RuyC9C@EoO9*)IX~}apTy< zFXwT%h}j>&PHx_>HpTbMLU$ZZPa{A+$nz`) zuzL?GyKEU!ET5o07<#=qH}9#jRYn^>ysO*_t$4tUGfmel_Fey5Rmd>tKC)O3XjvAl%-V^DIO}bn7HLk zeYtl6@U=$uP(OU7bDPiSP$~^Tezk5L(=%gRLccei|2MziSN_UG8!M$>_iFSNlHza} zb|-az`o6xocZ$-dgtSZ0NdWmM(};4x_GJKk-Zr$;JlWRn62$J%TNxX6F{PKxNrcD9~58alvP5wY`&G>~6=iQge4N?O*@=_#9B_K8w< z;1x2l|0QadVg5ag_TIN?YALFpmR{sRO5L=IWH^uoL@3SyacwE zaFzG{nr?gfgB@IC!QqL58{((gb2Z*+tYqa(kdI16ECKBNY5@5qV5Xl)aKNx>ht~!a z2Nw_t*fcbmkw<5#zfAck4Vh}gGW92anbLa{Uk#ZZ zkRJv{j*ouWWK|WJ7lAE@ob#$(?5^=1Cr25Bnb)(AtfB_?r=mmaw}xe+JEz-MM}fHR z!%pQ&`R2v;SL5Qm?ztczhcEmr*uFY|PY=^-Oxhti7d3Wlo5ZlQlw9PM`r$WC`|YFr zrbgEXa`7jqQ|aTMeF%24Y|hGWZiob%T!hy*p$3a#&CqnirQY?{OO5&-(ieUK z`CxU_mcjNl0DS$EiOLGSL^@x36cK(~FI@_J6osQU8BF|1A|sH==YWqowczxXlC3L7 zDYmFVQ6dA;Y80_lbT22Es-iIGLIikJV%5tL)^-T`&+Y=6io2eXN`&t3Ml>QfD zft^0TW8}yp%`zQv8Ibz3ei0Y37 zrvm~kT?9Q8*Uuw9Tz_IN@>F~=Cad}l3*R*4@SbxSY4ZOV8I&L(CII;1|B zrHS{zmizp1CKFB5CU_cm~eb zvXb;+9s+ekRm)*#@pklgQHU6jpLqz;XtdWe<2#xw8oQ;HFR*lfI}Fsqx~=9WzIhqc z%B~Pu2I5iK5VC=lETn&NBLZP1e{8ck9wWvGuXZ* zfUn+vv?VDxAb}0fZ)Ut&7Ds%*!e=A~0xBrFyFT*^T-~o%&YMMhN&hVHWg$O_oT_%9 z>C;Tw`g4|RGe)}ff%gL7TTF+y{Qtc4fszH>xQE;17_7zwq7T~*EQSsdAjhJBpP zAm8f_Ht>gMdw}Iec4Q7o~o~>T-JP{jmr>pPN%%(2v_{*{3{+V`!A)XwTAAmcs zy`ZM}j>?`4T}@c{ z?a}NxKMa-Fs9|#WMe8rFKhzYMMnp;p#!C_|4q!c(Sj%2weFym*x@^E-9&!N4?`XTH_{^?HLPwK~)#=mL zMB>+2eyHzcmF%JrL#u)bslLb!)^mSY($_e@c~p=ju+KnxnTiR|e|U0=HhY;P1{{8N zI639Ad`jE-v5dOB8O`lY=VLl?cAUYLQX3ig>|<58G~3h4L@mOKEBX97!1$LwJX)jF zFbWBB>BKzy_Nreu$VVsU2LAB#4v^oSwV4_}(M4b<`Z{$3nz?(Jyxd4qgAMkKryUM{ zD3-Nixz%B3P4yI^Y^|PgyY-K1H}$CCBy1WSbEW}l=m6m91qHn<7#pfZM_rgsW;rcn znI&^QeUoj_6rP?fOV7T6NY3ALRr4>&37k?6p)9XY*5HO0MX)Q$rdqF<< zrkAK--(Ma8J_xs-m3<=HS^O`hRDP!jRy)1%KNLsU2Tpv0!uc^U3*Ox?Z+b|6vUjWP zOQNpC!_tnWyAMHwsXw>h_9f!7dk#`CPY#%q^^_HH51_^;(hZ9Oas@6mF7f!z( zl4^t>fG2jD#_-IKbVcb_T(Ps z2wEa7KEQr-CtcDuUVwb~dbI5Sz9yOtG6u`|v%q^qfKPgho01xyFZg|$sRAS0AD)gK zzNg@R^yK#^D>cu)SQX{VY$beeRU>?zEPXZADjkR+4K?$`DpZP`b_wbo{85k(Ms^4M z>04;n|2e*1RLp^I3j8c32phGJZlQJnW03%3FM5ZA^*eSO;!i;z3wH4M5#%?X?1%Vl zlZ(uZrNJWZjPLE=5Jc^m4fmkm0DK?plO*yYQvyp?$h?>AM*VB|NHBi z^zZgDWPq>5+RU$>>qdS^>A|VEoVSvH!L2-`6A4 z{~4ck5oJM}E-Xq+-H085i5yqTwgj_X;@$`0(cK1I7f>#4Kv3uJk+#~ z@$D`9Oot8KjzZif^`CbC;r-X?C{P2UtT7Iuzwe|k<~ zpLZ#bRo0iHx*-aEcd_qY)G~CTNdI?-u01aAb>XZIISK`;xJC_Zlc8H-Ap&I?%{x z32HQ8BB=7CH@P5x(D2yQ#eO;cudiVO{M8{C0N>yv^W70t+b8k;14E-HoJC$mdEECU zFtzfT-&_YexsB!mv89n&aPfkP^PSTwn4~}7q9t2yRW%&bu{n9aHIxGQFn-xExrRh+ z=d0Xwp(&2Ix~MC4wSRbTZ*SeN^6ZOZe9>`yCbGNq+UX$rRgzDJgdPqy=0m3ggJ|0v z4E9Xu0?0?uD_8NqFVBB3KP-T+3zqfFH0-Ie>Dy~H`Q4uy5m&ikef_=qoHfl;E3xET z2Z;A%!D531B%;c00(T0l)io@M3|~Iv2#P%1(RSL$0(^!Gy7f4^8^IEMM3=&FH-vPJ z5t5VYPEwVbh>XuZ1Jbh#|KTM<#`A>*`MPWbU*ZpUB$bVVjpJU6N1JSu8&*WQ^8%cb-aP z%z)|56s5?QnvDjfCu!2=8i0? z1pGV^+S;|8wEEx|)x*k0@JzrAKSU`rKYXkj9J zg)8bl=}r-$;q|wz3r-FG1o_}(`M__~OAGLw4=+toNOyjNb#qu8xx~exM(~8rx|9rH zn8W%p5$B%%gne3gr#6)*_IBw;GK{iJgqz7yI+1TTm|ciD(aZ&SI?7G({h)d&!6i2S z>lo6|?e49p4G2FM7{0(mRrlxoB>nZaKd<&lSKYlTft`X_EUaPu1RwB|F}<>ExpQ^R z0^t%dow=&X_Y7NA0a0PL~ zGJ1w=%d-zUe`+j%x&8#x&9|<0lT>FOc8gtMdGx6r@pHg}LBp>25yE*d`fuy_%J6srlv)30RV_REv zOO{uhMqKah*(oYd-ujnAMB~JTObNS_|CR^(27@af*28xna{sLV?yEDfkTX@+wLg;V zsQgI!_w>WpBW8vy%gFZ%=QIQZW=iV6U}`@@eO1aWaI6hcTE;`$I|2FNB}Bh~?c)IW z%zt1-^$5VUi3bkvj6PuI?D_j5k)ubpMBn!3^L)VN=q8fcXiRSxIVvUSCy?v z2;42hzBPY;e<$RB4f3&y`hdTD#s}~jV!kY$Ve=%p4sGn>T8=9JWipO6h-N@pJMcb| zXjO9#@-VdyEmH^nO|H7Kh3PC3AtR!!wty2)Y&VzmCt|4I0H5{8s@3_-NC|2;!lgLY zxepRk;j?^NeR7U9F;*e6;W0&fvYCM{UGN!}t|_jvV=kk;U(g)ejz5rjH;W zR%hE9*!c+oe11g|na7{-t&31`TFqQM-d_G;b&!i*yNtz71L-|>B^Y(lFGR#~`HzY`*r<7BlBQJje%&VGRC7Drx|q#O4KC0=?cxMh_GNtg^`} zh&Q=2VU4Ecqp1<5b*sg==C~~H!z_qGpm0@}W>Q)7EClr;8zyv%ju|suw~{Jz{_FeC z^r%|qBaZsrmi4fjZlj{l134cLO+9o;I;6MNF3t1!e9s!(xK8N5!4QG5M()C6cue2A zDMeKxY;`iT3?rpQoq`DRL2gojKRt5#-|5jl3vH2_+!vPRvp7`!7ZOBk?i{M^UUlr_ z8Z)sd8J7E3?fxoG-vj%2x;uZjXF3d!E3E`4F(N?}GNTTjnZp8C=ViY9s)rA(m!c5S zG8n$~VUNJ*v1|!=DOt75CiKk1W{zwTMc!w)@I^vCPlx887~r>7@Ozie)TbvbrrOxm z_X5PD)Wm}T`|&db#MdxhlHR#WpUjGb zoqIX{HV0GjW%|iO?3bS60z-i29VS)G`O@B41d3L|xL61uqC`;w3*>{Drw0G?(+J?} z=}0&dqTn}~oWtphIk37GWb-npSEvFu0!5fj@-+2*7=4RgPkwc>cS1=yl%U9X6ggp=p|9#ciL&V#9=FeKaU4@4~zANM) z)BOSXM2FdBm1-v~~&)0JgGN zf|2W4#lg9AlGlOAMpaNAvrLr1d|iOq_M%KD75C3!0`-so^8PbC#VggTPs80+kcFpm z1|cKt42K^a6%7k_U_|WVo_Uu648$1wFTRMl2*ZYNSJ=UN*MH&q{!R6XyJyAYnsfW< zC5Q(-UI%{ba%(_*1uK+~E-N2x)~T`I9SYcKV(Hd3S@C-Xs>bLe6k|7J$2+DAO0CF&;LEXe^)2m z0ltt5gA&nYX_cwb>ivEF=zix^KBLxX(gx$sSE0c?)()Q01xq?Mk4K705jg4cBy#*k zry(O%b{T!Y5{Zopx!(cuNtgl^(1CBX=~>=S(Uu^8zIX`1gL{z0&c8~BAFXF7Zn zH0VU!VR|rOAX3#`vqlT@@vy-zfb9zb__C4ly~q~#=5GQP1O+5zII>P)sr14-6I~Z= ztV0K5NV>nRZ4iU`BKNShCF0AhH_&lLmMhFzW2ktG;DTAojjheS0FBP15 z<4NG$;9Sg=DOPTCMVZz3?6bXd!Lbpk{4CJOd1;q$-L{@q#Kx#@to7MuAk@ZWF`AhH z81+jIVR3!P_o*Lhi@p^>Il4H36ejY~Zjf(@%CG+eBVrw)_;0 zx;~jm?-mFF+}n!8-keK>`G|`fcCp2?eL;euT#DF&L4SUa{PpkWi)P*1kjv32yYLo) zwb~HQp8z78nOVaTEE{Og75`YmD=5Ygk~(9?9fcN zBi_XWU#;IbbAf!g9PK?|`@R8u+@`a~9vByYXezuV;kX?Zx{^Z#`ruhUqIC41D)Q*M-! zayDoLAvQ{z2U|?JC7zIs@y8Z)&DQ_-Y9M3=t0=?IlL9RWO4utnXWm#I@a0vn8DFr? zXJ0@2dPYNX99|fw{_^IQ_5az_bL_=(>uQv_-D3$8QL*@=$&&}sQx1&aT z*=4NJ&hLcH37-Jt(-6mOHAbFmdOTaK|2ubZ+>Rqhn>|~8OfmZv!?RBhRh#ODa!LHj zwIo?CHS|+QL7*D4Jd^mIy=S4Y?dc0%UXV}IsSb?U-@m`_;(%-1$KQPt$LaU^ie%b1 zWf`K$qRuEk*|DZJV2J>wpH3H7#k-;7b*k~!x!{fN_nTc?-7zR>sL_%#E^7mN!Tm$U z*8tz@t(pf7!YQ&_3{DI-g$3jLZ>GQ1Id{je^jtfiea1hPvnBFT=I)u^$;z`BzZ7l1 ziOq2pXdN+thVv2W&Z!p!`Pgd4zk!`!E+9XmypBoXJzfZbEt1!1XBTHX@JDod)tAv! ze4%AkAMt(7Z!$OqL>96l4&j-VA?x;2}?j;!gtHO45_D?iI z`9(p#$gn5ydlz5=@?)e}s=>zf{uHezU*j1(i6H(~?197R!;WoF(~mlcOaA*oMWYmNR#pJ{X%Z!rS6X;vBc-U&Ym(l)%FIdg)m}sN zfARFPi`%-fXt&T4Z@)3+PGJ@?Z0r-M`WZtpTSHSkijNZQ* zSD8kmSlpwz_r~1|E}C7ZRrJO((!+);@@Mewh^tQV3_fQUL21p+jZstob}xDC#}1s{ z_Gk+sTx_8Qke_T;mOateo220*Hr<0im6-^spRC^s-P31m2k0E|yQS`!48uwk}8kSir+ zbJpY|=DIkwZcBE)vd3c2`59@JOWC}|F-~lz(A8gy?-?x)DYCO#_-A?P<~;8G7h^L8 zkPqjVtUB2F)d74wbMzKNsbya}p>==6(9w~V<(w21Y!ss`VwLa2NiB-hsq7ltp5mHhXsM#tMv`q`b_4fl33Z^&C%66S`Z}zkc`VDLP-hh1AKQT7I_B8-}0VUM} ziGAGKja34(zT@?wo^cJ`-PWJ_Kd6FyPy@=~S06e7zT6Ut1S*dGs!52??C7Vr>|L$y z(D&wT53X(eEzskqKX4o7CstdfqC|Y zq^rYhn)D5}Snioz^@(7mfBM``9DhW4_Em9~?h^CZ${!z>GBV&WZkSZ?+UpSUVH@kD zL$O=>`4DM>d^AY#|1|&n=P&$yYM=k+|KFeIC6|AH--iLdX7L@?jQ5>NZFsmCxUOR6 zuUh{^({0eOP;J|xI!N7n=Oqej?;0IM!KS9UacJ$pSEF6V+1dC8A@z$1WUvPn0rJ~U zw{Eo*L2~uRQ~LOxxQNK~cR%0C!jRob&9?RPzfhQ1If{=16P~2+D{&nUMO{zFVO}_S z*}~Bei6c(T+xM(GAm2M*W-!h^{OkJ+@xSX!6kfB0KhIL)6=2(sY>cs#(F$Nuhq6tK zONb@KR{zBGlqS%@9z*kv)*mmh>2F^L8<8p4or?Y9aE?vk)d;f(_P)ldoIiOp*y`wZ zxXsAX&f|(zo+ww}a_QagpIR zy#CksvVH{o_sa+%KZq@~s(c?0+7dSPyW|uT1uV9)JoDLq8hLbP>D?Zr-YC}CV~ahp zTu5q`8+kY~D@vJ2Y}GTlYU%1j3wAauK>+ew!nfNruiFh&yVT0)M~`n`g|~P*OzFa8 zX-WRuTPj`ttbR~$XC~uD5`BSLuUyw7|I@C_k*NtZ=Z$=P1Cp z7d+$L-R*ogou3p#d<2sSgDl3Xq^+`+xG6 zx!Tmue&~Il^LKyX=GKW=<0N|y9Dio{ZCwQy{hQc+7m0%hPRTY~tHC=?etS zSE=L0==?lvds#!YaXg!ldDHXf<5*0)D!N3e2T_dz3Aug5kOEx@#s|7eB3eSc$P!?F zeLHCq9Iaktoa?#?GFxnPe!VBiI^Aw0VGQoiK7Z;W8NY-XPR3PapY~ssXIymTd3=2# z#lIehBYF#_Q!7nCJ}9wFDzNig0QmHa=@;ygJkSnbN%U!ReBUPtRrUTnqv+YcK8L*HGEbMb~fO2_fD6$gZK3y_aQ zFbMp^4@&@FQDd;+`QnTPOvb?ecaxgv1FMg{l;h0t;>9Ld1|e&P?-nlK3zEN_Ihe?$ z+?}u| zxf68bI<4ljN5Ti0jrMl=n?Dv~>0h@79mAj5BuD8g>lf}bQW^@;RZbJf0`jv_^6H9A ztb;wTGYWBA=C{wl&KT8(HR~5-B2s(yr8Fto?G8Ud4eai(Fa0^4apx_heC^c2(5>)K zvsQefXkS;5kKm906WICf1ALgU%XBI?y6wE9{f$N|rS|-a8V^`$9ASxZT$7z8{G`Hv z42OINqW%1_AV+Zh%O+uX9UIz8TJ>_M{t)cgmeK#$_n-37)i4Uq1f4M{XBw&h>>pMh z^+O_uxi2(^46~WT&pzHF^P)AEI`;!Usdd-c-8B}_z70$6@{f_xP( zzJPJJ)4$~-l>hyCH^eEZ3E!p|ILLqevMQmV4E3b0^Jo9oH7J@P_G{%Mv4=s8-JMPc z-T?jt{GpY#cnc(S&O^cj|4mFphx+O@aPKvw_8KSC6QAXcpCnO1MZb^cr}cD)pSLED z*KflPt4#%0?Z$#C7(rKmojTbxPQoFPn+Me?6c$dhk(j3vVWGBYM(Ltb<7cH4q_q`D5r< zcH^z6?m@a*LJ%DJf8+a4c`VGDzrxMTjS`=Vg}zs*leYv0sp9AbIb3y-xb1U%l1tpy zUl^R!XT%^0a6(q+o*tAAl1;Q-B$neR(3R06aQs0&h_(1uuzeQ*U$9%I?&plQlvjki z%OdjU^7hcM4|-j+P@0Bhh>(abp;}Ttd#R?aA5i6wqK%Ml2De>}N?If<#eMQ<7{2_@ zzytUkbKlr!$oX`Z1-z3~rdX(dSgR{l{75(_6+J=s?1NTAC^ZPi=|$?MZ@gd=82w&N zSRcLb3qe&REw~mU82|7I2VQeo>Dnh=dEX-!|&hiGatsYwS)X z&4N(tXjC^ol|%R~NIUdxMwlGzOD*kv;+TA|T&YhF>gIzMXPTT5km*Y0N0gvr9afmWd%|Ft5S5j^Aa zgO*`w9PRQsKTCqt8&Pg%+&SM?k5YC`3js{C#!+7bLINEfq0GInqt2lqA200+HrPHI z!1CGe4))gg?%!9`HH3*~ZOyG!(V2J-olEHDx(e)DJ)+z)id~-ubZ$PX+23P{d`_>0 zKp$;t-|pkUPfaMpy&?o&4fIpXNH=GAI*}2bfC)0E96Lb|$FG1S>5Q(=toPX`v%5F( zV81=DjEC5XVxDGQwWj7}`Z9M8i}@9-H|~TrZ5YT$L@((KwhtAM-{%-6(g;J^{#^-v zGq(xl{+EkrNuOgEu(mQLBZK^X6jr)Yh4x0K4~rG;RB=|1J}=Fl@t=QXUV0_15Fw0v z0i51C#pBCyE~LYiT@Tr25!0NksfcaCh@oz5QK5=I`+iG|6nW*WFmx7VoqziA$i!F3 zx4tTqv{@2?N!l83oxL9k@{tpXGl1=T3Gm&RVSTjwAqk~$Hc2(eTTsaJ?VB@i1||g! z%huSM6VCLEte^B{?lf|skuCSI)B?^JS@kC^c&?V1OgyK7&E8AE`(=i;LMgr*HVH zzni6e%?F|K;3aAC^A@__F9c?GE790^d+nY9e22f-CV2-->itSmaB5V{KH{M;E~>Ym zd~(X+{=2*9?37cw$5%p%uIxJk^^$vXyF=R7$7_+DKNN19!-gRdYB3-mv}XwTgT$a{itKRn?PmrW%?M@H^IkQLUMJ8M}aE(wuiCUw$yUb>0I^oR+5U!epr)Ym1 z)nrM8MVRT|jtmPn0k*c$bb?_@FFeK9hndhUwVHqqFC9|Gkqe~{J0tqLeZqV8*2=+E<9Q^NE-s^;05eWF>g9-y4QWA8&2ZYp}SEvUAlEBTa3_kdyF(**J1dtX# zD^mJ%L=y9O|Fc&p4=&Ow@Y!d>1kEqAK@rK{NGbX~qppxO&e6bhLv{6L$3w+rhplxa z4djExvr+`x#{uwRd1#Ct2crk(rAz$?hdp95$5M3k;kUhZAh|P_awHAn$&PNpBir1a z$zkRD(NymkM?sPUliVDll^c12a~6^d$S*s%n3p1GNJLVCS1l^!qJtIoJ>#Lw%|@fw z_rKFWcGhE|(fLvMG^IxscNzt+-n%vTOF_SZUkMYEgs&#>O%2r~EsVoQdsMxZZCtbZRQ5*23lZ_it1q0Hoj zrd#)9yejU%aF`+vErCenFKKs0jLm$TOuyPJe)eh70$aPi%*GDXNy_>31A^{?v-Qb@ zVyfJP^y{g)zX}5Nvk$+xs$eS4H&Z^poy8Xymkm?uFy|1-BW&q|+)bvV1Cmt%$j8K$ zCJ(kx7U1hbJfI_F&W*Gd6k?5kGxj1}_jLK%Q)N$7^)Z@ti7!(jK1sld7JiBAO?S1u zeMaG_Tf}gKz3cvHq0H0q9Ns!0zp%nj=0|Gqtf7sT^ainv_M|9hy=d_oXRDLR{?9&3 z0c+TVP5~&UAGvp)?>Zfe<+h3Vd!tmx>>0>p#`6kMia|cIG2bk(eR2Tbmi5rO{?Ml! z$5Gd%(XDO9A} zmHo0T06u12x`Zgj#^9QHyTBD=WS(F2hp^=qnmbUpgMZ7Lc8?H?hCjNYOF}A zWQS;4h!I8JCcIwkF%$Xlxvm`K!}}%!{`N?DfKLhsnwD{1N;d%xx{$)gY#23G9cnFF_Y*q z1=MY!Dj`DGcjM|H+DyJ)do`!~cY7A9nE#8}o1CEo%9~45gP$UgIZjZjn^3}stqxkA z+1-9GYCt~X{E=0#^HT-*2C5YXu2mZ}KF8Q@UIqJ(dB?q?cu^Nqg_;J9`TMw8U)3d^ zTyMEaNzZj?hn4P|-YB)D2c-_KeeLhQO-*wYWRzI_*jY}{Xa*_ql= z(D~)5{O6o1|0Y39sbpO~z{mdNQ?T)8*!d-OI5cT`Z>LZ@tVU-GNA8*NHTkp87U$|M z3k|{Wg_=$uVJqqcPVzc-E+6`If$5Xhr%hh{qMsmNghDA8yOaMdA7uf)ukGKIU+}Om zPI3wVo~hB=z*G;7W?l4OUR>|Dz&_z67eDLZCO%e*M{}%AMlThgPLLnqh-7$YV zh~GofjVX@aSjnvL3(miMzhCkf$VZ@c^b+jxX#~hm;*P;aQi4h$x7gMQ}kYCGvQmg4XrWp}?aZc{z`D5vdeW;4PRS(Vq^mHmVgXVH@qm8QrI9mULR zdn34l%-TUd8mts7uzjWgA1Qy2S8>zI$vGkMhq&D;We%Q}YRzqTUDZ=R63F*LR;GsL zI!yJmqqGzG#8qD0v~2Cn^~wa}@v|dYEmR+Uf!pi!8!f}in#ztSoej*CU&2J31`x?C zrtw0oJlyR+`!@%NOB>N3Xqh$%t50R9whc;{F z=JIg1EZ)g8NHahZ^Ayzw^1Dm0KnCg>3?#;Eip8#>s~c;P*={RY3_qmOX5o0#d#5!CaT@ktX-P0L!nr#z-(h(_E`9p=ghx0E@=-32`Gf8A1^Bvy z>JuaDT7t8)?;L6H39)4@vnjP+7Ts1!et2SmWpSJw*us^G(6p3TvoCm&R{W)a1< z6r$Q*N;)@<83R~SmE z56P9J!FOLe~(gj%5xD#Cwh=YI7J8~V9Pt*vL@j`2BpT?`5;L3{YqG3|Z1dHMh>S8G&K z)_M5l5<&5f+tk0lAHlg``$7S}B00qIX}d#q`3a#T5BT0}m{(D@HVeCps8~)&^mbTP z3QzItwA3_wQEv=_T$&XU4$w~NtX0^Tp;@@+>rXwtK8V3Q)v_hcXb3;MihMX%Zbik!J&^Cr8CEzBt6Z%8`bu8VO{i37xwj)N z8X)kM_6t)(BGqM5qMfXSGRnv>ZhD|gFE{crgeU#@l4AY9-wihv}5SxEAf zF57{A8!Zjuj^q7w-cMF;;RTS7u67Lk?blxc+vgh|UN7mWC|;Mm(|QaiDUX|a0i&V3UP>1ejCpikizrEciQ!3|uwHV;|JgY=g6Ki{)#!Ac*vS=HIei>k} z%u>*fErNWE@5fZY&hI-QzhNbm&cS?onT_OvAWNeGXounHJ#3OGPNE9N6zaJ<;bo0c zcL|0N2!ux(s<3D`{S=981^yfroLuP!+V#NYI)G2?Y_dAghGx*}YqNMy$<7;fv+;9# zQAOhy;ZHoz<1?}zb7^HmxZwp)_;{h}7G%C({~mdW@028JqdjQ{cg*W<;7WRX>pYi?v$q{9{W^s(4#bO$S> zmiRuh!F}=Z1#`)E^Ib8(_bV~;UMsKAvX<;5L$)?@Zzu2AawUy&w z^`!T%xM&MAsj7ABp$SG^rWzRQ+?Y*=Xi2#oTOc1alrJ9Gz7l{hiCrrTb5(1WQ;@2n zqaS+5#ISuUcT2#a1%LW+z(##a?a>!Q@VAFkj%<|JLn9+!&=IO6V_F&E9{?MpnD^`wtw?ODbN1X$GzWaDk-naKE1A0|GhVi zR6dQonx4<^Zc$tYa|h&OQk4b2IZ-LVS4A}#;E$`e#3NA<9+D4760Y0{xa9tYyQ;ARFnm;K`f1{ zTl#=u`%-Fqf7oqPWJ$b?1o=-xgt$$FejAyBI>QtfUTYPOr3@4Se56ffqBX)bp{@oCeCyU%lKb?sMq@=% zsyC8WjmK^0!1?V7i6bw6 za$aW&31AF7QoqV1q)q(x%6P&WawkX+l@E=(>Y&qt<;%Ate&03o1N+;C!kinB4*>PNe(e3q=SJ6xufnO zyZip9HKBb9J}Yw5yKfnANQ-?Xzh%$TB>nDDS~azl$Nd1l34*RlFHsf0vld_d@WeA~ z#q`ujqpD^Z9vHlr&*M|2w(RW2_ zk%v3jz9xY0m2}st84>4Vi!~lq+Ap$hDmM?flg8H*?=Fi9LM||nin9l%XKxqWO_S2g z54WQpR)kZ*`Elq@HW(h$PlQX%w0*qrl@8O5Ey>C&c-<@rfJhV0L;vXFNE+QA0em1Kg}cm`40hS`}_dFM}!qyI2IZ&ucb9( zBuE_iGm%Z%F=pN}KeYiq=3??H$*+B?%299YQEk|PexK(+LD44z{ig1veTGE9Xdku= zaDJo~EF>IzaF;I$ySguBPGypSpl|*1KslzbectRjzg^@lH(Hus$x)Wt)GDjc2jBS= zrClUmzm6PN@0Sg&+dM%4`M5WO!0#-YvXFu>d^18IvHm4t zHR@rAcVl?WsZCW?iU{cyuemui5?j&hUm-tW0;(xfnwLqUojuL|J3jxjeUM{KPSg<= z**eRPQ!diH{_FI1$|Kj`OLGgcBjk;A)3GSqa?+9#h?@AnIMwdE9jFqf$7vR z1g67>KaoJbA-Q&h|9gJ_ZXYE6-|b5XD~gdO9^~*9+Sv_Bh4c601VxG?SE^spCFNlS z-;uERhT1h6?fMnnY+GMX{Ycqk40|m{wy6)5B`-ma&R2-`U*7aT|McgP#GEmhv)4+} zc5&XLNZurNsQv1mgY6GeI$4jv-`7h7StLQwm}0??KR)s$$j%e@{RBC%$(I3GpFb9%J&2bnsRE zCM@1wzfMXz;0mVpdKI4ITmEO=z3Ioi@N0jY$b1xuUdU<>l0FVZX6{A3?6ZPs8;^f| zS;^uM|99WN@xA=t_+-P=deHP7N#Bq6PX+w(r>l-$hpkt4#X9G#H#YrZx-6Zwm^{9V zQM|WE4+0d?ye%Y)iy%D1NybU*L zFDwH6nTIYr1TVI;X6Jd+zRsu>e7WDJ?C@1@IbwJ|7N(fqTQ3D26d!LsG5D(!Gl2Mp zeb?hGU6GjhtcD#HrEM!QkIi$g=(p7+_Ew!3B;;`&)jySv;k{U*I_0A#wbvw9j;(KO z(GE00DiaImh?WIbAL=k*zuJfDV5;GL@3`d_m*0r_Ivk48Xkg+DI^2jhu8QF=B(JCH z~}t_jv*YWxfZ2|0^NL^|RS8|32>!9)7L$M^5>Tmbk;ZHfD2P`{T_hnYh= zkg2I3=>C~zooY9Fk}7!hk+}?ZS6CRrov+HPkrTf8I|q+RAN&vP9~KO}A!>~`nS7GK z!vU1mJ(&!56!o$8N`@LI0vBDYI>wN=ZPVM!jXTfz(d@IaGx#?@tPpB>V?CaI#$}1c zP<7IZt3YEXpkX_f`HcH-etOkqVEa}8KF%Ig4xbXU9kiU^<^|K#-SG#Ql@{E#2NaH4 z8ZR_;ifax!&8(6bsqdG_?a_nL@5Mqjd+Q*Sx)Pg8d9a=BodM%>Tgx{dSNXjmbs^sc z9m==TkA7Jge$}ctbni=zpMCXFOO*F97%}I2%wk@|#ec9*Eh}9p`ed|B>YI|1&0lX4 zfqd8y!wO*gwgA4O8pRMv_(1FRd-yAMzCV>MwxQ?q*bs|aCDc9&#_Fgc-L>@L>@~@a z3dFvoQE_s6d-(1I3c97?VK}CHDaRrJU&&c=N0La*EUEWUYL|)-2A|_-_FgaUxQnz7 z!n4oxT8AZazQ5AA$+`4f^cHPFoL$-N7H!F;rhqF9{_#(xm;d_SFoNIQ<_O@c8*wc= z4j2|opdb?#T~$ZiGDXVDh}KI(yH)9N{k3RL?YZUKYu)YuNmQVQ9Tvk*Siic+cDX2u zn#a$?-+>C8y@#Vy3so$~5NRl7NSg19Wam_&cn1`32sJNt&p!KbH_sx9#OTXQ=f@YO z&6zx7uupaA(OkKUJno!=wCr~KmU?K}1kv~ab#v(p2{JDV!| z8-fbkVcRuiOZ#yt!axN@)4O?DL^~J8FhiLVO->(VJ~*SsE=mb>xy1f-eL#LvJllHX z#WkBwU1n+J8v9WWI$~-mEQB3ZPc*vEJ}wi1ujRuAZU}_Ib-fX?pR|1K`^}i;CfJnh zFlH^H=C}X#rA@v8a$GrP0*z{CKO~mSIYeC9r}1^fv`NygIqnIuKd|@N5%1nuXM-X`?AZ+z^@`PJ z&#|#HRm#j$?4h$V!m0R2L2g2bfG0`X0Y*%x5*B@TD3qbw{xq*F%|q71uw#ujW#^P4r5%uvL( zzc)KkyWP}l5vmb4S+Q=W#(WXc5RMyUmco`kDG?C1n96FgqzC!vw#4ee_Q3;uUYMVJ z4d%U3-vuWLP~GC=YSi^j1<(!F=#{@g?4kbdT)^$lqeK2hs~+J%aw8c*LGtetRFQVTxip+<>)QC@@$XK4HP@ZV>dLRrE-bfozn zV~|3hJ%lL*uxrGKt7VU-?G8>Apm@D1M18hj?4>@1>P)NRep81 zqmJ=O*%a;`iZXMdlD^prb_qk!-ymYfA&xaSiSDD_AJKV=3Xbk^7oR&{T$HTS%_C9d0{T`I$86p zVR(C@j4sy|#RQ{DH9%s#P@xb}}HVrzC|?Pcx&AAI~_c4V@_z>eQ#{!^jN z*Q5lumpL$dSDF(!3eUb*n0$t?+4ebaOGsniGMK?KaufdC*7V35c8d#(o6O48;RN}Z z_91n^&JPigAEO%88kvO1dS0aSM(CkQ9erghYK!y^@{#DONKZ~i4obum>-mf1mBSl$ z%#GE}MvAYH9~PNqdyuG}qVZ(4=K(%aoj7tAp`Hp!aY##(^z8Kg_fu%GB_cEJ-(~(b z4|&9oR)x)kx)>DO!N{Ucf`YNBhu(ck?@8e*-C1h8Rn+GJ`3QydLcsQ+0DMN-*2u*k zXvulZYc=Bat^1V^DxO!=$N>|knVFv>LR%4=P_3<(HAL64zH3h@@;CHn^f}ekI0RFV za5lwDARz;Mt!Je+93~vHP{lNCrn~}>G{a}1Ba{QhdDMH^&-slxY`*v@9l}mMDWjY} zLG`&a9h-%#(Cd84sKmh@g3oMM2;{>_h?oQ0M+xu+j)q;06nb{qu@9T)3oJftyF|QI z?psA&QJD+tCl_9?+p@e5(PH!Up3X*N5l~em+)1g4dVj%5fq7Z2sLt~l;DafZ*3a{2 z3O0w3@1EQjL7ATjl8|P89hH+U`M3E5(M_cidzV!Q6m{R)q|4?Jm>@A z=&FTrLZToa>s=Q3%{3SSKF6Om?{3rHE?z`3==0BYV!QURy4GU7z9u#gi?^1B)%HNm zc=;;HG4{Lo5?A{$qv}M~M*XZG!uonFpH1yL>j&`~2*r8kqj9#M2@%8>H zE?{JjCom-HXQ26ekhhrSzrO!WZ&9!a9X?85-F9yLP%BGCNlYwE#WPXg#am=?{ac-` z`k4cFk)D7LeKMcao>nrk`&IC2<=0#GiSI1k_a5TrWYQp?V#XjCr#t?g-U|Nj&wEgw zMUI=fhyW7x>Sw+Bm)X$07(WnOrIqdR8T-W#(U1uhl%^VNi1_Empy}~!`!|yo8p5x;vm`uJO z8*BW4>gny}%}Ntz(C-@N@Qs}zKXqb+lI@4C42Wm2Vgi0~a~SY>wt&Qs4$~K-kw0{- z3cIobZvYJVYWP=S^ul<0c4FnIO8-eCMSsdV+>sWVm?`Asp2_^ltc9X590A0IzYAlR=LLBQ~YtZR%Yu3rqlXz0yCHTILauj;UBKIyvNAr8Ah zw)QHGCs8ErklLB9$Rp8u*}}-^e!q~ItbcuqNowFff7O7`vvS^_y(>nCj-51ggFQ>d zY_@9GxqP=2ma{yc#y@^JXpm{Vq%hmDz#mDFqBqDARHV}+adLlC^;X-6UE}WQP6*%| zdz7_1e`mne+{PTE^WOTOyAQkPQlJ{K~o_$aHH#seH%d~TrcwU2z!y1BkvkqRC zL#PLMvu#Awyby)zp!_I$u)zQMlLzFdrz!Tz?yWaAX$wu{OxHaB;&8XPc>IzOArjH` zL$2IXFY-~2u%iowna9)OOR9xjMjxk=?)pMQI!yf)duhf@t&L8^chYi*`INtKvq;nSwdds5=!#)CBE$S zaC2;LNXFJ)EaPSy+n+@kXj7z+M&R@hvz4EkaV37-{dDdq{;F}ARJqJYe@-Lm6}P6r zbAIVB1#McrjnAN0@u`{bTV%=XmL#~oFV;{A?|1ikyPorDgM3hCi%eiYf4Tr4N?%8l zr$1L`%JJ<2I$As{-%>52t2H?@)HDU5s*8J+CGpo;Ov*6Rq)KJKUzuLp+aYO@Jq83m zG||xGFjv*U-V;g(!kD8iEQ1SuuVU2G+s9tF88Rn5wi?5q#{NCrFKhb!a<|PZdnWD? zLWEV7P*dx25Bok64dI(JVZB%$KaT;($IEUG{^kh-fG<{*cz6xo!Q3$eX)|s;K5W#J z2VU(D3~WDC+;rj^7nDIDt!_FLUv17~O>o!er&b5f(h>|q+LGC#5yjwCHA}$w6hPX# z?g*i^PSMR7)!v#ci@q-9nO-r-jYt0kbw~uKxLS~GK=HRuZ*oEw z`L<%siEZMo;lKGM%Yk3KH39fk*!7kkn}k_e6I|^+z}4GK8SBaY{AAU8F}wI~`Lnk6 z(EH8IS8}sC%v+BnbX_lt2v&ZZzl)&G#dIJPe*Qfihn-iYs}*RNzuo7XLm^J`(M!I*Yj&0YRo%~oa174dh=1x)e~X(u z1FGQn*02Eh=$2@gv(x-T7bhm$B;tw!^^2OU-nZYr7279!K-9n_bi6Aw*z;u5^n*u1 za!eNY^t<#yKD(Ka&QsrHBC*0laa|jb4@UOSG}u08fbVncWiAGh%hmx`RAaNl0}@pA z8Kgr^?gPCAoCg|YN7ok``%kN3A+9V5=Ot`^Ks)KKx-9^_-lX!HQv=MM0BiS9(1S(PZ(_)4S;Ls28p%0$Tdc*l@E4yw|pN;tiD z{PevfrHojSZspc0b8+3RCucZjlj{HB?5?A#>iT}+)7{fHPqZUNG-|RUr&e$r$96&z)VI)GZeO>^cHI(i-qpWWs6dkqZc?uPo_ex^S%+^~h z|4E{H+g$H*08IVN*H*A+~(Ey?pCGzM|FO`O7~-Mp{190NUr?P41|BAnR{# zpQ~e7ZItQ`-!xiYm;*OG+}l6J^D_q2>a4C)8AUA?$aF_g${xtRC}XdA-NJXis-ICH z!3sKqe6*{0;QM?5K6ulT03(?!SIwy}kzFY_TIf=jCla%Y4eN%h+KzY-di5{Q3L{iS zHSa>4&AK}|s)L7gmP}Zlr}xCu$)2KC%maK5QP`G|p9)wb*B5`feYf&)sAks6Jmm8d zmnJ%V%1_$v=ezg%AH=k-t0TUc0Qd z4Q83)2U>CBt-JGT?b})DWRU@>H$(YLzQ^7mA5DuE_|FgF03T$d@K1_qM&fhSXEQtH z17f0vL0^2SD+-Kp*3Uk5oGn((+y}<`^5Brr_G)HxTp(O?$3rU5TdQoPOf4UhyayH! z`Ukj&V9HF<*H|75eZDfr;XTZUrqlCb$*juy^ZXvuavvmw{xk8{;$nr^O}Il}CL#O* z9&_{T&NG_13w8_)nB{)hxhO4bC1^Rv&OD)D`XTb3s#Fg zp*a$dpd-fZ{pgP*=_ei(_EO~!cBo}orj!0dIMJ5#LxHN`M1I%f&#!NrF@{m3LP7E2 zkI@-|9bXn8KJ8T75RWJ>$tdefn84|lja#ekKyHHG2Gy~myQxC=uwUis>BNd%eb%zm z!LG}rF%a7f7>3r^hAdF+#?M~bWCMKo4}oQpCGK4xT$vz#6MmLR`lu#KR`cj$+&#lD5OcN?uSHr84)3Gy>`kr7^)*mGX zKdBn@*h@wMzQbyf6#7V-nCay!tHb@rj5_KdnL{)0aTo^3KWiHy6ArD#7qJ`O*Hp|a zyl{b__x7cEElmA83MW!HQ*SLXB?{!D)cOB0`uQ2)b0IRM(Rn|%g+5`o<`6VeAcb^= z9M7Y8RbE|?WvD=RrA*1GkOB=s_xix-)gnG270rvE7ES%<;}Vgb24CWXy8q+*xBC_M z(hUV2to`K-KRaJ7W*9}1qErnMF`QRF)wzj2ZsvsJ zBi0W5ruMnPbuEkq`F?5Ng7J9!xBE%`clR^5pUFkhM~v~f>^M}P>;9m03Tuq>v~ z#`byfrUcfOskNcQ&N$SfbE-%0AVylXxsMfPeCd3!0Y*nNVMpD6c>i|4UqKOYBn6G$ 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%0DSmwz94=|ShJ1HAEmk- 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 z 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

      NxdL;@9MjUvmQlUkBD$FiS$P-<;ugWX=ca^ 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�|S!N^2? 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

    txydfC4_@(SF-AM`Nh+pSCM9s>dr^cl5d~ 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